add wolfauth file for peer auth

pull/435/head
Jacob Barthelmeh 2022-07-06 16:22:44 -06:00 committed by JacobBarthelmeh
parent 65dde05900
commit 475ee1f113
5 changed files with 394 additions and 54 deletions

View File

@ -3,9 +3,11 @@
if BUILD_SSHD
bin_PROGRAMS += apps/wolfsshd
noinst_HEADERS += apps/wolfsshd.h
noinst_HEADERS += apps/wolfsshd.h \
apps/wolfauth.h
apps_wolfsshd_SOURCES = apps/wolfsshd.c \
apps/wolfconfig.c
apps/wolfconfig.c \
apps/wolfauth.c
apps_wolfsshd_LDADD = src/libwolfssh.la
apps_wolfsshd_DEPENDENCIES = src/libwolfssh.la
endif

256
apps/wolfauth.c 100644
View File

@ -0,0 +1,256 @@
/* wolfauth.c
*
* Copyright (C) 2014-2021 wolfSSL Inc.
*
* This file is part of wolfSSH.
*
* wolfSSH is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSH is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef WOLFSSH_SSHD
#include <wolfssh/ssh.h>
#include <wolfssh/internal.h>
#include <wolfssh/log.h>
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#ifdef NO_INLINE
#include <wolfssh/misc.h>
#else
#define WOLFSSH_MISC_INCLUDED
#include "src/misc.c"
#endif
#include "wolfauth.h"
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <uuid/uuid.h>
static byte passwdRetry = 3;
/* Map user names to passwords */
/* 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. */
struct USER_NODE {
byte type;
byte username[32];
word32 usernameSz;
byte fingerprint[WC_SHA256_DIGEST_SIZE];
struct USER_NODE* next;
};
/* Takes a users input and adds it to the list of accepted users
* 'value' can be a users password / public key / or certificate
* returns an updated list on success (i.e. 'new' -> 'list' -> ...) or NULL
* on failure
*/
USER_NODE* AddNewUser(USER_NODE* list, byte type, const byte* username,
word32 usernameSz, const byte* value, word32 valueSz)
{
USER_NODE* map;
map = (USER_NODE*)WMALLOC(sizeof(USER_NODE), NULL, 0);
if (map != NULL) {
map->type = type;
if (usernameSz >= sizeof(map->username))
usernameSz = sizeof(map->username) - 1;
WMEMCPY(map->username, username, usernameSz + 1);
map->username[usernameSz] = 0;
map->usernameSz = usernameSz;
if (type != WOLFSSH_USERAUTH_NONE) {
wc_Sha256Hash(value, valueSz, map->fingerprint);
}
map->next = list;
}
return map;
}
/* returns WS_SUCCESS if user/password found */
static int CheckPassword(const byte* usr, const byte* pw, int pwSz)
{
int ret = WS_SUCCESS;
struct passwd* pwInfo;
// struct spwd* spwInfo;
char* encPw; /* encrypted version of password */
char tmp[256];
pwInfo = getpwnam((const char*)usr);
if (pwInfo == NULL) {
/* user name not found on system */
ret = WS_FATAL_ERROR;
}
/* check for shadow password record */
// spwInfo = getspnam(usr);
// if (spwInfo != NULL) {
// pwInfo->pw_passwd = spwInfo->sp_pwdp;
// }
//
{
int z;
for (z = 0; z < pwSz; z++)
tmp[z] = pw[z];
tmp[z] = '\0';
}
if (ret == WS_SUCCESS) {
encPw = crypt((const char*)tmp, pwInfo->pw_passwd);
if (encPw == NULL) {
/* error encrypting password for comparison */
ret = WS_FATAL_ERROR;
}
}
{
int z;
printf("peer pw : ");
for (z = 0; z < pwSz; z++)
printf("%02X", pw[z]);
printf("\n");
printf(" pw : ");
for (z = 0; z < pwSz; z++)
printf("%02X", pwInfo->pw_passwd[z]);
printf("\n");
printf(" enc : ");
for (z = 0; z < pwSz; z++)
printf("%02X", encPw[z]);
printf("\n");
}
if (ret == WS_SUCCESS) {
if (XSTRCMP(encPw, pwInfo->pw_passwd) == 0) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] User %s log in successful", usr);
}
else {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] User %s log in fail", usr);
ret = WS_FATAL_ERROR;
}
}
(void)pwSz;
return ret;
}
int DefaultUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
{
USER_NODE* map;
byte authHash[WC_SHA256_DIGEST_SIZE];
int ret;
if (authType != WOLFSSH_USERAUTH_PASSWORD &&
#ifdef WOLFSSH_ALLOW_USERAUTH_NONE
authType != WOLFSSH_USERAUTH_NONE &&
#endif
authType != WOLFSSH_USERAUTH_PUBLICKEY) {
return WOLFSSH_USERAUTH_FAILURE;
}
map = (USER_NODE*)ctx;
/* check if password on system */
if (authData->type == WOLFSSH_USERAUTH_PASSWORD) {
if (CheckPassword(authData->username, authData->sf.password.password,
authData->sf.password.passwordSz) == WS_SUCCESS) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Password and user on system");
return WOLFSSH_USERAUTH_SUCCESS;
}
}
if (authType == WOLFSSH_USERAUTH_PASSWORD) {
wc_Sha256Hash(authData->sf.password.password,
authData->sf.password.passwordSz,
authHash);
}
else if (authType == WOLFSSH_USERAUTH_PUBLICKEY) {
wc_Sha256Hash(authData->sf.publicKey.publicKey,
authData->sf.publicKey.publicKeySz,
authHash);
}
while (map != NULL) {
if (authData->usernameSz == map->usernameSz &&
WMEMCMP(authData->username, map->username, map->usernameSz) == 0 &&
authData->type == map->type) {
if (authData->type == WOLFSSH_USERAUTH_PUBLICKEY) {
if (WMEMCMP(map->fingerprint, authHash,
WC_SHA256_DIGEST_SIZE) == 0) {
return WOLFSSH_USERAUTH_SUCCESS;
}
else {
return WOLFSSH_USERAUTH_INVALID_PUBLICKEY;
}
}
else if (authData->type == WOLFSSH_USERAUTH_PASSWORD) {
if (WMEMCMP(map->fingerprint, authHash,
WC_SHA256_DIGEST_SIZE) == 0) {
return WOLFSSH_USERAUTH_SUCCESS;
}
else {
passwdRetry--;
return (passwdRetry > 0) ?
WOLFSSH_USERAUTH_INVALID_PASSWORD :
WOLFSSH_USERAUTH_REJECTED;
}
}
#ifdef WOLFSSH_ALLOW_USERAUTH_NONE
else if (authData->type == WOLFSSH_USERAUTH_NONE) {
return WOLFSSH_USERAUTH_SUCCESS;
}
#endif /* WOLFSSH_ALLOW_USERAUTH_NONE */
else {
return WOLFSSH_USERAUTH_INVALID_AUTHTYPE;
}
if (authData->type == map->type) {
if (WMEMCMP(map->fingerprint, authHash,
WC_SHA256_DIGEST_SIZE) == 0) {
return WOLFSSH_USERAUTH_SUCCESS;
}
else {
if (authType == WOLFSSH_USERAUTH_PASSWORD) {
passwdRetry--;
ret = (passwdRetry > 0) ?
WOLFSSH_USERAUTH_INVALID_PASSWORD :
WOLFSSH_USERAUTH_REJECTED;
}
else {
ret = WOLFSSH_USERAUTH_INVALID_PUBLICKEY;
}
return ret;
}
}
else {
return WOLFSSH_USERAUTH_INVALID_AUTHTYPE;
}
}
map = map->next;
}
return WOLFSSH_USERAUTH_INVALID_USER;
}
#endif /* WOLFSSH_SSHD */

View File

@ -52,11 +52,11 @@ struct WOLFSSHD_CONFIG {
char* listenAddress;
char* authKeysFile;
word16 port;
byte usePrivilegeSeparation;
byte passwordAuth:1;
byte pubKeyAuth:1;
byte permitRootLogin:1;
byte permitEmptyPasswords:1;
byte usePrivilegeSeparation:1;
};
/* returns WS_SUCCESS on success */
@ -141,7 +141,8 @@ static int wolfSSHD_ParseConfigLine(WOLFSSHD_CONFIG* conf, const char* l,
int sz;
/* supported config options */
const char authKeyFile[] = "AuthorizedKeysFile";
const char authKeyFile[] = "AuthorizedKeysFile";
const char privilegeSeparation[] = "UsePrivilegeSeparation";
sz = (int)XSTRLEN(authKeyFile);
if (lSz > sz && XSTRNCMP(l, authKeyFile, sz) == 0) {
@ -149,8 +150,32 @@ static int wolfSSHD_ParseConfigLine(WOLFSSHD_CONFIG* conf, const char* l,
conf->heap);
}
if (XSTRNCMP(l, "UsePrivilegeSeparation", 18) == 0) {
ret = WS_SUCCESS;
sz = (int)XSTRLEN(privilegeSeparation);
if (lSz > sz && XSTRNCMP(l, privilegeSeparation, sz) == 0) {
char* privType = NULL;
ret = wolfSSHD_CreateString(&privType, l + sz, lSz - sz, conf->heap);
/* check if is an allowed option */
if (XSTRNCMP(privType, "sandbox", 7) == 0) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Sandbox privilege separation");
ret = WS_SUCCESS;
}
if (XSTRNCMP(privType, "yes", 3) == 0) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Privilege separation enabled");
ret = WS_SUCCESS;
}
if (XSTRNCMP(privType, "no", 2) == 0) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Turning off privilege separation!");
ret = WS_SUCCESS;
}
if (ret != WS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Unknown/supported privilege separation!");
}
wolfSSHD_FreeString(&privType, conf->heap);
}
if (XSTRNCMP(l, "Subsystem", 9) == 0) {
@ -201,9 +226,11 @@ int wolfSSHD_LoadSSHD(WOLFSSHD_CONFIG* conf, const char* filename)
f = XFOPEN(filename, "rb");
if (f == XBADFILE) {
printf("Unable to open SSHD config file %s\n", filename);
wolfSSH_Log(WS_LOG_ERROR, "Unable to open SSHD config file %s\n",
filename);
return BAD_FUNC_ARG;
}
wolfSSH_Log(WS_LOG_INFO, "[SSHD] parsing config file %s", filename);
while ((current = XFGETS(buf, MAX_LINE_SIZE, f)) != NULL) {
int currentSz = (int)XSTRLEN(current);

View File

@ -34,6 +34,7 @@
#include <wolfssh/test.h>
#include "wolfsshd.h"
#include "wolfauth.h"
#include <signal.h>
@ -70,6 +71,8 @@
}
#endif /* WOLFSSH_SHELL */
static volatile byte debugMode = 0; /* default to off */
/* catch interrupts and close down gracefully */
static volatile byte quit = 0;
static const char defaultBanner[] = "wolfSSHD\n";
@ -86,6 +89,7 @@ static void ShowUsage(void)
printf(" -? display this help and exit\n");
printf(" -f <file name> Configuration file to use, default is /usr/locacl/etc/ssh/sshd_config\n");
printf(" -p <int> Port number to listen on\n");
printf(" -d Turn on debug mode\n");
}
static void interruptCatch(int in)
@ -97,35 +101,10 @@ static void interruptCatch(int in)
static void wolfSSHDLoggingCb(enum wolfSSH_LogLevel lvl, const char *const str)
{
fprintf(stderr, "[PID %d]: %s\n", getpid(), str);
(void)lvl;
}
static int wsUserAuth(byte authType,
WS_UserAuthData* authData,
void* ctx)
{
// if (ctx == NULL) {
// fprintf(stderr, "wsUserAuth: ctx not set");
// return WOLFSSH_USERAUTH_FAILURE;
// }
if (authType != WOLFSSH_USERAUTH_PASSWORD &&
#ifdef WOLFSSH_ALLOW_USERAUTH_NONE
authType != WOLFSSH_USERAUTH_NONE &&
#endif
authType != WOLFSSH_USERAUTH_PUBLICKEY) {
return WOLFSSH_USERAUTH_FAILURE;
if (debugMode) {
fprintf(stderr, "[PID %d]: %s\n", getpid(), str);
}
(void)ctx;
(void)authData;
fprintf(stderr, "returning success always for now");
/* @TODO allows all connections */
return WOLFSSH_USERAUTH_SUCCESS;
(void)lvl;
}
@ -143,7 +122,7 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
/* setup authority callback for checking peer connections */
if (ret == WS_SUCCESS) {
wolfSSH_SetUserAuth(*ctx, wsUserAuth);
wolfSSH_SetUserAuth(*ctx, DefaultUserAuth);
}
/* set banner to display on connection */
@ -270,12 +249,67 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
}
#if 0
int SFTP_Subsystem()
#ifdef WOLFSSH_SFTP
/* handle SFTP operations
* returns 0 on success
*/
static int SFTP_Subsystem(WOLFSSH* ssh, WOLFSSHD_CONNECTION* conn)
{
byte tmp[1];
int ret = WS_SUCCESS;
int error = WS_SUCCESS;
WS_SOCKET_T sockfd;
int select_ret = 0;
sockfd = (WS_SOCKET_T)wolfSSH_get_fd(ssh);
do {
// if (threadCtx->nonBlock) {
// if (error == WS_WANT_READ)
// printf("... sftp server would read block\n");
// else if (error == WS_WANT_WRITE)
// printf("... sftp server would write block\n");
// }
if (wolfSSH_stream_peek(ssh, tmp, 1) > 0) {
select_ret = WS_SELECT_RECV_READY;
}
else {
select_ret = tcp_select(sockfd, TEST_SFTP_TIMEOUT);
}
if (select_ret == WS_SELECT_RECV_READY ||
select_ret == WS_SELECT_ERROR_READY ||
error == WS_WANT_WRITE)
{
ret = wolfSSH_SFTP_read(ssh);
error = wolfSSH_get_error(ssh);
}
else if (select_ret == WS_SELECT_TIMEOUT)
error = WS_WANT_READ;
else
error = WS_FATAL_ERROR;
if (error == WS_WANT_READ || error == WS_WANT_WRITE ||
error == WS_CHAN_RXD || error == WS_REKEYING ||
error == WS_WINDOW_FULL)
ret = error;
if (ret == WS_FATAL_ERROR && error == 0) {
WOLFSSH_CHANNEL* channel =
wolfSSH_ChannelNext(ssh, NULL);
if (channel && wolfSSH_ChannelGetEof(channel)) {
ret = 0;
break;
}
}
} while (ret != WS_FATAL_ERROR);
return ret;
}
#endif
#ifdef WOLFSSH_SCP
int SCP_Subsystem()
{
@ -457,14 +491,25 @@ static void* wolfSSHD_HandleConnection(void* arg)
}
}
#ifdef WOLFSSH_SHELL
printf("ret of accept = %d\n",ret);
if (ret == WS_SUCCESS) {
printf("trying to run shell\n");
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Entering new shell");
SHELL_Subsystem(conn, ssh);
switch (ret) {
case WS_SFTP_COMPLETE:
#ifdef WOLFSSH_SFTP
ret = SFTP_Subsystem(ssh, conn);
#else
err_sys("SFTP not compiled in. Please use --enable-sftp");
#endif
break;
case WS_SUCCESS: /* default success case to shell */
#ifdef WOLFSSH_SHELL
printf("ret of accept = %d\n",ret);
if (ret == WS_SUCCESS) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Entering new shell");
SHELL_Subsystem(conn, ssh);
}
#endif
break;
}
#endif
wolfSSH_shutdown(ssh);
wolfSSH_free(ssh);
@ -573,21 +618,23 @@ int main(int argc, char** argv)
}
while ((ch = mygetopt(argc, argv, "?f:p:h:")) != -1) {
while ((ch = mygetopt(argc, argv, "?f:p:h:d")) != -1) {
switch (ch) {
case 'f':
configFile = myoptarg;
break;
case 'p':
ret = XATOI(myoptarg);
if (ret < 0) {
printf("Issue parsing port number %s\n", myoptarg);
ret = BAD_FUNC_ARG;
}
else {
port = (word16)ret;
ret = WS_SUCCESS;
if (ret == WS_SUCCESS) {
ret = XATOI(myoptarg);
if (ret < 0) {
printf("Issue parsing port number %s\n", myoptarg);
ret = BAD_FUNC_ARG;
}
else {
port = (word16)ret;
ret = WS_SUCCESS;
}
}
break;
@ -595,6 +642,10 @@ int main(int argc, char** argv)
hostKeyFile = myoptarg;
break;
case 'd':
debugMode = 1; /* turn on debug mode */
break;
case '?':
ShowUsage();
return WS_SUCCESS;

View File

@ -23,6 +23,10 @@
typedef struct WOLFSSHD_CONFIG WOLFSSHD_CONFIG;
#define WOLFSSHD_PRIV_SEPARAT 0
#define WOLFSSHD_PRIV_SANDBOX 1
#define WOLFSSHD_PRIV_OFF 2
WOLFSSHD_CONFIG* wolfSSHD_NewConfig(void* heap);
void wolfSSHD_FreeConfig(WOLFSSHD_CONFIG* conf);
int wolfSSHD_LoadSSHD(WOLFSSHD_CONFIG* conf, const char* filename);