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.
29 #define DBGC_CLASS DBGC_PASSDB
32 * persistent connections: if using NSS LDAP, many connections are made
33 * however, using only one within Samba would be nice
35 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
37 * Other LDAP based login attributes: accountExpires, etc.
38 * (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
39 * structures don't have fields for some of these attributes)
41 * SSL is done, but can't get the certificate based authentication to work
42 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
45 /* NOTE: this will NOT work against an Active Directory server
46 * due to the fact that the two password fields cannot be retrieved
47 * from a server; recommend using security = domain in this situation
54 #ifndef LDAP_OPT_SUCCESS
55 #define LDAP_OPT_SUCCESS 0
59 #define SAM_ACCOUNT struct sam_passwd
62 struct ldapsam_privates {
70 /* retrive-once info */
72 const char *domain_name;
75 /* configuration items */
78 BOOL permit_non_unix_accounts;
80 uint32 low_allocated_user_rid;
81 uint32 high_allocated_user_rid;
83 uint32 low_allocated_group_rid;
84 uint32 high_allocated_group_rid;
89 unsigned int num_failures;
92 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
94 static struct ldapsam_privates *static_ldap_state;
96 /*******************************************************************
97 find the ldap password
98 ******************************************************************/
99 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
104 *dn = smb_xstrdup(lp_ldap_admin_dn());
106 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
108 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
111 *pw=secrets_fetch(key, &size);
115 /* Upgrade 2.2 style entry */
117 char* old_style_key = strdup(*dn);
119 fstring old_style_pw;
121 if (!old_style_key) {
122 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
126 for (p=old_style_key; *p; p++)
127 if (*p == ',') *p = '/';
129 data=secrets_fetch(old_style_key, &size);
130 if (!size && size < sizeof(old_style_pw)) {
131 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
132 SAFE_FREE(old_style_key);
137 strncpy(old_style_pw, data, size);
138 old_style_pw[size] = 0;
142 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
143 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
144 SAFE_FREE(old_style_key);
148 if (!secrets_delete(old_style_key)) {
149 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
152 SAFE_FREE(old_style_key);
154 *pw = smb_xstrdup(old_style_pw);
160 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
161 "logoffTime", "kickoffTime", "cn",
162 "pwdCanChange", "pwdMustChange",
163 "displayName", "homeDrive",
164 "smbHome", "scriptPath",
165 "profilePath", "description",
166 "userWorkstations", "rid", "ntSid",
167 "primaryGroupID", "lmPassword",
168 "ntPassword", "acctFlags",
169 "domain", "objectClass",
170 "uidNumber", "gidNumber",
171 "homeDirectory", NULL };
173 static const char *domain_info_attrs[] = {"domain", "nextUserRid",
174 "nextGroupRid", "ntSid", NULL };
176 /*******************************************************************
177 open a connection to the ldap server.
178 ******************************************************************/
179 static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
181 int rc = LDAP_SUCCESS;
183 BOOL ldap_v3 = False;
185 #ifdef HAVE_LDAP_INITIALIZE
186 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
188 if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
189 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
195 /* Parse the string manually */
201 const char *p = ldap_state->uri;
202 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
204 /* skip leading "URL:" (if any) */
205 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
209 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
212 if (strequal(protocol, "ldap")) {
214 } else if (strequal(protocol, "ldaps")) {
217 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
221 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
222 DEBUG(0, ("ldap_init failed !\n"));
223 return LDAP_OPERATIONS_ERROR;
226 if (strequal(protocol, "ldaps")) {
227 #ifdef LDAP_OPT_X_TLS
228 int tls = LDAP_OPT_X_TLS_HARD;
229 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
231 DEBUG(0, ("Failed to setup a TLS session\n"));
234 DEBUG(3,("LDAPS option set...!\n"));
236 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
237 return LDAP_OPERATIONS_ERROR;
243 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
245 if (version != LDAP_VERSION3)
247 version = LDAP_VERSION3;
248 if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
256 if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
257 #ifdef LDAP_OPT_X_TLS
259 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
261 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
262 ldap_err2string(rc)));
265 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
268 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
269 return LDAP_OPERATIONS_ERROR;
272 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
273 return LDAP_OPERATIONS_ERROR;
277 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
282 /*******************************************************************
283 a rebind function for authenticated referrals
284 This version takes a void* that we can shove useful stuff in :-)
285 ******************************************************************/
286 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
288 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
289 int *methodp, int freeit, void *arg)
291 struct ldapsam_privates *ldap_state = arg;
293 /** @TODO Should we be doing something to check what servers we rebind to?
294 Could we get a referral to a machine that we don't want to give our
295 username and password to? */
299 memset(*credp, '\0', strlen(*credp));
302 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
303 ldap_state->bind_dn));
305 *whop = strdup(ldap_state->bind_dn);
307 return LDAP_NO_MEMORY;
309 *credp = strdup(ldap_state->bind_secret);
312 return LDAP_NO_MEMORY;
314 *methodp = LDAP_AUTH_SIMPLE;
318 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
320 /*******************************************************************
321 a rebind function for authenticated referrals
322 This version takes a void* that we can shove useful stuff in :-)
323 and actually does the connection.
324 ******************************************************************/
325 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
326 static int rebindproc_connect_with_state (LDAP *ldap_struct,
327 LDAP_CONST char *url,
329 ber_int_t msgid, void *arg)
331 struct ldapsam_privates *ldap_state = arg;
333 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
334 ldap_state->bind_dn));
336 /** @TODO Should we be doing something to check what servers we rebind to?
337 Could we get a referral to a machine that we don't want to give our
338 username and password to? */
340 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
344 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
346 /*******************************************************************
347 Add a rebind function for authenticated referrals
348 ******************************************************************/
349 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
351 # if LDAP_SET_REBIND_PROC_ARGS == 2
352 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
353 int *method, int freeit )
355 return rebindproc_with_state(ldap_struct, whop, credp,
356 method, freeit, 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 a rebind function for authenticated referrals
364 this also does the connection, but no void*.
365 ******************************************************************/
366 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
367 # if LDAP_SET_REBIND_PROC_ARGS == 2
368 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
371 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
374 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
375 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
377 /*******************************************************************
378 connect to the ldap server under system privilege.
379 ******************************************************************/
380 static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
386 /* The rebind proc needs this *HACK*. We are not multithreaded, so
387 this will work, but it's not nice. */
388 static_ldap_state = ldap_state;
390 /* get the password */
391 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
393 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
394 return LDAP_INVALID_CREDENTIALS;
397 ldap_state->bind_dn = ldap_dn;
398 ldap_state->bind_secret = ldap_secret;
400 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
401 (OpenLDAP) doesnt' seem to support it */
403 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
404 ldap_state->uri, ldap_dn));
406 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
407 # if LDAP_SET_REBIND_PROC_ARGS == 2
408 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
410 # if LDAP_SET_REBIND_PROC_ARGS == 3
411 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
413 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
414 # if LDAP_SET_REBIND_PROC_ARGS == 2
415 ldap_set_rebind_proc(ldap_struct, &rebindproc);
417 # if LDAP_SET_REBIND_PROC_ARGS == 3
418 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
420 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
422 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
424 if (rc != LDAP_SUCCESS) {
425 char *ld_error = NULL;
426 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
428 DEBUG(ldap_state->num_failures ? 2 : 0,
429 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
430 ldap_dn ? ld_error : "(unknown)", ldap_err2string(rc),
433 ldap_state->num_failures++;
437 ldap_state->num_failures = 0;
439 DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
443 /**********************************************************************
444 Connect to LDAP server
445 *********************************************************************/
446 static int ldapsam_open(struct ldapsam_privates *ldap_state)
449 SMB_ASSERT(ldap_state);
451 #ifndef NO_LDAP_SECURITY
452 if (geteuid() != 0) {
453 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
454 return LDAP_INSUFFICIENT_ACCESS;
458 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
459 struct sockaddr_un addr;
460 socklen_t len = sizeof(addr);
462 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
463 getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
464 /* the other end has died. reopen. */
465 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
466 ldap_state->ldap_struct = NULL;
467 ldap_state->last_ping = (time_t)0;
469 ldap_state->last_ping = time(NULL);
473 if (ldap_state->ldap_struct != NULL) {
474 DEBUG(5,("ldapsam_open: allready connected to the LDAP server\n"));
478 if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
482 if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
483 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
484 ldap_state->ldap_struct = NULL;
489 ldap_state->last_ping = time(NULL);
490 DEBUG(4,("The LDAP server is succesful connected\n"));
495 /**********************************************************************
496 Disconnect from LDAP server
497 *********************************************************************/
498 static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
501 return NT_STATUS_INVALID_PARAMETER;
503 if (ldap_state->ldap_struct != NULL) {
504 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
505 ldap_state->ldap_struct = NULL;
508 DEBUG(5,("The connection to the LDAP server was closed\n"));
509 /* maybe free the results here --metze */
514 static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
518 SMB_ASSERT(ldap_state && attempts);
520 if (*attempts != 0) {
521 unsigned int sleep_time;
522 uint8 rand_byte = 128; /* a reasonable place to start */
524 generate_random_buffer(&rand_byte, 1, False);
526 sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2;
527 /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
530 DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n",
536 if ((rc = ldapsam_open(ldap_state))) {
537 DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts));
545 static int ldapsam_search(struct ldapsam_privates *ldap_state,
546 const char *base, int scope, const char *filter,
547 const char *attrs[], int attrsonly,
550 int rc = LDAP_SERVER_DOWN;
554 SMB_ASSERT(ldap_state);
556 if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) {
557 return LDAP_NO_MEMORY;
560 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
562 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
565 rc = ldap_search_s(ldap_state->ldap_struct, base, scope,
566 utf8_filter, (char **)attrs, attrsonly, res);
569 if (rc == LDAP_SERVER_DOWN) {
570 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
571 ldapsam_close(ldap_state);
574 SAFE_FREE(utf8_filter);
578 static int ldapsam_modify(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
580 int rc = LDAP_SERVER_DOWN;
584 SMB_ASSERT(ldap_state);
586 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
587 return LDAP_NO_MEMORY;
590 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
592 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
595 rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
598 if (rc == LDAP_SERVER_DOWN) {
599 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
600 ldapsam_close(ldap_state);
607 static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
609 int rc = LDAP_SERVER_DOWN;
613 SMB_ASSERT(ldap_state);
615 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
616 return LDAP_NO_MEMORY;
619 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
621 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
624 rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
627 if (rc == LDAP_SERVER_DOWN) {
628 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
629 ldapsam_close(ldap_state);
636 static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
638 int rc = LDAP_SERVER_DOWN;
642 SMB_ASSERT(ldap_state);
644 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
645 return LDAP_NO_MEMORY;
648 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
650 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
653 rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
656 if (rc == LDAP_SERVER_DOWN) {
657 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
658 ldapsam_close(ldap_state);
665 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
666 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)
668 int rc = LDAP_SERVER_DOWN;
674 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
676 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
679 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
682 if (rc == LDAP_SERVER_DOWN) {
683 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
684 ldapsam_close(ldap_state);
691 /*******************************************************************
692 run the search by name.
693 ******************************************************************/
694 static int ldapsam_search_suffix (struct ldapsam_privates *ldap_state, const char *filter, const char **search_attr, LDAPMessage ** result)
696 int scope = LDAP_SCOPE_SUBTREE;
699 DEBUG(2, ("ldapsam_search_suffix: searching for:[%s]\n", filter));
701 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, filter, search_attr, 0, result);
703 if (rc != LDAP_SUCCESS) {
704 char *ld_error = NULL;
705 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
707 DEBUG(0,("ldapsam_search_suffix: Problem during the LDAP search: %s (%s)\n",
708 ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
709 DEBUG(3,("ldapsam_search_suffix: Query was: %s, %s\n", lp_ldap_suffix(),
717 /*******************************************************************
718 run the search by name.
719 ******************************************************************/
720 static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, const char *user,
721 LDAPMessage ** result)
724 char *escape_user = escape_ldap_string_alloc(user);
727 return LDAP_NO_MEMORY;
731 * in the filter expression, replace %u with the real name
732 * so in ldap filter, %u MUST exist :-)
734 pstrcpy(filter, lp_ldap_filter());
737 * have to use this here because $ is filtered out
742 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
743 SAFE_FREE(escape_user);
745 return ldapsam_search_suffix(ldap_state, filter, attr, result);
748 /*******************************************************************
749 run the search by rid.
750 ******************************************************************/
751 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
753 LDAPMessage ** result)
758 /* check if the user rid exsists, if not, try searching on the uid */
760 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
761 rc = ldapsam_search_suffix(ldap_state, filter, attr, result);
766 /*******************************************************************
767 run the search by SID.
768 ******************************************************************/
769 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
771 LDAPMessage ** result)
777 /* check if the user rid exsists, if not, try searching on the uid */
779 snprintf(filter, sizeof(filter) - 1, "ntSid=%s", sid_to_string(sid_string, sid));
780 rc = ldapsam_search_suffix(ldap_state, filter, attr, result);
785 /*******************************************************************
786 search an attribute and return the first value found.
787 ******************************************************************/
788 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
789 const char *attribute, pstring value)
794 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
795 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
800 if (convert_string(CH_UTF8, CH_UNIX,
802 value, sizeof(pstring)) == (size_t)-1)
804 DEBUG(1, ("get_single_attribute: string conversion of [%s] = [%s] failed!\n",
805 attribute, values[0]));
806 ldap_value_free(values);
810 ldap_value_free(values);
811 #ifdef DEBUG_PASSWORDS
812 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
817 /************************************************************************
818 Routine to manage the LDAPMod structure array
819 manage memory used by the array, by each struct, and values
821 ************************************************************************/
822 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
830 if (attribute == NULL || *attribute == '\0')
834 /* Why do we need this??? -- vl */
835 if (value == NULL || *value == '\0')
841 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
844 DEBUG(0, ("make_a_mod: out of memory!\n"));
850 for (i = 0; mods[i] != NULL; ++i) {
851 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
857 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
860 DEBUG(0, ("make_a_mod: out of memory!\n"));
863 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
866 DEBUG(0, ("make_a_mod: out of memory!\n"));
869 mods[i]->mod_op = modop;
870 mods[i]->mod_values = NULL;
871 mods[i]->mod_type = strdup(attribute);
877 char *utf8_value = NULL;
880 if (mods[i]->mod_values != NULL) {
881 for (; mods[i]->mod_values[j] != NULL; j++);
883 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
884 (j + 2) * sizeof (char *));
886 if (mods[i]->mod_values == NULL) {
887 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
891 if (push_utf8_allocate(&utf8_value, value) == (size_t)-1) {
892 DEBUG (0, ("make_a_mod: String conversion failure!\n"));
896 mods[i]->mod_values[j] = utf8_value;
898 mods[i]->mod_values[j + 1] = NULL;
903 /**********************************************************************
904 Set attribute to newval in LDAP, regardless of what value the
905 attribute had in LDAP before.
906 *********************************************************************/
907 static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
909 const char *attribute, const char *newval)
911 char **values = NULL;
913 if (existing != NULL) {
914 values = ldap_get_values(ldap_struct, existing, attribute);
917 if ((values != NULL) && (values[0] != NULL) &&
918 strcmp(values[0], newval) == 0) {
920 /* Believe it or not, but LDAP will deny a delete and
921 an add at the same time if the values are the
924 ldap_value_free(values);
928 /* Regardless of the real operation (add or modify)
929 we add the new value here. We rely on deleting
930 the old value, should it exist. */
932 if ((newval != NULL) && (strlen(newval) > 0)) {
933 make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
936 if (values == NULL) {
937 /* There has been no value before, so don't delete it.
938 Here's a possible race: We might end up with
939 duplicate attributes */
943 /* By deleting exactly the value we found in the entry this
944 should be race-free in the sense that the LDAP-Server will
945 deny the complete operation if somebody changed the
946 attribute behind our back. */
948 make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
949 ldap_value_free(values);
952 /*******************************************************************
953 Delete complete object or objectclass and attrs from
954 object found in search_result depending on lp_ldap_delete_dn
955 ******************************************************************/
956 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
958 const char *objectclass,
963 LDAPMod **mods = NULL;
965 BerElement *ptr = NULL;
967 rc = ldap_count_entries(ldap_state->ldap_struct, result);
970 DEBUG(0, ("Entry must exist exactly once!\n"));
971 return NT_STATUS_UNSUCCESSFUL;
974 entry = ldap_first_entry(ldap_state->ldap_struct, result);
975 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
977 if (lp_ldap_delete_dn()) {
978 NTSTATUS ret = NT_STATUS_OK;
979 rc = ldapsam_delete(ldap_state, dn);
981 if (rc != LDAP_SUCCESS) {
982 DEBUG(0, ("Could not delete object %s\n", dn));
983 ret = NT_STATUS_UNSUCCESSFUL;
989 /* Ok, delete only the SAM attributes */
991 for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
993 name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) {
997 /* We are only allowed to delete the attributes that
1000 for (attrib = attrs; *attrib != NULL; attrib++) {
1001 if (StrCaseCmp(*attrib, name) == 0) {
1002 DEBUG(10, ("deleting attribute %s\n", name));
1003 make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
1014 make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
1016 rc = ldapsam_modify(ldap_state, dn, mods);
1017 ldap_mods_free(mods, 1);
1019 if (rc != LDAP_SUCCESS) {
1020 char *ld_error = NULL;
1021 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1024 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
1025 dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
1026 SAFE_FREE(ld_error);
1028 return NT_STATUS_UNSUCCESSFUL;
1032 return NT_STATUS_OK;
1035 /**********************************************************************
1036 Search for the domain info entry
1037 *********************************************************************/
1038 static int ldapsam_search_domain_info(struct ldapsam_privates *ldap_state,
1039 LDAPMessage ** result)
1044 slprintf(filter, sizeof(filter)-1,
1045 "(&(objectClass=sambaDomain)(domain=%s))",
1046 ldap_state->domain_name);
1048 DEBUG(2, ("Searching for:[%s]\n", filter));
1050 rc = ldapsam_search_suffix(ldap_state, filter,
1051 domain_info_attrs, result);
1053 if (rc != LDAP_SUCCESS) {
1054 DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
1055 DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1061 /**********************************************************************
1062 If this entry is is the 'allocated' range, extract the RID and return
1063 it, so we can find the 'next' rid to allocate.
1065 Do this, no matter what type of object holds the RID - be it a user,
1066 group or somthing else.
1067 *********************************************************************/
1068 static uint32 entry_to_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, int rid_type)
1074 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
1079 if (!string_to_sid(&dom_sid, sid_string)) {
1083 if (!sid_peek_check_rid(&dom_sid, get_global_sam_sid(), &rid)) {
1084 /* not our domain, so we don't care */
1090 if (rid >= ldap_state->low_allocated_user_rid &&
1091 rid <= ldap_state->high_allocated_user_rid) {
1095 case GROUP_RID_TYPE:
1096 if (rid >= ldap_state->low_allocated_group_rid &&
1097 rid <= ldap_state->high_allocated_group_rid) {
1106 /**********************************************************************
1107 Connect to LDAP server and find the next available 'allocated' RID.
1109 The search is done 'per type' as we allocate seperate pools for the
1110 EVEN and ODD (user and group) RIDs.
1112 This is only done once, so that we can fill out the sambaDomain.
1113 *********************************************************************/
1114 static uint32 search_next_allocated_rid(struct ldapsam_privates *ldap_state, int rid_type)
1117 LDAPMessage *result;
1123 const char *sid_attr[] = {"ntSid", NULL};
1124 const char *filter = "(ntSid=*)";
1126 DEBUG(2, ("search_top_allocated_rid: searching for:[%s]\n", filter));
1128 rc = ldapsam_search_suffix(ldap_state, filter,
1131 if (rc != LDAP_SUCCESS) {
1132 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1133 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1139 count = ldap_count_entries(ldap_state->ldap_struct, result);
1140 DEBUG(2, ("search_top_allocated_rid: %d entries in the base!\n", count));
1143 DEBUG(3, ("LDAP search returned no records, assuming no allocated RIDs present!: %s\n", ldap_err2string(rc)));
1144 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1146 entry = ldap_first_entry(ldap_state->ldap_struct,result);
1148 top_rid = entry_to_rid(ldap_state, entry, rid_type);
1150 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1152 rid = entry_to_rid(ldap_state, entry, rid_type);
1153 if (((rid & ~RID_TYPE_MASK) == rid_type) && (rid > top_rid)) {
1161 if (top_rid < ldap_state->low_allocated_user_rid) {
1162 return ldap_state->low_allocated_user_rid;
1165 case GROUP_RID_TYPE:
1166 if (top_rid < ldap_state->low_allocated_group_rid)
1167 return ldap_state->low_allocated_group_rid;
1171 next_rid = (top_rid & ~RID_TYPE_MASK) + rid_type + RID_MULTIPLIER;
1175 if (next_rid > ldap_state->high_allocated_user_rid) {
1179 case GROUP_RID_TYPE:
1180 if (next_rid > ldap_state->high_allocated_group_rid) {
1188 /**********************************************************************
1189 Add the sambaDomain to LDAP, so we don't have to search for this stuff
1190 again. This is a once-add operation for now.
1192 TODO: Add other attributes, and allow modification.
1193 *********************************************************************/
1194 static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state)
1198 LDAPMod **mods = NULL;
1201 LDAPMessage *result = NULL;
1202 LDAPMessage *entry = NULL;
1206 uint32 next_allocated_user_rid;
1207 uint32 next_allocated_group_rid;
1209 next_allocated_user_rid = search_next_allocated_rid(ldap_state, USER_RID_TYPE);
1210 if (!next_allocated_user_rid) {
1211 return NT_STATUS_UNSUCCESSFUL;
1214 next_allocated_group_rid = search_next_allocated_rid(ldap_state, GROUP_RID_TYPE);
1215 if (!next_allocated_group_rid) {
1216 return NT_STATUS_UNSUCCESSFUL;
1219 slprintf (filter, sizeof (filter) - 1, "domain=%s", ldap_state->domain_name);
1220 rc = ldapsam_search_suffix(ldap_state, filter, domain_info_attrs, &result);
1221 if (rc != LDAP_SUCCESS) {
1222 return NT_STATUS_UNSUCCESSFUL;
1225 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
1227 if (num_result > 1) {
1228 DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
1229 ldap_msgfree(result);
1230 return NT_STATUS_UNSUCCESSFUL;
1233 /* Check if we need to update an existing entry */
1234 if (num_result == 1) {
1237 DEBUG(3,("Domain exists without samba properties: adding them\n"));
1238 ldap_op = LDAP_MOD_REPLACE;
1239 entry = ldap_first_entry (ldap_state->ldap_struct, result);
1240 tmp_dn = ldap_get_dn (ldap_state->ldap_struct, entry);
1241 asprintf (&dn, "%s", tmp_dn);
1242 ldap_memfree (tmp_dn);
1244 /* Check if we need to add an entry */
1245 DEBUG(3,("Adding new domain\n"));
1246 ldap_op = LDAP_MOD_ADD;
1247 asprintf (&dn, "domain=%s,%s", ldap_state->domain_name, lp_ldap_suffix ());
1250 /* Free original search */
1251 ldap_msgfree(result);
1254 return NT_STATUS_NO_MEMORY;
1257 /* make the changes - the entry *must* not already have samba attributes */
1258 make_a_mod(&mods, LDAP_MOD_ADD, "domain", ldap_state->domain_name);
1260 sid_to_string(tmp, &ldap_state->domain_sid);
1261 make_a_mod(&mods, LDAP_MOD_ADD, "ntSid", tmp);
1263 snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_user_rid);
1264 make_a_mod(&mods, LDAP_MOD_ADD, "nextUserRid", tmp);
1266 snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_group_rid);
1267 make_a_mod(&mods, LDAP_MOD_ADD, "nextGroupRid", tmp);
1269 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaDomain");
1274 rc = ldapsam_add(ldap_state, dn, mods);
1276 case LDAP_MOD_REPLACE:
1277 rc = ldapsam_modify(ldap_state, dn, mods);
1280 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1281 return NT_STATUS_INVALID_PARAMETER;
1284 if (rc!=LDAP_SUCCESS) {
1285 char *ld_error = NULL;
1286 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1289 ("failed to %s domain dn= %s with: %s\n\t%s\n",
1290 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1291 dn, ldap_err2string(rc),
1292 ld_error?ld_error:"unknown"));
1293 SAFE_FREE(ld_error);
1295 ldap_mods_free(mods,1);
1296 return NT_STATUS_UNSUCCESSFUL;
1299 DEBUG(2,("added: domain = %s in the LDAP database\n", ldap_state->domain_name));
1300 ldap_mods_free(mods, 1);
1301 return NT_STATUS_OK;
1304 /**********************************************************************
1305 Even if the sambaAccount attribute in LDAP tells us that this RID is
1306 safe to use, always check before use.
1307 *********************************************************************/
1308 static BOOL sid_in_use(struct ldapsam_privates *ldap_state,
1309 const DOM_SID *sid, int *error)
1313 LDAPMessage *result = NULL;
1316 const char *sid_attr[] = {"ntSid", NULL};
1318 slprintf(filter, sizeof(filter)-1, "(ntSid=%s)", sid_to_string(sid_string, sid));
1320 rc = ldapsam_search_suffix(ldap_state, filter, sid_attr, &result);
1322 if (rc != LDAP_SUCCESS) {
1323 char *ld_error = NULL;
1324 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1325 DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
1326 sid_string, ld_error));
1327 SAFE_FREE(ld_error);
1333 if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 0) {
1334 DEBUG(3, ("Sid %s already in use - trying next RID\n",
1336 ldap_msgfree(result);
1340 ldap_msgfree(result);
1342 /* good, sid is not in use */
1346 /**********************************************************************
1347 Set the new nextRid attribute, and return one we can use.
1349 This also checks that this RID is actually free - in case the admin
1350 manually stole it :-).
1351 *********************************************************************/
1352 static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *rid, int rid_type)
1354 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1356 LDAPMessage *result = NULL;
1357 LDAPMessage *entry = NULL;
1359 LDAPMod **mods = NULL;
1361 fstring old_rid_string;
1362 fstring next_rid_string;
1366 if (!ldap_state->use_ntsid) {
1367 DEBUG(0, ("Allocated RIDs require 'ldap use ntSid' to be set in smb.conf\n"));
1368 return NT_STATUS_UNSUCCESSFUL;
1371 while (attempts < 10) {
1373 if (ldapsam_search_domain_info(ldap_state, &result)) {
1377 if (ldap_count_entries(ldap_state->ldap_struct, result) < 1) {
1378 DEBUG(3, ("Got no domain info entries for domain %s\n",
1379 ldap_state->domain_name));
1380 ldap_msgfree(result);
1381 if (NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) {
1384 DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret)));
1389 if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 1) {
1390 DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
1391 count, ldap_state->domain_name));
1392 ldap_msgfree(result);
1396 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1398 ldap_msgfree(result);
1402 if ((dn = ldap_get_dn(ldap_state->ldap_struct, entry)) == NULL) {
1403 DEBUG(0, ("Could not get domain info DN\n"));
1404 ldap_msgfree(result);
1408 /* yes, we keep 2 seperate counters, to avoid stomping on the two
1409 different sets of algorithmic RIDs */
1413 if (!get_single_attribute(ldap_state->ldap_struct,
1414 entry, "nextUserRid",
1417 ldap_msgfree(result);
1421 case GROUP_RID_TYPE:
1422 if (!get_single_attribute(ldap_state->ldap_struct,
1423 entry, "nextGroupRid",
1426 ldap_msgfree(result);
1432 /* This is the core of the whole routine. If we had
1433 scheme-style closures, there would be a *lot* less code
1435 *rid = (uint32)atol(old_rid_string);
1436 next_rid = *rid+RID_MULTIPLIER;
1438 slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
1442 if (next_rid > ldap_state->high_allocated_user_rid) {
1443 return NT_STATUS_UNSUCCESSFUL;
1446 /* Try to make the modification atomically by enforcing the
1447 old value in the delete mod. */
1448 make_ldap_mod(ldap_state->ldap_struct, entry, &mods, "nextUserRid", next_rid_string);
1451 case GROUP_RID_TYPE:
1452 if (next_rid > ldap_state->high_allocated_group_rid) {
1453 return NT_STATUS_UNSUCCESSFUL;
1456 /* Try to make the modification atomically by enforcing the
1457 old value in the delete mod. */
1458 make_ldap_mod(ldap_state->ldap_struct, entry, &mods, "nextGroupRid", next_rid_string);
1462 if ((rc = ldap_modify_s(ldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) {
1465 pstring domain_sid_string;
1468 if (!get_single_attribute(ldap_state->ldap_struct, result, "ntSid",
1469 domain_sid_string)) {
1470 ldap_mods_free(mods, 1);
1472 ldap_msgfree(result);
1476 if (!string_to_sid(&dom_sid, domain_sid_string)) {
1477 ldap_mods_free(mods, 1);
1479 ldap_msgfree(result);
1483 ldap_mods_free(mods, 1);
1486 ldap_msgfree(result);
1488 sid_copy(&sid, &dom_sid);
1489 sid_append_rid(&sid, *rid);
1491 /* check RID is not in use */
1492 if (sid_in_use(ldap_state, &sid, &error)) {
1499 return NT_STATUS_OK;
1502 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1503 DEBUG(2, ("Failed to modify rid: %s\n", ld_error));
1504 SAFE_FREE(ld_error);
1506 ldap_mods_free(mods, 1);
1512 ldap_msgfree(result);
1516 /* Sleep for a random timeout */
1517 unsigned sleeptime = (sys_random()*sys_getpid()*attempts);
1525 DEBUG(0, ("Failed to set new RID\n"));
1529 /* New Interface is being implemented here */
1531 /**********************************************************************
1532 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
1533 *********************************************************************/
1534 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
1535 SAM_ACCOUNT * sampass,
1536 LDAPMessage * entry)
1545 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
1546 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
1550 for (values=ldap_values;*values;values++) {
1551 if (strcasecmp(*values, "posixAccount") == 0) {
1556 if (!*values) { /*end of array, no posixAccount */
1557 DEBUG(10, ("user does not have posixAcccount attributes\n"));
1558 ldap_value_free(ldap_values);
1561 ldap_value_free(ldap_values);
1563 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir))
1566 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
1569 uid = (uid_t)atol(temp);
1571 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
1574 gid = (gid_t)atol(temp);
1576 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
1577 pdb_set_uid(sampass, uid, PDB_SET);
1578 pdb_set_gid(sampass, gid, PDB_SET);
1580 DEBUG(10, ("user has posixAcccount attributes\n"));
1585 /**********************************************************************
1586 Initialize SAM_ACCOUNT from an LDAP query
1587 (Based on init_sam_from_buffer in pdb_tdb.c)
1588 *********************************************************************/
1589 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
1590 SAM_ACCOUNT * sampass,
1591 LDAPMessage * entry)
1597 pass_can_change_time,
1598 pass_must_change_time;
1612 uint8 smblmpwd[LM_HASH_LEN],
1613 smbntpwd[NT_HASH_LEN];
1614 uint16 acct_ctrl = 0,
1617 uint8 hours[MAX_HOURS_LEN];
1620 gid_t gid = getegid();
1624 * do a little initialization
1628 nt_username[0] = '\0';
1631 dir_drive[0] = '\0';
1632 logon_script[0] = '\0';
1633 profile_path[0] = '\0';
1634 acct_desc[0] = '\0';
1635 munged_dial[0] = '\0';
1636 workstations[0] = '\0';
1639 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1640 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1644 if (ldap_state->ldap_struct == NULL) {
1645 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1649 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uid", username)) {
1650 DEBUG(1, ("No uid attribute found for this user!\n"));
1654 DEBUG(2, ("Entry found for user: %s\n", username));
1656 pstrcpy(nt_username, username);
1658 pstrcpy(domain, ldap_state->domain_name);
1660 pdb_set_username(sampass, username, PDB_SET);
1662 pdb_set_domain(sampass, domain, PDB_DEFAULT);
1663 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1665 if (ldap_state->use_ntsid) {
1666 if (get_single_attribute(ldap_state->ldap_struct, entry, "ntSid", temp)) {
1667 pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
1670 if (get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp)) {
1671 user_rid = (uint32)atol(temp);
1672 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1676 if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
1677 DEBUG(1, ("no rid or ntSid attribute found for this user %s\n", username));
1681 if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
1682 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
1685 group_rid = (uint32)atol(temp);
1686 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1690 * If so configured, try and get the values from LDAP
1693 if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state, sampass, entry))) {
1696 * Otherwise just ask the system getpw() calls.
1699 pw = getpwnam_alloc(username);
1701 if (! ldap_state->permit_non_unix_accounts) {
1702 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
1707 pdb_set_uid(sampass, uid, PDB_SET);
1709 pdb_set_gid(sampass, gid, PDB_SET);
1711 pdb_set_unix_homedir(sampass, pw->pw_dir, PDB_SET);
1717 if ((pdb_get_init_flags(sampass,PDB_GROUPSID) == PDB_DEFAULT)
1718 && (pdb_get_init_flags(sampass,PDB_GID) != PDB_DEFAULT)) {
1720 gid = pdb_get_gid(sampass);
1721 /* call the mapping code here */
1722 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1723 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1726 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1730 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1731 /* leave as default */
1733 pass_last_set_time = (time_t) atol(temp);
1734 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1737 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1738 /* leave as default */
1740 logon_time = (time_t) atol(temp);
1741 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1744 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1745 /* leave as default */
1747 logoff_time = (time_t) atol(temp);
1748 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1751 if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1752 /* leave as default */
1754 kickoff_time = (time_t) atol(temp);
1755 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1758 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1759 /* leave as default */
1761 pass_can_change_time = (time_t) atol(temp);
1762 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1765 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1766 /* leave as default */
1768 pass_must_change_time = (time_t) atol(temp);
1769 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1772 /* recommend that 'gecos' and 'displayName' should refer to the same
1773 * attribute OID. userFullName depreciated, only used by Samba
1774 * primary rules of LDAP: don't make a new attribute when one is already defined
1775 * that fits your needs; using cn then displayName rather than 'userFullName'
1778 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1779 "displayName", fullname)) {
1780 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1782 /* leave as default */
1784 pdb_set_fullname(sampass, fullname, PDB_SET);
1787 pdb_set_fullname(sampass, fullname, PDB_SET);
1790 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1791 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
1797 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1800 if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1801 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
1807 pdb_set_homedir(sampass, homedir, PDB_SET);
1810 if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1811 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
1817 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1820 if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1821 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
1827 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1830 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1831 /* leave as default */
1833 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1836 if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1837 /* leave as default */;
1839 pdb_set_workstations(sampass, workstations, PDB_SET);
1842 /* FIXME: hours stuff should be cleaner */
1846 memset(hours, 0xff, hours_len);
1848 if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1849 /* leave as default */
1851 pdb_gethexpwd(temp, smblmpwd);
1852 memset((char *)temp, '\0', strlen(temp)+1);
1853 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1855 ZERO_STRUCT(smblmpwd);
1858 if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1859 /* leave as default */
1861 pdb_gethexpwd(temp, smbntpwd);
1862 memset((char *)temp, '\0', strlen(temp)+1);
1863 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1865 ZERO_STRUCT(smbntpwd);
1868 if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1869 acct_ctrl |= ACB_NORMAL;
1871 acct_ctrl = pdb_decode_acct_ctrl(temp);
1874 acct_ctrl |= ACB_NORMAL;
1876 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1879 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1880 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1882 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1884 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1885 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1886 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1888 pdb_set_hours(sampass, hours, PDB_SET);
1893 /**********************************************************************
1894 Initialize SAM_ACCOUNT from an LDAP query
1895 (Based on init_buffer_from_sam in pdb_tdb.c)
1896 *********************************************************************/
1897 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1898 LDAPMessage *existing,
1899 LDAPMod *** mods, SAM_ACCOUNT * sampass,
1900 BOOL (*need_update)(const SAM_ACCOUNT *,
1906 if (mods == NULL || sampass == NULL) {
1907 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1914 * took out adding "objectclass: sambaAccount"
1915 * do this on a per-mod basis
1917 if (need_update(sampass, PDB_USERNAME))
1918 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1919 "uid", pdb_get_username(sampass));
1921 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1923 if (pdb_get_init_flags(sampass, PDB_USERSID) == PDB_DEFAULT) {
1924 if (ldap_state->permit_non_unix_accounts) {
1925 if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state, &rid, USER_RID_TYPE))) {
1926 DEBUG(0, ("NO user RID specified on account %s, and "
1927 "finding next available NUA RID failed, "
1929 pdb_get_username(sampass)));
1930 ldap_mods_free(*mods, 1);
1934 DEBUG(0, ("NO user RID specified on account %s, "
1935 "cannot store!\n", pdb_get_username(sampass)));
1936 ldap_mods_free(*mods, 1);
1940 /* now that we have figured out the RID, always store it, as
1941 the schema requires it */
1942 if (!pdb_set_user_sid_from_rid(sampass, rid, PDB_CHANGED)) {
1943 DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n",
1944 pdb_get_username(sampass)));
1945 ldap_mods_free(*mods, 1);
1950 /* only update the RID if we actually need to */
1951 if (need_update(sampass, PDB_USERSID)) {
1953 fstring dom_sid_string;
1954 const DOM_SID *user_sid;
1955 user_sid = pdb_get_user_sid(sampass);
1957 if (ldap_state->use_ntsid) {
1958 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1959 "ntSid", sid_to_string(sid_string, user_sid));
1961 if (!sid_peek_check_rid(get_global_sam_sid(), user_sid, &rid)) {
1962 DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", sid_to_string(sid_string, user_sid), sid_to_string(dom_sid_string, get_global_sam_sid())));
1965 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1966 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1972 /* we don't need to store the primary group RID - so leaving it
1973 'free' to hang off the unix primary group makes life easier */
1975 if (need_update(sampass, PDB_GROUPSID)) {
1976 rid = pdb_get_group_rid(sampass);
1977 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1978 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1979 "primaryGroupID", temp);
1982 /* displayName, cn, and gecos should all be the same
1983 * most easily accomplished by giving them the same OID
1984 * gecos isn't set here b/c it should be handled by the
1986 * We change displayName only and fall back to cn if
1987 * it does not exist.
1990 if (need_update(sampass, PDB_FULLNAME))
1991 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1992 "displayName", pdb_get_fullname(sampass));
1994 if (need_update(sampass, PDB_ACCTDESC))
1995 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1996 "description", pdb_get_acct_desc(sampass));
1998 if (need_update(sampass, PDB_WORKSTATIONS))
1999 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2000 "userWorkstations", pdb_get_workstations(sampass));
2002 if (need_update(sampass, PDB_SMBHOME))
2003 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2004 "smbHome", pdb_get_homedir(sampass));
2006 if (need_update(sampass, PDB_DRIVE))
2007 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2008 "homeDrive", pdb_get_dir_drive(sampass));
2010 if (need_update(sampass, PDB_LOGONSCRIPT))
2011 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2012 "scriptPath", pdb_get_logon_script(sampass));
2014 if (need_update(sampass, PDB_PROFILE))
2015 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2016 "profilePath", pdb_get_profile_path(sampass));
2018 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
2020 if (need_update(sampass, PDB_LOGONTIME))
2021 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2024 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
2026 if (need_update(sampass, PDB_LOGOFFTIME))
2027 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2028 "logoffTime", temp);
2030 slprintf (temp, sizeof (temp) - 1, "%li",
2031 pdb_get_kickoff_time(sampass));
2033 if (need_update(sampass, PDB_KICKOFFTIME))
2034 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2035 "kickoffTime", temp);
2037 slprintf (temp, sizeof (temp) - 1, "%li",
2038 pdb_get_pass_can_change_time(sampass));
2040 if (need_update(sampass, PDB_CANCHANGETIME))
2041 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2042 "pwdCanChange", temp);
2044 slprintf (temp, sizeof (temp) - 1, "%li",
2045 pdb_get_pass_must_change_time(sampass));
2047 if (need_update(sampass, PDB_MUSTCHANGETIME))
2048 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2049 "pwdMustChange", temp);
2051 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
2052 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
2054 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass),
2055 pdb_get_acct_ctrl(sampass));
2057 if (need_update(sampass, PDB_LMPASSWD))
2058 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2059 "lmPassword", temp);
2061 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
2062 pdb_get_acct_ctrl(sampass));
2064 if (need_update(sampass, PDB_NTPASSWD))
2065 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2066 "ntPassword", temp);
2068 slprintf (temp, sizeof (temp) - 1, "%li",
2069 pdb_get_pass_last_set_time(sampass));
2071 if (need_update(sampass, PDB_PASSLASTSET))
2072 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2073 "pwdLastSet", temp);
2076 /* FIXME: Hours stuff goes in LDAP */
2078 if (need_update(sampass, PDB_ACCTCTRL))
2079 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2081 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
2082 NEW_PW_FORMAT_SPACE_PADDED_LEN));
2089 /**********************************************************************
2090 Connect to LDAP server for password enumeration
2091 *********************************************************************/
2092 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
2094 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2098 pstrcpy(filter, lp_ldap_filter());
2099 all_string_sub(filter, "%u", "*", sizeof(pstring));
2101 rc = ldapsam_search_suffix(ldap_state,
2103 &ldap_state->result);
2105 if (rc != LDAP_SUCCESS) {
2106 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2107 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2108 ldap_msgfree(ldap_state->result);
2109 ldap_state->result = NULL;
2110 return NT_STATUS_UNSUCCESSFUL;
2113 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2114 ldap_count_entries(ldap_state->ldap_struct,
2115 ldap_state->result)));
2117 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2118 ldap_state->result);
2119 ldap_state->index = 0;
2121 return NT_STATUS_OK;
2124 /**********************************************************************
2125 End enumeration of the LDAP password list
2126 *********************************************************************/
2127 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
2129 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2130 if (ldap_state->result) {
2131 ldap_msgfree(ldap_state->result);
2132 ldap_state->result = NULL;
2136 /**********************************************************************
2137 Get the next entry in the LDAP password database
2138 *********************************************************************/
2139 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
2141 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2142 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2145 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2146 this will work, but it's not nice. */
2147 static_ldap_state = ldap_state;
2150 if (!ldap_state->entry)
2153 ldap_state->index++;
2154 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
2156 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2160 return NT_STATUS_OK;
2163 /**********************************************************************
2164 Get SAM_ACCOUNT entry from LDAP by username
2165 *********************************************************************/
2166 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
2168 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2169 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2170 LDAPMessage *result;
2174 if (ldapsam_search_suffix_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
2175 return NT_STATUS_NO_SUCH_USER;
2178 count = ldap_count_entries(ldap_state->ldap_struct, result);
2182 ("We don't find this user [%s] count=%d\n", sname,
2184 return NT_STATUS_NO_SUCH_USER;
2185 } else if (count > 1) {
2187 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
2189 return NT_STATUS_NO_SUCH_USER;
2192 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2194 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2195 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
2196 ldap_msgfree(result);
2197 return NT_STATUS_NO_SUCH_USER;
2199 ldap_msgfree(result);
2202 ldap_msgfree(result);
2207 /**********************************************************************
2208 Get SAM_ACCOUNT entry from LDAP by SID
2209 *********************************************************************/
2210 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
2212 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2213 struct ldapsam_privates *ldap_state =
2214 (struct ldapsam_privates *)my_methods->private_data;
2215 LDAPMessage *result;
2220 if (ldap_state->use_ntsid) {
2221 if (ldapsam_search_suffix_by_sid(ldap_state, sid, &result) != LDAP_SUCCESS) {
2222 return NT_STATUS_NO_SUCH_USER;
2226 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) {
2227 return NT_STATUS_NO_SUCH_USER;
2230 if (ldapsam_search_suffix_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
2231 return NT_STATUS_NO_SUCH_USER;
2235 count = ldap_count_entries(ldap_state->ldap_struct, result);
2239 ("We don't find this SID [%s] count=%d\n", sid_to_string(sid_string, sid),
2241 return NT_STATUS_NO_SUCH_USER;
2242 } else if (count > 1) {
2244 ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid),
2246 return NT_STATUS_NO_SUCH_USER;
2249 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2251 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2252 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
2253 ldap_msgfree(result);
2254 return NT_STATUS_NO_SUCH_USER;
2256 ldap_msgfree(result);
2259 ldap_msgfree(result);
2264 /********************************************************************
2265 Do the actual modification - also change a plaittext passord if
2267 **********************************************************************/
2269 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
2270 SAM_ACCOUNT *newpwd, char *dn,
2271 LDAPMod **mods, int ldap_op,
2272 BOOL (*need_update)(const SAM_ACCOUNT *,
2275 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2278 if (!my_methods || !newpwd || !dn) {
2279 return NT_STATUS_INVALID_PARAMETER;
2283 DEBUG(5,("mods is empty: nothing to modify\n"));
2284 /* may be password change below however */
2289 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
2290 rc = ldapsam_add(ldap_state, dn, mods);
2292 case LDAP_MOD_REPLACE:
2293 rc = ldapsam_modify(ldap_state, dn ,mods);
2296 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
2297 return NT_STATUS_INVALID_PARAMETER;
2300 if (rc!=LDAP_SUCCESS) {
2301 char *ld_error = NULL;
2302 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2305 ("failed to %s user dn= %s with: %s\n\t%s\n",
2306 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
2307 dn, ldap_err2string(rc),
2308 ld_error?ld_error:"unknown"));
2309 SAFE_FREE(ld_error);
2310 return NT_STATUS_UNSUCCESSFUL;
2314 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
2315 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
2316 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
2317 need_update(newpwd, PDB_PLAINTEXT_PW) &&
2318 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
2322 struct berval *retdata;
2323 char *utf8_password;
2326 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
2327 return NT_STATUS_NO_MEMORY;
2330 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
2331 return NT_STATUS_NO_MEMORY;
2334 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
2335 DEBUG(0,("ber_alloc_t returns NULL\n"));
2336 SAFE_FREE(utf8_password);
2337 return NT_STATUS_UNSUCCESSFUL;
2340 ber_printf (ber, "{");
2341 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, utf8_dn);
2342 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, utf8_password);
2343 ber_printf (ber, "N}");
2345 if ((rc = ber_flatten (ber, &bv))<0) {
2346 DEBUG(0,("ber_flatten returns a value <0\n"));
2349 SAFE_FREE(utf8_password);
2350 return NT_STATUS_UNSUCCESSFUL;
2354 SAFE_FREE(utf8_password);
2357 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
2358 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
2359 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
2360 pdb_get_username(newpwd),ldap_err2string(rc)));
2362 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
2363 #ifdef DEBUG_PASSWORD
2364 DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
2366 ber_bvfree(retdata);
2367 ber_memfree(retoid);
2372 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
2373 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
2374 return NT_STATUS_OK;
2377 /**********************************************************************
2378 Delete entry from LDAP for username
2379 *********************************************************************/
2380 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
2382 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2385 LDAPMessage *result;
2387 const char *sam_user_attrs[] =
2388 { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
2389 "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
2390 "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
2391 "userWorkstations", "primaryGroupID", "domain", "rid", "ntSid", NULL };
2394 DEBUG(0, ("sam_acct was NULL!\n"));
2395 return NT_STATUS_INVALID_PARAMETER;
2398 sname = pdb_get_username(sam_acct);
2400 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
2402 rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result);
2403 if (rc != LDAP_SUCCESS) {
2404 return NT_STATUS_NO_SUCH_USER;
2407 ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
2409 ldap_msgfree(result);
2413 /**********************************************************************
2414 Helper function to determine for update_sam_account whether
2415 we need LDAP modification.
2416 *********************************************************************/
2417 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
2418 enum pdb_elements element)
2420 return IS_SAM_CHANGED(sampass, element);
2423 /**********************************************************************
2425 *********************************************************************/
2426 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2428 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2429 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2432 LDAPMessage *result;
2436 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result);
2437 if (rc != LDAP_SUCCESS) {
2438 return NT_STATUS_UNSUCCESSFUL;
2441 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2442 DEBUG(0, ("No user to modify!\n"));
2443 ldap_msgfree(result);
2444 return NT_STATUS_UNSUCCESSFUL;
2447 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2448 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2450 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2451 element_is_changed)) {
2452 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2453 ldap_msgfree(result);
2454 return NT_STATUS_UNSUCCESSFUL;
2457 ldap_msgfree(result);
2460 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2461 pdb_get_username(newpwd)));
2462 ldap_mods_free(mods, 1);
2463 return NT_STATUS_OK;
2466 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
2467 ldap_mods_free(mods,1);
2469 if (!NT_STATUS_IS_OK(ret)) {
2470 char *ld_error = NULL;
2471 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2473 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2474 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
2475 SAFE_FREE(ld_error);
2479 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2480 pdb_get_username(newpwd)));
2481 return NT_STATUS_OK;
2484 /**********************************************************************
2485 Helper function to determine for update_sam_account whether
2486 we need LDAP modification.
2487 *********************************************************************/
2488 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2489 enum pdb_elements element)
2491 return (IS_SAM_SET(sampass, element) ||
2492 IS_SAM_CHANGED(sampass, element));
2495 /**********************************************************************
2496 Add SAM_ACCOUNT to LDAP
2497 *********************************************************************/
2498 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2500 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2501 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2504 LDAPMessage *result = NULL;
2505 LDAPMessage *entry = NULL;
2507 LDAPMod **mods = NULL;
2511 const char *username = pdb_get_username(newpwd);
2512 if (!username || !*username) {
2513 DEBUG(0, ("Cannot add user without a username!\n"));
2514 return NT_STATUS_INVALID_PARAMETER;
2517 rc = ldapsam_search_suffix_by_name (ldap_state, username, &result);
2518 if (rc != LDAP_SUCCESS) {
2519 return NT_STATUS_UNSUCCESSFUL;
2522 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2523 DEBUG(0,("User '%s' already in the base, with samba properties\n",
2525 ldap_msgfree(result);
2526 return NT_STATUS_UNSUCCESSFUL;
2528 ldap_msgfree(result);
2530 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
2531 rc = ldapsam_search_suffix(ldap_state, filter, attr, &result);
2532 if (rc != LDAP_SUCCESS) {
2533 return NT_STATUS_UNSUCCESSFUL;
2536 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2538 if (num_result > 1) {
2539 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2540 ldap_msgfree(result);
2541 return NT_STATUS_UNSUCCESSFUL;
2544 /* Check if we need to update an existing entry */
2545 if (num_result == 1) {
2548 DEBUG(3,("User exists without samba properties: adding them\n"));
2549 ldap_op = LDAP_MOD_REPLACE;
2550 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2551 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2552 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2555 /* Check if we need to add an entry */
2556 DEBUG(3,("Adding new user\n"));
2557 ldap_op = LDAP_MOD_ADD;
2558 if (username[strlen(username)-1] == '$') {
2559 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2561 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2565 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2566 element_is_set_or_changed)) {
2567 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2568 ldap_msgfree(result);
2569 return NT_STATUS_UNSUCCESSFUL;
2572 ldap_msgfree(result);
2575 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2576 return NT_STATUS_UNSUCCESSFUL;
2579 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
2581 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
2582 if (NT_STATUS_IS_ERR(ret)) {
2583 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2584 pdb_get_username(newpwd),dn));
2585 ldap_mods_free(mods,1);
2589 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
2590 ldap_mods_free(mods, 1);
2591 return NT_STATUS_OK;
2594 static void free_private_data(void **vp)
2596 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2598 ldapsam_close(*ldap_state);
2600 if ((*ldap_state)->bind_secret) {
2601 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2604 ldapsam_close(*ldap_state);
2606 SAFE_FREE((*ldap_state)->bind_dn);
2607 SAFE_FREE((*ldap_state)->bind_secret);
2611 /* No need to free any further, as it is talloc()ed */
2614 static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
2616 "displayName", "description",
2619 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2621 LDAPMessage ** result)
2623 int scope = LDAP_SCOPE_SUBTREE;
2626 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2628 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
2629 filter, group_attr, 0, result);
2631 if (rc != LDAP_SUCCESS) {
2632 char *ld_error = NULL;
2633 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2635 DEBUG(0, ("ldapsam_search_one_group: "
2636 "Problem during the LDAP search: LDAP error: %s (%s)",
2637 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
2638 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2639 lp_ldap_suffix(), filter));
2640 SAFE_FREE(ld_error);
2646 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2647 GROUP_MAP *map, LDAPMessage *entry)
2651 if (ldap_state == NULL || map == NULL || entry == NULL ||
2652 ldap_state->ldap_struct == NULL) {
2653 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2657 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
2659 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
2662 DEBUG(2, ("Entry found for group: %s\n", temp));
2664 map->gid = (gid_t)atol(temp);
2666 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
2668 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
2671 string_to_sid(&map->sid, temp);
2673 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
2675 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
2678 map->sid_name_use = (uint32)atol(temp);
2680 if ((map->sid_name_use < SID_NAME_USER) ||
2681 (map->sid_name_use > SID_NAME_UNKNOWN)) {
2682 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2686 if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
2688 DEBUG(3, ("Attribute displayName not found\n"));
2690 if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn",
2692 DEBUG(0, ("Attributes cn not found either "
2693 "for gidNumber(%i)\n",map->gid));
2697 fstrcpy(map->nt_name, temp);
2699 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
2701 DEBUG(3, ("Attribute description not found\n"));
2704 fstrcpy(map->comment, temp);
2706 map->systemaccount = 0;
2707 init_privilege(&map->priv_set);
2712 static BOOL init_ldap_from_group(LDAP *ldap_struct,
2713 LDAPMessage *existing,
2715 const GROUP_MAP *map)
2719 if (mods == NULL || map == NULL) {
2720 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2726 sid_to_string(tmp, &map->sid);
2727 make_ldap_mod(ldap_struct, existing, mods, "ntSid", tmp);
2728 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2729 make_ldap_mod(ldap_struct, existing, mods, "ntGroupType", tmp);
2731 make_ldap_mod(ldap_struct, existing, mods, "displayName", map->nt_name);
2732 make_ldap_mod(ldap_struct, existing, mods, "description", map->comment);
2737 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2741 struct ldapsam_privates *ldap_state =
2742 (struct ldapsam_privates *)methods->private_data;
2743 LDAPMessage *result;
2747 if (ldapsam_search_one_group(ldap_state, filter, &result)
2749 return NT_STATUS_NO_SUCH_GROUP;
2752 count = ldap_count_entries(ldap_state->ldap_struct, result);
2755 DEBUG(4, ("Did not find group for filter %s\n", filter));
2756 return NT_STATUS_NO_SUCH_GROUP;
2760 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2762 return NT_STATUS_NO_SUCH_GROUP;
2765 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2768 ldap_msgfree(result);
2769 return NT_STATUS_UNSUCCESSFUL;
2772 if (!init_group_from_ldap(ldap_state, map, entry)) {
2773 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2775 ldap_msgfree(result);
2776 return NT_STATUS_NO_SUCH_GROUP;
2779 ldap_msgfree(result);
2780 return NT_STATUS_OK;
2783 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2784 DOM_SID sid, BOOL with_priv)
2788 snprintf(filter, sizeof(filter)-1,
2789 "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
2790 sid_string_static(&sid));
2792 return ldapsam_getgroup(methods, filter, map);
2795 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2796 gid_t gid, BOOL with_priv)
2800 snprintf(filter, sizeof(filter)-1,
2801 "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
2804 return ldapsam_getgroup(methods, filter, map);
2807 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2808 char *name, BOOL with_priv)
2812 /* TODO: Escaping of name? */
2814 snprintf(filter, sizeof(filter)-1,
2815 "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
2818 return ldapsam_getgroup(methods, filter, map);
2821 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2823 LDAPMessage **result)
2827 snprintf(filter, sizeof(filter)-1,
2828 "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
2830 return ldapsam_search_one_group(ldap_state, filter, result);
2833 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2836 struct ldapsam_privates *ldap_state =
2837 (struct ldapsam_privates *)methods->private_data;
2838 LDAPMessage *result = NULL;
2839 LDAPMod **mods = NULL;
2849 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2850 map->gid, False))) {
2851 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2852 return NT_STATUS_UNSUCCESSFUL;
2855 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2856 if (rc != LDAP_SUCCESS) {
2857 return NT_STATUS_UNSUCCESSFUL;
2860 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
2861 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
2863 ldap_msgfree(result);
2864 return NT_STATUS_UNSUCCESSFUL;
2867 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2868 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
2872 if (!init_ldap_from_group(ldap_state->ldap_struct,
2873 result, &mods, map)) {
2874 DEBUG(0, ("init_ldap_from_group failed!\n"));
2875 ldap_mods_free(mods, 1);
2876 ldap_msgfree(result);
2877 return NT_STATUS_UNSUCCESSFUL;
2880 ldap_msgfree(result);
2883 DEBUG(0, ("mods is empty\n"));
2884 return NT_STATUS_UNSUCCESSFUL;
2887 make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
2888 "sambaGroupMapping");
2890 rc = ldapsam_modify(ldap_state, dn, mods);
2891 ldap_mods_free(mods, 1);
2893 if (rc != LDAP_SUCCESS) {
2894 char *ld_error = NULL;
2895 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2897 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
2898 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2899 SAFE_FREE(ld_error);
2900 return NT_STATUS_UNSUCCESSFUL;
2903 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2904 return NT_STATUS_OK;
2907 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2910 struct ldapsam_privates *ldap_state =
2911 (struct ldapsam_privates *)methods->private_data;
2914 LDAPMessage *result;
2918 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2920 if (rc != LDAP_SUCCESS) {
2921 return NT_STATUS_UNSUCCESSFUL;
2924 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2925 DEBUG(0, ("No group to modify!\n"));
2926 ldap_msgfree(result);
2927 return NT_STATUS_UNSUCCESSFUL;
2930 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2931 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2933 if (!init_ldap_from_group(ldap_state->ldap_struct,
2934 result, &mods, map)) {
2935 DEBUG(0, ("init_ldap_from_group failed\n"));
2936 ldap_msgfree(result);
2937 return NT_STATUS_UNSUCCESSFUL;
2940 ldap_msgfree(result);
2943 DEBUG(4, ("mods is empty: nothing to do\n"));
2944 return NT_STATUS_UNSUCCESSFUL;
2947 rc = ldapsam_modify(ldap_state, dn, mods);
2949 ldap_mods_free(mods, 1);
2951 if (rc != LDAP_SUCCESS) {
2952 char *ld_error = NULL;
2953 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2955 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
2956 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2957 SAFE_FREE(ld_error);
2960 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2961 return NT_STATUS_OK;
2964 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2967 struct ldapsam_privates *ldap_state =
2968 (struct ldapsam_privates *)methods->private_data;
2969 pstring sidstring, filter;
2970 LDAPMessage *result;
2974 const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
2975 "description", "displayName",
2977 sid_to_string(sidstring, &sid);
2978 snprintf(filter, sizeof(filter)-1,
2979 "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
2981 rc = ldapsam_search_one_group(ldap_state, filter, &result);
2983 if (rc != LDAP_SUCCESS) {
2984 return NT_STATUS_NO_SUCH_GROUP;
2987 ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
2989 ldap_msgfree(result);
2993 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
2996 struct ldapsam_privates *ldap_state =
2997 (struct ldapsam_privates *)my_methods->private_data;
2998 const char *filter = "(objectClass=sambaGroupMapping)";
3001 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
3002 LDAP_SCOPE_SUBTREE, filter,
3003 group_attr, 0, &ldap_state->result);
3005 if (rc != LDAP_SUCCESS) {
3006 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
3007 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
3008 ldap_msgfree(ldap_state->result);
3009 ldap_state->result = NULL;
3010 return NT_STATUS_UNSUCCESSFUL;
3013 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
3014 ldap_count_entries(ldap_state->ldap_struct,
3015 ldap_state->result)));
3017 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
3018 ldap_state->result);
3019 ldap_state->index = 0;
3021 return NT_STATUS_OK;
3024 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
3026 ldapsam_endsampwent(my_methods);
3029 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
3032 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
3033 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
3036 /* The rebind proc needs this *HACK*. We are not multithreaded, so
3037 this will work, but it's not nice. */
3038 static_ldap_state = ldap_state;
3041 if (!ldap_state->entry)
3044 ldap_state->index++;
3045 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
3047 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
3051 return NT_STATUS_OK;
3054 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
3055 enum SID_NAME_USE sid_name_use,
3056 GROUP_MAP **rmap, int *num_entries,
3057 BOOL unix_only, BOOL with_priv)
3067 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
3068 DEBUG(0, ("Unable to open passdb\n"));
3069 return NT_STATUS_ACCESS_DENIED;
3072 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
3073 if (sid_name_use != SID_NAME_UNKNOWN &&
3074 sid_name_use != map.sid_name_use) {
3075 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
3078 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
3079 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
3083 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
3085 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
3087 return NT_STATUS_UNSUCCESSFUL;
3092 mapt[entries] = map;
3097 ldapsam_endsamgrent(methods);
3099 *num_entries = entries;
3101 return NT_STATUS_OK;
3104 static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3107 struct ldapsam_privates *ldap_state;
3109 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
3113 (*pdb_method)->name = "ldapsam";
3115 (*pdb_method)->setsampwent = ldapsam_setsampwent;
3116 (*pdb_method)->endsampwent = ldapsam_endsampwent;
3117 (*pdb_method)->getsampwent = ldapsam_getsampwent;
3118 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
3119 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
3120 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
3121 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
3122 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
3124 (*pdb_method)->getgrsid = ldapsam_getgrsid;
3125 (*pdb_method)->getgrgid = ldapsam_getgrgid;
3126 (*pdb_method)->getgrnam = ldapsam_getgrnam;
3127 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
3128 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
3129 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
3130 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
3132 /* TODO: Setup private data and free */
3134 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
3137 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
3138 return NT_STATUS_NO_MEMORY;
3142 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3144 ldap_state->uri = "ldap://localhost";
3147 ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
3148 if (!ldap_state->domain_name) {
3149 return NT_STATUS_NO_MEMORY;
3152 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
3154 ldap_state->use_ntsid = True;
3156 (*pdb_method)->private_data = ldap_state;
3158 (*pdb_method)->free_private_data = free_private_data;
3160 return NT_STATUS_OK;
3163 static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3166 struct ldapsam_privates *ldap_state;
3168 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
3172 (*pdb_method)->name = "ldapsam_compat";
3174 ldap_state = (*pdb_method)->private_data;
3175 ldap_state->use_ntsid = False;
3178 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3180 #ifndef WITH_LDAP_SAMCONFIG
3181 ldap_state->uri = "ldap://localhost";
3183 int ldap_port = lp_ldap_port();
3185 /* remap default port if not using SSL (ie clear or TLS) */
3186 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
3190 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);
3191 if (!ldap_state->uri) {
3192 return NT_STATUS_NO_MEMORY;
3197 return NT_STATUS_OK;
3200 static NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3203 struct ldapsam_privates *ldap_state;
3204 uint32 low_winbind_uid, high_winbind_uid;
3205 uint32 low_winbind_gid, high_winbind_gid;
3207 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
3211 (*pdb_method)->name = "ldapsam_nua";
3213 ldap_state = (*pdb_method)->private_data;
3215 ldap_state->permit_non_unix_accounts = True;
3217 /* We know these uids can't turn up as allogorithmic RIDs */
3218 if (!lp_winbind_uid(&low_winbind_uid, &high_winbind_uid)) {
3219 DEBUG(0, ("cannot use ldapsam_nua without 'winbind uid' range in smb.conf!\n"));
3220 return NT_STATUS_UNSUCCESSFUL;
3223 /* We know these gids can't turn up as allogorithmic RIDs */
3224 if (!lp_winbind_gid(&low_winbind_gid, &high_winbind_gid)) {
3225 DEBUG(0, ("cannot use ldapsam_nua without 'winbind gid' range in smb.conf!\n"));
3226 return NT_STATUS_UNSUCCESSFUL;
3229 ldap_state->low_allocated_user_rid=fallback_pdb_uid_to_user_rid(low_winbind_uid);
3231 ldap_state->high_allocated_user_rid=fallback_pdb_uid_to_user_rid(high_winbind_uid);
3233 ldap_state->low_allocated_group_rid=pdb_gid_to_group_rid(low_winbind_gid);
3235 ldap_state->high_allocated_group_rid=pdb_gid_to_group_rid(high_winbind_gid);
3237 return NT_STATUS_OK;
3240 NTSTATUS pdb_ldap_init(void)
3242 smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam);
3243 smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat);
3244 smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_nua", pdb_init_ldapsam_nua);
3245 return NT_STATUS_OK;