From e90b65284812aaa5ff9e9935ce9bbad7791cbbcd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Jul 2002 10:35:28 +0000 Subject: updated the 3.0 branch from the head branch - ready for alpha18 (This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce) --- source3/passdb/machine_sid.c | 53 +++-- source3/passdb/passdb.c | 513 ++++++++++++++++------------------------- source3/passdb/passgrp.c | 3 + source3/passdb/pdb_get_set.c | 168 +++++++++++--- source3/passdb/pdb_interface.c | 335 ++++++++++++++++++--------- source3/passdb/pdb_ldap.c | 279 ++++++++++++++-------- source3/passdb/pdb_nisplus.c | 22 +- source3/passdb/pdb_plugin.c | 21 +- source3/passdb/pdb_smbpasswd.c | 272 +++++++--------------- source3/passdb/pdb_tdb.c | 226 +++++++++++------- source3/passdb/secrets.c | 192 +++++++++++++-- 11 files changed, 1226 insertions(+), 858 deletions(-) (limited to 'source3/passdb') diff --git a/source3/passdb/machine_sid.c b/source3/passdb/machine_sid.c index 6436a2cd05..e1f7dec2a9 100644 --- a/source3/passdb/machine_sid.c +++ b/source3/passdb/machine_sid.c @@ -4,6 +4,7 @@ Copyright (C) Jeremy Allison 1996-2002 Copyright (C) Andrew Tridgell 2002 Copyright (C) Gerald (Jerry) Carter 2000 + Copyright (C) Stefan (metze) Metzmacher 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 @@ -22,6 +23,13 @@ #include "includes.h" +/* NOTE! the global_sam_sid is the SID of our local SAM. This is only + equal to the domain SID when we are a DC, otherwise its our + workstation SID */ +static DOM_SID *global_sam_sid=NULL; + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB /**************************************************************************** Read a SID from a file. This is for compatibility with the old MACHINE.SID @@ -68,13 +76,17 @@ static void generate_random_sid(DOM_SID *sid) Generate the global machine sid. ****************************************************************************/ -BOOL pdb_generate_sam_sid(void) +static BOOL pdb_generate_sam_sid(void) { char *fname = NULL; extern pstring global_myname; extern fstring global_myworkgroup; BOOL is_dc = False; + if(global_sam_sid==NULL) + if(!(global_sam_sid=(DOM_SID *)malloc(sizeof(DOM_SID)))) + return False; + generate_wellknown_sids(); switch (lp_server_role()) { @@ -87,7 +99,7 @@ BOOL pdb_generate_sam_sid(void) break; } - if (secrets_fetch_domain_sid(global_myname, &global_sam_sid)) { + if (secrets_fetch_domain_sid(global_myname, global_sam_sid)) { DOM_SID domain_sid; /* We got our sid. If not a pdc/bdc, we're done. */ @@ -98,19 +110,19 @@ BOOL pdb_generate_sam_sid(void) /* No domain sid and we're a pdc/bdc. Store it */ - if (!secrets_store_domain_sid(global_myworkgroup, &global_sam_sid)) { + if (!secrets_store_domain_sid(global_myworkgroup, global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Can't store domain SID as a pdc/bdc.\n")); return False; } return True; } - if (!sid_equal(&domain_sid, &global_sam_sid)) { + if (!sid_equal(&domain_sid, global_sam_sid)) { /* Domain name sid doesn't match global sam sid. Re-store global sam sid as domain sid. */ DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n")); - if (!secrets_store_domain_sid(global_myworkgroup, &global_sam_sid)) { + if (!secrets_store_domain_sid(global_myworkgroup, global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID as a pdc/bdc.\n")); return False; } @@ -124,24 +136,23 @@ BOOL pdb_generate_sam_sid(void) /* check for an old MACHINE.SID file for backwards compatibility */ asprintf(&fname, "%s/MACHINE.SID", lp_private_dir()); - if (read_sid_from_file(fname, &global_sam_sid)) { + if (read_sid_from_file(fname, global_sam_sid)) { /* remember it for future reference and unlink the old MACHINE.SID */ - if (!secrets_store_domain_sid(global_myname, &global_sam_sid)) { + if (!secrets_store_domain_sid(global_myname, global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Failed to store SID from file.\n")); SAFE_FREE(fname); return False; } unlink(fname); if (is_dc) { - if (!secrets_store_domain_sid(global_myworkgroup, &global_sam_sid)) { + if (!secrets_store_domain_sid(global_myworkgroup, global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Failed to store domain SID from file.\n")); SAFE_FREE(fname); return False; } } - /* Stored the old sid from MACHINE.SID successfully. - Patch from Stefan "metze" Metzmacher */ + /* Stored the old sid from MACHINE.SID successfully.*/ SAFE_FREE(fname); return True; } @@ -150,14 +161,14 @@ BOOL pdb_generate_sam_sid(void) /* we don't have the SID in secrets.tdb, we will need to generate one and save it */ - generate_random_sid(&global_sam_sid); + generate_random_sid(global_sam_sid); - if (!secrets_store_domain_sid(global_myname, &global_sam_sid)) { + if (!secrets_store_domain_sid(global_myname, global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Failed to store generated machine SID.\n")); return False; } if (is_dc) { - if (!secrets_store_domain_sid(global_myworkgroup, &global_sam_sid)) { + if (!secrets_store_domain_sid(global_myworkgroup, global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Failed to store generated domain SID.\n")); return False; } @@ -165,3 +176,19 @@ BOOL pdb_generate_sam_sid(void) return True; } + +/* return our global_sam_sid */ +DOM_SID *get_global_sam_sid(void) +{ + if (global_sam_sid != NULL) + return global_sam_sid; + + /* memory for global_sam_sid is allocated in + pdb_generate_sam_sid() as needed */ + + if (!pdb_generate_sam_sid()) + global_sam_sid=NULL; + + return global_sam_sid; +} + diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 17aefe1159..4e3d558e98 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -23,13 +23,16 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB + /* * This is set on startup - it defines the SID for this * machine, and therefore the SAM database for which it is * responsible. */ -extern DOM_SID global_sam_sid; +extern pstring global_myname; /************************************************************ Fill the SAM_ACCOUNT with default values. @@ -90,7 +93,7 @@ static void destroy_pdb_talloc(SAM_ACCOUNT **user) NTSTATUS pdb_init_sam_talloc(TALLOC_CTX *mem_ctx, SAM_ACCOUNT **user) { if (*user != NULL) { - DEBUG(0,("pdb_init_sam: SAM_ACCOUNT was non NULL\n")); + DEBUG(0,("pdb_init_sam_talloc: SAM_ACCOUNT was non NULL\n")); #if 0 smb_panic("non-NULL pointer passed to pdb_init_sam\n"); #endif @@ -105,7 +108,7 @@ NTSTATUS pdb_init_sam_talloc(TALLOC_CTX *mem_ctx, SAM_ACCOUNT **user) *user=(SAM_ACCOUNT *)talloc(mem_ctx, sizeof(SAM_ACCOUNT)); if (*user==NULL) { - DEBUG(0,("pdb_init_sam: error while allocating memory\n")); + DEBUG(0,("pdb_init_sam_talloc: error while allocating memory\n")); return NT_STATUS_NO_MEMORY; } @@ -150,59 +153,115 @@ 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(sam_account, pwd->pw_name); + pdb_set_fullname(sam_account, pwd->pw_gecos); - pdb_set_username(*new_sam_acct, pwd->pw_name); - pdb_set_fullname(*new_sam_acct, pwd->pw_gecos); + pdb_set_unix_homedir(sam_account, pwd->pw_dir); - pdb_set_uid(*new_sam_acct, pwd->pw_uid); - pdb_set_gid(*new_sam_acct, pwd->pw_gid); + 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 + */ + + if (!pdb_set_user_sid_from_rid(sam_account, + fallback_pdb_uid_to_user_rid(pwd->pw_uid))) { + DEBUG(0,("Can't set User SID from RID!\n")); + return NT_STATUS_INVALID_PARAMETER; + } /* call the mapping code here */ if(get_group_map_from_gid(pwd->pw_gid, &map, MAPPING_WITHOUT_PRIV)) { - sid_peek_rid(&map.sid, &rid); + if (!pdb_set_group_sid(sam_account,&map.sid)){ + DEBUG(0,("Can't set Group SID!\n")); + return NT_STATUS_INVALID_PARAMETER; + } } else { - rid=pdb_gid_to_group_rid(pwd->pw_gid); + if (!pdb_set_group_sid_from_rid(sam_account,pdb_gid_to_group_rid(pwd->pw_gid))) { + DEBUG(0,("Can't set Group SID\n")); + return NT_STATUS_INVALID_PARAMETER; + } } + + /* 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, + talloc_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, + talloc_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, + talloc_sub_specified((sam_account)->mem_ctx, + lp_logon_drive(), + pwd->pw_name, global_myname, + pwd->pw_uid, pwd->pw_gid), + False); - pdb_set_group_rid(*new_sam_acct, rid); + pdb_set_logon_script(sam_account, + talloc_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 +269,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)); } @@ -399,46 +461,14 @@ BOOL pdb_gethexpwd(const char *p, unsigned char *pwd) return (True); } -#if 0 /* seem it is not used by anyone */ -/******************************************************************* - Group and User RID username mapping function - ********************************************************************/ - -BOOL pdb_name_to_rid(const char *user_name, uint32 *u_rid, uint32 *g_rid) -{ - GROUP_MAP map; - struct passwd *pw = Get_Pwnam(user_name); - - if (u_rid == NULL || g_rid == NULL || user_name == NULL) - return False; - - if (!pw) { - DEBUG(1,("Username %s is invalid on this system\n", user_name)); - return False; - } - - /* turn the unix UID into a Domain RID. this is what the posix - sub-system does (adds 1000 to the uid) */ - *u_rid = fallback_pdb_uid_to_user_rid(pw->pw_uid); - - /* absolutely no idea what to do about the unix GID to Domain RID mapping */ - /* map it ! */ - if (get_group_map_from_gid(pw->pw_gid, &map, MAPPING_WITHOUT_PRIV)) { - sid_peek_rid(&map.sid, g_rid); - } else - *g_rid = pdb_gid_to_group_rid(pw->pw_gid); - - return True; -} -#endif /* seem it is not used by anyone */ - /******************************************************************* Converts NT user RID to a UNIX uid. ********************************************************************/ -static uid_t fallback_pdb_user_rid_to_uid(uint32 user_rid) +uid_t fallback_pdb_user_rid_to_uid(uint32 user_rid) { - return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER); + int rid_offset = lp_algorithmic_rid_base(); + return (uid_t)(((user_rid & (~USER_RID_TYPE))- rid_offset)/RID_MULTIPLIER); } @@ -446,9 +476,10 @@ static uid_t fallback_pdb_user_rid_to_uid(uint32 user_rid) converts UNIX uid to an NT User RID. ********************************************************************/ -static uint32 fallback_pdb_uid_to_user_rid(uid_t uid) +uint32 fallback_pdb_uid_to_user_rid(uid_t uid) { - return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE); + int rid_offset = lp_algorithmic_rid_base(); + return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE); } /******************************************************************* @@ -457,7 +488,8 @@ static uint32 fallback_pdb_uid_to_user_rid(uid_t uid) gid_t pdb_group_rid_to_gid(uint32 group_rid) { - return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- 1000)/RID_MULTIPLIER); + int rid_offset = lp_algorithmic_rid_base(); + return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER); } /******************************************************************* @@ -470,7 +502,8 @@ gid_t pdb_group_rid_to_gid(uint32 group_rid) uint32 pdb_gid_to_group_rid(gid_t gid) { - return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE); + int rid_offset = lp_algorithmic_rid_base(); + return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE); } /******************************************************************* @@ -479,7 +512,10 @@ uint32 pdb_gid_to_group_rid(gid_t gid) static BOOL pdb_rid_is_well_known(uint32 rid) { - return (rid < 1000); + /* Not using rid_offset here, becouse this is the actual + NT fixed value (1000) */ + + return (rid < BASE_RID); } /******************************************************************* @@ -512,14 +548,14 @@ 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); + if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)){ + DEBUG(0,("local_sid_to_gid: sid_peek_check_rid return False! SID: %s\n", + sid_string_static(&map.sid))); + return False; + } *psid_name_use = SID_NAME_UNKNOWN; DEBUG(5,("local_lookup_sid: looking up RID %u.\n", (unsigned int)rid)); @@ -557,7 +593,8 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use return False; } - if (pdb_getsampwrid(sam_account, rid)) { + /* This now does the 'generic' mapping in pdb_unix */ + if (pdb_getsampwsid(sam_account, sid)) { fstrcpy(name, pdb_get_username(sam_account)); *psid_name_use = SID_NAME_USER; @@ -565,47 +602,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); @@ -616,15 +642,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; } /******************************************************************* @@ -634,11 +660,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; /* @@ -648,7 +675,7 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi fstrcpy(user, c_user); - sid_copy(&local_sid, &global_sam_sid); + sid_copy(&local_sid, get_global_sam_sid()); /* * Special case for MACHINE\Everyone. Map to the world_sid. @@ -674,62 +701,54 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi } if (pdb_getsampwnam(sam_account, user)) { - sid_append_rid( &local_sid, pdb_get_user_rid(sam_account)); + sid_copy(psid, pdb_get_user_sid(sam_account)); *psid_name_use = SID_NAME_USER; - sid_copy( psid, &local_sid); pdb_free_sam(&sam_account); return True; } 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); @@ -743,12 +762,11 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) { - extern DOM_SID global_sam_sid; struct passwd *pass; SAM_ACCOUNT *sam_user = NULL; fstring str; /* sid string buffer */ - sid_copy(psid, &global_sam_sid); + sid_copy(psid, get_global_sam_sid()); if((pass = getpwuid_alloc(uid))) { @@ -758,7 +776,7 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) } if (pdb_getsampwnam(sam_user, pass->pw_name)) { - sid_append_rid(psid, pdb_get_user_rid(sam_user)); + sid_copy(psid, pdb_get_user_sid(sam_user)); } else { sid_append_rid(psid, fallback_pdb_uid_to_user_rid(uid)); } @@ -786,8 +804,6 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type) { - extern DOM_SID global_sam_sid; - DOM_SID dom_sid; uint32 rid; fstring str; @@ -802,13 +818,13 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type) * We can only convert to a uid if this is our local * Domain SID (ie. we are the controling authority). */ - if (!sid_equal(&global_sam_sid, &dom_sid)) + if (!sid_equal(get_global_sam_sid(), &dom_sid)) return False; if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user))) return False; - if (pdb_getsampwrid(sam_user, rid)) { + if (pdb_getsampwsid(sam_user, psid)) { *puid = pdb_get_uid(sam_user); if (*puid == -1) { pdb_free_sam(&sam_user); @@ -817,14 +833,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 { - 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); @@ -839,14 +850,13 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type) DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid) { - extern DOM_SID global_sam_sid; GROUP_MAP map; - sid_copy(psid, &global_sam_sid); + sid_copy(psid, get_global_sam_sid()); if (get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) { sid_copy(psid, &map.sid); - } + } else { sid_append_rid(psid, pdb_gid_to_group_rid(gid)); } @@ -860,11 +870,9 @@ DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid) BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type) { - extern DOM_SID global_sam_sid; DOM_SID dom_sid; uint32 rid; fstring str; - struct group *grp; GROUP_MAP map; *name_type = SID_NAME_UNKNOWN; @@ -879,7 +887,7 @@ BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type) * Or in the Builtin SID too. JFM, 11/30/2001 */ - if (!sid_equal(&global_sam_sid, &dom_sid)) + if (!sid_equal(get_global_sam_sid(), &dom_sid)) return False; if (get_group_map_from_sid(*psid, &map, MAPPING_WITHOUT_PRIV)) { @@ -888,27 +896,26 @@ BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type) if (map.gid==-1) return False; - sid_peek_rid(&map.sid, &rid); + if (!sid_peek_check_rid(get_global_sam_sid(), &map.sid, &rid)){ + DEBUG(0,("local_sid_to_gid: sid_peek_check_rid return False! SID: %s\n", + sid_string_static(&map.sid))); + return False; + } *pgid = map.gid; *name_type = map.sid_name_use; + DEBUG(10,("local_sid_to_gid: mapped SID %s (%s) -> gid (%u).\n", sid_to_string( str, psid), + map.nt_name, (unsigned int)*pgid)); + } else { if (pdb_rid_is_user(rid)) return False; *pgid = pdb_group_rid_to_gid(rid); *name_type = SID_NAME_ALIAS; + DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u).\n", sid_to_string( str, psid), + (unsigned int)*pgid)); } - /* - * Ensure this gid really does exist. - */ - - if(!(grp = getgrgid(*pgid))) - return False; - - DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u) (%s).\n", sid_to_string( str, psid), - (unsigned int)*pgid, grp->gr_name )); - return True; } @@ -917,7 +924,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; @@ -929,122 +936,6 @@ static char *pdb_convert(const UNISTR2 *from) return convert_buffer; } -/************************************************************* - Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT - **************************************************************/ - -void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from) -{ - - if (from == NULL || to == NULL) - return; - - pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time), True); - pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time), True); - pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time), True); - pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time), True); - pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time), True); - - 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 )); - if (from->uni_full_name.buffer) - pdb_set_fullname(to , pdb_convert(&from->uni_full_name )); - if (from->uni_home_dir.buffer) - pdb_set_homedir(to , pdb_convert(&from->uni_home_dir ), True); - if (from->uni_dir_drive.buffer) - pdb_set_dir_drive(to , pdb_convert(&from->uni_dir_drive ), True); - if (from->uni_logon_script.buffer) - pdb_set_logon_script(to , pdb_convert(&from->uni_logon_script), True); - if (from->uni_profile_path.buffer) - pdb_set_profile_path(to , pdb_convert(&from->uni_profile_path), True); - if (from->uni_acct_desc.buffer) - pdb_set_acct_desc(to , pdb_convert(&from->uni_acct_desc )); - if (from->uni_workstations.buffer) - pdb_set_workstations(to , pdb_convert(&from->uni_workstations)); - if (from->uni_unknown_str.buffer) - pdb_set_unknown_str(to , pdb_convert(&from->uni_unknown_str )); - if (from->uni_munged_dial.buffer) - pdb_set_munged_dial(to , pdb_convert(&from->uni_munged_dial )); - - if (from->user_rid) - pdb_set_user_rid(to, from->user_rid); - if (from->group_rid) - pdb_set_group_rid(to, from->group_rid); - - pdb_set_acct_ctrl(to, from->acb_info); - pdb_set_unknown_3(to, from->unknown_3); - - pdb_set_logon_divs(to, from->logon_divs); - pdb_set_hours_len(to, from->logon_hrs.len); - pdb_set_hours(to, from->logon_hrs.hours); - - pdb_set_unknown_5(to, from->unknown_5); - pdb_set_unknown_6(to, from->unknown_6); -} - - -/************************************************************* - Copies a sam passwd. - **************************************************************/ - -void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) -{ - if (from == NULL || to == NULL) - return; - - pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time), True); - pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time), True); - pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time), True); - pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time), True); - pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time), True); - - 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 )); - if (from->uni_full_name.buffer) - pdb_set_fullname(to , pdb_convert(&from->uni_full_name )); - if (from->uni_home_dir.buffer) - pdb_set_homedir(to , pdb_convert(&from->uni_home_dir ), True); - if (from->uni_dir_drive.buffer) - pdb_set_dir_drive(to , pdb_convert(&from->uni_dir_drive ), True); - if (from->uni_logon_script.buffer) - pdb_set_logon_script(to , pdb_convert(&from->uni_logon_script), True); - if (from->uni_profile_path.buffer) - pdb_set_profile_path(to , pdb_convert(&from->uni_profile_path), True); - if (from->uni_acct_desc.buffer) - pdb_set_acct_desc(to , pdb_convert(&from->uni_acct_desc )); - if (from->uni_workstations.buffer) - pdb_set_workstations(to , pdb_convert(&from->uni_workstations)); - if (from->uni_unknown_str.buffer) - pdb_set_unknown_str(to , pdb_convert(&from->uni_unknown_str )); - if (from->uni_munged_dial.buffer) - pdb_set_munged_dial(to , pdb_convert(&from->uni_munged_dial )); - - if (from->user_rid) - pdb_set_user_rid(to, from->user_rid); - if (from->group_rid) - pdb_set_group_rid(to, from->group_rid); - - /* FIXME!! Do we need to copy the passwords here as well? - I don't know. Need to figure this out --jerry */ - - /* Passwords dealt with in caller --abartlet */ - - pdb_set_acct_ctrl(to, from->acb_info); - pdb_set_unknown_3(to, from->unknown_3); - - pdb_set_logon_divs(to, from->logon_divs); - pdb_set_hours_len(to, from->logon_hrs.len); - pdb_set_hours(to, from->logon_hrs.hours); - - pdb_set_unknown_5(to, from->unknown_5); - pdb_set_unknown_6(to, from->unknown_6); -} - - /************************************************************* Change a password entry in the local smbpasswd file. diff --git a/source3/passdb/passgrp.c b/source3/passdb/passgrp.c index d7ed965648..f73591793f 100644 --- a/source3/passdb/passgrp.c +++ b/source3/passdb/passgrp.c @@ -21,6 +21,9 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB + /* * NOTE. All these functions are abstracted into a structure * that points to the correct function for the selected database. JRA. diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index cf77efd38f..dff4b40f4d 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -5,6 +5,7 @@ Copyright (C) Luke Kenneth Casson Leighton 1996-1998 Copyright (C) Gerald (Jerry) Carter 2000-2001 Copyright (C) Andrew Bartlett 2001-2002 + Copyright (C) Stefan (metze) Metzmacher 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 @@ -23,6 +24,9 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB + /** * @todo Redefine this to NULL, but this changes the API becouse * much of samba assumes that the pdb_get...() funtions @@ -138,22 +142,36 @@ const uint8* pdb_get_lanman_passwd (const SAM_ACCOUNT *sampass) return (NULL); } -uint32 pdb_get_user_rid (const SAM_ACCOUNT *sampass) +/* 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 (sampass->private.user_rid); + if (sampass) { + return ((char*)sampass->private.plaintext_pw.data); + } else - return (-1); + return (NULL); } - -uint32 pdb_get_group_rid (const SAM_ACCOUNT *sampass) +const DOM_SID *pdb_get_user_sid(const SAM_ACCOUNT *sampass) { - if (sampass) - return (sampass->private.group_rid); + if (sampass) + return &sampass->private.user_sid; else - return (-1); + return (NULL); } +const DOM_SID *pdb_get_group_sid(const SAM_ACCOUNT *sampass) +{ + if (sampass) + return &sampass->private.group_sid; + else + return (NULL); +} + /** * Get flags showing what is initalised in the SAM_ACCOUNT * @param sampass the SAM_ACCOUNT in question @@ -224,6 +242,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) @@ -461,27 +487,72 @@ BOOL pdb_set_gid (SAM_ACCOUNT *sampass, const gid_t gid) } -BOOL pdb_set_user_rid (SAM_ACCOUNT *sampass, uint32 rid) +BOOL pdb_set_user_sid (SAM_ACCOUNT *sampass, DOM_SID *u_sid) { - if (!sampass) + if (!sampass || !u_sid) return False; + + sid_copy(&sampass->private.user_sid, u_sid); - DEBUG(10, ("pdb_set_rid: setting user rid %d, was %d\n", - rid, sampass->private.user_rid)); - - sampass->private.user_rid = rid; + DEBUG(10, ("pdb_set_user_sid: setting user sid %s\n", + sid_string_static(&sampass->private.user_sid))); + return True; } -BOOL pdb_set_group_rid (SAM_ACCOUNT *sampass, uint32 grid) +BOOL pdb_set_user_sid_from_string (SAM_ACCOUNT *sampass, fstring u_sid) { - if (!sampass) + DOM_SID new_sid; + if (!sampass || !u_sid) return False; - DEBUG(10, ("pdb_set_group_rid: setting group rid %d, was %d\n", - grid, sampass->private.group_rid)); - - sampass->private.group_rid = grid; + DEBUG(10, ("pdb_set_user_sid_from_string: setting user sid %s\n", + u_sid)); + + if (!string_to_sid(&new_sid, u_sid)) { + DEBUG(1, ("pdb_set_user_sid_from_string: %s isn't a valid SID!\n", u_sid)); + return False; + } + + if (!pdb_set_user_sid(sampass, &new_sid)) { + DEBUG(1, ("pdb_set_user_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", u_sid)); + return False; + } + + return True; +} + +BOOL pdb_set_group_sid (SAM_ACCOUNT *sampass, DOM_SID *g_sid) +{ + if (!sampass || !g_sid) + return False; + + sid_copy(&sampass->private.group_sid, g_sid); + + DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n", + sid_string_static(&sampass->private.group_sid))); + + return True; +} + +BOOL pdb_set_group_sid_from_string (SAM_ACCOUNT *sampass, fstring g_sid) +{ + DOM_SID new_sid; + if (!sampass || !g_sid) + return False; + + DEBUG(10, ("pdb_set_group_sid_from_string: setting group sid %s\n", + g_sid)); + + if (!string_to_sid(&new_sid, g_sid)) { + DEBUG(1, ("pdb_set_group_sid_from_string: %s isn't a valid SID!\n", g_sid)); + return False; + } + + if (!pdb_set_group_sid(sampass, &new_sid)) { + DEBUG(1, ("pdb_set_group_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", g_sid)); + return False; + } return True; } @@ -618,7 +689,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 +721,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 +753,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); } @@ -714,13 +785,41 @@ BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, const char *home_dir, BOOL store) } if (store) { - DEBUG(10, ("pdb_set_homedir: setting home dir sam flag!")); + DEBUG(10, ("pdb_set_homedir: setting home dir sam flag!\n")); pdb_set_init_flag(sampass, FLAG_SAM_SMBHOME); } 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_unix_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 +939,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 +951,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 435b627da6..3b0f54b2b3 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -1,18 +1,19 @@ /* Unix SMB/CIFS implementation. Password and authentication handling - Copyright (C) Andrew Bartlett 2002 - + Copyright (C) Andrew Bartlett 2002 + 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. @@ -20,6 +21,9 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB + /** List of various built-in passdb modules */ const struct pdb_init_function_entry builtin_pdb_init_functions[] = { @@ -29,102 +33,199 @@ 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 }, -#if 0 - { "nisplus", pdb_init_nisplus }, - { "unix", pdb_init_unix }, -#endif + { "unixsam", pdb_init_unixsam }, { "plugin", pdb_init_plugin }, { NULL, NULL} }; static BOOL context_setsampwent(struct pdb_context *context, BOOL update) { - if ((!context) || (!context->pdb_selected)) { + if ((!context) || (!context->pdb_methods) || (!context->pdb_methods->setsampwent)) { DEBUG(0, ("invalid pdb_context specified!\n")); return False; } - - return context->pdb_selected->setsampwent(context, 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; + } + return True; } static void context_endsampwent(struct pdb_context *context) { - if ((!context) || (!context->pdb_selected)) { + if ((!context)){ DEBUG(0, ("invalid pdb_context specified!\n")); return; } - - context->pdb_selected->endsampwent(context); + + if (context->pwent_methods && context->pwent_methods->endsampwent) + context->pwent_methods->endsampwent(context->pwent_methods); + + /* So we won't get strange data when calling getsampwent now */ + context->pwent_methods = NULL; } static BOOL context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user) { - if ((!context) || (!context->pdb_selected)) { + if ((!context) || (!context->pwent_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); return False; } + /* Loop until we find something useful */ + while ((!context->pwent_methods->getsampwent) || + context->pwent_methods->getsampwent(context->pwent_methods, user) == False){ + + if (context->pwent_methods->endsampwent) + context->pwent_methods->endsampwent(context->pwent_methods); + + context->pwent_methods = context->pwent_methods->next; + + /* All methods are checked now. There are no more entries */ + if (context->pwent_methods == NULL) + return False; - return context->pdb_selected->getsampwent(context, user); + if (!context->pwent_methods->setsampwent){ + DEBUG(5, ("next backend does not implment setsampwent\n")); + return False; + } + + context->pwent_methods->setsampwent(context->pwent_methods, False); + } + user->methods = context->pwent_methods; + return True; } static BOOL context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username) { - if ((!context) || (!context->pdb_selected)) { + struct pdb_methods *curmethods; + if ((!context)) { DEBUG(0, ("invalid pdb_context specified!\n")); return False; } - - return context->pdb_selected->getsampwnam(context, sam_acct, username); + curmethods = context->pdb_methods; + while (curmethods){ + if (curmethods->getsampwnam && curmethods->getsampwnam(curmethods, sam_acct, username) == True){ + sam_acct->methods = curmethods; + return True; + } + curmethods = curmethods->next; + } + + return False; } -static BOOL context_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, uint32 rid) +static BOOL context_getsampwsid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, DOM_SID *sid) { - if ((!context) || (!context->pdb_selected)) { + struct pdb_methods *curmethods; + if ((!context)) { DEBUG(0, ("invalid pdb_context specified!\n")); return False; } - return context->pdb_selected->getsampwrid(context, sam_acct, rid); + curmethods = context->pdb_methods; + + while (curmethods){ + if (curmethods->getsampwsid && curmethods->getsampwsid(curmethods, sam_acct, sid) == True){ + sam_acct->methods = curmethods; + return True; + } + curmethods = curmethods->next; + } + + return False; } static BOOL context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) { - if ((!context) || (!context->pdb_selected)) { + if ((!context) || (!context->pdb_methods) || (!context->pdb_methods->add_sam_account)) { DEBUG(0, ("invalid pdb_context specified!\n")); return False; } - + /** @todo This is where a 're-read on add' should be done */ - - return context->pdb_selected->add_sam_account(context, sam_acct); + /* We now add a new account to the first database listed. + * Should we? */ + + return context->pdb_methods->add_sam_account(context->pdb_methods, sam_acct); } static BOOL context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) { - if ((!context) || (!context->pdb_selected)) { + if (!context) { DEBUG(0, ("invalid pdb_context specified!\n")); return False; } - + + if (!sam_acct || !sam_acct->methods){ + DEBUG(0, ("invalid sam_acct specified\n")); + return False; + } + + if (!sam_acct->methods->update_sam_account){ + DEBUG(0, ("invalid sam_acct->methods\n")); + return False; + } + /** @todo This is where a 're-read on update' should be done */ - - return context->pdb_selected->update_sam_account(context, sam_acct); + + return sam_acct->methods->update_sam_account(sam_acct->methods, sam_acct); } static BOOL context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) { - if ((!context) || (!context->pdb_selected)) { + struct pdb_methods *pdb_selected; + if (!context) { DEBUG(0, ("invalid pdb_context specified!\n")); return False; } + + if (!sam_acct->methods){ + pdb_selected = context->pdb_methods; + /* There's no passdb backend specified for this account. + * Try to delete it in every passdb available + * Needed to delete accounts in smbpasswd that are not + * in /etc/passwd. + */ + while (pdb_selected){ + if (pdb_selected->delete_sam_account && pdb_selected->delete_sam_account(pdb_selected, sam_acct)){ + return True; + } + pdb_selected = pdb_selected->next; + } + return False; + } + + if (!sam_acct->methods->delete_sam_account){ + DEBUG(0,("invalid sam_acct->methods->delete_sam_account\n")); + return False; + } - return context->pdb_selected->delete_sam_account(context, sam_acct); + return sam_acct->methods->delete_sam_account(sam_acct->methods, sam_acct); } +/****************************************************************** + Free and cleanup a pdb context, any associated data and anything + that the attached modules might have associated. + *******************************************************************/ + static void free_pdb_context(struct pdb_context **context) { - if (((*context)->pdb_selected) && ((*context)->pdb_selected->free_private_data)) { - (*context)->pdb_selected->free_private_data((*context)->pdb_selected->private_data); + struct pdb_methods *pdb_selected = (*context)->pdb_methods; + + while (pdb_selected){ + if (pdb_selected->free_private_data) { + pdb_selected->free_private_data(&(pdb_selected->private_data)); + } + pdb_selected = pdb_selected->next; } talloc_destroy((*context)->mem_ctx); @@ -132,13 +233,57 @@ static void free_pdb_context(struct pdb_context **context) } /****************************************************************** - Make a pdb_context from scratch. -*******************************************************************/ + Make a pdb_methods from scratch + *******************************************************************/ + +static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_context *context, const char *selected) +{ + char *module_name = smb_xstrdup(selected); + char *module_location = NULL, *p; + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + int i; + + p = strchr(module_name, ':'); + + if (p) { + *p = 0; + module_location = p+1; + trim_string(module_location, " ", " "); + } + + trim_string(module_name, " ", " "); + + DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", selected, module_name)); + for (i = 0; builtin_pdb_init_functions[i].name; i++) + { + if (strequal(builtin_pdb_init_functions[i].name, module_name)) + { + DEBUG(5,("Found pdb backend %s (at pos %d)\n", module_name, i)); + nt_status = builtin_pdb_init_functions[i].init(context, methods, module_location); + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(5,("pdb backend %s has a valid init\n", selected)); + } else { + DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, nt_errstr(nt_status))); + } + SAFE_FREE(module_name); + return nt_status; + break; /* unreached */ + } + } + + /* No such backend found */ + SAFE_FREE(module_name); + return NT_STATUS_INVALID_PARAMETER; +} + +/****************************************************************** + Make a pdb_context from scratch. + *******************************************************************/ static NTSTATUS make_pdb_context(struct pdb_context **context) { TALLOC_CTX *mem_ctx; - + mem_ctx = talloc_init_named("pdb_context internal allocation context"); if (!mem_ctx) { @@ -160,82 +305,60 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_endsampwent = context_endsampwent; (*context)->pdb_getsampwent = context_getsampwent; (*context)->pdb_getsampwnam = context_getsampwnam; - (*context)->pdb_getsampwrid = context_getsampwrid; + (*context)->pdb_getsampwsid = context_getsampwsid; (*context)->pdb_add_sam_account = context_add_sam_account; (*context)->pdb_update_sam_account = context_update_sam_account; (*context)->pdb_delete_sam_account = context_delete_sam_account; (*context)->free_fn = free_pdb_context; - + return NT_STATUS_OK; } /****************************************************************** - Make a pdb_context, given a text string. -*******************************************************************/ + Make a pdb_context, given an array of strings + *******************************************************************/ -NTSTATUS make_pdb_context_name(struct pdb_context **context, const char *selected) +NTSTATUS make_pdb_context_list(struct pdb_context **context, char **selected) { - /* HINT: Don't store 'selected' becouse its often an lp_ string and - will 'go away' */ + int i = 0; + struct pdb_methods *curmethods, *tmpmethods; NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - int i; - char *module_name = smb_xstrdup(selected); - char *module_location = NULL; - char *p; - p = strchr(module_name, ':'); - - if (p) { - *p = 0; - - module_location = p+1; - - trim_string(module_location, " ", " "); + if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) { + return nt_status; } - trim_string(module_name, " ", " "); - - if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) - goto done; - - DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", - selected, module_name)); - - for (i = 0; builtin_pdb_init_functions[i].name; i++) { - if (strequal(builtin_pdb_init_functions[i].name, - module_name)) { - - DEBUG(5,("Found pdb backend %s (at pos %d)\n", - module_name, i)); - - if (NT_STATUS_IS_OK(nt_status = builtin_pdb_init_functions[i].init(*context, &(*context)->pdb_selected, module_location))) { - DEBUG(5,("pdb backend %s has a valid init\n", selected)); - } else { - DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, nt_errstr(nt_status))); - (*context)->pdb_selected = NULL; - } - break; + while (selected[i]){ + /* Try to initialise pdb */ + DEBUG(5,("Trying to load: %s\n", selected[i])); + if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods, *context, selected[i]))) { + DEBUG(1, ("Loading %s failed!\n", selected[i])); + free_pdb_context(context); + return nt_status; } - } - - if (!(*context)->pdb_selected) { - DEBUG(0,("failed to select passdb backed!\n")); - talloc_destroy((*context)->mem_ctx); - *context = NULL; - goto done; + curmethods->parent = *context; + DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods); + i++; } - nt_status = NT_STATUS_OK; + return NT_STATUS_OK; +} - done: - SAFE_FREE(module_name); +/****************************************************************** + Make a pdb_context, given a text string. + *******************************************************************/ - return nt_status; +NTSTATUS make_pdb_context_string(struct pdb_context **context, const char *selected) +{ + NTSTATUS ret; + char **newsel = str_list_make(selected); + ret = make_pdb_context_list(context, newsel); + str_list_free(&newsel); + return ret; } - /****************************************************************** Return an already initialised pdb_context, to facilitate backward compatibility (see functions below). @@ -244,20 +367,20 @@ NTSTATUS make_pdb_context_name(struct pdb_context **context, const char *selecte static struct pdb_context *pdb_get_static_context(BOOL reload) { static struct pdb_context *pdb_context = NULL; - + if ((pdb_context) && (reload)) { pdb_context->free_fn(&pdb_context); - if (!NT_STATUS_IS_OK(make_pdb_context_name(&pdb_context, lp_passdb_backend()))) { + if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) { return NULL; } } - + if (!pdb_context) { - if (!NT_STATUS_IS_OK(make_pdb_context_name(&pdb_context, lp_passdb_backend()))) { + if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) { return NULL; } } - + return pdb_context; } @@ -311,7 +434,7 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) return pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username); } -BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct, uint32 rid) +BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, DOM_SID *sid) { struct pdb_context *pdb_context = pdb_get_static_context(False); @@ -319,7 +442,7 @@ BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct, uint32 rid) return False; } - return pdb_context->pdb_getsampwrid(pdb_context, sam_acct, rid); + return pdb_context->pdb_getsampwsid(pdb_context, sam_acct, sid); } BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct) @@ -347,21 +470,21 @@ BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct) BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) { struct pdb_context *pdb_context = pdb_get_static_context(False); - + if (!pdb_context) { return False; } - + return pdb_context->pdb_delete_sam_account(pdb_context, sam_acct); } #endif /* !defined(WITH_NISPLUS_SAM) */ /*************************************************************** - Initialize the static context (at smbd startup etc). + Initialize the static context (at smbd startup etc). - If uninitialised, context will auto-init on first use. -***************************************************************/ + If uninitialised, context will auto-init on first use. + ***************************************************************/ BOOL initialize_password_db(BOOL reload) { @@ -381,11 +504,3 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) return NT_STATUS_OK; } - - - - - - - - diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 02bb43b7ff..24eb7b9dc1 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -24,7 +24,10 @@ #include "includes.h" -#ifdef WITH_LDAP_SAM +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB + +#ifdef HAVE_LDAP /* TODO: * persistent connections: if using NSS LDAP, many connections are made * however, using only one within Samba would be nice @@ -71,56 +74,78 @@ struct ldapsam_privates { static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state); -/******************************************************************* - Converts NT user RID to a UNIX uid. - ********************************************************************/ - -static uid_t pdb_user_rid_to_uid(uint32 user_rid) -{ - return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER); -} - -/******************************************************************* - converts UNIX uid to an NT User RID. - ********************************************************************/ - -static uint32 pdb_uid_to_user_rid(uid_t uid) -{ - return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE); -} - /******************************************************************* find the ldap password ******************************************************************/ -static BOOL fetch_ldapsam_pw(char *dn, char* pw, int len) +static BOOL fetch_ldapsam_pw(char **dn, char** pw) { - fstring key; - char *p; - void *data = NULL; + char *key = NULL; size_t size; - pstrcpy(key, dn); - for (p=key; *p; p++) - if (*p == ',') *p = '/'; + *dn = smb_xstrdup(lp_ldap_admin_dn()); - data=secrets_fetch(key, &size); - if (!size) { - DEBUG(0,("fetch_ldap_pw: no ldap secret retrieved!\n")); - return False; + if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { + SAFE_FREE(*dn); + DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n")); } - if (size > len-1) - { - DEBUG(0,("fetch_ldap_pw: ldap secret is too long (%d > %d)!\n", size, len-1)); - return False; - } + *pw=secrets_fetch(key, &size); + if (!size) { + /* Upgrade 2.2 style entry */ + char *p; + char* old_style_key = strdup(*dn); + char *data; + fstring old_style_pw; + + if (!old_style_key) { + DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n")); + return False; + } - memcpy(pw, data, size); - pw[size] = '\0'; + for (p=old_style_key; *p; p++) + if (*p == ',') *p = '/'; + + data=secrets_fetch(old_style_key, &size); + if (!size && size < sizeof(old_style_pw)) { + DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); + SAFE_FREE(old_style_key); + SAFE_FREE(*dn); + return False; + } + + strncpy(old_style_pw, data, size); + old_style_pw[size] = 0; + + SAFE_FREE(data); + + if (!secrets_store_ldap_pw(*dn, old_style_pw)) { + DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); + SAFE_FREE(old_style_key); + SAFE_FREE(*dn); + return False; + } + if (!secrets_delete(old_style_key)) { + DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); + } + + SAFE_FREE(old_style_key); + + *pw = smb_xstrdup(old_style_pw); + } return True; } +static const char *attr[] = {"uid", "pwdLastSet", "logonTime", + "logoffTime", "kickoffTime", "cn", + "pwdCanChange", "pwdMustChange", + "displayName", "homeDrive", + "smbHome", "scriptPath", + "profilePath", "description", + "userWorkstations", "rid", + "primaryGroupID", "lmPassword", + "ntPassword", "acctFlags", + "domain", "description", NULL }; /******************************************************************* open a connection to the ldap server. @@ -225,20 +250,57 @@ static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP * return True; } + +/******************************************************************* + Add a rebind function for authenticated referrals +******************************************************************/ + +static int rebindproc (LDAP *ldap_struct, char **whop, char **credp, + int *method, int freeit ) +{ + int rc; + char *ldap_dn; + char *ldap_secret; + + /** @TODO Should we be doing something to check what servers we rebind to? + Could we get a referral to a machine that we don't want to give our + username and password to? */ + + if (freeit != 0) + { + + if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret)) + { + DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); + return LDAP_OPERATIONS_ERROR; /* No idea what to return */ + } + + DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n", + ldap_dn)); + + rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret); + + SAFE_FREE(ldap_dn); + SAFE_FREE(ldap_secret); + + return rc; + } + return 0; +} + /******************************************************************* connect to the ldap server under system privilege. ******************************************************************/ static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct) { int rc; - static BOOL got_pw = False; - static pstring ldap_secret; + char *ldap_dn; + char *ldap_secret; - /* get the password if we don't have it already */ - if (!got_pw && !(got_pw=fetch_ldapsam_pw(lp_ldap_admin_dn(), ldap_secret, sizeof(pstring)))) + /* get the password */ + if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret)) { - DEBUG(0, ("ldap_connect_system: Failed to retrieve password for %s from secrets.tdb\n", - lp_ldap_admin_dn())); + DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); return False; } @@ -246,10 +308,16 @@ static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * l (OpenLDAP) doesnt' seem to support it */ DEBUG(10,("ldap_connect_system: Binding to ldap server as \"%s\"\n", - lp_ldap_admin_dn())); - - if ((rc = ldap_simple_bind_s(ldap_struct, lp_ldap_admin_dn(), - ldap_secret)) != LDAP_SUCCESS) + ldap_dn)); + + ldap_set_rebind_proc(ldap_struct, (LDAP_REBIND_PROC *)(&rebindproc)); + + rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret); + + SAFE_FREE(ldap_dn); + SAFE_FREE(ldap_secret); + + if (rc != LDAP_SUCCESS) { DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc))); return False; @@ -269,7 +337,7 @@ static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, LDAP * DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter)); - rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, NULL, 0, result); + rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, attr, 0, result); if (rc != LDAP_SUCCESS) { DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n", @@ -347,7 +415,7 @@ static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state, if (rc != LDAP_SUCCESS) rc = ldapsam_search_one_user_by_uid(ldap_state, ldap_struct, - pdb_user_rid_to_uid(rid), + fallback_pdb_user_rid_to_uid(rid), result); return rc; @@ -357,7 +425,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,10 +589,14 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, get_single_attribute(ldap_struct, entry, "rid", temp); user_rid = (uint32)atol(temp); + + pdb_set_user_sid_from_rid(sampass, user_rid); + if (!get_single_attribute(ldap_struct, entry, "primaryGroupID", temp)) { group_rid = 0; } else { group_rid = (uint32)atol(temp); + pdb_set_group_sid_from_rid(sampass, group_rid); } if ((ldap_state->permit_non_unix_accounts) @@ -539,12 +611,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 ave a uid!\n", username)); + DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\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); @@ -554,10 +628,10 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, GROUP_MAP map; /* call the mapping code here */ if(get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) { - sid_peek_rid(&map.sid, &group_rid); + pdb_set_group_sid(sampass, &map.sid); } else { - group_rid=pdb_gid_to_group_rid(gid); + pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid)); } } } @@ -621,37 +695,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, talloc_sub_specified(sampass->mem_ctx, + lp_logon_drive(), + 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_homedir(sampass, talloc_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, talloc_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, talloc_sub_specified(sampass->mem_ctx, + lp_logon_path(), + username, domain, + uid, gid), + False); } else { pdb_set_profile_path(sampass, profile_path, True); } @@ -706,9 +784,6 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_hours_len(sampass, hours_len); pdb_set_logon_divs(sampass, logon_divs); - pdb_set_user_rid(sampass, user_rid); - pdb_set_group_rid(sampass, group_rid); - pdb_set_username(sampass, username); pdb_set_domain(sampass, domain); @@ -754,7 +829,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, if ( pdb_get_user_rid(sampass) ) { rid = pdb_get_user_rid(sampass); } else if (IS_SAM_SET(sampass, FLAG_SAM_UID)) { - rid = pdb_uid_to_user_rid(pdb_get_uid(sampass)); + rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass)); } else if (ldap_state->permit_non_unix_accounts) { rid = ldapsam_get_next_available_nua_rid(ldap_state); if (rid == 0) { @@ -932,7 +1007,7 @@ static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state, LDAP *ldap DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter)); rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, final_filter, NULL, 0, + LDAP_SCOPE_SUBTREE, final_filter, attr, 0, &result); if (rc != LDAP_SUCCESS) @@ -973,6 +1048,10 @@ static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state, LDAP *ldap } ldap_msgfree(result); + + if (top_rid < ldap_state->low_nua_rid) + top_rid = ldap_state->low_nua_rid; + return top_rid; } @@ -1006,9 +1085,9 @@ static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_s /********************************************************************** Connect to LDAP server for password enumeration *********************************************************************/ -static BOOL ldapsam_setsampwent(struct pdb_context *context, BOOL update) +static BOOL ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update) { - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; int rc; pstring filter; @@ -1026,7 +1105,7 @@ static BOOL ldapsam_setsampwent(struct pdb_context *context, BOOL update) all_string_sub(filter, "%u", "*", sizeof(pstring)); rc = ldap_search_s(ldap_state->ldap_struct, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, NULL, 0, + LDAP_SCOPE_SUBTREE, filter, attr, 0, &ldap_state->result); if (rc != LDAP_SUCCESS) @@ -1054,9 +1133,9 @@ static BOOL ldapsam_setsampwent(struct pdb_context *context, BOOL update) /********************************************************************** End enumeration of the LDAP password list *********************************************************************/ -static void ldapsam_endsampwent(struct pdb_context *context) +static void ldapsam_endsampwent(struct pdb_methods *my_methods) { - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; if (ldap_state->ldap_struct && ldap_state->result) { ldap_msgfree(ldap_state->result); @@ -1069,9 +1148,9 @@ static void ldapsam_endsampwent(struct pdb_context *context) /********************************************************************** Get the next entry in the LDAP password database *********************************************************************/ -static BOOL ldapsam_getsampwent(struct pdb_context *context, SAM_ACCOUNT * user) +static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * user) { - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; BOOL ret = False; while (!ret) { @@ -1093,9 +1172,9 @@ static BOOL ldapsam_getsampwent(struct pdb_context *context, SAM_ACCOUNT * user) /********************************************************************** Get SAM_ACCOUNT entry from LDAP by username *********************************************************************/ -static BOOL ldapsam_getsampwnam(struct pdb_context *context, SAM_ACCOUNT * user, const char *sname) +static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const char *sname) { - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; LDAP *ldap_struct; LDAPMessage *result; LDAPMessage *entry; @@ -1144,9 +1223,9 @@ static BOOL ldapsam_getsampwnam(struct pdb_context *context, SAM_ACCOUNT * user, /********************************************************************** Get SAM_ACCOUNT entry from LDAP by rid *********************************************************************/ -static BOOL ldapsam_getsampwrid(struct pdb_context *context, SAM_ACCOUNT * user, uint32 rid) +static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, uint32 rid) { - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; LDAP *ldap_struct; LDAPMessage *result; LDAPMessage *entry; @@ -1196,12 +1275,20 @@ static BOOL ldapsam_getsampwrid(struct pdb_context *context, SAM_ACCOUNT * user, } } +static BOOL ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid) +{ + uint32 rid; + if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) + return False; + return ldapsam_getsampwrid(my_methods, user, rid); +} + /********************************************************************** Delete entry from LDAP for username *********************************************************************/ -static BOOL ldapsam_delete_sam_account(struct pdb_context *context, const SAM_ACCOUNT * sam_acct) +static BOOL ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct) { - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; const char *sname; int rc; char *dn; @@ -1259,9 +1346,9 @@ static BOOL ldapsam_delete_sam_account(struct pdb_context *context, const SAM_AC /********************************************************************** Update SAM_ACCOUNT *********************************************************************/ -static BOOL ldapsam_update_sam_account(struct pdb_context *context, const SAM_ACCOUNT * newpwd) +static BOOL ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd) { - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; int rc; char *dn; LDAP *ldap_struct; @@ -1326,9 +1413,9 @@ static BOOL ldapsam_update_sam_account(struct pdb_context *context, const SAM_AC /********************************************************************** Add SAM_ACCOUNT to LDAP *********************************************************************/ -static BOOL ldapsam_add_sam_account(struct pdb_context *context, const SAM_ACCOUNT * newpwd) +static BOOL ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd) { - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; int rc; pstring filter; LDAP *ldap_struct = NULL; @@ -1463,7 +1550,7 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, co (*pdb_method)->endsampwent = ldapsam_endsampwent; (*pdb_method)->getsampwent = ldapsam_getsampwent; (*pdb_method)->getsampwnam = ldapsam_getsampwnam; - (*pdb_method)->getsampwrid = ldapsam_getsampwrid; + (*pdb_method)->getsampwsid = ldapsam_getsampwsid; (*pdb_method)->add_sam_account = ldapsam_add_sam_account; (*pdb_method)->update_sam_account = ldapsam_update_sam_account; (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account; @@ -1511,9 +1598,9 @@ NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method return NT_STATUS_UNSUCCESSFUL; } - ldap_state->low_nua_rid=pdb_uid_to_user_rid(low_nua_uid); + ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid); - ldap_state->high_nua_rid=pdb_uid_to_user_rid(high_nua_uid); + ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid); return NT_STATUS_OK; } @@ -1523,13 +1610,13 @@ NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { - DEBUG(0, ("ldapsam not compiled in!\n")); + DEBUG(0, ("ldap not detected at configure time, ldapsam not availalble!\n")); return NT_STATUS_UNSUCCESSFUL; } NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { - DEBUG(0, ("ldapsam_nua not compiled in!\n")); + DEBUG(0, ("ldap not dectected at configure time, ldapsam_nua not available!\n")); return NT_STATUS_UNSUCCESSFUL; } diff --git a/source3/passdb/pdb_nisplus.c b/source3/passdb/pdb_nisplus.c index 145e1d4f0c..9c5b2e1171 100644 --- a/source3/passdb/pdb_nisplus.c +++ b/source3/passdb/pdb_nisplus.c @@ -56,7 +56,7 @@ struct nisp_enum_info }; static struct nisp_enum_info global_nisp_ent; -static VOLATILE sig_atomic_t gotalarm; +static SIG_ATOMIC_T gotalarm; /*************************************************************** @@ -339,8 +339,8 @@ static BOOL make_sam_from_nisp_object(SAM_ACCOUNT *pw_buf, const nis_object *obj pdb_set_uid(pw_buf, atoi(ENTRY_VAL(obj, NPF_UID))); pdb_set_gid(pw_buf, atoi(ENTRY_VAL(obj, NPF_SMB_GRPID))); - pdb_set_user_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_USER_RID))); - pdb_set_group_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_GROUP_RID))); + pdb_set_user_sid_from_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_USER_RID))); + pdb_set_group_sid_from_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_GROUP_RID))); /* values, must exist for user */ if( !(pdb_get_acct_ctrl(pw_buf) & ACB_WSTRUST) ) { @@ -381,7 +381,7 @@ static BOOL make_sam_from_nisp_object(SAM_ACCOUNT *pw_buf, const nis_object *obj else { /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ - pdb_set_group_rid (pw_buf, DOMAIN_GROUP_RID_USERS); + pdb_set_group_sid_from_rid (pw_buf, DOMAIN_GROUP_RID_USERS); } /* Check the lanman password column. */ @@ -538,7 +538,8 @@ static BOOL init_nisp_from_sam(nis_object *obj, const SAM_ACCOUNT *sampass, if (rid==0) { if (get_group_map_from_gid(pdb_get_gid(sampass), &map, MAPPING_WITHOUT_PRIV)) { - sid_peek_rid(&map.sid, &rid); + if (!sid_peek_check_rid(get_global_sam_sid(), &map.sid, &rid)) + return False; } else rid=pdb_gid_to_group_rid(pdb_get_gid(sampass)); } @@ -1030,7 +1031,16 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT * user, const char *sname) /************************************************************************* Routine to search the nisplus passwd file for an entry matching the username *************************************************************************/ -BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid) + +BOOL pdb_getsampwsid(SAM_ACCOUNT * user, DOM_SID *sid) +{ + uint32 rid; + if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) + return False; + return pdb_getsampwrid(user, rid); +} + +static BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid) { nis_result *result; char *nisname; diff --git a/source3/passdb/pdb_plugin.c b/source3/passdb/pdb_plugin.c index 1de61abd5f..1a246631fe 100644 --- a/source3/passdb/pdb_plugin.c +++ b/source3/passdb/pdb_plugin.c @@ -21,11 +21,15 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB + NTSTATUS pdb_init_plugin(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { void * dl_handle; char *plugin_location, *plugin_name, *p; pdb_init_function plugin_init; + int (*plugin_version)(void); if (location == NULL) { DEBUG(0, ("The plugin module needs an argument!\n")); @@ -48,8 +52,23 @@ NTSTATUS pdb_init_plugin(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, con return NT_STATUS_UNSUCCESSFUL; } + plugin_version = sys_dlsym(dl_handle, "pdb_version"); + if (!plugin_version) { + sys_dlclose(dl_handle); + DEBUG(0, ("Failed to find function 'pdb_version' using sys_dlsym in sam plugin %s (%s)\n", plugin_name, sys_dlerror())); + return NT_STATUS_UNSUCCESSFUL; + } + + if (plugin_version()!=PASSDB_INTERFACE_VERSION) { + sys_dlclose(dl_handle); + DEBUG(0, ("Wrong PASSDB_INTERFACE_VERSION! sam plugin has version %d and version %d is needed! Please update!\n", + plugin_version(),PASSDB_INTERFACE_VERSION)); + return NT_STATUS_UNSUCCESSFUL; + } + plugin_init = sys_dlsym(dl_handle, "pdb_init"); - if (!plugin_init){ + if (!plugin_init) { + sys_dlclose(dl_handle); DEBUG(0, ("Failed to find function 'pdb_init' using sys_dlsym in sam plugin %s (%s)\n", plugin_name, sys_dlerror())); return NT_STATUS_UNSUCCESSFUL; } diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 89a4217c3b..8c7ba364b8 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -23,6 +23,8 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB /* smb_passwd is analogous to sam_passwd used everywhere @@ -69,24 +71,6 @@ struct smbpasswd_privates enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE }; -/******************************************************************* - Converts NT user RID to a UNIX uid. - ********************************************************************/ - -static uid_t pdb_user_rid_to_uid(uint32 user_rid) -{ - return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER); -} - -/******************************************************************* - converts UNIX uid to an NT User RID. - ********************************************************************/ - -static uint32 pdb_uid_to_user_rid(uid_t uid) -{ - return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE); -} - /*************************************************************** Lock an fd. Abandon after waitsecs seconds. ****************************************************************/ @@ -117,6 +101,10 @@ static BOOL pw_file_unlock(int fd, int *plock_depth) { BOOL ret=True; + if (fd == 0 || *plock_depth == 0) { + return True; + } + if(*plock_depth == 1) ret = do_file_lock(fd, 5, F_UNLCK); @@ -198,7 +186,7 @@ static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile)); if((fp = sys_fopen(pfile, open_mode)) == NULL) { - DEBUG(2, ("startsmbfilepwent_internal: unable to open file %s. Error was %s\n", pfile, strerror(errno) )); + DEBUG(0, ("startsmbfilepwent_internal: unable to open file %s. Error was %s\n", pfile, strerror(errno) )); return NULL; } @@ -280,10 +268,13 @@ Error was %s\n.", pfile, strerror(errno) )); ****************************************************************/ static void endsmbfilepwent(FILE *fp, int *lock_depth) { + if (!fp) { + return; + } - pw_file_unlock(fileno(fp), lock_depth); - fclose(fp); - DEBUG(7, ("endsmbfilepwent_internal: closed password file.\n")); + pw_file_unlock(fileno(fp), lock_depth); + fclose(fp); + DEBUG(7, ("endsmbfilepwent_internal: closed password file.\n")); } /************************************************************************* @@ -375,6 +366,8 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s * As 256 is shorter than a pstring we don't need to check * length here - if this ever changes.... */ + SMB_ASSERT(sizeof(pstring) > sizeof(linebuf)); + strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); user_name[PTR_DIFF(p, linebuf)] = '\0'; @@ -414,15 +407,6 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s /* Skip the ':' */ p++; - if (*p == '*' || *p == 'X') { - /* Password deliberately invalid - end here. */ - DEBUG(10, ("getsmbfilepwent: entry invalidated for user %s\n", user_name)); - pw_buf->smb_nt_passwd = NULL; - pw_buf->smb_passwd = NULL; - pw_buf->acct_ctrl |= ACB_DISABLED; - return pw_buf; - } - if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { DEBUG(0, ("getsmbfilepwent: malformed password entry (passwd too short)\n")); continue; @@ -437,11 +421,16 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s pw_buf->smb_passwd = NULL; pw_buf->acct_ctrl |= ACB_PWNOTREQ; } else { - if (!pdb_gethexpwd((char *)p, smbpwd)) { - DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n")); - continue; - } - pw_buf->smb_passwd = smbpwd; + if (*p == '*' || *p == 'X') { + /* NULL LM password */ + pw_buf->smb_passwd = NULL; + DEBUG(10, ("getsmbfilepwent: LM password for user %s invalidated\n", user_name)); + } else if (pdb_gethexpwd((char *)p, smbpwd)) { + pw_buf->smb_passwd = smbpwd; + } else { + pw_buf->smb_passwd = NULL; + DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n")); + } } /* @@ -524,7 +513,6 @@ static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd) int new_entry_length; char *new_entry; char *p; - int i; new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2; @@ -534,38 +522,16 @@ static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd) } slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->smb_name, (unsigned)newpwd->smb_userid); - p = &new_entry[strlen(new_entry)]; - if(newpwd->smb_passwd != NULL) { - for( i = 0; i < 16; i++) { - slprintf((char *)&p[i*2], new_entry_length - (p - new_entry) - 1, "%02X", newpwd->smb_passwd[i]); - } - } else { - i=0; - if(newpwd->acct_ctrl & ACB_PWNOTREQ) - safe_strcpy((char *)p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry)); - else - safe_strcpy((char *)p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry)); - } + p = new_entry+strlen(new_entry); - p += 32; + pdb_sethexpwd(p, newpwd->smb_passwd, newpwd->acct_ctrl); - *p++ = ':'; + p+=strlen(p); *p = ':'; p++; - if(newpwd->smb_nt_passwd != NULL) { - for( i = 0; i < 16; i++) { - slprintf((char *)&p[i*2], new_entry_length - 1 - (p - new_entry), "%02X", newpwd->smb_nt_passwd[i]); - } - } else { - if(newpwd->acct_ctrl & ACB_PWNOTREQ) - safe_strcpy((char *)p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry)); - else - safe_strcpy((char *)p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry)); - } + pdb_sethexpwd(p, newpwd->smb_nt_passwd, newpwd->acct_ctrl); - p += 32; - - *p++ = ':'; + p+=strlen(p); *p = ':'; p++; /* Add the account encoding and the last change time. */ slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n", @@ -712,7 +678,7 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n", static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd* pwd) { /* Static buffers we will return. */ - char * user_name = smbpasswd_state->user_name; + pstring user_name; char linebuf[256]; char readbuf[1024]; @@ -830,6 +796,9 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con * As 256 is shorter than a pstring we don't need to check * length here - if this ever changes.... */ + + SMB_ASSERT(sizeof(user_name) > sizeof(linebuf)); + strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); user_name[PTR_DIFF(p, linebuf)] = '\0'; if (strequal(user_name, pwd->smb_name)) { @@ -841,6 +810,9 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con if (!found_entry) { pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth)); fclose(fp); + + DEBUG(2, ("Cannot update entry for user %s, as they don't exist in the smbpasswd file!\n", + pwd->smb_name)); return False; } @@ -967,30 +939,12 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con /* Entry is correctly formed. */ /* Create the 32 byte representation of the new p16 */ - if(pwd->smb_passwd != NULL) { - for (i = 0; i < 16; i++) { - slprintf(&ascii_p16[i*2], sizeof(fstring) - 1, "%02X", (uchar) pwd->smb_passwd[i]); - } - } else { - if(pwd->acct_ctrl & ACB_PWNOTREQ) - fstrcpy(ascii_p16, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); - else - fstrcpy(ascii_p16, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); - } + pdb_sethexpwd(ascii_p16, pwd->smb_passwd, pwd->acct_ctrl); /* Add on the NT md4 hash */ ascii_p16[32] = ':'; wr_len = 66; - if (pwd->smb_nt_passwd != NULL) { - for (i = 0; i < 16; i++) { - slprintf(&ascii_p16[(i*2)+33], sizeof(fstring) - 1, "%02X", (uchar) pwd->smb_nt_passwd[i]); - } - } else { - if(pwd->acct_ctrl & ACB_PWNOTREQ) - fstrcpy(&ascii_p16[33], "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); - else - fstrcpy(&ascii_p16[33], "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); - } + pdb_sethexpwd(ascii_p16+33, pwd->smb_nt_passwd, pwd->acct_ctrl); ascii_p16[65] = ':'; ascii_p16[66] = '\0'; /* null-terminate the string so that strlen works */ @@ -1184,18 +1138,18 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas if (sampass == NULL) return False; - ZERO_STRUCTP(smb_pw); + ZERO_STRUCTP(smb_pw); if (!IS_SAM_UNIX_USER(sampass)) { smb_pw->smb_userid_set = False; - DEBUG(5,("build_sam_pass: storing user without a UNIX uid or gid. \n")); + DEBUG(5,("build_smb_pass: storing user without a UNIX uid or gid. \n")); } else { uint32 rid = pdb_get_user_rid(sampass); smb_pw->smb_userid_set = True; uid = pdb_get_uid(sampass); /* If the user specified a RID, make sure its able to be both stored and retreived */ - if (rid && uid != pdb_user_rid_to_uid(rid)) { + if (rid && uid != fallback_pdb_user_rid_to_uid(rid)) { DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n")); return False; } @@ -1236,7 +1190,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; @@ -1249,84 +1204,37 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, SAM_AC && (pw_buf->smb_userid >= smbpasswd_state->low_nua_userid) && (pw_buf->smb_userid <= smbpasswd_state->high_nua_userid)) { - pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pw_buf->smb_userid)); + pdb_set_user_sid_from_rid(sam_pass, fallback_pdb_uid_to_user_rid (pw_buf->smb_userid)); /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. This was down the bottom for machines, but it looks pretty good as a general default for non-unix users. --abartlet 2002-01-08 */ - pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS); - + pdb_set_group_sid_from_rid (sam_pass, DOMAIN_GROUP_RID_USERS); + pdb_set_username (sam_pass, pw_buf->smb_name); + pdb_set_domain (sam_pass, lp_workgroup()); } 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 not in unix passwd database!\n", pw_buf->smb_name)); + 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, 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 @@ -1340,9 +1248,9 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, SAM_AC /***************************************************************** Functions to be implemented by the new passdb API ****************************************************************/ -static BOOL smbpasswd_setsampwent (struct pdb_context *context, BOOL update) +static BOOL smbpasswd_setsampwent (struct pdb_methods *my_methods, BOOL update) { - struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file, update ? PWF_UPDATE : PWF_READ, @@ -1370,17 +1278,17 @@ static BOOL smbpasswd_setsampwent (struct pdb_context *context, BOOL update) return (smbpasswd_state->pw_file != NULL); } -static void smbpasswd_endsampwent (struct pdb_context *context) +static void smbpasswd_endsampwent (struct pdb_methods *my_methods) { - struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; endsmbfilepwent(smbpasswd_state->pw_file, &(smbpasswd_state->pw_file_lock_depth)); } /***************************************************************** ****************************************************************/ -static BOOL smbpasswd_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user) +static BOOL smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user) { - struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd *pw_buf=NULL; BOOL done = False; DEBUG(5,("pdb_getsampwent\n")); @@ -1419,32 +1327,14 @@ static BOOL smbpasswd_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user call getpwnam() for unix account information until we have found the correct entry ***************************************************************/ -static BOOL smbpasswd_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username) +static BOOL smbpasswd_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_acct, const char *username) { - struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd *smb_pw; void *fp = NULL; - char *domain = NULL; - char *user = NULL; - fstring name; DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username)); - - /* break the username from the domain if we have - been given a string in the form 'DOMAIN\user' */ - fstrcpy (name, username); - if ((user=strchr_m(name, '\\')) != NULL) { - domain = name; - *user = '\0'; - user++; - } - - /* if a domain was specified and it wasn't ours - then there is no chance of matching */ - if ( domain && !StrCaseCmp(domain, lp_workgroup()) ) - return False; - /* startsmbfilepwent() is used here as we don't want to lookup the UNIX account in the local system password file until we have a match. */ @@ -1455,11 +1345,6 @@ static BOOL smbpasswd_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_ return False; } - /* if we have a domain name, then we should map it to a UNIX - username first */ - if ( domain ) - map_username(user); - while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) ) /* do nothing....another loop */ ; @@ -1488,10 +1373,9 @@ static BOOL smbpasswd_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_ return True; } - -static BOOL smbpasswd_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_acct,uint32 rid) +static BOOL smbpasswd_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_acct,uint32 rid) { - struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd *smb_pw; void *fp = NULL; @@ -1505,7 +1389,7 @@ static BOOL smbpasswd_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_ return False; } - while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL) && (pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) ) + while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL) && (fallback_pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) ) /* do nothing */ ; endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); @@ -1533,9 +1417,17 @@ static BOOL smbpasswd_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_ return True; } -static BOOL smbpasswd_add_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sampass) +static BOOL smbpasswd_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid) { - struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + uint32 rid; + if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) + return False; + return smbpasswd_getsampwrid(my_methods, user, rid); +} + +static BOOL smbpasswd_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sampass) +{ + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd smb_pw; /* convert the SAM_ACCOUNT */ @@ -1551,25 +1443,29 @@ static BOOL smbpasswd_add_sam_account(struct pdb_context *context, const SAM_ACC return True; } -static BOOL smbpasswd_update_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sampass) +static BOOL smbpasswd_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sampass) { - struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd smb_pw; /* convert the SAM_ACCOUNT */ - if (!build_smb_pass(&smb_pw, sampass)) + if (!build_smb_pass(&smb_pw, sampass)) { + DEBUG(0, ("smbpasswd_update_sam_account: build_smb_pass failed!\n")); return False; + } /* update the entry */ - if(!mod_smbfilepwd_entry(smbpasswd_state, &smb_pw)) + if(!mod_smbfilepwd_entry(smbpasswd_state, &smb_pw)) { + DEBUG(0, ("smbpasswd_update_sam_account: mod_smbfilepwd_entry failed!\n")); return False; - + } + return True; } -static BOOL smbpasswd_delete_sam_account (struct pdb_context *context, const SAM_ACCOUNT *sampass) +static BOOL smbpasswd_delete_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *sampass) { - struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; const char *username = pdb_get_username(sampass); @@ -1602,7 +1498,7 @@ NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, (*pdb_method)->endsampwent = smbpasswd_endsampwent; (*pdb_method)->getsampwent = smbpasswd_getsampwent; (*pdb_method)->getsampwnam = smbpasswd_getsampwnam; - (*pdb_method)->getsampwrid = smbpasswd_getsampwrid; + (*pdb_method)->getsampwsid = smbpasswd_getsampwsid; (*pdb_method)->add_sam_account = smbpasswd_add_sam_account; (*pdb_method)->update_sam_account = smbpasswd_update_sam_account; (*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account; diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index a8edac917e..6279318969 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -2,7 +2,7 @@ * Unix SMB/CIFS implementation. * SMB parameters and setup * Copyright (C) Andrew Tridgell 1992-1998 - * Copyright (C) Simo Sorce 2000 + * Copyright (C) Simo Sorce 2000-2002 * Copyright (C) Gerald Carter 2000 * Copyright (C) Jeremy Allison 2001 * Copyright (C) Andrew Bartlett 2002 @@ -24,6 +24,19 @@ #include "includes.h" +#if 0 /* when made a module use this */ + +static int tdbsam_debug_level = DBGC_ALL; +#undef DBGC_CLASS +#define DBGC_CLASS tdbsam_debug_level + +#else + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB + +#endif + #ifdef WITH_TDB_SAM #define PDB_VERSION "20010830" @@ -41,8 +54,10 @@ struct tdbsam_privates { BOOL permit_non_unix_accounts; -/* uint32 low_nua_rid; - uint32 high_nua_rid; */ + BOOL algorithmic_rids; + + uint32 low_nua_rid; + uint32 high_nua_rid; }; /********************************************************************** @@ -84,12 +99,10 @@ 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) { @@ -119,8 +132,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, @@ -150,6 +163,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); @@ -163,70 +178,76 @@ 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; - 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)); + if (homedir) { + pdb_set_homedir(sampass, homedir, True); } - pdb_set_homedir(sampass, homedir, setflag); - - if (dir_drive) setflag = 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_homedir(sampass, + talloc_sub_specified(sampass->mem_ctx, + lp_logon_home(), + username, domain, + uid, gid), + False); } - pdb_set_dir_drive(sampass, dir_drive, setflag); - if (logon_script) setflag = True; + if (dir_drive) + pdb_set_dir_drive(sampass, dir_drive, 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_dir_drive(sampass, + talloc_sub_specified(sampass->mem_ctx, + lp_logon_drive(), + username, domain, + uid, gid), + False); } - pdb_set_logon_script(sampass, logon_script, setflag); - if (profile_path) setflag = True; + if (logon_script) + pdb_set_logon_script(sampass, logon_script, 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)); + pdb_set_logon_script(sampass, + talloc_sub_specified(sampass->mem_ctx, + lp_logon_script(), + username, domain, + uid, gid), + False); + } + + if (profile_path) { + pdb_set_profile_path(sampass, profile_path, True); + } else { + pdb_set_profile_path(sampass, + talloc_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); - pdb_set_group_rid(sampass, group_rid); + pdb_set_user_sid_from_rid(sampass, user_rid); + pdb_set_group_sid_from_rid(sampass, group_rid); pdb_set_unknown_3(sampass, unknown_3); pdb_set_hours_len(sampass, hours_len); pdb_set_unknown_5(sampass, unknown_5); @@ -462,9 +483,9 @@ static uint32 init_buffer_from_sam (struct tdbsam_privates *tdb_state, Open the TDB passwd database for SAM account enumeration. ****************************************************************/ -static BOOL tdbsam_setsampwent(struct pdb_context *context, BOOL update) +static BOOL tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update) { - struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; /* Open tdb passwd */ if (!(tdb_state->passwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, update?(O_RDWR|O_CREAT):O_RDONLY, 0600))) @@ -490,9 +511,9 @@ static void close_tdb(struct tdbsam_privates *tdb_state) End enumeration of the TDB passwd list. ****************************************************************/ -static void tdbsam_endsampwent(struct pdb_context *context) +static void tdbsam_endsampwent(struct pdb_methods *my_methods) { - struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; close_tdb(tdb_state); DEBUG(7, ("endtdbpwent: closed sam database.\n")); @@ -502,9 +523,9 @@ static void tdbsam_endsampwent(struct pdb_context *context) Get one SAM_ACCOUNT from the TDB (next in line) *****************************************************************/ -static BOOL tdbsam_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user) +static BOOL tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user) { - struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; TDB_DATA data; char *prefix = USERPREFIX; int prefixlen = strlen (prefix); @@ -550,9 +571,9 @@ static BOOL tdbsam_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user) Lookup a name in the SAM TDB ******************************************************************/ -static BOOL tdbsam_getsampwnam (struct pdb_context *context, SAM_ACCOUNT *user, const char *sname) +static BOOL tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname) { - struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; TDB_CONTEXT *pwd_tdb; TDB_DATA data, key; fstring keystr; @@ -606,9 +627,9 @@ static BOOL tdbsam_getsampwnam (struct pdb_context *context, SAM_ACCOUNT *user, Search by rid **************************************************************************/ -static BOOL tdbsam_getsampwrid (struct pdb_context *context, SAM_ACCOUNT *user, uint32 rid) +static BOOL tdbsam_getsampwrid (struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid) { - struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; TDB_CONTEXT *pwd_tdb; TDB_DATA data, key; fstring keystr; @@ -644,16 +665,24 @@ static BOOL tdbsam_getsampwrid (struct pdb_context *context, SAM_ACCOUNT *user, tdb_close (pwd_tdb); - return tdbsam_getsampwnam (context, user, name); + return tdbsam_getsampwnam (my_methods, user, name); +} + +static BOOL tdbsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid) +{ + uint32 rid; + if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) + return False; + return tdbsam_getsampwrid(my_methods, user, rid); } /*************************************************************************** Delete a SAM_ACCOUNT ****************************************************************************/ -static BOOL tdbsam_delete_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sam_pass) +static BOOL tdbsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_pass) { - struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; TDB_CONTEXT *pwd_tdb; TDB_DATA key; fstring keystr; @@ -707,9 +736,9 @@ static BOOL tdbsam_delete_sam_account(struct pdb_context *context, const SAM_ACC Update the TDB SAM ****************************************************************************/ -static BOOL tdb_update_sam(struct pdb_context *context, const SAM_ACCOUNT* newpwd, int flag) +static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, int flag) { - struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; TDB_CONTEXT *pwd_tdb = NULL; TDB_DATA key, data; uint8 *buf = NULL; @@ -717,7 +746,7 @@ static BOOL tdb_update_sam(struct pdb_context *context, const SAM_ACCOUNT* newpw fstring name; BOOL ret = True; uint32 user_rid; - int32 tdb_ret; + BOOL tdb_ret; /* invalidate the existing TDB iterator if it is open */ if (tdb_state->passwd_tdb) { @@ -736,13 +765,32 @@ static BOOL tdb_update_sam(struct pdb_context *context, const SAM_ACCOUNT* newpw /* if flag == TDB_INSERT then make up a new RID else throw an error. */ if (!(user_rid = pdb_get_user_rid(newpwd))) { if (flag & TDB_INSERT) { - user_rid = BASE_RID; - tdb_ret = tdb_change_int32_atomic(pwd_tdb, "RID_COUNTER", &user_rid, RID_MULTIPLIER); - if (tdb_ret == -1) { - ret = False; - goto done; + if (IS_SAM_UNIX_USER(newpwd)) { + if (tdb_state->algorithmic_rids) { + user_rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(newpwd)); + } else { + user_rid = BASE_RID; + tdb_ret = tdb_change_uint32_atomic(pwd_tdb, "RID_COUNTER", &user_rid, RID_MULTIPLIER); + if (!tdb_ret) { + ret = False; + goto done; + } + } + pdb_set_user_sid_from_rid(newpwd, user_rid); + } else { + user_rid = tdb_state->low_nua_rid; + tdb_ret = tdb_change_uint32_atomic(pwd_tdb, "NUA_RID_COUNTER", &user_rid, RID_MULTIPLIER); + if (!tdb_ret) { + ret = False; + goto done; + } + if (user_rid > tdb_state->high_nua_rid) { + DEBUG(0, ("tdbsam: no NUA rids available, cannot add user %s!\n", pdb_get_username(newpwd))); + ret = False; + goto done; + } + pdb_set_user_sid_from_rid(newpwd, user_rid); } - pdb_set_user_rid(newpwd, user_rid); } else { DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a RID\n",pdb_get_username(newpwd))); ret = False; @@ -758,7 +806,7 @@ static BOOL tdb_update_sam(struct pdb_context *context, const SAM_ACCOUNT* newpw goto done; } else { /* This seems like a good default choice for non-unix users */ - pdb_set_group_rid(newpwd, DOMAIN_GROUP_RID_USERS); + pdb_set_group_sid_from_rid(newpwd, DOMAIN_GROUP_RID_USERS); } } else { DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",pdb_get_username(newpwd))); @@ -823,18 +871,18 @@ done: Modifies an existing SAM_ACCOUNT ****************************************************************************/ -static BOOL tdbsam_update_sam_account (struct pdb_context *context, const SAM_ACCOUNT *newpwd) +static BOOL tdbsam_update_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd) { - return (tdb_update_sam(context, newpwd, TDB_MODIFY)); + return (tdb_update_sam(my_methods, newpwd, TDB_MODIFY)); } /*************************************************************************** Adds an existing SAM_ACCOUNT ****************************************************************************/ -static BOOL tdbsam_add_sam_account (struct pdb_context *context, const SAM_ACCOUNT *newpwd) +static BOOL tdbsam_add_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd) { - return (tdb_update_sam(context, newpwd, TDB_INSERT)); + return (tdb_update_sam(my_methods, newpwd, TDB_INSERT)); } static void free_private_data(void **vp) @@ -852,6 +900,14 @@ NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, con NTSTATUS nt_status; struct tdbsam_privates *tdb_state; +#if 0 /* when made a module use this */ + tdbsam_debug_level = debug_add_class("tdbsam"); + if(tdbsam_debug_level == -1) { + tdbsam_debug_level = DBGC_ALL; + DEBUG(0, ("tdbsam: Couldn't register custom debugging class!\n")); + } +#endif + if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { return nt_status; } @@ -862,7 +918,7 @@ NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, con (*pdb_method)->endsampwent = tdbsam_endsampwent; (*pdb_method)->getsampwent = tdbsam_getsampwent; (*pdb_method)->getsampwnam = tdbsam_getsampwnam; - (*pdb_method)->getsampwrid = tdbsam_getsampwrid; + (*pdb_method)->getsampwsid = tdbsam_getsampwsid; (*pdb_method)->add_sam_account = tdbsam_add_sam_account; (*pdb_method)->update_sam_account = tdbsam_update_sam_account; (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account; @@ -884,6 +940,8 @@ NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, con tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, tdbfile); } + tdb_state->algorithmic_rids = True; + (*pdb_method)->private_data = tdb_state; (*pdb_method)->free_private_data = free_private_data; @@ -904,7 +962,7 @@ NTSTATUS pdb_init_tdbsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, (*pdb_method)->name = "tdbsam_nua"; tdb_state = (*pdb_method)->private_data; - + tdb_state->permit_non_unix_accounts = True; if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) { @@ -912,10 +970,10 @@ NTSTATUS pdb_init_tdbsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, return NT_STATUS_UNSUCCESSFUL; } -/* tdb_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid); + tdb_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid); tdb_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid); -*/ + return NT_STATUS_OK; } diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index b3507a1392..3ecaf52e58 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -1,6 +1,8 @@ /* Unix SMB/CIFS implementation. Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Andrew Bartlett 2002 + Copyright (C) Rafal Szczesniak 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 @@ -22,6 +24,9 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB + static TDB_CONTEXT *tdb; /* open up the secrets database */ @@ -47,7 +52,7 @@ BOOL secrets_init(void) /* read a entry from the secrets database - the caller must free the result if size is non-null then the size of the entry is put in there */ -void *secrets_fetch(char *key, size_t *size) +void *secrets_fetch(const char *key, size_t *size) { TDB_DATA kbuf, dbuf; secrets_init(); @@ -63,7 +68,7 @@ void *secrets_fetch(char *key, size_t *size) /* store a secrets entry */ -BOOL secrets_store(char *key, void *data, size_t size) +BOOL secrets_store(const char *key, void *data, size_t size) { TDB_DATA kbuf, dbuf; secrets_init(); @@ -79,7 +84,7 @@ BOOL secrets_store(char *key, void *data, size_t size) /* delete a secets database entry */ -BOOL secrets_delete(char *key) +BOOL secrets_delete(const char *key) { TDB_DATA kbuf; secrets_init(); @@ -124,10 +129,14 @@ BOOL secrets_fetch_domain_sid(char *domain, DOM_SID *sid) } -/************************************************************************ -form a key for fetching the machine trust account password -************************************************************************/ -char *trust_keystr(char *domain) +/** + * Form a key for fetching the machine trust account password + * + * @param domain domain name + * + * @return stored password's key + **/ +const char *trust_keystr(const char *domain) { static fstring keystr; @@ -141,11 +150,11 @@ char *trust_keystr(char *domain) /** * Form a key for fetching a trusted domain password * - * @param domain domain name + * @param domain trusted domain name * * @return stored password's key **/ -char *trustdom_keystr(char *domain) +char *trustdom_keystr(const char *domain) { static char* keystr; @@ -194,21 +203,23 @@ BOOL secrets_fetch_trust_account_password(char *domain, uint8 ret_pwd[16], Routine to get account password to trusted domain ************************************************************************/ BOOL secrets_fetch_trusted_domain_password(char *domain, char** pwd, - DOM_SID *sid, time_t *pass_last_set_time) + DOM_SID *sid, time_t *pass_last_set_time) { struct trusted_dom_pass *pass; size_t size; + /* fetching trusted domain password structure */ if (!(pass = secrets_fetch(trustdom_keystr(domain), &size))) { DEBUG(5, ("secrets_fetch failed!\n")); return False; } - + if (size != sizeof(*pass)) { DEBUG(0, ("secrets were of incorrect size!\n")); return False; } - + + /* the trust's password */ if (pwd) { *pwd = strdup(pass->pass); if (!*pwd) { @@ -216,9 +227,12 @@ BOOL secrets_fetch_trusted_domain_password(char *domain, char** pwd, } } + /* last change time */ if (pass_last_set_time) *pass_last_set_time = pass->mod_time; + /* domain sid */ memcpy(&sid, &(pass->domain_sid), sizeof(sid)); + SAFE_FREE(pass); return True; @@ -247,19 +261,30 @@ BOOL secrets_store_trust_account_password(char *domain, uint8 new_pwd[16]) * @return true if succeeded **/ -BOOL secrets_store_trusted_domain_password(char* domain, char* pwd, +BOOL secrets_store_trusted_domain_password(char* domain, smb_ucs2_t *uni_dom_name, + size_t uni_name_len, char* pwd, DOM_SID sid) { struct trusted_dom_pass pass; ZERO_STRUCT(pass); + /* unicode domain name and its length */ + if (!uni_dom_name) + return False; + + strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1); + pass.uni_name_len = uni_name_len; + + /* last change time */ pass.mod_time = time(NULL); + /* password of the trust */ pass.pass_len = strlen(pwd); fstrcpy(pass.pass, pwd); + /* domain sid */ memcpy(&(pass.domain_sid), &sid, sizeof(sid)); - + return secrets_store(trustdom_keystr(domain), (void *)&pass, sizeof(pass)); } @@ -300,7 +325,7 @@ char *secrets_fetch_machine_password(void) Routine to delete the machine trust account password file for a domain. ************************************************************************/ -BOOL trust_password_delete(char *domain) +BOOL trust_password_delete(const char *domain) { return secrets_delete(trust_keystr(domain)); } @@ -308,7 +333,7 @@ BOOL trust_password_delete(char *domain) /************************************************************************ Routine to delete the password for trusted domain ************************************************************************/ -BOOL trusted_domain_password_delete(char *domain) +BOOL trusted_domain_password_delete(const char *domain) { return secrets_delete(trustdom_keystr(domain)); } @@ -345,15 +370,136 @@ void reset_globals_after_fork(void) generate_random_buffer( &dummy, 1, True); } -BOOL secrets_store_ldap_pw(char* dn, char* pw) +BOOL secrets_store_ldap_pw(const char* dn, char* pw) { - fstring key; - char *p; + char *key = NULL; + BOOL ret; - pstrcpy(key, dn); - for (p=key; *p; p++) - if (*p == ',') *p = '/'; + if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) { + DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n")); + return False; + } + + ret = secrets_store(key, pw, strlen(pw)+1); + + SAFE_FREE(key); + return ret; +} + + +/** + * The linked list is allocated on the supplied talloc context, caller gets to destory + * when done. + * + * @param ctx Allocation context + * @param enum_ctx Starting index, eg. we can start fetching at third + * or sixth trusted domain entry. Zero is the first index. + * Value it is set to is the enum context for the next enumeration. + * @param num_domains Number of domain entries to fetch at one call + * @param domains Pointer to array of trusted domain structs to be filled up + * + * @return nt status code of rpc response + **/ + +NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, int max_num_domains, int *num_domains, TRUSTDOM ***domains) +{ + TDB_LIST_NODE *keys, *k; + TRUSTDOM *dom = NULL; + char *pattern; + int start_idx; + uint32 idx = 0; + size_t size; + struct trusted_dom_pass *pass; + NTSTATUS status; + + secrets_init(); + + *num_domains = 0; + start_idx = *enum_ctx; + + /* generate searching pattern */ + if (!(pattern = talloc_asprintf(ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))) { + DEBUG(0, ("secrets_get_trusted_domains: talloc_asprintf() failed!\n")); + return NT_STATUS_NO_MEMORY; + } + + DEBUG(5, ("secrets_get_trusted_domains: looking for %d domains, starting at index %d\n", + max_num_domains, *enum_ctx)); + + *domains = talloc_zero(ctx, sizeof(**domains)*max_num_domains); + + /* fetching trusted domains' data and collecting them in a list */ + keys = tdb_search_keys(tdb, pattern); + + /* + * if there's no keys returned ie. no trusted domain, + * return "no more entries" code + */ + status = NT_STATUS_NO_MORE_ENTRIES; + + /* searching for keys in sectrets db -- way to go ... */ + for (k = keys; k; k = k->next) { + char *secrets_key; + + /* important: ensure null-termination of the key string */ + secrets_key = strndup(k->node_key.dptr, k->node_key.dsize); + if (!secrets_key) { + DEBUG(0, ("strndup failed!\n")); + return NT_STATUS_NO_MEMORY; + } + + pass = secrets_fetch(secrets_key, &size); + + if (size != sizeof(*pass)) { + DEBUG(2, ("Secrets record %s is invalid!\n", secrets_key)); + SAFE_FREE(pass); + continue; + } + + SAFE_FREE(secrets_key); + + if (idx >= start_idx && idx < start_idx + max_num_domains) { + dom = talloc_zero(ctx, sizeof(*dom)); + if (!dom) { + /* free returned tdb record */ + SAFE_FREE(pass); + + return NT_STATUS_NO_MEMORY; + } + + /* copy domain sid */ + SMB_ASSERT(sizeof(dom->sid) == sizeof(pass->domain_sid)); + memcpy(&(dom->sid), &(pass->domain_sid), sizeof(dom->sid)); + + /* copy unicode domain name */ + dom->name = talloc_strdup_w(ctx, pass->uni_name); + + (*domains)[idx - start_idx] = dom; + + *enum_ctx = idx + 1; + (*num_domains)++; + + /* set proper status code to return */ + if (k->next) { + /* there are yet some entries to enumerate */ + status = STATUS_MORE_ENTRIES; + } else { + /* this is the last entry in the whole enumeration */ + status = NT_STATUS_OK; + } + } + + idx++; + + /* free returned tdb record */ + SAFE_FREE(pass); + } - return secrets_store(key, pw, strlen(pw)); + DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n", *num_domains)); + + /* free the results of searching the keys */ + tdb_search_list_free(keys); + + return status; } -- cgit