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