diff options
author | jb150015 <none@none> | 2008-06-02 13:50:26 -0700 |
---|---|---|
committer | jb150015 <none@none> | 2008-06-02 13:50:26 -0700 |
commit | 3ad684d66b78e06edd37e2c4fd3b3949f095194b (patch) | |
tree | c8a46bd6352a4d612c208b2da5baa3d9817a28e4 /usr/src | |
parent | 25c3d9a2161e0ea7e7d2783b5f991fd797282b63 (diff) | |
download | illumos-gate-3ad684d66b78e06edd37e2c4fd3b3949f095194b.tar.gz |
6686467 Panic in smb_trans_net_share_enum() while browsing over 200 shares from Mac
6693094 zfs_frlock panic while running stress tests.
6696744 smbd dumped core while joining Windows 2K domain
6698934 ofile state needs to be checked before doing share (i.e. open/deny mode) checks
6705282 configuration changes are not propagated to kernel
6708562 SID filtering breaks trusted domain users
--HG--
rename : usr/src/uts/common/fs/smbsrv/smb_share_kdoor_client.c => usr/src/uts/common/fs/smbsrv/smb_kshare.c
Diffstat (limited to 'usr/src')
35 files changed, 1186 insertions, 2028 deletions
diff --git a/usr/src/cmd/smbsrv/smbd/smbd.h b/usr/src/cmd/smbsrv/smbd/smbd.h index 10b5b083f5..b60445cd8f 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd.h +++ b/usr/src/cmd/smbsrv/smbd/smbd.h @@ -40,13 +40,9 @@ extern "C" { 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); -extern int smb_doorsrv_start(void); -extern void smb_doorsrv_stop(void); -extern int smb_ntgroup_doorsrv_start(void); -extern void smb_ntgroup_doorsrv_stop(void); +extern int smb_share_dsrv_start(void); +extern void smb_share_dsrv_stop(void); extern int smb_netlogon_init(void); extern void smb_set_netlogon_cred(void); @@ -56,6 +52,7 @@ extern void smbd_user_nonauth_logon(uint32_t); extern void smbd_user_auth_logoff(uint32_t); extern uint32_t smbd_join(smb_joininfo_t *); + typedef struct smbd { const char *s_version; /* smbd version string */ const char *s_pname; /* basename to use for messages */ diff --git a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c index d1cfec3b63..4571324877 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c @@ -167,6 +167,11 @@ smb_door_srv_func(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, int err; smb_dr_op_t smbop; + if ((cookie != SMB_DR_SVC_COOKIE) || (argp == NULL) || + (arg_size < sizeof (uint32_t))) { + (void) door_return(NULL, 0, NULL, 0); + } + if ((opcode = smb_dr_get_opcode(argp, arg_size)) < 0) { tmpbuf = smb_door_srv_err_hdlr(SMB_DR_OP_ERR_DECODE, &rbufsize); diff --git a/usr/src/cmd/smbsrv/smbd/smbd_logon.c b/usr/src/cmd/smbsrv/smbd/smbd_logon.c index e0560e7598..0b88309dbf 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_logon.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_logon.c @@ -158,7 +158,7 @@ smbd_user_auth_logon(netr_client_t *clnt) entry->sa_username = strdup(clnt->username); entry->sa_domain = strdup(clnt->domain); - (void) smb_autohome_add(entry->sa_username); + smb_autohome_add(entry->sa_username); smbd_audit_link(entry); token->tkn_audit_sid = entry->sa_audit_sid; } @@ -205,7 +205,7 @@ smbd_user_auth_logoff(uint32_t audit_sid) if ((entry = smbd_audit_unlink(audit_sid)) == NULL) return; - (void) smb_autohome_remove(entry->sa_username); + smb_autohome_remove(entry->sa_username); ah = entry->sa_handle; diff --git a/usr/src/cmd/smbsrv/smbd/smbd_main.c b/usr/src/cmd/smbsrv/smbd/smbd_main.c index 92284e18c3..8811a24f6f 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_main.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c @@ -407,7 +407,7 @@ smbd_service_init(void) (void) lsa_query_primary_domain_info(); } - smbd.s_door_lmshr = smb_lmshrd_srv_start(); + smbd.s_door_lmshr = smb_share_dsrv_start(); if (smbd.s_door_lmshr < 0) { smbd_report("share initialization failed"); } @@ -457,7 +457,7 @@ smbd_service_fini(void) smbd_refresh_fini(); smbd_kernel_unbind(); smb_door_srv_stop(); - smb_lmshrd_srv_stop(); + smb_share_dsrv_stop(); lmshare_stop(); smb_nicmon_stop(); smb_idmap_stop(); @@ -529,6 +529,9 @@ smbd_refresh_monitor(void *arg) char fqdn[MAXHOSTNAMELEN]; int rc = 0; + bzero(&smb_io, sizeof (smb_io)); + smb_io.sio_version = SMB_IOC_VERSION; + (void) pthread_mutex_lock(&refresh_mutex); while (pthread_cond_wait(&refresh_cond, &refresh_mutex) == 0) { /* diff --git a/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c index 0b77424731..9e20d3bef6 100755 --- a/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c @@ -166,6 +166,11 @@ smb_winpipe_request(void *cookie, char *argp, size_t arg_size, char lfp[START_OUTDOOR_SIZE]; boolean_t more_data = B_FALSE; + if ((cookie != &smb_winpipe_cookie) || (argp == NULL) || + (arg_size < SMB_WINPIPE_MIN_REQ_SIZE)) { + (void) door_return(NULL, 0, NULL, 0); + } + bufp = argp; bcopy(bufp, &mdhin.md_tid, sizeof (uint64_t)); bytes_off = sizeof (uint64_t); @@ -338,5 +343,5 @@ smb_winpipe_request(void *cookie, char *argp, size_t arg_size, zero_exit: smb_user_ctx_free(user_ctx); - (void) door_return(0, 0, NULL, 0); + (void) door_return(NULL, 0, NULL, 0); } diff --git a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c index 60a19b4f05..31ef703e9a 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c @@ -37,6 +37,7 @@ #include <errno.h> #include <syslog.h> #include <string.h> +#include <strings.h> #include <pthread.h> #include <smbsrv/libsmb.h> @@ -45,155 +46,123 @@ #include <smbsrv/lmshare_door.h> #include <smbsrv/smbinfo.h> -static smb_kmod_cfg_t smb_kcfg; +static int smb_share_dsrv_fd = -1; +static pthread_mutex_t smb_share_dsrv_mtx = PTHREAD_MUTEX_INITIALIZER; -static int smb_lmshrd_fildes = -1; -static pthread_mutex_t smb_lmshrd_srv_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* forward declaration */ -static void smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, - door_desc_t *dp, uint_t n_desc); -static int smb_lmshrd_srv_check(int opcode, char *sharename); +static void smb_share_dsrv_dispatch(void *, char *, size_t, door_desc_t *, + uint_t); +static int smb_share_dsrv_check(int, char *); +static int smb_share_dsrv_enum(smb_enumshare_info_t *esi); /* - * smb_lmshrd_srv_start + * smb_share_dsrv_start * * Start the LanMan share door service. * Returns 0 on success. Otherwise, -1. */ int -smb_lmshrd_srv_start(void) +smb_share_dsrv_start(void) { int newfd; - (void) pthread_mutex_lock(&smb_lmshrd_srv_mutex); + (void) pthread_mutex_lock(&smb_share_dsrv_mtx); - if (smb_lmshrd_fildes != -1) { - syslog(LOG_ERR, "smb_lmshrd_srv_start: duplicate"); - (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); - return (smb_lmshrd_fildes); + if (smb_share_dsrv_fd != -1) { + syslog(LOG_ERR, "smb_share_dsrv_start: duplicate"); + (void) pthread_mutex_unlock(&smb_share_dsrv_mtx); + return (smb_share_dsrv_fd); } - if ((smb_lmshrd_fildes = door_create(smb_lmshrd_srv_door, + if ((smb_share_dsrv_fd = door_create(smb_share_dsrv_dispatch, LMSHR_DOOR_COOKIE, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) { - syslog(LOG_ERR, "smb_lmshrd_srv_start: door_create: %s", + syslog(LOG_ERR, "smb_share_dsrv_start: door_create: %s", strerror(errno)); - (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); + (void) pthread_mutex_unlock(&smb_share_dsrv_mtx); return (-1); } (void) unlink(LMSHR_DOOR_NAME); if ((newfd = creat(LMSHR_DOOR_NAME, 0644)) < 0) { - syslog(LOG_ERR, "smb_lmshrd_srv_start: open: %s", + syslog(LOG_ERR, "smb_share_dsrv_start: open: %s", strerror(errno)); - (void) door_revoke(smb_lmshrd_fildes); - smb_lmshrd_fildes = -1; - (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); + (void) door_revoke(smb_share_dsrv_fd); + smb_share_dsrv_fd = -1; + (void) pthread_mutex_unlock(&smb_share_dsrv_mtx); return (-1); } (void) close(newfd); (void) fdetach(LMSHR_DOOR_NAME); - if (fattach(smb_lmshrd_fildes, LMSHR_DOOR_NAME) < 0) { - syslog(LOG_ERR, "smb_lmshrd_srv_start: fattach: %s", + if (fattach(smb_share_dsrv_fd, LMSHR_DOOR_NAME) < 0) { + syslog(LOG_ERR, "smb_share_dsrv_start: fattach: %s", strerror(errno)); - (void) door_revoke(smb_lmshrd_fildes); - smb_lmshrd_fildes = -1; - (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); + (void) door_revoke(smb_share_dsrv_fd); + smb_share_dsrv_fd = -1; + (void) pthread_mutex_unlock(&smb_share_dsrv_mtx); return (-1); } - (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); - return (smb_lmshrd_fildes); + (void) pthread_mutex_unlock(&smb_share_dsrv_mtx); + return (smb_share_dsrv_fd); } - /* - * smb_lmshrd_srv_stop + * smb_share_dsrv_stop * * Stop the LanMan share door service. */ void -smb_lmshrd_srv_stop(void) +smb_share_dsrv_stop(void) { - (void) pthread_mutex_lock(&smb_lmshrd_srv_mutex); + (void) pthread_mutex_lock(&smb_share_dsrv_mtx); - if (smb_lmshrd_fildes != -1) { + if (smb_share_dsrv_fd != -1) { (void) fdetach(LMSHR_DOOR_NAME); - (void) door_revoke(smb_lmshrd_fildes); - smb_lmshrd_fildes = -1; + (void) door_revoke(smb_share_dsrv_fd); + smb_share_dsrv_fd = -1; } - (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); + (void) pthread_mutex_unlock(&smb_share_dsrv_mtx); } - /* - * smb_lmshrd_srv_door + * smb_share_dsrv_dispatch * * This function with which the LMSHARE door is associated * will invoke the appropriate CIFS share management function * based on the request type of the door call. */ /*ARGSUSED*/ -void -smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp, +static void +smb_share_dsrv_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp, uint_t n_desc) { DWORD rc; - int req_type, mode, rc2; + int req_type, rc2; char buf[LMSHR_DOOR_SIZE]; unsigned int used; - smb_dr_ctx_t *dec_ctx = smb_dr_decode_start(ptr, size); - smb_dr_ctx_t *enc_ctx = smb_dr_encode_start(buf, sizeof (buf)); + smb_dr_ctx_t *dec_ctx; + smb_dr_ctx_t *enc_ctx; unsigned int dec_status; unsigned int enc_status; char *sharename, *sharename2; lmshare_info_t lmshr_info; - lmshare_info_t *lmshr_infop; - lmshare_iterator_t *lmshr_iter; - int offset; lmshare_list_t lmshr_list; + smb_enumshare_info_t esi; + int offset; + + if ((cookie != LMSHR_DOOR_COOKIE) || (ptr == NULL) || + (size < sizeof (uint32_t))) { + (void) door_return(NULL, 0, NULL, 0); + } + dec_ctx = smb_dr_decode_start(ptr, size); + enc_ctx = smb_dr_encode_start(buf, sizeof (buf)); req_type = smb_dr_get_uint32(dec_ctx); switch (req_type) { - case LMSHR_DOOR_OPEN_ITERATOR: - mode = smb_dr_get_int32(dec_ctx); - - if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) - goto decode_error; - - lmshr_iter = lmshare_open_iterator(mode); - smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); - smb_dr_put_lmshr_iterator(enc_ctx, - (uint64_t)(uintptr_t)lmshr_iter); - - break; - - case LMSHR_DOOR_CLOSE_ITERATOR: - lmshr_iter = (lmshare_iterator_t *)(uintptr_t) - smb_dr_get_lmshr_iterator(dec_ctx); - if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) - goto decode_error; - - lmshare_close_iterator(lmshr_iter); - smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); - break; - - case LMSHR_DOOR_ITERATE: - lmshr_iter = (lmshare_iterator_t *)(uintptr_t) - smb_dr_get_lmshr_iterator(dec_ctx); - if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) - goto decode_error; - - lmshr_infop = lmshare_iterate(lmshr_iter); - smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); - smb_dr_put_lmshare(enc_ctx, lmshr_infop); - break; - case LMSHR_DOOR_NUM_SHARES: if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) goto decode_error; @@ -281,7 +250,7 @@ smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp, goto decode_error; } - rc2 = smb_lmshrd_srv_check(req_type, sharename); + rc2 = smb_share_dsrv_check(req_type, sharename); smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); smb_dr_put_uint32(enc_ctx, rc2); smb_dr_free_string(sharename); @@ -292,19 +261,33 @@ smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp, if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) goto decode_error; - rc = lmshare_list(offset, &lmshr_list); + lmshare_list(offset, &lmshr_list); smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); - smb_dr_put_uint32(enc_ctx, rc); smb_dr_put_lmshr_list(enc_ctx, &lmshr_list); break; - case SMB_GET_KCONFIG: - if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) + case LMSHR_DOOR_ENUM: + esi.es_bufsize = smb_dr_get_ushort(dec_ctx); + esi.es_username = smb_dr_get_string(dec_ctx); + if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) { + smb_dr_free_string(esi.es_username); goto decode_error; + } + + rc = smb_share_dsrv_enum(&esi); + + smb_dr_free_string(esi.es_username); - smb_load_kconfig(&smb_kcfg); smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); - smb_dr_put_kconfig(enc_ctx, &smb_kcfg); + smb_dr_put_uint32(enc_ctx, rc); + if (rc == NERR_Success) { + smb_dr_put_ushort(enc_ctx, esi.es_ntotal); + smb_dr_put_ushort(enc_ctx, esi.es_nsent); + smb_dr_put_ushort(enc_ctx, esi.es_datasize); + smb_dr_put_buf(enc_ctx, + (unsigned char *)esi.es_buf, esi.es_bufsize); + free(esi.es_buf); + } break; default: @@ -312,11 +295,14 @@ smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp, goto decode_error; } - if ((enc_status = smb_dr_encode_finish(enc_ctx, &used)) != 0) - goto encode_error; + if ((enc_status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { + enc_ctx = smb_dr_encode_start(buf, sizeof (buf)); + smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_ERROR); + smb_dr_put_uint32(enc_ctx, enc_status); + (void) smb_dr_encode_finish(enc_ctx, &used); + } (void) door_return(buf, used, NULL, 0); - return; decode_error: @@ -324,25 +310,17 @@ decode_error: smb_dr_put_uint32(enc_ctx, dec_status); (void) smb_dr_encode_finish(enc_ctx, &used); (void) door_return(buf, used, NULL, 0); - return; - -encode_error: - enc_ctx = smb_dr_encode_start(buf, sizeof (buf)); - smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_ERROR); - smb_dr_put_uint32(enc_ctx, enc_status); - (void) smb_dr_encode_finish(enc_ctx, &used); - (void) door_return(buf, used, NULL, 0); } /* - * smb_lmshrd_srv_check + * smb_share_dsrv_check * * Depending upon the opcode, this function will * either check the existence of a share/dir or * the the type of the specified share. */ static int -smb_lmshrd_srv_check(int opcode, char *sharename) +smb_share_dsrv_check(int opcode, char *sharename) { int rc; @@ -373,3 +351,111 @@ smb_lmshrd_srv_check(int opcode, char *sharename) return (rc); } + +/* + * smb_share_dsrv_enum + * + * This function builds a response for a NetShareEnum RAP request which + * originates from smbsrv kernel module. A response buffer is allocated + * with the specified size in esi->es_bufsize. List of shares is scanned + * twice. In the first round the total number of shares which their OEM + * name is shorter than 13 chars (esi->es_ntotal) and also the number of + * shares that fit in the given buffer are calculated. In the second + * round the shares data are encoded in the buffer. + * + * The data associated with each share has two parts, a fixed size part and + * a variable size part which is share's comment. The outline of the response + * buffer is so that fixed part for all the shares will appear first and follows + * with the comments for all those shares and that's why the data cannot be + * encoded in one round without unnecessarily complicating the code. + */ +static int +smb_share_dsrv_enum(smb_enumshare_info_t *esi) +{ + lmshare_iterator_t shi; + lmshare_info_t *si; + int remained; + uint16_t infolen = 0; + uint16_t cmntlen = 0; + uint16_t sharelen; + uint16_t clen; + uint32_t cmnt_offs; + smb_msgbuf_t info_mb; + smb_msgbuf_t cmnt_mb; + boolean_t autohome_added = B_FALSE; + + esi->es_ntotal = esi->es_nsent = 0; + + if ((esi->es_buf = malloc(esi->es_bufsize)) == NULL) + return (NERR_InternalError); + + bzero(esi->es_buf, esi->es_bufsize); + remained = esi->es_bufsize; + + /* Do the necessary calculations in the first round */ + lmshare_init_iterator(&shi, LMSHRM_ALL); + + while ((si = lmshare_iterate(&shi)) != NULL) { + if (si->mode & LMSHRM_LONGNAME) + continue; + + if ((si->mode & LMSHRM_AUTOHOME) && !autohome_added) { + if (strcasecmp(esi->es_username, si->share_name) == 0) + autohome_added = B_TRUE; + else + continue; + } + + esi->es_ntotal++; + + if (remained <= 0) + continue; + + clen = strlen(si->comment) + 1; + sharelen = SHARE_INFO_1_SIZE + clen; + + if (sharelen <= remained) { + infolen += SHARE_INFO_1_SIZE; + cmntlen += clen; + } + + remained -= sharelen; + } + + esi->es_datasize = infolen + cmntlen; + + smb_msgbuf_init(&info_mb, (uint8_t *)esi->es_buf, infolen, 0); + smb_msgbuf_init(&cmnt_mb, (uint8_t *)esi->es_buf + infolen, cmntlen, 0); + cmnt_offs = infolen; + + /* Encode the data in the second round */ + lmshare_init_iterator(&shi, LMSHRM_ALL); + autohome_added = B_FALSE; + + while ((si = lmshare_iterate(&shi)) != NULL) { + if (si->mode & LMSHRM_LONGNAME) + continue; + + if ((si->mode & LMSHRM_AUTOHOME) && !autohome_added) { + if (strcasecmp(esi->es_username, si->share_name) == 0) + autohome_added = B_TRUE; + else + continue; + } + + if (smb_msgbuf_encode(&info_mb, "13c.wl", + si->oem_name, si->stype, cmnt_offs) < 0) + break; + + if (smb_msgbuf_encode(&cmnt_mb, "s", si->comment) < 0) + break; + + cmnt_offs += strlen(si->comment) + 1; + esi->es_nsent++; + } + + smb_msgbuf_term(&info_mb); + smb_msgbuf_term(&cmnt_mb); + + return (NERR_Success); +} diff --git a/usr/src/common/smbsrv/smb_share_door_decode.c b/usr/src/common/smbsrv/smb_share_door_decode.c index cc3f2884e8..62628063dc 100644 --- a/usr/src/common/smbsrv/smb_share_door_decode.c +++ b/usr/src/common/smbsrv/smb_share_door_decode.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -46,28 +46,6 @@ #include <smbsrv/smbinfo.h> void -smb_dr_get_kconfig(smb_dr_ctx_t *ctx, smb_kmod_cfg_t *cfg) -{ - if (ctx->status == 0) { - (void) memcpy(cfg, ctx->ptr, sizeof (smb_kmod_cfg_t)); - ctx->ptr += sizeof (smb_kmod_cfg_t); - } - else - bzero(cfg, sizeof (smb_kmod_cfg_t)); -} - -void -smb_dr_put_kconfig(smb_dr_ctx_t *ctx, smb_kmod_cfg_t *cfg) -{ - if (ctx->ptr + sizeof (smb_kmod_cfg_t) <= ctx->end_ptr) { - (void) memcpy(ctx->ptr, cfg, sizeof (smb_kmod_cfg_t)); - ctx->ptr += sizeof (smb_kmod_cfg_t); - } - else - ctx->status = ENOSPC; -} - -void smb_dr_get_lmshare(smb_dr_ctx_t *ctx, lmshare_info_t *si) { if (ctx->status == 0) { @@ -98,30 +76,6 @@ smb_dr_put_lmshare(smb_dr_ctx_t *ctx, lmshare_info_t *si) smb_dr_put_int32(ctx, 0); } -uint64_t -smb_dr_get_lmshr_iterator(smb_dr_ctx_t *ctx) -{ - uint64_t lmshr_iter; - - if (smb_dr_get_int32(ctx)) - lmshr_iter = smb_dr_get_uint64(ctx); - else - lmshr_iter = 0; - - return (lmshr_iter); -} - -void -smb_dr_put_lmshr_iterator(smb_dr_ctx_t *ctx, uint64_t lmshr_iter) -{ - if (lmshr_iter) { - smb_dr_put_int32(ctx, 1); - smb_dr_put_uint64(ctx, lmshr_iter); - } - else - smb_dr_put_int32(ctx, 0); -} - void smb_dr_get_lmshr_list(smb_dr_ctx_t *ctx, lmshare_list_t *shrlist) { diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c index bec97b7c39..cbbc9297cb 100644 --- a/usr/src/lib/libshare/smb/libshare_smb.c +++ b/usr/src/lib/libshare/smb/libshare_smb.c @@ -413,7 +413,6 @@ smb_enable_share(sa_share_t share) for (resource = sa_get_share_resource(share, NULL); resource != NULL; resource = sa_get_next_resource(resource)) { - sa_optionset_t opts; bzero(&si, sizeof (lmshare_info_t)); rname = sa_get_resource_attr(resource, "name"); if (rname == NULL) { @@ -421,11 +420,9 @@ smb_enable_share(sa_share_t share) return (SA_NO_SUCH_RESOURCE); } - opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); - smb_build_lmshare_info(rname, path, opts, &si); + smb_build_lmshare_info(rname, path, resource, &si); sa_free_attr_string(rname); - sa_free_derived_optionset(opts); if (!iszfs) { err = lmshrd_add(&si); } else { @@ -458,7 +455,6 @@ smb_enable_resource(sa_resource_t resource) { char *path; char *rname; - sa_optionset_t opts; sa_share_t share; lmshare_info_t si; int ret = SA_OK; @@ -492,11 +488,9 @@ smb_enable_resource(sa_resource_t resource) return (SA_NO_SUCH_RESOURCE); } - opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); - smb_build_lmshare_info(rname, path, opts, &si); + smb_build_lmshare_info(rname, path, resource, &si); sa_free_attr_string(path); sa_free_attr_string(rname); - sa_free_derived_optionset(opts); /* * Attempt to add the share. Any error that occurs if it was @@ -595,7 +589,6 @@ smb_resource_changed(sa_resource_t resource) lmshare_info_t si; lmshare_info_t new_si; char *rname, *path; - sa_optionset_t opts; sa_share_t share; rname = sa_get_resource_attr(resource, "name"); @@ -627,9 +620,7 @@ smb_resource_changed(sa_resource_t resource) return (SA_CONFIG_ERR); } - opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); - smb_build_lmshare_info(rname, path, opts, &new_si); - sa_free_derived_optionset(opts); + smb_build_lmshare_info(rname, path, resource, &new_si); sa_free_attr_string(path); sa_free_attr_string(rname); diff --git a/usr/src/lib/libshare/smb/smb_share_doorclnt.c b/usr/src/lib/libshare/smb/smb_share_doorclnt.c index 1a06278568..731b70c47c 100644 --- a/usr/src/lib/libshare/smb/smb_share_doorclnt.c +++ b/usr/src/lib/libshare/smb/smb_share_doorclnt.c @@ -54,9 +54,6 @@ static cond_t lmshrd_cv; char *lmshrd_desc[] = { "", - "LmshrdOpenIter", - "LmshrdCloseIter", - "LmshrdIterate", "LmshrdNumShares", "LmshrdDelete", "LmshrdRename", @@ -70,7 +67,6 @@ char *lmshrd_desc[] = { "LmshrdIsValid", "LmshrdIsDir", "LmshrdList", - "LmshrdListTrans", "LmshrdNumTrans", "N/A", 0 @@ -179,140 +175,6 @@ lmshrd_door_check_status(smb_dr_ctx_t *dec_ctx) return (0); } -uint64_t -lmshrd_open_iterator(int mode) -{ - door_arg_t *arg; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - uint64_t lmshr_iter = 0; - int rc; - - if ((arg = lmshrd_door_enter()) == NULL) - return (lmshr_iter); - - enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_OPEN_ITERATOR); - smb_dr_put_int32(enc_ctx, mode); - - rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); - if (rc != 0) { - lmshrd_door_exit(arg, "encode error"); - return (lmshr_iter); - } - - if (door_call(lmshrd_fildes, arg) < 0) { - lmshrd_door_exit(arg, "door call error"); - lmshrd_door_close(); - return (lmshr_iter); - } - - dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); - if (lmshrd_door_check_status(dec_ctx) != 0) { - (void) smb_dr_decode_finish(dec_ctx); - lmshrd_door_exit(arg, "decode error"); - return (lmshr_iter); - } - - lmshr_iter = smb_dr_get_lmshr_iterator(dec_ctx); - if (smb_dr_decode_finish(dec_ctx) != 0) { - lmshrd_door_exit(arg, "decode error"); - return (lmshr_iter); - } - - lmshrd_door_exit(arg, NULL); - return (lmshr_iter); -} - - -DWORD -lmshrd_close_iterator(uint64_t iterator) -{ - door_arg_t *arg; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - int rc; - - if ((arg = lmshrd_door_enter()) == NULL) - return (NERR_InternalError); - - enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_CLOSE_ITERATOR); - smb_dr_put_lmshr_iterator(enc_ctx, iterator); - - rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); - if (rc != 0) { - lmshrd_door_exit(arg, "encode error"); - return (NERR_InternalError); - } - - if (door_call(lmshrd_fildes, arg) < 0) { - lmshrd_door_exit(arg, "door call error"); - lmshrd_door_close(); - return (NERR_InternalError); - } - - dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); - if (lmshrd_door_check_status(dec_ctx) != 0) { - (void) smb_dr_decode_finish(dec_ctx); - lmshrd_door_exit(arg, "decode error"); - return (NERR_InternalError); - } - - if (smb_dr_decode_finish(dec_ctx) != 0) { - lmshrd_door_exit(arg, "decode error"); - return (NERR_InternalError); - } - - lmshrd_door_exit(arg, NULL); - return (NERR_Success); -} - -DWORD -lmshrd_iterate(uint64_t iterator, lmshare_info_t *si) -{ - door_arg_t *arg; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - int rc; - - if ((arg = lmshrd_door_enter()) == NULL) - return (NERR_InternalError); - - bzero(si, sizeof (lmshare_info_t)); - enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_ITERATE); - smb_dr_put_lmshr_iterator(enc_ctx, iterator); - - rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); - if (rc != 0) { - lmshrd_door_exit(arg, "encode error"); - return (NERR_InternalError); - } - - if (door_call(lmshrd_fildes, arg) < 0) { - lmshrd_door_exit(arg, "door call error"); - lmshrd_door_close(); - return (NERR_InternalError); - } - - dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); - if (lmshrd_door_check_status(dec_ctx) != 0) { - (void) smb_dr_decode_finish(dec_ctx); - lmshrd_door_exit(arg, "decode error"); - return (NERR_InternalError); - } - - smb_dr_get_lmshare(dec_ctx, si); - if (smb_dr_decode_finish(dec_ctx) != 0) { - lmshrd_door_exit(arg, "decode error"); - return (NERR_InternalError); - } - - lmshrd_door_exit(arg, NULL); - return (NERR_Success); -} - DWORD lmshrd_list(int offset, lmshare_list_t *list) { @@ -347,7 +209,6 @@ lmshrd_list(int offset, lmshare_list_t *list) return (NERR_InternalError); } - rc = smb_dr_get_uint32(dec_ctx); smb_dr_get_lmshr_list(dec_ctx, list); if (smb_dr_decode_finish(dec_ctx) != 0) { lmshrd_door_exit(arg, "decode error"); @@ -355,7 +216,7 @@ lmshrd_list(int offset, lmshare_list_t *list) } lmshrd_door_exit(arg, NULL); - return (rc); + return (NERR_Success); } int diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c index b64ada2955..c6f889f5d7 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c @@ -899,11 +899,14 @@ mlndr_outer_conformant_array(struct ndr_reference *outer_ref) return (0); } - valp = MLNDS_MALLOC(mlnds, n_alloc, outer_ref); - if (!valp) { - NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED); - return (0); + if (size_is > 0) { + valp = MLNDS_MALLOC(mlnds, n_alloc, outer_ref); + if (!valp) { + NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED); + return (0); + } } + if (outer_ref->backptr) *outer_ref->backptr = valp; outer_ref->datum = valp; @@ -914,28 +917,30 @@ mlndr_outer_conformant_array(struct ndr_reference *outer_ref) return (0); } - bzero(&myref, sizeof (myref)); - myref.stream = mlnds; - myref.enclosing = outer_ref; - myref.ti = outer_ref->ti; - myref.datum = outer_ref->datum; - myref.name = "CONFORMANT-ARRAY"; - myref.outer_flags = NDR_F_NONE; - myref.inner_flags = NDR_F_SIZE_IS; - myref.size_is = outer_ref->size_is; - - myref.inner_flags = NDR_F_DIMENSION_IS; /* convenient */ - myref.dimension_is = outer_ref->size_is; /* convenient */ - - myref.pdu_offset = outer_ref->pdu_offset + 4; outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total; - outer_ref->type_flags = NDR_F_NONE; outer_ref->inner_flags = NDR_F_NONE; - rc = mlndr_inner(&myref); - if (!rc) - return (rc); /* error already set */ + if (size_is > 0) { + bzero(&myref, sizeof (myref)); + myref.stream = mlnds; + myref.enclosing = outer_ref; + myref.ti = outer_ref->ti; + myref.datum = outer_ref->datum; + myref.name = "CONFORMANT-ARRAY"; + myref.outer_flags = NDR_F_NONE; + myref.inner_flags = NDR_F_SIZE_IS; + myref.size_is = outer_ref->size_is; + + myref.inner_flags = NDR_F_DIMENSION_IS; /* convenient */ + myref.dimension_is = outer_ref->size_is; /* convenient */ + + myref.pdu_offset = outer_ref->pdu_offset + 4; + + rc = mlndr_inner(&myref); + if (!rc) + return (rc); /* error already set */ + } mlnds->pdu_scan_offset = outer_ref->pdu_end_offset; return (1); @@ -1041,6 +1046,10 @@ mlndr_outer_conformant_construct(struct ndr_reference *outer_ref) return (0); } + outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total; + outer_ref->type_flags = NDR_F_SIZE_IS; /* indicate pending */ + outer_ref->inner_flags = NDR_F_NONE; /* indicate pending */ + bzero(&myref, sizeof (myref)); myref.stream = mlnds; myref.enclosing = outer_ref; @@ -1052,10 +1061,6 @@ mlndr_outer_conformant_construct(struct ndr_reference *outer_ref) myref.size_is = outer_ref->size_is; myref.pdu_offset = outer_ref->pdu_offset + 4; - outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total; - - outer_ref->type_flags = NDR_F_SIZE_IS; /* indicate pending */ - outer_ref->inner_flags = NDR_F_NONE; /* indicate pending */ rc = mlndr_inner(&myref); if (!rc) diff --git a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h index 102f6d2ca4..07b25d1805 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h +++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h @@ -62,13 +62,9 @@ typedef struct smb_autohome { char *ah_container; /* ADS container distinguished name */ } smb_autohome_t; -extern int smb_autohome_add(const char *); -extern int smb_autohome_remove(const char *); -extern int smb_is_autohome(const lmshare_info_t *); -extern void smb_autohome_setent(void); -extern void smb_autohome_endent(void); -extern smb_autohome_t *smb_autohome_getent(const char *name); -extern smb_autohome_t *smb_autohome_lookup(const char *name); +extern void smb_autohome_add(const char *); +extern void smb_autohome_remove(const char *); +extern boolean_t smb_is_autohome(const lmshare_info_t *); #ifdef __cplusplus } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c b/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c index 5a52c64513..b64b7ac1ad 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c @@ -68,10 +68,11 @@ static HT_HANDLE *lmshare_handle = NULL; static rwlock_t lmshare_lock; static pthread_t lmshare_load_thread; static void *lmshare_load(void *); -static DWORD lmshare_create_table(); +static DWORD lmshare_create_table(void); static int lmshare_delete_shmgr(struct lmshare_info *); static int lmshare_setinfo_shmgr(struct lmshare_info *); -static DWORD lmshare_set_refcnt(char *share_name, int refcnt); +static DWORD lmshare_set_refcnt(char *, int); +static void lmshare_set_oemname(lmshare_info_t *); typedef struct lmshare_ad_item { TAILQ_ENTRY(lmshare_ad_item) next; @@ -139,7 +140,6 @@ lmshare_load_shares(sa_group_t group) { sa_share_t share; sa_resource_t resource; - sa_optionset_t opts; lmshare_info_t si; char *path, *rname; @@ -162,10 +162,7 @@ lmshare_load_shares(sa_group_t group) "resource for path: %s", path); continue; } - opts = sa_get_derived_optionset(resource, - SMB_PROTOCOL_NAME, 1); - smb_build_lmshare_info(rname, path, opts, &si); - sa_free_derived_optionset(opts); + smb_build_lmshare_info(rname, path, resource, &si); sa_free_attr_string(rname); if (lmshare_add(&si, 0) != NERR_Success) { syslog(LOG_ERR, "Failed to load " @@ -250,7 +247,7 @@ static void lmshare_callback(HT_ITEM *item) { if (item && item->hi_data) - (void) free(item->hi_data); + free(item->hi_data); } /* @@ -297,7 +294,7 @@ lmshare_add_adminshare(char *volname, unsigned char drive) bzero(&si, sizeof (lmshare_info_t)); (void) strcpy(si.directory, volname); - si.mode = LMSHRM_TRANS; + si.mode = LMSHRM_TRANS | LMSHRM_ADMIN; (void) snprintf(si.share_name, sizeof (si.share_name), "%c$", drive); rc = lmshare_add(&si, 0); @@ -324,55 +321,22 @@ lmshare_num_shares(void) } /* - * lmshare_open_iterator + * lmshare_init_iterator * - * Create and initialize an iterator for traversing hash table. - * It gets a mode that can be LMSHR_IM_ALL to iterate through all - * the shares stored in table or LMSHR_IM_PRES to iterate through - * only presentable shares. - * - * It also accepts a local IP address. This is used in dual head - * systems to only return the shares that belong to the head which - * is specified by the 'ipaddr'. If ipaddr is 0 it'll return shares - * of both heads. - * - * On success return pointer to the new iterator. - * On failure return (NULL). - */ -lmshare_iterator_t * -lmshare_open_iterator(int mode) -{ - lmshare_iterator_t *shi; - int sz = sizeof (lmshare_iterator_t) + sizeof (HT_ITERATOR); - - shi = malloc(sz); - if (shi != NULL) { - bzero(shi, sz); - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - shi->iterator = (HT_ITERATOR *) - ((char *)shi + sizeof (lmshare_iterator_t)); - shi->mode = mode; - } else { - syslog(LOG_DEBUG, "Failed to create share iterator handle"); - } - return (shi); -} - -/* - * lmshare_close_iterator - * - * Free memory allocated by the given iterator. + * Initialize an iterator for traversing hash table. + * 'mode' is used for filtering shares when iterating. */ void -lmshare_close_iterator(lmshare_iterator_t *shi) +lmshare_init_iterator(lmshare_iterator_t *shi, uint32_t mode) { - (void) free(shi); + bzero(shi, sizeof (lmshare_iterator_t)); + shi->mode = mode; } /* * lmshare_iterate * - * Iterate on the shares in the hash table. The iterator must be opened + * Iterate on the shares in the hash table. The iterator must be initialized * before the first iteration. On subsequent calls, the iterator must be * passed unchanged. * @@ -396,6 +360,7 @@ lmshare_iterate(lmshare_iterator_t *shi) * IPC$ is always first. */ (void) strcpy(shi->si.share_name, "IPC$"); + lmshare_set_oemname(&shi->si); shi->si.mode = LMSHRM_TRANS; shi->si.stype = (int)(STYPE_IPC | STYPE_SPECIAL); shi->iteration = 1; @@ -404,7 +369,7 @@ lmshare_iterate(lmshare_iterator_t *shi) if (shi->iteration == 1) { if ((item = ht_findfirst( - lmshare_handle, shi->iterator)) == NULL) { + lmshare_handle, &shi->iterator)) == NULL) { return (NULL); } @@ -412,18 +377,16 @@ lmshare_iterate(lmshare_iterator_t *shi) ++shi->iteration; if (si->mode & shi->mode) { - (void) memcpy(&(shi->si), si, - sizeof (lmshare_info_t)); + (void) memcpy(&(shi->si), si, sizeof (lmshare_info_t)); return (&(shi->si)); } } - while ((item = ht_findnext(shi->iterator)) != NULL) { + while ((item = ht_findnext(&shi->iterator)) != NULL) { si = (lmshare_info_t *)(item->hi_data); ++shi->iteration; if (si->mode & shi->mode) { (void) memcpy(&(shi->si), si, sizeof (lmshare_info_t)); - return (&(shi->si)); } } @@ -451,7 +414,10 @@ lmshare_add(lmshare_info_t *si, int doshm) (void) utf8_strlwr(si->share_name); if (lmshare_exists(si->share_name)) { - if ((si->mode & LMSHRM_TRANS) == 0) + /* + * Only autohome shares can be added multiple times + */ + if ((si->mode & LMSHRM_AUTOHOME) == 0) return (NERR_DuplicateShare); } @@ -460,7 +426,7 @@ lmshare_add(lmshare_info_t *si, int doshm) lmshare_do_publish(si, LMSHR_PUBLISH, 1); } - if ((si->mode & LMSHRM_TRANS) && (status == NERR_Success)) { + if ((si->mode & LMSHRM_AUTOHOME) && (status == NERR_Success)) { si->refcnt++; status = lmshare_set_refcnt(si->share_name, si->refcnt); } @@ -507,7 +473,7 @@ lmshare_delete(char *share_name, int doshm) return (NERR_InternalError); } - if ((si->mode & LMSHRM_TRANS) != 0) { + if ((si->mode & LMSHRM_AUTOHOME) == LMSHRM_AUTOHOME) { si->refcnt--; if (si->refcnt > 0) { status = lmshare_set_refcnt(si->share_name, si->refcnt); @@ -993,11 +959,13 @@ lmshare_setinfo(lmshare_info_t *si, int doshm) } } else { /* Unpublish old share from AD */ - if ((si->mode & LMSHRM_TRANS) == 0) { + if ((add_si->mode & LMSHRM_PERM) == LMSHRM_PERM) lmshare_do_publish(&old_si, LMSHR_UNPUBLISH, 1); - } (void) del_fromhash(si->share_name); } + + lmshare_set_oemname(add_si); + /* if it's not transient it should be permanent */ if ((add_si->mode & LMSHRM_TRANS) == 0) add_si->mode |= LMSHRM_PERM; @@ -1016,7 +984,7 @@ lmshare_setinfo(lmshare_info_t *si, int doshm) } (void) rw_unlock(&lmshare_lock); - if ((add_si->mode & LMSHRM_TRANS) == 0) { + if ((add_si->mode & LMSHRM_PERM) == LMSHRM_PERM) { if (doshm && (lmshare_setinfo_shmgr(add_si) != 0)) { syslog(LOG_ERR, "Update share %s in sharemgr failed", add_si->share_name); @@ -1028,21 +996,20 @@ lmshare_setinfo(lmshare_info_t *si, int doshm) return (res); } -DWORD +void lmshare_list(int offset, lmshare_list_t *list) { - lmshare_iterator_t *iterator; + lmshare_iterator_t iterator; lmshare_info_t *si; int list_idx = 0; int i = 0; bzero(list, sizeof (lmshare_list_t)); - if ((iterator = lmshare_open_iterator(LMSHRM_ALL)) == NULL) - return (NERR_InternalError); + lmshare_init_iterator(&iterator, LMSHRM_ALL); - (void) lmshare_iterate(iterator); /* To skip IPC$ */ + (void) lmshare_iterate(&iterator); /* To skip IPC$ */ - while ((si = lmshare_iterate(iterator)) != NULL) { + while ((si = lmshare_iterate(&iterator)) != NULL) { if (lmshare_is_special(si->share_name)) { /* * Don't return restricted shares. @@ -1059,11 +1026,8 @@ lmshare_list(int offset, lmshare_list_t *list) if (++list_idx == LMSHARES_PER_REQUEST) break; } - lmshare_close_iterator(iterator); list->no = list_idx; - - return (NERR_Success); } /* @@ -1076,8 +1040,10 @@ lmshare_do_publish(lmshare_info_t *si, char flag, int poke) if (publish_on == 0) return; + if ((si == NULL) || (si->container[0] == '\0')) return; + (void) mutex_lock(&lmshare_publish_mutex); item = (lmshare_ad_item_t *)malloc(sizeof (lmshare_ad_item_t)); if (item == NULL) { @@ -1221,3 +1187,47 @@ lmshare_get_realpath(const char *clipath, char *realpath, int maxlen) /* XXX do this translation */ return (NERR_Success); } + +/* + * lmshare_set_oemname + * + * Generates the OEM name of the given share. If it's + * shorter than 13 chars it'll be saved in si->oem_name. + * Otherwise si->oem_name will be empty and LMSHRM_LONGNAME + * will be set in si->mode. + */ +static void +lmshare_set_oemname(lmshare_info_t *si) +{ + unsigned int cpid = oem_get_smb_cpid(); + mts_wchar_t *unibuf; + char *oem_name; + int length; + + length = strlen(si->share_name) + 1; + + oem_name = malloc(length); + unibuf = malloc(length * sizeof (mts_wchar_t)); + if ((oem_name == NULL) || (unibuf == NULL)) { + free(oem_name); + free(unibuf); + return; + } + + (void) mts_mbstowcs(unibuf, si->share_name, length); + + if (unicodestooems(oem_name, unibuf, length, cpid) == 0) + (void) strcpy(oem_name, si->share_name); + + free(unibuf); + + if (strlen(oem_name) + 1 > LMSHR_OEM_NAME_MAX) { + si->mode |= LMSHRM_LONGNAME; + *si->oem_name = '\0'; + } else { + si->mode &= ~LMSHRM_LONGNAME; + (void) strlcpy(si->oem_name, oem_name, LMSHR_OEM_NAME_MAX); + } + + free(oem_name); +} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers index 96ef7d3d9d..a33e61cad5 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers @@ -28,7 +28,6 @@ SUNWprivate { global: lmshare_add; - lmshare_close_iterator; lmshare_delete; lmshare_exists; lmshare_getinfo; @@ -41,7 +40,7 @@ SUNWprivate { lmshare_iterate; lmshare_list; lmshare_num_shares; - lmshare_open_iterator; + lmshare_init_iterator; lmshare_rename; lmshare_setinfo; lmshare_start; @@ -60,11 +59,7 @@ SUNWprivate { smb_build_lmshare_info; smb_get_smb_share_group; smb_autohome_add; - smb_autohome_endent; - smb_autohome_getent; - smb_autohome_lookup; smb_autohome_remove; - smb_autohome_setent; smb_is_autohome; local: *; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c index 65d96399ed..bbd3b2c6cc 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c @@ -1328,7 +1328,7 @@ mlsvc_NetShareEnumLevel0(struct mlrpc_xaction *mxa, struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) { struct mslm_SHARE_INFO_0 *info0; - lmshare_iterator_t *iterator; + lmshare_iterator_t iterator; lmshare_info_t *si; DWORD status; @@ -1341,12 +1341,10 @@ mlsvc_NetShareEnumLevel0(struct mlrpc_xaction *mxa, if (info0 == NULL) return (ERROR_NOT_ENOUGH_MEMORY); - iterator = lmshare_open_iterator(LMSHRM_ALL); - if (iterator == NULL) - return (ERROR_NOT_ENOUGH_MEMORY); + lmshare_init_iterator(&iterator, LMSHRM_ALL); se->se_n_read = 0; - while ((si = lmshare_iterate(iterator)) != NULL) { + while ((si = lmshare_iterate(&iterator)) != NULL) { if (se->se_n_skip > 0) { --se->se_n_skip; continue; @@ -1377,7 +1375,6 @@ mlsvc_NetShareEnumLevel0(struct mlrpc_xaction *mxa, ++se->se_n_read; } - lmshare_close_iterator(iterator); infonres->entriesread = se->se_n_read; infonres->entries = info0; return (ERROR_SUCCESS); @@ -1391,7 +1388,7 @@ mlsvc_NetShareEnumLevel1(struct mlrpc_xaction *mxa, struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) { struct mslm_SHARE_INFO_1 *info1; - lmshare_iterator_t *iterator; + lmshare_iterator_t iterator; lmshare_info_t *si; DWORD status; @@ -1404,12 +1401,10 @@ mlsvc_NetShareEnumLevel1(struct mlrpc_xaction *mxa, if (info1 == NULL) return (ERROR_NOT_ENOUGH_MEMORY); - iterator = lmshare_open_iterator(LMSHRM_ALL); - if (iterator == NULL) - return (ERROR_NOT_ENOUGH_MEMORY); + lmshare_init_iterator(&iterator, LMSHRM_ALL); se->se_n_read = 0; - while ((si = lmshare_iterate(iterator)) != 0) { + while ((si = lmshare_iterate(&iterator)) != 0) { if (se->se_n_skip > 0) { --se->se_n_skip; continue; @@ -1440,7 +1435,6 @@ mlsvc_NetShareEnumLevel1(struct mlrpc_xaction *mxa, ++se->se_n_read; } - lmshare_close_iterator(iterator); infonres->entriesread = se->se_n_read; infonres->entries = info1; return (ERROR_SUCCESS); @@ -1454,7 +1448,7 @@ mlsvc_NetShareEnumLevel2(struct mlrpc_xaction *mxa, struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) { struct mslm_SHARE_INFO_2 *info2; - lmshare_iterator_t *iterator; + lmshare_iterator_t iterator; lmshare_info_t *si; DWORD status; @@ -1467,12 +1461,10 @@ mlsvc_NetShareEnumLevel2(struct mlrpc_xaction *mxa, if (info2 == 0) return (ERROR_NOT_ENOUGH_MEMORY); - iterator = lmshare_open_iterator(LMSHRM_ALL); - if (iterator == NULL) - return (ERROR_NOT_ENOUGH_MEMORY); + lmshare_init_iterator(&iterator, LMSHRM_ALL); se->se_n_read = 0; - while ((si = lmshare_iterate(iterator)) != 0) { + while ((si = lmshare_iterate(&iterator)) != 0) { if (se->se_n_skip > 0) { --se->se_n_skip; continue; @@ -1503,7 +1495,6 @@ mlsvc_NetShareEnumLevel2(struct mlrpc_xaction *mxa, ++se->se_n_read; } - lmshare_close_iterator(iterator); infonres->entriesread = se->se_n_read; infonres->entries = info2; return (ERROR_SUCCESS); @@ -1517,7 +1508,7 @@ mlsvc_NetShareEnumLevel501(struct mlrpc_xaction *mxa, struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) { struct mslm_SHARE_INFO_501 *info501; - lmshare_iterator_t *iterator; + lmshare_iterator_t iterator; lmshare_info_t *si; DWORD status; @@ -1531,12 +1522,10 @@ mlsvc_NetShareEnumLevel501(struct mlrpc_xaction *mxa, if (info501 == NULL) return (ERROR_NOT_ENOUGH_MEMORY); - iterator = lmshare_open_iterator(LMSHRM_ALL); - if (iterator == NULL) - return (ERROR_NOT_ENOUGH_MEMORY); + lmshare_init_iterator(&iterator, LMSHRM_ALL); se->se_n_read = 0; - while ((si = lmshare_iterate(iterator)) != 0) { + while ((si = lmshare_iterate(&iterator)) != 0) { if (se->se_n_skip > 0) { --se->se_n_skip; continue; @@ -1567,7 +1556,6 @@ mlsvc_NetShareEnumLevel501(struct mlrpc_xaction *mxa, ++se->se_n_read; } - lmshare_close_iterator(iterator); infonres->entriesread = se->se_n_read; infonres->entries = info501; return (ERROR_SUCCESS); @@ -1581,7 +1569,7 @@ mlsvc_NetShareEnumLevel502(struct mlrpc_xaction *mxa, struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) { struct mslm_SHARE_INFO_502 *info502; - lmshare_iterator_t *iterator; + lmshare_iterator_t iterator; lmshare_info_t *si; DWORD status; @@ -1595,12 +1583,10 @@ mlsvc_NetShareEnumLevel502(struct mlrpc_xaction *mxa, if (info502 == NULL) return (ERROR_NOT_ENOUGH_MEMORY); - iterator = lmshare_open_iterator(LMSHRM_ALL); - if (iterator == NULL) - return (ERROR_NOT_ENOUGH_MEMORY); + lmshare_init_iterator(&iterator, LMSHRM_ALL); se->se_n_read = 0; - while ((si = lmshare_iterate(iterator)) != NULL) { + while ((si = lmshare_iterate(&iterator)) != NULL) { if (se->se_n_skip > 0) { --se->se_n_skip; continue; @@ -1631,7 +1617,6 @@ mlsvc_NetShareEnumLevel502(struct mlrpc_xaction *mxa, ++se->se_n_read; } - lmshare_close_iterator(iterator); infonres->entriesread = se->se_n_read; infonres->entries = info502; return (ERROR_SUCCESS); @@ -1791,7 +1776,7 @@ srvsvc_add_autohome(struct mlrpc_xaction *mxa, srvsvc_enum_t *se, void *infop) if (lmshare_getinfo(username, &si) != NERR_Success) return (B_FALSE); - if (!(si.mode & LMSHRM_TRANS)) + if ((si.mode & LMSHRM_AUTOHOME) == 0) return (B_FALSE); status = mlsvc_NetShareEnumCommon(mxa, se, &si, infop); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c index bc3f526046..0199489fac 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c @@ -29,6 +29,8 @@ #include <stdlib.h> #include <stdio.h> #include <pwd.h> +#include <assert.h> +#include <strings.h> #include <sys/stat.h> #include <smbsrv/libsmb.h> #include <smbsrv/libmlsvc.h> @@ -53,6 +55,10 @@ static smb_autohome_info_t smb_ai; static smb_autohome_t *smb_autohome_make_entry(smb_autohome_info_t *); static char *smb_autohome_keysub(const char *, char *, int); static smb_autohome_info_t *smb_autohome_getinfo(void); +static smb_autohome_t *smb_autohome_lookup(const char *); +static void smb_autohome_setent(void); +static void smb_autohome_endent(void); +static smb_autohome_t *smb_autohome_getent(const char *); /* * Add an autohome share. See smb_autohome(4) for details. @@ -60,95 +66,65 @@ static smb_autohome_info_t *smb_autohome_getinfo(void); * If share directory contains backslash path separators, they will * be converted to forward slash to support NT/DOS path style for * autohome shares. - * - * Returns 0 on success or -1 to indicate an error. */ -int +void smb_autohome_add(const char *username) { lmshare_info_t si; - char *sharename; smb_autohome_t *ai; - if (username == NULL) - return (-1); + assert(username); - if ((sharename = strdup(username)) == NULL) - return (-1); - - if ((ai = smb_autohome_lookup(sharename)) == NULL) { - free(sharename); - return (0); - } + if ((ai = smb_autohome_lookup(username)) == NULL) + return; - (void) memset(&si, 0, sizeof (lmshare_info_t)); + bzero(&si, sizeof (lmshare_info_t)); (void) strlcpy(si.directory, ai->ah_path, MAXPATHLEN); (void) strsubst(si.directory, '\\', '/'); (void) strlcpy(si.container, ai->ah_container, MAXPATHLEN); - if (lmshare_is_dir(si.directory) == 0) { - free(sharename); - return (0); - } + if (lmshare_is_dir(si.directory) == 0) + return; - if (lmshare_exists(sharename) != 0) { - (void) lmshare_getinfo(sharename, &si); - if (!(si.mode & LMSHRM_TRANS)) { - free(sharename); - return (0); - } + if (lmshare_getinfo((char *)username, &si) == NERR_Success) { + /* + * autohome shares will be added for each login attemp + * even if they already exist + */ + if ((si.mode & LMSHRM_AUTOHOME) == 0) + return; } else { - (void) strcpy(si.share_name, sharename); - si.mode = LMSHRM_TRANS; + (void) strlcpy(si.share_name, username, MAXNAMELEN); + si.mode = LMSHRM_TRANS | LMSHRM_AUTOHOME; } (void) lmshare_add(&si, 0); - free(sharename); - return (0); } /* * Remove an autohome share. - * - * Returns 0 on success or -1 to indicate an error. */ -int +void smb_autohome_remove(const char *username) { lmshare_info_t si; - char *sharename; - if (username == NULL) - return (-1); + assert(username); - if ((sharename = strdup(username)) == NULL) - return (-1); - - if (lmshare_getinfo(sharename, &si) == NERR_Success) { - if (si.mode & LMSHRM_TRANS) { - (void) lmshare_delete(sharename, 0); + if (lmshare_getinfo((char *)username, &si) == NERR_Success) { + if (si.mode & LMSHRM_AUTOHOME) { + (void) lmshare_delete((char *)username, 0); } } - - free(sharename); - return (0); } /* * Find out if a share is an autohome share. - * - * Returns 1 if the share is an autohome share. - * Otherwise returns 0. */ -int +boolean_t smb_is_autohome(const lmshare_info_t *si) { - if (si && (si->mode & LMSHRM_TRANS) && - (lmshare_is_restricted((char *)si->share_name) == 0)) { - return (1); - } - - return (0); + return (si && (si->mode & LMSHRM_AUTOHOME)); } /* @@ -162,11 +138,11 @@ smb_is_autohome(const lmshare_info_t *si) * * Returns a pointer to the entry on success or null on failure. */ -smb_autohome_t * +static smb_autohome_t * smb_autohome_lookup(const char *name) { struct passwd *pw; - smb_autohome_t *ah = 0; + smb_autohome_t *ah = NULL; if (name == NULL) return (NULL); @@ -199,7 +175,7 @@ smb_autohome_lookup(const char *name) if (strcasecmp("+nsswitch", ah->ah_name) != 0) continue; if ((pw = getpwnam(name)) == NULL) { - ah = 0; + ah = NULL; break; } @@ -220,7 +196,7 @@ smb_autohome_lookup(const char *name) /* * Open or rewind the autohome database. */ -void +static void smb_autohome_setent(void) { smb_autohome_info_t *si; @@ -257,7 +233,7 @@ smb_autohome_setent(void) * We can't zero the whole info structure because the application * should still have access to the data after the file is closed. */ -void +static void smb_autohome_endent(void) { smb_autohome_info_t *si; @@ -278,7 +254,7 @@ smb_autohome_endent(void) * only used for key substitution, so that the caller sees the entry * in expanded form. */ -smb_autohome_t * +static smb_autohome_t * smb_autohome_getent(const char *name) { smb_autohome_info_t *si; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_share_util.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_share_util.c index 8e5a7ca031..0da57bc6e3 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_share_util.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_share_util.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,16 +32,20 @@ #include <libshare.h> #include <smbsrv/lmshare.h> +#include <syslog.h> + static pthread_mutex_t smb_group_mutex = PTHREAD_MUTEX_INITIALIZER; /* Sharemanager shared API */ void smb_build_lmshare_info(char *share_name, char *path, - sa_optionset_t opts, lmshare_info_t *si) + sa_resource_t resource, lmshare_info_t *si) { sa_property_t prop; char *val = NULL; + sa_optionset_t opts; + sa_share_t share; bzero(si, sizeof (lmshare_info_t)); /* Share is read from SMF so it should be permanent */ @@ -50,6 +54,18 @@ smb_build_lmshare_info(char *share_name, char *path, (void) strlcpy(si->directory, path, sizeof (si->directory)); (void) strlcpy(si->share_name, share_name, sizeof (si->share_name)); + val = sa_get_resource_description(resource); + if (val == NULL) { + share = sa_get_resource_parent(resource); + val = sa_get_resource_description(share); + } + + if (val != NULL) { + (void) strlcpy(si->comment, val, sizeof (si->comment)); + sa_free_share_description(val); + } + + opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); if (opts == NULL) return; @@ -61,14 +77,7 @@ smb_build_lmshare_info(char *share_name, char *path, free(val); } } - - prop = (sa_property_t)sa_get_property(opts, "description"); - if (prop != NULL) { - if ((val = sa_get_property_attr(prop, "value")) != NULL) { - (void) strlcpy(si->comment, val, sizeof (si->comment)); - free(val); - } - } + sa_free_derived_optionset(opts); } /* diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index 36fb1b0192..3e0b8cc0c5 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -193,6 +193,8 @@ extern int smb_config_set_secmode(int); extern int smb_config_set_idmap_domain(char *); extern int smb_config_refresh_idmap(void); +extern void smb_load_kconfig(smb_kmod_cfg_t *kcfg); + extern boolean_t smb_match_netlogon_seqnum(void); extern int smb_setdomainprops(char *, char *, char *); extern void smb_update_netlogon_seqnum(void); diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers index 43469722ea..4cb2da2227 100644 --- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers @@ -142,7 +142,6 @@ SUNWprivate { smb_dr_get_dword; smb_dr_get_int32; smb_dr_get_lmshare; - smb_dr_get_lmshr_iterator; smb_dr_get_lmshr_list; smb_dr_get_opcode; smb_dr_get_res_stat; @@ -156,9 +155,7 @@ SUNWprivate { smb_dr_put_buf; smb_dr_put_dword; smb_dr_put_int32; - smb_dr_put_kconfig; smb_dr_put_lmshare; - smb_dr_put_lmshr_iterator; smb_dr_put_lmshr_list; smb_dr_put_short; smb_dr_put_string; diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index a5944235c1..536e46a7ae 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -940,6 +940,7 @@ SMBSRV_OBJS += $(SMBSRV_SHARED_OBJS) \ smb_kdoor_ops.o \ smb_kdoor_clnt.o \ smb_kdoor_srv.o \ + smb_kshare.o \ smb_lock_byte_range.o \ smb_lock_svc.o \ smb_locking_andx.o \ @@ -979,7 +980,6 @@ SMBSRV_OBJS += $(SMBSRV_SHARED_OBJS) \ smb_set_information.o \ smb_set_information2.o \ smb_signing.o \ - smb_share_kdoor_client.o \ smb_tree.o \ smb_trans2_create_directory.o \ smb_trans2_dfs.o \ @@ -1043,11 +1043,12 @@ NSMB_OBJS += smb_conn.o smb_crypt.o smb_dev.o smb_iod.o \ smb_rq.o smb_smb.o smb_tran.o smb_trantcp.o \ smb_usr.o smb_subrs.o subr_mchain.o smb_pass.o -SMBFS_OBJS += smbfs_vfsops.o smbfs_vnops.o smbfs_node.o \ - smbfs_acl.o smbfs_client.o smbfs_io.o \ - smbfs_smb.o smbfs_subr.o smbfs_subr2.o \ +SMBFS_OBJS += smbfs_vfsops.o smbfs_vnops.o smbfs_node.o \ + smbfs_acl.o smbfs_client.o smbfs_io.o \ + smbfs_smb.o smbfs_subr.o smbfs_subr2.o \ smbfs_rwlock.o + # # LVM modules # diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c index e84f76011a..e010182dad 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c @@ -34,10 +34,6 @@ #include <smbsrv/lmerr.h> #include <smbsrv/nterror.h> -#define MAX_SHARE_NAME_LEN 13 -#define SHARE_INFO_1_SIZE (MAX_SHARE_NAME_LEN + sizeof (char) + \ - sizeof (short) + sizeof (uint32_t)) - /* * count of bytes in server response packet * except parameters and data. Note that setup @@ -719,473 +715,39 @@ smb_trans_ready(struct smb_xa *xa) return (rc); } - -/* - * smb_emit_SHARE_INFO_0 - * - * This function will convert unicode chars to oem chars before - * and store the result in a fixed length, MAX_SHARE_NAME_LEN, buffer. If the - * length after conversion is longer than 12, -1 will be reported - * to indicate an error. The fixed length is a limitation of the - * smb protocol. - */ -static int -smb_emit_SHARE_INFO_0(struct mbuf_chain *output, unsigned char *name) -{ - unsigned int cpid = oem_get_smb_cpid(); - unsigned int length; - char name_buf[MAX_SHARE_NAME_LEN]; - mts_wchar_t *unibuf; - char *tmpbuf; - int rc = 0; - - tmpbuf = (name == NULL) ? "" : (char *)name; - length = strlen(tmpbuf) + 1; - - unibuf = kmem_alloc(length * sizeof (mts_wchar_t), KM_SLEEP); - (void) mts_mbstowcs(unibuf, tmpbuf, length); - - tmpbuf = kmem_alloc(length, KM_SLEEP); - if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0) - (void) strcpy(tmpbuf, (char *)name); - - if (strlen(tmpbuf) + 1 <= MAX_SHARE_NAME_LEN) { - bzero(name_buf, sizeof (name_buf)); - (void) strcpy(name_buf, tmpbuf); - (void) smb_encode_mbc(output, "13c", name_buf); - } else { - rc = -1; - } - - kmem_free(unibuf, length * sizeof (mts_wchar_t)); - kmem_free(tmpbuf, length); - - return (rc); -} - -static int -smb_emit_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text, - unsigned char *name, uint16_t type, - unsigned char *comment) +static void +smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text, + char *oem_name, uint16_t type, char *comment) { - if (smb_emit_SHARE_INFO_0(output, name) < 0) - return (-1); + (void) smb_encode_mbc(output, "13c.wl", oem_name, + type, MBC_LENGTH(text)); - (void) smb_encode_mbc(output, ".wl", type, MBC_LENGTH(text)); - (void) smb_encode_mbc(text, "s", - (comment ? comment : (unsigned char *)"No comment")); - return (0); + (void) smb_encode_mbc(text, "s", comment ? comment : ""); } -static void /*ARGSUSED*/ -smb_emit_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text, - struct smb_request *sr, unsigned char *name, uint16_t type, - unsigned char *comment, uint16_t access, char *path, char *password) +static void +smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text, + smb_request_t *sr, char *oem_name, uint16_t type, + char *comment, uint16_t access, char *path, char *password) { - unsigned char pword[9]; + unsigned char pword[9]; - /* - * XXX PGD. Is there a bug here? We zero pword, copy password - * into pword then ignore it and use password for smb_encode_mbc? - */ bzero(pword, sizeof (pword)); (void) strncpy((char *)pword, password, sizeof (pword)); - (void) smb_emit_SHARE_INFO_1(output, text, name, type, comment); + smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment); (void) smb_encode_mbc(output, "wwwl9c.", access, sr->sr_cfg->skc_maxconnections, smb_server_get_session_count(), MBC_LENGTH(text), - password); + pword); (void) smb_encode_mbc(text, "s", path); } -/* - * is_long_sharename - * - * This function is extracted from smb_emit_SHARE_INFO_0 only for - * finding shares that their names are longer than MAX_SHARE_NAME_LEN. - * - * The function returns 1 for long share names and 0 when the length - * is Ok. - */ -static boolean_t -is_long_sharename(unsigned char *name) -{ - unsigned int cpid = oem_get_smb_cpid(); - size_t length; - mts_wchar_t *unibuf; - char *tmpbuf; - boolean_t islong; - - tmpbuf = (name == NULL) ? "" : (char *)name; - length = strlen(tmpbuf) + 1; - - unibuf = kmem_alloc(length * sizeof (mts_wchar_t), KM_SLEEP); - (void) mts_mbstowcs(unibuf, tmpbuf, length); - - tmpbuf = kmem_alloc(length, KM_SLEEP); - if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0) - (void) strcpy(tmpbuf, (char *)name); - - islong = (strlen(tmpbuf) + 1 > MAX_SHARE_NAME_LEN); - - kmem_free(unibuf, length * sizeof (mts_wchar_t)); - kmem_free(tmpbuf, length); - - return (islong); -} - -/* - * This structure holds information about shares which will - * fit in the specified client buffer size. - * - * sei_bufsize: Client specified buffer size - * sei_count: Maximum number of shares that can be - * sent in the buffer. - * - * The return data section consists of a number of SHARE_INFO_1 structures. - * In case there are multiple SHARE_INFO_1 data structures to return this - * function put all fixed length part of these structures in the return buffer - * and then put all the variable length data (shares' comment) at the end of - * buffer. - * - * sei_info_len: Size of fixed length part of SHARE_INFO_1 - * structures for sei_count shares - * sei_cmnt_len: Size of comments for sei_count shares - */ -typedef struct { - uint16_t sei_bufsize; - short sei_count; - int sei_infolen; - int sei_cmntlen; -} smb_share_enum_t; - -/* - * smb_share_update_info - * - * Check to see if the given buffer has enough - * room to fit the information of the given share. - * If there is enough room update the passed max_??? - * information. - * - * Return 1 if buffer is not full yet, 0 if it's full. - */ -static int -smb_share_update_info(door_handle_t dhdl, lmshare_info_t *si, - smb_share_enum_t *shr_enum_info) -{ - int cmnt_len; - int new_info_len = shr_enum_info->sei_infolen; - int new_cmnt_len = shr_enum_info->sei_cmntlen; - - if (lmshrd_is_special(dhdl, si->share_name)) - cmnt_len = 1; - else - cmnt_len = (strlen(si->comment) + 1); - - new_info_len += SHARE_INFO_1_SIZE; - new_cmnt_len += cmnt_len; - - if ((new_info_len + new_cmnt_len) < shr_enum_info->sei_bufsize) { - shr_enum_info->sei_count++; - shr_enum_info->sei_infolen = new_info_len; - shr_enum_info->sei_cmntlen = new_cmnt_len; - return (1); - } - - return (0); -} - -/* - * smb_share_skip_share - * - * Determines whether the given share should be enumerated - * or not. The share will not be enumerated if its name is - * long or it's autohome share. - * - * Return 1 if the share should be skipped; otherwise returns - * 0 - */ -static int -smb_share_skip_share(lmshare_info_t *si) -{ - if (is_long_sharename((unsigned char *)si->share_name)) { - return (1); - } - - /* Skip autohome share if autohome filter is enabled */ - if (si->mode == LMSHRM_TRANS) { - return (1); - } - - return (0); -} - -/* - * smb_share_add_autohome - * - * Determines if an autohome share should be added to shares' list - * for the given user. - * Autohome will be add when all the following conditions are true: - * - * 1. Autohome feature is enabled - * 2. A share with the same name as the given user exists - * 3. The share is not a permanent share - * 4. Share name is not longer than maximum allowed - */ -static int -smb_share_add_autohome(door_handle_t dhdl, char *username, lmshare_info_t *si) -{ - int do_add = 0; - - do_add = (lmshrd_getinfo(dhdl, username, si) == NERR_Success) && - (si->mode & LMSHRM_TRANS) && - (!is_long_sharename((unsigned char *)(si->share_name))); - - return (do_add); -} - -/* - * smb_share_total_info - * - * This function calculates following informations - * - Maximum number of shares that can be sent for clients - * according to its buffer size (cli_bufsize) - * - length of fixed information about above shares - * - length of comments of above shares - * - total number of shares that their names are no longer - * than MAX_SHARE_NAME_LEN. - * - * Added SMB user object to the parameter list to filter out other - * user autohome shares. - */ -static void -smb_share_total_info(door_handle_t dhdl, smb_share_enum_t *shr_enum_info, - short *tot_shares_num, smb_user_t *user) -{ - uint64_t iterator; - lmshare_info_t *si; - struct lmshare_info *auto_si; - int more_room = 1; - - si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP); - auto_si = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP); - - *tot_shares_num = 0; - shr_enum_info->sei_count = 0; - shr_enum_info->sei_infolen = 0; - shr_enum_info->sei_cmntlen = 0; - - if (smb_share_add_autohome(dhdl, user->u_name, auto_si)) { - (*tot_shares_num)++; - more_room = smb_share_update_info(dhdl, auto_si, shr_enum_info); - } - - iterator = lmshrd_open_iterator(dhdl, LMSHRM_ALL); - if (iterator == 0) { - kmem_free(si, sizeof (lmshare_info_t)); - kmem_free(auto_si, sizeof (struct lmshare_info)); - return; - } - - /* check for door errors */ - if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { - (void) lmshrd_close_iterator(dhdl, iterator); - kmem_free(si, sizeof (lmshare_info_t)); - kmem_free(auto_si, sizeof (struct lmshare_info)); - return; - } - - while (*si->share_name != 0) { - if (smb_share_skip_share(si)) { - /* check for door errors */ - if (lmshrd_iterate(dhdl, iterator, si) != - NERR_Success) { - (void) lmshrd_close_iterator(dhdl, iterator); - kmem_free(si, sizeof (lmshare_info_t)); - kmem_free(auto_si, - sizeof (struct lmshare_info)); - return; - } - continue; - } - - (*tot_shares_num)++; - - if (more_room) { - more_room = smb_share_update_info(dhdl, si, - shr_enum_info); - } - - /* check for door errors */ - if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { - (void) lmshrd_close_iterator(dhdl, iterator); - kmem_free(si, sizeof (lmshare_info_t)); - kmem_free(auto_si, sizeof (struct lmshare_info)); - return; - } - } - - (void) lmshrd_close_iterator(dhdl, iterator); - kmem_free(si, sizeof (lmshare_info_t)); - kmem_free(auto_si, sizeof (struct lmshare_info)); -} - -/* - * smb_encode_SHARE_INFO_1 - * - * This function is extracted from smb_emit_SHARE_INFO_1 and only - * encodes fixed part of SHARE_INFO_1 structure. - * - * The function returns -1 if encoding fails and 0 on success. - */ -static int -smb_encode_SHARE_INFO_1(struct mbuf_chain *output, unsigned char *name, - uint16_t type, int cmnt_len) -{ - if (smb_emit_SHARE_INFO_0(output, name) < 0) - return (-1); - (void) smb_encode_mbc(output, ".wl", type, cmnt_len); - return (0); -} - -/* - * collect_shares_info - * - * This function encodes information of shares_num of shares - * into data_mb and cmnt_str. - * - * Added SMB user object to the parameter list to filter out other - * user autohome shares. - * - */ -static void -collect_shares_info(door_handle_t dhdl, uint64_t iterator, int shares_num, - struct mbuf_chain *data_mb, char *cmnt_str, int *cmnt_len, smb_user_t *user, - int first_resp) -{ - int i = 0; - lmshare_info_t *si; - struct lmshare_info *tsi; - int is_special; - - si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP); - tsi = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP); - - if (first_resp && smb_share_add_autohome(dhdl, user->u_name, tsi)) { - if (smb_encode_SHARE_INFO_1(data_mb, - (unsigned char *)tsi->share_name, - tsi->stype, *cmnt_len) == 0) { - (void) memcpy(cmnt_str+(*cmnt_len), - tsi->comment, strlen(tsi->comment)+1); - (*cmnt_len) += (strlen(tsi->comment) + 1); - i++; - } - } - - /* check for door errors */ - if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { - kmem_free(si, sizeof (lmshare_info_t)); - kmem_free(tsi, sizeof (struct lmshare_info)); - return; - } - - while ((i < shares_num) && (*si->share_name != 0)) { - if (smb_share_skip_share(si)) { - goto next; - } - - - is_special = lmshrd_is_special(dhdl, si->share_name); - /* check for door errors */ - if (is_special == NERR_InternalError) { - kmem_free(si, sizeof (lmshare_info_t)); - kmem_free(tsi, sizeof (struct lmshare_info)); - return; - } - - if (is_special) { - si->stype |= STYPE_HIDDEN; - if (smb_encode_SHARE_INFO_1(data_mb, - (unsigned char *)si->share_name, - si->stype, *cmnt_len) < 0) { - goto next; - } - cmnt_str[*cmnt_len] = '\0'; - (*cmnt_len)++; - } else { - if (smb_encode_SHARE_INFO_1(data_mb, - (unsigned char *)si->share_name, si->stype, - *cmnt_len) < 0) { - goto next; - } - (void) memcpy(cmnt_str+(*cmnt_len), si->comment, - strlen(si->comment)+1); - (*cmnt_len) += (strlen(si->comment) + 1); - } - - next: - /* check for door errors */ - if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { - kmem_free(si, sizeof (lmshare_info_t)); - kmem_free(tsi, sizeof (struct lmshare_info)); - return; - } - } - kmem_free(si, sizeof (lmshare_info_t)); - kmem_free(tsi, sizeof (struct lmshare_info)); -} - int smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) { door_handle_t dhdl = sr->sr_server->sv_lmshrd; - smb_share_enum_t shr_enum_info; - short left_shares_cnt; /* Number of shares not sent yet */ - - /* - * Number of shares that should be sent - * in the current response packet. - * It can be a number between 0 and - * max_share_scnt. - */ - short shares_scnt; - - /* - * Maximum number of shares that can be - * sent in one response packet regarding - * the maximum negotiated buffer size - * for SMB messages. - */ - short max_shares_per_packet; - - /* - * Total number of shares on the server - * that their name is not greater than - * MAX_SHARE_NAME_LEN - */ - short shares_tot_num; - - /* - * Size of total data (info + cmnt) - * that should be sent for client - */ - int shares_tot_byte; - - /* - * Maximum size of data that can be - * sent in one SMB transaction response - * according to the maximum negotiated - * buffer size for SMB packets - */ - int data_buf_limit; - - /* - * Number of comment bytes that will - * be sent in the current response - */ - uint16_t cmnt_scnt; /* * Number of data bytes that will @@ -1215,9 +777,6 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) /* data and parameter displacement */ uint16_t data_disp, param_disp; - /* return status by the 1st reply */ - uint16_t ret_stat; - /* parameter and data offset and pad */ int param_off, param_pad, data_off, data_pad; @@ -1227,19 +786,17 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) */ int tot_packet_bytes; - char first_resp; - uint16_t opcode, level, cli_bufsize; - unsigned char *r_fmt; - char fmt[10]; - uint64_t iterator; - char *cmnt_str, *cmnt_start; - int cmnt_len; + boolean_t first_resp; + + char fmt[16]; struct mbuf_chain reply; - smb_user_t *user; - size_t cmnt_size; - user = sr->uid_user; - ASSERT(user); + uint16_t level; + uint16_t pkt_bufsize; + smb_enumshare_info_t esi; + char *sent_buf; + + ASSERT(sr->uid_user); /* * Initialize the mbuf chain of reply to zero. If it is not @@ -1247,98 +804,62 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) */ bzero(&reply, sizeof (struct mbuf_chain)); - if (smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr, - &opcode, &r_fmt, &r_fmt, &level, &cli_bufsize) != 0) + if (smb_decode_mbc(&xa->req_param_mb, "ww", &level, + &esi.es_bufsize) != 0) return (SDRC_NOT_IMPLEMENTED); if (level != 1) { + /* + * Only level 1 is valid for NetShareEnum + * None of the error codes in the spec are meaningful + * here. This error code is returned by Windows. + */ (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", - NERR_BadTransactConfig, 0, 0, 0); + ERROR_INVALID_LEVEL, 0, 0, 0); return (SDRC_SUCCESS); } - n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */ - n_param = 8; - data_buf_limit = sr->session->smb_msg_size - - (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param); + esi.es_buf = kmem_zalloc(esi.es_bufsize, KM_SLEEP); + esi.es_username = sr->uid_user->u_name; + (void) smb_kshare_enum(dhdl, &esi); - shr_enum_info.sei_bufsize = cli_bufsize; - smb_share_total_info(dhdl, &shr_enum_info, &shares_tot_num, user); - - shares_tot_byte = shr_enum_info.sei_infolen + shr_enum_info.sei_cmntlen; - - /* Check buffer to have enough space */ - if (shares_tot_byte == 0) { + /* client buffer size is not big enough to hold any shares */ + if (esi.es_nsent == 0) { (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", - ERROR_NOT_ENOUGH_MEMORY, 0, 0, 0); + ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal); + kmem_free(esi.es_buf, esi.es_bufsize); return (SDRC_SUCCESS); } - max_shares_per_packet = data_buf_limit / SHARE_INFO_1_SIZE; - - shares_scnt = (shr_enum_info.sei_count > max_shares_per_packet) - ? max_shares_per_packet : shr_enum_info.sei_count; - - cmnt_size = shr_enum_info.sei_cmntlen * sizeof (char); - cmnt_str = kmem_alloc(cmnt_size, KM_SLEEP); - cmnt_len = 0; - /* save start of buffer to free it at the end of function */ - cmnt_start = cmnt_str; - - iterator = lmshrd_open_iterator(dhdl, LMSHRM_ALL); - - if (iterator == NULL) { - kmem_free(cmnt_start, cmnt_size); - return (SDRC_DROP_VC); - } - /* * The rep_setup_mb is already initialized in smb_trans_dispatch(). * Calling MBC_INIT() will initialized the structure and so the * pointer to the mbuf chains will be lost. Therefore, we need * to free the resources before calling MBC_INIT() again. */ + n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */ m_freem(xa->rep_setup_mb.chain); MBC_INIT(&xa->rep_setup_mb, n_setup * 2); - left_shares_cnt = shr_enum_info.sei_count; + n_param = 8; + pkt_bufsize = sr->session->smb_msg_size - + (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param); + tot_data_scnt = 0; - cmnt_scnt = 0; + sent_buf = esi.es_buf; + first_resp = B_TRUE; - first_resp = 1; - while (tot_data_scnt < shares_tot_byte) { - /* - * Calling MBC_INIT() will initialized the structure and so the - * pointer to the mbuf chains will be lost. Therefore, we need - * to free the resources if any before calling MBC_INIT(). - */ + while (tot_data_scnt < esi.es_datasize) { + data_scnt = esi.es_datasize - tot_data_scnt; + if (data_scnt > pkt_bufsize) + data_scnt = pkt_bufsize; m_freem(xa->rep_data_mb.chain); - MBC_INIT(&xa->rep_data_mb, data_buf_limit); - collect_shares_info(dhdl, iterator, - shares_scnt, &xa->rep_data_mb, cmnt_str, &cmnt_len, user, - first_resp); - data_scnt = shares_scnt * SHARE_INFO_1_SIZE; - left_shares_cnt -= shares_scnt; - if (left_shares_cnt < max_shares_per_packet) - shares_scnt = left_shares_cnt; - if (left_shares_cnt == 0) { - /* - * Now send comments. - * Append comments to the end of share_info_1 - * structures. - */ - cmnt_scnt = data_buf_limit - - MBC_LENGTH(&xa->rep_data_mb); - if (cmnt_scnt > shr_enum_info.sei_cmntlen) { - /*LINTED E_ASSIGN_NARROW_CONV*/ - cmnt_scnt = shr_enum_info.sei_cmntlen; - } - (void) sprintf(fmt, "%dc", cmnt_scnt); - (void) smb_encode_mbc(&xa->rep_data_mb, fmt, cmnt_str); - cmnt_str += cmnt_scnt; - shr_enum_info.sei_cmntlen -= cmnt_scnt; - } - data_scnt += cmnt_scnt; + MBC_INIT(&xa->rep_data_mb, data_scnt); + + (void) sprintf(fmt, "%dc", data_scnt); + (void) smb_encode_mbc(&xa->rep_data_mb, fmt, sent_buf); + + sent_buf += data_scnt; tot_data_scnt += data_scnt; /* Only the 1st response packet contains parameters */ @@ -1347,22 +868,15 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN; param_disp = (first_resp) ? 0 : n_param; - /* - * Calling MBC_INIT() will initialized the structure and so the - * pointer to the mbuf chains will be lost. Therefore, we need - * to free the resources if any before calling MBC_INIT(). - */ m_freem(xa->rep_param_mb.chain); MBC_INIT(&xa->rep_param_mb, param_scnt); + if (first_resp) { - first_resp = 0; - /* Prepare parameters for the 1st response packet */ - ret_stat = (shares_tot_num > shr_enum_info.sei_count) - ? ERROR_MORE_DATA : 0; + first_resp = B_FALSE; (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", - ret_stat, -shr_enum_info.sei_infolen, - shr_enum_info.sei_count, - shares_tot_num); + (esi.es_ntotal > esi.es_nsent) + ? ERROR_MORE_DATA : 0, + 0, esi.es_nsent, esi.es_ntotal); } data_pad = (param_off + n_param) & 1; /* Pad to short */ @@ -1380,10 +894,10 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) */ m_freem(reply.chain); MBC_INIT(&reply, SMB_HEADER_ED_LEN - + sizeof (uchar_t) /* word parameters count */ - + 10*sizeof (ushort_t) /* word parameters */ - + n_setup*sizeof (ushort_t) /* setup parameters */ - + sizeof (ushort_t) /* total data byte count */ + + sizeof (uint8_t) /* word parameters count */ + + 10*sizeof (uint16_t) /* word parameters */ + + n_setup*sizeof (uint16_t) /* setup parameters */ + + sizeof (uint16_t) /* total data byte count */ + tot_packet_bytes); (void) smb_encode_mbc(&reply, SMB_HEADER_ED_FMT, @@ -1404,7 +918,7 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) "b ww 2. www www b . C w #. C #. C", 10 + n_setup, /* wct */ n_param, /* Total Parameter Bytes */ - shares_tot_byte, /* Total Data Bytes */ + esi.es_datasize, /* Total Data Bytes */ param_scnt, /* Total Parameter Bytes this buffer */ param_off, /* Param offset from header start */ param_disp, /* Param displacement */ @@ -1425,82 +939,61 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) (void) smb_session_send(sr->session, 0, &reply); } - (void) lmshrd_close_iterator(dhdl, iterator); - kmem_free(cmnt_start, cmnt_size); + kmem_free(esi.es_buf, esi.es_bufsize); return (SDRC_NO_REPLY); } int -smb_trans_net_share_get_info(smb_request_t *sr, struct smb_xa *xa) +smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa) { - uint16_t opcode, level, max_bytes, access; - uint32_t type; - unsigned char *req_fmt; - unsigned char *rep_fmt; + uint16_t level, max_bytes, access; struct mbuf_chain str_mb; char *share; - char *path; char *password; - char *comment; lmshare_info_t si; - int shr_found; + int rc; - if (smb_decode_mbc(&xa->req_param_mb, "%wsss(lev)w(size)w", sr, - &opcode, &req_fmt, &rep_fmt, &share, &level, &max_bytes) != 0) + if (smb_decode_mbc(&xa->req_param_mb, "%sww", sr, + &share, &level, &max_bytes) != 0) return (SDRC_NOT_IMPLEMENTED); (void) utf8_strlwr(share); - shr_found = lmshrd_getinfo(sr->sr_server->sv_lmshrd, share, &si); - if (strcmp(share, "ipc$") == 0) { - type = STYPE_IPC; - path = ""; - password = ""; - access = SHARE_ACCESS_ALL; - } else if (shr_found) { - path = si.directory; - type = STYPE_DISKTREE; - if (path[strlen(path)] == '$') - type |= STYPE_HIDDEN; - password = ""; - access = SHARE_ACCESS_ALL; - } else { - /* We have no idea what this share is... */ + rc = smb_kshare_getinfo(sr->sr_server->sv_lmshrd, share, &si); + if ((rc != NERR_Success) || (si.mode & LMSHRM_LONGNAME)) { (void) smb_encode_mbc(&xa->rep_param_mb, "www", NERR_NetNameNotFound, 0, 0); return (SDRC_SUCCESS); } - if (shr_found) - comment = si.comment; - else - comment = ""; - + access = SHARE_ACCESS_ALL; password = ""; MBC_INIT(&str_mb, max_bytes); switch (level) { case 0 : - (void) smb_emit_SHARE_INFO_0(&xa->rep_data_mb, - (unsigned char *)share); + (void) smb_encode_mbc(&xa->rep_data_mb, "13c", si.oem_name); break; case 1 : - (void) smb_emit_SHARE_INFO_1(&xa->rep_data_mb, &str_mb, - (unsigned char *)share, type, - (unsigned char *)comment); + smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb, + si.oem_name, si.stype, si.comment); break; case 2 : - smb_emit_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr, - (unsigned char *)share, type, (unsigned char *)comment, - access, path, password); + smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr, + si.oem_name, si.stype, si.comment, access, si.directory, + password); + break; + default: + (void) smb_encode_mbc(&xa->rep_param_mb, "www", + ERROR_INVALID_LEVEL, 0, 0); m_freem(str_mb.chain); return (SDRC_NOT_IMPLEMENTED); } - (void) smb_encode_mbc(&xa->rep_param_mb, "www", 0, + (void) smb_encode_mbc(&xa->rep_param_mb, "www", NERR_Success, -MBC_LENGTH(&xa->rep_data_mb), MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); (void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb); @@ -1509,17 +1002,15 @@ smb_trans_net_share_get_info(smb_request_t *sr, struct smb_xa *xa) } int -smb_trans_net_workstation_get_info(struct smb_request *sr, struct smb_xa *xa) +smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa) { - uint16_t opcode, level, max_bytes; - unsigned char *req_fmt; - unsigned char *rep_fmt; + uint16_t level, max_bytes; struct mbuf_chain str_mb; char *domain; char *hostname; - if ((smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr, - &opcode, &req_fmt, &rep_fmt, &level, &max_bytes) != 0) || + if ((smb_decode_mbc(&xa->req_param_mb, "ww", + &level, &max_bytes) != 0) || (level != 10)) { (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", NERR_BadTransactConfig, 0, 0, 0); @@ -1554,18 +1045,13 @@ smb_trans_net_workstation_get_info(struct smb_request *sr, struct smb_xa *xa) } int -smb_trans_net_user_get_info(struct smb_request *sr, struct smb_xa *xa) +smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa) { - uint16_t opcode, level, max_bytes; - unsigned char *req_fmt; - unsigned char *rep_fmt; + uint16_t level, max_bytes; unsigned char *user; int rc; - rc = smb_decode_mbc(&xa->req_param_mb, "%wssww", sr, - &opcode, - &req_fmt, - &rep_fmt, + rc = smb_decode_mbc(&xa->req_param_mb, "%sww", sr, &user, &level, &max_bytes); @@ -1579,104 +1065,48 @@ smb_trans_net_user_get_info(struct smb_request *sr, struct smb_xa *xa) } smb_sdrc_t -smb_trans_server_get_info(struct smb_request *sr, struct smb_xa *xa) +smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa) { - uint16_t opcode, level, buf_size; - char *req_fmt; - char *rep_fmt; + uint16_t level, buf_size; + uint16_t avail_data, max_data; char server_name[16]; struct mbuf_chain str_mb; - char *hostname; - char *comment; - if (smb_decode_mbc(&xa->req_param_mb, "%wssww", sr, - &opcode, &req_fmt, &rep_fmt, &level, &buf_size) != 0) { + if (smb_decode_mbc(&xa->req_param_mb, "ww", &level, &buf_size) != 0) return (SDRC_ERROR); - } - comment = sr->sr_cfg->skc_system_comment; - hostname = sr->sr_cfg->skc_hostname; + max_data = MBC_MAXBYTES(&xa->rep_data_mb); MBC_INIT(&str_mb, buf_size); bzero(server_name, sizeof (server_name)); - (void) strncpy(server_name, hostname, sizeof (server_name)); + (void) strncpy(server_name, sr->sr_cfg->skc_hostname, + sizeof (server_name)); + /* valid levels are 0 and 1 */ switch (level) { case 0: (void) smb_encode_mbc(&xa->rep_data_mb, "16c", server_name); break; + case 1: - (void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */ + (void) smb_encode_mbc(&str_mb, "s", + sr->sr_cfg->skc_system_comment); (void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name, SMB_VERSION_MAJOR, SMB_VERSION_MINOR, - MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); - (void) smb_encode_mbc(&str_mb, "s", comment); - break; - case 2: - /* B16BBDzDDDWWzWWWWWWWB21BzWWWWWWWWWWWWWWWWWWWWWWz */ - (void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */ - /* B16BBDz */ - (void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name, - SMB_VERSION_MAJOR, - SMB_VERSION_MINOR, MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); - (void) smb_encode_mbc(&str_mb, "s", comment); - (void) smb_encode_mbc(&xa->rep_data_mb, "lllwwl", - (uint32_t)1, - (uint32_t)2, - (uint32_t)3, - (uint16_t)4, - (uint16_t)5, - MBC_LENGTH(&str_mb)); - (void) smb_encode_mbc(&str_mb, "s", "str1"); - (void) smb_encode_mbc(&xa->rep_data_mb, "wwwwwww21cbl", - (uint16_t)6, - (uint16_t)7, - (uint16_t)8, - (uint16_t)9, - (uint16_t)10, - (uint16_t)11, - (uint16_t)12, - "21 byte comment ", - (unsigned char)13, - MBC_LENGTH(&str_mb)); - (void) smb_encode_mbc(&str_mb, "s", "str2"); - (void) smb_encode_mbc(&xa->rep_data_mb, - "wwwwwwwwwwwwwwwwwwwwwwl", - (uint16_t)14, - (uint16_t)15, - (uint16_t)16, - (uint16_t)17, - (uint16_t)18, - (uint16_t)19, - (uint16_t)20, - (uint16_t)21, - (uint16_t)22, - (uint16_t)23, - (uint16_t)24, - (uint16_t)25, - (uint16_t)26, - (uint16_t)27, - (uint16_t)28, - (uint16_t)29, - (uint16_t)20, - (uint16_t)31, - (uint16_t)32, - (uint16_t)33, - (uint16_t)34, - (uint16_t)35, - MBC_LENGTH(&str_mb)); - (void) smb_encode_mbc(&str_mb, "s", "str3"); + MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb)); break; + default: + (void) smb_encode_mbc(&xa->rep_param_mb, "www", + ERROR_INVALID_LEVEL, 0, 0); m_freem(str_mb.chain); - return (SDRC_NOT_IMPLEMENTED); + return (SDRC_SUCCESS); } - (void) smb_encode_mbc(&xa->rep_param_mb, "www", 0, - -MBC_LENGTH(&xa->rep_data_mb), - (MBC_LENGTH(&xa->rep_data_mb)) + - (MBC_LENGTH(&str_mb))); + avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb); + (void) smb_encode_mbc(&xa->rep_param_mb, "www", + NERR_Success, max_data - avail_data, avail_data); (void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb); m_freem(str_mb.chain); return (SDRC_SUCCESS); @@ -2011,30 +1441,29 @@ smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) xa->xa_smb_trans_name, MAILSLOT_MSBROWSE) != 0)) goto trans_err_not_supported; - if ((rc = smb_decode_mbc(&xa->req_param_mb, "%wss\b", sr, + if ((rc = smb_decode_mbc(&xa->req_param_mb, "%wss", sr, &opcode, &req_fmt, &rep_fmt)) != 0) goto trans_err_not_supported; - /* for now, only respond to the */ switch (opcode) { case API_WshareEnum: rc = smb_trans_net_share_enum(sr, xa); break; case API_WshareGetInfo: - rc = smb_trans_net_share_get_info(sr, xa); + rc = smb_trans_net_share_getinfo(sr, xa); break; case API_WserverGetInfo: - rc = smb_trans_server_get_info(sr, xa); + rc = smb_trans_net_server_getinfo(sr, xa); break; case API_WUserGetInfo: - rc = smb_trans_net_user_get_info(sr, xa); + rc = smb_trans_net_user_getinfo(sr, xa); break; case API_WWkstaGetInfo: - rc = smb_trans_net_workstation_get_info(sr, xa); + rc = smb_trans_net_workstation_getinfo(sr, xa); break; case API_NetServerEnum2: diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_tree.c b/usr/src/uts/common/fs/smbsrv/smb_common_tree.c index 97fb7c7bcd..715b3b1213 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_tree.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_tree.c @@ -186,7 +186,6 @@ smbsr_setup_share(struct smb_request *sr, char *sharename, int32_t stype, smb_sid_t *sid; fsvol_attr_t vol_attr; smb_attr_t attr; - int is_admin; smb_user_t *user = sr->uid_user; cred_t *u_cred; @@ -233,18 +232,18 @@ smbsr_setup_share(struct smb_request *sr, char *sharename, int32_t stype, return (ERRaccess); } + if (smb_kshare_getinfo(sr->sr_server->sv_lmshrd, sharename, &si) != + NERR_Success) { + (void) strlcpy(errmsg, "share not found", SMB_TREE_EMSZ); + return (ERRinvnetname); + } + /* * Handle the default administration shares: C$, D$ etc. * Only a user with admin rights is allowed to map these * shares. */ - is_admin = lmshrd_is_admin(sr->sr_server->sv_lmshrd, sharename); - if (is_admin == NERR_InternalError) { - (void) strlcpy(errmsg, "internal error", SMB_TREE_EMSZ); - return (ERRaccess); - } - - if (is_admin) { + if (si.mode & LMSHRM_ADMIN) { sid = smb_sid_fromstr(ADMINISTRATORS_SID); if (sid) { rc = smb_cred_is_member(u_cred, sid); @@ -257,11 +256,6 @@ smbsr_setup_share(struct smb_request *sr, char *sharename, int32_t stype, } } - if (lmshrd_getinfo(sr->sr_server->sv_lmshrd, sharename, &si) != - NERR_Success) { - (void) strlcpy(errmsg, "share not found", SMB_TREE_EMSZ); - return (ERRinvnetname); - } resource = si.directory; sr->arg.tcon.service = "A:"; diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c index cb92140574..d5a4a3e550 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c @@ -2594,6 +2594,27 @@ smb_fsop_frlock(smb_node_t *node, smb_lock_t *lock, boolean_t unlock, flock64_t bf; int flag = F_REMOTELOCK; + /* + * VOP_FRLOCK() will not be called if: + * + * 1) The lock has a range of zero bytes. The semantics of Windows and + * POSIX are different. In the case of POSIX it asks for the locking + * of all the bytes from the offset provided until the end of the + * file. In the case of Windows a range of zero locks nothing and + * doesn't conflict with any other lock. + * + * 2) The lock rolls over (start + lenght < start). Solaris will assert + * if such a request is submitted. This will not create + * incompatibilities between POSIX and Windows. In the Windows world, + * if a client submits such a lock, the server will not lock any + * bytes. Interestingly if the same lock (same offset and length) is + * resubmitted Windows will consider that there is an overlap and + * the granting rules will then apply. + */ + if ((lock->l_length == 0) || + ((lock->l_start + lock->l_length - 1) < lock->l_start)) + return (0); + bzero(&bf, sizeof (bf)); if (unlock) { diff --git a/usr/src/uts/common/fs/smbsrv/smb_kshare.c b/usr/src/uts/common/fs/smbsrv/smb_kshare.c new file mode 100644 index 0000000000..c67886af17 --- /dev/null +++ b/usr/src/uts/common/fs/smbsrv/smb_kshare.c @@ -0,0 +1,311 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Kernel door client for LanMan share management. + */ + +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/cmn_err.h> +#include <sys/door.h> +#include <smbsrv/lmshare.h> +#include <smbsrv/lmerr.h> +#include <smbsrv/smb_common_door.h> +#include <smbsrv/lmshare_door.h> +#include <smbsrv/smbinfo.h> + +static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *); + +/* + * smb_kshare_init + * + * This function is not MultiThread safe. The caller has to make sure only one + * thread calls this function. + */ +door_handle_t +smb_kshare_init(int door_id) +{ + return (door_ki_lookup(door_id)); +} + +/* + * smb_kshare_fini + * + * This function is not MultiThread safe. The caller has to make sure only one + * thread calls this function. + */ +void +smb_kshare_fini(door_handle_t dhdl) +{ + ASSERT(dhdl != NULL); + if (dhdl) + door_ki_rele(dhdl); +} + +uint32_t +smb_kshare_getinfo(door_handle_t dhdl, char *share_name, lmshare_info_t *si) +{ + door_arg_t arg; + char *buf; + unsigned int used; + smb_dr_ctx_t *dec_ctx; + smb_dr_ctx_t *enc_ctx; + int status; + uint32_t rc; + int opcode = LMSHR_DOOR_GETINFO; + + buf = kmem_alloc(LMSHR_DOOR_SIZE, KM_SLEEP); + + enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, opcode); + smb_dr_put_string(enc_ctx, share_name); + + if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { + cmn_err(CE_WARN, "smb_kshare_getinfo: Encode error %d", + status); + kmem_free(buf, LMSHR_DOOR_SIZE); + return (NERR_InternalError); + } + + arg.data_ptr = buf; + arg.data_size = used; + arg.desc_ptr = NULL; + arg.desc_num = 0; + arg.rbuf = buf; + arg.rsize = LMSHR_DOOR_SIZE; + + if (door_ki_upcall(dhdl, &arg) != 0) { + cmn_err(CE_WARN, "smb_kshare_getinfo: Door call failed"); + kmem_free(buf, LMSHR_DOOR_SIZE); + return (NERR_InternalError); + } + + dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); + if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { + kmem_free(buf, LMSHR_DOOR_SIZE); + return (NERR_InternalError); + } + + rc = smb_dr_get_uint32(dec_ctx); + smb_dr_get_lmshare(dec_ctx, si); + if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { + cmn_err(CE_WARN, "smb_kshare_getinfo: Decode error %d", + status); + rc = NERR_InternalError; + } + + kmem_free(buf, LMSHR_DOOR_SIZE); + return (rc); +} + +uint32_t +smb_kshare_enum(door_handle_t dhdl, smb_enumshare_info_t *enuminfo) +{ + door_arg_t arg; + char *door_buf; + int door_bufsz; + unsigned int used; + smb_dr_ctx_t *dec_ctx; + smb_dr_ctx_t *enc_ctx; + int status; + uint32_t rc; + int opcode = LMSHR_DOOR_ENUM; + + enuminfo->es_ntotal = enuminfo->es_nsent = 0; + + door_bufsz = enuminfo->es_bufsize + strlen(enuminfo->es_username) + + sizeof (smb_enumshare_info_t); + door_buf = kmem_alloc(door_bufsz, KM_SLEEP); + + enc_ctx = smb_dr_encode_start(door_buf, door_bufsz); + smb_dr_put_uint32(enc_ctx, opcode); + smb_dr_put_ushort(enc_ctx, enuminfo->es_bufsize); + smb_dr_put_string(enc_ctx, enuminfo->es_username); + + if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { + cmn_err(CE_WARN, "smb_kshare_enum: Encode error %d", status); + kmem_free(door_buf, door_bufsz); + return (NERR_InternalError); + } + + arg.data_ptr = door_buf; + arg.data_size = used; + arg.desc_ptr = NULL; + arg.desc_num = 0; + arg.rbuf = door_buf; + arg.rsize = door_bufsz; + + if (door_ki_upcall(dhdl, &arg) != 0) { + cmn_err(CE_WARN, "smb_kshare_enum: Door call failed"); + kmem_free(door_buf, door_bufsz); + return (NERR_InternalError); + } + + dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); + if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { + kmem_free(door_buf, door_bufsz); + return (NERR_InternalError); + } + + rc = smb_dr_get_uint32(dec_ctx); + if (rc == NERR_Success) { + enuminfo->es_ntotal = smb_dr_get_ushort(dec_ctx); + enuminfo->es_nsent = smb_dr_get_ushort(dec_ctx); + enuminfo->es_datasize = smb_dr_get_ushort(dec_ctx); + (void) smb_dr_get_buf(dec_ctx, + (unsigned char *)enuminfo->es_buf, + enuminfo->es_bufsize); + } + + if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { + cmn_err(CE_WARN, "smb_kshare_enum: Decode error %d", status); + rc = NERR_InternalError; + } + + kmem_free(door_buf, door_bufsz); + return (rc); +} + +/* + * This is a special interface that will be utilized by ZFS to cause + * a share to be added/removed + * + * arg is either a lmshare_info_t or share_name from userspace. + * It will need to be copied into the kernel. It is lmshare_info_t + * for add operations and share_name for delete operations. + */ +int +smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share) +{ + door_arg_t doorarg = { 0 }; + char *buf = NULL; + char *str = NULL; + int error; + int rc; + unsigned int used; + smb_dr_ctx_t *dec_ctx; + smb_dr_ctx_t *enc_ctx; + lmshare_info_t *lmshare = NULL; + int opcode; + + opcode = add_share == B_TRUE ? LMSHR_DOOR_ADD : LMSHR_DOOR_DELETE; + + buf = kmem_alloc(LMSHR_DOOR_SIZE, KM_SLEEP); + enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, opcode); + + switch (opcode) { + case LMSHR_DOOR_ADD: + lmshare = kmem_alloc(sizeof (lmshare_info_t), KM_SLEEP); + if (error = xcopyin(arg, lmshare, sizeof (lmshare_info_t))) { + kmem_free(lmshare, sizeof (lmshare_info_t)); + kmem_free(buf, LMSHR_DOOR_SIZE); + return (error); + } + smb_dr_put_lmshare(enc_ctx, lmshare); + break; + + case LMSHR_DOOR_DELETE: + str = kmem_alloc(MAXPATHLEN, KM_SLEEP); + if (error = copyinstr(arg, str, MAXPATHLEN, NULL)) { + kmem_free(str, MAXPATHLEN); + kmem_free(buf, LMSHR_DOOR_SIZE); + return (error); + } + smb_dr_put_string(enc_ctx, str); + kmem_free(str, MAXPATHLEN); + break; + } + + if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) { + kmem_free(buf, LMSHR_DOOR_SIZE); + if (lmshare) + kmem_free(lmshare, sizeof (lmshare_info_t)); + return (NERR_InternalError); + } + + doorarg.data_ptr = buf; + doorarg.data_size = used; + doorarg.rbuf = buf; + doorarg.rsize = LMSHR_DOOR_SIZE; + + error = door_ki_upcall(dhdl, &doorarg); + + if (error) { + kmem_free(buf, LMSHR_DOOR_SIZE); + if (lmshare) + kmem_free(lmshare, sizeof (lmshare_info_t)); + return (error); + } + + dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size); + if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { + kmem_free(buf, LMSHR_DOOR_SIZE); + if (lmshare) + kmem_free(lmshare, sizeof (lmshare_info_t)); + return (NERR_InternalError); + } + + rc = smb_dr_get_uint32(dec_ctx); + if (opcode == LMSHR_DOOR_ADD) + smb_dr_get_lmshare(dec_ctx, lmshare); + + if (smb_dr_decode_finish(dec_ctx)) + rc = NERR_InternalError; + + kmem_free(buf, LMSHR_DOOR_SIZE); + if (lmshare) + kmem_free(lmshare, sizeof (lmshare_info_t)); + + return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc); +} + +/* + * Return 0 upon success. Otherwise > 0 + */ +static int +smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx) +{ + int status = smb_dr_get_int32(dec_ctx); + int err; + + switch (status) { + case LMSHR_DOOR_SRV_SUCCESS: + return (0); + + case LMSHR_DOOR_SRV_ERROR: + err = smb_dr_get_uint32(dec_ctx); + cmn_err(CE_WARN, "%d: Encountered door server error %d", + opcode, err); + (void) smb_dr_decode_finish(dec_ctx); + return (err); + } + + ASSERT(0); + return (EINVAL); +} 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 d00dc52f46..fb144293a5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c +++ b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c @@ -450,6 +450,10 @@ smb_lock_range_overlap(struct smb_lock *lock, uint64_t start, uint64_t length) if (length == 0 || lock->l_length == 0) return (RANGE_NO_OVERLAP); + /* The following test is intended to catch roll over locks. */ + if ((start == lock->l_start) && (length == lock->l_length)) + return (RANGE_OVERLAP); + if (start < lock->l_start) { if (start + length > lock->l_start) return (RANGE_OVERLAP); diff --git a/usr/src/uts/common/fs/smbsrv/smb_mbuf_util.c b/usr/src/uts/common/fs/smbsrv/smb_mbuf_util.c index 44716ac8f0..a94a003941 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_mbuf_util.c +++ b/usr/src/uts/common/fs/smbsrv/smb_mbuf_util.c @@ -189,6 +189,12 @@ MBC_LENGTH(struct mbuf_chain *MBC) return (used); } +int +MBC_MAXBYTES(struct mbuf_chain *MBC) +{ + return (MBC->max_bytes); +} + void MBC_SETUP(struct mbuf_chain *MBC, uint32_t max_bytes) { diff --git a/usr/src/uts/common/fs/smbsrv/smb_node.c b/usr/src/uts/common/fs/smbsrv/smb_node.c index 759c6a8dc9..10ecb02af4 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_node.c +++ b/usr/src/uts/common/fs/smbsrv/smb_node.c @@ -864,7 +864,7 @@ smb_node_reset_delete_on_close(smb_node_t *node) } /* - * smb_node_share_check + * smb_node_open_check * * check file sharing rules for current open request * against all existing opens for a file. @@ -886,100 +886,30 @@ smb_node_open_check(struct smb_node *node, cred_t *cr, smb_llist_enter(&node->n_ofile_list, RW_READER); of = smb_llist_head(&node->n_ofile_list); while (of) { - status = smb_node_share_check(node, cr, desired_access, - share_access, of); - if (status == NT_STATUS_SHARING_VIOLATION) { + status = smb_ofile_open_check(of, cr, desired_access, + share_access); + + switch (status) { + case NT_STATUS_INVALID_HANDLE: + case NT_STATUS_SUCCESS: + of = smb_llist_next(&node->n_ofile_list, of); + break; + default: + ASSERT(status == NT_STATUS_SHARING_VIOLATION); smb_llist_exit(&node->n_ofile_list); return (status); } - of = smb_llist_next(&node->n_ofile_list, of); } - smb_llist_exit(&node->n_ofile_list); + smb_llist_exit(&node->n_ofile_list); return (NT_STATUS_SUCCESS); } -/* - * smb_open_share_check - * - * check file sharing rules for current open request - * against the given existing open. - * - * Returns NT_STATUS_SHARING_VIOLATION if there is any - * sharing conflict, otherwise returns NT_STATUS_SUCCESS. - */ uint32_t -smb_node_share_check( - struct smb_node *node, - cred_t *cr, - uint32_t desired_access, - uint32_t share_access, - smb_ofile_t *of) -{ - /* - * It appears that share modes are not relevant to - * directories, but this check will remain as it is not - * clear whether it was originally put here for a reason. - */ - if (node->attr.sa_vattr.va_type == VDIR) { - if (SMB_DENY_RW(of->f_share_access) && - (node->n_orig_uid != crgetuid(cr))) { - return (NT_STATUS_SHARING_VIOLATION); - } - - return (NT_STATUS_SUCCESS); - } - - /* if it's just meta data */ - if ((of->f_granted_access & FILE_DATA_ALL) == 0) - return (NT_STATUS_SUCCESS); - - /* - * Check requested share access against the - * open granted (desired) access - */ - if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) - return (NT_STATUS_SHARING_VIOLATION); - - if (SMB_DENY_READ(share_access) && - (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) - return (NT_STATUS_SHARING_VIOLATION); - - if (SMB_DENY_WRITE(share_access) && - (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) - return (NT_STATUS_SHARING_VIOLATION); - - /* check requested desired access against the open share access */ - if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) - return (NT_STATUS_SHARING_VIOLATION); - - if (SMB_DENY_READ(of->f_share_access) && - (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) - return (NT_STATUS_SHARING_VIOLATION); - - if (SMB_DENY_WRITE(of->f_share_access) && - (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) - return (NT_STATUS_SHARING_VIOLATION); - - return (NT_STATUS_SUCCESS); -} - -/* - * smb_rename_share_check - * - * An open file can be renamed if - * - * 1. isn't opened for data writing or deleting - * - * 2. Opened with "Deny Delete" share mode - * But not opened for data reading or executing - * (opened for accessing meta data) - */ - -DWORD smb_node_rename_check(struct smb_node *node) { - struct smb_ofile *open; + struct smb_ofile *of; + uint32_t status; ASSERT(node); ASSERT(node->n_magic == SMB_NODE_MAGIC); @@ -990,22 +920,20 @@ smb_node_rename_check(struct smb_node *node) */ smb_llist_enter(&node->n_ofile_list, RW_READER); - open = smb_llist_head(&node->n_ofile_list); - while (open) { - if (open->f_granted_access & - (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SHARING_VIOLATION); - } + of = smb_llist_head(&node->n_ofile_list); + while (of) { + status = smb_ofile_rename_check(of); - if ((open->f_share_access & FILE_SHARE_DELETE) == 0) { - if (open->f_granted_access & - (FILE_READ_DATA | FILE_EXECUTE)) { - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SHARING_VIOLATION); - } + switch (status) { + case NT_STATUS_INVALID_HANDLE: + case NT_STATUS_SUCCESS: + of = smb_llist_next(&node->n_ofile_list, of); + break; + default: + ASSERT(status == NT_STATUS_SHARING_VIOLATION); + smb_llist_exit(&node->n_ofile_list); + return (status); } - open = smb_llist_next(&node->n_ofile_list, open); } smb_llist_exit(&node->n_ofile_list); @@ -1019,27 +947,11 @@ smb_node_rename_check(struct smb_node *node) return (NT_STATUS_SUCCESS); } -/* - * smb_node_delete_check - * - * An open file can be deleted only if opened for - * accessing meta data. Share modes aren't important - * in this case. - * - * NOTE: there is another mechanism for deleting an - * open file that NT clients usually use. - * That's setting "Delete on close" flag for an open - * file. In this way the file will be deleted after - * last close. This flag can be set by SmbTrans2SetFileInfo - * with FILE_DISPOSITION_INFO information level. - * For setting this flag, the file should be opened by - * DELETE access in the FID that is passed in the Trans2 - * request. - */ -DWORD +uint32_t smb_node_delete_check(smb_node_t *node) { - smb_ofile_t *file; + smb_ofile_t *of; + uint32_t status; ASSERT(node); ASSERT(node->n_magic == SMB_NODE_MAGIC); @@ -1053,19 +965,20 @@ smb_node_delete_check(smb_node_t *node) */ smb_llist_enter(&node->n_ofile_list, RW_READER); - file = smb_llist_head(&node->n_ofile_list); - while (file) { - ASSERT(file->f_magic == SMB_OFILE_MAGIC); - if (file->f_granted_access & - (FILE_READ_DATA | - FILE_WRITE_DATA | - FILE_APPEND_DATA | - FILE_EXECUTE | - DELETE)) { + of = smb_llist_head(&node->n_ofile_list); + while (of) { + status = smb_ofile_delete_check(of); + + switch (status) { + case NT_STATUS_INVALID_HANDLE: + case NT_STATUS_SUCCESS: + of = smb_llist_next(&node->n_ofile_list, of); + break; + default: + ASSERT(status == NT_STATUS_SHARING_VIOLATION); smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SHARING_VIOLATION); + return (status); } - file = smb_llist_next(&node->n_ofile_list, file); } smb_llist_exit(&node->n_ofile_list); diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c index 5ee4fb0b56..cae9df9f8f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c +++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c @@ -746,3 +746,181 @@ smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access) return (NT_STATUS_SUCCESS); } + + +/* + * smb_ofile_open_check + * + * check file sharing rules for current open request + * against existing open instances of the same file + * + * Returns NT_STATUS_SHARING_VIOLATION if there is any + * sharing conflict, otherwise returns NT_STATUS_SUCCESS. + */ +uint32_t +smb_ofile_open_check( + smb_ofile_t *of, + cred_t *cr, + uint32_t desired_access, + uint32_t share_access) +{ + smb_node_t *node; + + ASSERT(of->f_magic == SMB_OFILE_MAGIC); + + node = of->f_node; + + mutex_enter(&of->f_mutex); + + if (of->f_state != SMB_OFILE_STATE_OPEN) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_INVALID_HANDLE); + } + + /* + * It appears that share modes are not relevant to + * directories, but this check will remain as it is not + * clear whether it was originally put here for a reason. + */ + if (node->attr.sa_vattr.va_type == VDIR) { + if (SMB_DENY_RW(of->f_share_access) && + (node->n_orig_uid != crgetuid(cr))) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SHARING_VIOLATION); + } + + mutex_exit(&of->f_mutex); + return (NT_STATUS_SUCCESS); + } + + /* if it's just meta data */ + if ((of->f_granted_access & FILE_DATA_ALL) == 0) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SUCCESS); + } + + /* + * Check requested share access against the + * open granted (desired) access + */ + if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SHARING_VIOLATION); + } + + if (SMB_DENY_READ(share_access) && + (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SHARING_VIOLATION); + } + + if (SMB_DENY_WRITE(share_access) && + (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SHARING_VIOLATION); + } + + /* check requested desired access against the open share access */ + if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SHARING_VIOLATION); + } + + if (SMB_DENY_READ(of->f_share_access) && + (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SHARING_VIOLATION); + } + + if (SMB_DENY_WRITE(of->f_share_access) && + (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SHARING_VIOLATION); + } + + mutex_exit(&of->f_mutex); + return (NT_STATUS_SUCCESS); +} + +/* + * smb_ofile_rename_check + * + * An open file can be renamed if + * + * 1. isn't opened for data writing or deleting + * + * 2. Opened with "Deny Delete" share mode + * But not opened for data reading or executing + * (opened for accessing meta data) + */ + +uint32_t +smb_ofile_rename_check(smb_ofile_t *of) +{ + ASSERT(of->f_magic == SMB_OFILE_MAGIC); + + mutex_enter(&of->f_mutex); + + if (of->f_state != SMB_OFILE_STATE_OPEN) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_INVALID_HANDLE); + } + + if (of->f_granted_access & + (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SHARING_VIOLATION); + } + + if ((of->f_share_access & FILE_SHARE_DELETE) == 0) { + if (of->f_granted_access & + (FILE_READ_DATA | FILE_EXECUTE)) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SHARING_VIOLATION); + } + } + + mutex_exit(&of->f_mutex); + return (NT_STATUS_SUCCESS); +} + +/* + * smb_ofile_delete_check + * + * An open file can be deleted only if opened for + * accessing meta data. Share modes aren't important + * in this case. + * + * NOTE: there is another mechanism for deleting an + * open file that NT clients usually use. + * That's setting "Delete on close" flag for an open + * file. In this way the file will be deleted after + * last close. This flag can be set by SmbTrans2SetFileInfo + * with FILE_DISPOSITION_INFO information level. + * For setting this flag, the file should be opened by + * DELETE access in the FID that is passed in the Trans2 + * request. + */ + +uint32_t +smb_ofile_delete_check(smb_ofile_t *of) +{ + ASSERT(of->f_magic == SMB_OFILE_MAGIC); + + mutex_enter(&of->f_mutex); + + if (of->f_state != SMB_OFILE_STATE_OPEN) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_INVALID_HANDLE); + } + + if (of->f_granted_access & + (FILE_READ_DATA | FILE_WRITE_DATA | + FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) { + mutex_exit(&of->f_mutex); + return (NT_STATUS_SHARING_VIOLATION); + } + + mutex_exit(&of->f_mutex); + return (NT_STATUS_SUCCESS); +} diff --git a/usr/src/uts/common/fs/smbsrv/smb_server.c b/usr/src/uts/common/fs/smbsrv/smb_server.c index 63846f7583..eaec0f8d39 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_server.c +++ b/usr/src/uts/common/fs/smbsrv/smb_server.c @@ -548,7 +548,7 @@ smb_server_start(struct smb_io_start *io_start) if (rc = smb_server_fsop_start(sv)) break; ASSERT(sv->sv_lmshrd == NULL); - sv->sv_lmshrd = lmshrd_kclient_init(io_start->lmshrd); + sv->sv_lmshrd = smb_kshare_init(io_start->lmshrd); if (sv->sv_lmshrd == NULL) break; if (rc = smb_kdoor_clnt_start(io_start->udoor)) @@ -1023,7 +1023,7 @@ smb_server_share(void *arg, boolean_t add_share) mutex_enter(&sv->sv_mutex); if (sv->sv_state == SMB_SERVER_STATE_RUNNING) { mutex_exit(&sv->sv_mutex); - rc = lmshrd_share_upcall(sv->sv_lmshrd, arg, add_share); + rc = smb_kshare_upcall(sv->sv_lmshrd, arg, add_share); } else { mutex_exit(&sv->sv_mutex); rc = EPERM; @@ -1172,7 +1172,7 @@ smb_server_stop(smb_server_t *sv) smb_winpipe_close(); smb_thread_stop(&sv->si_thread_timers); smb_kdoor_clnt_stop(); - lmshrd_kclient_fini(sv->sv_lmshrd); + smb_kshare_fini(sv->sv_lmshrd); smb_server_fsop_stop(sv); if (sv->sv_session) { smb_session_delete(sv->sv_session); diff --git a/usr/src/uts/common/fs/smbsrv/smb_share_kdoor_client.c b/usr/src/uts/common/fs/smbsrv/smb_share_kdoor_client.c deleted file mode 100644 index 23635d0561..0000000000 --- a/usr/src/uts/common/fs/smbsrv/smb_share_kdoor_client.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Kernel door client for LanMan share management. - */ - -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/cmn_err.h> -#include <sys/door.h> -#include <smbsrv/lmshare.h> -#include <smbsrv/lmerr.h> -#include <smbsrv/smb_common_door.h> -#include <smbsrv/lmshare_door.h> -#include <smbsrv/alloc.h> -#include <smbsrv/smbinfo.h> - -const char *lmshrd_desc[] = { - "", - "LmshrkOpenIter", - "LmshrkCloseIter", - "LmshrkIterate", - "LmshrkNumShares", - "", - "", - "LmshrkGetinfo", - "", - "", - "LmshrkExists", - "LmshrkIsSpecial", - "LmshrkIsRestricted", - "LmshrkIsAdmin", - "LmshrkIsValid", - "LmshrkIsDir", - "LmshrkList", - "LmshrkListTrans", - "LmshrkNumTrans", - "SmbGetKConfig", - NULL -}; - -static int lmshrd_door_check_srv_status(int, smb_dr_ctx_t *); - -/* - * lmshrd_kclient_init - * - * This function is not MultiThread safe. The caller has to make sure only one - * thread calls this function. - */ -door_handle_t -lmshrd_kclient_init(int door_id) -{ - return (door_ki_lookup(door_id)); -} - -/* - * lmshrd_kclient_fini - * - * This function is not MultiThread safe. The caller has to make sure only one - * thread calls this function. - */ -void -lmshrd_kclient_fini(door_handle_t dhdl) -{ - ASSERT(dhdl != NULL); - if (dhdl) - door_ki_rele(dhdl); -} - -uint64_t -lmshrd_open_iterator(door_handle_t dhdl, int mode) -{ - door_arg_t arg; - char *buf; - unsigned int used; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; - uint64_t lmshr_iter = 0; - - int opcode = LMSHR_DOOR_OPEN_ITERATOR; - - buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE); - if (!buf) - return (lmshr_iter); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); - smb_dr_put_int32(enc_ctx, mode); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - cmn_err(CE_WARN, "%s: Encode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (lmshr_iter); - } - - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_ki_upcall(dhdl, &arg) != 0) { - cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]); - MEM_FREE("lmshrd_kclient", buf); - return (lmshr_iter); - } - - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - MEM_FREE("lmshrd_kclient", buf); - return (lmshr_iter); - } - - lmshr_iter = smb_dr_get_lmshr_iterator(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - cmn_err(CE_WARN, "%s: Decode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (lmshr_iter); - } - - MEM_FREE("lmshrd_kclient", buf); - return (lmshr_iter); -} - -uint32_t -lmshrd_close_iterator(door_handle_t dhdl, uint64_t iterator) -{ - door_arg_t arg; - char *buf; - unsigned int used; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; - int opcode = LMSHR_DOOR_CLOSE_ITERATOR; - - buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE); - if (!buf) - return (NERR_InternalError); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); - smb_dr_put_lmshr_iterator(enc_ctx, iterator); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - cmn_err(CE_WARN, "%s: Encode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_ki_upcall(dhdl, &arg) != 0) { - cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - cmn_err(CE_WARN, "%s: Decode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - MEM_FREE("lmshrd_kclient", buf); - return (NERR_Success); -} - -uint32_t -lmshrd_iterate(door_handle_t dhdl, uint64_t iterator, lmshare_info_t *si) -{ - door_arg_t arg; - char *buf; - unsigned int used; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; - int opcode = LMSHR_DOOR_ITERATE; - - buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE); - if (!buf) - return (NERR_InternalError); - - bzero(si, sizeof (lmshare_info_t)); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); - smb_dr_put_lmshr_iterator(enc_ctx, iterator); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - cmn_err(CE_WARN, "%s: Encode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_ki_upcall(dhdl, &arg) != 0) { - cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - smb_dr_get_lmshare(dec_ctx, si); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - cmn_err(CE_WARN, "%s: Decode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - MEM_FREE("lmshrd_kclient", buf); - return (NERR_Success); -} - -int -lmshrd_num_shares(door_handle_t dhdl) -{ - door_arg_t arg; - char *buf; - unsigned int used; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; - uint32_t num_shares; - int opcode = LMSHR_DOOR_NUM_SHARES; - - buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE); - if (!buf) - return (-1); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - cmn_err(CE_WARN, "%s: Encode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (-1); - } - - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_ki_upcall(dhdl, &arg) != 0) { - cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]); - MEM_FREE("lmshrd_kclient", buf); - return (-1); - } - - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - MEM_FREE("lmshrd_kclient", buf); - return (-1); - } - - num_shares = smb_dr_get_uint32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - cmn_err(CE_WARN, "%s: Decode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (-1); - } - - MEM_FREE("lmshrd_kclient", buf); - return (num_shares); -} - -uint32_t -lmshrd_getinfo(door_handle_t dhdl, char *share_name, lmshare_info_t *si) -{ - door_arg_t arg; - char *buf; - unsigned int used; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - int status; - uint32_t rc; - int opcode = LMSHR_DOOR_GETINFO; - - buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE); - if (!buf) - return (NERR_InternalError); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); - smb_dr_put_string(enc_ctx, share_name); - - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - cmn_err(CE_WARN, "%s: Encode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_ki_upcall(dhdl, &arg) != 0) { - cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - rc = smb_dr_get_uint32(dec_ctx); - smb_dr_get_lmshare(dec_ctx, si); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - cmn_err(CE_WARN, "%s: Decode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - MEM_FREE("lmshrd_kclient", buf); - return (rc); -} - -int -lmshrd_check(door_handle_t dhdl, char *share_name, int opcode) -{ - door_arg_t arg; - char *buf; - unsigned int used; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - int status, rc; - - buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE); - if (!buf) - return (NERR_InternalError); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); - smb_dr_put_string(enc_ctx, share_name); - - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - cmn_err(CE_WARN, "%s: Encode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_ki_upcall(dhdl, &arg) != 0) { - cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - rc = smb_dr_get_int32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - cmn_err(CE_WARN, "%s: Decode error %d", - lmshrd_desc[opcode], status); - MEM_FREE("lmshrd_kclient", buf); - return (NERR_InternalError); - } - - MEM_FREE("lmshrd_kclient", buf); - return (rc); -} - -int -lmshrd_exists(door_handle_t dhdl, char *share_name) -{ - return (lmshrd_check(dhdl, share_name, LMSHR_DOOR_EXISTS)); -} - -int -lmshrd_is_special(door_handle_t dhdl, char *share_name) -{ - return (lmshrd_check(dhdl, share_name, LMSHR_DOOR_IS_SPECIAL)); -} - -int -lmshrd_is_restricted(door_handle_t dhdl, char *share_name) -{ - return (lmshrd_check(dhdl, share_name, LMSHR_DOOR_IS_RESTRICTED)); -} - -int -lmshrd_is_admin(door_handle_t dhdl, char *share_name) -{ - return (lmshrd_check(dhdl, share_name, LMSHR_DOOR_IS_ADMIN)); -} - -int -lmshrd_is_valid(door_handle_t dhdl, char *share_name) -{ - return (lmshrd_check(dhdl, share_name, LMSHR_DOOR_IS_VALID)); -} - -int -lmshrd_is_dir(door_handle_t dhdl, char *path) -{ - return (lmshrd_check(dhdl, path, LMSHR_DOOR_IS_DIR)); -} - -/* - * This is a special interface that will be utilized by ZFS to cause - * a share to be added/removed - * - * arg is either a lmshare_info_t or share_name from userspace. - * It will need to be copied into the kernel. It is lmshare_info_t - * for add operations and share_name for delete operations. - */ -int -lmshrd_share_upcall(door_handle_t dhdl, void *arg, boolean_t add_share) -{ - door_arg_t doorarg = { 0 }; - char *buf = NULL; - char *str = NULL; - int error; - int rc; - unsigned int used; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - lmshare_info_t *lmshare = NULL; - int opcode; - - opcode = add_share == B_TRUE ? LMSHR_DOOR_ADD : LMSHR_DOOR_DELETE; - - buf = MEM_MALLOC("lmshrd_share_upcall", LMSHR_DOOR_SIZE); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); - - switch (opcode) { - case LMSHR_DOOR_ADD: - lmshare = MEM_MALLOC("lmshrd_share_upcall", - sizeof (lmshare_info_t)); - - if (error = xcopyin(arg, lmshare, sizeof (lmshare_info_t))) { - MEM_FREE("lmshrd_share_upcall", lmshare); - MEM_FREE("lmshrd_share_upcall", buf); - return (error); - } - smb_dr_put_lmshare(enc_ctx, lmshare); - break; - - case LMSHR_DOOR_DELETE: - str = MEM_MALLOC("lmshrd_share_upcall", MAXPATHLEN); - if (error = copyinstr(arg, str, MAXPATHLEN, NULL)) { - MEM_FREE("lmshrd_share_upcall", buf); - MEM_FREE("lmshrd_share_upcall", str); - return (error); - } - smb_dr_put_string(enc_ctx, str); - MEM_FREE("lmshrd_share_upcall", str); - break; - } - - if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - MEM_FREE("lmshrd_share_upcall", buf); - if (lmshare) - MEM_FREE("lmshrd_share_upcall", lmshare); - return (NERR_InternalError); - } - - doorarg.data_ptr = buf; - doorarg.data_size = used; - doorarg.rbuf = buf; - doorarg.rsize = LMSHR_DOOR_SIZE; - - error = door_ki_upcall(dhdl, &doorarg); - - if (error) { - MEM_FREE("lmshrd_share_upcall", buf); - if (lmshare) - MEM_FREE("lmshrd_share_upcall", lmshare); - return (error); - } - - dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - MEM_FREE("lmshrd_share_upcall", buf); - if (lmshare) - MEM_FREE("lmshrd_share_upcall", lmshare); - return (NERR_InternalError); - } - - rc = smb_dr_get_uint32(dec_ctx); - if (opcode == LMSHR_DOOR_ADD) - smb_dr_get_lmshare(dec_ctx, lmshare); - - if (smb_dr_decode_finish(dec_ctx)) { - MEM_FREE("lmshrd_share_upcall", buf); - if (lmshare) - MEM_FREE("lmshrd_share_upcall", lmshare); - return (NERR_InternalError); - } - - MEM_FREE("lmshrd_share_upcall", buf); - if (lmshare) - MEM_FREE("lmshrd_share_upcall", lmshare); - return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc); -} - -/* - * Return 0 upon success. Otherwise, -1. - */ -static int -lmshrd_door_check_srv_status(int opcode, smb_dr_ctx_t *dec_ctx) -{ - int status = smb_dr_get_int32(dec_ctx); - int err; - int rc = -1; - - switch (status) { - case LMSHR_DOOR_SRV_SUCCESS: - rc = 0; - break; - - case LMSHR_DOOR_SRV_ERROR: - err = smb_dr_get_uint32(dec_ctx); - cmn_err(CE_WARN, "%s: Encountered door server error %d", - lmshrd_desc[opcode], err); - break; - - default: - cmn_err(CE_WARN, "%s: Unknown door server status", - lmshrd_desc[opcode]); - } - - if (rc != 0) { - if ((err = smb_dr_decode_finish(dec_ctx)) != 0) - cmn_err(CE_WARN, "%s: Decode error %d", - lmshrd_desc[opcode], err); - } - - return (rc); -} diff --git a/usr/src/uts/common/smbsrv/lmshare.h b/usr/src/uts/common/smbsrv/lmshare.h index 75a1a9e275..6f90d1b7e8 100644 --- a/usr/src/uts/common/smbsrv/lmshare.h +++ b/usr/src/uts/common/smbsrv/lmshare.h @@ -59,19 +59,41 @@ extern "C" { * Despite the fact that the MAXNAMELEN is 256, we only * support a maximum share name length of 15 characters. */ + +#define LMSHR_OEM_NAME_MAX 13 #define LMSHR_VALID_NAME_MAX 15 #define LMSHR_VALID_NAME_BUFSIZ 16 #define LMSHR_COMMENT_MAX (64 * MTS_MB_CHAR_MAX) /* + * struct SHARE_INFO_1 { + * char shi1_netname[13] + * char shi1_pad; + * unsigned short shi1_type + * char *shi1_remark; + * } + */ +#define SHARE_INFO_1_SIZE (LMSHR_OEM_NAME_MAX + 1 + 2 + 4) + +/* * Mode should be renamed to flags. * * LMSHRM_TRANS Transient share * LMSHRM_PERM Permanent share + * LMSHRM_AUTOHOME Autohome share. + * LMSHRM_LONGNAME Share name in OEM is longer than 13 chars + * LMSHRM_ADMIN Admin share + * + * All autohome shares are transient but not all transient shares are autohome. + * IPC$ and drive letter shares (e.g. d$, e$, etc) are transient but + * not autohome. */ -#define LMSHRM_TRANS 0x0001 -#define LMSHRM_PERM 0x0002 -#define LMSHRM_ALL (LMSHRM_TRANS | LMSHRM_PERM) +#define LMSHRM_TRANS 0x0001 +#define LMSHRM_PERM 0x0002 +#define LMSHRM_AUTOHOME 0x0004 +#define LMSHRM_LONGNAME 0x0008 +#define LMSHRM_ADMIN 0x0010 +#define LMSHRM_ALL (LMSHRM_TRANS | LMSHRM_PERM) #define LMSHR_PUBLISH 0 #define LMSHR_UNPUBLISH 1 @@ -86,20 +108,21 @@ extern "C" { * one is disconnected */ typedef struct lmshare_info { - char share_name[MAXNAMELEN]; - char directory[MAXPATHLEN]; - char comment[LMSHR_COMMENT_MAX]; - char container[MAXPATHLEN]; - int mode; - int stype; - int refcnt; + char share_name[MAXNAMELEN]; + char directory[MAXPATHLEN]; + char comment[LMSHR_COMMENT_MAX]; + char container[MAXPATHLEN]; + char oem_name[LMSHR_OEM_NAME_MAX]; + uint32_t mode; + uint32_t stype; + uint32_t refcnt; } lmshare_info_t; typedef struct lmshare_iterator { lmshare_info_t si; - HT_ITERATOR *iterator; - unsigned int iteration; - int mode; + HT_ITERATOR iterator; + uint32_t iteration; + uint32_t mode; } lmshare_iterator_t; #define LMSHARES_PER_REQUEST 10 @@ -109,6 +132,29 @@ typedef struct lmshare_list { } lmshare_list_t; /* + * This structure is a helper for building NetShareEnum response + * in user space and send it back down to kernel. + * + * es_username name of the user requesting the shares list which + * is used to detect if the user has any autohome + * es_bufsize size of the response buffer + * es_buf pointer to the response buffer + * es_ntotal total number of shares exported by server which + * their OEM names is less then 13 chars + * es_nsent number of shares that can fit in the specified buffer + * es_datasize actual data size (share's data) which was encoded + * in the response buffer + */ +typedef struct smb_enumshare_info { + char *es_username; + uint16_t es_bufsize; + char *es_buf; + uint16_t es_ntotal; + uint16_t es_nsent; + uint16_t es_datasize; +} smb_enumshare_info_t; + +/* * LanMan share API (for both SMB kernel module and GUI/CLI sub-system) * * NOTE: If any error is encounted by either the door server or client, @@ -124,11 +170,10 @@ typedef struct lmshare_list { */ int lmshare_start(void); void lmshare_stop(void); -lmshare_iterator_t *lmshare_open_iterator(int mode); -void lmshare_close_iterator(lmshare_iterator_t *); +void lmshare_init_iterator(lmshare_iterator_t *, uint32_t); lmshare_info_t *lmshare_iterate(lmshare_iterator_t *iterator); -DWORD lmshare_list(int offset, lmshare_list_t *list); +void lmshare_list(int offset, lmshare_list_t *list); DWORD lmshare_list_transient(int offset, lmshare_list_t *list); int lmshare_num_transient(void); @@ -147,17 +192,12 @@ int lmshare_is_restricted(char *share_name); int lmshare_is_admin(char *share_name); int lmshare_is_valid(char *share_name); int lmshare_is_dir(char *path); -/* XXX Move these 2 functions in mlsvc_util.h, after the libmlsvc cleanup */ -sa_group_t smb_get_smb_share_group(sa_handle_t handle); -void smb_build_lmshare_info(char *share_name, char *path, - sa_optionset_t opts, lmshare_info_t *si); -/* The following 3 functions are called by FSD user-space library */ DWORD lmshare_add_adminshare(char *volname, unsigned char drive); -uint64_t lmshrd_open_iterator(int); -DWORD lmshrd_close_iterator(uint64_t); -DWORD lmshrd_iterate(uint64_t iterator, lmshare_info_t *si); +sa_group_t smb_get_smb_share_group(sa_handle_t); +void smb_build_lmshare_info(char *, char *, sa_resource_t, lmshare_info_t *); + DWORD lmshrd_list(int offset, lmshare_list_t *list); DWORD lmshrd_list_transient(int offset, lmshare_list_t *list); DWORD lmshrd_num_transient(void); @@ -176,21 +216,11 @@ DWORD lmshrd_setinfo(lmshare_info_t *); #else -door_handle_t lmshrd_kclient_init(int); -void lmshrd_kclient_fini(door_handle_t); -uint64_t lmshrd_open_iterator(door_handle_t, int); -uint32_t lmshrd_close_iterator(door_handle_t, uint64_t); -uint32_t lmshrd_iterate(door_handle_t, uint64_t, lmshare_info_t *); -int lmshrd_num_shares(door_handle_t); -uint32_t lmshrd_getinfo(door_handle_t, char *, lmshare_info_t *); -int lmshrd_check(door_handle_t, char *, int); -int lmshrd_exists(door_handle_t, char *); -int lmshrd_is_special(door_handle_t, char *); -int lmshrd_is_restricted(door_handle_t, char *); -int lmshrd_is_admin(door_handle_t, char *); -int lmshrd_is_valid(door_handle_t, char *); -int lmshrd_is_dir(door_handle_t, char *); -int lmshrd_share_upcall(door_handle_t, void *, boolean_t); +door_handle_t smb_kshare_init(int); +void smb_kshare_fini(door_handle_t); +uint32_t smb_kshare_getinfo(door_handle_t, char *, lmshare_info_t *); +int smb_kshare_upcall(door_handle_t, void *, boolean_t); +uint32_t smb_kshare_enum(door_handle_t, smb_enumshare_info_t *); #endif diff --git a/usr/src/uts/common/smbsrv/lmshare_door.h b/usr/src/uts/common/smbsrv/lmshare_door.h index 4e4413bc9a..96f3110b1e 100644 --- a/usr/src/uts/common/smbsrv/lmshare_door.h +++ b/usr/src/uts/common/smbsrv/lmshare_door.h @@ -44,35 +44,27 @@ extern "C" { #define LMSHR_DOOR_VERSION 1 #define LMSHR_DOOR_COOKIE ((void*)(0xdeadbeef^LMSHR_DOOR_VERSION)) -#define LMSHR_DOOR_SIZE (sizeof (lmshare_list_t) + 32) +#define LMSHR_DOOR_SIZE (65 * 1024) /* * Door interface * * Define door operations */ -#define LMSHR_DOOR_OPEN_ITERATOR 1 -#define LMSHR_DOOR_CLOSE_ITERATOR 2 -#define LMSHR_DOOR_ITERATE 3 -#define LMSHR_DOOR_NUM_SHARES 4 -#define LMSHR_DOOR_DELETE 5 -#define LMSHR_DOOR_RENAME 6 -#define LMSHR_DOOR_GETINFO 7 -#define LMSHR_DOOR_ADD 8 -#define LMSHR_DOOR_SETINFO 9 -#define LMSHR_DOOR_EXISTS 10 -#define LMSHR_DOOR_IS_SPECIAL 11 -#define LMSHR_DOOR_IS_RESTRICTED 12 -#define LMSHR_DOOR_IS_ADMIN 13 -#define LMSHR_DOOR_IS_VALID 14 -#define LMSHR_DOOR_IS_DIR 15 -#define LMSHR_DOOR_LIST 16 - -#define SMB_GET_KCONFIG 17 - -void smb_load_kconfig(smb_kmod_cfg_t *); -void smb_dr_get_kconfig(smb_dr_ctx_t *, smb_kmod_cfg_t *); -void smb_dr_put_kconfig(smb_dr_ctx_t *, smb_kmod_cfg_t *); +#define LMSHR_DOOR_NUM_SHARES 1 +#define LMSHR_DOOR_DELETE 2 +#define LMSHR_DOOR_RENAME 3 +#define LMSHR_DOOR_GETINFO 4 +#define LMSHR_DOOR_ADD 5 +#define LMSHR_DOOR_SETINFO 6 +#define LMSHR_DOOR_EXISTS 7 +#define LMSHR_DOOR_IS_SPECIAL 8 +#define LMSHR_DOOR_IS_RESTRICTED 9 +#define LMSHR_DOOR_IS_ADMIN 10 +#define LMSHR_DOOR_IS_VALID 11 +#define LMSHR_DOOR_IS_DIR 12 +#define LMSHR_DOOR_LIST 13 +#define LMSHR_DOOR_ENUM 14 /* * Door server status @@ -100,9 +92,6 @@ void smb_dr_put_kconfig(smb_dr_ctx_t *, smb_kmod_cfg_t *); void smb_dr_get_lmshare(smb_dr_ctx_t *, lmshare_info_t *); void smb_dr_put_lmshare(smb_dr_ctx_t *, lmshare_info_t *); -uint64_t smb_dr_get_lmshr_iterator(smb_dr_ctx_t *); -void smb_dr_put_lmshr_iterator(smb_dr_ctx_t *, uint64_t); -void smb_dr_free_lmshr_iterator(smb_dr_ctx_t *); void smb_dr_get_lmshr_list(smb_dr_ctx_t *, lmshare_list_t *); void smb_dr_put_lmshr_list(smb_dr_ctx_t *, lmshare_list_t *); diff --git a/usr/src/uts/common/smbsrv/smb_common_door.h b/usr/src/uts/common/smbsrv/smb_common_door.h index 07ff2f1dd4..2b5ec20c1c 100644 --- a/usr/src/uts/common/smbsrv/smb_common_door.h +++ b/usr/src/uts/common/smbsrv/smb_common_door.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -103,12 +103,14 @@ extern DWORD smb_dr_get_dword(smb_dr_ctx_t *ctx); extern uint32_t smb_dr_get_uint32(smb_dr_ctx_t *ctx); extern int64_t smb_dr_get_int64(smb_dr_ctx_t *ctx); extern uint64_t smb_dr_get_uint64(smb_dr_ctx_t *ctx); +extern unsigned short smb_dr_get_ushort(smb_dr_ctx_t *ctx); extern void smb_dr_put_int32(smb_dr_ctx_t *ctx, int32_t num); extern void smb_dr_put_dword(smb_dr_ctx_t *ctx, DWORD num); extern void smb_dr_put_uint32(smb_dr_ctx_t *ctx, uint32_t num); extern void smb_dr_put_int64(smb_dr_ctx_t *ctx, int64_t num); extern void smb_dr_put_uint64(smb_dr_ctx_t *ctx, uint64_t num); +extern void smb_dr_put_ushort(smb_dr_ctx_t *ctx, unsigned short num); extern char *smb_dr_get_string(smb_dr_ctx_t *ctx); extern void smb_dr_put_string(smb_dr_ctx_t *ctx, char *buf); diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h index 8f40e24590..bb675ca115 100644 --- a/usr/src/uts/common/smbsrv/smb_kproto.h +++ b/usr/src/uts/common/smbsrv/smb_kproto.h @@ -385,8 +385,6 @@ int smb_node_in_crit(smb_node_t *node); uint32_t smb_node_open_check(smb_node_t *, cred_t *, uint32_t, uint32_t); -uint32_t smb_node_share_check(smb_node_t *, cred_t *, - uint32_t, uint32_t, smb_ofile_t *); DWORD smb_node_rename_check(smb_node_t *); DWORD smb_node_delete_check(smb_node_t *); @@ -532,6 +530,11 @@ void smb_ofile_close_all_by_pid(smb_tree_t *tree, uint16_t pid); void smb_ofile_set_flags(smb_ofile_t *of, uint32_t flags); void smb_ofile_close_timestamp_update(smb_ofile_t *of, uint32_t last_wtime); boolean_t smb_ofile_is_open(smb_ofile_t *of); +uint32_t smb_ofile_open_check(smb_ofile_t *, cred_t *, + uint32_t, uint32_t); +uint32_t smb_ofile_rename_check(smb_ofile_t *); +uint32_t smb_ofile_delete_check(smb_ofile_t *); + #define smb_ofile_granted_access(_of_) ((_of_)->f_granted_access) diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h index 99748042d1..89691295d7 100644 --- a/usr/src/uts/common/smbsrv/smb_ktypes.h +++ b/usr/src/uts/common/smbsrv/smb_ktypes.h @@ -375,6 +375,7 @@ typedef struct { } smb_xprt_t; int MBC_LENGTH(struct mbuf_chain *); +int MBC_MAXBYTES(struct mbuf_chain *); void MBC_SETUP(struct mbuf_chain *, uint32_t); void MBC_INIT(struct mbuf_chain *, uint32_t); void MBC_FLUSH(struct mbuf_chain *); diff --git a/usr/src/uts/common/smbsrv/smb_winpipe.h b/usr/src/uts/common/smbsrv/smb_winpipe.h index 4e4f383543..906979a63e 100755 --- a/usr/src/uts/common/smbsrv/smb_winpipe.h +++ b/usr/src/uts/common/smbsrv/smb_winpipe.h @@ -58,6 +58,9 @@ extern "C" { #define SMB_RPC_WRITE 3 #define SMB_RPC_FLUSH 4 +#define SMB_WINPIPE_MIN_REQ_SIZE (sizeof (uint64_t) + \ + (2 * sizeof (uint32_t)) + (2 * sizeof (uint16_t))) + typedef struct { uint64_t md_tid; /* caller's thread id */ uint16_t md_version; /* version number, start with 1 */ |