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