Beispiel #1
0
/*
 * Adds an entry with given DFS name (root sharename) and relative path
 * to the share (relpath) and the specified entry type (i.e. root/link)
 * to the namespace cache.
 */
uint32_t
dfs_cache_add_byname(const char *name, const char *relpath, uint32_t type)
{
	char uncpath[DFS_PATH_MAX];
	char fspath[DFS_PATH_MAX];
	smb_share_t si;

	if (smb_shr_get((char *)name, &si) != NERR_Success)
		return (ERROR_NOT_FOUND);

	if (type == DFS_OBJECT_ROOT) {
		(void) snprintf(uncpath, DFS_PATH_MAX, "\\\\%s\\%s",
		    dfs_nbname, name);
		return (dfs_cache_add_byunc(uncpath, si.shr_path, type));
	}

	/* add link entry */
	(void) snprintf(fspath, DFS_PATH_MAX, "%s/%s", si.shr_path, relpath);
	(void) snprintf(uncpath, DFS_PATH_MAX, "\\\\%s\\%s\\%s", dfs_nbname,
	    name, relpath);

	/* relpath may contain '/' */
	(void) strsubst(uncpath, '/', '\\');

	return (dfs_cache_add_byunc(uncpath, fspath, type));
}
Beispiel #2
0
/*ARGSUSED*/
static void *
smbd_share_printers(void *arg)
{
    cups_dest_t	*dests;
    cups_dest_t	*dest;
    smb_cups_ops_t	*cups;
    smb_share_t	si;
    uint32_t	nerr;
    int		num_dests;
    int		i;

    if (!smb_config_getbool(SMB_CI_PRINT_ENABLE))
        return (NULL);

    if ((cups = smbd_cups_ops()) == NULL)
        return (NULL);

    if (smb_shr_get(SMB_SHARE_PRINT, &si) != NERR_Success) {
        syslog(LOG_DEBUG,
               "smbd_share_printers unable to load %s", SMB_SHARE_PRINT);
        return (NULL);
    }

    num_dests = cups->cupsGetDests(&dests);

    for (i = num_dests, dest = dests; i > 0; i--, dest++) {
        if (dest->instance != NULL)
            continue;

        (void) strlcpy(si.shr_name, dest->name, MAXPATHLEN);
        smbd_print_share_comment(&si, dest);
        si.shr_type = STYPE_PRINTQ;

        nerr = smb_shr_add(&si);
        if (nerr == NERR_Success || nerr == NERR_DuplicateShare)
            syslog(LOG_DEBUG,
                   "shared printer: %s", si.shr_name);
        else
            syslog(LOG_DEBUG,
                   "smbd_share_printers: unable to add share %s: %u",
                   si.shr_name, nerr);
    }

    cups->cupsFreeDests(num_dests, dests);
    return (NULL);
}
Beispiel #3
0
/*
 * Returns the file system path for the given share if it
 * is a DFS root share.
 * If 'path' is NULL, this function only indicates whether
 * or not the given share represents a DFS namespace
 */
uint32_t
dfs_namespace_path(const char *name, char *path, size_t pathsz)
{
	smb_share_t si;

	if (smb_shr_get((char *)name, &si) != NERR_Success)
		return (ERROR_NOT_FOUND);

	if ((si.shr_flags & SMB_SHRF_DFSROOT) == 0)
		return (ERROR_NOT_FOUND);

	if (!dfs_namespace_iscached(name))
		return (ERROR_NOT_FOUND);

	if (path != NULL)
		(void) strlcpy(path, si.shr_path, pathsz);

	return (ERROR_SUCCESS);
}
Beispiel #4
0
/*
 * Removes the namespace and all the links in it.
 */
uint32_t
dfs_namespace_remove(const char *name)
{
	smb_cache_cursor_t cursor;
	dfs_nscnode_t nscnode;
	smb_share_t si;
	uint32_t status;

	if (smb_shr_get((char *)name, &si) != NERR_Success)
		return (ERROR_NOT_FOUND);

	if ((si.shr_flags & SMB_SHRF_DFSROOT) == 0)
		return (ERROR_NOT_FOUND);

	if ((status = dfs_root_remove(si.shr_path)) != ERROR_SUCCESS)
		return (status);

	status = srvsvc_shr_setdfsroot(&si, B_FALSE);
	if (status != ERROR_SUCCESS)
		syslog(LOG_WARNING, "dfs: failed to disable root share %s (%d)",
		    name, status);

	if (!dfs_namespace_iscached(name))
		return (ERROR_SUCCESS);

	smb_cache_iterinit(&dfs_nscache, &cursor);

	while (smb_cache_iterate(&dfs_nscache, &cursor, &nscnode)) {
		if (nscnode.nsc_type == DFS_OBJECT_ROOT)
			continue;
		status = dfs_link_remove(nscnode.nsc_fspath, NULL, NULL);
		if (status != ERROR_SUCCESS)
			syslog(LOG_WARNING, "dfs: failed to remove %s (%d)",
			    nscnode.nsc_fspath, status);
	}

	dfs_cache_flush(name);

	/* TODO: remove empty dirs */
	return (ERROR_SUCCESS);
}
Beispiel #5
0
/*
 * Caches the specified namespace
 */
static void *
dfs_namespace_cache(void *arg)
{
	char *share = arg;
	char uncpath[DFS_PATH_MAX];
	smb_share_t si;

	if (smb_shr_get(share, &si) != NERR_Success) {
		free(share);
		return (NULL);
	}

	/*
	 * This check should be removed when multiple standalone
	 * namespaces are supported.
	 */
	(void) mutex_lock(&dfs_nsmtx);
	if (*dfs_cached_ns != '\0') {
		syslog(LOG_WARNING, "dfs: trying to load %s namespace."
		    " Only one standalone namespace is supported."
		    " A namespace is already exported for %s",
		    share, dfs_cached_ns);
		(void) mutex_unlock(&dfs_nsmtx);
		free(share);
		return (NULL);
	}
	(void) strlcpy(dfs_cached_ns, share, sizeof (dfs_cached_ns));
	(void) smb_config_setnum(SMB_CI_DFS_STDROOT_NUM, 1);
	(void) mutex_unlock(&dfs_nsmtx);

	(void) snprintf(uncpath, DFS_PATH_MAX, "\\\\%s\\%s", dfs_nbname, share);
	(void) dfs_cache_add_byunc(uncpath, si.shr_path, DFS_OBJECT_ROOT);

	dfs_cache_populate(uncpath, si.shr_path);

	free(share);
	return (NULL);
}
/*
 * 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);
}
/*
 * Windows XP and 2000 use this mechanism to write spool files.
 * Create a spool file fd to be used by spoolss_s_WritePrinter
 * and add it to the tail of the spool list.
 */
static int
spoolss_s_StartDocPrinter(void *arg, ndr_xa_t *mxa)
{
	struct spoolss_StartDocPrinter *param = arg;
	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
	smb_spooldoc_t *spfile;
	spoolss_DocInfo_t *docinfo;
	char g_path[MAXPATHLEN];
	smb_share_t si;
	int rc;
	int fd;

	if (ndr_hdlookup(mxa, id) == NULL) {
		smb_tracef("spoolss_s_StartDocPrinter: invalid handle");
		param->status = ERROR_INVALID_HANDLE;
		return (NDR_DRC_OK);
	}

	if ((docinfo = param->dinfo.DocInfoContainer) == NULL) {
		param->status = ERROR_INVALID_PARAMETER;
		return (NDR_DRC_OK);
	}

	if ((rc = smb_shr_get(SMB_SHARE_PRINT, &si)) != NERR_Success) {
		smb_tracef("spoolss_s_StartDocPrinter: %s error=%d",
		    SMB_SHARE_PRINT, rc);
		param->status = rc;
		return (NDR_DRC_OK);
	}

	if ((spfile = calloc(1, sizeof (smb_spooldoc_t))) == NULL) {
		param->status = ERROR_NOT_ENOUGH_MEMORY;
		return (NDR_DRC_OK);
	}

	if (docinfo->doc_name != NULL)
		(void) strlcpy(spfile->sd_doc_name,
		    (char *)docinfo->doc_name, MAXNAMELEN);
	else
		(void) strlcpy(spfile->sd_doc_name, "document", MAXNAMELEN);

	if (docinfo->printer_name != NULL)
		(void) strlcpy(spfile->sd_printer_name,
		    (char *)docinfo->printer_name, MAXPATHLEN);
	else
		(void) strlcpy(spfile->sd_printer_name, "printer", MAXPATHLEN);

	spfile->sd_ipaddr = mxa->pipe->np_user->ui_ipaddr;
	(void) strlcpy((char *)spfile->sd_username,
	    mxa->pipe->np_user->ui_account, MAXNAMELEN);
	(void) memcpy(&spfile->sd_handle, &param->handle, sizeof (ndr_hdid_t));

	/*
	 *	write temporary spool file to print$
	 */
	(void) snprintf(g_path, MAXPATHLEN, "%s/%s%d", si.shr_path,
	    spfile->sd_username, spoolss_cnt);
	atomic_inc_32(&spoolss_cnt);

	fd = open(g_path, O_CREAT | O_RDWR, 0600);
	if (fd == -1) {
		smb_tracef("spoolss_s_StartDocPrinter: %s: %s",
		    g_path, strerror(errno));
		param->status = ERROR_OPEN_FAILED;
		free(spfile);
	} else {
		(void) strlcpy((char *)spfile->sd_path, g_path, MAXPATHLEN);
		spfile->sd_fd = (uint16_t)fd;

		/*
		 * Add the document to the spool list.
		 */
		(void) rw_wrlock(&spoolss_splist.sp_rwl);
		list_insert_tail(&spoolss_splist.sp_list, spfile);
		spoolss_splist.sp_cnt++;
		(void) rw_unlock(&spoolss_splist.sp_rwl);

		/*
		 * JobId isn't used now, but if printQ management is added
		 * this will have to be incremented per job submitted.
		 */
		param->JobId = 46;
		param->status = ERROR_SUCCESS;
	}
	return (NDR_DRC_OK);
}
Beispiel #8
0
/*
 * Creates a DFS root with the given name and comment.
 *
 * This function does not create the root share, it
 * should already exist.
 */
uint32_t
dfs_namespace_add(const char *rootshr, const char *cmnt)
{
	dfs_info_t info;
	dfs_target_t t;
	smb_share_t si;
	uuid_t uuid;
	uint32_t status;

	if (*rootshr == '\\') {
		/* Windows has a special case here! */
		return (ERROR_BAD_PATHNAME);
	}

	if (smb_shr_get((char *)rootshr, &si) != NERR_Success)
		return (NERR_NetNameNotFound);

	(void) mutex_lock(&dfs_nsmtx);
	if (smb_strcasecmp(dfs_cached_ns, rootshr, 0) == 0) {
		/* This DFS root is already exported */
		(void) mutex_unlock(&dfs_nsmtx);
		return (ERROR_FILE_EXISTS);
	}

	if (*dfs_cached_ns != '\0') {
		syslog(LOG_WARNING, "dfs: trying to add %s namespace."
		    " Only one standalone namespace is supported."
		    " A namespace is already exported for %s",
		    rootshr, dfs_cached_ns);
		(void) mutex_unlock(&dfs_nsmtx);
		return (ERROR_NOT_SUPPORTED);
	}

	bzero(&info, sizeof (info));
	if (cmnt)
		(void) strlcpy(info.i_comment, cmnt, sizeof (info.i_comment));
	info.i_state = DFS_VOLUME_STATE_OK | DFS_VOLUME_FLAVOR_STANDALONE;
	info.i_timeout = DFS_ROOT_TIMEOUT;
	info.i_propflags = 0;

	uuid_generate_random(uuid);
	uuid_unparse(uuid, info.i_guid);

	dfs_target_init(&t, dfs_nbname, rootshr, DFS_STORAGE_STATE_ONLINE);

	info.i_ntargets = 1;
	info.i_targets = &t;

	if ((status = dfs_root_add(si.shr_path, &info)) != ERROR_SUCCESS) {
		(void) mutex_unlock(&dfs_nsmtx);
		return (status);
	}

	status = srvsvc_shr_setdfsroot(&si, B_TRUE);
	if (status == ERROR_SUCCESS) {
		(void) dfs_cache_add_byname(rootshr, NULL, DFS_OBJECT_ROOT);
		(void) strlcpy(dfs_cached_ns, rootshr, sizeof (dfs_cached_ns));
		(void) smb_config_setnum(SMB_CI_DFS_STDROOT_NUM, 1);
	}
	(void) mutex_unlock(&dfs_nsmtx);

	return (status);
}