mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-22 14:39:24 -05:00
Expose lf_load_keyfile outside sshpubk.c.
I'm about to use it in cmdgen for a minor UI improvement. Also, I expect it to be useful in the Pageant client code sooner or later. While I'm here, I've also tweaked its UI a little so that it reports a more precise error, and provided a version that can read from an already open stdio stream.
This commit is contained in:
parent
c25dc9c2fd
commit
5db2f4ca7e
1
defs.h
1
defs.h
@ -64,6 +64,7 @@ typedef struct FontSpec FontSpec;
|
|||||||
typedef struct bufchain_tag bufchain;
|
typedef struct bufchain_tag bufchain;
|
||||||
|
|
||||||
typedef struct strbuf strbuf;
|
typedef struct strbuf strbuf;
|
||||||
|
typedef struct LoadedFile LoadedFile;
|
||||||
|
|
||||||
typedef struct RSAKey RSAKey;
|
typedef struct RSAKey RSAKey;
|
||||||
|
|
||||||
|
13
ssh.h
13
ssh.h
@ -1195,6 +1195,19 @@ int rsa1_loadpub_f(const Filename *filename, BinarySink *bs,
|
|||||||
const ssh_keyalg *find_pubkey_alg(const char *name);
|
const ssh_keyalg *find_pubkey_alg(const char *name);
|
||||||
const ssh_keyalg *find_pubkey_alg_len(ptrlen name);
|
const ssh_keyalg *find_pubkey_alg_len(ptrlen name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A mechanism for loading a key file from disk into a memory buffer
|
||||||
|
* where it can be picked apart as a BinarySource.
|
||||||
|
*/
|
||||||
|
struct LoadedFile {
|
||||||
|
char *data;
|
||||||
|
size_t len, max_size;
|
||||||
|
BinarySource_IMPLEMENTATION;
|
||||||
|
};
|
||||||
|
LoadedFile *lf_load_keyfile(const Filename *filename, const char **errptr);
|
||||||
|
LoadedFile *lf_load_keyfile_fp(FILE *fp, const char **errptr);
|
||||||
|
void lf_free(LoadedFile *lf);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SSH_KEYTYPE_UNOPENABLE,
|
SSH_KEYTYPE_UNOPENABLE,
|
||||||
SSH_KEYTYPE_UNKNOWN,
|
SSH_KEYTYPE_UNKNOWN,
|
||||||
|
143
sshpubk.c
143
sshpubk.c
@ -6,6 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@ -42,36 +44,35 @@ static const ptrlen rsa1_signature =
|
|||||||
(x)=='+' ? 62 : \
|
(x)=='+' ? 62 : \
|
||||||
(x)=='/' ? 63 : 0 )
|
(x)=='/' ? 63 : 0 )
|
||||||
|
|
||||||
typedef struct LoadedFile {
|
typedef enum {
|
||||||
char *data;
|
LF_OK, /* file loaded successfully */
|
||||||
size_t len;
|
LF_TOO_BIG, /* file didn't fit in buffer */
|
||||||
BinarySource_IMPLEMENTATION;
|
LF_ERROR, /* error from stdio layer */
|
||||||
} LoadedFile;
|
} LoadFileStatus;
|
||||||
|
|
||||||
static void lf_free(LoadedFile *lf)
|
static LoadedFile *lf_new(size_t max_size)
|
||||||
{
|
{
|
||||||
|
LoadedFile *lf = snew_plus(LoadedFile, max_size);
|
||||||
|
lf->data = snew_plus_get_aux(lf);
|
||||||
|
lf->len = 0;
|
||||||
|
lf->max_size = max_size;
|
||||||
|
return lf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lf_free(LoadedFile *lf)
|
||||||
|
{
|
||||||
|
smemclr(lf->data, lf->max_size);
|
||||||
smemclr(lf, sizeof(LoadedFile));
|
smemclr(lf, sizeof(LoadedFile));
|
||||||
sfree(lf);
|
sfree(lf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static LoadedFile *lf_load(const Filename *filename, size_t max_size,
|
static LoadFileStatus lf_load_fp(LoadedFile *lf, FILE *fp)
|
||||||
bool tolerate_overflow)
|
|
||||||
{
|
{
|
||||||
FILE *fp = f_open(filename, "rb", false);
|
|
||||||
if (!fp)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
LoadedFile *lf = snew_plus(LoadedFile, max_size);
|
|
||||||
lf->data = snew_plus_get_aux(lf);
|
|
||||||
lf->len = 0;
|
lf->len = 0;
|
||||||
|
while (lf->len < lf->max_size) {
|
||||||
while (lf->len < max_size) {
|
size_t retd = fread(lf->data + lf->len, 1, lf->max_size - lf->len, fp);
|
||||||
size_t retd = fread(lf->data + lf->len, 1, max_size - lf->len, fp);
|
if (ferror(fp))
|
||||||
if (ferror(fp)) {
|
return LF_ERROR;
|
||||||
lf_free(lf);
|
|
||||||
fclose(fp);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retd == 0)
|
if (retd == 0)
|
||||||
break;
|
break;
|
||||||
@ -79,24 +80,70 @@ static LoadedFile *lf_load(const Filename *filename, size_t max_size,
|
|||||||
lf->len += retd;
|
lf->len += retd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lf->len == max_size && !tolerate_overflow) {
|
LoadFileStatus status = LF_OK;
|
||||||
|
|
||||||
|
if (lf->len == lf->max_size) {
|
||||||
/* The file might be too long to fit in our fixed-size
|
/* The file might be too long to fit in our fixed-size
|
||||||
* structure. Try reading one more byte, to check. */
|
* structure. Try reading one more byte, to check. */
|
||||||
if (fgetc(fp) != EOF) {
|
if (fgetc(fp) != EOF)
|
||||||
lf_free(lf);
|
status = LF_TOO_BIG;
|
||||||
fclose(fp);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
BinarySource_INIT(lf, lf->data, lf->len);
|
BinarySource_INIT(lf, lf->data, lf->len);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LoadFileStatus lf_load(LoadedFile *lf, const Filename *filename)
|
||||||
|
{
|
||||||
|
FILE *fp = f_open(filename, "rb", false);
|
||||||
|
if (!fp)
|
||||||
|
return LF_ERROR;
|
||||||
|
|
||||||
|
LoadFileStatus status = lf_load_fp(lf, fp);
|
||||||
|
fclose(fp);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool lf_load_keyfile_helper(LoadFileStatus status,
|
||||||
|
const char **errptr)
|
||||||
|
{
|
||||||
|
const char *error;
|
||||||
|
switch (status) {
|
||||||
|
case LF_OK:
|
||||||
|
return true;
|
||||||
|
case LF_TOO_BIG:
|
||||||
|
error = "file is too large to be a key file";
|
||||||
|
break;
|
||||||
|
case LF_ERROR:
|
||||||
|
error = strerror(errno);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unreachable("bad status value in lf_load_keyfile_helper");
|
||||||
|
}
|
||||||
|
if (errptr)
|
||||||
|
*errptr = error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadedFile *lf_load_keyfile(const Filename *filename, const char **errptr)
|
||||||
|
{
|
||||||
|
LoadedFile *lf = lf_new(MAX_KEY_FILE_SIZE);
|
||||||
|
if (!lf_load_keyfile_helper(lf_load(lf, filename), errptr)) {
|
||||||
|
lf_free(lf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return lf;
|
return lf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LoadedFile *lf_load_keyfile(const Filename *filename)
|
LoadedFile *lf_load_keyfile_fp(FILE *fp, const char **errptr)
|
||||||
{
|
{
|
||||||
return lf_load(filename, MAX_KEY_FILE_SIZE, false);
|
LoadedFile *lf = lf_new(MAX_KEY_FILE_SIZE);
|
||||||
|
if (!lf_load_keyfile_helper(lf_load_fp(lf, fp), errptr)) {
|
||||||
|
lf_free(lf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return lf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int key_type_s(BinarySource *src);
|
static int key_type_s(BinarySource *src);
|
||||||
@ -220,11 +267,9 @@ int rsa1_load_s(BinarySource *src, RSAKey *key,
|
|||||||
int rsa1_load_f(const Filename *filename, RSAKey *key,
|
int rsa1_load_f(const Filename *filename, RSAKey *key,
|
||||||
const char *passphrase, const char **errstr)
|
const char *passphrase, const char **errstr)
|
||||||
{
|
{
|
||||||
LoadedFile *lf = lf_load_keyfile(filename);
|
LoadedFile *lf = lf_load_keyfile(filename, errstr);
|
||||||
if (!lf) {
|
if (!lf)
|
||||||
*errstr = "can't open file";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
int toret = rsa1_load_s(BinarySource_UPCAST(lf), key, passphrase, errstr);
|
int toret = rsa1_load_s(BinarySource_UPCAST(lf), key, passphrase, errstr);
|
||||||
lf_free(lf);
|
lf_free(lf);
|
||||||
@ -243,7 +288,7 @@ bool rsa1_encrypted_s(BinarySource *src, char **comment)
|
|||||||
|
|
||||||
bool rsa1_encrypted_f(const Filename *filename, char **comment)
|
bool rsa1_encrypted_f(const Filename *filename, char **comment)
|
||||||
{
|
{
|
||||||
LoadedFile *lf = lf_load_keyfile(filename);
|
LoadedFile *lf = lf_load_keyfile(filename, NULL);
|
||||||
if (!lf)
|
if (!lf)
|
||||||
return false; /* couldn't even open the file */
|
return false; /* couldn't even open the file */
|
||||||
|
|
||||||
@ -342,11 +387,9 @@ int rsa1_loadpub_s(BinarySource *src, BinarySink *bs,
|
|||||||
int rsa1_loadpub_f(const Filename *filename, BinarySink *bs,
|
int rsa1_loadpub_f(const Filename *filename, BinarySink *bs,
|
||||||
char **commentptr, const char **errorstr)
|
char **commentptr, const char **errorstr)
|
||||||
{
|
{
|
||||||
LoadedFile *lf = lf_load_keyfile(filename);
|
LoadedFile *lf = lf_load_keyfile(filename, errorstr);
|
||||||
if (!lf) {
|
if (!lf)
|
||||||
*errorstr = "can't open file";
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
int toret = rsa1_loadpub_s(BinarySource_UPCAST(lf), bs,
|
int toret = rsa1_loadpub_s(BinarySource_UPCAST(lf), bs,
|
||||||
commentptr, errorstr);
|
commentptr, errorstr);
|
||||||
@ -883,11 +926,9 @@ ssh2_userkey *ppk_load_s(BinarySource *src, const char *passphrase,
|
|||||||
ssh2_userkey *ppk_load_f(const Filename *filename, const char *passphrase,
|
ssh2_userkey *ppk_load_f(const Filename *filename, const char *passphrase,
|
||||||
const char **errorstr)
|
const char **errorstr)
|
||||||
{
|
{
|
||||||
LoadedFile *lf = lf_load_keyfile(filename);
|
LoadedFile *lf = lf_load_keyfile(filename, errorstr);
|
||||||
if (!lf) {
|
if (!lf)
|
||||||
*errorstr = "can't open file";
|
*errorstr = "can't open file";
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh2_userkey *toret = ppk_load_s(BinarySource_UPCAST(lf),
|
ssh2_userkey *toret = ppk_load_s(BinarySource_UPCAST(lf),
|
||||||
passphrase, errorstr);
|
passphrase, errorstr);
|
||||||
@ -1191,11 +1232,9 @@ bool ppk_loadpub_s(BinarySource *src, char **algorithm, BinarySink *bs,
|
|||||||
bool ppk_loadpub_f(const Filename *filename, char **algorithm, BinarySink *bs,
|
bool ppk_loadpub_f(const Filename *filename, char **algorithm, BinarySink *bs,
|
||||||
char **commentptr, const char **errorstr)
|
char **commentptr, const char **errorstr)
|
||||||
{
|
{
|
||||||
LoadedFile *lf = lf_load_keyfile(filename);
|
LoadedFile *lf = lf_load_keyfile(filename, errorstr);
|
||||||
if (!lf) {
|
if (!lf)
|
||||||
*errorstr = "can't open file";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
bool toret = ppk_loadpub_s(BinarySource_UPCAST(lf), algorithm, bs,
|
bool toret = ppk_loadpub_s(BinarySource_UPCAST(lf), algorithm, bs,
|
||||||
commentptr, errorstr);
|
commentptr, errorstr);
|
||||||
@ -1253,7 +1292,7 @@ bool ppk_encrypted_s(BinarySource *src, char **commentptr)
|
|||||||
|
|
||||||
bool ppk_encrypted_f(const Filename *filename, char **commentptr)
|
bool ppk_encrypted_f(const Filename *filename, char **commentptr)
|
||||||
{
|
{
|
||||||
LoadedFile *lf = lf_load_keyfile(filename);
|
LoadedFile *lf = lf_load_keyfile(filename, NULL);
|
||||||
if (!lf) {
|
if (!lf) {
|
||||||
if (commentptr)
|
if (commentptr)
|
||||||
*commentptr = NULL;
|
*commentptr = NULL;
|
||||||
@ -1648,9 +1687,11 @@ static int key_type_s(BinarySource *src)
|
|||||||
|
|
||||||
int key_type(const Filename *filename)
|
int key_type(const Filename *filename)
|
||||||
{
|
{
|
||||||
LoadedFile *lf = lf_load(filename, 1024, true);
|
LoadedFile *lf = lf_new(1024);
|
||||||
if (!lf)
|
if (lf_load(lf, filename) == LF_ERROR) {
|
||||||
|
lf_free(lf);
|
||||||
return SSH_KEYTYPE_UNOPENABLE;
|
return SSH_KEYTYPE_UNOPENABLE;
|
||||||
|
}
|
||||||
|
|
||||||
int toret = key_type_s(BinarySource_UPCAST(lf));
|
int toret = key_type_s(BinarySource_UPCAST(lf));
|
||||||
lf_free(lf);
|
lf_free(lf);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user