示例#1
0
/*
 * Returns the Unicode string length for the target UNC of
 * the specified entry by 'refno'
 *
 * Note that the UNC path should be encoded with ONE leading
 * slash not two as is common to user-visible UNC paths.
 */
static uint16_t
smb_dfs_referrals_unclen(dfs_info_t *referrals, uint16_t refno)
{
	uint16_t len;

	if (refno >= referrals->i_ntargets)
		return (0);

	/* Encoded target UNC \server\share */
	len = smb_wcequiv_strlen(referrals->i_targets[refno].t_server) +
	    smb_wcequiv_strlen(referrals->i_targets[refno].t_share) +
	    smb_wcequiv_strlen("\\\\") + 2; /* two '\' + NULL */

	return (len);
}
示例#2
0
/*
 * samr_lookup_domain
 *
 * Lookup up the domain SID for the specified domain name. The handle
 * should be one returned from samr_connect. The allocated memory for
 * the returned SID must be freed by caller.
 */
smb_sid_t *
samr_lookup_domain(mlsvc_handle_t *samr_handle, char *domain_name)
{
	struct samr_LookupDomain	arg;
	smb_sid_t	*domsid = NULL;
	int		opnum;
	size_t		length;

	if (ndr_is_null_handle(samr_handle) || domain_name == NULL)
		return (NULL);

	opnum = SAMR_OPNUM_LookupDomain;
	bzero(&arg, sizeof (struct samr_LookupDomain));

	(void) memcpy(&arg.handle, &samr_handle->handle,
	    sizeof (samr_handle_t));

	length = smb_wcequiv_strlen(domain_name);
	if (ndr_rpc_server_os(samr_handle) == NATIVE_OS_WIN2000)
		length += sizeof (smb_wchar_t);

	arg.domain_name.length = length;
	arg.domain_name.allosize = length;
	arg.domain_name.str = (unsigned char *)domain_name;

	if (ndr_rpc_call(samr_handle, opnum, &arg) == 0)
		domsid = smb_sid_dup((smb_sid_t *)arg.sid);

	ndr_rpc_release(samr_handle);
	return (domsid);
}
示例#3
0
/*
 * FileFsVolumeInformation
 */
uint32_t
smb2_qfs_volume(smb_request_t *sr)
{
	smb_tree_t *tree = sr->tid_tree;
	smb_node_t *snode;
	fsid_t fsid;
	uint32_t LabelLength;

	if (!STYPE_ISDSK(tree->t_res_type))
		return (NT_STATUS_INVALID_PARAMETER);

	snode = tree->t_snode;
	fsid = SMB_NODE_FSID(snode);

	LabelLength = smb_wcequiv_strlen(tree->t_volume);

	/*
	 * NT has the "supports objects" flag set to 1.
	 */
	(void) smb_mbc_encodef(
	    &sr->raw_data, "qllb.U",
	    0LL,	/* Volume creation time (q) */
	    fsid.val[0],	/* serial no.   (l) */
	    LabelLength,		/*	(l) */
	    0,		/* Supports objects	(b) */
	    /* reserved				(.) */
	    tree->t_volume);		/*	(U) */

	return (0);
}
示例#4
0
/*
 * This fills in a samr_user_password (a.k.a. SAMPR_USER_PASSWORD
 * in the MS Net API) which has the new password "right justified"
 * in the buffer, and any space on the left filled with random junk
 * to improve the quality of the encryption that is subsequently
 * applied to this buffer before it goes over the wire.
 */
static void
samr_fill_userpw(struct samr_user_password *upw, const char *new_pw)
{
	smb_wchar_t *pbuf;
	uint32_t pwlen_bytes;
	size_t pwlen_wchars;

	/*
	 * First fill the whole buffer with the random junk.
	 * (Slightly less random when debugging:)
	 */
#ifdef DEBUG
	(void) memset(upw->Buffer, '*', sizeof (upw->Buffer));
#else
	randomize((char *)upw->Buffer, sizeof (upw->Buffer));
#endif

	/*
	 * Now overwrite the last pwlen characters of
	 * that buffer with the password, and set the
	 * length field so the receiving end knows where
	 * the junk ends and the real password starts.
	 */
	pwlen_wchars = smb_wcequiv_strlen(new_pw) / 2;
	if (pwlen_wchars > SAMR_USER_PWLEN)
		pwlen_wchars = SAMR_USER_PWLEN;
	pwlen_bytes = pwlen_wchars * 2;

	pbuf = &upw->Buffer[SAMR_USER_PWLEN - pwlen_wchars];
	(void) smb_mbstowcs(pbuf, new_pw, pwlen_wchars);

	/* Yes, this is in Bytes, not wchars. */
	upw->Length = htolel(pwlen_bytes);
}
示例#5
0
/*
 * Prepare a response with V3/V4 referral format.
 *
 * For more details, see comments for smb_dfs_encode_refv2() or see
 * MS-DFSC specification.
 */
static uint32_t
smb_dfs_encode_refv3x(smb_request_t *sr, mbuf_chain_t *mbc,
	dfs_info_t *referrals,
    uint16_t ver)
{
	_NOTE(ARGUNUSED(sr))
	uint16_t entsize, rep_bufsize, hdrsize;
	uint16_t server_type;
	uint16_t flags = 0;
	uint16_t path_offs, altpath_offs, netpath_offs;
	uint16_t targetsz, total_targetsz = 0;
	uint16_t dfs_pathsz;
	uint16_t r;

	hdrsize = (ver == DFS_REFERRAL_V3) ? DFS_REFV3_ENTSZ : DFS_REFV4_ENTSZ;
	rep_bufsize = MBC_MAXBYTES(mbc);
	dfs_pathsz = smb_wcequiv_strlen(referrals->i_uncpath) + 2;
	entsize = hdrsize + dfs_pathsz + dfs_pathsz +
	    smb_dfs_referrals_unclen(referrals, 0);

	if (entsize > rep_bufsize) {
		/* need room for at least one referral */
		return (NT_STATUS_BUFFER_OVERFLOW);
	}

	server_type = (referrals->i_type == DFS_OBJECT_ROOT) ?
	    DFS_SRVTYPE_ROOT : DFS_SRVTYPE_NONROOT;

	rep_bufsize -= entsize;

	for (r = 0; r < referrals->i_ntargets; r++) {
		path_offs = (referrals->i_ntargets - r) * hdrsize;
		altpath_offs = path_offs + dfs_pathsz;
		netpath_offs = altpath_offs + dfs_pathsz + total_targetsz;
		targetsz = smb_dfs_referrals_unclen(referrals, r);

		if (r != 0) {
			entsize = hdrsize + targetsz;
			if (entsize > rep_bufsize)
				/* silently drop targets that do not fit */
				break;
			rep_bufsize -= entsize;
			flags = 0;
		} else if (ver == DFS_REFERRAL_V4) {
			flags = DFS_ENTFLG_T;
		}

		(void) smb_mbc_encodef(mbc, "wwwwlwww16.",
		    ver, hdrsize, server_type, flags,
		    referrals->i_timeout, path_offs, altpath_offs,
		    netpath_offs);

		total_targetsz += targetsz;
	}

	smb_dfs_encode_targets(mbc, referrals);

	return (NT_STATUS_SUCCESS);
}
示例#6
0
/*
 * samr_lookup_domain_names
 *
 * Lookup up the given name in the domain specified by domain_handle.
 * Upon a successful lookup the information is returned in the account
 * arg and caller must free allocated memories by calling smb_account_free().
 *
 * Returns NT status codes.
 */
uint32_t
samr_lookup_domain_names(mlsvc_handle_t *domain_handle, char *name,
    smb_account_t *account)
{
	struct samr_LookupNames	arg;
	int			opnum;
	uint32_t		status;
	size_t			length;

	if (ndr_is_null_handle(domain_handle) ||
	    name == NULL || account == NULL) {
		return (NT_STATUS_INVALID_PARAMETER);
	}

	bzero(account, sizeof (smb_account_t));
	opnum = SAMR_OPNUM_LookupNames;
	bzero(&arg, sizeof (struct samr_LookupNames));

	(void) memcpy(&arg.handle, &domain_handle->handle,
	    sizeof (samr_handle_t));
	arg.n_entry = 1;
	arg.max_n_entry = 1000;
	arg.index = 0;
	arg.total = 1;

	length = smb_wcequiv_strlen(name);
	if (ndr_rpc_server_os(domain_handle) == NATIVE_OS_WIN2000)
		length += sizeof (smb_wchar_t);

	arg.name.length = length;
	arg.name.allosize = length;
	arg.name.str = (unsigned char *)name;

	if (ndr_rpc_call(domain_handle, opnum, &arg) != 0) {
		status = NT_STATUS_INVALID_PARAMETER;
	} else if (arg.status != NT_STATUS_SUCCESS) {
		status = NT_SC_VALUE(arg.status);

		/*
		 * Handle none-mapped status quietly.
		 */
		if (status != NT_STATUS_NONE_MAPPED)
			ndr_rpc_status(domain_handle, opnum, arg.status);
	} else {
		account->a_type = arg.rid_types.rid_type[0];
		account->a_rid = arg.rids.rid[0];
		status = NT_STATUS_SUCCESS;
	}

	ndr_rpc_release(domain_handle);
	return (status);
}
示例#7
0
void
smb_rpc_off(char *dst, char *src, uint32_t *offset, uint32_t *outoffset)
{
	int nwchars;
	int bytes;

	bytes = smb_wcequiv_strlen(src) + 2;
	nwchars = strlen(src) + 1;
	*offset -= bytes;
	*outoffset = *offset;
	/*LINTED E_BAD_PTR_CAST_ALIGN*/
	(void) smb_mbstowcs(((smb_wchar_t *)(dst + *offset)), src, nwchars);
}
示例#8
0
/*
 * Make an ndr_mstring_t from a regular string.
 */
int
ndr_heap_mstring(ndr_heap_t *heap, const char *s, ndr_mstring_t *out)
{
	if (s == NULL || out == NULL)
		return (-1);

	out->length = smb_wcequiv_strlen(s);
	out->allosize = out->length + sizeof (smb_wchar_t);

	if ((out->str = ndr_heap_strdup(heap, s)) == NULL)
		return (-1);

	return (0);
}
示例#9
0
/*
 * FileFsAttributeInformation
 */
uint32_t
smb2_qfs_attr(smb_request_t *sr)
{
	smb_tree_t *tree = sr->tid_tree;
	char *fsname;
	uint32_t namelen;
	uint32_t FsAttr;

	/* This call is OK on all tree types. */
	switch (tree->t_res_type & STYPE_MASK) {
	case STYPE_IPC:
		fsname = "PIPE";
		break;
	case STYPE_DISKTREE:
		fsname = "NTFS"; /* A lie, but compatible... */
		break;
	case STYPE_PRINTQ:
	case STYPE_DEVICE:
	default: /* gcc -Wuninitialized */
		return (NT_STATUS_INVALID_PARAMETER);
	}
	namelen = smb_wcequiv_strlen(fsname);

	/*
	 * Todo: Store the FsAttributes in the tree object,
	 * then just return that directly here.
	 */
	FsAttr = FILE_CASE_PRESERVED_NAMES;
	if (tree->t_flags & SMB_TREE_UNICODE_ON_DISK)
		FsAttr |= FILE_UNICODE_ON_DISK;
	if (tree->t_flags & SMB_TREE_SUPPORTS_ACLS)
		FsAttr |= FILE_PERSISTENT_ACLS;
	if ((tree->t_flags & SMB_TREE_CASEINSENSITIVE) == 0)
		FsAttr |= FILE_CASE_SENSITIVE_SEARCH;
	if (tree->t_flags & SMB_TREE_STREAMS)
		FsAttr |= FILE_NAMED_STREAMS;
	if (tree->t_flags & SMB_TREE_QUOTA)
		FsAttr |= FILE_VOLUME_QUOTAS;
	if (tree->t_flags & SMB_TREE_SPARSE)
		FsAttr |= FILE_SUPPORTS_SPARSE_FILES;

	(void) smb_mbc_encodef(
	    &sr->raw_data, "lllU",
	    FsAttr,
	    MAXNAMELEN-1,
	    namelen,
	    fsname);

	return (0);
}
示例#10
0
static void
smb_dfs_encode_hdr(mbuf_chain_t *mbc, dfs_info_t *referrals)
{
	uint16_t path_consumed;
	uint32_t flags;

	path_consumed = smb_wcequiv_strlen(referrals->i_uncpath);
	flags = DFS_HDRFLG_S;
	if (referrals->i_type == DFS_OBJECT_ROOT)
		flags |= DFS_HDRFLG_R;

	/* Fill rep_param_mb in SMB1 caller. */
	(void) smb_mbc_encodef(mbc, "wwl", path_consumed,
	    referrals->i_ntargets, flags);
}
示例#11
0
static uint32_t
smb_dfs_encode_refv1(smb_request_t *sr, mbuf_chain_t *mbc,
	dfs_info_t *referrals)
{
	_NOTE(ARGUNUSED(sr))
	uint16_t entsize, rep_bufsize;
	uint16_t server_type;
	uint16_t flags = 0;
	uint16_t r;
	char *target;

	rep_bufsize = MBC_MAXBYTES(mbc);

	server_type = (referrals->i_type == DFS_OBJECT_ROOT) ?
	    DFS_SRVTYPE_ROOT : DFS_SRVTYPE_NONROOT;

	target = kmem_alloc(MAXPATHLEN, KM_SLEEP);

	for (r = 0; r < referrals->i_ntargets; r++) {
		(void) snprintf(target, MAXPATHLEN, "\\%s\\%s",
		    referrals->i_targets[r].t_server,
		    referrals->i_targets[r].t_share);

		entsize = DFS_REFV1_ENTSZ + smb_wcequiv_strlen(target) + 2;
		if (entsize > rep_bufsize)
			break;

		(void) smb_mbc_encodef(mbc, "wwwwU",
		    DFS_REFERRAL_V1, entsize, server_type, flags, target);
		rep_bufsize -= entsize;
	}

	kmem_free(target, MAXPATHLEN);

	/*
	 * Need room for at least one entry.
	 * Windows will silently drop targets that do not fit in
	 * the response buffer.
	 */
	if (r == 0) {
		return (NT_STATUS_BUFFER_OVERFLOW);
	}

	return (NT_STATUS_SUCCESS);
}
示例#12
0
/*
 * Our regular string marshalling always creates null terminated strings
 * but some Windows clients and servers are pedantic about the string
 * formats they will accept and require non-null terminated strings.
 * This function can be used to build a wide-char, non-null terminated
 * string in the heap as a varying/conformant array.  We need to do the
 * wide-char conversion here because the marshalling code won't be
 * aware that this is really a string.
 */
void
ndr_heap_mkvcs(ndr_heap_t *heap, char *s, ndr_vcstr_t *vc)
{
	int mlen;

	vc->wclen = smb_wcequiv_strlen(s);
	vc->wcsize = vc->wclen;

	mlen = sizeof (ndr_vcs_t) + vc->wcsize + sizeof (smb_wchar_t);

	vc->vcs = ndr_heap_malloc(heap, mlen);

	if (vc->vcs) {
		vc->vcs->vc_first_is = 0;
		vc->vcs->vc_length_is = vc->wclen / sizeof (smb_wchar_t);
		(void) smb_mbstowcs((smb_wchar_t *)vc->vcs->buffer, s,
		    vc->vcs->vc_length_is);
	}
}
示例#13
0
/*
 * lsar_lookup_priv_display_name
 *
 * Map a privilege name to a privilege display name. The input handle
 * should be an LSA policy handle and the name would normally be one
 * of the privileges defined in smb_privilege.h
 *
 * There's something peculiar about the return status from NT servers,
 * it's not always present. So for now, I'm ignoring the status in the
 * RPC response.
 *
 * Returns NT status codes.
 */
DWORD
lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *name,
    char *display_name, int display_len)
{
	struct mslsa_LookupPrivDisplayName	arg;
	int	opnum;
	size_t	length;
	DWORD	status;

	if (lsa_handle == NULL || name == NULL || display_name == NULL)
		return (NT_STATUS_INVALID_PARAMETER);

	opnum = LSARPC_OPNUM_LookupPrivDisplayName;

	bzero(&arg, sizeof (struct mslsa_LookupPrivDisplayName));
	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));

	length = smb_wcequiv_strlen(name);
	arg.name.length = length;
	arg.name.allosize = length;
	arg.name.str = (unsigned char *)name;

	arg.client_language = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
	arg.default_language = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);

	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0)
		status = NT_STATUS_INVALID_PARAMETER;
#if 0
	else if (arg.status != 0)
		status = NT_SC_VALUE(arg.status);
#endif
	else {
		(void) strlcpy(display_name,
		    (char const *)arg.display_name->str, display_len);
		status = NT_STATUS_SUCCESS;
	}

	ndr_rpc_release(lsa_handle);
	return (status);
}
示例#14
0
/*
 * FileAlternateNameInformation
 * See also:
 *	SMB_QUERY_FILE_ALT_NAME_INFO
 *	SMB_FILE_ALT_NAME_INFORMATION
 */
static uint32_t
smb2_qif_altname(smb_request_t *sr, smb_queryinfo_t *qi)
{
    smb_ofile_t *of = sr->fid_ofile;

    ASSERT(qi->qi_namelen > 0);
    ASSERT(qi->qi_attr.sa_mask & SMB_AT_NODEID);

    if (of->f_ftype != SMB_FTYPE_DISK)
        return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
    if ((of->f_tree->t_flags & SMB_TREE_SHORTNAMES) == 0)
        return (NT_STATUS_OBJECT_NAME_NOT_FOUND);

    /* fill in qi->qi_shortname */
    smb_query_shortname(of->f_node, qi);

    (void) smb_mbc_encodef(
        &sr->raw_data, "%lU", sr,
        smb_wcequiv_strlen(qi->qi_shortname),
        qi->qi_shortname);

    return (0);
}
示例#15
0
/*
 * lsar_lookup_priv_value
 *
 * Map a privilege name to a local unique id (LUID). Privilege names
 * are consistent across the network. LUIDs are machine specific.
 * This function provides the means to map a privilege name to the
 * LUID used by a remote server to represent it. The handle here is
 * a policy handle.
 */
int
lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name,
    struct ms_luid *luid)
{
	struct mslsa_LookupPrivValue	arg;
	int	opnum;
	int	rc;
	size_t	length;

	if (lsa_handle == NULL || name == NULL || luid == NULL)
		return (-1);

	opnum = LSARPC_OPNUM_LookupPrivValue;

	bzero(&arg, sizeof (struct mslsa_LookupPrivValue));
	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));

	length = smb_wcequiv_strlen(name);
	if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000)
		length += sizeof (smb_wchar_t);

	arg.name.length = length;
	arg.name.allosize = length;
	arg.name.str = (unsigned char *)name;

	rc = ndr_rpc_call(lsa_handle, opnum, &arg);
	if (rc == 0) {
		if (arg.status != 0)
			rc = -1;
		else
			(void) memcpy(luid, &arg.luid, sizeof (struct ms_luid));
	}

	ndr_rpc_release(lsa_handle);
	return (rc);
}
示例#16
0
/*
 * Lookup a name and obtain the sid/rid.
 * This is a wrapper for the various lookup sid RPCs.
 */
uint32_t
lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info)
{
	static lsar_nameop_t ops[] = {
		lsar_lookup_names3,
		lsar_lookup_names2,
		lsar_lookup_names1
	};

	const srvsvc_server_info_t	*svinfo;
	lsa_names_t	names;
	char		*p;
	uint32_t	length;
	uint32_t	status = NT_STATUS_INVALID_PARAMETER;
	int		n_op = (sizeof (ops) / sizeof (ops[0]));
	int		i;

	if (lsa_handle == NULL || name == NULL || info == NULL)
		return (NT_STATUS_INVALID_PARAMETER);

	bzero(info, sizeof (smb_account_t));

	svinfo = ndr_rpc_server_info(lsa_handle);
	if (svinfo->sv_os == NATIVE_OS_WIN2000 &&
	    svinfo->sv_version_major == 5 && svinfo->sv_version_minor == 0) {
		/*
		 * Windows 2000 doesn't like an LSA lookup for
		 * DOMAIN\Administrator.
		 */
		if ((p = strchr(name, '\\')) != 0) {
			++p;

			if (strcasecmp(p, "administrator") == 0)
				name = p;
		}

	}

	length = smb_wcequiv_strlen(name);
	names.name[0].length = length;
	names.name[0].allosize = length;
	names.name[0].str = (unsigned char *)name;
	names.n_entry = 1;

	if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) {
		for (i = 0; i < n_op; ++i) {
			ndr_rpc_set_nonull(lsa_handle);
			status = (*ops[i])(lsa_handle, &names, info);

			if (status != NT_STATUS_INVALID_PARAMETER)
				break;
		}
	} else {
		ndr_rpc_set_nonull(lsa_handle);
		status = lsar_lookup_names1(lsa_handle, &names, info);
	}

	if (status == NT_STATUS_SUCCESS) {
		info->a_name = lsar_get_username(name);

		if (!smb_account_validate(info)) {
			smb_account_free(info);
			status = NT_STATUS_NO_MEMORY;
		} else {
			smb_account_trace(info);
		}
	}

	return (status);
}
/*
 * smb_trans2_mbc_encode
 *
 * This function encodes the mbc for one directory entry.
 *
 * The function returns -1 when the max data requested by client
 * is reached. If the entry is valid and successful encoded, 0
 * will be returned; otherwise, 1 will be returned.
 *
 * We always null terminate the filename. The space for the null
 * is included in the maxdata calculation and is therefore included
 * in the next_entry_offset. namelen is the unterminated length of
 * the filename. For levels except STANDARD and EA_SIZE, if the
 * filename is ascii the name length returned to the client should
 * include the null terminator. Otherwise the length returned to
 * the client should not include the terminator.
 *
 * Returns: 0 - data successfully encoded
 *          1 - client request's maxdata limit reached
 *	   -1 - error
 */
static int
smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
    smb_fileinfo_t *fileinfo, smb_find_args_t *args)
{
	int		namelen, shortlen, buflen;
	uint32_t	next_entry_offset;
	uint32_t	dsize32, asize32;
	uint32_t	mb_flags = 0;
	char		buf83[26];
	char		*tmpbuf;
	smb_msgbuf_t	mb;

	namelen = smb_ascii_or_unicode_strlen(sr, fileinfo->fi_name);
	if (namelen == -1)
		return (-1);

	next_entry_offset = args->fa_maxdata + namelen;

	if (MBC_ROOM_FOR(&xa->rep_data_mb, (args->fa_maxdata + namelen)) == 0)
		return (1);

	/*
	 * If ascii the filename length returned to the client should
	 * include the null terminator for levels except STANDARD and
	 * EASIZE.
	 */
	if (!(sr->smb_flg2 & SMB_FLAGS2_UNICODE)) {
		if ((args->fa_infolev != SMB_INFO_STANDARD) &&
		    (args->fa_infolev != SMB_INFO_QUERY_EA_SIZE))
			namelen += 1;
	}

	mb_flags = (sr->smb_flg2 & SMB_FLAGS2_UNICODE) ? SMB_MSGBUF_UNICODE : 0;
	dsize32 = (fileinfo->fi_size > UINT_MAX) ?
	    UINT_MAX : (uint32_t)fileinfo->fi_size;
	asize32 = (fileinfo->fi_alloc_size > UINT_MAX) ?
	    UINT_MAX : (uint32_t)fileinfo->fi_alloc_size;

	switch (args->fa_infolev) {
	case SMB_INFO_STANDARD:
		if (args->fa_fflag & SMB_FIND_RETURN_RESUME_KEYS)
			(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
			    fileinfo->fi_cookie);

		(void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwbu", sr,
		    smb_time_gmt_to_local(sr, fileinfo->fi_crtime.tv_sec),
		    smb_time_gmt_to_local(sr, fileinfo->fi_atime.tv_sec),
		    smb_time_gmt_to_local(sr, fileinfo->fi_mtime.tv_sec),
		    dsize32,
		    asize32,
		    fileinfo->fi_dosattr,
		    namelen,
		    fileinfo->fi_name);
		break;

	case SMB_INFO_QUERY_EA_SIZE:
		if (args->fa_fflag & SMB_FIND_RETURN_RESUME_KEYS)
			(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
			    fileinfo->fi_cookie);

		/*
		 * Unicode filename should NOT be aligned. Encode ('u')
		 * into a temporary buffer, then encode buffer as a
		 * byte stream ('#c').
		 * Regardless of whether unicode or ascii, a single
		 * termination byte is used.
		 */
		buflen = namelen + sizeof (smb_wchar_t);
		tmpbuf = kmem_zalloc(buflen, KM_SLEEP);
		smb_msgbuf_init(&mb, (uint8_t *)tmpbuf, buflen, mb_flags);
		if (smb_msgbuf_encode(&mb, "u", fileinfo->fi_name) < 0) {
			smb_msgbuf_term(&mb);
			kmem_free(tmpbuf, buflen);
			return (-1);
		}
		tmpbuf[namelen] = '\0';

		(void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwlb#c", sr,
		    smb_time_gmt_to_local(sr, fileinfo->fi_crtime.tv_sec),
		    smb_time_gmt_to_local(sr, fileinfo->fi_atime.tv_sec),
		    smb_time_gmt_to_local(sr, fileinfo->fi_mtime.tv_sec),
		    dsize32,
		    asize32,
		    fileinfo->fi_dosattr,
		    0L,		/* EA Size */
		    namelen,
		    namelen + 1,
		    tmpbuf);

		smb_msgbuf_term(&mb);
		kmem_free(tmpbuf, buflen);
		break;

	case SMB_FIND_FILE_DIRECTORY_INFO:
		(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqllu", sr,
		    next_entry_offset,
		    fileinfo->fi_cookie,
		    &fileinfo->fi_crtime,
		    &fileinfo->fi_atime,
		    &fileinfo->fi_mtime,
		    &fileinfo->fi_ctime,
		    fileinfo->fi_size,
		    fileinfo->fi_alloc_size,
		    fileinfo->fi_dosattr,
		    namelen,
		    fileinfo->fi_name);
		break;

	case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
		(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlllu", sr,
		    next_entry_offset,
		    fileinfo->fi_cookie,
		    &fileinfo->fi_crtime,
		    &fileinfo->fi_atime,
		    &fileinfo->fi_mtime,
		    &fileinfo->fi_ctime,
		    fileinfo->fi_size,
		    fileinfo->fi_alloc_size,
		    fileinfo->fi_dosattr,
		    namelen,
		    0L,
		    fileinfo->fi_name);
		break;

	case SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO:
		(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlll4.qu", sr,
		    next_entry_offset,
		    fileinfo->fi_cookie,
		    &fileinfo->fi_crtime,
		    &fileinfo->fi_atime,
		    &fileinfo->fi_mtime,
		    &fileinfo->fi_ctime,
		    fileinfo->fi_size,
		    fileinfo->fi_alloc_size,
		    fileinfo->fi_dosattr,
		    namelen,
		    0L,
		    fileinfo->fi_nodeid,
		    fileinfo->fi_name);
		break;

	case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
		bzero(buf83, sizeof (buf83));
		smb_msgbuf_init(&mb, (uint8_t *)buf83, sizeof (buf83),
		    mb_flags);
		if (smb_msgbuf_encode(&mb, "U", fileinfo->fi_shortname) < 0) {
			smb_msgbuf_term(&mb);
			return (-1);
		}
		shortlen = smb_wcequiv_strlen(fileinfo->fi_shortname);

		(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlllb.24cu",
		    sr,
		    next_entry_offset,
		    fileinfo->fi_cookie,
		    &fileinfo->fi_crtime,
		    &fileinfo->fi_atime,
		    &fileinfo->fi_mtime,
		    &fileinfo->fi_ctime,
		    fileinfo->fi_size,
		    fileinfo->fi_alloc_size,
		    fileinfo->fi_dosattr,
		    namelen,
		    0L,
		    shortlen,
		    buf83,
		    fileinfo->fi_name);

		smb_msgbuf_term(&mb);
		break;

	case SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO:
		bzero(buf83, sizeof (buf83));
		smb_msgbuf_init(&mb, (uint8_t *)buf83, sizeof (buf83),
		    mb_flags);
		if (smb_msgbuf_encode(&mb, "u", fileinfo->fi_shortname) < 0) {
			smb_msgbuf_term(&mb);
			return (-1);
		}
		shortlen = smb_ascii_or_unicode_strlen(sr,
		    fileinfo->fi_shortname);

		(void) smb_mbc_encodef(&xa->rep_data_mb,
		    "%llTTTTqqlllb.24c2.qu",
		    sr,
		    next_entry_offset,
		    fileinfo->fi_cookie,
		    &fileinfo->fi_crtime,
		    &fileinfo->fi_atime,
		    &fileinfo->fi_mtime,
		    &fileinfo->fi_ctime,
		    fileinfo->fi_size,
		    fileinfo->fi_alloc_size,
		    fileinfo->fi_dosattr,
		    namelen,
		    0L,
		    shortlen,
		    buf83,
		    fileinfo->fi_nodeid,
		    fileinfo->fi_name);

		smb_msgbuf_term(&mb);
		break;

	case SMB_FIND_FILE_NAMES_INFO:
		(void) smb_mbc_encodef(&xa->rep_data_mb, "%lllu", sr,
		    next_entry_offset,
		    fileinfo->fi_cookie,
		    namelen,
		    fileinfo->fi_name);
		break;
	}

	return (0);
}
示例#18
0
/*
 * smb_query_encode_response
 *
 * Encode the data from smb_queryinfo_t into client response
 */
int
smb_query_encode_response(smb_request_t *sr, smb_xa_t *xa,
    uint16_t infolev, smb_queryinfo_t *qinfo)
{
	uint16_t dattr;
	u_offset_t datasz, allocsz;
	uint32_t isdir;

	dattr = qinfo->qi_attr.sa_dosattr & FILE_ATTRIBUTE_MASK;
	datasz = qinfo->qi_attr.sa_vattr.va_size;
	allocsz = qinfo->qi_attr.sa_allocsz;
	isdir = ((dattr & FILE_ATTRIBUTE_DIRECTORY) != 0);

	switch (infolev) {
	case SMB_QUERY_INFORMATION:
		(void) smbsr_encode_result(sr, 10, 0, "bwll10.w",
		    10,
		    dattr,
		    smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
		    smb_size32(datasz),
		    0);
		break;

	case SMB_QUERY_INFORMATION2:
		(void) smbsr_encode_result(sr, 11, 0, "byyyllww",
		    11,
		    smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
		    smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
		    smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
		    smb_size32(datasz), smb_size32(allocsz), dattr, 0);
	break;

	case SMB_FILE_ACCESS_INFORMATION:
		ASSERT(sr->fid_ofile);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
		    sr->fid_ofile->f_granted_access);
		break;

	case SMB_INFO_STANDARD:
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb,
		    ((sr->session->native_os == NATIVE_OS_WIN95) ?
		    "YYYllw" : "yyyllw"),
		    smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
		    smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
		    smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
		    smb_size32(datasz), smb_size32(allocsz), dattr);
		break;

	case SMB_INFO_QUERY_EA_SIZE:
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb,
		    ((sr->session->native_os == NATIVE_OS_WIN95) ?
		    "YYYllwl" : "yyyllwl"),
		    smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
		    smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
		    smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
		    smb_size32(datasz), smb_size32(allocsz), dattr, 0);
		break;

	case SMB_INFO_QUERY_ALL_EAS:
	case SMB_INFO_QUERY_EAS_FROM_LIST:
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
		break;

	case SMB_INFO_IS_NAME_VALID:
		break;

	case SMB_QUERY_FILE_BASIC_INFO:
	case SMB_FILE_BASIC_INFORMATION:
		/*
		 * NT includes 6 bytes (spec says 4) at the end of this
		 * response, which are required by NetBench 5.01.
		 */
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.",
		    &qinfo->qi_crtime,
		    &qinfo->qi_atime,
		    &qinfo->qi_mtime,
		    &qinfo->qi_ctime,
		    dattr);
		break;

	case SMB_QUERY_FILE_STANDARD_INFO:
	case SMB_FILE_STANDARD_INFORMATION:
		/* 2-byte pad at end */
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "qqlbb2.",
		    (uint64_t)allocsz,
		    (uint64_t)datasz,
		    qinfo->qi_attr.sa_vattr.va_nlink,
		    qinfo->qi_delete_on_close,
		    (uint8_t)isdir);
		break;

	case SMB_QUERY_FILE_EA_INFO:
	case SMB_FILE_EA_INFORMATION:
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
		break;

	case SMB_QUERY_FILE_NAME_INFO:
	case SMB_FILE_NAME_INFORMATION:
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "%lu", sr,
		    qinfo->qi_namelen, qinfo->qi_name);
		break;

	case SMB_QUERY_FILE_ALL_INFO:
	case SMB_FILE_ALL_INFORMATION:
		/*
		 * There is a 6-byte pad between Attributes and AllocationSize,
		 * and a 2-byte pad after the Directory field.
		 */
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.qqlbb2.l",
		    &qinfo->qi_crtime,
		    &qinfo->qi_atime,
		    &qinfo->qi_mtime,
		    &qinfo->qi_ctime,
		    dattr,
		    (uint64_t)allocsz,
		    (uint64_t)datasz,
		    qinfo->qi_attr.sa_vattr.va_nlink,
		    qinfo->qi_delete_on_close,
		    isdir,
		    0);

		(void) smb_mbc_encodef(&xa->rep_data_mb, "%lu",
		    sr, qinfo->qi_namelen, qinfo->qi_name);
		break;

	case SMB_QUERY_FILE_ALT_NAME_INFO:
	case SMB_FILE_ALT_NAME_INFORMATION:
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "%lU", sr,
		    smb_wcequiv_strlen(qinfo->qi_shortname),
		    qinfo->qi_shortname);
		break;

	case SMB_QUERY_FILE_STREAM_INFO:
	case SMB_FILE_STREAM_INFORMATION:
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		smb_encode_stream_info(sr, xa, qinfo);
		break;

	case SMB_QUERY_FILE_COMPRESSION_INFO:
	case SMB_FILE_COMPRESSION_INFORMATION:
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "qwbbb3.",
		    datasz, 0, 0, 0, 0);
		break;

	case SMB_FILE_INTERNAL_INFORMATION:
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "q",
		    qinfo->qi_attr.sa_vattr.va_nodeid);
		break;

	case SMB_FILE_NETWORK_OPEN_INFORMATION:
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTqql4.",
		    &qinfo->qi_crtime,
		    &qinfo->qi_atime,
		    &qinfo->qi_mtime,
		    &qinfo->qi_ctime,
		    (uint64_t)allocsz,
		    (uint64_t)datasz,
		    (uint32_t)dattr);
		break;

	case SMB_FILE_ATTR_TAG_INFORMATION:
		/*
		 * If dattr includes FILE_ATTRIBUTE_REPARSE_POINT, the
		 * second dword should be the reparse tag.  Otherwise
		 * the tag value should be set to zero.
		 * We don't support reparse points, so we set the tag
		 * to zero.
		 */
		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
		(void) smb_mbc_encodef(&xa->rep_data_mb, "ll",
		    (uint32_t)dattr, 0);
		break;

	default:
		if ((infolev > 1000) && smb_query_passthru)
			smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
			    ERRDOS, ERROR_NOT_SUPPORTED);
		else
			smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL);
		return (-1);
	}

	return (0);
}
示例#19
0
smb_sdrc_t
smb_com_negotiate(smb_request_t *sr)
{
	smb_session_t 		*session = sr->session;
	smb_arg_negotiate_t	*negprot = sr->sr_negprot;
	uint16_t		secmode;
	uint32_t		sesskey;
	char			*nbdomain;
	uint8_t			*wcbuf;
	int			wclen;
	smb_msgbuf_t		mb;
	int			rc;

	if (session->s_state != SMB_SESSION_STATE_ESTABLISHED) {
		/* The protocol has already been negotiated. */
		smbsr_error(sr, 0, ERRSRV, ERRerror);
		return (SDRC_ERROR);
	}

	/*
	 * Special case for negotiating SMB2 from SMB1.  The client
	 * includes the  "SMB 2..." dialects in the SMB1 negotiate,
	 * and if SMB2 is enabled, we choose one of those and then
	 * send an SMB2 reply to that SMB1 request.  Yes, it's very
	 * strange, but this SMB1 request can have an SMB2 reply!
	 * To accomplish this, we let the SMB2 code send the reply
	 * and return the special code SDRC_NO_REPLY to the SMB1
	 * dispatch logic so it will NOT send an SMB1 reply.
	 * (Or possibly send an SMB1 error reply.)
	 */
	if (negprot->ni_dialect >= DIALECT_SMB2002) {
		rc = smb1_negotiate_smb2(sr);
		ASSERT(rc == SDRC_NO_REPLY ||
		    rc == SDRC_DROP_VC || rc == SDRC_ERROR);
		return (rc);
	}

	session->secmode = NEGOTIATE_ENCRYPT_PASSWORDS |
	    NEGOTIATE_USER_SECURITY;
	secmode = session->secmode;
	sesskey = session->sesskey;

	negprot->ni_servertime.tv_sec = gethrestime_sec();
	negprot->ni_servertime.tv_nsec = 0;
	negprot->ni_tzcorrection = sr->sr_gmtoff / 60;
	negprot->ni_maxmpxcount = sr->sr_cfg->skc_maxworkers;
	negprot->ni_keylen = SMB_CHALLENGE_SZ;
	bcopy(&session->challenge_key, negprot->ni_key, SMB_CHALLENGE_SZ);
	nbdomain = sr->sr_cfg->skc_nbdomain;

	/*
	 * UNICODE support is required for long share names,
	 * long file names and streams.  Note: CAP_RAW_MODE
	 * is not supported because it does nothing to help
	 * modern clients and causes nasty complications.
	 */
	negprot->ni_capabilities = CAP_LARGE_FILES
	    | CAP_UNICODE
	    | CAP_NT_SMBS
	    | CAP_STATUS32
	    | CAP_NT_FIND
	    | CAP_LEVEL_II_OPLOCKS
	    | CAP_LOCK_AND_READ
	    | CAP_RPC_REMOTE_APIS
	    | CAP_LARGE_READX
	    | CAP_LARGE_WRITEX
	    | CAP_DFS;

	if (smb_cap_passthru)
		negprot->ni_capabilities |= CAP_INFOLEVEL_PASSTHRU;
	else
		cmn_err(CE_NOTE, "smbsrv: cap passthru is %s",
		    (negprot->ni_capabilities & CAP_INFOLEVEL_PASSTHRU) ?
		    "enabled" : "disabled");

	switch (negprot->ni_dialect) {
	case PC_NETWORK_PROGRAM_1_0:	/* core */
		(void) ksocket_setsockopt(session->sock, SOL_SOCKET,
		    SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
		    sizeof (smb_dos_tcp_rcvbuf), CRED());
		rc = smbsr_encode_result(sr, 1, 0, "bww", 1,
		    negprot->ni_index, 0);
		break;

	case Windows_for_Workgroups_3_1a:
	case PCLAN1_0:
	case MICROSOFT_NETWORKS_1_03:
	case MICROSOFT_NETWORKS_3_0:
	case LANMAN1_0:
	case LM1_2X002:
	case DOS_LM1_2X002:
		(void) ksocket_setsockopt(session->sock, SOL_SOCKET,
		    SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
		    sizeof (smb_dos_tcp_rcvbuf), CRED());
		sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK;
		rc = smbsr_encode_result(sr, 13, VAR_BCC,
		    "bwwwwwwlYww2.w#c",
		    13,				/* wct */
		    negprot->ni_index,		/* dialect index */
		    secmode,			/* security mode */
		    SMB_DOS_MAXBUF,		/* max buffer size */
		    1,				/* max MPX */
		    1,				/* max VCs */
		    0,				/* read/write raw */
		    sesskey,			/* session key */
		    negprot->ni_servertime.tv_sec, /* server date/time */
		    negprot->ni_tzcorrection,
		    (uint16_t)negprot->ni_keylen, /* encryption key length */
						/* reserved field handled 2. */
		    VAR_BCC,
		    (int)negprot->ni_keylen,
		    negprot->ni_key);		/* encryption key */
		break;

	case DOS_LANMAN2_1:
	case LANMAN2_1:
		(void) ksocket_setsockopt(session->sock, SOL_SOCKET,
		    SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
		    sizeof (smb_dos_tcp_rcvbuf), CRED());
		sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK;
		rc = smbsr_encode_result(sr, 13, VAR_BCC,
		    "bwwwwwwlYww2.w#cs",
		    13,				/* wct */
		    negprot->ni_index,		/* dialect index */
		    secmode,			/* security mode */
		    SMB_DOS_MAXBUF,		/* max buffer size */
		    1,				/* max MPX */
		    1,				/* max VCs */
		    0,				/* read/write raw */
		    sesskey,			/* session key */
		    negprot->ni_servertime.tv_sec, /* server date/time */
		    negprot->ni_tzcorrection,
		    (uint16_t)negprot->ni_keylen, /* encryption key length */
						/* reserved field handled 2. */
		    VAR_BCC,
		    (int)negprot->ni_keylen,
		    negprot->ni_key,		/* encryption key */
		    nbdomain);
		break;

	case NT_LM_0_12:
		(void) ksocket_setsockopt(session->sock, SOL_SOCKET,
		    SO_RCVBUF, (const void *)&smb_nt_tcp_rcvbuf,
		    sizeof (smb_nt_tcp_rcvbuf), CRED());

		/*
		 * Allow SMB signatures if using encrypted passwords
		 */
		if ((secmode & NEGOTIATE_ENCRYPT_PASSWORDS) &&
		    sr->sr_cfg->skc_signing_enable) {
			secmode |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
			if (sr->sr_cfg->skc_signing_required)
				secmode |=
				    NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;

			session->secmode = secmode;
		}

		/*
		 * Does the client want Extended Security?
		 * (and if we have it enabled)
		 * If so, handle as if a different dialect.
		 */
		if ((sr->smb_flg2 & SMB_FLAGS2_EXT_SEC) && smb_cap_ext_sec)
			goto NT_LM_0_12_ext_sec;
		sr->smb_flg2 &= ~SMB_FLAGS2_EXT_SEC;

		/*
		 * nbdomain is not expected to be aligned.
		 * Use temporary buffer to avoid alignment padding
		 */
		wclen = smb_wcequiv_strlen(nbdomain) + sizeof (smb_wchar_t);
		wcbuf = smb_srm_zalloc(sr, wclen);
		smb_msgbuf_init(&mb, wcbuf, wclen, SMB_MSGBUF_UNICODE);
		if (smb_msgbuf_encode(&mb, "U", nbdomain) < 0) {
			smb_msgbuf_term(&mb);
			smbsr_error(sr, 0, ERRSRV, ERRerror);
			return (SDRC_ERROR);
		}

		rc = smbsr_encode_result(sr, 17, VAR_BCC,
		    "bwbwwllllTwbw#c#c",
		    17,				/* wct */
		    negprot->ni_index,		/* dialect index */
		    secmode,			/* security mode */
		    negprot->ni_maxmpxcount,	/* max MPX */
		    1,				/* max VCs */
		    (DWORD)smb_maxbufsize,	/* max buffer size */
		    0xFFFF,			/* max raw size */
		    sesskey,			/* session key */
		    negprot->ni_capabilities,
		    &negprot->ni_servertime,	/* system time */
		    negprot->ni_tzcorrection,
		    negprot->ni_keylen,		/* encryption key length */
		    VAR_BCC,
		    (int)negprot->ni_keylen,
		    negprot->ni_key,		/* encryption key */
		    wclen,
		    wcbuf);			/* nbdomain (unicode) */

		smb_msgbuf_term(&mb);
		break;

NT_LM_0_12_ext_sec:
		/*
		 * This is the "Extended Security" variant of
		 * dialect NT_LM_0_12.
		 */
		negprot->ni_capabilities |= CAP_EXTENDED_SECURITY;

		rc = smbsr_encode_result(sr, 17, VAR_BCC,
		    "bwbwwllllTwbw#c#c",
		    17,				/* wct */
		    negprot->ni_index,		/* dialect index */
		    secmode,			/* security mode */
		    negprot->ni_maxmpxcount,	/* max MPX */
		    1,				/* max VCs */
		    (DWORD)smb_maxbufsize,	/* max buffer size */
		    0xFFFF,			/* max raw size */
		    sesskey,			/* session key */
		    negprot->ni_capabilities,
		    &negprot->ni_servertime,	/* system time */
		    negprot->ni_tzcorrection,
		    0,		/* encryption key length (MBZ) */
		    VAR_BCC,
		    UUID_LEN,
		    sr->sr_cfg->skc_machine_uuid,
		    sr->sr_cfg->skc_negtok_len,
		    sr->sr_cfg->skc_negtok);
		break;


	default:
		rc = smbsr_encode_result(sr, 1, 0, "bww", 1, -1, 0);
		break;
	}

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

	/*
	 * Save the agreed dialect. Note that the state is also
	 * used to detect and reject attempts to re-negotiate.
	 */
	session->dialect = negprot->ni_dialect;
	session->s_state = SMB_SESSION_STATE_NEGOTIATED;

	/* Allow normal SMB1 requests now. */
	session->newrq_func = smb1sr_newrq;

	return (SDRC_SUCCESS);
}
示例#20
0
/*
 * smb_trans2_mbc_encode
 *
 * This function encodes the mbc for one directory entry.
 *
 * The function returns -1 when the max data requested by client
 * is reached. If the entry is valid and successful encoded, 0
 * will be returned; otherwise, 1 will be returned.
 *
 * We always null terminate the filename. The space for the null
 * is included in the maxdata calculation and is therefore included
 * in the next_entry_offset. namelen is the unterminated length of
 * the filename. For levels except STANDARD and EA_SIZE, if the
 * filename is ascii the name length returned to the client should
 * include the null terminator. Otherwise the length returned to
 * the client should not include the terminator.
 *
 * Returns: 0 - data successfully encoded
 *          1 - client request's maxdata limit reached
 *	   -1 - error
 */
static int
smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
    smb_fileinfo_t *fileinfo, smb_find_args_t *args)
{
	int		namelen, shortlen;
	uint32_t	next_entry_offset;
	uint32_t	dsize32, asize32;
	uint32_t	mb_flags = 0;
	uint32_t	resume_key;
	char		buf83[26];
	smb_msgbuf_t	mb;

	namelen = smb_ascii_or_unicode_strlen(sr, fileinfo->fi_name);
	if (namelen == -1)
		return (-1);

	/*
	 * If ascii the filename length returned to the client should
	 * include the null terminator for levels except STANDARD and
	 * EASIZE.
	 */
	if (!(sr->smb_flg2 & SMB_FLAGS2_UNICODE)) {
		if ((args->fa_infolev != SMB_INFO_STANDARD) &&
		    (args->fa_infolev != SMB_INFO_QUERY_EA_SIZE))
			namelen += 1;
	}

	next_entry_offset = args->fa_maxdata + namelen;

	if (MBC_ROOM_FOR(&xa->rep_data_mb, (args->fa_maxdata + namelen)) == 0)
		return (1);

	mb_flags = (sr->smb_flg2 & SMB_FLAGS2_UNICODE) ? SMB_MSGBUF_UNICODE : 0;
	dsize32 = (fileinfo->fi_size > UINT_MAX) ?
	    UINT_MAX : (uint32_t)fileinfo->fi_size;
	asize32 = (fileinfo->fi_alloc_size > UINT_MAX) ?
	    UINT_MAX : (uint32_t)fileinfo->fi_alloc_size;

	resume_key = fileinfo->fi_cookie;
	if (smbd_use_resume_keys == 0)
		resume_key = 0;

	/*
	 * This switch handles all the "information levels" (formats)
	 * that we support.  Note that all formats have the file name
	 * placed after some fixed-size data, and the code to write
	 * the file name is factored out at the end of this switch.
	 */
	switch (args->fa_infolev) {
	case SMB_INFO_STANDARD:
		if (args->fa_fflag & SMB_FIND_RETURN_RESUME_KEYS)
			(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
			    resume_key);

		(void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwb", sr,
		    smb_time_gmt_to_local(sr, fileinfo->fi_crtime.tv_sec),
		    smb_time_gmt_to_local(sr, fileinfo->fi_atime.tv_sec),
		    smb_time_gmt_to_local(sr, fileinfo->fi_mtime.tv_sec),
		    dsize32,
		    asize32,
		    fileinfo->fi_dosattr,
		    namelen);
		break;

	case SMB_INFO_QUERY_EA_SIZE:
		if (args->fa_fflag & SMB_FIND_RETURN_RESUME_KEYS)
			(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
			    resume_key);

		(void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwlb", sr,
		    smb_time_gmt_to_local(sr, fileinfo->fi_crtime.tv_sec),
		    smb_time_gmt_to_local(sr, fileinfo->fi_atime.tv_sec),
		    smb_time_gmt_to_local(sr, fileinfo->fi_mtime.tv_sec),
		    dsize32,
		    asize32,
		    fileinfo->fi_dosattr,
		    0L,		/* EA Size */
		    namelen);
		break;

	case SMB_FIND_FILE_DIRECTORY_INFO:
		(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqll", sr,
		    next_entry_offset,
		    resume_key,
		    &fileinfo->fi_crtime,
		    &fileinfo->fi_atime,
		    &fileinfo->fi_mtime,
		    &fileinfo->fi_ctime,
		    fileinfo->fi_size,
		    fileinfo->fi_alloc_size,
		    fileinfo->fi_dosattr,
		    namelen);
		break;

	case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
		(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlll", sr,
		    next_entry_offset,
		    resume_key,
		    &fileinfo->fi_crtime,
		    &fileinfo->fi_atime,
		    &fileinfo->fi_mtime,
		    &fileinfo->fi_ctime,
		    fileinfo->fi_size,
		    fileinfo->fi_alloc_size,
		    fileinfo->fi_dosattr,
		    namelen,
		    0L);
		break;

	case SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO:
		(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlll4.q", sr,
		    next_entry_offset,
		    resume_key,
		    &fileinfo->fi_crtime,
		    &fileinfo->fi_atime,
		    &fileinfo->fi_mtime,
		    &fileinfo->fi_ctime,
		    fileinfo->fi_size,
		    fileinfo->fi_alloc_size,
		    fileinfo->fi_dosattr,
		    namelen,
		    0L,
		    fileinfo->fi_nodeid);
		break;

	case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
		bzero(buf83, sizeof (buf83));
		smb_msgbuf_init(&mb, (uint8_t *)buf83, sizeof (buf83),
		    mb_flags);
		if (smb_msgbuf_encode(&mb, "U", fileinfo->fi_shortname) < 0) {
			smb_msgbuf_term(&mb);
			return (-1);
		}
		shortlen = smb_wcequiv_strlen(fileinfo->fi_shortname);

		(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlllb.24c",
		    sr,
		    next_entry_offset,
		    resume_key,
		    &fileinfo->fi_crtime,
		    &fileinfo->fi_atime,
		    &fileinfo->fi_mtime,
		    &fileinfo->fi_ctime,
		    fileinfo->fi_size,
		    fileinfo->fi_alloc_size,
		    fileinfo->fi_dosattr,
		    namelen,
		    0L,
		    shortlen,
		    buf83);

		smb_msgbuf_term(&mb);
		break;

	case SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO:
		bzero(buf83, sizeof (buf83));
		smb_msgbuf_init(&mb, (uint8_t *)buf83, sizeof (buf83),
		    mb_flags);
		if (smb_msgbuf_encode(&mb, "u", fileinfo->fi_shortname) < 0) {
			smb_msgbuf_term(&mb);
			return (-1);
		}
		shortlen = smb_ascii_or_unicode_strlen(sr,
		    fileinfo->fi_shortname);

		(void) smb_mbc_encodef(&xa->rep_data_mb,
		    "%llTTTTqqlllb.24c2.q",
		    sr,
		    next_entry_offset,
		    resume_key,
		    &fileinfo->fi_crtime,
		    &fileinfo->fi_atime,
		    &fileinfo->fi_mtime,
		    &fileinfo->fi_ctime,
		    fileinfo->fi_size,
		    fileinfo->fi_alloc_size,
		    fileinfo->fi_dosattr,
		    namelen,
		    0L,
		    shortlen,
		    buf83,
		    fileinfo->fi_nodeid);

		smb_msgbuf_term(&mb);
		break;

	case SMB_FIND_FILE_NAMES_INFO:
		(void) smb_mbc_encodef(&xa->rep_data_mb, "%lll", sr,
		    next_entry_offset,
		    resume_key,
		    namelen);
		break;

	default:
		/* invalid info. level */
		return (-1);
	}

	/*
	 * At this point we have written all the fixed-size data
	 * for the specified info. level, and we're about to put
	 * the file name string in the message.  We may later
	 * need the offset in the trans2 data where this string
	 * is placed, so save the message position now.  Note:
	 * We also need to account for the alignment padding
	 * that may precede the unicode string.
	 */
	args->fa_lno = xa->rep_data_mb.chain_offset;
	if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0 &&
	    (args->fa_lno & 1) != 0)
		args->fa_lno++;

	(void) smb_mbc_encodef(&xa->rep_data_mb, "%u", sr,
	    fileinfo->fi_name);

	return (0);
}
示例#21
0
/*
 * GetPrinterData is used t obtain values from the registry for a
 * printer or a print server.  See [MS-RPRN] for value descriptions.
 * The registry returns ERROR_FILE_NOT_FOUND for unknown keys.
 */
static int
spoolss_s_GetPrinterData(void *arg, ndr_xa_t *mxa)
{
	static spoolss_winreg_t	reg[] = {
		{ "ChangeId",			0x0050acf2 },
		{ "W3SvcInstalled",		0x00000000 },
		{ "BeepEnabled",		0x00000000 },
		{ "EventLog",			0x0000001f },
		{ "NetPopup",			0x00000000 },
		{ "NetPopupToComputer",		0x00000000 },
		{ "MajorVersion",		0x00000003 },
		{ "MinorVersion",		0x00000000 },
		{ "DsPresent",			0x00000000 }
	};

	struct spoolss_GetPrinterData *param = arg;
	char			*name = (char *)param->pValueName;
	char			buf[MAXPATHLEN];
	static uint8_t		reserved_buf[4];
	spoolss_winreg_t	*rp;
	smb_share_t		si;
	smb_version_t		*osversion;
	struct utsname		sysname;
	smb_wchar_t		*wcs;
	uint32_t		value;
	uint32_t		status;
	int			wcslen;
	int			i;

	if (name == NULL || *name == '\0') {
		status = ERROR_FILE_NOT_FOUND;
		goto report_error;
	}

	for (i = 0; i < sizeof (reg) / sizeof (reg[0]); ++i) {
		param->pType = WINREG_DWORD;
		param->Needed = sizeof (uint32_t);
		rp = &reg[i];

		if (strcasecmp(name, rp->name) != 0)
			continue;

		if (param->Size < sizeof (uint32_t)) {
			param->Size = 0;
			goto need_more_data;
		}

		if ((param->Buf = NDR_NEW(mxa, uint32_t)) == NULL) {
			status = ERROR_NOT_ENOUGH_MEMORY;
			goto report_error;
		}

		value = rp->value;

		if ((strcasecmp(name, "DsPresent") == 0) &&
		    (smb_config_get_secmode() == SMB_SECMODE_DOMAIN))
			value = 0x00000001;

		bcopy(&value, param->Buf, sizeof (uint32_t));
		param->Size = sizeof (uint32_t);
		param->status = ERROR_SUCCESS;
		return (NDR_DRC_OK);
	}

	if (strcasecmp(name, "OSVersion") == 0) {
		param->pType = WINREG_BINARY;
		param->Needed = sizeof (smb_version_t);

		if (param->Size < sizeof (smb_version_t)) {
			param->Size = sizeof (smb_version_t);
			goto need_more_data;
		}

		if ((osversion = NDR_NEW(mxa, smb_version_t)) == NULL) {
			status = ERROR_NOT_ENOUGH_MEMORY;
			goto report_error;
		}

		smb_config_get_version(osversion);
		param->Buf = (uint8_t *)osversion;
		param->status = ERROR_SUCCESS;
		return (NDR_DRC_OK);
	}

	if (strcasecmp(name, "DNSMachineName") == 0) {
		param->pType = WINREG_SZ;
		buf[0] = '\0';
		(void) smb_getfqhostname(buf, MAXHOSTNAMELEN);
		goto encode_string;
	}

	if (strcasecmp(name, "DefaultSpoolDirectory") == 0) {
		param->pType = WINREG_SZ;
		buf[0] = '\0';

		if (smb_shr_get(SMB_SHARE_PRINT, &si) != NERR_Success) {
			status = ERROR_FILE_NOT_FOUND;
			goto report_error;
		}

		(void) snprintf(buf, MAXPATHLEN, "C:/%s", si.shr_path);
		(void) strcanon(buf, "/\\");
		(void) strsubst(buf, '/', '\\');
		goto encode_string;
	}

	if (strcasecmp(name, "Architecture") == 0) {
		param->pType = WINREG_SZ;

		if (uname(&sysname) < 0)
			(void) strlcpy(buf, "Solaris", MAXPATHLEN);
		else
			(void) snprintf(buf, MAXPATHLEN, "%s %s",
			    sysname.sysname, sysname.machine);

		goto encode_string;
	}

	status = ERROR_FILE_NOT_FOUND;

report_error:
	bzero(param, sizeof (struct spoolss_GetPrinterData));
	param->Buf = reserved_buf;
	param->status = status;
	return (NDR_DRC_OK);

encode_string:
	wcslen = smb_wcequiv_strlen(buf) + sizeof (smb_wchar_t);
	if (param->Size < wcslen) {
		param->Needed = wcslen;
		goto need_more_data;
	}

	if ((wcs = NDR_MALLOC(mxa, wcslen)) == NULL) {
		status = ERROR_NOT_ENOUGH_MEMORY;
		goto report_error;
	}

	(void) ndr_mbstowcs(NULL, wcs, buf, wcslen);
	param->Buf = (uint8_t *)wcs;
	param->Needed = wcslen;
	param->status = ERROR_SUCCESS;
	return (NDR_DRC_OK);

need_more_data:
	param->Size = 0;
	param->Buf = reserved_buf;
	param->status = ERROR_MORE_DATA;
	return (NDR_DRC_OK);
}