vssh: keyfile use cleanups
No binary (build failed)
—
(log yok)
| @@ -681,8 +681,8 @@ static bool ssh_config_matches(struct connectdata *one, | |
| sshc1 = Curl_conn_meta_get(one, CURL_META_SSH_CONN); | |
| sshc2 = Curl_conn_meta_get(two, CURL_META_SSH_CONN); | |
| - | return sshc1 && sshc2 && Curl_safecmp(sshc1->rsa, sshc2->rsa) && |
| - | Curl_safecmp(sshc1->rsa_pub, sshc2->rsa_pub); |
| + | return sshc1 && sshc2 && Curl_safecmp(sshc1->priv_key, sshc2->priv_key) && |
| + | Curl_safecmp(sshc1->pub_key, sshc2->pub_key); |
| } | |
| #endif | |
| @@ -832,8 +832,7 @@ static int myssh_in_AUTHLIST(struct Curl_easy *data, | |
| /* For public key auth we need either the private key or | |
| CURLSSH_AUTH_AGENT. */ | |
| if((sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) && | |
| - | (data->set.str[STRING_SSH_PRIVATE_KEY] || |
| - | (data->set.ssh_auth_types & CURLSSH_AUTH_AGENT))) { |
| + | (sshc->priv_key || (data->set.ssh_auth_types & CURLSSH_AUTH_AGENT))) { |
| myssh_to(data, sshc, SSH_AUTH_PKEY_INIT); | |
| infof(data, "Authentication using SSH public key file"); | |
| } | |
| @@ -863,7 +862,7 @@ static int myssh_in_AUTH_PKEY_INIT(struct Curl_easy *data, | |
| /* Two choices, (1) private key was given on CMD, | |
| * (2) use the "default" keys. */ | |
| - | if(data->set.str[STRING_SSH_PRIVATE_KEY]) { |
| + | if(sshc->priv_key) { |
| if(sshc->pubkey && !data->set.ssl.primary.key_passwd) { | |
| rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL, sshc->pubkey); | |
| if(rc == SSH_AUTH_AGAIN) | |
| @@ -875,13 +874,11 @@ static int myssh_in_AUTH_PKEY_INIT(struct Curl_easy *data, | |
| } | |
| } | |
| - | rc = ssh_pki_import_privkey_file(data-> |
| - | set.str[STRING_SSH_PRIVATE_KEY], |
| + | rc = ssh_pki_import_privkey_file(sshc->priv_key, |
| data->set.ssl.primary.key_passwd, NULL, | |
| NULL, &sshc->privkey); | |
| if(rc != SSH_OK) { | |
| - | failf(data, "Could not load private key file %s", |
| - | data->set.str[STRING_SSH_PRIVATE_KEY]); |
| + | failf(data, "Could not load private key file %s", sshc->priv_key); |
| rc = myssh_to_ERROR(data, sshc, CURLE_LOGIN_DENIED); | |
| return rc; | |
| } | |
| @@ -1916,8 +1913,8 @@ static void sshc_cleanup(struct ssh_conn *sshc) | |
| sshc->pubkey = NULL; | |
| } | |
| - | curlx_safefree(sshc->rsa_pub); |
| - | curlx_safefree(sshc->rsa); |
| + | curlx_safefree(sshc->pub_key); |
| + | curlx_safefree(sshc->priv_key); |
| curlx_safefree(sshc->quote_path1); | |
| curlx_safefree(sshc->quote_path2); | |
| curlx_dyn_free(&sshc->readdir_buf); | |
| @@ -2547,7 +2544,7 @@ static CURLcode myssh_setup_connection(struct Curl_easy *data, | |
| Curl_meta_set(data, CURL_META_SSH_EASY, sshp, myssh_easy_dtor)) | |
| return CURLE_OUT_OF_MEMORY; | |
| - | return CURLE_OK; |
| + | return Curl_ssh_setup_pkey(data, sshc); |
| } | |
| static Curl_recv scp_recv, sftp_recv; | |
| @@ -2655,9 +2652,8 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done) | |
| sshc->privkey = NULL; | |
| sshc->pubkey = NULL; | |
| - | if(data->set.str[STRING_SSH_PUBLIC_KEY]) { |
| - | rc = ssh_pki_import_pubkey_file(data->set.str[STRING_SSH_PUBLIC_KEY], |
| - | &sshc->pubkey); |
| + | if(sshc->pub_key) { |
| + | rc = ssh_pki_import_pubkey_file(sshc->pub_key, &sshc->pubkey); |
| if(rc != SSH_OK) { | |
| failf(data, "Could not load public key file"); | |
| return CURLE_FAILED_INIT; | |
| @@ -1094,8 +1094,7 @@ static CURLcode sftp_upload_init(struct Curl_easy *data, | |
| return CURLE_OK; | |
| } | |
| - | static CURLcode ssh_state_pkey_init(struct Curl_easy *data, |
| - | struct ssh_conn *sshc) |
| + | static void ssh_state_pkey_init(struct Curl_easy *data, struct ssh_conn *sshc) |
| { | |
| /* | |
| * Check the supported auth types in the order I feel is most secure | |
| @@ -1105,88 +1104,13 @@ static CURLcode ssh_state_pkey_init(struct Curl_easy *data, | |
| if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) && | |
| strstr(sshc->authlist, "publickey")) { | |
| - | bool out_of_memory = FALSE; |
| - | |
| - | sshc->rsa_pub = sshc->rsa = NULL; |
| - | |
| - | if(data->set.str[STRING_SSH_PRIVATE_KEY]) { |
| - | sshc->rsa = curlx_strdup(data->set.str[STRING_SSH_PRIVATE_KEY]); |
| - | if(!sshc->rsa) |
| - | out_of_memory = TRUE; |
| - | } |
| - | else { |
| - | /* To ponder about: should really the lib be messing about with the |
| - | HOME environment variable etc? */ |
| - | char *home = curl_getenv("HOME"); |
| - | curlx_struct_stat sbuf; |
| - | |
| - | /* If no private key file is specified, try some common paths. */ |
| - | if(home) { |
| - | /* Try ~/.ssh first. */ |
| - | sshc->rsa = curl_maprintf("%s/.ssh/id_rsa", home); |
| - | if(!sshc->rsa) |
| - | out_of_memory = TRUE; |
| - | else if(curlx_stat(sshc->rsa, &sbuf)) { |
| - | curlx_free(sshc->rsa); |
| - | sshc->rsa = curl_maprintf("%s/.ssh/id_dsa", home); |
| - | if(!sshc->rsa) |
| - | out_of_memory = TRUE; |
| - | else if(curlx_stat(sshc->rsa, &sbuf)) { |
| - | curlx_safefree(sshc->rsa); |
| - | } |
| - | } |
| - | curlx_free(home); |
| - | } |
| - | if(!out_of_memory && !sshc->rsa) { |
| - | /* Nothing found; try the current dir. */ |
| - | sshc->rsa = curlx_strdup("id_rsa"); |
| - | if(sshc->rsa && curlx_stat(sshc->rsa, &sbuf)) { |
| - | curlx_free(sshc->rsa); |
| - | sshc->rsa = curlx_strdup("id_dsa"); |
| - | if(sshc->rsa && curlx_stat(sshc->rsa, &sbuf)) { |
| - | curlx_free(sshc->rsa); |
| - | /* Out of guesses. Set to the empty string to avoid |
| - | * surprising info messages. */ |
| - | sshc->rsa = curlx_strdup(""); |
| - | } |
| - | } |
| - | } |
| - | } |
| - | |
| - | /* |
| - | * Unless the user explicitly specifies a public key file, let |
| - | * libssh2 extract the public key from the private key file. |
| - | * This is done by passing sshc->rsa_pub = NULL. |
| - | */ |
| - | if(!out_of_memory && data->set.str[STRING_SSH_PUBLIC_KEY] && |
| - | /* treat empty string the same way as NULL */ |
| - | data->set.str[STRING_SSH_PUBLIC_KEY][0]) { |
| - | sshc->rsa_pub = curlx_strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); |
| - | if(!sshc->rsa_pub) |
| - | out_of_memory = TRUE; |
| - | } |
| - | |
| - | if(out_of_memory || !sshc->rsa) { |
| - | curlx_safefree(sshc->rsa); |
| - | curlx_safefree(sshc->rsa_pub); |
| - | myssh_to(data, sshc, SSH_SESSION_FREE); |
| - | return CURLE_OUT_OF_MEMORY; |
| - | } |
| - | |
| - | sshc->passphrase = data->set.ssl.primary.key_passwd; |
| - | if(!sshc->passphrase) |
| - | sshc->passphrase = ""; |
| - | |
| - | if(sshc->rsa_pub) |
| - | infof(data, "SSH: trying public key file '%s'", sshc->rsa_pub); |
| - | infof(data, "SSH: trying private key file '%s'", sshc->rsa); |
| - | |
| + | if(sshc->pub_key) |
| + | infof(data, "SSH: trying public key file '%s'", sshc->pub_key); |
| + | infof(data, "SSH: trying private key file '%s'", sshc->priv_key); |
| myssh_to(data, sshc, SSH_AUTH_PKEY); | |
| } | |
| - | else { |
| + | else |
| myssh_to(data, sshc, SSH_AUTH_PASS_INIT); | |
| - | } |
| - | return CURLE_OK; |
| } | |
| static CURLcode sftp_quote_stat(struct Curl_easy *data, | |
| @@ -1559,14 +1483,11 @@ static CURLcode ssh_state_auth_pkey(struct Curl_easy *data, | |
| libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session, | |
| user, | |
| curlx_uztoui(strlen(user)), | |
| - | sshc->rsa_pub, |
| - | sshc->rsa, sshc->passphrase); |
| + | sshc->pub_key, |
| + | sshc->priv_key, sshc->passphrase); |
| if(rc == LIBSSH2_ERROR_EAGAIN) | |
| return CURLE_AGAIN; | |
| - | curlx_safefree(sshc->rsa_pub); |
| - | curlx_safefree(sshc->rsa); |
| - | |
| if(rc == 0) { | |
| sshc->authed = TRUE; | |
| infof(data, "SSH: authenticated via publickey"); | |
| @@ -2626,8 +2547,8 @@ static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, | |
| DEBUGASSERT(!sshc->kh); | |
| DEBUGASSERT(!sshc->ssh_agent); | |
| - | curlx_safefree(sshc->rsa_pub); |
| - | curlx_safefree(sshc->rsa); |
| + | curlx_safefree(sshc->pub_key); |
| + | curlx_safefree(sshc->priv_key); |
| curlx_safefree(sshc->quote_path1); | |
| curlx_safefree(sshc->quote_path2); | |
| curlx_safefree(sshc->homedir); | |
| @@ -2968,7 +2889,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, | |
| break; | |
| case SSH_AUTH_PKEY_INIT: | |
| - | result = ssh_state_pkey_init(data, sshc); |
| + | ssh_state_pkey_init(data, sshc); |
| break; | |
| case SSH_AUTH_PKEY: | |
| @@ -3343,7 +3264,7 @@ static CURLcode ssh_setup_connection(struct Curl_easy *data, | |
| if(Curl_meta_set(data, CURL_META_SSH_EASY, sshp, myssh_easy_dtor)) | |
| return CURLE_OUT_OF_MEMORY; | |
| - | return CURLE_OK; |
| + | return Curl_ssh_setup_pkey(data, sshc); |
| } | |
| static Curl_recv scp_recv, sftp_recv; | |
| @@ -144,8 +144,8 @@ struct ssh_conn { | |
| /* common */ | |
| const char *passphrase; /* pass-phrase to use */ | |
| - | char *rsa_pub; /* strdup'ed public key file */ |
| - | char *rsa; /* strdup'ed private key file */ |
| + | char *pub_key; /* strdup'ed public key file */ |
| + | char *priv_key; /* strdup'ed private key file */ |
| sshstate state; /* always use ssh.c:state() to change state! */ | |
| sshstate nextstate; /* the state to goto after stopping */ | |
| struct curl_slist *quote_item; /* for the quote option */ | |
| @@ -32,6 +32,7 @@ | |
| #include "escape.h" | |
| #include "select.h" /* for Curl_pollset_change() */ | |
| #include "url.h" /* for Curl_conn_meta_get() */ | |
| + | #include "curlx/fopen.h" |
| #ifdef CURLVERBOSE | |
| const char *Curl_ssh_statename(sshstate state) | |
| @@ -361,4 +362,87 @@ CURLcode Curl_ssh_pollset(struct Curl_easy *data, struct easy_pollset *ps) | |
| return CURLE_OK; | |
| } | |
| + | CURLcode Curl_ssh_setup_pkey(struct Curl_easy *data, struct ssh_conn *sshc) |
| + | { |
| + | char *home = NULL; |
| + | if(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) { |
| + | sshc->pub_key = sshc->priv_key = NULL; |
| + | |
| + | if(data->set.str[STRING_SSH_PRIVATE_KEY]) { |
| + | sshc->priv_key = curlx_strdup(data->set.str[STRING_SSH_PRIVATE_KEY]); |
| + | if(!sshc->priv_key) |
| + | goto fail; |
| + | } |
| + | else { |
| + | /* To ponder about: should really the lib be messing about with the HOME |
| + | environment variable etc? */ |
| + | curlx_struct_stat sbuf; |
| + | home = curl_getenv("HOME"); |
| + | |
| + | /* If no private key file is specified, try some common paths. */ |
| + | if(home) { |
| + | /* Try ~/.ssh first. */ |
| + | sshc->priv_key = curl_maprintf("%s/.ssh/id_rsa", home); |
| + | if(!sshc->priv_key) |
| + | goto fail; |
| + | else if(curlx_stat(sshc->priv_key, &sbuf)) { |
| + | curlx_free(sshc->priv_key); |
| + | sshc->priv_key = curl_maprintf("%s/.ssh/id_dsa", home); |
| + | if(!sshc->priv_key) |
| + | goto fail; |
| + | else if(curlx_stat(sshc->priv_key, &sbuf)) { |
| + | curlx_safefree(sshc->priv_key); |
| + | } |
| + | } |
| + | curlx_safefree(home); |
| + | } |
| + | if(!sshc->priv_key) { |
| + | /* Nothing found; try the current dir. */ |
| + | sshc->priv_key = curlx_strdup("id_rsa"); |
| + | if(sshc->priv_key && curlx_stat(sshc->priv_key, &sbuf)) { |
| + | curlx_free(sshc->priv_key); |
| + | sshc->priv_key = curlx_strdup("id_dsa"); |
| + | if(sshc->priv_key && curlx_stat(sshc->priv_key, &sbuf)) { |
| + | curlx_free(sshc->priv_key); |
| + | /* Out of guesses. Set to the empty string to avoid |
| + | * surprising info messages. */ |
| + | sshc->priv_key = curlx_strdup(""); |
| + | } |
| + | } |
| + | } |
| + | } |
| + | |
| + | /* |
| + | * Unless the user explicitly specifies a public key file, let the SSH |
| + | * library extract the public key from the private key file. This is done |
| + | * by passing sshc->pub_key = NULL. |
| + | */ |
| + | if(data->set.str[STRING_SSH_PUBLIC_KEY] && |
| + | /* treat empty string the same way as NULL */ |
| + | data->set.str[STRING_SSH_PUBLIC_KEY][0]) { |
| + | sshc->pub_key = curlx_strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); |
| + | if(!sshc->pub_key) |
| + | goto fail; |
| + | } |
| + | |
| + | sshc->passphrase = data->set.ssl.primary.key_passwd; |
| + | if(!sshc->passphrase) |
| + | sshc->passphrase = ""; |
| + | |
| + | if(sshc->pub_key) |
| + | infof(data, "SSH: public key file '%s'", sshc->pub_key); |
| + | if(sshc->priv_key) |
| + | infof(data, "SSH: private key file '%s'", sshc->priv_key); |
| + | else |
| + | infof(data, "SSH: public key auth without private key set!"); |
| + | } |
| + | return CURLE_OK; |
| + | |
| + | fail: |
| + | curlx_safefree(home); |
| + | curlx_safefree(sshc->priv_key); |
| + | curlx_safefree(sshc->pub_key); |
| + | return CURLE_OUT_OF_MEMORY; |
| + | } |
| + | |
| #endif /* USE_SSH */ | |
| @@ -29,6 +29,8 @@ | |
| #include "urldata.h" | |
| + | struct ssh_conn; |
| + | |
| CURLcode Curl_getworkingpath(struct Curl_easy *data, | |
| const char *homedir, | |
| char **path); | |
| @@ -40,5 +42,7 @@ CURLcode Curl_ssh_range(struct Curl_easy *data, | |
| curl_off_t *startp, curl_off_t *sizep); | |
| CURLcode Curl_ssh_pollset(struct Curl_easy *data, struct easy_pollset *ps); | |
| + | CURLcode Curl_ssh_setup_pkey(struct Curl_easy *data, struct ssh_conn *sshc); |
| + | |
| #endif /* USE_SSH */ | |
| #endif /* HEADER_CURL_VSSH_VSSH_H */ | |