From 43a460075a39148060d4193fcb9c62bfa4acc737 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 25 Mar 1999 13:54:31 +0000 Subject: SAM database "set user info". ---------------------------- - removed DOM_RID4 - removed SAMR_UNKNOWN_32 - added SAMR_SET_USERINFO (opcode 0x32) - added level 0x1 to SAMR_QUERY_DOM_INFO (needed for create user) - fixed pwdb_gethexpwd() it was failing on XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - added mod_sam21pwd_entry() - preparing to call mod_sam21pwd_entry() - added "user session key" to user_struct.dc. this is md4(nt#) and is needed to decode user's clear-text passwords in SAMR_SET_USERINFO. - split code out in chgpasswd.c to decode 516 byte password buffers. (This used to be commit 2e58ed742435befe419aa366c4052019fede8c23) --- source3/include/proto.h | 57 ++++++- source3/include/rpc_misc.h | 9 -- source3/include/rpc_samr.h | 130 +++++++++++---- source3/include/smb.h | 2 + source3/lib/util_pwdb.c | 21 ++- source3/passdb/ldap.c | 4 +- source3/passdb/sampassdb.c | 14 ++ source3/passdb/smbpass.c | 4 +- source3/passdb/smbpassfile.c | 2 +- source3/rpc_parse/parse_misc.c | 10 -- source3/rpc_parse/parse_samr.c | 326 ++++++++++++++++++++++++++++++++++++-- source3/rpc_server/srv_pipe.c | 10 +- source3/rpc_server/srv_pipe_hnd.c | 2 +- source3/rpc_server/srv_samr.c | 244 ++++++++++++++++++++++------ source3/smbd/chgpasswd.c | 61 ++++--- source3/smbd/ipc.c | 2 +- source3/smbd/password.c | 37 +++-- source3/smbd/reply.c | 7 +- 18 files changed, 772 insertions(+), 170 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 83bea437fa..8e8e7e292a 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -492,7 +492,7 @@ void pwdb_set_can_change_time(char *p, int max_len, time_t t); void pwdb_set_must_change_time(char *p, int max_len, time_t t); void pwdb_set_last_set_time(char *p, int max_len, time_t t); void pwdb_sethexpwd(char *p, const char *pwd, uint16 acct_ctrl); -BOOL pwdb_gethexpwd(const char *p, char *pwd); +BOOL pwdb_gethexpwd(const char *p, char *pwd, uint32 *acct_ctrl); BOOL pwdb_initialise(BOOL is_server); /*The following definitions come from lib/util_sid.c */ @@ -1507,6 +1507,7 @@ BOOL initialise_sam_password_db(void); void *startsam21pwent(BOOL update); void endsam21pwent(void *vp); struct sam_passwd *getsam21pwent(void *vp); +BOOL mod_sam21pwd_entry(struct sam_passwd* pwd, BOOL override); struct sam_passwd *iterate_getsam21pwntnam(const char *ntname); struct sam_passwd *iterate_getsam21pwrid(uint32 rid); struct sam_passwd *iterate_getsam21pwuid(uid_t uid); @@ -1973,7 +1974,6 @@ void make_dom_rid2(DOM_RID2 *rid2, uint32 rid, uint8 type, uint32 idx); void smb_io_dom_rid2(char *desc, DOM_RID2 *rid2, prs_struct *ps, int depth); void make_dom_rid3(DOM_RID3 *rid3, uint32 rid, uint8 type); void smb_io_dom_rid3(char *desc, DOM_RID3 *rid3, prs_struct *ps, int depth); -void make_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid); void make_log_info(DOM_LOG_INFO *log, const char *logon_srv, const char *acct_name, uint16 sec_chan, const char *comp_name); @@ -2264,6 +2264,8 @@ void make_unk_info7(SAM_UNK_INFO_7 *u_7); void sam_io_unk_info7(char *desc, SAM_UNK_INFO_7 *u_7, prs_struct *ps, int depth); void make_unk_info2(SAM_UNK_INFO_2 *u_2, char *domain, char *server); void sam_io_unk_info2(char *desc, SAM_UNK_INFO_2 *u_2, prs_struct *ps, int depth); +void make_unk_info1(SAM_UNK_INFO_1 *u_1); +void sam_io_unk_info1(char *desc, SAM_UNK_INFO_1 *u_1, prs_struct *ps, int depth); void make_samr_r_query_dom_info(SAMR_R_QUERY_DOMAIN_INFO *r_u, uint16 switch_value, SAM_UNK_CTR *ctr, uint32 status); @@ -2456,6 +2458,10 @@ void make_samr_q_create_user(SAMR_Q_CREATE_USER *q_u, const char *name, uint16 acb_info, uint32 unk_1); void samr_io_q_create_user(char *desc, SAMR_Q_CREATE_USER *q_u, prs_struct *ps, int depth); +void make_samr_r_create_user(SAMR_R_CREATE_USER *r_u, + POLICY_HND *user_pol, + uint32 unk_0, uint32 user_rid, + uint32 status); void samr_io_r_create_user(char *desc, SAMR_R_CREATE_USER *r_u, prs_struct *ps, int depth); void make_samr_q_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u, POLICY_HND *hnd, uint16 switch_value); @@ -2470,6 +2476,36 @@ void make_sam_user_info11(SAM_USER_INFO_11 *usr, uint32 rid_group, uint16 acct_ctrl); void sam_io_user_info11(char *desc, SAM_USER_INFO_11 *usr, prs_struct *ps, int depth); +void make_sam_user_info23(SAM_USER_INFO_23 *usr, + + NTTIME *logon_time, /* all zeros */ + NTTIME *logoff_time, /* all zeros */ + NTTIME *kickoff_time, /* all zeros */ + NTTIME *pass_last_set_time, /* all zeros */ + NTTIME *pass_can_change_time, /* all zeros */ + NTTIME *pass_must_change_time, /* all zeros */ + + char *user_name, /* NULL */ + char *full_name, + char *home_dir, + char *dir_drive, + char *logon_script, + char *profile_path, + char *description, + char *workstations, + char *unknown_str, + char *munged_dial, + + uint32 user_rid, /* 0x0000 0000 */ + uint32 group_rid, + uint16 acb_info, + + uint32 unknown_3, + uint16 logon_divs, + LOGON_HRS *hrs, + uint32 unknown_5, + char newpass[516], + uint32 unknown_6); void make_sam_user_info21(SAM_USER_INFO_21 *usr, NTTIME *logon_time, @@ -2502,8 +2538,12 @@ void make_sam_user_info21(SAM_USER_INFO_21 *usr, void make_samr_r_query_userinfo(SAMR_R_QUERY_USERINFO *r_u, uint16 switch_value, void *info, uint32 status); void samr_io_r_query_userinfo(char *desc, SAMR_R_QUERY_USERINFO *r_u, prs_struct *ps, int depth); -void samr_io_q_unknown_32(char *desc, SAMR_Q_UNKNOWN_32 *q_u, prs_struct *ps, int depth); -void samr_io_r_unknown_32(char *desc, SAMR_R_UNKNOWN_32 *r_u, prs_struct *ps, int depth); +void make_samr_q_set_userinfo(SAMR_Q_SET_USERINFO *q_u, + POLICY_HND *hnd, + uint16 switch_value, void *info); +void samr_io_q_set_userinfo(char *desc, SAMR_Q_SET_USERINFO *q_u, prs_struct *ps, int depth); +void make_samr_r_set_userinfo(SAMR_R_SET_USERINFO *r_u, uint32 status); +void samr_io_r_set_userinfo(char *desc, SAMR_R_SET_USERINFO *r_u, prs_struct *ps, int depth); void make_samr_q_connect(SAMR_Q_CONNECT *q_u, char *srv_name, uint32 unknown_0); void samr_io_q_connect(char *desc, SAMR_Q_CONNECT *q_u, prs_struct *ps, int depth); @@ -2932,6 +2972,8 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2 BOOL pass_oem_change(char *user, uchar *lmdata, uchar *lmhash, uchar *ntdata, uchar *nthash); +BOOL decode_pw_buffer(const char buffer[516], char *new_passwd, + int new_passwd_size, BOOL nt_pass_set); BOOL check_oem_password(char *user, uchar *lmdata, uchar *lmhash, uchar *ntdata, uchar *nthash, @@ -3119,15 +3161,16 @@ BOOL set_challenge(unsigned char *challenge); user_struct *get_valid_user_struct(uint16 vuid); void invalidate_vuid(uint16 vuid); char *validated_username(uint16 vuid); -uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest); +uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]); void add_session_user(char *user); BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8); BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], uchar lm_pass[24], uchar nt_pass[24]); BOOL pass_check_smb(char *user, char *domain, uchar *chal, uchar *lm_pwd, uchar *nt_pwd, - struct passwd *pwd); -BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd); + struct passwd *pwd, uchar user_sess_key[16]); +BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, + uchar user_sess_key[16]); BOOL user_ok(char *user,int snum); BOOL authorise_login(int snum,char *user,char *password, int pwlen, BOOL *guest,BOOL *force,uint16 vuid); diff --git a/source3/include/rpc_misc.h b/source3/include/rpc_misc.h index 1c5689dd87..3e4d52a038 100644 --- a/source3/include/rpc_misc.h +++ b/source3/include/rpc_misc.h @@ -212,15 +212,6 @@ typedef struct domrid3_info } DOM_RID3; -/* DOM_RID4 - rid + user attributes */ -typedef struct domrid4_info -{ - uint32 unknown; - uint16 attr; - uint32 rid; /* user RID */ - -} DOM_RID4; - /* DOM_CLNT_SRV - client / server names */ typedef struct clnt_srv_info { diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index 44e1c61484..92125f9f2c 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -68,7 +68,7 @@ SamrRemoveMultipleMembersFromAlias x SamrSetInformationAlias SamrSetInformationDomain x SamrSetInformationGroup -SamrSetInformationUser +x SamrSetInformationUser SamrSetMemberAttributesOfGroup SamrSetSecurityObject SamrShutdownSamServer @@ -114,6 +114,7 @@ SamrTestPrivateFunctionsUser #define SAMR_OPEN_USER 0x22 #define SAMR_CREATE_USER 0x32 +#define SAMR_SET_USERINFO 0x3A #define SAMR_QUERY_USERINFO 0x24 #define SAMR_QUERY_USERGROUPS 0x27 @@ -122,7 +123,6 @@ SamrTestPrivateFunctionsUser #define SAMR_UNKNOWN_2C 0x2c #define SAMR_QUERY_DISPINFO3 0x30 /* Alias for SAMR_QUERY_DISPINFO with info level 3 */ -#define SAMR_UNKNOWN_32 0x32 #define SAMR_QUERY_DISPINFO4 0x33 /* Alias for SAMR_QUERY_DISPINFO with info level 4 */ #define SAMR_UNKNOWN_34 0x34 @@ -140,6 +140,67 @@ typedef struct logon_hours_info } LOGON_HRS; +/* SAM_USER_INFO_23 */ +typedef struct sam_user_info_23 +{ + NTTIME logon_time; /* logon time */ + NTTIME logoff_time; /* logoff time */ + NTTIME kickoff_time; /* kickoff time */ + NTTIME pass_last_set_time; /* password last set time */ + NTTIME pass_can_change_time; /* password can change time */ + NTTIME pass_must_change_time; /* password must change time */ + + UNIHDR hdr_user_name; /* NULL - user name unicode string header */ + UNIHDR hdr_full_name; /* user's full name unicode string header */ + UNIHDR hdr_home_dir; /* home directory unicode string header */ + UNIHDR hdr_dir_drive; /* home drive unicode string header */ + UNIHDR hdr_logon_script; /* logon script unicode string header */ + UNIHDR hdr_profile_path; /* profile path unicode string header */ + UNIHDR hdr_acct_desc ; /* user description */ + UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */ + UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */ + UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */ + + uint8 lm_pwd[16]; /* lm user passwords */ + uint8 nt_pwd[16]; /* nt user passwords */ + + uint32 user_rid; /* Primary User ID */ + uint32 group_rid; /* Primary Group ID */ + + uint16 acb_info; /* account info (ACB_xxxx bit-mask) */ + /* uint8 pad[2] */ + + uint32 unknown_3; /* 0x09f8 27fa */ + + uint16 logon_divs; /* 0x0000 00a8 which is 168 which is num hrs in a week */ + /* uint8 pad[2] */ + uint32 ptr_logon_hrs; /* pointer to logon hours */ + + uint8 padding1[8]; + + uint32 unknown_5; /* 0x0001 0000 */ + + uint8 pass[516]; + + UNISTR2 uni_user_name; /* NULL - username unicode string */ + UNISTR2 uni_full_name; /* user's full name unicode string */ + UNISTR2 uni_home_dir; /* home directory unicode string */ + UNISTR2 uni_dir_drive; /* home directory drive unicode string */ + UNISTR2 uni_logon_script; /* logon script unicode string */ + UNISTR2 uni_profile_path; /* profile path unicode string */ + UNISTR2 uni_acct_desc ; /* user description unicode string */ + UNISTR2 uni_workstations; /* login from workstations unicode string */ + UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */ + UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel number */ + + uint32 unknown_6; /* 0x0000 04ec */ + uint32 padding4; + + LOGON_HRS logon_hrs; + +} SAM_USER_INFO_23; + + /* SAM_USER_INFO_21 */ typedef struct sam_user_info_21 { @@ -375,7 +436,7 @@ SAMR_Q_QUERY_DOMAIN_INFO - probably a query on domain group info. typedef struct q_samr_query_domain_info { POLICY_HND domain_pol; /* policy handle */ - uint16 switch_value; /* 0x0002 */ + uint16 switch_value; /* 0x0002, 0x0001 */ } SAMR_Q_QUERY_DOMAIN_INFO; @@ -394,7 +455,7 @@ typedef struct sam_unknown_info_7_info } SAM_UNK_INFO_7; -typedef struct sam_unknown_info_2_info +typedef struct sam_unknown_info_2_inf { uint32 unknown_0; /* 0x0000 0000 */ uint32 unknown_1; /* 0x8000 0000 */ @@ -425,11 +486,21 @@ typedef struct sam_unknown_info_2_info } SAM_UNK_INFO_2; +typedef struct sam_unknown_info_1_inf +{ + uint8 padding[12]; /* 12 bytes zeros */ + uint32 unknown_1; /* 0x8000 0000 */ + uint32 unknown_2; /* 0x0000 0000 */ + uint32 unknown_3; /* 0x0000 0000 */ + +} SAM_UNK_INFO_1; + typedef struct sam_unknown_ctr_info { union { + SAM_UNK_INFO_1 inf1; SAM_UNK_INFO_2 inf2; SAM_UNK_INFO_6 inf6; SAM_UNK_INFO_7 inf7; @@ -1035,6 +1106,30 @@ typedef struct r_samr_query_usergroup_info } SAMR_R_QUERY_USERGROUPS; +/* SAMR_Q_SET_USERINFO - set sam info */ +typedef struct q_samr_set_user_info +{ + POLICY_HND pol; /* policy handle associated with user */ + uint16 switch_value; /* 0x0017 */ + uint16 switch_value2; /* 0x0017 */ + + union + { + SAM_USER_INFO_23 *id23; /* auth-level 0x17 */ + void* id; /* to make typecasting easy */ + + } info; + +} SAMR_Q_SET_USERINFO; + +/* SAMR_R_SET_USERINFO - set sam info */ +typedef struct r_samr_set_user_info +{ + uint32 status; /* return status */ + +} SAMR_R_SET_USERINFO; + + /* SAMR_Q_QUERY_USERINFO - probably a get sam info */ typedef struct q_samr_query_user_info { @@ -1230,33 +1325,6 @@ typedef struct r_samr_create_user_info -/* SAMR_Q_UNKNOWN_32 - probably a "create SAM entry" */ -typedef struct q_samr_unknown_32_info -{ - POLICY_HND pol; /* policy handle */ - - UNIHDR hdr_mach_acct; /* unicode machine account name header */ - UNISTR2 uni_mach_acct; /* unicode machine account name */ - - uint32 acct_ctrl; /* 32 bit ACB_XXXX */ - uint16 unknown_1; /* 16 bit unknown - 0x00B0 */ - uint16 unknown_2; /* 16 bit unknown - 0xe005 */ - -} SAMR_Q_UNKNOWN_32; - - -/* SAMR_R_UNKNOWN_32 - probably a "create SAM entry" */ -typedef struct r_samr_unknown_32_info -{ - POLICY_HND pol; /* policy handle */ - - /* rid4.unknown - fail: 0030 success: 0x03ff */ - DOM_RID4 rid4; /* rid and attributes */ - - uint32 status; /* return status - fail: 0xC000 0099: user exists */ - -} SAMR_R_UNKNOWN_32; - /* SAMR_Q_QUERY_GROUPMEM - query group members */ typedef struct q_samr_query_groupmem_info { diff --git a/source3/include/smb.h b/source3/include/smb.h index 65746d219c..edd021f4fb 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -613,6 +613,7 @@ typedef struct connection_struct char *connectpath; char *origpath; char *user; /* name of user who *opened* this connection */ + uid_t uid; /* uid of user who *opened* this connection */ gid_t gid; /* gid of user who *opened* this connection */ @@ -709,6 +710,7 @@ struct dcinfo uchar sess_key[8]; /* Session key */ uchar md4pw[16]; /* md4(machine password) */ + uchar user_sess_key[16]; /* user session key (md4 nt#) */ }; typedef struct diff --git a/source3/lib/util_pwdb.c b/source3/lib/util_pwdb.c index a678e4b063..b3b638b5e6 100644 --- a/source3/lib/util_pwdb.c +++ b/source3/lib/util_pwdb.c @@ -415,9 +415,26 @@ void pwdb_sethexpwd(char *p, const char *pwd, uint16 acct_ctrl) Routine to get the 32 hex characters and turn them into a 16 byte array. **************************************************************/ -BOOL pwdb_gethexpwd(const char *p, char *pwd) +BOOL pwdb_gethexpwd(const char *p, char *pwd, uint32 *acct_ctrl) { - return strhex_to_str(pwd, 32, p) == 16; + if (strnequal(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32)) + { + if (acct_ctrl != NULL) + { + *acct_ctrl |= ACB_PWNOTREQ; + } + pwd[0] = 0; + return True; + } + else if (strnequal(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32)) + { + pwd[0] = 0; + return True; + } + else + { + return strhex_to_str(pwd, 32, p) == 16; + } } diff --git a/source3/passdb/ldap.c b/source3/passdb/ldap.c index fad67cb79f..7bdbdab320 100644 --- a/source3/passdb/ldap.c +++ b/source3/passdb/ldap.c @@ -187,7 +187,7 @@ struct smb_passwd *ldap_getpw(void) smbpw.acct_ctrl = ACB_NORMAL; if(ldap_get_attribute("lmPassword", temp)) { - pwdb_gethexpwd(temp, smblmpwd); + pwdb_gethexpwd(temp, smblmpwd, NULL); smbpw.smb_passwd = smblmpwd; } else { smbpw.smb_passwd = NULL; @@ -195,7 +195,7 @@ struct smb_passwd *ldap_getpw(void) } if(ldap_get_attribute("ntPassword", temp)) { - pwdb_gethexpwd(temp, smbntpwd); + pwdb_gethexpwd(temp, smbntpwd, NULL); smbpw.smb_nt_passwd = smbntpwd; } else { smbpw.smb_nt_passwd = NULL; diff --git a/source3/passdb/sampassdb.c b/source3/passdb/sampassdb.c index e80d157ec0..7c824cb7ca 100644 --- a/source3/passdb/sampassdb.c +++ b/source3/passdb/sampassdb.c @@ -123,6 +123,20 @@ struct sam_passwd *getsam21pwent(void *vp) return pwdb_sam_map_names(pwdb_ops->getsam21pwent(vp)); } +/************************************************************************ + Routine to search the smb passwd file for an entry matching the username. + and then modify its password entry. We can't use the startsampwent()/ + getsampwent()/endsampwent() interfaces here as we depend on looking + in the actual file to decide how much room we have to write data. + override = False, normal + override = True, override XXXXXXXX'd out password or NO PASS +************************************************************************/ + +BOOL mod_sam21pwd_entry(struct sam_passwd* pwd, BOOL override) +{ + return pwdb_ops->mod_sam21pwd_entry(pwdb_sam_map_names(pwd), override); +} + /************************************************************************ Utility function to search sam passwd by name. use this if your database does not have search facilities. diff --git a/source3/passdb/smbpass.c b/source3/passdb/smbpass.c index 2985af1ff8..464cec015c 100644 --- a/source3/passdb/smbpass.c +++ b/source3/passdb/smbpass.c @@ -158,7 +158,7 @@ struct smb_passwd *getsmbfilepwent(void *vp) } else { - if (!pwdb_gethexpwd(p, (char *)smbpwd)) + if (!pwdb_gethexpwd(p, (char *)smbpwd, NULL)) { DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n")); continue; @@ -178,7 +178,7 @@ struct smb_passwd *getsmbfilepwent(void *vp) { if (*p != '*' && *p != 'X') { - if(pwdb_gethexpwd(p,(char *)smbntpwd)) + if(pwdb_gethexpwd(p,(char *)smbntpwd, NULL)) { pw_buf.smb_nt_passwd = smbntpwd; } diff --git a/source3/passdb/smbpassfile.c b/source3/passdb/smbpassfile.c index b4f8e2b869..0165d76488 100644 --- a/source3/passdb/smbpassfile.c +++ b/source3/passdb/smbpassfile.c @@ -167,7 +167,7 @@ BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_t * Get the hex password. */ - if (!pwdb_gethexpwd((char *)linebuf, (char *)ret_pwd) || linebuf[32] != ':' || + if (!pwdb_gethexpwd((char *)linebuf, (char *)ret_pwd, NULL) || linebuf[32] != ':' || strncmp(&linebuf[33], "TLC-", 4)) { DEBUG(0,("get_trust_account_password: Malformed trust password file (incorrect format).\n")); #ifdef DEBUG_PASSWORD diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index 323d5f65e5..64cbdef716 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -702,16 +702,6 @@ void smb_io_dom_rid3(char *desc, DOM_RID3 *rid3, prs_struct *ps, int depth) prs_uint32("unk ", ps, depth, &(rid3->unk )); } -/******************************************************************* -creates a DOM_RID4 structure. -********************************************************************/ -void make_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid) -{ - rid4->unknown = unknown; - rid4->attr = attr; - rid4->rid = rid; -} - /******************************************************************* makes a DOM_CLNT_SRV structure. ********************************************************************/ diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index a2fc77981e..f724535a8c 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -449,6 +449,38 @@ void sam_io_unk_info2(char *desc, SAM_UNK_INFO_2 *u_2, prs_struct *ps, int depth } +/******************************************************************* +makes a structure. +********************************************************************/ +void make_unk_info1(SAM_UNK_INFO_1 *u_1) +{ + if (u_1 == NULL) return; + + memset(u_1->padding, 0, sizeof(u_1->padding)); /* 12 bytes zeros */ + u_1->unknown_1 = 0x80000000; + u_1->unknown_2 = 0x00000000; + u_1->unknown_3 = 0x00000000; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void sam_io_unk_info1(char *desc, SAM_UNK_INFO_1 *u_1, prs_struct *ps, int depth) +{ + if (u_1 == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_unk_info1"); + depth++; + + prs_uint8s(False, "padding", ps, depth, u_1->padding, sizeof(u_1->padding)); /* 12 bytes zeros */ + + prs_uint32("unknown_1", ps, depth, &u_1->unknown_1); /* 0x8000 0000 */ + prs_uint32("unknown_2", ps, depth, &u_1->unknown_2); /* 0x0000 0000 */ + prs_uint32("unknown_3", ps, depth, &u_1->unknown_3); /* 0x0000 0000 */ + + prs_align(ps); +} + /******************************************************************* makes a SAMR_R_QUERY_DOMAIN_INFO structure. ********************************************************************/ @@ -507,6 +539,11 @@ void samr_io_r_query_dom_info(char *desc, SAMR_R_QUERY_DOMAIN_INFO *r_u, prs_str sam_io_unk_info2("unk_inf2", &r_u->ctr->info.inf2, ps, depth); break; } + case 0x01: + { + sam_io_unk_info1("unk_inf1", &r_u->ctr->info.inf1, ps, depth); + break; + } default: { DEBUG(3,("samr_io_r_query_dom_info: unknown switch level 0x%x\n", @@ -3847,6 +3884,25 @@ void samr_io_q_create_user(char *desc, SAMR_Q_CREATE_USER *q_u, prs_struct *ps, prs_align(ps); } +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_samr_r_create_user(SAMR_R_CREATE_USER *r_u, + POLICY_HND *user_pol, + uint32 unk_0, uint32 user_rid, + uint32 status) +{ + if (r_u == NULL) return; + + DEBUG(5,("samr_make_samr_r_create_user\n")); + + memcpy(&r_u->user_pol, user_pol, sizeof(r_u->user_pol)); + + r_u->unknown_0 = unk_0; + r_u->user_rid = user_rid; + r_u->status = status; +} + /******************************************************************* reads or writes a structure. ********************************************************************/ @@ -4049,6 +4105,186 @@ void sam_io_user_info11(char *desc, SAM_USER_INFO_11 *usr, prs_struct *ps, int prs_uint8s (False, "padding_9", ps, depth, usr->padding_9, sizeof(usr->padding_9)); } +/************************************************************************* + make_sam_user_info23 + + unknown_3 = 0x09f8 27fa + unknown_5 = 0x0001 0000 + unknown_6 = 0x0000 04ec + + *************************************************************************/ +void make_sam_user_info23(SAM_USER_INFO_23 *usr, + + NTTIME *logon_time, /* all zeros */ + NTTIME *logoff_time, /* all zeros */ + NTTIME *kickoff_time, /* all zeros */ + NTTIME *pass_last_set_time, /* all zeros */ + NTTIME *pass_can_change_time, /* all zeros */ + NTTIME *pass_must_change_time, /* all zeros */ + + char *user_name, /* NULL */ + char *full_name, + char *home_dir, + char *dir_drive, + char *logon_script, + char *profile_path, + char *description, + char *workstations, + char *unknown_str, + char *munged_dial, + + uint32 user_rid, /* 0x0000 0000 */ + uint32 group_rid, + uint16 acb_info, + + uint32 unknown_3, + uint16 logon_divs, + LOGON_HRS *hrs, + uint32 unknown_5, + char newpass[516], + uint32 unknown_6) +{ + int len_user_name = user_name != NULL ? strlen(user_name ) : 0; + int len_full_name = full_name != NULL ? strlen(full_name ) : 0; + int len_home_dir = home_dir != NULL ? strlen(home_dir ) : 0; + int len_dir_drive = dir_drive != NULL ? strlen(dir_drive ) : 0; + int len_logon_script = logon_script != NULL ? strlen(logon_script) : 0; + int len_profile_path = profile_path != NULL ? strlen(profile_path) : 0; + int len_description = description != NULL ? strlen(description ) : 0; + int len_workstations = workstations != NULL ? strlen(workstations) : 0; + int len_unknown_str = unknown_str != NULL ? strlen(unknown_str ) : 0; + int len_munged_dial = munged_dial != NULL ? strlen(munged_dial ) : 0; + + usr->logon_time = *logon_time; /* all zeros */ + usr->logoff_time = *logoff_time; /* all zeros */ + usr->kickoff_time = *kickoff_time; /* all zeros */ + usr->pass_last_set_time = *pass_last_set_time; /* all zeros */ + usr->pass_can_change_time = *pass_can_change_time; /* all zeros */ + usr->pass_must_change_time = *pass_must_change_time; /* all zeros */ + + make_uni_hdr(&(usr->hdr_user_name ), len_user_name ); /* NULL */ + make_uni_hdr(&(usr->hdr_full_name ), len_full_name ); + make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir ); + make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive ); + make_uni_hdr(&(usr->hdr_logon_script), len_logon_script); + make_uni_hdr(&(usr->hdr_profile_path), len_profile_path); + make_uni_hdr(&(usr->hdr_acct_desc ), len_description ); + make_uni_hdr(&(usr->hdr_workstations), len_workstations); + make_uni_hdr(&(usr->hdr_unknown_str ), len_unknown_str ); + make_uni_hdr(&(usr->hdr_munged_dial ), len_munged_dial ); + + bzero(usr->nt_pwd, sizeof(usr->nt_pwd)); + bzero(usr->lm_pwd, sizeof(usr->lm_pwd)); + + usr->user_rid = user_rid; /* 0x0000 0000 */ + usr->group_rid = group_rid; + usr->acb_info = acb_info; + usr->unknown_3 = unknown_3; /* 09f8 27fa */ + + usr->logon_divs = logon_divs; /* should be 168 (hours/week) */ + usr->ptr_logon_hrs = hrs ? 1 : 0; + + bzero(usr->padding1, sizeof(usr->padding1)); + + usr->unknown_5 = unknown_5; /* 0x0001 0000 */ + + memcpy(usr->pass, newpass, sizeof(usr->pass)); + + make_unistr2(&(usr->uni_user_name ), user_name , len_user_name ); /* NULL */ + make_unistr2(&(usr->uni_full_name ), full_name , len_full_name ); + make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir ); + make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive ); + make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script); + make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path); + make_unistr2(&(usr->uni_acct_desc ), description , len_description ); + make_unistr2(&(usr->uni_workstations), workstations, len_workstations); + make_unistr2(&(usr->uni_unknown_str ), unknown_str , len_unknown_str ); + make_unistr2(&(usr->uni_munged_dial ), munged_dial , len_munged_dial ); + + usr->unknown_6 = unknown_6; /* 0x0000 04ec */ + usr->padding4 = 0; + + if (hrs) + { + memcpy(&(usr->logon_hrs), hrs, sizeof(usr->logon_hrs)); + } + else + { + memset(&(usr->logon_hrs), 0xff, sizeof(usr->logon_hrs)); + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static void sam_io_user_info23(char *desc, SAM_USER_INFO_23 *usr, prs_struct *ps, int depth) +{ + if (usr == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_user_info"); + depth++; + + prs_align(ps); + + smb_io_time("logon_time ", &(usr->logon_time) , ps, depth); + smb_io_time("logoff_time ", &(usr->logoff_time) , ps, depth); + smb_io_time("kickoff_time ", &(usr->kickoff_time) , ps, depth); + smb_io_time("pass_last_set_time ", &(usr->pass_last_set_time) , ps, depth); + smb_io_time("pass_can_change_time ", &(usr->pass_can_change_time) , ps, depth); + smb_io_time("pass_must_change_time", &(usr->pass_must_change_time), ps, depth); + + smb_io_unihdr("hdr_user_name ", &(usr->hdr_user_name) , ps, depth); /* username unicode string header */ + smb_io_unihdr("hdr_full_name ", &(usr->hdr_full_name) , ps, depth); /* user's full name unicode string header */ + smb_io_unihdr("hdr_home_dir ", &(usr->hdr_home_dir) , ps, depth); /* home directory unicode string header */ + smb_io_unihdr("hdr_dir_drive ", &(usr->hdr_dir_drive) , ps, depth); /* home directory drive */ + smb_io_unihdr("hdr_logon_script", &(usr->hdr_logon_script), ps, depth); /* logon script unicode string header */ + smb_io_unihdr("hdr_profile_path", &(usr->hdr_profile_path), ps, depth); /* profile path unicode string header */ + smb_io_unihdr("hdr_acct_desc ", &(usr->hdr_acct_desc ) , ps, depth); /* account description */ + smb_io_unihdr("hdr_workstations", &(usr->hdr_workstations), ps, depth); /* workstations user can log on from */ + smb_io_unihdr("hdr_unknown_str ", &(usr->hdr_unknown_str ), ps, depth); /* unknown string */ + smb_io_unihdr("hdr_munged_dial ", &(usr->hdr_munged_dial ), ps, depth); /* workstations user can log on from */ + + prs_uint8s (False, "lm_pwd ", ps, depth, usr->lm_pwd , sizeof(usr->lm_pwd )); + prs_uint8s (False, "nt_pwd ", ps, depth, usr->nt_pwd , sizeof(usr->nt_pwd )); + + prs_uint32("user_rid ", ps, depth, &(usr->user_rid )); /* User ID */ + prs_uint32("group_rid ", ps, depth, &(usr->group_rid )); /* Group ID */ + prs_uint16("acb_info ", ps, depth, &(usr->acb_info )); /* Group ID */ + prs_align(ps); + + prs_uint32("unknown_3 ", ps, depth, &(usr->unknown_3 )); + prs_uint16("logon_divs ", ps, depth, &(usr->logon_divs )); /* logon divisions per week */ + prs_align(ps); + prs_uint32("ptr_logon_hrs ", ps, depth, &(usr->ptr_logon_hrs)); + prs_uint8s (False, "padding1 ", ps, depth, usr->padding1, sizeof(usr->padding1)); + prs_uint32("unknown_5 ", ps, depth, &(usr->unknown_5 )); + + prs_uint8s (False, "password ", ps, depth, usr->pass, sizeof(usr->pass)); + + /* here begins pointed-to data */ + + smb_io_unistr2("uni_user_name ", &(usr->uni_user_name) , usr->hdr_user_name .buffer, ps, depth); /* username unicode string */ + smb_io_unistr2("uni_full_name ", &(usr->uni_full_name) , usr->hdr_full_name .buffer, ps, depth); /* user's full name unicode string */ + smb_io_unistr2("uni_home_dir ", &(usr->uni_home_dir) , usr->hdr_home_dir .buffer, ps, depth); /* home directory unicode string */ + smb_io_unistr2("uni_dir_drive ", &(usr->uni_dir_drive) , usr->hdr_dir_drive .buffer, ps, depth); /* home directory drive unicode string */ + smb_io_unistr2("uni_logon_script", &(usr->uni_logon_script), usr->hdr_logon_script.buffer, ps, depth); /* logon script unicode string */ + smb_io_unistr2("uni_profile_path", &(usr->uni_profile_path), usr->hdr_profile_path.buffer, ps, depth); /* profile path unicode string */ + smb_io_unistr2("uni_acct_desc ", &(usr->uni_acct_desc ), usr->hdr_acct_desc .buffer, ps, depth); /* user description unicode string */ + smb_io_unistr2("uni_workstations", &(usr->uni_workstations), usr->hdr_workstations.buffer, ps, depth); /* worksations user can log on from */ + smb_io_unistr2("uni_unknown_str ", &(usr->uni_unknown_str ), usr->hdr_unknown_str .buffer, ps, depth); /* unknown string */ + smb_io_unistr2("uni_munged_dial ", &(usr->uni_munged_dial ), usr->hdr_munged_dial .buffer, ps, depth); /* worksations user can log on from */ + + prs_uint32("unknown_6 ", ps, depth, &(usr->unknown_6 )); + prs_uint32("padding4 ", ps, depth, &(usr->padding4 )); + + if (usr->ptr_logon_hrs) + { + sam_io_logon_hrs("logon_hrs", &(usr->logon_hrs) , ps, depth); + prs_align(ps); + } +} + + /************************************************************************* make_sam_user_info21 @@ -4353,14 +4589,47 @@ void samr_io_r_query_userinfo(char *desc, SAMR_R_QUERY_USERINFO *r_u, prs_struc prs_uint32("status", ps, depth, &(r_u->status)); } +/******************************************************************* +makes a SAMR_Q_SET_USERINFO structure. +********************************************************************/ +void make_samr_q_set_userinfo(SAMR_Q_SET_USERINFO *q_u, + POLICY_HND *hnd, + uint16 switch_value, void *info) +{ + if (q_u == NULL || hnd == NULL) return; + + DEBUG(5,("make_samr_q_set_userinfo\n")); + + memcpy(&(q_u->pol), hnd, sizeof(q_u->pol)); + q_u->switch_value = switch_value; + q_u->switch_value2 = switch_value; + + switch (switch_value) + { + case 0x17: + { + q_u->info.id23 = (SAM_USER_INFO_23*)info; + + break; + } + + default: + { + DEBUG(4,("make_samr_q_set_userinfo: unsupported switch level\n")); + break; + } + } +} + + /******************************************************************* reads or writes a structure. ********************************************************************/ -void samr_io_q_unknown_32(char *desc, SAMR_Q_UNKNOWN_32 *q_u, prs_struct *ps, int depth) +void samr_io_q_set_userinfo(char *desc, SAMR_Q_SET_USERINFO *q_u, prs_struct *ps, int depth) { if (q_u == NULL) return; - prs_debug(ps, depth, desc, "samr_io_q_unknown_32"); + prs_debug(ps, depth, desc, "samr_io_q_set_userinfo"); depth++; prs_align(ps); @@ -4368,35 +4637,66 @@ void samr_io_q_unknown_32(char *desc, SAMR_Q_UNKNOWN_32 *q_u, prs_struct *ps, i smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); prs_align(ps); - smb_io_unihdr ("", &(q_u->hdr_mach_acct), ps, depth); - smb_io_unistr2("", &(q_u->uni_mach_acct), q_u->hdr_mach_acct.buffer, ps, depth); + prs_uint16("switch_value ", ps, depth, &(q_u->switch_value )); + prs_uint16("switch_value2", ps, depth, &(q_u->switch_value2)); prs_align(ps); - prs_uint32("acct_ctrl", ps, depth, &(q_u->acct_ctrl)); - prs_uint16("unknown_1", ps, depth, &(q_u->unknown_1)); - prs_uint16("unknown_2", ps, depth, &(q_u->unknown_2)); + switch (q_u->switch_value) + { + case 0: + { + break; + } + case 23: + { + q_u->info.id = Realloc(NULL, sizeof(*q_u->info.id23)); + if (q_u->info.id == NULL) + { + DEBUG(2,("samr_io_q_query_userinfo: info pointer not initialised\n")); + return; + } + sam_io_user_info23("", q_u->info.id23, ps, depth); + break; + } + default: + { + DEBUG(2,("samr_io_q_query_userinfo: unknown switch level\n")); + break; + } + + } + prs_align(ps); +} + +/******************************************************************* +makes a SAMR_R_SET_USERINFO structure. +********************************************************************/ +void make_samr_r_set_userinfo(SAMR_R_SET_USERINFO *r_u, uint32 status) + +{ + if (r_u == NULL) return; + + DEBUG(5,("make_samr_r_set_userinfo\n")); + + r_u->status = status; /* return status */ } /******************************************************************* reads or writes a structure. ********************************************************************/ -void samr_io_r_unknown_32(char *desc, SAMR_R_UNKNOWN_32 *r_u, prs_struct *ps, int depth) +void samr_io_r_set_userinfo(char *desc, SAMR_R_SET_USERINFO *r_u, prs_struct *ps, int depth) { if (r_u == NULL) return; - prs_debug(ps, depth, desc, "samr_io_r_unknown_32"); + prs_debug(ps, depth, desc, "samr_io_r_set_userinfo"); depth++; prs_align(ps); - smb_io_pol_hnd("pol", &(r_u->pol), ps, depth); - prs_align(ps); - prs_uint32("status", ps, depth, &(r_u->status)); } - /******************************************************************* makes a SAMR_Q_CONNECT structure. ********************************************************************/ diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index ec5b547c86..54d26650e9 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -211,8 +211,16 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p) uchar nt_owf[24]; struct smb_passwd *smb_pass = NULL; + user_struct *vuser = get_valid_user_struct(p->vuid); + DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n")); + if (vuser == NULL) + { + DEBUG(0,("get user struct %d failed\n", p->vuid)); + return False; + } + if (p->ntlmssp_resp.hdr_lm_resp.str_str_len == 0) return False; if (p->ntlmssp_resp.hdr_nt_resp.str_str_len == 0) return False; if (p->ntlmssp_resp.hdr_usr .str_str_len == 0) return False; @@ -256,7 +264,7 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p) become_root(True); p->ntlmssp_validated = pass_check_smb(p->user_name, p->domain, (uchar*)p->ntlmssp_chal.challenge, - lm_owf, nt_owf, NULL); + lm_owf, nt_owf, NULL, vuser->dc.user_sess_key); smb_pass = getsmbpwnam(p->user_name); unbecome_root(True); diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 531fcf6add..4361c0772e 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -140,7 +140,7 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name, p->ntlmssp_auth = False; fstrcpy(p->name, pipe_name); - + DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n", pipe_name, i, pipes_open)); diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c index 2dd7801e81..2437163f2b 100644 --- a/source3/rpc_server/srv_samr.c +++ b/source3/rpc_server/srv_samr.c @@ -1943,6 +1943,27 @@ static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u, } +/******************************************************************* + set_user_info_23 + ********************************************************************/ +static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid) +{ + static struct sam_passwd *pwd; + fstring new_pw; + if (!decode_pw_buffer(id23->pass, new_pw, sizeof(new_pw), True)) + { + return False; + } +#ifdef DEBUG_PASSWORD + DEBUG(0,("New Password: %s\n", new_pw)); +#endif +#if 0 + return mod_sam21pwd_entry(&pwd, True); +#else + return True; +#endif +} + /******************************************************************* api_samr_query_userinfo ********************************************************************/ @@ -1954,6 +1975,87 @@ static void api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct * } +/******************************************************************* + samr_reply_set_userinfo + ********************************************************************/ +static void samr_reply_set_userinfo(SAMR_Q_SET_USERINFO *q_u, + prs_struct *rdata, uchar user_sess_key[16]) +{ + SAMR_R_SET_USERINFO r_u; + + uint32 status = 0x0; + uint32 rid = 0x0; + + DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__)); + + /* search for the handle */ + if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1)) + { + status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + /* find the user's rid */ + if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff) + { + status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + DEBUG(5,("samr_reply_set_userinfo: rid:0x%x\n", rid)); + + /* ok! user info levels (there are lots: see MSDEV help), off we go... */ + if (status == 0x0) + { + switch (q_u->switch_value) + { + case 23: + { + SAM_USER_INFO_23 *id23 = q_u->info.id23; + SamOEMhash(id23->pass, user_sess_key, True); + status = set_user_info_23(id23, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); + break; + } + + default: + { + status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + + break; + } + } + } + + make_samr_r_set_userinfo(&r_u, status); + + /* store the response in the SMB stream */ + samr_io_r_set_userinfo("", &r_u, rdata, 0); + + DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_set_userinfo + ********************************************************************/ +static void api_samr_set_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + user_struct *vuser = get_valid_user_struct(vuid); + SAMR_Q_SET_USERINFO q_u; + ZERO_STRUCT(q_u); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("set user info: sess_key: ")); + dump_data(100, vuser->dc.user_sess_key, 16); +#endif + samr_io_q_set_userinfo("", &q_u, data, 0); + samr_reply_set_userinfo(&q_u, rdata, vuser->dc.user_sess_key); + + if (q_u.info.id != NULL) + { + free(q_u.info.id); + } +} + + /******************************************************************* samr_reply_query_usergroups ********************************************************************/ @@ -2310,6 +2412,13 @@ static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u, break; } + case 0x01: + { + switch_value = 0x1; + make_unk_info1(&ctr.info.inf1); + + break; + } default: { status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; @@ -2340,50 +2449,19 @@ static void api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct * /******************************************************************* - samr_reply_unknown_32 + samr_reply_create_user ********************************************************************/ -static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u, - prs_struct *rdata, - int status) -{ - int i; - SAMR_R_UNKNOWN_32 r_u; - - /* set up the SAMR unknown_32 response */ - bzero(r_u.pol.data, POL_HND_SIZE); - if (status == 0) - { - for (i = 4; i < POL_HND_SIZE; i++) - { - r_u.pol.data[i] = i+1; - } - } - - make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0); - r_u.status = status; - - DEBUG(5,("samr_unknown_32: %d\n", __LINE__)); - - /* store the response in the SMB stream */ - samr_io_r_unknown_32("", &r_u, rdata, 0); - - DEBUG(5,("samr_unknown_32: %d\n", __LINE__)); - -} - -/******************************************************************* - api_samr_unknown_32 - ********************************************************************/ -static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdata) +static void samr_reply_create_user(SAMR_Q_CREATE_USER *q_u, + prs_struct *rdata) { - uint32 status = 0; struct sam_passwd *sam_pass; - fstring mach_acct; - - SAMR_Q_UNKNOWN_32 q_u; + fstring user_name; - /* grab the samr unknown 32 */ - samr_io_q_unknown_32("", &q_u, data, 0); + SAMR_R_CREATE_USER r_u; + POLICY_HND pol; + uint32 status = 0x0; + uint32 user_rid = 0xffffffff; + BOOL pol_open = False; /* find the machine account: tell the caller if it exists. lkclXXXX i have *no* idea if this is a problem or not @@ -2391,26 +2469,91 @@ static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdat reply if the account already exists... */ - unistr2_to_ascii(mach_acct, &q_u.uni_mach_acct, sizeof(mach_acct)-1); + /* find the policy handle. open a policy on it. */ + if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1)) + { + status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } - become_root(True); - sam_pass = getsam21pwntnam(mach_acct); - unbecome_root(True); + /* get a (unique) handle. open a policy on it. */ + if (status == 0x0 && !(pol_open = open_lsa_policy_hnd(&pol))) + { + status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + unistr2_to_ascii(user_name, &q_u->uni_name, sizeof(user_name)-1); + + sam_pass = getsam21pwntnam(user_name); if (sam_pass != NULL) { - /* machine account exists: say so */ + /* account exists: say so */ status = 0xC0000000 | NT_STATUS_USER_EXISTS; } else { - /* this could cause trouble... */ - DEBUG(0,("trouble!\n")); - status = 0; + pstring err_str; + pstring msg_str; + + if (!local_password_change(user_name, True, + q_u->acb_info | ACB_DISABLED, 0xffff, + NULL, + err_str, sizeof(err_str), + msg_str, sizeof(msg_str))) + { + DEBUG(0,("%s\n", err_str)); + status = 0xC0000000 | NT_STATUS_ACCESS_DENIED; + } + else + { + sam_pass = getsam21pwntnam(user_name); + if (sam_pass == NULL) + { + /* account doesn't exist: say so */ + status = 0xC0000000 | NT_STATUS_ACCESS_DENIED; + } + else + { + user_rid = sam_pass->user_rid; + } + } + } + + /* associate the RID with the (unique) handle. */ + if (status == 0x0 && !set_lsa_policy_samr_rid(&pol, user_rid)) + { + /* oh, whoops. don't know what error message to return, here */ + status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (status != 0 && pol_open) + { + close_lsa_policy_hnd(&pol); } + DEBUG(5,("samr_create_user: %d\n", __LINE__)); + + make_samr_r_create_user(&r_u, &pol, 0x000703ff, user_rid, status); + + /* store the response in the SMB stream */ + samr_io_r_create_user("", &r_u, rdata, 0); + + DEBUG(5,("samr_create_user: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_create_user + ********************************************************************/ +static void api_samr_create_user( uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_CREATE_USER q_u; + + /* grab the samr unknown 32 */ + samr_io_q_create_user("", &q_u, data, 0); + /* construct reply. */ - samr_reply_unknown_32(&q_u, rdata, status); + samr_reply_create_user(&q_u, rdata); } @@ -2709,6 +2852,7 @@ static struct api_struct api_samr_cmds [] = { "SAMR_LOOKUP_NAMES" , SAMR_LOOKUP_NAMES , api_samr_lookup_names }, { "SAMR_OPEN_USER" , SAMR_OPEN_USER , api_samr_open_user }, { "SAMR_QUERY_USERINFO" , SAMR_QUERY_USERINFO , api_samr_query_userinfo }, + { "SAMR_SET_USERINFO" , SAMR_SET_USERINFO , api_samr_set_userinfo }, { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info }, { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups }, { "SAMR_QUERY_DISPINFO" , SAMR_QUERY_DISPINFO , api_samr_query_dispinfo }, @@ -2716,7 +2860,7 @@ static struct api_struct api_samr_cmds [] = { "SAMR_QUERY_DISPINFO4" , SAMR_QUERY_DISPINFO4 , api_samr_query_dispinfo }, { "SAMR_QUERY_ALIASINFO" , SAMR_QUERY_ALIASINFO , api_samr_query_aliasinfo }, { "SAMR_QUERY_GROUPINFO" , SAMR_QUERY_GROUPINFO , api_samr_query_groupinfo }, - { "SAMR_0x32" , SAMR_UNKNOWN_32 , api_samr_unknown_32 }, + { "SAMR_CREATE_USER" , SAMR_CREATE_USER , api_samr_create_user }, { "SAMR_LOOKUP_RIDS" , SAMR_LOOKUP_RIDS , api_samr_lookup_rids }, { "SAMR_UNKNOWN_38" , SAMR_UNKNOWN_38 , api_samr_unknown_38 }, { "SAMR_CHGPASSWD_USER" , SAMR_CHGPASSWD_USER , api_samr_chgpasswd_user }, diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 852d6aa618..c22f268684 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -603,6 +603,42 @@ BOOL pass_oem_change(char *user, return ret; } +/*********************************************************** + decode a password buffer +************************************************************/ +BOOL decode_pw_buffer(const char buffer[516], char *new_passwd, + int new_passwd_size, BOOL nt_pass_set) +{ + /* + * The length of the new password is in the last 4 bytes of + * the data buffer. + */ + + uint32 new_pw_len = IVAL(buffer, 512); + if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) + { + DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); + return False; + } + + if (nt_pass_set) + { + /* + * nt passwords are in unicode + */ + int uni_pw_len = new_pw_len; + new_pw_len /= 2; + unibuf_to_ascii(new_passwd, &buffer[512-uni_pw_len], new_pw_len); + } + else + { + memcpy(new_passwd, &buffer[512-new_pw_len], new_pw_len); + new_passwd[new_pw_len] = '\0'; + } + + return True; +} + /*********************************************************** Code to check the OEM hashed password. @@ -619,7 +655,6 @@ BOOL check_oem_password(char *user, static uchar null_pw[16]; static uchar null_ntpw[16]; struct smb_passwd *smbpw = NULL; - int new_pw_len; uchar new_ntp16[16]; uchar unenc_old_ntpw[16]; uchar new_p16[16]; @@ -681,33 +716,11 @@ BOOL check_oem_password(char *user, */ SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True); - /* - * The length of the new password is in the last 4 bytes of - * the data buffer. - */ - - new_pw_len = IVAL(lmdata, 512); - if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) + if (!decode_pw_buffer(lmdata, new_passwd, new_passwd_size, nt_pass_set)) { - DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); return False; } - if (nt_pass_set) - { - /* - * nt passwords are in unicode - */ - int uni_pw_len = new_pw_len; - new_pw_len /= 2; - unibuf_to_ascii(new_passwd, &lmdata[512-uni_pw_len], new_pw_len); - } - else - { - memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len); - new_passwd[new_pw_len] = '\0'; - } - /* * To ensure we got the correct new password, hash it and * use it as a key to test the passed old password. diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a4d452b2a8..5001b16b35 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1680,7 +1680,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param * Older versions of Windows seem to do this. */ - if (password_ok(user, pass1,strlen(pass1),NULL) && + if (password_ok(user, pass1,strlen(pass1),NULL, NULL) && chgpasswd(user,pass1,pass2,False)) { SSVAL(*rparam,0,NERR_Success); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 68d75b933f..11fe69b103 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -156,7 +156,7 @@ register a uid/name pair as being valid and that a valid password has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest) +uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]) { user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -205,6 +205,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, vuser->guest = guest; fstrcpy(vuser->name,unix_name); fstrcpy(vuser->requested_name,requested_name); + memcpy(vuser->dc.user_sess_key, user_sess_key, sizeof(vuser->dc.user_sess_key)); vuser->n_sids = 0; vuser->sids = NULL; @@ -412,7 +413,7 @@ return True if the password is correct, False otherwise BOOL pass_check_smb(char *user, char *domain, uchar *chal, uchar *lm_pwd, uchar *nt_pwd, - struct passwd *pwd) + struct passwd *pwd, uchar user_sess_key[16]) { struct passwd *pass; struct smb_passwd *smb_pass; @@ -467,6 +468,14 @@ BOOL pass_check_smb(char *user, char *domain, if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd)) { + if (user_sess_key != NULL) + { + mdfour(user_sess_key, smb_pass->smb_nt_passwd, 16); +#ifdef DEBUG_PASSWORD + DEBUG(100,("user session key: ")); + dump_data(100, user_sess_key, 16); +#endif + } return(True); } @@ -479,7 +488,8 @@ check if a username/password pair is OK either via the system password database or the encrypted SMB password database return True if the password is correct, False otherwise ****************************************************************************/ -BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) +BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, + uchar user_sess_key[16]) { if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) { @@ -493,7 +503,7 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) } return pass_check_smb(user, global_myworkgroup, - challenge, (uchar *)password, (uchar *)password, pwd); + challenge, (uchar *)password, (uchar *)password, pwd, user_sess_key); } return pass_check(user, password, pwlen, pwd, @@ -536,7 +546,8 @@ BOOL user_ok(char *user,int snum) /**************************************************************************** validate a group username entry. Return the username or NULL ****************************************************************************/ -static char *validate_group(char *group,char *password,int pwlen,int snum) +static char *validate_group(char *group,char *password,int pwlen,int snum, + uchar user_sess_key[16]) { #if defined(HAVE_NETGROUP) && defined(HAVE_GETNETGRENT) && defined(HAVE_SETNETGRENT) && defined(HAVE_ENDNETGRENT) { @@ -545,7 +556,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (getnetgrent(&host, &user, &domain)) { if (user) { if (user_ok(user, snum) && - password_ok(user,password,pwlen,NULL)) { + password_ok(user,password,pwlen,NULL, user_sess_key)) { endnetgrent(); return(user); } @@ -567,7 +578,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) static fstring name; fstrcpy(name,*member); if (user_ok(name,snum) && - password_ok(name,password,pwlen,NULL)) + password_ok(name,password,pwlen,NULL, user_sess_key)) return(&name[0]); member++; } @@ -580,7 +591,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (pwd = getpwent ()) { if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) { /* This Entry have PASSWORD and same GID then check pwd */ - if (password_ok(NULL, password, pwlen, pwd)) { + if (password_ok(NULL, password, pwlen, pwd, user_sess_key)) { fstrcpy(tm, pwd->pw_name); endpwent (); return tm; @@ -633,14 +644,14 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check the given username and password */ if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen, NULL); + ok = password_ok(user,password, pwlen, NULL, vuser->dc.user_sess_key); if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); } /* check for a previously registered guest username */ if (!ok && (vuser != 0) && vuser->guest) { if (user_ok(vuser->name,snum) && - password_ok(vuser->name, password, pwlen, NULL)) { + password_ok(vuser->name, password, pwlen, NULL, vuser->dc.user_sess_key)) { fstrcpy(user, vuser->name); vuser->guest = False; DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); @@ -664,7 +675,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstrcpy(user2,auser); if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen, NULL)) { + if (password_ok(user2,password, pwlen, NULL, vuser->dc.user_sess_key)) { ok = True; fstrcpy(user,user2); DEBUG(3,("ACCEPTED: session list username and given password ok\n")); @@ -703,7 +714,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, { if (*auser == '@') { - auser = validate_group(auser+1,password,pwlen,snum); + auser = validate_group(auser+1,password,pwlen,snum, vuser->dc.user_sess_key); if (auser) { ok = True; @@ -716,7 +727,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstring user2; fstrcpy(user2,auser); if (user_ok(user2,snum) && - password_ok(user2,password,pwlen,NULL)) + password_ok(user2,password,pwlen,NULL, vuser->dc.user_sess_key)) { ok = True; fstrcpy(user,user2); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 694cf3cdd5..57742003ff 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -511,6 +511,7 @@ reply to a session setup command int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { uint16 sess_vuid; + uchar user_sess_key[16]; int gid; int uid; int smb_bufsize; @@ -706,13 +707,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if(smb_ntpasslen) { - if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL)) + if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key)) DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); else valid_nt_password = True; } - if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL)) + if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key)) { if (lp_security() >= SEC_USER) { @@ -791,7 +792,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest); + sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); -- cgit