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

📄 fetch.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Dynamic fetching of X.509 CRLs * Copyright (C) 2002 Stephane Laroche <stephane.laroche@colubris.com> * Copyright (C) 2002-2004 Andreas Steffen, 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. * * RCSID $Id: fetch.c,v 1.6 2004/06/14 02:01:32 mcr Exp $ */#include <stdlib.h>#include <errno.h>#include <sys/time.h>#include <pthread.h>#include <string.h>#ifdef LIBCURL#include <curl/curl.h>#endif#include <openswan.h>#ifdef LDAP_VER#include <ldap.h>#endif#include "constants.h"#include "defs.h"#include "log.h"#include "id.h"#include "asn1.h"#include "pem.h"#include "x509.h"#include "whack.h"#include "ocsp.h"#include "fetch.h"#ifdef LIBCURL#define LIBCURL_UNUSED #else#define LIBCURL_UNUSED UNUSED#endif#define FETCH_CMD_TIMEOUT	5	/* seconds */typedef struct fetch_req fetch_req_t;struct fetch_req {  fetch_req_t   *next;  time_t        installed;  int           trials;  chunk_t       issuer;  generalName_t *distributionPoints;};fetch_req_t empty_fetch_req = {   NULL    , /* next */         0 , /* installed */         0 , /* trials */  {NULL, 0}, /* issuer */   NULL      /* distributionPoints */};/* chained list of crl fetch requests */static fetch_req_t *crl_fetch_reqs  = NULL;/* chained list of ocsp fetch requests */static ocsp_location_t *ocsp_fetch_reqs = NULL;static pthread_t thread;static pthread_mutex_t certs_and_keys_mutex  = PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t authcert_list_mutex   = PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t crl_list_mutex        = PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t ocsp_cache_mutex      = PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t crl_fetch_list_mutex  = PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t ocsp_fetch_list_mutex = PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t fetch_wake_mutex      = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t  fetch_wake_cond       = PTHREAD_COND_INITIALIZER;#define BUF_LEN		512/* * lock access to my certs and keys */voidlock_certs_and_keys(const char *who){    pthread_mutex_lock(&certs_and_keys_mutex);    DBG(DBG_CONTROLMORE,	DBG_log("certs and keys locked by '%s'", who)    )}/* * unlock access to my certs and keys */voidunlock_certs_and_keys(const char *who){    DBG(DBG_CONTROLMORE,	DBG_log("certs and keys unlocked by '%s'", who)    )    pthread_mutex_unlock(&certs_and_keys_mutex);}/* * lock access to the chained authcert list */voidlock_authcert_list(const char *who){    pthread_mutex_lock(&authcert_list_mutex);    DBG(DBG_CONTROLMORE,	DBG_log("authcert list locked by '%s'", who)    )}/* * unlock access to the chained authcert list */voidunlock_authcert_list(const char *who){    DBG(DBG_CONTROLMORE,	DBG_log("authcert list unlocked by '%s'", who)    )    pthread_mutex_unlock(&authcert_list_mutex);}/* * lock access to the chained crl list */voidlock_crl_list(const char *who){    pthread_mutex_lock(&crl_list_mutex);    DBG(DBG_CONTROLMORE,	DBG_log("crl list locked by '%s'", who)    )}/* * unlock access to the chained crl list */voidunlock_crl_list(const char *who){    DBG(DBG_CONTROLMORE,	DBG_log("crl list unlocked by '%s'", who)    )    pthread_mutex_unlock(&crl_list_mutex);}/* * lock access to the ocsp cache */extern voidlock_ocsp_cache(const char *who){    pthread_mutex_lock(&ocsp_cache_mutex);    DBG(DBG_CONTROLMORE,	DBG_log("ocsp cache locked by '%s'", who)    )}/* * unlock access to the ocsp cache */extern voidunlock_ocsp_cache(const char *who){    DBG(DBG_CONTROLMORE,	DBG_log("ocsp cache unlocked by '%s'", who)    )    pthread_mutex_unlock(&ocsp_cache_mutex);}/* * lock access to the chained crl fetch request list */static voidlock_crl_fetch_list(const char *who){    pthread_mutex_lock(&crl_fetch_list_mutex);    DBG(DBG_CONTROLMORE,	DBG_log("crl fetch request list locked by '%s'", who)    )}/* * unlock access to the chained crl fetch request list */static voidunlock_crl_fetch_list(const char *who){    DBG(DBG_CONTROLMORE,	DBG_log("crl fetch request list unlocked by '%s'", who)    )    pthread_mutex_unlock(&crl_fetch_list_mutex);}/* * lock access to the chained ocsp fetch request list */static voidlock_ocsp_fetch_list(const char *who){    pthread_mutex_lock(&ocsp_fetch_list_mutex);    DBG(DBG_CONTROLMORE,	DBG_log("ocsp fetch request list locked by '%s'", who)    )}/* * unlock access to the chained ocsp fetch request list */static voidunlock_ocsp_fetch_list(const char *who){    DBG(DBG_CONTROLMORE,	DBG_log("ocsp fetch request list unlocked by '%s'", who)    )    pthread_mutex_unlock(&ocsp_fetch_list_mutex);}/* * wakes up the sleeping fetch thread */voidwake_fetch_thread(const char *who){    if (crl_check_interval > 0)    {	DBG(DBG_CONTROLMORE,	    DBG_log("fetch thread wake call by '%s'", who)	)#ifdef HAVE_THREADS	pthread_mutex_lock(&fetch_wake_mutex);	pthread_cond_signal(&fetch_wake_cond);	pthread_mutex_unlock(&fetch_wake_mutex);#endif    }}/* *  free the dynamic memory used to store fetch requests */static voidfree_fetch_request(fetch_req_t *req){    pfree(req->issuer.ptr);    free_generalNames(req->distributionPoints, TRUE);    pfree(req);}#ifdef LIBCURL/* * writes data into a buffer * needed for libcurl */static size_twrite_buffer(void *ptr, size_t size, size_t nmemb, void *data){    size_t realsize = size * nmemb;    chunk_t *mem = (chunk_t*)data;    mem->ptr = (u_char *)realloc(mem->ptr, mem->len + realsize);    if (mem->ptr) {        memcpy(&(mem->ptr[mem->len]), ptr, realsize);        mem->len += realsize;    }    return realsize;}#endif/* * fetches a binary blob from a url with libcurl */static err_t fetch_curl(chunk_t url LIBCURL_UNUSED, chunk_t *blob LIBCURL_UNUSED){#ifdef LIBCURL    char errorbuffer[CURL_ERROR_SIZE] = "";    char *uri;    chunk_t response = empty_chunk;    CURLcode res;      /* get it with libcurl */    CURL *curl = curl_easy_init();    if (curl != NULL)    {        /* we need a null terminated string for curl */        uri = alloc_bytes(url.len + 1, "null terminated url");        memcpy(uri, url.ptr, url.len);        *(uri + url.len) = '\0';        DBG(DBG_CONTROL,            DBG_log("Trying cURL '%s'", uri)        )        curl_easy_setopt(curl, CURLOPT_URL, uri);        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer);        curl_easy_setopt(curl, CURLOPT_FILE, (void *)&response);        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &errorbuffer);        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT);        res = curl_easy_perform(curl);            if (res == CURLE_OK)        {            blob->len = response.len;            blob->ptr = alloc_bytes(response.len, "curl blob");            memcpy(blob->ptr, response.ptr, response.len);        }        else        {            plog("fetching uri (%s) with libcurl failed: %s", uri, errorbuffer);        }        curl_easy_cleanup(curl);        pfree(uri);        /* not using freeanychunk because of realloc (no leak detective) */        free(response.ptr);    }    return strlen(errorbuffer) > 0 ? "libcurl error" : NULL;#else    return "not compiled with libcurl support";#endif   }#ifdef LDAP_VER/* * parses the result returned by an ldap query */static err_tparse_ldap_result(LDAP * ldap, LDAPMessage *result, chunk_t *blob){    err_t ugh = NULL;    LDAPMessage * entry = ldap_first_entry(ldap, result);    if (entry != NULL)    {	BerElement *ber = NULL;	char *attr;		attr = ldap_first_attribute(ldap, entry, &ber);	if (attr != NULL)	{	    struct berval **values = ldap_get_values_len(ldap, entry, attr);	    if (values != NULL)	    {		if (values[0] != NULL)		{		    blob->len = values[0]->bv_len;		    blob->ptr = alloc_bytes(blob->len, "ldap blob");		    memcpy(blob->ptr, values[0]->bv_val, blob->len);		    if (values[1] != NULL)		    {			plog("warning: more than one value was fetched from LDAP URL");		    }		}		else		{		    ugh = "no values in attribute";		}		ldap_value_free_len(values);	    }	    else	    {		ugh = ldap_err2string(ldap_result2error(ldap, entry, 0));	    }	    ldap_memfree(attr);	}	else	{	    ugh = ldap_err2string(ldap_result2error(ldap, entry, 0));	}	ber_free(ber, 0);    }    else    {	ugh = ldap_err2string(ldap_result2error(ldap, result, 0));    }    return ugh;}/* * fetches a binary blob from an ldap url */static err_tfetch_ldap_url(chunk_t url, chunk_t *blob){    LDAPURLDesc *lurl;    err_t ugh = NULL;    int rc;    char *ldap_url = alloc_bytes(url.len + 1, "ldap query");    sprintf(ldap_url,"%.*s", (int)url.len, url.ptr);    DBG(DBG_CONTROL,	DBG_log("Trying LDAP URL '%s'", ldap_url)    )    rc = ldap_url_parse(ldap_url, &lurl);    pfree(ldap_url);    if (rc == LDAP_SUCCESS)    {	LDAP *ldap = ldap_init(lurl->lud_host, lurl->lud_port);	if (ldap != NULL)	{	    int ldap_version = (LDAP_VER == 2)? LDAP_VERSION2 : LDAP_VERSION3;	    struct timeval timeout;	    timeout.tv_sec  = FETCH_CMD_TIMEOUT;	    timeout.tv_usec = 0;	    ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);	    ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout);	    rc = ldap_simple_bind_s(ldap, NULL, NULL);	    if (rc == LDAP_SUCCESS)	    {		LDAPMessage *result;		timeout.tv_sec = FETCH_CMD_TIMEOUT;		timeout.tv_usec = 0;				rc = ldap_search_st(ldap, lurl->lud_dn					, lurl->lud_scope					, lurl->lud_filter					, lurl->lud_attrs					, 0, &timeout, &result);		if (rc == LDAP_SUCCESS)		{		    ugh = parse_ldap_result(ldap, result, blob);		    ldap_msgfree(result);		}		else		{		    ugh = ldap_err2string(rc);		}	    }	    else	    {		ugh = ldap_err2string(rc);	    }	    ldap_unbind_s(ldap);	}	else	{	    ugh = "ldap init";	}	ldap_free_urldesc(lurl);    }    else    {	ugh = ldap_err2string(rc);    }    return ugh;}#elsestatic err_tfetch_ldap_url(chunk_t url UNUSED	       , chunk_t *blob UNUSED){    return "LDAP URL fetching not activated in pluto source code";}#endif/* * fetch an ASN.1 blob coded in PEM or DER format from a URL */static err_tfetch_asn1_blob(chunk_t url, chunk_t *blob)

⌨️ 快捷键说明

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