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; |
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 |
if (!add_cgi_env(req, "SSL_VERSION_INTERFACE", SERVER_NAME"/"SERVER_VERSION, 0)) |
71 |
return 0; |
72 |
|
73 |
if (!add_cgi_env(req, "SSL_CIPHER", |
74 |
gnutls_cipher_suite_get_name(gnutls_kx_get |
75 |
(req->ssl_state), |
76 |
gnutls_cipher_get(req-> |
77 |
ssl_state), |
78 |
gnutls_mac_get(req-> |
79 |
ssl_state)), |
80 |
0)) |
81 |
return 0; |
82 |
|
83 |
|
84 |
{ |
85 |
char buf[22]; |
86 |
char *p; |
87 |
int keysize = |
88 |
gnutls_cipher_get_key_size(gnutls_cipher_get(req->ssl_state)) * |
89 |
8; |
90 |
simple_itoa(keysize, buf); |
91 |
|
92 |
if (!add_cgi_env(req, "SSL_CIPHER_ALGKEYSIZE", buf, 0)) |
93 |
return 0; |
94 |
|
95 |
if (!add_cgi_env(req, "SSL_CIPHER_USEKEYSIZE", buf, 0)) |
96 |
return 0; |
97 |
|
98 |
if (keysize <= 40) |
99 |
p = "true"; |
100 |
else |
101 |
p = "false"; |
102 |
|
103 |
if (!add_cgi_env(req, "SSL_CIPHER_EXPORT", p, 0)) |
104 |
return 0; |
105 |
} |
106 |
|
107 |
/* generate a printable (HEX) session ID */ |
108 |
if (gnutls_session_get_id |
109 |
(req->ssl_state, session_id, &session_id_length) >= 0) { |
110 |
char *p = str_session_id; |
111 |
|
112 |
for (i = 0; i < session_id_length; i++) { |
113 |
*p++ = HEX((session_id[i] >> 4) & 0x0f); |
114 |
*p++ = HEX((session_id[i]) & 0x0f); |
115 |
} |
116 |
*p = 0; |
117 |
|
118 |
if (!add_cgi_env(req, "SSL_SESSION_ID", str_session_id, 0)) |
119 |
return 0; |
120 |
} |
121 |
|
122 |
{ |
123 |
const gnutls_datum *cert_list; |
124 |
char buf[512]; |
125 |
int cert_list_size, ret; |
126 |
gnutls_x509_crt crt; |
127 |
|
128 |
buf[0] = 0; |
129 |
|
130 |
cert_list = gnutls_certificate_get_ours(req->ssl_state); |
131 |
|
132 |
/* Generate the server's DN |
133 |
*/ |
134 |
if (cert_list) { |
135 |
char serial[64]; |
136 |
char str_serial[129]; |
137 |
time_t vtime; |
138 |
struct tm vtm; |
139 |
|
140 |
ret = gnutls_x509_crt_init( &crt); |
141 |
if (ret < 0) { |
142 |
return 0; |
143 |
} |
144 |
|
145 |
ret = gnutls_x509_crt_import( crt, &cert_list[0], GNUTLS_X509_FMT_DER); |
146 |
if (ret < 0) { |
147 |
gnutls_x509_crt_deinit( crt); |
148 |
return 0; |
149 |
} |
150 |
|
151 |
size = sizeof(buf); |
152 |
if (gnutls_x509_crt_get_dn( crt, buf, &size) < 0) strcpy(buf, "Unknown"); |
153 |
|
154 |
if (!add_cgi_env(req, "SSL_SERVER_S_DN", buf, 0)) { |
155 |
gnutls_x509_crt_deinit( crt); |
156 |
return 0; |
157 |
} |
158 |
|
159 |
size = sizeof(buf); |
160 |
if (gnutls_x509_crt_get_issuer_dn( crt, buf, &size) < 0) |
161 |
strcpy( buf, "Unknown"); |
162 |
|
163 |
if (!add_cgi_env(req, "SSL_SERVER_I_DN", buf, 0)) { |
164 |
gnutls_x509_crt_deinit( crt); |
165 |
return 0; |
166 |
} |
167 |
|
168 |
size = sizeof(serial); |
169 |
if (gnutls_x509_crt_get_serial( crt, serial, &size) >= 0) |
170 |
{ |
171 |
char *p = str_serial; |
172 |
|
173 |
for (i = 0; i < size; i++) { |
174 |
*p++ = HEX((serial[i] >> 4) & 0x0f); |
175 |
*p++ = HEX((serial[i]) & 0x0f); |
176 |
} |
177 |
*p = 0; |
178 |
|
179 |
if (!add_cgi_env(req, "SSL_SERVER_M_SERIAL", str_serial, 0)) { |
180 |
gnutls_x509_crt_deinit( crt); |
181 |
return 0; |
182 |
} |
183 |
|
184 |
} |
185 |
|
186 |
vtime = |
187 |
gnutls_x509_crt_get_expiration_time(crt); |
188 |
gmtime_r(&vtime, &vtm); |
189 |
|
190 |
strftime(str_serial, sizeof(str_serial) - 1, CTIME, &vtm); |
191 |
|
192 |
if (!add_cgi_env(req, "SSL_SERVER_V_END", str_serial, 0)) { |
193 |
gnutls_x509_crt_deinit( crt); |
194 |
return 0; |
195 |
} |
196 |
|
197 |
vtime = |
198 |
gnutls_x509_crt_get_activation_time(crt); |
199 |
gmtime_r(&vtime, &vtm); |
200 |
|
201 |
strftime(str_serial, sizeof(str_serial) - 1, CTIME, &vtm); |
202 |
|
203 |
if (!add_cgi_env(req, "SSL_SERVER_V_START", str_serial, 0)) { |
204 |
gnutls_x509_crt_deinit( crt); |
205 |
return 0; |
206 |
} |
207 |
|
208 |
gnutls_x509_crt_deinit( crt); |
209 |
} |
210 |
|
211 |
if (ssl_verify >= 1) { |
212 |
/* Read peer's certificate - if any |
213 |
*/ |
214 |
cert_list = |
215 |
gnutls_certificate_get_peers(req->ssl_state, &cert_list_size); |
216 |
|
217 |
if (cert_list != NULL) { |
218 |
char serial[64]; |
219 |
char str_serial[129]; |
220 |
time_t vtime; |
221 |
struct tm vtm; |
222 |
|
223 |
ret = gnutls_x509_crt_init( &crt); |
224 |
if (ret < 0) { |
225 |
return 0; |
226 |
} |
227 |
|
228 |
ret = gnutls_x509_crt_import( crt, &cert_list[0], GNUTLS_X509_FMT_DER); |
229 |
if (ret < 0) { |
230 |
gnutls_x509_crt_deinit( crt); |
231 |
return 0; |
232 |
} |
233 |
|
234 |
size = sizeof(buf); |
235 |
if (gnutls_x509_crt_get_dn( crt, buf, &size) < 0) |
236 |
strcpy( buf, "Unknown"); |
237 |
|
238 |
if (!add_cgi_env(req, "SSL_CLIENT_S_DN", buf, 0)) { |
239 |
gnutls_x509_crt_deinit( crt); |
240 |
return 0; |
241 |
} |
242 |
|
243 |
size = sizeof(buf); |
244 |
if (gnutls_x509_crt_get_issuer_dn( crt, buf, &size) < 0) |
245 |
strcpy( buf, "Unknown"); |
246 |
|
247 |
if (!add_cgi_env(req, "SSL_CLIENT_I_DN", buf, 0)) { |
248 |
gnutls_x509_crt_deinit( crt); |
249 |
return 0; |
250 |
} |
251 |
|
252 |
/* Extract serial and expiration time. |
253 |
*/ |
254 |
size = sizeof( serial); |
255 |
if (gnutls_x509_crt_get_serial( crt, serial, &size) >= 0) { |
256 |
char *p = str_serial; |
257 |
|
258 |
for (i = 0; i < size; i++) { |
259 |
*p++ = HEX((serial[i] >> 4) & 0x0f); |
260 |
*p++ = HEX((serial[i]) & 0x0f); |
261 |
} |
262 |
*p = 0; |
263 |
|
264 |
if (!add_cgi_env(req, "SSL_CLIENT_M_SERIAL", str_serial, 0)) { |
265 |
gnutls_x509_crt_deinit( crt); |
266 |
return 0; |
267 |
} |
268 |
|
269 |
} |
270 |
|
271 |
vtime = |
272 |
gnutls_x509_crt_get_expiration_time(crt); |
273 |
gmtime_r(&vtime, &vtm); |
274 |
|
275 |
strftime(str_serial, sizeof(str_serial) - 1, CTIME, &vtm); |
276 |
|
277 |
if (!add_cgi_env(req, "SSL_CLIENT_V_END", str_serial, 0)) { |
278 |
gnutls_x509_crt_deinit( crt); |
279 |
return 0; |
280 |
} |
281 |
|
282 |
vtime = gnutls_x509_crt_get_activation_time(crt); |
283 |
gmtime_r(&vtime, &vtm); |
284 |
|
285 |
strftime(str_serial, sizeof(str_serial) - 1, CTIME, &vtm); |
286 |
|
287 |
if (!add_cgi_env(req, "SSL_CLIENT_V_START", str_serial, 0)) { |
288 |
gnutls_x509_crt_deinit( crt); |
289 |
return 0; |
290 |
} |
291 |
|
292 |
gnutls_x509_crt_deinit( crt); |
293 |
|
294 |
} |
295 |
} |
296 |
|
297 |
} |
298 |
|
299 |
return 1; |
300 |
#else |
301 |
return 1; |
302 |
#endif |
303 |
} |