From 709ed1ab7417596a049173ebe2380f7326c2d560 Mon Sep 17 00:00:00 2001 From: David Sommerseth Date: Fri, 2 Oct 2009 22:52:38 +0200 Subject: Modified get_env() function to limit number of bytes to extract This is to enhance the security and to avoid possible buffer overflows based on input received from the client --- plugin/eurephia-auth.c | 8 +- plugin/eurephia.c | 197 +++++++++++++++++++++++++++++++++++-------------- plugin/eurephia.h | 7 +- 3 files changed, 152 insertions(+), 60 deletions(-) (limited to 'plugin') diff --git a/plugin/eurephia-auth.c b/plugin/eurephia-auth.c index 10d9447..14ef79b 100644 --- a/plugin/eurephia-auth.c +++ b/plugin/eurephia-auth.c @@ -39,7 +39,7 @@ #include #include #include - +#include #ifdef ENABLE_DEBUG /* To avoid compiler warnings when ENABLE_DEBUG is not defined */ @@ -110,9 +110,9 @@ static void dump_env(FILE *f, const char *prefix, const char *envp[]) { */ static void daemonize(const char *envp[]) { - const char *daemon_string = get_env(NULL, 0, envp, "daemon"); + char *daemon_string = get_env(NULL, 0, 32, envp, "daemon"); if( daemon_string && daemon_string[0] == '1' ) { - const char *log_redirect = get_env(NULL, 0, envp, "daemon_log_redirect"); + char *log_redirect = get_env(NULL, 0, 32, envp, "daemon_log_redirect"); int fd = -1; if( log_redirect && log_redirect[0] == '1' ) { fd = dup (2); @@ -123,7 +123,9 @@ static void daemonize(const char *envp[]) dup2(fd, 2); close(fd); } + free_nullsafe(NULL, log_redirect); } + free_nullsafe(NULL, daemon_string); } diff --git a/plugin/eurephia.c b/plugin/eurephia.c index db7607f..b571a59 100644 --- a/plugin/eurephia.c +++ b/plugin/eurephia.c @@ -38,12 +38,11 @@ #define EUREPHIA_FWINTF /**< Include the proper eurephiaFWINTF declaration in eurephiaCTX */ #include -#include #include +#include #include #include #include -#include #include #include #include @@ -59,12 +58,14 @@ * * @param ctx eurephiaCTX context * @param logmasking If 1, the value will be masked in the log files (eg. to hide password) + * @param len How many bytes to copy out of the environment variable * @param envp the environment table * @param fmt The key to look for (stdarg) * * @return Returns a const char * with the value, or NULL if not found */ -const char *get_env(eurephiaCTX *ctx, int logmasking, const char *envp[], const char *fmt, ... ) +char *get_env(eurephiaCTX *ctx, int logmasking, size_t len, + const char *envp[], const char *fmt, ... ) { if (envp) { va_list ap; @@ -82,6 +83,7 @@ const char *get_env(eurephiaCTX *ctx, int logmasking, const char *envp[], const for (i = 0; envp[i]; ++i) { if (!strncmp (envp[i], key, keylen)) { const char *cp = envp[i] + keylen; + char *ret = NULL; if (*cp == '=') { #ifdef ENABLE_DEBUG int do_mask = 0; @@ -93,8 +95,9 @@ const char *get_env(eurephiaCTX *ctx, int logmasking, const char *envp[], const key, (do_mask == 0 ? cp + 1 : "xxxxxxxxxxxxxx")); } #endif - - return cp + 1; + ret = malloc_nullsafe(ctx, len+2); + strncpy(ret, cp+1, len); + return ret; } } } @@ -217,7 +220,8 @@ eurephiaCTX *eurephiaInit(const char **argv) assert( ctx->server_salt != NULL ); if( !eurephia_randstring(ctx, ctx->server_salt, SIZE_PWDCACHE_SALT) ) { - eurephia_log(ctx, LOG_PANIC, 0 , "Could not get enough random data for password cache."); + eurephia_log(ctx, LOG_PANIC, 0 , + "Could not get enough random data for password cache."); free_nullsafe(ctx, ctx->server_salt); eDBdisconnect(ctx); @@ -302,7 +306,7 @@ int eurephia_tlsverify(eurephiaCTX *ctx, const char **env, const char *depth) DEBUG(ctx, 10, "** Function call: eurephia_tlsverify(...)"); // Check if IP address is blacklisted - ipaddr = (char *) get_env(ctx, 0, env, "untrusted_ip"); + ipaddr = (char *) get_env(ctx, 0, 34, env, "untrusted_ip"); if( eDBblacklist_check(ctx, attempt_IPADDR, ipaddr) == 1 ) { eDBregister_attempt(ctx, attempt_IPADDR, ATTEMPT_REGISTER, ipaddr); @@ -310,19 +314,22 @@ int eurephia_tlsverify(eurephiaCTX *ctx, const char **env, const char *depth) if( (ctx->fwcfg != NULL) && (ctx->fwcfg->fwblacklist != NULL ) ) { eFW_UpdateFirewall(ctx, FWRULE_BLACKLIST, ipaddr, ctx->fwcfg->fwblacklist, NULL); } + free_nullsafe(ctx, ipaddr); return 0; } // Check if certificate digest is blacklisted - tls_digest = (char *) get_env(ctx, 0, env, "tls_digest_%s", depth); + tls_digest = (char *) get_env(ctx, 0, 60, env, "tls_digest_%s", depth); if( eDBblacklist_check(ctx, attempt_CERTIFICATE, tls_digest) == 1 ) { eDBregister_attempt(ctx, attempt_IPADDR, ATTEMPT_REGISTER, ipaddr); eDBregister_attempt(ctx, attempt_CERTIFICATE, ATTEMPT_REGISTER, tls_digest); + free_nullsafe(ctx, tls_digest); + free_nullsafe(ctx, ipaddr); return 0; } // Check if certificate is registered and allowed - tls_id = (char *) get_env(ctx, 0, env, "tls_id_%s", depth); + tls_id = (char *) get_env(ctx, 0, 2048, env, "tls_id_%s", depth); ci = parse_tlsid(tls_id); result = eDBauth_TLS(ctx, ci->org, ci->common_name, ci->email, tls_digest, depth); if( result < 1 ) { @@ -340,6 +347,9 @@ int eurephia_tlsverify(eurephiaCTX *ctx, const char **env, const char *depth) "Unknown certificate for: %s/%s/%s (depth %s, digest: %s)", ci->org, ci->common_name, ci->email, depth, tls_digest); } + free_nullsafe(ctx, tls_id); + free_nullsafe(ctx, tls_digest); + free_nullsafe(ctx, ipaddr); free_certinfo(ci); DEBUG(ctx, 10, "** Function result: eurephia_tlsverify(...) == %i", result > 0); @@ -359,8 +369,8 @@ int eurephia_userauth(eurephiaCTX *ctx, const char **env) { eurephiaSESSION *authsess = NULL; int result = 0, certid = 0; - const char *cname, *remport, *ipaddr = NULL; - const char *tls_digest = NULL, *tls_id = NULL, *username = NULL; + char *cname, *remport, *ipaddr = NULL; + char *tls_digest = NULL, *tls_id = NULL, *username = NULL; char *passwd = NULL, *pwdcache = NULL, *chkpwd = NULL; certinfo *ci = NULL; @@ -368,7 +378,7 @@ int eurephia_userauth(eurephiaCTX *ctx, const char **env) // Check if IP address is blacklisted - ipaddr = (char *) get_env(ctx, 0, env, "untrusted_ip"); + ipaddr = (char *) get_env(ctx, 0, 34, env, "untrusted_ip"); if( eDBblacklist_check(ctx, attempt_IPADDR, ipaddr) == 1 ) { eDBregister_attempt(ctx, attempt_IPADDR, ATTEMPT_REGISTER, ipaddr); @@ -376,44 +386,59 @@ int eurephia_userauth(eurephiaCTX *ctx, const char **env) if( (ctx->fwcfg != NULL) && (ctx->fwcfg->fwblacklist != NULL ) ) { eFW_UpdateFirewall(ctx, FWRULE_BLACKLIST, ipaddr, ctx->fwcfg->fwblacklist, NULL); } + free_nullsafe(ctx, ipaddr); + return 0; } // Check if certificate digest is blacklisted - tls_digest = (char *) get_env(ctx, 0, env, "tls_digest_0"); + tls_digest = (char *) get_env(ctx, 0, 60, env, "tls_digest_0"); if( eDBblacklist_check(ctx, attempt_CERTIFICATE, tls_digest) == 1 ) { eDBregister_attempt(ctx, attempt_IPADDR, ATTEMPT_REGISTER, ipaddr); eDBregister_attempt(ctx, attempt_CERTIFICATE, ATTEMPT_REGISTER, tls_digest); + free_nullsafe(ctx, ipaddr); + free_nullsafe(ctx, tls_digest); return 0; } // Check if username is blacklisted - username = (char *) get_env(ctx, 0, env, "username"); + username = (char *) get_env(ctx, 0, 34, env, "username"); if( eDBblacklist_check(ctx, attempt_USERNAME, username) == 1 ) { eDBregister_attempt(ctx, attempt_IPADDR, ATTEMPT_REGISTER, ipaddr); eDBregister_attempt(ctx, attempt_CERTIFICATE, ATTEMPT_REGISTER, tls_digest); eDBregister_attempt(ctx, attempt_USERNAME, ATTEMPT_REGISTER, username); + free_nullsafe(ctx, username); + free_nullsafe(ctx, ipaddr); + free_nullsafe(ctx, tls_digest); return 0; } // Get certificate ID - tls_id = (char *) get_env(ctx, 0, env, "tls_id_0"); + tls_id = (char *) get_env(ctx, 0, 2048, env, "tls_id_0"); ci = parse_tlsid(tls_id); certid = eDBauth_TLS(ctx, ci->org, ci->common_name, ci->email, tls_digest, "0"); if( certid < 1 ) { eDBregister_attempt(ctx, attempt_IPADDR, ATTEMPT_REGISTER, ipaddr); eDBregister_attempt(ctx, attempt_CERTIFICATE, ATTEMPT_REGISTER, tls_digest); eDBregister_attempt(ctx, attempt_USERNAME, ATTEMPT_REGISTER, username); + free_nullsafe(ctx, tls_id); + free_nullsafe(ctx, username); + free_nullsafe(ctx, ipaddr); + free_nullsafe(ctx, tls_digest); free_certinfo(ci); return 0; } free_certinfo(ci); // Do username/password/certificate authentication - passwd = (char *)get_env(ctx, 1, env, "password"); + passwd = (char *)get_env(ctx, 1, 64, env, "password"); if( (passwd == NULL) || (strlen_nullsafe(passwd) == 0) ) { eurephia_log(ctx, LOG_WARNING, 0, "eurephia-auth: No password received. Action aborted"); - free_certinfo(ci); + free_nullsafe(ctx, passwd); + free_nullsafe(ctx, tls_id); + free_nullsafe(ctx, username); + free_nullsafe(ctx, ipaddr); + free_nullsafe(ctx, tls_digest); return 0; } @@ -422,11 +447,12 @@ int eurephia_userauth(eurephiaCTX *ctx, const char **env) // Get an authentication session, which is not a real session ticket // but it uses almost the same system - cname = get_env(ctx, 0, env, "common_name"); - remport = get_env(ctx, 0, env, "untrusted_port"); + cname = get_env(ctx, 0, 64, env, "common_name"); + remport = get_env(ctx, 0, 6, env, "untrusted_port"); // an authentication session do not use assigned VPN address - authsess = eDBopen_session_seed(ctx, tls_digest, cname, username, NULL, NULL, ipaddr, remport); + authsess = eDBopen_session_seed(ctx, tls_digest, cname, username, NULL, NULL, + ipaddr, remport); if( authsess == NULL ) { // No session found goto chk_pwd; @@ -436,7 +462,9 @@ int eurephia_userauth(eurephiaCTX *ctx, const char **env) if( (pwdcache != NULL) && (chkpwd != NULL) && (strcmp(pwdcache, chkpwd) == 0) ) { // if cached password matches users password, we're done - eurephia_log(ctx, LOG_INFO, 3, "Authenticated user '%s' against password cache", username); + eurephia_log(ctx, LOG_INFO, 3, "Authenticated user '%s' against password cache", + username); + eDBfree_session(ctx, authsess); result = 1; goto exit; } @@ -457,14 +485,22 @@ int eurephia_userauth(eurephiaCTX *ctx, const char **env) eDBregister_attempt(ctx, attempt_USERNAME, ATTEMPT_RESET, username); if( !eDBset_session_value(ctx, authsess, "pwdcache", chkpwd) ) { - eurephia_log(ctx, LOG_WARNING, 0, "Failed to cache password for user '%s'", username); + eurephia_log(ctx, LOG_WARNING, 0, + "Failed to cache password for user '%s'", username); } eurephia_log(ctx, LOG_INFO, 0, "User '%s' authenticated", username); } exit: - free_nullsafe(ctx, chkpwd); eDBfree_session(ctx, authsess); + free_nullsafe(ctx, remport); + free_nullsafe(ctx, cname); + free_nullsafe(ctx, passwd); + free_nullsafe(ctx, tls_id); + free_nullsafe(ctx, username); + free_nullsafe(ctx, ipaddr); + free_nullsafe(ctx, tls_digest); + free_nullsafe(ctx, chkpwd); DEBUG(ctx, 10, "** Function result: eurephia_userauth(...) = %i", (result>0)); return (result > 0); } @@ -481,26 +517,37 @@ int eurephia_userauth(eurephiaCTX *ctx, const char **env) */ int eurephia_connect(eurephiaCTX *ctx, const char **env) { eurephiaSESSION *session = NULL; - const char *digest, *cname, *uname, *vpnipaddr, *vpnipmask, *remipaddr, *remport, *proto, *tlsid; + char *digest, *cname, *uname, *vpnipaddr, *vpnipmask, *remipaddr, *remport, + *proto, *tlsid; int certid = 0, uid = 0, ret = 0; certinfo *ci = NULL; DEBUG(ctx, 10, "** Function call: eurephia_connect(...)"); // Fetch needed info - digest = get_env(ctx, 0, env, "tls_digest_0"); - tlsid = get_env(ctx, 0, env, "tls_id_0"); - cname = get_env(ctx, 0, env, "common_name"); - uname = get_env(ctx, 0, env, "username"); - vpnipaddr = get_env(ctx, 0, env, "ifconfig_pool_remote_ip"); - vpnipmask = get_env(ctx, 0, env, "ifconfig_pool_netmask"); - remipaddr = get_env(ctx, 0, env, "trusted_ip"); - remport = get_env(ctx, 0, env, "trusted_port"); - proto = get_env(ctx, 0, env, "proto_1"); + digest = get_env(ctx, 0, 60, env, "tls_digest_0"); + tlsid = get_env(ctx, 0, 2048, env, "tls_id_0"); + cname = get_env(ctx, 0, 64, env, "common_name"); + uname = get_env(ctx, 0, 34, env, "username"); + vpnipaddr = get_env(ctx, 0, 34, env, "ifconfig_pool_remote_ip"); + vpnipmask = get_env(ctx, 0, 34, env, "ifconfig_pool_netmask"); + remipaddr = get_env(ctx, 0, 34, env, "trusted_ip"); + remport = get_env(ctx, 0, 6, env, "trusted_port"); + proto = get_env(ctx, 0, 4, env, "proto_1"); // Get a session ticket - session = eDBopen_session_seed(ctx, digest, cname, uname, vpnipaddr, vpnipmask, remipaddr, remport); + session = eDBopen_session_seed(ctx, digest, cname, uname, vpnipaddr, vpnipmask, + remipaddr, remport); if( session == NULL ) { + free_nullsafe(ctx, proto); + free_nullsafe(ctx, remport); + free_nullsafe(ctx, remipaddr); + free_nullsafe(ctx, vpnipaddr); + free_nullsafe(ctx, vpnipmask); + free_nullsafe(ctx, uname); + free_nullsafe(ctx, cname); + free_nullsafe(ctx, tlsid); + free_nullsafe(ctx, digest); return 0; } @@ -520,6 +567,16 @@ int eurephia_connect(eurephiaCTX *ctx, const char **env) { eDBfree_session(ctx, session); eurephia_log(ctx, LOG_INFO, 1, "User '%s' logged in", uname); + free_nullsafe(ctx, proto); + free_nullsafe(ctx, remport); + free_nullsafe(ctx, remipaddr); + free_nullsafe(ctx, vpnipaddr); + free_nullsafe(ctx, vpnipmask); + free_nullsafe(ctx, uname); + free_nullsafe(ctx, cname); + free_nullsafe(ctx, tlsid); + free_nullsafe(ctx, digest); + DEBUG(ctx, 10, "** Function result: eurephia_connect(...) = %i", ret); return ret; } @@ -534,27 +591,38 @@ int eurephia_connect(eurephiaCTX *ctx, const char **env) { */ int eurephia_disconnect(eurephiaCTX *ctx, const char **env) { eurephiaSESSION *session = NULL; - const char *digest, *cname, *uname, *vpnipaddr, *vpnipmask, *remipaddr, *remport; - const char *bytes_sent, *bytes_rec, *duration; + char *digest, *cname, *uname, *vpnipaddr, *vpnipmask, *remipaddr, *remport; + char *bytes_sent, *bytes_rec, *duration; int ret = 0; DEBUG(ctx, 10, "** Function call: eurephia_disconnect(...)"); // Fetch needed info - digest = get_env(ctx, 0, env, "tls_digest_0"); - cname = get_env(ctx, 0, env, "common_name"); - uname = get_env(ctx, 0, env, "username"); - vpnipaddr = get_env(ctx, 0, env, "ifconfig_pool_remote_ip"); - vpnipmask = get_env(ctx, 0, env, "ifconfig_pool_netmask"); - remipaddr = get_env(ctx, 0, env, "trusted_ip"); - remport = get_env(ctx, 0, env, "trusted_port"); - bytes_sent= get_env(ctx, 0, env, "bytes_sent"); - bytes_rec = get_env(ctx, 0, env, "bytes_received"); - duration = get_env(ctx, 0, env, "time_duration"); + digest = get_env(ctx, 0, 60, env, "tls_digest_0"); + cname = get_env(ctx, 0, 64, env, "common_name"); + uname = get_env(ctx, 0, 34, env, "username"); + vpnipaddr = get_env(ctx, 0, 34, env, "ifconfig_pool_remote_ip"); + vpnipmask = get_env(ctx, 0, 34, env, "ifconfig_pool_netmask"); + remipaddr = get_env(ctx, 0, 34, env, "trusted_ip"); + remport = get_env(ctx, 0, 6, env, "trusted_port"); + bytes_sent= get_env(ctx, 0, 21, env, "bytes_sent"); + bytes_rec = get_env(ctx, 0, 21, env, "bytes_received"); + duration = get_env(ctx, 0, 21, env, "time_duration"); // Get a session ticket - session = eDBopen_session_seed(ctx, digest, cname, uname, vpnipaddr, vpnipmask, remipaddr, remport); + session = eDBopen_session_seed(ctx, digest, cname, uname, vpnipaddr, vpnipmask, + remipaddr, remport); if( session == NULL ) { + free_nullsafe(ctx, duration); + free_nullsafe(ctx, bytes_rec); + free_nullsafe(ctx, bytes_sent); + free_nullsafe(ctx, remport); + free_nullsafe(ctx, remipaddr); + free_nullsafe(ctx, vpnipaddr); + free_nullsafe(ctx, vpnipmask); + free_nullsafe(ctx, uname); + free_nullsafe(ctx, cname); + free_nullsafe(ctx, digest); return 0; } @@ -569,6 +637,16 @@ int eurephia_disconnect(eurephiaCTX *ctx, const char **env) { uname, cname, digest); } eDBfree_session(ctx, session); + free_nullsafe(ctx, duration); + free_nullsafe(ctx, bytes_rec); + free_nullsafe(ctx, bytes_sent); + free_nullsafe(ctx, remport); + free_nullsafe(ctx, remipaddr); + free_nullsafe(ctx, vpnipaddr); + free_nullsafe(ctx, vpnipmask); + free_nullsafe(ctx, uname); + free_nullsafe(ctx, cname); + free_nullsafe(ctx, digest); DEBUG(ctx, 10, "** Function result: eurephia_disconnect(...) = %i", ret); return ret; @@ -589,7 +667,9 @@ int eurephia_disconnect(eurephiaCTX *ctx, const char **env) { */ int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *macaddr, const char **env) { eurephiaSESSION *session = NULL; - const char *digest, *cname, *uname, *vpnipaddr, *vpnipmask, *remipaddr, *remport; + char *digest = NULL, *cname = NULL, *uname = NULL, + *vpnipaddr = NULL, *vpnipmask = NULL, + *remipaddr = NULL, *remport = NULL; char *fwprofile = NULL, *fwdest = NULL; int ret = 0, fw_enabled = 0; @@ -605,13 +685,13 @@ int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *macad if( strncmp(mode, "add", 3) == 0 ) { // Fetch needed info - digest = get_env(ctx, 0, env, "tls_digest_0"); - cname = get_env(ctx, 0, env, "common_name"); - uname = get_env(ctx, 0, env, "username"); - vpnipaddr = get_env(ctx, 0, env, "ifconfig_pool_remote_ip"); - vpnipmask = get_env(ctx, 0, env, "ifconfig_pool_netmask"); - remipaddr = get_env(ctx, 0, env, "trusted_ip"); - remport = get_env(ctx, 0, env, "trusted_port"); + digest = get_env(ctx, 0, 60, env, "tls_digest_0"); + cname = get_env(ctx, 0, 64, env, "common_name"); + uname = get_env(ctx, 0, 34, env, "username"); + vpnipaddr = get_env(ctx, 0, 34, env, "ifconfig_pool_remote_ip"); + vpnipmask = get_env(ctx, 0, 34, env, "ifconfig_pool_netmask"); + remipaddr = get_env(ctx, 0, 34, env, "trusted_ip"); + remport = get_env(ctx, 0, 6, env, "trusted_port"); // Get a session ticket session = eDBopen_session_seed(ctx, digest, cname, uname, vpnipaddr, vpnipmask, @@ -657,6 +737,13 @@ int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *macad } exit: + free_nullsafe(ctx, remport); + free_nullsafe(ctx, remipaddr); + free_nullsafe(ctx, vpnipaddr); + free_nullsafe(ctx, vpnipmask); + free_nullsafe(ctx, uname); + free_nullsafe(ctx, cname); + free_nullsafe(ctx, digest); DEBUG(ctx, 10, "** Function result: eurephia_learn_address(ctx, '%s', '%s', ...) = %i", mode, macaddr, ret); diff --git a/plugin/eurephia.h b/plugin/eurephia.h index ef71f44..a6db845 100644 --- a/plugin/eurephia.h +++ b/plugin/eurephia.h @@ -33,7 +33,9 @@ #include -const char *get_env(eurephiaCTX *ctx, int logmasking, const char *envp[], const char *fmt, ... ); +char *get_env(eurephiaCTX *ctx, int logmasking, size_t len, const char *envp[], + const char *fmt, ... ); + eurephiaCTX *eurephiaInit(const char **argv); int eurephiaShutdown(eurephiaCTX *ctx); @@ -41,6 +43,7 @@ int eurephia_tlsverify(eurephiaCTX *ctx, const char **argv, const char *depth); int eurephia_userauth(eurephiaCTX *ctx, const char **env); int eurephia_connect(eurephiaCTX *ctx, const char **env); int eurephia_disconnect(eurephiaCTX *ctx, const char **env); -int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *macaddr, const char **env); +int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *macaddr, + const char **env); #endif /* !EUREPHIA_H_ */ -- cgit