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
33 * persistent connections: if using NSS LDAP, many connections are made
34 * however, using only one within Samba would be nice
36 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
38 * Other LDAP based login attributes: accountExpires, etc.
39 * (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
40 * structures don't have fields for some of these attributes)
42 * SSL is done, but can't get the certificate based authentication to work
43 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
46 /* NOTE: this will NOT work against an Active Directory server
47 * due to the fact that the two password fields cannot be retrieved
48 * from a server; recommend using security = domain in this situation
56 #define SAM_ACCOUNT struct sam_passwd
59 struct ldapsam_privates {
68 /* retrive-once info */
71 BOOL permit_non_unix_accounts;
80 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
82 static struct ldapsam_privates *static_ldap_state;
84 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
86 /*******************************************************************
87 find the ldap password
88 ******************************************************************/
89 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
94 *dn = smb_xstrdup(lp_ldap_admin_dn());
96 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
98 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
101 *pw=secrets_fetch(key, &size);
103 /* Upgrade 2.2 style entry */
105 char* old_style_key = strdup(*dn);
107 fstring old_style_pw;
109 if (!old_style_key) {
110 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
114 for (p=old_style_key; *p; p++)
115 if (*p == ',') *p = '/';
117 data=secrets_fetch(old_style_key, &size);
118 if (!size && size < sizeof(old_style_pw)) {
119 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
120 SAFE_FREE(old_style_key);
125 strncpy(old_style_pw, data, size);
126 old_style_pw[size] = 0;
130 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
131 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
132 SAFE_FREE(old_style_key);
136 if (!secrets_delete(old_style_key)) {
137 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
140 SAFE_FREE(old_style_key);
142 *pw = smb_xstrdup(old_style_pw);
148 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
149 "logoffTime", "kickoffTime", "cn",
150 "pwdCanChange", "pwdMustChange",
151 "displayName", "homeDrive",
152 "smbHome", "scriptPath",
153 "profilePath", "description",
154 "userWorkstations", "rid",
155 "primaryGroupID", "lmPassword",
156 "ntPassword", "acctFlags",
157 "domain", "objectClass",
158 "uidNumber", "gidNumber",
159 "homeDirectory", NULL };
161 /*******************************************************************
162 open a connection to the ldap server.
163 ******************************************************************/
164 static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
166 int rc = LDAP_SUCCESS;
168 BOOL ldap_v3 = False;
170 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
171 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
173 if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
174 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
180 /* Parse the string manually */
186 const char *p = ldap_state->uri;
187 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
189 /* skip leading "URL:" (if any) */
190 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
194 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
197 if (strequal(protocol, "ldap")) {
199 } else if (strequal(protocol, "ldaps")) {
202 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
206 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
207 DEBUG(0, ("ldap_init failed !\n"));
208 return LDAP_OPERATIONS_ERROR;
211 if (strequal(protocol, "ldaps")) {
212 #ifdef LDAP_OPT_X_TLS
213 int tls = LDAP_OPT_X_TLS_HARD;
214 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
216 DEBUG(0, ("Failed to setup a TLS session\n"));
219 DEBUG(3,("LDAPS option set...!\n"));
221 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
222 return LDAP_OPERATIONS_ERROR;
228 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
230 if (version != LDAP_VERSION3)
232 version = LDAP_VERSION3;
233 if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
241 if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
242 #ifdef LDAP_OPT_X_TLS
244 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
246 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
247 ldap_err2string(rc)));
250 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
253 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
254 return LDAP_OPERATIONS_ERROR;
257 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
258 return LDAP_OPERATIONS_ERROR;
262 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
267 /*******************************************************************
268 a rebind function for authenticated referrals
269 This version takes a void* that we can shove useful stuff in :-)
270 ******************************************************************/
271 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
273 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
274 int *methodp, int freeit, void *arg)
276 struct ldapsam_privates *ldap_state = arg;
278 /** @TODO Should we be doing something to check what servers we rebind to?
279 Could we get a referral to a machine that we don't want to give our
280 username and password to? */
284 memset(*credp, '\0', strlen(*credp));
287 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
288 ldap_state->bind_dn));
290 *whop = strdup(ldap_state->bind_dn);
292 return LDAP_NO_MEMORY;
294 *credp = strdup(ldap_state->bind_secret);
297 return LDAP_NO_MEMORY;
299 *methodp = LDAP_AUTH_SIMPLE;
303 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
305 /*******************************************************************
306 a rebind function for authenticated referrals
307 This version takes a void* that we can shove useful stuff in :-)
308 and actually does the connection.
309 ******************************************************************/
310 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
311 static int rebindproc_connect_with_state (LDAP *ldap_struct,
312 LDAP_CONST char *url,
314 ber_int_t msgid, void *arg)
316 struct ldapsam_privates *ldap_state = arg;
318 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
319 ldap_state->bind_dn));
321 /** @TODO Should we be doing something to check what servers we rebind to?
322 Could we get a referral to a machine that we don't want to give our
323 username and password to? */
325 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
329 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
331 /*******************************************************************
332 Add a rebind function for authenticated referrals
333 ******************************************************************/
334 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
336 # if LDAP_SET_REBIND_PROC_ARGS == 2
337 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
338 int *method, int freeit )
340 return rebindproc_with_state(ldap_struct, whop, credp,
341 method, freeit, static_ldap_state);
344 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
345 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
347 /*******************************************************************
348 a rebind function for authenticated referrals
349 this also does the connection, but no void*.
350 ******************************************************************/
351 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
352 # if LDAP_SET_REBIND_PROC_ARGS == 2
353 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
356 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
359 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
360 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
362 /*******************************************************************
363 connect to the ldap server under system privilege.
364 ******************************************************************/
365 static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
371 /* The rebind proc needs this *HACK*. We are not multithreaded, so
372 this will work, but it's not nice. */
373 static_ldap_state = ldap_state;
375 /* get the password */
376 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
378 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
379 return LDAP_INVALID_CREDENTIALS;
382 ldap_state->bind_dn = ldap_dn;
383 ldap_state->bind_secret = ldap_secret;
385 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
386 (OpenLDAP) doesnt' seem to support it */
388 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
389 ldap_state->uri, ldap_dn));
391 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
392 # if LDAP_SET_REBIND_PROC_ARGS == 2
393 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
395 # if LDAP_SET_REBIND_PROC_ARGS == 3
396 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
398 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
399 # if LDAP_SET_REBIND_PROC_ARGS == 2
400 ldap_set_rebind_proc(ldap_struct, &rebindproc);
402 # if LDAP_SET_REBIND_PROC_ARGS == 3
403 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
405 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
407 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
409 if (rc != LDAP_SUCCESS) {
411 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
414 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
415 ldap_dn, ldap_err2string(rc),
421 DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
425 /**********************************************************************
426 Connect to LDAP server
427 *********************************************************************/
428 static int ldapsam_open(struct ldapsam_privates *ldap_state)
431 SMB_ASSERT(ldap_state);
433 #ifndef NO_LDAP_SECURITY
434 if (geteuid() != 0) {
435 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
436 return LDAP_INSUFFICIENT_ACCESS;
440 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
441 struct sockaddr_un addr;
444 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
445 getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
446 /* the other end has died. reopen. */
447 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
448 ldap_state->ldap_struct = NULL;
449 ldap_state->last_ping = (time_t)0;
451 ldap_state->last_ping = time(NULL);
455 if (ldap_state->ldap_struct != NULL) {
456 DEBUG(5,("ldapsam_open: allready connected to the LDAP server\n"));
460 if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
464 if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
465 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
466 ldap_state->ldap_struct = NULL;
471 ldap_state->last_ping = time(NULL);
472 DEBUG(4,("The LDAP server is succesful connected\n"));
477 /**********************************************************************
478 Disconnect from LDAP server
479 *********************************************************************/
480 static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
483 return NT_STATUS_INVALID_PARAMETER;
485 if (ldap_state->ldap_struct != NULL) {
486 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
487 ldap_state->ldap_struct = NULL;
490 DEBUG(5,("The connection to the LDAP server was closed\n"));
491 /* maybe free the results here --metze */
496 static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
500 SMB_ASSERT(ldap_state && attempts);
502 if (*attempts != 0) {
503 /* we retry after 0.5, 2, 4.5, 8, 12.5, 18, 24.5 seconds */
504 msleep((((*attempts)*(*attempts))/2)*1000);
508 if ((rc = ldapsam_open(ldap_state))) {
509 DEBUG(0,("Connection to LDAP Server failed for the %d try!\n",*attempts));
517 static int ldapsam_search(struct ldapsam_privates *ldap_state,
518 const char *base, int scope, const char *filter,
519 const char *attrs[], int attrsonly,
522 int rc = LDAP_SERVER_DOWN;
525 SMB_ASSERT(ldap_state);
527 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
529 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
532 rc = ldap_search_s(ldap_state->ldap_struct, base, scope,
533 filter, attrs, attrsonly, res);
536 if (rc == LDAP_SERVER_DOWN) {
537 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
538 ldapsam_close(ldap_state);
544 static int ldapsam_modify(struct ldapsam_privates *ldap_state, char *dn, LDAPMod *attrs[])
546 int rc = LDAP_SERVER_DOWN;
552 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
554 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
557 rc = ldap_modify_s(ldap_state->ldap_struct, dn, attrs);
560 if (rc == LDAP_SERVER_DOWN) {
561 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
562 ldapsam_close(ldap_state);
568 static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
570 int rc = LDAP_SERVER_DOWN;
576 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
578 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
581 rc = ldap_add_s(ldap_state->ldap_struct, dn, attrs);
584 if (rc == LDAP_SERVER_DOWN) {
585 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
586 ldapsam_close(ldap_state);
592 static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
594 int rc = LDAP_SERVER_DOWN;
600 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
602 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
605 rc = ldap_delete_s(ldap_state->ldap_struct, dn);
608 if (rc == LDAP_SERVER_DOWN) {
609 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
610 ldapsam_close(ldap_state);
616 static int ldapsam_extended_operation(struct ldapsam_privates *ldap_state, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls, char **retoidp, struct berval **retdatap)
618 int rc = LDAP_SERVER_DOWN;
624 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
626 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
629 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
632 if (rc == LDAP_SERVER_DOWN) {
633 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
634 ldapsam_close(ldap_state);
640 /*******************************************************************
641 run the search by name.
642 ******************************************************************/
643 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, const char *filter, LDAPMessage ** result)
645 int scope = LDAP_SCOPE_SUBTREE;
648 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
650 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, filter, attr, 0, result);
652 if (rc != LDAP_SUCCESS) {
654 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
656 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s (%s)\n",
657 ld_error, ldap_err2string (rc)));
658 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
666 /*******************************************************************
667 run the search by name.
668 ******************************************************************/
669 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, const char *user,
670 LDAPMessage ** result)
673 char *escape_user = escape_ldap_string_alloc(user);
676 return LDAP_NO_MEMORY;
680 * in the filter expression, replace %u with the real name
681 * so in ldap filter, %u MUST exist :-)
683 pstrcpy(filter, lp_ldap_filter());
686 * have to use this here because $ is filtered out
691 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
692 SAFE_FREE(escape_user);
694 return ldapsam_search_one_user(ldap_state, filter, result);
697 /*******************************************************************
698 run the search by uid.
699 ******************************************************************/
700 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state,
702 LDAPMessage ** result)
708 /* Get the username from the system and look that up in the LDAP */
710 if ((user = getpwuid_alloc(uid)) == NULL) {
711 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
712 return LDAP_NO_SUCH_OBJECT;
715 pstrcpy(filter, lp_ldap_filter());
717 escape_user = escape_ldap_string_alloc(user->pw_name);
720 return LDAP_NO_MEMORY;
723 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
726 SAFE_FREE(escape_user);
728 return ldapsam_search_one_user(ldap_state, filter, result);
731 /*******************************************************************
732 run the search by rid.
733 ******************************************************************/
734 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state,
736 LDAPMessage ** result)
741 /* check if the user rid exsists, if not, try searching on the uid */
743 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
744 rc = ldapsam_search_one_user(ldap_state, filter, result);
746 if (rc != LDAP_SUCCESS)
747 rc = ldapsam_search_one_user_by_uid(ldap_state,
748 fallback_pdb_user_rid_to_uid(rid),
754 /*******************************************************************
755 search an attribute and return the first value found.
756 ******************************************************************/
757 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
758 const char *attribute, pstring value)
762 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
764 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
769 pstrcpy(value, values[0]);
770 ldap_value_free(values);
771 #ifdef DEBUG_PASSWORDS
772 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
777 /************************************************************************
778 Routine to manage the LDAPMod structure array
779 manage memory used by the array, by each struct, and values
781 ************************************************************************/
782 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
790 if (attribute == NULL || *attribute == '\0')
794 /* Why do we need this??? -- vl */
795 if (value == NULL || *value == '\0')
801 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
804 DEBUG(0, ("make_a_mod: out of memory!\n"));
810 for (i = 0; mods[i] != NULL; ++i) {
811 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
817 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
820 DEBUG(0, ("make_a_mod: out of memory!\n"));
823 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
826 DEBUG(0, ("make_a_mod: out of memory!\n"));
829 mods[i]->mod_op = modop;
830 mods[i]->mod_values = NULL;
831 mods[i]->mod_type = strdup(attribute);
838 if (mods[i]->mod_values != NULL) {
839 for (; mods[i]->mod_values[j] != NULL; j++);
841 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
842 (j + 2) * sizeof (char *));
844 if (mods[i]->mod_values == NULL) {
845 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
848 mods[i]->mod_values[j] = strdup(value);
849 mods[i]->mod_values[j + 1] = NULL;
854 /*******************************************************************
855 Delete complete object or objectclass and attrs from
856 object found in search_result depending on lp_ldap_delete_dn
857 ******************************************************************/
858 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
860 const char *objectclass,
865 LDAPMod **mods = NULL;
867 BerElement *ptr = NULL;
869 rc = ldap_count_entries(ldap_state->ldap_struct, result);
872 DEBUG(0, ("Entry must exist exactly once!\n"));
873 return NT_STATUS_UNSUCCESSFUL;
876 entry = ldap_first_entry(ldap_state->ldap_struct, result);
877 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
879 if (lp_ldap_delete_dn()) {
880 NTSTATUS ret = NT_STATUS_OK;
881 rc = ldapsam_delete(ldap_state, dn);
883 if (rc != LDAP_SUCCESS) {
884 DEBUG(0, ("Could not delete object %s\n", dn));
885 ret = NT_STATUS_UNSUCCESSFUL;
891 /* Ok, delete only the SAM attributes */
893 for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
895 name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) {
899 /* We are only allowed to delete the attributes that
902 for (attrib = attrs; *attrib != NULL; attrib++) {
903 if (StrCaseCmp(*attrib, name) == 0) {
904 DEBUG(10, ("deleting attribute %s\n", name));
905 make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
916 make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
918 rc = ldapsam_modify(ldap_state, dn, mods);
919 ldap_mods_free(mods, 1);
921 if (rc != LDAP_SUCCESS) {
923 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
926 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
927 dn, ldap_err2string(rc), ld_error));
930 return NT_STATUS_UNSUCCESSFUL;
937 /* New Interface is being implemented here */
939 /**********************************************************************
940 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
941 *********************************************************************/
942 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
943 SAM_ACCOUNT * sampass,
953 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
954 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
958 for (values=ldap_values;*values;values++) {
959 if (strcasecmp(*values, "posixAccount") == 0) {
964 if (!*values) { /*end of array, no posixAccount */
965 DEBUG(10, ("user does not have posixAcccount attributes\n"));
966 ldap_value_free(ldap_values);
969 ldap_value_free(ldap_values);
971 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir))
974 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
977 uid = (uid_t)atol(temp);
979 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
982 gid = (gid_t)atol(temp);
984 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
985 pdb_set_uid(sampass, uid, PDB_SET);
986 pdb_set_gid(sampass, gid, PDB_SET);
988 DEBUG(10, ("user has posixAcccount attributes\n"));
993 /**********************************************************************
994 Initialize SAM_ACCOUNT from an LDAP query
995 (Based on init_sam_from_buffer in pdb_tdb.c)
996 *********************************************************************/
997 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
998 SAM_ACCOUNT * sampass,
1005 pass_can_change_time,
1006 pass_must_change_time;
1021 uint8 smblmpwd[LM_HASH_LEN],
1022 smbntpwd[NT_HASH_LEN];
1023 uint16 acct_ctrl = 0,
1026 uint8 hours[MAX_HOURS_LEN];
1029 gid_t gid = getegid();
1033 * do a little initialization
1037 nt_username[0] = '\0';
1040 dir_drive[0] = '\0';
1041 logon_script[0] = '\0';
1042 profile_path[0] = '\0';
1043 acct_desc[0] = '\0';
1044 munged_dial[0] = '\0';
1045 workstations[0] = '\0';
1048 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1049 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1053 if (ldap_state->ldap_struct == NULL) {
1054 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1058 get_single_attribute(ldap_state->ldap_struct, entry, "uid", username);
1059 DEBUG(2, ("Entry found for user: %s\n", username));
1061 pstrcpy(nt_username, username);
1063 pstrcpy(domain, lp_workgroup());
1065 pdb_set_username(sampass, username, PDB_SET);
1067 pdb_set_domain(sampass, domain, PDB_DEFAULT);
1068 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1070 get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
1071 user_rid = (uint32)atol(temp);
1073 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1075 if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
1078 group_rid = (uint32)atol(temp);
1079 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1084 * If so configured, try and get the values from LDAP
1087 if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state, sampass, entry))) {
1090 * Otherwise just ask the system getpw() calls.
1093 pw = getpwnam_alloc(username);
1095 if (! ldap_state->permit_non_unix_accounts) {
1096 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
1101 pdb_set_uid(sampass, uid, PDB_SET);
1103 pdb_set_gid(sampass, gid, PDB_SET);
1105 pdb_set_unix_homedir(sampass, pw->pw_dir, PDB_SET);
1111 if (group_rid == 0 && pdb_get_init_flags(sampass,PDB_GID) != PDB_DEFAULT) {
1113 gid = pdb_get_gid(sampass);
1114 /* call the mapping code here */
1115 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1116 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1119 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1123 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1124 /* leave as default */
1126 pass_last_set_time = (time_t) atol(temp);
1127 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1130 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1131 /* leave as default */
1133 logon_time = (time_t) atol(temp);
1134 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1137 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1138 /* leave as default */
1140 logoff_time = (time_t) atol(temp);
1141 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1144 if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1145 /* leave as default */
1147 kickoff_time = (time_t) atol(temp);
1148 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1151 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1152 /* leave as default */
1154 pass_can_change_time = (time_t) atol(temp);
1155 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1158 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1159 /* leave as default */
1161 pass_must_change_time = (time_t) atol(temp);
1162 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1165 /* recommend that 'gecos' and 'displayName' should refer to the same
1166 * attribute OID. userFullName depreciated, only used by Samba
1167 * primary rules of LDAP: don't make a new attribute when one is already defined
1168 * that fits your needs; using cn then displayName rather than 'userFullName'
1171 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1172 "displayName", fullname)) {
1173 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1175 /* leave as default */
1177 pdb_set_fullname(sampass, fullname, PDB_SET);
1180 pdb_set_fullname(sampass, fullname, PDB_SET);
1183 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1184 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
1190 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1193 if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1194 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
1200 pdb_set_homedir(sampass, homedir, PDB_SET);
1203 if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1204 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
1210 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1213 if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1214 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
1220 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1223 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1224 /* leave as default */
1226 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1229 if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1230 /* leave as default */;
1232 pdb_set_workstations(sampass, workstations, PDB_SET);
1235 /* FIXME: hours stuff should be cleaner */
1239 memset(hours, 0xff, hours_len);
1241 if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1242 /* leave as default */
1244 pdb_gethexpwd(temp, smblmpwd);
1245 memset((char *)temp, '\0', strlen(temp)+1);
1246 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1248 ZERO_STRUCT(smblmpwd);
1251 if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1252 /* leave as default */
1254 pdb_gethexpwd(temp, smbntpwd);
1255 memset((char *)temp, '\0', strlen(temp)+1);
1256 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1258 ZERO_STRUCT(smbntpwd);
1261 if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1262 acct_ctrl |= ACB_NORMAL;
1264 acct_ctrl = pdb_decode_acct_ctrl(temp);
1267 acct_ctrl |= ACB_NORMAL;
1269 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1272 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1273 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1275 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1277 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1278 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1279 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1281 pdb_set_hours(sampass, hours, PDB_SET);
1286 /**********************************************************************
1287 An LDAP modification is needed in two cases:
1288 * If we are updating the record AND the attribute is CHANGED.
1289 * If we are adding the record AND it is SET or CHANGED (ie not default)
1290 *********************************************************************/
1291 static BOOL need_ldap_mod(BOOL pdb_add, const SAM_ACCOUNT * sampass, enum pdb_elements element) {
1293 return (!IS_SAM_DEFAULT(sampass, element));
1295 return IS_SAM_CHANGED(sampass, element);
1299 /**********************************************************************
1300 Set attribute to newval in LDAP, regardless of what value the
1301 attribute had in LDAP before.
1302 *********************************************************************/
1303 static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
1305 const SAM_ACCOUNT *sampass,
1306 BOOL (*need_update)(const SAM_ACCOUNT *,
1308 enum pdb_elements element,
1309 const char *attribute, const char *newval)
1311 char **values = NULL;
1313 if (!need_update(sampass, element)) {
1317 if (existing != NULL) {
1318 values = ldap_get_values(ldap_struct, existing, attribute);
1321 if ((values != NULL) && (values[0] != NULL) &&
1322 strcmp(values[0], newval) == 0) {
1324 /* Believe it or not, but LDAP will deny a delete and
1325 an add at the same time if the values are the
1328 ldap_value_free(values);
1332 /* Regardless of the real operation (add or modify)
1333 we add the new value here. We rely on deleting
1334 the old value, should it exist. */
1336 if ((newval != NULL) && (strlen(newval) > 0)) {
1337 make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
1340 if (values == NULL) {
1341 /* There has been no value before, so don't delete it.
1342 Here's a possible race: We might end up with
1343 duplicate attributes */
1347 /* By deleting exactly the value we found in the entry this
1348 should be race-free in the sense that the LDAP-Server will
1349 deny the complete operation if somebody changed the
1350 attribute behind our back. */
1352 make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
1353 ldap_value_free(values);
1356 /**********************************************************************
1357 Initialize SAM_ACCOUNT from an LDAP query
1358 (Based on init_buffer_from_sam in pdb_tdb.c)
1359 *********************************************************************/
1360 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1361 LDAPMessage *existing,
1362 LDAPMod *** mods, const SAM_ACCOUNT * sampass,
1363 BOOL (*need_update)(const SAM_ACCOUNT *,
1369 if (mods == NULL || sampass == NULL) {
1370 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1377 * took out adding "objectclass: sambaAccount"
1378 * do this on a per-mod basis
1380 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1381 PDB_USERNAME, "uid", pdb_get_username(sampass));
1382 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1384 rid = pdb_get_user_rid(sampass);
1387 if (!IS_SAM_DEFAULT(sampass, PDB_UID)) {
1388 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
1389 } else if (ldap_state->permit_non_unix_accounts) {
1390 rid = ldapsam_get_next_available_nua_rid(ldap_state);
1392 DEBUG(0, ("NO user RID specified on account %s, and "
1393 "findining next available NUA RID failed, "
1395 pdb_get_username(sampass)));
1396 ldap_mods_free(*mods, 1);
1400 DEBUG(0, ("NO user RID specified on account %s, "
1401 "cannot store!\n", pdb_get_username(sampass)));
1402 ldap_mods_free(*mods, 1);
1407 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1408 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1409 PDB_USERSID, "rid", temp);
1412 rid = pdb_get_group_rid(sampass);
1415 if (!IS_SAM_DEFAULT(sampass, PDB_GID)) {
1416 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
1417 } else if (ldap_state->permit_non_unix_accounts) {
1418 rid = DOMAIN_GROUP_RID_USERS;
1420 DEBUG(0, ("NO group RID specified on account %s, "
1421 "cannot store!\n", pdb_get_username(sampass)));
1422 ldap_mods_free(*mods, 1);
1427 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1428 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1429 PDB_GROUPSID, "primaryGroupID", temp);
1431 /* displayName, cn, and gecos should all be the same
1432 * most easily accomplished by giving them the same OID
1433 * gecos isn't set here b/c it should be handled by the
1435 * We change displayName only and fall back to cn if
1436 * it does not exist.
1439 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1440 PDB_FULLNAME, "displayName",
1441 pdb_get_fullname(sampass));
1443 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1444 PDB_ACCTDESC, "description",
1445 pdb_get_acct_desc(sampass));
1447 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1448 PDB_WORKSTATIONS, "userWorkstations",
1449 pdb_get_workstations(sampass));
1451 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1452 PDB_SMBHOME, "smbHome",
1453 pdb_get_homedir(sampass));
1455 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1456 PDB_DRIVE, "homeDrive",
1457 pdb_get_dir_drive(sampass));
1459 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1460 PDB_LOGONSCRIPT, "scriptPath",
1461 pdb_get_logon_script(sampass));
1463 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1464 PDB_PROFILE, "profilePath",
1465 pdb_get_profile_path(sampass));
1467 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1468 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1469 PDB_LOGONTIME, "logonTime", temp);
1471 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1472 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1473 PDB_LOGOFFTIME, "logoffTime", temp);
1475 slprintf (temp, sizeof (temp) - 1, "%li",
1476 pdb_get_kickoff_time(sampass));
1477 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1478 PDB_KICKOFFTIME, "kickoffTime", temp);
1480 slprintf (temp, sizeof (temp) - 1, "%li",
1481 pdb_get_pass_can_change_time(sampass));
1482 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1483 PDB_CANCHANGETIME, "pwdCanChange", temp);
1485 slprintf (temp, sizeof (temp) - 1, "%li",
1486 pdb_get_pass_must_change_time(sampass));
1487 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1488 PDB_MUSTCHANGETIME, "pwdMustChange", temp);
1490 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
1491 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1493 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass),
1494 pdb_get_acct_ctrl(sampass));
1495 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1496 PDB_LMPASSWD, "lmPassword", temp);
1498 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
1499 pdb_get_acct_ctrl(sampass));
1500 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1501 PDB_NTPASSWD, "ntPassword", temp);
1503 slprintf (temp, sizeof (temp) - 1, "%li",
1504 pdb_get_pass_last_set_time(sampass));
1505 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1506 PDB_PASSLASTSET, "pwdLastSet", temp);
1509 /* FIXME: Hours stuff goes in LDAP */
1510 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1511 PDB_ACCTCTRL, "acctFlags",
1512 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
1513 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1518 /**********************************************************************
1519 Connect to LDAP server and find the next available RID.
1520 *********************************************************************/
1521 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid)
1523 LDAPMessage *result;
1524 uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
1529 if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
1533 if (ldapsam_search_one_user_by_rid(ldap_state, final_rid, &result) != LDAP_SUCCESS) {
1534 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
1538 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
1539 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
1540 ldap_msgfree(result);
1544 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
1545 ldap_msgfree(result);
1549 /**********************************************************************
1550 Extract the RID from an LDAP entry
1551 *********************************************************************/
1552 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry) {
1554 SAM_ACCOUNT *user = NULL;
1555 if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
1559 if (init_sam_from_ldap(ldap_state, user, entry)) {
1560 rid = pdb_get_user_rid(user);
1564 pdb_free_sam(&user);
1565 if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
1572 /**********************************************************************
1573 Connect to LDAP server and find the next available RID.
1574 *********************************************************************/
1575 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state)
1579 LDAPMessage *result;
1581 char *final_filter = NULL;
1586 pstrcpy(filter, lp_ldap_filter());
1587 all_string_sub(filter, "%u", "*", sizeof(pstring));
1590 asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1592 final_filter = strdup(filter);
1594 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1596 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1597 LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1600 if (rc != LDAP_SUCCESS) {
1601 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1602 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1609 count = ldap_count_entries(ldap_state->ldap_struct, result);
1610 DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1613 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1614 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1616 ldap_msgfree(result);
1618 return ldap_state->low_nua_rid;
1622 entry = ldap_first_entry(ldap_state->ldap_struct,result);
1624 top_rid = entry_to_user_rid(ldap_state, entry);
1626 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1628 rid = entry_to_user_rid(ldap_state, entry);
1629 if (rid > top_rid) {
1634 ldap_msgfree(result);
1636 if (top_rid < ldap_state->low_nua_rid)
1637 top_rid = ldap_state->low_nua_rid;
1642 /**********************************************************************
1643 Connect to LDAP server and find the next available RID.
1644 *********************************************************************/
1645 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1646 uint32 next_nua_rid;
1649 top_nua_rid = search_top_nua_rid(ldap_state);
1651 next_nua_rid = check_nua_rid_is_avail(ldap_state,
1654 return next_nua_rid;
1657 /**********************************************************************
1658 Connect to LDAP server for password enumeration
1659 *********************************************************************/
1660 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1662 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1666 pstrcpy(filter, lp_ldap_filter());
1667 all_string_sub(filter, "%u", "*", sizeof(pstring));
1669 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1670 LDAP_SCOPE_SUBTREE, filter, attr, 0,
1671 &ldap_state->result);
1673 if (rc != LDAP_SUCCESS) {
1674 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1675 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1676 ldap_msgfree(ldap_state->result);
1677 ldap_state->result = NULL;
1678 return NT_STATUS_UNSUCCESSFUL;
1681 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1682 ldap_count_entries(ldap_state->ldap_struct,
1683 ldap_state->result)));
1685 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1686 ldap_state->result);
1687 ldap_state->index = 0;
1689 return NT_STATUS_OK;
1692 /**********************************************************************
1693 End enumeration of the LDAP password list
1694 *********************************************************************/
1695 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1697 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1698 if (ldap_state->result) {
1699 ldap_msgfree(ldap_state->result);
1700 ldap_state->result = NULL;
1704 /**********************************************************************
1705 Get the next entry in the LDAP password database
1706 *********************************************************************/
1707 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1709 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1710 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1713 /* The rebind proc needs this *HACK*. We are not multithreaded, so
1714 this will work, but it's not nice. */
1715 static_ldap_state = ldap_state;
1718 if (!ldap_state->entry)
1721 ldap_state->index++;
1722 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1724 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1728 return NT_STATUS_OK;
1731 /**********************************************************************
1732 Get SAM_ACCOUNT entry from LDAP by username
1733 *********************************************************************/
1734 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1736 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1737 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1738 LDAPMessage *result;
1742 if (ldapsam_search_one_user_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
1743 return NT_STATUS_NO_SUCH_USER;
1746 count = ldap_count_entries(ldap_state->ldap_struct, result);
1750 ("We don't find this user [%s] count=%d\n", sname,
1752 return NT_STATUS_NO_SUCH_USER;
1753 } else if (count > 1) {
1755 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
1757 return NT_STATUS_NO_SUCH_USER;
1760 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1762 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1763 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1764 ldap_msgfree(result);
1765 return NT_STATUS_NO_SUCH_USER;
1767 ldap_msgfree(result);
1770 ldap_msgfree(result);
1775 /**********************************************************************
1776 Get SAM_ACCOUNT entry from LDAP by rid
1777 *********************************************************************/
1778 static NTSTATUS ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
1780 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1781 struct ldapsam_privates *ldap_state =
1782 (struct ldapsam_privates *)my_methods->private_data;
1783 LDAPMessage *result;
1787 if (ldapsam_search_one_user_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
1788 return NT_STATUS_NO_SUCH_USER;
1791 count = ldap_count_entries(ldap_state->ldap_struct, result);
1795 ("We don't find this rid [%i] count=%d\n", rid,
1797 return NT_STATUS_NO_SUCH_USER;
1798 } else if (count > 1) {
1800 ("More than one user with rid [%i]. Failing. count=%d\n", rid,
1802 return NT_STATUS_NO_SUCH_USER;
1805 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1807 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1808 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1809 ldap_msgfree(result);
1810 return NT_STATUS_NO_SUCH_USER;
1812 ldap_msgfree(result);
1815 ldap_msgfree(result);
1820 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1823 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
1824 return NT_STATUS_NO_SUCH_USER;
1825 return ldapsam_getsampwrid(my_methods, user, rid);
1828 /********************************************************************
1829 Do the actual modification - also change a plaittext passord if
1831 **********************************************************************/
1833 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
1834 SAM_ACCOUNT *newpwd, char *dn,
1835 LDAPMod **mods, int ldap_op, BOOL pdb_add)
1837 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1840 if (!my_methods || !newpwd || !dn) {
1841 return NT_STATUS_INVALID_PARAMETER;
1845 DEBUG(5,("mods is empty: nothing to modify\n"));
1846 /* may be password change below however */
1851 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
1852 rc = ldapsam_add(ldap_state, dn, mods);
1854 case LDAP_MOD_REPLACE:
1855 rc = ldapsam_modify(ldap_state, dn ,mods);
1858 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1859 return NT_STATUS_UNSUCCESSFUL;
1862 if (rc!=LDAP_SUCCESS) {
1864 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1867 ("failed to %s user dn= %s with: %s\n\t%s\n",
1868 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1869 dn, ldap_err2string(rc),
1872 return NT_STATUS_UNSUCCESSFUL;
1876 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1877 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))&&
1878 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&
1879 need_ldap_mod(pdb_add, newpwd, PDB_PLAINTEXT_PW)&&
1880 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1884 struct berval *retdata;
1886 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1887 DEBUG(0,("ber_alloc_t returns NULL\n"));
1888 return NT_STATUS_UNSUCCESSFUL;
1890 ber_printf (ber, "{");
1891 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
1892 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, pdb_get_plaintext_passwd(newpwd));
1893 ber_printf (ber, "N}");
1895 if ((rc = ber_flatten (ber, &bv))<0) {
1896 DEBUG(0,("ber_flatten returns a value <0\n"));
1897 return NT_STATUS_UNSUCCESSFUL;
1902 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
1903 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
1904 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1905 pdb_get_username(newpwd),ldap_err2string(rc)));
1907 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1909 ber_bvfree(retdata);
1910 ber_memfree(retoid);
1915 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
1916 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
1917 return NT_STATUS_OK;
1920 /**********************************************************************
1921 Delete entry from LDAP for username
1922 *********************************************************************/
1923 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1925 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1928 LDAPMessage *result;
1930 const char *sam_user_attrs[] =
1931 { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
1932 "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
1933 "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
1934 "userWorkstations", "primaryGroupID", "domain", "rid", NULL };
1937 DEBUG(0, ("sam_acct was NULL!\n"));
1938 return NT_STATUS_INVALID_PARAMETER;
1941 sname = pdb_get_username(sam_acct);
1943 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1945 rc = ldapsam_search_one_user_by_name(ldap_state, sname, &result);
1946 if (rc != LDAP_SUCCESS) {
1947 return NT_STATUS_NO_SUCH_USER;
1950 ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
1952 ldap_msgfree(result);
1956 /**********************************************************************
1957 Helper function to determine for update_sam_account whether
1958 we need LDAP modification.
1959 *********************************************************************/
1960 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
1961 enum pdb_elements element)
1963 return IS_SAM_CHANGED(sampass, element);
1966 /**********************************************************************
1968 *********************************************************************/
1969 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1971 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1972 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1975 LDAPMessage *result;
1979 rc = ldapsam_search_one_user_by_name(ldap_state, pdb_get_username(newpwd), &result);
1980 if (rc != LDAP_SUCCESS) {
1981 return NT_STATUS_UNSUCCESSFUL;
1984 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
1985 DEBUG(0, ("No user to modify!\n"));
1986 ldap_msgfree(result);
1987 return NT_STATUS_UNSUCCESSFUL;
1990 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1991 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
1993 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1994 element_is_changed)) {
1995 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1996 ldap_msgfree(result);
1997 return NT_STATUS_UNSUCCESSFUL;
2000 ldap_msgfree(result);
2003 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2004 pdb_get_username(newpwd)));
2005 ldap_mods_free(mods, 1);
2006 return NT_STATUS_OK;
2009 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, False);
2010 ldap_mods_free(mods,1);
2012 if (!NT_STATUS_IS_OK(ret)) {
2014 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2016 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2017 pdb_get_username(newpwd), ld_error, ldap_err2string(rc)));
2018 SAFE_FREE(ld_error);
2022 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2023 pdb_get_username(newpwd)));
2024 return NT_STATUS_OK;
2027 /**********************************************************************
2028 Helper function to determine for update_sam_account whether
2029 we need LDAP modification.
2030 *********************************************************************/
2031 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2032 enum pdb_elements element)
2034 return (IS_SAM_SET(sampass, element) ||
2035 IS_SAM_CHANGED(sampass, element));
2038 /**********************************************************************
2039 Add SAM_ACCOUNT to LDAP
2040 *********************************************************************/
2041 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2043 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2044 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2047 LDAPMessage *result = NULL;
2048 LDAPMessage *entry = NULL;
2050 LDAPMod **mods = NULL;
2054 const char *username = pdb_get_username(newpwd);
2055 if (!username || !*username) {
2056 DEBUG(0, ("Cannot add user without a username!\n"));
2057 return NT_STATUS_INVALID_PARAMETER;
2060 rc = ldapsam_search_one_user_by_name (ldap_state, username, &result);
2061 if (rc != LDAP_SUCCESS) {
2062 return NT_STATUS_UNSUCCESSFUL;
2065 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2066 DEBUG(0,("User '%s' already in the base, with samba properties\n",
2068 ldap_msgfree(result);
2069 return NT_STATUS_UNSUCCESSFUL;
2071 ldap_msgfree(result);
2073 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
2074 rc = ldapsam_search_one_user(ldap_state, filter, &result);
2075 if (rc != LDAP_SUCCESS) {
2076 return NT_STATUS_UNSUCCESSFUL;
2079 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2081 if (num_result > 1) {
2082 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2083 ldap_msgfree(result);
2084 return NT_STATUS_UNSUCCESSFUL;
2087 /* Check if we need to update an existing entry */
2088 if (num_result == 1) {
2091 DEBUG(3,("User exists without samba properties: adding them\n"));
2092 ldap_op = LDAP_MOD_REPLACE;
2093 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2094 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2095 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2098 /* Check if we need to add an entry */
2099 DEBUG(3,("Adding new user\n"));
2100 ldap_op = LDAP_MOD_ADD;
2101 if (username[strlen(username)-1] == '$') {
2102 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2104 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2108 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2109 element_is_set_or_changed)) {
2110 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2111 ldap_msgfree(result);
2112 ldap_mods_free(mods, 1);
2113 return NT_STATUS_UNSUCCESSFUL;
2116 ldap_msgfree(result);
2119 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2120 return NT_STATUS_UNSUCCESSFUL;
2123 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
2125 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, True);
2126 if (NT_STATUS_IS_ERR(ret)) {
2127 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2128 pdb_get_username(newpwd),dn));
2129 ldap_mods_free(mods,1);
2133 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
2134 ldap_mods_free(mods, 1);
2135 return NT_STATUS_OK;
2138 static void free_private_data(void **vp)
2140 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2142 ldapsam_close(*ldap_state);
2144 if ((*ldap_state)->bind_secret) {
2145 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2148 ldapsam_close(*ldap_state);
2150 SAFE_FREE((*ldap_state)->bind_dn);
2151 SAFE_FREE((*ldap_state)->bind_secret);
2155 /* No need to free any further, as it is talloc()ed */
2158 static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
2160 "displayName", "description",
2163 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2165 LDAPMessage ** result)
2167 int scope = LDAP_SCOPE_SUBTREE;
2170 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2172 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
2173 filter, group_attr, 0, result);
2175 if (rc != LDAP_SUCCESS) {
2177 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2179 DEBUG(0, ("ldapsam_search_one_group: "
2180 "Problem during the LDAP search: LDAP error: %s (%s)",
2181 ld_error, ldap_err2string(rc)));
2182 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2183 lp_ldap_suffix(), filter));
2184 SAFE_FREE(ld_error);
2190 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2191 GROUP_MAP *map, LDAPMessage *entry)
2195 if (ldap_state == NULL || map == NULL || entry == NULL ||
2196 ldap_state->ldap_struct == NULL) {
2197 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2201 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
2203 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
2206 DEBUG(2, ("Entry found for group: %s\n", temp));
2208 map->gid = (gid_t)atol(temp);
2210 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
2212 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
2215 string_to_sid(&map->sid, temp);
2217 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
2219 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
2222 map->sid_name_use = (uint32)atol(temp);
2224 if ((map->sid_name_use < SID_NAME_USER) ||
2225 (map->sid_name_use > SID_NAME_UNKNOWN)) {
2226 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2230 if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
2232 DEBUG(3, ("Attribute displayName not found\n"));
2234 if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn",
2236 DEBUG(0, ("Attributes cn not found either "
2237 "for gidNumber(%i)\n",map->gid));
2241 fstrcpy(map->nt_name, temp);
2243 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
2245 DEBUG(3, ("Attribute description not found\n"));
2248 fstrcpy(map->comment, temp);
2250 map->systemaccount = 0;
2251 init_privilege(&map->priv_set);
2256 static BOOL init_ldap_from_group(struct ldapsam_privates *ldap_state,
2257 LDAPMod ***mods, int ldap_op,
2258 const GROUP_MAP *map)
2262 if (mods == NULL || map == NULL) {
2263 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2269 sid_to_string(tmp, &map->sid);
2270 make_a_mod(mods, ldap_op, "ntSid", tmp);
2272 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2273 make_a_mod(mods, ldap_op, "ntGroupType", tmp);
2275 make_a_mod(mods, ldap_op, "displayName", map->nt_name);
2276 make_a_mod(mods, ldap_op, "description", map->comment);
2281 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2285 struct ldapsam_privates *ldap_state =
2286 (struct ldapsam_privates *)methods->private_data;
2287 LDAPMessage *result;
2291 if (ldapsam_search_one_group(ldap_state, filter, &result)
2293 return NT_STATUS_NO_SUCH_GROUP;
2296 count = ldap_count_entries(ldap_state->ldap_struct, result);
2299 DEBUG(4, ("Did not find group for filter %s\n", filter));
2300 return NT_STATUS_NO_SUCH_GROUP;
2304 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2306 return NT_STATUS_NO_SUCH_GROUP;
2309 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2312 ldap_msgfree(result);
2313 return NT_STATUS_UNSUCCESSFUL;
2316 if (!init_group_from_ldap(ldap_state, map, entry)) {
2317 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2319 ldap_msgfree(result);
2320 return NT_STATUS_NO_SUCH_GROUP;
2323 ldap_msgfree(result);
2324 return NT_STATUS_OK;
2327 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2328 DOM_SID sid, BOOL with_priv)
2332 snprintf(filter, sizeof(filter)-1,
2333 "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
2334 sid_string_static(&sid));
2336 return ldapsam_getgroup(methods, filter, map);
2339 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2340 gid_t gid, BOOL with_priv)
2344 snprintf(filter, sizeof(filter)-1,
2345 "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
2348 return ldapsam_getgroup(methods, filter, map);
2351 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2352 char *name, BOOL with_priv)
2356 /* TODO: Escaping of name? */
2358 snprintf(filter, sizeof(filter)-1,
2359 "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
2362 return ldapsam_getgroup(methods, filter, map);
2365 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2367 LDAPMessage **result)
2371 snprintf(filter, sizeof(filter)-1,
2372 "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
2374 return ldapsam_search_one_group(ldap_state, filter, result);
2377 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2380 struct ldapsam_privates *ldap_state =
2381 (struct ldapsam_privates *)methods->private_data;
2382 LDAPMessage *result = NULL;
2383 LDAPMod **mods = NULL;
2393 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2394 map->gid, False))) {
2395 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2396 return NT_STATUS_UNSUCCESSFUL;
2399 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2400 if (rc != LDAP_SUCCESS) {
2401 return NT_STATUS_UNSUCCESSFUL;
2404 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
2405 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
2407 ldap_msgfree(result);
2408 return NT_STATUS_UNSUCCESSFUL;
2411 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2412 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
2415 ldap_msgfree(result);
2417 if (!init_ldap_from_group(ldap_state, &mods, LDAP_MOD_ADD, map)) {
2418 DEBUG(0, ("init_ldap_from_group failed!\n"));
2419 ldap_mods_free(mods, 1);
2420 return NT_STATUS_UNSUCCESSFUL;
2424 DEBUG(0, ("mods is empty\n"));
2425 return NT_STATUS_UNSUCCESSFUL;
2428 make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
2429 "sambaGroupMapping");
2431 rc = ldapsam_modify(ldap_state, dn, mods);
2432 ldap_mods_free(mods, 1);
2434 if (rc != LDAP_SUCCESS) {
2436 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2438 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
2439 ld_error, ldap_err2string(rc)));
2440 SAFE_FREE(ld_error);
2441 return NT_STATUS_UNSUCCESSFUL;
2444 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2445 return NT_STATUS_OK;
2448 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2451 struct ldapsam_privates *ldap_state =
2452 (struct ldapsam_privates *)methods->private_data;
2455 LDAPMessage *result;
2459 if (!init_ldap_from_group(ldap_state, &mods, LDAP_MOD_REPLACE, map)) {
2460 DEBUG(0, ("init_ldap_from_group failed\n"));
2461 return NT_STATUS_UNSUCCESSFUL;
2465 DEBUG(4, ("mods is empty: nothing to do\n"));
2466 return NT_STATUS_UNSUCCESSFUL;
2469 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2471 if (rc != LDAP_SUCCESS) {
2472 ldap_mods_free(mods, 1);
2473 return NT_STATUS_UNSUCCESSFUL;
2476 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2477 DEBUG(0, ("No group to modify!\n"));
2478 ldap_msgfree(result);
2479 ldap_mods_free(mods, 1);
2480 return NT_STATUS_UNSUCCESSFUL;
2483 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2484 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2485 ldap_msgfree(result);
2487 rc = ldapsam_modify(ldap_state, dn, mods);
2489 ldap_mods_free(mods, 1);
2491 if (rc != LDAP_SUCCESS) {
2493 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2495 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
2496 ld_error, ldap_err2string(rc)));
2497 SAFE_FREE(ld_error);
2500 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2501 return NT_STATUS_OK;
2504 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2507 struct ldapsam_privates *ldap_state =
2508 (struct ldapsam_privates *)methods->private_data;
2509 pstring sidstring, filter;
2510 LDAPMessage *result;
2514 const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
2515 "description", "displayName",
2517 sid_to_string(sidstring, &sid);
2518 snprintf(filter, sizeof(filter)-1,
2519 "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
2521 rc = ldapsam_search_one_group(ldap_state, filter, &result);
2523 if (rc != LDAP_SUCCESS) {
2524 return NT_STATUS_NO_SUCH_GROUP;
2527 ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
2529 ldap_msgfree(result);
2533 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
2536 struct ldapsam_privates *ldap_state =
2537 (struct ldapsam_privates *)my_methods->private_data;
2538 const char *filter = "(objectClass=sambaGroupMapping)";
2541 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
2542 LDAP_SCOPE_SUBTREE, filter,
2543 group_attr, 0, &ldap_state->result);
2545 if (rc != LDAP_SUCCESS) {
2546 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2547 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2548 ldap_msgfree(ldap_state->result);
2549 ldap_state->result = NULL;
2550 return NT_STATUS_UNSUCCESSFUL;
2553 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2554 ldap_count_entries(ldap_state->ldap_struct,
2555 ldap_state->result)));
2557 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2558 ldap_state->result);
2559 ldap_state->index = 0;
2561 return NT_STATUS_OK;
2564 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2566 ldapsam_endsampwent(my_methods);
2569 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2572 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2573 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2576 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2577 this will work, but it's not nice. */
2578 static_ldap_state = ldap_state;
2581 if (!ldap_state->entry)
2584 ldap_state->index++;
2585 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2587 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2591 return NT_STATUS_OK;
2594 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2595 enum SID_NAME_USE sid_name_use,
2596 GROUP_MAP **rmap, int *num_entries,
2597 BOOL unix_only, BOOL with_priv)
2607 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2608 DEBUG(0, ("Unable to open passdb\n"));
2609 return NT_STATUS_ACCESS_DENIED;
2612 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
2613 if (sid_name_use != SID_NAME_UNKNOWN &&
2614 sid_name_use != map.sid_name_use) {
2615 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2618 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2619 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
2623 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2625 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
2627 return NT_STATUS_UNSUCCESSFUL;
2632 mapt[entries] = map;
2637 ldapsam_endsamgrent(methods);
2639 *num_entries = entries;
2641 return NT_STATUS_OK;
2644 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2647 struct ldapsam_privates *ldap_state;
2649 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2653 (*pdb_method)->name = "ldapsam";
2655 (*pdb_method)->setsampwent = ldapsam_setsampwent;
2656 (*pdb_method)->endsampwent = ldapsam_endsampwent;
2657 (*pdb_method)->getsampwent = ldapsam_getsampwent;
2658 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2659 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2660 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2661 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2662 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2664 (*pdb_method)->getgrsid = ldapsam_getgrsid;
2665 (*pdb_method)->getgrgid = ldapsam_getgrgid;
2666 (*pdb_method)->getgrnam = ldapsam_getgrnam;
2667 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2668 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2669 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2670 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2672 /* TODO: Setup private data and free */
2674 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
2677 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2678 return NT_STATUS_NO_MEMORY;
2682 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
2683 #ifdef WITH_LDAP_SAMCONFIG
2685 int ldap_port = lp_ldap_port();
2687 /* remap default port if not using SSL (ie clear or TLS) */
2688 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2692 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);
2693 if (!ldap_state->uri) {
2694 return NT_STATUS_NO_MEMORY;
2698 ldap_state->uri = "ldap://localhost";
2702 (*pdb_method)->private_data = ldap_state;
2704 (*pdb_method)->free_private_data = free_private_data;
2706 return NT_STATUS_OK;
2709 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2712 struct ldapsam_privates *ldap_state;
2713 uint32 low_nua_uid, high_nua_uid;
2715 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
2719 (*pdb_method)->name = "ldapsam_nua";
2721 ldap_state = (*pdb_method)->private_data;
2723 ldap_state->permit_non_unix_accounts = True;
2725 if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
2726 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
2727 return NT_STATUS_UNSUCCESSFUL;
2730 ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
2732 ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
2734 return NT_STATUS_OK;
2740 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2742 DEBUG(0, ("ldap not detected at configure time, ldapsam not availalble!\n"));
2743 return NT_STATUS_UNSUCCESSFUL;
2746 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2748 DEBUG(0, ("ldap not dectected at configure time, ldapsam_nua not available!\n"));
2749 return NT_STATUS_UNSUCCESSFUL;