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