diff --git a/Makefile b/Makefile index eba3e9c..b783c14 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ # [g]make USE_xxxx=1 # +# ENABLE_TACK : enable/disable TACK extension support (disabled by default) # USE_SHARED_CACHE : enable/disable a shared session cache (disabled by default) DESTDIR = @@ -13,6 +14,11 @@ OBJS = stud.o ringbuffer.o configuration.o all: realall +# TACK support +ifneq ($(ENABLE_TACK),) +CFLAGS += -DENABLE_TACK +endif + # Shared cache feature ifneq ($(USE_SHARED_CACHE),) CFLAGS += -DUSE_SHARED_CACHE -DUSE_SYSCALL_FUTEX diff --git a/configuration.c b/configuration.c index ff3409f..d8a5e35 100644 --- a/configuration.c +++ b/configuration.c @@ -29,6 +29,11 @@ // BEGIN: configuration parameters #define CFG_CIPHERS "ciphers" #define CFG_SSL_ENGINE "ssl-engine" +#ifdef ENABLE_TACK +#define CFG_TACK_FILE "tack-file" +#define CFG_TACK_BREAK_SIGS_FILE "tack-break-sigs-file" +#define CFG_TACK_PIN_ACTIVATION "tack-pin-activation" +#endif /* ENABLE_TACK */ #define CFG_PREFER_SERVER_CIPHERS "prefer-server-ciphers" #define CFG_BACKEND "backend" #define CFG_FRONTEND "frontend" @@ -123,6 +128,11 @@ stud_config * config_new (void) { r->NCORES = 1; r->CERT_FILE = NULL; r->CIPHER_SUITE = NULL; +#ifdef ENABLE_TACK + r->TACK_FILE = NULL; + r->TACK_BREAK_SIGS_FILE = NULL; + r->TACK_PIN_ACTIVATION = 0; +#endif /* ENABLE_TACK */ r->ENGINE = NULL; r->BACKLOG = 100; @@ -160,6 +170,10 @@ void config_destroy (stud_config *cfg) { if (cfg->BACK_PORT != NULL) free(cfg->BACK_PORT); if (cfg->CERT_FILE != NULL) free(cfg->CERT_FILE); if (cfg->CIPHER_SUITE != NULL) free(cfg->CIPHER_SUITE); +#ifdef ENABLE_TACK + if (cfg->TACK_FILE != NULL) free(cfg->TACK_FILE); + if (cfg->TACK_BREAK_SIGS_FILE != NULL) free(cfg->TACK_BREAK_SIGS_FILE); +#endif /* ENABLE_TACK */ if (cfg->ENGINE != NULL) free(cfg->ENGINE); #ifdef USE_SHARED_CACHE @@ -538,6 +552,37 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int config_assign_str(&cfg->CIPHER_SUITE, v); } } +#ifdef ENABLE_TACK + else if (strcmp(k, CFG_TACK_FILE) == 0) { + if (v != NULL && strlen(v) > 0) { + if (stat(v, &st) != 0) { + config_error_set("Unable to stat TACK file '%s': ", v, strerror(errno)); + r = 0; + } + else if (! S_ISREG(st.st_mode)) { + config_error_set("Invalid TACK file '%s': Not a file.", v); + r = 0; + } else + config_assign_str(&cfg->TACK_FILE, v); + } + } + else if (strcmp(k, CFG_TACK_BREAK_SIGS_FILE) == 0) { + if (v != NULL && strlen(v) > 0) { + if (stat(v, &st) != 0) { + config_error_set("Unable to stat TACK break sigs file '%s': ", v, strerror(errno)); + r = 0; + } + else if (! S_ISREG(st.st_mode)) { + config_error_set("Invalid TACK break sigs file '%s': Not a file.", v); + r = 0; + } else + config_assign_str(&cfg->TACK_BREAK_SIGS_FILE, v); + } + } + else if (strcmp(k, CFG_TACK_PIN_ACTIVATION) == 0) { + r = config_param_val_bool(v, &cfg->TACK_PIN_ACTIVATION); + } +#endif /* ENABLE_TACK */ else if (strcmp(k, CFG_SSL_ENGINE) == 0) { if (v != NULL && strlen(v) > 0) { config_assign_str(&cfg->ENGINE, v); @@ -853,6 +898,11 @@ void config_print_usage_fd (char *prog, stud_config *cfg, FILE *out) { fprintf(out, " -c --ciphers=SUITE Sets allowed ciphers (Default: \"%s\")\n", config_disp_str(cfg->CIPHER_SUITE)); fprintf(out, " -e --ssl-engine=NAME Sets OpenSSL engine (Default: \"%s\")\n", config_disp_str(cfg->ENGINE)); fprintf(out, " -O --prefer-server-ciphers Prefer server list order\n"); +#ifdef ENABLE_TACK + fprintf(out, " -T --tack-file=FILE Load TACK data from specified file.\n"); + fprintf(out, " -S --tack-break-sigs-file=FILE Load TACK break sigs from specified file.\n"); + fprintf(out, " -p --tack-pin-activation Enable TACK pin activation (only meaningful with other TACK options).\n"); +#endif /* ENABLE_TACK */ fprintf(out, "\n"); fprintf(out, "SOCKET:\n"); fprintf(out, "\n"); @@ -1110,6 +1160,11 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) { { "ssl", 0, &ssl, 1}, { CFG_CIPHERS, 1, NULL, 'c' }, { CFG_PREFER_SERVER_CIPHERS, 0, NULL, 'O' }, +#ifdef ENABLE_TACK + { CFG_TACK_FILE, 1, NULL, 'T'}, + { CFG_TACK_BREAK_SIGS_FILE, 1, NULL, 'S'}, + { CFG_TACK_PIN_ACTIVATION, 0, NULL, 'p'}, +#endif /* ENABLE_TACK */ { CFG_BACKEND, 1, NULL, 'b' }, { CFG_FRONTEND, 1, NULL, 'f' }, { CFG_WORKERS, 1, NULL, 'n' }, @@ -1141,7 +1196,7 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) { int option_index = 0; c = getopt_long( argc, argv, - "c:e:Ob:f:n:B:C:U:P:M:k:r:u:g:qstVh", + "c:e:Ob:f:n:B:C:T:S:pU:P:M:k:r:u:g:qstVh", long_options, &option_index ); @@ -1167,6 +1222,17 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) { case 'c': config_param_validate(CFG_CIPHERS, optarg, cfg, NULL, 0); break; +#ifdef ENABLE_TACK + case 'T': + config_param_validate(CFG_TACK_FILE, optarg, cfg, NULL, 0); + break; + case 'S': + config_param_validate(CFG_TACK_BREAK_SIGS_FILE, optarg, cfg, NULL, 0); + break; + case 'p': + config_param_validate(CFG_TACK_PIN_ACTIVATION, CFG_BOOL_ON, cfg, NULL, 0); + break; +#endif /* ENABLE_TACK */ case 'e': config_param_validate(CFG_SSL_ENGINE, optarg, cfg, NULL, 0); break; diff --git a/configuration.h b/configuration.h index 44be7f6..42f3dca 100644 --- a/configuration.h +++ b/configuration.h @@ -41,6 +41,11 @@ struct __stud_config { long NCORES; char *CERT_FILE; char *CIPHER_SUITE; +#ifdef ENABLE_TACK + char *TACK_FILE; + char *TACK_BREAK_SIGS_FILE; + int TACK_PIN_ACTIVATION; +#endif /* ENABLE_TACK */ char *ENGINE; int BACKLOG; #ifdef USE_SHARED_CACHE diff --git a/stud.c b/stud.c index 0ed6581..720fd20 100644 --- a/stud.c +++ b/stud.c @@ -599,6 +599,11 @@ SSL_CTX * init_openssl() { if (CONFIG->PREFER_SERVER_CIPHERS) SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); +#ifdef ENABLE_TACK + if (CONFIG->TACK_FILE || CONFIG->TACK_BREAK_SIGS_FILE) + SSL_CTX_use_tack_files(ctx, CONFIG->TACK_FILE, CONFIG->TACK_BREAK_SIGS_FILE, CONFIG->TACK_PIN_ACTIVATION); +#endif + #ifdef USE_SHARED_CACHE if (CONFIG->SHARED_CACHE) { if (shared_context_init(ctx, CONFIG->SHARED_CACHE) < 0) {