]> jfr.im git - irc/evilnet/x3.git/blame - src/x3ldap.c
remove errors on remove non-existant, or add already exist in ldap
[irc/evilnet/x3.git] / src / x3ldap.c
CommitLineData
50895889 1/* x3ldap.c - LDAP functionality for x3, by Rubin
2 * Copyright 2002-2007 x3 Development Team
3 *
4 * This file is part of x3.
5 *
6 * x3 is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
e166c31b 19 *
e166c31b 20 *
21 * TODO:
22 * * get queries working in static existance, so i understand how it works
23 * * get ldap enabled in ./configure
24 * * x3.conf settings to enable/configure its use
25 * * generic functions to enable ldap
26 * * nickserv.c work to use said functions.
27 */
28
39edf54a 29#include "config.h"
db9a9a8a 30#ifdef WITH_LDAP
31
e166c31b 32#include <stdio.h>
33#include <stdlib.h>
34#include <ldap.h>
73d4cc91 35
e166c31b 36#include "conf.h"
e166c31b 37#include "global.h"
50895889 38#include "log.h"
e166c31b 39#include "x3ldap.h"
40
e166c31b 41extern struct nickserv_config nickserv_conf;
42
43
e166c31b 44LDAP *ld = NULL;
45
46int ldap_do_init()
47{
39edf54a 48 if(!nickserv_conf.ldap_enable)
49 return false;
e166c31b 50 /* TODO: check here for all required config options and exit() out if not present */
bec5dd26 51 //ld = ldap_init(nickserv_conf.ldap_host, nickserv_conf.ldap_port);
52
53 //if(ld == NULL) {
54 if(ldap_initialize(&ld, nickserv_conf.ldap_uri)) {
50895889 55 log_module(MAIN_LOG, LOG_ERROR, "LDAP initilization failed!\n");
e166c31b 56 exit(1);
57 }
58 ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &nickserv_conf.ldap_version);
bec5dd26 59 log_module(MAIN_LOG, LOG_INFO, "Success! ldap_init() was successfull in connecting to %s\n", nickserv_conf.ldap_uri);
e166c31b 60 return true;
61}
62
ea02341b 63
e166c31b 64/* Try to auth someone. If theres problems, try reconnecting
65 * once every 10 seconds for 1 minute.
66 * TODO: move this stuff to config file
67 */
ea02341b 68unsigned int ldap_do_bind( const char *dn, const char *pass)
e166c31b 69{
e166c31b 70 int q;
71
e166c31b 72 int n = 0;
73 while(1) {
ea02341b 74 q = ldap_simple_bind_s(ld, dn, pass);
e166c31b 75 if(q == LDAP_SUCCESS) {
4b8ccfeb 76 log_module(MAIN_LOG, LOG_DEBUG, "bind() successfull! You are bound as %s", dn);
ea02341b 77 /* unbind now */
a5a8a781 78 return q;
e166c31b 79 }
80 else if(q == LDAP_INVALID_CREDENTIALS) {
a5a8a781 81 return q;
e166c31b 82 }
83 else {
5aef35cf 84 log_module(MAIN_LOG, LOG_ERROR, "Bind failed: %s/****** (%s)", dn, ldap_err2string(q));
85 /* ldap_perror(ld, "ldap"); */
ea02341b 86 ldap_do_init();
e166c31b 87 }
39edf54a 88 if(n++ > 1) {
89 /* TODO: return to the user that this is a connection error and not a problem
90 * with their password
91 */
92 log_module(MAIN_LOG, LOG_ERROR, "Failing to reconnect to ldap server. Auth failing.");
a5a8a781 93 return q;
e166c31b 94 }
95 }
ea02341b 96 log_module(MAIN_LOG, LOG_ERROR, "ldap_do_bind falling off the end. this shouldnt happen");
a5a8a781 97 return q;
ea02341b 98}
24e9e6c3 99int ldap_do_admin_bind()
100{
101 if(!(nickserv_conf.ldap_admin_dn && *nickserv_conf.ldap_admin_dn &&
102 nickserv_conf.ldap_admin_pass && *nickserv_conf.ldap_admin_pass)) {
103 log_module(MAIN_LOG, LOG_ERROR, "Tried to admin bind, but no admin credentials configured in config file. ldap_admin_dn/ldap_admin_pass");
104 return LDAP_OTHER; /* not configured to do this */
105 }
106 return(ldap_do_bind(nickserv_conf.ldap_admin_dn, nickserv_conf.ldap_admin_pass));
107}
108
ea02341b 109
110unsigned int ldap_check_auth( char *account, char *pass)
111{
112 char buff[MAXLEN];
113
114 if(!nickserv_conf.ldap_enable)
a5a8a781 115 return LDAP_OTHER;
ea02341b 116
117 memset(buff, 0, MAXLEN);
118 snprintf(buff, sizeof(buff)-1, nickserv_conf.ldap_dn_fmt /*"uid=%s,ou=Users,dc=afternet,dc=org"*/, account);
119 return ldap_do_bind(buff, pass);
e166c31b 120
121}
122
24e9e6c3 123int ldap_search_user(char *account, LDAPMessage **entry)
e166c31b 124{
125
24e9e6c3 126 char filter[MAXLEN+1];
127 int rc;
128 LDAPMessage *res;
e166c31b 129
130 struct timeval timeout;
24e9e6c3 131
132 memset(filter, 0, MAXLEN+1);
133 snprintf(filter, MAXLEN, "%s=%s", nickserv_conf.ldap_field_account, account);
e166c31b 134 /*
135 Now we do a search;
136 */
137 timeout.tv_usec = 0;
ddcb3eb3 138 timeout.tv_sec = nickserv_conf.ldap_timeout;
24e9e6c3 139 if(LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
140 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
141 return rc;
142 }
143 if( (rc = ldap_search_st(ld, nickserv_conf.ldap_base, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &timeout, &res)) != LDAP_SUCCESS) {
144 log_module(MAIN_LOG, LOG_ERROR, "search failed: %s %s: %s", nickserv_conf.ldap_base, filter, ldap_err2string(rc));
145 return(rc);
e166c31b 146 }
24e9e6c3 147 log_module(MAIN_LOG, LOG_DEBUG, "Search successfull! %s %s\n", nickserv_conf.ldap_base, filter);
148 if(ldap_count_entries(ld, res) != 1) {
149 log_module(MAIN_LOG, LOG_ERROR, "LDAP search got %d entries when looking for %s", ldap_count_entries(ld, res), account);
150 return(LDAP_OTHER); /* Search was a success, but user not found.. */
e166c31b 151 }
24e9e6c3 152 log_module(MAIN_LOG, LOG_DEBUG, "LDAP search got %d entries", ldap_count_entries(ld, res));
153 *entry = ldap_first_entry(ld, res);
154 return(rc);
155}
156
157/* queries the ldap server for account..
158 * if a single account match is found,
159 * email is allocated and set to the email address
160 * and returns LDAP_SUCCESS. returns LDAP_OTHER if
161 * 0 or 2+ entries are matched, or the proper ldap error
162 * code for other errors.
163 */
164int ldap_get_user_info(char *account, char **email)
165{
166 int rc;
167 char **value;
168 LDAPMessage *entry, *res;
169 *email = NULL;
170 if( (rc = ldap_search_user(account, &res)) == LDAP_SUCCESS) {
171 entry = ldap_first_entry(ld, res);
172 value = ldap_get_values(ld, entry, nickserv_conf.ldap_field_email);
173 if(!value) {
174 return(LDAP_OTHER);
175 }
176 *email = strdup(value[0]);
177 log_module(MAIN_LOG, LOG_DEBUG, "%s: %s\n", nickserv_conf.ldap_field_email, value[0]);
178 /*
179 value = ldap_get_values(ld, entry, "description");
180 log_module(MAIN_LOG, LOG_DEBUG, "Description: %s\n", value[0]);
181 value = ldap_get_values(ld, entry, "userPassword");
182 log_module(MAIN_LOG, LOG_DEBUG, "pass: %s\n", value ? value[0] : "error");
183 */
184 }
185 return(rc);
186}
187
e166c31b 188 /*
189 ldap_result();
190 ldap_first_entry();
191 ldap_first_attribute();
192 for(;;) {
193 ldap_get_values();
194 ldap_next_attribute();
195 }
196
197 ldap_parse_result();
198
199 ldap_unbind_ext();
e166c31b 200 */
201 /* get errors with ldap_err2string(); */
e166c31b 202
e166c31b 203
4b8ccfeb 204/********* base64 stuff ***********/
205
8dc17ddf 206unsigned char *pack(const char *str, unsigned int *len)
4b8ccfeb 207{
208 int nibbleshift = 4;
209 int first = 1;
210 char *v;
211 static unsigned char buf[MAXLEN+1];
212 int outputpos = -1;
213
214 memset(buf, 0, MAXLEN+1);
8dc17ddf 215 v = (char *)str;
4b8ccfeb 216 while(*v) {
217 char n = *(v++);
218
219 if((n >= '0') && (n <= '9')) {
220 n -= '0';
221 } else if ((n >= 'A') && (n <= 'F')) {
222 n -= ('A' - 10);
223 } else if ((n >= 'a') && (n <= 'f')) {
224 n -= ('a' - 10);
225 } else {
226 printf("pack type H: illegal hex digit %c", n);
227 n = 0;
228 }
229
230 if (first--) {
231 buf[++outputpos] = 0;
232 } else {
233 first = 1;
234 }
235
236 buf[outputpos] |= (n << nibbleshift);
237 nibbleshift = (nibbleshift + 4) & 7;
238 }
239 *len = outputpos+1;
240 return(buf);
241}
242
243
244/* from php5 sources */
245static char base64_table[] =
246 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
247 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
248 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
249 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
250 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
251 };
252static char base64_pad = '=';
253
254char *base64_encode(const unsigned char *str, int length, int *ret_length)
255{
256 const unsigned char *current = str;
257 char *p;
258 char *result;
259
260 if ((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2))) {
261 if (ret_length != NULL) {
262 *ret_length = 0;
263 }
264 return NULL;
265 }
266
267 result = (char *)calloc(((length + 2) / 3) * 4, sizeof(char));
268 p = result;
269
270 while (length > 2) { /* keep going until we have less than 24 bits */
271 *p++ = base64_table[current[0] >> 2];
272 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
273 *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
274 *p++ = base64_table[current[2] & 0x3f];
275
276 current += 3;
277 length -= 3; /* we just handle 3 octets of data */
278 }
279
280 /* now deal with the tail end of things */
281 if (length != 0) {
282 *p++ = base64_table[current[0] >> 2];
283 if (length > 1) {
284 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
285 *p++ = base64_table[(current[1] & 0x0f) << 2];
286 *p++ = base64_pad;
287 } else {
288 *p++ = base64_table[(current[0] & 0x03) << 4];
289 *p++ = base64_pad;
290 *p++ = base64_pad;
291 }
292 }
293 if (ret_length != NULL) {
294 *ret_length = (int)(p - result);
295 }
296 *p = '\0';
297 return result;
298}
299
300
73d4cc91 301char **make_object_vals()
302{
303 unsigned int y;
304 static char **object_vals = NULL;
305
306 if(object_vals)
307 free(object_vals);
308
309 object_vals = malloc(sizeof( *object_vals ) * nickserv_conf.ldap_object_classes->used);
310
311 for(y = 0; y < nickserv_conf.ldap_object_classes->used; y++) {
312 object_vals[y] = nickserv_conf.ldap_object_classes->list[y];
313 }
314 object_vals[y] = NULL;
315 return object_vals;
316}
317
8dc17ddf 318char *make_password(const char *crypted)
4b8ccfeb 319{
320 char *base64pass;
4b8ccfeb 321 unsigned char *packed;
322 unsigned int len;
323 char *passbuf;
4b8ccfeb 324
325 packed = pack(crypted, &len);
326 base64pass = base64_encode(packed, len, NULL);
327 passbuf = malloc(strlen(base64pass) + 1 + 5);
328 strcpy(passbuf, "{MD5}");
329 strcat(passbuf, base64pass);
330 //log_module(MAIN_LOG, LOG_DEBUG, "Encoded password is: '%s'", passbuf);
331 free(base64pass);
332 return passbuf;
333
334}
335
73d4cc91 336LDAPMod **make_mods_add(const char *account, const char *password, const char *email, int *num_mods_ret)
ea02341b 337{
338 static char *account_vals[] = { NULL, NULL };
339 static char *password_vals[] = { NULL, NULL };
340 static char *email_vals[] = { NULL, NULL };
ea02341b 341 int num_mods = 3;
342 int i;
343 /* TODO: take this from nickserv_conf.ldap_add_objects */
ea02341b 344 LDAPMod **mods;
73d4cc91 345 static char **object_vals;
346 object_vals = make_object_vals();
ea02341b 347
348 account_vals[0] = (char *) account;
349 password_vals[0] = (char *) password;
350 email_vals[0] = (char *) email;
351
352 if(!(nickserv_conf.ldap_field_account && *nickserv_conf.ldap_field_account))
353 return 0; /* account required */
354 if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password))
355 return 0; /* password required */
356 if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email)
357 num_mods++;
358
359 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
360 for( i = 0; i < num_mods; i++) {
361 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
362 memset(mods[i], 0, sizeof(LDAPMod));
363 }
364
ea02341b 365 mods[0]->mod_op = LDAP_MOD_ADD;
366 mods[0]->mod_type = strdup("objectclass");
367 mods[0]->mod_values = object_vals;
368
369 mods[1]->mod_op = LDAP_MOD_ADD;
370 mods[1]->mod_type = strdup(nickserv_conf.ldap_field_account);
371 mods[1]->mod_values = account_vals;
372
373 mods[2]->mod_op = LDAP_MOD_ADD;
374 mods[2]->mod_type = strdup(nickserv_conf.ldap_field_password);
375 mods[2]->mod_values = password_vals;
376
377 if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email && *email) {
378 mods[3]->mod_op = LDAP_MOD_ADD;
379 mods[3]->mod_type = strdup(nickserv_conf.ldap_field_email);
380 mods[3]->mod_values = email_vals;
381 mods[4] = NULL;
382 }
383 else
384 mods[3] = NULL;
385 *num_mods_ret = num_mods;
386 return mods;
387}
388
8dc17ddf 389int ldap_do_add(const char *account, const char *crypted, const char *email)
ea02341b 390{
391 char newdn[MAXLEN];
392 LDAPMod **mods;
393 int rc, i;
394 int num_mods;
4b8ccfeb 395 char *passbuf;
ea02341b 396
a5a8a781 397 if(LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
ea02341b 398 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
a5a8a781 399 return rc;
ea02341b 400 }
401
8dc17ddf 402 passbuf = make_password(crypted);
ea02341b 403 snprintf(newdn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
8dc17ddf 404 mods = make_mods_add(account, passbuf, email, &num_mods);
ea02341b 405 if(!mods) {
406 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_add");
a5a8a781 407 return LDAP_OTHER;
ea02341b 408 }
409 rc = ldap_add_ext_s(ld, newdn, mods, NULL, NULL);
eb9bf540 410 if(rc != LDAP_SUCCESS && rc!= LDAP_ALREADY_EXISTS) {
ea02341b 411 log_module(MAIN_LOG, LOG_ERROR, "Error adding ldap account: %s -- %s", account, ldap_err2string(rc));
a5a8a781 412 return rc;
ea02341b 413 }
414 //ldap_unbind_s(ld);
415 for(i = 0; i < num_mods; i++) {
416 free(mods[i]->mod_type);
417 free(mods[i]);
418 }
419 free(mods);
4b8ccfeb 420 free(passbuf);
a5a8a781 421 return rc;
ea02341b 422}
423
73d4cc91 424int ldap_delete_account(char *account)
425{
426 char dn[MAXLEN];
a40080a2 427 int rc;
428
429 if(LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
430 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
431 return rc;
432 }
433
73d4cc91 434 memset(dn, 0, MAXLEN);
435 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
436 return(ldap_delete_s(ld, dn));
437}
438
439int ldap_rename_account(char *oldaccount, char *newaccount)
440{
441 char dn[MAXLEN], newdn[MAXLEN];
442 int rc;
443
444 if(LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
445 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
446 return rc;
447 }
448
449 memset(dn, 0, MAXLEN);
450 memset(newdn, 0, MAXLEN);
451 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, oldaccount);
452 strcat(newdn, nickserv_conf.ldap_field_account);
453 strcat(newdn, "=");
454 strcat(newdn, newaccount);
455 rc = ldap_modrdn2_s(ld, dn, newdn, true);
456 if(rc != LDAP_SUCCESS) {
457 log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap account: %s -- %s", oldaccount, ldap_err2string(rc));
458 return rc;
459 }
460 return rc;
461
462}
463
464LDAPMod **make_mods_modify(const char *password, const char *email, int *num_mods_ret)
465{
466 static char *password_vals[] = { NULL, NULL };
467 static char *email_vals[] = { NULL, NULL };
8a729617 468 int num_mods = 0;
73d4cc91 469 int i;
470 /* TODO: take this from nickserv_conf.ldap_add_objects */
471 LDAPMod **mods;
472
473 password_vals[0] = (char *) password;
474 email_vals[0] = (char *) email;
475
476 if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password))
477 return 0; /* password required */
8a729617 478 /*
73d4cc91 479 if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email)
480 num_mods++;
8a729617 481 */
482 if(password)
483 num_mods++;
484 if(email)
485 num_mods++;
73d4cc91 486
487 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
488 for( i = 0; i < num_mods; i++) {
489 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
490 memset(mods[i], 0, sizeof(LDAPMod));
491 }
492
493 i = 0;
494 if(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password &&
495 password) {
496 mods[i]->mod_op = LDAP_MOD_REPLACE;
497 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_password);
498 mods[i]->mod_values = password_vals;
499 i++;
500 }
501
502 if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email) {
503 mods[i]->mod_op = LDAP_MOD_REPLACE;
504 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_email);
505 mods[i]->mod_values = email_vals;
506 i++;
507 }
508 mods[i] = NULL;
509 *num_mods_ret = num_mods;
510 return mods;
511}
512
73d4cc91 513
514/* Save email or password to server
515 *
516 * password - UNENCRYPTED password. This function encrypts if libs are available
517 * email - email address
518 *
519 * NULL to make no change
520 */
521int ldap_do_modify(const char *account, const char *password, const char *email)
522{
523 char dn[MAXLEN];
524 LDAPMod **mods;
525 int rc, i;
526 int num_mods;
527 char *passbuf = NULL;
528
529 if(LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
530 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
531 return rc;
532 }
533
534 if(password) {
4b8ccfeb 535 passbuf = make_password(password);
73d4cc91 536 }
537
538 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
539 mods = make_mods_modify(passbuf, email, &num_mods);
540 if(!mods) {
541 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_add");
542 return LDAP_OTHER;
543 }
544 rc = ldap_modify_s(ld, dn, mods);
545 if(rc != LDAP_SUCCESS) {
546 log_module(MAIN_LOG, LOG_ERROR, "Error adding ldap account: %s -- %s", account, ldap_err2string(rc));
547 return rc;
548 }
549 for(i = 0; i < num_mods; i++) {
550 free(mods[i]->mod_type);
551 free(mods[i]);
552 }
553 free(mods);
554 if(passbuf)
555 free(passbuf);
556 return rc;
557}
558
8a729617 559LDAPMod **make_mods_group(const char *account, int operation, int *num_mods_ret)
560{
561 static char *uid_vals[] = { NULL, NULL };
562 int num_mods = 1;
563 int i;
564 /* TODO: take this from nickserv_conf.ldap_add_objects */
565 LDAPMod **mods;
566
567 uid_vals[0] = (char *) account;
568
569 if(!(nickserv_conf.ldap_field_group_member && *nickserv_conf.ldap_field_group_member))
570 return 0; /* password required */
571
572 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
573 for( i = 0; i < num_mods; i++) {
574 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
575 memset(mods[i], 0, sizeof(LDAPMod));
576 }
577
578 i = 0;
579 mods[i]->mod_op = operation;
580 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_group_member);
581 mods[i]->mod_values = uid_vals;
582 i++;
583 mods[i] = NULL;
584 *num_mods_ret = num_mods;
585 return mods;
586}
587
588
589int ldap_add2group(char *account, const char *group)
590{
591 LDAPMod **mods;
592 int num_mods;
593 int rc, i;
594
595 if(LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
596 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
597 return rc;
598 }
599 mods = make_mods_group(account, LDAP_MOD_ADD, &num_mods);
600 if(!mods) {
601 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for add2group");
602 return LDAP_OTHER;
603 }
604 rc = ldap_modify_s(ld, group, mods);
eb9bf540 605 if(rc != LDAP_SUCCESS && rc != LDAP_ALREADY_EXISTS) {
8a729617 606 log_module(MAIN_LOG, LOG_ERROR, "Error adding %s to group %s: %s", account, group, ldap_err2string(rc));
607 return rc;
608 }
609 for(i = 0; i < num_mods; i++) {
610 free(mods[i]->mod_type);
611 free(mods[i]);
612 }
613 free(mods);
614 return rc;
615}
616
617int ldap_delfromgroup(char *account, const char *group)
618{
619 LDAPMod **mods;
620 int num_mods;
621 int rc, i;
622
623 if(LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
624 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
625 return rc;
626 }
627 mods = make_mods_group(account, LDAP_MOD_DELETE, &num_mods);
628 if(!mods) {
629 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for delfromgroup");
630 return LDAP_OTHER;
631 }
632 rc = ldap_modify_s(ld, group, mods);
eb9bf540 633 if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE) {
8a729617 634 log_module(MAIN_LOG, LOG_ERROR, "Error removing %s from group %s: %s", account, group, ldap_err2string(rc));
635 return rc;
636 }
637 for(i = 0; i < num_mods; i++) {
638 free(mods[i]->mod_type);
639 free(mods[i]);
640 }
641 free(mods);
642 return rc;
643}
644
645
e166c31b 646void ldap_close()
647{
648 ldap_unbind(ld);
649}
650
651#endif