mirror of https://github.com/wolfSSL/wolfssh.git
X.509 Certificate Support
1. Quality of Life improvements to echoserver: command line user config 2. adding policy checkingpull/415/head
parent
a8fa38d7f8
commit
13e525478c
|
@ -34,6 +34,7 @@
|
||||||
#include <wolfssl/wolfcrypt/hash.h>
|
#include <wolfssl/wolfcrypt/hash.h>
|
||||||
#include <wolfssl/wolfcrypt/coding.h>
|
#include <wolfssl/wolfcrypt/coding.h>
|
||||||
#include <wolfssl/wolfcrypt/wc_port.h>
|
#include <wolfssl/wolfcrypt/wc_port.h>
|
||||||
|
#include <wolfssl/wolfcrypt/asn_public.h>
|
||||||
#include <wolfssh/ssh.h>
|
#include <wolfssh/ssh.h>
|
||||||
#include <wolfssh/internal.h>
|
#include <wolfssh/internal.h>
|
||||||
#include <wolfssh/wolfsftp.h>
|
#include <wolfssh/wolfsftp.h>
|
||||||
|
@ -1445,6 +1446,39 @@ static int load_key(byte isEcc, byte* buf, word32 bufSz)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct StrList {
|
||||||
|
const char* str;
|
||||||
|
struct StrList* next;
|
||||||
|
} StrList;
|
||||||
|
|
||||||
|
|
||||||
|
static StrList* StrListAdd(StrList* list, const char* str)
|
||||||
|
{
|
||||||
|
if (str != NULL) {
|
||||||
|
StrList* newStr = (StrList*)WMALLOC(sizeof *newStr, NULL, 0);
|
||||||
|
|
||||||
|
if (newStr != NULL) {
|
||||||
|
newStr->str = str;
|
||||||
|
newStr->next = list;
|
||||||
|
list = newStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void StrListFree(StrList* list)
|
||||||
|
{
|
||||||
|
StrList* curStr;
|
||||||
|
|
||||||
|
while (list != NULL) {
|
||||||
|
curStr = list;
|
||||||
|
list = list->next;
|
||||||
|
WFREE(curStr, NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Map user names to passwords */
|
/* Map user names to passwords */
|
||||||
/* Use arrays for username and p. The password or public key can
|
/* Use arrays for username and p. The password or public key can
|
||||||
* be hashed and the hash stored here. Then I won't need the type. */
|
* be hashed and the hash stored here. Then I won't need the type. */
|
||||||
|
@ -1508,6 +1542,8 @@ static const char samplePasswordBuffer[] =
|
||||||
"jack:fetchapail\n";
|
"jack:fetchapail\n";
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#ifndef NO_FILESYSTEM
|
||||||
#ifndef WOLFSSH_NO_ECC
|
#ifndef WOLFSSH_NO_ECC
|
||||||
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256
|
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256
|
||||||
static const char samplePublicKeyEccBuffer[] =
|
static const char samplePublicKeyEccBuffer[] =
|
||||||
|
@ -1547,6 +1583,11 @@ static const char samplePublicKeyRsaBuffer[] =
|
||||||
"biE57dK6BrH5iZwVLTQKux31uCJLPhiktI3iLbdlGZEctJkTasfVSsUizwVIyRjhVKmbdI"
|
"biE57dK6BrH5iZwVLTQKux31uCJLPhiktI3iLbdlGZEctJkTasfVSsUizwVIyRjhVKmbdI"
|
||||||
"RGwkU38D043AR1h0mUoGCPIKuqcFMf gretel\n";
|
"RGwkU38D043AR1h0mUoGCPIKuqcFMf gretel\n";
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* NO_FILESYSTEM */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WOLFSSH_ALLOW_USERAUTH_NONE
|
||||||
|
|
||||||
static const char sampleNoneBuffer[] =
|
static const char sampleNoneBuffer[] =
|
||||||
"holmes\n"
|
"holmes\n"
|
||||||
|
@ -1587,6 +1628,7 @@ static int LoadNoneBuffer(byte* buf, word32 bufSz, PwMapList* list)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* WOLFSSH_ALLOW_USERAUTH_NONE */
|
||||||
|
|
||||||
static int LoadPasswordBuffer(byte* buf, word32 bufSz, PwMapList* list)
|
static int LoadPasswordBuffer(byte* buf, word32 bufSz, PwMapList* list)
|
||||||
{
|
{
|
||||||
|
@ -1714,24 +1756,102 @@ static int LoadPublicKeyBuffer(byte* buf, word32 bufSz, PwMapList* list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef WOLFSSH_CERTS
|
static int LoadPasswdList(StrList* strList, PwMapList* mapList)
|
||||||
static int LoadCertBuffer(byte* buf, word32 bufSz, PwMapList* list)
|
|
||||||
{
|
{
|
||||||
if (list == NULL)
|
char names[256];
|
||||||
return -1;
|
char* passwd;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
if (buf == NULL || bufSz == 0)
|
while (strList) {
|
||||||
return 0;
|
WSTRNCPY(names, strList->str, sizeof names);
|
||||||
|
passwd = WSTRCHR(names, ':');
|
||||||
|
if (passwd != NULL) {
|
||||||
|
*passwd = 0;
|
||||||
|
passwd++;
|
||||||
|
|
||||||
if (PwMapNew(list,
|
PwMapNew(mapList, WOLFSSH_USERAUTH_PASSWORD,
|
||||||
WOLFSSH_USERAUTH_PUBLICKEY,
|
(byte*)names, (word32)WSTRLEN(names),
|
||||||
(const byte*)"orange", 6, buf, bufSz) == NULL ) {
|
(byte*)passwd, (word32)WSTRLEN(passwd));
|
||||||
return -1;
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Ignoring password: %s\n", names);
|
||||||
|
}
|
||||||
|
|
||||||
|
strList = strList->next;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int LoadPubKeyList(StrList* strList, int format, PwMapList* mapList)
|
||||||
|
{
|
||||||
|
char names[256];
|
||||||
|
char* fileName;
|
||||||
|
byte* buf;
|
||||||
|
word32 bufSz;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
while (strList) {
|
||||||
|
buf = NULL;
|
||||||
|
bufSz = 0;
|
||||||
|
|
||||||
|
WSTRNCPY(names, strList->str, sizeof names);
|
||||||
|
fileName = WSTRCHR(names, ':');
|
||||||
|
if (fileName != NULL) {
|
||||||
|
*fileName = 0;
|
||||||
|
fileName++;
|
||||||
|
|
||||||
|
load_file(fileName, NULL, &bufSz);
|
||||||
|
buf = (byte*)WMALLOC(bufSz, NULL, 0);
|
||||||
|
bufSz = load_file(fileName, buf, &bufSz);
|
||||||
|
if (bufSz > 0) {
|
||||||
|
if (format == WOLFSSH_FORMAT_SSH) {
|
||||||
|
const byte* type = NULL;
|
||||||
|
byte* out = NULL;
|
||||||
|
word32 typeSz, outSz;
|
||||||
|
|
||||||
|
wolfSSH_ReadKey_buffer(buf, bufSz, WOLFSSH_FORMAT_SSH,
|
||||||
|
&out, &outSz, &type, &typeSz, NULL);
|
||||||
|
|
||||||
|
(void)type;
|
||||||
|
(void)typeSz;
|
||||||
|
|
||||||
|
WFREE(buf, NULL, 0);
|
||||||
|
buf = out;
|
||||||
|
bufSz = outSz;
|
||||||
|
}
|
||||||
|
else if (format == WOLFSSH_FORMAT_PEM) {
|
||||||
|
byte* out = NULL;
|
||||||
|
word32 outSz;
|
||||||
|
|
||||||
|
out = (byte*)WMALLOC(bufSz, NULL, 0);
|
||||||
|
outSz = wc_CertPemToDer(buf, bufSz, out, bufSz, CERT_TYPE);
|
||||||
|
|
||||||
|
WFREE(buf, NULL, 0);
|
||||||
|
buf = out;
|
||||||
|
bufSz = outSz;
|
||||||
|
}
|
||||||
|
|
||||||
|
PwMapNew(mapList, WOLFSSH_USERAUTH_PUBLICKEY,
|
||||||
|
(byte*)names, (word32)WSTRLEN(names), buf, bufSz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "File error: %s\n", names);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Ignoring key: %s\n", names);
|
||||||
|
}
|
||||||
|
|
||||||
|
WFREE(buf, NULL, 0);
|
||||||
|
strList = strList->next;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static int wsUserAuth(byte authType,
|
static int wsUserAuth(byte authType,
|
||||||
|
@ -1847,7 +1967,16 @@ static void ShowUsage(void)
|
||||||
#ifdef WOLFSSH_SFTP
|
#ifdef WOLFSSH_SFTP
|
||||||
printf(" -d <string> set the home directory for SFTP connections\n");
|
printf(" -d <string> set the home directory for SFTP connections\n");
|
||||||
#endif
|
#endif
|
||||||
printf(" -j <file> load in a public key to accept from peer\n");
|
printf(" -j <file> load in a SSH public key to accept from peer\n"
|
||||||
|
" (user assumed in comment)\n");
|
||||||
|
printf(" -I <name>:<file>\n"
|
||||||
|
" load in a SSH public key to accept from peer\n");
|
||||||
|
printf(" -J <name>:<file>\n"
|
||||||
|
" load in an X.509 PEM cert to accept from peer\n");
|
||||||
|
printf(" -K <name>:<file>\n"
|
||||||
|
" load in an X.509 DER cert to accept from peer\n");
|
||||||
|
printf(" -P <name>:<password>\n"
|
||||||
|
" add password to accept from peer\n");
|
||||||
#ifdef WOLFSSH_CERTS
|
#ifdef WOLFSSH_CERTS
|
||||||
printf(" -a <file> load in a root CA certificate file\n");
|
printf(" -a <file> load in a root CA certificate file\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -1875,6 +2004,10 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
||||||
func_args* serverArgs = (func_args*)args;
|
func_args* serverArgs = (func_args*)args;
|
||||||
WOLFSSH_CTX* ctx = NULL;
|
WOLFSSH_CTX* ctx = NULL;
|
||||||
PwMapList pwMapList;
|
PwMapList pwMapList;
|
||||||
|
StrList* sshPubKeyList = NULL;
|
||||||
|
StrList* pemPubKeyList = NULL;
|
||||||
|
StrList* derPubKeyList = NULL;
|
||||||
|
StrList* passwdList = NULL;
|
||||||
WS_SOCKET_T listenFd = 0;
|
WS_SOCKET_T listenFd = 0;
|
||||||
word32 defaultHighwater = EXAMPLE_HIGHWATER_MARK;
|
word32 defaultHighwater = EXAMPLE_HIGHWATER_MARK;
|
||||||
word32 threadCount = 0;
|
word32 threadCount = 0;
|
||||||
|
@ -1897,7 +2030,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
||||||
serverArgs->return_code = 0;
|
serverArgs->return_code = 0;
|
||||||
|
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
while ((ch = mygetopt(argc, argv, "?1a:d:efEp:R:Nj:")) != -1) {
|
while ((ch = mygetopt(argc, argv, "?1a:d:efEp:R:Ni:j:I:J:K:P:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '?' :
|
case '?' :
|
||||||
ShowUsage();
|
ShowUsage();
|
||||||
|
@ -1955,6 +2088,22 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
||||||
userPubKey = myoptarg;
|
userPubKey = myoptarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
sshPubKeyList = StrListAdd(sshPubKeyList, myoptarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'J':
|
||||||
|
pemPubKeyList = StrListAdd(pemPubKeyList, myoptarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'K':
|
||||||
|
derPubKeyList = StrListAdd(derPubKeyList, myoptarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'P':
|
||||||
|
passwdList = StrListAdd(passwdList, myoptarg);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ShowUsage();
|
ShowUsage();
|
||||||
WEXIT(MY_EX_USAGE);
|
WEXIT(MY_EX_USAGE);
|
||||||
|
@ -1980,6 +2129,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
||||||
userEcc = 0;
|
userEcc = 0;
|
||||||
peerEcc = 0;
|
peerEcc = 0;
|
||||||
#endif
|
#endif
|
||||||
|
(void)userEcc;
|
||||||
|
|
||||||
if (wolfSSH_Init() != WS_SUCCESS) {
|
if (wolfSSH_Init() != WS_SUCCESS) {
|
||||||
fprintf(stderr, "Couldn't initialize wolfSSH.\n");
|
fprintf(stderr, "Couldn't initialize wolfSSH.\n");
|
||||||
|
@ -2005,8 +2155,29 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
||||||
wolfSSH_CTX_SetFwdCb(ctx, wolfSSH_FwdDefaultActions, NULL);
|
wolfSSH_CTX_SetFwdCb(ctx, wolfSSH_FwdDefaultActions, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (sshPubKeyList) {
|
||||||
|
LoadPubKeyList(sshPubKeyList, WOLFSSH_FORMAT_SSH, &pwMapList);
|
||||||
|
StrListFree(sshPubKeyList);
|
||||||
|
sshPubKeyList = NULL;
|
||||||
|
}
|
||||||
|
if (pemPubKeyList) {
|
||||||
|
LoadPubKeyList(pemPubKeyList, WOLFSSH_FORMAT_PEM, &pwMapList);
|
||||||
|
StrListFree(pemPubKeyList);
|
||||||
|
pemPubKeyList = NULL;
|
||||||
|
}
|
||||||
|
if (derPubKeyList) {
|
||||||
|
LoadPubKeyList(derPubKeyList, WOLFSSH_FORMAT_ASN1, &pwMapList);
|
||||||
|
StrListFree(derPubKeyList);
|
||||||
|
derPubKeyList = NULL;
|
||||||
|
}
|
||||||
|
if (passwdList) {
|
||||||
|
LoadPasswdList(passwdList, &pwMapList);
|
||||||
|
StrListFree(passwdList);
|
||||||
|
passwdList = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const char* bufName = NULL;
|
//const char* bufName = NULL;
|
||||||
#ifndef WOLFSSH_SMALL_STACK
|
#ifndef WOLFSSH_SMALL_STACK
|
||||||
byte buf[EXAMPLE_KEYLOAD_BUFFER_SZ];
|
byte buf[EXAMPLE_KEYLOAD_BUFFER_SZ];
|
||||||
#endif
|
#endif
|
||||||
|
@ -2055,30 +2226,10 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
||||||
}
|
}
|
||||||
load_file(userPubKey, userBuf, &userBufSz);
|
load_file(userPubKey, userBuf, &userBufSz);
|
||||||
LoadPublicKeyBuffer(userBuf, userBufSz, &pwMapList);
|
LoadPublicKeyBuffer(userBuf, userBufSz, &pwMapList);
|
||||||
|
WFREE(userBuf, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WOLFSSH_CERTS
|
#ifdef WOLFSSH_CERTS
|
||||||
{
|
|
||||||
byte* certBuf = NULL;
|
|
||||||
word32 certBufSz = 0;
|
|
||||||
const char* filename = "../ca/orange-cert.der";
|
|
||||||
|
|
||||||
load_file(filename, NULL, &certBufSz);
|
|
||||||
|
|
||||||
if (certBufSz == 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Couldn't find size of file %s.\n", filename);
|
|
||||||
WEXIT(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
certBuf = (byte*)WMALLOC(certBufSz, NULL, 0);
|
|
||||||
if (certBuf == NULL) {
|
|
||||||
fprintf(stderr, "WMALLOC failed\n");
|
|
||||||
WEXIT(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
load_file(filename, certBuf, &certBufSz);
|
|
||||||
LoadCertBuffer(certBuf, certBufSz, &pwMapList);
|
|
||||||
}
|
|
||||||
if (caCert) {
|
if (caCert) {
|
||||||
byte* certBuf = NULL;
|
byte* certBuf = NULL;
|
||||||
word32 certBufSz = 0;
|
word32 certBufSz = 0;
|
||||||
|
@ -2113,6 +2264,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
||||||
keyLoadBuf[bufSz] = 0;
|
keyLoadBuf[bufSz] = 0;
|
||||||
LoadPasswordBuffer(keyLoadBuf, bufSz, &pwMapList);
|
LoadPasswordBuffer(keyLoadBuf, bufSz, &pwMapList);
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (userEcc) {
|
if (userEcc) {
|
||||||
#ifndef WOLFSSH_NO_ECC
|
#ifndef WOLFSSH_NO_ECC
|
||||||
bufName = samplePublicKeyEccBuffer;
|
bufName = samplePublicKeyEccBuffer;
|
||||||
|
@ -2130,10 +2282,13 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
||||||
LoadPublicKeyBuffer(keyLoadBuf, bufSz, &pwMapList);
|
LoadPublicKeyBuffer(keyLoadBuf, bufSz, &pwMapList);
|
||||||
}
|
}
|
||||||
|
|
||||||
bufSz = (word32)WSTRLEN(sampleNoneBuffer);
|
#ifdef WOLFSSH_ALLOW_USERAUTH_NONE
|
||||||
WMEMCPY(keyLoadBuf, sampleNoneBuffer, bufSz);
|
bufSz = (word32)WSTRLEN(sampleNoneBuffer);
|
||||||
keyLoadBuf[bufSz] = 0;
|
WMEMCPY(keyLoadBuf, sampleNoneBuffer, bufSz);
|
||||||
LoadNoneBuffer(keyLoadBuf, bufSz, &pwMapList);
|
keyLoadBuf[bufSz] = 0;
|
||||||
|
LoadNoneBuffer(keyLoadBuf, bufSz, &pwMapList);
|
||||||
|
#endif /* WOLFSSH_ALLOW_USERAUTH_NONE */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WOLFSSH_SMALL_STACK
|
#ifdef WOLFSSH_SMALL_STACK
|
||||||
WFREE(keyLoadBuf, NULL, 0);
|
WFREE(keyLoadBuf, NULL, 0);
|
||||||
|
|
109
src/certman.c
109
src/certman.c
|
@ -181,6 +181,13 @@ int wolfSSH_CERTMAN_LoadRootCA_buffer(WOLFSSH_CERTMAN* cm,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int CheckProfile(DecodedCert* cert, int profile);
|
||||||
|
enum {
|
||||||
|
PROFILE_FPKI_WORKSHEET_6 = 6,
|
||||||
|
PROFILE_FPKI_WORKSHEET_10 = 10,
|
||||||
|
PROFILE_FPKI_WORKSHEET_16 = 16
|
||||||
|
};
|
||||||
|
|
||||||
int wolfSSH_CERTMAN_VerifyCert_buffer(WOLFSSH_CERTMAN* cm,
|
int wolfSSH_CERTMAN_VerifyCert_buffer(WOLFSSH_CERTMAN* cm,
|
||||||
const unsigned char* cert, word32 certSz)
|
const unsigned char* cert, word32 certSz)
|
||||||
{
|
{
|
||||||
|
@ -226,11 +233,113 @@ int wolfSSH_CERTMAN_VerifyCert_buffer(WOLFSSH_CERTMAN* cm,
|
||||||
else {
|
else {
|
||||||
WLOG(WS_LOG_CERTMAN, "ocsp lookup: other error (%d)", ret);
|
WLOG(WS_LOG_CERTMAN, "ocsp lookup: other error (%d)", ret);
|
||||||
ret = WS_CERT_OTHER_E;
|
ret = WS_CERT_OTHER_E;
|
||||||
|
ret = WS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret == WS_SUCCESS) {
|
||||||
|
DecodedCert decoded;
|
||||||
|
|
||||||
|
InitDecodedCert(&decoded, cert, certSz, cm->cm);
|
||||||
|
ret = ParseCert(&decoded, WOLFSSL_FILETYPE_ASN1, 0, cm->cm);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
ret =
|
||||||
|
CheckProfile(&decoded, PROFILE_FPKI_WORKSHEET_6) ||
|
||||||
|
CheckProfile(&decoded, PROFILE_FPKI_WORKSHEET_10) ||
|
||||||
|
CheckProfile(&decoded, PROFILE_FPKI_WORKSHEET_16);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
WLOG(WS_LOG_CERTMAN, "certificate didn't match profile");
|
||||||
|
ret = WS_CERT_PROFILE_E;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = WS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeDecodedCert(&decoded);
|
||||||
|
}
|
||||||
|
|
||||||
WLOG_LEAVE(ret);
|
WLOG_LEAVE(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int CheckProfile(DecodedCert* cert, int profile)
|
||||||
|
{
|
||||||
|
int valid = (cert != NULL);
|
||||||
|
const char* certPolicies[2] = {NULL, NULL};
|
||||||
|
byte extKeyUsage = 0, extKeyUsageSsh = 0, extKeyUsageSshAllowed = 0;
|
||||||
|
|
||||||
|
if (profile == PROFILE_FPKI_WORKSHEET_6) {
|
||||||
|
certPolicies[0] = "2.16.840.1.101.3.2.1.3.13";
|
||||||
|
extKeyUsage = EXTKEYUSE_CLIENT_AUTH;
|
||||||
|
extKeyUsageSsh = EXTKEYUSE_SSH_MSCL;
|
||||||
|
extKeyUsageSshAllowed =
|
||||||
|
EXTKEYUSE_SSH_KP_CLIENT_AUTH |
|
||||||
|
EXTKEYUSE_SSH_CLIENT_AUTH;
|
||||||
|
}
|
||||||
|
else if (profile == PROFILE_FPKI_WORKSHEET_10) {
|
||||||
|
certPolicies[0] = "2.16.840.1.101.3.2.1.3.40";
|
||||||
|
certPolicies[1] = "2.16.840.1.101.3.2.1.3.41";
|
||||||
|
extKeyUsage = EXTKEYUSE_CLIENT_AUTH;
|
||||||
|
extKeyUsageSshAllowed =
|
||||||
|
EXTKEYUSE_SSH_MSCL |
|
||||||
|
EXTKEYUSE_SSH_KP_CLIENT_AUTH |
|
||||||
|
EXTKEYUSE_SSH_CLIENT_AUTH;
|
||||||
|
}
|
||||||
|
else if (profile == PROFILE_FPKI_WORKSHEET_16) {
|
||||||
|
certPolicies[0] = "2.16.840.1.101.3.2.1.3.45";
|
||||||
|
extKeyUsage = EXTKEYUSE_CLIENT_AUTH;
|
||||||
|
extKeyUsageSsh = EXTKEYUSE_SSH_MSCL;
|
||||||
|
extKeyUsageSshAllowed =
|
||||||
|
EXTKEYUSE_SSH_KP_CLIENT_AUTH |
|
||||||
|
EXTKEYUSE_SSH_CLIENT_AUTH;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
valid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
valid = cert->extKeyUsageSet &&
|
||||||
|
cert->extKeyUsage == KEYUSE_DIGITAL_SIG &&
|
||||||
|
/*cert->extBasicConstCrit;*/ 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
valid = WSTRCMP(cert->countryOfCitizenship, "US") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
valid = !cert->isCA;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
valid =
|
||||||
|
/* Must include all in extKeyUsage */
|
||||||
|
((extKeyUsage == 0) ||
|
||||||
|
((cert->extExtKeyUsage & extKeyUsage) != extKeyUsage)) &&
|
||||||
|
/* Must include all in extKeyUsageSsh */
|
||||||
|
((extKeyUsageSsh == 0) ||
|
||||||
|
((cert->extExtKeyUsageSsh & extKeyUsageSsh)
|
||||||
|
!= extKeyUsageSsh)) &&
|
||||||
|
/* Must include at least one in extKeyUsageSshAllowed */
|
||||||
|
((extKeyUsageSshAllowed == 0) ||
|
||||||
|
((cert->extExtKeyUsageSsh & extKeyUsageSshAllowed) != 0));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* WOLFSSH_CERTS */
|
#endif /* WOLFSSH_CERTS */
|
||||||
|
|
|
@ -399,6 +399,9 @@ const char* GetErrorString(int err)
|
||||||
case WS_CERT_OTHER_E:
|
case WS_CERT_OTHER_E:
|
||||||
return "other certificate error";
|
return "other certificate error";
|
||||||
|
|
||||||
|
case WS_CERT_PROFILE_E:
|
||||||
|
return "certificate profile requirements error";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "Unknown error code";
|
return "Unknown error code";
|
||||||
}
|
}
|
||||||
|
@ -4837,6 +4840,7 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
|
||||||
WS_UserAuthData_PublicKey* pk = NULL;
|
WS_UserAuthData_PublicKey* pk = NULL;
|
||||||
int ret = WS_SUCCESS;
|
int ret = WS_SUCCESS;
|
||||||
int authFailure = 0;
|
int authFailure = 0;
|
||||||
|
byte pkTypeId;
|
||||||
|
|
||||||
WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestPublicKey()");
|
WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestPublicKey()");
|
||||||
|
|
||||||
|
@ -4859,13 +4863,25 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
|
||||||
if (ret == WS_SUCCESS) {
|
if (ret == WS_SUCCESS) {
|
||||||
pk->publicKeyType = buf + begin;
|
pk->publicKeyType = buf + begin;
|
||||||
begin += pk->publicKeyTypeSz;
|
begin += pk->publicKeyTypeSz;
|
||||||
ret = GetSize(&pk->publicKeySz, buf, len, &begin);
|
|
||||||
|
pkTypeId = NameToId((char*)pk->publicKeyType, pk->publicKeyTypeSz);
|
||||||
|
if (pkTypeId == ID_UNKNOWN) {
|
||||||
|
WLOG(WS_LOG_DEBUG, "DUARPK: Unknown / Unsupported key type");
|
||||||
|
ret = WS_INVALID_ALGO_ID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret == WS_SUCCESS)
|
||||||
|
ret = GetSize(&pk->publicKeySz, buf, len, &begin);
|
||||||
|
|
||||||
if (ret == WS_SUCCESS) {
|
if (ret == WS_SUCCESS) {
|
||||||
pk->publicKey = buf + begin;
|
pk->publicKey = buf + begin;
|
||||||
begin += pk->publicKeySz;
|
begin += pk->publicKeySz;
|
||||||
{
|
#ifdef WOLFSSH_CERTS
|
||||||
|
if (pkTypeId == ID_X509V3_SSH_RSA ||
|
||||||
|
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP256 ||
|
||||||
|
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP384 ||
|
||||||
|
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP521) {
|
||||||
word32 l = 0, m = 0;
|
word32 l = 0, m = 0;
|
||||||
|
|
||||||
/* Skip the name */
|
/* Skip the name */
|
||||||
|
@ -4877,6 +4893,7 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
|
||||||
pk->publicKeySz = l;
|
pk->publicKeySz = l;
|
||||||
pk->publicKey = pk->publicKey + m;
|
pk->publicKey = pk->publicKey + m;
|
||||||
}
|
}
|
||||||
|
#endif /* WOLFSSH_CERTS */
|
||||||
|
|
||||||
if (pk->hasSignature) {
|
if (pk->hasSignature) {
|
||||||
ret = GetSize(&pk->signatureSz, buf, len, &begin);
|
ret = GetSize(&pk->signatureSz, buf, len, &begin);
|
||||||
|
@ -4929,14 +4946,6 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
|
||||||
byte digest[WC_MAX_DIGEST_SIZE];
|
byte digest[WC_MAX_DIGEST_SIZE];
|
||||||
word32 digestSz = 0;
|
word32 digestSz = 0;
|
||||||
enum wc_HashType hashId = WC_HASH_TYPE_SHA;
|
enum wc_HashType hashId = WC_HASH_TYPE_SHA;
|
||||||
byte pkTypeId;
|
|
||||||
|
|
||||||
pkTypeId = NameToId((char*)pk->publicKeyType,
|
|
||||||
pk->publicKeyTypeSz);
|
|
||||||
if (pkTypeId == ID_UNKNOWN) {
|
|
||||||
WLOG(WS_LOG_DEBUG, "DUARPK: Unknown / Unsupported key type");
|
|
||||||
ret = WS_INVALID_ALGO_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == WS_SUCCESS) {
|
if (ret == WS_SUCCESS) {
|
||||||
hashId = HashForId(pkTypeId);
|
hashId = HashForId(pkTypeId);
|
||||||
|
@ -4968,12 +4977,26 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
|
||||||
/* The rest of the fields in the signature are already
|
/* The rest of the fields in the signature are already
|
||||||
* in the buffer. Just need to account for the sizes. */
|
* in the buffer. Just need to account for the sizes. */
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = wc_HashUpdate(&hash, hashId, pk->dataToSign,
|
word32 dataToSignSz;
|
||||||
authData->usernameSz +
|
|
||||||
authData->serviceNameSz +
|
dataToSignSz = authData->usernameSz +
|
||||||
authData->authNameSz + BOOLEAN_SZ +
|
authData->serviceNameSz +
|
||||||
(pk->publicKeyTypeSz*2) + pk->publicKeySz +
|
authData->authNameSz + BOOLEAN_SZ +
|
||||||
(UINT32_SZ * 9));
|
pk->publicKeyTypeSz + pk->publicKeySz +
|
||||||
|
(UINT32_SZ * 5);
|
||||||
|
|
||||||
|
#ifdef WOLFSSH_CERTS
|
||||||
|
if (pkTypeId == ID_X509V3_SSH_RSA ||
|
||||||
|
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP256 ||
|
||||||
|
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP384 ||
|
||||||
|
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP521) {
|
||||||
|
|
||||||
|
dataToSignSz += pk->publicKeyTypeSz + (UINT32_SZ * 4);
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSH_CERTS */
|
||||||
|
|
||||||
|
ret = wc_HashUpdate(&hash, hashId,
|
||||||
|
pk->dataToSign, dataToSignSz);
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = wc_HashFinal(&hash, hashId, digest);
|
ret = wc_HashFinal(&hash, hashId, digest);
|
||||||
|
|
|
@ -124,8 +124,9 @@ enum WS_ErrorCodes {
|
||||||
WS_CERT_REVOKED_E = -1083, /* User certificate reported revoked */
|
WS_CERT_REVOKED_E = -1083, /* User certificate reported revoked */
|
||||||
WS_CERT_SIG_CONFIRM_E = -1084, /* Root cert sig verify fail */
|
WS_CERT_SIG_CONFIRM_E = -1084, /* Root cert sig verify fail */
|
||||||
WS_CERT_OTHER_E = -1085, /* Other certificate issue */
|
WS_CERT_OTHER_E = -1085, /* Other certificate issue */
|
||||||
|
WS_CERT_PROFILE_E = -1086, /* Cert doesn't meet profile reqs */
|
||||||
|
|
||||||
WS_LAST_E = -1085 /* Update this to indicate last error */
|
WS_LAST_E = -1086 /* Update this to indicate last error */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue