diff --git a/apache-20-22-upgrade b/apache-20-22-upgrade index 6eeaaf2..561c697 100644 --- a/apache-20-22-upgrade +++ b/apache-20-22-upgrade @@ -13,7 +13,6 @@ if a2enmod -q auth; then a2enmod authz_groupfile a2enmod authz_default a2enmod authz_user - cat <<-EOF @@ -61,4 +60,11 @@ if a2enmod -q auth_ldap; then a2enmod mod_authnz_ldap fi +for module in mod_authn_default mod_authz_default mod_mem_cache; do + if a2enmod -q "$module"; then + echo "!!ATTENTION! $module was removed from apache version 2.4 or later, CHECK YOUR CONFIGURATION!!!" + a2dismod "$module" + fi +done + echo 'Done.' diff --git a/apache2-default-server.conf b/apache2-default-server.conf index fc45e52..eb12cad 100644 --- a/apache2-default-server.conf +++ b/apache2-default-server.conf @@ -102,5 +102,5 @@ ScriptAlias /cgi-bin/ "/srv/www/cgi-bin/" Include /etc/apache2/conf.d/*.conf # The manual... if it is installed ('?' means it won't complain) -Include /etc/apache2/conf.d/apache2-manual?conf +IncludeOptional /etc/apache2/conf.d/apache2-manual?conf diff --git a/apache2-httpd.conf b/apache2-httpd.conf index 696da7a..fe1f272 100644 --- a/apache2-httpd.conf +++ b/apache2-httpd.conf @@ -202,7 +202,7 @@ Include /etc/apache2/sysconfig.d/include.conf # You may use the command line option '-S' to verify your virtual host # configuration. # -Include /etc/apache2/vhosts.d/*.conf +IncludeOptional /etc/apache2/vhosts.d/*.conf # Note: instead of adding your own configuration here, consider diff --git a/apache2-mod_ssl_npn.patch b/apache2-mod_ssl_npn.patch index 246cd74..4213b95 100644 --- a/apache2-mod_ssl_npn.patch +++ b/apache2-mod_ssl_npn.patch @@ -1,51 +1,233 @@ -# This patch adds hooks for Next Protocol Negotiation (NPN) into mod_ssl. This -# change is under review to be included in Apache trunk: -# https://issues.apache.org/bugzilla/show_bug.cgi?id=52210 -# But until it becomes part of an Apache 2.2 release, we need to apply the patch -# ourselves. -Index: modules/ssl/ssl_private.h -=================================================================== ---- modules/ssl/ssl_private.h (revision 1202283) -+++ modules/ssl/ssl_private.h (working copy) -@@ -603,6 +603,7 @@ - #ifndef OPENSSL_NO_TLSEXT - int ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *); - #endif -+int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data, unsigned int *len, void *arg); +--- httpd-2.4.3.orig/modules/ssl/mod_ssl.c ++++ httpd-2.4.3/modules/ssl/mod_ssl.c +@@ -94,6 +94,15 @@ static const command_rec ssl_config_cmds + SSL_CMD_SRV(PKCS7CertificateFile, TAKE1, + "PKCS#7 file containing server certificate and chain" + " certificates ('/path/to/file' - PEM encoded)") ++ SSL_CMD_ALL(RSAAuthzFile, TAKE1, ++ "RFC 5878 Authz Extension file for RSA certificate " ++ "(`/path/to/file')") ++ SSL_CMD_ALL(DSAAuthzFile, TAKE1, ++ "RFC 5878 Authz Extension file for DSA certificate " ++ "(`/path/to/file')") ++ SSL_CMD_ALL(ECAuthzFile, TAKE1, ++ "RFC 5878 Authz Extension file for EC certificate " ++ "(`/path/to/file')") + #ifdef HAVE_TLS_SESSION_TICKETS + SSL_CMD_SRV(SessionTicketKeyFile, TAKE1, + "TLS session ticket encryption/decryption key file (RFC 5077) " +@@ -148,6 +157,15 @@ static const command_rec ssl_config_cmds + SSL_CMD_SRV(StrictSNIVHostCheck, FLAG, + "Strict SNI virtual host checking") - /** Session Cache Support */ - void ssl_scache_init(server_rec *, apr_pool_t *); -@@ -714,4 +715,3 @@ - - #endif /* SSL_PRIVATE_H */ - /** @} */ -- -Index: modules/ssl/ssl_engine_init.c -=================================================================== ---- modules/ssl/ssl_engine_init.c (revision 1202283) -+++ modules/ssl/ssl_engine_init.c (working copy) -@@ -559,6 +559,11 @@ - SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH); - - SSL_CTX_set_info_callback(ctx, ssl_callback_Info); ++#ifndef OPENSSL_NO_SRP ++ SSL_CMD_SRV(SRPVerifierFile, TAKE1, ++ "SRP verifier file " ++ "('/path/to/file' - created by srptool)") ++ SSL_CMD_SRV(SRPUnknownUserSeed, TAKE1, ++ "SRP seed for unknown users (to avoid leaking a user's existence) " ++ "('some secret text')") ++#endif + -+#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) -+ SSL_CTX_set_next_protos_advertised_cb( -+ ctx, ssl_callback_AdvertiseNextProtos, NULL); + /* + * Proxy configuration for remote SSL connections + */ +@@ -263,6 +281,18 @@ static const command_rec ssl_config_cmds + AP_END_CMD + }; + ++/* Implement 'modssl_run_npn_advertise_protos_hook'. */ ++APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL( ++ modssl, AP, int, npn_advertise_protos_hook, ++ (conn_rec *connection, apr_array_header_t *protos), ++ (connection, protos), OK, DECLINED); ++ ++/* Implement 'modssl_run_npn_proto_negotiated_hook'. */ ++APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL( ++ modssl, AP, int, npn_proto_negotiated_hook, ++ (conn_rec *connection, const char *proto_name, apr_size_t proto_name_len), ++ (connection, proto_name, proto_name_len), OK, DECLINED); ++ + /* + * the various processing hooks + */ +--- httpd-2.4.3.orig/modules/ssl/mod_ssl.h ++++ httpd-2.4.3/modules/ssl/mod_ssl.h +@@ -63,5 +63,26 @@ APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_e + + APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *)); + ++/** The npn_advertise_protos optional hook allows other modules to add entries ++ * to the list of protocol names advertised by the server during the Next ++ * Protocol Negotiation (NPN) portion of the SSL handshake. The hook callee is ++ * given the connection and an APR array; it should push one or more char*'s ++ * pointing to null-terminated strings (such as "http/1.1" or "spdy/2") onto ++ * the array and return OK, or do nothing and return DECLINED. */ ++APR_DECLARE_EXTERNAL_HOOK(modssl, AP, int, npn_advertise_protos_hook, ++ (conn_rec *connection, apr_array_header_t *protos)); ++ ++/** The npn_proto_negotiated optional hook allows other modules to discover the ++ * name of the protocol that was chosen during the Next Protocol Negotiation ++ * (NPN) portion of the SSL handshake. Note that this may be the empty string ++ * (in which case modules should probably assume HTTP), or it may be a protocol ++ * that was never even advertised by the server. The hook callee is given the ++ * connection, a non-null-terminated string containing the protocol name, and ++ * the length of the string; it should do something appropriate (i.e. insert or ++ * remove filters) and return OK, or do nothing and return DECLINED. */ ++APR_DECLARE_EXTERNAL_HOOK(modssl, AP, int, npn_proto_negotiated_hook, ++ (conn_rec *connection, const char *proto_name, ++ apr_size_t proto_name_len)); ++ + #endif /* __MOD_SSL_H__ */ + /** @} */ +--- httpd-2.4.3.orig/modules/ssl/ssl_engine_config.c ++++ httpd-2.4.3/modules/ssl/ssl_engine_config.c +@@ -125,6 +125,10 @@ static void modssl_ctx_init(modssl_ctx_t + mctx->crl_file = NULL; + mctx->crl_check_mode = SSL_CRLCHECK_UNSET; + ++ mctx->rsa_authz_file = NULL; ++ mctx->dsa_authz_file = NULL; ++ mctx->ec_authz_file = NULL; ++ + mctx->auth.ca_cert_path = NULL; + mctx->auth.ca_cert_file = NULL; + mctx->auth.cipher_suite = NULL; +@@ -149,6 +153,12 @@ static void modssl_ctx_init(modssl_ctx_t + mctx->stapling_responder_timeout = UNSET; + mctx->stapling_force_url = NULL; + #endif ++ ++#ifndef OPENSSL_NO_SRP ++ mctx->srp_vfile = NULL; ++ mctx->srp_unknown_user_seed = NULL; ++ mctx->srp_vbase = NULL; +#endif } - static void ssl_init_ctx_verify(server_rec *s, -@@ -1352,4 +1357,3 @@ + static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc, +@@ -251,6 +264,10 @@ static void modssl_ctx_cfg_merge(modssl_ + cfgMerge(crl_file, NULL); + cfgMerge(crl_check_mode, SSL_CRLCHECK_UNSET); - return APR_SUCCESS; ++ cfgMergeString(rsa_authz_file); ++ cfgMergeString(dsa_authz_file); ++ cfgMergeString(ec_authz_file); ++ + cfgMergeString(auth.ca_cert_path); + cfgMergeString(auth.ca_cert_file); + cfgMergeString(auth.cipher_suite); +@@ -274,6 +291,11 @@ static void modssl_ctx_cfg_merge(modssl_ + cfgMergeInt(stapling_responder_timeout); + cfgMerge(stapling_force_url, NULL); + #endif ++ ++#ifndef OPENSSL_NO_SRP ++ cfgMergeString(srp_vfile); ++ cfgMergeString(srp_unknown_user_seed); ++#endif } -- -Index: modules/ssl/ssl_engine_io.c -=================================================================== ---- modules/ssl/ssl_engine_io.c (revision 1202283) -+++ modules/ssl/ssl_engine_io.c (working copy) -@@ -338,6 +338,7 @@ + + static void modssl_ctx_cfg_merge_proxy(modssl_ctx_t *base, +@@ -829,6 +871,54 @@ const char *ssl_cmd_SSLPKCS7CertificateF + return NULL; + } + ++const char *ssl_cmd_SSLRSAAuthzFile(cmd_parms *cmd, ++ void *dcfg, ++ const char *arg) ++{ ++ SSLSrvConfigRec *sc = mySrvConfig(cmd->server); ++ const char *err; ++ ++ if ((err = ssl_cmd_check_file(cmd, &arg))) { ++ return err; ++ } ++ ++ sc->server->rsa_authz_file = arg; ++ ++ return NULL; ++} ++ ++const char *ssl_cmd_SSLDSAAuthzFile(cmd_parms *cmd, ++ void *dcfg, ++ const char *arg) ++{ ++ SSLSrvConfigRec *sc = mySrvConfig(cmd->server); ++ const char *err; ++ ++ if ((err = ssl_cmd_check_file(cmd, &arg))) { ++ return err; ++ } ++ ++ sc->server->dsa_authz_file = arg; ++ ++ return NULL; ++} ++ ++const char *ssl_cmd_SSLECAuthzFile(cmd_parms *cmd, ++ void *dcfg, ++ const char *arg) ++{ ++ SSLSrvConfigRec *sc = mySrvConfig(cmd->server); ++ const char *err; ++ ++ if ((err = ssl_cmd_check_file(cmd, &arg))) { ++ return err; ++ } ++ ++ sc->server->ec_authz_file = arg; ++ ++ return NULL; ++} ++ + #ifdef HAVE_TLS_SESSION_TICKETS + const char *ssl_cmd_SSLSessionTicketKeyFile(cmd_parms *cmd, + void *dcfg, +@@ -1782,6 +1872,32 @@ const char *ssl_cmd_SSLStaplingForceURL( + + #endif /* HAVE_OCSP_STAPLING */ + ++#ifndef OPENSSL_NO_SRP ++ ++const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, ++ const char *arg) ++{ ++ SSLSrvConfigRec *sc = mySrvConfig(cmd->server); ++ const char *err; ++ ++ if ((err = ssl_cmd_check_file(cmd, &arg))) ++ return err; ++ /* SRP_VBASE_init takes char*, not const char* */ ++ sc->server->srp_vfile = apr_pstrdup(cmd->pool, arg); ++ return NULL; ++} ++ ++const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, ++ const char *arg) ++{ ++ SSLSrvConfigRec *sc = mySrvConfig(cmd->server); ++ /* SRP_VBASE_new takes char*, not const char* */ ++ sc->server->srp_unknown_user_seed = apr_pstrdup(cmd->pool, arg); ++ return NULL; ++} ++ ++#endif /* OPENSSL_NO_SRP */ ++ + void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s) + { + apr_file_t *out = NULL; +--- httpd-2.4.3.orig/modules/ssl/ssl_engine_io.c ++++ httpd-2.4.3/modules/ssl/ssl_engine_io.c +@@ -28,6 +28,7 @@ + core keeps dumping.'' + -- Unknown */ + #include "ssl_private.h" ++#include "mod_ssl.h" + #include "apr_date.h" + + /* _________________________________________________________________ +@@ -297,6 +298,7 @@ typedef struct { apr_pool_t *pool; char buffer[AP_IOBUFSIZE]; ssl_filter_ctx_t *filter_ctx; @@ -53,44 +235,99 @@ Index: modules/ssl/ssl_engine_io.c } bio_filter_in_ctx_t; /* -@@ -1409,6 +1410,21 @@ +@@ -1374,6 +1376,26 @@ static apr_status_t ssl_io_filter_input( APR_BRIGADE_INSERT_TAIL(bb, bucket); } ++#ifdef HAVE_TLS_NPN + /* By this point, Next Protocol Negotiation (NPN) should be completed (if + * our version of OpenSSL supports it). If we haven't already, find out + * which protocol was decided upon and inform other modules by calling + * npn_proto_negotiated_hook. */ + if (!inctx->npn_finished) { -+ inctx->npn_finished = 1; -+#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) + const unsigned char *next_proto = NULL; + unsigned next_proto_len = 0; -+ SSL_get0_next_proto_negotiated(inctx->ssl, &next_proto, -+ &next_proto_len); -+ ssl_run_npn_proto_negotiated_hook(f->c, next_proto, next_proto_len); -+#endif ++ ++ SSL_get0_next_proto_negotiated( ++ inctx->ssl, &next_proto, &next_proto_len); ++ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, f->c, ++ APLOGNO(02306) "SSL NPN negotiated protocol: '%*s'", ++ next_proto_len, (const char*)next_proto); ++ modssl_run_npn_proto_negotiated_hook( ++ f->c, (const char*)next_proto, next_proto_len); ++ inctx->npn_finished = 1; + } ++#endif + return APR_SUCCESS; } -@@ -1753,6 +1769,7 @@ +@@ -1855,6 +1877,7 @@ static void ssl_io_input_add_filter(ssl_ inctx->block = APR_BLOCK_READ; inctx->pool = c->pool; inctx->filter_ctx = filter_ctx; + inctx->npn_finished = 0; } - void ssl_io_filter_init(conn_rec *c, SSL *ssl) -Index: modules/ssl/ssl_engine_kernel.c -=================================================================== ---- modules/ssl/ssl_engine_kernel.c (revision 1202283) -+++ modules/ssl/ssl_engine_kernel.c (working copy) -@@ -1969,6 +1969,77 @@ - } - } + /* The request_rec pointer is passed in here only to ensure that the +--- httpd-2.4.3.orig/modules/ssl/ssl_engine_kernel.c ++++ httpd-2.4.3/modules/ssl/ssl_engine_kernel.c +@@ -29,6 +29,7 @@ + time I was too famous.'' + -- Unknown */ + #include "ssl_private.h" ++#include "mod_ssl.h" + #include "util_md5.h" + static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn); +@@ -329,6 +330,19 @@ int ssl_hook_Access(request_rec *r) + return DECLINED; + } + ++#ifndef OPENSSL_NO_SRP ++ /* ++ * Support for per-directory reconfigured SSL connection parameters ++ * ++ * We do not force any renegotiation if the user is already authenticated ++ * via SRP. ++ * ++ */ ++ if (SSL_get_srp_username(ssl)) { ++ return DECLINED; ++ } ++#endif ++ + /* + * Support for per-directory reconfigured SSL connection parameters. + * +@@ -1088,6 +1102,10 @@ static const char *ssl_hook_Fixup_vars[] + "SSL_SERVER_A_SIG", + "SSL_SESSION_ID", + "SSL_SESSION_RESUMED", ++#ifndef OPENSSL_NO_SRP ++ "SSL_SRP_USER", ++ "SSL_SRP_USERINFO", ++#endif + NULL + }; + +@@ -2072,7 +2090,7 @@ static int ssl_find_vhost(void *serverna + + return 0; + } +-#endif ++#endif /* OPENSSL_NO_TLSEXT */ + + #ifdef HAVE_TLS_SESSION_TICKETS + /* +@@ -2142,4 +2160,114 @@ int ssl_callback_SessionTicket(SSL *ssl, + /* OpenSSL is not expected to call us with modes other than 1 or 0 */ + return -1; + } +-#endif ++#endif /* HAVE_TLS_SESSION_TICKETS */ ++ ++#ifdef HAVE_TLS_NPN +/* + * This callback function is executed when SSL needs to decide what protocols + * to advertise during Next Protocol Negotiation (NPN). It must produce a @@ -101,55 +338,65 @@ Index: modules/ssl/ssl_engine_kernel.c +int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data_out, + unsigned int *size_out, void *arg) +{ ++ conn_rec *c = (conn_rec*)SSL_get_app_data(ssl); ++ apr_array_header_t *protos; ++ int num_protos; ++ unsigned int size; ++ int i; ++ unsigned char *data; ++ unsigned char *start; ++ + *data_out = NULL; + *size_out = 0; + -+ /* Get the connection object. If it's not available, then there's nothing -+ * for us to do. */ -+ conn_rec *c = (conn_rec*)SSL_get_app_data(ssl); ++ /* If the connection object is not available, then there's nothing for us ++ * to do. */ + if (c == NULL) { + return SSL_TLSEXT_ERR_OK; + } + + /* Invoke our npn_advertise_protos hook, giving other modules a chance to + * add alternate protocol names to advertise. */ -+ apr_array_header_t *protos = apr_array_make(c->pool, 0, sizeof(char*)); -+ ssl_run_npn_advertise_protos_hook(c, protos); -+ int num_protos = protos->nelts; -+ -+ /* If no other modules added any alternate protocols, then we're done. */ -+ if (num_protos == 0) { -+ return SSL_TLSEXT_ERR_OK; -+ } ++ protos = apr_array_make(c->pool, 0, sizeof(char*)); ++ modssl_run_npn_advertise_protos_hook(c, protos); ++ num_protos = protos->nelts; + + /* We now have a list of null-terminated strings; we need to concatenate + * them together into a single string, where each protocol name is prefixed + * by its length. First, calculate how long that string will be. */ -+ unsigned int size = 0; -+ int i; ++ size = 0; + for (i = 0; i < num_protos; ++i) { -+ const char* string = APR_ARRAY_IDX(protos, i, const char*); ++ const char *string = APR_ARRAY_IDX(protos, i, const char*); + unsigned int length = strlen(string); + /* If the protocol name is too long (the length must fit in one byte), -+ * then log an error and quit. */ ++ * then log an error and skip it. */ + if (length > 255) { -+ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, ++ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02307) + "SSL NPN protocol name too long (length=%u): %s", + length, string); -+ return SSL_TLSEXT_ERR_OK; ++ continue; + } + /* Leave room for the length prefix (one byte) plus the protocol name + * itself. */ + size += 1 + length; + } + ++ /* If there is nothing to advertise (either because no modules added ++ * anything to the protos array, or because all strings added to the array ++ * were skipped), then we're done. */ ++ if (size == 0) { ++ return SSL_TLSEXT_ERR_OK; ++ } ++ + /* Now we can build the string. Copy each protocol name string into the + * larger string, prefixed by its length. */ -+ unsigned char* data = apr_palloc(c->pool, size * sizeof(unsigned char)); -+ unsigned char* start = data; ++ data = apr_palloc(c->pool, size * sizeof(unsigned char)); ++ start = data; + for (i = 0; i < num_protos; ++i) { -+ const char* string = APR_ARRAY_IDX(protos, i, const char*); -+ size_t length = strlen(string); ++ const char *string = APR_ARRAY_IDX(protos, i, const char*); ++ apr_size_t length = strlen(string); ++ if (length > 255) ++ continue; + *start = (unsigned char)length; + ++start; + memcpy(start, string, length * sizeof(unsigned char)); @@ -162,60 +409,144 @@ Index: modules/ssl/ssl_engine_kernel.c + return SSL_TLSEXT_ERR_OK; +} + - #ifndef OPENSSL_NO_TLSEXT - /* - * This callback function is executed when OpenSSL encounters an extended -Index: modules/ssl/mod_ssl.c -=================================================================== ---- modules/ssl/mod_ssl.c (revision 1202283) -+++ modules/ssl/mod_ssl.c (working copy) -@@ -220,6 +220,18 @@ - AP_END_CMD - }; ++#endif /* HAVE_TLS_NPN */ ++ ++#ifndef OPENSSL_NO_SRP ++ ++int ssl_callback_SRPServerParams(SSL *ssl, int *ad, void *arg) ++{ ++ modssl_ctx_t *mctx = (modssl_ctx_t *)arg; ++ char *username = SSL_get_srp_username(ssl); ++ SRP_user_pwd *u; ++ ++ if (username == NULL ++ || (u = SRP_VBASE_get_by_user(mctx->srp_vbase, username)) == NULL) { ++ *ad = SSL_AD_UNKNOWN_PSK_IDENTITY; ++ return SSL3_AL_FATAL; ++ } ++ ++ if (SSL_set_srp_server_param(ssl, u->N, u->g, u->s, u->v, u->info) < 0) { ++ *ad = SSL_AD_INTERNAL_ERROR; ++ return SSL3_AL_FATAL; ++ } ++ ++ /* reset all other options */ ++ SSL_set_verify(ssl, SSL_VERIFY_NONE, ssl_callback_SSLVerify); ++ return SSL_ERROR_NONE; ++} ++ ++#endif /* OPENSSL_NO_SRP */ +--- httpd-2.4.3.orig/modules/ssl/ssl_engine_vars.c ++++ httpd-2.4.3/modules/ssl/ssl_engine_vars.c +@@ -395,6 +395,18 @@ static char *ssl_var_lookup_ssl(apr_pool + #endif + result = apr_pstrdup(p, flag ? "true" : "false"); + } ++#ifndef OPENSSL_NO_SRP ++ else if (ssl != NULL && strcEQ(var, "SRP_USER")) { ++ if ((result = SSL_get_srp_username(ssl)) != NULL) { ++ result = apr_pstrdup(p, result); ++ } ++ } ++ else if (ssl != NULL && strcEQ(var, "SRP_USERINFO")) { ++ if ((result = SSL_get_srp_userinfo(ssl)) != NULL) { ++ result = apr_pstrdup(p, result); ++ } ++ } ++#endif -+/* Implement 'ssl_run_npn_advertise_protos_hook'. */ -+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL( -+ ssl, AP, int, npn_advertise_protos_hook, -+ (conn_rec* connection, apr_array_header_t* protos), -+ (connection, protos), OK, DECLINED); -+ -+/* Implement 'ssl_run_npn_proto_negotiated_hook'. */ -+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL( -+ ssl, AP, int, npn_proto_negotiated_hook, -+ (conn_rec* connection, char* proto_name, apr_size_t proto_name_len), -+ (connection, proto_name, proto_name_len), OK, DECLINED); -+ - /* - * the various processing hooks - */ -Index: modules/ssl/mod_ssl.h -=================================================================== ---- modules/ssl/mod_ssl.h (revision 1202283) -+++ modules/ssl/mod_ssl.h (working copy) -@@ -60,5 +60,26 @@ + return result; + } +--- httpd-2.4.3.orig/modules/ssl/ssl_private.h ++++ httpd-2.4.3/modules/ssl/ssl_private.h +@@ -139,6 +139,11 @@ + #define HAVE_FIPS + #endif - APR_DECLARE_OPTIONAL_FN(apr_array_header_t *, ssl_extlist_by_oid, (request_rec *r, const char *oidstr)); ++#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_NEXTPROTONEG) \ ++ && !defined(OPENSSL_NO_TLSEXT) ++#define HAVE_TLS_NPN ++#endif ++ + #if (OPENSSL_VERSION_NUMBER >= 0x10000000) + #define MODSSL_SSL_CIPHER_CONST const + #define MODSSL_SSL_METHOD_CONST const +@@ -185,6 +190,20 @@ + #define OPENSSL_NO_COMP + #endif -+/** The npn_advertise_protos optional hook allows other modules to add entries -+ * to the list of protocol names advertised by the server during the Next -+ * Protocol Negotiation (NPN) portion of the SSL handshake. The hook callee is -+ * given the connection and an APR array; it should push one or more char*'s -+ * pointing to null-terminated strings (such as "http/1.1" or "spdy/2") onto -+ * the array and return OK, or do nothing and return DECLINED. */ -+APR_DECLARE_EXTERNAL_HOOK(ssl, AP, int, npn_advertise_protos_hook, -+ (conn_rec* connection, apr_array_header_t* protos)); ++#if !defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION) \ ++ && OPENSSL_VERSION_NUMBER < 0x00908000L ++#define OPENSSL_NO_COMP ++#endif + -+/** The npn_proto_negotiated optional hook allows other modules to discover the -+ * name of the protocol that was chosen during the Next Protocol Negotiation -+ * (NPN) portion of the SSL handshake. Note that this may be the empty string -+ * (in which case modules should probably assume HTTP), or it may be a protocol -+ * that was never even advertised by the server. The hook callee is given the -+ * connection, a non-null-terminated string containing the protocol name, and -+ * the length of the string; it should do something appropriate (i.e. insert or -+ * remove filters) and return OK, or do nothing and return DECLINED. */ -+APR_DECLARE_EXTERNAL_HOOK(ssl, AP, int, npn_proto_negotiated_hook, -+ (conn_rec* connection, char* proto_name, -+ apr_size_t proto_name_len)); ++/* SRP support came in OpenSSL 1.0.1 */ ++#ifndef OPENSSL_NO_SRP ++#ifdef SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB ++#include ++#else ++#define OPENSSL_NO_SRP ++#endif ++#endif + - #endif /* __MOD_SSL_H__ */ - /** @} */ + /* mod_ssl headers */ + #include "ssl_util_ssl.h" + +@@ -647,6 +666,17 @@ typedef struct { + const char *stapling_force_url; + #endif + ++#ifndef OPENSSL_NO_SRP ++ char *srp_vfile; ++ char *srp_unknown_user_seed; ++ SRP_VBASE *srp_vbase; ++#endif ++ ++ /** RFC 5878 */ ++ const char *rsa_authz_file; ++ const char *dsa_authz_file; ++ const char *ec_authz_file; ++ + modssl_auth_ctx_t auth; + + BOOL ocsp_enabled; /* true if OCSP verification enabled */ +@@ -723,6 +756,9 @@ const char *ssl_cmd_SSLCryptoDevice(cmd + const char *ssl_cmd_SSLRandomSeed(cmd_parms *, void *, const char *, const char *, const char *); + const char *ssl_cmd_SSLEngine(cmd_parms *, void *, const char *); + const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *); ++const char *ssl_cmd_SSLRSAAuthzFile(cmd_parms *, void *, const char *); ++const char *ssl_cmd_SSLDSAAuthzFile(cmd_parms *, void *, const char *); ++const char *ssl_cmd_SSLECAuthzFile(cmd_parms *, void *, const char *); + const char *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *); + const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *); + const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, void *, const char *); +@@ -775,6 +811,11 @@ const char *ssl_cmd_SSLOCSPResponseMaxAg + const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg); + const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag); + ++#ifndef OPENSSL_NO_SRP ++const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg); ++const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char *arg); ++#endif ++ + const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag); + + /** module initialization */ +@@ -820,6 +861,7 @@ int ssl_callback_ServerNameIndi + int ssl_callback_SessionTicket(SSL *, unsigned char *, unsigned char *, + EVP_CIPHER_CTX *, HMAC_CTX *, int); + #endif ++int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data, unsigned int *len, void *arg); + + /** Session Cache Support */ + void ssl_scache_init(server_rec *, apr_pool_t *); +@@ -851,6 +893,9 @@ void modssl_init_stapling(server + void ssl_stapling_ex_init(void); + int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x); + #endif ++#ifndef OPENSSL_NO_SRP ++int ssl_callback_SRPServerParams(SSL *, int *, void *); ++#endif + + /** I/O */ + void ssl_io_filter_init(conn_rec *, request_rec *r, SSL *); diff --git a/apache2.2-mpm-itk-20090414-00.patch b/apache2.4-mpm-itk-2.4.2-01.patch similarity index 62% rename from apache2.2-mpm-itk-20090414-00.patch rename to apache2.4-mpm-itk-2.4.2-01.patch index 7948309..ba21410 100644 --- a/apache2.2-mpm-itk-20090414-00.patch +++ b/apache2.4-mpm-itk-2.4.2-01.patch @@ -1,21 +1,32 @@ -unchanged: +Index: httpd-2.4.2/server/mpm/itk/Makefile.in +=================================================================== --- /dev/null -+++ server/mpm/experimental/itk/Makefile.in -@@ -0,0 +1,5 @@ -+ -+LTLIBRARY_NAME = libitk.la -+LTLIBRARY_SOURCES = itk.c -+ -+include $(top_srcdir)/build/ltlib.mk ++++ httpd-2.4.2/server/mpm/itk/Makefile.in +@@ -0,0 +1 @@ ++include $(top_srcdir)/build/special.mk +Index: httpd-2.4.2/server/mpm/itk/config.m4 +=================================================================== --- /dev/null -+++ server/mpm/experimental/itk/config.m4 -@@ -0,0 +1,3 @@ -+if test "$MPM_NAME" = "itk" ; then -+ APACHE_FAST_OUTPUT(server/mpm/$MPM_SUBDIR_NAME/Makefile) ++++ httpd-2.4.2/server/mpm/itk/config.m4 +@@ -0,0 +1,7 @@ ++AC_MSG_CHECKING(if itk MPM supports this platform) ++if test $forking_mpms_supported != yes; then ++ AC_MSG_RESULT(no - This is not a forking platform) ++else ++ AC_MSG_RESULT(yes) ++ APACHE_MPM_SUPPORTED(itk, yes, no) +fi +Index: httpd-2.4.2/server/mpm/itk/config3.m4 +=================================================================== --- /dev/null -+++ server/mpm/experimental/itk/itk.c -@@ -0,0 +1,1740 @@ ++++ httpd-2.4.2/server/mpm/itk/config3.m4 +@@ -0,0 +1 @@ ++APACHE_MPM_MODULE(itk, $enable_mpm_itk) +Index: httpd-2.4.2/server/mpm/itk/itk.c +=================================================================== +--- /dev/null ++++ httpd-2.4.2/server/mpm/itk/itk.c +@@ -0,0 +1,1917 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. @@ -31,7 +42,7 @@ unchanged: + * See the License for the specific language governing permissions and + * limitations under the License. + * -+ * Portions copyright 2005-2009 Steinar H. Gunderson . ++ * Portions copyright 2005-2012 Steinar H. Gunderson . + * Licensed under the same terms as the rest of Apache. + * + * Portions copyright 2008 Knut Auvor Grythe . @@ -59,8 +70,8 @@ unchanged: +#if APR_HAVE_SYS_TYPES_H +#include +#endif -+ -+#define CORE_PRIVATE ++#include ++#include + +#include "ap_config.h" +#include "httpd.h" @@ -70,18 +81,16 @@ unchanged: +#include "http_config.h" +#include "http_core.h" /* for get_remote_host */ +#include "http_connection.h" -+#include "http_request.h" /* for ap_hook_post_perdir_config */ +#include "scoreboard.h" +#include "ap_mpm.h" ++#include "util_mutex.h" +#include "unixd.h" +#include "mpm_common.h" +#include "ap_listen.h" +#include "ap_mmn.h" +#include "apr_poll.h" ++#include "ap_expr.h" + -+#ifdef HAVE_BSTRING_H -+#include /* for IRIX, FD_SET calls bzero() */ -+#endif +#ifdef HAVE_TIME_H +#include +#endif @@ -96,6 +105,9 @@ unchanged: +#include +#include + ++/* Import our private hook. */ ++AP_DECLARE_HOOK(int,post_perdir_config,(request_rec *r)) ++ +/* Limit on the total --- clients will be locked out if more servers than + * this are needed. It is intended solely to keep the server from crashing + * when things get out of hand. @@ -124,25 +136,46 @@ unchanged: + +/* config globals */ + -+int ap_threads_per_child=0; /* Worker threads per child */ +static apr_proc_mutex_t *accept_mutex; +static int ap_daemons_to_start=0; +static int ap_daemons_min_free=0; +static int ap_daemons_max_free=0; -+static int ap_daemons_limit=0; /* MaxClients */ -+static int server_limit = DEFAULT_SERVER_LIMIT; -+static int first_server_limit = 0; -+static int changed_limit_at_restart; ++static int ap_daemons_limit=0; /* MaxRequestWorkers */ ++static int server_limit = 0; +static int mpm_state = AP_MPMQ_STARTING; +static ap_pod_t *pod; + -+/* -+ * The max child slot ever assigned, preserved across restarts. Necessary -+ * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We -+ * use this value to optimize routines that have to scan the entire scoreboard. ++/* data retained by itk across load/unload of the module ++ * allocated on first call to pre-config hook; located on ++ * subsequent calls to pre-config hook + */ -+int ap_max_daemons_limit = -1; -+server_rec *ap_server_conf; ++typedef struct itk_retained_data { ++ int first_server_limit; ++ int module_loads; ++ ap_generation_t my_generation; ++ int volatile is_graceful; /* set from signal handler */ ++ int maxclients_reported; ++ /* ++ * The max child slot ever assigned, preserved across restarts. Necessary ++ * to deal with MaxRequestWorkers changes across AP_SIG_GRACEFUL restarts. We ++ * use this value to optimize routines that have to scan the entire scoreboard. ++ */ ++ int max_daemons_limit; ++ /* ++ * idle_spawn_rate is the number of children that will be spawned on the ++ * next maintenance cycle if there aren't enough idle servers. It is ++ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by ++ * without the need to spawn. ++ */ ++ int idle_spawn_rate; ++#ifndef MAX_SPAWN_RATE ++#define MAX_SPAWN_RATE (32) ++#endif ++ int hold_off_on_exponential_spawning; ++} itk_retained_data; ++static itk_retained_data *retained; ++ ++#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) + +/* one_process --- debugging mode variable; can be set from the command line + * with the -X flag. If set, this gets you the child_main loop running @@ -162,17 +195,7 @@ unchanged: + +static pid_t ap_my_pid; /* it seems silly to call getpid all the time */ +static pid_t parent_pid; -+#ifndef MULTITHREAD +static int my_child_num; -+#endif -+ap_generation_t volatile ap_my_generation=0; -+ -+#ifdef TPF -+int tpf_child = 0; -+char tpf_server_name[INETD_SERVNAME_LENGTH+1]; -+#endif /* TPF */ -+ -+static volatile int die_now = 0; + +#define UNSET_NICE_VALUE 100 + @@ -182,6 +205,8 @@ unchanged: + gid_t gid; + char *username; + int nice_value; ++ ap_expr_info_t *uid_expr; ++ ap_expr_info_t *gid_expr; +} itk_per_dir_conf; + +typedef struct @@ -190,6 +215,7 @@ unchanged: +} itk_server_conf; + +module AP_MODULE_DECLARE_DATA mpm_itk_module; ++extern AP_DECLARE_DATA int ap_running_under_mpm_itk; + +#ifdef GPROF +/* @@ -201,7 +227,7 @@ unchanged: +static void chdir_for_gprof(void) +{ + core_server_config *sconf = -+ ap_get_module_config(ap_server_conf->module_config, &core_module); ++ ap_get_core_module_config(ap_server_conf->module_config); + char *dir = sconf->gprof_dir; + const char *use_dir; + @@ -219,7 +245,7 @@ unchanged: + APR_GREAD | APR_GEXECUTE | + APR_WREAD | APR_WEXECUTE, pconf); + if(res != APR_SUCCESS && !APR_STATUS_IS_EEXIST(res)) { -+ ap_log_error(APLOG_MARK, APLOG_ERR, res, ap_server_conf, ++ ap_log_error(APLOG_MARK, APLOG_ERR, res, ap_server_conf, APLOGNO(00142) + "gprof: error creating directory %s", dir); + } + } @@ -233,9 +259,24 @@ unchanged: +#define chdir_for_gprof() +#endif + -+/* XXX - I don't know if TPF will ever use this module or not, so leave -+ * the ap_check_signals calls in but disable them - manoj */ -+#define ap_check_signals() ++static void itk_note_child_killed(int childnum, pid_t pid, ++ ap_generation_t gen) ++{ ++ AP_DEBUG_ASSERT(childnum != -1); /* no scoreboard squatting with this MPM */ ++ ap_run_child_status(ap_server_conf, ++ ap_scoreboard_image->parent[childnum].pid, ++ ap_scoreboard_image->parent[childnum].generation, ++ childnum, MPM_CHILD_EXITED); ++ ap_scoreboard_image->parent[childnum].pid = 0; ++} ++ ++static void itk_note_child_started(int slot, pid_t pid) ++{ ++ ap_scoreboard_image->parent[slot].pid = pid; ++ ap_run_child_status(ap_server_conf, ++ ap_scoreboard_image->parent[slot].pid, ++ retained->my_generation, slot, MPM_CHILD_STARTED); ++} + +/* a clean exit from a child with proper cleanup */ +static void clean_child_exit(int code) __attribute__ ((noreturn)); @@ -246,6 +287,11 @@ unchanged: + if (pchild) { + apr_pool_destroy(pchild); + } ++ ++ if (one_process) { ++ itk_note_child_killed(/* slot */ 0, 0, 0); ++ } ++ + ap_mpm_pod_close(pod); + chdir_for_gprof(); + exit(code); @@ -257,13 +303,13 @@ unchanged: + if (rv != APR_SUCCESS) { + const char *msg = "couldn't grab the accept mutex"; + -+ if (ap_my_generation != ++ if (retained->my_generation != + ap_scoreboard_image->global->running_generation) { -+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg); ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(00143) "%s", msg); + clean_child_exit(0); + } + else { -+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg); ++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(00144) "%s", msg); + exit(APEXIT_CHILDFATAL); + } + } @@ -275,16 +321,16 @@ unchanged: + if (rv != APR_SUCCESS) { + const char *msg = "couldn't release the accept mutex"; + -+ if (ap_my_generation != ++ if (retained->my_generation != + ap_scoreboard_image->global->running_generation) { -+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg); ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(00145) "%s", msg); + /* don't exit here... we have a connection to + * process, after which point we'll see that the + * generation changed and we'll exit cleanly + */ + } + else { -+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg); ++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(00146) "%s", msg); + exit(APEXIT_CHILDFATAL); + } + } @@ -301,74 +347,63 @@ unchanged: +#define SAFE_ACCEPT(stmt) do {stmt;} while(0) +#endif + -+AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) ++static int itk_query(int query_code, int *result, apr_status_t *rv) +{ ++ *rv = APR_SUCCESS; + switch(query_code){ + case AP_MPMQ_MAX_DAEMON_USED: + *result = ap_daemons_limit; -+ return APR_SUCCESS; ++ break; + case AP_MPMQ_IS_THREADED: + *result = AP_MPMQ_NOT_SUPPORTED; -+ return APR_SUCCESS; ++ break; + case AP_MPMQ_IS_FORKED: + *result = AP_MPMQ_DYNAMIC; -+ return APR_SUCCESS; ++ break; + case AP_MPMQ_HARD_LIMIT_DAEMONS: + *result = server_limit; -+ return APR_SUCCESS; ++ break; + case AP_MPMQ_HARD_LIMIT_THREADS: + *result = HARD_THREAD_LIMIT; -+ return APR_SUCCESS; ++ break; + case AP_MPMQ_MAX_THREADS: -+ *result = 0; -+ return APR_SUCCESS; ++ *result = 1; ++ break; + case AP_MPMQ_MIN_SPARE_DAEMONS: + *result = ap_daemons_min_free; -+ return APR_SUCCESS; ++ break; + case AP_MPMQ_MIN_SPARE_THREADS: + *result = 0; -+ return APR_SUCCESS; ++ break; + case AP_MPMQ_MAX_SPARE_DAEMONS: + *result = ap_daemons_max_free; -+ return APR_SUCCESS; ++ break; + case AP_MPMQ_MAX_SPARE_THREADS: + *result = 0; -+ return APR_SUCCESS; ++ break; + case AP_MPMQ_MAX_REQUESTS_DAEMON: + *result = ap_max_requests_per_child; -+ return APR_SUCCESS; ++ break; + case AP_MPMQ_MAX_DAEMONS: -+ *result = server_limit; -+ return APR_SUCCESS; ++ *result = ap_daemons_limit; ++ break; + case AP_MPMQ_MPM_STATE: + *result = mpm_state; -+ return APR_SUCCESS; ++ break; ++ case AP_MPMQ_GENERATION: ++ *result = retained->my_generation; ++ break; ++ default: ++ *rv = APR_ENOTIMPL; ++ break; + } -+ return APR_ENOTIMPL; ++ return OK; +} + -+#if defined(NEED_WAITPID) -+/* -+ Systems without a real waitpid sometimes lose a child's exit while waiting -+ for another. Search through the scoreboard for missing children. -+ */ -+int reap_children(int *exitcode, apr_exit_why_e *status) ++static const char *itk_get_name(void) +{ -+ int n, pid; -+ -+ for (n = 0; n < ap_max_daemons_limit; ++n) { -+ if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD && -+ kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) { -+ ap_update_child_status_from_indexes(n, 0, SERVER_DEAD, NULL); -+ /* just mark it as having a successful exit status */ -+ *status = APR_PROC_EXIT; -+ *exitcode = 0; -+ return(pid); -+ } -+ } -+ return 0; ++ return "itk"; +} -+#endif + +/***************************************************************** + * Connection structures and accounting... @@ -379,19 +414,20 @@ unchanged: + clean_child_exit(0); +} + ++/* volatile because they're updated from a signal handler */ ++static int volatile shutdown_pending; ++static int volatile restart_pending; ++static int volatile die_now = 0; ++ +static void stop_listening(int sig) +{ ++ mpm_state = AP_MPMQ_STOPPING; + ap_close_listeners(); + + /* For a graceful stop, we want the child to exit when done */ + die_now = 1; +} + -+/* volatile just in case */ -+static int volatile shutdown_pending; -+static int volatile restart_pending; -+static int volatile is_graceful; -+ +static void sig_term(int sig) +{ + if (shutdown_pending == 1) { @@ -401,8 +437,9 @@ unchanged: + */ + return; + } ++ mpm_state = AP_MPMQ_STOPPING; + shutdown_pending = 1; -+ is_graceful = (sig == AP_SIG_GRACEFUL_STOP); ++ retained->is_graceful = (sig == AP_SIG_GRACEFUL_STOP); +} + +/* restart() is the signal handler for SIGHUP and AP_SIG_GRACEFUL @@ -414,8 +451,9 @@ unchanged: + /* Probably not an error - don't bother reporting it */ + return; + } ++ mpm_state = AP_MPMQ_STOPPING; + restart_pending = 1; -+ is_graceful = (sig == AP_SIG_GRACEFUL); ++ retained->is_graceful = (sig == AP_SIG_GRACEFUL); +} + +static void set_signals(void) @@ -434,30 +472,33 @@ unchanged: + + sa.sa_handler = sig_term; + if (sigaction(SIGTERM, &sa, NULL) < 0) -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)"); ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00147) "sigaction(SIGTERM)"); +#ifdef AP_SIG_GRACEFUL_STOP + if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0) -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00148) + "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")"); +#endif +#ifdef SIGINT + if (sigaction(SIGINT, &sa, NULL) < 0) -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)"); ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00149) "sigaction(SIGINT)"); +#endif +#ifdef SIGXCPU + sa.sa_handler = SIG_DFL; + if (sigaction(SIGXCPU, &sa, NULL) < 0) -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)"); ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00150) "sigaction(SIGXCPU)"); +#endif +#ifdef SIGXFSZ -+ sa.sa_handler = SIG_DFL; ++ /* For systems following the LFS standard, ignoring SIGXFSZ allows ++ * a write() beyond the 2GB limit to fail gracefully with E2BIG ++ * rather than terminate the process. */ ++ sa.sa_handler = SIG_IGN; + if (sigaction(SIGXFSZ, &sa, NULL) < 0) -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)"); ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00151) "sigaction(SIGXFSZ)"); +#endif +#ifdef SIGPIPE + sa.sa_handler = SIG_IGN; + if (sigaction(SIGPIPE, &sa, NULL) < 0) -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)"); ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00152) "sigaction(SIGPIPE)"); +#endif + + /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy @@ -467,16 +508,16 @@ unchanged: + sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL); + sa.sa_handler = restart; + if (sigaction(SIGHUP, &sa, NULL) < 0) -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)"); ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00153) "sigaction(SIGHUP)"); + if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0) -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")"); ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00154) "sigaction(" AP_SIG_GRACEFUL_STRING ")"); +#else + if (!one_process) { +#ifdef SIGXCPU + apr_signal(SIGXCPU, SIG_DFL); +#endif /* SIGXCPU */ +#ifdef SIGXFSZ -+ apr_signal(SIGXFSZ, SIG_DFL); ++ apr_signal(SIGXFSZ, SIG_IGN); +#endif /* SIGXFSZ */ + } + @@ -506,16 +547,12 @@ unchanged: +static int requests_this_child; +static int num_listensocks = 0; + -+ -+int ap_graceful_stop_signalled(void) -+{ -+ /* not ever called anymore... */ -+ return 0; -+} -+ -+ +static void child_main(int child_num_arg) +{ ++#if APR_HAS_THREADS ++ apr_thread_t *thd = NULL; ++ apr_os_thread_t osthd; ++#endif + apr_pool_t *ptrans; + apr_allocator_t *allocator; + apr_status_t status; @@ -525,21 +562,23 @@ unchanged: + ap_sb_handle_t *sbh; + apr_bucket_alloc_t *bucket_alloc; + int last_poll_idx = 0; ++ const char *lockfile; + +#if HAVE_LIBCAP + cap_t caps; + cap_value_t suidcaps[] = { + CAP_SETUID, + CAP_SETGID, -+ CAP_DAC_READ_SEARCH, ++ CAP_DAC_READ_SEARCH, + CAP_SYS_NICE, + }; -+#endif ++#endif + + mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this + * child initializes + */ + ++ ap_running_under_mpm_itk = 1; + my_child_num = child_num_arg; + ap_my_pid = getpid(); + requests_this_child = 0; @@ -553,17 +592,28 @@ unchanged: + apr_allocator_max_free_set(allocator, ap_max_mem_free); + apr_pool_create_ex(&pchild, pconf, NULL, allocator); + apr_allocator_owner_set(allocator, pchild); ++ apr_pool_tag(pchild, "pchild"); ++ ++#if APR_HAS_THREADS ++ osthd = apr_os_thread_current(); ++ apr_os_thread_put(&thd, &osthd, pchild); ++#endif + + apr_pool_create(&ptrans, pchild); + apr_pool_tag(ptrans, "transaction"); + + /* needs to be done before we switch UIDs so we have permissions */ + ap_reopen_scoreboard(pchild, NULL, 0); -+ status = apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild); ++ lockfile = apr_proc_mutex_lockfile(accept_mutex); ++ status = apr_proc_mutex_child_init(&accept_mutex, ++ lockfile, ++ pchild); + if (status != APR_SUCCESS) { -+ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, ++ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, APLOGNO(00155) + "Couldn't initialize cross-process lock in child " -+ "(%s) (%d)", ap_lock_fname, ap_accept_lock_mech); ++ "(%s) (%s)", ++ lockfile ? lockfile : "none", ++ apr_proc_mutex_name(accept_mutex)); + clean_child_exit(APEXIT_CHILDFATAL); + } + @@ -574,8 +624,12 @@ unchanged: + (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL); + + /* Set up the pollfd array */ -+ /* ### check the status */ -+ (void) apr_pollset_create(&pollset, num_listensocks, pchild, 0); ++ status = apr_pollset_create(&pollset, num_listensocks, pchild, 0); ++ if (status != APR_SUCCESS) { ++ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, APLOGNO(00156) ++ "Couldn't create pollset in child; check system or user limits"); ++ clean_child_exit(APEXIT_CHILDSICK); /* assume temporary resource issue */ ++ } + + for (lr = ap_listeners, i = num_listensocks; i--; lr = lr->next) { + apr_pollfd_t pfd = { 0 }; @@ -585,15 +639,21 @@ unchanged: + pfd.reqevents = APR_POLLIN; + pfd.client_data = lr; + -+ /* ### check the status */ -+ (void) apr_pollset_add(pollset, &pfd); ++ status = apr_pollset_add(pollset, &pfd); ++ if (status != APR_SUCCESS) { ++ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, APLOGNO(00157) ++ "Couldn't add listener to pollset; check system or user limits"); ++ clean_child_exit(APEXIT_CHILDSICK); ++ } ++ ++ lr->accept_func = ap_unixd_accept; + } + +#if HAVE_LIBCAP + /* Drop as many privileges as we can. We'll still + * access files with uid=0, and we can setuid() to anything, but + * at least there's tons of other evilness (like loading kernel -+ * modules) we can't do directly. (The setuid() capability will ++ * modules) we can't do directly. (The setuid() capability will + * go away automatically when we setuid() or exec() -- the former + * is likely to come first.) + */ @@ -603,7 +663,7 @@ unchanged: + cap_set_flag(caps, CAP_EFFECTIVE, sizeof(suidcaps)/sizeof(cap_value_t), suidcaps, CAP_SET); + cap_set_proc(caps); + cap_free(caps); -+#endif ++#endif + + mpm_state = AP_MPMQ_RUNNING; + @@ -646,19 +706,23 @@ unchanged: + apr_int32_t numdesc; + const apr_pollfd_t *pdesc; + -+ /* timeout == -1 == wait forever */ -+ status = apr_pollset_poll(pollset, -1, &numdesc, &pdesc); ++ /* check for termination first so we don't sleep for a while in ++ * poll if already signalled ++ */ ++ if (die_now /* in graceful stop/restart */ ++ || (one_process && shutdown_pending)) { ++ SAFE_ACCEPT(accept_mutex_off()); ++ clean_child_exit(0); ++ } ++ ++ /* timeout == 10 seconds to avoid a hang at graceful restart/stop ++ * caused by the closing of sockets by the signal handler ++ */ ++ status = apr_pollset_poll(pollset, apr_time_from_sec(10), ++ &numdesc, &pdesc); + if (status != APR_SUCCESS) { -+ if (APR_STATUS_IS_EINTR(status)) { -+ if (one_process && shutdown_pending) { -+ return; -+ } -+ else if (die_now) { -+ /* In graceful stop/restart; drop the mutex -+ * and terminate the child. */ -+ SAFE_ACCEPT(accept_mutex_off()); -+ clean_child_exit(0); -+ } ++ if (APR_STATUS_IS_TIMEUP(status) || ++ APR_STATUS_IS_EINTR(status)) { + continue; + } + /* Single Unix documents select as returning errnos @@ -668,7 +732,7 @@ unchanged: + * occasionally, and we'd loop forever due to it. + */ + ap_log_error(APLOG_MARK, APLOG_ERR, status, -+ ap_server_conf, "apr_pollset_poll: (listen)"); ++ ap_server_conf, APLOGNO(00158) "apr_pollset_poll: (listen)"); + SAFE_ACCEPT(accept_mutex_off()); + clean_child_exit(1); + } @@ -726,13 +790,15 @@ unchanged: + ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "fork: Unable to fork new process"); + break; + case 0: /* child */ -+ apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild); + current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc); + if (current_conn) { ++#if APR_HAS_THREADS ++ current_conn->current_thread = thd; ++#endif + ap_process_connection(current_conn, csd); + ap_lingering_close(current_conn); + } -+ exit(0); ++ clean_child_exit(0); + default: /* parent; just wait for child to be done */ + do { + child_pid = waitpid(pid, &status, 0); @@ -760,7 +826,7 @@ unchanged: + if (ap_mpm_pod_check(pod) == APR_SUCCESS) { /* selected as idle? */ + die_now = 1; + } -+ else if (ap_my_generation != ++ else if (retained->my_generation != + ap_scoreboard_image->global->running_generation) { /* restart? */ + /* yeah, this could be non-graceful restart, in which case the + * parent will kill us soon enough, but why bother checking? @@ -772,6 +838,7 @@ unchanged: + if (getuid()) + die_now = 1; + } ++ apr_pool_clear(ptrans); /* kludge to avoid crash in APR reslist cleanup code */ + clean_child_exit(0); +} + @@ -780,8 +847,8 @@ unchanged: +{ + int pid; + -+ if (slot + 1 > ap_max_daemons_limit) { -+ ap_max_daemons_limit = slot + 1; ++ if (slot + 1 > retained->max_daemons_limit) { ++ retained->max_daemons_limit = slot + 1; + } + + if (one_process) { @@ -792,8 +859,9 @@ unchanged: + apr_signal(SIGQUIT, SIG_DFL); +#endif + apr_signal(SIGTERM, sig_term); ++ itk_note_child_started(slot, getpid()); + child_main(slot); -+ return 0; ++ /* NOTREACHED */ + } + + (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING, @@ -802,13 +870,11 @@ unchanged: + +#ifdef _OSD_POSIX + /* BS2000 requires a "special" version of fork() before a setuid() call */ -+ if ((pid = os_fork(unixd_config.user_name)) == -1) { -+#elif defined(TPF) -+ if ((pid = os_fork(s, slot)) == -1) { ++ if ((pid = os_fork(ap_unixd_config.user_name)) == -1) { +#else + if ((pid = fork()) == -1) { +#endif -+ ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process"); ++ ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, APLOGNO(00159) "fork: Unable to fork new process"); + + /* fork didn't succeed. Fix the scoreboard or else + * it will say SERVER_STARTING forever and ever @@ -833,8 +899,8 @@ unchanged: + int status = bindprocessor(BINDPROCESS, (int)getpid(), + PROCESSOR_CLASS_ANY); + if (status != OK) { -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, -+ ap_server_conf, "processor unbind failed %d", status); ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, errno, ++ ap_server_conf, APLOGNO(00160) "processor unbind failed"); + } +#endif + RAISE_SIGSTOP(MAKE_CHILD); @@ -851,7 +917,7 @@ unchanged: + child_main(slot); + } + -+ ap_scoreboard_image->parent[slot].pid = pid; ++ itk_note_child_started(slot, pid); + + return 0; +} @@ -873,23 +939,9 @@ unchanged: + } +} + -+ -+/* -+ * idle_spawn_rate is the number of children that will be spawned on the -+ * next maintenance cycle if there aren't enough idle servers. It is -+ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by -+ * without the need to spawn. -+ */ -+static int idle_spawn_rate = 1; -+#ifndef MAX_SPAWN_RATE -+#define MAX_SPAWN_RATE (32) -+#endif -+static int hold_off_on_exponential_spawning; -+ +static void perform_idle_server_maintenance(apr_pool_t *p) +{ + int i; -+ int to_kill; + int idle_count; + worker_score *ws; + int free_length; @@ -900,7 +952,6 @@ unchanged: + /* initialize the free_list */ + free_length = 0; + -+ to_kill = -1; + idle_count = 0; + last_non_dead = -1; + total_non_dead = 0; @@ -908,13 +959,13 @@ unchanged: + for (i = 0; i < ap_daemons_limit; ++i) { + int status; + -+ if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate) ++ if (i >= retained->max_daemons_limit && free_length == retained->idle_spawn_rate) + break; + ws = &ap_scoreboard_image->servers[i][0]; + status = ws->status; + if (status == SERVER_DEAD) { + /* try to keep children numbers as low as possible */ -+ if (free_length < idle_spawn_rate) { ++ if (free_length < retained->idle_spawn_rate) { + free_slots[free_length] = i; + ++free_length; + } @@ -928,77 +979,58 @@ unchanged: + */ + if (status <= SERVER_READY) { + ++ idle_count; -+ /* always kill the highest numbered child if we have to... -+ * no really well thought out reason ... other than observing -+ * the server behaviour under linux where lower numbered children -+ * tend to service more hits (and hence are more likely to have -+ * their data in cpu caches). -+ */ -+ to_kill = i; + } + + ++total_non_dead; + last_non_dead = i; + } + } -+ ap_max_daemons_limit = last_non_dead + 1; ++ retained->max_daemons_limit = last_non_dead + 1; + if (idle_count > ap_daemons_max_free) { + /* kill off one child... we use the pod because that'll cause it to + * shut down gracefully, in case it happened to pick up a request + * while we were counting + */ + ap_mpm_pod_signal(pod); -+ idle_spawn_rate = 1; ++ retained->idle_spawn_rate = 1; + } + else if (idle_count < ap_daemons_min_free) { + /* terminate the free list */ + if (free_length == 0) { + /* only report this condition once */ -+ static int reported = 0; -+ -+ if (!reported) { -+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, -+ "server reached MaxClients setting, consider" -+ " raising the MaxClients setting"); -+ reported = 1; ++ if (!retained->maxclients_reported) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00161) ++ "server reached MaxRequestWorkers setting, consider" ++ " raising the MaxRequestWorkers setting"); ++ retained->maxclients_reported = 1; + } -+ idle_spawn_rate = 1; ++ retained->idle_spawn_rate = 1; + } + else { -+ if (idle_spawn_rate >= 8) { -+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, ++ if (retained->idle_spawn_rate >= 8) { ++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00162) + "server seems busy, (you may need " + "to increase StartServers, or Min/MaxSpareServers), " + "spawning %d children, there are %d idle, and " -+ "%d total children", idle_spawn_rate, ++ "%d total children", retained->idle_spawn_rate, + idle_count, total_non_dead); + } + for (i = 0; i < free_length; ++i) { -+#ifdef TPF -+ if (make_child(ap_server_conf, free_slots[i]) == -1) { -+ if(free_length == 1) { -+ shutdown_pending = 1; -+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, ap_server_conf, -+ "No active child processes: shutting down"); -+ } -+ } -+#else + make_child(ap_server_conf, free_slots[i]); -+#endif /* TPF */ + } + /* the next time around we want to spawn twice as many if this + * wasn't good enough, but not if we've just done a graceful + */ -+ if (hold_off_on_exponential_spawning) { -+ --hold_off_on_exponential_spawning; ++ if (retained->hold_off_on_exponential_spawning) { ++ --retained->hold_off_on_exponential_spawning; + } -+ else if (idle_spawn_rate < MAX_SPAWN_RATE) { -+ idle_spawn_rate *= 2; ++ else if (retained->idle_spawn_rate < MAX_SPAWN_RATE) { ++ retained->idle_spawn_rate *= 2; + } + } + } + else { -+ idle_spawn_rate = 1; ++ retained->idle_spawn_rate = 1; + } +} + @@ -1006,7 +1038,7 @@ unchanged: + * Executive routines. + */ + -+int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) ++static int itk_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) +{ + int index; + int remaining_children_to_start; @@ -1014,61 +1046,32 @@ unchanged: + + ap_log_pid(pconf, ap_pid_fname); + -+ first_server_limit = server_limit; -+ if (changed_limit_at_restart) { -+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, -+ "WARNING: Attempt to change ServerLimit " -+ "ignored during restart"); -+ changed_limit_at_restart = 0; -+ } -+ + /* Initialize cross-process accept lock */ -+ ap_lock_fname = apr_psprintf(_pconf, "%s.%" APR_PID_T_FMT, -+ ap_server_root_relative(_pconf, ap_lock_fname), -+ ap_my_pid); -+ -+ rv = apr_proc_mutex_create(&accept_mutex, ap_lock_fname, -+ ap_accept_lock_mech, _pconf); ++ rv = ap_proc_mutex_create(&accept_mutex, NULL, AP_ACCEPT_MUTEX_TYPE, NULL, ++ s, _pconf, 0); + if (rv != APR_SUCCESS) { -+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, -+ "Couldn't create accept lock (%s) (%d)", -+ ap_lock_fname, ap_accept_lock_mech); + mpm_state = AP_MPMQ_STOPPING; -+ return 1; ++ return DONE; + } + -+#if APR_USE_SYSVSEM_SERIALIZE -+ if (ap_accept_lock_mech == APR_LOCK_DEFAULT || -+ ap_accept_lock_mech == APR_LOCK_SYSVSEM) { -+#else -+ if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) { -+#endif -+ rv = unixd_set_proc_mutex_perms(accept_mutex); -+ if (rv != APR_SUCCESS) { -+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, -+ "Couldn't set permissions on cross-process lock; " -+ "check User and Group directives"); -+ mpm_state = AP_MPMQ_STOPPING; -+ return 1; -+ } -+ } -+ -+ if (!is_graceful) { ++ if (!retained->is_graceful) { + if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) { + mpm_state = AP_MPMQ_STOPPING; -+ return 1; ++ return DONE; + } + /* fix the generation number in the global score; we just got a new, + * cleared scoreboard + */ -+ ap_scoreboard_image->global->running_generation = ap_my_generation; ++ ap_scoreboard_image->global->running_generation = retained->my_generation; + } + ++ restart_pending = shutdown_pending = 0; + set_signals(); + + if (one_process) { + AP_MONCONTROL(1); + make_child(ap_server_conf, 0); ++ /* NOTREACHED */ + } + else { + if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */ @@ -1086,7 +1089,7 @@ unchanged: + if (remaining_children_to_start > ap_daemons_limit) { + remaining_children_to_start = ap_daemons_limit; + } -+ if (!is_graceful) { ++ if (!retained->is_graceful) { + startup_children(remaining_children_to_start); + remaining_children_to_start = 0; + } @@ -1094,21 +1097,19 @@ unchanged: + /* give the system some time to recover before kicking into + * exponential mode + */ -+ hold_off_on_exponential_spawning = 10; ++ retained->hold_off_on_exponential_spawning = 10; + } + -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00163) + "%s configured -- resuming normal operations", + ap_get_server_description()); -+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, ++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00164) + "Server built: %s", ap_get_server_built()); -+#ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH -+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, -+ "AcceptMutex: %s (default: %s)", ++ ap_log_command_line(plog, s); ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00165) ++ "Accept mutex: %s (default: %s)", + apr_proc_mutex_name(accept_mutex), + apr_proc_mutex_defname()); -+#endif -+ restart_pending = shutdown_pending = 0; + + mpm_state = AP_MPMQ_RUNNING; + @@ -1119,7 +1120,7 @@ unchanged: + /* this is a memory leak, but I'll fix it later. */ + apr_proc_t pid; + -+ ap_wait_or_timeout(&exitwhy, &status, &pid, pconf); ++ ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf); + + /* XXX: if it takes longer than 1 second for all our children + * to start up and get into IDLE state then we may spawn an @@ -1127,21 +1128,37 @@ unchanged: + */ + if (pid.pid != -1) { + processed_status = ap_process_child_status(&pid, exitwhy, status); ++ child_slot = ap_find_child_by_pid(&pid); + if (processed_status == APEXIT_CHILDFATAL) { -+ mpm_state = AP_MPMQ_STOPPING; -+ return 1; ++ /* fix race condition found in PR 39311 ++ * A child created at the same time as a graceful happens ++ * can find the lock missing and create a fatal error. ++ * It is not fatal for the last generation to be in this state. ++ */ ++ if (child_slot < 0 ++ || ap_get_scoreboard_process(child_slot)->generation ++ == retained->my_generation) { ++ mpm_state = AP_MPMQ_STOPPING; ++ return DONE; ++ } ++ else { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, APLOGNO(00166) ++ "Ignoring fatal error in child of previous " ++ "generation (pid %ld).", ++ (long)pid.pid); ++ } + } + + /* non-fatal death... note that it's gone in the scoreboard. */ -+ child_slot = find_child_by_pid(&pid); + if (child_slot >= 0) { + (void) ap_update_child_status_from_indexes(child_slot, 0, SERVER_DEAD, + (request_rec *) NULL); ++ itk_note_child_killed(child_slot, 0, 0); + if (processed_status == APEXIT_CHILDSICK) { + /* child detected a resource shortage (E[NM]FILE, ENOBUFS, etc) + * cut the fork rate to the minimum + */ -+ idle_spawn_rate = 1; ++ retained->idle_spawn_rate = 1; + } + else if (remaining_children_to_start + && child_slot < ap_daemons_limit) { @@ -1157,13 +1174,13 @@ unchanged: + /* handled */ +#endif + } -+ else if (is_graceful) { ++ else if (retained->is_graceful) { + /* Great, we've probably just lost a slot in the + * scoreboard. Somehow we don't know about this + * child. + */ + ap_log_error(APLOG_MARK, APLOG_WARNING, -+ 0, ap_server_conf, ++ 0, ap_server_conf, APLOGNO(00167) + "long lost child came home! (pid %ld)", (long)pid.pid); + } + /* Don't perform idle maintenance when a child dies, @@ -1188,40 +1205,27 @@ unchanged: + } + + perform_idle_server_maintenance(pconf); -+#ifdef TPF -+ shutdown_pending = os_check_server(tpf_server_name); -+ ap_check_signals(); -+ sleep(1); -+#endif /*TPF */ + } + } /* one_process */ + + mpm_state = AP_MPMQ_STOPPING; + -+ if (shutdown_pending && !is_graceful) { ++ if (shutdown_pending && !retained->is_graceful) { + /* Time to shut down: + * Kill child processes, tell them to call child_exit, etc... + */ -+ if (unixd_killpg(getpgrp(), SIGTERM) < 0) { -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM"); ++ if (ap_unixd_killpg(getpgrp(), SIGTERM) < 0) { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00168) "killpg SIGTERM"); + } -+ ap_reclaim_child_processes(1); /* Start with SIGTERM */ ++ ap_reclaim_child_processes(1, /* Start with SIGTERM */ ++ itk_note_child_killed); + + /* cleanup pid file on normal shutdown */ -+ { -+ const char *pidfile = NULL; -+ pidfile = ap_server_root_relative (pconf, ap_pid_fname); -+ if ( pidfile != NULL && unlink(pidfile) == 0) -+ ap_log_error(APLOG_MARK, APLOG_INFO, -+ 0, ap_server_conf, -+ "removed PID file %s (pid=%ld)", -+ pidfile, (long)getpid()); -+ } -+ -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, ++ ap_remove_pid(pconf, ap_pid_fname); ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00169) + "caught SIGTERM, shutting down"); + -+ return 1; ++ return DONE; + } else if (shutdown_pending) { + /* Time to perform a graceful shut down: + * Reap the inactive children, and ask the active ones @@ -1235,7 +1239,7 @@ unchanged: + ap_close_listeners(); + + /* kill off the idle ones */ -+ ap_mpm_pod_killpg(pod, ap_max_daemons_limit); ++ ap_mpm_pod_killpg(pod, retained->max_daemons_limit); + + /* Send SIGUSR1 to the active children */ + active_children = 0; @@ -1248,20 +1252,11 @@ unchanged: + } + + /* Allow each child which actually finished to exit */ -+ ap_relieve_child_processes(); ++ ap_relieve_child_processes(itk_note_child_killed); + + /* cleanup pid file */ -+ { -+ const char *pidfile = NULL; -+ pidfile = ap_server_root_relative (pconf, ap_pid_fname); -+ if ( pidfile != NULL && unlink(pidfile) == 0) -+ ap_log_error(APLOG_MARK, APLOG_INFO, -+ 0, ap_server_conf, -+ "removed PID file %s (pid=%ld)", -+ pidfile, (long)getpid()); -+ } -+ -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, ++ ap_remove_pid(pconf, ap_pid_fname); ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00170) + "caught " AP_SIG_GRACEFUL_STOP_STRING ", shutting down gracefully"); + + if (ap_graceful_shutdown_timeout) { @@ -1276,7 +1271,7 @@ unchanged: + sleep(1); + + /* Relieve any children which have now exited */ -+ ap_relieve_child_processes(); ++ ap_relieve_child_processes(itk_note_child_killed); + + active_children = 0; + for (index = 0; index < ap_daemons_limit; ++index) { @@ -1293,9 +1288,9 @@ unchanged: + * way, try and make sure that all of our processes are + * really dead. + */ -+ unixd_killpg(getpgrp(), SIGTERM); ++ ap_unixd_killpg(getpgrp(), SIGTERM); + -+ return 1; ++ return DONE; + } + + /* we've been told to restart */ @@ -1303,22 +1298,22 @@ unchanged: + apr_signal(AP_SIG_GRACEFUL, SIG_IGN); + if (one_process) { + /* not worth thinking about */ -+ return 1; ++ return DONE; + } + + /* advance to the next generation */ + /* XXX: we really need to make sure this new generation number isn't in + * use by any of the children. + */ -+ ++ap_my_generation; -+ ap_scoreboard_image->global->running_generation = ap_my_generation; ++ ++retained->my_generation; ++ ap_scoreboard_image->global->running_generation = retained->my_generation; + -+ if (is_graceful) { -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, ++ if (retained->is_graceful) { ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00171) + "Graceful restart requested, doing restart"); + + /* kill off the idle ones */ -+ ap_mpm_pod_killpg(pod, ap_max_daemons_limit); ++ ap_mpm_pod_killpg(pod, retained->max_daemons_limit); + + /* This is mostly for debugging... so that we know what is still + * gracefully dealing with existing request. This will break @@ -1341,15 +1336,16 @@ unchanged: + } + else { + /* Kill 'em off */ -+ if (unixd_killpg(getpgrp(), SIGHUP) < 0) { -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGHUP"); ++ if (ap_unixd_killpg(getpgrp(), SIGHUP) < 0) { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00172) "killpg SIGHUP"); + } -+ ap_reclaim_child_processes(0); /* Not when just starting up */ -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, ++ ap_reclaim_child_processes(0, /* Not when just starting up */ ++ itk_note_child_killed); ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00173) + "SIGHUP received. Attempting to restart"); + } + -+ return 0; ++ return OK; +} + +/* This really should be a post_config hook, but the error log is already @@ -1357,20 +1353,29 @@ unchanged: + */ +static int itk_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) +{ ++ int startup = 0; ++ int level_flags = 0; + apr_status_t rv; + + pconf = p; -+ ap_server_conf = s; ++ ++ /* the reverse of pre_config, we want this only the first time around */ ++ if (retained->module_loads == 1) { ++ startup = 1; ++ level_flags |= APLOG_STARTUP; ++ } + + if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) { -+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_STARTUP, 0, -+ NULL, "no listening sockets available, shutting down"); ++ ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0, ++ (startup ? NULL : s), ++ "no listening sockets available, shutting down"); + return DONE; + } + + if ((rv = ap_mpm_pod_open(pconf, &pod))) { -+ ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_STARTUP, rv, NULL, -+ "Could not open pipe-of-death."); ++ ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv, ++ (startup ? NULL : s), ++ "could not open pipe-of-death"); + return DONE; + } + return OK; @@ -1378,9 +1383,9 @@ unchanged: + +static int itk_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp) +{ -+ static int restart_num = 0; + int no_detach, debug, foreground; + apr_status_t rv; ++ const char *userdata_key = "mpm_itk_module"; + + mpm_state = AP_MPMQ_STARTING; + @@ -1397,38 +1402,161 @@ unchanged: + foreground = ap_exists_config_define("FOREGROUND"); + } + -+ /* sigh, want this only the second time around */ -+ if (restart_num++ == 1) { -+ is_graceful = 0; ++ ap_mutex_register(p, AP_ACCEPT_MUTEX_TYPE, NULL, APR_LOCK_DEFAULT, 0); + ++ /* sigh, want this only the second time around */ ++ retained = ap_retained_data_get(userdata_key); ++ if (!retained) { ++ retained = ap_retained_data_create(userdata_key, sizeof(*retained)); ++ retained->max_daemons_limit = -1; ++ retained->idle_spawn_rate = 1; ++ } ++ ++retained->module_loads; ++ if (retained->module_loads == 2) { + if (!one_process && !foreground) { ++ /* before we detach, setup crash handlers to log to errorlog */ ++ ap_fatal_signal_setup(ap_server_conf, pconf); + rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND + : APR_PROC_DETACH_DAEMONIZE); + if (rv != APR_SUCCESS) { -+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, ++ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00174) + "apr_proc_detach failed"); + return HTTP_INTERNAL_SERVER_ERROR; + } + } -+ -+ parent_pid = ap_my_pid = getpid(); + } + -+ unixd_pre_config(ptemp); ++ parent_pid = ap_my_pid = getpid(); ++ + ap_listen_pre_config(); + ap_daemons_to_start = DEFAULT_START_DAEMON; + ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON; + ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON; ++ server_limit = DEFAULT_SERVER_LIMIT; + ap_daemons_limit = server_limit; -+ ap_pid_fname = DEFAULT_PIDLOG; -+ ap_lock_fname = DEFAULT_LOCKFILE; -+ ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; + ap_extended_status = 0; -+#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE -+ ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED; -+#endif + -+ apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir)); ++ return OK; ++} ++ ++static int itk_check_config(apr_pool_t *p, apr_pool_t *plog, ++ apr_pool_t *ptemp, server_rec *s) ++{ ++ int startup = 0; ++ ++ /* the reverse of pre_config, we want this only the first time around */ ++ if (retained->module_loads == 1) { ++ startup = 1; ++ } ++ ++ if (server_limit > MAX_SERVER_LIMIT) { ++ if (startup) { ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00175) ++ "WARNING: ServerLimit of %d exceeds compile-time " ++ "limit of", server_limit); ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, ++ " %d servers, decreasing to %d.", ++ MAX_SERVER_LIMIT, MAX_SERVER_LIMIT); ++ } else { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00176) ++ "ServerLimit of %d exceeds compile-time limit " ++ "of %d, decreasing to match", ++ server_limit, MAX_SERVER_LIMIT); ++ } ++ server_limit = MAX_SERVER_LIMIT; ++ } ++ else if (server_limit < 1) { ++ if (startup) { ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00177) ++ "WARNING: ServerLimit of %d not allowed, " ++ "increasing to 1.", server_limit); ++ } else { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00178) ++ "ServerLimit of %d not allowed, increasing to 1", ++ server_limit); ++ } ++ server_limit = 1; ++ } ++ ++ /* you cannot change ServerLimit across a restart; ignore ++ * any such attempts ++ */ ++ if (!retained->first_server_limit) { ++ retained->first_server_limit = server_limit; ++ } ++ else if (server_limit != retained->first_server_limit) { ++ /* don't need a startup console version here */ ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00179) ++ "changing ServerLimit to %d from original value of %d " ++ "not allowed during restart", ++ server_limit, retained->first_server_limit); ++ server_limit = retained->first_server_limit; ++ } ++ ++ if (ap_daemons_limit > server_limit) { ++ if (startup) { ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00180) ++ "WARNING: MaxRequestWorkers of %d exceeds ServerLimit " ++ "value of", ap_daemons_limit); ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, ++ " %d servers, decreasing MaxRequestWorkers to %d.", ++ server_limit, server_limit); ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, ++ " To increase, please see the ServerLimit " ++ "directive."); ++ } else { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00181) ++ "MaxRequestWorkers of %d exceeds ServerLimit value " ++ "of %d, decreasing to match", ++ ap_daemons_limit, server_limit); ++ } ++ ap_daemons_limit = server_limit; ++ } ++ else if (ap_daemons_limit < 1) { ++ if (startup) { ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00182) ++ "WARNING: MaxRequestWorkers of %d not allowed, " ++ "increasing to 1.", ap_daemons_limit); ++ } else { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00183) ++ "MaxRequestWorkers of %d not allowed, increasing to 1", ++ ap_daemons_limit); ++ } ++ ap_daemons_limit = 1; ++ } ++ ++ /* ap_daemons_to_start > ap_daemons_limit checked in itk_run() */ ++ if (ap_daemons_to_start < 0) { ++ if (startup) { ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00184) ++ "WARNING: StartServers of %d not allowed, " ++ "increasing to 1.", ap_daemons_to_start); ++ } else { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00185) ++ "StartServers of %d not allowed, increasing to 1", ++ ap_daemons_to_start); ++ } ++ ap_daemons_to_start = 1; ++ } ++ ++ if (ap_daemons_min_free < 1) { ++ if (startup) { ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00186) ++ "WARNING: MinSpareServers of %d not allowed, " ++ "increasing to 1", ap_daemons_min_free); ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, ++ " to avoid almost certain server failure."); ++ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, ++ " Please read the documentation."); ++ } else { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00187) ++ "MinSpareServers of %d not allowed, increasing to 1", ++ ap_daemons_min_free); ++ } ++ ap_daemons_min_free = 1; ++ } ++ ++ /* ap_daemons_max_free < ap_daemons_min_free + 1 checked in itk_run() */ + + return OK; +} @@ -1442,6 +1570,7 @@ unchanged: + + itk_server_conf *sconf = + (itk_server_conf *) ap_get_module_config(r->server->module_config, &mpm_itk_module); ++ itk_per_dir_conf *dconf; + + /* Enforce MaxClientsVhost. */ + if (sconf->max_clients_vhost > 0) { @@ -1460,8 +1589,7 @@ unchanged: + } + } + -+ itk_per_dir_conf *dconf = -+ (itk_per_dir_conf *) ap_get_module_config(r->per_dir_config, &mpm_itk_module); ++ dconf = (itk_per_dir_conf *) ap_get_module_config(r->per_dir_config, &mpm_itk_module); + + strncpy(ap_scoreboard_image->servers[my_child_num][0].vhost, r->server->server_hostname, 31); + ap_scoreboard_image->servers[my_child_num][0].vhost[31] = 0; @@ -1477,9 +1605,51 @@ unchanged: + wanted_username = dconf->username; + + if (wanted_uid == -1 || wanted_gid == -1) { -+ wanted_uid = unixd_config.user_id; -+ wanted_gid = unixd_config.group_id; -+ wanted_username = unixd_config.user_name; ++ wanted_uid = ap_unixd_config.user_id; ++ wanted_gid = ap_unixd_config.group_id; ++ wanted_username = ap_unixd_config.user_name; ++ } ++ ++ /* AssignUserIDExpr and AssignGroupIDExpr override AssignUserID and defaults. */ ++ if (dconf->uid_expr != NULL) { ++ struct passwd *ent; ++ const char *err; ++ wanted_username = ap_expr_str_exec(r, dconf->uid_expr, &err); ++ if (err) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, \ ++ "Error while parsing AssignUserIDExpr expression: %s", ++ err); ++ return HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ if (!(ent = getpwnam(wanted_username))) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, \ ++ "AssignUserIDExpr returned '%s', which is not a valid user name", ++ wanted_username); ++ return HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ wanted_uid = ent->pw_uid; ++ } ++ if (dconf->gid_expr != NULL) { ++ struct group *ent; ++ const char *err; ++ const char *wanted_groupname = ap_expr_str_exec(r, dconf->gid_expr, &err); ++ if (err) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, \ ++ "Error while parsing AssignGroupIDExpr expression: %s", ++ err); ++ return HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ if (!(ent = getgrnam(wanted_groupname))) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, \ ++ "AssignGroupIDExpr returned '%s', which is not a valid group name", ++ wanted_username); ++ return HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ wanted_gid = ent->gr_gid; + } + + if (!err && wanted_uid != -1 && wanted_gid != -1 && (getuid() != wanted_uid || getgid() != wanted_gid)) { @@ -1511,23 +1681,23 @@ unchanged: + +static void itk_hooks(apr_pool_t *p) +{ -+ /* The itk open_logs phase must run before the core's, or stderr ++ /* Our open_logs hook function must run before the core's, or stderr + * will be redirected to a file, and the messages won't print to the + * console. + */ + static const char *const aszSucc[] = {"core.c", NULL}; + -+#ifdef AUX3 -+ (void) set42sig(); -+#endif -+ -+ ap_hook_open_logs(itk_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE); ++ ap_hook_open_logs(itk_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST); + /* we need to set the MPM state before other pre-config hooks use MPM query + * to retrieve it, so register as REALLY_FIRST + */ + ap_hook_pre_config(itk_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST); ++ ap_hook_check_config(itk_check_config, NULL, NULL, APR_HOOK_MIDDLE); ++ ap_hook_mpm(itk_run, NULL, NULL, APR_HOOK_MIDDLE); ++ ap_hook_mpm_query(itk_query, NULL, NULL, APR_HOOK_MIDDLE); ++ ap_hook_mpm_get_name(itk_get_name, NULL, NULL, APR_HOOK_MIDDLE); + -+ /* set the uid as fast as possible, but not before merging per-dit config */ ++ /* set the uid as fast as possible, but not before merging per-dir config */ + ap_hook_header_parser(itk_post_perdir_config, NULL, NULL, APR_HOOK_REALLY_FIRST); +} + @@ -1550,16 +1720,6 @@ unchanged: + } + + ap_daemons_min_free = atoi(arg); -+ if (ap_daemons_min_free <= 0) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: detected MinSpareServers set to non-positive."); -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "Resetting to 1 to avoid almost certain Apache failure."); -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "Please read the documentation."); -+ ap_daemons_min_free = 1; -+ } -+ + return NULL; +} + @@ -1580,76 +1740,88 @@ unchanged: + if (err != NULL) { + return err; + } -+ ++ if (!strcasecmp(cmd->cmd->name, "MaxClients")) { ++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, APLOGNO(00188) ++ "MaxClients is deprecated, use MaxRequestWorkers " ++ "instead."); ++ } + ap_daemons_limit = atoi(arg); -+ if (ap_daemons_limit > server_limit) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: MaxClients of %d exceeds ServerLimit value " -+ "of %d servers,", ap_daemons_limit, server_limit); -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ " lowering MaxClients to %d. To increase, please " -+ "see the ServerLimit", server_limit); -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ " directive."); -+ ap_daemons_limit = server_limit; -+ } -+ else if (ap_daemons_limit < 1) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: Require MaxClients > 0, setting to 1"); -+ ap_daemons_limit = 1; -+ } + return NULL; +} + +static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) +{ -+ int tmp_server_limit; -+ + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err != NULL) { + return err; + } + -+ tmp_server_limit = atoi(arg); -+ /* you cannot change ServerLimit across a restart; ignore -+ * any such attempts -+ */ -+ if (first_server_limit && -+ tmp_server_limit != server_limit) { -+ /* how do we log a message? the error log is a bit bucket at this -+ * point; we'll just have to set a flag so that ap_mpm_run() -+ * logs a warning later -+ */ -+ changed_limit_at_restart = 1; -+ return NULL; -+ } -+ server_limit = tmp_server_limit; -+ -+ if (server_limit > MAX_SERVER_LIMIT) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: ServerLimit of %d exceeds compile time limit " -+ "of %d servers,", server_limit, MAX_SERVER_LIMIT); -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ " lowering ServerLimit to %d.", MAX_SERVER_LIMIT); -+ server_limit = MAX_SERVER_LIMIT; -+ } -+ else if (server_limit < 1) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: Require ServerLimit > 0, setting to 1"); -+ server_limit = 1; -+ } ++ server_limit = atoi(arg); + return NULL; +} + +static const char *assign_user_id (cmd_parms *cmd, void *ptr, const char *user_name, const char *group_name) +{ + itk_per_dir_conf *dconf = (itk_per_dir_conf *) ptr; ++ ++ const char *err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS); ++ if (err) { ++ return err; ++ } ++ + dconf->username = apr_pstrdup(cmd->pool, user_name); + dconf->uid = ap_uname2id(user_name); + dconf->gid = ap_gname2id(group_name); + return NULL; +} + ++static const char *assign_user_id_expr (cmd_parms *cmd, void *ptr, const char *user_name_expr) ++{ ++ itk_per_dir_conf *dconf = (itk_per_dir_conf *) ptr; ++ ++ const char *err; ++ ++ err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS); ++ if (err) { ++ return err; ++ } ++ ++ dconf->uid_expr = ap_expr_parse_cmd_mi(cmd, ++ user_name_expr, ++ AP_EXPR_FLAG_STRING_RESULT, ++ &err, ++ NULL, ++ AP_CORE_MODULE_INDEX); ++ if (err) { ++ return err; ++ } ++ ++ return NULL; ++} ++ ++static const char *assign_group_id_expr (cmd_parms *cmd, void *ptr, const char *group_name_expr) ++{ ++ itk_per_dir_conf *dconf = (itk_per_dir_conf *) ptr; ++ ++ const char *err; ++ ++ err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS); ++ if (err) { ++ return err; ++ } ++ ++ dconf->gid_expr = ap_expr_parse_cmd_mi(cmd, ++ group_name_expr, ++ AP_EXPR_FLAG_STRING_RESULT, ++ &err, ++ NULL, ++ AP_CORE_MODULE_INDEX); ++ if (err) { ++ return err; ++ } ++ return NULL; ++} ++ +static const char *set_max_clients_vhost (cmd_parms *cmd, void *dummy, const char *arg) +{ + itk_server_conf *sconf = @@ -1680,7 +1852,6 @@ unchanged: +} + +static const command_rec itk_cmds[] = { -+UNIX_DAEMON_COMMANDS, +LISTEN_COMMANDS, +AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF, + "Number of child processes launched at server startup"), @@ -1689,11 +1860,17 @@ unchanged: +AP_INIT_TAKE1("MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF, + "Maximum number of idle children"), +AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF, ++ "Deprecated name of MaxRequestWorkers"), ++AP_INIT_TAKE1("MaxRequestWorkers", set_max_clients, NULL, RSRC_CONF, + "Maximum number of children alive at the same time"), +AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF, -+ "Maximum value of MaxClients for this run of Apache"), ++ "Maximum value of MaxRequestWorkers for this run of Apache"), +AP_INIT_TAKE2("AssignUserID", assign_user_id, NULL, RSRC_CONF|ACCESS_CONF, + "Tie a virtual host to a specific child process."), ++AP_INIT_RAW_ARGS("AssignUserIDExpr", assign_user_id_expr, NULL, RSRC_CONF|ACCESS_CONF, ++ "Choose user ID given an expression. Will override AssignUserID."), ++AP_INIT_RAW_ARGS("AssignGroupIDExpr", assign_group_id_expr, NULL, RSRC_CONF|ACCESS_CONF, ++ "Choose group ID given an expression. Will override AssignUserID."), +AP_INIT_TAKE1("MaxClientsVHost", set_max_clients_vhost, NULL, RSRC_CONF, + "Maximum number of children alive at the same time for this virtual host."), +AP_INIT_TAKE1("NiceValue", set_nice_value, NULL, RSRC_CONF|ACCESS_CONF, @@ -1708,6 +1885,7 @@ unchanged: + itk_per_dir_conf *c = (itk_per_dir_conf *) + apr_pcalloc(p, sizeof(itk_per_dir_conf)); + c->uid = c->gid = -1; ++ c->uid_expr = c->gid_expr = NULL; + c->nice_value = UNSET_NICE_VALUE; + return c; +} @@ -1721,14 +1899,24 @@ unchanged: + itk_per_dir_conf *child = (itk_per_dir_conf *) child_ptr; + + if (child->username != NULL) { -+ c->username = apr_pstrdup(p, child->username); ++ c->username = child->username; + c->uid = child->uid; + c->gid = child->gid; -+ } else if (parent->username != NULL) { -+ c->username = apr_pstrdup(p, parent->username); ++ } else { ++ c->username = parent->username; + c->uid = parent->uid; + c->gid = parent->gid; + } ++ if (child->uid_expr != NULL) { ++ c->uid_expr = child->uid_expr; ++ } else { ++ c->uid_expr = parent->uid_expr; ++ } ++ if (child->gid_expr != NULL) { ++ c->gid_expr = child->gid_expr; ++ } else { ++ c->gid_expr = parent->gid_expr; ++ } + if (child->nice_value != UNSET_NICE_VALUE) { + c->nice_value = child->nice_value; + } else { @@ -1746,9 +1934,9 @@ unchanged: + return c; +} + -+module AP_MODULE_DECLARE_DATA mpm_itk_module = { ++AP_DECLARE_MODULE(mpm_itk) = { + MPM20_MODULE_STUFF, -+ ap_mpm_rewrite_args, /* hook to run before apache parses args */ ++ NULL, /* hook to run before apache parses args */ + itk_create_dir_config, /* create per-directory config structure */ + itk_merge_dir_config, /* merge per-directory config structures */ + itk_create_server_config, /* create per-server config structure */ @@ -1756,80 +1944,11 @@ unchanged: + itk_cmds, /* command apr_table_t */ + itk_hooks, /* register hooks */ +}; +Index: httpd-2.4.2/server/mpm/itk/mpm_default.h +=================================================================== --- /dev/null -+++ server/mpm/experimental/itk/mpm.h -@@ -0,0 +1,68 @@ -+/* Licensed to the Apache Software Foundation (ASF) under one or more -+ * contributor license agreements. See the NOTICE file distributed with -+ * this work for additional information regarding copyright ownership. -+ * The ASF licenses this file 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 KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ * -+ * Portions copyright 2005-2009 Steinar H. Gunderson . -+ * Licensed under the same terms as the rest of Apache. -+ * -+ * Portions copyright 2008 Knut Auvor Grythe . -+ * Licensed under the same terms as the rest of Apache. -+ */ -+ -+/** -+ * @file itk/mpm.h -+ * @brief ITK MPM (setuid per-vhost, no threads) -+ * -+ * @defgroup APACHE_MPM_ITK Apache ITK -+ * @ingroup APACHE_MPM APACHE_OS_UNIX -+ * @{ -+ */ -+ -+#include "httpd.h" -+#include "mpm_default.h" -+#include "scoreboard.h" -+#include "unixd.h" -+ -+#ifndef APACHE_MPM_ITK_H -+#define APACHE_MPM_ITK_H -+ -+#define ITK_MPM -+ -+#define MPM_NAME "ITK" -+ -+#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES -+#define AP_MPM_WANT_WAIT_OR_TIMEOUT -+#define AP_MPM_WANT_PROCESS_CHILD_STATUS -+#define AP_MPM_WANT_SET_PIDFILE -+#define AP_MPM_WANT_SET_SCOREBOARD -+#define AP_MPM_WANT_SET_LOCKFILE -+#define AP_MPM_WANT_SET_MAX_REQUESTS -+#define AP_MPM_WANT_SET_COREDUMPDIR -+#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH -+#define AP_MPM_WANT_SIGNAL_SERVER -+#define AP_MPM_WANT_SET_MAX_MEM_FREE -+#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER -+#define AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN -+#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK -+ -+#define AP_MPM_USES_POD 1 -+#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) -+#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0) -+#define MPM_ACCEPT_FUNC unixd_accept -+ -+extern int ap_threads_per_child; -+extern int ap_max_daemons_limit; -+extern server_rec *ap_server_conf; -+#endif /* APACHE_MPM_ITK_H */ -+/** @} */ ---- /dev/null -+++ server/mpm/experimental/itk/mpm_default.h -@@ -0,0 +1,80 @@ ++++ httpd-2.4.2/server/mpm/itk/mpm_default.h +@@ -0,0 +1,57 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. @@ -1845,9 +1964,9 @@ unchanged: + * See the License for the specific language governing permissions and + * limitations under the License. + * -+ * Portions copyright 2005-2009 Steinar H. Gunderson . ++ * Portions copyright 2005-2012 Steinar H. Gunderson . + * Licensed under the same terms as the rest of Apache. -+ * ++ * + * Portions copyright 2008 Knut Auvor Grythe . + * Licensed under the same terms as the rest of Apache. + */ @@ -1856,7 +1975,8 @@ unchanged: + * @file itk/mpm_default.h + * @brief ITK MPM defaults + * -+ * @addtogroup APACHE_MPM_ITK ++ * @defgroup APACHE_MPM_ITK Apache ITK ++ * @ingroup APACHE_INTERNAL + * @{ + */ + @@ -1884,111 +2004,48 @@ unchanged: +#define DEFAULT_MIN_FREE_DAEMON 5 +#endif + -+/* File used for accept locking, when we use a file */ -+#ifndef DEFAULT_LOCKFILE -+#define DEFAULT_LOCKFILE DEFAULT_REL_RUNTIMEDIR "/accept.lock" -+#endif -+ -+/* Where the main/parent process's pid is logged */ -+#ifndef DEFAULT_PIDLOG -+#define DEFAULT_PIDLOG DEFAULT_REL_RUNTIMEDIR "/httpd.pid" -+#endif -+ -+/* -+ * Interval, in microseconds, between scoreboard maintenance. -+ */ -+#ifndef SCOREBOARD_MAINTENANCE_INTERVAL -+#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000 -+#endif -+ -+/* Number of requests to try to handle in a single process. If <= 0, -+ * the children don't die off. -+ */ -+#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD -+#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000 -+#endif -+ +#endif /* AP_MPM_DEFAULT_H */ +/** @} */ ---- server/mpm/config.m4.orig -+++ server/mpm/config.m4 +Index: httpd-2.4.2/server/mpm/config2.m4 +=================================================================== +--- httpd-2.4.2.orig/server/mpm/config2.m4 ++++ httpd-2.4.2/server/mpm/config2.m4 @@ -1,7 +1,7 @@ - AC_MSG_CHECKING(which MPM to use) + AC_MSG_CHECKING(which MPM to use by default) AC_ARG_WITH(mpm, - APACHE_HELP_STRING(--with-mpm=MPM,Choose the process model for Apache to use. -- MPM={beos|event|worker|prefork|mpmt_os2|winnt}),[ -+ MPM={beos|event|worker|prefork|mpmt_os2|winnt|itk}),[ - APACHE_MPM=$withval - ],[ - if test "x$APACHE_MPM" = "x"; then -@@ -23,7 +23,7 @@ ap_mpm_is_threaded () - - ap_mpm_is_experimental () - { -- if test "$apache_cv_mpm" = "event" ; then -+ if test "$apache_cv_mpm" = "event" -o "$apache_cv_mpm" = "itk" ; then - return 0 + APACHE_HELP_STRING(--with-mpm=MPM,Choose the process model for Apache to use by default. +- MPM={event|worker|prefork|winnt} ++ MPM={event|worker|prefork|winnt|itk} + This will be statically linked as the only available MPM unless + --enable-mpms-shared is also specified. + ),[ +@@ -66,6 +66,9 @@ for i in $ap_enabled_mpms; do else - return 1 -@@ -66,6 +66,11 @@ if ap_mpm_is_experimental; then + AC_MSG_ERROR([MPM $i is not supported on this platform.]) + fi ++ if test "$i" = "itk" ; then ++ AC_CHECK_LIB(cap, cap_init) ++ fi + done + + if test $mpm_build = "shared"; then +Index: httpd-2.4.2/modules/arch/unix/config5.m4 +=================================================================== +--- httpd-2.4.2.orig/modules/arch/unix/config5.m4 ++++ httpd-2.4.2/modules/arch/unix/config5.m4 +@@ -3,6 +3,7 @@ APACHE_MODPATH_INIT(arch/unix) + + if ap_mpm_is_enabled "worker" \ + || ap_mpm_is_enabled "event" \ ++ || ap_mpm_is_enabled "itk" \ + || ap_mpm_is_enabled "prefork"; then + unixd_mods_enable=yes else - MPM_SUBDIR_NAME=$MPM_NAME - fi -+ -+if test "$apache_cv_mpm" = "itk" ; then -+ AC_CHECK_LIB(cap, cap_init) -+fi -+ - MPM_DIR=server/mpm/$MPM_SUBDIR_NAME - MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la - ---- include/http_request.h.orig -+++ include/http_request.h -@@ -12,6 +12,12 @@ - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -+ * -+ * Portions copyright 2005-2009 Steinar H. Gunderson . -+ * Licensed under the same terms as the rest of Apache. -+ * -+ * Portions copyright 2008 Knut Auvor Grythe . -+ * Licensed under the same terms as the rest of Apache. - */ - - /** -@@ -350,6 +356,15 @@ AP_DECLARE_HOOK(int,auth_checker,(reques - */ - AP_DECLARE_HOOK(void,insert_filter,(request_rec *r)) - -+/** -+ * This hook allows modules to affect the request immediately after the -+ * per-directory configuration for the request has been generated. This allows -+ * modules to make decisions based upon the current directory configuration -+ * @param r The current request -+ * @return OK or DECLINED -+ */ -+AP_DECLARE_HOOK(int,post_perdir_config,(request_rec *r)) -+ - AP_DECLARE(int) ap_location_walk(request_rec *r); - AP_DECLARE(int) ap_directory_walk(request_rec *r); - AP_DECLARE(int) ap_file_walk(request_rec *r); ---- server/request.c.orig -+++ server/request.c -@@ -12,6 +12,12 @@ - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -+ * -+ * Portions copyright 2005-2009 Steinar H. Gunderson . -+ * Licensed under the same terms as the rest of Apache. -+ * -+ * Portions copyright 2008 Knut Auvor Grythe . -+ * Licensed under the same terms as the rest of Apache. - */ - - /* -@@ -61,6 +67,7 @@ APR_HOOK_STRUCT( +Index: httpd-2.4.2/server/request.c +=================================================================== +--- httpd-2.4.2.orig/server/request.c ++++ httpd-2.4.2/server/request.c +@@ -69,6 +69,7 @@ APR_HOOK_STRUCT( APR_HOOK_LINK(auth_checker) APR_HOOK_LINK(insert_filter) APR_HOOK_LINK(create_request) @@ -1996,17 +2053,35 @@ unchanged: ) AP_IMPLEMENT_HOOK_RUN_FIRST(int,translate_name, -@@ -80,6 +87,8 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int,auth_che - AP_IMPLEMENT_HOOK_VOID(insert_filter, (request_rec *r), (r)) +@@ -91,10 +92,26 @@ AP_IMPLEMENT_HOOK_VOID(insert_filter, (r AP_IMPLEMENT_HOOK_RUN_ALL(int, create_request, (request_rec *r), (r), OK, DECLINED) + ++/** ++ * This hook allows modules to affect the request immediately after the ++ * per-directory configuration for the request has been generated. This allows ++ * modules to make decisions based upon the current directory configuration ++ * ++ * This hook is private to mpm-itk, so it is not exposed in http_request.h. ++ * ++ * @param r The current request ++ * @return OK or DECLINED ++ */ ++AP_DECLARE_HOOK(int,post_perdir_config,(request_rec *r)) ++ +AP_IMPLEMENT_HOOK_RUN_ALL(int,post_perdir_config, + (request_rec *r), (r), OK, DECLINED) ++ + static int auth_internal_per_conf = 0; + static int auth_internal_per_conf_hooks = 0; + static int auth_internal_per_conf_providers = 0; ++extern AP_DECLARE_DATA int ap_running_under_mpm_itk; - static int decl_die(int status, char *phase, request_rec *r) -@@ -158,6 +167,13 @@ AP_DECLARE(int) ap_process_request_inter - return access_status; + static int decl_die(int status, const char *phase, request_rec *r) + { +@@ -191,6 +208,13 @@ AP_DECLARE(int) ap_process_request_inter + r->log = d->log; } + /* First chance to handle the request after per-directory configuration is @@ -2019,3 +2094,66 @@ unchanged: /* Only on the main request! */ if (r->main == NULL) { if ((access_status = ap_run_header_parser(r))) { +@@ -1093,6 +1117,16 @@ AP_DECLARE(int) ap_directory_walk(reques + break; + } + else if (APR_STATUS_IS_EACCES(rv)) { ++ /* See the corresponding section in server/config.c for the rationale ++ * behind this logic. ++ */ ++ if (ap_running_under_mpm_itk && r->main == NULL && getuid() != 0) { ++ ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, r, ++ "Access to %s denied, closing connection.", ++ r->filename); ++ ap_lingering_close(r->connection); ++ exit(0); ++ } + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(00035) + "access to %s denied (filesystem path '%s') " + "because search permissions are missing on a " +Index: httpd-2.4.2/server/config.c +=================================================================== +--- httpd-2.4.2.orig/server/config.c ++++ httpd-2.4.2/server/config.c +@@ -69,6 +69,8 @@ AP_DECLARE_DATA apr_array_header_t *ap_s + + AP_DECLARE_DATA ap_directive_t *ap_conftree = NULL; + ++AP_DECLARE_DATA int ap_running_under_mpm_itk = 0; ++ + APR_HOOK_STRUCT( + APR_HOOK_LINK(header_parser) + APR_HOOK_LINK(pre_config) +@@ -2129,6 +2131,32 @@ AP_CORE_DECLARE(int) ap_parse_htaccess(a + else { + if (!APR_STATUS_IS_ENOENT(status) + && !APR_STATUS_IS_ENOTDIR(status)) { ++ /* ++ * If we are in a persistent connection, we might end up in a state ++ * where we can no longer read .htaccess files because we have already ++ * setuid(). This can either be because the previous request was for ++ * another vhost (basically the same problem as when setuid() fails in ++ * itk.c), or it can be because a .htaccess file is readable only by ++ * root. ++ * ++ * In any case, we don't want to give out a 403, since the request has ++ * a very real chance of succeeding on a fresh connection (where ++ * presumably uid=0). Thus, we give up serving the request on this ++ * TCP connection, and do a hard close of the socket. As long as we're ++ * in a persistent connection (and there _should_ not be a way this ++ * would happen on the first request in a connection, save for subrequests, ++ * which we special-case), this is allowed, as it is what happens on ++ * a timeout. The browser will simply open a new connection and try ++ * again (there's of course a performance hit, though, both due to ++ * the new connection setup and the fork() of a new server child). ++ */ ++ if (ap_running_under_mpm_itk && r->main == NULL && getuid() != 0) { ++ ap_log_rerror(APLOG_MARK, APLOG_WARNING, status, r, ++ "Couldn't read %s, closing connection.", ++ filename); ++ ap_lingering_close(r->connection); ++ exit(0); ++ } + ap_log_rerror(APLOG_MARK, APLOG_CRIT, status, r, APLOGNO(00529) + "%s pcfg_openfile: unable to check htaccess file, " + "ensure it is readable and that '%s' " diff --git a/apache2.changes b/apache2.changes index 164d6e9..d51fa11 100644 --- a/apache2.changes +++ b/apache2.changes @@ -1,8 +1,53 @@ +------------------------------------------------------------------- +Mon Feb 25 08:19:41 UTC 2013 - mlin@suse.com + +- Install apache2.service accordingly (/usr/lib/systemd for 12.3 + and up or /lib/systemd for older versions). + +------------------------------------------------------------------- +Sat Jan 26 05:06:07 UTC 2013 - crrodriguez@opensuse.org + +- Apache 2.4.3 +* SECURITY: CVE-2012-3502 +* SECURITY: CVE-2012-2687 +* mod_cache: Set content type in case we return stale content. +* lots of bugfixes see http://www.apache.org/dist/httpd/CHANGES_2.4.3 + +------------------------------------------------------------------- +Sat Jan 26 05:00:00 UTC 2013 - crrodriguez@opensuse.org + +- Improve systemd unit file (tested for months) + ------------------------------------------------------------------- Fri Jan 18 11:52:30 CET 2013 - mhrusecky@suse.cz - use %set_permissions instead %run_permissions (bnc#764097) +------------------------------------------------------------------- +Wed Aug 1 04:10:13 UTC 2012 - crrodriguez@opensuse.org + +- Fix factory-auto (aka r2dbag) complains about URL. +- Provide a symlink for apxs2 new location otherwise + all buggy spec files of external modules will break. + +------------------------------------------------------------------- +Wed Aug 1 02:21:34 UTC 2012 - crrodriguez@opensuse.org + +- BuildRequire xz explicitly, fix build in !Factory +- Drop more old, unused patches + +------------------------------------------------------------------- +Wed Aug 1 01:14:35 UTC 2012 - crrodriguez@opensuse.org + +- Upgrade to apache 2.4.2 +** ATTENTION, before installing this update YOU MUST +READ http://httpd.apache.org/docs/2.4/upgrading.html +CAREFULLY otherwise your server will most likely +fail to start due to backward incompatible changes. + +* You can read the huge complete list of changes + at http://httpd.apache.org/docs/2.4/new_features_2_4.html + ------------------------------------------------------------------- Wed Jul 25 11:32:34 UTC 2012 - saschpe@suse.de diff --git a/apache2.service b/apache2.service index 9e30d6c..e339ca0 100644 --- a/apache2.service +++ b/apache2.service @@ -1,16 +1,14 @@ [Unit] -Description=apache -After=syslog.target network.target +Description=The Apache Webserver +After=network.target remote-fs.target nss-lookup.target Before=getty@tty1.service [Service] -Type=forking -PIDFile=/var/run/httpd2.pid +PrivateTmp=true EnvironmentFile=/etc/sysconfig/apache2 -ExecStart=/usr/sbin/start_apache2 -D SYSTEMD -k start -ExecReload=/usr/sbin/start_apache2 -D SYSTEMD -t -ExecReload=/bin/kill -HUP $MAINPID -ExecStop=/usr/sbin/httpd2 -D SYSTEMD -k stop +ExecStart=/usr/sbin/start_apache2 -D SYSTEMD -DNO_DETACH -k start +ExecReload=/usr/sbin/start_apache2 -D SYSTEMD -DNO_DETACH -t -k graceful +ExecStop=/usr/sbin/start_apache2 -D SYSTEMD -DNO_DETACH -k graceful-stop [Install] WantedBy=multi-user.target diff --git a/apache2.spec b/apache2.spec index d0c5970..8ef99ec 100644 --- a/apache2.spec +++ b/apache2.spec @@ -1,7 +1,7 @@ # # spec file for package apache2 # -# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -25,6 +25,7 @@ BuildRequires: libapr1-devel >= 1.4.2 BuildRequires: openldap2-devel BuildRequires: openssl-devel BuildRequires: pcre-devel +BuildRequires: xz BuildRequires: zlib-devel %if %{?suse_version:1}0 && 0%{?sles_version} == 9 BuildRequires: libcap @@ -47,7 +48,7 @@ BuildRequires: expat-devel %define pname apache2 %define vers 2 %define httpd httpd2 -%define apache_mmn %(test -s %{S:0} && { echo -n apache_mmn_; bzcat %{S:0} | awk '/^#define MODULE_MAGIC_NUMBER_MAJOR/ {printf "%d", $3}'; }) +%define apache_mmn %(test -s %{S:0} && { echo -n apache_mmn_; xzcat %{S:0} | awk '/^#define MODULE_MAGIC_NUMBER_MAJOR/ {printf "%d", $3}'; }) %define default_mpm prefork %{!?prefork:%define prefork 1} %{!?worker:%define worker 1} @@ -71,17 +72,21 @@ BuildRequires: expat-devel %define installbuilddir %{_prefix}/share/%{pname}/build %define userdir public_html %define suexec_safepath /usr/local/bin:/usr/bin:/bin +%if %suse_version > 1220 +%define _unitdir /usr/lib/systemd +%else +%define _unitdir /lib/systemd +%endif # "Server:" header %define VENDOR SUSE %define platform_string Linux/%VENDOR -%define realver 2.2.22 -Version: 2.2.22 +%define realver 2.4.3 +Version: 2.4.3 Release: 0 #Source0: http://www.apache.org/dist/httpd-%{version}.tar.bz2 -Source0: http://httpd.apache.org/dev/dist/httpd-%{realver}.tar.bz2 +Source0: httpd-%{realver}.tar.xz # Add file to take mtime from it in prep section Source1: apache2.changes -Source5: http://httpd.apache.org/dev/dist/httpd-%{realver}.tar.bz2.asc Source6: 60C5442D.key Source10: SUSE-NOTICE Source11: rc.%{pname} @@ -134,19 +139,13 @@ Source143: apache2-systemd-ask-pass Source144: apache2.service Patch2: httpd-2.1.3alpha-layout.dif Patch23: httpd-2.1.9-apachectl.dif -Patch65: httpd-2.0.49-log_server_status.dif +#Patch65: httpd-2.0.49-log_server_status.dif Patch66: httpd-2.0.54-envvars.dif Patch67: httpd-2.2.0-apxs-a2enmod.dif Patch68: httpd-2.x.x-logresolve.patch Patch69: httpd-2.2.x-bnc690734.patch -Patch100: apache2.2-mpm-itk-20090414-00.patch +Patch100: apache2.4-mpm-itk-2.4.2-01.patch Patch101: httpd-2.2.19-linux3.patch -Patch102: httpd-keepalivetimeout-millisecs.patch -Patch104: httpd-mod_deflate_head.patch -Patch105: ssl-mode-release-buffers.patch -Patch106: httpd-2.2.x-CVE-2011-3368-server_protocl_c.diff -# PATCH-FIX-UPSTREAM https://issues.apache.org/bugzilla/show_bug.cgi?id=52623 -Patch107: httpd-new_pcre.patch # PATCH-FEATURE-UPSTREAM apache2-mod_ssl_npn.patch dimstar@opensuse.org -- Add npn support to mod_ssl (needed for spdy) Patch108: apache2-mod_ssl_npn.patch Provides: apache2(mod_ssl+npn) @@ -362,22 +361,15 @@ to administrators of web servers in general. # %setup -q -n httpd-%{realver} %patch2 -p1 -%patch23 -p1 -%patch65 -p1 -%patch66 -p1 +%patch23 +#%patch65 -p1 +%patch66 %patch67 -p1 %patch68 -p1 -%patch69 -%patch100 +#%patch69 +%patch100 -p1 %patch101 -%patch102 -%patch104 -%patch105 -%patch106 -%if 0%{?suse_version} >= 1220 -%patch107 -%endif -%patch108 +%patch108 -p1 # cat $RPM_SOURCE_DIR/SUSE-NOTICE >> NOTICE @@ -480,7 +472,8 @@ function configure { --with-suexec-userdir=%{userdir} \ --with-suexec-uidmin=96 \ --with-suexec-gidmin=96 \ - --with-suexec-safepath=%{suexec_safepath} + --with-suexec-safepath=%{suexec_safepath} \ + --disable-heartbeat } # @@ -637,9 +630,9 @@ mkdir -p $RPM_BUILD_ROOT/etc/init.d install -m 744 $RPM_SOURCE_DIR/rc.%{pname} $RPM_BUILD_ROOT/etc/init.d/%{pname} install -m 744 $RPM_SOURCE_DIR/start_apache2 $RPM_BUILD_ROOT/usr/sbin/start_apache2 %if 0%{?suse_version} >= 1210 -mkdir -p $RPM_BUILD_ROOT/lib/systemd/system/ +mkdir -p $RPM_BUILD_ROOT%{_unitdir}/system/ install -m 744 $RPM_SOURCE_DIR/apache2-systemd-ask-pass $RPM_BUILD_ROOT/usr/sbin/apache2-systemd-ask-pass -install -m 644 $RPM_SOURCE_DIR/apache2.service $RPM_BUILD_ROOT/lib/systemd/system/apache2.service +install -m 644 $RPM_SOURCE_DIR/apache2.service $RPM_BUILD_ROOT%{_unitdir}/system/apache2.service %endif ln -sf ../../etc/init.d/%{pname} $RPM_BUILD_ROOT/%{_sbindir}/rc%{pname} install -m 755 $RPM_SOURCE_DIR/load_configuration $RPM_BUILD_ROOT/%{_prefix}/share/%{pname}/ @@ -737,17 +730,21 @@ pushd $RPM_BUILD_ROOT/%{_mandir} mv $i ${i%.*}%{vers}.${i#*.*.} || true done popd + +pushd $RPM_BUILD_ROOT/%{_bindir} +for i in ab dbmmanage htdbm htdigest htpasswd logresolve;do +mv $i ${i}%{vers} || true +done +popd + pushd $RPM_BUILD_ROOT/%{_sbindir} - for i in ab dbmmanage htdbm htdigest htpasswd logresolve rotatelogs suexec; do + for i in rotatelogs suexec; do mv $i ${i}%{vers} || true done mv apachectl apachectl.tmp; mv apachectl.tmp apache%{vers}ctl - for i in dbmmanage htdbm htdigest htpasswd; do - mv ${i}%{vers} ../bin/ - done popd # fix up apxs -pushd $RPM_BUILD_ROOT/%{_sbindir} +pushd $RPM_BUILD_ROOT/%{_bindir} for mpm in %{mpms_to_build}; do cat <<-EOT_ED | ed -s apxs H @@ -776,7 +773,7 @@ popd install -d $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ install -m 644 %{S:49} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/%{name} install -m 644 %{S:50} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/%{name}-ssl - +ln -sf %{_bindir}/apxs%{vers} %{buildroot}%{_sbindir} # # filelists # @@ -785,7 +782,7 @@ for mpm in %{mpms_to_build}; do echo %dir %{_libdir}/%{pname}-$mpm >> filelist ( echo %dir %{includedir}-$mpm - echo %{_sbindir}/apxs%{vers}-$mpm + echo %{_bindir}/apxs%{vers}-$mpm ) >> filelist-devel done find $RPM_BUILD_ROOT/%{includedir}/.. -type f -o -type l \ @@ -827,6 +824,7 @@ sed -e 's+/usr/%_lib+'$RPM_BUILD_ROOT'/usr/%_lib+' \ -e 's+%{sysconfdir}+'$RPM_BUILD_ROOT'%{sysconfdir}+' \ -e 's+%{datadir}+'$RPM_BUILD_ROOT'%{datadir}+' \ -e 's+\.conf$+&.test+' \ + -e 's+/var/log+'$RPM_BUILD_ROOT'/var/log+' \ httpd.conf > httpd.conf.test sed -e 's+%{sysconfdir}+'$RPM_BUILD_ROOT'%{sysconfdir}+' \ default-server.conf > default-server.conf.test @@ -900,7 +898,7 @@ mv $RPM_BUILD_ROOT/%{sysconfdir}/original . %endif %config /etc/init.d/%{pname} %if 0%{?suse_version} >= 1210 -/lib/systemd/system/%{pname}.service +%{_unitdir}/system/%{pname}.service %endif # %{_sbindir}/rc%{pname} @@ -973,6 +971,7 @@ mv $RPM_BUILD_ROOT/%{sysconfdir}/original . %dir %{_prefix}/share/%{pname} %dir %{installbuilddir} %dir %{includedir} +%{_bindir}/apxs%{vers} %{_sbindir}/apxs%{vers} %files doc @@ -999,6 +998,8 @@ mv $RPM_BUILD_ROOT/%{sysconfdir}/original . %doc %{_mandir}/man?/logresolve%{vers}.?.* %doc %{_mandir}/man?/rotatelogs%{vers}.?.* %doc %{_mandir}/man?/suexec%{vers}.?.* +%{_sbindir}/fcgistarter +%{_mandir}/man8/fcgistarter2.8.* %{_bindir}/check_forensic%{vers} %{_bindir}/dbmmanage%{vers} %{_bindir}/gensslcert @@ -1006,10 +1007,10 @@ mv $RPM_BUILD_ROOT/%{sysconfdir}/original . %{_bindir}/htdigest%{vers} %{_bindir}/htpasswd%{vers} %{_bindir}/split-logfile%{vers} -%{_sbindir}/ab%{vers} -%{_sbindir}/httxt2dbm +%{_bindir}/ab%{vers} +%{_bindir}/httxt2dbm %{_sbindir}/logresolve.pl%{vers} -%{_sbindir}/logresolve%{vers} +%{_bindir}/logresolve%{vers} %{_sbindir}/rotatelogs%{vers} %verify(not mode) %attr(0755,root,root) %_sbindir/suexec2 %if %prefork diff --git a/httpd-2.0.54-envvars.dif b/httpd-2.0.54-envvars.dif index 7c1f3fe..7e0ea8e 100644 --- a/httpd-2.0.54-envvars.dif +++ b/httpd-2.0.54-envvars.dif @@ -1,11 +1,17 @@ -diff -uNr httpd-2.0.54.orig/support/envvars-std.in httpd-2.0.54/support/envvars-std.in ---- httpd-2.0.54.orig/support/envvars-std.in 2005-02-04 21:21:18.000000000 +0100 -+++ httpd-2.0.54/support/envvars-std.in 2005-10-07 13:56:49.223546288 +0200 -@@ -19,6 +19,6 @@ +--- support/envvars-std.in.orig ++++ support/envvars-std.in +@@ -18,11 +18,9 @@ + # # This file is generated from envvars-std.in # --@SHLIBPATH_VAR@="@exp_libdir@:$@SHLIBPATH_VAR@" +-if test "x$@SHLIBPATH_VAR@" != "x" ; then +- @SHLIBPATH_VAR@="@exp_libdir@:$@SHLIBPATH_VAR@" +-else +- @SHLIBPATH_VAR@="@exp_libdir@" +-fi ++ +@SHLIBPATH_VAR@="@exp_libdir@${@SHLIBPATH_VAR@+:$@SHLIBPATH_VAR@}" ++ export @SHLIBPATH_VAR@ # @OS_SPECIFIC_VARS@ diff --git a/httpd-2.1.9-apachectl.dif b/httpd-2.1.9-apachectl.dif index 3d25d4c..abe1651 100644 --- a/httpd-2.1.9-apachectl.dif +++ b/httpd-2.1.9-apachectl.dif @@ -1,7 +1,6 @@ -diff -uNr httpd-2.1.3-alpha.orig/support/apachectl.in httpd-2.1.3-alpha/support/apachectl.in ---- httpd-2.1.3-alpha.orig/support/apachectl.in 2005-02-04 21:28:49.000000000 +0100 -+++ httpd-2.1.3-alpha/support/apachectl.in 2005-02-25 02:52:49.203566813 +0100 -@@ -41,17 +41,32 @@ +--- support/apachectl.in.orig ++++ support/apachectl.in +@@ -42,17 +42,32 @@ ARGV="$@" # -------------------- -------------------- # # the path to your httpd binary, including options if necessary @@ -36,16 +35,16 @@ diff -uNr httpd-2.1.3-alpha.orig/support/apachectl.in httpd-2.1.3-alpha/support/ # # the URL to your server's mod_status status page. If you do not # have one, then status and fullstatus will not work. -@@ -77,7 +92,7 @@ +@@ -78,7 +93,7 @@ fi - case $ARGV in + case $ACMD in start|stop|restart|graceful|graceful-stop) - $HTTPD -k $ARGV + $HTTPD ${httpd_conf+-f $httpd_conf} -k $ARGV ERROR=$? ;; startssl|sslstart|start-SSL) -@@ -87,7 +102,7 @@ +@@ -88,7 +103,7 @@ startssl|sslstart|start-SSL) ERROR=2 ;; configtest) @@ -54,12 +53,3 @@ diff -uNr httpd-2.1.3-alpha.orig/support/apachectl.in httpd-2.1.3-alpha/support/ ERROR=$? ;; status) -@@ -97,7 +112,7 @@ - $LYNX $STATUSURL - ;; - *) -- $HTTPD $ARGV -+ $HTTPD ${httpd_conf+-f $httpd_conf} $ARGV - ERROR=$? - esac - diff --git a/httpd-2.2.22.tar.bz2 b/httpd-2.2.22.tar.bz2 deleted file mode 100644 index 01c3754..0000000 --- a/httpd-2.2.22.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dcdc9f1dc722f84798caf69d69dca78daa5e09a4269060045aeca7e4f44cb231 -size 5378934 diff --git a/httpd-2.2.22.tar.bz2.asc b/httpd-2.2.22.tar.bz2.asc deleted file mode 100644 index b8ef53b..0000000 Binary files a/httpd-2.2.22.tar.bz2.asc and /dev/null differ diff --git a/httpd-2.2.x-CVE-2011-3368-server_protocl_c.diff b/httpd-2.2.x-CVE-2011-3368-server_protocl_c.diff deleted file mode 100644 index 63b9b6f..0000000 --- a/httpd-2.2.x-CVE-2011-3368-server_protocl_c.diff +++ /dev/null @@ -1,68 +0,0 @@ -diff -rNU 20 ../httpd-2.2.21-o/server/protocol.c ./server/protocol.c ---- ../httpd-2.2.21-o/server/protocol.c 2011-05-07 13:39:29.000000000 +0200 -+++ ./server/protocol.c 2011-10-07 17:10:46.000000000 +0200 -@@ -623,40 +623,64 @@ - - #if 0 - /* XXX If we want to keep track of the Method, the protocol module should do - * it. That support isn't in the scoreboard yet. Hopefully next week - * sometime. rbb */ - ap_update_connection_status(AP_CHILD_THREAD_FROM_ID(conn->id), "Method", - r->method); - #endif - - uri = ap_getword_white(r->pool, &ll); - - /* Provide quick information about the request method as soon as known */ - - r->method_number = ap_method_number_of(r->method); - if (r->method_number == M_GET && r->method[0] == 'H') { - r->header_only = 1; - } - - ap_parse_uri(r, uri); - -+/* -+ https://svn.apache.org/viewvc/httpd/httpd/trunk/server/protocol.c?r1=1178566&r2=1179239&pathrev=1179239&view=patch -+ This is the fix for CVE-2011-3368; via bnc#722545. -+ */ -+ -+ /* RFC 2616: -+ * Request-URI = "*" | absoluteURI | abs_path | authority -+ * -+ * authority is a special case for CONNECT. If the request is not -+ * using CONNECT, and the parsed URI does not have scheme, and -+ * it does not begin with '/', and it is not '*', then, fail -+ * and give a 400 response. */ -+ if (r->method_number != M_CONNECT -+ && !r->parsed_uri.scheme -+ && uri[0] != '/' -+ && !(uri[0] == '*' && uri[1] == '\0')) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -+ "invalid request-URI %s", uri); -+ r->args = NULL; -+ r->hostname = NULL; -+ r->status = HTTP_BAD_REQUEST; -+ r->uri = apr_pstrdup(r->pool, uri); -+ } -+ - if (ll[0]) { - r->assbackwards = 0; - pro = ll; - len = strlen(ll); - } else { - r->assbackwards = 1; - pro = "HTTP/0.9"; - len = 8; - } - r->protocol = apr_pstrmemdup(r->pool, pro, len); - - /* XXX ap_update_connection_status(conn->id, "Protocol", r->protocol); */ - - /* Avoid sscanf in the common case */ - if (len == 8 - && pro[0] == 'H' && pro[1] == 'T' && pro[2] == 'T' && pro[3] == 'P' - && pro[4] == '/' && apr_isdigit(pro[5]) && pro[6] == '.' - && apr_isdigit(pro[7])) { - r->proto_num = HTTP_VERSION(pro[5] - '0', pro[7] - '0'); - } diff --git a/httpd-2.2.x-bnc690734.patch b/httpd-2.2.x-bnc690734.patch index 68e142a..87ce840 100644 --- a/httpd-2.2.x-bnc690734.patch +++ b/httpd-2.2.x-bnc690734.patch @@ -1,7 +1,6 @@ -diff -ruN ../httpd-2.2.17-o/server/util_script.c ./server/util_script.c ---- ../httpd-2.2.17-o/server/util_script.c 2009-01-12 14:59:56.000000000 +0100 -+++ ./server/util_script.c 2011-07-26 15:39:50.000000000 +0200 -@@ -406,6 +406,7 @@ +--- server/util_script.c.orig ++++ server/util_script.c +@@ -415,6 +415,7 @@ AP_DECLARE(int) ap_scan_script_header_er { char x[MAX_STRING_LEN]; char *w, *l; @@ -9,7 +8,7 @@ diff -ruN ../httpd-2.2.17-o/server/util_script.c ./server/util_script.c int p; int cgi_status = HTTP_UNSET; apr_table_t *merge; -@@ -414,7 +415,14 @@ +@@ -425,7 +426,14 @@ AP_DECLARE(int) ap_scan_script_header_er if (buffer) { *buffer = '\0'; } @@ -25,17 +24,17 @@ diff -ruN ../httpd-2.2.17-o/server/util_script.c ./server/util_script.c /* temporary place to hold headers to merge in later */ merge = apr_table_make(r->pool, 10); -@@ -430,7 +438,7 @@ +@@ -441,7 +449,7 @@ AP_DECLARE(int) ap_scan_script_header_er while (1) { - int rv = (*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data); + int rv = (*getsfunc) (w, wlen - 1, getsfunc_data); if (rv == 0) { - ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r, - "Premature end of script headers: %s", -@@ -537,9 +545,12 @@ - + const char *msg = "Premature end of script headers"; + if (first_header) +@@ -553,9 +561,12 @@ AP_DECLARE(int) ap_scan_script_header_er + if (!(l = strchr(w, ':'))) { if (!buffer) { /* Soak up all the script output - may save an outright kill */ - while ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data)) { @@ -47,4 +46,4 @@ diff -ruN ../httpd-2.2.17-o/server/util_script.c ./server/util_script.c + buffer[MAX_STRING_LEN - 1] = 0; } - ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r, + ap_log_rerror(SCRIPT_LOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r, diff --git a/httpd-2.4.3.tar.xz b/httpd-2.4.3.tar.xz new file mode 100644 index 0000000..e57db9b --- /dev/null +++ b/httpd-2.4.3.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89ba3db446faa929206ed3f5a1bef7133e034ad8f8abfc5e8f8eb41f3cc61074 +size 4032716 diff --git a/httpd-keepalivetimeout-millisecs.patch b/httpd-keepalivetimeout-millisecs.patch deleted file mode 100644 index 2970a91..0000000 --- a/httpd-keepalivetimeout-millisecs.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- modules/http/http_core.c.orig -+++ modules/http/http_core.c -@@ -47,12 +47,15 @@ static int ap_process_http_connection(co - static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy, - const char *arg) - { -+ apr_interval_time_t timeout; - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT); - if (err != NULL) { - return err; - } -- -- cmd->server->keep_alive_timeout = apr_time_from_sec(atoi(arg)); -+ /* Stolen from mod_proxy.c */ -+ if (ap_timeout_parameter_parse(arg, &timeout, "s") != APR_SUCCESS) -+ return "KeepAliveTimeout has wrong format"; -+ cmd->server->keep_alive_timeout = timeout; - return NULL; - } - diff --git a/httpd-mod_deflate_head.patch b/httpd-mod_deflate_head.patch deleted file mode 100644 index 6d4011a..0000000 --- a/httpd-mod_deflate_head.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- modules/filters/mod_deflate.c.orig -+++ modules/filters/mod_deflate.c -@@ -582,6 +582,20 @@ static apr_status_t deflate_out_filter(a - apr_bucket *b; - apr_size_t len; - -+ /* -+ * Optimization: If we are a HEAD request and bytes_sent is not zero -+ * it means that we have passed the content-length filter once and -+ * have more data to sent. This means that the content-length filter -+ * could not determine our content-length for the response to the -+ * HEAD request anyway (the associated GET request would deliver the -+ * body in chunked encoding) and we can stop compressing. -+ */ -+ if (r->header_only && r->bytes_sent) { -+ ap_remove_output_filter(f); -+ return ap_pass_brigade(f->next, bb); -+ } -+ -+ - e = APR_BRIGADE_FIRST(bb); - - if (APR_BUCKET_IS_EOS(e)) { diff --git a/httpd-new_pcre.patch b/httpd-new_pcre.patch deleted file mode 100644 index dd558af..0000000 --- a/httpd-new_pcre.patch +++ /dev/null @@ -1,23 +0,0 @@ -Index: server/util_pcre.c -=================================================================== ---- server/util_pcre.c.orig 2012-02-11 10:07:31.000000000 +0100 -+++ server/util_pcre.c 2012-02-11 10:08:23.062838133 +0100 -@@ -128,6 +128,7 @@ AP_DECLARE(int) ap_regcomp(ap_regex_t *p - const char *errorptr; - int erroffset; - int options = 0; -+int nsub; - - if ((cflags & AP_REG_ICASE) != 0) options |= PCRE_CASELESS; - if ((cflags & AP_REG_NEWLINE) != 0) options |= PCRE_MULTILINE; -@@ -137,7 +138,9 @@ preg->re_erroffset = erroffset; - - if (preg->re_pcre == NULL) return AP_REG_INVARG; - --preg->re_nsub = pcre_info((const pcre *)preg->re_pcre, NULL, NULL); -+pcre_fullinfo((const pcre *)preg->re_pcre, NULL, -+ PCRE_INFO_CAPTURECOUNT, &nsub); -+preg->re_nsub = nsub; - return 0; - } - diff --git a/ssl-mode-release-buffers.patch b/ssl-mode-release-buffers.patch deleted file mode 100644 index 5898966..0000000 --- a/ssl-mode-release-buffers.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- modules/ssl/ssl_engine_init.c.orig -+++ modules/ssl/ssl_engine_init.c -@@ -482,7 +482,9 @@ static void ssl_init_ctx_protocol(server - } - - mctx->ssl_ctx = ctx; -- -+#ifdef SSL_MODE_RELEASE_BUFFERS -+ SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); -+#endif - SSL_CTX_set_options(ctx, SSL_OP_ALL); - - if (!(protocol & SSL_PROTOCOL_SSLV2)) {