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