mirror of https://github.com/wolfSSL/wolfssh.git
check on user name in UPN if exists
add check on host IP address in certificate alt namespull/465/head
parent
c11c7e3bbd
commit
9e3c2f3b78
|
@ -39,6 +39,10 @@
|
||||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||||
#include <wolfssl/wolfcrypt/coding.h>
|
#include <wolfssl/wolfcrypt/coding.h>
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_FPKI
|
||||||
|
#include <wolfssl/wolfcrypt/asn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
||||||
#include <wolfssh/misc.h>
|
#include <wolfssh/misc.h>
|
||||||
#else
|
#else
|
||||||
|
@ -740,29 +744,73 @@ static int RequestAuthentication(WS_UserAuthData* authData,
|
||||||
if (ret == WOLFSSH_USERAUTH_SUCCESS &&
|
if (ret == WOLFSSH_USERAUTH_SUCCESS &&
|
||||||
authData->type == WOLFSSH_USERAUTH_PUBLICKEY) {
|
authData->type == WOLFSSH_USERAUTH_PUBLICKEY) {
|
||||||
|
|
||||||
/* if this is a certificate and no specific authorized keys file has
|
#ifdef WOLFSSL_FPKI
|
||||||
* been set then rely on CA to have verified the cert */
|
/* compare user name to UPN in certificate */
|
||||||
if (authData->sf.publicKey.isCert &&
|
if (authData->sf.publicKey.isCert) {
|
||||||
!wolfSSHD_ConfigGetAuthKeysFileSet(authCtx->conf)) {
|
DecodedCert dCert;
|
||||||
wolfSSH_Log(WS_LOG_INFO,
|
|
||||||
"[SSHD] Relying on CA for public key check");
|
wc_InitDecodedCert(&dCert, authData->sf.publicKey.publicKey,
|
||||||
ret = WOLFSSH_USERAUTH_SUCCESS;
|
authData->sf.publicKey.publicKeySz, NULL);
|
||||||
}
|
if (wc_ParseCert(&dCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
|
||||||
else {
|
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Unable to parse peer cert.");
|
||||||
/* if not a certificate then parse through authorized key file */
|
|
||||||
rc = authCtx->checkPublicKeyCb(usr, &authData->sf.publicKey,
|
|
||||||
wolfSSHD_ConfigGetUserCAKeysFile(authCtx->conf));
|
|
||||||
if (rc == WSSHD_AUTH_SUCCESS) {
|
|
||||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key ok.");
|
|
||||||
ret = WOLFSSH_USERAUTH_SUCCESS;
|
|
||||||
}
|
|
||||||
else if (rc == WSSHD_AUTH_FAILURE) {
|
|
||||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key not authorized.");
|
|
||||||
ret = WOLFSSH_USERAUTH_INVALID_PUBLICKEY;
|
ret = WOLFSSH_USERAUTH_INVALID_PUBLICKEY;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error checking public key.");
|
int usrMatch = 0;
|
||||||
ret = WOLFSSH_USERAUTH_FAILURE;
|
DNS_entry* current = dCert.altNames;
|
||||||
|
|
||||||
|
while (current != NULL) {
|
||||||
|
if (current->type == ASN_OTHER_TYPE &&
|
||||||
|
current->oidSum == UPN_OID) {
|
||||||
|
/* found UPN oid, check name against user */
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < current->len; idx++) {
|
||||||
|
if (current->name[idx] == '@') break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int)XSTRLEN(usr) == idx &&
|
||||||
|
XSTRNCMP(usr, current->name, idx) == 0) {
|
||||||
|
usrMatch = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usrMatch == 0) {
|
||||||
|
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] incorrect user cert sent");
|
||||||
|
ret = WOLFSSH_USERAUTH_INVALID_PUBLICKEY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeDecodedCert(&dCert);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ret == WOLFSSH_USERAUTH_SUCCESS) {
|
||||||
|
/* if this is a certificate and no specific authorized keys file has
|
||||||
|
* been set then rely on CA to have verified the cert */
|
||||||
|
if (authData->sf.publicKey.isCert &&
|
||||||
|
!wolfSSHD_ConfigGetAuthKeysFileSet(authCtx->conf)) {
|
||||||
|
wolfSSH_Log(WS_LOG_INFO,
|
||||||
|
"[SSHD] Relying on CA for public key check");
|
||||||
|
ret = WOLFSSH_USERAUTH_SUCCESS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* if not a certificate then parse through authorized key file */
|
||||||
|
rc = authCtx->checkPublicKeyCb(usr, &authData->sf.publicKey,
|
||||||
|
wolfSSHD_ConfigGetUserCAKeysFile(authCtx->conf));
|
||||||
|
if (rc == WSSHD_AUTH_SUCCESS) {
|
||||||
|
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key ok.");
|
||||||
|
ret = WOLFSSH_USERAUTH_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (rc == WSSHD_AUTH_FAILURE) {
|
||||||
|
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key not authorized.");
|
||||||
|
ret = WOLFSSH_USERAUTH_INVALID_PUBLICKEY;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error checking public key.");
|
||||||
|
ret = WOLFSSH_USERAUTH_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,10 @@
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSH_CERTS
|
||||||
|
#include <wolfssl/wolfcrypt/asn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_WOLFSSH_CLIENT
|
#ifndef NO_WOLFSSH_CLIENT
|
||||||
|
|
||||||
|
@ -471,8 +475,71 @@ static int wsUserAuth(byte authType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(WOLFSSH_AGENT) || defined(WOLFSSH_CERTS)
|
||||||
|
static inline void ato32(const byte* c, word32* u32)
|
||||||
|
{
|
||||||
|
*u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WOLFSSH_CERTS
|
||||||
|
static int ParseRFC6187(const byte* in, word32 inSz, byte** leafOut,
|
||||||
|
word32* leafOutSz)
|
||||||
|
{
|
||||||
|
int ret = WS_SUCCESS;
|
||||||
|
word32 l = 0, m = 0;
|
||||||
|
|
||||||
|
if (inSz < sizeof(word32)) {
|
||||||
|
printf("inSz %d too small for holding cert name\n", inSz);
|
||||||
|
return WS_BUFFER_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip the name */
|
||||||
|
ato32(in, &l);
|
||||||
|
m += l + sizeof(word32);
|
||||||
|
|
||||||
|
/* Get the cert count */
|
||||||
|
if (ret == WS_SUCCESS) {
|
||||||
|
word32 count;
|
||||||
|
|
||||||
|
if (inSz - m < sizeof(word32))
|
||||||
|
return WS_BUFFER_E;
|
||||||
|
|
||||||
|
ato32(in + m, &count);
|
||||||
|
m += sizeof(word32);
|
||||||
|
if (ret == WS_SUCCESS && count == 0)
|
||||||
|
ret = WS_FATAL_ERROR; /* need at least one cert */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == WS_SUCCESS) {
|
||||||
|
word32 certSz = 0;
|
||||||
|
|
||||||
|
if (inSz - m < sizeof(word32))
|
||||||
|
return WS_BUFFER_E;
|
||||||
|
|
||||||
|
ato32(in + m, &certSz);
|
||||||
|
m += sizeof(word32);
|
||||||
|
if (ret == WS_SUCCESS) {
|
||||||
|
/* store leaf cert size to present to user callback */
|
||||||
|
*leafOutSz = certSz;
|
||||||
|
*leafOut = (byte*)in + m;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inSz - m < certSz)
|
||||||
|
return WS_BUFFER_E;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSH_CERTS */
|
||||||
|
|
||||||
|
|
||||||
static int wsPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx)
|
static int wsPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
#ifdef DEBUG_WOLFSSH
|
#ifdef DEBUG_WOLFSSH
|
||||||
printf("Sample public key check callback\n"
|
printf("Sample public key check callback\n"
|
||||||
" public key = %p\n"
|
" public key = %p\n"
|
||||||
|
@ -483,7 +550,49 @@ static int wsPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx)
|
||||||
(void)pubKeySz;
|
(void)pubKeySz;
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
|
||||||
|
#ifdef WOLFSSH_CERTS
|
||||||
|
#if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME)
|
||||||
|
/* try to parse the certificate and check it's IP address */
|
||||||
|
if (pubKeySz > 0) {
|
||||||
|
DecodedCert dCert;
|
||||||
|
byte* der = NULL;
|
||||||
|
word32 derSz = 0;
|
||||||
|
|
||||||
|
if (ParseRFC6187(pubKey, pubKeySz, &der, &derSz) == WS_SUCCESS) {
|
||||||
|
wc_InitDecodedCert(&dCert, der, derSz, NULL);
|
||||||
|
if (wc_ParseCert(&dCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
|
||||||
|
printf("public key not a cert\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int ipMatch = 0;
|
||||||
|
DNS_entry* current = dCert.altNames;
|
||||||
|
|
||||||
|
while (current != NULL) {
|
||||||
|
if (current->type == ASN_IP_TYPE) {
|
||||||
|
printf("host cert alt. name IP : %s\n",
|
||||||
|
current->ipString);
|
||||||
|
printf("\texpecting host IP : %s\n", (char*)ctx);
|
||||||
|
if (XSTRCMP(ctx, current->ipString) == 0) {
|
||||||
|
printf("\tmatched!\n");
|
||||||
|
ipMatch = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipMatch == 0) {
|
||||||
|
printf("IP did not match expected IP\n");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeDecodedCert(&dCert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -581,14 +690,6 @@ static THREAD_RET readInput(void* in)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef WOLFSSH_AGENT
|
|
||||||
static inline void ato32(const byte* c, word32* u32)
|
|
||||||
{
|
|
||||||
*u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static THREAD_RET readPeer(void* in)
|
static THREAD_RET readPeer(void* in)
|
||||||
{
|
{
|
||||||
byte buf[80];
|
byte buf[80];
|
||||||
|
@ -1161,7 +1262,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
|
||||||
#endif /* WOLFSSH_CERTS */
|
#endif /* WOLFSSH_CERTS */
|
||||||
|
|
||||||
wolfSSH_CTX_SetPublicKeyCheck(ctx, wsPublicKeyCheck);
|
wolfSSH_CTX_SetPublicKeyCheck(ctx, wsPublicKeyCheck);
|
||||||
wolfSSH_SetPublicKeyCheckCtx(ssh, (void*)"You've been sampled!");
|
wolfSSH_SetPublicKeyCheckCtx(ssh, (void*)host);
|
||||||
|
|
||||||
ret = wolfSSH_SetUsername(ssh, username);
|
ret = wolfSSH_SetUsername(ssh, username);
|
||||||
if (ret != WS_SUCCESS)
|
if (ret != WS_SUCCESS)
|
||||||
|
|
|
@ -20,6 +20,7 @@ EXTRA_DIST+= \
|
||||||
keys/pubkeys-rsa.txt keys/passwd.txt keys/ca-cert-ecc.der \
|
keys/pubkeys-rsa.txt keys/passwd.txt keys/ca-cert-ecc.der \
|
||||||
keys/ca-cert-ecc.pem keys/ca-key-ecc.der keys/ca-key-ecc.pem \
|
keys/ca-cert-ecc.pem keys/ca-key-ecc.der keys/ca-key-ecc.pem \
|
||||||
keys/server-cert.der keys/server-cert.pem \
|
keys/server-cert.der keys/server-cert.pem \
|
||||||
keys/john-cert.der keys/john-cert.pem \
|
keys/fred-cert.der keys/fred-cert.pem \
|
||||||
keys/server-key.pem keys/john-key.der keys/john-key.pem
|
keys/server-key.pem keys/fred-key.der keys/fred-key.pem \
|
||||||
|
keys/renewcerts.sh keys/renewcerts.cnf
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue