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 static const char *attr
[] = {"uid", "pwdLastSet", "logonTime",
64 "logoffTime", "kickoffTime", "cn",
65 "pwdCanChange", "pwdMustChange",
66 "displayName", "homeDrive",
67 "smbHome", "scriptPath",
68 "profilePath", "description",
69 "userWorkstations", "rid",
70 "primaryGroupID", "lmPassword",
71 "ntPassword", "acctFlags",
72 "domain", "objectClass",
73 "uidNumber", "gidNumber",
74 "homeDirectory", NULL
};
76 /*******************************************************************
77 run the search by name.
78 ******************************************************************/
79 static int ldapsam_search_one_user (struct smb_ldap_privates
*ldap_state
, const char *filter
, LDAPMessage
** result
)
81 int scope
= LDAP_SCOPE_SUBTREE
;
84 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter
));
86 rc
= smb_ldap_search(ldap_state
, lp_ldap_suffix (), scope
, filter
, attr
, 0, result
);
88 if (rc
!= LDAP_SUCCESS
) {
89 char *ld_error
= NULL
;
90 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
92 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s (%s)\n",
93 ld_error
?ld_error
:"(unknown)", ldap_err2string (rc
)));
94 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
102 /*******************************************************************
103 run the search by name.
104 ******************************************************************/
105 static int ldapsam_search_one_user_by_name (struct smb_ldap_privates
*ldap_state
, const char *user
,
106 LDAPMessage
** result
)
109 char *escape_user
= escape_ldap_string_alloc(user
);
112 return LDAP_NO_MEMORY
;
116 * in the filter expression, replace %u with the real name
117 * so in ldap filter, %u MUST exist :-)
119 pstrcpy(filter
, lp_ldap_filter());
122 * have to use this here because $ is filtered out
127 all_string_sub(filter
, "%u", escape_user
, sizeof(pstring
));
128 SAFE_FREE(escape_user
);
130 return ldapsam_search_one_user(ldap_state
, filter
, result
);
133 /*******************************************************************
134 run the search by uid.
135 ******************************************************************/
136 static int ldapsam_search_one_user_by_uid(struct smb_ldap_privates
*ldap_state
,
138 LDAPMessage
** result
)
144 /* Get the username from the system and look that up in the LDAP */
146 if ((user
= getpwuid_alloc(uid
)) == NULL
) {
147 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid
));
148 return LDAP_NO_SUCH_OBJECT
;
151 pstrcpy(filter
, lp_ldap_filter());
153 escape_user
= escape_ldap_string_alloc(user
->pw_name
);
156 return LDAP_NO_MEMORY
;
159 all_string_sub(filter
, "%u", escape_user
, sizeof(pstring
));
162 SAFE_FREE(escape_user
);
164 return ldapsam_search_one_user(ldap_state
, filter
, result
);
167 /*******************************************************************
168 run the search by rid.
169 ******************************************************************/
170 static int ldapsam_search_one_user_by_rid (struct smb_ldap_privates
*ldap_state
,
172 LDAPMessage
** result
)
177 /* check if the user rid exsists, if not, try searching on the uid */
179 snprintf(filter
, sizeof(filter
) - 1, "rid=%i", rid
);
180 rc
= ldapsam_search_one_user(ldap_state
, filter
, result
);
182 if (rc
!= LDAP_SUCCESS
)
183 rc
= ldapsam_search_one_user_by_uid(ldap_state
,
184 fallback_pdb_user_rid_to_uid(rid
),
190 /*******************************************************************
191 Delete complete object or objectclass and attrs from
192 object found in search_result depending on lp_ldap_delete_dn
193 ******************************************************************/
194 static NTSTATUS
ldapsam_delete_entry(struct smb_ldap_privates
*ldap_state
,
196 const char *objectclass
,
201 LDAPMod
**mods
= NULL
;
203 BerElement
*ptr
= NULL
;
205 rc
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
208 DEBUG(0, ("Entry must exist exactly once!\n"));
209 return NT_STATUS_UNSUCCESSFUL
;
212 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
213 dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
215 if (lp_ldap_delete_dn()) {
216 NTSTATUS ret
= NT_STATUS_OK
;
217 rc
= smb_ldap_delete(ldap_state
, dn
);
219 if (rc
!= LDAP_SUCCESS
) {
220 DEBUG(0, ("Could not delete object %s\n", dn
));
221 ret
= NT_STATUS_UNSUCCESSFUL
;
227 /* Ok, delete only the SAM attributes */
229 for (name
= ldap_first_attribute(ldap_state
->ldap_struct
, entry
, &ptr
);
231 name
= ldap_next_attribute(ldap_state
->ldap_struct
, entry
, ptr
)) {
235 /* We are only allowed to delete the attributes that
238 for (attrib
= attrs
; *attrib
!= NULL
; attrib
++) {
239 if (StrCaseCmp(*attrib
, name
) == 0) {
240 DEBUG(10, ("deleting attribute %s\n", name
));
241 smb_ldap_make_a_mod(&mods
, LDAP_MOD_DELETE
, name
, NULL
);
252 smb_ldap_make_a_mod(&mods
, LDAP_MOD_DELETE
, "objectClass", objectclass
);
254 rc
= smb_ldap_modify(ldap_state
, dn
, mods
);
255 ldap_mods_free(mods
, 1);
257 if (rc
!= LDAP_SUCCESS
) {
258 char *ld_error
= NULL
;
259 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
262 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
263 dn
, ldap_err2string(rc
), ld_error
?ld_error
:"unknown"));
266 return NT_STATUS_UNSUCCESSFUL
;
273 /* New Interface is being implemented here */
275 /**********************************************************************
276 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
277 *********************************************************************/
278 static BOOL
get_unix_attributes (struct smb_ldap_privates
*ldap_state
,
279 SAM_ACCOUNT
* sampass
,
289 if ((ldap_values
= ldap_get_values (ldap_state
->ldap_struct
, entry
, "objectClass")) == NULL
) {
290 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
294 for (values
=ldap_values
;*values
;values
++) {
295 if (strcasecmp(*values
, "posixAccount") == 0) {
300 if (!*values
) { /*end of array, no posixAccount */
301 DEBUG(10, ("user does not have posixAcccount attributes\n"));
302 ldap_value_free(ldap_values
);
305 ldap_value_free(ldap_values
);
307 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "homeDirectory", homedir
))
310 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "uidNumber", temp
))
313 uid
= (uid_t
)atol(temp
);
315 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "gidNumber", temp
))
318 gid
= (gid_t
)atol(temp
);
320 pdb_set_unix_homedir(sampass
, homedir
, PDB_SET
);
321 pdb_set_uid(sampass
, uid
, PDB_SET
);
322 pdb_set_gid(sampass
, gid
, PDB_SET
);
324 DEBUG(10, ("user has posixAcccount attributes\n"));
329 /**********************************************************************
330 Initialize SAM_ACCOUNT from an LDAP query
331 (Based on init_sam_from_buffer in pdb_tdb.c)
332 *********************************************************************/
333 static BOOL
init_sam_from_ldap (struct smb_ldap_privates
*ldap_state
,
334 SAM_ACCOUNT
* sampass
,
341 pass_can_change_time
,
342 pass_must_change_time
;
357 uint8 smblmpwd
[LM_HASH_LEN
],
358 smbntpwd
[NT_HASH_LEN
];
359 uint16 acct_ctrl
= 0,
362 uint8 hours
[MAX_HOURS_LEN
];
365 gid_t gid
= getegid();
369 * do a little initialization
373 nt_username
[0] = '\0';
377 logon_script
[0] = '\0';
378 profile_path
[0] = '\0';
380 munged_dial
[0] = '\0';
381 workstations
[0] = '\0';
384 if (sampass
== NULL
|| ldap_state
== NULL
|| entry
== NULL
) {
385 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
389 if (ldap_state
->ldap_struct
== NULL
) {
390 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
394 smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "uid", username
);
395 DEBUG(2, ("Entry found for user: %s\n", username
));
397 pstrcpy(nt_username
, username
);
399 pstrcpy(domain
, lp_workgroup());
401 pdb_set_username(sampass
, username
, PDB_SET
);
403 pdb_set_domain(sampass
, domain
, PDB_DEFAULT
);
404 pdb_set_nt_username(sampass
, nt_username
, PDB_SET
);
406 smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "rid", temp
);
407 user_rid
= (uint32
)atol(temp
);
409 pdb_set_user_sid_from_rid(sampass
, user_rid
, PDB_SET
);
411 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "primaryGroupID", temp
)) {
414 group_rid
= (uint32
)atol(temp
);
415 pdb_set_group_sid_from_rid(sampass
, group_rid
, PDB_SET
);
420 * If so configured, try and get the values from LDAP
423 if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state
, sampass
, entry
))) {
426 * Otherwise just ask the system getpw() calls.
429 pw
= getpwnam_alloc(username
);
431 if (! ldap_state
->permit_non_unix_accounts
) {
432 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username
));
437 pdb_set_uid(sampass
, uid
, PDB_SET
);
439 pdb_set_gid(sampass
, gid
, PDB_SET
);
441 pdb_set_unix_homedir(sampass
, pw
->pw_dir
, PDB_SET
);
447 if (group_rid
== 0 && pdb_get_init_flags(sampass
,PDB_GID
) != PDB_DEFAULT
) {
449 gid
= pdb_get_gid(sampass
);
450 /* call the mapping code here */
451 if(pdb_getgrgid(&map
, gid
, MAPPING_WITHOUT_PRIV
)) {
452 pdb_set_group_sid(sampass
, &map
.sid
, PDB_SET
);
455 pdb_set_group_sid_from_rid(sampass
, pdb_gid_to_group_rid(gid
), PDB_SET
);
459 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "pwdLastSet", temp
)) {
460 /* leave as default */
462 pass_last_set_time
= (time_t) atol(temp
);
463 pdb_set_pass_last_set_time(sampass
, pass_last_set_time
, PDB_SET
);
466 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "logonTime", temp
)) {
467 /* leave as default */
469 logon_time
= (time_t) atol(temp
);
470 pdb_set_logon_time(sampass
, logon_time
, PDB_SET
);
473 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "logoffTime", temp
)) {
474 /* leave as default */
476 logoff_time
= (time_t) atol(temp
);
477 pdb_set_logoff_time(sampass
, logoff_time
, PDB_SET
);
480 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "kickoffTime", temp
)) {
481 /* leave as default */
483 kickoff_time
= (time_t) atol(temp
);
484 pdb_set_kickoff_time(sampass
, kickoff_time
, PDB_SET
);
487 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "pwdCanChange", temp
)) {
488 /* leave as default */
490 pass_can_change_time
= (time_t) atol(temp
);
491 pdb_set_pass_can_change_time(sampass
, pass_can_change_time
, PDB_SET
);
494 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "pwdMustChange", temp
)) {
495 /* leave as default */
497 pass_must_change_time
= (time_t) atol(temp
);
498 pdb_set_pass_must_change_time(sampass
, pass_must_change_time
, PDB_SET
);
501 /* recommend that 'gecos' and 'displayName' should refer to the same
502 * attribute OID. userFullName depreciated, only used by Samba
503 * primary rules of LDAP: don't make a new attribute when one is already defined
504 * that fits your needs; using cn then displayName rather than 'userFullName'
507 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
,
508 "displayName", fullname
)) {
509 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
,
511 /* leave as default */
513 pdb_set_fullname(sampass
, fullname
, PDB_SET
);
516 pdb_set_fullname(sampass
, fullname
, PDB_SET
);
519 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "homeDrive", dir_drive
)) {
520 pdb_set_dir_drive(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
526 pdb_set_dir_drive(sampass
, dir_drive
, PDB_SET
);
529 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "smbHome", homedir
)) {
530 pdb_set_homedir(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
536 pdb_set_homedir(sampass
, homedir
, PDB_SET
);
539 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "scriptPath", logon_script
)) {
540 pdb_set_logon_script(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
546 pdb_set_logon_script(sampass
, logon_script
, PDB_SET
);
549 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "profilePath", profile_path
)) {
550 pdb_set_profile_path(sampass
, talloc_sub_specified(sampass
->mem_ctx
,
556 pdb_set_profile_path(sampass
, profile_path
, PDB_SET
);
559 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "description", acct_desc
)) {
560 /* leave as default */
562 pdb_set_acct_desc(sampass
, acct_desc
, PDB_SET
);
565 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "userWorkstations", workstations
)) {
566 /* leave as default */;
568 pdb_set_workstations(sampass
, workstations
, PDB_SET
);
571 /* FIXME: hours stuff should be cleaner */
575 memset(hours
, 0xff, hours_len
);
577 if (!smb_ldap_get_single_attribute (ldap_state
->ldap_struct
, entry
, "lmPassword", temp
)) {
578 /* leave as default */
580 pdb_gethexpwd(temp
, smblmpwd
);
581 memset((char *)temp
, '\0', strlen(temp
)+1);
582 if (!pdb_set_lanman_passwd(sampass
, smblmpwd
, PDB_SET
))
584 ZERO_STRUCT(smblmpwd
);
587 if (!smb_ldap_get_single_attribute (ldap_state
->ldap_struct
, entry
, "ntPassword", temp
)) {
588 /* leave as default */
590 pdb_gethexpwd(temp
, smbntpwd
);
591 memset((char *)temp
, '\0', strlen(temp
)+1);
592 if (!pdb_set_nt_passwd(sampass
, smbntpwd
, PDB_SET
))
594 ZERO_STRUCT(smbntpwd
);
597 if (!smb_ldap_get_single_attribute (ldap_state
->ldap_struct
, entry
, "acctFlags", temp
)) {
598 acct_ctrl
|= ACB_NORMAL
;
600 acct_ctrl
= pdb_decode_acct_ctrl(temp
);
603 acct_ctrl
|= ACB_NORMAL
;
605 pdb_set_acct_ctrl(sampass
, acct_ctrl
, PDB_SET
);
608 pdb_set_hours_len(sampass
, hours_len
, PDB_SET
);
609 pdb_set_logon_divs(sampass
, logon_divs
, PDB_SET
);
611 pdb_set_munged_dial(sampass
, munged_dial
, PDB_SET
);
613 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
614 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
615 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
617 pdb_set_hours(sampass
, hours
, PDB_SET
);
622 /**********************************************************************
623 An LDAP modification is needed in two cases:
624 * If we are updating the record AND the attribute is CHANGED.
625 * If we are adding the record AND it is SET or CHANGED (ie not default)
626 *********************************************************************/
627 static BOOL
need_ldap_mod(BOOL pdb_add
, const SAM_ACCOUNT
* sampass
, enum pdb_elements element
) {
629 return (!IS_SAM_DEFAULT(sampass
, element
));
631 return IS_SAM_CHANGED(sampass
, element
);
635 /**********************************************************************
636 Set attribute to newval in LDAP, regardless of what value the
637 attribute had in LDAP before.
638 *********************************************************************/
639 static void make_ldap_mod(LDAP
*ldap_struct
, LDAPMessage
*existing
,
641 const char *attribute
, const char *newval
)
643 char **values
= NULL
;
645 if (existing
!= NULL
) {
646 values
= ldap_get_values(ldap_struct
, existing
, attribute
);
649 if ((values
!= NULL
) && (values
[0] != NULL
) &&
650 strcmp(values
[0], newval
) == 0) {
652 /* Believe it or not, but LDAP will deny a delete and
653 an add at the same time if the values are the
656 ldap_value_free(values
);
660 /* Regardless of the real operation (add or modify)
661 we add the new value here. We rely on deleting
662 the old value, should it exist. */
664 if ((newval
!= NULL
) && (strlen(newval
) > 0)) {
665 smb_ldap_make_a_mod(mods
, LDAP_MOD_ADD
, attribute
, newval
);
668 if (values
== NULL
) {
669 /* There has been no value before, so don't delete it.
670 Here's a possible race: We might end up with
671 duplicate attributes */
675 /* By deleting exactly the value we found in the entry this
676 should be race-free in the sense that the LDAP-Server will
677 deny the complete operation if somebody changed the
678 attribute behind our back. */
680 smb_ldap_make_a_mod(mods
, LDAP_MOD_DELETE
, attribute
, values
[0]);
681 ldap_value_free(values
);
684 /**********************************************************************
685 Initialize SAM_ACCOUNT from an LDAP query
686 (Based on init_buffer_from_sam in pdb_tdb.c)
687 *********************************************************************/
688 static BOOL
init_ldap_from_sam (struct smb_ldap_privates
*ldap_state
,
689 LDAPMessage
*existing
,
690 LDAPMod
*** mods
, const SAM_ACCOUNT
* sampass
,
691 BOOL (*need_update
)(const SAM_ACCOUNT
*,
697 if (mods
== NULL
|| sampass
== NULL
) {
698 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
705 * took out adding "objectclass: sambaAccount"
706 * do this on a per-mod basis
708 if (need_update(sampass
, PDB_USERNAME
))
709 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
710 "uid", pdb_get_username(sampass
));
712 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass
)));
714 rid
= pdb_get_user_rid(sampass
);
717 if (!IS_SAM_DEFAULT(sampass
, PDB_UID
)) {
718 rid
= fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass
));
719 } else if (ldap_state
->permit_non_unix_accounts
) {
720 rid
= ldapsam_get_next_available_nua_rid(ldap_state
);
722 DEBUG(0, ("NO user RID specified on account %s, and "
723 "finding next available NUA RID failed, "
725 pdb_get_username(sampass
)));
726 ldap_mods_free(*mods
, 1);
730 DEBUG(0, ("NO user RID specified on account %s, "
731 "cannot store!\n", pdb_get_username(sampass
)));
732 ldap_mods_free(*mods
, 1);
737 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
739 if (need_update(sampass
, PDB_USERSID
))
740 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
744 rid
= pdb_get_group_rid(sampass
);
747 if (!IS_SAM_DEFAULT(sampass
, PDB_GID
)) {
748 rid
= pdb_gid_to_group_rid(pdb_get_gid(sampass
));
749 } else if (ldap_state
->permit_non_unix_accounts
) {
750 rid
= DOMAIN_GROUP_RID_USERS
;
752 DEBUG(0, ("NO group RID specified on account %s, "
753 "cannot store!\n", pdb_get_username(sampass
)));
754 ldap_mods_free(*mods
, 1);
759 slprintf(temp
, sizeof(temp
) - 1, "%i", rid
);
761 if (need_update(sampass
, PDB_GROUPSID
))
762 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
763 "primaryGroupID", temp
);
765 /* displayName, cn, and gecos should all be the same
766 * most easily accomplished by giving them the same OID
767 * gecos isn't set here b/c it should be handled by the
769 * We change displayName only and fall back to cn if
773 if (need_update(sampass
, PDB_FULLNAME
))
774 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
775 "displayName", pdb_get_fullname(sampass
));
777 if (need_update(sampass
, PDB_ACCTDESC
))
778 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
779 "description", pdb_get_acct_desc(sampass
));
781 if (need_update(sampass
, PDB_WORKSTATIONS
))
782 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
783 "userWorkstations", pdb_get_workstations(sampass
));
785 if (need_update(sampass
, PDB_SMBHOME
))
786 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
787 "smbHome", pdb_get_homedir(sampass
));
789 if (need_update(sampass
, PDB_DRIVE
))
790 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
791 "homeDrive", pdb_get_dir_drive(sampass
));
793 if (need_update(sampass
, PDB_LOGONSCRIPT
))
794 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
795 "scriptPath", pdb_get_logon_script(sampass
));
797 if (need_update(sampass
, PDB_PROFILE
))
798 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
799 "profilePath", pdb_get_profile_path(sampass
));
801 slprintf(temp
, sizeof(temp
) - 1, "%li", pdb_get_logon_time(sampass
));
803 if (need_update(sampass
, PDB_LOGONTIME
))
804 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
807 slprintf(temp
, sizeof(temp
) - 1, "%li", pdb_get_logoff_time(sampass
));
809 if (need_update(sampass
, PDB_LOGOFFTIME
))
810 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
813 slprintf (temp
, sizeof (temp
) - 1, "%li",
814 pdb_get_kickoff_time(sampass
));
816 if (need_update(sampass
, PDB_KICKOFFTIME
))
817 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
818 "kickoffTime", temp
);
820 slprintf (temp
, sizeof (temp
) - 1, "%li",
821 pdb_get_pass_can_change_time(sampass
));
823 if (need_update(sampass
, PDB_CANCHANGETIME
))
824 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
825 "pwdCanChange", temp
);
827 slprintf (temp
, sizeof (temp
) - 1, "%li",
828 pdb_get_pass_must_change_time(sampass
));
830 if (need_update(sampass
, PDB_MUSTCHANGETIME
))
831 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
832 "pwdMustChange", temp
);
834 if ((pdb_get_acct_ctrl(sampass
)&(ACB_WSTRUST
|ACB_SVRTRUST
|ACB_DOMTRUST
))||
835 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY
)) {
837 pdb_sethexpwd (temp
, pdb_get_lanman_passwd(sampass
),
838 pdb_get_acct_ctrl(sampass
));
840 if (need_update(sampass
, PDB_LMPASSWD
))
841 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
844 pdb_sethexpwd (temp
, pdb_get_nt_passwd(sampass
),
845 pdb_get_acct_ctrl(sampass
));
847 if (need_update(sampass
, PDB_NTPASSWD
))
848 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
851 slprintf (temp
, sizeof (temp
) - 1, "%li",
852 pdb_get_pass_last_set_time(sampass
));
854 if (need_update(sampass
, PDB_PASSLASTSET
))
855 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
859 /* FIXME: Hours stuff goes in LDAP */
861 if (need_update(sampass
, PDB_ACCTCTRL
))
862 make_ldap_mod(ldap_state
->ldap_struct
, existing
, mods
,
864 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass
),
865 NEW_PW_FORMAT_SPACE_PADDED_LEN
));
871 /**********************************************************************
872 Connect to LDAP server and find the next available RID.
873 *********************************************************************/
874 static uint32
check_nua_rid_is_avail(struct smb_ldap_privates
*ldap_state
, uint32 top_rid
)
877 uint32 final_rid
= (top_rid
& (~USER_RID_TYPE
)) + RID_MULTIPLIER
;
882 if (final_rid
< ldap_state
->low_nua_rid
|| final_rid
> ldap_state
->high_nua_rid
) {
886 if (ldapsam_search_one_user_by_rid(ldap_state
, final_rid
, &result
) != LDAP_SUCCESS
) {
887 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid
, final_rid
));
891 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) != 0) {
892 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid
, final_rid
));
893 ldap_msgfree(result
);
897 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid
, final_rid
));
898 ldap_msgfree(result
);
902 /**********************************************************************
903 Extract the RID from an LDAP entry
904 *********************************************************************/
905 static uint32
entry_to_user_rid(struct smb_ldap_privates
*ldap_state
, LDAPMessage
*entry
) {
907 SAM_ACCOUNT
*user
= NULL
;
908 if (!NT_STATUS_IS_OK(pdb_init_sam(&user
))) {
912 if (init_sam_from_ldap(ldap_state
, user
, entry
)) {
913 rid
= pdb_get_user_rid(user
);
918 if (rid
>= ldap_state
->low_nua_rid
&& rid
<= ldap_state
->high_nua_rid
) {
925 /**********************************************************************
926 Connect to LDAP server and find the next available RID.
927 *********************************************************************/
928 static uint32
search_top_nua_rid(struct smb_ldap_privates
*ldap_state
)
934 char *final_filter
= NULL
;
939 pstrcpy(filter
, lp_ldap_filter());
940 all_string_sub(filter
, "%u", "*", sizeof(pstring
));
943 asprintf(&final_filter
, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter
, ldap_state
->low_nua_rid
, ldap_state
->high_nua_rid
);
945 final_filter
= strdup(filter
);
947 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter
));
949 rc
= smb_ldap_search(ldap_state
, lp_ldap_suffix(),
950 LDAP_SCOPE_SUBTREE
, final_filter
, attr
, 0,
953 if (rc
!= LDAP_SUCCESS
) {
954 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc
)));
955 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter
));
962 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
963 DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count
));
966 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc
)));
967 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter
));
969 ldap_msgfree(result
);
971 return ldap_state
->low_nua_rid
;
975 entry
= ldap_first_entry(ldap_state
->ldap_struct
,result
);
977 top_rid
= entry_to_user_rid(ldap_state
, entry
);
979 while ((entry
= ldap_next_entry(ldap_state
->ldap_struct
, entry
))) {
981 rid
= entry_to_user_rid(ldap_state
, entry
);
987 ldap_msgfree(result
);
989 if (top_rid
< ldap_state
->low_nua_rid
)
990 top_rid
= ldap_state
->low_nua_rid
;
995 /**********************************************************************
996 Connect to LDAP server and find the next available RID.
997 *********************************************************************/
998 static uint32
ldapsam_get_next_available_nua_rid(struct smb_ldap_privates
*ldap_state
) {
1002 top_nua_rid
= search_top_nua_rid(ldap_state
);
1004 next_nua_rid
= check_nua_rid_is_avail(ldap_state
,
1007 return next_nua_rid
;
1010 /**********************************************************************
1011 Connect to LDAP server for password enumeration
1012 *********************************************************************/
1013 static NTSTATUS
ldapsam_setsampwent(struct pdb_methods
*my_methods
, BOOL update
)
1015 struct smb_ldap_privates
*ldap_state
= (struct smb_ldap_privates
*)my_methods
->private_data
;
1019 pstrcpy(filter
, lp_ldap_filter());
1020 all_string_sub(filter
, "%u", "*", sizeof(pstring
));
1022 rc
= smb_ldap_search(ldap_state
, lp_ldap_suffix(),
1023 LDAP_SCOPE_SUBTREE
, filter
, attr
, 0,
1024 &ldap_state
->result
);
1026 if (rc
!= LDAP_SUCCESS
) {
1027 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc
)));
1028 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
1029 ldap_msgfree(ldap_state
->result
);
1030 ldap_state
->result
= NULL
;
1031 return NT_STATUS_UNSUCCESSFUL
;
1034 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1035 ldap_count_entries(ldap_state
->ldap_struct
,
1036 ldap_state
->result
)));
1038 ldap_state
->entry
= ldap_first_entry(ldap_state
->ldap_struct
,
1039 ldap_state
->result
);
1040 ldap_state
->index
= 0;
1042 return NT_STATUS_OK
;
1045 /**********************************************************************
1046 End enumeration of the LDAP password list
1047 *********************************************************************/
1048 static void ldapsam_endsampwent(struct pdb_methods
*my_methods
)
1050 struct smb_ldap_privates
*ldap_state
= (struct smb_ldap_privates
*)my_methods
->private_data
;
1051 if (ldap_state
->result
) {
1052 ldap_msgfree(ldap_state
->result
);
1053 ldap_state
->result
= NULL
;
1057 /**********************************************************************
1058 Get the next entry in the LDAP password database
1059 *********************************************************************/
1060 static NTSTATUS
ldapsam_getsampwent(struct pdb_methods
*my_methods
, SAM_ACCOUNT
*user
)
1062 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1063 struct smb_ldap_privates
*ldap_state
= (struct smb_ldap_privates
*)my_methods
->private_data
;
1067 if (!ldap_state
->entry
)
1070 ldap_state
->index
++;
1071 bret
= init_sam_from_ldap(ldap_state
, user
, ldap_state
->entry
);
1073 ldap_state
->entry
= ldap_next_entry(ldap_state
->ldap_struct
,
1077 return NT_STATUS_OK
;
1080 /**********************************************************************
1081 Get SAM_ACCOUNT entry from LDAP by username
1082 *********************************************************************/
1083 static NTSTATUS
ldapsam_getsampwnam(struct pdb_methods
*my_methods
, SAM_ACCOUNT
*user
, const char *sname
)
1085 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1086 struct smb_ldap_privates
*ldap_state
= (struct smb_ldap_privates
*)my_methods
->private_data
;
1087 LDAPMessage
*result
;
1091 if (ldapsam_search_one_user_by_name(ldap_state
, sname
, &result
) != LDAP_SUCCESS
) {
1092 return NT_STATUS_NO_SUCH_USER
;
1095 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1099 ("We don't find this user [%s] count=%d\n", sname
,
1101 return NT_STATUS_NO_SUCH_USER
;
1102 } else if (count
> 1) {
1104 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname
,
1106 return NT_STATUS_NO_SUCH_USER
;
1109 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1111 if (!init_sam_from_ldap(ldap_state
, user
, entry
)) {
1112 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname
));
1113 ldap_msgfree(result
);
1114 return NT_STATUS_NO_SUCH_USER
;
1116 ldap_msgfree(result
);
1119 ldap_msgfree(result
);
1124 /**********************************************************************
1125 Get SAM_ACCOUNT entry from LDAP by rid
1126 *********************************************************************/
1127 static NTSTATUS
ldapsam_getsampwrid(struct pdb_methods
*my_methods
, SAM_ACCOUNT
*user
, uint32 rid
)
1129 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1130 struct smb_ldap_privates
*ldap_state
=
1131 (struct smb_ldap_privates
*)my_methods
->private_data
;
1132 LDAPMessage
*result
;
1136 if (ldapsam_search_one_user_by_rid(ldap_state
, rid
, &result
) != LDAP_SUCCESS
) {
1137 return NT_STATUS_NO_SUCH_USER
;
1140 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1144 ("We don't find this rid [%i] count=%d\n", rid
,
1146 return NT_STATUS_NO_SUCH_USER
;
1147 } else if (count
> 1) {
1149 ("More than one user with rid [%i]. Failing. count=%d\n", rid
,
1151 return NT_STATUS_NO_SUCH_USER
;
1154 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1156 if (!init_sam_from_ldap(ldap_state
, user
, entry
)) {
1157 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1158 ldap_msgfree(result
);
1159 return NT_STATUS_NO_SUCH_USER
;
1161 ldap_msgfree(result
);
1164 ldap_msgfree(result
);
1169 static NTSTATUS
ldapsam_getsampwsid(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* user
, const DOM_SID
*sid
)
1172 if (!sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
))
1173 return NT_STATUS_NO_SUCH_USER
;
1174 return ldapsam_getsampwrid(my_methods
, user
, rid
);
1177 /********************************************************************
1178 Do the actual modification - also change a plaittext passord if
1180 **********************************************************************/
1182 static NTSTATUS
ldapsam_modify_entry(struct pdb_methods
*my_methods
,
1183 SAM_ACCOUNT
*newpwd
, char *dn
,
1184 LDAPMod
**mods
, int ldap_op
, BOOL pdb_add
)
1186 struct smb_ldap_privates
*ldap_state
= (struct smb_ldap_privates
*)my_methods
->private_data
;
1189 if (!my_methods
|| !newpwd
|| !dn
) {
1190 return NT_STATUS_INVALID_PARAMETER
;
1194 DEBUG(5,("mods is empty: nothing to modify\n"));
1195 /* may be password change below however */
1200 smb_ldap_make_a_mod(&mods
, LDAP_MOD_ADD
, "objectclass", "account");
1201 rc
= smb_ldap_add(ldap_state
, dn
, mods
);
1203 case LDAP_MOD_REPLACE
:
1204 rc
= smb_ldap_modify(ldap_state
, dn
,mods
);
1207 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op
));
1208 return NT_STATUS_UNSUCCESSFUL
;
1211 if (rc
!=LDAP_SUCCESS
) {
1212 char *ld_error
= NULL
;
1213 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
1216 ("failed to %s user dn= %s with: %s\n\t%s\n",
1217 ldap_op
== LDAP_MOD_ADD
? "add" : "modify",
1218 dn
, ldap_err2string(rc
),
1219 ld_error
?ld_error
:"unknown"));
1220 SAFE_FREE(ld_error
);
1221 return NT_STATUS_UNSUCCESSFUL
;
1225 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1226 if (!(pdb_get_acct_ctrl(newpwd
)&(ACB_WSTRUST
|ACB_SVRTRUST
|ACB_DOMTRUST
))&&
1227 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF
)&&
1228 need_ldap_mod(pdb_add
, newpwd
, PDB_PLAINTEXT_PW
)&&
1229 (pdb_get_plaintext_passwd(newpwd
)!=NULL
)) {
1233 struct berval
*retdata
;
1235 if ((ber
= ber_alloc_t(LBER_USE_DER
))==NULL
) {
1236 DEBUG(0,("ber_alloc_t returns NULL\n"));
1237 return NT_STATUS_UNSUCCESSFUL
;
1239 ber_printf (ber
, "{");
1240 ber_printf (ber
, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID
,dn
);
1241 ber_printf (ber
, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW
, pdb_get_plaintext_passwd(newpwd
));
1242 ber_printf (ber
, "N}");
1244 if ((rc
= ber_flatten (ber
, &bv
))<0) {
1245 DEBUG(0,("ber_flatten returns a value <0\n"));
1246 return NT_STATUS_UNSUCCESSFUL
;
1251 if ((rc
= smb_ldap_extended_operation(ldap_state
, LDAP_EXOP_X_MODIFY_PASSWD
,
1252 bv
, NULL
, NULL
, &retoid
, &retdata
))!=LDAP_SUCCESS
) {
1253 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1254 pdb_get_username(newpwd
),ldap_err2string(rc
)));
1256 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd
)));
1258 ber_bvfree(retdata
);
1259 ber_memfree(retoid
);
1264 DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
1265 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
1266 return NT_STATUS_OK
;
1269 /**********************************************************************
1270 Delete entry from LDAP for username
1271 *********************************************************************/
1272 static NTSTATUS
ldapsam_delete_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* sam_acct
)
1274 struct smb_ldap_privates
*ldap_state
= (struct smb_ldap_privates
*)my_methods
->private_data
;
1277 LDAPMessage
*result
;
1279 const char *sam_user_attrs
[] =
1280 { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
1281 "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
1282 "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
1283 "userWorkstations", "primaryGroupID", "domain", "rid", NULL
};
1286 DEBUG(0, ("sam_acct was NULL!\n"));
1287 return NT_STATUS_INVALID_PARAMETER
;
1290 sname
= pdb_get_username(sam_acct
);
1292 DEBUG (3, ("Deleting user %s from LDAP.\n", sname
));
1294 rc
= ldapsam_search_one_user_by_name(ldap_state
, sname
, &result
);
1295 if (rc
!= LDAP_SUCCESS
) {
1296 return NT_STATUS_NO_SUCH_USER
;
1299 ret
= ldapsam_delete_entry(ldap_state
, result
, "sambaAccount",
1301 ldap_msgfree(result
);
1305 /**********************************************************************
1306 Helper function to determine for update_sam_account whether
1307 we need LDAP modification.
1308 *********************************************************************/
1309 static BOOL
element_is_changed(const SAM_ACCOUNT
*sampass
,
1310 enum pdb_elements element
)
1312 return IS_SAM_CHANGED(sampass
, element
);
1315 /**********************************************************************
1317 *********************************************************************/
1318 static NTSTATUS
ldapsam_update_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* newpwd
)
1320 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1321 struct smb_ldap_privates
*ldap_state
= (struct smb_ldap_privates
*)my_methods
->private_data
;
1324 LDAPMessage
*result
;
1328 rc
= ldapsam_search_one_user_by_name(ldap_state
, pdb_get_username(newpwd
), &result
);
1329 if (rc
!= LDAP_SUCCESS
) {
1330 return NT_STATUS_UNSUCCESSFUL
;
1333 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) == 0) {
1334 DEBUG(0, ("No user to modify!\n"));
1335 ldap_msgfree(result
);
1336 return NT_STATUS_UNSUCCESSFUL
;
1339 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1340 dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
1342 if (!init_ldap_from_sam(ldap_state
, entry
, &mods
, newpwd
,
1343 element_is_changed
)) {
1344 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1345 ldap_msgfree(result
);
1346 return NT_STATUS_UNSUCCESSFUL
;
1349 ldap_msgfree(result
);
1352 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
1353 pdb_get_username(newpwd
)));
1354 ldap_mods_free(mods
, 1);
1355 return NT_STATUS_OK
;
1358 ret
= ldapsam_modify_entry(my_methods
,newpwd
,dn
,mods
,LDAP_MOD_REPLACE
, False
);
1359 ldap_mods_free(mods
,1);
1361 if (!NT_STATUS_IS_OK(ret
)) {
1362 char *ld_error
= NULL
;
1363 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
1365 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
1366 pdb_get_username(newpwd
), ld_error
?ld_error
:"(unknwon)", ldap_err2string(rc
)));
1367 SAFE_FREE(ld_error
);
1371 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
1372 pdb_get_username(newpwd
)));
1373 return NT_STATUS_OK
;
1376 /**********************************************************************
1377 Helper function to determine for update_sam_account whether
1378 we need LDAP modification.
1379 *********************************************************************/
1380 static BOOL
element_is_set_or_changed(const SAM_ACCOUNT
*sampass
,
1381 enum pdb_elements element
)
1383 return (IS_SAM_SET(sampass
, element
) ||
1384 IS_SAM_CHANGED(sampass
, element
));
1387 /**********************************************************************
1388 Add SAM_ACCOUNT to LDAP
1389 *********************************************************************/
1390 static NTSTATUS
ldapsam_add_sam_account(struct pdb_methods
*my_methods
, SAM_ACCOUNT
* newpwd
)
1392 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1393 struct smb_ldap_privates
*ldap_state
= (struct smb_ldap_privates
*)my_methods
->private_data
;
1396 LDAPMessage
*result
= NULL
;
1397 LDAPMessage
*entry
= NULL
;
1399 LDAPMod
**mods
= NULL
;
1403 const char *username
= pdb_get_username(newpwd
);
1404 if (!username
|| !*username
) {
1405 DEBUG(0, ("Cannot add user without a username!\n"));
1406 return NT_STATUS_INVALID_PARAMETER
;
1409 rc
= ldapsam_search_one_user_by_name (ldap_state
, username
, &result
);
1410 if (rc
!= LDAP_SUCCESS
) {
1411 return NT_STATUS_UNSUCCESSFUL
;
1414 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) != 0) {
1415 DEBUG(0,("User '%s' already in the base, with samba properties\n",
1417 ldap_msgfree(result
);
1418 return NT_STATUS_UNSUCCESSFUL
;
1420 ldap_msgfree(result
);
1422 slprintf (filter
, sizeof (filter
) - 1, "uid=%s", username
);
1423 rc
= ldapsam_search_one_user(ldap_state
, filter
, &result
);
1424 if (rc
!= LDAP_SUCCESS
) {
1425 return NT_STATUS_UNSUCCESSFUL
;
1428 num_result
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1430 if (num_result
> 1) {
1431 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1432 ldap_msgfree(result
);
1433 return NT_STATUS_UNSUCCESSFUL
;
1436 /* Check if we need to update an existing entry */
1437 if (num_result
== 1) {
1440 DEBUG(3,("User exists without samba properties: adding them\n"));
1441 ldap_op
= LDAP_MOD_REPLACE
;
1442 entry
= ldap_first_entry (ldap_state
->ldap_struct
, result
);
1443 tmp
= ldap_get_dn (ldap_state
->ldap_struct
, entry
);
1444 slprintf (dn
, sizeof (dn
) - 1, "%s", tmp
);
1447 /* Check if we need to add an entry */
1448 DEBUG(3,("Adding new user\n"));
1449 ldap_op
= LDAP_MOD_ADD
;
1450 if (username
[strlen(username
)-1] == '$') {
1451 slprintf (dn
, sizeof (dn
) - 1, "uid=%s,%s", username
, lp_ldap_machine_suffix ());
1453 slprintf (dn
, sizeof (dn
) - 1, "uid=%s,%s", username
, lp_ldap_user_suffix ());
1457 if (!init_ldap_from_sam(ldap_state
, entry
, &mods
, newpwd
,
1458 element_is_set_or_changed
)) {
1459 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1460 ldap_msgfree(result
);
1461 return NT_STATUS_UNSUCCESSFUL
;
1464 ldap_msgfree(result
);
1467 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd
)));
1468 return NT_STATUS_UNSUCCESSFUL
;
1471 smb_ldap_make_a_mod(&mods
, LDAP_MOD_ADD
, "objectclass", "sambaAccount");
1473 ret
= ldapsam_modify_entry(my_methods
,newpwd
,dn
,mods
,ldap_op
, True
);
1474 if (NT_STATUS_IS_ERR(ret
)) {
1475 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
1476 pdb_get_username(newpwd
),dn
));
1477 ldap_mods_free(mods
,1);
1481 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd
)));
1482 ldap_mods_free(mods
, 1);
1483 return NT_STATUS_OK
;
1486 static void free_private_data(void **vp
)
1488 struct smb_ldap_privates
**ldap_state
= (struct smb_ldap_privates
**)vp
;
1490 smb_ldap_close(*ldap_state
);
1492 if ((*ldap_state
)->bind_secret
) {
1493 memset((*ldap_state
)->bind_secret
, '\0', strlen((*ldap_state
)->bind_secret
));
1496 smb_ldap_close(*ldap_state
);
1498 SAFE_FREE((*ldap_state
)->bind_dn
);
1499 SAFE_FREE((*ldap_state
)->bind_secret
);
1503 /* No need to free any further, as it is talloc()ed */
1506 static const char *group_attr
[] = {"cn", "ntSid", "ntGroupType",
1508 "displayName", "description",
1511 static int ldapsam_search_one_group (struct smb_ldap_privates
*ldap_state
,
1513 LDAPMessage
** result
)
1515 int scope
= LDAP_SCOPE_SUBTREE
;
1518 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter
));
1520 rc
= smb_ldap_search(ldap_state
, lp_ldap_suffix (), scope
,
1521 filter
, group_attr
, 0, result
);
1523 if (rc
!= LDAP_SUCCESS
) {
1524 char *ld_error
= NULL
;
1525 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
1527 DEBUG(0, ("ldapsam_search_one_group: "
1528 "Problem during the LDAP search: LDAP error: %s (%s)",
1529 ld_error
?ld_error
:"(unknown)", ldap_err2string(rc
)));
1530 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
1531 lp_ldap_suffix(), filter
));
1532 SAFE_FREE(ld_error
);
1538 static BOOL
init_group_from_ldap(struct smb_ldap_privates
*ldap_state
,
1539 GROUP_MAP
*map
, LDAPMessage
*entry
)
1543 if (ldap_state
== NULL
|| map
== NULL
|| entry
== NULL
||
1544 ldap_state
->ldap_struct
== NULL
) {
1545 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
1549 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "gidNumber",
1551 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
1554 DEBUG(2, ("Entry found for group: %s\n", temp
));
1556 map
->gid
= (gid_t
)atol(temp
);
1558 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "ntSid",
1560 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
1563 string_to_sid(&map
->sid
, temp
);
1565 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "ntGroupType",
1567 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
1570 map
->sid_name_use
= (uint32
)atol(temp
);
1572 if ((map
->sid_name_use
< SID_NAME_USER
) ||
1573 (map
->sid_name_use
> SID_NAME_UNKNOWN
)) {
1574 DEBUG(0, ("Unknown Group type: %d\n", map
->sid_name_use
));
1578 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "displayName",
1580 DEBUG(3, ("Attribute displayName not found\n"));
1582 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "cn",
1584 DEBUG(0, ("Attributes cn not found either "
1585 "for gidNumber(%i)\n",map
->gid
));
1589 fstrcpy(map
->nt_name
, temp
);
1591 if (!smb_ldap_get_single_attribute(ldap_state
->ldap_struct
, entry
, "description",
1593 DEBUG(3, ("Attribute description not found\n"));
1596 fstrcpy(map
->comment
, temp
);
1598 map
->systemaccount
= 0;
1599 init_privilege(&map
->priv_set
);
1604 static BOOL
init_ldap_from_group(LDAP
*ldap_struct
,
1605 LDAPMessage
*existing
,
1607 const GROUP_MAP
*map
)
1611 if (mods
== NULL
|| map
== NULL
) {
1612 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
1618 sid_to_string(tmp
, &map
->sid
);
1619 make_ldap_mod(ldap_struct
, existing
, mods
, "ntSid", tmp
);
1620 snprintf(tmp
, sizeof(tmp
)-1, "%i", map
->sid_name_use
);
1621 make_ldap_mod(ldap_struct
, existing
, mods
, "ntGroupType", tmp
);
1623 make_ldap_mod(ldap_struct
, existing
, mods
, "displayName", map
->nt_name
);
1624 make_ldap_mod(ldap_struct
, existing
, mods
, "description", map
->comment
);
1629 static NTSTATUS
ldapsam_getgroup(struct pdb_methods
*methods
,
1633 struct smb_ldap_privates
*ldap_state
=
1634 (struct smb_ldap_privates
*)methods
->private_data
;
1635 LDAPMessage
*result
;
1639 if (ldapsam_search_one_group(ldap_state
, filter
, &result
)
1641 return NT_STATUS_NO_SUCH_GROUP
;
1644 count
= ldap_count_entries(ldap_state
->ldap_struct
, result
);
1647 DEBUG(4, ("Did not find group for filter %s\n", filter
));
1648 return NT_STATUS_NO_SUCH_GROUP
;
1652 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
1654 return NT_STATUS_NO_SUCH_GROUP
;
1657 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1660 ldap_msgfree(result
);
1661 return NT_STATUS_UNSUCCESSFUL
;
1664 if (!init_group_from_ldap(ldap_state
, map
, entry
)) {
1665 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
1667 ldap_msgfree(result
);
1668 return NT_STATUS_NO_SUCH_GROUP
;
1671 ldap_msgfree(result
);
1672 return NT_STATUS_OK
;
1675 static NTSTATUS
ldapsam_getgrsid(struct pdb_methods
*methods
, GROUP_MAP
*map
,
1676 DOM_SID sid
, BOOL with_priv
)
1680 snprintf(filter
, sizeof(filter
)-1,
1681 "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
1682 sid_string_static(&sid
));
1684 return ldapsam_getgroup(methods
, filter
, map
);
1687 static NTSTATUS
ldapsam_getgrgid(struct pdb_methods
*methods
, GROUP_MAP
*map
,
1688 gid_t gid
, BOOL with_priv
)
1692 snprintf(filter
, sizeof(filter
)-1,
1693 "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
1696 return ldapsam_getgroup(methods
, filter
, map
);
1699 static NTSTATUS
ldapsam_getgrnam(struct pdb_methods
*methods
, GROUP_MAP
*map
,
1700 char *name
, BOOL with_priv
)
1704 /* TODO: Escaping of name? */
1706 snprintf(filter
, sizeof(filter
)-1,
1707 "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
1710 return ldapsam_getgroup(methods
, filter
, map
);
1713 static int ldapsam_search_one_group_by_gid(struct smb_ldap_privates
*ldap_state
,
1715 LDAPMessage
**result
)
1719 snprintf(filter
, sizeof(filter
)-1,
1720 "(&(objectClass=posixGroup)(gidNumber=%i))", gid
);
1722 return ldapsam_search_one_group(ldap_state
, filter
, result
);
1725 static NTSTATUS
ldapsam_add_group_mapping_entry(struct pdb_methods
*methods
,
1728 struct smb_ldap_privates
*ldap_state
=
1729 (struct smb_ldap_privates
*)methods
->private_data
;
1730 LDAPMessage
*result
= NULL
;
1731 LDAPMod
**mods
= NULL
;
1741 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods
, &dummy
,
1742 map
->gid
, False
))) {
1743 DEBUG(0, ("Group %i already exists in LDAP\n", map
->gid
));
1744 return NT_STATUS_UNSUCCESSFUL
;
1747 rc
= ldapsam_search_one_group_by_gid(ldap_state
, map
->gid
, &result
);
1748 if (rc
!= LDAP_SUCCESS
) {
1749 return NT_STATUS_UNSUCCESSFUL
;
1752 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) != 1) {
1753 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
1755 ldap_msgfree(result
);
1756 return NT_STATUS_UNSUCCESSFUL
;
1759 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1760 tmp
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
1764 if (!init_ldap_from_group(ldap_state
->ldap_struct
,
1765 result
, &mods
, map
)) {
1766 DEBUG(0, ("init_ldap_from_group failed!\n"));
1767 ldap_mods_free(mods
, 1);
1768 ldap_msgfree(result
);
1769 return NT_STATUS_UNSUCCESSFUL
;
1772 ldap_msgfree(result
);
1775 DEBUG(0, ("mods is empty\n"));
1776 return NT_STATUS_UNSUCCESSFUL
;
1779 smb_ldap_make_a_mod(&mods
, LDAP_MOD_ADD
, "objectClass",
1780 "sambaGroupMapping");
1782 rc
= smb_ldap_modify(ldap_state
, dn
, mods
);
1783 ldap_mods_free(mods
, 1);
1785 if (rc
!= LDAP_SUCCESS
) {
1786 char *ld_error
= NULL
;
1787 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
1789 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map
->gid
,
1790 ld_error
? ld_error
: "(unknown)", ldap_err2string(rc
)));
1791 SAFE_FREE(ld_error
);
1792 return NT_STATUS_UNSUCCESSFUL
;
1795 DEBUG(2, ("successfully modified group %i in LDAP\n", map
->gid
));
1796 return NT_STATUS_OK
;
1799 static NTSTATUS
ldapsam_update_group_mapping_entry(struct pdb_methods
*methods
,
1802 struct smb_ldap_privates
*ldap_state
=
1803 (struct smb_ldap_privates
*)methods
->private_data
;
1806 LDAPMessage
*result
;
1810 rc
= ldapsam_search_one_group_by_gid(ldap_state
, map
->gid
, &result
);
1812 if (rc
!= LDAP_SUCCESS
) {
1813 return NT_STATUS_UNSUCCESSFUL
;
1816 if (ldap_count_entries(ldap_state
->ldap_struct
, result
) == 0) {
1817 DEBUG(0, ("No group to modify!\n"));
1818 ldap_msgfree(result
);
1819 return NT_STATUS_UNSUCCESSFUL
;
1822 entry
= ldap_first_entry(ldap_state
->ldap_struct
, result
);
1823 dn
= ldap_get_dn(ldap_state
->ldap_struct
, entry
);
1825 if (!init_ldap_from_group(ldap_state
->ldap_struct
,
1826 result
, &mods
, map
)) {
1827 DEBUG(0, ("init_ldap_from_group failed\n"));
1828 ldap_msgfree(result
);
1829 return NT_STATUS_UNSUCCESSFUL
;
1832 ldap_msgfree(result
);
1835 DEBUG(4, ("mods is empty: nothing to do\n"));
1836 return NT_STATUS_UNSUCCESSFUL
;
1839 rc
= smb_ldap_modify(ldap_state
, dn
, mods
);
1841 ldap_mods_free(mods
, 1);
1843 if (rc
!= LDAP_SUCCESS
) {
1844 char *ld_error
= NULL
;
1845 ldap_get_option(ldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
1847 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map
->gid
,
1848 ld_error
? ld_error
: "(unknown)", ldap_err2string(rc
)));
1849 SAFE_FREE(ld_error
);
1852 DEBUG(2, ("successfully modified group %i in LDAP\n", map
->gid
));
1853 return NT_STATUS_OK
;
1856 static NTSTATUS
ldapsam_delete_group_mapping_entry(struct pdb_methods
*methods
,
1859 struct smb_ldap_privates
*ldap_state
=
1860 (struct smb_ldap_privates
*)methods
->private_data
;
1861 pstring sidstring
, filter
;
1862 LDAPMessage
*result
;
1866 const char *sam_group_attrs
[] = { "ntSid", "ntGroupType",
1867 "description", "displayName",
1869 sid_to_string(sidstring
, &sid
);
1870 snprintf(filter
, sizeof(filter
)-1,
1871 "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring
);
1873 rc
= ldapsam_search_one_group(ldap_state
, filter
, &result
);
1875 if (rc
!= LDAP_SUCCESS
) {
1876 return NT_STATUS_NO_SUCH_GROUP
;
1879 ret
= ldapsam_delete_entry(ldap_state
, result
, "sambaGroupMapping",
1881 ldap_msgfree(result
);
1885 static NTSTATUS
ldapsam_setsamgrent(struct pdb_methods
*my_methods
,
1888 struct smb_ldap_privates
*ldap_state
=
1889 (struct smb_ldap_privates
*)my_methods
->private_data
;
1890 const char *filter
= "(objectClass=sambaGroupMapping)";
1893 rc
= smb_ldap_search(ldap_state
, lp_ldap_suffix(),
1894 LDAP_SCOPE_SUBTREE
, filter
,
1895 group_attr
, 0, &ldap_state
->result
);
1897 if (rc
!= LDAP_SUCCESS
) {
1898 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc
)));
1899 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter
));
1900 ldap_msgfree(ldap_state
->result
);
1901 ldap_state
->result
= NULL
;
1902 return NT_STATUS_UNSUCCESSFUL
;
1905 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1906 ldap_count_entries(ldap_state
->ldap_struct
,
1907 ldap_state
->result
)));
1909 ldap_state
->entry
= ldap_first_entry(ldap_state
->ldap_struct
,
1910 ldap_state
->result
);
1911 ldap_state
->index
= 0;
1913 return NT_STATUS_OK
;
1916 static void ldapsam_endsamgrent(struct pdb_methods
*my_methods
)
1918 ldapsam_endsampwent(my_methods
);
1921 static NTSTATUS
ldapsam_getsamgrent(struct pdb_methods
*my_methods
,
1924 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
1925 struct smb_ldap_privates
*ldap_state
= (struct smb_ldap_privates
*)my_methods
->private_data
;
1929 if (!ldap_state
->entry
)
1932 ldap_state
->index
++;
1933 bret
= init_group_from_ldap(ldap_state
, map
, ldap_state
->entry
);
1935 ldap_state
->entry
= ldap_next_entry(ldap_state
->ldap_struct
,
1939 return NT_STATUS_OK
;
1942 static NTSTATUS
ldapsam_enum_group_mapping(struct pdb_methods
*methods
,
1943 enum SID_NAME_USE sid_name_use
,
1944 GROUP_MAP
**rmap
, int *num_entries
,
1945 BOOL unix_only
, BOOL with_priv
)
1955 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods
, False
))) {
1956 DEBUG(0, ("Unable to open passdb\n"));
1957 return NT_STATUS_ACCESS_DENIED
;
1960 while (NT_STATUS_IS_OK(nt_status
= ldapsam_getsamgrent(methods
, &map
))) {
1961 if (sid_name_use
!= SID_NAME_UNKNOWN
&&
1962 sid_name_use
!= map
.sid_name_use
) {
1963 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map
.nt_name
));
1966 if (unix_only
==ENUM_ONLY_MAPPED
&& map
.gid
==-1) {
1967 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map
.nt_name
));
1971 mapt
=(GROUP_MAP
*)Realloc((*rmap
), (entries
+1)*sizeof(GROUP_MAP
));
1973 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
1975 return NT_STATUS_UNSUCCESSFUL
;
1980 mapt
[entries
] = map
;
1985 ldapsam_endsamgrent(methods
);
1987 *num_entries
= entries
;
1989 return NT_STATUS_OK
;
1992 NTSTATUS
pdb_init_ldapsam(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
, const char *location
)
1995 struct smb_ldap_privates
*ldap_state
;
1997 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_methods(pdb_context
->mem_ctx
, pdb_method
))) {
2001 (*pdb_method
)->name
= "ldapsam";
2003 (*pdb_method
)->setsampwent
= ldapsam_setsampwent
;
2004 (*pdb_method
)->endsampwent
= ldapsam_endsampwent
;
2005 (*pdb_method
)->getsampwent
= ldapsam_getsampwent
;
2006 (*pdb_method
)->getsampwnam
= ldapsam_getsampwnam
;
2007 (*pdb_method
)->getsampwsid
= ldapsam_getsampwsid
;
2008 (*pdb_method
)->add_sam_account
= ldapsam_add_sam_account
;
2009 (*pdb_method
)->update_sam_account
= ldapsam_update_sam_account
;
2010 (*pdb_method
)->delete_sam_account
= ldapsam_delete_sam_account
;
2012 (*pdb_method
)->getgrsid
= ldapsam_getgrsid
;
2013 (*pdb_method
)->getgrgid
= ldapsam_getgrgid
;
2014 (*pdb_method
)->getgrnam
= ldapsam_getgrnam
;
2015 (*pdb_method
)->add_group_mapping_entry
= ldapsam_add_group_mapping_entry
;
2016 (*pdb_method
)->update_group_mapping_entry
= ldapsam_update_group_mapping_entry
;
2017 (*pdb_method
)->delete_group_mapping_entry
= ldapsam_delete_group_mapping_entry
;
2018 (*pdb_method
)->enum_group_mapping
= ldapsam_enum_group_mapping
;
2020 /* TODO: Setup private data and free */
2022 ldap_state
= talloc_zero(pdb_context
->mem_ctx
, sizeof(struct smb_ldap_privates
));
2025 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2026 return NT_STATUS_NO_MEMORY
;
2030 ldap_state
->uri
= talloc_strdup(pdb_context
->mem_ctx
, location
);
2031 #ifdef WITH_LDAP_SAMCONFIG
2033 int ldap_port
= lp_ldap_port();
2035 /* remap default port if not using SSL (ie clear or TLS) */
2036 if ( (lp_ldap_ssl() != LDAP_SSL_ON
) && (ldap_port
== 636) ) {
2040 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
);
2041 if (!ldap_state
->uri
) {
2042 return NT_STATUS_NO_MEMORY
;
2046 ldap_state
->uri
= "ldap://localhost";
2050 (*pdb_method
)->private_data
= ldap_state
;
2052 (*pdb_method
)->free_private_data
= free_private_data
;
2054 return NT_STATUS_OK
;
2057 NTSTATUS
pdb_init_ldapsam_nua(PDB_CONTEXT
*pdb_context
, PDB_METHODS
**pdb_method
, const char *location
)
2060 struct smb_ldap_privates
*ldap_state
;
2061 uint32 low_nua_uid
, high_nua_uid
;
2063 if (!NT_STATUS_IS_OK(nt_status
= pdb_init_ldapsam(pdb_context
, pdb_method
, location
))) {
2067 (*pdb_method
)->name
= "ldapsam_nua";
2069 ldap_state
= (*pdb_method
)->private_data
;
2071 ldap_state
->permit_non_unix_accounts
= True
;
2073 if (!lp_non_unix_account_range(&low_nua_uid
, &high_nua_uid
)) {
2074 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
2075 return NT_STATUS_UNSUCCESSFUL
;
2078 ldap_state
->low_nua_rid
=fallback_pdb_uid_to_user_rid(low_nua_uid
);
2080 ldap_state
->high_nua_rid
=fallback_pdb_uid_to_user_rid(high_nua_uid
);
2082 return NT_STATUS_OK
;
2085 int pdb_ldap_init(void)
2087 smb_register_passdb("ldapsam", pdb_init_ldapsam
, PASSDB_INTERFACE_VERSION
);
2088 smb_register_passdb("ldapsam_nua", pdb_init_ldapsam_nua
, PASSDB_INTERFACE_VERSION
);