diff --git a/configure.ac b/configure.ac index af22a9d3..9c17720b 100644 --- a/configure.ac +++ b/configure.ac @@ -52,7 +52,7 @@ AC_C_CONST # Checks for library functions. # 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 fko/Makefile diff --git a/fko/Makefile.am b/fko/Makefile.am index e575ec52..d6325d97 100644 --- a/fko/Makefile.am +++ b/fko/Makefile.am @@ -3,7 +3,7 @@ lib_LTLIBRARIES = libfko.la libfko_source_files = \ 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_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_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 \ diff --git a/fko/cipher_funcs.c b/fko/cipher_funcs.c index 97bee80d..e593e00e 100644 --- a/fko/cipher_funcs.c +++ b/fko/cipher_funcs.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 * 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]; 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. */ -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. @@ -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 * 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; 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. */ -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; unsigned char plaintext[16]; diff --git a/fko/cipher_funcs.h b/fko/cipher_funcs.h index f5a27df3..532dfc78 100644 --- a/fko/cipher_funcs.h +++ b/fko/cipher_funcs.h @@ -33,8 +33,8 @@ */ #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_decrypt(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, const char *key, uchar *out); void hex_dump(uchar *data, int size); #endif /* CIPHER_FUNCS_H */ diff --git a/fko/fko.h b/fko/fko.h index 2bd79efc..5b26f951 100644 --- a/fko/fko.h +++ b/fko/fko.h @@ -139,7 +139,8 @@ enum { FKO_ERROR_INVALID_SPA_ACCESS_MSG, FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG, 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_UNKNOWN }; @@ -162,6 +163,7 @@ enum { #define MAX_SPA_SERVER_AUTH_SIZE 64 #define MIN_SPA_ENCODED_MSG_SIZE 36 /* Somewhat arbitrary */ +#define MIN_GNUPG_MSG_SIZE 400 /* Misc. */ @@ -202,6 +204,7 @@ typedef struct _fko_ctx { /* Function prototypes */ 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); 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_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 */ diff --git a/fko/fko_decode.c b/fko/fko_decode.c new file mode 100644 index 00000000..e7c15590 --- /dev/null +++ b/fko/fko_decode.c @@ -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***/ diff --git a/fko/fko_encode.c b/fko/fko_encode.c index e396cafe..3ef76128 100644 --- a/fko/fko_encode.c +++ b/fko/fko_encode.c @@ -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(ctx->server_auth != NULL) { strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE); if((res = append_b64(tbuf, ctx->server_auth)) != FKO_SUCCESS) return(res); } - */ /* If a client timeout is specified and we are not dealing with a * SPA command message, add the timeout here. @@ -179,19 +179,5 @@ int fko_encode_spa_data(fko_ctx_t *ctx) 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***/ diff --git a/fko/fko_encryption.c b/fko/fko_encryption.c index cc1b3f4e..0d7b5dae 100644 --- a/fko/fko_encryption.c +++ b/fko/fko_encryption.c @@ -28,6 +28,8 @@ #include "cipher_funcs.h" #include "base64.h" +#define B64_RIJNDAEL_SALT "U2FsdGVkX1" + /* Set the SPA encryption 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); } +/* 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***/ diff --git a/fko/fko_error.c b/fko/fko_error.c index 58ab41eb..ed341379 100644 --- a/fko/fko_error.c +++ b/fko/fko_error.c @@ -33,7 +33,7 @@ static const char *fko_err_msgs[] = { "Success", "FKO Context is not initialized", "Unable to allocate memory", - "Args contains invalid data", + "Args contain invalid data", "Value or Size of the data exceeded the max allowed", "Unable to determine username", "Missing or incomplete SPA data", @@ -44,7 +44,8 @@ static const char *fko_err_msgs[] = { "Invalid SPA access mesage format", "Invalid SPA nat_access mesage format", "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", 0 }; diff --git a/fko/fko_funcs.c b/fko/fko_funcs.c index 05d9accc..9ea11958 100644 --- a/fko/fko_funcs.c +++ b/fko/fko_funcs.c @@ -26,6 +26,11 @@ #include "fko_common.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. */ int fko_new(fko_ctx_t *ctx) @@ -113,6 +118,26 @@ int fko_new(fko_ctx_t *ctx) 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 */ void fko_destroy(fko_ctx_t *ctx) diff --git a/fko/fko_message.c b/fko/fko_message.c index a53ffdf1..abb85d24 100644 --- a/fko/fko_message.c +++ b/fko/fko_message.c @@ -194,7 +194,7 @@ int validate_access_msg(const char *msg) && strncmp(ndx, "none", 4)) return(FKO_ERROR_INVALID_SPA_ACCESS_MSG); - ndx = strchr(ndx, ','); + ndx = strchr(ndx, '/'); if(ndx == NULL || (1+(ndx - msg)) >= startlen) return(FKO_ERROR_INVALID_SPA_ACCESS_MSG); diff --git a/fko/fko_nat_access.c b/fko/fko_nat_access.c index 3b9624d6..ddca9a78 100644 --- a/fko/fko_nat_access.c +++ b/fko/fko_nat_access.c @@ -59,6 +59,20 @@ int fko_set_spa_nat_access(fko_ctx_t *ctx, const char *msg) if(ctx->nat_access == NULL) 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); } diff --git a/fko/fko_server_auth.c b/fko/fko_server_auth.c index d09fab53..e24c6c58 100644 --- a/fko/fko_server_auth.c +++ b/fko/fko_server_auth.c @@ -34,7 +34,7 @@ int fko_set_spa_server_auth(fko_ctx_t *ctx, const char *msg) * --DSS This is not supported yet **************************************** */ - return(FKO_ERROR_UNSUPPORTED_FEATURE); + //return(FKO_ERROR_UNSUPPORTED_FEATURE); /* Context must be initialized. diff --git a/src/fwknop.c b/src/fwknop.c index 7f63aa9e..bc45bf9e 100644 --- a/src/fwknop.c +++ b/src/fwknop.c @@ -32,7 +32,7 @@ void hex_dump(unsigned char *data, int size); int main(int argc, char **argv) { - fko_ctx_t ctx; + fko_ctx_t ctx, ctx2; int res; /* Intialize the context */ @@ -40,17 +40,26 @@ int main(int argc, char **argv) if(res != FKO_SUCCESS) 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 */ - 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) 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_client_timeout(&ctx, 300); - //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)); + res = fko_set_spa_nat_access(&ctx, "192.168.1.2,22"); + if(res != FKO_SUCCESS) + 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 res = fko_encode_spa_data(&ctx); @@ -68,7 +77,20 @@ int main(int argc, char **argv) //printf("\nHex dump of fko_ctx:\n====================\n"); //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(&ctx2); return(0); }