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 2009 Sun Microsystems, Inc. All rights reserved. 37 * Use is subject to license terms. 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 "spnego.h" 69 #include "derparse.h" 70 #include "private.h" 71 #include "ntlm.h" 72 73 #ifndef FALSE 74 #define FALSE 0 75 #endif 76 #ifndef TRUE 77 #define TRUE 1 78 #endif 79 80 81 /* These two may be set by commands. */ 82 int smb_debug, smb_verbose; 83 84 /* 85 * Was: STDPARAM_OPT - see smb_ctx_scan_argv, smb_ctx_opt 86 */ 87 const char smbutil_std_opts[] = "ABCD:E:I:L:M:NO:P:U:R:S:T:W:"; 88 89 /* 90 * Give the RPC library a callback hook that will be 91 * called whenever we destroy or reinit an smb_ctx_t. 92 * The name rpc_cleanup_smbctx() is legacy, and was 93 * originally a direct call into the RPC code. 94 */ 95 static smb_ctx_close_hook_t close_hook; 96 static void 97 rpc_cleanup_smbctx(struct smb_ctx *ctx) 98 { 99 if (close_hook) 100 (*close_hook)(ctx); 101 } 102 void 103 smb_ctx_set_close_hook(smb_ctx_close_hook_t hook) 104 { 105 close_hook = hook; 106 } 107 108 void 109 dump_ctx_flags(int flags) 110 { 111 printf(" Flags: "); 112 if (flags == 0) 113 printf("0"); 114 if (flags & SMBCF_NOPWD) 115 printf("NOPWD "); 116 if (flags & SMBCF_SRIGHTS) 117 printf("SRIGHTS "); 118 if (flags & SMBCF_LOCALE) 119 printf("LOCALE "); 120 if (flags & SMBCF_CMD_DOM) 121 printf("CMD_DOM "); 122 if (flags & SMBCF_CMD_USR) 123 printf("CMD_USR "); 124 if (flags & SMBCF_CMD_PW) 125 printf("CMD_PW "); 126 if (flags & SMBCF_RESOLVED) 127 printf("RESOLVED "); 128 if (flags & SMBCF_KCBAD) 129 printf("KCBAD "); 130 if (flags & SMBCF_KCFOUND) 131 printf("KCFOUND "); 132 if (flags & SMBCF_BROWSEOK) 133 printf("BROWSEOK "); 134 if (flags & SMBCF_AUTHREQ) 135 printf("AUTHREQ "); 136 if (flags & SMBCF_KCSAVE) 137 printf("KCSAVE "); 138 if (flags & SMBCF_XXX) 139 printf("XXX "); 140 if (flags & SMBCF_SSNACTIVE) 141 printf("SSNACTIVE "); 142 if (flags & SMBCF_KCDOMAIN) 143 printf("KCDOMAIN "); 144 printf("\n"); 145 } 146 147 void 148 dump_iod_ssn(smb_iod_ssn_t *is) 149 { 150 static const char zeros[NTLM_HASH_SZ] = {0}; 151 struct smbioc_ossn *ssn = &is->iod_ossn; 152 153 printf(" ct_srvname=\"%s\", ", ssn->ssn_srvname); 154 dump_sockaddr(&ssn->ssn_srvaddr.sa); 155 printf(" dom=\"%s\", user=\"%s\"\n", 156 ssn->ssn_domain, ssn->ssn_user); 157 printf(" ct_vopt=0x%x, ct_owner=%d\n", 158 ssn->ssn_vopt, ssn->ssn_owner); 159 printf(" ct_authflags=0x%x\n", is->iod_authflags); 160 161 printf(" ct_nthash:"); 162 if (bcmp(zeros, &is->iod_nthash, NTLM_HASH_SZ)) 163 smb_hexdump(&is->iod_nthash, NTLM_HASH_SZ); 164 else 165 printf(" {0}\n"); 166 167 printf(" ct_lmhash:"); 168 if (bcmp(zeros, &is->iod_lmhash, NTLM_HASH_SZ)) 169 smb_hexdump(&is->iod_lmhash, NTLM_HASH_SZ); 170 else 171 printf(" {0}\n"); 172 } 173 174 void 175 dump_ctx(char *where, struct smb_ctx *ctx) 176 { 177 printf("context %s:\n", where); 178 dump_ctx_flags(ctx->ct_flags); 179 180 if (ctx->ct_locname) 181 printf(" localname=\"%s\"", ctx->ct_locname); 182 else 183 printf(" localname=NULL"); 184 185 if (ctx->ct_fullserver) 186 printf(" fullserver=\"%s\"", ctx->ct_fullserver); 187 else 188 printf(" fullserver=NULL"); 189 190 if (ctx->ct_srvaddr_s) 191 printf(" srvaddr_s=\"%s\"\n", ctx->ct_srvaddr_s); 192 else 193 printf(" srvaddr_s=NULL\n"); 194 195 if (ctx->ct_addrinfo) 196 dump_addrinfo(ctx->ct_addrinfo); 197 else 198 printf(" ct_addrinfo = NULL\n"); 199 200 dump_iod_ssn(&ctx->ct_iod_ssn); 201 202 printf(" share_name=\"%s\", share_type=%d\n", 203 ctx->ct_origshare ? ctx->ct_origshare : "", 204 ctx->ct_shtype_req); 205 206 /* dump_iod_work()? */ 207 } 208 209 int 210 smb_ctx_alloc(struct smb_ctx **ctx_pp) 211 { 212 smb_ctx_t *ctx; 213 int err; 214 215 ctx = malloc(sizeof (*ctx)); 216 if (ctx == NULL) 217 return (ENOMEM); 218 err = smb_ctx_init(ctx); 219 if (err != 0) { 220 free(ctx); 221 return (err); 222 } 223 *ctx_pp = ctx; 224 return (0); 225 } 226 227 /* 228 * Initialize an smb_ctx struct (defaults) 229 */ 230 int 231 smb_ctx_init(struct smb_ctx *ctx) 232 { 233 char pwbuf[NSS_BUFLEN_PASSWD]; 234 struct passwd pw; 235 int error = 0; 236 237 bzero(ctx, sizeof (*ctx)); 238 239 error = nb_ctx_create(&ctx->ct_nb); 240 if (error) 241 return (error); 242 243 ctx->ct_dev_fd = -1; 244 ctx->ct_door_fd = -1; 245 ctx->ct_tran_fd = -1; 246 ctx->ct_parsedlevel = SMBL_NONE; 247 ctx->ct_minlevel = SMBL_NONE; 248 ctx->ct_maxlevel = SMBL_PATH; 249 250 /* Fill in defaults */ 251 ctx->ct_vopt = SMBVOPT_EXT_SEC; 252 ctx->ct_owner = SMBM_ANY_OWNER; 253 ctx->ct_authflags = SMB_AT_DEFAULT; 254 ctx->ct_minauth = SMB_AT_DEFAULT; 255 256 error = nb_ctx_setscope(ctx->ct_nb, ""); 257 if (error) 258 return (error); 259 260 /* 261 * if the user name is not specified some other way, 262 * use the current user name (built-in default) 263 */ 264 if (getpwuid_r(getuid(), &pw, pwbuf, sizeof (pwbuf)) != NULL) { 265 error = smb_ctx_setuser(ctx, pw.pw_name, 0); 266 if (error) 267 return (error); 268 ctx->ct_home = strdup(pw.pw_name); 269 if (ctx->ct_home == NULL) 270 return (ENOMEM); 271 } 272 273 /* 274 * Set a built-in default domain (workgroup). 275 * Using the Windows/NT default for now. 276 */ 277 error = smb_ctx_setdomain(ctx, "WORKGROUP", 0); 278 if (error) 279 return (error); 280 281 return (error); 282 } 283 284 /* 285 * "Scan" the command line args to find the server name, 286 * user name, and share name, as needed. We need these 287 * before reading the RC files and/or sharectl values. 288 * 289 * The sequence for getting all the members filled in 290 * has some tricky aspects. Here's how it works: 291 * 292 * The search order for options is as follows: 293 * command line options 294 * values parsed from UNC path (cmd) 295 * values from RC file (per-user) 296 * values from SMF (system-wide) 297 * built-in defaults 298 * 299 * Normally, one would simply get all the values starting with 300 * the bottom of the above list and working to the top, and 301 * overwriting values as you go. But we need an exception. 302 * 303 * In this function, we parse the UNC path and command line options, 304 * because we need (at least) the server name when we're getting the 305 * SMF and RC file values. However, values we get from the command 306 * should not be overwritten by SMF or RC file parsing, so we mark 307 * values from the command as "from CMD" and the RC file parser 308 * leaves in place any values so marked. See: SMBCF_CMD_* 309 * 310 * The semantics of these flags are: "This value came from the 311 * current command instance, not from sources that may apply to 312 * multiple commands." (Different from the old "FROMUSR" flag.) 313 * 314 * Note that smb_ctx_opt() is called later to handle the 315 * remaining options, which should be ignored here. 316 * The (magic) leading ":" in cf_getopt() makes it 317 * ignore options not in the options string. 318 */ 319 int 320 smb_ctx_scan_argv(struct smb_ctx *ctx, int argc, char **argv, 321 int minlevel, int maxlevel, int sharetype) 322 { 323 int ind, opt, error = 0; 324 int aflg = 0, uflg = 0; 325 const char *arg; 326 327 /* 328 * Parse options, if any. Values from here too 329 * are marked as "from CMD". 330 */ 331 if (argv == NULL) 332 return (0); 333 334 ctx->ct_minlevel = minlevel; 335 ctx->ct_maxlevel = maxlevel; 336 ctx->ct_shtype_req = sharetype; 337 338 cf_opt_lock(); 339 /* Careful: no return/goto before cf_opt_unlock! */ 340 while (error == 0) { 341 opt = cf_getopt(argc, argv, STDPARAM_OPT); 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 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 if (ctx->ct_srv_OS) { 444 free(ctx->ct_srv_OS); 445 ctx->ct_srv_OS = NULL; 446 } 447 if (ctx->ct_srv_LM) { 448 free(ctx->ct_srv_LM); 449 ctx->ct_srv_LM = NULL; 450 } 451 if (ctx->ct_mackey) { 452 free(ctx->ct_mackey); 453 ctx->ct_mackey = NULL; 454 } 455 } 456 457 static int 458 getsubstring(const char *p, uchar_t sep, char *dest, int maxlen, 459 const char **next) 460 { 461 int len; 462 463 maxlen--; 464 for (len = 0; len < maxlen && *p != sep; p++, len++, dest++) { 465 if (*p == 0) 466 return (EINVAL); 467 *dest = *p; 468 } 469 *dest = 0; 470 *next = *p ? p + 1 : p; 471 return (0); 472 } 473 474 /* 475 * Parse the UNC path. Here we expect something like 476 * "//[workgroup;][user[:password]@]host[/share[/path]]" 477 * See http://ietf.org/internet-drafts/draft-crhertel-smb-url-07.txt 478 * Values found here are marked as "from CMD". 479 */ 480 int 481 smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc, 482 int minlevel, int maxlevel, int sharetype, 483 const char **next) 484 { 485 const char *p = unc; 486 char *p1, *colon; 487 char tmp[1024]; 488 char tmp2[1024]; 489 int error; 490 491 /* 492 * This may be called outside of _scan_argv, 493 * so make sure these get initialized. 494 */ 495 ctx->ct_minlevel = minlevel; 496 ctx->ct_maxlevel = maxlevel; 497 ctx->ct_shtype_req = sharetype; 498 499 ctx->ct_parsedlevel = SMBL_NONE; 500 if (*p++ != '/' || *p++ != '/') { 501 smb_error(dgettext(TEXT_DOMAIN, 502 "UNC should start with '//'"), 0); 503 error = EINVAL; 504 goto out; 505 } 506 p1 = tmp; 507 error = getsubstring(p, ';', p1, sizeof (tmp), &p); 508 if (!error) { 509 if (*p1 == 0) { 510 smb_error(dgettext(TEXT_DOMAIN, 511 "empty workgroup name"), 0); 512 error = EINVAL; 513 goto out; 514 } 515 nls_str_upper(tmp, tmp); 516 error = smb_ctx_setdomain(ctx, unpercent(tmp), TRUE); 517 if (error) 518 goto out; 519 } 520 colon = (char *)p; 521 error = getsubstring(p, '@', p1, sizeof (tmp), &p); 522 if (!error) { 523 if (ctx->ct_maxlevel < SMBL_VC) { 524 smb_error(dgettext(TEXT_DOMAIN, 525 "no user name required"), 0); 526 error = EINVAL; 527 goto out; 528 } 529 p1 = strchr(tmp, ':'); 530 if (p1) { 531 colon += p1 - tmp; 532 *p1++ = (char)0; 533 error = smb_ctx_setpassword(ctx, unpercent(p1), TRUE); 534 if (error) 535 goto out; 536 if (p - colon > 2) 537 memset(colon+1, '*', p - colon - 2); 538 } 539 p1 = tmp; 540 if (*p1 == 0) { 541 smb_error(dgettext(TEXT_DOMAIN, 542 "empty user name"), 0); 543 error = EINVAL; 544 goto out; 545 } 546 error = smb_ctx_setuser(ctx, unpercent(tmp), TRUE); 547 if (error) 548 goto out; 549 ctx->ct_parsedlevel = SMBL_VC; 550 } 551 error = getsubstring(p, '/', p1, sizeof (tmp), &p); 552 if (error) { 553 error = getsubstring(p, '\0', p1, sizeof (tmp), &p); 554 if (error) { 555 smb_error(dgettext(TEXT_DOMAIN, 556 "no server name found"), 0); 557 goto out; 558 } 559 } 560 if (*p1 == 0) { 561 smb_error(dgettext(TEXT_DOMAIN, "empty server name"), 0); 562 error = EINVAL; 563 goto out; 564 } 565 566 /* 567 * It's safe to uppercase this string, which 568 * consists of ascii characters that should 569 * be uppercased, %s, and ascii characters representing 570 * hex digits 0-9 and A-F (already uppercased, and 571 * if not uppercased they need to be). However, 572 * it is NOT safe to uppercase after it has been 573 * "unpercent" converted, below! 574 */ 575 nls_str_upper(tmp2, tmp); 576 577 /* 578 * Save ct_fullserver without case conversion. 579 */ 580 if (strchr(tmp, '%')) 581 (void) unpercent(tmp); 582 error = smb_ctx_setfullserver(ctx, tmp); 583 if (error) 584 goto out; 585 586 #ifdef SMB_ST_NONE 587 if (sharetype == SMB_ST_NONE) { 588 if (next) 589 *next = p; 590 error = 0; 591 goto out; 592 } 593 #endif 594 595 if (*p != 0 && ctx->ct_maxlevel < SMBL_SHARE) { 596 smb_error(dgettext(TEXT_DOMAIN, "no share name required"), 0); 597 error = EINVAL; 598 goto out; 599 } 600 error = getsubstring(p, '/', p1, sizeof (tmp), &p); 601 if (error) { 602 error = getsubstring(p, '\0', p1, sizeof (tmp), &p); 603 if (error) { 604 smb_error(dgettext(TEXT_DOMAIN, 605 "unexpected end of line"), 0); 606 goto out; 607 } 608 } 609 if (*p1 == 0 && ctx->ct_minlevel >= SMBL_SHARE && 610 !(ctx->ct_flags & SMBCF_BROWSEOK)) { 611 smb_error(dgettext(TEXT_DOMAIN, "empty share name"), 0); 612 error = EINVAL; 613 goto out; 614 } 615 if (next) 616 *next = p; 617 if (*p1 == 0) { 618 error = 0; 619 goto out; 620 } 621 error = smb_ctx_setshare(ctx, unpercent(p1), sharetype); 622 623 out: 624 if (error == 0 && smb_debug > 0) 625 dump_ctx("after smb_ctx_parseunc", ctx); 626 627 return (error); 628 } 629 630 #ifdef KICONV_SUPPORT 631 int 632 smb_ctx_setcharset(struct smb_ctx *ctx, const char *arg) 633 { 634 char *cp, *servercs, *localcs; 635 int cslen = sizeof (ctx->ct_ssn.ioc_localcs); 636 int scslen, lcslen, error; 637 638 cp = strchr(arg, ':'); 639 lcslen = cp ? (cp - arg) : 0; 640 if (lcslen == 0 || lcslen >= cslen) { 641 smb_error(dgettext(TEXT_DOMAIN, 642 "invalid local charset specification (%s)"), 0, arg); 643 return (EINVAL); 644 } 645 scslen = (size_t)strlen(++cp); 646 if (scslen == 0 || scslen >= cslen) { 647 smb_error(dgettext(TEXT_DOMAIN, 648 "invalid server charset specification (%s)"), 0, arg); 649 return (EINVAL); 650 } 651 localcs = memcpy(ctx->ct_ssn.ioc_localcs, arg, lcslen); 652 localcs[lcslen] = 0; 653 servercs = strcpy(ctx->ct_ssn.ioc_servercs, cp); 654 error = nls_setrecode(localcs, servercs); 655 if (error == 0) 656 return (0); 657 smb_error(dgettext(TEXT_DOMAIN, 658 "can't initialize iconv support (%s:%s)"), 659 error, localcs, servercs); 660 localcs[0] = 0; 661 servercs[0] = 0; 662 return (error); 663 } 664 #endif /* KICONV_SUPPORT */ 665 666 int 667 smb_ctx_setauthflags(struct smb_ctx *ctx, int flags) 668 { 669 ctx->ct_authflags = flags; 670 return (0); 671 } 672 673 int 674 smb_ctx_setfullserver(struct smb_ctx *ctx, const char *name) 675 { 676 char *p = strdup(name); 677 678 if (p == NULL) 679 return (ENOMEM); 680 if (ctx->ct_fullserver) 681 free(ctx->ct_fullserver); 682 ctx->ct_fullserver = p; 683 return (0); 684 } 685 686 /* this routine does not uppercase the server name */ 687 int 688 smb_ctx_setserver(struct smb_ctx *ctx, const char *name) 689 { 690 /* don't uppercase the server name */ 691 strlcpy(ctx->ct_srvname, name, 692 sizeof (ctx->ct_srvname)); 693 return (0); 694 } 695 696 int 697 smb_ctx_setuser(struct smb_ctx *ctx, const char *name, int from_cmd) 698 { 699 700 if (strlen(name) >= sizeof (ctx->ct_user)) { 701 smb_error(dgettext(TEXT_DOMAIN, 702 "user name '%s' too long"), 0, name); 703 return (ENAMETOOLONG); 704 } 705 706 /* 707 * Don't overwrite a value from the command line 708 * with one from anywhere else. 709 */ 710 if (!from_cmd && (ctx->ct_flags & SMBCF_CMD_USR)) 711 return (0); 712 713 /* don't uppercase the username, just copy it. */ 714 strlcpy(ctx->ct_user, name, 715 sizeof (ctx->ct_user)); 716 717 /* Mark this as "from the command line". */ 718 if (from_cmd) 719 ctx->ct_flags |= SMBCF_CMD_USR; 720 721 return (0); 722 } 723 724 /* 725 * Never uppercase the workgroup 726 * name here, because it might come 727 * from a Windows codepage encoding. 728 * 729 * Don't overwrite a domain name from the 730 * command line with one from anywhere else. 731 * See smb_ctx_init() for notes about this. 732 */ 733 int 734 smb_ctx_setdomain(struct smb_ctx *ctx, const char *name, int from_cmd) 735 { 736 737 if (strlen(name) >= sizeof (ctx->ct_domain)) { 738 smb_error(dgettext(TEXT_DOMAIN, 739 "workgroup name '%s' too long"), 0, name); 740 return (ENAMETOOLONG); 741 } 742 743 /* 744 * Don't overwrite a value from the command line 745 * with one from anywhere else. 746 */ 747 if (!from_cmd && (ctx->ct_flags & SMBCF_CMD_DOM)) 748 return (0); 749 750 strlcpy(ctx->ct_domain, name, 751 sizeof (ctx->ct_domain)); 752 753 /* Mark this as "from the command line". */ 754 if (from_cmd) 755 ctx->ct_flags |= SMBCF_CMD_DOM; 756 757 return (0); 758 } 759 760 int 761 smb_ctx_setpassword(struct smb_ctx *ctx, const char *passwd, int from_cmd) 762 { 763 int err; 764 765 if (passwd == NULL) 766 return (EINVAL); 767 if (strlen(passwd) >= sizeof (ctx->ct_password)) { 768 smb_error(dgettext(TEXT_DOMAIN, "password too long"), 0); 769 return (ENAMETOOLONG); 770 } 771 772 /* 773 * If called again after comand line parsing, 774 * don't overwrite a value from the command line 775 * with one from any stored config. 776 */ 777 if (!from_cmd && (ctx->ct_flags & SMBCF_CMD_PW)) 778 return (0); 779 780 memset(ctx->ct_password, 0, sizeof (ctx->ct_password)); 781 if (strncmp(passwd, "$$1", 3) == 0) 782 (void) smb_simpledecrypt(ctx->ct_password, passwd); 783 else 784 strlcpy(ctx->ct_password, passwd, 785 sizeof (ctx->ct_password)); 786 787 /* 788 * Compute LM hash, NT hash. 789 */ 790 if (ctx->ct_password[0]) { 791 err = ntlm_compute_nt_hash(ctx->ct_nthash, ctx->ct_password); 792 if (err != 0) 793 return (err); 794 err = ntlm_compute_lm_hash(ctx->ct_lmhash, ctx->ct_password); 795 if (err != 0) 796 return (err); 797 } 798 799 /* Mark this as "from the command line". */ 800 if (from_cmd) 801 ctx->ct_flags |= SMBCF_CMD_PW; 802 803 return (0); 804 } 805 806 /* 807 * Use this to set NTLM auth. info (hashes) 808 * when we don't have the password. 809 */ 810 int 811 smb_ctx_setpwhash(smb_ctx_t *ctx, 812 const uchar_t *nthash, const uchar_t *lmhash) 813 { 814 815 /* Need ct_password to be non-null. */ 816 if (ctx->ct_password[0] == '\0') 817 strlcpy(ctx->ct_password, "$HASH", 818 sizeof (ctx->ct_password)); 819 820 /* 821 * Compute LM hash, NT hash. 822 */ 823 memcpy(ctx->ct_nthash, nthash, NTLM_HASH_SZ); 824 825 /* The LM hash is optional */ 826 if (lmhash) { 827 memcpy(ctx->ct_nthash, nthash, NTLM_HASH_SZ); 828 } 829 830 return (0); 831 } 832 833 int 834 smb_ctx_setshare(struct smb_ctx *ctx, const char *share, int stype) 835 { 836 if (strlen(share) >= SMBIOC_MAX_NAME) { 837 smb_error(dgettext(TEXT_DOMAIN, 838 "share name '%s' too long"), 0, share); 839 return (ENAMETOOLONG); 840 } 841 if (ctx->ct_origshare) 842 free(ctx->ct_origshare); 843 if ((ctx->ct_origshare = strdup(share)) == NULL) 844 return (ENOMEM); 845 846 ctx->ct_shtype_req = stype; 847 848 return (0); 849 } 850 851 int 852 smb_ctx_setsrvaddr(struct smb_ctx *ctx, const char *addr) 853 { 854 if (addr == NULL || addr[0] == 0) 855 return (EINVAL); 856 if (ctx->ct_srvaddr_s) 857 free(ctx->ct_srvaddr_s); 858 if ((ctx->ct_srvaddr_s = strdup(addr)) == NULL) 859 return (ENOMEM); 860 return (0); 861 } 862 863 /* 864 * API for library caller to set signing enabled, required 865 * Note: if not enable, ignore require 866 */ 867 int 868 smb_ctx_setsigning(struct smb_ctx *ctx, int enable, int require) 869 { 870 ctx->ct_vopt &= ~SMBVOPT_SIGNING_MASK; 871 if (enable) { 872 ctx->ct_vopt |= SMBVOPT_SIGNING_ENABLED; 873 if (require) 874 ctx->ct_vopt |= SMBVOPT_SIGNING_REQUIRED; 875 } 876 return (0); 877 } 878 879 static int 880 smb_parse_owner(char *pair, uid_t *uid, gid_t *gid) 881 { 882 struct group gr; 883 struct passwd pw; 884 char buf[NSS_BUFLEN_PASSWD]; 885 char *cp; 886 887 cp = strchr(pair, ':'); 888 if (cp) { 889 *cp++ = '\0'; 890 if (*cp && gid) { 891 if (getgrnam_r(cp, &gr, buf, sizeof (buf)) != NULL) { 892 *gid = gr.gr_gid; 893 } else 894 smb_error(dgettext(TEXT_DOMAIN, 895 "Invalid group name %s, ignored"), 0, cp); 896 } 897 } 898 if (*pair) { 899 if (getpwnam_r(pair, &pw, buf, sizeof (buf)) != NULL) { 900 *uid = pw.pw_uid; 901 } else 902 smb_error(dgettext(TEXT_DOMAIN, 903 "Invalid user name %s, ignored"), 0, pair); 904 } 905 906 return (0); 907 } 908 909 /* 910 * Commands use this with getopt. See: 911 * STDPARAM_OPT, STDPARAM_ARGS 912 * Called after smb_ctx_readrc(). 913 */ 914 int 915 smb_ctx_opt(struct smb_ctx *ctx, int opt, const char *arg) 916 { 917 int error = 0; 918 char *p, *cp; 919 char tmp[1024]; 920 921 switch (opt) { 922 case 'A': 923 case 'U': 924 /* Handled in smb_ctx_init() */ 925 break; 926 case 'I': 927 error = smb_ctx_setsrvaddr(ctx, arg); 928 break; 929 case 'M': 930 /* share connect rights - ignored */ 931 ctx->ct_flags |= SMBCF_SRIGHTS; 932 break; 933 case 'N': 934 ctx->ct_flags |= SMBCF_NOPWD; 935 break; 936 case 'O': 937 p = strdup(arg); 938 cp = strchr(p, '/'); 939 if (cp) 940 *cp = '\0'; 941 error = smb_parse_owner(cp, &ctx->ct_owner, NULL); 942 free(p); 943 break; 944 case 'P': 945 /* ctx->ct_vopt |= SMBCOPT_PERMANENT; */ 946 break; 947 case 'R': 948 /* retry count - ignored */ 949 break; 950 case 'T': 951 /* timeout - ignored */ 952 break; 953 case 'D': /* domain */ 954 case 'W': /* workgroup (legacy alias) */ 955 nls_str_upper(tmp, arg); 956 error = smb_ctx_setdomain(ctx, tmp, TRUE); 957 break; 958 } 959 return (error); 960 } 961 962 963 /* 964 * Original code injected iconv tables into the kernel. 965 * Not sure if we'll need this or not... REVISIT 966 */ 967 #ifdef KICONV_SUPPORT 968 static int 969 smb_addiconvtbl(const char *to, const char *from, const uchar_t *tbl) 970 { 971 int error = 0; 972 973 error = kiconv_add_xlat_table(to, from, tbl); 974 if (error && error != EEXIST) { 975 smb_error(dgettext(TEXT_DOMAIN, 976 "can not setup kernel iconv table (%s:%s)"), 977 error, from, to); 978 return (error); 979 } 980 return (error); 981 } 982 #endif /* KICONV_SUPPORT */ 983 984 /* 985 * Verify context info. before connect operation(s), 986 * lookup specified server and try to fill all forgotten fields. 987 * Legacy name used by commands. 988 */ 989 int 990 smb_ctx_resolve(struct smb_ctx *ctx) 991 { 992 struct smbioc_ossn *ssn = &ctx->ct_ssn; 993 int error = 0; 994 #ifdef KICONV_SUPPORT 995 uchar_t cstbl[256]; 996 uint_t i; 997 #endif 998 999 ctx->ct_flags &= ~SMBCF_RESOLVED; 1000 1001 if (ctx->ct_fullserver == NULL) { 1002 smb_error(dgettext(TEXT_DOMAIN, 1003 "no server name specified"), 0); 1004 return (EINVAL); 1005 } 1006 1007 if (ctx->ct_minlevel >= SMBL_SHARE && 1008 ctx->ct_origshare == NULL) { 1009 smb_error(dgettext(TEXT_DOMAIN, 1010 "no share name specified for %s@%s"), 1011 0, ssn->ssn_user, ctx->ct_fullserver); 1012 return (EINVAL); 1013 } 1014 error = nb_ctx_resolve(ctx->ct_nb); 1015 if (error) 1016 return (error); 1017 #ifdef KICONV_SUPPORT 1018 if (ssn->ioc_localcs[0] == 0) 1019 strcpy(ssn->ioc_localcs, "default"); /* XXX: locale name ? */ 1020 error = smb_addiconvtbl("tolower", ssn->ioc_localcs, nls_lower); 1021 if (error) 1022 return (error); 1023 error = smb_addiconvtbl("toupper", ssn->ioc_localcs, nls_upper); 1024 if (error) 1025 return (error); 1026 if (ssn->ioc_servercs[0] != 0) { 1027 for (i = 0; i < sizeof (cstbl); i++) 1028 cstbl[i] = i; 1029 nls_mem_toext(cstbl, cstbl, sizeof (cstbl)); 1030 error = smb_addiconvtbl(ssn->ioc_servercs, ssn->ioc_localcs, 1031 cstbl); 1032 if (error) 1033 return (error); 1034 for (i = 0; i < sizeof (cstbl); i++) 1035 cstbl[i] = i; 1036 nls_mem_toloc(cstbl, cstbl, sizeof (cstbl)); 1037 error = smb_addiconvtbl(ssn->ioc_localcs, ssn->ioc_servercs, 1038 cstbl); 1039 if (error) 1040 return (error); 1041 } 1042 #endif /* KICONV_SUPPORT */ 1043 1044 /* 1045 * Lookup the IP address and fill in ct_addrinfo. 1046 * 1047 * Note: smb_ctx_getaddr() returns a EAI_xxx 1048 * error value like getaddrinfo(3), but this 1049 * function needs to return an errno value. 1050 */ 1051 error = smb_ctx_getaddr(ctx); 1052 if (error) { 1053 const char *ais = gai_strerror(error); 1054 smb_error(dgettext(TEXT_DOMAIN, 1055 "can't get server address, %s"), 0, ais); 1056 return (ENODATA); 1057 } 1058 assert(ctx->ct_addrinfo != NULL); 1059 1060 /* 1061 * If we have a user name but no password, 1062 * check for a keychain entry. 1063 * XXX: Only for auth NTLM? 1064 */ 1065 if (ctx->ct_user[0] == '\0') { 1066 /* 1067 * No user name (anonymous session). 1068 * The minauth checks do not apply. 1069 */ 1070 ctx->ct_authflags = SMB_AT_ANON; 1071 } else { 1072 /* 1073 * Have a user name. 1074 * If we don't have a p/w yet, 1075 * try the keychain. 1076 */ 1077 if (ctx->ct_password[0] == '\0') 1078 (void) smb_get_keychain(ctx); 1079 /* 1080 * If we're doing p/w based auth, 1081 * that means not using Kerberos. 1082 */ 1083 if (ctx->ct_password[0] != '\0') 1084 ctx->ct_authflags &= ~SMB_AT_KRB5; 1085 /* 1086 * Mask out disallowed auth types. 1087 */ 1088 ctx->ct_authflags &= ctx->ct_minauth; 1089 } 1090 if (ctx->ct_authflags == 0) { 1091 smb_error(dgettext(TEXT_DOMAIN, 1092 "no valid auth. types"), 0); 1093 return (ENOTSUP); 1094 } 1095 1096 ctx->ct_flags |= SMBCF_RESOLVED; 1097 if (smb_debug) 1098 dump_ctx("after smb_ctx_resolve", ctx); 1099 1100 return (0); 1101 } 1102 1103 int 1104 smb_open_driver() 1105 { 1106 int err, fd; 1107 uint32_t version; 1108 1109 fd = open("/dev/"NSMB_NAME, O_RDWR); 1110 if (fd < 0) { 1111 err = errno; 1112 smb_error(dgettext(TEXT_DOMAIN, 1113 "failed to open driver"), err); 1114 return (-1); 1115 } 1116 1117 /* 1118 * Check the driver version (paranoia) 1119 * Do this BEFORE any other ioctl calls. 1120 */ 1121 if (ioctl(fd, SMBIOC_GETVERS, &version) < 0) 1122 version = 0; 1123 if (version != NSMB_VERSION) { 1124 smb_error(dgettext(TEXT_DOMAIN, 1125 "incorrect driver version"), 0); 1126 close(fd); 1127 return (-1); 1128 } 1129 1130 /* This handle controls per-process resources. */ 1131 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 1132 1133 return (fd); 1134 } 1135 1136 int 1137 smb_ctx_gethandle(struct smb_ctx *ctx) 1138 { 1139 int fd; 1140 1141 if (ctx->ct_dev_fd != -1) { 1142 rpc_cleanup_smbctx(ctx); 1143 close(ctx->ct_dev_fd); 1144 ctx->ct_dev_fd = -1; 1145 ctx->ct_flags &= ~SMBCF_SSNACTIVE; 1146 } 1147 1148 fd = smb_open_driver(); 1149 if (fd < 0) 1150 return (ENODEV); 1151 1152 ctx->ct_dev_fd = fd; 1153 return (0); 1154 } 1155 1156 1157 /* 1158 * Find or create a connection + logon session 1159 */ 1160 int 1161 smb_ctx_get_ssn(struct smb_ctx *ctx) 1162 { 1163 int err = 0; 1164 1165 if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) 1166 return (EINVAL); 1167 1168 if (ctx->ct_dev_fd < 0) { 1169 if ((err = smb_ctx_gethandle(ctx))) 1170 return (err); 1171 } 1172 1173 /* 1174 * Check whether the driver already has a VC 1175 * we can use. If so, we're done! 1176 */ 1177 err = smb_ctx_findvc(ctx); 1178 if (err == 0) { 1179 DPRINT("found an existing VC"); 1180 } else { 1181 /* 1182 * This calls the IOD to create a new session. 1183 */ 1184 DPRINT("setup a new VC"); 1185 err = smb_ctx_newvc(ctx); 1186 if (err != 0) 1187 return (err); 1188 1189 /* 1190 * Call findvc again. The new VC sould be 1191 * found in the driver this time. 1192 */ 1193 err = smb_ctx_findvc(ctx); 1194 } 1195 1196 return (err); 1197 } 1198 1199 /* 1200 * Get the string representation of a share "use" type, 1201 * as needed for the "service" in tree connect. 1202 */ 1203 static const char * 1204 smb_use_type_str(smb_use_shtype_t stype) 1205 { 1206 const char *pp; 1207 1208 switch (stype) { 1209 default: 1210 case USE_WILDCARD: 1211 pp = "?????"; 1212 break; 1213 case USE_DISKDEV: 1214 pp = "A:"; 1215 break; 1216 case USE_SPOOLDEV: 1217 pp = "LPT1:"; 1218 break; 1219 case USE_CHARDEV: 1220 pp = "COMM"; 1221 break; 1222 case USE_IPC: 1223 pp = "IPC"; 1224 break; 1225 } 1226 return (pp); 1227 } 1228 1229 /* 1230 * Find or create a tree connection 1231 */ 1232 int 1233 smb_ctx_get_tree(struct smb_ctx *ctx) 1234 { 1235 smbioc_tcon_t *tcon = NULL; 1236 const char *stype; 1237 int cmd, err = 0; 1238 1239 if (ctx->ct_dev_fd < 0 || 1240 ctx->ct_origshare == NULL) { 1241 return (EINVAL); 1242 } 1243 1244 cmd = SMBIOC_TREE_CONNECT; 1245 tcon = malloc(sizeof (*tcon)); 1246 if (tcon == NULL) 1247 return (ENOMEM); 1248 bzero(tcon, sizeof (*tcon)); 1249 tcon->tc_flags = SMBLK_CREATE; 1250 tcon->tc_opt = 0; 1251 1252 /* The share name */ 1253 strlcpy(tcon->tc_sh.sh_name, ctx->ct_origshare, 1254 sizeof (tcon->tc_sh.sh_name)); 1255 1256 /* The share "use" type. */ 1257 stype = smb_use_type_str(ctx->ct_shtype_req); 1258 strlcpy(tcon->tc_sh.sh_type_req, stype, 1259 sizeof (tcon->tc_sh.sh_type_req)); 1260 1261 /* 1262 * Todo: share passwords for share-level security. 1263 * 1264 * The driver does the actual TCON call. 1265 */ 1266 if (ioctl(ctx->ct_dev_fd, cmd, tcon) == -1) { 1267 err = errno; 1268 goto out; 1269 } 1270 1271 /* 1272 * Check the returned share type 1273 */ 1274 DPRINT("ret. sh_type: \"%s\"", tcon->tc_sh.sh_type_ret); 1275 if (ctx->ct_shtype_req != USE_WILDCARD && 1276 0 != strcmp(stype, tcon->tc_sh.sh_type_ret)) { 1277 smb_error(dgettext(TEXT_DOMAIN, 1278 "%s: incompatible share type"), 1279 0, ctx->ct_origshare); 1280 err = EINVAL; 1281 } 1282 1283 out: 1284 if (tcon != NULL) 1285 free(tcon); 1286 1287 return (err); 1288 } 1289 1290 /* 1291 * Return the hflags2 word for an smb_ctx. 1292 */ 1293 int 1294 smb_ctx_flags2(struct smb_ctx *ctx) 1295 { 1296 uint16_t flags2; 1297 1298 if (ioctl(ctx->ct_dev_fd, SMBIOC_FLAGS2, &flags2) == -1) { 1299 smb_error(dgettext(TEXT_DOMAIN, 1300 "can't get flags2 for a session"), errno); 1301 return (-1); 1302 } 1303 return (flags2); 1304 } 1305 1306 /* 1307 * Get the transport level session key. 1308 * Must already have an active SMB session. 1309 */ 1310 int 1311 smb_ctx_get_ssnkey(struct smb_ctx *ctx, uchar_t *key, size_t len) 1312 { 1313 if (len < SMBIOC_HASH_SZ) 1314 return (EINVAL); 1315 1316 if (ioctl(ctx->ct_dev_fd, SMBIOC_GETSSNKEY, key) == -1) 1317 return (errno); 1318 1319 return (0); 1320 } 1321 1322 1323 /* 1324 * RC file parsing stuff 1325 */ 1326 1327 struct nv { 1328 char *name; 1329 int value; 1330 } minauth_table[] = { 1331 /* Allowed auth. types */ 1332 { "kerberos", SMB_AT_KRB5 }, 1333 { "ntlmv2", SMB_AT_KRB5|SMB_AT_NTLM2 }, 1334 { "ntlm", SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1 }, 1335 { "lm", SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1|SMB_AT_LM1 }, 1336 { "none", SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1|SMB_AT_LM1| 1337 SMB_AT_ANON }, 1338 { NULL } 1339 }; 1340 1341 1342 /* 1343 * level values: 1344 * 0 - default 1345 * 1 - server 1346 * 2 - server:user 1347 * 3 - server:user:share 1348 */ 1349 static int 1350 smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level) 1351 { 1352 char *p; 1353 int error; 1354 1355 #ifdef KICONV_SUPPORT 1356 if (level > 0) { 1357 rc_getstringptr(smb_rc, sname, "charsets", &p); 1358 if (p) { 1359 error = smb_ctx_setcharset(ctx, p); 1360 if (error) 1361 smb_error(dgettext(TEXT_DOMAIN, 1362 "charset specification in the section '%s' ignored"), 1363 error, sname); 1364 } 1365 } 1366 #endif 1367 1368 if (level <= 1) { 1369 /* Section is: [default] or [server] */ 1370 1371 rc_getstringptr(smb_rc, sname, "minauth", &p); 1372 if (p) { 1373 /* 1374 * "minauth" was set in this section; override 1375 * the current minimum authentication setting. 1376 */ 1377 struct nv *nvp; 1378 for (nvp = minauth_table; nvp->name; nvp++) 1379 if (strcmp(p, nvp->name) == 0) 1380 break; 1381 if (nvp->name) 1382 ctx->ct_minauth = nvp->value; 1383 else { 1384 /* 1385 * Unknown minimum authentication level. 1386 */ 1387 smb_error(dgettext(TEXT_DOMAIN, 1388 "invalid minimum authentication level \"%s\" specified in the section %s"), 1389 0, p, sname); 1390 return (EINVAL); 1391 } 1392 } 1393 1394 rc_getstringptr(smb_rc, sname, "signing", &p); 1395 if (p) { 1396 /* 1397 * "signing" was set in this section; override 1398 * the current signing settings. Note: 1399 * setsigning flags are: enable, require 1400 */ 1401 if (strcmp(p, "disabled") == 0) { 1402 (void) smb_ctx_setsigning(ctx, FALSE, FALSE); 1403 } else if (strcmp(p, "enabled") == 0) { 1404 (void) smb_ctx_setsigning(ctx, TRUE, FALSE); 1405 } else if (strcmp(p, "required") == 0) { 1406 (void) smb_ctx_setsigning(ctx, TRUE, TRUE); 1407 } else { 1408 /* 1409 * Unknown "signing" value. 1410 */ 1411 smb_error(dgettext(TEXT_DOMAIN, 1412 "invalid signing policy \"%s\" specified in the section %s"), 1413 0, p, sname); 1414 return (EINVAL); 1415 } 1416 } 1417 1418 /* 1419 * Domain name. Allow both keywords: 1420 * "workgroup", "domain" 1421 * 1422 * Note: these are NOT marked "from CMD". 1423 * See long comment at smb_ctx_init() 1424 */ 1425 rc_getstringptr(smb_rc, sname, "workgroup", &p); 1426 if (p) { 1427 nls_str_upper(p, p); 1428 error = smb_ctx_setdomain(ctx, p, 0); 1429 if (error) 1430 smb_error(dgettext(TEXT_DOMAIN, 1431 "workgroup specification in the " 1432 "section '%s' ignored"), error, sname); 1433 } 1434 rc_getstringptr(smb_rc, sname, "domain", &p); 1435 if (p) { 1436 nls_str_upper(p, p); 1437 error = smb_ctx_setdomain(ctx, p, 0); 1438 if (error) 1439 smb_error(dgettext(TEXT_DOMAIN, 1440 "domain specification in the " 1441 "section '%s' ignored"), error, sname); 1442 } 1443 1444 rc_getstringptr(smb_rc, sname, "user", &p); 1445 if (p) { 1446 error = smb_ctx_setuser(ctx, p, 0); 1447 if (error) 1448 smb_error(dgettext(TEXT_DOMAIN, 1449 "user specification in the " 1450 "section '%s' ignored"), error, sname); 1451 } 1452 } 1453 1454 if (level == 1) { 1455 /* Section is: [server] */ 1456 rc_getstringptr(smb_rc, sname, "addr", &p); 1457 if (p) { 1458 error = smb_ctx_setsrvaddr(ctx, p); 1459 if (error) { 1460 smb_error(dgettext(TEXT_DOMAIN, 1461 "invalid address specified in section %s"), 1462 0, sname); 1463 return (error); 1464 } 1465 } 1466 } 1467 1468 rc_getstringptr(smb_rc, sname, "password", &p); 1469 if (p) { 1470 error = smb_ctx_setpassword(ctx, p, 0); 1471 if (error) 1472 smb_error(dgettext(TEXT_DOMAIN, 1473 "password specification in the section '%s' ignored"), 1474 error, sname); 1475 } 1476 1477 return (0); 1478 } 1479 1480 /* 1481 * read rc file as follows: 1482 * 0: read [default] section 1483 * 1: override with [server] section 1484 * 2: override with [server:user] section 1485 * 3: override with [server:user:share] section 1486 * Since absence of rcfile is not fatal, silently ignore this fact. 1487 * smb_rc file should be closed by caller. 1488 */ 1489 int 1490 smb_ctx_readrc(struct smb_ctx *ctx) 1491 { 1492 char *home; 1493 char *sname = NULL; 1494 int sname_max; 1495 int err = 0; 1496 1497 if ((home = getenv("HOME")) == NULL) 1498 home = ctx->ct_home; 1499 if ((err = smb_open_rcfile(home)) != 0) { 1500 DPRINT("smb_open_rcfile, err=%d", err); 1501 /* ignore any error here */ 1502 return (0); 1503 } 1504 1505 sname_max = 3 * SMBIOC_MAX_NAME + 4; 1506 sname = malloc(sname_max); 1507 if (sname == NULL) { 1508 err = ENOMEM; 1509 goto done; 1510 } 1511 1512 /* 1513 * default parameters (level=0) 1514 */ 1515 smb_ctx_readrcsection(ctx, "default", 0); 1516 nb_ctx_readrcsection(smb_rc, ctx->ct_nb, "default", 0); 1517 1518 /* 1519 * If we don't have a server name, we can't read any of the 1520 * [server...] sections. 1521 */ 1522 if (ctx->ct_fullserver == NULL) 1523 goto done; 1524 /* 1525 * SERVER parameters. 1526 */ 1527 smb_ctx_readrcsection(ctx, ctx->ct_fullserver, 1); 1528 1529 /* 1530 * If we don't have a user name, we can't read any of the 1531 * [server:user...] sections. 1532 */ 1533 if (ctx->ct_user[0] == 0) 1534 goto done; 1535 /* 1536 * SERVER:USER parameters 1537 */ 1538 snprintf(sname, sname_max, "%s:%s", 1539 ctx->ct_fullserver, 1540 ctx->ct_user); 1541 smb_ctx_readrcsection(ctx, sname, 2); 1542 1543 1544 /* 1545 * If we don't have a share name, we can't read any of the 1546 * [server:user:share] sections. 1547 */ 1548 if (ctx->ct_origshare == NULL) 1549 goto done; 1550 /* 1551 * SERVER:USER:SHARE parameters 1552 */ 1553 snprintf(sname, sname_max, "%s:%s:%s", 1554 ctx->ct_fullserver, 1555 ctx->ct_user, 1556 ctx->ct_origshare); 1557 smb_ctx_readrcsection(ctx, sname, 3); 1558 1559 done: 1560 if (sname) 1561 free(sname); 1562 smb_close_rcfile(); 1563 if (smb_debug) 1564 dump_ctx("after smb_ctx_readrc", ctx); 1565 if (err) 1566 DPRINT("err=%d\n", err); 1567 1568 return (err); 1569 } 1570