#include <stdlib.h>
#include <assert.h>
+#include "putty.h"
#include "ssh.h"
#include "misc.h"
*/
if (ciphertype) {
MD5Init(&md5c);
- MD5Update(&md5c, passphrase, strlen(passphrase));
+ MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
MD5Final(keybuf, &md5c);
des3_decrypt_pubkey(keybuf, buf + i, (len - i + 7) & ~7);
memset(keybuf, 0, sizeof(keybuf)); /* burn the evidence */
return ret;
}
-int loadrsakey(char *filename, struct RSAKey *key, char *passphrase)
+int loadrsakey(const Filename *filename, struct RSAKey *key, char *passphrase)
{
FILE *fp;
- unsigned char buf[64];
+ char buf[64];
- fp = fopen(filename, "rb");
+ fp = f_open(*filename, "rb");
if (!fp)
return 0; /* doesn't even exist */
* See whether an RSA key is encrypted. Return its comment field as
* well.
*/
-int rsakey_encrypted(char *filename, char **comment)
+int rsakey_encrypted(const Filename *filename, char **comment)
{
FILE *fp;
- unsigned char buf[64];
+ char buf[64];
- fp = fopen(filename, "rb");
+ fp = f_open(*filename, "rb");
if (!fp)
return 0; /* doesn't even exist */
* an RSA key, as given in the agent protocol (modulus bits,
* exponent, modulus).
*/
-int rsakey_pubblob(char *filename, void **blob, int *bloblen)
+int rsakey_pubblob(const Filename *filename, void **blob, int *bloblen)
{
FILE *fp;
- unsigned char buf[64];
+ char buf[64];
struct RSAKey key;
int ret;
*bloblen = 0;
ret = 0;
- fp = fopen(filename, "rb");
+ fp = f_open(*filename, "rb");
if (!fp)
return 0; /* doesn't even exist */
/*
* Save an RSA key file. Return nonzero on success.
*/
-int saversakey(char *filename, struct RSAKey *key, char *passphrase)
+int saversakey(const Filename *filename, struct RSAKey *key, char *passphrase)
{
unsigned char buf[16384];
unsigned char keybuf[16];
*/
if (passphrase) {
MD5Init(&md5c);
- MD5Update(&md5c, passphrase, strlen(passphrase));
+ MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
MD5Final(keybuf, &md5c);
des3_encrypt_pubkey(keybuf, estart, p - estart);
memset(keybuf, 0, sizeof(keybuf)); /* burn the evidence */
/*
* Done. Write the result to the file.
*/
- fp = fopen(filename, "wb");
+ fp = f_open(*filename, "wb");
if (fp) {
int ret = (fwrite(buf, 1, p - buf, fp) == (size_t) (p - buf));
ret = ret && (fclose(fp) == 0);
return len;
}
-static char *read_blob(FILE * fp, int nlines, int *bloblen)
+static unsigned char *read_blob(FILE * fp, int nlines, int *bloblen)
{
unsigned char *blob;
char *line;
NULL, NULL, NULL
};
-struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase)
+struct ssh2_userkey *ssh2_load_userkey(const Filename *filename,
+ char *passphrase)
{
FILE *fp;
char header[40], *b, *encryption, *comment, *mac;
int passlen = passphrase ? strlen(passphrase) : 0;
ret = NULL; /* return NULL for most errors */
- comment = mac = NULL;
+ encryption = comment = mac = NULL;
public_blob = private_blob = NULL;
- fp = fopen(filename, "rb");
+ fp = f_open(*filename, "rb");
if (!fp)
goto error;
return ret;
}
-char *ssh2_userkey_loadpub(char *filename, char **algorithm,
+char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,
int *pub_blob_len)
{
FILE *fp;
public_blob = NULL;
- fp = fopen(filename, "rb");
+ fp = f_open(*filename, "rb");
if (!fp)
goto error;
*pub_blob_len = public_blob_len;
if (algorithm)
*algorithm = alg->name;
- return public_blob;
+ return (char *)public_blob;
/*
* Error processing.
return NULL;
}
-int ssh2_userkey_encrypted(char *filename, char **commentptr)
+int ssh2_userkey_encrypted(const Filename *filename, char **commentptr)
{
FILE *fp;
char header[40], *b, *comment;
if (commentptr)
*commentptr = NULL;
- fp = fopen(filename, "rb");
+ fp = f_open(*filename, "rb");
if (!fp)
return 0;
if (!read_header(fp, header)
return (datalen + 47) / 48;
}
-void base64_encode_atom(unsigned char *data, int n, char *out)
-{
- static const char base64_chars[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- unsigned word;
-
- word = data[0] << 16;
- if (n > 1)
- word |= data[1] << 8;
- if (n > 2)
- word |= data[2];
- out[0] = base64_chars[(word >> 18) & 0x3F];
- out[1] = base64_chars[(word >> 12) & 0x3F];
- if (n > 1)
- out[2] = base64_chars[(word >> 6) & 0x3F];
- else
- out[2] = '=';
- if (n > 2)
- out[3] = base64_chars[word & 0x3F];
- else
- out[3] = '=';
-}
-
-void base64_encode(FILE * fp, unsigned char *data, int datalen)
+void base64_encode(FILE * fp, unsigned char *data, int datalen, int cpl)
{
int linelen = 0;
char out[4];
- int n;
+ int n, i;
while (datalen > 0) {
- if (linelen >= 64) {
- linelen = 0;
- fputc('\n', fp);
- }
n = (datalen < 3 ? datalen : 3);
base64_encode_atom(data, n, out);
data += n;
datalen -= n;
- fwrite(out, 1, 4, fp);
- linelen += 4;
+ for (i = 0; i < 4; i++) {
+ if (linelen >= cpl) {
+ linelen = 0;
+ fputc('\n', fp);
+ }
+ fputc(out[i], fp);
+ linelen++;
+ }
}
fputc('\n', fp);
}
-int ssh2_save_userkey(char *filename, struct ssh2_userkey *key,
+int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
char *passphrase)
{
FILE *fp;
}
if (passphrase) {
- char key[40];
+ unsigned char key[40];
SHA_State s;
passlen = strlen(passphrase);
memset(&s, 0, sizeof(s));
}
- fp = fopen(filename, "w");
+ fp = f_open(*filename, "w");
if (!fp)
return 0;
fprintf(fp, "PuTTY-User-Key-File-2: %s\n", key->alg->name);
fprintf(fp, "Encryption: %s\n", cipherstr);
fprintf(fp, "Comment: %s\n", key->comment);
fprintf(fp, "Public-Lines: %d\n", base64_lines(pub_blob_len));
- base64_encode(fp, pub_blob, pub_blob_len);
+ base64_encode(fp, pub_blob, pub_blob_len, 64);
fprintf(fp, "Private-Lines: %d\n", base64_lines(priv_encrypted_len));
- base64_encode(fp, priv_blob_encrypted, priv_encrypted_len);
+ base64_encode(fp, priv_blob_encrypted, priv_encrypted_len, 64);
fprintf(fp, "Private-MAC: ");
for (i = 0; i < 20; i++)
fprintf(fp, "%02x", priv_mac[i]);
}
/* ----------------------------------------------------------------------
- * A function to determine which version of SSH to try on a private
- * key file. Returns 0 on failure, 1 or 2 on success.
+ * A function to determine the type of a private key file. Returns
+ * 0 on failure, 1 or 2 on success.
*/
-int keyfile_version(char *filename)
+int key_type(const Filename *filename)
{
FILE *fp;
+ char buf[32];
+ const char putty2_sig[] = "PuTTY-User-Key-File-";
+ const char sshcom_sig[] = "---- BEGIN SSH2 ENCRYPTED PRIVAT";
+ const char openssh_sig[] = "-----BEGIN ";
int i;
- fp = fopen(filename, "r");
+ fp = f_open(*filename, "r");
if (!fp)
- return 0;
- i = fgetc(fp);
+ return SSH_KEYTYPE_UNOPENABLE;
+ i = fread(buf, 1, sizeof(buf), fp);
fclose(fp);
- if (i == 'S')
- return 1; /* "SSH PRIVATE KEY FORMAT" etc */
- if (i == 'P') /* "PuTTY-User-Key-File" etc */
- return 2;
- return 0; /* unrecognised or EOF */
+ if (i < 0)
+ return SSH_KEYTYPE_UNOPENABLE;
+ if (i < 32)
+ return SSH_KEYTYPE_UNKNOWN;
+ if (!memcmp(buf, rsa_signature, sizeof(rsa_signature)-1))
+ return SSH_KEYTYPE_SSH1;
+ if (!memcmp(buf, putty2_sig, sizeof(putty2_sig)-1))
+ return SSH_KEYTYPE_SSH2;
+ if (!memcmp(buf, openssh_sig, sizeof(openssh_sig)-1))
+ return SSH_KEYTYPE_OPENSSH;
+ if (!memcmp(buf, sshcom_sig, sizeof(sshcom_sig)-1))
+ return SSH_KEYTYPE_SSHCOM;
+ return SSH_KEYTYPE_UNKNOWN; /* unrecognised or EOF */
+}
+
+/*
+ * Convert the type word to a string, for `wrong type' error
+ * messages.
+ */
+char *key_type_to_str(int type)
+{
+ switch (type) {
+ case SSH_KEYTYPE_UNOPENABLE: return "unable to open file"; break;
+ case SSH_KEYTYPE_UNKNOWN: return "not a private key"; break;
+ case SSH_KEYTYPE_SSH1: return "SSH1 private key"; break;
+ case SSH_KEYTYPE_SSH2: return "PuTTY SSH2 private key"; break;
+ case SSH_KEYTYPE_OPENSSH: return "OpenSSH SSH2 private key"; break;
+ case SSH_KEYTYPE_SSHCOM: return "ssh.com SSH2 private key"; break;
+ default: return "INTERNAL ERROR"; break;
+ }
}