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 = ¶ms[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 + -
显示快捷键?