📄 pageant.c
字号:
attempts++;
} while (ret == -1);
/* if they typed in an ok passphrase, remember it */
if(original_pass && ret) {
char *pp = dupstr(passphrase);
addpos234(passphrases, pp, 0);
}
if (comment)
sfree(comment);
if (ret == 0) {
MessageBox(NULL, "Couldn't load private key.", APPNAME,
MB_OK | MB_ICONERROR);
if (type == SSH_KEYTYPE_SSH1)
sfree(rkey);
return;
}
if (type == SSH_KEYTYPE_SSH1) {
if (already_running) {
unsigned char *request, *response;
void *vresponse;
int reqlen, clen, resplen, ret;
clen = strlen(rkey->comment);
reqlen = 4 + 1 + /* length, message type */
4 + /* bit count */
ssh1_bignum_length(rkey->modulus) +
ssh1_bignum_length(rkey->exponent) +
ssh1_bignum_length(rkey->private_exponent) +
ssh1_bignum_length(rkey->iqmp) +
ssh1_bignum_length(rkey->p) +
ssh1_bignum_length(rkey->q) + 4 + clen /* comment */
;
request = snewn(reqlen, unsigned char);
request[4] = SSH1_AGENTC_ADD_RSA_IDENTITY;
reqlen = 5;
PUT_32BIT(request + reqlen, bignum_bitcount(rkey->modulus));
reqlen += 4;
reqlen += ssh1_write_bignum(request + reqlen, rkey->modulus);
reqlen += ssh1_write_bignum(request + reqlen, rkey->exponent);
reqlen +=
ssh1_write_bignum(request + reqlen,
rkey->private_exponent);
reqlen += ssh1_write_bignum(request + reqlen, rkey->iqmp);
reqlen += ssh1_write_bignum(request + reqlen, rkey->p);
reqlen += ssh1_write_bignum(request + reqlen, rkey->q);
PUT_32BIT(request + reqlen, clen);
memcpy(request + reqlen + 4, rkey->comment, clen);
reqlen += 4 + clen;
PUT_32BIT(request, reqlen - 4);
ret = agent_query(request, reqlen, &vresponse, &resplen,
NULL, NULL);
assert(ret == 1);
response = vresponse;
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS)
MessageBox(NULL, "The already running Pageant "
"refused to add the key.", APPNAME,
MB_OK | MB_ICONERROR);
sfree(request);
sfree(response);
} else {
if (add234(rsakeys, rkey) != rkey)
sfree(rkey); /* already present, don't waste RAM */
}
} else {
if (already_running) {
unsigned char *request, *response;
void *vresponse;
int reqlen, alglen, clen, keybloblen, resplen, ret;
alglen = strlen(skey->alg->name);
clen = strlen(skey->comment);
keybloblen = skey->alg->openssh_fmtkey(skey->data, NULL, 0);
reqlen = 4 + 1 + /* length, message type */
4 + alglen + /* algorithm name */
keybloblen + /* key data */
4 + clen /* comment */
;
request = snewn(reqlen, unsigned char);
request[4] = SSH2_AGENTC_ADD_IDENTITY;
reqlen = 5;
PUT_32BIT(request + reqlen, alglen);
reqlen += 4;
memcpy(request + reqlen, skey->alg->name, alglen);
reqlen += alglen;
reqlen += skey->alg->openssh_fmtkey(skey->data,
request + reqlen,
keybloblen);
PUT_32BIT(request + reqlen, clen);
memcpy(request + reqlen + 4, skey->comment, clen);
reqlen += clen + 4;
PUT_32BIT(request, reqlen - 4);
ret = agent_query(request, reqlen, &vresponse, &resplen,
NULL, NULL);
assert(ret == 1);
response = vresponse;
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS)
MessageBox(NULL, "The already running Pageant "
"refused to add the key.", APPNAME,
MB_OK | MB_ICONERROR);
sfree(request);
sfree(response);
} else {
if (add234(ssh2keys, skey) != skey) {
skey->alg->freekey(skey->data);
sfree(skey); /* already present, don't waste RAM */
}
}
}
}
/*
* Create an SSH1 key list in a malloc'ed buffer; return its
* length.
*/
static void *make_keylist1(int *length)
{
int i, nkeys, len;
struct RSAKey *key;
unsigned char *blob, *p, *ret;
int bloblen;
/*
* Count up the number and length of keys we hold.
*/
len = 4;
nkeys = 0;
for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {
nkeys++;
blob = rsa_public_blob(key, &bloblen);
len += bloblen;
sfree(blob);
len += 4 + strlen(key->comment);
}
/* Allocate the buffer. */
p = ret = snewn(len, unsigned char);
if (length) *length = len;
PUT_32BIT(p, nkeys);
p += 4;
for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {
blob = rsa_public_blob(key, &bloblen);
memcpy(p, blob, bloblen);
p += bloblen;
sfree(blob);
PUT_32BIT(p, strlen(key->comment));
memcpy(p + 4, key->comment, strlen(key->comment));
p += 4 + strlen(key->comment);
}
assert(p - ret == len);
return ret;
}
/*
* Create an SSH2 key list in a malloc'ed buffer; return its
* length.
*/
static void *make_keylist2(int *length)
{
struct ssh2_userkey *key;
int i, len, nkeys;
unsigned char *blob, *p, *ret;
int bloblen;
/*
* Count up the number and length of keys we hold.
*/
len = 4;
nkeys = 0;
for (i = 0; NULL != (key = index234(ssh2keys, i)); i++) {
nkeys++;
len += 4; /* length field */
blob = key->alg->public_blob(key->data, &bloblen);
len += bloblen;
sfree(blob);
len += 4 + strlen(key->comment);
}
/* Allocate the buffer. */
p = ret = snewn(len, unsigned char);
if (length) *length = len;
/*
* Packet header is the obvious five bytes, plus four
* bytes for the key count.
*/
PUT_32BIT(p, nkeys);
p += 4;
for (i = 0; NULL != (key = index234(ssh2keys, i)); i++) {
blob = key->alg->public_blob(key->data, &bloblen);
PUT_32BIT(p, bloblen);
p += 4;
memcpy(p, blob, bloblen);
p += bloblen;
sfree(blob);
PUT_32BIT(p, strlen(key->comment));
memcpy(p + 4, key->comment, strlen(key->comment));
p += 4 + strlen(key->comment);
}
assert(p - ret == len);
return ret;
}
/*
* Acquire a keylist1 from the primary Pageant; this means either
* calling make_keylist1 (if that's us) or sending a message to the
* primary Pageant (if it's not).
*/
static void *get_keylist1(int *length)
{
void *ret;
if (already_running) {
unsigned char request[5], *response;
void *vresponse;
int resplen, retval;
request[4] = SSH1_AGENTC_REQUEST_RSA_IDENTITIES;
PUT_32BIT(request, 4);
retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL);
assert(retval == 1);
response = vresponse;
if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER)
return NULL;
ret = snewn(resplen-5, unsigned char);
memcpy(ret, response+5, resplen-5);
sfree(response);
if (length)
*length = resplen-5;
} else {
ret = make_keylist1(length);
}
return ret;
}
/*
* Acquire a keylist2 from the primary Pageant; this means either
* calling make_keylist2 (if that's us) or sending a message to the
* primary Pageant (if it's not).
*/
static void *get_keylist2(int *length)
{
void *ret;
if (already_running) {
unsigned char request[5], *response;
void *vresponse;
int resplen, retval;
request[4] = SSH2_AGENTC_REQUEST_IDENTITIES;
PUT_32BIT(request, 4);
retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL);
assert(retval == 1);
response = vresponse;
if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER)
return NULL;
ret = snewn(resplen-5, unsigned char);
memcpy(ret, response+5, resplen-5);
sfree(response);
if (length)
*length = resplen-5;
} else {
ret = make_keylist2(length);
}
return ret;
}
/*
* This is the main agent function that answers messages.
*/
static void answer_msg(void *msg)
{
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;
switch (type) {
case SSH1_AGENTC_REQUEST_RSA_IDENTITIES:
/*
* Reply with SSH1_AGENT_RSA_IDENTITIES_ANSWER.
*/
{
int len;
void *keylist;
ret[4] = SSH1_AGENT_RSA_IDENTITIES_ANSWER;
keylist = make_keylist1(&len);
if (len + 5 > AGENT_MAX_MSGLEN) {
sfree(keylist);
goto failure;
}
PUT_32BIT(ret, len + 1);
memcpy(ret + 5, keylist, len);
sfree(keylist);
}
break;
case SSH2_AGENTC_REQUEST_IDENTITIES:
/*
* Reply with SSH2_AGENT_IDENTITIES_ANSWER.
*/
{
int len;
void *keylist;
ret[4] = SSH2_AGENT_IDENTITIES_ANSWER;
keylist = make_keylist2(&len);
if (len + 5 > AGENT_MAX_MSGLEN) {
sfree(keylist);
goto failure;
}
PUT_32BIT(ret, len + 1);
memcpy(ret + 5, keylist, len);
sfree(keylist);
}
break;
case SSH1_AGENTC_RSA_CHALLENGE:
/*
* Reply with either SSH1_AGENT_RSA_RESPONSE or
* SSH_AGENT_FAILURE, depending on whether we have that key
* or not.
*/
{
struct RSAKey reqkey, *key;
Bignum challenge, response;
unsigned char response_source[48], response_md5[16];
struct MD5Context md5c;
int i, len;
p += 4;
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 (msgend < p+4 ||
GET_32BIT(p) != 1 ||
(key = find234(rsakeys, &reqkey, NULL)) == NULL) {
freebn(reqkey.exponent);
freebn(reqkey.modulus);
freebn(challenge);
goto failure;
}
response = rsadecrypt(challenge, key);
for (i = 0; i < 32; i++)
response_source[i] = bignum_byte(response, 31 - i);
MD5Init(&md5c);
MD5Update(&md5c, response_source, 48);
MD5Final(response_md5, &md5c);
memset(response_source, 0, 48); /* burn the evidence */
freebn(response); /* and that evidence */
freebn(challenge); /* yes, and that evidence */
freebn(reqkey.exponent); /* and free some memory ... */
freebn(reqkey.modulus); /* ... while we're at it. */
/*
* Packet is the obvious five byte header, plus sixteen
* bytes of MD5.
*/
len = 5 + 16;
PUT_32BIT(ret, len - 4);
ret[4] = SSH1_AGENT_RSA_RESPONSE;
memcpy(ret + 5, response_md5, 16);
}
break;
case SSH2_AGENTC_SIGN_REQUEST:
/*
* Reply with either SSH2_AGENT_SIGN_RESPONSE or
* SSH_AGENT_FAILURE, depending on whether we have that key
* or not.
*/
{
struct ssh2_userkey *key;
struct blob b;
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)
goto failure;
signature = key->alg->sign(key->data, data, datalen, &siglen);
len = 5 + 4 + siglen;
PUT_32BIT(ret, len - 4);
ret[4] = SSH2_AGENT_SIGN_RESPONSE;
PUT_32BIT(ret + 5, siglen);
memcpy(ret + 5 + 4, signature, siglen);
sfree(signature);
}
break;
case SSH1_AGENTC_ADD_RSA_IDENTITY:
/*
* Add to the list and return SSH_AGENT_SUCCESS, or
* SSH_AGENT_FAILURE if the key was malformed.
*/
{
struct RSAKey *key;
char *comment;
int n, commentlen;
key = snew(struct RSAKey);
memset(key, 0, sizeof(struct RSAKey));
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);
comment[commentlen] = '\0';
key->comment = comment;
}
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_FAILURE;
if (add234(rsakeys, key) == key) {
keylist_update();
ret[4] = SSH_AGENT_SUCCESS;
} else {
freersakey(key);
sfree(key);
}
}
break;
case SSH2_AGENTC_ADD_IDENTITY:
/*
* Add to the list and return SSH_AGENT_SUCCESS, or
* SSH_AGENT_FAILURE if the key was malformed.
*/
{
struct ssh2_userkey *key;
char *comment, *alg;
int alglen, commlen;
int bloblen;
if (msgend < p+4)
goto failure;
alglen = GET_32BIT(p);
p += 4;
if (msgend < p+alglen)
goto failure;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -