Lines 31-36
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 |
#ifdef HAVE_SSL_OCSP |
35 |
#include <stdio.h> |
36 |
#include <stdlib.h> |
37 |
#include <string.h> |
38 |
#include <ctype.h> |
39 |
|
40 |
#include <openssl/bio.h> |
41 |
#include <openssl/ocsp.h> |
42 |
|
43 |
#include "apr_network_io.h" |
44 |
|
45 |
#include "ocsp_sock.h" |
46 |
|
47 |
/* defines with the values as seen by the asn1parse -dump openssl command */ |
48 |
#define ASN1_SEQUENCE 0x30 |
49 |
#define ASN1_OID 0x06 |
50 |
#define ASN1_STRING 0x86 |
51 |
|
52 |
int ssl_verify_OCSP(int ok, X509_STORE_CTX *ctx); |
53 |
|
54 |
#endif /* HAVE_SSL_OCSP */ |
34 |
/* _________________________________________________________________ |
55 |
/* _________________________________________________________________ |
35 |
** |
56 |
** |
36 |
** Additional High-Level Functions for OpenSSL |
57 |
** Additional High-Level Functions for OpenSSL |
Lines 621-626
Link Here
|
621 |
* This OpenSSL callback function is called when OpenSSL |
642 |
* This OpenSSL callback function is called when OpenSSL |
622 |
* does client authentication and verifies the certificate chain. |
643 |
* does client authentication and verifies the certificate chain. |
623 |
*/ |
644 |
*/ |
|
|
645 |
|
646 |
|
624 |
int SSL_callback_SSL_verify(int ok, X509_STORE_CTX *ctx) |
647 |
int SSL_callback_SSL_verify(int ok, X509_STORE_CTX *ctx) |
625 |
{ |
648 |
{ |
626 |
/* Get Apache context back through OpenSSL context */ |
649 |
/* Get Apache context back through OpenSSL context */ |
Lines 632-637
Link Here
|
632 |
int errdepth = X509_STORE_CTX_get_error_depth(ctx); |
655 |
int errdepth = X509_STORE_CTX_get_error_depth(ctx); |
633 |
int verify = con->ctx->verify_mode; |
656 |
int verify = con->ctx->verify_mode; |
634 |
int depth = con->ctx->verify_depth; |
657 |
int depth = con->ctx->verify_depth; |
|
|
658 |
int ocsp_response; |
659 |
int skip_crl = 0; |
635 |
|
660 |
|
636 |
if (verify == SSL_CVERIFY_UNSET || |
661 |
if (verify == SSL_CVERIFY_UNSET || |
637 |
verify == SSL_CVERIFY_NONE) |
662 |
verify == SSL_CVERIFY_NONE) |
Lines 642-651
Link Here
|
642 |
ok = 1; |
667 |
ok = 1; |
643 |
SSL_set_verify_result(ssl, X509_V_OK); |
668 |
SSL_set_verify_result(ssl, X509_V_OK); |
644 |
} |
669 |
} |
|
|
670 |
|
671 |
#ifdef HAVE_SSL_OCSP |
672 |
/* First perform OCSP validation if possible */ |
673 |
if(ok) { |
674 |
ocsp_response = ssl_verify_OCSP(ok, ctx); |
675 |
if (ocsp_response == OCSP_STATUS_OK ) { |
676 |
skip_crl = 1; /* we know it is valid we skip crl evaluation */ |
677 |
} |
678 |
else if(ocsp_response == OCSP_STATUS_REVOKED ) { |
679 |
ok = 0 ; |
680 |
errnum = X509_STORE_CTX_get_error(ctx); |
681 |
} |
682 |
else if (ocsp_response == OCSP_STATUS_UNKNOWN) |
683 |
; /* do nothing for time being, continue with CRL */ |
684 |
} |
685 |
#endif /* HAVE_SSL_OCSP */ |
645 |
/* |
686 |
/* |
646 |
* Additionally perform CRL-based revocation checks |
687 |
* Additionally perform CRL-based revocation checks |
647 |
*/ |
688 |
*/ |
648 |
if (ok && con->ctx->crl) { |
689 |
if (ok && con->ctx->crl && !skip_crl) { |
649 |
if (!(ok = ssl_verify_CRL(ok, ctx, con))) { |
690 |
if (!(ok = ssl_verify_CRL(ok, ctx, con))) { |
650 |
errnum = X509_STORE_CTX_get_error(ctx); |
691 |
errnum = X509_STORE_CTX_get_error(ctx); |
651 |
/* TODO: Log something */ |
692 |
/* TODO: Log something */ |
Lines 672-675
Link Here
|
672 |
return ok; |
713 |
return ok; |
673 |
} |
714 |
} |
674 |
|
715 |
|
|
|
716 |
#ifdef HAVE_SSL_OCSP |
717 |
|
718 |
/* Function that is used to do the OCSP verification */ |
719 |
int ssl_verify_OCSP(int ok, X509_STORE_CTX *ctx) |
720 |
{ |
721 |
X509 *cert, *issuer; |
722 |
int r = OCSP_STATUS_UNKNOWN, o; |
723 |
|
724 |
cert = X509_STORE_CTX_get_current_cert(ctx); |
725 |
|
726 |
o = X509_STORE_CTX_get1_issuer(&issuer, ctx, cert); |
727 |
/* if we can't get the issuer, we cannot perform OCSP verification */ |
728 |
if( o == 1 ) { |
729 |
r = ocspRequest(cert, issuer); |
730 |
if (r == OCSP_STATUS_REVOKED ) |
731 |
/* we set the error if we know that it is revoked */ |
732 |
X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED); |
733 |
else |
734 |
r = OCSP_STATUS_UNKNOWN; /* else we return unknown, so that we can continue with the crl */ |
735 |
X509_free(issuer); /* It appears that we should free issuer since |
736 |
X509_STORE_CTX_get1_issuer() calls X509_OBJECT_up_ref_count() |
737 |
on the issuer object (unline X509_STORE_CTX_get_current_cert() |
738 |
that just returns the pointer */ |
739 |
|
740 |
} |
741 |
|
742 |
return r; |
743 |
} |
744 |
|
745 |
|
746 |
/* Helps with error handling or realloc */ |
747 |
static void *apr_xrealloc(void *buf, size_t oldlen, size_t len, apr_pool_t *p) |
748 |
{ |
749 |
void *newp; |
750 |
newp = apr_palloc(p, len); |
751 |
if(newp) |
752 |
memcpy(newp, buf, oldlen); |
753 |
|
754 |
return newp; |
755 |
} |
756 |
|
757 |
/* parses the ocsp url and updates the ocsp_urls and nocsp_urls variables |
758 |
returns 0 on success, 1 on failure */ |
759 |
static int parse_ocsp_url(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls, apr_pool_t *p) |
760 |
{ |
761 |
char **new_ocsp_urls, *ocsp_url; |
762 |
int len, err = 0, new_nocsp_urls; |
763 |
|
764 |
if(*asn1 == ASN1_STRING) { |
765 |
len = *++asn1; |
766 |
asn1++; |
767 |
new_nocsp_urls = *nocsp_urls+1; |
768 |
if((new_ocsp_urls = apr_xrealloc(*ocsp_urls,*nocsp_urls, new_nocsp_urls, p)) == NULL) |
769 |
err = 1; |
770 |
if(!err) { |
771 |
*ocsp_urls = new_ocsp_urls; |
772 |
*nocsp_urls = new_nocsp_urls; |
773 |
*(*ocsp_urls + *nocsp_urls) = NULL; |
774 |
if((ocsp_url = apr_palloc(p, (len+1)*sizeof(char))) == NULL) { |
775 |
err = 1; |
776 |
} |
777 |
else { |
778 |
memcpy(ocsp_url, asn1, len); |
779 |
*(ocsp_url+len) = '\0'; |
780 |
*(*ocsp_urls + *nocsp_urls -1 ) = ocsp_url; |
781 |
} |
782 |
} |
783 |
} |
784 |
return err; |
785 |
|
786 |
} |
787 |
|
788 |
/* parses the ANS1 OID and if it is an OCSP OID then calls the parse_ocsp_url function */ |
789 |
static int parse_ASN1_OID(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls, apr_pool_t *p) |
790 |
{ |
791 |
int len, err = 0 ; |
792 |
const unsigned char OCSP_OID[] = {0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01}; |
793 |
|
794 |
len = *++asn1; |
795 |
asn1++; |
796 |
if(memcmp(asn1, OCSP_OID, len) == 0 ) { |
797 |
asn1+=len; |
798 |
err = parse_ocsp_url(asn1, ocsp_urls, nocsp_urls, p); |
799 |
} |
800 |
return err; |
801 |
} |
802 |
|
803 |
|
804 |
/* Parses an ASN1 Sequence. It is a recursive function, since if it finds a sequence |
805 |
within the sequence it calls recursively itself. This function stops when it finds |
806 |
the end of the ASN1 sequence (marked by '\0'), so if there are other sequences within |
807 |
the same sequence the while loop parses the sequences */ |
808 |
|
809 |
/* This algo was developped with AIA in mind so it was tested only with this extension */ |
810 |
static int parse_ASN1_Sequence(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls, apr_pool_t *p) |
811 |
{ |
812 |
int len = 0 , err = 0; |
813 |
while( !err && *asn1 != '\0') { |
814 |
switch(*asn1) { |
815 |
case ASN1_SEQUENCE: |
816 |
len = *++asn1; |
817 |
asn1++; |
818 |
err = parse_ASN1_Sequence(asn1, ocsp_urls, nocsp_urls, p); |
819 |
break; |
820 |
case ASN1_OID: |
821 |
err = parse_ASN1_OID(asn1,ocsp_urls,nocsp_urls, p); |
822 |
return 0; |
823 |
break; |
824 |
default: |
825 |
err = 1; /* we shouldn't have any errors */ |
826 |
break; |
827 |
} |
828 |
asn1+=len; |
829 |
} |
830 |
return err; |
831 |
} |
832 |
|
833 |
/* the main function that gets the ASN1 encoding string and returns |
834 |
a pointer to a NULL terminated "array" of char *, that contains |
835 |
the ocsp_urls */ |
836 |
static char **decode_OCSP_url(ASN1_OCTET_STRING *os, apr_pool_t *p) |
837 |
{ |
838 |
char **response = NULL; |
839 |
unsigned char *ocsp_urls; |
840 |
int i, len, err = 0, numofresponses = 0 ; |
841 |
|
842 |
len = ASN1_STRING_length(os); |
843 |
|
844 |
ocsp_urls = apr_palloc(p, ((size_t)(len+1)*sizeof(char))); |
845 |
memcpy(ocsp_urls,os->data, (size_t) len); |
846 |
ocsp_urls[len] = '\0'; |
847 |
|
848 |
if ((response = apr_palloc(p, sizeof(char *))) == NULL) |
849 |
return NULL; |
850 |
*response = NULL; |
851 |
|
852 |
err = parse_ASN1_Sequence(ocsp_urls, &response, &numofresponses, p); |
853 |
if (err) { |
854 |
response = NULL; |
855 |
} |
856 |
|
857 |
return response; |
858 |
} |
859 |
|
860 |
|
861 |
|
862 |
/* stolen from openssl ocsp command */ |
863 |
static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer, |
864 |
STACK_OF(OCSP_CERTID) *ids) |
865 |
{ |
866 |
OCSP_CERTID *id; |
867 |
if(!issuer) |
868 |
return 0; |
869 |
if(!*req) *req = OCSP_REQUEST_new(); |
870 |
if(!*req) goto err; |
871 |
id = OCSP_cert_to_id(NULL, cert, issuer); |
872 |
if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err; |
873 |
if(!OCSP_request_add0_id(*req, id)) goto err; |
874 |
return 1; |
875 |
|
876 |
err: |
877 |
return 0; |
878 |
} |
879 |
|
880 |
|
881 |
/* Creates the APR socket and connect to the hostname. Returns the |
882 |
socket or NULL if there is an error. |
883 |
*/ |
884 |
static apr_socket_t *make_socket(char *hostname, int port, apr_pool_t *mp) |
885 |
{ |
886 |
int r = 0; |
887 |
apr_sockaddr_t *sa_in; |
888 |
apr_status_t status; |
889 |
apr_socket_t *sock = NULL; |
890 |
|
891 |
|
892 |
status = apr_sockaddr_info_get(&sa_in, hostname, APR_INET, port, 0, mp); |
893 |
|
894 |
if(status == APR_SUCCESS) |
895 |
status = apr_socket_create(&sock, sa_in->family, SOCK_STREAM, APR_PROTO_TCP, mp); |
896 |
if(status == APR_SUCCESS) |
897 |
status = apr_socket_connect(sock, sa_in); |
898 |
|
899 |
if(status == APR_SUCCESS) |
900 |
return sock; |
901 |
return NULL; |
902 |
|
903 |
} |
904 |
|
905 |
|
906 |
/* Creates the request in a memory BIO in order to send it to the OCSP server. |
907 |
Most parts of this function are taken from mod_ssl support for OCSP (with some |
908 |
minor modifications |
909 |
*/ |
910 |
static BIO *serialize_request(OCSP_REQUEST *req, char *host, int port, char *path) |
911 |
{ |
912 |
BIO *bio; |
913 |
int len; |
914 |
|
915 |
len = i2d_OCSP_REQUEST(req, NULL); |
916 |
|
917 |
bio = BIO_new(BIO_s_mem()); |
918 |
|
919 |
BIO_printf(bio, "POST %s HTTP/1.0\r\n" |
920 |
"Host: %s:%d\r\n" |
921 |
"Content-Type: application/ocsp-request\r\n" |
922 |
"Content-Length: %d\r\n" |
923 |
"\r\n", |
924 |
path, host, port, len); |
925 |
|
926 |
if (i2d_OCSP_REQUEST_bio(bio, req) != 1) { |
927 |
BIO_free(bio); |
928 |
return NULL; |
929 |
} |
930 |
|
931 |
return bio; |
932 |
} |
933 |
|
934 |
|
935 |
/* Send the OCSP request to the OCSP server. Taken from mod_ssl OCSP support */ |
936 |
#define HUGE_STRING_LENGTH 8192 |
937 |
static int ocsp_send_req(apr_socket_t *sock, BIO *req) |
938 |
{ |
939 |
int len; |
940 |
char buf[HUGE_STRING_LENGTH]; |
941 |
apr_status_t rv; |
942 |
int ok = 1; |
943 |
|
944 |
while ((len = BIO_read(req, buf, sizeof buf)) > 0) { |
945 |
char *wbuf = buf; |
946 |
apr_size_t remain = len; |
947 |
|
948 |
do { |
949 |
apr_size_t wlen = remain; |
950 |
rv = apr_socket_send(sock, wbuf, &wlen); |
951 |
wbuf += remain; |
952 |
remain -= wlen; |
953 |
} while (rv == APR_SUCCESS && remain > 0); |
954 |
|
955 |
if (rv != APR_SUCCESS) { |
956 |
apr_socket_close(sock); |
957 |
ok = 0; |
958 |
} |
959 |
} |
960 |
|
961 |
return ok; |
962 |
} |
963 |
|
964 |
|
965 |
|
966 |
/* Parses the buffer from the response and extracts the OCSP response. |
967 |
Taken from openssl library */ |
968 |
static OCSP_RESPONSE *parse_ocsp_resp(char *buf, int len) |
969 |
{ |
970 |
BIO *mem = NULL; |
971 |
char tmpbuf[1024]; |
972 |
OCSP_RESPONSE *resp = NULL; |
973 |
char *p, *q, *r; |
974 |
int retcode; |
975 |
|
976 |
mem = BIO_new(BIO_s_mem()); |
977 |
if(mem == NULL) |
978 |
return NULL; |
979 |
|
980 |
BIO_write(mem, buf, len); /* write the buffer to the bio */ |
981 |
if(BIO_gets(mem, tmpbuf, 512) <= 0) { |
982 |
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); |
983 |
goto err; |
984 |
} |
985 |
/* Parse the HTTP response. This will look like this: |
986 |
* "HTTP/1.0 200 OK". We need to obtain the numeric code and |
987 |
* (optional) informational message. |
988 |
*/ |
989 |
|
990 |
/* Skip to first white space (passed protocol info) */ |
991 |
for(p = tmpbuf; *p && !isspace((unsigned char)*p); p++) continue; |
992 |
if(!*p) { |
993 |
goto err; |
994 |
} |
995 |
/* Skip past white space to start of response code */ |
996 |
while(isspace((unsigned char)*p)) p++; |
997 |
if(!*p) { |
998 |
goto err; |
999 |
} |
1000 |
/* Find end of response code: first whitespace after start of code */ |
1001 |
for(q = p; *q && !isspace((unsigned char)*q); q++) continue; |
1002 |
if(!*q) { |
1003 |
goto err; |
1004 |
} |
1005 |
/* Set end of response code and start of message */ |
1006 |
*q++ = 0; |
1007 |
/* Attempt to parse numeric code */ |
1008 |
retcode = strtoul(p, &r, 10); |
1009 |
if(*r) goto err; |
1010 |
/* Skip over any leading white space in message */ |
1011 |
while(isspace((unsigned char)*q)) q++; |
1012 |
if(*q) { |
1013 |
/* Finally zap any trailing white space in message (include CRLF) */ |
1014 |
/* We know q has a non white space character so this is OK */ |
1015 |
for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) *r = 0; |
1016 |
} |
1017 |
if(retcode != 200) { |
1018 |
goto err; |
1019 |
} |
1020 |
/* Find blank line marking beginning of content */ |
1021 |
while(BIO_gets(mem, tmpbuf, 512) > 0) |
1022 |
{ |
1023 |
for(p = tmpbuf; isspace((unsigned char)*p); p++) continue; |
1024 |
if(!*p) break; |
1025 |
} |
1026 |
if(*p) { |
1027 |
goto err; |
1028 |
} |
1029 |
if(!(resp = d2i_OCSP_RESPONSE_bio(mem, NULL))) { |
1030 |
goto err; |
1031 |
} |
1032 |
err: |
1033 |
BIO_free(mem); |
1034 |
return resp; |
1035 |
|
1036 |
|
1037 |
} |
1038 |
|
1039 |
|
1040 |
/* Reads the respnse from the APR socket to a buffer, and parses the buffer to |
1041 |
return the OCSP response */ |
1042 |
#define ADDLEN 512 |
1043 |
static OCSP_RESPONSE *ocsp_get_resp(apr_socket_t *sock) |
1044 |
{ |
1045 |
int buflen = 0, totalread = 0; |
1046 |
apr_size_t readlen; |
1047 |
char *buf, tmpbuf[ADDLEN]; |
1048 |
apr_status_t rv = APR_SUCCESS; |
1049 |
apr_pool_t *p; |
1050 |
|
1051 |
OCSP_RESPONSE *resp; |
1052 |
|
1053 |
apr_pool_create(&p, NULL); |
1054 |
|
1055 |
buflen = ADDLEN; |
1056 |
buf = apr_palloc(p, buflen); |
1057 |
if(buf == NULL) { |
1058 |
apr_pool_destroy(p); |
1059 |
return NULL; |
1060 |
} |
1061 |
|
1062 |
while(rv == APR_SUCCESS ) { |
1063 |
readlen = sizeof(tmpbuf); |
1064 |
rv = apr_socket_recv(sock, tmpbuf, &readlen); |
1065 |
if(rv == APR_SUCCESS) { /* if we have read something .. we can put it in the buffer*/ |
1066 |
if((totalread + readlen) >= buflen) { |
1067 |
buf = apr_xrealloc(buf,buflen,buflen+ADDLEN, p); |
1068 |
if (buf == NULL) { |
1069 |
apr_pool_destroy(p); |
1070 |
return NULL; |
1071 |
} |
1072 |
buflen+=ADDLEN; /* if needed we enlarge the buffer */ |
1073 |
} |
1074 |
memcpy(buf+totalread, tmpbuf, readlen); /* the copy to the buffer */ |
1075 |
totalread+=readlen; /* update the total bytes read */ |
1076 |
} |
1077 |
else { |
1078 |
if (rv == APR_EOF && readlen == 0 ) |
1079 |
; /* EOF, normal situation */ |
1080 |
else if ( readlen == 0 ) { |
1081 |
/* Not success, and readlen == 0 .. some error */ |
1082 |
apr_pool_destroy(p); |
1083 |
return NULL; |
1084 |
} |
1085 |
} |
1086 |
} |
1087 |
|
1088 |
|
1089 |
resp = parse_ocsp_resp(buf, buflen); |
1090 |
|
1091 |
apr_pool_destroy(p); |
1092 |
|
1093 |
return resp; |
1094 |
} |
1095 |
|
1096 |
/* Creates and OCSP request and returns the OCSP_RESPONSE */ |
1097 |
static OCSP_RESPONSE *get_ocsp_response(X509 *cert, X509 *issuer, char *url) |
1098 |
{ |
1099 |
OCSP_RESPONSE *ocsp_resp = NULL; |
1100 |
OCSP_REQUEST *ocsp_req = NULL; |
1101 |
BIO *bio_req; |
1102 |
char *hostname, *path, *c_port; |
1103 |
int port, use_ssl; |
1104 |
STACK_OF(OCSP_CERTID) *ids = NULL; |
1105 |
int ok = 0; |
1106 |
|
1107 |
apr_socket_t *apr_sock=NULL; |
1108 |
|
1109 |
apr_pool_t *mp; |
1110 |
|
1111 |
apr_pool_create(&mp, NULL); |
1112 |
|
1113 |
ids = sk_OCSP_CERTID_new_null(); |
1114 |
|
1115 |
/* problem parsing the URL */ |
1116 |
if(OCSP_parse_url(url,&hostname, &c_port, &path, &use_ssl) == 0 ) { |
1117 |
sk_OCSP_CERTID_free(ids); |
1118 |
return NULL; |
1119 |
} |
1120 |
|
1121 |
/* Create the OCSP request */ |
1122 |
if(sscanf(c_port, "%d", &port) != 1) |
1123 |
goto end; |
1124 |
ocsp_req = OCSP_REQUEST_new(); |
1125 |
if(ocsp_req == NULL) |
1126 |
return NULL; |
1127 |
if(add_ocsp_cert(&ocsp_req,cert,issuer,ids) == 0 ) |
1128 |
goto free_req; |
1129 |
|
1130 |
/* create the BIO with the request to send */ |
1131 |
bio_req = serialize_request(ocsp_req, hostname, port, path); |
1132 |
if(bio_req == NULL) { |
1133 |
goto free_req; |
1134 |
} |
1135 |
|
1136 |
apr_sock = make_socket(hostname, port, mp); |
1137 |
if (apr_sock == NULL) { |
1138 |
ocsp_resp = NULL; |
1139 |
goto free_bio; |
1140 |
} |
1141 |
|
1142 |
ok = ocsp_send_req(apr_sock, bio_req); |
1143 |
if(ok) |
1144 |
ocsp_resp = ocsp_get_resp(apr_sock); |
1145 |
|
1146 |
free_bio: |
1147 |
BIO_free(bio_req); |
1148 |
|
1149 |
free_req: |
1150 |
if(apr_sock && ok) /* if ok == 0 we have already closed the socket */ |
1151 |
apr_socket_close(apr_sock); |
1152 |
|
1153 |
apr_pool_destroy(mp); |
1154 |
|
1155 |
sk_OCSP_CERTID_free(ids); |
1156 |
OCSP_REQUEST_free(ocsp_req); |
1157 |
|
1158 |
end: |
1159 |
return ocsp_resp; |
1160 |
} |
1161 |
|
1162 |
/* Process the OCSP_RESPONSE and returns the corresponding |
1163 |
answert according to the status. |
1164 |
*/ |
1165 |
static int processOCSPResponse(OCSP_RESPONSE *ocsp_resp) |
1166 |
{ |
1167 |
int r, o = V_OCSP_CERTSTATUS_UNKNOWN, i; |
1168 |
OCSP_BASICRESP *bs; |
1169 |
OCSP_SINGLERESP *ss; |
1170 |
|
1171 |
r = OCSP_response_status(ocsp_resp); |
1172 |
|
1173 |
if(r != OCSP_RESPONSE_STATUS_SUCCESSFUL) { |
1174 |
OCSP_RESPONSE_free(ocsp_resp); |
1175 |
return OCSP_STATUS_UNKNOWN; |
1176 |
} |
1177 |
bs = OCSP_response_get1_basic(ocsp_resp); |
1178 |
|
1179 |
ss = OCSP_resp_get0(bs,0); /* we know we have only 1 request */ |
1180 |
|
1181 |
i = OCSP_single_get0_status(ss, NULL, NULL, NULL, NULL); |
1182 |
if ( i == V_OCSP_CERTSTATUS_GOOD ) |
1183 |
o = OCSP_STATUS_OK; |
1184 |
else if ( i == V_OCSP_CERTSTATUS_REVOKED ) |
1185 |
o = OCSP_STATUS_REVOKED; |
1186 |
else if ( i == V_OCSP_CERTSTATUS_UNKNOWN) |
1187 |
o = OCSP_STATUS_UNKNOWN; |
1188 |
|
1189 |
/* we clean up */ |
1190 |
OCSP_RESPONSE_free(ocsp_resp); |
1191 |
|
1192 |
return o; |
1193 |
} |
1194 |
|
1195 |
|
1196 |
int ocspRequest(X509 *cert, X509 *issuer) |
1197 |
{ |
1198 |
char **ocsp_urls = NULL; |
1199 |
int nid, i; |
1200 |
X509_EXTENSION *ext; |
1201 |
ASN1_OCTET_STRING *os; |
1202 |
|
1203 |
apr_pool_t *p; |
1204 |
|
1205 |
apr_pool_create(&p, NULL); |
1206 |
|
1207 |
/* Get the proper extension */ |
1208 |
nid = X509_get_ext_by_NID(cert,NID_info_access,-1); |
1209 |
if(nid >= 0 ) { |
1210 |
ext = X509_get_ext(cert,nid); |
1211 |
os = X509_EXTENSION_get_data(ext); |
1212 |
|
1213 |
ocsp_urls = decode_OCSP_url(os, p); |
1214 |
} |
1215 |
|
1216 |
/* if we find the extensions and we can parse it check |
1217 |
the ocsp status. Otherwise, return OCSP_STATUS_UNKNOWN */ |
1218 |
if(ocsp_urls != NULL) { |
1219 |
OCSP_RESPONSE *resp; |
1220 |
/* for the time being just check for the fist response .. a better |
1221 |
approach is to iterate for all the possible ocsp urls */ |
1222 |
resp = get_ocsp_response(cert, issuer, ocsp_urls[0]); |
1223 |
|
1224 |
apr_pool_destroy(p); |
1225 |
if(resp != NULL) |
1226 |
return processOCSPResponse(resp); |
1227 |
} |
1228 |
apr_pool_destroy(p); |
1229 |
return OCSP_STATUS_UNKNOWN; |
1230 |
} |
1231 |
|
1232 |
#endif /* HAVE_SSL_OCSP */ |
1233 |
|
675 |
#endif |
1234 |
#endif |