diff options
Diffstat (limited to 'usr/src/lib/libsmbfs')
-rw-r--r-- | usr/src/lib/libsmbfs/Makefile.com | 3 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/cflib.h | 4 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/netsmb/smb_lib.h | 5 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/netsmb/smbfs_api.h | 7 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.apple.descrip | 2 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.boris_popov.descrip | 2 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.bsd4.descrip | 2 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.microsoft.descrip | 2 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/connect.c | 75 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/ctx.c | 147 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/file.c | 3 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/iod_wk.c | 17 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/mapfile-vers | 5 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/print.c | 24 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/rc_scf.c | 231 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/rcfile.c | 76 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/rcfile_priv.h | 28 |
17 files changed, 573 insertions, 60 deletions
diff --git a/usr/src/lib/libsmbfs/Makefile.com b/usr/src/lib/libsmbfs/Makefile.com index e69b199ad0..be5ad05c42 100644 --- a/usr/src/lib/libsmbfs/Makefile.com +++ b/usr/src/lib/libsmbfs/Makefile.com @@ -64,6 +64,7 @@ OBJ_LIB=\ ntlmssp.o \ print.o \ rcfile.o \ + rc_scf.o \ spnego.o \ spnegoparse.o \ ssp.o \ @@ -89,7 +90,7 @@ $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) CSTD= $(CSTD_GNU99) -LDLIBS += -lsocket -lnsl -lc -lmd -lpkcs11 -lkrb5 -lsec -lidmap +LDLIBS += -lsocket -lnsl -lc -lmd -lpkcs11 -lkrb5 -lsec -lidmap -lscf -luuid # normal warnings... CFLAGS += $(CCVERBOSE) diff --git a/usr/src/lib/libsmbfs/cflib.h b/usr/src/lib/libsmbfs/cflib.h index 0e8d6b57ee..85db96fcfd 100644 --- a/usr/src/lib/libsmbfs/cflib.h +++ b/usr/src/lib/libsmbfs/cflib.h @@ -35,6 +35,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ #ifndef _CFLIB_H_ @@ -85,6 +87,8 @@ int cf_getopt(int, char * const *, const char *); void cf_opt_lock(void); void cf_opt_unlock(void); +char *cf_get_client_uuid(void); + int rc_getstringptr(struct rcfile *, const char *, const char *, char **); int rc_getstring(struct rcfile *, const char *, const char *, size_t, char *); int rc_getint(struct rcfile *, const char *, const char *, int *); diff --git a/usr/src/lib/libsmbfs/netsmb/smb_lib.h b/usr/src/lib/libsmbfs/netsmb/smb_lib.h index c9aa810c91..ae71332e97 100644 --- a/usr/src/lib/libsmbfs/netsmb/smb_lib.h +++ b/usr/src/lib/libsmbfs/netsmb/smb_lib.h @@ -126,6 +126,8 @@ struct smb_ctx { */ #define ct_ssn ct_iod_ssn.iod_ossn #define ct_vopt ct_iod_ssn.iod_ossn.ssn_vopt +#define ct_minver ct_iod_ssn.iod_ossn.ssn_minver +#define ct_maxver ct_iod_ssn.iod_ossn.ssn_maxver #define ct_owner ct_iod_ssn.iod_ossn.ssn_owner #define ct_srvaddr ct_iod_ssn.iod_ossn.ssn_srvaddr #define ct_domain ct_iod_ssn.iod_ossn.ssn_domain @@ -194,6 +196,9 @@ int smb_iod_work(struct smb_ctx *); int smb_open_rcfile(char *); void smb_close_rcfile(void); +int smb_cf_minauth_from_str(char *); +int smb_cf_version_from_str(char *); + void smb_simplecrypt(char *dst, const char *src); int smb_simpledecrypt(char *dst, const char *src); diff --git a/usr/src/lib/libsmbfs/netsmb/smbfs_api.h b/usr/src/lib/libsmbfs/netsmb/smbfs_api.h index b1f4b1e198..7b87b571ff 100644 --- a/usr/src/lib/libsmbfs/netsmb/smbfs_api.h +++ b/usr/src/lib/libsmbfs/netsmb/smbfs_api.h @@ -22,7 +22,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ #ifndef _NETSMB_SMBFS_API_H @@ -48,7 +49,7 @@ extern "C" { * EAUTH is used for CIFS authentication errors. */ #ifndef EBADRPC -#define EBADRPC 113 +#define EBADRPC 113 #endif #ifndef EAUTH #define EAUTH 114 @@ -122,6 +123,8 @@ int smb_ctx_setauthflags(struct smb_ctx *, int); int smb_ctx_setcharset(struct smb_ctx *, const char *); int smb_ctx_setfullserver(struct smb_ctx *, const char *); int smb_ctx_setsigning(struct smb_ctx *, int ena, int req); +int smb_ctx_setminver(struct smb_ctx *, int ver); +int smb_ctx_setmaxver(struct smb_ctx *, int ver); int smb_ctx_setnbflags(struct smb_ctx *, int ena, int bcast); int smb_ctx_setscope(struct smb_ctx *, const char *); diff --git a/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.apple.descrip b/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.apple.descrip index aa3d6ad7e1..35fdfd0404 100644 --- a/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.apple.descrip +++ b/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.apple.descrip @@ -1 +1 @@ -PORTIONS OF LIBSMBFS IN CIFS CLIENT +PORTIONS OF LIBSMBFS IN SMB CLIENT diff --git a/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.boris_popov.descrip b/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.boris_popov.descrip index d7cc9ebbd7..35fdfd0404 100644 --- a/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.boris_popov.descrip +++ b/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.boris_popov.descrip @@ -1 +1 @@ -CIFS CLIENT SOFTWARE +PORTIONS OF LIBSMBFS IN SMB CLIENT diff --git a/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.bsd4.descrip b/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.bsd4.descrip index aa3d6ad7e1..35fdfd0404 100644 --- a/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.bsd4.descrip +++ b/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.bsd4.descrip @@ -1 +1 @@ -PORTIONS OF LIBSMBFS IN CIFS CLIENT +PORTIONS OF LIBSMBFS IN SMB CLIENT diff --git a/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.microsoft.descrip b/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.microsoft.descrip index aa3d6ad7e1..35fdfd0404 100644 --- a/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.microsoft.descrip +++ b/usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.microsoft.descrip @@ -1 +1 @@ -PORTIONS OF LIBSMBFS IN CIFS CLIENT +PORTIONS OF LIBSMBFS IN SMB CLIENT diff --git a/usr/src/lib/libsmbfs/smb/connect.c b/usr/src/lib/libsmbfs/smb/connect.c index a45fa90958..c231fe0e8a 100644 --- a/usr/src/lib/libsmbfs/smb/connect.c +++ b/usr/src/lib/libsmbfs/smb/connect.c @@ -51,6 +51,7 @@ #include <netinet/in.h> #include <netinet/tcp.h> #include <arpa/inet.h> +#include <uuid/uuid.h> #include <netsmb/smb.h> #include <netsmb/smb_lib.h> @@ -59,6 +60,8 @@ #include <netsmb/nb_lib.h> #include <netsmb/smb_dev.h> +#include <cflib.h> + #include "charsets.h" #include "private.h" #include "smb_crypt.h" @@ -115,12 +118,18 @@ smb_iod_state_name(enum smbiod_state st) /* * Make a new connection, or reconnect. + * + * This is called first from the door service thread in smbiod + * (so that can report success or failure to the door client) + * and thereafter it's called when we need to reconnect after a + * network outage (or whatever might cause connection loss). */ int smb_iod_connect(smb_ctx_t *ctx) { smbioc_ossn_t *ossn = &ctx->ct_ssn; smbioc_ssn_work_t *work = &ctx->ct_work; + char *uuid_str; int err; struct mbdata blob; char *nego_buf = NULL; @@ -151,6 +160,20 @@ smb_iod_connect(smb_ctx_t *ctx) } /* + * Get local machine uuid. + */ + uuid_str = cf_get_client_uuid(); + if (uuid_str == NULL) { + err = EINVAL; + smb_error(dgettext(TEXT_DOMAIN, + "can't get local UUID"), err); + return (err); + } + (void) uuid_parse(uuid_str, ctx->ct_work.wk_cl_guid); + free(uuid_str); + uuid_str = NULL; + + /* * We're called with each IP address * already copied into ct_srvaddr. */ @@ -227,6 +250,13 @@ out: return (err); } +/* + * smb_ssnsetup_spnego + * + * This does an SMB session setup sequence using SPNEGO. + * The state changes seen during this sequence are there + * just to help track what's going on. + */ int smb_ssnsetup_spnego(struct smb_ctx *ctx, struct mbdata *hint_mb) { @@ -249,25 +279,39 @@ smb_ssnsetup_spnego(struct smb_ctx *ctx, struct mbdata *hint_mb) } for (;;) { err = smb__ssnsetup(ctx, &send_mb, &recv_mb); - if (err != 0 && err != EINPROGRESS) { - DPRINT("smb__ssnsetup, err=%d", err); - goto out; - } - DPRINT("smb__ssnsetup, new state=%s", + DPRINT("smb__ssnsetup rc=%d, new state=%s", err, smb_iod_state_name(work->wk_out_state)); - if (work->wk_out_state == SMBIOD_ST_AUTHOK) { - err = 0; + + if (err == 0) { + /* + * Session setup complete w/ success. + * Should have state AUTHOK + */ + if (work->wk_out_state != SMBIOD_ST_AUTHOK) { + DPRINT("Wrong state (expected AUTHOK)"); + } break; } - if (work->wk_out_state == SMBIOD_ST_AUTHFAIL) { - err = EAUTH; + + if (err != EINPROGRESS) { + /* + * Session setup complete w/ failure. + * Should have state AUTHFAIL + */ + if (work->wk_out_state != SMBIOD_ST_AUTHFAIL) { + DPRINT("Wrong state (expected AUTHFAIL)"); + } goto out; } + + /* + * err == EINPROGRESS + * Session setup continuing. + * Should have state AUTHCONT + */ if (work->wk_out_state != SMBIOD_ST_AUTHCONT) { - err = EPROTO; - goto out; + DPRINT("Wrong state (expected AUTHCONT)"); } - /* state == SMBIOD_ST_AUTHCONT */ /* middle calls get both in, out */ err = ssp_ctx_next_token(ctx, &recv_mb, &send_mb); @@ -277,7 +321,12 @@ smb_ssnsetup_spnego(struct smb_ctx *ctx, struct mbdata *hint_mb) } } - /* NULL output indicates last call. */ + /* + * Only get here via break in the err==0 case above, + * so we're finalizing a successful session setup. + * + * NULL output token here indicates the final call. + */ (void) ssp_ctx_next_token(ctx, &recv_mb, NULL); /* diff --git a/usr/src/lib/libsmbfs/smb/ctx.c b/usr/src/lib/libsmbfs/smb/ctx.c index 43ca516f81..3aa67fd5f5 100644 --- a/usr/src/lib/libsmbfs/smb/ctx.c +++ b/usr/src/lib/libsmbfs/smb/ctx.c @@ -165,6 +165,8 @@ dump_iod_ssn(smb_iod_ssn_t *is) ssn->ssn_domain, ssn->ssn_user); printf(" ct_vopt=0x%x, ct_owner=%d\n", ssn->ssn_vopt, ssn->ssn_owner); + printf(" ct_minver=0x%x, ct_maxver=0x%x\n", + ssn->ssn_minver, ssn->ssn_maxver); printf(" ct_authflags=0x%x\n", is->iod_authflags); printf(" ct_nthash:"); @@ -259,6 +261,7 @@ smb_ctx_init(struct smb_ctx *ctx) ctx->ct_owner = SMBM_ANY_OWNER; ctx->ct_authflags = SMB_AT_DEFAULT; ctx->ct_minauth = SMB_AT_MINAUTH; + ctx->ct_maxver = SMB2_DIALECT_MAX; /* * Default domain, user, ... @@ -856,6 +859,37 @@ smb_ctx_setsigning(struct smb_ctx *ctx, int enable, int require) return (0); } +/* + * Handle .nsmbrc "minver" option. + * Must be <= maxver + */ +int +smb_ctx_setminver(struct smb_ctx *ctx, int ver) +{ + if (ver < 0 || ver > ctx->ct_maxver) + return (EINVAL); + ctx->ct_minver = (uint16_t)ver; + return (0); +} + +/* + * Handle .nsmbrc "maxver" option. + * Must be >= minver + * + * Any "too high" value is just clamped, so the caller + * doesn't need to know what's the highest we support. + */ +int +smb_ctx_setmaxver(struct smb_ctx *ctx, int ver) +{ + if (ver < 1 || ver < ctx->ct_minver) + return (EINVAL); + if (ver > SMB2_DIALECT_MAX) + ver = SMB2_DIALECT_MAX; + ctx->ct_maxver = (uint16_t)ver; + return (0); +} + static int smb_parse_owner(char *pair, uid_t *uid, gid_t *gid) { @@ -1120,8 +1154,12 @@ smb_ctx_resolve(struct smb_ctx *ctx) * If we don't have a p/w yet, * try the keychain. */ - if (ctx->ct_password[0] == '\0') - (void) smb_get_keychain(ctx); + if (ctx->ct_password[0] == '\0' && + smb_get_keychain(ctx) == 0) { + strlcpy(ctx->ct_password, "$HASH", + sizeof (ctx->ct_password)); + } + /* * Mask out disallowed auth types. */ @@ -1362,6 +1400,35 @@ minauth_table[] = { { NULL } }; +int +smb_cf_minauth_from_str(char *str) +{ + struct nv *nvp; + + for (nvp = minauth_table; nvp->name; nvp++) + if (strcmp(nvp->name, str) == 0) + return (nvp->value); + return (-1); +} + + +static struct nv +smbver_table[] = { + { "2.1", SMB2_DIALECT_0210 }, + { "1", 1 }, + { NULL, 0 } +}; + +int +smb_cf_version_from_str(char *str) +{ + struct nv *nvp; + + for (nvp = smbver_table; nvp->name; nvp++) + if (strcmp(nvp->name, str) == 0) + return (nvp->value); + return (-1); +} /* * level values: @@ -1374,7 +1441,9 @@ static int smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level) { char *p; + int ival; int error; + int minver, maxver; #ifdef KICONV_SUPPORT if (level > 0) { @@ -1392,19 +1461,79 @@ smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level) if (level <= 1) { /* Section is: [default] or [server] */ + /* + * Handle min_protocol, max_protocol + * (SMB protocol versions) + */ + minver = -1; + rc_getstringptr(smb_rc, sname, "min_protocol", &p); + if (p != NULL) { + minver = smb_cf_version_from_str(p); + if (minver == -1) { + smb_error(dgettext(TEXT_DOMAIN, +"invalid min_protocol value \"%s\" specified in the section %s"), + 0, p, sname); + } + } + maxver = -1; + rc_getstringptr(smb_rc, sname, "max_protocol", &p); + if (p != NULL) { + maxver = smb_cf_version_from_str(p); + if (maxver == -1) { + smb_error(dgettext(TEXT_DOMAIN, +"invalid max_protocol value \"%s\" specified in the section %s"), + 0, p, sname); + } + } + + /* + * If setting both min/max protocol, + * validate against each other + */ + if (minver != -1 && maxver != -1) { + if (minver > maxver) { + smb_error(dgettext(TEXT_DOMAIN, +"invalid min/max protocol combination in the section %s"), + 0, sname); + } else { + ctx->ct_minver = minver; + ctx->ct_maxver = maxver; + } + } + + /* + * Setting just min or max, validate against + * current settings + */ + if (minver != -1) { + if (minver > ctx->ct_maxver) { + smb_error(dgettext(TEXT_DOMAIN, +"invalid min/max protocol combination in the section %s"), + 0, sname); + } else { + ctx->ct_minver = minver; + } + } + if (maxver != -1) { + if (maxver < ctx->ct_minver) { + smb_error(dgettext(TEXT_DOMAIN, +"invalid min/max protocol combination in the section %s"), + 0, sname); + } else { + ctx->ct_maxver = maxver; + } + } + rc_getstringptr(smb_rc, sname, "minauth", &p); if (p) { /* * "minauth" was set in this section; override * the current minimum authentication setting. */ - struct nv *nvp; - for (nvp = minauth_table; nvp->name; nvp++) - if (strcmp(p, nvp->name) == 0) - break; - if (nvp->name) - ctx->ct_minauth = nvp->value; - else { + ival = smb_cf_minauth_from_str(p); + if (ival != -1) { + ctx->ct_minauth = ival; + } else { /* * Unknown minimum authentication level. */ diff --git a/usr/src/lib/libsmbfs/smb/file.c b/usr/src/lib/libsmbfs/smb/file.c index 1c4e2dc236..3d2a431142 100644 --- a/usr/src/lib/libsmbfs/smb/file.c +++ b/usr/src/lib/libsmbfs/smb/file.c @@ -217,7 +217,6 @@ smb_fh_read(int fd, off64_t offset, size_t count, struct smbioc_rw rwrq; bzero(&rwrq, sizeof (rwrq)); - rwrq.ioc_fh = -1; /* tell driver to supply this */ rwrq.ioc_base = dst; rwrq.ioc_cnt = count; rwrq.ioc_offset = offset; @@ -234,7 +233,6 @@ smb_fh_write(int fd, off64_t offset, size_t count, struct smbioc_rw rwrq; bzero(&rwrq, sizeof (rwrq)); - rwrq.ioc_fh = -1; /* tell driver to supply this */ rwrq.ioc_base = (char *)src; rwrq.ioc_cnt = count; rwrq.ioc_offset = offset; @@ -262,7 +260,6 @@ smb_fh_xactnp(int fd, /* this gets copyin & copyout */ bzero(&ioc, sizeof (ioc)); - ioc.ioc_fh = -1; /* tell driver to supply this */ ioc.ioc_tdlen = tdlen; ioc.ioc_rdlen = *rdlen; ioc.ioc_more = 0; diff --git a/usr/src/lib/libsmbfs/smb/iod_wk.c b/usr/src/lib/libsmbfs/smb/iod_wk.c index b19f1f3f0f..38e9d5e0de 100644 --- a/usr/src/lib/libsmbfs/smb/iod_wk.c +++ b/usr/src/lib/libsmbfs/smb/iod_wk.c @@ -104,6 +104,7 @@ smb_iod_work(smb_ctx_t *ctx) DPRINT("ioc_idle: err %d", err); goto out; } + DPRINT("Ret. from _ioc_idle"); continue; case SMBIOD_ST_RECONNECT: @@ -119,16 +120,14 @@ smb_iod_work(smb_ctx_t *ctx) * will need to run smbutil to get * a new thread with new auth info. */ - if (err == EAUTH) + if (err == EAUTH) { + DPRINT("iod_connect: EAUTH (give up)"); goto out; - continue; - - case SMBIOD_ST_RCFAILED: + } /* - * Reconnect failed. Kill off any - * requests waiting in the driver, - * then get ready to try again. - * Next state is normally IDLE. + * Reconnect failed. Notify any requests + * that we're not connected, and delay. + * Next state will be IDLE or RECONNECT. */ DPRINT("Call _iod_rcfail..."); if (nsmb_ioctl(ctx->ct_dev_fd, @@ -152,9 +151,11 @@ smb_iod_work(smb_ctx_t *ctx) DPRINT("iod_work: err %d", err); goto out; } + DPRINT("Ret. from _ioc_work"); continue; case SMBIOD_ST_DEAD: + DPRINT("got state=DEAD"); err = 0; goto out; diff --git a/usr/src/lib/libsmbfs/smb/mapfile-vers b/usr/src/lib/libsmbfs/smb/mapfile-vers index 73ab2504f5..a94b3bc6e1 100644 --- a/usr/src/lib/libsmbfs/smb/mapfile-vers +++ b/usr/src/lib/libsmbfs/smb/mapfile-vers @@ -68,6 +68,9 @@ SYMBOL_VERSION SUNWprivate { nsmb_close { FLAGS = NODIRECT }; nsmb_ioctl { FLAGS = NODIRECT }; + smb_cf_minauth_from_str; + smb_cf_version_from_str; + smb_close_rcfile; smb_ctx_alloc; @@ -91,6 +94,8 @@ SYMBOL_VERSION SUNWprivate { smb_ctx_setauthflags; smb_ctx_setdomain; smb_ctx_setfullserver; + smb_ctx_setminver; + smb_ctx_setmaxver; smb_ctx_setnbflags; smb_ctx_setpassword; smb_ctx_setpwhash; diff --git a/usr/src/lib/libsmbfs/smb/print.c b/usr/src/lib/libsmbfs/smb/print.c index 80fcab7d10..698dd8359f 100644 --- a/usr/src/lib/libsmbfs/smb/print.c +++ b/usr/src/lib/libsmbfs/smb/print.c @@ -33,7 +33,7 @@ */ /* - * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ #include <sys/param.h> @@ -57,12 +57,24 @@ #include "private.h" +/* + * Replacing invalid characters in print job titles: + * + * The spec. is unclear about what characters are allowed in a + * print job title (used with NtCreate) so out of caution this + * makes sure the title contains none of the characters that + * are known to be illegal in a file name component. + */ +static const char invalid_chars[] = SMB_FILENAME_INVALID_CHARS; + int smb_open_printer(struct smb_ctx *ctx, const char *title, int setuplen, int mode) { smbioc_printjob_t ioc; - int err, tlen, new_fd; + char *p; + int err, tlen; + int new_fd = -1; int32_t from_fd; tlen = strlen(title); @@ -91,6 +103,14 @@ smb_open_printer(struct smb_ctx *ctx, const char *title, ioc.ioc_prmode = mode; strlcpy(ioc.ioc_title, title, SMBIOC_MAX_NAME); + /* + * The title is used in NtCreate so sanitize by + * replacing any illegal chars with spaces. + */ + for (p = ioc.ioc_title; *p != '\0'; p++) + if (strchr(invalid_chars, *p) != NULL) + *p = ' '; + if (nsmb_ioctl(new_fd, SMBIOC_PRINTJOB, &ioc) == -1) { err = errno; goto errout; diff --git a/usr/src/lib/libsmbfs/smb/rc_scf.c b/usr/src/lib/libsmbfs/smb/rc_scf.c new file mode 100644 index 0000000000..477982c0c8 --- /dev/null +++ b/usr/src/lib/libsmbfs/smb/rc_scf.c @@ -0,0 +1,231 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Support functions for getting things libsmbfs needs + * from the SMF configuration (using libscf). + */ + +#include <sys/types.h> +#include <sys/queue.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <unistd.h> +#include <libscf.h> + +#include <cflib.h> +#include "rcfile_priv.h" + +#define IDMAP_SERVICE_FMRI "svc:/system/idmap" +#define IDMAP_PG_NAME "config" +#define MACHINE_UUID "machine_uuid" + +#define SMBC_DEFAULT_INSTANCE_FMRI "svc:/network/smb/client:default" + +scf_handle_t *_scf_handle_create_and_bind(scf_version_t ver); + +/* + * Get the "machine_uuid" from idmap, as a string (allocated) + */ +char * +cf_get_client_uuid(void) +{ + char val_buf[64]; + char *ret = NULL; + + scf_handle_t *h = NULL; + scf_service_t *svc = NULL; + scf_propertygroup_t *pg = NULL; + scf_property_t *prop = NULL; + scf_value_t *val = NULL; + + if ((h = _scf_handle_create_and_bind(SCF_VERSION)) == NULL) + goto out; + + if ((svc = scf_service_create(h)) == NULL || + (pg = scf_pg_create(h)) == NULL || + (prop = scf_property_create(h)) == NULL || + (val = scf_value_create(h)) == NULL) + goto out; + + if (scf_handle_decode_fmri(h, IDMAP_SERVICE_FMRI, + NULL, svc, NULL, NULL, NULL, 0) == -1) + goto out; + + + if (scf_service_get_pg(svc, IDMAP_PG_NAME, pg) != 0) + goto out; + if (scf_pg_get_property(pg, MACHINE_UUID, prop) != 0) + goto out; + if (scf_property_get_value(prop, val) != 0) + goto out; + if (scf_value_get_as_string(val, val_buf, sizeof (val_buf)) < 0) + goto out; + + ret = strdup(val_buf); + +out: + scf_value_destroy(val); + scf_property_destroy(prop); + scf_pg_destroy(pg); + scf_service_destroy(svc); + + if (h != NULL) + scf_handle_destroy(h); + + return (ret); +} + +/* + * Get the output of "sharectl get smbfs" into a file, without an + * actual fork/exec of sharectl. + * + * Each section of the smbfs settings are represented as an SMF + * property group with an "S-" prefix and a UUID, and the section + * name itself a property which can have a more flexible name than + * a property group name can have. + */ +int +rc_scf_get_sharectl(FILE *fp) +{ + char sect_name[256]; + char prop_name[256]; + char val_buf[1024]; + + scf_handle_t *h = NULL; + scf_service_t *svc = NULL; + scf_instance_t *inst = NULL; + scf_propertygroup_t *pg = NULL; + scf_property_t *prop = NULL; + scf_value_t *val = NULL; + scf_iter_t *pgiter = NULL; + scf_iter_t *propiter = NULL; + scf_iter_t *valiter = NULL; + int ret = -1; + + if ((h = _scf_handle_create_and_bind(SCF_VERSION)) == NULL) + goto out; + + if ((svc = scf_service_create(h)) == NULL || + (inst = scf_instance_create(h)) == NULL || + (pgiter = scf_iter_create(h)) == NULL || + (propiter = scf_iter_create(h)) == NULL || + (valiter = scf_iter_create(h)) == NULL || + (pg = scf_pg_create(h)) == NULL || + (prop = scf_property_create(h)) == NULL || + (val = scf_value_create(h)) == NULL) + goto out; + + if (scf_handle_decode_fmri(h, SMBC_DEFAULT_INSTANCE_FMRI, + NULL, svc, inst, NULL, NULL, 0) == -1) + goto out; + + if (scf_iter_instance_pgs_composed(pgiter, inst, NULL) == -1) + goto out; + while ((ret = scf_iter_next_pg(pgiter, pg)) == 1) { + /* + * Using prop_name array for pg name temporarily. + * Skip any property groups names other than "S-*". + */ + if (scf_pg_get_name(pg, prop_name, sizeof (prop_name)) < 0) + continue; + if (strncmp(prop_name, "S-", 2) != 0) + continue; + + /* + * Get the "section" name, which is a property of + * this property group. + */ + if (scf_pg_get_property(pg, "section", prop) != 0) + continue; + if (scf_property_get_value(prop, val) != 0) + continue; + if (scf_value_get_as_string(val, sect_name, + sizeof (sect_name)) < 0) + continue; + + /* + * Have an S-* property group with a "section" name. + * Print the section start. + */ + fprintf(fp, "[%s]\n", sect_name); + + /* + * Now print the remaining properties in this PG, + * but skip the special "section" (name) prop. + */ + if (scf_iter_pg_properties(propiter, pg) == -1) + goto out; + while ((ret = scf_iter_next_property(propiter, prop)) == 1) { + + if (scf_property_get_name(prop, prop_name, + sizeof (prop_name)) < 0) + continue; + + /* Skip the "section" prop. now */ + if (strcmp(prop_name, "section") == 0) + continue; + + if (scf_property_get_value(prop, val) != 0) + continue; + + if (scf_value_get_as_string(val, val_buf, + sizeof (val_buf)) < 0) + continue; + + fprintf(fp, "%s=%s\n", prop_name, val_buf); + } + } + ret = 0; + +out: + fflush(fp); + + scf_value_destroy(val); + scf_property_destroy(prop); + scf_pg_destroy(pg); + scf_iter_destroy(valiter); + scf_iter_destroy(propiter); + scf_iter_destroy(pgiter); + scf_instance_destroy(inst); + scf_service_destroy(svc); + + if (h != NULL) + scf_handle_destroy(h); + + return (ret); +} + +/* + * Simple test wrapper. Compile with: + * cc -o rc_scf_test -I.. -DTEST_MAIN rc_scf.c -lscf + */ +#ifdef TEST_MAIN +int +main(int argc, char **arv) +{ + char *s; + int rc; + + rc = rc_scf_get_sharectl(stdout); + printf("# rc=%d\n", rc); + return (0); +} +#endif /* TEST_MAIN */ diff --git a/usr/src/lib/libsmbfs/smb/rcfile.c b/usr/src/lib/libsmbfs/smb/rcfile.c index 56335d0954..d7ee2d15af 100644 --- a/usr/src/lib/libsmbfs/smb/rcfile.c +++ b/usr/src/lib/libsmbfs/smb/rcfile.c @@ -32,7 +32,7 @@ * $Id: rcfile.c,v 1.1.1.2 2001/07/06 22:38:43 conrad Exp $ */ /* - * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ #include <fcntl.h> @@ -60,7 +60,6 @@ #define SMB_CFG_FILE "/etc/nsmb.conf" #define OLD_SMB_CFG_FILE "/usr/local/etc/nsmb.conf" #endif -#define SMBFS_SHARECTL_CMD "/usr/sbin/sharectl get smbfs" extern int smb_debug; @@ -150,37 +149,77 @@ rc_merge(const char *filename, struct rcfile **rcfile) } /* - * Like rc_open, but does popen of command: - * sharectl get smbfs + * Like rc_open, but creates a temporary file and + * reads the sharectl settings into it. + * The file is deleted when we close it. */ static int -rc_popen_cmd(const char *command, struct rcfile **rcfile) +rc_open_sharectl(struct rcfile **rcfile) { - struct rcfile *rcp; - FILE *f; + static char template[24] = "/tmp/smbfsXXXXXX"; + struct rcfile *rcp = NULL; + FILE *fp = NULL; + int err; + int fd = -1; assert(MUTEX_HELD(&rcfile_mutex)); - f = popen(command, "r"); - if (f == NULL) - return (errno); - insecure_nsmbrc = 0; + fd = mkstemp(template); + if (fd < 0) { + err = errno; + goto errout; + } + + fp = fdopen(fd, "w+"); + if (fp == NULL) { + err = errno; + close(fd); + goto errout; + } + fd = -1; /* The fp owns this fd now. */ + + /* + * Get smbfs sharectl settings into the file. + */ + if ((err = rc_scf_get_sharectl(fp)) != 0) + goto errout; rcp = malloc(sizeof (struct rcfile)); if (rcp == NULL) { - fclose(f); - return (ENOMEM); + err = ENOMEM; + goto errout; } bzero(rcp, sizeof (struct rcfile)); - rcp->rf_name = strdup(command); - rcp->rf_f = f; + + rcp->rf_name = strdup(template); + if (rcp->rf_name == NULL) { + err = ENOMEM; + goto errout; + } + rcp->rf_f = fp; + rcp->rf_flags = RCFILE_DELETE_ON_CLOSE; + SLIST_INSERT_HEAD(&pf_head, rcp, rf_next); + insecure_nsmbrc = 0; rc_parse(rcp); *rcfile = rcp; /* fclose(f) in rc_close */ return (0); + +errout: + if (rcp != NULL) + free(rcp); + if (fp != NULL) { + fclose(fp); + fd = -1; + } + if (fd != -1) + close(fd); + + return (err); } + static int rc_close(struct rcfile *rcp) { @@ -189,6 +228,9 @@ rc_close(struct rcfile *rcp) mutex_lock(&rcfile_mutex); fclose(rcp->rf_f); + if (rcp->rf_flags & RCFILE_DELETE_ON_CLOSE) + (void) unlink(rcp->rf_name); + for (p = SLIST_FIRST(&rcp->rf_sect); p; ) { n = p; p = SLIST_NEXT(p, rs_next); @@ -663,8 +705,8 @@ smb_open_rcfile(char *home) fn = SMB_CFG_FILE; error = rc_open(fn, &smb_rc); #else - fn = SMBFS_SHARECTL_CMD; - error = rc_popen_cmd(fn, &smb_rc); + fn = "(sharectl get smbfs)"; + error = rc_open_sharectl(&smb_rc); #endif if (error != 0 && error != ENOENT) { /* Error from fopen. strerror is OK. */ diff --git a/usr/src/lib/libsmbfs/smb/rcfile_priv.h b/usr/src/lib/libsmbfs/smb/rcfile_priv.h index ef9e31d7fc..b239c77a67 100644 --- a/usr/src/lib/libsmbfs/smb/rcfile_priv.h +++ b/usr/src/lib/libsmbfs/smb/rcfile_priv.h @@ -30,9 +30,26 @@ * SUCH DAMAGE. */ +/* + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _RCFILE_PRIV_H +#define _RCFILE_PRIV_H + +/* + * Private RC file support. + */ + +#include <sys/queue.h> + +#ifdef __cplusplus +extern "C" { +#endif + struct rckey { SLIST_ENTRY(rckey) rk_next; - char *rk_name; + char *rk_name; char *rk_value; }; @@ -52,3 +69,12 @@ struct rcfile { #define RCFILE_HOME_NSMBRC 1 #define RCFILE_IS_INSECURE 2 +#define RCFILE_DELETE_ON_CLOSE 4 + +int rc_scf_get_sharectl(FILE *); + +#ifdef __cplusplus +} +#endif + +#endif /* _RCFILE_PRIV_H */ |