add mutual X509 auth of host key and sshd_config parsing additions

pull/453/head
JacobBarthelmeh 2022-08-25 14:04:01 -07:00
parent 7c486e518a
commit 3e1a6ff342
9 changed files with 1234 additions and 551 deletions

View File

@ -76,7 +76,7 @@ struct WOLFSSHD_AUTH {
#endif
#ifndef MAX_LINE_SZ
#define MAX_LINE_SZ 500
#define MAX_LINE_SZ 900
#endif
#ifndef MAX_PATH_SZ
#define MAX_PATH_SZ 80
@ -144,14 +144,24 @@ static int CheckAuthKeysLine(char* line, word32 lineSz, const byte* key,
word32 keyCandSz;
char* last;
enum {
#ifdef WOLFSSH_CERTS
NUM_ALLOWED_TYPES = 9
#else
NUM_ALLOWED_TYPES = 5
#endif
};
static const char* allowedTypes[NUM_ALLOWED_TYPES] = {
"ssh-rsa",
"ssh-ed25519",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521"
"ecdsa-sha2-nistp521",
#ifdef WOLFSSH_CERTS
"x509v3-ssh-rsa",
"x509v3-ecdsa-sha2-nistp256",
"x509v3-ecdsa-sha2-nistp384",
"x509v3-ecdsa-sha2-nistp521",
#endif
};
int typeOk = 0;
int i;
@ -639,7 +649,7 @@ static int DoCheckUser(const char* usr, WOLFSSHD_AUTH* auth)
if (wolfSSHD_ConfigGetPermitRoot(auth->conf) == 0) {
if (XSTRCMP(usr, "root") == 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Login as root not permited");
ret = WOLFSSH_USERAUTH_FAILURE;
ret = WOLFSSH_USERAUTH_REJECTED;
}
}
@ -692,7 +702,7 @@ static int RequestAuthentication(WS_UserAuthData* authData,
if (wolfSSHD_ConfigGetPwAuth(authCtx->conf) != 1) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Password authentication not "
"allowed by configuration!");
ret = WOLFSSH_USERAUTH_FAILURE;
ret = WOLFSSH_USERAUTH_REJECTED;
}
/* Check if password is valid for this user. */
/* first handle empty password cases */
@ -797,6 +807,35 @@ int DefaultUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
}
int DefaultUserAuthTypes(WOLFSSH* ssh, void* ctx)
{
WOLFSSHD_CONFIG* usrConf;
WOLFSSHD_AUTH* authCtx;
char* usr;
int ret = 0;
if (ssh == NULL || ctx == NULL)
return WS_BAD_ARGUMENT;
authCtx = (WOLFSSHD_AUTH*)ctx;
/* get configuration for user */
usr = wolfSSH_GetUsername(ssh);
usrConf = wolfSSHD_AuthGetUserConf(authCtx, usr, NULL, NULL,
NULL, NULL, NULL);
if (usrConf == NULL) {
ret = WS_BAD_ARGUMENT;
}
else {
if (wolfSSHD_ConfigGetPwAuth(usrConf) == 1) {
ret |= WOLFSSH_USERAUTH_PASSWORD;
}
ret |= WOLFSSH_USERAUTH_PUBLICKEY;
}
return ret;
}
static int SetDefaultUserCheck(WOLFSSHD_AUTH* auth)
{
int ret = WS_NOT_COMPILED;
@ -1018,18 +1057,22 @@ WOLFSSHD_CONFIG* wolfSSHD_AuthGetUserConf(const WOLFSSHD_AUTH* auth,
if (auth != NULL) {
struct passwd *p_passwd;
char* gName = NULL;
p_passwd = getpwnam((const char *)usr);
if (p_passwd == NULL) {
return NULL;
if (usr != NULL) {
p_passwd = getpwnam((const char *)usr);
if (p_passwd == NULL) {
return NULL;
}
g = getgrgid(p_passwd->pw_gid);
if (g == NULL) {
return NULL;
}
gName = g->gr_name;
}
g = getgrgid(p_passwd->pw_gid);
if (g == NULL) {
return NULL;
}
ret = wolfSSHD_GetUserConf(auth->conf, usr, g->gr_name, host, localAdr,
ret = wolfSSHD_GetUserConf(auth->conf, usr, gName, host, localAdr,
localPort, RDomain, adr);
}
return ret;

View File

@ -30,6 +30,7 @@ USER_NODE* AddNewUser(USER_NODE* list, byte type, const byte* username,
void SetAuthKeysPattern(const char* pattern);
int DefaultUserAuth(byte authType, WS_UserAuthData* authData, void* ctx);
int DefaultUserAuthTypes(WOLFSSH* ssh, void* ctx);
typedef struct WOLFSSHD_AUTH WOLFSSHD_AUTH;

View File

@ -478,6 +478,7 @@ static int HandlePwAuth(WOLFSSHD_CONFIG* conf, const char* value)
if (ret == WS_SUCCESS) {
if (WSTRCMP(value, "no") == 0) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] password authentication disabled");
conf->passwordAuth = 0;
}
else if (WSTRCMP(value, "yes") == 0) {

View File

@ -187,6 +187,47 @@ static void CleanupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
(void)conf;
}
#ifndef NO_FILESYSTEM
static void freeBufferFromFile(byte* buf, void* heap)
{
if (buf != NULL)
WFREE(buf, heap, DYNTYPE_SSHD);
(void)heap;
}
/* set bufSz to size wanted if too small and buf is null */
static byte* getBufferFromFile(const char* fileName, word32* bufSz, void* heap)
{
FILE* file;
byte* buf = NULL;
word32 fileSz;
word32 readSz;
if (fileName == NULL) return NULL;
if (WFOPEN(&file, fileName, "rb") != 0)
return NULL;
fseek(file, 0, XSEEK_END);
fileSz = (word32)ftell(file);
rewind(file);
buf = (byte*)WMALLOC(fileSz + 1, heap, DYNTYPE_SSHD);
if (buf != NULL) {
readSz = (word32)fread(buf, 1, fileSz, file);
if (readSz < fileSz) {
fclose(file);
WFREE(buf, heap, DYNTYPE_SSHD);
return NULL;
}
*bufSz = readSz;
fclose(file);
}
(void)heap;
return buf;
}
#endif /* NO_FILESYSTEM */
/* Initializes and sets up the WOLFSSH_CTX struct based on the configure options
* return WS_SUCCESS on success
@ -198,6 +239,7 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
DerBuffer* der = NULL;
byte* privBuf;
word32 privBufSz;
void* heap = NULL;
/* create a new WOLFSSH_CTX */
*ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL);
@ -230,23 +272,18 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
ret = WS_BAD_ARGUMENT;
}
else {
FILE* f;
byte* data;
word32 dataSz = 0;
f = XFOPEN(hostKey, "rb");
if (f == NULL) {
data = getBufferFromFile(hostKey, &dataSz, heap);
if (data == NULL) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Unable to open host private key");
ret = WS_BAD_ARGUMENT;
"[SSHD] Error reading host key file.");
ret = WS_MEMORY_E;
}
else {
byte* data;
int dataSz = 4096;
data = (byte*)WMALLOC(dataSz, NULL, 0);
dataSz = (int)XFREAD(data, 1, dataSz, f);
XFCLOSE(f);
if (ret == WS_SUCCESS) {
if (wc_PemToDer(data, dataSz, PRIVATEKEY_TYPE, &der, NULL,
NULL, NULL) != 0) {
wolfSSH_Log(WS_LOG_DEBUG, "[SSHD] Failed to convert host "
@ -267,49 +304,106 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
ret = WS_BAD_ARGUMENT;
}
WFREE(data, NULL, 0);
freeBufferFromFile(data, heap);
wc_FreeDer(&der);
}
}
}
#ifdef WOLFSSH_OSSH_CERTS
#if defined(WOLFSSH_OSSH_CERTS) || defined(WOLFSSH_CERTS)
if (ret == WS_SUCCESS) {
/* TODO: Create a helper function that uses a file instead. */
char* hostCert = wolfSSHD_ConfigGetHostCertFile(conf);
if (hostCert != NULL) {
FILE* f;
byte* data;
word32 dataSz = 0;
f = XFOPEN(hostCert, "rb");
if (f == NULL) {
data = getBufferFromFile(hostCert, &dataSz, heap);
if (data == NULL) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Unable to open host certificate.");
ret = WS_BAD_ARGUMENT;
"[SSHD] Error reading host key file.");
ret = WS_MEMORY_E;
}
else {
byte* data;
int dataSz = 4096;
data = (byte*)WMALLOC(dataSz, NULL, 0);
dataSz = (int)XFREAD(data, 1, dataSz, f);
XFCLOSE(f);
if (ret == WS_SUCCESS) {
#ifdef WOLFSSH_OPENSSH_CERTS
if (wolfSSH_CTX_UseOsshCert_buffer(*ctx, data, dataSz) < 0) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Failed to use host certificate.");
ret = WS_BAD_ARGUMENT;
}
#endif
#ifdef WOLFSSH_CERTS
if (ret == WS_SUCCESS || ret == WS_BAD_ARGUMENT) {
ret = wolfSSH_CTX_UseCert_buffer(*ctx, data, dataSz,
WOLFSSH_FORMAT_PEM);
if (ret != WS_SUCCESS) {
ret = wolfSSH_CTX_UseCert_buffer(*ctx, data, dataSz,
WOLFSSH_FORMAT_ASN1);
}
if (ret != WS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Failed to load in host certificate.");
}
}
#endif
WFREE(data, NULL, 0);
freeBufferFromFile(data, heap);
}
}
}
#endif /* WOLFSSH_OSSH_CERTS */
#endif /* WOLFSSH_OSSH_CERTS || WOLFSSH_CERTS */
#ifdef WOLFSSH_CERTS
if (ret == WS_SUCCESS) {
char* caCert = wolfSSHD_ConfigGetUserCAKeysFile(conf);
if (caCert != NULL) {
byte* data;
word32 dataSz = 0;
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Using CA keys file %s", caCert);
data = getBufferFromFile(caCert, &dataSz, heap);
if (data == NULL) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Error reading CA cert file.");
ret = WS_MEMORY_E;
}
if (ret == WS_SUCCESS) {
ret = wolfSSH_CTX_AddRootCert_buffer(*ctx, data, dataSz,
WOLFSSH_FORMAT_PEM);
if (ret != WS_SUCCESS) {
ret = wolfSSH_CTX_AddRootCert_buffer(*ctx, data, dataSz,
WOLFSSH_FORMAT_ASN1);
}
if (ret != WS_SUCCESS) {
#ifdef WOLFSSH_OPENSSH_CERTS
wolfSSH_Log(WS_LOG_INFO,
"[SSHD] Continuing on in case CA is openssh "
"style.");
ret = WS_SUCCESS;
#else
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Failed to load in CA certificate.");
#endif
}
freeBufferFromFile(data, heap);
}
}
}
#endif
wolfSSH_SetUserAuthTypes(*ctx, DefaultUserAuthTypes);
/* @TODO Load in host public key */
/* Set allowed connection type, i.e. public key / password */
(void)heap;
return ret;
}

View File

@ -184,6 +184,7 @@ static void ShowUsage(void)
printf(" -J <filename> filename for DER certificate to use\n");
printf(" Certificate example : client -u orange \\\n");
printf(" -J orange-cert.der -i orange-key.der\n");
printf(" -A <filename> filename for DER CA certificate to verify host\n");
#endif
}
@ -194,6 +195,7 @@ static byte* userPublicKey = userPublicKeyBuf;
static const byte* userPublicKeyType = NULL;
static const char* pubKeyName = NULL;
static const char* certName = NULL;
static const char* caCert = NULL;
static byte userPrivateKeyBuf[1191]; /* Size equal to hanselPrivateRsaSz. */
static byte* userPrivateKey = userPrivateKeyBuf;
static const byte* userPrivateKeyType = NULL;
@ -912,7 +914,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
char** argv = ((func_args*)args)->argv;
((func_args*)args)->return_code = 0;
while ((ch = mygetopt(argc, argv, "?ac:eh:i:j:p:tu:xzNP:RJ:")) != -1) {
while ((ch = mygetopt(argc, argv, "?ac:eh:i:j:p:tu:xzNP:RJ:A:")) != -1) {
switch (ch) {
case 'h':
host = myoptarg;
@ -957,6 +959,11 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
case 'J':
certName = myoptarg;
break;
case 'A':
caCert = myoptarg;
break;
#endif
case 'x':
@ -1134,6 +1141,24 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
wolfSSH_set_agent_cb_ctx(ssh, &agentCbCtx);
}
#endif
#ifdef WOLFSSH_CERTS
/* CA certificate to verify host cert with */
if (caCert) {
byte* der = NULL;
word32 derSz;
ret = load_der_file(caCert, &der, &derSz);
if (ret != 0) err_sys("Couldn't load CA certificate file.");
if (wolfSSH_CTX_AddRootCert_buffer(ctx, der, derSz,
WOLFSSH_FORMAT_ASN1) != WS_SUCCESS) {
err_sys("Couldn't parse in CA certificate.");
}
WFREE(der, NULL, 0);
}
#else
(void)caCert;
#endif /* WOLFSSH_CERTS */
wolfSSH_CTX_SetPublicKeyCheck(ctx, wsPublicKeyCheck);
wolfSSH_SetPublicKeyCheckCtx(ssh, (void*)"You've been sampled!");

File diff suppressed because it is too large Load Diff

View File

@ -1259,6 +1259,14 @@ void wolfSSH_SetUserAuth(WOLFSSH_CTX* ctx, WS_CallbackUserAuth cb)
}
void wolfSSH_SetUserAuthTypes(WOLFSSH_CTX* ctx, WS_CallbackUserAuthTypes cb)
{
if (ctx != NULL) {
ctx->userAuthTypesCb = cb;
}
}
void wolfSSH_SetUserAuthCtx(WOLFSSH* ssh, void* userAuthCtx)
{
if (ssh != NULL) {

View File

@ -408,6 +408,7 @@ struct WOLFSSH_CTX {
WS_CallbackIORecv ioRecvCb; /* I/O Receive Callback */
WS_CallbackIOSend ioSendCb; /* I/O Send Callback */
WS_CallbackUserAuth userAuthCb; /* User Authentication Callback */
WS_CallbackUserAuthTypes userAuthTypesCb; /* Authentication Types Allowed */
WS_CallbackUserAuthResult userAuthResultCb; /* User Authentication Result */
WS_CallbackHighwater highwaterCb; /* Data Highwater Mark Callback */
WS_CallbackGlobalReq globalReqCb; /* Global Request Callback */

View File

@ -210,6 +210,9 @@ typedef struct WS_UserAuthData {
typedef int (*WS_CallbackUserAuth)(byte, WS_UserAuthData*, void*);
WOLFSSH_API void wolfSSH_SetUserAuth(WOLFSSH_CTX*, WS_CallbackUserAuth);
typedef int (*WS_CallbackUserAuthTypes)(WOLFSSH* ssh, void* ctx);
WOLFSSH_API void wolfSSH_SetUserAuthTypes(WOLFSSH_CTX*,
WS_CallbackUserAuthTypes);
WOLFSSH_API void wolfSSH_SetUserAuthCtx(WOLFSSH*, void*);
WOLFSSH_API void* wolfSSH_GetUserAuthCtx(WOLFSSH*);