]> git.ipfire.org Git - thirdparty/squid.git/blame - helpers/external_acl/kerberos_ldap_group/support_ldap.cc
Bug 3650: Negotiate auth missing challenge token
[thirdparty/squid.git] / helpers / external_acl / kerberos_ldap_group / support_ldap.cc
CommitLineData
b1218840
AJ
1/*
2 * -----------------------------------------------------------------------------
3 *
4 * Author: Markus Moeller (markus_moeller at compuserve.com)
5 *
6 * Copyright (C) 2007 Markus Moeller. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21 *
22 * -----------------------------------------------------------------------------
23 */
24
f7f3304a 25#include "squid.h"
b1218840
AJ
26#include "util.h"
27
28#ifdef HAVE_LDAP
29
30#include "support.h"
31#ifdef HAVE_ERRNO_H
32#include <errno.h>
33#endif
34
35char *convert_domain_to_bind_path(char *domain);
36char *escape_filter(char *filter);
37int check_AD(struct main_args *margs, LDAP * ld);
38int ldap_set_defaults(struct main_args *margs, LDAP * ld);
39int ldap_set_ssl_defaults(struct main_args *margs);
40LDAP *tool_ldap_open(struct main_args *margs, char *host, int port, char *ssl);
41
42#define CONNECT_TIMEOUT 2
43#define SEARCH_TIMEOUT 30
44
45#define FILTER "(memberuid=%s)"
46#define ATTRIBUTE "cn"
47#define FILTER_UID "(uid=%s)"
48#define FILTER_GID "(&(gidNumber=%s)(objectclass=posixgroup))"
49#define ATTRIBUTE_GID "gidNumber"
50
51#define FILTER_AD "(samaccountname=%s)"
52#define ATTRIBUTE_AD "memberof"
53
54int get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char *attribute /* IN */ , char ***out_val /* OUT (caller frees) */ );
55int search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_group, char *group, int depth);
56
57#if defined(HAVE_SUN_LDAP_SDK) || defined(HAVE_MOZILLA_LDAP_SDK)
58#ifdef HAVE_LDAP_REBINDPROC_CALLBACK
59
60#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
61static LDAP_REBINDPROC_CALLBACK ldap_sasl_rebind;
62
63static int LDAP_CALL LDAP_CALLBACK
64ldap_sasl_rebind(
65 LDAP * ld,
66 char **whop,
67 char **credp,
68 int *methodp,
69 int freeit,
70 void *params)
71{
72 struct ldap_creds *cp = (struct ldap_creds *) params;
73 whop = whop;
74 credp = credp;
75 methodp = methodp;
76 freeit = freeit;
77 return tool_sasl_bind(ld, cp->dn, cp->pw);
78}
79#endif
80
81static LDAP_REBINDPROC_CALLBACK ldap_simple_rebind;
82
83static int LDAP_CALL LDAP_CALLBACK
84ldap_simple_rebind(
85 LDAP * ld,
86 char **whop,
87 char **credp,
88 int *methodp,
89 int freeit,
90 void *params)
91{
92 struct ldap_creds *cp = (struct ldap_creds *) params;
93 whop = whop;
94 credp = credp;
95 methodp = methodp;
96 freeit = freeit;
97 return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
98}
99#elif defined(HAVE_LDAP_REBIND_PROC)
100#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
101static LDAP_REBIND_PROC ldap_sasl_rebind;
102
103static int
104ldap_sasl_rebind(
105 LDAP * ld,
106 LDAP_CONST char *url,
107 ber_tag_t request,
108 ber_int_t msgid,
109 void *params)
110{
111 struct ldap_creds *cp = (struct ldap_creds *) params;
112 url = url;
113 request = request;
114 msgid = msgid;
115 return tool_sasl_bind(ld, cp->dn, cp->pw);
116}
117#endif
118
119static LDAP_REBIND_PROC ldap_simple_rebind;
120
121static int
122ldap_simple_rebind(
123 LDAP * ld,
124 LDAP_CONST char *url,
125 ber_tag_t request,
126 ber_int_t msgid,
127 void *params)
128{
129 struct ldap_creds *cp = (struct ldap_creds *) params;
130 url = url;
131 request = request;
132 msgid = msgid;
133 return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
134}
135
136#elif defined(HAVE_LDAP_REBIND_FUNCTION)
137#ifndef LDAP_REFERRALS
138#define LDAP_REFERRALS
139#endif
140#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
141static LDAP_REBIND_FUNCTION ldap_sasl_rebind;
142
143static int
144ldap_sasl_rebind(
145 LDAP * ld,
146 char **whop,
147 char **credp,
148 int *methodp,
149 int freeit,
150 void *params)
151{
152 struct ldap_creds *cp = (struct ldap_creds *) params;
153 whop = whop;
154 credp = credp;
155 methodp = methodp;
156 freeit = freeit;
157 return tool_sasl_bind(ld, cp->dn, cp->pw);
158}
159#endif
160
161static LDAP_REBIND_FUNCTION ldap_simple_rebind;
162
163static int
164ldap_simple_rebind(
165 LDAP * ld,
166 char **whop,
167 char **credp,
168 int *methodp,
169 int freeit,
170 void *params)
171{
172 struct ldap_creds *cp = (struct ldap_creds *) params;
173 whop = whop;
174 credp = credp;
175 methodp = methodp;
176 freeit = freeit;
177 return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
178}
179#else
180#error "No rebind functione defined"
181#endif
182#else /* HAVE_SUN_LDAP_SDK */
183#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
184static LDAP_REBIND_PROC ldap_sasl_rebind;
185
186static int
187ldap_sasl_rebind(
188 LDAP * ld,
189 LDAP_CONST char *url,
190 ber_tag_t request,
191 ber_int_t msgid,
192 void *params)
193{
194 struct ldap_creds *cp = (struct ldap_creds *) params;
195 url = url;
196 request = request;
197 msgid = msgid;
198 return tool_sasl_bind(ld, cp->dn, cp->pw);
199}
200#endif
201
202static LDAP_REBIND_PROC ldap_simple_rebind;
203
204static int
205ldap_simple_rebind(
206 LDAP * ld,
207 LDAP_CONST char *url,
208 ber_tag_t request,
209 ber_int_t msgid,
210 void *params)
211{
212
213 struct ldap_creds *cp = (struct ldap_creds *) params;
214 url = url;
215 request = request;
216 msgid = msgid;
217 return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
218}
219
220#endif
221char *
222convert_domain_to_bind_path(char *domain)
223{
224 char *dp, *bindp = NULL, *bp = NULL;
225 int i = 0;
226
227 if (!domain)
2e881a6f 228 return NULL;
b1218840 229
a2f5277a 230 for (dp = domain; *dp; ++dp) {
2e881a6f 231 if (*dp == '.')
755494da 232 ++i;
b1218840 233 }
2e881a6f
A
234 /*
235 * add dc= and
236 * replace . with ,dc= => new length = old length + #dots * 3 + 3
b1218840
AJ
237 */
238 bindp = (char *) xmalloc(strlen(domain) + 3 + i * 3 + 1);
239 bp = bindp;
240 strcpy(bp, "dc=");
241 bp += 3;
a2f5277a 242 for (dp = domain; *dp; ++dp) {
2e881a6f
A
243 if (*dp == '.') {
244 strcpy(bp, ",dc=");
245 bp += 4;
f207fe64
FC
246 } else {
247 *bp = *dp;
248 ++bp;
249 }
b1218840
AJ
250 }
251 *bp = '\0';
252 return bindp;
253}
254
255char *
256escape_filter(char *filter)
257{
258 int i;
259 char *ldap_filter_esc, *ldf;
260
261 i = 0;
a2f5277a 262 for (ldap_filter_esc = filter; *ldap_filter_esc; ++ldap_filter_esc) {
2e881a6f
A
263 if ((*ldap_filter_esc == '*') ||
264 (*ldap_filter_esc == '(') ||
265 (*ldap_filter_esc == ')') ||
266 (*ldap_filter_esc == '\\'))
267 i = i + 3;
b1218840
AJ
268 }
269
270 ldap_filter_esc = (char *) xcalloc(strlen(filter) + i + 1, sizeof(char));
271 ldf = ldap_filter_esc;
a2f5277a 272 for (; *filter; ++filter) {
2e881a6f
A
273 if (*filter == '*') {
274 strcpy(ldf, "\\2a");
275 ldf = ldf + 3;
276 } else if (*filter == '(') {
277 strcpy(ldf, "\\28");
278 ldf = ldf + 3;
279 } else if (*filter == ')') {
280 strcpy(ldf, "\\29");
281 ldf = ldf + 3;
282 } else if (*filter == '\\') {
283 strcpy(ldf, "\\5c");
284 ldf = ldf + 3;
285 } else {
286 *ldf = *filter;
755494da 287 ++ldf;
2e881a6f 288 }
b1218840
AJ
289 }
290 *ldf = '\0';
291
292 return ldap_filter_esc;
293};
294
295int
296check_AD(struct main_args *margs, LDAP * ld)
297{
298 LDAPMessage *res;
299 char **attr_value = NULL;
300 struct timeval searchtime;
301 int max_attr = 0;
302 int j, rc = 0;
303
304#define FILTER_SCHEMA "(objectclass=*)"
305#define ATTRIBUTE_SCHEMA "schemaNamingContext"
306#define FILTER_SAM "(ldapdisplayname=samaccountname)"
307
308 searchtime.tv_sec = SEARCH_TIMEOUT;
309 searchtime.tv_usec = 0;
310
311 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path \"\" and filter: %s\n", LogTime(), PROGRAM, FILTER_SCHEMA);
312 rc = ldap_search_ext_s(ld, (char *) "", LDAP_SCOPE_BASE, (char *) FILTER_SCHEMA, NULL, 0,
2e881a6f 313 NULL, NULL, &searchtime, 0, &res);
b1218840
AJ
314
315 if (rc == LDAP_SUCCESS)
2e881a6f 316 max_attr = get_attributes(margs, ld, res, ATTRIBUTE_SCHEMA, &attr_value);
b1218840
AJ
317
318 if (max_attr == 1) {
2e881a6f
A
319 ldap_msgfree(res);
320 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, attr_value[0], FILTER_SAM);
321 rc = ldap_search_ext_s(ld, attr_value[0], LDAP_SCOPE_SUBTREE, (char *) FILTER_SAM, NULL, 0,
322 NULL, NULL, &searchtime, 0, &res);
323 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
324 if (ldap_count_entries(ld, res) > 0)
325 margs->AD = 1;
b1218840 326 } else
2e881a6f 327 debug((char *) "%s| %s: DEBUG: Did not find ldap entry for subschemasubentry\n", LogTime(), PROGRAM);
b1218840
AJ
328 debug((char *) "%s| %s: DEBUG: Determined ldap server %sas an Active Directory server\n", LogTime(), PROGRAM, margs->AD ? "" : "not ");
329 /*
330 * Cleanup
331 */
332 if (attr_value) {
a2f5277a 333 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
334 xfree(attr_value[j]);
335 }
336 xfree(attr_value);
337 attr_value = NULL;
b1218840
AJ
338 }
339 ldap_msgfree(res);
340 return rc;
341}
342int
343search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_group, char *group, int depth)
344{
345 LDAPMessage *res = NULL;
346 char **attr_value = NULL;
347 int max_attr = 0;
348 char *filter = NULL;
349 char *search_exp = NULL;
350 int j, rc = 0, retval = 0;
351 char *av = NULL, *avp = NULL;
352 int ldepth;
353 char *ldap_filter_esc = NULL;
354 struct timeval searchtime;
355
356#define FILTER_GROUP_AD "(&(%s)(objectclass=group))"
357#define FILTER_GROUP "(&(memberuid=%s)(objectclass=posixgroup))"
358
359 searchtime.tv_sec = SEARCH_TIMEOUT;
360 searchtime.tv_usec = 0;
361
362 if (margs->AD)
2e881a6f 363 filter = (char *) FILTER_GROUP_AD;
b1218840 364 else
2e881a6f 365 filter = (char *) FILTER_GROUP;
b1218840
AJ
366
367 ldap_filter_esc = escape_filter(ldap_group);
368
369 search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
370 snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
371
4ad7aabf 372 xfree(ldap_filter_esc);
b1218840
AJ
373
374 if (depth > margs->mdepth) {
2e881a6f 375 debug((char *) "%s| %s: DEBUG: Max search depth reached %d>%d\n", LogTime(), PROGRAM, depth, margs->mdepth);
4ad7aabf 376 xfree(search_exp);
2e881a6f 377 return 0;
b1218840
AJ
378 }
379 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
380 rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
2e881a6f
A
381 search_exp, NULL, 0,
382 NULL, NULL, &searchtime, 0, &res);
4ad7aabf 383 xfree(search_exp);
b1218840
AJ
384
385 if (rc != LDAP_SUCCESS) {
2e881a6f
A
386 error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
387 ldap_unbind_s(ld);
388 return 0;
b1218840
AJ
389 }
390 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
391
392 if (margs->AD)
2e881a6f 393 max_attr = get_attributes(margs, ld, res, ATTRIBUTE_AD, &attr_value);
b1218840 394 else
2e881a6f 395 max_attr = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value);
b1218840
AJ
396
397 /*
398 * Compare group names
399 */
400 retval = 0;
401 ldepth = depth + 1;
a2f5277a 402 for (j = 0; j < max_attr; ++j) {
b1218840 403
2e881a6f
A
404 /* Compare first CN= value assuming it is the same as the group name itself */
405 av = attr_value[j];
406 if (!strncasecmp("CN=", av, 3)) {
407 av += 3;
408 if ((avp = strchr(av, ','))) {
409 *avp = '\0';
410 }
411 }
412 if (debug_enabled) {
413 int n;
414 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
a2f5277a 415 for (n = 0; av[n] != '\0'; ++n)
2e881a6f
A
416 fprintf(stderr, "%02x", (unsigned char) av[n]);
417 fprintf(stderr, "\n");
418 }
419 if (!strcasecmp(group, av)) {
420 retval = 1;
421 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
422 break;
423 } else
424 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
425 /*
426 * Do recursive group search
427 */
428 debug((char *) "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n", LogTime(), PROGRAM, av);
429 av = attr_value[j];
430 if (search_group_tree(margs, ld, bindp, av, group, ldepth)) {
431 retval = 1;
432 if (!strncasecmp("CN=", av, 3)) {
433 av += 3;
434 if ((avp = strchr(av, ','))) {
435 *avp = '\0';
436 }
437 }
438 if (debug_enabled)
439 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" is member of group named \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
440 else
441 break;
442
443 }
b1218840
AJ
444 }
445
446 /*
447 * Cleanup
448 */
449 if (attr_value) {
a2f5277a 450 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
451 xfree(attr_value[j]);
452 }
453 xfree(attr_value);
454 attr_value = NULL;
b1218840
AJ
455 }
456 ldap_msgfree(res);
457
458 return retval;
459}
460
461int
462ldap_set_defaults(struct main_args *margs, LDAP * ld)
463{
464 int val, rc = 0;
465#ifdef LDAP_OPT_NETWORK_TIMEOUT
466 struct timeval tv;
467#endif
468 val = LDAP_VERSION3;
469 rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &val);
470 if (rc != LDAP_SUCCESS) {
2e881a6f
A
471 debug((char *) "%s| %s: DEBUG: Error while setting protocol version: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
472 return rc;
b1218840
AJ
473 }
474 rc = ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
475 if (rc != LDAP_SUCCESS) {
2e881a6f
A
476 debug((char *) "%s| %s: DEBUG: Error while setting referrals off: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
477 return rc;
b1218840
AJ
478 }
479#ifdef LDAP_OPT_NETWORK_TIMEOUT
480 tv.tv_sec = CONNECT_TIMEOUT;
481 tv.tv_usec = 0;
482 rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
483 if (rc != LDAP_SUCCESS) {
2e881a6f
A
484 debug((char *) "%s| %s: DEBUG: Error while setting network timeout: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
485 return rc;
b1218840
AJ
486 }
487#endif /* LDAP_OPT_NETWORK_TIMEOUT */
488 return LDAP_SUCCESS;
489}
490
491int
492ldap_set_ssl_defaults(struct main_args *margs)
493{
494#if defined(HAVE_OPENLDAP) || defined(HAVE_LDAPSSL_CLIENT_INIT)
495 int rc = 0;
496#endif
497#ifdef HAVE_OPENLDAP
498 int val;
499 char *ssl_cacertfile = NULL;
500 int free_path;
501#elif defined(HAVE_LDAPSSL_CLIENT_INIT)
502 char *ssl_certdbpath = NULL;
503#endif
504
505#ifdef HAVE_OPENLDAP
506 if (!margs->rc_allow) {
2e881a6f
A
507 debug((char *) "%s| %s: DEBUG: Enable server certificate check for ldap server.\n", LogTime(), PROGRAM);
508 val = LDAP_OPT_X_TLS_DEMAND;
509 rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
510 if (rc != LDAP_SUCCESS) {
511 error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
512 return rc;
513 }
514 ssl_cacertfile = getenv("TLS_CACERTFILE");
515 free_path = 0;
516 if (!ssl_cacertfile) {
517 ssl_cacertfile = xstrdup("/etc/ssl/certs/cert.pem");
518 free_path = 1;
519 }
520 debug((char *) "%s| %s: DEBUG: Set certificate file for ldap server to %s.(Changeable through setting environment variable TLS_CACERTFILE)\n", LogTime(), PROGRAM, ssl_cacertfile);
521 rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ssl_cacertfile);
522 if (ssl_cacertfile && free_path) {
523 xfree(ssl_cacertfile);
524 ssl_cacertfile = NULL;
525 }
526 if (rc != LDAP_OPT_SUCCESS) {
527 error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
528 return rc;
529 }
b1218840 530 } else {
2e881a6f
A
531 debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM);
532 val = LDAP_OPT_X_TLS_ALLOW;
533 rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
534 if (rc != LDAP_SUCCESS) {
535 error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
536 return rc;
537 }
b1218840
AJ
538 }
539#elif defined(HAVE_LDAPSSL_CLIENT_INIT)
2e881a6f 540 /*
b1218840
AJ
541 * Solaris SSL ldap calls require path to certificate database
542 */
2e881a6f
A
543 /*
544 * rc = ldapssl_client_init( ssl_certdbpath, NULL );
545 * rc = ldapssl_advclientauth_init( ssl_certdbpath, NULL , 0 , NULL, NULL, 0, NULL, 2);
546 */
b1218840
AJ
547 ssl_certdbpath = getenv("SSL_CERTDBPATH");
548 if (!ssl_certdbpath) {
2e881a6f 549 ssl_certdbpath = xstrdup("/etc/certs");
b1218840
AJ
550 }
551 debug((char *) "%s| %s: DEBUG: Set certificate database path for ldap server to %s.(Changeable through setting environment variable SSL_CERTDBPATH)\n", LogTime(), PROGRAM, ssl_certdbpath);
552 if (!margs->rc_allow) {
2e881a6f 553 rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0, NULL, 2);
b1218840 554 } else {
2e881a6f
A
555 rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0, NULL, 0);
556 debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM);
b1218840
AJ
557 }
558 if (ssl_certdbpath) {
2e881a6f
A
559 xfree(ssl_certdbpath);
560 ssl_certdbpath = NULL;
b1218840
AJ
561 }
562 if (rc != LDAP_SUCCESS) {
2e881a6f
A
563 error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM, ldapssl_err2string(rc));
564 return rc;
b1218840
AJ
565 }
566#else
567 error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM);
568#endif
569 return LDAP_SUCCESS;
570}
571
572int
573get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char *attribute, char ***ret_value)
574{
575
576 LDAPMessage *msg;
577 char **attr_value = NULL;
578 int max_attr = 0;
579
580 attr_value = *ret_value;
581 /*
582 * loop over attributes
583 */
584 debug((char *) "%s| %s: DEBUG: Search ldap entries for attribute : %s\n", LogTime(), PROGRAM, attribute);
585 for (msg = ldap_first_entry(ld, res); msg; msg = ldap_next_entry(ld, msg)) {
586
2e881a6f
A
587 BerElement *b;
588 char *attr;
589
590 switch (ldap_msgtype(msg)) {
591
592 case LDAP_RES_SEARCH_ENTRY:
593
594 for (attr = ldap_first_attribute(ld, msg, &b); attr;
595 attr = ldap_next_attribute(ld, msg, b)) {
596 if (strcasecmp(attr, attribute) == 0) {
597 struct berval **values;
598 int il;
599
600 if ((values = ldap_get_values_len(ld, msg, attr)) != NULL) {
a2f5277a 601 for (il = 0; values[il] != NULL; ++il) {
2e881a6f
A
602
603 attr_value = (char **) xrealloc(attr_value, (il + 1) * sizeof(char *));
604 if (!attr_value)
605 break;
606
607 attr_value[il] = (char *) xmalloc(values[il]->bv_len + 1);
608 memcpy(attr_value[il], values[il]->bv_val, values[il]->bv_len);
609 attr_value[il][values[il]->bv_len] = 0;
610 }
611 max_attr = il;
612 }
613 ber_bvecfree(values);
614 }
615 ldap_memfree(attr);
616 }
617 ber_free(b, 0);
618 break;
619 case LDAP_RES_SEARCH_REFERENCE:
620 debug((char *) "%s| %s: DEBUG: Received a search reference message\n", LogTime(), PROGRAM);
621 break;
622 case LDAP_RES_SEARCH_RESULT:
623 debug((char *) "%s| %s: DEBUG: Received a search result message\n", LogTime(), PROGRAM);
624 break;
625 default:
626 break;
627 }
b1218840
AJ
628 }
629
630 debug((char *) "%s| %s: DEBUG: %d ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM, max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
631
632 *ret_value = attr_value;
633 return max_attr;
634}
635
636/*
637 * call to open ldap server with or without SSL
638 */
639LDAP *
640tool_ldap_open(struct main_args * margs, char *host, int port, char *ssl)
641{
642 LDAP *ld;
643#ifdef HAVE_OPENLDAP
644 LDAPURLDesc *url = NULL;
645 char *ldapuri = NULL;
646#endif
647 int rc = 0;
648
2e881a6f
A
649 /*
650 * Use ldap open here to check if TCP connection is possible. If possible use it.
b1218840
AJ
651 * (Not sure if this is the best way)
652 */
653#ifdef HAVE_OPENLDAP
654 url = (LDAPURLDesc *) xmalloc(sizeof(*url));
655 memset(url, 0, sizeof(*url));
656#ifdef HAVE_LDAP_URL_LUD_SCHEME
657 if (ssl)
2e881a6f 658 url->lud_scheme = (char *) "ldaps";
b1218840 659 else
2e881a6f 660 url->lud_scheme = (char *) "ldap";
b1218840
AJ
661#endif
662 url->lud_host = host;
663 url->lud_port = port;
664#ifdef HAVE_LDAP_SCOPE_DEFAULT
665 url->lud_scope = LDAP_SCOPE_DEFAULT;
666#else
667 url->lud_scope = LDAP_SCOPE_SUBTREE;
668#endif
669#ifdef HAVE_LDAP_URL_DESC2STR
670 ldapuri = ldap_url_desc2str(url);
671#elif defined(HAVE_LDAP_URL_PARSE)
672 rc = ldap_url_parse(ldapuri, &url);
673 if (rc != LDAP_SUCCESS) {
2e881a6f 674 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
b656d212
AJ
675 xfree(ldapuri);
676 xfree(url);
2e881a6f 677 return NULL;
b1218840
AJ
678 }
679#else
680#error "No URL parsing function"
681#endif
b656d212 682 safe_free(url);
b1218840 683 rc = ldap_initialize(&ld, ldapuri);
b656d212 684 xfree(ldapuri);
b1218840 685 if (rc != LDAP_SUCCESS) {
2e881a6f
A
686 error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
687 ldap_unbind(ld);
688 ld = NULL;
689 return NULL;
b1218840
AJ
690 }
691#else
692 ld = ldap_init(host, port);
693#endif
694 rc = ldap_set_defaults(margs, ld);
695 if (rc != LDAP_SUCCESS) {
2e881a6f
A
696 error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
697 ldap_unbind(ld);
698 ld = NULL;
699 return NULL;
b1218840
AJ
700 }
701 if (ssl) {
2e881a6f
A
702 /*
703 * Try Start TLS first
704 */
705 debug((char *) "%s| %s: DEBUG: Set SSL defaults\n", LogTime(), PROGRAM);
706 rc = ldap_set_ssl_defaults(margs);
707 if (rc != LDAP_SUCCESS) {
708 error((char *) "%s| %s: ERROR: Error while setting SSL default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
709 ldap_unbind(ld);
710 ld = NULL;
711 return NULL;
712 }
b1218840 713#ifdef HAVE_OPENLDAP
2e881a6f
A
714 /*
715 * Use tls if possible
716 */
717 rc = ldap_start_tls_s(ld, NULL, NULL);
718 if (rc != LDAP_SUCCESS) {
719 error((char *) "%s| %s: ERROR: Error while setting start_tls for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
720 ldap_unbind(ld);
721 ld = NULL;
722 url = (LDAPURLDesc *) xmalloc(sizeof(*url));
723 memset(url, 0, sizeof(*url));
b1218840 724#ifdef HAVE_LDAP_URL_LUD_SCHEME
2e881a6f 725 url->lud_scheme = (char *) "ldaps";
b1218840 726#endif
2e881a6f
A
727 url->lud_host = host;
728 url->lud_port = port;
b1218840 729#ifdef HAVE_LDAP_SCOPE_DEFAULT
2e881a6f 730 url->lud_scope = LDAP_SCOPE_DEFAULT;
b1218840 731#else
2e881a6f 732 url->lud_scope = LDAP_SCOPE_SUBTREE;
b1218840
AJ
733#endif
734#ifdef HAVE_LDAP_URL_DESC2STR
2e881a6f 735 ldapuri = ldap_url_desc2str(url);
b1218840 736#elif defined(HAVE_LDAP_URL_PARSE)
2e881a6f
A
737 rc = ldap_url_parse(ldapuri, &url);
738 if (rc != LDAP_SUCCESS) {
739 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
4ad7aabf
AJ
740 xfree(ldapuri);
741 xfree(url);
2e881a6f
A
742 return NULL;
743 }
b1218840
AJ
744#else
745#error "No URL parsing function"
746#endif
4ad7aabf 747 safe_free(url);
2e881a6f 748 rc = ldap_initialize(&ld, ldapuri);
4ad7aabf 749 xfree(ldapuri);
2e881a6f
A
750 if (rc != LDAP_SUCCESS) {
751 error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
752 ldap_unbind(ld);
753 ld = NULL;
754 return NULL;
755 }
756 rc = ldap_set_defaults(margs, ld);
757 if (rc != LDAP_SUCCESS) {
758 error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
759 ldap_unbind(ld);
760 ld = NULL;
761 return NULL;
762 }
763 }
b1218840 764#elif defined(HAVE_LDAPSSL_CLIENT_INIT)
2e881a6f
A
765 ld = ldapssl_init(host, port, 1);
766 if (!ld) {
767 error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM, ldapssl_err2string(rc));
768 ldap_unbind(ld);
769 ld = NULL;
770 return NULL;
771 }
772 rc = ldap_set_defaults(margs, ld);
773 if (rc != LDAP_SUCCESS) {
774 error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
775 ldap_unbind(ld);
776 ld = NULL;
777 return NULL;
778 }
b1218840 779#else
2e881a6f 780 error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM);
b1218840
AJ
781#endif
782 }
783 return ld;
784}
785
786/*
787 * ldap calls to get attribute from Ldap Directory Server
788 */
789int
790get_memberof(struct main_args *margs, char *user, char *domain, char *group)
791{
792 LDAP *ld = NULL;
793 LDAPMessage *res;
794#ifndef HAVE_SUN_LDAP_SDK
795 int ldap_debug = 0;
796#endif
797 struct ldap_creds *lcreds = NULL;
798 char *bindp = NULL;
799 char *filter = NULL;
800 char *search_exp;
801 struct timeval searchtime;
802 int i, j, rc = 0, kc = 1;
803 int retval;
804 char **attr_value = NULL;
805 char *av = NULL, *avp = NULL;
806 int max_attr = 0;
807 struct hstruct *hlist = NULL;
808 int nhosts = 0;
809 char *hostname;
810 char *host;
811 int port;
812 char *ssl = NULL;
813 char *p;
814 char *ldap_filter_esc = NULL;
815
b1218840
AJ
816 searchtime.tv_sec = SEARCH_TIMEOUT;
817 searchtime.tv_usec = 0;
818 /*
819 * Fill Kerberos memory cache with credential from keytab for SASL/GSSAPI
820 */
821 if (domain) {
2e881a6f 822 debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n", LogTime(), PROGRAM);
b1218840 823
bec91ba0 824#ifdef HAVE_KRB5
2e881a6f
A
825 kc = krb5_create_cache(margs, domain);
826 if (kc) {
827 error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n", LogTime(), PROGRAM);
828 }
bec91ba0
MM
829#else
830 kc = 1;
831 debug((char *) "%s| %s: DEBUG: Kerberos is not supported. Use username/passwaord with ldap url instead\n", LogTime(), PROGRAM);
832#endif
b1218840 833 }
bec91ba0 834
b1218840 835 if (kc && (!margs->lurl || !margs->luser | !margs->lpass)) {
2e881a6f
A
836 /*
837 * If Kerberos fails and no url given exit here
838 */
839 retval = 0;
840 goto cleanup;
b1218840
AJ
841 }
842#ifndef HAVE_SUN_LDAP_SDK
843 /*
844 * Initialise ldap
845 */
846 ldap_debug = 127 /* LDAP_DEBUG_TRACE */ ;
847 ldap_debug = -1 /* LDAP_DEBUG_ANY */ ;
848 ldap_debug = 0;
849 (void) ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_debug);
850#endif
851 debug((char *) "%s| %s: DEBUG: Initialise ldap connection\n", LogTime(), PROGRAM);
852
853 if (domain && !kc) {
2e881a6f
A
854 if (margs->ssl) {
855 debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM);
856 }
857 debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n", LogTime(), PROGRAM, domain);
858 /*
859 * Loop over list of ldap servers of users domain
860 */
861 nhosts = get_ldap_hostname_list(margs, &hlist, 0, domain);
a2f5277a 862 for (i = 0; i < nhosts; ++i) {
2e881a6f
A
863 port = 389;
864 if (hlist[i].port != -1)
865 port = hlist[i].port;
866 debug((char *) "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n", LogTime(), PROGRAM, hlist[i].host, port);
867
868 ld = tool_ldap_open(margs, hlist[i].host, port, margs->ssl);
869 if (!ld)
870 continue;
871
872 /*
873 * ldap bind with SASL/GSSAPI authentication (only possible if a domain was part of the username)
874 */
b1218840
AJ
875
876#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
2e881a6f
A
877 debug((char *) "%s| %s: DEBUG: Bind to ldap server with SASL/GSSAPI\n", LogTime(), PROGRAM);
878
879 rc = tool_sasl_bind(ld, bindp, margs->ssl);
880 if (rc != LDAP_SUCCESS) {
881 error((char *) "%s| %s: ERROR: Error while binding to ldap server with SASL/GSSAPI: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
882 ldap_unbind(ld);
883 ld = NULL;
884 continue;
885 }
886 lcreds = (ldap_creds *) xmalloc(sizeof(struct ldap_creds));
4ad7aabf 887 lcreds->dn = NULL;
2e881a6f
A
888 lcreds->pw = margs->ssl ? xstrdup(margs->ssl) : NULL;
889 ldap_set_rebind_proc(ld, ldap_sasl_rebind, (char *) lcreds);
890 if (ld != NULL) {
891 debug((char *) "%s| %s: DEBUG: %s initialised %sconnection to ldap server %s:%d\n", LogTime(), PROGRAM, ld ? "Successfully" : "Failed to", margs->ssl ? "SSL protected " : "", hlist[i].host, port);
892 break;
893 }
b1218840 894#else
2e881a6f
A
895 ldap_unbind(ld);
896 ld = NULL;
897 error((char *) "%s| %s: ERROR: SASL not supported on system\n", LogTime(), PROGRAM);
898 continue;
b1218840 899#endif
2e881a6f
A
900 }
901 nhosts = free_hostname_list(&hlist, nhosts);
902 if (ld == NULL) {
903 debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM, strerror(errno));
904 }
905 bindp = convert_domain_to_bind_path(domain);
b1218840
AJ
906 }
907 if ((!domain || !ld) && margs->lurl && strstr(margs->lurl, "://")) {
2e881a6f
A
908 /*
909 * If username does not contain a domain and a url was given then try it
910 */
911 hostname = strstr(margs->lurl, "://") + 3;
912 ssl = strstr(margs->lurl, "ldaps://");
913 if (ssl) {
914 debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM);
915 }
916 debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name %s\n", LogTime(), PROGRAM, hostname);
917 /*
918 * Loop over list of ldap servers
919 */
920 host = xstrdup(hostname);
921 port = 389;
922 if ((p = strchr(host, ':'))) {
923 *p = '\0';
755494da 924 ++p;
2e881a6f
A
925 port = atoi(p);
926 }
927 nhosts = get_hostname_list(margs, &hlist, 0, host);
4ad7aabf 928 safe_free(host);
a2f5277a 929 for (i = 0; i < nhosts; ++i) {
2e881a6f
A
930
931 ld = tool_ldap_open(margs, hlist[i].host, port, ssl);
932 if (!ld)
933 continue;
934 /*
935 * ldap bind with username/password authentication
936 */
937
938 debug((char *) "%s| %s: DEBUG: Bind to ldap server with Username/Password\n", LogTime(), PROGRAM);
939 rc = ldap_simple_bind_s(ld, margs->luser, margs->lpass);
940 if (rc != LDAP_SUCCESS) {
941 error((char *) "%s| %s: ERROR: Error while binding to ldap server with Username/Password: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
942 ldap_unbind(ld);
943 ld = NULL;
944 continue;
945 }
946 lcreds = (ldap_creds *) xmalloc(sizeof(struct ldap_creds));
947 lcreds->dn = xstrdup(margs->luser);
948 lcreds->pw = xstrdup(margs->lpass);
949 ldap_set_rebind_proc(ld, ldap_simple_rebind, (char *) lcreds);
950 debug((char *) "%s| %s: DEBUG: %s set up %sconnection to ldap server %s:%d\n", LogTime(), PROGRAM, ld ? "Successfully" : "Failed to", ssl ? "SSL protected " : "", hlist[i].host, port);
951 break;
952
953 }
954 nhosts = free_hostname_list(&hlist, nhosts);
4ad7aabf 955 xfree(bindp);
2e881a6f
A
956 if (margs->lbind) {
957 bindp = xstrdup(margs->lbind);
958 } else {
959 bindp = convert_domain_to_bind_path(domain);
960 }
b1218840
AJ
961 }
962 if (ld == NULL) {
2e881a6f
A
963 debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM, strerror(errno));
964 retval = 0;
965 goto cleanup;
b1218840
AJ
966 }
967 /*
968 * ldap search for user
969 */
2e881a6f 970 /*
b1218840
AJ
971 * Check if server is AD by querying for attribute samaccountname
972 */
973 margs->AD = 0;
974 rc = check_AD(margs, ld);
975 if (rc != LDAP_SUCCESS) {
2e881a6f
A
976 error((char *) "%s| %s: ERROR: Error determining ldap server type: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
977 ldap_unbind(ld);
978 ld = NULL;
979 retval = 0;
980 goto cleanup;
b1218840
AJ
981 }
982 if (margs->AD)
2e881a6f 983 filter = (char *) FILTER_AD;
b1218840 984 else
2e881a6f 985 filter = (char *) FILTER;
b1218840
AJ
986
987 ldap_filter_esc = escape_filter(user);
988
989 search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
990 snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
991
4ad7aabf 992 xfree(ldap_filter_esc);
b1218840
AJ
993
994 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
995 rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
2e881a6f
A
996 search_exp, NULL, 0,
997 NULL, NULL, &searchtime, 0, &res);
4ad7aabf 998 xfree(search_exp);
b1218840
AJ
999
1000 if (rc != LDAP_SUCCESS) {
2e881a6f
A
1001 error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
1002 ldap_unbind(ld);
1003 ld = NULL;
1004 retval = 0;
1005 goto cleanup;
b1218840
AJ
1006 }
1007 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
1008
1009 if (ldap_count_entries(ld, res) != 0) {
1010
2e881a6f
A
1011 if (margs->AD)
1012 max_attr = get_attributes(margs, ld, res, ATTRIBUTE_AD, &attr_value);
1013 else {
1014 max_attr = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value);
1015 }
1016
1017 /*
1018 * Compare group names
1019 */
1020 retval = 0;
a2f5277a 1021 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
1022
1023 /* Compare first CN= value assuming it is the same as the group name itself */
1024 av = attr_value[j];
1025 if (!strncasecmp("CN=", av, 3)) {
1026 av += 3;
1027 if ((avp = strchr(av, ','))) {
1028 *avp = '\0';
1029 }
1030 }
1031 if (debug_enabled) {
1032 int n;
1033 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
a2f5277a 1034 for (n = 0; av[n] != '\0'; ++n)
2e881a6f
A
1035 fprintf(stderr, "%02x", (unsigned char) av[n]);
1036 fprintf(stderr, "\n");
1037 }
1038 if (!strcasecmp(group, av)) {
1039 retval = 1;
1040 if (debug_enabled)
1041 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
1042 else
1043 break;
1044 } else
1045 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
1046 }
1047 /*
1048 * Do recursive group search for AD only since posixgroups can not contain other groups
1049 */
1050 if (!retval && margs->AD) {
1051 if (debug_enabled && max_attr > 0) {
1052 debug((char *) "%s| %s: DEBUG: Perform recursive group search\n", LogTime(), PROGRAM);
1053 }
a2f5277a 1054 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
1055
1056 av = attr_value[j];
1057 if (search_group_tree(margs, ld, bindp, av, group, 1)) {
1058 retval = 1;
1059 if (!strncasecmp("CN=", av, 3)) {
1060 av += 3;
1061 if ((avp = strchr(av, ','))) {
1062 *avp = '\0';
1063 }
1064 }
1065 if (debug_enabled)
1066 debug((char *) "%s| %s: DEBUG: Entry %d group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
1067 else
1068 break;
1069 }
1070 }
1071 }
1072 /*
1073 * Cleanup
1074 */
1075 if (attr_value) {
a2f5277a 1076 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
1077 xfree(attr_value[j]);
1078 }
1079 xfree(attr_value);
1080 attr_value = NULL;
1081 }
1082 ldap_msgfree(res);
b1218840 1083 } else if (ldap_count_entries(ld, res) == 0 && margs->AD) {
2e881a6f
A
1084 ldap_msgfree(res);
1085 ldap_unbind(ld);
1086 ld = NULL;
1087 retval = 0;
1088 goto cleanup;
b1218840 1089 } else {
2e881a6f
A
1090 ldap_msgfree(res);
1091 retval = 0;
b1218840
AJ
1092 }
1093
1094 if (!margs->AD && retval == 0) {
2e881a6f
A
1095 /*
1096 * Check for primary Group membership
1097 */
1098 debug((char *) "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n", LogTime(), PROGRAM, group);
1099 filter = (char *) FILTER_UID;
1100
1101 ldap_filter_esc = escape_filter(user);
1102
1103 search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
1104 snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
1105
4ad7aabf 1106 xfree(ldap_filter_esc);
2e881a6f
A
1107
1108 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
1109 rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
1110 search_exp, NULL, 0,
1111 NULL, NULL, &searchtime, 0, &res);
4ad7aabf 1112 xfree(search_exp);
2e881a6f
A
1113
1114 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
1115
1116 max_attr = get_attributes(margs, ld, res, ATTRIBUTE_GID, &attr_value);
1117
1118 if (max_attr == 1) {
1119 char **attr_value_2 = NULL;
1120 int max_attr_2 = 0;
1121
1122 ldap_msgfree(res);
1123 filter = (char *) FILTER_GID;
1124
1125 ldap_filter_esc = escape_filter(attr_value[0]);
1126
1127 search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
1128 snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
1129
4ad7aabf 1130 xfree(ldap_filter_esc);
2e881a6f
A
1131
1132 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
1133 rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
1134 search_exp, NULL, 0,
1135 NULL, NULL, &searchtime, 0, &res);
4ad7aabf 1136 xfree(search_exp);
2e881a6f
A
1137
1138 max_attr_2 = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value_2);
1139 /*
1140 * Compare group names
1141 */
1142 retval = 0;
1143 if (max_attr_2 == 1) {
1144
1145 /* Compare first CN= value assuming it is the same as the group name itself */
1146 av = attr_value_2[0];
1147 if (!strcasecmp(group, av)) {
1148 retval = 1;
1149 debug((char *) "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, av, group);
1150 } else
1151 debug((char *) "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, av, group);
1152
1153 }
1154 /*
1155 * Cleanup
1156 */
1157 if (attr_value_2) {
a2f5277a 1158 for (j = 0; j < max_attr_2; ++j) {
2e881a6f
A
1159 xfree(attr_value_2[j]);
1160 }
1161 xfree(attr_value_2);
1162 attr_value_2 = NULL;
1163 }
1164 ldap_msgfree(res);
1165
1166 debug((char *) "%s| %s: DEBUG: Users primary group %s %s\n", LogTime(), PROGRAM, retval ? "matches" : "does not match", group);
1167
1168 } else
1169 debug((char *) "%s| %s: DEBUG: Did not find ldap entry for group %s\n", LogTime(), PROGRAM, group);
1170 /*
1171 * Cleanup
1172 */
1173 if (attr_value) {
a2f5277a 1174 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
1175 xfree(attr_value[j]);
1176 }
1177 xfree(attr_value);
1178 attr_value = NULL;
1179 }
b1218840
AJ
1180 }
1181 rc = ldap_unbind(ld);
1182 ld = NULL;
1183 if (rc != LDAP_SUCCESS) {
2e881a6f 1184 error((char *) "%s| %s: ERROR: Error unbind ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
b1218840
AJ
1185 }
1186 debug((char *) "%s| %s: DEBUG: Unbind ldap server\n", LogTime(), PROGRAM);
2e881a6f 1187cleanup:
bec91ba0 1188#ifdef HAVE_KRB5
b1218840 1189 if (domain)
2e881a6f 1190 krb5_cleanup();
bec91ba0 1191#endif
b1218840 1192 if (lcreds) {
4ad7aabf
AJ
1193 xfree(lcreds->dn);
1194 xfree(lcreds->pw);
2e881a6f 1195 xfree(lcreds);
b1218840 1196 }
4ad7aabf 1197 xfree(bindp);
b1218840 1198 return (retval);
b1218840
AJ
1199}
1200#endif