mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +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;
|
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.)
|
* 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;
|
struct openssh_key *ret;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char buffer[256];
|
char *line = NULL;
|
||||||
char *errmsg, *p;
|
char *errmsg, *p;
|
||||||
int headers_done;
|
int headers_done;
|
||||||
char base64_bit[4];
|
char base64_bit[4];
|
||||||
@ -327,46 +338,55 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
|
|||||||
errmsg = "unable to open key file";
|
errmsg = "unable to open key file";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!fgets(buffer, sizeof(buffer), fp) ||
|
|
||||||
0 != strncmp(buffer, "-----BEGIN ", 11) ||
|
if (!(line = fgetline(fp))) {
|
||||||
0 != strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) {
|
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";
|
errmsg = "file does not begin with OpenSSH key header";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!strcmp(buffer, "-----BEGIN RSA PRIVATE KEY-----\n"))
|
if (!strcmp(line, "-----BEGIN RSA PRIVATE KEY-----"))
|
||||||
ret->type = OSSH_RSA;
|
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;
|
ret->type = OSSH_DSA;
|
||||||
else {
|
else {
|
||||||
errmsg = "unrecognised key type";
|
errmsg = "unrecognised key type";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
memset(line, 0, strlen(line));
|
||||||
|
sfree(line);
|
||||||
|
line = NULL;
|
||||||
|
|
||||||
headers_done = 0;
|
headers_done = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
if (!(line = fgetline(fp))) {
|
||||||
errmsg = "unexpected end of file";
|
errmsg = "unexpected end of file";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (0 == strncmp(buffer, "-----END ", 9) &&
|
strip_crlf(line);
|
||||||
0 == strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n"))
|
if (0 == strncmp(line, "-----END ", 9) &&
|
||||||
|
0 == strcmp(line+strlen(line)-16, "PRIVATE KEY-----"))
|
||||||
break; /* done */
|
break; /* done */
|
||||||
if ((p = strchr(buffer, ':')) != NULL) {
|
if ((p = strchr(line, ':')) != NULL) {
|
||||||
if (headers_done) {
|
if (headers_done) {
|
||||||
errmsg = "header found in body of key data";
|
errmsg = "header found in body of key data";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
while (*p && isspace((unsigned char)*p)) p++;
|
while (*p && isspace((unsigned char)*p)) p++;
|
||||||
if (!strcmp(buffer, "Proc-Type")) {
|
if (!strcmp(line, "Proc-Type")) {
|
||||||
if (p[0] != '4' || p[1] != ',') {
|
if (p[0] != '4' || p[1] != ',') {
|
||||||
errmsg = "Proc-Type is not 4 (only 4 is supported)";
|
errmsg = "Proc-Type is not 4 (only 4 is supported)";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
p += 2;
|
p += 2;
|
||||||
if (!strcmp(p, "ENCRYPTED\n"))
|
if (!strcmp(p, "ENCRYPTED"))
|
||||||
ret->encrypted = 1;
|
ret->encrypted = 1;
|
||||||
} else if (!strcmp(buffer, "DEK-Info")) {
|
} else if (!strcmp(line, "DEK-Info")) {
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
if (strncmp(p, "DES-EDE3-CBC,", 13)) {
|
if (strncmp(p, "DES-EDE3-CBC,", 13)) {
|
||||||
@ -388,7 +408,7 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
|
|||||||
} else {
|
} else {
|
||||||
headers_done = 1;
|
headers_done = 1;
|
||||||
|
|
||||||
p = buffer;
|
p = line;
|
||||||
while (isbase64(*p)) {
|
while (isbase64(*p)) {
|
||||||
base64_bit[base64_chars++] = *p;
|
base64_bit[base64_chars++] = *p;
|
||||||
if (base64_chars == 4) {
|
if (base64_chars == 4) {
|
||||||
@ -419,6 +439,9 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
|
|||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
memset(line, 0, strlen(line));
|
||||||
|
sfree(line);
|
||||||
|
line = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret->keyblob_len == 0 || !ret->keyblob) {
|
if (ret->keyblob_len == 0 || !ret->keyblob) {
|
||||||
@ -431,13 +454,16 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(buffer, 0, sizeof(buffer));
|
|
||||||
memset(base64_bit, 0, sizeof(base64_bit));
|
memset(base64_bit, 0, sizeof(base64_bit));
|
||||||
if (errmsg_p) *errmsg_p = NULL;
|
if (errmsg_p) *errmsg_p = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
memset(buffer, 0, sizeof(buffer));
|
if (line) {
|
||||||
|
memset(line, 0, strlen(line));
|
||||||
|
sfree(line);
|
||||||
|
line = NULL;
|
||||||
|
}
|
||||||
memset(base64_bit, 0, sizeof(base64_bit));
|
memset(base64_bit, 0, sizeof(base64_bit));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (ret->keyblob) {
|
if (ret->keyblob) {
|
||||||
@ -989,8 +1015,8 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
|
|||||||
{
|
{
|
||||||
struct sshcom_key *ret;
|
struct sshcom_key *ret;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char buffer[256];
|
char *line = NULL;
|
||||||
int len;
|
int hdrstart, len;
|
||||||
char *errmsg, *p;
|
char *errmsg, *p;
|
||||||
int headers_done;
|
int headers_done;
|
||||||
char base64_bit[4];
|
char base64_bit[4];
|
||||||
@ -1006,44 +1032,67 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
|
|||||||
errmsg = "unable to open key file";
|
errmsg = "unable to open key file";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!fgets(buffer, sizeof(buffer), fp) ||
|
if (!(line = fgetline(fp))) {
|
||||||
0 != strcmp(buffer, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n")) {
|
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";
|
errmsg = "file does not begin with ssh.com key header";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
memset(line, 0, strlen(line));
|
||||||
|
sfree(line);
|
||||||
|
line = NULL;
|
||||||
|
|
||||||
headers_done = 0;
|
headers_done = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
if (!(line = fgetline(fp))) {
|
||||||
errmsg = "unexpected end of file";
|
errmsg = "unexpected end of file";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!strcmp(buffer, "---- END SSH2 ENCRYPTED PRIVATE KEY ----\n"))
|
strip_crlf(line);
|
||||||
|
if (!strcmp(line, "---- END SSH2 ENCRYPTED PRIVATE KEY ----"))
|
||||||
break; /* done */
|
break; /* done */
|
||||||
if ((p = strchr(buffer, ':')) != NULL) {
|
if ((p = strchr(line, ':')) != NULL) {
|
||||||
if (headers_done) {
|
if (headers_done) {
|
||||||
errmsg = "header found in body of key data";
|
errmsg = "header found in body of key data";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
while (*p && isspace((unsigned char)*p)) p++;
|
while (*p && isspace((unsigned char)*p)) p++;
|
||||||
|
hdrstart = p - line;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Header lines can end in a trailing backslash for
|
* Header lines can end in a trailing backslash for
|
||||||
* continuation.
|
* continuation.
|
||||||
*/
|
*/
|
||||||
while ((len = strlen(p)) > (int)(sizeof(buffer) - (p-buffer) -1) ||
|
len = hdrstart + strlen(line+hdrstart);
|
||||||
p[len-1] != '\n' || p[len-2] == '\\') {
|
assert(!line[len]);
|
||||||
if (len > (int)((p-buffer) + sizeof(buffer)-2)) {
|
while (line[len-1] == '\\') {
|
||||||
errmsg = "header line too long to deal with";
|
char *line2;
|
||||||
goto error;
|
int line2len;
|
||||||
}
|
|
||||||
if (!fgets(p+len-2, sizeof(buffer)-(p-buffer)-(len-2), fp)) {
|
line2 = fgetline(fp);
|
||||||
|
if (!line2) {
|
||||||
errmsg = "unexpected end of file";
|
errmsg = "unexpected end of file";
|
||||||
goto error;
|
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';
|
p = line + hdrstart;
|
||||||
if (!strcmp(buffer, "Comment")) {
|
strip_crlf(p);
|
||||||
|
if (!strcmp(line, "Comment")) {
|
||||||
/* Strip quotes in comment if present. */
|
/* Strip quotes in comment if present. */
|
||||||
if (p[0] == '"' && p[strlen(p)-1] == '"') {
|
if (p[0] == '"' && p[strlen(p)-1] == '"') {
|
||||||
p++;
|
p++;
|
||||||
@ -1055,7 +1104,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
|
|||||||
} else {
|
} else {
|
||||||
headers_done = 1;
|
headers_done = 1;
|
||||||
|
|
||||||
p = buffer;
|
p = line;
|
||||||
while (isbase64(*p)) {
|
while (isbase64(*p)) {
|
||||||
base64_bit[base64_chars++] = *p;
|
base64_bit[base64_chars++] = *p;
|
||||||
if (base64_chars == 4) {
|
if (base64_chars == 4) {
|
||||||
@ -1083,6 +1132,9 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
|
|||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
memset(line, 0, strlen(line));
|
||||||
|
sfree(line);
|
||||||
|
line = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret->keyblob_len == 0 || !ret->keyblob) {
|
if (ret->keyblob_len == 0 || !ret->keyblob) {
|
||||||
@ -1094,6 +1146,11 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
if (line) {
|
||||||
|
memset(line, 0, strlen(line));
|
||||||
|
sfree(line);
|
||||||
|
line = NULL;
|
||||||
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (ret->keyblob) {
|
if (ret->keyblob) {
|
||||||
memset(ret->keyblob, 0, ret->keyblob_size);
|
memset(ret->keyblob, 0, ret->keyblob_size);
|
||||||
|
Loading…
Reference in New Issue
Block a user