MINOR: cfgcond: implements openssl_version_atleast and openssl_version_before

Implements a way of checking the running openssl version:

If the OpenSSL support was not compiled within HAProxy it will returns a
error, so it's recommanded to do a SSL feature check before:

	$ ./haproxy -cc 'feature(OPENSSL) && openssl_version_atleast(0.9.8zh) && openssl_version_before(3.0.0)'

This will allow to select the SSL reg-tests more carefully.
This commit is contained in:
William Lallemand 2021-08-21 23:59:56 +02:00
parent 44d862d8d4
commit 3aeb3f9347
4 changed files with 65 additions and 6 deletions

View file

@ -50,6 +50,8 @@ enum cond_predicate {
CFG_PRED_STRNEQ, // "strneq" CFG_PRED_STRNEQ, // "strneq"
CFG_PRED_VERSION_ATLEAST, // "version_atleast" CFG_PRED_VERSION_ATLEAST, // "version_atleast"
CFG_PRED_VERSION_BEFORE, // "version_before" CFG_PRED_VERSION_BEFORE, // "version_before"
CFG_PRED_OSSL_VERSION_ATLEAST, // "openssl_version_atleast"
CFG_PRED_OSSL_VERSION_BEFORE, // "openssl_version_before"
}; };
/* types for condition terms */ /* types for condition terms */

View file

@ -1093,4 +1093,8 @@ static inline void update_char_fingerprint(uint8_t *fp, char prev, char curr)
fp[32 * from + to]++; fp[32 * from + to]++;
} }
/* compare the current OpenSSL version to a string */
int openssl_compare_current_version(const char *version);
#endif /* _HAPROXY_TOOLS_H */ #endif /* _HAPROXY_TOOLS_H */

View file

@ -18,12 +18,14 @@
/* supported condition predicates */ /* supported condition predicates */
const struct cond_pred_kw cond_predicates[] = { const struct cond_pred_kw cond_predicates[] = {
{ "defined", CFG_PRED_DEFINED, ARG1(1, STR) }, { "defined", CFG_PRED_DEFINED, ARG1(1, STR) },
{ "feature", CFG_PRED_FEATURE, ARG1(1, STR) }, { "feature", CFG_PRED_FEATURE, ARG1(1, STR) },
{ "streq", CFG_PRED_STREQ, ARG2(2, STR, STR) }, { "streq", CFG_PRED_STREQ, ARG2(2, STR, STR) },
{ "strneq", CFG_PRED_STRNEQ, ARG2(2, STR, STR) }, { "strneq", CFG_PRED_STRNEQ, ARG2(2, STR, STR) },
{ "version_atleast", CFG_PRED_VERSION_ATLEAST, ARG1(1, STR) }, { "version_atleast", CFG_PRED_VERSION_ATLEAST, ARG1(1, STR) },
{ "version_before", CFG_PRED_VERSION_BEFORE, ARG1(1, STR) }, { "version_before", CFG_PRED_VERSION_BEFORE, ARG1(1, STR) },
{ "openssl_version_atleast", CFG_PRED_OSSL_VERSION_ATLEAST, ARG1(1, STR) },
{ "openssl_version_before", CFG_PRED_OSSL_VERSION_BEFORE, ARG1(1, STR) },
{ NULL, CFG_PRED_NONE, 0 } { NULL, CFG_PRED_NONE, 0 }
}; };
@ -230,6 +232,24 @@ int cfg_eval_cond_term(const struct cfg_cond_term *term, char **err)
ret = compare_current_version(term->args[0].data.str.area) > 0; ret = compare_current_version(term->args[0].data.str.area) > 0;
break; break;
case CFG_PRED_OSSL_VERSION_ATLEAST: { // checks if the current openssl version is at least this one
int opensslret = openssl_compare_current_version(term->args[0].data.str.area);
if (opensslret < -1) /* can't parse the string or no openssl available */
ret = -1;
else
ret = opensslret <= 0;
break;
}
case CFG_PRED_OSSL_VERSION_BEFORE: { // checks if the current openssl version is older than this one
int opensslret = openssl_compare_current_version(term->args[0].data.str.area);
if (opensslret < -1) /* can't parse the string or no openssl available */
ret = -1;
else
ret = opensslret > 0;
break;
}
default: default:
memprintf(err, "internal error: unhandled conditional expression predicate '%s'", term->pred->word); memprintf(err, "internal error: unhandled conditional expression predicate '%s'", term->pred->word);
break; break;

View file

@ -62,6 +62,7 @@ extern void *__elf_aux_vector;
#include <haproxy/resolvers.h> #include <haproxy/resolvers.h>
#include <haproxy/sock.h> #include <haproxy/sock.h>
#include <haproxy/ssl_sock.h> #include <haproxy/ssl_sock.h>
#include <haproxy/ssl_utils.h>
#include <haproxy/stream_interface.h> #include <haproxy/stream_interface.h>
#include <haproxy/task.h> #include <haproxy/task.h>
#include <haproxy/tools.h> #include <haproxy/tools.h>
@ -5592,6 +5593,38 @@ int word_fingerprint_distance(const uint8_t *fp1, const uint8_t *fp2)
return dist; return dist;
} }
/*
* This function compares the loaded openssl version with a string <version>
* This function use the same return code as compare_current_version:
*
* -1 : the version in argument is older than the current openssl version
* 0 : the version in argument is the same as the current openssl version
* 1 : the version in argument is newer than the current openssl version
*
* Or some errors:
* -2 : openssl is not available on this process
* -3 : the version in argument is not parsable
*/
int openssl_compare_current_version(const char *version)
{
#ifdef USE_OPENSSL
int numversion;
numversion = openssl_version_parser(version);
if (numversion == 0)
return -3;
if (numversion < OPENSSL_VERSION_NUMBER)
return -1;
else if (numversion > OPENSSL_VERSION_NUMBER)
return 1;
else
return 0;
#else
return -2;
#endif
}
static int init_tools_per_thread() static int init_tools_per_thread()
{ {
/* Let's make each thread start from a different position */ /* Let's make each thread start from a different position */