mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Greater leniency when importing private key files: accept both CRLF
and LF, and don't object if the final line of the key lacks a newline. Also, while I'm here, switch to using fgetline() throughout so as not to have to do nasty buffer-size ad-hockery. [originally from svn r7072]
This commit is contained in:
parent
57a763b0ec
commit
720693cfab
123
import.c
123
import.c
@ -109,6 +109,17 @@ int export_ssh2(const Filename *filename, int type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Strip trailing CRs and LFs at the end of a line of text.
|
||||
*/
|
||||
void strip_crlf(char *str)
|
||||
{
|
||||
char *p = str + strlen(str);
|
||||
|
||||
while (p > str && (p[-1] == '\r' || p[-1] == '\n'))
|
||||
*--p = '\0';
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Helper routines. (The base64 ones are defined in sshpubk.c.)
|
||||
*/
|
||||
@ -310,7 +321,7 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
|
||||
{
|
||||
struct openssh_key *ret;
|
||||
FILE *fp;
|
||||
char buffer[256];
|
||||
char *line = NULL;
|
||||
char *errmsg, *p;
|
||||
int headers_done;
|
||||
char base64_bit[4];
|
||||
@ -327,46 +338,55 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
|
||||
errmsg = "unable to open key file";
|
||||
goto error;
|
||||
}
|
||||
if (!fgets(buffer, sizeof(buffer), fp) ||
|
||||
0 != strncmp(buffer, "-----BEGIN ", 11) ||
|
||||
0 != strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) {
|
||||
|
||||
if (!(line = fgetline(fp))) {
|
||||
errmsg = "unexpected end of file";
|
||||
goto error;
|
||||
}
|
||||
strip_crlf(line);
|
||||
if (0 != strncmp(line, "-----BEGIN ", 11) ||
|
||||
0 != strcmp(line+strlen(line)-16, "PRIVATE KEY-----")) {
|
||||
errmsg = "file does not begin with OpenSSH key header";
|
||||
goto error;
|
||||
}
|
||||
if (!strcmp(buffer, "-----BEGIN RSA PRIVATE KEY-----\n"))
|
||||
if (!strcmp(line, "-----BEGIN RSA PRIVATE KEY-----"))
|
||||
ret->type = OSSH_RSA;
|
||||
else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n"))
|
||||
else if (!strcmp(line, "-----BEGIN DSA PRIVATE KEY-----"))
|
||||
ret->type = OSSH_DSA;
|
||||
else {
|
||||
errmsg = "unrecognised key type";
|
||||
goto error;
|
||||
}
|
||||
memset(line, 0, strlen(line));
|
||||
sfree(line);
|
||||
line = NULL;
|
||||
|
||||
headers_done = 0;
|
||||
while (1) {
|
||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
||||
if (!(line = fgetline(fp))) {
|
||||
errmsg = "unexpected end of file";
|
||||
goto error;
|
||||
}
|
||||
if (0 == strncmp(buffer, "-----END ", 9) &&
|
||||
0 == strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n"))
|
||||
strip_crlf(line);
|
||||
if (0 == strncmp(line, "-----END ", 9) &&
|
||||
0 == strcmp(line+strlen(line)-16, "PRIVATE KEY-----"))
|
||||
break; /* done */
|
||||
if ((p = strchr(buffer, ':')) != NULL) {
|
||||
if ((p = strchr(line, ':')) != NULL) {
|
||||
if (headers_done) {
|
||||
errmsg = "header found in body of key data";
|
||||
goto error;
|
||||
}
|
||||
*p++ = '\0';
|
||||
while (*p && isspace((unsigned char)*p)) p++;
|
||||
if (!strcmp(buffer, "Proc-Type")) {
|
||||
if (!strcmp(line, "Proc-Type")) {
|
||||
if (p[0] != '4' || p[1] != ',') {
|
||||
errmsg = "Proc-Type is not 4 (only 4 is supported)";
|
||||
goto error;
|
||||
}
|
||||
p += 2;
|
||||
if (!strcmp(p, "ENCRYPTED\n"))
|
||||
if (!strcmp(p, "ENCRYPTED"))
|
||||
ret->encrypted = 1;
|
||||
} else if (!strcmp(buffer, "DEK-Info")) {
|
||||
} else if (!strcmp(line, "DEK-Info")) {
|
||||
int i, j;
|
||||
|
||||
if (strncmp(p, "DES-EDE3-CBC,", 13)) {
|
||||
@ -388,7 +408,7 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
|
||||
} else {
|
||||
headers_done = 1;
|
||||
|
||||
p = buffer;
|
||||
p = line;
|
||||
while (isbase64(*p)) {
|
||||
base64_bit[base64_chars++] = *p;
|
||||
if (base64_chars == 4) {
|
||||
@ -419,6 +439,9 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
|
||||
p++;
|
||||
}
|
||||
}
|
||||
memset(line, 0, strlen(line));
|
||||
sfree(line);
|
||||
line = NULL;
|
||||
}
|
||||
|
||||
if (ret->keyblob_len == 0 || !ret->keyblob) {
|
||||
@ -431,13 +454,16 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
|
||||
goto error;
|
||||
}
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
memset(base64_bit, 0, sizeof(base64_bit));
|
||||
if (errmsg_p) *errmsg_p = NULL;
|
||||
return ret;
|
||||
|
||||
error:
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
if (line) {
|
||||
memset(line, 0, strlen(line));
|
||||
sfree(line);
|
||||
line = NULL;
|
||||
}
|
||||
memset(base64_bit, 0, sizeof(base64_bit));
|
||||
if (ret) {
|
||||
if (ret->keyblob) {
|
||||
@ -989,8 +1015,8 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
|
||||
{
|
||||
struct sshcom_key *ret;
|
||||
FILE *fp;
|
||||
char buffer[256];
|
||||
int len;
|
||||
char *line = NULL;
|
||||
int hdrstart, len;
|
||||
char *errmsg, *p;
|
||||
int headers_done;
|
||||
char base64_bit[4];
|
||||
@ -1006,44 +1032,67 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
|
||||
errmsg = "unable to open key file";
|
||||
goto error;
|
||||
}
|
||||
if (!fgets(buffer, sizeof(buffer), fp) ||
|
||||
0 != strcmp(buffer, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n")) {
|
||||
if (!(line = fgetline(fp))) {
|
||||
errmsg = "unexpected end of file";
|
||||
goto error;
|
||||
}
|
||||
strip_crlf(line);
|
||||
if (0 != strcmp(line, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----")) {
|
||||
errmsg = "file does not begin with ssh.com key header";
|
||||
goto error;
|
||||
}
|
||||
memset(line, 0, strlen(line));
|
||||
sfree(line);
|
||||
line = NULL;
|
||||
|
||||
headers_done = 0;
|
||||
while (1) {
|
||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
||||
if (!(line = fgetline(fp))) {
|
||||
errmsg = "unexpected end of file";
|
||||
goto error;
|
||||
}
|
||||
if (!strcmp(buffer, "---- END SSH2 ENCRYPTED PRIVATE KEY ----\n"))
|
||||
strip_crlf(line);
|
||||
if (!strcmp(line, "---- END SSH2 ENCRYPTED PRIVATE KEY ----"))
|
||||
break; /* done */
|
||||
if ((p = strchr(buffer, ':')) != NULL) {
|
||||
if ((p = strchr(line, ':')) != NULL) {
|
||||
if (headers_done) {
|
||||
errmsg = "header found in body of key data";
|
||||
goto error;
|
||||
}
|
||||
*p++ = '\0';
|
||||
while (*p && isspace((unsigned char)*p)) p++;
|
||||
hdrstart = p - line;
|
||||
|
||||
/*
|
||||
* Header lines can end in a trailing backslash for
|
||||
* continuation.
|
||||
*/
|
||||
while ((len = strlen(p)) > (int)(sizeof(buffer) - (p-buffer) -1) ||
|
||||
p[len-1] != '\n' || p[len-2] == '\\') {
|
||||
if (len > (int)((p-buffer) + sizeof(buffer)-2)) {
|
||||
errmsg = "header line too long to deal with";
|
||||
goto error;
|
||||
}
|
||||
if (!fgets(p+len-2, sizeof(buffer)-(p-buffer)-(len-2), fp)) {
|
||||
len = hdrstart + strlen(line+hdrstart);
|
||||
assert(!line[len]);
|
||||
while (line[len-1] == '\\') {
|
||||
char *line2;
|
||||
int line2len;
|
||||
|
||||
line2 = fgetline(fp);
|
||||
if (!line2) {
|
||||
errmsg = "unexpected end of file";
|
||||
goto error;
|
||||
}
|
||||
strip_crlf(line2);
|
||||
|
||||
line2len = strlen(line2);
|
||||
line = sresize(line, len + line2len + 1, char);
|
||||
strcpy(line + len - 1, line2);
|
||||
len += line2len - 1;
|
||||
assert(!line[len]);
|
||||
|
||||
memset(line2, 0, strlen(line2));
|
||||
sfree(line2);
|
||||
line2 = NULL;
|
||||
}
|
||||
p[strcspn(p, "\n")] = '\0';
|
||||
if (!strcmp(buffer, "Comment")) {
|
||||
p = line + hdrstart;
|
||||
strip_crlf(p);
|
||||
if (!strcmp(line, "Comment")) {
|
||||
/* Strip quotes in comment if present. */
|
||||
if (p[0] == '"' && p[strlen(p)-1] == '"') {
|
||||
p++;
|
||||
@ -1055,7 +1104,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
|
||||
} else {
|
||||
headers_done = 1;
|
||||
|
||||
p = buffer;
|
||||
p = line;
|
||||
while (isbase64(*p)) {
|
||||
base64_bit[base64_chars++] = *p;
|
||||
if (base64_chars == 4) {
|
||||
@ -1083,6 +1132,9 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
|
||||
p++;
|
||||
}
|
||||
}
|
||||
memset(line, 0, strlen(line));
|
||||
sfree(line);
|
||||
line = NULL;
|
||||
}
|
||||
|
||||
if (ret->keyblob_len == 0 || !ret->keyblob) {
|
||||
@ -1094,6 +1146,11 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
|
||||
return ret;
|
||||
|
||||
error:
|
||||
if (line) {
|
||||
memset(line, 0, strlen(line));
|
||||
sfree(line);
|
||||
line = NULL;
|
||||
}
|
||||
if (ret) {
|
||||
if (ret->keyblob) {
|
||||
memset(ret->keyblob, 0, ret->keyblob_size);
|
||||
|
Loading…
Reference in New Issue
Block a user