Ok, this patch removes the privilege stuff we had in, unused, for some time.
[Samba.git] / source / passdb / pdb_ldap.c
blobe8ba63907327861978d0c9459159bbfa3914f052
1 /*
2 Unix SMB/CIFS mplementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Jean François Micouleau 1998
5 Copyright (C) Gerald Carter 2001-2003
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 /* TODO:
27 * persistent connections: if using NSS LDAP, many connections are made
28 * however, using only one within Samba would be nice
30 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
32 * Other LDAP based login attributes: accountExpires, etc.
33 * (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
34 * structures don't have fields for some of these attributes)
36 * SSL is done, but can't get the certificate based authentication to work
37 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
40 /* NOTE: this will NOT work against an Active Directory server
41 * due to the fact that the two password fields cannot be retrieved
42 * from a server; recommend using security = domain in this situation
43 * and/or winbind
46 #include "includes.h"
48 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_PASSDB
51 #include <lber.h>
52 #include <ldap.h>
54 #ifndef LDAP_OPT_SUCCESS
55 #define LDAP_OPT_SUCCESS 0
56 #endif
58 #if defined(LDAP_EXOP_X_MODIFY_PASSWD) && !defined(LDAP_EXOP_MODIFY_PASSWD)
59 #define LDAP_EXOP_MODIFY_PASSWD LDAP_EXOP_X_MODIFY_PASSWD
60 #elif !defined(LDAP_EXOP_MODIFY_PASSWD)
61 #define "1.3.6.1.4.1.4203.1.11.1"
62 #endif
64 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_ID) && !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
65 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID LDAP_EXOP_X_MODIFY_PASSWD_ID
66 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
67 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID ((ber_tag_t) 0x80U)
68 #endif
70 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_NEW) && !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
71 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW LDAP_EXOP_X_MODIFY_PASSWD_NEW
72 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
73 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U)
74 #endif
76 #ifndef SAM_ACCOUNT
77 #define SAM_ACCOUNT struct sam_passwd
78 #endif
80 #include "smbldap.h"
82 struct ldapsam_privates {
83 /* Former statics */
84 LDAP *ldap_struct;
85 LDAPMessage *result;
86 LDAPMessage *entry;
87 int index;
89 time_t last_ping;
90 /* retrive-once info */
91 const char *uri;
92 const char *domain_name;
93 DOM_SID domain_sid;
95 /* configuration items */
96 int schema_ver;
98 BOOL permit_non_unix_accounts;
100 uint32 low_allocated_user_rid;
101 uint32 high_allocated_user_rid;
103 uint32 low_allocated_group_rid;
104 uint32 high_allocated_group_rid;
106 char *bind_dn;
107 char *bind_secret;
109 unsigned int num_failures;
112 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
114 static struct ldapsam_privates *static_ldap_state;
117 /**********************************************************************
118 get the attribute name given a user schame version
119 **********************************************************************/
121 static const char* get_userattr_key2string( int schema_ver, int key )
123 switch ( schema_ver )
125 case SCHEMAVER_SAMBAACCOUNT:
126 return get_attr_key2string( attrib_map_v22, key );
128 case SCHEMAVER_SAMBASAMACCOUNT:
129 return get_attr_key2string( attrib_map_v30, key );
131 default:
132 DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
133 break;
135 return NULL;
138 /**********************************************************************
139 return the list of attribute names given a user schema version
140 **********************************************************************/
142 static char** get_userattr_list( int schema_ver )
144 switch ( schema_ver )
146 case SCHEMAVER_SAMBAACCOUNT:
147 return get_attr_list( attrib_map_v22 );
149 case SCHEMAVER_SAMBASAMACCOUNT:
150 return get_attr_list( attrib_map_v30 );
151 default:
152 DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
153 break;
156 return NULL;
159 /*******************************************************************
160 open a connection to the ldap server.
161 ******************************************************************/
162 static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
164 int rc = LDAP_SUCCESS;
165 int version;
166 BOOL ldap_v3 = False;
168 #ifdef HAVE_LDAP_INITIALIZE
169 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
171 if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
172 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
173 return rc;
176 #else
178 /* Parse the string manually */
181 int port = 0;
182 fstring protocol;
183 fstring host;
184 const char *p = ldap_state->uri;
185 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
187 /* skip leading "URL:" (if any) */
188 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
189 p += 4;
192 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
194 if (port == 0) {
195 if (strequal(protocol, "ldap")) {
196 port = LDAP_PORT;
197 } else if (strequal(protocol, "ldaps")) {
198 port = LDAPS_PORT;
199 } else {
200 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
204 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
205 DEBUG(0, ("ldap_init failed !\n"));
206 return LDAP_OPERATIONS_ERROR;
209 if (strequal(protocol, "ldaps")) {
210 #ifdef LDAP_OPT_X_TLS
211 int tls = LDAP_OPT_X_TLS_HARD;
212 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
214 DEBUG(0, ("Failed to setup a TLS session\n"));
217 DEBUG(3,("LDAPS option set...!\n"));
218 #else
219 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
220 return LDAP_OPERATIONS_ERROR;
221 #endif
224 #endif
226 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
228 if (version != LDAP_VERSION3)
230 version = LDAP_VERSION3;
231 if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
232 ldap_v3 = True;
234 } else {
235 ldap_v3 = True;
239 if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
240 #ifdef LDAP_OPT_X_TLS
241 if (ldap_v3) {
242 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
244 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
245 ldap_err2string(rc)));
246 return rc;
248 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
249 } else {
251 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
252 return LDAP_OPERATIONS_ERROR;
254 #else
255 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
256 return LDAP_OPERATIONS_ERROR;
257 #endif
260 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
261 return rc;
265 /*******************************************************************
266 a rebind function for authenticated referrals
267 This version takes a void* that we can shove useful stuff in :-)
268 ******************************************************************/
269 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
270 #else
271 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
272 int *methodp, int freeit, void *arg)
274 struct ldapsam_privates *ldap_state = arg;
276 /** @TODO Should we be doing something to check what servers we rebind to?
277 Could we get a referral to a machine that we don't want to give our
278 username and password to? */
280 if (freeit) {
281 SAFE_FREE(*whop);
282 memset(*credp, '\0', strlen(*credp));
283 SAFE_FREE(*credp);
284 } else {
285 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
286 ldap_state->bind_dn));
288 *whop = strdup(ldap_state->bind_dn);
289 if (!*whop) {
290 return LDAP_NO_MEMORY;
292 *credp = strdup(ldap_state->bind_secret);
293 if (!*credp) {
294 SAFE_FREE(*whop);
295 return LDAP_NO_MEMORY;
297 *methodp = LDAP_AUTH_SIMPLE;
299 return 0;
301 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
303 /*******************************************************************
304 a rebind function for authenticated referrals
305 This version takes a void* that we can shove useful stuff in :-)
306 and actually does the connection.
307 ******************************************************************/
308 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
309 static int rebindproc_connect_with_state (LDAP *ldap_struct,
310 LDAP_CONST char *url,
311 ber_tag_t request,
312 ber_int_t msgid, void *arg)
314 struct ldapsam_privates *ldap_state = arg;
315 int rc;
316 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
317 ldap_state->bind_dn));
319 /** @TODO Should we be doing something to check what servers we rebind to?
320 Could we get a referral to a machine that we don't want to give our
321 username and password to? */
323 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
325 return rc;
327 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
329 /*******************************************************************
330 Add a rebind function for authenticated referrals
331 ******************************************************************/
332 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
333 #else
334 # if LDAP_SET_REBIND_PROC_ARGS == 2
335 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
336 int *method, int freeit )
338 return rebindproc_with_state(ldap_struct, whop, credp,
339 method, freeit, static_ldap_state);
342 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
343 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
345 /*******************************************************************
346 a rebind function for authenticated referrals
347 this also does the connection, but no void*.
348 ******************************************************************/
349 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
350 # if LDAP_SET_REBIND_PROC_ARGS == 2
351 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
352 ber_int_t msgid)
354 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
355 static_ldap_state);
357 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
358 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
360 /*******************************************************************
361 connect to the ldap server under system privilege.
362 ******************************************************************/
363 static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
365 int rc;
366 char *ldap_dn;
367 char *ldap_secret;
369 /* The rebind proc needs this *HACK*. We are not multithreaded, so
370 this will work, but it's not nice. */
371 static_ldap_state = ldap_state;
373 /* get the password */
374 if (!fetch_ldap_pw(&ldap_dn, &ldap_secret))
376 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
377 return LDAP_INVALID_CREDENTIALS;
380 ldap_state->bind_dn = ldap_dn;
381 ldap_state->bind_secret = ldap_secret;
383 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
384 (OpenLDAP) doesnt' seem to support it */
386 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
387 ldap_state->uri, ldap_dn));
389 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
390 # if LDAP_SET_REBIND_PROC_ARGS == 2
391 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
392 # endif
393 # if LDAP_SET_REBIND_PROC_ARGS == 3
394 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
395 # endif
396 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
397 # if LDAP_SET_REBIND_PROC_ARGS == 2
398 ldap_set_rebind_proc(ldap_struct, &rebindproc);
399 # endif
400 # if LDAP_SET_REBIND_PROC_ARGS == 3
401 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
402 # endif
403 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
405 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
407 if (rc != LDAP_SUCCESS) {
408 char *ld_error = NULL;
409 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
410 &ld_error);
411 DEBUG(ldap_state->num_failures ? 2 : 0,
412 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
413 ldap_dn ? ld_error : "(unknown)", ldap_err2string(rc),
414 ld_error));
415 SAFE_FREE(ld_error);
416 ldap_state->num_failures++;
417 return rc;
420 ldap_state->num_failures = 0;
422 DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
423 return rc;
426 /**********************************************************************
427 Connect to LDAP server
428 *********************************************************************/
429 static int ldapsam_open(struct ldapsam_privates *ldap_state)
431 int rc;
432 SMB_ASSERT(ldap_state);
434 #ifndef NO_LDAP_SECURITY
435 if (geteuid() != 0) {
436 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
437 return LDAP_INSUFFICIENT_ACCESS;
439 #endif
441 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
442 struct sockaddr_un addr;
443 socklen_t len = sizeof(addr);
444 int sd;
445 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
446 getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
447 /* the other end has died. reopen. */
448 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
449 ldap_state->ldap_struct = NULL;
450 ldap_state->last_ping = (time_t)0;
451 } else {
452 ldap_state->last_ping = time(NULL);
456 if (ldap_state->ldap_struct != NULL) {
457 DEBUG(5,("ldapsam_open: already connected to the LDAP server\n"));
458 return LDAP_SUCCESS;
461 if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
462 return rc;
465 if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
466 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
467 ldap_state->ldap_struct = NULL;
468 return rc;
472 ldap_state->last_ping = time(NULL);
473 DEBUG(4,("The LDAP server is succesful connected\n"));
475 return LDAP_SUCCESS;
478 /**********************************************************************
479 Disconnect from LDAP server
480 *********************************************************************/
481 static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
483 if (!ldap_state)
484 return NT_STATUS_INVALID_PARAMETER;
486 if (ldap_state->ldap_struct != NULL) {
487 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
488 ldap_state->ldap_struct = NULL;
491 DEBUG(5,("The connection to the LDAP server was closed\n"));
492 /* maybe free the results here --metze */
494 return NT_STATUS_OK;
497 static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
499 int rc;
501 SMB_ASSERT(ldap_state && attempts);
503 if (*attempts != 0) {
504 unsigned int sleep_time;
505 uint8 rand_byte;
507 /* Sleep for a random timeout */
508 rand_byte = (char)(sys_random());
510 sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2;
511 /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
512 on average.
514 DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n",
515 sleep_time));
516 msleep(sleep_time);
518 (*attempts)++;
520 if ((rc = ldapsam_open(ldap_state))) {
521 DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts));
522 return rc;
525 return LDAP_SUCCESS;
529 /*********************************************************************
530 ********************************************************************/
532 static int ldapsam_search(struct ldapsam_privates *ldap_state,
533 const char *base, int scope, const char *filter,
534 char *attrs[], int attrsonly,
535 LDAPMessage **res)
537 int rc = LDAP_SERVER_DOWN;
538 int attempts = 0;
539 char *utf8_filter;
541 SMB_ASSERT(ldap_state);
543 if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) {
544 return LDAP_NO_MEMORY;
547 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
549 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
550 continue;
552 rc = ldap_search_s(ldap_state->ldap_struct, base, scope,
553 utf8_filter, attrs, attrsonly, res);
556 if (rc == LDAP_SERVER_DOWN) {
557 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
558 ldapsam_close(ldap_state);
561 SAFE_FREE(utf8_filter);
562 return rc;
565 static int ldapsam_modify(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
567 int rc = LDAP_SERVER_DOWN;
568 int attempts = 0;
569 char *utf8_dn;
571 SMB_ASSERT(ldap_state);
573 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
574 return LDAP_NO_MEMORY;
577 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
579 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
580 continue;
582 rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
585 if (rc == LDAP_SERVER_DOWN) {
586 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
587 ldapsam_close(ldap_state);
590 SAFE_FREE(utf8_dn);
591 return rc;
594 static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
596 int rc = LDAP_SERVER_DOWN;
597 int attempts = 0;
598 char *utf8_dn;
600 SMB_ASSERT(ldap_state);
602 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
603 return LDAP_NO_MEMORY;
606 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
608 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
609 continue;
611 rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
614 if (rc == LDAP_SERVER_DOWN) {
615 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
616 ldapsam_close(ldap_state);
619 SAFE_FREE(utf8_dn);
620 return rc;
623 static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
625 int rc = LDAP_SERVER_DOWN;
626 int attempts = 0;
627 char *utf8_dn;
629 SMB_ASSERT(ldap_state);
631 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
632 return LDAP_NO_MEMORY;
635 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
637 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
638 continue;
640 rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
643 if (rc == LDAP_SERVER_DOWN) {
644 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
645 ldapsam_close(ldap_state);
648 SAFE_FREE(utf8_dn);
649 return rc;
652 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)
654 int rc = LDAP_SERVER_DOWN;
655 int attempts = 0;
657 if (!ldap_state)
658 return (-1);
660 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
662 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
663 continue;
665 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
668 if (rc == LDAP_SERVER_DOWN) {
669 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
670 ldapsam_close(ldap_state);
673 return rc;
676 /*******************************************************************
677 run the search by name.
678 ******************************************************************/
679 static int ldapsam_search_suffix (struct ldapsam_privates *ldap_state, const char *filter,
680 char **search_attr, LDAPMessage ** result)
682 int scope = LDAP_SCOPE_SUBTREE;
683 int rc;
685 DEBUG(2, ("ldapsam_search_suffix: searching for:[%s]\n", filter));
687 rc = ldapsam_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result);
689 if (rc != LDAP_SUCCESS) {
690 char *ld_error = NULL;
691 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
692 &ld_error);
693 DEBUG(0,("ldapsam_search_suffix: Problem during the LDAP search: %s (%s)\n",
694 ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
695 DEBUG(3,("ldapsam_search_suffix: Query was: %s, %s\n", lp_ldap_suffix(),
696 filter));
697 SAFE_FREE(ld_error);
700 return rc;
703 /*******************************************************************
704 generate the LDAP search filter for the objectclass based on the
705 version of the schema we are using
706 ******************************************************************/
708 static const char* get_objclass_filter( int schema_ver )
710 static fstring objclass_filter;
712 switch( schema_ver )
714 case SCHEMAVER_SAMBAACCOUNT:
715 snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT );
716 break;
717 case SCHEMAVER_SAMBASAMACCOUNT:
718 snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT );
719 break;
720 default:
721 DEBUG(0,("ldapsam_search_suffix_by_name(): Invalid schema version specified!\n"));
722 break;
725 return objclass_filter;
728 /*******************************************************************
729 run the search by name.
730 ******************************************************************/
731 static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, const char *user,
732 LDAPMessage ** result, char **attr)
734 pstring filter;
735 char *escape_user = escape_ldap_string_alloc(user);
737 if (!escape_user) {
738 return LDAP_NO_MEMORY;
742 * in the filter expression, replace %u with the real name
743 * so in ldap filter, %u MUST exist :-)
745 snprintf(filter, sizeof(filter)-1, "(&%s%s)", lp_ldap_filter(),
746 get_objclass_filter(ldap_state->schema_ver));
749 * have to use this here because $ is filtered out
750 * in pstring_sub
754 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
755 SAFE_FREE(escape_user);
757 return ldapsam_search_suffix(ldap_state, filter, attr, result);
760 /*******************************************************************
761 run the search by rid.
762 ******************************************************************/
763 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
764 uint32 rid, LDAPMessage ** result,
765 char **attr)
767 pstring filter;
768 int rc;
770 /* check if the user rid exists, if not, try searching on the uid */
772 snprintf(filter, sizeof(filter)-1, "(&(rid=%i)%s)", rid,
773 get_objclass_filter(ldap_state->schema_ver));
775 rc = ldapsam_search_suffix(ldap_state, filter, attr, result);
777 return rc;
780 /*******************************************************************
781 run the search by SID.
782 ******************************************************************/
783 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
784 const DOM_SID *sid, LDAPMessage ** result,
785 char **attr)
787 pstring filter;
788 int rc;
789 fstring sid_string;
791 /* check if the user rid exsists, if not, try searching on the uid */
793 snprintf(filter, sizeof(filter)-1, "(&(%s=%s)%s)",
794 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
795 sid_to_string(sid_string, sid),
796 get_objclass_filter(ldap_state->schema_ver));
798 rc = ldapsam_search_suffix(ldap_state, filter, attr, result);
800 return rc;
803 /*******************************************************************
804 search an attribute and return the first value found.
805 ******************************************************************/
806 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
807 const char *attribute, pstring value)
809 char **values;
811 if ( !attribute )
812 return False;
814 value[0] = '\0';
816 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
817 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
819 return False;
822 if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1)
824 DEBUG(1, ("get_single_attribute: string conversion of [%s] = [%s] failed!\n",
825 attribute, values[0]));
826 ldap_value_free(values);
827 return False;
830 ldap_value_free(values);
831 #ifdef DEBUG_PASSWORDS
832 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
833 #endif
834 return True;
837 /**********************************************************************
838 Set attribute to newval in LDAP, regardless of what value the
839 attribute had in LDAP before.
840 *********************************************************************/
841 static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
842 LDAPMod ***mods,
843 const char *attribute, const char *newval)
845 char **values = NULL;
847 if (existing != NULL) {
848 values = ldap_get_values(ldap_struct, existing, attribute);
851 /* all of our string attributes are case insensitive */
853 if ((values != NULL) && (values[0] != NULL) &&
854 StrCaseCmp(values[0], newval) == 0)
857 /* Believe it or not, but LDAP will deny a delete and
858 an add at the same time if the values are the
859 same... */
861 ldap_value_free(values);
862 return;
865 /* Regardless of the real operation (add or modify)
866 we add the new value here. We rely on deleting
867 the old value, should it exist. */
869 if ((newval != NULL) && (strlen(newval) > 0)) {
870 ldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
873 if (values == NULL) {
874 /* There has been no value before, so don't delete it.
875 Here's a possible race: We might end up with
876 duplicate attributes */
877 return;
880 /* By deleting exactly the value we found in the entry this
881 should be race-free in the sense that the LDAP-Server will
882 deny the complete operation if somebody changed the
883 attribute behind our back. */
885 ldap_set_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
886 ldap_value_free(values);
889 /*******************************************************************
890 Delete complete object or objectclass and attrs from
891 object found in search_result depending on lp_ldap_delete_dn
892 ******************************************************************/
893 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
894 LDAPMessage *result,
895 const char *objectclass,
896 char **attrs)
898 int rc;
899 LDAPMessage *entry;
900 LDAPMod **mods = NULL;
901 char *name, *dn;
902 BerElement *ptr = NULL;
904 rc = ldap_count_entries(ldap_state->ldap_struct, result);
906 if (rc != 1) {
907 DEBUG(0, ("Entry must exist exactly once!\n"));
908 return NT_STATUS_UNSUCCESSFUL;
911 entry = ldap_first_entry(ldap_state->ldap_struct, result);
912 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
914 if (lp_ldap_delete_dn()) {
915 NTSTATUS ret = NT_STATUS_OK;
916 rc = ldapsam_delete(ldap_state, dn);
918 if (rc != LDAP_SUCCESS) {
919 DEBUG(0, ("Could not delete object %s\n", dn));
920 ret = NT_STATUS_UNSUCCESSFUL;
922 ldap_memfree(dn);
923 return ret;
926 /* Ok, delete only the SAM attributes */
928 for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
929 name != NULL;
930 name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr))
932 char **attrib;
934 /* We are only allowed to delete the attributes that
935 really exist. */
937 for (attrib = attrs; *attrib != NULL; attrib++)
939 if (StrCaseCmp(*attrib, name) == 0) {
940 DEBUG(10, ("deleting attribute %s\n", name));
941 ldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL);
945 ldap_memfree(name);
948 if (ptr != NULL) {
949 ber_free(ptr, 0);
952 ldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
954 rc = ldapsam_modify(ldap_state, dn, mods);
955 ldap_mods_free(mods, True);
957 if (rc != LDAP_SUCCESS) {
958 char *ld_error = NULL;
959 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
960 &ld_error);
962 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
963 dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
964 SAFE_FREE(ld_error);
965 ldap_memfree(dn);
966 return NT_STATUS_UNSUCCESSFUL;
969 ldap_memfree(dn);
970 return NT_STATUS_OK;
973 /**********************************************************************
974 Search for the domain info entry
975 *********************************************************************/
976 static int ldapsam_search_domain_info(struct ldapsam_privates *ldap_state,
977 LDAPMessage ** result)
979 pstring filter;
980 int rc;
981 char **attr_list;
983 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
984 LDAP_OBJ_DOMINFO,
985 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
986 ldap_state->domain_name);
988 DEBUG(2, ("Searching for:[%s]\n", filter));
991 attr_list = get_attr_list( dominfo_attr_list );
992 rc = ldapsam_search_suffix(ldap_state, filter, attr_list , result);
993 free_attr_list( attr_list );
995 if (rc != LDAP_SUCCESS) {
996 DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
997 DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1000 return rc;
1003 /**********************************************************************
1004 If this entry is is the 'allocated' range, extract the RID and return
1005 it, so we can find the 'next' rid to allocate.
1007 Do this, no matter what type of object holds the RID - be it a user,
1008 group or somthing else.
1009 *********************************************************************/
1010 static uint32 entry_to_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, int rid_type)
1012 pstring sid_string;
1013 DOM_SID dom_sid;
1014 uint32 rid;
1016 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1017 LDAP_ATTRIBUTE_SID, sid_string))
1019 return 0;
1022 if (!string_to_sid(&dom_sid, sid_string)) {
1023 return 0;
1026 if (!sid_peek_check_rid(&dom_sid, get_global_sam_sid(), &rid)) {
1027 /* not our domain, so we don't care */
1028 return 0;
1031 switch (rid_type) {
1032 case USER_RID_TYPE:
1033 if (rid >= ldap_state->low_allocated_user_rid &&
1034 rid <= ldap_state->high_allocated_user_rid) {
1035 return rid;
1037 break;
1038 case GROUP_RID_TYPE:
1039 if (rid >= ldap_state->low_allocated_group_rid &&
1040 rid <= ldap_state->high_allocated_group_rid) {
1041 return rid;
1043 break;
1045 return 0;
1049 /**********************************************************************
1050 Connect to LDAP server and find the next available 'allocated' RID.
1052 The search is done 'per type' as we allocate seperate pools for the
1053 EVEN and ODD (user and group) RIDs.
1055 This is only done once, so that we can fill out the sambaDomain.
1056 *********************************************************************/
1057 static uint32 search_next_allocated_rid(struct ldapsam_privates *ldap_state, int rid_type)
1059 int rc;
1060 LDAPMessage *result;
1061 LDAPMessage *entry;
1062 uint32 top_rid = 0;
1063 uint32 next_rid;
1064 uint32 count;
1065 uint32 rid;
1066 char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
1067 fstring filter;
1069 snprintf( filter, sizeof(filter)-1, "(%s=*)", LDAP_ATTRIBUTE_SID );
1071 DEBUG(2, ("search_top_allocated_rid: searching for:[%s]\n", filter));
1073 rc = ldapsam_search_suffix(ldap_state, filter, sid_attr, &result);
1075 if (rc != LDAP_SUCCESS) {
1076 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1077 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1079 result = NULL;
1080 return 0;
1083 count = ldap_count_entries(ldap_state->ldap_struct, result);
1084 DEBUG(2, ("search_top_allocated_rid: %d entries in the base!\n", count));
1086 if (count == 0) {
1087 DEBUG(3, ("LDAP search returned no records, assuming no allocated RIDs present!: %s\n", ldap_err2string(rc)));
1088 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1089 } else {
1090 entry = ldap_first_entry(ldap_state->ldap_struct,result);
1092 top_rid = entry_to_rid(ldap_state, entry, rid_type);
1094 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1096 rid = entry_to_rid(ldap_state, entry, rid_type);
1097 if (((rid & ~RID_TYPE_MASK) == rid_type) && (rid > top_rid)) {
1098 top_rid = rid;
1103 switch (rid_type) {
1104 case USER_RID_TYPE:
1105 if (top_rid < ldap_state->low_allocated_user_rid) {
1106 return ldap_state->low_allocated_user_rid;
1108 break;
1109 case GROUP_RID_TYPE:
1110 if (top_rid < ldap_state->low_allocated_group_rid)
1111 return ldap_state->low_allocated_group_rid;
1112 break;
1115 next_rid = (top_rid & ~RID_TYPE_MASK) + rid_type + RID_MULTIPLIER;
1117 switch (rid_type) {
1118 case USER_RID_TYPE:
1119 if (next_rid > ldap_state->high_allocated_user_rid) {
1120 return 0;
1122 break;
1123 case GROUP_RID_TYPE:
1124 if (next_rid > ldap_state->high_allocated_group_rid) {
1125 return 0;
1127 break;
1129 return next_rid;
1132 /**********************************************************************
1133 Add the sambaDomain to LDAP, so we don't have to search for this stuff
1134 again. This is a once-add operation for now.
1136 TODO: Add other attributes, and allow modification.
1137 *********************************************************************/
1138 static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state)
1140 pstring tmp;
1141 pstring filter, dn;
1142 LDAPMod **mods = NULL;
1143 int rc;
1144 int ldap_op;
1145 LDAPMessage *result = NULL;
1146 int num_result;
1147 char **attr_list;
1149 uint32 next_allocated_user_rid;
1150 uint32 next_allocated_group_rid;
1152 next_allocated_user_rid = search_next_allocated_rid(ldap_state, USER_RID_TYPE);
1153 if (!next_allocated_user_rid) {
1154 return NT_STATUS_UNSUCCESSFUL;
1157 next_allocated_group_rid = search_next_allocated_rid(ldap_state, GROUP_RID_TYPE);
1158 if (!next_allocated_group_rid) {
1159 return NT_STATUS_UNSUCCESSFUL;
1162 slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))",
1163 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
1164 ldap_state->domain_name, LDAP_OBJ_DOMINFO);
1166 attr_list = get_attr_list( dominfo_attr_list );
1167 rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &result);
1168 free_attr_list( attr_list );
1170 if (rc != LDAP_SUCCESS) {
1171 return NT_STATUS_UNSUCCESSFUL;
1174 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
1176 if (num_result > 1) {
1177 DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
1178 ldap_msgfree(result);
1179 return NT_STATUS_UNSUCCESSFUL;
1182 /* Check if we need to add an entry */
1183 DEBUG(3,("Adding new domain\n"));
1184 ldap_op = LDAP_MOD_ADD;
1185 snprintf(dn, sizeof(dn), "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
1186 ldap_state->domain_name, lp_ldap_suffix());
1188 /* Free original search */
1189 ldap_msgfree(result);
1191 /* make the changes - the entry *must* not already have samba attributes */
1192 ldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
1193 ldap_state->domain_name);
1195 sid_to_string(tmp, &ldap_state->domain_sid);
1196 ldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), tmp);
1198 snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_user_rid);
1199 ldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), tmp);
1201 snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_group_rid);
1202 ldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), tmp);
1204 ldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
1206 switch(ldap_op)
1208 case LDAP_MOD_ADD:
1209 rc = ldapsam_add(ldap_state, dn, mods);
1210 break;
1211 case LDAP_MOD_REPLACE:
1212 rc = ldapsam_modify(ldap_state, dn, mods);
1213 break;
1214 default:
1215 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1216 return NT_STATUS_INVALID_PARAMETER;
1219 if (rc!=LDAP_SUCCESS) {
1220 char *ld_error = NULL;
1221 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1222 &ld_error);
1223 DEBUG(1,
1224 ("failed to %s domain dn= %s with: %s\n\t%s\n",
1225 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1226 dn, ldap_err2string(rc),
1227 ld_error?ld_error:"unknown"));
1228 SAFE_FREE(ld_error);
1230 ldap_mods_free(mods, True);
1231 return NT_STATUS_UNSUCCESSFUL;
1234 DEBUG(2,("added: domain = %s in the LDAP database\n", ldap_state->domain_name));
1235 ldap_mods_free(mods, True);
1236 return NT_STATUS_OK;
1239 /**********************************************************************
1240 Even if the sambaAccount attribute in LDAP tells us that this RID is
1241 safe to use, always check before use.
1242 *********************************************************************/
1243 static BOOL sid_in_use(struct ldapsam_privates *ldap_state,
1244 const DOM_SID *sid, int *error)
1246 fstring filter;
1247 fstring sid_string;
1248 LDAPMessage *result = NULL;
1249 int count;
1250 int rc;
1251 char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
1253 slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid));
1255 rc = ldapsam_search_suffix(ldap_state, filter, sid_attr, &result);
1257 if (rc != LDAP_SUCCESS) {
1258 char *ld_error = NULL;
1259 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1260 DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
1261 sid_string, ld_error));
1262 SAFE_FREE(ld_error);
1264 *error = rc;
1265 return True;
1268 if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 0) {
1269 DEBUG(3, ("Sid %s already in use - trying next RID\n",
1270 sid_string));
1271 ldap_msgfree(result);
1272 return True;
1275 ldap_msgfree(result);
1277 /* good, sid is not in use */
1278 return False;
1281 /**********************************************************************
1282 Set the new nextRid attribute, and return one we can use.
1284 This also checks that this RID is actually free - in case the admin
1285 manually stole it :-).
1286 *********************************************************************/
1287 static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *rid, int rid_type)
1289 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1290 int rc;
1291 LDAPMessage *result = NULL;
1292 LDAPMessage *entry = NULL;
1293 char *dn;
1294 LDAPMod **mods = NULL;
1295 int count;
1296 fstring old_rid_string;
1297 fstring next_rid_string;
1298 uint32 next_rid;
1299 int attempts = 0;
1301 if ( ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT ) {
1302 DEBUG(0, ("Allocated RIDs require the %s objectclass used by 'ldapsam'\n",
1303 LDAP_OBJ_SAMBASAMACCOUNT));
1304 return NT_STATUS_UNSUCCESSFUL;
1307 while (attempts < 10)
1309 char *ld_error;
1310 if (ldapsam_search_domain_info(ldap_state, &result)) {
1311 return ret;
1314 if (ldap_count_entries(ldap_state->ldap_struct, result) < 1) {
1315 DEBUG(3, ("Got no domain info entries for domain %s\n",
1316 ldap_state->domain_name));
1317 ldap_msgfree(result);
1318 if (NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) {
1319 continue;
1320 } else {
1321 DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret)));
1322 return ret;
1326 if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 1) {
1327 DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
1328 count, ldap_state->domain_name));
1329 ldap_msgfree(result);
1330 return ret;
1333 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1334 if (!entry) {
1335 ldap_msgfree(result);
1336 return ret;
1339 if ((dn = ldap_get_dn(ldap_state->ldap_struct, entry)) == NULL) {
1340 DEBUG(0, ("Could not get domain info DN\n"));
1341 ldap_msgfree(result);
1342 return ret;
1345 /* yes, we keep 2 seperate counters, to avoid stomping on the two
1346 different sets of algorithmic RIDs */
1348 switch (rid_type) {
1349 case USER_RID_TYPE:
1350 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1351 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
1352 old_rid_string))
1354 ldap_memfree(dn);
1355 ldap_msgfree(result);
1356 return ret;
1358 break;
1359 case GROUP_RID_TYPE:
1360 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1361 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
1362 old_rid_string))
1364 ldap_memfree(dn);
1365 ldap_msgfree(result);
1366 return ret;
1368 break;
1371 /* This is the core of the whole routine. If we had
1372 scheme-style closures, there would be a *lot* less code
1373 duplication... */
1374 *rid = (uint32)atol(old_rid_string);
1375 next_rid = *rid+RID_MULTIPLIER;
1377 slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
1379 switch (rid_type) {
1380 case USER_RID_TYPE:
1381 if (next_rid > ldap_state->high_allocated_user_rid) {
1382 return NT_STATUS_UNSUCCESSFUL;
1385 /* Try to make the modification atomically by enforcing the
1386 old value in the delete mod. */
1387 make_ldap_mod(ldap_state->ldap_struct, entry, &mods,
1388 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
1389 next_rid_string);
1390 break;
1392 case GROUP_RID_TYPE:
1393 if (next_rid > ldap_state->high_allocated_group_rid) {
1394 return NT_STATUS_UNSUCCESSFUL;
1397 /* Try to make the modification atomically by enforcing the
1398 old value in the delete mod. */
1399 make_ldap_mod(ldap_state->ldap_struct, entry, &mods,
1400 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
1401 next_rid_string);
1402 break;
1405 if ((rc = ldap_modify_s(ldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) {
1406 DOM_SID dom_sid;
1407 DOM_SID sid;
1408 pstring domain_sid_string;
1409 int error = 0;
1411 if (!get_single_attribute(ldap_state->ldap_struct, result,
1412 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID),
1413 domain_sid_string))
1415 ldap_mods_free(mods, True);
1416 ldap_memfree(dn);
1417 ldap_msgfree(result);
1418 return ret;
1421 if (!string_to_sid(&dom_sid, domain_sid_string)) {
1422 ldap_mods_free(mods, True);
1423 ldap_memfree(dn);
1424 ldap_msgfree(result);
1425 return ret;
1428 ldap_mods_free(mods, True);
1429 mods = NULL;
1430 ldap_memfree(dn);
1431 ldap_msgfree(result);
1433 sid_copy(&sid, &dom_sid);
1434 sid_append_rid(&sid, *rid);
1436 /* check RID is not in use */
1437 if (sid_in_use(ldap_state, &sid, &error)) {
1438 if (error) {
1439 return ret;
1441 continue;
1444 return NT_STATUS_OK;
1447 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1448 DEBUG(2, ("Failed to modify rid: %s\n", ld_error));
1449 SAFE_FREE(ld_error);
1451 ldap_mods_free(mods, True);
1452 mods = NULL;
1454 ldap_memfree(dn);
1455 dn = NULL;
1457 ldap_msgfree(result);
1458 result = NULL;
1461 /* Sleep for a random timeout */
1462 unsigned sleeptime = (sys_random()*sys_getpid()*attempts);
1463 attempts += 1;
1465 sleeptime %= 100;
1466 msleep(sleeptime);
1470 DEBUG(0, ("Failed to set new RID\n"));
1471 return ret;
1474 /* New Interface is being implemented here */
1476 /**********************************************************************
1477 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
1478 *********************************************************************/
1479 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
1480 SAM_ACCOUNT * sampass,
1481 LDAPMessage * entry,
1482 gid_t *gid)
1484 pstring homedir;
1485 pstring temp;
1486 char **ldap_values;
1487 char **values;
1489 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
1490 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
1491 return False;
1494 for (values=ldap_values;*values;values++) {
1495 if (strcasecmp(*values, LDAP_OBJ_POSIXACCOUNT ) == 0) {
1496 break;
1500 if (!*values) { /*end of array, no posixAccount */
1501 DEBUG(10, ("user does not have %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
1502 ldap_value_free(ldap_values);
1503 return False;
1505 ldap_value_free(ldap_values);
1507 if ( !get_single_attribute(ldap_state->ldap_struct, entry,
1508 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) )
1510 return False;
1513 if ( !get_single_attribute(ldap_state->ldap_struct, entry,
1514 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) )
1516 return False;
1519 *gid = (gid_t)atol(temp);
1521 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
1523 DEBUG(10, ("user has %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
1525 return True;
1529 /**********************************************************************
1530 Initialize SAM_ACCOUNT from an LDAP query
1531 (Based on init_sam_from_buffer in pdb_tdb.c)
1532 *********************************************************************/
1533 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
1534 SAM_ACCOUNT * sampass,
1535 LDAPMessage * entry)
1537 time_t logon_time,
1538 logoff_time,
1539 kickoff_time,
1540 pass_last_set_time,
1541 pass_can_change_time,
1542 pass_must_change_time;
1543 pstring username,
1544 domain,
1545 nt_username,
1546 fullname,
1547 homedir,
1548 dir_drive,
1549 logon_script,
1550 profile_path,
1551 acct_desc,
1552 munged_dial,
1553 workstations;
1554 uint32 user_rid;
1555 uint8 smblmpwd[LM_HASH_LEN],
1556 smbntpwd[NT_HASH_LEN];
1557 uint16 acct_ctrl = 0,
1558 logon_divs;
1559 uint32 hours_len;
1560 uint8 hours[MAX_HOURS_LEN];
1561 pstring temp;
1562 uid_t uid = -1;
1563 gid_t gid = getegid();
1566 * do a little initialization
1568 username[0] = '\0';
1569 domain[0] = '\0';
1570 nt_username[0] = '\0';
1571 fullname[0] = '\0';
1572 homedir[0] = '\0';
1573 dir_drive[0] = '\0';
1574 logon_script[0] = '\0';
1575 profile_path[0] = '\0';
1576 acct_desc[0] = '\0';
1577 munged_dial[0] = '\0';
1578 workstations[0] = '\0';
1581 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1582 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1583 return False;
1586 if (ldap_state->ldap_struct == NULL) {
1587 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1588 return False;
1591 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uid", username)) {
1592 DEBUG(1, ("No uid attribute found for this user!\n"));
1593 return False;
1596 DEBUG(2, ("Entry found for user: %s\n", username));
1598 pstrcpy(nt_username, username);
1600 pstrcpy(domain, ldap_state->domain_name);
1602 pdb_set_username(sampass, username, PDB_SET);
1604 pdb_set_domain(sampass, domain, PDB_DEFAULT);
1605 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1607 /* deal with different attributes between the schema first */
1609 if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT )
1611 if (get_single_attribute(ldap_state->ldap_struct, entry,
1612 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp))
1614 pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
1617 if (get_single_attribute(ldap_state->ldap_struct, entry,
1618 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp))
1620 pdb_set_group_sid_from_string(sampass, temp, PDB_SET);
1622 else
1624 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
1629 else
1631 if (get_single_attribute(ldap_state->ldap_struct, entry,
1632 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp))
1634 user_rid = (uint32)atol(temp);
1635 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1638 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1639 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp))
1641 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
1642 } else {
1643 uint32 group_rid;
1645 group_rid = (uint32)atol(temp);
1647 /* for some reason, we often have 0 as a primary group RID.
1648 Make sure that we treat this just as a 'default' value */
1650 if ( group_rid > 0 )
1651 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1652 else
1653 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
1657 if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
1658 DEBUG(1, ("no %s or %s attribute found for this user %s\n",
1659 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
1660 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID),
1661 username));
1662 return False;
1667 * If so configured, try and get the values from LDAP
1670 if (lp_ldap_trust_ids() && (get_unix_attributes(ldap_state, sampass, entry, &gid)))
1672 if (pdb_get_init_flags(sampass,PDB_GROUPSID) == PDB_DEFAULT)
1674 GROUP_MAP map;
1675 /* call the mapping code here */
1676 if(pdb_getgrgid(&map, gid)) {
1677 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1679 else {
1680 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1685 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1686 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp))
1688 /* leave as default */
1689 } else {
1690 pass_last_set_time = (time_t) atol(temp);
1691 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1694 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1695 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp))
1697 /* leave as default */
1698 } else {
1699 logon_time = (time_t) atol(temp);
1700 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1703 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1704 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp))
1706 /* leave as default */
1707 } else {
1708 logoff_time = (time_t) atol(temp);
1709 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1712 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1713 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp))
1715 /* leave as default */
1716 } else {
1717 kickoff_time = (time_t) atol(temp);
1718 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1721 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1722 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp))
1724 /* leave as default */
1725 } else {
1726 pass_can_change_time = (time_t) atol(temp);
1727 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1730 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1731 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp))
1733 /* leave as default */
1734 } else {
1735 pass_must_change_time = (time_t) atol(temp);
1736 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1739 /* recommend that 'gecos' and 'displayName' should refer to the same
1740 * attribute OID. userFullName depreciated, only used by Samba
1741 * primary rules of LDAP: don't make a new attribute when one is already defined
1742 * that fits your needs; using cn then displayName rather than 'userFullName'
1745 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1746 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname))
1748 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1749 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname))
1751 /* leave as default */
1752 } else {
1753 pdb_set_fullname(sampass, fullname, PDB_SET);
1755 } else {
1756 pdb_set_fullname(sampass, fullname, PDB_SET);
1759 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1760 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive))
1762 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
1763 lp_logon_drive(),
1764 username, domain,
1765 uid, gid),
1766 PDB_DEFAULT);
1767 } else {
1768 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1771 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1772 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir))
1774 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
1775 lp_logon_home(),
1776 username, domain,
1777 uid, gid),
1778 PDB_DEFAULT);
1779 } else {
1780 pdb_set_homedir(sampass, homedir, PDB_SET);
1783 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1784 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script))
1786 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
1787 lp_logon_script(),
1788 username, domain,
1789 uid, gid),
1790 PDB_DEFAULT);
1791 } else {
1792 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1795 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1796 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path))
1798 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
1799 lp_logon_path(),
1800 username, domain,
1801 uid, gid),
1802 PDB_DEFAULT);
1803 } else {
1804 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1807 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1808 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), acct_desc))
1810 /* leave as default */
1811 } else {
1812 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1815 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1816 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations))
1818 /* leave as default */;
1819 } else {
1820 pdb_set_workstations(sampass, workstations, PDB_SET);
1823 /* FIXME: hours stuff should be cleaner */
1825 logon_divs = 168;
1826 hours_len = 21;
1827 memset(hours, 0xff, hours_len);
1829 if (!get_single_attribute (ldap_state->ldap_struct, entry,
1830 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp))
1832 /* leave as default */
1833 } else {
1834 pdb_gethexpwd(temp, smblmpwd);
1835 memset((char *)temp, '\0', strlen(temp)+1);
1836 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1837 return False;
1838 ZERO_STRUCT(smblmpwd);
1841 if (!get_single_attribute (ldap_state->ldap_struct, entry,
1842 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp))
1844 /* leave as default */
1845 } else {
1846 pdb_gethexpwd(temp, smbntpwd);
1847 memset((char *)temp, '\0', strlen(temp)+1);
1848 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1849 return False;
1850 ZERO_STRUCT(smbntpwd);
1853 if (!get_single_attribute (ldap_state->ldap_struct, entry,
1854 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp))
1856 acct_ctrl |= ACB_NORMAL;
1857 } else {
1858 acct_ctrl = pdb_decode_acct_ctrl(temp);
1860 if (acct_ctrl == 0)
1861 acct_ctrl |= ACB_NORMAL;
1863 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1866 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1867 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1869 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1871 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1872 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1873 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1875 pdb_set_hours(sampass, hours, PDB_SET);
1877 return True;
1880 /**********************************************************************
1881 Initialize SAM_ACCOUNT from an LDAP query
1882 (Based on init_buffer_from_sam in pdb_tdb.c)
1883 *********************************************************************/
1884 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1885 LDAPMessage *existing,
1886 LDAPMod *** mods, SAM_ACCOUNT * sampass,
1887 BOOL (*need_update)(const SAM_ACCOUNT *,
1888 enum pdb_elements))
1890 pstring temp;
1891 uint32 rid;
1893 if (mods == NULL || sampass == NULL) {
1894 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1895 return False;
1898 *mods = NULL;
1901 * took out adding "objectclass: sambaAccount"
1902 * do this on a per-mod basis
1904 if (need_update(sampass, PDB_USERNAME))
1905 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1906 "uid", pdb_get_username(sampass));
1908 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1910 if (pdb_get_init_flags(sampass, PDB_USERSID) == PDB_DEFAULT) {
1911 if (ldap_state->permit_non_unix_accounts) {
1912 if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state, &rid, USER_RID_TYPE))) {
1913 DEBUG(0, ("NO user RID specified on account %s, and "
1914 "finding next available NUA RID failed, "
1915 "cannot store!\n",
1916 pdb_get_username(sampass)));
1917 ldap_mods_free(*mods, True);
1918 return False;
1920 } else {
1921 DEBUG(0, ("NO user RID specified on account %s, "
1922 "cannot store!\n", pdb_get_username(sampass)));
1923 ldap_mods_free(*mods, True);
1924 return False;
1927 /* now that we have figured out the RID, always store it, as
1928 the schema requires it (either as a SID or a RID) */
1930 if (!pdb_set_user_sid_from_rid(sampass, rid, PDB_CHANGED)) {
1931 DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n",
1932 pdb_get_username(sampass)));
1933 ldap_mods_free(*mods, True);
1934 return False;
1938 /* only update the RID if we actually need to */
1939 if (need_update(sampass, PDB_USERSID))
1941 fstring sid_string;
1942 fstring dom_sid_string;
1943 const DOM_SID *user_sid = pdb_get_user_sid(sampass);
1945 switch ( ldap_state->schema_ver )
1947 case SCHEMAVER_SAMBAACCOUNT:
1948 if (!sid_peek_check_rid(get_global_sam_sid(), user_sid, &rid)) {
1949 DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
1950 sid_to_string(sid_string, user_sid),
1951 sid_to_string(dom_sid_string, get_global_sam_sid())));
1952 return False;
1954 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1955 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1956 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID),
1957 temp);
1958 break;
1960 case SCHEMAVER_SAMBASAMACCOUNT:
1961 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1962 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
1963 sid_to_string(sid_string, user_sid));
1964 break;
1966 default:
1967 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
1968 break;
1972 /* we don't need to store the primary group RID - so leaving it
1973 'free' to hang off the unix primary group makes life easier */
1975 if (need_update(sampass, PDB_GROUPSID))
1977 fstring sid_string;
1978 fstring dom_sid_string;
1979 const DOM_SID *group_sid = pdb_get_group_sid(sampass);
1981 switch ( ldap_state->schema_ver )
1983 case SCHEMAVER_SAMBAACCOUNT:
1984 if (!sid_peek_check_rid(get_global_sam_sid(), group_sid, &rid)) {
1985 DEBUG(1, ("User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
1986 sid_to_string(sid_string, group_sid),
1987 sid_to_string(dom_sid_string, get_global_sam_sid())));
1988 return False;
1991 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1992 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1993 get_userattr_key2string(ldap_state->schema_ver,
1994 LDAP_ATTR_PRIMARY_GROUP_RID), temp);
1995 break;
1997 case SCHEMAVER_SAMBASAMACCOUNT:
1998 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1999 get_userattr_key2string(ldap_state->schema_ver,
2000 LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_string(sid_string, group_sid));
2001 break;
2003 default:
2004 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
2005 break;
2010 /* displayName, cn, and gecos should all be the same
2011 * most easily accomplished by giving them the same OID
2012 * gecos isn't set here b/c it should be handled by the
2013 * add-user script
2014 * We change displayName only and fall back to cn if
2015 * it does not exist.
2018 if (need_update(sampass, PDB_FULLNAME))
2019 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2020 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME),
2021 pdb_get_fullname(sampass));
2023 if (need_update(sampass, PDB_ACCTDESC))
2024 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2025 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC),
2026 pdb_get_acct_desc(sampass));
2028 if (need_update(sampass, PDB_WORKSTATIONS))
2029 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2030 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS),
2031 pdb_get_workstations(sampass));
2033 if (need_update(sampass, PDB_SMBHOME))
2034 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2035 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH),
2036 pdb_get_homedir(sampass));
2038 if (need_update(sampass, PDB_DRIVE))
2039 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2040 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE),
2041 pdb_get_dir_drive(sampass));
2043 if (need_update(sampass, PDB_LOGONSCRIPT))
2044 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2045 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT),
2046 pdb_get_logon_script(sampass));
2048 if (need_update(sampass, PDB_PROFILE))
2049 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2050 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH),
2051 pdb_get_profile_path(sampass));
2053 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
2054 if (need_update(sampass, PDB_LOGONTIME))
2055 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2056 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp);
2058 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
2059 if (need_update(sampass, PDB_LOGOFFTIME))
2060 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2061 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp);
2063 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
2064 if (need_update(sampass, PDB_KICKOFFTIME))
2065 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2066 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
2068 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
2069 if (need_update(sampass, PDB_CANCHANGETIME))
2070 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2071 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
2073 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
2074 if (need_update(sampass, PDB_MUSTCHANGETIME))
2075 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2076 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp);
2078 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
2079 || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY))
2082 pdb_sethexpwd(temp, pdb_get_lanman_passwd(sampass),
2083 pdb_get_acct_ctrl(sampass));
2085 if (need_update(sampass, PDB_LMPASSWD))
2086 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2087 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW),
2088 temp);
2090 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
2091 pdb_get_acct_ctrl(sampass));
2093 if (need_update(sampass, PDB_NTPASSWD))
2094 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2095 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW),
2096 temp);
2098 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
2099 if (need_update(sampass, PDB_PASSLASTSET))
2100 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2101 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET),
2102 temp);
2105 /* FIXME: Hours stuff goes in LDAP */
2107 if (need_update(sampass, PDB_ACCTCTRL))
2108 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2109 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO),
2110 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN));
2112 return True;
2117 /**********************************************************************
2118 Connect to LDAP server for password enumeration
2119 *********************************************************************/
2120 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
2122 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2123 int rc;
2124 pstring filter;
2125 char **attr_list;
2127 snprintf( filter, sizeof(filter)-1, "(&%s%s)", lp_ldap_filter(),
2128 get_objclass_filter(ldap_state->schema_ver));
2129 all_string_sub(filter, "%u", "*", sizeof(pstring));
2131 attr_list = get_userattr_list(ldap_state->schema_ver);
2132 rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &ldap_state->result);
2133 free_attr_list( attr_list );
2135 if (rc != LDAP_SUCCESS) {
2136 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2137 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2138 ldap_msgfree(ldap_state->result);
2139 ldap_state->result = NULL;
2140 return NT_STATUS_UNSUCCESSFUL;
2143 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2144 ldap_count_entries(ldap_state->ldap_struct,
2145 ldap_state->result)));
2147 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2148 ldap_state->result);
2149 ldap_state->index = 0;
2151 return NT_STATUS_OK;
2154 /**********************************************************************
2155 End enumeration of the LDAP password list
2156 *********************************************************************/
2157 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
2159 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2160 if (ldap_state->result) {
2161 ldap_msgfree(ldap_state->result);
2162 ldap_state->result = NULL;
2166 /**********************************************************************
2167 Get the next entry in the LDAP password database
2168 *********************************************************************/
2169 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
2171 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2172 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2173 BOOL bret = False;
2175 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2176 this will work, but it's not nice. */
2177 static_ldap_state = ldap_state;
2179 while (!bret) {
2180 if (!ldap_state->entry)
2181 return ret;
2183 ldap_state->index++;
2184 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
2186 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2187 ldap_state->entry);
2190 return NT_STATUS_OK;
2193 /**********************************************************************
2194 Get SAM_ACCOUNT entry from LDAP by username
2195 *********************************************************************/
2196 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
2198 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2199 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2200 LDAPMessage *result;
2201 LDAPMessage *entry;
2202 int count;
2203 char ** attr_list;
2204 int rc;
2206 attr_list = get_userattr_list( ldap_state->schema_ver );
2207 rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
2208 free_attr_list( attr_list );
2210 if ( rc != LDAP_SUCCESS )
2211 return NT_STATUS_NO_SUCH_USER;
2213 count = ldap_count_entries(ldap_state->ldap_struct, result);
2215 if (count < 1) {
2216 DEBUG(4,
2217 ("Unable to locate user [%s] count=%d\n", sname,
2218 count));
2219 return NT_STATUS_NO_SUCH_USER;
2220 } else if (count > 1) {
2221 DEBUG(1,
2222 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
2223 count));
2224 return NT_STATUS_NO_SUCH_USER;
2227 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2228 if (entry) {
2229 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2230 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
2231 ldap_msgfree(result);
2232 return NT_STATUS_NO_SUCH_USER;
2234 ldap_msgfree(result);
2235 ret = NT_STATUS_OK;
2236 } else {
2237 ldap_msgfree(result);
2239 return ret;
2242 /**********************************************************************
2243 Get SAM_ACCOUNT entry from LDAP by SID
2244 *********************************************************************/
2245 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
2247 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2248 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2249 LDAPMessage *result;
2250 LDAPMessage *entry;
2251 fstring sid_string;
2252 int count;
2253 int rc;
2254 char ** attr_list;
2256 switch ( ldap_state->schema_ver )
2258 case SCHEMAVER_SAMBASAMACCOUNT:
2259 attr_list = get_userattr_list(ldap_state->schema_ver);
2260 rc = ldapsam_search_suffix_by_sid(ldap_state, sid, &result, attr_list);
2261 free_attr_list( attr_list );
2263 if ( rc != LDAP_SUCCESS )
2264 return NT_STATUS_NO_SUCH_USER;
2265 break;
2267 case SCHEMAVER_SAMBAACCOUNT:
2269 uint32 rid;
2270 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) {
2271 return NT_STATUS_NO_SUCH_USER;
2274 attr_list = get_userattr_list(ldap_state->schema_ver);
2275 rc = ldapsam_search_suffix_by_rid(ldap_state, rid, &result, attr_list );
2276 free_attr_list( attr_list );
2278 if ( rc != LDAP_SUCCESS )
2279 return NT_STATUS_NO_SUCH_USER;
2281 break;
2284 count = ldap_count_entries(ldap_state->ldap_struct, result);
2286 if (count < 1)
2288 DEBUG(4,
2289 ("Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string, sid),
2290 count));
2291 ldap_msgfree(result);
2292 return NT_STATUS_NO_SUCH_USER;
2294 else if (count > 1)
2296 DEBUG(1,
2297 ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid),
2298 count));
2299 ldap_msgfree(result);
2300 return NT_STATUS_NO_SUCH_USER;
2303 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2304 if (entry)
2306 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2307 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
2308 ldap_msgfree(result);
2309 return NT_STATUS_NO_SUCH_USER;
2311 ret = NT_STATUS_OK;
2313 ldap_msgfree(result);
2314 return ret;
2317 /********************************************************************
2318 Do the actual modification - also change a plaittext passord if
2319 it it set.
2320 **********************************************************************/
2322 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
2323 SAM_ACCOUNT *newpwd, char *dn,
2324 LDAPMod **mods, int ldap_op,
2325 BOOL (*need_update)(const SAM_ACCOUNT *,
2326 enum pdb_elements))
2328 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2329 int rc;
2331 if (!my_methods || !newpwd || !dn) {
2332 return NT_STATUS_INVALID_PARAMETER;
2335 if (!mods) {
2336 DEBUG(5,("mods is empty: nothing to modify\n"));
2337 /* may be password change below however */
2338 } else {
2339 switch(ldap_op)
2341 case LDAP_MOD_ADD:
2342 ldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_ACCOUNT);
2343 rc = ldapsam_add(ldap_state, dn, mods);
2344 break;
2345 case LDAP_MOD_REPLACE:
2346 rc = ldapsam_modify(ldap_state, dn ,mods);
2347 break;
2348 default:
2349 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
2350 return NT_STATUS_INVALID_PARAMETER;
2353 if (rc!=LDAP_SUCCESS) {
2354 char *ld_error = NULL;
2355 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2356 &ld_error);
2357 DEBUG(1,
2358 ("failed to %s user dn= %s with: %s\n\t%s\n",
2359 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
2360 dn, ldap_err2string(rc),
2361 ld_error?ld_error:"unknown"));
2362 SAFE_FREE(ld_error);
2363 return NT_STATUS_UNSUCCESSFUL;
2367 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
2368 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
2369 need_update(newpwd, PDB_PLAINTEXT_PW) &&
2370 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
2371 BerElement *ber;
2372 struct berval *bv;
2373 char *retoid;
2374 struct berval *retdata;
2375 char *utf8_password;
2376 char *utf8_dn;
2378 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
2379 return NT_STATUS_NO_MEMORY;
2382 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
2383 return NT_STATUS_NO_MEMORY;
2386 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
2387 DEBUG(0,("ber_alloc_t returns NULL\n"));
2388 SAFE_FREE(utf8_password);
2389 return NT_STATUS_UNSUCCESSFUL;
2392 ber_printf (ber, "{");
2393 ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn);
2394 ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password);
2395 ber_printf (ber, "N}");
2397 if ((rc = ber_flatten (ber, &bv))<0) {
2398 DEBUG(0,("ber_flatten returns a value <0\n"));
2399 ber_free(ber,1);
2400 SAFE_FREE(utf8_dn);
2401 SAFE_FREE(utf8_password);
2402 return NT_STATUS_UNSUCCESSFUL;
2405 SAFE_FREE(utf8_dn);
2406 SAFE_FREE(utf8_password);
2407 ber_free(ber, 1);
2409 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_MODIFY_PASSWD,
2410 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
2411 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
2412 pdb_get_username(newpwd),ldap_err2string(rc)));
2413 } else {
2414 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
2415 #ifdef DEBUG_PASSWORD
2416 DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
2417 #endif
2418 ber_bvfree(retdata);
2419 ber_memfree(retoid);
2421 ber_bvfree(bv);
2423 return NT_STATUS_OK;
2426 /**********************************************************************
2427 Delete entry from LDAP for username
2428 *********************************************************************/
2429 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
2431 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2432 const char *sname;
2433 int rc;
2434 LDAPMessage *result;
2435 NTSTATUS ret;
2436 char **attr_list;
2437 fstring objclass;
2439 if (!sam_acct) {
2440 DEBUG(0, ("sam_acct was NULL!\n"));
2441 return NT_STATUS_INVALID_PARAMETER;
2444 sname = pdb_get_username(sam_acct);
2446 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
2448 attr_list= get_userattr_list( ldap_state->schema_ver );
2449 rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
2451 if (rc != LDAP_SUCCESS) {
2452 free_attr_list( attr_list );
2453 return NT_STATUS_NO_SUCH_USER;
2456 switch ( ldap_state->schema_ver )
2458 case SCHEMAVER_SAMBASAMACCOUNT:
2459 fstrcpy( objclass, LDAP_OBJ_SAMBASAMACCOUNT );
2460 break;
2462 case SCHEMAVER_SAMBAACCOUNT:
2463 fstrcpy( objclass, LDAP_OBJ_SAMBAACCOUNT );
2464 break;
2465 default:
2466 fstrcpy( objclass, "UNKNOWN" );
2467 DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
2468 break;
2471 ret = ldapsam_delete_entry(ldap_state, result, objclass, attr_list );
2472 ldap_msgfree(result);
2473 free_attr_list( attr_list );
2475 return ret;
2478 /**********************************************************************
2479 Helper function to determine for update_sam_account whether
2480 we need LDAP modification.
2481 *********************************************************************/
2482 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
2483 enum pdb_elements element)
2485 return IS_SAM_CHANGED(sampass, element);
2488 /**********************************************************************
2489 Update SAM_ACCOUNT
2490 *********************************************************************/
2491 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2493 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2494 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2495 int rc;
2496 char *dn;
2497 LDAPMessage *result;
2498 LDAPMessage *entry;
2499 LDAPMod **mods;
2500 char **attr_list;
2502 attr_list = get_userattr_list(ldap_state->schema_ver);
2503 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
2504 free_attr_list( attr_list );
2505 if (rc != LDAP_SUCCESS)
2506 return NT_STATUS_UNSUCCESSFUL;
2508 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2509 DEBUG(0, ("No user to modify!\n"));
2510 ldap_msgfree(result);
2511 return NT_STATUS_UNSUCCESSFUL;
2514 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2515 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2517 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2518 element_is_changed)) {
2519 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2520 ldap_msgfree(result);
2521 return NT_STATUS_UNSUCCESSFUL;
2524 ldap_msgfree(result);
2526 if (mods == NULL) {
2527 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2528 pdb_get_username(newpwd)));
2529 ldap_mods_free(mods, True);
2530 return NT_STATUS_OK;
2533 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
2534 ldap_mods_free(mods,True);
2536 if (!NT_STATUS_IS_OK(ret)) {
2537 char *ld_error = NULL;
2538 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2539 &ld_error);
2540 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2541 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
2542 SAFE_FREE(ld_error);
2543 return ret;
2546 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2547 pdb_get_username(newpwd)));
2548 return NT_STATUS_OK;
2551 /**********************************************************************
2552 Helper function to determine for update_sam_account whether
2553 we need LDAP modification.
2554 *********************************************************************/
2555 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2556 enum pdb_elements element)
2558 return (IS_SAM_SET(sampass, element) ||
2559 IS_SAM_CHANGED(sampass, element));
2562 /**********************************************************************
2563 Add SAM_ACCOUNT to LDAP
2564 *********************************************************************/
2566 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2568 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2569 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2570 int rc;
2571 LDAPMessage *result = NULL;
2572 LDAPMessage *entry = NULL;
2573 pstring dn;
2574 LDAPMod **mods = NULL;
2575 int ldap_op;
2576 uint32 num_result;
2577 char **attr_list;
2578 char *escape_user;
2579 const char *username = pdb_get_username(newpwd);
2580 pstring filter;
2582 if (!username || !*username) {
2583 DEBUG(0, ("Cannot add user without a username!\n"));
2584 return NT_STATUS_INVALID_PARAMETER;
2587 /* free this list after the second search or in case we exit on failure */
2589 attr_list = get_userattr_list(ldap_state->schema_ver);
2590 rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
2592 if (rc != LDAP_SUCCESS) {
2593 free_attr_list( attr_list );
2594 return NT_STATUS_UNSUCCESSFUL;
2597 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2598 DEBUG(0,("User '%s' already in the base, with samba attributes\n",
2599 username));
2600 ldap_msgfree(result);
2601 free_attr_list( attr_list );
2602 return NT_STATUS_UNSUCCESSFUL;
2604 ldap_msgfree(result);
2606 /* does the entry already exist but without a samba rttibutes?
2607 we don't really care what attributes are returned here */
2609 escape_user = escape_ldap_string_alloc( username );
2610 pstrcpy( filter, lp_ldap_filter() );
2611 all_string_sub( filter, "%u", escape_user, sizeof(filter) );
2612 SAFE_FREE( escape_user );
2614 rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &result);
2615 free_attr_list( attr_list );
2617 if ( rc != LDAP_SUCCESS )
2618 return NT_STATUS_UNSUCCESSFUL;
2620 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2622 if (num_result > 1) {
2623 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2624 ldap_msgfree(result);
2625 return NT_STATUS_UNSUCCESSFUL;
2628 /* Check if we need to update an existing entry */
2629 if (num_result == 1) {
2630 char *tmp;
2632 DEBUG(3,("User exists without samba attributes: adding them\n"));
2633 ldap_op = LDAP_MOD_REPLACE;
2634 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2635 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2636 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2637 ldap_memfree (tmp);
2638 } else {
2639 /* Check if we need to add an entry */
2640 DEBUG(3,("Adding new user\n"));
2641 ldap_op = LDAP_MOD_ADD;
2642 if (username[strlen(username)-1] == '$') {
2643 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2644 } else {
2645 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2649 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2650 element_is_set_or_changed)) {
2651 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2652 ldap_msgfree(result);
2653 return NT_STATUS_UNSUCCESSFUL;
2656 ldap_msgfree(result);
2658 if (mods == NULL) {
2659 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2660 return NT_STATUS_UNSUCCESSFUL;
2662 switch ( ldap_state->schema_ver )
2664 case SCHEMAVER_SAMBAACCOUNT:
2665 ldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT);
2666 break;
2667 case SCHEMAVER_SAMBASAMACCOUNT:
2668 ldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT);
2669 break;
2670 default:
2671 DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
2672 break;
2675 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
2676 if (NT_STATUS_IS_ERR(ret)) {
2677 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2678 pdb_get_username(newpwd),dn));
2679 ldap_mods_free(mods, True);
2680 return ret;
2683 DEBUG(2,("added: uid == %s in the LDAP database\n", pdb_get_username(newpwd)));
2684 ldap_mods_free(mods, True);
2686 return NT_STATUS_OK;
2689 /**********************************************************************
2690 Housekeeping
2691 *********************************************************************/
2693 static void free_private_data(void **vp)
2695 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2697 ldapsam_close(*ldap_state);
2699 if ((*ldap_state)->bind_secret) {
2700 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2703 ldapsam_close(*ldap_state);
2705 SAFE_FREE((*ldap_state)->bind_dn);
2706 SAFE_FREE((*ldap_state)->bind_secret);
2708 *ldap_state = NULL;
2710 /* No need to free any further, as it is talloc()ed */
2713 /**********************************************************************
2714 *********************************************************************/
2716 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2717 const char *filter,
2718 LDAPMessage ** result)
2720 int scope = LDAP_SCOPE_SUBTREE;
2721 int rc;
2722 char **attr_list;
2724 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2727 attr_list = get_attr_list(groupmap_attr_list);
2728 rc = ldapsam_search(ldap_state, lp_ldap_group_suffix (), scope,
2729 filter, attr_list, 0, result);
2730 free_attr_list( attr_list );
2732 if (rc != LDAP_SUCCESS) {
2733 char *ld_error = NULL;
2734 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2735 &ld_error);
2736 DEBUG(0, ("ldapsam_search_one_group: "
2737 "Problem during the LDAP search: LDAP error: %s (%s)",
2738 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
2739 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2740 lp_ldap_group_suffix(), filter));
2741 SAFE_FREE(ld_error);
2744 return rc;
2747 /**********************************************************************
2748 *********************************************************************/
2750 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2751 GROUP_MAP *map, LDAPMessage *entry)
2753 pstring temp;
2755 if (ldap_state == NULL || map == NULL || entry == NULL ||
2756 ldap_state->ldap_struct == NULL)
2758 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2759 return False;
2762 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2763 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp))
2765 DEBUG(0, ("Mandatory attribute %s not found\n",
2766 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER)));
2767 return False;
2769 DEBUG(2, ("Entry found for group: %s\n", temp));
2771 map->gid = (gid_t)atol(temp);
2773 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2774 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp))
2776 DEBUG(0, ("Mandatory attribute %s not found\n",
2777 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID)));
2778 return False;
2780 string_to_sid(&map->sid, temp);
2782 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2783 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp))
2785 DEBUG(0, ("Mandatory attribute %s not found\n",
2786 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
2787 return False;
2789 map->sid_name_use = (uint32)atol(temp);
2791 if ((map->sid_name_use < SID_NAME_USER) ||
2792 (map->sid_name_use > SID_NAME_UNKNOWN)) {
2793 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2794 return False;
2797 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2798 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp))
2800 temp[0] = '\0';
2801 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2802 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp))
2804 DEBUG(0, ("Attributes cn not found either "
2805 "for gidNumber(%i)\n",map->gid));
2806 return False;
2809 fstrcpy(map->nt_name, temp);
2811 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2812 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp))
2814 temp[0] = '\0';
2816 fstrcpy(map->comment, temp);
2818 return True;
2821 /**********************************************************************
2822 *********************************************************************/
2824 static BOOL init_ldap_from_group(LDAP *ldap_struct,
2825 LDAPMessage *existing,
2826 LDAPMod ***mods,
2827 const GROUP_MAP *map)
2829 pstring tmp;
2831 if (mods == NULL || map == NULL) {
2832 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2833 return False;
2836 *mods = NULL;
2838 sid_to_string(tmp, &map->sid);
2839 make_ldap_mod(ldap_struct, existing, mods,
2840 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
2841 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2842 make_ldap_mod(ldap_struct, existing, mods,
2843 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
2845 make_ldap_mod(ldap_struct, existing, mods,
2846 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
2847 make_ldap_mod(ldap_struct, existing, mods,
2848 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
2850 return True;
2853 /**********************************************************************
2854 *********************************************************************/
2856 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2857 const char *filter,
2858 GROUP_MAP *map)
2860 struct ldapsam_privates *ldap_state =
2861 (struct ldapsam_privates *)methods->private_data;
2862 LDAPMessage *result;
2863 LDAPMessage *entry;
2864 int count;
2866 if (ldapsam_search_one_group(ldap_state, filter, &result)
2867 != LDAP_SUCCESS) {
2868 return NT_STATUS_NO_SUCH_GROUP;
2871 count = ldap_count_entries(ldap_state->ldap_struct, result);
2873 if (count < 1) {
2874 DEBUG(4, ("Did not find group for filter %s\n", filter));
2875 return NT_STATUS_NO_SUCH_GROUP;
2878 if (count > 1) {
2879 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2880 filter, count));
2881 return NT_STATUS_NO_SUCH_GROUP;
2884 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2886 if (!entry) {
2887 ldap_msgfree(result);
2888 return NT_STATUS_UNSUCCESSFUL;
2891 if (!init_group_from_ldap(ldap_state, map, entry)) {
2892 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2893 filter));
2894 ldap_msgfree(result);
2895 return NT_STATUS_NO_SUCH_GROUP;
2898 ldap_msgfree(result);
2899 return NT_STATUS_OK;
2902 /**********************************************************************
2903 *********************************************************************/
2905 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2906 DOM_SID sid)
2908 pstring filter;
2910 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
2911 LDAP_OBJ_GROUPMAP,
2912 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
2913 sid_string_static(&sid));
2915 return ldapsam_getgroup(methods, filter, map);
2918 /**********************************************************************
2919 *********************************************************************/
2921 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2922 gid_t gid)
2924 pstring filter;
2926 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%d))",
2927 LDAP_OBJ_GROUPMAP,
2928 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
2929 gid);
2931 return ldapsam_getgroup(methods, filter, map);
2934 /**********************************************************************
2935 *********************************************************************/
2937 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2938 const char *name)
2940 pstring filter;
2942 /* TODO: Escaping of name? */
2944 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
2945 LDAP_OBJ_GROUPMAP,
2946 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), name,
2947 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), name);
2949 return ldapsam_getgroup(methods, filter, map);
2952 /**********************************************************************
2953 *********************************************************************/
2955 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2956 gid_t gid,
2957 LDAPMessage **result)
2959 pstring filter;
2961 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%i))",
2962 LDAP_OBJ_POSIXGROUP,
2963 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
2964 gid);
2966 return ldapsam_search_one_group(ldap_state, filter, result);
2969 /**********************************************************************
2970 *********************************************************************/
2972 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2973 GROUP_MAP *map)
2975 struct ldapsam_privates *ldap_state =
2976 (struct ldapsam_privates *)methods->private_data;
2977 LDAPMessage *result = NULL;
2978 LDAPMod **mods = NULL;
2980 char *tmp;
2981 pstring dn;
2982 LDAPMessage *entry;
2984 GROUP_MAP dummy;
2986 int rc;
2988 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2989 map->gid))) {
2990 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2991 return NT_STATUS_UNSUCCESSFUL;
2994 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2995 if (rc != LDAP_SUCCESS) {
2996 return NT_STATUS_UNSUCCESSFUL;
2999 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
3000 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
3001 map->gid));
3002 ldap_msgfree(result);
3003 return NT_STATUS_UNSUCCESSFUL;
3006 entry = ldap_first_entry(ldap_state->ldap_struct, result);
3007 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
3008 pstrcpy(dn, tmp);
3009 ldap_memfree(tmp);
3011 if (!init_ldap_from_group(ldap_state->ldap_struct,
3012 result, &mods, map)) {
3013 DEBUG(0, ("init_ldap_from_group failed!\n"));
3014 ldap_mods_free(mods, True);
3015 ldap_msgfree(result);
3016 return NT_STATUS_UNSUCCESSFUL;
3019 ldap_msgfree(result);
3021 if (mods == NULL) {
3022 DEBUG(0, ("mods is empty\n"));
3023 return NT_STATUS_UNSUCCESSFUL;
3026 ldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP );
3028 rc = ldapsam_modify(ldap_state, dn, mods);
3029 ldap_mods_free(mods, True);
3031 if (rc != LDAP_SUCCESS) {
3032 char *ld_error = NULL;
3033 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
3034 &ld_error);
3035 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
3036 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
3037 SAFE_FREE(ld_error);
3038 return NT_STATUS_UNSUCCESSFUL;
3041 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
3042 return NT_STATUS_OK;
3045 /**********************************************************************
3046 *********************************************************************/
3048 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
3049 GROUP_MAP *map)
3051 struct ldapsam_privates *ldap_state =
3052 (struct ldapsam_privates *)methods->private_data;
3053 int rc;
3054 char *dn;
3055 LDAPMessage *result;
3056 LDAPMessage *entry;
3057 LDAPMod **mods;
3059 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
3061 if (rc != LDAP_SUCCESS) {
3062 return NT_STATUS_UNSUCCESSFUL;
3065 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
3066 DEBUG(0, ("No group to modify!\n"));
3067 ldap_msgfree(result);
3068 return NT_STATUS_UNSUCCESSFUL;
3071 entry = ldap_first_entry(ldap_state->ldap_struct, result);
3072 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
3074 if (!init_ldap_from_group(ldap_state->ldap_struct,
3075 result, &mods, map)) {
3076 DEBUG(0, ("init_ldap_from_group failed\n"));
3077 ldap_msgfree(result);
3078 return NT_STATUS_UNSUCCESSFUL;
3081 ldap_msgfree(result);
3083 if (mods == NULL) {
3084 DEBUG(4, ("mods is empty: nothing to do\n"));
3085 return NT_STATUS_UNSUCCESSFUL;
3088 rc = ldapsam_modify(ldap_state, dn, mods);
3090 ldap_mods_free(mods, True);
3092 if (rc != LDAP_SUCCESS) {
3093 char *ld_error = NULL;
3094 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
3095 &ld_error);
3096 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
3097 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
3098 SAFE_FREE(ld_error);
3101 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
3102 return NT_STATUS_OK;
3105 /**********************************************************************
3106 *********************************************************************/
3108 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
3109 DOM_SID sid)
3111 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
3112 pstring sidstring, filter;
3113 LDAPMessage *result;
3114 int rc;
3115 NTSTATUS ret;
3116 char **attr_list;
3118 sid_to_string(sidstring, &sid);
3120 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
3121 LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
3123 rc = ldapsam_search_one_group(ldap_state, filter, &result);
3125 if (rc != LDAP_SUCCESS) {
3126 return NT_STATUS_NO_SUCH_GROUP;
3129 attr_list = get_attr_list( groupmap_attr_list_to_delete );
3130 ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
3131 free_attr_list ( attr_list );
3133 ldap_msgfree(result);
3135 return ret;
3138 /**********************************************************************
3139 *********************************************************************/
3141 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
3143 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
3144 fstring filter;
3145 int rc;
3146 char **attr_list;
3148 snprintf( filter, sizeof(filter)-1, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
3149 attr_list = get_attr_list( groupmap_attr_list );
3150 rc = ldapsam_search(ldap_state, lp_ldap_group_suffix(),
3151 LDAP_SCOPE_SUBTREE, filter,
3152 attr_list, 0, &ldap_state->result);
3153 free_attr_list( attr_list );
3155 if (rc != LDAP_SUCCESS) {
3156 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
3157 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_group_suffix(), filter));
3158 ldap_msgfree(ldap_state->result);
3159 ldap_state->result = NULL;
3160 return NT_STATUS_UNSUCCESSFUL;
3163 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
3164 ldap_count_entries(ldap_state->ldap_struct,
3165 ldap_state->result)));
3167 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct, ldap_state->result);
3168 ldap_state->index = 0;
3170 return NT_STATUS_OK;
3173 /**********************************************************************
3174 *********************************************************************/
3176 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
3178 ldapsam_endsampwent(my_methods);
3181 /**********************************************************************
3182 *********************************************************************/
3184 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
3185 GROUP_MAP *map)
3187 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
3188 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
3189 BOOL bret = False;
3191 /* The rebind proc needs this *HACK*. We are not multithreaded, so
3192 this will work, but it's not nice. */
3193 static_ldap_state = ldap_state;
3195 while (!bret) {
3196 if (!ldap_state->entry)
3197 return ret;
3199 ldap_state->index++;
3200 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
3202 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
3203 ldap_state->entry);
3206 return NT_STATUS_OK;
3209 /**********************************************************************
3210 *********************************************************************/
3212 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
3213 enum SID_NAME_USE sid_name_use,
3214 GROUP_MAP **rmap, int *num_entries,
3215 BOOL unix_only)
3217 GROUP_MAP map;
3218 GROUP_MAP *mapt;
3219 int entries = 0;
3220 NTSTATUS nt_status;
3222 *num_entries = 0;
3223 *rmap = NULL;
3225 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
3226 DEBUG(0, ("Unable to open passdb\n"));
3227 return NT_STATUS_ACCESS_DENIED;
3230 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
3231 if (sid_name_use != SID_NAME_UNKNOWN &&
3232 sid_name_use != map.sid_name_use) {
3233 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
3234 continue;
3236 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
3237 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
3238 continue;
3241 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
3242 if (!mapt) {
3243 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
3244 SAFE_FREE(*rmap);
3245 return NT_STATUS_UNSUCCESSFUL;
3247 else
3248 (*rmap) = mapt;
3250 mapt[entries] = map;
3252 entries += 1;
3255 ldapsam_endsamgrent(methods);
3257 *num_entries = entries;
3259 return NT_STATUS_OK;
3262 /**********************************************************************
3263 *********************************************************************/
3265 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method,
3266 const char *location)
3268 NTSTATUS nt_status;
3269 struct ldapsam_privates *ldap_state;
3271 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
3272 return nt_status;
3275 (*pdb_method)->name = "ldapsam";
3277 (*pdb_method)->setsampwent = ldapsam_setsampwent;
3278 (*pdb_method)->endsampwent = ldapsam_endsampwent;
3279 (*pdb_method)->getsampwent = ldapsam_getsampwent;
3280 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
3281 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
3282 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
3283 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
3284 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
3286 (*pdb_method)->getgrsid = ldapsam_getgrsid;
3287 (*pdb_method)->getgrgid = ldapsam_getgrgid;
3288 (*pdb_method)->getgrnam = ldapsam_getgrnam;
3289 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
3290 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
3291 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
3292 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
3294 /* TODO: Setup private data and free */
3296 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
3298 if (!ldap_state) {
3299 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
3300 return NT_STATUS_NO_MEMORY;
3303 if (location) {
3304 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3305 } else {
3306 ldap_state->uri = "ldap://localhost";
3309 ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
3310 if (!ldap_state->domain_name) {
3311 return NT_STATUS_NO_MEMORY;
3314 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
3316 (*pdb_method)->private_data = ldap_state;
3318 (*pdb_method)->free_private_data = free_private_data;
3320 return NT_STATUS_OK;
3323 /**********************************************************************
3324 *********************************************************************/
3326 static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3328 NTSTATUS nt_status;
3329 struct ldapsam_privates *ldap_state;
3331 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3332 return nt_status;
3335 (*pdb_method)->name = "ldapsam_compat";
3337 ldap_state = (*pdb_method)->private_data;
3338 ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
3340 if (location) {
3341 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3342 } else {
3343 #ifndef WITH_LDAP_SAMCONFIG
3344 ldap_state->uri = "ldap://localhost";
3345 #else
3346 int ldap_port = lp_ldap_port();
3348 /* remap default port if not using SSL (ie clear or TLS) */
3349 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
3350 ldap_port = 389;
3353 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);
3354 if (!ldap_state->uri) {
3355 return NT_STATUS_NO_MEMORY;
3357 #endif
3360 return NT_STATUS_OK;
3363 /**********************************************************************
3364 *********************************************************************/
3366 static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3368 NTSTATUS nt_status;
3369 struct ldapsam_privates *ldap_state;
3370 uint32 low_idmap_uid, high_idmap_uid;
3371 uint32 low_idmap_gid, high_idmap_gid;
3373 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3374 return nt_status;
3377 (*pdb_method)->name = "ldapsam";
3379 ldap_state = (*pdb_method)->private_data;
3380 ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
3381 ldap_state->permit_non_unix_accounts = False;
3383 /* check for non-unix account ranges */
3385 if (lp_idmap_uid(&low_idmap_uid, &high_idmap_uid)
3386 && lp_idmap_gid(&low_idmap_gid, &high_idmap_gid))
3388 DEBUG(2, ("Enabling non-unix account ranges\n"));
3390 ldap_state->permit_non_unix_accounts = True;
3392 ldap_state->low_allocated_user_rid = fallback_pdb_uid_to_user_rid(low_idmap_uid);
3393 ldap_state->high_allocated_user_rid = fallback_pdb_uid_to_user_rid(high_idmap_uid);
3394 ldap_state->low_allocated_group_rid = pdb_gid_to_group_rid(low_idmap_gid);
3395 ldap_state->high_allocated_group_rid = pdb_gid_to_group_rid(high_idmap_gid);
3398 return NT_STATUS_OK;
3401 NTSTATUS pdb_ldap_init(void)
3403 NTSTATUS nt_status;
3404 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
3405 return nt_status;
3407 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
3408 return nt_status;
3410 return NT_STATUS_OK;