blob: 2c814d3bfdf2d7c5bebb0bc8d779a1a70849b666 [file] [log] [blame]
William Lallemand15e16942020-05-15 00:25:08 +02001/*
2 * This file contains the sample fetches related to the SSL
3 *
4 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
5 * Copyright (C) 2020 HAProxy Technologies, William Lallemand <wlallemand@haproxy.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#define _GNU_SOURCE
14#include <ctype.h>
15#include <dirent.h>
16#include <errno.h>
William Lallemand15e16942020-05-15 00:25:08 +020017#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21
Willy Tarreaudcc048a2020-06-04 19:11:43 +020022#include <haproxy/acl.h>
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020023#include <haproxy/api.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020024#include <haproxy/arg.h>
Willy Tarreau99ea1882021-10-06 15:37:17 +020025#include <haproxy/base64.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +020026#include <haproxy/buf-t.h>
Willy Tarreau939b0bf2022-04-11 11:29:11 +020027#include <haproxy/connection.h>
Willy Tarreau8efbdfb2020-06-04 11:29:21 +020028#include <haproxy/obj_type.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +020029#include <haproxy/openssl-compat.h>
Willy Tarreaue6ce10b2020-06-04 15:33:47 +020030#include <haproxy/sample.h>
Willy Tarreau209108d2020-06-04 20:30:20 +020031#include <haproxy/ssl_sock.h>
Willy Tarreaub2bd8652020-06-04 14:21:22 +020032#include <haproxy/ssl_utils.h>
Willy Tarreaucb086c62022-05-27 09:47:12 +020033#include <haproxy/stconn.h>
Willy Tarreau48fbcae2020-06-03 18:09:46 +020034#include <haproxy/tools.h>
Willy Tarreau99ea1882021-10-06 15:37:17 +020035#include <haproxy/vars.h>
William Lallemand15e16942020-05-15 00:25:08 +020036
William Lallemand15e16942020-05-15 00:25:08 +020037
38/***** Below are some sample fetching functions for ACL/patterns *****/
39
Willy Tarreau99ea1882021-10-06 15:37:17 +020040#if defined(HAVE_CRYPTO_memcmp)
41/* Compares bytestring with a variable containing a bytestring. Return value
42 * is `true` if both bytestrings are bytewise identical and `false` otherwise.
43 *
44 * Comparison will be performed in constant time if both bytestrings are of
45 * the same length. If the lengths differ execution time will not be constant.
46 */
47static int sample_conv_secure_memcmp(const struct arg *arg_p, struct sample *smp, void *private)
48{
49 struct sample tmp;
50 int result;
51
52 smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt);
53 if (arg_p[0].type != ARGT_VAR)
54 return 0;
55
56 if (!sample_conv_var2smp(&arg_p[0].data.var, &tmp, SMP_T_BIN))
57 return 0;
58
59 if (smp->data.u.str.data != tmp.data.u.str.data) {
60 smp->data.u.sint = 0;
61 smp->data.type = SMP_T_BOOL;
62 return 1;
63 }
64
65 /* The following comparison is performed in constant time. */
66 result = CRYPTO_memcmp(smp->data.u.str.area, tmp.data.u.str.area, smp->data.u.str.data);
67
68 smp->data.u.sint = result == 0;
69 smp->data.type = SMP_T_BOOL;
70 return 1;
71}
72
73/* This function checks the "secure_memcmp" converter's arguments and extracts the
74 * variable name and its scope.
75 */
76static int smp_check_secure_memcmp(struct arg *args, struct sample_conv *conv,
77 const char *file, int line, char **err)
78{
79 if (!args[0].data.str.data) {
80 memprintf(err, "missing variable name");
81 return 0;
82 }
83
84 /* Try to decode a variable. */
85 if (vars_check_arg(&args[0], NULL))
86 return 1;
87
88 memprintf(err, "failed to register variable name '%s'",
89 args[0].data.str.area);
90 return 0;
91}
92#endif // HAVE_secure_memcmp()
93
94static int smp_check_sha2(struct arg *args, struct sample_conv *conv,
95 const char *file, int line, char **err)
96{
97 if (args[0].type == ARGT_STOP)
98 return 1;
99 if (args[0].type != ARGT_SINT) {
100 memprintf(err, "Invalid type '%s'", arg_type_names[args[0].type]);
101 return 0;
102 }
103
104 switch (args[0].data.sint) {
105 case 224:
106 case 256:
107 case 384:
108 case 512:
109 /* this is okay */
110 return 1;
111 default:
112 memprintf(err, "Unsupported number of bits: '%lld'", args[0].data.sint);
113 return 0;
114 }
115}
116
117static int sample_conv_sha2(const struct arg *arg_p, struct sample *smp, void *private)
118{
119 struct buffer *trash = get_trash_chunk();
120 int bits = 256;
Remi Tricot-Le Breton2559bc82022-02-08 17:45:53 +0100121 EVP_MD_CTX *mdctx;
122 const EVP_MD *evp = NULL;
123 unsigned int digest_length = 0;
Willy Tarreau99ea1882021-10-06 15:37:17 +0200124 if (arg_p->data.sint)
125 bits = arg_p->data.sint;
126
127 switch (bits) {
Remi Tricot-Le Breton2559bc82022-02-08 17:45:53 +0100128 case 224:
129 evp = EVP_sha224();
Willy Tarreau99ea1882021-10-06 15:37:17 +0200130 break;
Remi Tricot-Le Breton2559bc82022-02-08 17:45:53 +0100131 case 256:
132 evp = EVP_sha256();
Willy Tarreau99ea1882021-10-06 15:37:17 +0200133 break;
Remi Tricot-Le Breton2559bc82022-02-08 17:45:53 +0100134 case 384:
135 evp = EVP_sha384();
Willy Tarreau99ea1882021-10-06 15:37:17 +0200136 break;
Remi Tricot-Le Breton2559bc82022-02-08 17:45:53 +0100137 case 512:
138 evp = EVP_sha512();
Willy Tarreau99ea1882021-10-06 15:37:17 +0200139 break;
Willy Tarreau99ea1882021-10-06 15:37:17 +0200140 default:
141 return 0;
142 }
143
Remi Tricot-Le Breton2559bc82022-02-08 17:45:53 +0100144 mdctx = EVP_MD_CTX_new();
145 if (!mdctx)
146 return 0;
147 EVP_DigestInit_ex(mdctx, evp, NULL);
148 EVP_DigestUpdate(mdctx, smp->data.u.str.area, smp->data.u.str.data);
149 EVP_DigestFinal_ex(mdctx, (unsigned char*)trash->area, &digest_length);
150 trash->data = digest_length;
151
152 EVP_MD_CTX_free(mdctx);
153
Willy Tarreau99ea1882021-10-06 15:37:17 +0200154 smp->data.u.str = *trash;
155 smp->data.type = SMP_T_BIN;
156 smp->flags &= ~SMP_F_CONST;
157 return 1;
158}
159
160/* This function checks an <arg> and fills it with a variable type if the
161 * <arg> string contains a valid variable name. If failed, the function
162 * tries to perform a base64 decode operation on the same string, and
163 * fills the <arg> with the decoded content.
164 *
165 * Validation is skipped if the <arg> string is empty.
166 *
167 * This function returns 0 if the variable lookup fails and the specified
168 * <arg> string is not a valid base64 encoded string, as well if
169 * unexpected argument type is specified or memory allocation error
170 * occurs. Otherwise it returns 1.
171 */
172static inline int sample_check_arg_base64(struct arg *arg, char **err)
173{
174 char *dec = NULL;
175 int dec_size;
176
177 if (arg->type != ARGT_STR) {
178 memprintf(err, "unexpected argument type");
179 return 0;
180 }
181
182 if (arg->data.str.data == 0) /* empty */
183 return 1;
184
185 if (vars_check_arg(arg, NULL))
186 return 1;
187
188 if (arg->data.str.data % 4) {
189 memprintf(err, "argument needs to be base64 encoded, and "
190 "can either be a string or a variable");
191 return 0;
192 }
193
194 dec_size = (arg->data.str.data / 4 * 3)
195 - (arg->data.str.area[arg->data.str.data-1] == '=' ? 1 : 0)
196 - (arg->data.str.area[arg->data.str.data-2] == '=' ? 1 : 0);
197
198 if ((dec = malloc(dec_size)) == NULL) {
199 memprintf(err, "memory allocation error");
200 return 0;
201 }
202
203 dec_size = base64dec(arg->data.str.area, arg->data.str.data, dec, dec_size);
204 if (dec_size < 0) {
205 memprintf(err, "argument needs to be base64 encoded, and "
206 "can either be a string or a variable");
207 free(dec);
208 return 0;
209 }
210
211 /* base64 decoded */
212 chunk_destroy(&arg->data.str);
213 arg->data.str.area = dec;
214 arg->data.str.data = dec_size;
215 return 1;
216}
217
218#ifdef EVP_CIPH_GCM_MODE
219static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
220 const char *file, int line, char **err)
221{
222 switch(args[0].data.sint) {
223 case 128:
224 case 192:
225 case 256:
226 break;
227 default:
228 memprintf(err, "key size must be 128, 192 or 256 (bits).");
229 return 0;
230 }
231
232 /* Try to decode variables. */
233 if (!sample_check_arg_base64(&args[1], err)) {
234 memprintf(err, "failed to parse nonce : %s", *err);
235 return 0;
236 }
237 if (!sample_check_arg_base64(&args[2], err)) {
238 memprintf(err, "failed to parse key : %s", *err);
239 return 0;
240 }
241 if (!sample_check_arg_base64(&args[3], err)) {
242 memprintf(err, "failed to parse aead_tag : %s", *err);
243 return 0;
244 }
245
246 return 1;
247}
248
249/* Arguments: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
250static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
251{
252 struct sample nonce, key, aead_tag;
253 struct buffer *smp_trash = NULL, *smp_trash_alloc = NULL;
Dragan Dosen3bf56c42024-03-11 18:10:01 +0100254 EVP_CIPHER_CTX *ctx = NULL;
Willy Tarreau99ea1882021-10-06 15:37:17 +0200255 int dec_size, ret;
256
257 smp_trash_alloc = alloc_trash_chunk();
258 if (!smp_trash_alloc)
259 return 0;
260
261 /* smp copy */
262 smp_trash_alloc->data = smp->data.u.str.data;
263 if (unlikely(smp_trash_alloc->data > smp_trash_alloc->size))
264 smp_trash_alloc->data = smp_trash_alloc->size;
265 memcpy(smp_trash_alloc->area, smp->data.u.str.area, smp_trash_alloc->data);
266
267 ctx = EVP_CIPHER_CTX_new();
268
269 if (!ctx)
270 goto err;
271
272 smp_trash = alloc_trash_chunk();
273 if (!smp_trash)
274 goto err;
275
276 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
277 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
278 goto err;
279
280 if (arg_p[1].type == ARGT_VAR) {
281 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
282 if (dec_size < 0)
283 goto err;
284 smp_trash->data = dec_size;
285 nonce.data.u.str = *smp_trash;
286 }
287
288 /* Set cipher type and mode */
289 switch(arg_p[0].data.sint) {
290 case 128:
291 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
292 break;
293 case 192:
294 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
295 break;
296 case 256:
297 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
298 break;
299 }
300
301 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, nonce.data.u.str.data, NULL);
302
303 /* Initialise IV */
304 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) nonce.data.u.str.area))
305 goto err;
306
307 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
308 if (!sample_conv_var2smp_str(&arg_p[2], &key))
309 goto err;
310
311 if (arg_p[2].type == ARGT_VAR) {
312 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
313 if (dec_size < 0)
314 goto err;
315 smp_trash->data = dec_size;
316 key.data.u.str = *smp_trash;
317 }
318
319 /* Initialise key */
320 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) key.data.u.str.area, NULL))
321 goto err;
322
323 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
324 (unsigned char *) smp_trash_alloc->area, (int) smp_trash_alloc->data))
325 goto err;
326
327 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
328 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
329 goto err;
330
331 if (arg_p[3].type == ARGT_VAR) {
332 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
333 if (dec_size < 0)
334 goto err;
335 smp_trash_alloc->data = dec_size;
336 aead_tag.data.u.str = *smp_trash_alloc;
337 }
338
339 dec_size = smp_trash->data;
340
341 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, aead_tag.data.u.str.data, (void *) aead_tag.data.u.str.area);
342 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
343
344 if (ret <= 0)
345 goto err;
346
347 smp->data.u.str.data = dec_size + smp_trash->data;
348 smp->data.u.str.area = smp_trash->area;
349 smp->data.type = SMP_T_BIN;
350 smp_dup(smp);
351 free_trash_chunk(smp_trash_alloc);
352 free_trash_chunk(smp_trash);
Dragan Dosen3bf56c42024-03-11 18:10:01 +0100353 EVP_CIPHER_CTX_free(ctx);
Willy Tarreau99ea1882021-10-06 15:37:17 +0200354 return 1;
355
356err:
357 free_trash_chunk(smp_trash_alloc);
358 free_trash_chunk(smp_trash);
Dragan Dosen3bf56c42024-03-11 18:10:01 +0100359 EVP_CIPHER_CTX_free(ctx);
Willy Tarreau99ea1882021-10-06 15:37:17 +0200360 return 0;
361}
362#endif
363
364static int check_crypto_digest(struct arg *args, struct sample_conv *conv,
365 const char *file, int line, char **err)
366{
367 const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.area);
368
369 if (evp)
370 return 1;
371
372 memprintf(err, "algorithm must be a valid OpenSSL message digest name.");
373 return 0;
374}
375
376static int sample_conv_crypto_digest(const struct arg *args, struct sample *smp, void *private)
377{
378 struct buffer *trash = get_trash_chunk();
379 unsigned char *md = (unsigned char*) trash->area;
380 unsigned int md_len = trash->size;
381 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
382 const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.area);
383
384 if (!ctx)
385 return 0;
386
387 if (!EVP_DigestInit_ex(ctx, evp, NULL) ||
388 !EVP_DigestUpdate(ctx, smp->data.u.str.area, smp->data.u.str.data) ||
389 !EVP_DigestFinal_ex(ctx, md, &md_len)) {
390 EVP_MD_CTX_free(ctx);
391 return 0;
392 }
393
394 EVP_MD_CTX_free(ctx);
395
396 trash->data = md_len;
397 smp->data.u.str = *trash;
398 smp->data.type = SMP_T_BIN;
399 smp->flags &= ~SMP_F_CONST;
400 return 1;
401}
402
William Lallemand9fbc84e2022-11-03 18:56:37 +0100403/* Take a numerical X509_V_ERR and return its constant name */
404static int sample_conv_x509_v_err(const struct arg *arg_p, struct sample *smp, void *private)
405{
406 const char *res = x509_v_err_int_to_str(smp->data.u.sint);
407
408 /* if the value was found return its string */
409 if (res) {
410 smp->data.u.str.area = (char *)res;
411 smp->data.u.str.data = strlen(res);
412 smp->data.type = SMP_T_STR;
413 smp->flags |= SMP_F_CONST;
414
415 return 1;
William Lallemand117c7fd2023-05-03 15:13:10 +0200416 } else {
417 struct buffer *smp_trash = get_trash_chunk();
418
419 /* if the conversion failed, output the numbers as string */
420 chunk_printf(smp_trash, "%llu", smp->data.u.sint);
421
422 smp->data.u.str = *smp_trash;
423 smp->data.type = SMP_T_STR;
424 smp->flags &= ~SMP_F_CONST;
425
426 return 1;
William Lallemand9fbc84e2022-11-03 18:56:37 +0100427 }
428
429 return 0;
430}
431
Willy Tarreau99ea1882021-10-06 15:37:17 +0200432static int check_crypto_hmac(struct arg *args, struct sample_conv *conv,
433 const char *file, int line, char **err)
434{
435 if (!check_crypto_digest(args, conv, file, line, err))
436 return 0;
437
438 if (!sample_check_arg_base64(&args[1], err)) {
439 memprintf(err, "failed to parse key : %s", *err);
440 return 0;
441 }
442
443 return 1;
444}
445
446static int sample_conv_crypto_hmac(const struct arg *args, struct sample *smp, void *private)
447{
448 struct sample key;
449 struct buffer *trash = NULL, *key_trash = NULL;
450 unsigned char *md;
451 unsigned int md_len;
452 const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.area);
453 int dec_size;
454
455 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
456 if (!sample_conv_var2smp_str(&args[1], &key))
457 return 0;
458
459 if (args[1].type == ARGT_VAR) {
460 key_trash = alloc_trash_chunk();
461 if (!key_trash)
462 goto err;
463
464 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, key_trash->area, key_trash->size);
465 if (dec_size < 0)
466 goto err;
467 key_trash->data = dec_size;
468 key.data.u.str = *key_trash;
469 }
470
471 trash = alloc_trash_chunk();
472 if (!trash)
473 goto err;
474
475 md = (unsigned char*) trash->area;
476 md_len = trash->size;
477 if (!HMAC(evp, key.data.u.str.area, key.data.u.str.data, (const unsigned char*) smp->data.u.str.area,
478 smp->data.u.str.data, md, &md_len))
479 goto err;
480
481 free_trash_chunk(key_trash);
482
483 trash->data = md_len;
484 smp->data.u.str = *trash;
485 smp->data.type = SMP_T_BIN;
486 smp_dup(smp);
487 free_trash_chunk(trash);
488 return 1;
489
490err:
491 free_trash_chunk(key_trash);
492 free_trash_chunk(trash);
493 return 0;
494}
495
William Lallemand15e16942020-05-15 00:25:08 +0200496static int
497smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
498{
499 SSL *ssl;
500 struct connection *conn;
501
502 conn = objt_conn(smp->sess->origin);
503 ssl = ssl_sock_get_ssl_object(conn);
504 if (!ssl)
505 return 0;
506
507 smp->flags = 0;
508 smp->data.type = SMP_T_BOOL;
509#ifdef OPENSSL_IS_BORINGSSL
510 {
511 smp->data.u.sint = (SSL_in_early_data(ssl) &&
512 SSL_early_data_accepted(ssl));
513 }
514#else
515 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
516 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
517#endif
518 return 1;
519}
520
521/* boolean, returns true if client cert was present */
522static int
523smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
524{
Willy Tarreau939b0bf2022-04-11 11:29:11 +0200525 struct connection *conn = objt_conn(smp->sess->origin);
526 struct ssl_sock_ctx *ctx = conn_get_ssl_sock_ctx(conn);
William Lallemand15e16942020-05-15 00:25:08 +0200527
Willy Tarreau939b0bf2022-04-11 11:29:11 +0200528 if (!ctx)
William Lallemand15e16942020-05-15 00:25:08 +0200529 return 0;
530
William Lallemand15e16942020-05-15 00:25:08 +0200531 if (conn->flags & CO_FL_WAIT_XPRT) {
532 smp->flags |= SMP_F_MAY_CHANGE;
533 return 0;
534 }
535
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200536 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200537 smp->data.type = SMP_T_BOOL;
538 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
539
540 return 1;
541}
542
Abhijeet Rastogidf97f472023-05-13 20:04:45 -0700543/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of the
544 * client certificate's root CA.
545 */
William Lallemand6e0c39d2023-05-15 12:05:55 +0200546#ifdef HAVE_SSL_get0_verified_chain
Abhijeet Rastogidf97f472023-05-13 20:04:45 -0700547static int
548smp_fetch_ssl_r_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
549{
550 X509 *crt = NULL;
551 X509_NAME *name;
552 int ret = 0;
553 struct buffer *smp_trash;
554 struct connection *conn;
555 SSL *ssl;
556
557 conn = objt_conn(smp->sess->origin);
558 ssl = ssl_sock_get_ssl_object(conn);
559 if (!ssl)
560 return 0;
561
562 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
563 smp->flags |= SMP_F_MAY_CHANGE;
564 return 0;
565 }
566
567 crt = ssl_sock_get_verified_chain_root(ssl);
568 if (!crt)
569 goto out;
570
571 name = X509_get_subject_name(crt);
572 if (!name)
573 goto out;
574
575 smp_trash = get_trash_chunk();
576 if (args[0].type == ARGT_STR && args[0].data.str.data > 0) {
577 int pos = 1;
578
579 if (args[1].type == ARGT_SINT)
580 pos = args[1].data.sint;
581
582 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
583 goto out;
584 }
585 else if (args[2].type == ARGT_STR && args[2].data.str.data > 0) {
586 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
587 goto out;
588 }
589 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
590 goto out;
591
592 smp->flags = SMP_F_VOL_SESS;
593 smp->data.type = SMP_T_STR;
594 smp->data.u.str = *smp_trash;
595 ret = 1;
596out:
597 return ret;
598}
William Lallemand6e0c39d2023-05-15 12:05:55 +0200599#endif
Abhijeet Rastogidf97f472023-05-13 20:04:45 -0700600
William Lallemand15e16942020-05-15 00:25:08 +0200601/* binary, returns a certificate in a binary chunk (der/raw).
602 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
603 * should be use.
604 */
605static int
606smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
607{
William Lallemandbfa3e812020-06-25 20:07:18 +0200608 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
609 int conn_server = (kw[4] == 's') ? 1 : 0;
610
William Lallemand15e16942020-05-15 00:25:08 +0200611 X509 *crt = NULL;
612 int ret = 0;
613 struct buffer *smp_trash;
614 struct connection *conn;
615 SSL *ssl;
616
William Lallemandbfa3e812020-06-25 20:07:18 +0200617 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +0200618 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200619 else
620 conn = objt_conn(smp->sess->origin);
621
William Lallemand15e16942020-05-15 00:25:08 +0200622 ssl = ssl_sock_get_ssl_object(conn);
623 if (!ssl)
624 return 0;
625
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200626 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +0200627 smp->flags |= SMP_F_MAY_CHANGE;
628 return 0;
629 }
630
631 if (cert_peer)
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200632 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +0200633 else
634 crt = SSL_get_certificate(ssl);
635
636 if (!crt)
637 goto out;
638
639 smp_trash = get_trash_chunk();
640 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
641 goto out;
642
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200643 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200644 smp->data.u.str = *smp_trash;
645 smp->data.type = SMP_T_BIN;
646 ret = 1;
647out:
648 /* SSL_get_peer_certificate, it increase X509 * ref count */
649 if (cert_peer && crt)
650 X509_free(crt);
651 return ret;
652}
653
William Dauchya598b502020-08-06 18:11:38 +0200654/* binary, returns a chain certificate in a binary chunk (der/raw).
655 * The 5th keyword char is used to support only peer cert
656 */
657static int
658smp_fetch_ssl_x_chain_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
659{
660 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
661 int conn_server = (kw[4] == 's') ? 1 : 0;
662 struct buffer *smp_trash;
663 struct buffer *tmp_trash = NULL;
664 struct connection *conn;
665 STACK_OF(X509) *certs = NULL;
666 X509 *crt = NULL;
667 SSL *ssl;
668 int ret = 0;
669 int num_certs;
670 int i;
671
672 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +0200673 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Dauchya598b502020-08-06 18:11:38 +0200674 else
675 conn = objt_conn(smp->sess->origin);
676
677 if (!conn)
678 return 0;
679
680 ssl = ssl_sock_get_ssl_object(conn);
681 if (!ssl)
682 return 0;
683
684 if (conn->flags & CO_FL_WAIT_XPRT) {
685 smp->flags |= SMP_F_MAY_CHANGE;
686 return 0;
687 }
688
689 if (!cert_peer)
690 return 0;
691
692 certs = SSL_get_peer_cert_chain(ssl);
693 if (!certs)
694 return 0;
695
696 num_certs = sk_X509_num(certs);
697 if (!num_certs)
698 goto out;
699 smp_trash = get_trash_chunk();
700 tmp_trash = alloc_trash_chunk();
701 if (!tmp_trash)
702 goto out;
703 for (i = 0; i < num_certs; i++) {
704 crt = sk_X509_value(certs, i);
705 if (ssl_sock_crt2der(crt, tmp_trash) <= 0)
706 goto out;
707 chunk_cat(smp_trash, tmp_trash);
708 }
709
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200710 smp->flags = SMP_F_VOL_SESS;
William Dauchya598b502020-08-06 18:11:38 +0200711 smp->data.u.str = *smp_trash;
712 smp->data.type = SMP_T_BIN;
713 ret = 1;
714out:
715 if (tmp_trash)
716 free_trash_chunk(tmp_trash);
William Dauchya598b502020-08-06 18:11:38 +0200717 return ret;
718}
719
William Lallemand15e16942020-05-15 00:25:08 +0200720/* binary, returns serial of certificate in a binary chunk.
721 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
722 * should be use.
723 */
724static int
725smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
726{
William Lallemandbfa3e812020-06-25 20:07:18 +0200727 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
728 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200729 X509 *crt = NULL;
730 int ret = 0;
731 struct buffer *smp_trash;
732 struct connection *conn;
733 SSL *ssl;
734
William Lallemandbfa3e812020-06-25 20:07:18 +0200735 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +0200736 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200737 else
738 conn = objt_conn(smp->sess->origin);
William Lallemand15e16942020-05-15 00:25:08 +0200739 ssl = ssl_sock_get_ssl_object(conn);
740 if (!ssl)
741 return 0;
742
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200743 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +0200744 smp->flags |= SMP_F_MAY_CHANGE;
745 return 0;
746 }
747
748 if (cert_peer)
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200749 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +0200750 else
751 crt = SSL_get_certificate(ssl);
752
753 if (!crt)
754 goto out;
755
756 smp_trash = get_trash_chunk();
757 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
758 goto out;
759
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200760 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200761 smp->data.u.str = *smp_trash;
762 smp->data.type = SMP_T_BIN;
763 ret = 1;
764out:
765 /* SSL_get_peer_certificate, it increase X509 * ref count */
766 if (cert_peer && crt)
767 X509_free(crt);
768 return ret;
769}
770
771/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
772 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
773 * should be use.
774 */
775static int
776smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
777{
William Lallemandbfa3e812020-06-25 20:07:18 +0200778 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
779 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200780 X509 *crt = NULL;
781 const EVP_MD *digest;
782 int ret = 0;
783 unsigned int len = 0;
784 struct buffer *smp_trash;
785 struct connection *conn;
786 SSL *ssl;
787
William Lallemandbfa3e812020-06-25 20:07:18 +0200788 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +0200789 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200790 else
791 conn = objt_conn(smp->sess->origin);
792
William Lallemand15e16942020-05-15 00:25:08 +0200793 ssl = ssl_sock_get_ssl_object(conn);
794 if (!ssl)
795 return 0;
796
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200797 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +0200798 smp->flags |= SMP_F_MAY_CHANGE;
799 return 0;
800 }
801
802 if (cert_peer)
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200803 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +0200804 else
805 crt = SSL_get_certificate(ssl);
806 if (!crt)
807 goto out;
808
809 smp_trash = get_trash_chunk();
810 digest = EVP_sha1();
811 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
812 smp_trash->data = len;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200813 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200814 smp->data.u.str = *smp_trash;
815 smp->data.type = SMP_T_BIN;
816 ret = 1;
817out:
818 /* SSL_get_peer_certificate, it increase X509 * ref count */
819 if (cert_peer && crt)
820 X509_free(crt);
821 return ret;
822}
823
824/* string, returns certificate's notafter date in ASN1_UTCTIME format.
825 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
826 * should be use.
827 */
828static int
829smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
830{
William Lallemandbfa3e812020-06-25 20:07:18 +0200831 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
832 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200833 X509 *crt = NULL;
834 int ret = 0;
835 struct buffer *smp_trash;
836 struct connection *conn;
837 SSL *ssl;
838
William Lallemandbfa3e812020-06-25 20:07:18 +0200839 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +0200840 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200841 else
842 conn = objt_conn(smp->sess->origin);
843
William Lallemand15e16942020-05-15 00:25:08 +0200844 ssl = ssl_sock_get_ssl_object(conn);
845 if (!ssl)
846 return 0;
847
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200848 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +0200849 smp->flags |= SMP_F_MAY_CHANGE;
850 return 0;
851 }
852
853 if (cert_peer)
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200854 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +0200855 else
856 crt = SSL_get_certificate(ssl);
857 if (!crt)
858 goto out;
859
860 smp_trash = get_trash_chunk();
861 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
862 goto out;
863
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200864 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200865 smp->data.u.str = *smp_trash;
866 smp->data.type = SMP_T_STR;
867 ret = 1;
868out:
869 /* SSL_get_peer_certificate, it increase X509 * ref count */
870 if (cert_peer && crt)
871 X509_free(crt);
872 return ret;
873}
874
875/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
876 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
877 * should be use.
878 */
879static int
880smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
881{
William Lallemandbfa3e812020-06-25 20:07:18 +0200882 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
883 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200884 X509 *crt = NULL;
885 X509_NAME *name;
886 int ret = 0;
887 struct buffer *smp_trash;
888 struct connection *conn;
889 SSL *ssl;
890
William Lallemandbfa3e812020-06-25 20:07:18 +0200891 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +0200892 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200893 else
894 conn = objt_conn(smp->sess->origin);
895
William Lallemand15e16942020-05-15 00:25:08 +0200896 ssl = ssl_sock_get_ssl_object(conn);
897 if (!ssl)
898 return 0;
899
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200900 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +0200901 smp->flags |= SMP_F_MAY_CHANGE;
902 return 0;
903 }
904
905 if (cert_peer)
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200906 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +0200907 else
908 crt = SSL_get_certificate(ssl);
909 if (!crt)
910 goto out;
911
912 name = X509_get_issuer_name(crt);
913 if (!name)
914 goto out;
915
916 smp_trash = get_trash_chunk();
Christopher Faulet3702f782021-01-29 11:30:37 +0100917 if (args[0].type == ARGT_STR && args[0].data.str.data > 0) {
William Lallemand15e16942020-05-15 00:25:08 +0200918 int pos = 1;
919
920 if (args[1].type == ARGT_SINT)
921 pos = args[1].data.sint;
922
923 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
924 goto out;
925 }
Christopher Faulet3702f782021-01-29 11:30:37 +0100926 else if (args[2].type == ARGT_STR && args[2].data.str.data > 0) {
William Lallemand15e16942020-05-15 00:25:08 +0200927 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
928 goto out;
929 }
930 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
931 goto out;
932
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200933 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200934 smp->data.type = SMP_T_STR;
935 smp->data.u.str = *smp_trash;
936 ret = 1;
937out:
938 /* SSL_get_peer_certificate, it increase X509 * ref count */
939 if (cert_peer && crt)
940 X509_free(crt);
941 return ret;
942}
943
944/* string, returns notbefore date in ASN1_UTCTIME format.
945 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
946 * should be use.
947 */
948static int
949smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
950{
William Lallemandbfa3e812020-06-25 20:07:18 +0200951 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
952 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200953 X509 *crt = NULL;
954 int ret = 0;
955 struct buffer *smp_trash;
956 struct connection *conn;
957 SSL *ssl;
958
William Lallemandbfa3e812020-06-25 20:07:18 +0200959 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +0200960 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200961 else
962 conn = objt_conn(smp->sess->origin);
963
William Lallemand15e16942020-05-15 00:25:08 +0200964 ssl = ssl_sock_get_ssl_object(conn);
965 if (!ssl)
966 return 0;
967
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200968 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +0200969 smp->flags |= SMP_F_MAY_CHANGE;
970 return 0;
971 }
972
973 if (cert_peer)
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +0200974 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +0200975 else
976 crt = SSL_get_certificate(ssl);
977 if (!crt)
978 goto out;
979
980 smp_trash = get_trash_chunk();
981 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
982 goto out;
983
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200984 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200985 smp->data.u.str = *smp_trash;
986 smp->data.type = SMP_T_STR;
987 ret = 1;
988out:
989 /* SSL_get_peer_certificate, it increase X509 * ref count */
990 if (cert_peer && crt)
991 X509_free(crt);
992 return ret;
993}
994
995/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
996 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
997 * should be use.
998 */
999static int
1000smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
1001{
William Lallemandbfa3e812020-06-25 20:07:18 +02001002 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
1003 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +02001004 X509 *crt = NULL;
1005 X509_NAME *name;
1006 int ret = 0;
1007 struct buffer *smp_trash;
1008 struct connection *conn;
1009 SSL *ssl;
1010
William Lallemandbfa3e812020-06-25 20:07:18 +02001011 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001012 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +02001013 else
1014 conn = objt_conn(smp->sess->origin);
1015
William Lallemand15e16942020-05-15 00:25:08 +02001016 ssl = ssl_sock_get_ssl_object(conn);
1017 if (!ssl)
1018 return 0;
1019
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +02001020 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +02001021 smp->flags |= SMP_F_MAY_CHANGE;
1022 return 0;
1023 }
1024
1025 if (cert_peer)
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +02001026 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +02001027 else
1028 crt = SSL_get_certificate(ssl);
1029 if (!crt)
1030 goto out;
1031
1032 name = X509_get_subject_name(crt);
1033 if (!name)
1034 goto out;
1035
1036 smp_trash = get_trash_chunk();
Christopher Faulet3702f782021-01-29 11:30:37 +01001037 if (args[0].type == ARGT_STR && args[0].data.str.data > 0) {
William Lallemand15e16942020-05-15 00:25:08 +02001038 int pos = 1;
1039
1040 if (args[1].type == ARGT_SINT)
1041 pos = args[1].data.sint;
1042
1043 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1044 goto out;
1045 }
Christopher Faulet3702f782021-01-29 11:30:37 +01001046 else if (args[2].type == ARGT_STR && args[2].data.str.data > 0) {
William Lallemand15e16942020-05-15 00:25:08 +02001047 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
1048 goto out;
1049 }
1050 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1051 goto out;
1052
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001053 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001054 smp->data.type = SMP_T_STR;
1055 smp->data.u.str = *smp_trash;
1056 ret = 1;
1057out:
1058 /* SSL_get_peer_certificate, it increase X509 * ref count */
1059 if (cert_peer && crt)
1060 X509_free(crt);
1061 return ret;
1062}
1063
1064/* integer, returns true if current session use a client certificate */
1065static int
1066smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
1067{
1068 X509 *crt;
1069 struct connection *conn;
1070 SSL *ssl;
1071
1072 conn = objt_conn(smp->sess->origin);
1073 ssl = ssl_sock_get_ssl_object(conn);
1074 if (!ssl)
1075 return 0;
1076
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +02001077 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +02001078 smp->flags |= SMP_F_MAY_CHANGE;
1079 return 0;
1080 }
1081
1082 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +02001083 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +02001084 if (crt) {
1085 X509_free(crt);
1086 }
1087
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001088 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001089 smp->data.type = SMP_T_BOOL;
1090 smp->data.u.sint = (crt != NULL);
1091 return 1;
1092}
1093
1094/* integer, returns the certificate version
1095 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
1096 * should be use.
1097 */
1098static int
1099smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
1100{
William Lallemandbfa3e812020-06-25 20:07:18 +02001101 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
1102 int conn_server = (kw[4] == 's') ? 1 : 0;
1103
William Lallemand15e16942020-05-15 00:25:08 +02001104 X509 *crt;
1105 struct connection *conn;
1106 SSL *ssl;
1107
William Lallemandbfa3e812020-06-25 20:07:18 +02001108 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001109 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +02001110 else
1111 conn = objt_conn(smp->sess->origin);
William Lallemand15e16942020-05-15 00:25:08 +02001112 ssl = ssl_sock_get_ssl_object(conn);
1113 if (!ssl)
1114 return 0;
1115
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +02001116 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +02001117 smp->flags |= SMP_F_MAY_CHANGE;
1118 return 0;
1119 }
1120
1121 if (cert_peer)
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +02001122 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +02001123 else
1124 crt = SSL_get_certificate(ssl);
1125 if (!crt)
1126 return 0;
1127
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001128 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001129 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
1130 /* SSL_get_peer_certificate increase X509 * ref count */
1131 if (cert_peer)
1132 X509_free(crt);
1133 smp->data.type = SMP_T_SINT;
1134
1135 return 1;
1136}
1137
1138/* string, returns the certificate's signature algorithm.
1139 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
1140 * should be use.
1141 */
1142static int
1143smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
1144{
William Lallemandbfa3e812020-06-25 20:07:18 +02001145 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
1146 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +02001147 X509 *crt;
1148 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
1149 int nid;
1150 struct connection *conn;
1151 SSL *ssl;
1152
William Lallemandbfa3e812020-06-25 20:07:18 +02001153 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001154 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +02001155 else
1156 conn = objt_conn(smp->sess->origin);
1157
William Lallemand15e16942020-05-15 00:25:08 +02001158 ssl = ssl_sock_get_ssl_object(conn);
1159 if (!ssl)
1160 return 0;
1161
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +02001162 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +02001163 smp->flags |= SMP_F_MAY_CHANGE;
1164 return 0;
1165 }
1166
1167 if (cert_peer)
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +02001168 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +02001169 else
1170 crt = SSL_get_certificate(ssl);
1171 if (!crt)
1172 return 0;
1173
1174 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
1175 nid = OBJ_obj2nid(algorithm);
1176
1177 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
1178 if (!smp->data.u.str.area) {
1179 /* SSL_get_peer_certificate increase X509 * ref count */
1180 if (cert_peer)
1181 X509_free(crt);
1182 return 0;
1183 }
1184
1185 smp->data.type = SMP_T_STR;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001186 smp->flags |= SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +02001187 smp->data.u.str.data = strlen(smp->data.u.str.area);
1188 /* SSL_get_peer_certificate increase X509 * ref count */
1189 if (cert_peer)
1190 X509_free(crt);
1191
1192 return 1;
1193}
1194
1195/* string, returns the certificate's key algorithm.
1196 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
1197 * should be use.
1198 */
1199static int
1200smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
1201{
William Lallemandbfa3e812020-06-25 20:07:18 +02001202 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
1203 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +02001204 X509 *crt;
1205 ASN1_OBJECT *algorithm;
1206 int nid;
1207 struct connection *conn;
1208 SSL *ssl;
1209
William Lallemandbfa3e812020-06-25 20:07:18 +02001210 if (conn_server)
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001211 conn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +02001212 else
1213 conn = objt_conn(smp->sess->origin);
William Lallemand15e16942020-05-15 00:25:08 +02001214 ssl = ssl_sock_get_ssl_object(conn);
1215 if (!ssl)
1216 return 0;
1217
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +02001218 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +02001219 smp->flags |= SMP_F_MAY_CHANGE;
1220 return 0;
1221 }
1222
1223 if (cert_peer)
Remi Tricot-Le Breton74f6ab62021-08-19 18:06:30 +02001224 crt = ssl_sock_get_peer_certificate(ssl);
William Lallemand15e16942020-05-15 00:25:08 +02001225 else
1226 crt = SSL_get_certificate(ssl);
1227 if (!crt)
1228 return 0;
1229
1230 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
1231 nid = OBJ_obj2nid(algorithm);
1232
1233 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
1234 if (!smp->data.u.str.area) {
1235 /* SSL_get_peer_certificate increase X509 * ref count */
1236 if (cert_peer)
1237 X509_free(crt);
1238 return 0;
1239 }
1240
1241 smp->data.type = SMP_T_STR;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001242 smp->flags |= SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +02001243 smp->data.u.str.data = strlen(smp->data.u.str.area);
1244 if (cert_peer)
1245 X509_free(crt);
1246
1247 return 1;
1248}
1249
1250/* boolean, returns true if front conn. transport layer is SSL.
1251 * This function is also usable on backend conn if the fetch keyword 5th
1252 * char is 'b'.
1253 */
1254static int
1255smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
1256{
1257 struct connection *conn;
1258
1259 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001260 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001261 else
1262 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001263 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001264
1265 smp->data.type = SMP_T_BOOL;
Willy Tarreau939b0bf2022-04-11 11:29:11 +02001266 smp->data.u.sint = conn_is_ssl(conn);
William Lallemand15e16942020-05-15 00:25:08 +02001267 return 1;
1268}
1269
1270/* boolean, returns true if client present a SNI */
1271static int
1272smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
1273{
1274#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1275 struct connection *conn = objt_conn(smp->sess->origin);
1276 SSL *ssl = ssl_sock_get_ssl_object(conn);
1277
1278 smp->data.type = SMP_T_BOOL;
1279 smp->data.u.sint = ssl && SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) != NULL;
1280 return 1;
1281#else
1282 return 0;
1283#endif
1284}
1285
1286/* boolean, returns true if client session has been resumed.
1287 * This function is also usable on backend conn if the fetch keyword 5th
1288 * char is 'b'.
1289 */
1290static int
1291smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
1292{
1293 struct connection *conn;
1294 SSL *ssl;
1295
1296 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001297 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001298 else
1299 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001300 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001301
1302 ssl = ssl_sock_get_ssl_object(conn);
1303
1304 smp->data.type = SMP_T_BOOL;
1305 smp->data.u.sint = ssl && SSL_session_reused(ssl);
1306 return 1;
1307}
1308
1309/* string, returns the used cipher if front conn. transport layer is SSL.
1310 * This function is also usable on backend conn if the fetch keyword 5th
1311 * char is 'b'.
1312 */
1313static int
1314smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
1315{
1316 struct connection *conn;
1317 SSL *ssl;
1318
1319 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001320 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001321 else
1322 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001323 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001324
1325 smp->flags = 0;
1326 ssl = ssl_sock_get_ssl_object(conn);
1327 if (!ssl)
1328 return 0;
1329
1330 smp->data.u.str.area = (char *)SSL_get_cipher_name(ssl);
1331 if (!smp->data.u.str.area)
1332 return 0;
1333
1334 smp->data.type = SMP_T_STR;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001335 smp->flags |= SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +02001336 smp->data.u.str.data = strlen(smp->data.u.str.area);
1337
1338 return 1;
1339}
1340
1341/* integer, returns the algoritm's keysize if front conn. transport layer
1342 * is SSL.
1343 * This function is also usable on backend conn if the fetch keyword 5th
1344 * char is 'b'.
1345 */
1346static int
1347smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
1348{
1349 struct connection *conn;
1350 SSL *ssl;
1351 int sint;
1352
1353 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001354 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001355 else
1356 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001357 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001358
1359 smp->flags = 0;
1360 ssl = ssl_sock_get_ssl_object(conn);
1361 if (!ssl)
1362 return 0;
1363
1364 if (!SSL_get_cipher_bits(ssl, &sint))
1365 return 0;
1366
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001367 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001368 smp->data.u.sint = sint;
1369 smp->data.type = SMP_T_SINT;
1370
1371 return 1;
1372}
1373
1374/* integer, returns the used keysize if front conn. transport layer is SSL.
1375 * This function is also usable on backend conn if the fetch keyword 5th
1376 * char is 'b'.
1377 */
1378static int
1379smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
1380{
1381 struct connection *conn;
1382 SSL *ssl;
1383
1384 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001385 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001386 else
1387 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001388 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001389
1390 smp->flags = 0;
1391 ssl = ssl_sock_get_ssl_object(conn);
1392 if (!ssl)
1393 return 0;
1394
1395 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ssl, NULL);
1396 if (!smp->data.u.sint)
1397 return 0;
1398
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001399 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001400 smp->data.type = SMP_T_SINT;
1401
1402 return 1;
1403}
1404
1405#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1406static int
1407smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
1408{
1409 struct connection *conn;
1410 SSL *ssl;
1411 unsigned int len = 0;
1412
1413 smp->flags = SMP_F_CONST;
1414 smp->data.type = SMP_T_STR;
1415
1416 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001417 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001418 else
1419 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001420 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001421
1422 ssl = ssl_sock_get_ssl_object(conn);
1423 if (!ssl)
1424 return 0;
1425
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001426 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001427 smp->data.u.str.area = NULL;
1428 SSL_get0_next_proto_negotiated(ssl,
1429 (const unsigned char **)&smp->data.u.str.area,
1430 &len);
1431
1432 if (!smp->data.u.str.area)
1433 return 0;
1434
1435 smp->data.u.str.data = len;
1436 return 1;
1437}
1438#endif
1439
1440#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1441static int
1442smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
1443{
1444 struct connection *conn;
1445 SSL *ssl;
1446 unsigned int len = 0;
1447
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001448 smp->flags = SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +02001449 smp->data.type = SMP_T_STR;
1450
1451 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001452 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001453 else
1454 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001455 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001456
1457 ssl = ssl_sock_get_ssl_object(conn);
1458 if (!ssl)
1459 return 0;
1460
1461 smp->data.u.str.area = NULL;
1462 SSL_get0_alpn_selected(ssl,
1463 (const unsigned char **)&smp->data.u.str.area,
1464 &len);
1465
1466 if (!smp->data.u.str.area)
1467 return 0;
1468
1469 smp->data.u.str.data = len;
1470 return 1;
1471}
1472#endif
1473
1474/* string, returns the used protocol if front conn. transport layer is SSL.
1475 * This function is also usable on backend conn if the fetch keyword 5th
1476 * char is 'b'.
1477 */
1478static int
1479smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
1480{
1481 struct connection *conn;
1482 SSL *ssl;
1483
1484 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001485 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001486 else
1487 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001488 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001489
1490 smp->flags = 0;
1491 ssl = ssl_sock_get_ssl_object(conn);
1492 if (!ssl)
1493 return 0;
1494
1495 smp->data.u.str.area = (char *)SSL_get_version(ssl);
1496 if (!smp->data.u.str.area)
1497 return 0;
1498
1499 smp->data.type = SMP_T_STR;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001500 smp->flags = SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +02001501 smp->data.u.str.data = strlen(smp->data.u.str.area);
1502
1503 return 1;
1504}
1505
1506/* binary, returns the SSL stream id if front conn. transport layer is SSL.
1507 * This function is also usable on backend conn if the fetch keyword 5th
1508 * char is 'b'.
1509 */
1510#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
1511static int
1512smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
1513{
1514 struct connection *conn;
1515 SSL_SESSION *ssl_sess;
1516 SSL *ssl;
1517 unsigned int len = 0;
1518
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001519 smp->flags = SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +02001520 smp->data.type = SMP_T_BIN;
1521
1522 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001523 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001524 else
1525 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001526 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001527
1528 ssl = ssl_sock_get_ssl_object(conn);
1529 if (!ssl)
1530 return 0;
1531
1532 ssl_sess = SSL_get_session(ssl);
1533 if (!ssl_sess)
1534 return 0;
1535
1536 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
1537 if (!smp->data.u.str.area || !len)
1538 return 0;
1539
1540 smp->data.u.str.data = len;
1541 return 1;
1542}
1543#endif
1544
1545
Ilya Shipitsindf627942021-03-25 00:41:41 +05001546#ifdef HAVE_SSL_EXTRACT_RANDOM
William Lallemand15e16942020-05-15 00:25:08 +02001547static int
1548smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
1549{
1550 struct connection *conn;
1551 struct buffer *data;
1552 SSL *ssl;
1553
1554 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001555 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001556 else
1557 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001558 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001559
1560 ssl = ssl_sock_get_ssl_object(conn);
1561 if (!ssl)
1562 return 0;
1563
1564 data = get_trash_chunk();
1565 if (kw[7] == 'c')
1566 data->data = SSL_get_client_random(ssl,
1567 (unsigned char *) data->area,
1568 data->size);
1569 else
1570 data->data = SSL_get_server_random(ssl,
1571 (unsigned char *) data->area,
1572 data->size);
1573 if (!data->data)
1574 return 0;
1575
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001576 smp->flags = SMP_F_VOL_TEST;
William Lallemand15e16942020-05-15 00:25:08 +02001577 smp->data.type = SMP_T_BIN;
1578 smp->data.u.str = *data;
1579
1580 return 1;
1581}
1582
1583static int
1584smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
1585{
1586 struct connection *conn;
1587 SSL_SESSION *ssl_sess;
1588 struct buffer *data;
1589 SSL *ssl;
1590
1591 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001592 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001593 else
1594 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001595 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001596
1597 ssl = ssl_sock_get_ssl_object(conn);
1598 if (!ssl)
1599 return 0;
1600
1601 ssl_sess = SSL_get_session(ssl);
1602 if (!ssl_sess)
1603 return 0;
1604
1605 data = get_trash_chunk();
1606 data->data = SSL_SESSION_get_master_key(ssl_sess,
1607 (unsigned char *) data->area,
1608 data->size);
1609 if (!data->data)
1610 return 0;
1611
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001612 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001613 smp->data.type = SMP_T_BIN;
1614 smp->data.u.str = *data;
1615
1616 return 1;
1617}
1618#endif
1619
William Lallemand15e16942020-05-15 00:25:08 +02001620static int
1621smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
1622{
Willy Tarreau579259d2021-11-05 19:12:54 +01001623#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand15e16942020-05-15 00:25:08 +02001624 struct connection *conn;
1625 SSL *ssl;
1626
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001627 smp->flags = SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +02001628 smp->data.type = SMP_T_STR;
1629
1630 conn = objt_conn(smp->sess->origin);
1631 ssl = ssl_sock_get_ssl_object(conn);
1632 if (!ssl)
1633 return 0;
1634
1635 smp->data.u.str.area = (char *)SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Remi Tricot-Le Bretona9967632022-01-07 17:12:01 +01001636 if (!smp->data.u.str.area) {
1637 /* We might have stored the SNI ourselves, look for it in the
1638 * context's ex_data.
1639 */
1640 smp->data.u.str.area = SSL_get_ex_data(ssl, ssl_client_sni_index);
1641
1642 if (!smp->data.u.str.area)
1643 return 0;
1644 }
William Lallemand15e16942020-05-15 00:25:08 +02001645
1646 smp->data.u.str.data = strlen(smp->data.u.str.area);
Remi Tricot-Le Bretona9967632022-01-07 17:12:01 +01001647
William Lallemand15e16942020-05-15 00:25:08 +02001648 return 1;
Willy Tarreau579259d2021-11-05 19:12:54 +01001649#else
1650 /* SNI not supported */
1651 return 0;
William Lallemand15e16942020-05-15 00:25:08 +02001652#endif
Willy Tarreau579259d2021-11-05 19:12:54 +01001653}
William Lallemand15e16942020-05-15 00:25:08 +02001654
Marcin Deranek959a48c2021-07-13 15:14:21 +02001655/* binary, returns tls client hello cipher list.
1656 * Arguments: filter_option (0,1)
1657 */
William Lallemand15e16942020-05-15 00:25:08 +02001658static int
1659smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
1660{
Marcin Deranek959a48c2021-07-13 15:14:21 +02001661 struct buffer *smp_trash;
William Lallemand15e16942020-05-15 00:25:08 +02001662 struct connection *conn;
1663 struct ssl_capture *capture;
1664 SSL *ssl;
1665
1666 conn = objt_conn(smp->sess->origin);
1667 ssl = ssl_sock_get_ssl_object(conn);
1668 if (!ssl)
1669 return 0;
1670
1671 capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
1672 if (!capture)
1673 return 0;
1674
Marcin Deranek959a48c2021-07-13 15:14:21 +02001675 if (args[0].data.sint) {
1676 smp_trash = get_trash_chunk();
1677 exclude_tls_grease(capture->data + capture->ciphersuite_offset, capture->ciphersuite_len, smp_trash);
1678 smp->data.u.str.area = smp_trash->area;
1679 smp->data.u.str.data = smp_trash->data;
1680 smp->flags = SMP_F_VOL_SESS;
1681 }
1682 else {
1683 smp->data.u.str.area = capture->data + capture->ciphersuite_offset;
1684 smp->data.u.str.data = capture->ciphersuite_len;
1685 smp->flags = SMP_F_VOL_TEST | SMP_F_CONST;
1686 }
1687
William Lallemand15e16942020-05-15 00:25:08 +02001688 smp->data.type = SMP_T_BIN;
William Lallemand15e16942020-05-15 00:25:08 +02001689 return 1;
1690}
1691
Marcin Deranek959a48c2021-07-13 15:14:21 +02001692/* binary, returns tls client hello cipher list as hexadecimal string.
1693 * Arguments: filter_option (0,1)
1694 */
William Lallemand15e16942020-05-15 00:25:08 +02001695static int
1696smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
1697{
1698 struct buffer *data;
1699
1700 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
1701 return 0;
1702
1703 data = get_trash_chunk();
1704 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001705 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001706 smp->data.type = SMP_T_BIN;
1707 smp->data.u.str = *data;
1708 return 1;
1709}
1710
Marcin Deranek959a48c2021-07-13 15:14:21 +02001711/* integer, returns xxh64 hash of tls client hello cipher list. */
William Lallemand15e16942020-05-15 00:25:08 +02001712static int
1713smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
1714{
1715 struct connection *conn;
1716 struct ssl_capture *capture;
1717 SSL *ssl;
1718
1719 conn = objt_conn(smp->sess->origin);
1720 ssl = ssl_sock_get_ssl_object(conn);
1721 if (!ssl)
1722 return 0;
1723
1724 capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
1725 if (!capture)
1726 return 0;
1727
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001728 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001729 smp->data.type = SMP_T_SINT;
1730 smp->data.u.sint = capture->xxh64;
1731 return 1;
1732}
1733
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001734static int
Remi Tricot-Le Breton1fe0fad2021-09-29 18:56:52 +02001735smp_fetch_ssl_fc_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001736{
1737 struct connection *conn;
1738 struct ssl_sock_ctx *ctx;
1739
Remi Tricot-Le Breton163cdeb2021-09-01 15:52:14 +02001740 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001741 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
Remi Tricot-Le Breton163cdeb2021-09-01 15:52:14 +02001742 else
1743 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001744 smp->strm ? sc_conn(smp->strm->scb) : NULL;
Remi Tricot-Le Breton163cdeb2021-09-01 15:52:14 +02001745
Willy Tarreauce7a5e02022-04-12 07:40:42 +02001746 if (!conn)
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001747 return 0;
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001748
1749 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
1750 smp->flags = SMP_F_MAY_CHANGE;
1751 return 0;
1752 }
1753
Willy Tarreauce7a5e02022-04-12 07:40:42 +02001754 ctx = conn_get_ssl_sock_ctx(conn);
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001755 if (!ctx)
1756 return 0;
1757
1758 smp->flags = SMP_F_VOL_SESS;
1759 smp->data.type = SMP_T_SINT;
Remi Tricot-Le Breton1fe0fad2021-09-29 18:56:52 +02001760 smp->data.u.sint = ctx->error_code;
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001761 return 1;
1762}
1763
1764static int
Marcin Deranek959a48c2021-07-13 15:14:21 +02001765smp_fetch_ssl_fc_protocol_hello_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
1766{
1767 struct connection *conn;
1768 struct ssl_capture *capture;
1769 SSL *ssl;
1770
1771 conn = objt_conn(smp->sess->origin);
1772 ssl = ssl_sock_get_ssl_object(conn);
1773 if (!ssl)
1774 return 0;
1775
1776 capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
1777 if (!capture)
1778 return 0;
1779
1780 smp->flags = SMP_F_VOL_SESS;
1781 smp->data.type = SMP_T_SINT;
1782 smp->data.u.sint = capture->protocol_version;
1783 return 1;
1784}
1785
1786static int
Remi Tricot-Le Breton1fe0fad2021-09-29 18:56:52 +02001787smp_fetch_ssl_fc_err_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001788{
1789 struct connection *conn;
1790 struct ssl_sock_ctx *ctx;
1791 const char *err_code_str;
1792
Remi Tricot-Le Breton163cdeb2021-09-01 15:52:14 +02001793 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02001794 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
Remi Tricot-Le Breton163cdeb2021-09-01 15:52:14 +02001795 else
1796 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001797 smp->strm ? sc_conn(smp->strm->scb) : NULL;
Remi Tricot-Le Breton163cdeb2021-09-01 15:52:14 +02001798
Willy Tarreauce7a5e02022-04-12 07:40:42 +02001799 if (!conn)
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001800 return 0;
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001801
1802 if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
1803 smp->flags = SMP_F_MAY_CHANGE;
1804 return 0;
1805 }
1806
Willy Tarreauce7a5e02022-04-12 07:40:42 +02001807 ctx = conn_get_ssl_sock_ctx(conn);
Remi Tricot-Le Breton1fe0fad2021-09-29 18:56:52 +02001808 if (!ctx || !ctx->error_code)
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001809 return 0;
1810
Remi Tricot-Le Breton1fe0fad2021-09-29 18:56:52 +02001811 err_code_str = ERR_error_string(ctx->error_code, NULL);
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001812
1813 smp->flags = SMP_F_VOL_SESS;
1814 smp->data.type = SMP_T_STR;
1815 smp->data.u.str.area = (char*)err_code_str;
1816 smp->data.u.str.data = strlen(err_code_str);
1817
Marcin Deranek959a48c2021-07-13 15:14:21 +02001818 return 1;
1819}
1820
1821/* binary, returns tls client hello extensions list.
1822 * Arguments: filter_option (0,1)
1823 */
1824static int
1825smp_fetch_ssl_fc_ext_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
1826{
1827 struct buffer *smp_trash;
1828 struct connection *conn;
1829 struct ssl_capture *capture;
1830 SSL *ssl;
1831
1832 conn = objt_conn(smp->sess->origin);
1833 ssl = ssl_sock_get_ssl_object(conn);
1834 if (!ssl)
1835 return 0;
1836
1837 capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
1838 if (!capture)
1839 return 0;
1840
1841 if (args[0].data.sint) {
1842 smp_trash = get_trash_chunk();
1843 exclude_tls_grease(capture->data + capture->extensions_offset, capture->extensions_len, smp_trash);
1844 smp->data.u.str.area = smp_trash->area;
1845 smp->data.u.str.data = smp_trash->data;
1846 smp->flags = SMP_F_VOL_SESS;
1847 }
1848 else {
1849 smp->data.u.str.area = capture->data + capture->extensions_offset;
1850 smp->data.u.str.data = capture->extensions_len;
1851 smp->flags = SMP_F_VOL_TEST | SMP_F_CONST;
1852 }
1853
1854 smp->data.type = SMP_T_BIN;
1855 return 1;
1856}
1857
1858/* binary, returns tls client hello supported elliptic curves.
1859 * Arguments: filter_option (0,1)
1860 */
1861static int
1862smp_fetch_ssl_fc_ecl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
1863{
1864 struct buffer *smp_trash;
1865 struct connection *conn;
1866 struct ssl_capture *capture;
1867 SSL *ssl;
1868
1869 conn = objt_conn(smp->sess->origin);
1870 ssl = ssl_sock_get_ssl_object(conn);
1871 if (!ssl)
1872 return 0;
1873
1874 capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
1875 if (!capture)
1876 return 0;
1877
1878 if (args[0].data.sint) {
1879 smp_trash = get_trash_chunk();
1880 exclude_tls_grease(capture->data + capture->ec_offset, capture->ec_len, smp_trash);
1881 smp->data.u.str.area = smp_trash->area;
1882 smp->data.u.str.data = smp_trash->data;
1883 smp->flags = SMP_F_VOL_SESS;
1884 }
1885 else {
1886 smp->data.u.str.area = capture->data + capture->ec_offset;
1887 smp->data.u.str.data = capture->ec_len;
1888 smp->flags = SMP_F_VOL_TEST | SMP_F_CONST;
1889 }
1890
1891 smp->data.type = SMP_T_BIN;
1892 return 1;
1893}
1894
1895/* binary, returns tls client hello supported elliptic curve point formats */
1896static int
1897smp_fetch_ssl_fc_ecf_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
1898{
1899 struct connection *conn;
1900 struct ssl_capture *capture;
1901 SSL *ssl;
1902
1903 conn = objt_conn(smp->sess->origin);
1904 ssl = ssl_sock_get_ssl_object(conn);
1905 if (!ssl)
1906 return 0;
1907
1908 capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
1909 if (!capture)
1910 return 0;
1911
1912 smp->flags = SMP_F_VOL_TEST | SMP_F_CONST;
1913 smp->data.type = SMP_T_BIN;
1914 smp->data.u.str.area = capture->data + capture->ec_formats_offset;
1915 smp->data.u.str.data = capture->ec_formats_len;
Remi Tricot-Le Breton7c6898e2021-07-29 09:45:51 +02001916 return 1;
1917}
1918
William Lallemand7d42ef52020-07-06 11:41:30 +02001919/* Dump the SSL keylog, it only works with "tune.ssl.keylog 1" */
William Lallemand722180a2021-06-09 16:46:12 +02001920#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +02001921static int smp_fetch_ssl_x_keylog(const struct arg *args, struct sample *smp, const char *kw, void *private)
1922{
1923 struct connection *conn;
1924 struct ssl_keylog *keylog;
1925 SSL *ssl;
1926 char *src = NULL;
1927 const char *sfx;
1928
William Lallemandb60a77b2022-11-18 15:00:15 +01001929 if (global_ssl.keylog <= 0)
1930 return 0;
1931
William Lallemand7d42ef52020-07-06 11:41:30 +02001932 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02001933 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand7d42ef52020-07-06 11:41:30 +02001934
William Lallemandeec1d452020-07-07 10:48:13 +02001935 if (!conn)
1936 return 0;
1937
William Lallemand7d42ef52020-07-06 11:41:30 +02001938 if (conn->flags & CO_FL_WAIT_XPRT) {
1939 smp->flags |= SMP_F_MAY_CHANGE;
1940 return 0;
1941 }
1942
1943 ssl = ssl_sock_get_ssl_object(conn);
1944 if (!ssl)
1945 return 0;
1946
1947 keylog = SSL_get_ex_data(ssl, ssl_keylog_index);
1948 if (!keylog)
1949 return 0;
1950
1951 sfx = kw + strlen("ssl_xx_");
1952
1953 if (strcmp(sfx, "client_early_traffic_secret") == 0) {
1954 src = keylog->client_early_traffic_secret;
1955 } else if (strcmp(sfx, "client_handshake_traffic_secret") == 0) {
1956 src = keylog->client_handshake_traffic_secret;
1957 } else if (strcmp(sfx, "server_handshake_traffic_secret") == 0) {
1958 src = keylog->server_handshake_traffic_secret;
1959 } else if (strcmp(sfx, "client_traffic_secret_0") == 0) {
1960 src = keylog->client_traffic_secret_0;
1961 } else if (strcmp(sfx, "server_traffic_secret_0") == 0) {
1962 src = keylog->server_traffic_secret_0;
1963 } else if (strcmp(sfx, "exporter_secret") == 0) {
1964 src = keylog->exporter_secret;
1965 } else if (strcmp(sfx, "early_exporter_secret") == 0) {
1966 src = keylog->early_exporter_secret;
1967 }
1968
1969 if (!src || !*src)
1970 return 0;
1971
1972 smp->data.u.str.area = src;
1973 smp->data.type = SMP_T_STR;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001974 smp->flags |= SMP_F_VOL_TEST | SMP_F_CONST;
William Lallemand7d42ef52020-07-06 11:41:30 +02001975 smp->data.u.str.data = strlen(smp->data.u.str.area);
1976 return 1;
William Lallemand7d42ef52020-07-06 11:41:30 +02001977}
1978#endif
1979
William Lallemand15e16942020-05-15 00:25:08 +02001980static int
1981smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
1982{
Ilya Shipitsinc9dfee42020-10-31 02:10:02 +05001983#if defined(OPENSSL_IS_BORINGSSL) || defined(SSL_CTRL_GET_RAW_CIPHERLIST)
William Lallemand15e16942020-05-15 00:25:08 +02001984 struct buffer *data;
1985 int i;
1986
1987 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
1988 return 0;
1989
1990 data = get_trash_chunk();
1991 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
1992 const char *str;
1993 const SSL_CIPHER *cipher;
1994 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
1995 uint16_t id = (bin[0] << 8) | bin[1];
1996#if defined(OPENSSL_IS_BORINGSSL)
1997 cipher = SSL_get_cipher_by_value(id);
1998#else
1999 struct connection *conn = __objt_conn(smp->sess->origin);
2000 SSL *ssl = ssl_sock_get_ssl_object(conn);
2001 cipher = SSL_CIPHER_find(ssl, bin);
2002#endif
2003 str = SSL_CIPHER_get_name(cipher);
2004 if (!str || strcmp(str, "(NONE)") == 0)
2005 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
2006 else
2007 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
2008 }
2009 smp->data.type = SMP_T_STR;
2010 smp->data.u.str = *data;
2011 return 1;
2012#else
2013 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
2014#endif
2015}
2016
2017#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
2018static int
2019smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
2020{
2021 struct connection *conn;
2022 int finished_len;
2023 struct buffer *finished_trash;
2024 SSL *ssl;
2025
2026 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Willy Tarreaubde14ad2022-05-27 10:04:04 +02002027 conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02002028 else
2029 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
Willy Tarreaufd9417b2022-05-18 16:23:22 +02002030 smp->strm ? sc_conn(smp->strm->scb) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02002031
2032 smp->flags = 0;
2033 ssl = ssl_sock_get_ssl_object(conn);
2034 if (!ssl)
2035 return 0;
2036
2037 if (conn->flags & CO_FL_WAIT_XPRT) {
2038 smp->flags |= SMP_F_MAY_CHANGE;
2039 return 0;
2040 }
2041
2042 finished_trash = get_trash_chunk();
2043 if (!SSL_session_reused(ssl))
2044 finished_len = SSL_get_peer_finished(ssl,
2045 finished_trash->area,
2046 finished_trash->size);
2047 else
2048 finished_len = SSL_get_finished(ssl,
2049 finished_trash->area,
2050 finished_trash->size);
2051
2052 if (!finished_len)
2053 return 0;
2054
2055 finished_trash->data = finished_len;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02002056 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02002057 smp->data.u.str = *finished_trash;
2058 smp->data.type = SMP_T_BIN;
2059
2060 return 1;
2061}
2062#endif
2063
2064/* integer, returns the first verify error in CA chain of client certificate chain. */
2065static int
2066smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
2067{
Willy Tarreau939b0bf2022-04-11 11:29:11 +02002068 struct connection *conn = objt_conn(smp->sess->origin);
2069 struct ssl_sock_ctx *ctx = conn_get_ssl_sock_ctx(conn);
William Lallemand15e16942020-05-15 00:25:08 +02002070
Willy Tarreau939b0bf2022-04-11 11:29:11 +02002071 if (conn && conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +02002072 smp->flags = SMP_F_MAY_CHANGE;
2073 return 0;
2074 }
2075
Remi Tricot-Le Breton89b65cf2021-07-29 09:45:50 +02002076 if (!ctx)
2077 return 0;
2078
William Lallemand15e16942020-05-15 00:25:08 +02002079 smp->data.type = SMP_T_SINT;
2080 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02002081 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02002082
2083 return 1;
2084}
2085
2086/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
2087static int
2088smp_fetch_ssl_c_ca_err_depth(const struct arg *args, struct sample *smp, const char *kw, void *private)
2089{
Willy Tarreau939b0bf2022-04-11 11:29:11 +02002090 struct connection *conn = objt_conn(smp->sess->origin);
2091 struct ssl_sock_ctx *ctx = conn_get_ssl_sock_ctx(conn);
William Lallemand15e16942020-05-15 00:25:08 +02002092
Willy Tarreau939b0bf2022-04-11 11:29:11 +02002093 if (conn && conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +02002094 smp->flags = SMP_F_MAY_CHANGE;
2095 return 0;
2096 }
William Lallemand15e16942020-05-15 00:25:08 +02002097
Remi Tricot-Le Breton89b65cf2021-07-29 09:45:50 +02002098 if (!ctx)
2099 return 0;
2100
William Lallemand15e16942020-05-15 00:25:08 +02002101 smp->data.type = SMP_T_SINT;
2102 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02002103 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02002104
2105 return 1;
2106}
2107
2108/* integer, returns the first verify error on client certificate */
2109static int
2110smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
2111{
Willy Tarreau939b0bf2022-04-11 11:29:11 +02002112 struct connection *conn = objt_conn(smp->sess->origin);
2113 struct ssl_sock_ctx *ctx = conn_get_ssl_sock_ctx(conn);
William Lallemand15e16942020-05-15 00:25:08 +02002114
Willy Tarreau939b0bf2022-04-11 11:29:11 +02002115 if (conn && conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
William Lallemand15e16942020-05-15 00:25:08 +02002116 smp->flags = SMP_F_MAY_CHANGE;
2117 return 0;
2118 }
2119
Remi Tricot-Le Breton89b65cf2021-07-29 09:45:50 +02002120 if (!ctx)
2121 return 0;
2122
William Lallemand15e16942020-05-15 00:25:08 +02002123 smp->data.type = SMP_T_SINT;
2124 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02002125 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02002126
2127 return 1;
2128}
2129
2130/* integer, returns the verify result on client cert */
2131static int
2132smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
2133{
2134 struct connection *conn;
2135 SSL *ssl;
2136
2137 conn = objt_conn(smp->sess->origin);
2138 ssl = ssl_sock_get_ssl_object(conn);
2139 if (!ssl)
2140 return 0;
2141
2142 if (conn->flags & CO_FL_WAIT_XPRT) {
2143 smp->flags = SMP_F_MAY_CHANGE;
2144 return 0;
2145 }
2146
2147 smp->data.type = SMP_T_SINT;
2148 smp->data.u.sint = (long long int)SSL_get_verify_result(ssl);
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02002149 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02002150
2151 return 1;
2152}
2153
2154/* Argument validation functions */
2155
2156/* This function is used to validate the arguments passed to any "x_dn" ssl
2157 * keywords. These keywords support specifying a third parameter that must be
2158 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
2159 */
2160int val_dnfmt(struct arg *arg, char **err_msg)
2161{
2162 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
2163 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
2164 return 0;
2165 }
2166 return 1;
2167}
2168
2169/* Note: must not be declared <const> as its list will be overwritten.
2170 * Please take care of keeping this list alphabetically sorted.
2171 */
2172static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
2173 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
2174 { "ssl_bc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
2175#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2176 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
2177#endif
2178 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
2179#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
2180 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
2181#endif
2182 { "ssl_bc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
2183 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
2184 { "ssl_bc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
2185 { "ssl_bc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
2186#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
2187 { "ssl_bc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
2188#endif
Ilya Shipitsindf627942021-03-25 00:41:41 +05002189#ifdef HAVE_SSL_EXTRACT_RANDOM
William Lallemand15e16942020-05-15 00:25:08 +02002190 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
2191 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
2192 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
2193#endif
Remi Tricot-Le Breton1fe0fad2021-09-29 18:56:52 +02002194 { "ssl_bc_err", smp_fetch_ssl_fc_err, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
2195 { "ssl_bc_err_str", smp_fetch_ssl_fc_err_str, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
William Lallemand15e16942020-05-15 00:25:08 +02002196 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
2197 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
2198 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
William Dauchya598b502020-08-06 18:11:38 +02002199 { "ssl_c_chain_der", smp_fetch_ssl_x_chain_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
William Lallemand15e16942020-05-15 00:25:08 +02002200 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
2201 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
2202 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2203 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2204 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
William Lallemand6e0c39d2023-05-15 12:05:55 +02002205#ifdef HAVE_SSL_get0_verified_chain
Abhijeet Rastogidf97f472023-05-13 20:04:45 -07002206 { "ssl_c_r_dn", smp_fetch_ssl_r_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
William Lallemand6e0c39d2023-05-15 12:05:55 +02002207#endif
William Lallemand15e16942020-05-15 00:25:08 +02002208 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2209 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
2210 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2211 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2212 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
2213 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
2214 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
2215 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2216 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
2217 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2218 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2219 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2220 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2221 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
2222 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2223 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2224 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
2225 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
2226 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
2227 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2228 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
2229 { "ssl_fc_has_early", smp_fetch_ssl_fc_has_early, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
2230 { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
2231 { "ssl_fc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
2232#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
2233 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2234#endif
2235#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2236 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2237#endif
2238 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2239#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
2240 { "ssl_fc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2241#endif
2242 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
2243#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
2244 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2245#endif
Ilya Shipitsindf627942021-03-25 00:41:41 +05002246#ifdef HAVE_SSL_EXTRACT_RANDOM
William Lallemand15e16942020-05-15 00:25:08 +02002247 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2248 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2249 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2250#endif
William Lallemand7d42ef52020-07-06 11:41:30 +02002251
William Lallemand722180a2021-06-09 16:46:12 +02002252#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +02002253 { "ssl_fc_client_early_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2254 { "ssl_fc_client_handshake_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2255 { "ssl_fc_server_handshake_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2256 { "ssl_fc_client_traffic_secret_0", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2257 { "ssl_fc_server_traffic_secret_0", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2258 { "ssl_fc_exporter_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2259 { "ssl_fc_early_exporter_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2260#endif
2261
William Lallemand15e16942020-05-15 00:25:08 +02002262 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Marcin Deranek959a48c2021-07-13 15:14:21 +02002263 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, ARG1(0,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
2264 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, ARG1(0,SINT), NULL, SMP_T_BIN, SMP_USE_L5CLI },
2265 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, ARG1(0,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
William Lallemand15e16942020-05-15 00:25:08 +02002266 { "ssl_fc_cipherlist_xxh", smp_fetch_ssl_fc_cl_xxh64, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Remi Tricot-Le Breton1fe0fad2021-09-29 18:56:52 +02002267 { "ssl_fc_err", smp_fetch_ssl_fc_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
2268 { "ssl_fc_err_str", smp_fetch_ssl_fc_err_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Marcin Deranek959a48c2021-07-13 15:14:21 +02002269 { "ssl_fc_protocol_hello_id",smp_fetch_ssl_fc_protocol_hello_id,0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
2270 { "ssl_fc_extlist_bin", smp_fetch_ssl_fc_ext_bin, ARG1(0,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
2271 { "ssl_fc_eclist_bin", smp_fetch_ssl_fc_ecl_bin, ARG1(0,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
2272 { "ssl_fc_ecformats_bin", smp_fetch_ssl_fc_ecf_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
William Lallemandbfa3e812020-06-25 20:07:18 +02002273
2274/* SSL server certificate fetches */
2275 { "ssl_s_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
William Dauchya598b502020-08-06 18:11:38 +02002276 { "ssl_s_chain_der", smp_fetch_ssl_x_chain_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
William Lallemandbfa3e812020-06-25 20:07:18 +02002277 { "ssl_s_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2278 { "ssl_s_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2279 { "ssl_s_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2280 { "ssl_s_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
2281 { "ssl_s_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
2282 { "ssl_s_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
2283 { "ssl_s_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2284 { "ssl_s_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
2285 { "ssl_s_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
William Lallemand15e16942020-05-15 00:25:08 +02002286 { NULL, NULL, 0, 0, 0 },
2287}};
2288
2289INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
2290
Willy Tarreau99ea1882021-10-06 15:37:17 +02002291/* Note: must not be declared <const> as its list will be overwritten */
2292static struct sample_conv_kw_list sample_conv_kws = {ILH, {
2293 { "sha2", sample_conv_sha2, ARG1(0, SINT), smp_check_sha2, SMP_T_BIN, SMP_T_BIN },
2294#ifdef EVP_CIPH_GCM_MODE
2295 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
2296#endif
William Lallemand9fbc84e2022-11-03 18:56:37 +01002297 { "x509_v_err_str", sample_conv_x509_v_err, 0, NULL, SMP_T_SINT, SMP_T_STR },
Willy Tarreau99ea1882021-10-06 15:37:17 +02002298 { "digest", sample_conv_crypto_digest, ARG1(1,STR), check_crypto_digest, SMP_T_BIN, SMP_T_BIN },
2299 { "hmac", sample_conv_crypto_hmac, ARG2(2,STR,STR), check_crypto_hmac, SMP_T_BIN, SMP_T_BIN },
2300#if defined(HAVE_CRYPTO_memcmp)
2301 { "secure_memcmp", sample_conv_secure_memcmp, ARG1(1,STR), smp_check_secure_memcmp, SMP_T_BIN, SMP_T_BOOL },
2302#endif
2303 { NULL, NULL, 0, 0, 0 },
2304}};
2305
2306INITCALL1(STG_REGISTER, sample_register_convs, &sample_conv_kws);
2307
2308
William Lallemand15e16942020-05-15 00:25:08 +02002309/* Note: must not be declared <const> as its list will be overwritten.
2310 * Please take care of keeping this list alphabetically sorted.
2311 */
2312static struct acl_kw_list acl_kws = {ILH, {
2313 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
2314 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
2315 { /* END */ },
2316}};
2317
2318INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);