2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Gerald Carter 2001
5 Copyright (C) Shahms King 2001
6 Copyright (C) Jean François Micouleau 1998
7 Copyright (C) Andrew Bartlett 2002
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.
28 #define DBGC_CLASS DBGC_PASSDB
32 * persistent connections: if using NSS LDAP, many connections are made
33 * however, using only one within Samba would be nice
35 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
37 * Other LDAP based login attributes: accountExpires, etc.
38 * (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
39 * structures don't have fields for some of these attributes)
41 * SSL is done, but can't get the certificate based authentication to work
42 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
45 /* NOTE: this will NOT work against an Active Directory server
46 * due to the fact that the two password fields cannot be retrieved
47 * from a server; recommend using security = domain in this situation
55 #define SAM_ACCOUNT struct sam_passwd
58 struct ldapsam_privates {
66 /* retrive-once info */
69 BOOL permit_non_unix_accounts;
75 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
77 /*******************************************************************
78 find the ldap password
79 ******************************************************************/
80 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
85 *dn = smb_xstrdup(lp_ldap_admin_dn());
87 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
89 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
92 *pw=secrets_fetch(key, &size);
94 /* Upgrade 2.2 style entry */
96 char* old_style_key = strdup(*dn);
100 if (!old_style_key) {
101 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
105 for (p=old_style_key; *p; p++)
106 if (*p == ',') *p = '/';
108 data=secrets_fetch(old_style_key, &size);
109 if (!size && size < sizeof(old_style_pw)) {
110 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
111 SAFE_FREE(old_style_key);
116 strncpy(old_style_pw, data, size);
117 old_style_pw[size] = 0;
121 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
122 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
123 SAFE_FREE(old_style_key);
127 if (!secrets_delete(old_style_key)) {
128 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
131 SAFE_FREE(old_style_key);
133 *pw = smb_xstrdup(old_style_pw);
139 char *attr[] = {"uid", "pwdLastSet", "logonTime",
140 "logoffTime", "kickoffTime", "cn",
141 "pwdCanChange", "pwdMustChange",
142 "dislplayName", "homeDrive",
143 "smbHome", "scriptPath",
144 "profilePath", "description",
145 "userWorkstation", "rid",
146 "primaryGroupID", "lmPassword",
147 "ntPassword", "acctFlags",
148 "domain", "description", NULL };
150 /*******************************************************************
151 open a connection to the ldap server.
152 ******************************************************************/
153 static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
156 if (geteuid() != 0) {
157 DEBUG(0, ("ldap_open_connection: cannot access LDAP when not root..\n"));
161 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
162 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
164 if (ldap_initialize(ldap_struct, ldap_state->uri) != LDAP_SUCCESS) {
165 DEBUG(0, ("ldap_initialize: %s\n", strerror(errno)));
170 /* Parse the string manually */
174 int tls = LDAP_OPT_X_TLS_HARD;
179 const char *p = ldap_state->uri;
180 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
182 /* skip leading "URL:" (if any) */
183 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
187 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
190 if (strequal(protocol, "ldap")) {
192 } else if (strequal(protocol, "ldaps")) {
195 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
199 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
200 DEBUG(0, ("ldap_init failed !\n"));
204 /* Connect to older servers using SSL and V2 rather than Start TLS */
205 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
207 if (version != LDAP_VERSION2)
209 version = LDAP_VERSION2;
210 ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
214 if (strequal(protocol, "ldaps")) {
215 if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
216 if (ldap_get_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
217 &version) == LDAP_OPT_SUCCESS)
219 if (version < LDAP_VERSION3)
221 version = LDAP_VERSION3;
222 ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
226 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
228 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
229 ldap_err2string(rc)));
232 DEBUG (2, ("StartTLS issued: using a TLS connection\n"));
235 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
237 DEBUG(0, ("Failed to setup a TLS session\n"));
242 * No special needs to setup options prior to the LDAP
243 * bind (which should be called next via ldap_connect_system()
249 DEBUG(2, ("ldap_open_connection: connection opened\n"));
254 /*******************************************************************
255 Add a rebind function for authenticated referrals
256 ******************************************************************/
258 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
259 int *method, int freeit )
265 /** @TODO Should we be doing something to check what servers we rebind to?
266 Could we get a referral to a machine that we don't want to give our
267 username and password to? */
272 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
274 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
275 return LDAP_OPERATIONS_ERROR; /* No idea what to return */
278 DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n",
281 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
284 SAFE_FREE(ldap_secret);
291 /*******************************************************************
292 connect to the ldap server under system privilege.
293 ******************************************************************/
294 static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
300 /* get the password */
301 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
303 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
307 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
308 (OpenLDAP) doesnt' seem to support it */
310 DEBUG(10,("ldap_connect_system: Binding to ldap server as \"%s\"\n",
313 ldap_set_rebind_proc(ldap_struct, (LDAP_REBIND_PROC *)(&rebindproc));
315 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
318 SAFE_FREE(ldap_secret);
320 if (rc != LDAP_SUCCESS)
322 DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc)));
326 DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
330 /*******************************************************************
331 run the search by name.
332 ******************************************************************/
333 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, LDAP * ldap_struct, const char *filter, LDAPMessage ** result)
335 int scope = LDAP_SCOPE_SUBTREE;
338 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
340 rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, attr, 0, result);
342 if (rc != LDAP_SUCCESS) {
343 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n",
344 ldap_err2string (rc)));
345 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
352 /*******************************************************************
353 run the search by name.
354 ******************************************************************/
355 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, LDAP * ldap_struct, const char *user,
356 LDAPMessage ** result)
361 * in the filter expression, replace %u with the real name
362 * so in ldap filter, %u MUST exist :-)
364 pstrcpy(filter, lp_ldap_filter());
367 * have to use this here because $ is filtered out
370 all_string_sub(filter, "%u", user, sizeof(pstring));
372 return ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
375 /*******************************************************************
376 run the search by uid.
377 ******************************************************************/
378 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state,
379 LDAP * ldap_struct, int uid,
380 LDAPMessage ** result)
385 /* Get the username from the system and look that up in the LDAP */
387 if ((user = getpwuid_alloc(uid)) == NULL) {
388 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
389 return LDAP_NO_SUCH_OBJECT;
392 pstrcpy(filter, lp_ldap_filter());
394 all_string_sub(filter, "%u", user->pw_name, sizeof(pstring));
398 return ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
401 /*******************************************************************
402 run the search by rid.
403 ******************************************************************/
404 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state,
405 LDAP * ldap_struct, uint32 rid,
406 LDAPMessage ** result)
411 /* check if the user rid exsists, if not, try searching on the uid */
413 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
414 rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
416 if (rc != LDAP_SUCCESS)
417 rc = ldapsam_search_one_user_by_uid(ldap_state, ldap_struct,
418 fallback_pdb_user_rid_to_uid(rid),
424 /*******************************************************************
425 search an attribute and return the first value found.
426 ******************************************************************/
427 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
428 char *attribute, pstring value)
432 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
434 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
439 pstrcpy(value, values[0]);
440 ldap_value_free(values);
441 #ifdef DEBUG_PASSWORDS
442 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
447 /************************************************************************
448 Routine to manage the LDAPMod structure array
449 manage memory used by the array, by each struct, and values
451 ************************************************************************/
452 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
460 if (attribute == NULL || *attribute == '\0')
463 if (value == NULL || *value == '\0')
468 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
471 DEBUG(0, ("make_a_mod: out of memory!\n"));
477 for (i = 0; mods[i] != NULL; ++i) {
478 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
484 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
487 DEBUG(0, ("make_a_mod: out of memory!\n"));
490 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
493 DEBUG(0, ("make_a_mod: out of memory!\n"));
496 mods[i]->mod_op = modop;
497 mods[i]->mod_values = NULL;
498 mods[i]->mod_type = strdup(attribute);
505 if (mods[i]->mod_values != NULL) {
506 for (; mods[i]->mod_values[j] != NULL; j++);
508 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
509 (j + 2) * sizeof (char *));
511 if (mods[i]->mod_values == NULL) {
512 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
515 mods[i]->mod_values[j] = strdup(value);
516 mods[i]->mod_values[j + 1] = NULL;
521 /* New Interface is being implemented here */
523 /**********************************************************************
524 Initialize SAM_ACCOUNT from an LDAP query
525 (Based on init_sam_from_buffer in pdb_tdb.c)
526 *********************************************************************/
527 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
528 SAM_ACCOUNT * sampass,
529 LDAP * ldap_struct, LDAPMessage * entry)
535 pass_can_change_time,
536 pass_must_change_time;
556 uint8 hours[MAX_HOURS_LEN];
559 gid_t gid = getegid();
563 * do a little initialization
567 nt_username[0] = '\0';
571 logon_script[0] = '\0';
572 profile_path[0] = '\0';
574 munged_dial[0] = '\0';
575 workstations[0] = '\0';
578 if (sampass == NULL || ldap_struct == NULL || entry == NULL) {
579 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
583 get_single_attribute(ldap_struct, entry, "uid", username);
584 DEBUG(2, ("Entry found for user: %s\n", username));
586 pstrcpy(nt_username, username);
588 pstrcpy(domain, lp_workgroup());
590 get_single_attribute(ldap_struct, entry, "rid", temp);
591 user_rid = (uint32)atol(temp);
592 if (!get_single_attribute(ldap_struct, entry, "primaryGroupID", temp)) {
595 group_rid = (uint32)atol(temp);
598 if ((ldap_state->permit_non_unix_accounts)
599 && (user_rid >= ldap_state->low_nua_rid)
600 && (user_rid <= ldap_state->high_nua_rid)) {
604 /* These values MAY be in LDAP, but they can also be retrieved through
605 * sys_getpw*() which is how we're doing it
608 pw = getpwnam_alloc(username);
610 DEBUG (2,("init_sam_from_ldap: User [%s] does not ave a uid!\n", username));
616 pdb_set_unix_homedir(sampass, pw->pw_dir);
620 pdb_set_uid(sampass, uid);
621 pdb_set_gid(sampass, gid);
623 if (group_rid == 0) {
625 /* call the mapping code here */
626 if(get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
627 sid_peek_rid(&map.sid, &group_rid);
630 group_rid=pdb_gid_to_group_rid(gid);
635 if (!get_single_attribute(ldap_struct, entry, "pwdLastSet", temp)) {
636 /* leave as default */
638 pass_last_set_time = (time_t) atol(temp);
639 pdb_set_pass_last_set_time(sampass, pass_last_set_time);
642 if (!get_single_attribute(ldap_struct, entry, "logonTime", temp)) {
643 /* leave as default */
645 logon_time = (time_t) atol(temp);
646 pdb_set_logon_time(sampass, logon_time, True);
649 if (!get_single_attribute(ldap_struct, entry, "logoffTime", temp)) {
650 /* leave as default */
652 logoff_time = (time_t) atol(temp);
653 pdb_set_logoff_time(sampass, logoff_time, True);
656 if (!get_single_attribute(ldap_struct, entry, "kickoffTime", temp)) {
657 /* leave as default */
659 kickoff_time = (time_t) atol(temp);
660 pdb_set_kickoff_time(sampass, kickoff_time, True);
663 if (!get_single_attribute(ldap_struct, entry, "pwdCanChange", temp)) {
664 /* leave as default */
666 pass_can_change_time = (time_t) atol(temp);
667 pdb_set_pass_can_change_time(sampass, pass_can_change_time, True);
670 if (!get_single_attribute(ldap_struct, entry, "pwdMustChange", temp)) {
671 /* leave as default */
673 pass_must_change_time = (time_t) atol(temp);
674 pdb_set_pass_must_change_time(sampass, pass_must_change_time, True);
677 /* recommend that 'gecos' and 'displayName' should refer to the same
678 * attribute OID. userFullName depreciated, only used by Samba
679 * primary rules of LDAP: don't make a new attribute when one is already defined
680 * that fits your needs; using cn then displayName rather than 'userFullName'
683 if (!get_single_attribute(ldap_struct, entry, "cn", fullname)) {
684 if (!get_single_attribute(ldap_struct, entry, "displayName", fullname)) {
685 /* leave as default */
687 pdb_set_fullname(sampass, fullname);
690 pdb_set_fullname(sampass, fullname);
693 if (!get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive)) {
694 pdb_set_dir_drive(sampass, standard_sub_specified(sampass->mem_ctx,
700 pdb_set_dir_drive(sampass, dir_drive, True);
703 if (!get_single_attribute(ldap_struct, entry, "smbHome", homedir)) {
704 pdb_set_dir_drive(sampass, standard_sub_specified(sampass->mem_ctx,
710 pdb_set_homedir(sampass, homedir, True);
713 if (!get_single_attribute(ldap_struct, entry, "scriptPath", logon_script)) {
714 pdb_set_logon_script(sampass, standard_sub_specified(sampass->mem_ctx,
720 pdb_set_logon_script(sampass, logon_script, True);
723 if (!get_single_attribute(ldap_struct, entry, "profilePath", profile_path)) {
724 pdb_set_profile_path(sampass, standard_sub_specified(sampass->mem_ctx,
730 pdb_set_profile_path(sampass, profile_path, True);
733 if (!get_single_attribute(ldap_struct, entry, "description", acct_desc)) {
734 /* leave as default */
736 pdb_set_acct_desc(sampass, acct_desc);
739 if (!get_single_attribute(ldap_struct, entry, "userWorkstations", workstations)) {
740 /* leave as default */;
742 pdb_set_workstations(sampass, workstations);
745 /* FIXME: hours stuff should be cleaner */
749 memset(hours, 0xff, hours_len);
751 if (!get_single_attribute (ldap_struct, entry, "lmPassword", temp)) {
752 /* leave as default */
754 pdb_gethexpwd(temp, smblmpwd);
755 memset((char *)temp, '\0', sizeof(temp));
756 if (!pdb_set_lanman_passwd(sampass, smblmpwd))
760 if (!get_single_attribute (ldap_struct, entry, "ntPassword", temp)) {
761 /* leave as default */
763 pdb_gethexpwd(temp, smbntpwd);
764 memset((char *)temp, '\0', sizeof(temp));
765 if (!pdb_set_nt_passwd(sampass, smbntpwd))
769 if (!get_single_attribute (ldap_struct, entry, "acctFlags", temp)) {
770 acct_ctrl |= ACB_NORMAL;
772 acct_ctrl = pdb_decode_acct_ctrl(temp);
775 acct_ctrl |= ACB_NORMAL;
777 pdb_set_acct_ctrl(sampass, acct_ctrl);
780 pdb_set_hours_len(sampass, hours_len);
781 pdb_set_logon_divs(sampass, logon_divs);
783 pdb_set_user_rid(sampass, user_rid);
784 pdb_set_group_rid(sampass, group_rid);
786 pdb_set_username(sampass, username);
788 pdb_set_domain(sampass, domain);
789 pdb_set_nt_username(sampass, nt_username);
791 pdb_set_munged_dial(sampass, munged_dial);
793 /* pdb_set_unknown_3(sampass, unknown3); */
794 /* pdb_set_unknown_5(sampass, unknown5); */
795 /* pdb_set_unknown_6(sampass, unknown6); */
797 pdb_set_hours(sampass, hours);
802 /**********************************************************************
803 Initialize SAM_ACCOUNT from an LDAP query
804 (Based on init_buffer_from_sam in pdb_tdb.c)
805 *********************************************************************/
806 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
807 LDAPMod *** mods, int ldap_op,
808 const SAM_ACCOUNT * sampass)
813 if (mods == NULL || sampass == NULL) {
814 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
821 * took out adding "objectclass: sambaAccount"
822 * do this on a per-mod basis
825 make_a_mod(mods, ldap_op, "uid", pdb_get_username(sampass));
826 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
828 if ( pdb_get_user_rid(sampass) ) {
829 rid = pdb_get_user_rid(sampass);
830 } else if (IS_SAM_SET(sampass, FLAG_SAM_UID)) {
831 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
832 } else if (ldap_state->permit_non_unix_accounts) {
833 rid = ldapsam_get_next_available_nua_rid(ldap_state);
835 DEBUG(0, ("NO user RID specified on account %s, and findining next available NUA RID failed, cannot store!\n", pdb_get_username(sampass)));
839 DEBUG(0, ("NO user RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
843 slprintf(temp, sizeof(temp) - 1, "%i", rid);
844 make_a_mod(mods, ldap_op, "rid", temp);
846 if ( pdb_get_group_rid(sampass) ) {
847 rid = pdb_get_group_rid(sampass);
848 } else if (IS_SAM_SET(sampass, FLAG_SAM_GID)) {
849 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
850 } else if (ldap_state->permit_non_unix_accounts) {
851 rid = DOMAIN_GROUP_RID_USERS;
853 DEBUG(0, ("NO group RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
857 slprintf(temp, sizeof(temp) - 1, "%i", rid);
858 make_a_mod(mods, ldap_op, "primaryGroupID", temp);
860 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
861 make_a_mod(mods, ldap_op, "pwdLastSet", temp);
863 /* displayName, cn, and gecos should all be the same
864 * most easily accomplished by giving them the same OID
865 * gecos isn't set here b/c it should be handled by the
869 make_a_mod(mods, ldap_op, "displayName", pdb_get_fullname(sampass));
870 make_a_mod(mods, ldap_op, "cn", pdb_get_fullname(sampass));
871 make_a_mod(mods, ldap_op, "description", pdb_get_acct_desc(sampass));
872 make_a_mod(mods, ldap_op, "userWorkstations", pdb_get_workstations(sampass));
875 * Only updates fields which have been set (not defaults from smb.conf)
878 if (IS_SAM_SET(sampass, FLAG_SAM_SMBHOME))
879 make_a_mod(mods, ldap_op, "smbHome", pdb_get_homedir(sampass));
881 if (IS_SAM_SET(sampass, FLAG_SAM_DRIVE))
882 make_a_mod(mods, ldap_op, "homeDrive", pdb_get_dirdrive(sampass));
884 if (IS_SAM_SET(sampass, FLAG_SAM_LOGONSCRIPT))
885 make_a_mod(mods, ldap_op, "scriptPath", pdb_get_logon_script(sampass));
887 if (IS_SAM_SET(sampass, FLAG_SAM_PROFILE))
888 make_a_mod(mods, ldap_op, "profilePath", pdb_get_profile_path(sampass));
890 if (IS_SAM_SET(sampass, FLAG_SAM_LOGONTIME)) {
891 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
892 make_a_mod(mods, ldap_op, "logonTime", temp);
895 if (IS_SAM_SET(sampass, FLAG_SAM_LOGOFFTIME)) {
896 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
897 make_a_mod(mods, ldap_op, "logoffTime", temp);
900 if (IS_SAM_SET(sampass, FLAG_SAM_KICKOFFTIME)) {
901 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
902 make_a_mod(mods, ldap_op, "kickoffTime", temp);
905 if (IS_SAM_SET(sampass, FLAG_SAM_CANCHANGETIME)) {
906 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
907 make_a_mod(mods, ldap_op, "pwdCanChange", temp);
910 if (IS_SAM_SET(sampass, FLAG_SAM_MUSTCHANGETIME)) {
911 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
912 make_a_mod(mods, ldap_op, "pwdMustChange", temp);
915 /* FIXME: Hours stuff goes in LDAP */
916 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
917 make_a_mod (mods, ldap_op, "lmPassword", temp);
919 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
920 make_a_mod (mods, ldap_op, "ntPassword", temp);
922 make_a_mod (mods, ldap_op, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
923 NEW_PW_FORMAT_SPACE_PADDED_LEN));
929 /**********************************************************************
930 Connect to LDAP server and find the next available RID.
931 *********************************************************************/
932 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid, LDAP *ldap_struct)
935 uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
940 if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
944 if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, final_rid, &result) != LDAP_SUCCESS) {
945 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
947 ldap_msgfree(result);
950 if (ldap_count_entries(ldap_struct, result) != 0)
952 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
954 ldap_msgfree(result);
957 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
961 /**********************************************************************
962 Extract the RID from an LDAP entry
963 *********************************************************************/
964 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, LDAP *ldap_struct) {
966 SAM_ACCOUNT *user = NULL;
967 if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
971 if (init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
972 rid = pdb_get_user_rid(user);
977 if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
984 /**********************************************************************
985 Connect to LDAP server and find the next available RID.
986 *********************************************************************/
987 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state, LDAP *ldap_struct)
993 char *final_filter = NULL;
998 pstrcpy(filter, lp_ldap_filter());
999 all_string_sub(filter, "%u", "*", sizeof(pstring));
1002 asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1004 final_filter = strdup(filter);
1006 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1008 rc = ldap_search_s(ldap_struct, lp_ldap_suffix(),
1009 LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1012 if (rc != LDAP_SUCCESS)
1015 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1016 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1019 ldap_msgfree(result);
1024 count = ldap_count_entries(ldap_struct, result);
1025 DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1028 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1029 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1031 ldap_msgfree(result);
1033 return ldap_state->low_nua_rid;
1037 entry = ldap_first_entry(ldap_struct,result);
1039 top_rid = entry_to_user_rid(ldap_state, entry, ldap_struct);
1041 while ((entry = ldap_next_entry(ldap_struct, entry))) {
1043 rid = entry_to_user_rid(ldap_state, entry, ldap_struct);
1044 if (rid > top_rid) {
1049 ldap_msgfree(result);
1053 /**********************************************************************
1054 Connect to LDAP server and find the next available RID.
1055 *********************************************************************/
1056 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1058 uint32 next_nua_rid;
1061 if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1065 if (!ldapsam_connect_system(ldap_state, ldap_struct))
1067 ldap_unbind(ldap_struct);
1071 top_nua_rid = search_top_nua_rid(ldap_state, ldap_struct);
1073 next_nua_rid = check_nua_rid_is_avail(ldap_state,
1074 top_nua_rid, ldap_struct);
1076 ldap_unbind(ldap_struct);
1077 return next_nua_rid;
1080 /**********************************************************************
1081 Connect to LDAP server for password enumeration
1082 *********************************************************************/
1083 static BOOL ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1085 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1089 if (!ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))
1093 if (!ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))
1095 ldap_unbind(ldap_state->ldap_struct);
1099 pstrcpy(filter, lp_ldap_filter());
1100 all_string_sub(filter, "%u", "*", sizeof(pstring));
1102 rc = ldap_search_s(ldap_state->ldap_struct, lp_ldap_suffix(),
1103 LDAP_SCOPE_SUBTREE, filter, attr, 0,
1104 &ldap_state->result);
1106 if (rc != LDAP_SUCCESS)
1108 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1109 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1110 ldap_msgfree(ldap_state->result);
1111 ldap_unbind(ldap_state->ldap_struct);
1112 ldap_state->ldap_struct = NULL;
1113 ldap_state->result = NULL;
1117 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1118 ldap_count_entries(ldap_state->ldap_struct,
1119 ldap_state->result)));
1121 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1122 ldap_state->result);
1123 ldap_state->index = 0;
1128 /**********************************************************************
1129 End enumeration of the LDAP password list
1130 *********************************************************************/
1131 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1133 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1134 if (ldap_state->ldap_struct && ldap_state->result)
1136 ldap_msgfree(ldap_state->result);
1137 ldap_unbind(ldap_state->ldap_struct);
1138 ldap_state->ldap_struct = NULL;
1139 ldap_state->result = NULL;
1143 /**********************************************************************
1144 Get the next entry in the LDAP password database
1145 *********************************************************************/
1146 static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * user)
1148 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1152 if (!ldap_state->entry)
1155 ldap_state->index++;
1156 ret = init_sam_from_ldap(ldap_state, user, ldap_state->ldap_struct,
1159 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1167 /**********************************************************************
1168 Get SAM_ACCOUNT entry from LDAP by username
1169 *********************************************************************/
1170 static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const char *sname)
1172 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1174 LDAPMessage *result;
1177 if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1179 if (!ldapsam_connect_system(ldap_state, ldap_struct))
1181 ldap_unbind(ldap_struct);
1184 if (ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result) != LDAP_SUCCESS)
1186 ldap_unbind(ldap_struct);
1189 if (ldap_count_entries(ldap_struct, result) < 1)
1192 ("We don't find this user [%s] count=%d\n", sname,
1193 ldap_count_entries(ldap_struct, result)));
1194 ldap_unbind(ldap_struct);
1197 entry = ldap_first_entry(ldap_struct, result);
1200 if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
1201 DEBUG(0,("ldapsam_getsampwnam: init_sam_from_ldap failed!\n"));
1202 ldap_msgfree(result);
1203 ldap_unbind(ldap_struct);
1206 ldap_msgfree(result);
1207 ldap_unbind(ldap_struct);
1212 ldap_msgfree(result);
1213 ldap_unbind(ldap_struct);
1218 /**********************************************************************
1219 Get SAM_ACCOUNT entry from LDAP by rid
1220 *********************************************************************/
1221 static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, uint32 rid)
1223 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1225 LDAPMessage *result;
1228 if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1231 if (!ldapsam_connect_system(ldap_state, ldap_struct))
1233 ldap_unbind(ldap_struct);
1236 if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, rid, &result) !=
1239 ldap_unbind(ldap_struct);
1243 if (ldap_count_entries(ldap_struct, result) < 1)
1246 ("We don't find this rid [%i] count=%d\n", rid,
1247 ldap_count_entries(ldap_struct, result)));
1248 ldap_unbind(ldap_struct);
1252 entry = ldap_first_entry(ldap_struct, result);
1255 if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
1256 DEBUG(0,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1257 ldap_msgfree(result);
1258 ldap_unbind(ldap_struct);
1261 ldap_msgfree(result);
1262 ldap_unbind(ldap_struct);
1267 ldap_msgfree(result);
1268 ldap_unbind(ldap_struct);
1273 /**********************************************************************
1274 Delete entry from LDAP for username
1275 *********************************************************************/
1276 static BOOL ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1278 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1284 LDAPMessage *result;
1287 DEBUG(0, ("sam_acct was NULL!\n"));
1291 sname = pdb_get_username(sam_acct);
1293 if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1296 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1298 if (!ldapsam_connect_system(ldap_state, ldap_struct)) {
1299 ldap_unbind (ldap_struct);
1300 DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname));
1304 rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result);
1305 if (ldap_count_entries (ldap_struct, result) == 0) {
1306 DEBUG (0, ("User doesn't exit!\n"));
1307 ldap_msgfree (result);
1308 ldap_unbind (ldap_struct);
1312 entry = ldap_first_entry (ldap_struct, result);
1313 dn = ldap_get_dn (ldap_struct, entry);
1315 rc = ldap_delete_s (ldap_struct, dn);
1318 if (rc != LDAP_SUCCESS) {
1320 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1321 DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n",
1322 sname, ldap_err2string (rc), ld_error));
1324 ldap_unbind (ldap_struct);
1328 DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname));
1329 ldap_unbind (ldap_struct);
1333 /**********************************************************************
1335 *********************************************************************/
1336 static BOOL ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1338 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1342 LDAPMessage *result;
1346 if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
1349 if (!ldapsam_connect_system(ldap_state, ldap_struct)) /* connect as system account */
1351 ldap_unbind(ldap_struct);
1355 rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct,
1356 pdb_get_username(newpwd), &result);
1358 if (ldap_count_entries(ldap_struct, result) == 0)
1360 DEBUG(0, ("No user to modify!\n"));
1361 ldap_msgfree(result);
1362 ldap_unbind(ldap_struct);
1366 if (!init_ldap_from_sam(ldap_state, &mods, LDAP_MOD_REPLACE, newpwd)) {
1367 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1368 ldap_msgfree(result);
1369 ldap_unbind(ldap_struct);
1373 entry = ldap_first_entry(ldap_struct, result);
1374 dn = ldap_get_dn(ldap_struct, entry);
1376 rc = ldap_modify_s(ldap_struct, dn, mods);
1378 if (rc != LDAP_SUCCESS)
1381 ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
1384 ("failed to modify user with uid = %s with: %s\n\t%s\n",
1385 pdb_get_username(newpwd), ldap_err2string(rc),
1388 ldap_unbind(ldap_struct);
1393 ("successfully modified uid = %s in the LDAP database\n",
1394 pdb_get_username(newpwd)));
1395 ldap_mods_free(mods, 1);
1396 ldap_unbind(ldap_struct);
1400 /**********************************************************************
1401 Add SAM_ACCOUNT to LDAP
1402 *********************************************************************/
1403 static BOOL ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1405 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1408 LDAP *ldap_struct = NULL;
1409 LDAPMessage *result = NULL;
1411 LDAPMod **mods = NULL;
1415 const char *username = pdb_get_username(newpwd);
1416 if (!username || !*username) {
1417 DEBUG(0, ("Cannot add user without a username!\n"));
1421 if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
1426 if (!ldapsam_connect_system(ldap_state, ldap_struct)) /* connect as system account */
1428 ldap_unbind(ldap_struct);
1432 rc = ldapsam_search_one_user_by_name (ldap_state, ldap_struct, username, &result);
1434 if (ldap_count_entries(ldap_struct, result) != 0)
1436 DEBUG(0,("User already in the base, with samba properties\n"));
1437 ldap_msgfree(result);
1438 ldap_unbind(ldap_struct);
1441 ldap_msgfree(result);
1443 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
1444 rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, &result);
1445 num_result = ldap_count_entries(ldap_struct, result);
1447 if (num_result > 1) {
1448 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1449 ldap_msgfree(result);
1453 /* Check if we need to update an existing entry */
1454 if (num_result == 1) {
1458 DEBUG(3,("User exists without samba properties: adding them\n"));
1459 ldap_op = LDAP_MOD_REPLACE;
1460 entry = ldap_first_entry (ldap_struct, result);
1461 tmp = ldap_get_dn (ldap_struct, entry);
1462 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1466 /* Check if we need to add an entry */
1467 DEBUG(3,("Adding new user\n"));
1468 ldap_op = LDAP_MOD_ADD;
1469 if (username[strlen(username)-1] == '$') {
1470 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1472 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1476 ldap_msgfree(result);
1478 if (!init_ldap_from_sam(ldap_state, &mods, ldap_op, newpwd)) {
1479 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1480 ldap_mods_free(mods, 1);
1481 ldap_unbind(ldap_struct);
1484 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
1486 if (ldap_op == LDAP_MOD_REPLACE) {
1487 rc = ldap_modify_s(ldap_struct, dn, mods);
1490 rc = ldap_add_s(ldap_struct, dn, mods);
1493 if (rc != LDAP_SUCCESS)
1497 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1498 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s) with: %s\n\t%s\n",
1499 pdb_get_username(newpwd), dn, ldap_err2string (rc), ld_error));
1501 ldap_mods_free(mods, 1);
1502 ldap_unbind(ldap_struct);
1506 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
1507 ldap_mods_free(mods, 1);
1508 ldap_unbind(ldap_struct);
1512 static void free_private_data(void **vp)
1514 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
1516 if ((*ldap_state)->ldap_struct) {
1517 ldap_unbind((*ldap_state)->ldap_struct);
1522 /* No need to free any further, as it is talloc()ed */
1525 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1528 struct ldapsam_privates *ldap_state;
1530 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
1534 (*pdb_method)->name = "ldapsam";
1536 (*pdb_method)->setsampwent = ldapsam_setsampwent;
1537 (*pdb_method)->endsampwent = ldapsam_endsampwent;
1538 (*pdb_method)->getsampwent = ldapsam_getsampwent;
1539 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
1540 (*pdb_method)->getsampwrid = ldapsam_getsampwrid;
1541 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
1542 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
1543 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
1545 /* TODO: Setup private data and free */
1547 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
1550 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1551 return NT_STATUS_NO_MEMORY;
1555 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
1557 ldap_state->uri = "ldap://localhost";
1560 (*pdb_method)->private_data = ldap_state;
1562 (*pdb_method)->free_private_data = free_private_data;
1564 return NT_STATUS_OK;
1567 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1570 struct ldapsam_privates *ldap_state;
1571 uint32 low_nua_uid, high_nua_uid;
1573 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
1577 (*pdb_method)->name = "ldapsam_nua";
1579 ldap_state = (*pdb_method)->private_data;
1581 ldap_state->permit_non_unix_accounts = True;
1583 if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
1584 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
1585 return NT_STATUS_UNSUCCESSFUL;
1588 ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
1590 ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
1592 return NT_STATUS_OK;
1598 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1600 DEBUG(0, ("ldap not detected at configure time, ldapsam not availalble!\n"));
1601 return NT_STATUS_UNSUCCESSFUL;
1604 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1606 DEBUG(0, ("ldap not dectected at configure time, ldapsam_nua not available!\n"));
1607 return NT_STATUS_UNSUCCESSFUL;