* Pageant: the PuTTY Authentication Agent.
*/
-#include <windows.h>
-#ifndef NO_SECURITY
-#include <aclapi.h>
-#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "ssh.h"
#include "misc.h"
#include "tree234.h"
-#include "winstuff.h"
+
+#include <shellapi.h>
+
+#ifndef NO_SECURITY
+#include <aclapi.h>
+#endif
#define IDI_MAINICON 200
#define IDI_TRAYICON 201
static int already_running;
static int requested_help;
-static char *help_path;
+char *help_path;
static char *putty_path;
#define IDM_PUTTY 0x0060
*/
static void *make_keylist1(int *length);
static void *make_keylist2(int *length);
-static void *get_keylist1(void);
-static void *get_keylist2(void);
+static void *get_keylist1(int *length);
+static void *get_keylist2(int *length);
/*
* We need this to link with the RSA code, because rsaencrypt()
{
void *blob;
unsigned char *keylist, *p;
- int i, nkeys, bloblen;
+ int i, nkeys, bloblen, keylistlen;
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();
+ keylist = get_keylist1(&keylistlen);
} 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);
sfree(blob);
blob = blob2;
- keylist = get_keylist2();
+ keylist = get_keylist2(&keylistlen);
}
if (keylist) {
+ if (keylistlen < 4) {
+ MessageBox(NULL, "Received broken key list?!", APPNAME,
+ MB_OK | MB_ICONERROR);
+ return;
+ }
nkeys = GET_32BIT(keylist);
p = keylist + 4;
+ keylistlen -= 4;
for (i = 0; i < nkeys; i++) {
if (!memcmp(blob, p, bloblen)) {
return;
}
/* Now skip over public blob */
- if (type == SSH_KEYTYPE_SSH1)
- p += rsa_public_blob_len(p);
- else
- p += 4 + GET_32BIT(p);
+ if (type == SSH_KEYTYPE_SSH1) {
+ int n = rsa_public_blob_len(p, keylistlen);
+ if (n < 0) {
+ MessageBox(NULL, "Received broken key list?!", APPNAME,
+ MB_OK | MB_ICONERROR);
+ return;
+ }
+ p += n;
+ keylistlen -= n;
+ } else {
+ int n;
+ if (keylistlen < 4) {
+ MessageBox(NULL, "Received broken key list?!", APPNAME,
+ MB_OK | MB_ICONERROR);
+ return;
+ }
+ n = 4 + GET_32BIT(p);
+ if (keylistlen < n) {
+ MessageBox(NULL, "Received broken key list?!", APPNAME,
+ MB_OK | MB_ICONERROR);
+ return;
+ }
+ p += n;
+ keylistlen -= n;
+ }
/* Now skip over comment field */
- p += 4 + GET_32BIT(p);
+ {
+ int n;
+ if (keylistlen < 4) {
+ MessageBox(NULL, "Received broken key list?!", APPNAME,
+ MB_OK | MB_ICONERROR);
+ return;
+ }
+ n = 4 + GET_32BIT(p);
+ if (keylistlen < n) {
+ MessageBox(NULL, "Received broken key list?!", APPNAME,
+ MB_OK | MB_ICONERROR);
+ return;
+ }
+ p += n;
+ keylistlen -= n;
+ }
}
sfree(keylist);
} 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)
keybloblen);
PUT_32BIT(request + reqlen, clen);
memcpy(request + reqlen + 4, skey->comment, clen);
- PUT_32BIT(request, reqlen - 4);
reqlen += clen + 4;
+ PUT_32BIT(request, reqlen - 4);
ret = agent_query(request, reqlen, &vresponse, &resplen,
NULL, NULL);
* calling make_keylist1 (if that's us) or sending a message to the
* primary Pageant (if it's not).
*/
-static void *get_keylist1(void)
+static void *get_keylist1(int *length)
{
void *ret;
ret = snewn(resplen-5, unsigned char);
memcpy(ret, response+5, resplen-5);
sfree(response);
+
+ if (length)
+ *length = resplen-5;
} else {
- ret = make_keylist1(NULL);
+ ret = make_keylist1(length);
}
return ret;
}
* calling make_keylist2 (if that's us) or sending a message to the
* primary Pageant (if it's not).
*/
-static void *get_keylist2(void)
+static void *get_keylist2(int *length)
{
void *ret;
ret = snewn(resplen-5, unsigned char);
memcpy(ret, response+5, resplen-5);
sfree(response);
+
+ if (length)
+ *length = resplen-5;
} else {
- ret = make_keylist2(NULL);
+ ret = make_keylist2(length);
}
return ret;
}
{
unsigned char *p = msg;
unsigned char *ret = msg;
+ unsigned char *msgend;
int type;
/*
+ * Get the message length.
+ */
+ msgend = p + 4 + GET_32BIT(p);
+
+ /*
* Get the message type.
*/
+ if (msgend < p+5)
+ goto failure;
type = p[4];
p += 5;
int i, len;
p += 4;
- p += ssh1_read_bignum(p, &reqkey.exponent);
- p += ssh1_read_bignum(p, &reqkey.modulus);
- p += ssh1_read_bignum(p, &challenge);
+ i = ssh1_read_bignum(p, msgend - p, &reqkey.exponent);
+ if (i < 0)
+ goto failure;
+ p += i;
+ i = ssh1_read_bignum(p, msgend - p, &reqkey.modulus);
+ if (i < 0)
+ goto failure;
+ p += i;
+ i = ssh1_read_bignum(p, msgend - p, &challenge);
+ if (i < 0)
+ goto failure;
+ p += i;
+ if (msgend < p+16) {
+ freebn(reqkey.exponent);
+ freebn(reqkey.modulus);
+ freebn(challenge);
+ goto failure;
+ }
memcpy(response_source + 32, p, 16);
p += 16;
- if (GET_32BIT(p) != 1 ||
+ if (msgend < p+4 ||
+ GET_32BIT(p) != 1 ||
(key = find234(rsakeys, &reqkey, NULL)) == NULL) {
freebn(reqkey.exponent);
freebn(reqkey.modulus);
unsigned char *data, *signature;
int datalen, siglen, len;
+ if (msgend < p+4)
+ goto failure;
b.len = GET_32BIT(p);
p += 4;
+ if (msgend < p+b.len)
+ goto failure;
b.blob = p;
p += b.len;
+ if (msgend < p+4)
+ goto failure;
datalen = GET_32BIT(p);
p += 4;
+ if (msgend < p+datalen)
+ goto failure;
data = p;
key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
if (!key)
{
struct RSAKey *key;
char *comment;
- int commentlen;
+ int n, commentlen;
+
key = snew(struct RSAKey);
memset(key, 0, sizeof(struct RSAKey));
- p += makekey(p, key, NULL, 1);
- p += makeprivate(p, key);
- p += ssh1_read_bignum(p, &key->iqmp); /* p^-1 mod q */
- p += ssh1_read_bignum(p, &key->p); /* p */
- p += ssh1_read_bignum(p, &key->q); /* q */
+
+ n = makekey(p, msgend - p, key, NULL, 1);
+ if (n < 0) {
+ freersakey(key);
+ sfree(key);
+ goto failure;
+ }
+ p += n;
+
+ n = makeprivate(p, msgend - p, key);
+ if (n < 0) {
+ freersakey(key);
+ sfree(key);
+ goto failure;
+ }
+ p += n;
+
+ n = ssh1_read_bignum(p, msgend - p, &key->iqmp); /* p^-1 mod q */
+ if (n < 0) {
+ freersakey(key);
+ sfree(key);
+ goto failure;
+ }
+ p += n;
+
+ n = ssh1_read_bignum(p, msgend - p, &key->p); /* p */
+ if (n < 0) {
+ freersakey(key);
+ sfree(key);
+ goto failure;
+ }
+ p += n;
+
+ n = ssh1_read_bignum(p, msgend - p, &key->q); /* q */
+ if (n < 0) {
+ freersakey(key);
+ sfree(key);
+ goto failure;
+ }
+ p += n;
+
+ if (msgend < p+4) {
+ freersakey(key);
+ sfree(key);
+ goto failure;
+ }
commentlen = GET_32BIT(p);
+
+ if (msgend < p+commentlen) {
+ freersakey(key);
+ sfree(key);
+ goto failure;
+ }
+
comment = snewn(commentlen+1, char);
if (comment) {
memcpy(comment, p + 4, commentlen);
int alglen, commlen;
int bloblen;
- key = snew(struct ssh2_userkey);
+ if (msgend < p+4)
+ goto failure;
alglen = GET_32BIT(p);
p += 4;
+ if (msgend < p+alglen)
+ goto failure;
alg = p;
p += alglen;
+
+ key = snew(struct ssh2_userkey);
/* Add further algorithm names here. */
if (alglen == 7 && !memcmp(alg, "ssh-rsa", 7))
key->alg = &ssh_rsa;
goto failure;
}
- bloblen =
- GET_32BIT((unsigned char *) msg) - (p -
- (unsigned char *) msg -
- 4);
+ bloblen = msgend - p;
key->data = key->alg->openssh_createkey(&p, &bloblen);
if (!key->data) {
sfree(key);
goto failure;
}
+
+ /*
+ * p has been advanced by openssh_createkey, but
+ * certainly not _beyond_ the end of the buffer.
+ */
+ assert(p <= msgend);
+
+ if (msgend < p+4) {
+ key->alg->freekey(key->data);
+ sfree(key);
+ goto failure;
+ }
commlen = GET_32BIT(p);
p += 4;
+ if (msgend < p+commlen) {
+ key->alg->freekey(key->data);
+ sfree(key);
+ goto failure;
+ }
comment = snewn(commlen + 1, char);
if (comment) {
memcpy(comment, p, commlen);
*/
{
struct RSAKey reqkey, *key;
+ int n;
+
+ n = makekey(p, msgend - p, &reqkey, NULL, 0);
+ if (n < 0)
+ goto failure;
- p += makekey(p, &reqkey, NULL, 0);
key = find234(rsakeys, &reqkey, NULL);
freebn(reqkey.exponent);
freebn(reqkey.modulus);
struct ssh2_userkey *key;
struct blob b;
+ if (msgend < p+4)
+ goto failure;
b.len = GET_32BIT(p);
p += 4;
+
+ if (msgend < p+b.len)
+ goto failure;
b.blob = p;
p += b.len;
+
key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
if (!key)
goto failure;
}
}
+/*
+ * This is a can't-happen stub, since Pageant never makes
+ * asynchronous agent requests.
+ */
+void agent_schedule_callback(void (*callback)(void *, void *, int),
+ void *callback_ctx, void *data, int len)
+{
+ assert(!"We shouldn't get here");
+}
+
void cleanup_exit(int code) { exit(code); }
+int flags = FLAG_SYNCAGENT;
+
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
{
WNDCLASS wndclass;
MSG msg;
- OSVERSIONINFO osi;
HMODULE advapi;
char *command = NULL;
int added_keys = 0;
* Determine whether we're an NT system (should have security
* APIs) or a non-NT system (don't do security).
*/
- memset(&osi, 0, sizeof(OSVERSIONINFO));
- osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (GetVersionEx(&osi) && osi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+ if (!init_winver())
+ {
+ modalfatalbox("Windows refuses to report a version");
+ }
+ if (osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT) {
has_security = TRUE;
} else
has_security = FALSE;