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 2018 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 110 rpc_cleanup_smbctx(struct smb_ctx *ctx) 111 { 112 if (close_hook) 113 (*close_hook)(ctx); 114 } 115 void 116 smb_ctx_set_close_hook(smb_ctx_close_hook_t hook) 117 { 118 close_hook = hook; 119 } 120 121 void 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_KCDOMAIN) 152 printf("KCDOMAIN "); 153 printf("\n"); 154 } 155 156 void 157 dump_iod_ssn(smb_iod_ssn_t *is) 158 { 159 static const char zeros[NTLM_HASH_SZ] = {0}; 160 struct smbioc_ossn *ssn = &is->iod_ossn; 161 162 printf(" ct_srvname=\"%s\", ", ssn->ssn_srvname); 163 dump_sockaddr(&ssn->ssn_srvaddr.sa); 164 printf(" dom=\"%s\", user=\"%s\"\n", 165 ssn->ssn_domain, ssn->ssn_user); 166 printf(" ct_vopt=0x%x, ct_owner=%d\n", 167 ssn->ssn_vopt, ssn->ssn_owner); 168 printf(" ct_minver=0x%x, ct_maxver=0x%x\n", 169 ssn->ssn_minver, ssn->ssn_maxver); 170 printf(" ct_authflags=0x%x\n", is->iod_authflags); 171 172 printf(" ct_nthash:"); 173 if (bcmp(zeros, &is->iod_nthash, NTLM_HASH_SZ)) 174 smb_hexdump(&is->iod_nthash, NTLM_HASH_SZ); 175 else 176 printf(" {0}\n"); 177 178 printf(" ct_lmhash:"); 179 if (bcmp(zeros, &is->iod_lmhash, NTLM_HASH_SZ)) 180 smb_hexdump(&is->iod_lmhash, NTLM_HASH_SZ); 181 else 182 printf(" {0}\n"); 183 } 184 185 void 186 dump_ctx(char *where, struct smb_ctx *ctx) 187 { 188 printf("context %s:\n", where); 189 dump_ctx_flags(ctx->ct_flags); 190 191 if (ctx->ct_locname) 192 printf(" localname=\"%s\"", ctx->ct_locname); 193 else 194 printf(" localname=NULL"); 195 196 if (ctx->ct_fullserver) 197 printf(" fullserver=\"%s\"", ctx->ct_fullserver); 198 else 199 printf(" fullserver=NULL"); 200 201 if (ctx->ct_srvaddr_s) 202 printf(" srvaddr_s=\"%s\"\n", ctx->ct_srvaddr_s); 203 else 204 printf(" srvaddr_s=NULL\n"); 205 206 if (ctx->ct_addrinfo) 207 dump_addrinfo(ctx->ct_addrinfo); 208 else 209 printf(" ct_addrinfo = NULL\n"); 210 211 dump_iod_ssn(&ctx->ct_iod_ssn); 212 213 printf(" share_name=\"%s\", share_type=%d\n", 214 ctx->ct_origshare ? ctx->ct_origshare : "", 215 ctx->ct_shtype_req); 216 217 printf(" ct_home=\"%s\"\n", ctx->ct_home); 218 printf(" ct_rpath=\"%s\"\n", ctx->ct_rpath); 219 } 220 221 int 222 smb_ctx_alloc(struct smb_ctx **ctx_pp) 223 { 224 smb_ctx_t *ctx; 225 int err; 226 227 ctx = malloc(sizeof (*ctx)); 228 if (ctx == NULL) 229 return (ENOMEM); 230 err = smb_ctx_init(ctx); 231 if (err != 0) { 232 free(ctx); 233 return (err); 234 } 235 *ctx_pp = ctx; 236 return (0); 237 } 238 239 /* 240 * Initialize an smb_ctx struct (defaults) 241 */ 242 int 243 smb_ctx_init(struct smb_ctx *ctx) 244 { 245 int error; 246 247 bzero(ctx, sizeof (*ctx)); 248 249 error = nb_ctx_create(&ctx->ct_nb); 250 if (error) 251 return (error); 252 253 ctx->ct_dev_fd = -1; 254 ctx->ct_door_fd = -1; 255 ctx->ct_parsedlevel = SMBL_NONE; 256 ctx->ct_minlevel = SMBL_NONE; 257 ctx->ct_maxlevel = SMBL_PATH; 258 259 /* Fill in defaults */ 260 ctx->ct_vopt = SMBVOPT_SIGNING_ENABLED; 261 ctx->ct_owner = SMBM_ANY_OWNER; 262 ctx->ct_authflags = SMB_AT_DEFAULT; 263 ctx->ct_minauth = SMB_AT_MINAUTH; 264 ctx->ct_maxver = SMB2_DIALECT_MAX; 265 266 /* 267 * Default domain, user, ... 268 */ 269 strlcpy(ctx->ct_domain, default_domain, 270 sizeof (ctx->ct_domain)); 271 strlcpy(ctx->ct_user, default_user, 272 sizeof (ctx->ct_user)); 273 274 return (0); 275 } 276 277 /* 278 * "Scan" the command line args to find the server name, 279 * user name, and share name, as needed. We need these 280 * before reading the RC files and/or sharectl values. 281 * 282 * The sequence for getting all the members filled in 283 * has some tricky aspects. Here's how it works: 284 * 285 * The search order for options is as follows: 286 * command line options 287 * values parsed from UNC path (cmd) 288 * values from RC file (per-user) 289 * values from SMF (system-wide) 290 * built-in defaults 291 * 292 * Normally, one would simply get all the values starting with 293 * the bottom of the above list and working to the top, and 294 * overwriting values as you go. But we need an exception. 295 * 296 * In this function, we parse the UNC path and command line options, 297 * because we need (at least) the server name when we're getting the 298 * SMF and RC file values. However, values we get from the command 299 * should not be overwritten by SMF or RC file parsing, so we mark 300 * values from the command as "from CMD" and the RC file parser 301 * leaves in place any values so marked. See: SMBCF_CMD_* 302 * 303 * The semantics of these flags are: "This value came from the 304 * current command instance, not from sources that may apply to 305 * multiple commands." (Different from the old "FROMUSR" flag.) 306 * 307 * Note that smb_ctx_opt() is called later to handle the 308 * remaining options, which should be ignored here. 309 * The (magic) leading ":" in cf_getopt() makes it 310 * ignore options not in the options string. 311 */ 312 int 313 smb_ctx_scan_argv(struct smb_ctx *ctx, int argc, char **argv, 314 int minlevel, int maxlevel, int sharetype) 315 { 316 int ind, opt, error = 0; 317 int aflg = 0, uflg = 0; 318 const char *arg; 319 320 /* 321 * Parse options, if any. Values from here too 322 * are marked as "from CMD". 323 */ 324 if (argv == NULL) 325 return (0); 326 327 ctx->ct_minlevel = minlevel; 328 ctx->ct_maxlevel = maxlevel; 329 ctx->ct_shtype_req = sharetype; 330 331 cf_opt_lock(); 332 /* Careful: no return/goto before cf_opt_unlock! */ 333 while (error == 0) { 334 /* 335 * Leading ':' tells this to skip unknown opts. 336 * Just get -A and -U here so we know the user 337 * for config file parsing. 338 */ 339 opt = cf_getopt(argc, argv, ":AU:"); 340 if (opt == -1) 341 break; 342 arg = cf_optarg; 343 /* NB: handle most in smb_ctx_opt */ 344 switch (opt) { 345 case 'A': 346 aflg = 1; 347 error = smb_ctx_setuser(ctx, "", TRUE); 348 ctx->ct_flags |= SMBCF_NOPWD; 349 break; 350 case 'U': 351 uflg = 1; 352 error = smb_ctx_setuser(ctx, arg, TRUE); 353 break; 354 default: 355 DPRINT("skip opt=%c", opt); 356 break; 357 } 358 } 359 ind = cf_optind; 360 arg = argv[ind]; 361 cf_optind = cf_optreset = 1; 362 cf_opt_unlock(); 363 364 if (error) 365 return (error); 366 367 if (aflg && uflg) { 368 printf(gettext("-A and -U flags are exclusive.\n")); 369 return (EINVAL); 370 } 371 372 /* 373 * Parse the UNC path. Values from here are 374 * marked as "from CMD". 375 */ 376 for (; ind < argc; ind++) { 377 arg = argv[ind]; 378 if (strncmp(arg, "//", 2) != 0) 379 continue; 380 error = smb_ctx_parseunc(ctx, arg, 381 minlevel, maxlevel, sharetype, &arg); 382 if (error) 383 return (error); 384 break; 385 } 386 387 return (error); 388 } 389 390 void 391 smb_ctx_free(smb_ctx_t *ctx) 392 { 393 smb_ctx_done(ctx); 394 free(ctx); 395 } 396 397 void 398 smb_ctx_done(struct smb_ctx *ctx) 399 { 400 401 rpc_cleanup_smbctx(ctx); 402 403 if (ctx->ct_dev_fd != -1) { 404 nsmb_close(ctx->ct_dev_fd); 405 ctx->ct_dev_fd = -1; 406 } 407 if (ctx->ct_door_fd != -1) { 408 close(ctx->ct_door_fd); 409 ctx->ct_door_fd = -1; 410 } 411 if (ctx->ct_srvaddr_s) { 412 free(ctx->ct_srvaddr_s); 413 ctx->ct_srvaddr_s = NULL; 414 } 415 if (ctx->ct_nb) { 416 nb_ctx_done(ctx->ct_nb); 417 ctx->ct_nb = NULL; 418 } 419 if (ctx->ct_locname) { 420 free(ctx->ct_locname); 421 ctx->ct_locname = NULL; 422 } 423 if (ctx->ct_origshare) { 424 free(ctx->ct_origshare); 425 ctx->ct_origshare = NULL; 426 } 427 if (ctx->ct_fullserver) { 428 free(ctx->ct_fullserver); 429 ctx->ct_fullserver = NULL; 430 } 431 if (ctx->ct_addrinfo) { 432 freeaddrinfo(ctx->ct_addrinfo); 433 ctx->ct_addrinfo = NULL; 434 } 435 if (ctx->ct_home) { 436 free(ctx->ct_home); 437 ctx->ct_home = NULL; 438 } 439 if (ctx->ct_rpath) { 440 free(ctx->ct_rpath); 441 ctx->ct_rpath = NULL; 442 } 443 if (ctx->ct_ssnkey_buf) { 444 free(ctx->ct_ssnkey_buf); 445 ctx->ct_ssnkey_buf = NULL; 446 } 447 } 448 449 /* 450 * Parse the UNC path. Here we expect something like 451 * "//[[domain;]user[:password]@]host[/share[/path]]" 452 * See http://ietf.org/internet-drafts/draft-crhertel-smb-url-07.txt 453 * Values found here are marked as "from CMD". 454 */ 455 int 456 smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc, 457 int minlevel, int maxlevel, int sharetype, 458 const char **next) 459 { 460 char tmp[1024]; 461 char *host, *share, *path; 462 char *dom, *usr, *pw, *p; 463 int error; 464 465 /* 466 * This may be called outside of _scan_argv, 467 * so make sure these get initialized. 468 */ 469 ctx->ct_minlevel = minlevel; 470 ctx->ct_maxlevel = maxlevel; 471 ctx->ct_shtype_req = sharetype; 472 ctx->ct_parsedlevel = SMBL_NONE; 473 474 dom = usr = pw = host = NULL; 475 476 /* Work on a temporary copy, fix back slashes. */ 477 strlcpy(tmp, unc, sizeof (tmp)); 478 for (p = tmp; *p; p++) 479 if (*p == '\\') 480 *p = '/'; 481 482 if (tmp[0] != '/' || tmp[1] != '/') { 483 smb_error(dgettext(TEXT_DOMAIN, 484 "UNC should start with '//'"), 0); 485 error = EINVAL; 486 goto out; 487 } 488 p = tmp + 2; /* user@host... */ 489 490 /* Find the share part, if any. */ 491 share = strchr(p, '/'); 492 if (share) 493 *share = '\0'; 494 (void) unpercent(p); /* host component */ 495 496 /* 497 * Parse the "host" stuff right to left: 498 * 1: trailing "@hostname" (or whole field) 499 * 2: trailing ":password" 500 * 3: trailing "domain;user" (or just user) 501 */ 502 host = strrchr(p, '@'); 503 if (host == NULL) { 504 host = p; /* no user@ prefix */ 505 } else { 506 *host++ = '\0'; 507 508 /* may have [[domain;]user[:passwd]] */ 509 pw = strchr(p, ':'); 510 if (pw) 511 *pw++ = '\0'; 512 usr = strchr(p, ';'); 513 if (usr) { 514 *usr++ = '\0'; 515 dom = p; 516 } else 517 usr = p; 518 } 519 520 if (*host == '\0') { 521 smb_error(dgettext(TEXT_DOMAIN, "empty server name"), 0); 522 error = EINVAL; 523 goto out; 524 } 525 error = smb_ctx_setfullserver(ctx, host); 526 if (error) 527 goto out; 528 ctx->ct_parsedlevel = SMBL_VC; 529 530 if (dom != NULL) { 531 error = smb_ctx_setdomain(ctx, dom, TRUE); 532 if (error) 533 goto out; 534 } 535 if (usr != NULL) { 536 if (*usr == '\0') { 537 smb_error(dgettext(TEXT_DOMAIN, 538 "empty user name"), 0); 539 error = EINVAL; 540 goto out; 541 } 542 if (ctx->ct_maxlevel < SMBL_VC) { 543 smb_error(dgettext(TEXT_DOMAIN, 544 "no user name required"), 0); 545 error = EINVAL; 546 goto out; 547 } 548 error = smb_ctx_setuser(ctx, usr, TRUE); 549 if (error) 550 goto out; 551 } 552 if (pw != NULL) { 553 error = smb_ctx_setpassword(ctx, pw, TRUE); 554 if (error) 555 goto out; 556 } 557 558 if (share != NULL) { 559 /* restore the slash */ 560 *share = '/'; 561 p = share + 1; 562 563 /* Find the path part, if any. */ 564 path = strchr(p, '/'); 565 if (path) 566 *path = '\0'; 567 (void) unpercent(p); /* share component */ 568 569 if (*p == '\0') { 570 smb_error(dgettext(TEXT_DOMAIN, 571 "empty share name"), 0); 572 error = EINVAL; 573 goto out; 574 } 575 if (ctx->ct_maxlevel < SMBL_SHARE) { 576 smb_error(dgettext(TEXT_DOMAIN, 577 "no share name required"), 0); 578 error = EINVAL; 579 goto out; 580 } 581 582 /* 583 * Special case UNC names like: 584 * //host/PIPE/endpoint 585 * to have share: IPC$ 586 */ 587 if (strcasecmp(p, "PIPE") == 0) { 588 sharetype = USE_IPC; 589 p = "IPC$"; 590 } 591 error = smb_ctx_setshare(ctx, p, sharetype); 592 if (error) 593 goto out; 594 ctx->ct_parsedlevel = SMBL_SHARE; 595 596 if (path) { 597 /* restore the slash */ 598 *path = '/'; 599 p = path + 1; 600 (void) unpercent(p); /* remainder */ 601 free(ctx->ct_rpath); 602 ctx->ct_rpath = strdup(path); 603 } 604 } else if (ctx->ct_minlevel >= SMBL_SHARE) { 605 smb_error(dgettext(TEXT_DOMAIN, "empty share name"), 0); 606 error = EINVAL; 607 goto out; 608 } 609 610 if (next) 611 *next = NULL; 612 613 out: 614 if (error == 0 && smb_debug > 0) 615 dump_ctx("after smb_ctx_parseunc", ctx); 616 617 return (error); 618 } 619 620 #ifdef KICONV_SUPPORT 621 int 622 smb_ctx_setcharset(struct smb_ctx *ctx, const char *arg) 623 { 624 char *cp, *servercs, *localcs; 625 int cslen = sizeof (ctx->ct_ssn.ioc_localcs); 626 int scslen, lcslen, error; 627 628 cp = strchr(arg, ':'); 629 lcslen = cp ? (cp - arg) : 0; 630 if (lcslen == 0 || lcslen >= cslen) { 631 smb_error(dgettext(TEXT_DOMAIN, 632 "invalid local charset specification (%s)"), 0, arg); 633 return (EINVAL); 634 } 635 scslen = (size_t)strlen(++cp); 636 if (scslen == 0 || scslen >= cslen) { 637 smb_error(dgettext(TEXT_DOMAIN, 638 "invalid server charset specification (%s)"), 0, arg); 639 return (EINVAL); 640 } 641 localcs = memcpy(ctx->ct_ssn.ioc_localcs, arg, lcslen); 642 localcs[lcslen] = 0; 643 servercs = strcpy(ctx->ct_ssn.ioc_servercs, cp); 644 error = nls_setrecode(localcs, servercs); 645 if (error == 0) 646 return (0); 647 smb_error(dgettext(TEXT_DOMAIN, 648 "can't initialize iconv support (%s:%s)"), 649 error, localcs, servercs); 650 localcs[0] = 0; 651 servercs[0] = 0; 652 return (error); 653 } 654 #endif /* KICONV_SUPPORT */ 655 656 int 657 smb_ctx_setauthflags(struct smb_ctx *ctx, int flags) 658 { 659 ctx->ct_authflags = flags; 660 return (0); 661 } 662 663 int 664 smb_ctx_setfullserver(struct smb_ctx *ctx, const char *name) 665 { 666 char *p = strdup(name); 667 668 if (p == NULL) 669 return (ENOMEM); 670 if (ctx->ct_fullserver) 671 free(ctx->ct_fullserver); 672 ctx->ct_fullserver = p; 673 return (0); 674 } 675 676 int 677 smb_ctx_setserver(struct smb_ctx *ctx, const char *name) 678 { 679 strlcpy(ctx->ct_srvname, name, 680 sizeof (ctx->ct_srvname)); 681 return (0); 682 } 683 684 int 685 smb_ctx_setuser(struct smb_ctx *ctx, const char *name, int from_cmd) 686 { 687 688 if (strlen(name) >= sizeof (ctx->ct_user)) { 689 smb_error(dgettext(TEXT_DOMAIN, 690 "user name '%s' too long"), 0, name); 691 return (ENAMETOOLONG); 692 } 693 694 /* 695 * Don't overwrite a value from the command line 696 * with one from anywhere else. 697 */ 698 if (!from_cmd && (ctx->ct_flags & SMBCF_CMD_USR)) 699 return (0); 700 701 strlcpy(ctx->ct_user, name, 702 sizeof (ctx->ct_user)); 703 704 /* Mark this as "from the command line". */ 705 if (from_cmd) 706 ctx->ct_flags |= SMBCF_CMD_USR; 707 708 return (0); 709 } 710 711 /* 712 * Don't overwrite a domain name from the 713 * command line with one from anywhere else. 714 * See smb_ctx_init() for notes about this. 715 */ 716 int 717 smb_ctx_setdomain(struct smb_ctx *ctx, const char *name, int from_cmd) 718 { 719 720 if (strlen(name) >= sizeof (ctx->ct_domain)) { 721 smb_error(dgettext(TEXT_DOMAIN, 722 "workgroup name '%s' too long"), 0, name); 723 return (ENAMETOOLONG); 724 } 725 726 /* 727 * Don't overwrite a value from the command line 728 * with one from anywhere else. 729 */ 730 if (!from_cmd && (ctx->ct_flags & SMBCF_CMD_DOM)) 731 return (0); 732 733 strlcpy(ctx->ct_domain, name, 734 sizeof (ctx->ct_domain)); 735 736 /* Mark this as "from the command line". */ 737 if (from_cmd) 738 ctx->ct_flags |= SMBCF_CMD_DOM; 739 740 return (0); 741 } 742 743 int 744 smb_ctx_setpassword(struct smb_ctx *ctx, const char *passwd, int from_cmd) 745 { 746 int err; 747 748 if (passwd == NULL) 749 return (EINVAL); 750 if (strlen(passwd) >= sizeof (ctx->ct_password)) { 751 smb_error(dgettext(TEXT_DOMAIN, "password too long"), 0); 752 return (ENAMETOOLONG); 753 } 754 755 /* 756 * If called again after comand line parsing, 757 * don't overwrite a value from the command line 758 * with one from any stored config. 759 */ 760 if (!from_cmd && (ctx->ct_flags & SMBCF_CMD_PW)) 761 return (0); 762 763 memset(ctx->ct_password, 0, sizeof (ctx->ct_password)); 764 if (strncmp(passwd, "$$1", 3) == 0) 765 (void) smb_simpledecrypt(ctx->ct_password, passwd); 766 else 767 strlcpy(ctx->ct_password, passwd, 768 sizeof (ctx->ct_password)); 769 770 /* 771 * Compute LM hash, NT hash. 772 */ 773 if (ctx->ct_password[0]) { 774 err = ntlm_compute_nt_hash(ctx->ct_nthash, ctx->ct_password); 775 if (err != 0) 776 return (err); 777 err = ntlm_compute_lm_hash(ctx->ct_lmhash, ctx->ct_password); 778 if (err != 0) 779 return (err); 780 } 781 782 /* Mark this as "from the command line". */ 783 if (from_cmd) 784 ctx->ct_flags |= SMBCF_CMD_PW; 785 786 return (0); 787 } 788 789 /* 790 * Use this to set NTLM auth. info (hashes) 791 * when we don't have the password. 792 */ 793 int 794 smb_ctx_setpwhash(smb_ctx_t *ctx, 795 const uchar_t *nthash, const uchar_t *lmhash) 796 { 797 798 /* Need ct_password to be non-null. */ 799 if (ctx->ct_password[0] == '\0') 800 strlcpy(ctx->ct_password, "$HASH", 801 sizeof (ctx->ct_password)); 802 803 /* 804 * Compute LM hash, NT hash. 805 */ 806 memcpy(ctx->ct_nthash, nthash, NTLM_HASH_SZ); 807 808 /* The LM hash is optional */ 809 if (lmhash) { 810 memcpy(ctx->ct_nthash, nthash, NTLM_HASH_SZ); 811 } 812 813 return (0); 814 } 815 816 int 817 smb_ctx_setshare(struct smb_ctx *ctx, const char *share, int stype) 818 { 819 if (strlen(share) >= SMBIOC_MAX_NAME) { 820 smb_error(dgettext(TEXT_DOMAIN, 821 "share name '%s' too long"), 0, share); 822 return (ENAMETOOLONG); 823 } 824 if (ctx->ct_origshare) 825 free(ctx->ct_origshare); 826 if ((ctx->ct_origshare = strdup(share)) == NULL) 827 return (ENOMEM); 828 829 ctx->ct_shtype_req = stype; 830 831 return (0); 832 } 833 834 int 835 smb_ctx_setsrvaddr(struct smb_ctx *ctx, const char *addr) 836 { 837 if (addr == NULL || addr[0] == 0) 838 return (EINVAL); 839 if (ctx->ct_srvaddr_s) 840 free(ctx->ct_srvaddr_s); 841 if ((ctx->ct_srvaddr_s = strdup(addr)) == NULL) 842 return (ENOMEM); 843 return (0); 844 } 845 846 /* 847 * API for library caller to set signing enabled, required 848 * Note: if not enable, ignore require 849 */ 850 int 851 smb_ctx_setsigning(struct smb_ctx *ctx, int enable, int require) 852 { 853 ctx->ct_vopt &= ~SMBVOPT_SIGNING_MASK; 854 if (enable) { 855 ctx->ct_vopt |= SMBVOPT_SIGNING_ENABLED; 856 if (require) 857 ctx->ct_vopt |= SMBVOPT_SIGNING_REQUIRED; 858 } 859 return (0); 860 } 861 862 /* 863 * Handle .nsmbrc "minver" option. 864 * Must be <= maxver 865 */ 866 int 867 smb_ctx_setminver(struct smb_ctx *ctx, int ver) 868 { 869 if (ver < 0 || ver > ctx->ct_maxver) 870 return (EINVAL); 871 ctx->ct_minver = (uint16_t)ver; 872 return (0); 873 } 874 875 /* 876 * Handle .nsmbrc "maxver" option. 877 * Must be >= minver 878 * 879 * Any "too high" value is just clamped, so the caller 880 * doesn't need to know what's the highest we support. 881 */ 882 int 883 smb_ctx_setmaxver(struct smb_ctx *ctx, int ver) 884 { 885 if (ver < 1 || ver < ctx->ct_minver) 886 return (EINVAL); 887 if (ver > SMB2_DIALECT_MAX) 888 ver = SMB2_DIALECT_MAX; 889 ctx->ct_maxver = (uint16_t)ver; 890 return (0); 891 } 892 893 static int 894 smb_parse_owner(char *pair, uid_t *uid, gid_t *gid) 895 { 896 struct group gr; 897 struct passwd pw; 898 char buf[NSS_BUFLEN_PASSWD]; 899 char *cp; 900 901 cp = strchr(pair, ':'); 902 if (cp) { 903 *cp++ = '\0'; 904 if (*cp && gid) { 905 if (getgrnam_r(cp, &gr, buf, sizeof (buf)) != NULL) { 906 *gid = gr.gr_gid; 907 } else 908 smb_error(dgettext(TEXT_DOMAIN, 909 "Invalid group name %s, ignored"), 0, cp); 910 } 911 } 912 if (*pair) { 913 if (getpwnam_r(pair, &pw, buf, sizeof (buf)) != NULL) { 914 *uid = pw.pw_uid; 915 } else 916 smb_error(dgettext(TEXT_DOMAIN, 917 "Invalid user name %s, ignored"), 0, pair); 918 } 919 920 return (0); 921 } 922 923 /* 924 * Suport a securty options arg, i.e. -S lm,ntlm 925 * for testing various type of authenticators. 926 */ 927 static struct nv 928 sectype_table[] = { 929 { "anon", SMB_AT_ANON }, 930 { "lm", SMB_AT_LM1 }, 931 { "ntlm", SMB_AT_NTLM1 }, 932 { "ntlm2", SMB_AT_NTLM2 }, 933 { "krb5", SMB_AT_KRB5 }, 934 { NULL, 0 }, 935 }; 936 int 937 smb_parse_secopts(struct smb_ctx *ctx, const char *arg) 938 { 939 const char *sep = ":;,"; 940 const char *p = arg; 941 struct nv *nv; 942 int nlen, tlen; 943 int authflags = 0; 944 945 for (;;) { 946 /* skip separators */ 947 tlen = strspn(p, sep); 948 p += tlen; 949 950 nlen = strcspn(p, sep); 951 if (nlen == 0) 952 break; 953 954 /* This is rarely called, so not optimized. */ 955 for (nv = sectype_table; nv->name; nv++) { 956 tlen = strlen(nv->name); 957 if (tlen == nlen && 0 == strncmp(p, nv->name, tlen)) 958 break; 959 } 960 if (nv->name == NULL) { 961 smb_error(dgettext(TEXT_DOMAIN, 962 "%s: invalid security options"), 0, p); 963 return (EINVAL); 964 } 965 authflags |= nv->value; 966 p += nlen; 967 } 968 969 if (authflags) 970 ctx->ct_authflags = authflags; 971 972 return (0); 973 } 974 975 /* 976 * Commands use this with getopt. See: 977 * STDPARAM_OPT, STDPARAM_ARGS 978 * Called after smb_ctx_readrc(). 979 */ 980 int 981 smb_ctx_opt(struct smb_ctx *ctx, int opt, const char *arg) 982 { 983 int error = 0; 984 char *p, *cp; 985 char tmp[1024]; 986 987 switch (opt) { 988 case 'A': 989 case 'U': 990 /* Handled in smb_ctx_init() */ 991 break; 992 case 'I': 993 error = smb_ctx_setsrvaddr(ctx, arg); 994 break; 995 case 'M': 996 /* share connect rights - ignored */ 997 ctx->ct_flags |= SMBCF_SRIGHTS; 998 break; 999 case 'N': 1000 ctx->ct_flags |= SMBCF_NOPWD; 1001 break; 1002 case 'O': 1003 p = strdup(arg); 1004 cp = strchr(p, '/'); 1005 if (cp) 1006 *cp = '\0'; 1007 error = smb_parse_owner(cp, &ctx->ct_owner, NULL); 1008 free(p); 1009 break; 1010 case 'P': 1011 /* ctx->ct_vopt |= SMBCOPT_PERMANENT; */ 1012 break; 1013 case 'R': 1014 /* retry count - ignored */ 1015 break; 1016 case 'S': 1017 /* Security options (undocumented, just for tests) */ 1018 error = smb_parse_secopts(ctx, arg); 1019 break; 1020 case 'T': 1021 /* timeout - ignored */ 1022 break; 1023 case 'D': /* domain */ 1024 case 'W': /* workgroup (legacy alias) */ 1025 error = smb_ctx_setdomain(ctx, tmp, TRUE); 1026 break; 1027 } 1028 return (error); 1029 } 1030 1031 1032 /* 1033 * Original code injected iconv tables into the kernel. 1034 * Not sure if we'll need this or not... REVISIT 1035 */ 1036 #ifdef KICONV_SUPPORT 1037 static int 1038 smb_addiconvtbl(const char *to, const char *from, const uchar_t *tbl) 1039 { 1040 int error = 0; 1041 1042 error = kiconv_add_xlat_table(to, from, tbl); 1043 if (error && error != EEXIST) { 1044 smb_error(dgettext(TEXT_DOMAIN, 1045 "can not setup kernel iconv table (%s:%s)"), 1046 error, from, to); 1047 return (error); 1048 } 1049 return (error); 1050 } 1051 #endif /* KICONV_SUPPORT */ 1052 1053 /* 1054 * Verify context info. before connect operation(s), 1055 * lookup specified server and try to fill all forgotten fields. 1056 * Legacy name used by commands. 1057 */ 1058 int 1059 smb_ctx_resolve(struct smb_ctx *ctx) 1060 { 1061 struct smbioc_ossn *ssn = &ctx->ct_ssn; 1062 int error = 0; 1063 #ifdef KICONV_SUPPORT 1064 uchar_t cstbl[256]; 1065 uint_t i; 1066 #endif 1067 1068 if (smb_debug) 1069 dump_ctx("before smb_ctx_resolve", ctx); 1070 1071 ctx->ct_flags &= ~SMBCF_RESOLVED; 1072 1073 if (ctx->ct_fullserver == NULL) { 1074 smb_error(dgettext(TEXT_DOMAIN, 1075 "no server name specified"), 0); 1076 return (EINVAL); 1077 } 1078 1079 if (ctx->ct_minlevel >= SMBL_SHARE && 1080 ctx->ct_origshare == NULL) { 1081 smb_error(dgettext(TEXT_DOMAIN, 1082 "no share name specified for %s@%s"), 1083 0, ssn->ssn_user, ctx->ct_fullserver); 1084 return (EINVAL); 1085 } 1086 error = nb_ctx_resolve(ctx->ct_nb); 1087 if (error) 1088 return (error); 1089 #ifdef KICONV_SUPPORT 1090 if (ssn->ioc_localcs[0] == 0) 1091 strcpy(ssn->ioc_localcs, "default"); /* XXX: locale name ? */ 1092 error = smb_addiconvtbl("tolower", ssn->ioc_localcs, nls_lower); 1093 if (error) 1094 return (error); 1095 error = smb_addiconvtbl("toupper", ssn->ioc_localcs, nls_upper); 1096 if (error) 1097 return (error); 1098 if (ssn->ioc_servercs[0] != 0) { 1099 for (i = 0; i < sizeof (cstbl); i++) 1100 cstbl[i] = i; 1101 nls_mem_toext(cstbl, cstbl, sizeof (cstbl)); 1102 error = smb_addiconvtbl(ssn->ioc_servercs, ssn->ioc_localcs, 1103 cstbl); 1104 if (error) 1105 return (error); 1106 for (i = 0; i < sizeof (cstbl); i++) 1107 cstbl[i] = i; 1108 nls_mem_toloc(cstbl, cstbl, sizeof (cstbl)); 1109 error = smb_addiconvtbl(ssn->ioc_localcs, ssn->ioc_servercs, 1110 cstbl); 1111 if (error) 1112 return (error); 1113 } 1114 #endif /* KICONV_SUPPORT */ 1115 1116 /* 1117 * Lookup the IP address and fill in ct_addrinfo. 1118 * 1119 * Note: smb_ctx_getaddr() returns a EAI_xxx 1120 * error value like getaddrinfo(3), but this 1121 * function needs to return an errno value. 1122 */ 1123 error = smb_ctx_getaddr(ctx); 1124 if (error) { 1125 const char *ais = gai_strerror(error); 1126 smb_error(dgettext(TEXT_DOMAIN, 1127 "can't resolve name\"%s\", %s"), 1128 0, ctx->ct_fullserver, ais); 1129 return (ENODATA); 1130 } 1131 assert(ctx->ct_addrinfo != NULL); 1132 1133 /* 1134 * Empty user name means an explicit request for 1135 * NULL session setup, which is a special case. 1136 * (No SMB signing, per [MS-SMB] 3.3.5.3) 1137 */ 1138 if (ctx->ct_user[0] == '\0') { 1139 /* Null user should have null domain too. */ 1140 ctx->ct_domain[0] = '\0'; 1141 ctx->ct_authflags = SMB_AT_ANON; 1142 ctx->ct_vopt |= SMBVOPT_ANONYMOUS; 1143 ctx->ct_vopt &= ~SMBVOPT_SIGNING_REQUIRED; 1144 } 1145 1146 /* 1147 * If we have a user name but no password, 1148 * check for a keychain entry. 1149 * XXX: Only for auth NTLM? 1150 */ 1151 if (ctx->ct_user[0] != '\0') { 1152 /* 1153 * Have a user name. 1154 * If we don't have a p/w yet, 1155 * try the keychain. 1156 */ 1157 if (ctx->ct_password[0] == '\0' && 1158 smb_get_keychain(ctx) == 0) { 1159 strlcpy(ctx->ct_password, "$HASH", 1160 sizeof (ctx->ct_password)); 1161 } 1162 1163 /* 1164 * Mask out disallowed auth types. 1165 */ 1166 ctx->ct_authflags &= ctx->ct_minauth; 1167 } 1168 1169 if (ctx->ct_authflags == 0) { 1170 smb_error(dgettext(TEXT_DOMAIN, 1171 "no valid auth. types"), 0); 1172 return (ENOTSUP); 1173 } 1174 1175 ctx->ct_flags |= SMBCF_RESOLVED; 1176 if (smb_debug) 1177 dump_ctx("after smb_ctx_resolve", ctx); 1178 1179 return (0); 1180 } 1181 1182 /* 1183 * Note: The next three have NODIRECT binding so the 1184 * "fksmbcl" development tool can provide its own. 1185 */ 1186 int 1187 smb_open_driver() 1188 { 1189 int fd; 1190 1191 fd = open("/dev/"NSMB_NAME, O_RDWR); 1192 if (fd < 0) { 1193 return (-1); 1194 } 1195 1196 /* This handle controls per-process resources. */ 1197 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 1198 1199 return (fd); 1200 } 1201 1202 int 1203 nsmb_close(int fd) 1204 { 1205 return (close(fd)); 1206 } 1207 1208 int 1209 nsmb_ioctl(int fd, int cmd, void *arg) 1210 { 1211 return (ioctl(fd, cmd, arg)); 1212 } 1213 1214 1215 int 1216 smb_ctx_gethandle(struct smb_ctx *ctx) 1217 { 1218 int fd, err; 1219 uint32_t version; 1220 1221 if (ctx->ct_dev_fd != -1) { 1222 rpc_cleanup_smbctx(ctx); 1223 nsmb_close(ctx->ct_dev_fd); 1224 ctx->ct_dev_fd = -1; 1225 } 1226 1227 fd = smb_open_driver(); 1228 if (fd < 0) { 1229 err = errno; 1230 smb_error(dgettext(TEXT_DOMAIN, 1231 "failed to open driver"), err); 1232 return (err); 1233 } 1234 1235 /* 1236 * Check the driver version (paranoia) 1237 */ 1238 if (nsmb_ioctl(fd, SMBIOC_GETVERS, &version) < 0) 1239 version = 0; 1240 if (version != NSMB_VERSION) { 1241 smb_error(dgettext(TEXT_DOMAIN, 1242 "incorrect driver version"), 0); 1243 nsmb_close(fd); 1244 return (ENODEV); 1245 } 1246 1247 ctx->ct_dev_fd = fd; 1248 return (0); 1249 } 1250 1251 1252 /* 1253 * Find or create a connection + logon session 1254 */ 1255 int 1256 smb_ctx_get_ssn(struct smb_ctx *ctx) 1257 { 1258 int err = 0; 1259 1260 if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) 1261 return (EINVAL); 1262 1263 /* 1264 * Check whether the driver already has a VC 1265 * we can use. If so, we're done! 1266 */ 1267 err = smb_ctx_findvc(ctx); 1268 if (err == 0) { 1269 DPRINT("found an existing VC"); 1270 } else { 1271 /* 1272 * If we're authenticating (real user, not NULL session) 1273 * and we don't yet have a password, return EAUTH and 1274 * the caller will prompt for it and call again. 1275 */ 1276 if (ctx->ct_user[0] != '\0' && 1277 ctx->ct_password[0] == '\0') 1278 return (EAUTH); 1279 1280 /* 1281 * This calls the IOD to create a new session. 1282 */ 1283 DPRINT("setup a new VC"); 1284 err = smb_ctx_newvc(ctx); 1285 if (err != 0) 1286 return (err); 1287 1288 /* 1289 * Call findvc again. The new VC sould be 1290 * found in the driver this time. 1291 */ 1292 err = smb_ctx_findvc(ctx); 1293 } 1294 1295 return (err); 1296 } 1297 1298 /* 1299 * Find or create a tree connection 1300 */ 1301 int 1302 smb_ctx_get_tree(struct smb_ctx *ctx) 1303 { 1304 smbioc_tcon_t *tcon = NULL; 1305 int cmd, err = 0; 1306 1307 if (ctx->ct_dev_fd < 0 || 1308 ctx->ct_origshare == NULL) { 1309 return (EINVAL); 1310 } 1311 1312 cmd = SMBIOC_TREE_CONNECT; 1313 tcon = malloc(sizeof (*tcon)); 1314 if (tcon == NULL) 1315 return (ENOMEM); 1316 bzero(tcon, sizeof (*tcon)); 1317 tcon->tc_flags = SMBLK_CREATE; 1318 tcon->tc_opt = 0; 1319 1320 /* The share name */ 1321 strlcpy(tcon->tc_sh.sh_name, ctx->ct_origshare, 1322 sizeof (tcon->tc_sh.sh_name)); 1323 1324 /* The share "use" type. */ 1325 tcon->tc_sh.sh_use = ctx->ct_shtype_req; 1326 1327 /* 1328 * Todo: share passwords for share-level security. 1329 * 1330 * The driver does the actual TCON call. 1331 */ 1332 if (nsmb_ioctl(ctx->ct_dev_fd, cmd, tcon) == -1) { 1333 err = errno; 1334 goto out; 1335 } 1336 1337 /* 1338 * Check the returned share type 1339 */ 1340 DPRINT("ret. sh_type: \"%d\"", tcon->tc_sh.sh_type); 1341 if (ctx->ct_shtype_req != USE_WILDCARD && 1342 ctx->ct_shtype_req != tcon->tc_sh.sh_type) { 1343 smb_error(dgettext(TEXT_DOMAIN, 1344 "%s: incompatible share type"), 1345 0, ctx->ct_origshare); 1346 } 1347 1348 out: 1349 if (tcon != NULL) 1350 free(tcon); 1351 1352 return (err); 1353 } 1354 1355 /* 1356 * Return the hflags2 word for an smb_ctx. 1357 */ 1358 int 1359 smb_ctx_flags2(struct smb_ctx *ctx) 1360 { 1361 uint16_t flags2; 1362 1363 if (nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_FLAGS2, &flags2) == -1) { 1364 smb_error(dgettext(TEXT_DOMAIN, 1365 "can't get flags2 for a session"), errno); 1366 return (-1); 1367 } 1368 return (flags2); 1369 } 1370 1371 /* 1372 * Get the transport level session key. 1373 * Must already have an active SMB session. 1374 */ 1375 int 1376 smb_fh_getssnkey(int dev_fd, uchar_t *key, size_t len) 1377 { 1378 if (len < SMBIOC_HASH_SZ) 1379 return (EINVAL); 1380 1381 if (nsmb_ioctl(dev_fd, SMBIOC_GETSSNKEY, key) == -1) 1382 return (errno); 1383 1384 return (0); 1385 } 1386 1387 /* 1388 * RC file parsing stuff 1389 */ 1390 1391 static struct nv 1392 minauth_table[] = { 1393 /* Allowed auth. types */ 1394 { "kerberos", SMB_AT_KRB5 }, 1395 { "ntlmv2", SMB_AT_KRB5|SMB_AT_NTLM2 }, 1396 { "ntlm", SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1 }, 1397 { "lm", SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1|SMB_AT_LM1 }, 1398 { "none", SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1|SMB_AT_LM1| 1399 SMB_AT_ANON }, 1400 { NULL } 1401 }; 1402 1403 int 1404 smb_cf_minauth_from_str(char *str) 1405 { 1406 struct nv *nvp; 1407 1408 for (nvp = minauth_table; nvp->name; nvp++) 1409 if (strcmp(nvp->name, str) == 0) 1410 return (nvp->value); 1411 return (-1); 1412 } 1413 1414 1415 static struct nv 1416 smbver_table[] = { 1417 { "2.1", SMB2_DIALECT_0210 }, 1418 { "1", 1 }, 1419 { NULL, 0 } 1420 }; 1421 1422 int 1423 smb_cf_version_from_str(char *str) 1424 { 1425 struct nv *nvp; 1426 1427 for (nvp = smbver_table; nvp->name; nvp++) 1428 if (strcmp(nvp->name, str) == 0) 1429 return (nvp->value); 1430 return (-1); 1431 } 1432 1433 /* 1434 * level values: 1435 * 0 - default 1436 * 1 - server 1437 * 2 - server:user 1438 * 3 - server:user:share 1439 */ 1440 static int 1441 smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level) 1442 { 1443 char *p; 1444 int ival; 1445 int error; 1446 int minver, maxver; 1447 1448 #ifdef KICONV_SUPPORT 1449 if (level > 0) { 1450 rc_getstringptr(smb_rc, sname, "charsets", &p); 1451 if (p) { 1452 error = smb_ctx_setcharset(ctx, p); 1453 if (error) 1454 smb_error(dgettext(TEXT_DOMAIN, 1455 "charset specification in the section '%s' ignored"), 1456 error, sname); 1457 } 1458 } 1459 #endif 1460 1461 if (level <= 1) { 1462 /* Section is: [default] or [server] */ 1463 1464 /* 1465 * Handle min_protocol, max_protocol 1466 * (SMB protocol versions) 1467 */ 1468 minver = -1; 1469 rc_getstringptr(smb_rc, sname, "min_protocol", &p); 1470 if (p != NULL) { 1471 minver = smb_cf_version_from_str(p); 1472 if (minver == -1) { 1473 smb_error(dgettext(TEXT_DOMAIN, 1474 "invalid min_protocol value \"%s\" specified in the section %s"), 1475 0, p, sname); 1476 } 1477 } 1478 maxver = -1; 1479 rc_getstringptr(smb_rc, sname, "max_protocol", &p); 1480 if (p != NULL) { 1481 maxver = smb_cf_version_from_str(p); 1482 if (maxver == -1) { 1483 smb_error(dgettext(TEXT_DOMAIN, 1484 "invalid max_protocol value \"%s\" specified in the section %s"), 1485 0, p, sname); 1486 } 1487 } 1488 1489 /* 1490 * If setting both min/max protocol, 1491 * validate against each other 1492 */ 1493 if (minver != -1 && maxver != -1) { 1494 if (minver > maxver) { 1495 smb_error(dgettext(TEXT_DOMAIN, 1496 "invalid min/max protocol combination in the section %s"), 1497 0, sname); 1498 } else { 1499 ctx->ct_minver = minver; 1500 ctx->ct_maxver = maxver; 1501 } 1502 } 1503 1504 /* 1505 * Setting just min or max, validate against 1506 * current settings 1507 */ 1508 if (minver != -1) { 1509 if (minver > ctx->ct_maxver) { 1510 smb_error(dgettext(TEXT_DOMAIN, 1511 "invalid min/max protocol combination in the section %s"), 1512 0, sname); 1513 } else { 1514 ctx->ct_minver = minver; 1515 } 1516 } 1517 if (maxver != -1) { 1518 if (maxver < ctx->ct_minver) { 1519 smb_error(dgettext(TEXT_DOMAIN, 1520 "invalid min/max protocol combination in the section %s"), 1521 0, sname); 1522 } else { 1523 ctx->ct_maxver = maxver; 1524 } 1525 } 1526 1527 rc_getstringptr(smb_rc, sname, "minauth", &p); 1528 if (p) { 1529 /* 1530 * "minauth" was set in this section; override 1531 * the current minimum authentication setting. 1532 */ 1533 ival = smb_cf_minauth_from_str(p); 1534 if (ival != -1) { 1535 ctx->ct_minauth = ival; 1536 } else { 1537 /* 1538 * Unknown minimum authentication level. 1539 */ 1540 smb_error(dgettext(TEXT_DOMAIN, 1541 "invalid minimum authentication level \"%s\" specified in the section %s"), 1542 0, p, sname); 1543 return (EINVAL); 1544 } 1545 } 1546 1547 rc_getstringptr(smb_rc, sname, "signing", &p); 1548 if (p) { 1549 /* 1550 * "signing" was set in this section; override 1551 * the current signing settings. Note: 1552 * setsigning flags are: enable, require 1553 */ 1554 if (strcmp(p, "disabled") == 0) { 1555 (void) smb_ctx_setsigning(ctx, FALSE, FALSE); 1556 } else if (strcmp(p, "enabled") == 0) { 1557 (void) smb_ctx_setsigning(ctx, TRUE, FALSE); 1558 } else if (strcmp(p, "required") == 0) { 1559 (void) smb_ctx_setsigning(ctx, TRUE, TRUE); 1560 } else { 1561 /* 1562 * Unknown "signing" value. 1563 */ 1564 smb_error(dgettext(TEXT_DOMAIN, 1565 "invalid signing policy \"%s\" specified in the section %s"), 1566 0, p, sname); 1567 return (EINVAL); 1568 } 1569 } 1570 1571 /* 1572 * Domain name. Allow both keywords: 1573 * "workgroup", "domain" 1574 * 1575 * Note: these are NOT marked "from CMD". 1576 * See long comment at smb_ctx_init() 1577 */ 1578 rc_getstringptr(smb_rc, sname, "workgroup", &p); 1579 if (p) { 1580 error = smb_ctx_setdomain(ctx, p, 0); 1581 if (error) 1582 smb_error(dgettext(TEXT_DOMAIN, 1583 "workgroup specification in the " 1584 "section '%s' ignored"), error, sname); 1585 } 1586 rc_getstringptr(smb_rc, sname, "domain", &p); 1587 if (p) { 1588 error = smb_ctx_setdomain(ctx, p, 0); 1589 if (error) 1590 smb_error(dgettext(TEXT_DOMAIN, 1591 "domain specification in the " 1592 "section '%s' ignored"), error, sname); 1593 } 1594 1595 rc_getstringptr(smb_rc, sname, "user", &p); 1596 if (p) { 1597 error = smb_ctx_setuser(ctx, p, 0); 1598 if (error) 1599 smb_error(dgettext(TEXT_DOMAIN, 1600 "user specification in the " 1601 "section '%s' ignored"), error, sname); 1602 } 1603 } 1604 1605 if (level == 1) { 1606 /* Section is: [server] */ 1607 rc_getstringptr(smb_rc, sname, "addr", &p); 1608 if (p) { 1609 error = smb_ctx_setsrvaddr(ctx, p); 1610 if (error) { 1611 smb_error(dgettext(TEXT_DOMAIN, 1612 "invalid address specified in section %s"), 1613 0, sname); 1614 return (error); 1615 } 1616 } 1617 } 1618 1619 rc_getstringptr(smb_rc, sname, "password", &p); 1620 if (p) { 1621 error = smb_ctx_setpassword(ctx, p, 0); 1622 if (error) 1623 smb_error(dgettext(TEXT_DOMAIN, 1624 "password specification in the section '%s' ignored"), 1625 error, sname); 1626 } 1627 1628 return (0); 1629 } 1630 1631 /* 1632 * read rc file as follows: 1633 * 0: read [default] section 1634 * 1: override with [server] section 1635 * 2: override with [server:user] section 1636 * 3: override with [server:user:share] section 1637 * Since absence of rcfile is not fatal, silently ignore this fact. 1638 * smb_rc file should be closed by caller. 1639 */ 1640 int 1641 smb_ctx_readrc(struct smb_ctx *ctx) 1642 { 1643 char pwbuf[NSS_BUFLEN_PASSWD]; 1644 struct passwd pw; 1645 char *sname = NULL; 1646 int sname_max; 1647 int err = 0; 1648 1649 /* 1650 * If the user name is not specified some other way, 1651 * use the current user name. Also save the homedir. 1652 * NB: ct_home=NULL is allowed, and we don't want to 1653 * bail out with an error for a missing ct_home. 1654 */ 1655 if (getpwuid_r(getuid(), &pw, pwbuf, sizeof (pwbuf)) != NULL) { 1656 if (ctx->ct_user[0] == 0) 1657 (void) smb_ctx_setuser(ctx, pw.pw_name, B_FALSE); 1658 if (ctx->ct_home == NULL) 1659 ctx->ct_home = strdup(pw.pw_dir); 1660 } 1661 1662 if ((err = smb_open_rcfile(ctx->ct_home)) != 0) { 1663 DPRINT("smb_open_rcfile, err=%d", err); 1664 /* ignore any error here */ 1665 return (0); 1666 } 1667 1668 sname_max = 3 * SMBIOC_MAX_NAME + 4; 1669 sname = malloc(sname_max); 1670 if (sname == NULL) { 1671 err = ENOMEM; 1672 goto done; 1673 } 1674 1675 /* 1676 * default parameters (level=0) 1677 */ 1678 smb_ctx_readrcsection(ctx, "default", 0); 1679 nb_ctx_readrcsection(smb_rc, ctx->ct_nb, "default", 0); 1680 1681 /* 1682 * If we don't have a server name, we can't read any of the 1683 * [server...] sections. 1684 */ 1685 if (ctx->ct_fullserver == NULL) 1686 goto done; 1687 /* 1688 * SERVER parameters. 1689 */ 1690 smb_ctx_readrcsection(ctx, ctx->ct_fullserver, 1); 1691 1692 /* 1693 * If we don't have a user name, we can't read any of the 1694 * [server:user...] sections. 1695 */ 1696 if (ctx->ct_user[0] == 0) 1697 goto done; 1698 /* 1699 * SERVER:USER parameters 1700 */ 1701 snprintf(sname, sname_max, "%s:%s", 1702 ctx->ct_fullserver, 1703 ctx->ct_user); 1704 smb_ctx_readrcsection(ctx, sname, 2); 1705 1706 1707 /* 1708 * If we don't have a share name, we can't read any of the 1709 * [server:user:share] sections. 1710 */ 1711 if (ctx->ct_origshare == NULL) 1712 goto done; 1713 /* 1714 * SERVER:USER:SHARE parameters 1715 */ 1716 snprintf(sname, sname_max, "%s:%s:%s", 1717 ctx->ct_fullserver, 1718 ctx->ct_user, 1719 ctx->ct_origshare); 1720 smb_ctx_readrcsection(ctx, sname, 3); 1721 1722 done: 1723 if (sname) 1724 free(sname); 1725 smb_close_rcfile(); 1726 if (smb_debug) 1727 dump_ctx("after smb_ctx_readrc", ctx); 1728 if (err) 1729 DPRINT("err=%d\n", err); 1730 1731 return (err); 1732 } 1733 1734 void 1735 smbfs_set_default_domain(const char *domain) 1736 { 1737 strlcpy(default_domain, domain, sizeof (default_domain)); 1738 } 1739 1740 void 1741 smbfs_set_default_user(const char *user) 1742 { 1743 strlcpy(default_user, user, sizeof (default_user)); 1744 } 1745