svnno****@sourc*****
svnno****@sourc*****
2011年 2月 19日 (土) 20:07:05 JST
Revision: 4324 http://sourceforge.jp/projects/ttssh2/svn/view?view=rev&revision=4324 Author: maya Date: 2011-02-19 20:07:05 +0900 (Sat, 19 Feb 2011) Log Message: ----------- SSH2 ã® ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521 å ¬ééµèªè¨¼ããµãã¼ããã Modified Paths: -------------- trunk/doc/en/html/about/history.html trunk/doc/ja/html/about/history.html trunk/installer/release/lang/English.lng trunk/installer/release/lang/French.lng trunk/installer/release/lang/German.lng trunk/installer/release/lang/Japanese.lng trunk/ttssh2/ttxssh/auth.c trunk/ttssh2/ttxssh/key.c trunk/ttssh2/ttxssh/keyfiles.c trunk/ttssh2/ttxssh/ttxssh.rc -------------- next part -------------- Modified: trunk/doc/en/html/about/history.html =================================================================== --- trunk/doc/en/html/about/history.html 2011-02-19 08:11:10 UTC (rev 4323) +++ trunk/doc/en/html/about/history.html 2011-02-19 11:07:05 UTC (rev 4324) @@ -1636,6 +1636,7 @@ <li>added support for confirming agent-forwarding request.</li> <!--li>SSH2 Ì diffie-hellman-group-exchange-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521 ®ð·vgRðT|[gµ½B</li--> <!--li>SSH2 Ì ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521 zXg®û®ðT|[gµ½B</li--> + <!--li>SSH2 Ì ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521 öJ®FØðT|[gµ½B</li--> </ul> </li> Modified: trunk/doc/ja/html/about/history.html =================================================================== --- trunk/doc/ja/html/about/history.html 2011-02-19 08:11:10 UTC (rev 4323) +++ trunk/doc/ja/html/about/history.html 2011-02-19 11:07:05 UTC (rev 4324) @@ -1637,6 +1637,7 @@ <li>SSHG[WFg]ðv³ê½Æ«ÉAó¯üêé©Ç¤©[UÉmF·é@\ðÇÁµ½B</li> <li>SSH2 Ì diffie-hellman-group-exchange-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521 ®ð·vgRðT|[gµ½B</li> <li>SSH2 Ì ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521 zXg®û®ðT|[gµ½B</li> + <li>SSH2 Ì ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521 öJ®FØðT|[gµ½B</li> </ul> </li> Modified: trunk/installer/release/lang/English.lng =================================================================== --- trunk/installer/release/lang/English.lng 2011-02-19 08:11:10 UTC (rev 4323) +++ trunk/installer/release/lang/English.lng 2011-02-19 11:07:05 UTC (rev 4324) @@ -510,9 +510,9 @@ DLG_AUTHSETUP_HOST_PRIVATEKEY=Host private key &file: DLG_AUTHSETUP_CHECKAUTH=&Check the enabled authentication methods before login (SSH2) -FILEDLG_OPEN_PRIVATEKEY_TITLE=Choose a file with the RSA/DSA private key -FILEDLG_OPEN_PRIVATEKEY_FILTER=identity files\0identity;id_rsa;id_dsa\0identity(RSA1)\0identity\0id_rsa(SSH2)\0id_rsa\0id_dsa(SSH2)\0id_dsa\0all(*.*)\0*.*\0\0 -MSG_KEYSPECIFY_ERROR=You must specify a file containing the RSA/DSA private key. +FILEDLG_OPEN_PRIVATEKEY_TITLE=Choose a file with the RSA/DSA/ECDSA private key +FILEDLG_OPEN_PRIVATEKEY_FILTER=identity files\0identity;id_rsa;id_dsa;id_ecdsa\0identity(RSA1)\0identity\0id_rsa(SSH2)\0id_rsa\0id_dsa(SSH2)\0id_dsa\0id_ecdsa(SSH2)\0id_ecdsa\0all(*.*)\0*.*\0\0 +MSG_KEYSPECIFY_ERROR=You must specify a file containing the RSA/DSA/ECDSA private key. MSG_READKEY_ERROR=read error SSH2 private key file\n%s MSG_RHOSTS_NOTDEFAULT_ERROR=Rhosts authentication will probably fail because it was not the default authentication method.\nTo use Rhosts authentication in TTSSH, you need to set it to be the default by restarting\nTTSSH and selecting "SSH Authentication..." from the Setup menubefore connecting. MSG_NOAUTHMETHOD_ERROR=Server does not support any of the authentication options\nprovided by TTSSH. This connection will now close. Modified: trunk/installer/release/lang/French.lng =================================================================== --- trunk/installer/release/lang/French.lng 2011-02-19 08:11:10 UTC (rev 4323) +++ trunk/installer/release/lang/French.lng 2011-02-19 11:07:05 UTC (rev 4324) @@ -509,9 +509,9 @@ DLG_AUTHSETUP_HOST_PRIVATEKEY=Fichier clé privée hôte: DLG_AUTHSETUP_CHECKAUTH=Vérifier la méthode d'authentification autorisée avant la connexion (SSH2) -FILEDLG_OPEN_PRIVATEKEY_TITLE=Choisir le fichier contenant la clé privée RSA/DSA -FILEDLG_OPEN_PRIVATEKEY_FILTER=identity files\0identity;id_rsa;id_dsa\0identity(RSA1)\0identity\0id_rsa(SSH2)\0id_rsa\0id_dsa(SSH2)\0id_dsa\0all(*.*)\0*.*\0\0 -MSG_KEYSPECIFY_ERROR=Vous devez spécifier un fichier contenant la clé privée RSA/DSA. +FILEDLG_OPEN_PRIVATEKEY_TITLE=Choisir le fichier contenant la clé privée RSA/DSA/ECDSA +FILEDLG_OPEN_PRIVATEKEY_FILTER=identity files\0identity;id_rsa;id_dsa;id_ecdsa\0identity(RSA1)\0identity\0id_rsa(SSH2)\0id_rsa\0id_dsa(SSH2)\0id_dsa\0id_ecdsa(SSH2)\0id_ecdsa\0all(*.*)\0*.*\0\0 +MSG_KEYSPECIFY_ERROR=Vous devez spécifier un fichier contenant la clé privée RSA/DSA/ECDSA. MSG_READKEY_ERROR=Erreur de lecture du fichier de clé privée SSH2\n%s MSG_RHOSTS_NOTDEFAULT_ERROR=L'authentification Rhosts va probablement échouer car ce n'est pas la méthode d'authentification par défaut.\nPour utiliser l'authentification Rhosts avec TTSSH, il faut la paramétrer par défaut en redémarrant\nTTSSH et en sélectionnant "Authentification SSH..." dans le menu de configuration avant de vous connecter. MSG_NOAUTHMETHOD_ERROR=Le serveur ne supporte aucune des options d'authentification\nfournies par TTSSH. Cette connexion va maintenant être fermée. Modified: trunk/installer/release/lang/German.lng =================================================================== --- trunk/installer/release/lang/German.lng 2011-02-19 08:11:10 UTC (rev 4323) +++ trunk/installer/release/lang/German.lng 2011-02-19 11:07:05 UTC (rev 4324) @@ -508,10 +508,10 @@ DLG_AUTHSETUP_HOST_PRIVATEKEY=rhosts-Schlüssel: DLG_AUTHSETUP_CHECKAUTH=Prüfe die Authentifizierungsmethoden vor dem Logins (SSH2) -FILEDLG_OPEN_PRIVATEKEY_TITLE=DSA/RSA-Schlüssel auswählen -FILEDLG_OPEN_PRIVATEKEY_FILTER=identity files\0identity;*.*;id_rsa;id_dsa\0identity(RSA1)\0identity\0id_rsa(SSH2)\0id_rsa\0id_dsa(SSH2)\0id_dsa\0all(*.*)\0*.*\0\0 -MSG_KEYSPECIFY_ERROR=Bitte einen DSA/RSA-Schlüssel auswählen. -MSG_READKEY_ERROR=Lesefehler des DSA/RSA-Schlüssels\n%s +FILEDLG_OPEN_PRIVATEKEY_TITLE=DSA/RSA/ECDSA-Schlüssel auswählen +FILEDLG_OPEN_PRIVATEKEY_FILTER=identity files\0identity;*.*;id_rsa;id_dsa;id_ecdsa\0identity(RSA1)\0identity\0id_rsa(SSH2)\0id_rsa\0id_dsa(SSH2)\0id_dsa\0id_ecdsa(SSH2)\0id_ecdsa\0all(*.*)\0*.*\0\0 +MSG_KEYSPECIFY_ERROR=Bitte einen DSA/RSA/ECDSA-Schlüssel auswählen. +MSG_READKEY_ERROR=Lesefehler des DSA/RSA/ECDSA-Schlüssels\n%s MSG_RHOSTS_NOTDEFAULT_ERROR=Rhosts authentication will probably fail because it was not the default authentication method.\nTo use Rhosts authentication in TTSSH, you need to set it to be the default by restarting\nTTSSH and selecting "SSH Authentication..." from the Setup menubefore connecting. MSG_NOAUTHMETHOD_ERROR=Der Server unterstützt keine der von TTSSH angebotenen\nAuthentifizierungs-Optionen. Die Verbindung wird beendet. Modified: trunk/installer/release/lang/Japanese.lng =================================================================== --- trunk/installer/release/lang/Japanese.lng 2011-02-19 08:11:10 UTC (rev 4323) +++ trunk/installer/release/lang/Japanese.lng 2011-02-19 11:07:05 UTC (rev 4324) @@ -510,9 +510,9 @@ DLG_AUTHSETUP_HOST_PRIVATEKEY=zXg®(&F): DLG_AUTHSETUP_CHECKAUTH=OCOÉT[oÅLøÈFØû®ðmF·é (SSH2)(&C) -FILEDLG_OPEN_PRIVATEKEY_TITLE=RSA/DSA駮t@CÌIð -FILEDLG_OPEN_PRIVATEKEY_FILTER=駮t@C\0identity;id_rsa;id_dsa\0identity(RSA1)\0identity\0id_rsa(SSH2)\0id_rsa\0id_dsa(SSH2)\0id_dsa\0·×ÄÌt@C(*.*)\0*.*\0\0 -MSG_KEYSPECIFY_ERROR=RSA/DSA駮ÌÜÜêét@CðwèµÄ¾³¢ +FILEDLG_OPEN_PRIVATEKEY_TITLE=RSA/DSA/ECDSA駮t@CÌIð +FILEDLG_OPEN_PRIVATEKEY_FILTER=駮t@C\0identity;id_rsa;id_dsa;id_ecdsa\0identity(RSA1)\0identity\0id_rsa(SSH2)\0id_rsa\0id_dsa(SSH2)\0id_dsa\0id_ecdsa(SSH2)\0id_ecdsa\0·×ÄÌt@C(*.*)\0*.*\0\0 +MSG_KEYSPECIFY_ERROR=RSA/DSA/ECDSA駮ÌÜÜêét@CðwèµÄ¾³¢ MSG_READKEY_ERROR=SSH2駮ÌÇÝÝɸsµÜµ½\n%s MSG_RHOSTS_NOTDEFAULT_ERROR=Rhosts FØÍWÌFØû®ÅÍÈ¢½ß, FØɸs·é©àµêܹñ.\nRhosts FØðTTSSH Ågp·éÉÍ, Rhosts FØðWÉÝèãTTSSH ðÄN®µ, Ú±OÉÝèj [©ç"SSH FØ..." ðIðµÄº³¢. MSG_NOAUTHMETHOD_ERROR=T[oÍTTSSH ªñ·éFØIvVðT|[gµÄ¢Ü¹ñ.\nڱͶçêÜ·. Modified: trunk/ttssh2/ttxssh/auth.c =================================================================== --- trunk/ttssh2/ttxssh/auth.c 2011-02-19 08:11:10 UTC (rev 4323) +++ trunk/ttssh2/ttxssh/auth.c 2011-02-19 11:07:05 UTC (rev 4324) @@ -377,7 +377,7 @@ // tB^ÌÇÁ (2004.12.19 yutaka) // 3t@CtB^ÌÇÁ (2005.4.26 yutaka) UTIL_get_lang_msg("FILEDLG_OPEN_PRIVATEKEY_FILTER", pvar, - "identity files\\0identity;id_rsa;id_dsa\\0identity(RSA1)\\0identity\\0id_rsa(SSH2)\\0id_rsa\\0id_dsa(SSH2)\\0id_dsa\\0all(*.*)\\0*.*\\0\\0"); + "identity files\\0identity;id_rsa;id_dsa;id_ecdsa\\0identity(RSA1)\\0identity\\0id_rsa(SSH2)\\0id_rsa\\0id_dsa(SSH2)\\0id_dsa\\0id_ecdsa(SSH2)\\0id_ecdsa\\0all(*.*)\\0*.*\\0\\0"); memcpy(filter, pvar->ts->UIMsg, sizeof(filter)); params.lpstrFilter = filter; params.lpstrCustomFilter = NULL; @@ -388,7 +388,7 @@ params.lpstrFileTitle = NULL; params.lpstrInitialDir = NULL; UTIL_get_lang_msg("FILEDLG_OPEN_PRIVATEKEY_TITLE", pvar, - "Choose a file with the RSA/DSA private key"); + "Choose a file with the RSA/DSA/ECDSA private key"); params.lpstrTitle = pvar->ts->UIMsg; params.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; @@ -450,7 +450,7 @@ GetDlgItemText(dlg, file_ctl_ID, buf, sizeof(buf)); if (buf[0] == 0) { UTIL_get_lang_msg("MSG_KEYSPECIFY_ERROR", pvar, - "You must specify a file containing the RSA/DSA private key."); + "You must specify a file containing the RSA/DSA/ECDSA private key."); notify_nonfatal_error(pvar, pvar->ts->UIMsg); SetFocus(GetDlgItem(dlg, file_ctl_ID)); destroy_malloced_string(&password); Modified: trunk/ttssh2/ttxssh/key.c =================================================================== --- trunk/ttssh2/ttxssh/key.c 2011-02-19 08:11:10 UTC (rev 4323) +++ trunk/ttssh2/ttxssh/key.c 2011-02-19 11:07:05 UTC (rev 4324) @@ -995,7 +995,9 @@ return FALSE; } - if (keypair->type == KEY_RSA) { // RSA + switch (keypair->type) { + case KEY_RSA: // RSA + { const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; u_char digest[EVP_MAX_MD_SIZE], *sig; @@ -1048,9 +1050,11 @@ } memcpy(*sigptr, buffer_ptr(msg), len); free(sig); - + + break; } - else if (keypair->type == KEY_DSA) { // DSA + case KEY_DSA: // DSA + { DSA_SIG *sig; const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; @@ -1095,10 +1099,72 @@ } memcpy(*sigptr, buffer_ptr(msg), len); + break; } - else { + case KEY_ECDSA256: // ECDSA + case KEY_ECDSA384: + case KEY_ECDSA521: + { + ECDSA_SIG *sig; + const EVP_MD *evp_md; + EVP_MD_CTX md; + u_char digest[EVP_MAX_MD_SIZE]; + u_int len, dlen, nid; + buffer_t *buf2 = NULL; + + switch (keypair->type) { + case KEY_ECDSA256: + nid = NID_sha256; + break; + case KEY_ECDSA384: + nid = NID_sha384; + break; + case KEY_ECDSA521: + nid = NID_sha512; + break; + } + if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { + goto error; + } + EVP_DigestInit(&md, evp_md); + EVP_DigestUpdate(&md, data, datalen); + EVP_DigestFinal(&md, digest, &dlen); + + sig = ECDSA_do_sign(digest, dlen, keypair->ecdsa); + memset(digest, 'd', sizeof(digest)); + + if (sig == NULL) { + goto error; + } + + buf2 = buffer_init(); + if (buf2 == NULL) { + // TODO: error check + goto error; + } + buffer_put_bignum2(buf2, sig->r); + buffer_put_bignum2(buf2, sig->s); + ECDSA_SIG_free(sig); + + s = get_sshname_from_key(keypair); + buffer_put_string(msg, s, strlen(s)); + buffer_put_string(msg, buffer_ptr(buf2), buffer_len(buf2)); + buffer_free(buf2); + len = buffer_len(msg); + + *siglen = len; + *sigptr = malloc(len); + if (*sigptr == NULL) { + goto error; + } + memcpy(*sigptr, buffer_ptr(msg), len); + + break; + } + default: buffer_free(msg); return FALSE; + break; } buffer_free(msg); @@ -1115,7 +1181,7 @@ { buffer_t *msg = NULL; Key *keypair; - char *s; + char *s, *tmp; msg = buffer_init(); if (msg == NULL) { @@ -1125,25 +1191,33 @@ keypair = pvar->auth_state.cur_cred.key_pair; - if (keypair->type == KEY_RSA) { // RSA + switch (keypair->type) { + case KEY_RSA: // RSA s = get_sshname_from_key(keypair); buffer_put_string(msg, s, strlen(s)); buffer_put_bignum2(msg, keypair->rsa->e); // öJw buffer_put_bignum2(msg, keypair->rsa->n); // p~q - - } - else if (keypair->type == KEY_RSA) { // DSA + break; + case KEY_DSA: // DSA s = get_sshname_from_key(keypair); buffer_put_string(msg, s, strlen(s)); buffer_put_bignum2(msg, keypair->dsa->p); // f buffer_put_bignum2(msg, keypair->dsa->q); // (p-1)Ìfö buffer_put_bignum2(msg, keypair->dsa->g); // ® buffer_put_bignum2(msg, keypair->dsa->pub_key); // öJ® - - } - else { + break; + case KEY_ECDSA256: // ECDSA + case KEY_ECDSA384: + case KEY_ECDSA521: + s = get_sshname_from_key(keypair); + buffer_put_string(msg, s, strlen(s)); + tmp = curve_keytype_to_name(keypair->type); + buffer_put_string(msg, tmp, strlen(tmp)); + buffer_put_ecpoint(msg, EC_KEY_get0_group(keypair->ecdsa), + EC_KEY_get0_public_key(keypair->ecdsa)); + break; + default: return FALSE; - } *blobptr = msg; Modified: trunk/ttssh2/ttxssh/keyfiles.c =================================================================== --- trunk/ttssh2/ttxssh/keyfiles.c 2011-02-19 08:11:10 UTC (rev 4323) +++ trunk/ttssh2/ttxssh/keyfiles.c 2011-02-19 11:07:05 UTC (rev 4324) @@ -380,10 +380,12 @@ goto error; } - if (pk->type == EVP_PKEY_RSA) { // RSA key + switch (pk->type) { + case EVP_PKEY_RSA: // RSA key result->type = KEY_RSA; result->rsa = EVP_PKEY_get1_RSA(pk); result->dsa = NULL; + result->ecdsa = NULL; // RSAÚçܵðLøÉ·éi^C~OU©çÌhäj if (RSA_blinding_on(result->rsa, NULL) != 1) { @@ -391,14 +393,41 @@ ERR_error_string_n(err, errmsg, errmsg_len); goto error; } + break; - } else if (pk->type == EVP_PKEY_DSA) { // DSA key + case EVP_PKEY_DSA: // DSA key result->type = KEY_DSA; result->rsa = NULL; result->dsa = EVP_PKEY_get1_DSA(pk); + result->ecdsa = NULL; + break; - } else { + case EVP_PKEY_EC: // ECDSA key + result->rsa = NULL; + result->dsa = NULL; + result->ecdsa = EVP_PKEY_get1_EC_KEY(pk); + { + const EC_GROUP *g = EC_KEY_get0_group(result->ecdsa); + switch (EC_GROUP_get_curve_name(g)) { + case NID_X9_62_prime256v1: + result->type = KEY_ECDSA256; + break; + case NID_secp384r1: + result->type = KEY_ECDSA384; + break; + case NID_secp521r1: + result->type = KEY_ECDSA521; + break; + default: + goto error; + break; + } + } + break; + + default: goto error; + break; } if (pk != NULL) Modified: trunk/ttssh2/ttxssh/ttxssh.rc =================================================================== --- trunk/ttssh2/ttxssh/ttxssh.rc 2011-02-19 08:11:10 UTC (rev 4323) +++ trunk/ttssh2/ttxssh/ttxssh.rc 2011-02-19 11:07:05 UTC (rev 4324) @@ -86,13 +86,13 @@ CONTROL "F&orward agent",IDC_FORWARD_AGENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,75,74,132,10 CONTROL "Use p&lain password to log in",IDC_SSHUSEPASSWORD, "Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,94,219,10 - CONTROL "Use &RSA/DSA key to log in",IDC_SSHUSERSA,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,122,98,10 + CONTROL "Use &RSA/DSA/ECDSA key to log in",IDC_SSHUSERSA,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,122,120,10 CONTROL "Use r&hosts to log in (SSH1)",IDC_SSHUSERHOSTS,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,149,99,10 CONTROL "Use challenge/response to log in (SSH1:&TIS, SSH2:keyboard-interactive)",IDC_SSHUSETIS, "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,14,193,276,10 CONTROL "Use P&ageant",IDC_SSHUSEPAGEANT,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,14,219,276,10 - PUSHBUTTON "Private &key file:",IDC_CHOOSERSAFILE,117,120,58,14,WS_GROUP - EDITTEXT IDC_RSAFILENAME,179,121,118,13,ES_AUTOHSCROLL + PUSHBUTTON "Private &key file:",IDC_CHOOSERSAFILE,139,120,58,14,WS_GROUP + EDITTEXT IDC_RSAFILENAME,201,121,96,13,ES_AUTOHSCROLL RTEXT "Local &user name:",IDC_LOCALUSERNAMELABEL,120,150,91,8,0,WS_EX_RIGHT EDITTEXT IDC_LOCALUSERNAME,214,148,82,13,ES_AUTOHSCROLL PUSHBUTTON "Host private key &file:",IDC_CHOOSEHOSTRSAFILE,92,164,73,14 @@ -208,13 +208,13 @@ EDITTEXT IDC_SSHUSERNAME,75,22,145,12,ES_AUTOHSCROLL CONTROL "Use p&lain password to log in",IDC_SSHUSEPASSWORD, "Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,45,120,10 - CONTROL "Use &RSA/DSA key to log in",IDC_SSHUSERSA,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,73,100,10 + CONTROL "Use &RSA/DSA/ECDSA key to log in",IDC_SSHUSERSA,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,73,122,10 CONTROL "Use r&hosts to log in (SSH1)",IDC_SSHUSERHOSTS,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,100,99,10 CONTROL "Use challenge/response to log in (SSH1:&TIS, SSH2:keyboard-interactive)",IDC_SSHUSETIS, "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,14,144,278,10 CONTROL "Use P&ageant",IDC_SSHUSEPAGEANT,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,14,171,278,10 - PUSHBUTTON "Private &key file:",IDC_CHOOSERSAFILE,117,72,58,14,WS_GROUP - EDITTEXT IDC_RSAFILENAME,179,73,118,13,ES_AUTOHSCROLL + PUSHBUTTON "Private &key file:",IDC_CHOOSERSAFILE,139,72,58,14,WS_GROUP + EDITTEXT IDC_RSAFILENAME,201,73,96,13,ES_AUTOHSCROLL RTEXT "Local &user name:",IDC_LOCALUSERNAMELABEL,118,100,91,8,0,WS_EX_RIGHT EDITTEXT IDC_LOCALUSERNAME,214,99,82,13,ES_AUTOHSCROLL PUSHBUTTON "Host private key &file:",IDC_CHOOSEHOSTRSAFILE,92,114,73,14