diff options
Diffstat (limited to 'src/sbearssl/sbearssl_send_environment.c')
-rw-r--r-- | src/sbearssl/sbearssl_send_environment.c | 118 |
1 files changed, 109 insertions, 9 deletions
diff --git a/src/sbearssl/sbearssl_send_environment.c b/src/sbearssl/sbearssl_send_environment.c index bb0fb35..a998ee9 100644 --- a/src/sbearssl/sbearssl_send_environment.c +++ b/src/sbearssl/sbearssl_send_environment.c @@ -1,21 +1,98 @@ /* ISC license. */ +#include <stddef.h> +#include <stdint.h> + #include <skalibs/bytestr.h> #include <skalibs/buffer.h> +#include <skalibs/fmtscan.h> #include <bearssl.h> #include <s6-networking/sbearssl.h> -int sbearssl_send_environment (br_ssl_engine_context *ctx, int fd) +static uint8_t class (char c) +{ + switch (c) + { + case '\0' : return 0 ; + case ' ' : return 1 ; + case ',' : + case '=' : + case '\n' : + case '+' : + case '<' : + case '>' : + case '#' : + case '\\' : return 2 ; + default : return 3 ; + } +} + +static int print_element (buffer *b, char const *s) +{ + static uint8_t const table[3][4] = + { + { 0x03, 0x00, 0x19, 0x09 }, + { 0x03, 0x62, 0x19, 0x09 }, + { 0x03, 0x42, 0x99, 0x89 } + } ; + size_t counter = 0 ; + uint8_t state = 0 ; + while (state < 3) + { + char ch = *s++ ; + uint8_t c = table[state][class(ch)] ; + state = c & 3 ; + if (c & 0x10) if (buffer_put(b, "\\", 1) < 0) return 0 ; + if (c & 0x20) counter = 0 ; + if (c & 0x40) counter++ ; + if (c & 0x80) while (counter--) if (buffer_put(b, " ", 1) < 0) return 0 ; + if (c & 0x08) if (buffer_put(b, &ch, 1) < 0) return 0 ; + } + return 1 ; +} + +struct eltinfo_s +{ + char const *keyword ; + size_t offset ; +} ; + + +static int print_dn (buffer *b, sbearssl_dn const *dn, uint8_t eltstatus) +{ + static struct eltinfo_s const eltinfo[6] = + { + { .keyword = "C", .offset = offsetof(sbearssl_dn, c) }, + { .keyword = "ST", .offset = offsetof(sbearssl_dn, st) }, + { .keyword = "L", .offset = offsetof(sbearssl_dn, l) }, + { .keyword = "O", .offset = offsetof(sbearssl_dn, o) }, + { .keyword = "OU", .offset = offsetof(sbearssl_dn, ou) }, + { .keyword = "CN", .offset = offsetof(sbearssl_dn, cn) } + } ; + int got = 0 ; + unsigned int mask = 1 ; + for (unsigned int i = 0 ; i < 6 ; i++, mask <<= 1) if (eltstatus & mask) + { + if ((got && buffer_puts(b, ", ") < 0) + || buffer_puts(b, eltinfo[i].keyword) < 0 + || buffer_put(b, "=", 1) < 0 + || !print_element(b, (char const *)dn + eltinfo[i].offset)) + return 0 ; + got = 1 ; + } + return 1 ; +} + +int sbearssl_send_environment (br_ssl_engine_context *ctx, sbearssl_handshake_cbarg *p) { char buf[4096] ; - buffer b = BUFFER_INIT(&buffer_write, fd, buf, 4096) ; + buffer b = BUFFER_INIT(&buffer_write, p->notif, buf, 4096) ; unsigned int v = br_ssl_engine_get_version(ctx) ; char const *name = br_ssl_engine_get_server_name(ctx) ; char const *suite ; br_ssl_session_parameters params ; - br_ssl_engine_get_session_parameters(ctx, ¶ms) ; suite = sbearssl_suite_name(¶ms) ; byte_zzero((char *)params.master_secret, 48) ; @@ -26,16 +103,39 @@ int sbearssl_send_environment (br_ssl_engine_context *ctx, int fd) || buffer_put(&b, "", 1) < 0 || buffer_puts(&b, "SSL_CIPHER=") < 0 || buffer_puts(&b, suite) < 0 - || buffer_put(&b, "", 1) < 0 - || buffer_puts(&b, "SSL_TLS_SNI_SERVERNAME") < 0) - return 0 ; + || buffer_put(&b, "", 1) < 0) return 0 ; + + if (buffer_puts(&b, "SSL_TLS_SNI_SERVERNAME") < 0) return 0 ; if (name[0]) { if (buffer_put(&b, "=", 1) < 0 || buffer_puts(&b, name) < 0) return 0 ; } - if (buffer_putflush(&b, "\0", 2) < 0) - return 0 ; - return 1 ; + if (buffer_put(&b, "", 1) < 0) return 0 ; + + if (buffer_puts(&b, "SSL_PEER_CERT_HASH") < 0) return 0 ; + if (p->exportmask & 1) + { + char eehash[64] ; + ucharn_fmt(eehash, p->eehash, 32) ; + if (buffer_puts(&b, "=SHA256:") < 0 + || buffer_put(&b, eehash, 64) < 0) + return 0 ; + } + if (buffer_put(&b, "", 1) < 0) return 0 ; + + if (buffer_puts(&b, "SSL_PEER_CERT_SUBJECT") < 0) return 0 ; + if (p->exportmask & 2 && p->eltstatus) + { + if (buffer_put(&b, "=", 1) < 0) return 0 ; + if (p->eltstatus & 128) + { + if (buffer_puts(&b, "<invalid>") < 0) return 0 ; + } + else if (!print_dn(&b, &p->eedn, p->eltstatus)) return 0 ; + } + if (buffer_put(&b, "", 1) < 0) return 0 ; + + return buffer_putflush(&b, "\0", 2) >= 0 ; } |