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 | |
---|
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 | |
---|
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 | |
---|
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 | |
---|
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 && !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 | |
---|
131 | mgs_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 | } |
---|
151 | return ctxt; |
---|
152 | } |
---|