Fix memory leak.
[Samba/gebeck_regimport.git] / source3 / passdb / pdb_ldap.c
blob46e099437934d7671249ee44cd6f278b75449e29
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Jean François Micouleau 1998
5 Copyright (C) Gerald Carter 2001
6 Copyright (C) Shahms King 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Stefan (metze) Metzmacher 2002
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_PASSDB
31 #ifdef HAVE_LDAP
32 /* TODO:
33 * persistent connections: if using NSS LDAP, many connections are made
34 * however, using only one within Samba would be nice
36 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
38 * Other LDAP based login attributes: accountExpires, etc.
39 * (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
40 * structures don't have fields for some of these attributes)
42 * SSL is done, but can't get the certificate based authentication to work
43 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
46 /* NOTE: this will NOT work against an Active Directory server
47 * due to the fact that the two password fields cannot be retrieved
48 * from a server; recommend using security = domain in this situation
49 * and/or winbind
52 #include <lber.h>
53 #include <ldap.h>
55 #ifndef SAM_ACCOUNT
56 #define SAM_ACCOUNT struct sam_passwd
57 #endif
59 struct ldapsam_privates {
61 /* Former statics */
62 LDAP *ldap_struct;
63 LDAPMessage *result;
64 LDAPMessage *entry;
65 int index;
67 time_t last_ping;
68 /* retrive-once info */
69 const char *uri;
71 BOOL permit_non_unix_accounts;
73 uint32 low_nua_rid;
74 uint32 high_nua_rid;
76 char *bind_dn;
77 char *bind_secret;
80 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
82 static struct ldapsam_privates *static_ldap_state;
84 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
86 /*******************************************************************
87 find the ldap password
88 ******************************************************************/
89 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
91 char *key = NULL;
92 size_t size;
94 *dn = smb_xstrdup(lp_ldap_admin_dn());
96 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
97 SAFE_FREE(*dn);
98 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
101 *pw=secrets_fetch(key, &size);
102 if (!size) {
103 /* Upgrade 2.2 style entry */
104 char *p;
105 char* old_style_key = strdup(*dn);
106 char *data;
107 fstring old_style_pw;
109 if (!old_style_key) {
110 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
111 return False;
114 for (p=old_style_key; *p; p++)
115 if (*p == ',') *p = '/';
117 data=secrets_fetch(old_style_key, &size);
118 if (!size && size < sizeof(old_style_pw)) {
119 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
120 SAFE_FREE(old_style_key);
121 SAFE_FREE(*dn);
122 return False;
125 strncpy(old_style_pw, data, size);
126 old_style_pw[size] = 0;
128 SAFE_FREE(data);
130 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
131 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
132 SAFE_FREE(old_style_key);
133 SAFE_FREE(*dn);
134 return False;
136 if (!secrets_delete(old_style_key)) {
137 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
140 SAFE_FREE(old_style_key);
142 *pw = smb_xstrdup(old_style_pw);
145 return True;
148 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
149 "logoffTime", "kickoffTime", "cn",
150 "pwdCanChange", "pwdMustChange",
151 "displayName", "homeDrive",
152 "smbHome", "scriptPath",
153 "profilePath", "description",
154 "userWorkstations", "rid",
155 "primaryGroupID", "lmPassword",
156 "ntPassword", "acctFlags",
157 "domain", "objectClass",
158 "uidNumber", "gidNumber",
159 "homeDirectory", NULL };
161 /*******************************************************************
162 open a connection to the ldap server.
163 ******************************************************************/
164 static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
166 int rc = LDAP_SUCCESS;
167 int version;
168 BOOL ldap_v3 = False;
170 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
171 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
173 if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
174 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
175 return rc;
178 #else
180 /* Parse the string manually */
183 int port = 0;
184 fstring protocol;
185 fstring host;
186 const char *p = ldap_state->uri;
187 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
189 /* skip leading "URL:" (if any) */
190 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
191 p += 4;
194 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
196 if (port == 0) {
197 if (strequal(protocol, "ldap")) {
198 port = LDAP_PORT;
199 } else if (strequal(protocol, "ldaps")) {
200 port = LDAPS_PORT;
201 } else {
202 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
206 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
207 DEBUG(0, ("ldap_init failed !\n"));
208 return LDAP_OPERATIONS_ERROR;
211 if (strequal(protocol, "ldaps")) {
212 #ifdef LDAP_OPT_X_TLS
213 int tls = LDAP_OPT_X_TLS_HARD;
214 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
216 DEBUG(0, ("Failed to setup a TLS session\n"));
219 DEBUG(3,("LDAPS option set...!\n"));
220 #else
221 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
222 return LDAP_OPERATIONS_ERROR;
223 #endif
226 #endif
228 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
230 if (version != LDAP_VERSION3)
232 version = LDAP_VERSION3;
233 if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
234 ldap_v3 = True;
236 } else {
237 ldap_v3 = True;
241 if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
242 #ifdef LDAP_OPT_X_TLS
243 if (ldap_v3) {
244 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
246 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
247 ldap_err2string(rc)));
248 return rc;
250 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
251 } else {
253 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
254 return LDAP_OPERATIONS_ERROR;
256 #else
257 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
258 return LDAP_OPERATIONS_ERROR;
259 #endif
262 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
263 return rc;
267 /*******************************************************************
268 a rebind function for authenticated referrals
269 This version takes a void* that we can shove useful stuff in :-)
270 ******************************************************************/
271 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
272 #else
273 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
274 int *methodp, int freeit, void *arg)
276 struct ldapsam_privates *ldap_state = arg;
278 /** @TODO Should we be doing something to check what servers we rebind to?
279 Could we get a referral to a machine that we don't want to give our
280 username and password to? */
282 if (freeit) {
283 SAFE_FREE(*whop);
284 memset(*credp, '\0', strlen(*credp));
285 SAFE_FREE(*credp);
286 } else {
287 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
288 ldap_state->bind_dn));
290 *whop = strdup(ldap_state->bind_dn);
291 if (!*whop) {
292 return LDAP_NO_MEMORY;
294 *credp = strdup(ldap_state->bind_secret);
295 if (!*credp) {
296 SAFE_FREE(*whop);
297 return LDAP_NO_MEMORY;
299 *methodp = LDAP_AUTH_SIMPLE;
301 return 0;
303 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
305 /*******************************************************************
306 a rebind function for authenticated referrals
307 This version takes a void* that we can shove useful stuff in :-)
308 and actually does the connection.
309 ******************************************************************/
310 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
311 static int rebindproc_connect_with_state (LDAP *ldap_struct,
312 LDAP_CONST char *url,
313 ber_tag_t request,
314 ber_int_t msgid, void *arg)
316 struct ldapsam_privates *ldap_state = arg;
317 int rc;
318 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
319 ldap_state->bind_dn));
321 /** @TODO Should we be doing something to check what servers we rebind to?
322 Could we get a referral to a machine that we don't want to give our
323 username and password to? */
325 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
327 return rc;
329 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
331 /*******************************************************************
332 Add a rebind function for authenticated referrals
333 ******************************************************************/
334 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
335 #else
336 # if LDAP_SET_REBIND_PROC_ARGS == 2
337 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
338 int *method, int freeit )
340 return rebindproc_with_state(ldap_struct, whop, credp,
341 method, freeit, static_ldap_state);
344 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
345 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
347 /*******************************************************************
348 a rebind function for authenticated referrals
349 this also does the connection, but no void*.
350 ******************************************************************/
351 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
352 # if LDAP_SET_REBIND_PROC_ARGS == 2
353 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
354 ber_int_t msgid)
356 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
357 static_ldap_state);
359 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
360 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
362 /*******************************************************************
363 connect to the ldap server under system privilege.
364 ******************************************************************/
365 static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
367 int rc;
368 char *ldap_dn;
369 char *ldap_secret;
371 /* The rebind proc needs this *HACK*. We are not multithreaded, so
372 this will work, but it's not nice. */
373 static_ldap_state = ldap_state;
375 /* get the password */
376 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
378 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
379 return LDAP_INVALID_CREDENTIALS;
382 ldap_state->bind_dn = ldap_dn;
383 ldap_state->bind_secret = ldap_secret;
385 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
386 (OpenLDAP) doesnt' seem to support it */
388 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
389 ldap_state->uri, ldap_dn));
391 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
392 # if LDAP_SET_REBIND_PROC_ARGS == 2
393 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
394 # endif
395 # if LDAP_SET_REBIND_PROC_ARGS == 3
396 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
397 # endif
398 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
399 # if LDAP_SET_REBIND_PROC_ARGS == 2
400 ldap_set_rebind_proc(ldap_struct, &rebindproc);
401 # endif
402 # if LDAP_SET_REBIND_PROC_ARGS == 3
403 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
404 # endif
405 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
407 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
409 if (rc != LDAP_SUCCESS) {
410 char *ld_error;
411 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
412 &ld_error);
413 DEBUG(0,
414 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
415 ldap_dn, ldap_err2string(rc),
416 ld_error));
417 free(ld_error);
418 return rc;
421 DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
422 return rc;
425 /**********************************************************************
426 Connect to LDAP server
427 *********************************************************************/
428 static int ldapsam_open(struct ldapsam_privates *ldap_state)
430 int rc;
431 SMB_ASSERT(ldap_state);
433 #ifndef NO_LDAP_SECURITY
434 if (geteuid() != 0) {
435 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
436 return LDAP_INSUFFICIENT_ACCESS;
438 #endif
440 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
441 struct sockaddr_un addr;
442 socklen_t len;
443 int sd;
444 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
445 getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
446 /* the other end has died. reopen. */
447 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
448 ldap_state->ldap_struct = NULL;
449 ldap_state->last_ping = (time_t)0;
450 } else {
451 ldap_state->last_ping = time(NULL);
455 if (ldap_state->ldap_struct != NULL) {
456 DEBUG(5,("ldapsam_open: allready connected to the LDAP server\n"));
457 return LDAP_SUCCESS;
460 if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
461 return rc;
464 if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
465 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
466 ldap_state->ldap_struct = NULL;
467 return rc;
471 ldap_state->last_ping = time(NULL);
472 DEBUG(4,("The LDAP server is succesful connected\n"));
474 return LDAP_SUCCESS;
477 /**********************************************************************
478 Disconnect from LDAP server
479 *********************************************************************/
480 static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
482 if (!ldap_state)
483 return NT_STATUS_INVALID_PARAMETER;
485 if (ldap_state->ldap_struct != NULL) {
486 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
487 ldap_state->ldap_struct = NULL;
490 DEBUG(5,("The connection to the LDAP server was closed\n"));
491 /* maybe free the results here --metze */
493 return NT_STATUS_OK;
496 static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
498 int rc;
500 SMB_ASSERT(ldap_state && attempts);
502 if (*attempts != 0) {
503 /* we retry after 0.5, 2, 4.5, 8, 12.5, 18, 24.5 seconds */
504 msleep((((*attempts)*(*attempts))/2)*1000);
506 (*attempts)++;
508 if ((rc = ldapsam_open(ldap_state))) {
509 DEBUG(0,("Connection to LDAP Server failed for the %d try!\n",*attempts));
510 return rc;
513 return LDAP_SUCCESS;
517 static int ldapsam_search(struct ldapsam_privates *ldap_state,
518 const char *base, int scope, const char *filter,
519 const char *attrs[], int attrsonly,
520 LDAPMessage **res)
522 int rc = LDAP_SERVER_DOWN;
523 int attempts = 0;
525 SMB_ASSERT(ldap_state);
527 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
529 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
530 continue;
532 rc = ldap_search_s(ldap_state->ldap_struct, base, scope,
533 filter, attrs, attrsonly, res);
536 if (rc == LDAP_SERVER_DOWN) {
537 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
538 ldapsam_close(ldap_state);
541 return rc;
544 static int ldapsam_modify(struct ldapsam_privates *ldap_state, char *dn, LDAPMod *attrs[])
546 int rc = LDAP_SERVER_DOWN;
547 int attempts = 0;
549 if (!ldap_state)
550 return (-1);
552 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
554 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
555 continue;
557 rc = ldap_modify_s(ldap_state->ldap_struct, dn, attrs);
560 if (rc == LDAP_SERVER_DOWN) {
561 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
562 ldapsam_close(ldap_state);
565 return rc;
568 static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
570 int rc = LDAP_SERVER_DOWN;
571 int attempts = 0;
573 if (!ldap_state)
574 return (-1);
576 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
578 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
579 continue;
581 rc = ldap_add_s(ldap_state->ldap_struct, dn, attrs);
584 if (rc == LDAP_SERVER_DOWN) {
585 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
586 ldapsam_close(ldap_state);
589 return rc;
592 static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
594 int rc = LDAP_SERVER_DOWN;
595 int attempts = 0;
597 if (!ldap_state)
598 return (-1);
600 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
602 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
603 continue;
605 rc = ldap_delete_s(ldap_state->ldap_struct, dn);
608 if (rc == LDAP_SERVER_DOWN) {
609 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
610 ldapsam_close(ldap_state);
613 return rc;
616 static int ldapsam_extended_operation(struct ldapsam_privates *ldap_state, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls, char **retoidp, struct berval **retdatap)
618 int rc = LDAP_SERVER_DOWN;
619 int attempts = 0;
621 if (!ldap_state)
622 return (-1);
624 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
626 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
627 continue;
629 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
632 if (rc == LDAP_SERVER_DOWN) {
633 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
634 ldapsam_close(ldap_state);
637 return rc;
640 /*******************************************************************
641 run the search by name.
642 ******************************************************************/
643 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, const char *filter, LDAPMessage ** result)
645 int scope = LDAP_SCOPE_SUBTREE;
646 int rc;
648 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
650 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, filter, attr, 0, result);
652 if (rc != LDAP_SUCCESS) {
653 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n",
654 ldap_err2string (rc)));
655 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
656 filter));
659 return rc;
662 /*******************************************************************
663 run the search by name.
664 ******************************************************************/
665 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, const char *user,
666 LDAPMessage ** result)
668 pstring filter;
669 char *escape_user = escape_ldap_string_alloc(user);
671 if (!escape_user) {
672 return LDAP_NO_MEMORY;
676 * in the filter expression, replace %u with the real name
677 * so in ldap filter, %u MUST exist :-)
679 pstrcpy(filter, lp_ldap_filter());
682 * have to use this here because $ is filtered out
683 * in pstring_sub
687 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
688 SAFE_FREE(escape_user);
690 return ldapsam_search_one_user(ldap_state, filter, result);
693 /*******************************************************************
694 run the search by uid.
695 ******************************************************************/
696 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state,
697 int uid,
698 LDAPMessage ** result)
700 struct passwd *user;
701 pstring filter;
702 char *escape_user;
704 /* Get the username from the system and look that up in the LDAP */
706 if ((user = getpwuid_alloc(uid)) == NULL) {
707 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
708 return LDAP_NO_SUCH_OBJECT;
711 pstrcpy(filter, lp_ldap_filter());
713 escape_user = escape_ldap_string_alloc(user->pw_name);
714 if (!escape_user) {
715 passwd_free(&user);
716 return LDAP_NO_MEMORY;
719 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
721 passwd_free(&user);
722 SAFE_FREE(escape_user);
724 return ldapsam_search_one_user(ldap_state, filter, result);
727 /*******************************************************************
728 run the search by rid.
729 ******************************************************************/
730 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state,
731 uint32 rid,
732 LDAPMessage ** result)
734 pstring filter;
735 int rc;
737 /* check if the user rid exsists, if not, try searching on the uid */
739 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
740 rc = ldapsam_search_one_user(ldap_state, filter, result);
742 if (rc != LDAP_SUCCESS)
743 rc = ldapsam_search_one_user_by_uid(ldap_state,
744 fallback_pdb_user_rid_to_uid(rid),
745 result);
747 return rc;
750 /*******************************************************************
751 search an attribute and return the first value found.
752 ******************************************************************/
753 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
754 const char *attribute, pstring value)
756 char **values;
758 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
759 value = NULL;
760 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
762 return False;
765 pstrcpy(value, values[0]);
766 ldap_value_free(values);
767 #ifdef DEBUG_PASSWORDS
768 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
769 #endif
770 return True;
773 /************************************************************************
774 Routine to manage the LDAPMod structure array
775 manage memory used by the array, by each struct, and values
777 ************************************************************************/
778 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
780 LDAPMod **mods;
781 int i;
782 int j;
784 mods = *modlist;
786 if (attribute == NULL || *attribute == '\0')
787 return;
789 if (value == NULL || *value == '\0')
790 return;
792 if (mods == NULL)
794 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
795 if (mods == NULL)
797 DEBUG(0, ("make_a_mod: out of memory!\n"));
798 return;
800 mods[0] = NULL;
803 for (i = 0; mods[i] != NULL; ++i) {
804 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
805 break;
808 if (mods[i] == NULL)
810 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
811 if (mods == NULL)
813 DEBUG(0, ("make_a_mod: out of memory!\n"));
814 return;
816 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
817 if (mods[i] == NULL)
819 DEBUG(0, ("make_a_mod: out of memory!\n"));
820 return;
822 mods[i]->mod_op = modop;
823 mods[i]->mod_values = NULL;
824 mods[i]->mod_type = strdup(attribute);
825 mods[i + 1] = NULL;
828 if (value != NULL)
830 j = 0;
831 if (mods[i]->mod_values != NULL) {
832 for (; mods[i]->mod_values[j] != NULL; j++);
834 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
835 (j + 2) * sizeof (char *));
837 if (mods[i]->mod_values == NULL) {
838 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
839 return;
841 mods[i]->mod_values[j] = strdup(value);
842 mods[i]->mod_values[j + 1] = NULL;
844 *modlist = mods;
847 /* New Interface is being implemented here */
849 /**********************************************************************
850 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
851 *********************************************************************/
852 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
853 SAM_ACCOUNT * sampass,
854 LDAPMessage * entry)
856 pstring homedir;
857 pstring temp;
858 uid_t uid;
859 gid_t gid;
860 char **ldap_values;
861 char **values;
863 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
864 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
865 return False;
868 for (values=ldap_values;*values;values++) {
869 if (strcasecmp(*values, "posixAccount") == 0) {
870 break;
874 if (!*values) { /*end of array, no posixAccount */
875 DEBUG(10, ("user does not have posixAcccount attributes\n"));
876 ldap_value_free(ldap_values);
877 return False;
879 ldap_value_free(ldap_values);
881 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir))
882 return False;
884 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
885 return False;
887 uid = (uid_t)atol(temp);
889 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
890 return False;
892 gid = (gid_t)atol(temp);
894 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
895 pdb_set_uid(sampass, uid, PDB_SET);
896 pdb_set_gid(sampass, gid, PDB_SET);
898 DEBUG(10, ("user has posixAcccount attributes\n"));
899 return True;
903 /**********************************************************************
904 Initialize SAM_ACCOUNT from an LDAP query
905 (Based on init_sam_from_buffer in pdb_tdb.c)
906 *********************************************************************/
907 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
908 SAM_ACCOUNT * sampass,
909 LDAPMessage * entry)
911 time_t logon_time,
912 logoff_time,
913 kickoff_time,
914 pass_last_set_time,
915 pass_can_change_time,
916 pass_must_change_time;
917 pstring username,
918 domain,
919 nt_username,
920 fullname,
921 homedir,
922 dir_drive,
923 logon_script,
924 profile_path,
925 acct_desc,
926 munged_dial,
927 workstations;
928 struct passwd *pw;
929 uint32 user_rid,
930 group_rid;
931 uint8 smblmpwd[LM_HASH_LEN],
932 smbntpwd[NT_HASH_LEN];
933 uint16 acct_ctrl = 0,
934 logon_divs;
935 uint32 hours_len;
936 uint8 hours[MAX_HOURS_LEN];
937 pstring temp;
938 uid_t uid = -1;
939 gid_t gid = getegid();
943 * do a little initialization
945 username[0] = '\0';
946 domain[0] = '\0';
947 nt_username[0] = '\0';
948 fullname[0] = '\0';
949 homedir[0] = '\0';
950 dir_drive[0] = '\0';
951 logon_script[0] = '\0';
952 profile_path[0] = '\0';
953 acct_desc[0] = '\0';
954 munged_dial[0] = '\0';
955 workstations[0] = '\0';
958 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
959 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
960 return False;
963 if (ldap_state->ldap_struct == NULL) {
964 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
965 return False;
968 get_single_attribute(ldap_state->ldap_struct, entry, "uid", username);
969 DEBUG(2, ("Entry found for user: %s\n", username));
971 pstrcpy(nt_username, username);
973 pstrcpy(domain, lp_workgroup());
975 pdb_set_username(sampass, username, PDB_SET);
977 pdb_set_domain(sampass, domain, PDB_DEFAULT);
978 pdb_set_nt_username(sampass, nt_username, PDB_SET);
980 get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
981 user_rid = (uint32)atol(temp);
983 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
985 if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
986 group_rid = 0;
987 } else {
988 group_rid = (uint32)atol(temp);
989 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
994 * If so configured, try and get the values from LDAP
997 if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state, sampass, entry))) {
1000 * Otherwise just ask the system getpw() calls.
1003 pw = getpwnam_alloc(username);
1004 if (pw == NULL) {
1005 if (! ldap_state->permit_non_unix_accounts) {
1006 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
1007 return False;
1009 } else {
1010 uid = pw->pw_uid;
1011 pdb_set_uid(sampass, uid, PDB_SET);
1012 gid = pw->pw_gid;
1013 pdb_set_gid(sampass, gid, PDB_SET);
1015 pdb_set_unix_homedir(sampass, pw->pw_dir, PDB_SET);
1017 passwd_free(&pw);
1021 if (group_rid == 0 && pdb_get_init_flags(sampass,PDB_GID) != PDB_DEFAULT) {
1022 GROUP_MAP map;
1023 gid = pdb_get_gid(sampass);
1024 /* call the mapping code here */
1025 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1026 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1028 else {
1029 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1033 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1034 /* leave as default */
1035 } else {
1036 pass_last_set_time = (time_t) atol(temp);
1037 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1040 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1041 /* leave as default */
1042 } else {
1043 logon_time = (time_t) atol(temp);
1044 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1047 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1048 /* leave as default */
1049 } else {
1050 logoff_time = (time_t) atol(temp);
1051 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1054 if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1055 /* leave as default */
1056 } else {
1057 kickoff_time = (time_t) atol(temp);
1058 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1061 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1062 /* leave as default */
1063 } else {
1064 pass_can_change_time = (time_t) atol(temp);
1065 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1068 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1069 /* leave as default */
1070 } else {
1071 pass_must_change_time = (time_t) atol(temp);
1072 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1075 /* recommend that 'gecos' and 'displayName' should refer to the same
1076 * attribute OID. userFullName depreciated, only used by Samba
1077 * primary rules of LDAP: don't make a new attribute when one is already defined
1078 * that fits your needs; using cn then displayName rather than 'userFullName'
1081 if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn", fullname)) {
1082 if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName", fullname)) {
1083 /* leave as default */
1084 } else {
1085 pdb_set_fullname(sampass, fullname, PDB_SET);
1087 } else {
1088 pdb_set_fullname(sampass, fullname, PDB_SET);
1091 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1092 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
1093 lp_logon_drive(),
1094 username, domain,
1095 uid, gid),
1096 PDB_DEFAULT);
1097 } else {
1098 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1101 if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1102 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
1103 lp_logon_home(),
1104 username, domain,
1105 uid, gid),
1106 PDB_DEFAULT);
1107 } else {
1108 pdb_set_homedir(sampass, homedir, PDB_SET);
1111 if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1112 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
1113 lp_logon_script(),
1114 username, domain,
1115 uid, gid),
1116 PDB_DEFAULT);
1117 } else {
1118 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1121 if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1122 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
1123 lp_logon_path(),
1124 username, domain,
1125 uid, gid),
1126 PDB_DEFAULT);
1127 } else {
1128 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1131 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1132 /* leave as default */
1133 } else {
1134 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1137 if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1138 /* leave as default */;
1139 } else {
1140 pdb_set_workstations(sampass, workstations, PDB_SET);
1143 /* FIXME: hours stuff should be cleaner */
1145 logon_divs = 168;
1146 hours_len = 21;
1147 memset(hours, 0xff, hours_len);
1149 if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1150 /* leave as default */
1151 } else {
1152 pdb_gethexpwd(temp, smblmpwd);
1153 memset((char *)temp, '\0', strlen(temp)+1);
1154 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1155 return False;
1156 ZERO_STRUCT(smblmpwd);
1159 if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1160 /* leave as default */
1161 } else {
1162 pdb_gethexpwd(temp, smbntpwd);
1163 memset((char *)temp, '\0', strlen(temp)+1);
1164 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1165 return False;
1166 ZERO_STRUCT(smbntpwd);
1169 if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1170 acct_ctrl |= ACB_NORMAL;
1171 } else {
1172 acct_ctrl = pdb_decode_acct_ctrl(temp);
1174 if (acct_ctrl == 0)
1175 acct_ctrl |= ACB_NORMAL;
1177 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1180 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1181 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1183 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1185 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1186 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1187 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1189 pdb_set_hours(sampass, hours, PDB_SET);
1191 return True;
1194 static BOOL need_ldap_mod(BOOL pdb_add, const SAM_ACCOUNT * sampass, enum pdb_elements element) {
1195 if (pdb_add) {
1196 return (!IS_SAM_DEFAULT(sampass, element));
1197 } else {
1198 return IS_SAM_CHANGED(sampass, element);
1202 /**********************************************************************
1203 Initialize SAM_ACCOUNT from an LDAP query
1204 (Based on init_buffer_from_sam in pdb_tdb.c)
1205 *********************************************************************/
1206 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1207 LDAPMod *** mods, int ldap_op,
1208 BOOL pdb_add,
1209 const SAM_ACCOUNT * sampass)
1211 pstring temp;
1212 uint32 rid;
1214 if (mods == NULL || sampass == NULL) {
1215 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1216 return False;
1219 *mods = NULL;
1222 * took out adding "objectclass: sambaAccount"
1223 * do this on a per-mod basis
1225 if (need_ldap_mod(pdb_add, sampass, PDB_USERNAME)) {
1226 make_a_mod(mods, ldap_op, "uid", pdb_get_username(sampass));
1227 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1230 if ((rid = pdb_get_user_rid(sampass))!=0 ) {
1231 if (need_ldap_mod(pdb_add, sampass, PDB_USERSID)) {
1232 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1233 make_a_mod(mods, ldap_op, "rid", temp);
1235 } else if (!IS_SAM_DEFAULT(sampass, PDB_UID)) {
1236 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
1237 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1238 make_a_mod(mods, ldap_op, "rid", temp);
1239 } else if (ldap_state->permit_non_unix_accounts) {
1240 rid = ldapsam_get_next_available_nua_rid(ldap_state);
1241 if (rid == 0) {
1242 DEBUG(0, ("NO user RID specified on account %s, and findining next available NUA RID failed, cannot store!\n", pdb_get_username(sampass)));
1243 return False;
1245 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1246 make_a_mod(mods, ldap_op, "rid", temp);
1247 } else {
1248 DEBUG(0, ("NO user RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
1249 return False;
1254 if ((rid = pdb_get_group_rid(sampass))!=0 ) {
1255 if (need_ldap_mod(pdb_add, sampass, PDB_GROUPSID)) {
1256 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1257 make_a_mod(mods, ldap_op, "primaryGroupID", temp);
1259 } else if (!IS_SAM_DEFAULT(sampass, PDB_GID)) {
1260 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
1261 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1262 make_a_mod(mods, ldap_op, "primaryGroupID", temp);
1263 } else if (ldap_state->permit_non_unix_accounts) {
1264 rid = DOMAIN_GROUP_RID_USERS;
1265 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1266 make_a_mod(mods, ldap_op, "primaryGroupID", temp);
1267 } else {
1268 DEBUG(0, ("NO group RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
1269 return False;
1273 /* displayName, cn, and gecos should all be the same
1274 * most easily accomplished by giving them the same OID
1275 * gecos isn't set here b/c it should be handled by the
1276 * add-user script
1278 if (need_ldap_mod(pdb_add, sampass, PDB_FULLNAME)) {
1279 make_a_mod(mods, ldap_op, "displayName", pdb_get_fullname(sampass));
1280 make_a_mod(mods, ldap_op, "cn", pdb_get_fullname(sampass));
1282 if (need_ldap_mod(pdb_add, sampass, PDB_ACCTDESC)) {
1283 make_a_mod(mods, ldap_op, "description", pdb_get_acct_desc(sampass));
1285 if (need_ldap_mod(pdb_add, sampass, PDB_WORKSTATIONS)) {
1286 make_a_mod(mods, ldap_op, "userWorkstations", pdb_get_workstations(sampass));
1289 * Only updates fields which have been set (not defaults from smb.conf)
1292 if (need_ldap_mod(pdb_add, sampass, PDB_SMBHOME)) {
1293 make_a_mod(mods, ldap_op, "smbHome", pdb_get_homedir(sampass));
1296 if (need_ldap_mod(pdb_add, sampass, PDB_DRIVE)) {
1297 make_a_mod(mods, ldap_op, "homeDrive", pdb_get_dir_drive(sampass));
1300 if (need_ldap_mod(pdb_add, sampass, PDB_LOGONSCRIPT)) {
1301 make_a_mod(mods, ldap_op, "scriptPath", pdb_get_logon_script(sampass));
1304 if (need_ldap_mod(pdb_add, sampass, PDB_PROFILE))
1305 make_a_mod(mods, ldap_op, "profilePath", pdb_get_profile_path(sampass));
1307 if (need_ldap_mod(pdb_add, sampass, PDB_LOGONTIME)) {
1308 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1309 make_a_mod(mods, ldap_op, "logonTime", temp);
1312 if (need_ldap_mod(pdb_add, sampass, PDB_LOGOFFTIME)) {
1313 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1314 make_a_mod(mods, ldap_op, "logoffTime", temp);
1317 if (need_ldap_mod(pdb_add, sampass, PDB_KICKOFFTIME)) {
1318 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
1319 make_a_mod(mods, ldap_op, "kickoffTime", temp);
1323 if (need_ldap_mod(pdb_add, sampass, PDB_CANCHANGETIME)) {
1324 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
1325 make_a_mod(mods, ldap_op, "pwdCanChange", temp);
1328 if (need_ldap_mod(pdb_add, sampass, PDB_MUSTCHANGETIME)) {
1329 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
1330 make_a_mod(mods, ldap_op, "pwdMustChange", temp);
1333 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
1334 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1336 if (need_ldap_mod(pdb_add, sampass, PDB_LMPASSWD)) {
1337 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
1338 make_a_mod (mods, ldap_op, "lmPassword", temp);
1341 if (need_ldap_mod(pdb_add, sampass, PDB_NTPASSWD)) {
1342 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
1343 make_a_mod (mods, ldap_op, "ntPassword", temp);
1346 if (need_ldap_mod(pdb_add, sampass, PDB_PASSLASTSET)) {
1347 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
1348 make_a_mod(mods, ldap_op, "pwdLastSet", temp);
1352 /* FIXME: Hours stuff goes in LDAP */
1353 if (need_ldap_mod(pdb_add, sampass, PDB_ACCTCTRL)) {
1354 make_a_mod (mods, ldap_op, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
1355 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1358 return True;
1362 /**********************************************************************
1363 Connect to LDAP server and find the next available RID.
1364 *********************************************************************/
1365 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid)
1367 LDAPMessage *result;
1368 uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
1369 if (top_rid == 0) {
1370 return 0;
1373 if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
1374 return 0;
1377 if (ldapsam_search_one_user_by_rid(ldap_state, final_rid, &result) != LDAP_SUCCESS) {
1378 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
1379 return 0;
1382 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
1383 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
1384 ldap_msgfree(result);
1385 return 0;
1388 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
1389 ldap_msgfree(result);
1390 return final_rid;
1393 /**********************************************************************
1394 Extract the RID from an LDAP entry
1395 *********************************************************************/
1396 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry) {
1397 uint32 rid;
1398 SAM_ACCOUNT *user = NULL;
1399 if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
1400 return 0;
1403 if (init_sam_from_ldap(ldap_state, user, entry)) {
1404 rid = pdb_get_user_rid(user);
1405 } else {
1406 rid =0;
1408 pdb_free_sam(&user);
1409 if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
1410 return rid;
1412 return 0;
1416 /**********************************************************************
1417 Connect to LDAP server and find the next available RID.
1418 *********************************************************************/
1419 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state)
1421 int rc;
1422 pstring filter;
1423 LDAPMessage *result;
1424 LDAPMessage *entry;
1425 char *final_filter = NULL;
1426 uint32 top_rid = 0;
1427 uint32 count;
1428 uint32 rid;
1430 pstrcpy(filter, lp_ldap_filter());
1431 all_string_sub(filter, "%u", "*", sizeof(pstring));
1433 #if 0
1434 asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1435 #else
1436 final_filter = strdup(filter);
1437 #endif
1438 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1440 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1441 LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1442 &result);
1444 if (rc != LDAP_SUCCESS) {
1445 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1446 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1448 free(final_filter);
1449 result = NULL;
1450 return 0;
1453 count = ldap_count_entries(ldap_state->ldap_struct, result);
1454 DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1456 if (count == 0) {
1457 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1458 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1459 free(final_filter);
1460 ldap_msgfree(result);
1461 result = NULL;
1462 return ldap_state->low_nua_rid;
1465 free(final_filter);
1466 entry = ldap_first_entry(ldap_state->ldap_struct,result);
1468 top_rid = entry_to_user_rid(ldap_state, entry);
1470 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1472 rid = entry_to_user_rid(ldap_state, entry);
1473 if (rid > top_rid) {
1474 top_rid = rid;
1478 ldap_msgfree(result);
1480 if (top_rid < ldap_state->low_nua_rid)
1481 top_rid = ldap_state->low_nua_rid;
1483 return top_rid;
1486 /**********************************************************************
1487 Connect to LDAP server and find the next available RID.
1488 *********************************************************************/
1489 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1490 uint32 next_nua_rid;
1491 uint32 top_nua_rid;
1493 top_nua_rid = search_top_nua_rid(ldap_state);
1495 next_nua_rid = check_nua_rid_is_avail(ldap_state,
1496 top_nua_rid);
1498 return next_nua_rid;
1501 /**********************************************************************
1502 Connect to LDAP server for password enumeration
1503 *********************************************************************/
1504 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1506 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1507 int rc;
1508 pstring filter;
1510 pstrcpy(filter, lp_ldap_filter());
1511 all_string_sub(filter, "%u", "*", sizeof(pstring));
1513 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1514 LDAP_SCOPE_SUBTREE, filter, attr, 0,
1515 &ldap_state->result);
1517 if (rc != LDAP_SUCCESS) {
1518 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1519 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1520 ldap_msgfree(ldap_state->result);
1521 ldap_state->result = NULL;
1522 return NT_STATUS_UNSUCCESSFUL;
1525 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1526 ldap_count_entries(ldap_state->ldap_struct,
1527 ldap_state->result)));
1529 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1530 ldap_state->result);
1531 ldap_state->index = 0;
1533 return NT_STATUS_OK;
1536 /**********************************************************************
1537 End enumeration of the LDAP password list
1538 *********************************************************************/
1539 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1541 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1542 if (ldap_state->result) {
1543 ldap_msgfree(ldap_state->result);
1544 ldap_state->result = NULL;
1548 /**********************************************************************
1549 Get the next entry in the LDAP password database
1550 *********************************************************************/
1551 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1553 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1554 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1555 BOOL bret = False;
1557 /* The rebind proc needs this *HACK*. We are not multithreaded, so
1558 this will work, but it's not nice. */
1559 static_ldap_state = ldap_state;
1561 while (!bret) {
1562 if (!ldap_state->entry)
1563 return ret;
1565 ldap_state->index++;
1566 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1568 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1569 ldap_state->entry);
1572 return NT_STATUS_OK;
1575 /**********************************************************************
1576 Get SAM_ACCOUNT entry from LDAP by username
1577 *********************************************************************/
1578 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1580 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1581 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1582 LDAPMessage *result;
1583 LDAPMessage *entry;
1584 int count;
1586 if (ldapsam_search_one_user_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
1587 return NT_STATUS_NO_SUCH_USER;
1590 count = ldap_count_entries(ldap_state->ldap_struct, result);
1592 if (count < 1) {
1593 DEBUG(4,
1594 ("We don't find this user [%s] count=%d\n", sname,
1595 count));
1596 return NT_STATUS_NO_SUCH_USER;
1597 } else if (count > 1) {
1598 DEBUG(1,
1599 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
1600 count));
1601 return NT_STATUS_NO_SUCH_USER;
1604 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1605 if (entry) {
1606 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1607 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1608 ldap_msgfree(result);
1609 return NT_STATUS_NO_SUCH_USER;
1611 ldap_msgfree(result);
1612 ret = NT_STATUS_OK;
1613 } else {
1614 ldap_msgfree(result);
1616 return ret;
1619 /**********************************************************************
1620 Get SAM_ACCOUNT entry from LDAP by rid
1621 *********************************************************************/
1622 static NTSTATUS ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
1624 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1625 struct ldapsam_privates *ldap_state =
1626 (struct ldapsam_privates *)my_methods->private_data;
1627 LDAPMessage *result;
1628 LDAPMessage *entry;
1629 int count;
1631 if (ldapsam_search_one_user_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
1632 return NT_STATUS_NO_SUCH_USER;
1635 count = ldap_count_entries(ldap_state->ldap_struct, result);
1637 if (count < 1) {
1638 DEBUG(4,
1639 ("We don't find this rid [%i] count=%d\n", rid,
1640 count));
1641 return NT_STATUS_NO_SUCH_USER;
1642 } else if (count > 1) {
1643 DEBUG(1,
1644 ("More than one user with rid [%i]. Failing. count=%d\n", rid,
1645 count));
1646 return NT_STATUS_NO_SUCH_USER;
1649 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1650 if (entry) {
1651 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1652 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1653 ldap_msgfree(result);
1654 return NT_STATUS_NO_SUCH_USER;
1656 ldap_msgfree(result);
1657 ret = NT_STATUS_OK;
1658 } else {
1659 ldap_msgfree(result);
1661 return ret;
1664 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1666 uint32 rid;
1667 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
1668 return NT_STATUS_NO_SUCH_USER;
1669 return ldapsam_getsampwrid(my_methods, user, rid);
1672 /********************************************************************
1673 Do the actual modification - also change a plaittext passord if
1674 it it set.
1675 **********************************************************************/
1677 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
1678 SAM_ACCOUNT *newpwd, char *dn,
1679 LDAPMod **mods, int ldap_op, BOOL pdb_add)
1681 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1682 int rc;
1684 if (!my_methods || !newpwd || !dn) {
1685 return NT_STATUS_INVALID_PARAMETER;
1688 if (!mods) {
1689 DEBUG(5,("mods is empty: nothing to modify\n"));
1690 /* may be password change below however */
1691 } else {
1692 switch(ldap_op)
1694 case LDAP_MOD_ADD:
1695 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
1696 rc = ldapsam_add(ldap_state, dn, mods);
1697 break;
1698 case LDAP_MOD_REPLACE:
1699 rc = ldapsam_modify(ldap_state, dn ,mods);
1700 break;
1701 default:
1702 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1703 return NT_STATUS_UNSUCCESSFUL;
1706 if (rc!=LDAP_SUCCESS) {
1707 char *ld_error;
1708 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1709 &ld_error);
1710 DEBUG(1,
1711 ("failed to %s user dn= %s with: %s\n\t%s\n",
1712 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1713 dn, ldap_err2string(rc),
1714 ld_error));
1715 free(ld_error);
1716 return NT_STATUS_UNSUCCESSFUL;
1720 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1721 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))&&
1722 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&
1723 need_ldap_mod(pdb_add, newpwd, PDB_PLAINTEXT_PW)&&
1724 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1725 BerElement *ber;
1726 struct berval *bv;
1727 char *retoid;
1728 struct berval *retdata;
1730 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1731 DEBUG(0,("ber_alloc_t returns NULL\n"));
1732 return NT_STATUS_UNSUCCESSFUL;
1734 ber_printf (ber, "{");
1735 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
1736 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, pdb_get_plaintext_passwd(newpwd));
1737 ber_printf (ber, "N}");
1739 if ((rc = ber_flatten (ber, &bv))<0) {
1740 DEBUG(0,("ber_flatten returns a value <0\n"));
1741 return NT_STATUS_UNSUCCESSFUL;
1744 ber_free(ber,1);
1746 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
1747 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
1748 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1749 pdb_get_username(newpwd),ldap_err2string(rc)));
1750 } else {
1751 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1753 ber_bvfree(retdata);
1754 ber_memfree(retoid);
1756 ber_bvfree(bv);
1758 #else
1759 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
1760 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
1761 return NT_STATUS_OK;
1764 /**********************************************************************
1765 Delete entry from LDAP for username
1766 *********************************************************************/
1767 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1769 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1770 const char *sname;
1771 int rc;
1772 char *dn;
1773 LDAPMessage *entry;
1774 LDAPMessage *result;
1776 if (!sam_acct) {
1777 DEBUG(0, ("sam_acct was NULL!\n"));
1778 return NT_STATUS_INVALID_PARAMETER;
1781 sname = pdb_get_username(sam_acct);
1783 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1785 rc = ldapsam_search_one_user_by_name(ldap_state, sname, &result);
1786 if (rc != LDAP_SUCCESS) {
1787 return NT_STATUS_NO_SUCH_USER;
1790 if (ldap_count_entries (ldap_state->ldap_struct, result) == 0) {
1791 DEBUG (0, ("User doesn't exit!\n"));
1792 ldap_msgfree (result);
1793 return NT_STATUS_NO_SUCH_USER;
1796 entry = ldap_first_entry (ldap_state->ldap_struct, result);
1797 dn = ldap_get_dn (ldap_state->ldap_struct, entry);
1798 ldap_msgfree(result);
1800 rc = ldapsam_delete(ldap_state, dn);
1802 ldap_memfree (dn);
1803 if (rc != LDAP_SUCCESS) {
1804 char *ld_error;
1805 ldap_get_option (ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1806 DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n",
1807 sname, ldap_err2string (rc), ld_error));
1808 free (ld_error);
1809 return NT_STATUS_CANNOT_DELETE;
1812 DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname));
1813 return NT_STATUS_OK;
1816 /**********************************************************************
1817 Update SAM_ACCOUNT
1818 *********************************************************************/
1819 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1821 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1822 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1823 int rc;
1824 char *dn;
1825 LDAPMessage *result;
1826 LDAPMessage *entry;
1827 LDAPMod **mods;
1829 if (!init_ldap_from_sam(ldap_state, &mods, LDAP_MOD_REPLACE, False, newpwd)) {
1830 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1831 return NT_STATUS_UNSUCCESSFUL;
1834 if (mods == NULL) {
1835 DEBUG(4,("mods is empty: nothing to update for user: %s\n",pdb_get_username(newpwd)));
1836 return NT_STATUS_OK;
1839 rc = ldapsam_search_one_user_by_name(ldap_state, pdb_get_username(newpwd), &result);
1840 if (rc != LDAP_SUCCESS) {
1841 ldap_mods_free(mods, 1);
1842 return NT_STATUS_UNSUCCESSFUL;
1845 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
1846 DEBUG(0, ("No user to modify!\n"));
1847 ldap_msgfree(result);
1848 ldap_mods_free(mods, 1);
1849 return NT_STATUS_UNSUCCESSFUL;
1852 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1853 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
1854 ldap_msgfree(result);
1856 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, False);
1857 if (NT_STATUS_IS_ERR(ret)) {
1858 DEBUG(0,("failed to modify user with uid = %s\n",
1859 pdb_get_username(newpwd)));
1860 ldap_mods_free(mods,1);
1861 return ret;
1865 DEBUG(2,
1866 ("successfully modified uid = %s in the LDAP database\n",
1867 pdb_get_username(newpwd)));
1868 ldap_mods_free(mods, 1);
1869 return NT_STATUS_OK;
1872 /**********************************************************************
1873 Add SAM_ACCOUNT to LDAP
1874 *********************************************************************/
1875 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1877 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1878 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1879 int rc;
1880 pstring filter;
1881 LDAPMessage *result = NULL;
1882 pstring dn;
1883 LDAPMod **mods = NULL;
1884 int ldap_op;
1885 uint32 num_result;
1887 const char *username = pdb_get_username(newpwd);
1888 if (!username || !*username) {
1889 DEBUG(0, ("Cannot add user without a username!\n"));
1890 return NT_STATUS_INVALID_PARAMETER;
1893 rc = ldapsam_search_one_user_by_name (ldap_state, username, &result);
1894 if (rc != LDAP_SUCCESS) {
1895 return NT_STATUS_UNSUCCESSFUL;
1898 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
1899 DEBUG(0,("User '%s' already in the base, with samba properties\n",
1900 username));
1901 ldap_msgfree(result);
1902 return NT_STATUS_UNSUCCESSFUL;
1904 ldap_msgfree(result);
1906 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
1907 rc = ldapsam_search_one_user(ldap_state, filter, &result);
1908 if (rc != LDAP_SUCCESS) {
1909 return NT_STATUS_UNSUCCESSFUL;
1912 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
1914 if (num_result > 1) {
1915 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1916 ldap_msgfree(result);
1917 return NT_STATUS_UNSUCCESSFUL;
1920 /* Check if we need to update an existing entry */
1921 if (num_result == 1) {
1922 char *tmp;
1923 LDAPMessage *entry;
1925 DEBUG(3,("User exists without samba properties: adding them\n"));
1926 ldap_op = LDAP_MOD_REPLACE;
1927 entry = ldap_first_entry (ldap_state->ldap_struct, result);
1928 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
1929 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1930 ldap_memfree (tmp);
1931 } else {
1932 /* Check if we need to add an entry */
1933 DEBUG(3,("Adding new user\n"));
1934 ldap_op = LDAP_MOD_ADD;
1935 if (username[strlen(username)-1] == '$') {
1936 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1937 } else {
1938 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1942 ldap_msgfree(result);
1944 if (!init_ldap_from_sam(ldap_state, &mods, ldap_op, True, newpwd)) {
1945 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1946 ldap_mods_free(mods, 1);
1947 return NT_STATUS_UNSUCCESSFUL;
1950 if (mods == NULL) {
1951 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
1952 return NT_STATUS_UNSUCCESSFUL;
1955 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
1957 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, True);
1958 if (NT_STATUS_IS_ERR(ret)) {
1959 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
1960 pdb_get_username(newpwd),dn));
1961 ldap_mods_free(mods,1);
1962 return ret;
1965 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
1966 ldap_mods_free(mods, 1);
1967 return NT_STATUS_OK;
1970 static void free_private_data(void **vp)
1972 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
1974 ldapsam_close(*ldap_state);
1976 if ((*ldap_state)->bind_secret) {
1977 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1980 ldapsam_close(*ldap_state);
1982 SAFE_FREE((*ldap_state)->bind_dn);
1983 SAFE_FREE((*ldap_state)->bind_secret);
1985 *ldap_state = NULL;
1987 /* No need to free any further, as it is talloc()ed */
1990 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1992 NTSTATUS nt_status;
1993 struct ldapsam_privates *ldap_state;
1995 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
1996 return nt_status;
1999 (*pdb_method)->name = "ldapsam";
2001 (*pdb_method)->setsampwent = ldapsam_setsampwent;
2002 (*pdb_method)->endsampwent = ldapsam_endsampwent;
2003 (*pdb_method)->getsampwent = ldapsam_getsampwent;
2004 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2005 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2006 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2007 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2008 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2010 /* TODO: Setup private data and free */
2012 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
2014 if (!ldap_state) {
2015 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2016 return NT_STATUS_NO_MEMORY;
2019 if (location) {
2020 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
2021 #ifdef WITH_LDAP_SAMCONFIG
2022 } else {
2023 int ldap_port = lp_ldap_port();
2025 /* remap default port if not using SSL (ie clear or TLS) */
2026 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2027 ldap_port = 389;
2030 ldap_state->uri = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
2031 if (!ldap_state->uri) {
2032 return NT_STATUS_NO_MEMORY;
2034 #else
2035 } else {
2036 ldap_state->uri = "ldap://localhost";
2037 #endif
2040 (*pdb_method)->private_data = ldap_state;
2042 (*pdb_method)->free_private_data = free_private_data;
2044 return NT_STATUS_OK;
2047 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2049 NTSTATUS nt_status;
2050 struct ldapsam_privates *ldap_state;
2051 uint32 low_nua_uid, high_nua_uid;
2053 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
2054 return nt_status;
2057 (*pdb_method)->name = "ldapsam_nua";
2059 ldap_state = (*pdb_method)->private_data;
2061 ldap_state->permit_non_unix_accounts = True;
2063 if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
2064 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
2065 return NT_STATUS_UNSUCCESSFUL;
2068 ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
2070 ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
2072 return NT_STATUS_OK;
2076 #else
2078 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2080 DEBUG(0, ("ldap not detected at configure time, ldapsam not availalble!\n"));
2081 return NT_STATUS_UNSUCCESSFUL;
2084 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2086 DEBUG(0, ("ldap not dectected at configure time, ldapsam_nua not available!\n"));
2087 return NT_STATUS_UNSUCCESSFUL;
2091 #endif