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;
78 unsigned int num_failures;
81 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
83 static struct ldapsam_privates *static_ldap_state;
85 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
87 /*******************************************************************
88 find the ldap password
89 ******************************************************************/
90 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
95 *dn = smb_xstrdup(lp_ldap_admin_dn());
97 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
99 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
102 *pw=secrets_fetch(key, &size);
104 /* Upgrade 2.2 style entry */
106 char* old_style_key = strdup(*dn);
108 fstring old_style_pw;
110 if (!old_style_key) {
111 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
115 for (p=old_style_key; *p; p++)
116 if (*p == ',') *p = '/';
118 data=secrets_fetch(old_style_key, &size);
119 if (!size && size < sizeof(old_style_pw)) {
120 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
121 SAFE_FREE(old_style_key);
126 strncpy(old_style_pw, data, size);
127 old_style_pw[size] = 0;
131 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
132 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
133 SAFE_FREE(old_style_key);
137 if (!secrets_delete(old_style_key)) {
138 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
141 SAFE_FREE(old_style_key);
143 *pw = smb_xstrdup(old_style_pw);
149 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
150 "logoffTime", "kickoffTime", "cn",
151 "pwdCanChange", "pwdMustChange",
152 "displayName", "homeDrive",
153 "smbHome", "scriptPath",
154 "profilePath", "description",
155 "userWorkstations", "rid",
156 "primaryGroupID", "lmPassword",
157 "ntPassword", "acctFlags",
158 "domain", "objectClass",
159 "uidNumber", "gidNumber",
160 "homeDirectory", NULL };
162 /*******************************************************************
163 open a connection to the ldap server.
164 ******************************************************************/
165 static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
167 int rc = LDAP_SUCCESS;
169 BOOL ldap_v3 = False;
171 #ifdef HAVE_LDAP_INITIALIZE
172 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
174 if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
175 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
181 /* Parse the string manually */
187 const char *p = ldap_state->uri;
188 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
190 /* skip leading "URL:" (if any) */
191 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
195 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
198 if (strequal(protocol, "ldap")) {
200 } else if (strequal(protocol, "ldaps")) {
203 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
207 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
208 DEBUG(0, ("ldap_init failed !\n"));
209 return LDAP_OPERATIONS_ERROR;
212 if (strequal(protocol, "ldaps")) {
213 #ifdef LDAP_OPT_X_TLS
214 int tls = LDAP_OPT_X_TLS_HARD;
215 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
217 DEBUG(0, ("Failed to setup a TLS session\n"));
220 DEBUG(3,("LDAPS option set...!\n"));
222 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
223 return LDAP_OPERATIONS_ERROR;
229 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
231 if (version != LDAP_VERSION3)
233 version = LDAP_VERSION3;
234 if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
242 if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
243 #ifdef LDAP_OPT_X_TLS
245 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
247 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
248 ldap_err2string(rc)));
251 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
254 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
255 return LDAP_OPERATIONS_ERROR;
258 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
259 return LDAP_OPERATIONS_ERROR;
263 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
268 /*******************************************************************
269 a rebind function for authenticated referrals
270 This version takes a void* that we can shove useful stuff in :-)
271 ******************************************************************/
272 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
274 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
275 int *methodp, int freeit, void *arg)
277 struct ldapsam_privates *ldap_state = arg;
279 /** @TODO Should we be doing something to check what servers we rebind to?
280 Could we get a referral to a machine that we don't want to give our
281 username and password to? */
285 memset(*credp, '\0', strlen(*credp));
288 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
289 ldap_state->bind_dn));
291 *whop = strdup(ldap_state->bind_dn);
293 return LDAP_NO_MEMORY;
295 *credp = strdup(ldap_state->bind_secret);
298 return LDAP_NO_MEMORY;
300 *methodp = LDAP_AUTH_SIMPLE;
304 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
306 /*******************************************************************
307 a rebind function for authenticated referrals
308 This version takes a void* that we can shove useful stuff in :-)
309 and actually does the connection.
310 ******************************************************************/
311 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
312 static int rebindproc_connect_with_state (LDAP *ldap_struct,
313 LDAP_CONST char *url,
315 ber_int_t msgid, void *arg)
317 struct ldapsam_privates *ldap_state = arg;
319 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
320 ldap_state->bind_dn));
322 /** @TODO Should we be doing something to check what servers we rebind to?
323 Could we get a referral to a machine that we don't want to give our
324 username and password to? */
326 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
330 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
332 /*******************************************************************
333 Add a rebind function for authenticated referrals
334 ******************************************************************/
335 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
337 # if LDAP_SET_REBIND_PROC_ARGS == 2
338 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
339 int *method, int freeit )
341 return rebindproc_with_state(ldap_struct, whop, credp,
342 method, freeit, static_ldap_state);
345 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
346 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
348 /*******************************************************************
349 a rebind function for authenticated referrals
350 this also does the connection, but no void*.
351 ******************************************************************/
352 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
353 # if LDAP_SET_REBIND_PROC_ARGS == 2
354 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
357 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
360 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
361 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
363 /*******************************************************************
364 connect to the ldap server under system privilege.
365 ******************************************************************/
366 static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
372 /* The rebind proc needs this *HACK*. We are not multithreaded, so
373 this will work, but it's not nice. */
374 static_ldap_state = ldap_state;
376 /* get the password */
377 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
379 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
380 return LDAP_INVALID_CREDENTIALS;
383 ldap_state->bind_dn = ldap_dn;
384 ldap_state->bind_secret = ldap_secret;
386 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
387 (OpenLDAP) doesnt' seem to support it */
389 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
390 ldap_state->uri, ldap_dn));
392 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
393 # if LDAP_SET_REBIND_PROC_ARGS == 2
394 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
396 # if LDAP_SET_REBIND_PROC_ARGS == 3
397 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
399 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
400 # if LDAP_SET_REBIND_PROC_ARGS == 2
401 ldap_set_rebind_proc(ldap_struct, &rebindproc);
403 # if LDAP_SET_REBIND_PROC_ARGS == 3
404 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
406 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
408 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
410 if (rc != LDAP_SUCCESS) {
411 char *ld_error = NULL;
412 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
414 DEBUG(ldap_state->num_failures ? 2 : 0,
415 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
416 ldap_dn ? ld_error : "(unknown)", ldap_err2string(rc),
419 ldap_state->num_failures++;
423 ldap_state->num_failures = 0;
425 DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
429 /**********************************************************************
430 Connect to LDAP server
431 *********************************************************************/
432 static int ldapsam_open(struct ldapsam_privates *ldap_state)
435 SMB_ASSERT(ldap_state);
437 #ifndef NO_LDAP_SECURITY
438 if (geteuid() != 0) {
439 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
440 return LDAP_INSUFFICIENT_ACCESS;
444 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
445 struct sockaddr_un addr;
448 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
449 getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
450 /* the other end has died. reopen. */
451 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
452 ldap_state->ldap_struct = NULL;
453 ldap_state->last_ping = (time_t)0;
455 ldap_state->last_ping = time(NULL);
459 if (ldap_state->ldap_struct != NULL) {
460 DEBUG(5,("ldapsam_open: allready connected to the LDAP server\n"));
464 if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
468 if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
469 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
470 ldap_state->ldap_struct = NULL;
475 ldap_state->last_ping = time(NULL);
476 DEBUG(4,("The LDAP server is succesful connected\n"));
481 /**********************************************************************
482 Disconnect from LDAP server
483 *********************************************************************/
484 static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
487 return NT_STATUS_INVALID_PARAMETER;
489 if (ldap_state->ldap_struct != NULL) {
490 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
491 ldap_state->ldap_struct = NULL;
494 DEBUG(5,("The connection to the LDAP server was closed\n"));
495 /* maybe free the results here --metze */
500 static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
504 SMB_ASSERT(ldap_state && attempts);
506 if (*attempts != 0) {
507 unsigned int sleep_time;
508 uint8 rand_byte = 128; /* a reasonable place to start */
510 generate_random_buffer(&rand_byte, 1, False);
512 sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2;
513 /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
516 DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n",
522 if ((rc = ldapsam_open(ldap_state))) {
523 DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts));
531 static int ldapsam_search(struct ldapsam_privates *ldap_state,
532 const char *base, int scope, const char *filter,
533 const char *attrs[], int attrsonly,
536 int rc = LDAP_SERVER_DOWN;
539 SMB_ASSERT(ldap_state);
541 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
543 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
546 rc = ldap_search_s(ldap_state->ldap_struct, base, scope,
547 filter, (char **)attrs, attrsonly, res);
550 if (rc == LDAP_SERVER_DOWN) {
551 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
552 ldapsam_close(ldap_state);
558 static int ldapsam_modify(struct ldapsam_privates *ldap_state, char *dn, LDAPMod *attrs[])
560 int rc = LDAP_SERVER_DOWN;
566 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
568 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
571 rc = ldap_modify_s(ldap_state->ldap_struct, dn, attrs);
574 if (rc == LDAP_SERVER_DOWN) {
575 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
576 ldapsam_close(ldap_state);
582 static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
584 int rc = LDAP_SERVER_DOWN;
590 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
592 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
595 rc = ldap_add_s(ldap_state->ldap_struct, dn, attrs);
598 if (rc == LDAP_SERVER_DOWN) {
599 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
600 ldapsam_close(ldap_state);
606 static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
608 int rc = LDAP_SERVER_DOWN;
614 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
616 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
619 rc = ldap_delete_s(ldap_state->ldap_struct, dn);
622 if (rc == LDAP_SERVER_DOWN) {
623 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
624 ldapsam_close(ldap_state);
630 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
631 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)
633 int rc = LDAP_SERVER_DOWN;
639 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
641 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
644 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
647 if (rc == LDAP_SERVER_DOWN) {
648 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
649 ldapsam_close(ldap_state);
656 /*******************************************************************
657 run the search by name.
658 ******************************************************************/
659 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, const char *filter, LDAPMessage ** result)
661 int scope = LDAP_SCOPE_SUBTREE;
664 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
666 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, filter, attr, 0, result);
668 if (rc != LDAP_SUCCESS) {
669 char *ld_error = NULL;
670 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
672 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s (%s)\n",
673 ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
674 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
682 /*******************************************************************
683 run the search by name.
684 ******************************************************************/
685 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, const char *user,
686 LDAPMessage ** result)
689 char *escape_user = escape_ldap_string_alloc(user);
692 return LDAP_NO_MEMORY;
696 * in the filter expression, replace %u with the real name
697 * so in ldap filter, %u MUST exist :-)
699 pstrcpy(filter, lp_ldap_filter());
702 * have to use this here because $ is filtered out
707 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
708 SAFE_FREE(escape_user);
710 return ldapsam_search_one_user(ldap_state, filter, result);
713 /*******************************************************************
714 run the search by uid.
715 ******************************************************************/
716 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state,
718 LDAPMessage ** result)
724 /* Get the username from the system and look that up in the LDAP */
726 if ((user = getpwuid_alloc(uid)) == NULL) {
727 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
728 return LDAP_NO_SUCH_OBJECT;
731 pstrcpy(filter, lp_ldap_filter());
733 escape_user = escape_ldap_string_alloc(user->pw_name);
736 return LDAP_NO_MEMORY;
739 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
742 SAFE_FREE(escape_user);
744 return ldapsam_search_one_user(ldap_state, filter, result);
747 /*******************************************************************
748 run the search by rid.
749 ******************************************************************/
750 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state,
752 LDAPMessage ** result)
757 /* check if the user rid exsists, if not, try searching on the uid */
759 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
760 rc = ldapsam_search_one_user(ldap_state, filter, result);
762 if (rc != LDAP_SUCCESS)
763 rc = ldapsam_search_one_user_by_uid(ldap_state,
764 fallback_pdb_user_rid_to_uid(rid),
770 /*******************************************************************
771 search an attribute and return the first value found.
772 ******************************************************************/
773 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
774 const char *attribute, pstring value)
778 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
780 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
785 pstrcpy(value, values[0]);
786 ldap_value_free(values);
787 #ifdef DEBUG_PASSWORDS
788 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
793 /************************************************************************
794 Routine to manage the LDAPMod structure array
795 manage memory used by the array, by each struct, and values
797 ************************************************************************/
798 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
806 if (attribute == NULL || *attribute == '\0')
810 /* Why do we need this??? -- vl */
811 if (value == NULL || *value == '\0')
817 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
820 DEBUG(0, ("make_a_mod: out of memory!\n"));
826 for (i = 0; mods[i] != NULL; ++i) {
827 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
833 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
836 DEBUG(0, ("make_a_mod: out of memory!\n"));
839 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
842 DEBUG(0, ("make_a_mod: out of memory!\n"));
845 mods[i]->mod_op = modop;
846 mods[i]->mod_values = NULL;
847 mods[i]->mod_type = strdup(attribute);
854 if (mods[i]->mod_values != NULL) {
855 for (; mods[i]->mod_values[j] != NULL; j++);
857 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
858 (j + 2) * sizeof (char *));
860 if (mods[i]->mod_values == NULL) {
861 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
864 mods[i]->mod_values[j] = strdup(value);
865 mods[i]->mod_values[j + 1] = NULL;
870 /*******************************************************************
871 Delete complete object or objectclass and attrs from
872 object found in search_result depending on lp_ldap_delete_dn
873 ******************************************************************/
874 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
876 const char *objectclass,
881 LDAPMod **mods = NULL;
883 BerElement *ptr = NULL;
885 rc = ldap_count_entries(ldap_state->ldap_struct, result);
888 DEBUG(0, ("Entry must exist exactly once!\n"));
889 return NT_STATUS_UNSUCCESSFUL;
892 entry = ldap_first_entry(ldap_state->ldap_struct, result);
893 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
895 if (lp_ldap_delete_dn()) {
896 NTSTATUS ret = NT_STATUS_OK;
897 rc = ldapsam_delete(ldap_state, dn);
899 if (rc != LDAP_SUCCESS) {
900 DEBUG(0, ("Could not delete object %s\n", dn));
901 ret = NT_STATUS_UNSUCCESSFUL;
907 /* Ok, delete only the SAM attributes */
909 for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
911 name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) {
915 /* We are only allowed to delete the attributes that
918 for (attrib = attrs; *attrib != NULL; attrib++) {
919 if (StrCaseCmp(*attrib, name) == 0) {
920 DEBUG(10, ("deleting attribute %s\n", name));
921 make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
932 make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
934 rc = ldapsam_modify(ldap_state, dn, mods);
935 ldap_mods_free(mods, 1);
937 if (rc != LDAP_SUCCESS) {
938 char *ld_error = NULL;
939 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
942 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
943 dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
946 return NT_STATUS_UNSUCCESSFUL;
953 /* New Interface is being implemented here */
955 /**********************************************************************
956 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
957 *********************************************************************/
958 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
959 SAM_ACCOUNT * sampass,
969 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
970 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
974 for (values=ldap_values;*values;values++) {
975 if (strcasecmp(*values, "posixAccount") == 0) {
980 if (!*values) { /*end of array, no posixAccount */
981 DEBUG(10, ("user does not have posixAcccount attributes\n"));
982 ldap_value_free(ldap_values);
985 ldap_value_free(ldap_values);
987 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir))
990 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
993 uid = (uid_t)atol(temp);
995 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
998 gid = (gid_t)atol(temp);
1000 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
1001 pdb_set_uid(sampass, uid, PDB_SET);
1002 pdb_set_gid(sampass, gid, PDB_SET);
1004 DEBUG(10, ("user has posixAcccount attributes\n"));
1009 /**********************************************************************
1010 Initialize SAM_ACCOUNT from an LDAP query
1011 (Based on init_sam_from_buffer in pdb_tdb.c)
1012 *********************************************************************/
1013 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
1014 SAM_ACCOUNT * sampass,
1015 LDAPMessage * entry)
1021 pass_can_change_time,
1022 pass_must_change_time;
1037 uint8 smblmpwd[LM_HASH_LEN],
1038 smbntpwd[NT_HASH_LEN];
1039 uint16 acct_ctrl = 0,
1042 uint8 hours[MAX_HOURS_LEN];
1045 gid_t gid = getegid();
1049 * do a little initialization
1053 nt_username[0] = '\0';
1056 dir_drive[0] = '\0';
1057 logon_script[0] = '\0';
1058 profile_path[0] = '\0';
1059 acct_desc[0] = '\0';
1060 munged_dial[0] = '\0';
1061 workstations[0] = '\0';
1064 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1065 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1069 if (ldap_state->ldap_struct == NULL) {
1070 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1074 get_single_attribute(ldap_state->ldap_struct, entry, "uid", username);
1075 DEBUG(2, ("Entry found for user: %s\n", username));
1077 pstrcpy(nt_username, username);
1079 pstrcpy(domain, lp_workgroup());
1081 pdb_set_username(sampass, username, PDB_SET);
1083 pdb_set_domain(sampass, domain, PDB_DEFAULT);
1084 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1086 get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
1087 user_rid = (uint32)atol(temp);
1089 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1091 if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
1094 group_rid = (uint32)atol(temp);
1095 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1100 * If so configured, try and get the values from LDAP
1103 if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state, sampass, entry))) {
1106 * Otherwise just ask the system getpw() calls.
1109 pw = getpwnam_alloc(username);
1111 if (! ldap_state->permit_non_unix_accounts) {
1112 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
1117 pdb_set_uid(sampass, uid, PDB_SET);
1119 pdb_set_gid(sampass, gid, PDB_SET);
1121 pdb_set_unix_homedir(sampass, pw->pw_dir, PDB_SET);
1127 if (group_rid == 0 && pdb_get_init_flags(sampass,PDB_GID) != PDB_DEFAULT) {
1129 gid = pdb_get_gid(sampass);
1130 /* call the mapping code here */
1131 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1132 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1135 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1139 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1140 /* leave as default */
1142 pass_last_set_time = (time_t) atol(temp);
1143 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1146 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1147 /* leave as default */
1149 logon_time = (time_t) atol(temp);
1150 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1153 if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1154 /* leave as default */
1156 logoff_time = (time_t) atol(temp);
1157 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1160 if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1161 /* leave as default */
1163 kickoff_time = (time_t) atol(temp);
1164 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1167 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1168 /* leave as default */
1170 pass_can_change_time = (time_t) atol(temp);
1171 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1174 if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1175 /* leave as default */
1177 pass_must_change_time = (time_t) atol(temp);
1178 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1181 /* recommend that 'gecos' and 'displayName' should refer to the same
1182 * attribute OID. userFullName depreciated, only used by Samba
1183 * primary rules of LDAP: don't make a new attribute when one is already defined
1184 * that fits your needs; using cn then displayName rather than 'userFullName'
1187 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1188 "displayName", fullname)) {
1189 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1191 /* leave as default */
1193 pdb_set_fullname(sampass, fullname, PDB_SET);
1196 pdb_set_fullname(sampass, fullname, PDB_SET);
1199 if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1200 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
1206 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1209 if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1210 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
1216 pdb_set_homedir(sampass, homedir, PDB_SET);
1219 if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1220 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
1226 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1229 if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1230 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
1236 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1239 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1240 /* leave as default */
1242 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1245 if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1246 /* leave as default */;
1248 pdb_set_workstations(sampass, workstations, PDB_SET);
1251 /* FIXME: hours stuff should be cleaner */
1255 memset(hours, 0xff, hours_len);
1257 if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1258 /* leave as default */
1260 pdb_gethexpwd(temp, smblmpwd);
1261 memset((char *)temp, '\0', strlen(temp)+1);
1262 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1264 ZERO_STRUCT(smblmpwd);
1267 if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1268 /* leave as default */
1270 pdb_gethexpwd(temp, smbntpwd);
1271 memset((char *)temp, '\0', strlen(temp)+1);
1272 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1274 ZERO_STRUCT(smbntpwd);
1277 if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1278 acct_ctrl |= ACB_NORMAL;
1280 acct_ctrl = pdb_decode_acct_ctrl(temp);
1283 acct_ctrl |= ACB_NORMAL;
1285 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1288 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1289 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1291 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1293 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1294 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1295 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1297 pdb_set_hours(sampass, hours, PDB_SET);
1302 /**********************************************************************
1303 An LDAP modification is needed in two cases:
1304 * If we are updating the record AND the attribute is CHANGED.
1305 * If we are adding the record AND it is SET or CHANGED (ie not default)
1306 *********************************************************************/
1307 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1308 static BOOL need_ldap_mod(BOOL pdb_add, const SAM_ACCOUNT * sampass, enum pdb_elements element) {
1310 return (!IS_SAM_DEFAULT(sampass, element));
1312 return IS_SAM_CHANGED(sampass, element);
1317 /**********************************************************************
1318 Set attribute to newval in LDAP, regardless of what value the
1319 attribute had in LDAP before.
1320 *********************************************************************/
1321 static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
1323 const char *attribute, const char *newval)
1325 char **values = NULL;
1327 if (existing != NULL) {
1328 values = ldap_get_values(ldap_struct, existing, attribute);
1331 if ((values != NULL) && (values[0] != NULL) &&
1332 strcmp(values[0], newval) == 0) {
1334 /* Believe it or not, but LDAP will deny a delete and
1335 an add at the same time if the values are the
1338 ldap_value_free(values);
1342 /* Regardless of the real operation (add or modify)
1343 we add the new value here. We rely on deleting
1344 the old value, should it exist. */
1346 if ((newval != NULL) && (strlen(newval) > 0)) {
1347 make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
1350 if (values == NULL) {
1351 /* There has been no value before, so don't delete it.
1352 Here's a possible race: We might end up with
1353 duplicate attributes */
1357 /* By deleting exactly the value we found in the entry this
1358 should be race-free in the sense that the LDAP-Server will
1359 deny the complete operation if somebody changed the
1360 attribute behind our back. */
1362 make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
1363 ldap_value_free(values);
1366 /**********************************************************************
1367 Initialize SAM_ACCOUNT from an LDAP query
1368 (Based on init_buffer_from_sam in pdb_tdb.c)
1369 *********************************************************************/
1370 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1371 LDAPMessage *existing,
1372 LDAPMod *** mods, const SAM_ACCOUNT * sampass,
1373 BOOL (*need_update)(const SAM_ACCOUNT *,
1379 if (mods == NULL || sampass == NULL) {
1380 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1387 * took out adding "objectclass: sambaAccount"
1388 * do this on a per-mod basis
1390 if (need_update(sampass, PDB_USERNAME))
1391 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1392 "uid", pdb_get_username(sampass));
1394 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1396 rid = pdb_get_user_rid(sampass);
1399 if (!IS_SAM_DEFAULT(sampass, PDB_UID)) {
1400 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
1401 } else if (ldap_state->permit_non_unix_accounts) {
1402 rid = ldapsam_get_next_available_nua_rid(ldap_state);
1404 DEBUG(0, ("NO user RID specified on account %s, and "
1405 "finding next available NUA RID failed, "
1407 pdb_get_username(sampass)));
1408 ldap_mods_free(*mods, 1);
1412 DEBUG(0, ("NO user RID specified on account %s, "
1413 "cannot store!\n", pdb_get_username(sampass)));
1414 ldap_mods_free(*mods, 1);
1419 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1421 if (need_update(sampass, PDB_USERSID))
1422 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1426 rid = pdb_get_group_rid(sampass);
1429 if (!IS_SAM_DEFAULT(sampass, PDB_GID)) {
1430 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
1431 } else if (ldap_state->permit_non_unix_accounts) {
1432 rid = DOMAIN_GROUP_RID_USERS;
1434 DEBUG(0, ("NO group RID specified on account %s, "
1435 "cannot store!\n", pdb_get_username(sampass)));
1436 ldap_mods_free(*mods, 1);
1441 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1443 if (need_update(sampass, PDB_GROUPSID))
1444 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1445 "primaryGroupID", temp);
1447 /* displayName, cn, and gecos should all be the same
1448 * most easily accomplished by giving them the same OID
1449 * gecos isn't set here b/c it should be handled by the
1451 * We change displayName only and fall back to cn if
1452 * it does not exist.
1455 if (need_update(sampass, PDB_FULLNAME))
1456 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1457 "displayName", pdb_get_fullname(sampass));
1459 if (need_update(sampass, PDB_ACCTDESC))
1460 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1461 "description", pdb_get_acct_desc(sampass));
1463 if (need_update(sampass, PDB_WORKSTATIONS))
1464 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1465 "userWorkstations", pdb_get_workstations(sampass));
1467 if (need_update(sampass, PDB_SMBHOME))
1468 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1469 "smbHome", pdb_get_homedir(sampass));
1471 if (need_update(sampass, PDB_DRIVE))
1472 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1473 "homeDrive", pdb_get_dir_drive(sampass));
1475 if (need_update(sampass, PDB_LOGONSCRIPT))
1476 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1477 "scriptPath", pdb_get_logon_script(sampass));
1479 if (need_update(sampass, PDB_PROFILE))
1480 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1481 "profilePath", pdb_get_profile_path(sampass));
1483 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1485 if (need_update(sampass, PDB_LOGONTIME))
1486 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1489 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1491 if (need_update(sampass, PDB_LOGOFFTIME))
1492 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1493 "logoffTime", temp);
1495 slprintf (temp, sizeof (temp) - 1, "%li",
1496 pdb_get_kickoff_time(sampass));
1498 if (need_update(sampass, PDB_KICKOFFTIME))
1499 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1500 "kickoffTime", temp);
1502 slprintf (temp, sizeof (temp) - 1, "%li",
1503 pdb_get_pass_can_change_time(sampass));
1505 if (need_update(sampass, PDB_CANCHANGETIME))
1506 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1507 "pwdCanChange", temp);
1509 slprintf (temp, sizeof (temp) - 1, "%li",
1510 pdb_get_pass_must_change_time(sampass));
1512 if (need_update(sampass, PDB_MUSTCHANGETIME))
1513 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1514 "pwdMustChange", temp);
1516 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
1517 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1519 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass),
1520 pdb_get_acct_ctrl(sampass));
1522 if (need_update(sampass, PDB_LMPASSWD))
1523 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1524 "lmPassword", temp);
1526 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
1527 pdb_get_acct_ctrl(sampass));
1529 if (need_update(sampass, PDB_NTPASSWD))
1530 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1531 "ntPassword", temp);
1533 slprintf (temp, sizeof (temp) - 1, "%li",
1534 pdb_get_pass_last_set_time(sampass));
1536 if (need_update(sampass, PDB_PASSLASTSET))
1537 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1538 "pwdLastSet", temp);
1541 /* FIXME: Hours stuff goes in LDAP */
1543 if (need_update(sampass, PDB_ACCTCTRL))
1544 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1546 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
1547 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1553 /**********************************************************************
1554 Connect to LDAP server and find the next available RID.
1555 *********************************************************************/
1556 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid)
1558 LDAPMessage *result;
1559 uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
1564 if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
1568 if (ldapsam_search_one_user_by_rid(ldap_state, final_rid, &result) != LDAP_SUCCESS) {
1569 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
1573 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
1574 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
1575 ldap_msgfree(result);
1579 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
1580 ldap_msgfree(result);
1584 /**********************************************************************
1585 Extract the RID from an LDAP entry
1586 *********************************************************************/
1587 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry) {
1589 SAM_ACCOUNT *user = NULL;
1590 if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
1594 if (init_sam_from_ldap(ldap_state, user, entry)) {
1595 rid = pdb_get_user_rid(user);
1599 pdb_free_sam(&user);
1600 if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
1607 /**********************************************************************
1608 Connect to LDAP server and find the next available RID.
1609 *********************************************************************/
1610 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state)
1614 LDAPMessage *result;
1616 char *final_filter = NULL;
1621 pstrcpy(filter, lp_ldap_filter());
1622 all_string_sub(filter, "%u", "*", sizeof(pstring));
1625 asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1627 final_filter = strdup(filter);
1629 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1631 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1632 LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1635 if (rc != LDAP_SUCCESS) {
1636 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1637 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1644 count = ldap_count_entries(ldap_state->ldap_struct, result);
1645 DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1648 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1649 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1651 ldap_msgfree(result);
1653 return ldap_state->low_nua_rid;
1657 entry = ldap_first_entry(ldap_state->ldap_struct,result);
1659 top_rid = entry_to_user_rid(ldap_state, entry);
1661 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1663 rid = entry_to_user_rid(ldap_state, entry);
1664 if (rid > top_rid) {
1669 ldap_msgfree(result);
1671 if (top_rid < ldap_state->low_nua_rid)
1672 top_rid = ldap_state->low_nua_rid;
1677 /**********************************************************************
1678 Connect to LDAP server and find the next available RID.
1679 *********************************************************************/
1680 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1681 uint32 next_nua_rid;
1684 top_nua_rid = search_top_nua_rid(ldap_state);
1686 next_nua_rid = check_nua_rid_is_avail(ldap_state,
1689 return next_nua_rid;
1692 /**********************************************************************
1693 Connect to LDAP server for password enumeration
1694 *********************************************************************/
1695 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1697 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1701 pstrcpy(filter, lp_ldap_filter());
1702 all_string_sub(filter, "%u", "*", sizeof(pstring));
1704 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1705 LDAP_SCOPE_SUBTREE, filter, attr, 0,
1706 &ldap_state->result);
1708 if (rc != LDAP_SUCCESS) {
1709 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1710 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1711 ldap_msgfree(ldap_state->result);
1712 ldap_state->result = NULL;
1713 return NT_STATUS_UNSUCCESSFUL;
1716 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1717 ldap_count_entries(ldap_state->ldap_struct,
1718 ldap_state->result)));
1720 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1721 ldap_state->result);
1722 ldap_state->index = 0;
1724 return NT_STATUS_OK;
1727 /**********************************************************************
1728 End enumeration of the LDAP password list
1729 *********************************************************************/
1730 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1732 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1733 if (ldap_state->result) {
1734 ldap_msgfree(ldap_state->result);
1735 ldap_state->result = NULL;
1739 /**********************************************************************
1740 Get the next entry in the LDAP password database
1741 *********************************************************************/
1742 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1744 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1745 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1748 /* The rebind proc needs this *HACK*. We are not multithreaded, so
1749 this will work, but it's not nice. */
1750 static_ldap_state = ldap_state;
1753 if (!ldap_state->entry)
1756 ldap_state->index++;
1757 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1759 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1763 return NT_STATUS_OK;
1766 /**********************************************************************
1767 Get SAM_ACCOUNT entry from LDAP by username
1768 *********************************************************************/
1769 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1771 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1772 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1773 LDAPMessage *result;
1777 if (ldapsam_search_one_user_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
1778 return NT_STATUS_NO_SUCH_USER;
1781 count = ldap_count_entries(ldap_state->ldap_struct, result);
1785 ("We don't find this user [%s] count=%d\n", sname,
1787 return NT_STATUS_NO_SUCH_USER;
1788 } else if (count > 1) {
1790 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
1792 return NT_STATUS_NO_SUCH_USER;
1795 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1797 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1798 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1799 ldap_msgfree(result);
1800 return NT_STATUS_NO_SUCH_USER;
1802 ldap_msgfree(result);
1805 ldap_msgfree(result);
1810 /**********************************************************************
1811 Get SAM_ACCOUNT entry from LDAP by rid
1812 *********************************************************************/
1813 static NTSTATUS ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
1815 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1816 struct ldapsam_privates *ldap_state =
1817 (struct ldapsam_privates *)my_methods->private_data;
1818 LDAPMessage *result;
1822 if (ldapsam_search_one_user_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
1823 return NT_STATUS_NO_SUCH_USER;
1826 count = ldap_count_entries(ldap_state->ldap_struct, result);
1830 ("We don't find this rid [%i] count=%d\n", rid,
1832 return NT_STATUS_NO_SUCH_USER;
1833 } else if (count > 1) {
1835 ("More than one user with rid [%i]. Failing. count=%d\n", rid,
1837 return NT_STATUS_NO_SUCH_USER;
1840 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1842 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1843 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1844 ldap_msgfree(result);
1845 return NT_STATUS_NO_SUCH_USER;
1847 ldap_msgfree(result);
1850 ldap_msgfree(result);
1855 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1858 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
1859 return NT_STATUS_NO_SUCH_USER;
1860 return ldapsam_getsampwrid(my_methods, user, rid);
1863 /********************************************************************
1864 Do the actual modification - also change a plaittext passord if
1866 **********************************************************************/
1868 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
1869 SAM_ACCOUNT *newpwd, char *dn,
1870 LDAPMod **mods, int ldap_op, BOOL pdb_add)
1872 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1875 if (!my_methods || !newpwd || !dn) {
1876 return NT_STATUS_INVALID_PARAMETER;
1880 DEBUG(5,("mods is empty: nothing to modify\n"));
1881 /* may be password change below however */
1886 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
1887 rc = ldapsam_add(ldap_state, dn, mods);
1889 case LDAP_MOD_REPLACE:
1890 rc = ldapsam_modify(ldap_state, dn ,mods);
1893 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1894 return NT_STATUS_UNSUCCESSFUL;
1897 if (rc!=LDAP_SUCCESS) {
1898 char *ld_error = NULL;
1899 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1902 ("failed to %s user dn= %s with: %s\n\t%s\n",
1903 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1904 dn, ldap_err2string(rc),
1905 ld_error?ld_error:"unknown"));
1906 SAFE_FREE(ld_error);
1907 return NT_STATUS_UNSUCCESSFUL;
1911 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1912 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))&&
1913 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&
1914 need_ldap_mod(pdb_add, newpwd, PDB_PLAINTEXT_PW)&&
1915 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1919 struct berval *retdata;
1921 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1922 DEBUG(0,("ber_alloc_t returns NULL\n"));
1923 return NT_STATUS_UNSUCCESSFUL;
1925 ber_printf (ber, "{");
1926 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
1927 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, pdb_get_plaintext_passwd(newpwd));
1928 ber_printf (ber, "N}");
1930 if ((rc = ber_flatten (ber, &bv))<0) {
1931 DEBUG(0,("ber_flatten returns a value <0\n"));
1932 return NT_STATUS_UNSUCCESSFUL;
1937 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
1938 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
1939 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1940 pdb_get_username(newpwd),ldap_err2string(rc)));
1942 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1944 ber_bvfree(retdata);
1945 ber_memfree(retoid);
1950 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
1951 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
1952 return NT_STATUS_OK;
1955 /**********************************************************************
1956 Delete entry from LDAP for username
1957 *********************************************************************/
1958 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1960 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1963 LDAPMessage *result;
1965 const char *sam_user_attrs[] =
1966 { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
1967 "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
1968 "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
1969 "userWorkstations", "primaryGroupID", "domain", "rid", NULL };
1972 DEBUG(0, ("sam_acct was NULL!\n"));
1973 return NT_STATUS_INVALID_PARAMETER;
1976 sname = pdb_get_username(sam_acct);
1978 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1980 rc = ldapsam_search_one_user_by_name(ldap_state, sname, &result);
1981 if (rc != LDAP_SUCCESS) {
1982 return NT_STATUS_NO_SUCH_USER;
1985 ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
1987 ldap_msgfree(result);
1991 /**********************************************************************
1992 Helper function to determine for update_sam_account whether
1993 we need LDAP modification.
1994 *********************************************************************/
1995 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
1996 enum pdb_elements element)
1998 return IS_SAM_CHANGED(sampass, element);
2001 /**********************************************************************
2003 *********************************************************************/
2004 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2006 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2007 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2010 LDAPMessage *result;
2014 rc = ldapsam_search_one_user_by_name(ldap_state, pdb_get_username(newpwd), &result);
2015 if (rc != LDAP_SUCCESS) {
2016 return NT_STATUS_UNSUCCESSFUL;
2019 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2020 DEBUG(0, ("No user to modify!\n"));
2021 ldap_msgfree(result);
2022 return NT_STATUS_UNSUCCESSFUL;
2025 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2026 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2028 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2029 element_is_changed)) {
2030 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2031 ldap_msgfree(result);
2032 return NT_STATUS_UNSUCCESSFUL;
2035 ldap_msgfree(result);
2038 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2039 pdb_get_username(newpwd)));
2040 ldap_mods_free(mods, 1);
2041 return NT_STATUS_OK;
2044 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, False);
2045 ldap_mods_free(mods,1);
2047 if (!NT_STATUS_IS_OK(ret)) {
2048 char *ld_error = NULL;
2049 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2051 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2052 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
2053 SAFE_FREE(ld_error);
2057 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2058 pdb_get_username(newpwd)));
2059 return NT_STATUS_OK;
2062 /**********************************************************************
2063 Helper function to determine for update_sam_account whether
2064 we need LDAP modification.
2065 *********************************************************************/
2066 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2067 enum pdb_elements element)
2069 return (IS_SAM_SET(sampass, element) ||
2070 IS_SAM_CHANGED(sampass, element));
2073 /**********************************************************************
2074 Add SAM_ACCOUNT to LDAP
2075 *********************************************************************/
2076 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2078 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2079 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2082 LDAPMessage *result = NULL;
2083 LDAPMessage *entry = NULL;
2085 LDAPMod **mods = NULL;
2089 const char *username = pdb_get_username(newpwd);
2090 if (!username || !*username) {
2091 DEBUG(0, ("Cannot add user without a username!\n"));
2092 return NT_STATUS_INVALID_PARAMETER;
2095 rc = ldapsam_search_one_user_by_name (ldap_state, username, &result);
2096 if (rc != LDAP_SUCCESS) {
2097 return NT_STATUS_UNSUCCESSFUL;
2100 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2101 DEBUG(0,("User '%s' already in the base, with samba properties\n",
2103 ldap_msgfree(result);
2104 return NT_STATUS_UNSUCCESSFUL;
2106 ldap_msgfree(result);
2108 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
2109 rc = ldapsam_search_one_user(ldap_state, filter, &result);
2110 if (rc != LDAP_SUCCESS) {
2111 return NT_STATUS_UNSUCCESSFUL;
2114 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2116 if (num_result > 1) {
2117 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2118 ldap_msgfree(result);
2119 return NT_STATUS_UNSUCCESSFUL;
2122 /* Check if we need to update an existing entry */
2123 if (num_result == 1) {
2126 DEBUG(3,("User exists without samba properties: adding them\n"));
2127 ldap_op = LDAP_MOD_REPLACE;
2128 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2129 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2130 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2133 /* Check if we need to add an entry */
2134 DEBUG(3,("Adding new user\n"));
2135 ldap_op = LDAP_MOD_ADD;
2136 if (username[strlen(username)-1] == '$') {
2137 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2139 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2143 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2144 element_is_set_or_changed)) {
2145 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2146 ldap_msgfree(result);
2147 return NT_STATUS_UNSUCCESSFUL;
2150 ldap_msgfree(result);
2153 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2154 return NT_STATUS_UNSUCCESSFUL;
2157 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
2159 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, True);
2160 if (NT_STATUS_IS_ERR(ret)) {
2161 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2162 pdb_get_username(newpwd),dn));
2163 ldap_mods_free(mods,1);
2167 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
2168 ldap_mods_free(mods, 1);
2169 return NT_STATUS_OK;
2172 static void free_private_data(void **vp)
2174 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2176 ldapsam_close(*ldap_state);
2178 if ((*ldap_state)->bind_secret) {
2179 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2182 ldapsam_close(*ldap_state);
2184 SAFE_FREE((*ldap_state)->bind_dn);
2185 SAFE_FREE((*ldap_state)->bind_secret);
2189 /* No need to free any further, as it is talloc()ed */
2192 static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
2194 "displayName", "description",
2197 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2199 LDAPMessage ** result)
2201 int scope = LDAP_SCOPE_SUBTREE;
2204 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2206 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
2207 filter, group_attr, 0, result);
2209 if (rc != LDAP_SUCCESS) {
2210 char *ld_error = NULL;
2211 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2213 DEBUG(0, ("ldapsam_search_one_group: "
2214 "Problem during the LDAP search: LDAP error: %s (%s)",
2215 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
2216 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2217 lp_ldap_suffix(), filter));
2218 SAFE_FREE(ld_error);
2224 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2225 GROUP_MAP *map, LDAPMessage *entry)
2229 if (ldap_state == NULL || map == NULL || entry == NULL ||
2230 ldap_state->ldap_struct == NULL) {
2231 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2235 if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
2237 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
2240 DEBUG(2, ("Entry found for group: %s\n", temp));
2242 map->gid = (gid_t)atol(temp);
2244 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
2246 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
2249 string_to_sid(&map->sid, temp);
2251 if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
2253 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
2256 map->sid_name_use = (uint32)atol(temp);
2258 if ((map->sid_name_use < SID_NAME_USER) ||
2259 (map->sid_name_use > SID_NAME_UNKNOWN)) {
2260 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2264 if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
2266 DEBUG(3, ("Attribute displayName not found\n"));
2268 if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn",
2270 DEBUG(0, ("Attributes cn not found either "
2271 "for gidNumber(%i)\n",map->gid));
2275 fstrcpy(map->nt_name, temp);
2277 if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
2279 DEBUG(3, ("Attribute description not found\n"));
2282 fstrcpy(map->comment, temp);
2284 map->systemaccount = 0;
2285 init_privilege(&map->priv_set);
2290 static BOOL init_ldap_from_group(LDAP *ldap_struct,
2291 LDAPMessage *existing,
2293 const GROUP_MAP *map)
2297 if (mods == NULL || map == NULL) {
2298 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2304 sid_to_string(tmp, &map->sid);
2305 make_ldap_mod(ldap_struct, existing, mods, "ntSid", tmp);
2306 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2307 make_ldap_mod(ldap_struct, existing, mods, "ntGroupType", tmp);
2309 make_ldap_mod(ldap_struct, existing, mods, "displayName", map->nt_name);
2310 make_ldap_mod(ldap_struct, existing, mods, "description", map->comment);
2315 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2319 struct ldapsam_privates *ldap_state =
2320 (struct ldapsam_privates *)methods->private_data;
2321 LDAPMessage *result;
2325 if (ldapsam_search_one_group(ldap_state, filter, &result)
2327 return NT_STATUS_NO_SUCH_GROUP;
2330 count = ldap_count_entries(ldap_state->ldap_struct, result);
2333 DEBUG(4, ("Did not find group for filter %s\n", filter));
2334 return NT_STATUS_NO_SUCH_GROUP;
2338 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2340 return NT_STATUS_NO_SUCH_GROUP;
2343 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2346 ldap_msgfree(result);
2347 return NT_STATUS_UNSUCCESSFUL;
2350 if (!init_group_from_ldap(ldap_state, map, entry)) {
2351 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2353 ldap_msgfree(result);
2354 return NT_STATUS_NO_SUCH_GROUP;
2357 ldap_msgfree(result);
2358 return NT_STATUS_OK;
2361 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2362 DOM_SID sid, BOOL with_priv)
2366 snprintf(filter, sizeof(filter)-1,
2367 "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
2368 sid_string_static(&sid));
2370 return ldapsam_getgroup(methods, filter, map);
2373 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2374 gid_t gid, BOOL with_priv)
2378 snprintf(filter, sizeof(filter)-1,
2379 "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
2382 return ldapsam_getgroup(methods, filter, map);
2385 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2386 char *name, BOOL with_priv)
2390 /* TODO: Escaping of name? */
2392 snprintf(filter, sizeof(filter)-1,
2393 "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
2396 return ldapsam_getgroup(methods, filter, map);
2399 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2401 LDAPMessage **result)
2405 snprintf(filter, sizeof(filter)-1,
2406 "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
2408 return ldapsam_search_one_group(ldap_state, filter, result);
2411 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2414 struct ldapsam_privates *ldap_state =
2415 (struct ldapsam_privates *)methods->private_data;
2416 LDAPMessage *result = NULL;
2417 LDAPMod **mods = NULL;
2427 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2428 map->gid, False))) {
2429 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2430 return NT_STATUS_UNSUCCESSFUL;
2433 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2434 if (rc != LDAP_SUCCESS) {
2435 return NT_STATUS_UNSUCCESSFUL;
2438 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
2439 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
2441 ldap_msgfree(result);
2442 return NT_STATUS_UNSUCCESSFUL;
2445 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2446 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
2450 if (!init_ldap_from_group(ldap_state->ldap_struct,
2451 result, &mods, map)) {
2452 DEBUG(0, ("init_ldap_from_group failed!\n"));
2453 ldap_mods_free(mods, 1);
2454 ldap_msgfree(result);
2455 return NT_STATUS_UNSUCCESSFUL;
2458 ldap_msgfree(result);
2461 DEBUG(0, ("mods is empty\n"));
2462 return NT_STATUS_UNSUCCESSFUL;
2465 make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
2466 "sambaGroupMapping");
2468 rc = ldapsam_modify(ldap_state, dn, mods);
2469 ldap_mods_free(mods, 1);
2471 if (rc != LDAP_SUCCESS) {
2472 char *ld_error = NULL;
2473 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2475 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
2476 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2477 SAFE_FREE(ld_error);
2478 return NT_STATUS_UNSUCCESSFUL;
2481 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2482 return NT_STATUS_OK;
2485 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2488 struct ldapsam_privates *ldap_state =
2489 (struct ldapsam_privates *)methods->private_data;
2492 LDAPMessage *result;
2496 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2498 if (rc != LDAP_SUCCESS) {
2499 return NT_STATUS_UNSUCCESSFUL;
2502 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2503 DEBUG(0, ("No group to modify!\n"));
2504 ldap_msgfree(result);
2505 return NT_STATUS_UNSUCCESSFUL;
2508 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2509 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2511 if (!init_ldap_from_group(ldap_state->ldap_struct,
2512 result, &mods, map)) {
2513 DEBUG(0, ("init_ldap_from_group failed\n"));
2514 ldap_msgfree(result);
2515 return NT_STATUS_UNSUCCESSFUL;
2518 ldap_msgfree(result);
2521 DEBUG(4, ("mods is empty: nothing to do\n"));
2522 return NT_STATUS_UNSUCCESSFUL;
2525 rc = ldapsam_modify(ldap_state, dn, mods);
2527 ldap_mods_free(mods, 1);
2529 if (rc != LDAP_SUCCESS) {
2530 char *ld_error = NULL;
2531 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2533 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
2534 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2535 SAFE_FREE(ld_error);
2538 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2539 return NT_STATUS_OK;
2542 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2545 struct ldapsam_privates *ldap_state =
2546 (struct ldapsam_privates *)methods->private_data;
2547 pstring sidstring, filter;
2548 LDAPMessage *result;
2552 const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
2553 "description", "displayName",
2555 sid_to_string(sidstring, &sid);
2556 snprintf(filter, sizeof(filter)-1,
2557 "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
2559 rc = ldapsam_search_one_group(ldap_state, filter, &result);
2561 if (rc != LDAP_SUCCESS) {
2562 return NT_STATUS_NO_SUCH_GROUP;
2565 ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
2567 ldap_msgfree(result);
2571 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
2574 struct ldapsam_privates *ldap_state =
2575 (struct ldapsam_privates *)my_methods->private_data;
2576 const char *filter = "(objectClass=sambaGroupMapping)";
2579 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
2580 LDAP_SCOPE_SUBTREE, filter,
2581 group_attr, 0, &ldap_state->result);
2583 if (rc != LDAP_SUCCESS) {
2584 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2585 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2586 ldap_msgfree(ldap_state->result);
2587 ldap_state->result = NULL;
2588 return NT_STATUS_UNSUCCESSFUL;
2591 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2592 ldap_count_entries(ldap_state->ldap_struct,
2593 ldap_state->result)));
2595 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2596 ldap_state->result);
2597 ldap_state->index = 0;
2599 return NT_STATUS_OK;
2602 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2604 ldapsam_endsampwent(my_methods);
2607 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2610 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2611 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2614 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2615 this will work, but it's not nice. */
2616 static_ldap_state = ldap_state;
2619 if (!ldap_state->entry)
2622 ldap_state->index++;
2623 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2625 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2629 return NT_STATUS_OK;
2632 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2633 enum SID_NAME_USE sid_name_use,
2634 GROUP_MAP **rmap, int *num_entries,
2635 BOOL unix_only, BOOL with_priv)
2645 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2646 DEBUG(0, ("Unable to open passdb\n"));
2647 return NT_STATUS_ACCESS_DENIED;
2650 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
2651 if (sid_name_use != SID_NAME_UNKNOWN &&
2652 sid_name_use != map.sid_name_use) {
2653 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2656 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2657 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
2661 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2663 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
2665 return NT_STATUS_UNSUCCESSFUL;
2670 mapt[entries] = map;
2675 ldapsam_endsamgrent(methods);
2677 *num_entries = entries;
2679 return NT_STATUS_OK;
2682 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2685 struct ldapsam_privates *ldap_state;
2687 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2691 (*pdb_method)->name = "ldapsam";
2693 (*pdb_method)->setsampwent = ldapsam_setsampwent;
2694 (*pdb_method)->endsampwent = ldapsam_endsampwent;
2695 (*pdb_method)->getsampwent = ldapsam_getsampwent;
2696 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2697 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2698 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2699 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2700 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2702 (*pdb_method)->getgrsid = ldapsam_getgrsid;
2703 (*pdb_method)->getgrgid = ldapsam_getgrgid;
2704 (*pdb_method)->getgrnam = ldapsam_getgrnam;
2705 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2706 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2707 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2708 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2710 /* TODO: Setup private data and free */
2712 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
2715 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2716 return NT_STATUS_NO_MEMORY;
2720 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
2721 #ifdef WITH_LDAP_SAMCONFIG
2723 int ldap_port = lp_ldap_port();
2725 /* remap default port if not using SSL (ie clear or TLS) */
2726 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2730 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);
2731 if (!ldap_state->uri) {
2732 return NT_STATUS_NO_MEMORY;
2736 ldap_state->uri = "ldap://localhost";
2740 (*pdb_method)->private_data = ldap_state;
2742 (*pdb_method)->free_private_data = free_private_data;
2744 return NT_STATUS_OK;
2747 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2750 struct ldapsam_privates *ldap_state;
2751 uint32 low_nua_uid, high_nua_uid;
2753 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
2757 (*pdb_method)->name = "ldapsam_nua";
2759 ldap_state = (*pdb_method)->private_data;
2761 ldap_state->permit_non_unix_accounts = True;
2763 if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
2764 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
2765 return NT_STATUS_UNSUCCESSFUL;
2768 ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
2770 ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
2772 return NT_STATUS_OK;
2775 int pdb_ldap_init(void)
2777 smb_register_passdb("ldapsam", pdb_init_ldapsam, PASSDB_INTERFACE_VERSION);
2778 smb_register_passdb("ldapsam_nua", pdb_init_ldapsam_nua, PASSDB_INTERFACE_VERSION);