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