1 /*
2 * jabberd - Jabber Open Source Server
3 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4 * Ryan Eatmon, Robert Norris
5 *
6 * This program 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 2 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19 */
20
21 /*
22 * Written by Nikita Smirnov in 2004
23 * on basis of authreg_ldap.c
24 */
25
26 /*
27 * !!! this doesn't do any caching. It really should.
28 *
29 * !!! this blocks for every auth.
30 */
31
32 #include <stdio.h>
33
34 #define _XOPEN_SOURCE 500 // need this to get crypt()
35 #include "c2s.h"
36
37 #ifdef STORAGE_LDAP
38 #ifdef HAVE_CRYPT
39 #include <unistd.h>
40 #endif
41
42 #ifdef HAVE_SSL
43 #include <openssl/rand.h>
44 #include <openssl/evp.h>
45 #endif
46
47 #include <lber.h>
48 #define LDAP_DEPRECATED 1
49 #include <ldap.h>
50
51 #define LDAPFULL_PASSBUF_MAX 257
52 #define LDAPFULL_DN_MAX 4096
53
54 #define LDAPFULL_SRVTYPE_LDAP 1
55 #define LDAPFULL_SRVTYPE_AD 2
56
57 #define LDAPFULL_SEARCH_MAX_RETRIES 1
58
59 /** internal structure, holds our data */
60 typedef struct moddata_st
61 {
62 authreg_t ar;
63
64 LDAP *ld;
65
66 const char *uri;
67
68 const char *binddn;
69 const char *bindpw;
70
71 const char *objectclass;
72 const char *uidattr;
73 const char *validattr;
74 const char *group_dn;
75 const char *pwattr;
76 const char *pwscheme;
77
78 int fulluid; // use "uid@realm" in ldap searches (1) or just use "uid" (0)
79 int binded; // if we are binded with binddn and bindpw, then 1, otherwise 0
80
81 int srvtype;
82
83 xht basedn;
84 const char *default_basedn;
85 } *moddata_t;
86
87 //////////////////////////////////////////////////////////////////////////////
88 //
89 // Here is stuff for hashing passwords
90 // ideas and some part of code are taken from cyrus-sasl/saslauthd
91 //
92 //////////////////////////////////////////////////////////////////////////////
93
94 #ifdef HAVE_SSL
95 #include <openssl/evp.h>
96 #include <openssl/des.h>
97 #endif
98
99 typedef struct _ldapfull_pw_scheme {
100 char *name;
101 char *scheme;
102 char *prefix;
103 int saltlen;
104 int (*check) (moddata_t data, const char *scheme, int salted, const char *hash, const char *passwd);
105 int (*set) (moddata_t data, const char *scheme, const char *prefix, int saltlen, const char *passwd, char *buf, int buflen);
106 } ldapfull_pw_scheme;
107
108 int _ldapfull_hash_init(); // call it before use of other stuff
109 #ifdef HAVE_SSL
110 static int _ldapfull_chk_hashed(moddata_t data, const char *scheme, int salted, const char *hash, const char *passwd);
111 static int _ldapfull_set_hashed(moddata_t data, const char *scheme, const char *prefix, int saltlen, const char *passwd, char *buf, int buflen);
112 #endif
113 #ifdef HAVE_CRYPT
114 static int _ldapfull_chk_crypt(moddata_t data, const char *scheme, int salted, const char *hash, const char *passwd);
115 static int _ldapfull_set_crypt(moddata_t data, const char *scheme, const char *prefix, int saltlen, const char *passwd, char *buf, int buflen);
116 #endif
117 static int _ldapfull_chk_clear(moddata_t data, const char *scheme, int salted, const char *hash, const char *passwd);
118 static int _ldapfull_set_clear(moddata_t data, const char* scheme, const char* prefix, int saltlen, const char* passwd, char* buf, int buflen);
119
120 static int _ldapfull_check_passhash(moddata_t data, const char *hash, const char *passwd);
121 static int _ldapfull_set_passhash(moddata_t data, const char* scheme_name, const char* passwd, char* buf, int buflen);
122 static int _ldapfull_check_password_bind(authreg_t ar, const char *username, const char *realm, char password[LDAPFULL_PASSBUF_MAX]);
123
124 ldapfull_pw_scheme _ldapfull_pw_schemas[] = {
125 #ifdef HAVE_SSL
126 { "sha", "sha1", "{SHA}", 0, _ldapfull_chk_hashed, _ldapfull_set_hashed },
127 { "ssha", "sha1", "{SSHA}", 4, _ldapfull_chk_hashed, _ldapfull_set_hashed },
128 #endif
129 #ifdef HAVE_CRYPT
130 { "crypt", "crypt", "", 2, _ldapfull_chk_crypt, _ldapfull_set_crypt },
131 #endif
132 { "clear", "", "", 0, _ldapfull_chk_clear, _ldapfull_set_clear },
133 { "bind", "", "", 0, NULL, NULL },
134 { NULL, NULL, NULL, 0, NULL, NULL }
135 };
136
137
138 // general check_password
139 // returns 1 if password is checked, 0 otherwise
_ldapfull_check_passhash(moddata_t data,const char * hash,const char * passwd)140 int _ldapfull_check_passhash(moddata_t data, const char *hash, const char *passwd) {
141 int n;
142 int plen;
143 int hlen;
144
145 if( ! hash ) {
146 log_write(data->ar->c2s->log,LOG_ERR,"_ldapfull_check_passhash: hash is NULL");
147 return 0;
148 }
149 if( ! passwd ) {
150 log_write(data->ar->c2s->log,LOG_ERR,"_ldapfull_check_passhash: passwd is NULL");
151 return 0;
152 }
153
154 hlen = strlen(hash);
155
156 for( n=0 ; _ldapfull_pw_schemas[n].name != NULL ; n++ ) {
157 plen = strlen(_ldapfull_pw_schemas[n].prefix);
158 if( (plen <= hlen) && !strncmp(hash,_ldapfull_pw_schemas[n].prefix,plen) ) {
159 // if scheme found is cleartext and hash begins with '{', than maybe it is
160 // unknown scheme, so don't pass it
161 if( ! strlen(_ldapfull_pw_schemas[n].scheme) && hlen ) {
162 if( hash[0] == '{' ) {
163 continue;
164 }
165 }
166 if( _ldapfull_pw_schemas[n].check ) {
167 return _ldapfull_pw_schemas[n].check(
168 data,
169 _ldapfull_pw_schemas[n].scheme,
170 _ldapfull_pw_schemas[n].saltlen,
171 hash + plen,passwd);
172 } else {
173 log_write(data->ar->c2s->log,LOG_ERR,"_ldapfull_check_passhash: no check function for schema %s",
174 _ldapfull_pw_schemas[n].name);
175 return 0;
176 }
177 }
178 }
179 return 0;
180 }
181
182 // general set_password
183 // returns 1 if password in buf is set, 0 otherwise
184 // must provide with buffer of sufficient length, or it will fail
_ldapfull_set_passhash(moddata_t data,const char * scheme_name,const char * passwd,char * buf,int buflen)185 int _ldapfull_set_passhash(moddata_t data, const char *scheme_name, const char *passwd, char *buf, int buflen) {
186 int n;
187
188 if( ! passwd ) {
189 log_write(data->ar->c2s->log,LOG_ERR,"_ldapfull_set_passhash: passwd is NULL");
190 return 0;
191 }
192 if( ! buf ) {
193 log_write(data->ar->c2s->log,LOG_ERR,"_ldapfull_set_passhash: buf is NULL");
194 return 0;
195 }
196
197 for( n=0 ; _ldapfull_pw_schemas[n].name != NULL ; n++ ) {
198 if( !strcmp(scheme_name,_ldapfull_pw_schemas[n].name) ) {
199 if( _ldapfull_pw_schemas[n].set ) {
200 return _ldapfull_pw_schemas[n].set(
201 data,
202 _ldapfull_pw_schemas[n].scheme,
203 _ldapfull_pw_schemas[n].prefix,
204 _ldapfull_pw_schemas[n].saltlen,
205 passwd, buf, buflen);
206 } else {
207 log_write(data->ar->c2s->log,LOG_ERR,"_ldapfull_set_passhash: no set function for schema %s",
208 _ldapfull_pw_schemas[n].name);
209 return 0;
210 }
211 }
212 }
213 return 0;
214 }
215
_ldapfull_chk_clear(moddata_t data,const char * scheme,int salted,const char * hash,const char * passwd)216 int _ldapfull_chk_clear(moddata_t data, const char *scheme, int salted, const char *hash, const char *passwd) {
217 return !strcmp(hash,passwd);
218 }
219
_ldapfull_set_clear(moddata_t data,const char * scheme,const char * prefix,int saltlen,const char * passwd,char * buf,int buflen)220 int _ldapfull_set_clear(moddata_t data, const char *scheme, const char *prefix, int saltlen, const char *passwd, char *buf, int buflen) {
221 if( buflen <= strlen(passwd) ) {
222 log_write(data->ar->c2s->log,LOG_ERR,"_ldapfull_set_clear: buffer is too short (%i bytes)",buflen);
223 return 0;
224 }
225 strcpy(buf, passwd);
226 return 1;
227 }
228
229 #ifdef HAVE_SSL
_ldapfull_base64_decode(const char * src,const unsigned char ** ret,int * rlen)230 int _ldapfull_base64_decode( const char *src, const unsigned char **ret, int *rlen ) {
231 int rc, tlen = 0;
232 int i;
233 unsigned char *text;
234 #if OPENSSL_VERSION_NUMBER < 0x10100005L
235 EVP_ENCODE_CTX EVP_ctx;
236 #else
237 EVP_ENCODE_CTX *EVP_ctx;
238 #endif
239
240 text = (unsigned char *)malloc(((strlen(src)+3)/4 * 3) + 1);
241 if (text == NULL) {
242 return 0;
243 }
244
245 #if OPENSSL_VERSION_NUMBER < 0x10100005L
246 EVP_DecodeInit(&EVP_ctx);
247 rc = EVP_DecodeUpdate(&EVP_ctx, text, &i, (const unsigned char *)src, strlen(src));
248 if (rc < 0) {
249 free(text);
250 return 0;
251 }
252 tlen+=i;
253 EVP_DecodeFinal(&EVP_ctx, (unsigned char*)text, &i);
254 #else
255 EVP_ctx = EVP_ENCODE_CTX_new();
256 EVP_DecodeInit(EVP_ctx);
257 rc = EVP_DecodeUpdate(EVP_ctx, text, &i, (const unsigned char *)src, strlen(src));
258 if (rc < 0) {
259 free(text);
260 EVP_ENCODE_CTX_free(EVP_ctx);
261 return 0;
262 }
263 tlen+=i;
264 EVP_DecodeFinal(EVP_ctx, (unsigned char*)text, &i);
265 #endif
266
267 *ret = text;
268 if (rlen != NULL) {
269 *rlen = tlen;
270 }
271
272 #if !(OPENSSL_VERSION_NUMBER < 0x10100005L)
273 EVP_ENCODE_CTX_free(EVP_ctx);
274 #endif
275 return 1;
276 }
277
_ldapfull_base64_encode(const unsigned char * src,int srclen,char ** ret,int * rlen)278 static int _ldapfull_base64_encode( const unsigned char *src, int srclen, char **ret, int *rlen ) {
279 int tlen = 0;
280 unsigned char *text;
281 #if OPENSSL_VERSION_NUMBER < 0x10100005L
282 EVP_ENCODE_CTX EVP_ctx;
283 #else
284 EVP_ENCODE_CTX *EVP_ctx;
285 #endif
286
287 text = (unsigned char *)malloc((srclen*4/3) + 1 );
288 if (text == NULL) {
289 return 0;
290 }
291
292 #if OPENSSL_VERSION_NUMBER < 0x10100005L
293 EVP_EncodeInit(&EVP_ctx);
294 EVP_EncodeUpdate(&EVP_ctx, text, &tlen, src, srclen);
295 EVP_EncodeFinal(&EVP_ctx, text, &tlen);
296 #else
297 EVP_ctx = EVP_ENCODE_CTX_new();
298 EVP_EncodeInit(EVP_ctx);
299 EVP_EncodeUpdate(EVP_ctx, text, &tlen, src, srclen);
300 EVP_EncodeFinal(EVP_ctx, text, &tlen);
301 #endif
302
303 *ret = (char*)text;
304 if (rlen != NULL) {
305 *rlen = tlen;
306 }
307
308 #if !(OPENSSL_VERSION_NUMBER < 0x10100005L)
309 EVP_ENCODE_CTX_free(EVP_ctx);
310 #endif
311 return 1;
312 }
313
_ldapfull_chk_hashed(moddata_t data,const char * scheme,int salted,const char * hash,const char * passwd)314 int _ldapfull_chk_hashed(moddata_t data, const char *scheme, int salted, const char *hash, const char *passwd) {
315 const unsigned char *bhash; // binary hash, will get it from base64
316 EVP_MD_CTX *mdctx;
317 const EVP_MD *md;
318 unsigned char digest[EVP_MAX_MD_SIZE];
319 int bhlen, rc;
320
321 md = EVP_get_digestbyname(scheme);
322 if (!md) {
323 return 0;
324 }
325 if( ! _ldapfull_base64_decode(hash, &bhash, &bhlen) ) {
326 return 0;
327 }
328
329 #if OPENSSL_VERSION_NUMBER < 0x10100005L
330 mdctx = EVP_MD_CTX_create();
331 #else
332 mdctx = EVP_MD_CTX_new();
333 #endif
334 EVP_DigestInit(mdctx, md);
335 EVP_DigestUpdate(mdctx, passwd, strlen(passwd));
336 if (salted) {
337 EVP_DigestUpdate(mdctx, &bhash[EVP_MD_size(md)],
338 bhlen - EVP_MD_size(md));
339 }
340 EVP_DigestFinal(mdctx, digest, NULL);
341
342 rc = memcmp((char *)bhash, (char *)digest, EVP_MD_size(md));
343 free((void*)bhash);
344 #if OPENSSL_VERSION_NUMBER < 0x10100005L
345 EVP_MD_CTX_destroy(mdctx);
346 #else
347 EVP_MD_CTX_free(mdctx);
348 #endif
349 return !rc;
350 }
351
_ldapfull_set_hashed(moddata_t data,const char * scheme,const char * prefix,int saltlen,const char * passwd,char * buf,int buflen)352 int _ldapfull_set_hashed(moddata_t data, const char *scheme, const char *prefix, int saltlen, const char *passwd, char *buf, int buflen) {
353 char *hash = 0; // base64 hash
354 EVP_MD_CTX *mdctx;
355 const EVP_MD *md;
356 unsigned char *digest;
357 unsigned char *salt;
358 int hlen=0;
359 int plen, rc;
360 unsigned int dlen;
361
362 md = EVP_get_digestbyname(scheme);
363 if (!md) {
364 return 0;
365 }
366
367 #if OPENSSL_VERSION_NUMBER < 0x10100005L
368 mdctx = EVP_MD_CTX_create();
369 #else
370 mdctx = EVP_MD_CTX_new();
371 #endif
372 EVP_DigestInit(mdctx, md);
373 EVP_DigestUpdate(mdctx, passwd, strlen(passwd));
374 if (saltlen) {
375 salt = (unsigned char *)malloc(saltlen);
376 if( !salt ) {
377 #if OPENSSL_VERSION_NUMBER < 0x10100005L
378 EVP_MD_CTX_destroy(mdctx);
379 #else
380 EVP_MD_CTX_free(mdctx);
381 #endif
382 return 0;
383 }
384 if( !RAND_bytes(salt,saltlen) ) {
385 #if OPENSSL_VERSION_NUMBER < 0x10100005L
386 EVP_MD_CTX_destroy(mdctx);
387 #else
388 EVP_MD_CTX_free(mdctx);
389 #endif
390 free(salt);
391 return 0;
392 }
393 EVP_DigestUpdate(mdctx, salt, saltlen);
394 }
395 digest = (unsigned char *)malloc(EVP_MD_size(md) + saltlen);
396 if( !digest ) {
397 if (saltlen) {
398 free(salt);
399 }
400 #if OPENSSL_VERSION_NUMBER < 0x10100005L
401 EVP_MD_CTX_destroy(mdctx);
402 #else
403 EVP_MD_CTX_free(mdctx);
404 #endif
405 return 0;
406 }
407 EVP_DigestFinal(mdctx, digest, &dlen);
408
409 memcpy(digest+dlen,salt,saltlen);
410 if (saltlen) {
411 free(salt);
412 }
413 rc = _ldapfull_base64_encode(digest, dlen+saltlen, &hash, &hlen);
414 if( hash[hlen-1] == '\n' ) {
415 hash[--hlen] = '\0';
416 }
417 free(digest);
418 if( !rc ) {
419 free(hash);
420 #if OPENSSL_VERSION_NUMBER < 0x10100005L
421 EVP_MD_CTX_destroy(mdctx);
422 #else
423 EVP_MD_CTX_free(mdctx);
424 #endif
425 return 0;
426 }
427
428 plen = strlen(prefix);
429 if( hlen + plen >= buflen ) {
430 log_write(data->ar->c2s->log,LOG_ERR,"_ldapfull_set_hashed: buffer is too short (%i bytes)",buflen);
431 free(hash);
432 #if OPENSSL_VERSION_NUMBER < 0x10100005L
433 EVP_MD_CTX_destroy(mdctx);
434 #else
435 EVP_MD_CTX_free(mdctx);
436 #endif
437 return 0;
438 }
439 memcpy(buf,prefix,plen);
440 memcpy(buf+plen,hash,hlen);
441 buf[hlen+plen]='\0';
442 free(hash);
443 #if OPENSSL_VERSION_NUMBER < 0x10100005L
444 EVP_MD_CTX_destroy(mdctx);
445 #else
446 EVP_MD_CTX_free(mdctx);
447 #endif
448
449 return 1;
450 }
451 #endif // HAVE_SSL
452
453 #ifdef HAVE_CRYPT
454 /** Check UNIX style crypt hashed password */
_ldapfull_chk_crypt(moddata_t data,const char * scheme,int salted,const char * hash,const char * passwd)455 int _ldapfull_chk_crypt(moddata_t data, const char *scheme, int salted, const char *hash, const char *passwd) {
456 const char *encrypted;
457 char salt[3];
458 if (strlen(hash) != 13) {
459 log_write(data->ar->c2s->log, LOG_ERR, "Invalid crypt hash length %d", strlen(hash));
460 return 0;
461 }
462 salt[0] = hash[0];
463 salt[1] = hash[1];
464 salt[2] = 0;
465 encrypted = crypt(passwd, salt);
466 return !strcmp(encrypted, hash);
467 }
468
_ldapfull_set_crypt(moddata_t data,const char * scheme,const char * prefix,int saltlen,const char * passwd,char * buf,int buflen)469 int _ldapfull_set_crypt(moddata_t data, const char *scheme, const char *prefix, int saltlen, const char *passwd, char *buf, int buflen) {
470 const char *encrypted;
471 char salt[3];
472 static const char saltchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
473 if ((saltlen != 2) || (buflen < 14)) {
474 log_write(data->ar->c2s->log, LOG_ERR, "Invalid crypt hash params");
475 return 0;
476 }
477 #ifdef HAVE_SSL
478 if( !RAND_bytes((unsigned char*)salt, saltlen) )
479 return 0;
480 salt[0] = saltchars[salt[0] % 64];
481 salt[1] = saltchars[salt[1] % 64];
482 salt[2] = 0;
483 #else
484 /* Note: This is not a cryptographically secure random number generator */
485 salt[0] = saltchars[random() % 64];
486 salt[1] = saltchars[random() % 64];
487 salt[2] = 0;
488 #endif
489 encrypted = crypt(passwd, salt);
490 strncpy(buf, encrypted, buflen);
491 buf[buflen-1] = 0;
492 return 1;
493 }
494 #endif // HAVE_CRYPT
495
496
497 /** Makes a copy of enough LDAP data in order to establish a second connection */
copy_ldap_config(moddata_t from,moddata_t to)498 static void copy_ldap_config(moddata_t from, moddata_t to)
499 {
500 memset(to, 0, sizeof(struct moddata_st));
501 to->uri = from->uri;
502 to->ar = from->ar;
503 }
504
_ldapfull_hash_init()505 int _ldapfull_hash_init() {
506 #ifdef HAVE_SSL
507 OpenSSL_add_all_digests();
508 #else
509 srandom(time(NULL) ^ getpid());
510 #endif
511 return 1;
512 }
513 //////////////////////////////////////////////////////////////////////////////
514 //
515 // end of stuff for hashing passwords
516 //
517 //////////////////////////////////////////////////////////////////////////////
518
519
520 /** utility function to get ld_errno */
_ldapfull_get_lderrno(LDAP * ld)521 static int _ldapfull_get_lderrno(LDAP *ld)
522 {
523 int ld_errno;
524
525 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
526
527 return ld_errno;
528 }
529
530 /** connect to the ldap host */
_ldapfull_connect(moddata_t data)531 static int _ldapfull_connect(moddata_t data)
532 {
533 int ldapversion = LDAP_VERSION3;
534 int rc;
535
536 if(data->ld != NULL)
537 ldap_unbind_s(data->ld);
538
539 data->binded=0;
540
541 rc = ldap_initialize(&(data->ld), data->uri);
542 if( rc != LDAP_SUCCESS )
543 {
544 log_write(data->ar->c2s->log, LOG_ERR, "ldap: ldap_initialize failed, uri=%s (%d): %s", data->uri, rc, ldap_err2string(rc));
545 return 1;
546 }
547
548 if (ldap_set_option(data->ld, LDAP_OPT_PROTOCOL_VERSION, &ldapversion) != LDAP_SUCCESS)
549 {
550 log_write(data->ar->c2s->log, LOG_ERR, "ldap: couldn't set v3 protocol");
551 return 1;
552 }
553
554 if (ldap_set_option(data->ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON) != LDAP_SUCCESS) {
555 log_write(data->ar->c2s->log, LOG_ERR, "ldap: couldn't set LDAP_OPT_REFERRALS");
556 }
557
558 log_debug(ZONE, "connected to ldap server");
559
560 return 0;
561 }
562
563 /** unbind and clear variables */
_ldapfull_unbind(moddata_t data)564 static int _ldapfull_unbind(moddata_t data) {
565 ldap_unbind_s(data->ld);
566 data->ld = NULL;
567 data->binded = 0;
568 log_debug(ZONE, "unbinded from ldap server");
569 return 0;
570 }
571
572 /** connect to ldap and bind as data->binddn */
_ldapfull_connect_bind(moddata_t data)573 static int _ldapfull_connect_bind(moddata_t data)
574 {
575 if(data->ld != NULL && data->binded ) {
576 return 0;
577 }
578
579 if( _ldapfull_connect(data) ) {
580 return 1;
581 }
582
583 if(ldap_simple_bind_s(data->ld, data->binddn, data->bindpw))
584 {
585 log_write(data->ar->c2s->log, LOG_ERR, "ldap: bind as '%s' failed: %s", data->binddn, ldap_err2string(_ldapfull_get_lderrno(data->ld)));
586 _ldapfull_unbind(data);
587 return 1;
588 }
589
590 log_debug(ZONE, "binded to ldap server");
591 data->binded = 1;
592 return 0;
593 }
594
595 /** do a search, return the dn */
_ldapfull_search(moddata_t data,const char * realm,const char * username)596 static char *_ldapfull_search(moddata_t data, const char *realm, const char *username)
597 {
598 char validfilter[256], filter[1024], *dn, *no_attrs[] = { NULL };
599 const char *basedn;
600 LDAPMessage *result, *entry;
601 int tried = 0;
602
603 log_debug(ZONE, "searching for %s", username);
604
605 basedn = xhash_get(data->basedn, realm);
606 if(basedn == NULL)
607 basedn = data->default_basedn;
608
609 if(basedn == NULL) {
610 log_write(data->ar->c2s->log, LOG_ERR, "ldap: no basedn specified for realm '%s'", realm);
611 _ldapfull_unbind(data);
612 return NULL;
613 }
614
615 // for AD validattr should be =TRUE, for [open]ldap =1
616 if( data->validattr ) {
617 validfilter[0] = '\0';
618 if( data->srvtype == LDAPFULL_SRVTYPE_AD ) {
619 snprintf(validfilter, 256, "(%s=TRUE)", data->validattr);
620 } else {
621 snprintf(validfilter, 256, "(%s=1)", data->validattr);
622 }
623 if( data->fulluid ) {
624 snprintf(filter, 1024, "(&(objectClass=%s)%s(%s=%s@%s))", data->objectclass, validfilter, data->uidattr, username, realm);
625 } else {
626 snprintf(filter, 1024, "(&(objectClass=%s)%s(%s=%s))", data->objectclass, validfilter, data->uidattr, username);
627 }
628 } else {
629 if( data->fulluid ) {
630 snprintf(filter, 1024, "(&(objectClass=%s)(%s=%s@%s))", data->objectclass, data->uidattr, username, realm);
631 } else {
632 snprintf(filter, 1024, "(&(objectClass=%s)(%s=%s))", data->objectclass, data->uidattr, username);
633 }
634 }
635
636 log_debug(ZONE, "search filter: %s", filter);
637
638 retry:
639 if(ldap_search_s(data->ld, basedn, LDAP_SCOPE_SUBTREE, filter, no_attrs, 0, &result))
640 {
641 if( tried++ < LDAPFULL_SEARCH_MAX_RETRIES ) {
642 log_debug(ZONE, "ldap: search fail, will retry; %s: %s", filter, ldap_err2string(_ldapfull_get_lderrno(data->ld)));
643 _ldapfull_unbind(data);
644 if( _ldapfull_connect_bind(data) == 0 ) {
645 goto retry;
646 } else {
647 return NULL;
648 }
649 }
650 log_write(data->ar->c2s->log, LOG_ERR, "ldap: search %s failed: %s", filter, ldap_err2string(_ldapfull_get_lderrno(data->ld)));
651 _ldapfull_unbind(data);
652 return NULL;
653 }
654
655 entry = ldap_first_entry(data->ld, result);
656 if(entry == NULL)
657 {
658 ldap_msgfree(result);
659
660 return NULL;
661 }
662
663 dn = ldap_get_dn(data->ld, entry);
664
665 ldap_msgfree(result);
666
667 log_debug(ZONE, "found user %s: dn=%s", username, dn);
668
669 return dn;
670 }
671
672 /** Is this user part of the given LDAP group? */
_ldapfull_user_in_group(moddata_t data,const char * user_dn,const char * group_dn)673 static int _ldapfull_user_in_group(moddata_t data, const char *user_dn, const char *group_dn)
674 {
675 LDAPMessage *result, *entry;
676 int tried = 0;
677 char filter[1024];
678
679 log_debug(ZONE, "checking whether user with dn %s is in group %s", user_dn, group_dn);
680
681 memset(filter, 0, 1024);
682 snprintf(filter, 1024, "(member=%s)", user_dn); // TODO Check if snprintf result was truncated
683
684 retry:
685 if(ldap_search_s(data->ld, group_dn, LDAP_SCOPE_BASE, filter, NULL, 0, &result))
686 {
687 if( tried++ < LDAPFULL_SEARCH_MAX_RETRIES ) {
688 log_debug(ZONE, "ldap: group search fail, will retry; %s: %s", filter, ldap_err2string(_ldapfull_get_lderrno(data->ld)));
689 _ldapfull_unbind(data);
690 if( _ldapfull_connect_bind(data) == 0 ) {
691 goto retry;
692 } else {
693 return 0;
694 }
695 }
696 log_write(data->ar->c2s->log, LOG_ERR, "ldap: group search %s failed: %s", filter, ldap_err2string(_ldapfull_get_lderrno(data->ld)));
697 _ldapfull_unbind(data);
698 return 0;
699 }
700
701 entry = ldap_first_entry(data->ld, result);
702 if(entry == NULL)
703 {
704 ldap_msgfree(result);
705
706 return 0;
707 }
708 else
709 {
710 ldap_msgfree(result);
711
712 return 1;
713 }
714 }
715
716 /** Get distinguished name for this user if we have it */
_ldapfull_find_user_dn(moddata_t data,const char * username,const char * realm,const char ** dn)717 static int _ldapfull_find_user_dn(moddata_t data, const char *username, const char *realm, const char **dn)
718 {
719 *dn = NULL;
720 if(_ldapfull_connect_bind(data))
721 return 0; // error
722
723 log_debug(ZONE, "checking existance of %s", username);
724
725 *dn = _ldapfull_search(data, realm, username);
726 return *dn != NULL;
727 }
728
729 /** do we have this user? */
_ldapfull_user_exists(authreg_t ar,sess_t sess,const char * username,const char * realm)730 static int _ldapfull_user_exists(authreg_t ar, sess_t sess, const char *username, const char *realm)
731 {
732 const char *dn;
733 if (_ldapfull_find_user_dn((moddata_t) ar->private, username, realm, &dn)) {
734 if(((moddata_t) ar->private)->group_dn != NULL
735 && !_ldapfull_user_in_group((moddata_t) ar->private, dn, ((moddata_t) ar->private)->group_dn)) {
736 ldap_memfree((void*)dn);
737 return 0;
738 }
739 ldap_memfree((void*)dn);
740 return 1;
741 }
742 return 0;
743 }
744
745 /** This method determines the DN of the user and does a new simple bind of the LDAP
746 server. If the server allows it, the user has been authenticated.
747 */
_ldapfull_check_password_bind(authreg_t ar,const char * username,const char * realm,char password[LDAPFULL_PASSBUF_MAX])748 static int _ldapfull_check_password_bind(authreg_t ar, const char *username, const char *realm, char password[LDAPFULL_PASSBUF_MAX])
749 {
750 moddata_t data = (moddata_t) ar->private;
751 struct moddata_st bind_data;
752 int invalid;
753 const char *dn;
754
755 if (!_ldapfull_find_user_dn(data, username, realm, &dn)) {
756 log_debug(ZONE, "User %s not found", username);
757 return 1;
758 }
759
760 /* Try logging in to the LDAP server as this user's DN */
761 copy_ldap_config(data, &bind_data);
762 bind_data.binddn = dn;
763 bind_data.bindpw = password;
764 invalid = _ldapfull_connect_bind(&bind_data);
765 if (!invalid)
766 _ldapfull_unbind(&bind_data);
767 ldap_memfree((void*)dn);
768 return invalid;
769 }
770
771 // get password from jabberPassword attribute
_ldapfull_get_password(authreg_t ar,sess_t sess,const char * username,const char * realm,char password[LDAPFULL_PASSBUF_MAX])772 static int _ldapfull_get_password(authreg_t ar, sess_t sess, const char *username, const char *realm, char password[LDAPFULL_PASSBUF_MAX]) {
773 moddata_t data = (moddata_t) ar->private;
774 LDAPMessage *result, *entry;
775 const char *dn, *no_attrs[] = { data->pwattr, NULL };
776 char **vals;
777
778 log_debug(ZONE, "getting password for %s", username);
779
780 if( _ldapfull_connect_bind(data) ) {
781 return 1;
782 }
783
784 dn = _ldapfull_search(data, realm, username);
785 if(dn == NULL)
786 return 1;
787
788 if(ldap_search_s(data->ld, dn, LDAP_SCOPE_BASE, "(objectClass=*)", (char**)no_attrs, 0, &result))
789 {
790 log_write(data->ar->c2s->log, LOG_ERR, "ldap: search %s failed: %s", dn, ldap_err2string(_ldapfull_get_lderrno(data->ld)));
791 ldap_memfree((void*)dn);
792 _ldapfull_unbind(data);
793 return 1;
794 }
795
796 ldap_memfree((void*)dn);
797
798 entry = ldap_first_entry(data->ld, result);
799 if(entry == NULL)
800 {
801 ldap_msgfree(result);
802 return 1;
803 }
804
805 vals=ldap_get_values(data->ld,entry,data->pwattr);
806 if( ldap_count_values(vals) <= 0 ) {
807 ldap_value_free(vals);
808 ldap_msgfree(result);
809 return 1;
810 }
811 strncpy(password,vals[0],LDAPFULL_PASSBUF_MAX-1);
812 password[LDAPFULL_PASSBUF_MAX-1] = '\0';
813 ldap_value_free(vals);
814
815 ldap_msgfree(result);
816
817 log_debug(ZONE, "found password for %s", username);
818
819 return 0;
820 }
821
822 // set password from jabberPassword attribute
_ldapfull_set_password(authreg_t ar,sess_t sess,const char * username,const char * realm,char password[LDAPFULL_PASSBUF_MAX])823 static int _ldapfull_set_password(authreg_t ar, sess_t sess, const char *username, const char *realm, char password[LDAPFULL_PASSBUF_MAX]) {
824 moddata_t data = (moddata_t) ar->private;
825 LDAPMessage *result, *entry;
826 LDAPMod *mods[2], attr_pw;
827 char buf[LDAPFULL_PASSBUF_MAX];
828 char *pdn, *attrs[] = { NULL }, *pw_mod_vals[] = { buf, NULL };
829 char dn[LDAPFULL_DN_MAX];
830
831 log_debug(ZONE, "setting password for %s", username);
832
833 if( ! _ldapfull_set_passhash(data,data->pwscheme,password,buf,LDAPFULL_PASSBUF_MAX) ) {
834 log_debug(ZONE, "password scheme is not defined");
835 return 1;
836 }
837
838 if( _ldapfull_connect_bind(data) ) {
839 return 1;
840 }
841
842 pdn = _ldapfull_search(data, realm, username);
843 if(pdn == NULL)
844 return 1;
845
846 strncpy(dn, pdn, LDAPFULL_DN_MAX-1); dn[LDAPFULL_DN_MAX-1] = '\0';
847 ldap_memfree(pdn);
848
849 if(ldap_search_s(data->ld, dn, LDAP_SCOPE_BASE, "(objectClass=*)", attrs, 0, &result))
850 {
851 log_write(data->ar->c2s->log, LOG_ERR, "ldap: search %s failed: %s", dn, ldap_err2string(_ldapfull_get_lderrno(data->ld)));
852 _ldapfull_unbind(data);
853 return 1;
854 }
855
856 entry = ldap_first_entry(data->ld, result);
857 if(entry == NULL)
858 {
859 ldap_msgfree(result);
860 return 1;
861 }
862 ldap_msgfree(result);
863
864 attr_pw.mod_op = LDAP_MOD_REPLACE;
865 attr_pw.mod_type = (char*)data->pwattr;
866 attr_pw.mod_values = pw_mod_vals;
867
868 mods[0] = &attr_pw;
869 mods[1] = NULL;
870
871 if( ldap_modify_s(data->ld, dn, mods) != LDAP_SUCCESS ) {
872 log_write(data->ar->c2s->log, LOG_ERR, "ldap: error modifying %s: %s", dn, ldap_err2string(_ldapfull_get_lderrno(data->ld)));
873 _ldapfull_unbind(data);
874 return 1;
875 }
876
877 log_debug(ZONE, "password was set for %s", username);
878
879 return 0;
880 }
881
882 /** check the password */
_ldapfull_check_password(authreg_t ar,sess_t sess,const char * username,const char * realm,char password[LDAPFULL_PASSBUF_MAX])883 static int _ldapfull_check_password(authreg_t ar, sess_t sess, const char *username, const char *realm, char password[LDAPFULL_PASSBUF_MAX])
884 {
885 moddata_t data = (moddata_t) ar->private;
886 char buf[LDAPFULL_PASSBUF_MAX];
887 const char *dn = NULL;
888
889 log_debug(ZONE, "checking password for %s", username);
890
891 if(password[0] == '\0')
892 return 1;
893
894 if(data->group_dn != NULL) {
895 if (!_ldapfull_find_user_dn(data, username, realm, &dn))
896 return 1;
897 }
898 /* The bind scheme doesn't need the password read first, so short circuit
899 the whole passhash scheme */
900 if (!strcmp(data->pwscheme, "bind")) {
901 if(_ldapfull_check_password_bind(ar, username, realm, password) == 0) {
902 if(data->group_dn != NULL && !_ldapfull_user_in_group(data, dn, data->group_dn)) {
903 ldap_memfree((void*)dn);
904 return 1;
905 }
906 else {
907 ldap_memfree((void*)dn);
908 return 0;
909 }
910 }
911 }
912
913 if( _ldapfull_get_password(ar,sess,username,realm,buf) != 0 ) {
914 if(dn != NULL)
915 ldap_memfree((void*)dn);
916 return 1;
917 }
918
919 if(_ldapfull_check_passhash(data,buf,password)){
920 if(data->group_dn != NULL && !_ldapfull_user_in_group(data, dn, data->group_dn)) {
921 ldap_memfree((void*)dn);
922 return 1;
923 }
924 else {
925 if(dn != NULL)
926 ldap_memfree((void*)dn);
927 return 0;
928 }
929 }
930 else {
931 if(dn != NULL)
932 ldap_memfree((void*)dn);
933 return 1;
934 }
935 }
936
_ldapfull_create_user(authreg_t ar,sess_t sess,const char * username,const char * realm)937 static int _ldapfull_create_user(authreg_t ar, sess_t sess, const char *username, const char *realm) {
938 if( _ldapfull_user_exists(ar,sess,username,realm) ) {
939 return 0;
940 } else {
941 return 1;
942 }
943 }
944
_ldapfull_delete_user(authreg_t ar,sess_t sess,const char * username,const char * realm)945 static int _ldapfull_delete_user(authreg_t ar, sess_t sess, const char *username, const char *realm) {
946 return 0;
947 }
948
949 /** shut me down */
_ldapfull_free(authreg_t ar)950 static void _ldapfull_free(authreg_t ar)
951 {
952 moddata_t data = (moddata_t) ar->private;
953
954 _ldapfull_unbind(data);
955
956 xhash_free(data->basedn);
957 free(data);
958
959 return;
960 }
961
962 /** start me up */
ar_init(authreg_t ar)963 DLLEXPORT int ar_init(authreg_t ar)
964 {
965 moddata_t data;
966 const char *uri, *realm, *srvtype_s;
967 config_elem_t basedn;
968 int i,hascheck,srvtype_i;
969
970 uri = config_get_one(ar->c2s->config, "authreg.ldapfull.uri", 0);
971 if(uri == NULL)
972 {
973 log_write(ar->c2s->log, LOG_ERR, "ldap: no uri specified in config file");
974 return 1;
975 }
976
977 basedn = config_get(ar->c2s->config, "authreg.ldapfull.basedn");
978 if(basedn == NULL)
979 {
980 log_write(ar->c2s->log, LOG_ERR, "ldap: no basedn specified in config file");
981 return 1;
982 }
983
984 srvtype_s = config_get_one(ar->c2s->config, "authreg.ldapfull.type", 0);
985 if( srvtype_s == NULL ) {
986 srvtype_i = LDAPFULL_SRVTYPE_LDAP;
987 } else if( !strcmp(srvtype_s, "ldap") ) {
988 srvtype_i = LDAPFULL_SRVTYPE_LDAP;
989 } else if( !strcmp(srvtype_s, "ad") ) {
990 srvtype_i = LDAPFULL_SRVTYPE_AD;
991 } else {
992 log_write(ar->c2s->log, LOG_ERR, "ldap: unknown server type: %s", srvtype_s);
993 return 1;
994 }
995
996 data = (moddata_t) calloc(1, sizeof(struct moddata_st));
997
998 data->basedn = xhash_new(101);
999
1000 for(i = 0; i < basedn->nvalues; i++)
1001 {
1002 realm = (basedn->attrs[i] != NULL) ? j_attr((const char **) basedn->attrs[i], "realm") : NULL;
1003 if(realm == NULL)
1004 data->default_basedn = basedn->values[i];
1005 else
1006 xhash_put(data->basedn, realm, (void*)basedn->values[i]);
1007
1008 log_debug(ZONE, "realm '%s' has base dn '%s'", realm, basedn->values[i]);
1009 }
1010
1011 log_write(ar->c2s->log, LOG_NOTICE, "ldap: configured %d realms", i);
1012
1013 data->uri = uri;
1014
1015 data->srvtype = srvtype_i;
1016
1017 data->binddn = config_get_one(ar->c2s->config, "authreg.ldapfull.binddn", 0);
1018 if(data->binddn != NULL)
1019 data->bindpw = config_get_one(ar->c2s->config, "authreg.ldapfull.bindpw", 0);
1020
1021 data->uidattr = config_get_one(ar->c2s->config, "authreg.ldapfull.uidattr", 0);
1022 if(data->uidattr == NULL)
1023 data->uidattr = "uid";
1024
1025 data->validattr = config_get_one(ar->c2s->config, "authreg.ldapfull.validattr", 0);
1026
1027 data->group_dn = config_get_one(ar->c2s->config, "authreg.ldapfull.group_dn", 0);
1028
1029 data->pwattr = config_get_one(ar->c2s->config, "authreg.ldapfull.pwattr", 0);
1030 if(data->pwattr == NULL)
1031 data->pwattr = "jabberPassword";
1032
1033 data->pwscheme = config_get_one(ar->c2s->config, "authreg.ldapfull.pwscheme", 0);
1034 if(data->pwscheme == NULL) {
1035 data->pwscheme = "clear";
1036 hascheck=0;
1037 } else {
1038 hascheck=1;
1039 }
1040
1041 data->objectclass = config_get_one(ar->c2s->config, "authreg.ldapfull.objectclass", 0);
1042 if(data->objectclass == NULL)
1043 data->objectclass = "jabberUser";
1044
1045 if( (char *)config_get_one(ar->c2s->config, "authreg.ldapfull.fulluid", 0) != NULL ) {
1046 data->fulluid = 1;
1047 }
1048
1049 data->ar = ar;
1050
1051 if(_ldapfull_connect_bind(data))
1052 {
1053 xhash_free(data->basedn);
1054 free(data);
1055 return 1;
1056 }
1057
1058 _ldapfull_hash_init();
1059
1060 ar->private = data;
1061
1062 ar->user_exists = _ldapfull_user_exists;
1063 ar->create_user = _ldapfull_create_user;
1064 ar->delete_user = _ldapfull_delete_user;
1065 ar->set_password = _ldapfull_set_password;
1066 if( hascheck ) {
1067 ar->check_password = _ldapfull_check_password;
1068 } else {
1069 ar->get_password = _ldapfull_get_password;
1070 }
1071
1072 ar->free = _ldapfull_free;
1073
1074 return 0;
1075 }
1076
1077 #endif // STORAGE_LDAP
1078