2 * Copyright (c) 2000, Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $Id: ctx.c,v 1.32.70.2 2005/06/02 00:55:40 lindak Exp $
36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
37 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
40 #include <sys/param.h>
41 #include <sys/ioctl.h>
43 #include <sys/mount.h>
44 #include <sys/types.h>
45 #include <sys/byteorder.h>
59 #include <nss_dbdefs.h>
62 #include <netsmb/smb_lib.h>
63 #include <netsmb/netbios.h>
64 #include <netsmb/nb_lib.h>
65 #include <netsmb/smb_dev.h>
78 #define SMB_AT_DEFAULT (SMB_AT_KRB5 | SMB_AT_NTLM2)
79 #define SMB_AT_MINAUTH (SMB_AT_KRB5 | SMB_AT_NTLM2 | SMB_AT_NTLM1)
86 /* These two may be set by commands. */
87 int smb_debug
, smb_verbose
;
90 * Was: STDPARAM_OPT - see smb_ctx_scan_argv, smb_ctx_opt
92 const char smbutil_std_opts
[] = "ABCD:E:I:L:M:NO:P:U:R:S:T:W:";
95 * Defaults for new contexts (connections to servers).
96 * These are set by smbfs_set_default_...
98 static char default_domain
[SMBIOC_MAX_NAME
];
99 static char default_user
[SMBIOC_MAX_NAME
];
103 * Give the RPC library a callback hook that will be
104 * called whenever we destroy or reinit an smb_ctx_t.
105 * The name rpc_cleanup_smbctx() is legacy, and was
106 * originally a direct call into the RPC code.
108 static smb_ctx_close_hook_t close_hook
;
110 rpc_cleanup_smbctx(struct smb_ctx
*ctx
)
116 smb_ctx_set_close_hook(smb_ctx_close_hook_t hook
)
122 dump_ctx_flags(int flags
)
127 if (flags
& SMBCF_NOPWD
)
129 if (flags
& SMBCF_SRIGHTS
)
131 if (flags
& SMBCF_LOCALE
)
133 if (flags
& SMBCF_CMD_DOM
)
135 if (flags
& SMBCF_CMD_USR
)
137 if (flags
& SMBCF_CMD_PW
)
139 if (flags
& SMBCF_RESOLVED
)
141 if (flags
& SMBCF_KCBAD
)
143 if (flags
& SMBCF_KCFOUND
)
145 if (flags
& SMBCF_BROWSEOK
)
147 if (flags
& SMBCF_AUTHREQ
)
149 if (flags
& SMBCF_KCSAVE
)
151 if (flags
& SMBCF_XXX
)
153 if (flags
& SMBCF_SSNACTIVE
)
154 printf("SSNACTIVE ");
155 if (flags
& SMBCF_KCDOMAIN
)
161 dump_iod_ssn(smb_iod_ssn_t
*is
)
163 static const char zeros
[NTLM_HASH_SZ
] = {0};
164 struct smbioc_ossn
*ssn
= &is
->iod_ossn
;
166 printf(" ct_srvname=\"%s\", ", ssn
->ssn_srvname
);
167 dump_sockaddr(&ssn
->ssn_srvaddr
.sa
);
168 printf(" dom=\"%s\", user=\"%s\"\n",
169 ssn
->ssn_domain
, ssn
->ssn_user
);
170 printf(" ct_vopt=0x%x, ct_owner=%d\n",
171 ssn
->ssn_vopt
, ssn
->ssn_owner
);
172 printf(" ct_authflags=0x%x\n", is
->iod_authflags
);
174 printf(" ct_nthash:");
175 if (bcmp(zeros
, &is
->iod_nthash
, NTLM_HASH_SZ
))
176 smb_hexdump(&is
->iod_nthash
, NTLM_HASH_SZ
);
180 printf(" ct_lmhash:");
181 if (bcmp(zeros
, &is
->iod_lmhash
, NTLM_HASH_SZ
))
182 smb_hexdump(&is
->iod_lmhash
, NTLM_HASH_SZ
);
188 dump_ctx(char *where
, struct smb_ctx
*ctx
)
190 printf("context %s:\n", where
);
191 dump_ctx_flags(ctx
->ct_flags
);
194 printf(" localname=\"%s\"", ctx
->ct_locname
);
196 printf(" localname=NULL");
198 if (ctx
->ct_fullserver
)
199 printf(" fullserver=\"%s\"", ctx
->ct_fullserver
);
201 printf(" fullserver=NULL");
203 if (ctx
->ct_srvaddr_s
)
204 printf(" srvaddr_s=\"%s\"\n", ctx
->ct_srvaddr_s
);
206 printf(" srvaddr_s=NULL\n");
208 if (ctx
->ct_addrinfo
)
209 dump_addrinfo(ctx
->ct_addrinfo
);
211 printf(" ct_addrinfo = NULL\n");
213 dump_iod_ssn(&ctx
->ct_iod_ssn
);
215 printf(" share_name=\"%s\", share_type=%d\n",
216 ctx
->ct_origshare
? ctx
->ct_origshare
: "",
219 printf(" ct_home=\"%s\"\n", ctx
->ct_home
);
220 printf(" ct_rpath=\"%s\"\n", ctx
->ct_rpath
);
224 smb_ctx_alloc(struct smb_ctx
**ctx_pp
)
229 ctx
= malloc(sizeof (*ctx
));
232 err
= smb_ctx_init(ctx
);
242 * Initialize an smb_ctx struct (defaults)
245 smb_ctx_init(struct smb_ctx
*ctx
)
249 bzero(ctx
, sizeof (*ctx
));
251 error
= nb_ctx_create(&ctx
->ct_nb
);
256 ctx
->ct_door_fd
= -1;
257 ctx
->ct_tran_fd
= -1;
258 ctx
->ct_parsedlevel
= SMBL_NONE
;
259 ctx
->ct_minlevel
= SMBL_NONE
;
260 ctx
->ct_maxlevel
= SMBL_PATH
;
262 /* Fill in defaults */
263 ctx
->ct_vopt
= SMBVOPT_EXT_SEC
;
264 ctx
->ct_owner
= SMBM_ANY_OWNER
;
265 ctx
->ct_authflags
= SMB_AT_DEFAULT
;
266 ctx
->ct_minauth
= SMB_AT_MINAUTH
;
269 * Default domain, user, ...
271 strlcpy(ctx
->ct_domain
, default_domain
,
272 sizeof (ctx
->ct_domain
));
273 strlcpy(ctx
->ct_user
, default_user
,
274 sizeof (ctx
->ct_user
));
280 * "Scan" the command line args to find the server name,
281 * user name, and share name, as needed. We need these
282 * before reading the RC files and/or sharectl values.
284 * The sequence for getting all the members filled in
285 * has some tricky aspects. Here's how it works:
287 * The search order for options is as follows:
288 * command line options
289 * values parsed from UNC path (cmd)
290 * values from RC file (per-user)
291 * values from SMF (system-wide)
294 * Normally, one would simply get all the values starting with
295 * the bottom of the above list and working to the top, and
296 * overwriting values as you go. But we need an exception.
298 * In this function, we parse the UNC path and command line options,
299 * because we need (at least) the server name when we're getting the
300 * SMF and RC file values. However, values we get from the command
301 * should not be overwritten by SMF or RC file parsing, so we mark
302 * values from the command as "from CMD" and the RC file parser
303 * leaves in place any values so marked. See: SMBCF_CMD_*
305 * The semantics of these flags are: "This value came from the
306 * current command instance, not from sources that may apply to
307 * multiple commands." (Different from the old "FROMUSR" flag.)
309 * Note that smb_ctx_opt() is called later to handle the
310 * remaining options, which should be ignored here.
311 * The (magic) leading ":" in cf_getopt() makes it
312 * ignore options not in the options string.
315 smb_ctx_scan_argv(struct smb_ctx
*ctx
, int argc
, char **argv
,
316 int minlevel
, int maxlevel
, int sharetype
)
318 int ind
, opt
, error
= 0;
319 int aflg
= 0, uflg
= 0;
323 * Parse options, if any. Values from here too
324 * are marked as "from CMD".
329 ctx
->ct_minlevel
= minlevel
;
330 ctx
->ct_maxlevel
= maxlevel
;
331 ctx
->ct_shtype_req
= sharetype
;
334 /* Careful: no return/goto before cf_opt_unlock! */
336 opt
= cf_getopt(argc
, argv
, STDPARAM_OPT
);
340 /* NB: handle most in smb_ctx_opt */
344 error
= smb_ctx_setuser(ctx
, "", TRUE
);
345 ctx
->ct_flags
|= SMBCF_NOPWD
;
349 error
= smb_ctx_setuser(ctx
, arg
, TRUE
);
352 DPRINT("skip opt=%c", opt
);
358 cf_optind
= cf_optreset
= 1;
365 printf(gettext("-A and -U flags are exclusive.\n"));
370 * Parse the UNC path. Values from here are
371 * marked as "from CMD".
373 for (; ind
< argc
; ind
++) {
375 if (strncmp(arg
, "//", 2) != 0)
377 error
= smb_ctx_parseunc(ctx
, arg
,
378 minlevel
, maxlevel
, sharetype
, &arg
);
388 smb_ctx_free(smb_ctx_t
*ctx
)
395 smb_ctx_done(struct smb_ctx
*ctx
)
398 rpc_cleanup_smbctx(ctx
);
400 if (ctx
->ct_dev_fd
!= -1) {
401 close(ctx
->ct_dev_fd
);
404 if (ctx
->ct_door_fd
!= -1) {
405 close(ctx
->ct_door_fd
);
406 ctx
->ct_door_fd
= -1;
408 if (ctx
->ct_tran_fd
!= -1) {
409 close(ctx
->ct_tran_fd
);
410 ctx
->ct_tran_fd
= -1;
412 if (ctx
->ct_srvaddr_s
) {
413 free(ctx
->ct_srvaddr_s
);
414 ctx
->ct_srvaddr_s
= NULL
;
417 nb_ctx_done(ctx
->ct_nb
);
420 if (ctx
->ct_locname
) {
421 free(ctx
->ct_locname
);
422 ctx
->ct_locname
= NULL
;
424 if (ctx
->ct_origshare
) {
425 free(ctx
->ct_origshare
);
426 ctx
->ct_origshare
= NULL
;
428 if (ctx
->ct_fullserver
) {
429 free(ctx
->ct_fullserver
);
430 ctx
->ct_fullserver
= NULL
;
432 if (ctx
->ct_addrinfo
) {
433 freeaddrinfo(ctx
->ct_addrinfo
);
434 ctx
->ct_addrinfo
= NULL
;
442 ctx
->ct_rpath
= NULL
;
444 if (ctx
->ct_srv_OS
) {
445 free(ctx
->ct_srv_OS
);
446 ctx
->ct_srv_OS
= NULL
;
448 if (ctx
->ct_srv_LM
) {
449 free(ctx
->ct_srv_LM
);
450 ctx
->ct_srv_LM
= NULL
;
452 if (ctx
->ct_mackey
) {
453 free(ctx
->ct_mackey
);
454 ctx
->ct_mackey
= NULL
;
459 * Parse the UNC path. Here we expect something like
460 * "//[[domain;]user[:password]@]host[/share[/path]]"
461 * See http://ietf.org/internet-drafts/draft-crhertel-smb-url-07.txt
462 * Values found here are marked as "from CMD".
465 smb_ctx_parseunc(struct smb_ctx
*ctx
, const char *unc
,
466 int minlevel
, int maxlevel
, int sharetype
,
470 char *host
, *share
, *path
;
471 char *dom
, *usr
, *pw
, *p
;
475 * This may be called outside of _scan_argv,
476 * so make sure these get initialized.
478 ctx
->ct_minlevel
= minlevel
;
479 ctx
->ct_maxlevel
= maxlevel
;
480 ctx
->ct_shtype_req
= sharetype
;
481 ctx
->ct_parsedlevel
= SMBL_NONE
;
483 dom
= usr
= pw
= host
= NULL
;
485 /* Work on a temporary copy, fix back slashes. */
486 strlcpy(tmp
, unc
, sizeof (tmp
));
487 for (p
= tmp
; *p
; p
++)
491 if (tmp
[0] != '/' || tmp
[1] != '/') {
492 smb_error(dgettext(TEXT_DOMAIN
,
493 "UNC should start with '//'"), 0);
497 p
= tmp
+ 2; /* user@host... */
499 /* Find the share part, if any. */
500 share
= strchr(p
, '/');
503 (void) unpercent(p
); /* host component */
506 * Parse the "host" stuff right to left:
507 * 1: trailing "@hostname" (or whole field)
508 * 2: trailing ":password"
509 * 3: trailing "domain;user" (or just user)
511 host
= strrchr(p
, '@');
513 host
= p
; /* no user@ prefix */
517 /* may have [[domain;]user[:passwd]] */
521 usr
= strchr(p
, ';');
530 smb_error(dgettext(TEXT_DOMAIN
, "empty server name"), 0);
534 error
= smb_ctx_setfullserver(ctx
, host
);
537 ctx
->ct_parsedlevel
= SMBL_VC
;
540 error
= smb_ctx_setdomain(ctx
, dom
, TRUE
);
546 smb_error(dgettext(TEXT_DOMAIN
,
547 "empty user name"), 0);
551 if (ctx
->ct_maxlevel
< SMBL_VC
) {
552 smb_error(dgettext(TEXT_DOMAIN
,
553 "no user name required"), 0);
557 error
= smb_ctx_setuser(ctx
, usr
, TRUE
);
562 error
= smb_ctx_setpassword(ctx
, pw
, TRUE
);
568 /* restore the slash */
572 /* Find the path part, if any. */
573 path
= strchr(p
, '/');
576 (void) unpercent(p
); /* share component */
579 smb_error(dgettext(TEXT_DOMAIN
,
580 "empty share name"), 0);
584 if (ctx
->ct_maxlevel
< SMBL_SHARE
) {
585 smb_error(dgettext(TEXT_DOMAIN
,
586 "no share name required"), 0);
592 * Special case UNC names like:
593 * //host/PIPE/endpoint
594 * to have share: IPC$
596 if (strcasecmp(p
, "PIPE") == 0) {
600 error
= smb_ctx_setshare(ctx
, p
, sharetype
);
603 ctx
->ct_parsedlevel
= SMBL_SHARE
;
606 /* restore the slash */
609 (void) unpercent(p
); /* remainder */
611 ctx
->ct_rpath
= strdup(path
);
613 } else if (ctx
->ct_minlevel
>= SMBL_SHARE
) {
614 smb_error(dgettext(TEXT_DOMAIN
, "empty share name"), 0);
623 if (error
== 0 && smb_debug
> 0)
624 dump_ctx("after smb_ctx_parseunc", ctx
);
629 #ifdef KICONV_SUPPORT
631 smb_ctx_setcharset(struct smb_ctx
*ctx
, const char *arg
)
633 char *cp
, *servercs
, *localcs
;
634 int cslen
= sizeof (ctx
->ct_ssn
.ioc_localcs
);
635 int scslen
, lcslen
, error
;
637 cp
= strchr(arg
, ':');
638 lcslen
= cp
? (cp
- arg
) : 0;
639 if (lcslen
== 0 || lcslen
>= cslen
) {
640 smb_error(dgettext(TEXT_DOMAIN
,
641 "invalid local charset specification (%s)"), 0, arg
);
644 scslen
= (size_t)strlen(++cp
);
645 if (scslen
== 0 || scslen
>= cslen
) {
646 smb_error(dgettext(TEXT_DOMAIN
,
647 "invalid server charset specification (%s)"), 0, arg
);
650 localcs
= memcpy(ctx
->ct_ssn
.ioc_localcs
, arg
, lcslen
);
652 servercs
= strcpy(ctx
->ct_ssn
.ioc_servercs
, cp
);
653 error
= nls_setrecode(localcs
, servercs
);
656 smb_error(dgettext(TEXT_DOMAIN
,
657 "can't initialize iconv support (%s:%s)"),
658 error
, localcs
, servercs
);
663 #endif /* KICONV_SUPPORT */
666 smb_ctx_setauthflags(struct smb_ctx
*ctx
, int flags
)
668 ctx
->ct_authflags
= flags
;
673 smb_ctx_setfullserver(struct smb_ctx
*ctx
, const char *name
)
675 char *p
= strdup(name
);
679 free(ctx
->ct_fullserver
);
680 ctx
->ct_fullserver
= p
;
685 smb_ctx_setserver(struct smb_ctx
*ctx
, const char *name
)
687 strlcpy(ctx
->ct_srvname
, name
,
688 sizeof (ctx
->ct_srvname
));
693 smb_ctx_setuser(struct smb_ctx
*ctx
, const char *name
, int from_cmd
)
696 if (strlen(name
) >= sizeof (ctx
->ct_user
)) {
697 smb_error(dgettext(TEXT_DOMAIN
,
698 "user name '%s' too long"), 0, name
);
699 return (ENAMETOOLONG
);
703 * Don't overwrite a value from the command line
704 * with one from anywhere else.
706 if (!from_cmd
&& (ctx
->ct_flags
& SMBCF_CMD_USR
))
709 strlcpy(ctx
->ct_user
, name
,
710 sizeof (ctx
->ct_user
));
712 /* Mark this as "from the command line". */
714 ctx
->ct_flags
|= SMBCF_CMD_USR
;
720 * Don't overwrite a domain name from the
721 * command line with one from anywhere else.
722 * See smb_ctx_init() for notes about this.
725 smb_ctx_setdomain(struct smb_ctx
*ctx
, const char *name
, int from_cmd
)
728 if (strlen(name
) >= sizeof (ctx
->ct_domain
)) {
729 smb_error(dgettext(TEXT_DOMAIN
,
730 "workgroup name '%s' too long"), 0, name
);
731 return (ENAMETOOLONG
);
735 * Don't overwrite a value from the command line
736 * with one from anywhere else.
738 if (!from_cmd
&& (ctx
->ct_flags
& SMBCF_CMD_DOM
))
741 strlcpy(ctx
->ct_domain
, name
,
742 sizeof (ctx
->ct_domain
));
744 /* Mark this as "from the command line". */
746 ctx
->ct_flags
|= SMBCF_CMD_DOM
;
752 smb_ctx_setpassword(struct smb_ctx
*ctx
, const char *passwd
, int from_cmd
)
758 if (strlen(passwd
) >= sizeof (ctx
->ct_password
)) {
759 smb_error(dgettext(TEXT_DOMAIN
, "password too long"), 0);
760 return (ENAMETOOLONG
);
764 * If called again after comand line parsing,
765 * don't overwrite a value from the command line
766 * with one from any stored config.
768 if (!from_cmd
&& (ctx
->ct_flags
& SMBCF_CMD_PW
))
771 memset(ctx
->ct_password
, 0, sizeof (ctx
->ct_password
));
772 if (strncmp(passwd
, "$$1", 3) == 0)
773 (void) smb_simpledecrypt(ctx
->ct_password
, passwd
);
775 strlcpy(ctx
->ct_password
, passwd
,
776 sizeof (ctx
->ct_password
));
779 * Compute LM hash, NT hash.
781 if (ctx
->ct_password
[0]) {
782 err
= ntlm_compute_nt_hash(ctx
->ct_nthash
, ctx
->ct_password
);
785 err
= ntlm_compute_lm_hash(ctx
->ct_lmhash
, ctx
->ct_password
);
790 /* Mark this as "from the command line". */
792 ctx
->ct_flags
|= SMBCF_CMD_PW
;
798 * Use this to set NTLM auth. info (hashes)
799 * when we don't have the password.
802 smb_ctx_setpwhash(smb_ctx_t
*ctx
,
803 const uchar_t
*nthash
, const uchar_t
*lmhash
)
806 /* Need ct_password to be non-null. */
807 if (ctx
->ct_password
[0] == '\0')
808 strlcpy(ctx
->ct_password
, "$HASH",
809 sizeof (ctx
->ct_password
));
812 * Compute LM hash, NT hash.
814 memcpy(ctx
->ct_nthash
, nthash
, NTLM_HASH_SZ
);
816 /* The LM hash is optional */
818 memcpy(ctx
->ct_nthash
, nthash
, NTLM_HASH_SZ
);
825 smb_ctx_setshare(struct smb_ctx
*ctx
, const char *share
, int stype
)
827 if (strlen(share
) >= SMBIOC_MAX_NAME
) {
828 smb_error(dgettext(TEXT_DOMAIN
,
829 "share name '%s' too long"), 0, share
);
830 return (ENAMETOOLONG
);
832 free(ctx
->ct_origshare
);
833 if ((ctx
->ct_origshare
= strdup(share
)) == NULL
)
836 ctx
->ct_shtype_req
= stype
;
842 smb_ctx_setsrvaddr(struct smb_ctx
*ctx
, const char *addr
)
844 if (addr
== NULL
|| addr
[0] == 0)
846 free(ctx
->ct_srvaddr_s
);
847 if ((ctx
->ct_srvaddr_s
= strdup(addr
)) == NULL
)
853 * API for library caller to set signing enabled, required
854 * Note: if not enable, ignore require
857 smb_ctx_setsigning(struct smb_ctx
*ctx
, int enable
, int require
)
859 ctx
->ct_vopt
&= ~SMBVOPT_SIGNING_MASK
;
861 ctx
->ct_vopt
|= SMBVOPT_SIGNING_ENABLED
;
863 ctx
->ct_vopt
|= SMBVOPT_SIGNING_REQUIRED
;
869 smb_parse_owner(char *pair
, uid_t
*uid
, gid_t
*gid
)
873 char buf
[NSS_BUFLEN_PASSWD
];
876 cp
= strchr(pair
, ':');
880 if (getgrnam_r(cp
, &gr
, buf
, sizeof (buf
)) != NULL
) {
883 smb_error(dgettext(TEXT_DOMAIN
,
884 "Invalid group name %s, ignored"), 0, cp
);
888 struct passwd
*result
;
889 getpwnam_r(pair
, &pw
, buf
, sizeof (buf
), &result
);
893 smb_error(dgettext(TEXT_DOMAIN
,
894 "Invalid user name %s, ignored"), 0, pair
);
901 * Suport a securty options arg, i.e. -S noext,lm,ntlm
902 * for testing various type of authenticators.
906 /* noext - handled below */
907 { "anon", SMB_AT_ANON
},
908 { "lm", SMB_AT_LM1
},
909 { "ntlm", SMB_AT_NTLM1
},
910 { "ntlm2", SMB_AT_NTLM2
},
911 { "krb5", SMB_AT_KRB5
},
915 smb_parse_secopts(struct smb_ctx
*ctx
, const char *arg
)
917 const char *sep
= ":;,";
924 /* skip separators */
925 tlen
= strspn(p
, sep
);
928 nlen
= strcspn(p
, sep
);
932 if (nlen
== 5 && 0 == strncmp(p
, "noext", nlen
)) {
933 /* Don't offer extended security. */
934 ctx
->ct_vopt
&= ~SMBVOPT_EXT_SEC
;
939 /* This is rarely called, so not optimized. */
940 for (nv
= sectype_table
; nv
->name
; nv
++) {
941 tlen
= strlen(nv
->name
);
942 if (tlen
== nlen
&& 0 == strncmp(p
, nv
->name
, tlen
))
945 if (nv
->name
== NULL
) {
946 smb_error(dgettext(TEXT_DOMAIN
,
947 "%s: invalid security options"), 0, p
);
950 authflags
|= nv
->value
;
955 ctx
->ct_authflags
= authflags
;
961 * Commands use this with getopt. See:
962 * STDPARAM_OPT, STDPARAM_ARGS
963 * Called after smb_ctx_readrc().
966 smb_ctx_opt(struct smb_ctx
*ctx
, int opt
, const char *arg
)
975 /* Handled in smb_ctx_init() */
978 error
= smb_ctx_setsrvaddr(ctx
, arg
);
981 /* share connect rights - ignored */
982 ctx
->ct_flags
|= SMBCF_SRIGHTS
;
985 ctx
->ct_flags
|= SMBCF_NOPWD
;
992 error
= smb_parse_owner(cp
, &ctx
->ct_owner
, NULL
);
996 /* ctx->ct_vopt |= SMBCOPT_PERMANENT; */
999 /* retry count - ignored */
1002 /* Security options (undocumented, just for tests) */
1003 error
= smb_parse_secopts(ctx
, arg
);
1006 /* timeout - ignored */
1008 case 'D': /* domain */
1009 case 'W': /* workgroup (legacy alias) */
1010 error
= smb_ctx_setdomain(ctx
, tmp
, TRUE
);
1018 * Original code injected iconv tables into the kernel.
1019 * Not sure if we'll need this or not... REVISIT
1021 #ifdef KICONV_SUPPORT
1023 smb_addiconvtbl(const char *to
, const char *from
, const uchar_t
*tbl
)
1027 error
= kiconv_add_xlat_table(to
, from
, tbl
);
1028 if (error
&& error
!= EEXIST
) {
1029 smb_error(dgettext(TEXT_DOMAIN
,
1030 "can not setup kernel iconv table (%s:%s)"),
1036 #endif /* KICONV_SUPPORT */
1039 * Verify context info. before connect operation(s),
1040 * lookup specified server and try to fill all forgotten fields.
1041 * Legacy name used by commands.
1044 smb_ctx_resolve(struct smb_ctx
*ctx
)
1046 struct smbioc_ossn
*ssn
= &ctx
->ct_ssn
;
1048 #ifdef KICONV_SUPPORT
1054 dump_ctx("before smb_ctx_resolve", ctx
);
1056 ctx
->ct_flags
&= ~SMBCF_RESOLVED
;
1058 if (ctx
->ct_fullserver
== NULL
) {
1059 smb_error(dgettext(TEXT_DOMAIN
,
1060 "no server name specified"), 0);
1064 if (ctx
->ct_minlevel
>= SMBL_SHARE
&&
1065 ctx
->ct_origshare
== NULL
) {
1066 smb_error(dgettext(TEXT_DOMAIN
,
1067 "no share name specified for %s@%s"),
1068 0, ssn
->ssn_user
, ctx
->ct_fullserver
);
1071 error
= nb_ctx_resolve(ctx
->ct_nb
);
1074 #ifdef KICONV_SUPPORT
1075 if (ssn
->ioc_localcs
[0] == 0)
1076 strcpy(ssn
->ioc_localcs
, "default"); /* XXX: locale name ? */
1077 error
= smb_addiconvtbl("tolower", ssn
->ioc_localcs
, nls_lower
);
1080 error
= smb_addiconvtbl("toupper", ssn
->ioc_localcs
, nls_upper
);
1083 if (ssn
->ioc_servercs
[0] != 0) {
1084 for (i
= 0; i
< sizeof (cstbl
); i
++)
1086 nls_mem_toext(cstbl
, cstbl
, sizeof (cstbl
));
1087 error
= smb_addiconvtbl(ssn
->ioc_servercs
, ssn
->ioc_localcs
,
1091 for (i
= 0; i
< sizeof (cstbl
); i
++)
1093 nls_mem_toloc(cstbl
, cstbl
, sizeof (cstbl
));
1094 error
= smb_addiconvtbl(ssn
->ioc_localcs
, ssn
->ioc_servercs
,
1099 #endif /* KICONV_SUPPORT */
1102 * Lookup the IP address and fill in ct_addrinfo.
1104 * Note: smb_ctx_getaddr() returns a EAI_xxx
1105 * error value like getaddrinfo(3), but this
1106 * function needs to return an errno value.
1108 error
= smb_ctx_getaddr(ctx
);
1110 const char *ais
= gai_strerror(error
);
1111 smb_error(dgettext(TEXT_DOMAIN
,
1112 "can't resolve name\"%s\", %s"),
1113 0, ctx
->ct_fullserver
, ais
);
1116 assert(ctx
->ct_addrinfo
!= NULL
);
1119 * If we have a user name but no password,
1120 * check for a keychain entry.
1121 * XXX: Only for auth NTLM?
1123 if (ctx
->ct_user
[0] != '\0') {
1126 * If we don't have a p/w yet,
1129 if (ctx
->ct_password
[0] == '\0')
1130 (void) smb_get_keychain(ctx
);
1132 * Mask out disallowed auth types.
1134 ctx
->ct_authflags
&= ctx
->ct_minauth
;
1136 if (ctx
->ct_authflags
== 0) {
1137 smb_error(dgettext(TEXT_DOMAIN
,
1138 "no valid auth. types"), 0);
1142 ctx
->ct_flags
|= SMBCF_RESOLVED
;
1144 dump_ctx("after smb_ctx_resolve", ctx
);
1154 fd
= open("/dev/"NSMB_NAME
, O_RDWR
);
1159 /* This handle controls per-process resources. */
1160 (void) fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
1166 smb_ctx_gethandle(struct smb_ctx
*ctx
)
1171 if (ctx
->ct_dev_fd
!= -1) {
1172 rpc_cleanup_smbctx(ctx
);
1173 close(ctx
->ct_dev_fd
);
1174 ctx
->ct_dev_fd
= -1;
1175 ctx
->ct_flags
&= ~SMBCF_SSNACTIVE
;
1178 fd
= smb_open_driver();
1181 smb_error(dgettext(TEXT_DOMAIN
,
1182 "failed to open driver"), err
);
1187 * Check the driver version (paranoia)
1189 if (ioctl(fd
, SMBIOC_GETVERS
, &version
) < 0)
1191 if (version
!= NSMB_VERSION
) {
1192 smb_error(dgettext(TEXT_DOMAIN
,
1193 "incorrect driver version"), 0);
1198 ctx
->ct_dev_fd
= fd
;
1204 * Find or create a connection + logon session
1207 smb_ctx_get_ssn(struct smb_ctx
*ctx
)
1211 if ((ctx
->ct_flags
& SMBCF_RESOLVED
) == 0)
1214 if (ctx
->ct_dev_fd
< 0) {
1215 if ((err
= smb_ctx_gethandle(ctx
)))
1220 * Check whether the driver already has a VC
1221 * we can use. If so, we're done!
1223 err
= smb_ctx_findvc(ctx
);
1225 DPRINT("found an existing VC");
1228 * This calls the IOD to create a new session.
1230 DPRINT("setup a new VC");
1231 err
= smb_ctx_newvc(ctx
);
1236 * Call findvc again. The new VC sould be
1237 * found in the driver this time.
1239 err
= smb_ctx_findvc(ctx
);
1246 * Find or create a tree connection
1249 smb_ctx_get_tree(struct smb_ctx
*ctx
)
1251 smbioc_tcon_t
*tcon
= NULL
;
1254 if (ctx
->ct_dev_fd
< 0 ||
1255 ctx
->ct_origshare
== NULL
) {
1259 cmd
= SMBIOC_TREE_CONNECT
;
1260 tcon
= malloc(sizeof (*tcon
));
1263 bzero(tcon
, sizeof (*tcon
));
1264 tcon
->tc_flags
= SMBLK_CREATE
;
1267 /* The share name */
1268 strlcpy(tcon
->tc_sh
.sh_name
, ctx
->ct_origshare
,
1269 sizeof (tcon
->tc_sh
.sh_name
));
1271 /* The share "use" type. */
1272 tcon
->tc_sh
.sh_use
= ctx
->ct_shtype_req
;
1275 * Todo: share passwords for share-level security.
1277 * The driver does the actual TCON call.
1279 if (ioctl(ctx
->ct_dev_fd
, cmd
, tcon
) == -1) {
1285 * Check the returned share type
1287 DPRINT("ret. sh_type: \"%d\"", tcon
->tc_sh
.sh_type
);
1288 if (ctx
->ct_shtype_req
!= USE_WILDCARD
&&
1289 ctx
->ct_shtype_req
!= tcon
->tc_sh
.sh_type
) {
1290 smb_error(dgettext(TEXT_DOMAIN
,
1291 "%s: incompatible share type"),
1292 0, ctx
->ct_origshare
);
1302 * Return the hflags2 word for an smb_ctx.
1305 smb_ctx_flags2(struct smb_ctx
*ctx
)
1309 if (ioctl(ctx
->ct_dev_fd
, SMBIOC_FLAGS2
, &flags2
) == -1) {
1310 smb_error(dgettext(TEXT_DOMAIN
,
1311 "can't get flags2 for a session"), errno
);
1318 * Get the transport level session key.
1319 * Must already have an active SMB session.
1322 smb_fh_getssnkey(int dev_fd
, uchar_t
*key
, size_t len
)
1324 if (len
< SMBIOC_HASH_SZ
)
1327 if (ioctl(dev_fd
, SMBIOC_GETSSNKEY
, key
) == -1)
1334 * RC file parsing stuff
1339 /* Allowed auth. types */
1340 { "kerberos", SMB_AT_KRB5
},
1341 { "ntlmv2", SMB_AT_KRB5
|SMB_AT_NTLM2
},
1342 { "ntlm", SMB_AT_KRB5
|SMB_AT_NTLM2
|SMB_AT_NTLM1
},
1343 { "lm", SMB_AT_KRB5
|SMB_AT_NTLM2
|SMB_AT_NTLM1
|SMB_AT_LM1
},
1344 { "none", SMB_AT_KRB5
|SMB_AT_NTLM2
|SMB_AT_NTLM1
|SMB_AT_LM1
|
1355 * 3 - server:user:share
1358 smb_ctx_readrcsection(struct smb_ctx
*ctx
, const char *sname
, int level
)
1363 #ifdef KICONV_SUPPORT
1365 rc_getstringptr(smb_rc
, sname
, "charsets", &p
);
1367 error
= smb_ctx_setcharset(ctx
, p
);
1369 smb_error(dgettext(TEXT_DOMAIN
,
1370 "charset specification in the section '%s' ignored"),
1377 /* Section is: [default] or [server] */
1379 rc_getstringptr(smb_rc
, sname
, "minauth", &p
);
1382 * "minauth" was set in this section; override
1383 * the current minimum authentication setting.
1386 for (nvp
= minauth_table
; nvp
->name
; nvp
++)
1387 if (strcmp(p
, nvp
->name
) == 0)
1390 ctx
->ct_minauth
= nvp
->value
;
1393 * Unknown minimum authentication level.
1395 smb_error(dgettext(TEXT_DOMAIN
,
1396 "invalid minimum authentication level \"%s\" specified in the section %s"),
1402 rc_getstringptr(smb_rc
, sname
, "signing", &p
);
1405 * "signing" was set in this section; override
1406 * the current signing settings. Note:
1407 * setsigning flags are: enable, require
1409 if (strcmp(p
, "disabled") == 0) {
1410 (void) smb_ctx_setsigning(ctx
, FALSE
, FALSE
);
1411 } else if (strcmp(p
, "enabled") == 0) {
1412 (void) smb_ctx_setsigning(ctx
, TRUE
, FALSE
);
1413 } else if (strcmp(p
, "required") == 0) {
1414 (void) smb_ctx_setsigning(ctx
, TRUE
, TRUE
);
1417 * Unknown "signing" value.
1419 smb_error(dgettext(TEXT_DOMAIN
,
1420 "invalid signing policy \"%s\" specified in the section %s"),
1427 * Domain name. Allow both keywords:
1428 * "workgroup", "domain"
1430 * Note: these are NOT marked "from CMD".
1431 * See long comment at smb_ctx_init()
1433 rc_getstringptr(smb_rc
, sname
, "workgroup", &p
);
1435 error
= smb_ctx_setdomain(ctx
, p
, 0);
1437 smb_error(dgettext(TEXT_DOMAIN
,
1438 "workgroup specification in the "
1439 "section '%s' ignored"), error
, sname
);
1441 rc_getstringptr(smb_rc
, sname
, "domain", &p
);
1443 error
= smb_ctx_setdomain(ctx
, p
, 0);
1445 smb_error(dgettext(TEXT_DOMAIN
,
1446 "domain specification in the "
1447 "section '%s' ignored"), error
, sname
);
1450 rc_getstringptr(smb_rc
, sname
, "user", &p
);
1452 error
= smb_ctx_setuser(ctx
, p
, 0);
1454 smb_error(dgettext(TEXT_DOMAIN
,
1455 "user specification in the "
1456 "section '%s' ignored"), error
, sname
);
1461 /* Section is: [server] */
1462 rc_getstringptr(smb_rc
, sname
, "addr", &p
);
1464 error
= smb_ctx_setsrvaddr(ctx
, p
);
1466 smb_error(dgettext(TEXT_DOMAIN
,
1467 "invalid address specified in section %s"),
1474 rc_getstringptr(smb_rc
, sname
, "password", &p
);
1476 error
= smb_ctx_setpassword(ctx
, p
, 0);
1478 smb_error(dgettext(TEXT_DOMAIN
,
1479 "password specification in the section '%s' ignored"),
1487 * read rc file as follows:
1488 * 0: read [default] section
1489 * 1: override with [server] section
1490 * 2: override with [server:user] section
1491 * 3: override with [server:user:share] section
1492 * Since absence of rcfile is not fatal, silently ignore this fact.
1493 * smb_rc file should be closed by caller.
1496 smb_ctx_readrc(struct smb_ctx
*ctx
)
1498 char pwbuf
[NSS_BUFLEN_PASSWD
];
1503 struct passwd
*result
;
1506 * If the user name is not specified some other way,
1507 * use the current user name. Also save the homedir.
1508 * NB: ct_home=NULL is allowed, and we don't want to
1509 * bail out with an error for a missing ct_home.
1511 getpwuid_r(getuid(), &pw
, pwbuf
, sizeof (pwbuf
), &result
);
1513 if (ctx
->ct_user
[0] == 0)
1514 (void) smb_ctx_setuser(ctx
, pw
.pw_name
, B_FALSE
);
1515 if (ctx
->ct_home
== NULL
)
1516 ctx
->ct_home
= strdup(pw
.pw_dir
);
1519 if ((err
= smb_open_rcfile(ctx
->ct_home
)) != 0) {
1520 DPRINT("smb_open_rcfile, err=%d", err
);
1521 /* ignore any error here */
1525 sname_max
= 3 * SMBIOC_MAX_NAME
+ 4;
1526 sname
= malloc(sname_max
);
1527 if (sname
== NULL
) {
1533 * default parameters (level=0)
1535 smb_ctx_readrcsection(ctx
, "default", 0);
1536 nb_ctx_readrcsection(smb_rc
, ctx
->ct_nb
, "default", 0);
1539 * If we don't have a server name, we can't read any of the
1540 * [server...] sections.
1542 if (ctx
->ct_fullserver
== NULL
)
1545 * SERVER parameters.
1547 smb_ctx_readrcsection(ctx
, ctx
->ct_fullserver
, 1);
1550 * If we don't have a user name, we can't read any of the
1551 * [server:user...] sections.
1553 if (ctx
->ct_user
[0] == 0)
1556 * SERVER:USER parameters
1558 snprintf(sname
, sname_max
, "%s:%s",
1561 smb_ctx_readrcsection(ctx
, sname
, 2);
1565 * If we don't have a share name, we can't read any of the
1566 * [server:user:share] sections.
1568 if (ctx
->ct_origshare
== NULL
)
1571 * SERVER:USER:SHARE parameters
1573 snprintf(sname
, sname_max
, "%s:%s:%s",
1577 smb_ctx_readrcsection(ctx
, sname
, 3);
1583 dump_ctx("after smb_ctx_readrc", ctx
);
1585 DPRINT("err=%d\n", err
);
1591 smbfs_set_default_domain(const char *domain
)
1593 strlcpy(default_domain
, domain
, sizeof (default_domain
));
1597 smbfs_set_default_user(const char *user
)
1599 strlcpy(default_user
, user
, sizeof (default_user
));