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