blob: 5509e1f227abfdd7f571d4c6e3d4f3c6eba14bdf [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>
17#include <fcntl.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <unistd.h>
22
Willy Tarreaudcc048a2020-06-04 19:11:43 +020023#include <haproxy/acl.h>
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020024#include <haproxy/api.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020025#include <haproxy/arg.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +020026#include <haproxy/buf-t.h>
Willy Tarreau8efbdfb2020-06-04 11:29:21 +020027#include <haproxy/obj_type.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +020028#include <haproxy/openssl-compat.h>
Willy Tarreaue6ce10b2020-06-04 15:33:47 +020029#include <haproxy/sample.h>
Willy Tarreau209108d2020-06-04 20:30:20 +020030#include <haproxy/ssl_sock.h>
Willy Tarreaub2bd8652020-06-04 14:21:22 +020031#include <haproxy/ssl_utils.h>
Willy Tarreau48fbcae2020-06-03 18:09:46 +020032#include <haproxy/tools.h>
William Lallemand15e16942020-05-15 00:25:08 +020033
William Lallemand15e16942020-05-15 00:25:08 +020034
35/***** Below are some sample fetching functions for ACL/patterns *****/
36
37static int
38smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
39{
40 SSL *ssl;
41 struct connection *conn;
42
43 conn = objt_conn(smp->sess->origin);
44 ssl = ssl_sock_get_ssl_object(conn);
45 if (!ssl)
46 return 0;
47
48 smp->flags = 0;
49 smp->data.type = SMP_T_BOOL;
50#ifdef OPENSSL_IS_BORINGSSL
51 {
52 smp->data.u.sint = (SSL_in_early_data(ssl) &&
53 SSL_early_data_accepted(ssl));
54 }
55#else
56 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
57 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
58#endif
59 return 1;
60}
61
62/* boolean, returns true if client cert was present */
63static int
64smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
65{
66 struct connection *conn;
67 struct ssl_sock_ctx *ctx;
68
69 conn = objt_conn(smp->sess->origin);
70 if (!conn || conn->xprt != &ssl_sock)
71 return 0;
72
73 ctx = conn->xprt_ctx;
74
75 if (conn->flags & CO_FL_WAIT_XPRT) {
76 smp->flags |= SMP_F_MAY_CHANGE;
77 return 0;
78 }
79
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +020080 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +020081 smp->data.type = SMP_T_BOOL;
82 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
83
84 return 1;
85}
86
87/* binary, returns a certificate in a binary chunk (der/raw).
88 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
89 * should be use.
90 */
91static int
92smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
93{
William Lallemandbfa3e812020-06-25 20:07:18 +020094 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
95 int conn_server = (kw[4] == 's') ? 1 : 0;
96
William Lallemand15e16942020-05-15 00:25:08 +020097 X509 *crt = NULL;
98 int ret = 0;
99 struct buffer *smp_trash;
100 struct connection *conn;
101 SSL *ssl;
102
William Lallemandbfa3e812020-06-25 20:07:18 +0200103 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200104 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200105 else
106 conn = objt_conn(smp->sess->origin);
107
William Lallemand15e16942020-05-15 00:25:08 +0200108 ssl = ssl_sock_get_ssl_object(conn);
109 if (!ssl)
110 return 0;
111
112 if (conn->flags & CO_FL_WAIT_XPRT) {
113 smp->flags |= SMP_F_MAY_CHANGE;
114 return 0;
115 }
116
117 if (cert_peer)
118 crt = SSL_get_peer_certificate(ssl);
119 else
120 crt = SSL_get_certificate(ssl);
121
122 if (!crt)
123 goto out;
124
125 smp_trash = get_trash_chunk();
126 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
127 goto out;
128
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200129 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200130 smp->data.u.str = *smp_trash;
131 smp->data.type = SMP_T_BIN;
132 ret = 1;
133out:
134 /* SSL_get_peer_certificate, it increase X509 * ref count */
135 if (cert_peer && crt)
136 X509_free(crt);
137 return ret;
138}
139
William Dauchya598b502020-08-06 18:11:38 +0200140/* binary, returns a chain certificate in a binary chunk (der/raw).
141 * The 5th keyword char is used to support only peer cert
142 */
143static int
144smp_fetch_ssl_x_chain_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
145{
146 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
147 int conn_server = (kw[4] == 's') ? 1 : 0;
148 struct buffer *smp_trash;
149 struct buffer *tmp_trash = NULL;
150 struct connection *conn;
151 STACK_OF(X509) *certs = NULL;
152 X509 *crt = NULL;
153 SSL *ssl;
154 int ret = 0;
155 int num_certs;
156 int i;
157
158 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200159 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Dauchya598b502020-08-06 18:11:38 +0200160 else
161 conn = objt_conn(smp->sess->origin);
162
163 if (!conn)
164 return 0;
165
166 ssl = ssl_sock_get_ssl_object(conn);
167 if (!ssl)
168 return 0;
169
170 if (conn->flags & CO_FL_WAIT_XPRT) {
171 smp->flags |= SMP_F_MAY_CHANGE;
172 return 0;
173 }
174
175 if (!cert_peer)
176 return 0;
177
178 certs = SSL_get_peer_cert_chain(ssl);
179 if (!certs)
180 return 0;
181
182 num_certs = sk_X509_num(certs);
183 if (!num_certs)
184 goto out;
185 smp_trash = get_trash_chunk();
186 tmp_trash = alloc_trash_chunk();
187 if (!tmp_trash)
188 goto out;
189 for (i = 0; i < num_certs; i++) {
190 crt = sk_X509_value(certs, i);
191 if (ssl_sock_crt2der(crt, tmp_trash) <= 0)
192 goto out;
193 chunk_cat(smp_trash, tmp_trash);
194 }
195
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200196 smp->flags = SMP_F_VOL_SESS;
William Dauchya598b502020-08-06 18:11:38 +0200197 smp->data.u.str = *smp_trash;
198 smp->data.type = SMP_T_BIN;
199 ret = 1;
200out:
201 if (tmp_trash)
202 free_trash_chunk(tmp_trash);
William Dauchya598b502020-08-06 18:11:38 +0200203 return ret;
204}
205
William Lallemand15e16942020-05-15 00:25:08 +0200206/* binary, returns serial of certificate in a binary chunk.
207 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
208 * should be use.
209 */
210static int
211smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
212{
William Lallemandbfa3e812020-06-25 20:07:18 +0200213 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
214 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200215 X509 *crt = NULL;
216 int ret = 0;
217 struct buffer *smp_trash;
218 struct connection *conn;
219 SSL *ssl;
220
William Lallemandbfa3e812020-06-25 20:07:18 +0200221 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200222 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200223 else
224 conn = objt_conn(smp->sess->origin);
William Lallemand15e16942020-05-15 00:25:08 +0200225 ssl = ssl_sock_get_ssl_object(conn);
226 if (!ssl)
227 return 0;
228
229 if (conn->flags & CO_FL_WAIT_XPRT) {
230 smp->flags |= SMP_F_MAY_CHANGE;
231 return 0;
232 }
233
234 if (cert_peer)
235 crt = SSL_get_peer_certificate(ssl);
236 else
237 crt = SSL_get_certificate(ssl);
238
239 if (!crt)
240 goto out;
241
242 smp_trash = get_trash_chunk();
243 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
244 goto out;
245
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200246 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200247 smp->data.u.str = *smp_trash;
248 smp->data.type = SMP_T_BIN;
249 ret = 1;
250out:
251 /* SSL_get_peer_certificate, it increase X509 * ref count */
252 if (cert_peer && crt)
253 X509_free(crt);
254 return ret;
255}
256
257/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
258 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
259 * should be use.
260 */
261static int
262smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
263{
William Lallemandbfa3e812020-06-25 20:07:18 +0200264 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
265 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200266 X509 *crt = NULL;
267 const EVP_MD *digest;
268 int ret = 0;
269 unsigned int len = 0;
270 struct buffer *smp_trash;
271 struct connection *conn;
272 SSL *ssl;
273
William Lallemandbfa3e812020-06-25 20:07:18 +0200274 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200275 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200276 else
277 conn = objt_conn(smp->sess->origin);
278
William Lallemand15e16942020-05-15 00:25:08 +0200279 ssl = ssl_sock_get_ssl_object(conn);
280 if (!ssl)
281 return 0;
282
283 if (conn->flags & CO_FL_WAIT_XPRT) {
284 smp->flags |= SMP_F_MAY_CHANGE;
285 return 0;
286 }
287
288 if (cert_peer)
289 crt = SSL_get_peer_certificate(ssl);
290 else
291 crt = SSL_get_certificate(ssl);
292 if (!crt)
293 goto out;
294
295 smp_trash = get_trash_chunk();
296 digest = EVP_sha1();
297 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
298 smp_trash->data = len;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200299 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200300 smp->data.u.str = *smp_trash;
301 smp->data.type = SMP_T_BIN;
302 ret = 1;
303out:
304 /* SSL_get_peer_certificate, it increase X509 * ref count */
305 if (cert_peer && crt)
306 X509_free(crt);
307 return ret;
308}
309
310/* string, returns certificate's notafter date in ASN1_UTCTIME format.
311 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
312 * should be use.
313 */
314static int
315smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
316{
William Lallemandbfa3e812020-06-25 20:07:18 +0200317 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
318 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200319 X509 *crt = NULL;
320 int ret = 0;
321 struct buffer *smp_trash;
322 struct connection *conn;
323 SSL *ssl;
324
William Lallemandbfa3e812020-06-25 20:07:18 +0200325 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200326 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200327 else
328 conn = objt_conn(smp->sess->origin);
329
William Lallemand15e16942020-05-15 00:25:08 +0200330 ssl = ssl_sock_get_ssl_object(conn);
331 if (!ssl)
332 return 0;
333
334 if (conn->flags & CO_FL_WAIT_XPRT) {
335 smp->flags |= SMP_F_MAY_CHANGE;
336 return 0;
337 }
338
339 if (cert_peer)
340 crt = SSL_get_peer_certificate(ssl);
341 else
342 crt = SSL_get_certificate(ssl);
343 if (!crt)
344 goto out;
345
346 smp_trash = get_trash_chunk();
347 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
348 goto out;
349
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200350 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200351 smp->data.u.str = *smp_trash;
352 smp->data.type = SMP_T_STR;
353 ret = 1;
354out:
355 /* SSL_get_peer_certificate, it increase X509 * ref count */
356 if (cert_peer && crt)
357 X509_free(crt);
358 return ret;
359}
360
361/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
362 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
363 * should be use.
364 */
365static int
366smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
367{
William Lallemandbfa3e812020-06-25 20:07:18 +0200368 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
369 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200370 X509 *crt = NULL;
371 X509_NAME *name;
372 int ret = 0;
373 struct buffer *smp_trash;
374 struct connection *conn;
375 SSL *ssl;
376
William Lallemandbfa3e812020-06-25 20:07:18 +0200377 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200378 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200379 else
380 conn = objt_conn(smp->sess->origin);
381
William Lallemand15e16942020-05-15 00:25:08 +0200382 ssl = ssl_sock_get_ssl_object(conn);
383 if (!ssl)
384 return 0;
385
386 if (conn->flags & CO_FL_WAIT_XPRT) {
387 smp->flags |= SMP_F_MAY_CHANGE;
388 return 0;
389 }
390
391 if (cert_peer)
392 crt = SSL_get_peer_certificate(ssl);
393 else
394 crt = SSL_get_certificate(ssl);
395 if (!crt)
396 goto out;
397
398 name = X509_get_issuer_name(crt);
399 if (!name)
400 goto out;
401
402 smp_trash = get_trash_chunk();
Christopher Faulet3702f782021-01-29 11:30:37 +0100403 if (args[0].type == ARGT_STR && args[0].data.str.data > 0) {
William Lallemand15e16942020-05-15 00:25:08 +0200404 int pos = 1;
405
406 if (args[1].type == ARGT_SINT)
407 pos = args[1].data.sint;
408
409 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
410 goto out;
411 }
Christopher Faulet3702f782021-01-29 11:30:37 +0100412 else if (args[2].type == ARGT_STR && args[2].data.str.data > 0) {
William Lallemand15e16942020-05-15 00:25:08 +0200413 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
414 goto out;
415 }
416 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
417 goto out;
418
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200419 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200420 smp->data.type = SMP_T_STR;
421 smp->data.u.str = *smp_trash;
422 ret = 1;
423out:
424 /* SSL_get_peer_certificate, it increase X509 * ref count */
425 if (cert_peer && crt)
426 X509_free(crt);
427 return ret;
428}
429
430/* string, returns notbefore date in ASN1_UTCTIME format.
431 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
432 * should be use.
433 */
434static int
435smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
436{
William Lallemandbfa3e812020-06-25 20:07:18 +0200437 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
438 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200439 X509 *crt = NULL;
440 int ret = 0;
441 struct buffer *smp_trash;
442 struct connection *conn;
443 SSL *ssl;
444
William Lallemandbfa3e812020-06-25 20:07:18 +0200445 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200446 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200447 else
448 conn = objt_conn(smp->sess->origin);
449
William Lallemand15e16942020-05-15 00:25:08 +0200450 ssl = ssl_sock_get_ssl_object(conn);
451 if (!ssl)
452 return 0;
453
454 if (conn->flags & CO_FL_WAIT_XPRT) {
455 smp->flags |= SMP_F_MAY_CHANGE;
456 return 0;
457 }
458
459 if (cert_peer)
460 crt = SSL_get_peer_certificate(ssl);
461 else
462 crt = SSL_get_certificate(ssl);
463 if (!crt)
464 goto out;
465
466 smp_trash = get_trash_chunk();
467 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
468 goto out;
469
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200470 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200471 smp->data.u.str = *smp_trash;
472 smp->data.type = SMP_T_STR;
473 ret = 1;
474out:
475 /* SSL_get_peer_certificate, it increase X509 * ref count */
476 if (cert_peer && crt)
477 X509_free(crt);
478 return ret;
479}
480
481/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
482 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
483 * should be use.
484 */
485static int
486smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
487{
William Lallemandbfa3e812020-06-25 20:07:18 +0200488 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
489 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200490 X509 *crt = NULL;
491 X509_NAME *name;
492 int ret = 0;
493 struct buffer *smp_trash;
494 struct connection *conn;
495 SSL *ssl;
496
William Lallemandbfa3e812020-06-25 20:07:18 +0200497 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200498 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200499 else
500 conn = objt_conn(smp->sess->origin);
501
William Lallemand15e16942020-05-15 00:25:08 +0200502 ssl = ssl_sock_get_ssl_object(conn);
503 if (!ssl)
504 return 0;
505
506 if (conn->flags & CO_FL_WAIT_XPRT) {
507 smp->flags |= SMP_F_MAY_CHANGE;
508 return 0;
509 }
510
511 if (cert_peer)
512 crt = SSL_get_peer_certificate(ssl);
513 else
514 crt = SSL_get_certificate(ssl);
515 if (!crt)
516 goto out;
517
518 name = X509_get_subject_name(crt);
519 if (!name)
520 goto out;
521
522 smp_trash = get_trash_chunk();
Christopher Faulet3702f782021-01-29 11:30:37 +0100523 if (args[0].type == ARGT_STR && args[0].data.str.data > 0) {
William Lallemand15e16942020-05-15 00:25:08 +0200524 int pos = 1;
525
526 if (args[1].type == ARGT_SINT)
527 pos = args[1].data.sint;
528
529 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
530 goto out;
531 }
Christopher Faulet3702f782021-01-29 11:30:37 +0100532 else if (args[2].type == ARGT_STR && args[2].data.str.data > 0) {
William Lallemand15e16942020-05-15 00:25:08 +0200533 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
534 goto out;
535 }
536 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
537 goto out;
538
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200539 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200540 smp->data.type = SMP_T_STR;
541 smp->data.u.str = *smp_trash;
542 ret = 1;
543out:
544 /* SSL_get_peer_certificate, it increase X509 * ref count */
545 if (cert_peer && crt)
546 X509_free(crt);
547 return ret;
548}
549
550/* integer, returns true if current session use a client certificate */
551static int
552smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
553{
554 X509 *crt;
555 struct connection *conn;
556 SSL *ssl;
557
558 conn = objt_conn(smp->sess->origin);
559 ssl = ssl_sock_get_ssl_object(conn);
560 if (!ssl)
561 return 0;
562
563 if (conn->flags & CO_FL_WAIT_XPRT) {
564 smp->flags |= SMP_F_MAY_CHANGE;
565 return 0;
566 }
567
568 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
569 crt = SSL_get_peer_certificate(ssl);
570 if (crt) {
571 X509_free(crt);
572 }
573
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200574 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200575 smp->data.type = SMP_T_BOOL;
576 smp->data.u.sint = (crt != NULL);
577 return 1;
578}
579
580/* integer, returns the certificate version
581 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
582 * should be use.
583 */
584static int
585smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
586{
William Lallemandbfa3e812020-06-25 20:07:18 +0200587 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
588 int conn_server = (kw[4] == 's') ? 1 : 0;
589
William Lallemand15e16942020-05-15 00:25:08 +0200590 X509 *crt;
591 struct connection *conn;
592 SSL *ssl;
593
William Lallemandbfa3e812020-06-25 20:07:18 +0200594 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200595 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200596 else
597 conn = objt_conn(smp->sess->origin);
William Lallemand15e16942020-05-15 00:25:08 +0200598 ssl = ssl_sock_get_ssl_object(conn);
599 if (!ssl)
600 return 0;
601
602 if (conn->flags & CO_FL_WAIT_XPRT) {
603 smp->flags |= SMP_F_MAY_CHANGE;
604 return 0;
605 }
606
607 if (cert_peer)
608 crt = SSL_get_peer_certificate(ssl);
609 else
610 crt = SSL_get_certificate(ssl);
611 if (!crt)
612 return 0;
613
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200614 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200615 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
616 /* SSL_get_peer_certificate increase X509 * ref count */
617 if (cert_peer)
618 X509_free(crt);
619 smp->data.type = SMP_T_SINT;
620
621 return 1;
622}
623
624/* string, returns the certificate's signature algorithm.
625 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
626 * should be use.
627 */
628static int
629smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
630{
William Lallemandbfa3e812020-06-25 20:07:18 +0200631 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
632 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200633 X509 *crt;
634 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
635 int nid;
636 struct connection *conn;
637 SSL *ssl;
638
William Lallemandbfa3e812020-06-25 20:07:18 +0200639 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200640 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200641 else
642 conn = objt_conn(smp->sess->origin);
643
William Lallemand15e16942020-05-15 00:25:08 +0200644 ssl = ssl_sock_get_ssl_object(conn);
645 if (!ssl)
646 return 0;
647
648 if (conn->flags & CO_FL_WAIT_XPRT) {
649 smp->flags |= SMP_F_MAY_CHANGE;
650 return 0;
651 }
652
653 if (cert_peer)
654 crt = SSL_get_peer_certificate(ssl);
655 else
656 crt = SSL_get_certificate(ssl);
657 if (!crt)
658 return 0;
659
660 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
661 nid = OBJ_obj2nid(algorithm);
662
663 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
664 if (!smp->data.u.str.area) {
665 /* SSL_get_peer_certificate increase X509 * ref count */
666 if (cert_peer)
667 X509_free(crt);
668 return 0;
669 }
670
671 smp->data.type = SMP_T_STR;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200672 smp->flags |= SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +0200673 smp->data.u.str.data = strlen(smp->data.u.str.area);
674 /* SSL_get_peer_certificate increase X509 * ref count */
675 if (cert_peer)
676 X509_free(crt);
677
678 return 1;
679}
680
681/* string, returns the certificate's key algorithm.
682 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
683 * should be use.
684 */
685static int
686smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
687{
William Lallemandbfa3e812020-06-25 20:07:18 +0200688 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
689 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200690 X509 *crt;
691 ASN1_OBJECT *algorithm;
692 int nid;
693 struct connection *conn;
694 SSL *ssl;
695
William Lallemandbfa3e812020-06-25 20:07:18 +0200696 if (conn_server)
Amaury Denoyelle73617f92021-07-21 11:50:12 +0200697 conn = smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
William Lallemandbfa3e812020-06-25 20:07:18 +0200698 else
699 conn = objt_conn(smp->sess->origin);
William Lallemand15e16942020-05-15 00:25:08 +0200700 ssl = ssl_sock_get_ssl_object(conn);
701 if (!ssl)
702 return 0;
703
704 if (conn->flags & CO_FL_WAIT_XPRT) {
705 smp->flags |= SMP_F_MAY_CHANGE;
706 return 0;
707 }
708
709 if (cert_peer)
710 crt = SSL_get_peer_certificate(ssl);
711 else
712 crt = SSL_get_certificate(ssl);
713 if (!crt)
714 return 0;
715
716 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
717 nid = OBJ_obj2nid(algorithm);
718
719 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
720 if (!smp->data.u.str.area) {
721 /* SSL_get_peer_certificate increase X509 * ref count */
722 if (cert_peer)
723 X509_free(crt);
724 return 0;
725 }
726
727 smp->data.type = SMP_T_STR;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200728 smp->flags |= SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +0200729 smp->data.u.str.data = strlen(smp->data.u.str.area);
730 if (cert_peer)
731 X509_free(crt);
732
733 return 1;
734}
735
736/* boolean, returns true if front conn. transport layer is SSL.
737 * This function is also usable on backend conn if the fetch keyword 5th
738 * char is 'b'.
739 */
740static int
741smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
742{
743 struct connection *conn;
744
745 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +0200746 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +0200747 else
748 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
749 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
750
751 smp->data.type = SMP_T_BOOL;
752 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
753 return 1;
754}
755
756/* boolean, returns true if client present a SNI */
757static int
758smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
759{
760#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
761 struct connection *conn = objt_conn(smp->sess->origin);
762 SSL *ssl = ssl_sock_get_ssl_object(conn);
763
764 smp->data.type = SMP_T_BOOL;
765 smp->data.u.sint = ssl && SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) != NULL;
766 return 1;
767#else
768 return 0;
769#endif
770}
771
772/* boolean, returns true if client session has been resumed.
773 * This function is also usable on backend conn if the fetch keyword 5th
774 * char is 'b'.
775 */
776static int
777smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
778{
779 struct connection *conn;
780 SSL *ssl;
781
782 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +0200783 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +0200784 else
785 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
786 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
787
788 ssl = ssl_sock_get_ssl_object(conn);
789
790 smp->data.type = SMP_T_BOOL;
791 smp->data.u.sint = ssl && SSL_session_reused(ssl);
792 return 1;
793}
794
795/* string, returns the used cipher if front conn. transport layer is SSL.
796 * This function is also usable on backend conn if the fetch keyword 5th
797 * char is 'b'.
798 */
799static int
800smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
801{
802 struct connection *conn;
803 SSL *ssl;
804
805 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +0200806 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +0200807 else
808 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
809 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
810
811 smp->flags = 0;
812 ssl = ssl_sock_get_ssl_object(conn);
813 if (!ssl)
814 return 0;
815
816 smp->data.u.str.area = (char *)SSL_get_cipher_name(ssl);
817 if (!smp->data.u.str.area)
818 return 0;
819
820 smp->data.type = SMP_T_STR;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200821 smp->flags |= SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +0200822 smp->data.u.str.data = strlen(smp->data.u.str.area);
823
824 return 1;
825}
826
827/* integer, returns the algoritm's keysize if front conn. transport layer
828 * is SSL.
829 * This function is also usable on backend conn if the fetch keyword 5th
830 * char is 'b'.
831 */
832static int
833smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
834{
835 struct connection *conn;
836 SSL *ssl;
837 int sint;
838
839 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +0200840 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +0200841 else
842 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
843 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
844
845 smp->flags = 0;
846 ssl = ssl_sock_get_ssl_object(conn);
847 if (!ssl)
848 return 0;
849
850 if (!SSL_get_cipher_bits(ssl, &sint))
851 return 0;
852
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200853 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200854 smp->data.u.sint = sint;
855 smp->data.type = SMP_T_SINT;
856
857 return 1;
858}
859
860/* integer, returns the used keysize if front conn. transport layer is SSL.
861 * This function is also usable on backend conn if the fetch keyword 5th
862 * char is 'b'.
863 */
864static int
865smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
866{
867 struct connection *conn;
868 SSL *ssl;
869
870 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +0200871 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +0200872 else
873 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
874 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
875
876 smp->flags = 0;
877 ssl = ssl_sock_get_ssl_object(conn);
878 if (!ssl)
879 return 0;
880
881 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ssl, NULL);
882 if (!smp->data.u.sint)
883 return 0;
884
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200885 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200886 smp->data.type = SMP_T_SINT;
887
888 return 1;
889}
890
891#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
892static int
893smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
894{
895 struct connection *conn;
896 SSL *ssl;
897 unsigned int len = 0;
898
899 smp->flags = SMP_F_CONST;
900 smp->data.type = SMP_T_STR;
901
902 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +0200903 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +0200904 else
905 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
906 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
907
908 ssl = ssl_sock_get_ssl_object(conn);
909 if (!ssl)
910 return 0;
911
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200912 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +0200913 smp->data.u.str.area = NULL;
914 SSL_get0_next_proto_negotiated(ssl,
915 (const unsigned char **)&smp->data.u.str.area,
916 &len);
917
918 if (!smp->data.u.str.area)
919 return 0;
920
921 smp->data.u.str.data = len;
922 return 1;
923}
924#endif
925
926#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
927static int
928smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
929{
930 struct connection *conn;
931 SSL *ssl;
932 unsigned int len = 0;
933
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200934 smp->flags = SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +0200935 smp->data.type = SMP_T_STR;
936
937 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +0200938 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +0200939 else
940 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
941 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
942
943 ssl = ssl_sock_get_ssl_object(conn);
944 if (!ssl)
945 return 0;
946
947 smp->data.u.str.area = NULL;
948 SSL_get0_alpn_selected(ssl,
949 (const unsigned char **)&smp->data.u.str.area,
950 &len);
951
952 if (!smp->data.u.str.area)
953 return 0;
954
955 smp->data.u.str.data = len;
956 return 1;
957}
958#endif
959
960/* string, returns the used protocol if front conn. transport layer is SSL.
961 * This function is also usable on backend conn if the fetch keyword 5th
962 * char is 'b'.
963 */
964static int
965smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
966{
967 struct connection *conn;
968 SSL *ssl;
969
970 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +0200971 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +0200972 else
973 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
974 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
975
976 smp->flags = 0;
977 ssl = ssl_sock_get_ssl_object(conn);
978 if (!ssl)
979 return 0;
980
981 smp->data.u.str.area = (char *)SSL_get_version(ssl);
982 if (!smp->data.u.str.area)
983 return 0;
984
985 smp->data.type = SMP_T_STR;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +0200986 smp->flags = SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +0200987 smp->data.u.str.data = strlen(smp->data.u.str.area);
988
989 return 1;
990}
991
992/* binary, returns the SSL stream id if front conn. transport layer is SSL.
993 * This function is also usable on backend conn if the fetch keyword 5th
994 * char is 'b'.
995 */
996#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
997static int
998smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
999{
1000 struct connection *conn;
1001 SSL_SESSION *ssl_sess;
1002 SSL *ssl;
1003 unsigned int len = 0;
1004
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001005 smp->flags = SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +02001006 smp->data.type = SMP_T_BIN;
1007
1008 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +02001009 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001010 else
1011 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
1012 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
1013
1014 ssl = ssl_sock_get_ssl_object(conn);
1015 if (!ssl)
1016 return 0;
1017
1018 ssl_sess = SSL_get_session(ssl);
1019 if (!ssl_sess)
1020 return 0;
1021
1022 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
1023 if (!smp->data.u.str.area || !len)
1024 return 0;
1025
1026 smp->data.u.str.data = len;
1027 return 1;
1028}
1029#endif
1030
1031
Ilya Shipitsindf627942021-03-25 00:41:41 +05001032#ifdef HAVE_SSL_EXTRACT_RANDOM
William Lallemand15e16942020-05-15 00:25:08 +02001033static int
1034smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
1035{
1036 struct connection *conn;
1037 struct buffer *data;
1038 SSL *ssl;
1039
1040 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +02001041 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001042 else
1043 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
1044 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
1045
1046 ssl = ssl_sock_get_ssl_object(conn);
1047 if (!ssl)
1048 return 0;
1049
1050 data = get_trash_chunk();
1051 if (kw[7] == 'c')
1052 data->data = SSL_get_client_random(ssl,
1053 (unsigned char *) data->area,
1054 data->size);
1055 else
1056 data->data = SSL_get_server_random(ssl,
1057 (unsigned char *) data->area,
1058 data->size);
1059 if (!data->data)
1060 return 0;
1061
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001062 smp->flags = SMP_F_VOL_TEST;
William Lallemand15e16942020-05-15 00:25:08 +02001063 smp->data.type = SMP_T_BIN;
1064 smp->data.u.str = *data;
1065
1066 return 1;
1067}
1068
1069static int
1070smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
1071{
1072 struct connection *conn;
1073 SSL_SESSION *ssl_sess;
1074 struct buffer *data;
1075 SSL *ssl;
1076
1077 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +02001078 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001079 else
1080 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
1081 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
1082
1083 ssl = ssl_sock_get_ssl_object(conn);
1084 if (!ssl)
1085 return 0;
1086
1087 ssl_sess = SSL_get_session(ssl);
1088 if (!ssl_sess)
1089 return 0;
1090
1091 data = get_trash_chunk();
1092 data->data = SSL_SESSION_get_master_key(ssl_sess,
1093 (unsigned char *) data->area,
1094 data->size);
1095 if (!data->data)
1096 return 0;
1097
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001098 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001099 smp->data.type = SMP_T_BIN;
1100 smp->data.u.str = *data;
1101
1102 return 1;
1103}
1104#endif
1105
1106#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1107static int
1108smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
1109{
1110 struct connection *conn;
1111 SSL *ssl;
1112
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001113 smp->flags = SMP_F_VOL_SESS | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +02001114 smp->data.type = SMP_T_STR;
1115
1116 conn = objt_conn(smp->sess->origin);
1117 ssl = ssl_sock_get_ssl_object(conn);
1118 if (!ssl)
1119 return 0;
1120
1121 smp->data.u.str.area = (char *)SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
1122 if (!smp->data.u.str.area)
1123 return 0;
1124
1125 smp->data.u.str.data = strlen(smp->data.u.str.area);
1126 return 1;
1127}
1128#endif
1129
1130static int
1131smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
1132{
1133 struct connection *conn;
1134 struct ssl_capture *capture;
1135 SSL *ssl;
1136
1137 conn = objt_conn(smp->sess->origin);
1138 ssl = ssl_sock_get_ssl_object(conn);
1139 if (!ssl)
1140 return 0;
1141
1142 capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
1143 if (!capture)
1144 return 0;
1145
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001146 smp->flags = SMP_F_VOL_TEST | SMP_F_CONST;
William Lallemand15e16942020-05-15 00:25:08 +02001147 smp->data.type = SMP_T_BIN;
1148 smp->data.u.str.area = capture->ciphersuite;
1149 smp->data.u.str.data = capture->ciphersuite_len;
1150 return 1;
1151}
1152
1153static int
1154smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
1155{
1156 struct buffer *data;
1157
1158 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
1159 return 0;
1160
1161 data = get_trash_chunk();
1162 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001163 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001164 smp->data.type = SMP_T_BIN;
1165 smp->data.u.str = *data;
1166 return 1;
1167}
1168
1169static int
1170smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
1171{
1172 struct connection *conn;
1173 struct ssl_capture *capture;
1174 SSL *ssl;
1175
1176 conn = objt_conn(smp->sess->origin);
1177 ssl = ssl_sock_get_ssl_object(conn);
1178 if (!ssl)
1179 return 0;
1180
1181 capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
1182 if (!capture)
1183 return 0;
1184
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001185 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001186 smp->data.type = SMP_T_SINT;
1187 smp->data.u.sint = capture->xxh64;
1188 return 1;
1189}
1190
William Lallemand7d42ef52020-07-06 11:41:30 +02001191/* Dump the SSL keylog, it only works with "tune.ssl.keylog 1" */
William Lallemandca5cf0a2021-06-09 16:46:12 +02001192#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +02001193static int smp_fetch_ssl_x_keylog(const struct arg *args, struct sample *smp, const char *kw, void *private)
1194{
1195 struct connection *conn;
1196 struct ssl_keylog *keylog;
1197 SSL *ssl;
1198 char *src = NULL;
1199 const char *sfx;
1200
1201 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
1202 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
1203
William Lallemandeec1d452020-07-07 10:48:13 +02001204 if (!conn)
1205 return 0;
1206
William Lallemand7d42ef52020-07-06 11:41:30 +02001207 if (conn->flags & CO_FL_WAIT_XPRT) {
1208 smp->flags |= SMP_F_MAY_CHANGE;
1209 return 0;
1210 }
1211
1212 ssl = ssl_sock_get_ssl_object(conn);
1213 if (!ssl)
1214 return 0;
1215
1216 keylog = SSL_get_ex_data(ssl, ssl_keylog_index);
1217 if (!keylog)
1218 return 0;
1219
1220 sfx = kw + strlen("ssl_xx_");
1221
1222 if (strcmp(sfx, "client_early_traffic_secret") == 0) {
1223 src = keylog->client_early_traffic_secret;
1224 } else if (strcmp(sfx, "client_handshake_traffic_secret") == 0) {
1225 src = keylog->client_handshake_traffic_secret;
1226 } else if (strcmp(sfx, "server_handshake_traffic_secret") == 0) {
1227 src = keylog->server_handshake_traffic_secret;
1228 } else if (strcmp(sfx, "client_traffic_secret_0") == 0) {
1229 src = keylog->client_traffic_secret_0;
1230 } else if (strcmp(sfx, "server_traffic_secret_0") == 0) {
1231 src = keylog->server_traffic_secret_0;
1232 } else if (strcmp(sfx, "exporter_secret") == 0) {
1233 src = keylog->exporter_secret;
1234 } else if (strcmp(sfx, "early_exporter_secret") == 0) {
1235 src = keylog->early_exporter_secret;
1236 }
1237
1238 if (!src || !*src)
1239 return 0;
1240
1241 smp->data.u.str.area = src;
1242 smp->data.type = SMP_T_STR;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001243 smp->flags |= SMP_F_VOL_TEST | SMP_F_CONST;
William Lallemand7d42ef52020-07-06 11:41:30 +02001244 smp->data.u.str.data = strlen(smp->data.u.str.area);
1245 return 1;
William Lallemand7d42ef52020-07-06 11:41:30 +02001246}
1247#endif
1248
William Lallemand15e16942020-05-15 00:25:08 +02001249static int
1250smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
1251{
Ilya Shipitsinc9dfee42020-10-31 02:10:02 +05001252#if defined(OPENSSL_IS_BORINGSSL) || defined(SSL_CTRL_GET_RAW_CIPHERLIST)
William Lallemand15e16942020-05-15 00:25:08 +02001253 struct buffer *data;
1254 int i;
1255
1256 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
1257 return 0;
1258
1259 data = get_trash_chunk();
1260 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
1261 const char *str;
1262 const SSL_CIPHER *cipher;
1263 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
1264 uint16_t id = (bin[0] << 8) | bin[1];
1265#if defined(OPENSSL_IS_BORINGSSL)
1266 cipher = SSL_get_cipher_by_value(id);
1267#else
1268 struct connection *conn = __objt_conn(smp->sess->origin);
1269 SSL *ssl = ssl_sock_get_ssl_object(conn);
1270 cipher = SSL_CIPHER_find(ssl, bin);
1271#endif
1272 str = SSL_CIPHER_get_name(cipher);
1273 if (!str || strcmp(str, "(NONE)") == 0)
1274 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
1275 else
1276 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
1277 }
1278 smp->data.type = SMP_T_STR;
1279 smp->data.u.str = *data;
1280 return 1;
1281#else
1282 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
1283#endif
1284}
1285
1286#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
1287static int
1288smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
1289{
1290 struct connection *conn;
1291 int finished_len;
1292 struct buffer *finished_trash;
1293 SSL *ssl;
1294
1295 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
Christopher Faulet4bef8d12021-04-14 15:49:41 +02001296 conn = (kw[4] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
William Lallemand15e16942020-05-15 00:25:08 +02001297 else
1298 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
1299 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
1300
1301 smp->flags = 0;
1302 ssl = ssl_sock_get_ssl_object(conn);
1303 if (!ssl)
1304 return 0;
1305
1306 if (conn->flags & CO_FL_WAIT_XPRT) {
1307 smp->flags |= SMP_F_MAY_CHANGE;
1308 return 0;
1309 }
1310
1311 finished_trash = get_trash_chunk();
1312 if (!SSL_session_reused(ssl))
1313 finished_len = SSL_get_peer_finished(ssl,
1314 finished_trash->area,
1315 finished_trash->size);
1316 else
1317 finished_len = SSL_get_finished(ssl,
1318 finished_trash->area,
1319 finished_trash->size);
1320
1321 if (!finished_len)
1322 return 0;
1323
1324 finished_trash->data = finished_len;
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001325 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001326 smp->data.u.str = *finished_trash;
1327 smp->data.type = SMP_T_BIN;
1328
1329 return 1;
1330}
1331#endif
1332
1333/* integer, returns the first verify error in CA chain of client certificate chain. */
1334static int
1335smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
1336{
1337 struct connection *conn;
1338 struct ssl_sock_ctx *ctx;
1339
1340 conn = objt_conn(smp->sess->origin);
1341 if (!conn || conn->xprt != &ssl_sock)
1342 return 0;
1343 ctx = conn->xprt_ctx;
1344
1345 if (conn->flags & CO_FL_WAIT_XPRT) {
1346 smp->flags = SMP_F_MAY_CHANGE;
1347 return 0;
1348 }
1349
1350 smp->data.type = SMP_T_SINT;
1351 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001352 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001353
1354 return 1;
1355}
1356
1357/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
1358static int
1359smp_fetch_ssl_c_ca_err_depth(const struct arg *args, struct sample *smp, const char *kw, void *private)
1360{
1361 struct connection *conn;
1362 struct ssl_sock_ctx *ctx;
1363
1364 conn = objt_conn(smp->sess->origin);
1365 if (!conn || conn->xprt != &ssl_sock)
1366 return 0;
1367
1368 if (conn->flags & CO_FL_WAIT_XPRT) {
1369 smp->flags = SMP_F_MAY_CHANGE;
1370 return 0;
1371 }
1372 ctx = conn->xprt_ctx;
1373
1374 smp->data.type = SMP_T_SINT;
1375 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001376 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001377
1378 return 1;
1379}
1380
1381/* integer, returns the first verify error on client certificate */
1382static int
1383smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
1384{
1385 struct connection *conn;
1386 struct ssl_sock_ctx *ctx;
1387
1388 conn = objt_conn(smp->sess->origin);
1389 if (!conn || conn->xprt != &ssl_sock)
1390 return 0;
1391
1392 if (conn->flags & CO_FL_WAIT_XPRT) {
1393 smp->flags = SMP_F_MAY_CHANGE;
1394 return 0;
1395 }
1396
1397 ctx = conn->xprt_ctx;
1398
1399 smp->data.type = SMP_T_SINT;
1400 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001401 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001402
1403 return 1;
1404}
1405
1406/* integer, returns the verify result on client cert */
1407static int
1408smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
1409{
1410 struct connection *conn;
1411 SSL *ssl;
1412
1413 conn = objt_conn(smp->sess->origin);
1414 ssl = ssl_sock_get_ssl_object(conn);
1415 if (!ssl)
1416 return 0;
1417
1418 if (conn->flags & CO_FL_WAIT_XPRT) {
1419 smp->flags = SMP_F_MAY_CHANGE;
1420 return 0;
1421 }
1422
1423 smp->data.type = SMP_T_SINT;
1424 smp->data.u.sint = (long long int)SSL_get_verify_result(ssl);
Amaury Denoyelle2f0a7972020-10-15 16:41:08 +02001425 smp->flags = SMP_F_VOL_SESS;
William Lallemand15e16942020-05-15 00:25:08 +02001426
1427 return 1;
1428}
1429
1430/* Argument validation functions */
1431
1432/* This function is used to validate the arguments passed to any "x_dn" ssl
1433 * keywords. These keywords support specifying a third parameter that must be
1434 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
1435 */
1436int val_dnfmt(struct arg *arg, char **err_msg)
1437{
1438 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
1439 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
1440 return 0;
1441 }
1442 return 1;
1443}
1444
1445/* Note: must not be declared <const> as its list will be overwritten.
1446 * Please take care of keeping this list alphabetically sorted.
1447 */
1448static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
1449 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
1450 { "ssl_bc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
1451#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1452 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
1453#endif
1454 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
1455#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1456 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
1457#endif
1458 { "ssl_bc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
1459 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
1460 { "ssl_bc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
1461 { "ssl_bc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
1462#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
1463 { "ssl_bc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
1464#endif
Ilya Shipitsindf627942021-03-25 00:41:41 +05001465#ifdef HAVE_SSL_EXTRACT_RANDOM
William Lallemand15e16942020-05-15 00:25:08 +02001466 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
1467 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
1468 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
1469#endif
1470 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1471 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1472 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
William Dauchya598b502020-08-06 18:11:38 +02001473 { "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 +02001474 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1475 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1476 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1477 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1478 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1479 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1480 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1481 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1482 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1483 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1484 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1485 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1486 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1487 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1488 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1489 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1490 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1491 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1492 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1493 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1494 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1495 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1496 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1497 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1498 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1499 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1500 { "ssl_fc_has_early", smp_fetch_ssl_fc_has_early, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1501 { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1502 { "ssl_fc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1503#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1504 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1505#endif
1506#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1507 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1508#endif
1509 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1510#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
1511 { "ssl_fc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1512#endif
1513 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1514#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
1515 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1516#endif
Ilya Shipitsindf627942021-03-25 00:41:41 +05001517#ifdef HAVE_SSL_EXTRACT_RANDOM
William Lallemand15e16942020-05-15 00:25:08 +02001518 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1519 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1520 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1521#endif
William Lallemand7d42ef52020-07-06 11:41:30 +02001522
William Lallemandca5cf0a2021-06-09 16:46:12 +02001523#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +02001524 { "ssl_fc_client_early_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1525 { "ssl_fc_client_handshake_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1526 { "ssl_fc_server_handshake_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1527 { "ssl_fc_client_traffic_secret_0", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1528 { "ssl_fc_server_traffic_secret_0", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1529 { "ssl_fc_exporter_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1530 { "ssl_fc_early_exporter_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1531#endif
1532
William Lallemand15e16942020-05-15 00:25:08 +02001533#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1534 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1535#endif
1536 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1537 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1538 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1539 { "ssl_fc_cipherlist_xxh", smp_fetch_ssl_fc_cl_xxh64, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
William Lallemandbfa3e812020-06-25 20:07:18 +02001540
1541/* SSL server certificate fetches */
1542 { "ssl_s_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
William Dauchya598b502020-08-06 18:11:38 +02001543 { "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 +02001544 { "ssl_s_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1545 { "ssl_s_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1546 { "ssl_s_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1547 { "ssl_s_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1548 { "ssl_s_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1549 { "ssl_s_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1550 { "ssl_s_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1551 { "ssl_s_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1552 { "ssl_s_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
William Lallemand15e16942020-05-15 00:25:08 +02001553 { NULL, NULL, 0, 0, 0 },
1554}};
1555
1556INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
1557
1558/* Note: must not be declared <const> as its list will be overwritten.
1559 * Please take care of keeping this list alphabetically sorted.
1560 */
1561static struct acl_kw_list acl_kws = {ILH, {
1562 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
1563 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
1564 { /* END */ },
1565}};
1566
1567INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);