Skip to content

Commit e8f78b4

Browse files
committed
Add support for OpenSSH-style certificates.
This commit adds support for presenting an OpenSSH-style RSA SHA-1 cert as the host public key. It also adds support for receiving the same type of cert for user authentication.
1 parent 6f57587 commit e8f78b4

40 files changed

+3109
-328
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ examples/scpclient/wolfscp
5858

5959
# applications
6060
apps/wolfsshd/wolfsshd
61-
apps/wolfsshd/test/test_configuration
61+
apps/wolfsshd/test/test_configuration.test
6262

6363
# test output
6464
tests/*.test

apps/wolfsshd/auth.c

Lines changed: 8 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -477,8 +477,7 @@ static int ResolveAuthKeysPath(const char* homeDir, char* resolved)
477477
}
478478

479479
static int CheckPublicKeyUnix(const char* name,
480-
const WS_UserAuthData_PublicKey* pubKeyCtx,
481-
const char* usrCaKeysFile)
480+
const WS_UserAuthData_PublicKey* pubKeyCtx)
482481
{
483482
int ret = WSSHD_AUTH_SUCCESS;
484483
int rc;
@@ -493,65 +492,14 @@ static int CheckPublicKeyUnix(const char* name,
493492

494493
#ifdef WOLFSSH_OSSH_CERTS
495494
if (pubKeyCtx->isOsshCert) {
496-
byte* caKey = NULL;
497-
word32 caKeySz;
498-
const byte* caKeyType = NULL;
499-
word32 caKeyTypeSz;
500-
byte fingerprint[WC_SHA256_DIGEST_SIZE];
501-
502-
if (pubKeyCtx->caKey == NULL ||
503-
pubKeyCtx->caKeySz != WC_SHA256_DIGEST_SIZE) {
504-
ret = WS_FATAL_ERROR;
505-
}
506-
507-
if (ret == WSSHD_AUTH_SUCCESS) {
508-
f = XFOPEN(usrCaKeysFile, "rb");
509-
if (f == XBADFILE) {
510-
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Unable to open %s",
511-
usrCaKeysFile);
512-
ret = WS_BAD_FILE_E;
513-
}
514-
}
515-
if (ret == WSSHD_AUTH_SUCCESS) {
516-
lineBuf = (char*)WMALLOC(MAX_LINE_SZ, NULL, DYNTYPE_BUFFER);
517-
if (lineBuf == NULL) {
518-
ret = WS_MEMORY_E;
519-
}
520-
}
521-
while (ret == WSSHD_AUTH_SUCCESS &&
522-
(current = XFGETS(lineBuf, MAX_LINE_SZ, f)) != NULL) {
523-
currentSz = (word32)XSTRLEN(current);
524-
525-
/* remove leading spaces */
526-
while (currentSz > 0 && current[0] == ' ') {
527-
currentSz = currentSz - 1;
528-
current = current + 1;
529-
}
530-
531-
if (currentSz <= 1) {
532-
continue; /* empty line */
533-
}
534-
535-
if (current[0] == '#') {
536-
continue; /* commented out line */
537-
}
538-
539-
rc = wolfSSH_ReadKey_buffer((const byte*)current, currentSz,
540-
WOLFSSH_FORMAT_SSH, &caKey, &caKeySz,
541-
&caKeyType, &caKeyTypeSz, NULL);
542-
if (rc == WS_SUCCESS) {
543-
rc = wc_Hash(WC_HASH_TYPE_SHA256, caKey, caKeySz, fingerprint,
544-
WC_SHA256_DIGEST_SIZE);
545-
if (rc == 0 && WMEMCMP(fingerprint, pubKeyCtx->caKey,
546-
WC_SHA256_DIGEST_SIZE) == 0) {
547-
foundKey = 1;
548-
break;
549-
}
550-
}
551-
}
495+
/*
496+
* wolfSSH proper will have already verified the user's cert if we've
497+
* made it this far. There's no further checking to do in this callback.
498+
*/
499+
foundKey = 1;
552500
}
553501
else
554-
#endif /* WOLFSSH_OSSH_CERTS */
502+
#endif /* WOLFSSH_OSSH_CERTS */
555503
{
556504
errno = 0;
557505
pwInfo = getpwnam((const char*)name);
@@ -632,7 +580,6 @@ static int CheckPublicKeyUnix(const char* name,
632580
WFREE(authKeysFile, NULL, DYNTYPE_STRING);
633581
}
634582

635-
(void)usrCaKeysFile;
636583
return ret;
637584
}
638585
#endif /* !_WIN32*/
@@ -750,8 +697,7 @@ static int RequestAuthentication(WS_UserAuthData* authData,
750697
}
751698
else {
752699
/* if not a certificate then parse through authorized key file */
753-
rc = authCtx->checkPublicKeyCb(usr, &authData->sf.publicKey,
754-
wolfSSHD_ConfigGetUserCAKeysFile(authCtx->conf));
700+
rc = authCtx->checkPublicKeyCb(usr, &authData->sf.publicKey);
755701
if (rc == WSSHD_AUTH_SUCCESS) {
756702
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key ok.");
757703
ret = WOLFSSH_USERAUTH_SUCCESS;

apps/wolfsshd/auth.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ typedef int (*CallbackCheckPassword)(const char* usr, const byte* psw,
5353
* ok, and negative values if an error occurs during checking.
5454
*/
5555
typedef int (*CallbackCheckPublicKey)(const char* usr,
56-
const WS_UserAuthData_PublicKey* pubKey,
57-
const char* usrCaKeysFile);
56+
const WS_UserAuthData_PublicKey* pubKey);
5857

5958
WOLFSSHD_AUTH* wolfSSHD_AuthCreateUser(void* heap, const WOLFSSHD_CONFIG* conf);
6059
int wolfSSHD_AuthFreeUser(WOLFSSHD_AUTH* auth);

apps/wolfsshd/configuration.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -284,16 +284,17 @@ void wolfSSHD_ConfigFree(WOLFSSHD_CONFIG* conf)
284284
while (current != NULL) {
285285
WOLFSSHD_CONFIG* next = current->next;
286286
heap = current->heap;
287-
288-
FreeString(&current->banner, heap);
287+
288+
FreeString(&current->banner, heap);
289289
FreeString(&current->chrootDir, heap);
290-
FreeString(&current->ciphers, heap);
291-
FreeString(&current->kekAlgos, heap);
292-
FreeString(&current->hostKeyAlgos, heap);
290+
FreeString(&current->ciphers, heap);
291+
FreeString(&current->kekAlgos, heap);
292+
FreeString(&current->hostKeyAlgos, heap);
293293
FreeString(&current->listenAddress, heap);
294-
FreeString(&current->authKeysFile, heap);
295-
FreeString(&current->hostKeyFile, heap);
296-
FreeString(&current->hostCertFile, heap);
294+
FreeString(&current->authKeysFile, heap);
295+
FreeString(&current->hostKeyFile, heap);
296+
FreeString(&current->hostCertFile, heap);
297+
FreeString(&current->userCAKeysFile, heap);
297298

298299
WFREE(current, heap, DYNTYPE_SSHD);
299300
current = next;

apps/wolfsshd/include.am

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@ apps_wolfsshd_wolfsshd_SOURCES = apps/wolfsshd/wolfsshd.c \
99
apps_wolfsshd_wolfsshd_LDADD = src/libwolfssh.la
1010
apps_wolfsshd_wolfsshd_DEPENDENCIES = src/libwolfssh.la
1111

12-
noinst_PROGRAMS += apps/wolfsshd/test/test_configuration
13-
apps_wolfsshd_test_test_configuration_SOURCES = apps/wolfsshd/test/test_configuration.c \
12+
noinst_PROGRAMS += apps/wolfsshd/test/test_configuration.test
13+
check_PROGRAMS += apps/wolfsshd/test/test_configuration.test
14+
apps_wolfsshd_test_test_configuration_test_SOURCES = apps/wolfsshd/test/test_configuration.c \
1415
apps/wolfsshd/configuration.c \
1516
apps/wolfsshd/auth.c
16-
apps_wolfsshd_test_test_configuration_LDADD = src/libwolfssh.la
17-
apps_wolfsshd_test_test_configuration_DEPENDENCIES = src/libwolfssh.la
18-
apps_wolfsshd_test_test_configuration_CPPFLAGS = $(AM_CPPFLAGS) -DWOLFSSH_SSHD -DWOLFSSHD_UNIT_TEST -I$(srcdir)/apps/wolfsshd/
17+
18+
apps_wolfsshd_test_test_configuration_test_LDADD = src/libwolfssh.la
19+
apps_wolfsshd_test_test_configuration_test_DEPENDENCIES = src/libwolfssh.la
20+
apps_wolfsshd_test_test_configuration_test_CPPFLAGS = $(AM_CPPFLAGS) -DWOLFSSH_SSHD -DWOLFSSHD_UNIT_TEST -I$(srcdir)/apps/wolfsshd/
1921

2022
DISTCLEANFILES+= apps/wolfsshd/.libs/wolfsshd \
21-
apps/wolfsshd/test/.libs/test_configuration
23+
apps/wolfsshd/test/.libs/test_configuration.test
2224

2325
endif BUILD_SSHD

apps/wolfsshd/wolfsshd.c

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ static void CleanupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
189189
}
190190

191191
#ifndef NO_FILESYSTEM
192-
static void freeBufferFromFile(byte* buf, void* heap)
192+
static void FreeBufferFromFile(byte* buf, void* heap)
193193
{
194194
if (buf != NULL)
195195
WFREE(buf, heap, DYNTYPE_SSHD);
@@ -198,7 +198,7 @@ static void freeBufferFromFile(byte* buf, void* heap)
198198

199199

200200
/* set bufSz to size wanted if too small and buf is null */
201-
static byte* getBufferFromFile(const char* fileName, word32* bufSz, void* heap)
201+
static byte* GetBufferFromFile(const char* fileName, word32* bufSz, void* heap)
202202
{
203203
FILE* file;
204204
byte* buf = NULL;
@@ -282,7 +282,7 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
282282
byte* data;
283283
word32 dataSz = 0;
284284

285-
data = getBufferFromFile(hostKey, &dataSz, heap);
285+
data = GetBufferFromFile(hostKey, &dataSz, heap);
286286
if (data == NULL) {
287287
wolfSSH_Log(WS_LOG_ERROR,
288288
"[SSHD] Error reading host key file.");
@@ -311,22 +311,22 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
311311
ret = WS_BAD_ARGUMENT;
312312
}
313313

314-
freeBufferFromFile(data, heap);
314+
FreeBufferFromFile(data, heap);
315315
wc_FreeDer(&der);
316316
}
317317
}
318318
}
319-
320319
#if defined(WOLFSSH_OSSH_CERTS) || defined(WOLFSSH_CERTS)
321320
if (ret == WS_SUCCESS) {
322-
/* TODO: Create a helper function that uses a file instead. */
323321
char* hostCert = wolfSSHD_ConfigGetHostCertFile(conf);
324322

325323
if (hostCert != NULL) {
326324
byte* data;
327325
word32 dataSz = 0;
328326

329-
data = getBufferFromFile(hostCert, &dataSz, heap);
327+
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Using host cert file %s",
328+
hostCert);
329+
data = GetBufferFromFile(hostCert, &dataSz, heap);
330330
if (data == NULL) {
331331
wolfSSH_Log(WS_LOG_ERROR,
332332
"[SSHD] Error reading host key file.");
@@ -335,44 +335,48 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
335335
}
336336

337337
if (ret == WS_SUCCESS) {
338-
#ifdef WOLFSSH_OPENSSH_CERTS
339-
if (wolfSSH_CTX_UseOsshCert_buffer(*ctx, data, dataSz) < 0) {
340-
wolfSSH_Log(WS_LOG_ERROR,
341-
"[SSHD] Failed to use host certificate.");
342-
ret = WS_BAD_ARGUMENT;
343-
}
344-
#endif
338+
#ifdef WOLFSSH_OSSH_CERTS
339+
ret = wolfSSH_CTX_UseOsshCert_buffer(*ctx, data, dataSz);
340+
/*
341+
* If wolfSSH_CTX_UseOsshCert_buffer failed, the cert might be
342+
* X.509. Try with wolfSSH_CTX_UseCert_buffer.
343+
*/
344+
if (ret != WS_SUCCESS)
345+
#endif /* WOLFSSH_OSSH_CERTS */
346+
{
345347
#ifdef WOLFSSH_CERTS
346-
if (ret == WS_SUCCESS || ret == WS_BAD_ARGUMENT) {
348+
/* Try PEM first. */
347349
ret = wolfSSH_CTX_UseCert_buffer(*ctx, data, dataSz,
348350
WOLFSSH_FORMAT_PEM);
349351
if (ret != WS_SUCCESS) {
352+
/* Try DER (ASN.1) if it wasn't PEM. */
350353
ret = wolfSSH_CTX_UseCert_buffer(*ctx, data, dataSz,
351354
WOLFSSH_FORMAT_ASN1);
352355
}
353-
if (ret != WS_SUCCESS) {
354-
wolfSSH_Log(WS_LOG_ERROR,
355-
"[SSHD] Failed to load in host certificate.");
356-
}
356+
#endif /* WOLFSSH_CERTS */
357+
}
358+
if (ret != WS_SUCCESS) {
359+
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failed to load in host "
360+
"certificate %s.", hostCert);
357361
}
358-
#endif
359362

360-
freeBufferFromFile(data, heap);
363+
FreeBufferFromFile(data, heap);
361364
}
362365
}
363366
}
364367
#endif /* WOLFSSH_OSSH_CERTS || WOLFSSH_CERTS */
365368

366-
#ifdef WOLFSSH_CERTS
369+
#if defined(WOLFSSH_CERTS) || defined(WOLFSSH_OSSH_CERTS)
367370
if (ret == WS_SUCCESS) {
368371
char* caCert = wolfSSHD_ConfigGetUserCAKeysFile(conf);
372+
369373
if (caCert != NULL) {
370374
byte* data;
371375
word32 dataSz = 0;
372376

373-
374-
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Using CA keys file %s", caCert);
375-
data = getBufferFromFile(caCert, &dataSz, heap);
377+
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Using user CA keys file %s",
378+
caCert);
379+
data = GetBufferFromFile(caCert, &dataSz, heap);
376380
if (data == NULL) {
377381
wolfSSH_Log(WS_LOG_ERROR,
378382
"[SSHD] Error reading CA cert file.");
@@ -381,25 +385,32 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
381385
}
382386

383387
if (ret == WS_SUCCESS) {
384-
ret = wolfSSH_CTX_AddRootCert_buffer(*ctx, data, dataSz,
385-
WOLFSSH_FORMAT_PEM);
386-
if (ret != WS_SUCCESS) {
388+
#ifdef WOLFSSH_OSSH_CERTS
389+
ret = wolfSSH_CTX_AddOsshCAKey(*ctx, data, dataSz);
390+
/*
391+
* If wolfSSH_CTX_AddOsshCAKey failed, try
392+
* wolfSSH_CTX_AddRootCert_buffer.
393+
*/
394+
if (ret != WS_SUCCESS)
395+
#endif /* WOLFSSH_OSSH_CERTS */
396+
{
397+
#ifdef WOLFSSH_CERTS
398+
/* Try PEM first. */
387399
ret = wolfSSH_CTX_AddRootCert_buffer(*ctx, data, dataSz,
388-
WOLFSSH_FORMAT_ASN1);
400+
WOLFSSH_FORMAT_PEM);
401+
if (ret != WS_SUCCESS) {
402+
/* Try DER (ASN.1) if it wasn't PEM. */
403+
ret = wolfSSH_CTX_AddRootCert_buffer(*ctx, data, dataSz,
404+
WOLFSSH_FORMAT_ASN1);
405+
}
406+
#endif /* WOLFSSH_CERTS */
389407
}
390408
if (ret != WS_SUCCESS) {
391-
#ifdef WOLFSSH_OPENSSH_CERTS
392-
wolfSSH_Log(WS_LOG_INFO,
393-
"[SSHD] Continuing on in case CA is openssh "
394-
"style.");
395-
ret = WS_SUCCESS;
396-
#else
397-
wolfSSH_Log(WS_LOG_ERROR,
398-
"[SSHD] Failed to load in CA certificate.");
399-
#endif
409+
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failed to load in user CA"
410+
" keys file %s.", caCert);
400411
}
401412

402-
freeBufferFromFile(data, heap);
413+
FreeBufferFromFile(data, heap);
403414
}
404415
}
405416
}

0 commit comments

Comments
 (0)