📄 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 + -