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