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