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#define NO_SYSLOG 22 23#include "includes.h" 24 25#include <mntent.h> 26#include <asm/types.h> 27#include <linux/smb_fs.h> 28 29extern BOOL in_client; 30extern pstring user_socket_options; 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(NULL)) || (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 (!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 !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 /* redirect stdout & stderr since we can't know that 392 the library functions we use are using DEBUG. */ 393 if ( (fd = open("/dev/null", O_WRONLY)) < 0) 394 DEBUG(2,("mount.smbfs: can't open /dev/null\n")); 395 close_our_files(fd); 396 if (fd >= 0) { 397 dup2(fd, STDOUT_FILENO); 398 dup2(fd, STDERR_FILENO); 399 close(fd); 400 } 401 402 /* here we are no longer interactive */ 403 set_remote_machine_name("smbmount", False); /* sneaky ... */ 404 setup_logging("mount.smbfs", False); 405 reopen_logs(); 406 DEBUG(0, ("mount.smbfs: entering daemon mode for service %s, pid=%d\n", the_service, sys_getpid())); 407 408 closed = 1; 409 } 410 411 /* Wait for a signal from smbfs ... but don't continue 412 until we actually get a new connection. */ 413 while (!c) { 414 CatchSignal(SIGUSR1, &usr1_handler); 415 pause(); 416 DEBUG(2,("mount.smbfs[%d]: got signal, getting new socket\n", sys_getpid())); 417 c = do_connection(the_service); 418 } 419 } 420 421 smb_umount(mount_point); 422 DEBUG(2,("mount.smbfs[%d]: exit\n", sys_getpid())); 423 exit(1); 424} 425 426 427/** 428 * Mount a smbfs 429 **/ 430static void init_mount(void) 431{ 432 char mount_point[PATH_MAX+1]; 433 pstring tmp; 434 pstring svc2; 435 struct cli_state *c; 436 char *args[20]; 437 int i, status; 438 439 if (realpath(mpoint, mount_point) == NULL) { 440 fprintf(stderr, "Could not resolve mount point %s\n", mpoint); 441 return; 442 } 443 444 445 c = do_connection(service); 446 if (!c) { 447 fprintf(stderr,"SMB connection failed\n"); 448 exit(1); 449 } 450 451 /* 452 Set up to return as a daemon child and wait in the parent 453 until the child say it's ready... 454 */ 455 daemonize(); 456 457 pstrcpy(svc2, service); 458 string_replace(svc2, '\\','/'); 459 string_replace(svc2, ' ','_'); 460 461 memset(args, 0, sizeof(args[0])*20); 462 463 i=0; 464 args[i++] = "smbmnt"; 465 466 args[i++] = mount_point; 467 args[i++] = "-s"; 468 args[i++] = svc2; 469 470 if (mount_ro) { 471 args[i++] = "-r"; 472 } 473 if (mount_uid) { 474 slprintf(tmp, sizeof(tmp)-1, "%d", mount_uid); 475 args[i++] = "-u"; 476 args[i++] = smb_xstrdup(tmp); 477 } 478 if (mount_gid) { 479 slprintf(tmp, sizeof(tmp)-1, "%d", mount_gid); 480 args[i++] = "-g"; 481 args[i++] = smb_xstrdup(tmp); 482 } 483 if (mount_fmask) { 484 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_fmask); 485 args[i++] = "-f"; 486 args[i++] = smb_xstrdup(tmp); 487 } 488 if (mount_dmask) { 489 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_dmask); 490 args[i++] = "-d"; 491 args[i++] = smb_xstrdup(tmp); 492 } 493 if (options) { 494 args[i++] = "-o"; 495 args[i++] = options; 496 } 497 498 if (sys_fork() == 0) { 499 char *smbmnt_path; 500 501 asprintf(&smbmnt_path, "%s/smbmnt", dyn_BINDIR); 502 503 if (file_exist(smbmnt_path, NULL)) { 504 execv(smbmnt_path, args); 505 fprintf(stderr, 506 "smbfs/init_mount: execv of %s failed. Error was %s.", 507 smbmnt_path, strerror(errno)); 508 } else { 509 execvp("smbmnt", args); 510 fprintf(stderr, 511 "smbfs/init_mount: execv of %s failed. Error was %s.", 512 "smbmnt", strerror(errno)); 513 } 514 free(smbmnt_path); 515 exit(1); 516 } 517 518 if (waitpid(-1, &status, 0) == -1) { 519 fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) ); 520 /* FIXME: do some proper error handling */ 521 exit(1); 522 } 523 524 if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { 525 fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status)); 526 /* FIXME: do some proper error handling */ 527 exit(1); 528 } else if (WIFSIGNALED(status)) { 529 fprintf(stderr, "smbmnt killed by signal %d\n", WTERMSIG(status)); 530 exit(1); 531 } 532 533 /* Ok... This is the rubicon for that mount point... At any point 534 after this, if the connections fail and can not be reconstructed 535 for any reason, we will have to unmount the mount point. There 536 is no exit from the next call... 537 */ 538 send_fs_socket(service, mount_point, c); 539} 540 541 542/**************************************************************************** 543get a password from a a file or file descriptor 544exit on failure (from smbclient, move to libsmb or shared .c file?) 545****************************************************************************/ 546static void get_password_file(void) 547{ 548 int fd = -1; 549 char *p; 550 BOOL close_it = False; 551 pstring spec; 552 char pass[128]; 553 554 if ((p = getenv("PASSWD_FD")) != NULL) { 555 pstrcpy(spec, "descriptor "); 556 pstrcat(spec, p); 557 sscanf(p, "%d", &fd); 558 close_it = False; 559 } else if ((p = getenv("PASSWD_FILE")) != NULL) { 560 fd = sys_open(p, O_RDONLY, 0); 561 pstrcpy(spec, p); 562 if (fd < 0) { 563 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", 564 spec, strerror(errno)); 565 exit(1); 566 } 567 close_it = True; 568 } 569 570 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ 571 p && p - pass < sizeof(pass);) { 572 switch (read(fd, p, 1)) { 573 case 1: 574 if (*p != '\n' && *p != '\0') { 575 *++p = '\0'; /* advance p, and null-terminate pass */ 576 break; 577 } 578 case 0: 579 if (p - pass) { 580 *p = '\0'; /* null-terminate it, just in case... */ 581 p = NULL; /* then force the loop condition to become false */ 582 break; 583 } else { 584 fprintf(stderr, "Error reading password from file %s: %s\n", 585 spec, "empty password\n"); 586 exit(1); 587 } 588 589 default: 590 fprintf(stderr, "Error reading password from file %s: %s\n", 591 spec, strerror(errno)); 592 exit(1); 593 } 594 } 595 pstrcpy(password, pass); 596 if (close_it) 597 close(fd); 598} 599 600/**************************************************************************** 601get username and password from a credentials file 602exit on failure (from smbclient, move to libsmb or shared .c file?) 603****************************************************************************/ 604static void read_credentials_file(char *filename) 605{ 606 FILE *auth; 607 fstring buf; 608 uint16 len = 0; 609 char *ptr, *val, *param; 610 611 if ((auth=sys_fopen(filename, "r")) == NULL) 612 { 613 /* fail if we can't open the credentials file */ 614 DEBUG(0,("ERROR: Unable to open credentials file!\n")); 615 exit (-1); 616 } 617 618 while (!feof(auth)) 619 { 620 /* get a line from the file */ 621 if (!fgets (buf, sizeof(buf), auth)) 622 continue; 623 len = strlen(buf); 624 625 if ((len) && (buf[len-1]=='\n')) 626 { 627 buf[len-1] = '\0'; 628 len--; 629 } 630 if (len == 0) 631 continue; 632 633 /* break up the line into parameter & value. 634 will need to eat a little whitespace possibly */ 635 param = buf; 636 if (!(ptr = strchr (buf, '='))) 637 continue; 638 val = ptr+1; 639 *ptr = '\0'; 640 641 /* eat leading white space */ 642 while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) 643 val++; 644 645 if (strwicmp("password", param) == 0) 646 { 647 pstrcpy(password, val); 648 got_pass = True; 649 } 650 else if (strwicmp("username", param) == 0) { 651 pstrcpy(username, val); 652 } 653 654 memset(buf, 0, sizeof(buf)); 655 } 656 fclose(auth); 657} 658 659 660/**************************************************************************** 661usage on the program 662****************************************************************************/ 663static void usage(void) 664{ 665 printf("Usage: mount.smbfs service mountpoint [-o options,...]\n"); 666 667 printf("Version %s\n\n",SAMBA_VERSION_STRING); 668 669 printf( 670"Options:\n\ 671 username=<arg> SMB username\n\ 672 password=<arg> SMB password\n\ 673 credentials=<filename> file with username/password\n\ 674 krb use kerberos (active directory)\n\ 675 netbiosname=<arg> source NetBIOS name\n\ 676 uid=<arg> mount uid or username\n\ 677 gid=<arg> mount gid or groupname\n\ 678 port=<arg> remote SMB port number\n\ 679 fmask=<arg> file umask\n\ 680 dmask=<arg> directory umask\n\ 681 debug=<arg> debug level\n\ 682 ip=<arg> destination host or IP address\n\ 683 workgroup=<arg> workgroup on destination\n\ 684 sockopt=<arg> TCP socket options\n\ 685 scope=<arg> NetBIOS scope\n\ 686 iocharset=<arg> Linux charset (iso8859-1, utf8)\n\ 687 codepage=<arg> server codepage (cp850)\n\ 688 unicode use unicode when communicating with server\n\ 689 lfs large file system support\n\ 690 ttl=<arg> dircache time to live\n\ 691 guest don't prompt for a password\n\ 692 ro mount read-only\n\ 693 rw mount read-write\n\ 694\n\ 695This command is designed to be run from within /bin/mount by giving\n\ 696the option '-t smbfs'. For example:\n\ 697 mount -t smbfs -o username=tridge,password=foobar //fjall/test /data/test\n\ 698"); 699} 700 701 702/**************************************************************************** 703 Argument parsing for mount.smbfs interface 704 mount will call us like this: 705 mount.smbfs device mountpoint -o <options> 706 707 <options> is never empty, containing at least rw or ro 708 ****************************************************************************/ 709static void parse_mount_smb(int argc, char **argv) 710{ 711 int opt; 712 char *opts; 713 char *opteq; 714 extern char *optarg; 715 int val; 716 char *p; 717 718 /* FIXME: This function can silently fail if the arguments are 719 * not in the expected order. 720 721 > The arguments syntax of smbmount 2.2.3a (smbfs of Debian stable) 722 > requires that one gives "-o" before further options like username=... 723 > . Without -o, the username=.. setting is *silently* ignored. I've 724 > spent about an hour trying to find out why I couldn't log in now.. 725 726 */ 727 728 729 if (argc < 2 || argv[1][0] == '-') { 730 usage(); 731 exit(1); 732 } 733 734 pstrcpy(service, argv[1]); 735 pstrcpy(mpoint, argv[2]); 736 737 /* Convert any '/' characters in the service name to 738 '\' characters */ 739 string_replace(service, '/','\\'); 740 argc -= 2; 741 argv += 2; 742 743 opt = getopt(argc, argv, "o:"); 744 if(opt != 'o') { 745 return; 746 } 747 748 options[0] = 0; 749 p = options; 750 751 /* 752 * option parsing from nfsmount.c (util-linux-2.9u) 753 */ 754 for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) { 755 DEBUG(3, ("opts: %s\n", opts)); 756 if ((opteq = strchr_m(opts, '='))) { 757 val = atoi(opteq + 1); 758 *opteq = '\0'; 759 760 if (!strcmp(opts, "username") || 761 !strcmp(opts, "logon")) { 762 char *lp; 763 got_user = True; 764 pstrcpy(username,opteq+1); 765 if ((lp=strchr_m(username,'%'))) { 766 *lp = 0; 767 pstrcpy(password,lp+1); 768 got_pass = True; 769 memset(strchr_m(opteq+1,'%')+1,'X',strlen(password)); 770 } 771 if ((lp=strchr_m(username,'/'))) { 772 *lp = 0; 773 pstrcpy(workgroup,lp+1); 774 } 775 } else if(!strcmp(opts, "passwd") || 776 !strcmp(opts, "password")) { 777 pstrcpy(password,opteq+1); 778 got_pass = True; 779 memset(opteq+1,'X',strlen(password)); 780 } else if(!strcmp(opts, "credentials")) { 781 pstrcpy(credentials,opteq+1); 782 } else if(!strcmp(opts, "netbiosname")) { 783 pstrcpy(my_netbios_name,opteq+1); 784 } else if(!strcmp(opts, "uid")) { 785 mount_uid = nametouid(opteq+1); 786 } else if(!strcmp(opts, "gid")) { 787 mount_gid = nametogid(opteq+1); 788 } else if(!strcmp(opts, "port")) { 789 smb_port = val; 790 } else if(!strcmp(opts, "fmask")) { 791 mount_fmask = strtol(opteq+1, NULL, 8); 792 } else if(!strcmp(opts, "dmask")) { 793 mount_dmask = strtol(opteq+1, NULL, 8); 794 } else if(!strcmp(opts, "debug")) { 795 DEBUGLEVEL = val; 796 } else if(!strcmp(opts, "ip")) { 797 dest_ip = *interpret_addr2(opteq+1); 798 if (is_zero_ip(dest_ip)) { 799 fprintf(stderr,"Can't resolve address %s\n", opteq+1); 800 exit(1); 801 } 802 have_ip = True; 803 } else if(!strcmp(opts, "workgroup")) { 804 pstrcpy(workgroup,opteq+1); 805 } else if(!strcmp(opts, "sockopt")) { 806 pstrcpy(user_socket_options,opteq+1); 807 } else if(!strcmp(opts, "scope")) { 808 set_global_scope(opteq+1); 809 } else { 810 slprintf(p, sizeof(pstring) - (p - options) - 1, "%s=%s,", opts, opteq+1); 811 p += strlen(p); 812 } 813 } else { 814 val = 1; 815 if(!strcmp(opts, "nocaps")) { 816 fprintf(stderr, "Unhandled option: %s\n", opteq+1); 817 exit(1); 818 } else if(!strcmp(opts, "guest")) { 819 *password = '\0'; 820 got_pass = True; 821 } else if(!strcmp(opts, "krb")) { 822#ifdef HAVE_KRB5 823 824 use_kerberos = True; 825 if(!status32_smbfs) 826 fprintf(stderr, "Warning: kerberos support will only work for samba servers\n"); 827#else 828 fprintf(stderr,"No kerberos support compiled in\n"); 829 exit(1); 830#endif 831 } else if(!strcmp(opts, "rw")) { 832 mount_ro = 0; 833 } else if(!strcmp(opts, "ro")) { 834 mount_ro = 1; 835 } else if(!strcmp(opts, "unicode")) { 836 smbfs_has_unicode = True; 837 } else if(!strcmp(opts, "lfs")) { 838 smbfs_has_lfs = True; 839 } else { 840 strncpy(p, opts, sizeof(pstring) - (p - options) - 1); 841 p += strlen(opts); 842 *p++ = ','; 843 *p = 0; 844 } 845 } 846 } 847 848 if (!*service) { 849 usage(); 850 exit(1); 851 } 852 853 if (p != options) { 854 *(p-1) = 0; /* remove trailing , */ 855 DEBUG(3,("passthrough options '%s'\n", options)); 856 } 857} 858 859/**************************************************************************** 860 main program 861****************************************************************************/ 862 int main(int argc,char *argv[]) 863{ 864 extern char *optarg; 865 extern int optind; 866 char *p; 867 868 DEBUGLEVEL = 1; 869 870 /* here we are interactive, even if run from autofs */ 871 setup_logging("mount.smbfs",True); 872 873#if 0 /* JRA - Urban says not needed ? */ 874 /* CLI_FORCE_ASCII=false makes smbmount negotiate unicode. The default 875 is to not announce any unicode capabilities as current smbfs does 876 not support it. */ 877 p = getenv("CLI_FORCE_ASCII"); 878 if (p && !strcmp(p, "false")) 879 unsetenv("CLI_FORCE_ASCII"); 880 else 881 setenv("CLI_FORCE_ASCII", "true", 1); 882#endif 883 884 in_client = True; /* Make sure that we tell lp_load we are */ 885 886 if (getenv("USER")) { 887 pstrcpy(username,getenv("USER")); 888 889 if ((p=strchr_m(username,'%'))) { 890 *p = 0; 891 pstrcpy(password,p+1); 892 got_pass = True; 893 memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password)); 894 } 895 strupper_m(username); 896 } 897 898 if (getenv("PASSWD")) { 899 pstrcpy(password,getenv("PASSWD")); 900 got_pass = True; 901 } 902 903 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { 904 get_password_file(); 905 got_pass = True; 906 } 907 908 if (*username == 0 && getenv("LOGNAME")) { 909 pstrcpy(username,getenv("LOGNAME")); 910 } 911 912 if (!lp_load(dyn_CONFIGFILE,True,False,False)) { 913 fprintf(stderr, "Can't load %s - run testparm to debug it\n", 914 dyn_CONFIGFILE); 915 } 916 917 parse_mount_smb(argc, argv); 918 919 if (use_kerberos && !got_user) { 920 got_pass = True; 921 } 922 923 if (*credentials != 0) { 924 read_credentials_file(credentials); 925 } 926 927 DEBUG(3,("mount.smbfs started (version %s)\n", SAMBA_VERSION_STRING)); 928 929 if (*workgroup == 0) { 930 pstrcpy(workgroup,lp_workgroup()); 931 } 932 933 load_interfaces(); 934 if (!*my_netbios_name) { 935 pstrcpy(my_netbios_name, myhostname()); 936 } 937 strupper_m(my_netbios_name); 938 939 init_mount(); 940 return 0; 941} 942