add WITH_SENDFILE profiling data (from Pierre Belanger)
[Samba.git] / source / passdb / pdb_ldap.c
bloba42583471789b1e060056c0e0d6971a84050ff72
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;
69 extern pstring samlogon_user;
70 extern BOOL sam_logon_in_ssb;
72 /*
73 * attributes needed from sambaAccount
75 * objectclass ( 1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' SUP top AUXILIARY
76 * DESC 'Samba Auxilary Account'
77 * MUST ( uid $ rid )
78 * MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $
79 * logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $
80 * displayName $ smbHome $ homeDrive $ scriptPath $ profilePath $
81 * description $ userWorkstations $ primaryGroupID $ domain ))
84 char* attribs[] = {
85 "uid",
86 "rid",
87 "cn",
88 "lmPassword",
89 "ntPassword",
90 "pwdLastSet",
91 "logonTime",
92 "logoffTime",
93 "kickoffTime",
94 "pwdCanChange",
95 "pwdMustChange",
96 "acctFlags",
97 "displayName",
98 "smbHome",
99 "homeDrive",
100 "scriptPath",
101 "profilePath",
102 "description",
103 "userWorkstations",
104 "primaryGroupID",
105 "domain",
106 NULL
110 /*******************************************************************
111 open a connection to the ldap server.
112 ******************************************************************/
113 static BOOL ldap_open_connection (LDAP ** ldap_struct)
115 int port;
116 int version;
117 int tls, rc;
118 uid_t uid = geteuid();
119 struct passwd* pass;
121 DEBUG(5,("ldap_open_connection: starting...\n"));
123 * using sys_getpwnam() here since I'm assuming that the
124 * ldapsam is only used on a standalone server or PDC.
125 * winbind not in the picture....
128 if ( (pass=sys_getpwuid(uid)) == NULL ) {
129 DEBUG(0,("ldap_open_connection: Can't determine user of running process!\n"));
130 return False;
133 /* check that the user is in the domain admin group for connecting */
135 if ( (uid != 0) && !user_in_list(pass->pw_name, lp_domain_admin_group()) ) {
136 DEBUG(0, ("ldap_open_connection: cannot access LDAP when not root or a member of domain admin group..\n"));
137 return False;
140 port = lp_ldap_port();
142 /* remap default port is no SSL */
143 if ( (lp_ldap_ssl() == LDAP_SSL_OFF) && (lp_ldap_port() == 636) ) {
144 port = 389;
147 DEBUG(10,("Initializing connection to %s on port %d\n",
148 lp_ldap_server(), port ));
150 if ((*ldap_struct = ldap_init(lp_ldap_server(), port)) == NULL) {
151 DEBUG(0, ("The LDAP server is not responding !\n"));
152 return False;
155 /* Connect to older servers using SSL and V2 rather than Start TLS */
156 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
158 if (version != LDAP_VERSION2)
160 version = LDAP_VERSION2;
161 ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
165 switch (lp_ldap_ssl())
167 case LDAP_SSL_START_TLS:
168 #ifdef HAVE_LDAP_START_TLS_S
169 if (ldap_get_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
170 &version) == LDAP_OPT_SUCCESS)
172 if (version < LDAP_VERSION3)
174 version = LDAP_VERSION3;
175 ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
176 &version);
179 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
181 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
182 ldap_err2string(rc)));
183 return False;
185 DEBUG (2, ("StartTLS issued: using a TLS connection\n"));
186 #else
187 DEBUG(0,("ldap_open_connection: StartTLS not supported by LDAP client libraries!\n"));
188 return False;
189 #endif
190 break;
192 case LDAP_SSL_ON:
193 #ifdef LDAP_OPT_X_TLS
194 tls = LDAP_OPT_X_TLS_HARD;
195 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
197 DEBUG(0, ("Failed to setup a TLS session\n"));
200 DEBUG(0,("LDAPS option set...!\n"));
201 #else
202 DEBUG(0,("ldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
203 return False;
204 #endif
205 break;
207 case LDAP_SSL_OFF:
208 default:
210 * No special needs to setup options prior to the LDAP
211 * bind (which should be called next via ldap_connect_system()
213 break;
216 DEBUG(2, ("ldap_open_connection: connection opened\n"));
217 return True;
220 /*******************************************************************
221 connect to the ldap server under system privilege.
222 ******************************************************************/
223 static BOOL ldap_connect_system(LDAP * ldap_struct)
225 int rc;
226 static BOOL got_pw = False;
227 static pstring ldap_secret;
229 /* get the password if we don't have it already */
230 if (!got_pw && !(got_pw=fetch_ldap_pw(lp_ldap_admin_dn(), ldap_secret, sizeof(pstring))))
232 DEBUG(0, ("ldap_connect_system: Failed to retrieve password for %s from secrets.tdb\n",
233 lp_ldap_admin_dn()));
234 return False;
237 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
238 (OpenLDAP) doesnt' seem to support it */
240 DEBUG(10,("ldap_connect_system: Binding to ldap server as \"%s\"\n",
241 lp_ldap_admin_dn()));
243 if ((rc = ldap_simple_bind_s(ldap_struct, lp_ldap_admin_dn(),
244 ldap_secret)) != LDAP_SUCCESS)
246 DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc)));
247 return False;
250 DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
251 return True;
254 /*******************************************************************
255 run the search by name.
256 ******************************************************************/
257 static int ldap_search_one_user (LDAP * ldap_struct, const char *filter, LDAPMessage ** result)
259 int scope = LDAP_SCOPE_SUBTREE;
260 int rc;
262 DEBUG(2, ("ldap_search_one_user: searching for:[%s]\n", filter));
264 rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, (char*)filter, attribs, 0, result);
266 if (rc != LDAP_SUCCESS) {
267 DEBUG(0,("ldap_search_one_user: Problem during the LDAP search: %s\n",
268 ldap_err2string (rc)));
269 DEBUG(3,("ldap_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
270 filter));
273 return rc;
276 /*******************************************************************
277 run the search by name.
278 ******************************************************************/
279 static int ldap_search_one_user_by_name (LDAP * ldap_struct, const char *user,
280 LDAPMessage ** result)
282 pstring filter;
285 * in the filter expression, replace %u with the real name
286 * so in ldap filter, %u MUST exist :-)
288 pstrcpy(filter, lp_ldap_filter());
291 * have to use this here because $ is filtered out
292 * in pstring_sub
294 all_string_sub(filter, "%u", user, sizeof(pstring));
296 return ldap_search_one_user(ldap_struct, filter, result);
299 /*******************************************************************
300 run the search by uid.
301 ******************************************************************/
302 static int ldap_search_one_user_by_uid(LDAP * ldap_struct, int uid,
303 LDAPMessage ** result)
305 struct passwd *user;
306 pstring filter;
308 /* Get the username from the system and look that up in the LDAP */
310 if ((user = sys_getpwuid(uid)) == NULL) {
311 DEBUG(3,("ldap_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
312 return LDAP_NO_SUCH_OBJECT;
315 pstrcpy(filter, lp_ldap_filter());
317 all_string_sub(filter, "%u", user->pw_name, sizeof(pstring));
319 return ldap_search_one_user(ldap_struct, filter, result);
322 /*******************************************************************
323 run the search by rid.
324 ******************************************************************/
325 static int ldap_search_one_user_by_rid (LDAP * ldap_struct, uint32 rid,
326 LDAPMessage ** result)
328 pstring filter;
329 int rc;
331 /* check if the user rid exsists, if not, try searching on the uid */
333 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
334 rc = ldap_search_one_user(ldap_struct, filter, result);
336 if (rc != LDAP_SUCCESS)
337 rc = ldap_search_one_user_by_uid(ldap_struct,
338 pdb_user_rid_to_uid(rid), result);
340 return rc;
343 /*******************************************************************
344 search an attribute and return the first value found.
345 the string in 'value' is unchanged if the attribute does not exist
346 ******************************************************************/
348 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
349 char *attribute, char *value)
351 char **values;
353 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
354 DEBUG (2, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
355 return False;
358 pstrcpy(value, values[0]);
359 ldap_value_free(values);
360 DEBUG (2, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
362 return True;
365 /************************************************************************
366 Routine to manage the LDAPMod structure array
367 manage memory used by the array, by each struct, and values
368 ************************************************************************/
370 static void make_a_mod (LDAPMod *** modlist, int modop, char *attribute, char *value)
372 LDAPMod **mods;
373 int i;
374 int j;
376 mods = *modlist;
378 if (attribute == NULL || *attribute == '\0')
379 return;
381 if (value == NULL || *value == '\0')
382 return;
384 if (mods == NULL)
386 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
387 if (mods == NULL)
389 DEBUG(0, ("make_a_mod: out of memory!\n"));
390 return;
392 mods[0] = NULL;
395 for (i = 0; mods[i] != NULL; ++i) {
396 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
397 break;
400 if (mods[i] == NULL)
402 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
403 if (mods == NULL)
405 DEBUG(0, ("make_a_mod: out of memory!\n"));
406 return;
408 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
409 if (mods[i] == NULL)
411 DEBUG(0, ("make_a_mod: out of memory!\n"));
412 return;
414 mods[i]->mod_op = modop;
415 mods[i]->mod_values = NULL;
416 mods[i]->mod_type = strdup(attribute);
417 mods[i + 1] = NULL;
420 if (value != NULL)
422 j = 0;
423 if (mods[i]->mod_values != NULL) {
424 for (; mods[i]->mod_values[j] != NULL; j++);
426 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
427 (j + 2) * sizeof (char *));
429 if (mods[i]->mod_values == NULL) {
430 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
431 return;
433 mods[i]->mod_values[j] = strdup(value);
434 mods[i]->mod_values[j + 1] = NULL;
436 *modlist = mods;
439 /* New Interface is being implemented here */
441 /**********************************************************************
442 Initialize SAM_ACCOUNT from an LDAP query
443 (Based on init_sam_from_buffer in pdb_tdb.c)
444 *********************************************************************/
445 static BOOL init_sam_from_ldap (SAM_ACCOUNT * sampass,
446 LDAP * ldap_struct, LDAPMessage * entry)
448 time_t logon_time,
449 logoff_time,
450 kickoff_time,
451 pass_last_set_time,
452 pass_can_change_time,
453 pass_must_change_time;
454 pstring username,
455 domain,
456 nt_username,
457 fullname,
458 homedir,
459 dir_drive,
460 logon_script,
461 profile_path,
462 acct_desc,
463 munged_dial,
464 workstations;
465 struct passwd *sys_user;
466 uint32 user_rid,
467 group_rid;
468 uint8 smblmpwd[16],
469 smbntpwd[16];
470 uint16 acct_ctrl,
471 logon_divs;
472 uint32 hours_len;
473 uint8 hours[MAX_HOURS_LEN];
474 pstring temp;
475 gid_t gid = getegid();
479 * do a little initialization
481 username[0] = '\0';
482 domain[0] = '\0';
483 nt_username[0] = '\0';
484 fullname[0] = '\0';
485 homedir[0] = '\0';
486 dir_drive[0] = '\0';
487 logon_script[0] = '\0';
488 profile_path[0] = '\0';
489 acct_desc[0] = '\0';
490 munged_dial[0] = '\0';
491 workstations[0] = '\0';
494 get_single_attribute(ldap_struct, entry, "uid", username);
495 DEBUG(2, ("Entry found for user: %s\n", username));
497 pstrcpy(samlogon_user, username);
499 pstrcpy(nt_username, username);
501 pstrcpy(domain, lp_workgroup());
503 pass_last_set_time = TIME_T_MAX;
504 logon_time = TIME_T_MAX;
505 logoff_time = TIME_T_MAX;
506 kickoff_time = TIME_T_MAX;
507 pass_can_change_time = TIME_T_MAX;
508 pass_must_change_time = TIME_T_MAX;
511 if (get_single_attribute(ldap_struct, entry, "pwdLastSet", temp))
512 pass_last_set_time = (time_t) atol(temp);
514 if (get_single_attribute(ldap_struct, entry, "logonTime", temp))
515 logon_time = (time_t) atol(temp);
517 if (get_single_attribute(ldap_struct, entry, "logoffTime", temp))
518 logoff_time = (time_t) atol(temp);
520 if (get_single_attribute(ldap_struct, entry, "kickoffTime", temp))
521 kickoff_time = (time_t) atol(temp);
523 if (get_single_attribute(ldap_struct, entry, "pwdCanChange", temp))
524 pass_can_change_time = (time_t) atol(temp);
526 if (get_single_attribute(ldap_struct, entry, "pwdMustChange", temp))
527 pass_must_change_time = (time_t) atol(temp);
529 /* recommend that 'gecos' and 'displayName' should refer to the same
530 * attribute OID. userFullName depreciated, only used by Samba
531 * primary rules of LDAP: don't make a new attribute when one is already defined
532 * that fits your needs; using cn then displayName rather than 'userFullName'
535 sam_logon_in_ssb = True;
537 if (!get_single_attribute(ldap_struct, entry, "cn", fullname)) {
538 get_single_attribute(ldap_struct, entry, "displayName", fullname);
542 if (!get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive)) {
543 pstrcpy(dir_drive, lp_logon_drive());
544 standard_sub_advanced(-1, username, "", gid, dir_drive, sizeof(dir_drive));
545 DEBUG(5,("homeDrive fell back to %s\n",dir_drive));
546 pdb_set_dir_drive(sampass, dir_drive, False);
548 else
549 pdb_set_dir_drive(sampass, dir_drive, True);
551 if (!get_single_attribute(ldap_struct, entry, "smbHome", homedir)) {
552 pstrcpy(homedir, lp_logon_home());
553 standard_sub_advanced(-1, username, "", gid, homedir, sizeof(homedir));
554 DEBUG(5,("smbHome fell back to %s\n",homedir));
555 pdb_set_homedir(sampass, homedir, False);
557 else
558 pdb_set_homedir(sampass, homedir, True);
560 if (!get_single_attribute(ldap_struct, entry, "scriptPath", logon_script)) {
561 pstrcpy(logon_script, lp_logon_script());
562 standard_sub_advanced(-1, username, "", gid, logon_script, sizeof(logon_script));
563 DEBUG(5,("scriptPath fell back to %s\n",logon_script));
564 pdb_set_logon_script(sampass, logon_script, False);
566 else
567 pdb_set_logon_script(sampass, logon_script, True);
569 if (!get_single_attribute(ldap_struct, entry, "profilePath", profile_path)) {
570 pstrcpy(profile_path, lp_logon_path());
571 standard_sub_advanced(-1, username, "", gid, profile_path, sizeof(profile_path));
572 DEBUG(5,("profilePath fell back to %s\n",profile_path));
573 pdb_set_profile_path(sampass, profile_path, False);
575 else
576 pdb_set_profile_path(sampass, profile_path, True);
578 sam_logon_in_ssb = False;
580 get_single_attribute(ldap_struct, entry, "description", acct_desc);
581 get_single_attribute(ldap_struct, entry, "userWorkstations", workstations);
582 get_single_attribute(ldap_struct, entry, "rid", temp);
583 user_rid = (uint32)atol(temp);
584 get_single_attribute(ldap_struct, entry, "primaryGroupID", temp);
585 group_rid = (uint32)atol(temp);
588 /* These values MAY be in LDAP, but they can also be retrieved through
589 * sys_getpw*() which is how we're doing it
591 sys_user = sys_getpwnam(username);
592 if (sys_user == NULL) {
593 DEBUG (2,("init_sam_from_ldap: User [%s] does not ave a uid!\n", username));
594 return False;
598 /* FIXME: hours stuff should be cleaner */
600 logon_divs = 168;
601 hours_len = 21;
602 memset(hours, 0xff, hours_len);
604 get_single_attribute (ldap_struct, entry, "lmPassword", temp);
605 pdb_gethexpwd(temp, smblmpwd);
606 memset((char *)temp, '\0', sizeof(temp));
607 get_single_attribute (ldap_struct, entry, "ntPassword", temp);
608 pdb_gethexpwd(temp, smbntpwd);
609 memset((char *)temp, '\0', sizeof(temp));
610 get_single_attribute (ldap_struct, entry, "acctFlags", temp);
611 acct_ctrl = pdb_decode_acct_ctrl(temp);
613 if (acct_ctrl == 0)
614 acct_ctrl |= ACB_NORMAL;
617 pdb_set_acct_ctrl(sampass, acct_ctrl);
618 pdb_set_logon_time(sampass, logon_time);
619 pdb_set_logoff_time(sampass, logoff_time);
620 pdb_set_kickoff_time(sampass, kickoff_time);
621 pdb_set_pass_can_change_time(sampass, pass_can_change_time);
622 pdb_set_pass_must_change_time(sampass, pass_must_change_time);
623 pdb_set_pass_last_set_time(sampass, pass_last_set_time);
625 pdb_set_hours_len(sampass, hours_len);
626 pdb_set_logon_divs(sampass, logon_divs);
628 pdb_set_uid(sampass, sys_user->pw_uid);
629 pdb_set_gid(sampass, sys_user->pw_gid);
630 pdb_set_user_rid(sampass, user_rid);
631 pdb_set_group_rid(sampass, group_rid);
633 pdb_set_username(sampass, username);
635 pdb_set_domain(sampass, domain);
636 pdb_set_nt_username(sampass, nt_username);
638 pdb_set_fullname(sampass, fullname);
640 pdb_set_acct_desc(sampass, acct_desc);
641 pdb_set_workstations(sampass, workstations);
642 pdb_set_munged_dial(sampass, munged_dial);
644 if (!pdb_set_nt_passwd(sampass, smbntpwd))
645 return False;
646 if (!pdb_set_lanman_passwd(sampass, smblmpwd))
647 return False;
649 /* pdb_set_unknown_3(sampass, unknown3); */
650 /* pdb_set_unknown_5(sampass, unknown5); */
651 /* pdb_set_unknown_6(sampass, unknown6); */
653 pdb_set_hours(sampass, hours);
655 return True;
658 /**********************************************************************
659 Initialize SAM_ACCOUNT from an LDAP query
660 (Based on init_buffer_from_sam in pdb_tdb.c)
661 *********************************************************************/
662 static BOOL init_ldap_from_sam (LDAPMod *** mods, int ldap_state, SAM_ACCOUNT * sampass)
664 pstring temp;
666 *mods = NULL;
669 * took out adding "objectclass: sambaAccount"
670 * do this on a per-mod basis
674 make_a_mod(mods, ldap_state, "uid", pdb_get_username(sampass));
675 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
677 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
678 make_a_mod(mods, ldap_state, "pwdLastSet", temp);
680 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
681 make_a_mod(mods, ldap_state, "logonTime", temp);
683 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
684 make_a_mod(mods, ldap_state, "logoffTime", temp);
686 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
687 make_a_mod(mods, ldap_state, "kickoffTime", temp);
689 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
690 make_a_mod(mods, ldap_state, "pwdCanChange", temp);
692 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
693 make_a_mod(mods, ldap_state, "pwdMustChange", temp);
695 /* displayName, cn, and gecos should all be the same
696 * most easily accomplished by giving them the same OID
697 * gecos isn't set here b/c it should be handled by the
698 * add-user script
701 make_a_mod(mods, ldap_state, "displayName", pdb_get_fullname(sampass));
702 make_a_mod(mods, ldap_state, "cn", pdb_get_fullname(sampass));
703 make_a_mod(mods, ldap_state, "description", pdb_get_acct_desc(sampass));
704 make_a_mod(mods, ldap_state, "userWorkstations", pdb_get_workstations(sampass));
707 * Only updates fields which have been set (not defaults from smb.conf)
710 if (IS_SAM_SET(sampass, FLAG_SAM_SMBHOME))
711 make_a_mod(mods, ldap_state, "smbHome", pdb_get_homedir(sampass));
713 if (IS_SAM_SET(sampass, FLAG_SAM_DRIVE))
714 make_a_mod(mods, ldap_state, "homeDrive", pdb_get_dirdrive(sampass));
716 if (IS_SAM_SET(sampass, FLAG_SAM_LOGONSCRIPT))
717 make_a_mod(mods, ldap_state, "scriptPath", pdb_get_logon_script(sampass));
719 if (IS_SAM_SET(sampass, FLAG_SAM_PROFILE))
720 make_a_mod(mods, ldap_state, "profilePath", pdb_get_profile_path(sampass));
723 if ( !pdb_get_user_rid(sampass))
724 slprintf(temp, sizeof(temp) - 1, "%i", pdb_uid_to_user_rid(pdb_get_uid(sampass)));
725 else
726 slprintf(temp, sizeof(temp) - 1, "%i", pdb_get_user_rid(sampass));
727 make_a_mod(mods, ldap_state, "rid", temp);
729 if ( !pdb_get_group_rid(sampass))
730 slprintf(temp, sizeof(temp) - 1, "%i", pdb_gid_to_group_rid(pdb_get_gid(sampass)));
731 else
732 slprintf(temp, sizeof(temp) - 1, "%i", pdb_get_group_rid(sampass));
733 make_a_mod(mods, ldap_state, "primaryGroupID", temp);
735 /* FIXME: Hours stuff goes in LDAP */
736 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
737 make_a_mod (mods, ldap_state, "lmPassword", temp);
739 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
740 make_a_mod (mods, ldap_state, "ntPassword", temp);
742 make_a_mod (mods, ldap_state, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
743 NEW_PW_FORMAT_SPACE_PADDED_LEN));
745 return True;
748 /**********************************************************************
749 Connect to LDAP server for password enumeration
750 *********************************************************************/
751 BOOL pdb_setsampwent(BOOL update)
753 int rc;
754 pstring filter;
756 if (!ldap_open_connection(&global_ldap_ent.ldap_struct))
758 return False;
760 if (!ldap_connect_system(global_ldap_ent.ldap_struct))
762 ldap_unbind(global_ldap_ent.ldap_struct);
763 return False;
766 pstrcpy(filter, lp_ldap_filter());
767 all_string_sub(filter, "%u", "*", sizeof(pstring));
769 rc = ldap_search_s(global_ldap_ent.ldap_struct, lp_ldap_suffix(),
770 LDAP_SCOPE_SUBTREE, filter, attribs, 0,
771 &global_ldap_ent.result);
773 if (rc != LDAP_SUCCESS)
775 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
776 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
777 ldap_msgfree(global_ldap_ent.result);
778 ldap_unbind(global_ldap_ent.ldap_struct);
779 global_ldap_ent.ldap_struct = NULL;
780 global_ldap_ent.result = NULL;
781 return False;
784 DEBUG(2, ("pdb_setsampwent: %d entries in the base!\n",
785 ldap_count_entries(global_ldap_ent.ldap_struct,
786 global_ldap_ent.result)));
788 global_ldap_ent.entry = ldap_first_entry(global_ldap_ent.ldap_struct,
789 global_ldap_ent.result);
790 global_ldap_ent.index = -1;
792 return True;
795 /**********************************************************************
796 End enumeration of the LDAP password list
797 *********************************************************************/
798 void pdb_endsampwent(void)
800 if (global_ldap_ent.ldap_struct && global_ldap_ent.result)
802 ldap_msgfree(global_ldap_ent.result);
803 ldap_unbind(global_ldap_ent.ldap_struct);
804 global_ldap_ent.ldap_struct = NULL;
805 global_ldap_ent.result = NULL;
809 /**********************************************************************
810 Get the next entry in the LDAP password database
811 *********************************************************************/
812 BOOL pdb_getsampwent(SAM_ACCOUNT * user)
814 if (!global_ldap_ent.entry)
815 return False;
817 global_ldap_ent.index++;
818 if (global_ldap_ent.index > 0)
820 global_ldap_ent.entry = ldap_next_entry(global_ldap_ent.ldap_struct, global_ldap_ent.entry);
823 if (global_ldap_ent.entry != NULL)
825 return init_sam_from_ldap(user, global_ldap_ent.ldap_struct,
826 global_ldap_ent.entry);
828 return False;
831 /**********************************************************************
832 Get SAM_ACCOUNT entry from LDAP by username
833 *********************************************************************/
834 BOOL pdb_getsampwnam(SAM_ACCOUNT * user, char *sname)
836 LDAP *ldap_struct;
837 LDAPMessage *result;
838 LDAPMessage *entry;
840 if (!ldap_open_connection(&ldap_struct))
841 return False;
842 if (!ldap_connect_system(ldap_struct))
844 ldap_unbind(ldap_struct);
845 return False;
847 if (ldap_search_one_user_by_name(ldap_struct, sname, &result) != LDAP_SUCCESS)
849 ldap_unbind(ldap_struct);
850 return False;
852 if (ldap_count_entries(ldap_struct, result) < 1)
854 pstring filter;
856 pstrcpy(filter, lp_ldap_filter());
857 standard_sub_advanced(-1, sname, "", -1, filter, sizeof(filter));
858 DEBUG(0,("LDAP search \"%s\" returned %d entries.\n", filter,
859 ldap_count_entries(ldap_struct, result)));
860 ldap_unbind(ldap_struct);
861 return False;
863 entry = ldap_first_entry(ldap_struct, result);
864 if (entry)
866 init_sam_from_ldap(user, ldap_struct, entry);
867 ldap_msgfree(result);
868 ldap_unbind(ldap_struct);
869 return True;
871 else
873 ldap_msgfree(result);
874 ldap_unbind(ldap_struct);
875 return False;
879 /**********************************************************************
880 Get SAM_ACCOUNT entry from LDAP by rid
881 *********************************************************************/
882 BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid)
884 LDAP *ldap_struct;
885 LDAPMessage *result;
886 LDAPMessage *entry;
888 if (!ldap_open_connection(&ldap_struct))
889 return False;
891 if (!ldap_connect_system(ldap_struct))
893 ldap_unbind(ldap_struct);
894 return False;
896 if (ldap_search_one_user_by_rid(ldap_struct, rid, &result) !=
897 LDAP_SUCCESS)
899 ldap_unbind(ldap_struct);
900 return False;
903 if (ldap_count_entries(ldap_struct, result) < 1)
905 DEBUG(0,
906 ("We don't find this rid [%i] count=%d\n", rid,
907 ldap_count_entries(ldap_struct, result)));
908 ldap_unbind(ldap_struct);
909 return False;
912 entry = ldap_first_entry(ldap_struct, result);
913 if (entry)
915 init_sam_from_ldap(user, ldap_struct, entry);
916 ldap_msgfree(result);
917 ldap_unbind(ldap_struct);
918 return True;
920 else
922 ldap_msgfree(result);
923 ldap_unbind(ldap_struct);
924 return False;
928 /**********************************************************************
929 Delete entry from LDAP for username
930 *********************************************************************/
932 BOOL pdb_delete_sam_account(char *sname)
934 int rc;
935 char *dn;
936 LDAP *ldap_struct;
937 LDAPMessage *entry;
938 LDAPMessage *result;
940 /* Ensure we have euid as root - else deny this. */
941 if (!ldap_open_connection (&ldap_struct))
942 return False;
944 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
946 if (!ldap_connect_system (ldap_struct)) {
947 ldap_unbind (ldap_struct);
948 DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname));
949 return False;
952 rc = ldap_search_one_user_by_name (ldap_struct, sname, &result);
953 if (ldap_count_entries (ldap_struct, result) == 0) {
954 DEBUG (0, ("User doesn't exit!\n"));
955 ldap_msgfree (result);
956 ldap_unbind (ldap_struct);
957 return False;
960 entry = ldap_first_entry (ldap_struct, result);
961 dn = ldap_get_dn (ldap_struct, entry);
963 rc = ldap_delete_s (ldap_struct, dn);
965 ldap_memfree (dn);
966 if (rc != LDAP_SUCCESS) {
967 char *ld_error;
968 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
969 DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n",
970 sname, ldap_err2string (rc), ld_error));
971 free (ld_error);
972 ldap_unbind (ldap_struct);
973 return False;
976 DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname));
977 ldap_unbind (ldap_struct);
978 return True;
981 /**********************************************************************
982 Update SAM_ACCOUNT
983 *********************************************************************/
985 BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd, BOOL override)
987 int rc;
988 char *dn;
989 LDAP *ldap_struct;
990 LDAPMessage *result;
991 LDAPMessage *entry;
992 LDAPMod **mods;
994 if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
995 return False;
997 if (!ldap_connect_system(ldap_struct)) /* connect as system account */ {
998 ldap_unbind(ldap_struct);
999 return False;
1002 rc = ldap_search_one_user_by_name(ldap_struct,
1003 pdb_get_username(newpwd), &result);
1005 if (ldap_count_entries(ldap_struct, result) == 0) {
1006 DEBUG(0, ("No user to modify!\n"));
1007 ldap_msgfree(result);
1008 ldap_unbind(ldap_struct);
1009 return False;
1012 init_ldap_from_sam(&mods, LDAP_MOD_REPLACE, newpwd);
1014 entry = ldap_first_entry(ldap_struct, result);
1015 dn = ldap_get_dn(ldap_struct, entry);
1017 rc = ldap_modify_s(ldap_struct, dn, mods);
1019 if (rc != LDAP_SUCCESS) {
1020 char *ld_error;
1021 ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
1022 &ld_error);
1023 DEBUG(0,
1024 ("failed to modify user with uid = %s with: %s\n\t%s\n",
1025 pdb_get_username(newpwd), ldap_err2string(rc),
1026 ld_error));
1027 free(ld_error);
1028 ldap_unbind(ldap_struct);
1029 return False;
1032 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
1033 pdb_get_username(newpwd)));
1034 ldap_mods_free(mods, 1);
1035 ldap_unbind(ldap_struct);
1036 return True;
1039 /**********************************************************************
1040 Add SAM_ACCOUNT to LDAP
1041 *********************************************************************/
1043 BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd)
1045 int rc;
1046 pstring filter;
1047 LDAP *ldap_struct;
1048 LDAPMessage *result;
1049 pstring dn;
1050 LDAPMod **mods;
1051 int ldap_op;
1052 uint32 num_result;
1054 if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
1055 return False;
1057 if (!ldap_connect_system(ldap_struct)) /* connect as system account */ {
1058 ldap_unbind(ldap_struct);
1059 return False;
1062 rc = ldap_search_one_user_by_name (ldap_struct, pdb_get_username(newpwd), &result);
1064 if (ldap_count_entries(ldap_struct, result) != 0) {
1065 DEBUG(0,("User already in the base, with samba properties\n"));
1066 ldap_msgfree(result);
1067 ldap_unbind(ldap_struct);
1068 return False;
1070 ldap_msgfree(result);
1072 slprintf (filter, sizeof (filter) - 1, "uid=%s", pdb_get_username(newpwd));
1073 rc = ldap_search_one_user(ldap_struct, filter, &result);
1074 num_result = ldap_count_entries(ldap_struct, result);
1076 if (num_result > 1) {
1077 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1078 return False;
1081 /* Check if we need to update an existing entry */
1082 if (num_result == 1) {
1083 char *tmp;
1084 LDAPMessage *entry;
1086 DEBUG(3,("User exists without samba properties: adding them\n"));
1087 ldap_op = LDAP_MOD_REPLACE;
1088 entry = ldap_first_entry (ldap_struct, result);
1089 tmp = ldap_get_dn (ldap_struct, entry);
1090 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1091 ldap_memfree (tmp);
1092 } else {
1093 /* Check if we need to add an entry */
1094 DEBUG(3,("Adding new user\n"));
1095 ldap_op = LDAP_MOD_ADD;
1096 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", pdb_get_username(newpwd), lp_ldap_suffix ());
1099 ldap_msgfree(result);
1101 init_ldap_from_sam(&mods, ldap_op, newpwd);
1102 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
1104 if (ldap_op == LDAP_MOD_REPLACE) {
1105 rc = ldap_modify_s(ldap_struct, dn, mods);
1106 } else {
1107 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
1108 rc = ldap_add_s(ldap_struct, dn, mods);
1111 if (rc != LDAP_SUCCESS) {
1112 char *ld_error;
1114 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1115 DEBUG(0,("failed to modify user with uid = %s with: %s\n\t%s\n",
1116 pdb_get_username(newpwd), ldap_err2string (rc), ld_error));
1117 free(ld_error);
1118 ldap_mods_free(mods, 1);
1119 ldap_unbind(ldap_struct);
1120 return False;
1123 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
1124 ldap_mods_free(mods, 1);
1125 ldap_unbind(ldap_struct);
1126 return True;
1129 #else
1130 void dummy_function(void);
1131 void
1132 dummy_function (void)
1134 } /* stop some compilers complaining */
1135 #endif