diff --git a/client/cmd_opts.h b/client/cmd_opts.h index cd042c15..ab2f8f4a 100644 --- a/client/cmd_opts.h +++ b/client/cmd_opts.h @@ -35,6 +35,7 @@ */ enum { FKO_DIGEST_NAME = 0x100, + ENCRYPTION_MODE, NAT_LOCAL, NAT_PORT, NAT_RAND_PORT, @@ -55,7 +56,7 @@ enum { /* Our getopt_long options string. */ -#define GETOPTS_OPTION_STRING "a:A:bB:C:D:f:gG:hH:lm:n:N:p:P:Q:rRsS:Tu:U:vV" +#define GETOPTS_OPTION_STRING "a:A:bB:C:D:f:gG:hH:lm:M:n:N:p:P:Q:rRsS:Tu:U:vV" /* Our program command-line options... */ @@ -69,6 +70,7 @@ static struct option cmd_opts[] = {"server-cmd", 1, NULL, 'C'}, {"digest-type", 1, NULL, FKO_DIGEST_NAME}, {"destination", 1, NULL, 'D'}, + {"encryption-mode", 1, NULL, ENCRYPTION_MODE}, {"fw-timeout", 1, NULL, 'f'}, {"gpg-encryption", 0, NULL, 'g'}, {"gpg-recipient-key", 1, NULL, GPG_RECIP_KEY }, diff --git a/client/config_init.c b/client/config_init.c index f0cd41b7..e97ea0eb 100644 --- a/client/config_init.c +++ b/client/config_init.c @@ -33,9 +33,9 @@ #include "cmd_opts.h" #include "utils.h" -/* Convert a digest_type string to its intger value. +/* Convert a digest_type string to its integer value. */ -static int +static short digest_strtoint(const char *dt_str) { if(strcasecmp(dt_str, "md5") == 0) @@ -52,7 +52,28 @@ digest_strtoint(const char *dt_str) return(-1); } -/* Convert a protocol string to its intger value. +/* Convert an encryption_mode string to its integer value. +*/ +static int +enc_mode_strtoint(const char *enc_mode_str) +{ + if(strcasecmp(enc_mode_str, "cbc") == 0) + return(FKO_ENC_MODE_CBC); + else if(strcasecmp(enc_mode_str, "ecb") == 0) + return(FKO_ENC_MODE_ECB); + else if(strcasecmp(enc_mode_str, "cfb") == 0) + return(FKO_ENC_MODE_CFB); + else if(strcasecmp(enc_mode_str, "pcbc") == 0) + return(FKO_ENC_MODE_PCBC); + else if(strcasecmp(enc_mode_str, "ofb") == 0) + return(FKO_ENC_MODE_OFB); + else if(strcasecmp(enc_mode_str, "ctr") == 0) + return(FKO_ENC_MODE_CTR); + else + return(-1); +} + +/* Convert a protocol string to its integer value. */ static int proto_strtoint(const char *pr_str) @@ -290,6 +311,15 @@ parse_rc_param(fko_cli_options_t *options, const char *var, char * val) else options->time_offset_plus = parse_time_offset(val); } + /* symmetric encryption mode */ + else if(CONF_VAR_IS(var, "ENCRYPTION_MODE")) + { + tmpint = enc_mode_strtoint(val); + if(tmpint < 0) + return(-1); + else + options->encryption_mode = tmpint; + } /* Use GPG ? */ else if(CONF_VAR_IS(var, "USE_GPG")) { @@ -724,7 +754,19 @@ config_init(fko_cli_options_t *options, int argc, char **argv) case FKO_DIGEST_NAME: if((options->digest_type = digest_strtoint(optarg)) < 0) { - fprintf(stderr, "* Invalid digest type: %s\n", optarg); + fprintf(stderr, + "* Invalid digest type: %s, use {md5,sha1,sha256,sha384,sha512}\n", + optarg); + exit(EXIT_FAILURE); + } + break; + case 'M': + case ENCRYPTION_MODE: + if((options->encryption_mode = enc_mode_strtoint(optarg)) < 0) + { + fprintf(stderr, + "* Invalid encryption mode: %s, use {cbc,ecb}\n", + optarg); exit(EXIT_FAILURE); } break; diff --git a/client/fwknop.c b/client/fwknop.c index 687f5a04..1e545f78 100644 --- a/client/fwknop.c +++ b/client/fwknop.c @@ -252,6 +252,23 @@ main(int argc, char **argv) return(EXIT_FAILURE); } } + + res = fko_set_spa_encryption_mode(ctx, FKO_ENC_MODE_ASYMMETRIC); + if(res != FKO_SUCCESS) + { + errmsg("fko_set_spa_encryption_mode", res); + return(EXIT_FAILURE); + } + } + + if(options.encryption_mode && !options.use_gpg) + { + res = fko_set_spa_encryption_mode(ctx, options.encryption_mode); + if(res != FKO_SUCCESS) + { + errmsg("fko_set_spa_encryption_mode", res); + return(EXIT_FAILURE); + } } /* Set Digest type. @@ -328,13 +345,20 @@ main(int argc, char **argv) * an empty context, populate it with the encrypted data, set our * options, then decode it. */ - res = fko_new_with_data(&ctx2, spa_data, NULL); + res = fko_new_with_data(&ctx2, spa_data, NULL, ctx->encryption_mode); if(res != FKO_SUCCESS) { errmsg("fko_new_with_data", res); return(EXIT_FAILURE); } + res = fko_set_spa_encryption_mode(ctx2, ctx->encryption_mode); + if(res != FKO_SUCCESS) + { + errmsg("fko_set_spa_encryption_mode", res); + return(EXIT_FAILURE); + } + /* See if we are using gpg and if we need to set the GPG home dir. */ if(options.use_gpg) @@ -770,6 +794,7 @@ display_ctx(fko_ctx_t ctx) time_t timestamp = 0; short msg_type = -1; short digest_type = -1; + int encryption_mode = -1; int client_timeout = -1; /* Should be checking return values, but this is temp code. --DSS @@ -784,6 +809,7 @@ display_ctx(fko_ctx_t ctx) fko_get_spa_server_auth(ctx, &server_auth); fko_get_spa_client_timeout(ctx, &client_timeout); fko_get_spa_digest_type(ctx, &digest_type); + fko_get_spa_encryption_mode(ctx, &encryption_mode); fko_get_encoded_data(ctx, &enc_data); fko_get_spa_digest(ctx, &spa_digest); fko_get_spa_data(ctx, &spa_data); @@ -798,7 +824,8 @@ display_ctx(fko_ctx_t ctx) printf(" Nat Access: %s\n", nat_access == NULL ? "" : nat_access); printf(" Server Auth: %s\n", server_auth == NULL ? "" : server_auth); printf(" Client Timeout: %u\n", client_timeout); - printf(" Digest Type: %u\n", digest_type); + printf(" Digest Type: %d\n", digest_type); + printf("Encryption Mode: %d\n", encryption_mode); printf("\n Encoded Data: %s\n", enc_data == NULL ? "" : enc_data); printf("\nSPA Data Digest: %s\n", spa_digest == NULL ? "" : spa_digest); printf("\nFinal Packed/Encrypted/Encoded Data:\n\n%s\n\n", spa_data); diff --git a/client/fwknop_common.h b/client/fwknop_common.h index 5d7e8ef3..4e494aa7 100644 --- a/client/fwknop_common.h +++ b/client/fwknop_common.h @@ -116,7 +116,8 @@ typedef struct fko_cli_options unsigned int spa_dst_port; unsigned int spa_src_port; /* only used with --source-port */ - unsigned int digest_type; + short digest_type; + int encryption_mode; /* Various command-line flags */ unsigned char verbose; /* --verbose mode */ diff --git a/doc/fwknop.man.asciidoc b/doc/fwknop.man.asciidoc index f110d20c..ade2674d 100644 --- a/doc/fwknop.man.asciidoc +++ b/doc/fwknop.man.asciidoc @@ -1,5 +1,5 @@ :man source: Fwknop Client -:man manual: Fwknop Client +:man manual: Fwknop Client FWKNOP(8) ========= @@ -38,7 +38,7 @@ sequence on the server to break port knocking authentication. SPA packets can easily be spoofed as well (this is a good thing in this context), and this makes it possible to make it appear as though, say, www.yahoo.com is trying to authenticate to a target system but in reality -the actual connection will come from a seemingly unrelated IP. +the actual connection will come from a seemingly unrelated IP. Authorization packets are either encrypted with the 'Rijndael' block cipher or via 'GnuPG' and associated asymmetric ciphers. If the symmetric encryption @@ -161,10 +161,10 @@ SPA OPTIONS *-a, --allow-ip*='':: Specify IP address that should be permitted through the destination *fwknopd* server firewall (this IP is encrypted within the SPA packet - itself). This is useful to prevent a MTIM attack where a SPA packet + itself). This is useful to prevent a MITM attack where a SPA packet can be intercepted en-route and sent from a different IP than the original. Hence, if the *fwknopd* server trusts the source address - on the SPA packet IP header then the attacker gains access. + on the SPA packet IP header then the attacker gains access. The *-a* option puts the source address within the encrypted SPA packet, and so thwarts this attack. The *-a* option is also useful to specify the IP that will be granted access when the @@ -197,6 +197,15 @@ SPA OPTIONS Specify the message digest algorithm to use in the SPA data. Choices are: *MD5*, *SHA1*, *SHA256* (the default), *SHA384*, and *SHA512*. +*-M, --encryption-mode*='':: + Specify the encryption mode when AES is used. The default (for now) is + ECB mode in order to remain backwards compatible with pre-2.0 versions of + fwknop which relied on the Crypt::CBC perl module. This will be changed + in an upcoming version of fwknop to use the more secure CBC mode. In the + meantime, it is recommend to use this option to specify CBC mode (use the + string "CBC" as the argument), and then also use the ENCRYPTION_MODE + variable in the 'access.conf' file on the server. + *-N, --nat-access*='':: The *fwknopd* server offers the ability to provide SPA access through an iptables firewall to an internal service by interfacing with the @@ -205,7 +214,7 @@ SPA OPTIONS client can request that the server port forward an external port to an internal IP, i.e. ``+--NAT-access 192.168.10.2,55000+''. In this case, access will be granted to 192.168.10.2 via port 55000 to whatever - service is requested via the *--access* argument (usually tcp/22). + service is requested via the *--access* argument (usually tcp/22). Hence, after sending such an SPA packet, one would then do ``ssh -p 55000 user@host'' and the connection would be forwarded on through to the internal 192.168.10.2 system automatically. Note that @@ -404,6 +413,10 @@ description and its matching command-line option(s): Set a value to apply to the timestamp in the SPA packet. This can be either a positive or negative value ('--time-offset-plus/minus'). +*ENCRYPTION_MODE*:: + Specify the encryption mode when AES is used. This variable is a synonym + for the '--encryption-mode' command line argument. + *USE_GPG*:: Set to 'Y' to specify the use of GPG for encryption ('--gpg-encryption'). @@ -552,7 +565,7 @@ More information on Single Packet Authorization can be found in the paper AUTHORS ------- -Damien Stuart , +Damien Stuart , Michael Rash CONTRIBUTORS diff --git a/doc/fwknopd.man.asciidoc b/doc/fwknopd.man.asciidoc index a4b86667..36cb3e39 100644 --- a/doc/fwknopd.man.asciidoc +++ b/doc/fwknopd.man.asciidoc @@ -344,6 +344,15 @@ directive starts a new stanza. ``FW_ACCESS_TIMEOUT'' is not set then the default timeout of 30 seconds will automatically be set. +*ENCRYPTION_MODE*: '':: + Specify the encryption mode when AES is used. The default (for now) is + ECB mode in order to remain backwards compatible with pre-2.0 versions of + fwknop which relied on the Crypt::CBC perl module. This will be changed + in an upcoming version of fwknop to use the more secure CBC mode. In the + meantime, it is recommend to use this option to specify CBC mode (use the + string "CBC" as the argument), and then also use '--encryption-mode' + command line argument on the *fwknop* client. + *ENABLE_CMD_EXEC*: '':: This instructs *fwknopd* to accept complete commands that are contained within an authorization packet. Any such command will be executed on diff --git a/lib/cipher_funcs.c b/lib/cipher_funcs.c index 8fee6907..872ab81e 100644 --- a/lib/cipher_funcs.c +++ b/lib/cipher_funcs.c @@ -181,12 +181,13 @@ rij_salt_and_iv(RIJNDAEL_context *ctx, const char *pass, const unsigned char *da /* Initialization entry point. */ static void -rijndael_init(RIJNDAEL_context *ctx, const char *pass, const unsigned char *data) +rijndael_init(RIJNDAEL_context *ctx, const char *pass, + const unsigned char *data, int encryption_mode) { /* Use ECB mode to be compatible with the Crypt::CBC perl module. */ - ctx->mode = MODE_ECB; + ctx->mode = encryption_mode; /* Generate the salt and initialization vector. */ @@ -201,7 +202,8 @@ rijndael_init(RIJNDAEL_context *ctx, const char *pass, const unsigned char *data * module would. */ size_t -rij_encrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *out) +rij_encrypt(unsigned char *in, size_t in_len, + const char *pass, unsigned char *out, int encryption_mode) { RIJNDAEL_context ctx; unsigned char plaintext[RIJNDAEL_BLOCKSIZE]; @@ -211,7 +213,7 @@ rij_encrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *o unsigned char *ondx = out; - rijndael_init(&ctx, pass, NULL); + rijndael_init(&ctx, pass, NULL, encryption_mode); /* Prepend the salt... */ @@ -255,7 +257,8 @@ rij_encrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *o /* Decrypt the given data. */ size_t -rij_decrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *out) +rij_decrypt(unsigned char *in, size_t in_len, + const char *pass, unsigned char *out, int encryption_mode) { RIJNDAEL_context ctx; unsigned char plaintext[RIJNDAEL_BLOCKSIZE]; @@ -265,7 +268,7 @@ rij_decrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *o unsigned char *pad_s; unsigned char *ondx = out; - rijndael_init(&ctx, pass, in); + rijndael_init(&ctx, pass, in, encryption_mode); /* Remove the salt from the input. */ diff --git a/lib/cipher_funcs.h b/lib/cipher_funcs.h index 07edace9..a311d105 100644 --- a/lib/cipher_funcs.h +++ b/lib/cipher_funcs.h @@ -47,8 +47,10 @@ */ #define PREDICT_ENCSIZE(x) (1+(x>>4)+(x&0xf?1:0))<<4 -size_t rij_encrypt(unsigned char *in, size_t len, const char *key, unsigned char *out); -size_t rij_decrypt(unsigned char *in, size_t len, const char *key, unsigned char *out); +size_t rij_encrypt(unsigned char *in, size_t len, + const char *key, unsigned char *out, int encryption_mode); +size_t rij_decrypt(unsigned char *in, size_t len, + const char *key, unsigned char *out, int encryption_mode); #endif /* CIPHER_FUNCS_H */ diff --git a/lib/fko.h b/lib/fko.h index 9dadcc3c..d6bdbfd4 100644 --- a/lib/fko.h +++ b/lib/fko.h @@ -33,6 +33,8 @@ #include +#include "rijndael.h" /* For encryption modes */ + #ifdef __cplusplus extern "C" { #endif @@ -91,6 +93,20 @@ typedef enum { FKO_LAST_ENCRYPTION_TYPE /* Always leave this as the last one */ } fko_encryption_type_t; +/* Symmetric encryption modes derived from rijndael.h +*/ +typedef enum { + FKO_ENC_MODE_UNKNOWN = 0, + FKO_ENC_MODE_ECB = MODE_ECB, + FKO_ENC_MODE_CBC = MODE_CBC, + FKO_ENC_MODE_CFB = MODE_CFB, + FKO_ENC_MODE_PCBC = MODE_PCBC, + FKO_ENC_MODE_OFB = MODE_OFB, + FKO_ENC_MODE_CTR = MODE_CTR, + FKO_ENC_MODE_ASYMMETRIC, /* placeholder when GPG is used */ + FKO_LAST_ENC_MODE /* Always leave this as the last one */ +} fko_encryption_mode_t; + /* FKO ERROR_CODES * * Note: If you change this list in any way, please be sure to make the @@ -160,6 +176,7 @@ typedef enum { #define FKO_DEFAULT_MSG_TYPE FKO_ACCESS_MSG #define FKO_DEFAULT_DIGEST FKO_DIGEST_SHA256 #define FKO_DEFAULT_ENCRYPTION FKO_ENCRYPTION_RIJNDAEL +#define FKO_DEFAULT_ENC_MODE MODE_ECB /* The context holds the global state and config options, as * well as some intermediate results during processing. This @@ -189,7 +206,8 @@ enum { /* General api calls */ DLL_API int fko_new(fko_ctx_t *ctx); -DLL_API int fko_new_with_data(fko_ctx_t *ctx, const char *enc_msg, const char *dec_key); +DLL_API int fko_new_with_data(fko_ctx_t *ctx, const char *enc_msg, const char *dec_key, + int encryption_mode); DLL_API void fko_destroy(fko_ctx_t ctx); DLL_API int fko_spa_data_final(fko_ctx_t ctx, const char *enc_key); @@ -207,6 +225,7 @@ DLL_API int fko_set_spa_client_timeout(fko_ctx_t ctx, const int timeout); DLL_API int fko_set_spa_digest_type(fko_ctx_t ctx, const short digest_type); DLL_API int fko_set_spa_digest(fko_ctx_t ctx); DLL_API int fko_set_spa_encryption_type(fko_ctx_t ctx, const short encrypt_type); +DLL_API int fko_set_spa_encryption_mode(fko_ctx_t ctx, const int encrypt_mode); DLL_API int fko_set_spa_data(fko_ctx_t ctx, const char *enc_msg); /* Data processing and misc utility functions @@ -235,6 +254,7 @@ DLL_API int fko_get_spa_client_timeout(fko_ctx_t ctx, int *client_timeout); DLL_API int fko_get_spa_digest_type(fko_ctx_t ctx, short *spa_digest_type); DLL_API int fko_get_spa_digest(fko_ctx_t ctx, char **spa_digest); DLL_API int fko_get_spa_encryption_type(fko_ctx_t ctx, short *spa_enc_type); +DLL_API int fko_get_spa_encryption_mode(fko_ctx_t ctx, int *spa_enc_mode); DLL_API int fko_get_spa_data(fko_ctx_t ctx, char **spa_data); DLL_API int fko_get_version(fko_ctx_t ctx, char **version); diff --git a/lib/fko_context.h b/lib/fko_context.h index 8a98b557..18d5a8a8 100644 --- a/lib/fko_context.h +++ b/lib/fko_context.h @@ -63,6 +63,7 @@ struct fko_context { /* FKO SPA user-settable message encoding types */ short digest_type; short encryption_type; + int encryption_mode; /* Computed or predefined data */ char *version; diff --git a/lib/fko_encryption.c b/lib/fko_encryption.c index 4b81a411..6eca9294 100644 --- a/lib/fko_encryption.c +++ b/lib/fko_encryption.c @@ -66,7 +66,8 @@ _rijndael_encrypt(fko_ctx_t ctx, const char *enc_key) return(FKO_ERROR_MEMORY_ALLOCATION); cipher_len = rij_encrypt( - (unsigned char*)plain, strlen(plain), (char*)enc_key, cipher + (unsigned char*)plain, strlen(plain), (char*)enc_key, cipher, + ctx->encryption_mode ); /* Now make a bucket for the base64-encoded version and populate it. @@ -95,7 +96,7 @@ _rijndael_encrypt(fko_ctx_t ctx, const char *enc_key) /* Decode, decrypt, and parse SPA data into the context. */ static int -_rijndael_decrypt(fko_ctx_t ctx, const char *dec_key) +_rijndael_decrypt(fko_ctx_t ctx, const char *dec_key, int encryption_mode) { char *tbuf; unsigned char *ndx; @@ -143,7 +144,8 @@ _rijndael_decrypt(fko_ctx_t ctx, const char *dec_key) if(ctx->encoded_msg == NULL) return(FKO_ERROR_MEMORY_ALLOCATION); - pt_len = rij_decrypt(cipher, cipher_len, dec_key, (unsigned char*)ctx->encoded_msg); + pt_len = rij_decrypt(cipher, cipher_len, dec_key, + (unsigned char*)ctx->encoded_msg, encryption_mode); /* Done with cipher... */ @@ -351,6 +353,41 @@ fko_get_spa_encryption_type(fko_ctx_t ctx, short *enc_type) return(FKO_SUCCESS); } +/* Set the SPA encryption mode. +*/ +int +fko_set_spa_encryption_mode(fko_ctx_t ctx, const int encrypt_mode) +{ + /* Must be initialized + */ + if(!CTX_INITIALIZED(ctx)) + return(FKO_ERROR_CTX_NOT_INITIALIZED); + + if(encrypt_mode < 0 || encrypt_mode >= FKO_LAST_ENC_MODE) + return(FKO_ERROR_INVALID_DATA); + + ctx->encryption_mode = encrypt_mode; + + ctx->state |= FKO_ENCRYPT_MODE_MODIFIED; + + return(FKO_SUCCESS); +} + +/* Return the SPA encryption mode. +*/ +int +fko_get_spa_encryption_mode(fko_ctx_t ctx, int *enc_mode) +{ + /* Must be initialized + */ + if(!CTX_INITIALIZED(ctx)) + return(FKO_ERROR_CTX_NOT_INITIALIZED); + + *enc_mode = ctx->encryption_mode; + + return(FKO_SUCCESS); +} + /* Encrypt the encoded SPA data. */ int @@ -425,7 +462,7 @@ fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key) else if(enc_type == FKO_ENCRYPTION_RIJNDAEL) { ctx->encryption_type = FKO_ENCRYPTION_RIJNDAEL; - res = _rijndael_decrypt(ctx, dec_key); + res = _rijndael_decrypt(ctx, dec_key, ctx->encryption_mode); } else return(FKO_ERROR_INVALID_DATA); diff --git a/lib/fko_funcs.c b/lib/fko_funcs.c index 4a74438d..e6fe8a82 100644 --- a/lib/fko_funcs.c +++ b/lib/fko_funcs.c @@ -133,6 +133,18 @@ fko_new(fko_ctx_t *r_ctx) return res; } + /* Default Encryption Mode (Rijndael in EBC mode for backwards + * compatibility - it recommended to change this to CBC mode) + */ + ctx->initval = FKO_CTX_INITIALIZED; + res = fko_set_spa_encryption_mode(ctx, FKO_DEFAULT_ENC_MODE); + ctx->initval = 0; + if(res != FKO_SUCCESS) + { + fko_destroy(ctx); + return res; + } + #if HAVE_LIBGPGME /* Set gpg signature verify on. */ @@ -156,7 +168,8 @@ fko_new(fko_ctx_t *r_ctx) * and parsing the provided data into the context data. */ int -fko_new_with_data(fko_ctx_t *r_ctx, const char *enc_msg, const char *dec_key) +fko_new_with_data(fko_ctx_t *r_ctx, const char *enc_msg, + const char *dec_key, int encryption_mode) { fko_ctx_t ctx; int res = FKO_SUCCESS; /* Are we optimistic or what? */ @@ -174,13 +187,23 @@ fko_new_with_data(fko_ctx_t *r_ctx, const char *enc_msg, const char *dec_key) return(FKO_ERROR_MEMORY_ALLOCATION); } + /* Default Encryption Mode (Rijndael in CBC mode) + */ + ctx->initval = FKO_CTX_INITIALIZED; + res = fko_set_spa_encryption_mode(ctx, encryption_mode); + ctx->initval = 0; + if(res != FKO_SUCCESS) + { + fko_destroy(ctx); + return res; + } + /* Consider it initialized here. */ ctx->initval = FKO_CTX_INITIALIZED; FKO_SET_CTX_INITIALIZED(ctx); - /* If a decryption password is provided, go ahead and decrypt and - * decode. + /* If a decryption key is provided, go ahead and decrypt and decode. */ if(dec_key != NULL) { diff --git a/lib/fko_state.h b/lib/fko_state.h index 8c37f0aa..8349e5f5 100644 --- a/lib/fko_state.h +++ b/lib/fko_state.h @@ -49,7 +49,8 @@ typedef enum { FKO_DIGEST_TYPE_MODIFIED = 1 << 12, FKO_ENCRYPT_TYPE_MODIFIED = 1 << 13, STATE_RESERVED_14 = 1 << 14, - FKO_BACKWARD_COMPATIBLE = 1 << 15 + FKO_BACKWARD_COMPATIBLE = 1 << 15, + FKO_ENCRYPT_MODE_MODIFIED = 1 << 16, } fko_state_flags_t; /* This is used in conjunction with the ctx->initial value as a means to diff --git a/server/access.c b/server/access.c index 889d2f79..15a6088a 100644 --- a/server/access.c +++ b/server/access.c @@ -132,6 +132,27 @@ add_acc_expire_time_epoch(fko_srv_options_t *opts, time_t *access_expire_time, c return; } +/* Convert an encryption_mode string to its integer value. +*/ +static int +enc_mode_strtoint(const char *enc_mode_str) +{ + if(strcasecmp(enc_mode_str, "cbc") == 0) + return(FKO_ENC_MODE_CBC); + else if(strcasecmp(enc_mode_str, "ecb") == 0) + return(FKO_ENC_MODE_ECB); + else if(strcasecmp(enc_mode_str, "cfb") == 0) + return(FKO_ENC_MODE_CFB); + else if(strcasecmp(enc_mode_str, "pcbc") == 0) + return(FKO_ENC_MODE_PCBC); + else if(strcasecmp(enc_mode_str, "ofb") == 0) + return(FKO_ENC_MODE_OFB); + else if(strcasecmp(enc_mode_str, "ctr") == 0) + return(FKO_ENC_MODE_CTR); + else + return(-1); +} + #if FIREWALL_IPTABLES static void add_acc_force_nat(fko_srv_options_t *opts, acc_stanza_t *curr_acc, const char *val) @@ -708,8 +729,15 @@ set_acc_defaults(fko_srv_options_t *opts) /* set default gpg keyring path if necessary */ - if(acc->gpg_decrypt_pw != NULL && acc->gpg_home_dir == NULL) - add_acc_string(&(acc->gpg_home_dir), opts->config[CONF_GPG_HOME_DIR]); + if(acc->gpg_decrypt_pw != NULL) + { + acc->encryption_mode = FKO_ENC_MODE_ASYMMETRIC; + if(acc->gpg_home_dir == NULL) + add_acc_string(&(acc->gpg_home_dir), opts->config[CONF_GPG_HOME_DIR]); + } + + if (acc->encryption_mode == FKO_ENC_MODE_UNKNOWN) + acc->encryption_mode = FKO_DEFAULT_ENC_MODE; acc = acc->next; } @@ -869,6 +897,16 @@ parse_access_file(fko_srv_options_t *opts) { add_acc_int(&(curr_acc->fw_access_timeout), val); } + else if(CONF_VAR_IS(var, "ENCRYPTION_MODE")) + { + if((curr_acc->encryption_mode = enc_mode_strtoint(val)) < 0) + { + fprintf(stderr, + "[*] Unrecognized ENCRYPTION_MODE '%s', use {cbc,ecb}\n", + val); + clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE); + } + } else if(CONF_VAR_IS(var, "ENABLE_CMD_EXEC")) { add_acc_bool(&(curr_acc->enable_cmd_exec), val); @@ -1005,7 +1043,6 @@ parse_access_file(fko_srv_options_t *opts) expand_acc_ent_lists(opts); /* Make sure default values are set where needed. - * a default value. */ set_acc_defaults(opts); diff --git a/server/fwknopd_common.h b/server/fwknopd_common.h index 4fe7ec4f..36612276 100644 --- a/server/fwknopd_common.h +++ b/server/fwknopd_common.h @@ -282,6 +282,7 @@ typedef struct acc_stanza acc_string_list_t *gpg_remote_id_list; time_t access_expire_time; int expired; + int encryption_mode; unsigned char force_nat; char *force_nat_ip; char *force_nat_proto; diff --git a/server/incoming_spa.c b/server/incoming_spa.c index 27e17f09..922b120a 100644 --- a/server/incoming_spa.c +++ b/server/incoming_spa.c @@ -242,7 +242,8 @@ incoming_spa(fko_srv_options_t *opts) if(enc_type == FKO_ENCRYPTION_RIJNDAEL) { if(acc->key != NULL) - res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data, acc->key); + res = fko_new_with_data(&ctx, + (char *)spa_pkt->packet_data, acc->key, acc->encryption_mode); else { log_msg(LOG_ERR, @@ -260,7 +261,8 @@ incoming_spa(fko_srv_options_t *opts) */ if(acc->gpg_decrypt_pw != NULL) { - res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data, NULL); + res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data, NULL, + acc->encryption_mode); if(res != FKO_SUCCESS) { log_msg(LOG_WARNING,