summaryrefslogtreecommitdiff
path: root/source3/client
diff options
context:
space:
mode:
Diffstat (limited to 'source3/client')
-rw-r--r--source3/client/smbmount.c301
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) {