From 0043e870145d167003931cda2fd90b5e13b0b7f8 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Fri, 23 Mar 2007 17:59:40 +0000 Subject: [PATCH] Added --pubkey option to curl and made --key also work for SCP/SFTP, plus made --pass work on an SSH private key as well. --- CHANGES | 4 ++++ RELEASE-NOTES | 4 +++- docs/MANUAL | 11 ++++++++++- docs/curl.1 | 9 +++++++-- docs/libcurl/curl_easy_setopt.3 | 4 +++- lib/ssh.c | 18 ++++++++++++------ src/main.c | 16 ++++++++++++++-- 7 files changed, 53 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 8e1a6c999..dec9678a9 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,10 @@ Changelog +Dan F (23 March 2007) +- Added --pubkey option to curl and made --key also work for SCP/SFTP, + plus made --pass work on an SSH private key as well. + Yang Tse (20 March 2007) - Fixed: When a signal was caught awaiting for an event using Curl_select() or Curl_poll() with a non-zero timeout both functions would restart the diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 20ad3d43a..f3a8cfaa2 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -2,7 +2,7 @@ Curl and libcurl 7.16.2 Public curl release number: 98 Releases counted from the very beginning: 125 - Available command line options: 117 + Available command line options: 118 Available curl_easy_setopt() options: 141 Number of public functions in libcurl: 54 Amount of public web site mirrors: 38 @@ -22,6 +22,8 @@ This release includes the following changes: o includes VC8 Makefiles in the release archive o --ftp-ssl-control is now honoured on ftps:// URLs o added experimental CURL_ACKNOWLEDGE_EINTR symbol definition check + o --key and new --pubkey options for SSH public key file logins + o --pass now works for a SSH public key file, too This release includes the following bugfixes: diff --git a/docs/MANUAL b/docs/MANUAL index dd063911d..d087c3b22 100644 --- a/docs/MANUAL +++ b/docs/MANUAL @@ -7,7 +7,7 @@ LATEST VERSION SIMPLE USAGE - Get the main page from netscape's web-server: + Get the main page from Netscape's web-server: curl http://www.netscape.com/ @@ -39,6 +39,15 @@ SIMPLE USAGE curl --ftp-ssl ftp://files.are.secure.com/secrets.txt + Get a file from an SSH server using SFTP: + + curl -u username sftp://shell.example.com/~/personal.txt + + Get a file from an SSH server using SCP using a private key to authenticate: + + curl -u username: --key ~/.ssh/id_dsa --pubkey ~/.ssh/id_dsa.pub \ + scp://shell.example.com/~/personal.txt + DOWNLOAD TO A FILE diff --git a/docs/curl.1 b/docs/curl.1 index a08432c0b..301461339 100644 --- a/docs/curl.1 +++ b/docs/curl.1 @@ -582,7 +582,7 @@ See this online resource for further details: If this option is used twice, the second time will again disable it. .IP "--key " -(SSL) Private key file name. Allows you to provide your private key in this +(SSL/SSH) Private key file name. Allows you to provide your private key in this separate file. If this option is used several times, the last one will be used. @@ -825,7 +825,7 @@ nothing else. You may use this option as many times as you have number of URLs. .IP "--pass " -(SSL) Pass phrase for the private key +(SSL/SSH) Pass phrase for the private key If this option is used several times, the last one will be used. .IP "--proxy-anyauth" @@ -860,6 +860,11 @@ CONNECT request and requires that the proxy allows direct connect to the remote port number curl wants to tunnel through to. If this option is used twice, the second will again disable proxy tunnel. +.IP "--pubkey " +(SSH) Public key file name. Allows you to provide your public key in this +separate file. + +If this option is used several times, the last one will be used. .IP "-P/--ftp-port
" (FTP) Reverses the initiator/listener roles when connecting with ftp. This switch makes Curl use the PORT command instead of PASV. In practice, PORT diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index ac26b7237..970600859 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -1217,7 +1217,8 @@ engine. You have to set the crypto engine with \fICURLOPT_SSLENGINE\fP. \&"DER" format key file currently does not work because of a bug in OpenSSL. .IP CURLOPT_SSLKEYPASSWD Pass a pointer to a zero terminated string as parameter. It will be used as -the password required to use the \fICURLOPT_SSLKEY\fP private key. +the password required to use the \fICURLOPT_SSLKEY\fP or +\fICURLOPT_SSH_PRIVATE_KEYFILE\fP private key. .IP CURLOPT_SSLENGINE Pass a pointer to a zero terminated string as parameter. It will be used as the identifier for the crypto engine you want to use for your private @@ -1372,6 +1373,7 @@ libcurl defaults to using \fB~/.ssh/id_dsa.pub\fP. .IP CURLOPT_SSH_PRIVATE_KEYFILE Pass a char * pointing to a file name for your private key. If not used, libcurl defaults to using \fB~/.ssh/id_dsa\fP. +If the file is password-protected, set the password with \fICURLOPT_SSLKEYPASSWD\fP. .SH OTHER OPTIONS .IP CURLOPT_PRIVATE Pass a char * as parameter, pointing to data that should be associated with diff --git a/lib/ssh.c b/lib/ssh.c index 0a3ed420d..30cd22508 100644 --- a/lib/ssh.c +++ b/lib/ssh.c @@ -268,9 +268,6 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done) struct SSHPROTO *ssh; const char *fingerprint; const char *authlist; - char *home; - char rsa_pub[PATH_MAX]; - char rsa[PATH_MAX]; char tempHome[PATH_MAX]; curl_socket_t sock; char *real_path; @@ -280,8 +277,6 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done) CURLcode result; struct SessionHandle *data = conn->data; - rsa_pub[0] = rsa[0] = '\0'; - result = ssh_init(conn); if (result) return result; @@ -369,6 +364,13 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done) */ if ((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) && (strstr(authlist, "publickey") != NULL)) { + const char *home; + const char *passphrase; + char rsa_pub[PATH_MAX]; + char rsa[PATH_MAX]; + + rsa_pub[0] = rsa[0] = '\0'; + /* To ponder about: should really the lib be messing about with the HOME environment variable etc? */ home = curl_getenv("HOME"); @@ -383,6 +385,10 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done) else if (home) snprintf(rsa, sizeof(rsa), "%s/.ssh/id_dsa", home); + passphrase = data->set.key_passwd; + if (!passphrase) + passphrase = ""; + curl_free(home); infof(conn->data, "Using ssh public key file %s\n", rsa_pub); @@ -392,7 +398,7 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done) /* The function below checks if the files exists, no need to stat() here. */ if (libssh2_userauth_publickey_fromfile(ssh->ssh_session, ssh->user, - rsa_pub, rsa, "") == 0) { + rsa_pub, rsa, passphrase) == 0) { authed = TRUE; infof(conn->data, "Initialized SSH public key authentication\n"); } diff --git a/src/main.c b/src/main.c index 32bc8a03c..56bc1c7bf 100644 --- a/src/main.c +++ b/src/main.c @@ -389,6 +389,7 @@ struct Configurable { char *key; char *key_type; char *key_passwd; + char *pubkey; char *engine; bool list_engines; bool crlf; @@ -607,9 +608,10 @@ static void help(void) " -e/--referer Referer URL (H)", " -E/--cert Client certificate file and password (SSL)", " --cert-type Certificate file type (DER/PEM/ENG) (SSL)", - " --key Private key file name (SSL)", + " --key Private key file name (SSL/SSH)", " --key-type Private key file type (DER/PEM/ENG) (SSL)", - " --pass Pass phrase for the private key (SSL)", + " --pass Pass phrase for the private key (SSL/SSH)", + " --pubkey Public key file name (SSH)", " --engine Crypto engine to use (SSL). \"--engine list\" for list", " --cacert CA certificate to verify peer against (SSL)", " --capath CA directory (made using c_rehash) to verify", @@ -1505,6 +1507,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ {"Ee","pass", TRUE}, {"Ef","engine", TRUE}, {"Eg","capath ", TRUE}, + {"Eh","pubkey", TRUE}, {"f", "fail", FALSE}, {"F", "form", TRUE}, {"Fs","form-string", TRUE}, @@ -2111,6 +2114,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ /* CA cert directory */ GetStr(&config->capath, nextarg); break; + case 'h': /* --pubkey public key file */ + GetStr(&config->pubkey, nextarg); + break; default: /* certificate file */ { char *ptr = strchr(nextarg, ':'); @@ -3255,6 +3261,8 @@ static void free_config_fields(struct Configurable *config) free(config->key); if (config->key_type) free(config->key_type); + if (config->pubkey) + free(config->pubkey); if (config->referer) free(config->referer); @@ -4112,6 +4120,10 @@ operate(struct Configurable *config, int argc, char *argv[]) my_setopt(curl, CURLOPT_SSLKEYTYPE, config->key_type); my_setopt(curl, CURLOPT_SSLKEYPASSWD, config->key_passwd); + /* SSH private key uses the same command-line option as SSL private key */ + my_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key); + my_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey); + /* default to strict verifyhost */ my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2); if(config->cacert || config->capath) {