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
http_post_header(apr_pool_t * p,apr_uri_t * uri,const char * content_type,const char * accept,apr_size_t size)23 const 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
sock_send_buf(apr_socket_t * sock,const char * buf,const apr_size_t size)40 apr_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
read_line(apr_pool_t * p,apr_bucket_brigade * sockb,apr_bucket_brigade * lineb)62 const 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
datum_from_file(apr_pool_t * p,const char * filename,gnutls_datum_t * datum)91 apr_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 && \
117 !(defined(__clang__) && __has_builtin(__builtin_add_overflow))
118 if (__builtin_expect(br > UINT_MAX, 0))
119 return APR_EINVAL;
120 else
121 datum->size = (unsigned int) br;
122 #else
123 if (__builtin_add_overflow(br, 0, &datum->size))
124 return APR_EINVAL;
125 #endif
126
127 return rv;
128 }
129
130
131
init_gnutls_ctxt(conn_rec * c)132 mgs_handle_t *init_gnutls_ctxt(conn_rec *c)
133 {
134 mgs_handle_t *ctxt = (mgs_handle_t *)
135 ap_get_module_config(c->conn_config, &gnutls_module);
136 if (ctxt == NULL)
137 {
138 ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
139 ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
140
141 /* Get mod_gnutls server configuration */
142 mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
143 ap_get_module_config(c->base_server->module_config,
144 &gnutls_module);
145
146 /* Set up connection and server references */
147 ctxt->c = c;
148 ctxt->sc = sc;
149 /* Default, unconditionally changed in proxy setup functions */
150 ctxt->is_proxy = GNUTLS_ENABLED_FALSE;
151 }
152 return ctxt;
153 }
154