diff options
Diffstat (limited to 'source3/client')
-rw-r--r-- | source3/client/smbmount.c | 301 |
1 files changed, 246 insertions, 55 deletions
diff --git a/source3/client/smbmount.c b/source3/client/smbmount.c index ec3f32bd36..3c0b132937 100644 --- a/source3/client/smbmount.c +++ b/source3/client/smbmount.c @@ -27,25 +27,22 @@ #include <asm/types.h> #include <linux/smb_fs.h> -/* Uncomment this to allow debug the mount.smb daemon */ -/* WARNING! This option is incompatible with autofs/automount because - it does not close the stdout pipe back to the automount - process, which automount depends on. This will cause automount - to hang! Use with caution! */ -/* #define SMBFS_DEBUG 1 */ - extern struct in_addr ipzero; extern int DEBUGLEVEL; extern BOOL in_client; extern pstring user_socket_options; +extern BOOL append_log; +extern fstring remote_machine; +static pstring credentials; static pstring my_netbios_name; static pstring password; static pstring username; static pstring workgroup; static pstring mpoint; static pstring service; +static pstring options; static struct in_addr dest_ip; static BOOL have_ip; @@ -73,7 +70,7 @@ static void daemonize(void) signal( SIGTERM, exit_parent ); if ((child_pid = sys_fork()) < 0) { - fprintf(stderr,"could not fork\n"); + DEBUG(0,("could not fork\n")); } if (child_pid > 0) { @@ -138,8 +135,6 @@ static struct cli_state *do_connection(char *service) share++; server_n = server; - - ip = ipzero; make_nmb_name(&calling, my_netbios_name, 0x0); make_nmb_name(&called , server, 0x20); @@ -151,13 +146,24 @@ static struct cli_state *do_connection(char *service) /* have to open a new connection */ if (!(c=cli_initialise(NULL)) || (cli_set_port(c, smb_port) == 0) || !cli_connect(c, server_n, &ip)) { - fprintf(stderr,"Connection to %s failed\n", server_n); + DEBUG(0,("%d: Connection to %s failed\n", getpid(), server_n)); + if (c) { + cli_shutdown(c); + free(c); + } return NULL; } if (!cli_session_request(c, &calling, &called)) { - fprintf(stderr, "session request to %s failed\n", called.name); + char *p; + DEBUG(0,("%d: session request to %s failed (%s)\n", + getpid(), called.name, cli_errstr(c))); cli_shutdown(c); + free(c); + if ((p=strchr(called.name, '.'))) { + *p = 0; + goto again; + } if (strcmp(called.name, "*SMBSERVER")) { make_nmb_name(&called , "*SMBSERVER", 0x20); goto again; @@ -165,11 +171,12 @@ static struct cli_state *do_connection(char *service) return NULL; } - DEBUG(4,(" session request ok\n")); + DEBUG(4,("%d: session request ok\n", getpid())); if (!cli_negprot(c)) { - fprintf(stderr, "protocol negotiation failed\n"); + DEBUG(0,("%d: protocol negotiation failed\n", getpid())); cli_shutdown(c); + free(c); return NULL; } @@ -184,20 +191,25 @@ static struct cli_state *do_connection(char *service) password, strlen(password), password, strlen(password), workgroup)) { - fprintf(stderr, "session setup failed: %s\n", cli_errstr(c)); + DEBUG(0,("%d: session setup failed: %s\n", + getpid(), cli_errstr(c))); + cli_shutdown(c); + free(c); return NULL; } - DEBUG(4,(" session setup ok\n")); + DEBUG(4,("%d: session setup ok\n", getpid())); if (!cli_send_tconX(c, share, "?????", password, strlen(password)+1)) { - fprintf(stderr,"tree connect failed: %s\n", cli_errstr(c)); + DEBUG(0,("%d: tree connect failed: %s\n", + getpid(), cli_errstr(c))); cli_shutdown(c); + free(c); return NULL; } - DEBUG(4,(" tconx ok\n")); + DEBUG(4,("%d: tconx ok\n", getpid())); got_pass = True; @@ -226,29 +238,29 @@ static void smb_umount(char *mount_point) the lights to exit anyways... */ if (umount(mount_point) != 0) { - fprintf(stderr, "Could not umount %s: %s\n", - mount_point, strerror(errno)); + DEBUG(0,("%d: Could not umount %s: %s\n", + getpid(), mount_point, strerror(errno))); return; } if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) { - fprintf(stderr, "Can't get "MOUNTED"~ lock file"); + DEBUG(0,("%d: Can't get "MOUNTED"~ lock file", getpid())); return; } close(fd); if ((mtab = setmntent(MOUNTED, "r")) == NULL) { - fprintf(stderr, "Can't open " MOUNTED ": %s\n", - strerror(errno)); + DEBUG(0,("%d: Can't open " MOUNTED ": %s\n", + getpid(), strerror(errno))); return; } #define MOUNTED_TMP MOUNTED".tmp" if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) { - fprintf(stderr, "Can't open " MOUNTED_TMP ": %s\n", - strerror(errno)); + DEBUG(0,("%d: Can't open " MOUNTED_TMP ": %s\n", + getpid(), strerror(errno))); endmntent(mtab); return; } @@ -262,21 +274,21 @@ static void smb_umount(char *mount_point) endmntent(mtab); if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { - fprintf(stderr, "Error changing mode of %s: %s\n", - MOUNTED_TMP, strerror(errno)); + DEBUG(0,("%d: Error changing mode of %s: %s\n", + getpid(), MOUNTED_TMP, strerror(errno))); return; } endmntent(new_mtab); if (rename(MOUNTED_TMP, MOUNTED) < 0) { - fprintf(stderr, "Cannot rename %s to %s: %s\n", - MOUNTED, MOUNTED_TMP, strerror(errno)); + DEBUG(0,("%d: Cannot rename %s to %s: %s\n", + getpid(), MOUNTED, MOUNTED_TMP, strerror(errno))); return; } if (unlink(MOUNTED"~") == -1) { - fprintf(stderr, "Can't remove "MOUNTED"~"); + DEBUG(0,("%d: Can't remove "MOUNTED"~", getpid())); return; } } @@ -298,9 +310,10 @@ static void send_fs_socket(char *service, char *mount_point, struct cli_state *c while (1) { if ((fd = open(mount_point, O_RDONLY)) < 0) { - fprintf(stderr, "mount.smbfs: can't open %s\n", mount_point); + DEBUG(0,("mount.smbfs[%d]: can't open %s\n", + getpid(), mount_point)); break; - } + } conn_options.fd = c->fd; conn_options.protocol = c->protocol; @@ -317,7 +330,9 @@ static void send_fs_socket(char *service, char *mount_point, struct cli_state *c res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options); if (res != 0) { - fprintf(stderr, "mount.smbfs: ioctl failed, res=%d\n", res); + DEBUG(0,("mount.smbfs[%d]: ioctl failed, res=%d\n", + getpid(), res)); + close(fd); break; } @@ -332,27 +347,50 @@ static void send_fs_socket(char *service, char *mount_point, struct cli_state *c close(fd); -#ifndef SMBFS_DEBUG - /* Close all open files if we haven't done so yet. */ + /* This looks wierd but we are only closing the userspace + side, the connection has already been passed to smbfs and + it has increased the usage count on the socket. + + If we don't do this we will "leak" sockets and memory on + each reconnection we have to make. */ + cli_shutdown(c); + free(c); + c = NULL; + if (!closed) { - extern FILE *dbf; + /* redirect stdout & stderr since we can't know that + the library functions we use are using DEBUG. */ + if ( (fd = open("/dev/null", O_WRONLY)) < 0) + DEBUG(2,("mount.smbfs: can't open /dev/null\n")); + close_our_files(fd); + if (fd >= 0) { + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + close(fd); + } + + /* here we are no longer interactive */ + pstrcpy(remote_machine, "smbmount"); /* sneaky ... */ + setup_logging("mount.smbfs", False); + append_log = True; + reopen_logs(); + DEBUG(0, ("mount.smbfs: entering daemon mode for service %s, pid=%d\n", service, getpid())); + closed = 1; - dbf = NULL; - close_our_files(c?c->fd:-1); } -#endif - /* Wait for a signal from smbfs ... */ - CatchSignal(SIGUSR1, &usr1_handler); - pause(); -#ifdef SMBFS_DEBUG - DEBUG(2,("mount.smbfs: got signal, getting new socket\n")); -#endif - c = do_connection(service); + /* Wait for a signal from smbfs ... but don't continue + until we actually get a new connection. */ + while (!c) { + CatchSignal(SIGUSR1, &usr1_handler); + pause(); + DEBUG(2,("mount.smbfs[%d]: got signal, getting new socket\n", getpid())); + c = do_connection(service); + } } smb_umount(mount_point); - DEBUG(2,("mount.smbfs: exit\n")); + DEBUG(2,("mount.smbfs[%d]: exit\n", getpid())); exit(1); } @@ -436,6 +474,10 @@ static void init_mount(void) args[i++] = "-d"; args[i++] = xstrdup(tmp); } + if (options) { + args[i++] = "-o"; + args[i++] = options; + } if (sys_fork() == 0) { if (file_exist(BINDIR "/smbmnt", NULL)) { @@ -452,10 +494,12 @@ static void init_mount(void) fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) ); /* FIXME: do some proper error handling */ exit(1); - } + } if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status)); + /* FIXME: do some proper error handling */ + exit(1); } /* Ok... This is the rubicon for that mount point... At any point @@ -468,6 +512,123 @@ static void init_mount(void) /**************************************************************************** +get a password from a a file or file descriptor +exit on failure (from smbclient, move to libsmb or shared .c file?) +****************************************************************************/ +static void get_password_file(void) +{ + int fd = -1; + char *p; + BOOL close_it = False; + pstring spec; + char pass[128]; + + if ((p = getenv("PASSWD_FD")) != NULL) { + pstrcpy(spec, "descriptor "); + pstrcat(spec, p); + sscanf(p, "%d", &fd); + close_it = False; + } else if ((p = getenv("PASSWD_FILE")) != NULL) { + fd = sys_open(p, O_RDONLY, 0); + pstrcpy(spec, p); + if (fd < 0) { + fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", + spec, strerror(errno)); + exit(1); + } + close_it = True; + } + + for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ + p && p - pass < sizeof(pass);) { + switch (read(fd, p, 1)) { + case 1: + if (*p != '\n' && *p != '\0') { + *++p = '\0'; /* advance p, and null-terminate pass */ + break; + } + case 0: + if (p - pass) { + *p = '\0'; /* null-terminate it, just in case... */ + p = NULL; /* then force the loop condition to become false */ + break; + } else { + fprintf(stderr, "Error reading password from file %s: %s\n", + spec, "empty password\n"); + exit(1); + } + + default: + fprintf(stderr, "Error reading password from file %s: %s\n", + spec, strerror(errno)); + exit(1); + } + } + pstrcpy(password, pass); + if (close_it) + close(fd); +} + +/**************************************************************************** +get username and password from a credentials file +exit on failure (from smbclient, move to libsmb or shared .c file?) +****************************************************************************/ +static void read_credentials_file(char *filename) +{ + FILE *auth; + fstring buf; + uint16 len = 0; + char *ptr, *val, *param; + + if ((auth=sys_fopen(filename, "r")) == NULL) + { + /* fail if we can't open the credentials file */ + DEBUG(0,("ERROR: Unable to open credentials file!\n")); + exit (-1); + } + + while (!feof(auth)) + { + /* get a line from the file */ + if (!fgets (buf, sizeof(buf), auth)) + continue; + len = strlen(buf); + + if ((len) && (buf[len-1]=='\n')) + { + buf[len-1] = '\0'; + len--; + } + if (len == 0) + continue; + + /* break up the line into parameter & value. + will need to eat a little whitespace possibly */ + param = buf; + if (!(ptr = strchr (buf, '='))) + continue; + val = ptr+1; + *ptr = '\0'; + + /* eat leading white space */ + while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) + val++; + + if (strwicmp("password", param) == 0) + { + pstrcpy(password, val); + got_pass = True; + } + else if (strwicmp("username", param) == 0) + pstrcpy(username, val); + + memset(buf, 0, sizeof(buf)); + } + fclose(auth); +} + + +/**************************************************************************** usage on the program ****************************************************************************/ static void usage(void) @@ -491,6 +652,7 @@ static void usage(void) workgroup=<arg> workgroup on destination sockopt=<arg> TCP socket options scope=<arg> NetBIOS scope + credentials=<filename> file with username/password guest don't prompt for a password ro mount read-only rw mount read-write @@ -517,6 +679,7 @@ static void parse_mount_smb(int argc, char **argv) extern char *optarg; int val; extern pstring global_scope; + char *p; if (argc < 2 || argv[1][0] == '-') { usage(); @@ -537,6 +700,9 @@ static void parse_mount_smb(int argc, char **argv) return; } + options[0] = 0; + p = options; + /* * option parsing from nfsmount.c (util-linux-2.9u) */ @@ -565,6 +731,8 @@ static void parse_mount_smb(int argc, char **argv) pstrcpy(password,opteq+1); got_pass = True; memset(opteq+1,'X',strlen(password)); + } else if(!strcmp(opts, "credentials")) { + pstrcpy(credentials,opteq+1); } else if(!strcmp(opts, "netbiosname")) { pstrcpy(my_netbios_name,opteq+1); } else if(!strcmp(opts, "uid")) { @@ -593,8 +761,8 @@ static void parse_mount_smb(int argc, char **argv) } else if(!strcmp(opts, "scope")) { pstrcpy(global_scope,opteq+1); } else { - usage(); - exit(1); + slprintf(p, sizeof(pstring) - (p - options) - 1, "%s=%s,", opts, opteq+1); + p += strlen(p); } } else { val = 1; @@ -607,6 +775,11 @@ static void parse_mount_smb(int argc, char **argv) mount_ro = 0; } else if(!strcmp(opts, "ro")) { mount_ro = 1; + } else { + strncpy(p, opts, sizeof(pstring) - (p - options) - 1); + p += strlen(opts); + *p++ = ','; + *p = 0; } } } @@ -615,6 +788,11 @@ static void parse_mount_smb(int argc, char **argv) usage(); exit(1); } + + if (p != options) { + *(p-1) = 0; /* remove trailing , */ + DEBUG(3,("passthrough options '%s'\n", options)); + } } /**************************************************************************** @@ -628,7 +806,8 @@ static void parse_mount_smb(int argc, char **argv) char *p; DEBUGLEVEL = 1; - + + /* here we are interactive, even if run from autofs */ setup_logging("mount.smbfs",True); TimeInit(); @@ -643,26 +822,38 @@ static void parse_mount_smb(int argc, char **argv) *p = 0; pstrcpy(password,p+1); got_pass = True; + memset(strchr(getenv("USER"),'%')+1,'X',strlen(password)); } + strupper(username); } if (getenv("PASSWD")) { pstrcpy(password,getenv("PASSWD")); + got_pass = True; + } + + if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { + get_password_file(); + got_pass = True; } if (*username == 0 && getenv("LOGNAME")) { pstrcpy(username,getenv("LOGNAME")); } - parse_mount_smb(argc, argv); - - DEBUG(3,("mount.smbfs started (version %s)\n", VERSION)); - if (!lp_load(servicesf,True,False,False)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); } + parse_mount_smb(argc, argv); + + if (*credentials != 0) { + read_credentials_file(credentials); + } + + DEBUG(3,("mount.smbfs started (version %s)\n", VERSION)); + codepage_initialise(lp_client_code_page()); if (*workgroup == 0) { |