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.22 2001/12/26 04:10:52 bp Exp $ 33 */ 34 #include <sys/param.h> 35 #include <sys/sysctl.h> 36 #include <sys/ioctl.h> 37 #include <sys/time.h> 38 #include <sys/mount.h> 39 #include <fcntl.h> 40 #include <ctype.h> 41 #include <errno.h> 42 #include <stdio.h> 43 #include <string.h> 44 #include <stdlib.h> 45 #include <pwd.h> 46 #include <grp.h> 47 #include <unistd.h> 48 #include <sys/iconv.h> 49 50 #define NB_NEEDRESOLVER 51 52 #include <netsmb/smb_lib.h> 53 #include <netsmb/netbios.h> 54 #include <netsmb/nb_lib.h> 55 #include <netsmb/smb_conn.h> 56 #include <cflib.h> 57 58 /* 59 * Prescan command line for [-U user] argument 60 * and fill context with defaults 61 */ 62 int 63 smb_ctx_init(struct smb_ctx *ctx, int argc, char *argv[], 64 int minlevel, int maxlevel, int sharetype) 65 { 66 int opt, error = 0; 67 const char *arg, *cp; 68 69 bzero(ctx,sizeof(*ctx)); 70 error = nb_ctx_create(&ctx->ct_nb); 71 if (error) 72 return error; 73 ctx->ct_fd = -1; 74 ctx->ct_parsedlevel = SMBL_NONE; 75 ctx->ct_minlevel = minlevel; 76 ctx->ct_maxlevel = maxlevel; 77 78 ctx->ct_ssn.ioc_opt = SMBVOPT_CREATE; 79 ctx->ct_ssn.ioc_timeout = 15; 80 ctx->ct_ssn.ioc_retrycount = 4; 81 ctx->ct_ssn.ioc_owner = SMBM_ANY_OWNER; 82 ctx->ct_ssn.ioc_group = SMBM_ANY_GROUP; 83 ctx->ct_ssn.ioc_mode = SMBM_EXEC; 84 ctx->ct_ssn.ioc_rights = SMBM_DEFAULT; 85 86 ctx->ct_sh.ioc_opt = SMBVOPT_CREATE; 87 ctx->ct_sh.ioc_owner = SMBM_ANY_OWNER; 88 ctx->ct_sh.ioc_group = SMBM_ANY_GROUP; 89 ctx->ct_sh.ioc_mode = SMBM_EXEC; 90 ctx->ct_sh.ioc_rights = SMBM_DEFAULT; 91 ctx->ct_sh.ioc_owner = SMBM_ANY_OWNER; 92 ctx->ct_sh.ioc_group = SMBM_ANY_GROUP; 93 94 nb_ctx_setscope(ctx->ct_nb, ""); 95 smb_ctx_setuser(ctx, getpwuid(geteuid())->pw_name); 96 endpwent(); 97 if (argv == NULL) 98 return 0; 99 for (opt = 1; opt < argc; opt++) { 100 cp = argv[opt]; 101 if (strncmp(cp, "//", 2) != 0) 102 continue; 103 error = smb_ctx_parseunc(ctx, cp, sharetype, (const char**)&cp); 104 if (error) 105 return error; 106 ctx->ct_uncnext = cp; 107 break; 108 } 109 while (error == 0 && (opt = cf_getopt(argc, argv, ":E:L:U:")) != -1) { 110 arg = cf_optarg; 111 switch (opt) { 112 case 'E': 113 error = smb_ctx_setcharset(ctx, arg); 114 if (error) 115 return error; 116 break; 117 case 'L': 118 error = nls_setlocale(optarg); 119 if (error) 120 break; 121 break; 122 case 'U': 123 error = smb_ctx_setuser(ctx, arg); 124 break; 125 } 126 } 127 cf_optind = cf_optreset = 1; 128 return error; 129 } 130 131 void 132 smb_ctx_done(struct smb_ctx *ctx) 133 { 134 if (ctx->ct_ssn.ioc_server) 135 nb_snbfree(ctx->ct_ssn.ioc_server); 136 if (ctx->ct_ssn.ioc_local) 137 nb_snbfree(ctx->ct_ssn.ioc_local); 138 if (ctx->ct_srvaddr) 139 free(ctx->ct_srvaddr); 140 if (ctx->ct_nb) 141 nb_ctx_done(ctx->ct_nb); 142 } 143 144 static int 145 getsubstring(const char *p, u_char sep, char *dest, int maxlen, const char **next) 146 { 147 int len; 148 149 maxlen--; 150 for (len = 0; len < maxlen && *p != sep; p++, len++, dest++) { 151 if (*p == 0) 152 return EINVAL; 153 *dest = *p; 154 } 155 *dest = 0; 156 *next = *p ? p + 1 : p; 157 return 0; 158 } 159 160 /* 161 * Here we expect something like "[proto:]//[user@]host[/share][/path]" 162 */ 163 int 164 smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc, int sharetype, 165 const char **next) 166 { 167 const char *p = unc; 168 char *p1; 169 char tmp[1024]; 170 int error ; 171 172 ctx->ct_parsedlevel = SMBL_NONE; 173 if (*p++ != '/' || *p++ != '/') { 174 smb_error("UNC should start with '//'", 0); 175 return EINVAL; 176 } 177 p1 = tmp; 178 error = getsubstring(p, '@', p1, sizeof(tmp), &p); 179 if (!error) { 180 if (ctx->ct_maxlevel < SMBL_VC) { 181 smb_error("no user name required", 0); 182 return EINVAL; 183 } 184 if (*p1 == 0) { 185 smb_error("empty user name", 0); 186 return EINVAL; 187 } 188 error = smb_ctx_setuser(ctx, tmp); 189 if (error) 190 return error; 191 ctx->ct_parsedlevel = SMBL_VC; 192 } 193 error = getsubstring(p, '/', p1, sizeof(tmp), &p); 194 if (error) { 195 error = getsubstring(p, '\0', p1, sizeof(tmp), &p); 196 if (error) { 197 smb_error("no server name found", 0); 198 return error; 199 } 200 } 201 if (*p1 == 0) { 202 smb_error("empty server name", 0); 203 return EINVAL; 204 } 205 error = smb_ctx_setserver(ctx, tmp); 206 if (error) 207 return error; 208 if (sharetype == SMB_ST_NONE) { 209 *next = p; 210 return 0; 211 } 212 if (*p != 0 && ctx->ct_maxlevel < SMBL_SHARE) { 213 smb_error("no share name required", 0); 214 return EINVAL; 215 } 216 error = getsubstring(p, '/', p1, sizeof(tmp), &p); 217 if (error) { 218 error = getsubstring(p, '\0', p1, sizeof(tmp), &p); 219 if (error) { 220 smb_error("unexpected end of line", 0); 221 return error; 222 } 223 } 224 if (*p1 == 0 && ctx->ct_minlevel >= SMBL_SHARE) { 225 smb_error("empty share name", 0); 226 return EINVAL; 227 } 228 *next = p; 229 if (*p1 == 0) 230 return 0; 231 error = smb_ctx_setshare(ctx, p1, sharetype); 232 return error; 233 } 234 235 int 236 smb_ctx_setcharset(struct smb_ctx *ctx, const char *arg) 237 { 238 char *cp, *servercs, *localcs; 239 int cslen = sizeof(ctx->ct_ssn.ioc_localcs); 240 int scslen, lcslen, error; 241 242 cp = strchr(arg, ':'); 243 lcslen = cp ? (cp - arg) : 0; 244 if (lcslen == 0 || lcslen >= cslen) { 245 smb_error("invalid local charset specification (%s)", 0, arg); 246 return EINVAL; 247 } 248 scslen = (size_t)strlen(++cp); 249 if (scslen == 0 || scslen >= cslen) { 250 smb_error("invalid server charset specification (%s)", 0, arg); 251 return EINVAL; 252 } 253 localcs = memcpy(ctx->ct_ssn.ioc_localcs, arg, lcslen); 254 localcs[lcslen] = 0; 255 servercs = strcpy(ctx->ct_ssn.ioc_servercs, cp); 256 error = nls_setrecode(localcs, servercs); 257 if (error == 0) 258 return 0; 259 smb_error("can't initialize iconv support (%s:%s)", 260 error, localcs, servercs); 261 localcs[0] = 0; 262 servercs[0] = 0; 263 return error; 264 } 265 266 int 267 smb_ctx_setserver(struct smb_ctx *ctx, const char *name) 268 { 269 if (strlen(name) >= SMB_MAXSRVNAMELEN) { 270 smb_error("server name '%s' too long", 0, name); 271 return ENAMETOOLONG; 272 } 273 nls_str_upper(ctx->ct_ssn.ioc_srvname, name); 274 return 0; 275 } 276 277 int 278 smb_ctx_setuser(struct smb_ctx *ctx, const char *name) 279 { 280 if (strlen(name) >= SMB_MAXUSERNAMELEN) { 281 smb_error("user name '%s' too long", 0, name); 282 return ENAMETOOLONG; 283 } 284 nls_str_upper(ctx->ct_ssn.ioc_user, name); 285 return 0; 286 } 287 288 int 289 smb_ctx_setworkgroup(struct smb_ctx *ctx, const char *name) 290 { 291 if (strlen(name) >= SMB_MAXUSERNAMELEN) { 292 smb_error("workgroup name '%s' too long", 0, name); 293 return ENAMETOOLONG; 294 } 295 nls_str_upper(ctx->ct_ssn.ioc_workgroup, name); 296 return 0; 297 } 298 299 int 300 smb_ctx_setpassword(struct smb_ctx *ctx, const char *passwd) 301 { 302 if (passwd == NULL) 303 return EINVAL; 304 if (strlen(passwd) >= SMB_MAXPASSWORDLEN) { 305 smb_error("password too long", 0); 306 return ENAMETOOLONG; 307 } 308 if (strncmp(passwd, "$$1", 3) == 0) 309 smb_simpledecrypt(ctx->ct_ssn.ioc_password, passwd); 310 else 311 strcpy(ctx->ct_ssn.ioc_password, passwd); 312 strcpy(ctx->ct_sh.ioc_password, ctx->ct_ssn.ioc_password); 313 return 0; 314 } 315 316 int 317 smb_ctx_setshare(struct smb_ctx *ctx, const char *share, int stype) 318 { 319 if (strlen(share) >= SMB_MAXSHARENAMELEN) { 320 smb_error("share name '%s' too long", 0, share); 321 return ENAMETOOLONG; 322 } 323 nls_str_upper(ctx->ct_sh.ioc_share, share); 324 if (share[0] != 0) 325 ctx->ct_parsedlevel = SMBL_SHARE; 326 ctx->ct_sh.ioc_stype = stype; 327 return 0; 328 } 329 330 int 331 smb_ctx_setsrvaddr(struct smb_ctx *ctx, const char *addr) 332 { 333 if (addr == NULL || addr[0] == 0) 334 return EINVAL; 335 if (ctx->ct_srvaddr) 336 free(ctx->ct_srvaddr); 337 if ((ctx->ct_srvaddr = strdup(addr)) == NULL) 338 return ENOMEM; 339 return 0; 340 } 341 342 static int 343 smb_parse_owner(char *pair, uid_t *uid, gid_t *gid) 344 { 345 struct group *gr; 346 struct passwd *pw; 347 char *cp; 348 349 cp = strchr(pair, ':'); 350 if (cp) { 351 *cp++ = '\0'; 352 if (*cp) { 353 gr = getgrnam(cp); 354 if (gr) { 355 *gid = gr->gr_gid; 356 } else 357 smb_error("Invalid group name %s, ignored", 358 0, cp); 359 } 360 } 361 if (*pair) { 362 pw = getpwnam(pair); 363 if (pw) { 364 *uid = pw->pw_uid; 365 } else 366 smb_error("Invalid user name %s, ignored", 0, pair); 367 } 368 endpwent(); 369 return 0; 370 } 371 372 int 373 smb_ctx_opt(struct smb_ctx *ctx, int opt, const char *arg) 374 { 375 int error = 0; 376 char *p, *cp; 377 378 switch(opt) { 379 case 'U': 380 break; 381 case 'I': 382 error = smb_ctx_setsrvaddr(ctx, arg); 383 break; 384 case 'M': 385 ctx->ct_ssn.ioc_rights = strtol(arg, &cp, 8); 386 if (*cp == '/') { 387 ctx->ct_sh.ioc_rights = strtol(cp + 1, &cp, 8); 388 ctx->ct_flags |= SMBCF_SRIGHTS; 389 } 390 break; 391 case 'N': 392 ctx->ct_flags |= SMBCF_NOPWD; 393 break; 394 case 'O': 395 p = strdup(arg); 396 cp = strchr(p, '/'); 397 if (cp) { 398 *cp++ = '\0'; 399 error = smb_parse_owner(cp, &ctx->ct_sh.ioc_owner, 400 &ctx->ct_sh.ioc_group); 401 } 402 if (*p && error == 0) { 403 error = smb_parse_owner(cp, &ctx->ct_ssn.ioc_owner, 404 &ctx->ct_ssn.ioc_group); 405 } 406 free(p); 407 break; 408 case 'P': 409 /* ctx->ct_ssn.ioc_opt |= SMBCOPT_PERMANENT;*/ 410 break; 411 case 'R': 412 ctx->ct_ssn.ioc_retrycount = atoi(arg); 413 break; 414 case 'T': 415 ctx->ct_ssn.ioc_timeout = atoi(arg); 416 break; 417 case 'W': 418 error = smb_ctx_setworkgroup(ctx, arg); 419 break; 420 } 421 return error; 422 } 423 424 #if 0 425 static void 426 smb_hexdump(const u_char *buf, int len) { 427 int ofs = 0; 428 429 while (len--) { 430 if (ofs % 16 == 0) 431 printf("\n%02X: ", ofs); 432 printf("%02x ", *buf++); 433 ofs++; 434 } 435 printf("\n"); 436 } 437 #endif 438 439 440 static int 441 smb_addiconvtbl(const char *to, const char *from, const u_char *tbl) 442 { 443 int error; 444 445 error = kiconv_add_xlat_table(to, from, tbl); 446 if (error && error != EEXIST) { 447 smb_error("can not setup kernel iconv table (%s:%s)", error, 448 from, to); 449 return error; 450 } 451 return 0; 452 } 453 454 /* 455 * Verify context before connect operation(s), 456 * lookup specified server and try to fill all forgotten fields. 457 */ 458 int 459 smb_ctx_resolve(struct smb_ctx *ctx) 460 { 461 struct smbioc_ossn *ssn = &ctx->ct_ssn; 462 struct smbioc_oshare *sh = &ctx->ct_sh; 463 struct nb_name nn; 464 struct sockaddr *sap; 465 struct sockaddr_nb *salocal, *saserver; 466 char *cp; 467 u_char cstbl[256]; 468 u_int i; 469 int error = 0; 470 471 ctx->ct_flags &= ~SMBCF_RESOLVED; 472 if (ssn->ioc_srvname[0] == 0) { 473 smb_error("no server name specified", 0); 474 return EINVAL; 475 } 476 if (ssn->ioc_user[0] == 0) { 477 smb_error("no user name specified for server %s", 478 0, ssn->ioc_srvname); 479 return EINVAL; 480 } 481 if (ctx->ct_minlevel >= SMBL_SHARE && sh->ioc_share[0] == 0) { 482 smb_error("no share name specified for %s@%s", 483 0, ssn->ioc_user, ssn->ioc_srvname); 484 return EINVAL; 485 } 486 error = nb_ctx_resolve(ctx->ct_nb); 487 if (error) 488 return error; 489 if (ssn->ioc_localcs[0] == 0) 490 strcpy(ssn->ioc_localcs, "default"); /* XXX: locale name ? */ 491 error = smb_addiconvtbl("tolower", ssn->ioc_localcs, nls_lower); 492 if (error) 493 return error; 494 error = smb_addiconvtbl("toupper", ssn->ioc_localcs, nls_upper); 495 if (error) 496 return error; 497 if (ssn->ioc_servercs[0] != 0) { 498 for(i = 0; i < sizeof(cstbl); i++) 499 cstbl[i] = i; 500 nls_mem_toext(cstbl, cstbl, sizeof(cstbl)); 501 error = smb_addiconvtbl(ssn->ioc_servercs, ssn->ioc_localcs, cstbl); 502 if (error) 503 return error; 504 for(i = 0; i < sizeof(cstbl); i++) 505 cstbl[i] = i; 506 nls_mem_toloc(cstbl, cstbl, sizeof(cstbl)); 507 error = smb_addiconvtbl(ssn->ioc_localcs, ssn->ioc_servercs, cstbl); 508 if (error) 509 return error; 510 } 511 if (ctx->ct_srvaddr) { 512 error = nb_resolvehost_in(ctx->ct_srvaddr, &sap); 513 } else { 514 error = nbns_resolvename(ssn->ioc_srvname, ctx->ct_nb, &sap); 515 } 516 if (error) { 517 smb_error("can't get server address", error); 518 return error; 519 } 520 nn.nn_scope = ctx->ct_nb->nb_scope; 521 nn.nn_type = NBT_SERVER; 522 strcpy(nn.nn_name, ssn->ioc_srvname); 523 error = nb_sockaddr(sap, &nn, &saserver); 524 nb_snbfree(sap); 525 if (error) { 526 smb_error("can't allocate server address", error); 527 return error; 528 } 529 ssn->ioc_server = (struct sockaddr*)saserver; 530 if (ctx->ct_locname[0] == 0) { 531 error = nb_getlocalname(ctx->ct_locname); 532 if (error) { 533 smb_error("can't get local name", error); 534 return error; 535 } 536 nls_str_upper(ctx->ct_locname, ctx->ct_locname); 537 } 538 strcpy(nn.nn_name, ctx->ct_locname); 539 nn.nn_type = NBT_WKSTA; 540 nn.nn_scope = ctx->ct_nb->nb_scope; 541 error = nb_sockaddr(NULL, &nn, &salocal); 542 if (error) { 543 nb_snbfree((struct sockaddr*)saserver); 544 smb_error("can't allocate local address", error); 545 return error; 546 } 547 ssn->ioc_local = (struct sockaddr*)salocal; 548 ssn->ioc_lolen = salocal->snb_len; 549 ssn->ioc_svlen = saserver->snb_len; 550 if (ssn->ioc_password[0] == 0 && (ctx->ct_flags & SMBCF_NOPWD) == 0) { 551 cp = getpass("Password:"); 552 error = smb_ctx_setpassword(ctx, cp); 553 if (error) 554 return error; 555 } 556 ctx->ct_flags |= SMBCF_RESOLVED; 557 return 0; 558 } 559 560 static int 561 smb_ctx_gethandle(struct smb_ctx *ctx) 562 { 563 int fd, i; 564 char buf[20]; 565 566 /* 567 * First try to open as clone 568 */ 569 fd = open("/dev/"NSMB_NAME, O_RDWR); 570 if (fd >= 0) { 571 ctx->ct_fd = fd; 572 return 0; 573 } 574 /* 575 * well, no clone capabilities available - we have to scan 576 * all devices in order to get free one 577 */ 578 for (i = 0; i < 1024; i++) { 579 snprintf(buf, sizeof(buf), "/dev/%s%d", NSMB_NAME, i); 580 fd = open(buf, O_RDWR); 581 if (fd >= 0) { 582 ctx->ct_fd = fd; 583 return 0; 584 } 585 } 586 /* 587 * This is a compatibility with old /dev/net/nsmb device 588 */ 589 for (i = 0; i < 1024; i++) { 590 snprintf(buf, sizeof(buf), "/dev/net/%s%d", NSMB_NAME, i); 591 fd = open(buf, O_RDWR); 592 if (fd >= 0) { 593 ctx->ct_fd = fd; 594 return 0; 595 } 596 if (errno == ENOENT) 597 return ENOENT; 598 } 599 return ENOENT; 600 } 601 602 int 603 smb_ctx_lookup(struct smb_ctx *ctx, int level, int flags) 604 { 605 struct smbioc_lookup rq; 606 int error; 607 608 if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) { 609 smb_error("smb_ctx_lookup() data is not resolved", 0); 610 return EINVAL; 611 } 612 if (ctx->ct_fd != -1) { 613 close(ctx->ct_fd); 614 ctx->ct_fd = -1; 615 } 616 error = smb_ctx_gethandle(ctx); 617 if (error) { 618 smb_error("can't get handle to requester (no /dev/"NSMB_NAME"* device)", 0); 619 return EINVAL; 620 } 621 bzero(&rq, sizeof(rq)); 622 bcopy(&ctx->ct_ssn, &rq.ioc_ssn, sizeof(struct smbioc_ossn)); 623 bcopy(&ctx->ct_sh, &rq.ioc_sh, sizeof(struct smbioc_oshare)); 624 rq.ioc_flags = flags; 625 rq.ioc_level = level; 626 if (ioctl(ctx->ct_fd, SMBIOC_LOOKUP, &rq) == -1) { 627 error = errno; 628 if (flags & SMBLK_CREATE) 629 smb_error("unable to open connection", error); 630 return error; 631 } 632 return 0; 633 } 634 635 int 636 smb_ctx_login(struct smb_ctx *ctx) 637 { 638 struct smbioc_ossn *ssn = &ctx->ct_ssn; 639 struct smbioc_oshare *sh = &ctx->ct_sh; 640 int error; 641 642 if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) { 643 smb_error("smb_ctx_resolve() should be called first", 0); 644 return EINVAL; 645 } 646 if (ctx->ct_fd != -1) { 647 close(ctx->ct_fd); 648 ctx->ct_fd = -1; 649 } 650 error = smb_ctx_gethandle(ctx); 651 if (error) { 652 smb_error("can't get handle to requester", 0); 653 return EINVAL; 654 } 655 if (ioctl(ctx->ct_fd, SMBIOC_OPENSESSION, ssn) == -1) { 656 error = errno; 657 smb_error("can't open session to server %s", error, ssn->ioc_srvname); 658 return error; 659 } 660 if (sh->ioc_share[0] == 0) 661 return 0; 662 if (ioctl(ctx->ct_fd, SMBIOC_OPENSHARE, sh) == -1) { 663 error = errno; 664 smb_error("can't connect to share //%s/%s", error, 665 ssn->ioc_srvname, sh->ioc_share); 666 return error; 667 } 668 return 0; 669 } 670 671 int 672 smb_ctx_setflags(struct smb_ctx *ctx, int level, int mask, int flags) 673 { 674 struct smbioc_flags fl; 675 676 if (ctx->ct_fd == -1) 677 return EINVAL; 678 fl.ioc_level = level; 679 fl.ioc_mask = mask; 680 fl.ioc_flags = flags; 681 if (ioctl(ctx->ct_fd, SMBIOC_SETFLAGS, &fl) == -1) 682 return errno; 683 return 0; 684 } 685 686 /* 687 * level values: 688 * 0 - default 689 * 1 - server 690 * 2 - server:user 691 * 3 - server:user:share 692 */ 693 static int 694 smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level) 695 { 696 char *p; 697 int error; 698 699 if (level >= 0) { 700 rc_getstringptr(smb_rc, sname, "charsets", &p); 701 if (p) { 702 error = smb_ctx_setcharset(ctx, p); 703 if (error) 704 smb_error("charset specification in the section '%s' ignored", error, sname); 705 } 706 } 707 if (level <= 1) { 708 rc_getint(smb_rc, sname, "timeout", &ctx->ct_ssn.ioc_timeout); 709 rc_getint(smb_rc, sname, "retry_count", &ctx->ct_ssn.ioc_retrycount); 710 } 711 if (level == 1) { 712 rc_getstringptr(smb_rc, sname, "addr", &p); 713 if (p) { 714 error = smb_ctx_setsrvaddr(ctx, p); 715 if (error) { 716 smb_error("invalid address specified in the section %s", 0, sname); 717 return error; 718 } 719 } 720 } 721 if (level >= 2) { 722 rc_getstringptr(smb_rc, sname, "password", &p); 723 if (p) 724 smb_ctx_setpassword(ctx, p); 725 } 726 rc_getstringptr(smb_rc, sname, "workgroup", &p); 727 if (p) 728 smb_ctx_setworkgroup(ctx, p); 729 return 0; 730 } 731 732 /* 733 * read rc file as follows: 734 * 1. read [default] section 735 * 2. override with [server] section 736 * 3. override with [server:user:share] section 737 * Since abcence of rcfile is not fatal, silently ignore this fact. 738 * smb_rc file should be closed by caller. 739 */ 740 int 741 smb_ctx_readrc(struct smb_ctx *ctx) 742 { 743 char sname[SMB_MAXSRVNAMELEN + SMB_MAXUSERNAMELEN + SMB_MAXSHARENAMELEN + 4]; 744 /* char *p;*/ 745 746 if (smb_open_rcfile() != 0) 747 return 0; 748 749 if (ctx->ct_ssn.ioc_user[0] == 0 || ctx->ct_ssn.ioc_srvname[0] == 0) 750 return 0; 751 752 smb_ctx_readrcsection(ctx, "default", 0); 753 nb_ctx_readrcsection(smb_rc, ctx->ct_nb, "default", 0); 754 smb_ctx_readrcsection(ctx, ctx->ct_ssn.ioc_srvname, 1); 755 nb_ctx_readrcsection(smb_rc, ctx->ct_nb, ctx->ct_ssn.ioc_srvname, 1); 756 /* 757 * SERVER:USER parameters 758 */ 759 snprintf(sname, sizeof(sname), "%s:%s", ctx->ct_ssn.ioc_srvname, 760 ctx->ct_ssn.ioc_user); 761 smb_ctx_readrcsection(ctx, sname, 2); 762 763 if (ctx->ct_sh.ioc_share[0] != 0) { 764 /* 765 * SERVER:USER:SHARE parameters 766 */ 767 snprintf(sname, sizeof(sname), "%s:%s:%s", ctx->ct_ssn.ioc_srvname, 768 ctx->ct_ssn.ioc_user, ctx->ct_sh.ioc_share); 769 smb_ctx_readrcsection(ctx, sname, 3); 770 } 771 return 0; 772 } 773 774