Added decrypting/decoding/parsing of SPA data.
git-svn-id: file:///home/mbr/svn/fwknop/trunk@24 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
@@ -52,7 +52,7 @@ AC_C_CONST
|
|||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
#
|
#
|
||||||
AC_FUNC_MALLOC
|
AC_FUNC_MALLOC
|
||||||
AC_CHECK_FUNCS([bzero gettimeofday memmove memset setlocale strchr strdup])
|
AC_CHECK_FUNCS([bzero gettimeofday memmove memset strchr strcspn strdup strrchr strspn])
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
fko/Makefile
|
fko/Makefile
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ lib_LTLIBRARIES = libfko.la
|
|||||||
libfko_source_files = \
|
libfko_source_files = \
|
||||||
base64.c base64.h cipher_funcs.c cipher_funcs.h digest.c digest.h \
|
base64.c base64.h cipher_funcs.c cipher_funcs.h digest.c digest.h \
|
||||||
fko_client_timeout.c fko_common.h fko_digest.c fko_encode.c \
|
fko_client_timeout.c fko_common.h fko_digest.c fko_encode.c \
|
||||||
fko_encryption.c fko_error.c fko_funcs.c fko_message.c \
|
fko_decode.c fko_encryption.c fko_error.c fko_funcs.c fko_message.c \
|
||||||
fko_nat_access.c fko_rand_value.c fko_server_auth.c fko.h \
|
fko_nat_access.c fko_rand_value.c fko_server_auth.c fko.h \
|
||||||
fko_timestamp.c fko_types.h fko_user.c fko_util.c fko_util.h \
|
fko_timestamp.c fko_types.h fko_user.c fko_util.c fko_util.h \
|
||||||
md5.c md5.h rijndael.c rijndael.h sha1.c sha256.c sha.h strlcat.c \
|
md5.c md5.h rijndael.c rijndael.h sha1.c sha256.c sha.h strlcat.c \
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ void get_random_data(unsigned char *data, int len)
|
|||||||
* This is is done to be compatible with the data produced via
|
* This is is done to be compatible with the data produced via
|
||||||
* the Perl Crypt::CBC module's use of Rijndael.
|
* the Perl Crypt::CBC module's use of Rijndael.
|
||||||
*/
|
*/
|
||||||
void salt_and_iv(RIJNDAEL_context *ctx, char *pass, unsigned char *data)
|
void salt_and_iv(RIJNDAEL_context *ctx, const char *pass, unsigned char *data)
|
||||||
{
|
{
|
||||||
char pw_buf[16];
|
char pw_buf[16];
|
||||||
unsigned char tmp_buf[64]; /* How big does this need to be? */
|
unsigned char tmp_buf[64]; /* How big does this need to be? */
|
||||||
@@ -132,7 +132,7 @@ void salt_and_iv(RIJNDAEL_context *ctx, char *pass, unsigned char *data)
|
|||||||
|
|
||||||
/* Initialization entry point.
|
/* Initialization entry point.
|
||||||
*/
|
*/
|
||||||
void rijndael_init(RIJNDAEL_context *ctx, char *pass, unsigned char *data)
|
void rijndael_init(RIJNDAEL_context *ctx, const char *pass, unsigned char *data)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Use ECB mode to be compatible with the Crypt::CBC perl module.
|
/* Use ECB mode to be compatible with the Crypt::CBC perl module.
|
||||||
@@ -151,7 +151,7 @@ void rijndael_init(RIJNDAEL_context *ctx, char *pass, unsigned char *data)
|
|||||||
/* Take a chunk of data, encrypt it in the same way the perl Crypt::CBC
|
/* Take a chunk of data, encrypt it in the same way the perl Crypt::CBC
|
||||||
* module would.
|
* module would.
|
||||||
*/
|
*/
|
||||||
int fko_encrypt(unsigned char *in, int in_len, char *pass, unsigned char *out)
|
int fko_encrypt(unsigned char *in, int in_len, const char *pass, unsigned char *out)
|
||||||
{
|
{
|
||||||
RIJNDAEL_context ctx;
|
RIJNDAEL_context ctx;
|
||||||
unsigned char plaintext[16];
|
unsigned char plaintext[16];
|
||||||
@@ -204,7 +204,7 @@ int fko_encrypt(unsigned char *in, int in_len, char *pass, unsigned char *out)
|
|||||||
|
|
||||||
/* Decrypt the given data.
|
/* Decrypt the given data.
|
||||||
*/
|
*/
|
||||||
int fko_decrypt(unsigned char *in, int in_len, char *pass, unsigned char *out)
|
int fko_decrypt(unsigned char *in, int in_len, const char *pass, unsigned char *out)
|
||||||
{
|
{
|
||||||
RIJNDAEL_context ctx;
|
RIJNDAEL_context ctx;
|
||||||
unsigned char plaintext[16];
|
unsigned char plaintext[16];
|
||||||
|
|||||||
@@ -33,8 +33,8 @@
|
|||||||
*/
|
*/
|
||||||
#define PREDICT_ENCSIZE(x) (1+(x>>4)+(x&0xf?1:0))<<4
|
#define PREDICT_ENCSIZE(x) (1+(x>>4)+(x&0xf?1:0))<<4
|
||||||
|
|
||||||
int fko_encrypt(uchar *in, int len, char *key, uchar *out);
|
int fko_encrypt(uchar *in, int len, const char *key, uchar *out);
|
||||||
int fko_decrypt(uchar *in, int len, char *key, uchar *out);
|
int fko_decrypt(uchar *in, int len, const char *key, uchar *out);
|
||||||
void hex_dump(uchar *data, int size);
|
void hex_dump(uchar *data, int size);
|
||||||
|
|
||||||
#endif /* CIPHER_FUNCS_H */
|
#endif /* CIPHER_FUNCS_H */
|
||||||
|
|||||||
@@ -139,7 +139,8 @@ enum {
|
|||||||
FKO_ERROR_INVALID_SPA_ACCESS_MSG,
|
FKO_ERROR_INVALID_SPA_ACCESS_MSG,
|
||||||
FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG,
|
FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG,
|
||||||
FKO_ERROR_INVALID_ENCRYPTION_TYPE,
|
FKO_ERROR_INVALID_ENCRYPTION_TYPE,
|
||||||
/* Add more errors here */
|
FKO_ERROR_DECRYPTION_SIZE_ERROR,
|
||||||
|
/* Add more errors above this line */
|
||||||
FKO_ERROR_UNSUPPORTED_FEATURE,
|
FKO_ERROR_UNSUPPORTED_FEATURE,
|
||||||
FKO_ERROR_UNKNOWN
|
FKO_ERROR_UNKNOWN
|
||||||
};
|
};
|
||||||
@@ -162,6 +163,7 @@ enum {
|
|||||||
#define MAX_SPA_SERVER_AUTH_SIZE 64
|
#define MAX_SPA_SERVER_AUTH_SIZE 64
|
||||||
|
|
||||||
#define MIN_SPA_ENCODED_MSG_SIZE 36 /* Somewhat arbitrary */
|
#define MIN_SPA_ENCODED_MSG_SIZE 36 /* Somewhat arbitrary */
|
||||||
|
#define MIN_GNUPG_MSG_SIZE 400
|
||||||
|
|
||||||
/* Misc.
|
/* Misc.
|
||||||
*/
|
*/
|
||||||
@@ -202,6 +204,7 @@ typedef struct _fko_ctx {
|
|||||||
/* Function prototypes
|
/* Function prototypes
|
||||||
*/
|
*/
|
||||||
int fko_new(fko_ctx_t *ctx);
|
int fko_new(fko_ctx_t *ctx);
|
||||||
|
int fko_new_with_data(fko_ctx_t *ctx, char *enc_data);
|
||||||
void fko_destroy(fko_ctx_t *ctx);
|
void fko_destroy(fko_ctx_t *ctx);
|
||||||
|
|
||||||
char* fko_version(fko_ctx_t *ctx);
|
char* fko_version(fko_ctx_t *ctx);
|
||||||
@@ -235,7 +238,7 @@ int fko_encode_spa_data(fko_ctx_t *ctx);
|
|||||||
int fko_decode_spa_data(fko_ctx_t *ctx);
|
int fko_decode_spa_data(fko_ctx_t *ctx);
|
||||||
|
|
||||||
int fko_encrypt_spa_data(fko_ctx_t *ctx, const char *enc_key);
|
int fko_encrypt_spa_data(fko_ctx_t *ctx, const char *enc_key);
|
||||||
int fko_decrypt_spa_data(fko_ctx_t *ctx, unsigned char *data, int size);
|
int fko_decrypt_spa_data(fko_ctx_t *ctx, const char *dec_key);
|
||||||
|
|
||||||
|
|
||||||
#endif /* FKO_H */
|
#endif /* FKO_H */
|
||||||
|
|||||||
305
fko/fko_decode.c
Normal file
305
fko/fko_decode.c
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
/* $Id$
|
||||||
|
*****************************************************************************
|
||||||
|
*
|
||||||
|
* File: fko_decode.c
|
||||||
|
*
|
||||||
|
* Author: Damien S. Stuart
|
||||||
|
*
|
||||||
|
* Purpose: Decrypt and decode an FKO SPA message.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Damien Stuart (dstuart@dstuart.org)
|
||||||
|
*
|
||||||
|
* License (GNU Public License):
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
*/
|
||||||
|
#include "fko_common.h"
|
||||||
|
#include "fko.h"
|
||||||
|
#include "cipher_funcs.h"
|
||||||
|
#include "base64.h"
|
||||||
|
#include "digest.h"
|
||||||
|
|
||||||
|
/* Decrypt the encoded SPA data.
|
||||||
|
*/
|
||||||
|
int fko_decode_spa_data(fko_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
char *tbuf, *ndx;
|
||||||
|
//int cipher_len, res;
|
||||||
|
int edata_size, t_size;
|
||||||
|
|
||||||
|
/* Check for required data.
|
||||||
|
*/
|
||||||
|
if(ctx->encoded_msg == NULL
|
||||||
|
|| strlen(ctx->encoded_msg) < MIN_SPA_ENCODED_MSG_SIZE)
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
|
||||||
|
edata_size = strlen(ctx->encoded_msg);
|
||||||
|
|
||||||
|
/* Move the Digest to its place in the context.
|
||||||
|
*/
|
||||||
|
ndx = strrchr(ctx->encoded_msg, ':'); /* Find the last : in the data */
|
||||||
|
if(ndx == NULL)
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
|
||||||
|
ndx++;
|
||||||
|
|
||||||
|
t_size = strlen(ndx);
|
||||||
|
|
||||||
|
switch(t_size)
|
||||||
|
{
|
||||||
|
case MD_B64_SIZE(MD5_DIGESTSIZE):
|
||||||
|
ctx->digest_type = FKO_DIGEST_MD5;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MD_B64_SIZE(SHA1_DIGESTSIZE):
|
||||||
|
ctx->digest_type = FKO_DIGEST_SHA1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MD_B64_SIZE(SHA256_DIGESTSIZE):
|
||||||
|
ctx->digest_type = FKO_DIGEST_SHA256;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* Invalid or unsupported digest */
|
||||||
|
return(FKO_ERROR_INVALID_DIGEST_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the digest into the context and terminate the encoded data
|
||||||
|
* at that point so the original digest is not part of the
|
||||||
|
* encoded string.
|
||||||
|
*/
|
||||||
|
if((ctx->digest = strdup(ndx)) == NULL)
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
|
||||||
|
/* Zero out the rest of the encoded_msg bucket...
|
||||||
|
*/
|
||||||
|
bzero((ndx-1), t_size);
|
||||||
|
|
||||||
|
/* Now we will work through the encoded data and extract (and base64-
|
||||||
|
* decode where necessary), the SPA data fields and populate the context.
|
||||||
|
*/
|
||||||
|
ndx = ctx->encoded_msg;
|
||||||
|
|
||||||
|
/* The rand val data */
|
||||||
|
if((t_size = strcspn(ndx, ":")) < FKO_RAND_VAL_SIZE)
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
|
||||||
|
strlcpy(ctx->rand_val, ndx, FKO_RAND_VAL_SIZE+1);
|
||||||
|
|
||||||
|
/* Make a tmp bucket for processinv base64 encoded data.
|
||||||
|
*/
|
||||||
|
if((tbuf = malloc(FKO_ENCODE_TMP_BUF_SIZE)) == NULL)
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
|
||||||
|
/* Jump to the next field (username). We need to use the temp buffer
|
||||||
|
* for the base64 decode step.
|
||||||
|
*/
|
||||||
|
ndx += t_size + 1;
|
||||||
|
if((t_size = strcspn(ndx, ":")) < 1)
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(tbuf, ndx, t_size+1);
|
||||||
|
|
||||||
|
if((ctx->username = malloc(t_size+1)) == NULL) /* Yes, more than we need */
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
b64_decode(tbuf, (unsigned char*)ctx->username, t_size);
|
||||||
|
|
||||||
|
/* Extract the timestamp value.
|
||||||
|
*/
|
||||||
|
ndx += t_size + 1;
|
||||||
|
if((t_size = strcspn(ndx, ":")) < 1)
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(tbuf, ndx, t_size+1);
|
||||||
|
|
||||||
|
ctx->timestamp = (unsigned int)atoi(tbuf);
|
||||||
|
|
||||||
|
/* Extract the version string.
|
||||||
|
*/
|
||||||
|
ndx += t_size + 1;
|
||||||
|
if((t_size = strcspn(ndx, ":")) < 1)
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((ctx->version = malloc(t_size+1)) == NULL)
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(ctx->version, ndx, t_size+1);
|
||||||
|
|
||||||
|
/* Extract the message type value.
|
||||||
|
*/
|
||||||
|
ndx += t_size + 1;
|
||||||
|
if((t_size = strcspn(ndx, ":")) < 1)
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(tbuf, ndx, t_size+1);
|
||||||
|
|
||||||
|
ctx->message_type = (unsigned int)atoi(tbuf);
|
||||||
|
|
||||||
|
/* Extract the SPA message string.
|
||||||
|
*/
|
||||||
|
ndx += t_size + 1;
|
||||||
|
if((t_size = strcspn(ndx, ":")) < 1)
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(tbuf, ndx, t_size+1);
|
||||||
|
|
||||||
|
if((ctx->message = malloc(t_size+1)) == NULL) /* Yes, more than we need */
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
b64_decode(tbuf, (unsigned char*)ctx->message, t_size);
|
||||||
|
|
||||||
|
/* Extract nat_access string if the message_type indicates so.
|
||||||
|
*/
|
||||||
|
if( ctx->message_type == FKO_NAT_ACCESS_MSG
|
||||||
|
|| ctx->message_type == FKO_LOCAL_NAT_ACCESS_MSG
|
||||||
|
|| ctx->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG
|
||||||
|
|| ctx->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG)
|
||||||
|
{
|
||||||
|
ndx += t_size + 1;
|
||||||
|
if((t_size = strcspn(ndx, ":")) < 1)
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(tbuf, ndx, t_size+1);
|
||||||
|
|
||||||
|
if((ctx->nat_access = malloc(t_size+1)) == NULL) /* Yes, more than we need */
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
b64_decode(tbuf, (unsigned char*)ctx->nat_access, t_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now look for a server_auth string.
|
||||||
|
*/
|
||||||
|
ndx += t_size + 1;
|
||||||
|
if((t_size = strlen(ndx)) > 0)
|
||||||
|
{
|
||||||
|
/* There is data, but what is it?
|
||||||
|
* If the message_type does not have a timeout, assume it is a
|
||||||
|
* server_auth field.
|
||||||
|
*/
|
||||||
|
if( ctx->message_type != FKO_CLIENT_TIMEOUT_ACCESS_MSG
|
||||||
|
&& ctx->message_type != FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG
|
||||||
|
&& ctx->message_type != FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG)
|
||||||
|
{
|
||||||
|
strlcpy(tbuf, ndx, t_size+1);
|
||||||
|
|
||||||
|
if((ctx->server_auth = malloc(t_size+1)) == NULL) /* Yes, more than we need */
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
b64_decode(tbuf, (unsigned char*)ctx->server_auth, t_size);
|
||||||
|
|
||||||
|
/* At this point we should be done.
|
||||||
|
*/
|
||||||
|
free(tbuf);
|
||||||
|
|
||||||
|
/* Call the context initialized.
|
||||||
|
*/
|
||||||
|
ctx->initval = FKO_CTX_INITIALIZED;
|
||||||
|
FKO_SET_CTX_INITIALIZED(ctx);
|
||||||
|
|
||||||
|
return(FKO_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are here then we may still have a server_auth string,
|
||||||
|
* or a timeout, or both. So we look for a ':' delimiter. If
|
||||||
|
* it is there we have both, if not we check the message_type
|
||||||
|
* again.
|
||||||
|
*/
|
||||||
|
if(strchr(ndx, ':'))
|
||||||
|
{
|
||||||
|
t_size = strcspn(ndx, ":");
|
||||||
|
|
||||||
|
/* Looks like we have both, so assume this is the
|
||||||
|
*/
|
||||||
|
strlcpy(tbuf, ndx, t_size+1);
|
||||||
|
|
||||||
|
if((ctx->server_auth = malloc(t_size+1)) == NULL) /* Yes, more than we need */
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
b64_decode(tbuf, (unsigned char*)ctx->server_auth, t_size);
|
||||||
|
|
||||||
|
ndx += t_size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we look for a timeout value if one is supposed to be there.
|
||||||
|
*/
|
||||||
|
if( ctx->message_type == FKO_CLIENT_TIMEOUT_ACCESS_MSG
|
||||||
|
|| ctx->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG
|
||||||
|
|| ctx->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG)
|
||||||
|
{
|
||||||
|
if((t_size = strlen(ndx)) < 1)
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should be a number only.
|
||||||
|
*/
|
||||||
|
if(strspn(ndx, "0123456789") != t_size)
|
||||||
|
{
|
||||||
|
free(tbuf);
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->client_timeout = (unsigned int)atoi(ndx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done with the tmp buffer.
|
||||||
|
*/
|
||||||
|
free(tbuf);
|
||||||
|
|
||||||
|
/* Call the context initialized.
|
||||||
|
*/
|
||||||
|
ctx->initval = FKO_CTX_INITIALIZED;
|
||||||
|
FKO_SET_CTX_INITIALIZED(ctx);
|
||||||
|
|
||||||
|
return(FKO_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***EOF***/
|
||||||
@@ -137,13 +137,13 @@ int fko_encode_spa_data(fko_ctx_t *ctx)
|
|||||||
|
|
||||||
/* If we have a server_auth field set. Add it here.
|
/* If we have a server_auth field set. Add it here.
|
||||||
*
|
*
|
||||||
|
*/
|
||||||
if(ctx->server_auth != NULL)
|
if(ctx->server_auth != NULL)
|
||||||
{
|
{
|
||||||
strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE);
|
strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE);
|
||||||
if((res = append_b64(tbuf, ctx->server_auth)) != FKO_SUCCESS)
|
if((res = append_b64(tbuf, ctx->server_auth)) != FKO_SUCCESS)
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/* If a client timeout is specified and we are not dealing with a
|
/* If a client timeout is specified and we are not dealing with a
|
||||||
* SPA command message, add the timeout here.
|
* SPA command message, add the timeout here.
|
||||||
@@ -179,19 +179,5 @@ int fko_encode_spa_data(fko_ctx_t *ctx)
|
|||||||
return(FKO_SUCCESS);
|
return(FKO_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the SPA encryption type.
|
|
||||||
*/
|
|
||||||
int fko_decode_spa_data(fko_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
/* Must be initialized
|
|
||||||
*/
|
|
||||||
if(!CTX_INITIALIZED(ctx))
|
|
||||||
return(FKO_ERROR_CTX_NOT_INITIALIZED);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return(FKO_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***EOF***/
|
/***EOF***/
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
#include "cipher_funcs.h"
|
#include "cipher_funcs.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
|
||||||
|
#define B64_RIJNDAEL_SALT "U2FsdGVkX1"
|
||||||
|
|
||||||
/* Set the SPA encryption type.
|
/* Set the SPA encryption type.
|
||||||
*/
|
*/
|
||||||
int fko_set_spa_encryption_type(fko_ctx_t *ctx, short encrypt_type)
|
int fko_set_spa_encryption_type(fko_ctx_t *ctx, short encrypt_type)
|
||||||
@@ -130,4 +132,78 @@ int fko_encrypt_spa_data(fko_ctx_t *ctx, const char *enc_key)
|
|||||||
return(FKO_SUCCESS);
|
return(FKO_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Decode, decrypt, and parse SPA data into the context.
|
||||||
|
*/
|
||||||
|
int fko_decrypt_spa_data(fko_ctx_t *ctx, const char *dec_key)
|
||||||
|
{
|
||||||
|
char *tbuf;
|
||||||
|
unsigned char *cipher;
|
||||||
|
int b64_len, cipher_len, pt_len;
|
||||||
|
|
||||||
|
/* First, make sure we have data to work with.
|
||||||
|
*/
|
||||||
|
if(ctx->encrypted_msg == NULL
|
||||||
|
|| strlen(ctx->encrypted_msg) < MIN_SPA_ENCODED_MSG_SIZE)
|
||||||
|
return(FKO_ERROR_INVALID_DATA);
|
||||||
|
|
||||||
|
/* Determine type of encryption used. For know, we are using the
|
||||||
|
* size of the message. However, we will want to come up with a
|
||||||
|
* more reliable method of identification.
|
||||||
|
*/
|
||||||
|
b64_len = strlen(ctx->encrypted_msg);
|
||||||
|
|
||||||
|
if(b64_len > MIN_GNUPG_MSG_SIZE)
|
||||||
|
{
|
||||||
|
/* TODO: add GPG handling */
|
||||||
|
/* Since we do not support GPG yet, we will just fall through */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assuming Rijndael */
|
||||||
|
|
||||||
|
/* Now see if we need to add the "Salted__" string to the front of the
|
||||||
|
* encrypted data.
|
||||||
|
*/
|
||||||
|
if(strncmp(ctx->encrypted_msg, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT)))
|
||||||
|
{
|
||||||
|
/* We need to realloc space for the salt.
|
||||||
|
*/
|
||||||
|
tbuf = realloc(ctx->encrypted_msg, b64_len + 12);
|
||||||
|
if(tbuf == NULL)
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
|
||||||
|
memmove(tbuf+10, tbuf, b64_len);
|
||||||
|
ctx->encrypted_msg = memcpy(tbuf, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a bucket for the (base64) decoded encrypted data and get the
|
||||||
|
* raw cipher data.
|
||||||
|
*/
|
||||||
|
if((cipher = malloc(strlen(ctx->encrypted_msg))) == NULL)
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
|
||||||
|
cipher_len = b64_decode(ctx->encrypted_msg, cipher, b64_len);
|
||||||
|
|
||||||
|
/* Create a bucket for the plaintext data and decrypt the message
|
||||||
|
* data into it.
|
||||||
|
*/
|
||||||
|
if((ctx->encoded_msg = malloc(cipher_len)) == NULL)
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
|
||||||
|
pt_len = fko_decrypt(cipher, cipher_len, dec_key, (unsigned char*)ctx->encoded_msg);
|
||||||
|
|
||||||
|
/* Done with cipher...
|
||||||
|
*/
|
||||||
|
free(cipher);
|
||||||
|
|
||||||
|
/* The length of the decrypted data should be within 16 of the
|
||||||
|
* length of the encrypted version.
|
||||||
|
*/
|
||||||
|
if(pt_len < (cipher_len - 32))
|
||||||
|
return(FKO_ERROR_DECRYPTION_SIZE_ERROR);
|
||||||
|
|
||||||
|
/* Call fko_decode and return the results.
|
||||||
|
*/
|
||||||
|
return(fko_decode_spa_data(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
/***EOF***/
|
/***EOF***/
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ static const char *fko_err_msgs[] = {
|
|||||||
"Success",
|
"Success",
|
||||||
"FKO Context is not initialized",
|
"FKO Context is not initialized",
|
||||||
"Unable to allocate memory",
|
"Unable to allocate memory",
|
||||||
"Args contains invalid data",
|
"Args contain invalid data",
|
||||||
"Value or Size of the data exceeded the max allowed",
|
"Value or Size of the data exceeded the max allowed",
|
||||||
"Unable to determine username",
|
"Unable to determine username",
|
||||||
"Missing or incomplete SPA data",
|
"Missing or incomplete SPA data",
|
||||||
@@ -44,7 +44,8 @@ static const char *fko_err_msgs[] = {
|
|||||||
"Invalid SPA access mesage format",
|
"Invalid SPA access mesage format",
|
||||||
"Invalid SPA nat_access mesage format",
|
"Invalid SPA nat_access mesage format",
|
||||||
"Invalid encryption type",
|
"Invalid encryption type",
|
||||||
"Unsupported or unimplemented feature or function.",
|
"Unexpected or invalid size for decrypted data",
|
||||||
|
"Unsupported or unimplemented feature or function",
|
||||||
"Unknown/Unclassified error",
|
"Unknown/Unclassified error",
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,6 +26,11 @@
|
|||||||
#include "fko_common.h"
|
#include "fko_common.h"
|
||||||
#include "fko.h"
|
#include "fko.h"
|
||||||
|
|
||||||
|
/* The base64 encoded version of "Salted__" that may be found at the head
|
||||||
|
* of Rijndael encrypted data.
|
||||||
|
*/
|
||||||
|
#define B64_RIJNDAEL_SALT "U2FsdGVkX1"
|
||||||
|
|
||||||
/* Initialize an fko context.
|
/* Initialize an fko context.
|
||||||
*/
|
*/
|
||||||
int fko_new(fko_ctx_t *ctx)
|
int fko_new(fko_ctx_t *ctx)
|
||||||
@@ -113,6 +118,26 @@ int fko_new(fko_ctx_t *ctx)
|
|||||||
return(FKO_SUCCESS);
|
return(FKO_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize an fko context with external (encrypted/encoded) data.
|
||||||
|
* This is used to create a context with the purpose of decoding
|
||||||
|
* and parsing the provided data into the context data.
|
||||||
|
*/
|
||||||
|
int fko_new_with_data(fko_ctx_t *ctx, char *enc_msg)
|
||||||
|
{
|
||||||
|
/* Zero out the context...
|
||||||
|
*/
|
||||||
|
bzero(ctx, sizeof(fko_ctx_t));
|
||||||
|
|
||||||
|
/* First, add the data to the context.
|
||||||
|
*/
|
||||||
|
if((ctx->encrypted_msg = strdup(enc_msg)) == NULL)
|
||||||
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
|
||||||
|
FKO_SET_CTX_INITIALIZED(ctx);
|
||||||
|
|
||||||
|
return(FKO_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
/* Destroy a context and free its resources
|
/* Destroy a context and free its resources
|
||||||
*/
|
*/
|
||||||
void fko_destroy(fko_ctx_t *ctx)
|
void fko_destroy(fko_ctx_t *ctx)
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ int validate_access_msg(const char *msg)
|
|||||||
&& strncmp(ndx, "none", 4))
|
&& strncmp(ndx, "none", 4))
|
||||||
return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
|
return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
|
||||||
|
|
||||||
ndx = strchr(ndx, ',');
|
ndx = strchr(ndx, '/');
|
||||||
if(ndx == NULL || (1+(ndx - msg)) >= startlen)
|
if(ndx == NULL || (1+(ndx - msg)) >= startlen)
|
||||||
return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
|
return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,20 @@ int fko_set_spa_nat_access(fko_ctx_t *ctx, const char *msg)
|
|||||||
if(ctx->nat_access == NULL)
|
if(ctx->nat_access == NULL)
|
||||||
return(FKO_ERROR_MEMORY_ALLOCATION);
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
|
||||||
|
/* If we set the nat_access message Then we force the message_type
|
||||||
|
* as well. Technically, the message type should be set already.
|
||||||
|
* This will serve a half-protective measure.
|
||||||
|
* --DSS XXX: should do this better.
|
||||||
|
*/
|
||||||
|
if(ctx->client_timeout > 0)
|
||||||
|
{
|
||||||
|
if(ctx->message_type != FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG)
|
||||||
|
ctx->message_type = FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(ctx->message_type != FKO_LOCAL_NAT_ACCESS_MSG)
|
||||||
|
ctx->message_type = FKO_NAT_ACCESS_MSG;
|
||||||
|
|
||||||
return(FKO_SUCCESS);
|
return(FKO_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ int fko_set_spa_server_auth(fko_ctx_t *ctx, const char *msg)
|
|||||||
* --DSS This is not supported yet
|
* --DSS This is not supported yet
|
||||||
****************************************
|
****************************************
|
||||||
*/
|
*/
|
||||||
return(FKO_ERROR_UNSUPPORTED_FEATURE);
|
//return(FKO_ERROR_UNSUPPORTED_FEATURE);
|
||||||
|
|
||||||
|
|
||||||
/* Context must be initialized.
|
/* Context must be initialized.
|
||||||
|
|||||||
34
src/fwknop.c
34
src/fwknop.c
@@ -32,7 +32,7 @@ void hex_dump(unsigned char *data, int size);
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
fko_ctx_t ctx;
|
fko_ctx_t ctx, ctx2;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
/* Intialize the context */
|
/* Intialize the context */
|
||||||
@@ -40,17 +40,26 @@ int main(int argc, char **argv)
|
|||||||
if(res != FKO_SUCCESS)
|
if(res != FKO_SUCCESS)
|
||||||
fprintf(stderr, "Error #%i from fko_new: %s\n", res, fko_errstr(res));
|
fprintf(stderr, "Error #%i from fko_new: %s\n", res, fko_errstr(res));
|
||||||
|
|
||||||
|
res = fko_set_spa_message_type(&ctx, FKO_ACCESS_MSG);
|
||||||
|
if(res != FKO_SUCCESS)
|
||||||
|
fprintf(stderr, "Error #%i from fko_set_spa_message_type: %s\n", res, fko_errstr(res));
|
||||||
|
|
||||||
/* Set a message string */
|
/* Set a message string */
|
||||||
res = fko_set_spa_message(&ctx, "192.168.1.5,tcp,22");
|
res = fko_set_spa_message(&ctx, "0.0.0.0,tcp/22");
|
||||||
if(res != FKO_SUCCESS)
|
if(res != FKO_SUCCESS)
|
||||||
fprintf(stderr, "Error #%i from fko_set_spa_message: %s\n", res, fko_errstr(res));
|
fprintf(stderr, "Error #%i from fko_set_spa_message: %s\n", res, fko_errstr(res));
|
||||||
|
|
||||||
//fko_set_spa_digest_type(&ctx, FKO_DIGEST_SHA1);
|
//fko_set_spa_digest_type(&ctx, FKO_DIGEST_SHA1);
|
||||||
fko_set_spa_client_timeout(&ctx, 300);
|
|
||||||
|
|
||||||
//res = fko_set_spa_server_auth(&ctx, "crypt,BubbaWasHere");
|
res = fko_set_spa_nat_access(&ctx, "192.168.1.2,22");
|
||||||
//if(res != FKO_SUCCESS)
|
if(res != FKO_SUCCESS)
|
||||||
// fprintf(stderr, "Error #%i from fko_set_spa_server_auth: %s\n", res, fko_errstr(res));
|
fprintf(stderr, "Error #%i from fko_set_spa_nat_access: %s\n", res, fko_errstr(res));
|
||||||
|
|
||||||
|
fko_set_spa_client_timeout(&ctx, 120);
|
||||||
|
|
||||||
|
res = fko_set_spa_server_auth(&ctx, "crypt,BubbaWasHere");
|
||||||
|
if(res != FKO_SUCCESS)
|
||||||
|
fprintf(stderr, "Error #%i from fko_set_spa_server_auth: %s\n", res, fko_errstr(res));
|
||||||
|
|
||||||
/* Encode the SPA data
|
/* Encode the SPA data
|
||||||
res = fko_encode_spa_data(&ctx);
|
res = fko_encode_spa_data(&ctx);
|
||||||
@@ -68,7 +77,20 @@ int main(int argc, char **argv)
|
|||||||
//printf("\nHex dump of fko_ctx:\n====================\n");
|
//printf("\nHex dump of fko_ctx:\n====================\n");
|
||||||
//hex_dump((unsigned char*)&ctx, sizeof(fko_ctx_t));
|
//hex_dump((unsigned char*)&ctx, sizeof(fko_ctx_t));
|
||||||
|
|
||||||
|
/* Now we create a new context based on data from the first one.
|
||||||
|
*/
|
||||||
|
res = fko_new_with_data(&ctx2, ctx.encrypted_msg);
|
||||||
|
if(res != FKO_SUCCESS)
|
||||||
|
fprintf(stderr, "Error #%i from fko_new_with_data: %s\n", res, fko_errstr(res));
|
||||||
|
|
||||||
|
res = fko_decrypt_spa_data(&ctx2, "BubbaWasHere");
|
||||||
|
if(res != FKO_SUCCESS)
|
||||||
|
fprintf(stderr, "Error #%i from fko_decrypt_spa_data: %s\n", res, fko_errstr(res));
|
||||||
|
|
||||||
|
display_ctx(&ctx2);
|
||||||
|
|
||||||
fko_destroy(&ctx);
|
fko_destroy(&ctx);
|
||||||
|
fko_destroy(&ctx2);
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user