aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--Makefile.am2
-rw-r--r--README4
-rw-r--r--opts.c99
-rw-r--r--opts.h16
-rw-r--r--sshfs.c120
6 files changed, 216 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index e5a92dc..b014217 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
2005-02-08 Miklos Szeredi <miklos@szeredi.hu>
* Add caching of symlinks
+
+ * Add support for many ssh options to be passed to ssh
+
+ * Port number can now actually be specified with "-o port=PORT",
+ bug spotted by Nadia Maksymiw
2005-02-07 Miklos Szeredi <miklos@szeredi.hu>
diff --git a/Makefile.am b/Makefile.am
index 1c894e5..fe3b4a3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
## Process this file with automake to produce Makefile.in
bin_PROGRAMS = sshfs
-sshfs_SOURCES = sshfs.c cache.c
+sshfs_SOURCES = sshfs.c cache.c opts.c
sshfs_CPPFLAGS = -DFUSE_USE_VERSION=22
diff --git a/README b/README
index fd2bad0..498f836 100644
--- a/README
+++ b/README
@@ -36,6 +36,10 @@ for it (actually it just runs ssh which ask for the password if
needed). You can also specify a directory after the ":". The default
is the home directory.
+Also many ssh options can be specified (see the manual pages for
+sftp(1) and ssh_config(5)), including the remote port number
+('-oport=PORT')
+
Installing
==========
diff --git a/opts.c b/opts.c
new file mode 100644
index 0000000..3976d3a
--- /dev/null
+++ b/opts.c
@@ -0,0 +1,99 @@
+/*
+ Mount option parsing
+ Copyright (C) 2004 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include "opts.h"
+#include <string.h>
+#include <stdlib.h>
+
+static int process_option(char *arg, struct opt opts[], int case_sensitive)
+{
+ int i;
+ char *eq = strchr(arg, '=');
+ if (eq)
+ *eq = '\0';
+
+ for (i = 0; opts[i].optname != NULL; i++) {
+ if (case_sensitive) {
+ if (strcmp(opts[i].optname, arg) == 0)
+ break;
+ } else if (strcasecmp(opts[i].optname, arg) == 0)
+ break;
+ }
+ if (opts[i].optname == NULL) {
+ if (eq)
+ *eq = '=';
+ return 0;
+ }
+ opts[i].present = 1;
+ if (eq) {
+ if (opts[i].value)
+ free(opts[i].value);
+ opts[i].value = strdup(eq+1);
+ }
+ return 1;
+}
+
+static int process_option_group(char *arg, struct opt opts[],
+ int case_sensitive)
+{
+ int remove = 1;
+ char *prevcomma = NULL;
+ while (1) {
+ int remove_one;
+ char *comma = strchr(arg, ',');
+ if (comma)
+ *comma = '\0';
+ remove_one = process_option(arg, opts, case_sensitive);
+ if (remove_one) {
+ if (comma)
+ memmove(arg, comma + 1, strlen(comma + 1));
+ } else {
+ remove = 0;
+ if (comma)
+ arg = comma + 1;
+ }
+ if (!remove_one && prevcomma)
+ *prevcomma = ',';
+ if (!comma)
+ break;
+ prevcomma = comma;
+ }
+ return remove;
+}
+
+void process_options(int *argcp, char *argv[], struct opt opts[],
+ int case_sensitive)
+{
+ int argctr;
+ int newargctr;
+
+ for (argctr = 1, newargctr = 1; argctr < *argcp; argctr++) {
+ char *arg = argv[argctr];
+ int removed = 0;
+ if (arg[0] == '-' && arg[1] == 'o') {
+ if (arg[2])
+ removed = process_option_group(arg+2, opts, case_sensitive);
+ else {
+ if (argctr + 1 < *argcp) {
+ argctr++;
+ arg = argv[argctr];
+ removed = process_option_group(arg, opts, case_sensitive);
+ if (!removed && argctr != newargctr)
+ argv[newargctr++] = argv[argctr-1];
+ }
+ }
+ }
+ if (!removed) {
+ if(argctr != newargctr)
+ argv[newargctr] = arg;
+ newargctr++;
+ }
+ }
+ *argcp = newargctr;
+}
+
diff --git a/opts.h b/opts.h
new file mode 100644
index 0000000..b5c8729
--- /dev/null
+++ b/opts.h
@@ -0,0 +1,16 @@
+/*
+ Mount option parsing
+ Copyright (C) 2004 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+struct opt {
+ const char *optname;
+ int present;
+ char *value;
+};
+
+void process_options(int *argcp, char *argv[], struct opt opts[],
+ int case_sensitive);
diff --git a/sshfs.c b/sshfs.c
index 9f6a82c..ae65107 100644
--- a/sshfs.c
+++ b/sshfs.c
@@ -23,6 +23,7 @@
#include <glib.h>
#include "cache.h"
+#include "opts.h"
#define SSH_FXP_INIT 1
#define SSH_FXP_VERSION 2
@@ -116,6 +117,60 @@ static GHashTable *reqtab;
static pthread_mutex_t lock;
static int processing_thread_started;
+static struct opt ssh_opts[] = {
+ { .optname = "AddressFamily" },
+ { .optname = "BatchMode" },
+ { .optname = "BindAddress" },
+ { .optname = "ChallengeResponseAuthentication" },
+ { .optname = "CheckHostIP" },
+ { .optname = "Cipher" },
+ { .optname = "Ciphers" },
+ { .optname = "Compression" },
+ { .optname = "CompressionLevel" },
+ { .optname = "ConnectionAttempts" },
+ { .optname = "ConnectionTimeout" },
+ { .optname = "GlobalKnownHostsFile" },
+ { .optname = "GSSAPIAuthentication" },
+ { .optname = "GSSAPIDelegateCredentials" },
+ { .optname = "HostbasedAuthentication" },
+ { .optname = "HostKeyAlgorithms" },
+ { .optname = "HostKeyAlias" },
+ { .optname = "HostName" },
+ { .optname = "IdentityFile" },
+ { .optname = "IdentitiesOnly" },
+ { .optname = "LogLevel" },
+ { .optname = "MACs" },
+ { .optname = "NoHostAuthenticationForLocalhost" },
+ { .optname = "NumberOfPasswordPrompts" },
+ { .optname = "PasswordAuthentication" },
+ { .optname = "Port" },
+ { .optname = "PreferredAuthentications" },
+ { .optname = "Protocol" },
+ { .optname = "ProxyCommand" },
+ { .optname = "PubkeyAuthentication" },
+ { .optname = "RhostsRSAAuthentication" },
+ { .optname = "RSAAuthentication" },
+ { .optname = "ServerAliveInterval" },
+ { .optname = "ServerAliveCountMax" },
+ { .optname = "SmartcardDevice" },
+ { .optname = "StrictHostKeyChecking" },
+ { .optname = "TCPKeepAlive" },
+ { .optname = "UsePrivilegedPort" },
+ { .optname = "UserKnownHostsFile" },
+ { .optname = "VerifyHostKeyDNS" },
+ { .optname = NULL }
+};
+
+enum {
+ SOPT_DIRECTPORT,
+ SOPT_LAST /* Last entry in this list! */
+};
+
+static struct opt sshfs_opts[] = {
+ [SOPT_DIRECTPORT] = { .optname = "directport" },
+ [SOPT_LAST] = { .optname = NULL }
+};
+
#define DEBUG(format, args...) \
do { if (debug) fprintf(stderr, format, args); } while(0)
@@ -400,10 +455,11 @@ static int buf_get_entries(struct buffer *buf, fuse_cache_dirh_t h,
return 0;
}
-static int start_ssh(const char *host, const char *port)
+static int start_ssh(char *host)
{
int inpipe[2];
int outpipe[2];
+ int i;
int pid;
if (pipe(inpipe) == -1 || pipe(outpipe) == -1) {
@@ -418,6 +474,9 @@ static int start_ssh(const char *host, const char *port)
perror("failed to fork");
return -1;
} else if (pid == 0) {
+ int argctr = 0;
+ char *ssh_args[sizeof(ssh_opts)/sizeof(struct opt) + 32];
+
if (dup2(outpipe[0], 0) == -1 || dup2(inpipe[1], 1) == -1) {
perror("failed to redirect input/output");
exit(1);
@@ -426,8 +485,26 @@ static int start_ssh(const char *host, const char *port)
close(inpipe[1]);
close(outpipe[0]);
close(outpipe[1]);
- execlp("ssh", "ssh", "-2", "-x", "-a", "-oClearAllForwardings=yes",
- host, "-s", "sftp", port ? "-p" : NULL, port, NULL);
+
+ ssh_args[argctr++] = "ssh";
+ ssh_args[argctr++] = "-2";
+ ssh_args[argctr++] = "-x";
+ ssh_args[argctr++] = "-a";
+ ssh_args[argctr++] = "-oClearAllForwardings=yes";
+ for (i = 0; ssh_opts[i].optname != NULL; i++) {
+ if (ssh_opts[i].present) {
+ char *val = ssh_opts[i].value;
+ char *sopt = g_strdup_printf("-o%s=%s", ssh_opts[i].optname,
+ val ? val : "");
+ ssh_args[argctr++] = sopt;
+ }
+ }
+ ssh_args[argctr++] = host;
+ ssh_args[argctr++] = "-s";
+ ssh_args[argctr++] = "sftp";
+ ssh_args[argctr++] = NULL;
+
+ execvp("ssh", ssh_args);
exit(1);
}
close(inpipe[1]);
@@ -1080,22 +1157,20 @@ static void usage(const char *progname)
fprintf(stderr,
"usage: %s [user@]host:[dir]] mountpoint [options]\n"
"\n"
- "SSH Options:\n"
- " -p port remote port\n"
- " -c port directly connect to port bypassing ssh\n"
+ "SSHFS Options:\n"
+ " -o directport=PORT directly connect to port bypassing ssh\n"
+ " -o SSHOPT=VAL ssh options (see man ssh_config(5))\n"
"\n", progname);
- fuse_main(2, (char **) fusehelp, NULL);
+ fuse_main(2, (char **) fusehelp, &sshfs_oper.oper);
exit(1);
}
int main(int argc, char *argv[])
{
char *host = NULL;
- char *port = NULL;
char *fsname;
int res;
int argctr;
- int direct = 0;
int newargc = 0;
char **newargv = (char **) malloc((argc + 10) * sizeof(char *));
newargv[newargc++] = argv[0];
@@ -1104,22 +1179,6 @@ int main(int argc, char *argv[])
char *arg = argv[argctr];
if (arg[0] == '-') {
switch (arg[1]) {
- case 'c':
- direct = 1;
- /* fallthrough */
-
- case 'p':
- if (arg[2])
- port = &arg[2];
- else if (argctr + 1 < argc)
- port = argv[++argctr];
- else {
- fprintf(stderr, "missing argument to %s option\n", arg);
- fprintf(stderr, "see `%s -h' for usage\n", argv[0]);
- exit(1);
- }
- break;
-
case 'h':
usage(argv[0]);
break;
@@ -1146,10 +1205,13 @@ int main(int argc, char *argv[])
else
base_path = g_strdup(base_path);
- if (!direct)
- res = start_ssh(host, port);
- else
- res = connect_to(host, port);
+ process_options(&newargc, newargv, sshfs_opts, 1);
+ if (sshfs_opts[SOPT_DIRECTPORT].present)
+ res = connect_to(host, sshfs_opts[SOPT_DIRECTPORT].value);
+ else {
+ process_options(&newargc, newargv, ssh_opts, 0);
+ res = start_ssh(host);
+ }
if (res == -1)
exit(1);