View | Details | Raw Unified | Return to bug 45392
Collapse All | Expand All

(-)a/jni/native/build-outputs.mk (-1 / +2 lines)
Lines 1-5 Link Here
1
# DO NOT EDIT. AUTOMATICALLY GENERATED.
1
# DO NOT EDIT. AUTOMATICALLY GENERATED.
2
2
3
src/ocsp_sock.lo: src/ocsp_sock.c .make.dirs include/ocsp_sock.h
3
src/proc.lo: src/proc.c .make.dirs include/tcn.h include/tcn_api.h
4
src/proc.lo: src/proc.c .make.dirs include/tcn.h include/tcn_api.h
4
src/poll.lo: src/poll.c .make.dirs include/tcn.h include/tcn_api.h
5
src/poll.lo: src/poll.c .make.dirs include/tcn.h include/tcn_api.h
5
src/ssl.lo: src/ssl.c .make.dirs include/tcn.h include/tcn_api.h include/ssl_private.h
6
src/ssl.lo: src/ssl.c .make.dirs include/tcn.h include/tcn_api.h include/ssl_private.h
Lines 26-32 src/os.lo: src/os.c .make.dirs include/t Link Here
26
src/os.lo: src/os.c .make.dirs include/tcn.h include/tcn_api.h
27
src/os.lo: src/os.c .make.dirs include/tcn.h include/tcn_api.h
27
src/pool.lo: src/pool.c .make.dirs include/tcn.h include/tcn_api.h
28
src/pool.lo: src/pool.c .make.dirs include/tcn.h include/tcn_api.h
28
29
29
OBJECTS_all = src/proc.lo src/poll.lo src/ssl.lo src/sslutils.lo src/thread.lo src/dir.lo src/network.lo src/sslinfo.lo src/stdlib.lo src/multicast.lo src/error.lo src/lock.lo src/file.lo src/sslcontext.lo src/jnilib.lo src/info.lo src/mmap.lo src/shm.lo src/user.lo src/address.lo src/misc.lo src/bb.lo src/sslnetwork.lo src/os.lo src/pool.lo
30
OBJECTS_all = src/ocsp_sock src/proc.lo src/poll.lo src/ssl.lo src/sslutils.lo src/thread.lo src/dir.lo src/network.lo src/sslinfo.lo src/stdlib.lo src/multicast.lo src/error.lo src/lock.lo src/file.lo src/sslcontext.lo src/jnilib.lo src/info.lo src/mmap.lo src/shm.lo src/user.lo src/address.lo src/misc.lo src/bb.lo src/sslnetwork.lo src/os.lo src/pool.lo
30
31
31
os/unix/system.lo: os/unix/system.c .make.dirs include/tcn.h include/tcn_api.h
32
os/unix/system.lo: os/unix/system.c .make.dirs include/tcn.h include/tcn_api.h
32
os/unix/uxpipe.lo: os/unix/uxpipe.c .make.dirs include/tcn.h include/tcn_api.h
33
os/unix/uxpipe.lo: os/unix/uxpipe.c .make.dirs include/tcn.h include/tcn_api.h
(-)3b86749fdda8 (+6 lines)
Added Link Here
1
#define OCSP_STATUS_OK        0
2
#define OCSP_STATUS_REVOKED   1
3
#define OCSP_STATUS_UNKNOWN   2
4
5
6
int ocspRequest(X509 *cert, X509 *issuer);
(-)3b86749fdda8 (+314 lines)
Added Link Here
1
#include <sys/types.h>
2
#include <sys/socket.h>
3
4
#include <stdio.h>
5
#include <stdlib.h>
6
#include <string.h>
7
8
#include <netdb.h>
9
#include <netinet/in.h>
10
#include <arpa/inet.h>
11
12
#include <openssl/bio.h>
13
#include <openssl/ocsp.h>
14
#include <openssl/err.h>
15
16
17
#include "ocsp_sock.h"
18
19
/* defines with the values as seen by the asn1parse -dump openssl command */
20
#define ASN1_SEQUENCE 0x30
21
#define ASN1_OID      0x06
22
#define ASN1_STRING   0x86
23
24
25
26
/* parses the ocsp url and updates the ocsp_urls and nocsp_urls variables 
27
   returns 0 on success, 1 on failure */
28
static int parse_ocsp_url(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls)
29
{
30
	char **new_ocsp_urls, *ocsp_url;
31
	int len, err = 0, new_nocsp_urls;
32
	if(*asn1 == ASN1_STRING) {
33
		len = *++asn1;
34
		asn1++;
35
		new_nocsp_urls = *nocsp_urls+1;
36
		if((new_ocsp_urls = realloc(*ocsp_urls,new_nocsp_urls)) == NULL) 
37
			err = 1;
38
		if(!err) {
39
			*ocsp_urls = new_ocsp_urls;
40
			*nocsp_urls = new_nocsp_urls;
41
			*(*ocsp_urls + *nocsp_urls) = NULL;
42
			if((ocsp_url = malloc((len+1)*sizeof(char))) == NULL)
43
				err = 1;
44
			else {
45
				memcpy(ocsp_url, asn1, len);
46
				*(ocsp_url+len) = '\0';
47
				*(*ocsp_urls + *nocsp_urls -1 ) = ocsp_url;
48
			}
49
		}
50
	}
51
		return err;
52
53
}
54
55
/* parses the ANS1 OID and if it is an OCSP OID then calls the parse_ocsp_url function */
56
static int parse_ASN1_OID(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls)
57
{
58
	int len, err = 0 ;
59
	const unsigned char OCSP_OID[] = {0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01};
60
61
	len = *++asn1;
62
	asn1++;
63
	if(memcmp(asn1, OCSP_OID, len) == 0 ) {
64
		asn1+=len;
65
		err = parse_ocsp_url(asn1, ocsp_urls, nocsp_urls);
66
	}
67
	return err;
68
}
69
70
71
/* Parses an ASN1 Sequence. It is a recursive function, since if it finds a  sequence
72
   within the sequence it calls recursively itself. This function stops when it finds 
73
   the end of the ASN1 sequence (marked by '\0'), so if there are other sequences within
74
   the same sequence the while loop parses the sequences */
75
76
/* This algo was developped with AIA in mind so it was tested only with this extension */
77
static int parse_ASN1_Sequence(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls)
78
{
79
	int len, err = 0;
80
	while( !err && *asn1 != '\0') {
81
		 switch(*asn1) {
82
		 case ASN1_SEQUENCE:
83
			 len = *++asn1;
84
			 asn1++;
85
			 err = parse_ASN1_Sequence(asn1, ocsp_urls, nocsp_urls);
86
			 break;
87
		 case ASN1_OID:
88
			 err = parse_ASN1_OID(asn1,ocsp_urls,nocsp_urls);
89
			 return 0;
90
			 break;
91
		 default:
92
			 err = 1; /* we shouldn't have any errors */
93
			 break;
94
		 }
95
		 asn1+=len;
96
	}
97
	return err;
98
}
99
100
/* the main function that gets the ASN1 encoding string and returns
101
   a pointer to a NULL terminated "array" of char *, that contains
102
   the ocsp_urls */
103
static char **decode_OCSP_url(ASN1_OCTET_STRING *os)
104
{
105
	char **response = NULL;
106
	unsigned char *ocsp_urls;
107
	int i, len, err = 0, numofresponses = 0 ;
108
109
	len = ASN1_STRING_length(os);
110
111
	ocsp_urls = malloc((size_t)(len+1)*sizeof(char));
112
	memcpy(ocsp_urls,os->data, (size_t) len);
113
	ocsp_urls[len] = '\0';
114
115
	if ((response = malloc(sizeof(char *))) == NULL)
116
		return NULL;
117
	*response = NULL;
118
119
	err = parse_ASN1_Sequence(ocsp_urls, &response, &numofresponses);
120
	if (err) {
121
		for(i = 0 ; i < numofresponses ; i++)
122
			free(response[i]);
123
		free(response);
124
		response = NULL;
125
	}
126
127
	free(ocsp_urls);
128
	return response;
129
}
130
131
132
133
/* stolen from openssl ocsp command */
134
static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
135
    STACK_OF(OCSP_CERTID) *ids)
136
{
137
	OCSP_CERTID *id;
138
	if(!issuer)
139
		return 0;
140
	if(!*req) *req = OCSP_REQUEST_new();
141
	if(!*req) goto err;
142
	id = OCSP_cert_to_id(NULL, cert, issuer);
143
	if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
144
	if(!OCSP_request_add0_id(*req, id)) goto err;
145
	return 1;
146
147
err:
148
	return 0;
149
}
150
151
152
/* Creates a socket, connects to the OCSP host and then
153
returns a BIO object than can be used from the openssl
154
library
155
156
TODO : Suport https connections 
157
*/
158
static BIO *make_socket(char *hostname, int port)
159
{
160
	BIO *biosock;
161
	struct hostent *host;
162
	int sock, r = 0;
163
	struct sockaddr_in sa_in;
164
165
	bzero(&sa_in, sizeof(struct sockaddr_in));
166
167
168
	sa_in.sin_family = AF_INET;
169
	sa_in.sin_port = htons(port);
170
171
	sa_in.sin_addr.s_addr = inet_addr(hostname); /* if the adrress is
172
							already in IP notation
173
							then we can use it */
174
	if(sa_in.sin_addr.s_addr == -1) {
175
		h_errno = NETDB_SUCCESS;     /* Clear h_errno */
176
		do {
177
			host = gethostbyname(hostname);  /* If we have a try again error  */
178
			r++;
179
		}while(r < 10 && h_errno == TRY_AGAIN); /* we try for 10 times */
180
		/* for all other errors , we just fail */
181
		if(host == NULL)
182
			return NULL;
183
184
		memcpy(&(sa_in.sin_addr), host->h_addr, sizeof(sa_in.sin_addr));
185
		if(sa_in.sin_addr.s_addr == -1)
186
			return NULL;
187
	}
188
189
	sock = socket(AF_INET,SOCK_STREAM, 0);
190
	if(sock == -1)
191
		return NULL;
192
193
	if ( (connect(sock,(struct sockaddr *) &sa_in, sizeof(struct sockaddr_in))) == -1)
194
	    return NULL;
195
196
	biosock = BIO_new_socket(sock, BIO_CLOSE); /* when we free we want the socket to close
197
						      BIO_CLOSE does this (????) */
198
	return biosock;
199
200
}
201
202
/* Creates and OCSP request and returns the OCSP_RESPONSE */
203
static OCSP_RESPONSE *get_ocsp_response(X509 *cert, X509 *issuer, char *url)
204
{
205
	OCSP_RESPONSE *ocsp_resp;
206
	OCSP_REQUEST *ocsp_req;
207
	BIO *sock;
208
	char *hostname, *path, *c_port;
209
	int port, use_ssl;
210
	STACK_OF(OCSP_CERTID) *ids = NULL;
211
212
	ids = sk_OCSP_CERTID_new_null();
213
214
	/* problem parsing the URL */
215
	if(OCSP_parse_url(url,&hostname, &c_port, &path, &use_ssl) == 0 ) {
216
		sk_OCP_CERTID_free(ids);
217
		return NULL;
218
	}
219
220
	/* Create the OCSP request */
221
	if(sscanf(c_port, "%d", &port) != 1)
222
		goto end;
223
	ocsp_req = OCSP_REQUEST_new();
224
	if(ocsp_req == NULL)
225
		return NULL;
226
	if(add_ocsp_cert(&ocsp_req,cert,issuer,ids) == 0 )
227
		goto free_req;
228
229
	sock = make_socket(hostname, port);
230
	if (sock == NULL) {
231
		ocsp_resp = NULL;
232
		goto free_req;
233
	}
234
235
	ocsp_resp = OCSP_sendreq_bio(sock,path,ocsp_req);
236
237
238
	BIO_free(sock);
239
240
free_req:
241
	sk_OCSP_CERTID_free(ids);
242
	OCSP_REQUEST_free(ocsp_req);
243
244
end:
245
	return ocsp_resp;
246
}
247
248
/* Process the OCSP_RESPONSE and returns the corresponding
249
   answert according to the status.
250
*/
251
static int processOCSPResponse(OCSP_RESPONSE *ocsp_resp)
252
{
253
	int r, o = V_OCSP_CERTSTATUS_UNKNOWN, i;
254
	OCSP_BASICRESP *bs;
255
	OCSP_SINGLERESP *ss;
256
257
	r = OCSP_response_status(ocsp_resp);
258
259
	if(r != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
260
		OCSP_RESPONSE_free(ocsp_resp);
261
		return OCSP_STATUS_UNKNOWN;
262
	}
263
	bs = OCSP_response_get1_basic(ocsp_resp);
264
265
	ss = OCSP_resp_get0(bs,0); /* we know we have only 1 request */
266
267
	i = OCSP_single_get0_status(ss, NULL, NULL, NULL, NULL);
268
	if ( i == V_OCSP_CERTSTATUS_GOOD )
269
		o =  OCSP_STATUS_OK;
270
	else if ( i == V_OCSP_CERTSTATUS_REVOKED )
271
		o = OCSP_STATUS_REVOKED;
272
	else if ( i == V_OCSP_CERTSTATUS_UNKNOWN)
273
		o = OCSP_STATUS_UNKNOWN;
274
275
	/* we clean up */
276
	OCSP_RESPONSE_free(ocsp_resp);
277
278
	return o;
279
}
280
281
282
int ocspRequest(X509 *cert, X509 *issuer)
283
{
284
	char **ocsp_urls = NULL;
285
	int nid, i;
286
	X509_EXTENSION *ext;
287
	ASN1_OCTET_STRING *os;
288
289
	/* Get the proper extension */
290
	nid = X509_get_ext_by_NID(cert,NID_info_access,-1);
291
	if(nid >= 0 ) {
292
		ext = X509_get_ext(cert,nid);
293
		os = X509_EXTENSION_get_data(ext);
294
295
		ocsp_urls = decode_OCSP_url(os);
296
	}
297
298
	/* if we find the extensions and we can parse it check 
299
	   the ocsp status. Otherwise, return OCSP_STATUS_UNKNOWN */
300
	if(ocsp_urls != NULL) {
301
		OCSP_RESPONSE *resp;
302
		/* for the time being just check for the fist response .. a better
303
		   approach is to iterate for all the possible ocsp urls */
304
		resp = get_ocsp_response(cert, issuer, ocsp_urls[0]);
305
306
		/* memory clean up */
307
		for(i = 0 ; ocsp_urls[i] != NULL ; i++ )
308
			free(ocsp_urls[i]);
309
		free(ocsp_urls);
310
311
		return processOCSPResponse(resp);
312
	}
313
	return OCSP_STATUS_UNKNOWN;
314
}
(-)a/jni/native/src/sslutils.c (-1 / +48 lines)
Lines 31-36 extern int WIN32_SSL_password_prompt(tcn Link Here
31
extern int WIN32_SSL_password_prompt(tcn_pass_cb_t *data);
31
extern int WIN32_SSL_password_prompt(tcn_pass_cb_t *data);
32
#endif
32
#endif
33
33
34
#include "ocsp_sock.h"
34
/*  _________________________________________________________________
35
/*  _________________________________________________________________
35
**
36
**
36
**  Additional High-Level Functions for OpenSSL
37
**  Additional High-Level Functions for OpenSSL
Lines 621-626 static int ssl_verify_CRL(int ok, X509_S Link Here
621
 * This OpenSSL callback function is called when OpenSSL
622
 * This OpenSSL callback function is called when OpenSSL
622
 * does client authentication and verifies the certificate chain.
623
 * does client authentication and verifies the certificate chain.
623
 */
624
 */
625
626
624
int SSL_callback_SSL_verify(int ok, X509_STORE_CTX *ctx)
627
int SSL_callback_SSL_verify(int ok, X509_STORE_CTX *ctx)
625
{
628
{
626
   /* Get Apache context back through OpenSSL context */
629
   /* Get Apache context back through OpenSSL context */
Lines 632-637 int SSL_callback_SSL_verify(int ok, X509 Link Here
632
    int errdepth = X509_STORE_CTX_get_error_depth(ctx);
635
    int errdepth = X509_STORE_CTX_get_error_depth(ctx);
633
    int verify   = con->ctx->verify_mode;
636
    int verify   = con->ctx->verify_mode;
634
    int depth    = con->ctx->verify_depth;
637
    int depth    = con->ctx->verify_depth;
638
    int ocsp_response;
639
    int skip_crl = 0;
635
640
636
    if (verify == SSL_CVERIFY_UNSET ||
641
    if (verify == SSL_CVERIFY_UNSET ||
637
        verify == SSL_CVERIFY_NONE)
642
        verify == SSL_CVERIFY_NONE)
Lines 642-651 int SSL_callback_SSL_verify(int ok, X509 Link Here
642
        ok = 1;
647
        ok = 1;
643
        SSL_set_verify_result(ssl, X509_V_OK);
648
        SSL_set_verify_result(ssl, X509_V_OK);
644
    }
649
    }
650
651
    /* First perform OCSP validation if possible */
652
    if(ok) {
653
	    ocsp_response = ssl_verify_OCSP(ok, ctx);
654
	    if (ocsp_response == OCSP_STATUS_OK ) {
655
		    skip_crl = 1; /* we know it is valid we skip crl evaluation */
656
            }
657
	    else if(ocsp_response == OCSP_STATUS_REVOKED ) {
658
		    ok = 0 ;
659
		    errnum = X509_STORE_CTX_get_error(ctx);
660
	    }
661
	    else if (ocsp_response == OCSP_STATUS_UNKNOWN) 
662
		    ; /* do nothing for time being, continue with CRL */
663
    }
645
    /*
664
    /*
646
     * Additionally perform CRL-based revocation checks
665
     * Additionally perform CRL-based revocation checks
647
     */
666
     */
648
    if (ok && con->ctx->crl) {
667
    if (ok && con->ctx->crl && !skip_crl) {
649
        if (!(ok = ssl_verify_CRL(ok, ctx, con))) {
668
        if (!(ok = ssl_verify_CRL(ok, ctx, con))) {
650
            errnum = X509_STORE_CTX_get_error(ctx);
669
            errnum = X509_STORE_CTX_get_error(ctx);
651
            /* TODO: Log something */
670
            /* TODO: Log something */
Lines 672-675 int SSL_callback_SSL_verify(int ok, X509 Link Here
672
    return ok;
691
    return ok;
673
}
692
}
674
693
694
695
/* Function that is used to do the OCSP verification */
696
int ssl_verify_OCSP(int ok, X509_STORE_CTX *ctx)
697
{
698
	X509 *cert, *issuer;
699
	int r, o;
700
701
	cert = X509_STORE_CTX_get_current_cert(ctx);
702
703
	o = X509_STORE_CTX_get1_issuer(&issuer, ctx, cert);
704
	/* if we can't get the issuer, we cannot perform OCSP verification */
705
	if( o == 1 ) {
706
		r = ocspRequest(cert, issuer);
707
		if (r == OCSP_STATUS_REVOKED )
708
/* we set the error if we know that it is revoked */
709
			X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
710
		else
711
			r = OCSP_STATUS_UNKNOWN; /* else we return unknown, so that we can continue with the crl */
712
		X509_free(issuer); /* It appears that we  should free issuer since
713
				      X509_STORE_CTX_get1_issuer() calls X509_OBJECT_up_ref_count()
714
				      on the issuer object (unline X509_STORE_CTX_get_current_cert()
715
				      that just returns the pointer */
716
717
	}
718
719
	return r;
720
}
721
675
#endif
722
#endif

Return to bug 45392