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