int i, nkeys, bloblen;
if (type == SSH_KEYTYPE_SSH1) {
- if (!rsakey_pubblob(&filename, &blob, &bloblen)) {
+ if (!rsakey_pubblob(&filename, &blob, &bloblen, NULL)) {
MessageBox(NULL, "Couldn't load private key.", APPNAME,
MB_OK | MB_ICONERROR);
return;
keylist = get_keylist1();
} else {
unsigned char *blob2;
- blob = ssh2_userkey_loadpub(&filename, NULL, &bloblen);
+ blob = ssh2_userkey_loadpub(&filename, NULL, &bloblen, NULL);
if (!blob) {
MessageBox(NULL, "Couldn't load private key.", APPNAME,
MB_OK | MB_ICONERROR);
} else
*passphrase = '\0';
if (type == SSH_KEYTYPE_SSH1)
- ret = loadrsakey(&filename, rkey, passphrase);
+ ret = loadrsakey(&filename, rkey, passphrase, NULL);
else {
- skey = ssh2_load_userkey(&filename, passphrase);
+ skey = ssh2_load_userkey(&filename, passphrase, NULL);
if (skey == SSH2_WRONG_PASSPHRASE)
ret = -1;
else if (!skey)
/* Load the public half of ssh->cfg.keyfile so we notice if it's in Pageant */
if (!filename_is_null(ssh->cfg.keyfile)) {
if (!rsakey_pubblob(&ssh->cfg.keyfile,
- &s->publickey_blob, &s->publickey_bloblen))
+ &s->publickey_blob, &s->publickey_bloblen, NULL))
s->publickey_blob = NULL;
} else
s->publickey_blob = NULL;
s->tried_publickey = 1;
{
- int ret = loadrsakey(&ssh->cfg.keyfile, &s->key, s->password);
+ const char *error = NULL;
+ int ret = loadrsakey(&ssh->cfg.keyfile, &s->key, s->password,
+ &error);
if (ret == 0) {
c_write_str(ssh, "Couldn't load private key from ");
c_write_str(ssh, filename_to_str(&ssh->cfg.keyfile));
- c_write_str(ssh, ".\r\n");
+ c_write_str(ssh, " (");
+ c_write_str(ssh, error);
+ c_write_str(ssh, ").\r\n");
continue; /* go and try password */
}
if (ret == -1) {
if (keytype == SSH_KEYTYPE_SSH2) {
s->publickey_blob =
ssh2_userkey_loadpub(&ssh->cfg.keyfile, NULL,
- &s->publickey_bloblen);
+ &s->publickey_bloblen, NULL);
} else {
char *msgbuf;
logeventf(ssh, "Unable to use this key file (%s)",
pub_blob =
(unsigned char *)ssh2_userkey_loadpub(&ssh->cfg.keyfile,
&algorithm,
- &pub_blob_len);
+ &pub_blob_len,
+ NULL);
if (pub_blob) {
ssh2_pkt_init(ssh, SSH2_MSG_USERAUTH_REQUEST);
ssh2_pkt_addstring(ssh, s->username);
* We have our passphrase. Now try the actual authentication.
*/
struct ssh2_userkey *key;
+ const char *error = NULL;
- key = ssh2_load_userkey(&ssh->cfg.keyfile, s->password);
+ key = ssh2_load_userkey(&ssh->cfg.keyfile, s->password,
+ &error);
if (key == SSH2_WRONG_PASSPHRASE || key == NULL) {
if (key == SSH2_WRONG_PASSPHRASE) {
c_write_str(ssh, "Wrong passphrase\r\n");
s->tried_pubkey_config = FALSE;
} else {
- c_write_str(ssh, "Unable to load private key\r\n");
+ c_write_str(ssh, "Unable to load private key (");
+ c_write_str(ssh, error);
+ c_write_str(ssh, ")\r\n");
s->tried_pubkey_config = TRUE;
}
/* Send a spurious AUTH_NONE to return to the top. */
(x)=='/' ? 63 : 0 )
static int loadrsakey_main(FILE * fp, struct RSAKey *key, int pub_only,
- char **commentptr, char *passphrase)
+ char **commentptr, char *passphrase,
+ const char **error)
{
unsigned char buf[16384];
unsigned char keybuf[16];
struct MD5Context md5c;
char *comment;
+ *error = NULL;
+
/* Slurp the whole file (minus the header) into a buffer. */
len = fread(buf, 1, sizeof(buf), fp);
fclose(fp);
- if (len < 0 || len == sizeof(buf))
+ if (len < 0 || len == sizeof(buf)) {
+ *error = "error reading file";
goto end; /* file too big or not read */
+ }
i = 0;
+ *error = "file format error";
/*
* A zero byte. (The signature includes a terminating NUL.)
if (key)
key->comment = comment;
if (!key) {
- return ciphertype != 0;
+ ret = ciphertype != 0;
+ *error = NULL;
+ goto end;
}
/*
if (len - i < 4)
goto end;
if (buf[i] != buf[i + 2] || buf[i + 1] != buf[i + 3]) {
+ *error = "wrong passphrase";
ret = -1;
goto end;
}
goto end;
if (!rsa_verify(key)) {
+ *error = "rsa_verify failed";
freersakey(key);
ret = 0;
} else
return ret;
}
-int loadrsakey(const Filename *filename, struct RSAKey *key, char *passphrase)
+int loadrsakey(const Filename *filename, struct RSAKey *key, char *passphrase,
+ const char **errorstr)
{
FILE *fp;
char buf[64];
+ int ret = 0;
+ const char *error = NULL;
fp = f_open(*filename, "rb");
- if (!fp)
- return 0; /* doesn't even exist */
+ if (!fp) {
+ error = "can't open file";
+ goto end;
+ }
/*
* Read the first line of the file and see if it's a v1 private
* key file.
*/
if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
- return loadrsakey_main(fp, key, FALSE, NULL, passphrase);
+ ret = loadrsakey_main(fp, key, FALSE, NULL, passphrase, &error);
+ goto end;
}
/*
* Otherwise, we have nothing. Return empty-handed.
*/
fclose(fp);
- return 0;
+ error = "not an SSH-1 RSA file";
+
+ end:
+ if ((ret != 1) && errorstr)
+ *errorstr = error;
+ return ret;
}
/*
* key file.
*/
if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
- return loadrsakey_main(fp, NULL, FALSE, comment, NULL);
+ const char *dummy;
+ return loadrsakey_main(fp, NULL, FALSE, comment, NULL, &dummy);
}
fclose(fp);
return 0; /* wasn't the right kind of file */
* an RSA key, as given in the agent protocol (modulus bits,
* exponent, modulus).
*/
-int rsakey_pubblob(const Filename *filename, void **blob, int *bloblen)
+int rsakey_pubblob(const Filename *filename, void **blob, int *bloblen,
+ const char **errorstr)
{
FILE *fp;
char buf[64];
struct RSAKey key;
int ret;
+ const char *error = NULL;
/* Default return if we fail. */
*blob = NULL;
ret = 0;
fp = f_open(*filename, "rb");
- if (!fp)
- return 0; /* doesn't even exist */
+ if (!fp) {
+ error = "can't open file";
+ goto end;
+ }
/*
* Read the first line of the file and see if it's a v1 private
*/
if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
memset(&key, 0, sizeof(key));
- if (loadrsakey_main(fp, &key, TRUE, NULL, NULL)) {
+ if (loadrsakey_main(fp, &key, TRUE, NULL, NULL, &error)) {
*blob = rsa_public_blob(&key, bloblen);
freersakey(&key);
ret = 1;
}
+ } else {
+ error = "not an SSH-1 RSA file";
+ fclose(fp);
}
- fclose(fp);
+
+ end:
+ if ((ret != 1) && errorstr)
+ *errorstr = error;
return ret;
}
};
struct ssh2_userkey *ssh2_load_userkey(const Filename *filename,
- char *passphrase)
+ char *passphrase, const char **errorstr)
{
FILE *fp;
char header[40], *b, *encryption, *comment, *mac;
int public_blob_len, private_blob_len;
int i, is_mac, old_fmt;
int passlen = passphrase ? strlen(passphrase) : 0;
+ const char *error = NULL;
ret = NULL; /* return NULL for most errors */
encryption = comment = mac = NULL;
public_blob = private_blob = NULL;
fp = f_open(*filename, "rb");
- if (!fp)
+ if (!fp) {
+ error = "can't open file";
goto error;
+ }
/* Read the first header line which contains the key type. */
if (!read_header(fp, header))
/* this is an old key file; warn and then continue */
old_keyfile_warning();
old_fmt = 1;
- } else
+ } else {
+ error = "not a PuTTY SSH-2 private key";
goto error;
+ }
+ error = "file format error";
if ((b = read_body(fp)) == NULL)
goto error;
/* Select key algorithm structure. */
if (strcmp(mac, realmac)) {
/* An incorrect MAC is an unconditional Error if the key is
* unencrypted. Otherwise, it means Wrong Passphrase. */
- ret = cipher ? SSH2_WRONG_PASSPHRASE : NULL;
+ if (cipher) {
+ ret = SSH2_WRONG_PASSPHRASE;
+ } else {
+ error = "MAC failed";
+ ret = NULL;
+ }
goto error;
}
}
sfree(ret->comment);
sfree(ret);
ret = NULL;
+ error = "createkey failed";
+ goto error;
}
sfree(public_blob);
sfree(private_blob);
sfree(encryption);
+ *errorstr = NULL;
return ret;
/*
sfree(public_blob);
if (private_blob)
sfree(private_blob);
+ if (errorstr)
+ *errorstr = error;
return ret;
}
char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,
- int *pub_blob_len)
+ int *pub_blob_len, const char **errorstr)
{
FILE *fp;
char header[40], *b;
unsigned char *public_blob;
int public_blob_len;
int i;
+ const char *error = NULL;
public_blob = NULL;
fp = f_open(*filename, "rb");
- if (!fp)
+ if (!fp) {
+ error = "can't open file";
goto error;
+ }
/* Read the first header line which contains the key type. */
if (!read_header(fp, header)
|| (0 != strcmp(header, "PuTTY-User-Key-File-2") &&
- 0 != strcmp(header, "PuTTY-User-Key-File-1")))
+ 0 != strcmp(header, "PuTTY-User-Key-File-1"))) {
+ error = "not a PuTTY SSH-2 private key";
goto error;
+ }
+ error = "file format error";
if ((b = read_body(fp)) == NULL)
goto error;
/* Select key algorithm structure. Currently only ssh-rsa. */
fclose(fp);
if (public_blob)
sfree(public_blob);
+ if (errorstr)
+ *errorstr = error;
return NULL;
}