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.
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
49 #define DBGC_CLASS DBGC_PASSDB
54 #ifndef LDAP_OPT_SUCCESS
55 #define LDAP_OPT_SUCCESS 0
58 #if defined(LDAP_EXOP_X_MODIFY_PASSWD) && !defined(LDAP_EXOP_MODIFY_PASSWD)
59 #define LDAP_EXOP_MODIFY_PASSWD LDAP_EXOP_X_MODIFY_PASSWD
60 #elif !defined(LDAP_EXOP_MODIFY_PASSWD)
61 #define "1.3.6.1.4.1.4203.1.11.1"
64 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_ID) && !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
65 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID LDAP_EXOP_X_MODIFY_PASSWD_ID
66 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
67 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID ((ber_tag_t) 0x80U)
70 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_NEW) && !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
71 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW LDAP_EXOP_X_MODIFY_PASSWD_NEW
72 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
73 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U)
77 #define SAM_ACCOUNT struct sam_passwd
82 struct ldapsam_privates
{
90 /* retrive-once info */
92 const char *domain_name
;
95 /* configuration items */
98 BOOL permit_non_unix_accounts
;
100 uint32 low_allocated_user_rid
;
101 uint32 high_allocated_user_rid
;
103 uint32 low_allocated_group_rid
;
104 uint32 high_allocated_group_rid
;
109 unsigned int num_failures
;
112 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
114 static struct ldapsam_privates
*static_ldap_state
;
117 /**********************************************************************
118 get the attribute name given a user schame version
119 **********************************************************************/
121 static const char* get_userattr_key2string( int schema_ver
, int key
)
123 switch ( schema_ver
)
125 case SCHEMAVER_SAMBAACCOUNT
:
126 return get_attr_key2string( attrib_map_v22
, key
);
128 case SCHEMAVER_SAMBASAMACCOUNT
:
129 return get_attr_key2string( attrib_map_v30
, key
);
132 DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
138 /**********************************************************************
139 return the list of attribute names given a user schema version
140 **********************************************************************/
142 static char** get_userattr_list( int schema_ver
)
144 switch ( schema_ver
)
146 case SCHEMAVER_SAMBAACCOUNT
:
147 return get_attr_list( attrib_map_v22
);
149 case SCHEMAVER_SAMBASAMACCOUNT
:
150 return get_attr_list( attrib_map_v30
);
152 DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
159 /*******************************************************************
160 open a connection to the ldap server.
161 ******************************************************************/
162 static int ldapsam_open_connection (struct ldapsam_privates
*ldap_state
, LDAP
** ldap_struct
)
164 int rc
= LDAP_SUCCESS
;
166 BOOL ldap_v3
= False
;
168 #ifdef HAVE_LDAP_INITIALIZE
169 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state
->uri
));
171 if ((rc
= ldap_initialize(ldap_struct
, ldap_state
->uri
)) != LDAP_SUCCESS
) {
172 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc
)));
178 /* Parse the string manually */
184 const char *p
= ldap_state
->uri
;
185 SMB_ASSERT(sizeof(protocol
)>10 && sizeof(host
)>254);
187 /* skip leading "URL:" (if any) */
188 if ( strncasecmp( p
, "URL:", 4 ) == 0 ) {
192 sscanf(p
, "%10[^:]://%254s[^:]:%d", protocol
, host
, &port
);
195 if (strequal(protocol
, "ldap")) {
197 } else if (strequal(protocol
, "ldaps")) {
200 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol
));
204 if ((*ldap_struct
= ldap_init(host
, port
)) == NULL
) {
205 DEBUG(0, ("ldap_init failed !\n"));
206 return LDAP_OPERATIONS_ERROR
;
209 if (strequal(protocol
, "ldaps")) {
210 #ifdef LDAP_OPT_X_TLS
211 int tls
= LDAP_OPT_X_TLS_HARD
;
212 if (ldap_set_option (*ldap_struct
, LDAP_OPT_X_TLS
, &tls
) != LDAP_SUCCESS
)
214 DEBUG(0, ("Failed to setup a TLS session\n"));
217 DEBUG(3,("LDAPS option set...!\n"));
219 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
220 return LDAP_OPERATIONS_ERROR
;
226 if (ldap_get_option(*ldap_struct
, LDAP_OPT_PROTOCOL_VERSION
, &version
) == LDAP_OPT_SUCCESS
)
228 if (version
!= LDAP_VERSION3
)
230 version
= LDAP_VERSION3
;
231 if (ldap_set_option (*ldap_struct
, LDAP_OPT_PROTOCOL_VERSION
, &version
) == LDAP_OPT_SUCCESS
) {
239 if (lp_ldap_ssl() == LDAP_SSL_START_TLS
) {
240 #ifdef LDAP_OPT_X_TLS
242 if ((rc
= ldap_start_tls_s (*ldap_struct
, NULL
, NULL
)) != LDAP_SUCCESS
)
244 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
245 ldap_err2string(rc
)));
248 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
251 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
252 return LDAP_OPERATIONS_ERROR
;
255 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
256 return LDAP_OPERATIONS_ERROR
;
260 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
265 /*******************************************************************
266 a rebind function for authenticated referrals
267 This version takes a void* that we can shove useful stuff in :-)
268 ******************************************************************/
269 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
271 static int rebindproc_with_state (LDAP
* ld
, char **whop
, char **credp
,
272 int *methodp
, int freeit
, void *arg
)
274 struct ldapsam_privates
*ldap_state
= arg
;
276 /** @TODO Should we be doing something to check what servers we rebind to?
277 Could we get a referral to a machine that we don't want to give our
278 username and password to? */
282 memset(*credp
, '\0', strlen(*credp
));
285 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
286 ldap_state
->bind_dn
));
288 *whop
= strdup(ldap_state
->bind_dn
);
290 return LDAP_NO_MEMORY
;
292 *credp
= strdup(ldap_state
->bind_secret
);
295 return LDAP_NO_MEMORY
;
297 *methodp
= LDAP_AUTH_SIMPLE
;
301 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
303 /*******************************************************************
304 a rebind function for authenticated referrals
305 This version takes a void* that we can shove useful stuff in :-)
306 and actually does the connection.
307 ******************************************************************/
308 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
309 static int rebindproc_connect_with_state (LDAP
*ldap_struct
,
310 LDAP_CONST
char *url
,
312 ber_int_t msgid
, void *arg
)
314 struct ldapsam_privates
*ldap_state
= arg
;
316 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
317 ldap_state
->bind_dn
));
319 /** @TODO Should we be doing something to check what servers we rebind to?
320 Could we get a referral to a machine that we don't want to give our
321 username and password to? */
323 rc
= ldap_simple_bind_s(ldap_struct
, ldap_state
->bind_dn
, ldap_state
->bind_secret
);
327 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
329 /*******************************************************************
330 Add a rebind function for authenticated referrals
331 ******************************************************************/
332 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
334 # if LDAP_SET_REBIND_PROC_ARGS == 2
335 static int rebindproc (LDAP
*ldap_struct
, char **whop
, char **credp
,
336 int *method
, int freeit
)
338 return rebindproc_with_state(ldap_struct
, whop
, credp
,
339 method
, freeit
, static_ldap_state
);
342 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
343 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
345 /*******************************************************************
346 a rebind function for authenticated referrals
347 this also does the connection, but no void*.
348 ******************************************************************/
349 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
350 # if LDAP_SET_REBIND_PROC_ARGS == 2
351 static int rebindproc_connect (LDAP
* ld
, LDAP_CONST
char *url
, int request
,
354 return rebindproc_connect_with_state(ld
, url
, (ber_tag_t
)request
, msgid
,
357 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
358 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
360 /*******************************************************************
361 connect to the ldap server under system privilege.
362 ******************************************************************/
363 static int ldapsam_connect_system(struct ldapsam_privates
*ldap_state
, LDAP
* ldap_struct
)
369 /* The rebind proc needs this *HACK*. We are not multithreaded, so
370 this will work, but it's not nice. */
371 static_ldap_state
= ldap_state
;
373 /* get the password */
374 if (!fetch_ldap_pw(&ldap_dn
, &ldap_secret
))
376 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
377 return LDAP_INVALID_CREDENTIALS
;
380 ldap_state
->bind_dn
= ldap_dn
;
381 ldap_state
->bind_secret
= ldap_secret
;
383 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
384 (OpenLDAP) doesnt' seem to support it */
386 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
387 ldap_state
->uri
, ldap_dn
));
389 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
390 # if LDAP_SET_REBIND_PROC_ARGS == 2
391 ldap_set_rebind_proc(ldap_struct
, &rebindproc_connect
);
393 # if LDAP_SET_REBIND_PROC_ARGS == 3
394 ldap_set_rebind_proc(ldap_struct
, &rebindproc_connect_with_state
, (void *)ldap_state
);
396 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
397 # if LDAP_SET_REBIND_PROC_ARGS == 2
398 ldap_set_rebind_proc(ldap_struct
, &rebindproc
);
400 # if LDAP_SET_REBIND_PROC_ARGS == 3
401 ldap_set_rebind_proc(ldap_struct
, &rebindproc_with_state
, (void *)ldap_state
);
403 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
405 rc
= ldap_simple_bind_s(ldap_struct
, ldap_dn
, ldap_secret
);
407 if (rc
!= LDAP_SUCCESS
) {
408 char *ld_error
= NULL
;
409 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
411 DEBUG(ldap_state
->num_failures
? 2 : 0,
412 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
413 ldap_dn
? ld_error
: "(unknown)", ldap_err2string(rc
),
416 ldap_state
->num_failures
++;
420 ldap_state
->num_failures
= 0;
422 DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
426 /**********************************************************************
427 Connect to LDAP server
428 *********************************************************************/
429 static int ldapsam_open(struct ldapsam_privates
*ldap_state
)
432 SMB_ASSERT(ldap_state
);
434 #ifndef NO_LDAP_SECURITY
435 if (geteuid() != 0) {
436 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
437 return LDAP_INSUFFICIENT_ACCESS
;
441 if ((ldap_state
->ldap_struct
!= NULL
) && ((ldap_state
->last_ping
+ LDAPSAM_DONT_PING_TIME
) < time(NULL
))) {
442 struct sockaddr_un addr
;
443 socklen_t len
= sizeof(addr
);
445 if (ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_DESC
, &sd
) == 0 &&
446 getpeername(sd
, (struct sockaddr
*) &addr
, &len
) < 0) {
447 /* the other end has died. reopen. */
448 ldap_unbind_ext(ldap_state
->ldap_struct
, NULL
, NULL
);
449 ldap_state
->ldap_struct
= NULL
;
450 ldap_state
->last_ping
= (time_t)0;
452 ldap_state
->last_ping
= time(NULL
);
456 if (ldap_state
->ldap_struct
!= NULL
) {
457 DEBUG(5,("ldapsam_open: already connected to the LDAP server\n"));
461 if ((rc
= ldapsam_open_connection(ldap_state
, &ldap_state
->ldap_struct
))) {
465 if ((rc
= ldapsam_connect_system(ldap_state
, ldap_state
->ldap_struct
))) {
466 ldap_unbind_ext(ldap_state
->ldap_struct
, NULL
, NULL
);
467 ldap_state
->ldap_struct
= NULL
;
472 ldap_state
->last_ping
= time(NULL
);
473 DEBUG(4,("The LDAP server is succesful connected\n"));
478 /**********************************************************************
479 Disconnect from LDAP server
480 *********************************************************************/
481 static NTSTATUS
ldapsam_close(struct ldapsam_privates
*ldap_state
)
484 return NT_STATUS_INVALID_PARAMETER
;
486 if (ldap_state
->ldap_struct
!= NULL
) {
487 ldap_unbind_ext(ldap_state
->ldap_struct
, NULL
, NULL
);
488 ldap_state
->ldap_struct
= NULL
;
491 DEBUG(5,("The connection to the LDAP server was closed\n"));
492 /* maybe free the results here --metze */
497 static int ldapsam_retry_open(struct ldapsam_privates
*ldap_state
, int *attempts
)
501 SMB_ASSERT(ldap_state
&& attempts
);
503 if (*attempts
!= 0) {
504 unsigned int sleep_time
;
507 /* Sleep for a random timeout */
508 rand_byte
= (char)(sys_random());
510 sleep_time
= (((*attempts
)*(*attempts
))/2)*rand_byte
*2;
511 /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
514 DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n",
520 if ((rc
= ldapsam_open(ldap_state
))) {
521 DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts
));
529 /*********************************************************************
530 ********************************************************************/
532 static int ldapsam_search(struct ldapsam_privates
*ldap_state
,
533 const char *base
, int scope
, const char *filter
,
534 char *attrs
[], int attrsonly
,
537 int rc
= LDAP_SERVER_DOWN
;
541 SMB_ASSERT(ldap_state
);
543 if (push_utf8_allocate(&utf8_filter
, filter
) == (size_t)-1) {
544 return LDAP_NO_MEMORY
;
547 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
549 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
552 rc
= ldap_search_s(ldap_state
->ldap_struct
, base
, scope
,
553 utf8_filter
, attrs
, attrsonly
, res
);
556 if (rc
== LDAP_SERVER_DOWN
) {
557 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
558 ldapsam_close(ldap_state
);
561 SAFE_FREE(utf8_filter
);
565 static int ldapsam_modify(struct ldapsam_privates
*ldap_state
, const char *dn
, LDAPMod
*attrs
[])
567 int rc
= LDAP_SERVER_DOWN
;
571 SMB_ASSERT(ldap_state
);
573 if (push_utf8_allocate(&utf8_dn
, dn
) == (size_t)-1) {
574 return LDAP_NO_MEMORY
;
577 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
579 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
582 rc
= ldap_modify_s(ldap_state
->ldap_struct
, utf8_dn
, attrs
);
585 if (rc
== LDAP_SERVER_DOWN
) {
586 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
587 ldapsam_close(ldap_state
);
594 static int ldapsam_add(struct ldapsam_privates
*ldap_state
, const char *dn
, LDAPMod
*attrs
[])
596 int rc
= LDAP_SERVER_DOWN
;
600 SMB_ASSERT(ldap_state
);
602 if (push_utf8_allocate(&utf8_dn
, dn
) == (size_t)-1) {
603 return LDAP_NO_MEMORY
;
606 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
608 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
611 rc
= ldap_add_s(ldap_state
->ldap_struct
, utf8_dn
, attrs
);
614 if (rc
== LDAP_SERVER_DOWN
) {
615 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
616 ldapsam_close(ldap_state
);
623 static int ldapsam_delete(struct ldapsam_privates
*ldap_state
, char *dn
)
625 int rc
= LDAP_SERVER_DOWN
;
629 SMB_ASSERT(ldap_state
);
631 if (push_utf8_allocate(&utf8_dn
, dn
) == (size_t)-1) {
632 return LDAP_NO_MEMORY
;
635 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
637 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
640 rc
= ldap_delete_s(ldap_state
->ldap_struct
, utf8_dn
);
643 if (rc
== LDAP_SERVER_DOWN
) {
644 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
645 ldapsam_close(ldap_state
);
652 static int ldapsam_extended_operation(struct ldapsam_privates
*ldap_state
, LDAP_CONST
char *reqoid
, struct berval
*reqdata
, LDAPControl
**serverctrls
, LDAPControl
**clientctrls
, char **retoidp
, struct berval
**retdatap
)
654 int rc
= LDAP_SERVER_DOWN
;
660 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
662 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
665 rc
= ldap_extended_operation_s(ldap_state
->ldap_struct
, reqoid
, reqdata
, serverctrls
, clientctrls
, retoidp
, retdatap
);
668 if (rc
== LDAP_SERVER_DOWN
) {
669 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
670 ldapsam_close(ldap_state
);
676 /*******************************************************************
677 run the search by name.
678 ******************************************************************/
679 static int ldapsam_search_suffix (struct ldapsam_privates
*ldap_state
, const char *filter
,
680 char **search_attr
, LDAPMessage
** result
)
682 int scope
= LDAP_SCOPE_SUBTREE
;
685 DEBUG(2, ("ldapsam_search_suffix: searching for:[%s]\n", filter
));
687 rc
= ldapsam_search(ldap_state
, lp_ldap_suffix(), scope
, filter
, search_attr
, 0, result
);
689 if (rc
!= LDAP_SUCCESS
) {
690 char *ld_error
= NULL
;
691 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
693 DEBUG(0,("ldapsam_search_suffix: Problem during the LDAP search: %s (%s)\n",
694 ld_error
?ld_error
:"(unknown)", ldap_err2string (rc
)));
695 DEBUG(3,("ldapsam_search_suffix: Query was: %s, %s\n", lp_ldap_suffix(),
703 /*******************************************************************
704 generate the LDAP search filter for the objectclass based on the
705 version of the schema we are using
706 ******************************************************************/
708 static const char* get_objclass_filter( int schema_ver
)
710 static fstring objclass_filter
;
714 case SCHEMAVER_SAMBAACCOUNT
:
715 snprintf( objclass_filter
, sizeof(objclass_filter
)-1, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT
);
717 case SCHEMAVER_SAMBASAMACCOUNT
:
718 snprintf( objclass_filter
, sizeof(objclass_filter
)-1, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT
);
721 DEBUG(0,("ldapsam_search_suffix_by_name(): Invalid schema version specified!\n"));
725 return objclass_filter
;
728 /*******************************************************************
729 run the search by name.
730 ******************************************************************/
731 static int ldapsam_search_suffix_by_name (struct ldapsam_privates
*ldap_state
, const char *user
,
732 LDAPMessage
** result
, char **attr
)
735 char *escape_user
= escape_ldap_string_alloc(user
);
738 return LDAP_NO_MEMORY
;
742 * in the filter expression, replace %u with the real name
743 * so in ldap filter, %u MUST exist :-)
745 snprintf(filter
, sizeof(filter
)-1, "(&%s%s)", lp_ldap_filter(),
746 get_objclass_filter(ldap_state
->schema_ver
));
749 * have to use this here because $ is filtered out
754 all_string_sub(filter
, "%u", escape_user
, sizeof(pstring
));
755 SAFE_FREE(escape_user
);
757 return ldapsam_search_suffix(ldap_state
, filter
, attr
, result
);
760 /*******************************************************************
761 run the search by rid.
762 ******************************************************************/
763 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates
*ldap_state
,
764 uint32 rid
, LDAPMessage
** result
,
770 /* check if the user rid exists, if not, try searching on the uid */
772 snprintf(filter
, sizeof(filter
)-1, "(&(rid=%i)%s)", rid
,
773 get_objclass_filter(ldap_state
->schema_ver
));
775 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr
, result
);
780 /*******************************************************************
781 run the search by SID.
782 ******************************************************************/
783 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates
*ldap_state
,
784 const DOM_SID
*sid
, LDAPMessage
** result
,
791 /* check if the user rid exsists, if not, try searching on the uid */
793 snprintf(filter
, sizeof(filter
)-1, "(&(%s=%s)%s)",
794 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_SID
),
795 sid_to_string(sid_string
, sid
),
796 get_objclass_filter(ldap_state
->schema_ver
));
798 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr
, result
);
803 /*******************************************************************
804 search an attribute and return the first value found.
805 ******************************************************************/
806 static BOOL
get_single_attribute (LDAP
* ldap_struct
, LDAPMessage
* entry
,
807 const char *attribute
, pstring value
)
816 if ((values
= ldap_get_values (ldap_struct
, entry
, attribute
)) == NULL
) {
817 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute
));
822 if (convert_string(CH_UTF8
, CH_UNIX
,values
[0], -1, value
, sizeof(pstring
)) == (size_t)-1)
824 DEBUG(1, ("get_single_attribute: string conversion of [%s] = [%s] failed!\n",
825 attribute
, values
[0]));
826 ldap_value_free(values
);
830 ldap_value_free(values
);
831 #ifdef DEBUG_PASSWORDS
832 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute
, value
));
837 /**********************************************************************
838 Set attribute to newval in LDAP, regardless of what value the
839 attribute had in LDAP before.
840 *********************************************************************/
841 static void make_ldap_mod(LDAP
*ldap_struct
, LDAPMessage
*existing
,
843 const char *attribute
, const char *newval
)
845 char **values
= NULL
;
847 if (existing
!= NULL
) {
848 values
= ldap_get_values(ldap_struct
, existing
, attribute
);
851 /* all of our string attributes are case insensitive */
853 if ((values
!= NULL
) && (values
[0] != NULL
) &&
854 StrCaseCmp(values
[0], newval
) == 0)
857 /* Believe it or not, but LDAP will deny a delete and
858 an add at the same time if the values are the
861 ldap_value_free(values
);
865 /* Regardless of the real operation (add or modify)
866 we add the new value here. We rely on deleting
867 the old value, should it exist. */
869 if ((newval
!= NULL
) && (strlen(newval
) > 0)) {
870 ldap_set_mod(mods
, LDAP_MOD_ADD
, attribute
, newval
);
873 if (values
== NULL
) {
874 /* There has been no value before, so don't delete it.
875 Here's a possible race: We might end up with
876 duplicate attributes */
880 /* By deleting exactly the value we found in the entry this
881 should be race-free in the sense that the LDAP-Server will
882 deny the complete operation if somebody changed the
883 attribute behind our back. */
885 ldap_set_mod(mods
, LDAP_MOD_DELETE
, attribute
, values
[0]);
886 ldap_value_free(values
);
889 /*******************************************************************
890 Delete complete object or objectclass and attrs from
891 object found in search_result depending on lp_ldap_delete_dn
892 ******************************************************************/
893 static NTSTATUS
ldapsam_delete_entry(struct ldapsam_privates
*ldap_state
,
895 const char *objectclass
,
900 LDAPMod
**mods
= NULL
;
902 BerElement
*ptr
= NULL
;
904 rc
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
907 DEBUG(0, ("Entry must exist exactly once!\n"));
908 return NT_STATUS_UNSUCCESSFUL
;
911 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
912 dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
914 if (lp_ldap_delete_dn()) {
915 NTSTATUS ret
= NT_STATUS_OK
;
916 rc
= ldapsam_delete(ldap_state
, dn
);
918 if (rc
!= LDAP_SUCCESS
) {
919 DEBUG(0, ("Could not delete object %s\n", dn
));
920 ret
= NT_STATUS_UNSUCCESSFUL
;
926 /* Ok, delete only the SAM attributes */
928 for (name
= ldap_first_attribute(ldap_state
->ldap_struct
, entry
, &ptr
);
930 name
= ldap_next_attribute(ldap_state
->ldap_struct
, entry
, ptr
))
934 /* We are only allowed to delete the attributes that
937 for (attrib
= attrs
; *attrib
!= NULL
; attrib
++)
939 if (StrCaseCmp(*attrib
, name
) == 0) {
940 DEBUG(10, ("deleting attribute %s\n", name
));
941 ldap_set_mod(&mods
, LDAP_MOD_DELETE
, name
, NULL
);
952 ldap_set_mod(&mods
, LDAP_MOD_DELETE
, "objectClass", objectclass
);
954 rc
= ldapsam_modify(ldap_state
, dn
, mods
);
955 ldap_mods_free(mods
, True
);
957 if (rc
!= LDAP_SUCCESS
) {
958 char *ld_error
= NULL
;
959 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
962 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
963 dn
, ldap_err2string(rc
), ld_error
?ld_error
:"unknown"));
966 return NT_STATUS_UNSUCCESSFUL
;
973 /**********************************************************************
974 Search for the domain info entry
975 *********************************************************************/
976 static int ldapsam_search_domain_info(struct ldapsam_privates
*ldap_state
,
977 LDAPMessage
** result
)
983 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(%s=%s))",
985 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOMAIN
),
986 ldap_state
->domain_name
);
988 DEBUG(2, ("Searching for:[%s]\n", filter
));
991 attr_list
= get_attr_list( dominfo_attr_list
);
992 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr_list
, result
);
993 free_attr_list( attr_list
);
995 if (rc
!= LDAP_SUCCESS
) {
996 DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc
)));
997 DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
1003 /**********************************************************************
1004 If this entry is is the 'allocated' range, extract the RID and return
1005 it, so we can find the 'next' rid to allocate.
1007 Do this, no matter what type of object holds the RID - be it a user,
1008 group or somthing else.
1009 *********************************************************************/
1010 static uint32
entry_to_rid(struct ldapsam_privates
*ldap_state
, LDAPMessage
*entry
, int rid_type
)
1016 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1017 LDAP_ATTRIBUTE_SID
, sid_string
))
1022 if (!string_to_sid(&dom_sid
, sid_string
)) {
1026 if (!sid_peek_check_rid(&dom_sid
, get_global_sam_sid(), &rid
)) {
1027 /* not our domain, so we don't care */
1033 if (rid
>= ldap_state
->low_allocated_user_rid
&&
1034 rid
<= ldap_state
->high_allocated_user_rid
) {
1038 case GROUP_RID_TYPE
:
1039 if (rid
>= ldap_state
->low_allocated_group_rid
&&
1040 rid
<= ldap_state
->high_allocated_group_rid
) {
1049 /**********************************************************************
1050 Connect to LDAP server and find the next available 'allocated' RID.
1052 The search is done 'per type' as we allocate seperate pools for the
1053 EVEN and ODD (user and group) RIDs.
1055 This is only done once, so that we can fill out the sambaDomain.
1056 *********************************************************************/
1057 static uint32
search_next_allocated_rid(struct ldapsam_privates
*ldap_state
, int rid_type
)
1060 LDAPMessage
*result
;
1066 char *sid_attr
[] = {LDAP_ATTRIBUTE_SID
, NULL
};
1069 snprintf( filter
, sizeof(filter
)-1, "(%s=*)", LDAP_ATTRIBUTE_SID
);
1071 DEBUG(2, ("search_top_allocated_rid: searching for:[%s]\n", filter
));
1073 rc
= ldapsam_search_suffix(ldap_state
, filter
, sid_attr
, &result
);
1075 if (rc
!= LDAP_SUCCESS
) {
1076 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc
)));
1077 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
1083 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1084 DEBUG(2, ("search_top_allocated_rid: %d entries in the base!\n", count
));
1087 DEBUG(3, ("LDAP search returned no records, assuming no allocated RIDs present!: %s\n", ldap_err2string(rc
)));
1088 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
1090 entry
= ldap_first_entry(ldap_state
->ldap_struct
,result
);
1092 top_rid
= entry_to_rid(ldap_state
, entry
, rid_type
);
1094 while ((entry
= ldap_next_entry(ldap_state
->ldap_struct
, entry
))) {
1096 rid
= entry_to_rid(ldap_state
, entry
, rid_type
);
1097 if (((rid
& ~RID_TYPE_MASK
) == rid_type
) && (rid
> top_rid
)) {
1105 if (top_rid
< ldap_state
->low_allocated_user_rid
) {
1106 return ldap_state
->low_allocated_user_rid
;
1109 case GROUP_RID_TYPE
:
1110 if (top_rid
< ldap_state
->low_allocated_group_rid
)
1111 return ldap_state
->low_allocated_group_rid
;
1115 next_rid
= (top_rid
& ~RID_TYPE_MASK
) + rid_type
+ RID_MULTIPLIER
;
1119 if (next_rid
> ldap_state
->high_allocated_user_rid
) {
1123 case GROUP_RID_TYPE
:
1124 if (next_rid
> ldap_state
->high_allocated_group_rid
) {
1132 /**********************************************************************
1133 Add the sambaDomain to LDAP, so we don't have to search for this stuff
1134 again. This is a once-add operation for now.
1136 TODO: Add other attributes, and allow modification.
1137 *********************************************************************/
1138 static NTSTATUS
add_new_domain_info(struct ldapsam_privates
*ldap_state
)
1142 LDAPMod
**mods
= NULL
;
1145 LDAPMessage
*result
= NULL
;
1149 uint32 next_allocated_user_rid
;
1150 uint32 next_allocated_group_rid
;
1152 next_allocated_user_rid
= search_next_allocated_rid(ldap_state
, USER_RID_TYPE
);
1153 if (!next_allocated_user_rid
) {
1154 return NT_STATUS_UNSUCCESSFUL
;
1157 next_allocated_group_rid
= search_next_allocated_rid(ldap_state
, GROUP_RID_TYPE
);
1158 if (!next_allocated_group_rid
) {
1159 return NT_STATUS_UNSUCCESSFUL
;
1162 slprintf (filter
, sizeof (filter
) - 1, "(&(%s=%s)(objectclass=%s))",
1163 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOMAIN
),
1164 ldap_state
->domain_name
, LDAP_OBJ_DOMINFO
);
1166 attr_list
= get_attr_list( dominfo_attr_list
);
1167 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr_list
, &result
);
1168 free_attr_list( attr_list
);
1170 if (rc
!= LDAP_SUCCESS
) {
1171 return NT_STATUS_UNSUCCESSFUL
;
1174 num_result
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1176 if (num_result
> 1) {
1177 DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
1178 ldap_msgfree(result
);
1179 return NT_STATUS_UNSUCCESSFUL
;
1182 /* Check if we need to add an entry */
1183 DEBUG(3,("Adding new domain\n"));
1184 ldap_op
= LDAP_MOD_ADD
;
1185 snprintf(dn
, sizeof(dn
), "%s=%s,%s", get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOMAIN
),
1186 ldap_state
->domain_name
, lp_ldap_suffix());
1188 /* Free original search */
1189 ldap_msgfree(result
);
1191 /* make the changes - the entry *must* not already have samba attributes */
1192 ldap_set_mod(&mods
, LDAP_MOD_ADD
, get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOMAIN
),
1193 ldap_state
->domain_name
);
1195 sid_to_string(tmp
, &ldap_state
->domain_sid
);
1196 ldap_set_mod(&mods
, LDAP_MOD_ADD
, get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOM_SID
), tmp
);
1198 snprintf(tmp
, sizeof(tmp
)-1, "%i", next_allocated_user_rid
);
1199 ldap_set_mod(&mods
, LDAP_MOD_ADD
, get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_USERRID
), tmp
);
1201 snprintf(tmp
, sizeof(tmp
)-1, "%i", next_allocated_group_rid
);
1202 ldap_set_mod(&mods
, LDAP_MOD_ADD
, get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_GROUPRID
), tmp
);
1204 ldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectclass", LDAP_OBJ_DOMINFO
);
1209 rc
= ldapsam_add(ldap_state
, dn
, mods
);
1211 case LDAP_MOD_REPLACE
:
1212 rc
= ldapsam_modify(ldap_state
, dn
, mods
);
1215 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op
));
1216 return NT_STATUS_INVALID_PARAMETER
;
1219 if (rc
!=LDAP_SUCCESS
) {
1220 char *ld_error
= NULL
;
1221 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
1224 ("failed to %s domain dn= %s with: %s\n\t%s\n",
1225 ldap_op
== LDAP_MOD_ADD
? "add" : "modify",
1226 dn
, ldap_err2string(rc
),
1227 ld_error
?ld_error
:"unknown"));
1228 SAFE_FREE(ld_error
);
1230 ldap_mods_free(mods
, True
);
1231 return NT_STATUS_UNSUCCESSFUL
;
1234 DEBUG(2,("added: domain = %s in the LDAP database\n", ldap_state
->domain_name
));
1235 ldap_mods_free(mods
, True
);
1236 return NT_STATUS_OK
;
1239 /**********************************************************************
1240 Even if the sambaAccount attribute in LDAP tells us that this RID is
1241 safe to use, always check before use.
1242 *********************************************************************/
1243 static BOOL
sid_in_use(struct ldapsam_privates
*ldap_state
,
1244 const DOM_SID
*sid
, int *error
)
1248 LDAPMessage
*result
= NULL
;
1251 char *sid_attr
[] = {LDAP_ATTRIBUTE_SID
, NULL
};
1253 slprintf(filter
, sizeof(filter
)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID
, sid_to_string(sid_string
, sid
));
1255 rc
= ldapsam_search_suffix(ldap_state
, filter
, sid_attr
, &result
);
1257 if (rc
!= LDAP_SUCCESS
) {
1258 char *ld_error
= NULL
;
1259 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
1260 DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
1261 sid_string
, ld_error
));
1262 SAFE_FREE(ld_error
);
1268 if ((count
= ldap_count_entries(ldap_state
->ldap_struct
, result
)) > 0) {
1269 DEBUG(3, ("Sid %s already in use - trying next RID\n",
1271 ldap_msgfree(result
);
1275 ldap_msgfree(result
);
1277 /* good, sid is not in use */
1281 /**********************************************************************
1282 Set the new nextRid attribute, and return one we can use.
1284 This also checks that this RID is actually free - in case the admin
1285 manually stole it :-).
1286 *********************************************************************/
1287 static NTSTATUS
ldapsam_next_rid(struct ldapsam_privates
*ldap_state
, uint32
*rid
, int rid_type
)
1289 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1291 LDAPMessage
*result
= NULL
;
1292 LDAPMessage
*entry
= NULL
;
1294 LDAPMod
**mods
= NULL
;
1296 fstring old_rid_string
;
1297 fstring next_rid_string
;
1301 if ( ldap_state
->schema_ver
!= SCHEMAVER_SAMBASAMACCOUNT
) {
1302 DEBUG(0, ("Allocated RIDs require the %s objectclass used by 'ldapsam'\n",
1303 LDAP_OBJ_SAMBASAMACCOUNT
));
1304 return NT_STATUS_UNSUCCESSFUL
;
1307 while (attempts
< 10)
1310 if (ldapsam_search_domain_info(ldap_state
, &result
)) {
1314 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) < 1) {
1315 DEBUG(3, ("Got no domain info entries for domain %s\n",
1316 ldap_state
->domain_name
));
1317 ldap_msgfree(result
);
1318 if (NT_STATUS_IS_OK(ret
= add_new_domain_info(ldap_state
))) {
1321 DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret
)));
1326 if ((count
= ldap_count_entries(ldap_state
->ldap_struct
, result
)) > 1) {
1327 DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
1328 count
, ldap_state
->domain_name
));
1329 ldap_msgfree(result
);
1333 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1335 ldap_msgfree(result
);
1339 if ((dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
)) == NULL
) {
1340 DEBUG(0, ("Could not get domain info DN\n"));
1341 ldap_msgfree(result
);
1345 /* yes, we keep 2 seperate counters, to avoid stomping on the two
1346 different sets of algorithmic RIDs */
1350 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1351 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_USERRID
),
1355 ldap_msgfree(result
);
1359 case GROUP_RID_TYPE
:
1360 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1361 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_GROUPRID
),
1365 ldap_msgfree(result
);
1371 /* This is the core of the whole routine. If we had
1372 scheme-style closures, there would be a *lot* less code
1374 *rid
= (uint32
)atol(old_rid_string
);
1375 next_rid
= *rid
+RID_MULTIPLIER
;
1377 slprintf(next_rid_string
, sizeof(next_rid_string
)-1, "%d", next_rid
);
1381 if (next_rid
> ldap_state
->high_allocated_user_rid
) {
1382 return NT_STATUS_UNSUCCESSFUL
;
1385 /* Try to make the modification atomically by enforcing the
1386 old value in the delete mod. */
1387 make_ldap_mod(ldap_state
->ldap_struct
, entry
, &mods
,
1388 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_USERRID
),
1392 case GROUP_RID_TYPE
:
1393 if (next_rid
> ldap_state
->high_allocated_group_rid
) {
1394 return NT_STATUS_UNSUCCESSFUL
;
1397 /* Try to make the modification atomically by enforcing the
1398 old value in the delete mod. */
1399 make_ldap_mod(ldap_state
->ldap_struct
, entry
, &mods
,
1400 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_GROUPRID
),
1405 if ((rc
= ldap_modify_s(ldap_state
->ldap_struct
, dn
, mods
)) == LDAP_SUCCESS
) {
1408 pstring domain_sid_string
;
1411 if (!get_single_attribute(ldap_state
->ldap_struct
, result
,
1412 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOM_SID
),
1415 ldap_mods_free(mods
, True
);
1417 ldap_msgfree(result
);
1421 if (!string_to_sid(&dom_sid
, domain_sid_string
)) {
1422 ldap_mods_free(mods
, True
);
1424 ldap_msgfree(result
);
1428 ldap_mods_free(mods
, True
);
1431 ldap_msgfree(result
);
1433 sid_copy(&sid
, &dom_sid
);
1434 sid_append_rid(&sid
, *rid
);
1436 /* check RID is not in use */
1437 if (sid_in_use(ldap_state
, &sid
, &error
)) {
1444 return NT_STATUS_OK
;
1447 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
1448 DEBUG(2, ("Failed to modify rid: %s\n", ld_error
));
1449 SAFE_FREE(ld_error
);
1451 ldap_mods_free(mods
, True
);
1457 ldap_msgfree(result
);
1461 /* Sleep for a random timeout */
1462 unsigned sleeptime
= (sys_random()*sys_getpid()*attempts
);
1470 DEBUG(0, ("Failed to set new RID\n"));
1474 /* New Interface is being implemented here */
1476 /**********************************************************************
1477 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
1478 *********************************************************************/
1479 static BOOL
get_unix_attributes (struct ldapsam_privates
*ldap_state
,
1480 SAM_ACCOUNT
* sampass
,
1481 LDAPMessage
* entry
,
1489 if ((ldap_values
= ldap_get_values (ldap_state
->ldap_struct
, entry
, "objectClass")) == NULL
) {
1490 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
1494 for (values
=ldap_values
;*values
;values
++) {
1495 if (strcasecmp(*values
, LDAP_OBJ_POSIXACCOUNT
) == 0) {
1500 if (!*values
) { /*end of array, no posixAccount */
1501 DEBUG(10, ("user does not have %s attributes\n", LDAP_OBJ_POSIXACCOUNT
));
1502 ldap_value_free(ldap_values
);
1505 ldap_value_free(ldap_values
);
1507 if ( !get_single_attribute(ldap_state
->ldap_struct
, entry
,
1508 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_UNIX_HOME
), homedir
) )
1513 if ( !get_single_attribute(ldap_state
->ldap_struct
, entry
,
1514 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_GIDNUMBER
), temp
) )
1519 *gid
= (gid_t
)atol(temp
);
1521 pdb_set_unix_homedir(sampass
, homedir
, PDB_SET
);
1523 DEBUG(10, ("user has %s attributes\n", LDAP_OBJ_POSIXACCOUNT
));
1529 /**********************************************************************
1530 Initialize SAM_ACCOUNT from an LDAP query
1531 (Based on init_sam_from_buffer in pdb_tdb.c)
1532 *********************************************************************/
1533 static BOOL
init_sam_from_ldap (struct ldapsam_privates
*ldap_state
,
1534 SAM_ACCOUNT
* sampass
,
1535 LDAPMessage
* entry
)
1541 pass_can_change_time
,
1542 pass_must_change_time
;
1555 uint8 smblmpwd
[LM_HASH_LEN
],
1556 smbntpwd
[NT_HASH_LEN
];
1557 uint16 acct_ctrl
= 0,
1560 uint8 hours
[MAX_HOURS_LEN
];
1563 gid_t gid
= getegid();
1566 * do a little initialization
1570 nt_username
[0] = '\0';
1573 dir_drive
[0] = '\0';
1574 logon_script
[0] = '\0';
1575 profile_path
[0] = '\0';
1576 acct_desc
[0] = '\0';
1577 munged_dial
[0] = '\0';
1578 workstations
[0] = '\0';
1581 if (sampass
== NULL
|| ldap_state
== NULL
|| entry
== NULL
) {
1582 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1586 if (ldap_state
->ldap_struct
== NULL
) {
1587 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1591 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "uid", username
)) {
1592 DEBUG(1, ("No uid attribute found for this user!\n"));
1596 DEBUG(2, ("Entry found for user: %s\n", username
));
1598 pstrcpy(nt_username
, username
);
1600 pstrcpy(domain
, ldap_state
->domain_name
);
1602 pdb_set_username(sampass
, username
, PDB_SET
);
1604 pdb_set_domain(sampass
, domain
, PDB_DEFAULT
);
1605 pdb_set_nt_username(sampass
, nt_username
, PDB_SET
);
1607 /* deal with different attributes between the schema first */
1609 if ( ldap_state
->schema_ver
== SCHEMAVER_SAMBASAMACCOUNT
)
1611 if (get_single_attribute(ldap_state
->ldap_struct
, entry
,
1612 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_SID
), temp
))
1614 pdb_set_user_sid_from_string(sampass
, temp
, PDB_SET
);
1617 if (get_single_attribute(ldap_state
->ldap_struct
, entry
,
1618 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PRIMARY_GROUP_SID
), temp
))
1620 pdb_set_group_sid_from_string(sampass
, temp
, PDB_SET
);
1624 pdb_set_group_sid_from_rid(sampass
, DOMAIN_GROUP_RID_USERS
, PDB_DEFAULT
);
1631 if (get_single_attribute(ldap_state
->ldap_struct
, entry
,
1632 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_RID
), temp
))
1634 user_rid
= (uint32
)atol(temp
);
1635 pdb_set_user_sid_from_rid(sampass
, user_rid
, PDB_SET
);
1638 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1639 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PRIMARY_GROUP_RID
), temp
))
1641 pdb_set_group_sid_from_rid(sampass
, DOMAIN_GROUP_RID_USERS
, PDB_DEFAULT
);
1645 group_rid
= (uint32
)atol(temp
);
1647 /* for some reason, we often have 0 as a primary group RID.
1648 Make sure that we treat this just as a 'default' value */
1650 if ( group_rid
> 0 )
1651 pdb_set_group_sid_from_rid(sampass
, group_rid
, PDB_SET
);
1653 pdb_set_group_sid_from_rid(sampass
, DOMAIN_GROUP_RID_USERS
, PDB_DEFAULT
);
1657 if (pdb_get_init_flags(sampass
,PDB_USERSID
) == PDB_DEFAULT
) {
1658 DEBUG(1, ("no %s or %s attribute found for this user %s\n",
1659 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_SID
),
1660 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_RID
),
1667 * If so configured, try and get the values from LDAP
1670 if (lp_ldap_trust_ids() && (get_unix_attributes(ldap_state
, sampass
, entry
, &gid
)))
1672 if (pdb_get_init_flags(sampass
,PDB_GROUPSID
) == PDB_DEFAULT
)
1675 /* call the mapping code here */
1676 if(pdb_getgrgid(&map
, gid
)) {
1677 pdb_set_group_sid(sampass
, &map
.sid
, PDB_SET
);
1680 pdb_set_group_sid_from_rid(sampass
, pdb_gid_to_group_rid(gid
), PDB_SET
);
1685 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1686 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_LAST_SET
), temp
))
1688 /* leave as default */
1690 pass_last_set_time
= (time_t) atol(temp
);
1691 pdb_set_pass_last_set_time(sampass
, pass_last_set_time
, PDB_SET
);
1694 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1695 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGON_TIME
), temp
))
1697 /* leave as default */
1699 logon_time
= (time_t) atol(temp
);
1700 pdb_set_logon_time(sampass
, logon_time
, PDB_SET
);
1703 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1704 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGOFF_TIME
), temp
))
1706 /* leave as default */
1708 logoff_time
= (time_t) atol(temp
);
1709 pdb_set_logoff_time(sampass
, logoff_time
, PDB_SET
);
1712 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1713 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_KICKOFF_TIME
), temp
))
1715 /* leave as default */
1717 kickoff_time
= (time_t) atol(temp
);
1718 pdb_set_kickoff_time(sampass
, kickoff_time
, PDB_SET
);
1721 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1722 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_CAN_CHANGE
), temp
))
1724 /* leave as default */
1726 pass_can_change_time
= (time_t) atol(temp
);
1727 pdb_set_pass_can_change_time(sampass
, pass_can_change_time
, PDB_SET
);
1730 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1731 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_MUST_CHANGE
), temp
))
1733 /* leave as default */
1735 pass_must_change_time
= (time_t) atol(temp
);
1736 pdb_set_pass_must_change_time(sampass
, pass_must_change_time
, PDB_SET
);
1739 /* recommend that 'gecos' and 'displayName' should refer to the same
1740 * attribute OID. userFullName depreciated, only used by Samba
1741 * primary rules of LDAP: don't make a new attribute when one is already defined
1742 * that fits your needs; using cn then displayName rather than 'userFullName'
1745 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1746 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_DISPLAY_NAME
), fullname
))
1748 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1749 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_CN
), fullname
))
1751 /* leave as default */
1753 pdb_set_fullname(sampass
, fullname
, PDB_SET
);
1756 pdb_set_fullname(sampass
, fullname
, PDB_SET
);
1759 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1760 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_HOME_DRIVE
), dir_drive
))
1762 pdb_set_dir_drive(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
1768 pdb_set_dir_drive(sampass
, dir_drive
, PDB_SET
);
1771 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1772 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_HOME_PATH
), homedir
))
1774 pdb_set_homedir(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
1780 pdb_set_homedir(sampass
, homedir
, PDB_SET
);
1783 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1784 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGON_SCRIPT
), logon_script
))
1786 pdb_set_logon_script(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
1792 pdb_set_logon_script(sampass
, logon_script
, PDB_SET
);
1795 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1796 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PROFILE_PATH
), profile_path
))
1798 pdb_set_profile_path(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
1804 pdb_set_profile_path(sampass
, profile_path
, PDB_SET
);
1807 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1808 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_DESC
), acct_desc
))
1810 /* leave as default */
1812 pdb_set_acct_desc(sampass
, acct_desc
, PDB_SET
);
1815 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1816 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_WKS
), workstations
))
1818 /* leave as default */;
1820 pdb_set_workstations(sampass
, workstations
, PDB_SET
);
1823 /* FIXME: hours stuff should be cleaner */
1827 memset(hours
, 0xff, hours_len
);
1829 if (!get_single_attribute (ldap_state
->ldap_struct
, entry
,
1830 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LMPW
), temp
))
1832 /* leave as default */
1834 pdb_gethexpwd(temp
, smblmpwd
);
1835 memset((char *)temp
, '\0', strlen(temp
)+1);
1836 if (!pdb_set_lanman_passwd(sampass
, smblmpwd
, PDB_SET
))
1838 ZERO_STRUCT(smblmpwd
);
1841 if (!get_single_attribute (ldap_state
->ldap_struct
, entry
,
1842 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_NTPW
), temp
))
1844 /* leave as default */
1846 pdb_gethexpwd(temp
, smbntpwd
);
1847 memset((char *)temp
, '\0', strlen(temp
)+1);
1848 if (!pdb_set_nt_passwd(sampass
, smbntpwd
, PDB_SET
))
1850 ZERO_STRUCT(smbntpwd
);
1853 if (!get_single_attribute (ldap_state
->ldap_struct
, entry
,
1854 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_ACB_INFO
), temp
))
1856 acct_ctrl
|= ACB_NORMAL
;
1858 acct_ctrl
= pdb_decode_acct_ctrl(temp
);
1861 acct_ctrl
|= ACB_NORMAL
;
1863 pdb_set_acct_ctrl(sampass
, acct_ctrl
, PDB_SET
);
1866 pdb_set_hours_len(sampass
, hours_len
, PDB_SET
);
1867 pdb_set_logon_divs(sampass
, logon_divs
, PDB_SET
);
1869 pdb_set_munged_dial(sampass
, munged_dial
, PDB_SET
);
1871 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1872 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1873 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1875 pdb_set_hours(sampass
, hours
, PDB_SET
);
1880 /**********************************************************************
1881 Initialize SAM_ACCOUNT from an LDAP query
1882 (Based on init_buffer_from_sam in pdb_tdb.c)
1883 *********************************************************************/
1884 static BOOL
init_ldap_from_sam (struct ldapsam_privates
*ldap_state
,
1885 LDAPMessage
*existing
,
1886 LDAPMod
*** mods
, SAM_ACCOUNT
* sampass
,
1887 BOOL (*need_update
)(const SAM_ACCOUNT
*,
1893 if (mods
== NULL
|| sampass
== NULL
) {
1894 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1901 * took out adding "objectclass: sambaAccount"
1902 * do this on a per-mod basis
1904 if (need_update(sampass
, PDB_USERNAME
))
1905 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
1906 "uid", pdb_get_username(sampass
));
1908 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass
)));
1910 if (pdb_get_init_flags(sampass
, PDB_USERSID
) == PDB_DEFAULT
) {
1911 if (ldap_state
->permit_non_unix_accounts
) {
1912 if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state
, &rid
, USER_RID_TYPE
))) {
1913 DEBUG(0, ("NO user RID specified on account %s, and "
1914 "finding next available NUA RID failed, "
1916 pdb_get_username(sampass
)));
1917 ldap_mods_free(*mods
, True
);
1921 DEBUG(0, ("NO user RID specified on account %s, "
1922 "cannot store!\n", pdb_get_username(sampass
)));
1923 ldap_mods_free(*mods
, True
);
1927 /* now that we have figured out the RID, always store it, as
1928 the schema requires it (either as a SID or a RID) */
1930 if (!pdb_set_user_sid_from_rid(sampass
, rid
, PDB_CHANGED
)) {
1931 DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n",
1932 pdb_get_username(sampass
)));
1933 ldap_mods_free(*mods
, True
);
1938 /* only update the RID if we actually need to */
1939 if (need_update(sampass
, PDB_USERSID
))
1942 fstring dom_sid_string
;
1943 const DOM_SID
*user_sid
= pdb_get_user_sid(sampass
);
1945 switch ( ldap_state
->schema_ver
)
1947 case SCHEMAVER_SAMBAACCOUNT
:
1948 if (!sid_peek_check_rid(get_global_sam_sid(), user_sid
, &rid
)) {
1949 DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
1950 sid_to_string(sid_string
, user_sid
),
1951 sid_to_string(dom_sid_string
, get_global_sam_sid())));
1954 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
1955 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
1956 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_RID
),
1960 case SCHEMAVER_SAMBASAMACCOUNT
:
1961 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
1962 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_SID
),
1963 sid_to_string(sid_string
, user_sid
));
1967 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
1972 /* we don't need to store the primary group RID - so leaving it
1973 'free' to hang off the unix primary group makes life easier */
1975 if (need_update(sampass
, PDB_GROUPSID
))
1978 fstring dom_sid_string
;
1979 const DOM_SID
*group_sid
= pdb_get_group_sid(sampass
);
1981 switch ( ldap_state
->schema_ver
)
1983 case SCHEMAVER_SAMBAACCOUNT
:
1984 if (!sid_peek_check_rid(get_global_sam_sid(), group_sid
, &rid
)) {
1985 DEBUG(1, ("User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
1986 sid_to_string(sid_string
, group_sid
),
1987 sid_to_string(dom_sid_string
, get_global_sam_sid())));
1991 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
1992 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
1993 get_userattr_key2string(ldap_state
->schema_ver
,
1994 LDAP_ATTR_PRIMARY_GROUP_RID
), temp
);
1997 case SCHEMAVER_SAMBASAMACCOUNT
:
1998 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
1999 get_userattr_key2string(ldap_state
->schema_ver
,
2000 LDAP_ATTR_PRIMARY_GROUP_SID
), sid_to_string(sid_string
, group_sid
));
2004 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
2010 /* displayName, cn, and gecos should all be the same
2011 * most easily accomplished by giving them the same OID
2012 * gecos isn't set here b/c it should be handled by the
2014 * We change displayName only and fall back to cn if
2015 * it does not exist.
2018 if (need_update(sampass
, PDB_FULLNAME
))
2019 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2020 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_DISPLAY_NAME
),
2021 pdb_get_fullname(sampass
));
2023 if (need_update(sampass
, PDB_ACCTDESC
))
2024 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2025 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_DESC
),
2026 pdb_get_acct_desc(sampass
));
2028 if (need_update(sampass
, PDB_WORKSTATIONS
))
2029 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2030 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_WKS
),
2031 pdb_get_workstations(sampass
));
2033 if (need_update(sampass
, PDB_SMBHOME
))
2034 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2035 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_HOME_PATH
),
2036 pdb_get_homedir(sampass
));
2038 if (need_update(sampass
, PDB_DRIVE
))
2039 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2040 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_HOME_DRIVE
),
2041 pdb_get_dir_drive(sampass
));
2043 if (need_update(sampass
, PDB_LOGONSCRIPT
))
2044 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2045 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGON_SCRIPT
),
2046 pdb_get_logon_script(sampass
));
2048 if (need_update(sampass
, PDB_PROFILE
))
2049 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2050 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PROFILE_PATH
),
2051 pdb_get_profile_path(sampass
));
2053 slprintf(temp
, sizeof(temp
) - 1, "%li", pdb_get_logon_time(sampass
));
2054 if (need_update(sampass
, PDB_LOGONTIME
))
2055 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2056 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGON_TIME
), temp
);
2058 slprintf(temp
, sizeof(temp
) - 1, "%li", pdb_get_logoff_time(sampass
));
2059 if (need_update(sampass
, PDB_LOGOFFTIME
))
2060 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2061 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGOFF_TIME
), temp
);
2063 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_kickoff_time(sampass
));
2064 if (need_update(sampass
, PDB_KICKOFFTIME
))
2065 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2066 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_KICKOFF_TIME
), temp
);
2068 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_can_change_time(sampass
));
2069 if (need_update(sampass
, PDB_CANCHANGETIME
))
2070 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2071 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_CAN_CHANGE
), temp
);
2073 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_must_change_time(sampass
));
2074 if (need_update(sampass
, PDB_MUSTCHANGETIME
))
2075 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2076 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_MUST_CHANGE
), temp
);
2078 if ((pdb_get_acct_ctrl(sampass
)&(ACB_WSTRUST
|ACB_SVRTRUST
|ACB_DOMTRUST
))
2079 || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY
))
2082 pdb_sethexpwd(temp
, pdb_get_lanman_passwd(sampass
),
2083 pdb_get_acct_ctrl(sampass
));
2085 if (need_update(sampass
, PDB_LMPASSWD
))
2086 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2087 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LMPW
),
2090 pdb_sethexpwd (temp
, pdb_get_nt_passwd(sampass
),
2091 pdb_get_acct_ctrl(sampass
));
2093 if (need_update(sampass
, PDB_NTPASSWD
))
2094 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2095 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_NTPW
),
2098 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_last_set_time(sampass
));
2099 if (need_update(sampass
, PDB_PASSLASTSET
))
2100 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2101 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_LAST_SET
),
2105 /* FIXME: Hours stuff goes in LDAP */
2107 if (need_update(sampass
, PDB_ACCTCTRL
))
2108 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2109 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_ACB_INFO
),
2110 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass
), NEW_PW_FORMAT_SPACE_PADDED_LEN
));
2117 /**********************************************************************
2118 Connect to LDAP server for password enumeration
2119 *********************************************************************/
2120 static NTSTATUS
ldapsam_setsampwent(struct pdb_methods
*my_methods
, BOOL update
)
2122 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2127 snprintf( filter
, sizeof(filter
)-1, "(&%s%s)", lp_ldap_filter(),
2128 get_objclass_filter(ldap_state
->schema_ver
));
2129 all_string_sub(filter
, "%u", "*", sizeof(pstring
));
2131 attr_list
= get_userattr_list(ldap_state
->schema_ver
);
2132 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr_list
, &ldap_state
->result
);
2133 free_attr_list( attr_list
);
2135 if (rc
!= LDAP_SUCCESS
) {
2136 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc
)));
2137 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
2138 ldap_msgfree(ldap_state
->result
);
2139 ldap_state
->result
= NULL
;
2140 return NT_STATUS_UNSUCCESSFUL
;
2143 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2144 ldap_count_entries(ldap_state
->ldap_struct
,
2145 ldap_state
->result
)));
2147 ldap_state
->entry
= ldap_first_entry(ldap_state
->ldap_struct
,
2148 ldap_state
->result
);
2149 ldap_state
->index
= 0;
2151 return NT_STATUS_OK
;
2154 /**********************************************************************
2155 End enumeration of the LDAP password list
2156 *********************************************************************/
2157 static void ldapsam_endsampwent(struct pdb_methods
*my_methods
)
2159 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2160 if (ldap_state
->result
) {
2161 ldap_msgfree(ldap_state
->result
);
2162 ldap_state
->result
= NULL
;
2166 /**********************************************************************
2167 Get the next entry in the LDAP password database
2168 *********************************************************************/
2169 static NTSTATUS
ldapsam_getsampwent(struct pdb_methods
*my_methods
, SAM_ACCOUNT
*user
)
2171 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
2172 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2175 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2176 this will work, but it's not nice. */
2177 static_ldap_state
= ldap_state
;
2180 if (!ldap_state
->entry
)
2183 ldap_state
->index
++;
2184 bret
= init_sam_from_ldap(ldap_state
, user
, ldap_state
->entry
);
2186 ldap_state
->entry
= ldap_next_entry(ldap_state
->ldap_struct
,
2190 return NT_STATUS_OK
;
2193 /**********************************************************************
2194 Get SAM_ACCOUNT entry from LDAP by username
2195 *********************************************************************/
2196 static NTSTATUS
ldapsam_getsampwnam(struct pdb_methods
*my_methods
, SAM_ACCOUNT
*user
, const char *sname
)
2198 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
2199 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2200 LDAPMessage
*result
;
2206 attr_list
= get_userattr_list( ldap_state
->schema_ver
);
2207 rc
= ldapsam_search_suffix_by_name(ldap_state
, sname
, &result
, attr_list
);
2208 free_attr_list( attr_list
);
2210 if ( rc
!= LDAP_SUCCESS
)
2211 return NT_STATUS_NO_SUCH_USER
;
2213 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
2217 ("Unable to locate user [%s] count=%d\n", sname
,
2219 return NT_STATUS_NO_SUCH_USER
;
2220 } else if (count
> 1) {
2222 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname
,
2224 return NT_STATUS_NO_SUCH_USER
;
2227 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
2229 if (!init_sam_from_ldap(ldap_state
, user
, entry
)) {
2230 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname
));
2231 ldap_msgfree(result
);
2232 return NT_STATUS_NO_SUCH_USER
;
2234 ldap_msgfree(result
);
2237 ldap_msgfree(result
);
2242 /**********************************************************************
2243 Get SAM_ACCOUNT entry from LDAP by SID
2244 *********************************************************************/
2245 static NTSTATUS
ldapsam_getsampwsid(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* user
, const DOM_SID
*sid
)
2247 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
2248 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2249 LDAPMessage
*result
;
2256 switch ( ldap_state
->schema_ver
)
2258 case SCHEMAVER_SAMBASAMACCOUNT
:
2259 attr_list
= get_userattr_list(ldap_state
->schema_ver
);
2260 rc
= ldapsam_search_suffix_by_sid(ldap_state
, sid
, &result
, attr_list
);
2261 free_attr_list( attr_list
);
2263 if ( rc
!= LDAP_SUCCESS
)
2264 return NT_STATUS_NO_SUCH_USER
;
2267 case SCHEMAVER_SAMBAACCOUNT
:
2270 if (!sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
)) {
2271 return NT_STATUS_NO_SUCH_USER
;
2274 attr_list
= get_userattr_list(ldap_state
->schema_ver
);
2275 rc
= ldapsam_search_suffix_by_rid(ldap_state
, rid
, &result
, attr_list
);
2276 free_attr_list( attr_list
);
2278 if ( rc
!= LDAP_SUCCESS
)
2279 return NT_STATUS_NO_SUCH_USER
;
2284 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
2289 ("Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string
, sid
),
2291 ldap_msgfree(result
);
2292 return NT_STATUS_NO_SUCH_USER
;
2297 ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string
, sid
),
2299 ldap_msgfree(result
);
2300 return NT_STATUS_NO_SUCH_USER
;
2303 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
2306 if (!init_sam_from_ldap(ldap_state
, user
, entry
)) {
2307 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
2308 ldap_msgfree(result
);
2309 return NT_STATUS_NO_SUCH_USER
;
2313 ldap_msgfree(result
);
2317 /********************************************************************
2318 Do the actual modification - also change a plaittext passord if
2320 **********************************************************************/
2322 static NTSTATUS
ldapsam_modify_entry(struct pdb_methods
*my_methods
,
2323 SAM_ACCOUNT
*newpwd
, char *dn
,
2324 LDAPMod
**mods
, int ldap_op
,
2325 BOOL (*need_update
)(const SAM_ACCOUNT
*,
2328 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2331 if (!my_methods
|| !newpwd
|| !dn
) {
2332 return NT_STATUS_INVALID_PARAMETER
;
2336 DEBUG(5,("mods is empty: nothing to modify\n"));
2337 /* may be password change below however */
2342 ldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectclass", LDAP_OBJ_ACCOUNT
);
2343 rc
= ldapsam_add(ldap_state
, dn
, mods
);
2345 case LDAP_MOD_REPLACE
:
2346 rc
= ldapsam_modify(ldap_state
, dn
,mods
);
2349 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op
));
2350 return NT_STATUS_INVALID_PARAMETER
;
2353 if (rc
!=LDAP_SUCCESS
) {
2354 char *ld_error
= NULL
;
2355 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
2358 ("failed to %s user dn= %s with: %s\n\t%s\n",
2359 ldap_op
== LDAP_MOD_ADD
? "add" : "modify",
2360 dn
, ldap_err2string(rc
),
2361 ld_error
?ld_error
:"unknown"));
2362 SAFE_FREE(ld_error
);
2363 return NT_STATUS_UNSUCCESSFUL
;
2367 if (!(pdb_get_acct_ctrl(newpwd
)&(ACB_WSTRUST
|ACB_SVRTRUST
|ACB_DOMTRUST
)) &&
2368 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF
) &&
2369 need_update(newpwd
, PDB_PLAINTEXT_PW
) &&
2370 (pdb_get_plaintext_passwd(newpwd
)!=NULL
)) {
2374 struct berval
*retdata
;
2375 char *utf8_password
;
2378 if (push_utf8_allocate(&utf8_password
, pdb_get_plaintext_passwd(newpwd
)) == (size_t)-1) {
2379 return NT_STATUS_NO_MEMORY
;
2382 if (push_utf8_allocate(&utf8_dn
, dn
) == (size_t)-1) {
2383 return NT_STATUS_NO_MEMORY
;
2386 if ((ber
= ber_alloc_t(LBER_USE_DER
))==NULL
) {
2387 DEBUG(0,("ber_alloc_t returns NULL\n"));
2388 SAFE_FREE(utf8_password
);
2389 return NT_STATUS_UNSUCCESSFUL
;
2392 ber_printf (ber
, "{");
2393 ber_printf (ber
, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID
, utf8_dn
);
2394 ber_printf (ber
, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW
, utf8_password
);
2395 ber_printf (ber
, "N}");
2397 if ((rc
= ber_flatten (ber
, &bv
))<0) {
2398 DEBUG(0,("ber_flatten returns a value <0\n"));
2401 SAFE_FREE(utf8_password
);
2402 return NT_STATUS_UNSUCCESSFUL
;
2406 SAFE_FREE(utf8_password
);
2409 if ((rc
= ldapsam_extended_operation(ldap_state
, LDAP_EXOP_MODIFY_PASSWD
,
2410 bv
, NULL
, NULL
, &retoid
, &retdata
))!=LDAP_SUCCESS
) {
2411 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
2412 pdb_get_username(newpwd
),ldap_err2string(rc
)));
2414 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd
)));
2415 #ifdef DEBUG_PASSWORD
2416 DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd
)));
2418 ber_bvfree(retdata
);
2419 ber_memfree(retoid
);
2423 return NT_STATUS_OK
;
2426 /**********************************************************************
2427 Delete entry from LDAP for username
2428 *********************************************************************/
2429 static NTSTATUS
ldapsam_delete_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* sam_acct
)
2431 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2434 LDAPMessage
*result
;
2440 DEBUG(0, ("sam_acct was NULL!\n"));
2441 return NT_STATUS_INVALID_PARAMETER
;
2444 sname
= pdb_get_username(sam_acct
);
2446 DEBUG (3, ("Deleting user %s from LDAP.\n", sname
));
2448 attr_list
= get_userattr_list( ldap_state
->schema_ver
);
2449 rc
= ldapsam_search_suffix_by_name(ldap_state
, sname
, &result
, attr_list
);
2451 if (rc
!= LDAP_SUCCESS
) {
2452 free_attr_list( attr_list
);
2453 return NT_STATUS_NO_SUCH_USER
;
2456 switch ( ldap_state
->schema_ver
)
2458 case SCHEMAVER_SAMBASAMACCOUNT
:
2459 fstrcpy( objclass
, LDAP_OBJ_SAMBASAMACCOUNT
);
2462 case SCHEMAVER_SAMBAACCOUNT
:
2463 fstrcpy( objclass
, LDAP_OBJ_SAMBAACCOUNT
);
2466 fstrcpy( objclass
, "UNKNOWN" );
2467 DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
2471 ret
= ldapsam_delete_entry(ldap_state
, result
, objclass
, attr_list
);
2472 ldap_msgfree(result
);
2473 free_attr_list( attr_list
);
2478 /**********************************************************************
2479 Helper function to determine for update_sam_account whether
2480 we need LDAP modification.
2481 *********************************************************************/
2482 static BOOL
element_is_changed(const SAM_ACCOUNT
*sampass
,
2483 enum pdb_elements element
)
2485 return IS_SAM_CHANGED(sampass
, element
);
2488 /**********************************************************************
2490 *********************************************************************/
2491 static NTSTATUS
ldapsam_update_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* newpwd
)
2493 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
2494 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2497 LDAPMessage
*result
;
2502 attr_list
= get_userattr_list(ldap_state
->schema_ver
);
2503 rc
= ldapsam_search_suffix_by_name(ldap_state
, pdb_get_username(newpwd
), &result
, attr_list
);
2504 free_attr_list( attr_list
);
2505 if (rc
!= LDAP_SUCCESS
)
2506 return NT_STATUS_UNSUCCESSFUL
;
2508 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) == 0) {
2509 DEBUG(0, ("No user to modify!\n"));
2510 ldap_msgfree(result
);
2511 return NT_STATUS_UNSUCCESSFUL
;
2514 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
2515 dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
2517 if (!init_ldap_from_sam(ldap_state
, entry
, &mods
, newpwd
,
2518 element_is_changed
)) {
2519 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2520 ldap_msgfree(result
);
2521 return NT_STATUS_UNSUCCESSFUL
;
2524 ldap_msgfree(result
);
2527 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2528 pdb_get_username(newpwd
)));
2529 ldap_mods_free(mods
, True
);
2530 return NT_STATUS_OK
;
2533 ret
= ldapsam_modify_entry(my_methods
,newpwd
,dn
,mods
,LDAP_MOD_REPLACE
, element_is_changed
);
2534 ldap_mods_free(mods
,True
);
2536 if (!NT_STATUS_IS_OK(ret
)) {
2537 char *ld_error
= NULL
;
2538 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
2540 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2541 pdb_get_username(newpwd
), ld_error
?ld_error
:"(unknwon)", ldap_err2string(rc
)));
2542 SAFE_FREE(ld_error
);
2546 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2547 pdb_get_username(newpwd
)));
2548 return NT_STATUS_OK
;
2551 /**********************************************************************
2552 Helper function to determine for update_sam_account whether
2553 we need LDAP modification.
2554 *********************************************************************/
2555 static BOOL
element_is_set_or_changed(const SAM_ACCOUNT
*sampass
,
2556 enum pdb_elements element
)
2558 return (IS_SAM_SET(sampass
, element
) ||
2559 IS_SAM_CHANGED(sampass
, element
));
2562 /**********************************************************************
2563 Add SAM_ACCOUNT to LDAP
2564 *********************************************************************/
2566 static NTSTATUS
ldapsam_add_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* newpwd
)
2568 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
2569 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2571 LDAPMessage
*result
= NULL
;
2572 LDAPMessage
*entry
= NULL
;
2574 LDAPMod
**mods
= NULL
;
2579 const char *username
= pdb_get_username(newpwd
);
2582 if (!username
|| !*username
) {
2583 DEBUG(0, ("Cannot add user without a username!\n"));
2584 return NT_STATUS_INVALID_PARAMETER
;
2587 /* free this list after the second search or in case we exit on failure */
2589 attr_list
= get_userattr_list(ldap_state
->schema_ver
);
2590 rc
= ldapsam_search_suffix_by_name (ldap_state
, username
, &result
, attr_list
);
2592 if (rc
!= LDAP_SUCCESS
) {
2593 free_attr_list( attr_list
);
2594 return NT_STATUS_UNSUCCESSFUL
;
2597 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) != 0) {
2598 DEBUG(0,("User '%s' already in the base, with samba attributes\n",
2600 ldap_msgfree(result
);
2601 free_attr_list( attr_list
);
2602 return NT_STATUS_UNSUCCESSFUL
;
2604 ldap_msgfree(result
);
2606 /* does the entry already exist but without a samba rttibutes?
2607 we don't really care what attributes are returned here */
2609 escape_user
= escape_ldap_string_alloc( username
);
2610 pstrcpy( filter
, lp_ldap_filter() );
2611 all_string_sub( filter
, "%u", escape_user
, sizeof(filter
) );
2612 SAFE_FREE( escape_user
);
2614 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr_list
, &result
);
2615 free_attr_list( attr_list
);
2617 if ( rc
!= LDAP_SUCCESS
)
2618 return NT_STATUS_UNSUCCESSFUL
;
2620 num_result
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
2622 if (num_result
> 1) {
2623 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2624 ldap_msgfree(result
);
2625 return NT_STATUS_UNSUCCESSFUL
;
2628 /* Check if we need to update an existing entry */
2629 if (num_result
== 1) {
2632 DEBUG(3,("User exists without samba attributes: adding them\n"));
2633 ldap_op
= LDAP_MOD_REPLACE
;
2634 entry
= ldap_first_entry (ldap_state
->ldap_struct
, result
);
2635 tmp
= ldap_get_dn (ldap_state
->ldap_struct
, entry
);
2636 slprintf (dn
, sizeof (dn
) - 1, "%s", tmp
);
2639 /* Check if we need to add an entry */
2640 DEBUG(3,("Adding new user\n"));
2641 ldap_op
= LDAP_MOD_ADD
;
2642 if (username
[strlen(username
)-1] == '$') {
2643 slprintf (dn
, sizeof (dn
) - 1, "uid=%s,%s", username
, lp_ldap_machine_suffix ());
2645 slprintf (dn
, sizeof (dn
) - 1, "uid=%s,%s", username
, lp_ldap_user_suffix ());
2649 if (!init_ldap_from_sam(ldap_state
, entry
, &mods
, newpwd
,
2650 element_is_set_or_changed
)) {
2651 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2652 ldap_msgfree(result
);
2653 return NT_STATUS_UNSUCCESSFUL
;
2656 ldap_msgfree(result
);
2659 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd
)));
2660 return NT_STATUS_UNSUCCESSFUL
;
2662 switch ( ldap_state
->schema_ver
)
2664 case SCHEMAVER_SAMBAACCOUNT
:
2665 ldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectclass", LDAP_OBJ_SAMBAACCOUNT
);
2667 case SCHEMAVER_SAMBASAMACCOUNT
:
2668 ldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT
);
2671 DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
2675 ret
= ldapsam_modify_entry(my_methods
,newpwd
,dn
,mods
,ldap_op
, element_is_set_or_changed
);
2676 if (NT_STATUS_IS_ERR(ret
)) {
2677 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2678 pdb_get_username(newpwd
),dn
));
2679 ldap_mods_free(mods
, True
);
2683 DEBUG(2,("added: uid == %s in the LDAP database\n", pdb_get_username(newpwd
)));
2684 ldap_mods_free(mods
, True
);
2686 return NT_STATUS_OK
;
2689 /**********************************************************************
2691 *********************************************************************/
2693 static void free_private_data(void **vp
)
2695 struct ldapsam_privates
**ldap_state
= (struct ldapsam_privates
**)vp
;
2697 ldapsam_close(*ldap_state
);
2699 if ((*ldap_state
)->bind_secret
) {
2700 memset((*ldap_state
)->bind_secret
, '\0', strlen((*ldap_state
)->bind_secret
));
2703 ldapsam_close(*ldap_state
);
2705 SAFE_FREE((*ldap_state
)->bind_dn
);
2706 SAFE_FREE((*ldap_state
)->bind_secret
);
2710 /* No need to free any further, as it is talloc()ed */
2713 /**********************************************************************
2714 *********************************************************************/
2716 static int ldapsam_search_one_group (struct ldapsam_privates
*ldap_state
,
2718 LDAPMessage
** result
)
2720 int scope
= LDAP_SCOPE_SUBTREE
;
2724 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter
));
2727 attr_list
= get_attr_list(groupmap_attr_list
);
2728 rc
= ldapsam_search(ldap_state
, lp_ldap_group_suffix (), scope
,
2729 filter
, attr_list
, 0, result
);
2730 free_attr_list( attr_list
);
2732 if (rc
!= LDAP_SUCCESS
) {
2733 char *ld_error
= NULL
;
2734 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
2736 DEBUG(0, ("ldapsam_search_one_group: "
2737 "Problem during the LDAP search: LDAP error: %s (%s)",
2738 ld_error
?ld_error
:"(unknown)", ldap_err2string(rc
)));
2739 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2740 lp_ldap_group_suffix(), filter
));
2741 SAFE_FREE(ld_error
);
2747 /**********************************************************************
2748 *********************************************************************/
2750 static BOOL
init_group_from_ldap(struct ldapsam_privates
*ldap_state
,
2751 GROUP_MAP
*map
, LDAPMessage
*entry
)
2755 if (ldap_state
== NULL
|| map
== NULL
|| entry
== NULL
||
2756 ldap_state
->ldap_struct
== NULL
)
2758 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2762 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2763 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GIDNUMBER
), temp
))
2765 DEBUG(0, ("Mandatory attribute %s not found\n",
2766 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_GIDNUMBER
)));
2769 DEBUG(2, ("Entry found for group: %s\n", temp
));
2771 map
->gid
= (gid_t
)atol(temp
);
2773 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2774 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_GROUP_SID
), temp
))
2776 DEBUG(0, ("Mandatory attribute %s not found\n",
2777 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_GROUP_SID
)));
2780 string_to_sid(&map
->sid
, temp
);
2782 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2783 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_GROUP_TYPE
), temp
))
2785 DEBUG(0, ("Mandatory attribute %s not found\n",
2786 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_GROUP_TYPE
)));
2789 map
->sid_name_use
= (uint32
)atol(temp
);
2791 if ((map
->sid_name_use
< SID_NAME_USER
) ||
2792 (map
->sid_name_use
> SID_NAME_UNKNOWN
)) {
2793 DEBUG(0, ("Unknown Group type: %d\n", map
->sid_name_use
));
2797 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2798 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_DISPLAY_NAME
), temp
))
2801 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2802 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_CN
), temp
))
2804 DEBUG(0, ("Attributes cn not found either "
2805 "for gidNumber(%i)\n",map
->gid
));
2809 fstrcpy(map
->nt_name
, temp
);
2811 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2812 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_DESC
), temp
))
2816 fstrcpy(map
->comment
, temp
);
2821 /**********************************************************************
2822 *********************************************************************/
2824 static BOOL
init_ldap_from_group(LDAP
*ldap_struct
,
2825 LDAPMessage
*existing
,
2827 const GROUP_MAP
*map
)
2831 if (mods
== NULL
|| map
== NULL
) {
2832 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2838 sid_to_string(tmp
, &map
->sid
);
2839 make_ldap_mod(ldap_struct
, existing
, mods
,
2840 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GROUP_SID
), tmp
);
2841 snprintf(tmp
, sizeof(tmp
)-1, "%i", map
->sid_name_use
);
2842 make_ldap_mod(ldap_struct
, existing
, mods
,
2843 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GROUP_TYPE
), tmp
);
2845 make_ldap_mod(ldap_struct
, existing
, mods
,
2846 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_DISPLAY_NAME
), map
->nt_name
);
2847 make_ldap_mod(ldap_struct
, existing
, mods
,
2848 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_DESC
), map
->comment
);
2853 /**********************************************************************
2854 *********************************************************************/
2856 static NTSTATUS
ldapsam_getgroup(struct pdb_methods
*methods
,
2860 struct ldapsam_privates
*ldap_state
=
2861 (struct ldapsam_privates
*)methods
->private_data
;
2862 LDAPMessage
*result
;
2866 if (ldapsam_search_one_group(ldap_state
, filter
, &result
)
2868 return NT_STATUS_NO_SUCH_GROUP
;
2871 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
2874 DEBUG(4, ("Did not find group for filter %s\n", filter
));
2875 return NT_STATUS_NO_SUCH_GROUP
;
2879 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2881 return NT_STATUS_NO_SUCH_GROUP
;
2884 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
2887 ldap_msgfree(result
);
2888 return NT_STATUS_UNSUCCESSFUL
;
2891 if (!init_group_from_ldap(ldap_state
, map
, entry
)) {
2892 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2894 ldap_msgfree(result
);
2895 return NT_STATUS_NO_SUCH_GROUP
;
2898 ldap_msgfree(result
);
2899 return NT_STATUS_OK
;
2902 /**********************************************************************
2903 *********************************************************************/
2905 static NTSTATUS
ldapsam_getgrsid(struct pdb_methods
*methods
, GROUP_MAP
*map
,
2910 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(%s=%s))",
2912 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GROUP_SID
),
2913 sid_string_static(&sid
));
2915 return ldapsam_getgroup(methods
, filter
, map
);
2918 /**********************************************************************
2919 *********************************************************************/
2921 static NTSTATUS
ldapsam_getgrgid(struct pdb_methods
*methods
, GROUP_MAP
*map
,
2926 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(%s=%d))",
2928 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GIDNUMBER
),
2931 return ldapsam_getgroup(methods
, filter
, map
);
2934 /**********************************************************************
2935 *********************************************************************/
2937 static NTSTATUS
ldapsam_getgrnam(struct pdb_methods
*methods
, GROUP_MAP
*map
,
2942 /* TODO: Escaping of name? */
2944 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
2946 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_DISPLAY_NAME
), name
,
2947 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_CN
), name
);
2949 return ldapsam_getgroup(methods
, filter
, map
);
2952 /**********************************************************************
2953 *********************************************************************/
2955 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates
*ldap_state
,
2957 LDAPMessage
**result
)
2961 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(%s=%i))",
2962 LDAP_OBJ_POSIXGROUP
,
2963 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GIDNUMBER
),
2966 return ldapsam_search_one_group(ldap_state
, filter
, result
);
2969 /**********************************************************************
2970 *********************************************************************/
2972 static NTSTATUS
ldapsam_add_group_mapping_entry(struct pdb_methods
*methods
,
2975 struct ldapsam_privates
*ldap_state
=
2976 (struct ldapsam_privates
*)methods
->private_data
;
2977 LDAPMessage
*result
= NULL
;
2978 LDAPMod
**mods
= NULL
;
2988 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods
, &dummy
,
2990 DEBUG(0, ("Group %i already exists in LDAP\n", map
->gid
));
2991 return NT_STATUS_UNSUCCESSFUL
;
2994 rc
= ldapsam_search_one_group_by_gid(ldap_state
, map
->gid
, &result
);
2995 if (rc
!= LDAP_SUCCESS
) {
2996 return NT_STATUS_UNSUCCESSFUL
;
2999 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) != 1) {
3000 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
3002 ldap_msgfree(result
);
3003 return NT_STATUS_UNSUCCESSFUL
;
3006 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
3007 tmp
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
3011 if (!init_ldap_from_group(ldap_state
->ldap_struct
,
3012 result
, &mods
, map
)) {
3013 DEBUG(0, ("init_ldap_from_group failed!\n"));
3014 ldap_mods_free(mods
, True
);
3015 ldap_msgfree(result
);
3016 return NT_STATUS_UNSUCCESSFUL
;
3019 ldap_msgfree(result
);
3022 DEBUG(0, ("mods is empty\n"));
3023 return NT_STATUS_UNSUCCESSFUL
;
3026 ldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectClass", LDAP_OBJ_GROUPMAP
);
3028 rc
= ldapsam_modify(ldap_state
, dn
, mods
);
3029 ldap_mods_free(mods
, True
);
3031 if (rc
!= LDAP_SUCCESS
) {
3032 char *ld_error
= NULL
;
3033 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
3035 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map
->gid
,
3036 ld_error
? ld_error
: "(unknown)", ldap_err2string(rc
)));
3037 SAFE_FREE(ld_error
);
3038 return NT_STATUS_UNSUCCESSFUL
;
3041 DEBUG(2, ("successfully modified group %i in LDAP\n", map
->gid
));
3042 return NT_STATUS_OK
;
3045 /**********************************************************************
3046 *********************************************************************/
3048 static NTSTATUS
ldapsam_update_group_mapping_entry(struct pdb_methods
*methods
,
3051 struct ldapsam_privates
*ldap_state
=
3052 (struct ldapsam_privates
*)methods
->private_data
;
3055 LDAPMessage
*result
;
3059 rc
= ldapsam_search_one_group_by_gid(ldap_state
, map
->gid
, &result
);
3061 if (rc
!= LDAP_SUCCESS
) {
3062 return NT_STATUS_UNSUCCESSFUL
;
3065 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) == 0) {
3066 DEBUG(0, ("No group to modify!\n"));
3067 ldap_msgfree(result
);
3068 return NT_STATUS_UNSUCCESSFUL
;
3071 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
3072 dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
3074 if (!init_ldap_from_group(ldap_state
->ldap_struct
,
3075 result
, &mods
, map
)) {
3076 DEBUG(0, ("init_ldap_from_group failed\n"));
3077 ldap_msgfree(result
);
3078 return NT_STATUS_UNSUCCESSFUL
;
3081 ldap_msgfree(result
);
3084 DEBUG(4, ("mods is empty: nothing to do\n"));
3085 return NT_STATUS_UNSUCCESSFUL
;
3088 rc
= ldapsam_modify(ldap_state
, dn
, mods
);
3090 ldap_mods_free(mods
, True
);
3092 if (rc
!= LDAP_SUCCESS
) {
3093 char *ld_error
= NULL
;
3094 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
3096 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map
->gid
,
3097 ld_error
? ld_error
: "(unknown)", ldap_err2string(rc
)));
3098 SAFE_FREE(ld_error
);
3101 DEBUG(2, ("successfully modified group %i in LDAP\n", map
->gid
));
3102 return NT_STATUS_OK
;
3105 /**********************************************************************
3106 *********************************************************************/
3108 static NTSTATUS
ldapsam_delete_group_mapping_entry(struct pdb_methods
*methods
,
3111 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)methods
->private_data
;
3112 pstring sidstring
, filter
;
3113 LDAPMessage
*result
;
3118 sid_to_string(sidstring
, &sid
);
3120 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(%s=%s))",
3121 LDAP_OBJ_GROUPMAP
, LDAP_ATTRIBUTE_SID
, sidstring
);
3123 rc
= ldapsam_search_one_group(ldap_state
, filter
, &result
);
3125 if (rc
!= LDAP_SUCCESS
) {
3126 return NT_STATUS_NO_SUCH_GROUP
;
3129 attr_list
= get_attr_list( groupmap_attr_list_to_delete
);
3130 ret
= ldapsam_delete_entry(ldap_state
, result
, LDAP_OBJ_GROUPMAP
, attr_list
);
3131 free_attr_list ( attr_list
);
3133 ldap_msgfree(result
);
3138 /**********************************************************************
3139 *********************************************************************/
3141 static NTSTATUS
ldapsam_setsamgrent(struct pdb_methods
*my_methods
, BOOL update
)
3143 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
3148 snprintf( filter
, sizeof(filter
)-1, "(objectclass=%s)", LDAP_OBJ_GROUPMAP
);
3149 attr_list
= get_attr_list( groupmap_attr_list
);
3150 rc
= ldapsam_search(ldap_state
, lp_ldap_group_suffix(),
3151 LDAP_SCOPE_SUBTREE
, filter
,
3152 attr_list
, 0, &ldap_state
->result
);
3153 free_attr_list( attr_list
);
3155 if (rc
!= LDAP_SUCCESS
) {
3156 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc
)));
3157 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_group_suffix(), filter
));
3158 ldap_msgfree(ldap_state
->result
);
3159 ldap_state
->result
= NULL
;
3160 return NT_STATUS_UNSUCCESSFUL
;
3163 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
3164 ldap_count_entries(ldap_state
->ldap_struct
,
3165 ldap_state
->result
)));
3167 ldap_state
->entry
= ldap_first_entry(ldap_state
->ldap_struct
, ldap_state
->result
);
3168 ldap_state
->index
= 0;
3170 return NT_STATUS_OK
;
3173 /**********************************************************************
3174 *********************************************************************/
3176 static void ldapsam_endsamgrent(struct pdb_methods
*my_methods
)
3178 ldapsam_endsampwent(my_methods
);
3181 /**********************************************************************
3182 *********************************************************************/
3184 static NTSTATUS
ldapsam_getsamgrent(struct pdb_methods
*my_methods
,
3187 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
3188 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
3191 /* The rebind proc needs this *HACK*. We are not multithreaded, so
3192 this will work, but it's not nice. */
3193 static_ldap_state
= ldap_state
;
3196 if (!ldap_state
->entry
)
3199 ldap_state
->index
++;
3200 bret
= init_group_from_ldap(ldap_state
, map
, ldap_state
->entry
);
3202 ldap_state
->entry
= ldap_next_entry(ldap_state
->ldap_struct
,
3206 return NT_STATUS_OK
;
3209 /**********************************************************************
3210 *********************************************************************/
3212 static NTSTATUS
ldapsam_enum_group_mapping(struct pdb_methods
*methods
,
3213 enum SID_NAME_USE sid_name_use
,
3214 GROUP_MAP
**rmap
, int *num_entries
,
3225 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods
, False
))) {
3226 DEBUG(0, ("Unable to open passdb\n"));
3227 return NT_STATUS_ACCESS_DENIED
;
3230 while (NT_STATUS_IS_OK(nt_status
= ldapsam_getsamgrent(methods
, &map
))) {
3231 if (sid_name_use
!= SID_NAME_UNKNOWN
&&
3232 sid_name_use
!= map
.sid_name_use
) {
3233 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map
.nt_name
));
3236 if (unix_only
==ENUM_ONLY_MAPPED
&& map
.gid
==-1) {
3237 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map
.nt_name
));
3241 mapt
=(GROUP_MAP
*)Realloc((*rmap
), (entries
+1)*sizeof(GROUP_MAP
));
3243 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
3245 return NT_STATUS_UNSUCCESSFUL
;
3250 mapt
[entries
] = map
;
3255 ldapsam_endsamgrent(methods
);
3257 *num_entries
= entries
;
3259 return NT_STATUS_OK
;
3262 /**********************************************************************
3263 *********************************************************************/
3265 static NTSTATUS
pdb_init_ldapsam_common(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
,
3266 const char *location
)
3269 struct ldapsam_privates
*ldap_state
;
3271 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_methods(pdb_context
->mem_ctx
, pdb_method
))) {
3275 (*pdb_method
)->name
= "ldapsam";
3277 (*pdb_method
)->setsampwent
= ldapsam_setsampwent
;
3278 (*pdb_method
)->endsampwent
= ldapsam_endsampwent
;
3279 (*pdb_method
)->getsampwent
= ldapsam_getsampwent
;
3280 (*pdb_method
)->getsampwnam
= ldapsam_getsampwnam
;
3281 (*pdb_method
)->getsampwsid
= ldapsam_getsampwsid
;
3282 (*pdb_method
)->add_sam_account
= ldapsam_add_sam_account
;
3283 (*pdb_method
)->update_sam_account
= ldapsam_update_sam_account
;
3284 (*pdb_method
)->delete_sam_account
= ldapsam_delete_sam_account
;
3286 (*pdb_method
)->getgrsid
= ldapsam_getgrsid
;
3287 (*pdb_method
)->getgrgid
= ldapsam_getgrgid
;
3288 (*pdb_method
)->getgrnam
= ldapsam_getgrnam
;
3289 (*pdb_method
)->add_group_mapping_entry
= ldapsam_add_group_mapping_entry
;
3290 (*pdb_method
)->update_group_mapping_entry
= ldapsam_update_group_mapping_entry
;
3291 (*pdb_method
)->delete_group_mapping_entry
= ldapsam_delete_group_mapping_entry
;
3292 (*pdb_method
)->enum_group_mapping
= ldapsam_enum_group_mapping
;
3294 /* TODO: Setup private data and free */
3296 ldap_state
= talloc_zero(pdb_context
->mem_ctx
, sizeof(struct ldapsam_privates
));
3299 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
3300 return NT_STATUS_NO_MEMORY
;
3304 ldap_state
->uri
= talloc_strdup(pdb_context
->mem_ctx
, location
);
3306 ldap_state
->uri
= "ldap://localhost";
3309 ldap_state
->domain_name
= talloc_strdup(pdb_context
->mem_ctx
, get_global_sam_name());
3310 if (!ldap_state
->domain_name
) {
3311 return NT_STATUS_NO_MEMORY
;
3314 sid_copy(&ldap_state
->domain_sid
, get_global_sam_sid());
3316 (*pdb_method
)->private_data
= ldap_state
;
3318 (*pdb_method
)->free_private_data
= free_private_data
;
3320 return NT_STATUS_OK
;
3323 /**********************************************************************
3324 *********************************************************************/
3326 static NTSTATUS
pdb_init_ldapsam_compat(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
, const char *location
)
3329 struct ldapsam_privates
*ldap_state
;
3331 if (!NT_STATUS_IS_OK(nt_status
= pdb_init_ldapsam_common(pdb_context
, pdb_method
, location
))) {
3335 (*pdb_method
)->name
= "ldapsam_compat";
3337 ldap_state
= (*pdb_method
)->private_data
;
3338 ldap_state
->schema_ver
= SCHEMAVER_SAMBAACCOUNT
;
3341 ldap_state
->uri
= talloc_strdup(pdb_context
->mem_ctx
, location
);
3343 #ifndef WITH_LDAP_SAMCONFIG
3344 ldap_state
->uri
= "ldap://localhost";
3346 int ldap_port
= lp_ldap_port();
3348 /* remap default port if not using SSL (ie clear or TLS) */
3349 if ( (lp_ldap_ssl() != LDAP_SSL_ON
) && (ldap_port
== 636) ) {
3353 ldap_state
->uri
= talloc_asprintf(pdb_context
->mem_ctx
, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON
? "ldaps" : "ldap", lp_ldap_server(), ldap_port
);
3354 if (!ldap_state
->uri
) {
3355 return NT_STATUS_NO_MEMORY
;
3360 return NT_STATUS_OK
;
3363 /**********************************************************************
3364 *********************************************************************/
3366 static NTSTATUS
pdb_init_ldapsam(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
, const char *location
)
3369 struct ldapsam_privates
*ldap_state
;
3370 uint32 low_idmap_uid
, high_idmap_uid
;
3371 uint32 low_idmap_gid
, high_idmap_gid
;
3373 if (!NT_STATUS_IS_OK(nt_status
= pdb_init_ldapsam_common(pdb_context
, pdb_method
, location
))) {
3377 (*pdb_method
)->name
= "ldapsam";
3379 ldap_state
= (*pdb_method
)->private_data
;
3380 ldap_state
->schema_ver
= SCHEMAVER_SAMBASAMACCOUNT
;
3381 ldap_state
->permit_non_unix_accounts
= False
;
3383 /* check for non-unix account ranges */
3385 if (lp_idmap_uid(&low_idmap_uid
, &high_idmap_uid
)
3386 && lp_idmap_gid(&low_idmap_gid
, &high_idmap_gid
))
3388 DEBUG(2, ("Enabling non-unix account ranges\n"));
3390 ldap_state
->permit_non_unix_accounts
= True
;
3392 ldap_state
->low_allocated_user_rid
= fallback_pdb_uid_to_user_rid(low_idmap_uid
);
3393 ldap_state
->high_allocated_user_rid
= fallback_pdb_uid_to_user_rid(high_idmap_uid
);
3394 ldap_state
->low_allocated_group_rid
= pdb_gid_to_group_rid(low_idmap_gid
);
3395 ldap_state
->high_allocated_group_rid
= pdb_gid_to_group_rid(high_idmap_gid
);
3398 return NT_STATUS_OK
;
3401 NTSTATUS
pdb_ldap_init(void)
3404 if (!NT_STATUS_IS_OK(nt_status
= smb_register_passdb(PASSDB_INTERFACE_VERSION
, "ldapsam", pdb_init_ldapsam
)))
3407 if (!NT_STATUS_IS_OK(nt_status
= smb_register_passdb(PASSDB_INTERFACE_VERSION
, "ldapsam_compat", pdb_init_ldapsam_compat
)))
3410 return NT_STATUS_OK
;