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

📄 x509.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
    while (*pp != NULL)    {	x509cert_t *cert = *pp;	if (cert->isCA)	{	    *pp = cert->next;	    	    /* we don't accept self-signed CA certs */	    if (same_dn(cert->issuer, cert->subject))	    {		openswan_log("self-signed cacert rejected");		free_x509cert(cert);	    }	    else	    {                /* insertion into temporary chain of candidate CA certs */                cert->next = cacerts;                cacerts = cert;	    }	}	else	    pp = &cert->next;    }    /* now verify the candidate CA certs */        while (cacerts != NULL)    {        x509cert_t *cert = cacerts;               cacerts = cacerts->next;        if (trust_authcert_candidate(cert, cacerts))        {           add_authcert(cert, AUTH_CA);        }        else        {           plog("intermediate cacert rejected");           free_x509cert(cert);        }    }        /* now verify the end certificates */    pp = firstcert;    while (*pp != NULL)    {	time_t valid_until;	x509cert_t *cert = *pp;	if (verify_x509cert(cert, strict, &valid_until))	{	    DBG(DBG_X509 | DBG_PARSING,		DBG_log("public key validated")	    )	    add_x509_public_key(cert, valid_until, DAL_SIGNED);	}	else	{	    openswan_log("X.509 certificate rejected");	}	*pp = cert->next;	free_x509cert(cert);    }}/* *  compute a digest over a binary blob */boolcompute_digest(chunk_t tbs, int alg, chunk_t *digest){    switch (alg)    {	case OID_MD2:	case OID_MD2_WITH_RSA:	{	    MD2_CTX context;	    MD2Init(&context);	    MD2Update(&context, tbs.ptr, tbs.len);	    MD2Final(digest->ptr, &context);	    digest->len = MD2_DIGEST_SIZE;	    return TRUE;	}	case OID_MD5:	case OID_MD5_WITH_RSA:	{	    MD5_CTX context;	    osMD5Init(&context);	    osMD5Update(&context, tbs.ptr, tbs.len);	    osMD5Final(digest->ptr, &context);	    digest->len = MD5_DIGEST_SIZE;	    return TRUE;	}	case OID_SHA1:	case OID_SHA1_WITH_RSA:	case OID_SHA1_WITH_RSA_OIW:	{	    SHA1_CTX context;	    SHA1Init(&context);	    SHA1Update(&context, tbs.ptr, tbs.len);	    SHA1Final(digest->ptr, &context);	    digest->len = SHA1_DIGEST_SIZE;	    return TRUE;	}	default:	    digest->len = 0;	    return FALSE;    }}/* *  decrypts an RSA signature using the issuer's certificate */static booldecrypt_sig(chunk_t sig, int alg, const x509cert_t *issuer_cert,	    chunk_t *digest){    switch (alg)    {	chunk_t decrypted;	case OID_RSA_ENCRYPTION:	case OID_MD2_WITH_RSA:	case OID_MD5_WITH_RSA:	case OID_SHA1_WITH_RSA:	case OID_SHA1_WITH_RSA_OIW:	case OID_SHA256_WITH_RSA:	case OID_SHA384_WITH_RSA:	case OID_SHA512_WITH_RSA:	{	    mpz_t s;	    mpz_t e;	    mpz_t n;	    n_to_mpz(s, sig.ptr, sig.len);	    n_to_mpz(e, issuer_cert->publicExponent.ptr,			issuer_cert->publicExponent.len);	    n_to_mpz(n, issuer_cert->modulus.ptr,			issuer_cert->modulus.len);	    /* decrypt the signature s = s^e mod n */	    mpz_powm(s, s, e, n);	    /* convert back to bytes */	    decrypted = mpz_to_n(s, issuer_cert->modulus.len);	    DBG(DBG_PARSING,		DBG_dump_chunk("  decrypted signature: ", decrypted)	    )	    /*  copy the least significant bits of decrypted signature	     *  into the digest string	    */	    memcpy(digest->ptr, decrypted.ptr + decrypted.len - digest->len,		   digest->len);	    /* free memory */	    pfree(decrypted.ptr);	    mpz_clear(s);	    mpz_clear(e);	    mpz_clear(n);	    return TRUE;	}	default:	    digest->len = 0;	    return FALSE;    }}/* *   Check if a signature over binary blob is genuine */boolcheck_signature(chunk_t tbs, chunk_t sig, int algorithm,		const x509cert_t *issuer_cert){    u_char digest_buf[MAX_DIGEST_LEN];    u_char decrypted_buf[MAX_DIGEST_LEN];    chunk_t digest = {digest_buf, MAX_DIGEST_LEN};    chunk_t decrypted = {decrypted_buf, MAX_DIGEST_LEN};    if (algorithm != OID_UNKNOWN)    {	DBG(DBG_X509 | DBG_PARSING,	    DBG_log("signature algorithm: '%s'",oid_names[algorithm].name);	)    }    else    {	DBG(DBG_X509 | DBG_PARSING,	    DBG_log("unknown signature algorithm");	)    }    if (!compute_digest(tbs, algorithm, &digest))    {	openswan_log("  digest algorithm not supported");	return FALSE;    }    DBG(DBG_PARSING,	DBG_dump_chunk("  digest:", digest)    )    decrypted.len = digest.len; /* we want the same digest length */    if (!decrypt_sig(sig, algorithm, issuer_cert, &decrypted))    {    	openswan_log("  decryption algorithm not supported");	return FALSE;    }    /* check if digests are equal */    return !memcmp(decrypted.ptr, digest.ptr, digest.len);}/* * Insert X.509 CRL into chained list */boolinsert_crl(chunk_t blob, chunk_t crl_uri){    x509crl_t *crl = alloc_thing(x509crl_t, "x509crl");    *crl = empty_x509crl;    if (parse_x509crl(blob, 0, crl))    {	x509cert_t *issuer_cert;	x509crl_t *oldcrl;	bool valid_sig;	generalName_t *gn;	/* add distribution point */	gn = alloc_thing(generalName_t, "generalName");	gn->kind = GN_URI;	gn->name = crl_uri;	gn->next = crl->distributionPoints;	crl->distributionPoints = gn;	lock_authcert_list("insert_crl");	/* get the issuer cacert */	issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber,	    crl->authKeyID, AUTH_CA);	if (issuer_cert == NULL)	{	    char distpoint[PATH_MAX];	    strncpy(distpoint, crl->distributionPoints->name.ptr,		    (crl->distributionPoints->name.len < PATH_MAX ?		     crl->distributionPoints->name.len : PATH_MAX));	    	    openswan_log("crl issuer cacert not found for (%s)",			 distpoint);;	    free_crl(crl);	    unlock_authcert_list("insert_crl");	    return FALSE;	}	DBG(DBG_X509,	    DBG_log("crl issuer cacert found")	)	/* check the issuer's signature of the crl */	valid_sig = check_signature(crl->tbsCertList, crl->signature			, crl->algorithm, issuer_cert);	unlock_authcert_list("insert_crl");	if (!valid_sig)	{	    free_crl(crl);	    return FALSE;	}	DBG(DBG_X509,	    DBG_log("crl signature is valid")	)	lock_crl_list("insert_crl");	oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber	    , crl->authKeyID);	if (oldcrl != NULL)	{	    if (crl->thisUpdate > oldcrl->thisUpdate)	    {#ifdef HAVE_THREADS		/* keep any known CRL distribution points */		add_distribution_points(oldcrl->distributionPoints		    , &crl->distributionPoints);#endif		/* now delete the old CRL */		free_first_crl();		DBG(DBG_X509,		    DBG_log("thisUpdate is newer - existing crl deleted")		)	    }	    else	    {		unlock_crl_list("insert_crls");		DBG(DBG_X509,		    DBG_log("thisUpdate is not newer - existing crl not replaced");		)		free_crl(crl);		return oldcrl->nextUpdate - time(NULL) > 2*crl_check_interval;	    }	}	/* insert new CRL */	crl->next = x509crls;	x509crls = crl;	unlock_crl_list("insert_crl");	/* is the fetched crl valid? */	return crl->nextUpdate - time(NULL) > 2*crl_check_interval;    }    else    {	openswan_log("  error in X.509 crl");	free_crl(crl);	return FALSE;    }} /* *  Loads CRLs */voidload_crls(void){    struct dirent **filelist;    u_char buf[BUF_LEN];    u_char *save_dir;    int n;    /* change directory to specified path */    save_dir = getcwd(buf, BUF_LEN);    if (chdir(CRL_PATH))    {	openswan_log("Could not change to directory '%s'", CRL_PATH);    }    else    {	openswan_log("Changing to directory '%s'", CRL_PATH);	n = scandir(CRL_PATH, &filelist, file_select, alphasort);	if (n <= 0)	    openswan_log("  Warning: empty directory");	else	{	    while (n--)	    {		bool pgp = FALSE;		chunk_t blob = empty_chunk;		char *filename = filelist[n]->d_name;		if (load_coded_file(filename, NULL, "crl", &blob, &pgp))		{		    chunk_t crl_uri;                    crl_uri.len = 8 + strlen(CRL_PATH) + strlen(filename);		    crl_uri.ptr = alloc_bytes(crl_uri.len + 1, "crl uri");		    /* build CRL file URI */		    snprintf(crl_uri.ptr, crl_uri.len +1, "file://%s/%s", CRL_PATH, filename);		    insert_crl(blob, crl_uri);		}		free(filelist[n]);	    }	    free(filelist);	}    }    /* restore directory path */    chdir(save_dir);}/* * extracts the basicConstraints extension */static boolparse_basicConstraints(chunk_t blob, int level0){    asn1_ctx_t ctx;    chunk_t object;    u_int level;    int objectID = 0;    bool isCA = FALSE;    asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);    while (objectID < BASIC_CONSTRAINTS_ROOF) {	if (!extract_object(basicConstraintsObjects, &objectID,			    &object,&level, &ctx))	     break;	if (objectID == BASIC_CONSTRAINTS_CA)	{	    isCA = object.len && *object.ptr;	    DBG(DBG_PARSING,		DBG_log("  %s",(isCA)?"TRUE":"FALSE");	    )	}	objectID++;    }    return isCA;}/* *  Converts a X.500 generalName into an ID */voidgntoid(struct id *id, const generalName_t *gn){    switch(gn->kind)    {    case GN_DNS_NAME:		/* ID type: ID_FQDN */	id->kind = ID_FQDN;	id->name = gn->name;	break;    case GN_IP_ADDRESS:		/* ID type: ID_IPV4_ADDR */	{	    const struct af_info *afi = &af_inet4_info;	    err_t ugh = NULL;	    id->kind = afi->id_addr;	    ugh = initaddr(gn->name.ptr, gn->name.len, afi->af, &id->ip_addr);	}	break;    case GN_RFC822_NAME:	/* ID type: ID_USER_FQDN */	id->kind = ID_USER_FQDN;	id->name = gn->name;	break;    default:	id->kind = ID_NONE;	id->name = empty_chunk;    }}/* * extracts a generalName */static generalName_t*parse_generalName(chunk_t blob, int level0){    u_char buf[BUF_LEN];    asn1_ctx_t ctx;    chunk_t object;    int objectID = 0;    u_int level;    asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);    while (objectID < GN_OBJ_ROOF)    {	bool valid_gn = FALSE;		if (!extract_object(generalNameObjects, &objectID, &object, &level, &ctx))	     return NULL;	switch (objectID) {	case GN_OBJ_RFC822_NAME:	case GN_OBJ_DNS_NAME:	case GN_OBJ_URI:	    DBG(DBG_PARSING,		DBG_log("  '%.*s'", (int)object.len, object.ptr);	    )	    valid_gn = TRUE;	    break;	case GN_OBJ_DIRECTORY_NAME:	    DBG(DBG_PARSING,		dntoa(buf, BUF_LEN, object);		DBG_log("  '%s'", buf)	    )	    valid_gn = TRUE;	    break;	case GN_OBJ_IP_ADDRESS:	    DBG(DBG_PARSING,		DBG_log("  '%d.%d.%d.%d'", *object.ptr, *(object.ptr+1),				      *(object.ptr+2), *(object.ptr+3));	    )	    valid_gn = TRUE;	    break;	case GN_OBJ_OTHER_NAME:	case GN_OBJ_X400_ADDRESS:	case GN_OBJ_EDI_PARTY_NAME:	case GN_OBJ_REGISTERED_ID:	    break;	default:	    break;	}	if (valid_gn)	{	    generalName_t *gn = alloc_thing(generalName_t, "generalName");	    gn->kind = (objectID - GN_OBJ_OTHER_NAME) / 2;	    gn->name = object;	    gn->next = FALSE;	    return gn;        }	objectID++;    }    return NULL;}/* * extracts one or several GNs and puts them into a chained list

⌨️ 快捷键说明

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