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/coding.h>
|
||||
|
||||
#ifdef WOLFSSL_FPKI
|
||||
#include <wolfssl/wolfcrypt/asn.h>
|
||||
#endif
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssh/misc.h>
|
||||
#else
|
||||
|
@ -740,6 +744,49 @@ static int RequestAuthentication(WS_UserAuthData* authData,
|
|||
if (ret == WOLFSSH_USERAUTH_SUCCESS &&
|
||||
authData->type == WOLFSSH_USERAUTH_PUBLICKEY) {
|
||||
|
||||
#ifdef WOLFSSL_FPKI
|
||||
/* compare user name to UPN in certificate */
|
||||
if (authData->sf.publicKey.isCert) {
|
||||
DecodedCert dCert;
|
||||
|
||||
wc_InitDecodedCert(&dCert, authData->sf.publicKey.publicKey,
|
||||
authData->sf.publicKey.publicKeySz, NULL);
|
||||
if (wc_ParseCert(&dCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Unable to parse peer cert.");
|
||||
ret = WOLFSSH_USERAUTH_INVALID_PUBLICKEY;
|
||||
}
|
||||
else {
|
||||
int usrMatch = 0;
|
||||
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 &&
|
||||
|
@ -766,6 +813,7 @@ static int RequestAuthentication(WS_UserAuthData* authData,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (wolfSSHD_AuthReducePermissions(authCtx) != WS_SUCCESS) {
|
||||
|
|
|
@ -60,6 +60,10 @@
|
|||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSH_CERTS
|
||||
#include <wolfssl/wolfcrypt/asn.h>
|
||||
#endif
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef DEBUG_WOLFSSH
|
||||
printf("Sample public key check callback\n"
|
||||
" public key = %p\n"
|
||||
|
@ -483,7 +550,49 @@ static int wsPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx)
|
|||
(void)pubKeySz;
|
||||
(void)ctx;
|
||||
#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)
|
||||
{
|
||||
byte buf[80];
|
||||
|
@ -1161,7 +1262,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
|
|||
#endif /* WOLFSSH_CERTS */
|
||||
|
||||
wolfSSH_CTX_SetPublicKeyCheck(ctx, wsPublicKeyCheck);
|
||||
wolfSSH_SetPublicKeyCheckCtx(ssh, (void*)"You've been sampled!");
|
||||
wolfSSH_SetPublicKeyCheckCtx(ssh, (void*)host);
|
||||
|
||||
ret = wolfSSH_SetUsername(ssh, username);
|
||||
if (ret != WS_SUCCESS)
|
||||
|
|
|
@ -20,6 +20,7 @@ EXTRA_DIST+= \
|
|||
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/server-cert.der keys/server-cert.pem \
|
||||
keys/john-cert.der keys/john-cert.pem \
|
||||
keys/server-key.pem keys/john-key.der keys/john-key.pem
|
||||
keys/fred-cert.der keys/fred-cert.pem \
|
||||
keys/server-key.pem keys/fred-key.der keys/fred-key.pem \
|
||||
keys/renewcerts.sh keys/renewcerts.cnf
|
||||
|
||||
|
|
Loading…
Reference in New Issue