1/* 2 Unix SMB/CIFS implementation. 3 SMBFS mount program 4 Copyright (C) Andrew Tridgell 1999 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#include "includes.h" 22 23#include <mntent.h> 24#include <asm/types.h> 25#include <linux/smb_fs.h> 26 27extern BOOL in_client; 28extern pstring user_socket_options; 29extern char *optarg; 30extern int optind; 31 32static pstring credentials; 33static pstring my_netbios_name; 34static pstring password; 35static pstring username; 36static pstring workgroup; 37static pstring mpoint; 38static pstring service; 39static pstring options; 40 41static struct in_addr dest_ip; 42static BOOL have_ip; 43static int smb_port = 0; 44static BOOL got_user; 45static BOOL got_pass; 46static uid_t mount_uid; 47static gid_t mount_gid; 48static int mount_ro; 49static unsigned mount_fmask; 50static unsigned mount_dmask; 51static BOOL use_kerberos; 52/* TODO: Add code to detect smbfs version in kernel */ 53static BOOL status32_smbfs = False; 54static BOOL smbfs_has_unicode = False; 55static BOOL smbfs_has_lfs = False; 56 57static void usage(void); 58 59static void exit_parent(int sig) 60{ 61 /* parent simply exits when child says go... */ 62 exit(0); 63} 64 65static void daemonize(void) 66{ 67 int j, status; 68 pid_t child_pid; 69 70 signal( SIGTERM, exit_parent ); 71 72 if ((child_pid = sys_fork()) < 0) { 73 DEBUG(0,("could not fork\n")); 74 } 75 76 if (child_pid > 0) { 77 while( 1 ) { 78 j = waitpid( child_pid, &status, 0 ); 79 if( j < 0 ) { 80 if( EINTR == errno ) { 81 continue; 82 } 83 status = errno; 84 } 85 break; 86 } 87 88 /* If we get here - the child exited with some error status */ 89 if (WIFSIGNALED(status)) 90 exit(128 + WTERMSIG(status)); 91 else 92 exit(WEXITSTATUS(status)); 93 } 94 95 signal( SIGTERM, SIG_DFL ); 96 chdir("/"); 97} 98 99static void close_our_files(int client_fd) 100{ 101 int i; 102 struct rlimit limits; 103 104 getrlimit(RLIMIT_NOFILE,&limits); 105 for (i = 0; i< limits.rlim_max; i++) { 106 if (i == client_fd) 107 continue; 108 close(i); 109 } 110} 111 112static void usr1_handler(int x) 113{ 114 return; 115} 116 117 118/***************************************************** 119return a connection to a server 120*******************************************************/ 121static struct cli_state *do_connection(char *the_service) 122{ 123 struct cli_state *c; 124 struct nmb_name called, calling; 125 char *server_n; 126 struct in_addr ip; 127 pstring server; 128 char *share; 129 130 if (the_service[0] != '\\' || the_service[1] != '\\') { 131 usage(); 132 exit(1); 133 } 134 135 pstrcpy(server, the_service+2); 136 share = strchr_m(server,'\\'); 137 if (!share) { 138 usage(); 139 exit(1); 140 } 141 *share = 0; 142 share++; 143 144 server_n = server; 145 146 make_nmb_name(&calling, my_netbios_name, 0x0); 147 make_nmb_name(&called , server, 0x20); 148 149 again: 150 zero_ip(&ip); 151 if (have_ip) ip = dest_ip; 152 153 /* have to open a new connection */ 154 if (!(c=cli_initialise()) || (cli_set_port(c, smb_port) != smb_port) || 155 !cli_connect(c, server_n, &ip)) { 156 DEBUG(0,("%d: Connection to %s failed\n", sys_getpid(), server_n)); 157 if (c) { 158 cli_shutdown(c); 159 } 160 return NULL; 161 } 162 163 /* SPNEGO doesn't work till we get NTSTATUS error support */ 164 /* But it is REQUIRED for kerberos authentication */ 165 if(!use_kerberos) c->use_spnego = False; 166 167 /* The kernel doesn't yet know how to sign it's packets */ 168 c->sign_info.allow_smb_signing = False; 169 170 /* Use kerberos authentication if specified */ 171 c->use_kerberos = use_kerberos; 172 173 if (!cli_session_request(c, &calling, &called)) { 174 char *p; 175 DEBUG(0,("%d: session request to %s failed (%s)\n", 176 sys_getpid(), called.name, cli_errstr(c))); 177 cli_shutdown(c); 178 if ((p=strchr_m(called.name, '.'))) { 179 *p = 0; 180 goto again; 181 } 182 if (strcmp(called.name, "*SMBSERVER")) { 183 make_nmb_name(&called , "*SMBSERVER", 0x20); 184 goto again; 185 } 186 return NULL; 187 } 188 189 DEBUG(4,("%d: session request ok\n", sys_getpid())); 190 191 if (!cli_negprot(c)) { 192 DEBUG(0,("%d: protocol negotiation failed\n", sys_getpid())); 193 cli_shutdown(c); 194 return NULL; 195 } 196 197 if (!got_pass) { 198 char *pass = getpass("Password: "); 199 if (pass) { 200 pstrcpy(password, pass); 201 } 202 } 203 204 /* This should be right for current smbfs. Future versions will support 205 large files as well as unicode and oplocks. */ 206 c->capabilities &= ~(CAP_NT_SMBS | CAP_NT_FIND | CAP_LEVEL_II_OPLOCKS); 207 if (!smbfs_has_lfs) 208 c->capabilities &= ~CAP_LARGE_FILES; 209 if (!smbfs_has_unicode) 210 c->capabilities &= ~CAP_UNICODE; 211 if (!status32_smbfs) { 212 c->capabilities &= ~CAP_STATUS32; 213 c->force_dos_errors = True; 214 } 215 216 if (!NT_STATUS_IS_OK(cli_session_setup(c, username, 217 password, strlen(password), 218 password, strlen(password), 219 workgroup))) { 220 /* if a password was not supplied then try again with a 221 null username */ 222 if (password[0] || !username[0] || 223 !NT_STATUS_IS_OK(cli_session_setup(c, "", "", 0, "", 0, workgroup))) { 224 DEBUG(0,("%d: session setup failed: %s\n", 225 sys_getpid(), cli_errstr(c))); 226 cli_shutdown(c); 227 return NULL; 228 } 229 DEBUG(0,("Anonymous login successful\n")); 230 } 231 232 DEBUG(4,("%d: session setup ok\n", sys_getpid())); 233 234 if (!cli_send_tconX(c, share, "?????", 235 password, strlen(password)+1)) { 236 DEBUG(0,("%d: tree connect failed: %s\n", 237 sys_getpid(), cli_errstr(c))); 238 cli_shutdown(c); 239 return NULL; 240 } 241 242 DEBUG(4,("%d: tconx ok\n", sys_getpid())); 243 244 got_pass = True; 245 246 return c; 247} 248 249 250/**************************************************************************** 251unmount smbfs (this is a bailout routine to clean up if a reconnect fails) 252 Code blatently stolen from smbumount.c 253 -mhw- 254****************************************************************************/ 255static void smb_umount(char *mount_point) 256{ 257 int fd; 258 struct mntent *mnt; 259 FILE* mtab; 260 FILE* new_mtab; 261 262 /* Programmers Note: 263 This routine only gets called to the scene of a disaster 264 to shoot the survivors... A connection that was working 265 has now apparently failed. We have an active mount point 266 (presumably) that we need to dump. If we get errors along 267 the way - make some noise, but we are already turning out 268 the lights to exit anyways... 269 */ 270 if (umount(mount_point) != 0) { 271 DEBUG(0,("%d: Could not umount %s: %s\n", 272 sys_getpid(), mount_point, strerror(errno))); 273 return; 274 } 275 276 if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) { 277 DEBUG(0,("%d: Can't get "MOUNTED"~ lock file", sys_getpid())); 278 return; 279 } 280 281 close(fd); 282 283 if ((mtab = setmntent(MOUNTED, "r")) == NULL) { 284 DEBUG(0,("%d: Can't open " MOUNTED ": %s\n", 285 sys_getpid(), strerror(errno))); 286 return; 287 } 288 289#define MOUNTED_TMP MOUNTED".tmp" 290 291 if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) { 292 DEBUG(0,("%d: Can't open " MOUNTED_TMP ": %s\n", 293 sys_getpid(), strerror(errno))); 294 endmntent(mtab); 295 return; 296 } 297 298 while ((mnt = getmntent(mtab)) != NULL) { 299 if (strcmp(mnt->mnt_dir, mount_point) != 0) { 300 addmntent(new_mtab, mnt); 301 } 302 } 303 304 endmntent(mtab); 305 306 if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { 307 DEBUG(0,("%d: Error changing mode of %s: %s\n", 308 sys_getpid(), MOUNTED_TMP, strerror(errno))); 309 return; 310 } 311 312 endmntent(new_mtab); 313 314 if (rename(MOUNTED_TMP, MOUNTED) < 0) { 315 DEBUG(0,("%d: Cannot rename %s to %s: %s\n", 316 sys_getpid(), MOUNTED, MOUNTED_TMP, strerror(errno))); 317 return; 318 } 319 320 if (unlink(MOUNTED"~") == -1) { 321 DEBUG(0,("%d: Can't remove "MOUNTED"~", sys_getpid())); 322 return; 323 } 324} 325 326 327/* 328 * Call the smbfs ioctl to install a connection socket, 329 * then wait for a signal to reconnect. Note that we do 330 * not exit after open_sockets() or send_login() errors, 331 * as the smbfs mount would then have no way to recover. 332 */ 333static void send_fs_socket(char *the_service, char *mount_point, struct cli_state *c) 334{ 335 int fd, closed = 0, res = 1; 336 pid_t parentpid = getppid(); 337 struct smb_conn_opt conn_options; 338 339 memset(&conn_options, 0, sizeof(conn_options)); 340 341 while (1) { 342 if ((fd = open(mount_point, O_RDONLY)) < 0) { 343 DEBUG(0,("mount.smbfs[%d]: can't open %s\n", 344 sys_getpid(), mount_point)); 345 break; 346 } 347 348 conn_options.fd = c->fd; 349 conn_options.protocol = c->protocol; 350 conn_options.case_handling = SMB_CASE_DEFAULT; 351 conn_options.max_xmit = c->max_xmit; 352 conn_options.server_uid = c->vuid; 353 conn_options.tid = c->cnum; 354 conn_options.secmode = c->sec_mode; 355 conn_options.rawmode = 0; 356 conn_options.sesskey = c->sesskey; 357 conn_options.maxraw = 0; 358 conn_options.capabilities = c->capabilities; 359 conn_options.serverzone = c->serverzone/60; 360 361 res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options); 362 if (res != 0) { 363 DEBUG(0,("mount.smbfs[%d]: ioctl failed, res=%d\n", 364 sys_getpid(), res)); 365 close(fd); 366 break; 367 } 368 369 if (parentpid) { 370 /* Ok... We are going to kill the parent. Now 371 is the time to break the process group... */ 372 setsid(); 373 /* Send a signal to the parent to terminate */ 374 kill(parentpid, SIGTERM); 375 parentpid = 0; 376 } 377 378 close(fd); 379 380 /* This looks wierd but we are only closing the userspace 381 side, the connection has already been passed to smbfs and 382 it has increased the usage count on the socket. 383 384 If we don't do this we will "leak" sockets and memory on 385 each reconnection we have to make. */ 386 c->smb_rw_error = DO_NOT_DO_TDIS; 387 cli_shutdown(c); 388 c = NULL; 389 390 if (!closed) { 391 /* close the name cache so that close_our_files() doesn't steal its FD */ 392 namecache_shutdown(); 393 394 /* redirect stdout & stderr since we can't know that 395 the library functions we use are using DEBUG. */ 396 if ( (fd = open("/dev/null", O_WRONLY)) < 0) 397 DEBUG(2,("mount.smbfs: can't open /dev/null\n")); 398 close_our_files(fd); 399 if (fd >= 0) { 400 dup2(fd, STDOUT_FILENO); 401 dup2(fd, STDERR_FILENO); 402 close(fd); 403 } 404 405 /* here we are no longer interactive */ 406 set_remote_machine_name("smbmount", False); /* sneaky ... */ 407 setup_logging("mount.smbfs", False); 408 reopen_logs(); 409 DEBUG(0, ("mount.smbfs: entering daemon mode for service %s, pid=%d\n", the_service, sys_getpid())); 410 411 closed = 1; 412 } 413 414 /* Wait for a signal from smbfs ... but don't continue 415 until we actually get a new connection. */ 416 while (!c) { 417 CatchSignal(SIGUSR1, &usr1_handler); 418 pause(); 419 DEBUG(2,("mount.smbfs[%d]: got signal, getting new socket\n", sys_getpid())); 420 c = do_connection(the_service); 421 } 422 } 423 424 smb_umount(mount_point); 425 DEBUG(2,("mount.smbfs[%d]: exit\n", sys_getpid())); 426 exit(1); 427} 428 429 430/** 431 * Mount a smbfs 432 **/ 433static void init_mount(void) 434{ 435 char mount_point[PATH_MAX+1]; 436 pstring tmp; 437 pstring svc2; 438 struct cli_state *c; 439 char *args[20]; 440 int i, status; 441 442 if (realpath(mpoint, mount_point) == NULL) { 443 fprintf(stderr, "Could not resolve mount point %s\n", mpoint); 444 return; 445 } 446 447 448 c = do_connection(service); 449 if (!c) { 450 fprintf(stderr,"SMB connection failed\n"); 451 exit(1); 452 } 453 454 /* 455 Set up to return as a daemon child and wait in the parent 456 until the child say it's ready... 457 */ 458 daemonize(); 459 460 pstrcpy(svc2, service); 461 string_replace(svc2, '\\','/'); 462 string_replace(svc2, ' ','_'); 463 464 memset(args, 0, sizeof(args[0])*20); 465 466 i=0; 467 args[i++] = "smbmnt"; 468 469 args[i++] = mount_point; 470 args[i++] = "-s"; 471 args[i++] = svc2; 472 473 if (mount_ro) { 474 args[i++] = "-r"; 475 } 476 if (mount_uid) { 477 slprintf(tmp, sizeof(tmp)-1, "%d", mount_uid); 478 args[i++] = "-u"; 479 args[i++] = smb_xstrdup(tmp); 480 } 481 if (mount_gid) { 482 slprintf(tmp, sizeof(tmp)-1, "%d", mount_gid); 483 args[i++] = "-g"; 484 args[i++] = smb_xstrdup(tmp); 485 } 486 if (mount_fmask) { 487 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_fmask); 488 args[i++] = "-f"; 489 args[i++] = smb_xstrdup(tmp); 490 } 491 if (mount_dmask) { 492 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_dmask); 493 args[i++] = "-d"; 494 args[i++] = smb_xstrdup(tmp); 495 } 496 if (options) { 497 args[i++] = "-o"; 498 args[i++] = options; 499 } 500 501 if (sys_fork() == 0) { 502 char *smbmnt_path; 503 504 asprintf(&smbmnt_path, "%s/smbmnt", dyn_BINDIR); 505 506 if (file_exist(smbmnt_path, NULL)) { 507 execv(smbmnt_path, args); 508 fprintf(stderr, 509 "smbfs/init_mount: execv of %s failed. Error was %s.", 510 smbmnt_path, strerror(errno)); 511 } else { 512 execvp("smbmnt", args); 513 fprintf(stderr, 514 "smbfs/init_mount: execv of %s failed. Error was %s.", 515 "smbmnt", strerror(errno)); 516 } 517 free(smbmnt_path); 518 exit(1); 519 } 520 521 if (waitpid(-1, &status, 0) == -1) { 522 fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) ); 523 /* FIXME: do some proper error handling */ 524 exit(1); 525 } 526 527 if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { 528 fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status)); 529 /* FIXME: do some proper error handling */ 530 exit(1); 531 } else if (WIFSIGNALED(status)) { 532 fprintf(stderr, "smbmnt killed by signal %d\n", WTERMSIG(status)); 533 exit(1); 534 } 535 536 /* Ok... This is the rubicon for that mount point... At any point 537 after this, if the connections fail and can not be reconstructed 538 for any reason, we will have to unmount the mount point. There 539 is no exit from the next call... 540 */ 541 send_fs_socket(service, mount_point, c); 542} 543 544 545/**************************************************************************** 546get a password from a a file or file descriptor 547exit on failure (from smbclient, move to libsmb or shared .c file?) 548****************************************************************************/ 549static void get_password_file(void) 550{ 551 int fd = -1; 552 char *p; 553 BOOL close_it = False; 554 pstring spec; 555 char pass[128]; 556 557 if ((p = getenv("PASSWD_FD")) != NULL) { 558 pstrcpy(spec, "descriptor "); 559 pstrcat(spec, p); 560 sscanf(p, "%d", &fd); 561 close_it = False; 562 } else if ((p = getenv("PASSWD_FILE")) != NULL) { 563 fd = sys_open(p, O_RDONLY, 0); 564 pstrcpy(spec, p); 565 if (fd < 0) { 566 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", 567 spec, strerror(errno)); 568 exit(1); 569 } 570 close_it = True; 571 } 572 573 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ 574 p && p - pass < sizeof(pass);) { 575 switch (read(fd, p, 1)) { 576 case 1: 577 if (*p != '\n' && *p != '\0') { 578 *++p = '\0'; /* advance p, and null-terminate pass */ 579 break; 580 } 581 case 0: 582 if (p - pass) { 583 *p = '\0'; /* null-terminate it, just in case... */ 584 p = NULL; /* then force the loop condition to become false */ 585 break; 586 } else { 587 fprintf(stderr, "Error reading password from file %s: %s\n", 588 spec, "empty password\n"); 589 exit(1); 590 } 591 592 default: 593 fprintf(stderr, "Error reading password from file %s: %s\n", 594 spec, strerror(errno)); 595 exit(1); 596 } 597 } 598 pstrcpy(password, pass); 599 if (close_it) 600 close(fd); 601} 602 603/**************************************************************************** 604get username and password from a credentials file 605exit on failure (from smbclient, move to libsmb or shared .c file?) 606****************************************************************************/ 607static void read_credentials_file(char *filename) 608{ 609 FILE *auth; 610 fstring buf; 611 uint16 len = 0; 612 char *ptr, *val, *param; 613 614 if ((auth=sys_fopen(filename, "r")) == NULL) 615 { 616 /* fail if we can't open the credentials file */ 617 DEBUG(0,("ERROR: Unable to open credentials file!\n")); 618 exit (-1); 619 } 620 621 while (!feof(auth)) 622 { 623 /* get a line from the file */ 624 if (!fgets (buf, sizeof(buf), auth)) 625 continue; 626 len = strlen(buf); 627 628 if ((len) && (buf[len-1]=='\n')) 629 { 630 buf[len-1] = '\0'; 631 len--; 632 } 633 if (len == 0) 634 continue; 635 636 /* break up the line into parameter & value. 637 will need to eat a little whitespace possibly */ 638 param = buf; 639 if (!(ptr = strchr (buf, '='))) 640 continue; 641 val = ptr+1; 642 *ptr = '\0'; 643 644 /* eat leading white space */ 645 while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) 646 val++; 647 648 if (strwicmp("password", param) == 0) 649 { 650 pstrcpy(password, val); 651 got_pass = True; 652 } 653 else if (strwicmp("username", param) == 0) { 654 pstrcpy(username, val); 655 } 656 657 memset(buf, 0, sizeof(buf)); 658 } 659 fclose(auth); 660} 661 662 663/**************************************************************************** 664usage on the program 665****************************************************************************/ 666static void usage(void) 667{ 668 printf("Usage: mount.smbfs service mountpoint [-o options,...]\n"); 669 670 printf("Version %s\n\n",SAMBA_VERSION_STRING); 671 672 printf("Please be aware that smbfs is deprecated in favor of " 673 "cifs\n\n"); 674 675 printf( 676"Options:\n\ 677 username=<arg> SMB username\n\ 678 password=<arg> SMB password\n\ 679 credentials=<filename> file with username/password\n\ 680 krb use kerberos (active directory)\n\ 681 netbiosname=<arg> source NetBIOS name\n\ 682 uid=<arg> mount uid or username\n\ 683 gid=<arg> mount gid or groupname\n\ 684 port=<arg> remote SMB port number\n\ 685 fmask=<arg> file umask\n\ 686 dmask=<arg> directory umask\n\ 687 debug=<arg> debug level\n\ 688 ip=<arg> destination host or IP address\n\ 689 workgroup=<arg> workgroup on destination\n\ 690 sockopt=<arg> TCP socket options\n\ 691 scope=<arg> NetBIOS scope\n\ 692 iocharset=<arg> Linux charset (iso8859-1, utf8)\n\ 693 codepage=<arg> server codepage (cp850)\n\ 694 unicode use unicode when communicating with server\n\ 695 lfs large file system support\n\ 696 ttl=<arg> dircache time to live\n\ 697 guest don't prompt for a password\n\ 698 ro mount read-only\n\ 699 rw mount read-write\n\ 700\n\ 701This command is designed to be run from within /bin/mount by giving\n\ 702the option '-t smbfs'. For example:\n\ 703 mount -t smbfs -o username=tridge,password=foobar //fjall/test /data/test\n\ 704"); 705} 706 707 708/**************************************************************************** 709 Argument parsing for mount.smbfs interface 710 mount will call us like this: 711 mount.smbfs device mountpoint -o <options> 712 713 <options> is never empty, containing at least rw or ro 714 ****************************************************************************/ 715static void parse_mount_smb(int argc, char **argv) 716{ 717 int opt; 718 char *opts; 719 char *opteq; 720 int val; 721 char *p; 722 723 /* FIXME: This function can silently fail if the arguments are 724 * not in the expected order. 725 726 > The arguments syntax of smbmount 2.2.3a (smbfs of Debian stable) 727 > requires that one gives "-o" before further options like username=... 728 > . Without -o, the username=.. setting is *silently* ignored. I've 729 > spent about an hour trying to find out why I couldn't log in now.. 730 731 */ 732 733 734 if (argc < 2 || argv[1][0] == '-') { 735 usage(); 736 exit(1); 737 } 738 739 pstrcpy(service, argv[1]); 740 pstrcpy(mpoint, argv[2]); 741 742 /* Convert any '/' characters in the service name to 743 '\' characters */ 744 string_replace(service, '/','\\'); 745 argc -= 2; 746 argv += 2; 747 748 opt = getopt(argc, argv, "o:"); 749 if(opt != 'o') { 750 return; 751 } 752 753 options[0] = 0; 754 p = options; 755 756 /* 757 * option parsing from nfsmount.c (util-linux-2.9u) 758 */ 759 for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) { 760 DEBUG(3, ("opts: %s\n", opts)); 761 if ((opteq = strchr_m(opts, '='))) { 762 val = atoi(opteq + 1); 763 *opteq = '\0'; 764 765 if (!strcmp(opts, "username") || 766 !strcmp(opts, "logon")) { 767 char *lp; 768 got_user = True; 769 pstrcpy(username,opteq+1); 770 if ((lp=strchr_m(username,'%'))) { 771 *lp = 0; 772 pstrcpy(password,lp+1); 773 got_pass = True; 774 memset(strchr_m(opteq+1,'%')+1,'X',strlen(password)); 775 } 776 if ((lp=strchr_m(username,'/'))) { 777 *lp = 0; 778 pstrcpy(workgroup,lp+1); 779 } 780 } else if(!strcmp(opts, "passwd") || 781 !strcmp(opts, "password")) { 782 pstrcpy(password,opteq+1); 783 got_pass = True; 784 memset(opteq+1,'X',strlen(password)); 785 } else if(!strcmp(opts, "credentials")) { 786 pstrcpy(credentials,opteq+1); 787 } else if(!strcmp(opts, "netbiosname")) { 788 pstrcpy(my_netbios_name,opteq+1); 789 } else if(!strcmp(opts, "uid")) { 790 mount_uid = nametouid(opteq+1); 791 } else if(!strcmp(opts, "gid")) { 792 mount_gid = nametogid(opteq+1); 793 } else if(!strcmp(opts, "port")) { 794 smb_port = val; 795 } else if(!strcmp(opts, "fmask")) { 796 mount_fmask = strtol(opteq+1, NULL, 8); 797 } else if(!strcmp(opts, "dmask")) { 798 mount_dmask = strtol(opteq+1, NULL, 8); 799 } else if(!strcmp(opts, "debug")) { 800 DEBUGLEVEL = val; 801 } else if(!strcmp(opts, "ip")) { 802 dest_ip = *interpret_addr2(opteq+1); 803 if (is_zero_ip(dest_ip)) { 804 fprintf(stderr,"Can't resolve address %s\n", opteq+1); 805 exit(1); 806 } 807 have_ip = True; 808 } else if(!strcmp(opts, "workgroup")) { 809 pstrcpy(workgroup,opteq+1); 810 } else if(!strcmp(opts, "sockopt")) { 811 pstrcpy(user_socket_options,opteq+1); 812 } else if(!strcmp(opts, "scope")) { 813 set_global_scope(opteq+1); 814 } else { 815 slprintf(p, sizeof(pstring) - (p - options) - 1, "%s=%s,", opts, opteq+1); 816 p += strlen(p); 817 } 818 } else { 819 val = 1; 820 if(!strcmp(opts, "nocaps")) { 821 fprintf(stderr, "Unhandled option: %s\n", opteq+1); 822 exit(1); 823 } else if(!strcmp(opts, "guest")) { 824 *password = '\0'; 825 got_pass = True; 826 } else if(!strcmp(opts, "krb")) { 827#ifdef HAVE_KRB5 828 829 use_kerberos = True; 830 if(!status32_smbfs) 831 fprintf(stderr, "Warning: kerberos support will only work for samba servers\n"); 832#else 833 fprintf(stderr,"No kerberos support compiled in\n"); 834 exit(1); 835#endif 836 } else if(!strcmp(opts, "rw")) { 837 mount_ro = 0; 838 } else if(!strcmp(opts, "ro")) { 839 mount_ro = 1; 840 } else if(!strcmp(opts, "unicode")) { 841 smbfs_has_unicode = True; 842 } else if(!strcmp(opts, "lfs")) { 843 smbfs_has_lfs = True; 844 } else { 845 strncpy(p, opts, sizeof(pstring) - (p - options) - 1); 846 p += strlen(opts); 847 *p++ = ','; 848 *p = 0; 849 } 850 } 851 } 852 853 if (!*service) { 854 usage(); 855 exit(1); 856 } 857 858 if (p != options) { 859 *(p-1) = 0; /* remove trailing , */ 860 DEBUG(3,("passthrough options '%s'\n", options)); 861 } 862} 863 864/**************************************************************************** 865 main program 866****************************************************************************/ 867 int main(int argc,char *argv[]) 868{ 869 char *p; 870 871 DEBUGLEVEL = 1; 872 873 load_case_tables(); 874 875 /* here we are interactive, even if run from autofs */ 876 setup_logging("mount.smbfs",True); 877 878#if 0 /* JRA - Urban says not needed ? */ 879 /* CLI_FORCE_ASCII=false makes smbmount negotiate unicode. The default 880 is to not announce any unicode capabilities as current smbfs does 881 not support it. */ 882 p = getenv("CLI_FORCE_ASCII"); 883 if (p && !strcmp(p, "false")) 884 unsetenv("CLI_FORCE_ASCII"); 885 else 886 setenv("CLI_FORCE_ASCII", "true", 1); 887#endif 888 889 in_client = True; /* Make sure that we tell lp_load we are */ 890 891 if (getenv("USER")) { 892 pstrcpy(username,getenv("USER")); 893 894 if ((p=strchr_m(username,'%'))) { 895 *p = 0; 896 pstrcpy(password,p+1); 897 got_pass = True; 898 memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password)); 899 } 900 strupper_m(username); 901 } 902 903 if (getenv("PASSWD")) { 904 pstrcpy(password,getenv("PASSWD")); 905 got_pass = True; 906 } 907 908 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { 909 get_password_file(); 910 got_pass = True; 911 } 912 913 if (*username == 0 && getenv("LOGNAME")) { 914 pstrcpy(username,getenv("LOGNAME")); 915 } 916 917 if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) { 918 fprintf(stderr, "Can't load %s - run testparm to debug it\n", 919 dyn_CONFIGFILE); 920 } 921 922 parse_mount_smb(argc, argv); 923 924 if (use_kerberos && !got_user) { 925 got_pass = True; 926 } 927 928 if (*credentials != 0) { 929 read_credentials_file(credentials); 930 } 931 932 DEBUG(3,("mount.smbfs started (version %s)\n", SAMBA_VERSION_STRING)); 933 934 if (*workgroup == 0) { 935 pstrcpy(workgroup,lp_workgroup()); 936 } 937 938 load_interfaces(); 939 if (!*my_netbios_name) { 940 pstrcpy(my_netbios_name, myhostname()); 941 } 942 strupper_m(my_netbios_name); 943 944 init_mount(); 945 return 0; 946} 947