1 /*
2 * Copyright (c) 2000, Boris Popov
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
19 *
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
30 * SUCH DAMAGE.
31 *
32 * $Id: ctx.c,v 1.32.70.2 2005/06/02 00:55:40 lindak Exp $
33 */
34
35 /*
36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
37 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
38 */
39
40 #include <sys/param.h>
41 #include <sys/ioctl.h>
42 #include <sys/time.h>
43 #include <sys/mount.h>
44 #include <sys/types.h>
45 #include <sys/byteorder.h>
46
47 #include <fcntl.h>
48 #include <ctype.h>
49 #include <errno.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <strings.h>
53 #include <stdlib.h>
54 #include <pwd.h>
55 #include <grp.h>
56 #include <unistd.h>
57 #include <libintl.h>
58 #include <assert.h>
59 #include <nss_dbdefs.h>
60
61 #include <cflib.h>
62 #include <netsmb/smb_lib.h>
63 #include <netsmb/netbios.h>
64 #include <netsmb/nb_lib.h>
65 #include <netsmb/smb_dev.h>
66
67 #include "charsets.h"
68 #include "private.h"
69 #include "ntlm.h"
70
71 #ifndef FALSE
72 #define FALSE 0
73 #endif
74 #ifndef TRUE
75 #define TRUE 1
76 #endif
77
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)
80
81 struct nv {
82 char *name;
83 int value;
84 };
85
86 /* These two may be set by commands. */
87 int smb_debug, smb_verbose;
88
89 /*
90 * Was: STDPARAM_OPT - see smb_ctx_scan_argv, smb_ctx_opt
91 */
92 const char smbutil_std_opts[] = "ABCD:E:I:L:M:NO:P:U:R:S:T:W:";
93
94 /*
95 * Defaults for new contexts (connections to servers).
96 * These are set by smbfs_set_default_...
97 */
98 static char default_domain[SMBIOC_MAX_NAME];
99 static char default_user[SMBIOC_MAX_NAME];
100
101
102 /*
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.
107 */
108 static smb_ctx_close_hook_t close_hook;
109 static void
rpc_cleanup_smbctx(struct smb_ctx * ctx)110 rpc_cleanup_smbctx(struct smb_ctx *ctx)
111 {
112 if (close_hook)
113 (*close_hook)(ctx);
114 }
115 void
smb_ctx_set_close_hook(smb_ctx_close_hook_t hook)116 smb_ctx_set_close_hook(smb_ctx_close_hook_t hook)
117 {
118 close_hook = hook;
119 }
120
121 void
dump_ctx_flags(int flags)122 dump_ctx_flags(int flags)
123 {
124 printf(" Flags: ");
125 if (flags == 0)
126 printf("0");
127 if (flags & SMBCF_NOPWD)
128 printf("NOPWD ");
129 if (flags & SMBCF_SRIGHTS)
130 printf("SRIGHTS ");
131 if (flags & SMBCF_LOCALE)
132 printf("LOCALE ");
133 if (flags & SMBCF_CMD_DOM)
134 printf("CMD_DOM ");
135 if (flags & SMBCF_CMD_USR)
136 printf("CMD_USR ");
137 if (flags & SMBCF_CMD_PW)
138 printf("CMD_PW ");
139 if (flags & SMBCF_RESOLVED)
140 printf("RESOLVED ");
141 if (flags & SMBCF_KCBAD)
142 printf("KCBAD ");
143 if (flags & SMBCF_KCFOUND)
144 printf("KCFOUND ");
145 if (flags & SMBCF_BROWSEOK)
146 printf("BROWSEOK ");
147 if (flags & SMBCF_AUTHREQ)
148 printf("AUTHREQ ");
149 if (flags & SMBCF_KCSAVE)
150 printf("KCSAVE ");
151 if (flags & SMBCF_XXX)
152 printf("XXX ");
153 if (flags & SMBCF_SSNACTIVE)
154 printf("SSNACTIVE ");
155 if (flags & SMBCF_KCDOMAIN)
156 printf("KCDOMAIN ");
157 printf("\n");
158 }
159
160 void
dump_iod_ssn(smb_iod_ssn_t * is)161 dump_iod_ssn(smb_iod_ssn_t *is)
162 {
163 static const char zeros[NTLM_HASH_SZ] = {0};
164 struct smbioc_ossn *ssn = &is->iod_ossn;
165
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);
173
174 printf(" ct_nthash:");
175 if (bcmp(zeros, &is->iod_nthash, NTLM_HASH_SZ))
176 smb_hexdump(&is->iod_nthash, NTLM_HASH_SZ);
177 else
178 printf(" {0}\n");
179
180 printf(" ct_lmhash:");
181 if (bcmp(zeros, &is->iod_lmhash, NTLM_HASH_SZ))
182 smb_hexdump(&is->iod_lmhash, NTLM_HASH_SZ);
183 else
184 printf(" {0}\n");
185 }
186
187 void
dump_ctx(char * where,struct smb_ctx * ctx)188 dump_ctx(char *where, struct smb_ctx *ctx)
189 {
190 printf("context %s:\n", where);
191 dump_ctx_flags(ctx->ct_flags);
192
193 if (ctx->ct_locname)
194 printf(" localname=\"%s\"", ctx->ct_locname);
195 else
196 printf(" localname=NULL");
197
198 if (ctx->ct_fullserver)
199 printf(" fullserver=\"%s\"", ctx->ct_fullserver);
200 else
201 printf(" fullserver=NULL");
202
203 if (ctx->ct_srvaddr_s)
204 printf(" srvaddr_s=\"%s\"\n", ctx->ct_srvaddr_s);
205 else
206 printf(" srvaddr_s=NULL\n");
207
208 if (ctx->ct_addrinfo)
209 dump_addrinfo(ctx->ct_addrinfo);
210 else
211 printf(" ct_addrinfo = NULL\n");
212
213 dump_iod_ssn(&ctx->ct_iod_ssn);
214
215 printf(" share_name=\"%s\", share_type=%d\n",
216 ctx->ct_origshare ? ctx->ct_origshare : "",
217 ctx->ct_shtype_req);
218
219 printf(" ct_home=\"%s\"\n", ctx->ct_home);
220 printf(" ct_rpath=\"%s\"\n", ctx->ct_rpath);
221 }
222
223 int
smb_ctx_alloc(struct smb_ctx ** ctx_pp)224 smb_ctx_alloc(struct smb_ctx **ctx_pp)
225 {
226 smb_ctx_t *ctx;
227 int err;
228
229 ctx = malloc(sizeof (*ctx));
230 if (ctx == NULL)
231 return (ENOMEM);
232 err = smb_ctx_init(ctx);
233 if (err != 0) {
234 free(ctx);
235 return (err);
236 }
237 *ctx_pp = ctx;
238 return (0);
239 }
240
241 /*
242 * Initialize an smb_ctx struct (defaults)
243 */
244 int
smb_ctx_init(struct smb_ctx * ctx)245 smb_ctx_init(struct smb_ctx *ctx)
246 {
247 int error;
248
249 bzero(ctx, sizeof (*ctx));
250
251 error = nb_ctx_create(&ctx->ct_nb);
252 if (error)
253 return (error);
254
255 ctx->ct_dev_fd = -1;
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;
261
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;
267
268 /*
269 * Default domain, user, ...
270 */
271 strlcpy(ctx->ct_domain, default_domain,
272 sizeof (ctx->ct_domain));
273 strlcpy(ctx->ct_user, default_user,
274 sizeof (ctx->ct_user));
275
276 return (0);
277 }
278
279 /*
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.
283 *
284 * The sequence for getting all the members filled in
285 * has some tricky aspects. Here's how it works:
286 *
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)
292 * built-in defaults
293 *
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.
297 *
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_*
304 *
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.)
308 *
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.
313 */
314 int
smb_ctx_scan_argv(struct smb_ctx * ctx,int argc,char ** argv,int minlevel,int maxlevel,int sharetype)315 smb_ctx_scan_argv(struct smb_ctx *ctx, int argc, char **argv,
316 int minlevel, int maxlevel, int sharetype)
317 {
318 int ind, opt, error = 0;
319 int aflg = 0, uflg = 0;
320 const char *arg;
321
322 /*
323 * Parse options, if any. Values from here too
324 * are marked as "from CMD".
325 */
326 if (argv == NULL)
327 return (0);
328
329 ctx->ct_minlevel = minlevel;
330 ctx->ct_maxlevel = maxlevel;
331 ctx->ct_shtype_req = sharetype;
332
333 cf_opt_lock();
334 /* Careful: no return/goto before cf_opt_unlock! */
335 while (error == 0) {
336 opt = cf_getopt(argc, argv, STDPARAM_OPT);
337 if (opt == -1)
338 break;
339 arg = cf_optarg;
340 /* NB: handle most in smb_ctx_opt */
341 switch (opt) {
342 case 'A':
343 aflg = 1;
344 error = smb_ctx_setuser(ctx, "", TRUE);
345 ctx->ct_flags |= SMBCF_NOPWD;
346 break;
347 case 'U':
348 uflg = 1;
349 error = smb_ctx_setuser(ctx, arg, TRUE);
350 break;
351 default:
352 DPRINT("skip opt=%c", opt);
353 break;
354 }
355 }
356 ind = cf_optind;
357 arg = argv[ind];
358 cf_optind = cf_optreset = 1;
359 cf_opt_unlock();
360
361 if (error)
362 return (error);
363
364 if (aflg && uflg) {
365 printf(gettext("-A and -U flags are exclusive.\n"));
366 return (EINVAL);
367 }
368
369 /*
370 * Parse the UNC path. Values from here are
371 * marked as "from CMD".
372 */
373 for (; ind < argc; ind++) {
374 arg = argv[ind];
375 if (strncmp(arg, "//", 2) != 0)
376 continue;
377 error = smb_ctx_parseunc(ctx, arg,
378 minlevel, maxlevel, sharetype, &arg);
379 if (error)
380 return (error);
381 break;
382 }
383
384 return (error);
385 }
386
387 void
smb_ctx_free(smb_ctx_t * ctx)388 smb_ctx_free(smb_ctx_t *ctx)
389 {
390 smb_ctx_done(ctx);
391 free(ctx);
392 }
393
394 void
smb_ctx_done(struct smb_ctx * ctx)395 smb_ctx_done(struct smb_ctx *ctx)
396 {
397
398 rpc_cleanup_smbctx(ctx);
399
400 if (ctx->ct_dev_fd != -1) {
401 close(ctx->ct_dev_fd);
402 ctx->ct_dev_fd = -1;
403 }
404 if (ctx->ct_door_fd != -1) {
405 close(ctx->ct_door_fd);
406 ctx->ct_door_fd = -1;
407 }
408 if (ctx->ct_tran_fd != -1) {
409 close(ctx->ct_tran_fd);
410 ctx->ct_tran_fd = -1;
411 }
412 if (ctx->ct_srvaddr_s) {
413 free(ctx->ct_srvaddr_s);
414 ctx->ct_srvaddr_s = NULL;
415 }
416 if (ctx->ct_nb) {
417 nb_ctx_done(ctx->ct_nb);
418 ctx->ct_nb = NULL;
419 }
420 if (ctx->ct_locname) {
421 free(ctx->ct_locname);
422 ctx->ct_locname = NULL;
423 }
424 if (ctx->ct_origshare) {
425 free(ctx->ct_origshare);
426 ctx->ct_origshare = NULL;
427 }
428 if (ctx->ct_fullserver) {
429 free(ctx->ct_fullserver);
430 ctx->ct_fullserver = NULL;
431 }
432 if (ctx->ct_addrinfo) {
433 freeaddrinfo(ctx->ct_addrinfo);
434 ctx->ct_addrinfo = NULL;
435 }
436 if (ctx->ct_home) {
437 free(ctx->ct_home);
438 ctx->ct_home = NULL;
439 }
440 if (ctx->ct_rpath) {
441 free(ctx->ct_rpath);
442 ctx->ct_rpath = NULL;
443 }
444 if (ctx->ct_srv_OS) {
445 free(ctx->ct_srv_OS);
446 ctx->ct_srv_OS = NULL;
447 }
448 if (ctx->ct_srv_LM) {
449 free(ctx->ct_srv_LM);
450 ctx->ct_srv_LM = NULL;
451 }
452 if (ctx->ct_mackey) {
453 free(ctx->ct_mackey);
454 ctx->ct_mackey = NULL;
455 }
456 }
457
458 /*
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".
463 */
464 int
smb_ctx_parseunc(struct smb_ctx * ctx,const char * unc,int minlevel,int maxlevel,int sharetype,const char ** next)465 smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc,
466 int minlevel, int maxlevel, int sharetype,
467 const char **next)
468 {
469 char tmp[1024];
470 char *host, *share, *path;
471 char *dom, *usr, *pw, *p;
472 int error;
473
474 /*
475 * This may be called outside of _scan_argv,
476 * so make sure these get initialized.
477 */
478 ctx->ct_minlevel = minlevel;
479 ctx->ct_maxlevel = maxlevel;
480 ctx->ct_shtype_req = sharetype;
481 ctx->ct_parsedlevel = SMBL_NONE;
482
483 dom = usr = pw = host = NULL;
484
485 /* Work on a temporary copy, fix back slashes. */
486 strlcpy(tmp, unc, sizeof (tmp));
487 for (p = tmp; *p; p++)
488 if (*p == '\\')
489 *p = '/';
490
491 if (tmp[0] != '/' || tmp[1] != '/') {
492 smb_error(dgettext(TEXT_DOMAIN,
493 "UNC should start with '//'"), 0);
494 error = EINVAL;
495 goto out;
496 }
497 p = tmp + 2; /* user@host... */
498
499 /* Find the share part, if any. */
500 share = strchr(p, '/');
501 if (share)
502 *share = '\0';
503 (void) unpercent(p); /* host component */
504
505 /*
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)
510 */
511 host = strrchr(p, '@');
512 if (host == NULL) {
513 host = p; /* no user@ prefix */
514 } else {
515 *host++ = '\0';
516
517 /* may have [[domain;]user[:passwd]] */
518 pw = strchr(p, ':');
519 if (pw)
520 *pw++ = '\0';
521 usr = strchr(p, ';');
522 if (usr) {
523 *usr++ = '\0';
524 dom = p;
525 } else
526 usr = p;
527 }
528
529 if (*host == '\0') {
530 smb_error(dgettext(TEXT_DOMAIN, "empty server name"), 0);
531 error = EINVAL;
532 goto out;
533 }
534 error = smb_ctx_setfullserver(ctx, host);
535 if (error)
536 goto out;
537 ctx->ct_parsedlevel = SMBL_VC;
538
539 if (dom != NULL) {
540 error = smb_ctx_setdomain(ctx, dom, TRUE);
541 if (error)
542 goto out;
543 }
544 if (usr != NULL) {
545 if (*usr == '\0') {
546 smb_error(dgettext(TEXT_DOMAIN,
547 "empty user name"), 0);
548 error = EINVAL;
549 goto out;
550 }
551 if (ctx->ct_maxlevel < SMBL_VC) {
552 smb_error(dgettext(TEXT_DOMAIN,
553 "no user name required"), 0);
554 error = EINVAL;
555 goto out;
556 }
557 error = smb_ctx_setuser(ctx, usr, TRUE);
558 if (error)
559 goto out;
560 }
561 if (pw != NULL) {
562 error = smb_ctx_setpassword(ctx, pw, TRUE);
563 if (error)
564 goto out;
565 }
566
567 if (share != NULL) {
568 /* restore the slash */
569 *share = '/';
570 p = share + 1;
571
572 /* Find the path part, if any. */
573 path = strchr(p, '/');
574 if (path)
575 *path = '\0';
576 (void) unpercent(p); /* share component */
577
578 if (*p == '\0') {
579 smb_error(dgettext(TEXT_DOMAIN,
580 "empty share name"), 0);
581 error = EINVAL;
582 goto out;
583 }
584 if (ctx->ct_maxlevel < SMBL_SHARE) {
585 smb_error(dgettext(TEXT_DOMAIN,
586 "no share name required"), 0);
587 error = EINVAL;
588 goto out;
589 }
590
591 /*
592 * Special case UNC names like:
593 * //host/PIPE/endpoint
594 * to have share: IPC$
595 */
596 if (strcasecmp(p, "PIPE") == 0) {
597 sharetype = USE_IPC;
598 p = "IPC$";
599 }
600 error = smb_ctx_setshare(ctx, p, sharetype);
601 if (error)
602 goto out;
603 ctx->ct_parsedlevel = SMBL_SHARE;
604
605 if (path) {
606 /* restore the slash */
607 *path = '/';
608 p = path + 1;
609 (void) unpercent(p); /* remainder */
610 free(ctx->ct_rpath);
611 ctx->ct_rpath = strdup(path);
612 }
613 } else if (ctx->ct_minlevel >= SMBL_SHARE) {
614 smb_error(dgettext(TEXT_DOMAIN, "empty share name"), 0);
615 error = EINVAL;
616 goto out;
617 }
618
619 if (next)
620 *next = NULL;
621
622 out:
623 if (error == 0 && smb_debug > 0)
624 dump_ctx("after smb_ctx_parseunc", ctx);
625
626 return (error);
627 }
628
629 #ifdef KICONV_SUPPORT
630 int
smb_ctx_setcharset(struct smb_ctx * ctx,const char * arg)631 smb_ctx_setcharset(struct smb_ctx *ctx, const char *arg)
632 {
633 char *cp, *servercs, *localcs;
634 int cslen = sizeof (ctx->ct_ssn.ioc_localcs);
635 int scslen, lcslen, error;
636
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);
642 return (EINVAL);
643 }
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);
648 return (EINVAL);
649 }
650 localcs = memcpy(ctx->ct_ssn.ioc_localcs, arg, lcslen);
651 localcs[lcslen] = 0;
652 servercs = strcpy(ctx->ct_ssn.ioc_servercs, cp);
653 error = nls_setrecode(localcs, servercs);
654 if (error == 0)
655 return (0);
656 smb_error(dgettext(TEXT_DOMAIN,
657 "can't initialize iconv support (%s:%s)"),
658 error, localcs, servercs);
659 localcs[0] = 0;
660 servercs[0] = 0;
661 return (error);
662 }
663 #endif /* KICONV_SUPPORT */
664
665 int
smb_ctx_setauthflags(struct smb_ctx * ctx,int flags)666 smb_ctx_setauthflags(struct smb_ctx *ctx, int flags)
667 {
668 ctx->ct_authflags = flags;
669 return (0);
670 }
671
672 int
smb_ctx_setfullserver(struct smb_ctx * ctx,const char * name)673 smb_ctx_setfullserver(struct smb_ctx *ctx, const char *name)
674 {
675 char *p = strdup(name);
676
677 if (p == NULL)
678 return (ENOMEM);
679 if (ctx->ct_fullserver)
680 free(ctx->ct_fullserver);
681 ctx->ct_fullserver = p;
682 return (0);
683 }
684
685 int
smb_ctx_setserver(struct smb_ctx * ctx,const char * name)686 smb_ctx_setserver(struct smb_ctx *ctx, const char *name)
687 {
688 strlcpy(ctx->ct_srvname, name,
689 sizeof (ctx->ct_srvname));
690 return (0);
691 }
692
693 int
smb_ctx_setuser(struct smb_ctx * ctx,const char * name,int from_cmd)694 smb_ctx_setuser(struct smb_ctx *ctx, const char *name, int from_cmd)
695 {
696
697 if (strlen(name) >= sizeof (ctx->ct_user)) {
698 smb_error(dgettext(TEXT_DOMAIN,
699 "user name '%s' too long"), 0, name);
700 return (ENAMETOOLONG);
701 }
702
703 /*
704 * Don't overwrite a value from the command line
705 * with one from anywhere else.
706 */
707 if (!from_cmd && (ctx->ct_flags & SMBCF_CMD_USR))
708 return (0);
709
710 strlcpy(ctx->ct_user, name,
711 sizeof (ctx->ct_user));
712
713 /* Mark this as "from the command line". */
714 if (from_cmd)
715 ctx->ct_flags |= SMBCF_CMD_USR;
716
717 return (0);
718 }
719
720 /*
721 * Don't overwrite a domain name from the
722 * command line with one from anywhere else.
723 * See smb_ctx_init() for notes about this.
724 */
725 int
smb_ctx_setdomain(struct smb_ctx * ctx,const char * name,int from_cmd)726 smb_ctx_setdomain(struct smb_ctx *ctx, const char *name, int from_cmd)
727 {
728
729 if (strlen(name) >= sizeof (ctx->ct_domain)) {
730 smb_error(dgettext(TEXT_DOMAIN,
731 "workgroup name '%s' too long"), 0, name);
732 return (ENAMETOOLONG);
733 }
734
735 /*
736 * Don't overwrite a value from the command line
737 * with one from anywhere else.
738 */
739 if (!from_cmd && (ctx->ct_flags & SMBCF_CMD_DOM))
740 return (0);
741
742 strlcpy(ctx->ct_domain, name,
743 sizeof (ctx->ct_domain));
744
745 /* Mark this as "from the command line". */
746 if (from_cmd)
747 ctx->ct_flags |= SMBCF_CMD_DOM;
748
749 return (0);
750 }
751
752 int
smb_ctx_setpassword(struct smb_ctx * ctx,const char * passwd,int from_cmd)753 smb_ctx_setpassword(struct smb_ctx *ctx, const char *passwd, int from_cmd)
754 {
755 int err;
756
757 if (passwd == NULL)
758 return (EINVAL);
759 if (strlen(passwd) >= sizeof (ctx->ct_password)) {
760 smb_error(dgettext(TEXT_DOMAIN, "password too long"), 0);
761 return (ENAMETOOLONG);
762 }
763
764 /*
765 * If called again after comand line parsing,
766 * don't overwrite a value from the command line
767 * with one from any stored config.
768 */
769 if (!from_cmd && (ctx->ct_flags & SMBCF_CMD_PW))
770 return (0);
771
772 memset(ctx->ct_password, 0, sizeof (ctx->ct_password));
773 if (strncmp(passwd, "$$1", 3) == 0)
774 (void) smb_simpledecrypt(ctx->ct_password, passwd);
775 else
776 strlcpy(ctx->ct_password, passwd,
777 sizeof (ctx->ct_password));
778
779 /*
780 * Compute LM hash, NT hash.
781 */
782 if (ctx->ct_password[0]) {
783 err = ntlm_compute_nt_hash(ctx->ct_nthash, ctx->ct_password);
784 if (err != 0)
785 return (err);
786 err = ntlm_compute_lm_hash(ctx->ct_lmhash, ctx->ct_password);
787 if (err != 0)
788 return (err);
789 }
790
791 /* Mark this as "from the command line". */
792 if (from_cmd)
793 ctx->ct_flags |= SMBCF_CMD_PW;
794
795 return (0);
796 }
797
798 /*
799 * Use this to set NTLM auth. info (hashes)
800 * when we don't have the password.
801 */
802 int
smb_ctx_setpwhash(smb_ctx_t * ctx,const uchar_t * nthash,const uchar_t * lmhash)803 smb_ctx_setpwhash(smb_ctx_t *ctx,
804 const uchar_t *nthash, const uchar_t *lmhash)
805 {
806
807 /* Need ct_password to be non-null. */
808 if (ctx->ct_password[0] == '\0')
809 strlcpy(ctx->ct_password, "$HASH",
810 sizeof (ctx->ct_password));
811
812 /*
813 * Compute LM hash, NT hash.
814 */
815 memcpy(ctx->ct_nthash, nthash, NTLM_HASH_SZ);
816
817 /* The LM hash is optional */
818 if (lmhash) {
819 memcpy(ctx->ct_nthash, nthash, NTLM_HASH_SZ);
820 }
821
822 return (0);
823 }
824
825 int
smb_ctx_setshare(struct smb_ctx * ctx,const char * share,int stype)826 smb_ctx_setshare(struct smb_ctx *ctx, const char *share, int stype)
827 {
828 if (strlen(share) >= SMBIOC_MAX_NAME) {
829 smb_error(dgettext(TEXT_DOMAIN,
830 "share name '%s' too long"), 0, share);
831 return (ENAMETOOLONG);
832 }
833 if (ctx->ct_origshare)
834 free(ctx->ct_origshare);
835 if ((ctx->ct_origshare = strdup(share)) == NULL)
836 return (ENOMEM);
837
838 ctx->ct_shtype_req = stype;
839
840 return (0);
841 }
842
843 int
smb_ctx_setsrvaddr(struct smb_ctx * ctx,const char * addr)844 smb_ctx_setsrvaddr(struct smb_ctx *ctx, const char *addr)
845 {
846 if (addr == NULL || addr[0] == 0)
847 return (EINVAL);
848 if (ctx->ct_srvaddr_s)
849 free(ctx->ct_srvaddr_s);
850 if ((ctx->ct_srvaddr_s = strdup(addr)) == NULL)
851 return (ENOMEM);
852 return (0);
853 }
854
855 /*
856 * API for library caller to set signing enabled, required
857 * Note: if not enable, ignore require
858 */
859 int
smb_ctx_setsigning(struct smb_ctx * ctx,int enable,int require)860 smb_ctx_setsigning(struct smb_ctx *ctx, int enable, int require)
861 {
862 ctx->ct_vopt &= ~SMBVOPT_SIGNING_MASK;
863 if (enable) {
864 ctx->ct_vopt |= SMBVOPT_SIGNING_ENABLED;
865 if (require)
866 ctx->ct_vopt |= SMBVOPT_SIGNING_REQUIRED;
867 }
868 return (0);
869 }
870
871 static int
smb_parse_owner(char * pair,uid_t * uid,gid_t * gid)872 smb_parse_owner(char *pair, uid_t *uid, gid_t *gid)
873 {
874 struct group gr;
875 struct passwd pw;
876 char buf[NSS_BUFLEN_PASSWD];
877 char *cp;
878
879 cp = strchr(pair, ':');
880 if (cp) {
881 *cp++ = '\0';
882 if (*cp && gid) {
883 if (getgrnam_r(cp, &gr, buf, sizeof (buf)) != NULL) {
884 *gid = gr.gr_gid;
885 } else
886 smb_error(dgettext(TEXT_DOMAIN,
887 "Invalid group name %s, ignored"), 0, cp);
888 }
889 }
890 if (*pair) {
891 if (getpwnam_r(pair, &pw, buf, sizeof (buf)) != NULL) {
892 *uid = pw.pw_uid;
893 } else
894 smb_error(dgettext(TEXT_DOMAIN,
895 "Invalid user name %s, ignored"), 0, pair);
896 }
897
898 return (0);
899 }
900
901 /*
902 * Suport a securty options arg, i.e. -S noext,lm,ntlm
903 * for testing various type of authenticators.
904 */
905 static struct nv
906 sectype_table[] = {
907 /* noext - handled below */
908 { "anon", SMB_AT_ANON },
909 { "lm", SMB_AT_LM1 },
910 { "ntlm", SMB_AT_NTLM1 },
911 { "ntlm2", SMB_AT_NTLM2 },
912 { "krb5", SMB_AT_KRB5 },
913 { NULL, 0 },
914 };
915 int
smb_parse_secopts(struct smb_ctx * ctx,const char * arg)916 smb_parse_secopts(struct smb_ctx *ctx, const char *arg)
917 {
918 const char *sep = ":;,";
919 const char *p = arg;
920 struct nv *nv;
921 int nlen, tlen;
922 int authflags = 0;
923
924 for (;;) {
925 /* skip separators */
926 tlen = strspn(p, sep);
927 p += tlen;
928
929 nlen = strcspn(p, sep);
930 if (nlen == 0)
931 break;
932
933 if (nlen == 5 && 0 == strncmp(p, "noext", nlen)) {
934 /* Don't offer extended security. */
935 ctx->ct_vopt &= ~SMBVOPT_EXT_SEC;
936 p += nlen;
937 continue;
938 }
939
940 /* This is rarely called, so not optimized. */
941 for (nv = sectype_table; nv->name; nv++) {
942 tlen = strlen(nv->name);
943 if (tlen == nlen && 0 == strncmp(p, nv->name, tlen))
944 break;
945 }
946 if (nv->name == NULL) {
947 smb_error(dgettext(TEXT_DOMAIN,
948 "%s: invalid security options"), 0, p);
949 return (EINVAL);
950 }
951 authflags |= nv->value;
952 p += nlen;
953 }
954
955 if (authflags)
956 ctx->ct_authflags = authflags;
957
958 return (0);
959 }
960
961 /*
962 * Commands use this with getopt. See:
963 * STDPARAM_OPT, STDPARAM_ARGS
964 * Called after smb_ctx_readrc().
965 */
966 int
smb_ctx_opt(struct smb_ctx * ctx,int opt,const char * arg)967 smb_ctx_opt(struct smb_ctx *ctx, int opt, const char *arg)
968 {
969 int error = 0;
970 char *p, *cp;
971 char tmp[1024];
972
973 switch (opt) {
974 case 'A':
975 case 'U':
976 /* Handled in smb_ctx_init() */
977 break;
978 case 'I':
979 error = smb_ctx_setsrvaddr(ctx, arg);
980 break;
981 case 'M':
982 /* share connect rights - ignored */
983 ctx->ct_flags |= SMBCF_SRIGHTS;
984 break;
985 case 'N':
986 ctx->ct_flags |= SMBCF_NOPWD;
987 break;
988 case 'O':
989 p = strdup(arg);
990 cp = strchr(p, '/');
991 if (cp)
992 *cp = '\0';
993 error = smb_parse_owner(cp, &ctx->ct_owner, NULL);
994 free(p);
995 break;
996 case 'P':
997 /* ctx->ct_vopt |= SMBCOPT_PERMANENT; */
998 break;
999 case 'R':
1000 /* retry count - ignored */
1001 break;
1002 case 'S':
1003 /* Security options (undocumented, just for tests) */
1004 error = smb_parse_secopts(ctx, arg);
1005 break;
1006 case 'T':
1007 /* timeout - ignored */
1008 break;
1009 case 'D': /* domain */
1010 case 'W': /* workgroup (legacy alias) */
1011 error = smb_ctx_setdomain(ctx, tmp, TRUE);
1012 break;
1013 }
1014 return (error);
1015 }
1016
1017
1018 /*
1019 * Original code injected iconv tables into the kernel.
1020 * Not sure if we'll need this or not... REVISIT
1021 */
1022 #ifdef KICONV_SUPPORT
1023 static int
smb_addiconvtbl(const char * to,const char * from,const uchar_t * tbl)1024 smb_addiconvtbl(const char *to, const char *from, const uchar_t *tbl)
1025 {
1026 int error = 0;
1027
1028 error = kiconv_add_xlat_table(to, from, tbl);
1029 if (error && error != EEXIST) {
1030 smb_error(dgettext(TEXT_DOMAIN,
1031 "can not setup kernel iconv table (%s:%s)"),
1032 error, from, to);
1033 return (error);
1034 }
1035 return (error);
1036 }
1037 #endif /* KICONV_SUPPORT */
1038
1039 /*
1040 * Verify context info. before connect operation(s),
1041 * lookup specified server and try to fill all forgotten fields.
1042 * Legacy name used by commands.
1043 */
1044 int
smb_ctx_resolve(struct smb_ctx * ctx)1045 smb_ctx_resolve(struct smb_ctx *ctx)
1046 {
1047 struct smbioc_ossn *ssn = &ctx->ct_ssn;
1048 int error = 0;
1049 #ifdef KICONV_SUPPORT
1050 uchar_t cstbl[256];
1051 uint_t i;
1052 #endif
1053
1054 if (smb_debug)
1055 dump_ctx("before smb_ctx_resolve", ctx);
1056
1057 ctx->ct_flags &= ~SMBCF_RESOLVED;
1058
1059 if (ctx->ct_fullserver == NULL) {
1060 smb_error(dgettext(TEXT_DOMAIN,
1061 "no server name specified"), 0);
1062 return (EINVAL);
1063 }
1064
1065 if (ctx->ct_minlevel >= SMBL_SHARE &&
1066 ctx->ct_origshare == NULL) {
1067 smb_error(dgettext(TEXT_DOMAIN,
1068 "no share name specified for %s@%s"),
1069 0, ssn->ssn_user, ctx->ct_fullserver);
1070 return (EINVAL);
1071 }
1072 error = nb_ctx_resolve(ctx->ct_nb);
1073 if (error)
1074 return (error);
1075 #ifdef KICONV_SUPPORT
1076 if (ssn->ioc_localcs[0] == 0)
1077 strcpy(ssn->ioc_localcs, "default"); /* XXX: locale name ? */
1078 error = smb_addiconvtbl("tolower", ssn->ioc_localcs, nls_lower);
1079 if (error)
1080 return (error);
1081 error = smb_addiconvtbl("toupper", ssn->ioc_localcs, nls_upper);
1082 if (error)
1083 return (error);
1084 if (ssn->ioc_servercs[0] != 0) {
1085 for (i = 0; i < sizeof (cstbl); i++)
1086 cstbl[i] = i;
1087 nls_mem_toext(cstbl, cstbl, sizeof (cstbl));
1088 error = smb_addiconvtbl(ssn->ioc_servercs, ssn->ioc_localcs,
1089 cstbl);
1090 if (error)
1091 return (error);
1092 for (i = 0; i < sizeof (cstbl); i++)
1093 cstbl[i] = i;
1094 nls_mem_toloc(cstbl, cstbl, sizeof (cstbl));
1095 error = smb_addiconvtbl(ssn->ioc_localcs, ssn->ioc_servercs,
1096 cstbl);
1097 if (error)
1098 return (error);
1099 }
1100 #endif /* KICONV_SUPPORT */
1101
1102 /*
1103 * Lookup the IP address and fill in ct_addrinfo.
1104 *
1105 * Note: smb_ctx_getaddr() returns a EAI_xxx
1106 * error value like getaddrinfo(3), but this
1107 * function needs to return an errno value.
1108 */
1109 error = smb_ctx_getaddr(ctx);
1110 if (error) {
1111 const char *ais = gai_strerror(error);
1112 smb_error(dgettext(TEXT_DOMAIN,
1113 "can't resolve name\"%s\", %s"),
1114 0, ctx->ct_fullserver, ais);
1115 return (ENODATA);
1116 }
1117 assert(ctx->ct_addrinfo != NULL);
1118
1119 /*
1120 * If we have a user name but no password,
1121 * check for a keychain entry.
1122 * XXX: Only for auth NTLM?
1123 */
1124 if (ctx->ct_user[0] != '\0') {
1125 /*
1126 * Have a user name.
1127 * If we don't have a p/w yet,
1128 * try the keychain.
1129 */
1130 if (ctx->ct_password[0] == '\0')
1131 (void) smb_get_keychain(ctx);
1132 /*
1133 * Mask out disallowed auth types.
1134 */
1135 ctx->ct_authflags &= ctx->ct_minauth;
1136 }
1137 if (ctx->ct_authflags == 0) {
1138 smb_error(dgettext(TEXT_DOMAIN,
1139 "no valid auth. types"), 0);
1140 return (ENOTSUP);
1141 }
1142
1143 ctx->ct_flags |= SMBCF_RESOLVED;
1144 if (smb_debug)
1145 dump_ctx("after smb_ctx_resolve", ctx);
1146
1147 return (0);
1148 }
1149
1150 int
smb_open_driver()1151 smb_open_driver()
1152 {
1153 int fd;
1154
1155 fd = open("/dev/"NSMB_NAME, O_RDWR);
1156 if (fd < 0) {
1157 return (-1);
1158 }
1159
1160 /* This handle controls per-process resources. */
1161 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
1162
1163 return (fd);
1164 }
1165
1166 int
smb_ctx_gethandle(struct smb_ctx * ctx)1167 smb_ctx_gethandle(struct smb_ctx *ctx)
1168 {
1169 int fd, err;
1170 uint32_t version;
1171
1172 if (ctx->ct_dev_fd != -1) {
1173 rpc_cleanup_smbctx(ctx);
1174 close(ctx->ct_dev_fd);
1175 ctx->ct_dev_fd = -1;
1176 ctx->ct_flags &= ~SMBCF_SSNACTIVE;
1177 }
1178
1179 fd = smb_open_driver();
1180 if (fd < 0) {
1181 err = errno;
1182 smb_error(dgettext(TEXT_DOMAIN,
1183 "failed to open driver"), err);
1184 return (err);
1185 }
1186
1187 /*
1188 * Check the driver version (paranoia)
1189 */
1190 if (ioctl(fd, SMBIOC_GETVERS, &version) < 0)
1191 version = 0;
1192 if (version != NSMB_VERSION) {
1193 smb_error(dgettext(TEXT_DOMAIN,
1194 "incorrect driver version"), 0);
1195 close(fd);
1196 return (ENODEV);
1197 }
1198
1199 ctx->ct_dev_fd = fd;
1200 return (0);
1201 }
1202
1203
1204 /*
1205 * Find or create a connection + logon session
1206 */
1207 int
smb_ctx_get_ssn(struct smb_ctx * ctx)1208 smb_ctx_get_ssn(struct smb_ctx *ctx)
1209 {
1210 int err = 0;
1211
1212 if ((ctx->ct_flags & SMBCF_RESOLVED) == 0)
1213 return (EINVAL);
1214
1215 if (ctx->ct_dev_fd < 0) {
1216 if ((err = smb_ctx_gethandle(ctx)))
1217 return (err);
1218 }
1219
1220 /*
1221 * Check whether the driver already has a VC
1222 * we can use. If so, we're done!
1223 */
1224 err = smb_ctx_findvc(ctx);
1225 if (err == 0) {
1226 DPRINT("found an existing VC");
1227 } else {
1228 /*
1229 * This calls the IOD to create a new session.
1230 */
1231 DPRINT("setup a new VC");
1232 err = smb_ctx_newvc(ctx);
1233 if (err != 0)
1234 return (err);
1235
1236 /*
1237 * Call findvc again. The new VC sould be
1238 * found in the driver this time.
1239 */
1240 err = smb_ctx_findvc(ctx);
1241 }
1242
1243 return (err);
1244 }
1245
1246 /*
1247 * Find or create a tree connection
1248 */
1249 int
smb_ctx_get_tree(struct smb_ctx * ctx)1250 smb_ctx_get_tree(struct smb_ctx *ctx)
1251 {
1252 smbioc_tcon_t *tcon = NULL;
1253 int cmd, err = 0;
1254
1255 if (ctx->ct_dev_fd < 0 ||
1256 ctx->ct_origshare == NULL) {
1257 return (EINVAL);
1258 }
1259
1260 cmd = SMBIOC_TREE_CONNECT;
1261 tcon = malloc(sizeof (*tcon));
1262 if (tcon == NULL)
1263 return (ENOMEM);
1264 bzero(tcon, sizeof (*tcon));
1265 tcon->tc_flags = SMBLK_CREATE;
1266 tcon->tc_opt = 0;
1267
1268 /* The share name */
1269 strlcpy(tcon->tc_sh.sh_name, ctx->ct_origshare,
1270 sizeof (tcon->tc_sh.sh_name));
1271
1272 /* The share "use" type. */
1273 tcon->tc_sh.sh_use = ctx->ct_shtype_req;
1274
1275 /*
1276 * Todo: share passwords for share-level security.
1277 *
1278 * The driver does the actual TCON call.
1279 */
1280 if (ioctl(ctx->ct_dev_fd, cmd, tcon) == -1) {
1281 err = errno;
1282 goto out;
1283 }
1284
1285 /*
1286 * Check the returned share type
1287 */
1288 DPRINT("ret. sh_type: \"%d\"", tcon->tc_sh.sh_type);
1289 if (ctx->ct_shtype_req != USE_WILDCARD &&
1290 ctx->ct_shtype_req != tcon->tc_sh.sh_type) {
1291 smb_error(dgettext(TEXT_DOMAIN,
1292 "%s: incompatible share type"),
1293 0, ctx->ct_origshare);
1294 }
1295
1296 out:
1297 if (tcon != NULL)
1298 free(tcon);
1299
1300 return (err);
1301 }
1302
1303 /*
1304 * Return the hflags2 word for an smb_ctx.
1305 */
1306 int
smb_ctx_flags2(struct smb_ctx * ctx)1307 smb_ctx_flags2(struct smb_ctx *ctx)
1308 {
1309 uint16_t flags2;
1310
1311 if (ioctl(ctx->ct_dev_fd, SMBIOC_FLAGS2, &flags2) == -1) {
1312 smb_error(dgettext(TEXT_DOMAIN,
1313 "can't get flags2 for a session"), errno);
1314 return (-1);
1315 }
1316 return (flags2);
1317 }
1318
1319 /*
1320 * Get the transport level session key.
1321 * Must already have an active SMB session.
1322 */
1323 int
smb_fh_getssnkey(int dev_fd,uchar_t * key,size_t len)1324 smb_fh_getssnkey(int dev_fd, uchar_t *key, size_t len)
1325 {
1326 if (len < SMBIOC_HASH_SZ)
1327 return (EINVAL);
1328
1329 if (ioctl(dev_fd, SMBIOC_GETSSNKEY, key) == -1)
1330 return (errno);
1331
1332 return (0);
1333 }
1334
1335 /*
1336 * RC file parsing stuff
1337 */
1338
1339 static struct nv
1340 minauth_table[] = {
1341 /* Allowed auth. types */
1342 { "kerberos", SMB_AT_KRB5 },
1343 { "ntlmv2", SMB_AT_KRB5|SMB_AT_NTLM2 },
1344 { "ntlm", SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1 },
1345 { "lm", SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1|SMB_AT_LM1 },
1346 { "none", SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1|SMB_AT_LM1|
1347 SMB_AT_ANON },
1348 { NULL }
1349 };
1350
1351
1352 /*
1353 * level values:
1354 * 0 - default
1355 * 1 - server
1356 * 2 - server:user
1357 * 3 - server:user:share
1358 */
1359 static int
smb_ctx_readrcsection(struct smb_ctx * ctx,const char * sname,int level)1360 smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
1361 {
1362 char *p;
1363 int error;
1364
1365 #ifdef KICONV_SUPPORT
1366 if (level > 0) {
1367 rc_getstringptr(smb_rc, sname, "charsets", &p);
1368 if (p) {
1369 error = smb_ctx_setcharset(ctx, p);
1370 if (error)
1371 smb_error(dgettext(TEXT_DOMAIN,
1372 "charset specification in the section '%s' ignored"),
1373 error, sname);
1374 }
1375 }
1376 #endif
1377
1378 if (level <= 1) {
1379 /* Section is: [default] or [server] */
1380
1381 rc_getstringptr(smb_rc, sname, "minauth", &p);
1382 if (p) {
1383 /*
1384 * "minauth" was set in this section; override
1385 * the current minimum authentication setting.
1386 */
1387 struct nv *nvp;
1388 for (nvp = minauth_table; nvp->name; nvp++)
1389 if (strcmp(p, nvp->name) == 0)
1390 break;
1391 if (nvp->name)
1392 ctx->ct_minauth = nvp->value;
1393 else {
1394 /*
1395 * Unknown minimum authentication level.
1396 */
1397 smb_error(dgettext(TEXT_DOMAIN,
1398 "invalid minimum authentication level \"%s\" specified in the section %s"),
1399 0, p, sname);
1400 return (EINVAL);
1401 }
1402 }
1403
1404 rc_getstringptr(smb_rc, sname, "signing", &p);
1405 if (p) {
1406 /*
1407 * "signing" was set in this section; override
1408 * the current signing settings. Note:
1409 * setsigning flags are: enable, require
1410 */
1411 if (strcmp(p, "disabled") == 0) {
1412 (void) smb_ctx_setsigning(ctx, FALSE, FALSE);
1413 } else if (strcmp(p, "enabled") == 0) {
1414 (void) smb_ctx_setsigning(ctx, TRUE, FALSE);
1415 } else if (strcmp(p, "required") == 0) {
1416 (void) smb_ctx_setsigning(ctx, TRUE, TRUE);
1417 } else {
1418 /*
1419 * Unknown "signing" value.
1420 */
1421 smb_error(dgettext(TEXT_DOMAIN,
1422 "invalid signing policy \"%s\" specified in the section %s"),
1423 0, p, sname);
1424 return (EINVAL);
1425 }
1426 }
1427
1428 /*
1429 * Domain name. Allow both keywords:
1430 * "workgroup", "domain"
1431 *
1432 * Note: these are NOT marked "from CMD".
1433 * See long comment at smb_ctx_init()
1434 */
1435 rc_getstringptr(smb_rc, sname, "workgroup", &p);
1436 if (p) {
1437 error = smb_ctx_setdomain(ctx, p, 0);
1438 if (error)
1439 smb_error(dgettext(TEXT_DOMAIN,
1440 "workgroup specification in the "
1441 "section '%s' ignored"), error, sname);
1442 }
1443 rc_getstringptr(smb_rc, sname, "domain", &p);
1444 if (p) {
1445 error = smb_ctx_setdomain(ctx, p, 0);
1446 if (error)
1447 smb_error(dgettext(TEXT_DOMAIN,
1448 "domain specification in the "
1449 "section '%s' ignored"), error, sname);
1450 }
1451
1452 rc_getstringptr(smb_rc, sname, "user", &p);
1453 if (p) {
1454 error = smb_ctx_setuser(ctx, p, 0);
1455 if (error)
1456 smb_error(dgettext(TEXT_DOMAIN,
1457 "user specification in the "
1458 "section '%s' ignored"), error, sname);
1459 }
1460 }
1461
1462 if (level == 1) {
1463 /* Section is: [server] */
1464 rc_getstringptr(smb_rc, sname, "addr", &p);
1465 if (p) {
1466 error = smb_ctx_setsrvaddr(ctx, p);
1467 if (error) {
1468 smb_error(dgettext(TEXT_DOMAIN,
1469 "invalid address specified in section %s"),
1470 0, sname);
1471 return (error);
1472 }
1473 }
1474 }
1475
1476 rc_getstringptr(smb_rc, sname, "password", &p);
1477 if (p) {
1478 error = smb_ctx_setpassword(ctx, p, 0);
1479 if (error)
1480 smb_error(dgettext(TEXT_DOMAIN,
1481 "password specification in the section '%s' ignored"),
1482 error, sname);
1483 }
1484
1485 return (0);
1486 }
1487
1488 /*
1489 * read rc file as follows:
1490 * 0: read [default] section
1491 * 1: override with [server] section
1492 * 2: override with [server:user] section
1493 * 3: override with [server:user:share] section
1494 * Since absence of rcfile is not fatal, silently ignore this fact.
1495 * smb_rc file should be closed by caller.
1496 */
1497 int
smb_ctx_readrc(struct smb_ctx * ctx)1498 smb_ctx_readrc(struct smb_ctx *ctx)
1499 {
1500 char pwbuf[NSS_BUFLEN_PASSWD];
1501 struct passwd pw;
1502 char *sname = NULL;
1503 int sname_max;
1504 int err = 0;
1505
1506 /*
1507 * If the user name is not specified some other way,
1508 * use the current user name. Also save the homedir.
1509 * NB: ct_home=NULL is allowed, and we don't want to
1510 * bail out with an error for a missing ct_home.
1511 */
1512 if (getpwuid_r(getuid(), &pw, pwbuf, sizeof (pwbuf)) != NULL) {
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);
1517 }
1518
1519 if ((err = smb_open_rcfile(ctx->ct_home)) != 0) {
1520 DPRINT("smb_open_rcfile, err=%d", err);
1521 /* ignore any error here */
1522 return (0);
1523 }
1524
1525 sname_max = 3 * SMBIOC_MAX_NAME + 4;
1526 sname = malloc(sname_max);
1527 if (sname == NULL) {
1528 err = ENOMEM;
1529 goto done;
1530 }
1531
1532 /*
1533 * default parameters (level=0)
1534 */
1535 smb_ctx_readrcsection(ctx, "default", 0);
1536 nb_ctx_readrcsection(smb_rc, ctx->ct_nb, "default", 0);
1537
1538 /*
1539 * If we don't have a server name, we can't read any of the
1540 * [server...] sections.
1541 */
1542 if (ctx->ct_fullserver == NULL)
1543 goto done;
1544 /*
1545 * SERVER parameters.
1546 */
1547 smb_ctx_readrcsection(ctx, ctx->ct_fullserver, 1);
1548
1549 /*
1550 * If we don't have a user name, we can't read any of the
1551 * [server:user...] sections.
1552 */
1553 if (ctx->ct_user[0] == 0)
1554 goto done;
1555 /*
1556 * SERVER:USER parameters
1557 */
1558 snprintf(sname, sname_max, "%s:%s",
1559 ctx->ct_fullserver,
1560 ctx->ct_user);
1561 smb_ctx_readrcsection(ctx, sname, 2);
1562
1563
1564 /*
1565 * If we don't have a share name, we can't read any of the
1566 * [server:user:share] sections.
1567 */
1568 if (ctx->ct_origshare == NULL)
1569 goto done;
1570 /*
1571 * SERVER:USER:SHARE parameters
1572 */
1573 snprintf(sname, sname_max, "%s:%s:%s",
1574 ctx->ct_fullserver,
1575 ctx->ct_user,
1576 ctx->ct_origshare);
1577 smb_ctx_readrcsection(ctx, sname, 3);
1578
1579 done:
1580 if (sname)
1581 free(sname);
1582 smb_close_rcfile();
1583 if (smb_debug)
1584 dump_ctx("after smb_ctx_readrc", ctx);
1585 if (err)
1586 DPRINT("err=%d\n", err);
1587
1588 return (err);
1589 }
1590
1591 void
smbfs_set_default_domain(const char * domain)1592 smbfs_set_default_domain(const char *domain)
1593 {
1594 strlcpy(default_domain, domain, sizeof (default_domain));
1595 }
1596
1597 void
smbfs_set_default_user(const char * user)1598 smbfs_set_default_user(const char *user)
1599 {
1600 strlcpy(default_user, user, sizeof (default_user));
1601 }
1602