9static char strnum[FMT_ULONG];
10static stralloc ctemp = {0};
11static stralloc *envsa = 0;
12static stralloc btemp = {0};
13static stralloc etemp = {0};
15#define set_env_id(n,e,v) \
16if (!set_env_name_entry((n),(e),(v))) return 0
18static int env_val(
const char *
env,
const void *val,
int len)
22 if (!stralloc_cats(envsa,
env))
return 0;
23 if (!stralloc_catb(envsa,
"=",1))
return 0;
24 if (!stralloc_catb(envsa,v,len))
return 0;
25 if (!stralloc_0(envsa))
return 0;
28 if (!stralloc_copyb(&etemp,v,len))
return 0;
29 if (!stralloc_0(&etemp))
return 0;
30 return pathexec_env(
env,etemp.s);
33static int env_str(
const char *
env,
const char *val)
36 return env_val(
env,val,str_len(val));
37 if (!stralloc_cats(envsa,
env))
return 0;
38 if (!stralloc_catb(envsa,
"=",1))
return 0;
39 if (!stralloc_catb(envsa,val,str_len(val) + 1))
return 0;
42 return pathexec_env(
env,val);
45static int set_env_name_entry(X509_NAME *xname,
const char *
env,
int nid)
52 for (m = 0; m < X509_NAME_entry_count(xname); m++) {
53 xne = X509_NAME_get_entry(xname,m);
54 n = OBJ_obj2nid(X509_NAME_ENTRY_get_object(xne));
56 if (!env_val(
env,X509_NAME_ENTRY_get_data(xne)->data,X509_NAME_ENTRY_get_data(xne)->length))
return 0;
64 unsigned const char *x;
68 const SSL_CIPHER *cipher;
72 if (!env_str(
"SSL_PROTOCOL",SSL_get_version(ssl)))
75 session = SSL_get1_session(ssl);
76 x = SSL_SESSION_get_id(session,&n);
78 if (!stralloc_ready(&btemp,2 * n))
return 0;
83 if (c >
'0' + 9) c +=
'a' -
'0' - 10;
84 btemp.s[2 * n + 1] = c;
87 if (c >
'0' + 9) c +=
'a' -
'0' - 10;
90 if (!env_val(
"SSL_SESSION_ID",btemp.s,btemp.len))
return 0;
92 if (!env_str(
"SSL_CIPHER",SSL_get_cipher_name(ssl)))
return 0;
94 cipher = SSL_get_current_cipher(ssl);
95 if (!cipher)
return 0;
96 n = SSL_CIPHER_get_bits(cipher,&m);
97 if (!env_str(
"SSL_CIPHER_EXPORT",n < 56 ?
"true" :
"false"))
return 0;
98 if (!env_val(
"SSL_CIPHER_USEKEYSIZE",strnum,fmt_ulong(strnum,n)))
return 0;
99 if (!env_val(
"SSL_CIPHER_ALGKEYSIZE",strnum,fmt_ulong(strnum,m)))
return 0;
101 if (!env_str(
"SSL_VERSION_INTERFACE",
"ucspi-ssl"))
return 0;
102 if (!env_str(
"SSL_VERSION_LIBRARY",OPENSSL_VERSION_TEXT))
return 0;
107static int ssl_client_bio_vars(X509 *
cert,STACK_OF(X509) *chain,BIO *bio)
109 ASN1_STRING *astring;
113 astring = X509_get_notBefore(
cert);
114 if (!ASN1_UTCTIME_print(bio,astring))
return 0;
115 n = BIO_pending(bio);
116 if (!stralloc_ready(&btemp,n))
return 0;
118 n = BIO_read(bio,btemp.s,n);
119 if (n != btemp.len)
return 0;
120 if (!env_val(
"SSL_CLIENT_V_START",btemp.s,btemp.len))
return 0;
122 astring = X509_get_notAfter(
cert);
123 if (!ASN1_UTCTIME_print(bio,astring))
return 0;
124 n = BIO_pending(bio);
125 if (!stralloc_ready(&btemp,n))
return 0;
127 n = BIO_read(bio,btemp.s,n);
128 if (n != btemp.len)
return 0;
129 if (!env_val(
"SSL_CLIENT_V_END",btemp.s,btemp.len))
return 0;
131 if (!PEM_write_bio_X509(bio,
cert))
return 0;
132 n = BIO_pending(bio);
133 if (!stralloc_ready(&btemp,n))
return 0;
135 n = BIO_read(bio,btemp.s,n);
136 if (n != btemp.len)
return 0;
137 if (!env_val(
"SSL_CLIENT_CERT",btemp.s,btemp.len))
return 0;
140 for (m = 0; m < sk_X509_num(chain); m++) {
141 if (!stralloc_copys(&ctemp,
"SSL_CLIENT_CERT_CHAIN_"))
return 0;
142 if (!stralloc_catb(&ctemp,strnum,fmt_ulong(strnum,m)))
return 0;
143 if (!stralloc_0(&ctemp))
return 0;
145 if (m < sk_X509_num(chain)) {
146 if (!PEM_write_bio_X509(bio,sk_X509_value(chain,m)))
return 0;
147 n = BIO_pending(bio);
148 if (!stralloc_ready(&btemp,n))
return 0;
150 n = BIO_read(bio,btemp.s,n);
151 if (n != btemp.len)
return 0;
152 if (!env_val(ctemp.s,btemp.s,btemp.len))
return 0;
160static int ssl_client_vars(X509 *
cert,STACK_OF(X509) *chain)
164 const X509_ALGOR *sigalg;
165 const ASN1_OBJECT *calgoid;
175 if (!env_val(
"SSL_CLIENT_M_VERSION",strnum,fmt_ulong(strnum,X509_get_version(
cert) + 1)))
178 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(
cert), 0);
181 if (!env_val(
"SSL_CLIENT_M_SERIAL",x,strlen(x)))
186 xname = X509_get_subject_name(
cert);
187 x = X509_NAME_oneline(xname,0,0);
188 n = env_str(
"SSL_CLIENT_S_DN",x);
192 set_env_id(xname,
"SSL_CLIENT_S_DN_C",NID_countryName);
193 set_env_id(xname,
"SSL_CLIENT_S_DN_ST",NID_stateOrProvinceName);
194 set_env_id(xname,
"SSL_CLIENT_S_DN_L",NID_localityName);
195 set_env_id(xname,
"SSL_CLIENT_S_DN_O",NID_organizationName);
196 set_env_id(xname,
"SSL_CLIENT_S_DN_OU",NID_organizationalUnitName);
197 set_env_id(xname,
"SSL_CLIENT_S_DN_CN",NID_commonName);
198 set_env_id(xname,
"SSL_CLIENT_S_DN_T",NID_title);
199 set_env_id(xname,
"SSL_CLIENT_S_DN_I",NID_initials);
200 set_env_id(xname,
"SSL_CLIENT_S_DN_G",NID_givenName);
201 set_env_id(xname,
"SSL_CLIENT_S_DN_S",NID_surname);
202 set_env_id(xname,
"SSL_CLIENT_S_DN_D",NID_description);
203 set_env_id(xname,
"SSL_CLIENT_S_DN_UID",NID_x500UniqueIdentifier);
204 set_env_id(xname,
"SSL_CLIENT_S_DN_Email",NID_pkcs9_emailAddress);
207 xname = X509_get_issuer_name(
cert);
208 x = X509_NAME_oneline(xname,0,0);
209 n = env_str(
"SSL_CLIENT_I_DN",x);
213 set_env_id(xname,
"SSL_CLIENT_I_DN_C",NID_countryName);
214 set_env_id(xname,
"SSL_CLIENT_I_DN_ST",NID_stateOrProvinceName);
215 set_env_id(xname,
"SSL_CLIENT_I_DN_L",NID_localityName);
216 set_env_id(xname,
"SSL_CLIENT_I_DN_O",NID_organizationName);
217 set_env_id(xname,
"SSL_CLIENT_I_DN_OU",NID_organizationalUnitName);
218 set_env_id(xname,
"SSL_CLIENT_I_DN_CN",NID_commonName);
219 set_env_id(xname,
"SSL_CLIENT_I_DN_T",NID_title);
220 set_env_id(xname,
"SSL_CLIENT_I_DN_I",NID_initials);
221 set_env_id(xname,
"SSL_CLIENT_I_DN_G",NID_givenName);
222 set_env_id(xname,
"SSL_CLIENT_I_DN_S",NID_surname);
223 set_env_id(xname,
"SSL_CLIENT_I_DN_D",NID_description);
224 set_env_id(xname,
"SSL_CLIENT_I_DN_UID",NID_x500UniqueIdentifier);
225 set_env_id(xname,
"SSL_CLIENT_I_DN_Email",NID_pkcs9_emailAddress);
228 sigalg = X509_get0_tbs_sigalg(
cert);
229 X509_ALGOR_get0(&calgoid,0,0,sigalg);
230 n = OBJ_obj2nid(calgoid);
231 if (!env_str(
"SSL_CLIENT_A_SIG",(n == NID_undef) ?
"UNKNOWN" : OBJ_nid2ln(n)))
235 pubkey = X509_get_X509_PUBKEY(
cert);
236 X509_PUBKEY_get0_param(&algoid,0,0,0,pubkey);
237 n = OBJ_obj2nid(algoid);
238 if (!env_str(
"SSL_CLIENT_A_KEY",(n == NID_undef) ?
"UNKNOWN" : OBJ_nid2ln(n)))
243 GENERAL_NAMES *extensions = X509_get_ext_d2i(
cert,NID_subject_alt_name,0,0);
244 int num = sk_GENERAL_NAME_num(extensions);
246 for (
int i = 0, n = 0; i < num; ++i) {
247 const GENERAL_NAME *ext = sk_GENERAL_NAME_value(extensions,i);
248 if (ext->type == GEN_DNS) {
249 if (OBJ_sn2nid((
const char*)ext->d.ia5) != V_ASN1_IA5STRING)
continue;
250 yname = (
char *)ASN1_STRING_get0_data(ext->d.ia5);
252 if (!env_str(
"SSL_CLIENT_SAN_DNS_0=",yname))
return 0;
255 if (!env_str(
"SSL_CLIENT_SAN_DNS_1=",yname))
return 0;
257 if (ext->type == GEN_EMAIL) {
259 if (OBJ_sn2nid((
const char*)ext->d.ia5) != V_ASN1_IA5STRING)
continue;
260 yname = (
char *)ASN1_STRING_get0_data(ext->d.ia5);
262 if (!env_str(
"SSL_CLIENT_SAN_Email_0=",yname))
return 0;
265 if (!env_str(
"SSL_CLIENT_SAN_Email_1=",yname))
return 0;
269 bio = BIO_new(BIO_s_mem());
271 n = ssl_client_bio_vars(
cert,chain,bio);
278static int ssl_server_bio_vars(X509 *
cert,STACK_OF(X509) *chain,BIO *bio)
280 ASN1_STRING *astring;
284 astring = X509_get_notBefore(
cert);
285 if (!ASN1_UTCTIME_print(bio,astring))
return 0;
286 n = BIO_pending(bio);
287 if (!stralloc_ready(&btemp,n))
return 0;
289 n = BIO_read(bio,btemp.s,n);
290 if (n != btemp.len)
return 0;
291 if (!env_val(
"SSL_SERVER_V_START",btemp.s,btemp.len))
return 0;
293 astring = X509_get_notAfter(
cert);
294 if (!ASN1_UTCTIME_print(bio,astring))
return 0;
295 n = BIO_pending(bio);
296 if (!stralloc_ready(&btemp,n))
return 0;
298 n = BIO_read(bio,btemp.s,n);
299 if (n != btemp.len)
return 0;
300 if (!env_val(
"SSL_SERVER_V_END",btemp.s,btemp.len))
return 0;
302 if (!PEM_write_bio_X509(bio,
cert))
return 0;
303 n = BIO_pending(bio);
304 if (!stralloc_ready(&btemp,n))
return 0;
306 n = BIO_read(bio,btemp.s,n);
307 if (n != btemp.len)
return 0;
308 if (!env_val(
"SSL_SERVER_CERT",btemp.s,btemp.len))
return 0;
311 for (m = 0; m < sk_X509_num(chain); m++) {
312 if (!stralloc_copys(&ctemp,
"SSL_SERVER_CERT_CHAIN_"))
return 0;
313 if (!stralloc_catb(&ctemp,strnum,fmt_ulong(strnum,m)))
return 0;
314 if (!stralloc_0(&ctemp))
return 0;
316 if (m < sk_X509_num(chain)) {
317 if (!PEM_write_bio_X509(bio,sk_X509_value(chain,m)))
return 0;
318 n = BIO_pending(bio);
319 if (!stralloc_ready(&btemp,n))
return 0;
321 n = BIO_read(bio,btemp.s,n);
322 if (n != btemp.len)
return 0;
323 if (!env_val(ctemp.s,btemp.s,btemp.len))
return 0;
331static int ssl_server_vars(X509 *
cert,STACK_OF(X509) *chain)
335 const X509_ALGOR *sigalg;
336 const ASN1_OBJECT *calgoid;
346 if (!env_val(
"SSL_SERVER_M_VERSION",strnum,fmt_ulong(strnum,X509_get_version(
cert) + 1)))
349 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(
cert), 0);
352 if (!env_val(
"SSL_SERVER_M_SERIAL",x,strlen(x)))
return 0;
355 xname = X509_get_subject_name(
cert);
356 x = X509_NAME_oneline(xname,0,0);
357 n = env_str(
"SSL_SERVER_S_DN",x);
361 set_env_id(xname,
"SSL_SERVER_S_DN_C",NID_countryName);
362 set_env_id(xname,
"SSL_SERVER_S_DN_ST",NID_stateOrProvinceName);
363 set_env_id(xname,
"SSL_SERVER_S_DN_L",NID_localityName);
364 set_env_id(xname,
"SSL_SERVER_S_DN_O",NID_organizationName);
365 set_env_id(xname,
"SSL_SERVER_S_DN_OU",NID_organizationalUnitName);
366 set_env_id(xname,
"SSL_SERVER_S_DN_CN",NID_commonName);
367 set_env_id(xname,
"SSL_SERVER_S_DN_T",NID_title);
368 set_env_id(xname,
"SSL_SERVER_S_DN_I",NID_initials);
369 set_env_id(xname,
"SSL_SERVER_S_DN_G",NID_givenName);
370 set_env_id(xname,
"SSL_SERVER_S_DN_S",NID_surname);
371 set_env_id(xname,
"SSL_SERVER_S_DN_D",NID_description);
372 set_env_id(xname,
"SSL_SERVER_S_DN_UID",NID_x500UniqueIdentifier);
373 set_env_id(xname,
"SSL_SERVER_S_DN_Email",NID_pkcs9_emailAddress);
375 xname = X509_get_issuer_name(
cert);
376 x = X509_NAME_oneline(xname,0,0);
377 n = env_str(
"SSL_SERVER_I_DN",x);
381 set_env_id(xname,
"SSL_SERVER_I_DN_C",NID_countryName);
382 set_env_id(xname,
"SSL_SERVER_I_DN_ST",NID_stateOrProvinceName);
383 set_env_id(xname,
"SSL_SERVER_I_DN_L",NID_localityName);
384 set_env_id(xname,
"SSL_SERVER_I_DN_O",NID_organizationName);
385 set_env_id(xname,
"SSL_SERVER_I_DN_OU",NID_organizationalUnitName);
386 set_env_id(xname,
"SSL_SERVER_I_DN_CN",NID_commonName);
387 set_env_id(xname,
"SSL_SERVER_I_DN_T",NID_title);
388 set_env_id(xname,
"SSL_SERVER_I_DN_I",NID_initials);
389 set_env_id(xname,
"SSL_SERVER_I_DN_G",NID_givenName);
390 set_env_id(xname,
"SSL_SERVER_I_DN_S",NID_surname);
391 set_env_id(xname,
"SSL_SERVER_I_DN_D",NID_description);
392 set_env_id(xname,
"SSL_SERVER_I_DN_UID",NID_x500UniqueIdentifier);
393 set_env_id(xname,
"SSL_SERVER_I_DN_Email",NID_pkcs9_emailAddress);
396 sigalg = X509_get0_tbs_sigalg(
cert);
397 X509_ALGOR_get0(&calgoid,0,0,sigalg);
398 n = OBJ_obj2nid(calgoid);
399 if (!env_str(
"SSL_SERVER_A_SIG",(n == NID_undef) ?
"UNKNOWN" : OBJ_nid2ln(n)))
403 pubkey = X509_get_X509_PUBKEY(
cert);
404 X509_PUBKEY_get0_param(&algoid,0,0,0,pubkey);
405 n = OBJ_obj2nid(algoid);
406 if (!env_str(
"SSL_SERVER_A_KEY",(n == NID_undef) ?
"UNKNOWN" : OBJ_nid2ln(n)))
411 GENERAL_NAMES *extensions = X509_get_ext_d2i(
cert,NID_subject_alt_name,0,0);
412 int num = sk_GENERAL_NAME_num(extensions);
414 for (
int i = 0, n = 0; i < num; ++i) {
415 const GENERAL_NAME *ext = sk_GENERAL_NAME_value(extensions,i);
416 if (ext->type == GEN_DNS) {
417 if (OBJ_sn2nid((
const char*)ext->d.ia5) != V_ASN1_IA5STRING)
continue;
418 yname = (
char *)ASN1_STRING_get0_data(ext->d.ia5);
420 if (!env_str(
"SSL_SERVER_SAN_DNS_0=",yname))
return 0;
423 if (!env_str(
"SSL_SERVER_SAN_DNS_1=",yname))
return 0;
425 if (ext->type == GEN_EMAIL) {
427 if (OBJ_sn2nid((
const char*)ext->d.ia5) != V_ASN1_IA5STRING)
continue;
428 yname = (
char *)ASN1_STRING_get0_data(ext->d.ia5);
430 if (!env_str(
"SSL_SERVER_SAN_Email_0=",yname))
return 0;
433 if (!env_str(
"SSL_SERVER_SAN_Email_1=",yname))
return 0;
437 bio = BIO_new(BIO_s_mem());
439 n = ssl_server_bio_vars(
cert,chain,bio);
451 if (!ssl_client_vars(SSL_get_certificate(ssl),0))
return 0;
452 if (!ssl_server_vars(0,SSL_get_peer_cert_chain(ssl)))
return 0;
460 if (!ssl_server_vars(SSL_get_certificate(ssl),0))
return 0;
461 if (!ssl_server_vars(0,SSL_get_peer_cert_chain(ssl)))
return 0;
#define set_env_id(n, e, v)
int ssl_server_env(SSL *ssl, stralloc *sa)
int ssl_client_env(SSL *ssl, stralloc *sa)
int ssl_session_vars(SSL *ssl)
void env(const char *s, const char *t)
Header file to be used with sqmail; previously called ssl.h. (name clash)