Re: [PATCH] BUG/MINOR: lua: Segfaults with wrong usage of types.
I read the ML too quicky, thiss is the right patch. Thanks. Thierry > On 15 Jun 2018, at 15:06, Frederic Lecaille wrote: > > On 06/15/2018 02:28 PM, Frederic Lecaille wrote: >> On 06/15/2018 02:15 PM, Frederic Lecaille wrote: >>> On 06/14/2018 11:05 PM, Patrick Hemmer wrote: Haproxy segfaults if you pass the wrong argument type to a converter. Example: haproxy.cfg: global lua-load /tmp/haproxy.lua frontend f1 mode http bind :8000 default_backend b1 http-request lua.foo backend b1 mode http server s1 127.0.0.1:8080 haproxy.lua: core.register_action("foo", { "http-req" }, function(txn) txn.sc:ipmask(txn.f:src(), 24, 112) end) Result: * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x18) frame #0: 0x7fffc9fcbf56 libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 182 libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell: -> 0x7fffc9fcbf56 <+182>: movb (%rsi,%r8), %cl 0x7fffc9fcbf5a <+186>: movb %cl, (%rdi,%r8) 0x7fffc9fcbf5e <+190>: subq $0x1, %rdx 0x7fffc9fcbf62 <+194>: je 0x7fffc9fcbf78; <+216> Target 0: (haproxy) stopped. (lldb) bt * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x18) * frame #0: 0x7fffc9fcbf56 libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 182 frame #1: 0x7fffc9e7442e libsystem_c.dylib`__memcpy_chk + 22 frame #2: 0x00010002ec46 haproxy`hlua_lua2arg_check(L=0x00010120d298, first=3, argp=0x7fff5fbfe690, mask=196, p=0x000101817000) at hlua.c:749 frame #3: 0x00010001fa00 haproxy`hlua_run_sample_conv(L=0x00010120d298) at hlua.c:3393 frame #4: 0x00010032400b haproxy`luaD_precall + 747 frame #5: 0x0001003343c6 haproxy`luaV_execute + 3158 frame #6: 0x000100323429 haproxy`luaD_rawrunprotected + 89 frame #7: 0x000100324516 haproxy`lua_resume + 278 frame #8: 0x00010001b199 haproxy`hlua_ctx_resume(lua=0x000101205080, yield_allowed=1) at hlua.c:1080 frame #9: 0x000100027de8 haproxy`hlua_action(rule=0x00010101b180, px=0x000101817000, sess=0x00010120cb70, s=0x00010120cc00, flags=2) at hlua.c:6198 frame #10: 0x000100044bcd haproxy`http_req_get_intercept_rule(px=0x000101817000, rules=0x000101817048, s=0x00010120cc00, deny_status=0x7fff5fbfee78) at proto_http.c:2760 frame #11: 0x000100046182 haproxy`http_process_req_common(s=0x00010120cc00, req=0x00010120cc10, an_bit=16, px=0x000101817000) at proto_http.c:3461 frame #12: 0x000100094c50 haproxy`process_stream(t=0x00010120cf40, context=0x00010120cc00, state=9) at stream.c:1905 frame #13: 0x00010016179f haproxy`process_runnable_tasks at task.c:362 frame #14: 0x0001000ea0eb haproxy`run_poll_loop at haproxy.c:2403 frame #15: 0x0001000e7c74 haproxy`run_thread_poll_loop(data=0x7fff5fbff3a4) at haproxy.c:2464 frame #16: 0x0001000e4a49 haproxy`main(argc=3, argv=0x7fff5fbff590) at haproxy.c:3082 frame #17: 0x7fffc9db9235 libdyld.dylib`start + 1 Issue goes away if you change the lua txn.sc:ipmask() line to: txn.sc:ipmask(txn.f:src(), '24', '112') Reproduced with current master (9db0fed) and lua version 5.3.4. -Patrick >>> >>> It seems the patch attached to this mail fixes this issue. It at least make >>> the varnishtest test file pass. >>> >>> Must be checked by Thierry. >> Should have mentionned that I could not reproduce this issue without >> compiling the thread support (USE_THREAD=1). > > There is potentially the same issue in hlua_run_sample_conv(). See the > updated patch attached to this mail. > > > > > <0001-BUG-MINOR-lua-Segfaults-with-wrong-usage-of-types.patch>
Re: BUG: segfault with lua sample converters & wrong arg types
Thanks. the patch make sense. Willy, could you apply ? > On 15 Jun 2018, at 14:15, Frederic Lecaille wrote: > > On 06/14/2018 11:05 PM, Patrick Hemmer wrote: >> Haproxy segfaults if you pass the wrong argument type to a converter. >> Example: >> haproxy.cfg: >> global >> lua-load /tmp/haproxy.lua >> frontend f1 >> mode http >> bind :8000 >> default_backend b1 >> http-request lua.foo >> backend b1 >> mode http >> server s1 127.0.0.1:8080 >> haproxy.lua: >> core.register_action("foo", { "http-req" }, function(txn) >> txn.sc:ipmask(txn.f:src(), 24, 112) >> end) >> Result: >> * thread #1, queue = 'com.apple.main-thread', stop reason = >> EXC_BAD_ACCESS (code=1, address=0x18) >> frame #0: 0x7fffc9fcbf56 >> libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 182 >> libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell: >> -> 0x7fffc9fcbf56 <+182>: movb (%rsi,%r8), %cl >> 0x7fffc9fcbf5a <+186>: movb %cl, (%rdi,%r8) >> 0x7fffc9fcbf5e <+190>: subq $0x1, %rdx >> 0x7fffc9fcbf62 <+194>: je 0x7fffc9fcbf78; <+216> >> Target 0: (haproxy) stopped. >> (lldb) bt >> * thread #1, queue = 'com.apple.main-thread', stop reason = >> EXC_BAD_ACCESS (code=1, address=0x18) >> * frame #0: 0x7fffc9fcbf56 >> libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 182 >> frame #1: 0x7fffc9e7442e libsystem_c.dylib`__memcpy_chk + 22 >> frame #2: 0x00010002ec46 >> haproxy`hlua_lua2arg_check(L=0x00010120d298, first=3, >> argp=0x7fff5fbfe690, mask=196, p=0x000101817000) at hlua.c:749 >> frame #3: 0x00010001fa00 >> haproxy`hlua_run_sample_conv(L=0x00010120d298) at hlua.c:3393 >> frame #4: 0x00010032400b haproxy`luaD_precall + 747 >> frame #5: 0x0001003343c6 haproxy`luaV_execute + 3158 >> frame #6: 0x000100323429 haproxy`luaD_rawrunprotected + 89 >> frame #7: 0x000100324516 haproxy`lua_resume + 278 >> frame #8: 0x00010001b199 >> haproxy`hlua_ctx_resume(lua=0x000101205080, yield_allowed=1) at >> hlua.c:1080 >> frame #9: 0x000100027de8 >> haproxy`hlua_action(rule=0x00010101b180, px=0x000101817000, >> sess=0x00010120cb70, s=0x00010120cc00, flags=2) at hlua.c:6198 >> frame #10: 0x000100044bcd >> haproxy`http_req_get_intercept_rule(px=0x000101817000, >> rules=0x000101817048, s=0x00010120cc00, >> deny_status=0x7fff5fbfee78) at proto_http.c:2760 >> frame #11: 0x000100046182 >> haproxy`http_process_req_common(s=0x00010120cc00, >> req=0x00010120cc10, an_bit=16, px=0x000101817000) at >> proto_http.c:3461 >> frame #12: 0x000100094c50 >> haproxy`process_stream(t=0x00010120cf40, context=0x00010120cc00, >> state=9) at stream.c:1905 >> frame #13: 0x00010016179f haproxy`process_runnable_tasks at >> task.c:362 >> frame #14: 0x0001000ea0eb haproxy`run_poll_loop at haproxy.c:2403 >> frame #15: 0x0001000e7c74 >> haproxy`run_thread_poll_loop(data=0x7fff5fbff3a4) at haproxy.c:2464 >> frame #16: 0x0001000e4a49 haproxy`main(argc=3, >> argv=0x7fff5fbff590) at haproxy.c:3082 >> frame #17: 0x7fffc9db9235 libdyld.dylib`start + 1 >> Issue goes away if you change the lua txn.sc:ipmask() line to: >> txn.sc:ipmask(txn.f:src(), '24', '112') >> Reproduced with current master (9db0fed) and lua version 5.3.4. >> -Patrick > > It seems the patch attached to this mail fixes this issue. It at least make > the varnishtest test file pass. > > Must be checked by Thierry. > > > Fred. > <0001-BUG-MINOR-lua-Segfaults-with-wrong-usage-of-types.patch>
[PATCH] Re: Random crash (segfault, double free, ...) with a mix of SSL + cipherlist hash
Finally, I got it ! It works with luck because we have 1 bug in Haproxy and 1 error (I suppose) in a OpenSSL compatibility layer. First point is some OpenSSL macro, in the ssl.h file: #define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char*)arg)) #define SSL_get_app_data(s) (SSL_get_ex_data(s,0)) These macro uses the function SSL_get_ex_data ans SSL_set_ex_data with the index 0, but this index is not reserved with the function SSL_get_ex_new_index() When I reserve a slot for the cipherlist hash, I have the number 0, this produce a collision an the set_app_data pointer is crushed by the cipherlist data. Luckily, the cipherlist hash is declared in the SSL_CTX space in place of SSL space. The first consequence was a memory leak because the allocated struct is never cleared. The second consequence is an index number > 0. - With this index number > 0, the data doesn't crush app_data, but there stored in a non-reserved storage => various crash cause - When I fix the reservation, The app_data are crushed, and we have systematic segfault. I join two patch. The first which fix the cipher capture must be backported to 1.8, for the second patch wich fix the app data compatibility, I dont known (at least 1.8). I join also the backports for 1.8 (there are trivial backport, with ery minor conflict) Thierry On Sun, 17 Jun 2018 03:01:54 +0200 Thierry FOURNIER wrote: > Hi, > > When I use SSL requests and the cipherlist hash enabled, HAProxy > randomly crash: > > - segfault > - double free > - munmap_chunk(): invalid pointer > > I think that is a memory crush. > > I read the "cipherlist hash" code, and I put some printf, I do not > detect any memory override. > > When I comment the following line, the bug disappear > >SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture); > > The crash happens with many versions of openssl: > > - 1.0.2j (home build) > - 1.0.1t-1+deb7u4 > - 1.0.1t-1+deb8u8 > - 1.0.2g-1ubuntu4.12 > > cipherlist hash is available from 1.8. The bug appears with current 1.8 > and current 1.9dev. > > I join some files: > > - bug36.build.sh : build script > - bug36.run.sh : run haproxy command > - bug36.request.sh : curl request > - bug36.conf : minimal conf which reproduce the problem > - bug36.pem: ramdom self signed certificate > > Just execute some requests, and the bug is reproduced. > > BR, > Thierry >From a99fcb5af1a079ab5403f4cf7d2cf9345e4daf03 Mon Sep 17 00:00:00 2001 From: Thierry FOURNIER Date: Sun, 17 Jun 2018 21:33:01 +0200 Subject: [PATCH 1/2] BUG/MAJOR: Random crash with cipherlist capture The cipher list capture struct is stored in the SSL memory space, but the slot is reserved in the SSL_CTX memory space. This causes ramdom crashes. This patch should be backported to 1.8 --- src/ssl_sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 9fb2bb151..599c8c3ec 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -8805,7 +8805,7 @@ static void __ssl_sock_init(void) #if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER) sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func); #endif - ssl_capture_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func); + ssl_capture_ptr_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func); sample_register_fetches(_fetch_keywords); acl_register_keywords(_kws); bind_register_keywords(_kws); -- 2.16.3 >From 54ce55a1203e732d266e72332bfea19d30f45487 Mon Sep 17 00:00:00 2001 From: Thierry FOURNIER Date: Sun, 17 Jun 2018 21:37:05 +0200 Subject: [PATCH 2/2] BUG/MAJOR: OpenSSL context is stored in non-reserved memory slot We never saw unexplicated crash with SSL, so I suppose that we are luck, or the slot 0 is always reserved. Anyway the usage of the macro SSL_get_app_data() and SSL_set_app_data() seem wrong. This patch change the deprecated functions SSL_get_app_data() and SSL_set_app_data() by the new functions SSL_get_ex_data() and SSL_set_ex_data(), and it reserves the slot in the SSL memory space. For information, this is the two declaration which seems wrong or incomplete in the OpenSSL ssl.h file. We can see the usage of the slot 0 whoch is hardcoded, but never reserved. #define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)arg)) #define SSL_get_app_data(s) (SSL_get_ex_data(s,0)) This patch must be backported at least in 1.8, maybe in other versions. --- src/ssl_sock.c | 22 -- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 599c8c3ec..2707a40a9 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -260,6 +260,7 @@ struct ssl_capture { }; struct pool_head *pool_head_ssl_capture = NULL; static int ssl_capture_ptr_index = -1; +static int
Re: [PATCH] MINOR: crypto: Add digest and hmac converters
Le dim. 17 juin 2018 à 14:10, Patrick Gansterer a écrit : > > > On 17 Jun 2018, at 13:36, Baptiste wrote: > > > > Can they be used to validate oauth tokens too? > > Depends on the implementation of the tokens, but if they are HMACSHA256 > signed JWT, it’s very easy to validate them in a lua script now. > That's how I am doing it now. Just wanted to know if a combination of http rules could do the job. And be maybe faster. Baptiste
Re: [PATCH] MINOR: crypto: Add digest and hmac converters
> On 17 Jun 2018, at 13:36, Baptiste wrote: > > Can they be used to validate oauth tokens too? Depends on the implementation of the tokens, but if they are HMACSHA256 signed JWT, it’s very easy to validate them in a lua script now. > Note: maybe an update for configuration.txt would be helpful too. Thx for the note. I’ve updated the patch. - Patrick
[PATCH] MINOR: crypto: Add digest and hmac converters
Make the digest and HMAC function of OpenSSL accesable to the user via converters. e.g. They can be used to sign and validate cookies. --- Makefile | 2 +- doc/configuration.txt | 9 + src/crypto.c | 84 +++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/crypto.c diff --git a/Makefile b/Makefile index 5d170041..9a3a5024 100644 --- a/Makefile +++ b/Makefile @@ -609,7 +609,7 @@ OPTIONS_LDFLAGS += $(if $(SSL_LIB),-L$(SSL_LIB)) -lssl -lcrypto ifneq ($(USE_DL),) OPTIONS_LDFLAGS += -ldl endif -OPTIONS_OBJS += src/ssl_sock.o +OPTIONS_OBJS += src/crypto.o src/ssl_sock.o endif # The private cache option affect the way the shctx is built diff --git a/doc/configuration.txt b/doc/configuration.txt index e901d7ee..7c9eb55c 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -12909,6 +12909,10 @@ debug type of the input sample. The sample is returned as is on its output. This converter only exists when haproxy was built with debugging enabled. +digest() + Converts a binary input sample to a message digest. The result is a binary + sample. The alorithm must a OpenSSL message digest name (e.g sha256). + div() Divides the input value of type signed integer by , and returns the result as an signed integer. If is null, the largest unsigned @@ -12963,6 +12967,11 @@ hex2i Converts a hex string containing two hex digits per input byte to an integer. If the input value can not be converted, then zero is returned. +hmac(, ) + Converts a binary input sample to a message authentication code with the given + key. The result is a binary sample. The alorithm must be of the registered + OpenSSL message digest names (e.g sha256). + http_date([]) Converts an integer supposed to contain a date since epoch to a string representing this date in a format suitable for use in HTTP header fields. If diff --git a/src/crypto.c b/src/crypto.c new file mode 100644 index ..e4a65557 --- /dev/null +++ b/src/crypto.c @@ -0,0 +1,84 @@ +/* + * Crypto converters + * + * Copyright 2018 Patrick Gansterer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include + +#include +#include + +#include +#include + +static int sample_conv_crypto_digest(const struct arg *args, struct sample *smp, void *private) +{ + struct chunk *trash = get_trash_chunk(); + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.str); + unsigned char *md = (unsigned char*) trash->str; + unsigned int md_len = trash->size; + + if (!ctx) + return 0; + if (!evp) + return 0; + + if (!EVP_DigestInit(ctx, evp) || + !EVP_DigestUpdate(ctx, smp->data.u.str.str, smp->data.u.str.len) || + !EVP_DigestFinal(ctx, md, _len)) { + EVP_MD_CTX_free(ctx); + return 0; + } + + EVP_MD_CTX_free(ctx); + + trash->len = md_len; + smp->data.u.str = *trash; + smp->data.type = SMP_T_BIN; + smp->flags &= ~SMP_F_CONST; + return 1; +} + +static int sample_conv_crypto_hmac(const struct arg *args, struct sample *smp, void *private) +{ + struct chunk *trash = get_trash_chunk(); + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.str); + const char* key = args[1].data.str.str; + int key_len = args[1].data.str.len; + unsigned char *md = (unsigned char*) trash->str; + unsigned int md_len = trash->size; + + trash->len = 0; + + if (!evp) + return 0; + + if (!HMAC(evp, key, key_len, (const unsigned char*) smp->data.u.str.str, smp->data.u.str.len, md, _len)) + return 0; + + trash->len = md_len; + smp->data.u.str = *trash; + smp->data.type = SMP_T_BIN; + smp->flags &= ~SMP_F_CONST; + return 1; +} + +static struct sample_conv_kw_list sample_conv_kws = {ILH, { + { "digest", sample_conv_crypto_digest, ARG1(1,STR), NULL, SMP_T_BIN, SMP_T_BIN }, + { "hmac", sample_conv_crypto_hmac, ARG2(2,STR,STR), NULL, SMP_T_BIN, SMP_T_BIN }, + { /* END */ }, +}}; + +__attribute__((constructor)) +static void __crypto_init(void) +{ + sample_register_convs(_conv_kws); +} -- 2.17.1
Re: [PATCH] MINOR: crypto: Add digest and hmac converters
On Sun, Jun 17, 2018 at 11:21 AM, Patrick Gansterer wrote: > Make the digest and HMAC function of OpenSSL accesable to the user via > converters. e.g. They can be used to sign and validate cookies. > --- > Makefile | 2 +- > src/crypto.c | 84 > 2 files changed, 85 insertions(+), 1 deletion(-) > create mode 100644 src/crypto.c > > diff --git a/Makefile b/Makefile > index 5d170041..9a3a5024 100644 > --- a/Makefile > +++ b/Makefile > @@ -609,7 +609,7 @@ OPTIONS_LDFLAGS += $(if $(SSL_LIB),-L$(SSL_LIB)) -lssl > -lcrypto > ifneq ($(USE_DL),) > OPTIONS_LDFLAGS += -ldl > endif > -OPTIONS_OBJS += src/ssl_sock.o > +OPTIONS_OBJS += src/crypto.o src/ssl_sock.o > endif > > # The private cache option affect the way the shctx is built > diff --git a/src/crypto.c b/src/crypto.c > new file mode 100644 > index ..dcb343dc > --- /dev/null > +++ b/src/crypto.c > @@ -0,0 +1,84 @@ > +/* > + * Crypto converters > + * > + * Copyright 2018 Patrick Gansterer > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version > + * 2 of the License, or (at your option) any later version. > + * > + */ > + > +#include > + > +#include > +#include > + > +#include > +#include > + > +static int sample_conv_crypto_digest(const struct arg *args, struct > sample *smp, void *private) > +{ > + struct chunk *trash = get_trash_chunk(); > + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); > + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.str); > + unsigned char *md = (unsigned char*) trash->str; > + unsigned int md_len = trash->size; > + > + if (!ctx) > + return 0; > + if (!evp) > + return 0; > + > + if (!EVP_DigestInit(ctx, evp) || > + !EVP_DigestUpdate(ctx, smp->data.u.str.str, > smp->data.u.str.len) || > + !EVP_DigestFinal(ctx, md, _len)) { > + EVP_MD_CTX_free(ctx); > + return 0; > + } > + > + EVP_MD_CTX_free(ctx); > + > + trash->len = md_len; > + smp->data.u.str = *trash; > + smp->data.type = SMP_T_BIN; > + smp->flags &= ~SMP_F_CONST; > + return 1; > +} > + > +static int sample_conv_crypto_hmac(const struct arg *args, struct sample > *smp, void *private) > +{ > + struct chunk *trash = get_trash_chunk(); > + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.str); > + const char* key = args[1].data.str.str; > + int key_len = args[1].data.str.len; > + unsigned char *md = (unsigned char*) trash->str; > + unsigned int md_len = trash->size; > + > + trash->len = 0; > + > + if (!evp) > + return 0; > + > + if (!HMAC(evp, key, key_len, (const unsigned char*) > smp->data.u.str.str, smp->data.u.str.len, md, _len)) > + return 0; > + > + trash->len = md_len; > + smp->data.u.str = *trash; > + smp->data.type = SMP_T_BIN; > + smp->flags &= ~SMP_F_CONST; > + return 1; > +} > + > +static struct sample_conv_kw_list sample_conv_kws = {ILH, { > + { "digest", sample_conv_crypto_digest, ARG1(1,STR), NULL, > SMP_T_BIN, SMP_T_BIN }, > + { "hmac", sample_conv_crypto_hmac, ARG2(2,STR,STR), NULL, > SMP_T_BIN, SMP_T_BIN }, > + { /* END */ }, > +}}; > + > +__attribute__((constructor)) > +static void __crypto_init(void) > +{ > + sample_register_convs(_conv_kws); > +} > -- > 2.17.1 > Hi, Nice ones. Can they be used to validate oauth tokens too? Note: maybe an update for configuration.txt would be helpful too. Baptiste
Re: Haproxy health check interval value is not being respected
On Wed, Jun 13, 2018 at 6:31 PM, Adwait Gokhale wrote: > Hello, > > I have come across an issue with use of 'inter' parameter that sets > interval between two consecutive health checks. When configured, I found > that health checks are twice as aggressive than what is configured. > > For instance, when I have haproxy with 2 backends with 'default-server > inter 10s port 80 rise 5 fall 3' I see that health checks to every > backend is at interval of 5 seconds instead of 10. With more than 2 > backends, this behavior does not change. > > Is this a known bug or is it a misconfiguration of some sorts? Appreciate > your help with this. > > Thanks, > Adwait > Hi, Maybe you could share your entire configuration? That would help a lot. Baptiste
[PATCH] MINOR: crypto: Add digest and hmac converters
Make the digest and HMAC function of OpenSSL accesable to the user via converters. e.g. They can be used to sign and validate cookies. --- Makefile | 2 +- src/crypto.c | 84 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/crypto.c diff --git a/Makefile b/Makefile index 5d170041..9a3a5024 100644 --- a/Makefile +++ b/Makefile @@ -609,7 +609,7 @@ OPTIONS_LDFLAGS += $(if $(SSL_LIB),-L$(SSL_LIB)) -lssl -lcrypto ifneq ($(USE_DL),) OPTIONS_LDFLAGS += -ldl endif -OPTIONS_OBJS += src/ssl_sock.o +OPTIONS_OBJS += src/crypto.o src/ssl_sock.o endif # The private cache option affect the way the shctx is built diff --git a/src/crypto.c b/src/crypto.c new file mode 100644 index ..dcb343dc --- /dev/null +++ b/src/crypto.c @@ -0,0 +1,84 @@ +/* + * Crypto converters + * + * Copyright 2018 Patrick Gansterer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include + +#include +#include + +#include +#include + +static int sample_conv_crypto_digest(const struct arg *args, struct sample *smp, void *private) +{ + struct chunk *trash = get_trash_chunk(); + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.str); + unsigned char *md = (unsigned char*) trash->str; + unsigned int md_len = trash->size; + + if (!ctx) + return 0; + if (!evp) + return 0; + + if (!EVP_DigestInit(ctx, evp) || + !EVP_DigestUpdate(ctx, smp->data.u.str.str, smp->data.u.str.len) || + !EVP_DigestFinal(ctx, md, _len)) { + EVP_MD_CTX_free(ctx); + return 0; + } + + EVP_MD_CTX_free(ctx); + + trash->len = md_len; + smp->data.u.str = *trash; + smp->data.type = SMP_T_BIN; + smp->flags &= ~SMP_F_CONST; + return 1; +} + +static int sample_conv_crypto_hmac(const struct arg *args, struct sample *smp, void *private) +{ + struct chunk *trash = get_trash_chunk(); + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.str); + const char* key = args[1].data.str.str; + int key_len = args[1].data.str.len; + unsigned char *md = (unsigned char*) trash->str; + unsigned int md_len = trash->size; + + trash->len = 0; + + if (!evp) + return 0; + + if (!HMAC(evp, key, key_len, (const unsigned char*) smp->data.u.str.str, smp->data.u.str.len, md, _len)) + return 0; + + trash->len = md_len; + smp->data.u.str = *trash; + smp->data.type = SMP_T_BIN; + smp->flags &= ~SMP_F_CONST; + return 1; +} + +static struct sample_conv_kw_list sample_conv_kws = {ILH, { + { "digest", sample_conv_crypto_digest, ARG1(1,STR), NULL, SMP_T_BIN, SMP_T_BIN }, + { "hmac", sample_conv_crypto_hmac, ARG2(2,STR,STR), NULL, SMP_T_BIN, SMP_T_BIN }, + { /* END */ }, +}}; + +__attribute__((constructor)) +static void __crypto_init(void) +{ + sample_register_convs(_conv_kws); +} -- 2.17.1