1 |
/* |
2 |
* Copyright (C) 2002 Nikos Mavroyanopoulos |
3 |
* |
4 |
* This file is part of Hydra webserver. |
5 |
* |
6 |
* Hydra is free software; you can redistribute it and/or modify |
7 |
* it under the terms of the GNU General Public License as published by |
8 |
* the Free Software Foundation; either version 2 of the License, or |
9 |
* (at your option) any later version. |
10 |
* |
11 |
* Hydra is distributed in the hope that it will be useful, |
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
* GNU General Public License for more details. |
15 |
* |
16 |
* You should have received a copy of the GNU General Public License |
17 |
* along with this program; if not, write to the Free Software |
18 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
19 |
*/ |
20 |
|
21 |
#include "boa.h" |
22 |
#include <gnutls/x509.h> |
23 |
|
24 |
#ifdef ENABLE_SSL |
25 |
extern int ssl_verify; |
26 |
#endif |
27 |
|
28 |
/* |
29 |
* Name: add_cgi_env_ssl |
30 |
* |
31 |
* Description: Adds the required environment variables for SSL |
32 |
* secured sessions. |
33 |
* |
34 |
* Return values: |
35 |
* 0 on failure, 1 otherwise. |
36 |
*/ |
37 |
int complete_env_ssl(request * req) |
38 |
{ |
39 |
#ifdef ENABLE_SSL |
40 |
|
41 |
#define CTIME "%b %d %k:%M:%S %Y %Z" |
42 |
|
43 |
#ifndef GNUTLS_MAX_SESSION_ID |
44 |
# define GNUTLS_MAX_SESSION_ID 32 |
45 |
#endif |
46 |
char session_id[GNUTLS_MAX_SESSION_ID]; |
47 |
int session_id_length = sizeof(session_id); |
48 |
int i, ret; |
49 |
char str_session_id[(GNUTLS_MAX_SESSION_ID * 2) + 1]; |
50 |
size_t size; |
51 |
|
52 |
if (!add_cgi_env(req, "SSL_PROTOCOL", |
53 |
gnutls_protocol_get_name(gnutls_protocol_get_version |
54 |
(req->ssl_state)), 0)) |
55 |
return 0; |
56 |
|
57 |
if (!add_cgi_env(req, "HTTPS", "on", 0)) |
58 |
return 0; |
59 |
|
60 |
if (!add_cgi_env(req, "SSL_CLIENT_VERIFY", req->certificate_verified, 0)) |
61 |
return 0; |
62 |
|
63 |
{ |
64 |
char version[20] = "GnuTLS/"; |
65 |
strcat(version, gnutls_check_version(NULL)); |
66 |
if (!add_cgi_env(req, "SSL_VERSION_LIBRARY", version, 0)) |
67 |
return 0; |
68 |
} |
69 |
|
70 |
{ |
71 |
unsigned int type = 0; |
72 |
|
73 |
size = sizeof(str_session_id); |
74 |
ret = gnutls_server_name_get( req->ssl_state, str_session_id, &size, &type, 0); |
75 |
|
76 |
if (ret == 0 && type == GNUTLS_NAME_DNS) |
77 |
if (!add_cgi_env(req, "SSL_CLIENT_SERVER_NAME", str_session_id, 0)) |
78 |
return 0; |
79 |
} |
80 |
|
81 |
if (!add_cgi_env(req, "SSL_VERSION_INTERFACE", SERVER_NAME"/"SERVER_VERSION, 0)) |
82 |
return 0; |
83 |
|
84 |
if (!add_cgi_env(req, "SSL_CIPHER", |
85 |
gnutls_cipher_suite_get_name(gnutls_kx_get |
86 |
(req->ssl_state), |
87 |
gnutls_cipher_get(req->ssl_state), |
88 |
gnutls_mac_get(req->ssl_state)), 0)) |
89 |
return 0; |
90 |
|
91 |
|
92 |
{ |
93 |
char buf[22]; |
94 |
char *p; |
95 |
int keysize = |
96 |
gnutls_cipher_get_key_size(gnutls_cipher_get(req->ssl_state)) * |
97 |
8; |
98 |
simple_itoa(keysize, buf); |
99 |
|
100 |
if (!add_cgi_env(req, "SSL_CIPHER_ALGKEYSIZE", buf, 0)) |
101 |
return 0; |
102 |
|
103 |
if (!add_cgi_env(req, "SSL_CIPHER_USEKEYSIZE", buf, 0)) |
104 |
return 0; |
105 |
|
106 |
if (keysize <= 40) |
107 |
p = "true"; |
108 |
else |
109 |
p = "false"; |
110 |
|
111 |
if (!add_cgi_env(req, "SSL_CIPHER_EXPORT", p, 0)) |
112 |
return 0; |
113 |
} |
114 |
|
115 |
/* generate a printable (HEX) session ID */ |
116 |
if (gnutls_session_get_id |
117 |
(req->ssl_state, session_id, &session_id_length) >= 0) { |
118 |
char *p = str_session_id; |
119 |
|
120 |
for (i = 0; i < session_id_length; i++) { |
121 |
*p++ = HEX((session_id[i] >> 4) & 0x0f); |
122 |
*p++ = HEX((session_id[i]) & 0x0f); |
123 |
} |
124 |
*p = 0; |
125 |
|
126 |
if (!add_cgi_env(req, "SSL_SESSION_ID", str_session_id, 0)) |
127 |
return 0; |
128 |
} |
129 |
|
130 |
{ |
131 |
const gnutls_datum *cert_list; |
132 |
char buf[512]; |
133 |
int cert_list_size, ret; |
134 |
gnutls_x509_crt crt; |
135 |
|
136 |
buf[0] = 0; |
137 |
|
138 |
cert_list = gnutls_certificate_get_ours(req->ssl_state); |
139 |
|
140 |
/* Generate the server's DN |
141 |
*/ |
142 |
if (cert_list) { |
143 |
char serial[64]; |
144 |
char str_serial[129]; |
145 |
time_t vtime; |
146 |
struct tm vtm; |
147 |
|
148 |
ret = gnutls_x509_crt_init( &crt); |
149 |
if (ret < 0) { |
150 |
return 0; |
151 |
} |
152 |
|
153 |
ret = gnutls_x509_crt_import( crt, &cert_list[0], GNUTLS_X509_FMT_DER); |
154 |
if (ret < 0) { |
155 |
gnutls_x509_crt_deinit( crt); |
156 |
return 0; |
157 |
} |
158 |
|
159 |
size = sizeof(buf); |
160 |
if (gnutls_x509_crt_get_dn( crt, buf, &size) < 0) strcpy(buf, "Unknown"); |
161 |
|
162 |
if (!add_cgi_env(req, "SSL_SERVER_S_DN", buf, 0)) { |
163 |
gnutls_x509_crt_deinit( crt); |
164 |
return 0; |
165 |
} |
166 |
|
167 |
size = sizeof(buf); |
168 |
if (gnutls_x509_crt_get_issuer_dn( crt, buf, &size) < 0) |
169 |
strcpy( buf, "Unknown"); |
170 |
|
171 |
if (!add_cgi_env(req, "SSL_SERVER_I_DN", buf, 0)) { |
172 |
gnutls_x509_crt_deinit( crt); |
173 |
return 0; |
174 |
} |
175 |
|
176 |
size = sizeof(serial); |
177 |
if (gnutls_x509_crt_get_serial( crt, serial, &size) >= 0) |
178 |
{ |
179 |
char *p = str_serial; |
180 |
|
181 |
for (i = 0; i < size; i++) { |
182 |
*p++ = HEX((serial[i] >> 4) & 0x0f); |
183 |
*p++ = HEX((serial[i]) & 0x0f); |
184 |
} |
185 |
*p = 0; |
186 |
|
187 |
if (!add_cgi_env(req, "SSL_SERVER_M_SERIAL", str_serial, 0)) { |
188 |
gnutls_x509_crt_deinit( crt); |
189 |
return 0; |
190 |
} |
191 |
|
192 |
} |
193 |
|
194 |
vtime = |
195 |
gnutls_x509_crt_get_expiration_time(crt); |
196 |
gmtime_r(&vtime, &vtm); |
197 |
|
198 |
strftime(str_serial, sizeof(str_serial) - 1, CTIME, &vtm); |
199 |
|
200 |
if (!add_cgi_env(req, "SSL_SERVER_V_END", str_serial, 0)) { |
201 |
gnutls_x509_crt_deinit( crt); |
202 |
return 0; |
203 |
} |
204 |
|
205 |
vtime = |
206 |
gnutls_x509_crt_get_activation_time(crt); |
207 |
gmtime_r(&vtime, &vtm); |
208 |
|
209 |
strftime(str_serial, sizeof(str_serial) - 1, CTIME, &vtm); |
210 |
|
211 |
if (!add_cgi_env(req, "SSL_SERVER_V_START", str_serial, 0)) { |
212 |
gnutls_x509_crt_deinit( crt); |
213 |
return 0; |
214 |
} |
215 |
|
216 |
gnutls_x509_crt_deinit( crt); |
217 |
} |
218 |
|
219 |
if (ssl_verify >= 1) { |
220 |
/* Read peer's certificate - if any |
221 |
*/ |
222 |
cert_list = |
223 |
gnutls_certificate_get_peers(req->ssl_state, &cert_list_size); |
224 |
|
225 |
if (cert_list != NULL) { |
226 |
char serial[64]; |
227 |
char str_serial[129]; |
228 |
time_t vtime; |
229 |
struct tm vtm; |
230 |
|
231 |
ret = gnutls_x509_crt_init( &crt); |
232 |
if (ret < 0) { |
233 |
return 0; |
234 |
} |
235 |
|
236 |
ret = gnutls_x509_crt_import( crt, &cert_list[0], GNUTLS_X509_FMT_DER); |
237 |
if (ret < 0) { |
238 |
gnutls_x509_crt_deinit( crt); |
239 |
return 0; |
240 |
} |
241 |
|
242 |
size = sizeof(buf); |
243 |
if (gnutls_x509_crt_get_dn( crt, buf, &size) < 0) |
244 |
strcpy( buf, "Unknown"); |
245 |
|
246 |
if (!add_cgi_env(req, "SSL_CLIENT_S_DN", buf, 0)) { |
247 |
gnutls_x509_crt_deinit( crt); |
248 |
return 0; |
249 |
} |
250 |
|
251 |
size = sizeof(buf); |
252 |
if (gnutls_x509_crt_get_issuer_dn( crt, buf, &size) < 0) |
253 |
strcpy( buf, "Unknown"); |
254 |
|
255 |
if (!add_cgi_env(req, "SSL_CLIENT_I_DN", buf, 0)) { |
256 |
gnutls_x509_crt_deinit( crt); |
257 |
return 0; |
258 |
} |
259 |
|
260 |
/* Extract serial and expiration time. |
261 |
*/ |
262 |
size = sizeof( serial); |
263 |
if (gnutls_x509_crt_get_serial( crt, serial, &size) >= 0) { |
264 |
char *p = str_serial; |
265 |
|
266 |
for (i = 0; i < size; i++) { |
267 |
*p++ = HEX((serial[i] >> 4) & 0x0f); |
268 |
*p++ = HEX((serial[i]) & 0x0f); |
269 |
} |
270 |
*p = 0; |
271 |
|
272 |
if (!add_cgi_env(req, "SSL_CLIENT_M_SERIAL", str_serial, 0)) { |
273 |
gnutls_x509_crt_deinit( crt); |
274 |
return 0; |
275 |
} |
276 |
|
277 |
} |
278 |
|
279 |
vtime = |
280 |
gnutls_x509_crt_get_expiration_time(crt); |
281 |
gmtime_r(&vtime, &vtm); |
282 |
|
283 |
strftime(str_serial, sizeof(str_serial) - 1, CTIME, &vtm); |
284 |
|
285 |
if (!add_cgi_env(req, "SSL_CLIENT_V_END", str_serial, 0)) { |
286 |
gnutls_x509_crt_deinit( crt); |
287 |
return 0; |
288 |
} |
289 |
|
290 |
vtime = gnutls_x509_crt_get_activation_time(crt); |
291 |
gmtime_r(&vtime, &vtm); |
292 |
|
293 |
strftime(str_serial, sizeof(str_serial) - 1, CTIME, &vtm); |
294 |
|
295 |
if (!add_cgi_env(req, "SSL_CLIENT_V_START", str_serial, 0)) { |
296 |
gnutls_x509_crt_deinit( crt); |
297 |
return 0; |
298 |
} |
299 |
|
300 |
gnutls_x509_crt_deinit( crt); |
301 |
|
302 |
} |
303 |
} |
304 |
|
305 |
} |
306 |
|
307 |
return 1; |
308 |
#else |
309 |
return 1; |
310 |
#endif |
311 |
} |