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
55 #define SAM_ACCOUNT struct sam_passwd
58 struct ldapsam_privates {
67 /* retrive-once info */
70 BOOL permit_non_unix_accounts;
79 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
81 static struct ldapsam_privates *static_ldap_state;
83 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
85 /*******************************************************************
86 find the ldap password
87 ******************************************************************/
88 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
93 *dn = smb_xstrdup(lp_ldap_admin_dn());
95 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
97 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
100 *pw=secrets_fetch(key, &size);
102 /* Upgrade 2.2 style entry */
104 char* old_style_key = strdup(*dn);
106 fstring old_style_pw;
108 if (!old_style_key) {
109 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
113 for (p=old_style_key; *p; p++)
114 if (*p == ',') *p = '/';
116 data=secrets_fetch(old_style_key, &size);
117 if (!size && size < sizeof(old_style_pw)) {
118 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
119 SAFE_FREE(old_style_key);
124 strncpy(old_style_pw, data, size);
125 old_style_pw[size] = 0;
129 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
130 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
131 SAFE_FREE(old_style_key);
135 if (!secrets_delete(old_style_key)) {
136 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
139 SAFE_FREE(old_style_key);
141 *pw = smb_xstrdup(old_style_pw);
147 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
148 "logoffTime", "kickoffTime", "cn",
149 "pwdCanChange", "pwdMustChange",
150 "displayName", "homeDrive",
151 "smbHome", "scriptPath",
152 "profilePath", "description",
153 "userWorkstations", "rid",
154 "primaryGroupID", "lmPassword",
155 "ntPassword", "acctFlags",
156 "domain", "objectClass",
157 "uidNumber", "gidNumber",
158 "homeDirectory", NULL };
160 /*******************************************************************
161 open a connection to the ldap server.
162 ******************************************************************/
163 static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
165 int rc = LDAP_SUCCESS;
167 BOOL ldap_v3 = False;
169 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
170 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
172 if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
173 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
179 /* Parse the string manually */
185 const char *p = ldap_state->uri;
186 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
188 /* skip leading "URL:" (if any) */
189 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
193 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
196 if (strequal(protocol, "ldap")) {
198 } else if (strequal(protocol, "ldaps")) {
201 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
205 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
206 DEBUG(0, ("ldap_init failed !\n"));
207 return LDAP_OPERATIONS_ERROR;
210 if (strequal(protocol, "ldaps")) {
211 #ifdef LDAP_OPT_X_TLS
212 int tls = LDAP_OPT_X_TLS_HARD;
213 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
215 DEBUG(0, ("Failed to setup a TLS session\n"));
218 DEBUG(3,("LDAPS option set...!\n"));
220 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
221 return LDAP_OPERATIONS_ERROR;
227 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
229 if (version != LDAP_VERSION3)
231 version = LDAP_VERSION3;
232 if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
240 if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
241 #ifdef LDAP_OPT_X_TLS
243 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
245 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
246 ldap_err2string(rc)));
249 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
252 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
253 return LDAP_OPERATIONS_ERROR;
256 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
257 return LDAP_OPERATIONS_ERROR;
261 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
266 /*******************************************************************
267 a rebind function for authenticated referrals
268 This version takes a void* that we can shove useful stuff in :-)
269 ******************************************************************/
270 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
272 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
273 int *methodp, int freeit, void *arg)
275 struct ldapsam_privates *ldap_state = arg;
277 /** @TODO Should we be doing something to check what servers we rebind to?
278 Could we get a referral to a machine that we don't want to give our
279 username and password to? */
283 memset(*credp, '\0', strlen(*credp));
286 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
287 ldap_state->bind_dn));
289 *whop = strdup(ldap_state->bind_dn);
291 return LDAP_NO_MEMORY;
293 *credp = strdup(ldap_state->bind_secret);
296 return LDAP_NO_MEMORY;
298 *methodp = LDAP_AUTH_SIMPLE;
302 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
304 /*******************************************************************
305 a rebind function for authenticated referrals
306 This version takes a void* that we can shove useful stuff in :-)
307 and actually does the connection.
308 ******************************************************************/
309 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
310 static int rebindproc_connect_with_state (LDAP *ldap_struct,
311 LDAP_CONST char *url,
313 ber_int_t msgid, void *arg)
315 struct ldapsam_privates *ldap_state = arg;
317 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
318 ldap_state->bind_dn));
320 /** @TODO Should we be doing something to check what servers we rebind to?
321 Could we get a referral to a machine that we don't want to give our
322 username and password to? */
324 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
328 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
330 /*******************************************************************
331 Add a rebind function for authenticated referrals
332 ******************************************************************/
333 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
335 # if LDAP_SET_REBIND_PROC_ARGS == 2
336 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
337 int *method, int freeit )
339 return rebindproc_with_state(ldap_struct, whop, credp,
340 method, freeit, static_ldap_state);
343 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
344 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
346 /*******************************************************************
347 a rebind function for authenticated referrals
348 this also does the connection, but no void*.
349 ******************************************************************/
350 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
351 # if LDAP_SET_REBIND_PROC_ARGS == 2
352 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
355 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
358 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
359 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
361 /*******************************************************************
362 connect to the ldap server under system privilege.
363 ******************************************************************/
364 static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
370 /* The rebind proc needs this *HACK*. We are not multithreaded, so
371 this will work, but it's not nice. */
372 static_ldap_state = ldap_state;
374 /* get the password */
375 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
377 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
378 return LDAP_INVALID_CREDENTIALS;
381 ldap_state->bind_dn = ldap_dn;
382 ldap_state->bind_secret = ldap_secret;
384 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
385 (OpenLDAP) doesnt' seem to support it */
387 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
388 ldap_state->uri, ldap_dn));
390 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
391 # if LDAP_SET_REBIND_PROC_ARGS == 2
392 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
394 # if LDAP_SET_REBIND_PROC_ARGS == 3
395 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
397 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
398 # if LDAP_SET_REBIND_PROC_ARGS == 2
399 ldap_set_rebind_proc(ldap_struct, &rebindproc);
401 # if LDAP_SET_REBIND_PROC_ARGS == 3
402 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
404 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
406 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
408 if (rc != LDAP_SUCCESS) {
410 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
413 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
414 ldap_dn, ldap_err2string(rc),
420 DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
424 /**********************************************************************
425 Connect to LDAP server
426 *********************************************************************/
427 static int ldapsam_open(struct ldapsam_privates *ldap_state)
430 SMB_ASSERT(ldap_state);
432 #ifndef NO_LDAP_SECURITY
433 if (geteuid() != 0) {
434 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
435 return LDAP_INSUFFICIENT_ACCESS;
439 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
440 struct sockaddr_un addr;
443 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
444 getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
445 /* the other end has died. reopen. */
446 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
447 ldap_state->ldap_struct = NULL;
448 ldap_state->last_ping = (time_t)0;
450 ldap_state->last_ping = time(NULL);
454 if (ldap_state->ldap_struct != NULL) {
455 DEBUG(5,("ldapsam_open: allready connected to the LDAP server\n"));
459 if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
463 if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
464 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
465 ldap_state->ldap_struct = NULL;
470 ldap_state->last_ping = time(NULL);
471 DEBUG(4,("The LDAP server is succesful connected\n"));
476 /**********************************************************************
477 Disconnect from LDAP server
478 *********************************************************************/
479 static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
482 return NT_STATUS_INVALID_PARAMETER;
484 if (ldap_state->ldap_struct != NULL) {
485 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
486 ldap_state->ldap_struct = NULL;
489 DEBUG(5,("The connection to the LDAP server was closed\n"));
490 /* maybe free the results here --metze */
495 static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
499 SMB_ASSERT(ldap_state && attempts);
501 if (*attempts != 0) {
502 /* we retry after 0.5, 2, 4.5, 8, 12.5, 18, 24.5 seconds */
503 msleep((((*attempts)*(*attempts))/2)*1000);
507 if ((rc = ldapsam_open(ldap_state))) {
508 DEBUG(0,("Connection to LDAP Server failed for the %d try!\n",*attempts));
516 static int ldapsam_search(struct ldapsam_privates *ldap_state,
517 const char *base, int scope, const char *filter,
518 const char *attrs[], int attrsonly,
521 int rc = LDAP_SERVER_DOWN;
524 SMB_ASSERT(ldap_state);
526 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
528 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
531 rc = ldap_search_s(ldap_state->ldap_struct, base, scope,
532 filter, attrs, attrsonly, res);
535 if (rc == LDAP_SERVER_DOWN) {
536 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
537 ldapsam_close(ldap_state);
543 static int ldapsam_modify(struct ldapsam_privates *ldap_state, char *dn, LDAPMod *attrs[])
545 int rc = LDAP_SERVER_DOWN;
551 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
553 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
556 rc = ldap_modify_s(ldap_state->ldap_struct, dn, attrs);
559 if (rc == LDAP_SERVER_DOWN) {
560 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
561 ldapsam_close(ldap_state);
567 static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
569 int rc = LDAP_SERVER_DOWN;
575 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
577 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
580 rc = ldap_add_s(ldap_state->ldap_struct, dn, attrs);
583 if (rc == LDAP_SERVER_DOWN) {
584 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
585 ldapsam_close(ldap_state);
591 static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
593 int rc = LDAP_SERVER_DOWN;
599 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
601 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
604 rc = ldap_delete_s(ldap_state->ldap_struct, dn);
607 if (rc == LDAP_SERVER_DOWN) {
608 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
609 ldapsam_close(ldap_state);
615 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)
617 int rc = LDAP_SERVER_DOWN;
623 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
625 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
628 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
631 if (rc == LDAP_SERVER_DOWN) {
632 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
633 ldapsam_close(ldap_state);
639 /*******************************************************************
640 run the search by name.
641 ******************************************************************/
642 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, const char *filter, LDAPMessage ** result)
644 int scope = LDAP_SCOPE_SUBTREE;
647 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
649 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, filter, attr, 0, result);
651 if (rc != LDAP_SUCCESS) {
652 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n",
653 ldap_err2string (rc)));
654 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
661 /*******************************************************************
662 run the search by name.
663 ******************************************************************/
664 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, const char *user,
665 LDAPMessage ** result)
668 char *escape_user = escape_ldap_string_alloc(user);
671 return LDAP_NO_MEMORY;
675 * in the filter expression, replace %u with the real name
676 * so in ldap filter, %u MUST exist :-)
678 pstrcpy(filter, lp_ldap_filter());
681 * have to use this here because $ is filtered out
686 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
687 SAFE_FREE(escape_user);
689 return ldapsam_search_one_user(ldap_state, filter, result);
692 /*******************************************************************
693 run the search by uid.
694 ******************************************************************/
695 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state,
697 LDAPMessage ** result)
703 /* Get the username from the system and look that up in the LDAP */
705 if ((user = getpwuid_alloc(uid)) == NULL) {
706 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
707 return LDAP_NO_SUCH_OBJECT;
710 pstrcpy(filter, lp_ldap_filter());
712 escape_user = escape_ldap_string_alloc(user->pw_name);
715 return LDAP_NO_MEMORY;
718 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
721 SAFE_FREE(escape_user);
723 return ldapsam_search_one_user(ldap_state, filter, result);
726 /*******************************************************************
727 run the search by rid.
728 ******************************************************************/
729 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state,
731 LDAPMessage ** result)
736 /* check if the user rid exsists, if not, try searching on the uid */
738 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
739 rc = ldapsam_search_one_user(ldap_state, filter, result);
741 if (rc != LDAP_SUCCESS)
742 rc = ldapsam_search_one_user_by_uid(ldap_state,
743 fallback_pdb_user_rid_to_uid(rid),
749 /*******************************************************************
750 search an attribute and return the first value found.
751 ******************************************************************/
752 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
753 const char *attribute, pstring value)
757 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
759 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
764 pstrcpy(value, values[0]);
765 ldap_value_free(values);
766 #ifdef DEBUG_PASSWORDS
767 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
772 /************************************************************************
773 Routine to manage the LDAPMod structure array
774 manage memory used by the array, by each struct, and values
776 ************************************************************************/
777 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
785 if (attribute == NULL || *attribute == '\0')
789 /* Why do we need this??? -- vl */
790 if (value == NULL || *value == '\0')
796 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
799 DEBUG(0, ("make_a_mod: out of memory!\n"));
805 for (i = 0; mods[i] != NULL; ++i) {
806 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
812 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
815 DEBUG(0, ("make_a_mod: out of memory!\n"));
818 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
821 DEBUG(0, ("make_a_mod: out of memory!\n"));
824 mods[i]->mod_op = modop;
825 mods[i]->mod_values = NULL;
826 mods[i]->mod_type = strdup(attribute);
833 if (mods[i]->mod_values != NULL) {
834 for (; mods[i]->mod_values[j] != NULL; j++);
836 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
837 (j + 2) * sizeof (char *));
839 if (mods[i]->mod_values == NULL) {
840 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
843 mods[i]->mod_values[j] = strdup(value);
844 mods[i]->mod_values[j + 1] = NULL;
849 /*******************************************************************
850 Delete complete object or objectclass and attrs from
851 object found in search_result depending on lp_ldap_delete_dn
852 ******************************************************************/
853 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
855 const char *objectclass,
860 LDAPMod **mods = NULL;
862 BerElement *ptr = NULL;
864 rc = ldap_count_entries(ldap_state->ldap_struct, result);
867 DEBUG(0, ("Entry must exist exactly once!\n"));
868 return NT_STATUS_UNSUCCESSFUL;
871 entry = ldap_first_entry(ldap_state->ldap_struct, result);
872 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
874 if (lp_ldap_delete_dn()) {
875 NTSTATUS ret = NT_STATUS_OK;
876 rc = ldapsam_delete(ldap_state, dn);
878 if (rc != LDAP_SUCCESS) {
879 DEBUG(0, ("Could not delete object %s\n", dn));
880 ret = NT_STATUS_UNSUCCESSFUL;
886 /* Ok, delete only the SAM attributes */
888 for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
890 name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) {
894 /* We are only allowed to delete the attributes that
897 for (attrib = attrs; *attrib != NULL; attrib++) {
898 if (StrCaseCmp(*attrib, name) == 0) {
899 DEBUG(10, ("deleting attribute %s\n", name));
900 make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
911 make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
913 rc = ldapsam_modify(ldap_state, dn, mods);
914 ldap_mods_free(mods, 1);
916 if (rc != LDAP_SUCCESS) {
917 DEBUG(0, ("could not delete attributes for %s, error: %s\n",
918 dn, ldap_err2string(rc)));
920 return NT_STATUS_UNSUCCESSFUL;
927 /* New Interface is being implemented here */
929 /**********************************************************************
930 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
931 *********************************************************************/
932 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
933 SAM_ACCOUNT * sampass,
943 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
944 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
948 for (values=ldap_values;*values;values++) {
949 if (strcasecmp(*values, "posixAccount") == 0) {
954 if (!*values) { /*end of array, no posixAccount */
955 DEBUG(10, ("user does not have posixAcccount attributes\n"));
956 ldap_value_free(ldap_values);
959 ldap_value_free(ldap_values);
961 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir))
964 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
967 uid = (uid_t)atol(temp);
969 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
972 gid = (gid_t)atol(temp);
974 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
975 pdb_set_uid(sampass, uid, PDB_SET);
976 pdb_set_gid(sampass, gid, PDB_SET);
978 DEBUG(10, ("user has posixAcccount attributes\n"));
983 /**********************************************************************
984 Initialize SAM_ACCOUNT from an LDAP query
985 (Based on init_sam_from_buffer in pdb_tdb.c)
986 *********************************************************************/
987 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
988 SAM_ACCOUNT * sampass,
995 pass_can_change_time,
996 pass_must_change_time;
1011 uint8 smblmpwd[LM_HASH_LEN],
1012 smbntpwd[NT_HASH_LEN];
1013 uint16 acct_ctrl = 0,
1016 uint8 hours[MAX_HOURS_LEN];
1019 gid_t gid = getegid();
1023 * do a little initialization
1027 nt_username[0] = '\0';
1030 dir_drive[0] = '\0';
1031 logon_script[0] = '\0';
1032 profile_path[0] = '\0';
1033 acct_desc[0] = '\0';
1034 munged_dial[0] = '\0';
1035 workstations[0] = '\0';
1038 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1039 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1043 if (ldap_state->ldap_struct == NULL) {
1044 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1048 get_single_attribute(ldap_state->ldap_struct, entry, "uid", username);
1049 DEBUG(2, ("Entry found for user: %s\n", username));
1051 pstrcpy(nt_username, username);
1053 pstrcpy(domain, lp_workgroup());
1055 pdb_set_username(sampass, username, PDB_SET);
1057 pdb_set_domain(sampass, domain, PDB_DEFAULT);
1058 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1060 get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
1061 user_rid = (uint32)atol(temp);
1063 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1065 if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
1068 group_rid = (uint32)atol(temp);
1069 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1074 * If so configured, try and get the values from LDAP
1077 if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state, sampass, entry))) {
1080 * Otherwise just ask the system getpw() calls.
1083 pw = getpwnam_alloc(username);
1085 if (! ldap_state->permit_non_unix_accounts) {
1086 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
1091 pdb_set_uid(sampass, uid, PDB_SET);
1093 pdb_set_gid(sampass, gid, PDB_SET);
1095 pdb_set_unix_homedir(sampass, pw->pw_dir, PDB_SET);
1101 if (group_rid == 0 && pdb_get_init_flags(sampass,PDB_GID) != PDB_DEFAULT) {
1103 gid = pdb_get_gid(sampass);
1104 /* call the mapping code here */
1105 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1106 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1109 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1113 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1114 /* leave as default */
1116 pass_last_set_time = (time_t) atol(temp);
1117 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1120 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1121 /* leave as default */
1123 logon_time = (time_t) atol(temp);
1124 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1127 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1128 /* leave as default */
1130 logoff_time = (time_t) atol(temp);
1131 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1134 if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1135 /* leave as default */
1137 kickoff_time = (time_t) atol(temp);
1138 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1141 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1142 /* leave as default */
1144 pass_can_change_time = (time_t) atol(temp);
1145 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1148 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1149 /* leave as default */
1151 pass_must_change_time = (time_t) atol(temp);
1152 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1155 /* recommend that 'gecos' and 'displayName' should refer to the same
1156 * attribute OID. userFullName depreciated, only used by Samba
1157 * primary rules of LDAP: don't make a new attribute when one is already defined
1158 * that fits your needs; using cn then displayName rather than 'userFullName'
1161 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1162 "displayName", fullname)) {
1163 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1165 /* leave as default */
1167 pdb_set_fullname(sampass, fullname, PDB_SET);
1170 pdb_set_fullname(sampass, fullname, PDB_SET);
1173 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1174 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
1180 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1183 if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1184 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
1190 pdb_set_homedir(sampass, homedir, PDB_SET);
1193 if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1194 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
1200 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1203 if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1204 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
1210 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1213 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1214 /* leave as default */
1216 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1219 if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1220 /* leave as default */;
1222 pdb_set_workstations(sampass, workstations, PDB_SET);
1225 /* FIXME: hours stuff should be cleaner */
1229 memset(hours, 0xff, hours_len);
1231 if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1232 /* leave as default */
1234 pdb_gethexpwd(temp, smblmpwd);
1235 memset((char *)temp, '\0', strlen(temp)+1);
1236 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1238 ZERO_STRUCT(smblmpwd);
1241 if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1242 /* leave as default */
1244 pdb_gethexpwd(temp, smbntpwd);
1245 memset((char *)temp, '\0', strlen(temp)+1);
1246 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1248 ZERO_STRUCT(smbntpwd);
1251 if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1252 acct_ctrl |= ACB_NORMAL;
1254 acct_ctrl = pdb_decode_acct_ctrl(temp);
1257 acct_ctrl |= ACB_NORMAL;
1259 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1262 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1263 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1265 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1267 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1268 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1269 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1271 pdb_set_hours(sampass, hours, PDB_SET);
1276 /**********************************************************************
1277 An LDAP modification is needed in two cases:
1278 * If we are updating the record AND the attribute is CHANGED.
1279 * If we are adding the record AND it is SET or CHANGED (ie not default)
1280 *********************************************************************/
1281 static BOOL need_ldap_mod(BOOL pdb_add, const SAM_ACCOUNT * sampass, enum pdb_elements element) {
1283 return (!IS_SAM_DEFAULT(sampass, element));
1285 return IS_SAM_CHANGED(sampass, element);
1289 /**********************************************************************
1290 Set attribute to newval in LDAP, regardless of what value the
1291 attribute had in LDAP before.
1292 *********************************************************************/
1293 static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
1295 const SAM_ACCOUNT *sampass,
1296 BOOL (*need_update)(const SAM_ACCOUNT *,
1298 enum pdb_elements element,
1299 const char *attribute, const char *newval)
1301 char **values = NULL;
1303 if (!need_update(sampass, element)) {
1307 if (existing != NULL) {
1308 values = ldap_get_values(ldap_struct, existing, attribute);
1311 if ((values != NULL) && (values[0] != NULL) &&
1312 strcmp(values[0], newval) == 0) {
1314 /* Believe it or not, but LDAP will deny a delete and
1315 an add at the same time if the values are the
1318 ldap_value_free(values);
1322 /* Regardless of the real operation (add or modify)
1323 we add the new value here. We rely on deleting
1324 the old value, should it exist. */
1326 if ((newval != NULL) && (strlen(newval) > 0)) {
1327 make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
1330 if (values == NULL) {
1331 /* There has been no value before, so don't delete it.
1332 Here's a possible race: We might end up with
1333 duplicate attributes */
1337 /* By deleting exactly the value we found in the entry this
1338 should be race-free in the sense that the LDAP-Server will
1339 deny the complete operation if somebody changed the
1340 attribute behind our back. */
1342 make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
1343 ldap_value_free(values);
1346 /**********************************************************************
1347 Initialize SAM_ACCOUNT from an LDAP query
1348 (Based on init_buffer_from_sam in pdb_tdb.c)
1349 *********************************************************************/
1350 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1351 LDAPMessage *existing,
1352 LDAPMod *** mods, const SAM_ACCOUNT * sampass,
1353 BOOL (*need_update)(const SAM_ACCOUNT *,
1359 if (mods == NULL || sampass == NULL) {
1360 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1367 * took out adding "objectclass: sambaAccount"
1368 * do this on a per-mod basis
1370 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1371 PDB_USERNAME, "uid", pdb_get_username(sampass));
1372 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1374 rid = pdb_get_user_rid(sampass);
1377 if (!IS_SAM_DEFAULT(sampass, PDB_UID)) {
1378 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
1379 } else if (ldap_state->permit_non_unix_accounts) {
1380 rid = ldapsam_get_next_available_nua_rid(ldap_state);
1382 DEBUG(0, ("NO user RID specified on account %s, and "
1383 "findining next available NUA RID failed, "
1385 pdb_get_username(sampass)));
1386 ldap_mods_free(*mods, 1);
1390 DEBUG(0, ("NO user RID specified on account %s, "
1391 "cannot store!\n", pdb_get_username(sampass)));
1392 ldap_mods_free(*mods, 1);
1397 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1398 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1399 PDB_USERSID, "rid", temp);
1402 rid = pdb_get_group_rid(sampass);
1405 if (!IS_SAM_DEFAULT(sampass, PDB_GID)) {
1406 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
1407 } else if (ldap_state->permit_non_unix_accounts) {
1408 rid = DOMAIN_GROUP_RID_USERS;
1410 DEBUG(0, ("NO group RID specified on account %s, "
1411 "cannot store!\n", pdb_get_username(sampass)));
1412 ldap_mods_free(*mods, 1);
1417 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1418 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1419 PDB_GROUPSID, "primaryGroupID", temp);
1421 /* displayName, cn, and gecos should all be the same
1422 * most easily accomplished by giving them the same OID
1423 * gecos isn't set here b/c it should be handled by the
1425 * We change displayName only and fall back to cn if
1426 * it does not exist.
1429 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1430 PDB_FULLNAME, "displayName",
1431 pdb_get_fullname(sampass));
1433 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1434 PDB_ACCTDESC, "description",
1435 pdb_get_acct_desc(sampass));
1437 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1438 PDB_WORKSTATIONS, "userWorkstations",
1439 pdb_get_workstations(sampass));
1441 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1442 PDB_SMBHOME, "smbHome",
1443 pdb_get_homedir(sampass));
1445 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1446 PDB_DRIVE, "homeDrive",
1447 pdb_get_dir_drive(sampass));
1449 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1450 PDB_LOGONSCRIPT, "scriptPath",
1451 pdb_get_logon_script(sampass));
1453 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1454 PDB_PROFILE, "profilePath",
1455 pdb_get_profile_path(sampass));
1457 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1458 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1459 PDB_LOGONTIME, "logonTime", temp);
1461 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1462 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1463 PDB_LOGOFFTIME, "logoffTime", temp);
1465 slprintf (temp, sizeof (temp) - 1, "%li",
1466 pdb_get_kickoff_time(sampass));
1467 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1468 PDB_KICKOFFTIME, "kickoffTime", temp);
1470 slprintf (temp, sizeof (temp) - 1, "%li",
1471 pdb_get_pass_can_change_time(sampass));
1472 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1473 PDB_CANCHANGETIME, "pwdCanChange", temp);
1475 slprintf (temp, sizeof (temp) - 1, "%li",
1476 pdb_get_pass_must_change_time(sampass));
1477 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1478 PDB_MUSTCHANGETIME, "pwdMustChange", temp);
1480 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
1481 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1483 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass),
1484 pdb_get_acct_ctrl(sampass));
1485 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1486 PDB_LMPASSWD, "lmPassword", temp);
1488 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
1489 pdb_get_acct_ctrl(sampass));
1490 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1491 PDB_NTPASSWD, "ntPassword", temp);
1493 slprintf (temp, sizeof (temp) - 1, "%li",
1494 pdb_get_pass_last_set_time(sampass));
1495 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1496 PDB_PASSLASTSET, "pwdLastSet", temp);
1499 /* FIXME: Hours stuff goes in LDAP */
1500 make_ldap_mod(ldap_state->ldap_struct, existing, mods, sampass, need_update,
1501 PDB_ACCTCTRL, "acctFlags",
1502 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
1503 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1508 /**********************************************************************
1509 Connect to LDAP server and find the next available RID.
1510 *********************************************************************/
1511 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid)
1513 LDAPMessage *result;
1514 uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
1519 if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
1523 if (ldapsam_search_one_user_by_rid(ldap_state, final_rid, &result) != LDAP_SUCCESS) {
1524 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
1528 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
1529 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
1530 ldap_msgfree(result);
1534 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
1535 ldap_msgfree(result);
1539 /**********************************************************************
1540 Extract the RID from an LDAP entry
1541 *********************************************************************/
1542 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry) {
1544 SAM_ACCOUNT *user = NULL;
1545 if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
1549 if (init_sam_from_ldap(ldap_state, user, entry)) {
1550 rid = pdb_get_user_rid(user);
1554 pdb_free_sam(&user);
1555 if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
1562 /**********************************************************************
1563 Connect to LDAP server and find the next available RID.
1564 *********************************************************************/
1565 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state)
1569 LDAPMessage *result;
1571 char *final_filter = NULL;
1576 pstrcpy(filter, lp_ldap_filter());
1577 all_string_sub(filter, "%u", "*", sizeof(pstring));
1580 asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1582 final_filter = strdup(filter);
1584 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1586 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1587 LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1590 if (rc != LDAP_SUCCESS) {
1591 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1592 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1599 count = ldap_count_entries(ldap_state->ldap_struct, result);
1600 DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1603 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1604 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1606 ldap_msgfree(result);
1608 return ldap_state->low_nua_rid;
1612 entry = ldap_first_entry(ldap_state->ldap_struct,result);
1614 top_rid = entry_to_user_rid(ldap_state, entry);
1616 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1618 rid = entry_to_user_rid(ldap_state, entry);
1619 if (rid > top_rid) {
1624 ldap_msgfree(result);
1626 if (top_rid < ldap_state->low_nua_rid)
1627 top_rid = ldap_state->low_nua_rid;
1632 /**********************************************************************
1633 Connect to LDAP server and find the next available RID.
1634 *********************************************************************/
1635 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1636 uint32 next_nua_rid;
1639 top_nua_rid = search_top_nua_rid(ldap_state);
1641 next_nua_rid = check_nua_rid_is_avail(ldap_state,
1644 return next_nua_rid;
1647 /**********************************************************************
1648 Connect to LDAP server for password enumeration
1649 *********************************************************************/
1650 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1652 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1656 pstrcpy(filter, lp_ldap_filter());
1657 all_string_sub(filter, "%u", "*", sizeof(pstring));
1659 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1660 LDAP_SCOPE_SUBTREE, filter, attr, 0,
1661 &ldap_state->result);
1663 if (rc != LDAP_SUCCESS) {
1664 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1665 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1666 ldap_msgfree(ldap_state->result);
1667 ldap_state->result = NULL;
1668 return NT_STATUS_UNSUCCESSFUL;
1671 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1672 ldap_count_entries(ldap_state->ldap_struct,
1673 ldap_state->result)));
1675 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1676 ldap_state->result);
1677 ldap_state->index = 0;
1679 return NT_STATUS_OK;
1682 /**********************************************************************
1683 End enumeration of the LDAP password list
1684 *********************************************************************/
1685 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1687 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1688 if (ldap_state->result) {
1689 ldap_msgfree(ldap_state->result);
1690 ldap_state->result = NULL;
1694 /**********************************************************************
1695 Get the next entry in the LDAP password database
1696 *********************************************************************/
1697 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1699 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1700 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1703 /* The rebind proc needs this *HACK*. We are not multithreaded, so
1704 this will work, but it's not nice. */
1705 static_ldap_state = ldap_state;
1708 if (!ldap_state->entry)
1711 ldap_state->index++;
1712 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1714 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1718 return NT_STATUS_OK;
1721 /**********************************************************************
1722 Get SAM_ACCOUNT entry from LDAP by username
1723 *********************************************************************/
1724 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1726 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1727 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1728 LDAPMessage *result;
1732 if (ldapsam_search_one_user_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
1733 return NT_STATUS_NO_SUCH_USER;
1736 count = ldap_count_entries(ldap_state->ldap_struct, result);
1740 ("We don't find this user [%s] count=%d\n", sname,
1742 return NT_STATUS_NO_SUCH_USER;
1743 } else if (count > 1) {
1745 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
1747 return NT_STATUS_NO_SUCH_USER;
1750 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1752 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1753 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1754 ldap_msgfree(result);
1755 return NT_STATUS_NO_SUCH_USER;
1757 ldap_msgfree(result);
1760 ldap_msgfree(result);
1765 /**********************************************************************
1766 Get SAM_ACCOUNT entry from LDAP by rid
1767 *********************************************************************/
1768 static NTSTATUS ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
1770 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1771 struct ldapsam_privates *ldap_state =
1772 (struct ldapsam_privates *)my_methods->private_data;
1773 LDAPMessage *result;
1777 if (ldapsam_search_one_user_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
1778 return NT_STATUS_NO_SUCH_USER;
1781 count = ldap_count_entries(ldap_state->ldap_struct, result);
1785 ("We don't find this rid [%i] count=%d\n", rid,
1787 return NT_STATUS_NO_SUCH_USER;
1788 } else if (count > 1) {
1790 ("More than one user with rid [%i]. Failing. count=%d\n", rid,
1792 return NT_STATUS_NO_SUCH_USER;
1795 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1797 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1798 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1799 ldap_msgfree(result);
1800 return NT_STATUS_NO_SUCH_USER;
1802 ldap_msgfree(result);
1805 ldap_msgfree(result);
1810 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1813 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
1814 return NT_STATUS_NO_SUCH_USER;
1815 return ldapsam_getsampwrid(my_methods, user, rid);
1818 /********************************************************************
1819 Do the actual modification - also change a plaittext passord if
1821 **********************************************************************/
1823 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
1824 SAM_ACCOUNT *newpwd, char *dn,
1825 LDAPMod **mods, int ldap_op, BOOL pdb_add)
1827 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1830 if (!my_methods || !newpwd || !dn) {
1831 return NT_STATUS_INVALID_PARAMETER;
1835 DEBUG(5,("mods is empty: nothing to modify\n"));
1836 /* may be password change below however */
1841 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
1842 rc = ldapsam_add(ldap_state, dn, mods);
1844 case LDAP_MOD_REPLACE:
1845 rc = ldapsam_modify(ldap_state, dn ,mods);
1848 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1849 return NT_STATUS_UNSUCCESSFUL;
1852 if (rc!=LDAP_SUCCESS) {
1854 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1857 ("failed to %s user dn= %s with: %s\n\t%s\n",
1858 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1859 dn, ldap_err2string(rc),
1862 return NT_STATUS_UNSUCCESSFUL;
1866 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1867 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))&&
1868 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&
1869 need_ldap_mod(pdb_add, newpwd, PDB_PLAINTEXT_PW)&&
1870 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1874 struct berval *retdata;
1876 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1877 DEBUG(0,("ber_alloc_t returns NULL\n"));
1878 return NT_STATUS_UNSUCCESSFUL;
1880 ber_printf (ber, "{");
1881 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
1882 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, pdb_get_plaintext_passwd(newpwd));
1883 ber_printf (ber, "N}");
1885 if ((rc = ber_flatten (ber, &bv))<0) {
1886 DEBUG(0,("ber_flatten returns a value <0\n"));
1887 return NT_STATUS_UNSUCCESSFUL;
1892 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
1893 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
1894 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1895 pdb_get_username(newpwd),ldap_err2string(rc)));
1897 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1899 ber_bvfree(retdata);
1900 ber_memfree(retoid);
1905 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
1906 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
1907 return NT_STATUS_OK;
1910 /**********************************************************************
1911 Delete entry from LDAP for username
1912 *********************************************************************/
1913 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1915 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1918 LDAPMessage *result;
1920 const char *sam_user_attrs[] =
1921 { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
1922 "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
1923 "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
1924 "userWorkstations", "primaryGroupID", "domain", "rid", NULL };
1927 DEBUG(0, ("sam_acct was NULL!\n"));
1928 return NT_STATUS_INVALID_PARAMETER;
1931 sname = pdb_get_username(sam_acct);
1933 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1935 rc = ldapsam_search_one_user_by_name(ldap_state, sname, &result);
1936 if (rc != LDAP_SUCCESS) {
1937 return NT_STATUS_NO_SUCH_USER;
1940 ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
1942 ldap_msgfree(result);
1946 /**********************************************************************
1947 Helper function to determine for update_sam_account whether
1948 we need LDAP modification.
1949 *********************************************************************/
1950 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
1951 enum pdb_elements element)
1953 return IS_SAM_CHANGED(sampass, element);
1956 /**********************************************************************
1958 *********************************************************************/
1959 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1961 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1962 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1965 LDAPMessage *result;
1969 rc = ldapsam_search_one_user_by_name(ldap_state, pdb_get_username(newpwd), &result);
1970 if (rc != LDAP_SUCCESS) {
1971 return NT_STATUS_UNSUCCESSFUL;
1974 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
1975 DEBUG(0, ("No user to modify!\n"));
1976 ldap_msgfree(result);
1977 return NT_STATUS_UNSUCCESSFUL;
1980 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1981 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
1983 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1984 element_is_changed)) {
1985 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1986 ldap_msgfree(result);
1987 return NT_STATUS_UNSUCCESSFUL;
1990 ldap_msgfree(result);
1993 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
1994 pdb_get_username(newpwd)));
1995 ldap_mods_free(mods, 1);
1996 return NT_STATUS_OK;
1999 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, False);
2000 ldap_mods_free(mods,1);
2002 if (NT_STATUS_IS_ERR(ret)) {
2003 DEBUG(0,("failed to modify user with uid = %s\n",
2004 pdb_get_username(newpwd)));
2008 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2009 pdb_get_username(newpwd)));
2010 return NT_STATUS_OK;
2013 /**********************************************************************
2014 Helper function to determine for update_sam_account whether
2015 we need LDAP modification.
2016 *********************************************************************/
2017 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2018 enum pdb_elements element)
2020 return (IS_SAM_SET(sampass, element) ||
2021 IS_SAM_CHANGED(sampass, element));
2024 /**********************************************************************
2025 Add SAM_ACCOUNT to LDAP
2026 *********************************************************************/
2027 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2029 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2030 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2033 LDAPMessage *result = NULL;
2034 LDAPMessage *entry = NULL;
2036 LDAPMod **mods = NULL;
2040 const char *username = pdb_get_username(newpwd);
2041 if (!username || !*username) {
2042 DEBUG(0, ("Cannot add user without a username!\n"));
2043 return NT_STATUS_INVALID_PARAMETER;
2046 rc = ldapsam_search_one_user_by_name (ldap_state, username, &result);
2047 if (rc != LDAP_SUCCESS) {
2048 return NT_STATUS_UNSUCCESSFUL;
2051 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2052 DEBUG(0,("User '%s' already in the base, with samba properties\n",
2054 ldap_msgfree(result);
2055 return NT_STATUS_UNSUCCESSFUL;
2057 ldap_msgfree(result);
2059 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
2060 rc = ldapsam_search_one_user(ldap_state, filter, &result);
2061 if (rc != LDAP_SUCCESS) {
2062 return NT_STATUS_UNSUCCESSFUL;
2065 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2067 if (num_result > 1) {
2068 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2069 ldap_msgfree(result);
2070 return NT_STATUS_UNSUCCESSFUL;
2073 /* Check if we need to update an existing entry */
2074 if (num_result == 1) {
2077 DEBUG(3,("User exists without samba properties: adding them\n"));
2078 ldap_op = LDAP_MOD_REPLACE;
2079 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2080 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2081 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2084 /* Check if we need to add an entry */
2085 DEBUG(3,("Adding new user\n"));
2086 ldap_op = LDAP_MOD_ADD;
2087 if (username[strlen(username)-1] == '$') {
2088 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2090 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2094 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2095 element_is_set_or_changed)) {
2096 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2097 ldap_msgfree(result);
2098 ldap_mods_free(mods, 1);
2099 return NT_STATUS_UNSUCCESSFUL;
2102 ldap_msgfree(result);
2105 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2106 return NT_STATUS_UNSUCCESSFUL;
2109 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
2111 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, True);
2112 if (NT_STATUS_IS_ERR(ret)) {
2113 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2114 pdb_get_username(newpwd),dn));
2115 ldap_mods_free(mods,1);
2119 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
2120 ldap_mods_free(mods, 1);
2121 return NT_STATUS_OK;
2124 static void free_private_data(void **vp)
2126 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2128 ldapsam_close(*ldap_state);
2130 if ((*ldap_state)->bind_secret) {
2131 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2134 ldapsam_close(*ldap_state);
2136 SAFE_FREE((*ldap_state)->bind_dn);
2137 SAFE_FREE((*ldap_state)->bind_secret);
2141 /* No need to free any further, as it is talloc()ed */
2144 static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
2146 "displayName", "description",
2149 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2151 LDAPMessage ** result)
2153 int scope = LDAP_SCOPE_SUBTREE;
2156 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2158 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
2159 filter, group_attr, 0, result);
2161 if (rc != LDAP_SUCCESS) {
2162 DEBUG(0, ("ldapsam_search_one_group: "
2163 "Problem during the LDAP search: %s\n",
2164 ldap_err2string(rc)));
2165 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2166 lp_ldap_suffix(), filter));
2172 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2173 GROUP_MAP *map, LDAPMessage *entry)
2177 if (ldap_state == NULL || map == NULL || entry == NULL ||
2178 ldap_state->ldap_struct == NULL) {
2179 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2183 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
2185 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
2188 DEBUG(2, ("Entry found for group: %s\n", temp));
2190 map->gid = (gid_t)atol(temp);
2192 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
2194 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
2197 string_to_sid(&map->sid, temp);
2199 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
2201 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
2204 map->sid_name_use = (uint32)atol(temp);
2206 if ((map->sid_name_use < SID_NAME_USER) ||
2207 (map->sid_name_use > SID_NAME_UNKNOWN)) {
2208 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2212 if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
2214 DEBUG(3, ("Attribute displayName not found\n"));
2216 if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn",
2218 DEBUG(0, ("Attributes cn not found either "
2219 "for gidNumber(%i)\n",map->gid));
2223 fstrcpy(map->nt_name, temp);
2225 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
2227 DEBUG(3, ("Attribute description not found\n"));
2230 fstrcpy(map->comment, temp);
2232 map->systemaccount = 0;
2233 init_privilege(&map->priv_set);
2238 static BOOL init_ldap_from_group(struct ldapsam_privates *ldap_state,
2239 LDAPMod ***mods, int ldap_op,
2240 const GROUP_MAP *map)
2244 if (mods == NULL || map == NULL) {
2245 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2251 sid_to_string(tmp, &map->sid);
2252 make_a_mod(mods, ldap_op, "ntSid", tmp);
2254 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2255 make_a_mod(mods, ldap_op, "ntGroupType", tmp);
2257 make_a_mod(mods, ldap_op, "displayName", map->nt_name);
2258 make_a_mod(mods, ldap_op, "description", map->comment);
2263 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2267 struct ldapsam_privates *ldap_state =
2268 (struct ldapsam_privates *)methods->private_data;
2269 LDAPMessage *result;
2273 if (ldapsam_search_one_group(ldap_state, filter, &result)
2275 return NT_STATUS_NO_SUCH_GROUP;
2278 count = ldap_count_entries(ldap_state->ldap_struct, result);
2281 DEBUG(4, ("Did not find group for filter %s\n", filter));
2282 return NT_STATUS_NO_SUCH_GROUP;
2286 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2288 return NT_STATUS_NO_SUCH_GROUP;
2291 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2294 ldap_msgfree(result);
2295 return NT_STATUS_UNSUCCESSFUL;
2298 if (!init_group_from_ldap(ldap_state, map, entry)) {
2299 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2301 ldap_msgfree(result);
2302 return NT_STATUS_NO_SUCH_GROUP;
2305 ldap_msgfree(result);
2306 return NT_STATUS_OK;
2309 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2310 DOM_SID sid, BOOL with_priv)
2314 snprintf(filter, sizeof(filter)-1,
2315 "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
2316 sid_string_static(&sid));
2318 return ldapsam_getgroup(methods, filter, map);
2321 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2322 gid_t gid, BOOL with_priv)
2326 snprintf(filter, sizeof(filter)-1,
2327 "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
2330 return ldapsam_getgroup(methods, filter, map);
2333 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2334 char *name, BOOL with_priv)
2338 /* TODO: Escaping of name? */
2340 snprintf(filter, sizeof(filter)-1,
2341 "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
2344 return ldapsam_getgroup(methods, filter, map);
2347 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2349 LDAPMessage **result)
2353 snprintf(filter, sizeof(filter)-1,
2354 "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
2356 return ldapsam_search_one_group(ldap_state, filter, result);
2359 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2362 struct ldapsam_privates *ldap_state =
2363 (struct ldapsam_privates *)methods->private_data;
2364 LDAPMessage *result = NULL;
2365 LDAPMod **mods = NULL;
2375 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2376 map->gid, False))) {
2377 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2378 return NT_STATUS_UNSUCCESSFUL;
2381 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2382 if (rc != LDAP_SUCCESS) {
2383 return NT_STATUS_UNSUCCESSFUL;
2386 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
2387 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
2389 ldap_msgfree(result);
2390 return NT_STATUS_UNSUCCESSFUL;
2393 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2394 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
2397 ldap_msgfree(result);
2399 if (!init_ldap_from_group(ldap_state, &mods, LDAP_MOD_ADD, map)) {
2400 DEBUG(0, ("init_ldap_from_group failed!\n"));
2401 ldap_mods_free(mods, 1);
2402 return NT_STATUS_UNSUCCESSFUL;
2406 DEBUG(0, ("mods is empty\n"));
2407 return NT_STATUS_UNSUCCESSFUL;
2410 make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
2411 "sambaGroupMapping");
2413 rc = ldapsam_modify(ldap_state, dn, mods);
2414 ldap_mods_free(mods, 1);
2416 if (rc != LDAP_SUCCESS) {
2417 DEBUG(0, ("failed to modify group %i\n", map->gid));
2418 return NT_STATUS_UNSUCCESSFUL;
2421 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2422 return NT_STATUS_OK;
2425 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2428 struct ldapsam_privates *ldap_state =
2429 (struct ldapsam_privates *)methods->private_data;
2432 LDAPMessage *result;
2436 if (!init_ldap_from_group(ldap_state, &mods, LDAP_MOD_REPLACE, map)) {
2437 DEBUG(0, ("init_ldap_from_group failed\n"));
2438 return NT_STATUS_UNSUCCESSFUL;
2442 DEBUG(4, ("mods is empty: nothing to do\n"));
2443 return NT_STATUS_UNSUCCESSFUL;
2446 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2448 if (rc != LDAP_SUCCESS) {
2449 ldap_mods_free(mods, 1);
2450 return NT_STATUS_UNSUCCESSFUL;
2453 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2454 DEBUG(0, ("No group to modify!\n"));
2455 ldap_msgfree(result);
2456 ldap_mods_free(mods, 1);
2457 return NT_STATUS_UNSUCCESSFUL;
2460 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2461 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2462 ldap_msgfree(result);
2464 rc = ldapsam_modify(ldap_state, dn, mods);
2466 ldap_mods_free(mods, 1);
2468 if (rc != LDAP_SUCCESS) {
2469 DEBUG(0, ("failed to modify group %i\n", map->gid));
2472 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2473 return NT_STATUS_OK;
2476 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2479 struct ldapsam_privates *ldap_state =
2480 (struct ldapsam_privates *)methods->private_data;
2481 pstring sidstring, filter;
2482 LDAPMessage *result;
2486 const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
2487 "description", "displayName",
2489 sid_to_string(sidstring, &sid);
2490 snprintf(filter, sizeof(filter)-1,
2491 "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
2493 rc = ldapsam_search_one_group(ldap_state, filter, &result);
2495 if (rc != LDAP_SUCCESS) {
2496 return NT_STATUS_NO_SUCH_GROUP;
2499 ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
2501 ldap_msgfree(result);
2505 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
2508 struct ldapsam_privates *ldap_state =
2509 (struct ldapsam_privates *)my_methods->private_data;
2510 const char *filter = "(objectClass=sambaGroupMapping)";
2513 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
2514 LDAP_SCOPE_SUBTREE, filter,
2515 group_attr, 0, &ldap_state->result);
2517 if (rc != LDAP_SUCCESS) {
2518 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2519 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2520 ldap_msgfree(ldap_state->result);
2521 ldap_state->result = NULL;
2522 return NT_STATUS_UNSUCCESSFUL;
2525 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2526 ldap_count_entries(ldap_state->ldap_struct,
2527 ldap_state->result)));
2529 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2530 ldap_state->result);
2531 ldap_state->index = 0;
2533 return NT_STATUS_OK;
2536 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2538 ldapsam_endsampwent(my_methods);
2541 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2544 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2545 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2548 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2549 this will work, but it's not nice. */
2550 static_ldap_state = ldap_state;
2553 if (!ldap_state->entry)
2556 ldap_state->index++;
2557 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2559 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2563 return NT_STATUS_OK;
2566 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2567 enum SID_NAME_USE sid_name_use,
2568 GROUP_MAP **rmap, int *num_entries,
2569 BOOL unix_only, BOOL with_priv)
2579 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2580 DEBUG(0, ("Unable to open passdb\n"));
2581 return NT_STATUS_ACCESS_DENIED;
2584 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
2585 if (sid_name_use != SID_NAME_UNKNOWN &&
2586 sid_name_use != map.sid_name_use) {
2587 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2590 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2591 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
2595 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2597 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
2599 return NT_STATUS_UNSUCCESSFUL;
2604 mapt[entries] = map;
2609 ldapsam_endsamgrent(methods);
2611 *num_entries = entries;
2613 return NT_STATUS_OK;
2616 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2619 struct ldapsam_privates *ldap_state;
2621 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2625 (*pdb_method)->name = "ldapsam";
2627 (*pdb_method)->setsampwent = ldapsam_setsampwent;
2628 (*pdb_method)->endsampwent = ldapsam_endsampwent;
2629 (*pdb_method)->getsampwent = ldapsam_getsampwent;
2630 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2631 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2632 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2633 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2634 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2636 (*pdb_method)->getgrsid = ldapsam_getgrsid;
2637 (*pdb_method)->getgrgid = ldapsam_getgrgid;
2638 (*pdb_method)->getgrnam = ldapsam_getgrnam;
2639 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2640 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2641 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2642 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2644 /* TODO: Setup private data and free */
2646 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
2649 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2650 return NT_STATUS_NO_MEMORY;
2654 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
2655 #ifdef WITH_LDAP_SAMCONFIG
2657 int ldap_port = lp_ldap_port();
2659 /* remap default port if not using SSL (ie clear or TLS) */
2660 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2664 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);
2665 if (!ldap_state->uri) {
2666 return NT_STATUS_NO_MEMORY;
2670 ldap_state->uri = "ldap://localhost";
2674 (*pdb_method)->private_data = ldap_state;
2676 (*pdb_method)->free_private_data = free_private_data;
2678 return NT_STATUS_OK;
2681 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2684 struct ldapsam_privates *ldap_state;
2685 uint32 low_nua_uid, high_nua_uid;
2687 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
2691 (*pdb_method)->name = "ldapsam_nua";
2693 ldap_state = (*pdb_method)->private_data;
2695 ldap_state->permit_non_unix_accounts = True;
2697 if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
2698 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
2699 return NT_STATUS_UNSUCCESSFUL;
2702 ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
2704 ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
2706 return NT_STATUS_OK;
2709 int pdb_ldap_init(void)
2711 smb_register_passdb("ldapsam", pdb_init_ldapsam, PASSDB_INTERFACE_VERSION);
2712 smb_register_passdb("ldapsam_nua", pdb_init_ldapsam_nua, PASSDB_INTERFACE_VERSION);