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