source: mod_gnutls/include/mod_gnutls.h.in @ 2cde8111

debian/masterdebian/stretch-backportsjessie-backportsupstream
Last change on this file since 2cde8111 was 2cde8111, checked in by Thomas Klute <thomas2.klute@…>, 5 years ago

Workarounds for OpenPGP key handling

Commit 031acac9c6541034777f8917633164b51f6bd10a 'Use the new (3.1.3+)
GnuTLS APIs to obtain private keys' led to failed handshakes when using
OpenPGP keys for authentication. Debugging revealed two separate issues,
this commit adds workarounds for both.

The first problem was that the supported certificate types for the
session were not set correctly. This is a known bug in
gnutls_certificate_set_retrieve_function2 [1], the workaround comes from
[2]. The bug should be fixed in GnuTLS 3.3.12, hence the version guard.

After this problem was fixed, segfaults occurred during handshake. A
Valgrind trace showed attemts to access memory that had been free'd in
gnutls_privkey_import_openpgp_raw. I could work around the issue by
loading the key into a gnutls_openpgp_privkey_t structure first and then
importing it into the gnutls_privkey_t using
gnutls_privkey_import_openpgp afterwards.

Thank you to Nikos Mavrogiannopoulos for very fast help with debugging!

[1] https://lists.gnupg.org/pipermail/gnutls-devel/2015-January/007377.html
[2] https://github.com/vanrein/tlspool/commit/4938102d3d1b086491d147e6c8e4e2a02825fc12

  • Property mode set to 100644
File size: 13.5 KB
Line 
1/**
2 *  Copyright 2004-2005 Paul Querna
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  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/* Apache Runtime Headers */
19#include "httpd.h"
20#include "http_config.h"
21#include "http_protocol.h"
22#include "http_connection.h"
23#include "http_request.h"
24#include "http_core.h"
25#include "http_log.h"
26#include "apr_buckets.h"
27#include "apr_strings.h"
28#include "apr_tables.h"
29#include "ap_release.h"
30#include "apr_fnmatch.h"
31/* GnuTLS Library Headers */
32#include <gnutls/gnutls.h>
33#if GNUTLS_VERSION_MAJOR == 2
34#include <gnutls/extra.h>
35#endif
36#include <gnutls/abstract.h>
37#include <gnutls/openpgp.h>
38#include <gnutls/x509.h>
39
40#ifndef __mod_gnutls_h_inc
41#define __mod_gnutls_h_inc
42
43#define HAVE_APR_MEMCACHE    @have_apr_memcache@
44
45extern module AP_MODULE_DECLARE_DATA gnutls_module;
46
47/* IO Filter names */
48#define GNUTLS_OUTPUT_FILTER_NAME "gnutls_output_filter"
49#define GNUTLS_INPUT_FILTER_NAME "gnutls_input_filter"
50/* GnuTLS Constants */
51#define GNUTLS_ENABLED_FALSE 0
52#define GNUTLS_ENABLED_TRUE  1
53#define GNUTLS_ENABLED_UNSET  2
54/* Current module version */
55#define MOD_GNUTLS_VERSION "@MOD_GNUTLS_VERSION@"
56
57/* Module Debug Mode */
58#define MOD_GNUTLS_DEBUG @OOO_MAINTAIN@
59
60/*
61 * Recent Versions of 2.1 renamed several hooks.
62 * This allows us to compile on 2.0.xx
63 */
64#if AP_SERVER_MINORVERSION_NUMBER >= 2 || (AP_SERVER_MINORVERSION_NUMBER == 1 && AP_SERVER_PATCHLEVEL_NUMBER >= 3)
65        #define USING_2_1_RECENT 1
66#else
67        #define USING_2_1_RECENT 0
68#endif
69
70/* mod_gnutls Cache Types */
71typedef enum {
72        /* No Cache */
73    mgs_cache_none,
74        /* Use Old Berkley DB */
75    mgs_cache_dbm,
76        /* Use Gnu's version of Berkley DB */
77    mgs_cache_gdbm,
78#if HAVE_APR_MEMCACHE
79        /* Use Memcache */
80    mgs_cache_memcache,
81#endif
82    mgs_cache_unset
83} mgs_cache_e;
84
85typedef enum {
86    mgs_cvm_unset,
87    mgs_cvm_cartel,
88    mgs_cvm_msva
89} mgs_client_verification_method_e;
90
91
92/* Directory Configuration Record */
93typedef struct {
94    int client_verify_mode;
95    const char* lua_bytecode;
96    apr_size_t lua_bytecode_len;
97} mgs_dirconf_rec;
98
99
100/* The maximum number of certificates to send in a chain */
101#define MAX_CHAIN_SIZE 8
102/* The maximum number of SANs to read from a x509 certificate */
103#define MAX_CERT_SAN 5
104
105/* Server Configuration Record */
106typedef struct {
107    /* --- Configuration values --- */
108        /* Is the module enabled? */
109    int enabled;
110        /* Is mod_proxy enabled? */
111    int proxy_enabled;
112        /* A Plain HTTP request */
113    int non_ssl_request;
114
115    /* PIN used for PKCS #11 operations */
116    char *pin;
117
118    /* the SRK PIN used in TPM operations */
119    char *srk_pin;
120
121    char *x509_cert_file;
122    char *x509_key_file;
123    char *x509_ca_file;
124
125    char *pgp_cert_file;
126    char *pgp_key_file;
127    char *pgp_ring_file;
128
129    char *dh_file;
130
131    char *priorities_str;
132
133    const char* srp_tpasswd_file;
134    const char* srp_tpasswd_conf_file;
135
136        /* Cache timeout value */
137    int cache_timeout;
138        /* Chose Cache Type */
139    mgs_cache_e cache_type;
140    const char* cache_config;
141
142        /* GnuTLS uses Session Tickets */
143    int tickets;
144
145    /* --- Things initialized at _child_init --- */
146
147        /* x509 Certificate Structure */
148    gnutls_certificate_credentials_t certs;
149        /* SRP Certificate Structure*/
150    gnutls_srp_server_credentials_t srp_creds;
151        /* Annonymous Certificate Structure */
152    gnutls_anon_server_credentials_t anon_creds;
153        /* Current x509 Certificate CN [Common Name] */
154    char* cert_cn;
155        /* Current x509 Certificate SAN [Subject Alternate Name]s*/
156    char* cert_san[MAX_CERT_SAN];
157        /* An x509 Certificate Chain */
158    gnutls_pcert_st *certs_x509_chain;
159    gnutls_x509_crt_t *certs_x509_crt_chain;
160        /* Number of Certificates in Chain */
161    unsigned int certs_x509_chain_num;
162
163        /* Current x509 Certificate Private Key */
164    gnutls_privkey_t privkey_x509;
165
166        /* OpenPGP Certificate */
167    gnutls_pcert_st *cert_pgp;
168    gnutls_openpgp_crt_t *cert_crt_pgp;
169
170        /* OpenPGP Certificate Private Key */
171    gnutls_privkey_t privkey_pgp;
172    /* Internal structure for the OpenPGP private key. DO NOT USE
173     * outside key loading. */
174    gnutls_openpgp_privkey_t privkey_pgp_internal;
175
176    /* Export full certificates to CGI environment: */
177    int export_certificates_size;
178        /* GnuTLS Priorities */
179    gnutls_priority_t priorities;
180        /* GnuTLS DH Parameters */
181    gnutls_dh_params_t dh_params;
182        /* A list of CA Certificates */
183    gnutls_x509_crt_t *ca_list;
184        /* OpenPGP Key Ring */
185    gnutls_openpgp_keyring_t pgp_list;
186        /* CA Certificate list size */
187    unsigned int ca_list_size;
188        /* Client Certificate Verification Mode */
189    int client_verify_mode;
190        /* Client Certificate Verification Method */
191    mgs_client_verification_method_e client_verify_method;
192        /* Last Cache timestamp */
193    apr_time_t last_cache_check;
194} mgs_srvconf_rec;
195
196/* Character Buffer */
197typedef struct {
198    int length;
199    char *value;
200} mgs_char_buffer_t;
201
202/* GnuTLS Handle */
203typedef struct {
204        /* Server configuration record */
205    mgs_srvconf_rec *sc;
206        /* Connection record */
207    conn_rec* c;
208        /* Is TLS enabled for this connection? */
209    int enabled;
210        /* GnuTLS Session handle */
211    gnutls_session_t session;
212        /* module input status */
213    apr_status_t input_rc;
214        /* Input filter */
215    ap_filter_t *input_filter;
216        /* Input Bucket Brigade */
217    apr_bucket_brigade *input_bb;
218        /* Input Read Type */
219    apr_read_type_e input_block;
220        /* Input Mode */
221    ap_input_mode_t input_mode;
222        /* Input Character Buffer */
223    mgs_char_buffer_t input_cbuf;
224        /* Input Character Array */
225    char input_buffer[AP_IOBUFSIZE];
226        /* module Output status */
227    apr_status_t output_rc;
228        /* Output filter */
229    ap_filter_t *output_filter;
230        /* Output Bucket Brigade */
231    apr_bucket_brigade *output_bb;
232        /* Output character array */
233    char output_buffer[AP_IOBUFSIZE];
234        /* Output buffer length */
235    apr_size_t output_blen;
236        /* Output length */
237    apr_size_t output_length;
238        /* General Status */
239    int status;
240} mgs_handle_t;
241
242
243
244/** Functions in gnutls_io.c **/
245
246/* apr_signal_block() for blocking SIGPIPE */
247apr_status_t apr_signal_block(int signum);
248
249 /* Proxy Support */
250/* An optional function which returns non-zero if the given connection
251is using SSL/TLS. */
252APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
253/* The ssl_proxy_enable() and ssl_engine_disable() optional functions
254 * are used by mod_proxy to enable use of SSL for outgoing
255 * connections. */
256APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));
257APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
258int ssl_is_https(conn_rec *c);
259int ssl_proxy_enable(conn_rec *c);
260int ssl_engine_disable(conn_rec *c);
261const char *mgs_set_proxy_engine(cmd_parms * parms, void *dummy,
262    const char *arg);
263apr_status_t mgs_cleanup_pre_config(void *data);
264
265/**
266 * mgs_filter_input will filter the input data
267 * by decrypting it using GnuTLS and passes it cleartext.
268 *
269 * @param f     the filter info record
270 * @param bb    the bucket brigade, where to store the result to
271 * @param mode  what shall we read?
272 * @param block a block index we shall read from?
273 * @return result status
274 */
275apr_status_t mgs_filter_input(ap_filter_t * f,
276                                     apr_bucket_brigade * bb,
277                                     ap_input_mode_t mode,
278                                     apr_read_type_e block,
279                                     apr_off_t readbytes);
280
281/**
282 * mgs_filter_output will filter the encrypt
283 * the incoming bucket using GnuTLS and passes it onto the next filter.
284 *
285 * @param f     the filter info record
286 * @param bb    the bucket brigade, where to store the result to
287 * @return result status
288 */
289apr_status_t mgs_filter_output(ap_filter_t * f,
290                                      apr_bucket_brigade * bb);
291
292
293/**
294 * mgs_transport_read is called from GnuTLS to provide encrypted
295 * data from the client.
296 *
297 * @param ptr     pointer to the filter context
298 * @param buffer  place to put data
299 * @param len     maximum size
300 * @return size   length of the data stored in buffer
301 */
302ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr,
303                                  void *buffer, size_t len);
304
305/**
306 * mgs_transport_write is called from GnuTLS to
307 * write data to the client.
308 *
309 * @param ptr     pointer to the filter context
310 * @param buffer  buffer to write to the client
311 * @param len     size of the buffer
312 * @return size   length of the data written
313 */
314ssize_t mgs_transport_write(gnutls_transport_ptr_t ptr,
315                                   const void *buffer, size_t len);
316
317
318int mgs_rehandshake(mgs_handle_t * ctxt);
319
320
321
322/**
323 * Init the Cache after Configuration is done
324 */
325int mgs_cache_post_config(apr_pool_t *p, server_rec *s,
326                                 mgs_srvconf_rec *sc);
327/**
328 * Init the Cache inside each Process
329 */
330int mgs_cache_child_init(apr_pool_t *p, server_rec *s,
331                                mgs_srvconf_rec *sc);
332/**
333 * Setup the Session Caching
334 */
335int mgs_cache_session_init(mgs_handle_t *ctxt);
336
337#define GNUTLS_SESSION_ID_STRING_LEN \
338    ((GNUTLS_MAX_SESSION_ID + 1) * 2)
339
340/**
341 * Perform any reinitialization required in PKCS #11
342 */
343int mgs_pkcs11_reinit(server_rec * s);
344
345/**
346 * Convert a SSL Session ID into a Null Terminated Hex Encoded String
347 * @param id raw SSL Session ID
348 * @param idlen Length of the raw Session ID
349 * @param str Location to store the Hex Encoded String
350 * @param strsize The Maximum Length that can be stored in str
351 */
352char *mgs_session_id2sz(unsigned char *id, int idlen,
353                                char *str, int strsize);
354
355/**
356 * Convert a time_t into a Null Terminated String
357 * @param t time_t time
358 * @param str Location to store the Hex Encoded String
359 * @param strsize The Maximum Length that can be stored in str
360 */
361char *mgs_time2sz(time_t t, char *str, int strsize);
362
363
364/* Configuration Functions */
365
366/* Loads all files set in the configuration */
367int mgs_load_files(apr_pool_t * p, server_rec * s);
368
369const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy,
370                                        const char *arg);
371const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy,
372                                        const char *arg);
373const char *mgs_set_dh_file(cmd_parms * parms, void *dummy,
374                                        const char *arg);
375const char *mgs_set_cert_file(cmd_parms * parms, void *dummy,
376                                        const char *arg);
377
378const char *mgs_set_key_file(cmd_parms * parms, void *dummy,
379                             const char *arg);
380
381const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy,
382                                        const char *arg);
383
384const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy,
385                             const char *arg);
386
387const char *mgs_set_cache(cmd_parms * parms, void *dummy,
388                          const char *type, const char* arg);
389
390const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy,
391                                  const char *arg);
392
393const char *mgs_set_client_verify(cmd_parms * parms, void *dummy,
394                                  const char *arg);
395
396const char *mgs_set_client_verify_method(cmd_parms * parms, void *dummy,
397                                         const char *arg);
398
399const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy,
400                                   const char *arg);
401const char *mgs_set_pin(cmd_parms * parms, void *dummy,
402                                   const char *arg);
403
404const char *mgs_set_srk_pin(cmd_parms * parms, void *dummy,
405                                   const char *arg);
406
407const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy,
408                                   const char *arg);
409
410const char *mgs_set_enabled(cmd_parms * parms, void *dummy,
411                            const char *arg);
412const char *mgs_set_export_certificates_size(cmd_parms * parms, void *dummy,
413                            const char *arg);
414const char *mgs_set_priorities(cmd_parms * parms, void *dummy,
415                            const char *arg);
416const char *mgs_set_tickets(cmd_parms * parms, void *dummy,
417                            const char *arg);
418
419const char *mgs_set_require_section(cmd_parms *cmd,
420                                    void *mconfig, const char *arg);
421void *mgs_config_server_create(apr_pool_t * p, server_rec * s);
422void *mgs_config_server_merge(apr_pool_t *p, void *BASE, void *ADD);
423
424void *mgs_config_dir_merge(apr_pool_t *p, void *basev, void *addv);
425
426void *mgs_config_dir_create(apr_pool_t *p, char *dir);
427
428const char *mgs_set_require_bytecode(cmd_parms *cmd,
429                                    void *mconfig, const char *arg);
430
431mgs_srvconf_rec* mgs_find_sni_server(gnutls_session_t session);
432
433/* mod_gnutls Hooks. */
434
435int mgs_hook_pre_config(apr_pool_t * pconf,
436                        apr_pool_t * plog, apr_pool_t * ptemp);
437
438int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
439                         apr_pool_t * ptemp,
440                         server_rec * base_server);
441
442void mgs_hook_child_init(apr_pool_t *p, server_rec *s);
443
444const char *mgs_hook_http_scheme(const request_rec * r);
445
446apr_port_t mgs_hook_default_port(const request_rec * r);
447
448int mgs_hook_pre_connection(conn_rec * c, void *csd);
449
450int mgs_hook_fixups(request_rec *r);
451
452int mgs_hook_authz(request_rec *r);
453
454#endif /*  __mod_gnutls_h_inc */
Note: See TracBrowser for help on using the repository browser.