Exemple #1
0
/*
 * Starts the creation of a new printer file, which will be deleted
 * automatically once it has been closed and printed.
 *
 * SetupLength is the number of bytes in the first part of the resulting
 * print spool file which contains printer-specific control strings.
 *
 * Mode can have the following values:
 *      0     Text mode.  The server may optionally
 *            expand tabs to a series of spaces.
 *      1     Graphics mode.  No conversion of data
 *            should be done by the server.
 *
 * IdentifierString can be used by the server to provide some sort of
 * per-client identifying component to the print file.
 *
 * When the file is closed, it will be sent to the spooler and printed.
 */
smb_sdrc_t
smb_pre_open_print_file(smb_request_t *sr)
{
	struct open_param	*op = &sr->arg.open;
	char			*path;
	char			*identifier;
	uint32_t		new_id;
	uint16_t		setup;
	uint16_t		mode;
	int			rc;
	static uint32_t		tmp_id = 10000;

	bzero(op, sizeof (sr->arg.open));
	rc = smbsr_decode_vwv(sr, "ww", &setup, &mode);
	if (rc == 0)
		rc = smbsr_decode_data(sr, "%S", sr, &identifier);

	if (rc == 0) {
		path = smb_srm_zalloc(sr, MAXPATHLEN);
		op->fqi.fq_path.pn_path = path;
		new_id = atomic_inc_32_nv(&tmp_id);
		(void) snprintf(path, MAXPATHLEN, "%s%05u", identifier, new_id);
	}

	op->create_disposition = FILE_OVERWRITE_IF;
	op->create_options = FILE_NON_DIRECTORY_FILE;
	DTRACE_SMB_2(op__OpenPrintFile__start, smb_request_t *, sr,
	    struct open_param *, op);

	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
/*
 * smb_com_query_information (aka getattr)
 */
smb_sdrc_t
smb_pre_query_information(smb_request_t *sr)
{
	int rc;
	smb_fqi_t *fqi = &sr->arg.dirop.fqi;

	rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path);

	DTRACE_SMB_2(op__QueryInformation__start, smb_request_t *, sr,
	    smb_fqi_t *, fqi);

	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
Exemple #3
0
/*
 * The create directory message is sent to create a new directory.  The
 * appropriate Tid and additional pathname are passed.  The directory must
 * not exist for it to be created.
 *
 * Client Request                     Description
 * ================================== =================================
 * UCHAR WordCount;                   Count of parameter words = 0
 * USHORT ByteCount;                  Count of data bytes; min = 2
 * UCHAR BufferFormat;                0x04
 * STRING DirectoryName[];            Directory name
 *
 * Servers require clients to have at least create permission for the
 * subtree containing the directory in order to create a new directory.
 * The creator's access rights to the new directory are be determined by
 * local policy on the server.
 *
 * Server Response                    Description
 * ================================== =================================
 * UCHAR WordCount;                   Count of parameter words = 0
 * USHORT ByteCount;                  Count of data bytes = 0
 */
smb_sdrc_t
smb_pre_create_directory(smb_request_t *sr)
{
	int rc;

	rc = smbsr_decode_data(sr, "%S", sr,
	    &sr->arg.dirop.fqi.fq_path.pn_path);

	DTRACE_SMB_2(op__CreateDirectory__start, smb_request_t *, sr,
	    struct dirop *, &sr->arg.dirop);

	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
/*
 * smb_com_nt_create_andx
 *
 * This command is used to create or open a file or directory.
 *
 *  Client Request                     Description
 *  =================================  ==================================
 *
 *  UCHAR WordCount;                   Count of parameter words = 24
 *  UCHAR AndXCommand;                 Secondary command;  0xFF = None
 *  UCHAR AndXReserved;                Reserved (must be 0)
 *  USHORT AndXOffset;                 Offset to next command WordCount
 *  UCHAR Reserved;                    Reserved (must be 0)
 *  USHORT NameLength;                 Length of Name[] in bytes
 *  ULONG Flags;                       Create bit set:
 *                                     0x02 - Request an oplock
 *                                     0x04 - Request a batch oplock
 *                                     0x08 - Target of open must be
 *                                     directory
 *  ULONG RootDirectoryFid;            If non-zero, open is relative to
 *                                     this directory
 *  ACCESS_MASK DesiredAccess;         access desired
 *  LARGE_INTEGER AllocationSize;      Initial allocation size
 *  ULONG ExtFileAttributes;           File attributes
 *  ULONG ShareAccess;                 Type of share access
 *  ULONG CreateDisposition;           Action to take if file exists or
 *                                     not
 *  ULONG CreateOptions;               Options to use if creating a file
 *  ULONG ImpersonationLevel;          Security QOS information
 *  UCHAR SecurityFlags;               Security tracking mode flags:
 *                                     0x1 - SECURITY_CONTEXT_TRACKING
 *                                     0x2 - SECURITY_EFFECTIVE_ONLY
 *  USHORT ByteCount;                  Length of byte parameters
 *  STRING Name[];                     File to open or create
 *
 * The DesiredAccess parameter is specified in section 3.7 on  Access Mask
 * Encoding.
 *
 * If no value is specified, it still allows an application to query
 * attributes without actually accessing the file.
 *
 * The ExtFIleAttributes parameter specifies the file attributes and flags
 * for the file. The parameter's value is the sum of allowed attributes and
 * flags defined in section 3.11 on  Extended File Attribute Encoding
 *
 * The ShareAccess field Specifies how this file can be shared. This
 * parameter must be some combination of the following values:
 *
 * Name              Value      Meaning
 *                   0          Prevents the file from being shared.
 * FILE_SHARE_READ   0x00000001 Other open operations can be performed on
 *                               the file for read access.
 * FILE_SHARE_WRITE  0x00000002 Other open operations can be performed on
 *                               the file for write access.
 * FILE_SHARE_DELETE 0x00000004 Other open operations can be performed on
 *                               the file for delete access.
 *
 * The CreateDisposition parameter can contain one of the following values:
 *
 * CREATE_NEW        Creates a new file. The function fails if the
 *                   specified file already exists.
 * CREATE_ALWAYS     Creates a new file. The function overwrites the file
 *                   if it exists.
 * OPEN_EXISTING     Opens the file. The function fails if the file does
 *                   not exist.
 * OPEN_ALWAYS       Opens the file, if it exists. If the file does not
 *                   exist, act like CREATE_NEW.
 * TRUNCATE_EXISTING Opens the file. Once opened, the file is truncated so
 *                   that its size is zero bytes. The calling process must
 *                   open the file with at least GENERIC_WRITE access. The
 *                   function fails if the file does not exist.
 *
 * The ImpersonationLevel parameter can contain one or more of the
 * following values:
 *
 * SECURITY_ANONYMOUS        Specifies to impersonate the client at the
 *                           Anonymous impersonation level.
 * SECURITY_IDENTIFICATION   Specifies to impersonate the client at the
 *                           Identification impersonation level.
 * SECURITY_IMPERSONATION    Specifies to impersonate the client at the
 *                           Impersonation impersonation level.
 * SECURITY_DELEGATION       Specifies to impersonate the client at the
 *                           Delegation impersonation level.
 *
 * The SecurityFlags parameter can have either of the following two flags
 * set:
 *
 * SECURITY_CONTEXT_TRACKING  Specifies that the security tracking mode is
 *                            dynamic. If this flag is not specified,
 *                            Security Tracking Mode is static.
 * SECURITY_EFFECTIVE_ONLY    Specifies that only the enabled aspects of
 *                            the client's security context are available
 *                            to the server. If you do not specify this
 *                            flag, all aspects of the client's security
 *                            context are available. This flag allows the
 *                            client to limit the groups and privileges
 *                            that a server can use while impersonating the
 *                            client.
 *
 * The response is as follows:
 *
 *  Server Response                    Description
 *  =================================  ==================================
 *
 *  UCHAR WordCount;                   Count of parameter words = 26
 *  UCHAR AndXCommand;  Secondary      0xFF = None
 *  command;
 *  UCHAR AndXReserved;                MBZ
 *  USHORT AndXOffset;                 Offset to next command WordCount
 *  UCHAR OplockLevel;                 The oplock level granted
 *                                     0 - No oplock granted
 *                                     1 - Exclusive oplock granted
 *                                     2 - Batch oplock granted
 *                                     3 - Level II oplock granted
 *  USHORT Fid;                        The file ID
 *  ULONG CreateAction;                The action taken
 *  TIME CreationTime;                 The time the file was created
 *  TIME LastAccessTime;               The time the file was accessed
 *  TIME LastWriteTime;                The time the file was last written
 *  TIME ChangeTime;                   The time the file was last changed
 *  ULONG ExtFileAttributes;           The file attributes
 *  LARGE_INTEGER AllocationSize;      The number of bytes allocated
 *  LARGE_INTEGER EndOfFile;           The end of file offset
 *  USHORT FileType;
 *  USHORT DeviceState;                state of IPC device (e.g. pipe)
 *  BOOLEAN Directory;                 TRUE if this is a directory
 *  USHORT ByteCount;                  = 0
 *
 * The following SMBs may follow SMB_COM_NT_CREATE_ANDX:
 *
 *    SMB_COM_READ    SMB_COM_READ_ANDX
 *    SMB_COM_IOCTL
 */
smb_sdrc_t
smb_pre_nt_create_andx(smb_request_t *sr)
{
	struct open_param *op = &sr->arg.open;
	uint8_t SecurityFlags;
	uint32_t ImpersonationLevel;
	uint16_t NameLength;
	int rc;

	bzero(op, sizeof (sr->arg.open));

	rc = smbsr_decode_vwv(sr, "5.wlllqlllllb",
	    &NameLength,
	    &op->nt_flags,
	    &op->rootdirfid,
	    &op->desired_access,
	    &op->dsize,
	    &op->dattr,
	    &op->share_access,
	    &op->create_disposition,
	    &op->create_options,
	    &ImpersonationLevel,
	    &SecurityFlags);

	if (rc == 0) {
		if (NameLength == 0) {
			op->fqi.fq_path.pn_path = "\\";
		} else if (NameLength >= MAXPATHLEN) {
			smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
			    ERRDOS, ERROR_PATH_NOT_FOUND);
			rc = -1;
		} else {
			rc = smbsr_decode_data(sr, "%#u", sr, NameLength,
			    &op->fqi.fq_path.pn_path);
		}
	}

	op->op_oplock_level = SMB_OPLOCK_NONE;
	if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
		if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
			op->op_oplock_level = SMB_OPLOCK_BATCH;
		else
			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
	}

	DTRACE_SMB_2(op__NtCreateX__start, smb_request_t *, sr,
	    struct open_param *, op);

	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
Exemple #5
0
smb_sdrc_t
smb_com_write_print_file(smb_request_t *sr)
{
	smb_rw_param_t	*param = sr->arg.rw;
	smb_node_t	*node;
	smb_attr_t	attr;
	int		rc;

	if (sr->sr_server->sv_cfg.skc_print_enable == 0 ||
	    !STYPE_ISPRN(sr->tid_tree->t_res_type)) {
		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
		    ERRDOS, ERROR_BAD_DEV_TYPE);
		return (SDRC_ERROR);
	}

	smbsr_lookup_file(sr);
	if (sr->fid_ofile == NULL) {
		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
		return (SDRC_ERROR);
	}

	node = sr->fid_ofile->f_node;
	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);

	if (smb_node_getattr(sr, node, &attr) != 0) {
		smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
		    ERRDOS, ERROR_INTERNAL_ERROR);
		return (SDRC_ERROR);
	}

	if ((smbsr_decode_data(sr, "D", &param->rw_vdb)) != 0) {
		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
		    ERRDOS, ERROR_INVALID_PARAMETER);
		return (SDRC_ERROR);
	}

	param->rw_count = param->rw_vdb.vdb_len;
	param->rw_offset = attr.sa_vattr.va_size;
	param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;

	if ((rc = smb_common_write(sr, param)) != 0) {
		if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
			smbsr_errno(sr, rc);
		return (SDRC_ERROR);
	}

	rc = smbsr_encode_empty_result(sr);
	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
smb_sdrc_t
smb_pre_open(smb_request_t *sr)
{
	struct open_param *op = &sr->arg.open;
	int rc;

	bzero(op, sizeof (sr->arg.open));

	rc = smbsr_decode_vwv(sr, "ww", &op->omode, &op->fqi.fq_sattr);
	if (rc == 0)
		rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);

	DTRACE_SMB_2(op__Open__start, smb_request_t *, sr,
	    struct open_param *, op);

	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
Exemple #7
0
/*
 * Create a new file and return a fid.  The file is specified using
 * a fully qualified name relative to the tree.
 */
smb_sdrc_t
smb_pre_create_new(smb_request_t *sr)
{
	struct open_param *op = &sr->arg.open;
	int rc;

	bzero(op, sizeof (sr->arg.open));

	rc = smbsr_decode_vwv(sr, "wl", &op->dattr, &op->mtime.tv_sec);
	if (rc == 0)
		rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);

	op->create_disposition = FILE_CREATE;

	DTRACE_SMB_2(op__CreateNew__start, smb_request_t *, sr,
	    struct open_param *, op);

	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
Exemple #8
0
smb_sdrc_t
smb_pre_negotiate(smb_request_t *sr)
{
	smb_kmod_cfg_t		*skc;
	smb_arg_negotiate_t	*negprot;
	int			dialect;
	int			pos;
	int			rc = 0;

	skc = &sr->session->s_cfg;
	negprot = smb_srm_zalloc(sr, sizeof (smb_arg_negotiate_t));
	negprot->ni_index = -1;
	sr->sr_negprot = negprot;

	for (pos = 0; smbsr_decode_data_avail(sr); pos++) {
		if (smbsr_decode_data(sr, "%L", sr, &negprot->ni_name) != 0) {
			smbsr_error(sr, 0, ERRSRV, ERRerror);
			rc = -1;
			break;
		}

		if ((dialect = smb_xlate_dialect(negprot->ni_name)) < 0)
			continue;

		/*
		 * Conditionally recognize the SMB2 dialects.
		 */
		if (dialect >= DIALECT_SMB2002 &&
		    skc->skc_max_protocol < SMB_VERS_2_BASE)
			continue;

		if (negprot->ni_dialect < dialect) {
			negprot->ni_dialect = dialect;
			negprot->ni_index = pos;
		}
	}

	DTRACE_SMB_2(op__Negotiate__start, smb_request_t *, sr,
	    smb_arg_negotiate_t, negprot);

	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
/*
 * smb_pre_open_andx
 * For compatibility with windows servers, the search attributes
 * specified in the request are ignored.
 */
smb_sdrc_t
smb_pre_open_andx(smb_request_t *sr)
{
	struct open_param *op = &sr->arg.open;
	uint16_t flags;
	uint32_t creation_time;
	uint16_t file_attr, sattr;
	int rc;

	bzero(op, sizeof (sr->arg.open));

	rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com,
	    &sr->andx_off, &flags, &op->omode, &sattr,
	    &file_attr, &creation_time, &op->ofun, &op->dsize, &op->timeo);

	if (rc == 0) {
		rc = smbsr_decode_data(sr, "%u", sr, &op->fqi.fq_path.pn_path);

		op->dattr = file_attr;

		if (flags & 2)
			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
		else if (flags & 4)
			op->op_oplock_level = SMB_OPLOCK_BATCH;
		else
			op->op_oplock_level = SMB_OPLOCK_NONE;

		if ((creation_time != 0) && (creation_time != UINT_MAX))
			op->crtime.tv_sec =
			    smb_time_local_to_gmt(sr, creation_time);
		op->crtime.tv_nsec = 0;

		op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
	}

	DTRACE_SMB_2(op__OpenX__start, smb_request_t *, sr,
	    struct open_param *, op);

	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
smb_sdrc_t
smb_com_session_setup_andx(smb_request_t *sr)
{
	smb_sessionsetup_info_t sinfo;
	smb_session_key_t *session_key = NULL;
	char ipaddr_buf[INET6_ADDRSTRLEN];
	int native_lm;
	int auth_res;
	int rc;

	bzero(&sinfo, sizeof (smb_sessionsetup_info_t));

	if (sr->session->dialect >= NT_LM_0_12) {
		rc = smbsr_decode_vwv(sr, "b.wwwwlww4.l", &sr->andx_com,
		    &sr->andx_off, &sinfo.ssi_maxbufsize,
		    &sinfo.ssi_maxmpxcount, &sinfo.ssi_vcnumber,
		    &sinfo.ssi_sesskey, &sinfo.ssi_cipwlen,
		    &sinfo.ssi_cspwlen, &sinfo.ssi_capabilities);

		if (rc != 0)
			return (SDRC_ERROR);

		sinfo.ssi_cipwd = kmem_alloc(sinfo.ssi_cipwlen + 1, KM_SLEEP);
		sinfo.ssi_cspwd = kmem_alloc(sinfo.ssi_cspwlen + 1, KM_SLEEP);

		/*
		 * The padding between the Native OS and Native LM is a
		 * bit strange. On NT4.0, there is a 2 byte pad between
		 * the OS (Windows NT 1381) and LM (Windows NT 4.0).
		 * On Windows 2000, there is no padding between the OS
		 * (Windows 2000 2195) and LM (Windows 2000 5.0).
		 *
		 * If the padding is removed from this decode string
		 * the NT4.0 LM comes out as an empty string.
		 *
		 * So if the client's native OS is Win NT we consider
		 * the padding otherwise we don't.
		 */
		rc = smbsr_decode_data(sr, "%#c#cuuu",
		    sr,
		    sinfo.ssi_cipwlen, sinfo.ssi_cipwd,
		    sinfo.ssi_cspwlen, sinfo.ssi_cspwd,
		    &sinfo.ssi_user,
		    &sinfo.ssi_domain,
		    &sinfo.ssi_native_os);

		if (rc != 0) {
			kmem_free(sinfo.ssi_cipwd, sinfo.ssi_cipwlen + 1);
			kmem_free(sinfo.ssi_cspwd, sinfo.ssi_cspwlen + 1);
			return (SDRC_ERROR);
		}

		sinfo.ssi_cipwd[sinfo.ssi_cipwlen] = 0;
		sinfo.ssi_cspwd[sinfo.ssi_cspwlen] = 0;

		sr->session->native_os =
		    smbnative_os_value(sinfo.ssi_native_os);

		if (sr->session->native_os == NATIVE_OS_WINNT)
			rc = smbsr_decode_data(sr, "%,u", sr,
			    &sinfo.ssi_native_lm);
		else
			rc = smbsr_decode_data(sr, "%u", sr,
			    &sinfo.ssi_native_lm);

		/*
		 * If the Native Lanman cannot be determined,
		 * default to Windows NT.
		 */
		if (rc != 0 || sinfo.ssi_native_lm == NULL)
			sinfo.ssi_native_lm = "NT LAN Manager 4.0";
	} else {
		rc = smbsr_decode_vwv(sr, "b.wwwwlw4.", &sr->andx_com,
		    &sr->andx_off, &sinfo.ssi_maxbufsize,
		    &sinfo.ssi_maxmpxcount,
		    &sinfo.ssi_vcnumber, &sinfo.ssi_sesskey,
		    &sinfo.ssi_cipwlen);

		if (rc != 0)
			return (SDRC_ERROR);

		sinfo.ssi_cipwd = kmem_alloc(sinfo.ssi_cipwlen + 1, KM_SLEEP);
		rc = smbsr_decode_data(sr, "%#c", sr, sinfo.ssi_cipwlen,
		    sinfo.ssi_cipwd);
		if (rc != 0) {
			kmem_free(sinfo.ssi_cipwd, sinfo.ssi_cipwlen + 1);
			return (SDRC_ERROR);
		}

		sinfo.ssi_cipwd[sinfo.ssi_cipwlen] = 0;

		/*
		 * Despite the CIFS/1.0 spec, the rest of this message is
		 * not always present. We need to try to get the account
		 * name and the primary domain but we don't care about the
		 * the native OS or native LanMan fields.
		 */
		if (smbsr_decode_data(sr, "%u", sr, &sinfo.ssi_user) != 0)
			sinfo.ssi_user = "";

		if (smbsr_decode_data(sr, "%u", sr, &sinfo.ssi_domain) != 0)
			sinfo.ssi_domain = "";

		sr->session->native_os = NATIVE_OS_WINNT;
		sinfo.ssi_native_lm = "NT LAN Manager 4.0";
	}

	/*
	 * If the sinfo.ssi_vcnumber is zero, we can discard any
	 * other connections associated with this client.
	 */
	sr->session->vcnumber = sinfo.ssi_vcnumber;
	if (sinfo.ssi_vcnumber == 0)
		smb_server_reconnection_check(sr->sr_server, sr->session);

	auth_res = smb_authenticate(sr, &sinfo, &session_key);

	if (sinfo.ssi_cipwd)
		kmem_free(sinfo.ssi_cipwd, sinfo.ssi_cipwlen + 1);

	if (auth_res == SMB_AUTH_FAILED) {
		if (sinfo.ssi_cspwd)
			kmem_free(sinfo.ssi_cspwd, sinfo.ssi_cspwlen + 1);
		return (SDRC_ERROR);
	}

	native_lm = smbnative_lm_value(sinfo.ssi_native_lm);
	if (native_lm == NATIVE_LM_WIN2000)
		sinfo.ssi_capabilities |= CAP_LARGE_FILES |
		    CAP_LARGE_READX | CAP_LARGE_WRITEX;

	sr->session->smb_msg_size = sinfo.ssi_maxbufsize;
	sr->session->capabilities = sinfo.ssi_capabilities;

	/*
	 * Check to see if SMB signing is enable, but if it is already turned
	 * on leave it.
	 * The first authenticated logon provides the MAC key and sequence
	 * numbers for signing all further session on the
	 * same network connection.
	 */
	if (!(sr->session->signing.flags & SMB_SIGNING_ENABLED) &&
	    (sr->session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) &&
	    (sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) &&
	    session_key)
		smb_sign_init(sr, session_key, (char *)sinfo.ssi_cspwd,
		    sinfo.ssi_cspwlen);

	if (sinfo.ssi_cspwd)
		kmem_free(sinfo.ssi_cspwd, sinfo.ssi_cspwlen + 1);

	if (session_key)
		kmem_free(session_key, sizeof (smb_session_key_t));

	if (!(sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) &&
	    (sr->sr_cfg->skc_signing_required)) {
		(void) smb_inet_ntop(&sr->session->ipaddr, ipaddr_buf,
		    SMB_IPSTRLEN(sr->session->ipaddr.a_family));
		cmn_err(CE_NOTE,
		    "SmbSessonSetupX: client %s is not capable of signing",
		    ipaddr_buf);
		smbsr_error(sr, NT_STATUS_LOGON_FAILURE,
		    ERRDOS, ERROR_LOGON_FAILURE);
		return (SDRC_ERROR);
	}

	/*
	 * NT systems use different native OS and native LanMan values
	 * dependent on whether they are acting as a client or a server.
	 * As a server, NT 4.0 responds with the following values:
	 *
	 *	NativeOS:	Windows NT 4.0
	 *	NativeLM:	NT LAN Manager 4.0
	 *
	 * We should probably use the same values as NT but this code has
	 * been using the product name and "Windows NT 4.0" for a long time
	 * and I don't know if a change would cause any problems (see the
	 * conditional test below).
	 */
	rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu",
	    3,
	    sr->andx_com,
	    -1,			/* andx_off */
	    (auth_res == SMB_AUTH_GUEST) ? 1 : 0,
	    VAR_BCC,
	    sr,
	    "Windows NT 4.0",
	    "NT LAN Manager 4.0",
	    sr->sr_cfg->skc_nbdomain);

	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
Exemple #11
0
smb_sdrc_t
smb_com_write_raw(struct smb_request *sr)
{
	smb_rw_param_t		*param = sr->arg.rw;
	int			rc = 0;
	int			session_send_rc = 0;
	uint16_t		addl_xfer_count;
	offset_t		addl_xfer_offset;
	struct mbuf_chain	reply;
	smb_error_t		err;

	if (sr->session->s_state != SMB_SESSION_STATE_WRITE_RAW_ACTIVE)
		return (SDRC_DROP_VC);

	if (!smb_raw_mode) {
		smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS,
		    ERROR_NOT_SUPPORTED);
		return (SDRC_ERROR);
	}

	smbsr_lookup_file(sr);
	if (sr->fid_ofile == NULL) {
		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
		return (SDRC_ERROR);
	}

	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);

	/*
	 * Send response if there is additional data to transfer.
	 * This will prompt the client to send the remaining data.
	 */
	addl_xfer_count = param->rw_total - param->rw_count;
	addl_xfer_offset = param->rw_count;

	if (addl_xfer_count != 0) {
		MBC_INIT(&reply, MLEN);
		(void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT "bww",
		    sr->first_smb_com,
		    sr->smb_rcls,
		    sr->smb_reh,
		    sr->smb_err,
		    sr->smb_flg | SMB_FLAGS_REPLY,
		    sr->smb_flg2,
		    sr->smb_pid_high,
		    sr->smb_sig,
		    sr->smb_tid,
		    sr->smb_pid,
		    sr->smb_uid,
		    sr->smb_mid, 1, -1, 0);

		if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
			smb_sign_reply(sr, &reply);

		session_send_rc = smb_session_send(sr->session, 0, &reply);

		/*
		 * If the response failed, force write-through and
		 * complete the write before dealing with the error.
		 */
		if (session_send_rc != 0)
			param->rw_mode = SMB_WRMODE_WRITE_THRU;
	}

	/*
	 * While the response is in flight (and the data begins to arrive)
	 * write out the first data segment.
	 */
	if (smbsr_decode_data(sr, "#.#B", param->rw_dsoff, param->rw_count,
	    &param->rw_vdb) != 0)
		return (SDRC_ERROR);

	if (param->rw_count > 0)
		rc = smb_common_write(sr, param);

	if (session_send_rc != 0) {
		sr->smb_rcls = ERRSRV;
		sr->smb_err  = ERRusestd;
		goto write_raw_transfer_failed;
	}

	/*
	 * If we have more data to read then go get it
	 */
	if (addl_xfer_count > 0) {
		/*
		 * This is the only place where a worker thread should
		 * directly read from the session socket.  If the data
		 * is read successfully then the buffer (sr->sr_raw_data_buf)
		 * will need to be freed after the data is written.
		 */
		param->rw_offset += addl_xfer_offset;
		param->rw_vdb.vdb_uio.uio_loffset = param->rw_offset;
		param->rw_vdb.vdb_iovec[0].iov_len = addl_xfer_count;
		param->rw_vdb.vdb_uio.uio_resid = addl_xfer_count;
		if (smb_transfer_write_raw_data(sr, param) != 0)
			goto write_raw_transfer_failed;
	}

	/*
	 * Wake up session daemon since we now have all of our data and
	 * it's safe for the session daemon to resume processing SMB's.
	 */
	sr->session->s_write_raw_status = 0;
	sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED;

	/*
	 * If we didn't write all the data from the first segment then
	 * there's not much point in continuing (we still wanted to
	 * read any additional data above since we don't necessarily
	 * want to drop the connection and we need to read through
	 * to the next SMB).
	 */
	if (rc != 0)
		goto notify_write_raw_complete;

	/*
	 * Write any additional data
	 */
	if (addl_xfer_count > 0) {
		rc = smb_common_write(sr, param);
		addl_xfer_offset += param->rw_count;
	}

	/*
	 * If we were called in "Write-behind" mode and the transfer was
	 * successful then we don't need to send any further response.
	 * If we were called in "Write-Through" mode or if the transfer
	 * failed we need to send a completion notification.  The "count"
	 * value will indicate whether the transfer was successful.
	 */
	if ((rc != 0) || SMB_WRMODE_IS_STABLE(param->rw_mode))
		goto notify_write_raw_complete;

	(void) smb_session_send(sr->session, SESSION_KEEP_ALIVE, NULL);
	return (SDRC_NO_REPLY);

write_raw_transfer_failed:
	/*
	 * Raw data transfer failed, wake up session daemon
	 */
	sr->session->s_write_raw_status = 20;
	sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED;

notify_write_raw_complete:
	/*
	 * If we had an error fill in the appropriate error code
	 */
	if (rc != 0) {
		smbsr_map_errno(rc, &err);
		smbsr_set_error(sr, &err);
	}

	sr->first_smb_com = SMB_COM_WRITE_COMPLETE;
	rc = smbsr_encode_result(sr, 1, 0, "bww", 1, addl_xfer_offset, 0);
	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}