Coverage Report

Created: 2023-03-26 06:28

/src/httpd/server/ssl.c
Line
Count
Source (jump to first uncovered line)
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_lib.h"
25
#include "apr_signal.h"
26
#include "apr_strmatch.h"
27
28
#define APR_WANT_STRFUNC
29
#define APR_WANT_MEMFUNC
30
#include "apr_want.h"
31
32
#include "ap_config.h"
33
#include "httpd.h"
34
#include "http_core.h"
35
#include "http_connection.h"
36
#include "http_protocol.h"
37
#include "http_request.h"
38
#include "http_ssl.h"
39
#include "http_log.h"           /* For errors detected in basic auth common
40
                                 * support code... */
41
#include "mod_core.h"
42
43
#if APR_HAVE_STDARG_H
44
#include <stdarg.h>
45
#endif
46
#if APR_HAVE_UNISTD_H
47
#include <unistd.h>
48
#endif
49
50
/* we know core's module_index is 0 */
51
#undef APLOG_MODULE_INDEX
52
#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
53
54
APR_HOOK_STRUCT(
55
    APR_HOOK_LINK(ssl_conn_is_ssl)
56
    APR_HOOK_LINK(ssl_var_lookup)
57
    APR_HOOK_LINK(ssl_add_cert_files)
58
    APR_HOOK_LINK(ssl_add_fallback_cert_files)
59
    APR_HOOK_LINK(ssl_answer_challenge)
60
    APR_HOOK_LINK(ssl_ocsp_prime_hook)
61
    APR_HOOK_LINK(ssl_ocsp_get_resp_hook)
62
    APR_HOOK_LINK(ssl_bind_outgoing)
63
)
64
65
APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
66
static APR_OPTIONAL_FN_TYPE(ssl_is_https) *module_ssl_is_https;
67
APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));
68
static APR_OPTIONAL_FN_TYPE(ssl_proxy_enable) *module_ssl_proxy_enable;
69
APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
70
static APR_OPTIONAL_FN_TYPE(ssl_engine_disable) *module_ssl_engine_disable;
71
APR_DECLARE_OPTIONAL_FN(int, ssl_engine_set, (conn_rec *,
72
                                              ap_conf_vector_t *,
73
                                              int proxy, int enable));
74
static APR_OPTIONAL_FN_TYPE(ssl_engine_set) *module_ssl_engine_set;
75
76
77
static int ssl_is_https(conn_rec *c)
78
0
{
79
    /* Someone retrieved the optional function., not knowing about the
80
     * new API. We redirect them to what they should have invoked. */
81
0
    return ap_ssl_conn_is_ssl(c);
82
0
}
83
84
AP_DECLARE(int) ap_ssl_conn_is_ssl(conn_rec *c)
85
0
{
86
0
    int r = (ap_run_ssl_conn_is_ssl(c) == OK);
87
0
    if (r == 0 && module_ssl_is_https) {
88
0
        r = module_ssl_is_https(c);
89
0
    }
90
0
    return r;
91
0
}
92
93
static int ssl_engine_set(conn_rec *c,
94
                          ap_conf_vector_t *per_dir_config,
95
                          int proxy, int enable)
96
0
{
97
0
    if (proxy) {
98
0
        return ap_ssl_bind_outgoing(c, per_dir_config, enable) == OK;
99
0
    }
100
0
    else if (module_ssl_engine_set) {
101
0
        return module_ssl_engine_set(c, per_dir_config, 0, enable);
102
0
    }
103
0
    else if (enable && module_ssl_proxy_enable) {
104
0
        return module_ssl_proxy_enable(c);
105
0
    }
106
0
    else if (!enable && module_ssl_engine_disable) {
107
0
        return module_ssl_engine_disable(c);
108
0
    }
109
0
    return 0;
110
0
}
111
112
static int ssl_proxy_enable(conn_rec *c)
113
0
{
114
0
    return ap_ssl_bind_outgoing(c, NULL, 1);
115
0
}
116
117
static int ssl_engine_disable(conn_rec *c)
118
0
{
119
0
    return ap_ssl_bind_outgoing(c, NULL, 0);
120
0
}
121
122
AP_DECLARE(int) ap_ssl_bind_outgoing(conn_rec *c, struct ap_conf_vector_t *dir_conf,
123
                                     int enable_ssl)
124
0
{
125
0
    int rv, enabled = 0;
126
127
0
    c->outgoing = 1;
128
0
    rv = ap_run_ssl_bind_outgoing(c, dir_conf, enable_ssl);
129
0
    enabled = (rv == OK);
130
0
    if (enable_ssl && !enabled) {
131
        /* the hooks did not take over. Is there an old skool optional that will? */
132
0
        if (module_ssl_engine_set) {
133
0
            enabled = module_ssl_engine_set(c, dir_conf, 1, 1);
134
0
        }
135
0
        else if (module_ssl_proxy_enable) {
136
0
            enabled = module_ssl_proxy_enable(c);
137
0
        }
138
0
    }
139
0
    else {
140
        /* !enable_ssl || enabled
141
         * any existing optional funcs need to not enable here */
142
0
        if (module_ssl_engine_set) {
143
0
            module_ssl_engine_set(c, dir_conf, 1, 0);
144
0
        }
145
0
        else if (module_ssl_engine_disable) {
146
0
            module_ssl_engine_disable(c);
147
0
        }
148
0
    }
149
0
    if (enable_ssl && !enabled) {
150
0
        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0,
151
0
                      c, APLOGNO(01961) " failed to enable ssl support "
152
0
                      "[Hint: if using mod_ssl, see SSLProxyEngine]");
153
0
        return DECLINED;
154
0
    }
155
0
    return OK;
156
0
}
157
158
AP_DECLARE(int) ap_ssl_has_outgoing_handlers(void)
159
0
{
160
0
    apr_array_header_t *hooks = ap_hook_get_ssl_bind_outgoing();
161
0
    return (hooks && hooks->nelts > 0)
162
0
        || module_ssl_engine_set || module_ssl_proxy_enable;
163
0
}
164
165
APR_DECLARE_OPTIONAL_FN(const char *, ssl_var_lookup,
166
                        (apr_pool_t *p, server_rec *s,
167
                         conn_rec *c, request_rec *r,
168
                         const char *name))
169
    AP_FN_ATTR_NONNULL((1, 2, 5)) AP_FN_ATTR_WARN_UNUSED_RESULT;
170
static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *module_ssl_var_lookup;
171
172
static const char *ssl_var_lookup(apr_pool_t *p, server_rec *s,
173
                                  conn_rec *c, request_rec *r,
174
                                  const char *name)
175
0
{
176
    /* Someone retrieved the optional function., not knowing about the
177
     * new API. We redirect them to what they should have invoked. */
178
0
    return ap_ssl_var_lookup(p, s, c, r, name);
179
0
}
180
181
AP_DECLARE(const char *) ap_ssl_var_lookup(apr_pool_t *p, server_rec *s,
182
                                           conn_rec *c, request_rec *r,
183
                                           const char *name)
184
0
{
185
0
    const char *val = ap_run_ssl_var_lookup(p, s, c, r, name);
186
0
    if (val == NULL && module_ssl_var_lookup) {
187
0
        val = module_ssl_var_lookup(p, s, c, r, name);
188
0
    }
189
0
    return val;
190
0
}
191
192
AP_DECLARE(void) ap_setup_ssl_optional_fns(apr_pool_t *pool)
193
0
{
194
    /* Run as core's very early 'post config' hook, check for any already
195
     * installed optional functions related to SSL and save them. Install
196
     * our own instances that invoke the new hooks. */
197
0
    APR_OPTIONAL_FN_TYPE(ssl_is_https) *fn_is_https;
198
0
    APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *fn_ssl_var_lookup;
199
200
0
    fn_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
201
0
    module_ssl_is_https = (fn_is_https
202
0
        && fn_is_https != ssl_is_https)? fn_is_https : NULL;
203
0
    APR_REGISTER_OPTIONAL_FN(ssl_is_https);
204
205
0
    fn_ssl_var_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
206
0
    module_ssl_var_lookup = (fn_ssl_var_lookup
207
0
        && fn_ssl_var_lookup != ssl_var_lookup)? fn_ssl_var_lookup : NULL;
208
0
    APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
209
210
0
    module_ssl_proxy_enable = APR_RETRIEVE_OPTIONAL_FN(ssl_proxy_enable);
211
0
    APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
212
0
    module_ssl_engine_disable = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable);
213
0
    APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
214
0
    module_ssl_engine_set = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_set);
215
0
    APR_REGISTER_OPTIONAL_FN(ssl_engine_set);
216
0
}
217
218
AP_DECLARE(apr_status_t) ap_ssl_add_cert_files(server_rec *s, apr_pool_t *p,
219
                                               apr_array_header_t *cert_files,
220
                                               apr_array_header_t *key_files)
221
0
{
222
0
    int rv = ap_run_ssl_add_cert_files(s, p, cert_files, key_files);
223
0
    return (rv == OK || rv == DECLINED)? APR_SUCCESS : APR_EGENERAL;
224
0
}
225
226
AP_DECLARE(apr_status_t) ap_ssl_add_fallback_cert_files(server_rec *s, apr_pool_t *p,
227
                                                        apr_array_header_t *cert_files,
228
                                                        apr_array_header_t *key_files)
229
0
{
230
0
    int rv = ap_run_ssl_add_fallback_cert_files(s, p, cert_files, key_files);
231
0
    return (rv == OK || rv == DECLINED)? APR_SUCCESS : APR_EGENERAL;
232
0
}
233
234
AP_DECLARE(int) ap_ssl_answer_challenge(conn_rec *c, const char *server_name,
235
                                        const char **pcert_pem, const char **pkey_pem)
236
0
{
237
0
    return (ap_run_ssl_answer_challenge(c, server_name, pcert_pem, pkey_pem) == OK);
238
0
}
239
240
AP_DECLARE(apr_status_t) ap_ssl_ocsp_prime(server_rec *s, apr_pool_t *p,
241
                                           const char *id, apr_size_t id_len,
242
                                           const char *pem)
243
0
{
244
0
    int rv = ap_run_ssl_ocsp_prime_hook(s, p, id, id_len, pem);
245
0
    return rv == OK? APR_SUCCESS : (rv == DECLINED? APR_ENOENT : APR_EGENERAL);
246
0
}
247
248
AP_DECLARE(apr_status_t) ap_ssl_ocsp_get_resp(server_rec *s, conn_rec *c,
249
                                              const char *id, apr_size_t id_len,
250
                                              ap_ssl_ocsp_copy_resp *cb, void *userdata)
251
0
{
252
0
    int rv = ap_run_ssl_ocsp_get_resp_hook(s, c, id, id_len, cb, userdata);
253
0
    return rv == OK? APR_SUCCESS : (rv == DECLINED? APR_ENOENT : APR_EGENERAL);
254
0
}
255
256
AP_IMPLEMENT_HOOK_RUN_FIRST(int, ssl_conn_is_ssl,
257
                            (conn_rec *c), (c), DECLINED)
258
AP_IMPLEMENT_HOOK_RUN_FIRST(const char *,ssl_var_lookup,
259
        (apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *name),
260
        (p, s, c, r, name), NULL)
261
AP_IMPLEMENT_HOOK_RUN_ALL(int, ssl_add_cert_files,
262
        (server_rec *s, apr_pool_t *p,
263
         apr_array_header_t *cert_files, apr_array_header_t *key_files),
264
        (s, p, cert_files, key_files), OK, DECLINED)
265
AP_IMPLEMENT_HOOK_RUN_ALL(int, ssl_add_fallback_cert_files,
266
        (server_rec *s, apr_pool_t *p,
267
         apr_array_header_t *cert_files, apr_array_header_t *key_files),
268
        (s, p, cert_files, key_files), OK, DECLINED)
269
AP_IMPLEMENT_HOOK_RUN_FIRST(int, ssl_answer_challenge,
270
        (conn_rec *c, const char *server_name, const char **pcert_pem, const char **pkey_pem),
271
        (c, server_name, pcert_pem, pkey_pem), DECLINED)
272
AP_IMPLEMENT_HOOK_RUN_FIRST(int, ssl_ocsp_prime_hook,
273
        (server_rec *s, apr_pool_t *p, const char *id, apr_size_t id_len, const char *pem),
274
        (s, p, id, id_len, pem), DECLINED)
275
AP_IMPLEMENT_HOOK_RUN_FIRST(int, ssl_ocsp_get_resp_hook,
276
         (server_rec *s, conn_rec *c, const char *id, apr_size_t id_len,
277
          ap_ssl_ocsp_copy_resp *cb, void *userdata),
278
         (s, c, id, id_len, cb, userdata), DECLINED)
279
AP_IMPLEMENT_HOOK_RUN_FIRST(int,ssl_bind_outgoing,(conn_rec *c, ap_conf_vector_t *dir_conf, int require_ssl),
280
                            (c, dir_conf, require_ssl), DECLINED)