diff options
Diffstat (limited to 'source/passdb/passdb.c')
-rw-r--r-- | source/passdb/passdb.c | 1917 |
1 files changed, 1256 insertions, 661 deletions
diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index 2d8ea858aa4..a79522d5e58 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -1,10 +1,10 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 1.9. Password and authentication handling Copyright (C) Jeremy Allison 1996-2001 Copyright (C) Luke Kenneth Casson Leighton 1996-1998 Copyright (C) Gerald (Jerry) Carter 2000-2001 - Copyright (C) Andrew Bartlett 2001-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,253 +23,103 @@ #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 pstring global_myname; - -/************************************************************ - Fill the SAM_ACCOUNT with default values. - ***********************************************************/ - -static void pdb_fill_default_sam(SAM_ACCOUNT *user) -{ - ZERO_STRUCT(user->private); /* Don't touch the talloc context */ - - /* Don't change these timestamp settings without a good reason. - They are important for NT member server compatibility. */ - - user->private.init_flag = FLAG_SAM_UNINIT; - user->private.uid = user->private.gid = -1; - - user->private.logon_time = (time_t)0; - user->private.pass_last_set_time = (time_t)0; - user->private.pass_can_change_time = (time_t)0; - user->private.logoff_time = - user->private.kickoff_time = - user->private.pass_must_change_time = get_time_t_max(); - user->private.unknown_3 = 0x00ffffff; /* don't know */ - user->private.logon_divs = 168; /* hours per week */ - user->private.hours_len = 21; /* 21 times 8 bits = 168 */ - memset(user->private.hours, 0xff, user->private.hours_len); /* available at all hours */ - user->private.unknown_5 = 0x00000000; /* don't know */ - user->private.unknown_6 = 0x000004ec; /* don't know */ - - /* Some parts of samba strlen their pdb_get...() returns, - so this keeps the interface unchanged for now. */ - - user->private.username = ""; - user->private.domain = ""; - user->private.nt_username = ""; - user->private.full_name = ""; - user->private.home_dir = ""; - user->private.logon_script = ""; - user->private.profile_path = ""; - user->private.acct_desc = ""; - user->private.workstations = ""; - user->private.unknown_str = ""; - user->private.munged_dial = ""; - - user->private.plaintext_pw = NULL; - -} - -static void destroy_pdb_talloc(SAM_ACCOUNT **user) -{ - if (*user) { - data_blob_clear_free(&((*user)->private.lm_pw)); - data_blob_clear_free(&((*user)->private.nt_pw)); - - if((*user)->private.plaintext_pw!=NULL) - memset((*user)->private.plaintext_pw,'\0',strlen((*user)->private.plaintext_pw)); - talloc_destroy((*user)->mem_ctx); - *user = NULL; - } -} +extern DOM_SID global_sam_sid; +struct passdb_ops *pdb_ops; -/********************************************************************** - Alloc memory and initialises a struct sam_passwd on supplied mem_ctx. -***********************************************************************/ - -NTSTATUS pdb_init_sam_talloc(TALLOC_CTX *mem_ctx, SAM_ACCOUNT **user) -{ - if (*user != NULL) { - 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"); +#if 0 /* JERRY */ +static void* pdb_handle = NULL; #endif - return NT_STATUS_UNSUCCESSFUL; - } - - if (!mem_ctx) { - DEBUG(0,("pdb_init_sam_talloc: mem_ctx was NULL!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - *user=(SAM_ACCOUNT *)talloc(mem_ctx, sizeof(SAM_ACCOUNT)); - - if (*user==NULL) { - DEBUG(0,("pdb_init_sam_talloc: error while allocating memory\n")); - return NT_STATUS_NO_MEMORY; - } - - (*user)->mem_ctx = mem_ctx; - (*user)->free_fn = NULL; +/*************************************************************** + Initialize the password db operations. +***************************************************************/ - pdb_fill_default_sam(*user); +BOOL initialize_password_db(BOOL reload) +{ + /* + * This function is unfinished right now, so just + * ignore the details and always return True. It + * is here only as a placeholder --jerry + */ + return True; - return NT_STATUS_OK; } - /************************************************************* - Alloc memory and initialises a struct sam_passwd. - ************************************************************/ + Initialises a struct sam_disp_info. + **************************************************************/ -NTSTATUS pdb_init_sam(SAM_ACCOUNT **user) +static void pdb_init_dispinfo(struct sam_disp_info *user) { - TALLOC_CTX *mem_ctx; - NTSTATUS nt_status; - - mem_ctx = talloc_init_named("passdb internal SAM_ACCOUNT allocation"); + if (user == NULL) + return; + ZERO_STRUCTP(user); +} - if (!mem_ctx) { - DEBUG(0,("pdb_init_sam: error while doing talloc_init()\n")); - return NT_STATUS_NO_MEMORY; - } - if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(mem_ctx, user))) { - talloc_destroy(mem_ctx); - return nt_status; +/************************************************************ + Fill the SAM_ACCOUNT with default values. + ***********************************************************/ + +static BOOL pdb_fill_default_sam(SAM_ACCOUNT *user) +{ + if (user == NULL) { + DEBUG(0,("pdb_fill_default_sam: SAM_ACCOUNT was NULL\n")); + return False; } - (*user)->free_fn = destroy_pdb_talloc; - - return NT_STATUS_OK; -} + ZERO_STRUCTP(user); + + user->init_flag = FLAG_SAM_UNINIT; + user->uid = user->gid = -1; + user->logon_time = (time_t)0; + user->pass_last_set_time = (time_t)0; + user->pass_can_change_time = (time_t)0; + user->logoff_time = + user->kickoff_time = + user->pass_must_change_time = get_time_t_max(); /* Password never expires. */ + + user->unknown_3 = 0x00ffffff; /* don't know */ + user->logon_divs = 168; /* hours per week */ + user->hours_len = 21; /* 21 times 8 bits = 168 */ + memset(user->hours, 0xff, user->hours_len); /* available at all hours */ + user->unknown_5 = 0x00000000; /* don't know */ + user->unknown_6 = 0x000004ec; /* don't know */ + return True; +} /************************************************************* - Initialises a struct sam_passwd with sane values. + Alloc memory and initialises a struct sam_passwd. ************************************************************/ -NTSTATUS pdb_fill_sam_pw(SAM_ACCOUNT *sam_account, const struct passwd *pwd) +BOOL pdb_init_sam(SAM_ACCOUNT **user) { - GROUP_MAP map; - - const char *guest_account = lp_guestaccount(); - if (!(guest_account && *guest_account)) { - DEBUG(1, ("NULL guest account!?!?\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!pwd) { - return NT_STATUS_UNSUCCESSFUL; + if (*user != NULL) { + DEBUG(0,("pdb_init_sam: SAM_ACCOUNT was non NULL\n")); +#if 0 + smb_panic("NULL pointer passed to pdb_init_sam\n"); +#endif + return False; } - - pdb_fill_default_sam(sam_account); - - pdb_set_username(sam_account, pwd->pw_name); - pdb_set_fullname(sam_account, pwd->pw_gecos); - - pdb_set_unix_homedir(sam_account, pwd->pw_dir); - - pdb_set_domain (sam_account, lp_workgroup()); - - pdb_set_uid(sam_account, pwd->pw_uid); - pdb_set_gid(sam_account, pwd->pw_gid); - /* 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 - */ - - - /* Ensure this *must* be set right */ - if (strcmp(pwd->pw_name, guest_account) == 0) { - if (!pdb_set_user_sid_from_rid(sam_account, DOMAIN_USER_RID_GUEST)) { - return NT_STATUS_UNSUCCESSFUL; - } - if (!pdb_set_group_sid_from_rid(sam_account, DOMAIN_GROUP_RID_GUESTS)) { - return NT_STATUS_UNSUCCESSFUL; - } - } else { - - 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)) { - if (!pdb_set_group_sid(sam_account,&map.sid)){ - DEBUG(0,("Can't set Group SID!\n")); - return NT_STATUS_INVALID_PARAMETER; - } - } - else { - 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; - } - } + *user=(SAM_ACCOUNT *)malloc(sizeof(SAM_ACCOUNT)); + + if (*user==NULL) { + DEBUG(0,("pdb_init_sam: error while allocating memory\n")); + return False; } - /* 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_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); - if (!pdb_set_acct_ctrl(sam_account, ACB_NORMAL)) { - DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n", pwd->pw_name)); - return NT_STATUS_UNSUCCESSFUL; - } - } else { - if (!pdb_set_acct_ctrl(sam_account, ACB_WSTRUST)) { - DEBUG(1, ("Failed to set 'trusted workstation account' flags for user %s.\n", pwd->pw_name)); - return NT_STATUS_UNSUCCESSFUL; - } - } - return NT_STATUS_OK; + pdb_fill_default_sam(*user); + + return True; } @@ -277,98 +127,123 @@ NTSTATUS pdb_fill_sam_pw(SAM_ACCOUNT *sam_account, const struct passwd *pwd) Initialises a struct sam_passwd with sane values. ************************************************************/ -NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd) +BOOL pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, struct passwd *pwd) { - NTSTATUS nt_status; - if (!pwd) { new_sam_acct = NULL; - return NT_STATUS_UNSUCCESSFUL; + return False; } - if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(new_sam_acct))) { + if (!pdb_init_sam(new_sam_acct)) { new_sam_acct = NULL; - return nt_status; + return False; } - 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; + pdb_set_username(*new_sam_acct, pwd->pw_name); + pdb_set_fullname(*new_sam_acct, pwd->pw_gecos); + pdb_set_uid(*new_sam_acct, pwd->pw_uid); + pdb_set_gid(*new_sam_acct, pwd->pw_gid); + pdb_set_profile_path(*new_sam_acct, lp_logon_path(), False); + pdb_set_homedir(*new_sam_acct, lp_logon_home(), False); + pdb_set_dir_drive(*new_sam_acct, lp_logon_drive(), False); + pdb_set_logon_script(*new_sam_acct, lp_logon_script(), False); + return True; } -/** - * Free the contets of the SAM_ACCOUNT, but not the structure. - * - * Also wipes the LM and NT hashes and plaintext passwrod from - * memory. - * - * @param user SAM_ACCOUNT to free members of. - **/ +/************************************************************ + Free the NT/LM hashes only. + ***********************************************************/ -static void pdb_free_sam_contents(SAM_ACCOUNT *user) +static BOOL pdb_free_sam_contents(SAM_ACCOUNT *user) { + if (user == NULL) { + DEBUG(0,("pdb_free_sam_contents: SAM_ACCOUNT was NULL\n")); +#if 0 + smb_panic("NULL pointer passed to pdb_free_sam\n"); +#endif + return False; + } - /* Kill off sensitive data. Free()ed by the - talloc mechinism */ + /* As we start mallocing more strings this is where + we should free them. */ - data_blob_clear_free(&(user->private.lm_pw)); - data_blob_clear_free(&(user->private.nt_pw)); - if (user->private.plaintext_pw!=NULL) - memset(user->private.plaintext_pw,'\0',strlen(user->private.plaintext_pw)); + SAFE_FREE(user->nt_pw); + SAFE_FREE(user->lm_pw); + + return True; } /************************************************************ Reset the SAM_ACCOUNT and free the NT/LM hashes. + - note: they are not zero'ed out however. ***********************************************************/ -NTSTATUS pdb_reset_sam(SAM_ACCOUNT *user) +BOOL pdb_reset_sam(SAM_ACCOUNT *user) { if (user == NULL) { DEBUG(0,("pdb_reset_sam: SAM_ACCOUNT was NULL\n")); -#if 0 - smb_panic("NULL pointer passed to pdb_free_sam\n"); -#endif - return NT_STATUS_UNSUCCESSFUL; + return False; } - pdb_free_sam_contents(user); + if (!pdb_free_sam_contents(user)) { + return False; + } - pdb_fill_default_sam(user); + if (!pdb_fill_default_sam(user)) { + return False; + } - return NT_STATUS_OK; + return True; } /************************************************************ - Free the SAM_ACCOUNT and the member pointers. + Free the SAM_ACCOUNT and the NT/LM hashes. ***********************************************************/ -NTSTATUS pdb_free_sam(SAM_ACCOUNT **user) +BOOL pdb_free_sam(SAM_ACCOUNT *user) { - if (*user == NULL) { + if (user == NULL) { DEBUG(0,("pdb_free_sam: SAM_ACCOUNT was NULL\n")); #if 0 smb_panic("NULL pointer passed to pdb_free_sam\n"); #endif - return NT_STATUS_UNSUCCESSFUL; + return False; } - pdb_free_sam_contents(*user); - - if ((*user)->free_fn) { - (*user)->free_fn(user); + if (!pdb_free_sam_contents(user)) { + return False; } - return NT_STATUS_OK; + SAFE_FREE(user); + + return True; } +/************************************************************************* + Routine to return the next entry in the sam passwd list. + *************************************************************************/ + +struct sam_disp_info *pdb_sam_to_dispinfo(SAM_ACCOUNT *user) +{ + static struct sam_disp_info disp_info; + + if (user == NULL) + return NULL; + + pdb_init_dispinfo(&disp_info); + + disp_info.smb_name = user->username; + disp_info.full_name = user->full_name; + disp_info.user_rid = user->user_rid; + + return &disp_info; +} + /********************************************************** Encode the account control bits into a string. length = length of string to encode into (including terminating @@ -450,7 +325,7 @@ uint16 pdb_decode_acct_ctrl(const char *p) Routine to set 32 hex password characters from a 16 byte array. **************************************************************/ -void pdb_sethexpwd(char *p, const unsigned char *pwd, uint16 acct_ctrl) +void pdb_sethexpwd(char *p, unsigned char *pwd, uint16 acct_ctrl) { if (pwd != NULL) { int i; @@ -469,7 +344,7 @@ void pdb_sethexpwd(char *p, const unsigned char *pwd, uint16 acct_ctrl) into a 16 byte array. **************************************************************/ -BOOL pdb_gethexpwd(const char *p, unsigned char *pwd) +BOOL pdb_gethexpwd(char *p, unsigned char *pwd) { int i; unsigned char lonybble, hinybble; @@ -498,48 +373,65 @@ BOOL pdb_gethexpwd(const char *p, unsigned char *pwd) } /******************************************************************* - Converts NT user RID to a UNIX uid. + Group and User RID username mapping function ********************************************************************/ -uid_t fallback_pdb_user_rid_to_uid(uint32 user_rid) +BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid) { - int rid_offset = lp_algorithmic_rid_base(); - return (uid_t)(((user_rid & (~USER_RID_TYPE))- rid_offset)/RID_MULTIPLIER); + struct passwd *pw = Get_Pwnam(user_name, False); + + 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 = pdb_uid_to_user_rid(pw->pw_uid); + + /* absolutely no idea what to do about the unix GID to Domain RID mapping */ + *g_rid = pdb_gid_to_group_rid(pw->pw_gid); + + return True; } +/******************************************************************* + Converts NT user RID to a UNIX uid. + ********************************************************************/ + +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. + Converts NT user RID to a UNIX gid. ********************************************************************/ -uint32 fallback_pdb_uid_to_user_rid(uid_t uid) +gid_t pdb_user_rid_to_gid(uint32 user_rid) { - int rid_offset = lp_algorithmic_rid_base(); - return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE); + return (uid_t)(((user_rid & (~GROUP_RID_TYPE))- 1000)/RID_MULTIPLIER); } /******************************************************************* - Converts NT group RID to a UNIX gid. + converts UNIX uid to an NT User RID. ********************************************************************/ -gid_t pdb_group_rid_to_gid(uint32 group_rid) +uint32 pdb_uid_to_user_rid(uid_t uid) { - int rid_offset = lp_algorithmic_rid_base(); - return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER); + return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE); } /******************************************************************* converts NT Group RID to a UNIX uid. - - warning: you must not call that function only - you must do a call to the group mapping first. - there is not anymore a direct link between the gid and the rid. ********************************************************************/ uint32 pdb_gid_to_group_rid(gid_t gid) { - int rid_offset = lp_algorithmic_rid_base(); - return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE); + return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE); } /******************************************************************* @@ -548,10 +440,7 @@ uint32 pdb_gid_to_group_rid(gid_t gid) static BOOL pdb_rid_is_well_known(uint32 rid) { - /* Not using rid_offset here, becouse this is the actual - NT fixed value (1000) */ - - return (rid < BASE_RID); + return (rid < 1000); } /******************************************************************* @@ -564,9 +453,6 @@ BOOL pdb_rid_is_user(uint32 rid) * such that it can be identified as either a user, group etc * type. there are 5 such categories, and they are documented. */ - /* However, they are not in the RID, just somthing you can query - seperatly. Sorry luke :-) */ - if(pdb_rid_is_well_known(rid)) { /* * The only well known user RIDs are DOMAIN_USER_RID_ADMIN @@ -584,130 +470,127 @@ BOOL pdb_rid_is_user(uint32 rid) Convert a rid into a name. Used in the lookup SID rpc. ********************************************************************/ -BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use) +BOOL local_lookup_rid(uint32 rid, char *name, enum SID_NAME_USE *psid_name_use) { - uint32 rid; - SAM_ACCOUNT *sam_account = NULL; - GROUP_MAP map; + BOOL is_user = pdb_rid_is_user(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)); - - if (rid == DOMAIN_USER_RID_ADMIN) { - char **admin_list = lp_admin_users(-1); - *psid_name_use = SID_NAME_USER; - if (admin_list) { - char *p = *admin_list; + + DEBUG(5,("local_lookup_rid: looking up %s RID %u.\n", is_user ? "user" : + "group", (unsigned int)rid)); + + if(is_user) { + if(rid == DOMAIN_USER_RID_ADMIN) { + char *p = lp_admin_users(-1); + *psid_name_use = SID_NAME_USER; if(!next_token(&p, name, NULL, sizeof(fstring))) fstrcpy(name, "Administrator"); + } else if (rid == DOMAIN_USER_RID_GUEST) { + char *p = lp_guestaccount(-1); + *psid_name_use = SID_NAME_USER; + if(!next_token(&p, name, NULL, sizeof(fstring))) + fstrcpy(name, "Guest"); } else { - fstrcpy(name, "Administrator"); - } - return True; - } - - /* - * Don't try to convert the rid to a name if - * running in appliance mode - */ - - if (lp_hide_local_users()) - return False; - - if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { - return False; - } - - /* This now does the 'generic' mapping in pdb_unix */ - /* 'guest' is also handled there */ - if (pdb_getsampwsid(sam_account, sid)) { - fstrcpy(name, pdb_get_username(sam_account)); - *psid_name_use = SID_NAME_USER; - - pdb_free_sam(&sam_account); + uid_t uid; + struct passwd *pass; - return True; - } + /* + * Don't try to convert the rid to a name if + * running in appliance mode + */ + if (lp_hide_local_users()) + return False; + + uid = pdb_user_rid_to_uid(rid); + pass = sys_getpwuid(uid); - 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)); - } else { - DEBUG(5,("local_lookup_sid: mapped group %s to no unix gid. Returning name.\n", map.nt_name)); - } + *psid_name_use = SID_NAME_USER; - fstrcpy(name, map.nt_name); - *psid_name_use = map.sid_name_use; - return True; - } + DEBUG(5,("local_lookup_rid: looking up uid %u %s\n", (unsigned int)uid, + pass ? "succeeded" : "failed" )); - if (pdb_rid_is_user(rid)) { - uid_t uid; + if(!pass) { + slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid); + return True; + } - DEBUG(5, ("assuming RID %u is a user\n", (unsigned)rid)); + fstrcpy(name, pass->pw_name); - uid = fallback_pdb_user_rid_to_uid(rid); - slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid); + DEBUG(5,("local_lookup_rid: found user %s for rid %u\n", name, + (unsigned int)rid )); + } - 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); + /* + * Don't try to convert the rid to a name if running + * in appliance mode + */ + + if (lp_hide_local_users()) + return False; + + gid = pdb_user_rid_to_gid(rid); gr = getgrgid(gid); - + *psid_name_use = SID_NAME_ALIAS; - - DEBUG(5,("local_lookup_sid: looking up gid %u %s\n", (unsigned int)gid, - gr ? "succeeded" : "failed" )); - + + DEBUG(5,("local_local_rid: looking up gid %u %s\n", (unsigned int)gid, + gr ? "succeeded" : "failed" )); + if(!gr) { + switch (rid) { + case DOMAIN_GROUP_RID_ADMINS: + fstrcpy(name, "Domain Admins"); + return True; + case DOMAIN_GROUP_RID_USERS: + fstrcpy(name, "Domain Users"); + return True; + case DOMAIN_GROUP_RID_GUESTS: + fstrcpy(name, "Domain Guests"); + return True; + case BUILTIN_ALIAS_RID_USERS: + fstrcpy(name, "Users"); + return True; + } slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid); - return False; /* Indicates that this group was 'not mapped' */ + return True; } - + fstrcpy( name, gr->gr_name); - - DEBUG(5,("local_lookup_sid: found group %s for rid %u\n", name, - (unsigned int)rid )); - return True; + + DEBUG(5,("local_lookup_rid: found group %s for rid %u\n", name, + (unsigned int)rid )); } + + return True; } /******************************************************************* Convert a name into a SID. Used in the lookup name rpc. ********************************************************************/ -BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psid_name_use) +BOOL local_lookup_name(const char *c_domain, 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; - + fstring domain; + *psid_name_use = SID_NAME_UNKNOWN; /* - * user may be quoted a const string, and map_username and - * friends can modify it. Make a modifiable copy. JRA. + * domain and user may be quoted const strings, and map_username and + * friends can modify them. Make a modifiable copy. JRA. */ + fstrcpy(domain, c_domain); fstrcpy(user, c_user); - sid_copy(&local_sid, get_global_sam_sid()); + sid_copy(&local_sid, &global_sam_sid); /* * Special case for MACHINE\Everyone. Map to the world_sid. @@ -728,51 +611,18 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi (void)map_username(user); - if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { - return False; - } - - if (pdb_getsampwnam(sam_account, user)) { - sid_copy(psid, pdb_get_user_sid(sam_account)); + if((pass = Get_Pwnam(user, False))) { + sid_append_rid( &local_sid, pdb_uid_to_user_rid(pass->pw_uid)); *psid_name_use = SID_NAME_USER; - - pdb_free_sam(&sam_account); - return True; - } - - pdb_free_sam(&sam_account); - - /* - * Maybe it was a group ? - */ - - /* check if it's a mapped group */ - if (get_group_map_from_ntname(user, &map, MAPPING_WITHOUT_PRIV)) { - /* yes it's a mapped group */ - sid_copy(&local_sid, &map.sid); - *psid_name_use = map.sid_name_use; } 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 + /* + * Maybe it was a group ? */ - - if (get_group_map_from_gid(grp->gr_gid, &map, MAPPING_WITHOUT_PRIV)){ + struct group *grp = getgrnam(user); + + if(!grp) return False; - } - + sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid)); *psid_name_use = SID_NAME_ALIAS; } @@ -788,40 +638,10 @@ 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) { - struct passwd *pass; - SAM_ACCOUNT *sam_user = NULL; - fstring str; /* sid string buffer */ - - sid_copy(psid, get_global_sam_sid()); - - if((pass = getpwuid_alloc(uid))) { - - if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user))) { - passwd_free(&pass); - return NULL; - } - - if (pdb_getsampwnam(sam_user, pass->pw_name)) { - sid_copy(psid, pdb_get_user_sid(sam_user)); - } else if (strcmp(pass->pw_name, lp_guestaccount()) == 0) { - sid_append_rid(psid, DOMAIN_USER_RID_GUEST); - } else { - sid_append_rid(psid, fallback_pdb_uid_to_user_rid(uid)); - } - - DEBUG(10,("local_uid_to_sid: uid %u -> SID (%s) (%s).\n", - (unsigned)uid, sid_to_string( str, psid), - pass->pw_name )); + extern DOM_SID global_sam_sid; - passwd_free(&pass); - pdb_free_sam(&sam_user); - - } else { - sid_append_rid(psid, fallback_pdb_uid_to_user_rid(uid)); - - DEBUG(10,("local_uid_to_sid: uid %u -> SID (%s) (unknown user).\n", - (unsigned)uid, sid_to_string( str, psid))); - } + sid_copy(psid, &global_sam_sid); + sid_append_rid(psid, pdb_uid_to_user_rid(uid)); return psid; } @@ -830,61 +650,42 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) Convert a SID to uid - locally. ****************************************************************************/ -BOOL local_sid_to_uid(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE *name_type) +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; - SAM_ACCOUNT *sam_user = NULL; + struct passwd *pass; *name_type = SID_NAME_UNKNOWN; - if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user))) - return False; - - if (pdb_getsampwsid(sam_user, psid)) { - - if (!(pdb_get_init_flag(sam_user) & FLAG_SAM_UID)) { - pdb_free_sam(&sam_user); - return False; - } + sid_copy(&dom_sid, psid); + sid_split_rid(&dom_sid, &rid); - *puid = pdb_get_uid(sam_user); - - 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))); - pdb_free_sam(&sam_user); - } else { - - DOM_SID dom_sid; - uint32 rid; - GROUP_MAP map; + if (!pdb_rid_is_user(rid)) + return False; - pdb_free_sam(&sam_user); + /* + * 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)) + return False; - if (get_group_map_from_sid(*psid, &map, MAPPING_WITHOUT_PRIV)) { - DEBUG(3, ("local_sid_to_uid: SID '%s' is a group, not a user... \n", sid_to_string(str, psid))); - /* It's a group, not a user... */ - return False; - } + *puid = pdb_user_rid_to_uid(rid); - sid_copy(&dom_sid, psid); - if (!sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) { - DEBUG(3, ("sid_peek_rid failed - sid '%s' is not in our domain\n", sid_to_string(str, psid))); - return False; - } + /* + * Ensure this uid really does exist. + */ + if(!(pass = sys_getpwuid(*puid))) + return False; - if (!pdb_rid_is_user(rid)) { - DEBUG(3, ("local_sid_to_uid: sid '%s' cannot be mapped to a uid algorithmicly becouse it is a group\n", sid_to_string(str, psid))); - return False; - } - - *puid = fallback_pdb_user_rid_to_uid(rid); - - DEBUG(5,("local_sid_to_uid: SID %s algorithmicly mapped to %ld mapped becouse SID was not found in passdb.\n", - sid_to_string(str, psid), (signed long int)(*puid))); - } + DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid), + (unsigned int)*puid, pass->pw_name )); *name_type = SID_NAME_USER; - return True; } @@ -894,16 +695,10 @@ BOOL local_sid_to_uid(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE *name_ DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid) { - GROUP_MAP map; + extern DOM_SID 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)); - } + sid_copy(psid, &global_sam_sid); + sid_append_rid(psid, pdb_gid_to_group_rid(gid)); return psid; } @@ -912,162 +707,250 @@ DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid) Convert a SID to gid - locally. ****************************************************************************/ -BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_type) +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; - GROUP_MAP map; + struct group *grp; *name_type = SID_NAME_UNKNOWN; + sid_copy(&dom_sid, psid); + sid_split_rid(&dom_sid, &rid); + /* * We can only convert to a gid if this is our local * Domain SID (ie. we are the controling authority). - * - * Or in the Builtin SID too. JFM, 11/30/2001 */ - if (get_group_map_from_sid(*psid, &map, MAPPING_WITHOUT_PRIV)) { - - /* the SID is in the mapping table but not mapped */ - if (map.gid==-1) - return False; + if (!sid_equal(&global_sam_sid, &dom_sid)) + return False; + + if (pdb_rid_is_user(rid)) + 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)); + *pgid = pdb_user_rid_to_gid(rid); - } else { - uint32 rid; - SAM_ACCOUNT *sam_user = NULL; - if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user))) - return False; - - if (pdb_getsampwsid(sam_user, psid)) { - return False; - pdb_free_sam(&sam_user); - } + /* + * Ensure this gid really does exist. + */ - pdb_free_sam(&sam_user); + if(!(grp = getgrgid(*pgid))) + return False; - if (!sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) { - DEBUG(3, ("sid_peek_rid failed - sid '%s' is not in our domain\n", sid_to_string(str, psid))); - return False; - } + *name_type = SID_NAME_ALIAS; + + DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u) (%s).\n", sid_to_string( str, psid), + (unsigned int)*pgid, grp->gr_name )); - 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)); - } - return True; } -/** - * Quick hack to do an easy ucs2 -> mulitbyte conversion - * @return static buffer containing the converted string - **/ +static void select_name(pstring string, const UNISTR2 *from) +{ + if (from->buffer != 0) + unistr2_to_dos(string, from, sizeof(pstring)); +} -const char *pdb_unistr2_convert(const UNISTR2 *from) +/************************************************************* + Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT + **************************************************************/ + +void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from) { - static pstring convert_buffer; - *convert_buffer = 0; - if (!from) { - return NULL; - } - unistr2_to_ascii(convert_buffer, from, sizeof(pstring)); - return convert_buffer; + if (from == NULL || to == NULL) + return; + + to->logon_time = nt_time_to_unix(&from->logon_time); + to->logoff_time = nt_time_to_unix(&from->logoff_time); + to->kickoff_time = nt_time_to_unix(&from->kickoff_time); + to->pass_last_set_time = nt_time_to_unix(&from->pass_last_set_time); + to->pass_can_change_time = nt_time_to_unix(&from->pass_can_change_time); + to->pass_must_change_time = nt_time_to_unix(&from->pass_must_change_time); + + select_name(to->username , &from->uni_user_name ); + select_name(to->full_name , &from->uni_full_name ); + select_name(to->home_dir , &from->uni_home_dir ); + select_name(to->dir_drive , &from->uni_dir_drive ); + select_name(to->logon_script, &from->uni_logon_script); + select_name(to->profile_path, &from->uni_profile_path); + select_name(to->acct_desc , &from->uni_acct_desc ); + select_name(to->workstations, &from->uni_workstations); + select_name(to->unknown_str , &from->uni_unknown_str ); + select_name(to->munged_dial , &from->uni_munged_dial ); + + to->user_rid = from->user_rid; + to->group_rid = from->group_rid; + + to->acct_ctrl = from->acb_info; + to->unknown_3 = from->unknown_3; + + to->logon_divs = from->logon_divs; + to->hours_len = from->logon_hrs.len; + memcpy(to->hours, from->logon_hrs.hours, MAX_HOURS_LEN); + + to->unknown_5 = from->unknown_5; + to->unknown_6 = 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; + + to->logon_time = nt_time_to_unix(&from->logon_time); + to->logoff_time = nt_time_to_unix(&from->logoff_time); + to->kickoff_time = nt_time_to_unix(&from->kickoff_time); + to->pass_last_set_time = nt_time_to_unix(&from->pass_last_set_time); + to->pass_can_change_time = nt_time_to_unix(&from->pass_can_change_time); + to->pass_must_change_time = nt_time_to_unix(&from->pass_must_change_time); + + select_name(to->username , &from->uni_user_name ); + select_name(to->full_name , &from->uni_full_name ); + select_name(to->home_dir , &from->uni_home_dir ); + select_name(to->dir_drive , &from->uni_dir_drive ); + select_name(to->logon_script, &from->uni_logon_script); + select_name(to->profile_path, &from->uni_profile_path); + select_name(to->acct_desc , &from->uni_acct_desc ); + select_name(to->workstations, &from->uni_workstations); + select_name(to->unknown_str , &from->uni_unknown_str ); + select_name(to->munged_dial , &from->uni_munged_dial ); + + to->user_rid = from->user_rid; + to->group_rid = from->group_rid; + + /* FIXME!! Do we need to copy the passwords here as well? + I don't know. Need to figure this out --jerry */ + + to->acct_ctrl = from->acb_info; + to->unknown_3 = from->unknown_3; + + to->logon_divs = from->logon_divs; + to->hours_len = from->logon_hrs.len; + memcpy(to->hours, from->logon_hrs.hours, MAX_HOURS_LEN); + + to->unknown_5 = from->unknown_5; + to->unknown_6 = from->unknown_6; } +#if 0 /* JERRY */ +/************************************************************* + Copies a SAM_ACCOUNT. + FIXME!!!! This is broken as SAM_ACCOUNT contains two + pointers. --jerry + **************************************************************/ + +void copy_sam_passwd(SAM_ACCOUNT *to, const SAM_ACCOUNT *from) +{ + if (!from || !to) + return; + + memcpy(to, from, sizeof(SAM_ACCOUNT)); + + +} +#endif + /************************************************************* Change a password entry in the local smbpasswd file. FIXME!! The function needs to be abstracted into the passdb interface or something. It is currently being called - by _api_samr_create_user() in rpc_server/srv_samr.c, - in SWAT and by smbpasswd/pdbedit. + by _api_samr_create_user() in rpc_server/srv_samr.c --jerry *************************************************************/ -BOOL local_password_change(const char *user_name, int local_flags, - const char *new_passwd, +BOOL local_password_change(char *user_name, int local_flags, + char *new_passwd, char *err_str, size_t err_str_len, char *msg_str, size_t msg_str_len) { struct passwd *pwd = NULL; SAM_ACCOUNT *sam_pass=NULL; - uint16 other_acb; *err_str = '\0'; *msg_str = '\0'; + if (local_flags & LOCAL_ADD_USER) { + + /* + * Check for a local account - if we're adding only. + */ + + if(!(pwd = sys_getpwnam(user_name))) { + slprintf(err_str, err_str_len - 1, "User %s does not \ +exist in system password file (usually /etc/passwd). Cannot add \ +account without a valid local system user.\n", user_name); + return False; + } + } + /* Get the smb passwd entry for this user */ pdb_init_sam(&sam_pass); + if(local_flags & LOCAL_DELETE_USER) { + if (!pdb_delete_sam_account(user_name)) { + slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name); + pdb_free_sam(sam_pass); + return False; + } + slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name); + pdb_free_sam(sam_pass); + return True; + } if(!pdb_getsampwnam(sam_pass, user_name)) { - pdb_free_sam(&sam_pass); + pdb_free_sam(sam_pass); - if (local_flags & LOCAL_ADD_USER) { - pwd = getpwnam_alloc(user_name); - } else if (local_flags & LOCAL_DELETE_USER) { - /* Might not exist in /etc/passwd */ - } else { + if(!(local_flags & LOCAL_ADD_USER)) { slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name); return False; } - - if (pwd) { - /* Local user found, so init from this */ - if (!NT_STATUS_IS_OK(pdb_init_sam_pw(&sam_pass, pwd))){ - slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name); - passwd_free(&pwd); - return False; - } - - passwd_free(&pwd); + + sam_pass = NULL; + if (!pdb_init_sam_pw(&sam_pass, sys_getpwnam(user_name))) { + return False; + } + + /* Set account flags. Note that the default is non-expiring accounts */ + pdb_set_acct_ctrl(sam_pass,(local_flags & LOCAL_TRUST_ACCOUNT) ? ACB_WSTRUST : ACB_NORMAL|ACB_PWNOEXP); + + if (local_flags & LOCAL_DISABLE_USER) + pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED); + + if (local_flags & LOCAL_SET_NO_PASSWORD) { + pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ); } else { - if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_pass))){ - slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name); + /* set the passwords here. if we get to here it means + we have a valid, active account */ + if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) { + pdb_free_sam(sam_pass); return False; } - - if (!pdb_set_username(sam_pass, user_name)) { - slprintf(err_str, err_str_len - 1, "Failed to set username for user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return False; - } } - } else { - /* the entry already existed */ - local_flags &= ~LOCAL_ADD_USER; - } - /* the 'other' acb bits not being changed here */ - other_acb = (pdb_get_acct_ctrl(sam_pass) & (!(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL))); - if (local_flags & LOCAL_TRUST_ACCOUNT) { - if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb) ) { - slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return False; - } - } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) { - if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb)) { - slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name); - pdb_free_sam(&sam_pass); + /* Remember to set the "last changed time". */ + pdb_set_pass_last_set_time(sam_pass, time(NULL)); + + if (pdb_add_sam_account(sam_pass)) { + slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name); + pdb_free_sam(sam_pass); + return True; + } else { + slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name); + pdb_free_sam(sam_pass); return False; } } else { - if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb)) { - slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return False; - } + /* the entry already existed */ + local_flags &= ~LOCAL_ADD_USER; + slprintf(msg_str, msg_str_len-1, "Password changed for user %s.\n", user_name ); } /* @@ -1075,27 +958,28 @@ BOOL local_password_change(const char *user_name, int local_flags, * and the valid last change time. */ - if (local_flags & LOCAL_DISABLE_USER) { - if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED)) { - slprintf(err_str, err_str_len-1, "Failed to set 'disabled' flag for user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return False; - } + if(local_flags & LOCAL_DISABLE_USER) { + pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED); } else if (local_flags & LOCAL_ENABLE_USER) { - if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED))) { - slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name); - pdb_free_sam(&sam_pass); + if(pdb_get_lanman_passwd(sam_pass) == NULL) { + if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) { + pdb_free_sam(sam_pass); + return False; + } + } + pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED)); + } else if (local_flags & LOCAL_SET_NO_PASSWORD) { + pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ); + /* This is needed to preserve ACB_PWNOTREQ in mod_smbfilepwd_entry */ + if (!pdb_set_lanman_passwd (sam_pass, NULL)) { + pdb_free_sam(sam_pass); return False; } - } - - if (local_flags & LOCAL_SET_NO_PASSWORD) { - if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ)) { - slprintf(err_str, err_str_len-1, "Failed to set 'no password required' flag for user %s.\n", user_name); - pdb_free_sam(&sam_pass); + if (!pdb_set_nt_passwd(sam_pass, NULL)) { + pdb_free_sam(sam_pass); return False; } - } else if (local_flags & LOCAL_SET_PASSWORD) { + } else { /* * If we're dealing with setting a completely empty user account * ie. One with a password of 'XXXX', but not set disabled (like @@ -1105,57 +989,768 @@ BOOL local_password_change(const char *user_name, int local_flags, * and the decision hasn't really been made to disable them (ie. * don't create them disabled). JRA. */ - if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) { - if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED))) { - slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return False; - } - } - if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ))) { - slprintf(err_str, err_str_len-1, "Failed to unset 'no password required' flag for user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return False; - } - + if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) + pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED)); + pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ)); if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) { - slprintf(err_str, err_str_len-1, "Failed to set password for user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return False; + pdb_free_sam(sam_pass); + return False; } - } + } + + if(!pdb_update_sam_account(sam_pass, True)) { + slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name); + pdb_free_sam(sam_pass); + return False; + } + if(local_flags & LOCAL_DISABLE_USER) + slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name); + else if (local_flags & LOCAL_ENABLE_USER) + slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name); + else if (local_flags & LOCAL_SET_NO_PASSWORD) + slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name); + + pdb_free_sam(sam_pass); + return True; +} - if (local_flags & LOCAL_ADD_USER) { - if (pdb_add_sam_account(sam_pass)) { - slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return True; - } else { - slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return False; - } - } else if (local_flags & LOCAL_DELETE_USER) { - if (!pdb_delete_sam_account(sam_pass)) { - slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return False; - } - slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name); - } else { - if(!pdb_update_sam_account(sam_pass)) { - slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name); - pdb_free_sam(&sam_pass); - return False; - } - if(local_flags & LOCAL_DISABLE_USER) - slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name); - else if (local_flags & LOCAL_ENABLE_USER) - slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name); - else if (local_flags & LOCAL_SET_NO_PASSWORD) - slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name); +/********************************************************************* + Collection of get...() functions for SAM_ACCOUNT_INFO. + ********************************************************************/ + +uint16 pdb_get_acct_ctrl (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->acct_ctrl); + else + return (ACB_DISABLED); +} + +time_t pdb_get_logon_time (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->logon_time); + else + return (0); +} + +time_t pdb_get_logoff_time (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->logoff_time); + else + return (-1); +} + +time_t pdb_get_kickoff_time (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->kickoff_time); + else + return (-1); +} + +time_t pdb_get_pass_last_set_time (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->pass_last_set_time); + else + return (-1); +} + +time_t pdb_get_pass_can_change_time (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->pass_can_change_time); + else + return (-1); +} + +time_t pdb_get_pass_must_change_time (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->pass_must_change_time); + else + return (-1); +} + +uint16 pdb_get_logon_divs (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->logon_divs); + else + return (-1); +} + +uint32 pdb_get_hours_len (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->hours_len); + else + return (-1); +} + +uint8* pdb_get_hours (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->hours); + else + return (NULL); +} + +uint8* pdb_get_nt_passwd (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->nt_pw); + else + return (NULL); +} + +uint8* pdb_get_lanman_passwd (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->lm_pw); + else + return (NULL); +} + +uint32 pdb_get_user_rid (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->user_rid); + else + return (-1); +} + +uint32 pdb_get_group_rid (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->group_rid); + else + return (-1); +} + +uid_t pdb_get_uid (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->uid); + else + return ((uid_t)-1); +} + +gid_t pdb_get_gid (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->gid); + else + return ((gid_t)-1); +} + +char* pdb_get_username (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->username); + else + return (NULL); +} + +char* pdb_get_domain (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->domain); + else + return (NULL); +} + +char* pdb_get_nt_username (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->nt_username); + else + return (NULL); +} + +char* pdb_get_fullname (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->full_name); + else + return (NULL); +} + +char* pdb_get_homedir (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->home_dir); + else + return (NULL); +} + +char* pdb_get_dirdrive (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->dir_drive); + else + return (NULL); +} + +char* pdb_get_logon_script (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->logon_script); + else + return (NULL); +} + +char* pdb_get_profile_path (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->profile_path); + else + return (NULL); +} + +char* pdb_get_acct_desc (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->acct_desc); + else + return (NULL); +} + +char* pdb_get_workstations (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->workstations); + else + return (NULL); +} + +char* pdb_get_munged_dial (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->munged_dial); + else + return (NULL); +} + +uint32 pdb_get_unknown3 (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->unknown_3); + else + return (-1); +} + +uint32 pdb_get_unknown5 (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->unknown_5); + else + return (-1); +} + +uint32 pdb_get_unknown6 (SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->unknown_6); + else + return (-1); +} + +/********************************************************************* + Collection of set...() functions for SAM_ACCOUNT_INFO. + ********************************************************************/ + +BOOL pdb_set_acct_ctrl (SAM_ACCOUNT *sampass, uint16 flags) +{ + if (!sampass) + return False; + + if (sampass) { + sampass->acct_ctrl = flags; + return True; } + + return False; +} + +BOOL pdb_set_logon_time (SAM_ACCOUNT *sampass, time_t mytime) +{ + if (!sampass) + return False; + + sampass->logon_time = mytime; + return True; +} + +BOOL pdb_set_logoff_time (SAM_ACCOUNT *sampass, time_t mytime) +{ + if (!sampass) + return False; + + sampass->logoff_time = mytime; + return True; +} + +BOOL pdb_set_kickoff_time (SAM_ACCOUNT *sampass, time_t mytime) +{ + if (!sampass) + return False; + + sampass->kickoff_time = mytime; + return True; +} + +BOOL pdb_set_pass_can_change_time (SAM_ACCOUNT *sampass, time_t mytime) +{ + if (!sampass) + return False; + + sampass->pass_can_change_time = mytime; + return True; +} + +BOOL pdb_set_pass_must_change_time (SAM_ACCOUNT *sampass, time_t mytime) +{ + if (!sampass) + return False; + + sampass->pass_must_change_time = mytime; + return True; +} + +BOOL pdb_set_pass_last_set_time (SAM_ACCOUNT *sampass, time_t mytime) +{ + if (!sampass) + return False; + + sampass->pass_last_set_time = mytime; + return True; +} + +BOOL pdb_set_hours_len (SAM_ACCOUNT *sampass, uint32 len) +{ + if (!sampass) + return False; + + sampass->hours_len = len; + return True; +} + +BOOL pdb_set_logon_divs (SAM_ACCOUNT *sampass, uint16 hours) +{ + if (!sampass) + return False; + + sampass->logon_divs = hours; + return True; +} + +BOOL pdb_set_init_flag (SAM_ACCOUNT *sampass, uint32 flag) +{ + if (!sampass) + return False; + + sampass->init_flag |= flag; + + return True; +} + +BOOL pdb_set_uid (SAM_ACCOUNT *sampass, uid_t uid) +{ + if (!sampass) + return False; + + sampass->uid = uid; + sampass->init_flag |= FLAG_SAM_UID; + + return True; +} + +BOOL pdb_set_gid (SAM_ACCOUNT *sampass, gid_t gid) +{ + if (!sampass) + return False; + + sampass->gid = gid; + sampass->init_flag |= FLAG_SAM_GID; - pdb_free_sam(&sam_pass); return True; } + +BOOL pdb_set_user_rid (SAM_ACCOUNT *sampass, uint32 rid) +{ + if (!sampass) + return False; + + sampass->user_rid = rid; + return True; +} + +BOOL pdb_set_group_rid (SAM_ACCOUNT *sampass, uint32 grid) +{ + if (!sampass) + return False; + + sampass->group_rid = grid; + return True; +} + +/********************************************************************* + Set the user's UNIX name. + ********************************************************************/ + +BOOL pdb_set_username(SAM_ACCOUNT *sampass, char *username) +{ + if (!sampass) + return False; + *sampass->username = '\0'; + if (!username) + return False; + + StrnCpy (sampass->username, username, sizeof(sampass->username)-1); + + return True; +} + +/********************************************************************* + Set the domain name. + ********************************************************************/ + +BOOL pdb_set_domain(SAM_ACCOUNT *sampass, char *domain) +{ + if (!sampass) + return False; + *sampass->domain = '\0'; + if (!domain) + return False; + + StrnCpy (sampass->domain, domain, sizeof(sampass->domain)-1); + + return True; +} + +/********************************************************************* + Set the user's NT name. + ********************************************************************/ + +BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, char *nt_username) +{ + if (!sampass) + return False; + *sampass->nt_username = '\0'; + if (!nt_username) + return False; + + StrnCpy (sampass->nt_username, nt_username, sizeof(sampass->nt_username) -1); + + return True; +} + +/********************************************************************* + Set the user's full name. + ********************************************************************/ + +BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, char *fullname) +{ + if (!sampass) + return False; + *sampass->full_name = '\0'; + if (!fullname) + return False; + + StrnCpy (sampass->full_name, fullname, sizeof(sampass->full_name)-1); + + return True; +} + +/********************************************************************* + Set the user's logon script. + ********************************************************************/ + +BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, char *logon_script, BOOL store) +{ + if (!sampass) + return False; + *sampass->logon_script = '\0'; + if (!logon_script) + return False; + + StrnCpy (sampass->logon_script, logon_script, sizeof(sampass->logon_script)-1); + + if (store) + pdb_set_init_flag(sampass, FLAG_SAM_LOGONSCRIPT); + + return True; +} + +/********************************************************************* + Set the user's profile path. + ********************************************************************/ + +BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, char *profile_path, BOOL store) +{ + if (!sampass) + return False; + *sampass->profile_path = '\0'; + if (!profile_path) + return False; + + StrnCpy (sampass->profile_path, profile_path, sizeof(sampass->profile_path)-1); + + if (store) + pdb_set_init_flag(sampass, FLAG_SAM_PROFILE); + + return True; +} + +/********************************************************************* + Set the user's directory drive. + ********************************************************************/ + +BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, char *dir_drive, BOOL store) +{ + if (!sampass) + return False; + *sampass->dir_drive = '\0'; + if (!dir_drive) + return False; + + StrnCpy (sampass->dir_drive, dir_drive, sizeof(sampass->dir_drive)-1); + + if (store) + pdb_set_init_flag(sampass, FLAG_SAM_DRIVE); + + return True; +} + +/********************************************************************* + Set the user's home directory. + ********************************************************************/ + +BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, char *homedir, BOOL store) +{ + if (!sampass) + return False; + *sampass->home_dir = '\0'; + if (!homedir) + return False; + + StrnCpy (sampass->home_dir, homedir, sizeof(sampass->home_dir)-1); + + if (store) + pdb_set_init_flag(sampass, FLAG_SAM_SMBHOME); + + return True; +} + +/********************************************************************* + Set the user's account description. + ********************************************************************/ + +BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, char *acct_desc) +{ + if (!sampass) + return False; + *sampass->acct_desc = '\0'; + if (!acct_desc) + return False; + + StrnCpy (sampass->acct_desc, acct_desc, sizeof(sampass->acct_desc)-1); + + return True; +} + +/********************************************************************* + Set the user's workstation allowed list. + ********************************************************************/ + +BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, char *workstations) +{ + if (!sampass) + return False; + *sampass->workstations = '\0'; + if (!workstations) + return False; + + StrnCpy (sampass->workstations, workstations, sizeof(sampass->workstations)-1); + + return True; +} + +/********************************************************************* + Set the user's dial string. + ********************************************************************/ + +BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, char *munged_dial) +{ + if (!sampass) + return False; + *sampass->munged_dial = '\0'; + if (!munged_dial) + return False; + + StrnCpy (sampass->munged_dial, munged_dial, sizeof(sampass->munged_dial)-1); + + return True; +} + +/********************************************************************* + Set the user's NT hash. + ********************************************************************/ + +BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, uint8 *pwd) +{ + if (!sampass) + return False; + + /* Remember to set the "last changed time". */ + pdb_set_pass_last_set_time(sampass, time(NULL)); + + if (!pwd) { + /* Allow setting to NULL */ + SAFE_FREE(sampass->nt_pw); + return True; + } + + if (sampass->nt_pw!=NULL) + DEBUG(4,("pdb_set_nt_passwd: NT hash non NULL overwritting ?\n")); + else + sampass->nt_pw=(unsigned char *)malloc(sizeof(unsigned char)*16); + + if (sampass->nt_pw==NULL) + return False; + + memcpy (sampass->nt_pw, pwd, 16); + + return True; +} + +/********************************************************************* + Set the user's LM hash. + ********************************************************************/ + +BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, uint8 *pwd) +{ + if (!sampass) + return False; + + /* Remember to set the "last changed time". */ + pdb_set_pass_last_set_time(sampass, time(NULL)); + + if (!pwd) { + /* Allow setting to NULL */ + SAFE_FREE(sampass->lm_pw); + return True; + } + + if (sampass->lm_pw!=NULL) + DEBUG(4,("pdb_set_lanman_passwd: LM hash non NULL overwritting ?\n")); + else + sampass->lm_pw=(unsigned char *)malloc(sizeof(unsigned char)*16); + + if (sampass->lm_pw==NULL) + return False; + + memcpy (sampass->lm_pw, pwd, 16); + + return True; +} + +/********************************************************************* + Set the user's PLAINTEXT password. Used as an interface to the above. + ********************************************************************/ + +BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, char *plaintext) +{ + uchar new_lanman_p16[16]; + uchar new_nt_p16[16]; + + if (!sampass || !plaintext) + return False; + + nt_lm_owf_gen (plaintext, new_nt_p16, new_lanman_p16); + + if (!pdb_set_nt_passwd (sampass, new_nt_p16)) + return False; + + if (!pdb_set_lanman_passwd (sampass, new_lanman_p16)) + return False; + + return True; +} + +BOOL pdb_set_unknown_3 (SAM_ACCOUNT *sampass, uint32 unkn) +{ + if (!sampass) + return False; + + sampass->unknown_3 = unkn; + return True; +} + +BOOL pdb_set_unknown_5 (SAM_ACCOUNT *sampass, uint32 unkn) +{ + if (!sampass) + return False; + + sampass->unknown_5 = unkn; + return True; +} + +BOOL pdb_set_unknown_6 (SAM_ACCOUNT *sampass, uint32 unkn) +{ + if (!sampass) + return False; + + sampass->unknown_6 = unkn; + return True; +} + +BOOL pdb_set_hours (SAM_ACCOUNT *sampass, uint8 *hours) +{ + if (!sampass) + return False; + + if (!hours) { + memset ((char *)sampass->hours, 0, MAX_HOURS_LEN); + return True; + } + + memcpy (sampass->hours, hours, MAX_HOURS_LEN); + + return True; +} + +/*************************************************************************** + Search by uid. Wrapper around pdb_getsampwnam() + **************************************************************************/ + +BOOL pdb_getsampwuid (SAM_ACCOUNT* user, uid_t uid) +{ + struct passwd *pw; + fstring name; + + if (user==NULL) { + DEBUG(0,("pdb_getsampwuid: SAM_ACCOUNT is NULL.\n")); + return False; + } + + /* + * Never trust the uid in the passdb. Lookup the username first + * and then lokup the user by name in the sam. + */ + + if ((pw=sys_getpwuid(uid)) == NULL) { + DEBUG(0,("pdb_getsampwuid: getpwuid(%u) return NULL. User does not exist in Unix accounts!\n", + (unsigned int)uid)); + return False; + } + + fstrcpy (name, pw->pw_name); + + return pdb_getsampwnam (user, name); + +} + |