mirror of https://github.com/wolfSSL/wolfssh.git
add mutual X509 auth of host key and sshd_config parsing additions
parent
7c486e518a
commit
3e1a6ff342
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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!");
|
||||
|
|
1521
src/internal.c
1521
src/internal.c
File diff suppressed because it is too large
Load Diff
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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*);
|
||||
|
||||
|
|
Loading…
Reference in New Issue