mirror of https://github.com/wolfSSL/wolfssh.git
initial openssh-style certificate parsing
parent
543e5c89e3
commit
7c486e518a
|
@ -61,9 +61,9 @@
|
|||
#endif
|
||||
|
||||
struct WOLFSSHD_AUTH {
|
||||
CallbackCheckUser CheckUserCb;
|
||||
CallbackCheckPassword CheckPasswordCb;
|
||||
CallbackCheckPublicKey CheckPublicKeyCb;
|
||||
CallbackCheckUser checkUserCb;
|
||||
CallbackCheckPassword checkPasswordCb;
|
||||
CallbackCheckPublicKey checkPublicKeyCb;
|
||||
const WOLFSSHD_CONFIG* conf;
|
||||
int gid;
|
||||
int uid;
|
||||
|
@ -75,7 +75,7 @@ struct WOLFSSHD_AUTH {
|
|||
#define WOLFSSHD_MAX_PASSWORD_ATTEMPTS 3
|
||||
#endif
|
||||
|
||||
#ifndef MAX_LEN_SZ
|
||||
#ifndef MAX_LINE_SZ
|
||||
#define MAX_LINE_SZ 500
|
||||
#endif
|
||||
#ifndef MAX_PATH_SZ
|
||||
|
@ -132,6 +132,7 @@ enum {
|
|||
WSSHD_AUTH_SUCCESS = 1
|
||||
};
|
||||
|
||||
/* TODO: Can use wolfSSH_ReadKey_buffer? */
|
||||
static int CheckAuthKeysLine(char* line, word32 lineSz, const byte* key,
|
||||
word32 keySz)
|
||||
{
|
||||
|
@ -465,7 +466,9 @@ static int ResolveAuthKeysPath(const char* homeDir, char* resolved)
|
|||
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 rc;
|
||||
|
@ -478,67 +481,132 @@ static int CheckPublicKeyUnix(const char* name, const byte* key, word32 keySz)
|
|||
int foundKey = 0;
|
||||
char authKeysPath[MAX_PATH_SZ];
|
||||
|
||||
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;
|
||||
}
|
||||
#ifdef WOLFSSH_OSSH_CERTS
|
||||
if (pubKeyCtx->isOsshCert) {
|
||||
byte* caKey = NULL;
|
||||
word32 caKeySz;
|
||||
const byte* caKeyType = NULL;
|
||||
word32 caKeyTypeSz;
|
||||
byte fingerprint[WC_SHA256_DIGEST_SIZE];
|
||||
|
||||
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 (pubKeyCtx->caKey == NULL ||
|
||||
pubKeyCtx->caKeySz != WC_SHA256_DIGEST_SIZE) {
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
if (currentSz <= 1) {
|
||||
continue; /* empty line */
|
||||
if (ret == WSSHD_AUTH_SUCCESS) {
|
||||
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] == '#') {
|
||||
continue; /* commented out line */
|
||||
}
|
||||
/* remove leading spaces */
|
||||
while (currentSz > 0 && current[0] == ' ') {
|
||||
currentSz = currentSz - 1;
|
||||
current = current + 1;
|
||||
}
|
||||
|
||||
rc = CheckAuthKeysLine(current, currentSz, key, keySz);
|
||||
if (rc == WSSHD_AUTH_SUCCESS) {
|
||||
foundKey = 1;
|
||||
break;
|
||||
}
|
||||
else if (rc < 0) {
|
||||
ret = rc;
|
||||
break;
|
||||
if (currentSz <= 1) {
|
||||
continue; /* empty line */
|
||||
}
|
||||
|
||||
if (current[0] == '#') {
|
||||
continue; /* commented out line */
|
||||
}
|
||||
|
||||
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) {
|
||||
XFCLOSE(f);
|
||||
}
|
||||
|
@ -554,6 +622,7 @@ static int CheckPublicKeyUnix(const char* name, const byte* key, word32 keySz)
|
|||
WFREE(authKeysFile, NULL, DYNTYPE_STRING);
|
||||
}
|
||||
|
||||
(void)usrCaKeysFile;
|
||||
return ret;
|
||||
}
|
||||
#endif /* !_WIN32*/
|
||||
|
@ -562,71 +631,80 @@ static int CheckPublicKeyUnix(const char* name, const byte* key, word32 keySz)
|
|||
/* return WOLFSSH_USERAUTH_SUCCESS on success */
|
||||
static int DoCheckUser(const char* usr, WOLFSSHD_AUTH* auth)
|
||||
{
|
||||
int ret = WOLFSSH_USERAUTH_FAILURE;
|
||||
int ret = WOLFSSH_USERAUTH_SUCCESS;
|
||||
int rc;
|
||||
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Checking user name %s", usr);
|
||||
rc = auth->CheckUserCb(usr);
|
||||
if (rc == WSSHD_AUTH_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] User ok.");
|
||||
ret = WOLFSSH_USERAUTH_SUCCESS;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
if (ret == WOLFSSH_USERAUTH_SUCCESS) {
|
||||
rc = auth->checkUserCb(usr);
|
||||
if (rc == WSSHD_AUTH_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] User ok.");
|
||||
ret = WOLFSSH_USERAUTH_SUCCESS;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* @TODO this will take in a pipe or equivalent to talk to a privileged thread
|
||||
* rathar than having WOLFSSHD_AUTH directly with privilege separation */
|
||||
static int RequestAuthentication(const char* usr, int type, const byte* data,
|
||||
int dataSz, WOLFSSHD_AUTH* auth)
|
||||
static int RequestAuthentication(WS_UserAuthData* authData,
|
||||
WOLFSSHD_AUTH* authCtx)
|
||||
{
|
||||
int ret;
|
||||
int rc;
|
||||
const char* usr;
|
||||
|
||||
if (auth == NULL)
|
||||
if (authData == NULL || authCtx == NULL) {
|
||||
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 */
|
||||
if (ret == WOLFSSH_USERAUTH_SUCCESS &&
|
||||
wolfSSHD_AuthRaisePermissions(auth) != WS_SUCCESS) {
|
||||
wolfSSHD_AuthRaisePermissions(authCtx) != WS_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Failure to raise permissions for auth");
|
||||
ret = WOLFSSH_USERAUTH_FAILURE;
|
||||
}
|
||||
|
||||
if (ret == WOLFSSH_USERAUTH_SUCCESS && type == WOLFSSH_USERAUTH_PASSWORD) {
|
||||
int rc;
|
||||
if (ret == WOLFSSH_USERAUTH_SUCCESS &&
|
||||
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 "
|
||||
"allowed by configuration!");
|
||||
ret = WOLFSSH_USERAUTH_FAILURE;
|
||||
}
|
||||
/* Check if password is valid for this user. */
|
||||
/* first handle empty password cases */
|
||||
else if (dataSz == 0 && wolfSSHD_ConfigGetPermitEmptyPw(auth->conf)
|
||||
!= 1) {
|
||||
else if (authData->sf.password.passwordSz == 0 &&
|
||||
wolfSSHD_ConfigGetPermitEmptyPw(authCtx->conf) != 1) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Empty passwords not allowed by "
|
||||
"configuration!");
|
||||
ret = WOLFSSH_USERAUTH_FAILURE;
|
||||
}
|
||||
else {
|
||||
rc = auth->CheckPasswordCb(usr, data, dataSz);
|
||||
rc = authCtx->checkPasswordCb(usr, authData->sf.password.password,
|
||||
authData->sf.password.passwordSz);
|
||||
if (rc == WSSHD_AUTH_SUCCESS) {
|
||||
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.");
|
||||
ret = WOLFSSH_USERAUTH_INVALID_PASSWORD;
|
||||
|
||||
auth->attempts--;
|
||||
if (auth->attempts == 0) {
|
||||
authCtx->attempts--;
|
||||
if (authCtx->attempts == 0) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Too many bad password attempts!");
|
||||
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) {
|
||||
int rc;
|
||||
if (ret == WOLFSSH_USERAUTH_SUCCESS &&
|
||||
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) {
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key ok.");
|
||||
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 */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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 ret = WOLFSSH_USERAUTH_SUCCESS;
|
||||
WOLFSSHD_AUTH* auth;
|
||||
WOLFSSHD_AUTH* authCtx;
|
||||
|
||||
if (ctx == NULL) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] No auth callbacks passed in");
|
||||
return WOLFSSH_USERAUTH_FAILURE;
|
||||
}
|
||||
else {
|
||||
auth = (WOLFSSHD_AUTH*)ctx;
|
||||
if (auth->CheckUserCb == NULL) {
|
||||
authCtx = (WOLFSSHD_AUTH*)ctx;
|
||||
if (authCtx->checkUserCb == NULL) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] No way to check the user is set");
|
||||
return WOLFSSH_USERAUTH_FAILURE;
|
||||
}
|
||||
|
@ -708,22 +788,9 @@ int DefaultUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
|
|||
ret = WOLFSSH_USERAUTH_INVALID_AUTHTYPE;
|
||||
}
|
||||
|
||||
/* call to possibly privilaged authentecator for password check */
|
||||
if (ret == WOLFSSH_USERAUTH_SUCCESS &&
|
||||
authData->type == WOLFSSH_USERAUTH_PASSWORD) {
|
||||
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);
|
||||
/* call to possibly privileged authenticator for password check */
|
||||
if (ret == WOLFSSH_USERAUTH_SUCCESS) {
|
||||
ret = RequestAuthentication(authData, authCtx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -738,7 +805,7 @@ static int SetDefaultUserCheck(WOLFSSHD_AUTH* auth)
|
|||
/* TODO: Implement for Windows. */
|
||||
#else
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting default Unix user name check");
|
||||
auth->CheckUserCb = CheckUserUnix;
|
||||
auth->checkUserCb = CheckUserUnix;
|
||||
ret = WS_SUCCESS;
|
||||
#endif
|
||||
|
||||
|
@ -754,11 +821,11 @@ static int SetDefaultPasswordCheck(WOLFSSHD_AUTH* auth)
|
|||
/* TODO: Add CheckPasswordWin. */
|
||||
#elif defined(WOLFSSH_USE_PAM)
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting PAM password check");
|
||||
auth->CheckPasswordCb = CheckPasswordPAM;
|
||||
auth->checkPasswordCb = CheckPasswordPAM;
|
||||
ret = WS_SUCCESS;
|
||||
#else
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting Unix password check");
|
||||
auth->CheckPasswordCb = CheckPasswordUnix;
|
||||
auth->checkPasswordCb = CheckPasswordUnix;
|
||||
ret = WS_SUCCESS;
|
||||
#endif
|
||||
return ret;
|
||||
|
@ -773,7 +840,7 @@ static int SetDefaultPublicKeyCheck(WOLFSSHD_AUTH* auth)
|
|||
/* TODO: Implement for Windows. */
|
||||
#else
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting Unix public key check");
|
||||
auth->CheckPublicKeyCb = CheckPublicKeyUnix;
|
||||
auth->checkPublicKeyCb = CheckPublicKeyUnix;
|
||||
ret = WS_SUCCESS;
|
||||
#endif
|
||||
return ret;
|
||||
|
|
|
@ -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
|
||||
* ok, and negative values if an error occurs during checking.
|
||||
*/
|
||||
typedef int (*CallbackCheckPublicKey)(const char* usr, const byte* key,
|
||||
word32 keySz);
|
||||
typedef int (*CallbackCheckPublicKey)(const char* usr,
|
||||
const WS_UserAuthData_PublicKey* pubKey,
|
||||
const char* usrCaKeysFile);
|
||||
|
||||
WOLFSSHD_AUTH* wolfSSHD_AuthCreateUser(void* heap, const WOLFSSHD_CONFIG* conf);
|
||||
int wolfSSHD_AuthFreeUser(WOLFSSHD_AUTH* auth);
|
||||
|
|
|
@ -57,6 +57,8 @@ struct WOLFSSHD_CONFIG {
|
|||
char* chrootDir;
|
||||
char* ciphers;
|
||||
char* hostKeyFile;
|
||||
char* hostCertFile;
|
||||
char* userCAKeysFile;
|
||||
char* hostKeyAlgos;
|
||||
char* kekAlgos;
|
||||
char* listenAddress;
|
||||
|
@ -290,6 +292,7 @@ void wolfSSHD_ConfigFree(WOLFSSHD_CONFIG* conf)
|
|||
FreeString(¤t->listenAddress, heap);
|
||||
FreeString(¤t->authKeysFile, heap);
|
||||
FreeString(¤t->hostKeyFile, heap);
|
||||
FreeString(¤t->hostCertFile, heap);
|
||||
|
||||
WFREE(current, heap, DYNTYPE_SSHD);
|
||||
current = next;
|
||||
|
@ -324,9 +327,11 @@ enum {
|
|||
OPT_CHROOT_DIR = 17,
|
||||
OPT_MATCH = 18,
|
||||
OPT_FORCE_CMD = 19,
|
||||
OPT_HOST_CERT = 20,
|
||||
OPT_TRUSTED_USER_CA_KEYS = 21,
|
||||
};
|
||||
enum {
|
||||
NUM_OPTIONS = 20
|
||||
NUM_OPTIONS = 22
|
||||
};
|
||||
|
||||
static const CONFIG_OPTION options[NUM_OPTIONS] = {
|
||||
|
@ -350,6 +355,8 @@ static const CONFIG_OPTION options[NUM_OPTIONS] = {
|
|||
{OPT_CHROOT_DIR, "ChrootDirectory"},
|
||||
{OPT_MATCH, "Match"},
|
||||
{OPT_FORCE_CMD, "ForceCommand"},
|
||||
{OPT_HOST_CERT, "HostCertificate"},
|
||||
{OPT_TRUSTED_USER_CA_KEYS, "TrustedUserCAKeys"},
|
||||
};
|
||||
|
||||
/* 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? */
|
||||
ret = wolfSSHD_ConfigSetHostKeyFile(*conf, value);
|
||||
break;
|
||||
case OPT_HOST_CERT:
|
||||
/* TODO: Add logic to check if file exists? */
|
||||
ret = wolfSSHD_ConfigSetHostCertFile(*conf, value);
|
||||
break;
|
||||
case OPT_PASSWORD_AUTH:
|
||||
ret = HandlePwAuth(*conf, value);
|
||||
break;
|
||||
|
@ -981,6 +992,10 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
|
|||
case OPT_FORCE_CMD:
|
||||
ret = HandleForcedCommand(*conf, full, fullSz);
|
||||
break;
|
||||
case OPT_TRUSTED_USER_CA_KEYS:
|
||||
/* TODO: Add logic to check if file exists? */
|
||||
ret = wolfSSHD_ConfigSetUserCAKeysFile(*conf, value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1234,6 +1249,50 @@ char* wolfSSHD_ConfigGetHostKeyFile(const WOLFSSHD_CONFIG* conf)
|
|||
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 ret = WS_SUCCESS;
|
||||
|
@ -1243,15 +1302,37 @@ int wolfSSHD_ConfigSetHostKeyFile(WOLFSSHD_CONFIG* conf, const char* file)
|
|||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
if (conf->hostKeyFile != NULL) {
|
||||
FreeString(&conf->hostKeyFile, conf->heap);
|
||||
conf->hostKeyFile = NULL;
|
||||
}
|
||||
ret = SetFileString(&conf->hostKeyFile, file, conf->heap);
|
||||
}
|
||||
|
||||
if (file != NULL) {
|
||||
ret = CreateString(&conf->hostKeyFile, file,
|
||||
(int)WSTRLEN(file), conf->heap);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -38,7 +38,11 @@ char* wolfSSHD_ConfigGetForcedCmd(const WOLFSSHD_CONFIG* conf);
|
|||
char* wolfSSHD_ConfigGetBanner(const WOLFSSHD_CONFIG* conf);
|
||||
char* wolfSSHD_ConfigGetChroot(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_ConfigSetHostCertFile(WOLFSSHD_CONFIG* conf, const char* file);
|
||||
int wolfSSHD_ConfigSetUserCAKeysFile(WOLFSSHD_CONFIG* conf, const char* file);
|
||||
word16 wolfSSHD_ConfigGetPort(const WOLFSSHD_CONFIG* conf);
|
||||
char* wolfSSHD_ConfigGetAuthKeysFile(const WOLFSSHD_CONFIG* conf);
|
||||
int wolfSSHD_ConfigSetAuthKeysFile(WOLFSSHD_CONFIG* conf, const char* 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 */
|
||||
|
||||
/* Set allowed connection type, i.e. public key / password */
|
||||
|
|
Loading…
Reference in New Issue