Permalink
Browse files

Memory Cleanup Fix & Various Refactoring

- Addressed issue where CryptDestroyHash was being called after
CryptReleaseContext.
- Enhanced code layout and CAPI related debugging when compiled in debug
mode.
- Various refactoring.
  • Loading branch information...
NoMoreFood committed Mar 19, 2017
1 parent 3ed740d commit e4bc505bf609157713a80137b7742a993ad04ad9
View
678 capi.c

Large diffs are not rendered by default.

Oops, something went wrong.
View
28 capi.h
@@ -3,10 +3,8 @@
* Andrew Prout, aprout at ll mit edu
*/
#ifndef PUTTY_CAPI_H
#define PUTTY_CAPI_H
#ifdef _WINDOWS
#pragma once
#ifdef PUTTY_CAC
struct capi_keyhandle_struct {
void* win_provider;
@@ -19,25 +17,21 @@ struct capi_keyhandle_struct {
struct capi_userkey {
unsigned char *blob;
int bloblen;
char *certID; // StoreType\StoreName\HexSHA1
char *certid; // StoreType\StoreName\HexSHA1
};
#define capi_userkey_Comment_Length(x) (strlen(x->certID) + 5 /* "CAPI:" */)
extern struct ssh2_userkey capi_key_ssh2_userkey;
BOOL capi_get_pubkey(void *f, char* certID, unsigned char** pubkey, char **algorithm, int *blob_len);
BOOL capi_get_key_handle(void *f, char* certID, struct capi_keyhandle_struct** keyhandle);
BOOL capi_display_cert_ui(HWND hwnd, char* certID, WCHAR* title);
//BOOL capi_get_cert_handle(char* certID, PCCERT_CONTEXT* oCertContext);
unsigned char* capi_sig(struct capi_keyhandle_struct* keyhandle, char *sigdata, int sigdata_len, int *sigblob_len);
unsigned char* capi_sig_certid(char* certID, const char *sigdata, int sigdata_len, int *sigblob_len);
BOOL capi_get_pubkey(char* certid, unsigned char** pubkey, char **algorithm, int *blob_len);
BOOL capi_get_key_handle(char* certid, struct capi_keyhandle_struct** keyhandle);
BOOL capi_display_cert_ui(HWND hwnd, char* certid, WCHAR* title);
unsigned char* capi_sig(HCRYPTPROV hProv, DWORD keyspec, const char* sigdata, int sigdata_len, int* sigblob_len);
unsigned char* capi_sig_certid(char* certid, const char *sigdata, int sigdata_len, int *sigblob_len);
void capi_release_key(struct capi_keyhandle_struct** keyhandle);
char* capi_get_key_string(char* certID);
char* capi_get_key_string(char* certid);
char* capi_userkey_getcomment(struct capi_userkey* ckey);
struct capi_userkey* create_capi_userkey(const char* certID, PCERT_CONTEXT pCertContext);
struct capi_userkey* create_capi_userkey(const char* certid, PCERT_CONTEXT pCertContext);
void free_capi_userkey(struct capi_userkey* ckey);
#endif //#ifdef _WINDOWS
#endif //#ifndef PUTTY_CAPI_H
#endif // PUTTY_CAC
View
@@ -619,7 +619,7 @@ struct sessionsaver_data {
#ifdef PUTTY_CAC
struct capi_data {
union control *certstore_droplist, *certID_text, *cert_browse, *keystring_text;
union control *certstore_droplist, *certid_text, *cert_browse, *keystring_text;
};
void capi_certstore_handler(union control *ctrl, void *dlg, void *data, int event ) {
@@ -632,7 +632,7 @@ void capi_certstore_handler(union control *ctrl, void *dlg, void *data, int even
dlg_listbox_clear(ctrl, dlg);
dlg_listbox_add(ctrl, dlg, "User\\MY (Personal Certificates)");
dlg_listbox_add(ctrl, dlg, "System\\MY (Personal Certificates)");
if (strncmp(conf_get_str(conf, CONF_capi_certID), "System\\MY", 9) == 0)
if (strncmp(conf_get_str(conf, CONF_capi_certid), "System\\MY", 9) == 0)
dlg_listbox_select(ctrl, dlg, 1);
else
dlg_listbox_select(ctrl, dlg, 0); /* *shrug* */
@@ -641,20 +641,20 @@ void capi_certstore_handler(union control *ctrl, void *dlg, void *data, int even
}
}
void capi_certID_handler(union control *ctrl, void *dlg, void *data, int event ) {
void capi_certid_handler(union control *ctrl, void *dlg, void *data, int event ) {
Conf *conf = (Conf *)data;
struct capi_data *capid = (struct capi_data *)ctrl->generic.context.p;
char* tmpKeystring = NULL;
if (event == EVENT_REFRESH) {
dlg_editbox_set(ctrl, dlg, conf_get_str(conf, CONF_capi_certID));
dlg_editbox_set(ctrl, dlg, conf_get_str(conf, CONF_capi_certid));
} else if (event == EVENT_VALCHANGE) {
//dlg_editbox_get(ctrl, dlg, conf_get_str(conf, CONF_capi_certID), sizeof(conf_get_str(conf, CONF_capi_certID)));
conf_set_str(conf, CONF_capi_certID, dlg_editbox_get(ctrl, dlg));
//dlg_editbox_get(ctrl, dlg, conf_get_str(conf, CONF_capi_certid), sizeof(conf_get_str(conf, CONF_capi_certid)));
conf_set_str(conf, CONF_capi_certid, dlg_editbox_get(ctrl, dlg));
}
if (conf_get_str(conf, CONF_capi_certID)) { //[0]
if ((tmpKeystring = capi_get_key_string(conf_get_str(conf, CONF_capi_certID))) != NULL) {
if (conf_get_str(conf, CONF_capi_certid)) { //[0]
if ((tmpKeystring = capi_get_key_string(conf_get_str(conf, CONF_capi_certid))) != NULL) {
dlg_editbox_set(capid->keystring_text, dlg, tmpKeystring);
free(tmpKeystring);
tmpKeystring = NULL;
@@ -729,11 +729,11 @@ void capi_certstore_browse_handler(union control *ctrl, void *dlg, void *data, i
tmpSHA1hex[sizeof(tmpSHA1hex)-1] = '\0';
_snprintf(tmpCertID, sizeof(tmpCertID)-1, "%s\\%s", i == 1 ? "Machine\\MY" : "User\\MY", tmpSHA1hex);
tmpCertID[sizeof(tmpCertID)-1] = '\0';
dlg_editbox_set(capid->certID_text, dlg, tmpCertID);
dlg_editbox_set(capid->certid_text, dlg, tmpCertID);
//strncpy(conf_get_str(conf, CONF_capi_certID), tmpCertID, sizeof(conf_get_str(conf, CONF_capi_certID)));
//conf_get_str(conf, CONF_capi_certID)[sizeof(conf_get_str(conf, CONF_capi_certID))-1] = '\0';
conf_set_str(conf, CONF_capi_certID, tmpCertID);
//strncpy(conf_get_str(conf, CONF_capi_certid), tmpCertID, sizeof(conf_get_str(conf, CONF_capi_certid)));
//conf_get_str(conf, CONF_capi_certid)[sizeof(conf_get_str(conf, CONF_capi_certid))-1] = '\0';
conf_set_str(conf, CONF_capi_certid, tmpCertID);
if ((tmpKeystring = capi_get_key_string(tmpCertID)) != NULL) {
dlg_editbox_set(capid->keystring_text, dlg, tmpKeystring);
@@ -2555,13 +2555,13 @@ void setup_config_box(struct controlbox *b, int midsession,
capi_certstore_handler, P(capid));
ctrl_columns(s, 2, 75, 25);
capid->certID_text =
capid->certid_text =
ctrl_editbox(s, "Cert:", NO_SHORTCUT, 80,
HELPCTX(ssh_auth_capi_certstore_label),
capi_certID_handler
capi_certid_handler
, P(capid), P(NULL)
);
capid->certID_text->generic.column = 0;
capid->certid_text->generic.column = 0;
capid->cert_browse = ctrl_pushbutton(s, "Browse", NO_SHORTCUT,
HELPCTX(ssh_auth_capi),
capi_certstore_browse_handler, P(capid));
View
BIN +0 Bytes (100%) executables/pageant.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/plink.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/pscp.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/psftp.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/putty.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/puttygen.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/puttytel.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/testbn.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/x64/pageant.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/x64/plink.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/x64/pscp.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/x64/psftp.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/x64/putty.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/x64/puttygen.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/x64/puttytel.exe
Binary file not shown.
View
BIN +0 Bytes (100%) executables/x64/testbn.exe
Binary file not shown.
View
@@ -1,7 +1,7 @@
@ECHO OFF
PUSHD "%~dp0"
SET VER=0.68
SET VER=0.68u1
IF DEFINED ProgramFiles SET PATH=%PATH%;%ProgramFiles%\WiX Toolset v3.11\bin
IF DEFINED ProgramFiles(x86) SET PATH=%PATH%;%ProgramFiles(x86)%\WiX Toolset v3.11\bin
View
@@ -5,6 +5,7 @@ FOR %%X IN (Win32 x64 Debug Release .vs) DO (
)
FOR %%X IN (Win32 x64 Debug Release) DO (
FORFILES /S /P "%~dp0..\executables" /M "*.pdb" /C "CMD /C DEL /Q @path"
FORFILES /S /P "%~dp0..\executables" /M "*.log" /C "CMD /C DEL /Q @path"
)
PAUSE
View
@@ -174,20 +174,16 @@ static int cmpkeys_ssh2_asymm(void *av, void *bv)
#ifdef PUTTY_CAC
// Key comparison function for the 2-3-4 tree of CAPI keys (struct capi_userkey) where the first argument is a blob.
static int cmpkeys_capi(void *av, void *bv) {
struct blob {
unsigned char *blob;
int len;
};
struct blob *a = (struct blob *) av;
struct blob *b = (struct blob *) bv;
struct capi_userkey *a = (struct capi_userkey *) av;
struct capi_userkey *b = (struct capi_userkey *) bv;
int i;
int c;
/*
* Compare purely by public blob.
*/
c = 0;
for (i = 0; i < a->len && i < b->len; i++) {
for (i = 0; i < a->bloblen && i < b->bloblen; i++) {
if (a->blob[i] < b->blob[i]) {
c = -1;
break;
@@ -197,9 +193,9 @@ static int cmpkeys_capi(void *av, void *bv) {
break;
}
}
if (c == 0 && i < a->len)
if (c == 0 && i < a->bloblen)
c = +1; /* a is longer */
if (c == 0 && i < b->len)
if (c == 0 && i < b->bloblen)
c = -1; /* b is longer */
return c;
@@ -284,7 +280,7 @@ void *pageant_make_keylist2(int *length)
nkeys++;
len += 4; /* length field */
len += ckey->bloblen;
len += 4 + strlen(ckey->certID) + 5; /* "CAPI:" */
len += 4 + strlen(ckey->certid) + 5; /* "CAPI:" */
}
#endif /* PUTTY_CAC */
@@ -590,7 +586,7 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
#ifdef PUTTY_CAC
ckey = find234(capikeys, &b, cmpkeys_capi);
if (ckey) {
if ((signature = capi_sig_certid(ckey->certID, data, datalen, &siglen)) == NULL)
if ((signature = capi_sig_certid(ckey->certid, data, datalen, &siglen)) == NULL)
goto failure;
}
else {
@@ -752,19 +748,19 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
#ifdef PUTTY_CAC
if (alglen == 4 && memcmp(alg, "CAPI", 4) == 0) {
struct capi_userkey *ckey;
const char *certID;
int certIDlen;
const char *certid;
int certidlen;
if (msgend < p + 4)
goto failure;
certIDlen = GET_32BIT(p);
certidlen = GET_32BIT(p);
p += 4;
if (msgend < p + certIDlen)
if (msgend < p + certidlen)
goto failure;
certID = p;
certid = p;
if ((ckey = create_capi_userkey(certID, NULL)) == NULL)
if ((ckey = create_capi_userkey(certid, NULL)) == NULL)
goto failure;
if (add234(capikeys, ckey) != ckey)
free_capi_userkey(ckey); // already loaded, free our (unused) copy
@@ -1424,10 +1420,10 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
if (strnicmp(filename_to_str(filename), "CAPI:", 5) == 0) {
const char *fn = filename_to_str(filename);
const char *certID = &fn[5];
const char *certid = &fn[5];
CAPI_KEY = TRUE;
if ((ckey = create_capi_userkey(certID, NULL)) == NULL) {
char *msg = dupprintf("Couldn't load CAPI certificate/key: %s", certID);
if ((ckey = create_capi_userkey(certid, NULL)) == NULL) {
char *msg = dupprintf("Couldn't load CAPI certificate/key: %s", certid);
message_box(msg, "Pageant", MB_OK | MB_ICONERROR, HELPCTXID(errors_cantloadkey));
sfree(msg);
return PAGEANT_ACTION_FAILURE;
@@ -1450,7 +1446,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
* which may or may not be us).
*/
{
void *blob;
void *blob = NULL;
unsigned char *keylist, *p;
int i, nkeys, bloblen, keylistlen;
@@ -1592,7 +1588,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
reqlen = 4 + 1 + // length, message type
4 + 4 + // length, "CAPI"
4 + strlen(ckey->certID); // length + certID string
4 + strlen(ckey->certid); // length + certid string
p = request = snewn(reqlen, unsigned char);
PUT_32BIT(p, reqlen - 4);
@@ -1604,10 +1600,10 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
memcpy(p, "CAPI", 4);
p += 4;
PUT_32BIT(p, strlen(ckey->certID));
PUT_32BIT(p, strlen(ckey->certid));
p += 4;
memcpy(p, ckey->certID, strlen(ckey->certID));
p += strlen(ckey->certID);
memcpy(p, ckey->certid, strlen(ckey->certid));
p += strlen(ckey->certid);
ret = agent_query(request, reqlen, &response, &resplen, NULL, NULL);
assert(ret == NULL);
View
@@ -737,7 +737,7 @@ void cleanup_exit(int);
X(INT, NONE, try_ki_auth) \
/* PUTTY_CAC START */ \
X(INT, NONE, try_capi_auth) /* check box */ \
X(STR, NONE, capi_certID) /* {Machine|User}\{Store Name}\cert sha-1 fingerprint (in hex) */ \
X(STR, NONE, capi_certid) /* {Machine|User}\{Store Name}\cert sha-1 fingerprint (in hex) */ \
/* PUTTY_CAC END */ \
X(INT, NONE, try_gssapi_auth) /* attempt gssapi auth */ \
X(INT, NONE, gssapifwd) /* forward tgt via gss */ \
View
@@ -537,7 +537,7 @@ void save_open_settings(void *sesskey, Conf *conf)
write_setting_i(sesskey, "RFCEnviron", conf_get_int(conf, CONF_rfc_environ));
#ifdef PUTTY_CAC
write_setting_i(sesskey, "AuthCAPI", conf_get_int(conf, CONF_try_capi_auth));
write_setting_s(sesskey, "CAPICertID", conf_get_str(conf, CONF_capi_certID));
write_setting_s(sesskey, "CAPICertID", conf_get_str(conf, CONF_capi_certid));
#endif // PUTTY_CAC
write_setting_i(sesskey, "PassiveTelnet", conf_get_int(conf, CONF_passive_telnet));
write_setting_i(sesskey, "BackspaceIsDelete", conf_get_int(conf, CONF_bksp_is_delete));
@@ -874,7 +874,7 @@ void load_open_settings(void *sesskey, Conf *conf)
gppi(sesskey, "PassiveTelnet", 0, conf, CONF_passive_telnet);
#ifdef PUTTY_CAC
gppi(sesskey, "AuthCAPI", 0, conf, CONF_try_capi_auth);
gpps(sesskey, "CAPICertID", "", conf, CONF_capi_certID);
gpps(sesskey, "CAPICertID", "", conf, CONF_capi_certid);
#endif // PUTTY_CAC
gppi(sesskey, "BackspaceIsDelete", 1, conf, CONF_bksp_is_delete);
gppi(sesskey, "RXVTHomeEnd", 0, conf, CONF_rxvt_homeend);
View
29 ssh.c
@@ -9403,11 +9403,11 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
#ifdef PUTTY_CAC
else if (conf_get_int(ssh->conf, CONF_try_capi_auth)) {
logeventf(ssh, "Use CAPI cert (%s)", conf_get_str(ssh->conf, CONF_capi_certID));
if (capi_get_pubkey(ssh->frontend, conf_get_str(ssh->conf, CONF_capi_certID), (unsigned char**) &s->publickey_blob, &s->publickey_algorithm, &s->publickey_bloblen)) {
logeventf(ssh, "Use CAPI cert (%s)", conf_get_str(ssh->conf, CONF_capi_certid));
if (capi_get_pubkey(conf_get_str(ssh->conf, CONF_capi_certid), (unsigned char**) &s->publickey_blob, &s->publickey_algorithm, &s->publickey_bloblen)) {
s->capi_key_loaded = TRUE;
s->publickey_comment = calloc(strlen(conf_get_str(ssh->conf, CONF_capi_certID)) + 6, 1);
_snprintf(s->publickey_comment, strlen(conf_get_str(ssh->conf, CONF_capi_certID)) + 6, "CAPI:%s", conf_get_str(ssh->conf, CONF_capi_certID));
s->publickey_comment = calloc(strlen(conf_get_str(ssh->conf, CONF_capi_certid)) + 6, 1);
_snprintf(s->publickey_comment, strlen(conf_get_str(ssh->conf, CONF_capi_certid)) + 6, "CAPI:%s", conf_get_str(ssh->conf, CONF_capi_certid));
}
}
#endif // PUTTY_CAC
@@ -10025,15 +10025,15 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
*/
s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
#ifdef PUTTY_CAC
if(s->can_capi && s->capi_key_loaded) {/*chained off the else above*/
if (capi_get_key_handle(ssh->frontend, conf_get_str(ssh->conf, CONF_capi_certID), &s->capi_keyhandle)) {
key = &capi_key_ssh2_userkey; // special flag-struct
}
else {
logeventf(ssh, "capi_get_key_handle(%s) returned false. s->capi_keyhandle=%08x", conf_get_str(ssh->conf, CONF_capi_certID), s->capi_keyhandle);
error = "Failed to load CAPI key";
}
}
if (s->can_capi && s->capi_key_loaded) {/*chained off the else above*/
if (capi_get_key_handle(conf_get_str(ssh->conf, CONF_capi_certid), &s->capi_keyhandle)) {
key = &capi_key_ssh2_userkey; // special flag-struct
}
else {
logeventf(ssh, "capi_get_key_handle(%s) returned false. s->capi_keyhandle=%08x", conf_get_str(ssh->conf, CONF_capi_certid), s->capi_keyhandle);
error = "Failed to load CAPI key";
}
}
else
#endif // PUTTY_CAC
key = ssh2_load_userkey(s->keyfile, passphrase, &error);
@@ -10122,7 +10122,8 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
assert(p == sigdata_len);
#ifdef PUTTY_CAC
if (s->capi_key_loaded && (s->capi_keyhandle != NULL)) { /* chained off else from above */
if ((sigblob = capi_sig(s->capi_keyhandle, sigdata, sigdata_len, &sigblob_len)) == NULL) {
if ((sigblob = capi_sig(s->capi_keyhandle->win_provider,
s->capi_keyhandle->win_keyspec, sigdata, sigdata_len, &sigblob_len)) == NULL) {
capi_release_key(&s->capi_keyhandle);
sfree(pkblob);
sfree(sigdata);
@@ -101,7 +101,7 @@
<ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName>
<WholeProgramOptimization>true</WholeProgramOptimization>
<DebugInformationFormat>None</DebugInformationFormat>
<ExceptionHandling>false</ExceptionHandling>
<ExceptionHandling>Sync</ExceptionHandling>
<IntrinsicFunctions>true</IntrinsicFunctions>
<DisableSpecificWarnings>4018;4267</DisableSpecificWarnings>
</ClCompile>
@@ -151,7 +151,7 @@
<ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName>
<WholeProgramOptimization>true</WholeProgramOptimization>
<DebugInformationFormat>None</DebugInformationFormat>
<ExceptionHandling>false</ExceptionHandling>
<ExceptionHandling>Sync</ExceptionHandling>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>PUTTY_CAC;NDEBUG;_WIN32_WINNT=_WIN32_WINNT_WIN6;WINVER=_WIN32_WINNT_WIN6;_WINDOWS;POSIX;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4018;4267;4244</DisableSpecificWarnings>
@@ -225,6 +225,7 @@
<SubSystem>Windows</SubSystem>
<OutputFile>..\..\..\executables\$(TargetFileName)</OutputFile>
<AdditionalDependencies>advapi32.lib;comctl32.lib;comdlg32.lib;gdi32.lib;imm32.lib;ole32.lib;shell32.lib;user32.lib;winmm.lib;winspool.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -266,6 +267,7 @@
<SubSystem>Windows</SubSystem>
<OutputFile>..\..\..\executables\x64\$(TargetFileName)</OutputFile>
<AdditionalDependencies>advapi32.lib;comctl32.lib;comdlg32.lib;gdi32.lib;imm32.lib;ole32.lib;shell32.lib;user32.lib;winmm.lib;winspool.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
Oops, something went wrong.

0 comments on commit e4bc505

Please sign in to comment.