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: already 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,
1544 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
1545 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
1549 for (values=ldap_values;*values;values++) {
1550 if (strcasecmp(*values, "posixAccount") == 0) {
1555 if (!*values) { /*end of array, no posixAccount */
1556 DEBUG(10, ("user does not have posixAcccount attributes\n"));
1557 ldap_value_free(ldap_values);
1560 ldap_value_free(ldap_values);
1562 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir))
1565 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
1568 gid = (gid_t)atol(temp);
1570 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
1572 DEBUG(10, ("user has posixAcccount attributes\n"));
1577 /**********************************************************************
1578 Initialize SAM_ACCOUNT from an LDAP query
1579 (Based on init_sam_from_buffer in pdb_tdb.c)
1580 *********************************************************************/
1581 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
1582 SAM_ACCOUNT * sampass,
1583 LDAPMessage * entry)
1589 pass_can_change_time,
1590 pass_must_change_time;
1604 uint8 smblmpwd[LM_HASH_LEN],
1605 smbntpwd[NT_HASH_LEN];
1606 uint16 acct_ctrl = 0,
1609 uint8 hours[MAX_HOURS_LEN];
1612 gid_t gid = getegid();
1615 * do a little initialization
1619 nt_username[0] = '\0';
1622 dir_drive[0] = '\0';
1623 logon_script[0] = '\0';
1624 profile_path[0] = '\0';
1625 acct_desc[0] = '\0';
1626 munged_dial[0] = '\0';
1627 workstations[0] = '\0';
1630 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1631 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1635 if (ldap_state->ldap_struct == NULL) {
1636 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1640 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uid", username)) {
1641 DEBUG(1, ("No uid attribute found for this user!\n"));
1645 DEBUG(2, ("Entry found for user: %s\n", username));
1647 pstrcpy(nt_username, username);
1649 pstrcpy(domain, ldap_state->domain_name);
1651 pdb_set_username(sampass, username, PDB_SET);
1653 pdb_set_domain(sampass, domain, PDB_DEFAULT);
1654 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1656 if (ldap_state->use_ntsid) {
1657 if (get_single_attribute(ldap_state->ldap_struct, entry, "ntSid", temp)) {
1658 pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
1661 if (get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp)) {
1662 user_rid = (uint32)atol(temp);
1663 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1667 if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
1668 DEBUG(1, ("no rid or ntSid attribute found for this user %s\n", username));
1672 if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
1673 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
1676 group_rid = (uint32)atol(temp);
1677 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1681 * If so configured, try and get the values from LDAP
1684 if (!lp_ldap_trust_ids() && (get_unix_attributes(ldap_state, sampass, entry, &gid))) {
1686 if (pdb_get_init_flags(sampass,PDB_GROUPSID) == PDB_DEFAULT) {
1688 /* call the mapping code here */
1689 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1690 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1693 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1698 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1699 /* leave as default */
1701 pass_last_set_time = (time_t) atol(temp);
1702 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1705 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1706 /* leave as default */
1708 logon_time = (time_t) atol(temp);
1709 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1712 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1713 /* leave as default */
1715 logoff_time = (time_t) atol(temp);
1716 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1719 if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1720 /* leave as default */
1722 kickoff_time = (time_t) atol(temp);
1723 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1726 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1727 /* leave as default */
1729 pass_can_change_time = (time_t) atol(temp);
1730 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1733 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1734 /* leave as default */
1736 pass_must_change_time = (time_t) atol(temp);
1737 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1740 /* recommend that 'gecos' and 'displayName' should refer to the same
1741 * attribute OID. userFullName depreciated, only used by Samba
1742 * primary rules of LDAP: don't make a new attribute when one is already defined
1743 * that fits your needs; using cn then displayName rather than 'userFullName'
1746 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1747 "displayName", fullname)) {
1748 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1750 /* leave as default */
1752 pdb_set_fullname(sampass, fullname, PDB_SET);
1755 pdb_set_fullname(sampass, fullname, PDB_SET);
1758 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1759 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
1765 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1768 if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1769 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
1775 pdb_set_homedir(sampass, homedir, PDB_SET);
1778 if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1779 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
1785 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1788 if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1789 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
1795 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1798 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1799 /* leave as default */
1801 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1804 if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1805 /* leave as default */;
1807 pdb_set_workstations(sampass, workstations, PDB_SET);
1810 /* FIXME: hours stuff should be cleaner */
1814 memset(hours, 0xff, hours_len);
1816 if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1817 /* leave as default */
1819 pdb_gethexpwd(temp, smblmpwd);
1820 memset((char *)temp, '\0', strlen(temp)+1);
1821 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1823 ZERO_STRUCT(smblmpwd);
1826 if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1827 /* leave as default */
1829 pdb_gethexpwd(temp, smbntpwd);
1830 memset((char *)temp, '\0', strlen(temp)+1);
1831 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1833 ZERO_STRUCT(smbntpwd);
1836 if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1837 acct_ctrl |= ACB_NORMAL;
1839 acct_ctrl = pdb_decode_acct_ctrl(temp);
1842 acct_ctrl |= ACB_NORMAL;
1844 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1847 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1848 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1850 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1852 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1853 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1854 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1856 pdb_set_hours(sampass, hours, PDB_SET);
1861 /**********************************************************************
1862 Initialize SAM_ACCOUNT from an LDAP query
1863 (Based on init_buffer_from_sam in pdb_tdb.c)
1864 *********************************************************************/
1865 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1866 LDAPMessage *existing,
1867 LDAPMod *** mods, SAM_ACCOUNT * sampass,
1868 BOOL (*need_update)(const SAM_ACCOUNT *,
1874 if (mods == NULL || sampass == NULL) {
1875 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1882 * took out adding "objectclass: sambaAccount"
1883 * do this on a per-mod basis
1885 if (need_update(sampass, PDB_USERNAME))
1886 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1887 "uid", pdb_get_username(sampass));
1889 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1891 if (pdb_get_init_flags(sampass, PDB_USERSID) == PDB_DEFAULT) {
1892 if (ldap_state->permit_non_unix_accounts) {
1893 if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state, &rid, USER_RID_TYPE))) {
1894 DEBUG(0, ("NO user RID specified on account %s, and "
1895 "finding next available NUA RID failed, "
1897 pdb_get_username(sampass)));
1898 ldap_mods_free(*mods, 1);
1902 DEBUG(0, ("NO user RID specified on account %s, "
1903 "cannot store!\n", pdb_get_username(sampass)));
1904 ldap_mods_free(*mods, 1);
1908 /* now that we have figured out the RID, always store it, as
1909 the schema requires it */
1910 if (!pdb_set_user_sid_from_rid(sampass, rid, PDB_CHANGED)) {
1911 DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n",
1912 pdb_get_username(sampass)));
1913 ldap_mods_free(*mods, 1);
1918 /* only update the RID if we actually need to */
1919 if (need_update(sampass, PDB_USERSID)) {
1921 fstring dom_sid_string;
1922 const DOM_SID *user_sid;
1923 user_sid = pdb_get_user_sid(sampass);
1925 if (ldap_state->use_ntsid) {
1926 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1927 "ntSid", sid_to_string(sid_string, user_sid));
1929 if (!sid_peek_check_rid(get_global_sam_sid(), user_sid, &rid)) {
1930 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())));
1933 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1934 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1940 /* we don't need to store the primary group RID - so leaving it
1941 'free' to hang off the unix primary group makes life easier */
1943 if (need_update(sampass, PDB_GROUPSID)) {
1944 rid = pdb_get_group_rid(sampass);
1945 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1946 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1947 "primaryGroupID", temp);
1950 /* displayName, cn, and gecos should all be the same
1951 * most easily accomplished by giving them the same OID
1952 * gecos isn't set here b/c it should be handled by the
1954 * We change displayName only and fall back to cn if
1955 * it does not exist.
1958 if (need_update(sampass, PDB_FULLNAME))
1959 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1960 "displayName", pdb_get_fullname(sampass));
1962 if (need_update(sampass, PDB_ACCTDESC))
1963 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1964 "description", pdb_get_acct_desc(sampass));
1966 if (need_update(sampass, PDB_WORKSTATIONS))
1967 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1968 "userWorkstations", pdb_get_workstations(sampass));
1970 if (need_update(sampass, PDB_SMBHOME))
1971 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1972 "smbHome", pdb_get_homedir(sampass));
1974 if (need_update(sampass, PDB_DRIVE))
1975 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1976 "homeDrive", pdb_get_dir_drive(sampass));
1978 if (need_update(sampass, PDB_LOGONSCRIPT))
1979 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1980 "scriptPath", pdb_get_logon_script(sampass));
1982 if (need_update(sampass, PDB_PROFILE))
1983 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1984 "profilePath", pdb_get_profile_path(sampass));
1986 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1988 if (need_update(sampass, PDB_LOGONTIME))
1989 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1992 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1994 if (need_update(sampass, PDB_LOGOFFTIME))
1995 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1996 "logoffTime", temp);
1998 slprintf (temp, sizeof (temp) - 1, "%li",
1999 pdb_get_kickoff_time(sampass));
2001 if (need_update(sampass, PDB_KICKOFFTIME))
2002 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2003 "kickoffTime", temp);
2005 slprintf (temp, sizeof (temp) - 1, "%li",
2006 pdb_get_pass_can_change_time(sampass));
2008 if (need_update(sampass, PDB_CANCHANGETIME))
2009 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2010 "pwdCanChange", temp);
2012 slprintf (temp, sizeof (temp) - 1, "%li",
2013 pdb_get_pass_must_change_time(sampass));
2015 if (need_update(sampass, PDB_MUSTCHANGETIME))
2016 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2017 "pwdMustChange", temp);
2019 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
2020 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
2022 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass),
2023 pdb_get_acct_ctrl(sampass));
2025 if (need_update(sampass, PDB_LMPASSWD))
2026 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2027 "lmPassword", temp);
2029 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
2030 pdb_get_acct_ctrl(sampass));
2032 if (need_update(sampass, PDB_NTPASSWD))
2033 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2034 "ntPassword", temp);
2036 slprintf (temp, sizeof (temp) - 1, "%li",
2037 pdb_get_pass_last_set_time(sampass));
2039 if (need_update(sampass, PDB_PASSLASTSET))
2040 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2041 "pwdLastSet", temp);
2044 /* FIXME: Hours stuff goes in LDAP */
2046 if (need_update(sampass, PDB_ACCTCTRL))
2047 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2049 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
2050 NEW_PW_FORMAT_SPACE_PADDED_LEN));
2057 /**********************************************************************
2058 Connect to LDAP server for password enumeration
2059 *********************************************************************/
2060 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
2062 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2066 pstrcpy(filter, lp_ldap_filter());
2067 all_string_sub(filter, "%u", "*", sizeof(pstring));
2069 rc = ldapsam_search_suffix(ldap_state,
2071 &ldap_state->result);
2073 if (rc != LDAP_SUCCESS) {
2074 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2075 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2076 ldap_msgfree(ldap_state->result);
2077 ldap_state->result = NULL;
2078 return NT_STATUS_UNSUCCESSFUL;
2081 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2082 ldap_count_entries(ldap_state->ldap_struct,
2083 ldap_state->result)));
2085 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2086 ldap_state->result);
2087 ldap_state->index = 0;
2089 return NT_STATUS_OK;
2092 /**********************************************************************
2093 End enumeration of the LDAP password list
2094 *********************************************************************/
2095 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
2097 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2098 if (ldap_state->result) {
2099 ldap_msgfree(ldap_state->result);
2100 ldap_state->result = NULL;
2104 /**********************************************************************
2105 Get the next entry in the LDAP password database
2106 *********************************************************************/
2107 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
2109 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2110 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2113 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2114 this will work, but it's not nice. */
2115 static_ldap_state = ldap_state;
2118 if (!ldap_state->entry)
2121 ldap_state->index++;
2122 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
2124 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2128 return NT_STATUS_OK;
2131 /**********************************************************************
2132 Get SAM_ACCOUNT entry from LDAP by username
2133 *********************************************************************/
2134 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
2136 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2137 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2138 LDAPMessage *result;
2142 if (ldapsam_search_suffix_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
2143 return NT_STATUS_NO_SUCH_USER;
2146 count = ldap_count_entries(ldap_state->ldap_struct, result);
2150 ("We don't find this user [%s] count=%d\n", sname,
2152 return NT_STATUS_NO_SUCH_USER;
2153 } else if (count > 1) {
2155 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
2157 return NT_STATUS_NO_SUCH_USER;
2160 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2162 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2163 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
2164 ldap_msgfree(result);
2165 return NT_STATUS_NO_SUCH_USER;
2167 ldap_msgfree(result);
2170 ldap_msgfree(result);
2175 /**********************************************************************
2176 Get SAM_ACCOUNT entry from LDAP by SID
2177 *********************************************************************/
2178 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
2180 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2181 struct ldapsam_privates *ldap_state =
2182 (struct ldapsam_privates *)my_methods->private_data;
2183 LDAPMessage *result;
2188 if (ldap_state->use_ntsid) {
2189 if (ldapsam_search_suffix_by_sid(ldap_state, sid, &result) != LDAP_SUCCESS) {
2190 return NT_STATUS_NO_SUCH_USER;
2194 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) {
2195 return NT_STATUS_NO_SUCH_USER;
2198 if (ldapsam_search_suffix_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
2199 return NT_STATUS_NO_SUCH_USER;
2203 count = ldap_count_entries(ldap_state->ldap_struct, result);
2207 ("We don't find this SID [%s] count=%d\n", sid_to_string(sid_string, sid),
2209 return NT_STATUS_NO_SUCH_USER;
2210 } else if (count > 1) {
2212 ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid),
2214 return NT_STATUS_NO_SUCH_USER;
2217 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2219 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2220 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
2221 ldap_msgfree(result);
2222 return NT_STATUS_NO_SUCH_USER;
2224 ldap_msgfree(result);
2227 ldap_msgfree(result);
2232 /********************************************************************
2233 Do the actual modification - also change a plaittext passord if
2235 **********************************************************************/
2237 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
2238 SAM_ACCOUNT *newpwd, char *dn,
2239 LDAPMod **mods, int ldap_op,
2240 BOOL (*need_update)(const SAM_ACCOUNT *,
2243 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2246 if (!my_methods || !newpwd || !dn) {
2247 return NT_STATUS_INVALID_PARAMETER;
2251 DEBUG(5,("mods is empty: nothing to modify\n"));
2252 /* may be password change below however */
2257 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
2258 rc = ldapsam_add(ldap_state, dn, mods);
2260 case LDAP_MOD_REPLACE:
2261 rc = ldapsam_modify(ldap_state, dn ,mods);
2264 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
2265 return NT_STATUS_INVALID_PARAMETER;
2268 if (rc!=LDAP_SUCCESS) {
2269 char *ld_error = NULL;
2270 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2273 ("failed to %s user dn= %s with: %s\n\t%s\n",
2274 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
2275 dn, ldap_err2string(rc),
2276 ld_error?ld_error:"unknown"));
2277 SAFE_FREE(ld_error);
2278 return NT_STATUS_UNSUCCESSFUL;
2282 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
2283 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
2284 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
2285 need_update(newpwd, PDB_PLAINTEXT_PW) &&
2286 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
2290 struct berval *retdata;
2291 char *utf8_password;
2294 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
2295 return NT_STATUS_NO_MEMORY;
2298 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
2299 return NT_STATUS_NO_MEMORY;
2302 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
2303 DEBUG(0,("ber_alloc_t returns NULL\n"));
2304 SAFE_FREE(utf8_password);
2305 return NT_STATUS_UNSUCCESSFUL;
2308 ber_printf (ber, "{");
2309 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, utf8_dn);
2310 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, utf8_password);
2311 ber_printf (ber, "N}");
2313 if ((rc = ber_flatten (ber, &bv))<0) {
2314 DEBUG(0,("ber_flatten returns a value <0\n"));
2317 SAFE_FREE(utf8_password);
2318 return NT_STATUS_UNSUCCESSFUL;
2322 SAFE_FREE(utf8_password);
2325 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
2326 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
2327 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
2328 pdb_get_username(newpwd),ldap_err2string(rc)));
2330 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
2331 #ifdef DEBUG_PASSWORD
2332 DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
2334 ber_bvfree(retdata);
2335 ber_memfree(retoid);
2340 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
2341 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
2342 return NT_STATUS_OK;
2345 /**********************************************************************
2346 Delete entry from LDAP for username
2347 *********************************************************************/
2348 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
2350 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2353 LDAPMessage *result;
2355 const char *sam_user_attrs[] =
2356 { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
2357 "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
2358 "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
2359 "userWorkstations", "primaryGroupID", "domain", "rid", "ntSid", NULL };
2362 DEBUG(0, ("sam_acct was NULL!\n"));
2363 return NT_STATUS_INVALID_PARAMETER;
2366 sname = pdb_get_username(sam_acct);
2368 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
2370 rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result);
2371 if (rc != LDAP_SUCCESS) {
2372 return NT_STATUS_NO_SUCH_USER;
2375 ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
2377 ldap_msgfree(result);
2381 /**********************************************************************
2382 Helper function to determine for update_sam_account whether
2383 we need LDAP modification.
2384 *********************************************************************/
2385 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
2386 enum pdb_elements element)
2388 return IS_SAM_CHANGED(sampass, element);
2391 /**********************************************************************
2393 *********************************************************************/
2394 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2396 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2397 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2400 LDAPMessage *result;
2404 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result);
2405 if (rc != LDAP_SUCCESS) {
2406 return NT_STATUS_UNSUCCESSFUL;
2409 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2410 DEBUG(0, ("No user to modify!\n"));
2411 ldap_msgfree(result);
2412 return NT_STATUS_UNSUCCESSFUL;
2415 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2416 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2418 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2419 element_is_changed)) {
2420 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2421 ldap_msgfree(result);
2422 return NT_STATUS_UNSUCCESSFUL;
2425 ldap_msgfree(result);
2428 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2429 pdb_get_username(newpwd)));
2430 ldap_mods_free(mods, 1);
2431 return NT_STATUS_OK;
2434 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
2435 ldap_mods_free(mods,1);
2437 if (!NT_STATUS_IS_OK(ret)) {
2438 char *ld_error = NULL;
2439 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2441 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2442 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
2443 SAFE_FREE(ld_error);
2447 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2448 pdb_get_username(newpwd)));
2449 return NT_STATUS_OK;
2452 /**********************************************************************
2453 Helper function to determine for update_sam_account whether
2454 we need LDAP modification.
2455 *********************************************************************/
2456 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2457 enum pdb_elements element)
2459 return (IS_SAM_SET(sampass, element) ||
2460 IS_SAM_CHANGED(sampass, element));
2463 /**********************************************************************
2464 Add SAM_ACCOUNT to LDAP
2465 *********************************************************************/
2466 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2468 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2469 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2472 LDAPMessage *result = NULL;
2473 LDAPMessage *entry = NULL;
2475 LDAPMod **mods = NULL;
2479 const char *username = pdb_get_username(newpwd);
2480 if (!username || !*username) {
2481 DEBUG(0, ("Cannot add user without a username!\n"));
2482 return NT_STATUS_INVALID_PARAMETER;
2485 rc = ldapsam_search_suffix_by_name (ldap_state, username, &result);
2486 if (rc != LDAP_SUCCESS) {
2487 return NT_STATUS_UNSUCCESSFUL;
2490 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2491 DEBUG(0,("User '%s' already in the base, with samba properties\n",
2493 ldap_msgfree(result);
2494 return NT_STATUS_UNSUCCESSFUL;
2496 ldap_msgfree(result);
2498 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
2499 rc = ldapsam_search_suffix(ldap_state, filter, attr, &result);
2500 if (rc != LDAP_SUCCESS) {
2501 return NT_STATUS_UNSUCCESSFUL;
2504 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2506 if (num_result > 1) {
2507 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2508 ldap_msgfree(result);
2509 return NT_STATUS_UNSUCCESSFUL;
2512 /* Check if we need to update an existing entry */
2513 if (num_result == 1) {
2516 DEBUG(3,("User exists without samba properties: adding them\n"));
2517 ldap_op = LDAP_MOD_REPLACE;
2518 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2519 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2520 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2523 /* Check if we need to add an entry */
2524 DEBUG(3,("Adding new user\n"));
2525 ldap_op = LDAP_MOD_ADD;
2526 if (username[strlen(username)-1] == '$') {
2527 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2529 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2533 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2534 element_is_set_or_changed)) {
2535 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2536 ldap_msgfree(result);
2537 return NT_STATUS_UNSUCCESSFUL;
2540 ldap_msgfree(result);
2543 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2544 return NT_STATUS_UNSUCCESSFUL;
2547 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
2549 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
2550 if (NT_STATUS_IS_ERR(ret)) {
2551 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2552 pdb_get_username(newpwd),dn));
2553 ldap_mods_free(mods,1);
2557 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
2558 ldap_mods_free(mods, 1);
2559 return NT_STATUS_OK;
2562 static void free_private_data(void **vp)
2564 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2566 ldapsam_close(*ldap_state);
2568 if ((*ldap_state)->bind_secret) {
2569 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2572 ldapsam_close(*ldap_state);
2574 SAFE_FREE((*ldap_state)->bind_dn);
2575 SAFE_FREE((*ldap_state)->bind_secret);
2579 /* No need to free any further, as it is talloc()ed */
2582 static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
2584 "displayName", "description",
2587 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2589 LDAPMessage ** result)
2591 int scope = LDAP_SCOPE_SUBTREE;
2594 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2596 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
2597 filter, group_attr, 0, result);
2599 if (rc != LDAP_SUCCESS) {
2600 char *ld_error = NULL;
2601 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2603 DEBUG(0, ("ldapsam_search_one_group: "
2604 "Problem during the LDAP search: LDAP error: %s (%s)",
2605 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
2606 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2607 lp_ldap_suffix(), filter));
2608 SAFE_FREE(ld_error);
2614 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2615 GROUP_MAP *map, LDAPMessage *entry)
2619 if (ldap_state == NULL || map == NULL || entry == NULL ||
2620 ldap_state->ldap_struct == NULL) {
2621 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2625 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
2627 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
2630 DEBUG(2, ("Entry found for group: %s\n", temp));
2632 map->gid = (gid_t)atol(temp);
2634 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
2636 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
2639 string_to_sid(&map->sid, temp);
2641 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
2643 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
2646 map->sid_name_use = (uint32)atol(temp);
2648 if ((map->sid_name_use < SID_NAME_USER) ||
2649 (map->sid_name_use > SID_NAME_UNKNOWN)) {
2650 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2654 if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
2656 DEBUG(3, ("Attribute displayName not found\n"));
2658 if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn",
2660 DEBUG(0, ("Attributes cn not found either "
2661 "for gidNumber(%i)\n",map->gid));
2665 fstrcpy(map->nt_name, temp);
2667 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
2669 DEBUG(3, ("Attribute description not found\n"));
2672 fstrcpy(map->comment, temp);
2674 map->systemaccount = 0;
2675 init_privilege(&map->priv_set);
2680 static BOOL init_ldap_from_group(LDAP *ldap_struct,
2681 LDAPMessage *existing,
2683 const GROUP_MAP *map)
2687 if (mods == NULL || map == NULL) {
2688 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2694 sid_to_string(tmp, &map->sid);
2695 make_ldap_mod(ldap_struct, existing, mods, "ntSid", tmp);
2696 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2697 make_ldap_mod(ldap_struct, existing, mods, "ntGroupType", tmp);
2699 make_ldap_mod(ldap_struct, existing, mods, "displayName", map->nt_name);
2700 make_ldap_mod(ldap_struct, existing, mods, "description", map->comment);
2705 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2709 struct ldapsam_privates *ldap_state =
2710 (struct ldapsam_privates *)methods->private_data;
2711 LDAPMessage *result;
2715 if (ldapsam_search_one_group(ldap_state, filter, &result)
2717 return NT_STATUS_NO_SUCH_GROUP;
2720 count = ldap_count_entries(ldap_state->ldap_struct, result);
2723 DEBUG(4, ("Did not find group for filter %s\n", filter));
2724 return NT_STATUS_NO_SUCH_GROUP;
2728 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2730 return NT_STATUS_NO_SUCH_GROUP;
2733 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2736 ldap_msgfree(result);
2737 return NT_STATUS_UNSUCCESSFUL;
2740 if (!init_group_from_ldap(ldap_state, map, entry)) {
2741 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2743 ldap_msgfree(result);
2744 return NT_STATUS_NO_SUCH_GROUP;
2747 ldap_msgfree(result);
2748 return NT_STATUS_OK;
2751 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2752 DOM_SID sid, BOOL with_priv)
2756 snprintf(filter, sizeof(filter)-1,
2757 "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
2758 sid_string_static(&sid));
2760 return ldapsam_getgroup(methods, filter, map);
2763 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2764 gid_t gid, BOOL with_priv)
2768 snprintf(filter, sizeof(filter)-1,
2769 "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
2772 return ldapsam_getgroup(methods, filter, map);
2775 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2776 char *name, BOOL with_priv)
2780 /* TODO: Escaping of name? */
2782 snprintf(filter, sizeof(filter)-1,
2783 "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
2786 return ldapsam_getgroup(methods, filter, map);
2789 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2791 LDAPMessage **result)
2795 snprintf(filter, sizeof(filter)-1,
2796 "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
2798 return ldapsam_search_one_group(ldap_state, filter, result);
2801 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2804 struct ldapsam_privates *ldap_state =
2805 (struct ldapsam_privates *)methods->private_data;
2806 LDAPMessage *result = NULL;
2807 LDAPMod **mods = NULL;
2817 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2818 map->gid, False))) {
2819 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2820 return NT_STATUS_UNSUCCESSFUL;
2823 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2824 if (rc != LDAP_SUCCESS) {
2825 return NT_STATUS_UNSUCCESSFUL;
2828 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
2829 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
2831 ldap_msgfree(result);
2832 return NT_STATUS_UNSUCCESSFUL;
2835 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2836 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
2840 if (!init_ldap_from_group(ldap_state->ldap_struct,
2841 result, &mods, map)) {
2842 DEBUG(0, ("init_ldap_from_group failed!\n"));
2843 ldap_mods_free(mods, 1);
2844 ldap_msgfree(result);
2845 return NT_STATUS_UNSUCCESSFUL;
2848 ldap_msgfree(result);
2851 DEBUG(0, ("mods is empty\n"));
2852 return NT_STATUS_UNSUCCESSFUL;
2855 make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
2856 "sambaGroupMapping");
2858 rc = ldapsam_modify(ldap_state, dn, mods);
2859 ldap_mods_free(mods, 1);
2861 if (rc != LDAP_SUCCESS) {
2862 char *ld_error = NULL;
2863 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2865 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
2866 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2867 SAFE_FREE(ld_error);
2868 return NT_STATUS_UNSUCCESSFUL;
2871 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2872 return NT_STATUS_OK;
2875 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2878 struct ldapsam_privates *ldap_state =
2879 (struct ldapsam_privates *)methods->private_data;
2882 LDAPMessage *result;
2886 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2888 if (rc != LDAP_SUCCESS) {
2889 return NT_STATUS_UNSUCCESSFUL;
2892 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2893 DEBUG(0, ("No group to modify!\n"));
2894 ldap_msgfree(result);
2895 return NT_STATUS_UNSUCCESSFUL;
2898 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2899 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2901 if (!init_ldap_from_group(ldap_state->ldap_struct,
2902 result, &mods, map)) {
2903 DEBUG(0, ("init_ldap_from_group failed\n"));
2904 ldap_msgfree(result);
2905 return NT_STATUS_UNSUCCESSFUL;
2908 ldap_msgfree(result);
2911 DEBUG(4, ("mods is empty: nothing to do\n"));
2912 return NT_STATUS_UNSUCCESSFUL;
2915 rc = ldapsam_modify(ldap_state, dn, mods);
2917 ldap_mods_free(mods, 1);
2919 if (rc != LDAP_SUCCESS) {
2920 char *ld_error = NULL;
2921 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2923 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
2924 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2925 SAFE_FREE(ld_error);
2928 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2929 return NT_STATUS_OK;
2932 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2935 struct ldapsam_privates *ldap_state =
2936 (struct ldapsam_privates *)methods->private_data;
2937 pstring sidstring, filter;
2938 LDAPMessage *result;
2942 const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
2943 "description", "displayName",
2945 sid_to_string(sidstring, &sid);
2946 snprintf(filter, sizeof(filter)-1,
2947 "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
2949 rc = ldapsam_search_one_group(ldap_state, filter, &result);
2951 if (rc != LDAP_SUCCESS) {
2952 return NT_STATUS_NO_SUCH_GROUP;
2955 ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
2957 ldap_msgfree(result);
2961 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
2964 struct ldapsam_privates *ldap_state =
2965 (struct ldapsam_privates *)my_methods->private_data;
2966 const char *filter = "(objectClass=sambaGroupMapping)";
2969 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
2970 LDAP_SCOPE_SUBTREE, filter,
2971 group_attr, 0, &ldap_state->result);
2973 if (rc != LDAP_SUCCESS) {
2974 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2975 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2976 ldap_msgfree(ldap_state->result);
2977 ldap_state->result = NULL;
2978 return NT_STATUS_UNSUCCESSFUL;
2981 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2982 ldap_count_entries(ldap_state->ldap_struct,
2983 ldap_state->result)));
2985 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2986 ldap_state->result);
2987 ldap_state->index = 0;
2989 return NT_STATUS_OK;
2992 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2994 ldapsam_endsampwent(my_methods);
2997 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
3000 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
3001 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
3004 /* The rebind proc needs this *HACK*. We are not multithreaded, so
3005 this will work, but it's not nice. */
3006 static_ldap_state = ldap_state;
3009 if (!ldap_state->entry)
3012 ldap_state->index++;
3013 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
3015 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
3019 return NT_STATUS_OK;
3022 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
3023 enum SID_NAME_USE sid_name_use,
3024 GROUP_MAP **rmap, int *num_entries,
3025 BOOL unix_only, BOOL with_priv)
3035 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
3036 DEBUG(0, ("Unable to open passdb\n"));
3037 return NT_STATUS_ACCESS_DENIED;
3040 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
3041 if (sid_name_use != SID_NAME_UNKNOWN &&
3042 sid_name_use != map.sid_name_use) {
3043 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
3046 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
3047 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
3051 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
3053 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
3055 return NT_STATUS_UNSUCCESSFUL;
3060 mapt[entries] = map;
3065 ldapsam_endsamgrent(methods);
3067 *num_entries = entries;
3069 return NT_STATUS_OK;
3072 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3075 struct ldapsam_privates *ldap_state;
3077 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
3081 (*pdb_method)->name = "ldapsam";
3083 (*pdb_method)->setsampwent = ldapsam_setsampwent;
3084 (*pdb_method)->endsampwent = ldapsam_endsampwent;
3085 (*pdb_method)->getsampwent = ldapsam_getsampwent;
3086 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
3087 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
3088 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
3089 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
3090 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
3092 (*pdb_method)->getgrsid = ldapsam_getgrsid;
3093 (*pdb_method)->getgrgid = ldapsam_getgrgid;
3094 (*pdb_method)->getgrnam = ldapsam_getgrnam;
3095 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
3096 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
3097 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
3098 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
3100 /* TODO: Setup private data and free */
3102 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
3105 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
3106 return NT_STATUS_NO_MEMORY;
3110 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3112 ldap_state->uri = "ldap://localhost";
3115 ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, lp_workgroup());
3116 if (!ldap_state->domain_name) {
3117 return NT_STATUS_NO_MEMORY;
3120 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
3122 ldap_state->use_ntsid = True;
3124 (*pdb_method)->private_data = ldap_state;
3126 (*pdb_method)->free_private_data = free_private_data;
3128 return NT_STATUS_OK;
3131 static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3134 struct ldapsam_privates *ldap_state;
3136 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3140 (*pdb_method)->name = "ldapsam_compat";
3142 ldap_state = (*pdb_method)->private_data;
3143 ldap_state->use_ntsid = False;
3146 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3148 #ifndef WITH_LDAP_SAMCONFIG
3149 ldap_state->uri = "ldap://localhost";
3151 int ldap_port = lp_ldap_port();
3153 /* remap default port if not using SSL (ie clear or TLS) */
3154 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
3158 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);
3159 if (!ldap_state->uri) {
3160 return NT_STATUS_NO_MEMORY;
3165 return NT_STATUS_OK;
3168 static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3171 struct ldapsam_privates *ldap_state;
3172 uint32 low_idmap_uid, high_idmap_uid;
3173 uint32 low_idmap_gid, high_idmap_gid;
3175 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3179 (*pdb_method)->name = "ldapsam";
3181 ldap_state = (*pdb_method)->private_data;
3183 ldap_state->permit_non_unix_accounts = True;
3185 /* We know these uids can't turn up as allogorithmic RIDs */
3186 if (!lp_idmap_uid(&low_idmap_uid, &high_idmap_uid)) {
3187 DEBUG(0, ("cannot use ldapsam_nua without 'idmap uid' range in smb.conf!\n"));
3188 return NT_STATUS_UNSUCCESSFUL;
3191 /* We know these gids can't turn up as allogorithmic RIDs */
3192 if (!lp_idmap_gid(&low_idmap_gid, &high_idmap_gid)) {
3193 DEBUG(0, ("cannot use ldapsam_nua without 'wibnind gid' range in smb.conf!\n"));
3194 return NT_STATUS_UNSUCCESSFUL;
3197 ldap_state->low_allocated_user_rid=fallback_pdb_uid_to_user_rid(low_idmap_uid);
3199 ldap_state->high_allocated_user_rid=fallback_pdb_uid_to_user_rid(high_idmap_uid);
3201 ldap_state->low_allocated_group_rid=pdb_gid_to_group_rid(low_idmap_gid);
3203 ldap_state->high_allocated_group_rid=pdb_gid_to_group_rid(high_idmap_gid);
3205 return NT_STATUS_OK;
3208 NTSTATUS pdb_ldap_init(void)
3211 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
3214 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
3217 return NT_STATUS_OK;