Branch data Line data Source code
1 : : // $Id: X509.cc 6724 2009-06-07 09:23:03Z vern $
2 : :
3 : : #include <openssl/err.h>
4 : :
5 : : #include "X509.h"
6 : : #include "config.h"
7 : :
8 : : // ### NOTE: while d2i_X509 does not take a const u_char** pointer,
9 : : // here we assume d2i_X509 does not write to <data>, so it is safe to
10 : : // convert data to a non-const pointer. Could some X509 guru verify
11 : : // this?
12 : :
13 : 0 : X509* d2i_X509_(X509** px, const u_char** in, int len)
14 : : {
15 : : #ifdef OPENSSL_D2I_X509_USES_CONST_CHAR
16 : 0 : return d2i_X509(px, in, len);
17 : : #else
18 : : return d2i_X509(px, (u_char**)in, len);
19 : : #endif
20 : : }
21 : :
22 : : X509_STORE* X509_Cert::ctx = 0;
23 : : X509_LOOKUP* X509_Cert::lookup = 0;
24 : : X509_STORE_CTX X509_Cert::csc;
25 : : bool X509_Cert::bInited = false;
26 : :
27 : : // TODO: Check if Key < 768 Bits => Weakness!
28 : : // FIXME: Merge verify and verifyChain.
29 : :
30 : 0 : void X509_Cert::sslCertificateEvent(Contents_SSL* e, X509* pCert)
31 : : {
32 : 0 : EventHandlerPtr event = ssl_certificate;
33 [ # # ]: 0 : if ( ! event )
34 : 0 : return;
35 : :
36 : : char tmp[256];
37 : 0 : RecordVal* pX509Cert = new RecordVal(x509_type);
38 : :
39 : 0 : X509_NAME_oneline(X509_get_issuer_name(pCert), tmp, sizeof tmp);
40 : 0 : pX509Cert->Assign(0, new StringVal(tmp));
41 : 0 : X509_NAME_oneline(X509_get_subject_name(pCert), tmp, sizeof tmp);
42 : 0 : pX509Cert->Assign(1, new StringVal(tmp));
43 : 0 : pX509Cert->Assign(2, new AddrVal(e->Conn()->OrigAddr()));
44 : :
45 : 0 : val_list* vl = new val_list;
46 : 0 : vl->append(e->BuildConnVal());
47 : 0 : vl->append(pX509Cert);
48 : 0 : vl->append(new Val(e->IsOrig(), TYPE_BOOL));
49 : :
50 : 0 : e->Conn()->ConnectionEvent(event, e, vl);
51 : : }
52 : :
53 : 0 : void X509_Cert::sslCertificateError(Contents_SSL* e, int error_numbe)
54 : : {
55 : 0 : Val* err_str = new StringVal(X509_verify_cert_error_string(csc.error));
56 : 0 : val_list* vl = new val_list;
57 : :
58 : 0 : vl->append(e->BuildConnVal());
59 : 0 : vl->append(new Val(csc.error, TYPE_INT));
60 : 0 : vl->append(err_str);
61 : :
62 : 0 : e->Conn()->ConnectionEvent(ssl_X509_error, e, vl);
63 : 0 : }
64 : :
65 : 0 : int X509_Cert::init()
66 : : {
67 : : #if 0
68 : : OpenSSL_add_all_algorithms();
69 : : #endif
70 : :
71 : 0 : ctx = X509_STORE_new();
72 : 0 : int flag = 0;
73 : 0 : int ret = 0;
74 : :
75 [ # # # # ]: 0 : if ( x509_trusted_cert_path &&
[ # # ]
76 : : x509_trusted_cert_path->AsString()->Len() > 0 )
77 : : { // add the path(s) for the local CA's certificates
78 : 0 : const BroString* pString = x509_trusted_cert_path->AsString();
79 : :
80 : 0 : lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
81 [ # # ]: 0 : if ( ! lookup )
82 : : {
83 : 0 : fprintf(stderr, "X509_Cert::init(): initing lookup failed\n");
84 : 0 : flag = 1;
85 : : }
86 : :
87 : 0 : int i = X509_LOOKUP_add_dir(lookup,
88 : : (const char*) pString->Bytes(),
89 : : X509_FILETYPE_PEM);
90 [ # # ]: 0 : if ( ! i )
91 : : {
92 : 0 : fprintf( stderr, "X509_Cert::init(): error adding lookup directory\n" );
93 : 0 : ret = 0;
94 : : }
95 : : }
96 : : else
97 : : {
98 : 0 : printf("X509: Using the default trusted cert path.\n");
99 : 0 : X509_STORE_set_default_paths(ctx);
100 : : }
101 : :
102 : : // Add crl functionality - will only add if defined and
103 : : // X509_STORE_add_lookup was successful.
104 [ # # ][ # # ]: 0 : if ( ! flag && x509_crl_file && x509_crl_file->AsString()->Len() > 0 )
[ # # ][ # # ]
105 : : {
106 : 0 : const BroString* rString = x509_crl_file->AsString();
107 : :
108 [ # # ]: 0 : if ( X509_load_crl_file(lookup, (const char*) rString->Bytes(),
109 : : X509_FILETYPE_PEM) != 1 )
110 : : {
111 : 0 : fprintf(stderr, "X509_Cert::init(): error reading CRL file\n");
112 : 0 : ret = 1;
113 : : }
114 : :
115 : : #if 0
116 : : // Note, openssl version must be > 0.9.7(a).
117 : : X509_STORE_set_flags(ctx,
118 : : X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
119 : : #endif
120 : : }
121 : :
122 : 0 : bInited = true;
123 : 0 : return ret;
124 : : }
125 : :
126 : 0 : int X509_Cert::verify(Contents_SSL* e, const u_char* data, uint32 len)
127 : : {
128 [ # # ]: 0 : if ( ! bInited )
129 : 0 : init();
130 : :
131 : 0 : X509* pCert = d2i_X509_(NULL, &data, len);
132 [ # # ]: 0 : if ( ! pCert )
133 : : {
134 : : // 5 = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY
135 : 0 : sslCertificateError(e, 5);
136 : 0 : return -1;
137 : : }
138 : :
139 : 0 : sslCertificateEvent(e, pCert);
140 : :
141 : 0 : X509_STORE_CTX_init(&csc, ctx, pCert, 0);
142 : 0 : X509_STORE_CTX_set_time(&csc, 0, (time_t) network_time);
143 : 0 : int i = X509_verify_cert(&csc);
144 : 0 : X509_STORE_CTX_cleanup(&csc);
145 : 0 : int ret = 0;
146 : :
147 : 0 : int ext = X509_get_ext_count(pCert);
148 : :
149 [ # # ]: 0 : if ( ext > 0 )
150 : : {
151 : 0 : TableVal* x509ex = new TableVal(x509_extension);
152 : 0 : val_list* vl = new val_list;
153 : : char buf[256];
154 : :
155 [ # # ]: 0 : for ( int k = 0; k < ext; ++k )
156 : : {
157 : 0 : X509_EXTENSION* ex = X509_get_ext(pCert, k);
158 : 0 : ASN1_OBJECT* obj = X509_EXTENSION_get_object(ex);
159 : 0 : i2t_ASN1_OBJECT(buf, sizeof(buf), obj);
160 : :
161 : 0 : Val* index = new Val(k+1, TYPE_COUNT);
162 : 0 : Val* value = new StringVal(strlen(buf), buf);
163 : 0 : x509ex->Assign(index, value);
164 : 0 : Unref(index);
165 : : // later we can do critical extensions like:
166 : : // X509_EXTENSION_get_critical(ex);
167 : : }
168 : :
169 : 0 : vl->append(e->BuildConnVal());
170 : 0 : vl->append(x509ex);
171 : 0 : e->Conn()->ConnectionEvent(process_X509_extensions, e, vl);
172 : : }
173 : :
174 [ # # ]: 0 : if ( ! i )
175 : : {
176 : 0 : sslCertificateError(e, csc.error);
177 : 0 : ret = csc.error;
178 : : }
179 : : else
180 : 0 : ret = 0;
181 : :
182 : 0 : delete pCert;
183 : 0 : return ret;
184 : : }
185 : :
186 : 0 : int X509_Cert::verifyChain(Contents_SSL* e, const u_char* data, uint32 len)
187 : : {
188 [ # # ]: 0 : if ( ! bInited )
189 : 0 : init();
190 : :
191 : : // Gets an ssl3x cert chain (could be one single cert, too,
192 : : // but in chain format).
193 : :
194 : : // Init the stack.
195 : 0 : STACK_OF(X509)* untrustedCerts = sk_X509_new_null();
196 [ # # ]: 0 : if ( ! untrustedCerts )
197 : : {
198 : : // Internal error allocating stack of untrusted certs.
199 : : // 11 = X509_V_ERR_OUT_OF_MEM
200 : 0 : sslCertificateError(e, 11);
201 : 0 : return -1;
202 : : }
203 : :
204 : : // NOT AGAIN!!!
205 : : // Extract certificates and put them into an OpenSSL Stack.
206 : 0 : uint tempLength = 0;
207 : 0 : int certCount = 0;
208 : 0 : X509* pCert = 0; // base cert, this one is to be verified
209 : :
210 [ # # ]: 0 : while ( tempLength < len )
211 : : {
212 : 0 : ++certCount;
213 : : uint32 certLength =
214 : : uint32((data[tempLength + 0] << 16) |
215 : : data[tempLength + 1] << 8) |
216 : 0 : data[tempLength + 2];
217 : :
218 : : // Points to current cert.
219 : 0 : const u_char* pCurrentCert = &data[tempLength+3];
220 : :
221 : 0 : X509* pTemp = d2i_X509_(0, &pCurrentCert, certLength);
222 [ # # ]: 0 : if ( ! pTemp )
223 : : { // error is somewhat of a misnomer
224 : : // 5 = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY
225 : 0 : sslCertificateError(e, 5);
226 : : //FIXME: free ptrs
227 : 0 : return -1;
228 : : }
229 : :
230 [ # # ]: 0 : if ( certCount == 1 )
231 : : // The first certificate goes directly into the ctx.
232 : 0 : pCert = pTemp;
233 : : else
234 : : // The remaining certificates (if any) are put into
235 : : // the list of untrusted certificates
236 : 0 : sk_X509_push(untrustedCerts, pTemp);
237 : :
238 : 0 : tempLength += certLength + 3;
239 : : }
240 : :
241 : 0 : sslCertificateEvent(e, pCert);
242 : :
243 : 0 : X509_STORE_CTX_init(&csc, ctx, pCert, untrustedCerts);
244 : 0 : X509_STORE_CTX_set_time(&csc, 0, (time_t) network_time);
245 : 0 : int i = X509_verify_cert(&csc);
246 : 0 : X509_STORE_CTX_cleanup(&csc);
247 : : //X509_STORE_CTX_free(&csc);
248 : 0 : int ret = 0;
249 : :
250 [ # # ]: 0 : if ( ! i )
251 : : {
252 : 0 : sslCertificateError(e, csc.error);
253 : 0 : ret = csc.error;
254 : : }
255 : : else
256 : 0 : ret = 0;
257 : :
258 : 0 : delete pCert;
259 : : // Free the stack, incuding. contents.
260 : :
261 : : // FIXME: could this break Bro's memory tracking?
262 : 0 : sk_X509_pop_free(untrustedCerts, X509_free);
263 : :
264 : 0 : return ret;
265 [ + - ][ + - ]: 6 : }
|