diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 9cee3a89..c1dea816 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -34,7 +34,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -1854,6 +1856,18 @@ static int LoadPubKeyList(StrList* strList, int format, PwMapList* mapList) } +static int wsUserAuthResult(byte res, + WS_UserAuthData* authData, + void* ctx) +{ + printf("In auth result callback, auth = %s\n", + (res == WOLFSSH_USERAUTH_SUCCESS) ? "Success" : "Failure"); + (void)authData; + (void)ctx; + return WS_SUCCESS; +} + + static int wsUserAuth(byte authType, WS_UserAuthData* authData, void* ctx) @@ -1886,6 +1900,69 @@ static int wsUserAuth(byte authType, wc_Sha256Hash(authData->sf.publicKey.publicKey, authData->sf.publicKey.publicKeySz, authHash); + #ifndef WOLFSSH_NO_FPKI + /* Display FPKI info UUID and FASC-N */ + if (authData->sf.publicKey.isCert) { + DecodedCert cert; + byte* uuid; + word32 fascnSz; + word32 uuidSz; + word32 i; + + printf("Peer connected with FPKI certificate\n"); + wc_InitDecodedCert(&cert, authData->sf.publicKey.publicKey, + authData->sf.publicKey.publicKeySz, NULL); + ret = wc_ParseCert(&cert, CERT_TYPE, 0, NULL); + + /* some profiles supported due not require FASC-N */ + if (ret == 0 && + wc_GetFASCNFromCert(&cert, NULL, &fascnSz) == LENGTH_ONLY_E) { + byte* fascn; + + fascn = (byte*)WMALLOC(fascnSz, NULL, 0); + if (fascn != NULL && + wc_GetFASCNFromCert(&cert, fascn, &fascnSz) == 0) { + printf("HEX of FASC-N :"); + for (i = 0; i < fascnSz; i++) + printf("%02X", fascn[i]); + printf("\n"); + } + if (fascn != NULL) + WFREE(fascn, NULL, 0); + } + + /* all profiles supported must have a UUID */ + if (ret == 0) { + ret = wc_GetUUIDFromCert(&cert, NULL, &uuidSz); + if (ret == LENGTH_ONLY_E) { /* expected error value */ + ret = 0; + } + + if (ret == 0 ) { + uuid = (byte*)WMALLOC(uuidSz, NULL, 0); + if (uuid == NULL) { + ret = WS_MEMORY_E; + } + } + + if (ret == 0) { + ret = wc_GetUUIDFromCert(&cert, uuid, &uuidSz); + printf("UUID string : "); + for (i = 0; i < uuidSz; i++) + printf("%c", uuid[i]); + printf("\n"); + } + + if (uuid != NULL) + WFREE(uuid, NULL, 0); + } + + /* failed to at least get UUID string */ + if (ret != 0) { + return WOLFSSH_USERAUTH_INVALID_PUBLICKEY; + } + } + #endif } list = (PwMapList*)ctx; @@ -2147,6 +2224,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) wolfSSH_SetUserAuth(ctx, wsUserAuth); else wolfSSH_SetUserAuth(ctx, ((func_args*)args)->user_auth); + wolfSSH_SetUserAuthResult(ctx, wsUserAuthResult); wolfSSH_CTX_SetBanner(ctx, echoserverBanner); #ifdef WOLFSSH_AGENT wolfSSH_CTX_set_agent_cb(ctx, wolfSSH_AGENT_DefaultActions, NULL); diff --git a/src/certman.c b/src/certman.c index 756baed6..89032d82 100644 --- a/src/certman.c +++ b/src/certman.c @@ -181,12 +181,14 @@ int wolfSSH_CERTMAN_LoadRootCA_buffer(WOLFSSH_CERTMAN* cm, } +#ifndef WOLFSSH_NO_FPKI static int CheckProfile(DecodedCert* cert, int profile); enum { PROFILE_FPKI_WORKSHEET_6 = 6, PROFILE_FPKI_WORKSHEET_10 = 10, PROFILE_FPKI_WORKSHEET_16 = 16 }; +#endif /* WOLFSSH_NO_FPKI */ int wolfSSH_CERTMAN_VerifyCert_buffer(WOLFSSH_CERTMAN* cm, const unsigned char* cert, word32 certSz) @@ -236,6 +238,7 @@ int wolfSSH_CERTMAN_VerifyCert_buffer(WOLFSSH_CERTMAN* cm, } } +#ifndef WOLFSSH_NO_FPKI if (ret == WS_SUCCESS) { DecodedCert decoded; @@ -259,12 +262,14 @@ int wolfSSH_CERTMAN_VerifyCert_buffer(WOLFSSH_CERTMAN* cm, FreeDecodedCert(&decoded); } +#endif /* WOLFSSH_NO_FPKI */ WLOG_LEAVE(ret); return ret; } +#ifndef WOLFSSH_NO_FPKI static int CheckProfile(DecodedCert* cert, int profile) { int valid = (cert != NULL); @@ -298,26 +303,33 @@ static int CheckProfile(DecodedCert* cert, int profile) if (valid) { valid = WSTRCMP(cert->countryOfCitizenship, "US") == 0; + if (valid != 1) + WLOG(WS_LOG_CERTMAN, "cert contry of citizenship invalid"); } if (valid) { valid = !cert->isCA; + if (valid != 1) + WLOG(WS_LOG_CERTMAN, "cert basic constraint invalid"); } if (valid) { valid = WMEMCMP(cert->extAuthKeyId, cert->extSubjKeyId, KEYID_SIZE) != 0; - + if (valid != 1) + WLOG(WS_LOG_CERTMAN, "cert auth key and subject key mismatch"); } if (valid) { - valid = - ((certPolicies[1] != NULL) && - (WSTRCMP(certPolicies[1], cert->extCertPolicies[0]) == 0 || - WSTRCMP(certPolicies[1], cert->extCertPolicies[1]) == 0)) || - ((certPolicies[0] != NULL) && - (WSTRCMP(certPolicies[0], cert->extCertPolicies[0]) == 0 || - WSTRCMP(certPolicies[0], cert->extCertPolicies[1]) == 0)); + valid = + ((certPolicies[1] != NULL) && + (WSTRCMP(certPolicies[1], cert->extCertPolicies[0]) == 0 || + WSTRCMP(certPolicies[1], cert->extCertPolicies[1]) == 0)) || + ((certPolicies[0] != NULL) && + (WSTRCMP(certPolicies[0], cert->extCertPolicies[0]) == 0 || + WSTRCMP(certPolicies[0], cert->extCertPolicies[1]) == 0)); + if (valid != 1) + WLOG(WS_LOG_CERTMAN, "cert policy invalid"); } /* validity period must be utc up to and including 2049, general time @@ -364,6 +376,41 @@ static int CheckProfile(DecodedCert* cert, int profile) } } + /* check on FASC-N and UUID */ + if (valid) { + DNS_entry* current; + byte hasFascN = 0; + byte hasUUID = 0; + byte uuid[DEFAULT_UUID_SZ]; + word32 uuidSz = DEFAULT_UUID_SZ; + + /* cycle through alt names to check for needed types */ + current = cert->altNames; + while (current != NULL) { + if (current->oidSum == FASCN_OID) { + hasFascN = 1; + } + + current = current->next; + } + + if (wc_GetUUIDFromCert(cert, uuid, &uuidSz) == 0) { + hasUUID = 1; + } + + /* all must have UUID and worksheet 6 must have FASC-N in addition to + * UUID */ + if (profile == PROFILE_FPKI_WORKSHEET_6 && hasFascN == 0) { + WLOG(WS_LOG_CERTMAN, "cert did not inclue a FASC-N"); + valid = 0; + } + + if (valid && hasUUID == 0) { + WLOG(WS_LOG_CERTMAN, "cert did not inclue a UUID"); + valid = 0; + } + } + if (valid) { valid = /* Must include all in extKeyUsage */ @@ -373,6 +420,9 @@ static int CheckProfile(DecodedCert* cert, int profile) ((extKeyUsageSsh == 0) || ((cert->extExtKeyUsageSsh & extKeyUsageSsh) == extKeyUsageSsh)); + if (valid != 1) { + WLOG(WS_LOG_CERTMAN, "cert did not inclue all ext. key usage"); + } } #ifdef DEBUG_WOLFSSH @@ -402,5 +452,6 @@ static int CheckProfile(DecodedCert* cert, int profile) return valid; } +#endif /* WOLFSSH_NO_FPKI */ #endif /* WOLFSSH_CERTS */ diff --git a/src/internal.c b/src/internal.c index e22b70f1..d9e8fd1b 100644 --- a/src/internal.c +++ b/src/internal.c @@ -5054,6 +5054,7 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData, ret = GetSize(&l, pk->publicKey, pk->publicKeySz, &m); pk->publicKeySz = l; pk->publicKey = pk->publicKey + m; + pk->isCert = 1; } #endif /* WOLFSSH_CERTS */ @@ -5216,10 +5217,19 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData, } else { if (ssh->ctx->userAuthResultCb) { - ssh->ctx->userAuthResultCb(WOLFSSH_USERAUTH_SUCCESS, - authData, ssh->userAuthResultCtx); + if (ssh->ctx->userAuthResultCb(WOLFSSH_USERAUTH_SUCCESS, + authData, ssh->userAuthResultCtx) != WS_SUCCESS) { + + WLOG(WS_LOG_DEBUG, "DUARPK: user overriding success"); + ret = SendUserAuthFailure(ssh, 0); + } + else { + ssh->clientState = CLIENT_USERAUTH_DONE; + } + } + else { + ssh->clientState = CLIENT_USERAUTH_DONE; } - ssh->clientState = CLIENT_USERAUTH_DONE; } } } diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 2429d0a6..a3a02462 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -191,6 +191,7 @@ typedef struct WS_UserAuthData_PublicKey { byte hasSignature; const byte* signature; word32 signatureSz; + byte isCert:1; } WS_UserAuthData_PublicKey; typedef struct WS_UserAuthData {