From 25c70e3c984c4fed19763ed405741e83fe14f87e Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 15 Nov 1999 22:11:10 +0000 Subject: [PATCH] - added DCE/RPC "fault" PDU support. - disabled (AGAIN) the GETDC "if (MAILSLOT\NTLOGON)" code that will get NT5rc2 to work but WILL break win95 (AGAIN). this needs _not_ to be re-enabled but to be replaced with a better mechanism. - added SMBwrite support (note: SMBwriteX already existed) as NT5rc2 is sending DCE/RPC over SMBwrite not SMBwriteX. --- source/include/nameserv.h | 1 + source/include/ntdomain.h | 12 +++++---- source/include/proto.h | 5 ++++ source/include/rpc_dce.h | 9 +++++++ source/nmbd/nmbd_processlogon.c | 26 ++++++++++++++++---- source/rpc_parse/parse_rpc.c | 16 ++++++++++++ source/rpc_server/srv_pipe.c | 43 ++++++++++++++++++++++++++++++++- source/smbd/ipc.c | 9 ++++--- source/smbd/pipes.c | 41 +++++++++++++++++++++++++++++++ source/smbd/process.c | 2 +- source/smbd/reply.c | 4 +++ 11 files changed, 152 insertions(+), 16 deletions(-) diff --git a/source/include/nameserv.h b/source/include/nameserv.h index 995a47b2fa0..ad251314817 100644 --- a/source/include/nameserv.h +++ b/source/include/nameserv.h @@ -501,6 +501,7 @@ struct packet_struct #define QUERYFORPDC_R 12 /* Response to Query for PDC. */ #define SAMLOGON 18 #define SAMLOGON_R 19 +#define SAMLOGON_UNK_R 21 /* Ids for netbios packet types. */ diff --git a/source/include/ntdomain.h b/source/include/ntdomain.h index c36f619ef25..7f588744752 100644 --- a/source/include/ntdomain.h +++ b/source/include/ntdomain.h @@ -74,17 +74,19 @@ typedef struct pipes_struct fstring pipe_srv_name; prs_struct rhdr; /* output header */ + prs_struct rfault; /* fault */ prs_struct rdata; /* output data */ prs_struct rdata_i; /* output data (intermediate, for fragments) */ prs_struct rauth; /* output authentication verifier */ prs_struct rverf; /* output verifier */ prs_struct rntlm; /* output ntlmssp */ - RPC_HDR hdr; - RPC_HDR_BA hdr_ba; - RPC_HDR_RB hdr_rb; - RPC_HDR_REQ hdr_req; - RPC_HDR_RESP hdr_resp; + RPC_HDR hdr; + RPC_HDR_BA hdr_ba; + RPC_HDR_RB hdr_rb; + RPC_HDR_REQ hdr_req; + RPC_HDR_RESP hdr_resp; + RPC_HDR_FAULT hdr_fault; RPC_HDR_AUTH auth_info; RPC_HDR_AUTHA autha_info; diff --git a/source/include/proto.h b/source/include/proto.h index 0b0ca16c546..df05f2d7be1 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -480,6 +480,9 @@ int set_maxfiles(int requested_max); void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name); BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name); BOOL become_user_permanently(uid_t uid, gid_t gid); + +/*The following definitions come from lib/util_array.c */ + void free_void_array(uint32 num_entries, void **entries, void(free_item)(void*)); void* add_item_to_array(uint32 *len, void ***array, const void *item, @@ -2511,6 +2514,7 @@ BOOL reg_io_r_shutdown(char *desc, REG_R_SHUTDOWN *r_q, prs_struct *ps, int dep BOOL make_rpc_hdr(RPC_HDR *hdr, enum RPC_PKT_TYPE pkt_type, uint8 flags, uint32 call_id, int data_len, int auth_len); BOOL smb_io_rpc_hdr(char *desc, RPC_HDR *rpc, prs_struct *ps, int depth); +BOOL smb_io_rpc_hdr_fault(char *desc, RPC_HDR_FAULT *rpc, prs_struct *ps, int depth); BOOL make_rpc_hdr_rb(RPC_HDR_RB *rpc, uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid, uint32 num_elements, uint16 context_id, uint8 num_syntaxes, @@ -3912,6 +3916,7 @@ BOOL domain_client_validate( char *user, char *domain, int reply_open_pipe_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); +int reply_pipe_write(char *inbuf,char *outbuf,int length,int bufsize); int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize); int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize); int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf); diff --git a/source/include/rpc_dce.h b/source/include/rpc_dce.h index 3b2b3071d25..52544ac6422 100644 --- a/source/include/rpc_dce.h +++ b/source/include/rpc_dce.h @@ -43,6 +43,7 @@ enum RPC_PKT_TYPE /* DCE/RPC flags */ #define RPC_FLG_FIRST 0x01 #define RPC_FLG_LAST 0x02 +#define RPC_FLG_NOCALL 0x20 /* NTLMSSP message types */ enum NTLM_MESSAGE_TYPE @@ -127,6 +128,14 @@ typedef struct rpc_hdr_resp_info } RPC_HDR_RESP; +/* RPC_HDR_FAULT - ms fault rpc header */ +typedef struct rpc_hdr_fault_info +{ + uint32 status; + uint32 reserved; /* 0x0000 0000 */ + +} RPC_HDR_FAULT; + /* this seems to be the same string name depending on the name of the pipe, * but is more likely to be linked to the interface name * "srvsvc", "\\PIPE\\ntsvcs" diff --git a/source/nmbd/nmbd_processlogon.c b/source/nmbd/nmbd_processlogon.c index 0fc44a40c9a..6ddf47fc5f3 100644 --- a/source/nmbd/nmbd_processlogon.c +++ b/source/nmbd/nmbd_processlogon.c @@ -137,7 +137,9 @@ logons are not enabled.\n", inet_ntoa(p->ip) )); q = skip_string(q, 1); /* PDC name */ /* PDC and domain name */ +#if 0 if (strcmp(mailslot, NT_LOGON_MAILSLOT)==0) +#endif { q = align2(q, buf); @@ -179,13 +181,16 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", uniuser = skip_unibuf(unicomp, buf+len-q); getdc = skip_unibuf(uniuser, buf+len-q); q = skip_string(getdc,1); - q += 4; + q += 4; /* skip Account Control Bits */ domainsidsize = IVAL(q, 0); q += 4; - q += domainsidsize; - q = align4(q, buf); - q += 2; + if (domainsidsize != 0) + { + q += domainsidsize; + q += 2; + q = align4(q, buf); + } ntversion = IVAL(q, 0); q += 4; @@ -205,6 +210,10 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", fstrcpy(reply_name,"\\\\"); /* Here it wants \\LOGONSERVER. */ fstrcpy(reply_name+2,my_name); + ntversion = 0x01; + lmnttoken = 0xffff; + lm20token = 0xffff; + if (DEBUGLVL(3)) { fstring ascuser; @@ -221,7 +230,14 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", /* Construct reply. */ q = outbuf; - SSVAL(q, 0, SAMLOGON_R); + if (uniuser[0] == 0) + { + SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */ + } + else + { + SSVAL(q, 0, SAMLOGON_R); + } q += 2; /* Logon server, trust account, domain */ diff --git a/source/rpc_parse/parse_rpc.c b/source/rpc_parse/parse_rpc.c index b902ee14144..82b0be2802f 100644 --- a/source/rpc_parse/parse_rpc.c +++ b/source/rpc_parse/parse_rpc.c @@ -220,6 +220,22 @@ BOOL smb_io_rpc_hdr(char *desc, RPC_HDR *rpc, prs_struct *ps, int depth) return True; } +/******************************************************************* +reads or writes an RPC_HDR_FAULT structure. +********************************************************************/ +BOOL smb_io_rpc_hdr_fault(char *desc, RPC_HDR_FAULT *rpc, prs_struct *ps, int depth) +{ + if (rpc == NULL) return False; + + prs_debug(ps, depth, desc, "smb_io_rpc_hdr_fault"); + depth++; + + prs_uint32("status ", ps, depth, &(rpc->status )); + prs_uint32("reserved", ps, depth, &(rpc->reserved)); + + return True; +} + /******************************************************************* reads or writes an RPC_IFACE structure. ********************************************************************/ diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c index 458d7e883c8..1073ba21797 100644 --- a/source/rpc_server/srv_pipe.c +++ b/source/rpc_server/srv_pipe.c @@ -396,6 +396,45 @@ static BOOL api_pipe_bind_auth_resp(pipes_struct *p, prs_struct *pd) return api_pipe_ntlmssp(p, pd); } +static BOOL api_pipe_fault_resp(pipes_struct *p, prs_struct *pd, uint32 status) +{ + DEBUG(5,("api_pipe_fault_resp: make response\n")); + + prs_init(&(p->rhdr ), 0x18, 4, 0, False); + prs_init(&(p->rfault ), 0x8 , 4, 0, False); + + /***/ + /*** set up the header, response header and fault status ***/ + /***/ + + p->hdr_fault.status = status; + p->hdr_fault.reserved = 0x0; + + p->hdr_resp.alloc_hint = 0x0; + p->hdr_resp.cancel_count = 0x0; + p->hdr_resp.reserved = 0x0; + + make_rpc_hdr(&p->hdr, RPC_FAULT, RPC_FLG_NOCALL | RPC_FLG_FIRST | RPC_FLG_LAST, + p->hdr.call_id, + 0x20, + 0); + + smb_io_rpc_hdr ("hdr" , &(p->hdr ), &(p->rhdr), 0); + smb_io_rpc_hdr_resp ("resp" , &(p->hdr_resp ), &(p->rhdr), 0); + smb_io_rpc_hdr_fault("fault", &(p->hdr_fault), &(p->rfault), 0); + mem_realloc_data(p->rhdr.data, p->rhdr.offset); + mem_realloc_data(p->rfault.data, p->rfault.offset); + + /***/ + /*** link rpc header and fault together ***/ + /***/ + + prs_link(NULL , &p->rhdr , &p->rfault); + prs_link(&p->rhdr, &p->rfault, NULL ); + + return True; +} + static BOOL api_pipe_bind_and_alt_req(pipes_struct *p, prs_struct *pd, enum RPC_PKT_TYPE pkt_type) { uint16 assoc_gid; @@ -669,6 +708,8 @@ static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd) BOOL rpc_command(pipes_struct *p, prs_struct *pd) { BOOL reply = False; + DEBUG(10,("rpc_command\n")); + if (pd->data == NULL) return False; /* process the rpc header */ @@ -715,7 +756,7 @@ BOOL rpc_command(pipes_struct *p, prs_struct *pd) if (!reply) { - DEBUG(3,("rpc_command: DCE/RPC fault should be sent here\n")); + reply = api_pipe_fault_resp(p, pd, 0x1c010002); } return reply; diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 10c859d2666..a3e7932529a 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -3127,11 +3127,12 @@ static void api_rpc_trans_reply(char *outbuf, { /* all of data was sent: no need to wait for SMBreadX calls */ mem_free_data(p->rhdr .data); - mem_free_data(p->rdata.data); + mem_free_data(p->rfault .data); + mem_free_data(p->rdata .data); mem_free_data(p->rdata_i.data); - mem_free_data(p->rauth.data); - mem_free_data(p->rverf.data); - mem_free_data(p->rntlm.data); + mem_free_data(p->rauth .data); + mem_free_data(p->rverf .data); + mem_free_data(p->rntlm .data); } } diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 374aa70d0f2..e20d0498348 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -104,6 +104,47 @@ int reply_open_pipe_and_X(connection_struct *conn, return chain_reply(inbuf,outbuf,length,bufsize); } +/**************************************************************************** + reply to a write + + This code is basically stolen from reply_write with some + wrinkles to handle pipes. +****************************************************************************/ +int reply_pipe_write(char *inbuf,char *outbuf,int length,int bufsize) +{ + pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); + size_t numtowrite = SVAL(inbuf,smb_vwv1); + int nwritten = -1; + char *data; + size_t outsize; + + if (!p) return(ERROR(ERRDOS,ERRbadfid)); + + data = smb_buf(inbuf) + 3; + + if (numtowrite == 0) + { + nwritten = 0; + } + else + { + nwritten = write_pipe(p, data, numtowrite); + } + + if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) + { + return (UNIXERROR(ERRDOS,ERRnoaccess)); + } + + outsize = set_message(outbuf,1,0,True); + + SSVAL(outbuf,smb_vwv0,nwritten); + + DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", + p->pnum, nwritten)); + + return outsize; +} /**************************************************************************** reply to a write and X diff --git a/source/smbd/process.c b/source/smbd/process.c index e9fb230624c..1a6ec320e15 100644 --- a/source/smbd/process.c +++ b/source/smbd/process.c @@ -283,7 +283,7 @@ struct smb_message_struct {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, {SMBread,"SMBread",reply_read,AS_USER}, - {SMBwrite,"SMBwrite",reply_write,AS_USER}, + {SMBwrite,"SMBwrite",reply_write,AS_USER | CAN_IPC}, {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC}, {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 8723779d30b..0c4fb2003ca 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -2348,6 +2348,10 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i files_struct *fsp = file_fsp(inbuf,smb_vwv0); int outsize = 0; + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(conn)) + return reply_pipe_write(inbuf,outbuf,dum_size,dum_buffsize); + CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); CHECK_ERROR(fsp);