Author: brane Date: Mon Jun 23 10:09:30 2025 New Revision: 1926661 URL: http://svn.apache.org/viewvc?rev=1926661&view=rev Log: On the user-defined-authn branch: sync with trunk r1926660.
Added: serf/branches/user-defined-authn/.github/workflows/linux-old-scons.yml - copied unchanged from r1926660, serf/trunk/.github/workflows/linux-old-scons.yml serf/branches/user-defined-authn/src/init_once.c - copied unchanged from r1926660, serf/trunk/src/init_once.c Modified: serf/branches/user-defined-authn/ (props changed) serf/branches/user-defined-authn/CMakeLists.txt serf/branches/user-defined-authn/auth/auth_spnego.c serf/branches/user-defined-authn/buckets/ssl_buckets.c serf/branches/user-defined-authn/serf_private.h serf/branches/user-defined-authn/test/certs/create_certs.py serf/branches/user-defined-authn/test/serf_httpd.c Propchange: serf/branches/user-defined-authn/ ------------------------------------------------------------------------------ Merged /serf/trunk:r1926567-1926660 Modified: serf/branches/user-defined-authn/CMakeLists.txt URL: http://svn.apache.org/viewvc/serf/branches/user-defined-authn/CMakeLists.txt?rev=1926661&r1=1926660&r2=1926661&view=diff ============================================================================== --- serf/branches/user-defined-authn/CMakeLists.txt (original) +++ serf/branches/user-defined-authn/CMakeLists.txt Mon Jun 23 10:09:30 2025 @@ -131,6 +131,7 @@ list(APPEND SOURCES "src/context.c" "src/deprecated.c" "src/incoming.c" + "src/init_once.c" "src/logging.c" "src/outgoing.c" "src/outgoing_request.c" Modified: serf/branches/user-defined-authn/auth/auth_spnego.c URL: http://svn.apache.org/viewvc/serf/branches/user-defined-authn/auth/auth_spnego.c?rev=1926661&r1=1926660&r2=1926661&view=diff ============================================================================== --- serf/branches/user-defined-authn/auth/auth_spnego.c (original) +++ serf/branches/user-defined-authn/auth/auth_spnego.c Mon Jun 23 10:09:30 2025 @@ -261,20 +261,11 @@ do_auth(const serf__authn_scheme_t *sche const char *auth_hdr, apr_pool_t *pool) { - serf_context_t *ctx = conn->ctx; - serf__authn_info_t *authn_info; const char *tmp = NULL; char *token = NULL; apr_size_t tmp_len = 0, token_len = 0; apr_status_t status; - if (peer == HOST) { - authn_info = serf__get_authn_info_for_server(conn); - } else { - authn_info = &ctx->proxy_authn_info; - } - /* FIXME: authn_info's value is never used. */ - /* Is this a response from a host/proxy? auth_hdr should always be set. */ if (code && auth_hdr) { const char *space = NULL; Modified: serf/branches/user-defined-authn/buckets/ssl_buckets.c URL: http://svn.apache.org/viewvc/serf/branches/user-defined-authn/buckets/ssl_buckets.c?rev=1926661&r1=1926660&r2=1926661&view=diff ============================================================================== --- serf/branches/user-defined-authn/buckets/ssl_buckets.c (original) +++ serf/branches/user-defined-authn/buckets/ssl_buckets.c Mon Jun 23 10:09:30 2025 @@ -1467,90 +1467,66 @@ static apr_status_t cleanup_ssl(void *da #endif -#if !APR_VERSION_AT_LEAST(1,0,0) -#define apr_atomic_cas32(mem, with, cmp) apr_atomic_cas(mem, with, cmp) -#endif -enum ssl_init_e +static apr_status_t do_init_libraries(void* baton) { - INIT_UNINITIALIZED = 0, - INIT_BUSY = 1, - INIT_DONE = 2 -}; - -static volatile apr_uint32_t have_init_ssl = INIT_UNINITIALIZED; - -static void init_ssl_libraries(void) -{ - apr_uint32_t val; - - val = apr_atomic_cas32(&have_init_ssl, INIT_BUSY, INIT_UNINITIALIZED); - - if (!val) { #if APR_HAS_THREADS && defined(SERF_HAVE_SSL_LOCKING_CALLBACKS) - int i, numlocks; + int i, numlocks; #endif #ifdef SERF_LOGGING_ENABLED - /* Warn when compile-time and run-time version of OpenSSL differ in - major/minor version number. */ + /* Warn when compile-time and run-time version of OpenSSL differ in + major/minor version number. */ #ifdef SERF_HAVE_OPENSSL_VERSION_NUM - unsigned long libver = OpenSSL_version_num(); + unsigned long libver = OpenSSL_version_num(); #else - long libver = SSLeay(); + long libver = SSLeay(); #endif - if ((libver ^ OPENSSL_VERSION_NUMBER) & 0xFFF00000) { - serf__log(LOGLVL_WARNING, LOGCOMP_SSL, __FILE__, NULL, - "Warning: OpenSSL library version mismatch, compile-" - "time was %lx, runtime is %lx.\n", - OPENSSL_VERSION_NUMBER, libver); - } + if ((libver ^ OPENSSL_VERSION_NUMBER) & 0xFFF00000) { + serf__log(LOGLVL_WARNING, LOGCOMP_SSL, __FILE__, NULL, + "Warning: OpenSSL library version mismatch, compile-" + "time was %lx, runtime is %lx.\n", + OPENSSL_VERSION_NUMBER, libver); + } #endif #ifdef SERF_HAVE_OPENSSL_SSL_LIBRARY_INIT - ERR_load_crypto_strings(); - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); #endif #if APR_HAS_THREADS && defined(SERF_HAVE_SSL_LOCKING_CALLBACKS) - numlocks = CRYPTO_num_locks(); - apr_pool_create(&ssl_pool, NULL); - ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks); - for (i = 0; i < numlocks; i++) { - apr_status_t rv; + numlocks = CRYPTO_num_locks(); + apr_pool_create(&ssl_pool, NULL); + ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks); + for (i = 0; i < numlocks; i++) { + apr_status_t status; - /* Intraprocess locks don't /need/ a filename... */ - rv = apr_thread_mutex_create(&ssl_locks[i], + /* Intraprocess locks don't /need/ a filename... */ + status = apr_thread_mutex_create(&ssl_locks[i], APR_THREAD_MUTEX_DEFAULT, ssl_pool); - if (rv != APR_SUCCESS) { - /* FIXME: error out here */ - } - } - CRYPTO_set_locking_callback(ssl_lock); - CRYPTO_set_id_callback(ssl_id); - CRYPTO_set_dynlock_create_callback(ssl_dyn_create); - CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock); - CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy); + if (status != APR_SUCCESS) + return status; + } + CRYPTO_set_locking_callback(ssl_lock); + CRYPTO_set_id_callback(ssl_id); + CRYPTO_set_dynlock_create_callback(ssl_dyn_create); + CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock); + CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy); - apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl); + apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl); #endif - apr_atomic_cas32(&have_init_ssl, INIT_DONE, INIT_BUSY); - } - else - { - /* Make sure we don't continue before the initialization in another - thread has completed */ - while (val != INIT_DONE) { - apr_sleep(APR_USEC_PER_SEC / 1000); - - val = apr_atomic_cas32(&have_init_ssl, - INIT_UNINITIALIZED, - INIT_UNINITIALIZED); - } - } + + return APR_SUCCESS; +} + +static apr_status_t init_ssl_libraries(void) +{ + SERF__DECLARE_STATIC_INIT_ONCE_CONTEXT(init_ctx); + return serf__init_once(&init_ctx, do_init_libraries, NULL); } static int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey) @@ -1774,7 +1750,8 @@ static serf_ssl_context_t *ssl_init_cont { serf_ssl_context_t *ssl_ctx; - init_ssl_libraries(); + if (init_ssl_libraries()) + return NULL; ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx)); @@ -2023,11 +2000,13 @@ apr_status_t serf_ssl_load_cert_file( status = apr_file_open(&cert_file, file_path, APR_READ, APR_OS_DEFAULT, pool); + if (!status) { + status = init_ssl_libraries(); + } if (status) { return status; } - init_ssl_libraries(); biom = bio_meth_file_new(); bio = BIO_new(biom); Modified: serf/branches/user-defined-authn/serf_private.h URL: http://svn.apache.org/viewvc/serf/branches/user-defined-authn/serf_private.h?rev=1926661&r1=1926660&r2=1926661&view=diff ============================================================================== --- serf/branches/user-defined-authn/serf_private.h (original) +++ serf/branches/user-defined-authn/serf_private.h Mon Jun 23 10:09:30 2025 @@ -167,6 +167,32 @@ typedef int serf__bool_t; /* Not _Bool * #endif #endif +/*** One-time initialization. ***/ + +/* Init-once context. */ +struct serf__init_once_context +{ + volatile apr_uint32_t state; + apr_status_t status; +}; + +#define SERF__INIT_ONCE_NONE 0 +#define SERF__DECLARE_STATIC_INIT_ONCE_CONTEXT(name) \ + static struct serf__init_once_context name = { \ + SERF__INIT_ONCE_NONE, APR_SUCCESS \ + } + +/* The init-once callback function. */ +typedef apr_status_t (*serf__init_once_func_t)(void *baton); + +/* The function that performs on-time initialization. + If APR_HAS_THREADS, will use a spinlock to serialize the call to + the initialization function. */ +apr_status_t serf__init_once(struct serf__init_once_context *init_ctx, + serf__init_once_func_t init_func, + void *init_baton); + + typedef struct serf__authn_scheme_t serf__authn_scheme_t; typedef struct serf_io_baton_t { Modified: serf/branches/user-defined-authn/test/certs/create_certs.py URL: http://svn.apache.org/viewvc/serf/branches/user-defined-authn/test/certs/create_certs.py?rev=1926661&r1=1926660&r2=1926661&view=diff ============================================================================== --- serf/branches/user-defined-authn/test/certs/create_certs.py (original) +++ serf/branches/user-defined-authn/test/certs/create_certs.py Mon Jun 23 10:09:30 2025 @@ -9,9 +9,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -21,9 +21,9 @@ # =================================================================== # -# This script creates the private keys and certificates required for +# This script creates the private keys and certificates required for # running the serf test suite. -# +# # It should be run from the test/certs folder without arguments. # Certificates will be created in the test/certs folder, private keys in the # test/certs/private folder. @@ -47,12 +47,12 @@ def create_key(keyfile='', passphrase=No key = crypto.PKey() key.generate_key(KEY_ALGO, KEY_SIZE) if passphrase: - open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, - key, KEY_CIPHER, - passphrase)) + open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, + key, KEY_CIPHER, + passphrase).decode('utf-8')) else: - open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, - key)) + open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, + key).decode('utf-8')) return key @@ -62,7 +62,7 @@ def create_pkcs12(clientkey, clientcert, pkcs12.set_certificate(clientcert) pkcs12.set_privatekey(clientkey) pkcs12.set_ca_certificates([issuer]) - open(pkcs12file, "wt").write(pkcs12.export(passphrase=passphrase, + open(pkcs12file, "wb").write(pkcs12.export(passphrase=passphrase, iter=2048, maciter=2048)) def create_crl(revokedcert, cakey, cacert, crlfile, next_crl_days=VALID_DAYS): @@ -73,9 +73,9 @@ def create_crl(revokedcert, cakey, cacer now = datetime.utcnow() now_str = now.strftime('%Y%m%d%H%M%SZ') - revoked.set_serial(serial_number) - revoked.set_reason('unspecified') - revoked.set_rev_date(now_str) # revoked as of now + revoked.set_serial(serial_number.encode('ascii')) + revoked.set_reason(b'unspecified') + revoked.set_rev_date(now_str.encode('ascii')) # revoked as of now crl.add_revoked(revoked) try: @@ -84,16 +84,16 @@ def create_crl(revokedcert, cakey, cacer # Some very old versions of pyopenssl (such as the one on macOS) # do not support the 'digest' keyword argument. exported = crl.export(cacert, cakey, days=next_crl_days) - open(crlfile, "wt").write(exported) + open(crlfile, "wb").write(exported) # subjectAltName -def create_cert(subjectkey, certfile, issuer=None, issuerkey=None, country='', - state='', city='', org='', ou='', cn='', email='', ca=False, +def create_cert(subjectkey, certfile, issuer=None, issuerkey=None, country='', + state='', city='', org='', ou='', cn='', email='', ca=False, valid_before=0, days_valid=VALID_DAYS, subjectAltName=None, ocsp_responder_url=None, ocsp_signer=False): ''' Create a X509 signed certificate. - + subjectAltName Array of fully qualified subject alternative names (use OpenSSL syntax): For a DNS entry, use: ['DNS:localhost']. Other options are 'email', 'URI', 'IP'. @@ -103,15 +103,15 @@ def create_cert(subjectkey, certfile, is cert.set_version(3-1) # version 3, starts at 0 cert.get_subject().C = country cert.get_subject().ST = state - cert.get_subject().L = city - cert.get_subject().O = org + cert.get_subject().L = city + cert.get_subject().O = org cert.get_subject().OU = ou if cn: cert.get_subject().CN = cn cert.get_subject().emailAddress = email cert.set_serial_number(SERIAL_NUMBER) cert.set_pubkey(subjectkey) - + cert.gmtime_adj_notBefore(valid_before * 24 * 3600) cert.gmtime_adj_notAfter(days_valid * 24 * 3600) @@ -119,92 +119,92 @@ def create_cert(subjectkey, certfile, is issuer = cert # self signed issuerkey = subjectkey cert.set_issuer(issuer.get_subject()) - + if ca: cert.add_extensions([ - crypto.X509Extension("basicConstraints", False, - "CA:TRUE"), - crypto.X509Extension("subjectKeyIdentifier", False, "hash", + crypto.X509Extension(b"basicConstraints", False, + b"CA:TRUE"), + crypto.X509Extension(b"subjectKeyIdentifier", False, b"hash", subject=cert) ]) cert.add_extensions([ - crypto.X509Extension("authorityKeyIdentifier", False, - "keyid:always", issuer=issuer) + crypto.X509Extension(b"authorityKeyIdentifier", False, + b"keyid:always", issuer=issuer) ]) if subjectAltName: critical = True if not cn else False cert.add_extensions([ - crypto.X509Extension('subjectAltName', critical, ", ".join(subjectAltName))]) + crypto.X509Extension(b'subjectAltName', critical, ", ".join(subjectAltName).encode('ascii'))]) if ocsp_responder_url: cert.add_extensions([ - crypto.X509Extension('authorityInfoAccess', False, - 'OCSP;URI:' + ocsp_responder_url)]) + crypto.X509Extension(b'authorityInfoAccess', False, + ('OCSP;URI:' + ocsp_responder_url).encode('ascii'))]) if ocsp_signer: cert.add_extensions([ - crypto.X509Extension('extendedKeyUsage', True, 'OCSPSigning') + crypto.X509Extension(b'extendedKeyUsage', True, b'OCSPSigning') ]) cert.sign(issuerkey, SIGN_ALGO) - open(certfile, "wt").write(crypto.dump_certificate(crypto.FILETYPE_PEM, - cert)) + open(certfile, "wt").write(crypto.dump_certificate(crypto.FILETYPE_PEM, + cert).decode('utf-8')) return cert if __name__ == '__main__': # root CA key pair and certificate. # This key will be used to sign the intermediate CA certificate - rootcakey = create_key('private/serfrootcakey.pem', 'serftest') + rootcakey = create_key('private/serfrootcakey.pem', b'serftest') - rootcacert = create_cert(subjectkey=rootcakey, + rootcacert = create_cert(subjectkey=rootcakey, certfile='serfrootcacert.pem', - country='BE', state='Antwerp', city='Mechelen', - org='In Serf we trust, Inc.', - ou='Test Suite Root CA', cn='Serf Root CA', + country='BE', state='Antwerp', city='Mechelen', + org='In Serf we trust, Inc.', + ou='Test Suite Root CA', cn='Serf Root CA', email='serfroo...@example.com', ca=True) # intermediate CA key pair and certificate # This key will be used to sign all server certificates - cakey = create_key('private/serfcakey.pem', 'serftest') + cakey = create_key('private/serfcakey.pem', b'serftest') cacert = create_cert(subjectkey=cakey, certfile='serfcacert.pem', issuer=rootcacert, issuerkey=rootcakey, - country='BE', state='Antwerp', city='Mechelen', - org='In Serf we trust, Inc.', - ou='Test Suite CA', cn='Serf CA', + country='BE', state='Antwerp', city='Mechelen', + org='In Serf we trust, Inc.', + ou='Test Suite CA', cn='Serf CA', email='ser...@example.com', ca=True) # server key pair # server certificate, no errors - serverkey = create_key('private/serfserverkey.pem', 'serftest') + serverkey = create_key('private/serfserverkey.pem', b'serftest') - servercert = create_cert(subjectkey=serverkey, + servercert = create_cert(subjectkey=serverkey, certfile='serfservercert.pem', issuer=cacert, issuerkey=cakey, - country='BE', state='Antwerp', city='Mechelen', - org='In Serf we trust, Inc.', - ou='Test Suite Server', cn='localhost', + country='BE', state='Antwerp', city='Mechelen', + org='In Serf we trust, Inc.', + ou='Test Suite Server', cn='localhost', email='serfser...@example.com') # server certificate that expired a year ago - expiredcert = create_cert(subjectkey=serverkey, + expiredcert = create_cert(subjectkey=serverkey, certfile='serfserver_expired_cert.pem', issuer=cacert, issuerkey=cakey, - country='BE', state='Antwerp', city='Mechelen', - org='In Serf we trust, Inc.', - ou='Test Suite Server', cn='localhost', + country='BE', state='Antwerp', city='Mechelen', + org='In Serf we trust, Inc.', + ou='Test Suite Server', cn='localhost', email='serfser...@example.com', days_valid=-365) # server certificate that will be valid in 10 years - expiredcert = create_cert(subjectkey=serverkey, + expiredcert = create_cert(subjectkey=serverkey, certfile='serfserver_future_cert.pem', issuer=cacert, issuerkey=cakey, country='BE', state='Antwerp', city='Mechelen', - org='In Serf we trust, Inc.', - ou='Test Suite Server', cn='localhost', + org='In Serf we trust, Inc.', + ou='Test Suite Server', cn='localhost', email='serfser...@example.com', valid_before=10*365) @@ -243,21 +243,21 @@ if __name__ == '__main__': ocsp_signer=True) # client key pair and certificate - clientkey = create_key('private/serfclientkey.pem', 'serftest') + clientkey = create_key('private/serfclientkey.pem', b'serftest') - clientcert = create_cert(subjectkey=clientkey, + clientcert = create_cert(subjectkey=clientkey, certfile='serfclientcert.pem', issuer=cacert, issuerkey=cakey, - country='BE', state='Antwerp', city='Mechelen', - org='In Serf we trust, Inc.', - ou='Test Suite Client', cn='Serf Client', + country='BE', state='Antwerp', city='Mechelen', + org='In Serf we trust, Inc.', + ou='Test Suite Client', cn='Serf Client', email='serfcli...@example.com') - clientpkcs12 = create_pkcs12(clientkey, clientcert, cacert, - 'serfclientcert.p12', 'serftest') + clientpkcs12 = create_pkcs12(clientkey, clientcert, cacert, + 'serfclientcert.p12', b'serftest') - # Note that this creates a v1 CRL file without extensions set, and with + # Note that this creates a v1 CRL file without extensions set, and with # MD5 hash. Not ideal, but pyOpenSSL doesn't support more than this. - # + # # crl crl = create_crl(servercert, cakey, cacert, 'serfservercrl.pem') Modified: serf/branches/user-defined-authn/test/serf_httpd.c URL: http://svn.apache.org/viewvc/serf/branches/user-defined-authn/test/serf_httpd.c?rev=1926661&r1=1926660&r2=1926661&view=diff ============================================================================== --- serf/branches/user-defined-authn/test/serf_httpd.c (original) +++ serf/branches/user-defined-authn/test/serf_httpd.c Mon Jun 23 10:09:30 2025 @@ -383,6 +383,7 @@ int main(int argc, const char **argv) int verbose = 0; const char *opt_arg; const char *root_dir; + apr_finfo_t root_info; apr_initialize(); atexit(apr_terminate); @@ -448,8 +449,14 @@ int main(int argc, const char **argv) exit(-1); } + /* FIXME: root_dir is never used. */ root_dir = argv[opt->ind]; - /* FIXME: root_dir's value is never used. */ + status = apr_stat(&root_info, root_dir, APR_FINFO_TYPE, scratch_pool); + printf("Ignoring root directory %s%s", root_dir, + (status == APR_SUCCESS + ? (root_info.filetype == APR_DIR ? "\n" + : " (which isn't a directory)\n") + : " (which doesn't even exist)\n")); /* Setup debug logging */ if (verbose) {