1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * ssl.c --- routines for SSL/TLS server infrastructure.
19  *
20  */
21 
22 #include "apr.h"
23 #include "apr_strings.h"
24 #include "apr_buckets.h"
25 #include "apr_lib.h"
26 #include "apr_signal.h"
27 #include "apr_strmatch.h"
28 
29 #define APR_WANT_STDIO          /* for sscanf */
30 #define APR_WANT_STRFUNC
31 #define APR_WANT_MEMFUNC
32 #include "apr_want.h"
33 
34 #include "util_filter.h"
35 #include "ap_config.h"
36 #include "httpd.h"
37 #include "http_config.h"
38 #include "http_core.h"
39 #include "http_connection.h"
40 #include "http_protocol.h"
41 #include "http_request.h"
42 #include "http_main.h"
43 #include "http_ssl.h"
44 #include "http_log.h"           /* For errors detected in basic auth common
45                                  * support code... */
46 #include "mod_core.h"
47 
48 
49 #if APR_HAVE_STDARG_H
50 #include <stdarg.h>
51 #endif
52 #if APR_HAVE_UNISTD_H
53 #include <unistd.h>
54 #endif
55 
56 /* we know core's module_index is 0 */
57 #undef APLOG_MODULE_INDEX
58 #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
59 
60 APR_HOOK_STRUCT(
61     APR_HOOK_LINK(ssl_conn_is_ssl)
62     APR_HOOK_LINK(ssl_var_lookup)
63     APR_HOOK_LINK(ssl_add_cert_files)
64     APR_HOOK_LINK(ssl_add_fallback_cert_files)
65     APR_HOOK_LINK(ssl_answer_challenge)
66     APR_HOOK_LINK(ssl_ocsp_prime_hook)
67     APR_HOOK_LINK(ssl_ocsp_get_resp_hook)
68     APR_HOOK_LINK(ssl_bind_outgoing)
69 )
70 
71 APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
72 static APR_OPTIONAL_FN_TYPE(ssl_is_https) *module_ssl_is_https;
73 APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));
74 static APR_OPTIONAL_FN_TYPE(ssl_proxy_enable) *module_ssl_proxy_enable;
75 APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
76 static APR_OPTIONAL_FN_TYPE(ssl_engine_disable) *module_ssl_engine_disable;
77 APR_DECLARE_OPTIONAL_FN(int, ssl_engine_set, (conn_rec *,
78                                               ap_conf_vector_t *,
79                                               int proxy, int enable));
APR_OPTIONAL_FN_TYPE(ssl_engine_set)80 static APR_OPTIONAL_FN_TYPE(ssl_engine_set) *module_ssl_engine_set;
81 
82 
83 static int ssl_is_https(conn_rec *c)
84 {
85     /* Someone retrieved the optional function., not knowing about the
86      * new API. We redirect them to what they should have invoked. */
87     return ap_ssl_conn_is_ssl(c);
88 }
89 
ap_ssl_conn_is_ssl(conn_rec * c)90 AP_DECLARE(int) ap_ssl_conn_is_ssl(conn_rec *c)
91 {
92     int r = (ap_run_ssl_conn_is_ssl(c) == OK);
93     if (r == 0 && module_ssl_is_https) {
94         r = module_ssl_is_https(c);
95     }
96     return r;
97 }
98 
ssl_engine_set(conn_rec * c,ap_conf_vector_t * per_dir_config,int proxy,int enable)99 static int ssl_engine_set(conn_rec *c,
100                           ap_conf_vector_t *per_dir_config,
101                           int proxy, int enable)
102 {
103     if (proxy) {
104         return ap_ssl_bind_outgoing(c, per_dir_config, enable) == OK;
105     }
106     else if (module_ssl_engine_set) {
107         return module_ssl_engine_set(c, per_dir_config, 0, enable);
108     }
109     else if (enable && module_ssl_proxy_enable) {
110         return module_ssl_proxy_enable(c);
111     }
112     else if (!enable && module_ssl_engine_disable) {
113         return module_ssl_engine_disable(c);
114     }
115     return 0;
116 }
117 
ssl_proxy_enable(conn_rec * c)118 static int ssl_proxy_enable(conn_rec *c)
119 {
120     return ap_ssl_bind_outgoing(c, NULL, 1);
121 }
122 
ssl_engine_disable(conn_rec * c)123 static int ssl_engine_disable(conn_rec *c)
124 {
125     return ap_ssl_bind_outgoing(c, NULL, 0);
126 }
127 
ap_ssl_bind_outgoing(conn_rec * c,struct ap_conf_vector_t * dir_conf,int enable_ssl)128 AP_DECLARE(int) ap_ssl_bind_outgoing(conn_rec *c, struct ap_conf_vector_t *dir_conf,
129                                      int enable_ssl)
130 {
131     int rv, enabled = 0;
132 
133     c->outgoing = 1;
134     rv = ap_run_ssl_bind_outgoing(c, dir_conf, enable_ssl);
135     enabled = (rv == OK);
136     if (enable_ssl && !enabled) {
137         /* the hooks did not take over. Is there an old skool optional that will? */
138         if (module_ssl_engine_set) {
139             enabled = module_ssl_engine_set(c, dir_conf, 1, 1);
140         }
141         else if (module_ssl_proxy_enable) {
142             enabled = module_ssl_proxy_enable(c);
143         }
144     }
145     else {
146         /* !enable_ssl || enabled
147          * any existing optional funcs need to not enable here */
148         if (module_ssl_engine_set) {
149             module_ssl_engine_set(c, dir_conf, 1, 0);
150         }
151         else if (module_ssl_engine_disable) {
152             module_ssl_engine_disable(c);
153         }
154     }
155     if (enable_ssl && !enabled) {
156         ap_log_cerror(APLOG_MARK, APLOG_ERR, 0,
157                       c, APLOGNO(01961) " failed to enable ssl support "
158                       "[Hint: if using mod_ssl, see SSLProxyEngine]");
159         return DECLINED;
160     }
161     return OK;
162 }
163 
ap_ssl_has_outgoing_handlers(void)164 AP_DECLARE(int) ap_ssl_has_outgoing_handlers(void)
165 {
166     apr_array_header_t *hooks = ap_hook_get_ssl_bind_outgoing();
167     return (hooks && hooks->nelts > 0)
168         || module_ssl_engine_set || module_ssl_proxy_enable;
169 }
170 
171 APR_DECLARE_OPTIONAL_FN(const char *, ssl_var_lookup,
172                         (apr_pool_t *p, server_rec *s,
173                          conn_rec *c, request_rec *r,
174                          const char *name));
APR_OPTIONAL_FN_TYPE(ssl_var_lookup)175 static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *module_ssl_var_lookup;
176 
177 static const char *ssl_var_lookup(apr_pool_t *p, server_rec *s,
178                                   conn_rec *c, request_rec *r,
179                                   const char *name)
180 {
181     /* Someone retrieved the optional function., not knowing about the
182      * new API. We redirect them to what they should have invoked. */
183     return ap_ssl_var_lookup(p, s, c, r, name);
184 }
185 
ap_ssl_var_lookup(apr_pool_t * p,server_rec * s,conn_rec * c,request_rec * r,const char * name)186 AP_DECLARE(const char *) ap_ssl_var_lookup(apr_pool_t *p, server_rec *s,
187                                            conn_rec *c, request_rec *r,
188                                            const char *name)
189 {
190     const char *val = ap_run_ssl_var_lookup(p, s, c, r, name);
191     if (val == NULL && module_ssl_var_lookup) {
192         val = module_ssl_var_lookup(p, s, c, r, name);
193     }
194     return val;
195 }
196 
ap_setup_ssl_optional_fns(apr_pool_t * pool)197 AP_DECLARE(void) ap_setup_ssl_optional_fns(apr_pool_t *pool)
198 {
199     /* Run as core's very early 'post config' hook, check for any already
200      * installed optional functions related to SSL and save them. Install
201      * our own instances that invoke the new hooks. */
202     APR_OPTIONAL_FN_TYPE(ssl_is_https) *fn_is_https;
203     APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *fn_ssl_var_lookup;
204 
205     fn_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
206     module_ssl_is_https = (fn_is_https
207         && fn_is_https != ssl_is_https)? fn_is_https : NULL;
208     APR_REGISTER_OPTIONAL_FN(ssl_is_https);
209 
210     fn_ssl_var_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
211     module_ssl_var_lookup = (fn_ssl_var_lookup
212         && fn_ssl_var_lookup != ssl_var_lookup)? fn_ssl_var_lookup : NULL;
213     APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
214 
215     module_ssl_proxy_enable = APR_RETRIEVE_OPTIONAL_FN(ssl_proxy_enable);
216     APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
217     module_ssl_engine_disable = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable);
218     APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
219     module_ssl_engine_set = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_set);
220     APR_REGISTER_OPTIONAL_FN(ssl_engine_set);
221 }
222 
ap_ssl_add_cert_files(server_rec * s,apr_pool_t * p,apr_array_header_t * cert_files,apr_array_header_t * key_files)223 AP_DECLARE(apr_status_t) ap_ssl_add_cert_files(server_rec *s, apr_pool_t *p,
224                                                apr_array_header_t *cert_files,
225                                                apr_array_header_t *key_files)
226 {
227     int rv = ap_run_ssl_add_cert_files(s, p, cert_files, key_files);
228     return (rv == OK || rv == DECLINED)? APR_SUCCESS : APR_EGENERAL;
229 }
230 
ap_ssl_add_fallback_cert_files(server_rec * s,apr_pool_t * p,apr_array_header_t * cert_files,apr_array_header_t * key_files)231 AP_DECLARE(apr_status_t) ap_ssl_add_fallback_cert_files(server_rec *s, apr_pool_t *p,
232                                                         apr_array_header_t *cert_files,
233                                                         apr_array_header_t *key_files)
234 {
235     int rv = ap_run_ssl_add_fallback_cert_files(s, p, cert_files, key_files);
236     return (rv == OK || rv == DECLINED)? APR_SUCCESS : APR_EGENERAL;
237 }
238 
ap_ssl_answer_challenge(conn_rec * c,const char * server_name,const char ** pcert_pem,const char ** pkey_pem)239 AP_DECLARE(int) ap_ssl_answer_challenge(conn_rec *c, const char *server_name,
240                                         const char **pcert_pem, const char **pkey_pem)
241 {
242     return (ap_run_ssl_answer_challenge(c, server_name, pcert_pem, pkey_pem) == OK);
243 }
244 
ap_ssl_ocsp_prime(server_rec * s,apr_pool_t * p,const char * id,apr_size_t id_len,const char * pem)245 AP_DECLARE(apr_status_t) ap_ssl_ocsp_prime(server_rec *s, apr_pool_t *p,
246                                            const char *id, apr_size_t id_len,
247                                            const char *pem)
248 {
249     int rv = ap_run_ssl_ocsp_prime_hook(s, p, id, id_len, pem);
250     return rv == OK? APR_SUCCESS : (rv == DECLINED? APR_ENOENT : APR_EGENERAL);
251 }
252 
ap_ssl_ocsp_get_resp(server_rec * s,conn_rec * c,const char * id,apr_size_t id_len,ap_ssl_ocsp_copy_resp * cb,void * userdata)253 AP_DECLARE(apr_status_t) ap_ssl_ocsp_get_resp(server_rec *s, conn_rec *c,
254                                               const char *id, apr_size_t id_len,
255                                               ap_ssl_ocsp_copy_resp *cb, void *userdata)
256 {
257     int rv = ap_run_ssl_ocsp_get_resp_hook(s, c, id, id_len, cb, userdata);
258     return rv == OK? APR_SUCCESS : (rv == DECLINED? APR_ENOENT : APR_EGENERAL);
259 }
260 
261 AP_IMPLEMENT_HOOK_RUN_FIRST(int, ssl_conn_is_ssl,
262                             (conn_rec *c), (c), DECLINED)
263 AP_IMPLEMENT_HOOK_RUN_FIRST(const char *,ssl_var_lookup,
264         (apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *name),
265         (p, s, c, r, name), NULL)
266 AP_IMPLEMENT_HOOK_RUN_ALL(int, ssl_add_cert_files,
267         (server_rec *s, apr_pool_t *p,
268          apr_array_header_t *cert_files, apr_array_header_t *key_files),
269         (s, p, cert_files, key_files), OK, DECLINED)
270 AP_IMPLEMENT_HOOK_RUN_ALL(int, ssl_add_fallback_cert_files,
271         (server_rec *s, apr_pool_t *p,
272          apr_array_header_t *cert_files, apr_array_header_t *key_files),
273         (s, p, cert_files, key_files), OK, DECLINED)
274 AP_IMPLEMENT_HOOK_RUN_FIRST(int, ssl_answer_challenge,
275         (conn_rec *c, const char *server_name, const char **pcert_pem, const char **pkey_pem),
276         (c, server_name, pcert_pem, pkey_pem), DECLINED)
277 AP_IMPLEMENT_HOOK_RUN_FIRST(int, ssl_ocsp_prime_hook,
278         (server_rec *s, apr_pool_t *p, const char *id, apr_size_t id_len, const char *pem),
279         (s, p, id, id_len, pem), DECLINED)
280 AP_IMPLEMENT_HOOK_RUN_FIRST(int, ssl_ocsp_get_resp_hook,
281          (server_rec *s, conn_rec *c, const char *id, apr_size_t id_len,
282           ap_ssl_ocsp_copy_resp *cb, void *userdata),
283          (s, c, id, id_len, cb, userdata), DECLINED)
284 AP_IMPLEMENT_HOOK_RUN_FIRST(int,ssl_bind_outgoing,(conn_rec *c, ap_conf_vector_t *dir_conf, int require_ssl),
285                             (c, dir_conf, require_ssl), DECLINED)
286