mirror of https://github.com/wolfSSL/wolfssh.git
add wolfauth file for peer auth
parent
65dde05900
commit
475ee1f113
|
@ -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
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
145
apps/wolfsshd.c
145
apps/wolfsshd.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue