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
59 #define SAM_ACCOUNT struct sam_passwd
62 struct ldapsam_privates
{
70 /* retrive-once info */
72 const char *domain_name
;
75 /* configuration items */
78 BOOL permit_non_unix_accounts
;
80 uint32 low_allocated_user_rid
;
81 uint32 high_allocated_user_rid
;
83 uint32 low_allocated_group_rid
;
84 uint32 high_allocated_group_rid
;
89 unsigned int num_failures
;
92 #define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */
94 static struct ldapsam_privates
*static_ldap_state
;
96 /* specify schema versions between 2.2. and 3.0 */
98 #define SCHEMAVER_SAMBAACCOUNT 1
99 #define SCHEMAVER_SAMBASAMACCOUNT 2
101 /* objectclass names */
103 #define LDAP_OBJ_SAMBASAMACCOUNT "sambaSamAccount"
104 #define LDAP_OBJ_SAMBAACCOUNT "sambaAccount"
105 #define LDAP_OBJ_GROUPMAP "sambaGroupMapping"
106 #define LDAP_OBJ_DOMINFO "sambaDomain"
108 #define LDAP_OBJ_ACCOUNT "account"
109 #define LDAP_OBJ_POSIXACCOUNT "posixAccount"
110 #define LDAP_OBJ_POSIXGROUP "posixGroup"
112 /* some generic attributes that get reused a lot */
114 #define LDAP_ATTRIBUTE_SID "sambaSID"
116 /* attribute map table indexes */
118 #define LDAP_ATTR_LIST_END 0
119 #define LDAP_ATTR_UID 1
120 #define LDAP_ATTR_UIDNUMBER 2
121 #define LDAP_ATTR_GIDNUMBER 3
122 #define LDAP_ATTR_UNIX_HOME 4
123 #define LDAP_ATTR_PWD_LAST_SET 5
124 #define LDAP_ATTR_PWD_CAN_CHANGE 6
125 #define LDAP_ATTR_PWD_MUST_CHANGE 7
126 #define LDAP_ATTR_LOGON_TIME 8
127 #define LDAP_ATTR_LOGOFF_TIME 9
128 #define LDAP_ATTR_KICKOFF_TIME 10
129 #define LDAP_ATTR_CN 11
130 #define LDAP_ATTR_DISPLAY_NAME 12
131 #define LDAP_ATTR_HOME_PATH 13
132 #define LDAP_ATTR_LOGON_SCRIPT 14
133 #define LDAP_ATTR_PROFILE_PATH 15
134 #define LDAP_ATTR_DESC 16
135 #define LDAP_ATTR_USER_WKS 17
136 #define LDAP_ATTR_USER_SID 18
137 #define LDAP_ATTR_USER_RID 18
138 #define LDAP_ATTR_PRIMARY_GROUP_SID 19
139 #define LDAP_ATTR_PRIMARY_GROUP_RID 20
140 #define LDAP_ATTR_LMPW 21
141 #define LDAP_ATTR_NTPW 22
142 #define LDAP_ATTR_DOMAIN 23
143 #define LDAP_ATTR_OBJCLASS 24
144 #define LDAP_ATTR_ACB_INFO 25
145 #define LDAP_ATTR_NEXT_USERRID 26
146 #define LDAP_ATTR_NEXT_GROUPRID 27
147 #define LDAP_ATTR_DOM_SID 28
148 #define LDAP_ATTR_HOME_DRIVE 29
149 #define LDAP_ATTR_GROUP_SID 30
150 #define LDAP_ATTR_GROUP_TYPE 31
153 typedef struct _attrib_map_entry
{
159 /* attributes used by Samba 2.2 */
161 static ATTRIB_MAP_ENTRY attrib_map_v22
[] = {
162 { LDAP_ATTR_UID
, "uid" },
163 { LDAP_ATTR_UIDNUMBER
, "uidNumber" },
164 { LDAP_ATTR_GIDNUMBER
, "gidNumber" },
165 { LDAP_ATTR_UNIX_HOME
, "homeDirectory" },
166 { LDAP_ATTR_PWD_LAST_SET
, "pwdLastSet" },
167 { LDAP_ATTR_PWD_CAN_CHANGE
, "pwdCanChange" },
168 { LDAP_ATTR_PWD_MUST_CHANGE
, "pwdMustChange" },
169 { LDAP_ATTR_LOGON_TIME
, "logonTime" },
170 { LDAP_ATTR_LOGOFF_TIME
, "logoffTime" },
171 { LDAP_ATTR_KICKOFF_TIME
, "kickoffTime" },
172 { LDAP_ATTR_CN
, "cn" },
173 { LDAP_ATTR_DISPLAY_NAME
, "displayName" },
174 { LDAP_ATTR_HOME_PATH
, "smbHome" },
175 { LDAP_ATTR_HOME_DRIVE
, "homeDrives" },
176 { LDAP_ATTR_LOGON_SCRIPT
, "scriptPath" },
177 { LDAP_ATTR_PROFILE_PATH
, "profilePath" },
178 { LDAP_ATTR_DESC
, "description" },
179 { LDAP_ATTR_USER_WKS
, "userWorkstations"},
180 { LDAP_ATTR_USER_RID
, "rid" },
181 { LDAP_ATTR_PRIMARY_GROUP_RID
, "primaryGroupID"},
182 { LDAP_ATTR_LMPW
, "lmPassword" },
183 { LDAP_ATTR_NTPW
, "ntPassword" },
184 { LDAP_ATTR_DOMAIN
, "domain" },
185 { LDAP_ATTR_OBJCLASS
, "objectClass" },
186 { LDAP_ATTR_ACB_INFO
, "acctFlags" },
187 { LDAP_ATTR_LIST_END
, NULL
}
190 /* attributes used by Samba 3.0's sambaSamAccount */
192 static ATTRIB_MAP_ENTRY attrib_map_v30
[] = {
193 { LDAP_ATTR_UID
, "uid" },
194 { LDAP_ATTR_UIDNUMBER
, "uidNumber" },
195 { LDAP_ATTR_GIDNUMBER
, "gidNumber" },
196 { LDAP_ATTR_UNIX_HOME
, "homeDirectory" },
197 { LDAP_ATTR_PWD_LAST_SET
, "sambaPwdLastSet" },
198 { LDAP_ATTR_PWD_CAN_CHANGE
, "sambaPwdCanChange" },
199 { LDAP_ATTR_PWD_MUST_CHANGE
, "sambaPwdMustChange" },
200 { LDAP_ATTR_LOGON_TIME
, "sambaLogonTime" },
201 { LDAP_ATTR_LOGOFF_TIME
, "sambaLogoffTime" },
202 { LDAP_ATTR_KICKOFF_TIME
, "sambaKickoffTime" },
203 { LDAP_ATTR_CN
, "cn" },
204 { LDAP_ATTR_DISPLAY_NAME
, "displayName" },
205 { LDAP_ATTR_HOME_DRIVE
, "sambaHoneDrive" },
206 { LDAP_ATTR_HOME_PATH
, "sambaHomePath" },
207 { LDAP_ATTR_LOGON_SCRIPT
, "sambaLogonScript" },
208 { LDAP_ATTR_PROFILE_PATH
, "sambaProfilePath" },
209 { LDAP_ATTR_DESC
, "description" },
210 { LDAP_ATTR_USER_WKS
, "sambaUserWorkstations" },
211 { LDAP_ATTR_USER_SID
, "sambaSID" },
212 { LDAP_ATTR_PRIMARY_GROUP_SID
, "sambaPrimaryGroupSID" },
213 { LDAP_ATTR_LMPW
, "sambaLMPassword" },
214 { LDAP_ATTR_NTPW
, "sambaNTPassword" },
215 { LDAP_ATTR_DOMAIN
, "sambaDomainName" },
216 { LDAP_ATTR_OBJCLASS
, "objectClass" },
217 { LDAP_ATTR_ACB_INFO
, "sambaAcctFlags" },
218 { LDAP_ATTR_LIST_END
, NULL
}
221 /* attributes used for alalocating RIDs */
223 static ATTRIB_MAP_ENTRY dominfo_attr_list
[] = {
224 { LDAP_ATTR_DOMAIN
, "sambaDomainName" },
225 { LDAP_ATTR_NEXT_USERRID
, "sambaNextUserRid" },
226 { LDAP_ATTR_NEXT_GROUPRID
, "sambaNextGroupRid" },
227 { LDAP_ATTR_DOM_SID
, "sambaSID" },
228 { LDAP_ATTR_LIST_END
, NULL
},
231 /* Samba 3.0 group mapping attributes */
233 static ATTRIB_MAP_ENTRY groupmap_attr_list
[] = {
234 { LDAP_ATTR_GIDNUMBER
, "gidNumber" },
235 { LDAP_ATTR_GROUP_SID
, "sambaSID" },
236 { LDAP_ATTR_GROUP_TYPE
, "sambaGroupType" },
237 { LDAP_ATTR_DESC
, "description" },
238 { LDAP_ATTR_DISPLAY_NAME
, "displayName" },
239 { LDAP_ATTR_CN
, "cn" },
240 { LDAP_ATTR_LIST_END
, NULL
}
243 static ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete
[] = {
244 { LDAP_ATTR_GROUP_SID
, "sambaSID" },
245 { LDAP_ATTR_GROUP_TYPE
, "sambaGroupType" },
246 { LDAP_ATTR_DESC
, "description" },
247 { LDAP_ATTR_DISPLAY_NAME
, "displayName" },
248 { LDAP_ATTR_LIST_END
, NULL
}
251 /**********************************************************************
252 perform a simple table lookup and return the attribute name
253 **********************************************************************/
255 static const char* get_attr_key2string( ATTRIB_MAP_ENTRY table
[], int key
)
259 while ( table
[i
].attrib
!= LDAP_ATTR_LIST_END
) {
260 if ( table
[i
].attrib
== key
)
261 return table
[i
].name
;
268 /**********************************************************************
269 get the attribute name given a user schame version
270 **********************************************************************/
272 static const char* get_userattr_key2string( int schema_ver
, int key
)
274 switch ( schema_ver
)
276 case SCHEMAVER_SAMBAACCOUNT
:
277 return get_attr_key2string( attrib_map_v22
, key
);
279 case SCHEMAVER_SAMBASAMACCOUNT
:
280 return get_attr_key2string( attrib_map_v30
, key
);
283 DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
289 /**********************************************************************
290 Return the list of attribute names from a mapping table
291 **********************************************************************/
293 static char** get_attr_list( ATTRIB_MAP_ENTRY table
[] )
298 while ( table
[i
].attrib
!= LDAP_ATTR_LIST_END
)
302 names
= (char**)malloc( sizeof(char*)*i
);
304 DEBUG(0,("get_attr_list: out of memory\n"));
309 while ( table
[i
].attrib
!= LDAP_ATTR_LIST_END
) {
310 names
[i
] = strdup( table
[i
].name
);
318 /*********************************************************************
320 ********************************************************************/
322 static void free_attr_list( char **list
)
330 SAFE_FREE( list
[i
] );
335 /**********************************************************************
336 return the list of attribute names given a user schema version
337 **********************************************************************/
339 static char** get_userattr_list( int schema_ver
)
341 switch ( schema_ver
)
343 case SCHEMAVER_SAMBAACCOUNT
:
344 return get_attr_list( attrib_map_v22
);
346 case SCHEMAVER_SAMBASAMACCOUNT
:
347 return get_attr_list( attrib_map_v30
);
349 DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
356 /*******************************************************************
357 find the ldap password
358 ******************************************************************/
359 static BOOL
fetch_ldapsam_pw(char **dn
, char** pw
)
364 *dn
= smb_xstrdup(lp_ldap_admin_dn());
366 if (asprintf(&key
, "%s/%s", SECRETS_LDAP_BIND_PW
, *dn
) < 0) {
368 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
371 *pw
=secrets_fetch(key
, &size
);
375 /* Upgrade 2.2 style entry */
377 char* old_style_key
= strdup(*dn
);
379 fstring old_style_pw
;
381 if (!old_style_key
) {
382 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
386 for (p
=old_style_key
; *p
; p
++)
387 if (*p
== ',') *p
= '/';
389 data
=secrets_fetch(old_style_key
, &size
);
390 if (!size
&& size
< sizeof(old_style_pw
)) {
391 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
392 SAFE_FREE(old_style_key
);
397 strncpy(old_style_pw
, data
, size
);
398 old_style_pw
[size
] = 0;
402 if (!secrets_store_ldap_pw(*dn
, old_style_pw
)) {
403 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
404 SAFE_FREE(old_style_key
);
408 if (!secrets_delete(old_style_key
)) {
409 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
412 SAFE_FREE(old_style_key
);
414 *pw
= smb_xstrdup(old_style_pw
);
420 /*******************************************************************
421 open a connection to the ldap server.
422 ******************************************************************/
423 static int ldapsam_open_connection (struct ldapsam_privates
*ldap_state
, LDAP
** ldap_struct
)
425 int rc
= LDAP_SUCCESS
;
427 BOOL ldap_v3
= False
;
429 #ifdef HAVE_LDAP_INITIALIZE
430 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state
->uri
));
432 if ((rc
= ldap_initialize(ldap_struct
, ldap_state
->uri
)) != LDAP_SUCCESS
) {
433 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc
)));
439 /* Parse the string manually */
445 const char *p
= ldap_state
->uri
;
446 SMB_ASSERT(sizeof(protocol
)>10 && sizeof(host
)>254);
448 /* skip leading "URL:" (if any) */
449 if ( strncasecmp( p
, "URL:", 4 ) == 0 ) {
453 sscanf(p
, "%10[^:]://%254s[^:]:%d", protocol
, host
, &port
);
456 if (strequal(protocol
, "ldap")) {
458 } else if (strequal(protocol
, "ldaps")) {
461 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol
));
465 if ((*ldap_struct
= ldap_init(host
, port
)) == NULL
) {
466 DEBUG(0, ("ldap_init failed !\n"));
467 return LDAP_OPERATIONS_ERROR
;
470 if (strequal(protocol
, "ldaps")) {
471 #ifdef LDAP_OPT_X_TLS
472 int tls
= LDAP_OPT_X_TLS_HARD
;
473 if (ldap_set_option (*ldap_struct
, LDAP_OPT_X_TLS
, &tls
) != LDAP_SUCCESS
)
475 DEBUG(0, ("Failed to setup a TLS session\n"));
478 DEBUG(3,("LDAPS option set...!\n"));
480 DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
481 return LDAP_OPERATIONS_ERROR
;
487 if (ldap_get_option(*ldap_struct
, LDAP_OPT_PROTOCOL_VERSION
, &version
) == LDAP_OPT_SUCCESS
)
489 if (version
!= LDAP_VERSION3
)
491 version
= LDAP_VERSION3
;
492 if (ldap_set_option (*ldap_struct
, LDAP_OPT_PROTOCOL_VERSION
, &version
) == LDAP_OPT_SUCCESS
) {
500 if (lp_ldap_ssl() == LDAP_SSL_START_TLS
) {
501 #ifdef LDAP_OPT_X_TLS
503 if ((rc
= ldap_start_tls_s (*ldap_struct
, NULL
, NULL
)) != LDAP_SUCCESS
)
505 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
506 ldap_err2string(rc
)));
509 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
512 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
513 return LDAP_OPERATIONS_ERROR
;
516 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
517 return LDAP_OPERATIONS_ERROR
;
521 DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
526 /*******************************************************************
527 a rebind function for authenticated referrals
528 This version takes a void* that we can shove useful stuff in :-)
529 ******************************************************************/
530 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
532 static int rebindproc_with_state (LDAP
* ld
, char **whop
, char **credp
,
533 int *methodp
, int freeit
, void *arg
)
535 struct ldapsam_privates
*ldap_state
= arg
;
537 /** @TODO Should we be doing something to check what servers we rebind to?
538 Could we get a referral to a machine that we don't want to give our
539 username and password to? */
543 memset(*credp
, '\0', strlen(*credp
));
546 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
547 ldap_state
->bind_dn
));
549 *whop
= strdup(ldap_state
->bind_dn
);
551 return LDAP_NO_MEMORY
;
553 *credp
= strdup(ldap_state
->bind_secret
);
556 return LDAP_NO_MEMORY
;
558 *methodp
= LDAP_AUTH_SIMPLE
;
562 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
564 /*******************************************************************
565 a rebind function for authenticated referrals
566 This version takes a void* that we can shove useful stuff in :-)
567 and actually does the connection.
568 ******************************************************************/
569 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
570 static int rebindproc_connect_with_state (LDAP
*ldap_struct
,
571 LDAP_CONST
char *url
,
573 ber_int_t msgid
, void *arg
)
575 struct ldapsam_privates
*ldap_state
= arg
;
577 DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
578 ldap_state
->bind_dn
));
580 /** @TODO Should we be doing something to check what servers we rebind to?
581 Could we get a referral to a machine that we don't want to give our
582 username and password to? */
584 rc
= ldap_simple_bind_s(ldap_struct
, ldap_state
->bind_dn
, ldap_state
->bind_secret
);
588 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
590 /*******************************************************************
591 Add a rebind function for authenticated referrals
592 ******************************************************************/
593 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
595 # if LDAP_SET_REBIND_PROC_ARGS == 2
596 static int rebindproc (LDAP
*ldap_struct
, char **whop
, char **credp
,
597 int *method
, int freeit
)
599 return rebindproc_with_state(ldap_struct
, whop
, credp
,
600 method
, freeit
, static_ldap_state
);
603 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
604 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
606 /*******************************************************************
607 a rebind function for authenticated referrals
608 this also does the connection, but no void*.
609 ******************************************************************/
610 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
611 # if LDAP_SET_REBIND_PROC_ARGS == 2
612 static int rebindproc_connect (LDAP
* ld
, LDAP_CONST
char *url
, int request
,
615 return rebindproc_connect_with_state(ld
, url
, (ber_tag_t
)request
, msgid
,
618 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
619 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
621 /*******************************************************************
622 connect to the ldap server under system privilege.
623 ******************************************************************/
624 static int ldapsam_connect_system(struct ldapsam_privates
*ldap_state
, LDAP
* ldap_struct
)
630 /* The rebind proc needs this *HACK*. We are not multithreaded, so
631 this will work, but it's not nice. */
632 static_ldap_state
= ldap_state
;
634 /* get the password */
635 if (!fetch_ldapsam_pw(&ldap_dn
, &ldap_secret
))
637 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
638 return LDAP_INVALID_CREDENTIALS
;
641 ldap_state
->bind_dn
= ldap_dn
;
642 ldap_state
->bind_secret
= ldap_secret
;
644 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
645 (OpenLDAP) doesnt' seem to support it */
647 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
648 ldap_state
->uri
, ldap_dn
));
650 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
651 # if LDAP_SET_REBIND_PROC_ARGS == 2
652 ldap_set_rebind_proc(ldap_struct
, &rebindproc_connect
);
654 # if LDAP_SET_REBIND_PROC_ARGS == 3
655 ldap_set_rebind_proc(ldap_struct
, &rebindproc_connect_with_state
, (void *)ldap_state
);
657 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
658 # if LDAP_SET_REBIND_PROC_ARGS == 2
659 ldap_set_rebind_proc(ldap_struct
, &rebindproc
);
661 # if LDAP_SET_REBIND_PROC_ARGS == 3
662 ldap_set_rebind_proc(ldap_struct
, &rebindproc_with_state
, (void *)ldap_state
);
664 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
666 rc
= ldap_simple_bind_s(ldap_struct
, ldap_dn
, ldap_secret
);
668 if (rc
!= LDAP_SUCCESS
) {
669 char *ld_error
= NULL
;
670 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
672 DEBUG(ldap_state
->num_failures
? 2 : 0,
673 ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
674 ldap_dn
? ld_error
: "(unknown)", ldap_err2string(rc
),
677 ldap_state
->num_failures
++;
681 ldap_state
->num_failures
= 0;
683 DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
687 /**********************************************************************
688 Connect to LDAP server
689 *********************************************************************/
690 static int ldapsam_open(struct ldapsam_privates
*ldap_state
)
693 SMB_ASSERT(ldap_state
);
695 #ifndef NO_LDAP_SECURITY
696 if (geteuid() != 0) {
697 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
698 return LDAP_INSUFFICIENT_ACCESS
;
702 if ((ldap_state
->ldap_struct
!= NULL
) && ((ldap_state
->last_ping
+ LDAPSAM_DONT_PING_TIME
) < time(NULL
))) {
703 struct sockaddr_un addr
;
704 socklen_t len
= sizeof(addr
);
706 if (ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_DESC
, &sd
) == 0 &&
707 getpeername(sd
, (struct sockaddr
*) &addr
, &len
) < 0) {
708 /* the other end has died. reopen. */
709 ldap_unbind_ext(ldap_state
->ldap_struct
, NULL
, NULL
);
710 ldap_state
->ldap_struct
= NULL
;
711 ldap_state
->last_ping
= (time_t)0;
713 ldap_state
->last_ping
= time(NULL
);
717 if (ldap_state
->ldap_struct
!= NULL
) {
718 DEBUG(5,("ldapsam_open: already connected to the LDAP server\n"));
722 if ((rc
= ldapsam_open_connection(ldap_state
, &ldap_state
->ldap_struct
))) {
726 if ((rc
= ldapsam_connect_system(ldap_state
, ldap_state
->ldap_struct
))) {
727 ldap_unbind_ext(ldap_state
->ldap_struct
, NULL
, NULL
);
728 ldap_state
->ldap_struct
= NULL
;
733 ldap_state
->last_ping
= time(NULL
);
734 DEBUG(4,("The LDAP server is succesful connected\n"));
739 /**********************************************************************
740 Disconnect from LDAP server
741 *********************************************************************/
742 static NTSTATUS
ldapsam_close(struct ldapsam_privates
*ldap_state
)
745 return NT_STATUS_INVALID_PARAMETER
;
747 if (ldap_state
->ldap_struct
!= NULL
) {
748 ldap_unbind_ext(ldap_state
->ldap_struct
, NULL
, NULL
);
749 ldap_state
->ldap_struct
= NULL
;
752 DEBUG(5,("The connection to the LDAP server was closed\n"));
753 /* maybe free the results here --metze */
758 static int ldapsam_retry_open(struct ldapsam_privates
*ldap_state
, int *attempts
)
762 SMB_ASSERT(ldap_state
&& attempts
);
764 if (*attempts
!= 0) {
765 unsigned int sleep_time
;
768 /* Sleep for a random timeout */
769 rand_byte
= (char)(sys_random());
771 sleep_time
= (((*attempts
)*(*attempts
))/2)*rand_byte
*2;
772 /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
775 DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n",
781 if ((rc
= ldapsam_open(ldap_state
))) {
782 DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts
));
790 /*********************************************************************
791 ********************************************************************/
793 static int ldapsam_search(struct ldapsam_privates
*ldap_state
,
794 const char *base
, int scope
, const char *filter
,
795 char *attrs
[], int attrsonly
,
798 int rc
= LDAP_SERVER_DOWN
;
802 SMB_ASSERT(ldap_state
);
804 if (push_utf8_allocate(&utf8_filter
, filter
) == (size_t)-1) {
805 return LDAP_NO_MEMORY
;
808 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
810 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
813 rc
= ldap_search_s(ldap_state
->ldap_struct
, base
, scope
,
814 utf8_filter
, attrs
, attrsonly
, res
);
817 if (rc
== LDAP_SERVER_DOWN
) {
818 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
819 ldapsam_close(ldap_state
);
822 SAFE_FREE(utf8_filter
);
826 static int ldapsam_modify(struct ldapsam_privates
*ldap_state
, const char *dn
, LDAPMod
*attrs
[])
828 int rc
= LDAP_SERVER_DOWN
;
832 SMB_ASSERT(ldap_state
);
834 if (push_utf8_allocate(&utf8_dn
, dn
) == (size_t)-1) {
835 return LDAP_NO_MEMORY
;
838 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
840 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
843 rc
= ldap_modify_s(ldap_state
->ldap_struct
, utf8_dn
, attrs
);
846 if (rc
== LDAP_SERVER_DOWN
) {
847 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
848 ldapsam_close(ldap_state
);
855 static int ldapsam_add(struct ldapsam_privates
*ldap_state
, const char *dn
, LDAPMod
*attrs
[])
857 int rc
= LDAP_SERVER_DOWN
;
861 SMB_ASSERT(ldap_state
);
863 if (push_utf8_allocate(&utf8_dn
, dn
) == (size_t)-1) {
864 return LDAP_NO_MEMORY
;
867 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
869 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
872 rc
= ldap_add_s(ldap_state
->ldap_struct
, utf8_dn
, attrs
);
875 if (rc
== LDAP_SERVER_DOWN
) {
876 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
877 ldapsam_close(ldap_state
);
884 static int ldapsam_delete(struct ldapsam_privates
*ldap_state
, char *dn
)
886 int rc
= LDAP_SERVER_DOWN
;
890 SMB_ASSERT(ldap_state
);
892 if (push_utf8_allocate(&utf8_dn
, dn
) == (size_t)-1) {
893 return LDAP_NO_MEMORY
;
896 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
898 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
901 rc
= ldap_delete_s(ldap_state
->ldap_struct
, utf8_dn
);
904 if (rc
== LDAP_SERVER_DOWN
) {
905 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
906 ldapsam_close(ldap_state
);
913 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
914 static int ldapsam_extended_operation(struct ldapsam_privates
*ldap_state
, LDAP_CONST
char *reqoid
, struct berval
*reqdata
, LDAPControl
**serverctrls
, LDAPControl
**clientctrls
, char **retoidp
, struct berval
**retdatap
)
916 int rc
= LDAP_SERVER_DOWN
;
922 while ((rc
== LDAP_SERVER_DOWN
) && (attempts
< 8)) {
924 if ((rc
= ldapsam_retry_open(ldap_state
,&attempts
)) != LDAP_SUCCESS
)
927 rc
= ldap_extended_operation_s(ldap_state
->ldap_struct
, reqoid
, reqdata
, serverctrls
, clientctrls
, retoidp
, retdatap
);
930 if (rc
== LDAP_SERVER_DOWN
) {
931 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO
));
932 ldapsam_close(ldap_state
);
939 /*******************************************************************
940 run the search by name.
941 ******************************************************************/
942 static int ldapsam_search_suffix (struct ldapsam_privates
*ldap_state
, const char *filter
,
943 char **search_attr
, LDAPMessage
** result
)
945 int scope
= LDAP_SCOPE_SUBTREE
;
948 DEBUG(2, ("ldapsam_search_suffix: searching for:[%s]\n", filter
));
950 rc
= ldapsam_search(ldap_state
, lp_ldap_suffix(), scope
, filter
, search_attr
, 0, result
);
952 if (rc
!= LDAP_SUCCESS
) {
953 char *ld_error
= NULL
;
954 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
956 DEBUG(0,("ldapsam_search_suffix: Problem during the LDAP search: %s (%s)\n",
957 ld_error
?ld_error
:"(unknown)", ldap_err2string (rc
)));
958 DEBUG(3,("ldapsam_search_suffix: Query was: %s, %s\n", lp_ldap_suffix(),
966 /*******************************************************************
967 generate the LDAP search filter for the objectclass based on the
968 version of the schema we are using
969 ******************************************************************/
971 static const char* get_objclass_filter( int schema_ver
)
973 static fstring objclass_filter
;
977 case SCHEMAVER_SAMBAACCOUNT
:
978 snprintf( objclass_filter
, sizeof(objclass_filter
)-1, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT
);
980 case SCHEMAVER_SAMBASAMACCOUNT
:
981 snprintf( objclass_filter
, sizeof(objclass_filter
)-1, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT
);
984 DEBUG(0,("ldapsam_search_suffix_by_name(): Invalid schema version specified!\n"));
988 return objclass_filter
;
991 /*******************************************************************
992 run the search by name.
993 ******************************************************************/
994 static int ldapsam_search_suffix_by_name (struct ldapsam_privates
*ldap_state
, const char *user
,
995 LDAPMessage
** result
, char **attr
)
998 char *escape_user
= escape_ldap_string_alloc(user
);
1001 return LDAP_NO_MEMORY
;
1005 * in the filter expression, replace %u with the real name
1006 * so in ldap filter, %u MUST exist :-)
1008 snprintf(filter
, sizeof(filter
)-1, "(&%s%s)", lp_ldap_filter(),
1009 get_objclass_filter(ldap_state
->schema_ver
));
1012 * have to use this here because $ is filtered out
1017 all_string_sub(filter
, "%u", escape_user
, sizeof(pstring
));
1018 SAFE_FREE(escape_user
);
1020 return ldapsam_search_suffix(ldap_state
, filter
, attr
, result
);
1023 /*******************************************************************
1024 run the search by rid.
1025 ******************************************************************/
1026 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates
*ldap_state
,
1027 uint32 rid
, LDAPMessage
** result
,
1033 /* check if the user rid exists, if not, try searching on the uid */
1035 snprintf(filter
, sizeof(filter
)-1, "(&(rid=%i)%s)", rid
,
1036 get_objclass_filter(ldap_state
->schema_ver
));
1038 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr
, result
);
1043 /*******************************************************************
1044 run the search by SID.
1045 ******************************************************************/
1046 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates
*ldap_state
,
1047 const DOM_SID
*sid
, LDAPMessage
** result
,
1054 /* check if the user rid exsists, if not, try searching on the uid */
1056 snprintf(filter
, sizeof(filter
)-1, "(&(%s=%s)%s)",
1057 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_SID
),
1058 sid_to_string(sid_string
, sid
),
1059 get_objclass_filter(ldap_state
->schema_ver
));
1061 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr
, result
);
1066 /*******************************************************************
1067 search an attribute and return the first value found.
1068 ******************************************************************/
1069 static BOOL
get_single_attribute (LDAP
* ldap_struct
, LDAPMessage
* entry
,
1070 const char *attribute
, pstring value
)
1079 if ((values
= ldap_get_values (ldap_struct
, entry
, attribute
)) == NULL
) {
1080 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute
));
1085 if (convert_string(CH_UTF8
, CH_UNIX
,values
[0], -1, value
, sizeof(pstring
)) == (size_t)-1)
1087 DEBUG(1, ("get_single_attribute: string conversion of [%s] = [%s] failed!\n",
1088 attribute
, values
[0]));
1089 ldap_value_free(values
);
1093 ldap_value_free(values
);
1094 #ifdef DEBUG_PASSWORDS
1095 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute
, value
));
1100 /************************************************************************
1101 Routine to manage the LDAPMod structure array
1102 manage memory used by the array, by each struct, and values
1104 ************************************************************************/
1105 static void make_a_mod (LDAPMod
*** modlist
, int modop
, const char *attribute
, const char *value
)
1113 /* sanity checks on the mod values */
1115 if (attribute
== NULL
|| *attribute
== '\0')
1117 #if 0 /* commented out after discussion with abartlet. Do not reenable.
1118 left here so other so re-add similar code --jerry */
1119 if (value
== NULL
|| *value
== '\0')
1125 mods
= (LDAPMod
**) malloc(sizeof(LDAPMod
*));
1128 DEBUG(0, ("make_a_mod: out of memory!\n"));
1134 for (i
= 0; mods
[i
] != NULL
; ++i
) {
1135 if (mods
[i
]->mod_op
== modop
&& !strcasecmp(mods
[i
]->mod_type
, attribute
))
1139 if (mods
[i
] == NULL
)
1141 mods
= (LDAPMod
**) Realloc (mods
, (i
+ 2) * sizeof (LDAPMod
*));
1144 DEBUG(0, ("make_a_mod: out of memory!\n"));
1147 mods
[i
] = (LDAPMod
*) malloc(sizeof(LDAPMod
));
1148 if (mods
[i
] == NULL
)
1150 DEBUG(0, ("make_a_mod: out of memory!\n"));
1153 mods
[i
]->mod_op
= modop
;
1154 mods
[i
]->mod_values
= NULL
;
1155 mods
[i
]->mod_type
= strdup(attribute
);
1161 char *utf8_value
= NULL
;
1164 if (mods
[i
]->mod_values
!= NULL
) {
1165 for (; mods
[i
]->mod_values
[j
] != NULL
; j
++);
1167 mods
[i
]->mod_values
= (char **)Realloc(mods
[i
]->mod_values
,
1168 (j
+ 2) * sizeof (char *));
1170 if (mods
[i
]->mod_values
== NULL
) {
1171 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
1175 if (push_utf8_allocate(&utf8_value
, value
) == (size_t)-1) {
1176 DEBUG (0, ("make_a_mod: String conversion failure!\n"));
1180 mods
[i
]->mod_values
[j
] = utf8_value
;
1182 mods
[i
]->mod_values
[j
+ 1] = NULL
;
1187 /**********************************************************************
1188 Set attribute to newval in LDAP, regardless of what value the
1189 attribute had in LDAP before.
1190 *********************************************************************/
1191 static void make_ldap_mod(LDAP
*ldap_struct
, LDAPMessage
*existing
,
1193 const char *attribute
, const char *newval
)
1195 char **values
= NULL
;
1197 if (existing
!= NULL
) {
1198 values
= ldap_get_values(ldap_struct
, existing
, attribute
);
1201 /* all of our string attributes are case insensitive */
1203 if ((values
!= NULL
) && (values
[0] != NULL
) &&
1204 StrCaseCmp(values
[0], newval
) == 0)
1207 /* Believe it or not, but LDAP will deny a delete and
1208 an add at the same time if the values are the
1211 ldap_value_free(values
);
1215 /* Regardless of the real operation (add or modify)
1216 we add the new value here. We rely on deleting
1217 the old value, should it exist. */
1219 if ((newval
!= NULL
) && (strlen(newval
) > 0)) {
1220 make_a_mod(mods
, LDAP_MOD_ADD
, attribute
, newval
);
1223 if (values
== NULL
) {
1224 /* There has been no value before, so don't delete it.
1225 Here's a possible race: We might end up with
1226 duplicate attributes */
1230 /* By deleting exactly the value we found in the entry this
1231 should be race-free in the sense that the LDAP-Server will
1232 deny the complete operation if somebody changed the
1233 attribute behind our back. */
1235 make_a_mod(mods
, LDAP_MOD_DELETE
, attribute
, values
[0]);
1236 ldap_value_free(values
);
1239 /*******************************************************************
1240 Delete complete object or objectclass and attrs from
1241 object found in search_result depending on lp_ldap_delete_dn
1242 ******************************************************************/
1243 static NTSTATUS
ldapsam_delete_entry(struct ldapsam_privates
*ldap_state
,
1244 LDAPMessage
*result
,
1245 const char *objectclass
,
1250 LDAPMod
**mods
= NULL
;
1252 BerElement
*ptr
= NULL
;
1254 rc
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1257 DEBUG(0, ("Entry must exist exactly once!\n"));
1258 return NT_STATUS_UNSUCCESSFUL
;
1261 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1262 dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
1264 if (lp_ldap_delete_dn()) {
1265 NTSTATUS ret
= NT_STATUS_OK
;
1266 rc
= ldapsam_delete(ldap_state
, dn
);
1268 if (rc
!= LDAP_SUCCESS
) {
1269 DEBUG(0, ("Could not delete object %s\n", dn
));
1270 ret
= NT_STATUS_UNSUCCESSFUL
;
1276 /* Ok, delete only the SAM attributes */
1278 for (name
= ldap_first_attribute(ldap_state
->ldap_struct
, entry
, &ptr
);
1280 name
= ldap_next_attribute(ldap_state
->ldap_struct
, entry
, ptr
))
1284 /* We are only allowed to delete the attributes that
1287 for (attrib
= attrs
; *attrib
!= NULL
; attrib
++)
1289 if (StrCaseCmp(*attrib
, name
) == 0) {
1290 DEBUG(10, ("deleting attribute %s\n", name
));
1291 make_a_mod(&mods
, LDAP_MOD_DELETE
, name
, NULL
);
1302 make_a_mod(&mods
, LDAP_MOD_DELETE
, "objectClass", objectclass
);
1304 rc
= ldapsam_modify(ldap_state
, dn
, mods
);
1305 ldap_mods_free(mods
, 1);
1307 if (rc
!= LDAP_SUCCESS
) {
1308 char *ld_error
= NULL
;
1309 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
1312 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
1313 dn
, ldap_err2string(rc
), ld_error
?ld_error
:"unknown"));
1314 SAFE_FREE(ld_error
);
1316 return NT_STATUS_UNSUCCESSFUL
;
1320 return NT_STATUS_OK
;
1323 /**********************************************************************
1324 Search for the domain info entry
1325 *********************************************************************/
1326 static int ldapsam_search_domain_info(struct ldapsam_privates
*ldap_state
,
1327 LDAPMessage
** result
)
1333 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(%s=%s))",
1335 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOMAIN
),
1336 ldap_state
->domain_name
);
1338 DEBUG(2, ("Searching for:[%s]\n", filter
));
1341 attr_list
= get_attr_list( dominfo_attr_list
);
1342 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr_list
, result
);
1343 free_attr_list( attr_list
);
1345 if (rc
!= LDAP_SUCCESS
) {
1346 DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc
)));
1347 DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
1353 /**********************************************************************
1354 If this entry is is the 'allocated' range, extract the RID and return
1355 it, so we can find the 'next' rid to allocate.
1357 Do this, no matter what type of object holds the RID - be it a user,
1358 group or somthing else.
1359 *********************************************************************/
1360 static uint32
entry_to_rid(struct ldapsam_privates
*ldap_state
, LDAPMessage
*entry
, int rid_type
)
1366 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1367 LDAP_ATTRIBUTE_SID
, sid_string
))
1372 if (!string_to_sid(&dom_sid
, sid_string
)) {
1376 if (!sid_peek_check_rid(&dom_sid
, get_global_sam_sid(), &rid
)) {
1377 /* not our domain, so we don't care */
1383 if (rid
>= ldap_state
->low_allocated_user_rid
&&
1384 rid
<= ldap_state
->high_allocated_user_rid
) {
1388 case GROUP_RID_TYPE
:
1389 if (rid
>= ldap_state
->low_allocated_group_rid
&&
1390 rid
<= ldap_state
->high_allocated_group_rid
) {
1399 /**********************************************************************
1400 Connect to LDAP server and find the next available 'allocated' RID.
1402 The search is done 'per type' as we allocate seperate pools for the
1403 EVEN and ODD (user and group) RIDs.
1405 This is only done once, so that we can fill out the sambaDomain.
1406 *********************************************************************/
1407 static uint32
search_next_allocated_rid(struct ldapsam_privates
*ldap_state
, int rid_type
)
1410 LDAPMessage
*result
;
1416 char *sid_attr
[] = {LDAP_ATTRIBUTE_SID
, NULL
};
1419 snprintf( filter
, sizeof(filter
)-1, "(%s=*)", LDAP_ATTRIBUTE_SID
);
1421 DEBUG(2, ("search_top_allocated_rid: searching for:[%s]\n", filter
));
1423 rc
= ldapsam_search_suffix(ldap_state
, filter
, sid_attr
, &result
);
1425 if (rc
!= LDAP_SUCCESS
) {
1426 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc
)));
1427 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
1433 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1434 DEBUG(2, ("search_top_allocated_rid: %d entries in the base!\n", count
));
1437 DEBUG(3, ("LDAP search returned no records, assuming no allocated RIDs present!: %s\n", ldap_err2string(rc
)));
1438 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
1440 entry
= ldap_first_entry(ldap_state
->ldap_struct
,result
);
1442 top_rid
= entry_to_rid(ldap_state
, entry
, rid_type
);
1444 while ((entry
= ldap_next_entry(ldap_state
->ldap_struct
, entry
))) {
1446 rid
= entry_to_rid(ldap_state
, entry
, rid_type
);
1447 if (((rid
& ~RID_TYPE_MASK
) == rid_type
) && (rid
> top_rid
)) {
1455 if (top_rid
< ldap_state
->low_allocated_user_rid
) {
1456 return ldap_state
->low_allocated_user_rid
;
1459 case GROUP_RID_TYPE
:
1460 if (top_rid
< ldap_state
->low_allocated_group_rid
)
1461 return ldap_state
->low_allocated_group_rid
;
1465 next_rid
= (top_rid
& ~RID_TYPE_MASK
) + rid_type
+ RID_MULTIPLIER
;
1469 if (next_rid
> ldap_state
->high_allocated_user_rid
) {
1473 case GROUP_RID_TYPE
:
1474 if (next_rid
> ldap_state
->high_allocated_group_rid
) {
1482 /**********************************************************************
1483 Add the sambaDomain to LDAP, so we don't have to search for this stuff
1484 again. This is a once-add operation for now.
1486 TODO: Add other attributes, and allow modification.
1487 *********************************************************************/
1488 static NTSTATUS
add_new_domain_info(struct ldapsam_privates
*ldap_state
)
1492 LDAPMod
**mods
= NULL
;
1495 LDAPMessage
*result
= NULL
;
1500 uint32 next_allocated_user_rid
;
1501 uint32 next_allocated_group_rid
;
1503 next_allocated_user_rid
= search_next_allocated_rid(ldap_state
, USER_RID_TYPE
);
1504 if (!next_allocated_user_rid
) {
1505 return NT_STATUS_UNSUCCESSFUL
;
1508 next_allocated_group_rid
= search_next_allocated_rid(ldap_state
, GROUP_RID_TYPE
);
1509 if (!next_allocated_group_rid
) {
1510 return NT_STATUS_UNSUCCESSFUL
;
1513 slprintf (filter
, sizeof (filter
) - 1, "(&(%s=%s)(objectclass=%s))",
1514 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOMAIN
),
1515 ldap_state
->domain_name
, LDAP_OBJ_DOMINFO
);
1517 attr_list
= get_attr_list( dominfo_attr_list
);
1518 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr_list
, &result
);
1519 free_attr_list( attr_list
);
1521 if (rc
!= LDAP_SUCCESS
) {
1522 return NT_STATUS_UNSUCCESSFUL
;
1525 num_result
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1527 if (num_result
> 1) {
1528 DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
1529 ldap_msgfree(result
);
1530 return NT_STATUS_UNSUCCESSFUL
;
1533 /* Check if we need to add an entry */
1534 DEBUG(3,("Adding new domain\n"));
1535 ldap_op
= LDAP_MOD_ADD
;
1536 asprintf (&dn
, "%s=%s,%s", get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOMAIN
),
1537 ldap_state
->domain_name
, lp_ldap_suffix());
1539 /* Free original search */
1540 ldap_msgfree(result
);
1543 return NT_STATUS_NO_MEMORY
;
1545 /* make the changes - the entry *must* not already have samba attributes */
1546 make_a_mod(&mods
, LDAP_MOD_ADD
, get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOMAIN
),
1547 ldap_state
->domain_name
);
1549 sid_to_string(tmp
, &ldap_state
->domain_sid
);
1550 make_a_mod(&mods
, LDAP_MOD_ADD
, get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOM_SID
), tmp
);
1552 snprintf(tmp
, sizeof(tmp
)-1, "%i", next_allocated_user_rid
);
1553 make_a_mod(&mods
, LDAP_MOD_ADD
, get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_USERRID
), tmp
);
1555 snprintf(tmp
, sizeof(tmp
)-1, "%i", next_allocated_group_rid
);
1556 make_a_mod(&mods
, LDAP_MOD_ADD
, get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_GROUPRID
), tmp
);
1558 make_a_mod(&mods
, LDAP_MOD_ADD
, "objectclass", LDAP_OBJ_DOMINFO
);
1563 rc
= ldapsam_add(ldap_state
, dn
, mods
);
1565 case LDAP_MOD_REPLACE
:
1566 rc
= ldapsam_modify(ldap_state
, dn
, mods
);
1569 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op
));
1570 return NT_STATUS_INVALID_PARAMETER
;
1573 if (rc
!=LDAP_SUCCESS
) {
1574 char *ld_error
= NULL
;
1575 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
1578 ("failed to %s domain dn= %s with: %s\n\t%s\n",
1579 ldap_op
== LDAP_MOD_ADD
? "add" : "modify",
1580 dn
, ldap_err2string(rc
),
1581 ld_error
?ld_error
:"unknown"));
1582 SAFE_FREE(ld_error
);
1584 ldap_mods_free(mods
,1);
1585 return NT_STATUS_UNSUCCESSFUL
;
1588 DEBUG(2,("added: domain = %s in the LDAP database\n", ldap_state
->domain_name
));
1589 ldap_mods_free(mods
, 1);
1590 return NT_STATUS_OK
;
1593 /**********************************************************************
1594 Even if the sambaAccount attribute in LDAP tells us that this RID is
1595 safe to use, always check before use.
1596 *********************************************************************/
1597 static BOOL
sid_in_use(struct ldapsam_privates
*ldap_state
,
1598 const DOM_SID
*sid
, int *error
)
1602 LDAPMessage
*result
= NULL
;
1605 char *sid_attr
[] = {LDAP_ATTRIBUTE_SID
, NULL
};
1607 slprintf(filter
, sizeof(filter
)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID
, sid_to_string(sid_string
, sid
));
1609 rc
= ldapsam_search_suffix(ldap_state
, filter
, sid_attr
, &result
);
1611 if (rc
!= LDAP_SUCCESS
) {
1612 char *ld_error
= NULL
;
1613 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
1614 DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
1615 sid_string
, ld_error
));
1616 SAFE_FREE(ld_error
);
1622 if ((count
= ldap_count_entries(ldap_state
->ldap_struct
, result
)) > 0) {
1623 DEBUG(3, ("Sid %s already in use - trying next RID\n",
1625 ldap_msgfree(result
);
1629 ldap_msgfree(result
);
1631 /* good, sid is not in use */
1635 /**********************************************************************
1636 Set the new nextRid attribute, and return one we can use.
1638 This also checks that this RID is actually free - in case the admin
1639 manually stole it :-).
1640 *********************************************************************/
1641 static NTSTATUS
ldapsam_next_rid(struct ldapsam_privates
*ldap_state
, uint32
*rid
, int rid_type
)
1643 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1645 LDAPMessage
*result
= NULL
;
1646 LDAPMessage
*entry
= NULL
;
1648 LDAPMod
**mods
= NULL
;
1650 fstring old_rid_string
;
1651 fstring next_rid_string
;
1655 if ( ldap_state
->schema_ver
!= SCHEMAVER_SAMBASAMACCOUNT
) {
1656 DEBUG(0, ("Allocated RIDs require the %s objectclass used by 'ldapsam'\n",
1657 LDAP_OBJ_SAMBASAMACCOUNT
));
1658 return NT_STATUS_UNSUCCESSFUL
;
1661 while (attempts
< 10)
1664 if (ldapsam_search_domain_info(ldap_state
, &result
)) {
1668 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) < 1) {
1669 DEBUG(3, ("Got no domain info entries for domain %s\n",
1670 ldap_state
->domain_name
));
1671 ldap_msgfree(result
);
1672 if (NT_STATUS_IS_OK(ret
= add_new_domain_info(ldap_state
))) {
1675 DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret
)));
1680 if ((count
= ldap_count_entries(ldap_state
->ldap_struct
, result
)) > 1) {
1681 DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
1682 count
, ldap_state
->domain_name
));
1683 ldap_msgfree(result
);
1687 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1689 ldap_msgfree(result
);
1693 if ((dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
)) == NULL
) {
1694 DEBUG(0, ("Could not get domain info DN\n"));
1695 ldap_msgfree(result
);
1699 /* yes, we keep 2 seperate counters, to avoid stomping on the two
1700 different sets of algorithmic RIDs */
1704 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1705 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_USERRID
),
1709 ldap_msgfree(result
);
1713 case GROUP_RID_TYPE
:
1714 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1715 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_GROUPRID
),
1719 ldap_msgfree(result
);
1725 /* This is the core of the whole routine. If we had
1726 scheme-style closures, there would be a *lot* less code
1728 *rid
= (uint32
)atol(old_rid_string
);
1729 next_rid
= *rid
+RID_MULTIPLIER
;
1731 slprintf(next_rid_string
, sizeof(next_rid_string
)-1, "%d", next_rid
);
1735 if (next_rid
> ldap_state
->high_allocated_user_rid
) {
1736 return NT_STATUS_UNSUCCESSFUL
;
1739 /* Try to make the modification atomically by enforcing the
1740 old value in the delete mod. */
1741 make_ldap_mod(ldap_state
->ldap_struct
, entry
, &mods
,
1742 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_USERRID
),
1746 case GROUP_RID_TYPE
:
1747 if (next_rid
> ldap_state
->high_allocated_group_rid
) {
1748 return NT_STATUS_UNSUCCESSFUL
;
1751 /* Try to make the modification atomically by enforcing the
1752 old value in the delete mod. */
1753 make_ldap_mod(ldap_state
->ldap_struct
, entry
, &mods
,
1754 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_GROUPRID
),
1759 if ((rc
= ldap_modify_s(ldap_state
->ldap_struct
, dn
, mods
)) == LDAP_SUCCESS
) {
1762 pstring domain_sid_string
;
1765 if (!get_single_attribute(ldap_state
->ldap_struct
, result
,
1766 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOM_SID
),
1769 ldap_mods_free(mods
, 1);
1771 ldap_msgfree(result
);
1775 if (!string_to_sid(&dom_sid
, domain_sid_string
)) {
1776 ldap_mods_free(mods
, 1);
1778 ldap_msgfree(result
);
1782 ldap_mods_free(mods
, 1);
1785 ldap_msgfree(result
);
1787 sid_copy(&sid
, &dom_sid
);
1788 sid_append_rid(&sid
, *rid
);
1790 /* check RID is not in use */
1791 if (sid_in_use(ldap_state
, &sid
, &error
)) {
1798 return NT_STATUS_OK
;
1801 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
1802 DEBUG(2, ("Failed to modify rid: %s\n", ld_error
));
1803 SAFE_FREE(ld_error
);
1805 ldap_mods_free(mods
, 1);
1811 ldap_msgfree(result
);
1815 /* Sleep for a random timeout */
1816 unsigned sleeptime
= (sys_random()*sys_getpid()*attempts
);
1824 DEBUG(0, ("Failed to set new RID\n"));
1828 /* New Interface is being implemented here */
1830 /**********************************************************************
1831 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
1832 *********************************************************************/
1833 static BOOL
get_unix_attributes (struct ldapsam_privates
*ldap_state
,
1834 SAM_ACCOUNT
* sampass
,
1835 LDAPMessage
* entry
,
1843 if ((ldap_values
= ldap_get_values (ldap_state
->ldap_struct
, entry
, "objectClass")) == NULL
) {
1844 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
1848 for (values
=ldap_values
;*values
;values
++) {
1849 if (strcasecmp(*values
, LDAP_OBJ_POSIXACCOUNT
) == 0) {
1854 if (!*values
) { /*end of array, no posixAccount */
1855 DEBUG(10, ("user does not have %s attributes\n", LDAP_OBJ_POSIXACCOUNT
));
1856 ldap_value_free(ldap_values
);
1859 ldap_value_free(ldap_values
);
1861 if ( !get_single_attribute(ldap_state
->ldap_struct
, entry
,
1862 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_UNIX_HOME
), homedir
) )
1867 if ( !get_single_attribute(ldap_state
->ldap_struct
, entry
,
1868 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_GIDNUMBER
), temp
) )
1873 *gid
= (gid_t
)atol(temp
);
1875 pdb_set_unix_homedir(sampass
, homedir
, PDB_SET
);
1877 DEBUG(10, ("user has %s attributes\n", LDAP_OBJ_POSIXACCOUNT
));
1883 /**********************************************************************
1884 Initialize SAM_ACCOUNT from an LDAP query
1885 (Based on init_sam_from_buffer in pdb_tdb.c)
1886 *********************************************************************/
1887 static BOOL
init_sam_from_ldap (struct ldapsam_privates
*ldap_state
,
1888 SAM_ACCOUNT
* sampass
,
1889 LDAPMessage
* entry
)
1895 pass_can_change_time
,
1896 pass_must_change_time
;
1909 uint8 smblmpwd
[LM_HASH_LEN
],
1910 smbntpwd
[NT_HASH_LEN
];
1911 uint16 acct_ctrl
= 0,
1914 uint8 hours
[MAX_HOURS_LEN
];
1917 gid_t gid
= getegid();
1920 * do a little initialization
1924 nt_username
[0] = '\0';
1927 dir_drive
[0] = '\0';
1928 logon_script
[0] = '\0';
1929 profile_path
[0] = '\0';
1930 acct_desc
[0] = '\0';
1931 munged_dial
[0] = '\0';
1932 workstations
[0] = '\0';
1935 if (sampass
== NULL
|| ldap_state
== NULL
|| entry
== NULL
) {
1936 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1940 if (ldap_state
->ldap_struct
== NULL
) {
1941 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1945 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
, "uid", username
)) {
1946 DEBUG(1, ("No uid attribute found for this user!\n"));
1950 DEBUG(2, ("Entry found for user: %s\n", username
));
1952 pstrcpy(nt_username
, username
);
1954 pstrcpy(domain
, ldap_state
->domain_name
);
1956 pdb_set_username(sampass
, username
, PDB_SET
);
1958 pdb_set_domain(sampass
, domain
, PDB_DEFAULT
);
1959 pdb_set_nt_username(sampass
, nt_username
, PDB_SET
);
1961 /* deal with different attributes between the schema first */
1963 if ( ldap_state
->schema_ver
== SCHEMAVER_SAMBASAMACCOUNT
)
1965 if (get_single_attribute(ldap_state
->ldap_struct
, entry
,
1966 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_SID
), temp
))
1968 pdb_set_user_sid_from_string(sampass
, temp
, PDB_SET
);
1971 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1972 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PRIMARY_GROUP_SID
), temp
))
1974 pdb_set_group_sid_from_string(sampass
, temp
, PDB_SET
);
1978 pdb_set_group_sid_from_rid(sampass
, DOMAIN_GROUP_RID_USERS
, PDB_DEFAULT
);
1985 if (get_single_attribute(ldap_state
->ldap_struct
, entry
,
1986 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_RID
), temp
))
1988 user_rid
= (uint32
)atol(temp
);
1989 pdb_set_user_sid_from_rid(sampass
, user_rid
, PDB_SET
);
1992 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
1993 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PRIMARY_GROUP_RID
), temp
))
1995 pdb_set_group_sid_from_rid(sampass
, DOMAIN_GROUP_RID_USERS
, PDB_DEFAULT
);
1999 group_rid
= (uint32
)atol(temp
);
2001 /* for some reason, we often have 0 as a primary group RID.
2002 Make sure that we treat this just as a 'default' value */
2004 if ( group_rid
> 0 )
2005 pdb_set_group_sid_from_rid(sampass
, group_rid
, PDB_SET
);
2007 pdb_set_group_sid_from_rid(sampass
, DOMAIN_GROUP_RID_USERS
, PDB_DEFAULT
);
2011 if (pdb_get_init_flags(sampass
,PDB_USERSID
) == PDB_DEFAULT
) {
2012 DEBUG(1, ("no %s or %s attribute found for this user %s\n",
2013 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_SID
),
2014 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_RID
),
2021 * If so configured, try and get the values from LDAP
2024 if (lp_ldap_trust_ids() && (get_unix_attributes(ldap_state
, sampass
, entry
, &gid
)))
2026 if (pdb_get_init_flags(sampass
,PDB_GROUPSID
) == PDB_DEFAULT
)
2029 /* call the mapping code here */
2030 if(pdb_getgrgid(&map
, gid
, MAPPING_WITHOUT_PRIV
)) {
2031 pdb_set_group_sid(sampass
, &map
.sid
, PDB_SET
);
2034 pdb_set_group_sid_from_rid(sampass
, pdb_gid_to_group_rid(gid
), PDB_SET
);
2039 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2040 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_LAST_SET
), temp
))
2042 /* leave as default */
2044 pass_last_set_time
= (time_t) atol(temp
);
2045 pdb_set_pass_last_set_time(sampass
, pass_last_set_time
, PDB_SET
);
2048 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2049 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGON_TIME
), temp
))
2051 /* leave as default */
2053 logon_time
= (time_t) atol(temp
);
2054 pdb_set_logon_time(sampass
, logon_time
, PDB_SET
);
2057 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2058 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGOFF_TIME
), temp
))
2060 /* leave as default */
2062 logoff_time
= (time_t) atol(temp
);
2063 pdb_set_logoff_time(sampass
, logoff_time
, PDB_SET
);
2066 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2067 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_KICKOFF_TIME
), temp
))
2069 /* leave as default */
2071 kickoff_time
= (time_t) atol(temp
);
2072 pdb_set_kickoff_time(sampass
, kickoff_time
, PDB_SET
);
2075 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2076 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_CAN_CHANGE
), temp
))
2078 /* leave as default */
2080 pass_can_change_time
= (time_t) atol(temp
);
2081 pdb_set_pass_can_change_time(sampass
, pass_can_change_time
, PDB_SET
);
2084 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2085 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_MUST_CHANGE
), temp
))
2087 /* leave as default */
2089 pass_must_change_time
= (time_t) atol(temp
);
2090 pdb_set_pass_must_change_time(sampass
, pass_must_change_time
, PDB_SET
);
2093 /* recommend that 'gecos' and 'displayName' should refer to the same
2094 * attribute OID. userFullName depreciated, only used by Samba
2095 * primary rules of LDAP: don't make a new attribute when one is already defined
2096 * that fits your needs; using cn then displayName rather than 'userFullName'
2099 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2100 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_DISPLAY_NAME
), fullname
))
2102 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2103 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_CN
), fullname
))
2105 /* leave as default */
2107 pdb_set_fullname(sampass
, fullname
, PDB_SET
);
2110 pdb_set_fullname(sampass
, fullname
, PDB_SET
);
2113 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2114 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_HOME_DRIVE
), dir_drive
))
2116 pdb_set_dir_drive(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
2122 pdb_set_dir_drive(sampass
, dir_drive
, PDB_SET
);
2125 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2126 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_HOME_PATH
), homedir
))
2128 pdb_set_homedir(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
2134 pdb_set_homedir(sampass
, homedir
, PDB_SET
);
2137 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2138 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGON_SCRIPT
), logon_script
))
2140 pdb_set_logon_script(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
2146 pdb_set_logon_script(sampass
, logon_script
, PDB_SET
);
2149 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2150 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PROFILE_PATH
), profile_path
))
2152 pdb_set_profile_path(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
2158 pdb_set_profile_path(sampass
, profile_path
, PDB_SET
);
2161 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2162 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_DESC
), acct_desc
))
2164 /* leave as default */
2166 pdb_set_acct_desc(sampass
, acct_desc
, PDB_SET
);
2169 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
2170 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_WKS
), workstations
))
2172 /* leave as default */;
2174 pdb_set_workstations(sampass
, workstations
, PDB_SET
);
2177 /* FIXME: hours stuff should be cleaner */
2181 memset(hours
, 0xff, hours_len
);
2183 if (!get_single_attribute (ldap_state
->ldap_struct
, entry
,
2184 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LMPW
), temp
))
2186 /* leave as default */
2188 pdb_gethexpwd(temp
, smblmpwd
);
2189 memset((char *)temp
, '\0', strlen(temp
)+1);
2190 if (!pdb_set_lanman_passwd(sampass
, smblmpwd
, PDB_SET
))
2192 ZERO_STRUCT(smblmpwd
);
2195 if (!get_single_attribute (ldap_state
->ldap_struct
, entry
,
2196 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_NTPW
), temp
))
2198 /* leave as default */
2200 pdb_gethexpwd(temp
, smbntpwd
);
2201 memset((char *)temp
, '\0', strlen(temp
)+1);
2202 if (!pdb_set_nt_passwd(sampass
, smbntpwd
, PDB_SET
))
2204 ZERO_STRUCT(smbntpwd
);
2207 if (!get_single_attribute (ldap_state
->ldap_struct
, entry
,
2208 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_ACB_INFO
), temp
))
2210 acct_ctrl
|= ACB_NORMAL
;
2212 acct_ctrl
= pdb_decode_acct_ctrl(temp
);
2215 acct_ctrl
|= ACB_NORMAL
;
2217 pdb_set_acct_ctrl(sampass
, acct_ctrl
, PDB_SET
);
2220 pdb_set_hours_len(sampass
, hours_len
, PDB_SET
);
2221 pdb_set_logon_divs(sampass
, logon_divs
, PDB_SET
);
2223 pdb_set_munged_dial(sampass
, munged_dial
, PDB_SET
);
2225 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
2226 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
2227 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
2229 pdb_set_hours(sampass
, hours
, PDB_SET
);
2234 /**********************************************************************
2235 Initialize SAM_ACCOUNT from an LDAP query
2236 (Based on init_buffer_from_sam in pdb_tdb.c)
2237 *********************************************************************/
2238 static BOOL
init_ldap_from_sam (struct ldapsam_privates
*ldap_state
,
2239 LDAPMessage
*existing
,
2240 LDAPMod
*** mods
, SAM_ACCOUNT
* sampass
,
2241 BOOL (*need_update
)(const SAM_ACCOUNT
*,
2247 if (mods
== NULL
|| sampass
== NULL
) {
2248 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
2255 * took out adding "objectclass: sambaAccount"
2256 * do this on a per-mod basis
2258 if (need_update(sampass
, PDB_USERNAME
))
2259 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2260 "uid", pdb_get_username(sampass
));
2262 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass
)));
2264 if (pdb_get_init_flags(sampass
, PDB_USERSID
) == PDB_DEFAULT
) {
2265 if (ldap_state
->permit_non_unix_accounts
) {
2266 if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state
, &rid
, USER_RID_TYPE
))) {
2267 DEBUG(0, ("NO user RID specified on account %s, and "
2268 "finding next available NUA RID failed, "
2270 pdb_get_username(sampass
)));
2271 ldap_mods_free(*mods
, 1);
2275 DEBUG(0, ("NO user RID specified on account %s, "
2276 "cannot store!\n", pdb_get_username(sampass
)));
2277 ldap_mods_free(*mods
, 1);
2281 /* now that we have figured out the RID, always store it, as
2282 the schema requires it (either as a SID or a RID) */
2284 if (!pdb_set_user_sid_from_rid(sampass
, rid
, PDB_CHANGED
)) {
2285 DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n",
2286 pdb_get_username(sampass
)));
2287 ldap_mods_free(*mods
, 1);
2292 /* only update the RID if we actually need to */
2293 if (need_update(sampass
, PDB_USERSID
))
2296 fstring dom_sid_string
;
2297 const DOM_SID
*user_sid
= pdb_get_user_sid(sampass
);
2299 switch ( ldap_state
->schema_ver
)
2301 case SCHEMAVER_SAMBAACCOUNT
:
2302 if (!sid_peek_check_rid(get_global_sam_sid(), user_sid
, &rid
)) {
2303 DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
2304 sid_to_string(sid_string
, user_sid
),
2305 sid_to_string(dom_sid_string
, get_global_sam_sid())));
2308 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
2309 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2310 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_RID
),
2314 case SCHEMAVER_SAMBASAMACCOUNT
:
2315 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2316 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_SID
),
2317 sid_to_string(sid_string
, user_sid
));
2321 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
2326 /* we don't need to store the primary group RID - so leaving it
2327 'free' to hang off the unix primary group makes life easier */
2329 if (need_update(sampass
, PDB_GROUPSID
))
2332 fstring dom_sid_string
;
2333 const DOM_SID
*group_sid
= pdb_get_group_sid(sampass
);
2335 switch ( ldap_state
->schema_ver
)
2337 case SCHEMAVER_SAMBAACCOUNT
:
2338 if (!sid_peek_check_rid(get_global_sam_sid(), group_sid
, &rid
)) {
2339 DEBUG(1, ("User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
2340 sid_to_string(sid_string
, group_sid
),
2341 sid_to_string(dom_sid_string
, get_global_sam_sid())));
2345 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
2346 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2347 get_userattr_key2string(ldap_state
->schema_ver
,
2348 LDAP_ATTR_PRIMARY_GROUP_RID
), temp
);
2351 case SCHEMAVER_SAMBASAMACCOUNT
:
2352 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2353 get_userattr_key2string(ldap_state
->schema_ver
,
2354 LDAP_ATTR_PRIMARY_GROUP_SID
), sid_to_string(sid_string
, group_sid
));
2358 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
2364 /* displayName, cn, and gecos should all be the same
2365 * most easily accomplished by giving them the same OID
2366 * gecos isn't set here b/c it should be handled by the
2368 * We change displayName only and fall back to cn if
2369 * it does not exist.
2372 if (need_update(sampass
, PDB_FULLNAME
))
2373 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2374 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_DISPLAY_NAME
),
2375 pdb_get_fullname(sampass
));
2377 if (need_update(sampass
, PDB_ACCTDESC
))
2378 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2379 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_DESC
),
2380 pdb_get_acct_desc(sampass
));
2382 if (need_update(sampass
, PDB_WORKSTATIONS
))
2383 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2384 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_USER_WKS
),
2385 pdb_get_workstations(sampass
));
2387 if (need_update(sampass
, PDB_SMBHOME
))
2388 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2389 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_HOME_PATH
),
2390 pdb_get_homedir(sampass
));
2392 if (need_update(sampass
, PDB_DRIVE
))
2393 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2394 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_HOME_DRIVE
),
2395 pdb_get_dir_drive(sampass
));
2397 if (need_update(sampass
, PDB_LOGONSCRIPT
))
2398 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2399 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGON_SCRIPT
),
2400 pdb_get_logon_script(sampass
));
2402 if (need_update(sampass
, PDB_PROFILE
))
2403 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2404 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PROFILE_PATH
),
2405 pdb_get_profile_path(sampass
));
2407 slprintf(temp
, sizeof(temp
) - 1, "%li", pdb_get_logon_time(sampass
));
2408 if (need_update(sampass
, PDB_LOGONTIME
))
2409 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2410 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGON_TIME
), temp
);
2412 slprintf(temp
, sizeof(temp
) - 1, "%li", pdb_get_logoff_time(sampass
));
2413 if (need_update(sampass
, PDB_LOGOFFTIME
))
2414 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2415 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LOGOFF_TIME
), temp
);
2417 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_kickoff_time(sampass
));
2418 if (need_update(sampass
, PDB_KICKOFFTIME
))
2419 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2420 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_KICKOFF_TIME
), temp
);
2422 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_can_change_time(sampass
));
2423 if (need_update(sampass
, PDB_CANCHANGETIME
))
2424 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2425 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_CAN_CHANGE
), temp
);
2427 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_must_change_time(sampass
));
2428 if (need_update(sampass
, PDB_MUSTCHANGETIME
))
2429 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2430 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_MUST_CHANGE
), temp
);
2432 if ((pdb_get_acct_ctrl(sampass
)&(ACB_WSTRUST
|ACB_SVRTRUST
|ACB_DOMTRUST
))
2433 || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY
))
2436 pdb_sethexpwd(temp
, pdb_get_lanman_passwd(sampass
),
2437 pdb_get_acct_ctrl(sampass
));
2439 if (need_update(sampass
, PDB_LMPASSWD
))
2440 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2441 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_LMPW
),
2444 pdb_sethexpwd (temp
, pdb_get_nt_passwd(sampass
),
2445 pdb_get_acct_ctrl(sampass
));
2447 if (need_update(sampass
, PDB_NTPASSWD
))
2448 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2449 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_NTPW
),
2452 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_last_set_time(sampass
));
2453 if (need_update(sampass
, PDB_PASSLASTSET
))
2454 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2455 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_PWD_LAST_SET
),
2459 /* FIXME: Hours stuff goes in LDAP */
2461 if (need_update(sampass
, PDB_ACCTCTRL
))
2462 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
2463 get_userattr_key2string(ldap_state
->schema_ver
, LDAP_ATTR_ACB_INFO
),
2464 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass
), NEW_PW_FORMAT_SPACE_PADDED_LEN
));
2471 /**********************************************************************
2472 Connect to LDAP server for password enumeration
2473 *********************************************************************/
2474 static NTSTATUS
ldapsam_setsampwent(struct pdb_methods
*my_methods
, BOOL update
)
2476 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2481 snprintf( filter
, sizeof(filter
)-1, "(&%s%s)", lp_ldap_filter(),
2482 get_objclass_filter(ldap_state
->schema_ver
));
2483 all_string_sub(filter
, "%u", "*", sizeof(pstring
));
2485 attr_list
= get_userattr_list(ldap_state
->schema_ver
);
2486 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr_list
, &ldap_state
->result
);
2487 free_attr_list( attr_list
);
2489 if (rc
!= LDAP_SUCCESS
) {
2490 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc
)));
2491 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
2492 ldap_msgfree(ldap_state
->result
);
2493 ldap_state
->result
= NULL
;
2494 return NT_STATUS_UNSUCCESSFUL
;
2497 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2498 ldap_count_entries(ldap_state
->ldap_struct
,
2499 ldap_state
->result
)));
2501 ldap_state
->entry
= ldap_first_entry(ldap_state
->ldap_struct
,
2502 ldap_state
->result
);
2503 ldap_state
->index
= 0;
2505 return NT_STATUS_OK
;
2508 /**********************************************************************
2509 End enumeration of the LDAP password list
2510 *********************************************************************/
2511 static void ldapsam_endsampwent(struct pdb_methods
*my_methods
)
2513 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2514 if (ldap_state
->result
) {
2515 ldap_msgfree(ldap_state
->result
);
2516 ldap_state
->result
= NULL
;
2520 /**********************************************************************
2521 Get the next entry in the LDAP password database
2522 *********************************************************************/
2523 static NTSTATUS
ldapsam_getsampwent(struct pdb_methods
*my_methods
, SAM_ACCOUNT
*user
)
2525 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
2526 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2529 /* The rebind proc needs this *HACK*. We are not multithreaded, so
2530 this will work, but it's not nice. */
2531 static_ldap_state
= ldap_state
;
2534 if (!ldap_state
->entry
)
2537 ldap_state
->index
++;
2538 bret
= init_sam_from_ldap(ldap_state
, user
, ldap_state
->entry
);
2540 ldap_state
->entry
= ldap_next_entry(ldap_state
->ldap_struct
,
2544 return NT_STATUS_OK
;
2547 /**********************************************************************
2548 Get SAM_ACCOUNT entry from LDAP by username
2549 *********************************************************************/
2550 static NTSTATUS
ldapsam_getsampwnam(struct pdb_methods
*my_methods
, SAM_ACCOUNT
*user
, const char *sname
)
2552 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
2553 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2554 LDAPMessage
*result
;
2560 attr_list
= get_userattr_list( ldap_state
->schema_ver
);
2561 rc
= ldapsam_search_suffix_by_name(ldap_state
, sname
, &result
, attr_list
);
2562 free_attr_list( attr_list
);
2564 if ( rc
!= LDAP_SUCCESS
)
2565 return NT_STATUS_NO_SUCH_USER
;
2567 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
2571 ("Unable to locate user [%s] count=%d\n", sname
,
2573 return NT_STATUS_NO_SUCH_USER
;
2574 } else if (count
> 1) {
2576 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname
,
2578 return NT_STATUS_NO_SUCH_USER
;
2581 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
2583 if (!init_sam_from_ldap(ldap_state
, user
, entry
)) {
2584 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname
));
2585 ldap_msgfree(result
);
2586 return NT_STATUS_NO_SUCH_USER
;
2588 ldap_msgfree(result
);
2591 ldap_msgfree(result
);
2596 /**********************************************************************
2597 Get SAM_ACCOUNT entry from LDAP by SID
2598 *********************************************************************/
2599 static NTSTATUS
ldapsam_getsampwsid(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* user
, const DOM_SID
*sid
)
2601 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
2602 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2603 LDAPMessage
*result
;
2610 switch ( ldap_state
->schema_ver
)
2612 case SCHEMAVER_SAMBASAMACCOUNT
:
2613 attr_list
= get_userattr_list(ldap_state
->schema_ver
);
2614 rc
= ldapsam_search_suffix_by_sid(ldap_state
, sid
, &result
, attr_list
);
2615 free_attr_list( attr_list
);
2617 if ( rc
!= LDAP_SUCCESS
)
2618 return NT_STATUS_NO_SUCH_USER
;
2621 case SCHEMAVER_SAMBAACCOUNT
:
2624 if (!sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
)) {
2625 return NT_STATUS_NO_SUCH_USER
;
2628 attr_list
= get_userattr_list(ldap_state
->schema_ver
);
2629 rc
= ldapsam_search_suffix_by_rid(ldap_state
, rid
, &result
, attr_list
);
2630 free_attr_list( attr_list
);
2632 if ( rc
!= LDAP_SUCCESS
)
2633 return NT_STATUS_NO_SUCH_USER
;
2638 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
2643 ("Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string
, sid
),
2645 return NT_STATUS_NO_SUCH_USER
;
2650 ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string
, sid
),
2652 return NT_STATUS_NO_SUCH_USER
;
2655 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
2658 if (!init_sam_from_ldap(ldap_state
, user
, entry
)) {
2659 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
2660 ldap_msgfree(result
);
2661 return NT_STATUS_NO_SUCH_USER
;
2663 ldap_msgfree(result
);
2666 ldap_msgfree(result
);
2671 /********************************************************************
2672 Do the actual modification - also change a plaittext passord if
2674 **********************************************************************/
2676 static NTSTATUS
ldapsam_modify_entry(struct pdb_methods
*my_methods
,
2677 SAM_ACCOUNT
*newpwd
, char *dn
,
2678 LDAPMod
**mods
, int ldap_op
,
2679 BOOL (*need_update
)(const SAM_ACCOUNT
*,
2682 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2685 if (!my_methods
|| !newpwd
|| !dn
) {
2686 return NT_STATUS_INVALID_PARAMETER
;
2690 DEBUG(5,("mods is empty: nothing to modify\n"));
2691 /* may be password change below however */
2696 make_a_mod(&mods
, LDAP_MOD_ADD
, "objectclass", LDAP_OBJ_ACCOUNT
);
2697 rc
= ldapsam_add(ldap_state
, dn
, mods
);
2699 case LDAP_MOD_REPLACE
:
2700 rc
= ldapsam_modify(ldap_state
, dn
,mods
);
2703 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op
));
2704 return NT_STATUS_INVALID_PARAMETER
;
2707 if (rc
!=LDAP_SUCCESS
) {
2708 char *ld_error
= NULL
;
2709 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
2712 ("failed to %s user dn= %s with: %s\n\t%s\n",
2713 ldap_op
== LDAP_MOD_ADD
? "add" : "modify",
2714 dn
, ldap_err2string(rc
),
2715 ld_error
?ld_error
:"unknown"));
2716 SAFE_FREE(ld_error
);
2717 return NT_STATUS_UNSUCCESSFUL
;
2721 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
2722 if (!(pdb_get_acct_ctrl(newpwd
)&(ACB_WSTRUST
|ACB_SVRTRUST
|ACB_DOMTRUST
)) &&
2723 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF
) &&
2724 need_update(newpwd
, PDB_PLAINTEXT_PW
) &&
2725 (pdb_get_plaintext_passwd(newpwd
)!=NULL
)) {
2729 struct berval
*retdata
;
2730 char *utf8_password
;
2733 if (push_utf8_allocate(&utf8_password
, pdb_get_plaintext_passwd(newpwd
)) == (size_t)-1) {
2734 return NT_STATUS_NO_MEMORY
;
2737 if (push_utf8_allocate(&utf8_dn
, dn
) == (size_t)-1) {
2738 return NT_STATUS_NO_MEMORY
;
2741 if ((ber
= ber_alloc_t(LBER_USE_DER
))==NULL
) {
2742 DEBUG(0,("ber_alloc_t returns NULL\n"));
2743 SAFE_FREE(utf8_password
);
2744 return NT_STATUS_UNSUCCESSFUL
;
2747 ber_printf (ber
, "{");
2748 ber_printf (ber
, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID
, utf8_dn
);
2749 ber_printf (ber
, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW
, utf8_password
);
2750 ber_printf (ber
, "N}");
2752 if ((rc
= ber_flatten (ber
, &bv
))<0) {
2753 DEBUG(0,("ber_flatten returns a value <0\n"));
2756 SAFE_FREE(utf8_password
);
2757 return NT_STATUS_UNSUCCESSFUL
;
2761 SAFE_FREE(utf8_password
);
2764 if ((rc
= ldapsam_extended_operation(ldap_state
, LDAP_EXOP_X_MODIFY_PASSWD
,
2765 bv
, NULL
, NULL
, &retoid
, &retdata
))!=LDAP_SUCCESS
) {
2766 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
2767 pdb_get_username(newpwd
),ldap_err2string(rc
)));
2769 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd
)));
2770 #ifdef DEBUG_PASSWORD
2771 DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd
)));
2773 ber_bvfree(retdata
);
2774 ber_memfree(retoid
);
2779 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
2780 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
2781 return NT_STATUS_OK
;
2784 /**********************************************************************
2785 Delete entry from LDAP for username
2786 *********************************************************************/
2787 static NTSTATUS
ldapsam_delete_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* sam_acct
)
2789 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2792 LDAPMessage
*result
;
2798 DEBUG(0, ("sam_acct was NULL!\n"));
2799 return NT_STATUS_INVALID_PARAMETER
;
2802 sname
= pdb_get_username(sam_acct
);
2804 DEBUG (3, ("Deleting user %s from LDAP.\n", sname
));
2806 attr_list
= get_userattr_list( ldap_state
->schema_ver
);
2807 rc
= ldapsam_search_suffix_by_name(ldap_state
, sname
, &result
, attr_list
);
2809 if (rc
!= LDAP_SUCCESS
) {
2810 free_attr_list( attr_list
);
2811 return NT_STATUS_NO_SUCH_USER
;
2814 switch ( ldap_state
->schema_ver
)
2816 case SCHEMAVER_SAMBASAMACCOUNT
:
2817 fstrcpy( objclass
, LDAP_OBJ_SAMBASAMACCOUNT
);
2820 case SCHEMAVER_SAMBAACCOUNT
:
2821 fstrcpy( objclass
, LDAP_OBJ_SAMBAACCOUNT
);
2824 fstrcpy( objclass
, "UNKNOWN" );
2825 DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
2829 ret
= ldapsam_delete_entry(ldap_state
, result
, objclass
, attr_list
);
2830 ldap_msgfree(result
);
2831 free_attr_list( attr_list
);
2836 /**********************************************************************
2837 Helper function to determine for update_sam_account whether
2838 we need LDAP modification.
2839 *********************************************************************/
2840 static BOOL
element_is_changed(const SAM_ACCOUNT
*sampass
,
2841 enum pdb_elements element
)
2843 return IS_SAM_CHANGED(sampass
, element
);
2846 /**********************************************************************
2848 *********************************************************************/
2849 static NTSTATUS
ldapsam_update_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* newpwd
)
2851 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
2852 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2855 LDAPMessage
*result
;
2860 attr_list
= get_userattr_list(ldap_state
->schema_ver
);
2861 rc
= ldapsam_search_suffix_by_name(ldap_state
, pdb_get_username(newpwd
), &result
, attr_list
);
2862 free_attr_list( attr_list
);
2863 if (rc
!= LDAP_SUCCESS
)
2864 return NT_STATUS_UNSUCCESSFUL
;
2866 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) == 0) {
2867 DEBUG(0, ("No user to modify!\n"));
2868 ldap_msgfree(result
);
2869 return NT_STATUS_UNSUCCESSFUL
;
2872 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
2873 dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
2875 if (!init_ldap_from_sam(ldap_state
, entry
, &mods
, newpwd
,
2876 element_is_changed
)) {
2877 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2878 ldap_msgfree(result
);
2879 return NT_STATUS_UNSUCCESSFUL
;
2882 ldap_msgfree(result
);
2885 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2886 pdb_get_username(newpwd
)));
2887 ldap_mods_free(mods
, 1);
2888 return NT_STATUS_OK
;
2891 ret
= ldapsam_modify_entry(my_methods
,newpwd
,dn
,mods
,LDAP_MOD_REPLACE
, element_is_changed
);
2892 ldap_mods_free(mods
,1);
2894 if (!NT_STATUS_IS_OK(ret
)) {
2895 char *ld_error
= NULL
;
2896 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
2898 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2899 pdb_get_username(newpwd
), ld_error
?ld_error
:"(unknwon)", ldap_err2string(rc
)));
2900 SAFE_FREE(ld_error
);
2904 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2905 pdb_get_username(newpwd
)));
2906 return NT_STATUS_OK
;
2909 /**********************************************************************
2910 Helper function to determine for update_sam_account whether
2911 we need LDAP modification.
2912 *********************************************************************/
2913 static BOOL
element_is_set_or_changed(const SAM_ACCOUNT
*sampass
,
2914 enum pdb_elements element
)
2916 return (IS_SAM_SET(sampass
, element
) ||
2917 IS_SAM_CHANGED(sampass
, element
));
2920 /**********************************************************************
2921 Add SAM_ACCOUNT to LDAP
2922 *********************************************************************/
2924 static NTSTATUS
ldapsam_add_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* newpwd
)
2926 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
2927 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
2929 LDAPMessage
*result
= NULL
;
2930 LDAPMessage
*entry
= NULL
;
2932 LDAPMod
**mods
= NULL
;
2937 const char *username
= pdb_get_username(newpwd
);
2940 if (!username
|| !*username
) {
2941 DEBUG(0, ("Cannot add user without a username!\n"));
2942 return NT_STATUS_INVALID_PARAMETER
;
2945 /* free this list after the second search or in case we exit on failure */
2947 attr_list
= get_userattr_list(ldap_state
->schema_ver
);
2948 rc
= ldapsam_search_suffix_by_name (ldap_state
, username
, &result
, attr_list
);
2950 if (rc
!= LDAP_SUCCESS
) {
2951 free_attr_list( attr_list
);
2952 return NT_STATUS_UNSUCCESSFUL
;
2955 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) != 0) {
2956 DEBUG(0,("User '%s' already in the base, with samba attributes\n",
2958 ldap_msgfree(result
);
2959 free_attr_list( attr_list
);
2960 return NT_STATUS_UNSUCCESSFUL
;
2962 ldap_msgfree(result
);
2964 /* does the entry already exist but without a samba rttibutes?
2965 we don't really care what attributes are returned here */
2967 escape_user
= escape_ldap_string_alloc( username
);
2968 pstrcpy( filter
, lp_ldap_filter() );
2969 all_string_sub( filter
, "%u", escape_user
, sizeof(filter
) );
2970 SAFE_FREE( escape_user
);
2972 rc
= ldapsam_search_suffix(ldap_state
, filter
, attr_list
, &result
);
2973 free_attr_list( attr_list
);
2975 if ( rc
!= LDAP_SUCCESS
)
2976 return NT_STATUS_UNSUCCESSFUL
;
2978 num_result
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
2980 if (num_result
> 1) {
2981 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2982 ldap_msgfree(result
);
2983 return NT_STATUS_UNSUCCESSFUL
;
2986 /* Check if we need to update an existing entry */
2987 if (num_result
== 1) {
2990 DEBUG(3,("User exists without samba attributes: adding them\n"));
2991 ldap_op
= LDAP_MOD_REPLACE
;
2992 entry
= ldap_first_entry (ldap_state
->ldap_struct
, result
);
2993 tmp
= ldap_get_dn (ldap_state
->ldap_struct
, entry
);
2994 slprintf (dn
, sizeof (dn
) - 1, "%s", tmp
);
2997 /* Check if we need to add an entry */
2998 DEBUG(3,("Adding new user\n"));
2999 ldap_op
= LDAP_MOD_ADD
;
3000 if (username
[strlen(username
)-1] == '$') {
3001 slprintf (dn
, sizeof (dn
) - 1, "uid=%s,%s", username
, lp_ldap_machine_suffix ());
3003 slprintf (dn
, sizeof (dn
) - 1, "uid=%s,%s", username
, lp_ldap_user_suffix ());
3007 if (!init_ldap_from_sam(ldap_state
, entry
, &mods
, newpwd
,
3008 element_is_set_or_changed
)) {
3009 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
3010 ldap_msgfree(result
);
3011 return NT_STATUS_UNSUCCESSFUL
;
3014 ldap_msgfree(result
);
3017 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd
)));
3018 return NT_STATUS_UNSUCCESSFUL
;
3020 switch ( ldap_state
->schema_ver
)
3022 case SCHEMAVER_SAMBAACCOUNT
:
3023 make_a_mod(&mods
, LDAP_MOD_ADD
, "objectclass", LDAP_OBJ_SAMBAACCOUNT
);
3025 case SCHEMAVER_SAMBASAMACCOUNT
:
3026 make_a_mod(&mods
, LDAP_MOD_ADD
, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT
);
3029 DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
3033 ret
= ldapsam_modify_entry(my_methods
,newpwd
,dn
,mods
,ldap_op
, element_is_set_or_changed
);
3034 if (NT_STATUS_IS_ERR(ret
)) {
3035 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
3036 pdb_get_username(newpwd
),dn
));
3037 ldap_mods_free(mods
,1);
3041 DEBUG(2,("added: uid == %s in the LDAP database\n", pdb_get_username(newpwd
)));
3042 ldap_mods_free(mods
, 1);
3044 return NT_STATUS_OK
;
3047 /**********************************************************************
3049 *********************************************************************/
3051 static void free_private_data(void **vp
)
3053 struct ldapsam_privates
**ldap_state
= (struct ldapsam_privates
**)vp
;
3055 ldapsam_close(*ldap_state
);
3057 if ((*ldap_state
)->bind_secret
) {
3058 memset((*ldap_state
)->bind_secret
, '\0', strlen((*ldap_state
)->bind_secret
));
3061 ldapsam_close(*ldap_state
);
3063 SAFE_FREE((*ldap_state
)->bind_dn
);
3064 SAFE_FREE((*ldap_state
)->bind_secret
);
3068 /* No need to free any further, as it is talloc()ed */
3071 /**********************************************************************
3072 *********************************************************************/
3074 static int ldapsam_search_one_group (struct ldapsam_privates
*ldap_state
,
3076 LDAPMessage
** result
)
3078 int scope
= LDAP_SCOPE_SUBTREE
;
3082 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter
));
3085 attr_list
= get_attr_list(groupmap_attr_list
);
3086 rc
= ldapsam_search(ldap_state
, lp_ldap_suffix (), scope
,
3087 filter
, attr_list
, 0, result
);
3088 free_attr_list( attr_list
);
3090 if (rc
!= LDAP_SUCCESS
) {
3091 char *ld_error
= NULL
;
3092 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
3094 DEBUG(0, ("ldapsam_search_one_group: "
3095 "Problem during the LDAP search: LDAP error: %s (%s)",
3096 ld_error
?ld_error
:"(unknown)", ldap_err2string(rc
)));
3097 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
3098 lp_ldap_suffix(), filter
));
3099 SAFE_FREE(ld_error
);
3105 /**********************************************************************
3106 *********************************************************************/
3108 static BOOL
init_group_from_ldap(struct ldapsam_privates
*ldap_state
,
3109 GROUP_MAP
*map
, LDAPMessage
*entry
)
3113 if (ldap_state
== NULL
|| map
== NULL
|| entry
== NULL
||
3114 ldap_state
->ldap_struct
== NULL
)
3116 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
3120 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
3121 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GIDNUMBER
), temp
))
3123 DEBUG(0, ("Mandatory attribute %s not found\n",
3124 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_GIDNUMBER
)));
3127 DEBUG(2, ("Entry found for group: %s\n", temp
));
3129 map
->gid
= (gid_t
)atol(temp
);
3131 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
3132 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_GROUP_SID
), temp
))
3134 DEBUG(0, ("Mandatory attribute %s not found\n",
3135 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_GROUP_SID
)));
3138 string_to_sid(&map
->sid
, temp
);
3140 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
3141 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_GROUP_TYPE
), temp
))
3143 DEBUG(0, ("Mandatory attribute %s not found\n",
3144 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_GROUP_TYPE
)));
3147 map
->sid_name_use
= (uint32
)atol(temp
);
3149 if ((map
->sid_name_use
< SID_NAME_USER
) ||
3150 (map
->sid_name_use
> SID_NAME_UNKNOWN
)) {
3151 DEBUG(0, ("Unknown Group type: %d\n", map
->sid_name_use
));
3155 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
3156 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_DISPLAY_NAME
), temp
))
3159 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
3160 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_CN
), temp
))
3162 DEBUG(0, ("Attributes cn not found either "
3163 "for gidNumber(%i)\n",map
->gid
));
3167 fstrcpy(map
->nt_name
, temp
);
3169 if (!get_single_attribute(ldap_state
->ldap_struct
, entry
,
3170 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_DESC
), temp
))
3174 fstrcpy(map
->comment
, temp
);
3176 map
->systemaccount
= 0;
3177 init_privilege(&map
->priv_set
);
3182 /**********************************************************************
3183 *********************************************************************/
3185 static BOOL
init_ldap_from_group(LDAP
*ldap_struct
,
3186 LDAPMessage
*existing
,
3188 const GROUP_MAP
*map
)
3192 if (mods
== NULL
|| map
== NULL
) {
3193 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
3199 sid_to_string(tmp
, &map
->sid
);
3200 make_ldap_mod(ldap_struct
, existing
, mods
,
3201 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GROUP_SID
), tmp
);
3202 snprintf(tmp
, sizeof(tmp
)-1, "%i", map
->sid_name_use
);
3203 make_ldap_mod(ldap_struct
, existing
, mods
,
3204 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GROUP_TYPE
), tmp
);
3206 make_ldap_mod(ldap_struct
, existing
, mods
,
3207 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_DISPLAY_NAME
), map
->nt_name
);
3208 make_ldap_mod(ldap_struct
, existing
, mods
,
3209 get_attr_key2string( groupmap_attr_list
, LDAP_ATTR_DESC
), map
->comment
);
3214 /**********************************************************************
3215 *********************************************************************/
3217 static NTSTATUS
ldapsam_getgroup(struct pdb_methods
*methods
,
3221 struct ldapsam_privates
*ldap_state
=
3222 (struct ldapsam_privates
*)methods
->private_data
;
3223 LDAPMessage
*result
;
3227 if (ldapsam_search_one_group(ldap_state
, filter
, &result
)
3229 return NT_STATUS_NO_SUCH_GROUP
;
3232 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
3235 DEBUG(4, ("Did not find group for filter %s\n", filter
));
3236 return NT_STATUS_NO_SUCH_GROUP
;
3240 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
3242 return NT_STATUS_NO_SUCH_GROUP
;
3245 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
3248 ldap_msgfree(result
);
3249 return NT_STATUS_UNSUCCESSFUL
;
3252 if (!init_group_from_ldap(ldap_state
, map
, entry
)) {
3253 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
3255 ldap_msgfree(result
);
3256 return NT_STATUS_NO_SUCH_GROUP
;
3259 ldap_msgfree(result
);
3260 return NT_STATUS_OK
;
3263 /**********************************************************************
3264 *********************************************************************/
3266 static NTSTATUS
ldapsam_getgrsid(struct pdb_methods
*methods
, GROUP_MAP
*map
,
3267 DOM_SID sid
, BOOL with_priv
)
3271 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(%s=%s))",
3273 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GROUP_SID
),
3274 sid_string_static(&sid
));
3276 return ldapsam_getgroup(methods
, filter
, map
);
3279 /**********************************************************************
3280 *********************************************************************/
3282 static NTSTATUS
ldapsam_getgrgid(struct pdb_methods
*methods
, GROUP_MAP
*map
,
3283 gid_t gid
, BOOL with_priv
)
3287 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(%s=%d))",
3289 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GIDNUMBER
),
3292 return ldapsam_getgroup(methods
, filter
, map
);
3295 /**********************************************************************
3296 *********************************************************************/
3298 static NTSTATUS
ldapsam_getgrnam(struct pdb_methods
*methods
, GROUP_MAP
*map
,
3299 char *name
, BOOL with_priv
)
3303 /* TODO: Escaping of name? */
3305 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
3307 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_DISPLAY_NAME
), name
,
3308 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_CN
), name
);
3310 return ldapsam_getgroup(methods
, filter
, map
);
3313 /**********************************************************************
3314 *********************************************************************/
3316 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates
*ldap_state
,
3318 LDAPMessage
**result
)
3322 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(%s=%i))",
3323 LDAP_OBJ_POSIXGROUP
,
3324 get_attr_key2string(groupmap_attr_list
, LDAP_ATTR_GIDNUMBER
),
3327 return ldapsam_search_one_group(ldap_state
, filter
, result
);
3330 /**********************************************************************
3331 *********************************************************************/
3333 static NTSTATUS
ldapsam_add_group_mapping_entry(struct pdb_methods
*methods
,
3336 struct ldapsam_privates
*ldap_state
=
3337 (struct ldapsam_privates
*)methods
->private_data
;
3338 LDAPMessage
*result
= NULL
;
3339 LDAPMod
**mods
= NULL
;
3349 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods
, &dummy
,
3350 map
->gid
, False
))) {
3351 DEBUG(0, ("Group %i already exists in LDAP\n", map
->gid
));
3352 return NT_STATUS_UNSUCCESSFUL
;
3355 rc
= ldapsam_search_one_group_by_gid(ldap_state
, map
->gid
, &result
);
3356 if (rc
!= LDAP_SUCCESS
) {
3357 return NT_STATUS_UNSUCCESSFUL
;
3360 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) != 1) {
3361 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
3363 ldap_msgfree(result
);
3364 return NT_STATUS_UNSUCCESSFUL
;
3367 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
3368 tmp
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
3372 if (!init_ldap_from_group(ldap_state
->ldap_struct
,
3373 result
, &mods
, map
)) {
3374 DEBUG(0, ("init_ldap_from_group failed!\n"));
3375 ldap_mods_free(mods
, 1);
3376 ldap_msgfree(result
);
3377 return NT_STATUS_UNSUCCESSFUL
;
3380 ldap_msgfree(result
);
3383 DEBUG(0, ("mods is empty\n"));
3384 return NT_STATUS_UNSUCCESSFUL
;
3387 make_a_mod(&mods
, LDAP_MOD_ADD
, "objectClass",
3388 "sambaGroupMapping");
3390 rc
= ldapsam_modify(ldap_state
, dn
, mods
);
3391 ldap_mods_free(mods
, 1);
3393 if (rc
!= LDAP_SUCCESS
) {
3394 char *ld_error
= NULL
;
3395 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
3397 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map
->gid
,
3398 ld_error
? ld_error
: "(unknown)", ldap_err2string(rc
)));
3399 SAFE_FREE(ld_error
);
3400 return NT_STATUS_UNSUCCESSFUL
;
3403 DEBUG(2, ("successfully modified group %i in LDAP\n", map
->gid
));
3404 return NT_STATUS_OK
;
3407 /**********************************************************************
3408 *********************************************************************/
3410 static NTSTATUS
ldapsam_update_group_mapping_entry(struct pdb_methods
*methods
,
3413 struct ldapsam_privates
*ldap_state
=
3414 (struct ldapsam_privates
*)methods
->private_data
;
3417 LDAPMessage
*result
;
3421 rc
= ldapsam_search_one_group_by_gid(ldap_state
, map
->gid
, &result
);
3423 if (rc
!= LDAP_SUCCESS
) {
3424 return NT_STATUS_UNSUCCESSFUL
;
3427 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) == 0) {
3428 DEBUG(0, ("No group to modify!\n"));
3429 ldap_msgfree(result
);
3430 return NT_STATUS_UNSUCCESSFUL
;
3433 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
3434 dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
3436 if (!init_ldap_from_group(ldap_state
->ldap_struct
,
3437 result
, &mods
, map
)) {
3438 DEBUG(0, ("init_ldap_from_group failed\n"));
3439 ldap_msgfree(result
);
3440 return NT_STATUS_UNSUCCESSFUL
;
3443 ldap_msgfree(result
);
3446 DEBUG(4, ("mods is empty: nothing to do\n"));
3447 return NT_STATUS_UNSUCCESSFUL
;
3450 rc
= ldapsam_modify(ldap_state
, dn
, mods
);
3452 ldap_mods_free(mods
, 1);
3454 if (rc
!= LDAP_SUCCESS
) {
3455 char *ld_error
= NULL
;
3456 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
3458 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map
->gid
,
3459 ld_error
? ld_error
: "(unknown)", ldap_err2string(rc
)));
3460 SAFE_FREE(ld_error
);
3463 DEBUG(2, ("successfully modified group %i in LDAP\n", map
->gid
));
3464 return NT_STATUS_OK
;
3467 /**********************************************************************
3468 *********************************************************************/
3470 static NTSTATUS
ldapsam_delete_group_mapping_entry(struct pdb_methods
*methods
,
3473 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)methods
->private_data
;
3474 pstring sidstring
, filter
;
3475 LDAPMessage
*result
;
3480 sid_to_string(sidstring
, &sid
);
3482 snprintf(filter
, sizeof(filter
)-1, "(&(objectClass=%s)(%s=%s))",
3483 LDAP_OBJ_GROUPMAP
, LDAP_ATTRIBUTE_SID
, sidstring
);
3485 rc
= ldapsam_search_one_group(ldap_state
, filter
, &result
);
3487 if (rc
!= LDAP_SUCCESS
) {
3488 return NT_STATUS_NO_SUCH_GROUP
;
3491 attr_list
= get_attr_list( groupmap_attr_list_to_delete
);
3492 ret
= ldapsam_delete_entry(ldap_state
, result
, LDAP_OBJ_GROUPMAP
, attr_list
);
3493 free_attr_list ( attr_list
);
3495 ldap_msgfree(result
);
3500 /**********************************************************************
3501 *********************************************************************/
3503 static NTSTATUS
ldapsam_setsamgrent(struct pdb_methods
*my_methods
, BOOL update
)
3505 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
3510 snprintf( filter
, sizeof(filter
)-1, "(objectclass=%s)", LDAP_OBJ_GROUPMAP
);
3511 attr_list
= get_attr_list( groupmap_attr_list
);
3512 rc
= ldapsam_search(ldap_state
, lp_ldap_suffix(),
3513 LDAP_SCOPE_SUBTREE
, filter
,
3514 attr_list
, 0, &ldap_state
->result
);
3515 free_attr_list( attr_list
);
3517 if (rc
!= LDAP_SUCCESS
) {
3518 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc
)));
3519 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
3520 ldap_msgfree(ldap_state
->result
);
3521 ldap_state
->result
= NULL
;
3522 return NT_STATUS_UNSUCCESSFUL
;
3525 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
3526 ldap_count_entries(ldap_state
->ldap_struct
,
3527 ldap_state
->result
)));
3529 ldap_state
->entry
= ldap_first_entry(ldap_state
->ldap_struct
, ldap_state
->result
);
3530 ldap_state
->index
= 0;
3532 return NT_STATUS_OK
;
3535 /**********************************************************************
3536 *********************************************************************/
3538 static void ldapsam_endsamgrent(struct pdb_methods
*my_methods
)
3540 ldapsam_endsampwent(my_methods
);
3543 /**********************************************************************
3544 *********************************************************************/
3546 static NTSTATUS
ldapsam_getsamgrent(struct pdb_methods
*my_methods
,
3549 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
3550 struct ldapsam_privates
*ldap_state
= (struct ldapsam_privates
*)my_methods
->private_data
;
3553 /* The rebind proc needs this *HACK*. We are not multithreaded, so
3554 this will work, but it's not nice. */
3555 static_ldap_state
= ldap_state
;
3558 if (!ldap_state
->entry
)
3561 ldap_state
->index
++;
3562 bret
= init_group_from_ldap(ldap_state
, map
, ldap_state
->entry
);
3564 ldap_state
->entry
= ldap_next_entry(ldap_state
->ldap_struct
,
3568 return NT_STATUS_OK
;
3571 /**********************************************************************
3572 *********************************************************************/
3574 static NTSTATUS
ldapsam_enum_group_mapping(struct pdb_methods
*methods
,
3575 enum SID_NAME_USE sid_name_use
,
3576 GROUP_MAP
**rmap
, int *num_entries
,
3577 BOOL unix_only
, BOOL with_priv
)
3587 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods
, False
))) {
3588 DEBUG(0, ("Unable to open passdb\n"));
3589 return NT_STATUS_ACCESS_DENIED
;
3592 while (NT_STATUS_IS_OK(nt_status
= ldapsam_getsamgrent(methods
, &map
))) {
3593 if (sid_name_use
!= SID_NAME_UNKNOWN
&&
3594 sid_name_use
!= map
.sid_name_use
) {
3595 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map
.nt_name
));
3598 if (unix_only
==ENUM_ONLY_MAPPED
&& map
.gid
==-1) {
3599 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map
.nt_name
));
3603 mapt
=(GROUP_MAP
*)Realloc((*rmap
), (entries
+1)*sizeof(GROUP_MAP
));
3605 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
3607 return NT_STATUS_UNSUCCESSFUL
;
3612 mapt
[entries
] = map
;
3617 ldapsam_endsamgrent(methods
);
3619 *num_entries
= entries
;
3621 return NT_STATUS_OK
;
3624 /**********************************************************************
3625 *********************************************************************/
3627 static NTSTATUS
pdb_init_ldapsam_common(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
,
3628 const char *location
)
3631 struct ldapsam_privates
*ldap_state
;
3633 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_methods(pdb_context
->mem_ctx
, pdb_method
))) {
3637 (*pdb_method
)->name
= "ldapsam";
3639 (*pdb_method
)->setsampwent
= ldapsam_setsampwent
;
3640 (*pdb_method
)->endsampwent
= ldapsam_endsampwent
;
3641 (*pdb_method
)->getsampwent
= ldapsam_getsampwent
;
3642 (*pdb_method
)->getsampwnam
= ldapsam_getsampwnam
;
3643 (*pdb_method
)->getsampwsid
= ldapsam_getsampwsid
;
3644 (*pdb_method
)->add_sam_account
= ldapsam_add_sam_account
;
3645 (*pdb_method
)->update_sam_account
= ldapsam_update_sam_account
;
3646 (*pdb_method
)->delete_sam_account
= ldapsam_delete_sam_account
;
3648 (*pdb_method
)->getgrsid
= ldapsam_getgrsid
;
3649 (*pdb_method
)->getgrgid
= ldapsam_getgrgid
;
3650 (*pdb_method
)->getgrnam
= ldapsam_getgrnam
;
3651 (*pdb_method
)->add_group_mapping_entry
= ldapsam_add_group_mapping_entry
;
3652 (*pdb_method
)->update_group_mapping_entry
= ldapsam_update_group_mapping_entry
;
3653 (*pdb_method
)->delete_group_mapping_entry
= ldapsam_delete_group_mapping_entry
;
3654 (*pdb_method
)->enum_group_mapping
= ldapsam_enum_group_mapping
;
3656 /* TODO: Setup private data and free */
3658 ldap_state
= talloc_zero(pdb_context
->mem_ctx
, sizeof(struct ldapsam_privates
));
3661 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
3662 return NT_STATUS_NO_MEMORY
;
3666 ldap_state
->uri
= talloc_strdup(pdb_context
->mem_ctx
, location
);
3668 ldap_state
->uri
= "ldap://localhost";
3671 ldap_state
->domain_name
= talloc_strdup(pdb_context
->mem_ctx
, get_global_sam_name());
3672 if (!ldap_state
->domain_name
) {
3673 return NT_STATUS_NO_MEMORY
;
3676 sid_copy(&ldap_state
->domain_sid
, get_global_sam_sid());
3678 (*pdb_method
)->private_data
= ldap_state
;
3680 (*pdb_method
)->free_private_data
= free_private_data
;
3682 return NT_STATUS_OK
;
3685 /**********************************************************************
3686 *********************************************************************/
3688 static NTSTATUS
pdb_init_ldapsam_compat(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
, const char *location
)
3691 struct ldapsam_privates
*ldap_state
;
3693 if (!NT_STATUS_IS_OK(nt_status
= pdb_init_ldapsam_common(pdb_context
, pdb_method
, location
))) {
3697 (*pdb_method
)->name
= "ldapsam_compat";
3699 ldap_state
= (*pdb_method
)->private_data
;
3700 ldap_state
->schema_ver
= SCHEMAVER_SAMBAACCOUNT
;
3703 ldap_state
->uri
= talloc_strdup(pdb_context
->mem_ctx
, location
);
3705 #ifndef WITH_LDAP_SAMCONFIG
3706 ldap_state
->uri
= "ldap://localhost";
3708 int ldap_port
= lp_ldap_port();
3710 /* remap default port if not using SSL (ie clear or TLS) */
3711 if ( (lp_ldap_ssl() != LDAP_SSL_ON
) && (ldap_port
== 636) ) {
3715 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
);
3716 if (!ldap_state
->uri
) {
3717 return NT_STATUS_NO_MEMORY
;
3722 return NT_STATUS_OK
;
3725 /**********************************************************************
3726 *********************************************************************/
3728 static NTSTATUS
pdb_init_ldapsam(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
, const char *location
)
3731 struct ldapsam_privates
*ldap_state
;
3732 uint32 low_idmap_uid
, high_idmap_uid
;
3733 uint32 low_idmap_gid
, high_idmap_gid
;
3735 if (!NT_STATUS_IS_OK(nt_status
= pdb_init_ldapsam_common(pdb_context
, pdb_method
, location
))) {
3739 (*pdb_method
)->name
= "ldapsam";
3741 ldap_state
= (*pdb_method
)->private_data
;
3742 ldap_state
->schema_ver
= SCHEMAVER_SAMBASAMACCOUNT
;
3743 ldap_state
->permit_non_unix_accounts
= False
;
3745 /* check for non-unix account ranges */
3747 if (lp_idmap_uid(&low_idmap_uid
, &high_idmap_uid
)
3748 && lp_idmap_gid(&low_idmap_gid
, &high_idmap_gid
))
3750 DEBUG(2, ("Enabling non-unix account ranges\n"));
3752 ldap_state
->permit_non_unix_accounts
= True
;
3754 ldap_state
->low_allocated_user_rid
= fallback_pdb_uid_to_user_rid(low_idmap_uid
);
3755 ldap_state
->high_allocated_user_rid
= fallback_pdb_uid_to_user_rid(high_idmap_uid
);
3756 ldap_state
->low_allocated_group_rid
= pdb_gid_to_group_rid(low_idmap_gid
);
3757 ldap_state
->high_allocated_group_rid
= pdb_gid_to_group_rid(high_idmap_gid
);
3760 return NT_STATUS_OK
;
3763 NTSTATUS
pdb_ldap_init(void)
3766 if (!NT_STATUS_IS_OK(nt_status
= smb_register_passdb(PASSDB_INTERFACE_VERSION
, "ldapsam", pdb_init_ldapsam
)))
3769 if (!NT_STATUS_IS_OK(nt_status
= smb_register_passdb(PASSDB_INTERFACE_VERSION
, "ldapsam_compat", pdb_init_ldapsam_compat
)))
3772 return NT_STATUS_OK
;