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