source: mod_gnutls/src/gnutls_util.c @ a14cf5c

debian/master
Last change on this file since a14cf5c was a14cf5c, checked in by Fiona Klute <fiona.klute@…>, 11 months ago

Store SNI hostname in mod_gnutls' connection context

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/*
2 *  Copyright 2016-2018 Fiona Klute
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#include "gnutls_util.h"
18
19#include <apr_strings.h>
20#include <gnutls/gnutls.h>
21
22
23const char* http_post_header(apr_pool_t *p, apr_uri_t *uri,
24                             const char *content_type, const char *accept,
25                             apr_size_t size)
26{
27    return apr_psprintf(p, "POST %s HTTP/1.0\r\n"
28                        "Host: %s\r\n"
29                        "Content-Type: %s\r\n"
30                        "Accept: %s\r\n"
31                        "Content-Length: %" APR_SIZE_T_FMT "\r\n\r\n",
32                        apr_uri_unparse(p, uri, APR_URI_UNP_OMITSITEPART),
33                        uri->hostname, content_type,
34                        accept != NULL ? accept : "*/*",
35                        size);
36}
37
38
39
40apr_status_t sock_send_buf(apr_socket_t *sock, const char *buf,
41                           const apr_size_t size)
42{
43    apr_status_t rv = APR_EINIT;
44    apr_size_t len = 0;
45    for (apr_size_t sent = 0; sent < size; sent += len)
46    {
47        len = size - sent;
48        rv = apr_socket_send(sock, buf + sent, &len);
49        /* API documentation for apr_socket_send(): "It is possible
50         * for both bytes to be sent and an error to be returned."
51         *
52         * So break if there was an error, unless bytes were also
53         * sent. In the latter case try to continue. */
54        if (rv != APR_SUCCESS && len == 0)
55            break;
56    }
57    return rv;
58}
59
60
61
62const char* read_line(apr_pool_t *p, apr_bucket_brigade *sockb,
63                      apr_bucket_brigade *lineb)
64{
65    apr_brigade_cleanup(lineb);
66    apr_status_t rv = apr_brigade_split_line(lineb, sockb,
67                                             APR_BLOCK_READ,
68                                             HTTP_HDR_LINE_MAX);
69    if (rv != APR_SUCCESS)
70        return NULL;
71
72    char *line;
73    apr_size_t len;
74    rv = apr_brigade_pflatten(lineb, &line, &len, p);
75    if (rv != APR_SUCCESS)
76        return NULL;
77
78    /* The last two characters on a correct header line are
79     * "\r\n". Switch \r to \0 to chomp off the line break. */
80    if (len >= 2 && line[len-1] == '\n' && line[len-2] == '\r')
81    {
82        line[len-2] = '\0';
83        return line;
84    }
85    else
86        return NULL;
87}
88
89
90
91apr_status_t datum_from_file(apr_pool_t *p, const char* filename,
92                             gnutls_datum_t *datum)
93{
94    apr_status_t rv = APR_EINIT;
95    apr_file_t *file;
96    apr_finfo_t finfo;
97    apr_size_t br = 0;
98    rv = apr_file_open(&file, filename,
99                       APR_READ | APR_BINARY, APR_OS_DEFAULT, p);
100    if (rv != APR_SUCCESS)
101        return rv;
102
103    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, file);
104    if (rv != APR_SUCCESS)
105        return rv;
106
107    datum->data = apr_palloc(p, finfo.size);
108    rv = apr_file_read_full(file, datum->data, finfo.size, &br);
109    if (rv != APR_SUCCESS)
110        return rv;
111
112    apr_file_close(file);
113
114    /* safe integer type conversion: unsigned int and apr_size_t might
115     * have different sizes */
116#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
117    if (__builtin_expect(br > UINT_MAX, 0))
118        return APR_EINVAL;
119    else
120        datum->size = (unsigned int) br;
121#else
122    if (__builtin_add_overflow(br, 0, &datum->size))
123        return APR_EINVAL;
124#endif
125
126    return rv;
127}
128
129
130
131mgs_handle_t *init_gnutls_ctxt(conn_rec *c)
132{
133    mgs_handle_t *ctxt = (mgs_handle_t *)
134        ap_get_module_config(c->conn_config, &gnutls_module);
135    if (ctxt == NULL)
136    {
137        ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
138        ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
139
140        /* Get mod_gnutls server configuration */
141        mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
142            ap_get_module_config(c->base_server->module_config,
143                                 &gnutls_module);
144
145        /* Set up connection and server references */
146        ctxt->c = c;
147        ctxt->sc = sc;
148        /* Default, unconditionally changed in proxy setup functions */
149        ctxt->is_proxy = GNUTLS_ENABLED_FALSE;
150        /* Other default values */
151        ctxt->sni_name = NULL;
152    }
153    return ctxt;
154}
Note: See TracBrowser for help on using the repository browser.