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 *xrealloc(void *buf, size_t len) |
748 |
{ |
749 |
void *newp; |
750 |
if((newp = realloc(buf, len)) == NULL) { |
751 |
free(buf); |
752 |
return NULL; |
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) |
760 |
{ |
761 |
char **new_ocsp_urls, *ocsp_url; |
762 |
int len, err = 0, new_nocsp_urls; |
763 |
if(*asn1 == ASN1_STRING) { |
764 |
len = *++asn1; |
765 |
asn1++; |
766 |
new_nocsp_urls = *nocsp_urls+1; |
767 |
if((new_ocsp_urls = realloc(*ocsp_urls,new_nocsp_urls)) == NULL) |
768 |
err = 1; |
769 |
if(!err) { |
770 |
*ocsp_urls = new_ocsp_urls; |
771 |
*nocsp_urls = new_nocsp_urls; |
772 |
*(*ocsp_urls + *nocsp_urls) = NULL; |
773 |
if((ocsp_url = malloc((len+1)*sizeof(char))) == NULL) |
774 |
err = 1; |
775 |
else { |
776 |
memcpy(ocsp_url, asn1, len); |
777 |
*(ocsp_url+len) = '\0'; |
778 |
*(*ocsp_urls + *nocsp_urls -1 ) = ocsp_url; |
779 |
} |
780 |
} |
781 |
} |
782 |
return err; |
783 |
|
784 |
} |
785 |
|
786 |
/* parses the ANS1 OID and if it is an OCSP OID then calls the parse_ocsp_url function */ |
787 |
static int parse_ASN1_OID(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls) |
788 |
{ |
789 |
int len, err = 0 ; |
790 |
const unsigned char OCSP_OID[] = {0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01}; |
791 |
|
792 |
len = *++asn1; |
793 |
asn1++; |
794 |
if(memcmp(asn1, OCSP_OID, len) == 0 ) { |
795 |
asn1+=len; |
796 |
err = parse_ocsp_url(asn1, ocsp_urls, nocsp_urls); |
797 |
} |
798 |
return err; |
799 |
} |
800 |
|
801 |
|
802 |
/* Parses an ASN1 Sequence. It is a recursive function, since if it finds a sequence |
803 |
within the sequence it calls recursively itself. This function stops when it finds |
804 |
the end of the ASN1 sequence (marked by '\0'), so if there are other sequences within |
805 |
the same sequence the while loop parses the sequences */ |
806 |
|
807 |
/* This algo was developped with AIA in mind so it was tested only with this extension */ |
808 |
static int parse_ASN1_Sequence(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls) |
809 |
{ |
810 |
int len = 0 , err = 0; |
811 |
while( !err && *asn1 != '\0') { |
812 |
switch(*asn1) { |
813 |
case ASN1_SEQUENCE: |
814 |
len = *++asn1; |
815 |
asn1++; |
816 |
err = parse_ASN1_Sequence(asn1, ocsp_urls, nocsp_urls); |
817 |
break; |
818 |
case ASN1_OID: |
819 |
err = parse_ASN1_OID(asn1,ocsp_urls,nocsp_urls); |
820 |
return 0; |
821 |
break; |
822 |
default: |
823 |
err = 1; /* we shouldn't have any errors */ |
824 |
break; |
825 |
} |
826 |
asn1+=len; |
827 |
} |
828 |
return err; |
829 |
} |
830 |
|
831 |
/* the main function that gets the ASN1 encoding string and returns |
832 |
a pointer to a NULL terminated "array" of char *, that contains |
833 |
the ocsp_urls */ |
834 |
static char **decode_OCSP_url(ASN1_OCTET_STRING *os) |
835 |
{ |
836 |
char **response = NULL; |
837 |
unsigned char *ocsp_urls; |
838 |
int i, len, err = 0, numofresponses = 0 ; |
839 |
|
840 |
len = ASN1_STRING_length(os); |
841 |
|
842 |
ocsp_urls = malloc((size_t)(len+1)*sizeof(char)); |
843 |
memcpy(ocsp_urls,os->data, (size_t) len); |
844 |
ocsp_urls[len] = '\0'; |
845 |
|
846 |
if ((response = malloc(sizeof(char *))) == NULL) |
847 |
return NULL; |
848 |
*response = NULL; |
849 |
|
850 |
err = parse_ASN1_Sequence(ocsp_urls, &response, &numofresponses); |
851 |
if (err) { |
852 |
for(i = 0 ; i < numofresponses ; i++) |
853 |
free(response[i]); |
854 |
free(response); |
855 |
response = NULL; |
856 |
} |
857 |
|
858 |
free(ocsp_urls); |
859 |
return response; |
860 |
} |
861 |
|
862 |
|
863 |
|
864 |
/* stolen from openssl ocsp command */ |
865 |
static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer, |
866 |
STACK_OF(OCSP_CERTID) *ids) |
867 |
{ |
868 |
OCSP_CERTID *id; |
869 |
if(!issuer) |
870 |
return 0; |
871 |
if(!*req) *req = OCSP_REQUEST_new(); |
872 |
if(!*req) goto err; |
873 |
id = OCSP_cert_to_id(NULL, cert, issuer); |
874 |
if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err; |
875 |
if(!OCSP_request_add0_id(*req, id)) goto err; |
876 |
return 1; |
877 |
|
878 |
err: |
879 |
return 0; |
880 |
} |
881 |
|
882 |
|
883 |
/* Creates the APR socket and connect to the hostname. Returns the |
884 |
socket or NULL if there is an error. |
885 |
*/ |
886 |
static apr_socket_t *make_socket(char *hostname, int port, apr_pool_t *mp) |
887 |
{ |
888 |
int r = 0; |
889 |
apr_sockaddr_t *sa_in; |
890 |
apr_status_t status; |
891 |
apr_socket_t *sock = NULL; |
892 |
|
893 |
|
894 |
status = apr_sockaddr_info_get(&sa_in, hostname, APR_INET, port, 0, mp); |
895 |
|
896 |
if(status == APR_SUCCESS) |
897 |
status = apr_socket_create(&sock, sa_in->family, SOCK_STREAM, APR_PROTO_TCP, mp); |
898 |
if(status == APR_SUCCESS) |
899 |
status = apr_socket_connect(sock, sa_in); |
900 |
|
901 |
if(status == APR_SUCCESS) |
902 |
return sock; |
903 |
return NULL; |
904 |
|
905 |
} |
906 |
|
907 |
|
908 |
/* Creates the request in a memory BIO in order to send it to the OCSP server. |
909 |
Most parts of this function are taken from mod_ssl support for OCSP (with some |
910 |
minor modifications |
911 |
*/ |
912 |
static BIO *serialize_request(OCSP_REQUEST *req, char *host, int port, char *path) |
913 |
{ |
914 |
BIO *bio; |
915 |
int len; |
916 |
|
917 |
len = i2d_OCSP_REQUEST(req, NULL); |
918 |
|
919 |
bio = BIO_new(BIO_s_mem()); |
920 |
|
921 |
BIO_printf(bio, "POST %s HTTP/1.0\r\n" |
922 |
"Host: %s:%d\r\n" |
923 |
"Content-Type: application/ocsp-request\r\n" |
924 |
"Content-Length: %d\r\n" |
925 |
"\r\n", |
926 |
path, host, port, len); |
927 |
|
928 |
if (i2d_OCSP_REQUEST_bio(bio, req) != 1) { |
929 |
BIO_free(bio); |
930 |
return NULL; |
931 |
} |
932 |
|
933 |
return bio; |
934 |
} |
935 |
|
936 |
|
937 |
/* Send the OCSP request to the OCSP server. Taken from mod_ssl OCSP support */ |
938 |
#define HUGE_STRING_LENGTH 8192 |
939 |
static int ocsp_send_req(apr_socket_t *sock, BIO *req) |
940 |
{ |
941 |
int len; |
942 |
char buf[HUGE_STRING_LENGTH]; |
943 |
apr_status_t rv; |
944 |
int ok = 1; |
945 |
|
946 |
while ((len = BIO_read(req, buf, sizeof buf)) > 0) { |
947 |
char *wbuf = buf; |
948 |
apr_size_t remain = len; |
949 |
|
950 |
do { |
951 |
apr_size_t wlen = remain; |
952 |
rv = apr_socket_send(sock, wbuf, &wlen); |
953 |
wbuf += remain; |
954 |
remain -= wlen; |
955 |
} while (rv == APR_SUCCESS && remain > 0); |
956 |
|
957 |
if (rv != APR_SUCCESS) { |
958 |
apr_socket_close(sock); |
959 |
ok = 0; |
960 |
} |
961 |
} |
962 |
|
963 |
return ok; |
964 |
} |
965 |
|
966 |
|
967 |
|
968 |
/* Parses the buffer from the response and extracts the OCSP response. |
969 |
Taken from openssl library */ |
970 |
static OCSP_RESPONSE *parse_ocsp_resp(char *buf, int len) |
971 |
{ |
972 |
BIO *mem = NULL; |
973 |
char tmpbuf[1024]; |
974 |
OCSP_RESPONSE *resp = NULL; |
975 |
char *p, *q, *r; |
976 |
int retcode; |
977 |
|
978 |
mem = BIO_new(BIO_s_mem()); |
979 |
if(mem == NULL) |
980 |
return NULL; |
981 |
|
982 |
BIO_write(mem, buf, len); /* write the buffer to the bio */ |
983 |
if(BIO_gets(mem, tmpbuf, 512) <= 0) { |
984 |
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); |
985 |
goto err; |
986 |
} |
987 |
/* Parse the HTTP response. This will look like this: |
988 |
* "HTTP/1.0 200 OK". We need to obtain the numeric code and |
989 |
* (optional) informational message. |
990 |
*/ |
991 |
|
992 |
/* Skip to first white space (passed protocol info) */ |
993 |
for(p = tmpbuf; *p && !isspace((unsigned char)*p); p++) continue; |
994 |
if(!*p) { |
995 |
goto err; |
996 |
} |
997 |
/* Skip past white space to start of response code */ |
998 |
while(isspace((unsigned char)*p)) p++; |
999 |
if(!*p) { |
1000 |
goto err; |
1001 |
} |
1002 |
/* Find end of response code: first whitespace after start of code */ |
1003 |
for(q = p; *q && !isspace((unsigned char)*q); q++) continue; |
1004 |
if(!*q) { |
1005 |
goto err; |
1006 |
} |
1007 |
/* Set end of response code and start of message */ |
1008 |
*q++ = 0; |
1009 |
/* Attempt to parse numeric code */ |
1010 |
retcode = strtoul(p, &r, 10); |
1011 |
if(*r) goto err; |
1012 |
/* Skip over any leading white space in message */ |
1013 |
while(isspace((unsigned char)*q)) q++; |
1014 |
if(*q) { |
1015 |
/* Finally zap any trailing white space in message (include CRLF) */ |
1016 |
/* We know q has a non white space character so this is OK */ |
1017 |
for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) *r = 0; |
1018 |
} |
1019 |
if(retcode != 200) { |
1020 |
goto err; |
1021 |
} |
1022 |
/* Find blank line marking beginning of content */ |
1023 |
while(BIO_gets(mem, tmpbuf, 512) > 0) |
1024 |
{ |
1025 |
for(p = tmpbuf; isspace((unsigned char)*p); p++) continue; |
1026 |
if(!*p) break; |
1027 |
} |
1028 |
if(*p) { |
1029 |
goto err; |
1030 |
} |
1031 |
if(!(resp = d2i_OCSP_RESPONSE_bio(mem, NULL))) { |
1032 |
goto err; |
1033 |
} |
1034 |
err: |
1035 |
BIO_free(mem); |
1036 |
return resp; |
1037 |
|
1038 |
|
1039 |
} |
1040 |
|
1041 |
|
1042 |
/* Reads the respnse from the APR socket to a buffer, and parses the buffer to |
1043 |
return the OCSP response */ |
1044 |
#define ADDLEN 512 |
1045 |
static OCSP_RESPONSE *ocsp_get_resp(apr_socket_t *sock) |
1046 |
{ |
1047 |
int buflen = 0, totalread = 0; |
1048 |
apr_size_t readlen; |
1049 |
char *buf, tmpbuf[ADDLEN]; |
1050 |
apr_status_t rv = APR_SUCCESS; |
1051 |
|
1052 |
OCSP_RESPONSE *resp; |
1053 |
|
1054 |
buflen = ADDLEN; |
1055 |
buf = malloc(buflen); |
1056 |
if(buf == NULL) |
1057 |
return NULL; |
1058 |
|
1059 |
while(rv == APR_SUCCESS ) { |
1060 |
readlen = sizeof(tmpbuf); |
1061 |
rv = apr_socket_recv(sock, tmpbuf, &readlen); |
1062 |
if(rv == APR_SUCCESS) { /* if we have read something .. we can put it in the buffer*/ |
1063 |
if((totalread + readlen) >= buflen) { |
1064 |
buflen+=ADDLEN; /* if needed we enlarge the buffer */ |
1065 |
buf = xrealloc(buf,buflen); |
1066 |
if (buf == NULL) { |
1067 |
return NULL; |
1068 |
} |
1069 |
} |
1070 |
memcpy(buf+totalread, tmpbuf, readlen); /* the copy to the buffer */ |
1071 |
totalread+=readlen; /* update the total bytes read */ |
1072 |
} |
1073 |
else { |
1074 |
if (rv == APR_EOF && readlen == 0 ) |
1075 |
; /* EOF, normal situation */ |
1076 |
else if ( readlen == 0 ) { |
1077 |
/* Not success, and readlen == 0 .. some error */ |
1078 |
free(buf); |
1079 |
return NULL; |
1080 |
} |
1081 |
} |
1082 |
} |
1083 |
|
1084 |
|
1085 |
resp = parse_ocsp_resp(buf, buflen); |
1086 |
|
1087 |
free(buf); |
1088 |
|
1089 |
return resp; |
1090 |
} |
1091 |
|
1092 |
/* Creates and OCSP request and returns the OCSP_RESPONSE */ |
1093 |
static OCSP_RESPONSE *get_ocsp_response(X509 *cert, X509 *issuer, char *url) |
1094 |
{ |
1095 |
OCSP_RESPONSE *ocsp_resp = NULL; |
1096 |
OCSP_REQUEST *ocsp_req = NULL; |
1097 |
BIO *bio_req; |
1098 |
char *hostname, *path, *c_port; |
1099 |
int port, use_ssl; |
1100 |
STACK_OF(OCSP_CERTID) *ids = NULL; |
1101 |
int ok = 0; |
1102 |
|
1103 |
apr_socket_t *apr_sock=NULL; |
1104 |
|
1105 |
apr_pool_t *mp; |
1106 |
|
1107 |
apr_pool_create(&mp, NULL); |
1108 |
|
1109 |
ids = sk_OCSP_CERTID_new_null(); |
1110 |
|
1111 |
/* problem parsing the URL */ |
1112 |
if(OCSP_parse_url(url,&hostname, &c_port, &path, &use_ssl) == 0 ) { |
1113 |
sk_OCSP_CERTID_free(ids); |
1114 |
return NULL; |
1115 |
} |
1116 |
|
1117 |
/* Create the OCSP request */ |
1118 |
if(sscanf(c_port, "%d", &port) != 1) |
1119 |
goto end; |
1120 |
ocsp_req = OCSP_REQUEST_new(); |
1121 |
if(ocsp_req == NULL) |
1122 |
return NULL; |
1123 |
if(add_ocsp_cert(&ocsp_req,cert,issuer,ids) == 0 ) |
1124 |
goto free_req; |
1125 |
|
1126 |
/* create the BIO with the request to send */ |
1127 |
bio_req = serialize_request(ocsp_req, hostname, port, path); |
1128 |
if(bio_req == NULL) { |
1129 |
goto free_req; |
1130 |
} |
1131 |
|
1132 |
apr_sock = make_socket(hostname, port, mp); |
1133 |
if (apr_sock == NULL) { |
1134 |
ocsp_resp = NULL; |
1135 |
goto free_bio; |
1136 |
} |
1137 |
|
1138 |
ok = ocsp_send_req(apr_sock, bio_req); |
1139 |
if(ok) |
1140 |
ocsp_resp = ocsp_get_resp(apr_sock); |
1141 |
|
1142 |
free_bio: |
1143 |
BIO_free(bio_req); |
1144 |
|
1145 |
free_req: |
1146 |
if(apr_sock && ok) /* if ok == 0 we have already closed the socket */ |
1147 |
apr_socket_close(apr_sock); |
1148 |
|
1149 |
apr_pool_destroy(mp); |
1150 |
|
1151 |
sk_OCSP_CERTID_free(ids); |
1152 |
OCSP_REQUEST_free(ocsp_req); |
1153 |
|
1154 |
end: |
1155 |
return ocsp_resp; |
1156 |
} |
1157 |
|
1158 |
/* Process the OCSP_RESPONSE and returns the corresponding |
1159 |
answert according to the status. |
1160 |
*/ |
1161 |
static int processOCSPResponse(OCSP_RESPONSE *ocsp_resp) |
1162 |
{ |
1163 |
int r, o = V_OCSP_CERTSTATUS_UNKNOWN, i; |
1164 |
OCSP_BASICRESP *bs; |
1165 |
OCSP_SINGLERESP *ss; |
1166 |
|
1167 |
r = OCSP_response_status(ocsp_resp); |
1168 |
|
1169 |
if(r != OCSP_RESPONSE_STATUS_SUCCESSFUL) { |
1170 |
OCSP_RESPONSE_free(ocsp_resp); |
1171 |
return OCSP_STATUS_UNKNOWN; |
1172 |
} |
1173 |
bs = OCSP_response_get1_basic(ocsp_resp); |
1174 |
|
1175 |
ss = OCSP_resp_get0(bs,0); /* we know we have only 1 request */ |
1176 |
|
1177 |
i = OCSP_single_get0_status(ss, NULL, NULL, NULL, NULL); |
1178 |
if ( i == V_OCSP_CERTSTATUS_GOOD ) |
1179 |
o = OCSP_STATUS_OK; |
1180 |
else if ( i == V_OCSP_CERTSTATUS_REVOKED ) |
1181 |
o = OCSP_STATUS_REVOKED; |
1182 |
else if ( i == V_OCSP_CERTSTATUS_UNKNOWN) |
1183 |
o = OCSP_STATUS_UNKNOWN; |
1184 |
|
1185 |
/* we clean up */ |
1186 |
OCSP_RESPONSE_free(ocsp_resp); |
1187 |
|
1188 |
return o; |
1189 |
} |
1190 |
|
1191 |
|
1192 |
int ocspRequest(X509 *cert, X509 *issuer) |
1193 |
{ |
1194 |
char **ocsp_urls = NULL; |
1195 |
int nid, i; |
1196 |
X509_EXTENSION *ext; |
1197 |
ASN1_OCTET_STRING *os; |
1198 |
|
1199 |
/* Get the proper extension */ |
1200 |
nid = X509_get_ext_by_NID(cert,NID_info_access,-1); |
1201 |
if(nid >= 0 ) { |
1202 |
ext = X509_get_ext(cert,nid); |
1203 |
os = X509_EXTENSION_get_data(ext); |
1204 |
|
1205 |
ocsp_urls = decode_OCSP_url(os); |
1206 |
} |
1207 |
|
1208 |
/* if we find the extensions and we can parse it check |
1209 |
the ocsp status. Otherwise, return OCSP_STATUS_UNKNOWN */ |
1210 |
if(ocsp_urls != NULL) { |
1211 |
OCSP_RESPONSE *resp; |
1212 |
/* for the time being just check for the fist response .. a better |
1213 |
approach is to iterate for all the possible ocsp urls */ |
1214 |
resp = get_ocsp_response(cert, issuer, ocsp_urls[0]); |
1215 |
|
1216 |
/* memory clean up */ |
1217 |
for(i = 0 ; ocsp_urls[i] != NULL ; i++ ) |
1218 |
free(ocsp_urls[i]); |
1219 |
free(ocsp_urls); |
1220 |
if(resp != NULL) |
1221 |
return processOCSPResponse(resp); |
1222 |
} |
1223 |
return OCSP_STATUS_UNKNOWN; |
1224 |
} |
1225 |
|
1226 |
#endif /* HAVE_SSL_OCSP */ |
1227 |
|
675 |
#endif |
1228 |
#endif |