📄 nttrans.c
字号:
/* Unix SMB/CIFS implementation. SMB NT transaction handling Copyright (C) Jeremy Allison 1994-1998 Copyright (C) Stefan (metze) Metzmacher 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"extern int max_send;extern enum protocol_types Protocol;extern int smb_read_error;extern struct current_user current_user;static const char *known_nt_pipes[] = { "\\LANMAN", "\\srvsvc", "\\samr", "\\wkssvc", "\\NETLOGON", "\\ntlsa", "\\ntsvcs", "\\lsass", "\\lsarpc", "\\winreg", "\\spoolss", "\\netdfs", "\\rpcecho", "\\svcctl", "\\eventlog", "\\unixinfo", NULL};static char *nttrans_realloc(char **ptr, size_t size){ char *tptr = NULL; if (ptr==NULL) { smb_panic("nttrans_realloc() called with NULL ptr\n"); } tptr = SMB_REALLOC(*ptr, size); if(tptr == NULL) { *ptr = NULL; return NULL; } memset(tptr,'\0',size); *ptr = tptr; return tptr;}/**************************************************************************** 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_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, char *params, int paramsize, char *pdata, int datasize){ 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 = 3; int data_alignment_offset = 0; /* * Initially set the wcnt area to be 18 - this is true for all * transNT replies. */ set_message(outbuf,18,0,True); if (NT_STATUS_V(nt_error)) { ERROR_NT(nt_error); } /* * 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_nt_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 a four byte * boundary (2 bytes for data len, one byte pad). * NT 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. */ total_sent_thistime = MIN(total_sent_thistime, useable_space); set_message(outbuf, 18, total_sent_thistime, True); /* * Set total params and data to be sent. */ SIVAL(outbuf,smb_ntr_TotalParameterCount,paramsize); SIVAL(outbuf,smb_ntr_TotalDataCount,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); SIVAL(outbuf,smb_ntr_ParameterCount,params_sent_thistime); if(params_sent_thistime == 0) { SIVAL(outbuf,smb_ntr_ParameterOffset,0); SIVAL(outbuf,smb_ntr_ParameterDisplacement,0); } else { /* * smb_ntr_ParameterOffset 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. */ SIVAL(outbuf,smb_ntr_ParameterOffset, ((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); /* * Absolute displacement of param bytes sent in this packet. */ SIVAL(outbuf,smb_ntr_ParameterDisplacement,pp - params); } /* * Deal with the data portion. */ SIVAL(outbuf,smb_ntr_DataCount, data_sent_thistime); if(data_sent_thistime == 0) { SIVAL(outbuf,smb_ntr_DataOffset,0); SIVAL(outbuf,smb_ntr_DataDisplacement, 0); } else { /* * The offset of the data bytes is the offset of the * parameter bytes plus the number of parameters being sent this time. */ SIVAL(outbuf,smb_ntr_DataOffset,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)) + params_sent_thistime + data_alignment_offset); SIVAL(outbuf,smb_ntr_DataDisplacement, 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,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", params_sent_thistime, data_sent_thistime, useable_space)); DEBUG(9,("nt_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_nt_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_nt_replies failed sanity check pts = %d, dts = %d\n!!!", params_to_send, data_to_send)); return -1; } } return 0;}/**************************************************************************** Is it an NTFS stream name ?****************************************************************************/BOOL is_ntfs_stream_name(const char *fname){ if (lp_posix_pathnames()) { return False; } return (strchr_m(fname, ':') != NULL) ? True : False;}/**************************************************************************** Save case statics.****************************************************************************/static BOOL saved_case_sensitive;static BOOL saved_case_preserve;static BOOL saved_short_case_preserve;/**************************************************************************** Save case semantics.****************************************************************************/static void set_posix_case_semantics(connection_struct *conn, uint32 file_attributes){ if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { return; } saved_case_sensitive = conn->case_sensitive; saved_case_preserve = conn->case_preserve; saved_short_case_preserve = conn->short_case_preserve; /* Set to POSIX. */ conn->case_sensitive = True; conn->case_preserve = True; conn->short_case_preserve = True;}/**************************************************************************** Restore case semantics.****************************************************************************/static void restore_case_semantics(connection_struct *conn, uint32 file_attributes){ if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { return; } conn->case_sensitive = saved_case_sensitive; conn->case_preserve = saved_case_preserve; conn->short_case_preserve = saved_short_case_preserve;}/**************************************************************************** Reply to an NT create and X call on a pipe.****************************************************************************/static int nt_open_pipe(char *fname, connection_struct *conn, char *inbuf, char *outbuf, int *ppnum){ smb_np_struct *p = NULL; uint16 vuid = SVAL(inbuf, smb_uid); int i; DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); /* See if it is one we want to handle. */ if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) { return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); } for( i = 0; known_nt_pipes[i]; i++ ) { if( strequal(fname,known_nt_pipes[i])) { break; } } if ( known_nt_pipes[i] == NULL ) { return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); } /* Strip \\ off the name. */ fname++; DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); p = open_rpc_pipe_p(fname, conn, vuid); if (!p) { return(ERROR_DOS(ERRSRV,ERRnofids)); } *ppnum = p->pnum; return 0;}/**************************************************************************** Reply to an NT create and X call for pipes.****************************************************************************/static int do_ntcreate_pipe_open(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize){ pstring fname; int ret; int pnum = -1; char *p = NULL; srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) { return ret; } /* * Deal with pipe return. */ set_message(outbuf,34,0,True); p = outbuf + smb_vwv2; p++; SSVAL(p,0,pnum); p += 2; SIVAL(p,0,FILE_WAS_OPENED); p += 4; p += 32; SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ p += 20; /* File type. */ SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); /* Device state. */ SSVAL(p,2, 0x5FF); /* ? */ DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname)); return chain_reply(inbuf,outbuf,length,bufsize);}/**************************************************************************** Reply to an NT create and X call for a quota file.****************************************************************************/int reply_ntcreate_and_X_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, enum FAKE_FILE_TYPE fake_file_type, const char *fname){ int result; char *p; uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); files_struct *fsp = open_fake_file(conn, fake_file_type, fname, desired_access); if (!fsp) { return ERROR_NT(NT_STATUS_ACCESS_DENIED); } set_message(outbuf,34,0,True); p = outbuf + smb_vwv2; /* SCVAL(p,0,NO_OPLOCK_RETURN); */ p++; SSVAL(p,0,fsp->fnum);#if 0 p += 2; SIVAL(p,0,smb_action); p += 4; /* Create time. */ put_long_date(p,c_time); p += 8; put_long_date(p,sbuf.st_atime); /* access time */ p += 8; put_long_date(p,sbuf.st_mtime); /* write time */ p += 8; put_long_date(p,sbuf.st_mtime); /* change time */ p += 8; SIVAL(p,0,fattr); /* File Attributes. */ p += 4; SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; if (flags & EXTENDED_RESPONSE_REQUIRED) SSVAL(p,2,0x7); p += 4; SCVAL(p,0,fsp->is_directory ? 1 : 0);#endif DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); result = chain_reply(inbuf,outbuf,length,bufsize); return result;}/**************************************************************************** Reply to an NT create and X call.****************************************************************************/int reply_ntcreate_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize){ int result; pstring fname;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -