2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Jean François Micouleau 1998
5 Copyright (C) Gerald Carter 2001
6 Copyright (C) Shahms King 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Stefan (metze) Metzmacher 2002
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #define DBGC_CLASS DBGC_PASSDB
32 * persistent connections: if using NSS LDAP, many connections are made
33 * however, using only one within Samba would be nice
35 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
37 * Other LDAP based login attributes: accountExpires, etc.
38 * (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
39 * structures don't have fields for some of these attributes)
41 * SSL is done, but can't get the certificate based authentication to work
42 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
45 /* NOTE: this will NOT work against an Active Directory server
46 * due to the fact that the two password fields cannot be retrieved
47 * from a server; recommend using security = domain in this situation
54 #ifndef LDAP_OPT_SUCCESS
55 #define LDAP_OPT_SUCCESS 0
59 #define SAM_ACCOUNT struct sam_passwd
62 struct ldapsam_privates {
71 /* retrive-once info */
74 BOOL permit_non_unix_accounts;
82 unsigned int num_failures;
85 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
87 static struct ldapsam_privates *static_ldap_state;
89 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
91 /*******************************************************************
92 find the ldap password
93 ******************************************************************/
94 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
99 *dn = smb_xstrdup(lp_ldap_admin_dn());
101 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
103 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
106 *pw=secrets_fetch(key, &size);
110 /* Upgrade 2.2 style entry */
112 char* old_style_key = strdup(*dn);
114 fstring old_style_pw;
116 if (!old_style_key) {
117 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
121 for (p=old_style_key; *p; p++)
122 if (*p == ',') *p = '/';
124 data=secrets_fetch(old_style_key, &size);
125 if (!size && size < sizeof(old_style_pw)) {
126 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
127 SAFE_FREE(old_style_key);
132 strncpy(old_style_pw, data, size);
133 old_style_pw[size] = 0;
137 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
138 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
139 SAFE_FREE(old_style_key);
143 if (!secrets_delete(old_style_key)) {
144 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
147 SAFE_FREE(old_style_key);
149 *pw = smb_xstrdup(old_style_pw);
155 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
156 "logoffTime", "kickoffTime", "cn",
157 "pwdCanChange", "pwdMustChange",
158 "displayName", "homeDrive",
159 "smbHome", "scriptPath",
160 "profilePath", "description",
161 "userWorkstations", "rid",
162 "primaryGroupID", "lmPassword",
163 "ntPassword", "acctFlags",
164 "domain", "objectClass",
165 "uidNumber", "gidNumber",
166 "homeDirectory", NULL };
168 /*******************************************************************
169 open a connection to the ldap server.
170 ******************************************************************/
171 static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
173 int rc = LDAP_SUCCESS;
175 BOOL ldap_v3 = False;
177 #ifdef HAVE_LDAP_INITIALIZE
178 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
180 if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
181 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
187 /* Parse the string manually */
193 const char *p = ldap_state->uri;
194 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
196 /* skip leading "URL:" (if any) */
197 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
201 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
204 if (strequal(protocol, "ldap")) {
206 } else if (strequal(protocol, "ldaps")) {
209 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
213 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
214 DEBUG(0, ("ldap_init failed !\n"));
215 return LDAP_OPERATIONS_ERROR;
218 if (strequal(protocol, "ldaps")) {
219 #ifdef LDAP_OPT_X_TLS
220 int tls = LDAP_OPT_X_TLS_HARD;
221 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
223 DEBUG(0, ("Failed to setup a TLS session\n"));
226 DEBUG(3,("LDAPS option set...!\n"));
228 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
229 return LDAP_OPERATIONS_ERROR;
235 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
237 if (version != LDAP_VERSION3)
239 version = LDAP_VERSION3;
240 if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
248 if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
249 #ifdef LDAP_OPT_X_TLS
251 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
253 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
254 ldap_err2string(rc)));
257 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
260 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
261 return LDAP_OPERATIONS_ERROR;
264 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
265 return LDAP_OPERATIONS_ERROR;
269 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
274 /*******************************************************************
275 a rebind function for authenticated referrals
276 This version takes a void* that we can shove useful stuff in :-)
277 ******************************************************************/
278 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
280 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
281 int *methodp, int freeit, void *arg)
283 struct ldapsam_privates *ldap_state = arg;
285 /** @TODO Should we be doing something to check what servers we rebind to?
286 Could we get a referral to a machine that we don't want to give our
287 username and password to? */
291 memset(*credp, '\0', strlen(*credp));
294 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
295 ldap_state->bind_dn));
297 *whop = strdup(ldap_state->bind_dn);
299 return LDAP_NO_MEMORY;
301 *credp = strdup(ldap_state->bind_secret);
304 return LDAP_NO_MEMORY;
306 *methodp = LDAP_AUTH_SIMPLE;
310 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
312 /*******************************************************************
313 a rebind function for authenticated referrals
314 This version takes a void* that we can shove useful stuff in :-)
315 and actually does the connection.
316 ******************************************************************/
317 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
318 static int rebindproc_connect_with_state (LDAP *ldap_struct,
319 LDAP_CONST char *url,
321 ber_int_t msgid, void *arg)
323 struct ldapsam_privates *ldap_state = arg;
325 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
326 ldap_state->bind_dn));
328 /** @TODO Should we be doing something to check what servers we rebind to?
329 Could we get a referral to a machine that we don't want to give our
330 username and password to? */
332 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
336 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
338 /*******************************************************************
339 Add a rebind function for authenticated referrals
340 ******************************************************************/
341 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
343 # if LDAP_SET_REBIND_PROC_ARGS == 2
344 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
345 int *method, int freeit )
347 return rebindproc_with_state(ldap_struct, whop, credp,
348 method, freeit, static_ldap_state);
351 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
352 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
354 /*******************************************************************
355 a rebind function for authenticated referrals
356 this also does the connection, but no void*.
357 ******************************************************************/
358 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
359 # if LDAP_SET_REBIND_PROC_ARGS == 2
360 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
363 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
366 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
367 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
369 /*******************************************************************
370 connect to the ldap server under system privilege.
371 ******************************************************************/
372 static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
378 /* The rebind proc needs this *HACK*. We are not multithreaded, so
379 this will work, but it's not nice. */
380 static_ldap_state = ldap_state;
382 /* get the password */
383 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
385 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
386 return LDAP_INVALID_CREDENTIALS;
389 ldap_state->bind_dn = ldap_dn;
390 ldap_state->bind_secret = ldap_secret;
392 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
393 (OpenLDAP) doesnt' seem to support it */
395 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
396 ldap_state->uri, ldap_dn));
398 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
399 # if LDAP_SET_REBIND_PROC_ARGS == 2
400 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
402 # if LDAP_SET_REBIND_PROC_ARGS == 3
403 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
405 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
406 # if LDAP_SET_REBIND_PROC_ARGS == 2
407 ldap_set_rebind_proc(ldap_struct, &rebindproc);
409 # if LDAP_SET_REBIND_PROC_ARGS == 3
410 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
412 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
414 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
416 if (rc != LDAP_SUCCESS) {
417 char *ld_error = NULL;
418 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
420 DEBUG(ldap_state->num_failures ? 2 : 0,
421 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
422 ldap_dn ? ld_error : "(unknown)", ldap_err2string(rc),
425 ldap_state->num_failures++;
429 ldap_state->num_failures = 0;
431 DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
435 /**********************************************************************
436 Connect to LDAP server
437 *********************************************************************/
438 static int ldapsam_open(struct ldapsam_privates *ldap_state)
441 SMB_ASSERT(ldap_state);
443 #ifndef NO_LDAP_SECURITY
444 if (geteuid() != 0) {
445 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
446 return LDAP_INSUFFICIENT_ACCESS;
450 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
451 struct sockaddr_un addr;
452 socklen_t len = sizeof(addr);
454 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
455 getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
456 /* the other end has died. reopen. */
457 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
458 ldap_state->ldap_struct = NULL;
459 ldap_state->last_ping = (time_t)0;
461 ldap_state->last_ping = time(NULL);
465 if (ldap_state->ldap_struct != NULL) {
466 DEBUG(5,("ldapsam_open: allready connected to the LDAP server\n"));
470 if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
474 if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
475 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
476 ldap_state->ldap_struct = NULL;
481 ldap_state->last_ping = time(NULL);
482 DEBUG(4,("The LDAP server is succesful connected\n"));
487 /**********************************************************************
488 Disconnect from LDAP server
489 *********************************************************************/
490 static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
493 return NT_STATUS_INVALID_PARAMETER;
495 if (ldap_state->ldap_struct != NULL) {
496 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
497 ldap_state->ldap_struct = NULL;
500 DEBUG(5,("The connection to the LDAP server was closed\n"));
501 /* maybe free the results here --metze */
506 static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
510 SMB_ASSERT(ldap_state && attempts);
512 if (*attempts != 0) {
513 unsigned int sleep_time;
514 uint8 rand_byte = 128; /* a reasonable place to start */
516 generate_random_buffer(&rand_byte, 1, False);
518 sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2;
519 /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
522 DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n",
528 if ((rc = ldapsam_open(ldap_state))) {
529 DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts));
537 static int ldapsam_search(struct ldapsam_privates *ldap_state,
538 const char *base, int scope, const char *filter,
539 const char *attrs[], int attrsonly,
542 int rc = LDAP_SERVER_DOWN;
546 SMB_ASSERT(ldap_state);
548 if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) {
549 return LDAP_NO_MEMORY;
552 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
554 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
557 rc = ldap_search_s(ldap_state->ldap_struct, base, scope,
558 filter, (char **)attrs, attrsonly, res);
561 if (rc == LDAP_SERVER_DOWN) {
562 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
563 ldapsam_close(ldap_state);
566 SAFE_FREE(utf8_filter);
570 static int ldapsam_modify(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
572 int rc = LDAP_SERVER_DOWN;
576 SMB_ASSERT(ldap_state);
578 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
579 return LDAP_NO_MEMORY;
582 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
584 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
587 rc = ldap_modify_s(ldap_state->ldap_struct, dn, attrs);
590 if (rc == LDAP_SERVER_DOWN) {
591 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
592 ldapsam_close(ldap_state);
599 static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
601 int rc = LDAP_SERVER_DOWN;
605 SMB_ASSERT(ldap_state);
607 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
608 return LDAP_NO_MEMORY;
611 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
613 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
616 rc = ldap_add_s(ldap_state->ldap_struct, dn, attrs);
619 if (rc == LDAP_SERVER_DOWN) {
620 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
621 ldapsam_close(ldap_state);
628 static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
630 int rc = LDAP_SERVER_DOWN;
634 SMB_ASSERT(ldap_state);
636 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
637 return LDAP_NO_MEMORY;
640 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
642 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
645 rc = ldap_delete_s(ldap_state->ldap_struct, dn);
648 if (rc == LDAP_SERVER_DOWN) {
649 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
650 ldapsam_close(ldap_state);
657 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
658 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)
660 int rc = LDAP_SERVER_DOWN;
666 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
668 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
671 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
674 if (rc == LDAP_SERVER_DOWN) {
675 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
676 ldapsam_close(ldap_state);
683 /*******************************************************************
684 run the search by name.
685 ******************************************************************/
686 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, const char *filter, LDAPMessage ** result)
688 int scope = LDAP_SCOPE_SUBTREE;
691 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
693 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, filter, attr, 0, result);
695 if (rc != LDAP_SUCCESS) {
696 char *ld_error = NULL;
697 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
699 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s (%s)\n",
700 ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
701 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
709 /*******************************************************************
710 run the search by name.
711 ******************************************************************/
712 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, const char *user,
713 LDAPMessage ** result)
716 char *escape_user = escape_ldap_string_alloc(user);
719 return LDAP_NO_MEMORY;
723 * in the filter expression, replace %u with the real name
724 * so in ldap filter, %u MUST exist :-)
726 pstrcpy(filter, lp_ldap_filter());
729 * have to use this here because $ is filtered out
734 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
735 SAFE_FREE(escape_user);
737 return ldapsam_search_one_user(ldap_state, filter, result);
740 /*******************************************************************
741 run the search by rid.
742 ******************************************************************/
743 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state,
745 LDAPMessage ** result)
750 /* check if the user rid exsists, if not, try searching on the uid */
752 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
753 rc = ldapsam_search_one_user(ldap_state, filter, result);
758 /*******************************************************************
759 search an attribute and return the first value found.
760 ******************************************************************/
761 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
762 const char *attribute, pstring value)
767 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
768 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
773 if (convert_string(CH_UTF8, CH_UNIX,
775 value, sizeof(pstring)) == (size_t)-1)
777 DEBUG(1, ("get_single_attribute: string conversion of [%s] = [%s] failed!\n",
778 attribute, values[0]));
779 ldap_value_free(values);
783 ldap_value_free(values);
784 #ifdef DEBUG_PASSWORDS
785 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
790 /************************************************************************
791 Routine to manage the LDAPMod structure array
792 manage memory used by the array, by each struct, and values
794 ************************************************************************/
795 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
803 if (attribute == NULL || *attribute == '\0')
807 /* Why do we need this??? -- vl */
808 if (value == NULL || *value == '\0')
814 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
817 DEBUG(0, ("make_a_mod: out of memory!\n"));
823 for (i = 0; mods[i] != NULL; ++i) {
824 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
830 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
833 DEBUG(0, ("make_a_mod: out of memory!\n"));
836 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
839 DEBUG(0, ("make_a_mod: out of memory!\n"));
842 mods[i]->mod_op = modop;
843 mods[i]->mod_values = NULL;
844 mods[i]->mod_type = strdup(attribute);
850 char *utf8_value = NULL;
853 if (mods[i]->mod_values != NULL) {
854 for (; mods[i]->mod_values[j] != NULL; j++);
856 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
857 (j + 2) * sizeof (char *));
859 if (mods[i]->mod_values == NULL) {
860 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
864 if (push_utf8_allocate(&utf8_value, value) == (size_t)-1) {
865 DEBUG (0, ("make_a_mod: String conversion failure!\n"));
869 mods[i]->mod_values[j] = utf8_value;
871 mods[i]->mod_values[j + 1] = NULL;
876 /*******************************************************************
877 Delete complete object or objectclass and attrs from
878 object found in search_result depending on lp_ldap_delete_dn
879 ******************************************************************/
880 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
882 const char *objectclass,
887 LDAPMod **mods = NULL;
889 BerElement *ptr = NULL;
891 rc = ldap_count_entries(ldap_state->ldap_struct, result);
894 DEBUG(0, ("Entry must exist exactly once!\n"));
895 return NT_STATUS_UNSUCCESSFUL;
898 entry = ldap_first_entry(ldap_state->ldap_struct, result);
899 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
901 if (lp_ldap_delete_dn()) {
902 NTSTATUS ret = NT_STATUS_OK;
903 rc = ldapsam_delete(ldap_state, dn);
905 if (rc != LDAP_SUCCESS) {
906 DEBUG(0, ("Could not delete object %s\n", dn));
907 ret = NT_STATUS_UNSUCCESSFUL;
913 /* Ok, delete only the SAM attributes */
915 for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
917 name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) {
921 /* We are only allowed to delete the attributes that
924 for (attrib = attrs; *attrib != NULL; attrib++) {
925 if (StrCaseCmp(*attrib, name) == 0) {
926 DEBUG(10, ("deleting attribute %s\n", name));
927 make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
938 make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
940 rc = ldapsam_modify(ldap_state, dn, mods);
941 ldap_mods_free(mods, 1);
943 if (rc != LDAP_SUCCESS) {
944 char *ld_error = NULL;
945 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
948 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
949 dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
952 return NT_STATUS_UNSUCCESSFUL;
959 /* New Interface is being implemented here */
961 /**********************************************************************
962 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
963 *********************************************************************/
964 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
965 SAM_ACCOUNT * sampass,
975 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
976 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
980 for (values=ldap_values;*values;values++) {
981 if (strcasecmp(*values, "posixAccount") == 0) {
986 if (!*values) { /*end of array, no posixAccount */
987 DEBUG(10, ("user does not have posixAcccount attributes\n"));
988 ldap_value_free(ldap_values);
991 ldap_value_free(ldap_values);
993 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir))
996 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
999 uid = (uid_t)atol(temp);
1001 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
1004 gid = (gid_t)atol(temp);
1006 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
1007 pdb_set_uid(sampass, uid, PDB_SET);
1008 pdb_set_gid(sampass, gid, PDB_SET);
1010 DEBUG(10, ("user has posixAcccount attributes\n"));
1015 /**********************************************************************
1016 Initialize SAM_ACCOUNT from an LDAP query
1017 (Based on init_sam_from_buffer in pdb_tdb.c)
1018 *********************************************************************/
1019 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
1020 SAM_ACCOUNT * sampass,
1021 LDAPMessage * entry)
1027 pass_can_change_time,
1028 pass_must_change_time;
1042 uint8 smblmpwd[LM_HASH_LEN],
1043 smbntpwd[NT_HASH_LEN];
1044 uint16 acct_ctrl = 0,
1047 uint8 hours[MAX_HOURS_LEN];
1050 gid_t gid = getegid();
1054 * do a little initialization
1058 nt_username[0] = '\0';
1061 dir_drive[0] = '\0';
1062 logon_script[0] = '\0';
1063 profile_path[0] = '\0';
1064 acct_desc[0] = '\0';
1065 munged_dial[0] = '\0';
1066 workstations[0] = '\0';
1069 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1070 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1074 if (ldap_state->ldap_struct == NULL) {
1075 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1079 get_single_attribute(ldap_state->ldap_struct, entry, "uid", username);
1080 DEBUG(2, ("Entry found for user: %s\n", username));
1082 pstrcpy(nt_username, username);
1084 pstrcpy(domain, lp_workgroup());
1086 pdb_set_username(sampass, username, PDB_SET);
1088 pdb_set_domain(sampass, domain, PDB_DEFAULT);
1089 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1091 get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
1092 user_rid = (uint32)atol(temp);
1094 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1096 if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
1097 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
1100 group_rid = (uint32)atol(temp);
1101 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1105 * If so configured, try and get the values from LDAP
1108 if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state, sampass, entry))) {
1111 * Otherwise just ask the system getpw() calls.
1114 pw = getpwnam_alloc(username);
1116 if (! ldap_state->permit_non_unix_accounts) {
1117 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
1122 pdb_set_uid(sampass, uid, PDB_SET);
1124 pdb_set_gid(sampass, gid, PDB_SET);
1126 pdb_set_unix_homedir(sampass, pw->pw_dir, PDB_SET);
1132 if ((pdb_get_init_flags(sampass,PDB_GROUPSID) == PDB_DEFAULT)
1133 && (pdb_get_init_flags(sampass,PDB_GID) != PDB_DEFAULT)) {
1135 gid = pdb_get_gid(sampass);
1136 /* call the mapping code here */
1137 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1138 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1141 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1145 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1146 /* leave as default */
1148 pass_last_set_time = (time_t) atol(temp);
1149 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1152 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1153 /* leave as default */
1155 logon_time = (time_t) atol(temp);
1156 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1159 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1160 /* leave as default */
1162 logoff_time = (time_t) atol(temp);
1163 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1166 if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1167 /* leave as default */
1169 kickoff_time = (time_t) atol(temp);
1170 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1173 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1174 /* leave as default */
1176 pass_can_change_time = (time_t) atol(temp);
1177 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1180 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1181 /* leave as default */
1183 pass_must_change_time = (time_t) atol(temp);
1184 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1187 /* recommend that 'gecos' and 'displayName' should refer to the same
1188 * attribute OID. userFullName depreciated, only used by Samba
1189 * primary rules of LDAP: don't make a new attribute when one is already defined
1190 * that fits your needs; using cn then displayName rather than 'userFullName'
1193 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1194 "displayName", fullname)) {
1195 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1197 /* leave as default */
1199 pdb_set_fullname(sampass, fullname, PDB_SET);
1202 pdb_set_fullname(sampass, fullname, PDB_SET);
1205 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1206 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
1212 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1215 if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1216 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
1222 pdb_set_homedir(sampass, homedir, PDB_SET);
1225 if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1226 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
1232 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1235 if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1236 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
1242 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1245 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1246 /* leave as default */
1248 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1251 if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1252 /* leave as default */;
1254 pdb_set_workstations(sampass, workstations, PDB_SET);
1257 /* FIXME: hours stuff should be cleaner */
1261 memset(hours, 0xff, hours_len);
1263 if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1264 /* leave as default */
1266 pdb_gethexpwd(temp, smblmpwd);
1267 memset((char *)temp, '\0', strlen(temp)+1);
1268 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1270 ZERO_STRUCT(smblmpwd);
1273 if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1274 /* leave as default */
1276 pdb_gethexpwd(temp, smbntpwd);
1277 memset((char *)temp, '\0', strlen(temp)+1);
1278 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1280 ZERO_STRUCT(smbntpwd);
1283 if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1284 acct_ctrl |= ACB_NORMAL;
1286 acct_ctrl = pdb_decode_acct_ctrl(temp);
1289 acct_ctrl |= ACB_NORMAL;
1291 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1294 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1295 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1297 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1299 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1300 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1301 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1303 pdb_set_hours(sampass, hours, PDB_SET);
1308 /**********************************************************************
1309 Set attribute to newval in LDAP, regardless of what value the
1310 attribute had in LDAP before.
1311 *********************************************************************/
1312 static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
1314 const char *attribute, const char *newval)
1316 char **values = NULL;
1318 if (existing != NULL) {
1319 values = ldap_get_values(ldap_struct, existing, attribute);
1322 if ((values != NULL) && (values[0] != NULL) &&
1323 strcmp(values[0], newval) == 0) {
1325 /* Believe it or not, but LDAP will deny a delete and
1326 an add at the same time if the values are the
1329 ldap_value_free(values);
1333 /* Regardless of the real operation (add or modify)
1334 we add the new value here. We rely on deleting
1335 the old value, should it exist. */
1337 if ((newval != NULL) && (strlen(newval) > 0)) {
1338 make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
1341 if (values == NULL) {
1342 /* There has been no value before, so don't delete it.
1343 Here's a possible race: We might end up with
1344 duplicate attributes */
1348 /* By deleting exactly the value we found in the entry this
1349 should be race-free in the sense that the LDAP-Server will
1350 deny the complete operation if somebody changed the
1351 attribute behind our back. */
1353 make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
1354 ldap_value_free(values);
1357 /**********************************************************************
1358 Initialize SAM_ACCOUNT from an LDAP query
1359 (Based on init_buffer_from_sam in pdb_tdb.c)
1360 *********************************************************************/
1361 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1362 LDAPMessage *existing,
1363 LDAPMod *** mods, SAM_ACCOUNT * sampass,
1364 BOOL (*need_update)(const SAM_ACCOUNT *,
1370 if (mods == NULL || sampass == NULL) {
1371 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1378 * took out adding "objectclass: sambaAccount"
1379 * do this on a per-mod basis
1381 if (need_update(sampass, PDB_USERNAME))
1382 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1383 "uid", pdb_get_username(sampass));
1385 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1387 rid = pdb_get_user_rid(sampass);
1390 if (!IS_SAM_DEFAULT(sampass, PDB_UID)) {
1391 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
1392 } else if (ldap_state->permit_non_unix_accounts) {
1393 rid = ldapsam_get_next_available_nua_rid(ldap_state);
1395 DEBUG(0, ("NO user RID specified on account %s, and "
1396 "finding next available NUA RID failed, "
1398 pdb_get_username(sampass)));
1399 ldap_mods_free(*mods, 1);
1403 DEBUG(0, ("NO user RID specified on account %s, "
1404 "cannot store!\n", pdb_get_username(sampass)));
1405 ldap_mods_free(*mods, 1);
1409 /* now that we have figured out the RID, always store it, as
1410 the schema requires it */
1411 if (!pdb_set_user_sid_from_rid(sampass, rid, PDB_CHANGED)) {
1412 DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n",
1413 pdb_get_username(sampass)));
1414 ldap_mods_free(*mods, 1);
1419 /* only update the RID if we actually need to */
1420 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1421 if (need_update(sampass, PDB_USERSID))
1422 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1425 rid = pdb_get_group_rid(sampass);
1428 if (!IS_SAM_DEFAULT(sampass, PDB_GID)) {
1429 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
1430 } else if (ldap_state->permit_non_unix_accounts) {
1431 rid = DOMAIN_GROUP_RID_USERS;
1433 DEBUG(0, ("NO group RID specified on account %s, "
1434 "cannot store!\n", pdb_get_username(sampass)));
1435 ldap_mods_free(*mods, 1);
1440 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1442 if (need_update(sampass, PDB_GROUPSID))
1443 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1444 "primaryGroupID", temp);
1446 /* displayName, cn, and gecos should all be the same
1447 * most easily accomplished by giving them the same OID
1448 * gecos isn't set here b/c it should be handled by the
1450 * We change displayName only and fall back to cn if
1451 * it does not exist.
1454 if (need_update(sampass, PDB_FULLNAME))
1455 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1456 "displayName", pdb_get_fullname(sampass));
1458 if (need_update(sampass, PDB_ACCTDESC))
1459 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1460 "description", pdb_get_acct_desc(sampass));
1462 if (need_update(sampass, PDB_WORKSTATIONS))
1463 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1464 "userWorkstations", pdb_get_workstations(sampass));
1466 if (need_update(sampass, PDB_SMBHOME))
1467 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1468 "smbHome", pdb_get_homedir(sampass));
1470 if (need_update(sampass, PDB_DRIVE))
1471 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1472 "homeDrive", pdb_get_dir_drive(sampass));
1474 if (need_update(sampass, PDB_LOGONSCRIPT))
1475 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1476 "scriptPath", pdb_get_logon_script(sampass));
1478 if (need_update(sampass, PDB_PROFILE))
1479 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1480 "profilePath", pdb_get_profile_path(sampass));
1482 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1484 if (need_update(sampass, PDB_LOGONTIME))
1485 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1488 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1490 if (need_update(sampass, PDB_LOGOFFTIME))
1491 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1492 "logoffTime", temp);
1494 slprintf (temp, sizeof (temp) - 1, "%li",
1495 pdb_get_kickoff_time(sampass));
1497 if (need_update(sampass, PDB_KICKOFFTIME))
1498 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1499 "kickoffTime", temp);
1501 slprintf (temp, sizeof (temp) - 1, "%li",
1502 pdb_get_pass_can_change_time(sampass));
1504 if (need_update(sampass, PDB_CANCHANGETIME))
1505 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1506 "pwdCanChange", temp);
1508 slprintf (temp, sizeof (temp) - 1, "%li",
1509 pdb_get_pass_must_change_time(sampass));
1511 if (need_update(sampass, PDB_MUSTCHANGETIME))
1512 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1513 "pwdMustChange", temp);
1515 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
1516 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1518 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass),
1519 pdb_get_acct_ctrl(sampass));
1521 if (need_update(sampass, PDB_LMPASSWD))
1522 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1523 "lmPassword", temp);
1525 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
1526 pdb_get_acct_ctrl(sampass));
1528 if (need_update(sampass, PDB_NTPASSWD))
1529 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1530 "ntPassword", temp);
1532 slprintf (temp, sizeof (temp) - 1, "%li",
1533 pdb_get_pass_last_set_time(sampass));
1535 if (need_update(sampass, PDB_PASSLASTSET))
1536 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1537 "pwdLastSet", temp);
1540 /* FIXME: Hours stuff goes in LDAP */
1542 if (need_update(sampass, PDB_ACCTCTRL))
1543 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1545 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
1546 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1552 /**********************************************************************
1553 Connect to LDAP server and find the next available RID.
1554 *********************************************************************/
1555 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid)
1557 LDAPMessage *result;
1558 uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
1563 if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
1567 if (ldapsam_search_one_user_by_rid(ldap_state, final_rid, &result) != LDAP_SUCCESS) {
1568 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
1572 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
1573 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
1574 ldap_msgfree(result);
1578 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
1579 ldap_msgfree(result);
1583 /**********************************************************************
1584 Extract the RID from an LDAP entry
1585 *********************************************************************/
1586 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry) {
1588 SAM_ACCOUNT *user = NULL;
1589 if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
1593 if (init_sam_from_ldap(ldap_state, user, entry)) {
1594 rid = pdb_get_user_rid(user);
1598 pdb_free_sam(&user);
1599 if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
1606 /**********************************************************************
1607 Connect to LDAP server and find the next available RID.
1608 *********************************************************************/
1609 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state)
1613 LDAPMessage *result;
1615 char *final_filter = NULL;
1620 pstrcpy(filter, lp_ldap_filter());
1621 all_string_sub(filter, "%u", "*", sizeof(pstring));
1624 asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1626 final_filter = strdup(filter);
1628 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1630 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1631 LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1634 if (rc != LDAP_SUCCESS) {
1635 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1636 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1643 count = ldap_count_entries(ldap_state->ldap_struct, result);
1644 DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1647 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1648 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1650 ldap_msgfree(result);
1652 return ldap_state->low_nua_rid;
1656 entry = ldap_first_entry(ldap_state->ldap_struct,result);
1658 top_rid = entry_to_user_rid(ldap_state, entry);
1660 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1662 rid = entry_to_user_rid(ldap_state, entry);
1663 if (rid > top_rid) {
1668 ldap_msgfree(result);
1670 if (top_rid < ldap_state->low_nua_rid)
1671 top_rid = ldap_state->low_nua_rid;
1676 /**********************************************************************
1677 Connect to LDAP server and find the next available RID.
1678 *********************************************************************/
1679 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1680 uint32 next_nua_rid;
1683 top_nua_rid = search_top_nua_rid(ldap_state);
1685 next_nua_rid = check_nua_rid_is_avail(ldap_state,
1688 return next_nua_rid;
1691 /**********************************************************************
1692 Connect to LDAP server for password enumeration
1693 *********************************************************************/
1694 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1696 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1700 pstrcpy(filter, lp_ldap_filter());
1701 all_string_sub(filter, "%u", "*", sizeof(pstring));
1703 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1704 LDAP_SCOPE_SUBTREE, filter, attr, 0,
1705 &ldap_state->result);
1707 if (rc != LDAP_SUCCESS) {
1708 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1709 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1710 ldap_msgfree(ldap_state->result);
1711 ldap_state->result = NULL;
1712 return NT_STATUS_UNSUCCESSFUL;
1715 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1716 ldap_count_entries(ldap_state->ldap_struct,
1717 ldap_state->result)));
1719 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1720 ldap_state->result);
1721 ldap_state->index = 0;
1723 return NT_STATUS_OK;
1726 /**********************************************************************
1727 End enumeration of the LDAP password list
1728 *********************************************************************/
1729 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1731 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1732 if (ldap_state->result) {
1733 ldap_msgfree(ldap_state->result);
1734 ldap_state->result = NULL;
1738 /**********************************************************************
1739 Get the next entry in the LDAP password database
1740 *********************************************************************/
1741 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1743 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1744 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1747 /* The rebind proc needs this *HACK*. We are not multithreaded, so
1748 this will work, but it's not nice. */
1749 static_ldap_state = ldap_state;
1752 if (!ldap_state->entry)
1755 ldap_state->index++;
1756 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1758 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1762 return NT_STATUS_OK;
1765 /**********************************************************************
1766 Get SAM_ACCOUNT entry from LDAP by username
1767 *********************************************************************/
1768 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1770 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1771 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1772 LDAPMessage *result;
1776 if (ldapsam_search_one_user_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
1777 return NT_STATUS_NO_SUCH_USER;
1780 count = ldap_count_entries(ldap_state->ldap_struct, result);
1784 ("We don't find this user [%s] count=%d\n", sname,
1786 return NT_STATUS_NO_SUCH_USER;
1787 } else if (count > 1) {
1789 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
1791 return NT_STATUS_NO_SUCH_USER;
1794 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1796 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1797 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1798 ldap_msgfree(result);
1799 return NT_STATUS_NO_SUCH_USER;
1801 ldap_msgfree(result);
1804 ldap_msgfree(result);
1809 /**********************************************************************
1810 Get SAM_ACCOUNT entry from LDAP by rid
1811 *********************************************************************/
1812 static NTSTATUS ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
1814 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1815 struct ldapsam_privates *ldap_state =
1816 (struct ldapsam_privates *)my_methods->private_data;
1817 LDAPMessage *result;
1821 if (ldapsam_search_one_user_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
1822 return NT_STATUS_NO_SUCH_USER;
1825 count = ldap_count_entries(ldap_state->ldap_struct, result);
1829 ("We don't find this rid [%i] count=%d\n", rid,
1831 return NT_STATUS_NO_SUCH_USER;
1832 } else if (count > 1) {
1834 ("More than one user with rid [%i]. Failing. count=%d\n", rid,
1836 return NT_STATUS_NO_SUCH_USER;
1839 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1841 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1842 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1843 ldap_msgfree(result);
1844 return NT_STATUS_NO_SUCH_USER;
1846 ldap_msgfree(result);
1849 ldap_msgfree(result);
1854 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1857 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
1858 return NT_STATUS_NO_SUCH_USER;
1859 return ldapsam_getsampwrid(my_methods, user, rid);
1862 /********************************************************************
1863 Do the actual modification - also change a plaittext passord if
1865 **********************************************************************/
1867 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
1868 SAM_ACCOUNT *newpwd, char *dn,
1869 LDAPMod **mods, int ldap_op,
1870 BOOL (*need_update)(const SAM_ACCOUNT *,
1873 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1876 if (!my_methods || !newpwd || !dn) {
1877 return NT_STATUS_INVALID_PARAMETER;
1881 DEBUG(5,("mods is empty: nothing to modify\n"));
1882 /* may be password change below however */
1887 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
1888 rc = ldapsam_add(ldap_state, dn, mods);
1890 case LDAP_MOD_REPLACE:
1891 rc = ldapsam_modify(ldap_state, dn ,mods);
1894 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1895 return NT_STATUS_UNSUCCESSFUL;
1898 if (rc!=LDAP_SUCCESS) {
1899 char *ld_error = NULL;
1900 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1903 ("failed to %s user dn= %s with: %s\n\t%s\n",
1904 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1905 dn, ldap_err2string(rc),
1906 ld_error?ld_error:"unknown"));
1907 SAFE_FREE(ld_error);
1908 return NT_STATUS_UNSUCCESSFUL;
1912 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1913 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
1914 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
1915 need_update(newpwd, PDB_PLAINTEXT_PW) &&
1916 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1920 struct berval *retdata;
1921 char *utf8_password;
1923 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
1924 return NT_STATUS_NO_MEMORY;
1927 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1928 DEBUG(0,("ber_alloc_t returns NULL\n"));
1929 SAFE_FREE(utf8_password);
1930 return NT_STATUS_UNSUCCESSFUL;
1933 ber_printf (ber, "{");
1934 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
1935 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, utf8_password);
1936 ber_printf (ber, "N}");
1938 if ((rc = ber_flatten (ber, &bv))<0) {
1939 DEBUG(0,("ber_flatten returns a value <0\n"));
1941 SAFE_FREE(utf8_password);
1942 return NT_STATUS_UNSUCCESSFUL;
1945 SAFE_FREE(utf8_password);
1948 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
1949 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
1950 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1951 pdb_get_username(newpwd),ldap_err2string(rc)));
1953 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1954 #ifdef DEBUG_PASSWORD
1955 DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
1957 ber_bvfree(retdata);
1958 ber_memfree(retoid);
1963 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
1964 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
1965 return NT_STATUS_OK;
1968 /**********************************************************************
1969 Delete entry from LDAP for username
1970 *********************************************************************/
1971 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1973 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1976 LDAPMessage *result;
1978 const char *sam_user_attrs[] =
1979 { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
1980 "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
1981 "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
1982 "userWorkstations", "primaryGroupID", "domain", "rid", NULL };
1985 DEBUG(0, ("sam_acct was NULL!\n"));
1986 return NT_STATUS_INVALID_PARAMETER;
1989 sname = pdb_get_username(sam_acct);
1991 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1993 rc = ldapsam_search_one_user_by_name(ldap_state, sname, &result);
1994 if (rc != LDAP_SUCCESS) {
1995 return NT_STATUS_NO_SUCH_USER;
1998 ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
2000 ldap_msgfree(result);
2004 /**********************************************************************
2005 Helper function to determine for update_sam_account whether
2006 we need LDAP modification.
2007 *********************************************************************/
2008 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
2009 enum pdb_elements element)
2011 return IS_SAM_CHANGED(sampass, element);
2014 /**********************************************************************
2016 *********************************************************************/
2017 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2019 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2020 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2023 LDAPMessage *result;
2027 rc = ldapsam_search_one_user_by_name(ldap_state, pdb_get_username(newpwd), &result);
2028 if (rc != LDAP_SUCCESS) {
2029 return NT_STATUS_UNSUCCESSFUL;
2032 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2033 DEBUG(0, ("No user to modify!\n"));
2034 ldap_msgfree(result);
2035 return NT_STATUS_UNSUCCESSFUL;
2038 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2039 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2041 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2042 element_is_changed)) {
2043 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2044 ldap_msgfree(result);
2045 return NT_STATUS_UNSUCCESSFUL;
2048 ldap_msgfree(result);
2051 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2052 pdb_get_username(newpwd)));
2053 ldap_mods_free(mods, 1);
2054 return NT_STATUS_OK;
2057 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
2058 ldap_mods_free(mods,1);
2060 if (!NT_STATUS_IS_OK(ret)) {
2061 char *ld_error = NULL;
2062 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2064 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2065 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
2066 SAFE_FREE(ld_error);
2070 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2071 pdb_get_username(newpwd)));
2072 return NT_STATUS_OK;
2075 /**********************************************************************
2076 Helper function to determine for update_sam_account whether
2077 we need LDAP modification.
2078 *********************************************************************/
2079 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2080 enum pdb_elements element)
2082 return (IS_SAM_SET(sampass, element) ||
2083 IS_SAM_CHANGED(sampass, element));
2086 /**********************************************************************
2087 Add SAM_ACCOUNT to LDAP
2088 *********************************************************************/
2089 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2091 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2092 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2095 LDAPMessage *result = NULL;
2096 LDAPMessage *entry = NULL;
2098 LDAPMod **mods = NULL;
2102 const char *username = pdb_get_username(newpwd);
2103 if (!username || !*username) {
2104 DEBUG(0, ("Cannot add user without a username!\n"));
2105 return NT_STATUS_INVALID_PARAMETER;
2108 rc = ldapsam_search_one_user_by_name (ldap_state, username, &result);
2109 if (rc != LDAP_SUCCESS) {
2110 return NT_STATUS_UNSUCCESSFUL;
2113 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2114 DEBUG(0,("User '%s' already in the base, with samba properties\n",
2116 ldap_msgfree(result);
2117 return NT_STATUS_UNSUCCESSFUL;
2119 ldap_msgfree(result);
2121 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
2122 rc = ldapsam_search_one_user(ldap_state, filter, &result);
2123 if (rc != LDAP_SUCCESS) {
2124 return NT_STATUS_UNSUCCESSFUL;
2127 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2129 if (num_result > 1) {
2130 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2131 ldap_msgfree(result);
2132 return NT_STATUS_UNSUCCESSFUL;
2135 /* Check if we need to update an existing entry */
2136 if (num_result == 1) {
2139 DEBUG(3,("User exists without samba properties: adding them\n"));
2140 ldap_op = LDAP_MOD_REPLACE;
2141 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2142 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2143 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2146 /* Check if we need to add an entry */
2147 DEBUG(3,("Adding new user\n"));
2148 ldap_op = LDAP_MOD_ADD;
2149 if (username[strlen(username)-1] == '$') {
2150 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2152 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2156 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2157 element_is_set_or_changed)) {
2158 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2159 ldap_msgfree(result);
2160 return NT_STATUS_UNSUCCESSFUL;
2163 ldap_msgfree(result);
2166 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2167 return NT_STATUS_UNSUCCESSFUL;
2170 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
2172 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
2173 if (NT_STATUS_IS_ERR(ret)) {
2174 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2175 pdb_get_username(newpwd),dn));
2176 ldap_mods_free(mods,1);
2180 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
2181 ldap_mods_free(mods, 1);
2182 return NT_STATUS_OK;
2185 static void free_private_data(void **vp)
2187 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2189 ldapsam_close(*ldap_state);
2191 if ((*ldap_state)->bind_secret) {
2192 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2195 ldapsam_close(*ldap_state);
2197 SAFE_FREE((*ldap_state)->bind_dn);
2198 SAFE_FREE((*ldap_state)->bind_secret);
2202 /* No need to free any further, as it is talloc()ed */
2205 static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
2207 "displayName", "description",
2210 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2212 LDAPMessage ** result)
2214 int scope = LDAP_SCOPE_SUBTREE;
2217 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2219 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
2220 filter, group_attr, 0, result);
2222 if (rc != LDAP_SUCCESS) {
2223 char *ld_error = NULL;
2224 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2226 DEBUG(0, ("ldapsam_search_one_group: "
2227 "Problem during the LDAP search: LDAP error: %s (%s)",
2228 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
2229 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2230 lp_ldap_suffix(), filter));
2231 SAFE_FREE(ld_error);
2237 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2238 GROUP_MAP *map, LDAPMessage *entry)
2242 if (ldap_state == NULL || map == NULL || entry == NULL ||
2243 ldap_state->ldap_struct == NULL) {
2244 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2248 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
2250 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
2253 DEBUG(2, ("Entry found for group: %s\n", temp));
2255 map->gid = (gid_t)atol(temp);
2257 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
2259 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
2262 string_to_sid(&map->sid, temp);
2264 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
2266 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
2269 map->sid_name_use = (uint32)atol(temp);
2271 if ((map->sid_name_use < SID_NAME_USER) ||
2272 (map->sid_name_use > SID_NAME_UNKNOWN)) {
2273 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2277 if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
2279 DEBUG(3, ("Attribute displayName not found\n"));
2281 if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn",
2283 DEBUG(0, ("Attributes cn not found either "
2284 "for gidNumber(%i)\n",map->gid));
2288 fstrcpy(map->nt_name, temp);
2290 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
2292 DEBUG(3, ("Attribute description not found\n"));
2295 fstrcpy(map->comment, temp);
2297 map->systemaccount = 0;
2298 init_privilege(&map->priv_set);
2303 static BOOL init_ldap_from_group(LDAP *ldap_struct,
2304 LDAPMessage *existing,
2306 const GROUP_MAP *map)
2310 if (mods == NULL || map == NULL) {
2311 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2317 sid_to_string(tmp, &map->sid);
2318 make_ldap_mod(ldap_struct, existing, mods, "ntSid", tmp);
2319 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2320 make_ldap_mod(ldap_struct, existing, mods, "ntGroupType", tmp);
2322 make_ldap_mod(ldap_struct, existing, mods, "displayName", map->nt_name);
2323 make_ldap_mod(ldap_struct, existing, mods, "description", map->comment);
2328 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2332 struct ldapsam_privates *ldap_state =
2333 (struct ldapsam_privates *)methods->private_data;
2334 LDAPMessage *result;
2338 if (ldapsam_search_one_group(ldap_state, filter, &result)
2340 return NT_STATUS_NO_SUCH_GROUP;
2343 count = ldap_count_entries(ldap_state->ldap_struct, result);
2346 DEBUG(4, ("Did not find group for filter %s\n", filter));
2347 return NT_STATUS_NO_SUCH_GROUP;
2351 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2353 return NT_STATUS_NO_SUCH_GROUP;
2356 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2359 ldap_msgfree(result);
2360 return NT_STATUS_UNSUCCESSFUL;
2363 if (!init_group_from_ldap(ldap_state, map, entry)) {
2364 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2366 ldap_msgfree(result);
2367 return NT_STATUS_NO_SUCH_GROUP;
2370 ldap_msgfree(result);
2371 return NT_STATUS_OK;
2374 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2375 DOM_SID sid, BOOL with_priv)
2379 snprintf(filter, sizeof(filter)-1,
2380 "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
2381 sid_string_static(&sid));
2383 return ldapsam_getgroup(methods, filter, map);
2386 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2387 gid_t gid, BOOL with_priv)
2391 snprintf(filter, sizeof(filter)-1,
2392 "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
2395 return ldapsam_getgroup(methods, filter, map);
2398 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2399 char *name, BOOL with_priv)
2403 /* TODO: Escaping of name? */
2405 snprintf(filter, sizeof(filter)-1,
2406 "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
2409 return ldapsam_getgroup(methods, filter, map);
2412 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2414 LDAPMessage **result)
2418 snprintf(filter, sizeof(filter)-1,
2419 "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
2421 return ldapsam_search_one_group(ldap_state, filter, result);
2424 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2427 struct ldapsam_privates *ldap_state =
2428 (struct ldapsam_privates *)methods->private_data;
2429 LDAPMessage *result = NULL;
2430 LDAPMod **mods = NULL;
2440 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2441 map->gid, False))) {
2442 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2443 return NT_STATUS_UNSUCCESSFUL;
2446 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2447 if (rc != LDAP_SUCCESS) {
2448 return NT_STATUS_UNSUCCESSFUL;
2451 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
2452 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
2454 ldap_msgfree(result);
2455 return NT_STATUS_UNSUCCESSFUL;
2458 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2459 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
2463 if (!init_ldap_from_group(ldap_state->ldap_struct,
2464 result, &mods, map)) {
2465 DEBUG(0, ("init_ldap_from_group failed!\n"));
2466 ldap_mods_free(mods, 1);
2467 ldap_msgfree(result);
2468 return NT_STATUS_UNSUCCESSFUL;
2471 ldap_msgfree(result);
2474 DEBUG(0, ("mods is empty\n"));
2475 return NT_STATUS_UNSUCCESSFUL;
2478 make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
2479 "sambaGroupMapping");
2481 rc = ldapsam_modify(ldap_state, dn, mods);
2482 ldap_mods_free(mods, 1);
2484 if (rc != LDAP_SUCCESS) {
2485 char *ld_error = NULL;
2486 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2488 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
2489 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2490 SAFE_FREE(ld_error);
2491 return NT_STATUS_UNSUCCESSFUL;
2494 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2495 return NT_STATUS_OK;
2498 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2501 struct ldapsam_privates *ldap_state =
2502 (struct ldapsam_privates *)methods->private_data;
2505 LDAPMessage *result;
2509 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2511 if (rc != LDAP_SUCCESS) {
2512 return NT_STATUS_UNSUCCESSFUL;
2515 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2516 DEBUG(0, ("No group to modify!\n"));
2517 ldap_msgfree(result);
2518 return NT_STATUS_UNSUCCESSFUL;
2521 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2522 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2524 if (!init_ldap_from_group(ldap_state->ldap_struct,
2525 result, &mods, map)) {
2526 DEBUG(0, ("init_ldap_from_group failed\n"));
2527 ldap_msgfree(result);
2528 return NT_STATUS_UNSUCCESSFUL;
2531 ldap_msgfree(result);
2534 DEBUG(4, ("mods is empty: nothing to do\n"));
2535 return NT_STATUS_UNSUCCESSFUL;
2538 rc = ldapsam_modify(ldap_state, dn, mods);
2540 ldap_mods_free(mods, 1);
2542 if (rc != LDAP_SUCCESS) {
2543 char *ld_error = NULL;
2544 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2546 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
2547 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2548 SAFE_FREE(ld_error);
2551 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2552 return NT_STATUS_OK;
2555 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2558 struct ldapsam_privates *ldap_state =
2559 (struct ldapsam_privates *)methods->private_data;
2560 pstring sidstring, filter;
2561 LDAPMessage *result;
2565 const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
2566 "description", "displayName",
2568 sid_to_string(sidstring, &sid);
2569 snprintf(filter, sizeof(filter)-1,
2570 "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
2572 rc = ldapsam_search_one_group(ldap_state, filter, &result);
2574 if (rc != LDAP_SUCCESS) {
2575 return NT_STATUS_NO_SUCH_GROUP;
2578 ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
2580 ldap_msgfree(result);
2584 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
2587 struct ldapsam_privates *ldap_state =
2588 (struct ldapsam_privates *)my_methods->private_data;
2589 const char *filter = "(objectClass=sambaGroupMapping)";
2592 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
2593 LDAP_SCOPE_SUBTREE, filter,
2594 group_attr, 0, &ldap_state->result);
2596 if (rc != LDAP_SUCCESS) {
2597 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2598 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2599 ldap_msgfree(ldap_state->result);
2600 ldap_state->result = NULL;
2601 return NT_STATUS_UNSUCCESSFUL;
2604 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2605 ldap_count_entries(ldap_state->ldap_struct,
2606 ldap_state->result)));
2608 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2609 ldap_state->result);
2610 ldap_state->index = 0;
2612 return NT_STATUS_OK;
2615 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2617 ldapsam_endsampwent(my_methods);
2620 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2623 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2624 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2627 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2628 this will work, but it's not nice. */
2629 static_ldap_state = ldap_state;
2632 if (!ldap_state->entry)
2635 ldap_state->index++;
2636 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2638 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2642 return NT_STATUS_OK;
2645 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2646 enum SID_NAME_USE sid_name_use,
2647 GROUP_MAP **rmap, int *num_entries,
2648 BOOL unix_only, BOOL with_priv)
2658 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2659 DEBUG(0, ("Unable to open passdb\n"));
2660 return NT_STATUS_ACCESS_DENIED;
2663 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
2664 if (sid_name_use != SID_NAME_UNKNOWN &&
2665 sid_name_use != map.sid_name_use) {
2666 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2669 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2670 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
2674 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2676 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
2678 return NT_STATUS_UNSUCCESSFUL;
2683 mapt[entries] = map;
2688 ldapsam_endsamgrent(methods);
2690 *num_entries = entries;
2692 return NT_STATUS_OK;
2695 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2698 struct ldapsam_privates *ldap_state;
2700 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2704 (*pdb_method)->name = "ldapsam";
2706 (*pdb_method)->setsampwent = ldapsam_setsampwent;
2707 (*pdb_method)->endsampwent = ldapsam_endsampwent;
2708 (*pdb_method)->getsampwent = ldapsam_getsampwent;
2709 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2710 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2711 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2712 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2713 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2715 (*pdb_method)->getgrsid = ldapsam_getgrsid;
2716 (*pdb_method)->getgrgid = ldapsam_getgrgid;
2717 (*pdb_method)->getgrnam = ldapsam_getgrnam;
2718 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2719 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2720 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2721 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2723 /* TODO: Setup private data and free */
2725 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
2728 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2729 return NT_STATUS_NO_MEMORY;
2733 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
2734 #ifdef WITH_LDAP_SAMCONFIG
2736 int ldap_port = lp_ldap_port();
2738 /* remap default port if not using SSL (ie clear or TLS) */
2739 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2743 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);
2744 if (!ldap_state->uri) {
2745 return NT_STATUS_NO_MEMORY;
2749 ldap_state->uri = "ldap://localhost";
2753 (*pdb_method)->private_data = ldap_state;
2755 (*pdb_method)->free_private_data = free_private_data;
2757 return NT_STATUS_OK;
2760 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2763 struct ldapsam_privates *ldap_state;
2764 uint32 low_nua_uid, high_nua_uid;
2766 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
2770 (*pdb_method)->name = "ldapsam_nua";
2772 ldap_state = (*pdb_method)->private_data;
2774 ldap_state->permit_non_unix_accounts = True;
2776 if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
2777 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
2778 return NT_STATUS_UNSUCCESSFUL;
2781 ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
2783 ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
2785 return NT_STATUS_OK;
2788 int pdb_ldap_init(void)
2790 smb_register_passdb("ldapsam", pdb_init_ldapsam, PASSDB_INTERFACE_VERSION);
2791 smb_register_passdb("ldapsam_nua", pdb_init_ldapsam_nua, PASSDB_INTERFACE_VERSION);