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) {
409 char *ld_error = NULL;
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 ? ld_error : "(unknown)", 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, (char **)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 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
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);
641 /*******************************************************************
642 run the search by name.
643 ******************************************************************/
644 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, const char *filter, LDAPMessage ** result)
646 int scope = LDAP_SCOPE_SUBTREE;
649 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
651 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, filter, attr, 0, result);
653 if (rc != LDAP_SUCCESS) {
654 char *ld_error = NULL;
655 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
657 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s (%s)\n",
658 ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
659 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
667 /*******************************************************************
668 run the search by name.
669 ******************************************************************/
670 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, const char *user,
671 LDAPMessage ** result)
674 char *escape_user = escape_ldap_string_alloc(user);
677 return LDAP_NO_MEMORY;
681 * in the filter expression, replace %u with the real name
682 * so in ldap filter, %u MUST exist :-)
684 pstrcpy(filter, lp_ldap_filter());
687 * have to use this here because $ is filtered out
692 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
693 SAFE_FREE(escape_user);
695 return ldapsam_search_one_user(ldap_state, filter, result);
698 /*******************************************************************
699 run the search by uid.
700 ******************************************************************/
701 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state,
703 LDAPMessage ** result)
709 /* Get the username from the system and look that up in the LDAP */
711 if ((user = getpwuid_alloc(uid)) == NULL) {
712 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
713 return LDAP_NO_SUCH_OBJECT;
716 pstrcpy(filter, lp_ldap_filter());
718 escape_user = escape_ldap_string_alloc(user->pw_name);
721 return LDAP_NO_MEMORY;
724 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
727 SAFE_FREE(escape_user);
729 return ldapsam_search_one_user(ldap_state, filter, result);
732 /*******************************************************************
733 run the search by rid.
734 ******************************************************************/
735 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state,
737 LDAPMessage ** result)
742 /* check if the user rid exsists, if not, try searching on the uid */
744 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
745 rc = ldapsam_search_one_user(ldap_state, filter, result);
747 if (rc != LDAP_SUCCESS)
748 rc = ldapsam_search_one_user_by_uid(ldap_state,
749 fallback_pdb_user_rid_to_uid(rid),
755 /*******************************************************************
756 search an attribute and return the first value found.
757 ******************************************************************/
758 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
759 const char *attribute, pstring value)
763 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
765 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
770 pstrcpy(value, values[0]);
771 ldap_value_free(values);
772 #ifdef DEBUG_PASSWORDS
773 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
778 /************************************************************************
779 Routine to manage the LDAPMod structure array
780 manage memory used by the array, by each struct, and values
782 ************************************************************************/
783 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
791 if (attribute == NULL || *attribute == '\0')
795 /* Why do we need this??? -- vl */
796 if (value == NULL || *value == '\0')
802 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
805 DEBUG(0, ("make_a_mod: out of memory!\n"));
811 for (i = 0; mods[i] != NULL; ++i) {
812 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
818 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
821 DEBUG(0, ("make_a_mod: out of memory!\n"));
824 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
827 DEBUG(0, ("make_a_mod: out of memory!\n"));
830 mods[i]->mod_op = modop;
831 mods[i]->mod_values = NULL;
832 mods[i]->mod_type = strdup(attribute);
839 if (mods[i]->mod_values != NULL) {
840 for (; mods[i]->mod_values[j] != NULL; j++);
842 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
843 (j + 2) * sizeof (char *));
845 if (mods[i]->mod_values == NULL) {
846 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
849 mods[i]->mod_values[j] = strdup(value);
850 mods[i]->mod_values[j + 1] = NULL;
855 /*******************************************************************
856 Delete complete object or objectclass and attrs from
857 object found in search_result depending on lp_ldap_delete_dn
858 ******************************************************************/
859 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
861 const char *objectclass,
866 LDAPMod **mods = NULL;
868 BerElement *ptr = NULL;
870 rc = ldap_count_entries(ldap_state->ldap_struct, result);
873 DEBUG(0, ("Entry must exist exactly once!\n"));
874 return NT_STATUS_UNSUCCESSFUL;
877 entry = ldap_first_entry(ldap_state->ldap_struct, result);
878 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
880 if (lp_ldap_delete_dn()) {
881 NTSTATUS ret = NT_STATUS_OK;
882 rc = ldapsam_delete(ldap_state, dn);
884 if (rc != LDAP_SUCCESS) {
885 DEBUG(0, ("Could not delete object %s\n", dn));
886 ret = NT_STATUS_UNSUCCESSFUL;
892 /* Ok, delete only the SAM attributes */
894 for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
896 name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) {
900 /* We are only allowed to delete the attributes that
903 for (attrib = attrs; *attrib != NULL; attrib++) {
904 if (StrCaseCmp(*attrib, name) == 0) {
905 DEBUG(10, ("deleting attribute %s\n", name));
906 make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
917 make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
919 rc = ldapsam_modify(ldap_state, dn, mods);
920 ldap_mods_free(mods, 1);
922 if (rc != LDAP_SUCCESS) {
923 char *ld_error = NULL;
924 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
927 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
928 dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
931 return NT_STATUS_UNSUCCESSFUL;
938 /* New Interface is being implemented here */
940 /**********************************************************************
941 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
942 *********************************************************************/
943 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
944 SAM_ACCOUNT * sampass,
954 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
955 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
959 for (values=ldap_values;*values;values++) {
960 if (strcasecmp(*values, "posixAccount") == 0) {
965 if (!*values) { /*end of array, no posixAccount */
966 DEBUG(10, ("user does not have posixAcccount attributes\n"));
967 ldap_value_free(ldap_values);
970 ldap_value_free(ldap_values);
972 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir))
975 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
978 uid = (uid_t)atol(temp);
980 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
983 gid = (gid_t)atol(temp);
985 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
986 pdb_set_uid(sampass, uid, PDB_SET);
987 pdb_set_gid(sampass, gid, PDB_SET);
989 DEBUG(10, ("user has posixAcccount attributes\n"));
994 /**********************************************************************
995 Initialize SAM_ACCOUNT from an LDAP query
996 (Based on init_sam_from_buffer in pdb_tdb.c)
997 *********************************************************************/
998 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
999 SAM_ACCOUNT * sampass,
1000 LDAPMessage * entry)
1006 pass_can_change_time,
1007 pass_must_change_time;
1022 uint8 smblmpwd[LM_HASH_LEN],
1023 smbntpwd[NT_HASH_LEN];
1024 uint16 acct_ctrl = 0,
1027 uint8 hours[MAX_HOURS_LEN];
1030 gid_t gid = getegid();
1034 * do a little initialization
1038 nt_username[0] = '\0';
1041 dir_drive[0] = '\0';
1042 logon_script[0] = '\0';
1043 profile_path[0] = '\0';
1044 acct_desc[0] = '\0';
1045 munged_dial[0] = '\0';
1046 workstations[0] = '\0';
1049 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1050 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1054 if (ldap_state->ldap_struct == NULL) {
1055 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1059 get_single_attribute(ldap_state->ldap_struct, entry, "uid", username);
1060 DEBUG(2, ("Entry found for user: %s\n", username));
1062 pstrcpy(nt_username, username);
1064 pstrcpy(domain, lp_workgroup());
1066 pdb_set_username(sampass, username, PDB_SET);
1068 pdb_set_domain(sampass, domain, PDB_DEFAULT);
1069 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1071 get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
1072 user_rid = (uint32)atol(temp);
1074 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1076 if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
1079 group_rid = (uint32)atol(temp);
1080 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1085 * If so configured, try and get the values from LDAP
1088 if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state, sampass, entry))) {
1091 * Otherwise just ask the system getpw() calls.
1094 pw = getpwnam_alloc(username);
1096 if (! ldap_state->permit_non_unix_accounts) {
1097 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
1102 pdb_set_uid(sampass, uid, PDB_SET);
1104 pdb_set_gid(sampass, gid, PDB_SET);
1106 pdb_set_unix_homedir(sampass, pw->pw_dir, PDB_SET);
1112 if (group_rid == 0 && pdb_get_init_flags(sampass,PDB_GID) != PDB_DEFAULT) {
1114 gid = pdb_get_gid(sampass);
1115 /* call the mapping code here */
1116 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1117 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1120 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1124 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1125 /* leave as default */
1127 pass_last_set_time = (time_t) atol(temp);
1128 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1131 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1132 /* leave as default */
1134 logon_time = (time_t) atol(temp);
1135 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1138 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1139 /* leave as default */
1141 logoff_time = (time_t) atol(temp);
1142 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1145 if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1146 /* leave as default */
1148 kickoff_time = (time_t) atol(temp);
1149 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1152 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1153 /* leave as default */
1155 pass_can_change_time = (time_t) atol(temp);
1156 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1159 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1160 /* leave as default */
1162 pass_must_change_time = (time_t) atol(temp);
1163 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1166 /* recommend that 'gecos' and 'displayName' should refer to the same
1167 * attribute OID. userFullName depreciated, only used by Samba
1168 * primary rules of LDAP: don't make a new attribute when one is already defined
1169 * that fits your needs; using cn then displayName rather than 'userFullName'
1172 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1173 "displayName", fullname)) {
1174 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1176 /* leave as default */
1178 pdb_set_fullname(sampass, fullname, PDB_SET);
1181 pdb_set_fullname(sampass, fullname, PDB_SET);
1184 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1185 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
1191 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1194 if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1195 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
1201 pdb_set_homedir(sampass, homedir, PDB_SET);
1204 if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1205 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
1211 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1214 if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1215 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
1221 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1224 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1225 /* leave as default */
1227 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1230 if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1231 /* leave as default */;
1233 pdb_set_workstations(sampass, workstations, PDB_SET);
1236 /* FIXME: hours stuff should be cleaner */
1240 memset(hours, 0xff, hours_len);
1242 if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1243 /* leave as default */
1245 pdb_gethexpwd(temp, smblmpwd);
1246 memset((char *)temp, '\0', strlen(temp)+1);
1247 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1249 ZERO_STRUCT(smblmpwd);
1252 if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1253 /* leave as default */
1255 pdb_gethexpwd(temp, smbntpwd);
1256 memset((char *)temp, '\0', strlen(temp)+1);
1257 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1259 ZERO_STRUCT(smbntpwd);
1262 if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1263 acct_ctrl |= ACB_NORMAL;
1265 acct_ctrl = pdb_decode_acct_ctrl(temp);
1268 acct_ctrl |= ACB_NORMAL;
1270 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1273 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1274 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1276 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1278 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1279 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1280 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1282 pdb_set_hours(sampass, hours, PDB_SET);
1287 /**********************************************************************
1288 An LDAP modification is needed in two cases:
1289 * If we are updating the record AND the attribute is CHANGED.
1290 * If we are adding the record AND it is SET or CHANGED (ie not default)
1291 *********************************************************************/
1292 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1293 static BOOL need_ldap_mod(BOOL pdb_add, const SAM_ACCOUNT * sampass, enum pdb_elements element) {
1295 return (!IS_SAM_DEFAULT(sampass, element));
1297 return IS_SAM_CHANGED(sampass, element);
1302 /**********************************************************************
1303 Set attribute to newval in LDAP, regardless of what value the
1304 attribute had in LDAP before.
1305 *********************************************************************/
1306 static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
1308 const char *attribute, const char *newval)
1310 char **values = NULL;
1312 if (existing != NULL) {
1313 values = ldap_get_values(ldap_struct, existing, attribute);
1316 if ((values != NULL) && (values[0] != NULL) &&
1317 strcmp(values[0], newval) == 0) {
1319 /* Believe it or not, but LDAP will deny a delete and
1320 an add at the same time if the values are the
1323 ldap_value_free(values);
1327 /* Regardless of the real operation (add or modify)
1328 we add the new value here. We rely on deleting
1329 the old value, should it exist. */
1331 if ((newval != NULL) && (strlen(newval) > 0)) {
1332 make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
1335 if (values == NULL) {
1336 /* There has been no value before, so don't delete it.
1337 Here's a possible race: We might end up with
1338 duplicate attributes */
1342 /* By deleting exactly the value we found in the entry this
1343 should be race-free in the sense that the LDAP-Server will
1344 deny the complete operation if somebody changed the
1345 attribute behind our back. */
1347 make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
1348 ldap_value_free(values);
1351 /**********************************************************************
1352 Initialize SAM_ACCOUNT from an LDAP query
1353 (Based on init_buffer_from_sam in pdb_tdb.c)
1354 *********************************************************************/
1355 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1356 LDAPMessage *existing,
1357 LDAPMod *** mods, const SAM_ACCOUNT * sampass,
1358 BOOL (*need_update)(const SAM_ACCOUNT *,
1364 if (mods == NULL || sampass == NULL) {
1365 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1372 * took out adding "objectclass: sambaAccount"
1373 * do this on a per-mod basis
1375 if (need_update(sampass, PDB_USERNAME))
1376 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1377 "uid", pdb_get_username(sampass));
1379 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1381 rid = pdb_get_user_rid(sampass);
1384 if (!IS_SAM_DEFAULT(sampass, PDB_UID)) {
1385 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
1386 } else if (ldap_state->permit_non_unix_accounts) {
1387 rid = ldapsam_get_next_available_nua_rid(ldap_state);
1389 DEBUG(0, ("NO user RID specified on account %s, and "
1390 "finding next available NUA RID failed, "
1392 pdb_get_username(sampass)));
1393 ldap_mods_free(*mods, 1);
1397 DEBUG(0, ("NO user RID specified on account %s, "
1398 "cannot store!\n", pdb_get_username(sampass)));
1399 ldap_mods_free(*mods, 1);
1404 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1406 if (need_update(sampass, PDB_USERSID))
1407 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1411 rid = pdb_get_group_rid(sampass);
1414 if (!IS_SAM_DEFAULT(sampass, PDB_GID)) {
1415 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
1416 } else if (ldap_state->permit_non_unix_accounts) {
1417 rid = DOMAIN_GROUP_RID_USERS;
1419 DEBUG(0, ("NO group RID specified on account %s, "
1420 "cannot store!\n", pdb_get_username(sampass)));
1421 ldap_mods_free(*mods, 1);
1426 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1428 if (need_update(sampass, PDB_GROUPSID))
1429 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1430 "primaryGroupID", temp);
1432 /* displayName, cn, and gecos should all be the same
1433 * most easily accomplished by giving them the same OID
1434 * gecos isn't set here b/c it should be handled by the
1436 * We change displayName only and fall back to cn if
1437 * it does not exist.
1440 if (need_update(sampass, PDB_FULLNAME))
1441 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1442 "displayName", pdb_get_fullname(sampass));
1444 if (need_update(sampass, PDB_ACCTDESC))
1445 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1446 "description", pdb_get_acct_desc(sampass));
1448 if (need_update(sampass, PDB_WORKSTATIONS))
1449 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1450 "userWorkstations", pdb_get_workstations(sampass));
1452 if (need_update(sampass, PDB_SMBHOME))
1453 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1454 "smbHome", pdb_get_homedir(sampass));
1456 if (need_update(sampass, PDB_DRIVE))
1457 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1458 "homeDrive", pdb_get_dir_drive(sampass));
1460 if (need_update(sampass, PDB_LOGONSCRIPT))
1461 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1462 "scriptPath", pdb_get_logon_script(sampass));
1464 if (need_update(sampass, PDB_PROFILE))
1465 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1466 "profilePath", pdb_get_profile_path(sampass));
1468 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1470 if (need_update(sampass, PDB_LOGONTIME))
1471 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1474 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1476 if (need_update(sampass, PDB_LOGOFFTIME))
1477 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1478 "logoffTime", temp);
1480 slprintf (temp, sizeof (temp) - 1, "%li",
1481 pdb_get_kickoff_time(sampass));
1483 if (need_update(sampass, PDB_KICKOFFTIME))
1484 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1485 "kickoffTime", temp);
1487 slprintf (temp, sizeof (temp) - 1, "%li",
1488 pdb_get_pass_can_change_time(sampass));
1490 if (need_update(sampass, PDB_CANCHANGETIME))
1491 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1492 "pwdCanChange", temp);
1494 slprintf (temp, sizeof (temp) - 1, "%li",
1495 pdb_get_pass_must_change_time(sampass));
1497 if (need_update(sampass, PDB_MUSTCHANGETIME))
1498 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1499 "pwdMustChange", temp);
1501 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
1502 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1504 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass),
1505 pdb_get_acct_ctrl(sampass));
1507 if (need_update(sampass, PDB_LMPASSWD))
1508 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1509 "lmPassword", temp);
1511 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
1512 pdb_get_acct_ctrl(sampass));
1514 if (need_update(sampass, PDB_NTPASSWD))
1515 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1516 "ntPassword", temp);
1518 slprintf (temp, sizeof (temp) - 1, "%li",
1519 pdb_get_pass_last_set_time(sampass));
1521 if (need_update(sampass, PDB_PASSLASTSET))
1522 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1523 "pwdLastSet", temp);
1526 /* FIXME: Hours stuff goes in LDAP */
1528 if (need_update(sampass, PDB_ACCTCTRL))
1529 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1531 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
1532 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1538 /**********************************************************************
1539 Connect to LDAP server and find the next available RID.
1540 *********************************************************************/
1541 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid)
1543 LDAPMessage *result;
1544 uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
1549 if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
1553 if (ldapsam_search_one_user_by_rid(ldap_state, final_rid, &result) != LDAP_SUCCESS) {
1554 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
1558 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
1559 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
1560 ldap_msgfree(result);
1564 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
1565 ldap_msgfree(result);
1569 /**********************************************************************
1570 Extract the RID from an LDAP entry
1571 *********************************************************************/
1572 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry) {
1574 SAM_ACCOUNT *user = NULL;
1575 if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
1579 if (init_sam_from_ldap(ldap_state, user, entry)) {
1580 rid = pdb_get_user_rid(user);
1584 pdb_free_sam(&user);
1585 if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
1592 /**********************************************************************
1593 Connect to LDAP server and find the next available RID.
1594 *********************************************************************/
1595 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state)
1599 LDAPMessage *result;
1601 char *final_filter = NULL;
1606 pstrcpy(filter, lp_ldap_filter());
1607 all_string_sub(filter, "%u", "*", sizeof(pstring));
1610 asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1612 final_filter = strdup(filter);
1614 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1616 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1617 LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1620 if (rc != LDAP_SUCCESS) {
1621 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1622 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1629 count = ldap_count_entries(ldap_state->ldap_struct, result);
1630 DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1633 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1634 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1636 ldap_msgfree(result);
1638 return ldap_state->low_nua_rid;
1642 entry = ldap_first_entry(ldap_state->ldap_struct,result);
1644 top_rid = entry_to_user_rid(ldap_state, entry);
1646 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1648 rid = entry_to_user_rid(ldap_state, entry);
1649 if (rid > top_rid) {
1654 ldap_msgfree(result);
1656 if (top_rid < ldap_state->low_nua_rid)
1657 top_rid = ldap_state->low_nua_rid;
1662 /**********************************************************************
1663 Connect to LDAP server and find the next available RID.
1664 *********************************************************************/
1665 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1666 uint32 next_nua_rid;
1669 top_nua_rid = search_top_nua_rid(ldap_state);
1671 next_nua_rid = check_nua_rid_is_avail(ldap_state,
1674 return next_nua_rid;
1677 /**********************************************************************
1678 Connect to LDAP server for password enumeration
1679 *********************************************************************/
1680 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1682 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1686 pstrcpy(filter, lp_ldap_filter());
1687 all_string_sub(filter, "%u", "*", sizeof(pstring));
1689 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1690 LDAP_SCOPE_SUBTREE, filter, attr, 0,
1691 &ldap_state->result);
1693 if (rc != LDAP_SUCCESS) {
1694 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1695 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1696 ldap_msgfree(ldap_state->result);
1697 ldap_state->result = NULL;
1698 return NT_STATUS_UNSUCCESSFUL;
1701 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1702 ldap_count_entries(ldap_state->ldap_struct,
1703 ldap_state->result)));
1705 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1706 ldap_state->result);
1707 ldap_state->index = 0;
1709 return NT_STATUS_OK;
1712 /**********************************************************************
1713 End enumeration of the LDAP password list
1714 *********************************************************************/
1715 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1717 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1718 if (ldap_state->result) {
1719 ldap_msgfree(ldap_state->result);
1720 ldap_state->result = NULL;
1724 /**********************************************************************
1725 Get the next entry in the LDAP password database
1726 *********************************************************************/
1727 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1729 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1730 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1733 /* The rebind proc needs this *HACK*. We are not multithreaded, so
1734 this will work, but it's not nice. */
1735 static_ldap_state = ldap_state;
1738 if (!ldap_state->entry)
1741 ldap_state->index++;
1742 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1744 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1748 return NT_STATUS_OK;
1751 /**********************************************************************
1752 Get SAM_ACCOUNT entry from LDAP by username
1753 *********************************************************************/
1754 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1756 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1757 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1758 LDAPMessage *result;
1762 if (ldapsam_search_one_user_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
1763 return NT_STATUS_NO_SUCH_USER;
1766 count = ldap_count_entries(ldap_state->ldap_struct, result);
1770 ("We don't find this user [%s] count=%d\n", sname,
1772 return NT_STATUS_NO_SUCH_USER;
1773 } else if (count > 1) {
1775 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
1777 return NT_STATUS_NO_SUCH_USER;
1780 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1782 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1783 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1784 ldap_msgfree(result);
1785 return NT_STATUS_NO_SUCH_USER;
1787 ldap_msgfree(result);
1790 ldap_msgfree(result);
1795 /**********************************************************************
1796 Get SAM_ACCOUNT entry from LDAP by rid
1797 *********************************************************************/
1798 static NTSTATUS ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
1800 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1801 struct ldapsam_privates *ldap_state =
1802 (struct ldapsam_privates *)my_methods->private_data;
1803 LDAPMessage *result;
1807 if (ldapsam_search_one_user_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
1808 return NT_STATUS_NO_SUCH_USER;
1811 count = ldap_count_entries(ldap_state->ldap_struct, result);
1815 ("We don't find this rid [%i] count=%d\n", rid,
1817 return NT_STATUS_NO_SUCH_USER;
1818 } else if (count > 1) {
1820 ("More than one user with rid [%i]. Failing. count=%d\n", rid,
1822 return NT_STATUS_NO_SUCH_USER;
1825 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1827 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1828 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1829 ldap_msgfree(result);
1830 return NT_STATUS_NO_SUCH_USER;
1832 ldap_msgfree(result);
1835 ldap_msgfree(result);
1840 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1843 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
1844 return NT_STATUS_NO_SUCH_USER;
1845 return ldapsam_getsampwrid(my_methods, user, rid);
1848 /********************************************************************
1849 Do the actual modification - also change a plaittext passord if
1851 **********************************************************************/
1853 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
1854 SAM_ACCOUNT *newpwd, char *dn,
1855 LDAPMod **mods, int ldap_op, BOOL pdb_add)
1857 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1860 if (!my_methods || !newpwd || !dn) {
1861 return NT_STATUS_INVALID_PARAMETER;
1865 DEBUG(5,("mods is empty: nothing to modify\n"));
1866 /* may be password change below however */
1871 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
1872 rc = ldapsam_add(ldap_state, dn, mods);
1874 case LDAP_MOD_REPLACE:
1875 rc = ldapsam_modify(ldap_state, dn ,mods);
1878 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1879 return NT_STATUS_UNSUCCESSFUL;
1882 if (rc!=LDAP_SUCCESS) {
1883 char *ld_error = NULL;
1884 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1887 ("failed to %s user dn= %s with: %s\n\t%s\n",
1888 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1889 dn, ldap_err2string(rc),
1890 ld_error?ld_error:"unknown"));
1891 SAFE_FREE(ld_error);
1892 return NT_STATUS_UNSUCCESSFUL;
1896 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1897 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))&&
1898 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&
1899 need_ldap_mod(pdb_add, newpwd, PDB_PLAINTEXT_PW)&&
1900 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1904 struct berval *retdata;
1906 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1907 DEBUG(0,("ber_alloc_t returns NULL\n"));
1908 return NT_STATUS_UNSUCCESSFUL;
1910 ber_printf (ber, "{");
1911 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
1912 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, pdb_get_plaintext_passwd(newpwd));
1913 ber_printf (ber, "N}");
1915 if ((rc = ber_flatten (ber, &bv))<0) {
1916 DEBUG(0,("ber_flatten returns a value <0\n"));
1917 return NT_STATUS_UNSUCCESSFUL;
1922 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
1923 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
1924 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1925 pdb_get_username(newpwd),ldap_err2string(rc)));
1927 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1929 ber_bvfree(retdata);
1930 ber_memfree(retoid);
1935 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
1936 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
1937 return NT_STATUS_OK;
1940 /**********************************************************************
1941 Delete entry from LDAP for username
1942 *********************************************************************/
1943 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1945 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1948 LDAPMessage *result;
1950 const char *sam_user_attrs[] =
1951 { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
1952 "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
1953 "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
1954 "userWorkstations", "primaryGroupID", "domain", "rid", NULL };
1957 DEBUG(0, ("sam_acct was NULL!\n"));
1958 return NT_STATUS_INVALID_PARAMETER;
1961 sname = pdb_get_username(sam_acct);
1963 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1965 rc = ldapsam_search_one_user_by_name(ldap_state, sname, &result);
1966 if (rc != LDAP_SUCCESS) {
1967 return NT_STATUS_NO_SUCH_USER;
1970 ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
1972 ldap_msgfree(result);
1976 /**********************************************************************
1977 Helper function to determine for update_sam_account whether
1978 we need LDAP modification.
1979 *********************************************************************/
1980 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
1981 enum pdb_elements element)
1983 return IS_SAM_CHANGED(sampass, element);
1986 /**********************************************************************
1988 *********************************************************************/
1989 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1991 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1992 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1995 LDAPMessage *result;
1999 rc = ldapsam_search_one_user_by_name(ldap_state, pdb_get_username(newpwd), &result);
2000 if (rc != LDAP_SUCCESS) {
2001 return NT_STATUS_UNSUCCESSFUL;
2004 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2005 DEBUG(0, ("No user to modify!\n"));
2006 ldap_msgfree(result);
2007 return NT_STATUS_UNSUCCESSFUL;
2010 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2011 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2013 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2014 element_is_changed)) {
2015 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2016 ldap_msgfree(result);
2017 return NT_STATUS_UNSUCCESSFUL;
2020 ldap_msgfree(result);
2023 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2024 pdb_get_username(newpwd)));
2025 ldap_mods_free(mods, 1);
2026 return NT_STATUS_OK;
2029 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, False);
2030 ldap_mods_free(mods,1);
2032 if (!NT_STATUS_IS_OK(ret)) {
2033 char *ld_error = NULL;
2034 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2036 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2037 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
2038 SAFE_FREE(ld_error);
2042 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2043 pdb_get_username(newpwd)));
2044 return NT_STATUS_OK;
2047 /**********************************************************************
2048 Helper function to determine for update_sam_account whether
2049 we need LDAP modification.
2050 *********************************************************************/
2051 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2052 enum pdb_elements element)
2054 return (IS_SAM_SET(sampass, element) ||
2055 IS_SAM_CHANGED(sampass, element));
2058 /**********************************************************************
2059 Add SAM_ACCOUNT to LDAP
2060 *********************************************************************/
2061 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2063 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2064 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2067 LDAPMessage *result = NULL;
2068 LDAPMessage *entry = NULL;
2070 LDAPMod **mods = NULL;
2074 const char *username = pdb_get_username(newpwd);
2075 if (!username || !*username) {
2076 DEBUG(0, ("Cannot add user without a username!\n"));
2077 return NT_STATUS_INVALID_PARAMETER;
2080 rc = ldapsam_search_one_user_by_name (ldap_state, username, &result);
2081 if (rc != LDAP_SUCCESS) {
2082 return NT_STATUS_UNSUCCESSFUL;
2085 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2086 DEBUG(0,("User '%s' already in the base, with samba properties\n",
2088 ldap_msgfree(result);
2089 return NT_STATUS_UNSUCCESSFUL;
2091 ldap_msgfree(result);
2093 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
2094 rc = ldapsam_search_one_user(ldap_state, filter, &result);
2095 if (rc != LDAP_SUCCESS) {
2096 return NT_STATUS_UNSUCCESSFUL;
2099 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2101 if (num_result > 1) {
2102 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2103 ldap_msgfree(result);
2104 return NT_STATUS_UNSUCCESSFUL;
2107 /* Check if we need to update an existing entry */
2108 if (num_result == 1) {
2111 DEBUG(3,("User exists without samba properties: adding them\n"));
2112 ldap_op = LDAP_MOD_REPLACE;
2113 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2114 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2115 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2118 /* Check if we need to add an entry */
2119 DEBUG(3,("Adding new user\n"));
2120 ldap_op = LDAP_MOD_ADD;
2121 if (username[strlen(username)-1] == '$') {
2122 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2124 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2128 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2129 element_is_set_or_changed)) {
2130 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2131 ldap_msgfree(result);
2132 return NT_STATUS_UNSUCCESSFUL;
2135 ldap_msgfree(result);
2138 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2139 return NT_STATUS_UNSUCCESSFUL;
2142 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
2144 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, True);
2145 if (NT_STATUS_IS_ERR(ret)) {
2146 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2147 pdb_get_username(newpwd),dn));
2148 ldap_mods_free(mods,1);
2152 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
2153 ldap_mods_free(mods, 1);
2154 return NT_STATUS_OK;
2157 static void free_private_data(void **vp)
2159 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2161 ldapsam_close(*ldap_state);
2163 if ((*ldap_state)->bind_secret) {
2164 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2167 ldapsam_close(*ldap_state);
2169 SAFE_FREE((*ldap_state)->bind_dn);
2170 SAFE_FREE((*ldap_state)->bind_secret);
2174 /* No need to free any further, as it is talloc()ed */
2177 static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
2179 "displayName", "description",
2182 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2184 LDAPMessage ** result)
2186 int scope = LDAP_SCOPE_SUBTREE;
2189 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2191 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
2192 filter, group_attr, 0, result);
2194 if (rc != LDAP_SUCCESS) {
2195 char *ld_error = NULL;
2196 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2198 DEBUG(0, ("ldapsam_search_one_group: "
2199 "Problem during the LDAP search: LDAP error: %s (%s)",
2200 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
2201 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2202 lp_ldap_suffix(), filter));
2203 SAFE_FREE(ld_error);
2209 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2210 GROUP_MAP *map, LDAPMessage *entry)
2214 if (ldap_state == NULL || map == NULL || entry == NULL ||
2215 ldap_state->ldap_struct == NULL) {
2216 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2220 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
2222 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
2225 DEBUG(2, ("Entry found for group: %s\n", temp));
2227 map->gid = (gid_t)atol(temp);
2229 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
2231 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
2234 string_to_sid(&map->sid, temp);
2236 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
2238 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
2241 map->sid_name_use = (uint32)atol(temp);
2243 if ((map->sid_name_use < SID_NAME_USER) ||
2244 (map->sid_name_use > SID_NAME_UNKNOWN)) {
2245 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2249 if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
2251 DEBUG(3, ("Attribute displayName not found\n"));
2253 if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn",
2255 DEBUG(0, ("Attributes cn not found either "
2256 "for gidNumber(%i)\n",map->gid));
2260 fstrcpy(map->nt_name, temp);
2262 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
2264 DEBUG(3, ("Attribute description not found\n"));
2267 fstrcpy(map->comment, temp);
2269 map->systemaccount = 0;
2270 init_privilege(&map->priv_set);
2275 static BOOL init_ldap_from_group(LDAP *ldap_struct,
2276 LDAPMessage *existing,
2278 const GROUP_MAP *map)
2282 if (mods == NULL || map == NULL) {
2283 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2289 sid_to_string(tmp, &map->sid);
2290 make_ldap_mod(ldap_struct, existing, mods, "ntSid", tmp);
2291 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2292 make_ldap_mod(ldap_struct, existing, mods, "ntGroupType", tmp);
2294 make_ldap_mod(ldap_struct, existing, mods, "displayName", map->nt_name);
2295 make_ldap_mod(ldap_struct, existing, mods, "description", map->comment);
2300 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2304 struct ldapsam_privates *ldap_state =
2305 (struct ldapsam_privates *)methods->private_data;
2306 LDAPMessage *result;
2310 if (ldapsam_search_one_group(ldap_state, filter, &result)
2312 return NT_STATUS_NO_SUCH_GROUP;
2315 count = ldap_count_entries(ldap_state->ldap_struct, result);
2318 DEBUG(4, ("Did not find group for filter %s\n", filter));
2319 return NT_STATUS_NO_SUCH_GROUP;
2323 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2325 return NT_STATUS_NO_SUCH_GROUP;
2328 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2331 ldap_msgfree(result);
2332 return NT_STATUS_UNSUCCESSFUL;
2335 if (!init_group_from_ldap(ldap_state, map, entry)) {
2336 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2338 ldap_msgfree(result);
2339 return NT_STATUS_NO_SUCH_GROUP;
2342 ldap_msgfree(result);
2343 return NT_STATUS_OK;
2346 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2347 DOM_SID sid, BOOL with_priv)
2351 snprintf(filter, sizeof(filter)-1,
2352 "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
2353 sid_string_static(&sid));
2355 return ldapsam_getgroup(methods, filter, map);
2358 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2359 gid_t gid, BOOL with_priv)
2363 snprintf(filter, sizeof(filter)-1,
2364 "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
2367 return ldapsam_getgroup(methods, filter, map);
2370 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2371 char *name, BOOL with_priv)
2375 /* TODO: Escaping of name? */
2377 snprintf(filter, sizeof(filter)-1,
2378 "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
2381 return ldapsam_getgroup(methods, filter, map);
2384 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2386 LDAPMessage **result)
2390 snprintf(filter, sizeof(filter)-1,
2391 "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
2393 return ldapsam_search_one_group(ldap_state, filter, result);
2396 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2399 struct ldapsam_privates *ldap_state =
2400 (struct ldapsam_privates *)methods->private_data;
2401 LDAPMessage *result = NULL;
2402 LDAPMod **mods = NULL;
2412 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2413 map->gid, False))) {
2414 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2415 return NT_STATUS_UNSUCCESSFUL;
2418 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2419 if (rc != LDAP_SUCCESS) {
2420 return NT_STATUS_UNSUCCESSFUL;
2423 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
2424 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
2426 ldap_msgfree(result);
2427 return NT_STATUS_UNSUCCESSFUL;
2430 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2431 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
2435 if (!init_ldap_from_group(ldap_state->ldap_struct,
2436 result, &mods, map)) {
2437 DEBUG(0, ("init_ldap_from_group failed!\n"));
2438 ldap_mods_free(mods, 1);
2439 ldap_msgfree(result);
2440 return NT_STATUS_UNSUCCESSFUL;
2443 ldap_msgfree(result);
2446 DEBUG(0, ("mods is empty\n"));
2447 return NT_STATUS_UNSUCCESSFUL;
2450 make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
2451 "sambaGroupMapping");
2453 rc = ldapsam_modify(ldap_state, dn, mods);
2454 ldap_mods_free(mods, 1);
2456 if (rc != LDAP_SUCCESS) {
2457 char *ld_error = NULL;
2458 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2460 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
2461 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2462 SAFE_FREE(ld_error);
2463 return NT_STATUS_UNSUCCESSFUL;
2466 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2467 return NT_STATUS_OK;
2470 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2473 struct ldapsam_privates *ldap_state =
2474 (struct ldapsam_privates *)methods->private_data;
2477 LDAPMessage *result;
2481 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2483 if (rc != LDAP_SUCCESS) {
2484 return NT_STATUS_UNSUCCESSFUL;
2487 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2488 DEBUG(0, ("No group to modify!\n"));
2489 ldap_msgfree(result);
2490 return NT_STATUS_UNSUCCESSFUL;
2493 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2494 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2496 if (!init_ldap_from_group(ldap_state->ldap_struct,
2497 result, &mods, map)) {
2498 DEBUG(0, ("init_ldap_from_group failed\n"));
2499 ldap_msgfree(result);
2500 return NT_STATUS_UNSUCCESSFUL;
2503 ldap_msgfree(result);
2506 DEBUG(4, ("mods is empty: nothing to do\n"));
2507 return NT_STATUS_UNSUCCESSFUL;
2510 rc = ldapsam_modify(ldap_state, dn, mods);
2512 ldap_mods_free(mods, 1);
2514 if (rc != LDAP_SUCCESS) {
2515 char *ld_error = NULL;
2516 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2518 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
2519 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2520 SAFE_FREE(ld_error);
2523 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2524 return NT_STATUS_OK;
2527 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2530 struct ldapsam_privates *ldap_state =
2531 (struct ldapsam_privates *)methods->private_data;
2532 pstring sidstring, filter;
2533 LDAPMessage *result;
2537 const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
2538 "description", "displayName",
2540 sid_to_string(sidstring, &sid);
2541 snprintf(filter, sizeof(filter)-1,
2542 "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
2544 rc = ldapsam_search_one_group(ldap_state, filter, &result);
2546 if (rc != LDAP_SUCCESS) {
2547 return NT_STATUS_NO_SUCH_GROUP;
2550 ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
2552 ldap_msgfree(result);
2556 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
2559 struct ldapsam_privates *ldap_state =
2560 (struct ldapsam_privates *)my_methods->private_data;
2561 const char *filter = "(objectClass=sambaGroupMapping)";
2564 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
2565 LDAP_SCOPE_SUBTREE, filter,
2566 group_attr, 0, &ldap_state->result);
2568 if (rc != LDAP_SUCCESS) {
2569 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2570 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2571 ldap_msgfree(ldap_state->result);
2572 ldap_state->result = NULL;
2573 return NT_STATUS_UNSUCCESSFUL;
2576 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2577 ldap_count_entries(ldap_state->ldap_struct,
2578 ldap_state->result)));
2580 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2581 ldap_state->result);
2582 ldap_state->index = 0;
2584 return NT_STATUS_OK;
2587 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2589 ldapsam_endsampwent(my_methods);
2592 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2595 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2596 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2599 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2600 this will work, but it's not nice. */
2601 static_ldap_state = ldap_state;
2604 if (!ldap_state->entry)
2607 ldap_state->index++;
2608 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2610 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2614 return NT_STATUS_OK;
2617 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2618 enum SID_NAME_USE sid_name_use,
2619 GROUP_MAP **rmap, int *num_entries,
2620 BOOL unix_only, BOOL with_priv)
2630 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2631 DEBUG(0, ("Unable to open passdb\n"));
2632 return NT_STATUS_ACCESS_DENIED;
2635 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
2636 if (sid_name_use != SID_NAME_UNKNOWN &&
2637 sid_name_use != map.sid_name_use) {
2638 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2641 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2642 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
2646 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2648 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
2650 return NT_STATUS_UNSUCCESSFUL;
2655 mapt[entries] = map;
2660 ldapsam_endsamgrent(methods);
2662 *num_entries = entries;
2664 return NT_STATUS_OK;
2667 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2670 struct ldapsam_privates *ldap_state;
2672 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2676 (*pdb_method)->name = "ldapsam";
2678 (*pdb_method)->setsampwent = ldapsam_setsampwent;
2679 (*pdb_method)->endsampwent = ldapsam_endsampwent;
2680 (*pdb_method)->getsampwent = ldapsam_getsampwent;
2681 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2682 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2683 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2684 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2685 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2687 (*pdb_method)->getgrsid = ldapsam_getgrsid;
2688 (*pdb_method)->getgrgid = ldapsam_getgrgid;
2689 (*pdb_method)->getgrnam = ldapsam_getgrnam;
2690 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2691 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2692 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2693 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2695 /* TODO: Setup private data and free */
2697 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
2700 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2701 return NT_STATUS_NO_MEMORY;
2705 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
2706 #ifdef WITH_LDAP_SAMCONFIG
2708 int ldap_port = lp_ldap_port();
2710 /* remap default port if not using SSL (ie clear or TLS) */
2711 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2715 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);
2716 if (!ldap_state->uri) {
2717 return NT_STATUS_NO_MEMORY;
2721 ldap_state->uri = "ldap://localhost";
2725 (*pdb_method)->private_data = ldap_state;
2727 (*pdb_method)->free_private_data = free_private_data;
2729 return NT_STATUS_OK;
2732 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2735 struct ldapsam_privates *ldap_state;
2736 uint32 low_nua_uid, high_nua_uid;
2738 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
2742 (*pdb_method)->name = "ldapsam_nua";
2744 ldap_state = (*pdb_method)->private_data;
2746 ldap_state->permit_non_unix_accounts = True;
2748 if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
2749 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
2750 return NT_STATUS_UNSUCCESSFUL;
2753 ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
2755 ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
2757 return NT_STATUS_OK;
2760 int pdb_ldap_init(void)
2762 smb_register_passdb("ldapsam", pdb_init_ldapsam, PASSDB_INTERFACE_VERSION);
2763 smb_register_passdb("ldapsam_nua", pdb_init_ldapsam_nua, PASSDB_INTERFACE_VERSION);