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;
1603 uint8 smblmpwd[LM_HASH_LEN],
1604 smbntpwd[NT_HASH_LEN];
1605 uint16 acct_ctrl = 0,
1608 uint8 hours[MAX_HOURS_LEN];
1611 gid_t gid = getegid();
1614 * do a little initialization
1618 nt_username[0] = '\0';
1621 dir_drive[0] = '\0';
1622 logon_script[0] = '\0';
1623 profile_path[0] = '\0';
1624 acct_desc[0] = '\0';
1625 munged_dial[0] = '\0';
1626 workstations[0] = '\0';
1629 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1630 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1634 if (ldap_state->ldap_struct == NULL) {
1635 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1639 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uid", username)) {
1640 DEBUG(1, ("No uid attribute found for this user!\n"));
1644 DEBUG(2, ("Entry found for user: %s\n", username));
1646 pstrcpy(nt_username, username);
1648 pstrcpy(domain, ldap_state->domain_name);
1650 pdb_set_username(sampass, username, PDB_SET);
1652 pdb_set_domain(sampass, domain, PDB_DEFAULT);
1653 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1655 if (ldap_state->use_ntsid) {
1656 if (get_single_attribute(ldap_state->ldap_struct, entry, "ntSid", temp)) {
1657 pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
1660 if (get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp)) {
1661 user_rid = (uint32)atol(temp);
1662 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1666 if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
1667 DEBUG(1, ("no rid or ntSid attribute found for this user %s\n", username));
1671 if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
1672 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
1675 group_rid = (uint32)atol(temp);
1676 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1680 * If so configured, try and get the values from LDAP
1683 if (!lp_ldap_trust_ids() && (get_unix_attributes(ldap_state, sampass, entry, &gid))) {
1685 if (pdb_get_init_flags(sampass,PDB_GROUPSID) == PDB_DEFAULT) {
1687 /* call the mapping code here */
1688 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1689 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1692 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1697 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1698 /* leave as default */
1700 pass_last_set_time = (time_t) atol(temp);
1701 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1704 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1705 /* leave as default */
1707 logon_time = (time_t) atol(temp);
1708 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1711 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1712 /* leave as default */
1714 logoff_time = (time_t) atol(temp);
1715 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1718 if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1719 /* leave as default */
1721 kickoff_time = (time_t) atol(temp);
1722 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1725 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1726 /* leave as default */
1728 pass_can_change_time = (time_t) atol(temp);
1729 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1732 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1733 /* leave as default */
1735 pass_must_change_time = (time_t) atol(temp);
1736 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1739 /* recommend that 'gecos' and 'displayName' should refer to the same
1740 * attribute OID. userFullName depreciated, only used by Samba
1741 * primary rules of LDAP: don't make a new attribute when one is already defined
1742 * that fits your needs; using cn then displayName rather than 'userFullName'
1745 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1746 "displayName", fullname)) {
1747 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1749 /* leave as default */
1751 pdb_set_fullname(sampass, fullname, PDB_SET);
1754 pdb_set_fullname(sampass, fullname, PDB_SET);
1757 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1758 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
1764 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1767 if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1768 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
1774 pdb_set_homedir(sampass, homedir, PDB_SET);
1777 if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1778 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
1784 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1787 if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1788 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
1794 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1797 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1798 /* leave as default */
1800 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1803 if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1804 /* leave as default */;
1806 pdb_set_workstations(sampass, workstations, PDB_SET);
1809 /* FIXME: hours stuff should be cleaner */
1813 memset(hours, 0xff, hours_len);
1815 if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1816 /* leave as default */
1818 pdb_gethexpwd(temp, smblmpwd);
1819 memset((char *)temp, '\0', strlen(temp)+1);
1820 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1822 ZERO_STRUCT(smblmpwd);
1825 if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1826 /* leave as default */
1828 pdb_gethexpwd(temp, smbntpwd);
1829 memset((char *)temp, '\0', strlen(temp)+1);
1830 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1832 ZERO_STRUCT(smbntpwd);
1835 if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1836 acct_ctrl |= ACB_NORMAL;
1838 acct_ctrl = pdb_decode_acct_ctrl(temp);
1841 acct_ctrl |= ACB_NORMAL;
1843 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1846 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1847 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1849 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1851 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1852 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1853 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1855 pdb_set_hours(sampass, hours, PDB_SET);
1860 /**********************************************************************
1861 Initialize SAM_ACCOUNT from an LDAP query
1862 (Based on init_buffer_from_sam in pdb_tdb.c)
1863 *********************************************************************/
1864 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1865 LDAPMessage *existing,
1866 LDAPMod *** mods, SAM_ACCOUNT * sampass,
1867 BOOL (*need_update)(const SAM_ACCOUNT *,
1873 if (mods == NULL || sampass == NULL) {
1874 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1881 * took out adding "objectclass: sambaAccount"
1882 * do this on a per-mod basis
1884 if (need_update(sampass, PDB_USERNAME))
1885 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1886 "uid", pdb_get_username(sampass));
1888 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1890 if (pdb_get_init_flags(sampass, PDB_USERSID) == PDB_DEFAULT) {
1891 if (ldap_state->permit_non_unix_accounts) {
1892 if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state, &rid, USER_RID_TYPE))) {
1893 DEBUG(0, ("NO user RID specified on account %s, and "
1894 "finding next available NUA RID failed, "
1896 pdb_get_username(sampass)));
1897 ldap_mods_free(*mods, 1);
1901 DEBUG(0, ("NO user RID specified on account %s, "
1902 "cannot store!\n", pdb_get_username(sampass)));
1903 ldap_mods_free(*mods, 1);
1907 /* now that we have figured out the RID, always store it, as
1908 the schema requires it */
1909 if (!pdb_set_user_sid_from_rid(sampass, rid, PDB_CHANGED)) {
1910 DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n",
1911 pdb_get_username(sampass)));
1912 ldap_mods_free(*mods, 1);
1917 /* only update the RID if we actually need to */
1918 if (need_update(sampass, PDB_USERSID)) {
1920 fstring dom_sid_string;
1921 const DOM_SID *user_sid;
1922 user_sid = pdb_get_user_sid(sampass);
1924 if (ldap_state->use_ntsid) {
1925 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1926 "ntSid", sid_to_string(sid_string, user_sid));
1928 if (!sid_peek_check_rid(get_global_sam_sid(), user_sid, &rid)) {
1929 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())));
1932 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1933 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1939 /* we don't need to store the primary group RID - so leaving it
1940 'free' to hang off the unix primary group makes life easier */
1942 if (need_update(sampass, PDB_GROUPSID)) {
1943 rid = pdb_get_group_rid(sampass);
1944 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1945 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1946 "primaryGroupID", temp);
1949 /* displayName, cn, and gecos should all be the same
1950 * most easily accomplished by giving them the same OID
1951 * gecos isn't set here b/c it should be handled by the
1953 * We change displayName only and fall back to cn if
1954 * it does not exist.
1957 if (need_update(sampass, PDB_FULLNAME))
1958 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1959 "displayName", pdb_get_fullname(sampass));
1961 if (need_update(sampass, PDB_ACCTDESC))
1962 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1963 "description", pdb_get_acct_desc(sampass));
1965 if (need_update(sampass, PDB_WORKSTATIONS))
1966 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1967 "userWorkstations", pdb_get_workstations(sampass));
1969 if (need_update(sampass, PDB_SMBHOME))
1970 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1971 "smbHome", pdb_get_homedir(sampass));
1973 if (need_update(sampass, PDB_DRIVE))
1974 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1975 "homeDrive", pdb_get_dir_drive(sampass));
1977 if (need_update(sampass, PDB_LOGONSCRIPT))
1978 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1979 "scriptPath", pdb_get_logon_script(sampass));
1981 if (need_update(sampass, PDB_PROFILE))
1982 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1983 "profilePath", pdb_get_profile_path(sampass));
1985 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1987 if (need_update(sampass, PDB_LOGONTIME))
1988 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1991 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1993 if (need_update(sampass, PDB_LOGOFFTIME))
1994 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1995 "logoffTime", temp);
1997 slprintf (temp, sizeof (temp) - 1, "%li",
1998 pdb_get_kickoff_time(sampass));
2000 if (need_update(sampass, PDB_KICKOFFTIME))
2001 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2002 "kickoffTime", temp);
2004 slprintf (temp, sizeof (temp) - 1, "%li",
2005 pdb_get_pass_can_change_time(sampass));
2007 if (need_update(sampass, PDB_CANCHANGETIME))
2008 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2009 "pwdCanChange", temp);
2011 slprintf (temp, sizeof (temp) - 1, "%li",
2012 pdb_get_pass_must_change_time(sampass));
2014 if (need_update(sampass, PDB_MUSTCHANGETIME))
2015 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2016 "pwdMustChange", temp);
2018 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
2019 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
2021 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass),
2022 pdb_get_acct_ctrl(sampass));
2024 if (need_update(sampass, PDB_LMPASSWD))
2025 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2026 "lmPassword", temp);
2028 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
2029 pdb_get_acct_ctrl(sampass));
2031 if (need_update(sampass, PDB_NTPASSWD))
2032 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2033 "ntPassword", temp);
2035 slprintf (temp, sizeof (temp) - 1, "%li",
2036 pdb_get_pass_last_set_time(sampass));
2038 if (need_update(sampass, PDB_PASSLASTSET))
2039 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2040 "pwdLastSet", temp);
2043 /* FIXME: Hours stuff goes in LDAP */
2045 if (need_update(sampass, PDB_ACCTCTRL))
2046 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2048 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
2049 NEW_PW_FORMAT_SPACE_PADDED_LEN));
2056 /**********************************************************************
2057 Connect to LDAP server for password enumeration
2058 *********************************************************************/
2059 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
2061 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2065 pstrcpy(filter, lp_ldap_filter());
2066 all_string_sub(filter, "%u", "*", sizeof(pstring));
2068 rc = ldapsam_search_suffix(ldap_state,
2070 &ldap_state->result);
2072 if (rc != LDAP_SUCCESS) {
2073 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2074 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2075 ldap_msgfree(ldap_state->result);
2076 ldap_state->result = NULL;
2077 return NT_STATUS_UNSUCCESSFUL;
2080 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2081 ldap_count_entries(ldap_state->ldap_struct,
2082 ldap_state->result)));
2084 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2085 ldap_state->result);
2086 ldap_state->index = 0;
2088 return NT_STATUS_OK;
2091 /**********************************************************************
2092 End enumeration of the LDAP password list
2093 *********************************************************************/
2094 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
2096 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2097 if (ldap_state->result) {
2098 ldap_msgfree(ldap_state->result);
2099 ldap_state->result = NULL;
2103 /**********************************************************************
2104 Get the next entry in the LDAP password database
2105 *********************************************************************/
2106 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
2108 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2109 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2112 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2113 this will work, but it's not nice. */
2114 static_ldap_state = ldap_state;
2117 if (!ldap_state->entry)
2120 ldap_state->index++;
2121 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
2123 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2127 return NT_STATUS_OK;
2130 /**********************************************************************
2131 Get SAM_ACCOUNT entry from LDAP by username
2132 *********************************************************************/
2133 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
2135 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2136 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2137 LDAPMessage *result;
2141 if (ldapsam_search_suffix_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
2142 return NT_STATUS_NO_SUCH_USER;
2145 count = ldap_count_entries(ldap_state->ldap_struct, result);
2149 ("We don't find this user [%s] count=%d\n", sname,
2151 return NT_STATUS_NO_SUCH_USER;
2152 } else if (count > 1) {
2154 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
2156 return NT_STATUS_NO_SUCH_USER;
2159 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2161 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2162 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
2163 ldap_msgfree(result);
2164 return NT_STATUS_NO_SUCH_USER;
2166 ldap_msgfree(result);
2169 ldap_msgfree(result);
2174 /**********************************************************************
2175 Get SAM_ACCOUNT entry from LDAP by SID
2176 *********************************************************************/
2177 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
2179 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2180 struct ldapsam_privates *ldap_state =
2181 (struct ldapsam_privates *)my_methods->private_data;
2182 LDAPMessage *result;
2187 if (ldap_state->use_ntsid) {
2188 if (ldapsam_search_suffix_by_sid(ldap_state, sid, &result) != LDAP_SUCCESS) {
2189 return NT_STATUS_NO_SUCH_USER;
2193 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) {
2194 return NT_STATUS_NO_SUCH_USER;
2197 if (ldapsam_search_suffix_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
2198 return NT_STATUS_NO_SUCH_USER;
2202 count = ldap_count_entries(ldap_state->ldap_struct, result);
2206 ("We don't find this SID [%s] count=%d\n", sid_to_string(sid_string, sid),
2208 return NT_STATUS_NO_SUCH_USER;
2209 } else if (count > 1) {
2211 ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid),
2213 return NT_STATUS_NO_SUCH_USER;
2216 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2218 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2219 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
2220 ldap_msgfree(result);
2221 return NT_STATUS_NO_SUCH_USER;
2223 ldap_msgfree(result);
2226 ldap_msgfree(result);
2231 /********************************************************************
2232 Do the actual modification - also change a plaittext passord if
2234 **********************************************************************/
2236 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
2237 SAM_ACCOUNT *newpwd, char *dn,
2238 LDAPMod **mods, int ldap_op,
2239 BOOL (*need_update)(const SAM_ACCOUNT *,
2242 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2245 if (!my_methods || !newpwd || !dn) {
2246 return NT_STATUS_INVALID_PARAMETER;
2250 DEBUG(5,("mods is empty: nothing to modify\n"));
2251 /* may be password change below however */
2256 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
2257 rc = ldapsam_add(ldap_state, dn, mods);
2259 case LDAP_MOD_REPLACE:
2260 rc = ldapsam_modify(ldap_state, dn ,mods);
2263 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
2264 return NT_STATUS_INVALID_PARAMETER;
2267 if (rc!=LDAP_SUCCESS) {
2268 char *ld_error = NULL;
2269 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2272 ("failed to %s user dn= %s with: %s\n\t%s\n",
2273 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
2274 dn, ldap_err2string(rc),
2275 ld_error?ld_error:"unknown"));
2276 SAFE_FREE(ld_error);
2277 return NT_STATUS_UNSUCCESSFUL;
2281 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
2282 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
2283 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
2284 need_update(newpwd, PDB_PLAINTEXT_PW) &&
2285 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
2289 struct berval *retdata;
2290 char *utf8_password;
2293 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
2294 return NT_STATUS_NO_MEMORY;
2297 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
2298 return NT_STATUS_NO_MEMORY;
2301 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
2302 DEBUG(0,("ber_alloc_t returns NULL\n"));
2303 SAFE_FREE(utf8_password);
2304 return NT_STATUS_UNSUCCESSFUL;
2307 ber_printf (ber, "{");
2308 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, utf8_dn);
2309 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, utf8_password);
2310 ber_printf (ber, "N}");
2312 if ((rc = ber_flatten (ber, &bv))<0) {
2313 DEBUG(0,("ber_flatten returns a value <0\n"));
2316 SAFE_FREE(utf8_password);
2317 return NT_STATUS_UNSUCCESSFUL;
2321 SAFE_FREE(utf8_password);
2324 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
2325 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
2326 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
2327 pdb_get_username(newpwd),ldap_err2string(rc)));
2329 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
2330 #ifdef DEBUG_PASSWORD
2331 DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
2333 ber_bvfree(retdata);
2334 ber_memfree(retoid);
2339 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
2340 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
2341 return NT_STATUS_OK;
2344 /**********************************************************************
2345 Delete entry from LDAP for username
2346 *********************************************************************/
2347 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
2349 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2352 LDAPMessage *result;
2354 const char *sam_user_attrs[] =
2355 { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
2356 "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
2357 "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
2358 "userWorkstations", "primaryGroupID", "domain", "rid", "ntSid", NULL };
2361 DEBUG(0, ("sam_acct was NULL!\n"));
2362 return NT_STATUS_INVALID_PARAMETER;
2365 sname = pdb_get_username(sam_acct);
2367 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
2369 rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result);
2370 if (rc != LDAP_SUCCESS) {
2371 return NT_STATUS_NO_SUCH_USER;
2374 ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
2376 ldap_msgfree(result);
2380 /**********************************************************************
2381 Helper function to determine for update_sam_account whether
2382 we need LDAP modification.
2383 *********************************************************************/
2384 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
2385 enum pdb_elements element)
2387 return IS_SAM_CHANGED(sampass, element);
2390 /**********************************************************************
2392 *********************************************************************/
2393 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2395 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2396 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2399 LDAPMessage *result;
2403 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result);
2404 if (rc != LDAP_SUCCESS) {
2405 return NT_STATUS_UNSUCCESSFUL;
2408 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2409 DEBUG(0, ("No user to modify!\n"));
2410 ldap_msgfree(result);
2411 return NT_STATUS_UNSUCCESSFUL;
2414 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2415 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2417 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2418 element_is_changed)) {
2419 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2420 ldap_msgfree(result);
2421 return NT_STATUS_UNSUCCESSFUL;
2424 ldap_msgfree(result);
2427 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2428 pdb_get_username(newpwd)));
2429 ldap_mods_free(mods, 1);
2430 return NT_STATUS_OK;
2433 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
2434 ldap_mods_free(mods,1);
2436 if (!NT_STATUS_IS_OK(ret)) {
2437 char *ld_error = NULL;
2438 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2440 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2441 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
2442 SAFE_FREE(ld_error);
2446 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2447 pdb_get_username(newpwd)));
2448 return NT_STATUS_OK;
2451 /**********************************************************************
2452 Helper function to determine for update_sam_account whether
2453 we need LDAP modification.
2454 *********************************************************************/
2455 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2456 enum pdb_elements element)
2458 return (IS_SAM_SET(sampass, element) ||
2459 IS_SAM_CHANGED(sampass, element));
2462 /**********************************************************************
2463 Add SAM_ACCOUNT to LDAP
2464 *********************************************************************/
2465 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2467 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2468 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2471 LDAPMessage *result = NULL;
2472 LDAPMessage *entry = NULL;
2474 LDAPMod **mods = NULL;
2478 const char *username = pdb_get_username(newpwd);
2479 if (!username || !*username) {
2480 DEBUG(0, ("Cannot add user without a username!\n"));
2481 return NT_STATUS_INVALID_PARAMETER;
2484 rc = ldapsam_search_suffix_by_name (ldap_state, username, &result);
2485 if (rc != LDAP_SUCCESS) {
2486 return NT_STATUS_UNSUCCESSFUL;
2489 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2490 DEBUG(0,("User '%s' already in the base, with samba properties\n",
2492 ldap_msgfree(result);
2493 return NT_STATUS_UNSUCCESSFUL;
2495 ldap_msgfree(result);
2497 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
2498 rc = ldapsam_search_suffix(ldap_state, filter, attr, &result);
2499 if (rc != LDAP_SUCCESS) {
2500 return NT_STATUS_UNSUCCESSFUL;
2503 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2505 if (num_result > 1) {
2506 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2507 ldap_msgfree(result);
2508 return NT_STATUS_UNSUCCESSFUL;
2511 /* Check if we need to update an existing entry */
2512 if (num_result == 1) {
2515 DEBUG(3,("User exists without samba properties: adding them\n"));
2516 ldap_op = LDAP_MOD_REPLACE;
2517 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2518 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2519 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2522 /* Check if we need to add an entry */
2523 DEBUG(3,("Adding new user\n"));
2524 ldap_op = LDAP_MOD_ADD;
2525 if (username[strlen(username)-1] == '$') {
2526 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2528 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2532 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2533 element_is_set_or_changed)) {
2534 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2535 ldap_msgfree(result);
2536 return NT_STATUS_UNSUCCESSFUL;
2539 ldap_msgfree(result);
2542 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2543 return NT_STATUS_UNSUCCESSFUL;
2546 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
2548 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
2549 if (NT_STATUS_IS_ERR(ret)) {
2550 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2551 pdb_get_username(newpwd),dn));
2552 ldap_mods_free(mods,1);
2556 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
2557 ldap_mods_free(mods, 1);
2558 return NT_STATUS_OK;
2561 static void free_private_data(void **vp)
2563 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2565 ldapsam_close(*ldap_state);
2567 if ((*ldap_state)->bind_secret) {
2568 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2571 ldapsam_close(*ldap_state);
2573 SAFE_FREE((*ldap_state)->bind_dn);
2574 SAFE_FREE((*ldap_state)->bind_secret);
2578 /* No need to free any further, as it is talloc()ed */
2581 static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
2583 "displayName", "description",
2586 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2588 LDAPMessage ** result)
2590 int scope = LDAP_SCOPE_SUBTREE;
2593 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2595 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
2596 filter, group_attr, 0, result);
2598 if (rc != LDAP_SUCCESS) {
2599 char *ld_error = NULL;
2600 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2602 DEBUG(0, ("ldapsam_search_one_group: "
2603 "Problem during the LDAP search: LDAP error: %s (%s)",
2604 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
2605 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2606 lp_ldap_suffix(), filter));
2607 SAFE_FREE(ld_error);
2613 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2614 GROUP_MAP *map, LDAPMessage *entry)
2618 if (ldap_state == NULL || map == NULL || entry == NULL ||
2619 ldap_state->ldap_struct == NULL) {
2620 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2624 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
2626 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
2629 DEBUG(2, ("Entry found for group: %s\n", temp));
2631 map->gid = (gid_t)atol(temp);
2633 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
2635 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
2638 string_to_sid(&map->sid, temp);
2640 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
2642 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
2645 map->sid_name_use = (uint32)atol(temp);
2647 if ((map->sid_name_use < SID_NAME_USER) ||
2648 (map->sid_name_use > SID_NAME_UNKNOWN)) {
2649 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2653 if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
2655 DEBUG(3, ("Attribute displayName not found\n"));
2657 if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn",
2659 DEBUG(0, ("Attributes cn not found either "
2660 "for gidNumber(%i)\n",map->gid));
2664 fstrcpy(map->nt_name, temp);
2666 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
2668 DEBUG(3, ("Attribute description not found\n"));
2671 fstrcpy(map->comment, temp);
2673 map->systemaccount = 0;
2674 init_privilege(&map->priv_set);
2679 static BOOL init_ldap_from_group(LDAP *ldap_struct,
2680 LDAPMessage *existing,
2682 const GROUP_MAP *map)
2686 if (mods == NULL || map == NULL) {
2687 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2693 sid_to_string(tmp, &map->sid);
2694 make_ldap_mod(ldap_struct, existing, mods, "ntSid", tmp);
2695 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2696 make_ldap_mod(ldap_struct, existing, mods, "ntGroupType", tmp);
2698 make_ldap_mod(ldap_struct, existing, mods, "displayName", map->nt_name);
2699 make_ldap_mod(ldap_struct, existing, mods, "description", map->comment);
2704 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2708 struct ldapsam_privates *ldap_state =
2709 (struct ldapsam_privates *)methods->private_data;
2710 LDAPMessage *result;
2714 if (ldapsam_search_one_group(ldap_state, filter, &result)
2716 return NT_STATUS_NO_SUCH_GROUP;
2719 count = ldap_count_entries(ldap_state->ldap_struct, result);
2722 DEBUG(4, ("Did not find group for filter %s\n", filter));
2723 return NT_STATUS_NO_SUCH_GROUP;
2727 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2729 return NT_STATUS_NO_SUCH_GROUP;
2732 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2735 ldap_msgfree(result);
2736 return NT_STATUS_UNSUCCESSFUL;
2739 if (!init_group_from_ldap(ldap_state, map, entry)) {
2740 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2742 ldap_msgfree(result);
2743 return NT_STATUS_NO_SUCH_GROUP;
2746 ldap_msgfree(result);
2747 return NT_STATUS_OK;
2750 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2751 DOM_SID sid, BOOL with_priv)
2755 snprintf(filter, sizeof(filter)-1,
2756 "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
2757 sid_string_static(&sid));
2759 return ldapsam_getgroup(methods, filter, map);
2762 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2763 gid_t gid, BOOL with_priv)
2767 snprintf(filter, sizeof(filter)-1,
2768 "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
2771 return ldapsam_getgroup(methods, filter, map);
2774 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2775 char *name, BOOL with_priv)
2779 /* TODO: Escaping of name? */
2781 snprintf(filter, sizeof(filter)-1,
2782 "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
2785 return ldapsam_getgroup(methods, filter, map);
2788 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2790 LDAPMessage **result)
2794 snprintf(filter, sizeof(filter)-1,
2795 "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
2797 return ldapsam_search_one_group(ldap_state, filter, result);
2800 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2803 struct ldapsam_privates *ldap_state =
2804 (struct ldapsam_privates *)methods->private_data;
2805 LDAPMessage *result = NULL;
2806 LDAPMod **mods = NULL;
2816 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2817 map->gid, False))) {
2818 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2819 return NT_STATUS_UNSUCCESSFUL;
2822 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2823 if (rc != LDAP_SUCCESS) {
2824 return NT_STATUS_UNSUCCESSFUL;
2827 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
2828 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
2830 ldap_msgfree(result);
2831 return NT_STATUS_UNSUCCESSFUL;
2834 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2835 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
2839 if (!init_ldap_from_group(ldap_state->ldap_struct,
2840 result, &mods, map)) {
2841 DEBUG(0, ("init_ldap_from_group failed!\n"));
2842 ldap_mods_free(mods, 1);
2843 ldap_msgfree(result);
2844 return NT_STATUS_UNSUCCESSFUL;
2847 ldap_msgfree(result);
2850 DEBUG(0, ("mods is empty\n"));
2851 return NT_STATUS_UNSUCCESSFUL;
2854 make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
2855 "sambaGroupMapping");
2857 rc = ldapsam_modify(ldap_state, dn, mods);
2858 ldap_mods_free(mods, 1);
2860 if (rc != LDAP_SUCCESS) {
2861 char *ld_error = NULL;
2862 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2864 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
2865 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2866 SAFE_FREE(ld_error);
2867 return NT_STATUS_UNSUCCESSFUL;
2870 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2871 return NT_STATUS_OK;
2874 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2877 struct ldapsam_privates *ldap_state =
2878 (struct ldapsam_privates *)methods->private_data;
2881 LDAPMessage *result;
2885 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2887 if (rc != LDAP_SUCCESS) {
2888 return NT_STATUS_UNSUCCESSFUL;
2891 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2892 DEBUG(0, ("No group to modify!\n"));
2893 ldap_msgfree(result);
2894 return NT_STATUS_UNSUCCESSFUL;
2897 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2898 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2900 if (!init_ldap_from_group(ldap_state->ldap_struct,
2901 result, &mods, map)) {
2902 DEBUG(0, ("init_ldap_from_group failed\n"));
2903 ldap_msgfree(result);
2904 return NT_STATUS_UNSUCCESSFUL;
2907 ldap_msgfree(result);
2910 DEBUG(4, ("mods is empty: nothing to do\n"));
2911 return NT_STATUS_UNSUCCESSFUL;
2914 rc = ldapsam_modify(ldap_state, dn, mods);
2916 ldap_mods_free(mods, 1);
2918 if (rc != LDAP_SUCCESS) {
2919 char *ld_error = NULL;
2920 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2922 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
2923 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2924 SAFE_FREE(ld_error);
2927 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2928 return NT_STATUS_OK;
2931 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2934 struct ldapsam_privates *ldap_state =
2935 (struct ldapsam_privates *)methods->private_data;
2936 pstring sidstring, filter;
2937 LDAPMessage *result;
2941 const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
2942 "description", "displayName",
2944 sid_to_string(sidstring, &sid);
2945 snprintf(filter, sizeof(filter)-1,
2946 "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
2948 rc = ldapsam_search_one_group(ldap_state, filter, &result);
2950 if (rc != LDAP_SUCCESS) {
2951 return NT_STATUS_NO_SUCH_GROUP;
2954 ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
2956 ldap_msgfree(result);
2960 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
2963 struct ldapsam_privates *ldap_state =
2964 (struct ldapsam_privates *)my_methods->private_data;
2965 const char *filter = "(objectClass=sambaGroupMapping)";
2968 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
2969 LDAP_SCOPE_SUBTREE, filter,
2970 group_attr, 0, &ldap_state->result);
2972 if (rc != LDAP_SUCCESS) {
2973 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2974 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2975 ldap_msgfree(ldap_state->result);
2976 ldap_state->result = NULL;
2977 return NT_STATUS_UNSUCCESSFUL;
2980 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2981 ldap_count_entries(ldap_state->ldap_struct,
2982 ldap_state->result)));
2984 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2985 ldap_state->result);
2986 ldap_state->index = 0;
2988 return NT_STATUS_OK;
2991 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2993 ldapsam_endsampwent(my_methods);
2996 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2999 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
3000 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
3003 /* The rebind proc needs this *HACK*. We are not multithreaded, so
3004 this will work, but it's not nice. */
3005 static_ldap_state = ldap_state;
3008 if (!ldap_state->entry)
3011 ldap_state->index++;
3012 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
3014 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
3018 return NT_STATUS_OK;
3021 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
3022 enum SID_NAME_USE sid_name_use,
3023 GROUP_MAP **rmap, int *num_entries,
3024 BOOL unix_only, BOOL with_priv)
3034 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
3035 DEBUG(0, ("Unable to open passdb\n"));
3036 return NT_STATUS_ACCESS_DENIED;
3039 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
3040 if (sid_name_use != SID_NAME_UNKNOWN &&
3041 sid_name_use != map.sid_name_use) {
3042 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
3045 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
3046 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
3050 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
3052 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
3054 return NT_STATUS_UNSUCCESSFUL;
3059 mapt[entries] = map;
3064 ldapsam_endsamgrent(methods);
3066 *num_entries = entries;
3068 return NT_STATUS_OK;
3071 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3074 struct ldapsam_privates *ldap_state;
3076 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
3080 (*pdb_method)->name = "ldapsam";
3082 (*pdb_method)->setsampwent = ldapsam_setsampwent;
3083 (*pdb_method)->endsampwent = ldapsam_endsampwent;
3084 (*pdb_method)->getsampwent = ldapsam_getsampwent;
3085 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
3086 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
3087 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
3088 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
3089 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
3091 (*pdb_method)->getgrsid = ldapsam_getgrsid;
3092 (*pdb_method)->getgrgid = ldapsam_getgrgid;
3093 (*pdb_method)->getgrnam = ldapsam_getgrnam;
3094 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
3095 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
3096 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
3097 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
3099 /* TODO: Setup private data and free */
3101 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
3104 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
3105 return NT_STATUS_NO_MEMORY;
3109 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3111 ldap_state->uri = "ldap://localhost";
3114 ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, lp_workgroup());
3115 if (!ldap_state->domain_name) {
3116 return NT_STATUS_NO_MEMORY;
3119 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
3121 ldap_state->use_ntsid = True;
3123 (*pdb_method)->private_data = ldap_state;
3125 (*pdb_method)->free_private_data = free_private_data;
3127 return NT_STATUS_OK;
3130 static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3133 struct ldapsam_privates *ldap_state;
3135 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3139 (*pdb_method)->name = "ldapsam_compat";
3141 ldap_state = (*pdb_method)->private_data;
3142 ldap_state->use_ntsid = False;
3145 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3147 #ifndef WITH_LDAP_SAMCONFIG
3148 ldap_state->uri = "ldap://localhost";
3150 int ldap_port = lp_ldap_port();
3152 /* remap default port if not using SSL (ie clear or TLS) */
3153 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
3157 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);
3158 if (!ldap_state->uri) {
3159 return NT_STATUS_NO_MEMORY;
3164 return NT_STATUS_OK;
3167 static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3170 struct ldapsam_privates *ldap_state;
3171 uint32 low_idmap_uid, high_idmap_uid;
3172 uint32 low_idmap_gid, high_idmap_gid;
3174 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3178 (*pdb_method)->name = "ldapsam";
3180 ldap_state = (*pdb_method)->private_data;
3182 ldap_state->permit_non_unix_accounts = True;
3184 /* We know these uids can't turn up as algorithmic RIDs */
3185 if (!lp_idmap_uid(&low_idmap_uid, &high_idmap_uid)) {
3186 DEBUG(0, ("cannot use ldapsam_nua without 'idmap uid' range in smb.conf!\n"));
3187 return NT_STATUS_UNSUCCESSFUL;
3190 /* We know these gids can't turn up as algorithmic RIDs */
3191 if (!lp_idmap_gid(&low_idmap_gid, &high_idmap_gid)) {
3192 DEBUG(0, ("cannot use ldapsam_nua without 'wibnind gid' range in smb.conf!\n"));
3193 return NT_STATUS_UNSUCCESSFUL;
3196 ldap_state->low_allocated_user_rid=fallback_pdb_uid_to_user_rid(low_idmap_uid);
3198 ldap_state->high_allocated_user_rid=fallback_pdb_uid_to_user_rid(high_idmap_uid);
3200 ldap_state->low_allocated_group_rid=pdb_gid_to_group_rid(low_idmap_gid);
3202 ldap_state->high_allocated_group_rid=pdb_gid_to_group_rid(high_idmap_gid);
3204 return NT_STATUS_OK;
3207 NTSTATUS pdb_ldap_init(void)
3210 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
3213 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
3216 return NT_STATUS_OK;