2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Jean François Micouleau 1998
5 Copyright (C) Gerald Carter 2001
6 Copyright (C) Shahms King 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Stefan (metze) Metzmacher 2002
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #define DBGC_CLASS DBGC_PASSDB
33 * persistent connections: if using NSS LDAP, many connections are made
34 * however, using only one within Samba would be nice
36 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
38 * Other LDAP based login attributes: accountExpires, etc.
39 * (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
40 * structures don't have fields for some of these attributes)
42 * SSL is done, but can't get the certificate based authentication to work
43 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
46 /* NOTE: this will NOT work against an Active Directory server
47 * due to the fact that the two password fields cannot be retrieved
48 * from a server; recommend using security = domain in this situation
56 #define SAM_ACCOUNT struct sam_passwd
59 struct ldapsam_privates
{
68 /* retrive-once info */
71 BOOL permit_non_unix_accounts
;
80 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
82 static struct ldapsam_privates
*static_ldap_state
;
84 static uint32
ldapsam_get_next_available_nua_rid(struct ldapsam_privates
*ldap_state
);
86 /*******************************************************************
87 find the ldap password
88 ******************************************************************/
89 static BOOL
fetch_ldapsam_pw(char **dn
, char** pw
)
94 *dn
= smb_xstrdup(lp_ldap_admin_dn());
96 if (asprintf(&key
, "%s/%s", SECRETS_LDAP_BIND_PW
, *dn
) < 0) {
98 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
101 *pw
=secrets_fetch(key
, &size
);
103 /* Upgrade 2.2 style entry */
105 char* old_style_key
= strdup(*dn
);
107 fstring old_style_pw
;
109 if (!old_style_key
) {
110 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
114 for (p
=old_style_key
; *p
; p
++)
115 if (*p
== ',') *p
= '/';
117 data
=secrets_fetch(old_style_key
, &size
);
118 if (!size
&& size
< sizeof(old_style_pw
)) {
119 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
120 SAFE_FREE(old_style_key
);
125 strncpy(old_style_pw
, data
, size
);
126 old_style_pw
[size
] = 0;
130 if (!secrets_store_ldap_pw(*dn
, old_style_pw
)) {
131 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
132 SAFE_FREE(old_style_key
);
136 if (!secrets_delete(old_style_key
)) {
137 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
140 SAFE_FREE(old_style_key
);
142 *pw
= smb_xstrdup(old_style_pw
);
148 static const char *attr
[] = {"uid", "pwdLastSet", "logonTime",
149 "logoffTime", "kickoffTime", "cn",
150 "pwdCanChange", "pwdMustChange",
151 "displayName", "homeDrive",
152 "smbHome", "scriptPath",
153 "profilePath", "description",
154 "userWorkstations", "rid",
155 "primaryGroupID", "lmPassword",
156 "ntPassword", "acctFlags",
157 "domain", "objectClass",
158 "uidNumber", "gidNumber",
159 "homeDirectory", NULL
};
161 /*******************************************************************
162 open a connection to the ldap server.
163 ******************************************************************/
164 static int ldapsam_open_connection (struct ldapsam_privates
*ldap_state
, LDAP
** ldap_struct
)
166 int rc
= LDAP_SUCCESS
;
168 BOOL ldap_v3
= False
;
170 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
171 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state
->uri
));
173 if ((rc
= ldap_initialize(ldap_struct
, ldap_state
->uri
)) != LDAP_SUCCESS
) {
174 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc
)));
180 /* Parse the string manually */
186 const char *p
= ldap_state
->uri
;
187 SMB_ASSERT(sizeof(protocol
)>10 && sizeof(host
)>254);
189 /* skip leading "URL:" (if any) */
190 if ( strncasecmp( p
, "URL:", 4 ) == 0 ) {
194 sscanf(p
, "%10[^:]://%254s[^:]:%d", protocol
, host
, &port
);
197 if (strequal(protocol
, "ldap")) {
199 } else if (strequal(protocol
, "ldaps")) {
202 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol
));
206 if ((*ldap_struct
= ldap_init(host
, port
)) == NULL
) {
207 DEBUG(0, ("ldap_init failed !\n"));
208 return LDAP_OPERATIONS_ERROR
;
211 if (strequal(protocol
, "ldaps")) {
212 #ifdef LDAP_OPT_X_TLS
213 int tls
= LDAP_OPT_X_TLS_HARD
;
214 if (ldap_set_option (*ldap_struct
, LDAP_OPT_X_TLS
, &tls
) != LDAP_SUCCESS
)
216 DEBUG(0, ("Failed to setup a TLS session\n"));
219 DEBUG(3,("LDAPS option set...!\n"));
221 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
222 return LDAP_OPERATIONS_ERROR
;
228 if (ldap_get_option(*ldap_struct
, LDAP_OPT_PROTOCOL_VERSION
, &version
) == LDAP_OPT_SUCCESS
)
230 if (version
!= LDAP_VERSION3
)
232 version
= LDAP_VERSION3
;
233 if (ldap_set_option (*ldap_struct
, LDAP_OPT_PROTOCOL_VERSION
, &version
) == LDAP_OPT_SUCCESS
) {
241 if (lp_ldap_ssl() == LDAP_SSL_START_TLS
) {
242 #ifdef LDAP_OPT_X_TLS
244 if ((rc
= ldap_start_tls_s (*ldap_struct
, NULL
, NULL
)) != LDAP_SUCCESS
)
246 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
247 ldap_err2string(rc
)));
250 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
253 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
254 return LDAP_OPERATIONS_ERROR
;
257 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
258 return LDAP_OPERATIONS_ERROR
;
262 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
267 /*******************************************************************
268 a rebind function for authenticated referrals
269 This version takes a void* that we can shove useful stuff in :-)
270 ******************************************************************/
271 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
273 static int rebindproc_with_state (LDAP
* ld
, char **whop
, char **credp
,
274 int *methodp
, int freeit
, void *arg
)
276 struct ldapsam_privates
*ldap_state
= arg
;
278 /** @TODO Should we be doing something to check what servers we rebind to?
279 Could we get a referral to a machine that we don't want to give our
280 username and password to? */
284 memset(*credp
, '\0', strlen(*credp
));
287 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
288 ldap_state
->bind_dn
));
290 *whop
= strdup(ldap_state
->bind_dn
);
292 return LDAP_NO_MEMORY
;
294 *credp
= strdup(ldap_state
->bind_secret
);
297 return LDAP_NO_MEMORY
;
299 *methodp
= LDAP_AUTH_SIMPLE
;
303 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
305 /*******************************************************************
306 a rebind function for authenticated referrals
307 This version takes a void* that we can shove useful stuff in :-)
308 and actually does the connection.
309 ******************************************************************/
310 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
311 static int rebindproc_connect_with_state (LDAP
*ldap_struct
,
312 LDAP_CONST
char *url
,
314 ber_int_t msgid
, void *arg
)
316 struct ldapsam_privates
*ldap_state
= arg
;
318 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
319 ldap_state
->bind_dn
));
321 /** @TODO Should we be doing something to check what servers we rebind to?
322 Could we get a referral to a machine that we don't want to give our
323 username and password to? */
325 rc
= ldap_simple_bind_s(ldap_struct
, ldap_state
->bind_dn
, ldap_state
->bind_secret
);
329 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
331 /*******************************************************************
332 Add a rebind function for authenticated referrals
333 ******************************************************************/
334 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
336 # if LDAP_SET_REBIND_PROC_ARGS == 2
337 static int rebindproc (LDAP
*ldap_struct
, char **whop
, char **credp
,
338 int *method
, int freeit
)
340 return rebindproc_with_state(ldap_struct
, whop
, credp
,
341 method
, freeit
, static_ldap_state
);
344 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
345 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
347 /*******************************************************************
348 a rebind function for authenticated referrals
349 this also does the connection, but no void*.
350 ******************************************************************/
351 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
352 # if LDAP_SET_REBIND_PROC_ARGS == 2
353 static int rebindproc_connect (LDAP
* ld
, LDAP_CONST
char *url
, int request
,
356 return rebindproc_connect_with_state(ld
, url
, (ber_tag_t
)request
, msgid
,
359 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
360 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
362 /*******************************************************************
363 connect to the ldap server under system privilege.
364 ******************************************************************/
365 static int ldapsam_connect_system(struct ldapsam_privates
*ldap_state
, LDAP
* ldap_struct
)
371 /* The rebind proc needs this *HACK*. We are not multithreaded, so
372 this will work, but it's not nice. */
373 static_ldap_state
= ldap_state
;
375 /* get the password */
376 if (!fetch_ldapsam_pw(&ldap_dn
, &ldap_secret
))
378 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
379 return LDAP_INVALID_CREDENTIALS
;
382 ldap_state
->bind_dn
= ldap_dn
;
383 ldap_state
->bind_secret
= ldap_secret
;
385 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
386 (OpenLDAP) doesnt' seem to support it */
388 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
389 ldap_state
->uri
, ldap_dn
));
391 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
392 # if LDAP_SET_REBIND_PROC_ARGS == 2
393 ldap_set_rebind_proc(ldap_struct
, &rebindproc_connect
);
395 # if LDAP_SET_REBIND_PROC_ARGS == 3
396 ldap_set_rebind_proc(ldap_struct
, &rebindproc_connect_with_state
, (void *)ldap_state
);
398 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
399 # if LDAP_SET_REBIND_PROC_ARGS == 2
400 ldap_set_rebind_proc(ldap_struct
, &rebindproc
);
402 # if LDAP_SET_REBIND_PROC_ARGS == 3
403 ldap_set_rebind_proc(ldap_struct
, &rebindproc_with_state
, (void *)ldap_state
);
405 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
407 rc
= ldap_simple_bind_s(ldap_struct
, ldap_dn
, ldap_secret
);
409 if (rc
!= LDAP_SUCCESS
) {
411 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
414 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
415 ldap_dn
, ldap_err2string(rc
),
421 DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
425 /**********************************************************************
426 Connect to LDAP server
427 *********************************************************************/
428 static int ldapsam_open(struct ldapsam_privates
*ldap_state
)
431 SMB_ASSERT(ldap_state
);
433 #ifndef NO_LDAP_SECURITY
434 if (geteuid() != 0) {
435 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
436 return LDAP_INSUFFICIENT_ACCESS
;
440 if ((ldap_state
->ldap_struct
!= NULL
) && ((ldap_state
->last_ping
+ LDAPSAM_DONT_PING_TIME
) < time(NULL
))) {
441 struct sockaddr_un addr
;
444 if (ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_DESC
, &sd
) == 0 &&
445 getpeername(sd
, (struct sockaddr
*) &addr
, &len
) < 0) {
446 /* the other end has died. reopen. */
447 ldap_unbind_ext(ldap_state
->ldap_struct
, NULL
, NULL
);
448 ldap_state
->ldap_struct
= NULL
;
449 ldap_state
->last_ping
= (time_t)0;
451 ldap_state
->last_ping
= time(NULL
);
455 if (ldap_state
->ldap_struct
!= NULL
) {
456 DEBUG(5,("ldapsam_open: allready connected to the LDAP server\n"));
460 if ((rc
= ldapsam_open_connection(ldap_state
, &ldap_state
->ldap_struct
))) {
464 if ((rc
= ldapsam_connect_system(ldap_state
, ldap_state
->ldap_struct
))) {
465 ldap_unbind_ext(ldap_state
->ldap_struct
, NULL
, NULL
);
466 ldap_state
->ldap_struct
= NULL
;
471 ldap_state
->last_ping
= time(NULL
);
472 DEBUG(4,("The LDAP server is succesful connected\n"));
477 /**********************************************************************
478 Disconnect from LDAP server
479 *********************************************************************/
480 static NTSTATUS
ldapsam_close(struct ldapsam_privates
*ldap_state
)
483 return NT_STATUS_INVALID_PARAMETER
;
485 if (ldap_state
->ldap_struct
!= NULL
) {
486 ldap_unbind_ext(ldap_state
->ldap_struct
, NULL
, NULL
);
487 ldap_state
->ldap_struct
= NULL
;
490 DEBUG(5,("The connection to the LDAP server was closed\n"));
491 /* maybe free the results here --metze */
496 static int ldapsam_retry_open(struct ldapsam_privates
*ldap_state
, int *attempts
)
500 SMB_ASSERT(ldap_state
&& attempts
);
502 if (*attempts
!= 0) {
503 /* we retry after 0.5, 2, 4.5, 8, 12.5, 18, 24.5 seconds */
504 msleep((((*attempts
)*(*attempts
))/2)*1000);
508 if ((rc
= ldapsam_open(ldap_state
))) {
509 DEBUG(0,("Connection to LDAP Server failed for the %d try!\n",*attempts
));
517 static int ldapsam_search(struct ldapsam_privates
*ldap_state
,
518 const char *base
, int scope
, const char *filter
,
519 const char *attrs
[], int attrsonly
,
522 int rc
= LDAP_SERVER_DOWN
;
525 SMB_ASSERT(ldap_state
);
527 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
529 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
532 rc
= ldap_search_s(ldap_state
->ldap_struct
, base
, scope
,
533 filter
, attrs
, attrsonly
, res
);
536 if (rc
== LDAP_SERVER_DOWN
) {
537 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
538 ldapsam_close(ldap_state
);
544 static int ldapsam_modify(struct ldapsam_privates
*ldap_state
, char *dn
, LDAPMod
*attrs
[])
546 int rc
= LDAP_SERVER_DOWN
;
552 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
554 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
557 rc
= ldap_modify_s(ldap_state
->ldap_struct
, dn
, attrs
);
560 if (rc
== LDAP_SERVER_DOWN
) {
561 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
562 ldapsam_close(ldap_state
);
568 static int ldapsam_add(struct ldapsam_privates
*ldap_state
, const char *dn
, LDAPMod
*attrs
[])
570 int rc
= LDAP_SERVER_DOWN
;
576 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
578 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
581 rc
= ldap_add_s(ldap_state
->ldap_struct
, dn
, attrs
);
584 if (rc
== LDAP_SERVER_DOWN
) {
585 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
586 ldapsam_close(ldap_state
);
592 static int ldapsam_delete(struct ldapsam_privates
*ldap_state
, char *dn
)
594 int rc
= LDAP_SERVER_DOWN
;
600 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
602 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
605 rc
= ldap_delete_s(ldap_state
->ldap_struct
, dn
);
608 if (rc
== LDAP_SERVER_DOWN
) {
609 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
610 ldapsam_close(ldap_state
);
616 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
)
618 int rc
= LDAP_SERVER_DOWN
;
624 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
626 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
629 rc
= ldap_extended_operation_s(ldap_state
->ldap_struct
, reqoid
, reqdata
, serverctrls
, clientctrls
, retoidp
, retdatap
);
632 if (rc
== LDAP_SERVER_DOWN
) {
633 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
634 ldapsam_close(ldap_state
);
640 /*******************************************************************
641 run the search by name.
642 ******************************************************************/
643 static int ldapsam_search_one_user (struct ldapsam_privates
*ldap_state
, const char *filter
, LDAPMessage
** result
)
645 int scope
= LDAP_SCOPE_SUBTREE
;
648 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter
));
650 rc
= ldapsam_search(ldap_state
, lp_ldap_suffix (), scope
, filter
, attr
, 0, result
);
652 if (rc
!= LDAP_SUCCESS
) {
653 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n",
654 ldap_err2string (rc
)));
655 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
662 /*******************************************************************
663 run the search by name.
664 ******************************************************************/
665 static int ldapsam_search_one_user_by_name (struct ldapsam_privates
*ldap_state
, const char *user
,
666 LDAPMessage
** result
)
669 char *escape_user
= escape_ldap_string_alloc(user
);
672 return LDAP_NO_MEMORY
;
676 * in the filter expression, replace %u with the real name
677 * so in ldap filter, %u MUST exist :-)
679 pstrcpy(filter
, lp_ldap_filter());
682 * have to use this here because $ is filtered out
687 all_string_sub(filter
, "%u", escape_user
, sizeof(pstring
));
688 SAFE_FREE(escape_user
);
690 return ldapsam_search_one_user(ldap_state
, filter
, result
);
693 /*******************************************************************
694 run the search by uid.
695 ******************************************************************/
696 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates
*ldap_state
,
698 LDAPMessage
** result
)
704 /* Get the username from the system and look that up in the LDAP */
706 if ((user
= getpwuid_alloc(uid
)) == NULL
) {
707 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid
));
708 return LDAP_NO_SUCH_OBJECT
;
711 pstrcpy(filter
, lp_ldap_filter());
713 escape_user
= escape_ldap_string_alloc(user
->pw_name
);
716 return LDAP_NO_MEMORY
;
719 all_string_sub(filter
, "%u", escape_user
, sizeof(pstring
));
722 SAFE_FREE(escape_user
);
724 return ldapsam_search_one_user(ldap_state
, filter
, result
);
727 /*******************************************************************
728 run the search by rid.
729 ******************************************************************/
730 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates
*ldap_state
,
732 LDAPMessage
** result
)
737 /* check if the user rid exsists, if not, try searching on the uid */
739 snprintf(filter
, sizeof(filter
) - 1, "rid=%i", rid
);
740 rc
= ldapsam_search_one_user(ldap_state
, filter
, result
);
742 if (rc
!= LDAP_SUCCESS
)
743 rc
= ldapsam_search_one_user_by_uid(ldap_state
,
744 fallback_pdb_user_rid_to_uid(rid
),
750 /*******************************************************************
751 search an attribute and return the first value found.
752 ******************************************************************/
753 static BOOL
get_single_attribute (LDAP
* ldap_struct
, LDAPMessage
* entry
,
754 const char *attribute
, pstring value
)
758 if ((values
= ldap_get_values (ldap_struct
, entry
, attribute
)) == NULL
) {
760 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute
));
765 pstrcpy(value
, values
[0]);
766 ldap_value_free(values
);
767 #ifdef DEBUG_PASSWORDS
768 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute
, value
));
773 /************************************************************************
774 Routine to manage the LDAPMod structure array
775 manage memory used by the array, by each struct, and values
777 ************************************************************************/
778 static void make_a_mod (LDAPMod
*** modlist
, int modop
, const char *attribute
, const char *value
)
786 if (attribute
== NULL
|| *attribute
== '\0')
789 if (value
== NULL
|| *value
== '\0')
794 mods
= (LDAPMod
**) malloc(sizeof(LDAPMod
*));
797 DEBUG(0, ("make_a_mod: out of memory!\n"));
803 for (i
= 0; mods
[i
] != NULL
; ++i
) {
804 if (mods
[i
]->mod_op
== modop
&& !strcasecmp(mods
[i
]->mod_type
, attribute
))
810 mods
= (LDAPMod
**) Realloc (mods
, (i
+ 2) * sizeof (LDAPMod
*));
813 DEBUG(0, ("make_a_mod: out of memory!\n"));
816 mods
[i
] = (LDAPMod
*) malloc(sizeof(LDAPMod
));
819 DEBUG(0, ("make_a_mod: out of memory!\n"));
822 mods
[i
]->mod_op
= modop
;
823 mods
[i
]->mod_values
= NULL
;
824 mods
[i
]->mod_type
= strdup(attribute
);
831 if (mods
[i
]->mod_values
!= NULL
) {
832 for (; mods
[i
]->mod_values
[j
] != NULL
; j
++);
834 mods
[i
]->mod_values
= (char **)Realloc(mods
[i
]->mod_values
,
835 (j
+ 2) * sizeof (char *));
837 if (mods
[i
]->mod_values
== NULL
) {
838 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
841 mods
[i
]->mod_values
[j
] = strdup(value
);
842 mods
[i
]->mod_values
[j
+ 1] = NULL
;
847 /* New Interface is being implemented here */
849 /**********************************************************************
850 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
851 *********************************************************************/
852 static BOOL
get_unix_attributes (struct ldapsam_privates
*ldap_state
,
853 SAM_ACCOUNT
* sampass
,
863 if ((ldap_values
= ldap_get_values (ldap_state
->ldap_struct
, entry
, "objectClass")) == NULL
) {
864 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
868 for (values
=ldap_values
;*values
;values
++) {
869 if (strcasecmp(*values
, "posixAccount") == 0) {
874 if (!*values
) { /*end of array, no posixAccount */
875 DEBUG(10, ("user does not have posixAcccount attributes\n"));
876 ldap_value_free(ldap_values
);
879 ldap_value_free(ldap_values
);
881 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "homeDirectory", homedir
))
884 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "uidNumber", temp
))
887 uid
= (uid_t
)atol(temp
);
889 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "gidNumber", temp
))
892 gid
= (gid_t
)atol(temp
);
894 pdb_set_unix_homedir(sampass
, homedir
, PDB_SET
);
895 pdb_set_uid(sampass
, uid
, PDB_SET
);
896 pdb_set_gid(sampass
, gid
, PDB_SET
);
898 DEBUG(10, ("user has posixAcccount attributes\n"));
903 /**********************************************************************
904 Initialize SAM_ACCOUNT from an LDAP query
905 (Based on init_sam_from_buffer in pdb_tdb.c)
906 *********************************************************************/
907 static BOOL
init_sam_from_ldap (struct ldapsam_privates
*ldap_state
,
908 SAM_ACCOUNT
* sampass
,
915 pass_can_change_time
,
916 pass_must_change_time
;
931 uint8 smblmpwd
[LM_HASH_LEN
],
932 smbntpwd
[NT_HASH_LEN
];
933 uint16 acct_ctrl
= 0,
936 uint8 hours
[MAX_HOURS_LEN
];
939 gid_t gid
= getegid();
943 * do a little initialization
947 nt_username
[0] = '\0';
951 logon_script
[0] = '\0';
952 profile_path
[0] = '\0';
954 munged_dial
[0] = '\0';
955 workstations
[0] = '\0';
958 if (sampass
== NULL
|| ldap_state
== NULL
|| entry
== NULL
) {
959 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
963 if (ldap_state
->ldap_struct
== NULL
) {
964 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
968 get_single_attribute(ldap_state
->ldap_struct
, entry
, "uid", username
);
969 DEBUG(2, ("Entry found for user: %s\n", username
));
971 pstrcpy(nt_username
, username
);
973 pstrcpy(domain
, lp_workgroup());
975 pdb_set_username(sampass
, username
, PDB_SET
);
977 pdb_set_domain(sampass
, domain
, PDB_DEFAULT
);
978 pdb_set_nt_username(sampass
, nt_username
, PDB_SET
);
980 get_single_attribute(ldap_state
->ldap_struct
, entry
, "rid", temp
);
981 user_rid
= (uint32
)atol(temp
);
983 pdb_set_user_sid_from_rid(sampass
, user_rid
, PDB_SET
);
985 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "primaryGroupID", temp
)) {
988 group_rid
= (uint32
)atol(temp
);
989 pdb_set_group_sid_from_rid(sampass
, group_rid
, PDB_SET
);
994 * If so configured, try and get the values from LDAP
997 if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state
, sampass
, entry
))) {
1000 * Otherwise just ask the system getpw() calls.
1003 pw
= getpwnam_alloc(username
);
1005 if (! ldap_state
->permit_non_unix_accounts
) {
1006 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username
));
1011 pdb_set_uid(sampass
, uid
, PDB_SET
);
1013 pdb_set_gid(sampass
, gid
, PDB_SET
);
1015 pdb_set_unix_homedir(sampass
, pw
->pw_dir
, PDB_SET
);
1021 if (group_rid
== 0 && pdb_get_init_flags(sampass
,PDB_GID
) != PDB_DEFAULT
) {
1023 gid
= pdb_get_gid(sampass
);
1024 /* call the mapping code here */
1025 if(pdb_getgrgid(&map
, gid
, MAPPING_WITHOUT_PRIV
)) {
1026 pdb_set_group_sid(sampass
, &map
.sid
, PDB_SET
);
1029 pdb_set_group_sid_from_rid(sampass
, pdb_gid_to_group_rid(gid
), PDB_SET
);
1033 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "pwdLastSet", temp
)) {
1034 /* leave as default */
1036 pass_last_set_time
= (time_t) atol(temp
);
1037 pdb_set_pass_last_set_time(sampass
, pass_last_set_time
, PDB_SET
);
1040 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "logonTime", temp
)) {
1041 /* leave as default */
1043 logon_time
= (time_t) atol(temp
);
1044 pdb_set_logon_time(sampass
, logon_time
, PDB_SET
);
1047 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "logoffTime", temp
)) {
1048 /* leave as default */
1050 logoff_time
= (time_t) atol(temp
);
1051 pdb_set_logoff_time(sampass
, logoff_time
, PDB_SET
);
1054 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "kickoffTime", temp
)) {
1055 /* leave as default */
1057 kickoff_time
= (time_t) atol(temp
);
1058 pdb_set_kickoff_time(sampass
, kickoff_time
, PDB_SET
);
1061 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "pwdCanChange", temp
)) {
1062 /* leave as default */
1064 pass_can_change_time
= (time_t) atol(temp
);
1065 pdb_set_pass_can_change_time(sampass
, pass_can_change_time
, PDB_SET
);
1068 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "pwdMustChange", temp
)) {
1069 /* leave as default */
1071 pass_must_change_time
= (time_t) atol(temp
);
1072 pdb_set_pass_must_change_time(sampass
, pass_must_change_time
, PDB_SET
);
1075 /* recommend that 'gecos' and 'displayName' should refer to the same
1076 * attribute OID. userFullName depreciated, only used by Samba
1077 * primary rules of LDAP: don't make a new attribute when one is already defined
1078 * that fits your needs; using cn then displayName rather than 'userFullName'
1081 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "cn", fullname
)) {
1082 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "displayName", fullname
)) {
1083 /* leave as default */
1085 pdb_set_fullname(sampass
, fullname
, PDB_SET
);
1088 pdb_set_fullname(sampass
, fullname
, PDB_SET
);
1091 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "homeDrive", dir_drive
)) {
1092 pdb_set_dir_drive(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
1098 pdb_set_dir_drive(sampass
, dir_drive
, PDB_SET
);
1101 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "smbHome", homedir
)) {
1102 pdb_set_homedir(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
1108 pdb_set_homedir(sampass
, homedir
, PDB_SET
);
1111 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "scriptPath", logon_script
)) {
1112 pdb_set_logon_script(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
1118 pdb_set_logon_script(sampass
, logon_script
, PDB_SET
);
1121 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "profilePath", profile_path
)) {
1122 pdb_set_profile_path(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
1128 pdb_set_profile_path(sampass
, profile_path
, PDB_SET
);
1131 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "description", acct_desc
)) {
1132 /* leave as default */
1134 pdb_set_acct_desc(sampass
, acct_desc
, PDB_SET
);
1137 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "userWorkstations", workstations
)) {
1138 /* leave as default */;
1140 pdb_set_workstations(sampass
, workstations
, PDB_SET
);
1143 /* FIXME: hours stuff should be cleaner */
1147 memset(hours
, 0xff, hours_len
);
1149 if (!get_single_attribute (ldap_state
->ldap_struct
, entry
, "lmPassword", temp
)) {
1150 /* leave as default */
1152 pdb_gethexpwd(temp
, smblmpwd
);
1153 memset((char *)temp
, '\0', strlen(temp
)+1);
1154 if (!pdb_set_lanman_passwd(sampass
, smblmpwd
, PDB_SET
))
1156 ZERO_STRUCT(smblmpwd
);
1159 if (!get_single_attribute (ldap_state
->ldap_struct
, entry
, "ntPassword", temp
)) {
1160 /* leave as default */
1162 pdb_gethexpwd(temp
, smbntpwd
);
1163 memset((char *)temp
, '\0', strlen(temp
)+1);
1164 if (!pdb_set_nt_passwd(sampass
, smbntpwd
, PDB_SET
))
1166 ZERO_STRUCT(smbntpwd
);
1169 if (!get_single_attribute (ldap_state
->ldap_struct
, entry
, "acctFlags", temp
)) {
1170 acct_ctrl
|= ACB_NORMAL
;
1172 acct_ctrl
= pdb_decode_acct_ctrl(temp
);
1175 acct_ctrl
|= ACB_NORMAL
;
1177 pdb_set_acct_ctrl(sampass
, acct_ctrl
, PDB_SET
);
1180 pdb_set_hours_len(sampass
, hours_len
, PDB_SET
);
1181 pdb_set_logon_divs(sampass
, logon_divs
, PDB_SET
);
1183 pdb_set_munged_dial(sampass
, munged_dial
, PDB_SET
);
1185 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1186 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1187 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1189 pdb_set_hours(sampass
, hours
, PDB_SET
);
1194 static BOOL
need_ldap_mod(BOOL pdb_add
, const SAM_ACCOUNT
* sampass
, enum pdb_elements element
) {
1196 return (!IS_SAM_DEFAULT(sampass
, element
));
1198 return IS_SAM_CHANGED(sampass
, element
);
1202 /**********************************************************************
1203 Initialize SAM_ACCOUNT from an LDAP query
1204 (Based on init_buffer_from_sam in pdb_tdb.c)
1205 *********************************************************************/
1206 static BOOL
init_ldap_from_sam (struct ldapsam_privates
*ldap_state
,
1207 LDAPMod
*** mods
, int ldap_op
,
1209 const SAM_ACCOUNT
* sampass
)
1214 if (mods
== NULL
|| sampass
== NULL
) {
1215 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1222 * took out adding "objectclass: sambaAccount"
1223 * do this on a per-mod basis
1225 if (need_ldap_mod(pdb_add
, sampass
, PDB_USERNAME
)) {
1226 make_a_mod(mods
, ldap_op
, "uid", pdb_get_username(sampass
));
1227 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass
)));
1230 if ((rid
= pdb_get_user_rid(sampass
))!=0 ) {
1231 if (need_ldap_mod(pdb_add
, sampass
, PDB_USERSID
)) {
1232 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
1233 make_a_mod(mods
, ldap_op
, "rid", temp
);
1235 } else if (!IS_SAM_DEFAULT(sampass
, PDB_UID
)) {
1236 rid
= fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass
));
1237 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
1238 make_a_mod(mods
, ldap_op
, "rid", temp
);
1239 } else if (ldap_state
->permit_non_unix_accounts
) {
1240 rid
= ldapsam_get_next_available_nua_rid(ldap_state
);
1242 DEBUG(0, ("NO user RID specified on account %s, and findining next available NUA RID failed, cannot store!\n", pdb_get_username(sampass
)));
1245 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
1246 make_a_mod(mods
, ldap_op
, "rid", temp
);
1248 DEBUG(0, ("NO user RID specified on account %s, cannot store!\n", pdb_get_username(sampass
)));
1254 if ((rid
= pdb_get_group_rid(sampass
))!=0 ) {
1255 if (need_ldap_mod(pdb_add
, sampass
, PDB_GROUPSID
)) {
1256 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
1257 make_a_mod(mods
, ldap_op
, "primaryGroupID", temp
);
1259 } else if (!IS_SAM_DEFAULT(sampass
, PDB_GID
)) {
1260 rid
= pdb_gid_to_group_rid(pdb_get_gid(sampass
));
1261 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
1262 make_a_mod(mods
, ldap_op
, "primaryGroupID", temp
);
1263 } else if (ldap_state
->permit_non_unix_accounts
) {
1264 rid
= DOMAIN_GROUP_RID_USERS
;
1265 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
1266 make_a_mod(mods
, ldap_op
, "primaryGroupID", temp
);
1268 DEBUG(0, ("NO group RID specified on account %s, cannot store!\n", pdb_get_username(sampass
)));
1273 /* displayName, cn, and gecos should all be the same
1274 * most easily accomplished by giving them the same OID
1275 * gecos isn't set here b/c it should be handled by the
1278 if (need_ldap_mod(pdb_add
, sampass
, PDB_FULLNAME
)) {
1279 make_a_mod(mods
, ldap_op
, "displayName", pdb_get_fullname(sampass
));
1280 make_a_mod(mods
, ldap_op
, "cn", pdb_get_fullname(sampass
));
1282 if (need_ldap_mod(pdb_add
, sampass
, PDB_ACCTDESC
)) {
1283 make_a_mod(mods
, ldap_op
, "description", pdb_get_acct_desc(sampass
));
1285 if (need_ldap_mod(pdb_add
, sampass
, PDB_WORKSTATIONS
)) {
1286 make_a_mod(mods
, ldap_op
, "userWorkstations", pdb_get_workstations(sampass
));
1289 * Only updates fields which have been set (not defaults from smb.conf)
1292 if (need_ldap_mod(pdb_add
, sampass
, PDB_SMBHOME
)) {
1293 make_a_mod(mods
, ldap_op
, "smbHome", pdb_get_homedir(sampass
));
1296 if (need_ldap_mod(pdb_add
, sampass
, PDB_DRIVE
)) {
1297 make_a_mod(mods
, ldap_op
, "homeDrive", pdb_get_dir_drive(sampass
));
1300 if (need_ldap_mod(pdb_add
, sampass
, PDB_LOGONSCRIPT
)) {
1301 make_a_mod(mods
, ldap_op
, "scriptPath", pdb_get_logon_script(sampass
));
1304 if (need_ldap_mod(pdb_add
, sampass
, PDB_PROFILE
))
1305 make_a_mod(mods
, ldap_op
, "profilePath", pdb_get_profile_path(sampass
));
1307 if (need_ldap_mod(pdb_add
, sampass
, PDB_LOGONTIME
)) {
1308 slprintf(temp
, sizeof(temp
) - 1, "%li", pdb_get_logon_time(sampass
));
1309 make_a_mod(mods
, ldap_op
, "logonTime", temp
);
1312 if (need_ldap_mod(pdb_add
, sampass
, PDB_LOGOFFTIME
)) {
1313 slprintf(temp
, sizeof(temp
) - 1, "%li", pdb_get_logoff_time(sampass
));
1314 make_a_mod(mods
, ldap_op
, "logoffTime", temp
);
1317 if (need_ldap_mod(pdb_add
, sampass
, PDB_KICKOFFTIME
)) {
1318 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_kickoff_time(sampass
));
1319 make_a_mod(mods
, ldap_op
, "kickoffTime", temp
);
1323 if (need_ldap_mod(pdb_add
, sampass
, PDB_CANCHANGETIME
)) {
1324 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_can_change_time(sampass
));
1325 make_a_mod(mods
, ldap_op
, "pwdCanChange", temp
);
1328 if (need_ldap_mod(pdb_add
, sampass
, PDB_MUSTCHANGETIME
)) {
1329 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_must_change_time(sampass
));
1330 make_a_mod(mods
, ldap_op
, "pwdMustChange", temp
);
1333 if ((pdb_get_acct_ctrl(sampass
)&(ACB_WSTRUST
|ACB_SVRTRUST
|ACB_DOMTRUST
))||
1334 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY
)) {
1336 if (need_ldap_mod(pdb_add
, sampass
, PDB_LMPASSWD
)) {
1337 pdb_sethexpwd (temp
, pdb_get_lanman_passwd(sampass
), pdb_get_acct_ctrl(sampass
));
1338 make_a_mod (mods
, ldap_op
, "lmPassword", temp
);
1341 if (need_ldap_mod(pdb_add
, sampass
, PDB_NTPASSWD
)) {
1342 pdb_sethexpwd (temp
, pdb_get_nt_passwd(sampass
), pdb_get_acct_ctrl(sampass
));
1343 make_a_mod (mods
, ldap_op
, "ntPassword", temp
);
1346 if (need_ldap_mod(pdb_add
, sampass
, PDB_PASSLASTSET
)) {
1347 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_last_set_time(sampass
));
1348 make_a_mod(mods
, ldap_op
, "pwdLastSet", temp
);
1352 /* FIXME: Hours stuff goes in LDAP */
1353 if (need_ldap_mod(pdb_add
, sampass
, PDB_ACCTCTRL
)) {
1354 make_a_mod (mods
, ldap_op
, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass
),
1355 NEW_PW_FORMAT_SPACE_PADDED_LEN
));
1362 /**********************************************************************
1363 Connect to LDAP server and find the next available RID.
1364 *********************************************************************/
1365 static uint32
check_nua_rid_is_avail(struct ldapsam_privates
*ldap_state
, uint32 top_rid
)
1367 LDAPMessage
*result
;
1368 uint32 final_rid
= (top_rid
& (~USER_RID_TYPE
)) + RID_MULTIPLIER
;
1373 if (final_rid
< ldap_state
->low_nua_rid
|| final_rid
> ldap_state
->high_nua_rid
) {
1377 if (ldapsam_search_one_user_by_rid(ldap_state
, final_rid
, &result
) != LDAP_SUCCESS
) {
1378 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid
, final_rid
));
1382 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) != 0) {
1383 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid
, final_rid
));
1384 ldap_msgfree(result
);
1388 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid
, final_rid
));
1389 ldap_msgfree(result
);
1393 /**********************************************************************
1394 Extract the RID from an LDAP entry
1395 *********************************************************************/
1396 static uint32
entry_to_user_rid(struct ldapsam_privates
*ldap_state
, LDAPMessage
*entry
) {
1398 SAM_ACCOUNT
*user
= NULL
;
1399 if (!NT_STATUS_IS_OK(pdb_init_sam(&user
))) {
1403 if (init_sam_from_ldap(ldap_state
, user
, entry
)) {
1404 rid
= pdb_get_user_rid(user
);
1408 pdb_free_sam(&user
);
1409 if (rid
>= ldap_state
->low_nua_rid
&& rid
<= ldap_state
->high_nua_rid
) {
1416 /**********************************************************************
1417 Connect to LDAP server and find the next available RID.
1418 *********************************************************************/
1419 static uint32
search_top_nua_rid(struct ldapsam_privates
*ldap_state
)
1423 LDAPMessage
*result
;
1425 char *final_filter
= NULL
;
1430 pstrcpy(filter
, lp_ldap_filter());
1431 all_string_sub(filter
, "%u", "*", sizeof(pstring
));
1434 asprintf(&final_filter
, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter
, ldap_state
->low_nua_rid
, ldap_state
->high_nua_rid
);
1436 final_filter
= strdup(filter
);
1438 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter
));
1440 rc
= ldapsam_search(ldap_state
, lp_ldap_suffix(),
1441 LDAP_SCOPE_SUBTREE
, final_filter
, attr
, 0,
1444 if (rc
!= LDAP_SUCCESS
) {
1445 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc
)));
1446 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter
));
1453 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1454 DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count
));
1457 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc
)));
1458 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter
));
1460 ldap_msgfree(result
);
1462 return ldap_state
->low_nua_rid
;
1466 entry
= ldap_first_entry(ldap_state
->ldap_struct
,result
);
1468 top_rid
= entry_to_user_rid(ldap_state
, entry
);
1470 while ((entry
= ldap_next_entry(ldap_state
->ldap_struct
, entry
))) {
1472 rid
= entry_to_user_rid(ldap_state
, entry
);
1473 if (rid
> top_rid
) {
1478 ldap_msgfree(result
);
1480 if (top_rid
< ldap_state
->low_nua_rid
)
1481 top_rid
= ldap_state
->low_nua_rid
;
1486 /**********************************************************************
1487 Connect to LDAP server and find the next available RID.
1488 *********************************************************************/
1489 static uint32
ldapsam_get_next_available_nua_rid(struct ldapsam_privates
*ldap_state
) {
1490 uint32 next_nua_rid
;
1493 top_nua_rid
= search_top_nua_rid(ldap_state
);
1495 next_nua_rid
= check_nua_rid_is_avail(ldap_state
,
1498 return next_nua_rid
;
1501 /**********************************************************************
1502 Connect to LDAP server for password enumeration
1503 *********************************************************************/
1504 static NTSTATUS
ldapsam_setsampwent(struct pdb_methods
*my_methods
, BOOL update
)
1506 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
1510 pstrcpy(filter
, lp_ldap_filter());
1511 all_string_sub(filter
, "%u", "*", sizeof(pstring
));
1513 rc
= ldapsam_search(ldap_state
, lp_ldap_suffix(),
1514 LDAP_SCOPE_SUBTREE
, filter
, attr
, 0,
1515 &ldap_state
->result
);
1517 if (rc
!= LDAP_SUCCESS
) {
1518 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc
)));
1519 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
1520 ldap_msgfree(ldap_state
->result
);
1521 ldap_state
->result
= NULL
;
1522 return NT_STATUS_UNSUCCESSFUL
;
1525 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1526 ldap_count_entries(ldap_state
->ldap_struct
,
1527 ldap_state
->result
)));
1529 ldap_state
->entry
= ldap_first_entry(ldap_state
->ldap_struct
,
1530 ldap_state
->result
);
1531 ldap_state
->index
= 0;
1533 return NT_STATUS_OK
;
1536 /**********************************************************************
1537 End enumeration of the LDAP password list
1538 *********************************************************************/
1539 static void ldapsam_endsampwent(struct pdb_methods
*my_methods
)
1541 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
1542 if (ldap_state
->result
) {
1543 ldap_msgfree(ldap_state
->result
);
1544 ldap_state
->result
= NULL
;
1548 /**********************************************************************
1549 Get the next entry in the LDAP password database
1550 *********************************************************************/
1551 static NTSTATUS
ldapsam_getsampwent(struct pdb_methods
*my_methods
, SAM_ACCOUNT
*user
)
1553 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1554 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
1557 /* The rebind proc needs this *HACK*. We are not multithreaded, so
1558 this will work, but it's not nice. */
1559 static_ldap_state
= ldap_state
;
1562 if (!ldap_state
->entry
)
1565 ldap_state
->index
++;
1566 bret
= init_sam_from_ldap(ldap_state
, user
, ldap_state
->entry
);
1568 ldap_state
->entry
= ldap_next_entry(ldap_state
->ldap_struct
,
1572 return NT_STATUS_OK
;
1575 /**********************************************************************
1576 Get SAM_ACCOUNT entry from LDAP by username
1577 *********************************************************************/
1578 static NTSTATUS
ldapsam_getsampwnam(struct pdb_methods
*my_methods
, SAM_ACCOUNT
*user
, const char *sname
)
1580 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1581 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
1582 LDAPMessage
*result
;
1586 if (ldapsam_search_one_user_by_name(ldap_state
, sname
, &result
) != LDAP_SUCCESS
) {
1587 return NT_STATUS_NO_SUCH_USER
;
1590 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1594 ("We don't find this user [%s] count=%d\n", sname
,
1596 return NT_STATUS_NO_SUCH_USER
;
1597 } else if (count
> 1) {
1599 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname
,
1601 return NT_STATUS_NO_SUCH_USER
;
1604 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1606 if (!init_sam_from_ldap(ldap_state
, user
, entry
)) {
1607 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname
));
1608 ldap_msgfree(result
);
1609 return NT_STATUS_NO_SUCH_USER
;
1611 ldap_msgfree(result
);
1614 ldap_msgfree(result
);
1619 /**********************************************************************
1620 Get SAM_ACCOUNT entry from LDAP by rid
1621 *********************************************************************/
1622 static NTSTATUS
ldapsam_getsampwrid(struct pdb_methods
*my_methods
, SAM_ACCOUNT
*user
, uint32 rid
)
1624 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1625 struct ldapsam_privates
*ldap_state
=
1626 (struct ldapsam_privates
*)my_methods
->private_data
;
1627 LDAPMessage
*result
;
1631 if (ldapsam_search_one_user_by_rid(ldap_state
, rid
, &result
) != LDAP_SUCCESS
) {
1632 return NT_STATUS_NO_SUCH_USER
;
1635 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1639 ("We don't find this rid [%i] count=%d\n", rid
,
1641 return NT_STATUS_NO_SUCH_USER
;
1642 } else if (count
> 1) {
1644 ("More than one user with rid [%i]. Failing. count=%d\n", rid
,
1646 return NT_STATUS_NO_SUCH_USER
;
1649 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1651 if (!init_sam_from_ldap(ldap_state
, user
, entry
)) {
1652 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1653 ldap_msgfree(result
);
1654 return NT_STATUS_NO_SUCH_USER
;
1656 ldap_msgfree(result
);
1659 ldap_msgfree(result
);
1664 static NTSTATUS
ldapsam_getsampwsid(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* user
, const DOM_SID
*sid
)
1667 if (!sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
))
1668 return NT_STATUS_NO_SUCH_USER
;
1669 return ldapsam_getsampwrid(my_methods
, user
, rid
);
1672 /********************************************************************
1673 Do the actual modification - also change a plaittext passord if
1675 **********************************************************************/
1677 static NTSTATUS
ldapsam_modify_entry(struct pdb_methods
*my_methods
,
1678 SAM_ACCOUNT
*newpwd
, char *dn
,
1679 LDAPMod
**mods
, int ldap_op
, BOOL pdb_add
)
1681 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
1684 if (!my_methods
|| !newpwd
|| !dn
) {
1685 return NT_STATUS_INVALID_PARAMETER
;
1689 DEBUG(5,("mods is empty: nothing to modify\n"));
1690 /* may be password change below however */
1695 make_a_mod(&mods
, LDAP_MOD_ADD
, "objectclass", "account");
1696 rc
= ldapsam_add(ldap_state
, dn
, mods
);
1698 case LDAP_MOD_REPLACE
:
1699 rc
= ldapsam_modify(ldap_state
, dn
,mods
);
1702 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op
));
1703 return NT_STATUS_UNSUCCESSFUL
;
1706 if (rc
!=LDAP_SUCCESS
) {
1708 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
1711 ("failed to %s user dn= %s with: %s\n\t%s\n",
1712 ldap_op
== LDAP_MOD_ADD
? "add" : "modify",
1713 dn
, ldap_err2string(rc
),
1716 return NT_STATUS_UNSUCCESSFUL
;
1720 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1721 if (!(pdb_get_acct_ctrl(newpwd
)&(ACB_WSTRUST
|ACB_SVRTRUST
|ACB_DOMTRUST
))&&
1722 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF
)&&
1723 need_ldap_mod(pdb_add
, newpwd
, PDB_PLAINTEXT_PW
)&&
1724 (pdb_get_plaintext_passwd(newpwd
)!=NULL
)) {
1728 struct berval
*retdata
;
1730 if ((ber
= ber_alloc_t(LBER_USE_DER
))==NULL
) {
1731 DEBUG(0,("ber_alloc_t returns NULL\n"));
1732 return NT_STATUS_UNSUCCESSFUL
;
1734 ber_printf (ber
, "{");
1735 ber_printf (ber
, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID
,dn
);
1736 ber_printf (ber
, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW
, pdb_get_plaintext_passwd(newpwd
));
1737 ber_printf (ber
, "N}");
1739 if ((rc
= ber_flatten (ber
, &bv
))<0) {
1740 DEBUG(0,("ber_flatten returns a value <0\n"));
1741 return NT_STATUS_UNSUCCESSFUL
;
1746 if ((rc
= ldapsam_extended_operation(ldap_state
, LDAP_EXOP_X_MODIFY_PASSWD
,
1747 bv
, NULL
, NULL
, &retoid
, &retdata
))!=LDAP_SUCCESS
) {
1748 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1749 pdb_get_username(newpwd
),ldap_err2string(rc
)));
1751 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd
)));
1753 ber_bvfree(retdata
);
1754 ber_memfree(retoid
);
1759 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
1760 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
1761 return NT_STATUS_OK
;
1764 /**********************************************************************
1765 Delete entry from LDAP for username
1766 *********************************************************************/
1767 static NTSTATUS
ldapsam_delete_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* sam_acct
)
1769 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
1774 LDAPMessage
*result
;
1777 DEBUG(0, ("sam_acct was NULL!\n"));
1778 return NT_STATUS_INVALID_PARAMETER
;
1781 sname
= pdb_get_username(sam_acct
);
1783 DEBUG (3, ("Deleting user %s from LDAP.\n", sname
));
1785 rc
= ldapsam_search_one_user_by_name(ldap_state
, sname
, &result
);
1786 if (rc
!= LDAP_SUCCESS
) {
1787 return NT_STATUS_NO_SUCH_USER
;
1790 if (ldap_count_entries (ldap_state
->ldap_struct
, result
) == 0) {
1791 DEBUG (0, ("User doesn't exit!\n"));
1792 ldap_msgfree (result
);
1793 return NT_STATUS_NO_SUCH_USER
;
1796 entry
= ldap_first_entry (ldap_state
->ldap_struct
, result
);
1797 dn
= ldap_get_dn (ldap_state
->ldap_struct
, entry
);
1798 ldap_msgfree(result
);
1800 rc
= ldapsam_delete(ldap_state
, dn
);
1803 if (rc
!= LDAP_SUCCESS
) {
1805 ldap_get_option (ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
1806 DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n",
1807 sname
, ldap_err2string (rc
), ld_error
));
1809 return NT_STATUS_CANNOT_DELETE
;
1812 DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname
));
1813 return NT_STATUS_OK
;
1816 /**********************************************************************
1818 *********************************************************************/
1819 static NTSTATUS
ldapsam_update_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* newpwd
)
1821 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1822 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
1825 LDAPMessage
*result
;
1829 if (!init_ldap_from_sam(ldap_state
, &mods
, LDAP_MOD_REPLACE
, False
, newpwd
)) {
1830 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1831 return NT_STATUS_UNSUCCESSFUL
;
1835 DEBUG(4,("mods is empty: nothing to update for user: %s\n",pdb_get_username(newpwd
)));
1836 return NT_STATUS_OK
;
1839 rc
= ldapsam_search_one_user_by_name(ldap_state
, pdb_get_username(newpwd
), &result
);
1840 if (rc
!= LDAP_SUCCESS
) {
1841 ldap_mods_free(mods
, 1);
1842 return NT_STATUS_UNSUCCESSFUL
;
1845 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) == 0) {
1846 DEBUG(0, ("No user to modify!\n"));
1847 ldap_msgfree(result
);
1848 ldap_mods_free(mods
, 1);
1849 return NT_STATUS_UNSUCCESSFUL
;
1852 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1853 dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
1854 ldap_msgfree(result
);
1856 ret
= ldapsam_modify_entry(my_methods
,newpwd
,dn
,mods
,LDAP_MOD_REPLACE
, False
);
1857 if (NT_STATUS_IS_ERR(ret
)) {
1858 DEBUG(0,("failed to modify user with uid = %s\n",
1859 pdb_get_username(newpwd
)));
1860 ldap_mods_free(mods
,1);
1866 ("successfully modified uid = %s in the LDAP database\n",
1867 pdb_get_username(newpwd
)));
1868 ldap_mods_free(mods
, 1);
1869 return NT_STATUS_OK
;
1872 /**********************************************************************
1873 Add SAM_ACCOUNT to LDAP
1874 *********************************************************************/
1875 static NTSTATUS
ldapsam_add_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* newpwd
)
1877 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1878 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
1881 LDAPMessage
*result
= NULL
;
1883 LDAPMod
**mods
= NULL
;
1887 const char *username
= pdb_get_username(newpwd
);
1888 if (!username
|| !*username
) {
1889 DEBUG(0, ("Cannot add user without a username!\n"));
1890 return NT_STATUS_INVALID_PARAMETER
;
1893 rc
= ldapsam_search_one_user_by_name (ldap_state
, username
, &result
);
1894 if (rc
!= LDAP_SUCCESS
) {
1895 return NT_STATUS_UNSUCCESSFUL
;
1898 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) != 0) {
1899 DEBUG(0,("User '%s' already in the base, with samba properties\n",
1901 ldap_msgfree(result
);
1902 return NT_STATUS_UNSUCCESSFUL
;
1904 ldap_msgfree(result
);
1906 slprintf (filter
, sizeof (filter
) - 1, "uid=%s", username
);
1907 rc
= ldapsam_search_one_user(ldap_state
, filter
, &result
);
1908 if (rc
!= LDAP_SUCCESS
) {
1909 return NT_STATUS_UNSUCCESSFUL
;
1912 num_result
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1914 if (num_result
> 1) {
1915 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1916 ldap_msgfree(result
);
1917 return NT_STATUS_UNSUCCESSFUL
;
1920 /* Check if we need to update an existing entry */
1921 if (num_result
== 1) {
1925 DEBUG(3,("User exists without samba properties: adding them\n"));
1926 ldap_op
= LDAP_MOD_REPLACE
;
1927 entry
= ldap_first_entry (ldap_state
->ldap_struct
, result
);
1928 tmp
= ldap_get_dn (ldap_state
->ldap_struct
, entry
);
1929 slprintf (dn
, sizeof (dn
) - 1, "%s", tmp
);
1932 /* Check if we need to add an entry */
1933 DEBUG(3,("Adding new user\n"));
1934 ldap_op
= LDAP_MOD_ADD
;
1935 if (username
[strlen(username
)-1] == '$') {
1936 slprintf (dn
, sizeof (dn
) - 1, "uid=%s,%s", username
, lp_ldap_machine_suffix ());
1938 slprintf (dn
, sizeof (dn
) - 1, "uid=%s,%s", username
, lp_ldap_user_suffix ());
1942 ldap_msgfree(result
);
1944 if (!init_ldap_from_sam(ldap_state
, &mods
, ldap_op
, True
, newpwd
)) {
1945 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1946 ldap_mods_free(mods
, 1);
1947 return NT_STATUS_UNSUCCESSFUL
;
1951 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd
)));
1952 return NT_STATUS_UNSUCCESSFUL
;
1955 make_a_mod(&mods
, LDAP_MOD_ADD
, "objectclass", "sambaAccount");
1957 ret
= ldapsam_modify_entry(my_methods
,newpwd
,dn
,mods
,ldap_op
, True
);
1958 if (NT_STATUS_IS_ERR(ret
)) {
1959 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
1960 pdb_get_username(newpwd
),dn
));
1961 ldap_mods_free(mods
,1);
1965 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd
)));
1966 ldap_mods_free(mods
, 1);
1967 return NT_STATUS_OK
;
1970 static void free_private_data(void **vp
)
1972 struct ldapsam_privates
**ldap_state
= (struct ldapsam_privates
**)vp
;
1974 ldapsam_close(*ldap_state
);
1976 if ((*ldap_state
)->bind_secret
) {
1977 memset((*ldap_state
)->bind_secret
, '\0', strlen((*ldap_state
)->bind_secret
));
1980 ldapsam_close(*ldap_state
);
1982 SAFE_FREE((*ldap_state
)->bind_dn
);
1983 SAFE_FREE((*ldap_state
)->bind_secret
);
1987 /* No need to free any further, as it is talloc()ed */
1990 NTSTATUS
pdb_init_ldapsam(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
, const char *location
)
1993 struct ldapsam_privates
*ldap_state
;
1995 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_methods(pdb_context
->mem_ctx
, pdb_method
))) {
1999 (*pdb_method
)->name
= "ldapsam";
2001 (*pdb_method
)->setsampwent
= ldapsam_setsampwent
;
2002 (*pdb_method
)->endsampwent
= ldapsam_endsampwent
;
2003 (*pdb_method
)->getsampwent
= ldapsam_getsampwent
;
2004 (*pdb_method
)->getsampwnam
= ldapsam_getsampwnam
;
2005 (*pdb_method
)->getsampwsid
= ldapsam_getsampwsid
;
2006 (*pdb_method
)->add_sam_account
= ldapsam_add_sam_account
;
2007 (*pdb_method
)->update_sam_account
= ldapsam_update_sam_account
;
2008 (*pdb_method
)->delete_sam_account
= ldapsam_delete_sam_account
;
2010 /* TODO: Setup private data and free */
2012 ldap_state
= talloc_zero(pdb_context
->mem_ctx
, sizeof(struct ldapsam_privates
));
2015 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2016 return NT_STATUS_NO_MEMORY
;
2020 ldap_state
->uri
= talloc_strdup(pdb_context
->mem_ctx
, location
);
2021 #ifdef WITH_LDAP_SAMCONFIG
2023 int ldap_port
= lp_ldap_port();
2025 /* remap default port if not using SSL (ie clear or TLS) */
2026 if ( (lp_ldap_ssl() != LDAP_SSL_ON
) && (ldap_port
== 636) ) {
2030 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
);
2031 if (!ldap_state
->uri
) {
2032 return NT_STATUS_NO_MEMORY
;
2036 ldap_state
->uri
= "ldap://localhost";
2040 (*pdb_method
)->private_data
= ldap_state
;
2042 (*pdb_method
)->free_private_data
= free_private_data
;
2044 return NT_STATUS_OK
;
2047 NTSTATUS
pdb_init_ldapsam_nua(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
, const char *location
)
2050 struct ldapsam_privates
*ldap_state
;
2051 uint32 low_nua_uid
, high_nua_uid
;
2053 if (!NT_STATUS_IS_OK(nt_status
= pdb_init_ldapsam(pdb_context
, pdb_method
, location
))) {
2057 (*pdb_method
)->name
= "ldapsam_nua";
2059 ldap_state
= (*pdb_method
)->private_data
;
2061 ldap_state
->permit_non_unix_accounts
= True
;
2063 if (!lp_non_unix_account_range(&low_nua_uid
, &high_nua_uid
)) {
2064 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
2065 return NT_STATUS_UNSUCCESSFUL
;
2068 ldap_state
->low_nua_rid
=fallback_pdb_uid_to_user_rid(low_nua_uid
);
2070 ldap_state
->high_nua_rid
=fallback_pdb_uid_to_user_rid(high_nua_uid
);
2072 return NT_STATUS_OK
;
2078 NTSTATUS
pdb_init_ldapsam(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
, const char *location
)
2080 DEBUG(0, ("ldap not detected at configure time, ldapsam not availalble!\n"));
2081 return NT_STATUS_UNSUCCESSFUL
;
2084 NTSTATUS
pdb_init_ldapsam_nua(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
, const char *location
)
2086 DEBUG(0, ("ldap not dectected at configure time, ldapsam_nua not available!\n"));
2087 return NT_STATUS_UNSUCCESSFUL
;