From 7364b73e80d21b4671d696da8b05e451659f46e4 Mon Sep 17 00:00:00 2001 From: mssalvatore Date: Mon, 8 Apr 2019 16:50:10 -0400 Subject: Gracefully handle multiple spaces in ssh_command option (#169) When using the "ssh_command" option, commands with multiple spaces in a row will not be properly parsed. Example: Properly parsed: ssh_command = "ssh -o IdentityFile=~/.ssh/id_rsa" Improperly parsed: ssh_command = "ssh -o IdentityFile=~/.ssh/id_rsa" This commit changes the ssh_command parsing logic so that both of the above examples are considered valid and properly handled. Fixes: #114. --- ChangeLog.rst | 1 + sshfs.c | 78 +++++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/ChangeLog.rst b/ChangeLog.rst index 7e88754..c5468b4 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -2,6 +2,7 @@ Unreleased Changes ------------------ * Fixed "-o idmap=user" to map both UID and GID on all OSs. +* Fixed improper handling of sequential spaces spaces in "ssh_command" option Release 3.5.1 (2018-12-22) -------------------------- diff --git a/sshfs.c b/sshfs.c index 6919515..06a1ef3 100644 --- a/sshfs.c +++ b/sshfs.c @@ -3596,40 +3596,60 @@ static int read_password(void) return 0; } +// Behaves similarly to strtok(), but allows for the ' ' delimiter to be escaped +// by '\ '. +static char *tokenize_on_space(char *str) +{ + static char *pos = NULL; + char *start = NULL; + + if (str) + pos = str; + + if (!pos) + return NULL; + + // trim any leading spaces + while (*pos == ' ') + pos++; + + start = pos; + + while (pos && *pos != '\0') { + // break on space, but not on '\ ' + if (*pos == ' ' && *(pos - 1) != '\\') { + break; + } + pos++; + } + + if (*pos == '\0') { + pos = NULL; + } + else { + *pos = '\0'; + pos++; + } + + return start; +} + static void set_ssh_command(void) { - char *s; - char *d; + char *token = NULL; int i = 0; - int end = 0; - - d = sshfs.ssh_command; - s = sshfs.ssh_command; - while (!end) { - switch (*s) { - case '\0': - end = 1; - case ' ': - *d = '\0'; - if (i == 0) { - replace_arg(&sshfs.ssh_args.argv[0], - sshfs.ssh_command); - } else { - if (fuse_opt_insert_arg(&sshfs.ssh_args, i, - sshfs.ssh_command) == -1) - _exit(1); - } - i++; - d = sshfs.ssh_command; - break; - case '\\': - if (s[1]) - s++; - default: - *d++ = *s; + token = tokenize_on_space(sshfs.ssh_command); + while (token != NULL) { + if (i == 0) { + replace_arg(&sshfs.ssh_args.argv[0], token); + } else { + if (fuse_opt_insert_arg(&sshfs.ssh_args, i, token) == -1) + _exit(1); } - s++; + i++; + + token = tokenize_on_space(NULL); } } -- cgit v1.2.3