From 46b12f2275dcd4b3114085160cd456441f9e921e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Mar 2001 22:26:28 +0000 Subject: [PATCH] Moved cruft out of smb.h into ntdomain.h where it belongs. dc struct now in pipe struct (where used) rather than user_struct. Secured machine account password changing in srv_netlog_nt.c - ensure that only the given machine can change its own password. May need to free this up later for NT admin tools, but this is a fail-safe secure position for now. Jeremy. --- source/include/ntdomain.h | 33 ++++++------ source/include/proto.h | 32 ------------ source/include/rpc_misc.h | 13 +++++ source/include/smb.h | 45 ---------------- source/rpc_server/srv_netlog_nt.c | 86 +++++++++++++++++-------------- source/smbd/password.c | 2 - 6 files changed, 77 insertions(+), 134 deletions(-) diff --git a/source/include/ntdomain.h b/source/include/ntdomain.h index a3fd51948dd..799fa6d9072 100644 --- a/source/include/ntdomain.h +++ b/source/include/ntdomain.h @@ -24,7 +24,6 @@ #ifndef _NT_DOMAIN_H /* _NT_DOMAIN_H */ #define _NT_DOMAIN_H - /* dce/rpc support */ #include "rpc_dce.h" @@ -137,21 +136,6 @@ typedef struct _input_data { prs_struct data; } input_data; -struct msrpc_state -{ - fstring pipe_name; - struct user_creds usr; - struct ntdom_info nt; - - int fd; - BOOL redirect; - BOOL initialised; - char *inbuf; - char *outbuf; - - uint32 pid; -}; - /* * Handle database - stored per pipe. */ @@ -173,12 +157,26 @@ struct handle_list { size_t count; }; +/* Domain controller authentication protocol info */ +struct dcinfo +{ + DOM_CHAL clnt_chal; /* Initial challenge received from client */ + DOM_CHAL srv_chal; /* Initial server challenge */ + DOM_CRED clnt_cred; /* Last client credential */ + DOM_CRED srv_cred; /* Last server credential */ + + uchar sess_key[8]; /* Session key */ + uchar md4pw[16]; /* md4(machine password) */ + + fstring mach_acct; /* Machine name we've authenticated. */ +}; + typedef struct pipes_struct { struct pipes_struct *next, *prev; int pnum; connection_struct *conn; - uint16 vuid; + uint16 vuid; /* points to the unauthenticated user that opened this pipe. */ BOOL open; /* open connection */ uint16 device_state; uint16 priority; @@ -194,6 +192,7 @@ typedef struct pipes_struct unsigned char challenge[8]; unsigned char ntlmssp_hash[258]; uint32 ntlmssp_seq_num; + struct dcinfo dc; /* Keeps the creds data. */ /* * Windows user info. diff --git a/source/include/proto.h b/source/include/proto.h index c1271e7d277..774f623adb7 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -159,38 +159,6 @@ BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type, void *buf, size_t len int ms_fnmatch(char *pattern, char *string); -/*The following definitions come from lib/msrpc-client.c */ - -BOOL receive_msrpc(int fd, prs_struct *data, unsigned int timeout); -BOOL msrpc_send(int fd, prs_struct *ps); -BOOL msrpc_receive(int fd, prs_struct *ps); -BOOL msrpc_connect(struct msrpc_state *msrpc, const char *pipe_name); -void msrpc_init_creds(struct msrpc_state *msrpc, const struct user_creds *usr); -void msrpc_close_socket(struct msrpc_state *msrpc); -void msrpc_sockopt(struct msrpc_state *msrpc, char *options); -BOOL msrpc_connect_auth(struct msrpc_state *msrpc, - uint32 pid, - const char* pipename, - const struct user_creds *usr); -struct msrpc_state *msrpc_initialise(struct msrpc_state *msrpc, uint32 pid); -void msrpc_shutdown(struct msrpc_state *msrpc); -BOOL msrpc_establish_connection(struct msrpc_state *msrpc, - const char *pipe_name); - -/*The following definitions come from lib/msrpc_use.c */ - -void init_msrpc_use(void); -void free_msrpc_use(void); -struct msrpc_state *msrpc_use_add(const char* pipe_name, - uint32 pid, - struct user_creds *usr_creds, - BOOL redir); -BOOL msrpc_use_del(const char* pipe_name, - const struct user_creds *usr_creds, - BOOL force_close, - BOOL *connection_closed); -void msrpc_net_use_enum(uint32 *num_cons, struct use_info ***use); - /*The following definitions come from lib/pidfile.c */ pid_t pidfile_pid(char *name); diff --git a/source/include/rpc_misc.h b/source/include/rpc_misc.h index 5152df8e0f4..428db938ded 100644 --- a/source/include/rpc_misc.h +++ b/source/include/rpc_misc.h @@ -247,6 +247,19 @@ typedef struct log_info } DOM_LOG_INFO; +/* DOM_CHAL - challenge info */ +typedef struct chal_info +{ + uchar data[8]; /* credentials */ +} DOM_CHAL; + +/* DOM_CREDs - timestamped client or server credentials */ +typedef struct cred_info +{ + DOM_CHAL challenge; /* credentials */ + UTIME timestamp; /* credential time-stamp */ +} DOM_CRED; + /* DOM_CLNT_INFO - client info */ typedef struct clnt_info { diff --git a/source/include/smb.h b/source/include/smb.h index ab1cd60f66d..ba0a02e9507 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -425,25 +425,12 @@ typedef struct domain_grp_member_info } DOMAIN_GRP_MEMBER; -/* DOM_CHAL - challenge info */ -typedef struct chal_info -{ - uchar data[8]; /* credentials */ -} DOM_CHAL; - /* 32 bit time (sec) since 01jan1970 - cifs6.txt, section 3.5, page 30 */ typedef struct time_info { uint32 time; } UTIME; -/* DOM_CREDs - timestamped client or server credentials */ -typedef struct cred_info -{ - DOM_CHAL challenge; /* credentials */ - UTIME timestamp; /* credential time-stamp */ -} DOM_CRED; - /* Structure used when SMBwritebmpx is active */ typedef struct { @@ -581,19 +568,6 @@ struct current_user #define EXCLUSIVE_BREAK_SENT 1 #define LEVEL_II_BREAK_SENT 2 -/* Domain controller authentication protocol info */ -struct dcinfo -{ - DOM_CHAL clnt_chal; /* Initial challenge received from client */ - DOM_CHAL srv_chal; /* Initial server challenge */ - DOM_CRED clnt_cred; /* Last client credential */ - DOM_CRED srv_cred; /* Last server credential */ - - uchar sess_key[8]; /* Session key */ - uchar md4pw[16]; /* md4(machine password) */ -}; - - typedef struct { fstring smb_name; /* user name from the client */ fstring unix_name; /* unix user name of a validated user */ @@ -1600,21 +1574,6 @@ struct pwd_info uchar sess_key[16]; }; -struct ntdom_info -{ - unsigned char sess_key[16]; /* Current session key. */ - unsigned char ntlmssp_hash[258]; /* ntlmssp data. */ - uint32 ntlmssp_cli_flgs; /* ntlmssp client flags */ - uint32 ntlmssp_srv_flgs; /* ntlmssp server flags */ - uint32 ntlmssp_seq_num; /* ntlmssp sequence number */ - DOM_CRED clnt_cred; /* Client credential. */ - - int max_recv_frag; - int max_xmit_frag; - - vuser_key key; -}; - /* * Network Computing Architechture Context Name Named Pipe * See MSDN docs for more information @@ -1648,10 +1607,6 @@ typedef struct user_struct gid_t *groups; NT_USER_TOKEN *nt_user_token; - - /* per-user authentication information on NT RPCs */ - /* lkclXXXX - THIS SHOULD NOT BE HERE! */ - struct dcinfo dc; } user_struct; #include "ntdomain.h" diff --git a/source/rpc_server/srv_netlog_nt.c b/source/rpc_server/srv_netlog_nt.c index 764f76e0e47..f022b6f06b4 100644 --- a/source/rpc_server/srv_netlog_nt.c +++ b/source/rpc_server/srv_netlog_nt.c @@ -150,6 +150,8 @@ static BOOL get_md4pw(char *md4pw, char *mach_acct) } #endif /* 0 */ + /* JRA. This is ok as it is only used for generating the challenge. */ + become_root(); sampass = pdb_getsampwnam(mach_acct); unbecome_root(); @@ -175,10 +177,9 @@ uint32 _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u) { uint32 status = NT_STATUS_NOPROBLEMO; fstring mach_acct; - user_struct *vuser; - if ((vuser = get_valid_user_struct(p->vuid)) == NULL) - return False; + if (!get_valid_user_struct(p->vuid)) + return NT_STATUS_NO_SUCH_USER; fstrcpy(mach_acct, dos_unistrn2(q_u->uni_logon_clnt.buffer, q_u->uni_logon_clnt.uni_str_len)); @@ -186,29 +187,33 @@ uint32 _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u) strlower(mach_acct); fstrcat(mach_acct, "$"); - if (get_md4pw((char *)vuser->dc.md4pw, mach_acct)) { + if (get_md4pw((char *)p->dc.md4pw, mach_acct)) { /* copy the client credentials */ - memcpy(vuser->dc.clnt_chal.data , q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); - memcpy(vuser->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); + memcpy(p->dc.clnt_chal.data , q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); + memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); /* create a server challenge for the client */ /* Set these to random values. */ - generate_random_buffer(vuser->dc.srv_chal.data, 8, False); + generate_random_buffer(p->dc.srv_chal.data, 8, False); - memcpy(vuser->dc.srv_cred.challenge.data, vuser->dc.srv_chal.data, 8); + memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8); - memset((char *)vuser->dc.sess_key, '\0', sizeof(vuser->dc.sess_key)); + memset((char *)p->dc.sess_key, '\0', sizeof(p->dc.sess_key)); /* from client / server challenges and md4 password, generate sess key */ - cred_session_key(&vuser->dc.clnt_chal, &vuser->dc.srv_chal, - (char *)vuser->dc.md4pw, vuser->dc.sess_key); + cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal, + (char *)p->dc.md4pw, p->dc.sess_key); + + /* Save the machine account name. */ + fstrcpy(p->dc.mach_acct, mach_acct); + } else { /* lkclXXXX take a guess at a good error message to return :-) */ status = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } /* set up the LSA REQUEST CHALLENGE response */ - init_net_r_req_chal(r_u, &vuser->dc.srv_chal, status); + init_net_r_req_chal(r_u, &p->dc.srv_chal, status); return r_u->status; } @@ -223,22 +228,21 @@ uint32 _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u) DOM_CHAL srv_cred; UTIME srv_time; NEG_FLAGS srv_flgs; - user_struct *vuser; - if ((vuser = get_valid_user_struct(p->vuid)) == NULL) + if (!get_valid_user_struct(p->vuid)) return NT_STATUS_NO_SUCH_USER; srv_time.time = 0; /* check that the client credentials are valid */ - if (cred_assert(&q_u->clnt_chal, vuser->dc.sess_key, &vuser->dc.clnt_cred.challenge, srv_time)) { + if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) { /* create server challenge for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &vuser->dc.srv_cred.challenge, srv_time, &srv_cred); + cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred); /* copy the received client credentials for use next time */ - memcpy(vuser->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); - memcpy(vuser->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); + memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); + memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); } else { status = NT_STATUS_ACCESS_DENIED; } @@ -257,24 +261,22 @@ uint32 _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u) uint32 _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u) { - uint16 vuid = p->vuid; uint32 status = NT_STATUS_WRONG_PASSWORD; DOM_CRED srv_cred; pstring mach_acct; SAM_ACCOUNT *sampass; BOOL ret = False; - user_struct *vuser; unsigned char pwd[16]; int i; - if ((vuser = get_valid_user_struct(vuid)) == NULL) + if (!get_valid_user_struct(p->vuid)) return NT_STATUS_NO_SUCH_USER; /* checks and updates credentials. creates reply credentials */ - if (!deal_with_creds(vuser->dc.sess_key, &vuser->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred)) + if (!deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred)) return NT_STATUS_INVALID_HANDLE; - memcpy(&vuser->dc.srv_cred, &vuser->dc.clnt_cred, sizeof(vuser->dc.clnt_cred)); + memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred)); DEBUG(5,("_net_srv_pwset: %d\n", __LINE__)); @@ -287,15 +289,27 @@ uint32 _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_ sampass = pdb_getsampwnam(mach_acct); unbecome_root(); - if (sampass == NULL) + /* Ensure the account exists and is a machine account. */ + + if (sampass == NULL || !(pdb_get_acct_ctrl(sampass) & ACB_WSTRUST)) return NT_STATUS_NO_SUCH_USER; + /* + * Check the machine account name we're changing is the same + * as the one we've authenticated from. This prevents arbitrary + * machines changing other machine account passwords. + */ + + if (!strequal(mach_acct, p->dc.mach_acct)) + return NT_STATUS_ACCESS_DENIED; + + DEBUG(100,("Server password set : new given value was :\n")); for(i = 0; i < 16; i++) DEBUG(100,("%02X ", q_u->pwd[i])); DEBUG(100,("\n")); - cred_hash3( pwd, q_u->pwd, vuser->dc.sess_key, 0); + cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0); /* lies! nt and lm passwords are _not_ the same: don't care */ pdb_set_lanman_passwd (sampass, pwd); @@ -324,17 +338,15 @@ uint32 _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF { DOM_CRED srv_cred; - user_struct *vuser; - - if ((vuser = get_valid_user_struct(p->vuid)) == NULL) + if (!get_valid_user_struct(p->vuid)) return NT_STATUS_NO_SUCH_USER; /* checks and updates credentials. creates reply credentials */ - if (!deal_with_creds(vuser->dc.sess_key, &vuser->dc.clnt_cred, + if (!deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred)) return NT_STATUS_INVALID_HANDLE; - memcpy(&vuser->dc.srv_cred, &vuser->dc.clnt_cred, sizeof(vuser->dc.clnt_cred)); + memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred)); /* XXXX maybe we want to say 'no', reject the client's credentials */ r_u->buffer_creds = 1; /* yes, we have valid server credentials */ @@ -349,7 +361,7 @@ uint32 _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF net_login_interactive: *************************************************************************/ -static uint32 net_login_interactive(NET_ID_INFO_1 *id1, SAM_ACCOUNT *sampass, user_struct *vuser) +static uint32 net_login_interactive(NET_ID_INFO_1 *id1, SAM_ACCOUNT *sampass, pipes_struct *p) { uint32 status = 0x0; @@ -358,7 +370,7 @@ static uint32 net_login_interactive(NET_ID_INFO_1 *id1, SAM_ACCOUNT *sampass, us unsigned char key[16]; memset(key, 0, 16); - memcpy(key, vuser->dc.sess_key, 8); + memcpy(key, p->dc.sess_key, 8); memcpy(lm_pwd, id1->lm_owf.data, 16); memcpy(nt_pwd, id1->nt_owf.data, 16); @@ -444,28 +456,26 @@ static uint32 net_login_network(NET_ID_INFO_2 *id2, SAM_ACCOUNT *sampass) uint32 _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_u) { uint32 status = NT_STATUS_NOPROBLEMO; - uint16 vuid = p->vuid; NET_USER_INFO_3 *usr_info = NULL; DOM_CRED srv_cred; SAM_ACCOUNT *sampass = NULL; uint16 acct_ctrl; UNISTR2 *uni_samlogon_user = NULL; fstring nt_username; - user_struct *vuser = NULL; usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3)); if (!usr_info) return NT_STATUS_NO_MEMORY; ZERO_STRUCTP(usr_info); - if ((vuser = get_valid_user_struct(vuid)) == NULL) + if (!get_valid_user_struct(p->vuid)) return NT_STATUS_NO_SUCH_USER; /* checks and updates credentials. creates reply credentials */ - if (!deal_with_creds(vuser->dc.sess_key, &vuser->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred)) + if (!deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred)) return NT_STATUS_INVALID_HANDLE; else - memcpy(&vuser->dc.srv_cred, &vuser->dc.clnt_cred, sizeof(vuser->dc.clnt_cred)); + memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred)); /* find the username */ @@ -516,7 +526,7 @@ uint32 _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_ switch (q_u->sam_id.logon_level) { case INTERACTIVE_LOGON_TYPE: /* interactive login. */ - status = net_login_interactive(&q_u->sam_id.ctr->auth.id1, sampass, vuser); + status = net_login_interactive(&q_u->sam_id.ctr->auth.id1, sampass, p); break; case NET_LOGON_TYPE: /* network login. lm challenge and 24 byte responses */ diff --git a/source/smbd/password.c b/source/smbd/password.c index 9731b4140ce..12f7385f06c 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -313,8 +313,6 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, } } - memset(&vuser->dc, '\0', sizeof(vuser->dc)); - return vuser->vuid; }