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
(-)a5ecf12b8f1e (+22 lines)
Added Link Here
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
 * contributor license agreements.  See the NOTICE file distributed with
3
 * this work for additional information regarding copyright ownership.
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
5
 * (the "License"); you may not use this file except in compliance with
6
 * the License.  You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#define OCSP_STATUS_OK        0
18
#define OCSP_STATUS_REVOKED   1
19
#define OCSP_STATUS_UNKNOWN   2
20
21
22
int ocspRequest(X509 *cert, X509 *issuer);
(-)a5ecf12b8f1e (+330 lines)
Added Link Here
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
 * contributor license agreements.  See the NOTICE file distributed with
3
 * this work for additional information regarding copyright ownership.
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
5
 * (the "License"); you may not use this file except in compliance with
6
 * the License.  You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include <sys/types.h>
18
#include <sys/socket.h>
19
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <string.h>
23
24
#include <netdb.h>
25
#include <netinet/in.h>
26
#include <arpa/inet.h>
27
28
#include <openssl/bio.h>
29
#include <openssl/ocsp.h>
30
#include <openssl/err.h>
31
32
33
#include "ocsp_sock.h"
34
35
/* defines with the values as seen by the asn1parse -dump openssl command */
36
#define ASN1_SEQUENCE 0x30
37
#define ASN1_OID      0x06
38
#define ASN1_STRING   0x86
39
40
41
42
/* parses the ocsp url and updates the ocsp_urls and nocsp_urls variables 
43
   returns 0 on success, 1 on failure */
44
static int parse_ocsp_url(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls)
45
{
46
    char **new_ocsp_urls, *ocsp_url;
47
    int len, err = 0, new_nocsp_urls;
48
    if(*asn1 == ASN1_STRING) {
49
        len = *++asn1;
50
        asn1++;
51
        new_nocsp_urls = *nocsp_urls+1;
52
        if((new_ocsp_urls = realloc(*ocsp_urls,new_nocsp_urls)) == NULL) 
53
            err = 1;
54
        if(!err) {
55
            *ocsp_urls = new_ocsp_urls;
56
            *nocsp_urls = new_nocsp_urls;
57
            *(*ocsp_urls + *nocsp_urls) = NULL;
58
            if((ocsp_url = malloc((len+1)*sizeof(char))) == NULL)
59
                err = 1;
60
            else {
61
                memcpy(ocsp_url, asn1, len);
62
                *(ocsp_url+len) = '\0';
63
                *(*ocsp_urls + *nocsp_urls -1 ) = ocsp_url;
64
            }
65
        }
66
    }
67
    return err;
68
69
}
70
71
/* parses the ANS1 OID and if it is an OCSP OID then calls the parse_ocsp_url function */
72
static int parse_ASN1_OID(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls)
73
{
74
    int len, err = 0 ;
75
    const unsigned char OCSP_OID[] = {0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01};
76
77
    len = *++asn1;
78
    asn1++;
79
    if(memcmp(asn1, OCSP_OID, len) == 0 ) {
80
        asn1+=len;
81
        err = parse_ocsp_url(asn1, ocsp_urls, nocsp_urls);
82
    }
83
    return err;
84
}
85
86
87
/* Parses an ASN1 Sequence. It is a recursive function, since if it finds a  sequence
88
   within the sequence it calls recursively itself. This function stops when it finds 
89
   the end of the ASN1 sequence (marked by '\0'), so if there are other sequences within
90
   the same sequence the while loop parses the sequences */
91
92
/* This algo was developped with AIA in mind so it was tested only with this extension */
93
static int parse_ASN1_Sequence(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls)
94
{
95
    int len, err = 0;
96
    while( !err && *asn1 != '\0') {
97
        switch(*asn1) {
98
        case ASN1_SEQUENCE:
99
            len = *++asn1;
100
            asn1++;
101
            err = parse_ASN1_Sequence(asn1, ocsp_urls, nocsp_urls);
102
            break;
103
        case ASN1_OID:
104
            err = parse_ASN1_OID(asn1,ocsp_urls,nocsp_urls);
105
            return 0;
106
            break;
107
        default:
108
            err = 1; /* we shouldn't have any errors */
109
            break;
110
        }
111
        asn1+=len;
112
    }
113
    return err;
114
}
115
116
/* the main function that gets the ASN1 encoding string and returns
117
   a pointer to a NULL terminated "array" of char *, that contains
118
   the ocsp_urls */
119
static char **decode_OCSP_url(ASN1_OCTET_STRING *os)
120
{
121
    char **response = NULL;
122
    unsigned char *ocsp_urls;
123
    int i, len, err = 0, numofresponses = 0 ;
124
125
    len = ASN1_STRING_length(os);
126
127
    ocsp_urls = malloc((size_t)(len+1)*sizeof(char));
128
    memcpy(ocsp_urls,os->data, (size_t) len);
129
    ocsp_urls[len] = '\0';
130
131
    if ((response = malloc(sizeof(char *))) == NULL)
132
        return NULL;
133
    *response = NULL;
134
135
    err = parse_ASN1_Sequence(ocsp_urls, &response, &numofresponses);
136
    if (err) {
137
        for(i = 0 ; i < numofresponses ; i++)
138
            free(response[i]);
139
        free(response);
140
        response = NULL;
141
    }
142
143
    free(ocsp_urls);
144
    return response;
145
}
146
147
148
149
/* stolen from openssl ocsp command */
150
static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
151
  STACK_OF(OCSP_CERTID) *ids)
152
{
153
    OCSP_CERTID *id;
154
    if(!issuer)
155
        return 0;
156
    if(!*req) *req = OCSP_REQUEST_new();
157
    if(!*req) goto err;
158
    id = OCSP_cert_to_id(NULL, cert, issuer);
159
    if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
160
    if(!OCSP_request_add0_id(*req, id)) goto err;
161
    return 1;
162
163
err:
164
    return 0;
165
}
166
167
168
/* Creates a socket, connects to the OCSP host and then
169
   returns a BIO object than can be used from the openssl
170
   library
171
172
   TODO : Suport https connections 
173
*/
174
static BIO *make_socket(char *hostname, int port)
175
{
176
    BIO *biosock;
177
    struct hostent *host;
178
    int sock, r = 0;
179
    struct sockaddr_in sa_in;
180
181
    bzero(&sa_in, sizeof(struct sockaddr_in));
182
183
184
    sa_in.sin_family = AF_INET;
185
    sa_in.sin_port = htons(port);
186
187
    sa_in.sin_addr.s_addr = inet_addr(hostname); /* if the adrress is
188
                                                    already in IP notation
189
                                                    then we can use it */
190
    if(sa_in.sin_addr.s_addr == -1) {
191
        h_errno = NETDB_SUCCESS;     /* Clear h_errno */
192
        do {
193
            host = gethostbyname(hostname);  /* If we have a try again error  */
194
            r++;
195
        }while(r < 10 && h_errno == TRY_AGAIN); /* we try for 10 times */
196
        /* for all other errors , we just fail */
197
        if(host == NULL)
198
            return NULL;
199
200
        memcpy(&(sa_in.sin_addr), host->h_addr, sizeof(sa_in.sin_addr));
201
        if(sa_in.sin_addr.s_addr == -1)
202
            return NULL;
203
    }
204
205
    sock = socket(AF_INET,SOCK_STREAM, 0);
206
    if(sock == -1)
207
        return NULL;
208
209
    if ( (connect(sock,(struct sockaddr *) &sa_in, sizeof(struct sockaddr_in))) == -1)
210
        return NULL;
211
212
    biosock = BIO_new_socket(sock, BIO_CLOSE); /* when we free we want the socket to close
213
                                                  BIO_CLOSE does this (????) */
214
    return biosock;
215
216
}
217
218
/* Creates and OCSP request and returns the OCSP_RESPONSE */
219
static OCSP_RESPONSE *get_ocsp_response(X509 *cert, X509 *issuer, char *url)
220
{
221
    OCSP_RESPONSE *ocsp_resp;
222
    OCSP_REQUEST *ocsp_req;
223
    BIO *sock;
224
    char *hostname, *path, *c_port;
225
    int port, use_ssl;
226
    STACK_OF(OCSP_CERTID) *ids = NULL;
227
228
    ids = sk_OCSP_CERTID_new_null();
229
230
    /* problem parsing the URL */
231
    if(OCSP_parse_url(url,&hostname, &c_port, &path, &use_ssl) == 0 ) {
232
        sk_OCP_CERTID_free(ids);
233
        return NULL;
234
    }
235
236
    /* Create the OCSP request */
237
    if(sscanf(c_port, "%d", &port) != 1)
238
        goto end;
239
    ocsp_req = OCSP_REQUEST_new();
240
    if(ocsp_req == NULL)
241
        return NULL;
242
    if(add_ocsp_cert(&ocsp_req,cert,issuer,ids) == 0 )
243
        goto free_req;
244
245
    sock = make_socket(hostname, port);
246
    if (sock == NULL) {
247
        ocsp_resp = NULL;
248
        goto free_req;
249
    }
250
251
    ocsp_resp = OCSP_sendreq_bio(sock,path,ocsp_req);
252
253
254
    BIO_free(sock);
255
256
free_req:
257
    sk_OCSP_CERTID_free(ids);
258
    OCSP_REQUEST_free(ocsp_req);
259
260
end:
261
    return ocsp_resp;
262
}
263
264
/* Process the OCSP_RESPONSE and returns the corresponding
265
   answert according to the status.
266
*/
267
static int processOCSPResponse(OCSP_RESPONSE *ocsp_resp)
268
{
269
    int r, o = V_OCSP_CERTSTATUS_UNKNOWN, i;
270
    OCSP_BASICRESP *bs;
271
    OCSP_SINGLERESP *ss;
272
273
    r = OCSP_response_status(ocsp_resp);
274
275
    if(r != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
276
        OCSP_RESPONSE_free(ocsp_resp);
277
        return OCSP_STATUS_UNKNOWN;
278
    }
279
    bs = OCSP_response_get1_basic(ocsp_resp);
280
281
    ss = OCSP_resp_get0(bs,0); /* we know we have only 1 request */
282
283
    i = OCSP_single_get0_status(ss, NULL, NULL, NULL, NULL);
284
    if ( i == V_OCSP_CERTSTATUS_GOOD )
285
        o =  OCSP_STATUS_OK;
286
    else if ( i == V_OCSP_CERTSTATUS_REVOKED )
287
        o = OCSP_STATUS_REVOKED;
288
    else if ( i == V_OCSP_CERTSTATUS_UNKNOWN)
289
        o = OCSP_STATUS_UNKNOWN;
290
291
    /* we clean up */
292
    OCSP_RESPONSE_free(ocsp_resp);
293
294
    return o;
295
}
296
297
298
int ocspRequest(X509 *cert, X509 *issuer)
299
{
300
    char **ocsp_urls = NULL;
301
    int nid, i;
302
    X509_EXTENSION *ext;
303
    ASN1_OCTET_STRING *os;
304
305
    /* Get the proper extension */
306
    nid = X509_get_ext_by_NID(cert,NID_info_access,-1);
307
    if(nid >= 0 ) {
308
        ext = X509_get_ext(cert,nid);
309
        os = X509_EXTENSION_get_data(ext);
310
311
        ocsp_urls = decode_OCSP_url(os);
312
    }
313
314
    /* if we find the extensions and we can parse it check 
315
       the ocsp status. Otherwise, return OCSP_STATUS_UNKNOWN */
316
    if(ocsp_urls != NULL) {
317
        OCSP_RESPONSE *resp;
318
        /* for the time being just check for the fist response .. a better
319
           approach is to iterate for all the possible ocsp urls */
320
        resp = get_ocsp_response(cert, issuer, ocsp_urls[0]);
321
322
        /* memory clean up */
323
        for(i = 0 ; ocsp_urls[i] != NULL ; i++ )
324
            free(ocsp_urls[i]);
325
        free(ocsp_urls);
326
327
        return processOCSPResponse(resp);
328
    }
329
    return OCSP_STATUS_UNKNOWN;
330
}
(-)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