Re: [Openvpn-devel] [PATCH] reload CRL only if file was modified
On Wed, Nov 30, 2016 at 05:26:30PM +0300, SviMik wrote: > 1) I would also check if the file size was changed, not only mtime. > this would work against 2 CRLs with the same mtime but different size: is this is a real case we have to worry about? Anyway, adding this check is easy. I'd do it if it makes the whole check more robust. > 2) I wasn't digging the code deeply, but the > > ssl_ctx->crl_last_mtime.tv_sec >= crl_stat.st_mtime > makes me think it would fail if the file goes reverted to a previous version. > Perhaps the check shall be != instead of >=. > good point! I think we should definitely switch to !=. Thanks! -- Antonio Quartulli -- ___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Re: [Openvpn-devel] [PATCH] reload CRL only if file was modified
1) I would also check if the file size was changed, not only mtime. 2) I wasn't digging the code deeply, but the > ssl_ctx->crl_last_mtime.tv_sec >= crl_stat.st_mtime makes me think it would fail if the file goes reverted to a previous version. Perhaps the check shall be != instead of >=. > In order to prevent annoying delays upon client connection, > reload the CRL file only if it was modified since the last > reload operation. > If not, keep on using the already stored CRL. > > This change will boost client connection time in instances > where the CRL file is quite large (dropping from several > seconds to few milliseconds). > > Cc: Steffan Karger> Signed-off-by: Antonio Quartulli > --- > > Tested on linux by using my VM. > No test was performed on Windows* (compiled-only). > > Note: the check "!(session->opt->ssl_flags & SSLF_CRL_VERIFY_DIR))" may not > always work as expected. The user may forge a wrong, but still compliant, > configuration that would fool this test. This issue exists even before > applying > this patch. > > Cheers, > > src/openvpn/ssl.c | 40 +--- > src/openvpn/ssl_backend.h | 2 +- > src/openvpn/ssl_mbedtls.c | 2 +- > src/openvpn/ssl_mbedtls.h | 1 + > src/openvpn/ssl_openssl.c | 2 +- > src/openvpn/ssl_openssl.h | 1 + > 6 files changed, 42 insertions(+), 6 deletions(-) > > diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c > index 7347a78..235f7df 100644 > --- a/src/openvpn/ssl.c > +++ b/src/openvpn/ssl.c > @@ -612,7 +612,8 @@ init_ssl (const struct options *options, struct > tls_root_ctx *new_ctx) >/* Read CRL */ >if (options->crl_file && !(options->ssl_flags & SSLF_CRL_VERIFY_DIR)) > { > - tls_ctx_reload_crl(new_ctx, options->crl_file, > options->crl_file_inline); > + tls_ctx_reload_crl(new_ctx, options->crl_file, > options->crl_file_inline, > + false); > } > >/* Once keys and cert are loaded, load ECDH parameters */ > @@ -2450,6 +2451,36 @@ auth_deferred_expire_window (const struct tls_options > *o) >return ret; > } > > +void > +tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file, > +const char *crl_file_inline, bool reload) > +{ > + /* if something goes wrong with stat(), we'll store 0 as mtime */ > + platform_stat_t crl_stat = {0}; > + > + /* > + * an inline CRL can't change at runtime, therefore there is no need to > + * reload it. It will be reloaded upon config change + SIGHUP. > + */ > + if (crl_file_inline && reload) > +return; > + > + if (!crl_file_inline) > +platform_stat(crl_file, _stat); > + > + /* > + * If this is not a reload, update the CRL right away. > + * Otherwise, update only if the CRL file was modified after the last > reload. > + * Note: Windows does not support tv_nsec. > + */ > + if (reload && > + (ssl_ctx->crl_last_mtime.tv_sec >= crl_stat.st_mtime)) > +return; > + > + ssl_ctx->crl_last_mtime.tv_sec = crl_stat.st_mtime; > + backend_tls_ctx_reload_crl(ssl_ctx, crl_file, crl_file_inline); > +} > + > /* > * This is the primary routine for processing TLS stuff inside the > * the main event loop. When this routine exits > @@ -2581,12 +2612,15 @@ tls_process (struct tls_multi *multi, > ks->state = S_START; > state_change = true; > > - /* Reload the CRL before TLS negotiation */ > + /* > +* Attempt CRL reload before TLS negotiation. Won't be performed if > +* the file was not modified since the last reload > +*/ > if (session->opt->crl_file && > !(session->opt->ssl_flags & SSLF_CRL_VERIFY_DIR)) > { > tls_ctx_reload_crl(>opt->ssl_ctx, > - session->opt->crl_file, session->opt->crl_file_inline); > + session->opt->crl_file, session->opt->crl_file_inline, true); > } > > dmsg (D_TLS_DEBUG_MED, "STATE S_START"); > diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h > index 0777c61..3fbd2b4 100644 > --- a/src/openvpn/ssl_backend.h > +++ b/src/openvpn/ssl_backend.h > @@ -353,7 +353,7 @@ void key_state_ssl_free(struct key_state_ssl *ks_ssl); > * "[[INLINE]]" in the case of inline files. > * @param crl_inlineA string containing the CRL > */ > -void tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, > +void backend_tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, > const char *crl_file, const char *crl_inline); > > /** > diff --git a/src/openvpn/ssl_mbedtls.c b/src/openvpn/ssl_mbedtls.c > index 7fa35a7..11ee65b 100644 > --- a/src/openvpn/ssl_mbedtls.c > +++ b/src/openvpn/ssl_mbedtls.c > @@ -771,7 +771,7 @@ static void tls_version_to_major_minor(int tls_ver, int > *major, int *minor) { > } > > void > -tls_ctx_reload_crl(struct tls_root_ctx *ctx, const char *crl_file, > +backend_tls_ctx_reload_crl(struct tls_root_ctx *ctx, const
Re: [Openvpn-devel] [PATCH] reload CRL only if file was modified
Hi, On 30-11-16 02:16, Antonio Quartulli wrote: > Do I really need to split declaration and definition? Or can I just > doxy-document the definition in the same place where it is now? Well, either add a declaration at the top of the file (before the first usage), or move the function up to before the first usage and document it without splitting it. >> This can be done without the 'reload' argument too, something like: >> >> /* if something goes wrong with stat(), we'll store 0 as mtime */ >> platform_stat_t crl_stat = {0}; >> >> if (crl_file_inline) >> { >> /* >>* an inline CRL can't change at runtime, therefore there is no >> need to >>* reload it. It will be reloaded upon config change + SIGHUP. >>*/ >> if (ssl_ctx->crl_last_mtime.tv_sec) >> return; >> else >> crl_stat.st_mtime = now; /* Set dummy mtime */ >> } >> else >> { >> platform_stat (crl_file, _stat); >> } >> >> /* >>* If this is not a reload, update the CRL right away. >>* Otherwise, update only if the CRL file was modified after the last >> reload. >>* Note: Windows does not support tv_nsec. >>*/ >> if (ssl_ctx->crl_last_mtime.tv_sec <= crl_stat.st_mtime) >> { >> ssl_ctx->crl_last_mtime.tv_sec = crl_stat.st_mtime; >> backend_tls_ctx_reload_crl (ssl_ctx, crl_file, crl_file_inline); >> } >> >> I slightly prefer this over adding the extra argument, but can live with >> your approach just fine too. Pick what you like best :) > > I guess the assumption here is that crl_last_mtime.tv_sec is initialized with > 0. > This would make your code work. And yeah, I also prefer to avoid the reload > argument ;) Correct. This might not be immediately clear in the code, but we have the good habit of zero-initilializing structs like this :) > Will make these changes and resend the patch. Thanks! -Steffan -- ___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Re: [Openvpn-devel] [PATCH] reload CRL only if file was modified
On Tue, Nov 29, 2016 at 05:43:33PM +0100, Steffan Karger wrote: [CUT..] > > > > +void > > +tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file, > > + const char *crl_file_inline, bool reload) > > This is only used within ssl.c, so should be static and have a function > declaration, preferably doxygen-documented, at the beginning of ssl.c. You're absolutely right about this function supposed to be static. I missed that. Do I really need to split declaration and definition? Or can I just doxy-document the definition in the same place where it is now? > > > +{ > > + /* if something goes wrong with stat(), we'll store 0 as mtime */ > > + platform_stat_t crl_stat = {0}; > > + > > + /* > > + * an inline CRL can't change at runtime, therefore there is no need to > > + * reload it. It will be reloaded upon config change + SIGHUP. > > + */ > > + if (crl_file_inline && reload) > > +return; > > + > > + if (!crl_file_inline) > > +platform_stat(crl_file, _stat); > > + > > + /* > > + * If this is not a reload, update the CRL right away. > > + * Otherwise, update only if the CRL file was modified after the last > > reload. > > + * Note: Windows does not support tv_nsec. > > + */ > > + if (reload && > > + (ssl_ctx->crl_last_mtime.tv_sec >= crl_stat.st_mtime)) > > +return; > > + > > + ssl_ctx->crl_last_mtime.tv_sec = crl_stat.st_mtime; > > + backend_tls_ctx_reload_crl(ssl_ctx, crl_file, crl_file_inline); > > +} > > This can be done without the 'reload' argument too, something like: > > /* if something goes wrong with stat(), we'll store 0 as mtime */ > platform_stat_t crl_stat = {0}; > > if (crl_file_inline) > { > /* >* an inline CRL can't change at runtime, therefore there is no > need to >* reload it. It will be reloaded upon config change + SIGHUP. >*/ > if (ssl_ctx->crl_last_mtime.tv_sec) > return; > else > crl_stat.st_mtime = now; /* Set dummy mtime */ > } > else > { > platform_stat (crl_file, _stat); > } > > /* >* If this is not a reload, update the CRL right away. >* Otherwise, update only if the CRL file was modified after the last > reload. >* Note: Windows does not support tv_nsec. >*/ > if (ssl_ctx->crl_last_mtime.tv_sec <= crl_stat.st_mtime) > { > ssl_ctx->crl_last_mtime.tv_sec = crl_stat.st_mtime; > backend_tls_ctx_reload_crl (ssl_ctx, crl_file, crl_file_inline); > } > > I slightly prefer this over adding the extra argument, but can live with > your approach just fine too. Pick what you like best :) I guess the assumption here is that crl_last_mtime.tv_sec is initialized with 0. This would make your code work. And yeah, I also prefer to avoid the reload argument ;) Will make these changes and resend the patch. Thanks for the comments! Cheers, -- Antonio Quartulli -- ___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Re: [Openvpn-devel] [PATCH] reload CRL only if file was modified
On 29-11-16 17:43, Steffan Karger wrote: > Will test more thoroughly tonight (hopefully on Windows too), but have a > lot of faith that those will succeed. Just did this, on linux and windows, and code works as expected. So once you've taken care of the (minor) remarks in my previous mails, I think this patch is good to go! -Steffan -- ___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Re: [Openvpn-devel] [PATCH] reload CRL only if file was modified
Hi, One more thing. On 29-11-16 07:38, Antonio Quartulli wrote: > + if (!crl_file_inline) > +platform_stat(crl_file, _stat); If platform_stat() fails, we now silently ignore the error and continue using the old CRL. I think using the old CRL is fine, but we should print a warning to tell the user so: if (!crl_file_inline && 0 != platform_stat(crl_file, _stat)) msg (M_WARN, "WARNING: Failed to stat CRL file, using cached CRL."); -Steffan -- ___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Re: [Openvpn-devel] [PATCH] reload CRL only if file was modified
Christian Hesseon Tue, 2016/11/29 20:16: > Oops, missed that in my logs (and did not find the code)... You are right, > cache is cleared. > > Either of both is just fine and it works as-is. So ignore my patch. Oops again... Looks like I answered a wrong mail. Please ignore... (The mail, not any patch. ;) -- main(a){char*c=/*Schoene Gruesse */"B?IJj;MEH" "CX:;",b;for(a/*Best regards my address:*/=0;b=c[a++];) putchar(b-1/(/*Chriscc -ox -xc - && ./x*/b/42*2-3)*42);} pgpBSCfFHb2Lq.pgp Description: OpenPGP digital signature -- ___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Re: [Openvpn-devel] [PATCH] reload CRL only if file was modified
Steffan Kargeron Tue, 2016/11/29 17:43: > Hi, > > Thanks for following up. I did some stare-at-code and trivial tests. > Will test more thoroughly tonight (hopefully on Windows too), but have a > lot of faith that those will succeed. I have some comments from staring > at the code though, see below. Oops, missed that in my logs (and did not find the code)... You are right, cache is cleared. Either of both is just fine and it works as-is. So ignore my patch. -- main(a){char*c=/*Schoene Gruesse */"B?IJj;MEH" "CX:;",b;for(a/*Best regards my address:*/=0;b=c[a++];) putchar(b-1/(/*Chriscc -ox -xc - && ./x*/b/42*2-3)*42);} pgp7MmI2_Fygp.pgp Description: OpenPGP digital signature -- ___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Re: [Openvpn-devel] [PATCH] reload CRL only if file was modified
Hi, Thanks for following up. I did some stare-at-code and trivial tests. Will test more thoroughly tonight (hopefully on Windows too), but have a lot of faith that those will succeed. I have some comments from staring at the code though, see below. On 29-11-16 07:38, Antonio Quartulli wrote: > In order to prevent annoying delays upon client connection, > reload the CRL file only if it was modified since the last > reload operation. > If not, keep on using the already stored CRL. > > This change will boost client connection time in instances > where the CRL file is quite large (dropping from several > seconds to few milliseconds). > > Cc: Steffan Karger> Signed-off-by: Antonio Quartulli > --- > > Tested on linux by using my VM. > No test was performed on Windows* (compiled-only). > > Note: the check "!(session->opt->ssl_flags & SSLF_CRL_VERIFY_DIR))" may not > always work as expected. The user may forge a wrong, but still compliant, > configuration that would fool this test. This issue exists even before > applying > this patch. > > Cheers, > > src/openvpn/ssl.c | 40 +--- > src/openvpn/ssl_backend.h | 2 +- > src/openvpn/ssl_mbedtls.c | 2 +- > src/openvpn/ssl_mbedtls.h | 1 + > src/openvpn/ssl_openssl.c | 2 +- > src/openvpn/ssl_openssl.h | 1 + > 6 files changed, 42 insertions(+), 6 deletions(-) > > diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c > index 7347a78..235f7df 100644 > --- a/src/openvpn/ssl.c > +++ b/src/openvpn/ssl.c > @@ -612,7 +612,8 @@ init_ssl (const struct options *options, struct > tls_root_ctx *new_ctx) >/* Read CRL */ >if (options->crl_file && !(options->ssl_flags & SSLF_CRL_VERIFY_DIR)) > { > - tls_ctx_reload_crl(new_ctx, options->crl_file, > options->crl_file_inline); > + tls_ctx_reload_crl(new_ctx, options->crl_file, > options->crl_file_inline, > + false); > } > >/* Once keys and cert are loaded, load ECDH parameters */ > @@ -2450,6 +2451,36 @@ auth_deferred_expire_window (const struct tls_options > *o) >return ret; > } > > +void > +tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file, > +const char *crl_file_inline, bool reload) This is only used within ssl.c, so should be static and have a function declaration, preferably doxygen-documented, at the beginning of ssl.c. > +{ > + /* if something goes wrong with stat(), we'll store 0 as mtime */ > + platform_stat_t crl_stat = {0}; > + > + /* > + * an inline CRL can't change at runtime, therefore there is no need to > + * reload it. It will be reloaded upon config change + SIGHUP. > + */ > + if (crl_file_inline && reload) > +return; > + > + if (!crl_file_inline) > +platform_stat(crl_file, _stat); > + > + /* > + * If this is not a reload, update the CRL right away. > + * Otherwise, update only if the CRL file was modified after the last > reload. > + * Note: Windows does not support tv_nsec. > + */ > + if (reload && > + (ssl_ctx->crl_last_mtime.tv_sec >= crl_stat.st_mtime)) > +return; > + > + ssl_ctx->crl_last_mtime.tv_sec = crl_stat.st_mtime; > + backend_tls_ctx_reload_crl(ssl_ctx, crl_file, crl_file_inline); > +} This can be done without the 'reload' argument too, something like: /* if something goes wrong with stat(), we'll store 0 as mtime */ platform_stat_t crl_stat = {0}; if (crl_file_inline) { /* * an inline CRL can't change at runtime, therefore there is no need to * reload it. It will be reloaded upon config change + SIGHUP. */ if (ssl_ctx->crl_last_mtime.tv_sec) return; else crl_stat.st_mtime = now; /* Set dummy mtime */ } else { platform_stat (crl_file, _stat); } /* * If this is not a reload, update the CRL right away. * Otherwise, update only if the CRL file was modified after the last reload. * Note: Windows does not support tv_nsec. */ if (ssl_ctx->crl_last_mtime.tv_sec <= crl_stat.st_mtime) { ssl_ctx->crl_last_mtime.tv_sec = crl_stat.st_mtime; backend_tls_ctx_reload_crl (ssl_ctx, crl_file, crl_file_inline); } I slightly prefer this over adding the extra argument, but can live with your approach just fine too. Pick what you like best :) -Steffan -- ___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
[Openvpn-devel] [PATCH] reload CRL only if file was modified
In order to prevent annoying delays upon client connection, reload the CRL file only if it was modified since the last reload operation. If not, keep on using the already stored CRL. This change will boost client connection time in instances where the CRL file is quite large (dropping from several seconds to few milliseconds). Cc: Steffan KargerSigned-off-by: Antonio Quartulli --- Tested on linux by using my VM. No test was performed on Windows* (compiled-only). Note: the check "!(session->opt->ssl_flags & SSLF_CRL_VERIFY_DIR))" may not always work as expected. The user may forge a wrong, but still compliant, configuration that would fool this test. This issue exists even before applying this patch. Cheers, src/openvpn/ssl.c | 40 +--- src/openvpn/ssl_backend.h | 2 +- src/openvpn/ssl_mbedtls.c | 2 +- src/openvpn/ssl_mbedtls.h | 1 + src/openvpn/ssl_openssl.c | 2 +- src/openvpn/ssl_openssl.h | 1 + 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index 7347a78..235f7df 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -612,7 +612,8 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx) /* Read CRL */ if (options->crl_file && !(options->ssl_flags & SSLF_CRL_VERIFY_DIR)) { - tls_ctx_reload_crl(new_ctx, options->crl_file, options->crl_file_inline); + tls_ctx_reload_crl(new_ctx, options->crl_file, options->crl_file_inline, +false); } /* Once keys and cert are loaded, load ECDH parameters */ @@ -2450,6 +2451,36 @@ auth_deferred_expire_window (const struct tls_options *o) return ret; } +void +tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file, + const char *crl_file_inline, bool reload) +{ + /* if something goes wrong with stat(), we'll store 0 as mtime */ + platform_stat_t crl_stat = {0}; + + /* + * an inline CRL can't change at runtime, therefore there is no need to + * reload it. It will be reloaded upon config change + SIGHUP. + */ + if (crl_file_inline && reload) +return; + + if (!crl_file_inline) +platform_stat(crl_file, _stat); + + /* + * If this is not a reload, update the CRL right away. + * Otherwise, update only if the CRL file was modified after the last reload. + * Note: Windows does not support tv_nsec. + */ + if (reload && + (ssl_ctx->crl_last_mtime.tv_sec >= crl_stat.st_mtime)) +return; + + ssl_ctx->crl_last_mtime.tv_sec = crl_stat.st_mtime; + backend_tls_ctx_reload_crl(ssl_ctx, crl_file, crl_file_inline); +} + /* * This is the primary routine for processing TLS stuff inside the * the main event loop. When this routine exits @@ -2581,12 +2612,15 @@ tls_process (struct tls_multi *multi, ks->state = S_START; state_change = true; - /* Reload the CRL before TLS negotiation */ + /* + * Attempt CRL reload before TLS negotiation. Won't be performed if + * the file was not modified since the last reload + */ if (session->opt->crl_file && !(session->opt->ssl_flags & SSLF_CRL_VERIFY_DIR)) { tls_ctx_reload_crl(>opt->ssl_ctx, - session->opt->crl_file, session->opt->crl_file_inline); + session->opt->crl_file, session->opt->crl_file_inline, true); } dmsg (D_TLS_DEBUG_MED, "STATE S_START"); diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h index 0777c61..3fbd2b4 100644 --- a/src/openvpn/ssl_backend.h +++ b/src/openvpn/ssl_backend.h @@ -353,7 +353,7 @@ void key_state_ssl_free(struct key_state_ssl *ks_ssl); * "[[INLINE]]" in the case of inline files. * @param crl_inlineA string containing the CRL */ -void tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, +void backend_tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file, const char *crl_inline); /** diff --git a/src/openvpn/ssl_mbedtls.c b/src/openvpn/ssl_mbedtls.c index 7fa35a7..11ee65b 100644 --- a/src/openvpn/ssl_mbedtls.c +++ b/src/openvpn/ssl_mbedtls.c @@ -771,7 +771,7 @@ static void tls_version_to_major_minor(int tls_ver, int *major, int *minor) { } void -tls_ctx_reload_crl(struct tls_root_ctx *ctx, const char *crl_file, +backend_tls_ctx_reload_crl(struct tls_root_ctx *ctx, const char *crl_file, const char *crl_inline) { ASSERT (crl_file); diff --git a/src/openvpn/ssl_mbedtls.h b/src/openvpn/ssl_mbedtls.h index 3edeedc..911f3c7 100644 --- a/src/openvpn/ssl_mbedtls.h +++ b/src/openvpn/ssl_mbedtls.h @@ -74,6 +74,7 @@ struct tls_root_ctx { mbedtls_x509_crt *ca_chain;/**< CA chain for remote verification */ mbedtls_pk_context *priv_key; /**< Local private key */ mbedtls_x509_crl *crl; /**< Certificate Revocation List */ +struct