Skip to content

Commit

Permalink
refs #4550 fixed WebUtil to never serve files outside the root dir (#…
Browse files Browse the repository at this point in the history
…4552)

refs #4551 fixed libqore to allow for setting TLS v1.3 as the minimum protocol version
  • Loading branch information
davidnich committed Jul 5, 2022
1 parent 0c821ec commit 34a7b76
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 91 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12)
# NOTE: Qore should always use semantic versioning: https://semver.org/
set(VERSION_MAJOR 1)
set(VERSION_MINOR 9)
set(VERSION_SUB 0)
set(VERSION_SUB 1)
#set(VERSION_PATCH 0)

# support <pkg>_ROOT in find_package
Expand Down Expand Up @@ -692,7 +692,7 @@ if (APPLE)
set_target_properties(libqore PROPERTIES SOVERSION 12)
set_target_properties(libqore PROPERTIES INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
else (APPLE)
set_target_properties(libqore PROPERTIES VERSION 12.0.1)
set_target_properties(libqore PROPERTIES VERSION 12.0.2)
set_target_properties(libqore PROPERTIES SOVERSION 12)
endif (APPLE)

Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# AC_PREREQ(2.59)
# NOTE: Qore should always use semantic versioning: https://semver.org/
AC_INIT([qore], [1.9.0],
AC_INIT([qore], [1.9.1],
[David Nichols <david@qore.org>],
[qore])
AM_INIT_AUTOMAKE([no-dist-gzip dist-bzip2 tar-ustar subdir-objects])
Expand Down
12 changes: 12 additions & 0 deletions doxygen/lang/900_release_notes.dox.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

@tableofcontents

@section qore_1_9_1 Qore 1.9.1

@par Release Summary
Bugfix release; see below for more information

@subsection qore_1_9_1_bug_fixes Bug Fixes in Qore
- <a href="../../modules/WebUtil/html/index.html">WebUtil</a> module updates:
- fixed a bug where files outside the root directory could be served with specially-formatted requests
(<a href="https://github.com/qorelanguage/qore/issues/4550">issue 4550</a>)
- fixed a bug where it was not possible to set the minimum TLS level to v1.3 for encrypted connections
(<a href="https://github.com/qorelanguage/qore/issues/4551">issue 4551</a>)

@section qore_1_9_0 Qore 1.9.0

@par Release Summary
Expand Down
1 change: 1 addition & 0 deletions include/qore/Qore.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ DLLEXPORT extern const QoreStringMaker mpfrInfo;
#define QLO_DISABLE_GARBAGE_COLLECTION (1 << 3) //!< disable garbage collection / recursive object reference detection
#define QLO_DO_NOT_SEED_RNG (1 << 4) //!< disable seeding the random number generator when the Qore library is initialized
#define QLO_DISABLE_TLS_13 (1 << 5) //!< disable TLS v1.3 (may be set at runtime with qore_set_library_options())
#define QLO_MINIMUM_TLS_13 (1 << 6) //!< minimum TLS v1.3; overrides QLO_DISABLE_TLS_13 (may be set at runtime with qore_set_library_options())

#define QLO_RUNTIME_OPTS (QLO_DISABLE_TLS_13)

Expand Down
2 changes: 1 addition & 1 deletion lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dummy:
echo "Build started!"

EXTRA_INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_builddir)/lib
libqore_la_LDFLAGS = -version-info 12:1:0 -no-undefined ${QORE_LIB_LDFLAGS}
libqore_la_LDFLAGS = -version-info 12:2:0 -no-undefined ${QORE_LIB_LDFLAGS}
AM_CPPFLAGS = $(EXTRA_INCLUDES) ${QORE_LIB_CPPFLAGS}
AM_CXXFLAGS = ${QORE_LIB_CXXFLAGS}
AM_YFLAGS = -d
Expand Down
3 changes: 3 additions & 0 deletions lib/QoreLib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2250,6 +2250,9 @@ bool qore_is_gc_enabled() {
}

int qore_set_library_options(int opts) {
if (opts & QLO_MINIMUM_TLS_13) {
opts &= ~QLO_DISABLE_TLS_13;
}
int val = opts & QLO_RUNTIME_OPTS;
qore_library_options |= val;
return val;
Expand Down
21 changes: 17 additions & 4 deletions lib/QoreSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,22 @@ int SSLSocketHelper::setIntern(const char* mname, int sd, X509* cert, EVP_PKEY*
setVerifyMode(qs.ssl_verify_mode, qs.ssl_accept_all_certs, qs.client_target);
}

#if defined(HAVE_SSL_SET_MAX_PROTO_VERSION) && defined(TLS1_2_VERSION)
if (qore_library_options & QLO_DISABLE_TLS_13) {
SSL_set_max_proto_version(ssl, TLS1_2_VERSION);
#if defined(HAVE_SSL_SET_MAX_PROTO_VERSION) && defined(TLS1_3_VERSION)
if (qore_library_options & QLO_MINIMUM_TLS_13) {
if (!SSL_set_min_proto_version(ssl, TLS1_3_VERSION)) {
sslError(xsink, mname, "SSL_set_min_proto_version");
assert(*xsink);
return -1;
}
} else if (qore_library_options & QLO_DISABLE_TLS_13) {
if (!SSL_set_max_proto_version(ssl, TLS1_2_VERSION)) {
sslError(xsink, mname, "SSL_set_max_proto_version");
assert(*xsink);
return -1;
}
}
#else
#error
#endif

return 0;
Expand Down Expand Up @@ -563,7 +575,8 @@ static int q_ssl_verify_accept_default(int preverify_ok, X509_STORE_CTX* x509_ct
}

void SSLSocketHelper::setVerifyMode(int mode, bool accept_all_certs, const std::string& target) {
printd(5, "SSLSocketHelper::setVerifyMode() mode: %d accept_all_certs: %d target: %s\n", mode, (int)accept_all_certs, target.c_str());
printd(5, "SSLSocketHelper::setVerifyMode() mode: %d accept_all_certs: %d target: %s\n", mode,
(int)accept_all_certs, target.c_str());
if (!accept_all_certs) {
// issue #3818: load default CAs
SSL_CTX_set_default_verify_paths(ctx);
Expand Down
7 changes: 7 additions & 0 deletions lib/ql_lib.qpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,15 @@ const QLO_DISABLE_GARBAGE_COLLECTION = QLO_DISABLE_GARBAGE_COLLECTION;
const QLO_DO_NOT_SEED_RNG = QLO_DO_NOT_SEED_RNG;

//! disable TLS v1.3 (may be set at runtime with qore_set_library_options())
/** conflicts with @ref QLO_MINIMUM_TLS_13
*/
const QLO_DISABLE_TLS_13 = QLO_DISABLE_TLS_13;

//! enable minimum TLS v1.3 (may be set at runtime with qore_set_library_options())
/** conflicts with and overrides @ref QLO_DISABLE_TLS_13
*/
const QLO_MINIMUM_TLS_13 = QLO_MINIMUM_TLS_13;

//! bitmask for library options that can be set at runtime
/** the following options can be set at runtime:
- @ref Qore::QLO_DISABLE_TLS_13
Expand Down
6 changes: 3 additions & 3 deletions lib/qore-main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ int qore_ssl_data_index = -1;

qore_license_t qore_license;

const QoreStringMaker mpfrInfo("runtime: %s built with: %s (%d.%d.%d)", mpfr_get_version(), MPFR_VERSION_STRING, MPFR_VERSION_MAJOR,
MPFR_VERSION_MINOR, MPFR_VERSION_PATCHLEVEL);
const QoreStringMaker mpfrInfo("runtime: %s built with: %s (%d.%d.%d)", mpfr_get_version(), MPFR_VERSION_STRING,
MPFR_VERSION_MAJOR, MPFR_VERSION_MINOR, MPFR_VERSION_PATCHLEVEL);

#ifndef HAVE_OPENSSL_INIT_CRYPTO
// issue #2135: openssl locking functions were deprecated in openssl 1.0.0 and are no longer used in 1.1.0+
Expand Down Expand Up @@ -109,7 +109,7 @@ OSSL_PROVIDER* ssl_prov_legacy = nullptr,
* ssl_prov_default = nullptr;
#endif

void qore_init(qore_license_t license, const char *def_charset, bool show_module_errors, int n_qore_library_options) {
void qore_init(qore_license_t license, const char* def_charset, bool show_module_errors, int n_qore_library_options) {
qore_license = license;
qore_library_options = n_qore_library_options;

Expand Down
78 changes: 48 additions & 30 deletions qlib/Swagger.qm
Original file line number Diff line number Diff line change
Expand Up @@ -2542,50 +2542,61 @@ public class OperationObject inherits ObjectBase {
self.path = path;
self.method = method.upr();
string objType = "Operation";
*list tagsObj;
*list<auto> tagsObj;
if (optional_field(objType, oh, "tags", NT_LIST, \tagsObj)) {
foreach auto tag in (tagsObj) {
if (tag.typeCode() == NT_STRING)
if (tag.typeCode() == NT_STRING) {
tags += tag;
else if (tag.typeCode() == NT_HASH)
} else if (tag.typeCode() == NT_HASH) {
tags += new TagObject(tag);
else
error("INVALID-FIELD-TYPE", "'tags' list value has invalid type %y; expecting \"hash\" or \"string\"", tag.type());
} else {
error("INVALID-FIELD-TYPE", "'tags' list value has invalid type %y; expecting \"hash\" or "
"\"string\"", tag.fullType());
}
}
}

on_error rethrow $1.err, sprintf("%s (operation \"%s %s\")", $1.desc, method.upr(), path);

optional_field(objType, oh, "summary", NT_STRING, \summary);
optional_field(objType, oh, "description", (NT_STRING: True, NT_NOTHING: True), \desc);
optional_field(objType, oh, "deprecated", NT_BOOLEAN, \deprec);

*hash extDocsObj;
if (optional_field(objType, oh, "externalDocs", NT_HASH, \extDocsObj))
if (optional_field(objType, oh, "externalDocs", NT_HASH, \extDocsObj)) {
externalDocs = new ExternalDocumentationObject(extDocsObj);
}

optional_field(objType, oh, "operationId", NT_STRING, \operationId);
# TODO check operationId uniqueness as per docs

# use the global "consumes" definition if none is defined on the operation
if (!optional_field(objType, oh, "consumes", SwaggerListToStringSet, \consumes) && swagger.consumes)
if (!optional_field(objType, oh, "consumes", SwaggerListToStringSet, \consumes) && swagger.consumes) {
consumes = swagger.consumes;
}

# use the global "produces" definition if none is defined on the operation
if (!optional_field(objType, oh, "produces", SwaggerListToStringSet, \produces) && swagger.produces)
if (!optional_field(objType, oh, "produces", SwaggerListToStringSet, \produces) && swagger.produces) {
produces = swagger.produces;
}

{
list listObj;
optional_field(objType, oh, "parameters", NT_LIST, \listObj);
foreach auto p in (listObj) {
if (p.typeCode() != NT_HASH)
error("INVALID-FIELD-TYPE", "invalid 'parameters' list value datatype %y; expecing \"hash\"", p.type());
AbstractParameterObject param = AbstractParameterObject::newParameter(sprintf("%d/%d", $# + 1, listObj.lsize()), p, swagger);
if (param.inLoc == "body")
if (p.typeCode() != NT_HASH) {
error("INVALID-FIELD-TYPE", "invalid 'parameters' list value datatype %y; expecing \"hash\"",
p.fullType());
}
AbstractParameterObject param = AbstractParameterObject::newParameter(sprintf("%d/%d", $# + 1,
listObj.lsize()), p, swagger);
if (param.inLoc == "body") {
body = param;
else if (param.inLoc == "formData")
} else if (param.inLoc == "formData") {
formData{param.name} = param;
else
} else {
parameters{param.name} = param;
}
}
}

Expand All @@ -2600,10 +2611,14 @@ public class OperationObject inherits ObjectBase {
list schemesList;
optional_field(objType, oh, "schemes", NT_LIST, \schemesList);
foreach auto val in (schemesList) {
if (val.typeCode() != NT_STRING)
error("INVALID-FIELD-TYPE", "invalid 'schemes' list value datatype %y; expecting \"string\"", val.type());
if (!ValidSchemesHash{val})
error("INVALID-FIELD-VALUE", "invalid operation transfer protocol scheme value %y; expecting one of: %y", val, keys ValidSchemesHash);
if (val.typeCode() != NT_STRING) {
error("INVALID-FIELD-TYPE", "invalid 'schemes' list value datatype %y; expecting \"string\"",
val.fullType());
}
if (!ValidSchemesHash{val}) {
error("INVALID-FIELD-VALUE", "invalid operation transfer protocol scheme value %y; expecting one "
"of: %y", val, keys ValidSchemesHash);
}
}
if (schemesList) {
schemes = cast<list<string>>(schemesList);
Expand All @@ -2614,18 +2629,20 @@ public class OperationObject inherits ObjectBase {
list securityList;
optional_field(objType, oh, "security", NT_LIST, \securityList);
foreach auto val in (securityList) {
if (val.typeCode() != NT_HASH)
error("INVALID-FIELD-TYPE", "invalid 'security' list value datatype %y; expecting \"hash\"", val.type());
hash h = val;
foreach hash it in (h.pairIterator()) {
if (it.value.typeCode() != NT_LIST)
error("INVALID-FIELD-TYPE",
"invalid Security Requirement Object value type %y (should be a list of hashes)",
val.type());
if ((map True, it.value, $1.typeCode() != NT_STRING).size())
error("INVALID-FIELD-TYPE",
"invalid Security Requirement Object value type %y (should be a list of hashes with list values)",
val.type());
if (val.typeCode() != NT_HASH) {
error("INVALID-FIELD-TYPE", "invalid 'security' list value datatype %y; expecting \"hash\"",
val.fullType());
}
hash<auto> h = val;
foreach hash<auto> it in (h.pairIterator()) {
if (it.value.typeCode() != NT_LIST) {
error("INVALID-FIELD-TYPE", "invalid Security Requirement Object value type %y (should be a "
"list of hashes)", val.fullType());
}
if ((map True, it.value, $1.typeCode() != NT_STRING).size()) {
error("INVALID-FIELD-TYPE", "invalid Security Requirement Object value type %y (should be a "
"list of hashes with list values)", val.fullType());
}
}
}
if (securityList) {
Expand Down Expand Up @@ -3108,6 +3125,7 @@ public class AbstractParameterObject inherits ObjectBase {
public constructor(hash<auto> oh) : ObjectBase(oh) {
string objType = "Parameter";
required_field(objType, oh, "name", NT_STRING, \name);
on_error rethrow $1.err, sprintf("%s (parameter %y)", $1.desc, name);
required_field(objType, oh, "in", NT_STRING, \inLoc);
optional_field(objType, oh, "description", (NT_STRING: True, NT_NOTHING: True), \desc);
if (inLoc == "path")
Expand Down

0 comments on commit 34a7b76

Please sign in to comment.