1. Flushed out the authentication callback.

2. Added public key authentication.
pull/4/head
John Safranek 2016-05-16 18:16:53 -07:00
parent a744dcc540
commit a275ac59f0
11 changed files with 573 additions and 58 deletions

View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIPIxGlM2XBIY6NulXIJgXdOheM+mZ7ixU8RLaXy2OoJeoAoGCCqGSM49
AwEHoUQDQgAEpalbz23q5UgbcVHU0uGllXYqEw9kAG/uyCSMfZ1wliKi6tXrs/9p
WCseyyREeyKmmMqt6WkekGJd54jHPa/Wyw==
-----END EC PRIVATE KEY-----

View File

@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKWpW89t6uVIG3FR1NLhpZV2KhMPZABv7sgkjH2dcJYiourV67P/aVgrHsskRHsippjKrelpHpBiXeeIxz2v1ss= john@johnwork.local

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAqg8EVU0VZP8Iz4aKOuvjM7a3N9SrMQ2fpAFdNd/Tx0PsLLnj
aW2uozZ+aOplExDq8a89CzLAyTgTOwphtPfN5BeIESIoRAqUNK3Izj+gUn21UxPZ
nyCuSLFImRnfEqBPZEldqSdhb2XgUBDaAMRBZNM2S/bXIT0vjglBmyuEg487jWZf
99DHM7O9zdzAc4uidaD6O7BZaswennAYytiqY7rOGNa2BaYSZ1MbSrwdLPoaGmna
7m4hOe3Sugax+YmcFS00Crsd9bgiSz4YpLSN4i23ZRmRHLSZE2rH1UrFIs8FSMkY
4VSpm3SERsJFN/A9ONwEdYdJlKBgjyCrqnBTHwIDAQABAoIBADTkttRRRXZEXNkv
X480D1bmXdZfr19yfVTll7hKBfTUi4Dd0H3aP5dEO80mGonzmR/TAYmaH5x2dITI
ldtTuBZZu1iY5y1CnRZFd0+vOo5tyxgr9GQqJgs2GP6FrXx9oDPxHdCfDw83AK3m
j+ftIunZR+oYvJD6FvB2sJEy1+STBoI6znDILaJzm0sR6YCnaH05cfVTB/UyNisy
8OAIJrhB+oiH/BdWyYDhVM3E09uFt8b5+rJVqhQ+G+dFzRNsTLLAzADGWtxr3Yl6
XtHjNDE/HobMgjlH6CkXPZ5ZO3wkUPg4EuTaS1atlaxWqHqp/3OffB8rPGxg0N+n
w9NRbwECgYEA1E6AgiCVOj7fIFcznoEJSu2tcdPcCD+PopWisNWNE678ZqlUsD/4
7Fxz24RUn+1+pO4VjQ0vmDkhgM+O28gJdd1O+3loht9+h3Ie2+/EUXQudmqs7sPV
8DAuhWrnqrO6W4/nO/6MEgcXI5iJyi+uCNclMARDN1T3bh60UbcfAksCgYEAzQ6n
xGBkkAm2gItkjdIlZFVKJikSpKhLnQV5D04y/S5nw1XBdk7iL8rWIqZVYlE+7sjX
TB4gCXtFFZDTnM8fSzQU5I3ggo5NxmKq/Q4hl2aFSPEK3PMQ4Ik4jud85rluhTG8
WRtIlvbqSKTSiuPbZXD/xmS3EL8Xf+V2wbK/zf0CgYEAsvCbZZIa1KXLIBH/Ytf1
Qh8Dcg4TxSv1Xx5pqkvDhVSWTdzokUjKAEWILPvi64ybkl1M8r6rX8y/TTcjfGCk
gKAQAup4TD0xAu4PzmXO/KxEwO/2Y6PRvIiPnUnWiszDBItMZQeNfWBWg1z8vdnk
AHV9VXQyRv+pMDpW1wzV6PMCgYAnL6HH2VPeYrzJm9m/cGVM4y+kUz0I0lCA1Ubp
Mdx0naWeooix/ykiUPTS8k5m13fbUe4y0Z71sOTm1iJaWQp16KIFe0doK6GZQ8nB
Si4JLMJTyhx1VM3o2tBAHuSzgsQoF/USYjBhCRaEg1rox9ppbEq0sxJ41Mu82TD0
myAkUQKBgFboHyz32Lx4/xB0fNTyw5c4tmnvQ8B1BFInXV3+yfL6vRIVDAfj5mMn
WUNo1Hd77uHLuB3n4TzU8KwbF1vD2aACLk3p+OVRramMyv98nrl83oBMONxUh9Qb
J1NBwEkdjaqk+s+r3SSl7avVJJOViEGwGnrm0a6kACd5zxdjx0vk
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvT92RaMDrDjVxw+TMFognIl8rQUWRoaDDYorFkoFLOR3R3AA
rh2D4tlumdTwRZgVk/aHTqxkY6GVyXww6D4vo/EknwxrHP4bApnNxqdshIVGVBJA
4bTl8qo57NYnJAvRoeLvNGklbcB0ZyWYfcT4UqubSzoSHeHj+tbPmuacI045xIQW
iD1CTtgvzNKRZ522cSoCZV+7dQ6Mu4eXl8b4spjiL2gmSlPseTqKX8zP8BZHstBD
1jZsyOcv/qc1OWn7HXhFnYkAyEHPNB+j8/H7KBT72EhvrOP8M9Hbru8nnldWKaIa
OuWa/qRJyH+3TtAfBG5YFrfrnfiSPMKwIXxOMQIDAQABAoIBAQCNpGEGL8NA9Gz0
hzC4AMzlvHWHHgaVFHoj+STUkuQavIiV/DtWFhsu/2QrWNfYjsKfsuWEubyNYVQ1
sHD+cgTAJG0vaWEGGx3mLW15YLf027dOlzbed8GfhU7Dd2lmLj5hdvNn+8aaxW+Z
/+aJQ5JEddJOVJFYskgq5voNSsrUFJ72J2e3JXpDuytn0f7RaCMGMHy/YEnezH4m
Wjv+pqbnqN2sua+CmjpBfmEhN6MI5MS8EfU7jk1R873aurLF7vvP34OhggHhUZ0H
Wl3Yx1s/lxNqTR6NOaxAlYJsoqHMipshMjpYzOctGnmkMVCxS3YjG7NAPT1ycjLs
Xzi1jbKNAoGBAO1afo6hYn0mXHjEh3HJQVd3lJOTJnjIoxW9WcsbtLJrD+eA8vr8
jjKpGx5/4SbvACXY3ckaIwAmO0YjwFDnzmKyNrKYCRY0GJ5GvK8sKJQv4F3Jssj7
XRPVNqoVD4mlFlldInSkR136+wxegL8PwpyVD+eqfxYb1Ns4fVguV3gvAoGBAMwd
f3Q2bbSSJWLFULBcodrzsv0emA2LBWlgjl7SiZBKDUZ+4lRprhbmy9W9ezAre1zu
kxLPY4mcPcgt5HphCV6A+zwDs3PWmNCEDFmfToDzRu0DndXci+ex6KpX3NFBVQfH
32c8cniwYI+FoZCZDKVnq/C2dJADVXtezMW/3qefAoGAQIFuka7UiHSrfvrSYJ80
jePm0jCUrRDCGb9rLuLpue+U0/Lclk+bCbOhtilE9ILRxHdq1yOuTXUWeNpwgsxs
76/FY8Yj+g/QfPt2fhj/Mj7MuFB/sVV3F1PD1neA0IS4TTMdkRuwdZ8nKVZpoQNU
fZ+ZQfm5LjYEJEv27MczaGsCgYBgNcs80Ob3BSggHVeCObeFB/enPcN4Jr4/RGb3
JQ/4dh85ylcOaN3JJ7KOpgip1OUKEd47MIv/cijg8VjPomuTIwLI8AmnIVDYgFV9
7QxI1eLplxnPk2xSotZDbLTF4aCd0UVpWOGwJ5rsK5XTHYELeglepfHda+TgCPhG
gcEGiwKBgAD28uslungErQ4NLqdp1lfmNjJQ0vLrrTFGZcAHl4NsZic+lCwFAV9c
4DEw7GHSdDW3nzjnjmexUAhozs/Y7oj9XcTN4oY9Sg4Ef+6K6JsWofwJguJiAzzo
JX88mqqD+NiT0VT5zrT6NTbMGFSq8pC3fJcLJy+u/MOTrxp17Bjb
-----END RSA PRIVATE KEY-----

2
certs/passwd.txt 100644
View File

@ -0,0 +1,2 @@
jill:upthehill
jack:fetchapail

View File

@ -0,0 +1,2 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9P3ZFowOsONXHD5MwWiCciXytBRZGhoMNiisWSgUs5HdHcACuHYPi2W6Z1PBFmBWT9odOrGRjoZXJfDDoPi+j8SSfDGsc/hsCmc3Gp2yEhUZUEkDhtOXyqjns1ickC9Gh4u80aSVtwHRnJZh9xPhSq5tLOhId4eP61s+a5pwjTjnEhBaIPUJO2C/M0pFnnbZxKgJlX7t1Doy7h5eXxviymOIvaCZKU+x5OopfzM/wFkey0EPWNmzI5y/+pzU5afsdeEWdiQDIQc80H6Pz8fsoFPvYSG+s4/wz0duu7yeeV1Ypoho65Zr+pEnIf7dO0B8EblgWt+ud+JI8wrAhfE4x hansel
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqDwRVTRVk/wjPhoo66+Mztrc31KsxDZ+kAV0139PHQ+wsueNpba6jNn5o6mUTEOrxrz0LMsDJOBM7CmG0983kF4gRIihECpQ0rcjOP6BSfbVTE9mfIK5IsUiZGd8SoE9kSV2pJ2FvZeBQENoAxEFk0zZL9tchPS+OCUGbK4SDjzuNZl/30Mczs73N3MBzi6J1oPo7sFlqzB6ecBjK2Kpjus4Y1rYFphJnUxtKvB0s+hoaadrubiE57dK6BrH5iZwVLTQKux31uCJLPhiktI3iLbdlGZEctJkTasfVSsUizwVIyRjhVKmbdIRGwkU38D043AR1h0mUoGCPIKuqcFMf gretel

View File

@ -33,6 +33,8 @@
#include <sys/socket.h>
#include <stdio.h>
#include <pthread.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/coding.h>
#include <wolfssh/ssh.h>
#ifndef SO_NOSIGPIPE
#include <signal.h>
@ -315,9 +317,253 @@ static int load_file(const char* fileName, uint8_t* buf, uint32_t bufSz)
}
static inline void c32toa(uint32_t u32, uint8_t* c)
{
c[0] = (u32 >> 24) & 0xff;
c[1] = (u32 >> 16) & 0xff;
c[2] = (u32 >> 8) & 0xff;
c[3] = u32 & 0xff;
}
/* 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. */
typedef struct PwMap {
uint8_t type;
uint8_t username[32];
uint32_t usernameSz;
uint8_t p[SHA256_DIGEST_SIZE];
struct PwMap* next;
} PwMap;
typedef struct PwMapList {
PwMap* head;
} PwMapList;
static PwMap* PwMapNew(PwMapList* list, uint8_t type, const uint8_t* username,
uint32_t usernameSz, const uint8_t* p, uint32_t pSz)
{
PwMap* map;
map = (PwMap*)malloc(sizeof(PwMap));
if (map != NULL) {
Sha256 sha;
uint8_t flatSz[4];
map->type = type;
if (usernameSz >= sizeof(map->username))
usernameSz = sizeof(map->username) - 1;
memcpy(map->username, username, usernameSz + 1);
map->username[usernameSz] = 0;
map->usernameSz = usernameSz;
wc_InitSha256(&sha);
c32toa(pSz, flatSz);
wc_Sha256Update(&sha, flatSz, sizeof(flatSz));
wc_Sha256Update(&sha, p, pSz);
wc_Sha256Final(&sha, map->p);
map->next = list->head;
list->head = map;
}
return map;
}
static void PwMapListDelete(PwMapList* list)
{
if (list != NULL) {
PwMap* head = list->head;
while (head != NULL) {
PwMap* cur = head;
head = head->next;
memset(cur, 0, sizeof(PwMap));
}
}
}
static const char samplePasswordBuffer[] =
"jill:upthehill\n"
"jack:fetchapail\n";
static const char samplePublicKeyBuffer[] =
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9P3ZFowOsONXHD5MwWiCciXytBRZGho"
"MNiisWSgUs5HdHcACuHYPi2W6Z1PBFmBWT9odOrGRjoZXJfDDoPi+j8SSfDGsc/hsCmc3G"
"p2yEhUZUEkDhtOXyqjns1ickC9Gh4u80aSVtwHRnJZh9xPhSq5tLOhId4eP61s+a5pwjTj"
"nEhBaIPUJO2C/M0pFnnbZxKgJlX7t1Doy7h5eXxviymOIvaCZKU+x5OopfzM/wFkey0EPW"
"NmzI5y/+pzU5afsdeEWdiQDIQc80H6Pz8fsoFPvYSG+s4/wz0duu7yeeV1Ypoho65Zr+pE"
"nIf7dO0B8EblgWt+ud+JI8wrAhfE4x hansel\n"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqDwRVTRVk/wjPhoo66+Mztrc31KsxDZ"
"+kAV0139PHQ+wsueNpba6jNn5o6mUTEOrxrz0LMsDJOBM7CmG0983kF4gRIihECpQ0rcjO"
"P6BSfbVTE9mfIK5IsUiZGd8SoE9kSV2pJ2FvZeBQENoAxEFk0zZL9tchPS+OCUGbK4SDjz"
"uNZl/30Mczs73N3MBzi6J1oPo7sFlqzB6ecBjK2Kpjus4Y1rYFphJnUxtKvB0s+hoaadru"
"biE57dK6BrH5iZwVLTQKux31uCJLPhiktI3iLbdlGZEctJkTasfVSsUizwVIyRjhVKmbdI"
"RGwkU38D043AR1h0mUoGCPIKuqcFMf gretel\n";
static int LoadPasswordBuffer(uint8_t* buf, uint32_t bufSz, PwMapList* list)
{
char* str = (char*)buf;
char* delimiter;
char* username;
char* password;
/* Each line of passwd.txt is in the format
* username:password\n
* This function modifies the passed-in buffer. */
if (list == NULL)
return -1;
if (buf == NULL || bufSz == 0)
return 0;
while (*str != 0) {
delimiter = strchr(str, ':');
username = str;
*delimiter = 0;
password = delimiter + 1;
str = strchr(password, '\n');
*str = 0;
str++;
if (PwMapNew(list, WOLFSSH_USERAUTH_PASSWORD,
(uint8_t*)username, (uint32_t)strlen(username),
(uint8_t*)password, (uint32_t)strlen(password)) == NULL ) {
return -1;
}
}
return 0;
}
static int LoadPublicKeyBuffer(uint8_t* buf, uint32_t bufSz, PwMapList* list)
{
char* str = (char*)buf;
char* delimiter;
uint8_t* publicKey64;
uint32_t publicKey64Sz;
uint8_t* username;
uint32_t usernameSz;
uint8_t publicKey[300];
uint32_t publicKeySz;
int decodeResult;
/* Each line of passwd.txt is in the format
* ssh-rsa AAAB3BASE64ENCODEDPUBLICKEYBLOB username\n
* This function modifies the passed-in buffer. */
if (list == NULL)
return -1;
if (buf == NULL || bufSz == 0)
return 0;
while (*str != 0) {
/* Skip the public key type. This example will always be ssh-rsa. */
delimiter = strchr(str, ' ');
str = delimiter + 1;
delimiter = strchr(str, ' ');
publicKey64 = (uint8_t*)str;
publicKey64Sz = (uint32_t)(delimiter - str);
str = delimiter + 1;
delimiter = strchr(str, '\n');
username = (uint8_t*)str;
usernameSz = (uint32_t)(delimiter - str);
str = delimiter + 1;
publicKeySz = sizeof(publicKey);
decodeResult = Base64_Decode(publicKey64, publicKey64Sz,
publicKey, &publicKeySz);
printf("Base64_Decode = %d\n", decodeResult);
if (PwMapNew(list, WOLFSSH_USERAUTH_PUBLICKEY,
username, usernameSz,
publicKey, publicKeySz) == NULL ) {
return -1;
}
}
return 0;
}
static int wsUserAuth(uint8_t authType,
const WS_UserAuthData* authData,
void* ctx)
{
PwMapList* list;
PwMap* map;
uint8_t authHash[SHA256_DIGEST_SIZE];
if (ctx == NULL) {
fprintf(stderr, "wsUserAuth: ctx not set");
return WOLFSSH_USERAUTH_FAILURE;
}
if (authType != WOLFSSH_USERAUTH_PASSWORD &&
authType != WOLFSSH_USERAUTH_PUBLICKEY) {
return WOLFSSH_USERAUTH_FAILURE;
}
/* Hash the password or public key with its length. */
{
Sha256 sha;
uint8_t flatSz[4];
wc_InitSha256(&sha);
if (authType == WOLFSSH_USERAUTH_PASSWORD) {
c32toa(authData->sf.password.passwordSz, flatSz);
wc_Sha256Update(&sha, flatSz, sizeof(flatSz));
wc_Sha256Update(&sha,
authData->sf.password.password,
authData->sf.password.passwordSz);
}
else if (authType == WOLFSSH_USERAUTH_PUBLICKEY) {
c32toa(authData->sf.publicKey.publicKeySz, flatSz);
wc_Sha256Update(&sha, flatSz, sizeof(flatSz));
wc_Sha256Update(&sha,
authData->sf.publicKey.publicKey,
authData->sf.publicKey.publicKeySz);
}
wc_Sha256Final(&sha, authHash);
}
list = (PwMapList*)ctx;
map = list->head;
while (map != NULL) {
if (authData->type == map->type &&
authData->usernameSz == map->usernameSz &&
memcmp(authData->username, map->username, map->usernameSz) == 0) {
if (memcmp(map->p, authHash, SHA256_DIGEST_SIZE) != 0) {
return (authType == WOLFSSH_USERAUTH_PASSWORD ?
WOLFSSH_USERAUTH_INVALID_PASSWORD :
WOLFSSH_USERAUTH_INVALID_PUBLICKEY);
}
return WOLFSSH_USERAUTH_SUCCESS;
}
map = map->next;
}
return WOLFSSH_USERAUTH_INVALID_USER;
}
int main(void)
{
WOLFSSH_CTX* ctx = NULL;
PwMapList pwMapList;
SOCKET_T listenFd = 0;
#ifdef DEBUG_WOLFSSH
@ -335,6 +581,9 @@ int main(void)
exit(EXIT_FAILURE);
}
memset(&pwMapList, 0, sizeof(pwMapList));
wolfSSH_SetUserAuth(ctx, wsUserAuth);
{
uint8_t buf[SCRATCH_BUFFER_SIZE];
uint32_t bufSz;
@ -360,6 +609,16 @@ int main(void)
fprintf(stderr, "Couldn't use key buffer.\n");
exit(EXIT_FAILURE);
}
bufSz = (uint32_t)strlen((char*)samplePasswordBuffer);
memcpy(buf, samplePasswordBuffer, bufSz);
buf[bufSz] = 0;
LoadPasswordBuffer(buf, bufSz, &pwMapList);
bufSz = (uint32_t)strlen((char*)samplePublicKeyBuffer);
memcpy(buf, samplePublicKeyBuffer, bufSz);
buf[bufSz] = 0;
LoadPublicKeyBuffer(buf, bufSz, &pwMapList);
}
tcp_bind(&listenFd, SERVER_PORT_NUMBER, 0);
@ -376,6 +635,7 @@ int main(void)
fprintf(stderr, "Couldn't allocate SSH data.\n");
exit(EXIT_FAILURE);
}
wolfSSH_SetUserAuthCtx(ssh, &pwMapList);
if (listen(listenFd, 5) != 0)
err_sys("tcp listen failed");
@ -391,6 +651,7 @@ int main(void)
pthread_detach(thread);
}
PwMapListDelete(&pwMapList);
if (wolfSSH_Cleanup() != WS_SUCCESS) {
fprintf(stderr, "Couldn't clean up wolfSSH.\n");
exit(EXIT_FAILURE);

View File

@ -1360,65 +1360,176 @@ static int DoUserAuthRequest(WOLFSSH* ssh,
uint8_t* buf, uint32_t len, uint32_t* idx)
{
uint32_t begin = *idx;
int ret;
uint32_t valueSz;
char value[32];
uint8_t authNameId;
int ret;
uint8_t authNameId;
uint32_t authNameSz;
WS_UserAuthData authData;
(void)ssh;
(void)len;
GetUint32(&authData.usernameSz, buf, len, &begin);
authData.username = buf + begin;
begin += authData.usernameSz;
DumpOctetString(buf, len);
ato32(buf + begin, &valueSz);
begin += LENGTH_SZ;
GetUint32(&authData.serviceNameSz, buf, len, &begin);
authData.serviceName = buf + begin;
begin += authData.serviceNameSz;
XMEMCPY(value, buf + begin, valueSz);
begin += valueSz;
value[valueSz] = 0;
WLOG(WS_LOG_DEBUG, "DUAR: userName = %s", value);
ato32(buf + begin, &valueSz);
begin += LENGTH_SZ;
XMEMCPY(value, buf + begin, valueSz);
begin += valueSz;
value[valueSz] = 0;
WLOG(WS_LOG_DEBUG, "DUAR: serviceName = %s", value);
ato32(buf + begin, &valueSz);
begin += LENGTH_SZ;
XMEMCPY(value, buf + begin, valueSz);
begin += valueSz;
value[valueSz] = 0;
WLOG(WS_LOG_DEBUG, "DUAR: authName = %s", value);
authNameId = NameToId(value, valueSz);
GetUint32(&authNameSz, buf, len, &begin);
authNameId = NameToId((const char*)(buf + begin), authNameSz);
begin += authNameSz;
if (authNameId == ID_USERAUTH_PASSWORD) {
uint8_t pwChanged;
ret = GetBoolean(&pwChanged, buf, len, &begin);
WLOG(WS_LOG_DEBUG, "DUAR: pwChanged = %s",
(pwChanged ? "TRUE" : "FALSE"));
if (!pwChanged) {
ret = GetString(value, &valueSz, buf, len, &begin);
if (ret == WS_SUCCESS)
WLOG(WS_LOG_DEBUG, "DUAR: password = %s", value);
else
WLOG(WS_LOG_DEBUG, "DUAR: password = error? %d", ret);
}
else {
WS_UserAuthData_Password* pw = &authData.sf.password;
authData.type = WOLFSSH_USERAUTH_PASSWORD;
ret = GetBoolean(&pw->hasNewPassword, buf, len, &begin);
ret = GetUint32(&pw->passwordSz, buf, len, &begin);
pw->password = buf + begin;
begin += pw->passwordSz;
if (pw->hasNewPassword) {
/* Skip the password change. Maybe error out since we aren't
* supporting password changes at this time. */
ret = GetUint32(&pw->newPasswordSz, buf, len, &begin);
pw->newPassword = buf + begin;
begin += pw->newPasswordSz;
}
else {
pw->newPassword = NULL;
pw->newPasswordSz = 0;
}
if (ssh->ctx->userAuthCb != NULL) {
WLOG(WS_LOG_DEBUG, "DUAR: Checking the password");
ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD,
&authData, ssh->userAuthCtx);
if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "DUAR: password check successful");
ssh->clientState = CLIENT_USERAUTH_DONE;
}
else {
WLOG(WS_LOG_DEBUG, "DUAR: password check failed");
SendUserAuthFailure(ssh, 0);
}
}
else {
WLOG(WS_LOG_DEBUG, "DUAR: No user auth callback");
}
}
else if (authNameId == ID_USERAUTH_PUBLICKEY) {
} else
WS_UserAuthData_PublicKey* pk = &authData.sf.publicKey;
authData.type = WOLFSSH_USERAUTH_PUBLICKEY;
ret = GetBoolean(&pk->hasSignature, buf, len, &begin);
GetUint32(&pk->publicKeyTypeSz, buf, len, &begin);
pk->publicKeyType = buf + begin;
begin += pk->publicKeyTypeSz;
GetUint32(&pk->publicKeySz, buf, len, &begin);
pk->publicKey = buf + begin;
begin += pk->publicKeySz;
if (pk->hasSignature) {
GetUint32(&pk->signatureSz, buf, len, &begin);
pk->signature = buf + begin;
begin += pk->signatureSz;
}
else {
pk->signature = NULL;
pk->signatureSz = 0;
}
if (ssh->ctx->userAuthCb != NULL) {
ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY,
&authData, ssh->userAuthCtx);
}
if (pk->signature == NULL) {
WLOG(WS_LOG_DEBUG, "DUAR: Send the PK OK!");
}
else {
uint8_t checkDigest[MAX_ENCODED_SIG_SZ];
uint32_t checkDigestSz = 0;
uint8_t encDigest[MAX_ENCODED_SIG_SZ];
uint32_t encDigestSz;
{
RsaKey key;
uint8_t* n;
uint32_t nSz;
uint8_t* e;
uint32_t eSz;
uint32_t i = 0;
GetUint32(&nSz, pk->publicKey, pk->publicKeySz, &i);
i += nSz;
GetUint32(&eSz, pk->publicKey, pk->publicKeySz, &i);
e = pk->publicKey + i;
i += eSz;
GetUint32(&nSz, pk->publicKey, pk->publicKeySz, &i);
n = authData.sf.publicKey.publicKey + i;
wc_InitRsaKey(&key, ssh->ctx->heap);
ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, &key);
i = 0;
GetUint32(&nSz, pk->signature, pk->signatureSz, &i);
i += nSz;
GetUint32(&nSz, pk->signature, pk->signatureSz, &i);
n = pk->signature + i;
ret = wc_RsaSSL_Verify(n, nSz, checkDigest,
sizeof(checkDigest), &key);
wc_FreeRsaKey(&key);
}
if (ret > 0) {
checkDigestSz = (uint32_t)ret;
ret = 0;
}
{
Sha sha;
uint8_t digest[SHA_DIGEST_SIZE];
wc_InitSha(&sha);
c32toa(ssh->sessionIdSz, digest);
wc_ShaUpdate(&sha, digest, UINT32_SZ);
wc_ShaUpdate(&sha, ssh->sessionId, ssh->sessionIdSz);
digest[0] = MSGID_USERAUTH_REQUEST;
wc_ShaUpdate(&sha, digest, MSG_ID_SZ);
/* The rest of the fields in the signature are already
* in the buffer. Just need to account for the sizes. */
wc_ShaUpdate(&sha, buf + *idx,
authData.usernameSz + authData.serviceNameSz +
authNameSz + BOOLEAN_SZ +
authData.sf.publicKey.publicKeyTypeSz +
authData.sf.publicKey.publicKeySz + (UINT32_SZ * 5));
ShaFinal(&sha, digest);
encDigestSz = wc_EncodeSignature(encDigest, digest,
SHA_DIGEST_SIZE, SHAh);
}
{
volatile int compare;
volatile int sizeCompare;
compare = ConstantCompare(encDigest, checkDigest, encDigestSz);
sizeCompare = encDigestSz != checkDigestSz;
if (compare || sizeCompare || ret < 0) {
SendUserAuthFailure(ssh, 0);
}
else {
ssh->clientState = CLIENT_USERAUTH_DONE;
}
}
}
}
else
SendUserAuthFailure(ssh, 0);
*idx = begin;
ssh->clientState = CLIENT_USERAUTH_DONE;
return WS_SUCCESS;
}
@ -2652,7 +2763,7 @@ int SendServiceAccept(WOLFSSH* ssh)
}
static const char cannedAuths[] = "password";
static const char cannedAuths[] = "publickey";
static const uint32_t cannedAuthsSz = sizeof(cannedAuths) - 1;

View File

@ -487,6 +487,31 @@ int wolfSSH_stream_send(WOLFSSH* ssh, uint8_t* buf, uint32_t bufSz)
}
void wolfSSH_SetUserAuth(WOLFSSH_CTX* ctx, WS_CallbackUserAuth cb)
{
if (ctx != NULL) {
ctx->userAuthCb = cb;
}
}
void wolfSSH_SetUserAuthCtx(WOLFSSH* ssh, void* userAuthCtx)
{
if (ssh != NULL) {
ssh->userAuthCtx = userAuthCtx;
}
}
void* wolfSSH_GetUserAuthCtx(WOLFSSH* ssh)
{
if (ssh != NULL) {
return ssh->userAuthCtx;
}
return NULL;
}
static int ProcessBuffer(WOLFSSH_CTX* ctx, const uint8_t* in, uint32_t inSz,
int format, int type)
{

View File

@ -134,16 +134,17 @@ WOLFSSH_LOCAL void ShrinkBuffer(Buffer* buf, int);
/* our wolfSSH Context */
struct WOLFSSH_CTX {
void* heap; /* heap hint */
WS_CallbackIORecv ioRecvCb; /* I/O Receive Callback */
WS_CallbackIOSend ioSendCb; /* I/O Send Callback */
void* heap; /* heap hint */
WS_CallbackIORecv ioRecvCb; /* I/O Receive Callback */
WS_CallbackIOSend ioSendCb; /* I/O Send Callback */
WS_CallbackUserAuth userAuthCb; /* User Authentication Callback */
uint8_t* cert; /* Owned by CTX */
uint32_t certSz;
uint8_t* caCert; /* Owned by CTX */
uint32_t caCertSz;
uint8_t* privateKey; /* Owned by CTX */
uint32_t privateKeySz;
uint8_t* cert; /* Owned by CTX */
uint32_t certSz;
uint8_t* caCert; /* Owned by CTX */
uint32_t caCertSz;
uint8_t* privateKey; /* Owned by CTX */
uint32_t privateKeySz;
};
@ -248,8 +249,11 @@ struct WOLFSSH {
HandshakeInfo* handshake;
void* userAuthCtx;
uint8_t* userName;
uint32_t userNameSz;
uint8_t* pkBlob;
uint32_t pkBlobSz;
};

View File

@ -66,16 +66,51 @@ WOLFSSH_API const char* wolfSSH_get_error_name(const WOLFSSH*);
/* I/O callbacks */
typedef int (*WS_CallbackIORecv)(WOLFSSH*, void*, uint32_t, void*);
typedef int (*WS_CallbackIOSend)(WOLFSSH*, void*, uint32_t, void*);
WOLFSSH_API void wolfSSH_SetIORecv(WOLFSSH_CTX*, WS_CallbackIORecv);
WOLFSSH_API void wolfSSH_SetIOSend(WOLFSSH_CTX*, WS_CallbackIOSend);
WOLFSSH_API void wolfSSH_SetIOReadCtx(WOLFSSH*, void*);
WOLFSSH_API void wolfSSH_SetIOWriteCtx(WOLFSSH*, void*);
WOLFSSH_API void* wolfSSH_GetIOReadCtx(WOLFSSH*);
WOLFSSH_API void* wolfSSH_GetIOWriteCtx(WOLFSSH*);
/* User Authentication callback */
typedef struct WS_UserAuthData_Password {
uint8_t* password;
uint32_t passwordSz;
/* The following are present for future use. */
uint8_t hasNewPassword;
uint8_t* newPassword;
uint32_t newPasswordSz;
} WS_UserAuthData_Password;
typedef struct WS_UserAuthData_PublicKey {
uint8_t* publicKeyType;
uint32_t publicKeyTypeSz;
uint8_t* publicKey;
uint32_t publicKeySz;
uint8_t hasSignature;
uint8_t* signature;
uint32_t signatureSz;
} WS_UserAuthData_PublicKey;
typedef struct WS_UserAuthData {
uint8_t type;
uint8_t* username;
uint32_t usernameSz;
uint8_t* serviceName;
uint32_t serviceNameSz;
union {
WS_UserAuthData_Password password;
WS_UserAuthData_PublicKey publicKey;
} sf;
} WS_UserAuthData;
typedef int (*WS_CallbackUserAuth)(uint8_t, const WS_UserAuthData*, void*);
WOLFSSH_API void wolfSSH_SetUserAuth(WOLFSSH_CTX*, WS_CallbackUserAuth);
WOLFSSH_API void wolfSSH_SetUserAuthCtx(WOLFSSH*, void*);
WOLFSSH_API void* wolfSSH_GetUserAuthCtx(WOLFSSH*);
WOLFSSH_API int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX*,
const uint8_t*, uint32_t, int);
WOLFSSH_API int wolfSSH_CTX_UseCert_buffer(WOLFSSH_CTX*,
@ -104,6 +139,21 @@ enum WS_FormatTypes {
};
enum WS_UserAuthTypes {
WOLFSSH_USERAUTH_PASSWORD,
WOLFSSH_USERAUTH_PUBLICKEY
};
enum WS_UserAuthResults {
WOLFSSH_USERAUTH_SUCCESS,
WOLFSSH_USERAUTH_FAILURE,
WOLFSSH_USERAUTH_INVALID_USER,
WOLFSSH_USERAUTH_INVALID_PASSWORD,
WOLFSSH_USERAUTH_INVALID_PUBLICKEY
};
enum WS_DisconnectReasonCodes {
WOLFSSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1,
WOLFSSH_DISCONNECT_PROTOCOL_ERROR = 2,