/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Server Service RPC (SRVSVC) server-side interface definition.
* The server service provides a remote administration interface.
*
* values.
*/
#include <unistd.h>
#include <netdb.h>
#include <strings.h>
#include <time.h>
#include <thread.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <libshare.h>
#include <libnvpair.h>
#include <pwd.h>
#include <nss_dbdefs.h>
#include <smbsrv/libmlsvc.h>
#include <smbsrv/netrauth.h>
#include "mlsvc.h"
/*
* Qualifier types for NetConnectEnum.
*/
#define SRVSVC_CONNECT_ENUM_NULL 0
typedef struct srvsvc_sd {
} srvsvc_sd_t;
typedef struct srvsvc_netshare_setinfo {
char *nss_netname;
char *nss_comment;
char *nss_path;
typedef union srvsvc_netshare_getinfo {
smb_svcenum_t *se);
smb_svcenum_t *se);
smb_netsvc_t *, smb_svcenum_t *);
smb_svcenum_t *, int);
smb_svcenum_t *, int);
smb_svcenum_t *, int);
smb_svcenum_t *, int);
smb_svcenum_t *, int);
smb_share_t *, void *);
static char *srvsvc_share_mkpath(ndr_xa_t *, char *);
static int srvsvc_netconnect_qualifier(const char *);
static uint32_t srvsvc_open_sessions(void);
static uint32_t srvsvc_open_files(void);
static uint32_t srvsvc_sa_add(char *, char *, char *);
static uint32_t srvsvc_sa_delete(char *);
"SRVSVC", /* name */
"Server services", /* desc */
"\\srvsvc", /* endpoint */
PIPE_NTSVCS, /* sec_addr_port */
"4b324fc8-1670-01d3-1278-5a47bf6ee188", 3, /* abstract */
0, /* no bind_instance_size */
0, /* no bind_req() */
0, /* no unbind_and_close() */
0, /* use generic_call_stub() */
srvsvc_stub_table /* stub_table */
};
/*
* srvsvc_initialize
*
* This function registers the SRVSVC RPC interface with the RPC runtime
* library. It must be called in order to use either the client side
* or the server side functions.
*/
void
srvsvc_initialize(void)
{
(void) ndr_svc_register(&srvsvc_service);
}
/*
* share and save it.
*
* If the requested value is the same as what is already
* set then no change is required and the function returns.
*/
{
dfs = "true";
dfs = "false";
}
return (ERROR_SUCCESS);
return (NERR_InternalError);
return (NERR_InternalError);
}
if (nerr != NERR_Success)
return (nerr);
return (smb_shr_modify(si));
}
/*
* srvsvc_s_NetConnectEnum
*
* List tree connections made to a share on this server or all tree
* connections established from a specific client. Administrator,
* Server Operator, Print Operator or Power User group membership
* is required to use this interface.
*
* There are three information levels: 0, 1, and 50. We don't support
* level 50, which is only used by Windows 9x clients.
*
* It seems Server Manger (srvmgr) only sends workstation as the qualifier
* and the Computer Management Interface on Windows 2000 doesn't request
* a list of connections.
*
* Return Values:
* ERROR_SUCCESS Success
* ERROR_ACCESS_DENIED Caller does not have access to this call.
* ERROR_INVALID_PARAMETER One of the parameters is invalid.
* ERROR_INVALID_LEVEL Unknown information level specified.
* ERROR_MORE_DATA Partial date returned, more entries available.
* ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available.
* NERR_NetNameNotFound The share qualifier cannot be found.
* NERR_BufTooSmall The supplied buffer is too small.
*/
static int
{
char *qualifier;
int qualtype;
if (!ndr_is_poweruser(mxa)) {
}
if (qualtype == SRVSVC_CONNECT_ENUM_NULL) {
}
if (param->total_entries == 0) {
return (NDR_DRC_OK);
}
else
if (param->resume_handle) {
*param->resume_handle = 0;
}
case 0:
break;
case 1:
break;
case 50:
break;
default:
break;
}
if (status != ERROR_SUCCESS)
}
if (status != ERROR_SUCCESS)
if (param->resume_handle &&
}
}
return (NDR_DRC_OK);
return (NDR_DRC_OK);
}
/*
* Allocate memory and estimate the number of objects that can
* be returned for NetConnectEnum level 0.
*/
static uint32_t
{
return (ERROR_NOT_ENOUGH_MEMORY);
return (NERR_BufTooSmall);
do {
return (ERROR_NOT_ENOUGH_MEMORY);
info0->entries_read = 0;
return (ERROR_SUCCESS);
}
/*
* Allocate memory and estimate the number of objects that can
* be returned for NetConnectEnum level 1.
*/
static uint32_t
{
return (ERROR_NOT_ENOUGH_MEMORY);
sizeof (srvsvc_NetConnectInfoBuf1_t) + MAXNAMELEN);
return (NERR_BufTooSmall);
do {
return (ERROR_NOT_ENOUGH_MEMORY);
info1->entries_read = 0;
return (ERROR_SUCCESS);
}
/*
* Request a list of connections from the kernel and set up
* the connection information to be returned to the client.
*/
static uint32_t
{
if (smb_kmod_enum(ns) != 0)
return (ERROR_INTERNAL_ERROR);
case 0:
++ci0;
++info0->entries_read;
break;
case 1:
++ci1;
++info1->entries_read;
break;
default:
return (ERROR_INVALID_LEVEL);
}
}
return (ERROR_SUCCESS);
}
/*
* srvsvc_netconnect_qualifier
*
* The qualifier is a string that specifies a share name or computer name
* for the connections of interest. If it is a share name then all the
* connections made to that share name are listed. If it is a computer
* name (it starts with two backslash characters), then NetConnectEnum
* lists all connections made from that computer to the specified server.
*/
static int
{
return (SRVSVC_CONNECT_ENUM_NULL);
return (SRVSVC_CONNECT_ENUM_NULL);
return (SRVSVC_CONNECT_ENUM_WKSTN);
} else {
if (!smb_shr_exists((char *)qualifier))
return (SRVSVC_CONNECT_ENUM_NULL);
return (SRVSVC_CONNECT_ENUM_SHARE);
}
}
static uint32_t
srvsvc_open_sessions(void)
{
if (smb_kmod_get_open_num(&opennum) != 0)
return (0);
return (opennum.open_users);
}
static uint32_t
{
if (smb_kmod_get_open_num(&opennum) != 0)
return (0);
return (opennum.open_trees);
}
static uint32_t
srvsvc_open_files(void)
{
if (smb_kmod_get_open_num(&opennum) != 0)
return (0);
return (opennum.open_files);
}
/*
* srvsvc_s_NetFileEnum
*
* Return information on open files or named pipes. Only members of the
* Administrators or Server Operators local groups are allowed to make
* this call. Currently, we only support Administrators.
*
* If basepath is null, all open resources are enumerated. If basepath
* is non-null, only resources that have basepath as a prefix should
* be returned.
*
* If username is specified (non-null), only files opened by username
* should be returned.
*
* Notes:
* 1. We don't validate the servername because we would have to check
* all primary IPs and the ROI seems unlikely to be worth it.
* 2. Both basepath and username are currently ignored because both
* Server Manger (NT 4.0) and CMI (Windows 2000) always set them to null.
*
* The level of information requested may be one of:
*
* 2 Return the file identification number.
* This level is not supported on Windows Me/98/95.
*
* 3 Return information about the file.
* This level is not supported on Windows Me/98/95.
*
* 50 Windows Me/98/95: Return information about the file.
*
* Note:
* If pref_max_len is unlimited and resume_handle is null, the client
* expects to receive all data in a single call.
* If we are unable to do fit all data in a single response, we would
* normally return ERROR_MORE_DATA with a partial list.
*
* Unfortunately, when both of these conditions occur, Server Manager
* pops up an error box with the message "more data available" and
* doesn't display any of the returned data. In this case, it is
* probably better to return ERROR_SUCCESS with the partial list.
* Windows 2000 doesn't have this problem because it always sends a
* non-null resume_handle.
*
* Return Values:
* ERROR_SUCCESS Success
* ERROR_ACCESS_DENIED Caller does not have access to this call.
* ERROR_INVALID_PARAMETER One of the parameters is invalid.
* ERROR_INVALID_LEVEL Unknown information level specified.
* ERROR_MORE_DATA Partial date returned, more entries available.
* ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available.
* NERR_BufTooSmall The supplied buffer is too small.
*/
static int
{
if (!ndr_is_admin(mxa)) {
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
else
if (param->resume_handle) {
*param->resume_handle = 0;
}
case 2:
break;
case 3:
break;
case 50:
break;
default:
break;
}
if (status != ERROR_SUCCESS) {
return (NDR_DRC_OK);
}
if (param->resume_handle &&
}
}
return (NDR_DRC_OK);
}
/*
* Build level 2 file information.
*
* SMB fids are 16-bit values but this interface expects 32-bit file ids.
* So we use the uniqid here.
*
* On success, the caller expects that the info2, fi2 and entries_read
* fields have been set up.
*/
static DWORD
{
return (ERROR_NOT_ENOUGH_MEMORY);
return (NERR_BufTooSmall);
do {
return (ERROR_NOT_ENOUGH_MEMORY);
return (ERROR_NOT_ENOUGH_MEMORY);
if (smb_kmod_enum(ns) != 0) {
return (ERROR_INTERNAL_ERROR);
}
++entries_read;
++fi2;
}
return (ERROR_SUCCESS);
}
/*
* Build level 3 file information.
*
* SMB fids are 16-bit values but this interface expects 32-bit file ids.
* So we use the uniqid here.
*
* On success, the caller expects that the info3, fi3 and entries_read
* fields have been set up.
*/
static DWORD
{
return (ERROR_NOT_ENOUGH_MEMORY);
sizeof (struct mslm_NetFileInfoBuf3) + MAXNAMELEN);
return (NERR_BufTooSmall);
do {
return (ERROR_NOT_ENOUGH_MEMORY);
return (ERROR_NOT_ENOUGH_MEMORY);
if (smb_kmod_enum(ns) != 0) {
return (ERROR_INTERNAL_ERROR);
}
++entries_read;
++fi3;
}
return (ERROR_SUCCESS);
}
/*
* srvsvc_s_NetFileClose
*
* NetFileClose forces a file to close. This function can be used when
* an error prevents closure by other means. Use NetFileClose with
* caution because it does not flush data, cached on a client, to the
* file before closing the file.
*
* SMB fids are 16-bit values but this interface expects 32-bit file ids.
* So we use the uniqid here.
*
* Return Values
* ERROR_SUCCESS Operation succeeded.
* ERROR_ACCESS_DENIED Operation denied.
* NERR_FileIdNotFound No open file with the specified id.
*
* Note: MSDN suggests ERROR_FILE_NOT_FOUND for NetFileClose but network
* captures using NT show NERR_FileIdNotFound, which is consistent with
* the NetFileClose2 page on MSDN.
*/
static int
{
static struct {
int errnum;
int nerr;
} errmap[] = {
0, ERROR_SUCCESS,
};
int i;
int rc;
if (!ndr_is_admin(mxa)) {
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
}
return (NDR_DRC_OK);
}
/*
* srvsvc_s_NetShareGetInfo
*
* Returns Win32 error codes.
*/
static int
{
if (status != NERR_Success) {
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
case 0:
break;
case 1:
break;
case 2:
info2->shi2_passwd = 0;
info2->shi2_permissions = 0;
info2->shi2_current_uses = 0;
break;
case 501:
break;
case 502:
info502->shi502_passwd = 0;
info502->shi502_permissions = 0;
info502->shi502_current_uses = 0;
if (status == ERROR_SUCCESS) {
} else {
info502->shi502_reserved = 0;
}
break;
case 503:
info503->shi503_permissions = 0;
info503->shi503_current_uses = 0;
if (status == ERROR_SUCCESS) {
} else {
info503->shi503_reserved = 0;
}
break;
case 1004:
break;
case 1005:
break;
case 1006:
break;
case 1501:
if (status == ERROR_SUCCESS) {
} else {
info503->shi503_reserved = 0;
}
break;
default:
break;
}
if (status != ERROR_SUCCESS)
else
return (NDR_DRC_OK);
}
static uint32_t
{
if (status != ERROR_SUCCESS) {
if (status == ERROR_PATH_NOT_FOUND) {
}
return (status);
}
return (ERROR_NOT_ENOUGH_MEMORY);
if (status == ERROR_PATH_NOT_FOUND) {
}
return (status);
}
/*
* srvsvc_s_NetShareSetInfo
*
* This call is made by SrvMgr to set share information.
* Only power users groups can manage shares.
*
* To avoid misleading errors, we don't report an error
* when a FS doesn't support ACLs on shares.
*
* Returns Win32 error codes.
*/
static int
{
if (!ndr_is_poweruser(mxa)) {
goto netsharesetinfo_exit;
}
goto netsharesetinfo_exit;
}
goto netsharesetinfo_exit;
}
case 0:
break;
case 1:
break;
case 2:
break;
case 501:
info501 = (struct mslm_NetShareInfo_501 *)
if (status == ERROR_SUCCESS)
break;
case 502:
info502 = (struct mslm_NetShareInfo_502 *)
break;
case 503:
info503 = (struct mslm_NetShareInfo_503 *)
break;
case 1004:
info1004 = (struct mslm_NetShareInfo_1004 *)
break;
case 1005:
info1005 = (struct mslm_NetShareInfo_1005 *)
break;
case 1006:
/*
* We don't limit the maximum number of concurrent
* connections to a share.
*/
break;
case 1501:
info1501 = (struct mslm_NetShareInfo_1501 *)
if (status == ERROR_PATH_NOT_FOUND)
}
break;
default:
break;
}
if (status != ERROR_SUCCESS)
return (NDR_DRC_OK);
}
static uint32_t
{
if (nerr == ERROR_PATH_NOT_FOUND)
nerr = NERR_Success;
}
return (nerr);
}
/*
* Update transient shares. This includes autohome shares.
*/
static uint32_t
{
if (nerr != NERR_Success)
return (nerr);
}
return (nerr);
}
return (NERR_Success);
}
/*
* srvsvc_update_share_flags
*
* This function updates flags for shares.
* Flags for Persistent shares are updated in both libshare and the local cache.
* Flags for Transient shares are updated only in the local cache.
*/
static uint32_t
{
char *csc_value;
int err = 0;
flag = SMB_SHRF_ABE;
abe_value = "true";
}
case CSC_CACHE_AUTO_REINT:
break;
case CSC_CACHE_VDO:
break;
case CSC_CACHE_NONE:
break;
case CSC_CACHE_MANUAL_REINT:
break;
default:
return (NERR_InternalError);
}
return (NERR_InternalError);
if (err) {
return (NERR_InternalError);
}
if (nerr != NERR_Success)
return (nerr);
}
return (smb_shr_modify(si));
}
static uint32_t
{
case SMB_SHRF_CSC_DISABLED:
flags |= CSC_CACHE_NONE;
break;
case SMB_SHRF_CSC_AUTO:
break;
case SMB_SHRF_CSC_VDO:
flags |= CSC_CACHE_VDO;
break;
case SMB_SHRF_CSC_MANUAL:
default:
/*
* Default to CSC_CACHE_MANUAL_REINT.
*/
break;
}
/* if 'smb' zfs property: shortnames=disabled */
(shortnames == B_FALSE)) {
}
return (flags);
}
/*
* srvsvc_s_NetSessionEnum
*
* Level 1 request is made by (Server Manager (srvmgr) on NT Server when
* the user info icon is selected.
*
* On success, the return value is NERR_Success.
* On error, the return value can be one of the following error codes:
*
* ERROR_ACCESS_DENIED The user does not have access to the requested
* information.
* ERROR_INVALID_LEVEL The value specified for the level is invalid.
* ERROR_INVALID_PARAMETER The specified parameter is invalid.
* ERROR_MORE_DATA More entries are available. Specify a large
* enough buffer to receive all entries.
* ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available.
* NERR_ClientNameNotFound A session does not exist with the computer name.
* NERR_InvalidComputer The computer name is invalid.
* NERR_UserNotFound The user name could not be found.
*/
static int
{
if (!ndr_is_admin(mxa)) {
}
}
info->entriesread = 0;
return (NDR_DRC_OK);
}
if (param->resume_handle) {
*param->resume_handle = 0;
}
case 0:
break;
case 1:
break;
case 2:
break;
case 10:
break;
case 502:
break;
default:
return (NDR_DRC_OK);
}
}
}
if (status != ERROR_SUCCESS)
if (param->resume_handle &&
}
}
return (NDR_DRC_OK);
return (NDR_DRC_OK);
}
static uint32_t
{
char *workstation;
if (smb_kmod_enum(ns) != 0)
return (ERROR_INTERNAL_ERROR);
}
case 0:
return (ERROR_NOT_ENOUGH_MEMORY);
++info0;
break;
case 1:
return (ERROR_NOT_ENOUGH_MEMORY);
info1->sesi1_itime = 0;
++info1;
break;
case 2:
return (ERROR_NOT_ENOUGH_MEMORY);
info2->sesi2_itime = 0;
++info2;
break;
case 10:
return (ERROR_NOT_ENOUGH_MEMORY);
info10->sesi10_itime = 0;
++info10;
break;
case 502:
return (ERROR_NOT_ENOUGH_MEMORY);
info502->sesi502_itime = 0;
++info502;
break;
default:
return (ERROR_INVALID_LEVEL);
}
++entries_read;
}
return (ERROR_SUCCESS);
}
/*
* srvsvc_s_NetSessionDel
*
* Ends a network session between a server and a workstation.
* On NT only members of the Administrators or Account Operators
* local groups are permitted to use NetSessionDel.
*
* If unc_clientname is NULL, all sessions associated with the
* specified user will be disconnected.
*
* If username is NULL, all sessions from the specified client
* will be disconnected.
*
* Return Values
* On success, the return value is NERR_Success/ERROR_SUCCESS.
* On failure, the return value can be one of the following errors:
*
* ERROR_ACCESS_DENIED The user does not have access to the
* requested information.
* ERROR_INVALID_PARAMETER The specified parameter is invalid.
* ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available.
* NERR_ClientNameNotFound A session does not exist with that
* computer name.
*/
static int
{
static struct {
int errnum;
int nerr;
} errmap[] = {
0, ERROR_SUCCESS,
};
int i;
int rc;
if (!ndr_is_admin(mxa)) {
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
}
return (NDR_DRC_OK);
}
static int
{
return (ERROR_NOT_ENOUGH_MEMORY);
}
sizeof (sys_comment));
if (*sys_comment == '\0')
case 100:
break;
case 101:
break;
case 102:
/*
* The following level 102 fields are defaulted to zero
* by virtue of the call to bzero above.
*
* sv102_users
* sv102_disc
* sv102_hidden
* sv102_announce
* sv102_anndelta
* sv102_licenses
* sv102_userpath
*/
break;
case 502:
#ifdef SRVSVC_SATISFY_SMBTORTURE
break;
#else
return (NDR_DRC_OK);
#endif /* SRVSVC_SATISFY_SMBTORTURE */
case 503:
#ifdef SRVSVC_SATISFY_SMBTORTURE
break;
#else
return (NDR_DRC_OK);
#endif /* SRVSVC_SATISFY_SMBTORTURE */
default:
sizeof (struct mslm_NetServerGetInfo_result));
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
/*
* NetRemoteTOD
*
* Returns information about the time of day on this server.
*
* typedef struct _TIME_OF_DAY_INFO {
* DWORD tod_elapsedt; // seconds since 00:00:00 January 1 1970 GMT
* DWORD tod_msecs; // arbitrary milliseconds (since reset)
* DWORD tod_hours; // current hour [0-23]
* DWORD tod_mins; // current minute [0-59]
* DWORD tod_secs; // current second [0-59]
* DWORD tod_hunds; // current hundredth (0.01) second [0-99]
* LONG tod_timezone; // time zone of the server
* DWORD tod_tinterval; // clock tick time interval
* DWORD tod_day; // day of the month [1-31]
* DWORD tod_month; // month of the year [1-12]
* DWORD tod_year; // current year
* DWORD tod_weekday; // day of the week since Sunday [0-6]
* } TIME_OF_DAY_INFO;
*
* The time zone of the server is calculated in minutes from Greenwich
* Mean Time (GMT). For time zones west of Greenwich, the value is
* positive; for time zones east of Greenwich, the value is negative.
* A value of -1 indicates that the time zone is undefined.
*
* Determine offset from GMT. If daylight saving time use altzone,
* otherwise use timezone.
*
* The clock tick value represents a resolution of one ten-thousandth
* (0.0001) second.
*/
static int
{
(void) gettimeofday(&time_val, 0);
return (ERROR_NOT_ENOUGH_MEMORY);
}
return (NDR_DRC_OK);
}
/*
* srvsvc_s_NetNameValidate
*
* Perform name validation.
*
* Returns Win32 error codes.
*/
/*ARGSUSED*/
static int
{
char *name;
int maxlen;
int len;
return (NDR_DRC_OK);
}
case NAMETYPE_SHARE:
return (NDR_DRC_OK);
}
break;
case NAMETYPE_USER:
case NAMETYPE_GROUP:
break;
case NAMETYPE_DOMAIN: /* NetBIOS domain name */
break;
case NAMETYPE_WORKGROUP:
break;
case NAMETYPE_PASSWORD:
case NAMETYPE_COMPUTER:
case NAMETYPE_EVENT:
case NAMETYPE_SERVICE:
case NAMETYPE_NET:
case NAMETYPE_MESSAGE:
case NAMETYPE_MESSAGEDEST:
case NAMETYPE_SHAREPASSWORD:
break;
default:
break;
}
return (NDR_DRC_OK);
}
/*
* srvsvc_s_NetShareAdd
*
* Add a new share. Only power users groups can manage shares.
*
* This interface is used by the rmtshare command from the NT resource
* kit. Rmtshare allows a client to add or remove shares on a server
* from the client's command line.
*
* Returns Win32 error codes.
*/
static int
{
if (!ndr_is_poweruser(mxa)) {
return (NDR_DRC_OK);
}
case 2:
break;
case 502:
info502 = (struct mslm_NetShareInfo_502 *)
break;
default:
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
/*
* Derive the real path which will be stored in the
* directory field of the smb_share_t structure
* from the path field in this RPC request.
*/
if (parm_stat != NERR_Success) {
return (NDR_DRC_OK);
}
(char *)info2->shi2_comment);
}
return (NDR_DRC_OK);
}
/*
* srvsvc_estimate_limit
*
* Estimate the number of objects that will fit in prefmaxlen.
* nlimit is adjusted here.
*/
static void
{
if (obj_size == 0) {
return;
}
return;
}
else
}
/*
* srvsvc_s_NetShareEnum
*
* Enumerate all shares (see also NetShareEnumSticky).
*
* Request for various levels of information about our shares.
* Level 0: share names.
* Level 1: share name, share type and comment field.
* Level 2: everything that we know about the shares.
* Level 501: level 1 + flags.
* Level 502: level 2 + security descriptor.
*/
static int
{
return (NDR_DRC_OK);
}
infonres->entriesread = 0;
else
if (param->resume_handle) {
*param->resume_handle = 0;
}
case 0:
break;
case 1:
break;
case 2:
break;
case 501:
break;
case 502:
break;
default:
break;
}
if (status != 0) {
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
if (param->resume_handle &&
}
}
return (NDR_DRC_OK);
}
/*
* srvsvc_s_NetShareEnumSticky
*
* Enumerate sticky shares: all shares except those marked STYPE_SPECIAL.
* Except for excluding STYPE_SPECIAL shares, NetShareEnumSticky is the
* same as NetShareEnum.
*
* Request for various levels of information about our shares.
* Level 0: share names.
* Level 1: share name, share type and comment field.
* Level 2: everything that we know about the shares.
* Level 501: not valid for this request.
* Level 502: level 2 + security descriptor.
*
* We set n_skip to resume_handle, which is used to find the appropriate
* place to resume. The resume_handle is similar to the readdir cookie.
*/
static int
{
return (NDR_DRC_OK);
}
infonres->entriesread = 0;
else
if (param->resume_handle) {
*param->resume_handle = 0;
}
case 0:
break;
case 1:
break;
case 2:
break;
case 502:
break;
case 501:
default:
break;
}
if (status != ERROR_SUCCESS) {
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
if (param->resume_handle &&
}
}
return (NDR_DRC_OK);
}
/*
* NetShareEnum Level 0
*/
static DWORD
{
sizeof (struct mslm_NetShareInfo_0) + MAXNAMELEN);
return (ERROR_SUCCESS);
return (ERROR_NOT_ENOUGH_MEMORY);
continue;
}
continue;
continue;
break;
}
if (status != ERROR_SUCCESS)
break;
}
}
return (ERROR_SUCCESS);
}
/*
* NetShareEnum Level 1
*/
static DWORD
{
sizeof (struct mslm_NetShareInfo_1) + MAXNAMELEN);
return (ERROR_SUCCESS);
return (ERROR_NOT_ENOUGH_MEMORY);
continue;
}
continue;
continue;
break;
}
if (status != ERROR_SUCCESS)
break;
}
}
return (ERROR_SUCCESS);
}
/*
* NetShareEnum Level 2
*/
static DWORD
{
sizeof (struct mslm_NetShareInfo_2) + MAXNAMELEN);
return (ERROR_SUCCESS);
return (ERROR_NOT_ENOUGH_MEMORY);
continue;
}
continue;
continue;
break;
}
if (status != ERROR_SUCCESS)
break;
}
}
return (ERROR_SUCCESS);
}
/*
* NetShareEnum Level 501
*/
static DWORD
{
sizeof (struct mslm_NetShareInfo_501) + MAXNAMELEN);
return (ERROR_SUCCESS);
return (ERROR_NOT_ENOUGH_MEMORY);
continue;
}
continue;
continue;
break;
}
if (status != ERROR_SUCCESS)
break;
}
}
return (ERROR_SUCCESS);
}
/*
* NetShareEnum Level 502
*/
static DWORD
{
sizeof (struct mslm_NetShareInfo_502) + MAXNAMELEN);
return (ERROR_SUCCESS);
return (ERROR_NOT_ENOUGH_MEMORY);
continue;
}
continue;
continue;
break;
}
if (status != ERROR_SUCCESS)
break;
}
}
return (ERROR_SUCCESS);
}
/*
* mlsvc_NetShareEnumCommon
*
* Build the levels 0, 1, 2, 501 and 502 share information. This function
* is called by the various NetShareEnum levels for each share. If
* we cannot build the share data for some reason, we return an error
* but the actual value of the error is not important to the caller.
* The caller just needs to know not to include this info in the RPC
* response.
*
* Returns:
* ERROR_SUCCESS
* ERROR_NOT_ENOUGH_MEMORY
* ERROR_INVALID_LEVEL
*/
static DWORD
{
return (ERROR_NOT_ENOUGH_MEMORY);
case 0:
break;
case 1:
break;
case 2:
info2[i].shi2_permissions = 0;
info2[i].shi2_current_uses = 0;
break;
case 501:
break;
case 502:
info502[i].shi502_permissions = 0;
info502[i].shi502_current_uses = 0;
} else {
info502[i].shi502_reserved = 0;
}
break;
default:
return (ERROR_INVALID_LEVEL);
}
return (ERROR_SUCCESS);
}
/*
* srvsvc_add_autohome
*
* Add the autohome share for the user. The share must not be a permanent
* share to avoid duplicates.
*/
static boolean_t
{
char *username;
} else {
NULL)
return (B_FALSE);
}
return (B_FALSE);
return (B_FALSE);
return (status == ERROR_SUCCESS);
}
/*
* srvsvc_share_mkpath
*
* Create the share path required by the share enum calls. The path
* is created in a heap buffer ready for use by the caller.
*
* Some Windows over-the-wire backup applications do not work unless a
* drive letter is present in the share path. We don't care about the
* drive letter since the path is fully qualified with the volume name.
*
* Windows clients seem to be mostly okay with forward slashes in
* share paths but they cannot handle one immediately after the drive
* letter, i.e. B:/. For consistency we convert all the slashes in
* the path.
*
* Returns a pointer to a heap buffer containing the share path, which
* could be a null pointer if the heap allocation fails.
*/
static char *
{
char *p;
char drive_letter;
if (drive_letter != '\0') {
}
/*
*/
p = path;
p += strspn(p, "/");
p += strcspn(p, "/");
p += strspn(p, "/");
}
static int
{
char *path;
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
}
return (NDR_DRC_OK);
}
/*
* Delete a share. Only members of the Administrators, Server Operators
* or Power Users local groups are allowed to delete shares.
*
* This interface is used by the rmtshare command from the NT resource
* kit. Rmtshare allows a client to add or remove shares on a server
* from the client's command line.
*
* Returns Win32 error codes.
*/
static int
{
if (!ndr_is_poweruser(mxa) ||
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
}
return (NDR_DRC_OK);
}
/*
* srvsvc_s_NetGetFileSecurity
*
*
* Right now, just returns ERROR_ACCESS_DENIED, because we cannot
* get the requested SD here in RPC code.
*/
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*
* srvsvc_s_NetSetFileSecurity
*
*
* Right now, just returns ERROR_ACCESS_DENIED, because we cannot
* set the requested SD here in RPC code.
*/
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*
* If the default "smb" share group exists then return the group
* handle, otherwise create the group and return the handle.
*
* All shares created via the srvsvc will be added to the "smb"
* group.
*/
static sa_group_t
{
int err;
return (group);
return (NULL);
(void) sa_remove_group(group);
}
return (group);
}
/*
* Stores the given share in sharemgr
*/
static uint32_t
{
int err;
return (NERR_InternalError);
return (NERR_InternalError);
}
return (NERR_InternalError);
}
}
if (new_share)
(void) sa_remove_share(share);
return (NERR_InternalError);
}
}
return (status);
}
/*
* Removes the share from sharemgr
*/
static uint32_t
{
return (NERR_InternalError);
}
return (status);
}
/*
* Update the share information.
*/
static uint32_t
{
return (NERR_InternalError);
return (NERR_InternalError);
}
return (NERR_InternalError);
}
return (NERR_InternalError);
}
}
if (is_zfs)
info->nss_netname);
else
info->nss_netname);
}
if (is_zfs)
info->nss_comment);
else
(void) sa_set_resource_description(resource,
info->nss_comment);
}
if (is_zfs) {
return (NERR_InternalError);
}
}
if (renamed) {
if (nerr != NERR_Success)
return (nerr);
}
return (nerr);
}
/*
* Sets the share properties.
*
* This method sets share properties. If its a ZFS share, then properties
* are set by calling the sa_zfs_setprop method. Else the optionset properties
* of the share resource are set.The properties to be set are given as a list
* of name-value pair.
*/
static uint32_t
{
int err = 0;
return (NERR_InternalError);
return (NERR_InternalError);
}
return (NERR_InternalError);
}
return (nerr);
}
return (NERR_InternalError);
}
}
break;
}
if (nerr != NERR_Success) {
(void) sa_remove_property(prop);
break;
}
}
if (nerr != NERR_Success)
break;
} else {
if (nerr != NERR_Success)
break;
}
}
if (nerr == NERR_Success)
return (nerr);
}
{0}
};