]> jfr.im git - irc/evilnet/x3.git/blame - src/x3ldap.c
fix a couple oversights in building ldap add structs
[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
e166c31b 36#include "conf.h"
e166c31b 37#include "global.h"
50895889 38#include "log.h"
e166c31b 39#include "x3ldap.h"
40
e166c31b 41extern struct nickserv_config nickserv_conf;
42
43
e166c31b 44LDAP *ld = NULL;
b96027ad 45int admin_bind = false;
e166c31b 46
47int ldap_do_init()
48{
39edf54a 49 if(!nickserv_conf.ldap_enable)
50 return false;
e166c31b 51 /* TODO: check here for all required config options and exit() out if not present */
bec5dd26 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)) {
50895889 56 log_module(MAIN_LOG, LOG_ERROR, "LDAP initilization failed!\n");
e166c31b 57 exit(1);
58 }
59 ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &nickserv_conf.ldap_version);
bec5dd26 60 log_module(MAIN_LOG, LOG_INFO, "Success! ldap_init() was successfull in connecting to %s\n", nickserv_conf.ldap_uri);
e166c31b 61 return true;
62}
63
ea02341b 64
e166c31b 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 */
ea02341b 69unsigned int ldap_do_bind( const char *dn, const char *pass)
e166c31b 70{
e166c31b 71 int q;
72
e166c31b 73 int n = 0;
74 while(1) {
ea02341b 75 q = ldap_simple_bind_s(ld, dn, pass);
e166c31b 76 if(q == LDAP_SUCCESS) {
4b8ccfeb 77 log_module(MAIN_LOG, LOG_DEBUG, "bind() successfull! You are bound as %s", dn);
ea02341b 78 /* unbind now */
a5a8a781 79 return q;
e166c31b 80 }
81 else if(q == LDAP_INVALID_CREDENTIALS) {
a5a8a781 82 return q;
e166c31b 83 }
84 else {
5aef35cf 85 log_module(MAIN_LOG, LOG_ERROR, "Bind failed: %s/****** (%s)", dn, ldap_err2string(q));
86 /* ldap_perror(ld, "ldap"); */
ea02341b 87 ldap_do_init();
e166c31b 88 }
39edf54a 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.");
a5a8a781 94 return q;
e166c31b 95 }
96 }
ea02341b 97 log_module(MAIN_LOG, LOG_ERROR, "ldap_do_bind falling off the end. this shouldnt happen");
a5a8a781 98 return q;
ea02341b 99}
24e9e6c3 100int ldap_do_admin_bind()
101{
b96027ad 102 int rc;
24e9e6c3 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 }
b96027ad 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;
24e9e6c3 112}
113
ea02341b 114
115unsigned int ldap_check_auth( char *account, char *pass)
116{
117 char buff[MAXLEN];
118
119 if(!nickserv_conf.ldap_enable)
a5a8a781 120 return LDAP_OTHER;
ea02341b 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);
b96027ad 124 admin_bind = false;
ea02341b 125 return ldap_do_bind(buff, pass);
e166c31b 126
127}
128
24e9e6c3 129int ldap_search_user(char *account, LDAPMessage **entry)
e166c31b 130{
131
24e9e6c3 132 char filter[MAXLEN+1];
133 int rc;
134 LDAPMessage *res;
e166c31b 135
136 struct timeval timeout;
24e9e6c3 137
138 memset(filter, 0, MAXLEN+1);
139 snprintf(filter, MAXLEN, "%s=%s", nickserv_conf.ldap_field_account, account);
e166c31b 140 /*
141 Now we do a search;
142 */
143 timeout.tv_usec = 0;
ddcb3eb3 144 timeout.tv_sec = nickserv_conf.ldap_timeout;
b96027ad 145 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
24e9e6c3 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);
e166c31b 152 }
24e9e6c3 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) {
b96027ad 155 log_module(MAIN_LOG, LOG_DEBUG, "LDAP search got %d entries when looking for %s", ldap_count_entries(ld, res), account);
24e9e6c3 156 return(LDAP_OTHER); /* Search was a success, but user not found.. */
e166c31b 157 }
24e9e6c3 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;
b96027ad 175 if(email)
176 *email = NULL;
24e9e6c3 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 }
b96027ad 183 if(email)
184 *email = strdup(value[0]);
24e9e6c3 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
e166c31b 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();
e166c31b 208 */
209 /* get errors with ldap_err2string(); */
e166c31b 210
e166c31b 211
4b8ccfeb 212/********* base64 stuff ***********/
213
8dc17ddf 214unsigned char *pack(const char *str, unsigned int *len)
4b8ccfeb 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);
8dc17ddf 223 v = (char *)str;
4b8ccfeb 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
41a3556d 275 result = (char *)calloc((((length + 2) / 3) * 4)+1, sizeof(char));
4b8ccfeb 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
73d4cc91 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
e688d9c7 317 object_vals = malloc(sizeof( *object_vals ) * nickserv_conf.ldap_object_classes->used+1);
73d4cc91 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;
e688d9c7 324 /* NOTE: The return value of this is only good until the next call to it. */
73d4cc91 325}
326
8dc17ddf 327char *make_password(const char *crypted)
4b8ccfeb 328{
329 char *base64pass;
4b8ccfeb 330 unsigned char *packed;
331 unsigned int len;
332 char *passbuf;
4b8ccfeb 333
334 packed = pack(crypted, &len);
335 base64pass = base64_encode(packed, len, NULL);
336 passbuf = malloc(strlen(base64pass) + 1 + 5);
337 strcpy(passbuf, "{MD5}");
338 strcat(passbuf, base64pass);
339 //log_module(MAIN_LOG, LOG_DEBUG, "Encoded password is: '%s'", passbuf);
340 free(base64pass);
341 return passbuf;
342
343}
344
73d4cc91 345LDAPMod **make_mods_add(const char *account, const char *password, const char *email, int *num_mods_ret)
ea02341b 346{
347 static char *account_vals[] = { NULL, NULL };
348 static char *password_vals[] = { NULL, NULL };
349 static char *email_vals[] = { NULL, NULL };
75fcdcad 350 int num_mods = 2;
ea02341b 351 int i;
75fcdcad 352 int mod = 0;
ea02341b 353 /* TODO: take this from nickserv_conf.ldap_add_objects */
ea02341b 354 LDAPMod **mods;
73d4cc91 355 static char **object_vals;
e688d9c7 356
357 account_vals[0] = NULL;
358 account_vals[1] = NULL;
359 password_vals[0] = NULL;
360 password_vals[1] = NULL;
361 email_vals[0] = NULL;
362 email_vals[1] = NULL;
73d4cc91 363 object_vals = make_object_vals();
ea02341b 364
365 account_vals[0] = (char *) account;
75fcdcad 366 if (password != NULL) {
367 password_vals[0] = (char *) password;
368 num_mods++;
369 }
ea02341b 370 email_vals[0] = (char *) email;
371
372 if(!(nickserv_conf.ldap_field_account && *nickserv_conf.ldap_field_account))
373 return 0; /* account required */
374 if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password))
375 return 0; /* password required */
376 if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email)
377 num_mods++;
378
379 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
380 for( i = 0; i < num_mods; i++) {
381 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
382 memset(mods[i], 0, sizeof(LDAPMod));
383 }
384
75fcdcad 385 mods[mod]->mod_op = LDAP_MOD_ADD;
386 mods[mod]->mod_type = strdup("objectclass");
387 mods[mod]->mod_values = object_vals;
388 mod++;
389
390 mods[mod]->mod_op = LDAP_MOD_ADD;
391 mods[mod]->mod_type = strdup(nickserv_conf.ldap_field_account);
392 mods[mod]->mod_values = account_vals;
393 mod++;
394
395 if (password != NULL) {
396 mods[mod]->mod_op = LDAP_MOD_ADD;
397 mods[mod]->mod_type = strdup(nickserv_conf.ldap_field_password);
398 mods[mod]->mod_values = password_vals;
399 mod++;
400 }
ea02341b 401
402 if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email && *email) {
75fcdcad 403 mods[mod]->mod_op = LDAP_MOD_ADD;
404 mods[mod]->mod_type = strdup(nickserv_conf.ldap_field_email);
405 mods[mod]->mod_values = email_vals;
406 mod++;
ea02341b 407 }
75fcdcad 408 mods[mod] = NULL;
ea02341b 409 *num_mods_ret = num_mods;
410 return mods;
411}
412
8dc17ddf 413int ldap_do_add(const char *account, const char *crypted, const char *email)
ea02341b 414{
415 char newdn[MAXLEN];
416 LDAPMod **mods;
417 int rc, i;
418 int num_mods;
4b8ccfeb 419 char *passbuf;
ea02341b 420
b96027ad 421 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
ea02341b 422 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
a5a8a781 423 return rc;
ea02341b 424 }
75fcdcad 425
426 if (crypted != NULL)
427 passbuf = make_password(crypted);
ea02341b 428 snprintf(newdn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
75fcdcad 429 mods = make_mods_add(account, (crypted != NULL ? passbuf : crypted), email, &num_mods);
ea02341b 430 if(!mods) {
431 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_add");
a5a8a781 432 return LDAP_OTHER;
ea02341b 433 }
434 rc = ldap_add_ext_s(ld, newdn, mods, NULL, NULL);
eb9bf540 435 if(rc != LDAP_SUCCESS && rc!= LDAP_ALREADY_EXISTS) {
ea02341b 436 log_module(MAIN_LOG, LOG_ERROR, "Error adding ldap account: %s -- %s", account, ldap_err2string(rc));
b96027ad 437 // return rc;
ea02341b 438 }
439 //ldap_unbind_s(ld);
440 for(i = 0; i < num_mods; i++) {
441 free(mods[i]->mod_type);
442 free(mods[i]);
443 }
444 free(mods);
75fcdcad 445 if (crypted != NULL)
446 free(passbuf);
a5a8a781 447 return rc;
ea02341b 448}
449
73d4cc91 450int ldap_delete_account(char *account)
451{
452 char dn[MAXLEN];
a40080a2 453 int rc;
454
b96027ad 455 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
a40080a2 456 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
457 return rc;
458 }
459
73d4cc91 460 memset(dn, 0, MAXLEN);
461 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
462 return(ldap_delete_s(ld, dn));
463}
464
465int ldap_rename_account(char *oldaccount, char *newaccount)
466{
467 char dn[MAXLEN], newdn[MAXLEN];
468 int rc;
469
b96027ad 470 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
73d4cc91 471 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
472 return rc;
473 }
474
475 memset(dn, 0, MAXLEN);
476 memset(newdn, 0, MAXLEN);
477 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, oldaccount);
478 strcat(newdn, nickserv_conf.ldap_field_account);
479 strcat(newdn, "=");
480 strcat(newdn, newaccount);
481 rc = ldap_modrdn2_s(ld, dn, newdn, true);
482 if(rc != LDAP_SUCCESS) {
483 log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap account: %s -- %s", oldaccount, ldap_err2string(rc));
b96027ad 484 //return rc;
73d4cc91 485 }
486 return rc;
487
488}
489
490LDAPMod **make_mods_modify(const char *password, const char *email, int *num_mods_ret)
491{
492 static char *password_vals[] = { NULL, NULL };
493 static char *email_vals[] = { NULL, NULL };
8a729617 494 int num_mods = 0;
73d4cc91 495 int i;
496 /* TODO: take this from nickserv_conf.ldap_add_objects */
497 LDAPMod **mods;
498
499 password_vals[0] = (char *) password;
500 email_vals[0] = (char *) email;
501
502 if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password))
503 return 0; /* password required */
8a729617 504 /*
73d4cc91 505 if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email)
506 num_mods++;
8a729617 507 */
508 if(password)
509 num_mods++;
510 if(email)
511 num_mods++;
73d4cc91 512
513 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
514 for( i = 0; i < num_mods; i++) {
515 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
516 memset(mods[i], 0, sizeof(LDAPMod));
517 }
518
519 i = 0;
520 if(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password &&
521 password) {
522 mods[i]->mod_op = LDAP_MOD_REPLACE;
523 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_password);
524 mods[i]->mod_values = password_vals;
525 i++;
526 }
527
528 if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email) {
529 mods[i]->mod_op = LDAP_MOD_REPLACE;
530 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_email);
531 mods[i]->mod_values = email_vals;
532 i++;
533 }
534 mods[i] = NULL;
535 *num_mods_ret = num_mods;
536 return mods;
537}
538
35ea100f 539/* Save OpServ level to LDAP
540 *
541 * level - OpServ level
542 *
543 * A level of <0 will be treated as 0
544 */
f3aff201 545int ldap_do_oslevel(const char *account, int level, int oldlevel)
35ea100f 546{
547 LDAPMod **mods;
548 static char *oslevel_vals[] = { NULL, NULL };
549 char dn[MAXLEN], temp[MAXLEN];
550 int rc;
551
552 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
553 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
554 return rc;
555 }
556
557 if (level < 0) {
558 level = 0;
559 }
560
f3aff201 561 snprintf(temp, MAXLEN-1, "%d", (level ? level : oldlevel));
35ea100f 562 oslevel_vals[0] = (char *) temp;
563
564 if(!(nickserv_conf.ldap_field_oslevel && *nickserv_conf.ldap_field_oslevel))
565 return 0;
566
567 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
568
569 mods = ( LDAPMod ** ) malloc(( 1 ) * sizeof( LDAPMod * ));
570 mods[0] = (LDAPMod *) malloc(sizeof(LDAPMod));
571 memset(mods[0], 0, sizeof(LDAPMod));
572
f3aff201 573 mods[0]->mod_op = (level ? LDAP_MOD_REPLACE : LDAP_MOD_DELETE);
35ea100f 574 mods[0]->mod_type = strdup(nickserv_conf.ldap_field_oslevel);
575 mods[0]->mod_values = oslevel_vals;
576 mods[1] = NULL;
577
578 rc = ldap_modify_s(ld, dn, mods);
579 if(rc != LDAP_SUCCESS) {
580 log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap OpServ level: %s -- %s", account, ldap_err2string(rc));
581 //return rc;
582 }
583 free(mods[0]->mod_type);
584 free(mods[0]);
585 free(mods);
586
587 return rc;
588}
73d4cc91 589
590/* Save email or password to server
591 *
592 * password - UNENCRYPTED password. This function encrypts if libs are available
593 * email - email address
594 *
595 * NULL to make no change
596 */
597int ldap_do_modify(const char *account, const char *password, const char *email)
598{
599 char dn[MAXLEN];
600 LDAPMod **mods;
601 int rc, i;
602 int num_mods;
603 char *passbuf = NULL;
604
b96027ad 605 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
73d4cc91 606 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
607 return rc;
608 }
609
610 if(password) {
4b8ccfeb 611 passbuf = make_password(password);
73d4cc91 612 }
613
614 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
615 mods = make_mods_modify(passbuf, email, &num_mods);
616 if(!mods) {
b96027ad 617 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_do_modify");
73d4cc91 618 return LDAP_OTHER;
619 }
620 rc = ldap_modify_s(ld, dn, mods);
621 if(rc != LDAP_SUCCESS) {
b96027ad 622 log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap account: %s -- %s", account, ldap_err2string(rc));
623 // return rc;
73d4cc91 624 }
625 for(i = 0; i < num_mods; i++) {
626 free(mods[i]->mod_type);
627 free(mods[i]);
628 }
629 free(mods);
630 if(passbuf)
631 free(passbuf);
632 return rc;
633}
634
8a729617 635LDAPMod **make_mods_group(const char *account, int operation, int *num_mods_ret)
636{
637 static char *uid_vals[] = { NULL, NULL };
638 int num_mods = 1;
639 int i;
640 /* TODO: take this from nickserv_conf.ldap_add_objects */
641 LDAPMod **mods;
642
643 uid_vals[0] = (char *) account;
644
645 if(!(nickserv_conf.ldap_field_group_member && *nickserv_conf.ldap_field_group_member))
646 return 0; /* password required */
647
648 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
649 for( i = 0; i < num_mods; i++) {
650 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
651 memset(mods[i], 0, sizeof(LDAPMod));
652 }
653
654 i = 0;
655 mods[i]->mod_op = operation;
656 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_group_member);
657 mods[i]->mod_values = uid_vals;
658 i++;
659 mods[i] = NULL;
660 *num_mods_ret = num_mods;
661 return mods;
662}
663
664
665int ldap_add2group(char *account, const char *group)
666{
667 LDAPMod **mods;
668 int num_mods;
669 int rc, i;
670
b96027ad 671 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
8a729617 672 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
673 return rc;
674 }
675 mods = make_mods_group(account, LDAP_MOD_ADD, &num_mods);
676 if(!mods) {
677 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for add2group");
678 return LDAP_OTHER;
679 }
680 rc = ldap_modify_s(ld, group, mods);
87677bd8 681 if(rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS) {
8a729617 682 log_module(MAIN_LOG, LOG_ERROR, "Error adding %s to group %s: %s", account, group, ldap_err2string(rc));
683 return rc;
684 }
685 for(i = 0; i < num_mods; i++) {
686 free(mods[i]->mod_type);
687 free(mods[i]);
688 }
689 free(mods);
690 return rc;
691}
692
693int ldap_delfromgroup(char *account, const char *group)
694{
695 LDAPMod **mods;
696 int num_mods;
697 int rc, i;
698
b96027ad 699 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
8a729617 700 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
701 return rc;
702 }
703 mods = make_mods_group(account, LDAP_MOD_DELETE, &num_mods);
704 if(!mods) {
705 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for delfromgroup");
706 return LDAP_OTHER;
707 }
708 rc = ldap_modify_s(ld, group, mods);
eb9bf540 709 if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE) {
8a729617 710 log_module(MAIN_LOG, LOG_ERROR, "Error removing %s from group %s: %s", account, group, ldap_err2string(rc));
711 return rc;
712 }
713 for(i = 0; i < num_mods; i++) {
714 free(mods[i]->mod_type);
715 free(mods[i]);
716 }
717 free(mods);
718 return rc;
719}
720
721
e166c31b 722void ldap_close()
723{
b96027ad 724 admin_bind = false;
e166c31b 725 ldap_unbind(ld);
726}
727
728#endif