ucspi-ssl 0.13.00
ucspi-ssl
Loading...
Searching...
No Matches
ssl_env.c
Go to the documentation of this file.
1#include <unistd.h>
2#include <string.h>
3#include "fmt.h"
4#include "pathexec.h"
5#include "ucspissl.h"
6#include "stralloc.h"
7#include "str.h"
8
9static char strnum[FMT_ULONG];
10static stralloc ctemp = {0};
11static stralloc *envsa = 0;
12static stralloc btemp = {0};
13static stralloc etemp = {0};
14
15#define set_env_id(n,e,v) \
16if (!set_env_name_entry((n),(e),(v))) return 0
17
18static int env_val(const char *env,const void *val,int len) {
19 const char *v = val;
20 if (envsa) {
21 if (!stralloc_cats(envsa,env)) return 0;
22 if (!stralloc_catb(envsa,"=",1)) return 0;
23 if (!stralloc_catb(envsa,v,len)) return 0;
24 if (!stralloc_0(envsa)) return 0;
25 return 1;
26 }
27 if (!stralloc_copyb(&etemp,v,len)) return 0;
28 if (!stralloc_0(&etemp)) return 0;
29 return pathexec_env(env,etemp.s);
30}
31
32static int env_str(const char *env,const char *val) {
33 if (envsa) {
34 return env_val(env,val,str_len(val));
35 if (!stralloc_cats(envsa,env)) return 0;
36 if (!stralloc_catb(envsa,"=",1)) return 0;
37 if (!stralloc_catb(envsa,val,str_len(val) + 1)) return 0;
38 return 1;
39 }
40 return pathexec_env(env,val);
41}
42
43static int set_env_name_entry(X509_NAME *xname,const char *env,int nid) {
44 X509_NAME_ENTRY *xne;
45 int m;
46 int n;
47
48 if (!env) return 1;
49 for (m = 0; m < X509_NAME_entry_count(xname); m++) {
50 xne = X509_NAME_get_entry(xname,m);
51 n = OBJ_obj2nid(X509_NAME_ENTRY_get_object(xne));
52 if (n == nid)
53 if (!env_val(env,X509_NAME_ENTRY_get_data(xne)->data,X509_NAME_ENTRY_get_data(xne)->length)) return 0;
54 }
55
56 return 1;
57}
58
59int ssl_session_vars(SSL *ssl) {
60 unsigned const char *x;
61 SSL_SESSION *session;
62 unsigned int n = 0;
63 int m;
64 const SSL_CIPHER *cipher;
65 unsigned char u;
66 unsigned char c;
67
68 if (!env_str("SSL_PROTOCOL",SSL_get_version(ssl)))
69 return 0;
70
71 session = SSL_get1_session(ssl);
72 x = SSL_SESSION_get_id(session,&n);
73
74 if (!stralloc_ready(&btemp,2 * n)) return 0;
75 btemp.len = 2 * n;
76 while (n--) {
77 u = x[n];
78 c = '0' + (u & 15);
79 if (c > '0' + 9) c += 'a' - '0' - 10;
80 btemp.s[2 * n + 1] = c;
81 u >>= 4;
82 c = '0' + (u & 15);
83 if (c > '0' + 9) c += 'a' - '0' - 10;
84 btemp.s[2 * n] = c;
85 }
86 if (!env_val("SSL_SESSION_ID",btemp.s,btemp.len)) return 0;
87
88 if (!env_str("SSL_CIPHER",SSL_get_cipher_name(ssl))) return 0;
89
90 cipher = SSL_get_current_cipher(ssl);
91 if (!cipher) return 0;
92 n = SSL_CIPHER_get_bits(cipher,&m);
93 if (!env_str("SSL_CIPHER_EXPORT",n < 56 ? "true" : "false")) return 0;
94 if (!env_val("SSL_CIPHER_USEKEYSIZE",strnum,fmt_ulong(strnum,n))) return 0;
95 if (!env_val("SSL_CIPHER_ALGKEYSIZE",strnum,fmt_ulong(strnum,m))) return 0;
96
97 if (!env_str("SSL_VERSION_INTERFACE","ucspi-ssl")) return 0;
98 if (!env_str("SSL_VERSION_LIBRARY",OPENSSL_VERSION_TEXT)) return 0;
99
100 return 1;
101}
102
103static int ssl_client_bio_vars(X509 *cert,STACK_OF(X509) *chain,BIO *bio) {
104 ASN1_STRING *astring;
105 int n;
106 int m;
107
108 astring = X509_get_notBefore(cert);
109 if (!ASN1_UTCTIME_print(bio,astring)) return 0;
110 n = BIO_pending(bio);
111 if (!stralloc_ready(&btemp,n)) return 0;
112 btemp.len = n;
113 n = BIO_read(bio,btemp.s,n);
114 if (n != btemp.len) return 0;
115 if (!env_val("SSL_CLIENT_V_START",btemp.s,btemp.len)) return 0;
116
117 astring = X509_get_notAfter(cert);
118 if (!ASN1_UTCTIME_print(bio,astring)) return 0;
119 n = BIO_pending(bio);
120 if (!stralloc_ready(&btemp,n)) return 0;
121 btemp.len = n;
122 n = BIO_read(bio,btemp.s,n);
123 if (n != btemp.len) return 0;
124 if (!env_val("SSL_CLIENT_V_END",btemp.s,btemp.len)) return 0;
125
126 if (!PEM_write_bio_X509(bio,cert)) return 0;
127 n = BIO_pending(bio);
128 if (!stralloc_ready(&btemp,n)) return 0;
129 btemp.len = n;
130 n = BIO_read(bio,btemp.s,n);
131 if (n != btemp.len) return 0;
132 if (!env_val("SSL_CLIENT_CERT",btemp.s,btemp.len)) return 0;
133
134 if (chain) {
135 for (m = 0; m < sk_X509_num(chain); m++) {
136 if (!stralloc_copys(&ctemp,"SSL_CLIENT_CERT_CHAIN_")) return 0;
137 if (!stralloc_catb(&ctemp,strnum,fmt_ulong(strnum,m))) return 0;
138 if (!stralloc_0(&ctemp)) return 0;
139
140 if (m < sk_X509_num(chain)) {
141 if (!PEM_write_bio_X509(bio,sk_X509_value(chain,m))) return 0;
142 n = BIO_pending(bio);
143 if (!stralloc_ready(&btemp,n)) return 0;
144 btemp.len = n;
145 n = BIO_read(bio,btemp.s,n);
146 if (n != btemp.len) return 0;
147 if (!env_val(ctemp.s,btemp.s,btemp.len)) return 0;
148 }
149 }
150 }
151
152 return 1;
153}
154
155static int ssl_client_vars(X509 *cert,STACK_OF(X509) *chain) {
156 X509_NAME *xname;
157 X509_PUBKEY *pubkey;
158 const X509_ALGOR *sigalg;
159 const ASN1_OBJECT *calgoid;
160 ASN1_OBJECT *algoid;
161 BIGNUM *bn;
162 BIO *bio;
163 char *x = 0;
164 int n;
165
166 if (!cert) return 1;
167
168 if (!env_val("SSL_CLIENT_M_VERSION",strnum,fmt_ulong(strnum,X509_get_version(cert) + 1)))
169 return 0;
170
171 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), 0);
172 x = BN_bn2dec(bn);
173 BN_free(bn);
174 if (!env_val("SSL_CLIENT_M_SERIAL",x,strlen(x)))
175 return 0;
176 OPENSSL_free(x);
177
178 xname = X509_get_subject_name(cert);
179 x = X509_NAME_oneline(xname,0,0);
180 n = env_str("SSL_CLIENT_S_DN",x);
181 free(x);
182 if (!n) return 0;
183
184 set_env_id(xname,"SSL_CLIENT_S_DN_C",NID_countryName);
185 set_env_id(xname,"SSL_CLIENT_S_DN_ST",NID_stateOrProvinceName);
186 set_env_id(xname,"SSL_CLIENT_S_DN_L",NID_localityName);
187 set_env_id(xname,"SSL_CLIENT_S_DN_O",NID_organizationName);
188 set_env_id(xname,"SSL_CLIENT_S_DN_OU",NID_organizationalUnitName);
189 set_env_id(xname,"SSL_CLIENT_S_DN_CN",NID_commonName);
190 set_env_id(xname,"SSL_CLIENT_S_DN_T",NID_title);
191 set_env_id(xname,"SSL_CLIENT_S_DN_I",NID_initials);
192 set_env_id(xname,"SSL_CLIENT_S_DN_G",NID_givenName);
193 set_env_id(xname,"SSL_CLIENT_S_DN_S",NID_surname);
194 set_env_id(xname,"SSL_CLIENT_S_DN_D",NID_description);
195 set_env_id(xname,"SSL_CLIENT_S_DN_UID",NID_x500UniqueIdentifier);
196 set_env_id(xname,"SSL_CLIENT_S_DN_Email",NID_pkcs9_emailAddress);
197
198 xname = X509_get_issuer_name(cert);
199 x = X509_NAME_oneline(xname,0,0);
200 n = env_str("SSL_CLIENT_I_DN",x);
201 free(x);
202 if (!n) return 0;
203
204 set_env_id(xname,"SSL_CLIENT_I_DN_C",NID_countryName);
205 set_env_id(xname,"SSL_CLIENT_I_DN_ST",NID_stateOrProvinceName);
206 set_env_id(xname,"SSL_CLIENT_I_DN_L",NID_localityName);
207 set_env_id(xname,"SSL_CLIENT_I_DN_O",NID_organizationName);
208 set_env_id(xname,"SSL_CLIENT_I_DN_OU",NID_organizationalUnitName);
209 set_env_id(xname,"SSL_CLIENT_I_DN_CN",NID_commonName);
210 set_env_id(xname,"SSL_CLIENT_I_DN_T",NID_title);
211 set_env_id(xname,"SSL_CLIENT_I_DN_I",NID_initials);
212 set_env_id(xname,"SSL_CLIENT_I_DN_G",NID_givenName);
213 set_env_id(xname,"SSL_CLIENT_I_DN_S",NID_surname);
214 set_env_id(xname,"SSL_CLIENT_I_DN_D",NID_description);
215 set_env_id(xname,"SSL_CLIENT_I_DN_UID",NID_x500UniqueIdentifier);
216 set_env_id(xname,"SSL_CLIENT_I_DN_Email",NID_pkcs9_emailAddress);
217
218/* Signature Algorithm for PubKey */
219 sigalg = X509_get0_tbs_sigalg(cert);
220 X509_ALGOR_get0(&calgoid,0,0,sigalg);
221 n = OBJ_obj2nid(calgoid);
222 if (!env_str("SSL_CLIENT_A_SIG",(n == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(n)))
223 return 0;
224
225/* Algorithm for PubKey */
226 pubkey = X509_get_X509_PUBKEY(cert);
227 X509_PUBKEY_get0_param(&algoid,0,0,0,pubkey);
228 n = OBJ_obj2nid(algoid);
229 if (!env_str("SSL_CLIENT_A_KEY",(n == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(n)))
230 return 0;
231
232 bio = BIO_new(BIO_s_mem());
233 if (!bio) return 0;
234 n = ssl_client_bio_vars(cert,chain,bio);
235 BIO_free(bio);
236 if (!n) return 0;
237
238 return 1;
239}
240
241static int ssl_server_bio_vars(X509 *cert,STACK_OF(X509) *chain,BIO *bio) {
242 ASN1_STRING *astring;
243 int n;
244 int m;
245
246 astring = X509_get_notBefore(cert);
247 if (!ASN1_UTCTIME_print(bio,astring)) return 0;
248 n = BIO_pending(bio);
249 if (!stralloc_ready(&btemp,n)) return 0;
250 btemp.len = n;
251 n = BIO_read(bio,btemp.s,n);
252 if (n != btemp.len) return 0;
253 if (!env_val("SSL_SERVER_V_START",btemp.s,btemp.len)) return 0;
254
255 astring = X509_get_notAfter(cert);
256 if (!ASN1_UTCTIME_print(bio,astring)) return 0;
257 n = BIO_pending(bio);
258 if (!stralloc_ready(&btemp,n)) return 0;
259 btemp.len = n;
260 n = BIO_read(bio,btemp.s,n);
261 if (n != btemp.len) return 0;
262 if (!env_val("SSL_SERVER_V_END",btemp.s,btemp.len)) return 0;
263
264 if (!PEM_write_bio_X509(bio,cert)) return 0;
265 n = BIO_pending(bio);
266 if (!stralloc_ready(&btemp,n)) return 0;
267 btemp.len = n;
268 n = BIO_read(bio,btemp.s,n);
269 if (n != btemp.len) return 0;
270 if (!env_val("SSL_SERVER_CERT",btemp.s,btemp.len)) return 0;
271
272 if (chain) {
273 for (m = 0; m < sk_X509_num(chain); m++) {
274 if (!stralloc_copys(&ctemp,"SSL_SERVER_CERT_CHAIN_")) return 0;
275 if (!stralloc_catb(&ctemp,strnum,fmt_ulong(strnum,m))) return 0;
276 if (!stralloc_0(&ctemp)) return 0;
277
278 if (m < sk_X509_num(chain)) {
279 if (!PEM_write_bio_X509(bio,sk_X509_value(chain,m))) return 0;
280 n = BIO_pending(bio);
281 if (!stralloc_ready(&btemp,n)) return 0;
282 btemp.len = n;
283 n = BIO_read(bio,btemp.s,n);
284 if (n != btemp.len) return 0;
285 if (!env_val(ctemp.s,btemp.s,btemp.len)) return 0;
286 }
287 }
288 }
289
290 return 1;
291}
292
293static int ssl_server_vars(X509 *cert,STACK_OF(X509) *chain) {
294 X509_NAME *xname;
295 X509_PUBKEY *pubkey;
296 const X509_ALGOR *sigalg;
297 const ASN1_OBJECT *calgoid;
298 ASN1_OBJECT *algoid;
299 BIGNUM *bn;
300 BIO *bio;
301 char *x = 0;
302 int n;
303
304 if (!cert) return 1;
305
306 if (!env_val("SSL_SERVER_M_VERSION",strnum,fmt_ulong(strnum,X509_get_version(cert) + 1)))
307 return 0;
308
309 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), 0);
310 x = BN_bn2dec(bn);
311 BN_free(bn);
312 if (!env_val("SSL_SERVER_M_SERIAL",x,strlen(x))) return 0;
313 OPENSSL_free(x);
314
315 xname = X509_get_subject_name(cert);
316 x = X509_NAME_oneline(xname,0,0);
317 n = env_str("SSL_SERVER_S_DN",x);
318 free(x);
319 if (!n) return 0;
320
321 set_env_id(xname,"SSL_SERVER_S_DN_C",NID_countryName);
322 set_env_id(xname,"SSL_SERVER_S_DN_ST",NID_stateOrProvinceName);
323 set_env_id(xname,"SSL_SERVER_S_DN_L",NID_localityName);
324 set_env_id(xname,"SSL_SERVER_S_DN_O",NID_organizationName);
325 set_env_id(xname,"SSL_SERVER_S_DN_OU",NID_organizationalUnitName);
326 set_env_id(xname,"SSL_SERVER_S_DN_CN",NID_commonName);
327 set_env_id(xname,"SSL_SERVER_S_DN_T",NID_title);
328 set_env_id(xname,"SSL_SERVER_S_DN_I",NID_initials);
329 set_env_id(xname,"SSL_SERVER_S_DN_G",NID_givenName);
330 set_env_id(xname,"SSL_SERVER_S_DN_S",NID_surname);
331 set_env_id(xname,"SSL_SERVER_S_DN_D",NID_description);
332 set_env_id(xname,"SSL_SERVER_S_DN_UID",NID_x500UniqueIdentifier);
333 set_env_id(xname,"SSL_SERVER_S_DN_Email",NID_pkcs9_emailAddress);
334
335 xname = X509_get_issuer_name(cert);
336 x = X509_NAME_oneline(xname,0,0);
337 n = env_str("SSL_SERVER_I_DN",x);
338 free(x);
339 if (!n) return 0;
340
341 set_env_id(xname,"SSL_SERVER_I_DN_C",NID_countryName);
342 set_env_id(xname,"SSL_SERVER_I_DN_ST",NID_stateOrProvinceName);
343 set_env_id(xname,"SSL_SERVER_I_DN_L",NID_localityName);
344 set_env_id(xname,"SSL_SERVER_I_DN_O",NID_organizationName);
345 set_env_id(xname,"SSL_SERVER_I_DN_OU",NID_organizationalUnitName);
346 set_env_id(xname,"SSL_SERVER_I_DN_CN",NID_commonName);
347 set_env_id(xname,"SSL_SERVER_I_DN_T",NID_title);
348 set_env_id(xname,"SSL_SERVER_I_DN_I",NID_initials);
349 set_env_id(xname,"SSL_SERVER_I_DN_G",NID_givenName);
350 set_env_id(xname,"SSL_SERVER_I_DN_S",NID_surname);
351 set_env_id(xname,"SSL_SERVER_I_DN_D",NID_description);
352 set_env_id(xname,"SSL_SERVER_I_DN_UID",NID_x500UniqueIdentifier);
353 set_env_id(xname,"SSL_SERVER_I_DN_Email",NID_pkcs9_emailAddress);
354
355/* Signature Algorithm of PubKey */
356 sigalg = X509_get0_tbs_sigalg(cert);
357 X509_ALGOR_get0(&calgoid,0,0,sigalg);
358 n = OBJ_obj2nid(calgoid);
359 if (!env_str("SSL_SERVER_A_SIG",(n == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(n)))
360 return 0;
361
362/* Algorithm of PubKey */
363 pubkey = X509_get_X509_PUBKEY(cert);
364 X509_PUBKEY_get0_param(&algoid,0,0,0,pubkey);
365 n = OBJ_obj2nid(algoid);
366 if (!env_str("SSL_SERVER_A_KEY",(n == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(n)))
367 return 0;
368
369 bio = BIO_new(BIO_s_mem());
370 if (!bio) return 0;
371 n = ssl_server_bio_vars(cert,chain,bio);
372 BIO_free(bio);
373
374 if (!n) return 0;
375
376 return 1;
377}
378
379int ssl_client_env(SSL *ssl,stralloc *sa) {
380 envsa = sa;
381 if (!ssl_session_vars(ssl)) return 0;
382 if (!ssl_client_vars(SSL_get_certificate(ssl),0))
383 return 0;
384 if (!ssl_server_vars(0,SSL_get_peer_cert_chain(ssl)))
385 return 0;
386 return 1;
387}
388
389int ssl_server_env(SSL *ssl,stralloc *sa) {
390 envsa = sa;
391 if (!ssl_session_vars(ssl)) return 0;
392 if (!ssl_server_vars(SSL_get_certificate(ssl),0))
393 return 0;
394 if (!ssl_server_vars(0,SSL_get_peer_cert_chain(ssl)))
395 return 0;
396 return 1;
397}
Header file to be used with sqmail; previously called ssl.h. (name clash)
#define set_env_id(n, e, v)
Definition: ssl_env.c:15
int ssl_server_env(SSL *ssl, stralloc *sa)
Definition: ssl_env.c:389
int ssl_client_env(SSL *ssl, stralloc *sa)
Definition: ssl_env.c:379
int ssl_session_vars(SSL *ssl)
Definition: ssl_env.c:59
X509 * cert
Definition: sslhandle.c:125
void env(const char *s, const char *t)
Definition: sslclient.c:42