From 58e1fe62cc955c6b8449332447a6879c6fab64e7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 18 May 2002 05:52:52 +0000 Subject: A few things in this commit: cleanup some of the code in net_rpc_join re const warnings and fstrings. Passdb: Make the %u and %U substituions in passdb work. This is done by declaring these paramters to be 'const' and doing the substitution manually. I'm told this is us going full circle, but I can't really see a better way. Finally these things actually seem to work properly... Make the lanman code use the pdb's recorded values for homedir etc rather than the values from lp_*() Add code to set the plaintext password in the passdb, where it can decide how to store/set it. For use with a future 'ldap password change' option, or somthing like that... Add pdb_unix, so as to remove the 'not in passdb' special cases from the local_lookup_*() code. Quite small, as it uses the new 'struct passwd -> SAM_ACCOUNT' code that is now in just one place. (also used by pdb_smbpasswd) Other: Fix up the adding of [homes] at session setup time to actually pass the right string, that is the unix homedir, not the UNC path. Fix up [homes] so that for winbind users is picks the correct name. (bad interactions with the default domain code previously) Change the rpc_server/srv_lsa_nt.c code to match NT when for the SATUS_NONE_MAPPED reply: This was only being triggered on no queries, now it is on the 'no mappings' (ie all mappings failed). Checked against Win2k. Policy Question: Should SID -> unix_user.234/unix_group.364 be considered a mapping or not? Currently it isn't. Andrew Bartlett (This used to be commit c28668068b5a3b3cf3c4317e5fb32ec9957f3e34) --- source3/passdb/passdb.c | 310 ++++++++++++++++++++++------------------- source3/passdb/pdb_get_set.c | 76 +++++++++- source3/passdb/pdb_interface.c | 16 ++- source3/passdb/pdb_ldap.c | 50 ++++--- source3/passdb/pdb_smbpasswd.c | 55 +------- source3/passdb/pdb_tdb.c | 99 +++++++------ source3/passdb/pdb_unix.c | 126 +++++++++++++++++ 7 files changed, 465 insertions(+), 267 deletions(-) create mode 100644 source3/passdb/pdb_unix.c (limited to 'source3/passdb') diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index d34866fa63..edae00389e 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -30,6 +30,7 @@ */ extern DOM_SID global_sam_sid; +extern pstring global_myname; /************************************************************ Fill the SAM_ACCOUNT with default values. @@ -150,32 +151,39 @@ NTSTATUS pdb_init_sam(SAM_ACCOUNT **user) Initialises a struct sam_passwd with sane values. ************************************************************/ -NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd) +NTSTATUS pdb_fill_sam_pw(SAM_ACCOUNT *sam_account, const struct passwd *pwd) { - pstring str; GROUP_MAP map; uint32 rid; - NTSTATUS nt_status; if (!pwd) { - new_sam_acct = NULL; return NT_STATUS_UNSUCCESSFUL; } - if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(new_sam_acct))) { - new_sam_acct = NULL; - return nt_status; - } + pdb_fill_default_sam(sam_account); - pdb_set_username(*new_sam_acct, pwd->pw_name); - pdb_set_fullname(*new_sam_acct, pwd->pw_gecos); + pdb_set_username(sam_account, pwd->pw_name); + pdb_set_fullname(sam_account, pwd->pw_gecos); - pdb_set_uid(*new_sam_acct, pwd->pw_uid); - pdb_set_gid(*new_sam_acct, pwd->pw_gid); + pdb_set_unix_homedir(sam_account, pwd->pw_dir); + + pdb_set_domain (sam_account, lp_workgroup()); + + pdb_set_uid(sam_account, pwd->pw_uid); + pdb_set_gid(sam_account, pwd->pw_gid); - /* let the backends set the rid!! - pdb_set_user_rid(*new_sam_acct, pdb_uid_to_user_rid(pwd->pw_uid)); - -- simo */ + /* When we get a proper uid -> SID and SID -> uid allocation + mechinism, we should call it here. + + We can't just set this to 0 or allow it only to be filled + in when added to the backend, becouse the user's SID + may already be in security descriptors etc. + + -- abartlet 11-May-02 + */ + + pdb_set_user_rid(sam_account, + fallback_pdb_uid_to_user_rid(pwd->pw_uid)); /* call the mapping code here */ if(get_group_map_from_gid(pwd->pw_gid, &map, MAPPING_WITHOUT_PRIV)) { @@ -185,24 +193,67 @@ NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd) rid=pdb_gid_to_group_rid(pwd->pw_gid); } - pdb_set_group_rid(*new_sam_acct, rid); + pdb_set_group_rid(sam_account, rid); + + /* check if this is a user account or a machine account */ + if (pwd->pw_name[strlen(pwd->pw_name)-1] != '$') + { + pdb_set_profile_path(sam_account, + standard_sub_specified((sam_account)->mem_ctx, + lp_logon_path(), + pwd->pw_name, global_myname, + pwd->pw_uid, pwd->pw_gid), + False); + + pdb_set_homedir(sam_account, + standard_sub_specified((sam_account)->mem_ctx, + lp_logon_home(), + pwd->pw_name, global_myname, + pwd->pw_uid, pwd->pw_gid), + False); + + pdb_set_dir_drive(sam_account, + standard_sub_specified((sam_account)->mem_ctx, + lp_logon_drive(), + pwd->pw_name, global_myname, + pwd->pw_uid, pwd->pw_gid), + False); + + pdb_set_logon_script(sam_account, + standard_sub_specified((sam_account)->mem_ctx, + lp_logon_script(), + pwd->pw_name, global_myname, + pwd->pw_uid, pwd->pw_gid), + False); + } + return NT_STATUS_OK; +} - pstrcpy(str, lp_logon_path()); - standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str); - pdb_set_profile_path(*new_sam_acct, str, False); - - pstrcpy(str, lp_logon_home()); - standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str); - pdb_set_homedir(*new_sam_acct, str, False); - - pstrcpy(str, lp_logon_drive()); - standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str); - pdb_set_dir_drive(*new_sam_acct, str, False); - pstrcpy(str, lp_logon_script()); - standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str); - pdb_set_logon_script(*new_sam_acct, str, False); - +/************************************************************* + Initialises a struct sam_passwd with sane values. + ************************************************************/ + +NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd) +{ + NTSTATUS nt_status; + + if (!pwd) { + new_sam_acct = NULL; + return NT_STATUS_UNSUCCESSFUL; + } + + if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(new_sam_acct))) { + new_sam_acct = NULL; + return nt_status; + } + + if (!NT_STATUS_IS_OK(nt_status = pdb_fill_sam_pw(*new_sam_acct, pwd))) { + pdb_free_sam(new_sam_acct); + new_sam_acct = NULL; + return nt_status; + } + return NT_STATUS_OK; } @@ -210,18 +261,21 @@ NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd) /** * Free the contets of the SAM_ACCOUNT, but not the structure. * - * Also wipes the LM and NT hashes from memory. + * Also wipes the LM and NT hashes and plaintext passwrod from + * memory. * * @param user SAM_ACCOUNT to free members of. **/ static void pdb_free_sam_contents(SAM_ACCOUNT *user) { - /* As we start mallocing more strings this is where - we should free them. */ + + /* Kill off sensitive data. Free()ed by the + talloc mechinism */ data_blob_clear_free(&(user->private.lm_pw)); data_blob_clear_free(&(user->private.nt_pw)); + data_blob_clear_free(&(user->private.plaintext_pw)); } @@ -519,12 +573,8 @@ BOOL pdb_rid_is_user(uint32 rid) BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use) { uint32 rid; - BOOL is_user; SAM_ACCOUNT *sam_account = NULL; - uid_t uid; - struct passwd *pass; GROUP_MAP map; - sid_peek_rid(sid, &rid); *psid_name_use = SID_NAME_UNKNOWN; @@ -564,6 +614,7 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use return False; } + /* This now does the 'generic' mapping in pdb_unix */ if (pdb_getsampwrid(sam_account, rid)) { fstrcpy(name, pdb_get_username(sam_account)); *psid_name_use = SID_NAME_USER; @@ -572,47 +623,36 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use return True; } - + pdb_free_sam(&sam_account); if (get_group_map_from_sid(*sid, &map, MAPPING_WITHOUT_PRIV)) { if (map.gid!=-1) { DEBUG(5,("local_lookup_sid: mapped group %s to gid %u\n", map.nt_name, (unsigned int)map.gid)); - fstrcpy(name, map.nt_name); - *psid_name_use = map.sid_name_use; - return True; + } else { + DEBUG(5,("local_lookup_sid: mapped group %s to no unix gid. Returning name.\n", map.nt_name)); } - } - - is_user = pdb_rid_is_user(rid); - DEBUG(5, ("assuming RID %u is a %s\n", (unsigned)rid, is_user ? "user" : "group")); + fstrcpy(name, map.nt_name); + *psid_name_use = map.sid_name_use; + return True; + } if (pdb_rid_is_user(rid)) { - uid = fallback_pdb_user_rid_to_uid(rid); - pass = getpwuid_alloc(uid); - - *psid_name_use = SID_NAME_USER; - - DEBUG(5,("local_lookup_sid: looking up uid %u %s\n", (unsigned int)uid, - pass ? "succeeded" : "failed" )); - - if(!pass) { - slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid); - return True; - } - - fstrcpy(name, pass->pw_name); - - DEBUG(5,("local_lookup_sid: found user %s for rid %u\n", name, - (unsigned int)rid )); - - passwd_free(&pass); - + uid_t uid; + + DEBUG(5, ("assuming RID %u is a user\n", (unsigned)rid)); + + uid = fallback_pdb_user_rid_to_uid(rid); + slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid); + + return False; /* Indicates that this user was 'not mapped' */ } else { gid_t gid; struct group *gr; + DEBUG(5, ("assuming RID %u is a group\n", (unsigned)rid)); + gid = pdb_group_rid_to_gid(rid); gr = getgrgid(gid); @@ -623,15 +663,15 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use if(!gr) { slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid); - return False; + return False; /* Indicates that this group was 'not mapped' */ } fstrcpy( name, gr->gr_name); DEBUG(5,("local_lookup_sid: found group %s for rid %u\n", name, (unsigned int)rid )); + return True; } - return True; } /******************************************************************* @@ -641,11 +681,12 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psid_name_use) { extern DOM_SID global_sid_World_Domain; - struct passwd *pass = NULL; DOM_SID local_sid; fstring user; SAM_ACCOUNT *sam_account = NULL; - + struct group *grp; + GROUP_MAP map; + *psid_name_use = SID_NAME_UNKNOWN; /* @@ -691,52 +732,45 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi pdb_free_sam(&sam_account); - if ((pass = Get_Pwnam(user))) { - sid_append_rid( &local_sid, fallback_pdb_uid_to_user_rid(pass->pw_uid)); - *psid_name_use = SID_NAME_USER; + /* + * Maybe it was a group ? + */ + /* check if it's a mapped group */ + if (get_group_map_from_ntname(user, &map, MAPPING_WITHOUT_PRIV)) { + if (map.gid!=-1) { + /* yes it's a mapped group to a valid unix group */ + sid_copy(&local_sid, &map.sid); + *psid_name_use = map.sid_name_use; + } + else { + /* it's a correct name but not mapped so it points to nothing*/ + return False; + } } else { - /* - * Maybe it was a group ? + /* it's not a mapped group */ + grp = getgrnam(user); + if(!grp) + return False; + + /* + *check if it's mapped, if it is reply it doesn't exist + * + * that's to prevent this case: + * + * unix group ug is mapped to nt group ng + * someone does a lookup on ug + * we must not reply as it doesn't "exist" anymore + * for NT. For NT only ng exists. + * JFM, 30/11/2001 */ - struct group *grp; - GROUP_MAP map; - /* check if it's a mapped group */ - if (get_group_map_from_ntname(user, &map, MAPPING_WITHOUT_PRIV)) { - if (map.gid!=-1) { - /* yes it's a mapped group to a valid unix group */ - sid_copy(&local_sid, &map.sid); - *psid_name_use = map.sid_name_use; - } - else - /* it's a correct name but not mapped so it points to nothing*/ - return False; - } else { - /* it's not a mapped group */ - grp = getgrnam(user); - if(!grp) - return False; - - /* - *check if it's mapped, if it is reply it doesn't exist - * - * that's to prevent this case: - * - * unix group ug is mapped to nt group ng - * someone does a lookup on ug - * we must not reply as it doesn't "exist" anymore - * for NT. For NT only ng exists. - * JFM, 30/11/2001 - */ - - if(get_group_map_from_gid(grp->gr_gid, &map, MAPPING_WITHOUT_PRIV)){ - return False; - } - - sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid)); - *psid_name_use = SID_NAME_ALIAS; + if (get_group_map_from_gid(grp->gr_gid, &map, MAPPING_WITHOUT_PRIV)){ + return False; } + + sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid)); + *psid_name_use = SID_NAME_ALIAS; } sid_copy( psid, &local_sid); @@ -824,15 +858,9 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type) DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid), (unsigned int)*puid, pdb_get_username(sam_user))); } else { - if ((pdb_rid_is_user(rid))) { - *puid = fallback_pdb_user_rid_to_uid(rid); - DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (non-passdb user).\n", sid_to_string( str, psid), - (unsigned int)*puid)); - } else { - DEBUG(5,("local_sid_to_uid: SID %s not mapped becouse RID isn't a user.\n", sid_to_string( str, psid))); - pdb_free_sam(&sam_user); - return False; - } + DEBUG(5,("local_sid_to_uid: SID %s not mapped becouse RID was not found in passdb.\n", sid_to_string( str, psid))); + pdb_free_sam(&sam_user); + return False; } pdb_free_sam(&sam_user); @@ -919,7 +947,7 @@ BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type) * @return static buffer containing the converted string **/ -static char *pdb_convert(const UNISTR2 *from) +const char *pdb_unistr2_convert(const UNISTR2 *from) { static pstring convert_buffer; *convert_buffer = 0; @@ -950,25 +978,25 @@ void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from) pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time)); if (from->uni_user_name.buffer) - pdb_set_username(to , pdb_convert(&from->uni_user_name )); + pdb_set_username(to , pdb_unistr2_convert(&from->uni_user_name )); if (from->uni_full_name.buffer) - pdb_set_fullname(to , pdb_convert(&from->uni_full_name )); + pdb_set_fullname(to , pdb_unistr2_convert(&from->uni_full_name )); if (from->uni_home_dir.buffer) - pdb_set_homedir(to , pdb_convert(&from->uni_home_dir ), True); + pdb_set_homedir(to , pdb_unistr2_convert(&from->uni_home_dir ), True); if (from->uni_dir_drive.buffer) - pdb_set_dir_drive(to , pdb_convert(&from->uni_dir_drive ), True); + pdb_set_dir_drive(to , pdb_unistr2_convert(&from->uni_dir_drive ), True); if (from->uni_logon_script.buffer) - pdb_set_logon_script(to , pdb_convert(&from->uni_logon_script), True); + pdb_set_logon_script(to , pdb_unistr2_convert(&from->uni_logon_script), True); if (from->uni_profile_path.buffer) - pdb_set_profile_path(to , pdb_convert(&from->uni_profile_path), True); + pdb_set_profile_path(to , pdb_unistr2_convert(&from->uni_profile_path), True); if (from->uni_acct_desc.buffer) - pdb_set_acct_desc(to , pdb_convert(&from->uni_acct_desc )); + pdb_set_acct_desc(to , pdb_unistr2_convert(&from->uni_acct_desc )); if (from->uni_workstations.buffer) - pdb_set_workstations(to , pdb_convert(&from->uni_workstations)); + pdb_set_workstations(to , pdb_unistr2_convert(&from->uni_workstations)); if (from->uni_unknown_str.buffer) - pdb_set_unknown_str(to , pdb_convert(&from->uni_unknown_str )); + pdb_set_unknown_str(to , pdb_unistr2_convert(&from->uni_unknown_str )); if (from->uni_munged_dial.buffer) - pdb_set_munged_dial(to , pdb_convert(&from->uni_munged_dial )); + pdb_set_munged_dial(to , pdb_unistr2_convert(&from->uni_munged_dial )); if (from->user_rid) pdb_set_user_rid(to, from->user_rid); @@ -1005,25 +1033,25 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time)); if (from->uni_user_name.buffer) - pdb_set_username(to , pdb_convert(&from->uni_user_name )); + pdb_set_username(to , pdb_unistr2_convert(&from->uni_user_name )); if (from->uni_full_name.buffer) - pdb_set_fullname(to , pdb_convert(&from->uni_full_name )); + pdb_set_fullname(to , pdb_unistr2_convert(&from->uni_full_name )); if (from->uni_home_dir.buffer) - pdb_set_homedir(to , pdb_convert(&from->uni_home_dir ), True); + pdb_set_homedir(to , pdb_unistr2_convert(&from->uni_home_dir ), True); if (from->uni_dir_drive.buffer) - pdb_set_dir_drive(to , pdb_convert(&from->uni_dir_drive ), True); + pdb_set_dir_drive(to , pdb_unistr2_convert(&from->uni_dir_drive ), True); if (from->uni_logon_script.buffer) - pdb_set_logon_script(to , pdb_convert(&from->uni_logon_script), True); + pdb_set_logon_script(to , pdb_unistr2_convert(&from->uni_logon_script), True); if (from->uni_profile_path.buffer) - pdb_set_profile_path(to , pdb_convert(&from->uni_profile_path), True); + pdb_set_profile_path(to , pdb_unistr2_convert(&from->uni_profile_path), True); if (from->uni_acct_desc.buffer) - pdb_set_acct_desc(to , pdb_convert(&from->uni_acct_desc )); + pdb_set_acct_desc(to , pdb_unistr2_convert(&from->uni_acct_desc )); if (from->uni_workstations.buffer) - pdb_set_workstations(to , pdb_convert(&from->uni_workstations)); + pdb_set_workstations(to , pdb_unistr2_convert(&from->uni_workstations)); if (from->uni_unknown_str.buffer) - pdb_set_unknown_str(to , pdb_convert(&from->uni_unknown_str )); + pdb_set_unknown_str(to , pdb_unistr2_convert(&from->uni_unknown_str )); if (from->uni_munged_dial.buffer) - pdb_set_munged_dial(to , pdb_convert(&from->uni_munged_dial )); + pdb_set_munged_dial(to , pdb_unistr2_convert(&from->uni_munged_dial )); if (from->user_rid) pdb_set_user_rid(to, from->user_rid); diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index cf77efd38f..372b332a45 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -138,6 +138,21 @@ const uint8* pdb_get_lanman_passwd (const SAM_ACCOUNT *sampass) return (NULL); } +/* Return the plaintext password if known. Most of the time + it isn't, so don't assume anything magic about this function. + + Used to pass the plaintext to passdb backends that might + want to store more than just the NTLM hashes. +*/ +const char* pdb_get_plaintext_passwd (const SAM_ACCOUNT *sampass) +{ + if (sampass) { + return ((char*)sampass->private.plaintext_pw.data); + } + else + return (NULL); +} + uint32 pdb_get_user_rid (const SAM_ACCOUNT *sampass) { if (sampass) @@ -224,6 +239,14 @@ const char* pdb_get_homedir (const SAM_ACCOUNT *sampass) return (NULL); } +const char* pdb_get_unix_homedir (const SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->private.unix_home_dir); + else + return (NULL); +} + const char* pdb_get_dirdrive (const SAM_ACCOUNT *sampass) { if (sampass) @@ -618,7 +641,7 @@ BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, const char *logon_script, BOOL s } if (store) { - DEBUG(10, ("pdb_set_logon_script: setting logon script sam flag!")); + DEBUG(10, ("pdb_set_logon_script: setting logon script sam flag!\n")); pdb_set_init_flag(sampass, FLAG_SAM_LOGONSCRIPT); } @@ -650,7 +673,7 @@ BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, const char *profile_path, BOOL } if (store) { - DEBUG(10, ("pdb_set_profile_path: setting profile path sam flag!")); + DEBUG(10, ("pdb_set_profile_path: setting profile path sam flag!\n")); pdb_set_init_flag(sampass, FLAG_SAM_PROFILE); } @@ -682,7 +705,7 @@ BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, const char *dir_drive, BOOL store) } if (store) { - DEBUG(10, ("pdb_set_dir_drive: setting dir drive sam flag!")); + DEBUG(10, ("pdb_set_dir_drive: setting dir drive sam flag!\n")); pdb_set_init_flag(sampass, FLAG_SAM_DRIVE); } @@ -721,6 +744,34 @@ BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, const char *home_dir, BOOL store) return True; } +/********************************************************************* + Set the user's unix home directory. + ********************************************************************/ + +BOOL pdb_set_unix_homedir (SAM_ACCOUNT *sampass, const char *unix_home_dir) +{ + if (!sampass) + return False; + + if (unix_home_dir) { + DEBUG(10, ("pdb_set_homedir: setting home dir %s, was %s\n", unix_home_dir, + (sampass->private.unix_home_dir)?(sampass->private.unix_home_dir):"NULL")); + + sampass->private.unix_home_dir = talloc_strdup(sampass->mem_ctx, + unix_home_dir); + + if (!sampass->private.unix_home_dir) { + DEBUG(0, ("pdb_set_unix_home_dir: talloc_strdup() failed!\n")); + return False; + } + + } else { + sampass->private.unix_home_dir = PDB_NOT_QUITE_NULL; + } + + return True; +} + /********************************************************************* Set the user's account description. ********************************************************************/ @@ -840,7 +891,7 @@ BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, const uint8 *pwd) Set the user's LM hash. ********************************************************************/ -BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 *pwd) +BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[16]) { if (!sampass) return False; @@ -852,6 +903,23 @@ BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 *pwd) return True; } +/********************************************************************* + Set the user's plaintext password only (base procedure, see helper + below) + ********************************************************************/ + +BOOL pdb_set_plaintext_pw_only (SAM_ACCOUNT *sampass, const uint8 *password, size_t len) +{ + if (!sampass) + return False; + + data_blob_clear_free(&sampass->private.plaintext_pw); + + sampass->private.plaintext_pw = data_blob(password, len); + + return True; +} + BOOL pdb_set_unknown_3 (SAM_ACCOUNT *sampass, uint32 unkn) { if (!sampass) diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index a19bf254e7..6488decf94 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -30,6 +30,7 @@ const struct pdb_init_function_entry builtin_pdb_init_functions[] = { { "tdbsam_nua", pdb_init_tdbsam_nua }, { "ldapsam", pdb_init_ldapsam }, { "ldapsam_nua", pdb_init_ldapsam_nua }, + { "unixsam", pdb_init_unixsam }, { "plugin", pdb_init_plugin }, { NULL, NULL} }; @@ -42,7 +43,12 @@ static BOOL context_setsampwent(struct pdb_context *context, BOOL update) } context->pwent_methods = context->pdb_methods; - + + if (!context->pwent_methods) { + /* No passdbs at all */ + return True; + } + while(!(context->pwent_methods->setsampwent(context->pwent_methods, update))){ context->pwent_methods = context->pwent_methods->next; if(context->pwent_methods == NULL)return False; @@ -83,7 +89,7 @@ static BOOL context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user) if(context->pwent_methods == NULL)return False; if(!context->pwent_methods->setsampwent){ - DEBUG(0, ("invalid context->pwent_methods->setsampwent\n")); + DEBUG(5, ("invalid context->pwent_methods->setsampwent\n")); return False; } @@ -251,7 +257,11 @@ static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_c if (!*methods) { DEBUG(0,("failed to select passdb backed!\n")); - return nt_status; + if (NT_STATUS_IS_OK(nt_status)) { + return NT_STATUS_INVALID_PARAMETER; + } else { + return nt_status; + } } return NT_STATUS_OK; } diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index af0cbef4f2..9614483ee1 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -339,7 +339,7 @@ static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state, search an attribute and return the first value found. ******************************************************************/ static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, - char *attribute, char *value) + char *attribute, pstring value) { char **values; @@ -521,12 +521,14 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pw = getpwnam_alloc(username); if (pw == NULL) { - DEBUG (2,("init_sam_from_ldap: User [%s] does not have a uid!\n", username)); + DEBUG (2,("init_sam_from_ldap: User [%s] does not ave a uid!\n", username)); return False; } uid = pw->pw_uid; gid = pw->pw_gid; + pdb_set_unix_homedir(sampass, pw->pw_dir); + passwd_free(&pw); pdb_set_uid(sampass, uid); @@ -603,37 +605,41 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive)) { - pstrcpy(dir_drive, lp_logon_drive()); - standard_sub_advanced(-1, username, "", gid, username, dir_drive); - DEBUG(5,("homeDrive fell back to %s\n",dir_drive)); - pdb_set_dir_drive(sampass, dir_drive, False); + pdb_set_dir_drive(sampass, standard_sub_specified(sampass->mem_ctx, + lp_logon_path(), + username, domain, + uid, gid), + False); } else { pdb_set_dir_drive(sampass, dir_drive, True); } if (!get_single_attribute(ldap_struct, entry, "smbHome", homedir)) { - pstrcpy(homedir, lp_logon_home()); - standard_sub_advanced(-1, username, "", gid, username, homedir); - DEBUG(5,("smbHome fell back to %s\n",homedir)); - pdb_set_homedir(sampass, homedir, False); + pdb_set_dir_drive(sampass, standard_sub_specified(sampass->mem_ctx, + lp_logon_home(), + username, domain, + uid, gid), + False); } else { pdb_set_homedir(sampass, homedir, True); } if (!get_single_attribute(ldap_struct, entry, "scriptPath", logon_script)) { - pstrcpy(logon_script, lp_logon_script()); - standard_sub_advanced(-1, username, "", gid, username, logon_script); - DEBUG(5,("scriptPath fell back to %s\n",logon_script)); - pdb_set_logon_script(sampass, logon_script, False); + pdb_set_logon_script(sampass, standard_sub_specified(sampass->mem_ctx, + lp_logon_script(), + username, domain, + uid, gid), + False); } else { pdb_set_logon_script(sampass, logon_script, True); } if (!get_single_attribute(ldap_struct, entry, "profilePath", profile_path)) { - pstrcpy(profile_path, lp_logon_path()); - standard_sub_advanced(-1, username, "", gid, username, profile_path); - DEBUG(5,("profilePath fell back to %s\n",profile_path)); - pdb_set_profile_path(sampass, profile_path, False); + pdb_set_profile_path(sampass, standard_sub_specified(sampass->mem_ctx, + lp_logon_path(), + username, domain, + uid, gid), + False); } else { pdb_set_profile_path(sampass, profile_path, True); } @@ -740,7 +746,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, } else if (ldap_state->permit_non_unix_accounts) { rid = ldapsam_get_next_available_nua_rid(ldap_state); if (rid == 0) { - DEBUG(0, ("NO user RID specified on account %s, and finding next available NUA RID failed, cannot store!\n", pdb_get_username(sampass))); + DEBUG(0, ("NO user RID specified on account %s, and findining next available NUA RID failed, cannot store!\n", pdb_get_username(sampass))); return False; } } else { @@ -1097,7 +1103,7 @@ static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * us if (ldap_count_entries(ldap_struct, result) < 1) { DEBUG(4, - ("We didn't find the user [%s] count=%d\n", sname, + ("We don't find this user [%s] count=%d\n", sname, ldap_count_entries(ldap_struct, result))); ldap_unbind(ldap_struct); return False; @@ -1151,7 +1157,7 @@ static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * us if (ldap_count_entries(ldap_struct, result) < 1) { DEBUG(0, - ("We didn't find the rid [%i] count=%d\n", rid, + ("We don't find this rid [%i] count=%d\n", rid, ldap_count_entries(ldap_struct, result))); ldap_unbind(ldap_struct); return False; @@ -1205,7 +1211,7 @@ static BOOL ldapsam_delete_sam_account(struct pdb_methods *my_methods, const SAM if (!ldapsam_connect_system(ldap_state, ldap_struct)) { ldap_unbind (ldap_struct); - DEBUG(0, ("failed to delete user %s from the LDAP database.\n", sname)); + DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname)); return False; } diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 9f37cadfe8..88e317cea9 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -1218,7 +1218,8 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas /********************************************************************* Create a SAM_ACCOUNT from a smb_passwd struct ********************************************************************/ -static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf) +static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, + SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf) { struct passwd *pwfile; @@ -1242,73 +1243,25 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, SAM_AC } else { - uint32 grid; - GROUP_MAP map; - - /* Verify in system password file... - FIXME!!! This is where we should look up an internal - mapping of allocated uid for machine accounts as well - --jerry */ pwfile = getpwnam_alloc(pw_buf->smb_name); if (pwfile == NULL) { DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s with uid %u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid)); return False; } - pdb_set_uid (sam_pass, pwfile->pw_uid); - pdb_set_gid (sam_pass, pwfile->pw_gid); - - pdb_set_fullname(sam_pass, pwfile->pw_gecos); - - pdb_set_user_rid(sam_pass, fallback_pdb_uid_to_user_rid (pwfile->pw_uid)); - - if (get_group_map_from_gid(pwfile->pw_gid, &map, MAPPING_WITHOUT_PRIV)) { - sid_peek_rid(&map.sid, &grid); - } else { - grid=pdb_gid_to_group_rid(pwfile->pw_gid); - } - - pdb_set_group_rid(sam_pass, grid); - - /* check if this is a user account or a machine account */ - if (pw_buf->smb_name[strlen(pw_buf->smb_name)-1] != '$') - { - pstring str; - - pstrcpy(str, lp_logon_path()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_profile_path(sam_pass, str, False); - - pstrcpy(str, lp_logon_home()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_homedir(sam_pass, str, False); - - pstrcpy(str, lp_logon_drive()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_dir_drive(sam_pass, str, False); - - pstrcpy(str, lp_logon_script()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_logon_script(sam_pass, str, False); - - } else { - /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ - /*pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS); */ + if (!NT_STATUS_IS_OK(pdb_fill_sam_pw(sam_pass, pwfile))) { + return False; } passwd_free(&pwfile); } - pdb_set_username (sam_pass, pw_buf->smb_name); pdb_set_nt_passwd (sam_pass, pw_buf->smb_nt_passwd); pdb_set_lanman_passwd (sam_pass, pw_buf->smb_passwd); pdb_set_acct_ctrl (sam_pass, pw_buf->acct_ctrl); pdb_set_pass_last_set_time (sam_pass, pw_buf->pass_last_set_time); pdb_set_pass_can_change_time (sam_pass, pw_buf->pass_last_set_time, True); - pdb_set_domain (sam_pass, lp_workgroup()); - pdb_set_dir_drive (sam_pass, lp_logon_drive(), False); - #if 0 /* JERRY */ /* the smbpasswd format doesn't have a must change time field, so we can't get this right. The best we can do is to set this to diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index 3a9bc894bb..46120c3ccc 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -86,12 +86,11 @@ static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, uint8 *hours; static uint8 *lm_pw_ptr, *nt_pw_ptr; uint32 len = 0; - uint32 lmpwlen, ntpwlen, hourslen; + uint32 lm_pw_len, nt_pw_len, hourslen; BOOL ret = True; - BOOL setflag; pstring sub_buffer; struct passwd *pw; - uid_t uid; + uid_t uid = -1; gid_t gid = -1; /* This is what standard sub advanced expects if no gid is known */ if(sampass == NULL || buf == NULL) { @@ -121,8 +120,8 @@ static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, &munged_dial_len, &munged_dial, &user_rid, &group_rid, - &lmpwlen, &lm_pw_ptr, - &ntpwlen, &nt_pw_ptr, + &lm_pw_len, &lm_pw_ptr, + &nt_pw_len, &nt_pw_ptr, &acct_ctrl, &unknown_3, &logon_divs, @@ -152,6 +151,8 @@ static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, uid = pw->pw_uid; gid = pw->pw_gid; + pdb_set_unix_homedir(sampass, pw->pw_dir); + passwd_free(&pw); pdb_set_uid(sampass, uid); @@ -165,66 +166,72 @@ static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, pdb_set_pass_must_change_time(sampass, pass_must_change_time, True); pdb_set_pass_last_set_time(sampass, pass_last_set_time); - pdb_set_username (sampass, username); + pdb_set_username (sampass, username); pdb_set_domain (sampass, domain); pdb_set_nt_username (sampass, nt_username); pdb_set_fullname (sampass, fullname); - if (homedir) setflag = True; + if (homedir) { + pdb_set_homedir(sampass, homedir, True); + } else { - setflag = False; - pstrcpy(sub_buffer, lp_logon_home()); - /* standard_sub_advanced() assumes pstring is passed!! */ - standard_sub_advanced(-1, username, "", gid, username, sub_buffer); - homedir = strdup(sub_buffer); - if(!homedir) { ret = False; goto done; } - DEBUG(5,("Home directory set back to %s\n", homedir)); + pdb_set_homedir(sampass, + standard_sub_specified(sampass->mem_ctx, + lp_logon_home(), + username, domain, + uid, gid), + False); } - pdb_set_homedir(sampass, homedir, setflag); - if (dir_drive) setflag = True; + if (dir_drive) + pdb_set_dir_drive(sampass, dir_drive, True); else { - setflag = False; - pstrcpy(sub_buffer, lp_logon_drive()); - standard_sub_advanced(-1, username, "", gid, username, sub_buffer); - dir_drive = strdup(sub_buffer); - if(!dir_drive) { ret = False; goto done; } - DEBUG(5,("Drive set back to %s\n", dir_drive)); + pdb_set_dir_drive(sampass, + standard_sub_specified(sampass->mem_ctx, + lp_logon_drive(), + username, domain, + uid, gid), + False); } - pdb_set_dir_drive(sampass, dir_drive, setflag); - if (logon_script) setflag = True; + if (logon_script) + pdb_set_logon_script(sampass, logon_script, True); else { - setflag = False; - pstrcpy(sub_buffer, lp_logon_script()); - standard_sub_advanced(-1, username, "", gid, username, sub_buffer); - logon_script = strdup(sub_buffer); - if(!logon_script) { ret = False; goto done; } - DEBUG(5,("Logon script set back to %s\n", logon_script)); + pdb_set_logon_script(sampass, + standard_sub_specified(sampass->mem_ctx, + lp_logon_script(), + username, domain, + uid, gid), + False); } - pdb_set_logon_script(sampass, logon_script, setflag); - if (profile_path) setflag = True; - else { - setflag = False; - pstrcpy(sub_buffer, lp_logon_path()); - standard_sub_advanced(-1, username, "", gid, username, sub_buffer); - profile_path = strdup(sub_buffer); - if(!profile_path) { ret = False; goto done; } - DEBUG(5,("Profile path set back to %s\n", profile_path)); + if (profile_path) { + pdb_set_profile_path(sampass, profile_path, True); + } else { + pdb_set_profile_path(sampass, + standard_sub_specified(sampass->mem_ctx, + lp_logon_path(), + username, domain, + uid, gid), + False); } - pdb_set_profile_path(sampass, profile_path, setflag); pdb_set_acct_desc (sampass, acct_desc); pdb_set_workstations (sampass, workstations); pdb_set_munged_dial (sampass, munged_dial); - if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr)) { - ret = False; - goto done; + + if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) { + if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr)) { + ret = False; + goto done; + } } - if (!pdb_set_nt_passwd(sampass, nt_pw_ptr)) { - ret = False; - goto done; + + if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) { + if (!pdb_set_nt_passwd(sampass, nt_pw_ptr)) { + ret = False; + goto done; + } } pdb_set_user_rid(sampass, user_rid); diff --git a/source3/passdb/pdb_unix.c b/source3/passdb/pdb_unix.c new file mode 100644 index 0000000000..d1f95c445b --- /dev/null +++ b/source3/passdb/pdb_unix.c @@ -0,0 +1,126 @@ +/* + * Unix password backend for samba + * Copyright (C) Jelmer Vernooij 2002 + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 675 + * Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/****************************************************************** + Lookup a name in the SAM database + ******************************************************************/ + +static BOOL unixsam_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname) +{ + struct passwd *pass; + if (!methods) { + DEBUG(0,("invalid methods\n")); + return False; + } + if (!sname) { + DEBUG(0,("invalid name specified")); + return False; + } + pass = Get_Pwnam(sname); + + return NT_STATUS_IS_OK(pdb_fill_sam_pw(user, pass)); +} + + +/*************************************************************************** + Search by rid + **************************************************************************/ + +static BOOL unixsam_getsampwrid (struct pdb_methods *methods, + SAM_ACCOUNT *user, uint32 rid) +{ + struct passwd *pass; + BOOL ret = False; + if (!methods) { + DEBUG(0,("invalid methods\n")); + return False; + } + + if (pdb_rid_is_user(rid)) { + pass = getpwuid_alloc(fallback_pdb_user_rid_to_uid (rid)); + + if (pass) { + ret = NT_STATUS_IS_OK(pdb_fill_sam_pw(user, pass)); + passwd_free(&pass); + } + } + return ret; +} + +/*************************************************************************** + Delete a SAM_ACCOUNT + ****************************************************************************/ + +static BOOL unixsam_delete_sam_account(struct pdb_methods *methods, const SAM_ACCOUNT *sam_pass) +{ + /* + * Unsupported as well - we don't need to get involved in + * unix passdb's - and hey, we would need to use pam for that anyway + */ + return False; +} + +/*************************************************************************** + Modifies an existing SAM_ACCOUNT + ****************************************************************************/ + +static BOOL unixsam_update_sam_account (struct pdb_methods *methods, const SAM_ACCOUNT *newpwd) +{ + return False; +} + +/*************************************************************************** + Adds an existing SAM_ACCOUNT + ****************************************************************************/ + +static BOOL unixsam_add_sam_account (struct pdb_methods *methods, const SAM_ACCOUNT *newpwd) +{ + DEBUG(0,("pdb_unix should not be listed as the first passdb backend! You can't add users to it.\n")); + return False; +} + +NTSTATUS pdb_init_unixsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS nt_status; + + if (!pdb_context) { + DEBUG(0, ("invalid pdb_context specified\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { + return nt_status; + } + + (*pdb_method)->name = "unixsam"; + + (*pdb_method)->setsampwent = NULL; + (*pdb_method)->endsampwent = NULL; + (*pdb_method)->getsampwent = NULL; + (*pdb_method)->getsampwnam = unixsam_getsampwnam; + (*pdb_method)->getsampwrid = unixsam_getsampwrid; + (*pdb_method)->add_sam_account = unixsam_add_sam_account; + (*pdb_method)->update_sam_account = unixsam_update_sam_account; + (*pdb_method)->delete_sam_account = unixsam_delete_sam_account; + + /* There's not very much to initialise here */ + return NT_STATUS_OK; +} -- cgit