blob: a21ae339791f0674bc308a46cfaf8228931192ba [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
80 smp->flags = 0;
81 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)
104 conn = cs_conn(objt_cs(smp->strm->si[1].end));
105 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
129 smp->data.u.str = *smp_trash;
130 smp->data.type = SMP_T_BIN;
131 ret = 1;
132out:
133 /* SSL_get_peer_certificate, it increase X509 * ref count */
134 if (cert_peer && crt)
135 X509_free(crt);
136 return ret;
137}
138
William Dauchya598b502020-08-06 18:11:38 +0200139/* binary, returns a chain certificate in a binary chunk (der/raw).
140 * The 5th keyword char is used to support only peer cert
141 */
142static int
143smp_fetch_ssl_x_chain_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
144{
145 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
146 int conn_server = (kw[4] == 's') ? 1 : 0;
147 struct buffer *smp_trash;
148 struct buffer *tmp_trash = NULL;
149 struct connection *conn;
150 STACK_OF(X509) *certs = NULL;
151 X509 *crt = NULL;
152 SSL *ssl;
153 int ret = 0;
154 int num_certs;
155 int i;
156
157 if (conn_server)
158 conn = cs_conn(objt_cs(smp->strm->si[1].end));
159 else
160 conn = objt_conn(smp->sess->origin);
161
162 if (!conn)
163 return 0;
164
165 ssl = ssl_sock_get_ssl_object(conn);
166 if (!ssl)
167 return 0;
168
169 if (conn->flags & CO_FL_WAIT_XPRT) {
170 smp->flags |= SMP_F_MAY_CHANGE;
171 return 0;
172 }
173
174 if (!cert_peer)
175 return 0;
176
177 certs = SSL_get_peer_cert_chain(ssl);
178 if (!certs)
179 return 0;
180
181 num_certs = sk_X509_num(certs);
182 if (!num_certs)
183 goto out;
184 smp_trash = get_trash_chunk();
185 tmp_trash = alloc_trash_chunk();
186 if (!tmp_trash)
187 goto out;
188 for (i = 0; i < num_certs; i++) {
189 crt = sk_X509_value(certs, i);
190 if (ssl_sock_crt2der(crt, tmp_trash) <= 0)
191 goto out;
192 chunk_cat(smp_trash, tmp_trash);
193 }
194
195 smp->data.u.str = *smp_trash;
196 smp->data.type = SMP_T_BIN;
197 ret = 1;
198out:
199 if (tmp_trash)
200 free_trash_chunk(tmp_trash);
201 if (certs)
202 sk_X509_pop_free(certs, X509_free);
203 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)
222 conn = cs_conn(objt_cs(smp->strm->si[1].end));
223 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
246 smp->data.u.str = *smp_trash;
247 smp->data.type = SMP_T_BIN;
248 ret = 1;
249out:
250 /* SSL_get_peer_certificate, it increase X509 * ref count */
251 if (cert_peer && crt)
252 X509_free(crt);
253 return ret;
254}
255
256/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
257 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
258 * should be use.
259 */
260static int
261smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
262{
William Lallemandbfa3e812020-06-25 20:07:18 +0200263 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
264 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200265 X509 *crt = NULL;
266 const EVP_MD *digest;
267 int ret = 0;
268 unsigned int len = 0;
269 struct buffer *smp_trash;
270 struct connection *conn;
271 SSL *ssl;
272
William Lallemandbfa3e812020-06-25 20:07:18 +0200273 if (conn_server)
274 conn = cs_conn(objt_cs(smp->strm->si[1].end));
275 else
276 conn = objt_conn(smp->sess->origin);
277
William Lallemand15e16942020-05-15 00:25:08 +0200278 ssl = ssl_sock_get_ssl_object(conn);
279 if (!ssl)
280 return 0;
281
282 if (conn->flags & CO_FL_WAIT_XPRT) {
283 smp->flags |= SMP_F_MAY_CHANGE;
284 return 0;
285 }
286
287 if (cert_peer)
288 crt = SSL_get_peer_certificate(ssl);
289 else
290 crt = SSL_get_certificate(ssl);
291 if (!crt)
292 goto out;
293
294 smp_trash = get_trash_chunk();
295 digest = EVP_sha1();
296 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
297 smp_trash->data = len;
298 smp->data.u.str = *smp_trash;
299 smp->data.type = SMP_T_BIN;
300 ret = 1;
301out:
302 /* SSL_get_peer_certificate, it increase X509 * ref count */
303 if (cert_peer && crt)
304 X509_free(crt);
305 return ret;
306}
307
308/* string, returns certificate's notafter date in ASN1_UTCTIME format.
309 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
310 * should be use.
311 */
312static int
313smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
314{
William Lallemandbfa3e812020-06-25 20:07:18 +0200315 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
316 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200317 X509 *crt = NULL;
318 int ret = 0;
319 struct buffer *smp_trash;
320 struct connection *conn;
321 SSL *ssl;
322
William Lallemandbfa3e812020-06-25 20:07:18 +0200323 if (conn_server)
324 conn = cs_conn(objt_cs(smp->strm->si[1].end));
325 else
326 conn = objt_conn(smp->sess->origin);
327
William Lallemand15e16942020-05-15 00:25:08 +0200328 ssl = ssl_sock_get_ssl_object(conn);
329 if (!ssl)
330 return 0;
331
332 if (conn->flags & CO_FL_WAIT_XPRT) {
333 smp->flags |= SMP_F_MAY_CHANGE;
334 return 0;
335 }
336
337 if (cert_peer)
338 crt = SSL_get_peer_certificate(ssl);
339 else
340 crt = SSL_get_certificate(ssl);
341 if (!crt)
342 goto out;
343
344 smp_trash = get_trash_chunk();
345 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
346 goto out;
347
348 smp->data.u.str = *smp_trash;
349 smp->data.type = SMP_T_STR;
350 ret = 1;
351out:
352 /* SSL_get_peer_certificate, it increase X509 * ref count */
353 if (cert_peer && crt)
354 X509_free(crt);
355 return ret;
356}
357
358/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
359 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
360 * should be use.
361 */
362static int
363smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
364{
William Lallemandbfa3e812020-06-25 20:07:18 +0200365 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
366 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200367 X509 *crt = NULL;
368 X509_NAME *name;
369 int ret = 0;
370 struct buffer *smp_trash;
371 struct connection *conn;
372 SSL *ssl;
373
William Lallemandbfa3e812020-06-25 20:07:18 +0200374 if (conn_server)
375 conn = cs_conn(objt_cs(smp->strm->si[1].end));
376 else
377 conn = objt_conn(smp->sess->origin);
378
William Lallemand15e16942020-05-15 00:25:08 +0200379 ssl = ssl_sock_get_ssl_object(conn);
380 if (!ssl)
381 return 0;
382
383 if (conn->flags & CO_FL_WAIT_XPRT) {
384 smp->flags |= SMP_F_MAY_CHANGE;
385 return 0;
386 }
387
388 if (cert_peer)
389 crt = SSL_get_peer_certificate(ssl);
390 else
391 crt = SSL_get_certificate(ssl);
392 if (!crt)
393 goto out;
394
395 name = X509_get_issuer_name(crt);
396 if (!name)
397 goto out;
398
399 smp_trash = get_trash_chunk();
400 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
401 int pos = 1;
402
403 if (args[1].type == ARGT_SINT)
404 pos = args[1].data.sint;
405
406 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
407 goto out;
408 }
409 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
410 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
411 goto out;
412 }
413 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
414 goto out;
415
416 smp->data.type = SMP_T_STR;
417 smp->data.u.str = *smp_trash;
418 ret = 1;
419out:
420 /* SSL_get_peer_certificate, it increase X509 * ref count */
421 if (cert_peer && crt)
422 X509_free(crt);
423 return ret;
424}
425
426/* string, returns notbefore date in ASN1_UTCTIME format.
427 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
428 * should be use.
429 */
430static int
431smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
432{
William Lallemandbfa3e812020-06-25 20:07:18 +0200433 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
434 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200435 X509 *crt = NULL;
436 int ret = 0;
437 struct buffer *smp_trash;
438 struct connection *conn;
439 SSL *ssl;
440
William Lallemandbfa3e812020-06-25 20:07:18 +0200441 if (conn_server)
442 conn = cs_conn(objt_cs(smp->strm->si[1].end));
443 else
444 conn = objt_conn(smp->sess->origin);
445
William Lallemand15e16942020-05-15 00:25:08 +0200446 ssl = ssl_sock_get_ssl_object(conn);
447 if (!ssl)
448 return 0;
449
450 if (conn->flags & CO_FL_WAIT_XPRT) {
451 smp->flags |= SMP_F_MAY_CHANGE;
452 return 0;
453 }
454
455 if (cert_peer)
456 crt = SSL_get_peer_certificate(ssl);
457 else
458 crt = SSL_get_certificate(ssl);
459 if (!crt)
460 goto out;
461
462 smp_trash = get_trash_chunk();
463 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
464 goto out;
465
466 smp->data.u.str = *smp_trash;
467 smp->data.type = SMP_T_STR;
468 ret = 1;
469out:
470 /* SSL_get_peer_certificate, it increase X509 * ref count */
471 if (cert_peer && crt)
472 X509_free(crt);
473 return ret;
474}
475
476/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
477 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
478 * should be use.
479 */
480static int
481smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
482{
William Lallemandbfa3e812020-06-25 20:07:18 +0200483 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
484 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200485 X509 *crt = NULL;
486 X509_NAME *name;
487 int ret = 0;
488 struct buffer *smp_trash;
489 struct connection *conn;
490 SSL *ssl;
491
William Lallemandbfa3e812020-06-25 20:07:18 +0200492 if (conn_server)
493 conn = cs_conn(objt_cs(smp->strm->si[1].end));
494 else
495 conn = objt_conn(smp->sess->origin);
496
William Lallemand15e16942020-05-15 00:25:08 +0200497 ssl = ssl_sock_get_ssl_object(conn);
498 if (!ssl)
499 return 0;
500
501 if (conn->flags & CO_FL_WAIT_XPRT) {
502 smp->flags |= SMP_F_MAY_CHANGE;
503 return 0;
504 }
505
506 if (cert_peer)
507 crt = SSL_get_peer_certificate(ssl);
508 else
509 crt = SSL_get_certificate(ssl);
510 if (!crt)
511 goto out;
512
513 name = X509_get_subject_name(crt);
514 if (!name)
515 goto out;
516
517 smp_trash = get_trash_chunk();
518 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
519 int pos = 1;
520
521 if (args[1].type == ARGT_SINT)
522 pos = args[1].data.sint;
523
524 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
525 goto out;
526 }
527 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
528 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
529 goto out;
530 }
531 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
532 goto out;
533
534 smp->data.type = SMP_T_STR;
535 smp->data.u.str = *smp_trash;
536 ret = 1;
537out:
538 /* SSL_get_peer_certificate, it increase X509 * ref count */
539 if (cert_peer && crt)
540 X509_free(crt);
541 return ret;
542}
543
544/* integer, returns true if current session use a client certificate */
545static int
546smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
547{
548 X509 *crt;
549 struct connection *conn;
550 SSL *ssl;
551
552 conn = objt_conn(smp->sess->origin);
553 ssl = ssl_sock_get_ssl_object(conn);
554 if (!ssl)
555 return 0;
556
557 if (conn->flags & CO_FL_WAIT_XPRT) {
558 smp->flags |= SMP_F_MAY_CHANGE;
559 return 0;
560 }
561
562 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
563 crt = SSL_get_peer_certificate(ssl);
564 if (crt) {
565 X509_free(crt);
566 }
567
568 smp->data.type = SMP_T_BOOL;
569 smp->data.u.sint = (crt != NULL);
570 return 1;
571}
572
573/* integer, returns the certificate version
574 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
575 * should be use.
576 */
577static int
578smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
579{
William Lallemandbfa3e812020-06-25 20:07:18 +0200580 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
581 int conn_server = (kw[4] == 's') ? 1 : 0;
582
William Lallemand15e16942020-05-15 00:25:08 +0200583 X509 *crt;
584 struct connection *conn;
585 SSL *ssl;
586
William Lallemandbfa3e812020-06-25 20:07:18 +0200587 if (conn_server)
588 conn = cs_conn(objt_cs(smp->strm->si[1].end));
589 else
590 conn = objt_conn(smp->sess->origin);
William Lallemand15e16942020-05-15 00:25:08 +0200591 ssl = ssl_sock_get_ssl_object(conn);
592 if (!ssl)
593 return 0;
594
595 if (conn->flags & CO_FL_WAIT_XPRT) {
596 smp->flags |= SMP_F_MAY_CHANGE;
597 return 0;
598 }
599
600 if (cert_peer)
601 crt = SSL_get_peer_certificate(ssl);
602 else
603 crt = SSL_get_certificate(ssl);
604 if (!crt)
605 return 0;
606
607 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
608 /* SSL_get_peer_certificate increase X509 * ref count */
609 if (cert_peer)
610 X509_free(crt);
611 smp->data.type = SMP_T_SINT;
612
613 return 1;
614}
615
616/* string, returns the certificate's signature algorithm.
617 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
618 * should be use.
619 */
620static int
621smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
622{
William Lallemandbfa3e812020-06-25 20:07:18 +0200623 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
624 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200625 X509 *crt;
626 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
627 int nid;
628 struct connection *conn;
629 SSL *ssl;
630
William Lallemandbfa3e812020-06-25 20:07:18 +0200631 if (conn_server)
632 conn = cs_conn(objt_cs(smp->strm->si[1].end));
633 else
634 conn = objt_conn(smp->sess->origin);
635
William Lallemand15e16942020-05-15 00:25:08 +0200636 ssl = ssl_sock_get_ssl_object(conn);
637 if (!ssl)
638 return 0;
639
640 if (conn->flags & CO_FL_WAIT_XPRT) {
641 smp->flags |= SMP_F_MAY_CHANGE;
642 return 0;
643 }
644
645 if (cert_peer)
646 crt = SSL_get_peer_certificate(ssl);
647 else
648 crt = SSL_get_certificate(ssl);
649 if (!crt)
650 return 0;
651
652 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
653 nid = OBJ_obj2nid(algorithm);
654
655 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
656 if (!smp->data.u.str.area) {
657 /* SSL_get_peer_certificate increase X509 * ref count */
658 if (cert_peer)
659 X509_free(crt);
660 return 0;
661 }
662
663 smp->data.type = SMP_T_STR;
664 smp->flags |= SMP_F_CONST;
665 smp->data.u.str.data = strlen(smp->data.u.str.area);
666 /* SSL_get_peer_certificate increase X509 * ref count */
667 if (cert_peer)
668 X509_free(crt);
669
670 return 1;
671}
672
673/* string, returns the certificate's key algorithm.
674 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
675 * should be use.
676 */
677static int
678smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
679{
William Lallemandbfa3e812020-06-25 20:07:18 +0200680 int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
681 int conn_server = (kw[4] == 's') ? 1 : 0;
William Lallemand15e16942020-05-15 00:25:08 +0200682 X509 *crt;
683 ASN1_OBJECT *algorithm;
684 int nid;
685 struct connection *conn;
686 SSL *ssl;
687
William Lallemandbfa3e812020-06-25 20:07:18 +0200688 if (conn_server)
689 conn = cs_conn(objt_cs(smp->strm->si[1].end));
690 else
691 conn = objt_conn(smp->sess->origin);
William Lallemand15e16942020-05-15 00:25:08 +0200692 ssl = ssl_sock_get_ssl_object(conn);
693 if (!ssl)
694 return 0;
695
696 if (conn->flags & CO_FL_WAIT_XPRT) {
697 smp->flags |= SMP_F_MAY_CHANGE;
698 return 0;
699 }
700
701 if (cert_peer)
702 crt = SSL_get_peer_certificate(ssl);
703 else
704 crt = SSL_get_certificate(ssl);
705 if (!crt)
706 return 0;
707
708 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
709 nid = OBJ_obj2nid(algorithm);
710
711 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
712 if (!smp->data.u.str.area) {
713 /* SSL_get_peer_certificate increase X509 * ref count */
714 if (cert_peer)
715 X509_free(crt);
716 return 0;
717 }
718
719 smp->data.type = SMP_T_STR;
720 smp->flags |= SMP_F_CONST;
721 smp->data.u.str.data = strlen(smp->data.u.str.area);
722 if (cert_peer)
723 X509_free(crt);
724
725 return 1;
726}
727
728/* boolean, returns true if front conn. transport layer is SSL.
729 * This function is also usable on backend conn if the fetch keyword 5th
730 * char is 'b'.
731 */
732static int
733smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
734{
735 struct connection *conn;
736
737 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
738 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
739 else
740 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
741 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
742
743 smp->data.type = SMP_T_BOOL;
744 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
745 return 1;
746}
747
748/* boolean, returns true if client present a SNI */
749static int
750smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
751{
752#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
753 struct connection *conn = objt_conn(smp->sess->origin);
754 SSL *ssl = ssl_sock_get_ssl_object(conn);
755
756 smp->data.type = SMP_T_BOOL;
757 smp->data.u.sint = ssl && SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) != NULL;
758 return 1;
759#else
760 return 0;
761#endif
762}
763
764/* boolean, returns true if client session has been resumed.
765 * This function is also usable on backend conn if the fetch keyword 5th
766 * char is 'b'.
767 */
768static int
769smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
770{
771 struct connection *conn;
772 SSL *ssl;
773
774 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
775 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
776 else
777 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
778 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
779
780 ssl = ssl_sock_get_ssl_object(conn);
781
782 smp->data.type = SMP_T_BOOL;
783 smp->data.u.sint = ssl && SSL_session_reused(ssl);
784 return 1;
785}
786
787/* string, returns the used cipher if front conn. transport layer is SSL.
788 * This function is also usable on backend conn if the fetch keyword 5th
789 * char is 'b'.
790 */
791static int
792smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
793{
794 struct connection *conn;
795 SSL *ssl;
796
797 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
798 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
799 else
800 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
801 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
802
803 smp->flags = 0;
804 ssl = ssl_sock_get_ssl_object(conn);
805 if (!ssl)
806 return 0;
807
808 smp->data.u.str.area = (char *)SSL_get_cipher_name(ssl);
809 if (!smp->data.u.str.area)
810 return 0;
811
812 smp->data.type = SMP_T_STR;
813 smp->flags |= SMP_F_CONST;
814 smp->data.u.str.data = strlen(smp->data.u.str.area);
815
816 return 1;
817}
818
819/* integer, returns the algoritm's keysize if front conn. transport layer
820 * is SSL.
821 * This function is also usable on backend conn if the fetch keyword 5th
822 * char is 'b'.
823 */
824static int
825smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
826{
827 struct connection *conn;
828 SSL *ssl;
829 int sint;
830
831 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
832 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
833 else
834 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
835 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
836
837 smp->flags = 0;
838 ssl = ssl_sock_get_ssl_object(conn);
839 if (!ssl)
840 return 0;
841
842 if (!SSL_get_cipher_bits(ssl, &sint))
843 return 0;
844
845 smp->data.u.sint = sint;
846 smp->data.type = SMP_T_SINT;
847
848 return 1;
849}
850
851/* integer, returns the used keysize if front conn. transport layer is SSL.
852 * This function is also usable on backend conn if the fetch keyword 5th
853 * char is 'b'.
854 */
855static int
856smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
857{
858 struct connection *conn;
859 SSL *ssl;
860
861 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
862 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
863 else
864 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
865 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
866
867 smp->flags = 0;
868 ssl = ssl_sock_get_ssl_object(conn);
869 if (!ssl)
870 return 0;
871
872 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ssl, NULL);
873 if (!smp->data.u.sint)
874 return 0;
875
876 smp->data.type = SMP_T_SINT;
877
878 return 1;
879}
880
881#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
882static int
883smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
884{
885 struct connection *conn;
886 SSL *ssl;
887 unsigned int len = 0;
888
889 smp->flags = SMP_F_CONST;
890 smp->data.type = SMP_T_STR;
891
892 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
893 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
894 else
895 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
896 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
897
898 ssl = ssl_sock_get_ssl_object(conn);
899 if (!ssl)
900 return 0;
901
902 smp->data.u.str.area = NULL;
903 SSL_get0_next_proto_negotiated(ssl,
904 (const unsigned char **)&smp->data.u.str.area,
905 &len);
906
907 if (!smp->data.u.str.area)
908 return 0;
909
910 smp->data.u.str.data = len;
911 return 1;
912}
913#endif
914
915#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
916static int
917smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
918{
919 struct connection *conn;
920 SSL *ssl;
921 unsigned int len = 0;
922
923 smp->flags = SMP_F_CONST;
924 smp->data.type = SMP_T_STR;
925
926 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
927 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
928 else
929 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
930 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
931
932 ssl = ssl_sock_get_ssl_object(conn);
933 if (!ssl)
934 return 0;
935
936 smp->data.u.str.area = NULL;
937 SSL_get0_alpn_selected(ssl,
938 (const unsigned char **)&smp->data.u.str.area,
939 &len);
940
941 if (!smp->data.u.str.area)
942 return 0;
943
944 smp->data.u.str.data = len;
945 return 1;
946}
947#endif
948
949/* string, returns the used protocol if front conn. transport layer is SSL.
950 * This function is also usable on backend conn if the fetch keyword 5th
951 * char is 'b'.
952 */
953static int
954smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
955{
956 struct connection *conn;
957 SSL *ssl;
958
959 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
960 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
961 else
962 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
963 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
964
965 smp->flags = 0;
966 ssl = ssl_sock_get_ssl_object(conn);
967 if (!ssl)
968 return 0;
969
970 smp->data.u.str.area = (char *)SSL_get_version(ssl);
971 if (!smp->data.u.str.area)
972 return 0;
973
974 smp->data.type = SMP_T_STR;
975 smp->flags = SMP_F_CONST;
976 smp->data.u.str.data = strlen(smp->data.u.str.area);
977
978 return 1;
979}
980
981/* binary, returns the SSL stream id if front conn. transport layer is SSL.
982 * This function is also usable on backend conn if the fetch keyword 5th
983 * char is 'b'.
984 */
985#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
986static int
987smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
988{
989 struct connection *conn;
990 SSL_SESSION *ssl_sess;
991 SSL *ssl;
992 unsigned int len = 0;
993
994 smp->flags = SMP_F_CONST;
995 smp->data.type = SMP_T_BIN;
996
997 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
998 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
999 else
1000 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
1001 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
1002
1003 ssl = ssl_sock_get_ssl_object(conn);
1004 if (!ssl)
1005 return 0;
1006
1007 ssl_sess = SSL_get_session(ssl);
1008 if (!ssl_sess)
1009 return 0;
1010
1011 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
1012 if (!smp->data.u.str.area || !len)
1013 return 0;
1014
1015 smp->data.u.str.data = len;
1016 return 1;
1017}
1018#endif
1019
1020
1021#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
1022static int
1023smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
1024{
1025 struct connection *conn;
1026 struct buffer *data;
1027 SSL *ssl;
1028
1029 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
1030 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
1031 else
1032 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
1033 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
1034
1035 ssl = ssl_sock_get_ssl_object(conn);
1036 if (!ssl)
1037 return 0;
1038
1039 data = get_trash_chunk();
1040 if (kw[7] == 'c')
1041 data->data = SSL_get_client_random(ssl,
1042 (unsigned char *) data->area,
1043 data->size);
1044 else
1045 data->data = SSL_get_server_random(ssl,
1046 (unsigned char *) data->area,
1047 data->size);
1048 if (!data->data)
1049 return 0;
1050
1051 smp->flags = 0;
1052 smp->data.type = SMP_T_BIN;
1053 smp->data.u.str = *data;
1054
1055 return 1;
1056}
1057
1058static int
1059smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
1060{
1061 struct connection *conn;
1062 SSL_SESSION *ssl_sess;
1063 struct buffer *data;
1064 SSL *ssl;
1065
1066 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
1067 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
1068 else
1069 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
1070 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
1071
1072 ssl = ssl_sock_get_ssl_object(conn);
1073 if (!ssl)
1074 return 0;
1075
1076 ssl_sess = SSL_get_session(ssl);
1077 if (!ssl_sess)
1078 return 0;
1079
1080 data = get_trash_chunk();
1081 data->data = SSL_SESSION_get_master_key(ssl_sess,
1082 (unsigned char *) data->area,
1083 data->size);
1084 if (!data->data)
1085 return 0;
1086
1087 smp->flags = 0;
1088 smp->data.type = SMP_T_BIN;
1089 smp->data.u.str = *data;
1090
1091 return 1;
1092}
1093#endif
1094
1095#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1096static int
1097smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
1098{
1099 struct connection *conn;
1100 SSL *ssl;
1101
1102 smp->flags = SMP_F_CONST;
1103 smp->data.type = SMP_T_STR;
1104
1105 conn = objt_conn(smp->sess->origin);
1106 ssl = ssl_sock_get_ssl_object(conn);
1107 if (!ssl)
1108 return 0;
1109
1110 smp->data.u.str.area = (char *)SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
1111 if (!smp->data.u.str.area)
1112 return 0;
1113
1114 smp->data.u.str.data = strlen(smp->data.u.str.area);
1115 return 1;
1116}
1117#endif
1118
1119static int
1120smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
1121{
1122 struct connection *conn;
1123 struct ssl_capture *capture;
1124 SSL *ssl;
1125
1126 conn = objt_conn(smp->sess->origin);
1127 ssl = ssl_sock_get_ssl_object(conn);
1128 if (!ssl)
1129 return 0;
1130
1131 capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
1132 if (!capture)
1133 return 0;
1134
1135 smp->flags = SMP_F_CONST;
1136 smp->data.type = SMP_T_BIN;
1137 smp->data.u.str.area = capture->ciphersuite;
1138 smp->data.u.str.data = capture->ciphersuite_len;
1139 return 1;
1140}
1141
1142static int
1143smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
1144{
1145 struct buffer *data;
1146
1147 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
1148 return 0;
1149
1150 data = get_trash_chunk();
1151 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
1152 smp->data.type = SMP_T_BIN;
1153 smp->data.u.str = *data;
1154 return 1;
1155}
1156
1157static int
1158smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
1159{
1160 struct connection *conn;
1161 struct ssl_capture *capture;
1162 SSL *ssl;
1163
1164 conn = objt_conn(smp->sess->origin);
1165 ssl = ssl_sock_get_ssl_object(conn);
1166 if (!ssl)
1167 return 0;
1168
1169 capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
1170 if (!capture)
1171 return 0;
1172
1173 smp->data.type = SMP_T_SINT;
1174 smp->data.u.sint = capture->xxh64;
1175 return 1;
1176}
1177
William Lallemand7d42ef52020-07-06 11:41:30 +02001178/* Dump the SSL keylog, it only works with "tune.ssl.keylog 1" */
1179#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1180static int smp_fetch_ssl_x_keylog(const struct arg *args, struct sample *smp, const char *kw, void *private)
1181{
1182 struct connection *conn;
1183 struct ssl_keylog *keylog;
1184 SSL *ssl;
1185 char *src = NULL;
1186 const char *sfx;
1187
1188 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
1189 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
1190
William Lallemandeec1d452020-07-07 10:48:13 +02001191 if (!conn)
1192 return 0;
1193
William Lallemand7d42ef52020-07-06 11:41:30 +02001194 if (conn->flags & CO_FL_WAIT_XPRT) {
1195 smp->flags |= SMP_F_MAY_CHANGE;
1196 return 0;
1197 }
1198
1199 ssl = ssl_sock_get_ssl_object(conn);
1200 if (!ssl)
1201 return 0;
1202
1203 keylog = SSL_get_ex_data(ssl, ssl_keylog_index);
1204 if (!keylog)
1205 return 0;
1206
1207 sfx = kw + strlen("ssl_xx_");
1208
1209 if (strcmp(sfx, "client_early_traffic_secret") == 0) {
1210 src = keylog->client_early_traffic_secret;
1211 } else if (strcmp(sfx, "client_handshake_traffic_secret") == 0) {
1212 src = keylog->client_handshake_traffic_secret;
1213 } else if (strcmp(sfx, "server_handshake_traffic_secret") == 0) {
1214 src = keylog->server_handshake_traffic_secret;
1215 } else if (strcmp(sfx, "client_traffic_secret_0") == 0) {
1216 src = keylog->client_traffic_secret_0;
1217 } else if (strcmp(sfx, "server_traffic_secret_0") == 0) {
1218 src = keylog->server_traffic_secret_0;
1219 } else if (strcmp(sfx, "exporter_secret") == 0) {
1220 src = keylog->exporter_secret;
1221 } else if (strcmp(sfx, "early_exporter_secret") == 0) {
1222 src = keylog->early_exporter_secret;
1223 }
1224
1225 if (!src || !*src)
1226 return 0;
1227
1228 smp->data.u.str.area = src;
1229 smp->data.type = SMP_T_STR;
1230 smp->flags |= SMP_F_CONST;
1231 smp->data.u.str.data = strlen(smp->data.u.str.area);
1232 return 1;
William Lallemand7d42ef52020-07-06 11:41:30 +02001233}
1234#endif
1235
William Lallemand15e16942020-05-15 00:25:08 +02001236static int
1237smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
1238{
1239#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
1240 struct buffer *data;
1241 int i;
1242
1243 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
1244 return 0;
1245
1246 data = get_trash_chunk();
1247 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
1248 const char *str;
1249 const SSL_CIPHER *cipher;
1250 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
1251 uint16_t id = (bin[0] << 8) | bin[1];
1252#if defined(OPENSSL_IS_BORINGSSL)
1253 cipher = SSL_get_cipher_by_value(id);
1254#else
1255 struct connection *conn = __objt_conn(smp->sess->origin);
1256 SSL *ssl = ssl_sock_get_ssl_object(conn);
1257 cipher = SSL_CIPHER_find(ssl, bin);
1258#endif
1259 str = SSL_CIPHER_get_name(cipher);
1260 if (!str || strcmp(str, "(NONE)") == 0)
1261 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
1262 else
1263 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
1264 }
1265 smp->data.type = SMP_T_STR;
1266 smp->data.u.str = *data;
1267 return 1;
1268#else
1269 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
1270#endif
1271}
1272
1273#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
1274static int
1275smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
1276{
1277 struct connection *conn;
1278 int finished_len;
1279 struct buffer *finished_trash;
1280 SSL *ssl;
1281
1282 if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
1283 conn = (kw[4] != 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
1284 else
1285 conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
1286 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
1287
1288 smp->flags = 0;
1289 ssl = ssl_sock_get_ssl_object(conn);
1290 if (!ssl)
1291 return 0;
1292
1293 if (conn->flags & CO_FL_WAIT_XPRT) {
1294 smp->flags |= SMP_F_MAY_CHANGE;
1295 return 0;
1296 }
1297
1298 finished_trash = get_trash_chunk();
1299 if (!SSL_session_reused(ssl))
1300 finished_len = SSL_get_peer_finished(ssl,
1301 finished_trash->area,
1302 finished_trash->size);
1303 else
1304 finished_len = SSL_get_finished(ssl,
1305 finished_trash->area,
1306 finished_trash->size);
1307
1308 if (!finished_len)
1309 return 0;
1310
1311 finished_trash->data = finished_len;
1312 smp->data.u.str = *finished_trash;
1313 smp->data.type = SMP_T_BIN;
1314
1315 return 1;
1316}
1317#endif
1318
1319/* integer, returns the first verify error in CA chain of client certificate chain. */
1320static int
1321smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
1322{
1323 struct connection *conn;
1324 struct ssl_sock_ctx *ctx;
1325
1326 conn = objt_conn(smp->sess->origin);
1327 if (!conn || conn->xprt != &ssl_sock)
1328 return 0;
1329 ctx = conn->xprt_ctx;
1330
1331 if (conn->flags & CO_FL_WAIT_XPRT) {
1332 smp->flags = SMP_F_MAY_CHANGE;
1333 return 0;
1334 }
1335
1336 smp->data.type = SMP_T_SINT;
1337 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
1338 smp->flags = 0;
1339
1340 return 1;
1341}
1342
1343/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
1344static int
1345smp_fetch_ssl_c_ca_err_depth(const struct arg *args, struct sample *smp, const char *kw, void *private)
1346{
1347 struct connection *conn;
1348 struct ssl_sock_ctx *ctx;
1349
1350 conn = objt_conn(smp->sess->origin);
1351 if (!conn || conn->xprt != &ssl_sock)
1352 return 0;
1353
1354 if (conn->flags & CO_FL_WAIT_XPRT) {
1355 smp->flags = SMP_F_MAY_CHANGE;
1356 return 0;
1357 }
1358 ctx = conn->xprt_ctx;
1359
1360 smp->data.type = SMP_T_SINT;
1361 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
1362 smp->flags = 0;
1363
1364 return 1;
1365}
1366
1367/* integer, returns the first verify error on client certificate */
1368static int
1369smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
1370{
1371 struct connection *conn;
1372 struct ssl_sock_ctx *ctx;
1373
1374 conn = objt_conn(smp->sess->origin);
1375 if (!conn || conn->xprt != &ssl_sock)
1376 return 0;
1377
1378 if (conn->flags & CO_FL_WAIT_XPRT) {
1379 smp->flags = SMP_F_MAY_CHANGE;
1380 return 0;
1381 }
1382
1383 ctx = conn->xprt_ctx;
1384
1385 smp->data.type = SMP_T_SINT;
1386 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
1387 smp->flags = 0;
1388
1389 return 1;
1390}
1391
1392/* integer, returns the verify result on client cert */
1393static int
1394smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
1395{
1396 struct connection *conn;
1397 SSL *ssl;
1398
1399 conn = objt_conn(smp->sess->origin);
1400 ssl = ssl_sock_get_ssl_object(conn);
1401 if (!ssl)
1402 return 0;
1403
1404 if (conn->flags & CO_FL_WAIT_XPRT) {
1405 smp->flags = SMP_F_MAY_CHANGE;
1406 return 0;
1407 }
1408
1409 smp->data.type = SMP_T_SINT;
1410 smp->data.u.sint = (long long int)SSL_get_verify_result(ssl);
1411 smp->flags = 0;
1412
1413 return 1;
1414}
1415
1416/* Argument validation functions */
1417
1418/* This function is used to validate the arguments passed to any "x_dn" ssl
1419 * keywords. These keywords support specifying a third parameter that must be
1420 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
1421 */
1422int val_dnfmt(struct arg *arg, char **err_msg)
1423{
1424 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
1425 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
1426 return 0;
1427 }
1428 return 1;
1429}
1430
1431/* Note: must not be declared <const> as its list will be overwritten.
1432 * Please take care of keeping this list alphabetically sorted.
1433 */
1434static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
1435 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
1436 { "ssl_bc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
1437#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1438 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
1439#endif
1440 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
1441#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1442 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
1443#endif
1444 { "ssl_bc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
1445 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
1446 { "ssl_bc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
1447 { "ssl_bc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
1448#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
1449 { "ssl_bc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
1450#endif
1451#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
1452 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
1453 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
1454 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
1455#endif
1456 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1457 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1458 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
William Dauchya598b502020-08-06 18:11:38 +02001459 { "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 +02001460 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1461 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1462 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1463 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1464 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1465 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1466 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1467 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1468 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1469 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1470 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1471 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1472 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1473 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1474 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1475 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1476 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1477 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1478 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1479 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1480 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1481 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1482 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1483 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1484 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1485 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1486 { "ssl_fc_has_early", smp_fetch_ssl_fc_has_early, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1487 { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1488 { "ssl_fc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
1489#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1490 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1491#endif
1492#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1493 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1494#endif
1495 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1496#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
1497 { "ssl_fc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1498#endif
1499 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
1500#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
1501 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1502#endif
1503#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
1504 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1505 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1506 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1507#endif
William Lallemand7d42ef52020-07-06 11:41:30 +02001508
1509#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1510 { "ssl_fc_client_early_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1511 { "ssl_fc_client_handshake_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1512 { "ssl_fc_server_handshake_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1513 { "ssl_fc_client_traffic_secret_0", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1514 { "ssl_fc_server_traffic_secret_0", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1515 { "ssl_fc_exporter_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1516 { "ssl_fc_early_exporter_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1517#endif
1518
William Lallemand15e16942020-05-15 00:25:08 +02001519#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1520 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1521#endif
1522 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1523 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1524 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1525 { "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 +02001526
1527/* SSL server certificate fetches */
1528 { "ssl_s_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
William Dauchya598b502020-08-06 18:11:38 +02001529 { "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 +02001530 { "ssl_s_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1531 { "ssl_s_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1532 { "ssl_s_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1533 { "ssl_s_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
1534 { "ssl_s_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1535 { "ssl_s_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
1536 { "ssl_s_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1537 { "ssl_s_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
1538 { "ssl_s_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
William Lallemand15e16942020-05-15 00:25:08 +02001539 { NULL, NULL, 0, 0, 0 },
1540}};
1541
1542INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
1543
1544/* Note: must not be declared <const> as its list will be overwritten.
1545 * Please take care of keeping this list alphabetically sorted.
1546 */
1547static struct acl_kw_list acl_kws = {ILH, {
1548 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
1549 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
1550 { /* END */ },
1551}};
1552
1553INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);