⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ocsp.c

📁 ipsec vpn
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Support of the Online Certificate Status Protocol (OCSP) * * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen *                    Zuercher Hochschule Winterthur * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * for more details. * */#include <unistd.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <openswan.h>#include <openswan/ipsec_policy.h>#include "constants.h"#include "defs.h"#include "id.h"#include "log.h"#include "x509.h"#include "rnd.h"#include "asn1.h"#include "pgp.h"#include "certs.h"#include "smartcard.h"#include "oid.h"#include "whack.h"#include "keys.h"#include "fetch.h"#include "ocsp.h"#define NONCE_LENGTH		16#define BUF_LEN			512#define constcpy(dst, str) \    { memcpy(dst, str, sizeof(str)); dst += sizeof(str);}static const char *const cert_status_names[] = {    "good",    "revoked",    "unknown",    "undefined"};static const char *const response_status_names[] = {    "successful",    "malformed request",    "internal error",    "try later",    "signature required",    "unauthorized"};/* response container */typedef struct response response_t;struct response {    chunk_t  tbs;    chunk_t  responder_id_name;    chunk_t  responder_id_key;    time_t   produced_at;    chunk_t  responses;    chunk_t  nonce;    int      algorithm;    chunk_t  signature;};const response_t empty_response = {    { NULL, 0 }   ,	/* tbs */    { NULL, 0 }   ,	/* responder_id_name */    { NULL, 0 }   ,	/* responder_id_key */    UNDEFINED_TIME,	/* produced_at */    { NULL, 0 }   ,	/* single_response */    { NULL, 0 }   ,	/* nonce */    OID_UNKNOWN   ,	/* signature_algorithm */    { NULL, 0 }		/* signature */};/* crl reasons */typedef enum {    REASON_UNSPECIFIED =		0,    REASON_KEYCOMPROMISE = 		1,    REASON_CACOMPROMISE = 		2,    REASON_AFFILIATIONCHANGED =		3,    REASON_SUPERSEEDED =		4,    REASON_CESSATIONOFOPERATION =	5,    REASON_CERTIFICATEHOLD =		6,    REASON_REMOVEFROMCRL =		8} crl_reason_t;/* single response container */typedef struct single_response single_response_t;struct single_response {    single_response_t *next;    int               hash_algorithm;    chunk_t           issuer_name_hash;    chunk_t           issuer_key_hash;    chunk_t           serialNumber;    cert_status_t     status;    time_t            revocation_time;    crl_reason_t      reason;    time_t            thisUpdate;    time_t            nextUpdate;};const single_response_t empty_single_response = {      NULL            ,	/* *next */    OID_UNKNOWN       ,	/* hash_algorithm */    { NULL, 0 }       ,	/* issuer_name_hash */    { NULL, 0 }       ,	/* issuer_key_hash */    { NULL, 0 }       ,	/* serial_number */    CERT_UNDEFINED    ,	/* status */    UNDEFINED_TIME    ,	/* revocation_time */    REASON_UNSPECIFIED,	/* reason */    UNDEFINED_TIME    ,	/* this_update */    UNDEFINED_TIME	/* next_update */};/* list of single requests */typedef struct request_list request_list_t;struct request_list {    chunk_t request;    request_list_t *next;};/* some prefabricated ASN.1 constants */const char ASN1_sha1_id[] = {    0x30, 0x09,	  0x06, 0x05, 0x2B, 0x0E,0x03, 0x02, 0x1A,	  0x05, 0x00};const char ASN1_sha1WithRSA_id[] = {    0x30, 0x0D,	  0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05,	  0x05, 0x00};const char ASN1_nonce_oid[] = {    0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02};const char ASN1_response_oid[] = {    0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04};const char ASN1_response_content[] = {    0x04, 0x0D,	  0x30, 0x0B,		0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01};/* default OCSP uri */static chunk_t ocsp_default_uri;/* ocsp cache: pointer to first element */static ocsp_location_t *ocsp_cache = NULL;/* static temporary storage for ocsp requestor information */static x509cert_t *ocsp_requestor_cert = NULL;static smartcard_t *ocsp_requestor_sc = NULL;static const struct RSA_private_key *ocsp_requestor_pri = NULL;/* asn.1 definitions for parsing */static const asn1Object_t ocspResponseObjects[] = {  { 0, "OCSPResponse",                  ASN1_SEQUENCE,     ASN1_NONE }, /*  0 */  { 1,   "responseStatus",              ASN1_ENUMERATED,   ASN1_BODY }, /*  1 */  { 1,   "responseBytesContext",        ASN1_CONTEXT_C_0,  ASN1_OPT  }, /*  2 */  { 2,     "responseBytes",             ASN1_SEQUENCE,     ASN1_NONE }, /*  3 */  { 3,       "responseType",            ASN1_OID,          ASN1_BODY }, /*  4 */  { 3,       "response",                ASN1_OCTET_STRING, ASN1_BODY }, /*  5 */  { 1,   "end opt",                     ASN1_EOC,          ASN1_END  }  /*  6 */};#define OCSP_RESPONSE_STATUS	1#define OCSP_RESPONSE_TYPE	4#define OCSP_RESPONSE		5#define OCSP_RESPONSE_ROOF	7static const asn1Object_t basicResponseObjects[] = {  { 0, "BasicOCSPResponse",             ASN1_SEQUENCE,        ASN1_NONE }, /*  0 */  { 1,   "tbsResponseData",             ASN1_SEQUENCE,        ASN1_OBJ  }, /*  1 */  { 2,     "versionContext",            ASN1_CONTEXT_C_0,     ASN1_NONE |							      ASN1_DEF  }, /*  2 */  { 3,       "version",                 ASN1_INTEGER,         ASN1_BODY }, /*  3 */  { 2,     "responderIdContext",        ASN1_CONTEXT_C_1,     ASN1_OPT  }, /*  4 */  { 3,       "responderIdByName",       ASN1_SEQUENCE,        ASN1_OBJ  }, /*  5 */  { 2,     "end choice",                ASN1_EOC,             ASN1_END  }, /*  6 */  { 2,     "responderIdContext",        ASN1_CONTEXT_C_2,     ASN1_OPT  }, /*  7 */  { 3,       "responderIdByKey",        ASN1_OCTET_STRING,    ASN1_BODY }, /*  8 */  { 2,     "end choice",                ASN1_EOC,             ASN1_END  }, /*  9 */  { 2,     "producedAt",                ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */  { 2,     "responses",                 ASN1_SEQUENCE,        ASN1_OBJ  }, /* 11 */  { 2,     "responseExtensionsContext", ASN1_CONTEXT_C_1,     ASN1_OPT  }, /* 12 */  { 3,       "responseExtensions",      ASN1_SEQUENCE,        ASN1_LOOP }, /* 13 */  { 4,         "extension",             ASN1_SEQUENCE,        ASN1_NONE }, /* 14 */  { 5,           "extnID",              ASN1_OID,             ASN1_BODY }, /* 15 */  { 5,           "critical",            ASN1_BOOLEAN,         ASN1_BODY |							      ASN1_DEF  }, /* 16 */  { 5,           "extnValue",           ASN1_OCTET_STRING,    ASN1_BODY }, /* 17 */  { 4,         "end loop",              ASN1_EOC,             ASN1_END  }, /* 18 */  { 2,     "end opt",                   ASN1_EOC,             ASN1_END  }, /* 19 */  { 1,   "signatureAlgorithm",          ASN1_EOC,             ASN1_RAW  }, /* 20 */  { 1,   "signature",                   ASN1_BIT_STRING,      ASN1_BODY }, /* 21 */  { 1,   "certsContext",                ASN1_CONTEXT_C_0,     ASN1_OPT  }, /* 22 */  { 2,     "certs",                     ASN1_SEQUENCE,        ASN1_LOOP }, /* 23 */  { 3,       "certificate",             ASN1_SEQUENCE,        ASN1_OBJ  }, /* 24 */  { 2,     "end loop",                  ASN1_EOC,	      ASN1_END  }, /* 25 */  { 1,   "end opt",                     ASN1_EOC,             ASN1_END  }  /* 26 */};#define BASIC_RESPONSE_TBS_DATA		 1#define BASIC_RESPONSE_VERSION		 3#define BASIC_RESPONSE_ID_BY_NAME	 5#define BASIC_RESPONSE_ID_BY_KEY	 8#define BASIC_RESPONSE_PRODUCED_AT	10#define BASIC_RESPONSE_RESPONSES	11#define BASIC_RESPONSE_EXT_ID		15#define BASIC_RESPONSE_CRITICAL		16#define BASIC_RESPONSE_EXT_VALUE	17#define BASIC_RESPONSE_ALGORITHM	20#define BASIC_RESPONSE_SIGNATURE	21#define BASIC_RESPONSE_CERTIFICATE	24#define BASIC_RESPONSE_ROOF		27static const asn1Object_t responsesObjects[] = {  { 0, "responses",                   ASN1_SEQUENCE,          ASN1_LOOP }, /*  0 */  { 1,   "singleResponse",            ASN1_EOC,               ASN1_RAW  }, /*  1 */  { 0, "end loop",                    ASN1_EOC,               ASN1_END  }  /*  2 */};#define RESPONSES_SINGLE_RESPONSE	 1#define RESPONSES_ROOF			 3static const asn1Object_t singleResponseObjects[] = {  { 0, "singleResponse",            ASN1_SEQUENCE,          ASN1_BODY }, /*  0 */  { 1,   "certID",                  ASN1_SEQUENCE,          ASN1_NONE }, /*  1 */  { 2,     "algorithm",             ASN1_EOC,               ASN1_RAW  }, /*  2 */  { 2,     "issuerNameHash",        ASN1_OCTET_STRING,      ASN1_BODY }, /*  3 */  { 2,     "issuerKeyHash",         ASN1_OCTET_STRING,      ASN1_BODY }, /*  4 */  { 2,     "serialNumber",          ASN1_INTEGER,           ASN1_BODY }, /*  5 */  { 1,   "certStatusGood",          ASN1_CONTEXT_S_0,       ASN1_OPT  }, /*  6 */  { 1,   "end opt",                 ASN1_EOC,               ASN1_END  }, /*  7 */  { 1,   "certStatusRevoked",       ASN1_CONTEXT_C_1,       ASN1_OPT  }, /*  8 */  { 2,     "revocationTime",        ASN1_GENERALIZEDTIME,   ASN1_BODY }, /*  9 */  { 2,     "revocationReason",      ASN1_CONTEXT_C_0,       ASN1_OPT  }, /* 10 */  { 3,       "crlReason",           ASN1_ENUMERATED,        ASN1_BODY }, /* 11 */  { 2,     "end opt",               ASN1_EOC,               ASN1_END  }, /* 12 */  { 1,   "end opt",                 ASN1_EOC,               ASN1_END  }, /* 13 */  { 1,   "certStatusUnknown",       ASN1_CONTEXT_S_2,       ASN1_OPT  }, /* 14 */  { 1,   "end opt",                 ASN1_EOC,               ASN1_END  }, /* 15 */  { 1,   "thisUpdate",              ASN1_GENERALIZEDTIME,   ASN1_BODY }, /* 16 */  { 1,   "nextUpdateContext",       ASN1_CONTEXT_C_0,       ASN1_OPT  }, /* 17 */  { 2,     "nextUpdate",            ASN1_GENERALIZEDTIME,   ASN1_BODY }, /* 18 */  { 1,   "end opt",                 ASN1_EOC,               ASN1_END  }, /* 19 */  { 1,   "singleExtensionsContext", ASN1_CONTEXT_C_1,       ASN1_OPT  }, /* 20 */  { 2,     "singleExtensions",      ASN1_SEQUENCE,          ASN1_LOOP }, /* 21 */  { 3,       "extension",           ASN1_SEQUENCE,          ASN1_NONE }, /* 22 */  { 4,         "extnID",            ASN1_OID,               ASN1_BODY }, /* 23 */  { 4,         "critical",          ASN1_BOOLEAN,           ASN1_BODY |							    ASN1_DEF  }, /* 24 */  { 4,         "extnValue",         ASN1_OCTET_STRING,      ASN1_BODY }, /* 25 */  { 2,     "end loop",              ASN1_EOC,               ASN1_END  }, /* 26 */  { 1,   "end opt",                 ASN1_EOC,               ASN1_END  }  /* 27 */};#define SINGLE_RESPONSE_ALGORITHM			 2#define SINGLE_RESPONSE_ISSUER_NAME_HASH		 3#define SINGLE_RESPONSE_ISSUER_KEY_HASH			 4#define SINGLE_RESPONSE_SERIAL_NUMBER			 5#define SINGLE_RESPONSE_CERT_STATUS_GOOD		 6#define SINGLE_RESPONSE_CERT_STATUS_REVOKED		 8#define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME	 9#define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON		11#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN		14#define SINGLE_RESPONSE_THIS_UPDATE			16#define SINGLE_RESPONSE_NEXT_UPDATE			18#define SINGLE_RESPONSE_EXT_ID				23#define SINGLE_RESPONSE_CRITICAL			24#define SINGLE_RESPONSE_EXT_VALUE			25#define SINGLE_RESPONSE_ROOF				28/* build an ocsp location from certificate information * without unsharing its contents */static boolbuild_ocsp_location(const x509cert_t *cert, ocsp_location_t *location){    static u_char digest[SHA1_DIGEST_SIZE];  /* temporary storage */    location->uri = (cert->accessLocation.ptr != NULL)	? cert->accessLocation : ocsp_default_uri;    /* abort if no ocsp location uri is defined */    if (location->uri.ptr == NULL) 	return FALSE;    setchunk(location->authNameID, digest, SHA1_DIGEST_SIZE);    compute_digest(cert->issuer, OID_SHA1, &location->authNameID);    location->next = NULL;    location->issuer = cert->issuer;    location->authKeyID = cert->authKeyID;    location->authKeySerialNumber = cert->authKeySerialNumber;        if (cert->authKeyID.ptr == NULL)     {	x509cert_t *authcert = get_authcert(cert->issuer		, cert->authKeySerialNumber, cert->authKeyID, AUTH_CA);	if (authcert != NULL)	{	    location->authKeyID = authcert->subjectKeyID;	    location->authKeySerialNumber = authcert->serialNumber;	}    }    location->nonce = empty_chunk;    location->certinfo = NULL;    return TRUE;}/* * compare two ocsp locations for equality */static boolsame_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *b){    return ((a->authKeyID.ptr != NULL)		? same_keyid(a->authKeyID, b->authKeyID)		: (same_dn(a->issuer, b->issuer)		    && same_serial(a->authKeySerialNumber, b->authKeySerialNumber)))	    && same_chunk(a->uri, b->uri);}/* * find an existing ocsp location in a chained list */ocsp_location_t*get_ocsp_location(const ocsp_location_t * loc, ocsp_location_t *chain){    while (chain != NULL)    {	if (same_ocsp_location(loc, chain))	    return chain;	chain = chain->next;    }    return NULL;} /* retrieves the status of a cert from the ocsp cache * returns CERT_UNDEFINED if no status is found */static cert_status_tget_ocsp_status(const ocsp_location_t *loc, chunk_t serialNumber    ,time_t *nextUpdate){    ocsp_certinfo_t *certinfo, **certinfop;    int cmp = 0;    /* find location */    ocsp_location_t *location = get_ocsp_location(loc, ocsp_cache);    if (location == NULL)	return CERT_UNDEFINED;    /* traverse list of certinfos in increasing order */    certinfop = &location->certinfo;    certinfo = *certinfop;    while (certinfo != NULL)    {	cmp = cmp_chunk(serialNumber, certinfo->serialNumber);	if (cmp <= 0)	    break;	certinfop = &certinfo->next;	certinfo = *certinfop;    }    if (cmp == 0)    {	*nextUpdate = certinfo->nextUpdate;	return certinfo->status;    }    return CERT_UNDEFINED;}/* * verify the ocsp status of a certificate */boolverify_by_ocsp(/*const*/ x509cert_t *cert, bool strict, time_t *until){    u_char status;    ocsp_location_t location;    time_t nextUpdate = 0;    /* is an ocsp location defined? */    if (!build_ocsp_location(cert, &location))	return FALSE;    lock_ocsp_cache("verify_by_ocsp");    status = get_ocsp_status(&location, cert->serialNumber, &nextUpdate);    unlock_ocsp_cache("verify_by_ocsp");#ifdef HAVE_THREADS    if (status == CERT_UNDEFINED || nextUpdate < time(NULL))    {	openswan_log("ocsp status is stale or not in cache");	add_ocsp_fetch_request(&location, cert->serialNumber);	/* inititate fetching of ocsp status */	wake_fetch_thread("verify_by_ocsp");	return !strict;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -