예제 #1
0
/*
 * smb_pathname_preprocess
 *
 * Perform common pre-processing of pn->pn_path:
 * - if the pn_path is blank, set it to '\\'
 * - perform unicode wildcard converstion.
 * - convert any '/' to '\\'
 * - eliminate duplicate slashes
 * - remove trailing slashes
 * - quota directory specific pre-processing
 */
static void
smb_pathname_preprocess(smb_request_t *sr, smb_pathname_t *pn)
{
	char *p;

	/* treat empty path as "\\" */
	if (strlen(pn->pn_path) == 0) {
		pn->pn_path = smb_pathname_strdup(sr, "\\");
		return;
	}

	if (sr->session->dialect < NT_LM_0_12)
		smb_convert_wildcards(pn->pn_path);

	/* treat '/' as '\\' */
	(void) strsubst(pn->pn_path, '/', '\\');

	(void) strcanon(pn->pn_path, "\\");

	/* remove trailing '\\' */
	p = pn->pn_path + strlen(pn->pn_path) - 1;
	if ((p != pn->pn_path) && (*p == '\\'))
		*p = '\0';

	smb_pathname_preprocess_quota(sr, pn);
	smb_pathname_preprocess_adminshare(sr, pn);
}
예제 #2
0
/*
 * Lookup the given account and returns the account information
 * in the passed smb_account_t structure.
 *
 * The lookup is performed in the following order:
 *    well known accounts
 *    local accounts
 *    domain accounts
 *
 * If it's established the given account is well know or local
 * but the lookup fails for some reason, the next step(s) won't be
 * performed.
 *
 * If the name is a domain account, it may refer to a user, group or
 * alias. If it is a local account, its type should be specified
 * in the sid_type parameter. In case the account type is unknown
 * sid_type should be set to SidTypeUnknown.
 *
 * account argument could be either [domain\]name or [domain/]name.
 *
 * Return status:
 *
 *   NT_STATUS_SUCCESS		Account is successfully translated
 *   NT_STATUS_NONE_MAPPED	Couldn't translate the account
 */
uint32_t
lsa_lookup_name(char *account, uint16_t type, smb_account_t *info)
{
	char nambuf[SMB_USERNAME_MAXLEN];
	char dombuf[SMB_PI_MAX_DOMAIN];
	char *name, *domain;
	uint32_t status;
	char *slash;

	(void) strsubst(account, '/', '\\');
	(void) strcanon(account, "\\");
	/* \john -> john */
	account += strspn(account, "\\");

	if ((slash = strchr(account, '\\')) != NULL) {
		*slash = '\0';
		(void) strlcpy(dombuf, account, sizeof (dombuf));
		(void) strlcpy(nambuf, slash + 1, sizeof (nambuf));
		*slash = '\\';
		name = nambuf;
		domain = dombuf;
	} else {
		name = account;
		domain = NULL;
	}

	status = lsa_lookup_name_builtin(domain, name, info);
	if (status == NT_STATUS_NOT_FOUND) {
		status = smb_sam_lookup_name(domain, name, type, info);
		if (status == NT_STATUS_SUCCESS)
			return (status);

		if ((domain == NULL) || (status == NT_STATUS_NOT_FOUND))
			status = lsa_lookup_name_domain(account, info);
	}

	return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED);
}
예제 #3
0
파일: smb_nic.c 프로젝트: bahamas10/openzfs
/*
 * smb_nic_nbt_get_exclude_list
 *
 * Construct an array containing list of i/f names on which NetBIOS traffic is
 * to be disabled, from a string containing a list of comma separated i/f names.
 *
 * Returns the number of i/f on which NetBIOS traffic is to be disabled.
 */
static int
smb_nic_nbt_get_exclude_list(char *excludestr, char **iflist, int max_nifs)
{
	int n = 0;
	char *entry;

	bzero(iflist, SMB_PI_MAX_NETWORKS * sizeof (char *));

	(void) trim_whitespace(excludestr);
	(void) strcanon(excludestr, ",");

	if (*excludestr == '\0')
		return (0);

	while (((iflist[n] = strsep(&excludestr, ",")) != NULL) &&
	    (n < max_nifs)) {
		entry = iflist[n];
		if (*entry == '\0')
			continue;
		n++;
	}

	return (n);
}
예제 #4
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);
}
예제 #5
0
int
smb_pathname_reduce(
    smb_request_t	*sr,
    cred_t		*cred,
    const char		*path,
    smb_node_t		*share_root_node,
    smb_node_t		*cur_node,
    smb_node_t		**dir_node,
    char		*last_component)
{
	smb_node_t	*root_node;
	pathname_t	ppn;
	char		*usepath;
	int		lookup_flags = FOLLOW;
	int 		trailing_slash = 0;
	int		err = 0;
	int		len;
	smb_node_t	*vss_cur_node;
	smb_node_t	*vss_root_node;
	smb_node_t	*local_cur_node;
	smb_node_t	*local_root_node;

	ASSERT(dir_node);
	ASSERT(last_component);

	*dir_node = NULL;
	*last_component = '\0';
	vss_cur_node = NULL;
	vss_root_node = NULL;

	if (sr && sr->tid_tree) {
		if (STYPE_ISIPC(sr->tid_tree->t_res_type))
			return (EACCES);
	}

	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
		lookup_flags |= FIGNORECASE;

	if (path == NULL)
		return (EINVAL);

	if (*path == '\0')
		return (ENOENT);

	usepath = kmem_alloc(MAXPATHLEN, KM_SLEEP);

	if ((len = strlcpy(usepath, path, MAXPATHLEN)) >= MAXPATHLEN) {
		kmem_free(usepath, MAXPATHLEN);
		return (ENAMETOOLONG);
	}

	(void) strsubst(usepath, '\\', '/');

	if (share_root_node)
		root_node = share_root_node;
	else
		root_node = sr->sr_server->si_root_smb_node;

	if (cur_node == NULL)
		cur_node = root_node;

	local_cur_node = cur_node;
	local_root_node = root_node;

	if (SMB_TREE_IS_DFSROOT(sr) && (sr->smb_flg2 & SMB_FLAGS2_DFS)) {
		err = smb_pathname_dfs_preprocess(sr, usepath, MAXPATHLEN);
		if (err != 0) {
			kmem_free(usepath, MAXPATHLEN);
			return (err);
		}
		len = strlen(usepath);
	}

	if (sr && (sr->smb_flg2 & SMB_FLAGS2_REPARSE_PATH)) {
		err = smb_vss_lookup_nodes(sr, root_node, cur_node,
		    usepath, &vss_cur_node, &vss_root_node);

		if (err != 0) {
			kmem_free(usepath, MAXPATHLEN);
			return (err);
		}

		len = strlen(usepath);
		local_cur_node = vss_cur_node;
		local_root_node = vss_root_node;
	}

	if (usepath[len - 1] == '/')
		trailing_slash = 1;

	(void) strcanon(usepath, "/");

	(void) pn_alloc(&ppn);

	if ((err = pn_set(&ppn, usepath)) != 0) {
		(void) pn_free(&ppn);
		kmem_free(usepath, MAXPATHLEN);
		if (vss_cur_node != NULL)
			(void) smb_node_release(vss_cur_node);
		if (vss_root_node != NULL)
			(void) smb_node_release(vss_root_node);
		return (err);
	}

	/*
	 * If a path does not have a trailing slash, strip off the
	 * last component.  (We only need to return an smb_node for
	 * the second to last component; a name is returned for the
	 * last component.)
	 */

	if (trailing_slash) {
		(void) strlcpy(last_component, ".", MAXNAMELEN);
	} else {
		(void) pn_setlast(&ppn);
		(void) strlcpy(last_component, ppn.pn_path, MAXNAMELEN);
		ppn.pn_path[0] = '\0';
	}

	if ((strcmp(ppn.pn_buf, "/") == 0) || (ppn.pn_buf[0] == '\0')) {
		smb_node_ref(local_cur_node);
		*dir_node = local_cur_node;
	} else {
		err = smb_pathname(sr, ppn.pn_buf, lookup_flags,
		    local_root_node, local_cur_node, NULL, dir_node, cred);
	}

	(void) pn_free(&ppn);
	kmem_free(usepath, MAXPATHLEN);

	/*
	 * Prevent traversal to another file system if mount point
	 * traversal is disabled.
	 *
	 * Note that we disregard whether the traversal of the path went
	 * outside of the file system and then came back (say via a link).
	 * This means that only symlinks that are expressed relatively to
	 * the share root work.
	 *
	 * share_root_node is NULL when mapping a share, so we disregard
	 * that case.
	 */

	if ((err == 0) && share_root_node) {
		if (share_root_node->vp->v_vfsp != (*dir_node)->vp->v_vfsp) {
			err = EACCES;
			if ((sr) && (sr)->tid_tree &&
			    smb_tree_has_feature((sr)->tid_tree,
			    SMB_TREE_TRAVERSE_MOUNTS))
				err = 0;
		}
	}

	if (err) {
		if (*dir_node) {
			(void) smb_node_release(*dir_node);
			*dir_node = NULL;
		}
		*last_component = 0;
	}

	if (vss_cur_node != NULL)
		(void) smb_node_release(vss_cur_node);
	if (vss_root_node != NULL)
		(void) smb_node_release(vss_root_node);

	return (err);
}