initial openssh-style certificate parsing

pull/453/head
Hayden Roche 2022-08-22 14:59:32 -07:00 committed by JacobBarthelmeh
parent 543e5c89e3
commit 7c486e518a
5 changed files with 313 additions and 127 deletions

View File

@ -61,9 +61,9 @@
#endif #endif
struct WOLFSSHD_AUTH { struct WOLFSSHD_AUTH {
CallbackCheckUser CheckUserCb; CallbackCheckUser checkUserCb;
CallbackCheckPassword CheckPasswordCb; CallbackCheckPassword checkPasswordCb;
CallbackCheckPublicKey CheckPublicKeyCb; CallbackCheckPublicKey checkPublicKeyCb;
const WOLFSSHD_CONFIG* conf; const WOLFSSHD_CONFIG* conf;
int gid; int gid;
int uid; int uid;
@ -75,7 +75,7 @@ struct WOLFSSHD_AUTH {
#define WOLFSSHD_MAX_PASSWORD_ATTEMPTS 3 #define WOLFSSHD_MAX_PASSWORD_ATTEMPTS 3
#endif #endif
#ifndef MAX_LEN_SZ #ifndef MAX_LINE_SZ
#define MAX_LINE_SZ 500 #define MAX_LINE_SZ 500
#endif #endif
#ifndef MAX_PATH_SZ #ifndef MAX_PATH_SZ
@ -132,6 +132,7 @@ enum {
WSSHD_AUTH_SUCCESS = 1 WSSHD_AUTH_SUCCESS = 1
}; };
/* TODO: Can use wolfSSH_ReadKey_buffer? */
static int CheckAuthKeysLine(char* line, word32 lineSz, const byte* key, static int CheckAuthKeysLine(char* line, word32 lineSz, const byte* key,
word32 keySz) word32 keySz)
{ {
@ -465,7 +466,9 @@ static int ResolveAuthKeysPath(const char* homeDir, char* resolved)
return ret; return ret;
} }
static int CheckPublicKeyUnix(const char* name, const byte* key, word32 keySz) static int CheckPublicKeyUnix(const char* name,
const WS_UserAuthData_PublicKey* pubKeyCtx,
const char* usrCaKeysFile)
{ {
int ret = WSSHD_AUTH_SUCCESS; int ret = WSSHD_AUTH_SUCCESS;
int rc; int rc;
@ -478,67 +481,132 @@ static int CheckPublicKeyUnix(const char* name, const byte* key, word32 keySz)
int foundKey = 0; int foundKey = 0;
char authKeysPath[MAX_PATH_SZ]; char authKeysPath[MAX_PATH_SZ];
errno = 0; #ifdef WOLFSSH_OSSH_CERTS
pwInfo = getpwnam((const char*)name); if (pubKeyCtx->isOsshCert) {
if (pwInfo == NULL) { byte* caKey = NULL;
if (errno != 0) { word32 caKeySz;
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error calling getpwnam for user " const byte* caKeyType = NULL;
"%s.", name); word32 caKeyTypeSz;
} byte fingerprint[WC_SHA256_DIGEST_SIZE];
ret = WS_FATAL_ERROR;
}
if (ret == WSSHD_AUTH_SUCCESS) { if (pubKeyCtx->caKey == NULL ||
WMEMSET(authKeysPath, 0, sizeof(authKeysPath)); pubKeyCtx->caKeySz != WC_SHA256_DIGEST_SIZE) {
rc = ResolveAuthKeysPath(pwInfo->pw_dir, authKeysPath); ret = WS_FATAL_ERROR;
if (rc != WS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failed to resolve authorized keys"
" file path.");
ret = rc;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
f = XFOPEN(authKeysPath, "rb");
if (f == XBADFILE) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Unable to open %s",
authKeysPath);
ret = WS_BAD_FILE_E;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
lineBuf = (char*)WMALLOC(MAX_LINE_SZ, NULL, DYNTYPE_BUFFER);
if (lineBuf == NULL) {
ret = WS_MEMORY_E;
}
}
while (ret == WSSHD_AUTH_SUCCESS &&
(current = XFGETS(lineBuf, MAX_LINE_SZ, f)) != NULL) {
currentSz = (word32)XSTRLEN(current);
/* remove leading spaces */
while (currentSz > 0 && current[0] == ' ') {
currentSz = currentSz - 1;
current = current + 1;
} }
if (currentSz <= 1) { if (ret == WSSHD_AUTH_SUCCESS) {
continue; /* empty line */ f = XFOPEN(usrCaKeysFile, "rb");
if (f == XBADFILE) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Unable to open %s",
usrCaKeysFile);
ret = WS_BAD_FILE_E;
}
} }
if (ret == WSSHD_AUTH_SUCCESS) {
lineBuf = (char*)WMALLOC(MAX_LINE_SZ, NULL, DYNTYPE_BUFFER);
if (lineBuf == NULL) {
ret = WS_MEMORY_E;
}
}
while (ret == WSSHD_AUTH_SUCCESS &&
(current = XFGETS(lineBuf, MAX_LINE_SZ, f)) != NULL) {
currentSz = (word32)XSTRLEN(current);
if (current[0] == '#') { /* remove leading spaces */
continue; /* commented out line */ while (currentSz > 0 && current[0] == ' ') {
} currentSz = currentSz - 1;
current = current + 1;
}
rc = CheckAuthKeysLine(current, currentSz, key, keySz); if (currentSz <= 1) {
if (rc == WSSHD_AUTH_SUCCESS) { continue; /* empty line */
foundKey = 1; }
break;
} if (current[0] == '#') {
else if (rc < 0) { continue; /* commented out line */
ret = rc; }
break;
rc = wolfSSH_ReadKey_buffer((const byte*)current, currentSz,
WOLFSSH_FORMAT_SSH, &caKey, &caKeySz,
&caKeyType, &caKeyTypeSz, NULL);
if (rc == WS_SUCCESS) {
rc = wc_Hash(WC_HASH_TYPE_SHA256, caKey, caKeySz, fingerprint,
WC_SHA256_DIGEST_SIZE);
if (rc == 0 && WMEMCMP(fingerprint, pubKeyCtx->caKey,
WC_SHA256_DIGEST_SIZE) == 0) {
foundKey = 1;
break;
}
}
} }
} }
else
#endif /* WOLFSSH_OSSH_CERTS */
{
errno = 0;
pwInfo = getpwnam((const char*)name);
if (pwInfo == NULL) {
if (errno != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error calling getpwnam for user "
"%s.", name);
}
ret = WS_FATAL_ERROR;
}
if (ret == WSSHD_AUTH_SUCCESS) {
WMEMSET(authKeysPath, 0, sizeof(authKeysPath));
rc = ResolveAuthKeysPath(pwInfo->pw_dir, authKeysPath);
if (rc != WS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failed to resolve authorized keys"
" file path.");
ret = rc;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
f = XFOPEN(authKeysPath, "rb");
if (f == XBADFILE) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Unable to open %s",
authKeysPath);
ret = WS_BAD_FILE_E;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
lineBuf = (char*)WMALLOC(MAX_LINE_SZ, NULL, DYNTYPE_BUFFER);
if (lineBuf == NULL) {
ret = WS_MEMORY_E;
}
}
while (ret == WSSHD_AUTH_SUCCESS &&
(current = XFGETS(lineBuf, MAX_LINE_SZ, f)) != NULL) {
currentSz = (word32)XSTRLEN(current);
/* remove leading spaces */
while (currentSz > 0 && current[0] == ' ') {
currentSz = currentSz - 1;
current = current + 1;
}
if (currentSz <= 1) {
continue; /* empty line */
}
if (current[0] == '#') {
continue; /* commented out line */
}
rc = CheckAuthKeysLine(current, currentSz, pubKeyCtx->publicKey,
pubKeyCtx->publicKeySz);
if (rc == WSSHD_AUTH_SUCCESS) {
foundKey = 1;
break;
}
else if (rc < 0) {
ret = rc;
break;
}
}
}
if (f != XBADFILE) { if (f != XBADFILE) {
XFCLOSE(f); XFCLOSE(f);
} }
@ -554,6 +622,7 @@ static int CheckPublicKeyUnix(const char* name, const byte* key, word32 keySz)
WFREE(authKeysFile, NULL, DYNTYPE_STRING); WFREE(authKeysFile, NULL, DYNTYPE_STRING);
} }
(void)usrCaKeysFile;
return ret; return ret;
} }
#endif /* !_WIN32*/ #endif /* !_WIN32*/
@ -562,71 +631,80 @@ static int CheckPublicKeyUnix(const char* name, const byte* key, word32 keySz)
/* return WOLFSSH_USERAUTH_SUCCESS on success */ /* return WOLFSSH_USERAUTH_SUCCESS on success */
static int DoCheckUser(const char* usr, WOLFSSHD_AUTH* auth) static int DoCheckUser(const char* usr, WOLFSSHD_AUTH* auth)
{ {
int ret = WOLFSSH_USERAUTH_FAILURE; int ret = WOLFSSH_USERAUTH_SUCCESS;
int rc; int rc;
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Checking user name %s", usr); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Checking user name %s", usr);
rc = auth->CheckUserCb(usr);
if (rc == WSSHD_AUTH_SUCCESS) { if (wolfSSHD_ConfigGetPermitRoot(auth->conf) == 0) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] User ok."); if (XSTRCMP(usr, "root") == 0) {
ret = WOLFSSH_USERAUTH_SUCCESS; wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Login as root not permited");
ret = WOLFSSH_USERAUTH_FAILURE;
}
} }
else if (ret == WSSHD_AUTH_FAILURE) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] User %s doesn't exist.", usr); if (ret == WOLFSSH_USERAUTH_SUCCESS) {
ret = WOLFSSH_USERAUTH_INVALID_USER; rc = auth->checkUserCb(usr);
} if (rc == WSSHD_AUTH_SUCCESS) {
else { wolfSSH_Log(WS_LOG_INFO, "[SSHD] User ok.");
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error looking up user %s.", usr); ret = WOLFSSH_USERAUTH_SUCCESS;
ret = WOLFSSH_USERAUTH_FAILURE; }
else if (ret == WSSHD_AUTH_FAILURE) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] User %s doesn't exist.", usr);
ret = WOLFSSH_USERAUTH_INVALID_USER;
}
else {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error looking up user %s.", usr);
ret = WOLFSSH_USERAUTH_FAILURE;
}
} }
return ret; return ret;
} }
/* @TODO this will take in a pipe or equivalent to talk to a privileged thread /* @TODO this will take in a pipe or equivalent to talk to a privileged thread
* rathar than having WOLFSSHD_AUTH directly with privilege separation */ * rathar than having WOLFSSHD_AUTH directly with privilege separation */
static int RequestAuthentication(const char* usr, int type, const byte* data, static int RequestAuthentication(WS_UserAuthData* authData,
int dataSz, WOLFSSHD_AUTH* auth) WOLFSSHD_AUTH* authCtx)
{ {
int ret; int ret;
int rc;
const char* usr;
if (auth == NULL) if (authData == NULL || authCtx == NULL) {
return WOLFSSH_USERAUTH_FAILURE; return WOLFSSH_USERAUTH_FAILURE;
if (wolfSSHD_ConfigGetPermitRoot(auth->conf) == 0) {
if (XSTRCMP(usr, "root") == 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Login as root not permited");
return WOLFSSH_USERAUTH_FAILURE;
}
} }
ret = DoCheckUser(usr, auth); usr = (const char*)authData->username;
ret = DoCheckUser(usr, authCtx);
/* temporarily elevate permissions */ /* temporarily elevate permissions */
if (ret == WOLFSSH_USERAUTH_SUCCESS && if (ret == WOLFSSH_USERAUTH_SUCCESS &&
wolfSSHD_AuthRaisePermissions(auth) != WS_SUCCESS) { wolfSSHD_AuthRaisePermissions(authCtx) != WS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR, wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Failure to raise permissions for auth"); "[SSHD] Failure to raise permissions for auth");
ret = WOLFSSH_USERAUTH_FAILURE; ret = WOLFSSH_USERAUTH_FAILURE;
} }
if (ret == WOLFSSH_USERAUTH_SUCCESS && type == WOLFSSH_USERAUTH_PASSWORD) { if (ret == WOLFSSH_USERAUTH_SUCCESS &&
int rc; authData->type == WOLFSSH_USERAUTH_PASSWORD) {
if (wolfSSHD_ConfigGetPwAuth(auth->conf) != 1) { if (wolfSSHD_ConfigGetPwAuth(authCtx->conf) != 1) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Password authentication not " wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Password authentication not "
"allowed by configuration!"); "allowed by configuration!");
ret = WOLFSSH_USERAUTH_FAILURE; ret = WOLFSSH_USERAUTH_FAILURE;
} }
/* Check if password is valid for this user. */ /* Check if password is valid for this user. */
/* first handle empty password cases */ /* first handle empty password cases */
else if (dataSz == 0 && wolfSSHD_ConfigGetPermitEmptyPw(auth->conf) else if (authData->sf.password.passwordSz == 0 &&
!= 1) { wolfSSHD_ConfigGetPermitEmptyPw(authCtx->conf) != 1) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Empty passwords not allowed by " wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Empty passwords not allowed by "
"configuration!"); "configuration!");
ret = WOLFSSH_USERAUTH_FAILURE; ret = WOLFSSH_USERAUTH_FAILURE;
} }
else { else {
rc = auth->CheckPasswordCb(usr, data, dataSz); rc = authCtx->checkPasswordCb(usr, authData->sf.password.password,
authData->sf.password.passwordSz);
if (rc == WSSHD_AUTH_SUCCESS) { if (rc == WSSHD_AUTH_SUCCESS) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Password ok."); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Password ok.");
} }
@ -634,8 +712,8 @@ static int RequestAuthentication(const char* usr, int type, const byte* data,
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Password incorrect."); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Password incorrect.");
ret = WOLFSSH_USERAUTH_INVALID_PASSWORD; ret = WOLFSSH_USERAUTH_INVALID_PASSWORD;
auth->attempts--; authCtx->attempts--;
if (auth->attempts == 0) { if (authCtx->attempts == 0) {
wolfSSH_Log(WS_LOG_ERROR, wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Too many bad password attempts!"); "[SSHD] Too many bad password attempts!");
ret = WOLFSSH_USERAUTH_REJECTED; ret = WOLFSSH_USERAUTH_REJECTED;
@ -649,10 +727,11 @@ static int RequestAuthentication(const char* usr, int type, const byte* data,
} }
if (ret == WOLFSSH_USERAUTH_SUCCESS && type == WOLFSSH_USERAUTH_PUBLICKEY) { if (ret == WOLFSSH_USERAUTH_SUCCESS &&
int rc; authData->type == WOLFSSH_USERAUTH_PUBLICKEY) {
rc = auth->CheckPublicKeyCb(usr, data, dataSz); rc = authCtx->checkPublicKeyCb(usr, &authData->sf.publicKey,
wolfSSHD_ConfigGetUserCAKeysFile(authCtx->conf));
if (rc == WSSHD_AUTH_SUCCESS) { if (rc == WSSHD_AUTH_SUCCESS) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key ok."); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key ok.");
ret = WOLFSSH_USERAUTH_SUCCESS; ret = WOLFSSH_USERAUTH_SUCCESS;
@ -668,10 +747,11 @@ static int RequestAuthentication(const char* usr, int type, const byte* data,
} }
if (wolfSSHD_AuthReducePermissions(auth) != WS_SUCCESS) { if (wolfSSHD_AuthReducePermissions(authCtx) != WS_SUCCESS) {
/* stop everything if not able to reduce permissions level */ /* stop everything if not able to reduce permissions level */
exit(1); exit(1);
} }
return ret; return ret;
} }
@ -680,15 +760,15 @@ static int RequestAuthentication(const char* usr, int type, const byte* data,
int DefaultUserAuth(byte authType, WS_UserAuthData* authData, void* ctx) int DefaultUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
{ {
int ret = WOLFSSH_USERAUTH_SUCCESS; int ret = WOLFSSH_USERAUTH_SUCCESS;
WOLFSSHD_AUTH* auth; WOLFSSHD_AUTH* authCtx;
if (ctx == NULL) { if (ctx == NULL) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] No auth callbacks passed in"); wolfSSH_Log(WS_LOG_ERROR, "[SSHD] No auth callbacks passed in");
return WOLFSSH_USERAUTH_FAILURE; return WOLFSSH_USERAUTH_FAILURE;
} }
else { else {
auth = (WOLFSSHD_AUTH*)ctx; authCtx = (WOLFSSHD_AUTH*)ctx;
if (auth->CheckUserCb == NULL) { if (authCtx->checkUserCb == NULL) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] No way to check the user is set"); wolfSSH_Log(WS_LOG_ERROR, "[SSHD] No way to check the user is set");
return WOLFSSH_USERAUTH_FAILURE; return WOLFSSH_USERAUTH_FAILURE;
} }
@ -708,22 +788,9 @@ int DefaultUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
ret = WOLFSSH_USERAUTH_INVALID_AUTHTYPE; ret = WOLFSSH_USERAUTH_INVALID_AUTHTYPE;
} }
/* call to possibly privilaged authentecator for password check */ /* call to possibly privileged authenticator for password check */
if (ret == WOLFSSH_USERAUTH_SUCCESS && if (ret == WOLFSSH_USERAUTH_SUCCESS) {
authData->type == WOLFSSH_USERAUTH_PASSWORD) { ret = RequestAuthentication(authData, authCtx);
ret = RequestAuthentication((const char*)authData->username,
authData->type,
authData->sf.password.password,
authData->sf.password.passwordSz, auth);
}
/* call to possibly privilaged authentecator for public key check */
if (ret == WOLFSSH_USERAUTH_SUCCESS &&
authData->type == WOLFSSH_USERAUTH_PUBLICKEY) {
ret = RequestAuthentication((const char*)authData->username,
authData->type,
authData->sf.publicKey.publicKey,
authData->sf.publicKey.publicKeySz, auth);
} }
return ret; return ret;
@ -738,7 +805,7 @@ static int SetDefaultUserCheck(WOLFSSHD_AUTH* auth)
/* TODO: Implement for Windows. */ /* TODO: Implement for Windows. */
#else #else
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting default Unix user name check"); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting default Unix user name check");
auth->CheckUserCb = CheckUserUnix; auth->checkUserCb = CheckUserUnix;
ret = WS_SUCCESS; ret = WS_SUCCESS;
#endif #endif
@ -754,11 +821,11 @@ static int SetDefaultPasswordCheck(WOLFSSHD_AUTH* auth)
/* TODO: Add CheckPasswordWin. */ /* TODO: Add CheckPasswordWin. */
#elif defined(WOLFSSH_USE_PAM) #elif defined(WOLFSSH_USE_PAM)
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting PAM password check"); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting PAM password check");
auth->CheckPasswordCb = CheckPasswordPAM; auth->checkPasswordCb = CheckPasswordPAM;
ret = WS_SUCCESS; ret = WS_SUCCESS;
#else #else
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting Unix password check"); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting Unix password check");
auth->CheckPasswordCb = CheckPasswordUnix; auth->checkPasswordCb = CheckPasswordUnix;
ret = WS_SUCCESS; ret = WS_SUCCESS;
#endif #endif
return ret; return ret;
@ -773,7 +840,7 @@ static int SetDefaultPublicKeyCheck(WOLFSSHD_AUTH* auth)
/* TODO: Implement for Windows. */ /* TODO: Implement for Windows. */
#else #else
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting Unix public key check"); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting Unix public key check");
auth->CheckPublicKeyCb = CheckPublicKeyUnix; auth->checkPublicKeyCb = CheckPublicKeyUnix;
ret = WS_SUCCESS; ret = WS_SUCCESS;
#endif #endif
return ret; return ret;

View File

@ -51,8 +51,9 @@ typedef int (*CallbackCheckPassword)(const char* usr, const byte* psw,
* Returns WSSHD_AUTH_SUCCESS if public key ok, WSSHD_AUTH_FAILURE if key not * Returns WSSHD_AUTH_SUCCESS if public key ok, WSSHD_AUTH_FAILURE if key not
* ok, and negative values if an error occurs during checking. * ok, and negative values if an error occurs during checking.
*/ */
typedef int (*CallbackCheckPublicKey)(const char* usr, const byte* key, typedef int (*CallbackCheckPublicKey)(const char* usr,
word32 keySz); const WS_UserAuthData_PublicKey* pubKey,
const char* usrCaKeysFile);
WOLFSSHD_AUTH* wolfSSHD_AuthCreateUser(void* heap, const WOLFSSHD_CONFIG* conf); WOLFSSHD_AUTH* wolfSSHD_AuthCreateUser(void* heap, const WOLFSSHD_CONFIG* conf);
int wolfSSHD_AuthFreeUser(WOLFSSHD_AUTH* auth); int wolfSSHD_AuthFreeUser(WOLFSSHD_AUTH* auth);

View File

@ -57,6 +57,8 @@ struct WOLFSSHD_CONFIG {
char* chrootDir; char* chrootDir;
char* ciphers; char* ciphers;
char* hostKeyFile; char* hostKeyFile;
char* hostCertFile;
char* userCAKeysFile;
char* hostKeyAlgos; char* hostKeyAlgos;
char* kekAlgos; char* kekAlgos;
char* listenAddress; char* listenAddress;
@ -290,6 +292,7 @@ void wolfSSHD_ConfigFree(WOLFSSHD_CONFIG* conf)
FreeString(&current->listenAddress, heap); FreeString(&current->listenAddress, heap);
FreeString(&current->authKeysFile, heap); FreeString(&current->authKeysFile, heap);
FreeString(&current->hostKeyFile, heap); FreeString(&current->hostKeyFile, heap);
FreeString(&current->hostCertFile, heap);
WFREE(current, heap, DYNTYPE_SSHD); WFREE(current, heap, DYNTYPE_SSHD);
current = next; current = next;
@ -324,9 +327,11 @@ enum {
OPT_CHROOT_DIR = 17, OPT_CHROOT_DIR = 17,
OPT_MATCH = 18, OPT_MATCH = 18,
OPT_FORCE_CMD = 19, OPT_FORCE_CMD = 19,
OPT_HOST_CERT = 20,
OPT_TRUSTED_USER_CA_KEYS = 21,
}; };
enum { enum {
NUM_OPTIONS = 20 NUM_OPTIONS = 22
}; };
static const CONFIG_OPTION options[NUM_OPTIONS] = { static const CONFIG_OPTION options[NUM_OPTIONS] = {
@ -350,6 +355,8 @@ static const CONFIG_OPTION options[NUM_OPTIONS] = {
{OPT_CHROOT_DIR, "ChrootDirectory"}, {OPT_CHROOT_DIR, "ChrootDirectory"},
{OPT_MATCH, "Match"}, {OPT_MATCH, "Match"},
{OPT_FORCE_CMD, "ForceCommand"}, {OPT_FORCE_CMD, "ForceCommand"},
{OPT_HOST_CERT, "HostCertificate"},
{OPT_TRUSTED_USER_CA_KEYS, "TrustedUserCAKeys"},
}; };
/* returns WS_SUCCESS on success */ /* returns WS_SUCCESS on success */
@ -955,6 +962,10 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
/* TODO: Add logic to check if file exists? */ /* TODO: Add logic to check if file exists? */
ret = wolfSSHD_ConfigSetHostKeyFile(*conf, value); ret = wolfSSHD_ConfigSetHostKeyFile(*conf, value);
break; break;
case OPT_HOST_CERT:
/* TODO: Add logic to check if file exists? */
ret = wolfSSHD_ConfigSetHostCertFile(*conf, value);
break;
case OPT_PASSWORD_AUTH: case OPT_PASSWORD_AUTH:
ret = HandlePwAuth(*conf, value); ret = HandlePwAuth(*conf, value);
break; break;
@ -981,6 +992,10 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
case OPT_FORCE_CMD: case OPT_FORCE_CMD:
ret = HandleForcedCommand(*conf, full, fullSz); ret = HandleForcedCommand(*conf, full, fullSz);
break; break;
case OPT_TRUSTED_USER_CA_KEYS:
/* TODO: Add logic to check if file exists? */
ret = wolfSSHD_ConfigSetUserCAKeysFile(*conf, value);
break;
default: default:
break; break;
} }
@ -1234,6 +1249,50 @@ char* wolfSSHD_ConfigGetHostKeyFile(const WOLFSSHD_CONFIG* conf)
return ret; return ret;
} }
char* wolfSSHD_ConfigGetHostCertFile(const WOLFSSHD_CONFIG* conf)
{
char* ret = NULL;
if (conf != NULL) {
ret = conf->hostCertFile;
}
return ret;
}
char* wolfSSHD_ConfigGetUserCAKeysFile(const WOLFSSHD_CONFIG* conf)
{
char* ret = NULL;
if (conf != NULL) {
ret = conf->userCAKeysFile;
}
return ret;
}
static int SetFileString(char** dst, const char* src, void* heap)
{
int ret = WS_SUCCESS;
if (dst == NULL) {
ret = WS_BAD_ARGUMENT;
}
if (ret == WS_SUCCESS) {
if (*dst != NULL) {
FreeString(dst, heap);
*dst = NULL;
}
if (src != NULL) {
ret = CreateString(dst, src, (int)WSTRLEN(src), heap);
}
}
return ret;
}
int wolfSSHD_ConfigSetHostKeyFile(WOLFSSHD_CONFIG* conf, const char* file) int wolfSSHD_ConfigSetHostKeyFile(WOLFSSHD_CONFIG* conf, const char* file)
{ {
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
@ -1243,15 +1302,37 @@ int wolfSSHD_ConfigSetHostKeyFile(WOLFSSHD_CONFIG* conf, const char* file)
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
if (conf->hostKeyFile != NULL) { ret = SetFileString(&conf->hostKeyFile, file, conf->heap);
FreeString(&conf->hostKeyFile, conf->heap); }
conf->hostKeyFile = NULL;
}
if (file != NULL) { return ret;
ret = CreateString(&conf->hostKeyFile, file, }
(int)WSTRLEN(file), conf->heap);
} int wolfSSHD_ConfigSetHostCertFile(WOLFSSHD_CONFIG* conf, const char* file)
{
int ret = WS_SUCCESS;
if (conf == NULL) {
ret = WS_BAD_ARGUMENT;
}
if (ret == WS_SUCCESS) {
ret = SetFileString(&conf->hostCertFile, file, conf->heap);
}
return ret;
}
int wolfSSHD_ConfigSetUserCAKeysFile(WOLFSSHD_CONFIG* conf, const char* file)
{
int ret = WS_SUCCESS;
if (conf == NULL) {
ret = WS_BAD_ARGUMENT;
}
if (ret == WS_SUCCESS) {
ret = SetFileString(&conf->userCAKeysFile, file, conf->heap);
} }
return ret; return ret;

View File

@ -38,7 +38,11 @@ char* wolfSSHD_ConfigGetForcedCmd(const WOLFSSHD_CONFIG* conf);
char* wolfSSHD_ConfigGetBanner(const WOLFSSHD_CONFIG* conf); char* wolfSSHD_ConfigGetBanner(const WOLFSSHD_CONFIG* conf);
char* wolfSSHD_ConfigGetChroot(const WOLFSSHD_CONFIG* conf); char* wolfSSHD_ConfigGetChroot(const WOLFSSHD_CONFIG* conf);
char* wolfSSHD_ConfigGetHostKeyFile(const WOLFSSHD_CONFIG* conf); char* wolfSSHD_ConfigGetHostKeyFile(const WOLFSSHD_CONFIG* conf);
char* wolfSSHD_ConfigGetHostCertFile(const WOLFSSHD_CONFIG* conf);
char* wolfSSHD_ConfigGetUserCAKeysFile(const WOLFSSHD_CONFIG* conf);
int wolfSSHD_ConfigSetHostKeyFile(WOLFSSHD_CONFIG* conf, const char* file); int wolfSSHD_ConfigSetHostKeyFile(WOLFSSHD_CONFIG* conf, const char* file);
int wolfSSHD_ConfigSetHostCertFile(WOLFSSHD_CONFIG* conf, const char* file);
int wolfSSHD_ConfigSetUserCAKeysFile(WOLFSSHD_CONFIG* conf, const char* file);
word16 wolfSSHD_ConfigGetPort(const WOLFSSHD_CONFIG* conf); word16 wolfSSHD_ConfigGetPort(const WOLFSSHD_CONFIG* conf);
char* wolfSSHD_ConfigGetAuthKeysFile(const WOLFSSHD_CONFIG* conf); char* wolfSSHD_ConfigGetAuthKeysFile(const WOLFSSHD_CONFIG* conf);
int wolfSSHD_ConfigSetAuthKeysFile(WOLFSSHD_CONFIG* conf, const char* file); int wolfSSHD_ConfigSetAuthKeysFile(WOLFSSHD_CONFIG* conf, const char* file);

View File

@ -272,7 +272,40 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
} }
} }
} }
#ifdef WOLFSSH_OSSH_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;
f = XFOPEN(hostCert, "rb");
if (f == NULL) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Unable to open host certificate.");
ret = WS_BAD_ARGUMENT;
}
else {
byte* data;
int dataSz = 4096;
data = (byte*)WMALLOC(dataSz, NULL, 0);
dataSz = (int)XFREAD(data, 1, dataSz, f);
XFCLOSE(f);
if (wolfSSH_CTX_UseOsshCert_buffer(*ctx, data, dataSz) < 0) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Failed to use host certificate.");
ret = WS_BAD_ARGUMENT;
}
WFREE(data, NULL, 0);
}
}
}
#endif /* WOLFSSH_OSSH_CERTS */
/* @TODO Load in host public key */ /* @TODO Load in host public key */
/* Set allowed connection type, i.e. public key / password */ /* Set allowed connection type, i.e. public key / password */