Don't throw fatal errors from create_temp_file()
PATCH 1/2 Don't throw fatal errors from create_temp_file()
This function is called in response to connecting clients, and can fail when I/O fails for some (possibly temporary) reason. In such cases we should not exit the process, but just reject the connecting client.
This commit changes the function to actually return NULL on errors, and (where needed) changes the callers to check for and handle errors.
Note that this changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
Since the tls-crypt-v2 metadata code also calls create_temp_file() when clients connect, I consider this a prerequisite for tls-crypt-v2.
--- src/openvpn/misc.c | 6 +++--- src/openvpn/pf.c | 8 ++++---- src/openvpn/ssl_verify.c | 32 +++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 18 deletions(-)
src/openvpn/misc.c +3 -3
@@ -740,7 +740,7 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) retfname =gen_path (directory,BSTR (&fname), gc);if (!retfname) { -msg (M_FATAL ,"Failed to create temporary filename and path" ); +msg (M_WARN ,"Failed to create temporary filename and path" );return NULL ; }
@@ -755,14 +755,14 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)else if (fd ==-1 && errno !=EEXIST ) {/* Something else went wrong, no need to retry. */ -msg (M_FATAL |M_ERRNO ,"Could not create temporary file '%s'" , +msg (M_WARN |M_ERRNO ,"Could not create temporary file '%s'" , retfname);return NULL ; } }while (attempts <6 ); -msg (M_FATAL ,"Failed to create temporary file after %i attempts" , attempts); +msg (M_WARN ,"Failed to create temporary file after %i attempts" , attempts);return NULL ; }
src/openvpn/pf.c +4 -4
@@ -639,10 +639,10 @@ pf_init_context(struct context *c) } #endif } -else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - } + } +if (!c->c2.pf.enabled) + { +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); } }#endif /* ifdef PLUGIN_PF */
src/openvpn/ssl_verify.c +21 -11
@@ -547,14 +547,14 @@ verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, struFILE *peercert_file;const char *peercert_filename ="" ; -if (!tmp_dir) +/* create tmp file to store peer cert */ +if (!tmp_dir || + !(peercert_filename =create_temp_file (tmp_dir,"pcf" , gc))) { +msg (M_WARN ,"Failed to create peer cert file" );return NULL ; } -/* create tmp file to store peer cert */ - peercert_filename =create_temp_file (tmp_dir,"pcf" , gc); -/* write peer-cert in tmp-file */ peercert_file =fopen (peercert_filename,"w+" );if (!peercert_file)
@@ -589,10 +589,13 @@ verify_cert_call_command(const char *verify_command, struct env_set *es,if (verify_export_cert) { -if ((tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc))) + tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc); +if (!tmp_file) { -setenv_str (es,"peer_cert" , tmp_file); + ret = false; + goto cleanup; } +setenv_str (es,"peer_cert" , tmp_file); }argv_parse_cmd (&argv, verify_command);
@@ -609,6 +612,7 @@ verify_cert_call_command(const char *verify_command, struct env_set *es, } } +cleanup:gc_free (&gc);argv_reset (&argv);
@@ -879,21 +883,21 @@ key_state_rm_auth_control_file(struct key_state *ks) } } -static void +static bool key_state_gen_auth_control_file (struct key_state *ks,const struct tls_options *opt) {struct gc_arena gc =gc_new (); -const char *acf;key_state_rm_auth_control_file (ks); - acf =create_temp_file (opt->tmp_dir,"acf" , &gc); +const char *acf =create_temp_file (opt->tmp_dir,"acf" , &gc);if (acf) { ks->auth_control_file =string_alloc (acf,NULL );setenv_str (opt->es,"auth_control_file" , ks->auth_control_file); - }/* FIXME: Should have better error handling? */ + }gc_free (&gc); +return acf; } static unsigned int
@@ -1184,7 +1188,12 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,#ifdef PLUGIN_DEF_AUTH /* generate filename for deferred auth control file */ -key_state_gen_auth_control_file (ks, session->opt); +if (!key_state_gen_auth_control_file (ks, session->opt)) + { +msg (D_TLS_ERRORS ,"TLS Auth Error (%s): " +"could not create deferred auth control file" , __func__); + goto cleanup; + }#endif /* call command */
@@ -1209,6 +1218,7 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,msg (D_TLS_ERRORS ,"TLS Auth Error (verify_user_pass_plugin): peer provided a blank username" ); } +cleanup:return retval; }
Signature · 1 line
2.7.4
PATCH 2/2 pf: clean up temporary files if plugin init fails
close_instance() tries to remove the file in c2.pf.filename, but that only works if we actually set that if we fail. So, set that filename as soon as we know we've created the file.
--- src/openvpn/pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
src/openvpn/pf.c +1 -1
@@ -625,12 +625,12 @@ pf_init_context(struct context *c)const char *pf_file =create_temp_file (c->options.tmp_dir,"pf" , &gc);if (pf_file) { + c->c2.pf.filename =string_alloc (pf_file, &c->c2.gc);setenv_str (c->c2.es,"pf_file" , pf_file);if (plugin_call (c->plugins,OPENVPN_PLUGIN_ENABLE_PF ,NULL ,NULL , c->c2.es) ==OPENVPN_PLUGIN_FUNC_SUCCESS ) {event_timeout_init (&c->c2.pf.reload,1 , now); - c->c2.pf.filename =string_alloc (pf_file, &c->c2.gc); c->c2.pf.enabled = true;#ifdef ENABLE_DEBUG if (check_debug_level (D_PF_DEBUG ))
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [PATCH 2/2] pf: clean up temporary files if plugin init fails
Hi,
Quoted 14 lines · Steffan Karger
close_instance()tries to remove the file in c2.pf.filename, but that only works if we actually set that if we fail. So, set that filename as soon as we know we've created the file.Signed-off-by Steffan Karger <[email protected]...>--- src/openvpn/pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)src/openvpn/pf.c +0
-0
src/openvpn/pf.c pf_init_context(struct context *c) · line 625
Quoted 1 line
src/openvpn/pf.c +0
-0@@ -625,12 +625,12 @@ pf_init_context(struct context *c)const char *pf_file =create_temp_file (c->options.tmp_dir,"pf" , &gc);
what prevents us from calling create_temp_file() directly with c->c2.pf.filename and &c->c2.gc as arguments?
Cheers,
Quoted 13 lines
src/openvpn/pf.c +1
-1if (pf_file) { + c->c2.pf.filename =string_alloc (pf_file, &c->c2.gc);setenv_str (c->c2.es,"pf_file" , pf_file);if (plugin_call (c->plugins,OPENVPN_PLUGIN_ENABLE_PF ,NULL ,NULL , c->c2.es) ==OPENVPN_PLUGIN_FUNC_SUCCESS ) {event_timeout_init (&c->c2.pf.reload,1 , now); - c->c2.pf.filename =string_alloc (pf_file, &c->c2.gc); c->c2.pf.enabled = true;#ifdef ENABLE_DEBUG if (check_debug_level (D_PF_DEBUG ))
Signature · 1 line
Antonio Quartulli
PATCH v2 1/1 pf: clean up temporary files if plugin init fails
close_instance() tries to remove the file in c2.pf.filename, but that only works if we actually set that if we fail. So, set that filename as soon as we know we've created the file.
---
v2: As suggested by Antionio, get rid of local 'gc' and 'file' vars.
src/openvpn/pf.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
src/openvpn/pf.c +4 -6
@@ -618,19 +618,18 @@ pf_load_from_buffer_list(struct context *c, const struct buffer_list *config)void pf_init_context (struct context *c) { -struct gc_arena gc =gc_new ();#ifdef PLUGIN_PF if (plugin_defined (c->plugins,OPENVPN_PLUGIN_ENABLE_PF )) { -const char *pf_file =create_temp_file (c->options.tmp_dir,"pf" , &gc); -if (pf_file) + c->c2.pf.filename =create_temp_file (c->options.tmp_dir,"pf" , + &c->c2.gc); +if (c->c2.pf.filename) { -setenv_str (c->c2.es,"pf_file" , pf_file); +setenv_str (c->c2.es,"pf_file" , c->c2.pf.filename);if (plugin_call (c->plugins,OPENVPN_PLUGIN_ENABLE_PF ,NULL ,NULL , c->c2.es) ==OPENVPN_PLUGIN_FUNC_SUCCESS ) {event_timeout_init (&c->c2.pf.reload,1 , now); - c->c2.pf.filename =string_alloc (pf_file, &c->c2.gc); c->c2.pf.enabled = true;#ifdef ENABLE_DEBUG if (check_debug_level (D_PF_DEBUG ))
@@ -658,7 +657,6 @@ pf_init_context(struct context *c) #endif }#endif -gc_free (&gc); }void
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [PATCH v2] pf: clean up temporary files if plugin init fails
Quoted 7 lines · Steffan Karger
close_instance()tries to remove the file in c2.pf.filename, but that only works if we actually set that if we fail. So, set that filename as soon as we know we've created the file.Signed-off-by Steffan Karger <[email protected]...>---
v2: As suggested by Antionio, get rid of local 'gc' and 'file' vars.
ACK.
Signature · 1 line
Antonio Quartulli
Re: [Openvpn-devel] [PATCH v2] pf: clean up temporary files if plugin init fails
In reply to Steffan KargerQuoted 17 lines · Steffan Karger
close_instance()tries to remove the file in c2.pf.filename, but that only works if we actually set that if we fail. So, set that filename as soon as we know we've created the file.Signed-off-by Steffan Karger <[email protected]...>---
v2: As suggested by Antionio, get rid of local 'gc' and 'file' vars.src/openvpn/pf.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)src/openvpn/pf.c +0
-0@@ -618,19 +618,18 @@ pf_load_from_buffer_list(struct context *c, const struct buffer_list *config)void
src/openvpn/pf.c pf_load_from_buffer_list(struct context *c, const struct buffer_list *config) · line 625
Quoted 10 lines
src/openvpn/pf.c +2
-3pf_init_context(struct context *c) { -struct gc_arena gc =gc_new ();#ifdef PLUGIN_PF if (plugin_defined (c->plugins,OPENVPN_PLUGIN_ENABLE_PF )) { -const char *pf_file =create_temp_file (c->options.tmp_dir,"pf" , &gc); -if (pf_file) + c->c2.pf.filename =create_temp_file (c->options.tmp_dir,"pf" , + &c->c2.gc);
Patch looks good. But it introduces a new compile warning.
pf.c: In function ‘pf_init_context’:
pf.c:624:27: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]
c->c2.pf.filename = create_temp_file(c->options.tmp_dir, "pf",
I'm pondering if we need create_temp_file() to actually return a const char * - wouldn't just a plain char * be enough?
The alternative is to cast the const away here; but that just feels too hacky in this code path.
Signature · 4 lines
kind regards, David Sommerseth OpenVPN Technologies, Inc
Re: [Openvpn-devel] [PATCH v2] pf: clean up temporary files if plugin init fails
Hi,
Quoted 31 lines · David Sommerseth
Quoted 17 lines · Steffan Karger
close_instance()tries to remove the file in c2.pf.filename, but that only works if we actually set that if we fail. So, set that filename as soon as we know we've created the file.Signed-off-by Steffan Karger <[email protected]...>---
v2: As suggested by Antionio, get rid of local 'gc' and 'file' vars.src/openvpn/pf.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)src/openvpn/pf.c +0
-0@@ -618,19 +618,18 @@ pf_load_from_buffer_list(struct context *c, const struct buffer_list *config)void src/openvpn/pf.c pf_load_from_buffer_list(struct context *c, const struct buffer_list *config) · line 625
Quoted 10 lines
src/openvpn/pf.c +2
-3pf_init_context(struct context *c) { -struct gc_arena gc =gc_new ();#ifdef PLUGIN_PF if (plugin_defined (c->plugins,OPENVPN_PLUGIN_ENABLE_PF )) { -const char *pf_file =create_temp_file (c->options.tmp_dir,"pf" , &gc); -if (pf_file) + c->c2.pf.filename =create_temp_file (c->options.tmp_dir,"pf" , + &c->c2.gc);Patch looks good. But it introduces a new compile warning.
Quoted 6 lines
pf.c: In function ‘pf_init_context’:
pf.c:624:27: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]c->c2.pf.filename = create_temp_file(c->options.tmp_dir, "pf",I'm pondering if we need
create_temp_file()to actually return a const char * - wouldn't just a plain char * be enough?
Good point. But I think it's best to return a const char * here, because the memory is allocated through a gc and therefore should also be free'd through the gc. The const modifier prevents freeing the data without a warning (as long as you keep smacking me for discarding const qualifiers, or we add a -Werror compile flag ;-) ).
Quoted 2 lines
The alternative is to cast the const away here; but that just feels too hacky in this code path.
Or change c->c2.filename to be const char *. I think that's the way to go here. And possibly reject a NULL gc argument in create_temp_file(), because that would make the function leak memory...
What do you think?
-Steffan
Re: [Openvpn-devel] [PATCH v2] pf: clean up temporary files if plugin init fails
Quoted 47 lines · Steffan Karger
Hi,
Quoted 31 lines · David Sommerseth
Quoted 17 lines · Steffan Karger
close_instance()tries to remove the file in c2.pf.filename, but that only works if we actually set that if we fail. So, set that filename as soon as we know we've created the file.Signed-off-by Steffan Karger <[email protected]...>---
v2: As suggested by Antionio, get rid of local 'gc' and 'file' vars.src/openvpn/pf.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)src/openvpn/pf.c +0
-0@@ -618,19 +618,18 @@ pf_load_from_buffer_list(struct context *c, const struct buffer_list *config)void src/openvpn/pf.c pf_load_from_buffer_list(struct context *c, const struct buffer_list *config) · line 625
Quoted 10 lines
src/openvpn/pf.c +2
-3pf_init_context(struct context *c) { -struct gc_arena gc =gc_new ();#ifdef PLUGIN_PF if (plugin_defined (c->plugins,OPENVPN_PLUGIN_ENABLE_PF )) { -const char *pf_file =create_temp_file (c->options.tmp_dir,"pf" , &gc); -if (pf_file) + c->c2.pf.filename =create_temp_file (c->options.tmp_dir,"pf" , + &c->c2.gc);Patch looks good. But it introduces a new compile warning.
Quoted 6 lines
pf.c: In function ‘pf_init_context’:
pf.c:624:27: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]c->c2.pf.filename = create_temp_file(c->options.tmp_dir, "pf",I'm pondering if we need
create_temp_file()to actually return a const char * - wouldn't just a plain char * be enough?Good point. But I think it's best to return a const char * here, because the memory is allocated through a gc and therefore should also be free'd through the gc. The const modifier prevents freeing the data without a warning (as long as you keep smacking me for discarding const qualifiers, or we add a -Werror compile flag ;-) ).
Quoted 8 lines
Quoted 2 lines
The alternative is to cast the const away here; but that just feels too hacky in this code path.
Or change
c->c2.filenameto be const char *. I think that's the way to go here. And possibly reject a NULL gc argument increate_temp_file(), because that would make the function leak memory...What do you think?
I personally like that. It somehow brings in the concept of 'ownership' and avoids introducing faulty code (we'd get warned as you said above).
Cheers,
Signature · 1 line
Antonio Quartulli
PATCH v3 2/2 pf: clean up temporary files if plugin init fails
From: Steffan Karger <[email protected]...>
close_instance() tries to remove the file in c2.pf.filename, but that only works if we actually set that if we fail. So, set that filename as soon as we know we've created the file.
---
v2: As suggested by Antionio, get rid of local 'gc' and 'file' vars.
v3: Make (struct pf_context).filename a const char *
src/openvpn/pf.c | 10 ++++------ src/openvpn/pf.h | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-)
src/openvpn/pf.c +4 -6
@@ -618,19 +618,18 @@ pf_load_from_buffer_list(struct context *c, const struct buffer_list *config)void pf_init_context (struct context *c) { -struct gc_arena gc =gc_new ();#ifdef PLUGIN_PF if (plugin_defined (c->plugins,OPENVPN_PLUGIN_ENABLE_PF )) { -const char *pf_file =create_temp_file (c->options.tmp_dir,"pf" , &gc); -if (pf_file) + c->c2.pf.filename =create_temp_file (c->options.tmp_dir,"pf" , + &c->c2.gc); +if (c->c2.pf.filename) { -setenv_str (c->c2.es,"pf_file" , pf_file); +setenv_str (c->c2.es,"pf_file" , c->c2.pf.filename);if (plugin_call (c->plugins,OPENVPN_PLUGIN_ENABLE_PF ,NULL ,NULL , c->c2.es) ==OPENVPN_PLUGIN_FUNC_SUCCESS ) {event_timeout_init (&c->c2.pf.reload,1 , now); - c->c2.pf.filename =string_alloc (pf_file, &c->c2.gc); c->c2.pf.enabled = true;#ifdef ENABLE_DEBUG if (check_debug_level (D_PF_DEBUG ))
@@ -659,7 +658,6 @@ pf_init_context(struct context *c) #endif }#endif -gc_free (&gc); }void
src/openvpn/pf.h +1 -1
@@ -75,7 +75,7 @@ struct pf_context {bool enabled;struct pf_set *pfs;#ifdef PLUGIN_PF -char *filename; +const char *filename;time_t file_last_mod;unsigned int n_check_reload;struct event_timeout reload;
Signature · 1 line
2.11.0
[Openvpn-devel] [PATCH 3/2] create_temp_file: prevent memory leak if gc == NULL
In reply to Antonio QuartulliIf gc == NULL, the data allocated in the alloc_gc_buf() call would never be free'd. The function is never called that way, but let's prevent future problems.
--- src/openvpn/misc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
src/openvpn/misc.c +4 -1
@@ -724,10 +724,13 @@ const char * create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) { static unsigned int counter; -struct buffer fname =alloc_buf_gc (256 , gc);int fd;const char *retfname =NULL ;unsigned int attempts =0 ; +struct buffer fname = (struct buffer ) {0 }; +char buf_data[256 ] = {0 }; + +buf_set_write (&fname, buf_data,sizeof (buf_data)); do {
Signature · 1 line
2.11.0
Re: [Openvpn-devel] [PATCH 3/2] create_temp_file: prevent memory leak if gc == NULL
Hi,
Quoted 3 lines · Steffan Karger
If gc == NULL, the data allocated in the
alloc_gc_buf()call would never be free'd. The function is never called that way, but let's prevent future problems.
Same problem exists with the invocation of gen_path() a few lines below:
it invokes string_mod_const() that invokes string_alloc(.., gc).
Would you fix that as well? Under the same umbrella patch maybe?
Quoted 12 lines
Signed-off-by Steffan Karger <[email protected]...>--- src/openvpn/misc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)src/openvpn/misc.c +0
-0@@ -724,10 +724,13 @@ const char * create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)
src/openvpn/misc.c const char * · line 733
Quoted 10 lines
src/openvpn/misc.c +4
-1{static unsigned int counter; -struct buffer fname =alloc_buf_gc (256 , gc);int fd;const char *retfname =NULL ;unsigned int attempts =0 ; +struct buffer fname = (struct buffer ) {0 }; +char buf_data[256 ] = {0 }; + +buf_set_write (&fname, buf_data,sizeof (buf_data));
This buffer is really only used to create a filename and then it's passed to gen_path().
Is it really worth creating a struct buffer, embedding a string and then extrapolating the string again to call gen_path()?
How about directly using the string directly?
The only argument against this approach I can see is that buf_printf() does all the checks for us, while if we switch to a snprintf() we need to add a one-line-check to ensure the resulting string could fit fname.
What do you think?
I am just trying to simplify the code while at it ..
Cheers,
Signature · 1 line
Antonio Quartulli
PATCH v2 1/1 create_temp_file/gen_path: prevent memory leak if gc == NULL
If gc == NULL, the data allocated in the alloc_gc_buf() call in create_temp_file or the string_mod_const call in gen_path would never be free'd.
These functions are currently never called that way, but let's prevent future problems.
While touching create_temp_file, also remove the counter variable, which is never read.
---
v2:
- change create_temp_file to avoid using a struct buffer (simpler)
- add gc != NULL check for gen_path (avoid similar memleak pitfall)
src/openvpn/misc.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
src/openvpn/misc.c +11 -6
@@ -723,21 +723,20 @@ test_file(const char *filename)const char *create_temp_file (const char *directory,const char *prefix,struct gc_arena *gc) { -static unsigned int counter; -struct buffer fname =alloc_buf_gc (256 , gc);int fd;const char *retfname =NULL ;unsigned int attempts =0 ; +char fname[256 ] = {0 }; do { ++attempts; - ++counter; - buf_printf(&fname, PACKAGE "_%s_%08lx%08lx.tmp", prefix, - (unsigned long) get_random(), (unsigned long) get_random()); + openvpn_snprintf(fname, sizeof(fname), PACKAGE "_%s_%08lx%08lx.tmp", + prefix, (unsigned long) get_random(), + (unsigned long) get_random()); - retfname = gen_path(directory, BSTR(&fname), gc); + retfname = gen_path(directory, fname, gc); if (!retfname) { msg(M_WARN, "Failed to create temporary filename and path");
@@ -812,6 +811,12 @@ gen_path(const char *directory, const char *filename, struct gc_arena *gc)#else const int CC_PATH_RESERVED =CC_SLASH ;#endif + +if (!gc) + { +return NULL ;/* Would leak memory otherwise */ + } +const char *safe_filename =string_mod_const (filename,CC_PRINT ,CC_PATH_RESERVED ,'_' , gc); if (safe_filename
Signature · 1 line
2.11.0
Re: [Openvpn-devel] [PATCH v2] create_temp_file/gen_path: prevent memory leak if gc == NULL
Quoted 34 lines · Steffan Karger
If gc == NULL, the data allocated in the
alloc_gc_buf()call increate_temp_fileor thestring_mod_constcall ingen_pathwould never be free'd.These functions are currently never called that way, but let's prevent future problems.
While touching
create_temp_file, also remove the counter variable, which is never read.Signed-off-by Steffan Karger <[email protected]...>---
v2:
- changecreate_temp_fileto avoid using a struct buffer (simpler)
- add gc != NULL check forgen_path(avoid similar memleak pitfall)src/openvpn/misc.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)src/openvpn/misc.c +1
-2@@ -723,21 +723,20 @@ test_file(const char *filename)const char *create_temp_file (const char *directory,const char *prefix,struct gc_arena *gc) { -static unsigned int counter; -struct buffer fname =alloc_buf_gc (256 , gc);int fd;const char *retfname =NULL ;unsigned int attempts =0 ; +char fname[256 ] = {0 };
src/openvpn/misc.c test_file(const char *filename) · line 737
Quoted 10 lines
src/openvpn/misc.c +3
-3do { ++attempts; - ++counter; - buf_printf(&fname, PACKAGE "_%s_%08lx%08lx.tmp", prefix, - (unsigned long) get_random(), (unsigned long) get_random()); + openvpn_snprintf(fname, sizeof(fname), PACKAGE "_%s_%08lx%08lx.tmp", + prefix, (unsigned long) get_random(), + (unsigned long) get_random());
Minor thought: do we want to check if the return value of snprintf is >= sizeof(fname)? That would tell us if the string did not entirely fit in the buffer so that we can abort the whole file creation.
Cheers,
Quoted 20 lines
src/openvpn/misc.c +7
-1- retfname =gen_path (directory,BSTR (&fname), gc); + retfname =gen_path (directory, fname, gc);if (!retfname) {msg (M_WARN ,"Failed to create temporary filename and path" );@@ -812,6 +811,12 @@ gen_path(const char *directory, const char *filename, struct gc_arena *gc)#else const int CC_PATH_RESERVED =CC_SLASH ;#endif + +if (!gc) + { +return NULL ;/* Would leak memory otherwise */ + } +const char *safe_filename =string_mod_const (filename,CC_PRINT ,CC_PATH_RESERVED ,'_' , gc); if (safe_filename
Signature · 1 line
Antonio Quartulli
I just did a quick skim for now and I only have a codestyle comment below:
Quoted 75 lines · Steffan Karger
This function is called in response to connecting clients, and can fail when I/O fails for some (possibly temporary) reason. In such cases we should not exit the process, but just reject the connecting client.
This commit changes the function to actually return NULL on errors, and (where needed) changes the callers to check for and handle errors.
Note that this changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
Since the tls-crypt-v2 metadata code also calls
create_temp_file()when clients connect, I consider this a prerequisite for tls-crypt-v2.Signed-off-by Steffan Karger <[email protected]...>--- src/openvpn/misc.c | 6 +++--- src/openvpn/pf.c | 8 ++++---- src/openvpn/ssl_verify.c | 32 +++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 18 deletions(-)src/openvpn/misc.c +3
-3@@ -740,7 +740,7 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) retfname =gen_path (directory,BSTR (&fname), gc);if (!retfname) { -msg (M_FATAL ,"Failed to create temporary filename and path" ); +msg (M_WARN ,"Failed to create temporary filename and path" );return NULL ; }@@ -755,14 +755,14 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)else if (fd ==-1 && errno !=EEXIST ) {/* Something else went wrong, no need to retry. */ -msg (M_FATAL |M_ERRNO ,"Could not create temporary file '%s'" , +msg (M_WARN |M_ERRNO ,"Could not create temporary file '%s'" , retfname);return NULL ; } }while (attempts <6 ); -msg (M_FATAL ,"Failed to create temporary file after %i attempts" , attempts); +msg (M_WARN ,"Failed to create temporary file after %i attempts" , attempts);return NULL ; }src/openvpn/pf.c +4
-4@@ -639,10 +639,10 @@ pf_init_context(struct context *c) } #endif } -else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - } + } +if (!c->c2.pf.enabled) + { +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); } }#endif /* ifdef PLUGIN_PF */ src/openvpn/ssl_verify.c +0
-0
src/openvpn/ssl_verify.c verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, stru · line 552
Quoted 7 lines
src/openvpn/ssl_verify.c +3
-1@@ -547,14 +547,14 @@ verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, struFILE *peercert_file;const char *peercert_filename ="" ; -if (!tmp_dir) +/* create tmp file to store peer cert */ +if (!tmp_dir || + !(peercert_filename =create_temp_file (tmp_dir,"pcf" , gc)))
The '||' should go at the beginning of the second line.
Quoted 84 lines
src/openvpn/ssl_verify.c +18
-10{ +msg (M_WARN ,"Failed to create peer cert file" );return NULL ; } -/* create tmp file to store peer cert */ - peercert_filename =create_temp_file (tmp_dir,"pcf" , gc); -/* write peer-cert in tmp-file */ peercert_file =fopen (peercert_filename,"w+" );if (!peercert_file)@@ -589,10 +589,13 @@ verify_cert_call_command(const char *verify_command, struct env_set *es,if (verify_export_cert) { -if ((tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc))) + tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc); +if (!tmp_file) { -setenv_str (es,"peer_cert" , tmp_file); + ret = false; + goto cleanup; } +setenv_str (es,"peer_cert" , tmp_file); }argv_parse_cmd (&argv, verify_command);@@ -609,6 +612,7 @@ verify_cert_call_command(const char *verify_command, struct env_set *es, } } +cleanup:gc_free (&gc);argv_reset (&argv);@@ -879,21 +883,21 @@ key_state_rm_auth_control_file(struct key_state *ks) } } -static void +static bool key_state_gen_auth_control_file (struct key_state *ks,const struct tls_options *opt) {struct gc_arena gc =gc_new (); -const char *acf;key_state_rm_auth_control_file (ks); - acf =create_temp_file (opt->tmp_dir,"acf" , &gc); +const char *acf =create_temp_file (opt->tmp_dir,"acf" , &gc);if (acf) { ks->auth_control_file =string_alloc (acf,NULL );setenv_str (opt->es,"auth_control_file" , ks->auth_control_file); - }/* FIXME: Should have better error handling? */ + }gc_free (&gc); +return acf; } static unsigned int@@ -1184,7 +1188,12 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,#ifdef PLUGIN_DEF_AUTH /* generate filename for deferred auth control file */ -key_state_gen_auth_control_file (ks, session->opt); +if (!key_state_gen_auth_control_file (ks, session->opt)) + { +msg (D_TLS_ERRORS ,"TLS Auth Error (%s): " +"could not create deferred auth control file" , __func__); + goto cleanup; + }#endif /* call command */ @@ -1209,6 +1218,7 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,msg (D_TLS_ERRORS ,"TLS Auth Error (verify_user_pass_plugin): peer provided a blank username" ); } +cleanup:return retval; }
Signature · 1 line
Antonio Quartulli
Hi,
Quoted 56 lines · Steffan Karger
This function is called in response to connecting clients, and can fail when I/O fails for some (possibly temporary) reason. In such cases we should not exit the process, but just reject the connecting client.
This commit changes the function to actually return NULL on errors, and (where needed) changes the callers to check for and handle errors.
Note that this changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
Since the tls-crypt-v2 metadata code also calls
create_temp_file()when clients connect, I consider this a prerequisite for tls-crypt-v2.Signed-off-by Steffan Karger <[email protected]...>--- src/openvpn/misc.c | 6 +++--- src/openvpn/pf.c | 8 ++++---- src/openvpn/ssl_verify.c | 32 +++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 18 deletions(-)src/openvpn/misc.c +3
-3@@ -740,7 +740,7 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) retfname =gen_path (directory,BSTR (&fname), gc);if (!retfname) { -msg (M_FATAL ,"Failed to create temporary filename and path" ); +msg (M_WARN ,"Failed to create temporary filename and path" );return NULL ; }@@ -755,14 +755,14 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)else if (fd ==-1 && errno !=EEXIST ) {/* Something else went wrong, no need to retry. */ -msg (M_FATAL |M_ERRNO ,"Could not create temporary file '%s'" , +msg (M_WARN |M_ERRNO ,"Could not create temporary file '%s'" , retfname);return NULL ; } }while (attempts <6 ); -msg (M_FATAL ,"Failed to create temporary file after %i attempts" , attempts); +msg (M_WARN ,"Failed to create temporary file after %i attempts" , attempts);return NULL ; }src/openvpn/pf.c +0
-0
src/openvpn/pf.c pf_init_context(struct context *c) · line 645
Quoted 7 lines
src/openvpn/pf.c +0
-4@@ -639,10 +639,10 @@ pf_init_context(struct context *c) }#endif } -else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - }
Why removing this chunk above? Isn't that supposed to be printed when the init function of the plugin fails?
src/openvpn/pf.c pf_init_context(struct context *c) · line 646
Quoted 5 lines
src/openvpn/pf.c +4
-0+ } +if (!c->c2.pf.enabled) + { +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); }
Maybe it's just me missing how the signaling part really works, but what happens on the server when the SIGUSR1 is delivered? And why registering the signal when PF is disabled? I am missing something I think...
Quoted 7 lines
src/openvpn/pf.c +0
-0}#endif /* ifdef PLUGIN_PF */ src/openvpn/ssl_verify.c +0
-0
src/openvpn/ssl_verify.c verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, stru · line 552
Quoted 7 lines
src/openvpn/ssl_verify.c +3
-1@@ -547,14 +547,14 @@ verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, struFILE *peercert_file;const char *peercert_filename ="" ; -if (!tmp_dir) +/* create tmp file to store peer cert */ +if (!tmp_dir || + !(peercert_filename =create_temp_file (tmp_dir,"pcf" , gc)))
|| at the beginning of the next line (as mentioned in my previous email)
Quoted 77 lines
src/openvpn/ssl_verify.c +17
-10{ +msg (M_WARN ,"Failed to create peer cert file" );return NULL ; } -/* create tmp file to store peer cert */ - peercert_filename =create_temp_file (tmp_dir,"pcf" , gc); -/* write peer-cert in tmp-file */ peercert_file =fopen (peercert_filename,"w+" );if (!peercert_file)@@ -589,10 +589,13 @@ verify_cert_call_command(const char *verify_command, struct env_set *es,if (verify_export_cert) { -if ((tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc))) + tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc); +if (!tmp_file) { -setenv_str (es,"peer_cert" , tmp_file); + ret = false; + goto cleanup; } +setenv_str (es,"peer_cert" , tmp_file); }argv_parse_cmd (&argv, verify_command);@@ -609,6 +612,7 @@ verify_cert_call_command(const char *verify_command, struct env_set *es, } } +cleanup:gc_free (&gc);argv_reset (&argv);@@ -879,21 +883,21 @@ key_state_rm_auth_control_file(struct key_state *ks) } } -static void +static bool key_state_gen_auth_control_file (struct key_state *ks,const struct tls_options *opt) {struct gc_arena gc =gc_new (); -const char *acf;key_state_rm_auth_control_file (ks); - acf =create_temp_file (opt->tmp_dir,"acf" , &gc); +const char *acf =create_temp_file (opt->tmp_dir,"acf" , &gc);if (acf) { ks->auth_control_file =string_alloc (acf,NULL );setenv_str (opt->es,"auth_control_file" , ks->auth_control_file); - }/* FIXME: Should have better error handling? */ + }gc_free (&gc); +return acf; } static unsigned int@@ -1184,7 +1188,12 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,#ifdef PLUGIN_DEF_AUTH /* generate filename for deferred auth control file */ -key_state_gen_auth_control_file (ks, session->opt); +if (!key_state_gen_auth_control_file (ks, session->opt)) + { +msg (D_TLS_ERRORS ,"TLS Auth Error (%s): " +"could not create deferred auth control file" , __func__); + goto cleanup; + }#endif /* call command */
src/openvpn/ssl_verify.c verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up, · line 1224
Quoted 7 lines
src/openvpn/ssl_verify.c +1
-0@@ -1209,6 +1218,7 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,msg (D_TLS_ERRORS ,"TLS Auth Error (verify_user_pass_plugin): peer provided a blank username" ); } +cleanup:return retval; }
The rest looks good to me.
Cheers,
Signature · 1 line
Antonio Quartulli
Hi,
Quoted 16 lines · Antonio Quartulli
src/openvpn/pf.c pf_init_context(struct context *c) · line 645
Quoted 12 lines · Steffan Karger
src/openvpn/pf.c +0
-4@@ -639,10 +639,10 @@ pf_init_context(struct context *c) }#endif } -else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - }Why removing this chunk above? Isn't that supposed to be printed when the init function of the plugin fails?
Because it's no longer true; instead of disabling the firewall, we will now reject the connection. I tried to explain that in the commit message:
Quoted 4 lines · Steffan Karger
Quoted 3 lines
Note that this changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
I think rejecting a client is the sensible thing to do when initializing the firewall failed. (Rather than accepting the client and not enforcing the firewall rules.)
Quoted 9 lines
src/openvpn/pf.c pf_init_context(struct context *c) · line 646
Quoted 5 lines
src/openvpn/pf.c +4
-0+ } +if (!c->c2.pf.enabled) + { +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); }Maybe it's just me missing how the signaling part really works, but what happens on the server when the SIGUSR1 is delivered? And why registering the signal when PF is disabled? I am missing something I think...
This registers a SIGUSR1 on the instance context, not the top-level context. This leads to an instance reset. See e.g. check_tls_errors(), which does the same in case of an error (or even uses SIGTERM, if --tls-exit is used).
Registering a signal is how error reporting is this part of the code works.
Quoted 10 lines
Quoted 10 lines
}#endif /* ifdef
PLUGIN_PF*/src/openvpn/ssl_verify.c +0
-0@@ -547,14 +547,14 @@ verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, struFILE *peercert_file;const char *peercert_filename ="" ;
Quoted 6 lines
src/openvpn/ssl_verify.c verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, stru · line 552
Quoted 4 lines
src/openvpn/ssl_verify.c +3
-1-if (!tmp_dir) +/* create tmp file to store peer cert */ +if (!tmp_dir || + !(peercert_filename =create_temp_file (tmp_dir,"pcf" , gc)))|| at the beginning of the next line (as mentioned in my previous email)
Will do, once we agree on the above discussion points.
Hope this clarifies things.
-Steffan
Hi²,
Quoted 23 lines · Steffan Karger
Hi,
Quoted 16 lines · Antonio Quartulli
src/openvpn/pf.c pf_init_context(struct context *c) · line 645
Quoted 12 lines · Steffan Karger
src/openvpn/pf.c +0
-4@@ -639,10 +639,10 @@ pf_init_context(struct context *c) }#endif } -else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - }Why removing this chunk above? Isn't that supposed to be printed when the init function of the plugin fails?
Because it's no longer true; instead of disabling the firewall, we will now reject the connection. I tried to explain that in the commit message:
Quoted 8 lines
Quoted 4 lines · Steffan Karger
Quoted 3 lines
Note that this changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
I think rejecting a client is the sensible thing to do when initializing the firewall failed. (Rather than accepting the client and not enforcing the firewall rules.)
Right.
This makes sense, but don't you think this is worth its own commit instead of hiding a behavioural change like this behind "Don't throw fatal errors from create_temp_file()" ? :-)
It could be done in a patch preceding this one, imho.
Quoted 11 lines
Quoted 10 lines
src/openvpn/pf.c pf_init_context(struct context *c) · line 646
Quoted 6 lines
src/openvpn/pf.c +4
-0+ } +if (!c->c2.pf.enabled) + { +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); }Maybe it's just me missing how the signaling part really works, but what happens on the server when the SIGUSR1 is delivered? And why registering the signal when PF is disabled? I am missing something I think...
Quoted 6 lines
This registers a SIGUSR1 on the instance context, not the top-level context. This leads to an instance reset. See e.g.
check_tls_errors(), which does the same in case of an error (or even uses SIGTERM, if --tls-exit is used).Registering a signal is how error reporting is this part of the code works.
I see, we basically use signals as they were flags. Thanks for clarifying that. I can see this is handled in init_instance() where we check for a signal and possibly abort the initialization of the child context. I think it makes sense and as you are saying this is similar to other error handling procedures.
Cheers,
Quoted 32 lines
Quoted 11 lines
Quoted 11 lines
}#endif /* ifdef
PLUGIN_PF*/src/openvpn/ssl_verify.c +0
-0@@ -547,14 +547,14 @@ verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, struFILE *peercert_file;const char *peercert_filename ="" ;Quoted 6 lines
src/openvpn/ssl_verify.c verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, stru · line 552
Quoted 4 lines
src/openvpn/ssl_verify.c +3
-1-if (!tmp_dir) +/* create tmp file to store peer cert */ +if (!tmp_dir || + !(peercert_filename =create_temp_file (tmp_dir,"pcf" , gc)))|| at the beginning of the next line (as mentioned in my previous email)
Will do, once we agree on the above discussion points.
Hope this clarifies things.
-Steffan
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Openvpn-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Signature · 1 line
Antonio Quartulli
cover Reject client if PF plugin is configured, but init fails
This changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
--- src/openvpn/pf.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
src/openvpn/pf.c +5 -4
@@ -639,10 +639,11 @@ pf_init_context(struct context *c) } #endif } -else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - } + } +if (!c->c2.pf.enabled) + { +msg (M_WARN ,"WARNING: failed to init PF plugin, rejecting client." ); +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); } }#endif /* ifdef PLUGIN_PF */
Signature · 1 line
2.11.0
Re: [Openvpn-devel] [PATCH 0/2] Reject client if PF plugin is configured, but init fails
Quoted 17 lines · Steffan Karger
This changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
Signed-off-by Steffan Karger <[email protected]...>--- src/openvpn/pf.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)src/openvpn/pf.c +0
-0@@ -639,10 +639,11 @@ pf_init_context(struct context *c) }#endif }
src/openvpn/pf.c pf_init_context(struct context *c) · line 647
Quoted 10 lines
src/openvpn/pf.c +5
-4-else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - } + } +if (!c->c2.pf.enabled) + { +msg (M_WARN ,"WARNING: failed to init PF plugin, rejecting client." ); +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); }
after this part there is some code dealing with the management
interface: wouldn't it be better to have a return after registering the signal so that we don't attempt any interaction with the management interface? If the plugin initialization failed, we should exit right away no?
(although this PF thing with the plugin being optional makes everything more complicated every time :/)
Another thought: if we abort every time we can't initialize the pf context, do you think we need the c->c2.pf.enabled member at all?
It looks to me that after this patch if PF is enabled, either a client is connected and has a PF context, or its connection was rejected entirely. Thus a overall state should be enough rather than a per-client one. (Can probably be adjusted with another patch if you don't feel like doing all this in here?)
Cheers,
Quoted 3 lines
src/openvpn/pf.c +0
-0}#endif /* ifdef PLUGIN_PF */
Signature · 1 line
Antonio Quartulli
Re: [Openvpn-devel] [PATCH 0/2] Reject client if PF plugin is configured, but init fails
Hi,
Quoted 35 lines · Antonio Quartulli
Quoted 17 lines · Steffan Karger
This changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
Signed-off-by Steffan Karger <[email protected]...>--- src/openvpn/pf.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)src/openvpn/pf.c +0
-0@@ -639,10 +639,11 @@ pf_init_context(struct context *c) }#endif }src/openvpn/pf.c pf_init_context(struct context *c) · line 647
Quoted 10 lines
src/openvpn/pf.c +5
-4-else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - } + } +if (!c->c2.pf.enabled) + { +msg (M_WARN ,"WARNING: failed to init PF plugin, rejecting client." ); +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); }after this part there is some code dealing with the management
interface: wouldn't it be better to have a return after registering the signal so that we don't attempt any interaction with the management interface? If the plugin initialization failed, we should exit right away no?
Quoted 2 lines
(although this PF thing with the plugin being optional makes everything more complicated every time :/)
Good point, I'll fix that and send a whole new patch set with all your comments processed. With the expansion from 2 to 4 patches, the thread has become quite a mess.
Quoted 8 lines
Another thought: if we abort every time we can't initialize the pf context, do you think we need the
c->c2.pf.enabledmember at all?It looks to me that after this patch if PF is enabled, either a client is connected and has a PF context, or its connection was rejected entirely. Thus a overall state should be enough rather than a per-client one. (Can probably be adjusted with another patch if you don't feel like doing all this in here?)
The pf.enabled member is used in a number of quick inline checks to determine whether to go into the whole pf code path or not. I think it's best to keep it.
-Steffan
PATCH v2 1/2 Don't throw fatal errors from create_temp_file()
In reply to Antonio QuartulliFrom: Steffan Karger <[email protected]...>
This function is called in response to connecting clients, and can fail when I/O fails for some (possibly temporary) reason. In such cases we should not exit the process, but just reject the connecting client.
This commit changes the function to actually return NULL on errors, and (where needed) changes the callers to check for and handle errors.
Since the tls-crypt-v2 metadata code also calls create_temp_file() when clients connect, I consider this a prerequisite for tls-crypt-v2.
---
v2:
- Move '||' to new line to conform to Knuth-style wrapping
- Re-add explicit warning message when pf plugin init fails
src/openvpn/misc.c | 6 +++--- src/openvpn/ssl_verify.c | 32 +++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 14 deletions(-)
src/openvpn/misc.c +3 -3
@@ -740,7 +740,7 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) retfname =gen_path (directory,BSTR (&fname), gc);if (!retfname) { -msg (M_FATAL ,"Failed to create temporary filename and path" ); +msg (M_WARN ,"Failed to create temporary filename and path" );return NULL ; }
@@ -755,14 +755,14 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)else if (fd ==-1 && errno !=EEXIST ) {/* Something else went wrong, no need to retry. */ -msg (M_FATAL |M_ERRNO ,"Could not create temporary file '%s'" , +msg (M_WARN |M_ERRNO ,"Could not create temporary file '%s'" , retfname);return NULL ; } }while (attempts <6 ); -msg (M_FATAL ,"Failed to create temporary file after %i attempts" , attempts); +msg (M_WARN ,"Failed to create temporary file after %i attempts" , attempts);return NULL ; }
src/openvpn/ssl_verify.c +21 -11
@@ -547,14 +547,14 @@ verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, struFILE *peercert_file;const char *peercert_filename ="" ; -if (!tmp_dir) +/* create tmp file to store peer cert */ +if (!tmp_dir + || !(peercert_filename =create_temp_file (tmp_dir,"pcf" , gc))) { +msg (M_WARN ,"Failed to create peer cert file" );return NULL ; } -/* create tmp file to store peer cert */ - peercert_filename =create_temp_file (tmp_dir,"pcf" , gc); -/* write peer-cert in tmp-file */ peercert_file =fopen (peercert_filename,"w+" );if (!peercert_file)
@@ -589,10 +589,13 @@ verify_cert_call_command(const char *verify_command, struct env_set *es,if (verify_export_cert) { -if ((tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc))) + tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc); +if (!tmp_file) { -setenv_str (es,"peer_cert" , tmp_file); + ret = false; + goto cleanup; } +setenv_str (es,"peer_cert" , tmp_file); }argv_parse_cmd (&argv, verify_command);
@@ -609,6 +612,7 @@ verify_cert_call_command(const char *verify_command, struct env_set *es, } } +cleanup:gc_free (&gc);argv_reset (&argv);
@@ -879,21 +883,21 @@ key_state_rm_auth_control_file(struct key_state *ks) } } -static void +static bool key_state_gen_auth_control_file (struct key_state *ks,const struct tls_options *opt) {struct gc_arena gc =gc_new (); -const char *acf;key_state_rm_auth_control_file (ks); - acf =create_temp_file (opt->tmp_dir,"acf" , &gc); +const char *acf =create_temp_file (opt->tmp_dir,"acf" , &gc);if (acf) { ks->auth_control_file =string_alloc (acf,NULL );setenv_str (opt->es,"auth_control_file" , ks->auth_control_file); - }/* FIXME: Should have better error handling? */ + }gc_free (&gc); +return acf; } static unsigned int
@@ -1184,7 +1188,12 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,#ifdef PLUGIN_DEF_AUTH /* generate filename for deferred auth control file */ -key_state_gen_auth_control_file (ks, session->opt); +if (!key_state_gen_auth_control_file (ks, session->opt)) + { +msg (D_TLS_ERRORS ,"TLS Auth Error (%s): " +"could not create deferred auth control file" , __func__); + goto cleanup; + }#endif /* call command */
@@ -1209,6 +1218,7 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,msg (D_TLS_ERRORS ,"TLS Auth Error (verify_user_pass_plugin): peer provided a blank username" ); } +cleanup:return retval; }
Signature · 1 line
2.11.0
Please stop sending me mails u fools, this is not unsubscribing fed up of this.
Remove my mail I'd for GOD sacks
Quoted 190 lines · Steffan Karger
This function is called in response to connecting clients, and can fail when I/O fails for some (possibly temporary) reason. In such cases we should not exit the process, but just reject the connecting client.
This commit changes the function to actually return NULL on errors, and (where needed) changes the callers to check for and handle errors.
Note that this changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
Since the tls-crypt-v2 metadata code also calls
create_temp_file()when clients connect, I consider this a prerequisite for tls-crypt-v2.Signed-off-by Steffan Karger <[email protected]...>--- src/openvpn/misc.c | 6 +++--- src/openvpn/pf.c | 8 ++++---- src/openvpn/ssl_verify.c | 32 +++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 18 deletions(-)src/openvpn/misc.c +3
-3@@ -740,7 +740,7 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) retfname =gen_path (directory,BSTR (&fname), gc);if (!retfname) { -msg (M_FATAL ,"Failed to create temporary filename and path" ); +msg (M_WARN ,"Failed to create temporary filename and path" );return NULL ; }@@ -755,14 +755,14 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) else if (fd == -1 && errno != EEXIST) {/* Something else went wrong, no need to retry. */ -msg (M_FATAL |M_ERRNO ,"Could not create temporary file '%s'" , +msg (M_WARN |M_ERRNO ,"Could not create temporary file '%s'" , retfname);return NULL ; } }while (attempts <6 ); -msg (M_FATAL ,"Failed to create temporary file after %i attempts" , attempts); +msg (M_WARN ,"Failed to create temporary file after %i attempts" , attempts);return NULL;}
src/openvpn/pf.c +4
-4@@ -639,10 +639,10 @@ pf_init_context(struct context *c) } #endif } -else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - } + } +if (!c->c2.pf.enabled) + { +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); } }#endif /* ifdef PLUGIN_PF */ src/openvpn/ssl_verify.c +4
-4@@ -547,14 +547,14 @@ verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, struFILE *peercert_file;const char *peercert_filename ="" ; -if (!tmp_dir) +/* create tmp file to store peer cert */ +if (!tmp_dir || + !(peercert_filename =create_temp_file (tmp_dir,"pcf" , gc))) { +msg (M_WARN ,"Failed to create peer cert file" );return NULL ; } -/* create tmp file to store peer cert */ - peercert_filename =create_temp_file (tmp_dir,"pcf" , gc); -/* write peer-cert in tmp-file */ peercert_file =fopen (peercert_filename,"w+" );if (!peercert_file)
src/openvpn/ssl_verify.c +5
-2@@ -589,10 +589,13 @@ verify_cert_call_command(const char *verify_command,struct env_set *es, if (verify_export_cert) { -if ((tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc))) + tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc); +if (!tmp_file) { -setenv_str (es,"peer_cert" , tmp_file); + ret = false; + goto cleanup; } +setenv_str (es,"peer_cert" , tmp_file); }argv_parse_cmd(&argv, verify_command);src/openvpn/ssl_verify.c +5
-4@@ -609,6 +612,7 @@ verify_cert_call_command(const char *verify_command, struct env_set *es, } } +cleanup:gc_free (&gc);argv_reset (&argv);@@ -879,21 +883,21 @@ key_state_rm_auth_control_file(struct key_state *ks) } } -static void +static bool key_state_gen_auth_control_file (struct key_state *ks,const struct tls_options *opt) {struct gc_arena gc =gc_new (); -const char *acf;key_state_rm_auth_control_file (ks); - acf =create_temp_file (opt->tmp_dir,"acf" , &gc); +const char *acf =create_temp_file (opt->tmp_dir,"acf" , &gc);if (acf) { ks->auth_control_file =string_alloc (acf,NULL );setenv_str (opt->es,"auth_control_file" , ks->auth_control_file); - }/* FIXME: Should have better error handling? */ + }gc_free (&gc); +return acf; }static unsigned int
src/openvpn/ssl_verify.c +6
-1@@ -1184,7 +1188,12 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,#ifdef PLUGIN_DEF_AUTH /* generate filename for deferred auth control file */ -key_state_gen_auth_control_file (ks, session->opt); +if (!key_state_gen_auth_control_file (ks, session->opt)) + { +msg (D_TLS_ERRORS ,"TLS Auth Error (%s): " +"could not create deferred auth control file" , __func__); + goto cleanup; + }#endif /* call command */src/openvpn/ssl_verify.c +1
-0@@ -1209,6 +1218,7 @@ verify_user_pass_plugin(struct tls_session *session,const struct user_pass *up, msg(D_TLS_ERRORS, "TLS Auth Error (verify_user_pass_plugin): peer provided a blank username"); } +cleanup:return retval;}
--
2.7.4------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Openvpn-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Quoted 26 lines · Steffan Karger
This function is called in response to connecting clients, and can fail when I/O fails for some (possibly temporary) reason. In such cases we should not exit the process, but just reject the connecting client.
This commit changes the function to actually return NULL on errors, and (where needed) changes the callers to check for and handle errors.
Note that this changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
Since the tls-crypt-v2 metadata code also calls
create_temp_file()when clients connect, I consider this a prerequisite for tls-crypt-v2.Signed-off-by Steffan Karger <[email protected]...>--- src/openvpn/misc.c | 6 +++--- src/openvpn/pf.c | 8 ++++---- src/openvpn/ssl_verify.c | 32 +++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 18 deletions(-)src/openvpn/misc.c +0
-0
src/openvpn/misc.c create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) · line 744
Quoted 6 lines
src/openvpn/misc.c +1
-1@@ -740,7 +740,7 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) retfname =gen_path (directory,BSTR (&fname), gc);if (!retfname) { -msg (M_FATAL ,"Failed to create temporary filename and path" ); +msg (M_WARN ,"Failed to create temporary filename and path" );return NULL ;
All these changes to create_temp_file() are good. The use of M_FATAL must have been an oversight when this part was overhauled approx 8 years ago. M_WARN is the proper log tag. And all places calling create_temp_file() have proper checks if this function returns NULL. So this part of the patch gets an ACK.
[...snip...]
Quoted 7 lines
src/openvpn/pf.c +0
-0@@ -639,10 +639,10 @@ pf_init_context(struct context *c) }#endif
src/openvpn/pf.c pf_init_context(struct context *c) · line 646
Quoted 10 lines
src/openvpn/pf.c +4
-4} -else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - } + } +if (!c->c2.pf.enabled) + { +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); }
This change scares me. Unless I overlooked something, pf_init_context() is called on each new connection happens on the server side, through multi_create_instance(). Is it truly safe to call SIGUSR1 on the server process, considering other clients may be connected at the same time? On a client process, this would be fine though.
Just noticed Antonio are thinking along the same paths, so either we're missing some details ... or this is risky.
Signature · 4 lines
kind regards, David Sommerseth OpenVPN Technologies, Inc
PATCH v2 1/1 Don't throw fatal errors from create_temp_file()
In reply to Steffan KargerHi,
The following four patches are a rebased and reordered set of patched that replace the original 2 patches I send in September. These should include fixes for all Antonio's and David's comments (where needed).
-Steffan
PATCH v3 1/4 pf: clean up temporary files if plugin init fails
From: Steffan Karger <[email protected]...>
close_instance() tries to remove the file in c2.pf.filename, but that only works if we actually set that if we fail. So, set that filename as soon as we know we've created the file.
---
v2: As suggested by Antionio, get rid of local 'gc' and 'file' vars.
v3: make c->c2.pf.filename const (fixes compile warning)
src/openvpn/pf.c | 10 ++++------ src/openvpn/pf.h | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-)
src/openvpn/pf.c +4 -6
@@ -618,19 +618,18 @@ pf_load_from_buffer_list(struct context *c, const struct buffer_list *config)void pf_init_context (struct context *c) { -struct gc_arena gc =gc_new ();#ifdef PLUGIN_PF if (plugin_defined (c->plugins,OPENVPN_PLUGIN_ENABLE_PF )) { -const char *pf_file =create_temp_file (c->options.tmp_dir,"pf" , &gc); -if (pf_file) + c->c2.pf.filename =create_temp_file (c->options.tmp_dir,"pf" , + &c->c2.gc); +if (c->c2.pf.filename) { -setenv_str (c->c2.es,"pf_file" , pf_file); +setenv_str (c->c2.es,"pf_file" , c->c2.pf.filename);if (plugin_call (c->plugins,OPENVPN_PLUGIN_ENABLE_PF ,NULL ,NULL , c->c2.es) ==OPENVPN_PLUGIN_FUNC_SUCCESS ) {event_timeout_init (&c->c2.pf.reload,1 , now); - c->c2.pf.filename =string_alloc (pf_file, &c->c2.gc); c->c2.pf.enabled = true;#ifdef ENABLE_DEBUG if (check_debug_level (D_PF_DEBUG ))
@@ -658,7 +657,6 @@ pf_init_context(struct context *c) #endif }#endif -gc_free (&gc); }void
src/openvpn/pf.h +1 -1
@@ -75,7 +75,7 @@ struct pf_context {bool enabled;struct pf_set *pfs;#ifdef PLUGIN_PF -char *filename; +const char *filename;time_t file_last_mod;unsigned int n_check_reload;struct event_timeout reload;
Signature · 1 line
2.14.1
Re: [Openvpn-devel] [PATCH 1/4 v3] pf: clean up temporary files if plugin init fails
Quoted 7 lines · Steffan Karger
From: Steffan Karger <[email protected]...>
close_instance()tries to remove the file in c2.pf.filename, but that only works if we actually set that if we fail. So, set that filename as soon as we know we've created the file.Signed-off-by Steffan Karger <[email protected]...>
Signature · 1 line
Antonio Quartulli
[Openvpn-devel] [PATCH applied] Re: pf: clean up temporary files if plugin init fails
In reply to Steffan KargerI like that :-) - less code, less malloc()ing, less gcs around and more correct at that.
I have also briefly reviewed the rest of the series, and everything looks good - but since Antonio has already ACKed everything, I leave that honour to him.
Your patch has been applied to the master branch.
(This is refactoring, according to branch rules it only goes to 2.4 in exceptionary circumstances, like "another patch depending on it" - but since tls-crypt-v2 is also intended for master only, this is good enough for now)
commit d2342067d95621b130dd3985a077872b032d53d2
Author: Steffan Karger Date: Wed Nov 1 23:03:39 2017 +0100
pf: clean up temporary files if plugin init fails
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Antonio Quartulli <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg15705.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
PATCH v2 2/4 pf: reject client if PF plugin is configured, but init fails
In reply to Steffan KargerThis changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
---
v3: return immediately after registering signal
src/openvpn/pf.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
src/openvpn/pf.c +6 -4
@@ -638,10 +638,12 @@ pf_init_context(struct context *c) } #endif } -else - { -msg (M_WARN ,"WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled" ); - } + } +if (!c->c2.pf.enabled) + { +msg (M_WARN ,"WARNING: failed to init PF plugin, rejecting client." ); +register_signal (c,SIGUSR1 ,"plugin-pf-init-failed" ); +return ; } }#endif /* ifdef PLUGIN_PF */
Signature · 1 line
2.14.1
Re: [Openvpn-devel] [PATCH 2/4 v2] pf: reject client if PF plugin is configured, but init fails
Quoted 5 lines · Steffan Karger
This changes the behavior for pf plugins: instead of just not initializing the firewall rules and happily continuing, this now rejects the client in the case of an (unlikely) failure to initialize the pf.
Signed-off-by Steffan Karger <[email protected]...>
Signature · 1 line
Antonio Quartulli
[Openvpn-devel] [PATCH applied] Re: pf: reject client if PF plugin is configured, but init fails
In reply to Steffan KargerYour patch has been applied to the master branch.
commit 492e42d35f141346fe21b3e984ed1bd86e5aac40
Author: Steffan Karger Date: Wed Nov 1 23:03:40 2017 +0100
pf: reject client if PF plugin is configured, but init fails
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Antonio Quartulli <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg15704.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
PATCH v2 3/4 Don't throw fatal errors from create_temp_file()
In reply to Steffan KargerFrom: Steffan Karger <[email protected]...>
This function is called in response to connecting clients, and can fail when I/O fails for some (possibly temporary) reason. In such cases we should not exit the process, but just reject the connecting client.
This commit changes the function to actually return NULL on errors, and (where needed) changes the callers to check for and handle errors.
Since the tls-crypt-v2 metadata code also calls create_temp_file() when clients connect, I consider this a prerequisite for tls-crypt-v2.
---
v2: put || at the beginning of a line (not the end)
src/openvpn/misc.c | 6 +++--- src/openvpn/ssl_verify.c | 32 +++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 14 deletions(-)
src/openvpn/misc.c +3 -3
@@ -740,7 +740,7 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) retfname =gen_path (directory,BSTR (&fname), gc);if (!retfname) { -msg (M_FATAL ,"Failed to create temporary filename and path" ); +msg (M_WARN ,"Failed to create temporary filename and path" );return NULL ; }
@@ -755,14 +755,14 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)else if (fd ==-1 && errno !=EEXIST ) {/* Something else went wrong, no need to retry. */ -msg (M_FATAL |M_ERRNO ,"Could not create temporary file '%s'" , +msg (M_WARN |M_ERRNO ,"Could not create temporary file '%s'" , retfname);return NULL ; } }while (attempts <6 ); -msg (M_FATAL ,"Failed to create temporary file after %i attempts" , attempts); +msg (M_WARN ,"Failed to create temporary file after %i attempts" , attempts);return NULL ; }
src/openvpn/ssl_verify.c +21 -11
@@ -547,14 +547,14 @@ verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, struFILE *peercert_file;const char *peercert_filename ="" ; -if (!tmp_dir) +/* create tmp file to store peer cert */ +if (!tmp_dir + || !(peercert_filename =create_temp_file (tmp_dir,"pcf" , gc))) { +msg (M_WARN ,"Failed to create peer cert file" );return NULL ; } -/* create tmp file to store peer cert */ - peercert_filename =create_temp_file (tmp_dir,"pcf" , gc); -/* write peer-cert in tmp-file */ peercert_file =fopen (peercert_filename,"w+" );if (!peercert_file)
@@ -589,10 +589,13 @@ verify_cert_call_command(const char *verify_command, struct env_set *es,if (verify_export_cert) { -if ((tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc))) + tmp_file =verify_cert_export_cert (cert, verify_export_cert, &gc); +if (!tmp_file) { -setenv_str (es,"peer_cert" , tmp_file); + ret = false; + goto cleanup; } +setenv_str (es,"peer_cert" , tmp_file); }argv_parse_cmd (&argv, verify_command);
@@ -609,6 +612,7 @@ verify_cert_call_command(const char *verify_command, struct env_set *es, } } +cleanup:gc_free (&gc);argv_reset (&argv);
@@ -879,21 +883,21 @@ key_state_rm_auth_control_file(struct key_state *ks) } } -static void +static bool key_state_gen_auth_control_file (struct key_state *ks,const struct tls_options *opt) {struct gc_arena gc =gc_new (); -const char *acf;key_state_rm_auth_control_file (ks); - acf =create_temp_file (opt->tmp_dir,"acf" , &gc); +const char *acf =create_temp_file (opt->tmp_dir,"acf" , &gc);if (acf) { ks->auth_control_file =string_alloc (acf,NULL );setenv_str (opt->es,"auth_control_file" , ks->auth_control_file); - }/* FIXME: Should have better error handling? */ + }gc_free (&gc); +return acf; } static unsigned int
@@ -1184,7 +1188,12 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,#ifdef PLUGIN_DEF_AUTH /* generate filename for deferred auth control file */ -key_state_gen_auth_control_file (ks, session->opt); +if (!key_state_gen_auth_control_file (ks, session->opt)) + { +msg (D_TLS_ERRORS ,"TLS Auth Error (%s): " +"could not create deferred auth control file" , __func__); + goto cleanup; + }#endif /* call command */
@@ -1209,6 +1218,7 @@ verify_user_pass_plugin(struct tls_session *session, const struct user_pass *up,msg (D_TLS_ERRORS ,"TLS Auth Error (verify_user_pass_plugin): peer provided a blank username" ); } +cleanup:return retval; }
Signature · 1 line
2.14.1
Quoted 6 lines · Steffan Karger
From: Steffan Karger <[email protected]...>
This function is called in response to connecting clients, and can fail when I/O fails for some (possibly temporary) reason. In such cases we should not exit the process, but just reject the connecting client.
Quoted 7 lines
This commit changes the function to actually return NULL on errors, and (where needed) changes the callers to check for and handle errors.
Since the tls-crypt-v2 metadata code also calls
create_temp_file()when clients connect, I consider this a prerequisite for tls-crypt-v2.Signed-off-by Steffan Karger <[email protected]...>
Signature · 1 line
Antonio Quartulli
Your patch has been applied to the master branch.
commit 3e0fd2b0471cf4e53959902ca10d88db7a1ef916
Author: Steffan Karger Date: Wed Nov 1 23:03:41 2017 +0100
Don't throw fatal errors from create_temp_file()
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Antonio Quartulli <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg15701.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
Hi,
Steffan asked me to pull this into 2.4, which makes sense - it's somewhere between "code cleanup" and "bugfix", basically avoiding an ASSERT() when we could more gracefully handle a failure on an incoming client (... in a somewhat unlikely chain of events, but still, ASSERT() on the server side for recoverable things is bad).
commit 77a0bdb77d4c5573fcb78f1e36c45d882a9923ba (HEAD -> release/2.4)
Author: Steffan Karger <[email protected]...> Date: Wed Nov 1 23:03:41 2017 +0100
Don't throw fatal errors from create_temp_file()
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Antonio Quartulli <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg15701.html
Signed-off-by: Gert Doering <[email protected]...>
(cherry picked from commit 3e0fd2b0471cf4e53959902ca10d88db7a1ef916)gert
Quoted 29 lines · Gert Doering
Your patch has been applied to the master branch.
commit
3e0fd2b0471cf4e53959902ca10d88db7a1ef916Author: Steffan Karger Date: Wed Nov 1 23:03:41 2017 +0100Don't throw fatal errors from create_temp_file() Signed-off-by: Steffan Karger <[email protected]...> Acked-by: Antonio Quartulli <[email protected]...> Message-Id: <[email protected]...> URL: https://www.mail-archive.com/[email protected]/msg15701.html Signed-off-by: Gert Doering <[email protected]...>--
kind regards,Gert Doering
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Openvpn-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Signature · 3 lines
now what should I write here... Gert Doering - Munich, Germany [email protected]...
PATCH v3 4/4 create_temp_file/gen_path: prevent memory leak if gc == NULL
In reply to Steffan KargerIf gc == NULL, the data allocated in the alloc_gc_buf() call in create_temp_file or the string_mod_const call in gen_path would never be free'd.
These functions are currently never called that way, but let's prevent future problems.
While touching create_temp_file, also remove the counter variable, which is never read, simplify the do-while to a while loop, and truncate the prefix (if needed) to preserve the random and extension of the created filename.
---
v2:
- change create_temp_file to avoid using a struct buffer (simpler)
- add gc != NULL check for gen_path (avoid similar memleak pitfall)
v3:
- Check the return value of openvpn_snprintf()
src/openvpn/misc.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-)
src/openvpn/misc.c +18 -8
@@ -723,21 +723,26 @@ test_file(const char *filename)const char *create_temp_file (const char *directory,const char *prefix,struct gc_arena *gc) { -static unsigned int counter; -struct buffer fname =alloc_buf_gc (256 , gc);int fd;const char *retfname =NULL ;unsigned int attempts =0 ; +char fname[256 ] = {0 }; +const char *fname_fmt =PACKAGE "_%.*s_%08lx%08lx.tmp" ; +const int max_prefix_len =sizeof (fname) - (sizeof (PACKAGE ) +7 + (2 *8 )); - do +while (attempts <6 ) { ++attempts; - ++counter; - buf_printf(&fname, PACKAGE "_%s_%08lx%08lx.tmp", prefix, - (unsigned long) get_random(), (unsigned long) get_random()); +if (!openvpn_snprintf (fname,sizeof (fname), fname_fmt, max_prefix_len, + prefix, (unsigned long )get_random (), + (unsigned long )get_random ())) + { +msg (M_WARN ,"ERROR: temporary filename too long" ); +return NULL ; + } - retfname = gen_path(directory, BSTR(&fname), gc); + retfname =gen_path (directory, fname, gc);if (!retfname) {msg (M_WARN ,"Failed to create temporary filename and path" );
@@ -760,7 +765,6 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)return NULL ; } } -while (attempts <6 );msg (M_WARN ,"Failed to create temporary file after %i attempts" , attempts);return NULL ;
@@ -812,6 +816,12 @@ gen_path(const char *directory, const char *filename, struct gc_arena *gc)#else const int CC_PATH_RESERVED =CC_SLASH ;#endif + +if (!gc) + { +return NULL ;/* Would leak memory otherwise */ + } +const char *safe_filename =string_mod_const (filename,CC_PRINT ,CC_PATH_RESERVED ,'_' , gc); if (safe_filename
Signature · 1 line
2.14.1
Re: [Openvpn-devel] [PATCH 4/4 v3] create_temp_file/gen_path: prevent memory leak if gc == NULL
Hi Steffan,
patch looks good, but I have just one comment below
Quoted 69 lines · Steffan Karger
If gc == NULL, the data allocated in the
alloc_gc_buf()call increate_temp_fileor thestring_mod_constcall ingen_pathwould never be free'd.These functions are currently never called that way, but let's prevent future problems.
While touching
create_temp_file, also remove the counter variable, which is never read, simplify the do-while to a while loop, and truncate the prefix (if needed) to preserve the random and extension of the created filename.Signed-off-by Steffan Karger <[email protected]...>---
v2:
- changecreate_temp_fileto avoid using a struct buffer (simpler)
- add gc != NULL check forgen_path(avoid similar memleak pitfall)
v3:
- Check the return value ofopenvpn_snprintf()src/openvpn/misc.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-)src/openvpn/misc.c +12
-8@@ -723,21 +723,26 @@ test_file(const char *filename)const char *create_temp_file (const char *directory,const char *prefix,struct gc_arena *gc) { -static unsigned int counter; -struct buffer fname =alloc_buf_gc (256 , gc);int fd;const char *retfname =NULL ;unsigned int attempts =0 ; +char fname[256 ] = {0 }; +const char *fname_fmt =PACKAGE "_%.*s_%08lx%08lx.tmp" ; +const int max_prefix_len =sizeof (fname) - (sizeof (PACKAGE ) +7 + (2 *8 )); - do +while (attempts <6 ) { ++attempts; - ++counter; - buf_printf(&fname, PACKAGE "_%s_%08lx%08lx.tmp", prefix, - (unsigned long) get_random(), (unsigned long) get_random()); +if (!openvpn_snprintf (fname,sizeof (fname), fname_fmt, max_prefix_len, + prefix, (unsigned long )get_random (), + (unsigned long )get_random ())) + { +msg (M_WARN ,"ERROR: temporary filename too long" ); +return NULL ; + } - retfname = gen_path(directory, BSTR(&fname), gc); + retfname =gen_path (directory, fname, gc);if (!retfname) {msg (M_WARN ,"Failed to create temporary filename and path" );@@ -760,7 +765,6 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)return NULL ; } } -while (attempts <6 );msg (M_WARN ,"Failed to create temporary file after %i attempts" , attempts);return NULL ;
src/openvpn/misc.c gen_path(const char *directory, const char *filename, struct gc_arena *gc) · line 822
Quoted 7 lines
src/openvpn/misc.c +4
-0@@ -812,6 +816,12 @@ gen_path(const char *directory, const char *filename, struct gc_arena *gc)#else const int CC_PATH_RESERVED =CC_SLASH ;#endif + +if (!gc) + { +return NULL ;/* Would leak memory otherwise */
As far as I understood the ratio behind this change, we are basically saying that passing gc == NULL is a real programming error and not a runtime problem. If so, wouldn't it be better to assert(gc) directly? I am saying so because we should make this failure louder, so that it can be recognized in an early test.
Or can we have cases when this function is called with NULL because of a temporary failure (my understanding is that this should not be possible)?
Cheers,
Quoted 6 lines
src/openvpn/misc.c +2
-0+ } +const char *safe_filename =string_mod_const (filename,CC_PRINT ,CC_PATH_RESERVED ,'_' , gc); if (safe_filename
Signature · 1 line
Antonio Quartulli
Re: [Openvpn-devel] [PATCH 4/4 v3] create_temp_file/gen_path: prevent memory leak if gc == NULL
Hi,
Quoted 15 lines · Antonio Quartulli
src/openvpn/misc.c gen_path(const char *directory, const char *filename, struct gc_arena *gc) · line 822
Quoted 8 lines
src/openvpn/misc.c +4
-0@@ -812,6 +816,12 @@ gen_path(const char *directory, const char *filename, struct gc_arena *gc)#else const int CC_PATH_RESERVED =CC_SLASH ;#endif + +if (!gc) + { +return NULL ;/* Would leak memory otherwise */ As far as I understood the ratio behind this change, we are basically saying that passing gc == NULL is a real programming error and not a runtime problem. If so, wouldn't it be better to assert(gc) directly? I am saying so because we should make this failure louder, so that it can be recognized in an early test.
Quoted 2 lines
Or can we have cases when this function is called with NULL because of a temporary failure (my understanding is that this should not be possible)?
I'm a bit in doubt here - if this parameter is NULL, that's a programming error. But we've seen before that programming errors sometimes can be triggered by external input. In this case, this function can be called when a client connects. It *should* never hit this case, but if it somehow does, that becomes a DoS vuln. So I think I prefer 'graceful error handling' in paths that are exposed like this, unless the error indicates a system integrity error such as an out-of-bounds read or write.
-Steffan
Antonio Quartulli
Acked-byRe: [Openvpn-devel] [PATCH 4/4 v3] create_temp_file/gen_path: prevent memory leak if gc == NULL
Quoted 21 lines · Steffan Karger
Hi,
Quoted 15 lines · Antonio Quartulli
src/openvpn/misc.c gen_path(const char *directory, const char *filename, struct gc_arena *gc) · line 822
Quoted 8 lines
src/openvpn/misc.c +4
-0@@ -812,6 +816,12 @@ gen_path(const char *directory, const char *filename, struct gc_arena *gc)#else const int CC_PATH_RESERVED =CC_SLASH ;#endif + +if (!gc) + { +return NULL ;/* Would leak memory otherwise */ As far as I understood the ratio behind this change, we are basically saying that passing gc == NULL is a real programming error and not a runtime problem. If so, wouldn't it be better to assert(gc) directly? I am saying so because we should make this failure louder, so that it can be recognized in an early test.
Quoted 2 lines
Or can we have cases when this function is called with NULL because of a temporary failure (my understanding is that this should not be possible)?
Quoted 8 lines
I'm a bit in doubt here - if this parameter is NULL, that's a programming error. But we've seen before that programming errors sometimes can be triggered by external input. In this case, this function can be called when a client connects. It *should* never hit this case, but if it somehow does, that becomes a DoS vuln. So I think I prefer 'graceful error handling' in paths that are exposed like this, unless the error indicates a system integrity error such as an out-of-bounds read or write.
Yeah, makes sense. I was also worried about the DoS, that's why I was trying to convince myself that passing NULL was not possible at all. But I like your defensive approach more.
Signature · 1 line
Antonio Quartulli
[Openvpn-devel] [PATCH applied] Re: create_temp_file/gen_path: prevent memory leak if gc == NULL
In reply to Steffan KargerYour patch has been applied to the master branch.
commit bd89ebd6a82856c7939b4ade35d14d0178a96986
Author: Steffan Karger Date: Wed Nov 1 23:03:42 2017 +0100
create_temp_file/gen_path: prevent memory leak if gc == NULL
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Antonio Quartulli <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg15703.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering