Fix from Alex Deiter <tiamat@komi.mts.ru>
[Samba/nascimento.git] / source / passdb / pdb_ldap.c
blob1ae706f6f065753aedede7ddbf73ab9831a31285
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 #ifndef SAM_ACCOUNT
59 #define SAM_ACCOUNT struct sam_passwd
60 #endif
62 struct ldapsam_privates {
63 /* Former statics */
64 LDAP *ldap_struct;
65 LDAPMessage *result;
66 LDAPMessage *entry;
67 int index;
69 time_t last_ping;
70 /* retrive-once info */
71 const char *uri;
72 const char *domain_name;
73 DOM_SID domain_sid;
75 /* configuration items */
76 int schema_ver;
78 BOOL permit_non_unix_accounts;
80 uint32 low_allocated_user_rid;
81 uint32 high_allocated_user_rid;
83 uint32 low_allocated_group_rid;
84 uint32 high_allocated_group_rid;
86 char *bind_dn;
87 char *bind_secret;
89 unsigned int num_failures;
92 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
94 static struct ldapsam_privates *static_ldap_state;
96 /* specify schema versions between 2.2. and 3.0 */
98 #define SCHEMAVER_SAMBAACCOUNT 1
99 #define SCHEMAVER_SAMBASAMACCOUNT 2
101 /* objectclass names */
103 #define LDAP_OBJ_SAMBASAMACCOUNT "sambaSamAccount"
104 #define LDAP_OBJ_SAMBAACCOUNT "sambaAccount"
105 #define LDAP_OBJ_GROUPMAP "sambaGroupMapping"
106 #define LDAP_OBJ_DOMINFO "sambaDomain"
108 #define LDAP_OBJ_ACCOUNT "account"
109 #define LDAP_OBJ_POSIXACCOUNT "posixAccount"
110 #define LDAP_OBJ_POSIXGROUP "posixGroup"
112 /* some generic attributes that get reused a lot */
114 #define LDAP_ATTRIBUTE_SID "sambaSID"
116 /* attribute map table indexes */
118 #define LDAP_ATTR_LIST_END 0
119 #define LDAP_ATTR_UID 1
120 #define LDAP_ATTR_UIDNUMBER 2
121 #define LDAP_ATTR_GIDNUMBER 3
122 #define LDAP_ATTR_UNIX_HOME 4
123 #define LDAP_ATTR_PWD_LAST_SET 5
124 #define LDAP_ATTR_PWD_CAN_CHANGE 6
125 #define LDAP_ATTR_PWD_MUST_CHANGE 7
126 #define LDAP_ATTR_LOGON_TIME 8
127 #define LDAP_ATTR_LOGOFF_TIME 9
128 #define LDAP_ATTR_KICKOFF_TIME 10
129 #define LDAP_ATTR_CN 11
130 #define LDAP_ATTR_DISPLAY_NAME 12
131 #define LDAP_ATTR_HOME_PATH 13
132 #define LDAP_ATTR_LOGON_SCRIPT 14
133 #define LDAP_ATTR_PROFILE_PATH 15
134 #define LDAP_ATTR_DESC 16
135 #define LDAP_ATTR_USER_WKS 17
136 #define LDAP_ATTR_USER_SID 18
137 #define LDAP_ATTR_USER_RID 18
138 #define LDAP_ATTR_PRIMARY_GROUP_SID 19
139 #define LDAP_ATTR_PRIMARY_GROUP_RID 20
140 #define LDAP_ATTR_LMPW 21
141 #define LDAP_ATTR_NTPW 22
142 #define LDAP_ATTR_DOMAIN 23
143 #define LDAP_ATTR_OBJCLASS 24
144 #define LDAP_ATTR_ACB_INFO 25
145 #define LDAP_ATTR_NEXT_USERRID 26
146 #define LDAP_ATTR_NEXT_GROUPRID 27
147 #define LDAP_ATTR_DOM_SID 28
148 #define LDAP_ATTR_HOME_DRIVE 29
149 #define LDAP_ATTR_GROUP_SID 30
150 #define LDAP_ATTR_GROUP_TYPE 31
153 typedef struct _attrib_map_entry {
154 int attrib;
155 const char *name;
156 } ATTRIB_MAP_ENTRY;
159 /* attributes used by Samba 2.2 */
161 static ATTRIB_MAP_ENTRY attrib_map_v22[] = {
162 { LDAP_ATTR_UID, "uid" },
163 { LDAP_ATTR_UIDNUMBER, "uidNumber" },
164 { LDAP_ATTR_GIDNUMBER, "gidNumber" },
165 { LDAP_ATTR_UNIX_HOME, "homeDirectory" },
166 { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" },
167 { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" },
168 { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" },
169 { LDAP_ATTR_LOGON_TIME, "logonTime" },
170 { LDAP_ATTR_LOGOFF_TIME, "logoffTime" },
171 { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" },
172 { LDAP_ATTR_CN, "cn" },
173 { LDAP_ATTR_DISPLAY_NAME, "displayName" },
174 { LDAP_ATTR_HOME_PATH, "smbHome" },
175 { LDAP_ATTR_HOME_DRIVE, "homeDrives" },
176 { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" },
177 { LDAP_ATTR_PROFILE_PATH, "profilePath" },
178 { LDAP_ATTR_DESC, "description" },
179 { LDAP_ATTR_USER_WKS, "userWorkstations"},
180 { LDAP_ATTR_USER_RID, "rid" },
181 { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"},
182 { LDAP_ATTR_LMPW, "lmPassword" },
183 { LDAP_ATTR_NTPW, "ntPassword" },
184 { LDAP_ATTR_DOMAIN, "domain" },
185 { LDAP_ATTR_OBJCLASS, "objectClass" },
186 { LDAP_ATTR_ACB_INFO, "acctFlags" },
187 { LDAP_ATTR_LIST_END, NULL }
190 /* attributes used by Samba 3.0's sambaSamAccount */
192 static ATTRIB_MAP_ENTRY attrib_map_v30[] = {
193 { LDAP_ATTR_UID, "uid" },
194 { LDAP_ATTR_UIDNUMBER, "uidNumber" },
195 { LDAP_ATTR_GIDNUMBER, "gidNumber" },
196 { LDAP_ATTR_UNIX_HOME, "homeDirectory" },
197 { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" },
198 { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" },
199 { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" },
200 { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" },
201 { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" },
202 { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" },
203 { LDAP_ATTR_CN, "cn" },
204 { LDAP_ATTR_DISPLAY_NAME, "displayName" },
205 { LDAP_ATTR_HOME_DRIVE, "sambaHoneDrive" },
206 { LDAP_ATTR_HOME_PATH, "sambaHomePath" },
207 { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" },
208 { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" },
209 { LDAP_ATTR_DESC, "description" },
210 { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" },
211 { LDAP_ATTR_USER_SID, "sambaSID" },
212 { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" },
213 { LDAP_ATTR_LMPW, "sambaLMPassword" },
214 { LDAP_ATTR_NTPW, "sambaNTPassword" },
215 { LDAP_ATTR_DOMAIN, "sambaDomainName" },
216 { LDAP_ATTR_OBJCLASS, "objectClass" },
217 { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" },
218 { LDAP_ATTR_LIST_END, NULL }
221 /* attributes used for alalocating RIDs */
223 static ATTRIB_MAP_ENTRY dominfo_attr_list[] = {
224 { LDAP_ATTR_DOMAIN, "sambaDomainName" },
225 { LDAP_ATTR_NEXT_USERRID, "sambaNextUserRid" },
226 { LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" },
227 { LDAP_ATTR_DOM_SID, "sambaSID" },
228 { LDAP_ATTR_LIST_END, NULL },
231 /* Samba 3.0 group mapping attributes */
233 static ATTRIB_MAP_ENTRY groupmap_attr_list[] = {
234 { LDAP_ATTR_GIDNUMBER, "gidNumber" },
235 { LDAP_ATTR_GROUP_SID, "sambaSID" },
236 { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" },
237 { LDAP_ATTR_DESC, "description" },
238 { LDAP_ATTR_DISPLAY_NAME, "displayName" },
239 { LDAP_ATTR_CN, "cn" },
240 { LDAP_ATTR_LIST_END, NULL }
243 static ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = {
244 { LDAP_ATTR_GROUP_SID, "sambaSID" },
245 { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" },
246 { LDAP_ATTR_DESC, "description" },
247 { LDAP_ATTR_DISPLAY_NAME, "displayName" },
248 { LDAP_ATTR_LIST_END, NULL }
251 /**********************************************************************
252 perform a simple table lookup and return the attribute name
253 **********************************************************************/
255 static const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key )
257 int i = 0;
259 while ( table[i].attrib != LDAP_ATTR_LIST_END ) {
260 if ( table[i].attrib == key )
261 return table[i].name;
262 i++;
265 return NULL;
268 /**********************************************************************
269 get the attribute name given a user schame version
270 **********************************************************************/
272 static const char* get_userattr_key2string( int schema_ver, int key )
274 switch ( schema_ver )
276 case SCHEMAVER_SAMBAACCOUNT:
277 return get_attr_key2string( attrib_map_v22, key );
279 case SCHEMAVER_SAMBASAMACCOUNT:
280 return get_attr_key2string( attrib_map_v30, key );
282 default:
283 DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
284 break;
286 return NULL;
289 /**********************************************************************
290 Return the list of attribute names from a mapping table
291 **********************************************************************/
293 static char** get_attr_list( ATTRIB_MAP_ENTRY table[] )
295 char **names;
296 int i = 0;
298 while ( table[i].attrib != LDAP_ATTR_LIST_END )
299 i++;
300 i++;
302 names = (char**)malloc( sizeof(char*)*i );
303 if ( !names ) {
304 DEBUG(0,("get_attr_list: out of memory\n"));
305 return NULL;
308 i = 0;
309 while ( table[i].attrib != LDAP_ATTR_LIST_END ) {
310 names[i] = strdup( table[i].name );
311 i++;
313 names[i] = NULL;
315 return names;
318 /*********************************************************************
319 Cleanup
320 ********************************************************************/
322 static void free_attr_list( char **list )
324 int i = 0;
326 if ( !list )
327 return;
329 while ( list[i] )
330 SAFE_FREE( list[i] );
332 SAFE_FREE( list );
335 /**********************************************************************
336 return the list of attribute names given a user schema version
337 **********************************************************************/
339 static char** get_userattr_list( int schema_ver )
341 switch ( schema_ver )
343 case SCHEMAVER_SAMBAACCOUNT:
344 return get_attr_list( attrib_map_v22 );
346 case SCHEMAVER_SAMBASAMACCOUNT:
347 return get_attr_list( attrib_map_v30 );
348 default:
349 DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
350 break;
353 return NULL;
356 /*******************************************************************
357 find the ldap password
358 ******************************************************************/
359 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
361 char *key = NULL;
362 size_t size;
364 *dn = smb_xstrdup(lp_ldap_admin_dn());
366 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
367 SAFE_FREE(*dn);
368 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
371 *pw=secrets_fetch(key, &size);
372 SAFE_FREE(key);
374 if (!size) {
375 /* Upgrade 2.2 style entry */
376 char *p;
377 char* old_style_key = strdup(*dn);
378 char *data;
379 fstring old_style_pw;
381 if (!old_style_key) {
382 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
383 return False;
386 for (p=old_style_key; *p; p++)
387 if (*p == ',') *p = '/';
389 data=secrets_fetch(old_style_key, &size);
390 if (!size && size < sizeof(old_style_pw)) {
391 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
392 SAFE_FREE(old_style_key);
393 SAFE_FREE(*dn);
394 return False;
397 strncpy(old_style_pw, data, size);
398 old_style_pw[size] = 0;
400 SAFE_FREE(data);
402 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
403 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
404 SAFE_FREE(old_style_key);
405 SAFE_FREE(*dn);
406 return False;
408 if (!secrets_delete(old_style_key)) {
409 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
412 SAFE_FREE(old_style_key);
414 *pw = smb_xstrdup(old_style_pw);
417 return True;
420 /*******************************************************************
421 open a connection to the ldap server.
422 ******************************************************************/
423 static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
425 int rc = LDAP_SUCCESS;
426 int version;
427 BOOL ldap_v3 = False;
429 #ifdef HAVE_LDAP_INITIALIZE
430 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
432 if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
433 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
434 return rc;
437 #else
439 /* Parse the string manually */
442 int port = 0;
443 fstring protocol;
444 fstring host;
445 const char *p = ldap_state->uri;
446 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
448 /* skip leading "URL:" (if any) */
449 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
450 p += 4;
453 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
455 if (port == 0) {
456 if (strequal(protocol, "ldap")) {
457 port = LDAP_PORT;
458 } else if (strequal(protocol, "ldaps")) {
459 port = LDAPS_PORT;
460 } else {
461 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
465 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
466 DEBUG(0, ("ldap_init failed !\n"));
467 return LDAP_OPERATIONS_ERROR;
470 if (strequal(protocol, "ldaps")) {
471 #ifdef LDAP_OPT_X_TLS
472 int tls = LDAP_OPT_X_TLS_HARD;
473 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
475 DEBUG(0, ("Failed to setup a TLS session\n"));
478 DEBUG(3,("LDAPS option set...!\n"));
479 #else
480 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
481 return LDAP_OPERATIONS_ERROR;
482 #endif
485 #endif
487 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
489 if (version != LDAP_VERSION3)
491 version = LDAP_VERSION3;
492 if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
493 ldap_v3 = True;
495 } else {
496 ldap_v3 = True;
500 if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
501 #ifdef LDAP_OPT_X_TLS
502 if (ldap_v3) {
503 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
505 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
506 ldap_err2string(rc)));
507 return rc;
509 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
510 } else {
512 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
513 return LDAP_OPERATIONS_ERROR;
515 #else
516 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
517 return LDAP_OPERATIONS_ERROR;
518 #endif
521 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
522 return rc;
526 /*******************************************************************
527 a rebind function for authenticated referrals
528 This version takes a void* that we can shove useful stuff in :-)
529 ******************************************************************/
530 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
531 #else
532 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
533 int *methodp, int freeit, void *arg)
535 struct ldapsam_privates *ldap_state = arg;
537 /** @TODO Should we be doing something to check what servers we rebind to?
538 Could we get a referral to a machine that we don't want to give our
539 username and password to? */
541 if (freeit) {
542 SAFE_FREE(*whop);
543 memset(*credp, '\0', strlen(*credp));
544 SAFE_FREE(*credp);
545 } else {
546 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
547 ldap_state->bind_dn));
549 *whop = strdup(ldap_state->bind_dn);
550 if (!*whop) {
551 return LDAP_NO_MEMORY;
553 *credp = strdup(ldap_state->bind_secret);
554 if (!*credp) {
555 SAFE_FREE(*whop);
556 return LDAP_NO_MEMORY;
558 *methodp = LDAP_AUTH_SIMPLE;
560 return 0;
562 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
564 /*******************************************************************
565 a rebind function for authenticated referrals
566 This version takes a void* that we can shove useful stuff in :-)
567 and actually does the connection.
568 ******************************************************************/
569 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
570 static int rebindproc_connect_with_state (LDAP *ldap_struct,
571 LDAP_CONST char *url,
572 ber_tag_t request,
573 ber_int_t msgid, void *arg)
575 struct ldapsam_privates *ldap_state = arg;
576 int rc;
577 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
578 ldap_state->bind_dn));
580 /** @TODO Should we be doing something to check what servers we rebind to?
581 Could we get a referral to a machine that we don't want to give our
582 username and password to? */
584 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
586 return rc;
588 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
590 /*******************************************************************
591 Add a rebind function for authenticated referrals
592 ******************************************************************/
593 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
594 #else
595 # if LDAP_SET_REBIND_PROC_ARGS == 2
596 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
597 int *method, int freeit )
599 return rebindproc_with_state(ldap_struct, whop, credp,
600 method, freeit, static_ldap_state);
603 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
604 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
606 /*******************************************************************
607 a rebind function for authenticated referrals
608 this also does the connection, but no void*.
609 ******************************************************************/
610 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
611 # if LDAP_SET_REBIND_PROC_ARGS == 2
612 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
613 ber_int_t msgid)
615 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
616 static_ldap_state);
618 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
619 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
621 /*******************************************************************
622 connect to the ldap server under system privilege.
623 ******************************************************************/
624 static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
626 int rc;
627 char *ldap_dn;
628 char *ldap_secret;
630 /* The rebind proc needs this *HACK*. We are not multithreaded, so
631 this will work, but it's not nice. */
632 static_ldap_state = ldap_state;
634 /* get the password */
635 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
637 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
638 return LDAP_INVALID_CREDENTIALS;
641 ldap_state->bind_dn = ldap_dn;
642 ldap_state->bind_secret = ldap_secret;
644 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
645 (OpenLDAP) doesnt' seem to support it */
647 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
648 ldap_state->uri, ldap_dn));
650 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
651 # if LDAP_SET_REBIND_PROC_ARGS == 2
652 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
653 # endif
654 # if LDAP_SET_REBIND_PROC_ARGS == 3
655 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
656 # endif
657 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
658 # if LDAP_SET_REBIND_PROC_ARGS == 2
659 ldap_set_rebind_proc(ldap_struct, &rebindproc);
660 # endif
661 # if LDAP_SET_REBIND_PROC_ARGS == 3
662 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
663 # endif
664 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
666 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
668 if (rc != LDAP_SUCCESS) {
669 char *ld_error = NULL;
670 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
671 &ld_error);
672 DEBUG(ldap_state->num_failures ? 2 : 0,
673 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
674 ldap_dn ? ld_error : "(unknown)", ldap_err2string(rc),
675 ld_error));
676 SAFE_FREE(ld_error);
677 ldap_state->num_failures++;
678 return rc;
681 ldap_state->num_failures = 0;
683 DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
684 return rc;
687 /**********************************************************************
688 Connect to LDAP server
689 *********************************************************************/
690 static int ldapsam_open(struct ldapsam_privates *ldap_state)
692 int rc;
693 SMB_ASSERT(ldap_state);
695 #ifndef NO_LDAP_SECURITY
696 if (geteuid() != 0) {
697 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
698 return LDAP_INSUFFICIENT_ACCESS;
700 #endif
702 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
703 struct sockaddr_un addr;
704 socklen_t len = sizeof(addr);
705 int sd;
706 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
707 getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
708 /* the other end has died. reopen. */
709 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
710 ldap_state->ldap_struct = NULL;
711 ldap_state->last_ping = (time_t)0;
712 } else {
713 ldap_state->last_ping = time(NULL);
717 if (ldap_state->ldap_struct != NULL) {
718 DEBUG(5,("ldapsam_open: already connected to the LDAP server\n"));
719 return LDAP_SUCCESS;
722 if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
723 return rc;
726 if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
727 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
728 ldap_state->ldap_struct = NULL;
729 return rc;
733 ldap_state->last_ping = time(NULL);
734 DEBUG(4,("The LDAP server is succesful connected\n"));
736 return LDAP_SUCCESS;
739 /**********************************************************************
740 Disconnect from LDAP server
741 *********************************************************************/
742 static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
744 if (!ldap_state)
745 return NT_STATUS_INVALID_PARAMETER;
747 if (ldap_state->ldap_struct != NULL) {
748 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
749 ldap_state->ldap_struct = NULL;
752 DEBUG(5,("The connection to the LDAP server was closed\n"));
753 /* maybe free the results here --metze */
755 return NT_STATUS_OK;
758 static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
760 int rc;
762 SMB_ASSERT(ldap_state && attempts);
764 if (*attempts != 0) {
765 unsigned int sleep_time;
766 uint8 rand_byte;
768 /* Sleep for a random timeout */
769 rand_byte = (char)(sys_random());
771 sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2;
772 /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
773 on average.
775 DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n",
776 sleep_time));
777 msleep(sleep_time);
779 (*attempts)++;
781 if ((rc = ldapsam_open(ldap_state))) {
782 DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts));
783 return rc;
786 return LDAP_SUCCESS;
790 /*********************************************************************
791 ********************************************************************/
793 static int ldapsam_search(struct ldapsam_privates *ldap_state,
794 const char *base, int scope, const char *filter,
795 char *attrs[], int attrsonly,
796 LDAPMessage **res)
798 int rc = LDAP_SERVER_DOWN;
799 int attempts = 0;
800 char *utf8_filter;
802 SMB_ASSERT(ldap_state);
804 if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) {
805 return LDAP_NO_MEMORY;
808 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
810 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
811 continue;
813 rc = ldap_search_s(ldap_state->ldap_struct, base, scope,
814 utf8_filter, attrs, attrsonly, res);
817 if (rc == LDAP_SERVER_DOWN) {
818 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
819 ldapsam_close(ldap_state);
822 SAFE_FREE(utf8_filter);
823 return rc;
826 static int ldapsam_modify(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
828 int rc = LDAP_SERVER_DOWN;
829 int attempts = 0;
830 char *utf8_dn;
832 SMB_ASSERT(ldap_state);
834 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
835 return LDAP_NO_MEMORY;
838 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
840 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
841 continue;
843 rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
846 if (rc == LDAP_SERVER_DOWN) {
847 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
848 ldapsam_close(ldap_state);
851 SAFE_FREE(utf8_dn);
852 return rc;
855 static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
857 int rc = LDAP_SERVER_DOWN;
858 int attempts = 0;
859 char *utf8_dn;
861 SMB_ASSERT(ldap_state);
863 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
864 return LDAP_NO_MEMORY;
867 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
869 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
870 continue;
872 rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
875 if (rc == LDAP_SERVER_DOWN) {
876 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
877 ldapsam_close(ldap_state);
880 SAFE_FREE(utf8_dn);
881 return rc;
884 static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
886 int rc = LDAP_SERVER_DOWN;
887 int attempts = 0;
888 char *utf8_dn;
890 SMB_ASSERT(ldap_state);
892 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
893 return LDAP_NO_MEMORY;
896 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
898 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
899 continue;
901 rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
904 if (rc == LDAP_SERVER_DOWN) {
905 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
906 ldapsam_close(ldap_state);
909 SAFE_FREE(utf8_dn);
910 return rc;
913 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
914 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)
916 int rc = LDAP_SERVER_DOWN;
917 int attempts = 0;
919 if (!ldap_state)
920 return (-1);
922 while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
924 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
925 continue;
927 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
930 if (rc == LDAP_SERVER_DOWN) {
931 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
932 ldapsam_close(ldap_state);
935 return rc;
937 #endif
939 /*******************************************************************
940 run the search by name.
941 ******************************************************************/
942 static int ldapsam_search_suffix (struct ldapsam_privates *ldap_state, const char *filter,
943 char **search_attr, LDAPMessage ** result)
945 int scope = LDAP_SCOPE_SUBTREE;
946 int rc;
948 DEBUG(2, ("ldapsam_search_suffix: searching for:[%s]\n", filter));
950 rc = ldapsam_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result);
952 if (rc != LDAP_SUCCESS) {
953 char *ld_error = NULL;
954 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
955 &ld_error);
956 DEBUG(0,("ldapsam_search_suffix: Problem during the LDAP search: %s (%s)\n",
957 ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
958 DEBUG(3,("ldapsam_search_suffix: Query was: %s, %s\n", lp_ldap_suffix(),
959 filter));
960 SAFE_FREE(ld_error);
963 return rc;
966 /*******************************************************************
967 generate the LDAP search filter for the objectclass based on the
968 version of the schema we are using
969 ******************************************************************/
971 static const char* get_objclass_filter( int schema_ver )
973 static fstring objclass_filter;
975 switch( schema_ver )
977 case SCHEMAVER_SAMBAACCOUNT:
978 snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT );
979 break;
980 case SCHEMAVER_SAMBASAMACCOUNT:
981 snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT );
982 break;
983 default:
984 DEBUG(0,("ldapsam_search_suffix_by_name(): Invalid schema version specified!\n"));
985 break;
988 return objclass_filter;
991 /*******************************************************************
992 run the search by name.
993 ******************************************************************/
994 static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, const char *user,
995 LDAPMessage ** result, char **attr)
997 pstring filter;
998 char *escape_user = escape_ldap_string_alloc(user);
1000 if (!escape_user) {
1001 return LDAP_NO_MEMORY;
1005 * in the filter expression, replace %u with the real name
1006 * so in ldap filter, %u MUST exist :-)
1008 snprintf(filter, sizeof(filter)-1, "(&%s%s)", lp_ldap_filter(),
1009 get_objclass_filter(ldap_state->schema_ver));
1012 * have to use this here because $ is filtered out
1013 * in pstring_sub
1017 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
1018 SAFE_FREE(escape_user);
1020 return ldapsam_search_suffix(ldap_state, filter, attr, result);
1023 /*******************************************************************
1024 run the search by rid.
1025 ******************************************************************/
1026 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
1027 uint32 rid, LDAPMessage ** result,
1028 char **attr)
1030 pstring filter;
1031 int rc;
1033 /* check if the user rid exists, if not, try searching on the uid */
1035 snprintf(filter, sizeof(filter)-1, "(&(rid=%i)%s)", rid,
1036 get_objclass_filter(ldap_state->schema_ver));
1038 rc = ldapsam_search_suffix(ldap_state, filter, attr, result);
1040 return rc;
1043 /*******************************************************************
1044 run the search by SID.
1045 ******************************************************************/
1046 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
1047 const DOM_SID *sid, LDAPMessage ** result,
1048 char **attr)
1050 pstring filter;
1051 int rc;
1052 fstring sid_string;
1054 /* check if the user rid exsists, if not, try searching on the uid */
1056 snprintf(filter, sizeof(filter)-1, "(&(%s=%s)%s)",
1057 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
1058 sid_to_string(sid_string, sid),
1059 get_objclass_filter(ldap_state->schema_ver));
1061 rc = ldapsam_search_suffix(ldap_state, filter, attr, result);
1063 return rc;
1066 /*******************************************************************
1067 search an attribute and return the first value found.
1068 ******************************************************************/
1069 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
1070 const char *attribute, pstring value)
1072 char **values;
1074 if ( !attribute )
1075 return False;
1077 value[0] = '\0';
1079 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
1080 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
1082 return False;
1085 if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1)
1087 DEBUG(1, ("get_single_attribute: string conversion of [%s] = [%s] failed!\n",
1088 attribute, values[0]));
1089 ldap_value_free(values);
1090 return False;
1093 ldap_value_free(values);
1094 #ifdef DEBUG_PASSWORDS
1095 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
1096 #endif
1097 return True;
1100 /************************************************************************
1101 Routine to manage the LDAPMod structure array
1102 manage memory used by the array, by each struct, and values
1104 ************************************************************************/
1105 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
1107 LDAPMod **mods;
1108 int i;
1109 int j;
1111 mods = *modlist;
1113 /* sanity checks on the mod values */
1115 if (attribute == NULL || *attribute == '\0')
1116 return;
1117 #if 0 /* commented out after discussion with abartlet. Do not reenable.
1118 left here so other so re-add similar code --jerry */
1119 if (value == NULL || *value == '\0')
1120 return;
1121 #endif
1123 if (mods == NULL)
1125 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
1126 if (mods == NULL)
1128 DEBUG(0, ("make_a_mod: out of memory!\n"));
1129 return;
1131 mods[0] = NULL;
1134 for (i = 0; mods[i] != NULL; ++i) {
1135 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
1136 break;
1139 if (mods[i] == NULL)
1141 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
1142 if (mods == NULL)
1144 DEBUG(0, ("make_a_mod: out of memory!\n"));
1145 return;
1147 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
1148 if (mods[i] == NULL)
1150 DEBUG(0, ("make_a_mod: out of memory!\n"));
1151 return;
1153 mods[i]->mod_op = modop;
1154 mods[i]->mod_values = NULL;
1155 mods[i]->mod_type = strdup(attribute);
1156 mods[i + 1] = NULL;
1159 if (value != NULL)
1161 char *utf8_value = NULL;
1163 j = 0;
1164 if (mods[i]->mod_values != NULL) {
1165 for (; mods[i]->mod_values[j] != NULL; j++);
1167 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
1168 (j + 2) * sizeof (char *));
1170 if (mods[i]->mod_values == NULL) {
1171 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
1172 return;
1175 if (push_utf8_allocate(&utf8_value, value) == (size_t)-1) {
1176 DEBUG (0, ("make_a_mod: String conversion failure!\n"));
1177 return;
1180 mods[i]->mod_values[j] = utf8_value;
1182 mods[i]->mod_values[j + 1] = NULL;
1184 *modlist = mods;
1187 /**********************************************************************
1188 Set attribute to newval in LDAP, regardless of what value the
1189 attribute had in LDAP before.
1190 *********************************************************************/
1191 static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
1192 LDAPMod ***mods,
1193 const char *attribute, const char *newval)
1195 char **values = NULL;
1197 if (existing != NULL) {
1198 values = ldap_get_values(ldap_struct, existing, attribute);
1201 if ((values != NULL) && (values[0] != NULL) &&
1202 strcmp(values[0], newval) == 0) {
1204 /* Believe it or not, but LDAP will deny a delete and
1205 an add at the same time if the values are the
1206 same... */
1208 ldap_value_free(values);
1209 return;
1212 /* Regardless of the real operation (add or modify)
1213 we add the new value here. We rely on deleting
1214 the old value, should it exist. */
1216 if ((newval != NULL) && (strlen(newval) > 0)) {
1217 make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
1220 if (values == NULL) {
1221 /* There has been no value before, so don't delete it.
1222 Here's a possible race: We might end up with
1223 duplicate attributes */
1224 return;
1227 /* By deleting exactly the value we found in the entry this
1228 should be race-free in the sense that the LDAP-Server will
1229 deny the complete operation if somebody changed the
1230 attribute behind our back. */
1232 make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
1233 ldap_value_free(values);
1236 /*******************************************************************
1237 Delete complete object or objectclass and attrs from
1238 object found in search_result depending on lp_ldap_delete_dn
1239 ******************************************************************/
1240 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
1241 LDAPMessage *result,
1242 const char *objectclass,
1243 char **attrs)
1245 int rc;
1246 LDAPMessage *entry;
1247 LDAPMod **mods = NULL;
1248 char *name, *dn;
1249 BerElement *ptr = NULL;
1251 rc = ldap_count_entries(ldap_state->ldap_struct, result);
1253 if (rc != 1) {
1254 DEBUG(0, ("Entry must exist exactly once!\n"));
1255 return NT_STATUS_UNSUCCESSFUL;
1258 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1259 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
1261 if (lp_ldap_delete_dn()) {
1262 NTSTATUS ret = NT_STATUS_OK;
1263 rc = ldapsam_delete(ldap_state, dn);
1265 if (rc != LDAP_SUCCESS) {
1266 DEBUG(0, ("Could not delete object %s\n", dn));
1267 ret = NT_STATUS_UNSUCCESSFUL;
1269 ldap_memfree(dn);
1270 return ret;
1273 /* Ok, delete only the SAM attributes */
1275 for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
1276 name != NULL;
1277 name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr))
1279 char **attrib;
1281 /* We are only allowed to delete the attributes that
1282 really exist. */
1284 for (attrib = attrs; *attrib != NULL; attrib++)
1286 if (StrCaseCmp(*attrib, name) == 0) {
1287 DEBUG(10, ("deleting attribute %s\n", name));
1288 make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
1292 ldap_memfree(name);
1295 if (ptr != NULL) {
1296 ber_free(ptr, 0);
1299 make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
1301 rc = ldapsam_modify(ldap_state, dn, mods);
1302 ldap_mods_free(mods, 1);
1304 if (rc != LDAP_SUCCESS) {
1305 char *ld_error = NULL;
1306 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1307 &ld_error);
1309 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
1310 dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
1311 SAFE_FREE(ld_error);
1312 ldap_memfree(dn);
1313 return NT_STATUS_UNSUCCESSFUL;
1316 ldap_memfree(dn);
1317 return NT_STATUS_OK;
1320 /**********************************************************************
1321 Search for the domain info entry
1322 *********************************************************************/
1323 static int ldapsam_search_domain_info(struct ldapsam_privates *ldap_state,
1324 LDAPMessage ** result)
1326 pstring filter;
1327 int rc;
1328 char **attr_list;
1330 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
1331 LDAP_OBJ_DOMINFO,
1332 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
1333 ldap_state->domain_name);
1335 DEBUG(2, ("Searching for:[%s]\n", filter));
1338 attr_list = get_attr_list( dominfo_attr_list );
1339 rc = ldapsam_search_suffix(ldap_state, filter, attr_list , result);
1340 free_attr_list( attr_list );
1342 if (rc != LDAP_SUCCESS) {
1343 DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
1344 DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1347 return rc;
1350 /**********************************************************************
1351 If this entry is is the 'allocated' range, extract the RID and return
1352 it, so we can find the 'next' rid to allocate.
1354 Do this, no matter what type of object holds the RID - be it a user,
1355 group or somthing else.
1356 *********************************************************************/
1357 static uint32 entry_to_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, int rid_type)
1359 pstring sid_string;
1360 DOM_SID dom_sid;
1361 uint32 rid;
1363 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1364 LDAP_ATTRIBUTE_SID, sid_string))
1366 return 0;
1369 if (!string_to_sid(&dom_sid, sid_string)) {
1370 return 0;
1373 if (!sid_peek_check_rid(&dom_sid, get_global_sam_sid(), &rid)) {
1374 /* not our domain, so we don't care */
1375 return 0;
1378 switch (rid_type) {
1379 case USER_RID_TYPE:
1380 if (rid >= ldap_state->low_allocated_user_rid &&
1381 rid <= ldap_state->high_allocated_user_rid) {
1382 return rid;
1384 break;
1385 case GROUP_RID_TYPE:
1386 if (rid >= ldap_state->low_allocated_group_rid &&
1387 rid <= ldap_state->high_allocated_group_rid) {
1388 return rid;
1390 break;
1392 return 0;
1396 /**********************************************************************
1397 Connect to LDAP server and find the next available 'allocated' RID.
1399 The search is done 'per type' as we allocate seperate pools for the
1400 EVEN and ODD (user and group) RIDs.
1402 This is only done once, so that we can fill out the sambaDomain.
1403 *********************************************************************/
1404 static uint32 search_next_allocated_rid(struct ldapsam_privates *ldap_state, int rid_type)
1406 int rc;
1407 LDAPMessage *result;
1408 LDAPMessage *entry;
1409 uint32 top_rid = 0;
1410 uint32 next_rid;
1411 uint32 count;
1412 uint32 rid;
1413 char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
1414 fstring filter;
1416 snprintf( filter, sizeof(filter)-1, "(%s=*)", LDAP_ATTRIBUTE_SID );
1418 DEBUG(2, ("search_top_allocated_rid: searching for:[%s]\n", filter));
1420 rc = ldapsam_search_suffix(ldap_state, filter, sid_attr, &result);
1422 if (rc != LDAP_SUCCESS) {
1423 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1424 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1426 result = NULL;
1427 return 0;
1430 count = ldap_count_entries(ldap_state->ldap_struct, result);
1431 DEBUG(2, ("search_top_allocated_rid: %d entries in the base!\n", count));
1433 if (count == 0) {
1434 DEBUG(3, ("LDAP search returned no records, assuming no allocated RIDs present!: %s\n", ldap_err2string(rc)));
1435 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1436 } else {
1437 entry = ldap_first_entry(ldap_state->ldap_struct,result);
1439 top_rid = entry_to_rid(ldap_state, entry, rid_type);
1441 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1443 rid = entry_to_rid(ldap_state, entry, rid_type);
1444 if (((rid & ~RID_TYPE_MASK) == rid_type) && (rid > top_rid)) {
1445 top_rid = rid;
1450 switch (rid_type) {
1451 case USER_RID_TYPE:
1452 if (top_rid < ldap_state->low_allocated_user_rid) {
1453 return ldap_state->low_allocated_user_rid;
1455 break;
1456 case GROUP_RID_TYPE:
1457 if (top_rid < ldap_state->low_allocated_group_rid)
1458 return ldap_state->low_allocated_group_rid;
1459 break;
1462 next_rid = (top_rid & ~RID_TYPE_MASK) + rid_type + RID_MULTIPLIER;
1464 switch (rid_type) {
1465 case USER_RID_TYPE:
1466 if (next_rid > ldap_state->high_allocated_user_rid) {
1467 return 0;
1469 break;
1470 case GROUP_RID_TYPE:
1471 if (next_rid > ldap_state->high_allocated_group_rid) {
1472 return 0;
1474 break;
1476 return next_rid;
1479 /**********************************************************************
1480 Add the sambaDomain to LDAP, so we don't have to search for this stuff
1481 again. This is a once-add operation for now.
1483 TODO: Add other attributes, and allow modification.
1484 *********************************************************************/
1485 static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state)
1487 pstring tmp;
1488 pstring filter;
1489 LDAPMod **mods = NULL;
1490 int rc;
1491 int ldap_op;
1492 LDAPMessage *result = NULL;
1493 char *dn = NULL;
1494 int num_result;
1495 char **attr_list;
1497 uint32 next_allocated_user_rid;
1498 uint32 next_allocated_group_rid;
1500 next_allocated_user_rid = search_next_allocated_rid(ldap_state, USER_RID_TYPE);
1501 if (!next_allocated_user_rid) {
1502 return NT_STATUS_UNSUCCESSFUL;
1505 next_allocated_group_rid = search_next_allocated_rid(ldap_state, GROUP_RID_TYPE);
1506 if (!next_allocated_group_rid) {
1507 return NT_STATUS_UNSUCCESSFUL;
1510 slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))",
1511 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
1512 ldap_state->domain_name, LDAP_OBJ_DOMINFO);
1514 attr_list = get_attr_list( dominfo_attr_list );
1515 rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &result);
1516 free_attr_list( attr_list );
1518 if (rc != LDAP_SUCCESS) {
1519 return NT_STATUS_UNSUCCESSFUL;
1522 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
1524 if (num_result > 1) {
1525 DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
1526 ldap_msgfree(result);
1527 return NT_STATUS_UNSUCCESSFUL;
1530 /* Check if we need to add an entry */
1531 DEBUG(3,("Adding new domain\n"));
1532 ldap_op = LDAP_MOD_ADD;
1533 asprintf (&dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
1534 ldap_state->domain_name, lp_ldap_suffix());
1536 /* Free original search */
1537 ldap_msgfree(result);
1539 if (!dn)
1540 return NT_STATUS_NO_MEMORY;
1542 /* make the changes - the entry *must* not already have samba attributes */
1543 make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
1544 ldap_state->domain_name);
1546 sid_to_string(tmp, &ldap_state->domain_sid);
1547 make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), tmp);
1549 snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_user_rid);
1550 make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), tmp);
1552 snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_group_rid);
1553 make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), tmp);
1555 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
1557 switch(ldap_op)
1559 case LDAP_MOD_ADD:
1560 rc = ldapsam_add(ldap_state, dn, mods);
1561 break;
1562 case LDAP_MOD_REPLACE:
1563 rc = ldapsam_modify(ldap_state, dn, mods);
1564 break;
1565 default:
1566 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1567 return NT_STATUS_INVALID_PARAMETER;
1570 if (rc!=LDAP_SUCCESS) {
1571 char *ld_error = NULL;
1572 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1573 &ld_error);
1574 DEBUG(1,
1575 ("failed to %s domain dn= %s with: %s\n\t%s\n",
1576 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1577 dn, ldap_err2string(rc),
1578 ld_error?ld_error:"unknown"));
1579 SAFE_FREE(ld_error);
1581 ldap_mods_free(mods,1);
1582 return NT_STATUS_UNSUCCESSFUL;
1585 DEBUG(2,("added: domain = %s in the LDAP database\n", ldap_state->domain_name));
1586 ldap_mods_free(mods, 1);
1587 return NT_STATUS_OK;
1590 /**********************************************************************
1591 Even if the sambaAccount attribute in LDAP tells us that this RID is
1592 safe to use, always check before use.
1593 *********************************************************************/
1594 static BOOL sid_in_use(struct ldapsam_privates *ldap_state,
1595 const DOM_SID *sid, int *error)
1597 fstring filter;
1598 fstring sid_string;
1599 LDAPMessage *result = NULL;
1600 int count;
1601 int rc;
1602 char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
1604 slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid));
1606 rc = ldapsam_search_suffix(ldap_state, filter, sid_attr, &result);
1608 if (rc != LDAP_SUCCESS) {
1609 char *ld_error = NULL;
1610 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1611 DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
1612 sid_string, ld_error));
1613 SAFE_FREE(ld_error);
1615 *error = rc;
1616 return True;
1619 if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 0) {
1620 DEBUG(3, ("Sid %s already in use - trying next RID\n",
1621 sid_string));
1622 ldap_msgfree(result);
1623 return True;
1626 ldap_msgfree(result);
1628 /* good, sid is not in use */
1629 return False;
1632 /**********************************************************************
1633 Set the new nextRid attribute, and return one we can use.
1635 This also checks that this RID is actually free - in case the admin
1636 manually stole it :-).
1637 *********************************************************************/
1638 static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *rid, int rid_type)
1640 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1641 int rc;
1642 LDAPMessage *result = NULL;
1643 LDAPMessage *entry = NULL;
1644 char *dn;
1645 LDAPMod **mods = NULL;
1646 int count;
1647 fstring old_rid_string;
1648 fstring next_rid_string;
1649 uint32 next_rid;
1650 int attempts = 0;
1652 if ( ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT ) {
1653 DEBUG(0, ("Allocated RIDs require the %s objectclass used by 'ldapsam'\n",
1654 LDAP_OBJ_SAMBASAMACCOUNT));
1655 return NT_STATUS_UNSUCCESSFUL;
1658 while (attempts < 10)
1660 char *ld_error;
1661 if (ldapsam_search_domain_info(ldap_state, &result)) {
1662 return ret;
1665 if (ldap_count_entries(ldap_state->ldap_struct, result) < 1) {
1666 DEBUG(3, ("Got no domain info entries for domain %s\n",
1667 ldap_state->domain_name));
1668 ldap_msgfree(result);
1669 if (NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) {
1670 continue;
1671 } else {
1672 DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret)));
1673 return ret;
1677 if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 1) {
1678 DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
1679 count, ldap_state->domain_name));
1680 ldap_msgfree(result);
1681 return ret;
1684 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1685 if (!entry) {
1686 ldap_msgfree(result);
1687 return ret;
1690 if ((dn = ldap_get_dn(ldap_state->ldap_struct, entry)) == NULL) {
1691 DEBUG(0, ("Could not get domain info DN\n"));
1692 ldap_msgfree(result);
1693 return ret;
1696 /* yes, we keep 2 seperate counters, to avoid stomping on the two
1697 different sets of algorithmic RIDs */
1699 switch (rid_type) {
1700 case USER_RID_TYPE:
1701 if (!get_single_attribute(ldap_state->ldap_struct,
1702 entry, "nextUserRid",
1703 old_rid_string)) {
1704 ldap_memfree(dn);
1705 ldap_msgfree(result);
1706 return ret;
1708 break;
1709 case GROUP_RID_TYPE:
1710 if (!get_single_attribute(ldap_state->ldap_struct,
1711 entry, "nextGroupRid",
1712 old_rid_string)) {
1713 ldap_memfree(dn);
1714 ldap_msgfree(result);
1715 return ret;
1717 break;
1720 /* This is the core of the whole routine. If we had
1721 scheme-style closures, there would be a *lot* less code
1722 duplication... */
1723 *rid = (uint32)atol(old_rid_string);
1724 next_rid = *rid+RID_MULTIPLIER;
1726 slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
1728 switch (rid_type) {
1729 case USER_RID_TYPE:
1730 if (next_rid > ldap_state->high_allocated_user_rid) {
1731 return NT_STATUS_UNSUCCESSFUL;
1734 /* Try to make the modification atomically by enforcing the
1735 old value in the delete mod. */
1736 make_ldap_mod(ldap_state->ldap_struct, entry, &mods,
1737 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
1738 next_rid_string);
1739 break;
1741 case GROUP_RID_TYPE:
1742 if (next_rid > ldap_state->high_allocated_group_rid) {
1743 return NT_STATUS_UNSUCCESSFUL;
1746 /* Try to make the modification atomically by enforcing the
1747 old value in the delete mod. */
1748 make_ldap_mod(ldap_state->ldap_struct, entry, &mods,
1749 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
1750 next_rid_string);
1751 break;
1754 if ((rc = ldap_modify_s(ldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) {
1755 DOM_SID dom_sid;
1756 DOM_SID sid;
1757 pstring domain_sid_string;
1758 int error = 0;
1760 if (!get_single_attribute(ldap_state->ldap_struct, result,
1761 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID),
1762 domain_sid_string))
1764 ldap_mods_free(mods, 1);
1765 ldap_memfree(dn);
1766 ldap_msgfree(result);
1767 return ret;
1770 if (!string_to_sid(&dom_sid, domain_sid_string)) {
1771 ldap_mods_free(mods, 1);
1772 ldap_memfree(dn);
1773 ldap_msgfree(result);
1774 return ret;
1777 ldap_mods_free(mods, 1);
1778 mods = NULL;
1779 ldap_memfree(dn);
1780 ldap_msgfree(result);
1782 sid_copy(&sid, &dom_sid);
1783 sid_append_rid(&sid, *rid);
1785 /* check RID is not in use */
1786 if (sid_in_use(ldap_state, &sid, &error)) {
1787 if (error) {
1788 return ret;
1790 continue;
1793 return NT_STATUS_OK;
1796 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1797 DEBUG(2, ("Failed to modify rid: %s\n", ld_error));
1798 SAFE_FREE(ld_error);
1800 ldap_mods_free(mods, 1);
1801 mods = NULL;
1803 ldap_memfree(dn);
1804 dn = NULL;
1806 ldap_msgfree(result);
1807 result = NULL;
1810 /* Sleep for a random timeout */
1811 unsigned sleeptime = (sys_random()*sys_getpid()*attempts);
1812 attempts += 1;
1814 sleeptime %= 100;
1815 msleep(sleeptime);
1819 DEBUG(0, ("Failed to set new RID\n"));
1820 return ret;
1823 /* New Interface is being implemented here */
1825 /**********************************************************************
1826 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
1827 *********************************************************************/
1828 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
1829 SAM_ACCOUNT * sampass,
1830 LDAPMessage * entry,
1831 gid_t *gid)
1833 pstring homedir;
1834 pstring temp;
1835 char **ldap_values;
1836 char **values;
1838 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
1839 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
1840 return False;
1843 for (values=ldap_values;*values;values++) {
1844 if (strcasecmp(*values, LDAP_OBJ_POSIXACCOUNT ) == 0) {
1845 break;
1849 if (!*values) { /*end of array, no posixAccount */
1850 DEBUG(10, ("user does not have %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
1851 ldap_value_free(ldap_values);
1852 return False;
1854 ldap_value_free(ldap_values);
1856 if ( !get_single_attribute(ldap_state->ldap_struct, entry,
1857 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) )
1859 return False;
1862 if ( !get_single_attribute(ldap_state->ldap_struct, entry,
1863 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) )
1865 return False;
1868 *gid = (gid_t)atol(temp);
1870 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
1872 DEBUG(10, ("user has %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
1874 return True;
1878 /**********************************************************************
1879 Initialize SAM_ACCOUNT from an LDAP query
1880 (Based on init_sam_from_buffer in pdb_tdb.c)
1881 *********************************************************************/
1882 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
1883 SAM_ACCOUNT * sampass,
1884 LDAPMessage * entry)
1886 time_t logon_time,
1887 logoff_time,
1888 kickoff_time,
1889 pass_last_set_time,
1890 pass_can_change_time,
1891 pass_must_change_time;
1892 pstring username,
1893 domain,
1894 nt_username,
1895 fullname,
1896 homedir,
1897 dir_drive,
1898 logon_script,
1899 profile_path,
1900 acct_desc,
1901 munged_dial,
1902 workstations;
1903 uint32 user_rid;
1904 uint8 smblmpwd[LM_HASH_LEN],
1905 smbntpwd[NT_HASH_LEN];
1906 uint16 acct_ctrl = 0,
1907 logon_divs;
1908 uint32 hours_len;
1909 uint8 hours[MAX_HOURS_LEN];
1910 pstring temp;
1911 uid_t uid = -1;
1912 gid_t gid = getegid();
1915 * do a little initialization
1917 username[0] = '\0';
1918 domain[0] = '\0';
1919 nt_username[0] = '\0';
1920 fullname[0] = '\0';
1921 homedir[0] = '\0';
1922 dir_drive[0] = '\0';
1923 logon_script[0] = '\0';
1924 profile_path[0] = '\0';
1925 acct_desc[0] = '\0';
1926 munged_dial[0] = '\0';
1927 workstations[0] = '\0';
1930 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1931 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1932 return False;
1935 if (ldap_state->ldap_struct == NULL) {
1936 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1937 return False;
1940 if (!get_single_attribute(ldap_state->ldap_struct, entry, "uid", username)) {
1941 DEBUG(1, ("No uid attribute found for this user!\n"));
1942 return False;
1945 DEBUG(2, ("Entry found for user: %s\n", username));
1947 pstrcpy(nt_username, username);
1949 pstrcpy(domain, ldap_state->domain_name);
1951 pdb_set_username(sampass, username, PDB_SET);
1953 pdb_set_domain(sampass, domain, PDB_DEFAULT);
1954 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1956 /* deal with different attributes between the schema first */
1958 if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT )
1960 if (get_single_attribute(ldap_state->ldap_struct, entry,
1961 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp))
1963 pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
1966 if (get_single_attribute(ldap_state->ldap_struct, entry,
1967 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp))
1969 pdb_set_group_sid_from_string(sampass, temp, PDB_SET);
1971 else
1973 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
1978 else
1980 if (get_single_attribute(ldap_state->ldap_struct, entry,
1981 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp))
1983 user_rid = (uint32)atol(temp);
1984 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1987 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1988 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp))
1990 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
1991 } else {
1992 uint32 group_rid;
1994 group_rid = (uint32)atol(temp);
1996 /* for some reason, we often have 0 as a primary group RID.
1997 Make sure that we treat this just as a 'default' value */
1999 if ( group_rid > 0 )
2000 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
2001 else
2002 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
2006 if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
2007 DEBUG(1, ("no %s or %s attribute found for this user %s\n",
2008 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
2009 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID),
2010 username));
2011 return False;
2016 * If so configured, try and get the values from LDAP
2019 if (lp_ldap_trust_ids() && (get_unix_attributes(ldap_state, sampass, entry, &gid)))
2021 if (pdb_get_init_flags(sampass,PDB_GROUPSID) == PDB_DEFAULT)
2023 GROUP_MAP map;
2024 /* call the mapping code here */
2025 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
2026 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
2028 else {
2029 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
2034 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2035 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp))
2037 /* leave as default */
2038 } else {
2039 pass_last_set_time = (time_t) atol(temp);
2040 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
2043 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2044 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp))
2046 /* leave as default */
2047 } else {
2048 logon_time = (time_t) atol(temp);
2049 pdb_set_logon_time(sampass, logon_time, PDB_SET);
2052 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2053 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp))
2055 /* leave as default */
2056 } else {
2057 logoff_time = (time_t) atol(temp);
2058 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
2061 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2062 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp))
2064 /* leave as default */
2065 } else {
2066 kickoff_time = (time_t) atol(temp);
2067 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
2070 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2071 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp))
2073 /* leave as default */
2074 } else {
2075 pass_can_change_time = (time_t) atol(temp);
2076 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
2079 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2080 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp))
2082 /* leave as default */
2083 } else {
2084 pass_must_change_time = (time_t) atol(temp);
2085 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
2088 /* recommend that 'gecos' and 'displayName' should refer to the same
2089 * attribute OID. userFullName depreciated, only used by Samba
2090 * primary rules of LDAP: don't make a new attribute when one is already defined
2091 * that fits your needs; using cn then displayName rather than 'userFullName'
2094 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2095 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname))
2097 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2098 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname))
2100 /* leave as default */
2101 } else {
2102 pdb_set_fullname(sampass, fullname, PDB_SET);
2104 } else {
2105 pdb_set_fullname(sampass, fullname, PDB_SET);
2108 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2109 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive))
2111 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
2112 lp_logon_drive(),
2113 username, domain,
2114 uid, gid),
2115 PDB_DEFAULT);
2116 } else {
2117 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
2120 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2121 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir))
2123 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
2124 lp_logon_home(),
2125 username, domain,
2126 uid, gid),
2127 PDB_DEFAULT);
2128 } else {
2129 pdb_set_homedir(sampass, homedir, PDB_SET);
2132 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2133 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script))
2135 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
2136 lp_logon_script(),
2137 username, domain,
2138 uid, gid),
2139 PDB_DEFAULT);
2140 } else {
2141 pdb_set_logon_script(sampass, logon_script, PDB_SET);
2144 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2145 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path))
2147 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
2148 lp_logon_path(),
2149 username, domain,
2150 uid, gid),
2151 PDB_DEFAULT);
2152 } else {
2153 pdb_set_profile_path(sampass, profile_path, PDB_SET);
2156 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2157 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), acct_desc))
2159 /* leave as default */
2160 } else {
2161 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
2164 if (!get_single_attribute(ldap_state->ldap_struct, entry,
2165 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations))
2167 /* leave as default */;
2168 } else {
2169 pdb_set_workstations(sampass, workstations, PDB_SET);
2172 /* FIXME: hours stuff should be cleaner */
2174 logon_divs = 168;
2175 hours_len = 21;
2176 memset(hours, 0xff, hours_len);
2178 if (!get_single_attribute (ldap_state->ldap_struct, entry,
2179 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp))
2181 /* leave as default */
2182 } else {
2183 pdb_gethexpwd(temp, smblmpwd);
2184 memset((char *)temp, '\0', strlen(temp)+1);
2185 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
2186 return False;
2187 ZERO_STRUCT(smblmpwd);
2190 if (!get_single_attribute (ldap_state->ldap_struct, entry,
2191 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp))
2193 /* leave as default */
2194 } else {
2195 pdb_gethexpwd(temp, smbntpwd);
2196 memset((char *)temp, '\0', strlen(temp)+1);
2197 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
2198 return False;
2199 ZERO_STRUCT(smbntpwd);
2202 if (!get_single_attribute (ldap_state->ldap_struct, entry,
2203 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp))
2205 acct_ctrl |= ACB_NORMAL;
2206 } else {
2207 acct_ctrl = pdb_decode_acct_ctrl(temp);
2209 if (acct_ctrl == 0)
2210 acct_ctrl |= ACB_NORMAL;
2212 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
2215 pdb_set_hours_len(sampass, hours_len, PDB_SET);
2216 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
2218 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
2220 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
2221 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
2222 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
2224 pdb_set_hours(sampass, hours, PDB_SET);
2226 return True;
2229 /**********************************************************************
2230 Initialize SAM_ACCOUNT from an LDAP query
2231 (Based on init_buffer_from_sam in pdb_tdb.c)
2232 *********************************************************************/
2233 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
2234 LDAPMessage *existing,
2235 LDAPMod *** mods, SAM_ACCOUNT * sampass,
2236 BOOL (*need_update)(const SAM_ACCOUNT *,
2237 enum pdb_elements))
2239 pstring temp;
2240 uint32 rid;
2242 if (mods == NULL || sampass == NULL) {
2243 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
2244 return False;
2247 *mods = NULL;
2250 * took out adding "objectclass: sambaAccount"
2251 * do this on a per-mod basis
2253 if (need_update(sampass, PDB_USERNAME))
2254 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2255 "uid", pdb_get_username(sampass));
2257 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
2259 if (pdb_get_init_flags(sampass, PDB_USERSID) == PDB_DEFAULT) {
2260 if (ldap_state->permit_non_unix_accounts) {
2261 if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state, &rid, USER_RID_TYPE))) {
2262 DEBUG(0, ("NO user RID specified on account %s, and "
2263 "finding next available NUA RID failed, "
2264 "cannot store!\n",
2265 pdb_get_username(sampass)));
2266 ldap_mods_free(*mods, 1);
2267 return False;
2269 } else {
2270 DEBUG(0, ("NO user RID specified on account %s, "
2271 "cannot store!\n", pdb_get_username(sampass)));
2272 ldap_mods_free(*mods, 1);
2273 return False;
2276 /* now that we have figured out the RID, always store it, as
2277 the schema requires it (either as a SID or a RID) */
2279 if (!pdb_set_user_sid_from_rid(sampass, rid, PDB_CHANGED)) {
2280 DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n",
2281 pdb_get_username(sampass)));
2282 ldap_mods_free(*mods, 1);
2283 return False;
2287 /* only update the RID if we actually need to */
2288 if (need_update(sampass, PDB_USERSID))
2290 fstring sid_string;
2291 fstring dom_sid_string;
2292 const DOM_SID *user_sid = pdb_get_user_sid(sampass);
2294 switch ( ldap_state->schema_ver )
2296 case SCHEMAVER_SAMBAACCOUNT:
2297 if (!sid_peek_check_rid(get_global_sam_sid(), user_sid, &rid)) {
2298 DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
2299 sid_to_string(sid_string, user_sid),
2300 sid_to_string(dom_sid_string, get_global_sam_sid())));
2301 return False;
2303 slprintf(temp, sizeof(temp) - 1, "%i", rid);
2304 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2305 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID),
2306 temp);
2307 break;
2309 case SCHEMAVER_SAMBASAMACCOUNT:
2310 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2311 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
2312 sid_to_string(sid_string, user_sid));
2313 break;
2315 default:
2316 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
2317 break;
2321 /* we don't need to store the primary group RID - so leaving it
2322 'free' to hang off the unix primary group makes life easier */
2324 if (need_update(sampass, PDB_GROUPSID))
2326 fstring sid_string;
2327 fstring dom_sid_string;
2328 const DOM_SID *group_sid = pdb_get_group_sid(sampass);
2330 switch ( ldap_state->schema_ver )
2332 case SCHEMAVER_SAMBAACCOUNT:
2333 if (!sid_peek_check_rid(get_global_sam_sid(), group_sid, &rid)) {
2334 DEBUG(1, ("User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
2335 sid_to_string(sid_string, group_sid),
2336 sid_to_string(dom_sid_string, get_global_sam_sid())));
2337 return False;
2340 slprintf(temp, sizeof(temp) - 1, "%i", rid);
2341 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2342 get_userattr_key2string(ldap_state->schema_ver,
2343 LDAP_ATTR_PRIMARY_GROUP_RID), temp);
2344 break;
2346 case SCHEMAVER_SAMBASAMACCOUNT:
2347 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2348 get_userattr_key2string(ldap_state->schema_ver,
2349 LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_string(sid_string, group_sid));
2350 break;
2352 default:
2353 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
2354 break;
2359 /* displayName, cn, and gecos should all be the same
2360 * most easily accomplished by giving them the same OID
2361 * gecos isn't set here b/c it should be handled by the
2362 * add-user script
2363 * We change displayName only and fall back to cn if
2364 * it does not exist.
2367 if (need_update(sampass, PDB_FULLNAME))
2368 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2369 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME),
2370 pdb_get_fullname(sampass));
2372 if (need_update(sampass, PDB_ACCTDESC))
2373 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2374 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC),
2375 pdb_get_acct_desc(sampass));
2377 if (need_update(sampass, PDB_WORKSTATIONS))
2378 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2379 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS),
2380 pdb_get_workstations(sampass));
2382 if (need_update(sampass, PDB_SMBHOME))
2383 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2384 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH),
2385 pdb_get_homedir(sampass));
2387 if (need_update(sampass, PDB_DRIVE))
2388 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2389 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE),
2390 pdb_get_dir_drive(sampass));
2392 if (need_update(sampass, PDB_LOGONSCRIPT))
2393 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2394 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT),
2395 pdb_get_logon_script(sampass));
2397 if (need_update(sampass, PDB_PROFILE))
2398 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2399 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH),
2400 pdb_get_profile_path(sampass));
2402 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
2403 if (need_update(sampass, PDB_LOGONTIME))
2404 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2405 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp);
2407 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
2408 if (need_update(sampass, PDB_LOGOFFTIME))
2409 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2410 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp);
2412 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
2413 if (need_update(sampass, PDB_KICKOFFTIME))
2414 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2415 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
2417 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
2418 if (need_update(sampass, PDB_CANCHANGETIME))
2419 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2420 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
2422 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
2423 if (need_update(sampass, PDB_MUSTCHANGETIME))
2424 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2425 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp);
2427 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
2428 || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY))
2431 pdb_sethexpwd(temp, pdb_get_lanman_passwd(sampass),
2432 pdb_get_acct_ctrl(sampass));
2434 if (need_update(sampass, PDB_LMPASSWD))
2435 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2436 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW),
2437 temp);
2439 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
2440 pdb_get_acct_ctrl(sampass));
2442 if (need_update(sampass, PDB_NTPASSWD))
2443 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2444 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW),
2445 temp);
2447 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
2448 if (need_update(sampass, PDB_PASSLASTSET))
2449 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2450 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET),
2451 temp);
2454 /* FIXME: Hours stuff goes in LDAP */
2456 if (need_update(sampass, PDB_ACCTCTRL))
2457 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2458 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO),
2459 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN));
2461 return True;
2466 /**********************************************************************
2467 Connect to LDAP server for password enumeration
2468 *********************************************************************/
2469 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
2471 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2472 int rc;
2473 pstring filter;
2474 char **attr_list;
2476 snprintf( filter, sizeof(filter)-1, "(&%s%s)", lp_ldap_filter(),
2477 get_objclass_filter(ldap_state->schema_ver));
2478 all_string_sub(filter, "%u", "*", sizeof(pstring));
2480 attr_list = get_userattr_list(ldap_state->schema_ver);
2481 rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &ldap_state->result);
2482 free_attr_list( attr_list );
2484 if (rc != LDAP_SUCCESS) {
2485 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2486 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2487 ldap_msgfree(ldap_state->result);
2488 ldap_state->result = NULL;
2489 return NT_STATUS_UNSUCCESSFUL;
2492 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2493 ldap_count_entries(ldap_state->ldap_struct,
2494 ldap_state->result)));
2496 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2497 ldap_state->result);
2498 ldap_state->index = 0;
2500 return NT_STATUS_OK;
2503 /**********************************************************************
2504 End enumeration of the LDAP password list
2505 *********************************************************************/
2506 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
2508 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2509 if (ldap_state->result) {
2510 ldap_msgfree(ldap_state->result);
2511 ldap_state->result = NULL;
2515 /**********************************************************************
2516 Get the next entry in the LDAP password database
2517 *********************************************************************/
2518 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
2520 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2521 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2522 BOOL bret = False;
2524 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2525 this will work, but it's not nice. */
2526 static_ldap_state = ldap_state;
2528 while (!bret) {
2529 if (!ldap_state->entry)
2530 return ret;
2532 ldap_state->index++;
2533 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
2535 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2536 ldap_state->entry);
2539 return NT_STATUS_OK;
2542 /**********************************************************************
2543 Get SAM_ACCOUNT entry from LDAP by username
2544 *********************************************************************/
2545 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
2547 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2548 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2549 LDAPMessage *result;
2550 LDAPMessage *entry;
2551 int count;
2552 char ** attr_list;
2553 int rc;
2555 attr_list = get_userattr_list( ldap_state->schema_ver );
2556 rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
2557 free_attr_list( attr_list );
2559 if ( rc != LDAP_SUCCESS )
2560 return NT_STATUS_NO_SUCH_USER;
2562 count = ldap_count_entries(ldap_state->ldap_struct, result);
2564 if (count < 1) {
2565 DEBUG(4,
2566 ("Unable to locate user [%s] count=%d\n", sname,
2567 count));
2568 return NT_STATUS_NO_SUCH_USER;
2569 } else if (count > 1) {
2570 DEBUG(1,
2571 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
2572 count));
2573 return NT_STATUS_NO_SUCH_USER;
2576 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2577 if (entry) {
2578 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2579 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
2580 ldap_msgfree(result);
2581 return NT_STATUS_NO_SUCH_USER;
2583 ldap_msgfree(result);
2584 ret = NT_STATUS_OK;
2585 } else {
2586 ldap_msgfree(result);
2588 return ret;
2591 /**********************************************************************
2592 Get SAM_ACCOUNT entry from LDAP by SID
2593 *********************************************************************/
2594 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
2596 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2597 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2598 LDAPMessage *result;
2599 LDAPMessage *entry;
2600 fstring sid_string;
2601 int count;
2602 int rc;
2603 char ** attr_list;
2605 switch ( ldap_state->schema_ver )
2607 case SCHEMAVER_SAMBASAMACCOUNT:
2608 attr_list = get_userattr_list(ldap_state->schema_ver);
2609 rc = ldapsam_search_suffix_by_sid(ldap_state, sid, &result, attr_list);
2610 free_attr_list( attr_list );
2612 if ( rc != LDAP_SUCCESS )
2613 return NT_STATUS_NO_SUCH_USER;
2614 break;
2616 case SCHEMAVER_SAMBAACCOUNT:
2618 uint32 rid;
2619 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) {
2620 return NT_STATUS_NO_SUCH_USER;
2623 attr_list = get_userattr_list(ldap_state->schema_ver);
2624 rc = ldapsam_search_suffix_by_rid(ldap_state, rid, &result, attr_list );
2625 free_attr_list( attr_list );
2627 if ( rc != LDAP_SUCCESS )
2628 return NT_STATUS_NO_SUCH_USER;
2630 break;
2633 count = ldap_count_entries(ldap_state->ldap_struct, result);
2635 if (count < 1)
2637 DEBUG(4,
2638 ("Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string, sid),
2639 count));
2640 return NT_STATUS_NO_SUCH_USER;
2642 else if (count > 1)
2644 DEBUG(1,
2645 ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid),
2646 count));
2647 return NT_STATUS_NO_SUCH_USER;
2650 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2651 if (entry)
2653 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2654 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
2655 ldap_msgfree(result);
2656 return NT_STATUS_NO_SUCH_USER;
2658 ldap_msgfree(result);
2659 ret = NT_STATUS_OK;
2660 } else {
2661 ldap_msgfree(result);
2663 return ret;
2666 /********************************************************************
2667 Do the actual modification - also change a plaittext passord if
2668 it it set.
2669 **********************************************************************/
2671 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
2672 SAM_ACCOUNT *newpwd, char *dn,
2673 LDAPMod **mods, int ldap_op,
2674 BOOL (*need_update)(const SAM_ACCOUNT *,
2675 enum pdb_elements))
2677 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2678 int rc;
2680 if (!my_methods || !newpwd || !dn) {
2681 return NT_STATUS_INVALID_PARAMETER;
2684 if (!mods) {
2685 DEBUG(5,("mods is empty: nothing to modify\n"));
2686 /* may be password change below however */
2687 } else {
2688 switch(ldap_op)
2690 case LDAP_MOD_ADD:
2691 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_ACCOUNT);
2692 rc = ldapsam_add(ldap_state, dn, mods);
2693 break;
2694 case LDAP_MOD_REPLACE:
2695 rc = ldapsam_modify(ldap_state, dn ,mods);
2696 break;
2697 default:
2698 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
2699 return NT_STATUS_INVALID_PARAMETER;
2702 if (rc!=LDAP_SUCCESS) {
2703 char *ld_error = NULL;
2704 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2705 &ld_error);
2706 DEBUG(1,
2707 ("failed to %s user dn= %s with: %s\n\t%s\n",
2708 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
2709 dn, ldap_err2string(rc),
2710 ld_error?ld_error:"unknown"));
2711 SAFE_FREE(ld_error);
2712 return NT_STATUS_UNSUCCESSFUL;
2716 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
2717 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
2718 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
2719 need_update(newpwd, PDB_PLAINTEXT_PW) &&
2720 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
2721 BerElement *ber;
2722 struct berval *bv;
2723 char *retoid;
2724 struct berval *retdata;
2725 char *utf8_password;
2726 char *utf8_dn;
2728 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
2729 return NT_STATUS_NO_MEMORY;
2732 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
2733 return NT_STATUS_NO_MEMORY;
2736 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
2737 DEBUG(0,("ber_alloc_t returns NULL\n"));
2738 SAFE_FREE(utf8_password);
2739 return NT_STATUS_UNSUCCESSFUL;
2742 ber_printf (ber, "{");
2743 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, utf8_dn);
2744 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, utf8_password);
2745 ber_printf (ber, "N}");
2747 if ((rc = ber_flatten (ber, &bv))<0) {
2748 DEBUG(0,("ber_flatten returns a value <0\n"));
2749 ber_free(ber,1);
2750 SAFE_FREE(utf8_dn);
2751 SAFE_FREE(utf8_password);
2752 return NT_STATUS_UNSUCCESSFUL;
2755 SAFE_FREE(utf8_dn);
2756 SAFE_FREE(utf8_password);
2757 ber_free(ber, 1);
2759 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
2760 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
2761 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
2762 pdb_get_username(newpwd),ldap_err2string(rc)));
2763 } else {
2764 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
2765 #ifdef DEBUG_PASSWORD
2766 DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
2767 #endif
2768 ber_bvfree(retdata);
2769 ber_memfree(retoid);
2771 ber_bvfree(bv);
2773 #else
2774 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
2775 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
2776 return NT_STATUS_OK;
2779 /**********************************************************************
2780 Delete entry from LDAP for username
2781 *********************************************************************/
2782 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
2784 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2785 const char *sname;
2786 int rc;
2787 LDAPMessage *result;
2788 NTSTATUS ret;
2789 char **attr_list;
2790 fstring objclass;
2792 if (!sam_acct) {
2793 DEBUG(0, ("sam_acct was NULL!\n"));
2794 return NT_STATUS_INVALID_PARAMETER;
2797 sname = pdb_get_username(sam_acct);
2799 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
2801 attr_list= get_userattr_list( ldap_state->schema_ver );
2802 rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
2804 if (rc != LDAP_SUCCESS) {
2805 free_attr_list( attr_list );
2806 return NT_STATUS_NO_SUCH_USER;
2809 switch ( ldap_state->schema_ver )
2811 case SCHEMAVER_SAMBASAMACCOUNT:
2812 fstrcpy( objclass, LDAP_OBJ_SAMBASAMACCOUNT );
2813 break;
2815 case SCHEMAVER_SAMBAACCOUNT:
2816 fstrcpy( objclass, LDAP_OBJ_SAMBAACCOUNT );
2817 break;
2818 default:
2819 fstrcpy( objclass, "UNKNOWN" );
2820 DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
2821 break;
2824 ret = ldapsam_delete_entry(ldap_state, result, objclass, attr_list );
2825 ldap_msgfree(result);
2826 free_attr_list( attr_list );
2828 return ret;
2831 /**********************************************************************
2832 Helper function to determine for update_sam_account whether
2833 we need LDAP modification.
2834 *********************************************************************/
2835 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
2836 enum pdb_elements element)
2838 return IS_SAM_CHANGED(sampass, element);
2841 /**********************************************************************
2842 Update SAM_ACCOUNT
2843 *********************************************************************/
2844 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2846 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2847 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2848 int rc;
2849 char *dn;
2850 LDAPMessage *result;
2851 LDAPMessage *entry;
2852 LDAPMod **mods;
2853 char **attr_list;
2855 attr_list = get_userattr_list(ldap_state->schema_ver);
2856 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
2857 free_attr_list( attr_list );
2858 if (rc != LDAP_SUCCESS)
2859 return NT_STATUS_UNSUCCESSFUL;
2861 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2862 DEBUG(0, ("No user to modify!\n"));
2863 ldap_msgfree(result);
2864 return NT_STATUS_UNSUCCESSFUL;
2867 entry = ldap_first_entry(ldap_state->ldap_struct, result);
2868 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2870 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2871 element_is_changed)) {
2872 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2873 ldap_msgfree(result);
2874 return NT_STATUS_UNSUCCESSFUL;
2877 ldap_msgfree(result);
2879 if (mods == NULL) {
2880 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2881 pdb_get_username(newpwd)));
2882 ldap_mods_free(mods, 1);
2883 return NT_STATUS_OK;
2886 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
2887 ldap_mods_free(mods,1);
2889 if (!NT_STATUS_IS_OK(ret)) {
2890 char *ld_error = NULL;
2891 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2892 &ld_error);
2893 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2894 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
2895 SAFE_FREE(ld_error);
2896 return ret;
2899 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2900 pdb_get_username(newpwd)));
2901 return NT_STATUS_OK;
2904 /**********************************************************************
2905 Helper function to determine for update_sam_account whether
2906 we need LDAP modification.
2907 *********************************************************************/
2908 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2909 enum pdb_elements element)
2911 return (IS_SAM_SET(sampass, element) ||
2912 IS_SAM_CHANGED(sampass, element));
2915 /**********************************************************************
2916 Add SAM_ACCOUNT to LDAP
2917 *********************************************************************/
2919 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2921 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2922 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2923 int rc;
2924 LDAPMessage *result = NULL;
2925 LDAPMessage *entry = NULL;
2926 pstring dn;
2927 LDAPMod **mods = NULL;
2928 int ldap_op;
2929 uint32 num_result;
2930 char **attr_list;
2931 char *escape_user;
2932 const char *username = pdb_get_username(newpwd);
2933 pstring filter;
2935 if (!username || !*username) {
2936 DEBUG(0, ("Cannot add user without a username!\n"));
2937 return NT_STATUS_INVALID_PARAMETER;
2940 /* free this list after the second search or in case we exit on failure */
2942 attr_list = get_userattr_list(ldap_state->schema_ver);
2943 rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
2945 if (rc != LDAP_SUCCESS) {
2946 free_attr_list( attr_list );
2947 return NT_STATUS_UNSUCCESSFUL;
2950 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2951 DEBUG(0,("User '%s' already in the base, with samba attributes\n",
2952 username));
2953 ldap_msgfree(result);
2954 free_attr_list( attr_list );
2955 return NT_STATUS_UNSUCCESSFUL;
2957 ldap_msgfree(result);
2959 /* does the entry already exist but without a samba rttibutes?
2960 we don't really care what attributes are returned here */
2962 escape_user = escape_ldap_string_alloc( username );
2963 pstrcpy( filter, lp_ldap_filter() );
2964 all_string_sub( filter, "%u", escape_user, sizeof(filter) );
2965 SAFE_FREE( escape_user );
2967 rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &result);
2968 free_attr_list( attr_list );
2970 if ( rc != LDAP_SUCCESS )
2971 return NT_STATUS_UNSUCCESSFUL;
2973 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2975 if (num_result > 1) {
2976 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2977 ldap_msgfree(result);
2978 return NT_STATUS_UNSUCCESSFUL;
2981 /* Check if we need to update an existing entry */
2982 if (num_result == 1) {
2983 char *tmp;
2985 DEBUG(3,("User exists without samba attributes: adding them\n"));
2986 ldap_op = LDAP_MOD_REPLACE;
2987 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2988 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2989 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2990 ldap_memfree (tmp);
2991 } else {
2992 /* Check if we need to add an entry */
2993 DEBUG(3,("Adding new user\n"));
2994 ldap_op = LDAP_MOD_ADD;
2995 if (username[strlen(username)-1] == '$') {
2996 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2997 } else {
2998 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
3002 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
3003 element_is_set_or_changed)) {
3004 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
3005 ldap_msgfree(result);
3006 return NT_STATUS_UNSUCCESSFUL;
3009 ldap_msgfree(result);
3011 if (mods == NULL) {
3012 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
3013 return NT_STATUS_UNSUCCESSFUL;
3015 switch ( ldap_state->schema_ver )
3017 case SCHEMAVER_SAMBAACCOUNT:
3018 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT);
3019 break;
3020 case SCHEMAVER_SAMBASAMACCOUNT:
3021 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT);
3022 break;
3023 default:
3024 DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
3025 break;
3028 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
3029 if (NT_STATUS_IS_ERR(ret)) {
3030 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
3031 pdb_get_username(newpwd),dn));
3032 ldap_mods_free(mods,1);
3033 return ret;
3036 DEBUG(2,("added: uid == %s in the LDAP database\n", pdb_get_username(newpwd)));
3037 ldap_mods_free(mods, 1);
3039 return NT_STATUS_OK;
3042 /**********************************************************************
3043 Housekeeping
3044 *********************************************************************/
3046 static void free_private_data(void **vp)
3048 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
3050 ldapsam_close(*ldap_state);
3052 if ((*ldap_state)->bind_secret) {
3053 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
3056 ldapsam_close(*ldap_state);
3058 SAFE_FREE((*ldap_state)->bind_dn);
3059 SAFE_FREE((*ldap_state)->bind_secret);
3061 *ldap_state = NULL;
3063 /* No need to free any further, as it is talloc()ed */
3066 /**********************************************************************
3067 *********************************************************************/
3069 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
3070 const char *filter,
3071 LDAPMessage ** result)
3073 int scope = LDAP_SCOPE_SUBTREE;
3074 int rc;
3075 char **attr_list;
3077 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
3080 attr_list = get_attr_list(groupmap_attr_list);
3081 rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
3082 filter, attr_list, 0, result);
3083 free_attr_list( attr_list );
3085 if (rc != LDAP_SUCCESS) {
3086 char *ld_error = NULL;
3087 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
3088 &ld_error);
3089 DEBUG(0, ("ldapsam_search_one_group: "
3090 "Problem during the LDAP search: LDAP error: %s (%s)",
3091 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
3092 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
3093 lp_ldap_suffix(), filter));
3094 SAFE_FREE(ld_error);
3097 return rc;
3100 /**********************************************************************
3101 *********************************************************************/
3103 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
3104 GROUP_MAP *map, LDAPMessage *entry)
3106 pstring temp;
3108 if (ldap_state == NULL || map == NULL || entry == NULL ||
3109 ldap_state->ldap_struct == NULL)
3111 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
3112 return False;
3115 if (!get_single_attribute(ldap_state->ldap_struct, entry,
3116 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp))
3118 DEBUG(0, ("Mandatory attribute %s not found\n",
3119 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER)));
3120 return False;
3122 DEBUG(2, ("Entry found for group: %s\n", temp));
3124 map->gid = (gid_t)atol(temp);
3126 if (!get_single_attribute(ldap_state->ldap_struct, entry,
3127 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp))
3129 DEBUG(0, ("Mandatory attribute %s not found\n",
3130 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID)));
3131 return False;
3133 string_to_sid(&map->sid, temp);
3135 if (!get_single_attribute(ldap_state->ldap_struct, entry,
3136 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp))
3138 DEBUG(0, ("Mandatory attribute %s not found\n",
3139 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
3140 return False;
3142 map->sid_name_use = (uint32)atol(temp);
3144 if ((map->sid_name_use < SID_NAME_USER) ||
3145 (map->sid_name_use > SID_NAME_UNKNOWN)) {
3146 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
3147 return False;
3150 if (!get_single_attribute(ldap_state->ldap_struct, entry,
3151 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp))
3153 temp[0] = '\0';
3154 if (!get_single_attribute(ldap_state->ldap_struct, entry,
3155 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp))
3157 DEBUG(0, ("Attributes cn not found either "
3158 "for gidNumber(%i)\n",map->gid));
3159 return False;
3162 fstrcpy(map->nt_name, temp);
3164 if (!get_single_attribute(ldap_state->ldap_struct, entry,
3165 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp))
3167 temp[0] = '\0';
3169 fstrcpy(map->comment, temp);
3171 map->systemaccount = 0;
3172 init_privilege(&map->priv_set);
3174 return True;
3177 /**********************************************************************
3178 *********************************************************************/
3180 static BOOL init_ldap_from_group(LDAP *ldap_struct,
3181 LDAPMessage *existing,
3182 LDAPMod ***mods,
3183 const GROUP_MAP *map)
3185 pstring tmp;
3187 if (mods == NULL || map == NULL) {
3188 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
3189 return False;
3192 *mods = NULL;
3194 sid_to_string(tmp, &map->sid);
3195 make_ldap_mod(ldap_struct, existing, mods,
3196 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
3197 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
3198 make_ldap_mod(ldap_struct, existing, mods,
3199 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
3201 make_ldap_mod(ldap_struct, existing, mods,
3202 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
3203 make_ldap_mod(ldap_struct, existing, mods,
3204 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
3206 return True;
3209 /**********************************************************************
3210 *********************************************************************/
3212 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
3213 const char *filter,
3214 GROUP_MAP *map)
3216 struct ldapsam_privates *ldap_state =
3217 (struct ldapsam_privates *)methods->private_data;
3218 LDAPMessage *result;
3219 LDAPMessage *entry;
3220 int count;
3222 if (ldapsam_search_one_group(ldap_state, filter, &result)
3223 != LDAP_SUCCESS) {
3224 return NT_STATUS_NO_SUCH_GROUP;
3227 count = ldap_count_entries(ldap_state->ldap_struct, result);
3229 if (count < 1) {
3230 DEBUG(4, ("Did not find group for filter %s\n", filter));
3231 return NT_STATUS_NO_SUCH_GROUP;
3234 if (count > 1) {
3235 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
3236 filter, count));
3237 return NT_STATUS_NO_SUCH_GROUP;
3240 entry = ldap_first_entry(ldap_state->ldap_struct, result);
3242 if (!entry) {
3243 ldap_msgfree(result);
3244 return NT_STATUS_UNSUCCESSFUL;
3247 if (!init_group_from_ldap(ldap_state, map, entry)) {
3248 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
3249 filter));
3250 ldap_msgfree(result);
3251 return NT_STATUS_NO_SUCH_GROUP;
3254 ldap_msgfree(result);
3255 return NT_STATUS_OK;
3258 /**********************************************************************
3259 *********************************************************************/
3261 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
3262 DOM_SID sid, BOOL with_priv)
3264 pstring filter;
3266 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
3267 LDAP_OBJ_GROUPMAP,
3268 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
3269 sid_string_static(&sid));
3271 return ldapsam_getgroup(methods, filter, map);
3274 /**********************************************************************
3275 *********************************************************************/
3277 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
3278 gid_t gid, BOOL with_priv)
3280 pstring filter;
3282 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%d))",
3283 LDAP_OBJ_GROUPMAP,
3284 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
3285 gid);
3287 return ldapsam_getgroup(methods, filter, map);
3290 /**********************************************************************
3291 *********************************************************************/
3293 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
3294 char *name, BOOL with_priv)
3296 pstring filter;
3298 /* TODO: Escaping of name? */
3300 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
3301 LDAP_OBJ_GROUPMAP,
3302 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), name,
3303 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), name);
3305 return ldapsam_getgroup(methods, filter, map);
3308 /**********************************************************************
3309 *********************************************************************/
3311 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
3312 gid_t gid,
3313 LDAPMessage **result)
3315 pstring filter;
3317 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%i))",
3318 LDAP_OBJ_POSIXGROUP,
3319 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
3320 gid);
3322 return ldapsam_search_one_group(ldap_state, filter, result);
3325 /**********************************************************************
3326 *********************************************************************/
3328 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
3329 GROUP_MAP *map)
3331 struct ldapsam_privates *ldap_state =
3332 (struct ldapsam_privates *)methods->private_data;
3333 LDAPMessage *result = NULL;
3334 LDAPMod **mods = NULL;
3336 char *tmp;
3337 pstring dn;
3338 LDAPMessage *entry;
3340 GROUP_MAP dummy;
3342 int rc;
3344 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
3345 map->gid, False))) {
3346 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
3347 return NT_STATUS_UNSUCCESSFUL;
3350 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
3351 if (rc != LDAP_SUCCESS) {
3352 return NT_STATUS_UNSUCCESSFUL;
3355 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
3356 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
3357 map->gid));
3358 ldap_msgfree(result);
3359 return NT_STATUS_UNSUCCESSFUL;
3362 entry = ldap_first_entry(ldap_state->ldap_struct, result);
3363 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
3364 pstrcpy(dn, tmp);
3365 ldap_memfree(tmp);
3367 if (!init_ldap_from_group(ldap_state->ldap_struct,
3368 result, &mods, map)) {
3369 DEBUG(0, ("init_ldap_from_group failed!\n"));
3370 ldap_mods_free(mods, 1);
3371 ldap_msgfree(result);
3372 return NT_STATUS_UNSUCCESSFUL;
3375 ldap_msgfree(result);
3377 if (mods == NULL) {
3378 DEBUG(0, ("mods is empty\n"));
3379 return NT_STATUS_UNSUCCESSFUL;
3382 make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
3383 "sambaGroupMapping");
3385 rc = ldapsam_modify(ldap_state, dn, mods);
3386 ldap_mods_free(mods, 1);
3388 if (rc != LDAP_SUCCESS) {
3389 char *ld_error = NULL;
3390 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
3391 &ld_error);
3392 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
3393 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
3394 SAFE_FREE(ld_error);
3395 return NT_STATUS_UNSUCCESSFUL;
3398 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
3399 return NT_STATUS_OK;
3402 /**********************************************************************
3403 *********************************************************************/
3405 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
3406 GROUP_MAP *map)
3408 struct ldapsam_privates *ldap_state =
3409 (struct ldapsam_privates *)methods->private_data;
3410 int rc;
3411 char *dn;
3412 LDAPMessage *result;
3413 LDAPMessage *entry;
3414 LDAPMod **mods;
3416 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
3418 if (rc != LDAP_SUCCESS) {
3419 return NT_STATUS_UNSUCCESSFUL;
3422 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
3423 DEBUG(0, ("No group to modify!\n"));
3424 ldap_msgfree(result);
3425 return NT_STATUS_UNSUCCESSFUL;
3428 entry = ldap_first_entry(ldap_state->ldap_struct, result);
3429 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
3431 if (!init_ldap_from_group(ldap_state->ldap_struct,
3432 result, &mods, map)) {
3433 DEBUG(0, ("init_ldap_from_group failed\n"));
3434 ldap_msgfree(result);
3435 return NT_STATUS_UNSUCCESSFUL;
3438 ldap_msgfree(result);
3440 if (mods == NULL) {
3441 DEBUG(4, ("mods is empty: nothing to do\n"));
3442 return NT_STATUS_UNSUCCESSFUL;
3445 rc = ldapsam_modify(ldap_state, dn, mods);
3447 ldap_mods_free(mods, 1);
3449 if (rc != LDAP_SUCCESS) {
3450 char *ld_error = NULL;
3451 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
3452 &ld_error);
3453 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
3454 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
3455 SAFE_FREE(ld_error);
3458 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
3459 return NT_STATUS_OK;
3462 /**********************************************************************
3463 *********************************************************************/
3465 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
3466 DOM_SID sid)
3468 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
3469 pstring sidstring, filter;
3470 LDAPMessage *result;
3471 int rc;
3472 NTSTATUS ret;
3473 char **attr_list;
3475 sid_to_string(sidstring, &sid);
3477 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
3478 LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
3480 rc = ldapsam_search_one_group(ldap_state, filter, &result);
3482 if (rc != LDAP_SUCCESS) {
3483 return NT_STATUS_NO_SUCH_GROUP;
3486 attr_list = get_attr_list( groupmap_attr_list_to_delete );
3487 ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
3488 free_attr_list ( attr_list );
3490 ldap_msgfree(result);
3492 return ret;
3495 /**********************************************************************
3496 *********************************************************************/
3498 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
3500 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
3501 fstring filter;
3502 int rc;
3503 char **attr_list;
3505 snprintf( filter, sizeof(filter)-1, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
3506 attr_list = get_attr_list( groupmap_attr_list );
3507 rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
3508 LDAP_SCOPE_SUBTREE, filter,
3509 attr_list, 0, &ldap_state->result);
3510 free_attr_list( attr_list );
3512 if (rc != LDAP_SUCCESS) {
3513 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
3514 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
3515 ldap_msgfree(ldap_state->result);
3516 ldap_state->result = NULL;
3517 return NT_STATUS_UNSUCCESSFUL;
3520 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
3521 ldap_count_entries(ldap_state->ldap_struct,
3522 ldap_state->result)));
3524 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct, ldap_state->result);
3525 ldap_state->index = 0;
3527 return NT_STATUS_OK;
3530 /**********************************************************************
3531 *********************************************************************/
3533 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
3535 ldapsam_endsampwent(my_methods);
3538 /**********************************************************************
3539 *********************************************************************/
3541 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
3542 GROUP_MAP *map)
3544 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
3545 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
3546 BOOL bret = False;
3548 /* The rebind proc needs this *HACK*. We are not multithreaded, so
3549 this will work, but it's not nice. */
3550 static_ldap_state = ldap_state;
3552 while (!bret) {
3553 if (!ldap_state->entry)
3554 return ret;
3556 ldap_state->index++;
3557 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
3559 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
3560 ldap_state->entry);
3563 return NT_STATUS_OK;
3566 /**********************************************************************
3567 *********************************************************************/
3569 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
3570 enum SID_NAME_USE sid_name_use,
3571 GROUP_MAP **rmap, int *num_entries,
3572 BOOL unix_only, BOOL with_priv)
3574 GROUP_MAP map;
3575 GROUP_MAP *mapt;
3576 int entries = 0;
3577 NTSTATUS nt_status;
3579 *num_entries = 0;
3580 *rmap = NULL;
3582 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
3583 DEBUG(0, ("Unable to open passdb\n"));
3584 return NT_STATUS_ACCESS_DENIED;
3587 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
3588 if (sid_name_use != SID_NAME_UNKNOWN &&
3589 sid_name_use != map.sid_name_use) {
3590 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
3591 continue;
3593 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
3594 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
3595 continue;
3598 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
3599 if (!mapt) {
3600 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
3601 SAFE_FREE(*rmap);
3602 return NT_STATUS_UNSUCCESSFUL;
3604 else
3605 (*rmap) = mapt;
3607 mapt[entries] = map;
3609 entries += 1;
3612 ldapsam_endsamgrent(methods);
3614 *num_entries = entries;
3616 return NT_STATUS_OK;
3619 /**********************************************************************
3620 *********************************************************************/
3622 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method,
3623 const char *location)
3625 NTSTATUS nt_status;
3626 struct ldapsam_privates *ldap_state;
3628 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
3629 return nt_status;
3632 (*pdb_method)->name = "ldapsam";
3634 (*pdb_method)->setsampwent = ldapsam_setsampwent;
3635 (*pdb_method)->endsampwent = ldapsam_endsampwent;
3636 (*pdb_method)->getsampwent = ldapsam_getsampwent;
3637 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
3638 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
3639 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
3640 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
3641 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
3643 (*pdb_method)->getgrsid = ldapsam_getgrsid;
3644 (*pdb_method)->getgrgid = ldapsam_getgrgid;
3645 (*pdb_method)->getgrnam = ldapsam_getgrnam;
3646 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
3647 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
3648 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
3649 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
3651 /* TODO: Setup private data and free */
3653 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
3655 if (!ldap_state) {
3656 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
3657 return NT_STATUS_NO_MEMORY;
3660 if (location) {
3661 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3662 } else {
3663 ldap_state->uri = "ldap://localhost";
3666 ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
3667 if (!ldap_state->domain_name) {
3668 return NT_STATUS_NO_MEMORY;
3671 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
3673 (*pdb_method)->private_data = ldap_state;
3675 (*pdb_method)->free_private_data = free_private_data;
3677 return NT_STATUS_OK;
3680 /**********************************************************************
3681 *********************************************************************/
3683 static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3685 NTSTATUS nt_status;
3686 struct ldapsam_privates *ldap_state;
3688 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3689 return nt_status;
3692 (*pdb_method)->name = "ldapsam_compat";
3694 ldap_state = (*pdb_method)->private_data;
3695 ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
3697 if (location) {
3698 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3699 } else {
3700 #ifndef WITH_LDAP_SAMCONFIG
3701 ldap_state->uri = "ldap://localhost";
3702 #else
3703 int ldap_port = lp_ldap_port();
3705 /* remap default port if not using SSL (ie clear or TLS) */
3706 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
3707 ldap_port = 389;
3710 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);
3711 if (!ldap_state->uri) {
3712 return NT_STATUS_NO_MEMORY;
3714 #endif
3717 return NT_STATUS_OK;
3720 /**********************************************************************
3721 *********************************************************************/
3723 static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3725 NTSTATUS nt_status;
3726 struct ldapsam_privates *ldap_state;
3727 uint32 low_idmap_uid, high_idmap_uid;
3728 uint32 low_idmap_gid, high_idmap_gid;
3730 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3731 return nt_status;
3734 (*pdb_method)->name = "ldapsam";
3736 ldap_state = (*pdb_method)->private_data;
3737 ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
3738 ldap_state->permit_non_unix_accounts = False;
3740 /* check for non-unix account ranges */
3742 if (lp_idmap_uid(&low_idmap_uid, &high_idmap_uid)
3743 && lp_idmap_gid(&low_idmap_gid, &high_idmap_gid))
3745 DEBUG(2, ("Enabling non-unix account ranges\n"));
3747 ldap_state->permit_non_unix_accounts = True;
3749 ldap_state->low_allocated_user_rid = fallback_pdb_uid_to_user_rid(low_idmap_uid);
3750 ldap_state->high_allocated_user_rid = fallback_pdb_uid_to_user_rid(high_idmap_uid);
3751 ldap_state->low_allocated_group_rid = pdb_gid_to_group_rid(low_idmap_gid);
3752 ldap_state->high_allocated_group_rid = pdb_gid_to_group_rid(high_idmap_gid);
3755 return NT_STATUS_OK;
3758 NTSTATUS pdb_ldap_init(void)
3760 NTSTATUS nt_status;
3761 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
3762 return nt_status;
3764 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
3765 return nt_status;
3767 return NT_STATUS_OK;