clean up if {} statement to keep in sync with HEAD
[Samba.git] / source / passdb / pdb_ldap.c
blob9d416f7c8bdfe6bd82550c148fbbe5b3b98a80c8
1 /*
2 Unix SMB/Netbios implementation.
3 Version 2.9.
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.
25 #include "includes.h"
27 #ifdef WITH_LDAP_SAM
28 /* TODO:
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
45 * and/or winbind
48 #include <lber.h>
49 #include <ldap.h>
51 #ifndef LDAP_OPT_SUCCESS
52 #define LDAP_OPT_SUCCESS LDAP_SUCCESS
53 #endif
55 #ifndef SAM_ACCOUNT
56 #define SAM_ACCOUNT struct sam_passwd
57 #endif
59 struct ldap_enum_info {
60 LDAP *ldap_struct;
61 LDAPMessage *result;
62 LDAPMessage *entry;
63 int index;
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;
73 /*
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'
78 * MUST ( uid $ rid )
79 * MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $
80 * logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $
81 * displayName $ smbHome $ homeDrive $ scriptPath $ profilePath $
82 * description $ userWorkstations $ primaryGroupID $ domain ))
85 char* attribs[] = {
86 "uid",
87 "rid",
88 "cn",
89 "lmPassword",
90 "ntPassword",
91 "pwdLastSet",
92 "logonTime",
93 "logoffTime",
94 "kickoffTime",
95 "pwdCanChange",
96 "pwdMustChange",
97 "acctFlags",
98 "displayName",
99 "smbHome",
100 "homeDrive",
101 "scriptPath",
102 "profilePath",
103 "description",
104 "userWorkstations",
105 "primaryGroupID",
106 "domain",
107 NULL
111 /*******************************************************************
112 open a connection to the ldap server.
113 ******************************************************************/
114 static BOOL ldap_open_connection (LDAP ** ldap_struct)
116 int port;
117 int version;
118 int tls, rc;
119 uid_t uid = geteuid();
120 struct passwd* pass;
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"));
131 return False;
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"));
138 return False;
141 port = lp_ldap_port();
143 /* remap default port is no SSL */
144 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (lp_ldap_port() == 636) ) {
145 port = 389;
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"));
153 return False;
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,
177 &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)));
184 return False;
186 DEBUG (2, ("StartTLS issued: using a TLS connection\n"));
187 #else
188 DEBUG(0,("ldap_open_connection: StartTLS not supported by LDAP client libraries!\n"));
189 return False;
190 #endif
191 break;
193 case LDAP_SSL_ON:
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"));
202 #else
203 DEBUG(0,("ldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
204 return False;
205 #endif
206 break;
208 case LDAP_SSL_OFF:
209 default:
211 * No special needs to setup options prior to the LDAP
212 * bind (which should be called next via ldap_connect_system()
214 break;
217 DEBUG(2, ("ldap_open_connection: connection opened\n"));
218 return True;
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,
230 ber_tag_t request,
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,
235 ber_tag_t request,
236 ber_int_t msgid)
237 # endif /* LDAP_SET_REBIND_PROC_ARGS */
240 int rc = 0;
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" ) );
253 else {
254 DEBUG( 2, ( "Rebind failed: %s\n", ldap_err2string( rc ) ) );
256 return 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 )
266 # endif
268 register char *to_clear = *credp;
271 if (freeit) {
272 SAFE_FREE(*whop);
273 memset(*credp, '\0', strlen(*credp));
274 SAFE_FREE(*credp);
275 } else {
276 *whop = strdup(ldap_state->bind_dn);
277 if (!*whop) {
278 return LDAP_NO_MEMORY;
280 DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n",
281 whop));
283 *credp = strdup(ldap_secret);
284 if (!*credp) {
285 SAFE_FREE(*whop);
286 return LDAP_NO_MEMORY;
288 *methodp = LDAP_AUTH_SIMPLE;
290 return LDAP_SUCCESS;
292 #endif
296 /*******************************************************************
297 connect to the ldap server under system privilege.
298 ******************************************************************/
299 static BOOL ldap_connect_system(LDAP * ldap_struct)
301 int rc;
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()));
309 return False;
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);
322 #endif
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)));
328 return False;
331 DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
332 return True;
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;
341 int rc;
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(),
351 filter));
354 return rc;
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)
363 pstring filter;
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
373 * in pstring_sub
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)
386 struct passwd *user;
387 pstring filter;
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)
409 pstring filter;
410 int rc;
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);
421 return rc;
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)
432 char **values;
434 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
435 DEBUG (2, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
436 return False;
439 pstrcpy(value, values[0]);
440 ldap_value_free(values);
441 DEBUG (2, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
443 return True;
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)
453 LDAPMod **mods;
454 int i;
455 int j;
457 mods = *modlist;
459 if (attribute == NULL || *attribute == '\0')
460 return;
462 if (value == NULL || *value == '\0')
463 return;
465 if (mods == NULL)
467 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
468 if (mods == NULL)
470 DEBUG(0, ("make_a_mod: out of memory!\n"));
471 return;
473 mods[0] = NULL;
476 for (i = 0; mods[i] != NULL; ++i) {
477 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
478 break;
481 if (mods[i] == NULL)
483 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
484 if (mods == NULL)
486 DEBUG(0, ("make_a_mod: out of memory!\n"));
487 return;
489 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
490 if (mods[i] == NULL)
492 DEBUG(0, ("make_a_mod: out of memory!\n"));
493 return;
495 mods[i]->mod_op = modop;
496 mods[i]->mod_values = NULL;
497 mods[i]->mod_type = strdup(attribute);
498 mods[i + 1] = NULL;
501 if (value != NULL)
503 j = 0;
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"));
512 return;
514 mods[i]->mod_values[j] = strdup(value);
515 mods[i]->mod_values[j + 1] = NULL;
517 *modlist = mods;
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)
529 time_t logon_time,
530 logoff_time,
531 kickoff_time,
532 pass_last_set_time,
533 pass_can_change_time,
534 pass_must_change_time;
535 pstring username,
536 domain,
537 nt_username,
538 fullname,
539 homedir,
540 dir_drive,
541 logon_script,
542 profile_path,
543 acct_desc,
544 munged_dial,
545 workstations;
546 struct passwd *sys_user;
547 uint32 user_rid,
548 group_rid;
549 uint8 smblmpwd[16],
550 smbntpwd[16];
551 uint16 acct_ctrl,
552 logon_divs;
553 uint32 hours_len;
554 uint8 hours[MAX_HOURS_LEN];
555 pstring temp;
556 gid_t gid = getegid();
560 * do a little initialization
562 username[0] = '\0';
563 domain[0] = '\0';
564 nt_username[0] = '\0';
565 fullname[0] = '\0';
566 homedir[0] = '\0';
567 dir_drive[0] = '\0';
568 logon_script[0] = '\0';
569 profile_path[0] = '\0';
570 acct_desc[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);
629 else
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);
638 else
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);
647 else
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);
656 else
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));
675 return False;
679 /* FIXME: hours stuff should be cleaner */
681 logon_divs = 168;
682 hours_len = 21;
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);
694 if (acct_ctrl == 0)
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))
726 return False;
727 if (!pdb_set_lanman_passwd(sampass, smblmpwd))
728 return False;
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);
736 return True;
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)
745 pstring temp;
747 *mods = NULL;
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
779 * add-user script
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)));
806 else
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)));
812 else
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));
826 return True;
829 /**********************************************************************
830 Connect to LDAP server for password enumeration
831 *********************************************************************/
832 BOOL pdb_setsampwent(BOOL update)
834 int rc;
835 pstring filter;
837 if (!ldap_open_connection(&global_ldap_ent.ldap_struct))
839 return False;
841 if (!ldap_connect_system(global_ldap_ent.ldap_struct))
843 ldap_unbind(global_ldap_ent.ldap_struct);
844 return False;
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;
862 return False;
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;
873 return True;
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)
896 return False;
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);
909 return False;
912 /**********************************************************************
913 Get SAM_ACCOUNT entry from LDAP by username
914 *********************************************************************/
915 BOOL pdb_getsampwnam(SAM_ACCOUNT * user, char *sname)
917 LDAP *ldap_struct;
918 LDAPMessage *result;
919 LDAPMessage *entry;
921 if (!ldap_open_connection(&ldap_struct))
922 return False;
923 if (!ldap_connect_system(ldap_struct))
925 ldap_unbind(ldap_struct);
926 return False;
928 if (ldap_search_one_user_by_name(ldap_struct, sname, &result) != LDAP_SUCCESS)
930 ldap_unbind(ldap_struct);
931 return False;
933 if (ldap_count_entries(ldap_struct, result) < 1)
935 pstring filter;
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);
942 return False;
944 entry = ldap_first_entry(ldap_struct, result);
945 if (entry)
947 init_sam_from_ldap(user, ldap_struct, entry);
948 ldap_msgfree(result);
949 ldap_unbind(ldap_struct);
950 return True;
952 else
954 ldap_msgfree(result);
955 ldap_unbind(ldap_struct);
956 return False;
960 /**********************************************************************
961 Get SAM_ACCOUNT entry from LDAP by rid
962 *********************************************************************/
963 BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid)
965 LDAP *ldap_struct;
966 LDAPMessage *result;
967 LDAPMessage *entry;
969 if (!ldap_open_connection(&ldap_struct))
970 return False;
972 if (!ldap_connect_system(ldap_struct))
974 ldap_unbind(ldap_struct);
975 return False;
977 if (ldap_search_one_user_by_rid(ldap_struct, rid, &result) !=
978 LDAP_SUCCESS)
980 ldap_unbind(ldap_struct);
981 return False;
984 if (ldap_count_entries(ldap_struct, result) < 1)
986 DEBUG(0,
987 ("We don't find this rid [%i] count=%d\n", rid,
988 ldap_count_entries(ldap_struct, result)));
989 ldap_unbind(ldap_struct);
990 return False;
993 entry = ldap_first_entry(ldap_struct, result);
994 if (entry)
996 init_sam_from_ldap(user, ldap_struct, entry);
997 ldap_msgfree(result);
998 ldap_unbind(ldap_struct);
999 return True;
1001 else
1003 ldap_msgfree(result);
1004 ldap_unbind(ldap_struct);
1005 return False;
1009 /**********************************************************************
1010 Delete entry from LDAP for username
1011 *********************************************************************/
1013 BOOL pdb_delete_sam_account(char *sname)
1015 int rc;
1016 char *dn;
1017 LDAP *ldap_struct;
1018 LDAPMessage *entry;
1019 LDAPMessage *result;
1021 /* Ensure we have euid as root - else deny this. */
1022 if (!ldap_open_connection (&ldap_struct))
1023 return False;
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));
1030 return False;
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);
1038 return False;
1041 entry = ldap_first_entry (ldap_struct, result);
1042 dn = ldap_get_dn (ldap_struct, entry);
1044 rc = ldap_delete_s (ldap_struct, dn);
1046 ldap_memfree (dn);
1047 if (rc != LDAP_SUCCESS) {
1048 char *ld_error;
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));
1052 free (ld_error);
1053 ldap_unbind (ldap_struct);
1054 return False;
1057 DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname));
1058 ldap_unbind (ldap_struct);
1059 return True;
1062 /**********************************************************************
1063 Update SAM_ACCOUNT
1064 *********************************************************************/
1066 BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd, BOOL override)
1068 int rc;
1069 char *dn;
1070 LDAP *ldap_struct;
1071 LDAPMessage *result;
1072 LDAPMessage *entry;
1073 LDAPMod **mods;
1075 if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
1076 return False;
1078 if (!ldap_connect_system(ldap_struct)) /* connect as system account */ {
1079 ldap_unbind(ldap_struct);
1080 return False;
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);
1090 return False;
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) {
1101 char *ld_error;
1102 ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
1103 &ld_error);
1104 DEBUG(0,
1105 ("failed to modify user with uid = %s with: %s\n\t%s\n",
1106 pdb_get_username(newpwd), ldap_err2string(rc),
1107 ld_error));
1108 free(ld_error);
1109 ldap_unbind(ldap_struct);
1110 return False;
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);
1117 return True;
1120 /**********************************************************************
1121 Add SAM_ACCOUNT to LDAP
1122 *********************************************************************/
1124 BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd)
1126 int rc;
1127 pstring filter;
1128 LDAP *ldap_struct;
1129 LDAPMessage *result;
1130 pstring dn;
1131 LDAPMod **mods;
1132 int ldap_op;
1133 uint32 num_result;
1135 if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
1136 return False;
1138 if (!ldap_connect_system(ldap_struct)) /* connect as system account */ {
1139 ldap_unbind(ldap_struct);
1140 return False;
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);
1149 return False;
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"));
1159 return False;
1162 /* Check if we need to update an existing entry */
1163 if (num_result == 1) {
1164 char *tmp;
1165 LDAPMessage *entry;
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);
1172 ldap_memfree (tmp);
1173 } else {
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);
1187 } else {
1188 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
1189 rc = ldap_add_s(ldap_struct, dn, mods);
1192 if (rc != LDAP_SUCCESS) {
1193 char *ld_error;
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));
1198 free(ld_error);
1199 ldap_mods_free(mods, 1);
1200 ldap_unbind(ldap_struct);
1201 return False;
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);
1207 return True;
1210 #else
1211 void dummy_function(void);
1212 void
1213 dummy_function (void)
1215 } /* stop some compilers complaining */
1216 #endif