2 Unix SMB/Netbios implementation.
4 LDAP protocol helper functions for SAMBA
5 Copyright (C) Gerald Carter 2001
6 Copyright (C) Shahms King 2001
7 Copyright (C) Jean François Micouleau 1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 * persistent connections: if using NSS LDAP, many connections are made
30 * however, using only one within Samba would be nice
32 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
34 * Other LDAP based login attributes: accountExpires, etc.
35 * (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
36 * structures don't have fields for some of these attributes)
38 * SSL is done, but can't get the certificate based authentication to work
39 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
42 /* NOTE: this will NOT work against an Active Directory server
43 * due to the fact that the two password fields cannot be retrieved
44 * from a server; recommend using security = domain in this situation
51 #ifndef LDAP_OPT_SUCCESS
52 #define LDAP_OPT_SUCCESS LDAP_SUCCESS
56 #define SAM_ACCOUNT struct sam_passwd
59 struct ldap_enum_info
{
66 static struct ldap_enum_info global_ldap_ent
;
67 static pstring ldap_secret
;
70 extern pstring samlogon_user
;
71 extern BOOL sam_logon_in_ssb
;
74 * attributes needed from sambaAccount
76 * objectclass ( 1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' SUP top AUXILIARY
77 * DESC 'Samba Auxilary Account'
79 * MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $
80 * logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $
81 * displayName $ smbHome $ homeDrive $ scriptPath $ profilePath $
82 * description $ userWorkstations $ primaryGroupID $ domain ))
111 /*******************************************************************
112 open a connection to the ldap server.
113 ******************************************************************/
114 static BOOL
ldap_open_connection (LDAP
** ldap_struct
)
119 uid_t uid
= geteuid();
122 DEBUG(5,("ldap_open_connection: starting...\n"));
124 * using sys_getpwnam() here since I'm assuming that the
125 * ldapsam is only used on a standalone server or PDC.
126 * winbind not in the picture....
129 if ( (pass
=sys_getpwuid(uid
)) == NULL
) {
130 DEBUG(0,("ldap_open_connection: Can't determine user of running process!\n"));
134 /* check that the user is in the domain admin group for connecting */
136 if ( (uid
!= 0) && !user_in_list(pass
->pw_name
, lp_domain_admin_group()) ) {
137 DEBUG(0, ("ldap_open_connection: cannot access LDAP when not root or a member of domain admin group..\n"));
141 port
= lp_ldap_port();
143 /* remap default port is no SSL */
144 if ( (lp_ldap_ssl() != LDAP_SSL_ON
) && (lp_ldap_port() == 636) ) {
148 DEBUG(10,("Initializing connection to %s on port %d\n",
149 lp_ldap_server(), port
));
151 if ((*ldap_struct
= ldap_init(lp_ldap_server(), port
)) == NULL
) {
152 DEBUG(0, ("The LDAP server is not responding !\n"));
156 /* Connect to older servers using SSL and V2 rather than Start TLS */
157 if (ldap_get_option(*ldap_struct
, LDAP_OPT_PROTOCOL_VERSION
, &version
) == LDAP_OPT_SUCCESS
)
159 if (version
!= LDAP_VERSION3
)
161 version
= LDAP_VERSION3
;
162 ldap_set_option (*ldap_struct
, LDAP_OPT_PROTOCOL_VERSION
, &version
);
166 switch (lp_ldap_ssl())
168 case LDAP_SSL_START_TLS
:
169 #ifdef HAVE_LDAP_START_TLS_S
170 if (ldap_get_option (*ldap_struct
, LDAP_OPT_PROTOCOL_VERSION
,
171 &version
) == LDAP_OPT_SUCCESS
)
173 if (version
< LDAP_VERSION3
)
175 version
= LDAP_VERSION3
;
176 ldap_set_option (*ldap_struct
, LDAP_OPT_PROTOCOL_VERSION
,
180 if ((rc
= ldap_start_tls_s (*ldap_struct
, NULL
, NULL
)) != LDAP_SUCCESS
)
182 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
183 ldap_err2string(rc
)));
186 DEBUG (2, ("StartTLS issued: using a TLS connection\n"));
188 DEBUG(0,("ldap_open_connection: StartTLS not supported by LDAP client libraries!\n"));
194 #ifdef LDAP_OPT_X_TLS
195 tls
= LDAP_OPT_X_TLS_HARD
;
196 if (ldap_set_option (*ldap_struct
, LDAP_OPT_X_TLS
, &tls
) != LDAP_SUCCESS
)
198 DEBUG(0, ("Failed to setup a TLS session\n"));
201 DEBUG(0,("LDAPS option set...!\n"));
203 DEBUG(0,("ldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
211 * No special needs to setup options prior to the LDAP
212 * bind (which should be called next via ldap_connect_system()
217 DEBUG(2, ("ldap_open_connection: connection opened\n"));
222 /*******************************************************************
223 ldap rebind proc to rebind w/ the admin dn when following referrals
224 *******************************************************************/
226 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
227 # if LDAP_SET_REBIND_PROC_ARGS == 3
228 static int rebindproc_with_state (LDAP
*ldap_struct
,
229 LDAP_CONST
char *url
,
231 ber_int_t msgid
, void *arg
)
232 # else /* LDAP_SET_REBIND_PROC_ARGS == 2 */
233 static int rebindproc (LDAP
*ldap_struct
,
234 LDAP_CONST
char *url
,
237 # endif /* LDAP_SET_REBIND_PROC_ARGS */
242 DEBUG(2,("ldap_connect_system: Rebinding as \"%s\", API: %d, PROC_ARGS: %d\n",
243 lp_ldap_admin_dn(), LDAP_API_VERSION
, LDAP_SET_REBIND_PROC_ARGS
));
245 /** @TODO Should we be doing something to check what servers we rebind to?
246 Could we get a referral to a machine that we don't want to give our
247 username and password to? */
249 if ( ( rc
= ldap_simple_bind_s( ldap_struct
, lp_ldap_admin_dn(), ldap_secret
) ) == LDAP_SUCCESS
)
251 DEBUG( 2, ( "Rebind successful\n" ) );
254 DEBUG( 2, ( "Rebind failed: %s\n", ldap_err2string( rc
) ) );
258 #else /* other Vendor or LDAP_API_VERSION */
259 # if LDAP_SET_REBIND_PROC_ARGS ==3
260 static int rebindproc_with_state (LDAP
* ld
, char **whop
, char **credp
,
261 int *methodp
, int freeit
, void *arg
)
263 # else /* LDAP_SET_REBIND_PROC_ARGS == 2 */
264 static int rebindproc (LDAP
*ldap_struct
, char **whop
, char **credp
,
265 int *method
, int freeit
)
268 register char *to_clear
= *credp
;
273 memset(*credp
, '\0', strlen(*credp
));
276 *whop
= strdup(ldap_state
->bind_dn
);
278 return LDAP_NO_MEMORY
;
280 DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n",
283 *credp
= strdup(ldap_secret
);
286 return LDAP_NO_MEMORY
;
288 *methodp
= LDAP_AUTH_SIMPLE
;
296 /*******************************************************************
297 connect to the ldap server under system privilege.
298 ******************************************************************/
299 static BOOL
ldap_connect_system(LDAP
* ldap_struct
)
302 static BOOL got_pw
= False
;
304 /* get the password if we don't have it already */
305 if (!got_pw
&& !(got_pw
=fetch_ldap_pw(lp_ldap_admin_dn(), ldap_secret
, sizeof(pstring
))))
307 DEBUG(0, ("ldap_connect_system: Failed to retrieve password for %s from secrets.tdb\n",
308 lp_ldap_admin_dn()));
312 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
313 (OpenLDAP) doesnt' seem to support it */
315 DEBUG(0,("ldap_connect_system: Binding to ldap server as \"%s\"\n",
316 lp_ldap_admin_dn()));
318 #if LDAP_SET_REBIND_PROC_ARGS == 2
319 ldap_set_rebind_proc(ldap_struct
, rebindproc
);
320 #else /* LDAP_SET_REBIND_PROC_ARGS == 3 */
321 ldap_set_rebind_proc(ldap_struct
, rebindproc_with_state
, NULL
);
324 if ((rc
= ldap_simple_bind_s(ldap_struct
, lp_ldap_admin_dn(),
325 ldap_secret
)) != LDAP_SUCCESS
)
327 DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc
)));
331 DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
335 /*******************************************************************
336 run the search by name.
337 ******************************************************************/
338 static int ldap_search_one_user (LDAP
* ldap_struct
, const char *filter
, LDAPMessage
** result
)
340 int scope
= LDAP_SCOPE_SUBTREE
;
343 DEBUG(2, ("ldap_search_one_user: searching for:[%s]\n", filter
));
345 rc
= ldap_search_s(ldap_struct
, lp_ldap_suffix (), scope
, (char*)filter
, attribs
, 0, result
);
347 if (rc
!= LDAP_SUCCESS
) {
348 DEBUG(0,("ldap_search_one_user: Problem during the LDAP search: %s\n",
349 ldap_err2string (rc
)));
350 DEBUG(3,("ldap_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
357 /*******************************************************************
358 run the search by name.
359 ******************************************************************/
360 static int ldap_search_one_user_by_name (LDAP
* ldap_struct
, const char *user
,
361 LDAPMessage
** result
)
366 * in the filter expression, replace %u with the real name
367 * so in ldap filter, %u MUST exist :-)
369 pstrcpy(filter
, lp_ldap_filter());
372 * have to use this here because $ is filtered out
375 all_string_sub(filter
, "%u", user
, sizeof(pstring
));
377 return ldap_search_one_user(ldap_struct
, filter
, result
);
380 /*******************************************************************
381 run the search by uid.
382 ******************************************************************/
383 static int ldap_search_one_user_by_uid(LDAP
* ldap_struct
, int uid
,
384 LDAPMessage
** result
)
389 /* Get the username from the system and look that up in the LDAP */
391 if ((user
= sys_getpwuid(uid
)) == NULL
) {
392 DEBUG(3,("ldap_search_one_user_by_uid: Failed to locate uid [%d]\n", uid
));
393 return LDAP_NO_SUCH_OBJECT
;
396 pstrcpy(filter
, lp_ldap_filter());
398 all_string_sub(filter
, "%u", user
->pw_name
, sizeof(pstring
));
400 return ldap_search_one_user(ldap_struct
, filter
, result
);
403 /*******************************************************************
404 run the search by rid.
405 ******************************************************************/
406 static int ldap_search_one_user_by_rid (LDAP
* ldap_struct
, uint32 rid
,
407 LDAPMessage
** result
)
412 /* check if the user rid exsists, if not, try searching on the uid */
414 snprintf(filter
, sizeof(filter
) - 1, "rid=%i", rid
);
415 rc
= ldap_search_one_user(ldap_struct
, filter
, result
);
417 if (rc
!= LDAP_SUCCESS
)
418 rc
= ldap_search_one_user_by_uid(ldap_struct
,
419 pdb_user_rid_to_uid(rid
), result
);
424 /*******************************************************************
425 search an attribute and return the first value found.
426 the string in 'value' is unchanged if the attribute does not exist
427 ******************************************************************/
429 static BOOL
get_single_attribute (LDAP
* ldap_struct
, LDAPMessage
* entry
,
430 char *attribute
, char *value
)
434 if ((values
= ldap_get_values (ldap_struct
, entry
, attribute
)) == NULL
) {
435 DEBUG (2, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute
));
439 pstrcpy(value
, values
[0]);
440 ldap_value_free(values
);
441 DEBUG (2, ("get_single_attribute: [%s] = [%s]\n", attribute
, value
));
446 /************************************************************************
447 Routine to manage the LDAPMod structure array
448 manage memory used by the array, by each struct, and values
449 ************************************************************************/
451 static void make_a_mod (LDAPMod
*** modlist
, int modop
, char *attribute
, char *value
)
459 if (attribute
== NULL
|| *attribute
== '\0')
462 if (value
== NULL
|| *value
== '\0')
467 mods
= (LDAPMod
**) malloc(sizeof(LDAPMod
*));
470 DEBUG(0, ("make_a_mod: out of memory!\n"));
476 for (i
= 0; mods
[i
] != NULL
; ++i
) {
477 if (mods
[i
]->mod_op
== modop
&& !strcasecmp(mods
[i
]->mod_type
, attribute
))
483 mods
= (LDAPMod
**) Realloc (mods
, (i
+ 2) * sizeof (LDAPMod
*));
486 DEBUG(0, ("make_a_mod: out of memory!\n"));
489 mods
[i
] = (LDAPMod
*) malloc(sizeof(LDAPMod
));
492 DEBUG(0, ("make_a_mod: out of memory!\n"));
495 mods
[i
]->mod_op
= modop
;
496 mods
[i
]->mod_values
= NULL
;
497 mods
[i
]->mod_type
= strdup(attribute
);
504 if (mods
[i
]->mod_values
!= NULL
) {
505 for (; mods
[i
]->mod_values
[j
] != NULL
; j
++);
507 mods
[i
]->mod_values
= (char **)Realloc(mods
[i
]->mod_values
,
508 (j
+ 2) * sizeof (char *));
510 if (mods
[i
]->mod_values
== NULL
) {
511 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
514 mods
[i
]->mod_values
[j
] = strdup(value
);
515 mods
[i
]->mod_values
[j
+ 1] = NULL
;
520 /* New Interface is being implemented here */
522 /**********************************************************************
523 Initialize SAM_ACCOUNT from an LDAP query
524 (Based on init_sam_from_buffer in pdb_tdb.c)
525 *********************************************************************/
526 static BOOL
init_sam_from_ldap (SAM_ACCOUNT
* sampass
,
527 LDAP
* ldap_struct
, LDAPMessage
* entry
)
533 pass_can_change_time
,
534 pass_must_change_time
;
546 struct passwd
*sys_user
;
554 uint8 hours
[MAX_HOURS_LEN
];
556 gid_t gid
= getegid();
560 * do a little initialization
564 nt_username
[0] = '\0';
568 logon_script
[0] = '\0';
569 profile_path
[0] = '\0';
571 munged_dial
[0] = '\0';
572 workstations
[0] = '\0';
575 get_single_attribute(ldap_struct
, entry
, "uid", username
);
576 DEBUG(2, ("Entry found for user: %s\n", username
));
578 pstrcpy(samlogon_user
, username
);
580 pstrcpy(nt_username
, username
);
582 pstrcpy(domain
, lp_workgroup());
584 pass_last_set_time
= TIME_T_MAX
;
585 logon_time
= TIME_T_MAX
;
586 logoff_time
= TIME_T_MAX
;
587 kickoff_time
= TIME_T_MAX
;
588 pass_can_change_time
= TIME_T_MAX
;
589 pass_must_change_time
= TIME_T_MAX
;
592 if (get_single_attribute(ldap_struct
, entry
, "pwdLastSet", temp
))
593 pass_last_set_time
= (time_t) atol(temp
);
595 if (get_single_attribute(ldap_struct
, entry
, "logonTime", temp
))
596 logon_time
= (time_t) atol(temp
);
598 if (get_single_attribute(ldap_struct
, entry
, "logoffTime", temp
))
599 logoff_time
= (time_t) atol(temp
);
601 if (get_single_attribute(ldap_struct
, entry
, "kickoffTime", temp
))
602 kickoff_time
= (time_t) atol(temp
);
604 if (get_single_attribute(ldap_struct
, entry
, "pwdCanChange", temp
))
605 pass_can_change_time
= (time_t) atol(temp
);
607 if (get_single_attribute(ldap_struct
, entry
, "pwdMustChange", temp
))
608 pass_must_change_time
= (time_t) atol(temp
);
610 /* recommend that 'gecos' and 'displayName' should refer to the same
611 * attribute OID. userFullName depreciated, only used by Samba
612 * primary rules of LDAP: don't make a new attribute when one is already defined
613 * that fits your needs; using cn then displayName rather than 'userFullName'
616 sam_logon_in_ssb
= True
;
618 if (!get_single_attribute(ldap_struct
, entry
, "cn", fullname
)) {
619 get_single_attribute(ldap_struct
, entry
, "displayName", fullname
);
623 if (!get_single_attribute(ldap_struct
, entry
, "homeDrive", dir_drive
)) {
624 pstrcpy(dir_drive
, lp_logon_drive());
625 standard_sub_advanced(-1, username
, "", gid
, dir_drive
, sizeof(dir_drive
));
626 DEBUG(5,("homeDrive fell back to %s\n",dir_drive
));
627 pdb_set_dir_drive(sampass
, dir_drive
, False
);
630 pdb_set_dir_drive(sampass
, dir_drive
, True
);
632 if (!get_single_attribute(ldap_struct
, entry
, "smbHome", homedir
)) {
633 pstrcpy(homedir
, lp_logon_home());
634 standard_sub_advanced(-1, username
, "", gid
, homedir
, sizeof(homedir
));
635 DEBUG(5,("smbHome fell back to %s\n",homedir
));
636 pdb_set_homedir(sampass
, homedir
, False
);
639 pdb_set_homedir(sampass
, homedir
, True
);
641 if (!get_single_attribute(ldap_struct
, entry
, "scriptPath", logon_script
)) {
642 pstrcpy(logon_script
, lp_logon_script());
643 standard_sub_advanced(-1, username
, "", gid
, logon_script
, sizeof(logon_script
));
644 DEBUG(5,("scriptPath fell back to %s\n",logon_script
));
645 pdb_set_logon_script(sampass
, logon_script
, False
);
648 pdb_set_logon_script(sampass
, logon_script
, True
);
650 if (!get_single_attribute(ldap_struct
, entry
, "profilePath", profile_path
)) {
651 pstrcpy(profile_path
, lp_logon_path());
652 standard_sub_advanced(-1, username
, "", gid
, profile_path
, sizeof(profile_path
));
653 DEBUG(5,("profilePath fell back to %s\n",profile_path
));
654 pdb_set_profile_path(sampass
, profile_path
, False
);
657 pdb_set_profile_path(sampass
, profile_path
, True
);
659 sam_logon_in_ssb
= False
;
661 get_single_attribute(ldap_struct
, entry
, "description", acct_desc
);
662 get_single_attribute(ldap_struct
, entry
, "userWorkstations", workstations
);
663 get_single_attribute(ldap_struct
, entry
, "rid", temp
);
664 user_rid
= (uint32
)atol(temp
);
665 get_single_attribute(ldap_struct
, entry
, "primaryGroupID", temp
);
666 group_rid
= (uint32
)atol(temp
);
669 /* These values MAY be in LDAP, but they can also be retrieved through
670 * sys_getpw*() which is how we're doing it
672 sys_user
= sys_getpwnam(username
);
673 if (sys_user
== NULL
) {
674 DEBUG (2,("init_sam_from_ldap: User [%s] does not ave a uid!\n", username
));
679 /* FIXME: hours stuff should be cleaner */
683 memset(hours
, 0xff, hours_len
);
685 get_single_attribute (ldap_struct
, entry
, "lmPassword", temp
);
686 pdb_gethexpwd(temp
, smblmpwd
);
687 memset((char *)temp
, '\0', sizeof(temp
));
688 get_single_attribute (ldap_struct
, entry
, "ntPassword", temp
);
689 pdb_gethexpwd(temp
, smbntpwd
);
690 memset((char *)temp
, '\0', sizeof(temp
));
691 get_single_attribute (ldap_struct
, entry
, "acctFlags", temp
);
692 acct_ctrl
= pdb_decode_acct_ctrl(temp
);
695 acct_ctrl
|= ACB_NORMAL
;
698 pdb_set_acct_ctrl(sampass
, acct_ctrl
);
699 pdb_set_logon_time(sampass
, logon_time
);
700 pdb_set_logoff_time(sampass
, logoff_time
);
701 pdb_set_kickoff_time(sampass
, kickoff_time
);
702 pdb_set_pass_can_change_time(sampass
, pass_can_change_time
);
703 pdb_set_pass_must_change_time(sampass
, pass_must_change_time
);
704 pdb_set_pass_last_set_time(sampass
, pass_last_set_time
);
706 pdb_set_hours_len(sampass
, hours_len
);
707 pdb_set_logon_divs(sampass
, logon_divs
);
709 pdb_set_uid(sampass
, sys_user
->pw_uid
);
710 pdb_set_gid(sampass
, sys_user
->pw_gid
);
711 pdb_set_user_rid(sampass
, user_rid
);
712 pdb_set_group_rid(sampass
, group_rid
);
714 pdb_set_username(sampass
, username
);
716 pdb_set_domain(sampass
, domain
);
717 pdb_set_nt_username(sampass
, nt_username
);
719 pdb_set_fullname(sampass
, fullname
);
721 pdb_set_acct_desc(sampass
, acct_desc
);
722 pdb_set_workstations(sampass
, workstations
);
723 pdb_set_munged_dial(sampass
, munged_dial
);
725 if (!pdb_set_nt_passwd(sampass
, smbntpwd
))
727 if (!pdb_set_lanman_passwd(sampass
, smblmpwd
))
730 /* pdb_set_unknown_3(sampass, unknown3); */
731 /* pdb_set_unknown_5(sampass, unknown5); */
732 /* pdb_set_unknown_6(sampass, unknown6); */
734 pdb_set_hours(sampass
, hours
);
739 /**********************************************************************
740 Initialize SAM_ACCOUNT from an LDAP query
741 (Based on init_buffer_from_sam in pdb_tdb.c)
742 *********************************************************************/
743 static BOOL
init_ldap_from_sam (LDAPMod
*** mods
, int ldap_state
, SAM_ACCOUNT
* sampass
)
750 * took out adding "objectclass: sambaAccount"
751 * do this on a per-mod basis
755 make_a_mod(mods
, ldap_state
, "uid", pdb_get_username(sampass
));
756 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass
)));
758 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_last_set_time(sampass
));
759 make_a_mod(mods
, ldap_state
, "pwdLastSet", temp
);
761 slprintf(temp
, sizeof(temp
) - 1, "%li", pdb_get_logon_time(sampass
));
762 make_a_mod(mods
, ldap_state
, "logonTime", temp
);
764 slprintf(temp
, sizeof(temp
) - 1, "%li", pdb_get_logoff_time(sampass
));
765 make_a_mod(mods
, ldap_state
, "logoffTime", temp
);
767 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_kickoff_time(sampass
));
768 make_a_mod(mods
, ldap_state
, "kickoffTime", temp
);
770 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_can_change_time(sampass
));
771 make_a_mod(mods
, ldap_state
, "pwdCanChange", temp
);
773 slprintf (temp
, sizeof (temp
) - 1, "%li", pdb_get_pass_must_change_time(sampass
));
774 make_a_mod(mods
, ldap_state
, "pwdMustChange", temp
);
776 /* displayName, cn, and gecos should all be the same
777 * most easily accomplished by giving them the same OID
778 * gecos isn't set here b/c it should be handled by the
782 make_a_mod(mods
, ldap_state
, "displayName", pdb_get_fullname(sampass
));
783 make_a_mod(mods
, ldap_state
, "cn", pdb_get_fullname(sampass
));
784 make_a_mod(mods
, ldap_state
, "description", pdb_get_acct_desc(sampass
));
785 make_a_mod(mods
, ldap_state
, "userWorkstations", pdb_get_workstations(sampass
));
788 * Only updates fields which have been set (not defaults from smb.conf)
791 if (IS_SAM_SET(sampass
, FLAG_SAM_SMBHOME
))
792 make_a_mod(mods
, ldap_state
, "smbHome", pdb_get_homedir(sampass
));
794 if (IS_SAM_SET(sampass
, FLAG_SAM_DRIVE
))
795 make_a_mod(mods
, ldap_state
, "homeDrive", pdb_get_dirdrive(sampass
));
797 if (IS_SAM_SET(sampass
, FLAG_SAM_LOGONSCRIPT
))
798 make_a_mod(mods
, ldap_state
, "scriptPath", pdb_get_logon_script(sampass
));
800 if (IS_SAM_SET(sampass
, FLAG_SAM_PROFILE
))
801 make_a_mod(mods
, ldap_state
, "profilePath", pdb_get_profile_path(sampass
));
804 if ( !pdb_get_user_rid(sampass
))
805 slprintf(temp
, sizeof(temp
) - 1, "%i", pdb_uid_to_user_rid(pdb_get_uid(sampass
)));
807 slprintf(temp
, sizeof(temp
) - 1, "%i", pdb_get_user_rid(sampass
));
808 make_a_mod(mods
, ldap_state
, "rid", temp
);
810 if ( !pdb_get_group_rid(sampass
))
811 slprintf(temp
, sizeof(temp
) - 1, "%i", pdb_gid_to_group_rid(pdb_get_gid(sampass
)));
813 slprintf(temp
, sizeof(temp
) - 1, "%i", pdb_get_group_rid(sampass
));
814 make_a_mod(mods
, ldap_state
, "primaryGroupID", temp
);
816 /* FIXME: Hours stuff goes in LDAP */
817 pdb_sethexpwd (temp
, pdb_get_lanman_passwd(sampass
), pdb_get_acct_ctrl(sampass
));
818 make_a_mod (mods
, ldap_state
, "lmPassword", temp
);
820 pdb_sethexpwd (temp
, pdb_get_nt_passwd(sampass
), pdb_get_acct_ctrl(sampass
));
821 make_a_mod (mods
, ldap_state
, "ntPassword", temp
);
823 make_a_mod (mods
, ldap_state
, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass
),
824 NEW_PW_FORMAT_SPACE_PADDED_LEN
));
829 /**********************************************************************
830 Connect to LDAP server for password enumeration
831 *********************************************************************/
832 BOOL
pdb_setsampwent(BOOL update
)
837 if (!ldap_open_connection(&global_ldap_ent
.ldap_struct
))
841 if (!ldap_connect_system(global_ldap_ent
.ldap_struct
))
843 ldap_unbind(global_ldap_ent
.ldap_struct
);
847 pstrcpy(filter
, lp_ldap_filter());
848 all_string_sub(filter
, "%u", "*", sizeof(pstring
));
850 rc
= ldap_search_s(global_ldap_ent
.ldap_struct
, lp_ldap_suffix(),
851 LDAP_SCOPE_SUBTREE
, filter
, attribs
, 0,
852 &global_ldap_ent
.result
);
854 if (rc
!= LDAP_SUCCESS
)
856 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc
)));
857 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
858 ldap_msgfree(global_ldap_ent
.result
);
859 ldap_unbind(global_ldap_ent
.ldap_struct
);
860 global_ldap_ent
.ldap_struct
= NULL
;
861 global_ldap_ent
.result
= NULL
;
865 DEBUG(2, ("pdb_setsampwent: %d entries in the base!\n",
866 ldap_count_entries(global_ldap_ent
.ldap_struct
,
867 global_ldap_ent
.result
)));
869 global_ldap_ent
.entry
= ldap_first_entry(global_ldap_ent
.ldap_struct
,
870 global_ldap_ent
.result
);
871 global_ldap_ent
.index
= -1;
876 /**********************************************************************
877 End enumeration of the LDAP password list
878 *********************************************************************/
879 void pdb_endsampwent(void)
881 if (global_ldap_ent
.ldap_struct
&& global_ldap_ent
.result
)
883 ldap_msgfree(global_ldap_ent
.result
);
884 ldap_unbind(global_ldap_ent
.ldap_struct
);
885 global_ldap_ent
.ldap_struct
= NULL
;
886 global_ldap_ent
.result
= NULL
;
890 /**********************************************************************
891 Get the next entry in the LDAP password database
892 *********************************************************************/
893 BOOL
pdb_getsampwent(SAM_ACCOUNT
* user
)
895 if (!global_ldap_ent
.entry
)
898 global_ldap_ent
.index
++;
899 if (global_ldap_ent
.index
> 0)
901 global_ldap_ent
.entry
= ldap_next_entry(global_ldap_ent
.ldap_struct
, global_ldap_ent
.entry
);
904 if (global_ldap_ent
.entry
!= NULL
)
906 return init_sam_from_ldap(user
, global_ldap_ent
.ldap_struct
,
907 global_ldap_ent
.entry
);
912 /**********************************************************************
913 Get SAM_ACCOUNT entry from LDAP by username
914 *********************************************************************/
915 BOOL
pdb_getsampwnam(SAM_ACCOUNT
* user
, char *sname
)
921 if (!ldap_open_connection(&ldap_struct
))
923 if (!ldap_connect_system(ldap_struct
))
925 ldap_unbind(ldap_struct
);
928 if (ldap_search_one_user_by_name(ldap_struct
, sname
, &result
) != LDAP_SUCCESS
)
930 ldap_unbind(ldap_struct
);
933 if (ldap_count_entries(ldap_struct
, result
) < 1)
937 pstrcpy(filter
, lp_ldap_filter());
938 standard_sub_advanced(-1, sname
, "", -1, filter
, sizeof(filter
));
939 DEBUG(0,("LDAP search \"%s\" returned %d entries.\n", filter
,
940 ldap_count_entries(ldap_struct
, result
)));
941 ldap_unbind(ldap_struct
);
944 entry
= ldap_first_entry(ldap_struct
, result
);
947 init_sam_from_ldap(user
, ldap_struct
, entry
);
948 ldap_msgfree(result
);
949 ldap_unbind(ldap_struct
);
954 ldap_msgfree(result
);
955 ldap_unbind(ldap_struct
);
960 /**********************************************************************
961 Get SAM_ACCOUNT entry from LDAP by rid
962 *********************************************************************/
963 BOOL
pdb_getsampwrid(SAM_ACCOUNT
* user
, uint32 rid
)
969 if (!ldap_open_connection(&ldap_struct
))
972 if (!ldap_connect_system(ldap_struct
))
974 ldap_unbind(ldap_struct
);
977 if (ldap_search_one_user_by_rid(ldap_struct
, rid
, &result
) !=
980 ldap_unbind(ldap_struct
);
984 if (ldap_count_entries(ldap_struct
, result
) < 1)
987 ("We don't find this rid [%i] count=%d\n", rid
,
988 ldap_count_entries(ldap_struct
, result
)));
989 ldap_unbind(ldap_struct
);
993 entry
= ldap_first_entry(ldap_struct
, result
);
996 init_sam_from_ldap(user
, ldap_struct
, entry
);
997 ldap_msgfree(result
);
998 ldap_unbind(ldap_struct
);
1003 ldap_msgfree(result
);
1004 ldap_unbind(ldap_struct
);
1009 /**********************************************************************
1010 Delete entry from LDAP for username
1011 *********************************************************************/
1013 BOOL
pdb_delete_sam_account(char *sname
)
1019 LDAPMessage
*result
;
1021 /* Ensure we have euid as root - else deny this. */
1022 if (!ldap_open_connection (&ldap_struct
))
1025 DEBUG (3, ("Deleting user %s from LDAP.\n", sname
));
1027 if (!ldap_connect_system (ldap_struct
)) {
1028 ldap_unbind (ldap_struct
);
1029 DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname
));
1033 rc
= ldap_search_one_user_by_name (ldap_struct
, sname
, &result
);
1034 if (ldap_count_entries (ldap_struct
, result
) == 0) {
1035 DEBUG (0, ("User doesn't exit!\n"));
1036 ldap_msgfree (result
);
1037 ldap_unbind (ldap_struct
);
1041 entry
= ldap_first_entry (ldap_struct
, result
);
1042 dn
= ldap_get_dn (ldap_struct
, entry
);
1044 rc
= ldap_delete_s (ldap_struct
, dn
);
1047 if (rc
!= LDAP_SUCCESS
) {
1049 ldap_get_option (ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
1050 DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n",
1051 sname
, ldap_err2string (rc
), ld_error
));
1053 ldap_unbind (ldap_struct
);
1057 DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname
));
1058 ldap_unbind (ldap_struct
);
1062 /**********************************************************************
1064 *********************************************************************/
1066 BOOL
pdb_update_sam_account(SAM_ACCOUNT
* newpwd
, BOOL override
)
1071 LDAPMessage
*result
;
1075 if (!ldap_open_connection(&ldap_struct
)) /* open a connection to the server */
1078 if (!ldap_connect_system(ldap_struct
)) /* connect as system account */ {
1079 ldap_unbind(ldap_struct
);
1083 rc
= ldap_search_one_user_by_name(ldap_struct
,
1084 pdb_get_username(newpwd
), &result
);
1086 if (ldap_count_entries(ldap_struct
, result
) == 0) {
1087 DEBUG(0, ("No user to modify!\n"));
1088 ldap_msgfree(result
);
1089 ldap_unbind(ldap_struct
);
1093 init_ldap_from_sam(&mods
, LDAP_MOD_REPLACE
, newpwd
);
1095 entry
= ldap_first_entry(ldap_struct
, result
);
1096 dn
= ldap_get_dn(ldap_struct
, entry
);
1098 rc
= ldap_modify_s(ldap_struct
, dn
, mods
);
1100 if (rc
!= LDAP_SUCCESS
) {
1102 ldap_get_option(ldap_struct
, LDAP_OPT_ERROR_STRING
,
1105 ("failed to modify user with uid = %s with: %s\n\t%s\n",
1106 pdb_get_username(newpwd
), ldap_err2string(rc
),
1109 ldap_unbind(ldap_struct
);
1113 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
1114 pdb_get_username(newpwd
)));
1115 ldap_mods_free(mods
, 1);
1116 ldap_unbind(ldap_struct
);
1120 /**********************************************************************
1121 Add SAM_ACCOUNT to LDAP
1122 *********************************************************************/
1124 BOOL
pdb_add_sam_account(SAM_ACCOUNT
* newpwd
)
1129 LDAPMessage
*result
;
1135 if (!ldap_open_connection(&ldap_struct
)) /* open a connection to the server */
1138 if (!ldap_connect_system(ldap_struct
)) /* connect as system account */ {
1139 ldap_unbind(ldap_struct
);
1143 rc
= ldap_search_one_user_by_name (ldap_struct
, pdb_get_username(newpwd
), &result
);
1145 if (ldap_count_entries(ldap_struct
, result
) != 0) {
1146 DEBUG(0,("User already in the base, with samba properties\n"));
1147 ldap_msgfree(result
);
1148 ldap_unbind(ldap_struct
);
1151 ldap_msgfree(result
);
1153 slprintf (filter
, sizeof (filter
) - 1, "uid=%s", pdb_get_username(newpwd
));
1154 rc
= ldap_search_one_user(ldap_struct
, filter
, &result
);
1155 num_result
= ldap_count_entries(ldap_struct
, result
);
1157 if (num_result
> 1) {
1158 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1162 /* Check if we need to update an existing entry */
1163 if (num_result
== 1) {
1167 DEBUG(3,("User exists without samba properties: adding them\n"));
1168 ldap_op
= LDAP_MOD_REPLACE
;
1169 entry
= ldap_first_entry (ldap_struct
, result
);
1170 tmp
= ldap_get_dn (ldap_struct
, entry
);
1171 slprintf (dn
, sizeof (dn
) - 1, "%s", tmp
);
1174 /* Check if we need to add an entry */
1175 DEBUG(3,("Adding new user\n"));
1176 ldap_op
= LDAP_MOD_ADD
;
1177 slprintf (dn
, sizeof (dn
) - 1, "uid=%s,%s", pdb_get_username(newpwd
), lp_ldap_suffix ());
1180 ldap_msgfree(result
);
1182 init_ldap_from_sam(&mods
, ldap_op
, newpwd
);
1183 make_a_mod(&mods
, LDAP_MOD_ADD
, "objectclass", "sambaAccount");
1185 if (ldap_op
== LDAP_MOD_REPLACE
) {
1186 rc
= ldap_modify_s(ldap_struct
, dn
, mods
);
1188 make_a_mod(&mods
, LDAP_MOD_ADD
, "objectclass", "account");
1189 rc
= ldap_add_s(ldap_struct
, dn
, mods
);
1192 if (rc
!= LDAP_SUCCESS
) {
1195 ldap_get_option (ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
1196 DEBUG(0,("failed to modify user with uid = %s with: %s\n\t%s\n",
1197 pdb_get_username(newpwd
), ldap_err2string (rc
), ld_error
));
1199 ldap_mods_free(mods
, 1);
1200 ldap_unbind(ldap_struct
);
1204 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd
)));
1205 ldap_mods_free(mods
, 1);
1206 ldap_unbind(ldap_struct
);
1211 void dummy_function(void);
1213 dummy_function (void)
1215 } /* stop some compilers complaining */