trans2.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,183 行 · 第 1/5 页

C
2,183
字号
		return NULL;	}	eal->ea.flags = CVAL(pdata,0);	namelen = CVAL(pdata,1);	val_len = SVAL(pdata,2);	if (4 + namelen + 1 + val_len > data_size) {		return NULL;	}	/* Ensure the name is null terminated. */	if (pdata[namelen + 4] != '\0') {		return NULL;	}	pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);	if (!eal->ea.name) {		return NULL;	}	eal->ea.value = data_blob(NULL, (size_t)val_len + 1);	if (!eal->ea.value.data) {		return NULL;	}	memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);	/* Ensure we're null terminated just in case we print the value. */	eal->ea.value.data[val_len] = '\0';	/* But don't count the null. */	eal->ea.value.length--;	if (pbytes_used) {		*pbytes_used = 4 + namelen + 1 + val_len;	}	DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));	dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);	return eal;}/**************************************************************************** Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.****************************************************************************/static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size){	struct ea_list *ea_list_head = NULL;	size_t offset = 0;	size_t bytes_used = 0;	while (offset < data_size) {		struct ea_list *tmp;		struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);		if (!eal) {			return NULL;		}		DLIST_ADD_END(ea_list_head, eal, tmp);		offset += bytes_used;	}	return ea_list_head;}/**************************************************************************** Count the total EA size needed.****************************************************************************/static size_t ea_list_size(struct ea_list *ealist){	fstring dos_ea_name;	struct ea_list *listp;	size_t ret = 0;	for (listp = ealist; listp; listp = listp->next) {		push_ascii_fstring(dos_ea_name, listp->ea.name);		ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;	}	/* Add on 4 for total length. */	if (ret) {		ret += 4;	}	return ret;}/**************************************************************************** Return a union of EA's from a file list and a list of names. The TALLOC context for the two lists *MUST* be identical as we steal memory from one list to add to another. JRA.****************************************************************************/static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len){	struct ea_list *nlistp, *flistp;	for (nlistp = name_list; nlistp; nlistp = nlistp->next) {		for (flistp = file_list; flistp; flistp = flistp->next) {			if (strequal(nlistp->ea.name, flistp->ea.name)) {				break;			}		}		if (flistp) {			/* Copy the data from this entry. */			nlistp->ea.flags = flistp->ea.flags;			nlistp->ea.value = flistp->ea.value;		} else {			/* Null entry. */			nlistp->ea.flags = 0;			ZERO_STRUCT(nlistp->ea.value);		}	}	*total_ea_len = ea_list_size(name_list);	return name_list;}/****************************************************************************  Send the required number of replies back.  We assume all fields other than the data fields are  set correctly for the type of call.  HACK ! Always assumes smb_setup field is zero.****************************************************************************/static int send_trans2_replies(char *outbuf,			int bufsize,			char *params, 			int paramsize,			char *pdata,			int datasize){	/* As we are using a protocol > LANMAN1 then the max_send	 variable must have been set in the sessetupX call.	 This takes precedence over the max_xmit field in the	 global struct. These different max_xmit variables should	 be merged as this is now too confusing */	int data_to_send = datasize;	int params_to_send = paramsize;	int useable_space;	char *pp = params;	char *pd = pdata;	int params_sent_thistime, data_sent_thistime, total_sent_thistime;	int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */	int data_alignment_offset = 0;	/* Initially set the wcnt area to be 10 - this is true for all trans2 replies */		set_message(outbuf,10,0,True);	/* If there genuinely are no parameters or data to send just send the empty packet */	if(params_to_send == 0 && data_to_send == 0) {		show_msg(outbuf);		if (!send_smb(smbd_server_fd(),outbuf))			exit_server("send_trans2_replies: send_smb failed.");		return 0;	}	/* When sending params and data ensure that both are nicely aligned */	/* Only do this alignment when there is also data to send - else		can cause NT redirector problems. */	if (((params_to_send % 4) != 0) && (data_to_send != 0))		data_alignment_offset = 4 - (params_to_send % 4);	/* Space is bufsize minus Netbios over TCP header minus SMB header */	/* The alignment_offset is to align the param bytes on an even byte		boundary. NT 4.0 Beta needs this to work correctly. */	useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);	/* useable_space can never be more than max_send minus the alignment offset. */	useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));	while (params_to_send || data_to_send) {		/* Calculate whether we will totally or partially fill this packet */		total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;		/* We can never send more than useable_space */		/*		 * Note that 'useable_space' does not include the alignment offsets,		 * but we must include the alignment offsets in the calculation of		 * the length of the data we send over the wire, as the alignment offsets		 * are sent here. Fix from Marc_Jacobsen@hp.com.		 */		total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);		set_message(outbuf, 10, total_sent_thistime, True);		/* Set total params and data to be sent */		SSVAL(outbuf,smb_tprcnt,paramsize);		SSVAL(outbuf,smb_tdrcnt,datasize);		/* Calculate how many parameters and data we can fit into		 * this packet. Parameters get precedence		 */		params_sent_thistime = MIN(params_to_send,useable_space);		data_sent_thistime = useable_space - params_sent_thistime;		data_sent_thistime = MIN(data_sent_thistime,data_to_send);		SSVAL(outbuf,smb_prcnt, params_sent_thistime);		/* smb_proff is the offset from the start of the SMB header to the			parameter bytes, however the first 4 bytes of outbuf are			the Netbios over TCP header. Thus use smb_base() to subtract			them from the calculation */		SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));		if(params_sent_thistime == 0)			SSVAL(outbuf,smb_prdisp,0);		else			/* Absolute displacement of param bytes sent in this packet */			SSVAL(outbuf,smb_prdisp,pp - params);		SSVAL(outbuf,smb_drcnt, data_sent_thistime);		if(data_sent_thistime == 0) {			SSVAL(outbuf,smb_droff,0);			SSVAL(outbuf,smb_drdisp, 0);		} else {			/* The offset of the data bytes is the offset of the				parameter bytes plus the number of parameters being sent this time */			SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 				smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);			SSVAL(outbuf,smb_drdisp, pd - pdata);		}		/* Copy the param bytes into the packet */		if(params_sent_thistime)			memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);		/* Copy in the data bytes */		if(data_sent_thistime)			memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+				data_alignment_offset,pd,data_sent_thistime);		DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",			params_sent_thistime, data_sent_thistime, useable_space));		DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",			params_to_send, data_to_send, paramsize, datasize));		/* Send the packet */		show_msg(outbuf);		if (!send_smb(smbd_server_fd(),outbuf))			exit_server("send_trans2_replies: send_smb failed.");		pp += params_sent_thistime;		pd += data_sent_thistime;		params_to_send -= params_sent_thistime;		data_to_send -= data_sent_thistime;		/* Sanity check */		if(params_to_send < 0 || data_to_send < 0) {			DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",				params_to_send, data_to_send));			return -1;		}	}	return 0;}/**************************************************************************** Reply to a TRANSACT2_OPEN.****************************************************************************/static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  				char **pparams, int total_params, char **ppdata, int total_data,				unsigned int max_data_bytes){	char *params = *pparams;	char *pdata = *ppdata;	int deny_mode;	int32 open_attr;	BOOL oplock_request;#if 0	BOOL return_additional_info;	int16 open_sattr;	time_t open_time;#endif	int open_ofun;	int32 open_size;	char *pname;	pstring fname;	SMB_OFF_T size=0;	int fattr=0,mtime=0;	SMB_INO_T inode = 0;	SMB_STRUCT_STAT sbuf;	int smb_action = 0;	BOOL bad_path = False;	files_struct *fsp;	TALLOC_CTX *ctx = NULL;	struct ea_list *ea_list = NULL;	uint16 flags = 0;	NTSTATUS status;	uint32 access_mask;	uint32 share_mode;	uint32 create_disposition;	uint32 create_options = 0;	/*	 * Ensure we have enough parameters to perform the operation.	 */	if (total_params < 29) {		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);	}	flags = SVAL(params, 0);	deny_mode = SVAL(params, 2);	open_attr = SVAL(params,6);        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;        if (oplock_request) {                oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;        }#if 0	return_additional_info = BITSETW(params,0);	open_sattr = SVAL(params, 4);	open_time = make_unix_date3(params+8);#endif	open_ofun = SVAL(params,12);	open_size = IVAL(params,14);	pname = &params[28];	if (IS_IPC(conn)) {		return(ERROR_DOS(ERRSRV,ERRaccess));	}	srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);	if (!NT_STATUS_IS_OK(status)) {		return ERROR_NT(status);	}	DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",		fname, (unsigned int)deny_mode, (unsigned int)open_attr,		(unsigned int)open_ofun, open_size));	/* XXXX we need to handle passed times, sattr and flags */	unix_convert(fname,conn,0,&bad_path,&sbuf);	if (bad_path) {		return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);	}    	if (!check_name(fname,conn)) {		return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);	}	if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,				&access_mask,				&share_mode,				&create_disposition,				&create_options)) {		return ERROR_DOS(ERRDOS, ERRbadaccess);	}	/* Any data in this call is an EA list. */	if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {		return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);	}	if (total_data != 4) {		if (total_data < 10) {			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);		}		if (IVAL(pdata,0) > total_data) {			DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",				IVAL(pdata,0), (unsigned int)total_data));			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);		}		ctx = talloc_init("TRANS2_OPEN_SET_EA");		if (!ctx) {			return ERROR_NT(NT_STATUS_NO_MEMORY);		}		ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);		if (!ea_list) {			talloc_destroy(ctx);			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);		}	} else if (IVAL(pdata,0) != 4) {		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);	}	fsp = open_file_ntcreate(conn,fname,&sbuf,		access_mask,		share_mode,		create_disposition,		create_options,		open_attr,		oplock_request,		&smb_action);      	if (!fsp) {		talloc_destroy(ctx);		if (open_was_deferred(SVAL(inbuf,smb_mid))) {			/* We have re-scheduled this call. */			return -1;		}		return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);	}	size = get_file_size(sbuf);	fattr = dos_mode(conn,fname,&sbuf);	mtime = sbuf.st_mtime;	inode = sbuf.st_ino;	if (fattr & aDIR) {		talloc_destroy(ctx);		close_file(fsp,False);		return(ERROR_DOS(ERRDOS,ERRnoaccess));	}	if (total_data && smb_action == FILE_WAS_CREATED) {		status = set_ea(conn, fsp, fname, ea_list);		talloc_destroy(ctx);		if (!NT_STATUS_IS_OK(status)) {			close_file(fsp,False);			return ERROR_NT(status);		}	}	/* Realloc the size of parameters and data we will return */	params = SMB_REALLOC(*pparams, 30);	if( params == NULL ) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?