Develop and Download Open Source Software

Browse Subversion Repository

Diff of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ttxssh.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2811 by yutakakn, Fri Apr 8 14:55:03 2005 UTC revision 2816 by yutakakn, Sat Apr 23 17:26:57 2005 UTC
# Line 55  static char FAR *ProtocolFamilyList[] = Line 55  static char FAR *ProtocolFamilyList[] =
55  #include <winsock.h>  #include <winsock.h>
56  #endif                                                  /* INET6 */  #endif                                                  /* INET6 */
57    
58    #include <Lmcons.h>
59    
60    // include OpenSSL header file
61  #include <openssl/opensslv.h>  #include <openssl/opensslv.h>
62    #include <openssl/evp.h>
63    #include <openssl/rsa.h>
64    #include <openssl/dsa.h>
65    #include <openssl/bn.h>
66    #include <openssl/pem.h>
67    #include <openssl/rand.h>
68    #include <openssl/rc4.h>
69    
70    #include "buffer.h"
71    #include "cipher.h"
72    
73  #define MATCH_STR(s, o) _strnicmp((s), (o), NUM_ELEM(o) - 1)  #define MATCH_STR(s, o) _strnicmp((s), (o), NUM_ELEM(o) - 1)
74    
# Line 1380  static void PASCAL FAR TTXModifyMenu(HME Line 1393  static void PASCAL FAR TTXModifyMenu(HME
1393          /* inserts before ID_SETUP_TCPIP */          /* inserts before ID_SETUP_TCPIP */
1394          insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU,          insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU,
1395                                                   "SSH F&orwarding...");                                                   "SSH F&orwarding...");
1396    
1397            insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU,
1398                                                     "SSH KeyGenerator...");
1399  }  }
1400    
1401  static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)  static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
# Line 1930  static BOOL CALLBACK TTXSetupDlg(HWND dl Line 1946  static BOOL CALLBACK TTXSetupDlg(HWND dl
1946          return FALSE;          return FALSE;
1947  }  }
1948    
1949    
1950    //
1951    // SSH key generator dialog (2005.4.10 yutaka)
1952    //
1953    
1954    typedef struct {
1955            RSA *rsa;
1956            DSA *dsa;
1957    } ssh_private_key_t;
1958    
1959    static ssh_private_key_t private_key = {NULL, NULL};
1960    
1961    typedef struct {
1962            RSA *rsa;
1963            DSA *dsa;
1964    } ssh_public_key_t;
1965    
1966    static ssh_public_key_t public_key = {NULL, NULL};;
1967    
1968    static void free_ssh_key(void)
1969    {
1970            // DSA_free(), RSA_free()にNULLを渡しても問題はなし。
1971            DSA_free(private_key.dsa);
1972            private_key.dsa = NULL;
1973            DSA_free(public_key.dsa);
1974            public_key.dsa = NULL;
1975    
1976            RSA_free(private_key.rsa);
1977            private_key.rsa = NULL;
1978            RSA_free(public_key.rsa);
1979            public_key.rsa = NULL;
1980    }
1981    
1982    
1983    static BOOL generate_ssh_key(enum hostkey_type type)
1984    {
1985            int bits = 1024;
1986    
1987            // if SSH key already is generated, should free the resource.
1988            free_ssh_key();
1989    
1990            if (type == KEY_RSA1 || type == KEY_RSA) {
1991                    RSA *priv = NULL;
1992                    RSA *pub = NULL;
1993    
1994                    // private key
1995                    priv =  RSA_generate_key(bits, 35, NULL, NULL);
1996                    if (priv == NULL)
1997                            goto error;
1998                    private_key.rsa = priv;
1999    
2000                    // public key
2001                    pub = RSA_new();
2002                    pub->n = BN_new();
2003                    pub->e = BN_new();
2004                    if (pub->n == NULL || pub->e == NULL) {
2005                            RSA_free(pub);
2006                            goto error;
2007                    }
2008    
2009                    BN_copy(pub->n, priv->n);
2010                    BN_copy(pub->e, priv->e);
2011                    public_key.rsa = pub;
2012    
2013            } else if (type == KEY_DSA) {
2014                    DSA *priv = NULL;
2015                    DSA *pub = NULL;
2016    
2017                    // private key
2018                    priv = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
2019                    if (priv == NULL)
2020                            goto error;
2021                    if (!DSA_generate_key(priv)) {
2022                            // TODO: free 'priv'?
2023                            goto error;
2024                    }
2025                    private_key.dsa = priv;
2026    
2027                    // public key
2028                    pub = DSA_new();
2029                    if (pub == NULL)
2030                            goto error;
2031                    pub->p = BN_new();
2032                    pub->q = BN_new();
2033                    pub->g = BN_new();
2034                    pub->pub_key = BN_new();
2035                    if (pub->p == NULL || pub->q == NULL || pub->g == NULL || pub->pub_key == NULL) {
2036                            DSA_free(pub);
2037                            goto error;
2038                    }
2039    
2040                    BN_copy(pub->p, priv->p);
2041                    BN_copy(pub->q, priv->q);
2042                    BN_copy(pub->g, priv->g);
2043                    BN_copy(pub->pub_key, priv->pub_key);
2044                    public_key.dsa = pub;
2045    
2046            } else {
2047                    goto error;
2048            }
2049    
2050            return TRUE;
2051    
2052    error:
2053            free_ssh_key();
2054            return FALSE;
2055    }
2056    
2057    
2058    //
2059    // RC4
2060    //
2061    
2062    /* Size of key to use */
2063    #define SEED_SIZE 20
2064    
2065    /* Number of bytes to reseed after */
2066    #define REKEY_BYTES (1 << 24)
2067    
2068    static int rc4_ready = 0;
2069    static RC4_KEY rc4;
2070    
2071    static void seed_rng(void)
2072    {
2073        if (RAND_status() != 1)
2074                    return;
2075    }
2076    
2077    static void arc4random_stir(void)
2078    {
2079        unsigned char rand_buf[SEED_SIZE];
2080        int i;
2081    
2082        memset(&rc4, 0, sizeof(rc4));
2083            if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) {
2084            //fatal("Couldn't obtain random bytes (error %ld)",
2085            //    ERR_get_error());
2086            }
2087        RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
2088    
2089        /*
2090         * Discard early keystream, as per recommendations in:
2091         * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
2092         */
2093        for(i = 0; i <= 256; i += sizeof(rand_buf))
2094            RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
2095    
2096        memset(rand_buf, 0, sizeof(rand_buf));
2097    
2098        rc4_ready = REKEY_BYTES;
2099    }
2100    
2101    static unsigned int arc4random(void)
2102    {
2103        unsigned int r = 0;
2104        static int first_time = 1;
2105    
2106        if (rc4_ready <= 0) {
2107                    if (first_time) {
2108                seed_rng();
2109                    }
2110            first_time = 0;
2111            arc4random_stir();
2112        }
2113    
2114        RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
2115    
2116        rc4_ready -= sizeof(r);
2117    
2118        return(r);
2119    }
2120    
2121    //
2122    // SSH1 3DES
2123    //
2124    /*
2125     * This is used by SSH1:
2126     *
2127     * What kind of triple DES are these 2 routines?
2128     *
2129     * Why is there a redundant initialization vector?
2130     *
2131     * If only iv3 was used, then, this would till effect have been
2132     * outer-cbc. However, there is also a private iv1 == iv2 which
2133     * perhaps makes differential analysis easier. On the other hand, the
2134     * private iv1 probably makes the CRC-32 attack ineffective. This is a
2135     * result of that there is no longer any known iv1 to use when
2136     * choosing the X block.
2137     */
2138    struct ssh1_3des_ctx
2139    {
2140            EVP_CIPHER_CTX  k1, k2, k3;
2141    };
2142    
2143    static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
2144    {
2145            struct ssh1_3des_ctx *c;
2146            u_char *k1, *k2, *k3;
2147    
2148            if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2149                    c = malloc(sizeof(*c));
2150                    EVP_CIPHER_CTX_set_app_data(ctx, c);
2151            }
2152            if (key == NULL)
2153                    return (1);
2154            if (enc == -1)
2155                    enc = ctx->encrypt;
2156            k1 = k2 = k3 = (u_char *) key;
2157            k2 += 8;
2158            if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
2159                    if (enc)
2160                            k3 += 16;
2161                    else
2162                            k1 += 16;
2163            }
2164            EVP_CIPHER_CTX_init(&c->k1);
2165            EVP_CIPHER_CTX_init(&c->k2);
2166            EVP_CIPHER_CTX_init(&c->k3);
2167            if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
2168                    EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
2169                    EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
2170                            memset(c, 0, sizeof(*c));
2171                            free(c);
2172                            EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2173                            return (0);
2174            }
2175            return (1);
2176    }
2177    
2178    static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
2179    {
2180            struct ssh1_3des_ctx *c;
2181    
2182            if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2183                    //error("ssh1_3des_cbc: no context");
2184                    return (0);
2185            }
2186            if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
2187                    EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
2188                    EVP_Cipher(&c->k3, dest, dest, len) == 0)
2189                    return (0);
2190            return (1);
2191    }
2192    
2193    static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
2194    {
2195            struct ssh1_3des_ctx *c;
2196    
2197            if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
2198                    EVP_CIPHER_CTX_cleanup(&c->k1);
2199                    EVP_CIPHER_CTX_cleanup(&c->k2);
2200                    EVP_CIPHER_CTX_cleanup(&c->k3);
2201                    memset(c, 0, sizeof(*c));
2202                    free(c);
2203                    EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2204            }
2205            return (1);
2206    }
2207    
2208    void ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
2209    {
2210            struct ssh1_3des_ctx *c;
2211    
2212            if (len != 24)
2213                    //fatal("%s: bad 3des iv length: %d", __func__, len);
2214                    ;
2215    
2216            if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
2217                    //fatal("%s: no 3des context", __func__);
2218                    ;
2219    
2220            if (doset) {
2221                    //debug3("%s: Installed 3DES IV", __func__);
2222                    memcpy(c->k1.iv, iv, 8);
2223                    memcpy(c->k2.iv, iv + 8, 8);
2224                    memcpy(c->k3.iv, iv + 16, 8);
2225            } else {
2226                    //debug3("%s: Copying 3DES IV", __func__);
2227                    memcpy(iv, c->k1.iv, 8);
2228                    memcpy(iv + 8, c->k2.iv, 8);
2229                    memcpy(iv + 16, c->k3.iv, 8);
2230            }
2231    }
2232    
2233    const EVP_CIPHER *evp_ssh1_3des(void)
2234    {
2235            static EVP_CIPHER ssh1_3des;
2236    
2237            memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
2238            ssh1_3des.nid = NID_undef;
2239            ssh1_3des.block_size = 8;
2240            ssh1_3des.iv_len = 0;
2241            ssh1_3des.key_len = 16;
2242            ssh1_3des.init = ssh1_3des_init;
2243            ssh1_3des.cleanup = ssh1_3des_cleanup;
2244            ssh1_3des.do_cipher = ssh1_3des_cbc;
2245            ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
2246            return (&ssh1_3des);
2247    }
2248    
2249    static void ssh_make_comment(char *comment, int maxlen)
2250    {
2251            char user[UNLEN + 1], host[128];
2252            DWORD dwSize;
2253            WSADATA wsaData;
2254            int ret;
2255    
2256            // get Windows logon user name
2257            dwSize = sizeof(user);
2258            if (GetUserName(user, &dwSize) == 0) {
2259                    strcpy(user, "yutaka");
2260            }
2261    
2262            // get local hostname (by WinSock)
2263            ret = WSAStartup(MAKEWORD(2,2), &wsaData);
2264            if (ret == 0) {
2265                    if (gethostname(host, sizeof(host)) != 0) {
2266                            ret = WSAGetLastError();
2267                    }
2268                    WSACleanup();
2269            }
2270            if (ret != 0) {
2271                    strcpy(host, "sai");
2272            }
2273    
2274            _snprintf(comment, maxlen, "%s@%s", user, host);
2275    }
2276    
2277    // uuencode (rfc1521)
2278    static int uuencode(unsigned char *src, int srclen, unsigned char *target, int targsize)
2279    {
2280            char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2281            char pad = '=';
2282        int datalength = 0;
2283        unsigned char input[3];
2284        unsigned char output[4];
2285        int i;
2286    
2287        while (srclen > 2) {
2288            input[0] = *src++;
2289            input[1] = *src++;
2290            input[2] = *src++;
2291            srclen -= 3;
2292    
2293            output[0] = input[0] >> 2;
2294            output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2295            output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2296            output[3] = input[2] & 0x3f;
2297                    if (output[0] >= 64 ||
2298                            output[1] >= 64 ||
2299                            output[2] >= 64 ||
2300                            output[3] >= 64)
2301                            return -1;
2302    
2303            if (datalength + 4 > targsize)
2304                return (-1);
2305            target[datalength++] = base64[output[0]];
2306            target[datalength++] = base64[output[1]];
2307            target[datalength++] = base64[output[2]];
2308            target[datalength++] = base64[output[3]];
2309        }
2310    
2311        if (srclen != 0) {
2312            /* Get what's left. */
2313            input[0] = input[1] = input[2] = '\0';
2314            for (i = 0; i < srclen; i++)
2315                input[i] = *src++;
2316    
2317            output[0] = input[0] >> 2;
2318            output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2319            output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2320                    if (output[0] >= 64 ||
2321                            output[1] >= 64 ||
2322                            output[2] >= 64)
2323                            return -1;
2324    
2325            if (datalength + 4 > targsize)
2326                return (-1);
2327            target[datalength++] = base64[output[0]];
2328            target[datalength++] = base64[output[1]];
2329            if (srclen == 1)
2330                target[datalength++] = pad;
2331            else
2332                target[datalength++] = base64[output[2]];
2333            target[datalength++] = pad;
2334        }
2335        if (datalength >= targsize)
2336            return (-1);
2337        target[datalength] = '\0';  /* Returned value doesn't count \0. */
2338    
2339            return (datalength); // success
2340    }
2341    
2342    static BOOL CALLBACK TTXKeyGenerator(HWND dlg, UINT msg, WPARAM wParam,
2343                                                                     LPARAM lParam)
2344    {
2345            static enum hostkey_type key_type;
2346    
2347            switch (msg) {
2348            case WM_INITDIALOG:
2349                    {
2350                    // default key type
2351                    SendMessage(GetDlgItem(dlg, IDC_RSA_TYPE), BM_SETCHECK, BST_CHECKED, 0);
2352                    key_type = KEY_RSA;
2353    
2354                    // passphrase edit box disabled(default)
2355                    EnableWindow(GetDlgItem(dlg, IDC_KEY_EDIT), FALSE);
2356                    EnableWindow(GetDlgItem(dlg, IDC_CONFIRM_EDIT), FALSE);
2357    
2358                    // file saving dialog disabled(default)
2359                    EnableWindow(GetDlgItem(dlg, IDC_SAVE_PUBLIC_KEY), FALSE);
2360                    EnableWindow(GetDlgItem(dlg, IDC_SAVE_PRIBATE_KEY), FALSE);
2361    
2362                    }
2363                    return TRUE;
2364    
2365            case WM_COMMAND:
2366                    switch (LOWORD(wParam)) {
2367                    case IDOK: // key generate button pressed
2368                            // passphrase edit box disabled(default)
2369                            EnableWindow(GetDlgItem(dlg, IDC_KEY_EDIT), FALSE);
2370                            EnableWindow(GetDlgItem(dlg, IDC_CONFIRM_EDIT), FALSE);
2371    
2372                            // file saving dialog disabled(default)
2373                            EnableWindow(GetDlgItem(dlg, IDC_SAVE_PUBLIC_KEY), FALSE);
2374                            EnableWindow(GetDlgItem(dlg, IDC_SAVE_PRIBATE_KEY), FALSE);
2375    
2376                            if (generate_ssh_key(key_type)) {
2377                                    // passphrase edit box disabled(default)
2378                                    EnableWindow(GetDlgItem(dlg, IDC_KEY_EDIT), TRUE);
2379                                    EnableWindow(GetDlgItem(dlg, IDC_CONFIRM_EDIT), TRUE);
2380    
2381                                    // file saving dialog disabled(default)
2382                                    EnableWindow(GetDlgItem(dlg, IDC_SAVE_PUBLIC_KEY), TRUE);
2383                                    EnableWindow(GetDlgItem(dlg, IDC_SAVE_PRIBATE_KEY), TRUE);
2384                            }
2385                            return TRUE;
2386    
2387                    case IDCANCEL:                  
2388                            // don't forget to free SSH resource!
2389                            free_ssh_key();
2390                            EndDialog(dlg, 0); // dialog close
2391                            return TRUE;
2392    
2393                    // if radio button pressed...
2394                    case IDC_RSA1_TYPE | (BN_CLICKED << 16):
2395                            key_type = KEY_RSA1;
2396                            break;
2397    
2398                    case IDC_RSA_TYPE | (BN_CLICKED << 16):
2399                            key_type = KEY_RSA;
2400                            break;
2401    
2402                    case IDC_DSA_TYPE | (BN_CLICKED << 16):
2403                            key_type = KEY_DSA;
2404                            break;
2405    
2406                    // saving public key file
2407                    case IDC_SAVE_PUBLIC_KEY:
2408                            {
2409                            int ret;
2410                            OPENFILENAME ofn;
2411                            char filename[MAX_PATH];
2412                            FILE *fp;
2413                            char comment[1024]; // comment string in private key
2414    
2415                            arc4random_stir();
2416    
2417                            // saving file dialog
2418                            ZeroMemory(&ofn, sizeof(ofn));
2419                            ofn.lStructSize = sizeof(ofn);
2420                            ofn.hwndOwner = dlg;
2421                            if (key_type == KEY_RSA1) {
2422                                    ofn.lpstrFilter = "SSH1 RSA key(identity.pub)\0identity.pub\0All Files(*.*)\0*.*\0\0";
2423                                    _snprintf(filename, sizeof(filename), "identity.pub");
2424                            } else if (key_type == KEY_RSA) {
2425                                    ofn.lpstrFilter = "SSH2 RSA key(id_rsa.pub)\0id_rsa.pub\0All Files(*.*)\0*.*\0\0";
2426                                    _snprintf(filename, sizeof(filename), "id_rsa.pub");
2427                            } else {
2428                                    ofn.lpstrFilter = "SSH2 DSA key(id_dsa.pub)\0id_dsa.pub\0All Files(*.*)\0*.*\0\0";
2429                                    _snprintf(filename, sizeof(filename), "id_dsa.pub");
2430                            }
2431                            ofn.lpstrFile = filename;
2432                            ofn.nMaxFile = sizeof(filename);
2433                            ofn.lpstrTitle = "Save public key as:";
2434                            if (GetSaveFileName(&ofn) == 0) { // failure
2435                                    ret = CommDlgExtendedError();
2436                                    break;
2437                            }
2438    
2439                            ssh_make_comment(comment, sizeof(comment));
2440    
2441                            // saving public key file
2442                            fp = fopen(filename, "wb");
2443                            if (fp == NULL) {
2444                                    MessageBox(dlg, "Can't open key file", "ERROR", MB_OK | MB_ICONEXCLAMATION);
2445                                    break;
2446                            }
2447    
2448                            if (key_type == KEY_RSA1) { // SSH1 RSA
2449                                    RSA *rsa = public_key.rsa;
2450                                    int bits;
2451                                    char *buf;
2452    
2453                                    bits = BN_num_bits(rsa->n);
2454                                    fprintf(fp, "%u", bits);
2455    
2456                                    buf = BN_bn2dec(rsa->e);
2457                                    fprintf(fp, " %s", buf);
2458                                    OPENSSL_free(buf);
2459    
2460                                    buf = BN_bn2dec(rsa->n);
2461                                    fprintf(fp, " %s", buf);
2462                                    OPENSSL_free(buf);
2463    
2464                            } else { // SSH2 RSA, DSA
2465                                    buffer_t *b;
2466                                    char *keyname;
2467                                    DSA *dsa = public_key.dsa;
2468                                    RSA *rsa = public_key.rsa;
2469                                    int len;
2470                                    char *blob;
2471                                    char *uuenc; // uuencode data
2472                                    int uulen;
2473    
2474                                    b = buffer_init();
2475                                    if (b == NULL)
2476                                            goto public_error;
2477    
2478                                    if (key_type == KEY_DSA) { // DSA
2479                                            keyname = "ssh-dss";
2480                                            buffer_put_string(b, keyname, strlen(keyname));
2481                                            buffer_put_bignum2(b, dsa->p);
2482                                            buffer_put_bignum2(b, dsa->q);
2483                                            buffer_put_bignum2(b, dsa->g);
2484                                            buffer_put_bignum2(b, dsa->pub_key);
2485    
2486                                    } else { // RSA
2487                                            keyname = "ssh-rsa";
2488                                            buffer_put_string(b, keyname, strlen(keyname));
2489                                            buffer_put_bignum2(b, rsa->e);
2490                                            buffer_put_bignum2(b, rsa->n);
2491                                    }
2492                                    
2493                                    blob = buffer_ptr(b);
2494                                    len = buffer_len(b);
2495                                    uuenc = malloc(len * 2);
2496                                    if (uuenc == NULL) {
2497                                            buffer_free(b);
2498                                            goto public_error;
2499                                    }
2500                                    uulen = uuencode(blob, len, uuenc, len * 2);
2501                                    if (uulen > 0) {
2502                                            fprintf(fp, "%s %s", keyname, uuenc);
2503                                    }
2504                                    free(uuenc);
2505                                    buffer_free(b);
2506                            }
2507    
2508                            // writing a comment(+LF)
2509                            fprintf(fp, " %s", comment);
2510                            fputc(0x0a, fp);
2511    
2512    public_error:
2513                            fclose(fp);
2514    
2515                            }
2516                            break;
2517    
2518                    // saving private key file
2519                    case IDC_SAVE_PRIVATE_KEY:
2520                            {
2521                            char buf[1024], buf_conf[1024];  // passphrase
2522                            int ret;
2523                            OPENFILENAME ofn;
2524                            char filename[MAX_PATH];
2525                            char comment[1024]; // comment string in private key
2526    
2527                            // パスフレーズのチェックを行う。パスフレーズは秘密鍵ファイルに付ける。
2528                            SendMessage(GetDlgItem(dlg, IDC_KEY_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
2529                            SendMessage(GetDlgItem(dlg, IDC_CONFIRM_EDIT), WM_GETTEXT, sizeof(buf_conf), (LPARAM)buf_conf);
2530    
2531                            // check matching
2532                            if (strcmp(buf, buf_conf) != 0) {
2533                                    MessageBox(dlg, "Two passphrases don't match.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
2534                                    break;
2535                            }
2536    
2537                            // check empty-passphrase (this is warning level)
2538                            if (buf[0] == '\0') {
2539                                    ret = MessageBox(dlg, "Are you sure that you want to use a empty passphrase?", "WARNING", MB_YESNO | MB_ICONWARNING);
2540                                    if (ret == IDNO)
2541                                            break;
2542                            }
2543    
2544                            ssh_make_comment(comment, sizeof(comment));
2545    
2546                            // saving file dialog
2547                            ZeroMemory(&ofn, sizeof(ofn));
2548                            ofn.lStructSize = sizeof(ofn);
2549                            ofn.hwndOwner = dlg;
2550                            if (key_type == KEY_RSA1) {
2551                                    ofn.lpstrFilter = "SSH1 RSA key(identity)\0identity\0All Files(*.*)\0*.*\0\0";
2552                                    _snprintf(filename, sizeof(filename), "identity");
2553                            } else if (key_type == KEY_RSA) {
2554                                    ofn.lpstrFilter = "SSH2 RSA key(id_rsa)\0id_rsa\0All Files(*.*)\0*.*\0\0";
2555                                    _snprintf(filename, sizeof(filename), "id_rsa");
2556                            } else {
2557                                    ofn.lpstrFilter = "SSH2 DSA key(id_dsa)\0id_dsa\0All Files(*.*)\0*.*\0\0";
2558                                    _snprintf(filename, sizeof(filename), "id_dsa");
2559                            }
2560                            ofn.lpstrFile = filename;
2561                            ofn.nMaxFile = sizeof(filename);
2562                            ofn.lpstrTitle = "Save private key as:";
2563                            if (GetSaveFileName(&ofn) == 0) { // failure
2564                                    ret = CommDlgExtendedError();
2565                                    break;
2566                            }
2567    
2568                            // saving private key file
2569                            if (key_type == KEY_RSA1) { // SSH1 RSA
2570                                    int cipher_num;
2571                                    buffer_t *b, *enc;
2572                                    unsigned int rnd;
2573                                    unsigned char tmp[128];
2574                                    RSA *rsa;
2575                                    int i, len;
2576                                    char authfile_id_string[] = "SSH PRIVATE KEY FILE FORMAT 1.1";
2577                                    MD5_CTX md;
2578                                    unsigned char digest[16];
2579                                    char *passphrase = buf;
2580                                    EVP_CIPHER_CTX cipher_ctx;
2581                                    FILE *fp;
2582                                    char wrapped[4096];
2583    
2584                                    if (passphrase[0] == '\0') { // passphrase is empty
2585                                            cipher_num = SSH_CIPHER_NONE;
2586                                    } else {
2587                                            cipher_num = SSH_CIPHER_3DES; // 3DES-CBC
2588                                    }
2589    
2590                                    b = buffer_init();
2591                                    if (b == NULL)
2592                                            break;
2593                                    enc = buffer_init();
2594                                    if (enc == NULL) {
2595                                            buffer_free(b);
2596                                            break;
2597                                    }
2598    
2599                                    // set random value
2600                                    rnd = arc4random();
2601                                    tmp[0] = rnd & 0xff;
2602                                    tmp[1] = (rnd >> 8) & 0xff;
2603                                    tmp[2] = tmp[0];
2604                                    tmp[3] = tmp[1];
2605                                    buffer_append(b, tmp, 4);
2606    
2607                                    // set private key
2608                                    rsa = private_key.rsa;
2609                                    buffer_put_bignum(b, rsa->d);
2610                                    buffer_put_bignum(b, rsa->iqmp);
2611                                    buffer_put_bignum(b, rsa->q);
2612                                    buffer_put_bignum(b, rsa->p);
2613    
2614                                    // padding with 8byte align
2615                                    while (buffer_len(b) % 8) {
2616                                            buffer_put_char(b, 0);
2617                                    }
2618    
2619                                    //
2620                                    // step(2)
2621                                    //
2622                                    // encrypted buffer
2623                                /* First store keyfile id string. */
2624                                    for (i = 0 ; authfile_id_string[i] ; i++) {
2625                                            buffer_put_char(enc, authfile_id_string[i]);
2626                                    }
2627                                    buffer_put_char(enc, 0x0a); // LF
2628                                    buffer_put_char(enc, 0);
2629    
2630                                    /* Store cipher type. */
2631                                    buffer_put_char(enc, cipher_num);
2632                                    buffer_put_int(enc, 0);  // type is 'int'!! (For future extension)
2633    
2634                                    /* Store public key.  This will be in plain text. */
2635                                    buffer_put_int(enc, BN_num_bits(rsa->n));
2636                                    buffer_put_bignum(enc, rsa->n);
2637                                    buffer_put_bignum(enc, rsa->e);
2638                                    buffer_put_string(enc, comment, strlen(comment));
2639    
2640                                    // setup the MD5ed passphrase to cipher encryption key
2641                                    MD5_Init(&md);
2642                                    MD5_Update(&md, (const unsigned char *)passphrase, strlen(passphrase));
2643                                    MD5_Final(digest, &md);
2644                                    if (cipher_num == SSH_CIPHER_NONE) {
2645                                            cipher_init_SSH2(&cipher_ctx, digest, 16, NULL, 0, CIPHER_ENCRYPT, EVP_enc_null);
2646                                    } else {
2647                                            cipher_init_SSH2(&cipher_ctx, digest, 16, NULL, 0, CIPHER_ENCRYPT, evp_ssh1_3des);
2648                                    }
2649                                    len = buffer_len(b);
2650                                    if (len % 8) { // fatal error
2651                                            goto error;
2652                                    }
2653    
2654                                    // check buffer overflow
2655                                    if (buffer_overflow_verify(enc, len) && (sizeof(wrapped) < len)) {
2656                                            goto error;
2657                                    }
2658    
2659                                    if (EVP_Cipher(&cipher_ctx, wrapped, buffer_ptr(b), len) == 0) {
2660                                            goto error;
2661                                    }
2662                                    if (EVP_CIPHER_CTX_cleanup(&cipher_ctx) == 0) {
2663                                            goto error;
2664                                    }
2665    
2666                                    buffer_append(enc, wrapped, len);
2667    
2668                                    // saving private key file (binary mode)
2669                                    fp = fopen(filename, "wb");
2670                                    if (fp == NULL) {
2671                                            MessageBox(dlg, "Can't open key file", "ERROR", MB_OK | MB_ICONEXCLAMATION);
2672                                            break;
2673                                    }
2674                                    fwrite(buffer_ptr(enc), buffer_len(enc), 1, fp);
2675    
2676                                    fclose(fp);
2677    
2678    error:;
2679                                    buffer_free(b);
2680                                    buffer_free(enc);
2681    
2682                            } else { // SSH2 RSA, DSA
2683                                    int len;
2684                                    FILE *fp;
2685                                    const EVP_CIPHER *cipher;
2686    
2687                                    len = strlen(buf);
2688                                    // TODO: range check (len >= 4)
2689    
2690                                    cipher = NULL;
2691                                    if (len > 0) {
2692                                            cipher = EVP_des_ede3_cbc();
2693                                    }
2694    
2695                                    fp = fopen(filename, "w");
2696                                    if (fp == NULL) {
2697                                            MessageBox(dlg, "Can't open key file", "ERROR", MB_OK | MB_ICONEXCLAMATION);
2698                                            break;
2699                                    }
2700    
2701                                    if (key_type == KEY_RSA) { // RSA
2702                                            ret = PEM_write_RSAPrivateKey(fp, private_key.rsa, cipher, buf, len, NULL, NULL);
2703                                    } else { // DSA
2704                                            ret = PEM_write_DSAPrivateKey(fp, private_key.dsa, cipher, buf, len, NULL, NULL);
2705                                    }
2706                                    if (ret == 0) {
2707                                            MessageBox(dlg, "Can't write key file", "ERROR", MB_OK | MB_ICONEXCLAMATION);
2708                                    }
2709                                    fclose(fp);
2710                            }
2711    
2712    
2713                            }
2714                            break;
2715    
2716                    }
2717                    break;
2718            }
2719    
2720            return FALSE;
2721    }
2722    
2723    
2724  static int PASCAL FAR TTXProcessCommand(HWND hWin, WORD cmd)  static int PASCAL FAR TTXProcessCommand(HWND hWin, WORD cmd)
2725  {  {
2726          GET_VAR();          GET_VAR();
# Line 1939  static int PASCAL FAR TTXProcessCommand( Line 2730  static int PASCAL FAR TTXProcessCommand(
2730          }          }
2731    
2732          switch (cmd) {          switch (cmd) {
2733            case ID_SSHKEYGENMENU:
2734                    if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHKEYGEN), hWin, TTXKeyGenerator,
2735                            (LPARAM) pvar) == -1) {
2736                            MessageBox(hWin, "Cannot create Key Generator window.",
2737                                    "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
2738                    }
2739                    return 1;
2740    
2741          case ID_ABOUTMENU:          case ID_ABOUTMENU:
2742                  if (DialogBoxParam                  if (DialogBoxParam
2743                          (hInst, MAKEINTRESOURCE(IDD_ABOUTDIALOG), hWin, TTXAboutDlg,                          (hInst, MAKEINTRESOURCE(IDD_ABOUTDIALOG), hWin, TTXAboutDlg,
# Line 2264  int CALLBACK LibMain(HANDLE hInstance, W Line 3063  int CALLBACK LibMain(HANDLE hInstance, W
3063    
3064  /*  /*
3065   * $Log: not supported by cvs2svn $   * $Log: not supported by cvs2svn $
3066     * Revision 1.19  2005/04/08 14:55:03  yutakakn
3067     * "Duplicate session"においてSSH自動ログインを行うようにした。
3068     *
3069   * Revision 1.18  2005/04/03 14:39:48  yutakakn   * Revision 1.18  2005/04/03 14:39:48  yutakakn
3070   * SSH2 channel lookup機構の追加(ポートフォワーディングのため)。   * SSH2 channel lookup機構の追加(ポートフォワーディングのため)。
3071   * TTSSH 2.10で追加したlog dump機構において、DH鍵再作成時にbuffer freeで   * TTSSH 2.10で追加したlog dump機構において、DH鍵再作成時にbuffer freeで

Legend:
Removed from v.2811  
changed lines
  Added in v.2816

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26