|
114 | 114 | #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK |
115 | 115 | #endif |
116 | 116 |
|
| 117 | +#if defined(USE_WINDOWS_API) && defined(WOLFSSH_CERTS) |
| 118 | + #include <windows.h> |
| 119 | + #include <wincrypt.h> |
| 120 | + #ifndef CERT_SYSTEM_STORE_CURRENT_USER |
| 121 | + #define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000 |
| 122 | + #endif |
| 123 | + #ifndef CERT_SYSTEM_STORE_LOCAL_MACHINE |
| 124 | + #define CERT_SYSTEM_STORE_LOCAL_MACHINE 0x00020000 |
| 125 | + #endif |
| 126 | +#endif |
117 | 127 |
|
118 | 128 | #ifndef NO_WOLFSSH_SERVER |
119 | 129 |
|
@@ -2314,6 +2324,9 @@ static void ShowUsage(void) |
2314 | 2324 | " add password to accept from peer\n"); |
2315 | 2325 | #ifdef WOLFSSH_CERTS |
2316 | 2326 | printf(" -a <file> load in a root CA certificate file\n"); |
| 2327 | +#endif |
| 2328 | +#if defined(USE_WINDOWS_API) && defined(WOLFSSH_CERTS) |
| 2329 | + printf(" -W <spec> Windows cert store: \"store:subject:flags\" (e.g. My:CN=Server:CURRENT_USER)\n"); |
2317 | 2330 | #endif |
2318 | 2331 | printf(" -k set the list of key algos to use\n"); |
2319 | 2332 | printf(" -b <num> test user auth would block\n"); |
@@ -2372,13 +2385,19 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) |
2372 | 2385 | #ifdef WOLFSSH_CERTS |
2373 | 2386 | char* caCert = NULL; |
2374 | 2387 | #endif |
| 2388 | + #if defined(USE_WINDOWS_API) && defined(WOLFSSH_CERTS) |
| 2389 | + const char* certStoreSpec = NULL; |
| 2390 | + #endif |
2375 | 2391 |
|
2376 | 2392 | int argc = serverArgs->argc; |
2377 | 2393 | char** argv = serverArgs->argv; |
2378 | 2394 | serverArgs->return_code = EXIT_SUCCESS; |
2379 | 2395 |
|
| 2396 | + #if defined(USE_WINDOWS_API) && defined(WOLFSSH_CERTS) |
| 2397 | + certStoreSpec = getenv("WOLFSSH_CERT_STORE"); |
| 2398 | + #endif |
2380 | 2399 | if (argc > 0) { |
2381 | | - const char* optlist = "?1a:d:efEp:R:Ni:j:I:J:K:P:k:b:"; |
| 2400 | + const char* optlist = "?1a:d:efEp:R:Ni:j:I:J:K:P:k:b:W:"; |
2382 | 2401 | myoptind = 0; |
2383 | 2402 | while ((ch = mygetopt(argc, argv, optlist)) != -1) { |
2384 | 2403 | switch (ch) { |
@@ -2466,6 +2485,12 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) |
2466 | 2485 | userAuthWouldBlock = atoi(myoptarg); |
2467 | 2486 | break; |
2468 | 2487 |
|
| 2488 | + #if defined(USE_WINDOWS_API) && defined(WOLFSSH_CERTS) |
| 2489 | + case 'W': |
| 2490 | + certStoreSpec = myoptarg; |
| 2491 | + break; |
| 2492 | + #endif |
| 2493 | + |
2469 | 2494 | default: |
2470 | 2495 | ShowUsage(); |
2471 | 2496 | serverArgs->return_code = MY_EX_USAGE; |
@@ -2580,28 +2605,94 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) |
2580 | 2605 | #endif |
2581 | 2606 | bufSz = EXAMPLE_KEYLOAD_BUFFER_SZ; |
2582 | 2607 |
|
2583 | | - bufSz = load_key(peerEcc, keyLoadBuf, bufSz); |
2584 | | - if (bufSz == 0) { |
2585 | | - ES_ERROR("Couldn't load first key file.\n"); |
2586 | | - } |
2587 | | - if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, keyLoadBuf, bufSz, |
2588 | | - WOLFSSH_FORMAT_ASN1) < 0) { |
2589 | | - ES_ERROR("Couldn't use first key buffer.\n"); |
2590 | | - } |
| 2608 | +#if defined(USE_WINDOWS_API) && defined(WOLFSSH_CERTS) |
| 2609 | + if (certStoreSpec != NULL) { |
| 2610 | + /* Load host key from Windows certificate store: store:subject:flags */ |
| 2611 | + char* specCopy = NULL; |
| 2612 | + char* storeName = NULL; |
| 2613 | + char* subjectName = NULL; |
| 2614 | + char* flagsStr = NULL; |
| 2615 | + wchar_t* wStoreName = NULL; |
| 2616 | + wchar_t* wSubjectName = NULL; |
| 2617 | + DWORD dwFlags = CERT_SYSTEM_STORE_CURRENT_USER; |
| 2618 | + int ret; |
| 2619 | + size_t specLen = WSTRLEN(certStoreSpec) + 1; |
2591 | 2620 |
|
2592 | | - #if !defined(WOLFSSH_NO_RSA) && !defined(WOLFSSH_NO_ECC) |
2593 | | - peerEcc = !peerEcc; |
2594 | | - bufSz = EXAMPLE_KEYLOAD_BUFFER_SZ; |
| 2621 | + specCopy = (char*)WMALLOC(specLen, NULL, 0); |
| 2622 | + if (specCopy == NULL) { |
| 2623 | + ES_ERROR("Memory allocation failed for cert store spec\n"); |
| 2624 | + } |
| 2625 | + WSTRNCPY(specCopy, certStoreSpec, specLen); |
| 2626 | + |
| 2627 | + storeName = specCopy; |
| 2628 | + subjectName = WSTRCHR(storeName, ':'); |
| 2629 | + if (subjectName != NULL) { |
| 2630 | + *subjectName++ = '\0'; |
| 2631 | + flagsStr = WSTRCHR(subjectName, ':'); |
| 2632 | + if (flagsStr != NULL) { |
| 2633 | + *flagsStr++ = '\0'; |
| 2634 | + if (WSTRCMP(flagsStr, "CURRENT_USER") == 0) { |
| 2635 | + dwFlags = CERT_SYSTEM_STORE_CURRENT_USER; |
| 2636 | + } else if (WSTRCMP(flagsStr, "LOCAL_MACHINE") == 0) { |
| 2637 | + dwFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE; |
| 2638 | + } else { |
| 2639 | + dwFlags = (DWORD)atoi(flagsStr); |
| 2640 | + } |
| 2641 | + } |
| 2642 | + } |
| 2643 | + if (storeName == NULL || subjectName == NULL) { |
| 2644 | + WFREE(specCopy, NULL, 0); |
| 2645 | + ES_ERROR("Invalid cert store spec. Use: store:subject:flags\n"); |
| 2646 | + } |
2595 | 2647 |
|
2596 | | - bufSz = load_key(peerEcc, keyLoadBuf, bufSz); |
2597 | | - if (bufSz == 0) { |
2598 | | - ES_ERROR("Couldn't load second key file.\n"); |
2599 | | - } |
2600 | | - if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, keyLoadBuf, bufSz, |
2601 | | - WOLFSSH_FORMAT_ASN1) < 0) { |
2602 | | - ES_ERROR("Couldn't use second key buffer.\n"); |
| 2648 | + { |
| 2649 | + int wStoreNameLen = MultiByteToWideChar(CP_UTF8, 0, storeName, -1, NULL, 0); |
| 2650 | + int wSubjectNameLen = MultiByteToWideChar(CP_UTF8, 0, subjectName, -1, NULL, 0); |
| 2651 | + wStoreName = (wchar_t*)WMALLOC(wStoreNameLen * sizeof(wchar_t), NULL, 0); |
| 2652 | + wSubjectName = (wchar_t*)WMALLOC(wSubjectNameLen * sizeof(wchar_t), NULL, 0); |
| 2653 | + if (wStoreName == NULL || wSubjectName == NULL) { |
| 2654 | + if (wStoreName != NULL) WFREE(wStoreName, NULL, 0); |
| 2655 | + if (wSubjectName != NULL) WFREE(wSubjectName, NULL, 0); |
| 2656 | + WFREE(specCopy, NULL, 0); |
| 2657 | + ES_ERROR("Memory allocation failed for cert store wide strings\n"); |
| 2658 | + } |
| 2659 | + MultiByteToWideChar(CP_UTF8, 0, storeName, -1, wStoreName, wStoreNameLen); |
| 2660 | + MultiByteToWideChar(CP_UTF8, 0, subjectName, -1, wSubjectName, wSubjectNameLen); |
| 2661 | + } |
| 2662 | + |
| 2663 | + ret = wolfSSH_CTX_UsePrivateKey_fromStore(ctx, wStoreName, dwFlags, wSubjectName); |
| 2664 | + WFREE(specCopy, NULL, 0); |
| 2665 | + WFREE(wStoreName, NULL, 0); |
| 2666 | + WFREE(wSubjectName, NULL, 0); |
| 2667 | + if (ret != WS_SUCCESS) { |
| 2668 | + ES_ERROR("Couldn't load host key from certificate store.\n"); |
| 2669 | + } |
| 2670 | + } else |
| 2671 | +#endif |
| 2672 | + { |
| 2673 | + bufSz = load_key(peerEcc, keyLoadBuf, bufSz); |
| 2674 | + if (bufSz == 0) { |
| 2675 | + ES_ERROR("Couldn't load first key file.\n"); |
| 2676 | + } |
| 2677 | + if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, keyLoadBuf, bufSz, |
| 2678 | + WOLFSSH_FORMAT_ASN1) < 0) { |
| 2679 | + ES_ERROR("Couldn't use first key buffer.\n"); |
| 2680 | + } |
| 2681 | + |
| 2682 | + #if !defined(WOLFSSH_NO_RSA) && !defined(WOLFSSH_NO_ECC) |
| 2683 | + peerEcc = !peerEcc; |
| 2684 | + bufSz = EXAMPLE_KEYLOAD_BUFFER_SZ; |
| 2685 | + |
| 2686 | + bufSz = load_key(peerEcc, keyLoadBuf, bufSz); |
| 2687 | + if (bufSz == 0) { |
| 2688 | + ES_ERROR("Couldn't load second key file.\n"); |
| 2689 | + } |
| 2690 | + if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, keyLoadBuf, bufSz, |
| 2691 | + WOLFSSH_FORMAT_ASN1) < 0) { |
| 2692 | + ES_ERROR("Couldn't use second key buffer.\n"); |
| 2693 | + } |
| 2694 | + #endif |
2603 | 2695 | } |
2604 | | - #endif |
2605 | 2696 |
|
2606 | 2697 | #ifndef NO_FILESYSTEM |
2607 | 2698 | if (userPubKey) { |
|
0 commit comments