Skip to content

Commit 18ebd81

Browse files
committed
MINOR: ssl: diagnostic warning when both 'default-crt' and 'strict-sni' are used
It possible to use both 'strict-sni' and 'default-crt' on the same bind line, which does not make much sense. This patch implements a check which will look for default certificates in the sni_w tree when strict-sni is used. (Referenced by their empty sni ""). default-crt sets the CKCH_INST_EXPL_DEFAULT flag in ckch_inst->is_default, so its possible to differenciate explicits default from implicit default. Could be backported as far as 3.0. This was discussed in ticket #3082.
1 parent d753f24 commit 18ebd81

File tree

4 files changed

+41
-9
lines changed

4 files changed

+41
-9
lines changed

include/haproxy/ssl_ckch-t.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ struct ckch_inst_link_ref {
116116
struct list list;
117117
};
118118

119+
120+
#define CKCH_INST_NO_DEFAULT 0 /* not the default instance */
121+
#define CKCH_INST_IMPL_DEFAULT 1 /* implicit default instance (declaration order) */
122+
#define CKCH_INST_EXPL_DEFAULT 2 /* explicit default instance (default-crt) */
123+
119124
/*
120125
* This structure describe a ckch instance. An instance is generated for each
121126
* bind_conf. The instance contains a linked list of the sni ctx which uses
@@ -128,7 +133,7 @@ struct ckch_inst {
128133
struct crtlist_entry *crtlist_entry; /* pointer to the crtlist_entry used, or NULL */
129134
struct server *server; /* pointer to the server if is_server_instance is set, NULL otherwise */
130135
SSL_CTX *ctx; /* pointer to the SSL context used by this instance */
131-
unsigned int is_default:1; /* This instance is used as the default ctx for this bind_conf */
136+
unsigned int is_default:2; /* This instance is used as the default ctx for this bind_conf (1: implicit default, 2: explicit default) */
132137
unsigned int is_server_instance:1; /* This instance is used by a backend server */
133138
/* space for more flag there */
134139
struct list sni_ctx; /* list of sni_ctx using this ckch_inst */

src/cfgparse-ssl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, s
789789
static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
790790
{
791791
char path[MAXPATHLEN];
792-
int default_crt = *args[cur_arg] == 'd' ? 1 : 0;
792+
int default_crt = *args[cur_arg] == 'd' ? CKCH_INST_EXPL_DEFAULT : CKCH_INST_NO_DEFAULT;
793793

794794
if (!*args[cur_arg + 1]) {
795795
memprintf(err, "'%s' : missing certificate location", args[cur_arg]);

src/ssl_ckch.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,8 +2612,7 @@ int ckch_inst_rebuild(struct ckch_store *ckch_store, struct ckch_inst *ckchi,
26122612
return 1;
26132613

26142614
/* if the previous ckchi was used as the default */
2615-
if (ckchi->is_default)
2616-
(*new_inst)->is_default = 1;
2615+
(*new_inst)->is_default = ckchi->is_default;
26172616

26182617
(*new_inst)->is_server_instance = ckchi->is_server_instance;
26192618
(*new_inst)->server = ckchi->server;

src/ssl_sock.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3211,7 +3211,7 @@ int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct
32113211
*/
32123212

32133213
if (is_default) {
3214-
ckch_inst->is_default = 1;
3214+
ckch_inst->is_default = is_default;
32153215

32163216
/* insert an empty SNI which will be used to lookup default certificate */
32173217
order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, "*", order);
@@ -3447,14 +3447,14 @@ int ssl_sock_load_cert_list_file(char *file, int dir, struct bind_conf *bind_con
34473447
list_for_each_entry(entry, &crtlist->ord_entries, by_crtlist) {
34483448
struct ckch_store *store;
34493449
struct ckch_inst *ckch_inst = NULL;
3450-
int is_default = 0;
3450+
int is_default = CKCH_INST_NO_DEFAULT;
34513451

34523452
store = entry->node.key;
34533453

34543454
/* if the SNI trees were empty the first "crt" become a default certificate,
34553455
* it can be applied on multiple certificates if it's a bundle */
34563456
if (eb_is_empty(&bind_conf->sni_ctx) && eb_is_empty(&bind_conf->sni_w_ctx))
3457-
is_default = 1;
3457+
is_default = CKCH_INST_IMPL_DEFAULT;
34583458

34593459

34603460
cfgerr |= ssl_sock_load_ckchs(store->path, store, bind_conf, entry->ssl_conf, entry->filters, entry->fcount, is_default, &ckch_inst, err);
@@ -3509,9 +3509,9 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, int is_default,
35093509

35103510
/* if the SNI trees were empty the first "crt" become a default certificate,
35113511
* it can be applied on multiple certificates if it's a bundle */
3512-
if (is_default == 0) {
3512+
if (is_default == CKCH_INST_NO_DEFAULT) {
35133513
if (eb_is_empty(&bind_conf->sni_ctx) && eb_is_empty(&bind_conf->sni_w_ctx))
3514-
is_default = 1;
3514+
is_default = CKCH_INST_IMPL_DEFAULT;
35153515
}
35163516

35173517
if ((ckchs = ckchs_lookup(path))) {
@@ -5027,6 +5027,34 @@ int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
50275027
}
50285028
}
50295029

5030+
/* check that we didn't use "strict-sni" and "default-crt" together */
5031+
if (bind_conf->ssl_options & BC_SSL_O_STRICT_SNI) {
5032+
struct ebmb_node *node, *n;
5033+
const char *wildp = "";
5034+
int is_default = CKCH_INST_NO_DEFAULT;
5035+
5036+
node = ebst_lookup(&bind_conf->sni_w_ctx, wildp);
5037+
for (n = node; n; n = ebmb_next_dup(n)) {
5038+
struct sni_ctx *sni;
5039+
5040+
sni = container_of(n, struct sni_ctx, name);
5041+
if (!sni->neg) {
5042+
5043+
if (sni->ckch_inst->is_default == CKCH_INST_EXPL_DEFAULT) {
5044+
is_default = CKCH_INST_EXPL_DEFAULT;
5045+
break;
5046+
}
5047+
}
5048+
}
5049+
5050+
if (is_default == CKCH_INST_EXPL_DEFAULT) {
5051+
ha_diag_warning("Proxy '%s': both 'default-crt' and 'strict-sni' keywords are used in bind '%s' at [%s:%d], certificates won't be used as fallback (use 'crt' instead).\n",
5052+
px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5053+
}
5054+
5055+
}
5056+
5057+
50305058
if ((bind_conf->options & BC_O_GENERATE_CERTS)) {
50315059
struct sni_ctx *sni_ctx;
50325060

0 commit comments

Comments
 (0)