1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-08 04:58:40 +03:00

Big update moving the multi-pdu support from 2.0.x into HEAD for JF

and the printer functions.
Also tidied up some header includes and got the order right so you
can now do a :

make proto
make clean
make

Jeremy.
This commit is contained in:
Jeremy Allison -
parent d22d4482b5
commit 833cd9fba9
12 changed files with 1699 additions and 231 deletions

View File

@ -118,7 +118,7 @@ RPC_SERVER_OBJ = rpc_server/srv_lsa.o \
rpc_server/srv_pipe_hnd.o rpc_server/srv_reg.o \
rpc_server/srv_samr.o rpc_server/srv_srvsvc.o \
rpc_server/srv_util.o rpc_server/srv_wkssvc.o \
rpc_server/srv_pipe_srv.o rpc_server/srv_pipe.o \
rpc_server/srv_pipe.o \
rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o
RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_misc.o \

View File

@ -665,6 +665,8 @@ extern int errno;
#include "nterr.h"
#include "msdfs.h"
#ifdef WITH_PROFILE
#include "profile.h"
#endif
@ -914,6 +916,4 @@ int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
#include <dlfcn.h>
#endif
#include "msdfs.h"
#endif /* _INCLUDES_H */

View File

@ -22,8 +22,6 @@
#ifndef _MSDFS_H
#define _MSDFS_H
#ifdef MS_DFS
#define REFERRAL_TTL 600
/* Flags used in trans2 Get Referral reply */
@ -46,6 +44,16 @@ struct junction_map
struct referral* referral_list;
};
struct dfs_path
{
pstring hostname;
pstring servicename;
pstring volumename;
pstring restofthepath;
};
#ifdef MS_DFS
#define RESOLVE_DFSPATH(name, conn, inbuf, outbuf) \
{ if(((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES)) && \
dfs_redirect(name,conn)) \

View File

@ -1,3 +1,6 @@
#ifndef NT_PRINTING_H_
#define NT_PRINTING_H_
#define ORIENTATION 0x00000001L
#define PAPERSIZE 0x00000002L
#define PAPERLENGTH 0x00000004L
@ -235,3 +238,4 @@ typedef struct _form
UNISTR2 name;
} FORM;
*/
#endif /* NT_PRINTING_H_ */

View File

@ -24,10 +24,6 @@
#ifndef _NT_DOMAIN_H /* _NT_DOMAIN_H */
#define _NT_DOMAIN_H
/*
* A bunch of stuff that was put into smb.h
* in the NTDOM branch - it didn't belong there.
*/
/* dce/rpc support */
#include "rpc_dce.h"
@ -35,8 +31,10 @@
/* miscellaneous structures / defines */
#include "rpc_misc.h"
/* security descriptor structures */
#include "rpc_secdes.h"
/*
* A bunch of stuff that was put into smb.h
* in the NTDOM branch - it didn't belong there.
*/
typedef struct _prs_struct
{
@ -63,32 +61,8 @@ typedef struct _prs_struct
#define MARSHALLING(ps) (!(ps)->io)
#define UNMARSHALLING(ps) ((ps)->io)
typedef struct _input_data {
/*
* This is the current incoming pdu. The data here
* is collected via multiple writes until a complete
* pdu is seen, then the data is copied into the in_data
* structure. The maximum size of this is 64k (2 byte length).
*/
prs_struct in_pdu;
/*
* The amount of data needed to complete the in_pdu.
* If this is zero, then we are at the start of a new
* pdu.
*/
uint32 in_pdu_needed_len;
/*
* This is the collection of input data with all
* the rpc headers and auth footers removed.
* The maximum length of this is strictly enforced.
*/
prs_struct in_data;
} input_data;
typedef struct _output_data {
/*
/*
* Raw RPC output data. This does not include RPC headers or footers.
*/
prs_struct rdata;
@ -96,7 +70,7 @@ typedef struct _output_data {
/* The amount of data sent from the current rdata struct. */
uint32 data_sent_length;
/*
/*
* The current PDU being returned. This inclues
* headers, data and authentication footer.
*/
@ -109,6 +83,37 @@ typedef struct _output_data {
uint32 current_pdu_sent;
} output_data;
typedef struct _input_data {
/*
* This is the current incoming pdu. The data here
* is collected via multiple writes until a complete
* pdu is seen, then the data is copied into the in_data
* structure. The maximum size of this is 0x1630 (MAX_PDU_FRAG_LEN).
*/
unsigned char current_in_pdu[MAX_PDU_FRAG_LEN];
/*
* The amount of data needed to complete the in_pdu.
* If this is zero, then we are at the start of a new
* pdu.
*/
uint32 pdu_needed_len;
/*
* The amount of data received so far in the in_pdu.
* If this is zero, then we are at the start of a new
* pdu.
*/
uint32 pdu_received_len;
/*
* This is the collection of input data with all
* the rpc headers and auth footers removed.
* The maximum length of this (1Mb) is strictly enforced.
*/
prs_struct data;
} input_data;
typedef struct pipes_struct
{
struct pipes_struct *next, *prev;
@ -145,6 +150,18 @@ typedef struct pipes_struct
uid_t uid;
gid_t gid;
/*
* Set to true when an RPC bind has been done on this pipe.
*/
BOOL pipe_bound;
/*
* Set to true when we should return fault PDU's for everything.
*/
BOOL fault_state;
/*
* Struct to deal with multiple pdu inputs.
*/
@ -186,6 +203,9 @@ struct acct_info
uint32 smb_userid; /* domain-relative RID */
};
/* security descriptor structures */
#include "rpc_secdes.h"
/* different dce/rpc pipes */
#include "rpc_lsa.h"
#include "rpc_netlogon.h"

View File

@ -24,6 +24,7 @@ BOOL allow_access(char *deny_list,char *allow_list,
BOOL check_access(int sock, char *allow_list, char *deny_list);
/*The following definitions come from lib/bitmap.c */
struct bitmap *bitmap_allocate(int n);
BOOL bitmap_set(struct bitmap *bm, unsigned i);
BOOL bitmap_clear(struct bitmap *bm, unsigned i);
@ -800,6 +801,35 @@ BOOL downgrade_share_oplock(files_struct *fsp);
BOOL modify_share_mode(files_struct *fsp, int new_mode, uint16 new_oplock);
int share_mode_forall(SHAREMODE_FN(fn));
/*The following definitions come from msdfs/msdfs.c */
void create_nondfs_path(char* pathname, struct dfs_path* pdp);
BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp);
BOOL dfs_redirect(char* pathname, connection_struct* conn);
BOOL dfs_findfirst_redirect(char* pathname, connection_struct* conn);
int setup_dfs_referral(char* pathname, int max_referral_level,
char** ppdata);
int dfs_path_error(char* inbuf, char* outbuf);
int setup_dfs_referral(char* pathname, int max_referral_level,
char** ppdata);
int unistr_to_dos(char* dst,uint16* src) ;
/*The following definitions come from msdfs/msdfs_tdb.c */
BOOL msdfs_open(BOOL update);
BOOL add_junction_entry(struct junction_map* junction);
BOOL get_junction_entry(struct junction_map* junction);
BOOL isDfsShare(char* svc,char* vol);
void msdfs_close();
void msdfs_end();
/*The following definitions come from msdfs/parse_dfs_map.c */
BOOL parse_referral(char* s, struct referral* ref);
void load_dfsmaps();
BOOL load_dfsmap(char* fname, int snum);
void load_dfsmaps();
/*The following definitions come from nmbd/asyncdns.c */
int asyncdns_fd(void);
@ -1244,6 +1274,7 @@ BOOL lp_nt_acl_support(void);
BOOL lp_stat_cache(void);
BOOL lp_allow_trusted_domains(void);
BOOL lp_restrict_anonymous(void);
BOOL lp_host_msdfs(void);
int lp_os_level(void);
int lp_max_ttl(void);
int lp_max_wins_ttl(void);
@ -1304,12 +1335,13 @@ char *lp_readlist(int );
char *lp_writelist(int );
char *lp_fstype(int );
char *lp_vfsobj(int );
char *lp_dfsmap(int );
char *lp_mangled_map(int );
char *lp_veto_files(int );
char *lp_hide_files(int );
char *lp_veto_oplocks(int );
char *lp_driverlocation(int );
char *lp_dfsmap(int );
BOOL lp_dfsmap_loaded(int );
BOOL lp_preexec_close(int );
BOOL lp_rootpreexec_close(int );
BOOL lp_revalidate(int );
@ -1368,6 +1400,7 @@ BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir);
int lp_add_service(char *pszService, int iDefaultService);
BOOL lp_add_printer(char *pszPrintername, int iDefaultService);
BOOL lp_file_list_changed(void);
void set_dfsmap_loaded(int i,BOOL b);
void *lp_local_ptr(int snum, void *ptr);
BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue);
BOOL lp_is_default(int snum, struct parm_struct *parm);
@ -2562,17 +2595,21 @@ BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data);
/*The following definitions come from rpc_server/srv_pipe.c */
BOOL readwrite_pipe(pipes_struct *p, char *data, int len,
char **rdata, int *rlen);
ssize_t write_pipe(pipes_struct *p, char *data, size_t n);
int read_pipe(pipes_struct *p, char *data, int n);
BOOL create_next_pdu(pipes_struct *p);
BOOL api_pipe_bind_auth_resp(pipes_struct *p, prs_struct *rpc_in_p);
BOOL setup_fault_pdu(pipes_struct *p);
BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p);
BOOL api_pipe_auth_process(pipes_struct *p, prs_struct *rpc_in);
BOOL api_pipe_request(pipes_struct *p);
BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds,
prs_struct *rpc_in);
/*The following definitions come from rpc_server/srv_pipe_hnd.c */
void set_pipe_handle_offset(int max_open_files);
void reset_chain_p(void);
void init_rpc_pipe_hnd(void);
BOOL pipe_init_outgoing_data(output_data *out_data);
BOOL pipe_init_outgoing_data(output_data *o_data);
pipes_struct *open_rpc_pipe_p(char *pipe_name,
connection_struct *conn, uint16 vuid);
ssize_t write_to_pipe(pipes_struct *p, char *data, size_t n);
@ -2583,13 +2620,6 @@ BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn);
pipes_struct *get_rpc_pipe_p(char *buf, int where);
pipes_struct *get_rpc_pipe(int pnum);
/*The following definitions come from rpc_server/srv_pipe_srv.c */
BOOL create_next_pdu(pipes_struct *p);
BOOL rpc_command(pipes_struct *p, char *input_data, int data_len);
BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds,
prs_struct *rpc_in);
/*The following definitions come from rpc_server/srv_reg.c */
BOOL api_reg_rpc(pipes_struct *p, prs_struct *data);

View File

@ -1145,6 +1145,10 @@ struct bitmap {
#define SMB_SUPPORT_SEARCH_BITS 0x0001
#define SMB_SHARE_IN_DFS 0x0002
/* Named pipe write mode flags. Used in writeX calls. */
#define PIPE_RAW_MODE 0x4
#define PIPE_START_MESSAGE 0x8
/* these are the constants used in the above call. */
/* DesiredAccess */
/* File Specific access rights. */

View File

@ -31,14 +31,6 @@ extern global_client_caps;
#define VERSION3_REFERRAL_SIZE 0x22
#define REFERRAL_HEADER_SIZE 0x08
struct dfs_path
{
pstring hostname;
pstring servicename;
pstring volumename;
pstring restofthepath;
};
void create_nondfs_path(char* pathname, struct dfs_path* pdp)
{
pstrcpy(pathname,pdp->volumename);

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
@ -78,67 +77,61 @@ void init_rpc_pipe_hnd(void)
Initialise an outgoing packet.
****************************************************************************/
BOOL pipe_init_outgoing_data(output_data *out_data)
BOOL pipe_init_outgoing_data(output_data *o_data)
{
memset(out_data->current_pdu, '\0', sizeof(out_data->current_pdu));
memset(o_data->current_pdu, '\0', sizeof(o_data->current_pdu));
/* Free any memory in the current return data buffer. */
prs_mem_free(&out_data->rdata);
prs_mem_free(&o_data->rdata);
/*
* Initialize the outgoing RPC data buffer.
* we will use this as the raw data area for replying to rpc requests.
*/
if(!prs_init(&out_data->rdata, 1024, 4, MARSHALL)) {
if(!prs_init(&o_data->rdata, MAX_PDU_FRAG_LEN, 4, MARSHALL)) {
DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n"));
return False;
}
/* Reset the offset counters. */
out_data->data_sent_length = 0;
out_data->current_pdu_len = 0;
out_data->current_pdu_sent = 0;
o_data->data_sent_length = 0;
o_data->current_pdu_len = 0;
o_data->current_pdu_sent = 0;
return True;
}
/****************************************************************************
Find first available pipe slot.
HACK !!! Attempt to find a remote process to communicate RPC's with.
****************************************************************************/
pipes_struct *open_rpc_pipe_p(char *pipe_name,
connection_struct *conn, uint16 vuid)
static void attempt_remote_rpc_connect(pipes_struct *p)
{
int i;
pipes_struct *p;
static int next_pipe;
struct msrpc_state *m = NULL;
user_struct *vuser = get_valid_user_struct(vuid);
struct user_creds usr;
struct msrpc_state *m;
user_struct *vuser = get_valid_user_struct(p->vuid);
p->m = NULL;
if (vuser == NULL) {
DEBUG(4,("attempt_remote_rpc_connect: invalid vuid %d\n", (int)p->vuid));
return;
}
ZERO_STRUCT(usr);
DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
pipe_name, pipes_open));
if (vuser == NULL)
{
DEBUG(4,("invalid vuid %d\n", vuid));
return NULL;
}
/* set up unix credentials from the smb side, to feed over the pipe */
make_creds_unix(&usr.uxc, vuser->name, vuser->requested_name,
vuser->real_name, vuser->guest);
vuser->real_name, vuser->guest);
usr.ptr_uxc = 1;
make_creds_unix_sec(&usr.uxs, vuser->uid, vuser->gid,
vuser->n_groups, vuser->groups);
vuser->n_groups, vuser->groups);
usr.ptr_uxs = 1;
usr.ptr_ssk = 1;
DEBUG(0,("user session key not available (yet).\n"));
DEBUG(0,("password-change operations may fail.\n"));
DEBUG(10,("user session key not available (yet).\n"));
DEBUG(10,("password-change operations may fail.\n"));
#if USER_SESSION_KEY_DEFINED_IN_VUSER_STRUCT
memcpy(usr.usr_sess_key, vuser->usr_sess_key, sizeof(usr.usr_sess_key));
@ -153,14 +146,28 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
*/
become_root(False); /* to connect to pipe */
m = msrpc_use_add(pipe_name, getpid(), &usr, False);
p->m = msrpc_use_add(p->name, getpid(), &usr, False);
unbecome_root(False);
if (m == NULL)
{
DEBUG(10,("open pipes: msrpc redirect failed - go local.\n"));
}
if (p->m == NULL)
DEBUG(10,("attempt_remote_rpc_connect: msrpc redirect failed - using local implementation.\n"));
}
/****************************************************************************
Find first available pipe slot.
****************************************************************************/
pipes_struct *open_rpc_pipe_p(char *pipe_name,
connection_struct *conn, uint16 vuid)
{
int i;
pipes_struct *p;
static int next_pipe;
DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
pipe_name, pipes_open));
/* not repeating pipe numbers makes it easier to track things in
log files and prevents client bugs where pipe numbers are reused
over connection restarts */
@ -180,18 +187,26 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));
p = (pipes_struct *)malloc(sizeof(*p));
if (!p)
return NULL;
ZERO_STRUCTP(p);
/*
* Initialize the RPC and PDU data buffers with no memory.
*/
prs_init(&p->out_data.rdata, 0, 4, MARSHALL);
DLIST_ADD(Pipes, p);
/*
* Initialize the incoming RPC data buffer with one PDU worth of memory.
* We cheat here and say we're marshalling, as we intend to add incoming
* data directly into the prs_struct and we want it to auto grow. We will
* change the type to UNMARSALLING before processing the stream.
*/
if(!prs_init(&p->in_data.data, MAX_PDU_FRAG_LEN, 4, MARSHALL)) {
DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n"));
return NULL;
}
bitmap_set(bmap, i);
i += pipe_handle_offset;
@ -204,8 +219,6 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
p->priority = 0;
p->conn = conn;
p->vuid = vuid;
p->m = m;
p->max_trans_reply = 0;
@ -213,15 +226,40 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
p->ntlmssp_auth_validated = False;
p->ntlmssp_auth_requested = False;
p->pipe_bound = False;
p->fault_state = False;
/*
* Initialize the incoming RPC struct.
*/
p->in_data.pdu_needed_len = 0;
p->in_data.pdu_received_len = 0;
/*
* Initialize the outgoing RPC struct.
*/
p->out_data.current_pdu_len = 0;
p->out_data.current_pdu_sent = 0;
p->out_data.data_sent_length = 0;
/*
* Initialize the outgoing RPC data buffer with no memory.
*/
prs_init(&p->out_data.rdata, 0, 4, MARSHALL);
p->uid = (uid_t)-1;
p->gid = (gid_t)-1;
fstrcpy(p->name, pipe_name);
/*
* HACK !!! For Luke - attempt to connect to RPC redirect process.
*/
attempt_remote_rpc_connect(p);
DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
pipe_name, i, pipes_open));
@ -234,27 +272,408 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
return chain_p;
}
/****************************************************************************
Sets the fault state on incoming packets.
****************************************************************************/
static void set_incoming_fault(pipes_struct *p)
{
prs_mem_free(&p->in_data.data);
p->in_data.pdu_needed_len = 0;
p->in_data.pdu_received_len = 0;
p->fault_state = True;
DEBUG(10,("set_incoming_fault: Setting fault state on pipe %s : pnum = 0x%x\n",
p->name, p->pnum ));
}
/****************************************************************************
Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.
****************************************************************************/
static ssize_t fill_rpc_header(pipes_struct *p, char *data, size_t data_to_copy)
{
size_t len_needed_to_complete_hdr = MIN(data_to_copy, RPC_HEADER_LEN - p->in_data.pdu_received_len);
DEBUG(10,("fill_rpc_header: data_to_copy = %u, len_needed_to_complete_hdr = %u, receive_len = %u\n",
(unsigned int)data_to_copy, (unsigned int)len_needed_to_complete_hdr,
(unsigned int)p->in_data.pdu_received_len ));
memcpy((char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, len_needed_to_complete_hdr);
p->in_data.pdu_received_len += len_needed_to_complete_hdr;
return (ssize_t)len_needed_to_complete_hdr;
}
/****************************************************************************
Unmarshalls a new PDU header. Assumes the raw header data is in current_in_pdu.
****************************************************************************/
static ssize_t unmarshall_rpc_header(pipes_struct *p)
{
/*
* Unmarshall the header to determine the needed length.
*/
prs_struct rpc_in;
if(p->in_data.pdu_received_len != RPC_HEADER_LEN) {
DEBUG(0,("unmarshall_rpc_header: assert on rpc header length failed.\n"));
set_incoming_fault(p);
return -1;
}
prs_init( &rpc_in, 0, 4, UNMARSHALL);
prs_give_memory( &rpc_in, (char *)&p->in_data.current_in_pdu[0],
p->in_data.pdu_received_len, False);
/*
* Unmarshall the header as this will tell us how much
* data we need to read to get the complete pdu.
*/
if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) {
DEBUG(0,("unmarshall_rpc_header: failed to unmarshall RPC_HDR.\n"));
set_incoming_fault(p);
return -1;
}
/*
* Validate the RPC header.
*/
if(p->hdr.major != 5 && p->hdr.minor != 0) {
DEBUG(0,("unmarshall_rpc_header: invalid major/minor numbers in RPC_HDR.\n"));
set_incoming_fault(p);
return -1;
}
/*
* If there is no data in the incoming buffer and it's a requst pdu then
* ensure that the FIRST flag is set. If not then we have
* a stream missmatch.
*/
if((p->hdr.pkt_type == RPC_REQUEST) && (prs_offset(&p->in_data.data) == 0) && !(p->hdr.flags & RPC_FLG_FIRST)) {
DEBUG(0,("unmarshall_rpc_header: FIRST flag not set in first PDU !\n"));
set_incoming_fault(p);
return -1;
}
/*
* Ensure that the pdu length is sane.
*/
if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > MAX_PDU_FRAG_LEN)) {
DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));
set_incoming_fault(p);
return -1;
}
DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,
(unsigned int)p->hdr.flags ));
/*
* Adjust for the header we just ate.
*/
p->in_data.pdu_received_len = 0;
p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;
/*
* Null the data we just ate.
*/
memset((char *)&p->in_data.current_in_pdu[0], '\0', RPC_HEADER_LEN);
return 0; /* No extra data processed. */
}
/****************************************************************************
Processes a request pdu. This will do auth processing if needed, and
appends the data into the complete stream if the LAST flag is not set.
****************************************************************************/
static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
{
BOOL auth_verify = IS_BITS_SET_ALL(p->ntlmssp_chal_flags, NTLMSSP_NEGOTIATE_SIGN);
size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
(auth_verify ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;
if(!p->pipe_bound) {
DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
set_incoming_fault(p);
return False;
}
/*
* Check if we need to do authentication processing.
* This is only done on requests, not binds.
*/
/*
* Read the RPC request header.
*/
if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {
DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));
set_incoming_fault(p);
return False;
}
if(p->ntlmssp_auth_validated && !api_pipe_auth_process(p, rpc_in_p)) {
DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
set_incoming_fault(p);
return False;
}
if (p->ntlmssp_auth_requested && !p->ntlmssp_auth_validated) {
/*
* Authentication _was_ requested and it already failed.
*/
DEBUG(0,("process_request_pdu: RPC request received on pipe %s where \
authentication failed. Denying the request.\n", p->name));
set_incoming_fault(p);
return False;
}
/*
* Check the data length doesn't go over the 1Mb limit.
*/
if(prs_data_size(&p->in_data.data) + data_len > 1024*1024) {
DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",
(unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));
set_incoming_fault(p);
return False;
}
/*
* Append the data portion into the buffer and return.
*/
{
char *data_from = prs_data_p(rpc_in_p) + prs_offset(rpc_in_p);
if(!prs_append_data(&p->in_data.data, data_from, data_len)) {
DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",
(unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));
set_incoming_fault(p);
return False;
}
}
if(p->hdr.flags & RPC_FLG_LAST) {
BOOL ret;
/*
* Ok - we finally have a complete RPC stream.
* Call the rpc command to process it.
*/
/*
* Set the parse offset to the start of the data and set the
* prs_struct to UNMARSHALL.
*/
prs_set_offset(&p->in_data.data, 0);
prs_switch_type(&p->in_data.data, UNMARSHALL);
/*
* Process the complete data stream here.
*/
ret = api_pipe_request(p);
/*
* We have consumed the whole data stream. Set back to
* marshalling and set the offset back to the start of
* the buffer to re-use it (we could also do a prs_mem_free()
* and then re_init on the next start of PDU. Not sure which
* is best here.... JRA.
*/
prs_switch_type(&p->in_data.data, MARSHALL);
prs_set_offset(&p->in_data.data, 0);
return ret;
}
return True;
}
/****************************************************************************
Processes a finished PDU stored in current_in_pdu. The RPC_HEADER has
already been parsed and stored in p->hdr.
****************************************************************************/
static ssize_t process_complete_pdu(pipes_struct *p)
{
prs_struct rpc_in;
size_t data_len = p->in_data.pdu_received_len;
char *data_p = (char *)&p->in_data.current_in_pdu[0];
BOOL reply = False;
if(p->fault_state) {
DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n",
p->name ));
set_incoming_fault(p);
setup_fault_pdu(p);
return (ssize_t)data_len;
}
prs_init( &rpc_in, 0, 4, UNMARSHALL);
prs_give_memory( &rpc_in, data_p, (uint32)data_len, False);
DEBUG(10,("process_complete_pdu: processing packet type %u\n",
(unsigned int)p->hdr.pkt_type ));
switch (p->hdr.pkt_type) {
case RPC_BIND:
case RPC_ALTCONT:
/*
* We assume that a pipe bind is only in one pdu.
*/
reply = api_pipe_bind_req(p, &rpc_in);
break;
case RPC_BINDRESP:
/*
* We assume that a pipe bind_resp is only in one pdu.
*/
reply = api_pipe_bind_auth_resp(p, &rpc_in);
break;
case RPC_REQUEST:
reply = process_request_pdu(p, &rpc_in);
break;
default:
DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type ));
break;
}
if (!reply) {
DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on pipe %s\n", p->pipe_srv_name));
set_incoming_fault(p);
setup_fault_pdu(p);
} else {
/*
* Reset the lengths. We're ready for a new pdu.
*/
p->in_data.pdu_needed_len = 0;
p->in_data.pdu_received_len = 0;
}
return (ssize_t)data_len;
}
/****************************************************************************
Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.
****************************************************************************/
static ssize_t process_incoming_data(pipes_struct *p, char *data, size_t n)
{
size_t data_to_copy = MIN(n, MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len);
DEBUG(10,("process_incoming_data: Start: pdu_received_len = %u, pdu_needed_len = %u, incoming data = %u\n",
(unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len,
(unsigned int)n ));
if(data_to_copy == 0) {
/*
* This is an error - data is being received and there is no
* space in the PDU. Free the received data and go into the fault state.
*/
DEBUG(0,("process_incoming_data: No space in incoming pdu buffer. Current size = %u \
incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned int)n ));
set_incoming_fault(p);
return -1;
}
/*
* If we have no data already, wait until we get at least a RPC_HEADER_LEN
* number of bytes before we can do anything.
*/
if((p->in_data.pdu_needed_len == 0) && (p->in_data.pdu_received_len < RPC_HEADER_LEN)) {
/*
* Always return here. If we have more data then the RPC_HEADER
* will be processed the next time around the loop.
*/
return fill_rpc_header(p, data, data_to_copy);
}
/*
* At this point we know we have at least an RPC_HEADER_LEN amount of data
* stored in current_in_pdu.
*/
/*
* If pdu_needed_len is zero this is a new pdu.
* Unmarshall the header so we know how much more
* data we need, then loop again.
*/
if(p->in_data.pdu_needed_len == 0)
return unmarshall_rpc_header(p);
/*
* Ok - at this point we have a valid RPC_HEADER in p->hdr.
* Keep reading until we have a full pdu.
*/
data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len);
/*
* Copy as much of the data as we need into the current_in_pdu buffer.
*/
memcpy( (char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, data_to_copy);
p->in_data.pdu_received_len += data_to_copy;
/*
* Do we have a complete PDU ?
*/
if(p->in_data.pdu_received_len == p->in_data.pdu_needed_len)
return process_complete_pdu(p);
DEBUG(10,("process_incoming_data: not a complete PDU yet. pdu_received_len = %u, pdu_needed_len = %u\n",
(unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len ));
return (ssize_t)data_to_copy;
}
/****************************************************************************
Accepts incoming data on an rpc pipe.
This code is probably incorrect at the moment. The problem is
that the rpc request shouldn't really be executed until all the
data needed for it is received. This currently assumes that each
SMBwrite or SMBwriteX contains all the data needed for an rpc
request. JRA.
****************************************************************************/
****************************************************************************/
ssize_t write_to_pipe(pipes_struct *p, char *data, size_t n)
{
size_t data_left = n;
DEBUG(6,("write_to_pipe: %x", p->pnum));
DEBUG(6,("name: %s open: %s len: %d",
DEBUG(6,(" name: %s open: %s len: %d\n",
p->name, BOOLSTR(p->open), (int)n));
dump_data(50, data, n);
return rpc_command(p, data, (int)n) ? ((ssize_t)n) : -1;
while(data_left) {
ssize_t data_used;
DEBUG(10,("write_to_pipe: data_left = %u\n", (unsigned int)data_left ));
data_used = process_incoming_data(p, data, data_left);
DEBUG(10,("write_to_pipe: data_used = %d\n", (int)data_used ));
if(data_used < 0)
return -1;
data_left -= data_used;
data += data_used;
}
return n;
}
@ -282,7 +701,7 @@ int read_from_pipe(pipes_struct *p, char *data, int n)
DEBUG(6,("read_from_pipe: %x", p->pnum));
DEBUG(6,("name: %s len: %d\n", p->name, n));
DEBUG(6,(" name: %s len: %d\n", p->name, n));
/*
* We cannot return more than one PDU length per
@ -320,8 +739,9 @@ returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len,
* may of course be zero if this is the first return fragment.
*/
DEBUG(10,("read_from_pipe: %s: data_sent_length = %u, prs_offset(&p->out_data.rdata) = %u.\n",
p->name, (unsigned int)p->out_data.data_sent_length, (unsigned int)prs_offset(&p->out_data.rdata) ));
DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length \
= %u, prs_offset(&p->out_data.rdata) = %u.\n",
p->name, (int)p->fault_state, (unsigned int)p->out_data.data_sent_length, (unsigned int)prs_offset(&p->out_data.rdata) ));
if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) {
/*
@ -415,22 +835,17 @@ BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
pipes_open--;
if (p->m != NULL) {
DEBUG(4,("close_rpc_pipe_hnd: closing msrpc redirect: "));
if (msrpc_use_del(p->m->pipe_name, &p->m->usr, False, NULL))
DEBUG(4,("OK\n"));
else
DEBUG(4,("FAILED\n"));
}
DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n",
p->name, p->pnum, pipes_open));
if (p->m != NULL)
{
DEBUG(4,("closed msrpc redirect: "));
if (msrpc_use_del(p->m->pipe_name, &p->m->usr, False, NULL))
{
DEBUG(4,("OK\n"));
}
else
{
DEBUG(4,("FAILED\n"));
}
}
DLIST_REMOVE(Pipes, p);
ZERO_STRUCTP(p);

View File

@ -3201,20 +3201,11 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
Start the first part of an RPC reply which began with an SMBtrans request.
****************************************************************************/
static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p,
char *redir_data, int redir_len)
static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p)
{
char *rdata;
char *rdata = malloc(p->max_trans_reply);
int data_len;
if (redir_data != NULL)
{
send_trans_reply(outbuf, NULL, 0, redir_data, redir_len,
redir_len > p->max_trans_reply);
return True;
}
rdata = malloc(p->max_trans_reply);
if(rdata == NULL) {
DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
return False;
@ -3340,23 +3331,11 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
switch (subcommand) {
case 0x26:
{
char *rdata = NULL;
int rlen = mdrcnt;
if (p->m)
{
reply = readwrite_pipe(p, data, tdscnt, &rdata, &rlen);
}
else
{
/* dce/rpc command */
reply = rpc_command(p, data, tdscnt);
}
/* dce/rpc command */
reply = write_to_pipe(p, data, tdscnt);
if (reply)
reply = api_rpc_trans_reply(outbuf, p, rdata, rlen);
reply = api_rpc_trans_reply(outbuf, p);
break;
}
case 0x53:
/* Wait Named Pipe Handle state */
reply = api_WNPHS(outbuf, p, params, tpscnt);

View File

@ -129,16 +129,7 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize)
if (numtowrite == 0)
nwritten = 0;
else
{
if (p->m != NULL)
{
nwritten = write_pipe(p, data, numtowrite);
}
else
{
nwritten = write_to_pipe(p, data, numtowrite);
}
}
nwritten = write_to_pipe(p, data, numtowrite);
if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0))
return (UNIXERROR(ERRDOS,ERRnoaccess));
@ -154,17 +145,19 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize)
}
/****************************************************************************
reply to a write and X
Reply to a write and X.
This code is basically stolen from reply_write_and_X with some
wrinkles to handle pipes.
This code is basically stolen from reply_write_and_X with some
wrinkles to handle pipes.
****************************************************************************/
int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
{
pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2);
size_t numtowrite = SVAL(inbuf,smb_vwv10);
int nwritten = -1;
int smb_doff = SVAL(inbuf, smb_vwv11);
BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) != 0);
char *data;
if (!p)
@ -174,14 +167,31 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
if (numtowrite == 0)
nwritten = 0;
else
else {
if(pipe_start_message_raw) {
/*
* For the start of a message in named pipe byte mode,
* the first two bytes are a length-of-pdu field. Ignore
* them (we don't trust the client. JRA.
*/
if(numtowrite < 2) {
DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n",
(unsigned int)numtowrite ));
return (UNIXERROR(ERRDOS,ERRnoaccess));
}
data += 2;
numtowrite -= 2;
}
nwritten = write_to_pipe(p, data, numtowrite);
}
if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0))
return (UNIXERROR(ERRDOS,ERRnoaccess));
set_message(outbuf,6,0,True);
nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten);
SSVAL(outbuf,smb_vwv2,nwritten);
DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n",
@ -216,14 +226,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
set_message(outbuf,12,0,True);
data = smb_buf(outbuf);
if (p->m != NULL)
{
nread = read_pipe(p, data, smb_maxcnt);
}
else
{
nread = read_from_pipe(p, data, smb_maxcnt);
}
nread = read_from_pipe(p, data, smb_maxcnt);
if (nread < 0)
return(UNIXERROR(ERRDOS,ERRnoaccess));