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 |
|
23 |
#ifdef ENABLE_SSL |
24 |
extern int ssl_verify; |
25 |
#endif |
26 |
|
27 |
/* |
28 |
* Name: add_cgi_env_ssl |
29 |
* |
30 |
* Description: Adds the required environment variables for SSL |
31 |
* secured sessions. |
32 |
* |
33 |
* Return values: |
34 |
* 0 on failure, 1 otherwise. |
35 |
*/ |
36 |
int complete_env_ssl(request * req) |
37 |
{ |
38 |
#ifdef ENABLE_SSL |
39 |
|
40 |
#define CTIME "%b %d %k:%M:%S %Y %Z" |
41 |
|
42 |
#ifndef GNUTLS_MAX_SESSION_ID |
43 |
# define GNUTLS_MAX_SESSION_ID 32 |
44 |
#endif |
45 |
char session_id[GNUTLS_MAX_SESSION_ID]; |
46 |
int session_id_length = sizeof(session_id); |
47 |
int i; |
48 |
char str_session_id[(GNUTLS_MAX_SESSION_ID * 2) + 1]; |
49 |
|
50 |
if (!add_cgi_env(req, "SSL_PROTOCOL", |
51 |
gnutls_protocol_get_name(gnutls_protocol_get_version |
52 |
(req->ssl_state)), 0)) |
53 |
return 0; |
54 |
|
55 |
if (!add_cgi_env(req, "HTTPS", "on", 0)) |
56 |
return 0; |
57 |
|
58 |
if (!add_cgi_env(req, "SSL_CLIENT_VERIFY", req->certificate_verified, 0)) |
59 |
return 0; |
60 |
|
61 |
{ |
62 |
char version[20] = "GnuTLS/"; |
63 |
strcat(version, gnutls_check_version(NULL)); |
64 |
if (!add_cgi_env(req, "SSL_VERSION_LIBRARY", version, 0)) |
65 |
return 0; |
66 |
} |
67 |
|
68 |
if (!add_cgi_env(req, "SSL_VERSION_INTERFACE", SERVER_NAME"/"SERVER_VERSION, 0)) |
69 |
return 0; |
70 |
|
71 |
if (!add_cgi_env(req, "SSL_CIPHER", |
72 |
gnutls_cipher_suite_get_name(gnutls_kx_get |
73 |
(req->ssl_state), |
74 |
gnutls_cipher_get(req-> |
75 |
ssl_state), |
76 |
gnutls_mac_get(req-> |
77 |
ssl_state)), |
78 |
0)) |
79 |
return 0; |
80 |
|
81 |
|
82 |
{ |
83 |
char buf[22]; |
84 |
char *p; |
85 |
int keysize = |
86 |
gnutls_cipher_get_key_size(gnutls_cipher_get(req->ssl_state)) * |
87 |
8; |
88 |
simple_itoa(keysize, buf); |
89 |
|
90 |
if (!add_cgi_env(req, "SSL_CIPHER_ALGKEYSIZE", buf, 0)) |
91 |
return 0; |
92 |
|
93 |
if (!add_cgi_env(req, "SSL_CIPHER_USEKEYSIZE", buf, 0)) |
94 |
return 0; |
95 |
|
96 |
if (keysize <= 40) |
97 |
p = "true"; |
98 |
else |
99 |
p = "false"; |
100 |
|
101 |
if (!add_cgi_env(req, "SSL_CIPHER_EXPORT", p, 0)) |
102 |
return 0; |
103 |
} |
104 |
|
105 |
/* generate a printable (HEX) session ID */ |
106 |
if (gnutls_session_get_id |
107 |
(req->ssl_state, session_id, &session_id_length) >= 0) { |
108 |
char *p = str_session_id; |
109 |
|
110 |
for (i = 0; i < session_id_length; i++) { |
111 |
*p++ = HEX((session_id[i] >> 4) & 0x0f); |
112 |
*p++ = HEX((session_id[i]) & 0x0f); |
113 |
} |
114 |
*p = 0; |
115 |
|
116 |
if (!add_cgi_env(req, "SSL_SESSION_ID", str_session_id, 0)) |
117 |
return 0; |
118 |
} |
119 |
|
120 |
{ |
121 |
const gnutls_datum *cert_list; |
122 |
char buf[512]; |
123 |
int cert_list_size; |
124 |
|
125 |
buf[0] = 0; |
126 |
|
127 |
cert_list = gnutls_certificate_get_ours(req->ssl_state); |
128 |
|
129 |
/* Generate the server's DN */ |
130 |
if (cert_list != NULL) { |
131 |
char serial[64]; |
132 |
char str_serial[129]; |
133 |
int serial_size = sizeof(serial); |
134 |
time_t vtime; |
135 |
struct tm vtm; |
136 |
|
137 |
if (gnutls_x509_extract_certificate_dn_string( buf, sizeof(buf), |
138 |
&cert_list[0], 0) < 0) strcpy(buf, "Unknown"); |
139 |
|
140 |
if (!add_cgi_env(req, "SSL_SERVER_S_DN", buf, 0)) |
141 |
return 0; |
142 |
|
143 |
if (gnutls_x509_extract_certificate_dn_string( buf, sizeof(buf), |
144 |
&cert_list[0], 1) < 0) strcpy( buf, "Unknown"); |
145 |
if (!add_cgi_env(req, "SSL_SERVER_I_DN", buf, 0)) |
146 |
return 0; |
147 |
|
148 |
if (gnutls_x509_extract_certificate_serial |
149 |
(&cert_list[0], serial, &serial_size) >= 0) { |
150 |
char *p = str_serial; |
151 |
|
152 |
for (i = 0; i < serial_size; i++) { |
153 |
*p++ = HEX((serial[i] >> 4) & 0x0f); |
154 |
*p++ = HEX((serial[i]) & 0x0f); |
155 |
} |
156 |
*p = 0; |
157 |
|
158 |
if (!add_cgi_env(req, "SSL_SERVER_M_SERIAL", str_serial, 0)) |
159 |
return 0; |
160 |
|
161 |
} |
162 |
|
163 |
vtime = |
164 |
gnutls_x509_extract_certificate_expiration_time(&cert_list |
165 |
[0]); |
166 |
gmtime_r(&vtime, &vtm); |
167 |
|
168 |
strftime(str_serial, sizeof(str_serial) - 1, CTIME, |
169 |
&vtm); |
170 |
|
171 |
if (!add_cgi_env(req, "SSL_SERVER_V_END", str_serial, 0)) |
172 |
return 0; |
173 |
|
174 |
vtime = |
175 |
gnutls_x509_extract_certificate_activation_time(&cert_list |
176 |
[0]); |
177 |
gmtime_r(&vtime, &vtm); |
178 |
|
179 |
strftime(str_serial, sizeof(str_serial) - 1, CTIME, |
180 |
&vtm); |
181 |
|
182 |
if (!add_cgi_env(req, "SSL_SERVER_V_START", str_serial, 0)) |
183 |
return 0; |
184 |
} |
185 |
|
186 |
if (ssl_verify >= 1) { |
187 |
/* Read peer's certificate - if any */ |
188 |
cert_list = |
189 |
gnutls_certificate_get_peers(req->ssl_state, &cert_list_size); |
190 |
|
191 |
if (cert_list != NULL) { |
192 |
if (gnutls_x509_extract_certificate_dn_string( buf, sizeof(buf), |
193 |
&cert_list[0], 0) < 0) strcpy( buf, "Unknown"); |
194 |
if (!add_cgi_env(req, "SSL_CLIENT_S_DN", buf, 0)) |
195 |
return 0; |
196 |
} |
197 |
|
198 |
/* If there is any issuer, then export it */ |
199 |
if (cert_list_size > 1) { |
200 |
if (gnutls_x509_extract_certificate_dn_string( buf, sizeof(buf), |
201 |
&cert_list[0], 1) < 0) strcpy(buf, "Unknown"); |
202 |
if (!add_cgi_env(req, "SSL_CLIENT_I_DN", buf, 0)) |
203 |
return 0; |
204 |
} |
205 |
|
206 |
if (cert_list != NULL) { |
207 |
char serial[64]; |
208 |
char str_serial[129]; |
209 |
int serial_size = sizeof(serial); |
210 |
time_t vtime; |
211 |
struct tm vtm; |
212 |
|
213 |
if (gnutls_x509_extract_certificate_serial |
214 |
(&cert_list[0], serial, &serial_size) >= 0) { |
215 |
char *p = str_serial; |
216 |
|
217 |
for (i = 0; i < serial_size; i++) { |
218 |
*p++ = HEX((serial[i] >> 4) & 0x0f); |
219 |
*p++ = HEX((serial[i]) & 0x0f); |
220 |
} |
221 |
*p = 0; |
222 |
|
223 |
if (!add_cgi_env(req, "SSL_CLIENT_M_SERIAL", str_serial, 0)) |
224 |
return 0; |
225 |
|
226 |
} |
227 |
|
228 |
vtime = |
229 |
gnutls_x509_extract_certificate_expiration_time(&cert_list |
230 |
[0]); |
231 |
gmtime_r(&vtime, &vtm); |
232 |
|
233 |
strftime(str_serial, sizeof(str_serial) - 1, |
234 |
CTIME, &vtm); |
235 |
|
236 |
if (!add_cgi_env(req, "SSL_CLIENT_V_END", str_serial, 0)) |
237 |
return 0; |
238 |
|
239 |
vtime = |
240 |
gnutls_x509_extract_certificate_activation_time(&cert_list |
241 |
[0]); |
242 |
gmtime_r(&vtime, &vtm); |
243 |
|
244 |
strftime(str_serial, sizeof(str_serial) - 1, |
245 |
CTIME, &vtm); |
246 |
|
247 |
if (!add_cgi_env(req, "SSL_CLIENT_V_START", str_serial, 0)) |
248 |
return 0; |
249 |
|
250 |
} |
251 |
} |
252 |
|
253 |
} |
254 |
|
255 |
return 1; |
256 |
#else |
257 |
return 1; |
258 |
#endif |
259 |
} |