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