]> jfr.im git - irc/evilnet/x3.git/blob - src/x3ldap.c
1739e67effb0b9e882d593329802c1e463f116be
[irc/evilnet/x3.git] / src / x3ldap.c
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
41 extern struct nickserv_config nickserv_conf;
42
43
44 LDAP *ld = NULL;
45 int admin_bind = false;
46
47 int 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 */
69 unsigned 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 }
100 int 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
115 unsigned int ldap_check_auth( const char *account, const 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
129 int 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 */
170 int ldap_get_user_info(const char *account, char **email)
171 {
172 int rc;
173 struct berval **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_len(ld, entry, nickserv_conf.ldap_field_email);
180 if(!value) {
181 return(LDAP_OTHER);
182 }
183 if(email)
184 *email = strdup(value[0]->bv_val);
185 log_module(MAIN_LOG, LOG_DEBUG, "%s: %s\n", nickserv_conf.ldap_field_email, value[0]->bv_val);
186 ldap_value_free_len(value);
187 /*
188 value = ldap_get_values(ld, entry, "description");
189 log_module(MAIN_LOG, LOG_DEBUG, "Description: %s\n", value[0]);
190 value = ldap_get_values(ld, entry, "userPassword");
191 log_module(MAIN_LOG, LOG_DEBUG, "pass: %s\n", value ? value[0] : "error");
192 */
193 }
194 return(rc);
195 }
196
197 /*
198 ldap_result();
199 ldap_first_entry();
200 ldap_first_attribute();
201 for(;;) {
202 ldap_get_values();
203 ldap_next_attribute();
204 }
205
206 ldap_parse_result();
207
208 ldap_unbind_ext();
209 */
210 /* get errors with ldap_err2string(); */
211
212
213 /********* base64 stuff ***********/
214
215 unsigned char *pack(const char *str, unsigned int *len)
216 {
217 int nibbleshift = 4;
218 int first = 1;
219 char *v;
220 static unsigned char buf[MAXLEN+1];
221 int outputpos = -1;
222
223 memset(buf, 0, MAXLEN+1);
224 v = (char *)str;
225 while(*v) {
226 char n = *(v++);
227
228 if((n >= '0') && (n <= '9')) {
229 n -= '0';
230 } else if ((n >= 'A') && (n <= 'F')) {
231 n -= ('A' - 10);
232 } else if ((n >= 'a') && (n <= 'f')) {
233 n -= ('a' - 10);
234 } else {
235 printf("pack type H: illegal hex digit %c", n);
236 n = 0;
237 }
238
239 if (first--) {
240 buf[++outputpos] = 0;
241 } else {
242 first = 1;
243 }
244
245 buf[outputpos] |= (n << nibbleshift);
246 nibbleshift = (nibbleshift + 4) & 7;
247 }
248 *len = outputpos+1;
249 return(buf);
250 }
251
252
253 /* from php5 sources */
254 static char base64_table[] =
255 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
256 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
257 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
258 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
259 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
260 };
261 static char base64_pad = '=';
262
263 char *base64_encode(const unsigned char *str, int length, int *ret_length)
264 {
265 const unsigned char *current = str;
266 char *p;
267 char *result;
268
269 if ((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2))) {
270 if (ret_length != NULL) {
271 *ret_length = 0;
272 }
273 return NULL;
274 }
275
276 result = (char *)calloc((((length + 2) / 3) * 4)+1, sizeof(char));
277 p = result;
278
279 while (length > 2) { /* keep going until we have less than 24 bits */
280 *p++ = base64_table[current[0] >> 2];
281 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
282 *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
283 *p++ = base64_table[current[2] & 0x3f];
284
285 current += 3;
286 length -= 3; /* we just handle 3 octets of data */
287 }
288
289 /* now deal with the tail end of things */
290 if (length != 0) {
291 *p++ = base64_table[current[0] >> 2];
292 if (length > 1) {
293 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
294 *p++ = base64_table[(current[1] & 0x0f) << 2];
295 *p++ = base64_pad;
296 } else {
297 *p++ = base64_table[(current[0] & 0x03) << 4];
298 *p++ = base64_pad;
299 *p++ = base64_pad;
300 }
301 }
302 if (ret_length != NULL) {
303 *ret_length = (int)(p - result);
304 }
305 *p = '\0';
306 return result;
307 }
308
309
310 char **make_object_vals()
311 {
312 unsigned int y;
313 static char **object_vals = NULL;
314
315 if(object_vals)
316 free(object_vals);
317
318 object_vals = malloc(sizeof( *object_vals ) * (nickserv_conf.ldap_object_classes->used+1));
319
320 for(y = 0; y < nickserv_conf.ldap_object_classes->used; y++) {
321 object_vals[y] = nickserv_conf.ldap_object_classes->list[y];
322 }
323 object_vals[y] = NULL;
324 return object_vals;
325 /* NOTE: The return value of this is only good until the next call to it. */
326 }
327
328 char *make_password(const char *crypted)
329 {
330 char *base64pass;
331 unsigned char *packed;
332 unsigned int len;
333 char *passbuf;
334
335 packed = pack(crypted, &len);
336 base64pass = base64_encode(packed, len, NULL);
337 passbuf = malloc(strlen(base64pass) + 1 + 5);
338 strcpy(passbuf, "{MD5}");
339 strcat(passbuf, base64pass);
340 //log_module(MAIN_LOG, LOG_DEBUG, "Encoded password is: '%s'", passbuf);
341 free(base64pass);
342 return passbuf;
343
344 }
345
346 LDAPMod **make_mods_add(const char *account, const char *password, const char *email, int *num_mods_ret)
347 {
348 static char *account_vals[] = { NULL, NULL };
349 static char *password_vals[] = { NULL, NULL };
350 static char *email_vals[] = { NULL, NULL };
351 int num_mods = 2;
352 int i;
353 int mod = 0;
354 /* TODO: take this from nickserv_conf.ldap_add_objects */
355 LDAPMod **mods;
356 static char **object_vals;
357
358 account_vals[0] = NULL;
359 account_vals[1] = NULL;
360 password_vals[0] = NULL;
361 password_vals[1] = NULL;
362 email_vals[0] = NULL;
363 email_vals[1] = NULL;
364 object_vals = make_object_vals();
365
366 account_vals[0] = (char *) account;
367 if (password != NULL) {
368 password_vals[0] = (char *) password;
369 num_mods++;
370 }
371 email_vals[0] = (char *) email;
372
373 if(!(nickserv_conf.ldap_field_account && *nickserv_conf.ldap_field_account))
374 return 0; /* account required */
375 if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password))
376 return 0; /* password required */
377 if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email)
378 num_mods++;
379
380 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
381 for( i = 0; i < num_mods; i++) {
382 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
383 memset(mods[i], 0, sizeof(LDAPMod));
384 }
385
386 mods[mod]->mod_op = LDAP_MOD_ADD;
387 mods[mod]->mod_type = strdup("objectclass");
388 mods[mod]->mod_values = object_vals;
389 mod++;
390
391 mods[mod]->mod_op = LDAP_MOD_ADD;
392 mods[mod]->mod_type = strdup(nickserv_conf.ldap_field_account);
393 mods[mod]->mod_values = account_vals;
394 mod++;
395
396 if (password != NULL) {
397 mods[mod]->mod_op = LDAP_MOD_ADD;
398 mods[mod]->mod_type = strdup(nickserv_conf.ldap_field_password);
399 mods[mod]->mod_values = password_vals;
400 mod++;
401 }
402
403 if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email && *email) {
404 mods[mod]->mod_op = LDAP_MOD_ADD;
405 mods[mod]->mod_type = strdup(nickserv_conf.ldap_field_email);
406 mods[mod]->mod_values = email_vals;
407 mod++;
408 }
409 mods[mod] = NULL;
410 *num_mods_ret = num_mods;
411 return mods;
412 }
413
414 int ldap_do_add(const char *account, const char *crypted, const char *email)
415 {
416 char newdn[MAXLEN];
417 LDAPMod **mods;
418 int rc, i;
419 int num_mods;
420 char *passbuf;
421
422 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
423 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
424 return rc;
425 }
426
427 if (crypted != NULL)
428 passbuf = make_password(crypted);
429 snprintf(newdn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
430 mods = make_mods_add(account, (crypted != NULL ? passbuf : crypted), email, &num_mods);
431 if(!mods) {
432 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_add");
433 return LDAP_OTHER;
434 }
435 rc = ldap_add_ext_s(ld, newdn, mods, NULL, NULL);
436 if(rc != LDAP_SUCCESS && rc!= LDAP_ALREADY_EXISTS) {
437 log_module(MAIN_LOG, LOG_ERROR, "Error adding ldap account: %s -- %s", account, ldap_err2string(rc));
438 // return rc;
439 }
440 //ldap_unbind_s(ld);
441 for(i = 0; i < num_mods; i++) {
442 free(mods[i]->mod_type);
443 free(mods[i]);
444 }
445 free(mods);
446 if (crypted != NULL)
447 free(passbuf);
448 return rc;
449 }
450
451 int ldap_delete_account(char *account)
452 {
453 char dn[MAXLEN];
454 int rc;
455
456 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
457 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
458 return rc;
459 }
460
461 memset(dn, 0, MAXLEN);
462 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
463 return(ldap_delete_s(ld, dn));
464 }
465
466 int ldap_rename_account(char *oldaccount, char *newaccount)
467 {
468 char dn[MAXLEN], newdn[MAXLEN];
469 int rc;
470
471 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
472 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
473 return rc;
474 }
475
476 memset(dn, 0, MAXLEN);
477 memset(newdn, 0, MAXLEN);
478 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, oldaccount);
479 strcat(newdn, nickserv_conf.ldap_field_account);
480 strcat(newdn, "=");
481 strcat(newdn, newaccount);
482 rc = ldap_modrdn2_s(ld, dn, newdn, true);
483 if(rc != LDAP_SUCCESS) {
484 log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap account: %s -- %s", oldaccount, ldap_err2string(rc));
485 //return rc;
486 }
487 return rc;
488
489 }
490
491 LDAPMod **make_mods_modify(const char *password, const char *email, int *num_mods_ret)
492 {
493 static char *password_vals[] = { NULL, NULL };
494 static char *email_vals[] = { NULL, NULL };
495 int num_mods = 0;
496 int i;
497 /* TODO: take this from nickserv_conf.ldap_add_objects */
498 LDAPMod **mods;
499
500 password_vals[0] = (char *) password;
501 email_vals[0] = (char *) email;
502
503 if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password))
504 return 0; /* password required */
505 /*
506 if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email)
507 num_mods++;
508 */
509 if(password)
510 num_mods++;
511 if(email)
512 num_mods++;
513
514 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
515 for( i = 0; i < num_mods; i++) {
516 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
517 memset(mods[i], 0, sizeof(LDAPMod));
518 }
519
520 i = 0;
521 if(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password &&
522 password) {
523 mods[i]->mod_op = LDAP_MOD_REPLACE;
524 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_password);
525 mods[i]->mod_values = password_vals;
526 i++;
527 }
528
529 if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email) {
530 mods[i]->mod_op = LDAP_MOD_REPLACE;
531 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_email);
532 mods[i]->mod_values = email_vals;
533 i++;
534 }
535 mods[i] = NULL;
536 *num_mods_ret = num_mods;
537 return mods;
538 }
539
540 /* Save OpServ level to LDAP
541 *
542 * level - OpServ level
543 *
544 * A level of <0 will be treated as 0
545 */
546 int ldap_do_oslevel(const char *account, int level, int oldlevel)
547 {
548 LDAPMod **mods;
549 static char *oslevel_vals[] = { NULL, NULL };
550 char dn[MAXLEN], temp[MAXLEN];
551 int rc;
552
553 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
554 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
555 return rc;
556 }
557
558 if (level < 0) {
559 level = 0;
560 }
561
562 snprintf(temp, MAXLEN-1, "%d", (level ? level : oldlevel));
563 oslevel_vals[0] = (char *) temp;
564
565 if(!(nickserv_conf.ldap_field_oslevel && *nickserv_conf.ldap_field_oslevel))
566 return 0;
567
568 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
569
570 mods = ( LDAPMod ** ) malloc(( 1 ) * sizeof( LDAPMod * ));
571 mods[0] = (LDAPMod *) malloc(sizeof(LDAPMod));
572 memset(mods[0], 0, sizeof(LDAPMod));
573
574 mods[0]->mod_op = (level ? LDAP_MOD_REPLACE : LDAP_MOD_DELETE);
575 mods[0]->mod_type = strdup(nickserv_conf.ldap_field_oslevel);
576 mods[0]->mod_values = oslevel_vals;
577 mods[1] = NULL;
578
579 rc = ldap_modify_s(ld, dn, mods);
580 if(rc != LDAP_SUCCESS) {
581 log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap OpServ level: %s -- %s", account, ldap_err2string(rc));
582 //return rc;
583 }
584 free(mods[0]->mod_type);
585 free(mods[0]);
586 free(mods);
587
588 return rc;
589 }
590
591 /* Save email or password to server
592 *
593 * password - UNENCRYPTED password. This function encrypts if libs are available
594 * email - email address
595 *
596 * NULL to make no change
597 */
598 int ldap_do_modify(const char *account, const char *password, const char *email)
599 {
600 char dn[MAXLEN];
601 LDAPMod **mods;
602 int rc, i;
603 int num_mods;
604 char *passbuf = NULL;
605
606 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
607 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
608 return rc;
609 }
610
611 if(password) {
612 passbuf = make_password(password);
613 }
614
615 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
616 mods = make_mods_modify(passbuf, email, &num_mods);
617 if(!mods) {
618 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_do_modify");
619 return LDAP_OTHER;
620 }
621 rc = ldap_modify_s(ld, dn, mods);
622 if(rc != LDAP_SUCCESS) {
623 log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap account: %s -- %s", account, ldap_err2string(rc));
624 // return rc;
625 }
626 for(i = 0; i < num_mods; i++) {
627 free(mods[i]->mod_type);
628 free(mods[i]);
629 }
630 free(mods);
631 if(passbuf)
632 free(passbuf);
633 return rc;
634 }
635
636 LDAPMod **make_mods_group(const char *account, int operation, int *num_mods_ret)
637 {
638 static char *uid_vals[] = { NULL, NULL };
639 int num_mods = 1;
640 int i;
641 /* TODO: take this from nickserv_conf.ldap_add_objects */
642 LDAPMod **mods;
643
644 uid_vals[0] = (char *) account;
645
646 if(!(nickserv_conf.ldap_field_group_member && *nickserv_conf.ldap_field_group_member))
647 return 0; /* password required */
648
649 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
650 for( i = 0; i < num_mods; i++) {
651 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
652 memset(mods[i], 0, sizeof(LDAPMod));
653 }
654
655 i = 0;
656 mods[i]->mod_op = operation;
657 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_group_member);
658 mods[i]->mod_values = uid_vals;
659 i++;
660 mods[i] = NULL;
661 *num_mods_ret = num_mods;
662 return mods;
663 }
664
665
666 int ldap_add2group(char *account, const char *group)
667 {
668 LDAPMod **mods;
669 int num_mods;
670 int rc, i;
671
672 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
673 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
674 return rc;
675 }
676 mods = make_mods_group(account, LDAP_MOD_ADD, &num_mods);
677 if(!mods) {
678 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for add2group");
679 return LDAP_OTHER;
680 }
681 rc = ldap_modify_s(ld, group, mods);
682 if(rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS) {
683 log_module(MAIN_LOG, LOG_ERROR, "Error adding %s to group %s: %s", account, group, ldap_err2string(rc));
684 return rc;
685 }
686 for(i = 0; i < num_mods; i++) {
687 free(mods[i]->mod_type);
688 free(mods[i]);
689 }
690 free(mods);
691 return rc;
692 }
693
694 int ldap_delfromgroup(char *account, const char *group)
695 {
696 LDAPMod **mods;
697 int num_mods;
698 int rc, i;
699
700 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
701 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
702 return rc;
703 }
704 mods = make_mods_group(account, LDAP_MOD_DELETE, &num_mods);
705 if(!mods) {
706 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for delfromgroup");
707 return LDAP_OTHER;
708 }
709 rc = ldap_modify_s(ld, group, mods);
710 if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE) {
711 log_module(MAIN_LOG, LOG_ERROR, "Error removing %s from group %s: %s", account, group, ldap_err2string(rc));
712 return rc;
713 }
714 for(i = 0; i < num_mods; i++) {
715 free(mods[i]->mod_type);
716 free(mods[i]);
717 }
718 free(mods);
719 return rc;
720 }
721
722
723 void ldap_close()
724 {
725 admin_bind = false;
726 ldap_unbind_ext(ld, NULL, NULL);
727 }
728
729 #endif