2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Jean François Micouleau 1998
5 Copyright (C) Gerald Carter 2001
6 Copyright (C) Shahms King 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Stefan (metze) Metzmacher 2002
9 Copyright (C) Jim McDonough 2003
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #define DBGC_CLASS DBGC_PASSDB
33 * persistent connections: if using NSS LDAP, many connections are made
34 * however, using only one within Samba would be nice
36 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
38 * Other LDAP based login attributes: accountExpires, etc.
39 * (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
40 * structures don't have fields for some of these attributes)
42 * SSL is done, but can't get the certificate based authentication to work
43 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
46 /* NOTE: this will NOT work against an Active Directory server
47 * due to the fact that the two password fields cannot be retrieved
48 * from a server; recommend using security = domain in this situation
58 #define SAM_ACCOUNT struct sam_passwd
61 static uint32 ldapsam_get_next_available_nua_rid(struct smb_ldap_privates *ldap_state);
63 /*******************************************************************
64 find the ldap password
65 ******************************************************************/
66 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
71 *dn = smb_xstrdup(lp_ldap_admin_dn());
73 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
75 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
78 *pw=secrets_fetch(key, &size);
80 /* Upgrade 2.2 style entry */
82 char* old_style_key = strdup(*dn);
87 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
91 for (p=old_style_key; *p; p++)
92 if (*p == ',') *p = '/';
94 data=secrets_fetch(old_style_key, &size);
95 if (!size && size < sizeof(old_style_pw)) {
96 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
97 SAFE_FREE(old_style_key);
102 strncpy(old_style_pw, data, size);
103 old_style_pw[size] = 0;
107 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
108 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
109 SAFE_FREE(old_style_key);
113 if (!secrets_delete(old_style_key)) {
114 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
117 SAFE_FREE(old_style_key);
119 *pw = smb_xstrdup(old_style_pw);
125 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
126 "logoffTime", "kickoffTime", "cn",
127 "pwdCanChange", "pwdMustChange",
128 "displayName", "homeDrive",
129 "smbHome", "scriptPath",
130 "profilePath", "description",
131 "userWorkstations", "rid",
132 "primaryGroupID", "lmPassword",
133 "ntPassword", "acctFlags",
134 "domain", "objectClass",
135 "uidNumber", "gidNumber",
136 "homeDirectory", NULL };
138 /*******************************************************************
139 run the search by name.
140 ******************************************************************/
141 static int ldapsam_search_one_user (struct smb_ldap_privates *ldap_state, const char *filter, LDAPMessage ** result)
143 int scope = LDAP_SCOPE_SUBTREE;
146 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
148 rc = smb_ldap_search(ldap_state, lp_ldap_suffix (), scope, filter, attr, 0, result);
150 if (rc != LDAP_SUCCESS) {
151 char *ld_error = NULL;
152 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
154 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s (%s)\n",
155 ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
156 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
164 /*******************************************************************
165 run the search by name.
166 ******************************************************************/
167 static int ldapsam_search_one_user_by_name (struct smb_ldap_privates *ldap_state, const char *user,
168 LDAPMessage ** result)
171 char *escape_user = escape_ldap_string_alloc(user);
174 return LDAP_NO_MEMORY;
178 * in the filter expression, replace %u with the real name
179 * so in ldap filter, %u MUST exist :-)
181 pstrcpy(filter, lp_ldap_filter());
184 * have to use this here because $ is filtered out
189 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
190 SAFE_FREE(escape_user);
192 return ldapsam_search_one_user(ldap_state, filter, result);
195 /*******************************************************************
196 run the search by uid.
197 ******************************************************************/
198 static int ldapsam_search_one_user_by_uid(struct smb_ldap_privates *ldap_state,
200 LDAPMessage ** result)
206 /* Get the username from the system and look that up in the LDAP */
208 if ((user = getpwuid_alloc(uid)) == NULL) {
209 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
210 return LDAP_NO_SUCH_OBJECT;
213 pstrcpy(filter, lp_ldap_filter());
215 escape_user = escape_ldap_string_alloc(user->pw_name);
218 return LDAP_NO_MEMORY;
221 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
224 SAFE_FREE(escape_user);
226 return ldapsam_search_one_user(ldap_state, filter, result);
229 /*******************************************************************
230 run the search by rid.
231 ******************************************************************/
232 static int ldapsam_search_one_user_by_rid (struct smb_ldap_privates *ldap_state,
234 LDAPMessage ** result)
239 /* check if the user rid exsists, if not, try searching on the uid */
241 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
242 rc = ldapsam_search_one_user(ldap_state, filter, result);
244 if (rc != LDAP_SUCCESS)
245 rc = ldapsam_search_one_user_by_uid(ldap_state,
246 fallback_pdb_user_rid_to_uid(rid),
252 /*******************************************************************
253 Delete complete object or objectclass and attrs from
254 object found in search_result depending on lp_ldap_delete_dn
255 ******************************************************************/
256 static NTSTATUS ldapsam_delete_entry(struct smb_ldap_privates *ldap_state,
258 const char *objectclass,
263 LDAPMod **mods = NULL;
265 BerElement *ptr = NULL;
267 rc = ldap_count_entries(ldap_state->ldap_struct, result);
270 DEBUG(0, ("Entry must exist exactly once!\n"));
271 return NT_STATUS_UNSUCCESSFUL;
274 entry = ldap_first_entry(ldap_state->ldap_struct, result);
275 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
277 if (lp_ldap_delete_dn()) {
278 NTSTATUS ret = NT_STATUS_OK;
279 rc = smb_ldap_delete(ldap_state, dn);
281 if (rc != LDAP_SUCCESS) {
282 DEBUG(0, ("Could not delete object %s\n", dn));
283 ret = NT_STATUS_UNSUCCESSFUL;
289 /* Ok, delete only the SAM attributes */
291 for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
293 name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) {
297 /* We are only allowed to delete the attributes that
300 for (attrib = attrs; *attrib != NULL; attrib++) {
301 if (StrCaseCmp(*attrib, name) == 0) {
302 DEBUG(10, ("deleting attribute %s\n", name));
303 smb_ldap_make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
314 smb_ldap_make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
316 rc = smb_ldap_modify(ldap_state, dn, mods);
317 ldap_mods_free(mods, 1);
319 if (rc != LDAP_SUCCESS) {
320 char *ld_error = NULL;
321 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
324 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
325 dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
328 return NT_STATUS_UNSUCCESSFUL;
335 /* New Interface is being implemented here */
337 /**********************************************************************
338 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
339 *********************************************************************/
340 static BOOL get_unix_attributes (struct smb_ldap_privates *ldap_state,
341 SAM_ACCOUNT * sampass,
351 if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
352 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
356 for (values=ldap_values;*values;values++) {
357 if (strcasecmp(*values, "posixAccount") == 0) {
362 if (!*values) { /*end of array, no posixAccount */
363 DEBUG(10, ("user does not have posixAcccount attributes\n"));
364 ldap_value_free(ldap_values);
367 ldap_value_free(ldap_values);
369 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir))
372 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
375 uid = (uid_t)atol(temp);
377 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
380 gid = (gid_t)atol(temp);
382 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
383 pdb_set_uid(sampass, uid, PDB_SET);
384 pdb_set_gid(sampass, gid, PDB_SET);
386 DEBUG(10, ("user has posixAcccount attributes\n"));
391 /**********************************************************************
392 Initialize SAM_ACCOUNT from an LDAP query
393 (Based on init_sam_from_buffer in pdb_tdb.c)
394 *********************************************************************/
395 static BOOL init_sam_from_ldap (struct smb_ldap_privates *ldap_state,
396 SAM_ACCOUNT * sampass,
403 pass_can_change_time,
404 pass_must_change_time;
419 uint8 smblmpwd[LM_HASH_LEN],
420 smbntpwd[NT_HASH_LEN];
421 uint16 acct_ctrl = 0,
424 uint8 hours[MAX_HOURS_LEN];
427 gid_t gid = getegid();
431 * do a little initialization
435 nt_username[0] = '\0';
439 logon_script[0] = '\0';
440 profile_path[0] = '\0';
442 munged_dial[0] = '\0';
443 workstations[0] = '\0';
446 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
447 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
451 if (ldap_state->ldap_struct == NULL) {
452 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
456 smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "uid", username);
457 DEBUG(2, ("Entry found for user: %s\n", username));
459 pstrcpy(nt_username, username);
461 pstrcpy(domain, lp_workgroup());
463 pdb_set_username(sampass, username, PDB_SET);
465 pdb_set_domain(sampass, domain, PDB_DEFAULT);
466 pdb_set_nt_username(sampass, nt_username, PDB_SET);
468 smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
469 user_rid = (uint32)atol(temp);
471 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
473 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
476 group_rid = (uint32)atol(temp);
477 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
482 * If so configured, try and get the values from LDAP
485 if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state, sampass, entry))) {
488 * Otherwise just ask the system getpw() calls.
491 pw = getpwnam_alloc(username);
493 if (! ldap_state->permit_non_unix_accounts) {
494 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
499 pdb_set_uid(sampass, uid, PDB_SET);
501 pdb_set_gid(sampass, gid, PDB_SET);
503 pdb_set_unix_homedir(sampass, pw->pw_dir, PDB_SET);
509 if (group_rid == 0 && pdb_get_init_flags(sampass,PDB_GID) != PDB_DEFAULT) {
511 gid = pdb_get_gid(sampass);
512 /* call the mapping code here */
513 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
514 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
517 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
521 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
522 /* leave as default */
524 pass_last_set_time = (time_t) atol(temp);
525 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
528 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
529 /* leave as default */
531 logon_time = (time_t) atol(temp);
532 pdb_set_logon_time(sampass, logon_time, PDB_SET);
535 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
536 /* leave as default */
538 logoff_time = (time_t) atol(temp);
539 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
542 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
543 /* leave as default */
545 kickoff_time = (time_t) atol(temp);
546 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
549 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
550 /* leave as default */
552 pass_can_change_time = (time_t) atol(temp);
553 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
556 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
557 /* leave as default */
559 pass_must_change_time = (time_t) atol(temp);
560 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
563 /* recommend that 'gecos' and 'displayName' should refer to the same
564 * attribute OID. userFullName depreciated, only used by Samba
565 * primary rules of LDAP: don't make a new attribute when one is already defined
566 * that fits your needs; using cn then displayName rather than 'userFullName'
569 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry,
570 "displayName", fullname)) {
571 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry,
573 /* leave as default */
575 pdb_set_fullname(sampass, fullname, PDB_SET);
578 pdb_set_fullname(sampass, fullname, PDB_SET);
581 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
582 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
588 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
591 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
592 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
598 pdb_set_homedir(sampass, homedir, PDB_SET);
601 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
602 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
608 pdb_set_logon_script(sampass, logon_script, PDB_SET);
611 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
612 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
618 pdb_set_profile_path(sampass, profile_path, PDB_SET);
621 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
622 /* leave as default */
624 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
627 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
628 /* leave as default */;
630 pdb_set_workstations(sampass, workstations, PDB_SET);
633 /* FIXME: hours stuff should be cleaner */
637 memset(hours, 0xff, hours_len);
639 if (!smb_ldap_get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
640 /* leave as default */
642 pdb_gethexpwd(temp, smblmpwd);
643 memset((char *)temp, '\0', strlen(temp)+1);
644 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
646 ZERO_STRUCT(smblmpwd);
649 if (!smb_ldap_get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
650 /* leave as default */
652 pdb_gethexpwd(temp, smbntpwd);
653 memset((char *)temp, '\0', strlen(temp)+1);
654 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
656 ZERO_STRUCT(smbntpwd);
659 if (!smb_ldap_get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
660 acct_ctrl |= ACB_NORMAL;
662 acct_ctrl = pdb_decode_acct_ctrl(temp);
665 acct_ctrl |= ACB_NORMAL;
667 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
670 pdb_set_hours_len(sampass, hours_len, PDB_SET);
671 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
673 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
675 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
676 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
677 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
679 pdb_set_hours(sampass, hours, PDB_SET);
684 /**********************************************************************
685 An LDAP modification is needed in two cases:
686 * If we are updating the record AND the attribute is CHANGED.
687 * If we are adding the record AND it is SET or CHANGED (ie not default)
688 *********************************************************************/
689 static BOOL need_ldap_mod(BOOL pdb_add, const SAM_ACCOUNT * sampass, enum pdb_elements element) {
691 return (!IS_SAM_DEFAULT(sampass, element));
693 return IS_SAM_CHANGED(sampass, element);
697 /**********************************************************************
698 Set attribute to newval in LDAP, regardless of what value the
699 attribute had in LDAP before.
700 *********************************************************************/
701 static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
703 const char *attribute, const char *newval)
705 char **values = NULL;
707 if (existing != NULL) {
708 values = ldap_get_values(ldap_struct, existing, attribute);
711 if ((values != NULL) && (values[0] != NULL) &&
712 strcmp(values[0], newval) == 0) {
714 /* Believe it or not, but LDAP will deny a delete and
715 an add at the same time if the values are the
718 ldap_value_free(values);
722 /* Regardless of the real operation (add or modify)
723 we add the new value here. We rely on deleting
724 the old value, should it exist. */
726 if ((newval != NULL) && (strlen(newval) > 0)) {
727 smb_ldap_make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
730 if (values == NULL) {
731 /* There has been no value before, so don't delete it.
732 Here's a possible race: We might end up with
733 duplicate attributes */
737 /* By deleting exactly the value we found in the entry this
738 should be race-free in the sense that the LDAP-Server will
739 deny the complete operation if somebody changed the
740 attribute behind our back. */
742 smb_ldap_make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
743 ldap_value_free(values);
746 /**********************************************************************
747 Initialize SAM_ACCOUNT from an LDAP query
748 (Based on init_buffer_from_sam in pdb_tdb.c)
749 *********************************************************************/
750 static BOOL init_ldap_from_sam (struct smb_ldap_privates *ldap_state,
751 LDAPMessage *existing,
752 LDAPMod *** mods, const SAM_ACCOUNT * sampass,
753 BOOL (*need_update)(const SAM_ACCOUNT *,
759 if (mods == NULL || sampass == NULL) {
760 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
767 * took out adding "objectclass: sambaAccount"
768 * do this on a per-mod basis
770 if (need_update(sampass, PDB_USERNAME))
771 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
772 "uid", pdb_get_username(sampass));
774 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
776 rid = pdb_get_user_rid(sampass);
779 if (!IS_SAM_DEFAULT(sampass, PDB_UID)) {
780 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
781 } else if (ldap_state->permit_non_unix_accounts) {
782 rid = ldapsam_get_next_available_nua_rid(ldap_state);
784 DEBUG(0, ("NO user RID specified on account %s, and "
785 "findining next available NUA RID failed, "
787 pdb_get_username(sampass)));
788 ldap_mods_free(*mods, 1);
792 DEBUG(0, ("NO user RID specified on account %s, "
793 "cannot store!\n", pdb_get_username(sampass)));
794 ldap_mods_free(*mods, 1);
799 slprintf(temp, sizeof(temp) - 1, "%i", rid);
801 if (need_update(sampass, PDB_USERSID))
802 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
806 rid = pdb_get_group_rid(sampass);
809 if (!IS_SAM_DEFAULT(sampass, PDB_GID)) {
810 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
811 } else if (ldap_state->permit_non_unix_accounts) {
812 rid = DOMAIN_GROUP_RID_USERS;
814 DEBUG(0, ("NO group RID specified on account %s, "
815 "cannot store!\n", pdb_get_username(sampass)));
816 ldap_mods_free(*mods, 1);
821 slprintf(temp, sizeof(temp) - 1, "%i", rid);
823 if (need_update(sampass, PDB_GROUPSID))
824 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
825 "primaryGroupID", temp);
827 /* displayName, cn, and gecos should all be the same
828 * most easily accomplished by giving them the same OID
829 * gecos isn't set here b/c it should be handled by the
831 * We change displayName only and fall back to cn if
835 if (need_update(sampass, PDB_FULLNAME))
836 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
837 "displayName", pdb_get_fullname(sampass));
839 if (need_update(sampass, PDB_ACCTDESC))
840 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
841 "description", pdb_get_acct_desc(sampass));
843 if (need_update(sampass, PDB_WORKSTATIONS))
844 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
845 "userWorkstations", pdb_get_workstations(sampass));
847 if (need_update(sampass, PDB_SMBHOME))
848 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
849 "smbHome", pdb_get_homedir(sampass));
851 if (need_update(sampass, PDB_DRIVE))
852 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
853 "homeDrive", pdb_get_dir_drive(sampass));
855 if (need_update(sampass, PDB_LOGONSCRIPT))
856 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
857 "scriptPath", pdb_get_logon_script(sampass));
859 if (need_update(sampass, PDB_PROFILE))
860 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
861 "profilePath", pdb_get_profile_path(sampass));
863 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
865 if (need_update(sampass, PDB_LOGONTIME))
866 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
869 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
871 if (need_update(sampass, PDB_LOGOFFTIME))
872 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
875 slprintf (temp, sizeof (temp) - 1, "%li",
876 pdb_get_kickoff_time(sampass));
878 if (need_update(sampass, PDB_KICKOFFTIME))
879 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
880 "kickoffTime", temp);
882 slprintf (temp, sizeof (temp) - 1, "%li",
883 pdb_get_pass_can_change_time(sampass));
885 if (need_update(sampass, PDB_CANCHANGETIME))
886 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
887 "pwdCanChange", temp);
889 slprintf (temp, sizeof (temp) - 1, "%li",
890 pdb_get_pass_must_change_time(sampass));
892 if (need_update(sampass, PDB_MUSTCHANGETIME))
893 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
894 "pwdMustChange", temp);
896 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
897 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
899 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass),
900 pdb_get_acct_ctrl(sampass));
902 if (need_update(sampass, PDB_LMPASSWD))
903 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
906 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
907 pdb_get_acct_ctrl(sampass));
909 if (need_update(sampass, PDB_NTPASSWD))
910 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
913 slprintf (temp, sizeof (temp) - 1, "%li",
914 pdb_get_pass_last_set_time(sampass));
916 if (need_update(sampass, PDB_PASSLASTSET))
917 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
921 /* FIXME: Hours stuff goes in LDAP */
923 if (need_update(sampass, PDB_ACCTCTRL))
924 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
926 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
927 NEW_PW_FORMAT_SPACE_PADDED_LEN));
933 /**********************************************************************
934 Connect to LDAP server and find the next available RID.
935 *********************************************************************/
936 static uint32 check_nua_rid_is_avail(struct smb_ldap_privates *ldap_state, uint32 top_rid)
939 uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
944 if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
948 if (ldapsam_search_one_user_by_rid(ldap_state, final_rid, &result) != LDAP_SUCCESS) {
949 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
953 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
954 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
955 ldap_msgfree(result);
959 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
960 ldap_msgfree(result);
964 /**********************************************************************
965 Extract the RID from an LDAP entry
966 *********************************************************************/
967 static uint32 entry_to_user_rid(struct smb_ldap_privates *ldap_state, LDAPMessage *entry) {
969 SAM_ACCOUNT *user = NULL;
970 if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
974 if (init_sam_from_ldap(ldap_state, user, entry)) {
975 rid = pdb_get_user_rid(user);
980 if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
987 /**********************************************************************
988 Connect to LDAP server and find the next available RID.
989 *********************************************************************/
990 static uint32 search_top_nua_rid(struct smb_ldap_privates *ldap_state)
996 char *final_filter = NULL;
1001 pstrcpy(filter, lp_ldap_filter());
1002 all_string_sub(filter, "%u", "*", sizeof(pstring));
1005 asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1007 final_filter = strdup(filter);
1009 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1011 rc = smb_ldap_search(ldap_state, lp_ldap_suffix(),
1012 LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1015 if (rc != LDAP_SUCCESS) {
1016 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1017 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1024 count = ldap_count_entries(ldap_state->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_state->ldap_struct,result);
1039 top_rid = entry_to_user_rid(ldap_state, entry);
1041 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1043 rid = entry_to_user_rid(ldap_state, entry);
1044 if (rid > top_rid) {
1049 ldap_msgfree(result);
1051 if (top_rid < ldap_state->low_nua_rid)
1052 top_rid = ldap_state->low_nua_rid;
1057 /**********************************************************************
1058 Connect to LDAP server and find the next available RID.
1059 *********************************************************************/
1060 static uint32 ldapsam_get_next_available_nua_rid(struct smb_ldap_privates *ldap_state) {
1061 uint32 next_nua_rid;
1064 top_nua_rid = search_top_nua_rid(ldap_state);
1066 next_nua_rid = check_nua_rid_is_avail(ldap_state,
1069 return next_nua_rid;
1072 /**********************************************************************
1073 Connect to LDAP server for password enumeration
1074 *********************************************************************/
1075 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1077 struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
1081 pstrcpy(filter, lp_ldap_filter());
1082 all_string_sub(filter, "%u", "*", sizeof(pstring));
1084 rc = smb_ldap_search(ldap_state, lp_ldap_suffix(),
1085 LDAP_SCOPE_SUBTREE, filter, attr, 0,
1086 &ldap_state->result);
1088 if (rc != LDAP_SUCCESS) {
1089 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1090 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1091 ldap_msgfree(ldap_state->result);
1092 ldap_state->result = NULL;
1093 return NT_STATUS_UNSUCCESSFUL;
1096 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1097 ldap_count_entries(ldap_state->ldap_struct,
1098 ldap_state->result)));
1100 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1101 ldap_state->result);
1102 ldap_state->index = 0;
1104 return NT_STATUS_OK;
1107 /**********************************************************************
1108 End enumeration of the LDAP password list
1109 *********************************************************************/
1110 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1112 struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
1113 if (ldap_state->result) {
1114 ldap_msgfree(ldap_state->result);
1115 ldap_state->result = NULL;
1119 /**********************************************************************
1120 Get the next entry in the LDAP password database
1121 *********************************************************************/
1122 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1124 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1125 struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
1129 if (!ldap_state->entry)
1132 ldap_state->index++;
1133 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1135 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1139 return NT_STATUS_OK;
1142 /**********************************************************************
1143 Get SAM_ACCOUNT entry from LDAP by username
1144 *********************************************************************/
1145 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1147 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1148 struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
1149 LDAPMessage *result;
1153 if (ldapsam_search_one_user_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
1154 return NT_STATUS_NO_SUCH_USER;
1157 count = ldap_count_entries(ldap_state->ldap_struct, result);
1161 ("We don't find this user [%s] count=%d\n", sname,
1163 return NT_STATUS_NO_SUCH_USER;
1164 } else if (count > 1) {
1166 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
1168 return NT_STATUS_NO_SUCH_USER;
1171 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1173 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1174 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1175 ldap_msgfree(result);
1176 return NT_STATUS_NO_SUCH_USER;
1178 ldap_msgfree(result);
1181 ldap_msgfree(result);
1186 /**********************************************************************
1187 Get SAM_ACCOUNT entry from LDAP by rid
1188 *********************************************************************/
1189 static NTSTATUS ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
1191 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1192 struct smb_ldap_privates *ldap_state =
1193 (struct smb_ldap_privates *)my_methods->private_data;
1194 LDAPMessage *result;
1198 if (ldapsam_search_one_user_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
1199 return NT_STATUS_NO_SUCH_USER;
1202 count = ldap_count_entries(ldap_state->ldap_struct, result);
1206 ("We don't find this rid [%i] count=%d\n", rid,
1208 return NT_STATUS_NO_SUCH_USER;
1209 } else if (count > 1) {
1211 ("More than one user with rid [%i]. Failing. count=%d\n", rid,
1213 return NT_STATUS_NO_SUCH_USER;
1216 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1218 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1219 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1220 ldap_msgfree(result);
1221 return NT_STATUS_NO_SUCH_USER;
1223 ldap_msgfree(result);
1226 ldap_msgfree(result);
1231 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1234 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
1235 return NT_STATUS_NO_SUCH_USER;
1236 return ldapsam_getsampwrid(my_methods, user, rid);
1239 /********************************************************************
1240 Do the actual modification - also change a plaittext passord if
1242 **********************************************************************/
1244 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
1245 SAM_ACCOUNT *newpwd, char *dn,
1246 LDAPMod **mods, int ldap_op, BOOL pdb_add)
1248 struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
1251 if (!my_methods || !newpwd || !dn) {
1252 return NT_STATUS_INVALID_PARAMETER;
1256 DEBUG(5,("mods is empty: nothing to modify\n"));
1257 /* may be password change below however */
1262 smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
1263 rc = smb_ldap_add(ldap_state, dn, mods);
1265 case LDAP_MOD_REPLACE:
1266 rc = smb_ldap_modify(ldap_state, dn ,mods);
1269 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1270 return NT_STATUS_UNSUCCESSFUL;
1273 if (rc!=LDAP_SUCCESS) {
1274 char *ld_error = NULL;
1275 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1278 ("failed to %s user dn= %s with: %s\n\t%s\n",
1279 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1280 dn, ldap_err2string(rc),
1281 ld_error?ld_error:"unknown"));
1282 SAFE_FREE(ld_error);
1283 return NT_STATUS_UNSUCCESSFUL;
1287 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1288 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))&&
1289 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&
1290 need_ldap_mod(pdb_add, newpwd, PDB_PLAINTEXT_PW)&&
1291 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1295 struct berval *retdata;
1297 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1298 DEBUG(0,("ber_alloc_t returns NULL\n"));
1299 return NT_STATUS_UNSUCCESSFUL;
1301 ber_printf (ber, "{");
1302 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
1303 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, pdb_get_plaintext_passwd(newpwd));
1304 ber_printf (ber, "N}");
1306 if ((rc = ber_flatten (ber, &bv))<0) {
1307 DEBUG(0,("ber_flatten returns a value <0\n"));
1308 return NT_STATUS_UNSUCCESSFUL;
1313 if ((rc = smb_ldap_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
1314 bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
1315 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1316 pdb_get_username(newpwd),ldap_err2string(rc)));
1318 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1320 ber_bvfree(retdata);
1321 ber_memfree(retoid);
1326 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
1327 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
1328 return NT_STATUS_OK;
1331 /**********************************************************************
1332 Delete entry from LDAP for username
1333 *********************************************************************/
1334 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1336 struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
1339 LDAPMessage *result;
1341 const char *sam_user_attrs[] =
1342 { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
1343 "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
1344 "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
1345 "userWorkstations", "primaryGroupID", "domain", "rid", NULL };
1348 DEBUG(0, ("sam_acct was NULL!\n"));
1349 return NT_STATUS_INVALID_PARAMETER;
1352 sname = pdb_get_username(sam_acct);
1354 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1356 rc = ldapsam_search_one_user_by_name(ldap_state, sname, &result);
1357 if (rc != LDAP_SUCCESS) {
1358 return NT_STATUS_NO_SUCH_USER;
1361 ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
1363 ldap_msgfree(result);
1367 /**********************************************************************
1368 Helper function to determine for update_sam_account whether
1369 we need LDAP modification.
1370 *********************************************************************/
1371 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
1372 enum pdb_elements element)
1374 return IS_SAM_CHANGED(sampass, element);
1377 /**********************************************************************
1379 *********************************************************************/
1380 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1382 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1383 struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
1386 LDAPMessage *result;
1390 rc = ldapsam_search_one_user_by_name(ldap_state, pdb_get_username(newpwd), &result);
1391 if (rc != LDAP_SUCCESS) {
1392 return NT_STATUS_UNSUCCESSFUL;
1395 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
1396 DEBUG(0, ("No user to modify!\n"));
1397 ldap_msgfree(result);
1398 return NT_STATUS_UNSUCCESSFUL;
1401 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1402 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
1404 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1405 element_is_changed)) {
1406 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1407 ldap_msgfree(result);
1408 return NT_STATUS_UNSUCCESSFUL;
1411 ldap_msgfree(result);
1414 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
1415 pdb_get_username(newpwd)));
1416 ldap_mods_free(mods, 1);
1417 return NT_STATUS_OK;
1420 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, False);
1421 ldap_mods_free(mods,1);
1423 if (!NT_STATUS_IS_OK(ret)) {
1424 char *ld_error = NULL;
1425 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1427 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
1428 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
1429 SAFE_FREE(ld_error);
1433 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
1434 pdb_get_username(newpwd)));
1435 return NT_STATUS_OK;
1438 /**********************************************************************
1439 Helper function to determine for update_sam_account whether
1440 we need LDAP modification.
1441 *********************************************************************/
1442 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
1443 enum pdb_elements element)
1445 return (IS_SAM_SET(sampass, element) ||
1446 IS_SAM_CHANGED(sampass, element));
1449 /**********************************************************************
1450 Add SAM_ACCOUNT to LDAP
1451 *********************************************************************/
1452 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1454 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1455 struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
1458 LDAPMessage *result = NULL;
1459 LDAPMessage *entry = NULL;
1461 LDAPMod **mods = NULL;
1465 const char *username = pdb_get_username(newpwd);
1466 if (!username || !*username) {
1467 DEBUG(0, ("Cannot add user without a username!\n"));
1468 return NT_STATUS_INVALID_PARAMETER;
1471 rc = ldapsam_search_one_user_by_name (ldap_state, username, &result);
1472 if (rc != LDAP_SUCCESS) {
1473 return NT_STATUS_UNSUCCESSFUL;
1476 if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
1477 DEBUG(0,("User '%s' already in the base, with samba properties\n",
1479 ldap_msgfree(result);
1480 return NT_STATUS_UNSUCCESSFUL;
1482 ldap_msgfree(result);
1484 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
1485 rc = ldapsam_search_one_user(ldap_state, filter, &result);
1486 if (rc != LDAP_SUCCESS) {
1487 return NT_STATUS_UNSUCCESSFUL;
1490 num_result = ldap_count_entries(ldap_state->ldap_struct, result);
1492 if (num_result > 1) {
1493 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1494 ldap_msgfree(result);
1495 return NT_STATUS_UNSUCCESSFUL;
1498 /* Check if we need to update an existing entry */
1499 if (num_result == 1) {
1502 DEBUG(3,("User exists without samba properties: adding them\n"));
1503 ldap_op = LDAP_MOD_REPLACE;
1504 entry = ldap_first_entry (ldap_state->ldap_struct, result);
1505 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
1506 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1509 /* Check if we need to add an entry */
1510 DEBUG(3,("Adding new user\n"));
1511 ldap_op = LDAP_MOD_ADD;
1512 if (username[strlen(username)-1] == '$') {
1513 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1515 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1519 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1520 element_is_set_or_changed)) {
1521 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1522 ldap_msgfree(result);
1523 ldap_mods_free(mods, 1);
1524 return NT_STATUS_UNSUCCESSFUL;
1527 ldap_msgfree(result);
1530 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
1531 return NT_STATUS_UNSUCCESSFUL;
1534 smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
1536 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, True);
1537 if (NT_STATUS_IS_ERR(ret)) {
1538 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
1539 pdb_get_username(newpwd),dn));
1540 ldap_mods_free(mods,1);
1544 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
1545 ldap_mods_free(mods, 1);
1546 return NT_STATUS_OK;
1549 static void free_private_data(void **vp)
1551 struct smb_ldap_privates **ldap_state = (struct smb_ldap_privates **)vp;
1553 smb_ldap_close(*ldap_state);
1555 if ((*ldap_state)->bind_secret) {
1556 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1559 smb_ldap_close(*ldap_state);
1561 SAFE_FREE((*ldap_state)->bind_dn);
1562 SAFE_FREE((*ldap_state)->bind_secret);
1566 /* No need to free any further, as it is talloc()ed */
1569 static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
1571 "displayName", "description",
1574 static int ldapsam_search_one_group (struct smb_ldap_privates *ldap_state,
1576 LDAPMessage ** result)
1578 int scope = LDAP_SCOPE_SUBTREE;
1581 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
1583 rc = smb_ldap_search(ldap_state, lp_ldap_suffix (), scope,
1584 filter, group_attr, 0, result);
1586 if (rc != LDAP_SUCCESS) {
1587 char *ld_error = NULL;
1588 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1590 DEBUG(0, ("ldapsam_search_one_group: "
1591 "Problem during the LDAP search: LDAP error: %s (%s)",
1592 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
1593 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
1594 lp_ldap_suffix(), filter));
1595 SAFE_FREE(ld_error);
1601 static BOOL init_group_from_ldap(struct smb_ldap_privates *ldap_state,
1602 GROUP_MAP *map, LDAPMessage *entry)
1606 if (ldap_state == NULL || map == NULL || entry == NULL ||
1607 ldap_state->ldap_struct == NULL) {
1608 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
1612 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
1614 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
1617 DEBUG(2, ("Entry found for group: %s\n", temp));
1619 map->gid = (gid_t)atol(temp);
1621 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
1623 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
1626 string_to_sid(&map->sid, temp);
1628 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
1630 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
1633 map->sid_name_use = (uint32)atol(temp);
1635 if ((map->sid_name_use < SID_NAME_USER) ||
1636 (map->sid_name_use > SID_NAME_UNKNOWN)) {
1637 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
1641 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
1643 DEBUG(3, ("Attribute displayName not found\n"));
1645 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "cn",
1647 DEBUG(0, ("Attributes cn not found either "
1648 "for gidNumber(%i)\n",map->gid));
1652 fstrcpy(map->nt_name, temp);
1654 if (!smb_ldap_get_single_attribute(ldap_state->ldap_struct, entry, "description",
1656 DEBUG(3, ("Attribute description not found\n"));
1659 fstrcpy(map->comment, temp);
1661 map->systemaccount = 0;
1662 init_privilege(&map->priv_set);
1667 static BOOL init_ldap_from_group(LDAP *ldap_struct,
1668 LDAPMessage *existing,
1670 const GROUP_MAP *map)
1674 if (mods == NULL || map == NULL) {
1675 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
1681 sid_to_string(tmp, &map->sid);
1682 make_ldap_mod(ldap_struct, existing, mods, "ntSid", tmp);
1683 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
1684 make_ldap_mod(ldap_struct, existing, mods, "ntGroupType", tmp);
1686 make_ldap_mod(ldap_struct, existing, mods, "displayName", map->nt_name);
1687 make_ldap_mod(ldap_struct, existing, mods, "description", map->comment);
1692 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
1696 struct smb_ldap_privates *ldap_state =
1697 (struct smb_ldap_privates *)methods->private_data;
1698 LDAPMessage *result;
1702 if (ldapsam_search_one_group(ldap_state, filter, &result)
1704 return NT_STATUS_NO_SUCH_GROUP;
1707 count = ldap_count_entries(ldap_state->ldap_struct, result);
1710 DEBUG(4, ("Did not find group for filter %s\n", filter));
1711 return NT_STATUS_NO_SUCH_GROUP;
1715 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
1717 return NT_STATUS_NO_SUCH_GROUP;
1720 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1723 ldap_msgfree(result);
1724 return NT_STATUS_UNSUCCESSFUL;
1727 if (!init_group_from_ldap(ldap_state, map, entry)) {
1728 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
1730 ldap_msgfree(result);
1731 return NT_STATUS_NO_SUCH_GROUP;
1734 ldap_msgfree(result);
1735 return NT_STATUS_OK;
1738 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1739 DOM_SID sid, BOOL with_priv)
1743 snprintf(filter, sizeof(filter)-1,
1744 "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
1745 sid_string_static(&sid));
1747 return ldapsam_getgroup(methods, filter, map);
1750 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1751 gid_t gid, BOOL with_priv)
1755 snprintf(filter, sizeof(filter)-1,
1756 "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
1759 return ldapsam_getgroup(methods, filter, map);
1762 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1763 char *name, BOOL with_priv)
1767 /* TODO: Escaping of name? */
1769 snprintf(filter, sizeof(filter)-1,
1770 "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
1773 return ldapsam_getgroup(methods, filter, map);
1776 static int ldapsam_search_one_group_by_gid(struct smb_ldap_privates *ldap_state,
1778 LDAPMessage **result)
1782 snprintf(filter, sizeof(filter)-1,
1783 "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
1785 return ldapsam_search_one_group(ldap_state, filter, result);
1788 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
1791 struct smb_ldap_privates *ldap_state =
1792 (struct smb_ldap_privates *)methods->private_data;
1793 LDAPMessage *result = NULL;
1794 LDAPMod **mods = NULL;
1804 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
1805 map->gid, False))) {
1806 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
1807 return NT_STATUS_UNSUCCESSFUL;
1810 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
1811 if (rc != LDAP_SUCCESS) {
1812 return NT_STATUS_UNSUCCESSFUL;
1815 if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
1816 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
1818 ldap_msgfree(result);
1819 return NT_STATUS_UNSUCCESSFUL;
1822 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1823 tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
1827 if (!init_ldap_from_group(ldap_state->ldap_struct,
1828 result, &mods, map)) {
1829 DEBUG(0, ("init_ldap_from_group failed!\n"));
1830 ldap_mods_free(mods, 1);
1831 ldap_msgfree(result);
1832 return NT_STATUS_UNSUCCESSFUL;
1835 ldap_msgfree(result);
1838 DEBUG(0, ("mods is empty\n"));
1839 return NT_STATUS_UNSUCCESSFUL;
1842 smb_ldap_make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
1843 "sambaGroupMapping");
1845 rc = smb_ldap_modify(ldap_state, dn, mods);
1846 ldap_mods_free(mods, 1);
1848 if (rc != LDAP_SUCCESS) {
1849 char *ld_error = NULL;
1850 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1852 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
1853 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
1854 SAFE_FREE(ld_error);
1855 return NT_STATUS_UNSUCCESSFUL;
1858 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
1859 return NT_STATUS_OK;
1862 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
1865 struct smb_ldap_privates *ldap_state =
1866 (struct smb_ldap_privates *)methods->private_data;
1869 LDAPMessage *result;
1873 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
1875 if (rc != LDAP_SUCCESS) {
1876 return NT_STATUS_UNSUCCESSFUL;
1879 if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
1880 DEBUG(0, ("No group to modify!\n"));
1881 ldap_msgfree(result);
1882 return NT_STATUS_UNSUCCESSFUL;
1885 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1886 dn = ldap_get_dn(ldap_state->ldap_struct, entry);
1888 if (!init_ldap_from_group(ldap_state->ldap_struct,
1889 result, &mods, map)) {
1890 DEBUG(0, ("init_ldap_from_group failed\n"));
1891 ldap_msgfree(result);
1892 return NT_STATUS_UNSUCCESSFUL;
1895 ldap_msgfree(result);
1898 DEBUG(4, ("mods is empty: nothing to do\n"));
1899 return NT_STATUS_UNSUCCESSFUL;
1902 rc = smb_ldap_modify(ldap_state, dn, mods);
1904 ldap_mods_free(mods, 1);
1906 if (rc != LDAP_SUCCESS) {
1907 char *ld_error = NULL;
1908 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1910 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
1911 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
1912 SAFE_FREE(ld_error);
1915 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
1916 return NT_STATUS_OK;
1919 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
1922 struct smb_ldap_privates *ldap_state =
1923 (struct smb_ldap_privates *)methods->private_data;
1924 pstring sidstring, filter;
1925 LDAPMessage *result;
1929 const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
1930 "description", "displayName",
1932 sid_to_string(sidstring, &sid);
1933 snprintf(filter, sizeof(filter)-1,
1934 "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
1936 rc = ldapsam_search_one_group(ldap_state, filter, &result);
1938 if (rc != LDAP_SUCCESS) {
1939 return NT_STATUS_NO_SUCH_GROUP;
1942 ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
1944 ldap_msgfree(result);
1948 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
1951 struct smb_ldap_privates *ldap_state =
1952 (struct smb_ldap_privates *)my_methods->private_data;
1953 const char *filter = "(objectClass=sambaGroupMapping)";
1956 rc = smb_ldap_search(ldap_state, lp_ldap_suffix(),
1957 LDAP_SCOPE_SUBTREE, filter,
1958 group_attr, 0, &ldap_state->result);
1960 if (rc != LDAP_SUCCESS) {
1961 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1962 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1963 ldap_msgfree(ldap_state->result);
1964 ldap_state->result = NULL;
1965 return NT_STATUS_UNSUCCESSFUL;
1968 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1969 ldap_count_entries(ldap_state->ldap_struct,
1970 ldap_state->result)));
1972 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1973 ldap_state->result);
1974 ldap_state->index = 0;
1976 return NT_STATUS_OK;
1979 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
1981 ldapsam_endsampwent(my_methods);
1984 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
1987 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1988 struct smb_ldap_privates *ldap_state = (struct smb_ldap_privates *)my_methods->private_data;
1992 if (!ldap_state->entry)
1995 ldap_state->index++;
1996 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
1998 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2002 return NT_STATUS_OK;
2005 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2006 enum SID_NAME_USE sid_name_use,
2007 GROUP_MAP **rmap, int *num_entries,
2008 BOOL unix_only, BOOL with_priv)
2018 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2019 DEBUG(0, ("Unable to open passdb\n"));
2020 return NT_STATUS_ACCESS_DENIED;
2023 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
2024 if (sid_name_use != SID_NAME_UNKNOWN &&
2025 sid_name_use != map.sid_name_use) {
2026 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2029 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2030 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
2034 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2036 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
2038 return NT_STATUS_UNSUCCESSFUL;
2043 mapt[entries] = map;
2048 ldapsam_endsamgrent(methods);
2050 *num_entries = entries;
2052 return NT_STATUS_OK;
2055 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2058 struct smb_ldap_privates *ldap_state;
2060 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2064 (*pdb_method)->name = "ldapsam";
2066 (*pdb_method)->setsampwent = ldapsam_setsampwent;
2067 (*pdb_method)->endsampwent = ldapsam_endsampwent;
2068 (*pdb_method)->getsampwent = ldapsam_getsampwent;
2069 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2070 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2071 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2072 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2073 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2075 (*pdb_method)->getgrsid = ldapsam_getgrsid;
2076 (*pdb_method)->getgrgid = ldapsam_getgrgid;
2077 (*pdb_method)->getgrnam = ldapsam_getgrnam;
2078 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2079 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2080 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2081 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2083 /* TODO: Setup private data and free */
2085 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct smb_ldap_privates));
2088 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2089 return NT_STATUS_NO_MEMORY;
2093 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
2094 #ifdef WITH_LDAP_SAMCONFIG
2096 int ldap_port = lp_ldap_port();
2098 /* remap default port if not using SSL (ie clear or TLS) */
2099 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2103 ldap_state->uri = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
2104 if (!ldap_state->uri) {
2105 return NT_STATUS_NO_MEMORY;
2109 ldap_state->uri = "ldap://localhost";
2113 (*pdb_method)->private_data = ldap_state;
2115 (*pdb_method)->free_private_data = free_private_data;
2117 return NT_STATUS_OK;
2120 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2123 struct smb_ldap_privates *ldap_state;
2124 uint32 low_nua_uid, high_nua_uid;
2126 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
2130 (*pdb_method)->name = "ldapsam_nua";
2132 ldap_state = (*pdb_method)->private_data;
2134 ldap_state->permit_non_unix_accounts = True;
2136 if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
2137 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
2138 return NT_STATUS_UNSUCCESSFUL;
2141 ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
2143 ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
2145 return NT_STATUS_OK;
2148 int pdb_ldap_init(void)
2150 smb_register_passdb("ldapsam", pdb_init_ldapsam, PASSDB_INTERFACE_VERSION);
2151 smb_register_passdb("ldapsam_nua", pdb_init_ldapsam_nua, PASSDB_INTERFACE_VERSION);