diff options
author | as200622 <none@none> | 2007-11-26 18:29:15 -0800 |
---|---|---|
committer | as200622 <none@none> | 2007-11-26 18:29:15 -0800 |
commit | 55bf511df53aad0fdb7eb3fa349f0308cc05234c (patch) | |
tree | a153d7bae39c0480da0107072553ce0b07b02f23 | |
parent | b3d911cb99b7e5dd9df4c81fd7b58a97c82d07db (diff) | |
download | illumos-gate-55bf511df53aad0fdb7eb3fa349f0308cc05234c.tar.gz |
6575640 rename/rmdir/remove on mixed file systems work incorrectly for mangled names
6582182 64-bit libraries
6588720 Unable to create new folder in autohome share from Solaris10u3 with UFS & ZFS.
6611820 Unable to map a SMB share on SPARC system.
6612193 Rework ADS client, DynDNS client and Auth IPC to use host principal
6614664 CIFS server should not request ctime changes
6614864 Security tab not available after a share is mapped on SPARC system
6614953 An error occurred while creating a notepad file on X86 32-bit system.
6616349 Sparc-Get error "input not UTF-8" and (Abort)(core dumped) in sharemgr with Korean resource name
6622828 Resolve unreferenced makefiles
6626833 SUNWsmbsu package issues with snv_77.
6627415 SmbCreateTemporary fails on SPARC
6627469 Unable to map SIDs to names for Windows Vista clients
6627471 Remove winpipe door server from name space
6628747 smbd crash and in maintenance state
6629402 The adjoin operation triggered by smbadm join CLI shouldn't overwrite the Kerberos keytab file.
6629410 SMB daemon should remove its ccache on refresh or restart
6629428 smb daemon crashes at smb_nic_clear_niclist+0x45(815ff10, 2)
6629797 sharemgr: Deleting an SMB resource that has an option leads to core dump
6630470 Get core in sharemgr:libshare_smb.so.1`smb_enable_service+0x78(2ec90, fe87c49c, 0, ff396000,17e54,6)
--HG--
rename : usr/src/uts/common/smbsrv/smb_secdesc.h => deleted_files/usr/src/uts/common/smbsrv/smb_secdesc.h
132 files changed, 3710 insertions, 3414 deletions
diff --git a/usr/src/uts/common/smbsrv/smb_secdesc.h b/deleted_files/usr/src/uts/common/smbsrv/smb_secdesc.h index 68b890a8e4..68b890a8e4 100644 --- a/usr/src/uts/common/smbsrv/smb_secdesc.h +++ b/deleted_files/usr/src/uts/common/smbsrv/smb_secdesc.h diff --git a/usr/src/Targetdirs b/usr/src/Targetdirs index 1e2d094be2..a281b3ba1a 100644 --- a/usr/src/Targetdirs +++ b/usr/src/Targetdirs @@ -354,6 +354,7 @@ ROOT.BIN64= \ /usr/lib/sasl/$(MACH64) \ /usr/lib/secure/$(MACH64) \ /usr/lib/security/$(MACH64) \ + /usr/lib/smbsrv/$(MACH64) \ /usr/lib/abi/$(MACH64) \ /usr/sbin/$(MACH64) \ /usr/ucb/$(MACH64) \ diff --git a/usr/src/cmd/dfs.cmds/sharemgr/commands.c b/usr/src/cmd/dfs.cmds/sharemgr/commands.c index 0f75ef7ebf..3ba5cc892b 100644 --- a/usr/src/cmd/dfs.cmds/sharemgr/commands.c +++ b/usr/src/cmd/dfs.cmds/sharemgr/commands.c @@ -123,6 +123,7 @@ static char * conv_to_utf8(char *input) { iconv_t cd; + char *inval = input; char *output = input; char *outleft; char *curlocale; @@ -142,12 +143,16 @@ conv_to_utf8(char *input) output = calloc(bytesleft, 1); if (output != NULL) { outleft = output; - osize = iconv(cd, (const char **)&input, &size, + /* inval can be modified on return */ + osize = iconv(cd, (const char **)&inval, &size, &outleft, &bytesleft); if (osize == (size_t)-1 || size != 0) { free(output); output = input; } + } else { + /* Need to return something. */ + output = input; } (void) iconv_close(cd); } else { @@ -173,6 +178,7 @@ conv_from_utf8(char *input) { iconv_t cd; char *output = input; + char *inval = input; char *outleft; char *curlocale; size_t bytesleft; @@ -191,12 +197,13 @@ conv_from_utf8(char *input) output = calloc(bytesleft, 1); if (output != NULL) { outleft = output; - osize = iconv(cd, (const char **)&input, &size, + osize = iconv(cd, (const char **)&inval, &size, &outleft, &bytesleft); - if (osize == (size_t)-1 || size != 0) { - free(output); + if (osize == (size_t)-1 || size != 0) output = input; - } + } else { + /* Need to return something. */ + output = input; } (void) iconv_close(cd); } else { diff --git a/usr/src/cmd/smbsrv/Makefile.smbsrv.defs b/usr/src/cmd/smbsrv/Makefile.smbsrv.defs index b8d8d6694f..40089b387b 100644 --- a/usr/src/cmd/smbsrv/Makefile.smbsrv.defs +++ b/usr/src/cmd/smbsrv/Makefile.smbsrv.defs @@ -32,10 +32,12 @@ OBJS= $(SRCS:%.c=%.o) LDLIBS += -lumem -LDLIBS += -L$(ROOT)/usr/lib/smbsrv -lsmb +LDLIBS += -L$(ROOT)/usr/lib/smbsrv LDFLAGS += -R/usr/lib/smbsrv +LINTFLAGS += -xerroff=E_NAME_DEF_NOT_USED2 CFLAGS += $(CCVERBOSE) +$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG C99MODE = -xc99=%all C99LMODE = -Xc99=%all diff --git a/usr/src/cmd/smbsrv/dtrace/msrpc.d b/usr/src/cmd/smbsrv/dtrace/msrpc.d index 1869ae59bf..abf6497980 100755 --- a/usr/src/cmd/smbsrv/dtrace/msrpc.d +++ b/usr/src/cmd/smbsrv/dtrace/msrpc.d @@ -32,6 +32,57 @@ * On multi-processor systems, it may be easier to follow the output * if run on a single processor: see psradm. For example, to disable * the second processor on a dual-processor system: psradm -f 1 + * + * This script can be used to trace NDR operations and MSRPC requests. + * In order to put these operations in context, SMB session and tree + * requests are also traced. + * + * Output formatting is as follows: + * + * UI 03 ... rpc_vers get 1@0 = 5 {05} + * UI 03 ... rpc_vers_minor get 1@1 = 0 {00} + * + * U Marshalling flag (M=marshal, U=unmarshal) + * I Direction flag (I=in, O=out) + * ... Field name + * get PDU operation (get or put) + * 1@0 Bytes @ offset (i.e. 1 byte at offset 0) + * {05} Value + * + * The value formatting is limited to 10 bytes, after which an ellipsis + * will be inserted before the closing brace. If the value is 1 or 2 + * bytes, an attempt will be made to present an ASCII value but this may + * or may not be relevent. + * + * The following example shows the header from a bind response: + * + * trace:entry MO 03 ... rpc_vers put 1@0 = 5 {05} + * trace:entry MO 03 ... rpc_vers_minor put 1@1 = 0 {00} + * trace:entry MO 03 ... ptype put 1@2 = 12 {0c} + * trace:entry MO 03 ... pfc_flags put 1@3 = 3 {03} + * trace:entry MO 04 .... intg_char_rep put 1@4 = 16 {10} + * trace:entry MO 04 .... float_rep put 1@5 = 0 {00} + * trace:entry MO 04 .... _spare[0] put 1@6 = 0 {00} + * trace:entry MO 04 .... _spare[1] put 1@7 = 0 {00} + * trace:entry MO 03 ... frag_length put 2@8 = 68 {44 00} D + * trace:entry MO 03 ... auth_length put 2@10 = 0 {00 00} + * trace:entry MO 03 ... call_id put 4@12 = 1 {01 00 00 00} + * trace:entry MO 02 .. max_xmit_frag put 2@16 = 4280 {b8 10} + * trace:entry MO 02 .. max_recv_frag put 2@18 = 4280 {b8 10} + * trace:entry MO 02 .. assoc_group_id put 4@20 = 1192620711 {a7 f2 15 47} + * trace:entry MO 02 .. sec_addr.length put 2@24 = 12 {0c 00} + * trace:entry MO 02 .. sec_addr.port_spec[0] put 1@26 = 92 {5c} \ + * trace:entry MO 02 .. sec_addr.port_spec[1] put 1@27 = 80 {50} P + * trace:entry MO 02 .. sec_addr.port_spec[2] put 1@28 = 73 {49} I + * trace:entry MO 02 .. sec_addr.port_spec[3] put 1@29 = 80 {50} P + * trace:entry MO 02 .. sec_addr.port_spec[4] put 1@30 = 69 {45} E + * trace:entry MO 02 .. sec_addr.port_spec[5] put 1@31 = 92 {5c} \ + * trace:entry MO 02 .. sec_addr.port_spec[6] put 1@32 = 108 {6c} l + * trace:entry MO 02 .. sec_addr.port_spec[7] put 1@33 = 115 {73} s + * trace:entry MO 02 .. sec_addr.port_spec[8] put 1@34 = 97 {61} a + * trace:entry MO 02 .. sec_addr.port_spec[9] put 1@35 = 115 {73} s + * trace:entry MO 02 .. sec_addr.port_spec[10] put 1@36 = 115 {73} s + * trace:entry MO 02 .. sec_addr.port_spec[11] put 1@37 = 0 {00} */ /* @@ -128,7 +179,6 @@ pid$target::lsarpc_s_EnumPrivsAccount:entry, pid$target::lsarpc_s_LookupPrivValue:entry, pid$target::lsarpc_s_LookupPrivName:entry, pid$target::lsarpc_s_LookupPrivDisplayName:entry, -pid$target::lsarpc_s_Discovery:entry, pid$target::lsarpc_s_QueryInfoPolicy:entry, pid$target::lsarpc_s_OpenDomainHandle:entry, pid$target::lsarpc_s_OpenDomainHandle:entry, @@ -149,7 +199,6 @@ pid$target::lsarpc_s_EnumPrivsAccount:return, pid$target::lsarpc_s_LookupPrivValue:return, pid$target::lsarpc_s_LookupPrivName:return, pid$target::lsarpc_s_LookupPrivDisplayName:return, -pid$target::lsarpc_s_Discovery:return, pid$target::lsarpc_s_QueryInfoPolicy:return, pid$target::lsarpc_s_OpenDomainHandle:return, pid$target::lsarpc_s_OpenDomainHandle:return, @@ -298,3 +347,39 @@ pid$target::wkssvc_s_*:entry, pid$target::wkssvc_s_*:return { } + +/* + * SMBRDR + */ +pid$target::smbrdr_*:entry, +pid$target::smbrdr_*:return +{ +} + +pid$target::mlsvc_tree_connect:entry +{ + printf("%s %s %s", + copyinstr(arg0), + copyinstr(arg1), + copyinstr(arg2)); +} + +pid$target::mlsvc_open_pipe:entry +{ + printf("%s %s %s %s", + copyinstr(arg0), + copyinstr(arg1), + copyinstr(arg2), + copyinstr(arg3)); +} + +pid$target::mlsvc_close_pipe:entry +{ +} + +pid$target::mlsvc_tree_connect:return, +pid$target::mlsvc_open_pipe:return, +pid$target::mlsvc_close_pipe:return +{ + printf("%d", arg1); +} diff --git a/usr/src/cmd/smbsrv/smbadm/Makefile b/usr/src/cmd/smbsrv/smbadm/Makefile index 9bf78a75c2..067c05be88 100644 --- a/usr/src/cmd/smbsrv/smbadm/Makefile +++ b/usr/src/cmd/smbsrv/smbadm/Makefile @@ -31,6 +31,8 @@ SRCS= smbadm.c include ../../Makefile.cmd include ../Makefile.smbsrv.defs +LDLIBS += -lsmb + all: $(PROG) clean: diff --git a/usr/src/cmd/smbsrv/smbadm/smbadm.c b/usr/src/cmd/smbsrv/smbadm/smbadm.c index 98f61b2b9b..17cb3b8300 100644 --- a/usr/src/cmd/smbsrv/smbadm/smbadm.c +++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c @@ -1358,14 +1358,12 @@ smbadm_pwd_strerror(int error) * Enable libumem debugging by default on DEBUG builds. */ #ifdef DEBUG -/* LINTED - external libumem symbol */ const char * _umem_debug_init(void) { return ("default,verbose"); /* $UMEM_DEBUG setting */ } -/* LINTED - external libumem symbol */ const char * _umem_logging_init(void) { diff --git a/usr/src/cmd/smbsrv/smbd/Makefile b/usr/src/cmd/smbsrv/smbd/Makefile index 725ebf7a63..86a4cb2037 100644 --- a/usr/src/cmd/smbsrv/smbd/Makefile +++ b/usr/src/cmd/smbsrv/smbd/Makefile @@ -46,7 +46,7 @@ $(ROOTMANIFEST):= FILEMODE = 0444 include ../Makefile.smbsrv.defs -LDLIBS += -lmlsvc -lmlrpc -lsmbrdr -lsmbns -lbsm -lnsl -lsocket +LDLIBS += -lmlsvc -lmlrpc -lsmbrdr -lsmbns -lsmb -lbsm -lnsl -lsocket ROOTSMBDDIR = $(ROOTLIB)/smbsrv ROOTSMBDFILE = $(PROG:%=$(ROOTSMBDDIR)/%) diff --git a/usr/src/cmd/smbsrv/smbd/smbd.h b/usr/src/cmd/smbsrv/smbd/smbd.h index 27cd6f02e6..b3d448381e 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd.h +++ b/usr/src/cmd/smbsrv/smbd/smbd.h @@ -40,8 +40,8 @@ extern "C" { extern int smb_nicmon_start(void); extern void smb_nicmon_stop(void); -extern int smb_mlsvc_srv_start(void); -extern void smb_mlsvc_srv_stop(void); +extern int smb_winpipe_doorsvc_start(void); +extern void smb_winpipe_doorsvc_stop(void); extern int smb_lmshrd_srv_start(void); extern void smb_lmshrd_srv_stop(void); diff --git a/usr/src/cmd/smbsrv/smbd/smbd_door_server.c b/usr/src/cmd/smbsrv/smbd/smbd_door_server.c index 30f3e91e13..ebdc051b79 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_door_server.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_door_server.c @@ -262,6 +262,20 @@ smb_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp, smb_dr_put_int32(enc_ctx, rc); break; + case SMBD_DOOR_ADS_DOMAIN_CHANGED: + domain = smb_dr_get_string(dec_ctx); + dec_status = smb_dr_decode_finish(dec_ctx); + if (dec_status != 0) { + smb_dr_free_string(domain); + goto decode_error; + } + + rc = ads_domain_change_notify_handler(domain); + smb_dr_put_int32(enc_ctx, SMBD_DOOR_SRV_SUCCESS); + smb_dr_put_int32(enc_ctx, rc); + smb_dr_free_string(domain); + break; + default: goto decode_error; } diff --git a/usr/src/cmd/smbsrv/smbd/smbd_join.c b/usr/src/cmd/smbsrv/smbd/smbd_join.c index 425df10df8..90e4059abd 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_join.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c @@ -151,7 +151,7 @@ smbd_join(smb_joininfo_t *info) * the workstation trust account. */ (void) sleep(2); - status = mlsvc_validate_user(pi->server, pi->domain, + status = mlsvc_join(pi->server, pi->domain, plain_user, plain_passwd); if (status == NT_STATUS_SUCCESS) { diff --git a/usr/src/cmd/smbsrv/smbd/smbd_main.c b/usr/src/cmd/smbsrv/smbd/smbd_main.c index 740cc73837..d174aeb18e 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_main.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c @@ -62,7 +62,8 @@ #include "smbd.h" #define DRV_DEVICE_PATH "/devices/pseudo/smbsrv@0:smbsrv" -#define SMB_CACHEDIR "/var/run/smb" +#define SMB_VARRUN_DIR "/var/run/smb" +#define SMB_CCACHE SMB_VARRUN_DIR "/ccache" #define SMB_DBDIR "/var/smb" extern void smb_netbios_name_reconfig(); @@ -75,6 +76,7 @@ static int smbd_kernel_bind(void); static void smbd_kernel_unbind(void); static int smbd_already_running(void); +static void smbd_remove_ccache(void); static int smbd_service_init(void); static void smbd_service_fini(void); @@ -326,9 +328,10 @@ smbd_service_init(void) { static char *dir[] = { SMB_DBDIR, /* smbpasswd */ - SMB_CACHEDIR /* KRB credential cache */ + SMB_VARRUN_DIR /* KRB credential cache */ }; + int door_id; int rc; int ddns_enabled; uint32_t mode; @@ -349,7 +352,7 @@ smbd_service_init(void) /* * Set KRB5CCNAME (for the SMB credential cache) in the environment. */ - if (putenv("KRB5CCNAME=" SMB_CACHEDIR "/ccache") != 0) { + if (putenv("KRB5CCNAME=" SMB_CCACHE) != 0) { smbd_report("unable to set KRB5CCNAME"); return (1); } @@ -420,11 +423,6 @@ smbd_service_init(void) return (rc); } - if (rc = smb_mlsvc_srv_start()) { - smbd_report("msrpc door initialization failed: %d", rc); - return (rc); - } - if (smb_lmshrd_srv_start() != 0) { smbd_report("share initialization failed"); } @@ -450,9 +448,25 @@ smbd_service_init(void) (void) smbd_localtime_init(); + if ((door_id = smb_winpipe_doorsvc_start()) == -1) { + smbd_report("winpipe initialization failed %s", + strerror(errno)); + return (rc); + } else { + if (ioctl(smbd.s_drv_fd, SMB_IOC_WINPIPE, &door_id) < 0) + smbd_report("winpipe ioctl: %s", strerror(errno)); + } + return (lmshare_start()); } +static void +smbd_remove_ccache(void) +{ + if ((remove(SMB_CCACHE) < 0) && (errno != ENOENT)) + smbd_report("failed to remove SMB ccache"); +} + /* * Close the kernel service and shutdown smbd services. * This function is registered with atexit(): ensure that anything @@ -461,6 +475,7 @@ smbd_service_init(void) static void smbd_service_fini(void) { + smb_winpipe_doorsvc_stop(); nt_builtin_fini(); smbd_refresh_fini(); smbd_kernel_unbind(); @@ -468,10 +483,11 @@ smbd_service_fini(void) smb_doorsrv_stop(); smb_lmshrd_srv_stop(); lmshare_stop(); - smb_mlsvc_srv_stop(); smb_nicmon_stop(); smb_resolver_close(); smb_idmap_stop(); + smbd_remove_ccache(); + } /* @@ -539,7 +555,8 @@ smbd_refresh_monitor(void *arg) smb_nic_build_info(); (void) smb_netbios_name_reconfig(); (void) smb_browser_config(); - if (ioctl(smbd.s_drv_fd, SMB_IOC_CONFIG_REFRESH, &dummy) < 0) { + smbd_remove_ccache(); + if (ioctl(smbd.s_drv_fd, SMB_IOC_CONFIG, &dummy) < 0) { smbd_report("configuration update ioctl: %s", strerror(errno)); } @@ -742,14 +759,12 @@ smbd_report(const char *fmt, ...) * Enable libumem debugging by default on DEBUG builds. */ #ifdef DEBUG -/* LINTED - external libumem symbol */ const char * _umem_debug_init(void) { return ("default,verbose"); /* $UMEM_DEBUG setting */ } -/* LINTED - external libumem symbol */ const char * _umem_logging_init(void) { diff --git a/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c index da39ac33c7..3ce7927215 100755 --- a/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c @@ -38,17 +38,59 @@ #include <pthread.h> #include <smbsrv/libsmb.h> - #include <smbsrv/ntsid.h> #include <smbsrv/mlsvc.h> #include <smbsrv/mlsvc_util.h> #include <smbsrv/smb_winpipe.h> -static int smb_updoor_id = -1; -static pthread_mutex_t smb_winpipe_user_mutex; +#define START_OUTDOOR_SIZE 65536 + +static int smb_winpipe_fd = -1; +static int smb_winpipe_cookie = 0x50495045; /* PIPE */ +static pthread_mutex_t smb_winpipe_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void smb_winpipe_request(void *, char *, size_t, door_desc_t *, uint_t); + +/* + * Create the winpipe door service. + * Returns the door descriptor on success. Otherwise returns -1. + */ +int +smb_winpipe_doorsvc_start(void) +{ + (void) pthread_mutex_lock(&smb_winpipe_mutex); + + if (smb_winpipe_fd != -1) { + (void) pthread_mutex_unlock(&smb_winpipe_mutex); + errno = EEXIST; + return (-1); + } -#define START_OUTDOOR_SIZE 65536 -#define MAX_INPIPE_LEN 65536 + errno = 0; + if ((smb_winpipe_fd = door_create(smb_winpipe_request, + &smb_winpipe_cookie, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) { + smb_winpipe_fd = -1; + } + + (void) pthread_mutex_unlock(&smb_winpipe_mutex); + return (smb_winpipe_fd); +} + +/* + * Stop the winpipe door service. + */ +void +smb_winpipe_doorsvc_stop(void) +{ + (void) pthread_mutex_lock(&smb_winpipe_mutex); + + if (smb_winpipe_fd != -1) { + (void) door_revoke(smb_winpipe_fd); + smb_winpipe_fd = -1; + } + + (void) pthread_mutex_unlock(&smb_winpipe_mutex); +} static smb_dr_user_ctx_t * smb_user_ctx_mkabsolute(uint8_t *buf, uint32_t len) @@ -85,9 +127,8 @@ smb_user_ctx_free(smb_dr_user_ctx_t *user_ctx) } /* - * Function: smb_mlsvc_door_server + * Winpipe door service request handler. * - * This is the userland winpipe door entry point. * Door arg data is a previously marshalled in to flat buffer * that contains no pointers. This data is first unmarshalled into * common structures. The data from the door *argp contains a header structure, @@ -99,35 +140,32 @@ smb_user_ctx_free(smb_dr_user_ctx_t *user_ctx) * rpc_ctx - some rpc context info such as domain, user account, ... * smb_pipe_t - pipeid, pipename, pipelen and data * - * After converting the data, mlsvc_rpc_process is called - * The returning outpipe contains the relevant data to be - * returned to the windows client. + * Convert the data and call mlrpc_process. The returned outpipe contains + * the relevant data to be returned to the client. * * Outgoing data must be marshalled again before returning. */ /*ARGSUSED*/ -void -smb_mlsvc_door_server(void *cookie, char *argp, size_t arg_size, +static void +smb_winpipe_request(void *cookie, char *argp, size_t arg_size, door_desc_t *dd, uint_t n_desc) { smb_pipe_t *inpipe = NULL; smb_pipe_t *outpipe = NULL; smb_pipe_t tmp_pipe; smb_dr_user_ctx_t *user_ctx = NULL; - uchar_t *bufp; + char *bufp; int bplen = 0; - int total_pipelen; mlsvc_door_hdr_t mdhin, mdhout; int tbytes = 0; int bytes_off = 0; struct mlsvc_rpc_context *context; - uchar_t *obuf = NULL; int current_out_len; uint32_t adj_len; char lfp[START_OUTDOOR_SIZE]; - bufp = (uchar_t *)argp; + bufp = argp; bcopy(bufp, &mdhin.md_tid, sizeof (uint64_t)); bytes_off = sizeof (uint64_t); bcopy(bufp+bytes_off, &mdhin.md_version, sizeof (uint16_t)); @@ -139,27 +177,16 @@ smb_mlsvc_door_server(void *cookie, char *argp, size_t arg_size, bcopy(bufp+bytes_off, &mdhin.md_reserved, sizeof (uint64_t)); bytes_off += sizeof (uint64_t); - /* flush is a special case, just free the buffers and return */ + /* + * Flush is a special case, just release the RPC context. + */ if (mdhin.md_call_type == SMB_RPC_FLUSH) { bcopy(bufp + bytes_off, &tmp_pipe.sp_pipeid, sizeof (uint32_t)); - context = mlsvc_lookup_context(tmp_pipe.sp_pipeid); - if (!context) { - syslog(LOG_ERR, "mds: Cannot lookup mlsvc context"); - goto zero_exit; - } - if (context->inpipe) { - free(context->inpipe); - context->inpipe = NULL; - } - if (context->outpipe) { - free(context->outpipe); - context->outpipe = NULL; - } - mlsvc_rpc_release(tmp_pipe.sp_pipeid); + mlrpc_release(tmp_pipe.sp_pipeid); goto zero_exit; } - user_ctx = smb_user_ctx_mkabsolute(bufp + bytes_off, + user_ctx = smb_user_ctx_mkabsolute((uchar_t *)bufp + bytes_off, arg_size - bytes_off); if (!user_ctx) { syslog(LOG_ERR, "mds: user_ctx_mkabsolute failed"); @@ -167,32 +194,27 @@ smb_mlsvc_door_server(void *cookie, char *argp, size_t arg_size, } tbytes += xdr_sizeof(xdr_smb_dr_user_ctx_t, user_ctx) + bytes_off; + bufp += tbytes; - bzero(tmp_pipe.sp_pipename, SMB_MAX_PIPENAMELEN); - bcopy(bufp + tbytes, tmp_pipe.sp_pipename, SMB_MAX_PIPENAMELEN); - bplen = SMB_MAX_PIPENAMELEN; - bcopy(bufp + tbytes + bplen, &tmp_pipe.sp_pipeid, sizeof (uint32_t)); - bplen += sizeof (uint32_t); - bcopy(bufp + tbytes + bplen, &tmp_pipe.sp_datalen, sizeof (uint32_t)); - bplen += sizeof (uint32_t); + bzero(&tmp_pipe, sizeof (smb_pipe_t)); + (void) strlcpy(tmp_pipe.sp_pipename, (char *)bufp, SMB_MAX_PIPENAMELEN); + bufp += SMB_MAX_PIPENAMELEN; + bcopy(bufp, &tmp_pipe.sp_pipeid, sizeof (uint32_t)); + bufp += sizeof (uint32_t); + bcopy(bufp, &tmp_pipe.sp_datalen, sizeof (uint32_t)); + bufp += sizeof (uint32_t); - total_pipelen = bplen + tmp_pipe.sp_datalen; - inpipe = malloc(total_pipelen); - if (! inpipe) { - syslog(LOG_ERR, "mds: resource shortage"); + if ((context = mlrpc_lookup(tmp_pipe.sp_pipeid)) == NULL) goto zero_exit; - } - (void) strlcpy(inpipe->sp_pipename, tmp_pipe.sp_pipename, - SMB_MAX_PIPENAMELEN); - inpipe->sp_pipeid = tmp_pipe.sp_pipeid; + + inpipe = context->inpipe; + (void) strcpy(inpipe->sp_pipename, tmp_pipe.sp_pipename); inpipe->sp_datalen = tmp_pipe.sp_datalen; - bcopy(bufp + tbytes + bplen, inpipe->sp_data, inpipe->sp_datalen); + bcopy(bufp, inpipe->sp_data, inpipe->sp_datalen); + + outpipe = context->outpipe; + (void) strcpy(outpipe->sp_pipename, "OUTPIPE"); - context = mlsvc_lookup_context(inpipe->sp_pipeid); - if (!context) { - syslog(LOG_ERR, "mds: Cannot lookup mlsvc context"); - goto zero_exit; - } adj_len = mdhin.md_length; /* * If RPC_TRANSACT, save len, set cookie to 0 and store @@ -201,64 +223,39 @@ smb_mlsvc_door_server(void *cookie, char *argp, size_t arg_size, * Clear the in context if we do. */ if ((mdhin.md_call_type == SMB_RPC_READ) && (context->inlen)) { - context->inpipe->sp_datalen = context->inlen; - if (context->inpipe->sp_pipeid != inpipe->sp_pipeid) { - syslog(LOG_DEBUG, "mds: RPC_READ pipeid mismatch !!"); + context = mlrpc_process(inpipe->sp_pipeid, user_ctx); + if (context == NULL) goto zero_exit; - } - (void) mlsvc_rpc_process(context->inpipe, &outpipe, user_ctx); + + context->inpipe->sp_datalen = context->inlen; context->inlen = 0; - free(context->inpipe); - context->inpipe = NULL; - /* - * if no outpipe yet, initialize it - */ - if (!context->outpipe) { - context->outpipe = outpipe; - context->outcookie = 0; - context->outlen = outpipe->sp_datalen; - } + + context->outcookie = 0; + context->outlen = outpipe->sp_datalen; } + if (mdhin.md_call_type == SMB_RPC_TRANSACT) { - (void) mlsvc_rpc_process(inpipe, &outpipe, user_ctx); - /* - * init pipe context for subsequent calls - */ - context->outpipe = outpipe; + context = mlrpc_process(inpipe->sp_pipeid, user_ctx); + if (context == NULL) + goto zero_exit; + context->outcookie = 0; context->outlen = outpipe->sp_datalen; if (outpipe->sp_datalen < mdhin.md_length) adj_len = outpipe->sp_datalen; } + if (mdhin.md_call_type == SMB_RPC_WRITE) { - /* - * the first write we need to allocate - * the maximum inpipe len - */ - if (context->inlen == 0) { - context->inpipe = malloc(MAX_INPIPE_LEN); - } - if (! context->inpipe) { - syslog(LOG_ERR, "mds: ctx resource shortage"); - goto zero_exit; - } bcopy(inpipe->sp_data, context->inpipe->sp_data + context->inlen, inpipe->sp_datalen); /* * if we get another RPC_WRITE then we need to append */ context->inlen += inpipe->sp_datalen; - context->inpipe->sp_pipeid = inpipe->sp_pipeid; context->inpipe->sp_datalen = context->inlen; - (void) strlcpy(context->inpipe->sp_pipename, - inpipe->sp_pipename, SMB_MAX_PIPENAMELEN); - goto zero_exit; - } - obuf = malloc(START_OUTDOOR_SIZE); - if (! obuf) { - syslog(LOG_ERR, "mds: obuf resource shortage"); goto zero_exit; } + /* * check if this is the first transfer * pipe and cookie management @@ -267,40 +264,29 @@ smb_mlsvc_door_server(void *cookie, char *argp, size_t arg_size, if (context->outcookie >= context->outlen) { goto zero_exit; } else { + bufp = outpipe->sp_data + context->outcookie; + if (adj_len < (context->outlen - context->outcookie)) { - bcopy(context->outpipe->sp_data + - context->outcookie, obuf, adj_len); context->outcookie += adj_len; current_out_len = adj_len; } else { - bcopy(context->outpipe->sp_data + - context->outcookie, obuf, (context->outlen - - context->outcookie)); current_out_len = context->outlen - context->outcookie; context->outcookie = 0; - free(context->outpipe); - context->outpipe = NULL; } } - outpipe = malloc(START_OUTDOOR_SIZE); - if (! outpipe) { - syslog(LOG_ERR, "mds: outpipe resource shortage"); - goto zero_exit; - } } else { + bufp = outpipe->sp_data; + if (adj_len < context->outlen) { - bcopy(context->outpipe->sp_data, obuf, adj_len); context->outcookie += adj_len; current_out_len = adj_len; } else { - bcopy(context->outpipe->sp_data, obuf, context->outlen); current_out_len = context->outlen; context->outcookie = 0; - free(context->outpipe); - context->outpipe = NULL; } } + mdhout = mdhin; mdhout.md_tid = (uint64_t)getpid(); /* user process pid */ bytes_off = 0; @@ -316,9 +302,6 @@ smb_mlsvc_door_server(void *cookie, char *argp, size_t arg_size, bytes_off += sizeof (uint64_t); tbytes = 0; tbytes = bytes_off; - bzero(outpipe->sp_pipename, SMB_MAX_PIPENAMELEN); - (void) strcpy(outpipe->sp_pipename, "OUTPIPE"); - outpipe->sp_pipeid = inpipe->sp_pipeid; bcopy(outpipe->sp_pipename, lfp + tbytes, SMB_MAX_PIPENAMELEN); bplen = SMB_MAX_PIPENAMELEN; bcopy(&(outpipe->sp_pipeid), lfp + tbytes + bplen, sizeof (uint32_t)); @@ -327,97 +310,13 @@ smb_mlsvc_door_server(void *cookie, char *argp, size_t arg_size, bcopy(&(current_out_len), lfp + tbytes + bplen, sizeof (uint32_t)); bplen += sizeof (uint32_t); - bcopy(obuf, lfp + tbytes + bplen, current_out_len); + bcopy(bufp, lfp + tbytes + bplen, current_out_len); tbytes += bplen + current_out_len; smb_user_ctx_free(user_ctx); - free(obuf); - free(inpipe); (void) door_return((char *)lfp, tbytes, NULL, 0); /*NOTREACHED*/ zero_exit: smb_user_ctx_free(user_ctx); - - if (obuf) - free(obuf); - if (inpipe) - free(inpipe); - (void) door_return(0, 0, NULL, 0); } - -/* - * smb_mlsvc_srv_start - * - * Start the mlsvc door service. - */ -int -smb_mlsvc_srv_start() -{ - int newfd; - - (void) pthread_mutex_lock(&smb_winpipe_user_mutex); - - if (smb_updoor_id != -1) { - (void) fprintf(stderr, "smb_mlsvc_srv_start: duplicate"); - (void) pthread_mutex_unlock(&smb_winpipe_user_mutex); - return (-1); - } - - errno = 0; - if ((smb_updoor_id = door_create(smb_mlsvc_door_server, 0, 0)) < 0) { - (void) fprintf(stderr, "smb_mlsvc_srv_start: door_create: %s", - strerror(errno)); - smb_updoor_id = -1; - (void) pthread_mutex_unlock(&smb_winpipe_user_mutex); - return (-1); - } - - (void) unlink(SMB_WINPIPE_DOOR_UP_PATH); - - if ((newfd = creat(SMB_WINPIPE_DOOR_UP_PATH, 0644)) < 0) { - (void) fprintf(stderr, "smb_mlsvc_srv_start: open: %s", - strerror(errno)); - (void) door_revoke(smb_updoor_id); - smb_updoor_id = -1; - (void) pthread_mutex_unlock(&smb_winpipe_user_mutex); - return (-1); - } - - (void) close(newfd); - (void) fdetach(SMB_WINPIPE_DOOR_UP_PATH); - - if (fattach(smb_updoor_id, SMB_WINPIPE_DOOR_UP_PATH) < 0) { - (void) fprintf(stderr, "smb_mlsvc_srv_start: fattach: %s", - strerror(errno)); - (void) door_revoke(smb_updoor_id); - smb_updoor_id = -1; - (void) pthread_mutex_unlock(&smb_winpipe_user_mutex); - return (-1); - } - - (void) pthread_mutex_unlock(&smb_winpipe_user_mutex); - return (0); -} - -/* - * smb_mlsvc_srv_stop - * - * Stop the mlsvc door service. - * We will eventually call this based on some signals - * No one calls this just yet, if the process dies all this stuff happens - * by default - */ -void -smb_mlsvc_srv_stop() -{ - (void) pthread_mutex_lock(&smb_winpipe_user_mutex); - - if (smb_updoor_id != -1) { - (void) fdetach(SMB_WINPIPE_DOOR_UP_PATH); - (void) door_revoke(smb_updoor_id); - smb_updoor_id = -1; - } - - (void) pthread_mutex_unlock(&smb_winpipe_user_mutex); -} diff --git a/usr/src/cmd/smbsrv/smbstat/Makefile b/usr/src/cmd/smbsrv/smbstat/Makefile index 1bb8b73737..c44c076464 100644 --- a/usr/src/cmd/smbsrv/smbstat/Makefile +++ b/usr/src/cmd/smbsrv/smbstat/Makefile @@ -34,6 +34,6 @@ OBJS= $(SRCS:%.c=%.o) include ../Makefile.smbsrv.defs -LDLIBS = -lumem -lkstat +LDLIBS += -lkstat include ../Makefile.smbsrv.targ include ../../Makefile.targ diff --git a/usr/src/cmd/smbsrv/smbstat/smbstat.c b/usr/src/cmd/smbsrv/smbstat/smbstat.c index b2c4bab4a7..9a4406f025 100644 --- a/usr/src/cmd/smbsrv/smbstat/smbstat.c +++ b/usr/src/cmd/smbsrv/smbstat/smbstat.c @@ -267,14 +267,12 @@ smbstat_kstat_read(kstat_ctl_t *kc, kstat_t *ksp, void *data) * Enable libumem debugging by default on DEBUG builds. */ #ifdef DEBUG -/* LINTED - external libumem symbol */ const char * _umem_debug_init(void) { return ("default,verbose"); /* $UMEM_DEBUG setting */ } -/* LINTED - external libumem symbol */ const char * _umem_logging_init(void) { diff --git a/usr/src/common/smbsrv/smb_native.c b/usr/src/common/smbsrv/smb_native.c index bd88cc5427..9032042c57 100644 --- a/usr/src/common/smbsrv/smb_native.c +++ b/usr/src/common/smbsrv/smb_native.c @@ -90,6 +90,13 @@ smbnative_os_value(char *native_os) return (NATIVE_OS_UNKNOWN); } + if (*native_os == '\0') { + /* + * Windows Vista sends an empty native OS string. + */ + return (NATIVE_OS_WIN2000); + } + for (i = 0; i < sizeof (os_table)/sizeof (os_table[0]); ++i) { os_name = os_table[i].os_name; len = strlen(os_name); @@ -156,6 +163,13 @@ smbnative_lm_value(char *native_lm) return (NATIVE_LM_NONE); } + if (*native_lm == '\0') { + /* + * Windows Vista sends an empty native LM string. + */ + return (NATIVE_LM_WIN2000); + } + for (i = 0; i < sizeof (lm_table)/sizeof (lm_table[0]); ++i) { lm_name = lm_table[i].lm_name; len = strlen(lm_name); diff --git a/usr/src/common/smbsrv/smb_utf8.c b/usr/src/common/smbsrv/smb_utf8.c index 704f01877e..4cdc44bee1 100644 --- a/usr/src/common/smbsrv/smb_utf8.c +++ b/usr/src/common/smbsrv/smb_utf8.c @@ -62,8 +62,6 @@ #include <smbsrv/smb_i18n.h> #include <smbsrv/string.h> -int mbtowc_verbose = 0; -int mbtowc_announce = 0; /* * mbstowcs @@ -109,8 +107,14 @@ mts_mbstowcs(mts_wchar_t *wcstring, const char *mbstring, size_t nwchars) * by wcharp. Up to nbytes bytes are examined. * * If mbchar is NULL, mbtowc() returns zero to indicate that shift - * states are not supported. If mbchar is valid, returns the number - * of bytes processed in mbchar. If mbchar is invalid, returns -1. + * states are not supported. Shift states are used to switch between + * representation modes using reserved bytes to signal shifting + * without them being interpreted as characters. If mbchar is null + * mbtowc should return non-zero if the current locale requires shift + * states. Otherwise it should be return 0. + * + * If mbchar is non-null, returns the number of bytes processed in + * mbchar. If mbchar is invalid, returns -1. */ int /*ARGSUSED*/ mts_mbtowc(mts_wchar_t *wcharp, const char *mbchar, size_t nbytes) @@ -120,8 +124,8 @@ mts_mbtowc(mts_wchar_t *wcharp, const char *mbchar, size_t nbytes) int count; int bytes_left; - if (mbchar == 0) - return (0); /* shift states not supported */ + if (mbchar == NULL) + return (0); /* no shift states */ /* 0xxxxxxx -> 1 byte ASCII encoding */ if (((mbyte = *mbchar++) & 0x80) == 0) { @@ -132,12 +136,8 @@ mts_mbtowc(mts_wchar_t *wcharp, const char *mbchar, size_t nbytes) } /* 10xxxxxx -> invalid first byte */ - if ((mbyte & 0x40) == 0) { - if (mbtowc_verbose || mbtowc_announce == 0) { - mbtowc_announce = 1; - } + if ((mbyte & 0x40) == 0) return (-1); - } wide_char = mbyte; if ((mbyte & 0x20) == 0) { @@ -147,20 +147,13 @@ mts_mbtowc(mts_wchar_t *wcharp, const char *mbchar, size_t nbytes) wide_char &= 0x0f; bytes_left = 2; } else { - if (mbtowc_verbose || mbtowc_announce == 0) { - mbtowc_announce = 1; - } return (-1); } count = 1; while (bytes_left--) { - if (((mbyte = *mbchar++) & 0xc0) != 0x80) { - if (mbtowc_verbose || mbtowc_announce == 0) { - mbtowc_announce = 1; - } + if (((mbyte = *mbchar++) & 0xc0) != 0x80) return (-1); - } count++; wide_char = (wide_char << 6) | (mbyte & 0x3f); @@ -185,10 +178,6 @@ mts_mbtowc(mts_wchar_t *wcharp, const char *mbchar, size_t nbytes) int mts_wctomb(char *mbchar, mts_wchar_t wchar) { -#ifdef UTF8_DEBUG - char *start = mbchar; -#endif - if ((wchar & ~0x7f) == 0) { *mbchar = (char)wchar; return (1); @@ -228,7 +217,7 @@ mts_wcstombs(char *mbstring, const mts_wchar_t *wcstring, size_t nbytes) char buf[4]; size_t len; - if ((mbstring == 0) || (wcstring == 0)) + if ((mbstring == NULL) || (wcstring == NULL)) return (0); while (nbytes > MTS_MB_CHAR_MAX) { @@ -388,7 +377,7 @@ mts_mbstos(char *string, const char *mbstring) unsigned char *start = (unsigned char *)string; int len; - if (string == 0 || mbstring == 0) + if (string == NULL || mbstring == NULL) return (-1); while (*mbstring) { diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c index 49104b2abe..5716ef931c 100644 --- a/usr/src/lib/libshare/common/libshare.c +++ b/usr/src/lib/libshare/common/libshare.c @@ -217,6 +217,15 @@ sa_errorstr(int err) case SA_PATH_IS_PARENTDIR: ret = dgettext(TEXT_DOMAIN, "path is parent of a share"); break; + case SA_KRB_KEYTAB_ERR: + ret = dgettext(TEXT_DOMAIN, "unable to remove the old keys" + " from the Kerberos keytab. Please manually remove" + " the old keys for your host principal prior to setting" + " the ads_domain property"); + break; + case SA_NO_SERVICE: + ret = dgettext(TEXT_DOMAIN, "service is not running"); + break; default: (void) snprintf(errstr, sizeof (errstr), dgettext(TEXT_DOMAIN, "unknown %d"), err); @@ -3603,6 +3612,7 @@ sa_remove_resource(sa_resource_t resource) char *type; int ret = SA_OK; int transient = 0; + sa_optionset_t opt; share = sa_get_resource_parent(resource); type = sa_get_share_attr(share, "type"); @@ -3615,6 +3625,15 @@ sa_remove_resource(sa_resource_t resource) sa_free_attr_string(type); } + /* Disable the resource for all protocols. */ + (void) sa_disable_resource(resource, NULL); + + /* Remove any optionsets from the resource. */ + for (opt = sa_get_optionset(resource, NULL); + opt != NULL; + opt = sa_get_next_optionset(opt)) + (void) sa_destroy_optionset(opt); + /* Remove from the share */ xmlUnlinkNode((xmlNode *)resource); xmlFreeNode((xmlNode *)resource); diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h index bdac6a6d64..af6e2db2f8 100644 --- a/usr/src/lib/libshare/common/libshare.h +++ b/usr/src/lib/libshare/common/libshare.h @@ -85,6 +85,8 @@ typedef void *sa_handle_t; /* opaque handle to access core functions */ #define SA_MULTIPLE_ERROR 26 /* multiple protocols reported error */ #define SA_PATH_IS_SUBDIR 27 /* check_path found path is subdir */ #define SA_PATH_IS_PARENTDIR 28 /* check_path found path is parent */ +#define SA_KRB_KEYTAB_ERR 29 /* fail to delete old keytab entries */ +#define SA_NO_SERVICE 30 /* service isn't running */ /* API Initialization */ #define SA_INIT_SHARE_API 0x0001 /* init share specific interface */ diff --git a/usr/src/lib/libshare/common/scfutil.c b/usr/src/lib/libshare/common/scfutil.c index 344d3729bb..1c35d7d151 100644 --- a/usr/src/lib/libshare/common/scfutil.c +++ b/usr/src/lib/libshare/common/scfutil.c @@ -790,8 +790,9 @@ sa_share_props_from_pgroup(xmlNodePtr root, scfutilhandle_t *handle, node = xmlNewChild(resource, NULL, (xmlChar *)"optionset", NULL); } else { - /* this shouldn't happen */ + /* This shouldn't happen. */ ret = SA_SYSTEM_ERR; + goto out; } } else { /* diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c index aa30b46352..9aa98e9a37 100644 --- a/usr/src/lib/libshare/smb/libshare_smb.c +++ b/usr/src/lib/libshare/smb/libshare_smb.c @@ -84,6 +84,7 @@ static int smb_enable_resource(sa_resource_t); static int smb_disable_resource(sa_resource_t); static uint64_t smb_share_features(void); static int smb_list_transient(sa_handle_t); +static int smb_domain_change_event(char *new_domain); /* size of basic format allocation */ #define OPT_CHUNK 1024 @@ -1037,6 +1038,7 @@ smb_enable_service(void) (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "%s failed to restart: %s\n"), + SMBD_DEFAULT_INSTANCE_FMRI, scf_strerror(scf_error())); return (SA_CONFIG_ERR); } @@ -1077,6 +1079,45 @@ smb_validate_proto_prop(int index, char *name, char *value) } /* + * smb_domain_change_event + * + * This function is called whenever ads_domain is changed via sharectl. + * It will make a door call to trigger the ADS domain change event. + */ +static int +smb_domain_change_event(char *new_domain) +{ + char *orig_domain; + int rc = SA_OK; + + orig_domain = smb_config_getenv(SMB_CI_ADS_DOMAIN); + if (orig_domain == NULL) + return (rc); + + if (strcasecmp(orig_domain, new_domain) == 0) { + free(orig_domain); + return (rc); + } + + if (!smb_isonline()) { + free(orig_domain); + return (SA_NO_SERVICE); + } + + /* + * Clear the ADS_HOST_INFO cache + * and remove old keys from the + * Kerberos keytab. + */ + if (smb_ads_domain_change_notify(orig_domain) != 0) + rc = SA_KRB_KEYTAB_ERR; + + free(orig_domain); + return (rc); +} + + +/* * smb_set_proto_prop(prop) * * check that prop is valid. @@ -1089,6 +1130,7 @@ smb_set_proto_prop(sa_property_t prop) char *name; char *value; int index = -1; + struct smb_proto_option_defs *opt; name = sa_get_property_attr(prop, "type"); value = sa_get_property_attr(prop, "value"); @@ -1098,25 +1140,29 @@ smb_set_proto_prop(sa_property_t prop) /* should test for valid value */ ret = smb_validate_proto_prop(index, name, value); if (ret == SA_OK) { + opt = &smb_proto_options[index]; + if ((opt->smb_index == SMB_CI_ADS_DOMAIN) && + (ret = smb_domain_change_event(value)) + != SA_OK) + goto cleanup; + /* Save to SMF */ - smb_config_setenv( - smb_proto_options[index].smb_index, value); + smb_config_setenv(opt->smb_index, value); /* * Specialized refresh mechanisms can * be flagged in the proto_options and * processed here. */ - if (smb_proto_options[index].refresh & - SMB_REFRESH_REFRESH) - (void) smf_refresh_instance( - SMBD_DEFAULT_INSTANCE_FMRI); - else if (smb_proto_options[index].refresh & - SMB_REFRESH_RESTART) + if (opt->refresh & SMB_REFRESH_REFRESH) + (void) smb_config_refresh(); + else if (opt->refresh & SMB_REFRESH_RESTART) (void) smf_restart_instance( SMBD_DEFAULT_INSTANCE_FMRI); } } } + +cleanup: if (name != NULL) sa_free_attr_string(name); if (value != NULL) diff --git a/usr/src/lib/smbsrv/Makefile.lib b/usr/src/lib/smbsrv/Makefile.lib index abd5776bc9..625bde45c4 100644 --- a/usr/src/lib/smbsrv/Makefile.lib +++ b/usr/src/lib/smbsrv/Makefile.lib @@ -28,12 +28,14 @@ # Common Makefile definitions for smbsrv. # -# We reset the Makefile.lib macros ROOTLIBDIR to refer to usr/lib/smbsrv -# We also install the userland library header files under /usr/include/smbsrv +# We reset the Makefile.lib macros ROOTLIBDIR to refer to usr/lib/smbsrv. +# For 64 bit, we reset ROOTLIBDIR64 to refer to usr/lib/smbsrv/$(MACH64). +# We also install the userland library header files under /usr/include/smbsrv. ROOTSMBHDRDIR= $(ROOTHDRDIR)/smbsrv ROOTSMBHDRS= $(HDRS:%=$(ROOTSMBHDRDIR)/%) ROOTLIBDIR = $(ROOT)/usr/lib/smbsrv +ROOTLIBDIR64 = $(ROOT)/usr/lib/smbsrv/$(MACH64) SRCDIR= ../common NDLDIR= $(ROOT)/usr/include/smbsrv/ndl @@ -41,8 +43,6 @@ LIBS= $(DYNLIB) $(LINTLIB) C99MODE = -xc99=%all C99LMODE = -Xc99=%all CPPFLAGS += -I$(SRCDIR) -I. -DYNFLAGS += -R/usr/lib/smbsrv -DYNFLAGS64 += -R/usr/lib/smbsrv/$(MACH64) LDLIBS32 += -L$(ROOT)/usr/lib/smbsrv LDLIBS64 += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) diff --git a/usr/src/lib/smbsrv/Makefile.smbsrv b/usr/src/lib/smbsrv/Makefile.smbsrv index 16d6ddfed1..aaa7149cbe 100644 --- a/usr/src/lib/smbsrv/Makefile.smbsrv +++ b/usr/src/lib/smbsrv/Makefile.smbsrv @@ -34,7 +34,7 @@ include ../../Makefile.lib include ../Makefile.lib SUBDIRS= $(MACH) -#$(BUILD64)SUBDIRS += $(MACH64) +$(BUILD64)SUBDIRS += $(MACH64) HDRDIR= common diff --git a/usr/src/lib/smbsrv/libmlrpc/Makefile.com b/usr/src/lib/smbsrv/libmlrpc/Makefile.com index 86c7672546..cc5ba2923f 100644 --- a/usr/src/lib/smbsrv/libmlrpc/Makefile.com +++ b/usr/src/lib/smbsrv/libmlrpc/Makefile.com @@ -46,6 +46,7 @@ include ../../Makefile.lib INCS += -I$(SRC)/common/smbsrv +LDLIBS += $(MACH_LDLIBS) LDLIBS += -lsmb -lc CPPFLAGS += $(INCS) -D_REENTRANT diff --git a/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile b/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile index a2f97019c8..b3c4916b0c 100644 --- a/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile +++ b/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile @@ -25,7 +25,11 @@ # ident "%Z%%M% %I% %E% SMI" # +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) + include ../Makefile.com include ../../../Makefile.lib.64 +DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) + install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers index 6858b4cea0..2f8fea95f3 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers @@ -36,6 +36,7 @@ SUNWprivate { mlrpc_c_bind; mlrpc_c_call; mlrpc_c_free_heap; + mlrpc_generic_call_stub; mlrpc_heap_avail; mlrpc_heap_create; mlrpc_heap_destroy; @@ -43,10 +44,12 @@ SUNWprivate { mlrpc_heap_mkvcs; mlrpc_heap_strsave; mlrpc_heap_used; + mlrpc_lookup; + mlrpc_process; mlrpc_register_service; - mlsvc_lookup_context; - mlsvc_rpc_process; - mlsvc_rpc_release; + mlrpc_release; + ndr_mbstowcs; + ndr_mbtowc; ndt__char; ndt_s_wchar; ndt__uchar; diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c b/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c index 6d13d459b3..e81225ede8 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c @@ -31,6 +31,7 @@ * complicated trees of data constructs between an RPC client and server. */ +#include <sys/byteorder.h> #include <strings.h> #include <assert.h> #include <string.h> @@ -1220,7 +1221,11 @@ mlndr_outer_string(struct ndr_reference *outer_ref) } first_is = 0; - length_is = size_is; + + if (mlnds->flags & MLNDS_F_NOTERM) + length_is = size_is - 1; + else + length_is = size_is; if (!mlndr_outer_poke_sizing(outer_ref, 0, &size_is) || !mlndr_outer_poke_sizing(outer_ref, 4, &first_is) || @@ -1929,12 +1934,9 @@ mlndr_s_wchar(struct ndr_reference *encl_ref) return (0); } else if (count == 0) { /* - * If the input char is 0, mts_mbtowc + * If the input char is 0, mbtowc * returns 0 without setting wide_char. - * I'm not sure if this is the correct - * behaviour for mts_mbtowc but for - * now we need to set wide_char to 0 - * and assume a count of 1. + * Set wide_char to 0 and a count of 1. */ wide_char = *valp; count = 1; @@ -1963,3 +1965,61 @@ mlndr_s_wchar(struct ndr_reference *encl_ref) return (1); } + +/* + * Converts a multibyte character string to a little-endian, wide-char + * string. No more than nwchars wide characters are stored. + * A terminating null wide character is appended if there is room. + * + * Returns the number of wide characters converted, not counting + * any terminating null wide character. Returns -1 if an invalid + * multibyte character is encountered. + */ +size_t +ndr_mbstowcs(struct mlndr_stream *mlnds, mts_wchar_t *wcs, const char *mbs, + size_t nwchars) +{ + mts_wchar_t *start = wcs; + int nbytes; + + while (nwchars--) { + nbytes = ndr_mbtowc(mlnds, wcs, mbs, MTS_MB_CHAR_MAX); + if (nbytes < 0) { + *wcs = 0; + return ((size_t)-1); + } + + if (*mbs == 0) + break; + + ++wcs; + mbs += nbytes; + } + + return (wcs - start); +} + +/* + * Converts a multibyte character to a little-endian, wide-char, which + * is stored in wcharp. Up to nbytes bytes are examined. + * + * If mbchar is valid, returns the number of bytes processed in mbchar. + * If mbchar is invalid, returns -1. See also mts_mbtowc(). + */ +/*ARGSUSED*/ +int +ndr_mbtowc(struct mlndr_stream *mlnds, mts_wchar_t *wcharp, + const char *mbchar, size_t nbytes) +{ + int rc; + + if ((rc = mts_mbtowc(wcharp, mbchar, nbytes)) < 0) + return (rc); + +#ifdef _BIG_ENDIAN + if (mlnds == NULL || NDR_MODE_MATCH(mlnds, NDR_MODE_RETURN_SEND)) + *wcharp = BSWAP_16(*wcharp); +#endif + + return (rc); +} diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c b/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c index 9bce9469ea..0f58231251 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c @@ -240,13 +240,12 @@ fault_exit: return (rc); } -int +void mlrpc_c_free_heap(struct mlrpc_binding *mbind, mlrpc_heapref_t *heapref) { struct mlrpc_client *mcli = mbind->context; (*mcli->xa_release)(mcli, heapref); - return (0); } static void diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c b/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c index a5bf41a617..2f442937be 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c @@ -29,6 +29,7 @@ * Server side RPC handler. */ +#include <sys/byteorder.h> #include <thread.h> #include <synch.h> #include <stdlib.h> @@ -37,6 +38,7 @@ #include <time.h> #include <smbsrv/libsmb.h> +#include <smbsrv/libmlrpc.h> #include <smbsrv/mlsvc.h> #include <smbsrv/ndr.h> #include <smbsrv/mlrpc.h> @@ -53,14 +55,14 @@ static unsigned long mlrpc_frag_size = MLRPC_FRAG_SZ; /* * Context table. */ +#define CTXT_PIPE_SZ 65536 #define CTXT_TABLE_ENTRIES 128 static struct mlsvc_rpc_context context_table[CTXT_TABLE_ENTRIES]; -static mutex_t mlsvc_context_lock; +static mutex_t mlrpc_context_lock; static int mlrpc_s_process(struct mlrpc_xaction *); static int mlrpc_s_bind(struct mlrpc_xaction *); static int mlrpc_s_request(struct mlrpc_xaction *); -static int mlrpc_generic_call_stub(struct mlrpc_xaction *); static void mlrpc_reply_prepare_hdr(struct mlrpc_xaction *); static int mlrpc_s_alter_context(struct mlrpc_xaction *); static void mlrpc_reply_bind_ack(struct mlrpc_xaction *); @@ -73,29 +75,27 @@ static int mlrpc_build_reply(struct mlrpc_xaction *); * structure as the client side but we don't need to set up the client * side info. */ -int -mlsvc_rpc_process(smb_pipe_t *inpipe, smb_pipe_t **outpipe, - smb_dr_user_ctx_t *user_ctx) +struct mlsvc_rpc_context * +mlrpc_process(int fid, smb_dr_user_ctx_t *user_ctx) { struct mlsvc_rpc_context *context; struct mlrpc_xaction *mxa; struct mlndr_stream *recv_mlnds; struct mlndr_stream *send_mlnds; unsigned char *pdu_base_addr; + char *data; int datalen; - if (inpipe == NULL || user_ctx == NULL) - return (-1); - - context = mlsvc_lookup_context(inpipe->sp_pipeid); - if (context == NULL) - return (-1); + if ((context = mlrpc_lookup(fid)) == NULL) + return (NULL); context->user_ctx = user_ctx; + data = context->inpipe->sp_data; + datalen = context->inpipe->sp_datalen; mxa = (struct mlrpc_xaction *)malloc(sizeof (struct mlrpc_xaction)); if (mxa == NULL) - return (-1); + return (NULL); bzero(mxa, sizeof (struct mlrpc_xaction)); mxa->context = context; @@ -103,30 +103,21 @@ mlsvc_rpc_process(smb_pipe_t *inpipe, smb_pipe_t **outpipe, if ((mxa->heap = mlrpc_heap_create()) == NULL) { free(mxa); - return (-1); + return (NULL); } recv_mlnds = &mxa->recv_mlnds; + (void) mlnds_initialize(recv_mlnds, datalen, NDR_MODE_CALL_RECV, + mxa->heap); - (void) mlnds_initialize(recv_mlnds, inpipe->sp_datalen, - NDR_MODE_CALL_RECV, mxa->heap); - - bcopy(inpipe->sp_data, recv_mlnds->pdu_base_addr, inpipe->sp_datalen); + bcopy(data, recv_mlnds->pdu_base_addr, datalen); send_mlnds = &mxa->send_mlnds; - (void) mlnds_initialize(send_mlnds, 0, - NDR_MODE_RETURN_SEND, mxa->heap); + (void) mlnds_initialize(send_mlnds, 0, NDR_MODE_RETURN_SEND, mxa->heap); (void) mlrpc_s_process(mxa); /* - * copy into outpipe - */ - datalen = send_mlnds->pdu_size_with_rpc_hdrs; - *outpipe = calloc(1, sizeof (smb_pipe_t) + datalen); - (*outpipe)->sp_datalen = datalen; - - /* * Different pointers for single frag vs multi frag responses. */ if (send_mlnds->pdu_base_addr_with_rpc_hdrs) @@ -134,12 +125,15 @@ mlsvc_rpc_process(smb_pipe_t *inpipe, smb_pipe_t **outpipe, else pdu_base_addr = send_mlnds->pdu_base_addr; - bcopy((char *)pdu_base_addr, (*outpipe)->sp_data, datalen); + datalen = send_mlnds->pdu_size_with_rpc_hdrs; + context->outpipe->sp_datalen = datalen; + bcopy(pdu_base_addr, context->outpipe->sp_data, datalen); + mlnds_destruct(&mxa->recv_mlnds); mlnds_destruct(&mxa->send_mlnds); mlrpc_heap_destroy(mxa->heap); free(mxa); - return (datalen); + return (context); } /* @@ -148,13 +142,13 @@ mlsvc_rpc_process(smb_pipe_t *inpipe, smb_pipe_t **outpipe, * context table is full, return a null pointer. */ struct mlsvc_rpc_context * -mlsvc_lookup_context(int fid) +mlrpc_lookup(int fid) { struct mlsvc_rpc_context *context; struct mlsvc_rpc_context *available = NULL; int i; - (void) mutex_lock(&mlsvc_context_lock); + (void) mutex_lock(&mlrpc_context_lock); for (i = 0; i < CTXT_TABLE_ENTRIES; ++i) { context = &context_table[i]; @@ -165,20 +159,33 @@ mlsvc_lookup_context(int fid) } if (context->fid == fid) { - (void) mutex_unlock(&mlsvc_context_lock); + (void) mutex_unlock(&mlrpc_context_lock); return (context); } } if (available) { bzero(available, sizeof (struct mlsvc_rpc_context)); + available->inpipe = malloc(CTXT_PIPE_SZ); + available->outpipe = malloc(CTXT_PIPE_SZ); + + if (available->inpipe == NULL || available->outpipe == NULL) { + free(available->inpipe); + free(available->outpipe); + bzero(available, sizeof (struct mlsvc_rpc_context)); + (void) mutex_unlock(&mlrpc_context_lock); + return (NULL); + } + available->fid = fid; + available->inpipe->sp_pipeid = fid; + available->outpipe->sp_pipeid = fid; mlrpc_binding_pool_initialize(&available->binding, available->binding_pool, CTXT_N_BINDING_POOL); } - (void) mutex_unlock(&mlsvc_context_lock); + (void) mutex_unlock(&mlrpc_context_lock); return (available); } @@ -187,23 +194,25 @@ mlsvc_lookup_context(int fid) * with a fid when the client performs a close file. */ void -mlsvc_rpc_release(int fid) +mlrpc_release(int fid) { struct mlsvc_rpc_context *context; int i; - (void) mutex_lock(&mlsvc_context_lock); + (void) mutex_lock(&mlrpc_context_lock); for (i = 0; i < CTXT_TABLE_ENTRIES; ++i) { context = &context_table[i]; if (context->fid == fid) { + free(context->inpipe); + free(context->outpipe); bzero(context, sizeof (struct mlsvc_rpc_context)); break; } } - (void) mutex_unlock(&mlsvc_context_lock); + (void) mutex_unlock(&mlrpc_context_lock); } /* @@ -509,7 +518,7 @@ mlrpc_s_request(struct mlrpc_xaction *mxa) * should already exist at this point. The heap will also be available * to the stub. */ -static int +int mlrpc_generic_call_stub(struct mlrpc_xaction *mxa) { struct mlrpc_binding *mbind = mxa->binding; @@ -775,11 +784,11 @@ mlrpc_build_reply(struct mlrpc_xaction *mxa) frag_data_size = frag_size - MLRPC_RSP_HDR_SIZE; num_ext_frags = pdu_data_size / frag_data_size; + /* - * if the outpipe is bigger than a frag_size, we need - * to stretch the pipe and insert an RPC header at each - * frag boundary. This outpipe gets chunked out in xdrlen - * sizes for each trans request + * We may need to stretch the pipe and insert an RPC header + * at each frag boundary. The response will get chunked into + * xdrlen sizes for each trans request. */ mlnds->pdu_base_addr_with_rpc_hdrs = malloc(pdu_size + (num_ext_frags * MLRPC_RSP_HDR_SIZE)); diff --git a/usr/src/lib/smbsrv/libmlrpc/i386/Makefile b/usr/src/lib/smbsrv/libmlrpc/i386/Makefile index f91f0270e9..710c9eb3dd 100644 --- a/usr/src/lib/smbsrv/libmlrpc/i386/Makefile +++ b/usr/src/lib/smbsrv/libmlrpc/i386/Makefile @@ -27,4 +27,6 @@ include ../Makefile.com +DYNFLAGS += -R/usr/lib/smbsrv + install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile b/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile index f91f0270e9..710c9eb3dd 100644 --- a/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile +++ b/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile @@ -27,4 +27,6 @@ include ../Makefile.com +DYNFLAGS += -R/usr/lib/smbsrv + install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile b/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile index a2f97019c8..b3c4916b0c 100644 --- a/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile +++ b/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile @@ -25,7 +25,11 @@ # ident "%Z%%M% %I% %E% SMI" # +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) + include ../Makefile.com include ../../../Makefile.lib.64 +DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) + install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libmlsvc/Makefile.com b/usr/src/lib/smbsrv/libmlsvc/Makefile.com index e0c1ee5c4c..60f0c4f66d 100644 --- a/usr/src/lib/smbsrv/libmlsvc/Makefile.com +++ b/usr/src/lib/smbsrv/libmlsvc/Makefile.com @@ -77,6 +77,7 @@ include ../../Makefile.lib INCS += -I$(SRC)/common/smbsrv +LDLIBS += $(MACH_LDLIBS) LDLIBS += -lmlrpc -lsmbrdr -lsmb -lsmbns -lshare -lnsl -lc SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \ diff --git a/usr/src/lib/smbsrv/libmlsvc/amd64/Makefile b/usr/src/lib/smbsrv/libmlsvc/amd64/Makefile index a2f97019c8..b3c4916b0c 100644 --- a/usr/src/lib/smbsrv/libmlsvc/amd64/Makefile +++ b/usr/src/lib/smbsrv/libmlsvc/amd64/Makefile @@ -25,7 +25,11 @@ # ident "%Z%%M% %I% %E% SMI" # +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) + include ../Makefile.com include ../../../Makefile.lib.64 +DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) + install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c index ca98eb8eab..8e2effc333 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c @@ -36,6 +36,7 @@ #include <smbsrv/libsmb.h> #include <smbsrv/libsmbns.h> #include <smbsrv/libmlsvc.h> +#include <smbsrv/libsmbrdr.h> #include <smbsrv/lsalib.h> #include <smbsrv/ntstatus.h> #include <smbsrv/smbinfo.h> @@ -60,8 +61,9 @@ lsa_query_primary_domain_info(void) { mlsvc_handle_t domain_handle; DWORD status; + char *user = smbrdr_ipc_get_user(); - if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0) + if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); status = lsar_query_info_policy(&domain_handle, @@ -87,8 +89,9 @@ lsa_query_account_domain_info(void) { mlsvc_handle_t domain_handle; DWORD status; + char *user = smbrdr_ipc_get_user(); - if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0) + if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); status = lsar_query_info_policy(&domain_handle, @@ -114,8 +117,9 @@ lsa_enum_trusted_domains(void) mlsvc_handle_t domain_handle; DWORD enum_context; DWORD status; + char *user = smbrdr_ipc_get_user(); - if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0) + if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); enum_context = 0; @@ -318,8 +322,9 @@ int lsa_lookup_name(char *server, char *domain, char *account_name, { mlsvc_handle_t domain_handle; int rc; + char *user = smbrdr_ipc_get_user(); - rc = lsar_open(MLSVC_IPC_ANON, server, domain, 0, 0, &domain_handle); + rc = lsar_open(server, domain, user, &domain_handle); if (rc != 0) return (-1); @@ -340,8 +345,9 @@ DWORD lsa_lookup_name2(char *server, char *domain, char *account_name, mlsvc_handle_t domain_handle; DWORD status; int rc; + char *user = smbrdr_ipc_get_user(); - rc = lsar_open(MLSVC_IPC_ANON, server, domain, 0, 0, &domain_handle); + rc = lsar_open(server, domain, user, &domain_handle); if (rc != 0) return (NT_STATUS_INVALID_PARAMETER); @@ -378,8 +384,9 @@ lsa_lookup_sid(nt_sid_t *sid, smb_userinfo_t *user_info) { mlsvc_handle_t domain_handle; int rc; + char *user = smbrdr_ipc_get_user(); - rc = lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle); + rc = lsar_open(NULL, NULL, user, &domain_handle); if (rc != 0) return (-1); @@ -401,8 +408,9 @@ lsa_lookup_sid2(nt_sid_t *sid, smb_userinfo_t *user_info) mlsvc_handle_t domain_handle; DWORD status; int rc; + char *user = smbrdr_ipc_get_user(); - rc = lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle); + rc = lsar_open(NULL, NULL, user, &domain_handle); if (rc != 0) return (NT_STATUS_INVALID_PARAMETER); @@ -479,30 +487,12 @@ lsa_lookup_privs(char *server, char *account_name, char *target_name, { mlsvc_handle_t domain_handle; int rc; -#if 0 - mlsvc_handle_t account_handle; - struct mslsa_sid *sid; - - lsa_lookup_name(0, 0, target_name, user_info); + char *user = smbrdr_ipc_get_user(); - sid = (struct mslsa_sid *) - nt_sid_splice(user_info->domain_sid, user_info->rid); - - lsa_lookup_sid(server, account_name, (nt_sid_t *)sid, user_info); -#endif - if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0) + if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0) return (-1); rc = lsa_list_accounts(&domain_handle); -#if 0 - rc = lsar_open_account(&domain_handle, sid, &account_handle); - if (rc == 0) { - (void) lsar_enum_privs_account(&account_handle, user_info); - (void) lsar_close(&account_handle); - } - - free(sid); -#endif (void) lsar_close(&domain_handle); return (rc); } @@ -523,8 +513,9 @@ lsa_list_privs(char *server, char *domain) mlsvc_handle_t domain_handle; int rc; int i; + char *user = smbrdr_ipc_get_user(); - rc = lsar_open(MLSVC_IPC_ANON, server, domain, 0, 0, &domain_handle); + rc = lsar_open(server, domain, user, &domain_handle); if (rc != 0) return (NT_STATUS_INVALID_PARAMETER); @@ -557,8 +548,9 @@ lsa_test(char *server, char *account_name) { mlsvc_handle_t domain_handle; int rc; + char *user = smbrdr_ipc_get_user(); - rc = lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle); + rc = lsar_open(NULL, NULL, user, &domain_handle); if (rc != 0) return (-1); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c index 57b1b62a97..10f77f49cf 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c @@ -49,48 +49,31 @@ * domain information if the caller didn't supply a server name and a * domain name. * + * If username argument is NULL, an anonymous connection will be established. + * Otherwise, an authenticated connection will be established. + * * On success 0 is returned. Otherwise a -ve error code. */ -int lsar_open(int ipc_mode, char *server, char *domain, char *username, - char *password, mlsvc_handle_t *domain_handle) +int lsar_open(char *server, char *domain, char *username, + mlsvc_handle_t *domain_handle) { smb_ntdomain_t *di; int remote_os; int remote_lm; int rc; - if ((di = smb_getdomaininfo(0)) == NULL) - return (-1); - if (server == NULL || domain == NULL) { - server = di->server; - domain = di->domain; - } + if ((di = smb_getdomaininfo(0)) == NULL) + return (-1); - switch (ipc_mode) { - case MLSVC_IPC_USER: - /* - * Use the supplied credentials. - */ - rc = mlsvc_user_logon(server, domain, username, password); - break; - - case MLSVC_IPC_ADMIN: - /* - * Use the resource domain administrator credentials. - */ server = di->server; domain = di->domain; - username = smbrdr_ipc_get_user(); + } - rc = mlsvc_admin_logon(server, domain); - break; + if (username == NULL) + username = MLSVC_ANON_USER; - case MLSVC_IPC_ANON: - default: - rc = mlsvc_anonymous_logon(server, domain, &username); - break; - } + rc = mlsvc_logon(server, domain, username); if (rc != 0) return (-1); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers index e05f51b279..a294b0ef2e 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers @@ -52,8 +52,8 @@ SUNWprivate { lsa_query_account_domain_info; lsa_enum_trusted_domains; mlsvc_init; - mlsvc_validate_user; mlsvc_is_local_domain; + mlsvc_join; nt_group_add; nt_group_add_groupprivs; nt_group_add_member_byname; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c index ac8cc3003c..de20a8c934 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c @@ -34,6 +34,8 @@ #include <smbsrv/libsmb.h> #include <smbsrv/libsmbrdr.h> +#include <smbsrv/ndr.h> +#include <smbsrv/mlrpc.h> #include <smbsrv/mlsvc_util.h> static int mlsvc_xa_init(struct mlrpc_client *, struct mlrpc_xaction *, diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c index 14c13a0315..4a6c80613d 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c @@ -200,7 +200,6 @@ static mts_wchar_t wcs_hostname[MAXHOSTNAMELEN]; static int hostname_len = 0; static mts_wchar_t wcs_srcname[MAX_SRCNAME_LEN]; static int srcname_len = 0; -static int str_offs, sh_len; /* * logr_initialize @@ -214,6 +213,7 @@ logr_initialize(void) { struct utsname name; char *sysname; + int len; if (uname(&name) < 0) sysname = "Solaris"; @@ -221,6 +221,10 @@ logr_initialize(void) sysname = name.sysname; (void) strlcpy(logr_sysname, sysname, SYS_NMLN); + len = strlen(logr_sysname) + 1; + (void) mts_mbstowcs(wcs_srcname, logr_sysname, len); + srcname_len = len * sizeof (mts_wchar_t); + (void) mlrpc_register_service(&logr_service); } @@ -244,7 +248,7 @@ logr_s_EventLogClose(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_OK); } - data = (read_data_t *)(desc->discrim); + data = (read_data_t *)(uintptr_t)(desc->discrim); free(data); (void) mlsvc_put_handle((ms_handle_t *)¶m->handle); @@ -267,12 +271,16 @@ logr_s_EventLogOpen(void *arg, struct mlrpc_xaction *mxa) struct logr_EventLogOpen *param = arg; ms_handle_t *handle; int log_enable = 0; + int len; + int rc; smb_config_rdlock(); log_enable = smb_config_getyorn(SMB_CI_LOGR_ENABLE); smb_config_unlock(); - if (log_enable == 0) { + rc = smb_gethostname(hostname, MAXHOSTNAMELEN, 1); + + if (log_enable == 0 || rc != 0) { bzero(¶m->handle, sizeof (logr_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); @@ -281,20 +289,9 @@ logr_s_EventLogOpen(void *arg, struct mlrpc_xaction *mxa) handle = mlsvc_get_handle(MLSVC_IFSPEC_LOGR, LOGR_KEY, 0); bcopy(handle, ¶m->handle, sizeof (logr_handle_t)); - if (hostname_len == 0) { - if (smb_gethostname(hostname, MAXHOSTNAMELEN, 1) != 0) { - bzero(¶m->handle, sizeof (logr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); - } - - hostname_len = (strlen(hostname) + 1) * 2; - (void) mts_mbstowcs(wcs_hostname, hostname, hostname_len / 2); - srcname_len = (strlen(logr_sysname) + 1) * 2; - (void) mts_mbstowcs(wcs_srcname, logr_sysname, srcname_len / 2); - sh_len = srcname_len + hostname_len; - str_offs = 12 * sizeof (DWORD) + 4 * sizeof (WORD) + sh_len; - } + len = strlen(hostname) + 1; + (void) mts_mbstowcs(wcs_hostname, hostname, len); + hostname_len = len * sizeof (mts_wchar_t); param->status = NT_STATUS_SUCCESS; return (MLRPC_DRC_OK); @@ -337,7 +334,7 @@ logr_s_EventLogQueryCount(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_OK); } - desc->discrim = (DWORD)data; + desc->discrim = (DWORD)(uintptr_t)data; param->rec_num = data->tot_recnum; param->status = NT_STATUS_SUCCESS; return (MLRPC_DRC_OK); @@ -362,7 +359,7 @@ logr_s_EventLogGetOldestRec(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_OK); } - data = (read_data_t *)desc->discrim; + data = (read_data_t *)(uintptr_t)desc->discrim; param->oldest_rec = data->log.ix - data->tot_recnum; param->status = NT_STATUS_SUCCESS; return (MLRPC_DRC_OK); @@ -413,8 +410,13 @@ log_get_entry(struct log_info *linfo, int entno) static void set_logrec(log_entry_t *le, DWORD recno, logr_record_t *rec) { + int str_offs; + int sh_len; int len; + sh_len = srcname_len + hostname_len; + str_offs = 12 * sizeof (DWORD) + 4 * sizeof (WORD) + sh_len; + rec->Length1 = sizeof (logr_record_t); rec->Reserved = 0x654C664C; rec->RecordNumber = recno; @@ -469,14 +471,14 @@ logr_s_EventLogRead(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_OK); } - rdata = (read_data_t *)(desc->discrim); + rdata = (read_data_t *)(uintptr_t)(desc->discrim); if (rdata == 0) { if ((rdata = logr_get_snapshot()) == NULL) { param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); return (MLRPC_DRC_OK); } - desc->discrim = (DWORD)rdata; + desc->discrim = (DWORD)(uintptr_t)rdata; } dir = (param->read_flags & EVENTLOG_FORWARDS_READ) ? FWD : REW; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c index 6aa4d716fe..4d770edbc1 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c @@ -36,6 +36,7 @@ #include <grp.h> #include <smbsrv/libsmb.h> +#include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/mlsvc_util.h> #include <smbsrv/ndl/lsarpc.ndl> @@ -53,6 +54,8 @@ struct local_group_table { char *name; }; +static int lsarpc_call_stub(struct mlrpc_xaction *mxa); + static int lsarpc_s_CloseHandle(void *arg, struct mlrpc_xaction *); static int lsarpc_s_QuerySecurityObject(void *arg, struct mlrpc_xaction *); static int lsarpc_s_EnumAccounts(void *arg, struct mlrpc_xaction *); @@ -117,9 +120,9 @@ static mlrpc_service_t lsarpc_service = { "12345778-1234-abcd-ef000123456789ab", 0, /* abstract */ "8a885d04-1ceb-11c9-9fe808002b104860", 2, /* transfer */ 0, /* no bind_instance_size */ - 0, /* no bind_req() */ - 0, /* no unbind_and_close() */ - 0, /* use generic_call_stub() */ + NULL, /* no bind_req() */ + NULL, /* no unbind_and_close() */ + lsarpc_call_stub, /* call_stub() */ &TYPEINFO(lsarpc_interface), /* interface ti */ lsarpc_stub_table /* stub_table */ }; @@ -135,9 +138,9 @@ static mlrpc_service_t lsarpc_w2k_service = { "3919286a-b10c-11d0-9ba800c04fd92ef5", 0, /* abstract */ "8a885d04-1ceb-11c9-9fe808002b104860", 2, /* transfer */ 0, /* no bind_instance_size */ - 0, /* no bind_req() */ - 0, /* no unbind_and_close() */ - 0, /* use generic_call_stub() */ + NULL, /* no bind_req() */ + NULL, /* no unbind_and_close() */ + lsarpc_call_stub, /* call_stub() */ &TYPEINFO(lsarpc_interface), /* interface ti */ lsarpc_stub_table /* stub_table */ }; @@ -159,6 +162,18 @@ lsarpc_initialize(void) } /* + * Custom call_stub to set the stream string policy. + */ +static int +lsarpc_call_stub(struct mlrpc_xaction *mxa) +{ + MLNDS_SETF(&mxa->send_mlnds, MLNDS_F_NOTERM); + MLNDS_SETF(&mxa->recv_mlnds, MLNDS_F_NOTERM); + + return (mlrpc_generic_call_stub(mxa)); +} + +/* * lsarpc_s_OpenDomainHandle opnum=0x06 * * This is a request to open the LSA (OpenPolicy and OpenPolicy2). diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c index 3b51c05e71..6d22e62127 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c @@ -36,6 +36,7 @@ #include <grp.h> #include <smbsrv/libsmb.h> +#include <smbsrv/libmlrpc.h> #include <smbsrv/ntstatus.h> #include <smbsrv/ntsid.h> #include <smbsrv/smbinfo.h> @@ -66,6 +67,8 @@ #define SAMR_BUILTIN_DOMAIN 0x80000003 #define SAMR_PRIMARY_DOMAIN 0x80000004 +static int samr_call_stub(struct mlrpc_xaction *mxa); + static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *, struct mlrpc_xaction *); @@ -79,9 +82,9 @@ static mlrpc_service_t samr_service = { "12345778-1234-abcd-ef000123456789ac", 1, /* abstract */ "8a885d04-1ceb-11c9-9fe808002b104860", 2, /* transfer */ 0, /* no bind_instance_size */ - 0, /* no bind_req() */ - 0, /* no unbind_and_close() */ - 0, /* use generic_call_stub() */ + NULL, /* no bind_req() */ + NULL, /* no unbind_and_close() */ + samr_call_stub, /* call_stub() */ &TYPEINFO(samr_interface), /* interface ti */ samr_stub_table /* stub_table */ }; @@ -100,6 +103,18 @@ samr_initialize(void) } /* + * Custom call_stub to set the stream string policy. + */ +static int +samr_call_stub(struct mlrpc_xaction *mxa) +{ + MLNDS_SETF(&mxa->send_mlnds, MLNDS_F_NOTERM); + MLNDS_SETF(&mxa->recv_mlnds, MLNDS_F_NOTERM); + + return (mlrpc_generic_call_stub(mxa)); +} + +/* * samr_s_ConnectAnon * * This is a request to connect to the local SAM database. We don't @@ -435,7 +450,7 @@ samr_s_QueryDomainInfo(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_FAULT_REQUEST_OPNUM_INVALID); }; - param->address = (DWORD)¶m->ru; + param->address = (DWORD)(uintptr_t)¶m->ru; param->switch_value = param->info_level; return (MLRPC_DRC_OK); } @@ -1140,7 +1155,7 @@ samr_s_QueryAliasInfo(void *arg, struct mlrpc_xaction *mxa) goto query_alias_err; }; - param->address = (DWORD)¶m->ru; + param->address = (DWORD)(uintptr_t)¶m->ru; param->status = 0; return (MLRPC_DRC_OK); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c index 2a9a1f52d0..26cd32ac5d 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c @@ -512,7 +512,8 @@ srvsvc_s_NetShareSetInfo(void *arg, struct mlrpc_xaction *mxa) struct mlsm_NetShareSetInfo *param = arg; (void) memset(param, 0, sizeof (struct mlsm_NetShareSetInfo)); - param->parm_err_ptr = (DWORD)MLRPC_HEAP_MALLOC(mxa, sizeof (DWORD)); + param->parm_err_ptr = (DWORD)(uintptr_t)MLRPC_HEAP_MALLOC(mxa, + sizeof (DWORD)); param->parm_err = 0; smb_config_rdlock(); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c index 29cd3f058a..81e3893781 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c @@ -377,32 +377,15 @@ mlsvc_setadmin_user_info(smb_userinfo_t *user_info) int mlsvc_string_save(ms_string_t *ms, char *str, struct mlrpc_xaction *mxa) { - int length; - char *p; - - if (ms == NULL || str == NULL || mxa == NULL) + if (str == NULL) return (0); - /* - * Windows NT expects the name length to exclude the - * terminating wchar null but doesn't care whether or - * not the allosize includes it. Windows 2000 insists - * that both the length and the allosize include the - * wchar null. - */ - length = mts_wcequiv_strlen(str); - ms->allosize = length + sizeof (mts_wchar_t); - - if (mxa->context->user_ctx->du_native_os == NATIVE_OS_WIN2000) - ms->length = ms->allosize; - else - ms->length = length; + ms->length = mts_wcequiv_strlen(str); + ms->allosize = ms->length + sizeof (mts_wchar_t); - if ((p = MLRPC_HEAP_STRSAVE(mxa, str)) == NULL) { + if ((ms->str = MLRPC_HEAP_STRSAVE(mxa, str)) == NULL) return (0); - } - ms->str = (LPTSTR)p; return (1); } @@ -451,13 +434,12 @@ mlsvc_is_null_handle(mlsvc_handle_t *handle) } /* - * mlsvc_validate_user + * mlsvc_join * * Returns NT status codes. */ DWORD -mlsvc_validate_user(char *server, char *domain, char *plain_user, - char *plain_text) +mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) { smb_auth_info_t auth; smb_ntdomain_t *di; @@ -487,7 +469,7 @@ mlsvc_validate_user(char *server, char *domain, char *plain_user, return (status); } - erc = mlsvc_user_logon(server, domain, plain_user, plain_text); + erc = mlsvc_logon(server, domain, plain_user); if (erc == AUTH_USER_GRANT) { int isenabled; @@ -496,20 +478,12 @@ mlsvc_validate_user(char *server, char *domain, char *plain_user, isenabled = smb_config_getyorn(SMB_CI_ADS_ENABLE); smb_config_unlock(); if (isenabled) { - if (adjoin(machine_passwd, - sizeof (machine_passwd)) == ADJOIN_SUCCESS) { + if (ads_join(plain_user, plain_text, machine_passwd, + sizeof (machine_passwd)) == ADJOIN_SUCCESS) status = NT_STATUS_SUCCESS; - } else { + else status = NT_STATUS_UNSUCCESSFUL; - } } else { - /* - * Ensure that we don't have an old account in - * this domain. There's no need to check the - * return status. - */ - (void) sam_remove_trust_account(server, domain); - if (mlsvc_user_getauth(server, plain_user, &auth) != 0) { status = NT_STATUS_INVALID_PARAMETER; @@ -526,13 +500,8 @@ mlsvc_validate_user(char *server, char *domain, char *plain_user, } if (status == NT_STATUS_SUCCESS) { - smb_config_wrlock(); - if (smb_config_set(SMB_CI_MACHINE_PASSWD, - machine_passwd) != 0) { - smb_config_unlock(); + if (smb_set_machine_pwd(machine_passwd) != 0) return (NT_STATUS_UNSUCCESSFUL); - } - smb_config_unlock(); /* * If we successfully create a trust account, we mark diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c index bd2d5ee26f..9dd5696526 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c @@ -356,7 +356,7 @@ winreg_s_QueryValue(void *arg, struct mlrpc_xaction *mxa) pv->vc_first_is = 0; pv->vc_length_is = slen; /*LINTED E_BAD_PTR_CAST_ALIGN*/ - (void) mts_mbstowcs((mts_wchar_t *)pv->value, value, slen); + (void) ndr_mbstowcs(NULL, (mts_wchar_t *)pv->value, value, slen); *param->type = 1; *param->value_size = slen; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c index 2eb3e78bb7..1b26087fb8 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c @@ -40,6 +40,7 @@ #include <ctype.h> #include <smbsrv/libsmb.h> +#include <smbsrv/libsmbrdr.h> #include <smbsrv/mlsvc_util.h> #include <smbsrv/ndl/netlogon.ndl> #include <smbsrv/ntstatus.h> @@ -74,7 +75,7 @@ netlogon_auth(char *server, mlsvc_handle_t *netr_handle, DWORD flags) { netr_info_t *netr_info; int rc; - DWORD random_challenge[2]; + DWORD leout_rc[2]; netr_info = &netr_global_info; bzero(netr_info, sizeof (netr_info_t)); @@ -88,10 +89,9 @@ netlogon_auth(char *server, mlsvc_handle_t *netr_handle, DWORD flags) (void) snprintf(netr_info->server, sizeof (netr_info->server), "\\\\%s", server); - random_challenge[0] = random(); - random_challenge[1] = random(); - - (void) memcpy(&netr_info->client_challenge, random_challenge, + LE_OUT32(&leout_rc[0], random()); + LE_OUT32(&leout_rc[1], random()); + (void) memcpy(&netr_info->client_challenge, leout_rc, sizeof (struct netr_credential)); if ((rc = netr_server_req_challenge(netr_handle, netr_info)) == 0) { @@ -118,12 +118,12 @@ netr_open(char *server, char *domain, mlsvc_handle_t *netr_handle) int remote_os = 0; int remote_lm = 0; int server_pdc; - char *username; + char *user = smbrdr_ipc_get_user(); - if (mlsvc_anonymous_logon(server, domain, &username) != 0) + if (mlsvc_logon(server, domain, user) != 0) return (-1); - fid = mlsvc_open_pipe(server, domain, username, "\\NETLOGON"); + fid = mlsvc_open_pipe(server, domain, user, "\\NETLOGON"); if (fid < 0) return (-1); @@ -293,7 +293,7 @@ netr_gen_session_key(netr_info_t *netr_info) DWORD *server_challenge; int rc; char *machine_passwd; - DWORD new_data[2]; + DWORD le_data[2]; client_challenge = (DWORD *)(uintptr_t)&netr_info->client_challenge; server_challenge = (DWORD *)(uintptr_t)&netr_info->server_challenge; @@ -324,10 +324,10 @@ netr_gen_session_key(netr_info_t *netr_info) data[0] = LE_IN32(&client_challenge[0]) + LE_IN32(&server_challenge[0]); data[1] = LE_IN32(&client_challenge[1]) + LE_IN32(&server_challenge[1]); - LE_OUT32(&new_data[0], data[0]); - LE_OUT32(&new_data[1], data[1]); + LE_OUT32(&le_data[0], data[0]); + LE_OUT32(&le_data[1], data[1]); - rc = smb_auth_DES(buffer, 8, md4hash, 8, (unsigned char *)new_data, 8); + rc = smb_auth_DES(buffer, 8, md4hash, 8, (unsigned char *)le_data, 8); if (rc != SMBAUTH_SUCCESS) return (rc); @@ -369,15 +369,19 @@ netr_gen_credentials(BYTE *session_key, netr_cred_t *challenge, unsigned char buffer[8]; unsigned char partial_key[8]; DWORD data[2]; + DWORD le_data[2]; DWORD *p; int rc; p = (DWORD *)(uintptr_t)challenge; - data[0] = p[0] + LE_IN32(×tamp); - data[1] = p[1]; + data[0] = LE_IN32(&p[0]) + timestamp; + data[1] = LE_IN32(&p[1]); + + LE_OUT32(&le_data[0], data[0]); + LE_OUT32(&le_data[1], data[1]); if (smb_auth_DES(buffer, 8, session_key, 8, - (unsigned char *)data, 8) != SMBAUTH_SUCCESS) + (unsigned char *)le_data, 8) != SMBAUTH_SUCCESS) return (SMBAUTH_FAILURE); bzero(partial_key, 8); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c index d26d6f0dc7..93079001e9 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c @@ -445,11 +445,7 @@ netr_setup_authenticator(netr_info_t *netr_info, { bzero(auth, sizeof (struct netr_authenticator)); -#ifdef _BIG_ENDIAN - netr_info->timestamp = 0; -#else - netr_info->timestamp = time(0) << 8; -#endif + netr_info->timestamp = time(0); auth->timestamp = netr_info->timestamp; if (netr_gen_credentials(netr_info->session_key, diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c index aa75c2678e..ef303a8b21 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c @@ -35,6 +35,7 @@ #include <alloca.h> #include <smbsrv/libsmb.h> +#include <smbsrv/libsmbrdr.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/ntstatus.h> #include <smbsrv/ntaccess.h> @@ -68,7 +69,7 @@ static int get_user_group_info(mlsvc_handle_t *, smb_userinfo_t *); */ int sam_lookup_user_info(char *server, char *domain_name, - char *account_name, char *password, smb_userinfo_t *user_info) + char *account_name, smb_userinfo_t *user_info) { mlsvc_handle_t samr_handle; mlsvc_handle_t domain_handle; @@ -86,35 +87,30 @@ sam_lookup_user_info(char *server, char *domain_name, return (-1); } - rc = samr_open(MLSVC_IPC_USER, server, domain_name, account_name, - password, SAM_LOOKUP_INFORMATION, &samr_handle); - if (rc != 0) - return (-1); -#if 0 - rc = samr_lookup_domain(&samr_handle, domain_name, user_info); + rc = samr_open(server, domain_name, account_name, + SAM_LOOKUP_INFORMATION, &samr_handle); if (rc != 0) return (-1); -#endif sid = (struct samr_sid *)user_info->domain_sid; status = samr_open_domain(&samr_handle, SAM_LOOKUP_INFORMATION, sid, &domain_handle); if (status == 0) { -#if 0 - (void) samr_lookup_domain_names(&domain_handle, account_name, - user_info); -#endif access_mask = STANDARD_RIGHTS_EXECUTE | SAM_ACCESS_USER_READ; - rc = samr_open_user(&domain_handle, access_mask, + status = samr_open_user(&domain_handle, access_mask, user_info->rid, &user_handle); - if (rc == 0) { + if (status == NT_STATUS_SUCCESS) { (void) get_user_group_info(&user_handle, user_info); (void) samr_close_handle(&user_handle); + } else { + rc = -1; } (void) samr_close_handle(&domain_handle); + } else { + rc = -1; } (void) samr_close_handle(&samr_handle); @@ -182,6 +178,18 @@ sam_create_trust_account(char *server, char *domain, smb_auth_info_t *auth) auth, SAMR_AF_WORKSTATION_TRUST_ACCOUNT, user_info); mlsvc_free_user_info(user_info); + + + /* + * Based on network traces, a Windows 2000 client will + * always try to create the computer account first. + * If it existed, then check the user permission to join + * the domain. + */ + + if (status == NT_STATUS_USER_EXISTS) + status = sam_check_user(server, domain, account_name); + return (status); } @@ -211,9 +219,10 @@ sam_create_account(char *server, char *domain_name, char *account_name, DWORD rid; DWORD status; int rc; + char *user = smbrdr_ipc_get_user(); - rc = samr_open(MLSVC_IPC_ADMIN, server, domain_name, 0, 0, - SAM_CONNECT_CREATE_ACCOUNT, &samr_handle); + rc = samr_open(server, domain_name, user, SAM_CONNECT_CREATE_ACCOUNT, + &samr_handle); if (rc != 0) { status = NT_STATUS_OPEN_FAILED; @@ -272,7 +281,6 @@ sam_create_account(char *server, char *domain_name, char *account_name, user_info); if (rc == 0) rid = user_info->rid; - status = 0; } else { smb_tracef("SamCreateAccount[%s]: %s", account_name, xlate_nt_status(status)); @@ -332,12 +340,13 @@ sam_delete_account(char *server, char *domain_name, char *account_name) DWORD access_mask; DWORD status; int rc; + char *user = smbrdr_ipc_get_user(); if ((user_info = mlsvc_alloc_user_info()) == 0) return (NT_STATUS_NO_MEMORY); - rc = samr_open(MLSVC_IPC_ADMIN, server, domain_name, 0, 0, - SAM_LOOKUP_INFORMATION, &samr_handle); + rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION, + &samr_handle); if (rc != 0) { mlsvc_free_user_info(user_info); @@ -379,9 +388,9 @@ sam_delete_account(char *server, char *domain_name, char *account_name) rid = user_info->rid; access_mask = STANDARD_RIGHTS_EXECUTE | DELETE; - rc = samr_open_user(&domain_handle, access_mask, + status = samr_open_user(&domain_handle, access_mask, rid, &user_handle); - if (rc == 0) { + if (status == NT_STATUS_SUCCESS) { if (samr_delete_user(&user_handle) != 0) (void) samr_close_handle(&user_handle); } @@ -396,6 +405,94 @@ sam_delete_account(char *server, char *domain_name, char *account_name) } /* + * sam_check_user + * + * Check to see if user have permission to access computer account. + * The user being checked is the specified user for joining the Solaris + * host to the domain. + */ +DWORD +sam_check_user(char *server, char *domain_name, char *account_name) +{ + mlsvc_handle_t samr_handle; + mlsvc_handle_t domain_handle; + mlsvc_handle_t user_handle; + smb_userinfo_t *user_info; + struct samr_sid *sid; + DWORD rid; + DWORD access_mask; + DWORD status; + int rc; + char *user = smbrdr_ipc_get_user(); + + if ((user_info = mlsvc_alloc_user_info()) == 0) + return (NT_STATUS_NO_MEMORY); + + rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION, + &samr_handle); + + if (rc != 0) { + mlsvc_free_user_info(user_info); + return (NT_STATUS_OPEN_FAILED); + } + + if (samr_handle.context->server_os == NATIVE_OS_WIN2000) { + nt_domain_t *ntdp; + + if ((ntdp = nt_domain_lookup_name(domain_name)) == 0) { + (void) lsa_query_account_domain_info(); + if ((ntdp = nt_domain_lookup_name(domain_name)) == 0) { + (void) samr_close_handle(&samr_handle); + return (NT_STATUS_NO_SUCH_DOMAIN); + } + } + + sid = (struct samr_sid *)ntdp->sid; + } else { + if (samr_lookup_domain(&samr_handle, domain_name, user_info) + != 0) { + (void) samr_close_handle(&samr_handle); + mlsvc_free_user_info(user_info); + return (NT_STATUS_NO_SUCH_DOMAIN); + } + + sid = (struct samr_sid *)user_info->domain_sid; + } + + status = samr_open_domain(&samr_handle, SAM_LOOKUP_INFORMATION, sid, + &domain_handle); + if (status == 0) { + mlsvc_release_user_info(user_info); + status = samr_lookup_domain_names(&domain_handle, account_name, + user_info); + + if (status == 0) { + rid = user_info->rid; + + /* + * Win2000 client uses this access mask. The + * following SAMR user specific rights bits are + * set: set password, set attributes, and get + * attributes. + */ + + access_mask = 0xb0; + + status = samr_open_user(&domain_handle, + access_mask, rid, &user_handle); + if (status == NT_STATUS_SUCCESS) + (void) samr_close_handle(&user_handle); + } + + (void) samr_close_handle(&domain_handle); + } + + (void) samr_close_handle(&samr_handle); + mlsvc_free_user_info(user_info); + return (status); +} + +/* * sam_lookup_name * * Lookup an account name in the SAM database on the specified domain @@ -413,14 +510,15 @@ sam_lookup_name(char *server, char *domain_name, char *account_name, struct samr_sid *domain_sid; int rc; DWORD status; + char *user = smbrdr_ipc_get_user(); *rid_ret = 0; if ((user_info = mlsvc_alloc_user_info()) == 0) return (NT_STATUS_NO_MEMORY); - rc = samr_open(MLSVC_IPC_ANON, server, domain_name, 0, 0, - SAM_LOOKUP_INFORMATION, &samr_handle); + rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION, + &samr_handle); if (rc != 0) { mlsvc_free_user_info(user_info); @@ -469,9 +567,10 @@ sam_get_local_domains(char *server, char *domain_name) mlsvc_handle_t samr_handle; DWORD status; int rc; + char *user = smbrdr_ipc_get_user(); - rc = samr_open(MLSVC_IPC_ANON, server, domain_name, 0, 0, - SAM_ENUM_LOCAL_DOMAIN, &samr_handle); + rc = samr_open(server, domain_name, user, SAM_ENUM_LOCAL_DOMAIN, + &samr_handle); if (rc != 0) return (NT_STATUS_OPEN_FAILED); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c index 7eccd83e22..e20b6404d7 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c @@ -523,7 +523,8 @@ samr_set_user_logon_hours(struct samr_SetUserInfo *sui) (void) memset(sui->logon_hours.bitmap, 0xFF, SAMR_SET_USER_HOURS_SZ); sui->info.ru.info23.logon_info.units = SAMR_HOURS_PER_WEEK; - sui->info.ru.info23.logon_info.hours = (DWORD)sui->logon_hours.bitmap; + sui->info.ru.info23.logon_info.hours = + (DWORD)(uintptr_t)sui->logon_hours.bitmap; } /* diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c index 38dca838cd..233acdf84d 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c @@ -66,50 +66,32 @@ static DWORD samr_connect4(char *, char *, char *, DWORD, mlsvc_handle_t *); * name. We store the remote server's native OS type - we may need it * due to differences between platforms like NT and Windows 2000. * + * If username argument is NULL, an anonymous connection will be established. + * Otherwise, an authenticated connection will be established. + * * On success 0 is returned. Otherwise a -ve error code. */ int -samr_open(int ipc_mode, char *server, char *domain, char *username, - char *password, DWORD access_mask, mlsvc_handle_t *samr_handle) +samr_open(char *server, char *domain, char *username, DWORD access_mask, + mlsvc_handle_t *samr_handle) { smb_ntdomain_t *di; int remote_os; int remote_lm; int rc; - if ((di = smb_getdomaininfo(0)) == NULL) - return (-1); - if (server == NULL || domain == NULL) { - server = di->server; - domain = di->domain; - } - - switch (ipc_mode) { - case MLSVC_IPC_USER: - /* - * Use the supplied credentials. - */ - rc = mlsvc_user_logon(server, domain, username, password); - break; + if ((di = smb_getdomaininfo(0)) == NULL) + return (-1); - case MLSVC_IPC_ADMIN: - /* - * Use the resource domain administrator credentials. - */ server = di->server; domain = di->domain; - username = smbrdr_ipc_get_user(); - - rc = mlsvc_admin_logon(server, domain); - break; - - case MLSVC_IPC_ANON: - default: - rc = mlsvc_anonymous_logon(server, domain, &username); - break; } + if (username == NULL) + username = MLSVC_ANON_USER; + rc = mlsvc_logon(server, domain, username); + if (rc != 0) return (-1); @@ -483,18 +465,18 @@ samr_open_domain(mlsvc_handle_t *samr_handle, DWORD access_mask, * Once you have a user handle it should be possible to query the SAM * for information on that user. */ -int +DWORD samr_open_user(mlsvc_handle_t *domain_handle, DWORD access_mask, DWORD rid, mlsvc_handle_t *user_handle) { struct samr_OpenUser arg; struct mlsvc_rpc_context *context; mlrpc_heapref_t heap; - int opnum; - int rc; + int opnum, rc; + DWORD status = NT_STATUS_SUCCESS; if (mlsvc_is_null_handle(domain_handle) || user_handle == NULL) - return (-1); + return (NT_STATUS_INVALID_PARAMETER); context = domain_handle->context; opnum = SAMR_OPNUM_OpenUser; @@ -506,22 +488,22 @@ samr_open_user(mlsvc_handle_t *domain_handle, DWORD access_mask, DWORD rid, (void) mlsvc_rpc_init(&heap); rc = mlsvc_rpc_call(context, opnum, &arg, &heap); - if (rc == 0) { - if (arg.status != 0) { - mlsvc_rpc_report_status(opnum, arg.status); - rc = -1; - } else { - (void) memcpy(&user_handle->handle, &arg.user_handle, - sizeof (ms_handle_t)); - user_handle->context = context; + if (rc != 0) { + status = NT_STATUS_UNSUCCESSFUL; + } else if (arg.status != 0) { + mlsvc_rpc_report_status(opnum, arg.status); + status = NT_SC_VALUE(arg.status); + } else { + (void) memcpy(&user_handle->handle, &arg.user_handle, + sizeof (ms_handle_t)); + user_handle->context = context; - if (mlsvc_is_null_handle(user_handle)) - rc = -1; - } + if (mlsvc_is_null_handle(user_handle)) + status = NT_STATUS_INVALID_HANDLE; } mlsvc_rpc_free(context, &heap); - return (rc); + return (status); } /* diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c index a9810bd538..6d0610add3 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c @@ -370,6 +370,7 @@ smb_autohome_keysub(const char *name, char *buf, int buflen) char key[SMB_AUTOHOME_KEYSIZ]; char *ampersand; char *tmp; + int bufsize = buflen; (void) strlcpy(key, buf, SMB_AUTOHOME_KEYSIZ); @@ -378,6 +379,12 @@ smb_autohome_keysub(const char *name, char *buf, int buflen) *tmp = '\0'; + /* + * Substitution characters are not allowed in the key. + */ + if (strpbrk(key, "?&") != NULL) + return (NULL); + if (strcmp(key, "*") == 0 && name != NULL) (void) strlcpy(key, name, SMB_AUTOHOME_KEYSIZ); @@ -387,8 +394,9 @@ smb_autohome_keysub(const char *name, char *buf, int buflen) if ((tmp = strdup(ampersand + 1)) == NULL) return (0); - (void) strlcpy(ampersand, key, buflen); - (void) strlcat(ampersand, tmp, buflen); + bufsize = buflen - (ampersand - buf); + (void) strlcpy(ampersand, key, bufsize); + (void) strlcat(ampersand, tmp, bufsize); free(tmp); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_client.c b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_client.c index aa9b12d241..3dca443d1a 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_client.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_client.c @@ -58,48 +58,31 @@ static int srvsvc_net_remote_tod(char *, char *, struct timeval *, struct tm *); * Ensure that an appropriate session and logon exists for the srvsvc * client calls. Open and bind the RPC interface. * + * If username argument is NULL, an anonymous connection will be established. + * Otherwise, an authenticated connection will be established. + * * On success 0 is returned. Otherwise a -ve error code. */ -int -srvsvc_open(int ipc_mode, char *server, char *domain, char *username, - char *password, mlsvc_handle_t *handle, mlrpc_heapref_t *heapref) +static int +srvsvc_open(char *server, char *domain, char *username, + mlsvc_handle_t *handle, mlrpc_heapref_t *heapref) { smb_ntdomain_t *di; int fid; int rc; - if ((di = smb_getdomaininfo(0)) == NULL) - return (-1); - if (server == NULL || domain == NULL) { - server = di->server; - domain = di->domain; - } + if ((di = smb_getdomaininfo(0)) == NULL) + return (-1); - switch (ipc_mode) { - case MLSVC_IPC_USER: - /* - * Use the supplied credentials. - */ - rc = mlsvc_user_logon(server, domain, username, password); - break; - - case MLSVC_IPC_ADMIN: - /* - * Use the resource domain administrator credentials. - */ server = di->server; domain = di->domain; - username = smbrdr_ipc_get_user(); + } - rc = mlsvc_admin_logon(server, domain); - break; + if (username == NULL) + username = MLSVC_ANON_USER; - case MLSVC_IPC_ANON: - default: - rc = mlsvc_anonymous_logon(server, domain, &username); - break; - } + rc = mlsvc_logon(server, domain, username); if (rc != 0) return (-1); @@ -145,18 +128,16 @@ srvsvc_net_share_get_info(char *server, char *domain, char *netname) struct mslm_NetShareGetInfo0 *info0; struct mslm_NetShareGetInfo1 *info1; struct mslm_NetShareGetInfo2 *info2; - int ipc_mode; int len; + char *user = NULL; if (netname == NULL) return (-1); if (srvsvc_info_level == 2) - ipc_mode = MLSVC_IPC_ADMIN; - else - ipc_mode = MLSVC_IPC_ANON; + user = smbrdr_ipc_get_user(); - rc = srvsvc_open(ipc_mode, server, domain, 0, 0, &handle, &heap); + rc = srvsvc_open(server, domain, user, &handle, &heap); if (rc != 0) return (-1); @@ -240,11 +221,12 @@ srvsvc_net_session_enum(char *server, char *domain, char *netname) struct mslm_infonres infonres; struct mslm_SESSION_INFO_1 *nsi1; int len; + char *user = smbrdr_ipc_get_user(); if (netname == NULL) return (-1); - rc = srvsvc_open(MLSVC_IPC_ADMIN, server, domain, 0, 0, &handle, &heap); + rc = srvsvc_open(server, domain, user, &handle, &heap); if (rc != 0) return (-1); @@ -305,11 +287,12 @@ srvsvc_net_connect_enum(char *server, char *domain, char *netname, int level) struct mslm_NetConnectInfo0 info0; struct mslm_NetConnectInfoBuf1 *cib1; int len; + char *user = smbrdr_ipc_get_user(); if (netname == NULL) return (-1); - rc = srvsvc_open(MLSVC_IPC_ADMIN, server, domain, 0, 0, &handle, &heap); + rc = srvsvc_open(server, domain, user, &handle, &heap); if (rc != 0) return (-1); @@ -476,8 +459,9 @@ srvsvc_net_remote_tod(char *server, char *domain, struct timeval *tv, int rc; int opnum; int len; + char *user = smbrdr_ipc_get_user(); - rc = srvsvc_open(MLSVC_IPC_ANON, server, domain, 0, 0, &handle, &heap); + rc = srvsvc_open(server, domain, user, &handle, &heap); if (rc != 0) return (-1); diff --git a/usr/src/lib/smbsrv/libmlsvc/i386/Makefile b/usr/src/lib/smbsrv/libmlsvc/i386/Makefile index f91f0270e9..710c9eb3dd 100644 --- a/usr/src/lib/smbsrv/libmlsvc/i386/Makefile +++ b/usr/src/lib/smbsrv/libmlsvc/i386/Makefile @@ -27,4 +27,6 @@ include ../Makefile.com +DYNFLAGS += -R/usr/lib/smbsrv + install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libmlsvc/sparc/Makefile b/usr/src/lib/smbsrv/libmlsvc/sparc/Makefile index f91f0270e9..710c9eb3dd 100644 --- a/usr/src/lib/smbsrv/libmlsvc/sparc/Makefile +++ b/usr/src/lib/smbsrv/libmlsvc/sparc/Makefile @@ -27,4 +27,6 @@ include ../Makefile.com +DYNFLAGS += -R/usr/lib/smbsrv + install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libmlsvc/sparcv9/Makefile b/usr/src/lib/smbsrv/libmlsvc/sparcv9/Makefile index a2f97019c8..e18b286b0a 100644 --- a/usr/src/lib/smbsrv/libmlsvc/sparcv9/Makefile +++ b/usr/src/lib/smbsrv/libmlsvc/sparcv9/Makefile @@ -25,7 +25,17 @@ # ident "%Z%%M% %I% %E% SMI" # +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) + include ../Makefile.com include ../../../Makefile.lib.64 +# With the adition of BIND 8.3.3, the symbol table for 64 bit went over +# the limit for Kpic, so we add -KPIC here, for just the 64 bit SPARC +# library. This avoids compiling the 32-bit library with PIC unnecessarily. +sparcv9_C_PICFLAGS = -K PIC +sparcv9_CC_PICFLAGS = -KPIC + +DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) + install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libsmb/Makefile.com b/usr/src/lib/smbsrv/libsmb/Makefile.com index c479406282..3771f7d993 100644 --- a/usr/src/lib/smbsrv/libsmb/Makefile.com +++ b/usr/src/lib/smbsrv/libsmb/Makefile.com @@ -76,6 +76,7 @@ include ../../Makefile.lib INCS += -I$(SRC)/common/smbsrv +LDLIBS += $(MACH_LDLIBS) LDLIBS += -lscf -lmd -lnsl -lpkcs11 -lc -lidmap CPPFLAGS += $(INCS) -D_REENTRANT diff --git a/usr/src/lib/smbsrv/libsmb/amd64/Makefile b/usr/src/lib/smbsrv/libsmb/amd64/Makefile index a2f97019c8..b3c4916b0c 100644 --- a/usr/src/lib/smbsrv/libsmb/amd64/Makefile +++ b/usr/src/lib/smbsrv/libsmb/amd64/Makefile @@ -25,7 +25,11 @@ # ident "%Z%%M% %I% %E% SMI" # +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) + include ../Makefile.com include ../../../Makefile.lib.64 +DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) + install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index 44da30085d..510f68c20d 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -279,6 +279,7 @@ extern int smb_config_set_secmode(int secmode); extern int smb_config_set_idmap_domain(char *value); extern int smb_config_set_idmap_gc(char *value); extern int smb_config_refresh_idmap(void); +extern int smb_config_refresh(void); /* smb_door_client.c */ typedef struct smb_joininfo { @@ -292,8 +293,10 @@ typedef struct smb_joininfo { extern int smbd_set_param(smb_cfg_id_t, char *); extern int smbd_get_param(smb_cfg_id_t, char *); extern int smbd_get_security_mode(int *); +extern int smb_set_machine_pwd(char *); extern int smbd_netbios_reconfig(void); extern uint32_t smb_join(smb_joininfo_t *info); +extern int smb_ads_domain_change_notify(char *); #define SMB_DOMAIN_NOMACHINE_SID -1 @@ -305,7 +308,7 @@ extern int nt_domain_init(char *resource_domain, uint32_t secmode); extern int smb_wins_allow_list(char *config_list, char *allow_list); extern int smb_wins_exclude_list(char *config_list, char *exclude_list); extern boolean_t smb_wins_is_excluded(in_addr_t ipaddr, - unsigned long *exclude_list, int nexclude); + ipaddr_t *exclude_list, int nexclude); extern void smb_wins_build_list(char *buf, uint32_t iplist[], int max_naddr); extern int smb_wins_iplist(char *list, uint32_t iplist[], int max_naddr); diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers index 05c89f93ff..3fa172f5d6 100644 --- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers @@ -108,6 +108,7 @@ SUNWprivate { oemstounicodes; rand_hash; randomize; + smb_ads_domain_change_notify; smb_auth_DES; smb_auth_gen_session_key; smb_auth_ntlm_hash; @@ -125,12 +126,12 @@ SUNWprivate { smb_config_getyorn; smb_config_load; smb_config_rdlock; + smb_config_refresh; smb_config_refresh_idmap; smb_config_secmode_fromstr; smb_config_secmode_tostr; smb_config_set; smb_config_set_idmap_domain; - smb_config_set_idmap_gc; smb_config_set_secmode; smb_config_setenv; smb_config_setnum; @@ -259,6 +260,7 @@ SUNWprivate { smb_pwd_setcntl; smb_pwd_setpasswd; smb_set_domain_member; + smb_set_machine_pwd; smb_setdomaininfo; smb_smf_create_instance_pgroup; smb_smf_create_service_pgroup; diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c index 844789e367..84d95609e5 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c @@ -65,8 +65,7 @@ typedef struct smb_cfg_param { /* idmap SMF fmri and Property Group */ #define IDMAP_FMRI_PREFIX "system/idmap" #define MACHINE_SID "machine_sid" -#define MAPPING_DOMAIN "mapping_domain" -#define GLOBAL_CATALOG "global_catalog" +#define IDMAP_DOMAIN "domain_name" #define IDMAP_PG_NAME "config" #define SMB_SECMODE_WORKGRP_STR "workgroup" @@ -1014,25 +1013,13 @@ smb_config_get_localsid(void) /* * smb_config_set_idmap_domain * - * Set the "config/mapping_domain" parameter from IDMAP SMF repository. + * Set the "config/domain_name" parameter from IDMAP SMF repository. */ int smb_config_set_idmap_domain(char *value) { return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME, - MAPPING_DOMAIN, value)); -} - -/* - * smb_config_set_idmap_gc - * - * Set the "config/global_catalog" parameter from IDMAP SMF repository. - */ -int -smb_config_set_idmap_gc(char *value) -{ - return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME, - GLOBAL_CATALOG, value)); + IDMAP_DOMAIN, value)); } /* @@ -1050,6 +1037,17 @@ smb_config_refresh_idmap(void) return (smf_refresh_instance(instance)); } +/* + * smb_config_refresh + * + * Refresh SMB SMF service. + */ +int +smb_config_refresh(void) +{ + return (smf_refresh_instance(SMBD_DEFAULT_INSTANCE_FMRI)); +} + int smb_config_secmode_fromstr(char *secmode) { diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c b/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c index 7e09b237b3..06eeac365c 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c @@ -36,6 +36,7 @@ #include <strings.h> #include <stdlib.h> #include <errno.h> +#include <unistd.h> #include <smbsrv/smbinfo.h> #include <smbsrv/wintypes.h> @@ -53,6 +54,7 @@ static char *smbd_desc[] = { "SmbdGetParam", "SmbdSetParam", "SmbdNetbiosReconfig", + "SmbdAdsDomainChanged", 0 }; @@ -409,3 +411,95 @@ smbd_get_security_mode(int *mode) *mode = smb_config_secmode_fromstr(buf); return (rc); } + +/* + * smb_ads_domain_change_notify + * + * When ADS domain has changed, this function is called to clear the + * ADS_HOST_INFO cache and remove the old keys from the Kerberos keytab. + */ +int +smb_ads_domain_change_notify(char *dom) +{ + door_arg_t arg; + char *buf; + uint32_t used; + smb_dr_ctx_t *dec_ctx; + smb_dr_ctx_t *enc_ctx; + int status; + int rc; + int opcode = SMBD_DOOR_ADS_DOMAIN_CHANGED; + + if (smbd_door_open(opcode) == -1) { + syslog(LOG_ERR, "%s: cannot open the door", smbd_desc[opcode]); + return (1); + } + + buf = MEM_MALLOC("smb_door_client", SMBD_DOOR_SIZE); + if (!buf) { + syslog(LOG_ERR, "%s: resource shortage", smbd_desc[opcode]); + (void) close(smb_door_fildes); + smb_door_fildes = -1; + return (1); + } + + enc_ctx = smb_dr_encode_start(buf, SMBD_DOOR_SIZE); + if (enc_ctx == 0) { + syslog(LOG_ERR, "%s: encode start failed", smbd_desc[opcode]); + MEM_FREE("smb_door_client", buf); + (void) close(smb_door_fildes); + smb_door_fildes = -1; + return (1); + } + + smb_dr_put_uint32(enc_ctx, opcode); + smb_dr_put_string(enc_ctx, dom); + + if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { + syslog(LOG_ERR, "%s: Encode error %s", + smbd_desc[opcode], strerror(status)); + MEM_FREE("smb_door_client", buf); + (void) close(smb_door_fildes); + smb_door_fildes = -1; + return (1); + } + + arg.data_ptr = buf; + arg.data_size = used; + arg.desc_ptr = NULL; + arg.desc_num = 0; + arg.rbuf = buf; + arg.rsize = SMBD_DOOR_SIZE; + + if (door_call(smb_door_fildes, &arg) < 0) { + syslog(LOG_ERR, "%s: Door call failed %s", smbd_desc[opcode], + strerror(errno)); + MEM_FREE("smb_door_client", buf); + (void) close(smb_door_fildes); + smb_door_fildes = -1; + return (1); + } + + dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); + if (smbd_door_check_srv_status(opcode, dec_ctx) != 0) { + MEM_FREE("smb_door_client", buf); + (void) close(smb_door_fildes); + smb_door_fildes = -1; + return (1); + } + rc = smb_dr_get_uint32(dec_ctx); + + if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { + syslog(LOG_ERR, "%s: Decode error %s", + smbd_desc[opcode], strerror(status)); + MEM_FREE("smb_door_client", buf); + (void) close(smb_door_fildes); + smb_door_fildes = -1; + return (1); + } + MEM_FREE("smb_door_client", buf); + (void) close(smb_door_fildes); + smb_door_fildes = -1; + + return (rc); +} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_info.c b/usr/src/lib/smbsrv/libsmb/common/smb_info.c index 24d7b1b3d1..d39eaf9208 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c @@ -112,6 +112,22 @@ smb_set_domain_member(int set) } /* + * smb_set_machine_pwd + * + * Returns 0 upon success. Otherwise, returns 1. + */ +int +smb_set_machine_pwd(char *pwd) +{ + int rc; + + smb_config_wrlock(); + rc = smb_config_set(SMB_CI_MACHINE_PASSWD, pwd); + smb_config_unlock(); + return (rc); +} + +/* * smb_getdomaininfo * * Returns a pointer to the cached domain data. The caller can specify diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_wins.c b/usr/src/lib/smbsrv/libsmb/common/smb_wins.c index 09498abfca..eb3a5216f4 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_wins.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_wins.c @@ -89,8 +89,7 @@ smb_wins_iplist(char *list, uint32_t iplist[], int max_naddr) * Returns 1 if it's excluded, 0 if it's not. */ boolean_t -smb_wins_is_excluded(in_addr_t ipaddr, - unsigned long *exclude_list, int nexclude) +smb_wins_is_excluded(in_addr_t ipaddr, ipaddr_t *exclude_list, int nexclude) { int i; diff --git a/usr/src/lib/smbsrv/libsmb/i386/Makefile b/usr/src/lib/smbsrv/libsmb/i386/Makefile index f91f0270e9..710c9eb3dd 100644 --- a/usr/src/lib/smbsrv/libsmb/i386/Makefile +++ b/usr/src/lib/smbsrv/libsmb/i386/Makefile @@ -27,4 +27,6 @@ include ../Makefile.com +DYNFLAGS += -R/usr/lib/smbsrv + install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libsmb/sparc/Makefile b/usr/src/lib/smbsrv/libsmb/sparc/Makefile index f91f0270e9..710c9eb3dd 100644 --- a/usr/src/lib/smbsrv/libsmb/sparc/Makefile +++ b/usr/src/lib/smbsrv/libsmb/sparc/Makefile @@ -27,4 +27,6 @@ include ../Makefile.com +DYNFLAGS += -R/usr/lib/smbsrv + install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile b/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile index a2f97019c8..b3c4916b0c 100644 --- a/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile +++ b/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile @@ -25,7 +25,11 @@ # ident "%Z%%M% %I% %E% SMI" # +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) + include ../Makefile.com include ../../../Makefile.lib.64 +DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) + install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libsmbns/Makefile.com b/usr/src/lib/smbsrv/libsmbns/Makefile.com index 2166b2640d..f4a45a3cac 100644 --- a/usr/src/lib/smbsrv/libsmbns/Makefile.com +++ b/usr/src/lib/smbsrv/libsmbns/Makefile.com @@ -52,6 +52,7 @@ include ../../Makefile.lib SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \ $(OBJS_SHARED:%.o=$(SRC)/common/smbsrv/%.c) +LDLIBS += $(MACH_LDLIBS) LDLIBS += -lsmb -lgss -lldap -lresolv -lnsl -lsocket -lc CPPFLAGS += -D_REENTRANT diff --git a/usr/src/lib/smbsrv/libsmbns/amd64/Makefile b/usr/src/lib/smbsrv/libsmbns/amd64/Makefile index a2f97019c8..b3c4916b0c 100644 --- a/usr/src/lib/smbsrv/libsmbns/amd64/Makefile +++ b/usr/src/lib/smbsrv/libsmbns/amd64/Makefile @@ -25,7 +25,11 @@ # ident "%Z%%M% %I% %E% SMI" # +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) + include ../Makefile.com include ../../../Makefile.lib.64 +DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) + install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h index a05c197c35..01de8f7f02 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h +++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h @@ -43,7 +43,6 @@ extern "C" { typedef struct ads_handle_s { char *user; /* admin user to create share in ADS */ char *pwd; /* user password */ - char *container; /* user container in ADS */ char *domain; /* ADS domain */ char *domain_dn; /* domain in Distinquish Name format */ char *ip_addr; /* ip addr in string format */ @@ -60,18 +59,17 @@ typedef enum adjoin_status { ADJOIN_ERR_GET_HANDLE, ADJOIN_ERR_GEN_PASSWD, ADJOIN_ERR_ADD_TRUST_ACCT, + ADJOIN_ERR_MOD_TRUST_ACCT, ADJOIN_ERR_GET_ENCTYPES, ADJOIN_ERR_GET_HOST_PRINC, ADJOIN_ERR_INIT_KRB_CTX, ADJOIN_ERR_GET_KRB_PRINC, ADJOIN_ERR_KSETPWD, - ADJOIN_ERR_MOD_TRUST_ACCT, + ADJOIN_ERR_UPDATE_CNTRL_ATTR, ADJOIN_ERR_WRITE_KEYTAB, ADJOIN_ERR_IDMAP_SET_DOMAIN, - ADJOIN_ERR_IDMAP_SET_GC, ADJOIN_ERR_IDMAP_REFRESH, - ADJOIN_ERR_IDMAP_CCACHE, - + ADJOIN_ERR_SMB_REFRESH, ADJOIN_NUM_STATUS } adjoin_status_t; @@ -86,8 +84,8 @@ extern int ads_build_unc_name(char *, int, const char *, const char *); extern int ads_lookup_share(ADS_HANDLE *, const char *, const char *, char *); extern int ads_add_share(ADS_HANDLE *, const char *, const char *, const char *); - -extern adjoin_status_t adjoin(char *, int); +extern int ads_domain_change_notify_handler(char *); +extern adjoin_status_t ads_join(char *, char *, char *, int); extern char *adjoin_report_err(adjoin_status_t status); /* DYNDNS functions */ diff --git a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers index d20641252d..63cf1a8f5b 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers @@ -27,11 +27,12 @@ SUNWprivate { global: - adjoin; adjoin_report_err; ads_add_share; ads_build_unc_name; ads_close; + ads_domain_change_notify_handler; + ads_join; ads_lookup_share; ads_open; ads_publish_share; diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c index c57971e455..5ea03bbd41 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c @@ -47,6 +47,7 @@ #include <sys/types.h> #include <sys/stat.h> + #include <smbsrv/libsmbns.h> #include <smbns_ads.h> #include <smbns_dyndns.h> @@ -56,6 +57,8 @@ #define ADS_MAXMSGLEN 512 #define ADS_HOST_PREFIX "host/" #define ADS_COMPUTERS_CN "Computers" +#define ADS_COMPUTER_NUM_ATTR 7 +#define ADS_SHARE_NUM_ATTR 3 /* current ADS server to communicate with */ ADS_HOST_INFO *ads_host_info = NULL; @@ -72,19 +75,20 @@ static char *adjoin_errmsg[] = { "ADJOIN failed to get handle.", "ADJOIN failed to generate machine password.", "ADJOIN failed to add workstation trust account.", + "ADJOIN failed to modify workstation trust account.", "ADJOIN failed to get list of encryption types.", "ADJOIN failed to get host principal.", "ADJOIN failed to initialize kerberos context.", - "ADJOIN failed to get kerberos principal.", + "ADJOIN failed to get Kerberos principal.", "ADJOIN failed to set machine account password on AD.", - "ADJOIN failed to modify workstation trust account.", - "ADJOIN failed to write Keberos keytab file.", - "ADJOIN failed to configure idmap(mapping domain).", - "ADJOIN failed to configure idmap(global catalog).", + "ADJOIN failed to modify CONTROL attribute of the account.", + "ADJOIN failed to write Kerberos keytab file.", + "ADJOIN failed to configure domain_name property for idmapd.", "ADJOIN failed to refresh idmap service." - "ADJOIN failed to remove idmap ccache." + "ADJOIN failed to refresh SMB service." }; +static ADS_HANDLE *ads_open_main(char *user, char *password); static int ads_bind(ADS_HANDLE *); static void ads_get_computer_dn(ADS_HANDLE *, char *, size_t); static char *ads_get_host_principal(char *fqhost); @@ -92,13 +96,15 @@ static char *ads_get_host_principal_w_realm(char *princ, char *domain); static int ads_get_host_principals(char *fqhost, char *domain, char **princ, char **princ_r); static int ads_add_computer(ADS_HANDLE *ah); +static int ads_modify_computer(ADS_HANDLE *ah); static void ads_del_computer(ADS_HANDLE *ah); +static int ads_computer_op(ADS_HANDLE *ah, int op); static int ads_lookup_computer_n_attr(ADS_HANDLE *ah, char *attr, char **val); -static int ads_modify_computer(ADS_HANDLE *ah, int des_only); +static int ads_update_computer_cntrl_attr(ADS_HANDLE *ah, int des_only); static krb5_kvno ads_lookup_computer_attr_kvno(ADS_HANDLE *ah); static int ads_gen_machine_passwd(char *machine_passwd, int bufsz); -static void ads_set_host_info(ADS_HOST_INFO *host); static ADS_HOST_INFO *ads_get_host_info(void); +static void ads_set_host_info(ADS_HOST_INFO *host); /* * ads_build_unc_name @@ -728,8 +734,27 @@ ads_free_host_info(void) /* * ads_open + * Open a LDAP connection to an ADS server if the system is in domain mode. + * Acquire both Kerberos TGT and LDAP service tickets for the host principal. + * + * This function should only be called after the system is successfully joined + * to a domain. + */ +ADS_HANDLE * +ads_open(void) +{ + uint32_t mode = smb_get_security_mode(); + + if (mode != SMB_SECMODE_DOMAIN) + return (NULL); + + return (ads_open_main(NULL, NULL)); +} + +/* + * ads_open_main * Open a LDAP connection to an ADS server. - * If ADS is enabled and the administrative username, password, container, and + * If ADS is enabled and the administrative username, password, and * ADS domain are defined then query DNS to find an ADS server if this is the * very first call to this routine. After an ADS server is found then this * server will be used everytime this routine is called until the system is @@ -751,12 +776,11 @@ ads_free_host_info(void) * ADS_HANDLE* : handle to ADS server */ ADS_HANDLE * -ads_open(void) +ads_open_main(char *user, char *password) { ADS_HANDLE *ah; LDAP *ld; int version = 3, ads_port, find_ads_retry; - char *adminUser, *password, *container; char domain[MAXHOSTNAMELEN]; int enable; ADS_HOST_INFO *ads_host = NULL; @@ -775,27 +799,10 @@ ads_open(void) smb_config_unlock(); return (NULL); } - adminUser = smb_config_getstr(SMB_CI_ADS_USER); - if (adminUser == NULL || *adminUser == 0) { - syslog(LOG_ERR, "smb_ads: admin user is not set"); - smb_config_unlock(); - return (NULL); - } - password = smb_config_getstr(SMB_CI_ADS_PASSWD); - if (password == NULL || *password == 0) { - syslog(LOG_ERR, "smb_ads: admin user password is not set"); - smb_config_unlock(); - return (NULL); - } - container = smb_config_getstr(SMB_CI_ADS_USER_CONTAINER); - if (container == NULL || *container == 0) - container = "cn=Users"; site = smb_config_getstr(SMB_CI_ADS_SITE); smb_config_unlock(); - - find_ads_retry = 0; find_ads_host: @@ -898,13 +905,11 @@ find_ads_host: } ah->ld = ld; - ah->user = strdup(adminUser); - ah->pwd = strdup(password); - ah->container = strdup(container); + ah->user = (user) ? strdup(user) : NULL; + ah->pwd = (password) ? strdup(password) : NULL; ah->domain = strdup(domain); - if ((ah->user == NULL) || (ah->pwd == NULL) || - (ah->container == NULL) || (ah->domain == NULL)) { + if (ah->domain == NULL) { ads_close(ah); return (NULL); } @@ -966,7 +971,6 @@ ads_close(ADS_HANDLE *ah) bzero(ah->pwd, len); free(ah->pwd); } - free(ah->container); free(ah->domain); free(ah->domain_dn); free(ah->hostname); @@ -1001,16 +1005,16 @@ ads_display_stat(OM_uint32 maj, OM_uint32 min) * free_attr * Free memory allocated when publishing a share. * Parameters: - * addattrs: an array of LDAPMod pointers + * attrs: an array of LDAPMod pointers * Returns: * None */ static void -free_attr(LDAPMod *addattrs[]) +free_attr(LDAPMod *attrs[]) { int i; - for (i = 0; addattrs[i]; i++) { - free(addattrs[i]); + for (i = 0; attrs[i]; i++) { + free(attrs[i]); } } @@ -1075,28 +1079,16 @@ ads_establish_sec_context(ADS_HANDLE *ah, gss_ctx_id_t *gss_context, int *kinit_retry, int *do_acquire_cred) { OM_uint32 maj, min, time_rec; - char service_name[ADS_MAXBUFLEN], *user_dn; + char service_name[ADS_MAXBUFLEN]; gss_buffer_desc send_tok, service_buf; gss_name_t target_name; gss_buffer_desc input; gss_buffer_desc *inputptr; struct berval cred; OM_uint32 ret_flags; - int stat, len; + int stat; int gss_flags; - /* - * 6 additional bytes for the "cn=,, " and the null terminator - */ - len = strlen(ah->user) + strlen(ah->container) + - strlen(ah->domain_dn) + 6; - - if ((user_dn = (char *)malloc(len)) == NULL) - return (-1); - - (void) snprintf(user_dn, len, "cn=%s,%s,%s", ah->user, ah->container, - ah->domain_dn); - (void) snprintf(service_name, ADS_MAXBUFLEN, "ldap@%s", ah->hostname); service_buf.value = service_name; service_buf.length = strlen(service_name)+1; @@ -1104,8 +1096,8 @@ ads_establish_sec_context(ADS_HANDLE *ah, gss_ctx_id_t *gss_context, (gss_OID) gss_nt_service_name, &target_name)) != GSS_S_COMPLETE) { ads_display_stat(maj, min); - (void) gss_release_oid(&min, &oid); - free(user_dn); + if (oid != GSS_C_NO_OID) + (void) gss_release_oid(&min, &oid); return (-1); } @@ -1119,9 +1111,9 @@ ads_establish_sec_context(ADS_HANDLE *ah, gss_ctx_id_t *gss_context, gss_flags, inputptr, &send_tok, &ret_flags, &time_rec, kinit_retry, do_acquire_cred, &maj, "ads") == -1) { - (void) gss_release_oid(&min, &oid); + if (oid != GSS_C_NO_OID) + (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); - free(user_dn); return (-1); } @@ -1131,16 +1123,16 @@ ads_establish_sec_context(ADS_HANDLE *ah, gss_ctx_id_t *gss_context, ber_bvfree(*sercred); *sercred = NULL; } - stat = ldap_sasl_bind_s(ah->ld, user_dn, "GSSAPI", + stat = ldap_sasl_bind_s(ah->ld, NULL, "GSSAPI", &cred, NULL, NULL, sercred); if (stat != LDAP_SUCCESS && stat != LDAP_SASL_BIND_IN_PROGRESS) { /* LINTED - E_SEC_PRINTF_VAR_FMT */ syslog(LOG_ERR, ldap_err2string(stat)); - (void) gss_release_oid(&min, &oid); + if (oid != GSS_C_NO_OID) + (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); (void) gss_release_buffer(&min, &send_tok); - free(user_dn); return (-1); } input.value = (*sercred)->bv_val; @@ -1150,9 +1142,9 @@ ads_establish_sec_context(ADS_HANDLE *ah, gss_ctx_id_t *gss_context, (void) gss_release_buffer(&min, &send_tok); } while (maj != GSS_S_COMPLETE); - (void) gss_release_oid(&min, &oid); + if (oid != GSS_C_NO_OID) + (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); - free(user_dn); return (0); } @@ -1279,14 +1271,15 @@ ads_bind(ADS_HANDLE *ah) OM_uint32 min; gss_cred_id_t cred_handle; gss_ctx_id_t gss_context; - OM_uint32 maj; gss_OID oid; struct berval *sercred; int kinit_retry, do_acquire_cred; + int rc = 0; kinit_retry = 0; do_acquire_cred = 0; - acquire_cred: + +acquire_cred: if (ads_acquire_cred(ah, &cred_handle, &oid, &kinit_retry)) return (-1); @@ -1300,29 +1293,13 @@ ads_bind(ADS_HANDLE *ah) } return (-1); } + rc = ads_negotiate_sec_layer(ah, gss_context, sercred); - if (ads_negotiate_sec_layer(ah, gss_context, sercred)) { + if (cred_handle != GSS_C_NO_CREDENTIAL) (void) gss_release_cred(&min, &cred_handle); - (void) gss_delete_sec_context(&min, &gss_context, NULL); - return (-1); - } + (void) gss_delete_sec_context(&min, &gss_context, NULL); - if ((maj = gss_release_cred(&min, &cred_handle)) - != GSS_S_COMPLETE) { - syslog(LOG_ERR, "smb_ads: Can't release credential handle\n"); - ads_display_stat(maj, min); - (void) gss_delete_sec_context(&min, &gss_context, NULL); - return (-1); - } - - if ((maj = gss_delete_sec_context(&min, &gss_context, NULL)) - != GSS_S_COMPLETE) { - syslog(LOG_ERR, "smb_ads: Can't delete security context\n"); - ads_display_stat(maj, min); - return (-1); - } - - return (0); + return ((rc) ? -1 : 0); } /* @@ -1347,12 +1324,11 @@ int ads_add_share(ADS_HANDLE *ah, const char *adsShareName, const char *unc_name, const char *adsContainer) { - LDAPMod *addattrs[3]; + LDAPMod *attrs[ADS_SHARE_NUM_ATTR]; char *tmp1[5], *tmp2[5]; - int j = -1; + int j = 0; char *share_dn; char buf[ADS_MAXMSGLEN]; - int len, ret; len = 5 + strlen(adsShareName) + strlen(adsContainer) + @@ -1365,37 +1341,44 @@ ads_add_share(ADS_HANDLE *ah, const char *adsShareName, (void) snprintf(share_dn, len, "cn=%s,%s,%s", adsShareName, adsContainer, ah->domain_dn); - addattrs[++j] = (LDAPMod *)malloc(sizeof (LDAPMod)); - addattrs[j]->mod_op = LDAP_MOD_ADD; - addattrs[j]->mod_type = "objectClass"; + for (j = 0; j < (ADS_SHARE_NUM_ATTR - 1); j++) { + attrs[j] = (LDAPMod *)malloc(sizeof (LDAPMod)); + if (attrs[j] == NULL) { + free_attr(attrs); + free(share_dn); + return (-1); + } + } + + j = 0; + attrs[j]->mod_op = LDAP_MOD_ADD; + attrs[j]->mod_type = "objectClass"; tmp1[0] = "top"; tmp1[1] = "leaf"; tmp1[2] = "connectionPoint"; tmp1[3] = "volume"; tmp1[4] = 0; - addattrs[j]->mod_values = tmp1; - - addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod)); - addattrs[j]->mod_op = LDAP_MOD_ADD; - addattrs[j]->mod_type = "uNCName"; + attrs[j]->mod_values = tmp1; + attrs[++j]->mod_op = LDAP_MOD_ADD; + attrs[j]->mod_type = "uNCName"; tmp2[0] = (char *)unc_name; tmp2[1] = 0; - addattrs[j]->mod_values = tmp2; + attrs[j]->mod_values = tmp2; - addattrs[++j] = 0; + attrs[++j] = 0; - if ((ret = ldap_add_s(ah->ld, share_dn, addattrs)) != LDAP_SUCCESS) { + if ((ret = ldap_add_s(ah->ld, share_dn, attrs)) != LDAP_SUCCESS) { (void) snprintf(buf, ADS_MAXMSGLEN, "ads_add_share: %s:", share_dn); /* LINTED - E_SEC_PRINTF_VAR_FMT */ syslog(LOG_ERR, ldap_err2string(ret)); - free_attr(addattrs); + free_attr(attrs); free(share_dn); return (ret); } free(share_dn); - free_attr(addattrs); + free_attr(attrs); (void) snprintf(buf, ADS_MAXMSGLEN, "Share %s has been added to ADS container: %s.\n", adsShareName, @@ -1787,15 +1770,21 @@ ads_get_host_principal_w_realm(char *princ, char *domain) * ads_get_host_principals * * If fqhost is NULL, this function will attempt to obtain fully qualified - * hostname prior to generating the host principals. + * hostname prior to generating the host principals. If caller is not + * interested in getting the principal name without the Kerberos realm + * info, princ can be set to NULL. */ static int ads_get_host_principals(char *fqhost, char *domain, char **princ, char **princ_r) { char hostname[MAXHOSTNAMELEN]; + char *p; + + if (princ != NULL) + *princ = NULL; - *princ = *princ_r = NULL; + *princ_r = NULL; if (fqhost) { (void) strlcpy(hostname, fqhost, MAXHOSTNAMELEN); @@ -1804,16 +1793,19 @@ ads_get_host_principals(char *fqhost, char *domain, char **princ, return (-1); } - if ((*princ = ads_get_host_principal(hostname)) == NULL) { + if ((p = ads_get_host_principal(hostname)) == NULL) { return (-1); } - *princ_r = ads_get_host_principal_w_realm(*princ, domain); + *princ_r = ads_get_host_principal_w_realm(p, domain); if (*princ_r == NULL) { - free(*princ); + free(p); return (-1); } + if (princ != NULL) + *princ = p; + return (0); } @@ -1825,16 +1817,34 @@ ads_get_host_principals(char *fqhost, char *domain, char **princ, static int ads_add_computer(ADS_HANDLE *ah) { - LDAPMod *addattrs[7]; + return (ads_computer_op(ah, LDAP_MOD_ADD)); +} + +/* + * ads_modify_computer + * + * Returns 0 upon success. Otherwise, returns -1. + */ +static int +ads_modify_computer(ADS_HANDLE *ah) +{ + return (ads_computer_op(ah, LDAP_MOD_REPLACE)); +} + +static int +ads_computer_op(ADS_HANDLE *ah, int op) +{ + LDAPMod *attrs[ADS_COMPUTER_NUM_ATTR]; char *oc_vals[6], *sam_val[2], *usr_val[2]; char *svc_val[2], *ctl_val[2], *fqh_val[2]; - int j = -1; + int j = 0; int ret, usrctl_flags = 0; char sam_acct[MAXHOSTNAMELEN + 1]; char fqhost[MAXHOSTNAMELEN]; char dn[ADS_DN_MAX]; char *user_principal, *svc_principal; char usrctl_buf[16]; + int max; if (smb_getfqhostname(fqhost, MAXHOSTNAMELEN) != 0) return (-1); @@ -1847,75 +1857,96 @@ ads_add_computer(ADS_HANDLE *ah) if (ads_get_host_principals(fqhost, ah->domain, &svc_principal, &user_principal) == -1) { syslog(LOG_ERR, - "ads_add_computer: unable to get host principal"); + "ads_computer_op: unable to get host principal"); return (-1); } ads_get_computer_dn(ah, dn, ADS_DN_MAX); - addattrs[++j] = (LDAPMod *)malloc(sizeof (LDAPMod)); - addattrs[j]->mod_op = LDAP_MOD_ADD; - addattrs[j]->mod_type = "objectClass"; - oc_vals[0] = "top"; - oc_vals[1] = "person"; - oc_vals[2] = "organizationalPerson"; - oc_vals[3] = "user"; - oc_vals[4] = "computer"; - oc_vals[5] = 0; - addattrs[j]->mod_values = oc_vals; - - addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod)); - addattrs[j]->mod_op = LDAP_MOD_ADD; - addattrs[j]->mod_type = "sAMAccountName"; + max = (ADS_COMPUTER_NUM_ATTR - ((op != LDAP_MOD_ADD) ? 1 : 0)); + for (j = 0; j < (max - 1); j++) { + attrs[j] = (LDAPMod *)malloc(sizeof (LDAPMod)); + if (attrs[j] == NULL) { + free_attr(attrs); + free(user_principal); + free(svc_principal); + return (-1); + } + } + j = -1; + /* objectClass attribute is not modifiable. */ + if (op == LDAP_MOD_ADD) { + attrs[++j]->mod_op = op; + attrs[j]->mod_type = "objectClass"; + oc_vals[0] = "top"; + oc_vals[1] = "person"; + oc_vals[2] = "organizationalPerson"; + oc_vals[3] = "user"; + oc_vals[4] = "computer"; + oc_vals[5] = 0; + attrs[j]->mod_values = oc_vals; + } + + attrs[++j]->mod_op = op; + attrs[j]->mod_type = "sAMAccountName"; sam_val[0] = sam_acct; sam_val[1] = 0; - addattrs[j]->mod_values = sam_val; - - - addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod)); - addattrs[j]->mod_op = LDAP_MOD_ADD; - addattrs[j]->mod_type = "userPrincipalName"; + attrs[j]->mod_values = sam_val; + attrs[++j]->mod_op = op; + attrs[j]->mod_type = "userPrincipalName"; usr_val[0] = user_principal; usr_val[1] = 0; - addattrs[j]->mod_values = usr_val; - - addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod)); - addattrs[j]->mod_op = LDAP_MOD_ADD; - addattrs[j]->mod_type = "servicePrincipalName"; + attrs[j]->mod_values = usr_val; + attrs[++j]->mod_op = op; + attrs[j]->mod_type = "servicePrincipalName"; svc_val[0] = svc_principal; svc_val[1] = 0; - addattrs[j]->mod_values = svc_val; - - addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod)); - addattrs[j]->mod_op = LDAP_MOD_ADD; - addattrs[j]->mod_type = "userAccountControl"; + attrs[j]->mod_values = svc_val; + attrs[++j]->mod_op = op; + attrs[j]->mod_type = "userAccountControl"; usrctl_flags |= (ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT | ADS_USER_ACCT_CTL_PASSWD_NOTREQD | ADS_USER_ACCT_CTL_ACCOUNTDISABLE); - (void) snprintf(usrctl_buf, sizeof (usrctl_buf), "%d", usrctl_flags); ctl_val[0] = usrctl_buf; ctl_val[1] = 0; - addattrs[j]->mod_values = ctl_val; - addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod)); - addattrs[j]->mod_op = LDAP_MOD_ADD; - addattrs[j]->mod_type = "dNSHostName"; + attrs[j]->mod_values = ctl_val; + attrs[++j]->mod_op = op; + attrs[j]->mod_type = "dNSHostName"; fqh_val[0] = fqhost; fqh_val[1] = 0; - addattrs[j]->mod_values = fqh_val; - addattrs[++j] = 0; + attrs[j]->mod_values = fqh_val; + + attrs[++j] = 0; + + switch (op) { + case LDAP_MOD_ADD: + if ((ret = ldap_add_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) { + syslog(LOG_ERR, "ads_add_computer: %s", + ldap_err2string(ret)); + ret = -1; + } + break; + + case LDAP_MOD_REPLACE: + if ((ret = ldap_modify_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) { + syslog(LOG_ERR, "ads_modify_computer: %s", + ldap_err2string(ret)); + ret = -1; + } + break; - if ((ret = ldap_add_s(ah->ld, dn, addattrs)) != LDAP_SUCCESS) { - syslog(LOG_ERR, "ads_add_computer: %s", ldap_err2string(ret)); + default: ret = -1; + } - free_attr(addattrs); + free_attr(attrs); free(user_principal); free(svc_principal); @@ -1978,8 +2009,7 @@ ads_lookup_computer_n_attr(ADS_HANDLE *ah, char *attr, char **val) return (-1); } - (void) snprintf(filter, sizeof (filter), - "(&(objectClass=computer)(sAMAccountName=%s))", + (void) snprintf(filter, sizeof (filter), "objectClass=computer", tmpbuf); if (ldap_search_s(ah->ld, dn, LDAP_SCOPE_BASE, filter, attrs, 0, @@ -2031,7 +2061,7 @@ ads_find_computer(ADS_HANDLE *ah) } /* - * ads_modify_computer + * ads_update_computer_cntrl_attr * * Modify the user account control attribute of an existing computer * object on AD. @@ -2039,7 +2069,7 @@ ads_find_computer(ADS_HANDLE *ah) * Returns 0 on success. Otherwise, returns -1. */ static int -ads_modify_computer(ADS_HANDLE *ah, int des_only) +ads_update_computer_cntrl_attr(ADS_HANDLE *ah, int des_only) { LDAPMod *attrs[6]; char *ctl_val[2]; @@ -2090,7 +2120,7 @@ ads_lookup_computer_attr_kvno(ADS_HANDLE *ah) char *val = NULL; int kvno = 1; - if (ads_lookup_computer_n_attr(ah, "ms-DS-KeyVersionNumber", + if (ads_lookup_computer_n_attr(ah, "msDS-KeyVersionNumber", &val) == 1) { if (val) { kvno = atoi(val); @@ -2135,11 +2165,49 @@ ads_gen_machine_passwd(char *machine_passwd, int bufsz) } /* - * adjoin + * ads_domain_change_notify_handler + * + * Clear the host info cache and remove the old keys from the keytab + * as the ads_domain property has changed. + * + * domain - is the old ADS domain name. + */ +int +ads_domain_change_notify_handler(char *domain) +{ + char *princ_r; + krb5_context ctx = NULL; + krb5_principal krb5princ; + int rc; + + if (ads_get_host_principals(NULL, domain, NULL, &princ_r) == -1) + return (-1); + + if (smb_krb5_ctx_init(&ctx) != 0) { + free(princ_r); + return (-1); + } + + if (smb_krb5_get_principal(ctx, princ_r, &krb5princ) != 0) { + free(princ_r); + smb_krb5_ctx_fini(ctx); + return (-1); + + } + + rc = smb_krb5_remove_keytab_entries(ctx, krb5princ, SMBNS_KRB5_KEYTAB); + free(princ_r); + smb_krb5_ctx_fini(ctx); + ads_free_host_info(); + return (rc); +} + +/* + * ads_join * * Besides the NT-4 style domain join (using MS-RPC), CIFS server also * provides the domain join using Kerberos Authentication, Keberos - * Change & Set password, and LDAP protocols. Basically, adjoin + * Change & Set password, and LDAP protocols. Basically, AD join * operation would require the following tickets to be acquired for the * the user account that is provided for the domain join. * @@ -2160,36 +2228,16 @@ ads_gen_machine_passwd(char *machine_passwd, int bufsz) * principal after the domain join operation. */ adjoin_status_t -adjoin(char *machine_passwd, int len) +ads_join(char *user, char *usr_passwd, char *machine_passwd, int len) { ADS_HANDLE *ah = NULL; - krb5_enctype enctypes[10]; krb5_context ctx = NULL; krb5_principal krb5princ; krb5_kvno kvno; - char *princ, *princ_r; - int des_only, delete = 1, fini_krbctx = 1; + char *princ_r; + boolean_t des_only, delete = B_TRUE, fini_krbctx = B_TRUE; adjoin_status_t rc = ADJOIN_SUCCESS; - struct stat fstat; - - char *idmap_ccache = "/var/run/idmap/ccache"; - - if ((ah = ads_open()) == NULL) - return (ADJOIN_ERR_GET_HANDLE); - - if (ads_gen_machine_passwd(machine_passwd, len) != 0) { - ads_close(ah); - return (ADJOIN_ERR_GEN_PASSWD); - } - - if (ads_find_computer(ah)) - ads_del_computer(ah); - - if (ads_add_computer(ah) != 0) { - ads_close(ah); - return (ADJOIN_ERR_ADD_TRUST_ACCT); - } - + boolean_t new_acct; /* * Call library functions that can be used to get * the list of encryption algorithms available on the system. @@ -2199,12 +2247,37 @@ adjoin(char *machine_passwd, int len) * list of algorithms available on any system running Nevada * by default. */ - enctypes[0] = ENCTYPE_DES_CBC_CRC; - enctypes[1] = ENCTYPE_DES_CBC_MD5; - enctypes[2] = ENCTYPE_ARCFOUR_HMAC; - enctypes[3] = ENCTYPE_AES128_CTS_HMAC_SHA1_96; + krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, + ENCTYPE_ARCFOUR_HMAC, ENCTYPE_AES128_CTS_HMAC_SHA1_96}; + + if ((ah = ads_open_main(user, usr_passwd)) == NULL) { + (void) smb_config_refresh(); + return (ADJOIN_ERR_GET_HANDLE); + } + + if (ads_gen_machine_passwd(machine_passwd, len) != 0) { + ads_close(ah); + (void) smb_config_refresh(); + return (ADJOIN_ERR_GEN_PASSWD); + } - des_only = 0; + if (ads_find_computer(ah)) { + new_acct = B_FALSE; + if (ads_modify_computer(ah) != 0) { + ads_close(ah); + (void) smb_config_refresh(); + return (ADJOIN_ERR_MOD_TRUST_ACCT); + } + } else { + new_acct = B_TRUE; + if (ads_add_computer(ah) != 0) { + ads_close(ah); + (void) smb_config_refresh(); + return (ADJOIN_ERR_ADD_TRUST_ACCT); + } + } + + des_only = B_FALSE; /* * If we are talking to a Longhorn server, we need to set up @@ -2216,14 +2289,16 @@ adjoin(char *machine_passwd, int len) * SmbSessionSetup request sent by SMB redirector. */ - if (ads_get_host_principals(NULL, ah->domain, &princ, &princ_r) == -1) { - ads_del_computer(ah); + if (ads_get_host_principals(NULL, ah->domain, NULL, &princ_r) == -1) { + if (new_acct) + ads_del_computer(ah); ads_close(ah); + (void) smb_config_refresh(); return (ADJOIN_ERR_GET_HOST_PRINC); } if (smb_krb5_ctx_init(&ctx) != 0) { - fini_krbctx = 0; + fini_krbctx = B_FALSE; rc = ADJOIN_ERR_INIT_KRB_CTX; goto adjoin_cleanup; } @@ -2239,12 +2314,15 @@ adjoin(char *machine_passwd, int len) } kvno = ads_lookup_computer_attr_kvno(ah); - if (ads_modify_computer(ah, des_only) != 0) { - rc = ADJOIN_ERR_MOD_TRUST_ACCT; + + if (ads_update_computer_cntrl_attr(ah, des_only) != 0) { + rc = ADJOIN_ERR_UPDATE_CNTRL_ATTR; goto adjoin_cleanup; } - if (smb_krb5_write_keytab(ctx, krb5princ, "/etc/krb5/krb5.keytab", kvno, - machine_passwd, enctypes, 4) != 0) { + + if (smb_krb5_update_keytab_entries(ctx, krb5princ, SMBNS_KRB5_KEYTAB, + kvno, machine_passwd, enctypes, + (sizeof (enctypes) / sizeof (krb5_enctype))) != 0) { rc = ADJOIN_ERR_WRITE_KEYTAB; goto adjoin_cleanup; } @@ -2255,37 +2333,30 @@ adjoin(char *machine_passwd, int len) goto adjoin_cleanup; } - if (smb_config_set_idmap_gc(ah->hostname) != 0) { - rc = ADJOIN_ERR_IDMAP_SET_GC; - goto adjoin_cleanup; - } - /* Refresh IDMAP service */ if (smb_config_refresh_idmap() != 0) { rc = ADJOIN_ERR_IDMAP_REFRESH; goto adjoin_cleanup; } - /* Remove the idmap ccache */ - if (stat(idmap_ccache, &fstat) == 0) { - if (remove(idmap_ccache) != 0) { - rc = ADJOIN_ERR_IDMAP_CCACHE; - goto adjoin_cleanup; - } - } - - delete = 0; + delete = B_FALSE; adjoin_cleanup: - if (delete) + if (new_acct && delete) ads_del_computer(ah); if (fini_krbctx) smb_krb5_ctx_fini(ctx); ads_close(ah); - free(princ); free(princ_r); + /* + * Don't mask other failure. Only reports SMF refresh + * failure if no other domain join failure. + */ + if ((smb_config_refresh() != 0) && (rc == ADJOIN_SUCCESS)) + rc = ADJOIN_ERR_SMB_REFRESH; + return (rc); } diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c index 474adca09b..094c1b4946 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c @@ -47,14 +47,12 @@ #include <net/if.h> #include <smbns_dyndns.h> -#include <smbns_krb.h> /* internal use, in dyndns_add_entry */ #define DEL_NONE 2 /* Maximum retires if not authoritative */ #define MAX_AUTH_RETRIES 3 - static int dyndns_enabled(void) { @@ -63,8 +61,7 @@ dyndns_enabled(void) smb_config_rdlock(); enabled = smb_config_getyorn(SMB_CI_DYNDNS_ENABLE); smb_config_unlock(); - - return ((enabled) ? 1 : 0); + return (enabled); } /* @@ -620,55 +617,6 @@ dyndns_open_init_socket(int sock_type, unsigned long dest_addr, int port) } /* - * dyndns_acquire_cred - * This routine is used to acquire a GSS credential handle to a user's Kerberos - * ticket-granting ticket (TGT) stored locally on the system. If getting a - * handle fails, then a new TGT will be obtained again before trying to get a - * handle once more. - * The user's password is taken from the environment variable - * lookup.dns.dynamic.passwd and is encrypted. - * Paramaters: - * kinit_retry: if 0 then a new TGT can be obtained before second attempt to - * get a handle to TGT if first attempt fails - * Returns: - * user_name : name of user to get credential handle from - * credHandle : handle to user's credential (TGT) - * oid : contains Kerberos 5 object identifier - * kinit_retry: 1 if a new TGT has been acquired in this routine, otherwise 0 - * -1 : error - */ -static int -dyndns_acquire_cred(gss_cred_id_t *credHandle, char *user_name, - gss_OID *oid, int *kinit_retry) -{ - char *p, pwd[100]; - - smb_config_rdlock(); - p = smb_config_getstr(SMB_CI_ADS_USER); - if (p == NULL || *p == 0) { - syslog(LOG_ERR, "No user configured for " - "secure dynamic DNS update.\n"); - smb_config_unlock(); - return (-1); - } - (void) strcpy(user_name, p); - - p = smb_config_getstr(SMB_CI_ADS_PASSWD); - if (p == NULL || *p == 0) { - syslog(LOG_ERR, "No password configured for " - "secure dynamic DNS update.\n"); - smb_config_unlock(); - return (-1); - } - smb_config_unlock(); - - (void) strcpy(pwd, p); - - return krb5_acquire_cred_kinit(user_name, pwd, credHandle, - oid, kinit_retry, "dyndns"); -} - -/* * dyndns_build_tkey_msg * This routine is used to build the TKEY message to transmit GSS tokens * during GSS security context establishment for secure DNS update. The @@ -741,30 +689,18 @@ dyndns_build_tkey_msg(char *buf, char *key_name, uint16_t *id, * processes the new token and then generates a new token to be sent to the * GSS server. This cycle is continued until the security establishment is * done. TCP is used to send and receive TKEY messages. - * If gss_init_sec_context fails then a new TGT will be acquired so that - * security establishment can be retry once more by the caller after getting - * a handle to the new TGT (credential). * Parameters: - * credHandle : handle to credential + * cred_handle : handle to credential * s : socket descriptor to DNS server * key_name : TKEY key name * dns_hostname: fully qualified DNS hostname * oid : contains Kerberos 5 object identifier - * user_name : name of user to perform DNS update - * kinit_retry : if 0 and gss_init_sec_context fails then get new TGT so - * the caller can restart doing security context establishment * Returns: * gss_context : handle to security context - * kinit_retry : 1 if a new TGT has been acquired in this routine, - * otherwise 0 - * do_acquire_cred: if 1 then caller will restart security context - * establishment - * -1 : error */ static int -dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, - int s, char *key_name, char *dns_hostname, gss_OID oid, char *user_name, - int *kinit_retry, int *do_acquire_cred) +dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t cred_handle, + int s, char *key_name, char *dns_hostname, gss_OID oid) { uint16_t id, rid, rsz; char buf[MAX_TCP_SIZE], buf2[MAX_TCP_SIZE]; @@ -778,34 +714,19 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, int gss_flags; OM_uint32 ret_flags; int buf_sz; - char *p, pwd[100]; - - smb_config_rdlock(); - p = smb_config_getstr(SMB_CI_ADS_PASSWD); - if (p == NULL || *p == 0) { - syslog(LOG_ERR, "No password configured for " - "secure dynamic DNS update.\n"); - smb_config_unlock(); - return (-1); - } - smb_config_unlock(); - (void) strcpy(pwd, p); service_sz = strlen(dns_hostname) + 5; service_name = (char *)malloc(sizeof (char) * service_sz); if (service_name == NULL) { syslog(LOG_ERR, "Malloc failed for %d bytes ", service_sz); - smb_config_unlock(); return (-1); } (void) snprintf(service_name, service_sz, "DNS@%s", dns_hostname); service_buf.value = service_name; service_buf.length = strlen(service_name)+1; if ((maj = gss_import_name(&min, &service_buf, - (gss_OID) gss_nt_service_name, - &target_name)) != GSS_S_COMPLETE) { + GSS_C_NT_HOSTBASED_SERVICE, &target_name)) != GSS_S_COMPLETE) { display_stat(maj, min); - (void) gss_release_oid(&min, &oid); (void) free(service_name); return (-1); } @@ -816,11 +737,17 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG; do { - if (krb5_establish_sec_ctx_kinit(user_name, pwd, credHandle, - gss_context, target_name, oid, gss_flags, inputptr, - &out_tok, &ret_flags, &time_rec, kinit_retry, - do_acquire_cred, &maj, "dyndns") == -1) { - (void) gss_release_oid(&min, &oid); + maj = gss_init_sec_context(&min, cred_handle, gss_context, + target_name, oid, gss_flags, 0, NULL, inputptr, NULL, + &out_tok, &ret_flags, &time_rec); + + if (maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) { + assert(gss_context); + if (*gss_context != GSS_C_NO_CONTEXT) + (void) gss_delete_sec_context(&min, + gss_context, NULL); + + display_stat(maj, min); (void) gss_release_name(&min, &target_name); return (-1); } @@ -830,7 +757,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, syslog(LOG_ERR, "dyndns: No GSS_C_REPLAY_FLAG\n"); if (out_tok.length > 0) (void) gss_release_buffer(&min, &out_tok); - (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); return (-1); } @@ -840,7 +766,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, syslog(LOG_ERR, "dyndns: No GSS_C_MUTUAL_FLAG\n"); if (out_tok.length > 0) (void) gss_release_buffer(&min, &out_tok); - (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); return (-1); } @@ -849,7 +774,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, if ((buf_sz = dyndns_build_tkey_msg(buf, key_name, &id, &out_tok)) <= 0) { (void) gss_release_buffer(&min, &out_tok); - (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); return (-1); } @@ -858,7 +782,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, if (send(s, buf, buf_sz, 0) == -1) { syslog(LOG_ERR, "dyndns: TKEY send error\n"); - (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); return (-1); } @@ -867,7 +790,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, if (recv(s, buf2, MAX_TCP_SIZE, 0) == -1) { syslog(LOG_ERR, "dyndns: TKEY " "reply recv error\n"); - (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); return (-1); } @@ -877,7 +799,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, syslog(LOG_ERR, "dyndns: Error in " "TKEY reply: %d: ", ret); dyndns_msg_err(ret); - (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); return (-1); } @@ -885,7 +806,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, tmpptr = &buf2[2]; (void) dyndns_get_nshort(tmpptr, &rid); if (id != rid) { - (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); return (-1); } @@ -901,7 +821,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, } while (maj != GSS_S_COMPLETE); - (void) gss_release_oid(&min, &oid); (void) gss_release_name(&min, &target_name); return (0); @@ -910,13 +829,8 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle, /* * dyndns_get_sec_context * Get security context for secure dynamic DNS update. This routine opens - * a TCP socket to the DNS server and calls routines to get a handle to a - * locally cached user's credential and establish a security context with - * the DNS server to perform secure dynamic DNS update. If getting security - * context fails then a retry may be done after reobtaining new credential and - * getting a new credential handle. If obtaining new credential has been - * done earlier during getting a handle to credential then there is no need to - * do a retry for security context. + * a TCP socket to the DNS server and establishes a security context with + * the DNS server using host principal to perform secure dynamic DNS update. * Parameters: * hostname: fully qualified hostname * dns_ip : ip address of hostname in network byte order @@ -930,14 +844,14 @@ static gss_ctx_id_t dyndns_get_sec_context(const char *hostname, int dns_ip) { int s; - gss_cred_id_t credHandle; + gss_cred_id_t cred_handle; gss_ctx_id_t gss_context; gss_OID oid; - OM_uint32 min; struct hostent *hentry; - int kinit_retry, do_acquire_cred; - char *key_name, dns_hostname[255], user_name[50]; + char *key_name, dns_hostname[MAXHOSTNAMELEN]; + cred_handle = GSS_C_NO_CREDENTIAL; + oid = GSS_C_NO_OID; key_name = (char *)hostname; hentry = gethostbyaddr((char *)&dns_ip, 4, AF_INET); @@ -952,29 +866,11 @@ dyndns_get_sec_context(const char *hostname, int dns_ip) return (NULL); } - kinit_retry = 0; - do_acquire_cred = 0; - acquire_cred: - - if (dyndns_acquire_cred(&credHandle, user_name, &oid, &kinit_retry)) { - (void) close(s); - return (NULL); - } - - if (dyndns_establish_sec_ctx(&gss_context, credHandle, s, key_name, - dns_hostname, oid, user_name, &kinit_retry, &do_acquire_cred)) { - (void) gss_release_cred(&min, &credHandle); - if (do_acquire_cred) { - do_acquire_cred = 0; - goto acquire_cred; - } - (void) close(s); - return (NULL); - } + if (dyndns_establish_sec_ctx(&gss_context, cred_handle, s, key_name, + dns_hostname, oid)) + gss_context = NULL; (void) close(s); - - (void) gss_release_cred(&min, &credHandle); return (gss_context); } @@ -1367,7 +1263,8 @@ sec_retry_higher: key_name = (char *)hostname; if ((s2 = dyndns_open_init_socket(SOCK_DGRAM, dns_ip, 53)) < 0) { - (void) gss_delete_sec_context(&min, &gss_context, NULL); + if (gss_context != GSS_C_NO_CONTEXT) + (void) gss_delete_sec_context(&min, &gss_context, NULL); return (-1); } @@ -1376,7 +1273,8 @@ sec_retry_higher: ip_addr, life_time, update_type, del_type, key_name, &id, level)) <= 0) { (void) close(s2); - (void) gss_delete_sec_context(&min, &gss_context, NULL); + if (gss_context != GSS_C_NO_CONTEXT) + (void) gss_delete_sec_context(&min, &gss_context, NULL); return (-1); } @@ -1388,7 +1286,8 @@ sec_retry_higher: GSS_S_COMPLETE) { display_stat(maj, min); (void) close(s2); - (void) gss_delete_sec_context(&min, &gss_context, NULL); + if (gss_context != GSS_C_NO_CONTEXT) + (void) gss_delete_sec_context(&min, &gss_context, NULL); return (-1); } @@ -1397,7 +1296,8 @@ sec_retry_higher: &out_mic, level)) <= 0) { (void) close(s2); (void) gss_release_buffer(&min, &out_mic); - (void) gss_delete_sec_context(&min, &gss_context, NULL); + if (gss_context != GSS_C_NO_CONTEXT) + (void) gss_delete_sec_context(&min, &gss_context, NULL); return (-1); } @@ -1405,13 +1305,15 @@ sec_retry_higher: if (dyndns_udp_send_recv(s2, buf, buf_sz, buf2)) { (void) close(s2); - (void) gss_delete_sec_context(&min, &gss_context, NULL); + if (gss_context != GSS_C_NO_CONTEXT) + (void) gss_delete_sec_context(&min, &gss_context, NULL); return (-1); } (void) close(s2); - (void) gss_delete_sec_context(&min, &gss_context, NULL); + if (gss_context != GSS_C_NO_CONTEXT) + (void) gss_delete_sec_context(&min, &gss_context, NULL); ret = buf2[3] & 0xf; /* error field in UDP */ @@ -1498,7 +1400,8 @@ dyndns_search_entry(int update_zone, const char *hostname, const char *ip_addr, /* * dyndns_add_remove_entry - * Perform non-secure dynamic DNS update. If fail then tries secure update. + * Perform non-secure dynamic DNS update. If it fails and the system is in + * domain mode, secure update will be performed. * This routine opens a UDP socket to the DNS sever, build the update request * message, and sends the message to the DNS server. The response is received * and check for error. If there is no error then the local NSS cached is @@ -1603,8 +1506,9 @@ retry_higher: return (-1); } - ret = dyndns_sec_add_remove_entry(update_zone, hostname, - ip_addr, life_time, update_type, del_type, dns_str); + if (smb_get_security_mode() == SMB_SECMODE_DOMAIN) + ret = dyndns_sec_add_remove_entry(update_zone, hostname, + ip_addr, life_time, update_type, del_type, dns_str); return (ret); } diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c index c1a2de7913..4fa2e34931 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c @@ -53,6 +53,7 @@ */ #include <kerberosv5/krb5.h> #include <kerberosv5/com_err.h> +#include <assert.h> #include <string.h> #include <stdio.h> #include <time.h> @@ -299,6 +300,9 @@ smb_kinit(char *user, char *passwd) struct k5_data k5; int authed_k5 = 0; + assert(user); + assert(passwd); + (void) memset(&opts, 0, sizeof (opts)); opts.action = INIT_PW; opts.principal_name = strdup(user); @@ -374,10 +378,18 @@ krb5_acquire_cred_kinit(char *user, char *pwd, gss_cred_id_t *cred_handle, /* * krb5_acquire_cred_kinit_main * - * This routine is called both by ADS and Dyn DNS modules to get a handle to - * administrative user's credential stored locally on the system. The - * credential is the TGT. If the attempt at getting handle fails then a second - * attempt will be made after getting a new TGT. + * This routine is called by ADS module to get a handle to administrative + * user's credential stored locally on the system. The credential is the TGT. + * If the attempt at getting handle fails then a second attempt will be made + * after getting a new TGT. + * + * If there's no username then we must be using host credentials and we don't + * bother trying to acquire a credential for GSS_C_NO_NAME (which should be + * equivalent to using GSS_C_NO_CREDENTIAL, but it isn't in a very subtle way + * because mech_krb5 isn't so smart). Specifically mech_krb5 will try hard + * to get a non-expired TGT using the keytab if we're running as root (or fake + * it, using the special app_krb5_user_uid() function), but only when we use + * the default credential, as opposed to a credential for the default principal. * * Paramters: * user : username to retrieve a handle to its credential @@ -399,12 +411,15 @@ krb5_acquire_cred_kinit_main(char *user, char *pwd, gss_cred_id_t *cred_handle, gss_OID *oid, int *kinit_retry, char *caller_mod) { OM_uint32 maj, min; - gss_name_t desired_name; + gss_name_t desired_name = GSS_C_NO_NAME; gss_OID_set desired_mechs; gss_buffer_desc oidstr, name_buf; char str[50], user_name[50]; - acquire_cred: + *cred_handle = GSS_C_NO_CREDENTIAL; + *oid = GSS_C_NO_OID; + if (user == NULL || *user == '\0') + return (0); /* Object Identifier for Kerberos 5 */ (void) strcpy(str, "{ 1 2 840 113554 1 2 2 }"); @@ -439,12 +454,10 @@ krb5_acquire_cred_kinit_main(char *user, char *pwd, gss_cred_id_t *cred_handle, return (-1); } +acquire_cred: if ((maj = gss_acquire_cred(&min, desired_name, 0, desired_mechs, GSS_C_INITIATE, cred_handle, NULL, NULL)) != GSS_S_COMPLETE) { - if (!*kinit_retry) { - (void) gss_release_oid(&min, oid); - (void) gss_release_oid_set(&min, &desired_mechs); - (void) gss_release_name(&min, &desired_name); + if (!*kinit_retry && pwd != NULL && *pwd != '\0') { syslog(LOG_ERR, "%s: Retry kinit to " "acquire credential.\n", caller_mod); (void) smb_kinit(user, pwd); @@ -455,9 +468,15 @@ krb5_acquire_cred_kinit_main(char *user, char *pwd, gss_cred_id_t *cred_handle, (void) gss_release_oid(&min, oid); (void) gss_release_oid_set(&min, &desired_mechs); (void) gss_release_name(&min, &desired_name); + if (pwd == NULL || *pwd == '\0') { + /* See above */ + *cred_handle = GSS_C_NO_CREDENTIAL; + return (0); + } return (-1); } } + (void) gss_release_oid_set(&min, &desired_mechs); (void) gss_release_name(&min, &desired_name); @@ -467,11 +486,11 @@ krb5_acquire_cred_kinit_main(char *user, char *pwd, gss_cred_id_t *cred_handle, /* * krb5_establish_sec_ctx_kinit * - * This routine is called by both the ADS and Dyn DNS modules to establish a - * security context before ADS or Dyn DNS updates are allowed. If establishing - * a security context fails for any reason, a second attempt will be made after - * a new TGT is obtained. This routine is called many time as needed until - * a security context is established. + * This routine is called by the ADS module to establish a security + * context before ADS updates are allowed. If establishing a security context + * fails for any reason, a second attempt will be made after a new TGT is + * obtained. This routine is called many time as needed until a security + * context is established. * * The resources use for the security context must be released if security * context establishment process fails. @@ -527,7 +546,7 @@ krb5_establish_sec_ctx_kinit(char *user, char *pwd, if (*gss_context != NULL) (void) gss_delete_sec_context(&min, gss_context, NULL); - if (!*kinit_retry) { + if ((user != NULL) && (pwd != NULL) && !*kinit_retry) { syslog(LOG_ERR, "%s: Retry kinit to establish " "security context.\n", caller_mod); (void) smb_kinit(user, pwd); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h index 22028fcdb5..18d6696771 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h @@ -35,6 +35,8 @@ extern "C" { #endif +#define SMBNS_KRB5_KEYTAB "/etc/krb5/krb5.keytab" + extern gss_OID gss_nt_user_name; extern gss_OID gss_nt_machine_uid_name; extern gss_OID gss_nt_string_uid_name; @@ -53,7 +55,9 @@ void smb_krb5_ctx_fini(krb5_context ctx); int smb_krb5_get_principal(krb5_context ctx, char *princ_str, krb5_principal *princ); int smb_krb5_setpwd(krb5_context ctx, krb5_principal princ, char *passwd); -int smb_krb5_write_keytab(krb5_context ctx, krb5_principal princ, +int smb_krb5_remove_keytab_entries(krb5_context ctx, krb5_principal princ, + char *fname); +int smb_krb5_update_keytab_entries(krb5_context ctx, krb5_principal princ, char *fname, krb5_kvno kvno, char *passwd, krb5_enctype *enctypes, int enctype_count); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c index a6c99799d1..83100131c2 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c @@ -34,14 +34,18 @@ #include <ctype.h> #include <errno.h> #include <syslog.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> #include <kerberosv5/krb5.h> +#include <kerberosv5/com_err.h> +#include <smbns_krb.h> +static int smb_krb5_open_wrfile(krb5_context ctx, char *fname, + krb5_keytab *kt); static int smb_krb5_ktadd(krb5_context ctx, krb5_keytab kt, const krb5_principal princ, krb5_enctype enctype, krb5_kvno kvno, const char *pw); +static krb5_error_code smb_krb5_ktremove(krb5_context ctx, krb5_keytab kt, + const krb5_principal princ); + /* * smb_krb5_ctx_init @@ -122,29 +126,18 @@ smb_krb5_setpwd(krb5_context ctx, krb5_principal princ, char *passwd) } /* - * smb_krb5_write_keytab + * smb_krb5_open_wrfile * - * Write all the Kerberos keys to the keytab file. - * Returns 0 on success. Otherwise, returns -1. + * Open the keytab file for writing. + * The keytab should be closed by calling krb5_kt_close(). */ -int -smb_krb5_write_keytab(krb5_context ctx, krb5_principal princ, char *fname, - krb5_kvno kvno, char *passwd, krb5_enctype *enctypes, int enctype_count) +static int +smb_krb5_open_wrfile(krb5_context ctx, char *fname, krb5_keytab *kt) { - krb5_keytab kt = NULL; char *ktname; - int i, len; - int rc = 0; - struct stat fstat; - - if (stat(fname, &fstat) == 0) { - if (remove(fname) != 0) { - syslog(LOG_ERR, "smb_krb5_write_keytab: cannot remove" - " existing keytab"); - return (-1); - } - } + int len; + *kt = NULL; len = snprintf(NULL, 0, "WRFILE:%s", fname) + 1; if ((ktname = malloc(len)) == NULL) { syslog(LOG_ERR, "smb_krb5_write_keytab: resource shortage"); @@ -153,7 +146,7 @@ smb_krb5_write_keytab(krb5_context ctx, krb5_principal princ, char *fname, (void) snprintf(ktname, len, "WRFILE:%s", fname); - if (krb5_kt_resolve(ctx, ktname, &kt) != 0) { + if (krb5_kt_resolve(ctx, ktname, kt) != 0) { syslog(LOG_ERR, "smb_krb5_write_keytab: failed to open/create " "keytab %s\n", fname); free(ktname); @@ -161,6 +154,59 @@ smb_krb5_write_keytab(krb5_context ctx, krb5_principal princ, char *fname, } free(ktname); + return (0); +} + +/* + * smb_krb5_remove_keytab_entries + * + * Remove the keys from the keytab for the specified principal. + */ +int +smb_krb5_remove_keytab_entries(krb5_context ctx, krb5_principal princ, + char *fname) +{ + krb5_keytab kt = NULL; + int rc = 0; + krb5_error_code code; + + if (smb_krb5_open_wrfile(ctx, fname, &kt) != 0) + return (-1); + + if ((code = smb_krb5_ktremove(ctx, kt, princ)) != 0) { + syslog(LOG_ERR, "smb_krb5_remove_keytab_entries: %s", + error_message(code)); + rc = -1; + } + + krb5_kt_close(ctx, kt); + return (rc); +} + +/* + * smb_krb5_update_keytab_entries + * + * Update the keys for the specified principal in the keytab. + * Returns 0 on success. Otherwise, returns -1. + */ +int +smb_krb5_update_keytab_entries(krb5_context ctx, krb5_principal princ, + char *fname, krb5_kvno kvno, char *passwd, krb5_enctype *enctypes, + int enctype_count) +{ + krb5_keytab kt = NULL; + int rc = 0, i; + krb5_error_code code; + + if (smb_krb5_open_wrfile(ctx, fname, &kt) != 0) + return (-1); + + if ((code = smb_krb5_ktremove(ctx, kt, princ)) != 0) { + syslog(LOG_ERR, "smb_krb5_update_keytab_entries: %s", + error_message(code)); + krb5_kt_close(ctx, kt); + return (-1); + } for (i = 0; i < enctype_count; i++) { if (smb_krb5_ktadd(ctx, kt, princ, enctypes[i], kvno, passwd) @@ -171,13 +217,74 @@ smb_krb5_write_keytab(krb5_context ctx, krb5_principal princ, char *fname, } - if (kt != NULL) - krb5_kt_close(ctx, kt); - + krb5_kt_close(ctx, kt); return (rc); } /* + * smb_krb5_ktremove + * + * Removes the old entries for the specified principal from the keytab. + * + * Returns 0 upon success. Otherwise, returns KRB5 error code. + */ +static krb5_error_code +smb_krb5_ktremove(krb5_context ctx, krb5_keytab kt, const krb5_principal princ) +{ + krb5_keytab_entry entry; + krb5_kt_cursor cursor; + int code; + + code = krb5_kt_get_entry(ctx, kt, princ, 0, 0, &entry); + if (code != 0) { + if (code == ENOENT || code == KRB5_KT_NOTFOUND) + return (0); + + return (code); + } + + krb5_kt_free_entry(ctx, &entry); + + if ((code = krb5_kt_start_seq_get(ctx, kt, &cursor)) != 0) + return (code); + + while ((code = krb5_kt_next_entry(ctx, kt, &entry, &cursor)) == 0) { + if (krb5_principal_compare(ctx, princ, entry.principal)) { + + code = krb5_kt_end_seq_get(ctx, kt, &cursor); + if (code != 0) { + krb5_kt_free_entry(ctx, &entry); + return (code); + } + + code = krb5_kt_remove_entry(ctx, kt, &entry); + if (code != 0) { + krb5_kt_free_entry(ctx, &entry); + return (code); + } + + code = krb5_kt_start_seq_get(ctx, kt, &cursor); + if (code != 0) { + krb5_kt_free_entry(ctx, &entry); + return (code); + } + + } + krb5_kt_free_entry(ctx, &entry); + } + + if (code && code != KRB5_KT_END) { + (void) krb5_kt_end_seq_get(ctx, kt, &cursor); + return (code); + } + + if ((code = krb5_kt_end_seq_get(ctx, kt, &cursor))) + return (code); + + return (0); +} + +/* * smb_krb5_ktadd * * Add a Keberos key to the keytab file. diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c index 2b2d20e3c3..b8de94a504 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c @@ -2134,6 +2134,7 @@ smb_send_node_status_response(struct addr_entry *addr, unsigned char *scan_end; unsigned char data[MAX_NETBIOS_REPLY_DATA_SIZE]; net_cfg_t cfg; + boolean_t scan_done = B_FALSE; bzero(&packet, sizeof (struct name_packet)); bzero(&answer, sizeof (struct resource_record)); @@ -2168,7 +2169,7 @@ smb_send_node_status_response(struct addr_entry *addr, smb_config_rdlock(); max_connections = smb_config_getnum(SMB_CI_MAX_CONNECTIONS); smb_config_unlock(); - for (;;) { + while (!scan_done) { if ((scan + 6) >= scan_end) { packet.info |= NAME_NM_FLAGS_TC; break; @@ -2256,8 +2257,7 @@ smb_send_node_status_response(struct addr_entry *addr, BE_OUT16(scan, 0); scan += 2; - break; - /*NOTREACHED*/ + scan_done = B_TRUE; } answer.rdlength = scan - data; return (smb_send_name_service_packet(addr, &packet)); @@ -4489,6 +4489,10 @@ smb_netbios_wins_config(char *ip) { uint32_t ipaddr; + /* Return if ip == NULL since this is the same as "" */ + if (ip == NULL) + return; + ipaddr = inet_addr(ip); if (ipaddr != INADDR_NONE) { smb_nbns[nbns_num].flags = ADDR_FLAG_VALID; diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c index 0aaf8338b4..6adeca1d50 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c @@ -638,7 +638,7 @@ smb_nic_get_list(struct if_list **list) int smb_nic_build_network_structures(net_cfg_t **nc, int *number) { - char ** names = NULL; + char **names = NULL; int res, numnics = 0; int num_aliases = 0; uint32_t uip; @@ -680,14 +680,16 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) if (num_aliases == -1) { (void) smb_nic_clear_name_list(names, numnics); free (*nc); + *nc = NULL; return (-1); } - (*nc)->aliases = (char **)malloc( - (sizeof (char) * IP_ABITS) * num_aliases); + (*nc)->aliases = (char **)calloc(num_aliases, + (sizeof (char) * IP_ABITS)); if ((*nc)->aliases == NULL) { (void) smb_nic_clear_name_list(names, numnics); free (*nc); + *nc = NULL; return (-1); } (void) strncpy((*nc)->ifname, names[i], @@ -699,17 +701,19 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) (void) smb_nic_clear_name_list(names, numnics); free ((*nc)->aliases); free (*nc); + *nc = NULL; return (-1); } (*nc)->ip = uip; - if (smb_wins_is_excluded(uip, (ulong_t *)exclude, - nexclude)) + if (smb_wins_is_excluded(uip, + (ipaddr_t *)exclude, nexclude)) (*nc)->exclude = B_TRUE; res = smb_nic_get_netmask((*nc)->ifname, &uip); if (res == -1) { /* error retrieving netmask address */ (void) smb_nic_clear_name_list(names, numnics); free ((*nc)->aliases); free (*nc); + *nc = NULL; return (-1); } (*nc)->mask = uip; @@ -718,6 +722,7 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) (void) smb_nic_clear_name_list(names, numnics); free ((*nc)->aliases); free (*nc); + *nc = NULL; return (-1); } (*nc)->broadcast = uip; @@ -727,6 +732,7 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) (void) smb_nic_clear_name_list(names, numnics); free ((*nc)->aliases); free (*nc); + *nc = NULL; return (-1); } res = smb_nic_flags((*nc)->ifname, &flags); @@ -734,6 +740,7 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) (void) smb_nic_clear_name_list(names, numnics); free ((*nc)->aliases); free (*nc); + *nc = NULL; return (-1); } (*nc)->flags = flags; @@ -747,6 +754,7 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) (void) smb_nic_clear_name_list(names, numnics); free ((*nc)->aliases); free (*nc); + *nc = NULL; return (-1); } @@ -761,16 +769,16 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) (char *)(list->next); j++; list = list->next; + } } + k++; + *number = k; /* needed if we have to cleanup on fail */ + j = 1; + (*nc)++; /* increment pointer */ } - k++; - j = 1; - (*nc)++; /* increment pointer */ - } } /* end for */ *nc = nc_array; - *number = k; (void) smb_nic_clear_name_list(names, numnics); return (0); } @@ -958,9 +966,11 @@ smb_nic_clear_niclist(net_cfg_t *niclist, int amount) for (i = 0; i < amount; i++) { while (niclist[i].aliases[j] != NULL) { free(niclist[i].aliases[j]); + niclist[i].aliases[j] = NULL; j++; } free(niclist[i].aliases); + niclist[i].aliases = NULL; j = 0; } free(niclist); @@ -971,8 +981,13 @@ smb_nic_clear_niclist(net_cfg_t *niclist, int amount) int smb_nic_free_niclist(net_cfg_list_t *niclist) { - return (smb_nic_clear_niclist(niclist->net_cfg_list, - niclist->net_cfg_cnt)); + int ret; + + ret = smb_nic_clear_niclist(niclist->net_cfg_list, + niclist->net_cfg_cnt); + niclist->net_cfg_list = NULL; + niclist->net_cfg_cnt = 0; + return (ret); } /* @@ -1048,10 +1063,15 @@ smb_nic_unlock(void) int smb_nic_init() { + int ret; + smb_nic_lock(); smb_nic_list.net_cfg_cnt = 0; - (void) smb_nic_build_network_structures(&smb_nic_list.net_cfg_list, + smb_nic_list.net_cfg_list = NULL; + ret = smb_nic_build_network_structures(&smb_nic_list.net_cfg_list, &smb_nic_list.net_cfg_cnt); + if (ret != 0) + (void) smb_nic_free_niclist(&smb_nic_list); smb_nic_unlock(); return (0); } @@ -1062,18 +1082,21 @@ smb_nic_init() void smb_nic_build_info(void) { + int ret; + smb_nic_lock(); if (smb_nic_list.net_cfg_list) { (void) smb_nic_free_niclist(&smb_nic_list); - smb_nic_list.net_cfg_list = NULL; } smb_nic_list.net_cfg_cnt = 0; - (void) smb_nic_build_network_structures(&smb_nic_list.net_cfg_list, + ret = smb_nic_build_network_structures(&smb_nic_list.net_cfg_list, &smb_nic_list.net_cfg_cnt); - if (smb_nic_list.net_cfg_cnt == 0) { + if (ret != 0) + (void) smb_nic_free_niclist(&smb_nic_list); + if (smb_nic_list.net_cfg_cnt == 0) syslog(LOG_ERR, "smb: No network interfaces are configured " "smb server may not function properly"); - } + smb_nic_unlock(); } diff --git a/usr/src/lib/smbsrv/libsmbns/i386/Makefile b/usr/src/lib/smbsrv/libsmbns/i386/Makefile index f91f0270e9..710c9eb3dd 100644 --- a/usr/src/lib/smbsrv/libsmbns/i386/Makefile +++ b/usr/src/lib/smbsrv/libsmbns/i386/Makefile @@ -27,4 +27,6 @@ include ../Makefile.com +DYNFLAGS += -R/usr/lib/smbsrv + install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libsmbns/sparc/Makefile b/usr/src/lib/smbsrv/libsmbns/sparc/Makefile index f91f0270e9..710c9eb3dd 100644 --- a/usr/src/lib/smbsrv/libsmbns/sparc/Makefile +++ b/usr/src/lib/smbsrv/libsmbns/sparc/Makefile @@ -27,4 +27,6 @@ include ../Makefile.com +DYNFLAGS += -R/usr/lib/smbsrv + install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libsmbns/sparcv9/Makefile b/usr/src/lib/smbsrv/libsmbns/sparcv9/Makefile index a2f97019c8..b3c4916b0c 100644 --- a/usr/src/lib/smbsrv/libsmbns/sparcv9/Makefile +++ b/usr/src/lib/smbsrv/libsmbns/sparcv9/Makefile @@ -25,7 +25,11 @@ # ident "%Z%%M% %I% %E% SMI" # +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) + include ../Makefile.com include ../../../Makefile.lib.64 +DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) + install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libsmbrdr/Makefile.com b/usr/src/lib/smbsrv/libsmbrdr/Makefile.com index 822331f26b..0586ba1034 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/Makefile.com +++ b/usr/src/lib/smbsrv/libsmbrdr/Makefile.com @@ -44,6 +44,7 @@ OBJECTS= $(OBJS_COMMON) $(OBJS_SHARED) include ../../../Makefile.lib include ../../Makefile.lib +LDLIBS += $(MACH_LDLIBS) LDLIBS += -lsmb -lnsl -lsocket -lc SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \ diff --git a/usr/src/lib/smbsrv/libsmbrdr/amd64/Makefile b/usr/src/lib/smbsrv/libsmbrdr/amd64/Makefile index a2f97019c8..b3c4916b0c 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/amd64/Makefile +++ b/usr/src/lib/smbsrv/libsmbrdr/amd64/Makefile @@ -25,7 +25,11 @@ # ident "%Z%%M% %I% %E% SMI" # +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) + include ../Makefile.com include ../../../Makefile.lib.64 +DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) + install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h b/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h index 846ac9d306..8d537650ac 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h +++ b/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h @@ -37,7 +37,7 @@ extern "C" { /* * Redirector IPC functions * - * The following functions are required by the mlsvc_validate_user to + * The following functions are required by the mlsvc_join to * apply new authentication information for the authenticated IPC, rollback * or commit the changes to the original authentication information. */ @@ -45,25 +45,12 @@ extern void smbrdr_ipc_set(char *, unsigned char *); extern void smbrdr_ipc_commit(void); extern void smbrdr_ipc_rollback(void); extern int smbrdr_ipc_skip_lsa_query(void); -extern int smbrdr_ipc_get_mode(void); -extern void smbrdr_ipc_save_mode(char *val); -extern unsigned smbrdr_ipc_get_flags(void); -extern void smbrdr_ipc_set_fallback(void); -extern void smbrdr_ipc_unset_fallback(void); -extern int smbrdr_ipc_is_fallback(void); - -/* - * Functions for obtaining the resource domain administrator credentials. - */ extern char *smbrdr_ipc_get_user(void); -extern char *smbrdr_ipc_get_passwd(void); -extern int smbrdr_ipc_is_valid(void); +extern unsigned char *smbrdr_ipc_get_passwd(void); -/* Redirector LOGON functions */ -extern int mlsvc_anonymous_logon(char *, char *, char **); -extern int mlsvc_user_logon(char *, char *, char *, char *); -extern int mlsvc_admin_logon(char *, char *); +/* Redirector LOGON function */ +extern int mlsvc_logon(char *, char *, char *); extern int smbrdr_rpc_readx(int, char *, int); diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers b/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers index 0ea435ee55..b6902203ef 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers @@ -27,35 +27,26 @@ SUNWprivate { global: - mlsvc_admin_logon; - mlsvc_anonymous_logon; mlsvc_check_sessions; mlsvc_close_pipe; mlsvc_disconnect; mlsvc_echo; mlsvc_install_pdc_cb; mlsvc_locate_domain_controller; + mlsvc_logon; mlsvc_open_pipe; mlsvc_session_native_values; mlsvc_user_getauth; - mlsvc_user_logon; smbrdr_dump_netuse; smbrdr_dump_ofiles; smbrdr_dump_sessions; smbrdr_init; - smbrdr_ipc_get_mode; smbrdr_ipc_commit; - smbrdr_ipc_get_flags; smbrdr_ipc_get_user; smbrdr_ipc_rollback; smbrdr_ipc_set; smbrdr_ipc_skip_lsa_query; - smbrdr_ipc_is_fallback; - smbrdr_ipc_is_valid; smbrdr_ipc_get_passwd; - smbrdr_ipc_save_mode; - smbrdr_ipc_set_fallback; - smbrdr_ipc_unset_fallback; smbrdr_rpc_readx; smbrdr_rpc_transact; local: diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c index 908a439864..cbce43db5e 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c @@ -44,17 +44,32 @@ #include <smbrdr.h> #include <smbrdr_ipc_util.h> -/* - * The binary NTLM hash is 16 bytes. When it is converted to hexidecimal, - * it will be at most twice as long. - */ -#define SMBRDR_IPC_HEX_PASSWD_MAXLEN (SMBAUTH_HASH_SZ * 2) + 1 #define SMBRDR_IPC_GETDOMAIN_TIMEOUT 10000 static rwlock_t smbrdr_ipc_lock; static smbrdr_ipc_t ipc_info; static smbrdr_ipc_t orig_ipc_info; +static int +smbrdr_get_machine_pwd_hash(unsigned char *hash) +{ + char *pwd; + int rc = 0; + + smb_config_rdlock(); + pwd = smb_config_getstr(SMB_CI_MACHINE_PASSWD); + if (!pwd || *pwd == 0) { + smb_config_unlock(); + return (-1); + } + + if (smb_auth_ntlm_hash((char *)pwd, hash) != 0) + rc = -1; + + smb_config_unlock(); + return (rc); +} + /* * smbrdr_ipc_init * @@ -66,73 +81,39 @@ static smbrdr_ipc_t orig_ipc_info; void smbrdr_ipc_init(void) { - char *p; + int rc; + (void) rw_wrlock(&smbrdr_ipc_lock); bzero(&ipc_info, sizeof (smbrdr_ipc_t)); bzero(&orig_ipc_info, sizeof (smbrdr_ipc_t)); - smb_config_rdlock(); - p = smb_config_getstr(SMB_CI_RDR_IPCMODE); - - if (!strncasecmp(p, IPC_MODE_AUTH, IPC_MODE_STRLEN)) { - ipc_info.mode = MLSVC_IPC_ADMIN; - - p = smb_config_getstr(SMB_CI_RDR_IPCUSER); - if (p) - (void) strlcpy(ipc_info.user, p, - MLSVC_ACCOUNT_NAME_MAX); - else - syslog(LOG_WARNING, "smbrdr: (ipc) no admin user name"); - - p = smb_config_get(SMB_CI_RDR_IPCPWD); - if (p) { - if (strlen(p) != SMBRDR_IPC_HEX_PASSWD_MAXLEN - 1) { - *ipc_info.passwd = 0; - syslog(LOG_WARNING, - "smbrdr: (ipc) invalid admin password"); - } else { - (void) hextobin(p, - SMBRDR_IPC_HEX_PASSWD_MAXLEN - 1, - ipc_info.passwd, SMBAUTH_HASH_SZ); - } - } else { - *ipc_info.passwd = 0; - syslog(LOG_WARNING, "smbrdr: (ipc) no admin password"); - } - - } else { - if (!strcasecmp(p, IPC_MODE_FALLBACK_ANON)) - ipc_info.flags |= IPC_FLG_FALLBACK_ANON; - - ipc_info.mode = MLSVC_IPC_ANON; - (void) strlcpy(ipc_info.user, MLSVC_ANON_USER, - MLSVC_ACCOUNT_NAME_MAX); + (void) smb_gethostname(ipc_info.user, MLSVC_ACCOUNT_NAME_MAX - 1, 0); + (void) strlcat(ipc_info.user, "$", MLSVC_ACCOUNT_NAME_MAX); + rc = smbrdr_get_machine_pwd_hash(ipc_info.passwd); + if (rc != 0) *ipc_info.passwd = 0; - } - smb_config_unlock(); + (void) rw_unlock(&smbrdr_ipc_lock); + } /* * smbrdr_ipc_set * * The given username and password hash will be applied to the - * ipc_info which will be used by mlsvc_validate_user(). + * ipc_info, which will be used for setting up the authenticated IPC + * channel during join domain. * - * If mlsvc_validate_user() succeeds, the calling function is responsible - * for invoking smbrdr_ipc_commit() for updating the environment - * variables. Otherwise, it should invoke smbrdr_ipc_rollback() to restore - * the previous credentials. + * If domain join operation succeeds, smbrdr_ipc_commit() should be + * invoked to set the ipc_info with host credentials. Otherwise, + * smbrdr_ipc_rollback() should be called to restore the previous + * credentials. */ void smbrdr_ipc_set(char *plain_user, unsigned char *passwd_hash) { (void) rw_wrlock(&smbrdr_ipc_lock); - if (ipc_info.flags & IPC_FLG_FALLBACK_ANON) - ipc_info.mode = MLSVC_IPC_ADMIN; - (void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user)); (void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ); - ipc_info.flags |= IPC_FLG_NEED_VERIFY; (void) rw_unlock(&smbrdr_ipc_lock); } @@ -140,39 +121,20 @@ smbrdr_ipc_set(char *plain_user, unsigned char *passwd_hash) /* * smbrdr_ipc_commit * - * Save the new admin credentials as environment variables. - * The binary NTLM password hash is first converted to a - * hex string before storing in the environment variable. + * Save the host credentials, which will be used for any authenticated + * IPC channel establishment after domain join. * - * The credentials also saved to the original IPC info as - * rollback data in case the join domain process - * fails in the future. + * The host credentials is also saved to the original IPC info as + * rollback data in case the join domain process fails in the future. */ void smbrdr_ipc_commit() { - unsigned char hexpass[SMBRDR_IPC_HEX_PASSWD_MAXLEN]; - (void) rw_wrlock(&smbrdr_ipc_lock); - smb_config_wrlock(); - (void) smb_config_set(SMB_CI_RDR_IPCUSER, ipc_info.user); - (void) bintohex(ipc_info.passwd, sizeof (ipc_info.passwd), - (char *)hexpass, sizeof (hexpass)); - hexpass[SMBRDR_IPC_HEX_PASSWD_MAXLEN - 1] = 0; - (void) smb_config_set(SMB_CI_RDR_IPCPWD, (char *)hexpass); - - ipc_info.flags &= ~IPC_FLG_NEED_VERIFY; - - if (ipc_info.flags & IPC_FLG_FALLBACK_ANON) { - ipc_info.flags &= ~IPC_FLG_FALLBACK_ANON; - ipc_info.mode = MLSVC_IPC_ADMIN; - (void) smb_config_set(SMB_CI_RDR_IPCMODE, IPC_MODE_AUTH); - syslog(LOG_DEBUG, "smbrdr: (ipc) Authenticated IPC " - "connection has been restored"); - } - + (void) smb_gethostname(ipc_info.user, MLSVC_ACCOUNT_NAME_MAX - 1, 0); + (void) strlcat(ipc_info.user, "$", MLSVC_ACCOUNT_NAME_MAX); + (void) smbrdr_get_machine_pwd_hash(ipc_info.passwd); (void) memcpy(&orig_ipc_info, &ipc_info, sizeof (smbrdr_ipc_t)); - smb_config_unlock(); (void) rw_unlock(&smbrdr_ipc_lock); } @@ -189,29 +151,12 @@ smbrdr_ipc_rollback() sizeof (ipc_info.user)); (void) memcpy(ipc_info.passwd, orig_ipc_info.passwd, sizeof (ipc_info.passwd)); - - ipc_info.flags &= ~IPC_FLG_NEED_VERIFY; - - if (ipc_info.flags & IPC_FLG_FALLBACK_ANON) - ipc_info.mode = MLSVC_IPC_ANON; (void) rw_unlock(&smbrdr_ipc_lock); } /* * Get & Set functions */ -int -smbrdr_ipc_get_mode() -{ - int mode; - - (void) rw_rdlock(&smbrdr_ipc_lock); - mode = ipc_info.mode; - (void) rw_unlock(&smbrdr_ipc_lock); - - return (mode); -} - char * smbrdr_ipc_get_user() { @@ -223,10 +168,10 @@ smbrdr_ipc_get_user() return (user); } -char * +unsigned char * smbrdr_ipc_get_passwd() { - char *passwd; + unsigned char *passwd; (void) rw_rdlock(&smbrdr_ipc_lock); passwd = ipc_info.passwd; @@ -234,67 +179,6 @@ smbrdr_ipc_get_passwd() return (passwd); } -unsigned -smbrdr_ipc_get_flags() -{ - unsigned flags; - - (void) rw_rdlock(&smbrdr_ipc_lock); - flags = ipc_info.flags; - (void) rw_unlock(&smbrdr_ipc_lock); - return (flags); -} - -void -smbrdr_ipc_set_fallback() -{ - (void) rw_wrlock(&smbrdr_ipc_lock); - ipc_info.flags |= IPC_FLG_FALLBACK_ANON; - (void) rw_unlock(&smbrdr_ipc_lock); -} - -void -smbrdr_ipc_unset_fallback() -{ - (void) rw_wrlock(&smbrdr_ipc_lock); - ipc_info.flags &= ~IPC_FLG_FALLBACK_ANON; - (void) rw_unlock(&smbrdr_ipc_lock); -} - -/* - * Whether the smbrdr.ipc.mode is set to fallback,anon or not - */ -int -smbrdr_ipc_is_fallback() -{ - int is_fallback; - - smb_config_rdlock(); - is_fallback = (!strcasecmp(smb_config_getstr(SMB_CI_RDR_IPCMODE), - IPC_MODE_FALLBACK_ANON) ? 1 : 0); - smb_config_unlock(); - - return (is_fallback); -} - -/* - * smbrdr_ipc_save_mode - * - * Set the SMBRDR_IPC_MODE_ENV variable and update the - * IPC mode of the cache. - */ -void -smbrdr_ipc_save_mode(char *val) -{ - (void) rw_wrlock(&smbrdr_ipc_lock); - smb_config_wrlock(); - (void) smb_config_set(SMB_CI_RDR_IPCMODE, val); - ipc_info.mode = !strncasecmp(val, IPC_MODE_AUTH, IPC_MODE_STRLEN) - ? MLSVC_IPC_ADMIN : MLSVC_IPC_ANON; - smb_config_unlock(); - (void) rw_unlock(&smbrdr_ipc_lock); -} - /* * smbrdr_ipc_skip_lsa_query * @@ -305,17 +189,9 @@ smbrdr_ipc_save_mode(char *val) int smbrdr_ipc_skip_lsa_query() { - char *user, *pwd; + char *user; + unsigned char *pwd; - if (ipc_info.mode != MLSVC_IPC_ADMIN) - return (0); - - smb_config_rdlock(); - user = smb_config_get(SMB_CI_RDR_IPCUSER); - pwd = smb_config_get(SMB_CI_RDR_IPCPWD); - smb_config_unlock(); - if ((user == NULL) && pwd) - return (1); (void) rw_rdlock(&smbrdr_ipc_lock); user = ipc_info.user; @@ -324,59 +200,3 @@ smbrdr_ipc_skip_lsa_query() return (!(*user && *pwd)); } - -static char * -smbrdr_ipc_modestr(int mode) -{ - switch (mode) { - case MLSVC_IPC_ANON: - return ("Anonymous"); - - case MLSVC_IPC_ADMIN: - return ("Authenticated"); - - default: - return ("Unknown"); - } -} - -/* - * For debugging purposes only. - */ -void -smbrdr_ipc_loginfo() -{ - smbrdr_ipc_t tmp; - smbrdr_ipc_t tmporg; - - (void) rw_rdlock(&smbrdr_ipc_lock); - (void) memcpy(&tmp, &ipc_info, sizeof (smbrdr_ipc_t)); - (void) memcpy(&tmporg, &orig_ipc_info, sizeof (smbrdr_ipc_t)); - (void) rw_unlock(&smbrdr_ipc_lock); - - syslog(LOG_DEBUG, "smbrdr: current IPC info:"); - syslog(LOG_DEBUG, "\t%s (user=%s, flags:0x%X)", - smbrdr_ipc_modestr(tmp.mode), tmp.user, tmp.flags); - - syslog(LOG_DEBUG, "smbrdr: original IPC info:"); - syslog(LOG_DEBUG, "\t%s (user=%s, flags:0x%X)", - smbrdr_ipc_modestr(tmporg.mode), tmporg.user, tmporg.flags); -} - -/* - * smbrdr_ipc_is_valid - * - * Determine whether the ipc_info has been validated or not. - * - */ -int -smbrdr_ipc_is_valid() -{ - int isvalid; - - (void) rw_rdlock(&smbrdr_ipc_lock); - isvalid = (ipc_info.flags & IPC_FLG_NEED_VERIFY) ? 0 : 1; - (void) rw_unlock(&smbrdr_ipc_lock); - - return (isvalid); -} diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h index a967e91b86..68df733f7c 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h @@ -39,40 +39,15 @@ extern "C" { #endif -#define SMBRDR_IPC_MODE_ENV "smbrdr.ipc.mode" -#define SMBRDR_IPC_USER_ENV "smbrdr.ipc.user" -#define SMBRDR_IPC_PASSWD_ENV "smbrdr.ipc.passwd" - -#define IPC_MODE_STRLEN 4 -#define IPC_MODE_ANON "anon" -#define IPC_MODE_AUTH "auth" -#define IPC_MODE_FALLBACK_ANON "fallback,anon" - -#define IPC_FLG_FALLBACK_ANON 0x00000001 -#define IPC_FLG_NEED_VERIFY 0x00000002 - /* * smbrdr_ipc_t * - * This structure contains information regarding the IPC configuration, - * as well as, the authentication info needed for connecting to the - * IPC$ share if the IPC connection is configured to be authenticated. - * - * IPC connection to the Primary Domain Controller [PDC] can be - * configured to be either anonymous or authenticated. Therefore, - * the IPC mode will be set to either one of the following values: - * MLSVC_IPC_ANON - * MLSVC_IPC_ADMIN - * - * The IPC_FLG_FALLBACK_ANON can be set in flags field to indicate whether - * a fallback from authenticated IPC to anonymous IPC has occurred. This - * flag will be unset once the join domain operation succeeds. + * This structure contains credentials for establishing authenticated + * IPC connection. */ typedef struct { - int mode; char user[MLSVC_ACCOUNT_NAME_MAX]; - char passwd[SMBAUTH_HASH_SZ]; - unsigned flags; + unsigned char passwd[SMBAUTH_HASH_SZ]; } smbrdr_ipc_t; diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c index 7dee7e41d2..d33f253b29 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c @@ -38,66 +38,58 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> - #include <smbsrv/libsmbrdr.h> - #include <smbsrv/ntstatus.h> #include <smbsrv/smb.h> #include <smbrdr_ipc_util.h> #include <smbrdr.h> -#define SMBRDR_PWD_NULL 0 -#define SMBRDR_PWD_USER 1 -#define SMBRDR_PWD_HASH 2 - +static int mlsvc_anonymous_logon(char *domain_controller, char *domain_name); +static int mlsvc_auth_logon(char *domain_controller, char *domain_name, + char *username, unsigned char *pwd_hash); static int smbrdr_smb_session_setupandx(struct sdb_logon *logon); static boolean_t smbrdr_logon_validate(char *server, char *username); static struct sdb_logon *smbrdr_logon_init(struct sdb_session *session, - char *username, char *pwd, int pwd_type); -static int smbrdr_logon_user(char *server, char *username, char *pwd, - int pwd_type); + char *username, unsigned char *pwd); +static int smbrdr_logon_user(char *server, char *username, unsigned char *pwd); static int smbrdr_authenticate(char *primary_domain, char *account_name, - char *pwd, int pwd_type); + unsigned char *pwd); /* - * mlsvc_anonymous_logon + * mlsvc_logon * - * Set up an anonymous session. If the session to the resource domain - * controller appears to be okay we shouldn't need to do anything here. - * Otherwise we clean up the stale session and create a new one. + * If the username is NULL, an anonymous session will be established. + * Otherwise, an authenticated session will be established based on the + * specified credentials. */ int -mlsvc_anonymous_logon(char *domain_controller, char *domain_name, - char **username) +mlsvc_logon(char *domain_controller, char *domain, char *username) { - int rc = 0; + int rc; + unsigned char *pwd_hash = NULL; - if (username == NULL) { - syslog(LOG_ERR, "smbrdr: (anon logon) %s", - xlate_nt_status(NT_STATUS_INVALID_PARAMETER)); - return (-1); + if (username) { + pwd_hash = smbrdr_ipc_get_passwd(); + rc = mlsvc_auth_logon(domain_controller, domain, username, + pwd_hash); + } else { + rc = mlsvc_anonymous_logon(domain_controller, domain); } - /* - * if the system is configured to establish Authenticated IPC - * connection to PDC - */ - if (smbrdr_ipc_get_mode() == MLSVC_IPC_ADMIN) { - rc = mlsvc_admin_logon(domain_controller, domain_name); - /* - * it is possible for the system to fallback to use - * anonymous IPC - */ - if (smbrdr_ipc_get_mode() != MLSVC_IPC_ADMIN) - *username = MLSVC_ANON_USER; - else - *username = smbrdr_ipc_get_user(); - - syslog(LOG_DEBUG, "smbrdr: (admin logon) %s", *username); - return (rc); - } + return (rc); +} - *username = MLSVC_ANON_USER; +/* + * mlsvc_anonymous_logon + * + * Set up an anonymous session. If the session to the resource domain + * controller appears to be okay we shouldn't need to do anything here. + * Otherwise we clean up the stale session and create a new one. + */ +static int +mlsvc_anonymous_logon(char *domain_controller, char *domain_name) +{ + int rc = 0; if (smbrdr_logon_validate(domain_controller, MLSVC_ANON_USER)) /* session & user are good use them */ @@ -110,8 +102,7 @@ mlsvc_anonymous_logon(char *domain_controller, char *domain_name, return (-1); } - if (smbrdr_logon_user(domain_controller, MLSVC_ANON_USER, 0, - SMBRDR_PWD_NULL) < 0) { + if (smbrdr_logon_user(domain_controller, MLSVC_ANON_USER, 0) < 0) { syslog(LOG_ERR, "smbrdr: (anon logon) logon failed"); rc = -1; } @@ -140,7 +131,7 @@ mlsvc_user_getauth(char *domain_controller, char *username, } /* - * mlsvc_user_logon + * mlsvc_auth_logon * * Set up a user session. If the session to the resource domain controller * appears to be okay we shouldn't need to do anything here. Otherwise we @@ -148,44 +139,19 @@ mlsvc_user_getauth(char *domain_controller, char *username, * established, we leave it intact. It should only need to be set up again * due to an inactivity timeout or a domain controller reset. */ -int -mlsvc_user_logon(char *domain_controller, char *domain_name, char *username, - char *password) +static int +mlsvc_auth_logon(char *domain_controller, char *domain_name, char *username, + unsigned char *pwd_hash) { int erc; - if (smbrdr_logon_validate(domain_controller, username)) - return (0); - - if (smbrdr_negotiate(domain_name) != 0) { - syslog(LOG_ERR, "smbrdr: (user logon) negotiate failed"); + if (username == NULL || *username == 0) { + syslog(LOG_ERR, "smbrdr: auth logon (no username)"); return (-1); } - erc = smbrdr_authenticate(domain_name, username, password, - SMBRDR_PWD_USER); - - return ((erc == AUTH_USER_GRANT) ? 0 : -1); -} - -/* - * mlsvc_admin_logon - * - * Unlike mlsvc_user_logon, mlsvc_admin_logon doesn't take - * any username or password as function arguments. - */ -int -mlsvc_admin_logon(char *domain_controller, char *domain_name) -{ - char password[PASS_LEN + 1]; - int erc; - char *username, *dummy; - - username = smbrdr_ipc_get_user(); - (void) memcpy(password, smbrdr_ipc_get_passwd(), SMBAUTH_HASH_SZ); - - if (*username == 0) { - syslog(LOG_ERR, "smbrdr: admin logon (no admin user)"); + if (!pwd_hash || *pwd_hash == 0) { + syslog(LOG_ERR, "smbrdr: auth logon (no password)"); return (-1); } @@ -197,24 +163,7 @@ mlsvc_admin_logon(char *domain_controller, char *domain_name) return (-1); } - erc = smbrdr_authenticate(domain_name, username, password, - SMBRDR_PWD_HASH); - - /* - * Fallback to anonmyous IPC logon if the IPC password hash is no - * longer valid. It happens when the administrator password has - * been reset from the Domain Controller. - */ - if (erc < 0 && smbrdr_ipc_is_valid()) { - if (!smbrdr_ipc_is_fallback()) - syslog(LOG_DEBUG, "smbrdr: admin logon " - "(fallback to anonymous IPC)"); - smbrdr_ipc_set_fallback(); - smbrdr_ipc_save_mode(IPC_MODE_FALLBACK_ANON); - erc = mlsvc_anonymous_logon(domain_controller, domain_name, - &dummy); - } - + erc = smbrdr_authenticate(domain_name, username, pwd_hash); return ((erc == AUTH_USER_GRANT) ? 0 : -1); } @@ -231,7 +180,7 @@ mlsvc_admin_logon(char *domain_controller, char *domain_name) */ static int smbrdr_authenticate(char *primary_domain, char *account_name, - char *pwd, int pwd_type) + unsigned char *pwd) { smb_ntdomain_t *di; @@ -267,7 +216,7 @@ smbrdr_authenticate(char *primary_domain, char *account_name, return (-2); } - return (smbrdr_logon_user(di->server, account_name, pwd, pwd_type)); + return (smbrdr_logon_user(di->server, account_name, pwd)); } /* @@ -284,14 +233,14 @@ smbrdr_authenticate(char *primary_domain, char *account_name, * pointer will be returned. */ static int -smbrdr_logon_user(char *server, char *username, char *pwd, int pwd_type) +smbrdr_logon_user(char *server, char *username, unsigned char *pwd) { struct sdb_session *session; struct sdb_logon *logon; struct sdb_logon old_logon; - if (server == 0 || username == 0 || - ((pwd == 0) && (pwd_type != SMBRDR_PWD_NULL))) { + if ((server == NULL) || (username == NULL) || + ((strcmp(username, MLSVC_ANON_USER) != 0) && (pwd == NULL))) { return (-1); } @@ -316,7 +265,7 @@ smbrdr_logon_user(char *server, char *username, char *pwd, int pwd_type) old_logon = *logon; } - logon = smbrdr_logon_init(session, username, pwd, pwd_type); + logon = smbrdr_logon_init(session, username, pwd); if (logon == 0) { syslog(LOG_ERR, "smbrdr: (logon[%s]) resource shortage", @@ -618,10 +567,10 @@ smbrdr_smb_logoff(struct sdb_logon *logon) */ static struct sdb_logon * smbrdr_logon_init(struct sdb_session *session, char *username, - char *pwd, int pwd_type) + unsigned char *pwd) { struct sdb_logon *logon; - int smbrdr_lmcomplvl; + int smbrdr_lmcompl; int rc; logon = (struct sdb_logon *)malloc(sizeof (sdb_logon_t)); @@ -631,52 +580,28 @@ smbrdr_logon_init(struct sdb_session *session, char *username, bzero(logon, sizeof (struct sdb_logon)); logon->session = session; - if (strcmp(username, "IPC$") == 0) - logon->type = SDB_LOGON_ANONYMOUS; - else - logon->type = SDB_LOGON_USER; - - (void) strlcpy(logon->username, username, MAX_ACCOUNT_NAME); - smb_config_rdlock(); - smbrdr_lmcomplvl = smb_config_getnum(SMB_CI_LM_LEVEL); + smbrdr_lmcompl = smb_config_getnum(SMB_CI_LM_LEVEL); smb_config_unlock(); - switch (pwd_type) { - case SMBRDR_PWD_USER: - rc = smb_auth_set_info(username, pwd, 0, session->di.domain, - session->challenge_key, session->challenge_len, - smbrdr_lmcomplvl, &logon->auth); - - if (rc != 0) { - free(logon); - return (0); - } - break; - - case SMBRDR_PWD_HASH: - rc = smb_auth_set_info(username, 0, (unsigned char *)pwd, + if (strcmp(username, "IPC$") == 0) { + logon->type = SDB_LOGON_ANONYMOUS; + logon->auth.ci_len = 1; + *(logon->auth.ci) = 0; + logon->auth.cs_len = 0; + } else { + logon->type = SDB_LOGON_USER; + rc = smb_auth_set_info(username, 0, pwd, session->di.domain, session->challenge_key, - session->challenge_len, smbrdr_lmcomplvl, &logon->auth); + session->challenge_len, smbrdr_lmcompl, &logon->auth); if (rc != 0) { free(logon); return (0); } - break; - - case SMBRDR_PWD_NULL: - logon->auth.ci_len = 1; - *(logon->auth.ci) = 0; - logon->auth.cs_len = 0; - break; - - default: - /* Unknown password type */ - free(logon); - return (0); } + (void) strlcpy(logon->username, username, MAX_ACCOUNT_NAME); logon->state = SDB_LSTATE_INIT; return (logon); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/i386/Makefile b/usr/src/lib/smbsrv/libsmbrdr/i386/Makefile index f91f0270e9..710c9eb3dd 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/i386/Makefile +++ b/usr/src/lib/smbsrv/libsmbrdr/i386/Makefile @@ -27,4 +27,6 @@ include ../Makefile.com +DYNFLAGS += -R/usr/lib/smbsrv + install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libsmbrdr/sparc/Makefile b/usr/src/lib/smbsrv/libsmbrdr/sparc/Makefile index f91f0270e9..710c9eb3dd 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/sparc/Makefile +++ b/usr/src/lib/smbsrv/libsmbrdr/sparc/Makefile @@ -27,4 +27,6 @@ include ../Makefile.com +DYNFLAGS += -R/usr/lib/smbsrv + install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libsmbrdr/sparcv9/Makefile b/usr/src/lib/smbsrv/libsmbrdr/sparcv9/Makefile index a2f97019c8..b3c4916b0c 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/sparcv9/Makefile +++ b/usr/src/lib/smbsrv/libsmbrdr/sparcv9/Makefile @@ -25,7 +25,11 @@ # ident "%Z%%M% %I% %E% SMI" # +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) + include ../Makefile.com include ../../../Makefile.lib.64 +DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) + install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/pkgdefs/SUNWsmbsu/depend b/usr/src/pkgdefs/SUNWsmbsu/depend index 53c41eedf3..1d28a9c7ae 100644 --- a/usr/src/pkgdefs/SUNWsmbsu/depend +++ b/usr/src/pkgdefs/SUNWsmbsu/depend @@ -53,3 +53,6 @@ P SUNWcsd Core Solaris Devices P SUNWcsl Core Solaris Libraries P SUNWsmbskr SMB Kernel (Root) P SUNWsmbsr SMB Server (Root) +P SUNWlxml The XML library +P SUNWgss GSSAPI V2 +P SUNWkrbu Kerberos version 5 support (Usr) diff --git a/usr/src/pkgdefs/etc/exception_list_i386 b/usr/src/pkgdefs/etc/exception_list_i386 index 6071c22139..12e706fc7d 100644 --- a/usr/src/pkgdefs/etc/exception_list_i386 +++ b/usr/src/pkgdefs/etc/exception_list_i386 @@ -962,7 +962,6 @@ usr/include/smbsrv/smb_incl.h i386 usr/include/smbsrv/smb_ioctl.h i386 usr/include/smbsrv/smb_kproto.h i386 usr/include/smbsrv/smb_privilege.h i386 -usr/include/smbsrv/smb_secdesc.h i386 usr/include/smbsrv/smb_svc_sm.h i386 usr/include/smbsrv/smb_token.h i386 usr/include/smbsrv/smb_vops.h i386 @@ -1003,6 +1002,25 @@ usr/lib/smbsrv/dtrace/smbnode.d i386 usr/lib/smbsrv/dtrace/smbvfs.d i386 usr/lib/smbsrv/dtrace/stype.d i386 # +# Private/Internal 64-bit libraries of smbsrv. Do not ship. +# +usr/lib/smbsrv/amd64 i386 +usr/lib/smbsrv/amd64/libsmb.so.1 i386 +usr/lib/smbsrv/amd64/libsmb.so i386 +usr/lib/smbsrv/amd64/llib-lsmb.ln i386 +usr/lib/smbsrv/amd64/libmlrpc.so.1 i386 +usr/lib/smbsrv/amd64/libmlrpc.so i386 +usr/lib/smbsrv/amd64/llib-lmlrpc.ln i386 +usr/lib/smbsrv/amd64/libmlsvc.so.1 i386 +usr/lib/smbsrv/amd64/libmlsvc.so i386 +usr/lib/smbsrv/amd64/llib-lmlsvc.ln i386 +usr/lib/smbsrv/amd64/libsmbns.so.1 i386 +usr/lib/smbsrv/amd64/libsmbns.so i386 +usr/lib/smbsrv/amd64/llib-lsmbns.ln i386 +usr/lib/smbsrv/amd64/libsmbrdr.so.1 i386 +usr/lib/smbsrv/amd64/libsmbrdr.so i386 +usr/lib/smbsrv/amd64/llib-lsmbrdr.ln i386 +# # Private dirent, extended to include flags, for use by SMB server # usr/include/sys/extdirent.h i386 diff --git a/usr/src/pkgdefs/etc/exception_list_sparc b/usr/src/pkgdefs/etc/exception_list_sparc index 9c344612ac..2fbae8d861 100644 --- a/usr/src/pkgdefs/etc/exception_list_sparc +++ b/usr/src/pkgdefs/etc/exception_list_sparc @@ -1047,7 +1047,6 @@ usr/include/smbsrv/smb_incl.h sparc usr/include/smbsrv/smb_ioctl.h sparc usr/include/smbsrv/smb_kproto.h sparc usr/include/smbsrv/smb_privilege.h sparc -usr/include/smbsrv/smb_secdesc.h sparc usr/include/smbsrv/smb_svc_sm.h sparc usr/include/smbsrv/smb_token.h sparc usr/include/smbsrv/smb_vops.h sparc @@ -1088,6 +1087,25 @@ usr/lib/smbsrv/dtrace/smbnode.d sparc usr/lib/smbsrv/dtrace/smbvfs.d sparc usr/lib/smbsrv/dtrace/stype.d sparc # +# Private/Internal 64 bit libraries of smbsrv. Do not ship. +# +usr/lib/smbsrv/sparcv9 sparc +usr/lib/smbsrv/sparcv9/libsmb.so.1 sparc +usr/lib/smbsrv/sparcv9/libsmb.so sparc +usr/lib/smbsrv/sparcv9/llib-lsmb.ln sparc +usr/lib/smbsrv/sparcv9/libmlrpc.so.1 sparc +usr/lib/smbsrv/sparcv9/libmlrpc.so sparc +usr/lib/smbsrv/sparcv9/llib-lmlrpc.ln sparc +usr/lib/smbsrv/sparcv9/libmlsvc.so.1 sparc +usr/lib/smbsrv/sparcv9/libmlsvc.so sparc +usr/lib/smbsrv/sparcv9/llib-lmlsvc.ln sparc +usr/lib/smbsrv/sparcv9/libsmbns.so.1 sparc +usr/lib/smbsrv/sparcv9/libsmbns.so sparc +usr/lib/smbsrv/sparcv9/llib-lsmbns.ln sparc +usr/lib/smbsrv/sparcv9/libsmbrdr.so.1 sparc +usr/lib/smbsrv/sparcv9/libsmbrdr.so sparc +usr/lib/smbsrv/sparcv9/llib-lsmbrdr.ln sparc +# # Private dirent, extended to include flags, for use by SMB server # usr/include/sys/extdirent.h sparc diff --git a/usr/src/tools/abi/etc/exceptions b/usr/src/tools/abi/etc/exceptions index 894fe5e5aa..a088ba4886 100644 --- a/usr/src/tools/abi/etc/exceptions +++ b/usr/src/tools/abi/etc/exceptions @@ -444,6 +444,16 @@ PSARC 2006/715: RULE W3: usr/lib/smbsrv/libmlsvc.so.1 PSARC 2006/715: RULE W3: usr/lib/smbsrv/libsmb.so.1 PSARC 2006/715: RULE W3: usr/lib/smbsrv/libsmbns.so.1 PSARC 2006/715: RULE W3: usr/lib/smbsrv/libsmbrdr.so.1 +PSARC 2006/715: RULE W3: usr/lib/smbsrv/amd64/libmlrpc.so.1 +PSARC 2006/715: RULE W3: usr/lib/smbsrv/amd64/libmlsvc.so.1 +PSARC 2006/715: RULE W3: usr/lib/smbsrv/amd64/libsmb.so.1 +PSARC 2006/715: RULE W3: usr/lib/smbsrv/amd64/libsmbns.so.1 +PSARC 2006/715: RULE W3: usr/lib/smbsrv/amd64/libsmbrdr.so.1 +PSARC 2006/715: RULE W3: usr/lib/smbsrv/sparcv9/libmlrpc.so.1 +PSARC 2006/715: RULE W3: usr/lib/smbsrv/sparcv9/libmlsvc.so.1 +PSARC 2006/715: RULE W3: usr/lib/smbsrv/sparcv9/libsmb.so.1 +PSARC 2006/715: RULE W3: usr/lib/smbsrv/sparcv9/libsmbns.so.1 +PSARC 2006/715: RULE W3: usr/lib/smbsrv/sparcv9/libsmbrdr.so.1 ############################################# # WARNINGs exempted from RULE W4 (See RULES section of intf_check manpage) diff --git a/usr/src/tools/findunref/exception_list b/usr/src/tools/findunref/exception_list index f1da587095..e0ab7dd900 100644 --- a/usr/src/tools/findunref/exception_list +++ b/usr/src/tools/findunref/exception_list @@ -209,16 +209,6 @@ ./src/uts/sparc/uhci/Makefile ./src/lib/pam_modules/smb/amd64/Makefile ./src/lib/pam_modules/smb/sparcv9/Makefile -./src/lib/smbsrv/libmlrpc/amd64/Makefile -./src/lib/smbsrv/libmlrpc/sparcv9/Makefile -./src/lib/smbsrv/libmlsvc/amd64/Makefile -./src/lib/smbsrv/libmlsvc/sparcv9/Makefile -./src/lib/smbsrv/libsmb/amd64/Makefile -./src/lib/smbsrv/libsmb/sparcv9/Makefile -./src/lib/smbsrv/libsmbns/amd64/Makefile -./src/lib/smbsrv/libsmbns/sparcv9/Makefile -./src/lib/smbsrv/libsmbrdr/amd64/Makefile -./src/lib/smbsrv/libsmbrdr/sparcv9/Makefile # # Ignore dtrace scripts only used by developers diff --git a/usr/src/uts/common/fs/smbsrv/smb_acl.c b/usr/src/uts/common/fs/smbsrv/smb_acl.c index 2617268d9e..5491e927f1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_acl.c +++ b/usr/src/uts/common/fs/smbsrv/smb_acl.c @@ -25,68 +25,15 @@ #pragma ident "%Z%%M% %I% %E% SMI" -/* - * Platform SDK: Security - * - * ACE Inheritance Rules - * - * The system propagates inheritable ACEs to child objects according to a - * set of inheritance rules. The system places inherited ACEs in the child's - * DACL according to the preferred order of ACEs in a DACL. For Windows - * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs. - * - * The following table shows the ACEs inherited by container and noncontainer - * child objects for different combinations of inheritance flags. These - * inheritance rules work the same for both DACLs and SACLs. - * - * Parent ACE type Effect on Child ACL - * ----------------------- ------------------- - * OBJECT_INHERIT_ACE only Noncontainer child objects: - * Inherited as an effective ACE. - * Container child objects: - * Containers inherit an inherit-only ACE - * unless the NO_PROPAGATE_INHERIT_ACE bit - * flag is also set. - * - * CONTAINER_INHERIT_ACE only Noncontainer child objects: - * No effect on the child object. - * Container child objects: - * The child object inherits an effective ACE. - * The inherited ACE is inheritable unless the - * NO_PROPAGATE_INHERIT_ACE bit flag is also set. - * - * CONTAINER_INHERIT_ACE and - * OBJECT_INHERIT_ACE Noncontainer child objects: - * Inherited as an effective ACE. - * Container child objects: - * The child object inherits an effective ACE. - * The inherited ACE is inheritable unless the - * NO_PROPAGATE_INHERIT_ACE bit flag is also set - * - * No inheritance flags set No effect on child container or noncontainer - * objects. - * - * If an inherited ACE is an effective ACE for the child object, the system - * maps any generic rights to the specific rights for the child object. - * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the - * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic - * rights or generic SIDs are left unchanged so that they can be mapped - * appropriately when the ACE is inherited by the next generation of child - * objects. - * - * For a case in which a container object inherits an ACE that is both - * effective on the container and inheritable by its descendants, the - * container may inherit two ACEs. This occurs if the inheritable ACE - * contains generic information. The container inherits an inherit-only - * ACE containing the generic information and an effective-only ACE in - * which the generic information has been mapped. - */ - #include <sys/acl.h> -#include <smbsrv/smb_incl.h> +#include <acl/acl_common.h> #include <smbsrv/ntsid.h> #include <smbsrv/smb_fsops.h> #include <smbsrv/smb_idmap.h> +#include <smbsrv/smb_kproto.h> +#include <smbsrv/smbvar.h> +#include <smbsrv/ntstatus.h> +#include <smbsrv/ntaccess.h> #define ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE) @@ -111,195 +58,143 @@ #define ZACE_IS_CREATOR(zace) \ (ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace)) -static int smb_ace_isvalid(smb_ace_hdr_t *ace, int which_acl); -static int smb_ace_append_generic(smb_acl_t *acl, void *generic_ace); - -static int smb_ace_common_add( - smb_acl_t *acl, - uint8_t type, - uint8_t flags, - uint32_t access_mask, - nt_sid_t *sid); - -static void smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir); -static uint16_t smb_ace_flags_tozfs(uint8_t c_flags, int isdir); -static uint8_t smb_ace_flags_fromzfs(uint16_t z_flags); -static void smb_acl_init(smb_acl_t *acl, uint16_t size, uint8_t rev); - -static int -smb_ace_isvalid(smb_ace_hdr_t *ace, int which_acl) -{ - uint16_t min_len; - smb_ace_t *p; +/* + * ACE groups within a DACL + * + * This is from lower to higher ACE order priority + */ +#define SMB_AG_START 0 +#define SMB_AG_ALW_INHRT 0 +#define SMB_AG_DNY_INHRT 1 +#define SMB_AG_ALW_DRCT 2 +#define SMB_AG_DNY_DRCT 3 +#define SMB_AG_NUM 4 - min_len = sizeof (smb_ace_hdr_t); +/* + * SID for Everyone group: S-1-1-0. + */ +nt_sid_t everyone_sid = { + NT_SID_REVISION, + 1, + NT_SECURITY_WORLD_AUTH, + { 0 } +}; - if (ace->se_size < min_len) - return (0); +#define DEFAULT_DACL_ACENUM 2 +/* + * Default ACL: + * owner: full access + * SYSTEM: full access + */ +static ace_t default_dacl[DEFAULT_DACL_ACENUM] = { + { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE }, + { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP, + ACE_ACCESS_ALLOWED_ACE_TYPE } +}; - if (smb_ace_is_access(ace->se_type) && - (which_acl != SMB_DACL_SECINFO)) { - return (0); - } +/* + * Note: + * + * smb_acl_xxx functions work with smb_acl_t which represents the CIFS format + * smb_fsacl_xxx functions work with acl_t which represents the Solaris native + * format + */ - if (smb_ace_is_audit(ace->se_type) && - (which_acl != SMB_SACL_SECINFO)) { - return (0); - } +static idmap_stat smb_acl_getsids(smb_idmap_batch_t *, acl_t *, uid_t, gid_t); +static acl_t *smb_acl_null_empty(boolean_t null); - if (smb_ace_is_generic(ace->se_type)) { - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - p = (smb_ace_t *)ace; +static int smb_fsacl_inheritable(acl_t *, int); - if (ace->se_size < sizeof (*p)) - return (0); /* won't handle empty SubAuthority[] */ - if (nt_sid_is_valid(&p->se_sid) == 0) - return (0); +static void smb_ace_inherit(ace_t *, ace_t *, int); +static boolean_t smb_ace_isvalid(smb_ace_t *, int); +static uint16_t smb_ace_len(smb_ace_t *); +static uint32_t smb_ace_mask_g2s(uint32_t); +static uint16_t smb_ace_flags_tozfs(uint8_t, int); +static uint8_t smb_ace_flags_fromzfs(uint16_t); - min_len += sizeof (p->se_mask); - min_len += nt_sid_length(&p->se_sid); +smb_acl_t * +smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt) +{ + smb_acl_t *acl; + int size; - if (ace->se_size < min_len) - return (0); - } + size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t)); + acl = kmem_zalloc(size, KM_SLEEP); + acl->sl_revision = revision; + acl->sl_bsize = bsize; + acl->sl_acecnt = acecnt; + acl->sl_aces = (smb_ace_t *)(acl + 1); - /* - * XXX object-specific ACE validation will be added later. - */ - return (1); + list_create(&acl->sl_sorted, sizeof (smb_ace_t), + offsetof(smb_ace_t, se_sln)); + return (acl); } -int -smb_acl_isvalid(smb_acl_t *acl, int which_acl) +void +smb_acl_free(smb_acl_t *acl) { - uint16_t min_len; - unsigned char *scan; - unsigned char *scan_end; - smb_ace_hdr_t *ace; - uint16_t count = 0; - - min_len = sizeof (smb_acl_t); - - if (acl->sl_size < min_len) - return (0); - - if (acl->sl_revision != ACL_REVISION) { - /* - * XXX we are rejecting ACLs with object-specific ACEs for now - */ - return (0); - } + int i, size; + void *ace; - scan = (unsigned char *) &acl[0]; - scan_end = scan + acl->sl_size; - scan = (unsigned char *) &acl[1]; /* skip Acl header */ + if (acl == NULL) + return; - while (count < acl->sl_acecnt && scan < scan_end) { - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - ace = (smb_ace_hdr_t *)scan; - - if (scan + sizeof (smb_ace_hdr_t) >= scan_end) - return (0); - - if (scan + ace->se_size > scan_end) - return (0); /* overflow */ - - if (!smb_ace_isvalid(ace, which_acl)) - return (0); - - scan += ace->se_size; - count++; + for (i = 0; i < acl->sl_acecnt; i++) { + MEM_FREE("smbsrv", acl->sl_aces[i].se_sid); } - return (1); -} - + while ((ace = list_head(&acl->sl_sorted)) != NULL) + list_remove(&acl->sl_sorted, ace); + list_destroy(&acl->sl_sorted); -static void -smb_acl_init(smb_acl_t *acl, uint16_t size, uint8_t rev) -{ - bzero(acl, size); - acl->sl_revision = rev; - acl->sl_size = size; + size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t)); + kmem_free(acl, size); } +/* + * smb_acl_len + * + * Returns the size of given ACL in bytes. Note that this + * is not an in-memory size, it's the ACL's size as it would + * appear on the wire + */ uint16_t smb_acl_len(smb_acl_t *acl) { - smb_ace_hdr_t *ace; - unsigned char *scan_beg; - unsigned char *scan_end; - unsigned char *scan; - uint16_t length; - uint16_t count; - - scan_beg = (unsigned char *) &acl[0]; - scan_end = scan_beg + acl->sl_size; - scan = (unsigned char *) &acl[1]; - length = sizeof (smb_acl_t); - count = 0; - - while ((count < acl->sl_acecnt) && (scan < scan_end)) { - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - ace = (smb_ace_hdr_t *)scan; - length += ace->se_size; - scan += ace->se_size; - count++; - } + if (acl == NULL) + return (0); - return (length); + return (acl->sl_bsize); } -/* - * Append the generic ACE to the ACL. This is used to put any - * kind of ACE on the ACL so the argument is declared as a void*. We cast it - * to an ACCESS_ALLOWED_ACE just because there is no sense of a generic ACE. - */ -static int -smb_ace_append_generic(smb_acl_t *acl, void *generic_ace) +boolean_t +smb_acl_isvalid(smb_acl_t *acl, int which_acl) { - smb_ace_t *ace = (smb_ace_t *)generic_ace; - uint16_t acl_len = smb_acl_len(acl); - unsigned char *scan = (uchar_t *)acl; + int i; - if ((acl_len + ace->se_header.se_size) > acl->sl_size) { - /* no room in the acl for this ace */ - return (0); + if (acl->sl_bsize < SMB_ACL_HDRSIZE) + return (B_FALSE); + + if (acl->sl_revision != ACL_REVISION) { + /* + * we are rejecting ACLs with object-specific ACEs for now + */ + return (B_FALSE); } - /* append the ace to the acl and inc ace count */ - bcopy(ace, &scan[acl_len], ace->se_header.se_size); - acl->sl_acecnt++; + for (i = 0; i < acl->sl_acecnt; i++) { + if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl)) + return (B_FALSE); + } - return (1); + return (B_TRUE); } /* - * Helper for the ACL sort routine - */ -typedef struct smb_ace_entry { - smb_ace_t *e_ace; - list_node_t e_node; -} smb_ace_entry_t; - -/* - * ACE groups within a DACL - * - * This is from lower to higher ACE order priority - */ -#define SMB_AG_START 0 -#define SMB_AG_ALW_INHRT 0 -#define SMB_AG_DNY_INHRT 1 -#define SMB_AG_ALW_DRCT 2 -#define SMB_AG_DNY_DRCT 3 -#define SMB_AG_NUM 4 - -/* - * smb_acl_do_sort + * smb_acl_sort * - * Sorts the given ACL, acl, and returns the result - * in a newly allocated memory. + * Sorts the given ACL in place if it needs to be sorted. * * The following is an excerpt from MSDN website. * @@ -327,82 +222,20 @@ typedef struct smb_ace_entry { * . Access-allowed ACEs that apply to the object itself * . Access-allowed ACEs that apply to a subobject of the object * - * Of course, not all ACE types are required in an ACL. - */ -static smb_acl_t * -smb_acl_do_sort(smb_acl_t *acl, list_t *ace_grps) -{ - smb_acl_t *sorted_acl; - smb_ace_entry_t *nae; - int i; - - sorted_acl = kmem_alloc(acl->sl_size, KM_SLEEP); - *sorted_acl = *acl; - - /* start with no ACE in the sorted ACL */ - sorted_acl->sl_acecnt = 0; - - /* - * start with highest priority ACE group and append - * the ACEs to the ACL. - */ - for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) { - nae = list_head(&ace_grps[i]); - while (nae) { - if (!smb_ace_append_generic(sorted_acl, nae->e_ace)) { - kmem_free(sorted_acl, acl->sl_size); - return (NULL); - } - nae = list_next(&ace_grps[i], nae); - } - } - - return (sorted_acl); -} - -/* - * smb_acl_need_sort - * - * Here is the desired ACE order + * So, here is the desired ACE order * * deny-direct, allow-direct, deny-inherited, allow-inherited * - * If any ace has been encountered which belongs to a group - * with lower priority of the specified ace_grp then the acl - * should be sorted. - */ -static int -smb_acl_need_sort(list_t *ace_grps, int ace_grp) -{ - int i; - - for (i = SMB_AG_START; i < ace_grp; i++) - if (!list_is_empty(&ace_grps[i])) - return (1); - - return (0); -} - -/* - * smb_acl_sort - * - * Returns NULL upon failure. - * Returns pointer to the passed (original) acl if no sort is required. - * Returns pointer to a new acl upon successful sort in which case the - * caller is responsible for freeing the allocated memory. + * Of course, not all ACE types are required in an ACL. */ -smb_acl_t * +void smb_acl_sort(smb_acl_t *acl) { - smb_acl_t *sorted_acl; - smb_ace_t *ace; - smb_ace_entry_t *ace_list; - int ace_list_size; list_t ace_grps[SMB_AG_NUM]; - int ag; - int do_sort = 0; - uint16_t i; + list_t *alist; + smb_ace_t *ace; uint8_t ace_flags; + int ag, i; ASSERT(acl); @@ -411,46 +244,26 @@ smb_acl_sort(smb_acl_t *acl) * ACL with no entry is a valid ACL and it means * no access for anybody. */ - return (acl); + return; } for (i = SMB_AG_START; i < SMB_AG_NUM; i++) { - list_create(&ace_grps[i], sizeof (smb_ace_entry_t), - offsetof(smb_ace_entry_t, e_node)); + list_create(&ace_grps[i], sizeof (smb_ace_t), + offsetof(smb_ace_t, se_sln)); } - /* - * Allocate the helper entries to group the ACEs based on - * the desired priorities. - */ - ace_list_size = sizeof (smb_ace_entry_t) * acl->sl_acecnt; - ace_list = kmem_alloc(ace_list_size, KM_SLEEP); - - for (i = 0; i < acl->sl_acecnt; ++i) { - ace_list[i].e_ace = smb_ace_get(acl, i); - ace = ace_list[i].e_ace; - ASSERT(ace); + for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) { + ace_flags = ace->se_hdr.se_flags; - ace_flags = ace->se_header.se_flags; - - switch (ace->se_header.se_type) { + switch (ace->se_hdr.se_type) { case ACCESS_DENIED_ACE_TYPE: - if (ace_flags & INHERITED_ACE) { - ag = SMB_AG_DNY_INHRT; - do_sort |= smb_acl_need_sort(ace_grps, ag); - } else { - ag = SMB_AG_DNY_DRCT; - do_sort |= smb_acl_need_sort(ace_grps, ag); - } + ag = (ace_flags & INHERITED_ACE) ? + SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT; break; case ACCESS_ALLOWED_ACE_TYPE: - if (ace_flags & INHERITED_ACE) { - ag = SMB_AG_ALW_INHRT; - } else { - ag = SMB_AG_ALW_DRCT; - do_sort |= smb_acl_need_sort(ace_grps, ag); - } + ag = (ace_flags & INHERITED_ACE) ? + SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT; break; default: @@ -462,185 +275,177 @@ smb_acl_sort(smb_acl_t *acl) break; } - /* Put the element on the appropriate list */ - list_insert_tail(&ace_grps[ag], &ace_list[i]); + /* Add the ACE to the selected group */ + list_insert_tail(&ace_grps[ag], ace); } - if (do_sort) - sorted_acl = smb_acl_do_sort(acl, ace_grps); - else - sorted_acl = acl; - - for (i = SMB_AG_START; i < SMB_AG_NUM; i++) { - void *ent; - list_t *alist = &ace_grps[i]; - - while ((ent = list_head(alist)) != NULL) - list_remove(alist, ent); + /* + * start with highest priority ACE group and append + * the ACEs to the ACL. + */ + for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) { + alist = &ace_grps[i]; + while ((ace = list_head(alist)) != NULL) { + list_remove(alist, ace); + list_insert_tail(&acl->sl_sorted, ace); + } list_destroy(alist); } - - kmem_free(ace_list, ace_list_size); - - return (sorted_acl); } -static int -smb_ace_common_add( - smb_acl_t *acl, - uint8_t type, - uint8_t flags, - uint32_t access_mask, - nt_sid_t *sid) +/* + * smb_acl_from_zfs + * + * Converts given ZFS ACL to a Windows ACL. + * + * A pointer to allocated memory for the Win ACL will be + * returned upon successful conversion. + */ +smb_acl_t * +smb_acl_from_zfs(acl_t *zacl, uid_t uid, gid_t gid) { + ace_t *zace; + int numaces; + smb_acl_t *acl; smb_ace_t *ace; - unsigned char *scan = (unsigned char *) acl; - uint16_t used = smb_acl_len(acl); - uint16_t sid_len = nt_sid_length(sid); - uint16_t size; + smb_idmap_batch_t sib; + smb_idmap_t *sim; + idmap_stat idm_stat; - size = sizeof (ace->se_header) + sizeof (ace->se_mask) + sid_len; + idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt, + SMB_IDMAP_ID2SID); + if (idm_stat != IDMAP_SUCCESS) + return (NULL); - if (size + used > acl->sl_size) { - /* won't fit */ - return (0); + if (smb_acl_getsids(&sib, zacl, uid, gid) != IDMAP_SUCCESS) { + smb_idmap_batch_destroy(&sib); + return (NULL); } - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - ace = (smb_ace_t *)&scan[used]; + acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt); + + sim = sib.sib_maps; + for (numaces = 0, zace = zacl->acl_aclp; + numaces < zacl->acl_cnt; + zace++, numaces++, sim++) { + ASSERT(sim->sim_sid); + if (sim->sim_sid == NULL) { + smb_acl_free(acl); + acl = NULL; + break; + } - ace->se_header.se_type = type; - ace->se_header.se_flags = flags; - ace->se_header.se_size = size; - ace->se_mask = access_mask; - bcopy(sid, &ace->se_sid, sid_len); + ace = &acl->sl_aces[numaces]; + ace->se_hdr.se_type = zace->a_type; + ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags); + ace->se_mask = zace->a_access_mask; + ace->se_sid = nt_sid_dup(sim->sim_sid); + ace->se_hdr.se_bsize = smb_ace_len(ace); - acl->sl_acecnt++; + acl->sl_bsize += ace->se_hdr.se_bsize; + } - return (1); + smb_idmap_batch_destroy(&sib); + return (acl); } -smb_ace_t * -smb_ace_get(smb_acl_t *acl, uint16_t idx) +/* + * smb_acl_to_zfs + * + * Converts given Windows ACL to a ZFS ACL. + * + * fs_acl will contain a pointer to the created ZFS ACL. + * The allocated memory should be freed by calling + * smb_fsacl_free(). + * + * Since the output parameter, fs_acl, is allocated in this + * function, the caller has to make sure *fs_acl is NULL which + * means it's not pointing to any memory. + */ +uint32_t +smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) { smb_ace_t *ace; - unsigned char *scan_beg = (unsigned char *) &acl[0]; - unsigned char *scan_end = scan_beg + acl->sl_size; - unsigned char *scan = (unsigned char *) &acl[1]; - uint16_t count = 0; + acl_t *zacl; + ace_t *zace; + smb_idmap_batch_t sib; + smb_idmap_t *sim; + idmap_stat idm_stat; + int i, isdir; - if (idx >= acl->sl_acecnt) - return (NULL); + ASSERT(fs_acl); + ASSERT(*fs_acl == NULL); - while (count <= idx && scan < scan_end) { - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - ace = (smb_ace_t *)scan; + if (acl && !smb_acl_isvalid(acl, which_acl)) + return (NT_STATUS_INVALID_ACL); - if (count == idx) { - return (ace); + if ((acl == NULL) || (acl->sl_acecnt == 0)) { + if (which_acl == SMB_DACL_SECINFO) { + *fs_acl = smb_acl_null_empty(acl == NULL); } - scan += ace->se_header.se_size; - count++; + return (NT_STATUS_SUCCESS); } - return (NULL); -} - -int -smb_acl_copy(uint16_t buflen, smb_acl_t *dst_acl, smb_acl_t *src_acl) -{ - smb_ace_hdr_t *dst_ace; - smb_ace_hdr_t *src_ace; - unsigned char *scan = (unsigned char *) &src_acl[1]; - unsigned char *dest_beg = (unsigned char *) &dst_acl[0]; - unsigned char *dest_end; - unsigned char *dest = (unsigned char *) &dst_acl[1]; - uint16_t count = 0; - uint16_t n_bytes; - - n_bytes = smb_acl_len(src_acl); - if (n_bytes > buflen) - return (0); + idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt, + SMB_IDMAP_SID2ID); + if (idm_stat != IDMAP_SUCCESS) + return (NT_STATUS_INTERNAL_ERROR); - dest_end = dest_beg + n_bytes; - - dst_acl->sl_revision = src_acl->sl_revision; - dst_acl->sl_sbz1 = 0; - dst_acl->sl_size = n_bytes; - dst_acl->sl_acecnt = 0; - dst_acl->sl_sbz2 = 0; - - while (count < src_acl->sl_acecnt && dest < dest_end) { - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - src_ace = (smb_ace_hdr_t *)scan; - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - dst_ace = (smb_ace_hdr_t *)dest; - bcopy(src_ace, dst_ace, src_ace->se_size); - dest += dst_ace->se_size; - dst_acl->sl_acecnt++; - scan += src_ace->se_size; - count++; - } + isdir = ((flags & ACL_IS_DIR) == ACL_IS_DIR); - /*LINTED E_PTRDIFF_OVERFLOW*/ - return (dest - dest_beg); -} + zacl = smb_fsacl_alloc(acl->sl_acecnt, flags); -/* - * smb_ace_len - * - * Returns the length of an ACE with the given SID - * - * struct smb_ace { - * smb_ace_hdr_t se_header; - * uint32_t se_mask; - * nt_sid_t se_sid; - * }; - */ -uint16_t -smb_ace_len(nt_sid_t *sid) -{ - ASSERT(sid); + zace = zacl->acl_aclp; + ace = acl->sl_aces; + sim = sib.sib_maps; - return (sizeof (smb_ace_hdr_t) - + sizeof (uint32_t) + nt_sid_length(sid)); -} + for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { + zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES; + zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask); + zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags, + isdir); -/* - * smb_ace_mask_g2s - * - * Converts generic access bits in the given mask (if any) - * to file specific bits. Generic access masks shouldn't be - * stored in filesystem ACEs. - */ -uint32_t -smb_ace_mask_g2s(DWORD mask) -{ - if (mask & GENERIC_ALL) { - mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE - | GENERIC_EXECUTE); + if (nt_sid_is_equal(ace->se_sid, &everyone_sid)) + zace->a_flags |= ACE_EVERYONE; + else { + sim->sim_id = &zace->a_who; + idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, + ace->se_sid, -1); - mask |= FILE_ALL_ACCESS; - return (mask); + if (idm_stat != IDMAP_SUCCESS) { + smb_fsacl_free(zacl); + smb_idmap_batch_destroy(&sib); + return (NT_STATUS_INTERNAL_ERROR); + } + } } - if (mask & GENERIC_READ) { - mask &= ~GENERIC_READ; - mask |= FILE_GENERIC_READ; + idm_stat = smb_idmap_batch_getmappings(&sib); + if (idm_stat != IDMAP_SUCCESS) { + smb_fsacl_free(zacl); + smb_idmap_batch_destroy(&sib); + return (NT_STATUS_NONE_MAPPED); } - if (mask & GENERIC_WRITE) { - mask &= ~GENERIC_WRITE; - mask |= FILE_GENERIC_WRITE; - } + /* + * Set the ACEs group flag based on the type of ID returned. + */ + zace = zacl->acl_aclp; + ace = acl->sl_aces; + sim = sib.sib_maps; + for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { + if (zace->a_flags & ACE_EVERYONE) + continue; - if (mask & GENERIC_EXECUTE) { - mask &= ~GENERIC_EXECUTE; - mask |= FILE_GENERIC_EXECUTE; + if (sim->sim_idtype == SMB_IDMAP_GROUP) + zace->a_flags |= ACE_IDENTIFIER_GROUP; } - return (mask); + smb_idmap_batch_destroy(&sib); + + *fs_acl = zacl; + return (NT_STATUS_SUCCESS); } /* @@ -702,239 +507,488 @@ smb_acl_getsids(smb_idmap_batch_t *sib, acl_t *zacl, uid_t uid, gid_t gid) } /* - * smb_acl_grow + * smb_acl_null_empty + * + * NULL DACL means everyone full-access + * Empty DACL means everyone full-deny * - * Grow the acl size by given number of bytes in 'grow' - * Returns pointer to the newly allocated memory. + * ZFS ACL must have at least one entry so smb server has + * to simulate the aforementioned expected behavior by adding + * an entry in case the requested DACL is null or empty. Adding + * a everyone full-deny entry has proved to be problematic in + * tests since a deny entry takes precedence over allow entries. + * So, instead of adding a everyone full-deny, an owner ACE with + * owner implicit permissions will be set. */ -static smb_acl_t * -smb_acl_grow(smb_acl_t *acl, uint16_t grow) +static acl_t * +smb_acl_null_empty(boolean_t null) { - smb_acl_t *new_acl; - uint16_t smb_aclsz; + acl_t *zacl; + ace_t *zace; - ASSERT(acl); + zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT); + zace = zacl->acl_aclp; - smb_aclsz = acl->sl_size; - new_acl = kmem_alloc(smb_aclsz + grow, KM_SLEEP); - (void) memcpy(new_acl, acl, smb_aclsz); - kmem_free(acl, smb_aclsz); - new_acl->sl_size = smb_aclsz + grow; + zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + if (null) { + zace->a_access_mask = ACE_ALL_PERMS; + zace->a_flags = ACE_EVERYONE; + } else { + zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL | + ACE_READ_ATTRIBUTES; + zace->a_flags = ACE_OWNER; + } - return (new_acl); + return (zacl); } /* - * smb_acl_from_zfs + * FS ACL (acl_t) Functions + */ +acl_t * +smb_fsacl_alloc(int acenum, int flags) +{ + acl_t *acl; + + acl = acl_alloc(ACE_T); + acl->acl_cnt = acenum; + acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP); + acl->acl_flags = flags; + return (acl); +} + +void +smb_fsacl_free(acl_t *acl) +{ + if (acl) + acl_free(acl); +} + +/* + * smb_fsop_aclmerge * - * Converts given ZFS ACL to a Windows ACL. + * smb_fsop_aclread/write routines which interact with filesystem + * work with single ACL. This routine merges given DACL and SACL + * which might have been created during CIFS to FS conversion into + * one single ACL. + */ +acl_t * +smb_fsacl_merge(acl_t *dacl, acl_t *sacl) +{ + acl_t *acl; + int dacl_size; + + ASSERT(dacl); + ASSERT(sacl); + + acl = smb_fsacl_alloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags); + dacl_size = dacl->acl_cnt * dacl->acl_entry_size; + bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size); + bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size, + sacl->acl_cnt * sacl->acl_entry_size); + + return (acl); +} + +/* + * smb_fsacl_split * - * A pointer to allocated memory for the Win ACL will be - * returned upon successful conversion. + * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on + * the 'which_acl' parameter. Note that output dacl/sacl parameters could be + * NULL even if they're specified in 'which_acl', which means the target + * doesn't have any access and/or audit ACEs. */ -smb_acl_t * -smb_acl_from_zfs(acl_t *zacl, uid_t uid, gid_t gid) +void +smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl) { ace_t *zace; + ace_t *access_ace; + ace_t *audit_ace; + int naccess, naudit; + int get_dacl, get_sacl; + int i; + + *dacl = *sacl = NULL; + naccess = naudit = 0; + get_dacl = (which_acl & SMB_DACL_SECINFO); + get_sacl = (which_acl & SMB_SACL_SECINFO); + + for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { + if (get_dacl && smb_ace_is_access(zace->a_type)) + naccess++; + else if (get_sacl && smb_ace_is_audit(zace->a_type)) + naudit++; + } + + if (naccess) { + *dacl = smb_fsacl_alloc(naccess, zacl->acl_flags); + access_ace = (*dacl)->acl_aclp; + } + + if (naudit) { + *sacl = smb_fsacl_alloc(naudit, zacl->acl_flags); + audit_ace = (*sacl)->acl_aclp; + } + + for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { + if (get_dacl && smb_ace_is_access(zace->a_type)) { + *access_ace = *zace; + access_ace++; + } else if (get_sacl && smb_ace_is_audit(zace->a_type)) { + *audit_ace = *zace; + audit_ace++; + } + } +} + +/* + * ACE Inheritance Rules + * + * The system propagates inheritable ACEs to child objects according to a + * set of inheritance rules. The system places inherited ACEs in the child's + * DACL according to the preferred order of ACEs in a DACL. For Windows + * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs. + * + * The following table shows the ACEs inherited by container and noncontainer + * child objects for different combinations of inheritance flags. These + * inheritance rules work the same for both DACLs and SACLs. + * + * Parent ACE type Effect on Child ACL + * ----------------------- ------------------- + * OBJECT_INHERIT_ACE only Noncontainer child objects: + * Inherited as an effective ACE. + * Container child objects: + * Containers inherit an inherit-only ACE + * unless the NO_PROPAGATE_INHERIT_ACE bit + * flag is also set. + * + * CONTAINER_INHERIT_ACE only Noncontainer child objects: + * No effect on the child object. + * Container child objects: + * The child object inherits an effective ACE. + * The inherited ACE is inheritable unless the + * NO_PROPAGATE_INHERIT_ACE bit flag is also set. + * + * CONTAINER_INHERIT_ACE and + * OBJECT_INHERIT_ACE Noncontainer child objects: + * Inherited as an effective ACE. + * Container child objects: + * The child object inherits an effective ACE. + * The inherited ACE is inheritable unless the + * NO_PROPAGATE_INHERIT_ACE bit flag is also set + * + * No inheritance flags set No effect on child container or noncontainer + * objects. + * + * If an inherited ACE is an effective ACE for the child object, the system + * maps any generic rights to the specific rights for the child object. + * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the + * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic + * rights or generic SIDs are left unchanged so that they can be mapped + * appropriately when the ACE is inherited by the next generation of child + * objects. + * + * For a case in which a container object inherits an ACE that is both + * effective on the container and inheritable by its descendants, the + * container may inherit two ACEs. This occurs if the inheritable ACE + * contains generic information. The container inherits an inherit-only + * ACE containing the generic information and an effective-only ACE in + * which the generic information has been mapped. + */ + +/* + * smb_fsacl_inherit + * + * Manufacture the inherited ACL from the given ACL considering + * the new object type (file/dir) specified by 'is_dir'. The + * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions. + * This function implements Windows inheritance rules explained above. + * + * Note that the in/out ACLs are ZFS ACLs not Windows ACLs + */ +acl_t * +smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, uid_t owner_uid) +{ + boolean_t use_default = B_FALSE; + int num_inheritable = 0; int numaces; - smb_acl_t *acl; - uint16_t smb_aclsz; - smb_idmap_batch_t sib; - smb_idmap_t *sim; - idmap_stat idm_stat; - int status; + ace_t *dir_zace; + acl_t *new_zacl; + ace_t *new_zace; - idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt, - SMB_IDMAP_ID2SID); - if (idm_stat != IDMAP_SUCCESS) - return (NULL); + num_inheritable = smb_fsacl_inheritable(dir_zacl, is_dir); - if (smb_acl_getsids(&sib, zacl, uid, gid) != IDMAP_SUCCESS) { - smb_idmap_batch_destroy(&sib); - return (NULL); + if (num_inheritable == 0) { + if (which_acl == SMB_DACL_SECINFO) { + /* No inheritable access ACEs -> default DACL */ + num_inheritable = DEFAULT_DACL_ACENUM; + use_default = B_TRUE; + } else { + return (NULL); + } } - smb_aclsz = sizeof (smb_acl_t); + new_zacl = smb_fsacl_alloc(num_inheritable, ACL_AUTO_INHERIT); + new_zace = new_zacl->acl_aclp; - acl = kmem_alloc(smb_aclsz, KM_SLEEP); - smb_acl_init(acl, smb_aclsz, ACL_REVISION); + if (use_default) { + bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl)); + new_zace->a_who = owner_uid; + return (new_zacl); + } - sim = sib.sib_maps; - for (numaces = 0, zace = zacl->acl_aclp; - numaces < zacl->acl_cnt; - zace++, numaces++, sim++) { - ASSERT(sim->sim_sid); - if (sim->sim_sid == NULL) { - kmem_free(acl, acl->sl_size); - acl = NULL; + for (numaces = 0, dir_zace = dir_zacl->acl_aclp; + numaces < dir_zacl->acl_cnt; + dir_zace++, numaces++) { + switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) { + case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): + /* + * Files inherit an effective ACE. + * + * Dirs inherit an effective ACE. + * The inherited ACE is inheritable unless the + * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set + */ + smb_ace_inherit(dir_zace, new_zace, is_dir); + new_zace++; + + if (is_dir && ZACE_IS_CREATOR(dir_zace) && + (ZACE_IS_PROPAGATE(dir_zace))) { + *new_zace = *dir_zace; + new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | + ACE_INHERITED_ACE); + new_zace++; + } break; - } - /* Make room for this ACE */ - acl = smb_acl_grow(acl, smb_ace_len(sim->sim_sid)); + case ACE_FILE_INHERIT_ACE: + /* + * Files inherit as an effective ACE. + * + * Dirs inherit an inherit-only ACE + * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit + * flag is also set. + */ + if (is_dir == 0) { + smb_ace_inherit(dir_zace, new_zace, is_dir); + new_zace++; + } else if (ZACE_IS_PROPAGATE(dir_zace)) { + *new_zace = *dir_zace; + new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | + ACE_INHERITED_ACE); + new_zace++; + } + break; - status = smb_ace_common_add(acl, - zace->a_type, - smb_ace_flags_fromzfs(zace->a_flags), - zace->a_access_mask, - sim->sim_sid); + case ACE_DIRECTORY_INHERIT_ACE: + /* + * No effect on files + * + * Dirs inherit an effective ACE. + * The inherited ACE is inheritable unless the + * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. + */ + if (is_dir == 0) + break; - if (status == 0) { - kmem_free(acl, acl->sl_size); - acl = NULL; + smb_ace_inherit(dir_zace, new_zace, is_dir); + new_zace++; + + if (ZACE_IS_CREATOR(dir_zace) && + (ZACE_IS_PROPAGATE(dir_zace))) { + *new_zace = *dir_zace; + new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | + ACE_INHERITED_ACE); + new_zace++; + } + + break; + + default: break; } } - smb_idmap_batch_destroy(&sib); - return (acl); + return (new_zacl); } /* - * SID for Everyone group: S-1-1-0. - */ -nt_sid_t everyone_sid = { - NT_SID_REVISION, - 1, - NT_SECURITY_WORLD_AUTH, - { 0 } -}; - -/* - * smb_acl_null_empty + * smb_fsacl_from_vsa * - * NULL DACL means everyone full-access - * Empty DACL means everyone full-deny + * Converts given vsecattr_t structure to a acl_t structure. * - * ZFS ACL must have at least one entry so smb server has - * to simulate the aforementioned expected behavior by adding - * an entry in case the requested DACL is null or empty. Adding - * a everyone full-deny entry has proved to be problematic in - * tests since a deny entry takes precedence over allow entries. - * So, instead of adding a everyone full-deny, an owner ACE with - * owner implicit permissions will be set. + * The allocated memory for retuned acl_t should be freed by + * calling acl_free(). */ acl_t * -smb_acl_null_empty(int null) +smb_fsacl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type) { - acl_t *zacl; - ace_t *zace; + int aclbsize = 0; /* size of acl list in bytes */ + int dfaclbsize = 0; /* size of default acl list in bytes */ + int numacls; + acl_t *acl_info; - zacl = smb_fsop_aclalloc(1, ACL_AUTO_INHERIT); - zace = zacl->acl_aclp; + ASSERT(vsecattr); - zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - if (null) { - zace->a_access_mask = ACE_ALL_PERMS; - zace->a_flags = ACE_EVERYONE; - } else { - zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL | - ACE_READ_ATTRIBUTES; - zace->a_flags = ACE_OWNER; + acl_info = acl_alloc(acl_type); + if (acl_info == NULL) + return (NULL); + + acl_info->acl_flags = 0; + + switch (acl_type) { + + case ACLENT_T: + numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt; + aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t); + dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t); + + acl_info->acl_cnt = numacls; + acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize, + KM_SLEEP); + (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, + aclbsize); + (void) memcpy((char *)acl_info->acl_aclp + aclbsize, + vsecattr->vsa_dfaclentp, dfaclbsize); + + if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) + acl_info->acl_flags |= ACL_IS_TRIVIAL; + + break; + + case ACE_T: + aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); + acl_info->acl_cnt = vsecattr->vsa_aclcnt; + acl_info->acl_flags = vsecattr->vsa_aclflags; + acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP); + (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, + aclbsize); + if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) + acl_info->acl_flags |= ACL_IS_TRIVIAL; + + break; + + default: + acl_free(acl_info); + return (NULL); } - return (zacl); + if (aclbsize && vsecattr->vsa_aclentp) + kmem_free(vsecattr->vsa_aclentp, aclbsize); + if (dfaclbsize && vsecattr->vsa_dfaclentp) + kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize); + + return (acl_info); } /* - * smb_acl_to_zfs + * smb_fsacl_to_vsa * - * Converts given Windows ACL to a ZFS ACL. + * Converts given acl_t structure to a vsecattr_t structure. * - * fs_acl will contain a pointer to the created ZFS ACL. - * The allocated memory should be freed by calling - * smb_fsop_aclfree(). - * - * Since the output parameter, fs_acl, is allocated in this - * function, the caller has to make sure *fs_acl is NULL which - * means it's not pointing to any memory. + * IMPORTANT: + * Upon successful return the memory allocated for vsa_aclentp + * should be freed by calling kmem_free(). The size is returned + * in aclbsize. */ -uint32_t -smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) +int +smb_fsacl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize) { - smb_ace_t *ace; - acl_t *zacl; - ace_t *zace; - smb_idmap_batch_t sib; - smb_idmap_t *sim; - idmap_stat idm_stat; - int i, isdir; + int error = 0; + int numacls; + aclent_t *aclp; - ASSERT(fs_acl); - ASSERT(*fs_acl == NULL); + ASSERT(acl_info); + ASSERT(vsecattr); + ASSERT(aclbsize); - if (acl && !smb_acl_isvalid(acl, which_acl)) - return (NT_STATUS_INVALID_ACL); + bzero(vsecattr, sizeof (vsecattr_t)); + *aclbsize = 0; - if ((acl == NULL) || (acl->sl_acecnt == 0)) { - if (which_acl == SMB_DACL_SECINFO) { - *fs_acl = smb_acl_null_empty(acl == NULL); + switch (acl_info->acl_type) { + case ACLENT_T: + numacls = acl_info->acl_cnt; + /* + * Minimum ACL size is three entries so might as well + * bail out here. Also limit request size to prevent user + * from allocating too much kernel memory. Maximum size + * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES + * for the default ACL part. + */ + if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) { + error = EINVAL; + break; } - return (NT_STATUS_SUCCESS); - } + vsecattr->vsa_mask = VSA_ACL; - idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt, - SMB_IDMAP_SID2ID); - if (idm_stat != IDMAP_SUCCESS) - return (NT_STATUS_INTERNAL_ERROR); + vsecattr->vsa_aclcnt = numacls; + *aclbsize = numacls * sizeof (aclent_t); + vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); + (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, + *aclbsize); - isdir = ((flags & ACL_IS_DIR) == ACL_IS_DIR); + /* Sort the acl list */ + ksort((caddr_t)vsecattr->vsa_aclentp, + vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls); - zacl = smb_fsop_aclalloc(acl->sl_acecnt, flags); + /* Break into acl and default acl lists */ + for (numacls = 0, aclp = vsecattr->vsa_aclentp; + numacls < vsecattr->vsa_aclcnt; + aclp++, numacls++) { + if (aclp->a_type & ACL_DEFAULT) + break; + } - zace = zacl->acl_aclp; - sim = sib.sib_maps; + /* Find where defaults start (if any) */ + if (numacls < vsecattr->vsa_aclcnt) { + vsecattr->vsa_mask |= VSA_DFACL; + vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls; + vsecattr->vsa_dfaclentp = aclp; + vsecattr->vsa_aclcnt = numacls; + } - for (i = 0; ace = smb_ace_get(acl, i); i++, zace++, sim++) { - zace->a_type = ace->se_header.se_type & ACE_ALL_TYPES; - zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask); - zace->a_flags = smb_ace_flags_tozfs(ace->se_header.se_flags, - isdir); + /* Adjust if they're all defaults */ + if (vsecattr->vsa_aclcnt == 0) { + vsecattr->vsa_mask &= ~VSA_ACL; + vsecattr->vsa_aclentp = NULL; + } - if (nt_sid_is_equal(&ace->se_sid, &everyone_sid)) - zace->a_flags |= ACE_EVERYONE; - else { - sim->sim_id = &zace->a_who; - idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, - &ace->se_sid, -1); + /* Only directories can have defaults */ + if (vsecattr->vsa_dfaclcnt && + (acl_info->acl_flags & ACL_IS_DIR)) { + error = ENOTDIR; + } - if (idm_stat != IDMAP_SUCCESS) { - smb_fsop_aclfree(zacl); - smb_idmap_batch_destroy(&sib); - return (NT_STATUS_INTERNAL_ERROR); - } + break; + + case ACE_T: + if (acl_info->acl_cnt < 1 || + acl_info->acl_cnt > MAX_ACL_ENTRIES) { + error = EINVAL; + break; } - } - idm_stat = smb_idmap_batch_getmappings(&sib); - if (idm_stat != IDMAP_SUCCESS) { - smb_fsop_aclfree(zacl); - smb_idmap_batch_destroy(&sib); - return (NT_STATUS_NONE_MAPPED); - } + vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; + vsecattr->vsa_aclcnt = acl_info->acl_cnt; + vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL; + *aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); + vsecattr->vsa_aclentsz = *aclbsize; + vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); + (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, + *aclbsize); - /* - * Set the ACEs group flag based on the type of ID returned. - */ - zace = zacl->acl_aclp; - sim = sib.sib_maps; - for (i = 0; i < acl->sl_acecnt; i++, zace++, sim++) { - if (zace->a_flags & ACE_EVERYONE) - continue; + break; - if (sim->sim_idtype == SMB_IDMAP_GROUP) - zace->a_flags |= ACE_IDENTIFIER_GROUP; + default: + error = EINVAL; } - smb_idmap_batch_destroy(&sib); - - *fs_acl = zacl; - return (NT_STATUS_SUCCESS); + return (error); } /* - * smb_acl_inheritable + * smb_fsacl_inheritable * * Checks to see if there are any inheritable ACEs in the * given ZFS ACL. Returns the number of inheritable ACEs. @@ -984,7 +1038,7 @@ smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) * 1c: one creator owner/group ACE */ static int -smb_acl_inheritable(acl_t *zacl, int is_dir) +smb_fsacl_inheritable(acl_t *zacl, int is_dir) { int numaces; int num_inheritable = 0; @@ -1053,132 +1107,92 @@ smb_acl_inheritable(acl_t *zacl, int is_dir) return (num_inheritable); } -#define DEFAULT_DACL_ACENUM 2 + /* - * Default ACL: - * owner: full access - * SYSTEM: full access + * ACE Functions */ -static ace_t default_dacl[DEFAULT_DACL_ACENUM] = { - { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE }, - { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP, - ACE_ACCESS_ALLOWED_ACE_TYPE } -}; /* - * smb_acl_inherit - * - * Manufacture the inherited ACL from the given ACL considering - * the new object type (file/dir) specified by 'is_dir'. The - * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions. - * This function implements Windows inheritance rules. - * - * Note that the in/our ACLs are ZFS ACLs not Windows ACLs + * This is generic (ACL version 2) vs. object-specific + * (ACL version 4) ACE types. */ -acl_t * -smb_acl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, uid_t owner_uid) +boolean_t +smb_ace_is_generic(int type) { - boolean_t use_default = B_FALSE; - int num_inheritable = 0; - int numaces; - ace_t *dir_zace; - acl_t *new_zacl; - ace_t *new_zace; - - num_inheritable = smb_acl_inheritable(dir_zacl, is_dir); + switch (type) { + case ACE_ACCESS_ALLOWED_ACE_TYPE: + case ACE_ACCESS_DENIED_ACE_TYPE: + case ACE_SYSTEM_AUDIT_ACE_TYPE: + case ACE_SYSTEM_ALARM_ACE_TYPE: + case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: + case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: + case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: + case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE: + return (B_TRUE); - if (num_inheritable == 0) { - if (which_acl == SMB_DACL_SECINFO) { - /* No inheritable access ACEs -> default DACL */ - num_inheritable = DEFAULT_DACL_ACENUM; - use_default = B_TRUE; - } else { - return (NULL); - } + default: + break; } - new_zacl = smb_fsop_aclalloc(num_inheritable, ACL_AUTO_INHERIT); - new_zace = new_zacl->acl_aclp; - - if (use_default) { - bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl)); - new_zace->a_who = owner_uid; - return (new_zacl); - } + return (B_FALSE); +} - for (numaces = 0, dir_zace = dir_zacl->acl_aclp; - numaces < dir_zacl->acl_cnt; - dir_zace++, numaces++) { - switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) { - case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): - /* - * Files inherit an effective ACE. - * - * Dirs inherit an effective ACE. - * The inherited ACE is inheritable unless the - * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set - */ - smb_ace_inherit(dir_zace, new_zace, is_dir); - new_zace++; +boolean_t +smb_ace_is_access(int type) +{ + switch (type) { + case ACE_ACCESS_ALLOWED_ACE_TYPE: + case ACE_ACCESS_DENIED_ACE_TYPE: + case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE: + case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: + case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: + case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: + case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: + case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: + case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: + return (B_TRUE); - if (is_dir && ZACE_IS_CREATOR(dir_zace) && - (ZACE_IS_PROPAGATE(dir_zace))) { - *new_zace = *dir_zace; - new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | - ACE_INHERITED_ACE); - new_zace++; - } - break; + default: + break; + } - case ACE_FILE_INHERIT_ACE: - /* - * Files inherit as an effective ACE. - * - * Dirs inherit an inherit-only ACE - * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit - * flag is also set. - */ - if (is_dir == 0) { - smb_ace_inherit(dir_zace, new_zace, is_dir); - new_zace++; - } else if (ZACE_IS_PROPAGATE(dir_zace)) { - *new_zace = *dir_zace; - new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | - ACE_INHERITED_ACE); - new_zace++; - } - break; + return (B_FALSE); +} - case ACE_DIRECTORY_INHERIT_ACE: - /* - * No effect on files - * - * Dirs inherit an effective ACE. - * The inherited ACE is inheritable unless the - * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. - */ - if (is_dir == 0) - break; +boolean_t +smb_ace_is_audit(int type) +{ + switch (type) { + case ACE_SYSTEM_AUDIT_ACE_TYPE: + case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: + case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: + case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: + return (B_TRUE); - smb_ace_inherit(dir_zace, new_zace, is_dir); - new_zace++; + default: + break; + } - if (ZACE_IS_CREATOR(dir_zace) && - (ZACE_IS_PROPAGATE(dir_zace))) { - *new_zace = *dir_zace; - new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | - ACE_INHERITED_ACE); - new_zace++; - } + return (B_FALSE); +} - break; +/* + * smb_ace_len + * + * Returns the length of the given ACE as it appears in an + * ACL on the wire (i.e. a flat buffer which contains the SID) + */ +static uint16_t +smb_ace_len(smb_ace_t *ace) +{ + ASSERT(ace); + ASSERT(ace->se_sid); - default: - break; - } - } + if (ace == NULL) + return (0); - return (new_zacl); + return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) + + nt_sid_length(ace->se_sid)); } static void @@ -1202,6 +1216,42 @@ smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir) } } +/* + * smb_ace_mask_g2s + * + * Converts generic access bits in the given mask (if any) + * to file specific bits. Generic access masks shouldn't be + * stored in filesystem ACEs. + */ +static uint32_t +smb_ace_mask_g2s(uint32_t mask) +{ + if (mask & GENERIC_ALL) { + mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE + | GENERIC_EXECUTE); + + mask |= FILE_ALL_ACCESS; + return (mask); + } + + if (mask & GENERIC_READ) { + mask &= ~GENERIC_READ; + mask |= FILE_GENERIC_READ; + } + + if (mask & GENERIC_WRITE) { + mask &= ~GENERIC_WRITE; + mask |= FILE_GENERIC_WRITE; + } + + if (mask & GENERIC_EXECUTE) { + mask &= ~GENERIC_EXECUTE; + mask |= FILE_GENERIC_EXECUTE; + } + + return (mask); +} + static uint16_t smb_ace_flags_tozfs(uint8_t c_flags, int isdir) { @@ -1245,66 +1295,37 @@ smb_ace_flags_fromzfs(uint16_t z_flags) return (c_flags); } -/* - * This is generic (ACL version 2) vs. object-specific - * (ACL version 4) ACE types. - */ -int -smb_ace_is_generic(int type) +static boolean_t +smb_ace_isvalid(smb_ace_t *ace, int which_acl) { - switch (type) { - case ACE_ACCESS_ALLOWED_ACE_TYPE: - case ACE_ACCESS_DENIED_ACE_TYPE: - case ACE_SYSTEM_AUDIT_ACE_TYPE: - case ACE_SYSTEM_ALARM_ACE_TYPE: - case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: - case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: - case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: - case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE: - return (1); + uint16_t min_len; - default: - break; - } + min_len = sizeof (smb_acehdr_t); - return (0); -} + if (ace->se_hdr.se_bsize < min_len) + return (B_FALSE); -int -smb_ace_is_access(int type) -{ - switch (type) { - case ACE_ACCESS_ALLOWED_ACE_TYPE: - case ACE_ACCESS_DENIED_ACE_TYPE: - case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE: - case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: - case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: - case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: - case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: - case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: - case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: - return (1); + if (smb_ace_is_access(ace->se_hdr.se_type) && + (which_acl != SMB_DACL_SECINFO)) + return (B_FALSE); - default: - break; - } + if (smb_ace_is_audit(ace->se_hdr.se_type) && + (which_acl != SMB_SACL_SECINFO)) + return (B_FALSE); - return (0); -} + if (smb_ace_is_generic(ace->se_hdr.se_type)) { + if (nt_sid_is_valid(ace->se_sid) == 0) + return (B_FALSE); -int -smb_ace_is_audit(int type) -{ - switch (type) { - case ACE_SYSTEM_AUDIT_ACE_TYPE: - case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: - case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: - case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: - return (1); + min_len += sizeof (ace->se_mask); + min_len += nt_sid_length(ace->se_sid); - default: - break; + if (ace->se_hdr.se_bsize < min_len) + return (B_FALSE); } - return (0); + /* + * object-specific ACE validation will be added later. + */ + return (B_TRUE); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c index 30058e8f82..d3a462fbc5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c @@ -879,7 +879,7 @@ smb_open_subr(struct smb_request *sr) op->dattr &= ~SMB_FA_READONLY; } smb_node_set_dosattr(node, op->dattr | SMB_FA_ARCHIVE); - if (op->utime.tv_sec == 0 || op->utime.tv_sec == 0xffffffff) + if (op->utime.tv_sec == 0 || op->utime.tv_sec == UINT_MAX) (void) microtime(&op->utime); smb_node_set_time(node, NULL, &op->utime, 0, 0, SMB_AT_MTIME); (void) smb_sync_fsattr(sr, sr->user_cr, node); diff --git a/usr/src/uts/common/fs/smbsrv/smb_create.c b/usr/src/uts/common/fs/smbsrv/smb_create.c index fccdf5ba9e..8fd289bb75 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_create.c +++ b/usr/src/uts/common/fs/smbsrv/smb_create.c @@ -176,7 +176,7 @@ smb_com_create_temporary(struct smb_request *sr) break; } - smbsr_encode_result(sr, 1, 0, "bwwwbs", 1, sr->smb_fid, bcc, 4, name); + smbsr_encode_result(sr, 1, 0, "bwwbs", 1, sr->smb_fid, bcc, 4, name); return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c index 655e5ad3ff..3d7292961e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c @@ -26,29 +26,19 @@ #pragma ident "%Z%%M% %I% %E% SMI" #include <sys/sid.h> -#include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> +#include <smbsrv/smb_kproto.h> +#include <smbsrv/smbvar.h> +#include <smbsrv/ntstatus.h> +#include <smbsrv/ntaccess.h> #include <acl/acl_common.h> u_longlong_t smb_caller_id; static int smb_fsop_amask_to_omode(uint32_t granted_access); - -extern uint32_t smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd); - -extern uint32_t smb_sd_write(smb_request_t *sr, smb_sdbuf_t *sr_sd, - uint32_t secinfo); - -extern int smb_vop_acl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, - int *aclbsize); - static int smb_fsop_sdinherit(smb_request_t *sr, smb_node_t *dnode, smb_fssd_t *fs_sd); -static void smb_fsop_aclsplit(acl_t *zacl, acl_t **dacl, acl_t **sacl, - int which_acl); -static acl_t *smb_fsop_aclmerge(acl_t *dacl, acl_t *sacl); - /* * The smb_fsop_* functions have knowledge of CIFS semantics. * @@ -161,6 +151,7 @@ smb_fsop_create_with_sd( int flags = 0; int is_dir; int rc; + boolean_t no_xvattr = B_FALSE; ASSERT(fs_sd); @@ -178,14 +169,14 @@ smb_fsop_create_with_sd( sacl = fs_sd->sd_zsacl; ASSERT(dacl || sacl); if (dacl && sacl) { - acl = smb_fsop_aclmerge(dacl, sacl); + acl = smb_fsacl_merge(dacl, sacl); } else if (dacl) { acl = dacl; } else { acl = sacl; } - rc = smb_vop_acl_to_vsa(acl, &vsecattr, &aclbsize); + rc = smb_fsacl_to_vsa(acl, &vsecattr, &aclbsize); if (dacl && sacl) acl_free(acl); @@ -231,8 +222,11 @@ smb_fsop_create_with_sd( } if (set_attr.sa_mask) { + if (sr && sr->tid_tree) + if (sr->tid_tree->t_flags & SMB_TREE_FLAG_UFS) + no_xvattr = B_TRUE; rc = smb_vop_setattr(snode->vp, NULL, &set_attr, - 0, kcred, &ct); + 0, kcred, no_xvattr, &ct); } } else { @@ -253,7 +247,10 @@ smb_fsop_create_with_sd( cr, &ct, NULL); } - if (rc == 0) + if (rc != 0) + return (rc); + + if ((sr->tid_tree->t_flags & SMB_TREE_FLAG_NFS_MOUNTED) == 0) rc = smb_fsop_sdwrite(sr, kcred, snode, fs_sd, 1); } @@ -267,6 +264,14 @@ smb_fsop_create_with_sd( } } + if (rc != 0) { + if (is_dir) { + (void) smb_vop_rmdir(snode->vp, name, flags, cr, &ct); + } else { + (void) smb_vop_remove(snode->vp, name, flags, cr, &ct); + } + } + return (rc); } @@ -417,36 +422,36 @@ smb_fsop_create( return (ENOMEM); } } else { - if (op->sd_buf) { + if (op->sd) { /* * SD sent by client in Windows format. Needs to be * converted to FS format. No inheritance. */ - secinfo = smb_sd_get_secinfo((smb_sdbuf_t *)op->sd_buf); - smb_fsop_sdinit(&fs_sd, secinfo, 0); + secinfo = smb_sd_get_secinfo(op->sd); + smb_fssd_init(&fs_sd, secinfo, 0); - status = smb_sd_tofs(op->sd_buf, &fs_sd); + status = smb_sd_tofs(op->sd, &fs_sd); if (status == NT_STATUS_SUCCESS) { rc = smb_fsop_create_with_sd(sr, cr, dir_snode, name, attr, ret_snode, ret_attr, &fs_sd); } else rc = EINVAL; - smb_fsop_sdterm(&fs_sd); + smb_fssd_term(&fs_sd); } else if (sr->tid_tree->t_acltype == ACE_T) { /* * No incoming SD and filesystem is ZFS * Server applies Windows inheritance rules, * see smb_fsop_sdinherit() comments as to why. */ - smb_fsop_sdinit(&fs_sd, SMB_ACL_SECINFO, 0); + smb_fssd_init(&fs_sd, SMB_ACL_SECINFO, 0); rc = smb_fsop_sdinherit(sr, dir_snode, &fs_sd); if (rc == 0) { rc = smb_fsop_create_with_sd(sr, cr, dir_snode, name, attr, ret_snode, ret_attr, &fs_sd); } - smb_fsop_sdterm(&fs_sd); + smb_fssd_term(&fs_sd); } else { /* * No incoming SD and filesystem is not ZFS @@ -554,36 +559,36 @@ smb_fsop_mkdir( smb_get_caller_context(sr, &ct); - if (op->sd_buf) { + if (op->sd) { /* * SD sent by client in Windows format. Needs to be * converted to FS format. No inheritance. */ - secinfo = smb_sd_get_secinfo((smb_sdbuf_t *)op->sd_buf); - smb_fsop_sdinit(&fs_sd, secinfo, SMB_FSSD_FLAGS_DIR); + secinfo = smb_sd_get_secinfo(op->sd); + smb_fssd_init(&fs_sd, secinfo, SMB_FSSD_FLAGS_DIR); - status = smb_sd_tofs(op->sd_buf, &fs_sd); + status = smb_sd_tofs(op->sd, &fs_sd); if (status == NT_STATUS_SUCCESS) { rc = smb_fsop_create_with_sd(sr, cr, dir_snode, name, attr, ret_snode, ret_attr, &fs_sd); } else rc = EINVAL; - smb_fsop_sdterm(&fs_sd); + smb_fssd_term(&fs_sd); } else if (sr->tid_tree->t_acltype == ACE_T) { /* * No incoming SD and filesystem is ZFS * Server applies Windows inheritance rules, * see smb_fsop_sdinherit() comments as to why. */ - smb_fsop_sdinit(&fs_sd, SMB_ACL_SECINFO, SMB_FSSD_FLAGS_DIR); + smb_fssd_init(&fs_sd, SMB_ACL_SECINFO, SMB_FSSD_FLAGS_DIR); rc = smb_fsop_sdinherit(sr, dir_snode, &fs_sd); if (rc == 0) { rc = smb_fsop_create_with_sd(sr, cr, dir_snode, name, attr, ret_snode, ret_attr, &fs_sd); } - smb_fsop_sdterm(&fs_sd); + smb_fssd_term(&fs_sd); } else { rc = smb_vop_mkdir(dir_snode->vp, name, attr, &vp, flags, cr, @@ -1242,6 +1247,7 @@ smb_fsop_setattr( uint32_t access = 0; int rc = 0; int flags = 0; + boolean_t no_xvattr = B_FALSE; ASSERT(cr); ASSERT(snode); @@ -1281,8 +1287,12 @@ smb_fsop_setattr( ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING); unnamed_vp = unnamed_node->vp; } + if (sr && sr->tid_tree) + if (sr->tid_tree->t_flags & SMB_TREE_FLAG_UFS) + no_xvattr = B_TRUE; - rc = smb_vop_setattr(snode->vp, unnamed_vp, set_attr, flags, cr, &ct); + rc = smb_vop_setattr(snode->vp, unnamed_vp, + set_attr, flags, cr, no_xvattr, &ct); if ((rc == 0) && ret_attr) { /* @@ -1930,34 +1940,6 @@ smb_fsop_commit(smb_request_t *sr, cred_t *cr, smb_node_t *snode) } /* - * smb_fsop_sdinit - * - * Initializes the given FS SD structure. - */ -void -smb_fsop_sdinit(smb_fssd_t *fs_sd, uint32_t secinfo, uint32_t flags) -{ - bzero(fs_sd, sizeof (smb_fssd_t)); - fs_sd->sd_secinfo = secinfo; - fs_sd->sd_flags = flags; -} - -/* - * smb_fsop_sdterm - * - * Frees allocated memory for acl fields. - */ -void -smb_fsop_sdterm(smb_fssd_t *fs_sd) -{ - ASSERT(fs_sd); - - smb_fsop_aclfree(fs_sd->sd_zdacl); - smb_fsop_aclfree(fs_sd->sd_zsacl); - bzero(fs_sd, sizeof (smb_fssd_t)); -} - -/* * smb_fsop_aclread * * Retrieve filesystem ACL. Depends on requested ACLs in @@ -1969,7 +1951,7 @@ smb_fsop_sdterm(smb_fssd_t *fs_sd) * * Returned ACL is always in ACE_T (aka ZFS) format. * If successful the allocated memory for the ACL should be freed - * using smb_fsop_aclfree() or smb_fsop_sdterm() + * using smb_fsacl_free() or smb_fssd_term() */ int smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode, @@ -2022,7 +2004,7 @@ smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode, (snode->vp->v_type == VDIR), fs_sd->sd_uid, fs_sd->sd_gid); if (error == 0) { - smb_fsop_aclsplit(acl, &fs_sd->sd_zdacl, &fs_sd->sd_zsacl, + smb_fsacl_split(acl, &fs_sd->sd_zdacl, &fs_sd->sd_zsacl, fs_sd->sd_secinfo); } @@ -2097,7 +2079,7 @@ smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode, return (EINVAL); if (dacl && sacl) - acl = smb_fsop_aclmerge(dacl, sacl); + acl = smb_fsacl_merge(dacl, sacl); else if (dacl) acl = dacl; else @@ -2119,102 +2101,6 @@ smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode, return (error); } -acl_t * -smb_fsop_aclalloc(int acenum, int flags) -{ - acl_t *acl; - - acl = acl_alloc(ACE_T); - acl->acl_cnt = acenum; - acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP); - acl->acl_flags = flags; - return (acl); -} - -void -smb_fsop_aclfree(acl_t *acl) -{ - if (acl) - acl_free(acl); -} - -/* - * smb_fsop_aclmerge - * - * smb_fsop_aclread/write routines which interact with filesystem - * work with single ACL. This routine merges given DACL and SACL - * which might have been created during CIFS to FS conversion into - * one single ACL. - */ -static acl_t * -smb_fsop_aclmerge(acl_t *dacl, acl_t *sacl) -{ - acl_t *acl; - int dacl_size; - - ASSERT(dacl); - ASSERT(sacl); - - acl = smb_fsop_aclalloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags); - dacl_size = dacl->acl_cnt * dacl->acl_entry_size; - bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size); - bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size, - sacl->acl_cnt * sacl->acl_entry_size); - - return (acl); -} - -/* - * smb_fsop_aclsplit - * - * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on - * the 'which_acl' parameter. Note that output dacl/sacl parameters could be - * NULL even if they're specified in 'which_acl', which means the target - * doesn't have any access and/or audit ACEs. - */ -static void -smb_fsop_aclsplit(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl) -{ - ace_t *zace; - ace_t *access_ace; - ace_t *audit_ace; - int naccess, naudit; - int get_dacl, get_sacl; - int i; - - *dacl = *sacl = NULL; - naccess = naudit = 0; - get_dacl = (which_acl & SMB_DACL_SECINFO); - get_sacl = (which_acl & SMB_SACL_SECINFO); - - for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { - if (get_dacl && smb_ace_is_access(zace->a_type)) - naccess++; - else if (get_sacl && smb_ace_is_audit(zace->a_type)) - naudit++; - } - - if (naccess) { - *dacl = smb_fsop_aclalloc(naccess, zacl->acl_flags); - access_ace = (*dacl)->acl_aclp; - } - - if (naudit) { - *sacl = smb_fsop_aclalloc(naudit, zacl->acl_flags); - audit_ace = (*sacl)->acl_aclp; - } - - for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { - if (get_dacl && smb_ace_is_access(zace->a_type)) { - *access_ace = *zace; - access_ace++; - } else if (get_sacl && smb_ace_is_audit(zace->a_type)) { - *audit_ace = *zace; - audit_ace++; - } - } -} - acl_type_t smb_fsop_acltype(smb_node_t *snode) { @@ -2328,7 +2214,7 @@ smb_fsop_sdmerge(smb_request_t *sr, smb_node_t *snode, smb_fssd_t *fs_sd) /* * Don't overwrite existing audit entries */ - smb_fsop_sdinit(&cur_sd, SMB_SACL_SECINFO, + smb_fssd_init(&cur_sd, SMB_SACL_SECINFO, fs_sd->sd_flags); error = smb_fsop_sdread(sr, kcred, snode, &cur_sd); @@ -2343,7 +2229,7 @@ smb_fsop_sdmerge(smb_request_t *sr, smb_node_t *snode, smb_fssd_t *fs_sd) /* * Don't overwrite existing access entries */ - smb_fsop_sdinit(&cur_sd, SMB_DACL_SECINFO, + smb_fssd_init(&cur_sd, SMB_DACL_SECINFO, fs_sd->sd_flags); error = smb_fsop_sdread(sr, kcred, snode, &cur_sd); @@ -2357,7 +2243,7 @@ smb_fsop_sdmerge(smb_request_t *sr, smb_node_t *snode, smb_fssd_t *fs_sd) } if (error) - smb_fsop_sdterm(&cur_sd); + smb_fssd_term(&cur_sd); } return (error); @@ -2460,15 +2346,6 @@ smb_fsop_sdwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode, return (error); } -/*ARGSUSED*/ -void -smb_get_caller_context(smb_request_t *sr, caller_context_t *ct) -{ - ct->cc_caller_id = smb_caller_id; - ct->cc_pid = 0; /* TBD */ - ct->cc_sysid = 0; /* TBD */ -} - /* * smb_fsop_sdinherit * @@ -2498,8 +2375,8 @@ static int smb_fsop_sdinherit(smb_request_t *sr, smb_node_t *dnode, smb_fssd_t *fs_sd) { int is_dir; - acl_t *dacl; - acl_t *sacl; + acl_t *dacl = NULL; + acl_t *sacl = NULL; ksid_t *owner_sid; int error; @@ -2523,13 +2400,16 @@ smb_fsop_sdinherit(smb_request_t *sr, smb_node_t *dnode, smb_fssd_t *fs_sd) is_dir = (fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR); owner_sid = crgetsid(sr->user_cr, KSID_OWNER); ASSERT(owner_sid); - dacl = smb_acl_inherit(fs_sd->sd_zdacl, is_dir, SMB_DACL_SECINFO, + dacl = smb_fsacl_inherit(fs_sd->sd_zdacl, is_dir, SMB_DACL_SECINFO, owner_sid->ks_id); - sacl = smb_acl_inherit(fs_sd->sd_zsacl, is_dir, SMB_SACL_SECINFO, + sacl = smb_fsacl_inherit(fs_sd->sd_zsacl, is_dir, SMB_SACL_SECINFO, (uid_t)-1); - smb_fsop_aclfree(fs_sd->sd_zdacl); - smb_fsop_aclfree(fs_sd->sd_zsacl); + if (sacl == NULL) + fs_sd->sd_secinfo &= ~SMB_SACL_SECINFO; + + smb_fsacl_free(fs_sd->sd_zdacl); + smb_fsacl_free(fs_sd->sd_zsacl); fs_sd->sd_zdacl = dacl; fs_sd->sd_zsacl = sacl; @@ -2593,3 +2473,12 @@ smb_fsop_eaccess(smb_request_t *sr, cred_t *cr, smb_node_t *snode, *eaccess |= FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | FILE_DELETE_CHILD; } + +/*ARGSUSED*/ +void +smb_get_caller_context(smb_request_t *sr, caller_context_t *ct) +{ + ct->cc_caller_id = smb_caller_id; + ct->cc_pid = 0; /* TBD */ + ct->cc_sysid = 0; /* TBD */ +} diff --git a/usr/src/uts/common/fs/smbsrv/smb_init.c b/usr/src/uts/common/fs/smbsrv/smb_init.c index 1d3d8f39cb..897f09bded 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_init.c +++ b/usr/src/uts/common/fs/smbsrv/smb_init.c @@ -292,21 +292,29 @@ smb_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred, int *retval) { int gmtoff; + int door_id; switch (cmd) { - case SMB_IOC_GMTOFF: if (ddi_copyin((int *)argp, &gmtoff, sizeof (int), flag)) return (EFAULT); (void) smb_set_gmtoff((uint32_t)gmtoff); break; - case SMB_IOC_CONFIG_REFRESH: + case SMB_IOC_CONFIG: #if 0 smb_svcstate_event(SMB_SVCEVT_CONFIG, NULL); #endif break; + case SMB_IOC_WINPIPE: + if (ddi_copyin((int *)argp, &door_id, sizeof (int), flag)) + return (EFAULT); + + if (smb_winpipe_open(door_id) != 0) + return (EPIPE); + break; + default: break; } diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c index 53e8d0326e..cb5aa042ee 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c +++ b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c @@ -88,7 +88,7 @@ smb_com_lock_byte_range(struct smb_request *sr) * normal lock (write lock). */ result = smb_lock_range(sr, sr->fid_ofile, - (off_t)off, (uint64_t)count, 0, SMB_LOCK_TYPE_READWRITE); + (u_offset_t)off, (uint64_t)count, 0, SMB_LOCK_TYPE_READWRITE); if (result != NT_STATUS_SUCCESS) { smb_lock_range_raise_error(sr, result); /* NOT REACHED */ diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c index e043472af5..7326d5a12c 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c +++ b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c @@ -571,7 +571,7 @@ smb_lock_create( * in cv_timedwait. */ lock->l_end_time = lbolt + MSEC_TO_TICK(timeout); - if (timeout == 0xffffffff) { + if (timeout == UINT_MAX) { lock->l_flags |= SMB_LOCK_FLAG_INDEFINITE; } mutex_init(&lock->l_mutex, NULL, MUTEX_DEFAULT, NULL); diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c index 63f1f81440..00d648cc32 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c @@ -35,9 +35,15 @@ * support them at this time. */ -#include <smbsrv/smb_incl.h> +#include <smbsrv/smbvar.h> +#include <smbsrv/smb_kproto.h> #include <smbsrv/smb_fsops.h> -#include <smbsrv/smb_vops.h> +#include <smbsrv/ntstatus.h> +#include <smbsrv/ntaccess.h> +#include <smbsrv/nterror.h> +#include <smbsrv/ntifs.h> +#include <smbsrv/cifs.h> +#include <smbsrv/doserror.h> /* * smb_nt_transact_create @@ -68,6 +74,7 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) uint32_t NameLength; smb_attr_t new_attr; smb_node_t *node; + smb_sd_t sd; DWORD status; int rc; @@ -112,18 +119,15 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) /* NOTREACHED */ } - if (sd_len >= sizeof (smb_sdbuf_t)) { - /* ignore security setting for files on Unix volumes */ - op->sd_buf = kmem_alloc(sd_len, KM_SLEEP); - - if ((smb_decode_mbc(&xa->req_data_mb, "#c", sd_len, - (char *)op->sd_buf)) != 0) { - kmem_free(op->sd_buf, sd_len); - smbsr_raise_nt_error(sr, NT_STATUS_BUFFER_TOO_SMALL); + if (sd_len) { + status = smb_decode_sd(xa, &sd); + if (status != NT_STATUS_SUCCESS) { + smbsr_raise_nt_error(sr, status); /* NOTREACHED */ } + op->sd = &sd; } else { - op->sd_buf = 0; + op->sd = NULL; } op->fqi.srch_attr = 0; @@ -168,8 +172,8 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) } status = smb_open_subr(sr); - if (op->sd_buf) - kmem_free(op->sd_buf, sd_len); + if (op->sd) + smb_sd_term(op->sd); if (status != NT_STATUS_SUCCESS) { if (status == NT_STATUS_SHARING_VIOLATION) diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c index 70d8437cdf..fec95a2835 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c @@ -25,14 +25,21 @@ #pragma ident "%Z%%M% %I% %E% SMI" -#include <smbsrv/smb_secdesc.h> -#include <smbsrv/smb_incl.h> -#include <smbsrv/smb_fsops.h> +#include <smbsrv/smbvar.h> +#include <smbsrv/smb_kproto.h> +#include <smbsrv/ntstatus.h> +#include <smbsrv/nterror.h> +#include <smbsrv/doserror.h> +#include <smbsrv/cifs.h> -extern uint32_t smb_sd_read(smb_request_t *sr, smb_sdbuf_t **sr_sd, - uint32_t secinfo, uint32_t *buflen); -extern uint32_t smb_sd_write(smb_request_t *sr, smb_sdbuf_t *sr_sd, - uint32_t secinfo); +static void smb_encode_sd(struct smb_xa *, smb_sd_t *, uint32_t); +static void smb_encode_sid(struct smb_xa *, nt_sid_t *); +static void smb_encode_sacl(struct smb_xa *, smb_acl_t *); +static void smb_encode_dacl(struct smb_xa *, smb_acl_t *); + +uint32_t smb_decode_sd(struct smb_xa *, smb_sd_t *); +static nt_sid_t *smb_decode_sid(struct smb_xa *, uint32_t); +static smb_acl_t *smb_decode_acl(struct smb_xa *, uint32_t); /* * smb_nt_transact_query_security_info @@ -63,20 +70,15 @@ extern uint32_t smb_sd_write(smb_request_t *sr, smb_sdbuf_t *sr_sd, int smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) { - smb_sdbuf_t *sr_sd; - uint32_t secinfo; - uint32_t sr_sdlen; - uint32_t status; + smb_sd_t sd; + uint32_t secinfo; + uint32_t sdlen; + uint32_t status; + if (smb_decode_mbc(&xa->req_param_mb, "w2.l", &sr->smb_fid, &secinfo) != 0) { - /* - * It's not clear why ERRnomem is returned here. - * This should rarely happen and we're not sure if - * it's going to break something if we change this - * error code, so we're going to keep it for now. - */ - smbsr_raise_error(sr, ERRSRV, ERRnomem); + smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); /* NOTREACHED */ } @@ -90,7 +92,8 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) if ((sr->fid_ofile->f_node == NULL) || (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { - smbsr_raise_nt_error(sr, NT_STATUS_ACCESS_DENIED); + smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -102,31 +105,36 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) secinfo &= ~SMB_SACL_SECINFO; } - sr_sdlen = xa->smb_mdrcnt; - status = smb_sd_read(sr, &sr_sd, secinfo, &sr_sdlen); - + status = smb_sd_read(sr, &sd, secinfo); if (status != NT_STATUS_SUCCESS) { - if (status == NT_STATUS_BUFFER_TOO_SMALL) { - /* - * The maximum data return count specified by the - * client is not big enough to hold the security - * descriptor. We have to return an error but we - * can provide a buffer size hint for the client. - */ - (void) smb_encode_mbc(&xa->rep_param_mb, "l", sr_sdlen); - smbsr_setup_nt_status(sr, ERROR_SEVERITY_ERROR, - NT_STATUS_BUFFER_TOO_SMALL); - return (SDRC_NORMAL_REPLY); - } - smbsr_raise_nt_error(sr, status); /* NOTREACHED */ } - (void) smb_encode_mbc(&xa->rep_data_mb, "#c", (int)sr_sdlen, sr_sd); - (void) smb_encode_mbc(&xa->rep_param_mb, "l", sr_sdlen); + sdlen = smb_sd_len(&sd, secinfo); + if (sdlen == 0) { + smb_sd_term(&sd); + smbsr_raise_nt_error(sr, NT_STATUS_INVALID_SECURITY_DESCR); + /* NOTREACHED */ + } + + if (sdlen > xa->smb_mdrcnt) { + /* + * The maximum data return count specified by the + * client is not big enough to hold the security + * descriptor. We have to return an error but we + * should provide a buffer size hint for the client. + */ + (void) smb_encode_mbc(&xa->rep_param_mb, "l", sdlen); + smbsr_setup_nt_status(sr, ERROR_SEVERITY_ERROR, + NT_STATUS_BUFFER_TOO_SMALL); + smb_sd_term(&sd); + return (SDRC_NORMAL_REPLY); + } - kmem_free(sr_sd, sr_sdlen); + smb_encode_sd(xa, &sd, secinfo); + (void) smb_encode_mbc(&xa->rep_param_mb, "l", sdlen); + smb_sd_term(&sd); return (SDRC_NORMAL_REPLY); } @@ -152,12 +160,12 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) int smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) { - smb_sdbuf_t *sd_buf; - uint32_t sec_info; + smb_sd_t sd; + uint32_t secinfo; uint32_t status; if (smb_decode_mbc(&xa->req_param_mb, "w2.l", - &sr->smb_fid, &sec_info) != 0) { + &sr->smb_fid, &secinfo) != 0) { smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); /* NOTREACHED */ } @@ -185,25 +193,27 @@ smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) * If target filesystem doesn't support ACE_T acls then * don't process SACL */ - sec_info &= ~SMB_SACL_SECINFO; + secinfo &= ~SMB_SACL_SECINFO; } - if ((sec_info & SMB_ALL_SECINFO) == 0) { + if ((secinfo & SMB_ALL_SECINFO) == 0) { return (NT_STATUS_SUCCESS); } - sd_buf = kmem_alloc(xa->smb_tdscnt, KM_SLEEP); - - if ((smb_decode_mbc(&xa->req_data_mb, "#c", - xa->smb_tdscnt, (char *)sd_buf)) != 0) { - kmem_free(sd_buf, xa->smb_tdscnt); - smbsr_raise_nt_error(sr, NT_STATUS_BUFFER_TOO_SMALL); + status = smb_decode_sd(xa, &sd); + if (status != NT_STATUS_SUCCESS) { + smbsr_raise_nt_error(sr, status); /* NOTREACHED */ } - status = smb_sd_write(sr, sd_buf, sec_info); - kmem_free(sd_buf, xa->smb_tdscnt); + if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) || + ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) { + smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + /* NOTREACHED */ + } + status = smb_sd_write(sr, &sd, secinfo); + smb_sd_term(&sd); if (status != NT_STATUS_SUCCESS) { smbsr_raise_nt_error(sr, status); /* NOTREACHED */ @@ -211,3 +221,331 @@ smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) return (SDRC_NORMAL_REPLY); } + +/* + * smb_encode_sd + * + * Encodes given security descriptor in the reply buffer. + */ +static void +smb_encode_sd(struct smb_xa *xa, smb_sd_t *sd, uint32_t secinfo) +{ + uint32_t offset = SMB_SD_HDRSIZE; + + /* encode header */ + (void) smb_encode_mbc(&xa->rep_data_mb, "b.w", + sd->sd_revision, sd->sd_control | SE_SELF_RELATIVE); + + /* owner offset */ + if (secinfo & SMB_OWNER_SECINFO) { + ASSERT(sd->sd_owner); + (void) smb_encode_mbc(&xa->rep_data_mb, "l", offset); + offset += nt_sid_length(sd->sd_owner); + } else { + (void) smb_encode_mbc(&xa->rep_data_mb, "l", 0); + } + + /* group offset */ + if (secinfo & SMB_GROUP_SECINFO) { + ASSERT(sd->sd_group); + (void) smb_encode_mbc(&xa->rep_data_mb, "l", offset); + offset += nt_sid_length(sd->sd_group); + } else { + (void) smb_encode_mbc(&xa->rep_data_mb, "l", 0); + } + + /* SACL offset */ + if ((secinfo & SMB_SACL_SECINFO) && (sd->sd_sacl)) { + (void) smb_encode_mbc(&xa->rep_data_mb, "l", offset); + offset += smb_acl_len(sd->sd_sacl); + } else { + (void) smb_encode_mbc(&xa->rep_data_mb, "l", 0); + } + + /* DACL offset */ + if ((secinfo & SMB_DACL_SECINFO) && (sd->sd_dacl)) + (void) smb_encode_mbc(&xa->rep_data_mb, "l", offset); + else + (void) smb_encode_mbc(&xa->rep_data_mb, "l", 0); + + if (secinfo & SMB_OWNER_SECINFO) + smb_encode_sid(xa, sd->sd_owner); + + if (secinfo & SMB_GROUP_SECINFO) + smb_encode_sid(xa, sd->sd_group); + + if (secinfo & SMB_SACL_SECINFO) + smb_encode_sacl(xa, sd->sd_sacl); + + if (secinfo & SMB_DACL_SECINFO) + smb_encode_dacl(xa, sd->sd_dacl); +} + +/* + * smb_encode_sid + * + * Encodes given SID in the reply buffer. + */ +static void +smb_encode_sid(struct smb_xa *xa, nt_sid_t *sid) +{ + int i; + + (void) smb_encode_mbc(&xa->rep_data_mb, "bb", + sid->Revision, sid->SubAuthCount); + + for (i = 0; i < NT_SID_AUTH_MAX; i++) { + (void) smb_encode_mbc(&xa->rep_data_mb, "b", + sid->Authority[i]); + } + + for (i = 0; i < sid->SubAuthCount; i++) { + (void) smb_encode_mbc(&xa->rep_data_mb, "l", + sid->SubAuthority[i]); + } +} + +/* + * smb_encode_sacl + * + * Encodes given SACL in the reply buffer. + */ +static void +smb_encode_sacl(struct smb_xa *xa, smb_acl_t *acl) +{ + smb_ace_t *ace; + int i; + + if (acl == NULL) + return; + + /* encode header */ + (void) smb_encode_mbc(&xa->rep_data_mb, "b.ww2.", acl->sl_revision, + acl->sl_bsize, acl->sl_acecnt); + + for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) { + (void) smb_encode_mbc(&xa->rep_data_mb, "bbwl", + ace->se_hdr.se_type, ace->se_hdr.se_flags, + ace->se_hdr.se_bsize, ace->se_mask); + + smb_encode_sid(xa, ace->se_sid); + } +} + +/* + * smb_encode_dacl + * + * Encodes given DACL in the reply buffer. + */ +static void +smb_encode_dacl(struct smb_xa *xa, smb_acl_t *acl) +{ + smb_ace_t *ace; + + if (acl == NULL) + return; + + /* encode header */ + (void) smb_encode_mbc(&xa->rep_data_mb, "b.ww2.", acl->sl_revision, + acl->sl_bsize, acl->sl_acecnt); + + ace = list_head(&acl->sl_sorted); + while (ace) { + (void) smb_encode_mbc(&xa->rep_data_mb, "bbwl", + ace->se_hdr.se_type, ace->se_hdr.se_flags, + ace->se_hdr.se_bsize, ace->se_mask); + + smb_encode_sid(xa, ace->se_sid); + ace = list_next(&acl->sl_sorted, ace); + } +} + +/* + * smb_decode_sd + * + * Decodes the security descriptor in the request buffer + * and set the fields of 'sd' appropraitely. Upon successful + * return, caller must free allocated memories by calling + * smb_sd_term(). + */ +uint32_t +smb_decode_sd(struct smb_xa *xa, smb_sd_t *sd) +{ + struct mbuf_chain sdbuf; + uint32_t owner_offs; + uint32_t group_offs; + uint32_t sacl_offs; + uint32_t dacl_offs; + + smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); + + (void) MBC_SHADOW_CHAIN(&sdbuf, &xa->req_data_mb, + xa->req_data_mb.chain_offset, + xa->req_data_mb.max_bytes - xa->req_data_mb.chain_offset); + + if (smb_decode_mbc(&sdbuf, "b.wllll", + &sd->sd_revision, &sd->sd_control, + &owner_offs, &group_offs, &sacl_offs, &dacl_offs)) + goto decode_error; + + sd->sd_control &= ~SE_SELF_RELATIVE; + + if (owner_offs != 0) { + if (owner_offs < SMB_SD_HDRSIZE) + goto decode_error; + + sd->sd_owner = smb_decode_sid(xa, owner_offs); + if (sd->sd_owner == NULL) + goto decode_error; + } + + if (group_offs != 0) { + if (group_offs < SMB_SD_HDRSIZE) + goto decode_error; + + sd->sd_group = smb_decode_sid(xa, group_offs); + if (sd->sd_group == NULL) + goto decode_error; + } + + if (sacl_offs != 0) { + if ((sd->sd_control & SE_SACL_PRESENT) == 0) + goto decode_error; + + if (sacl_offs < SMB_SD_HDRSIZE) + goto decode_error; + + sd->sd_sacl = smb_decode_acl(xa, sacl_offs); + if (sd->sd_sacl == NULL) + goto decode_error; + } + + if (dacl_offs != 0) { + if ((sd->sd_control & SE_DACL_PRESENT) == 0) + goto decode_error; + + if (dacl_offs < SMB_SD_HDRSIZE) + goto decode_error; + + sd->sd_dacl = smb_decode_acl(xa, dacl_offs); + if (sd->sd_dacl == NULL) + goto decode_error; + } + + return (NT_STATUS_SUCCESS); + +decode_error: + smb_sd_term(sd); + return (NT_STATUS_INVALID_SECURITY_DESCR); +} + +/* + * smb_decode_sid + * + * Allocates memory and decodes the SID in the request buffer + * Upon successful return, caller must free the allocated memory + * by calling MEM_FREE() + */ +static nt_sid_t * +smb_decode_sid(struct smb_xa *xa, uint32_t offset) +{ + uint8_t revision; + uint8_t subauth_cnt; + struct mbuf_chain sidbuf; + nt_sid_t *sid; + int sidlen; + int bytes_left; + int i; + + offset += xa->req_data_mb.chain_offset; + bytes_left = xa->req_data_mb.max_bytes - offset; + if (bytes_left < sizeof (nt_sid_t)) + return (NULL); + + (void) MBC_SHADOW_CHAIN(&sidbuf, &xa->req_data_mb, offset, bytes_left); + + if (smb_decode_mbc(&sidbuf, "bb", &revision, &subauth_cnt)) + return (NULL); + + sidlen = sizeof (nt_sid_t) - sizeof (uint32_t) + + (subauth_cnt * sizeof (uint32_t)); + sid = MEM_MALLOC("smbsrv", sidlen); + + sid->Revision = revision; + sid->SubAuthCount = subauth_cnt; + + for (i = 0; i < NT_SID_AUTH_MAX; i++) { + if (smb_decode_mbc(&sidbuf, "b", &sid->Authority[i])) + goto decode_err; + } + + for (i = 0; i < sid->SubAuthCount; i++) { + if (smb_decode_mbc(&sidbuf, "l", &sid->SubAuthority[i])) + goto decode_err; + } + + return (sid); + +decode_err: + MEM_FREE("smbsrv", sid); + return (NULL); +} + +/* + * smb_decode_acl + * + * Allocates memory and decodes the ACL in the request buffer + * Upon successful return, caller must free the allocated memory + * by calling smb_acl_free(). + */ +static smb_acl_t * +smb_decode_acl(struct smb_xa *xa, uint32_t offset) +{ + struct mbuf_chain aclbuf; + smb_acl_t *acl; + smb_ace_t *ace; + uint8_t revision; + uint16_t size; + uint16_t acecnt; + int bytes_left; + uint32_t sid_offs = offset; + int sidlen; + int i; + + offset += xa->req_data_mb.chain_offset; + bytes_left = xa->req_data_mb.max_bytes - offset; + if (bytes_left < SMB_ACL_HDRSIZE) + return (NULL); + + (void) MBC_SHADOW_CHAIN(&aclbuf, &xa->req_data_mb, offset, bytes_left); + + if (smb_decode_mbc(&aclbuf, "b.ww2.", &revision, &size, &acecnt)) + return (NULL); + + if (size == 0) + return (NULL); + + acl = smb_acl_alloc(revision, size, acecnt); + + sid_offs += SMB_ACL_HDRSIZE; + for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) { + if (smb_decode_mbc(&aclbuf, "bbwl", + &ace->se_hdr.se_type, &ace->se_hdr.se_flags, + &ace->se_hdr.se_bsize, &ace->se_mask)) + goto decode_error; + + sid_offs += SMB_ACE_HDRSIZE + sizeof (ace->se_mask); + ace->se_sid = smb_decode_sid(xa, sid_offs); + if (ace->se_sid == NULL) + goto decode_error; + sidlen = nt_sid_length(ace->se_sid); + aclbuf.chain_offset += sidlen; + sid_offs += sidlen; + } + + return (acl); + +decode_error: + smb_acl_free(acl); + return (NULL); +} diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c index 150262e28b..e8eb106291 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c +++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c @@ -498,7 +498,7 @@ smb_ofile_seek( int32_t off, uint32_t *retoff) { - off_t newoff = 0; + u_offset_t newoff = 0; int rc = 0; ASSERT(of); @@ -511,21 +511,22 @@ smb_ofile_seek( if (off < 0) newoff = 0; else - newoff = (off_t)off; + newoff = (u_offset_t)off; break; case SMB_SEEK_CUR: if (off < 0 && (-off) > of->f_seek_pos) newoff = 0; else - newoff = of->f_seek_pos + (off_t)off; + newoff = of->f_seek_pos + (u_offset_t)off; break; case SMB_SEEK_END: if (off < 0 && (-off) > of->f_node->attr.sa_vattr.va_size) newoff = 0; else - newoff = of->f_node->attr.sa_vattr.va_size + (off_t)off; + newoff = of->f_node->attr.sa_vattr.va_size + + (u_offset_t)off; break; default: @@ -533,7 +534,12 @@ smb_ofile_seek( return (EINVAL); } - if (newoff > ULONG_MAX) { + /* + * See comments at the beginning of smb_seek.c. + * If the offset is greater than UINT_MAX, we will return an error. + */ + + if (newoff > UINT_MAX) { rc = EOVERFLOW; } else { of->f_seek_pos = newoff; diff --git a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c index aa02274224..b195ed6353 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c @@ -280,7 +280,7 @@ smb_com_open(struct smb_request *sr) ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY); } - if (op->dsize > 0xffffffff) + if (op->dsize > UINT_MAX) smbsr_raise_error(sr, ERRDOS, ERRbadfunc); file_attr = op->dattr & FILE_ATTRIBUTE_MASK; @@ -350,7 +350,7 @@ smb_com_open_andx(struct smb_request *sr) else if (flags & 4) op->my_flags = MYF_BATCH_OPLOCK; - if ((CreationTime != 0) && (CreationTime != 0xffffffff)) + if ((CreationTime != 0) && (CreationTime != UINT_MAX)) op->utime.tv_sec = smb_local_time_to_gmt(CreationTime); op->utime.tv_nsec = 0; @@ -385,7 +385,7 @@ smb_com_open_andx(struct smb_request *sr) /* NOTREACHED */ } - if (op->dsize > 0xffffffff) + if (op->dsize > UINT_MAX) smbsr_raise_error(sr, ERRDOS, ERRbadfunc); if (MYF_OPLOCK_TYPE(op->my_flags) != MYF_OPLOCK_NONE) { diff --git a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c index cacbbb3e9d..cc203a7315 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c +++ b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c @@ -391,19 +391,17 @@ smb_pathname( rootvp = (vnode_t *)root_node->vp; /* - * Instead of passing the FOLLOW flag to lookuppnvp(), process links in - * this routine. This allows smb_nodes to be created for each component - * of a link. - */ - local_flags = flags & FIGNORECASE; - - /* * Path components are processed one at a time so that smb_nodes * can be created for each component. This allows the dir_snode * field in the smb_node to be properly populated. * - * Mangle checking is also done on each component. + * Because of the above, links are also processed in this routine + * (i.e., we do not pass the FOLLOW flag to lookuppnvp()). This + * will allow smb_nodes to be created for each component of a link. + * + * Mangle checking is per component. */ + while ((pathleft = pn_pathleft(&upn)) != 0) { if (fnode) { smb_node_release(dnode); @@ -419,10 +417,24 @@ smb_pathname( component, real_name, MAXNAMELEN, 0, 0, 1)) != 0) break; + /* + * Do not pass FIGNORECASE to lookuppnvp(). + * This is because we would like to do a lookup + * on the real name just obtained (which + * corresponds to the mangled name). + */ namep = real_name; + local_flags = 0; } else { + /* + * Pass FIGNORECASE to lookuppnvp(). + * This will cause the file system to + * return "first match" in the event of + * a case collision. + */ namep = component; + local_flags = flags & FIGNORECASE; } if ((err = pn_set(&pn, namep)) != 0) diff --git a/usr/src/uts/common/fs/smbsrv/smb_read.c b/usr/src/uts/common/fs/smbsrv/smb_read.c index 6554c07014..8542a1a1f9 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_read.c +++ b/usr/src/uts/common/fs/smbsrv/smb_read.c @@ -145,7 +145,7 @@ smb_com_lock_and_read(struct smb_request *sr) } result = smb_lock_range(sr, sr->fid_ofile, param.r_offset, - (uint64_t)param.r_count, 0xffffffff, SMB_LOCK_TYPE_READWRITE); + (uint64_t)param.r_count, UINT_MAX, SMB_LOCK_TYPE_READWRITE); if (result != NT_STATUS_SUCCESS) { smb_lock_range_raise_error(sr, result); } @@ -370,7 +370,7 @@ smb_common_read(struct smb_request *sr, smb_read_param_t *param) vdb->uio.uio_iov = &vdb->iovec[0]; vdb->uio.uio_iovcnt = MAX_IOVEC; vdb->uio.uio_resid = param->r_count; - vdb->uio.uio_offset = param->r_offset; + vdb->uio.uio_loffset = (offset_t)param->r_offset; vdb->uio.uio_segflg = UIO_SYSSPACE; switch (sr->tid_tree->t_res_type & STYPE_MASK) { diff --git a/usr/src/uts/common/fs/smbsrv/smb_rpc.c b/usr/src/uts/common/fs/smbsrv/smb_rpc.c index 394c5addbe..5059c909b4 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_rpc.c +++ b/usr/src/uts/common/fs/smbsrv/smb_rpc.c @@ -171,9 +171,6 @@ smb_rpc_open(struct smb_request *sr) char *pipe_name; int status; - if (smb_winpipe_open() != 0) - return (NT_STATUS_INTERNAL_ERROR); - op = &sr->arg.open; if ((pipe_name = smb_rpc_lookup(op->fqi.path)) != 0) { @@ -278,7 +275,7 @@ smb_rpc_transact(struct smb_request *sr, struct uio *uio) streamin = &pipe_info->input; streamin->uio.uio_iov = uio->uio_iov; streamin->uio.uio_iovcnt = uio->uio_iovcnt; - streamin->uio.uio_offset = 0; + streamin->uio.uio_loffset = 0; streamin->uio.uio_resid = uio->uio_resid; streamin->uio.uio_segflg = UIO_SYSSPACE; @@ -446,7 +443,7 @@ smb_rpc_write(struct smb_request *sr, struct uio *uio) streamin = &pipe_info->input; streamin->uio.uio_iov = uio->uio_iov; streamin->uio.uio_iovcnt = uio->uio_iovcnt; - streamin->uio.uio_offset = 0; + streamin->uio.uio_loffset = 0; streamin->uio.uio_resid = uio->uio_resid; streamin->uio.uio_segflg = UIO_SYSSPACE; mdrcnt = (uint32_t)uio->uio_resid; diff --git a/usr/src/uts/common/fs/smbsrv/smb_sd.c b/usr/src/uts/common/fs/smbsrv/smb_sd.c index 4afa258b9a..fa2bf223d7 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_sd.c +++ b/usr/src/uts/common/fs/smbsrv/smb_sd.c @@ -29,20 +29,21 @@ * This module provides Security Descriptor handling functions. */ -#include <smbsrv/smb_incl.h> +#include <smbsrv/smbvar.h> +#include <smbsrv/smb_kproto.h> #include <smbsrv/smb_fsops.h> #include <smbsrv/smb_idmap.h> +#include <smbsrv/ntstatus.h> -#define AS_DWORD(X) (*(uint32_t *)&(X)) -#define SELF_REL(P, M, T) (T *)(((char *)(P)) + AS_DWORD((P)->M)) - -void smb_fmt_sid(char *buf, nt_sid_t *sid); +static void smb_sd_set_sacl(smb_sd_t *, smb_acl_t *, boolean_t, int); +static void smb_sd_set_dacl(smb_sd_t *, smb_acl_t *, boolean_t, int); +static uint32_t smb_sd_fromfs(smb_fssd_t *, smb_sd_t *); void smb_sd_init(smb_sd_t *sd, uint8_t revision) { bzero(sd, sizeof (smb_sd_t)); - sd->sd_hdr.sd_revision = revision; + sd->sd_revision = revision; } /* @@ -55,7 +56,7 @@ void smb_sd_term(smb_sd_t *sd) { ASSERT(sd); - ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0); + ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); if (sd->sd_owner) MEM_FREE("libnt", sd->sd_owner); @@ -63,219 +64,28 @@ smb_sd_term(smb_sd_t *sd) if (sd->sd_group) MEM_FREE("libnt", sd->sd_group); - if (sd->sd_dacl) - kmem_free(sd->sd_dacl, sd->sd_dacl->sl_size); - - if (sd->sd_sacl) - kmem_free(sd->sd_sacl, sd->sd_sacl->sl_size); + smb_acl_free(sd->sd_dacl); + smb_acl_free(sd->sd_sacl); bzero(sd, sizeof (smb_sd_t)); } -/* - * Hmmm. For all of these smb_sd_set_xxx() functions, - * what do we do if the affected member is already set? - * Should we free() it? For now, punt and risk a memory leak. - */ - -void -smb_sd_set_owner(smb_sd_t *sd, nt_sid_t *owner, int defaulted) -{ - ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0); - - sd->sd_owner = owner; - if (defaulted) - sd->sd_hdr.sd_control |= SE_OWNER_DEFAULTED; - else - sd->sd_hdr.sd_control &= ~SE_OWNER_DEFAULTED; -} - -void -smb_sd_set_group(smb_sd_t *sd, nt_sid_t *group, int defaulted) -{ - ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0); - - sd->sd_group = group; - if (defaulted) - sd->sd_hdr.sd_control |= SE_GROUP_DEFAULTED; - else - sd->sd_hdr.sd_control &= ~SE_GROUP_DEFAULTED; -} - -void -smb_sd_set_dacl(smb_sd_t *sd, int present, smb_acl_t *acl, int flags) -{ - ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0); - - sd->sd_dacl = acl; - - if (flags & ACL_DEFAULTED) - sd->sd_hdr.sd_control |= SE_DACL_DEFAULTED; - if (flags & ACL_AUTO_INHERIT) - sd->sd_hdr.sd_control |= SE_DACL_AUTO_INHERITED; - if (flags & ACL_PROTECTED) - sd->sd_hdr.sd_control |= SE_DACL_PROTECTED; - - if (present) - sd->sd_hdr.sd_control |= SE_DACL_PRESENT; -} - -void -smb_sd_set_sacl(smb_sd_t *sd, int present, smb_acl_t *acl, int flags) -{ - ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0); - - sd->sd_sacl = acl; - - if (flags & ACL_DEFAULTED) - sd->sd_hdr.sd_control |= SE_SACL_DEFAULTED; - if (flags & ACL_AUTO_INHERIT) - sd->sd_hdr.sd_control |= SE_SACL_AUTO_INHERITED; - if (flags & ACL_PROTECTED) - sd->sd_hdr.sd_control |= SE_SACL_PROTECTED; - - if (present) - sd->sd_hdr.sd_control |= SE_SACL_PRESENT; -} - -nt_sid_t * -smb_sd_get_owner(void *sd, int *defaulted) -{ - smb_sdbuf_t *sr_sd; - smb_sd_hdr_t *sd_hdr; - nt_sid_t *sid; - - sd_hdr = (smb_sd_hdr_t *)sd; - if (defaulted != NULL) - *defaulted = (sd_hdr->sd_control & SE_OWNER_DEFAULTED) ? 1 : 0; - - if (sd_hdr->sd_control & SE_SELF_RELATIVE) { - sr_sd = ((smb_sdbuf_t *)sd); - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - sid = SELF_REL(sr_sd, sd_owner_offs, nt_sid_t); - } - else - sid = ((smb_sd_t *)sd)->sd_owner; - - return (sid); -} - -nt_sid_t * -smb_sd_get_group(void *sd, int *defaulted) -{ - smb_sdbuf_t *sr_sd; - smb_sd_hdr_t *sd_hdr; - nt_sid_t *sid; - - sd_hdr = (smb_sd_hdr_t *)sd; - if (defaulted != NULL) - *defaulted = (sd_hdr->sd_control & SE_GROUP_DEFAULTED) ? 1 : 0; - - if (sd_hdr->sd_control & SE_SELF_RELATIVE) { - sr_sd = ((smb_sdbuf_t *)sd); - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - sid = SELF_REL(sr_sd, sd_group_offs, nt_sid_t); - } - else - sid = ((smb_sd_t *)sd)->sd_group; - - return (sid); -} - -smb_acl_t * -smb_sd_get_dacl(void *sd, int *present, int *defaulted) -{ - smb_sdbuf_t *sr_sd; - smb_sd_hdr_t *sd_hdr; - smb_acl_t *acl = NULL; - - sd_hdr = (smb_sd_hdr_t *)sd; - if (present != NULL) - *present = (sd_hdr->sd_control & SE_DACL_PRESENT) ? 1 : 0; - - if (defaulted != NULL) - *defaulted = (sd_hdr->sd_control & SE_DACL_DEFAULTED) ? 1 : 0; - - if (sd_hdr->sd_control & SE_SELF_RELATIVE) { - sr_sd = ((smb_sdbuf_t *)sd); - if (sr_sd->sd_dacl_offs) { - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - acl = SELF_REL(sr_sd, sd_dacl_offs, smb_acl_t); - } - } - else - acl = ((smb_sd_t *)sd)->sd_dacl; - - return (acl); -} - -smb_acl_t * -smb_sd_get_sacl(void *sd, int *present, int *defaulted) -{ - smb_sdbuf_t *sr_sd; - smb_sd_hdr_t *sd_hdr; - smb_acl_t *acl = NULL; - - sd_hdr = (smb_sd_hdr_t *)sd; - if (present != NULL) - *present = (sd_hdr->sd_control & SE_SACL_PRESENT) ? 1 : 0; - - if (defaulted != NULL) - *defaulted = (sd_hdr->sd_control & SE_SACL_DEFAULTED) ? 1 : 0; - - if (sd_hdr->sd_control & SE_SELF_RELATIVE) { - sr_sd = ((smb_sdbuf_t *)sd); - if (sr_sd->sd_sacl_offs) { - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - acl = SELF_REL(sr_sd, sd_sacl_offs, smb_acl_t); - } - } - else - acl = ((smb_sd_t *)sd)->sd_sacl; - - return (acl); -} - uint32_t -smb_sd_len(void *sd, uint32_t secinfo) +smb_sd_len(smb_sd_t *sd, uint32_t secinfo) { - uint32_t length = 0; - nt_sid_t *sid; - smb_acl_t *acl; - int present; - - /* SD Header */ - length += sizeof (smb_sdbuf_t); + uint32_t length = SMB_SD_HDRSIZE; - /* Owner */ - if (secinfo & SMB_OWNER_SECINFO) { - sid = smb_sd_get_owner(sd, NULL); - if (sid) - length += nt_sid_length(sid); - } + if (secinfo & SMB_OWNER_SECINFO) + length += nt_sid_length(sd->sd_owner); + if (secinfo & SMB_GROUP_SECINFO) + length += nt_sid_length(sd->sd_group); - /* Group */ - if (secinfo & SMB_GROUP_SECINFO) { - sid = smb_sd_get_group(sd, NULL); - if (sid) - length += nt_sid_length(sid); - } + if (secinfo & SMB_DACL_SECINFO) + length += smb_acl_len(sd->sd_dacl); - - /* DACL */ - if (secinfo & SMB_DACL_SECINFO) { - acl = smb_sd_get_dacl(sd, &present, NULL); - if (present && acl) - length += smb_acl_len(acl); - } - - /* SACL */ - if (secinfo & SMB_SACL_SECINFO) { - acl = smb_sd_get_sacl(sd, &present, NULL); - if (present && acl) - length += smb_acl_len(acl); - } + if (secinfo & SMB_SACL_SECINFO) + length += smb_acl_len(sd->sd_sacl); return (length); } @@ -287,273 +97,103 @@ smb_sd_len(void *sd, uint32_t secinfo) * descriptor. */ uint32_t -smb_sd_get_secinfo(void *sd) +smb_sd_get_secinfo(smb_sd_t *sd) { uint32_t sec_info = 0; - smb_acl_t *acl; - int present; - if (sd == 0) + if (sd == NULL) return (0); - if (smb_sd_get_owner(sd, NULL) != 0) + if (sd->sd_owner) sec_info |= SMB_OWNER_SECINFO; - if (smb_sd_get_group(sd, NULL) != 0) + if (sd->sd_group) sec_info |= SMB_GROUP_SECINFO; - acl = smb_sd_get_dacl(sd, &present, NULL); - if (acl && present) + if (sd->sd_dacl) sec_info |= SMB_DACL_SECINFO; - acl = smb_sd_get_sacl(sd, &present, NULL); - if (acl && present) + if (sd->sd_sacl) sec_info |= SMB_SACL_SECINFO; return (sec_info); } /* - * smb_sd_abs2selfrel - * - * This function takes an absolute SD (sd) and make a self relative - * SD which will be returned in srel_sd. - * - * srel_sdsz contains the size of buffer which srel_sd points to. + * smb_sd_read * - * Do not add new error codes here without checking the impact on - * all callers of this function. + * Read uid, gid and ACL from filesystem. The returned ACL from read + * routine is always in ZFS format. Convert the ZFS acl to a Win acl + * and return the Win SD in absolute form. * - * Returns NT status codes: - * NT_STATUS_SUCCESS - * NT_STATUS_BUFFER_TOO_SMALL - * NT_STATUS_INVALID_SECURITY_DESCR + * NOTE: upon successful return caller MUST free the memory allocated + * for the returned SD by calling smb_sd_term(). */ -static uint32_t -smb_sd_abs2selfrel( - smb_sd_t *sd, - uint32_t secinfo, - smb_sdbuf_t *srel_sd, - uint32_t srel_sdsz) +uint32_t +smb_sd_read(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) { - uint32_t avail_len = srel_sdsz; - uint32_t length = 0; - unsigned char *scan_beg = (unsigned char *) srel_sd; - unsigned char *scan = scan_beg; - unsigned char *scan_end; - nt_sid_t *sid; - smb_acl_t *acl; - int present, defaulted; - - length = smb_sd_len(sd, secinfo); - - if (length == 0) - return (NT_STATUS_INVALID_SECURITY_DESCR); - - if (avail_len < length) - return (NT_STATUS_BUFFER_TOO_SMALL); - - bzero(srel_sd, length); - scan_end = scan_beg + length; - - /* SD Header */ - length = sizeof (smb_sdbuf_t); - srel_sd->sd_hdr.sd_revision = sd->sd_hdr.sd_revision; - srel_sd->sd_hdr.sd_control = SE_SELF_RELATIVE; - scan += length; - - if (secinfo & SMB_OWNER_SECINFO) { - /* Owner */ - sid = smb_sd_get_owner(sd, &defaulted); - - if (defaulted) - srel_sd->sd_hdr.sd_control |= SE_OWNER_DEFAULTED; - - if (sid) { - /*LINTED E_PTRDIFF_OVERFLOW*/ - length = nt_sid_copy((void*)scan, sid, scan_end - scan); - if (length == 0) - goto fail; - /*LINTED E_PTRDIFF_OVERFLOW*/ - srel_sd->sd_owner_offs = scan - scan_beg; - scan += length; - } - } - - if (secinfo & SMB_GROUP_SECINFO) { - /* Group */ - sid = smb_sd_get_group(sd, &defaulted); - - if (defaulted) - srel_sd->sd_hdr.sd_control |= SE_GROUP_DEFAULTED; - - if (sid) { - /*LINTED E_PTRDIFF_OVERFLOW*/ - length = nt_sid_copy((void*)scan, sid, scan_end - scan); - if (length == 0) - goto fail; - /*LINTED E_PTRDIFF_OVERFLOW*/ - srel_sd->sd_group_offs = scan - scan_beg; - scan += length; - } - } - - - if (secinfo & SMB_DACL_SECINFO) { - /* Dacl */ - acl = smb_sd_get_dacl(sd, &present, &defaulted); - - srel_sd->sd_hdr.sd_control |= - (sd->sd_hdr.sd_control & SE_DACL_INHERITANCE_MASK); - - if (defaulted) - srel_sd->sd_hdr.sd_control |= SE_DACL_DEFAULTED; + smb_fssd_t fs_sd; + smb_error_t smb_err; + smb_node_t *node; + uint32_t status = NT_STATUS_SUCCESS; + uint32_t sd_flags; + int error; - if (present) - srel_sd->sd_hdr.sd_control |= SE_DACL_PRESENT; + node = sr->fid_ofile->f_node; + sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0; + smb_fssd_init(&fs_sd, secinfo, sd_flags); - if (present && acl) { - /*LINTED E_PTRDIFF_OVERFLOW*/ - length = smb_acl_copy(scan_end - scan, - (void*) scan, acl); - if (length == 0) - goto fail; - /*LINTED E_PTRDIFF_OVERFLOW*/ - srel_sd->sd_dacl_offs = scan - scan_beg; - /*LINTED E_PTRDIFF_OVERFLOW*/ - acl = (smb_acl_t *)scan; - acl->sl_size = (WORD)length; /* set the size */ - scan += length; - } + error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd); + if (error) { + smb_errmap_unix2smb(error, &smb_err); + return (smb_err.status); } - if (secinfo & SMB_SACL_SECINFO) { - /* Sacl */ - acl = smb_sd_get_sacl(sd, &present, &defaulted); - - srel_sd->sd_hdr.sd_control |= - (sd->sd_hdr.sd_control & SE_SACL_INHERITANCE_MASK); - - if (defaulted) - srel_sd->sd_hdr.sd_control |= SE_SACL_DEFAULTED; - - if (present) - srel_sd->sd_hdr.sd_control |= SE_SACL_PRESENT; - - if (present && acl) { - /*LINTED E_PTRDIFF_OVERFLOW*/ - length = smb_acl_copy(scan_end - scan, - (void*) scan, acl); - if (length == 0) - goto fail; - /*LINTED E_PTRDIFF_OVERFLOW*/ - srel_sd->sd_sacl_offs = scan - scan_beg; - /*LINTED E_PTRDIFF_OVERFLOW*/ - acl = (smb_acl_t *)scan; - acl->sl_size = (WORD)length; /* set the size */ - scan += length; - } - } + status = smb_sd_fromfs(&fs_sd, sd); + smb_fssd_term(&fs_sd); - return (NT_STATUS_SUCCESS); - -fail: - return (NT_STATUS_INVALID_SECURITY_DESCR); + return (status); } /* - * smb_sd_fromfs - * - * Makes an Windows style security descriptor in absolute form - * based on the given filesystem security information. + * smb_sd_write * - * Should call smb_sd_term() for the returned sd to free allocated - * members. + * Takes a Win SD in absolute form, converts it to + * ZFS format and write it to filesystem. The write routine + * converts ZFS acl to Posix acl if required. */ -static uint32_t -smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd) +uint32_t +smb_sd_write(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) { - uint32_t status = NT_STATUS_SUCCESS; - smb_acl_t *acl = NULL; - smb_acl_t *sorted_acl; - nt_sid_t *sid; - idmap_stat idm_stat; - - ASSERT(fs_sd); - ASSERT(sd); - - smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); - - /* Owner */ - if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { - idm_stat = smb_idmap_getsid(fs_sd->sd_uid, - SMB_IDMAP_USER, &sid); - - if (idm_stat != IDMAP_SUCCESS) { - return (NT_STATUS_NONE_MAPPED); - } - - smb_sd_set_owner(sd, sid, 0); - } - - /* Group */ - if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { - idm_stat = smb_idmap_getsid(fs_sd->sd_gid, - SMB_IDMAP_GROUP, &sid); - - if (idm_stat != IDMAP_SUCCESS) { - smb_sd_term(sd); - return (NT_STATUS_NONE_MAPPED); - } - - smb_sd_set_group(sd, sid, 0); - } + smb_node_t *node; + smb_fssd_t fs_sd; + smb_error_t smb_err; + uint32_t status; + uint32_t sd_flags; + int error; - /* DACL */ - if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { - if (fs_sd->sd_zdacl != NULL) { - acl = smb_acl_from_zfs(fs_sd->sd_zdacl, fs_sd->sd_uid, - fs_sd->sd_gid); - if (acl == NULL) { - smb_sd_term(sd); - return (NT_STATUS_INTERNAL_ERROR); - } + node = sr->fid_ofile->f_node; + sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0; + smb_fssd_init(&fs_sd, secinfo, sd_flags); - /* - * Need to sort the ACL before send it to Windows - * clients. Winodws GUI is sensitive about the order - * of ACEs. - */ - sorted_acl = smb_acl_sort(acl); - if (sorted_acl && (sorted_acl != acl)) { - kmem_free(acl, acl->sl_size); - acl = sorted_acl; - } - smb_sd_set_dacl(sd, 1, acl, fs_sd->sd_zdacl->acl_flags); - } else { - smb_sd_set_dacl(sd, 0, NULL, 0); - } + status = smb_sd_tofs(sd, &fs_sd); + if (status != NT_STATUS_SUCCESS) { + smb_fssd_term(&fs_sd); + return (status); } - /* SACL */ - if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { - if (fs_sd->sd_zsacl != NULL) { - acl = smb_acl_from_zfs(fs_sd->sd_zsacl, fs_sd->sd_uid, - fs_sd->sd_gid); - if (acl == NULL) { - smb_sd_term(sd); - return (NT_STATUS_INTERNAL_ERROR); - } + error = smb_fsop_sdwrite(sr, sr->user_cr, node, &fs_sd, 0); + smb_fssd_term(&fs_sd); - smb_sd_set_sacl(sd, 1, acl, fs_sd->sd_zsacl->acl_flags); - } else { - smb_sd_set_sacl(sd, 0, NULL, 0); - } + if (error) { + smb_errmap_unix2smb(error, &smb_err); + return (smb_err.status); } - return (status); + return (NT_STATUS_SUCCESS); } + /* * smb_sd_tofs * @@ -561,18 +201,16 @@ smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd) * Windows security descriptor. */ uint32_t -smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd) +smb_sd_tofs(smb_sd_t *sd, smb_fssd_t *fs_sd) { nt_sid_t *sid; - smb_acl_t *acl; uint32_t status = NT_STATUS_SUCCESS; uint16_t sd_control; idmap_stat idm_stat; - int present; int idtype; int flags = 0; - sd_control = sr_sd->sd_hdr.sd_control; + sd_control = sd->sd_control; /* * ZFS only has one set of flags so for now only @@ -590,7 +228,7 @@ smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd) /* Owner */ if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { - sid = smb_sd_get_owner(sr_sd, NULL); + sid = sd->sd_owner; if (nt_sid_is_valid(sid) == 0) { return (NT_STATUS_INVALID_SID); } @@ -604,7 +242,7 @@ smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd) /* Group */ if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { - sid = smb_sd_get_group(sr_sd, NULL); + sid = sd->sd_group; if (nt_sid_is_valid(sid) == 0) { return (NT_STATUS_INVALID_SID); } @@ -618,9 +256,8 @@ smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd) /* DACL */ if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { - acl = smb_sd_get_dacl(sr_sd, &present, NULL); - if (present) { - status = smb_acl_to_zfs(acl, flags, + if (sd->sd_control & SE_DACL_PRESENT) { + status = smb_acl_to_zfs(sd->sd_dacl, flags, SMB_DACL_SECINFO, &fs_sd->sd_zdacl); if (status != NT_STATUS_SUCCESS) return (status); @@ -631,9 +268,8 @@ smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd) /* SACL */ if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { - acl = smb_sd_get_sacl(sr_sd, &present, NULL); - if (present) { - status = smb_acl_to_zfs(acl, flags, + if (sd->sd_control & SE_SACL_PRESENT) { + status = smb_acl_to_zfs(sd->sd_sacl, flags, SMB_SACL_SECINFO, &fs_sd->sd_zsacl); if (status != NT_STATUS_SUCCESS) { return (status); @@ -647,216 +283,156 @@ smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd) } /* - * smb_sd_read + * smb_sd_fromfs * - * Read uid, gid and ACL from filesystem. The returned ACL from read - * routine is always in ZFS format. Convert the ZFS acl to a Win acl - * and return the Win SD in relative form. + * Makes an Windows style security descriptor in absolute form + * based on the given filesystem security information. * - * NOTE: upon successful return caller MUST free the memory allocated - * for the returned SD by calling kmem_free(). The length of the allocated - * buffer is returned in 'buflen'. + * Should call smb_sd_term() for the returned sd to free allocated + * members. */ -uint32_t -smb_sd_read(smb_request_t *sr, smb_sdbuf_t **sr_sd, - uint32_t secinfo, uint32_t *buflen) +static uint32_t +smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd) { - smb_sd_t sd; - smb_fssd_t fs_sd; - smb_error_t smb_err; - smb_sdbuf_t *sdbuf; - smb_node_t *node; - uint32_t sdlen; uint32_t status = NT_STATUS_SUCCESS; - uint32_t sd_flags; - int error; + smb_acl_t *acl = NULL; + nt_sid_t *sid; + idmap_stat idm_stat; - *sr_sd = NULL; + ASSERT(fs_sd); + ASSERT(sd); - node = sr->fid_ofile->f_node; - sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0; - smb_fsop_sdinit(&fs_sd, secinfo, sd_flags); + smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); - error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd); - if (error) { - smb_errmap_unix2smb(error, &smb_err); - return (smb_err.status); + /* Owner */ + if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { + idm_stat = smb_idmap_getsid(fs_sd->sd_uid, + SMB_IDMAP_USER, &sid); + + if (idm_stat != IDMAP_SUCCESS) { + smb_sd_term(sd); + return (NT_STATUS_NONE_MAPPED); + } + + sd->sd_owner = sid; } - status = smb_sd_fromfs(&fs_sd, &sd); - smb_fsop_sdterm(&fs_sd); + /* Group */ + if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { + idm_stat = smb_idmap_getsid(fs_sd->sd_gid, + SMB_IDMAP_GROUP, &sid); - if (status != NT_STATUS_SUCCESS) - return (status); + if (idm_stat != IDMAP_SUCCESS) { + smb_sd_term(sd); + return (NT_STATUS_NONE_MAPPED); + } - sdlen = smb_sd_len(&sd, secinfo); + sd->sd_group = sid; + } - if (*buflen < sdlen) { - /* return the required size */ - *buflen = sdlen; - smb_sd_term(&sd); - return (NT_STATUS_BUFFER_TOO_SMALL); + /* DACL */ + if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { + if (fs_sd->sd_zdacl != NULL) { + acl = smb_acl_from_zfs(fs_sd->sd_zdacl, fs_sd->sd_uid, + fs_sd->sd_gid); + if (acl == NULL) { + smb_sd_term(sd); + return (NT_STATUS_INTERNAL_ERROR); + } + + /* + * Need to sort the ACL before send it to Windows + * clients. Winodws GUI is sensitive about the order + * of ACEs. + */ + smb_acl_sort(acl); + smb_sd_set_dacl(sd, acl, B_TRUE, + fs_sd->sd_zdacl->acl_flags); + } else { + smb_sd_set_dacl(sd, NULL, B_FALSE, 0); + } } - sdbuf = kmem_alloc(sdlen, KM_SLEEP); - status = smb_sd_abs2selfrel(&sd, secinfo, sdbuf, sdlen); - smb_sd_term(&sd); + /* SACL */ + if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { + if (fs_sd->sd_zsacl != NULL) { + acl = smb_acl_from_zfs(fs_sd->sd_zsacl, fs_sd->sd_uid, + fs_sd->sd_gid); + if (acl == NULL) { + smb_sd_term(sd); + return (NT_STATUS_INTERNAL_ERROR); + } - if (status == NT_STATUS_SUCCESS) { - *sr_sd = sdbuf; - *buflen = sdlen; + smb_sd_set_sacl(sd, acl, B_TRUE, + fs_sd->sd_zsacl->acl_flags); + } else { + smb_sd_set_sacl(sd, NULL, B_FALSE, 0); + } } - else - kmem_free(sdbuf, sdlen); return (status); } -/* - * smb_sd_write - * - * Takes a Win SD in self-relative form, convert it to - * ZFS format and write it to filesystem. The write routine - * converts ZFS acl to Posix acl if required. - */ -uint32_t -smb_sd_write(smb_request_t *sr, smb_sdbuf_t *sr_sd, uint32_t secinfo) +static void +smb_sd_set_dacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags) { - smb_node_t *node; - smb_fssd_t fs_sd; - smb_error_t smb_err; - uint32_t status; - uint32_t sd_flags; - int error; + ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); - node = sr->fid_ofile->f_node; - sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0; - smb_fsop_sdinit(&fs_sd, secinfo, sd_flags); + sd->sd_dacl = acl; - status = smb_sd_tofs(sr_sd, &fs_sd); - if (status != NT_STATUS_SUCCESS) { - smb_fsop_sdterm(&fs_sd); - return (status); - } + if (flags & ACL_DEFAULTED) + sd->sd_control |= SE_DACL_DEFAULTED; + if (flags & ACL_AUTO_INHERIT) + sd->sd_control |= SE_DACL_AUTO_INHERITED; + if (flags & ACL_PROTECTED) + sd->sd_control |= SE_DACL_PROTECTED; - error = smb_fsop_sdwrite(sr, sr->user_cr, node, &fs_sd, 0); - smb_fsop_sdterm(&fs_sd); + if (present) + sd->sd_control |= SE_DACL_PRESENT; +} - if (error) { - smb_errmap_unix2smb(error, &smb_err); - return (smb_err.status); - } +static void +smb_sd_set_sacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags) +{ + ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); - return (NT_STATUS_SUCCESS); + sd->sd_sacl = acl; + + if (flags & ACL_DEFAULTED) + sd->sd_control |= SE_SACL_DEFAULTED; + if (flags & ACL_AUTO_INHERIT) + sd->sd_control |= SE_SACL_AUTO_INHERITED; + if (flags & ACL_PROTECTED) + sd->sd_control |= SE_SACL_PROTECTED; + + if (present) + sd->sd_control |= SE_SACL_PRESENT; } /* - * smb_fmt_sid + * smb_fssd_init * - * Make an string SID and copy the result into the specified buffer. + * Initializes the given FS SD structure. */ void -smb_fmt_sid(char *buf, nt_sid_t *sid) +smb_fssd_init(smb_fssd_t *fs_sd, uint32_t secinfo, uint32_t flags) { - char *sid_str; - - sid_str = nt_sid_format(sid); - if (sid_str) { - (void) strcpy(buf, sid_str); - MEM_FREE("smb", sid_str); - } else { - (void) strcpy(buf, "<invalid SID>"); - } + bzero(fs_sd, sizeof (smb_fssd_t)); + fs_sd->sd_secinfo = secinfo; + fs_sd->sd_flags = flags; } /* - * smb_sd_log + * smb_fssd_term * - * log the given Windows style security descriptor information - * in system log. This is for debugging purposes. + * Frees allocated memory for acl fields. */ void -smb_sd_log(void *sd) +smb_fssd_term(smb_fssd_t *fs_sd) { - smb_acl_t *acl; - smb_ace_t *ace; - nt_sid_t *sid; - int present, defaulted; - char entry[128]; - char *inherit; - char *type; - int ix_dacl; - - sid = smb_sd_get_owner(sd, &defaulted); - if (sid) - smb_fmt_sid(entry, sid); - else - (void) strcpy(entry, "NULL"); - - cmn_err(CE_NOTE, " Owner: %s", entry); - - sid = smb_sd_get_group(sd, &defaulted); - if (sid) - smb_fmt_sid(entry, sid); - else - (void) strcpy(entry, "NULL"); - - cmn_err(CE_NOTE, " Primary Group: %s", entry); - - acl = smb_sd_get_dacl(sd, &present, &defaulted); - - if (!present || !acl) { - cmn_err(CE_NOTE, " No DACL"); - return; - } - - for (ix_dacl = 0; - ace = smb_ace_get(acl, ix_dacl); - ix_dacl++) { - /* - * Make sure the ACE type is something we grok. - * All ACE, now and in the future, have a valid - * header. Can't access fields passed the Header - * until we're sure it's right. - */ - switch (ace->se_header.se_type) { - case ACCESS_ALLOWED_ACE_TYPE: - type = "(Allow)"; - break; - case ACCESS_DENIED_ACE_TYPE: - type = "(Deny)"; - break; - - case SYSTEM_AUDIT_ACE_TYPE: - default: - /* Ignore unrecognized/misplaced ACE */ - continue; - } - - smb_fmt_sid(entry, &ace->se_sid); - - switch (ace->se_header.se_flags & INHERIT_MASK_ACE) { - case OBJECT_INHERIT_ACE: - inherit = "(OI)"; - break; - case CONTAINER_INHERIT_ACE: - inherit = "(CI)"; - break; - case INHERIT_ONLY_ACE: - inherit = "(IO)"; - break; - case NO_PROPOGATE_INHERIT_ACE: - inherit = "(NP)"; - break; - default: - inherit = ""; - } - - (void) snprintf(entry + strlen(entry), sizeof (entry), - ":%s 0x%X %s", inherit, ace->se_mask, type); - - cmn_err(CE_NOTE, " %s", entry); - } + ASSERT(fs_sd); - cmn_err(CE_NOTE, " %d ACE(s)", ix_dacl); + smb_fsacl_free(fs_sd->sd_zdacl); + smb_fsacl_free(fs_sd->sd_zsacl); + bzero(fs_sd, sizeof (smb_fssd_t)); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c index 3ab7076102..c92a248a93 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c @@ -637,7 +637,7 @@ int smb_trans2_find_get_dents( ihdr->uio.uio_iovcnt = maxcount; ihdr->uio.uio_resid = dent_buf_size; ihdr->uio.uio_iov = ihdr->iov; - ihdr->uio.uio_offset = 0; + ihdr->uio.uio_loffset = 0; rc = smb_get_dents(sr, cookie, dir_snode, wildcards, ihdr, more); if (rc != 0) { @@ -839,9 +839,9 @@ smb_gather_dents_info( * Each entry needs to be properly aligned or we may get an alignment * fault on sparc. */ - ihdr->uio.uio_offset = (off_t)PTRALIGN(ihdr->uio.uio_offset); + ihdr->uio.uio_loffset = (offset_t)PTRALIGN(ihdr->uio.uio_loffset); /*LINTED E_BAD_PTR_CAST_ALIGN*/ - ient = (smb_dent_info_t *)&ihdr->iov->iov_base[ihdr->uio.uio_offset]; + ient = (smb_dent_info_t *)&ihdr->iov->iov_base[ihdr->uio.uio_loffset]; ient->cookie = cookie; ient->attr = *attr; @@ -856,7 +856,7 @@ smb_gather_dents_info( ihdr->uio.uio_iov++; ihdr->uio.uio_iovcnt--; ihdr->uio.uio_resid -= reclen; - ihdr->uio.uio_offset += reclen; + ihdr->uio.uio_loffset += reclen; kmem_free(v5_name, MAXNAMELEN-1); return (0); diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c index 2d488b7f2c..e6d4dbeccf 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c @@ -78,7 +78,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) { static smb_attr_t pipe_attr; unsigned short infolev, dattr = 0; - off_t dsize = 0, dused = 0; + u_offset_t dsize = 0, dused = 0; smb_attr_t *ap = NULL; char *namep = NULL; char *filename = NULL, *alt_nm_ptr = NULL; @@ -194,10 +194,10 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) break; case SMB_INFO_STANDARD: - if (dsize > 0xffffffff) - dsize = 0xffffffff; - if (dused > 0xffffffff) - dused = 0xffffffff; + if (dsize > UINT_MAX) + dsize = UINT_MAX; + if (dused > UINT_MAX) + dused = UINT_MAX; (void) smb_encode_mbc(&xa->rep_param_mb, "w", 0); (void) smb_encode_mbc(&xa->rep_data_mb, @@ -212,10 +212,10 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) break; case SMB_INFO_QUERY_EA_SIZE: - if (dsize > 0xffffffff) - dsize = 0xffffffff; - if (dused > 0xffffffff) - dused = 0xffffffff; + if (dsize > UINT_MAX) + dsize = UINT_MAX; + if (dused > UINT_MAX) + dused = UINT_MAX; (void) smb_encode_mbc(&xa->rep_param_mb, "w", 0); (void) smb_encode_mbc(&xa->rep_data_mb, @@ -449,7 +449,7 @@ smb_encode_stream_info( uint32_t next_offset; uint32_t stream_nlen; uint32_t pad; - off_t dsize; + u_offset_t dsize; int is_dir; uint32_t cookie = 0; struct fs_stream_info *stream_info; diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c index aa7cc15343..509c4094f0 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c @@ -294,7 +294,7 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) /* NOTREACHED */ } - max_int = 0xffffffffLL; + max_int = (uint64_t)UINT_MAX; if (df.f_blocks > max_int) df.f_blocks = max_int; diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c index 1a80d6a2c4..374a6de2bd 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c @@ -329,7 +329,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) { char *path, *alt_nm_ptr; int rc; - off_t dsize, dused; + u_offset_t dsize, dused; unsigned short infolev, dattr; smb_attr_t *ap, ret_attr; struct smb_node *dir_node; @@ -415,10 +415,10 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) switch (infolev) { case SMB_INFO_STANDARD: - if (dsize > 0xffffffff) - dsize = 0xffffffff; - if (dused > 0xffffffff) - dused = 0xffffffff; + if (dsize > UINT_MAX) + dsize = UINT_MAX; + if (dused > UINT_MAX) + dused = UINT_MAX; (void) smb_encode_mbc(&xa->rep_param_mb, "w", 0); (void) smb_encode_mbc(&xa->rep_data_mb, @@ -433,10 +433,10 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) break; case SMB_INFO_QUERY_EA_SIZE: - if (dsize > 0xffffffff) - dsize = 0xffffffff; - if (dused > 0xffffffff) - dused = 0xffffffff; + if (dsize > UINT_MAX) + dsize = UINT_MAX; + if (dused > UINT_MAX) + dused = UINT_MAX; (void) smb_encode_mbc(&xa->rep_param_mb, "w", 0); (void) smb_encode_mbc(&xa->rep_data_mb, diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c index b41e1c426d..8c4368f93f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c @@ -197,7 +197,7 @@ smb_set_standard_info( if (DataSize != 0) { node->flags |= NODE_FLAGS_SET_SIZE; - node->n_size = DataSize; + node->n_size = (u_offset_t)DataSize; } /* @@ -331,7 +331,7 @@ smb_set_alloc_info( if (node->attr.sa_vattr.va_size != DataSize) { node->flags |= NODE_FLAGS_SET_SIZE; - node->n_size = (off_t)DataSize; + node->n_size = (u_offset_t)DataSize; /* * Ensure that the FS is consistent with the node cache diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c index 85d663c88c..d17c7dfade 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c @@ -164,6 +164,7 @@ * being queued in that list is NOT registered by incrementing the * reference count. */ +#include <sys/fsid.h> #include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> @@ -243,17 +244,21 @@ smb_tree_connect( tree->t_acltype = smb_fsop_acltype(snode); - if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_ACLONCREATE)) { + if (strncasecmp(tree->t_typename, NFS, sizeof (NFS)) == 0) + tree->t_flags |= SMB_TREE_FLAG_NFS_MOUNTED; + + if (strncasecmp(tree->t_typename, "UFS", sizeof ("UFS")) == 0) + tree->t_flags |= SMB_TREE_FLAG_UFS; + + if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_ACLONCREATE)) tree->t_flags |= SMB_TREE_FLAG_ACLONCREATE; - } - if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_ACEMASKONACCESS)) { + if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_ACEMASKONACCESS)) tree->t_flags |= SMB_TREE_FLAG_ACEMASKONACCESS; - } - if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_CASEINSENSITIVE)) { + if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_CASEINSENSITIVE)) tree->t_flags |= SMB_TREE_FLAG_IGNORE_CASE; - } + break; case STYPE_IPC: diff --git a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c index 420c26a250..fef432d9fc 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c +++ b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c @@ -75,7 +75,7 @@ smb_com_unlock_byte_range(struct smb_request *sr) } result = smb_unlock_range(sr, sr->fid_ofile->f_node, - (off_t)Offset, (uint64_t)Length); + (u_offset_t)Offset, (uint64_t)Length); if (result != NT_STATUS_SUCCESS) { smb_unlock_range_raise_error(sr, result); /* NOT REACHED */ diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c index b71174e9d5..538c9cfc91 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_vops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c @@ -34,13 +34,15 @@ #include <sys/pathname.h> #include <sys/cred.h> #include <sys/extdirent.h> -#include <acl/acl_common.h> + #include <smbsrv/smb_vops.h> #include <smbsrv/string.h> -#include <smbsrv/lmshare.h> + #include <smbsrv/smbtrans.h> -#include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> +#include <smbsrv/smb_kproto.h> +#include <smbsrv/smb_incl.h> + static int smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count, @@ -324,7 +326,7 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, int smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, - int flags, cred_t *cr, caller_context_t *ct) + int flags, cred_t *cr, boolean_t no_xvattr, caller_context_t *ct) { int error = 0; int at_size = 0; @@ -350,7 +352,8 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, set_attr->sa_vattr.va_mask = 0; - if (vfs_has_feature(use_vp->v_vfsp, VFSFT_XVATTR)) { + if ((no_xvattr == B_FALSE) && + vfs_has_feature(use_vp->v_vfsp, VFSFT_XVATTR)) { /* * Initialize xvattr, including bzero */ @@ -361,8 +364,8 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, /* * Copy caller-specified classic attributes to tmp_xvattr. - * First save tmp_xvattr's mask (set in xva_init()). - * This is |'d in later. + * First save tmp_xvattr's mask (set in xva_init()), which + * contains AT_XVATTR. This is |'d in later if needed. */ xva_mask = tmp_xvattr.xva_vattr.va_mask; @@ -372,12 +375,20 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, &tmp_xvattr.xva_vattr.va_mask); /* - * "|" in the original xva_mask. + * Do not set ctime (only the file system can do it) */ - tmp_xvattr.xva_vattr.va_mask |= xva_mask; + tmp_xvattr.xva_vattr.va_mask &= ~AT_CTIME; if (set_attr->sa_mask & SMB_AT_DOSATTR) { + + /* + * "|" in the original xva_mask, which contains + * AT_XVATTR + */ + + tmp_xvattr.xva_vattr.va_mask |= xva_mask; + XVA_SET_REQ(&tmp_xvattr, XAT_ARCHIVE); XVA_SET_REQ(&tmp_xvattr, XAT_SYSTEM); XVA_SET_REQ(&tmp_xvattr, XAT_READONLY); @@ -404,6 +415,12 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, } if (set_attr->sa_mask & SMB_AT_CRTIME) { + /* + * "|" in the original xva_mask, which contains + * AT_XVATTR + */ + + tmp_xvattr.xva_vattr.va_mask |= xva_mask; XVA_SET_REQ(&tmp_xvattr, XAT_CREATETIME); xoap->xoa_createtime = set_attr->sa_crtime; } @@ -431,16 +448,12 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, error = VOP_SETATTR(vp, &set_attr->sa_vattr, flags, cr, ct); } - return (error); } - /* - * Support for file systems without VFSFT_XVATTR + * Support for file systems without VFSFT_XVATTR or no_xvattr == B_TRUE */ - smb_sa_to_va_mask(set_attr->sa_mask, &set_attr->sa_vattr.va_mask); - /* * set_attr->sa_vattr already contains new values * as set by the caller @@ -463,7 +476,6 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, set_attr->sa_vattr.va_mask = AT_SIZE; error = VOP_SETATTR(vp, &set_attr->sa_vattr, flags, cr, ct); } - return (error); } @@ -1538,181 +1550,6 @@ smb_vop_statfs(vnode_t *vp, struct statvfs64 *statp, cred_t *cr) } /* - * smb_vop_acl_from_vsa - * - * Converts given vsecattr_t structure to a acl_t structure. - * - * The allocated memory for retuned acl_t should be freed by - * calling acl_free(). - */ -static acl_t * -smb_vop_acl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type) -{ - int aclbsize = 0; /* size of acl list in bytes */ - int dfaclbsize = 0; /* size of default acl list in bytes */ - int numacls; - acl_t *acl_info; - - ASSERT(vsecattr); - - acl_info = acl_alloc(acl_type); - if (acl_info == NULL) - return (NULL); - - acl_info->acl_flags = 0; - - switch (acl_type) { - - case ACLENT_T: - numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt; - aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t); - dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t); - - acl_info->acl_cnt = numacls; - acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize, - KM_SLEEP); - (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, - aclbsize); - (void) memcpy((char *)acl_info->acl_aclp + aclbsize, - vsecattr->vsa_dfaclentp, dfaclbsize); - - if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) - acl_info->acl_flags |= ACL_IS_TRIVIAL; - - break; - - case ACE_T: - aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); - acl_info->acl_cnt = vsecattr->vsa_aclcnt; - acl_info->acl_flags = vsecattr->vsa_aclflags; - acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP); - (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, - aclbsize); - if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) - acl_info->acl_flags |= ACL_IS_TRIVIAL; - - break; - - default: - acl_free(acl_info); - return (NULL); - } - - if (aclbsize && vsecattr->vsa_aclentp) - kmem_free(vsecattr->vsa_aclentp, aclbsize); - if (dfaclbsize && vsecattr->vsa_dfaclentp) - kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize); - - return (acl_info); -} - -/* - * smb_vop_acl_to_vsa - * - * Converts given acl_t structure to a vsecattr_t structure. - * - * IMPORTANT: - * Upon successful return the memory allocated for vsa_aclentp - * should be freed by calling kmem_free(). The size is returned - * in aclbsize. - */ -int -smb_vop_acl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize) -{ - int error = 0; - int numacls; - aclent_t *aclp; - - ASSERT(acl_info); - ASSERT(vsecattr); - ASSERT(aclbsize); - - bzero(vsecattr, sizeof (vsecattr_t)); - *aclbsize = 0; - - switch (acl_info->acl_type) { - case ACLENT_T: - numacls = acl_info->acl_cnt; - /* - * Minimum ACL size is three entries so might as well - * bail out here. Also limit request size to prevent user - * from allocating too much kernel memory. Maximum size - * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES - * for the default ACL part. - */ - if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) { - error = EINVAL; - break; - } - - vsecattr->vsa_mask = VSA_ACL; - - vsecattr->vsa_aclcnt = numacls; - *aclbsize = numacls * sizeof (aclent_t); - vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); - (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, - *aclbsize); - - /* Sort the acl list */ - ksort((caddr_t)vsecattr->vsa_aclentp, - vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls); - - /* Break into acl and default acl lists */ - for (numacls = 0, aclp = vsecattr->vsa_aclentp; - numacls < vsecattr->vsa_aclcnt; - aclp++, numacls++) { - if (aclp->a_type & ACL_DEFAULT) - break; - } - - /* Find where defaults start (if any) */ - if (numacls < vsecattr->vsa_aclcnt) { - vsecattr->vsa_mask |= VSA_DFACL; - vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls; - vsecattr->vsa_dfaclentp = aclp; - vsecattr->vsa_aclcnt = numacls; - } - - /* Adjust if they're all defaults */ - if (vsecattr->vsa_aclcnt == 0) { - vsecattr->vsa_mask &= ~VSA_ACL; - vsecattr->vsa_aclentp = NULL; - } - - /* Only directories can have defaults */ - if (vsecattr->vsa_dfaclcnt && - (acl_info->acl_flags & ACL_IS_DIR)) { - error = ENOTDIR; - } - - break; - - case ACE_T: - if (acl_info->acl_cnt < 1 || - acl_info->acl_cnt > MAX_ACL_ENTRIES) { - error = EINVAL; - break; - } - - vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; - vsecattr->vsa_aclcnt = acl_info->acl_cnt; - vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL; - *aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); - vsecattr->vsa_aclentsz = *aclbsize; - vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); - (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, - *aclbsize); - - break; - - default: - error = EINVAL; - } - - return (error); -} - -/* * smb_vop_acl_read * * Reads the ACL of the specified file into 'aclp'. @@ -1751,7 +1588,7 @@ smb_vop_acl_read(vnode_t *vp, acl_t **aclp, int flags, acl_type_t acl_type, if (error = VOP_GETSECATTR(vp, &vsecattr, flags, cr, ct)) return (error); - *aclp = smb_vop_acl_from_vsa(&vsecattr, acl_type); + *aclp = smb_fsacl_from_vsa(&vsecattr, acl_type); if (vp->v_type == VDIR) (*aclp)->acl_flags |= ACL_IS_DIR; @@ -1774,7 +1611,7 @@ smb_vop_acl_write(vnode_t *vp, acl_t *aclp, int flags, cred_t *cr, ASSERT(vp); ASSERT(aclp); - error = smb_vop_acl_to_vsa(aclp, &vsecattr, &aclbsize); + error = smb_fsacl_to_vsa(aclp, &vsecattr, &aclbsize); if (error == 0) { (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); diff --git a/usr/src/uts/common/fs/smbsrv/smb_winpipe.c b/usr/src/uts/common/fs/smbsrv/smb_winpipe.c index 361485783c..cf4c3beda0 100755 --- a/usr/src/uts/common/fs/smbsrv/smb_winpipe.c +++ b/usr/src/uts/common/fs/smbsrv/smb_winpipe.c @@ -26,8 +26,7 @@ #pragma ident "%Z%%M% %I% %E% SMI" /* - * This file contain routines to initialize the doors interfaces for - * CIFS winpipe calls. + * Winpipe door interface to MSRPC services. */ #define START_UPDOOR_SIZE 16384 @@ -46,7 +45,8 @@ #include <sys/uio.h> -static door_handle_t *smb_winpipe_dh = NULL; +static door_handle_t smb_winpipe_dh = NULL; +static int smb_winpipe_door_id = -1; static uint64_t smb_winpipe_ncall = 0; static kmutex_t smb_winpipe_mutex; static kcondvar_t smb_winpipe_cv; @@ -74,43 +74,41 @@ smb_winpipe_fini(void) mutex_destroy(&smb_winpipe_mutex); } +/* + * Open the winpipe (user space) door. If the door is already + * open, close it because the door-id has probably changed. + * Returns 0 on success. Otherwise -1 to indicate a lookup failure. + */ int -smb_winpipe_open(void) +smb_winpipe_open(int door_id) { - door_handle_t *dh; - int rc; + smb_winpipe_close(); mutex_enter(&smb_winpipe_mutex); + smb_winpipe_ncall = 0; if (smb_winpipe_dh == NULL) { - dh = kmem_zalloc(sizeof (door_handle_t), KM_SLEEP); - - rc = door_ki_open(SMB_WINPIPE_DOOR_UP_PATH, dh); - if (rc) { - kmem_free(dh, sizeof (door_handle_t)); - mutex_exit(&smb_winpipe_mutex); - cmn_err(CE_WARN, "smb_winpipe_open: rc=%d", rc); - return (-1); - } - - smb_winpipe_ncall = 0; - smb_winpipe_dh = dh; + smb_winpipe_door_id = door_id; + smb_winpipe_dh = door_ki_lookup(door_id); } mutex_exit(&smb_winpipe_mutex); - return (0); + return ((smb_winpipe_dh == NULL) ? -1 : 0); } +/* + * Close the winpipe (user space) door. + */ void smb_winpipe_close(void) { mutex_enter(&smb_winpipe_mutex); - while (smb_winpipe_ncall > 0) - cv_wait(&smb_winpipe_cv, &smb_winpipe_mutex); + if (smb_winpipe_dh != NULL) { + while (smb_winpipe_ncall > 0) + cv_wait(&smb_winpipe_cv, &smb_winpipe_mutex); - if (smb_winpipe_dh) { - kmem_free(smb_winpipe_dh, sizeof (door_handle_t)); + door_ki_rele(smb_winpipe_dh); smb_winpipe_dh = NULL; } @@ -140,7 +138,9 @@ smb_winpipe_call(struct smb_request *sr, if (smb_winpipe_dh == NULL) { mutex_exit(&smb_winpipe_mutex); - return (-1); + + if (smb_winpipe_open(smb_winpipe_door_id) != 0) + return (-1); } ++smb_winpipe_ncall; @@ -284,7 +284,7 @@ smb_winpipe_upcall(mlsvc_pipe_t *pipe_info, da.rbuf = (char *)lbuf; da.rsize = START_UPDOOR_SIZE; - if (door_ki_upcall(*smb_winpipe_dh, &da) != 0) { + if (door_ki_upcall(smb_winpipe_dh, &da) != 0) { return (-1); } /* RPC_WRITE just queues the data and returns */ diff --git a/usr/src/uts/common/fs/smbsrv/smb_write.c b/usr/src/uts/common/fs/smbsrv/smb_write.c index e6874397b4..93b9f6e758 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_write.c +++ b/usr/src/uts/common/fs/smbsrv/smb_write.c @@ -84,7 +84,7 @@ smb_com_write(struct smb_request *sr) } param->w_offset = (uint64_t)off; - param->w_vdb.uio.uio_offset = param->w_offset; + param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; if (param->w_count == 0) { rc = smb_write_truncate(sr, param); @@ -97,7 +97,7 @@ smb_com_write(struct smb_request *sr) /* NOTREACHED */ } - param->w_vdb.uio.uio_offset = param->w_offset; + param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; rc = smb_write_common(sr, param); } @@ -173,7 +173,7 @@ smb_com_write_and_close(struct smb_request *sr) /* NOTREACHED */ } - param->w_vdb.uio.uio_offset = param->w_offset; + param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; rc = smb_write_common(sr, param); } @@ -255,7 +255,7 @@ smb_com_write_and_unlock(struct smb_request *sr) } param->w_offset = (uint64_t)off; - param->w_vdb.uio.uio_offset = (off_t)param->w_offset; + param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; if ((rc = smb_write_common(sr, param)) != 0) { kmem_free(param, sizeof (smb_write_param_t)); @@ -344,7 +344,7 @@ smb_com_write_andx(struct smb_request *sr) /* NOTREACHED */ } - param->w_vdb.uio.uio_offset = param->w_offset; + param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; if (param->w_count != 0) { if ((rc = smb_write_common(sr, param)) != 0) { diff --git a/usr/src/uts/common/smbsrv/Makefile b/usr/src/uts/common/smbsrv/Makefile index 233f5d2141..7cd8b8b822 100644 --- a/usr/src/uts/common/smbsrv/Makefile +++ b/usr/src/uts/common/smbsrv/Makefile @@ -78,7 +78,6 @@ HDRS= alloc.h \ smb_ioctl.h \ smb_kproto.h \ smb_privilege.h \ - smb_secdesc.h \ smb_svc_sm.h \ smb_token.h \ smb_vops.h \ diff --git a/usr/src/uts/common/smbsrv/lsalib.h b/usr/src/uts/common/smbsrv/lsalib.h index b8566bf342..ae4076bf10 100644 --- a/usr/src/uts/common/smbsrv/lsalib.h +++ b/usr/src/uts/common/smbsrv/lsalib.h @@ -87,11 +87,9 @@ int lsa_test(char *server, char *account_name); /* * lsar_open.c */ -int lsar_open(int ipc_mode, - char *server, +int lsar_open(char *server, char *domain, char *username, - char *password, mlsvc_handle_t *domain_handle); int lsar_open_policy2(char *server, diff --git a/usr/src/uts/common/smbsrv/mlrpc.h b/usr/src/uts/common/smbsrv/mlrpc.h index fe82cf01df..59ea5536fd 100644 --- a/usr/src/uts/common/smbsrv/mlrpc.h +++ b/usr/src/uts/common/smbsrv/mlrpc.h @@ -378,7 +378,7 @@ void mlnds_destruct(struct mlndr_stream *); /* mlrpc_client.c */ int mlrpc_c_bind(struct mlrpc_client *, char *, struct mlrpc_binding **); int mlrpc_c_call(struct mlrpc_binding *, int, void *, mlrpc_heapref_t *); -int mlrpc_c_free_heap(struct mlrpc_binding *, mlrpc_heapref_t *); +void mlrpc_c_free_heap(struct mlrpc_binding *, mlrpc_heapref_t *); /* mlrpc_encdec.c */ int mlrpc_encode_decode_common(struct mlrpc_xaction *, int, unsigned, @@ -392,6 +392,9 @@ int mlrpc_encode_pdu_hdr(struct mlrpc_xaction *); void mlrpc_decode_frag_hdr(struct mlndr_stream *, mlrpcconn_common_header_t *); unsigned mlrpc_bind_ack_hdr_size(struct mlrpcconn_bind_ack_hdr *); +/* mlrpc_server.c */ +int mlrpc_generic_call_stub(struct mlrpc_xaction *); + /* mlrpc_svc.c */ struct mlrpc_stub_table *mlrpc_find_stub_in_svc(struct mlrpc_service *, int); struct mlrpc_service *mlrpc_find_service_by_name(const char *); diff --git a/usr/src/uts/common/smbsrv/mlsvc.h b/usr/src/uts/common/smbsrv/mlsvc.h index cb13cf5733..6177d9fbaf 100644 --- a/usr/src/uts/common/smbsrv/mlsvc.h +++ b/usr/src/uts/common/smbsrv/mlsvc.h @@ -138,14 +138,6 @@ typedef struct mlsvc_string { */ #define MLSVC_NO_MORE_DATA 0x1A -/* - * IPC connection types, used to indicate the type of session - * required for a subsequent series of requests. - */ -#define MLSVC_IPC_ANON 0x00 -#define MLSVC_IPC_USER 0x01 -#define MLSVC_IPC_ADMIN 0x02 - #define MLSVC_ANON_USER "IPC$" char *mlsvc_ipc_name(int ipc_type, char *username); @@ -160,11 +152,8 @@ char *mlsvc_ipc_name(int ipc_type, char *username); * the encrypted passwords. */ -int mlsvc_anonymous_logon(char *domain_controller, char *domain_name, - char **username); -int mlsvc_user_logon(char *domain_controller, char *domain_name, - char *username, char *password); -int mlsvc_admin_logon(char *domain_controller, char *domain_name); +int mlsvc_logon(char *domain_controller, char *domain_name, + char *username); int mlsvc_echo(char *server); int mlsvc_open_pipe(char *hostname, char *domain, char *username, char *pipename); @@ -172,8 +161,7 @@ int mlsvc_close_pipe(int fid); void mlsvc_nt_password_hash(char *result, char *password); int mlsvc_encrypt_nt_password(char *password, char *key, int keylen, char *out, int outmax); -DWORD mlsvc_validate_user(char *server, char *domain, char *username, - char *password); +DWORD mlsvc_join(char *server, char *domain, char *username, char *password); int mlsvc_locate_domain_controller(char *domain); /* @@ -207,14 +195,9 @@ typedef struct mlsvc_pipe { int32_t outlen; } mlsvc_pipe_t; -int mlsvc_rpc_process( - smb_pipe_t *inpipe, - smb_pipe_t **outpipe, - smb_dr_user_ctx_t *user_ctx); - -struct mlsvc_rpc_context *mlsvc_lookup_context(int fid); - -void mlsvc_rpc_release(int fid); +struct mlsvc_rpc_context *mlrpc_process(int, smb_dr_user_ctx_t *); +struct mlsvc_rpc_context *mlrpc_lookup(int fid); +void mlrpc_release(int); int mlsvc_session_native_values(int fid, int *remote_os, int *remote_lm, int *pdc_type); void mlsvc_rpc_report_status(int opnum, DWORD status); diff --git a/usr/src/uts/common/smbsrv/ndr.h b/usr/src/uts/common/smbsrv/ndr.h index 36c502d1b9..9f1700eedc 100644 --- a/usr/src/uts/common/smbsrv/ndr.h +++ b/usr/src/uts/common/smbsrv/ndr.h @@ -44,6 +44,7 @@ #include <syslog.h> #include <stdlib.h> #include <string.h> +#include <smbsrv/smb_i18n.h> #endif #ifdef __cplusplus @@ -259,6 +260,7 @@ struct mlndr_stream { unsigned char m_op; unsigned char dir; unsigned char swap; /* native/net endian swap */ + unsigned char flags; short error; short error_ref; @@ -289,6 +291,10 @@ struct mlndr_stream { #define NDR_MODE_MATCH(MLNDS, MODE) \ (NDR_M_OP_AND_DIR_TO_MODE((MLNDS)->m_op, (MLNDS)->dir) == (MODE)) +#define MLNDS_F_NONE 0x00 +#define MLNDS_F_NOTERM 0x01 /* strings are not null terminated */ +#define MLNDS_SETF(S, F) ((S)->flags |= (F)) +#define MLNDS_CLEARF(S, F) ((S)->flags &= ~(F)) #define NDR_ERR_MALLOC_FAILED -1 #define NDR_ERR_M_OP_INVALID -2 @@ -459,6 +465,10 @@ int mlndr_inner(struct ndr_reference *); int mlndr_inner_pointer(struct ndr_reference *); int mlndr_inner_reference(struct ndr_reference *); int mlndr_inner_array(struct ndr_reference *); + +size_t ndr_mbstowcs(struct mlndr_stream *, mts_wchar_t *, const char *, size_t); +int ndr_mbtowc(struct mlndr_stream *, mts_wchar_t *, const char *, size_t); + void mlnds_bswap(void *src, void *dst, size_t len); #ifdef __cplusplus diff --git a/usr/src/uts/common/smbsrv/samlib.h b/usr/src/uts/common/smbsrv/samlib.h index 19186ad8ba..efec26a922 100644 --- a/usr/src/uts/common/smbsrv/samlib.h +++ b/usr/src/uts/common/smbsrv/samlib.h @@ -49,7 +49,7 @@ extern "C" { * samlib.c */ int sam_lookup_user_info(char *server, char *domain_name, char *username, - char *password, smb_userinfo_t *user_info); + smb_userinfo_t *user_info); DWORD sam_create_trust_account(char *server, char *domain, smb_auth_info_t *auth); @@ -65,12 +65,13 @@ DWORD sam_lookup_name(char *server, char *domain_name, char *account_name, DWORD *rid_ret); DWORD sam_get_local_domains(char *server, char *domain_name); +DWORD sam_check_user(char *server, char *domain_name, char *account_name); /* * samr_open.c */ -int samr_open(int ipc_mode, char *server, char *domain, char *username, - char *password, DWORD access_mask, mlsvc_handle_t *samr_handle); +int samr_open(char *server, char *domain, char *username, + DWORD access_mask, mlsvc_handle_t *samr_handle); int samr_connect(char *server, char *domain, char *username, DWORD access_mask, mlsvc_handle_t *samr_handle); @@ -80,7 +81,7 @@ int samr_close_handle(mlsvc_handle_t *handle); DWORD samr_open_domain(mlsvc_handle_t *samr_handle, DWORD access_mask, struct samr_sid *sid, mlsvc_handle_t *domain_handle); -int samr_open_user(mlsvc_handle_t *domain_handle, DWORD access_mask, +DWORD samr_open_user(mlsvc_handle_t *domain_handle, DWORD access_mask, DWORD rid, mlsvc_handle_t *user_handle); DWORD samr_delete_user(mlsvc_handle_t *user_handle); diff --git a/usr/src/uts/common/smbsrv/smb_fsops.h b/usr/src/uts/common/smbsrv/smb_fsops.h index 56a15aa2d0..afed8b6637 100644 --- a/usr/src/uts/common/smbsrv/smb_fsops.h +++ b/usr/src/uts/common/smbsrv/smb_fsops.h @@ -35,6 +35,7 @@ #include <smbsrv/smb_i18n.h> #include <smbsrv/smbinfo.h> #include <smbsrv/smb_vops.h> +#include <smbsrv/smbvar.h> #ifdef __cplusplus extern "C" { @@ -111,21 +112,12 @@ int smb_fsop_stream_readdir(struct smb_request *sr, cred_t *cr, smb_node_t *fnode, uint32_t *cookiep, struct fs_stream_info *stream_info, smb_node_t **ret_snode, smb_attr_t *ret_attr); -void smb_fsop_aclfree(acl_t *acl); -acl_t *smb_fsop_aclalloc(int acenum, int flags); -int smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode, - smb_fssd_t *fssd); -int smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode, - smb_fssd_t *fs_sd); -acl_type_t smb_fsop_acltype(smb_node_t *snode); - -void smb_fsop_sdinit(smb_fssd_t *fs_sd, uint32_t secinfo, uint32_t sd_flags); -void smb_fsop_sdterm(smb_fssd_t *fssd); -int smb_fsop_sdread(smb_request_t *sr, cred_t *cr, smb_node_t *snode, - smb_fssd_t *fssd); -int smb_fsop_sdwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode, - smb_fssd_t *fs_sd, int overwrite); - +int smb_fsop_aclread(smb_request_t *, cred_t *, smb_node_t *, smb_fssd_t *); +int smb_fsop_aclwrite(smb_request_t *, cred_t *, smb_node_t *, smb_fssd_t *); +acl_type_t smb_fsop_acltype(smb_node_t *); +int smb_fsop_sdread(smb_request_t *, cred_t *, smb_node_t *, smb_fssd_t *); +int smb_fsop_sdwrite(smb_request_t *, cred_t *, smb_node_t *, smb_fssd_t *, + int); void smb_get_caller_context(smb_request_t *sr, caller_context_t *ct); diff --git a/usr/src/uts/common/smbsrv/smb_ioctl.h b/usr/src/uts/common/smbsrv/smb_ioctl.h index 6b6ad051fb..2809e27fd0 100755 --- a/usr/src/uts/common/smbsrv/smb_ioctl.h +++ b/usr/src/uts/common/smbsrv/smb_ioctl.h @@ -36,7 +36,8 @@ extern "C" { #define SMB_IOC_BASE (('S' << 16) | ('B' << 8)) #define SMB_IOC_GMTOFF _IOW(SMB_IOC_BASE, 1, int) -#define SMB_IOC_CONFIG_REFRESH _IOW(SMB_IOC_BASE, 2, int) +#define SMB_IOC_CONFIG _IOW(SMB_IOC_BASE, 2, int) +#define SMB_IOC_WINPIPE _IOW(SMB_IOC_BASE, 3, int) #ifdef __cplusplus } diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h index 26ac73055e..0b9442bed1 100644 --- a/usr/src/uts/common/smbsrv/smb_kproto.h +++ b/usr/src/uts/common/smbsrv/smb_kproto.h @@ -44,6 +44,7 @@ extern "C" { #include <smbsrv/smb_vops.h> #include <smbsrv/smb_xdr.h> #include <smbsrv/smb_token.h> +#include <smbsrv/smbvar.h> /* * Definitions that should be elsewhere... @@ -203,6 +204,8 @@ int smb_component_match(struct smb_request *sr, ino64_t fileid, int smb_lock_range_access(struct smb_request *, struct smb_node *, uint64_t, uint64_t, uint32_t desired_access); +uint32_t smb_decode_sd(struct smb_xa *, smb_sd_t *); + /* * Socket functions */ @@ -481,7 +484,7 @@ int smb_handle_write_raw(smb_session_t *session, smb_request_t *sr); void smb_winpipe_init(void); void smb_winpipe_fini(void); -int smb_winpipe_open(void); +int smb_winpipe_open(int door_id); void smb_winpipe_close(void); int smb_winpipe_call(smb_request_t *, mlsvc_pipe_t *, mlsvc_stream_t *, uint16_t, uint32_t *); @@ -595,6 +598,37 @@ void smb_audit_buf_node_destroy(smb_node_t *node); /* 100's of ns between 1/1/1970 and 1/1/1601 */ #define NT_TIME_BIAS (134774LL * 24LL * 60LL * 60LL * 10000000LL) +void smb_sd_init(smb_sd_t *, uint8_t); +void smb_sd_term(smb_sd_t *); +uint32_t smb_sd_get_secinfo(smb_sd_t *); +uint32_t smb_sd_len(smb_sd_t *, uint32_t); +uint32_t smb_sd_tofs(smb_sd_t *, smb_fssd_t *); +uint32_t smb_sd_read(smb_request_t *, smb_sd_t *, uint32_t); +uint32_t smb_sd_write(smb_request_t *, smb_sd_t *, uint32_t); + +void smb_fssd_init(smb_fssd_t *, uint32_t, uint32_t); +void smb_fssd_term(smb_fssd_t *); + +void smb_acl_sort(smb_acl_t *); +void smb_acl_free(smb_acl_t *); +smb_acl_t *smb_acl_alloc(uint8_t, uint16_t, uint16_t); +smb_acl_t *smb_acl_from_zfs(acl_t *, uid_t, gid_t); +uint32_t smb_acl_to_zfs(smb_acl_t *, uint32_t, int, acl_t **); +uint16_t smb_acl_len(smb_acl_t *); +boolean_t smb_acl_isvalid(smb_acl_t *, int); + +void smb_fsacl_free(acl_t *); +acl_t *smb_fsacl_alloc(int, int); +acl_t *smb_fsacl_inherit(acl_t *, int, int, uid_t); +acl_t *smb_fsacl_merge(acl_t *, acl_t *); +void smb_fsacl_split(acl_t *, acl_t **, acl_t **, int); +acl_t *smb_fsacl_from_vsa(vsecattr_t *, acl_type_t); +int smb_fsacl_to_vsa(acl_t *, vsecattr_t *, int *); + +boolean_t smb_ace_is_generic(int); +boolean_t smb_ace_is_access(int); +boolean_t smb_ace_is_audit(int); + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/smbsrv/smb_vops.h b/usr/src/uts/common/smbsrv/smb_vops.h index 8bc18b73ca..3b09c99b63 100644 --- a/usr/src/uts/common/smbsrv/smb_vops.h +++ b/usr/src/uts/common/smbsrv/smb_vops.h @@ -329,7 +329,8 @@ extern int smb_vop_write(vnode_t *vp, uio_t *uiop, unsigned int *flag, extern int smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, int flags, cred_t *cr, caller_context_t *ct); extern int smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, - smb_attr_t *set_attr, int flags, cred_t *cr, caller_context_t *ct); + smb_attr_t *set_attr, int flags, cred_t *cr, boolean_t no_xvattr, + caller_context_t *ct); extern int smb_vop_access(vnode_t *vp, int mode, int flags, vnode_t *dir_vp, cred_t *cr); extern void smb_vop_eaccess(vnode_t *vp, int *mode, int flags, vnode_t *dir_vp, diff --git a/usr/src/uts/common/smbsrv/smb_winpipe.h b/usr/src/uts/common/smbsrv/smb_winpipe.h index 93a176c101..944beb095a 100755 --- a/usr/src/uts/common/smbsrv/smb_winpipe.h +++ b/usr/src/uts/common/smbsrv/smb_winpipe.h @@ -48,7 +48,6 @@ extern "C" { #define SMB_MAX_PIPENAMELEN 32 #define SMB_WINPIPE_DOOR_DOWN_PATH "/var/run/winpipe_doordown" -#define SMB_WINPIPE_DOOR_UP_PATH "/var/run/winpipe_doorup" #define SMB_DOWNCALLINFO_MAGIC 0x19121969 #define SMB_MLSVC_DOOR_VERSION 1 diff --git a/usr/src/uts/common/smbsrv/smbinfo.h b/usr/src/uts/common/smbsrv/smbinfo.h index d6a7a03a9a..2426b54b61 100644 --- a/usr/src/uts/common/smbsrv/smbinfo.h +++ b/usr/src/uts/common/smbsrv/smbinfo.h @@ -173,6 +173,7 @@ int smbnative_pdc_value(char *native_lm); #define SMBD_DOOR_PARAM_GET 2 #define SMBD_DOOR_PARAM_SET 3 #define SMBD_DOOR_NETBIOS_RECONFIG 4 +#define SMBD_DOOR_ADS_DOMAIN_CHANGED 5 #ifdef __cplusplus } diff --git a/usr/src/uts/common/smbsrv/smbvar.h b/usr/src/uts/common/smbsrv/smbvar.h index 30e41c714a..edcfbe7187 100644 --- a/usr/src/uts/common/smbsrv/smbvar.h +++ b/usr/src/uts/common/smbsrv/smbvar.h @@ -49,13 +49,14 @@ extern "C" { #include <smbsrv/lmshare.h> #include <smbsrv/smbinfo.h> #include <smbsrv/mbuf.h> -#include <smbsrv/smb_secdesc.h> + #include <smbsrv/smb_vops.h> #include <smbsrv/smb_fsd.h> #include <smbsrv/mlsvc.h> typedef struct smb_session smb_session_t; typedef struct smb_request smb_request_t; +typedef struct smb_sd smb_sd_t; #include <smbsrv/smb_svc_sm.h> @@ -401,7 +402,7 @@ typedef struct smb_node { volatile int waiting_event; /* # of clients requesting FCN */ smb_attr_t attr; unsigned int what; - off_t n_size; + u_offset_t n_size; smb_oplock_t n_oplock; struct smb_node *dir_snode; /* Directory of node */ struct smb_node *unnamed_stream_node; /* set in stream nodes */ @@ -756,6 +757,8 @@ typedef struct smb_tree { #define SMB_TREE_FLAG_ACLONCREATE 0x0004 #define SMB_TREE_FLAG_ACEMASKONACCESS 0x0008 #define SMB_TREE_FLAG_IGNORE_CASE 0x0010 +#define SMB_TREE_FLAG_NFS_MOUNTED 0x0020 +#define SMB_TREE_FLAG_UFS 0x0040 #define SMB_TREE_CLOSED(tree) ((tree)->t_flags & SMB_TREE_FLAG_CLOSE) /* @@ -1183,7 +1186,7 @@ struct smb_request { uint32_t action_taken; uint64_t fileid; /* This is only set by NTTransactCreate */ - smb_sdbuf_t *sd_buf; + smb_sd_t *sd; } open; struct { @@ -1395,6 +1398,317 @@ typedef struct smb_dispatch_table { kstat_named_t sdt_dispatch_stats; /* invocations */ } smb_dispatch_table_t; +/* + * Discretionary Access Control List (DACL) + * + * A Discretionary Access Control List (DACL), often abbreviated to + * ACL, is a list of access controls which either allow or deny access + * for users or groups to a resource. There is a list header followed + * by a list of access control entries (ACE). Each ACE specifies the + * access allowed or denied to a single user or group (identified by + * a SID). + * + * There is another access control list object called a System Access + * Control List (SACL), which is used to control auditing, but no + * support is provideed for SACLs at this time. + * + * ACL header format: + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-------------------------------+---------------+---------------+ + * | AclSize | Sbz1 | AclRevision | + * +-------------------------------+---------------+---------------+ + * | Sbz2 | AceCount | + * +-------------------------------+-------------------------------+ + * + * AclRevision specifies the revision level of the ACL. This value should + * be ACL_REVISION, unless the ACL contains an object-specific ACE, in which + * case this value must be ACL_REVISION_DS. All ACEs in an ACL must be at the + * same revision level. + * + * ACE header format: + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +---------------+-------+-------+---------------+---------------+ + * | AceSize | AceFlags | AceType | + * +---------------+-------+-------+---------------+---------------+ + * + * Access mask format: + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +---------------+---------------+-------------------------------+ + * |G|G|G|G|Res'd|A| StandardRights| SpecificRights | + * |R|W|E|A| |S| | | + * +-+-------------+---------------+-------------------------------+ + * + * typedef struct ACCESS_MASK { + * WORD SpecificRights; + * BYTE StandardRights; + * BYTE AccessSystemAcl : 1; + * BYTE Reserved : 3; + * BYTE GenericAll : 1; + * BYTE GenericExecute : 1; + * BYTE GenericWrite : 1; + * BYTE GenericRead : 1; + * } ACCESS_MASK; + * + */ + +#define ACL_REVISION1 1 +#define ACL_REVISION2 2 +#define MIN_ACL_REVISION2 ACL_REVISION2 +#define ACL_REVISION3 3 +#define ACL_REVISION4 4 +#define MAX_ACL_REVISION ACL_REVISION4 + +/* + * Current ACE and ACL revision Levels + */ +#define ACE_REVISION 1 +#define ACL_REVISION ACL_REVISION2 +#define ACL_REVISION_DS ACL_REVISION4 + + +#define ACCESS_ALLOWED_ACE_TYPE 0 +#define ACCESS_DENIED_ACE_TYPE 1 +#define SYSTEM_AUDIT_ACE_TYPE 2 +#define SYSTEM_ALARM_ACE_TYPE 3 + +/* + * se_flags + * ---------- + * Specifies a set of ACE type-specific control flags. This member can be a + * combination of the following values. + * + * CONTAINER_INHERIT_ACE: Child objects that are containers, such as + * directories, inherit the ACE as an effective ACE. The inherited + * ACE is inheritable unless the NO_PROPAGATE_INHERIT_ACE bit flag + * is also set. + * + * INHERIT_ONLY_ACE: Indicates an inherit-only ACE which does not control + * access to the object to which it is attached. + * If this flag is not set, + * the ACE is an effective ACE which controls access to the object + * to which it is attached. + * Both effective and inherit-only ACEs can be inherited + * depending on the state of the other inheritance flags. + * + * INHERITED_ACE: Windows 2000/XP: Indicates that the ACE was inherited. + * The system sets this bit when it propagates an + * inherited ACE to a child object. + * + * NO_PROPAGATE_INHERIT_ACE: If the ACE is inherited by a child object, the + * system clears the OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE + * flags in the inherited ACE. + * This prevents the ACE from being inherited by + * subsequent generations of objects. + * + * OBJECT_INHERIT_ACE: Noncontainer child objects inherit the ACE as an + * effective ACE. For child objects that are containers, + * the ACE is inherited as an inherit-only ACE unless the + * NO_PROPAGATE_INHERIT_ACE bit flag is also set. + */ +#define OBJECT_INHERIT_ACE 0x01 +#define CONTAINER_INHERIT_ACE 0x02 +#define NO_PROPOGATE_INHERIT_ACE 0x04 +#define INHERIT_ONLY_ACE 0x08 +#define INHERITED_ACE 0x10 +#define INHERIT_MASK_ACE 0x1F + + +/* + * These flags are only used in system audit or alarm ACEs to + * indicate when an audit message should be generated, i.e. + * on successful access or on unsuccessful access. + */ +#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40 +#define FAILED_ACCESS_ACE_FLAG 0x80 + +/* + * se_bsize is the size, in bytes, of ACE as it appears on the wire. + * se_sln is used to sort the ACL when it's required. + */ +typedef struct smb_acehdr { + uint8_t se_type; + uint8_t se_flags; + uint16_t se_bsize; +} smb_acehdr_t; + +typedef struct smb_ace { + smb_acehdr_t se_hdr; + uint32_t se_mask; + list_node_t se_sln; + nt_sid_t *se_sid; +} smb_ace_t; + +/* + * sl_bsize is the size of ACL in bytes as it appears on the wire. + */ +typedef struct smb_acl { + uint8_t sl_revision; + uint16_t sl_bsize; + uint16_t sl_acecnt; + smb_ace_t *sl_aces; + list_t sl_sorted; +} smb_acl_t; + +/* + * ACE/ACL header size, in byte, as it appears on the wire + */ +#define SMB_ACE_HDRSIZE 4 +#define SMB_ACL_HDRSIZE 8 + +/* + * Security Descriptor (SD) + * + * Security descriptors provide protection for objects, for example + * files and directories. It identifies the owner and primary group + * (SIDs) and contains an access control list. When a user tries to + * access an object his SID is compared to the permissions in the + * DACL to determine if access should be allowed or denied. Note that + * this is a simplification because there are other factors, such as + * default behavior and privileges to be taken into account (see also + * access tokens). + * + * The boolean flags have the following meanings when set: + * + * SE_OWNER_DEFAULTED indicates that the SID pointed to by the Owner + * field was provided by a defaulting mechanism rather than explicitly + * provided by the original provider of the security descriptor. This + * may affect the treatment of the SID with respect to inheritance of + * an owner. + * + * SE_GROUP_DEFAULTED indicates that the SID in the Group field was + * provided by a defaulting mechanism rather than explicitly provided + * by the original provider of the security descriptor. This may + * affect the treatment of the SID with respect to inheritance of a + * primary group. + * + * SE_DACL_PRESENT indicates that the security descriptor contains a + * discretionary ACL. If this flag is set and the Dacl field of the + * SECURITY_DESCRIPTOR is null, then a null ACL is explicitly being + * specified. + * + * SE_DACL_DEFAULTED indicates that the ACL pointed to by the Dacl + * field was provided by a defaulting mechanism rather than explicitly + * provided by the original provider of the security descriptor. This + * may affect the treatment of the ACL with respect to inheritance of + * an ACL. This flag is ignored if the DaclPresent flag is not set. + * + * SE_SACL_PRESENT indicates that the security descriptor contains a + * system ACL pointed to by the Sacl field. If this flag is set and + * the Sacl field of the SECURITY_DESCRIPTOR is null, then an empty + * (but present) ACL is being specified. + * + * SE_SACL_DEFAULTED indicates that the ACL pointed to by the Sacl + * field was provided by a defaulting mechanism rather than explicitly + * provided by the original provider of the security descriptor. This + * may affect the treatment of the ACL with respect to inheritance of + * an ACL. This flag is ignored if the SaclPresent flag is not set. + * + * SE_DACL_PROTECTED Prevents ACEs set on the DACL of the parent container + * (and any objects above the parent container in the directory hierarchy) + * from being applied to the object's DACL. + * + * SE_SACL_PROTECTED Prevents ACEs set on the SACL of the parent container + * (and any objects above the parent container in the directory hierarchy) + * from being applied to the object's SACL. + * + * Note that the SE_DACL_PRESENT flag needs to be present to set + * SE_DACL_PROTECTED and SE_SACL_PRESENT needs to be present to set + * SE_SACL_PROTECTED. + * + * SE_SELF_RELATIVE indicates that the security descriptor is in self- + * relative form. In this form, all fields of the security descriptor + * are contiguous in memory and all pointer fields are expressed as + * offsets from the beginning of the security descriptor. + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +---------------------------------------------------------------+ + * | Control |Reserved1 (SBZ)| Revision | + * +---------------------------------------------------------------+ + * | Owner | + * +---------------------------------------------------------------+ + * | Group | + * +---------------------------------------------------------------+ + * | Sacl | + * +---------------------------------------------------------------+ + * | Dacl | + * +---------------------------------------------------------------+ + * + */ + +#define SMB_OWNER_SECINFO 0x0001 +#define SMB_GROUP_SECINFO 0x0002 +#define SMB_DACL_SECINFO 0x0004 +#define SMB_SACL_SECINFO 0x0008 +#define SMB_ALL_SECINFO 0x000F +#define SMB_ACL_SECINFO (SMB_DACL_SECINFO | SMB_SACL_SECINFO) + +#define SECURITY_DESCRIPTOR_REVISION 1 + + +#define SE_OWNER_DEFAULTED 0x0001 +#define SE_GROUP_DEFAULTED 0x0002 +#define SE_DACL_PRESENT 0x0004 +#define SE_DACL_DEFAULTED 0x0008 +#define SE_SACL_PRESENT 0x0010 +#define SE_SACL_DEFAULTED 0x0020 +#define SE_DACL_AUTO_INHERIT_REQ 0x0100 +#define SE_SACL_AUTO_INHERIT_REQ 0x0200 +#define SE_DACL_AUTO_INHERITED 0x0400 +#define SE_SACL_AUTO_INHERITED 0x0800 +#define SE_DACL_PROTECTED 0x1000 +#define SE_SACL_PROTECTED 0x2000 +#define SE_SELF_RELATIVE 0x8000 + +#define SE_DACL_INHERITANCE_MASK 0x1500 +#define SE_SACL_INHERITANCE_MASK 0x2A00 + +/* + * Security descriptor structures: + * + * smb_sd_t SD in SMB pointer form + * smb_fssd_t SD in filesystem form + * + * Filesystems (e.g. ZFS/UFS) don't have something equivalent + * to SD. The items comprising a SMB SD are kept separately in + * filesystem. smb_fssd_t is introduced as a helper to provide + * the required abstraction for CIFS code. + */ + +struct smb_sd { + uint8_t sd_revision; + uint16_t sd_control; + nt_sid_t *sd_owner; /* SID file owner */ + nt_sid_t *sd_group; /* SID group (for POSIX) */ + smb_acl_t *sd_sacl; /* ACL System (audits) */ + smb_acl_t *sd_dacl; /* ACL Discretionary (perm) */ +}; + +/* + * SD header size as it appears on the wire + */ +#define SMB_SD_HDRSIZE 20 + +/* + * values for smb_fssd.sd_flags + */ +#define SMB_FSSD_FLAGS_DIR 0x01 + +typedef struct smb_fssd { + uint32_t sd_secinfo; + uint32_t sd_flags; + uid_t sd_uid; + gid_t sd_gid; + acl_t *sd_zdacl; + acl_t *sd_zsacl; +} smb_fssd_t; + #ifdef __cplusplus } #endif |