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