introduced new logging subsystem using bus:
passive listeners can register on the bus active listeners wait for signals actively multiplexing allows multiple listeners to receive debug signals a lot more...
This commit is contained in:
@@ -30,12 +30,9 @@ crypto/diffie_hellman.c crypto/diffie_hellman.h \
|
||||
utils/identification.c utils/identification.h \
|
||||
utils/linked_list.c utils/linked_list.h utils/iterator.h\
|
||||
utils/randomizer.c utils/randomizer.h \
|
||||
utils/logger.c utils/logger.h \
|
||||
utils/logger_manager.c utils/logger_manager.h \
|
||||
utils/host.c utils/host.h \
|
||||
utils/lexparser.c utils/lexparser.h \
|
||||
utils/leak_detective.c utils/leak_detective.h \
|
||||
utils/tester.c utils/tester.h
|
||||
utils/leak_detective.c utils/leak_detective.h
|
||||
|
||||
libstrongswan_la_LIBADD = -lgmp -lpthread
|
||||
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "asn1.h"
|
||||
|
||||
#include <utils/logger_manager.h>
|
||||
#include <types.h>
|
||||
#include <library.h>
|
||||
|
||||
/* some common prefabricated ASN.1 constants */
|
||||
static u_char ASN1_INTEGER_0_str[] = { 0x02, 0x00 };
|
||||
@@ -80,17 +80,6 @@ static const asn1Object_t algorithmIdentifierObjects[] = {
|
||||
#define ALGORITHM_ID_PARAMETERS 2
|
||||
#define ALGORITHM_ID_ROOF 3
|
||||
|
||||
static logger_t *logger = NULL;
|
||||
|
||||
/**
|
||||
* initializes the ASN.1 logger
|
||||
*/
|
||||
static void asn1_init_logger(void)
|
||||
{
|
||||
if (logger == NULL)
|
||||
logger = logger_manager->get_logger(logger_manager, ASN1);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the ASN.1 encoded algorithm identifier
|
||||
*/
|
||||
@@ -171,14 +160,14 @@ u_int asn1_length(chunk_t *blob)
|
||||
|
||||
if (n > blob->len)
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, "number of length octets is larger than ASN.1 object");
|
||||
DBG2("number of length octets is larger than ASN.1 object");
|
||||
return ASN1_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
if (n > sizeof(len))
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, "number of length octets is larger than limit of %d octets",
|
||||
(int)sizeof(len));
|
||||
DBG2("number of length octets is larger than limit of %d octets",
|
||||
(int)sizeof(len));
|
||||
return ASN1_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
@@ -289,8 +278,6 @@ time_t asn1totime(const chunk_t *utctime, asn1_t type)
|
||||
*/
|
||||
void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, bool implicit)
|
||||
{
|
||||
asn1_init_logger();
|
||||
|
||||
ctx->blobs[0] = blob;
|
||||
ctx->level0 = level0;
|
||||
ctx->implicit = implicit;
|
||||
@@ -310,7 +297,7 @@ static void debug_asn1_simple_object(chunk_t object, asn1_t type)
|
||||
oid = known_oid(object);
|
||||
if (oid != OID_UNKNOWN)
|
||||
{
|
||||
logger->log(logger, CONTROL|LEVEL2, " '%s'", oid_names[oid].name);
|
||||
DBG2(" '%s'", oid_names[oid].name);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -319,22 +306,18 @@ static void debug_asn1_simple_object(chunk_t object, asn1_t type)
|
||||
case ASN1_PRINTABLESTRING:
|
||||
case ASN1_T61STRING:
|
||||
case ASN1_VISIBLESTRING:
|
||||
logger->log(logger, CONTROL|LEVEL2, " '%.*s'", (int)object.len, object.ptr);
|
||||
DBG2(" '%.*s'", (int)object.len, object.ptr);
|
||||
return;
|
||||
case ASN1_UTCTIME:
|
||||
case ASN1_GENERALIZEDTIME:
|
||||
{
|
||||
char buf[TIMETOA_BUF];
|
||||
time_t time = asn1totime(&object, type);
|
||||
|
||||
timetoa(buf, TIMETOA_BUF, &time, TRUE);
|
||||
logger->log(logger, CONTROL|LEVEL2, " '%s'", buf);
|
||||
DBG2(" '%T'", asn1totime(&object, type));
|
||||
}
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
logger->log_chunk(logger, RAW|LEVEL1, "", object);
|
||||
DBG3("%B", &object);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -372,7 +355,7 @@ bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *objec
|
||||
if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
|
||||
{
|
||||
/* field is missing */
|
||||
logger->log(logger, CONTROL|LEVEL2, "L%d - %s:", *level, obj.name);
|
||||
DBG2("L%d - %s:", *level, obj.name);
|
||||
if (obj.type & ASN1_CONSTRUCTED)
|
||||
{
|
||||
(*objectID)++ ; /* skip context-specific tag */
|
||||
@@ -397,7 +380,7 @@ bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *objec
|
||||
|
||||
if (blob->len < 2)
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN.1 object smaller than 2 octets",
|
||||
DBG2("L%d - %s: ASN.1 object smaller than 2 octets",
|
||||
*level, obj.name);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -406,7 +389,7 @@ bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *objec
|
||||
|
||||
if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len)
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, "L%d - %s: length of ASN.1 object invalid or too large",
|
||||
DBG2("L%d - %s: length of ASN.1 object invalid or too large",
|
||||
*level, obj.name);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -419,7 +402,7 @@ bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *objec
|
||||
|
||||
if (obj.flags & ASN1_RAW)
|
||||
{
|
||||
logger->log(logger, CONTROL|LEVEL2, "L%d - %s:", *level, obj.name);
|
||||
DBG2("L%d - %s:", *level, obj.name);
|
||||
object->ptr = start_ptr;
|
||||
object->len = (size_t)(blob->ptr - start_ptr);
|
||||
return TRUE;
|
||||
@@ -427,13 +410,13 @@ bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *objec
|
||||
|
||||
if (*start_ptr != obj.type && !(ctx->implicit && *objectID == 0))
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
|
||||
DBG1("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
|
||||
*level, obj.name, obj.type, *start_ptr);
|
||||
logger->log_bytes(logger, RAW|LEVEL1, "", start_ptr, (u_int)(blob->ptr - start_ptr));
|
||||
DBG3("%b", start_ptr, (u_int)(blob->ptr - start_ptr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
logger->log(logger, CONTROL|LEVEL2, "L%d - %s:", ctx->level0+obj.level, obj.name);
|
||||
DBG2("L%d - %s:", ctx->level0+obj.level, obj.name);
|
||||
|
||||
/* In case of "SEQUENCE OF" or "SET OF" start a loop */
|
||||
if (obj.flags & ASN1_LOOP)
|
||||
@@ -458,7 +441,7 @@ bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *objec
|
||||
{
|
||||
object->ptr = start_ptr;
|
||||
object->len = (size_t)(blob->ptr - start_ptr);
|
||||
logger->log_chunk(logger, RAW|LEVEL2, "", *object);
|
||||
DBG3("%B", object);
|
||||
}
|
||||
else if (obj.flags & ASN1_BODY)
|
||||
{
|
||||
@@ -478,15 +461,14 @@ bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, const c
|
||||
/* an ASN.1 object must possess at least a tag and length field */
|
||||
if (object->len < 2)
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN.1 object smaller than 2 octets",
|
||||
level, name);
|
||||
DBG2("L%d - %s: ASN.1 object smaller than 2 octets", level, name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (*object->ptr != type)
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
|
||||
level, name, type, *object->ptr);
|
||||
DBG2("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
|
||||
level, name, type, *object->ptr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -494,12 +476,12 @@ bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, const c
|
||||
|
||||
if (len == ASN1_INVALID_LENGTH || object->len < len)
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, "L%d - %s: length of ASN.1 object invalid or too large",
|
||||
level, name);
|
||||
DBG2("L%d - %s: length of ASN.1 object invalid or too large",
|
||||
level, name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
logger->log(logger, CONTROL|LEVEL2, "L%d - %s:", level, name);
|
||||
DBG2("L%d - %s:", level, name);
|
||||
debug_asn1_simple_object(*object, type);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -546,18 +528,16 @@ bool is_asn1(chunk_t blob)
|
||||
{
|
||||
u_int len;
|
||||
u_char tag = *blob.ptr;
|
||||
|
||||
asn1_init_logger();
|
||||
|
||||
if (tag != ASN1_SEQUENCE && tag != ASN1_SET)
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL2, " file content is not binary ASN.1");
|
||||
DBG2(" file content is not binary ASN.1");
|
||||
return FALSE;
|
||||
}
|
||||
len = asn1_length(&blob);
|
||||
if (len != blob.len)
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL2, " file size does not match ASN.1 coded length");
|
||||
DBG2(" file size does not match ASN.1 coded length");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
@@ -708,7 +688,7 @@ chunk_t timetoasn1(const time_t *time, asn1_t type)
|
||||
{
|
||||
int offset;
|
||||
const char *format;
|
||||
char buf[TIMETOA_BUF];
|
||||
char buf[32];
|
||||
chunk_t formatted_time;
|
||||
struct tm *t = gmtime(time);
|
||||
|
||||
@@ -722,8 +702,8 @@ chunk_t timetoasn1(const time_t *time, asn1_t type)
|
||||
format = "%02d%02d%02d%02d%02d%02dZ";
|
||||
offset = (t->tm_year < 100)? 0 : -100;
|
||||
}
|
||||
sprintf(buf, format, t->tm_year + offset, t->tm_mon + 1, t->tm_mday
|
||||
, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
snprintf(buf, sizeof(buf), format, t->tm_year + offset,
|
||||
t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
formatted_time.ptr = buf;
|
||||
formatted_time.len = strlen(buf);
|
||||
return asn1_simple_object(type, formatted_time);
|
||||
|
||||
@@ -20,28 +20,18 @@
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "asn1.h"
|
||||
#include "pem.h"
|
||||
#include "ttodata.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/ttodata.h>
|
||||
|
||||
#include <utils/lexparser.h>
|
||||
#include <utils/logger_manager.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
#include <crypto/crypters/crypter.h>
|
||||
|
||||
#define PKCS5_SALT_LEN 8 /* bytes */
|
||||
|
||||
static logger_t *logger = NULL;
|
||||
|
||||
/**
|
||||
* initializes the PEM logger
|
||||
*/
|
||||
static void pem_init_logger(void)
|
||||
{
|
||||
if (logger == NULL)
|
||||
logger = logger_manager->get_logger(logger_manager, ASN1);
|
||||
}
|
||||
|
||||
/**
|
||||
* check the presence of a pattern in a character string
|
||||
*/
|
||||
@@ -79,8 +69,7 @@ static bool find_boundary(const char* tag, chunk_t *line)
|
||||
{
|
||||
if (present("-----", line))
|
||||
{
|
||||
logger->log(logger, CONTROL|LEVEL2,
|
||||
" -----%s %.*s-----", tag, (int)name.len, name.ptr);
|
||||
DBG2(" -----%s %.*s-----", tag, (int)name.len, name.ptr);
|
||||
return TRUE;
|
||||
}
|
||||
line->ptr++; line->len--; name.len++;
|
||||
@@ -185,8 +174,6 @@ err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
|
||||
iv.ptr = iv_buf;
|
||||
iv.len = 0;
|
||||
|
||||
pem_init_logger();
|
||||
|
||||
while (fetchline(&src, &line))
|
||||
{
|
||||
if (state == PEM_PRE)
|
||||
@@ -222,7 +209,7 @@ err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
|
||||
}
|
||||
|
||||
/* we are looking for a parameter: value pair */
|
||||
logger->log(logger, CONTROL|LEVEL2, " %.*s", (int)line.len, line.ptr);
|
||||
DBG2(" %.*s", (int)line.len, line.ptr);
|
||||
ugh = extract_parameter_value(&name, &value, &line);
|
||||
if (ugh != NULL)
|
||||
continue;
|
||||
@@ -289,8 +276,7 @@ err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
|
||||
*pgp = TRUE;
|
||||
data.ptr++;
|
||||
data.len--;
|
||||
logger->log(logger, CONTROL|LEVEL2, " Armor checksum: %.*s",
|
||||
(int)data.len, data.ptr);
|
||||
DBG2(" Armor checksum: %.*s", (int)data.len, data.ptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -327,8 +313,6 @@ bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
|
||||
|
||||
FILE *fd = fopen(filename, "r");
|
||||
|
||||
pem_init_logger();
|
||||
|
||||
if (fd)
|
||||
{
|
||||
int bytes;
|
||||
@@ -338,19 +322,19 @@ bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
|
||||
blob->ptr = malloc(blob->len);
|
||||
bytes = fread(blob->ptr, 1, blob->len, fd);
|
||||
fclose(fd);
|
||||
logger->log(logger, CONTROL, " loading %s file '%s' (%d bytes)", type, filename, bytes);
|
||||
DBG1(" loading %s file '%s' (%d bytes)", type, filename, bytes);
|
||||
|
||||
*pgp = FALSE;
|
||||
|
||||
/* try DER format */
|
||||
if (is_asn1(*blob))
|
||||
{
|
||||
logger->log(logger, CONTROL|LEVEL1, " file coded in DER format");
|
||||
DBG2(" file coded in DER format");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (passphrase != NULL)
|
||||
logger->log_bytes(logger, PRIVATE, " passphrase:", passphrase->ptr, passphrase->len);
|
||||
DBG4(" passphrase:", passphrase->ptr, passphrase->len);
|
||||
|
||||
/* try PEM format */
|
||||
ugh = pem_to_bin(blob, passphrase, pgp);
|
||||
@@ -359,24 +343,24 @@ bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
|
||||
{
|
||||
if (*pgp)
|
||||
{
|
||||
logger->log(logger, CONTROL|LEVEL1, " file coded in armored PGP format");
|
||||
DBG2(" file coded in armored PGP format");
|
||||
return TRUE;
|
||||
}
|
||||
if (is_asn1(*blob))
|
||||
{
|
||||
logger->log(logger, CONTROL|LEVEL1, " file coded in PEM format");
|
||||
DBG2(" file coded in PEM format");
|
||||
return TRUE;
|
||||
}
|
||||
ugh = "file coded in unknown format, discarded";
|
||||
}
|
||||
|
||||
/* a conversion error has occured */
|
||||
logger->log(logger, ERROR, " %s", ugh);
|
||||
DBG1(" %s", ugh);
|
||||
chunk_free(blob);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->log(logger, ERROR, " could not open %s file '%s'", type, filename);
|
||||
DBG1(" could not open %s file '%s'", type, filename);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -69,24 +69,15 @@ struct private_certinfo_t {
|
||||
crl_reason_t revocationReason;
|
||||
};
|
||||
|
||||
/**
|
||||
* RFC 2560 OCSP - certificate status
|
||||
*/
|
||||
static const char *const cert_status_name[] = {
|
||||
ENUM(cert_status_names, CERT_GOOD, CERT_UNTRUSTED,
|
||||
"good",
|
||||
"revoked",
|
||||
"unknown",
|
||||
"unknown",
|
||||
"untrusted"
|
||||
};
|
||||
"untrusted",
|
||||
);
|
||||
|
||||
enum_names cert_status_names =
|
||||
{ CERT_GOOD, CERT_UNTRUSTED, cert_status_name, NULL};
|
||||
|
||||
/**
|
||||
* RFC 2459 CRL reason codes
|
||||
*/
|
||||
static const char *const crl_reason_name[] = {
|
||||
ENUM(crl_reason_names, REASON_UNSPECIFIED, REASON_REMOVE_FROM_CRL,
|
||||
"unspecified",
|
||||
"key compromise",
|
||||
"ca compromise",
|
||||
@@ -95,11 +86,8 @@ static const char *const crl_reason_name[] = {
|
||||
"cessation of operation",
|
||||
"certificate hold",
|
||||
"reason #7",
|
||||
"remove from crl"
|
||||
};
|
||||
|
||||
enum_names crl_reason_names =
|
||||
{ REASON_UNSPECIFIED, REASON_REMOVE_FROM_CRL, crl_reason_name, NULL};
|
||||
"remove from crl",
|
||||
);
|
||||
|
||||
/**
|
||||
* Implements certinfo_t.get_serialNumber
|
||||
@@ -168,9 +156,9 @@ static void set_revocationReason(private_certinfo_t *this, crl_reason_t reason)
|
||||
/**
|
||||
* Implements certinfo_t.get_revocationReason
|
||||
*/
|
||||
static const char *get_revocationReason(const private_certinfo_t *this)
|
||||
static crl_reason_t get_revocationReason(const private_certinfo_t *this)
|
||||
{
|
||||
return enum_name(&crl_reason_names, this->revocationReason);
|
||||
return this->revocationReason;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,7 +193,7 @@ certinfo_t *certinfo_create(chunk_t serial)
|
||||
this->public.set_revocationTime = (void (*) (certinfo_t*,time_t))set_revocationTime;
|
||||
this->public.get_revocationTime = (time_t (*) (const certinfo_t*))get_revocationTime;
|
||||
this->public.set_revocationReason = (void (*) (certinfo_t*, crl_reason_t))set_revocationReason;
|
||||
this->public.get_revocationReason = (const char *(*) (const certinfo_t*))get_revocationReason;
|
||||
this->public.get_revocationReason = (crl_reason_t(*) (const certinfo_t*))get_revocationReason;
|
||||
this->public.destroy = (void (*) (certinfo_t*))destroy;
|
||||
|
||||
return &this->public;
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
/**
|
||||
* RFC 2560 OCSP - certificate status
|
||||
*/
|
||||
extern enum_names cert_status_names;
|
||||
|
||||
typedef enum {
|
||||
CERT_GOOD = 0,
|
||||
CERT_REVOKED = 1,
|
||||
@@ -39,12 +37,11 @@ typedef enum {
|
||||
CERT_UNTRUSTED = 4 /* private use */
|
||||
} cert_status_t;
|
||||
|
||||
extern enum_name_t *cert_status_names;
|
||||
|
||||
/**
|
||||
* RFC 2459 CRL reason codes
|
||||
*/
|
||||
|
||||
extern enum_names crl_reason_names;
|
||||
|
||||
typedef enum {
|
||||
REASON_UNSPECIFIED = 0,
|
||||
REASON_KEY_COMPROMISE = 1,
|
||||
@@ -56,6 +53,8 @@ typedef enum {
|
||||
REASON_REMOVE_FROM_CRL = 8
|
||||
} crl_reason_t;
|
||||
|
||||
extern enum_name_t *crl_reason_names;
|
||||
|
||||
typedef struct certinfo_t certinfo_t;
|
||||
|
||||
/**
|
||||
@@ -67,85 +66,76 @@ typedef struct certinfo_t certinfo_t;
|
||||
struct certinfo_t {
|
||||
|
||||
/**
|
||||
* @brief Get serial number
|
||||
*
|
||||
*
|
||||
* @brief Get serial number.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return serialNumber
|
||||
*/
|
||||
chunk_t (*get_serialNumber) (const certinfo_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set certificate status
|
||||
*
|
||||
*
|
||||
* @brief Set certificate status.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param status status
|
||||
*/
|
||||
void (*set_status) (certinfo_t *this, cert_status_t status);
|
||||
|
||||
/**
|
||||
* @brief Get certificate status
|
||||
*
|
||||
*
|
||||
* @brief Get certificate status.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return status
|
||||
*/
|
||||
cert_status_t (*get_status) (const certinfo_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set nextUpdate
|
||||
*
|
||||
*
|
||||
* @brief Set nextUpdate.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return nextUpdate
|
||||
*/
|
||||
void (*set_nextUpdate) (certinfo_t *this, time_t nextUpdate);
|
||||
|
||||
/**
|
||||
* @brief Get nextUpdate
|
||||
*
|
||||
*
|
||||
* @brief Get nextUpdate.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return nextUpdate
|
||||
*/
|
||||
time_t (*get_nextUpdate) (const certinfo_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set revocationTime
|
||||
*
|
||||
*
|
||||
* @brief Set revocationTime.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param revocationTime revocationTime
|
||||
*/
|
||||
void (*set_revocationTime) (certinfo_t *this, time_t revocationTime);
|
||||
|
||||
/**
|
||||
* @brief Get revocationTime
|
||||
*
|
||||
*
|
||||
* @brief Get revocationTime.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return revocationTime
|
||||
*/
|
||||
time_t (*get_revocationTime) (const certinfo_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set revocationReason
|
||||
*
|
||||
*
|
||||
* @brief Set revocationReason.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param reason revocationReason
|
||||
*/
|
||||
void (*set_revocationReason) (certinfo_t *this, crl_reason_t reason);
|
||||
|
||||
/**
|
||||
* @brief Get revocationReason
|
||||
*
|
||||
*
|
||||
* @brief Get revocationReason.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return revocationReason
|
||||
*/
|
||||
const char *(*get_revocationReason) (const certinfo_t *this);
|
||||
crl_reason_t (*get_revocationReason) (const certinfo_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys the certinfo_t object.
|
||||
|
||||
@@ -23,13 +23,14 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <printf.h>
|
||||
|
||||
#include <types.h>
|
||||
#include <library.h>
|
||||
#include <definitions.h>
|
||||
#include <asn1/oid.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/pem.h>
|
||||
#include <utils/logger_manager.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <utils/identification.h>
|
||||
|
||||
@@ -39,7 +40,6 @@
|
||||
|
||||
#define CRL_WARNING_INTERVAL 7 /* days */
|
||||
|
||||
static logger_t *logger;
|
||||
extern char* check_expiry(time_t expiration_date, int warning_interval, bool strict);
|
||||
extern time_t parse_time(chunk_t blob, int level0);
|
||||
extern void parse_authorityKeyIdentifier(chunk_t blob, int level0 , chunk_t *authKeyID, chunk_t *authKeySerialNumber);
|
||||
@@ -206,9 +206,9 @@ static crl_reason_t parse_crl_reasonCode(chunk_t object)
|
||||
{
|
||||
reason = *object.ptr;
|
||||
}
|
||||
logger->log(logger, CONTROL|LEVEL2, " '%s'", enum_name(&crl_reason_names, reason));
|
||||
DBG2(" '%N'", crl_reason_names, reason);
|
||||
|
||||
return reason;
|
||||
return reason;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,7 +219,7 @@ bool parse_x509crl(chunk_t blob, u_int level0, private_crl_t *crl)
|
||||
asn1_ctx_t ctx;
|
||||
bool critical;
|
||||
chunk_t extnID;
|
||||
chunk_t userCertificate;
|
||||
chunk_t userCertificate = CHUNK_INITIALIZER;
|
||||
revokedCert_t *revokedCert = NULL;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
@@ -245,14 +245,14 @@ bool parse_x509crl(chunk_t blob, u_int level0, private_crl_t *crl)
|
||||
break;
|
||||
case CRL_OBJ_VERSION:
|
||||
crl->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
|
||||
logger->log(logger, CONTROL|LEVEL2, " v%d", crl->version);
|
||||
DBG2(" v%d", crl->version);
|
||||
break;
|
||||
case CRL_OBJ_SIG_ALG:
|
||||
crl->sigAlg = parse_algorithmIdentifier(object, level, NULL);
|
||||
break;
|
||||
case CRL_OBJ_ISSUER:
|
||||
crl->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
|
||||
logger->log(logger, CONTROL|LEVEL1, " '%D'", crl->issuer);
|
||||
DBG2(" '%D'", crl->issuer);
|
||||
break;
|
||||
case CRL_OBJ_THIS_UPDATE:
|
||||
crl->thisUpdate = parse_time(object, level);
|
||||
@@ -277,7 +277,7 @@ bool parse_x509crl(chunk_t blob, u_int level0, private_crl_t *crl)
|
||||
case CRL_OBJ_CRL_ENTRY_CRITICAL:
|
||||
case CRL_OBJ_CRITICAL:
|
||||
critical = object.len && *object.ptr;
|
||||
logger->log(logger, CONTROL|LEVEL2, " %s",(critical)?"TRUE":"FALSE");
|
||||
DBG2(" %s",(critical)?"TRUE":"FALSE");
|
||||
break;
|
||||
case CRL_OBJ_CRL_ENTRY_EXTN_VALUE:
|
||||
case CRL_OBJ_EXTN_VALUE:
|
||||
@@ -314,25 +314,22 @@ bool parse_x509crl(chunk_t blob, u_int level0, private_crl_t *crl)
|
||||
*/
|
||||
static err_t is_valid(const private_crl_t *this, time_t *until, bool strict)
|
||||
{
|
||||
char buf[TIMETOA_BUF];
|
||||
|
||||
time_t current_time = time(NULL);
|
||||
|
||||
timetoa(buf, BUF_LEN, &this->thisUpdate, TRUE);
|
||||
logger->log(logger, CONTROL|LEVEL1, " this update : %s", buf);
|
||||
timetoa(buf, BUF_LEN, ¤t_time, TRUE);
|
||||
logger->log(logger, CONTROL|LEVEL1, " current time: %s", buf);
|
||||
timetoa(buf, BUF_LEN, &this->nextUpdate, TRUE);
|
||||
logger->log(logger, CONTROL|LEVEL1, " next update: %s", buf);
|
||||
DBG2(" this update : %T", this->thisUpdate);
|
||||
DBG2(" current time: %T", current_time);
|
||||
DBG2(" next update: %T", this->nextUpdate);
|
||||
|
||||
if (strict && until != NULL
|
||||
&& (*until == UNDEFINED_TIME || this->nextUpdate < *until))
|
||||
if (strict && until != NULL &&
|
||||
(*until == UNDEFINED_TIME || this->nextUpdate < *until))
|
||||
{
|
||||
*until = this->nextUpdate;
|
||||
}
|
||||
if (current_time > this->nextUpdate)
|
||||
{
|
||||
return "has expired";
|
||||
logger->log(logger, CONTROL|LEVEL1, " crl is valid", buf);
|
||||
}
|
||||
DBG2(" crl is valid");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -437,38 +434,88 @@ static void destroy(private_crl_t *this)
|
||||
}
|
||||
|
||||
/**
|
||||
* log crl
|
||||
* output handler in printf()
|
||||
*/
|
||||
static void log_crl(const private_crl_t *this, logger_t *logger, bool utc, bool strict)
|
||||
static int print(FILE *stream, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
identification_t *issuer = this->issuer;
|
||||
linked_list_t *revokedCertificates = this->revokedCertificates;
|
||||
|
||||
char buf[BUF_LEN];
|
||||
|
||||
timetoa(buf, BUF_LEN, &this->installed, utc);
|
||||
logger->log(logger, CONTROL, "%s, revoked certs: %d",
|
||||
buf, revokedCertificates->get_count(revokedCertificates));
|
||||
|
||||
logger->log(logger, CONTROL, " issuer: '%D'", issuer);
|
||||
private_crl_t *this = *((private_crl_t**)(args[0]));
|
||||
bool utc = TRUE;
|
||||
int written = 0;
|
||||
time_t now;
|
||||
|
||||
timetoa(buf, BUF_LEN, &this->thisUpdate, utc);
|
||||
logger->log(logger, CONTROL, " updates: this %s", buf);
|
||||
if (info->alt)
|
||||
{
|
||||
utc = *((bool*)(args[1]));
|
||||
}
|
||||
|
||||
timetoa(buf, BUF_LEN, &this->nextUpdate, utc);
|
||||
logger->log(logger, CONTROL, " next %s %s", buf,
|
||||
check_expiry(this->nextUpdate, CRL_WARNING_INTERVAL, strict));
|
||||
if (this == NULL)
|
||||
{
|
||||
return fprintf(stream, "(null)");
|
||||
}
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
written += fprintf(stream, " issuer: %D\n", this->issuer);
|
||||
written += fprintf(stream, " installed: %#T, revoked certs: %d\n", this->installed, utc,
|
||||
this->revokedCertificates->get_count(this->revokedCertificates));
|
||||
written += fprintf(stream, " updates: this %#T\n", this->thisUpdate, utc);
|
||||
written += fprintf(stream, " next %#T ");
|
||||
if (this->nextUpdate == UNDEFINED_TIME)
|
||||
{
|
||||
written += fprintf(stream, "ok (expires never)");
|
||||
}
|
||||
else if (now > this->nextUpdate)
|
||||
{
|
||||
written += fprintf(stream, "expired (since %V)", now, this->nextUpdate);
|
||||
}
|
||||
else if (now > this->nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24)
|
||||
{
|
||||
written += fprintf(stream, "ok (expires in %V)", now, this->nextUpdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
written += fprintf(stream, "ok");
|
||||
}
|
||||
if (this->authKeyID.ptr)
|
||||
{
|
||||
written += fprintf(stream, "\n authkey: %#B", &this->authKeyID);
|
||||
}
|
||||
if (this->authKeySerialNumber.ptr)
|
||||
{
|
||||
written += fprintf(stream, "\n aserial: %#B", &this->authKeySerialNumber);
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
if (this->authKeyID.ptr != NULL)
|
||||
/**
|
||||
* arginfo handler in printf()
|
||||
*/
|
||||
static int print_arginfo(const struct printf_info *info, size_t n, int *argtypes)
|
||||
{
|
||||
if (info->alt)
|
||||
{
|
||||
chunk_to_hex(buf, BUF_LEN, this->authKeyID);
|
||||
logger->log(logger, CONTROL, " authkey: %s", buf);
|
||||
if (n > 1)
|
||||
{
|
||||
argtypes[0] = PA_INT;
|
||||
argtypes[1] = PA_INT;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
if (this->authKeySerialNumber.ptr != NULL)
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
chunk_to_hex(buf, BUF_LEN, this->authKeySerialNumber);
|
||||
logger->log(logger, CONTROL, " aserial: %s", buf);
|
||||
argtypes[0] = PA_INT;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* register printf() handlers
|
||||
*/
|
||||
static void __attribute__ ((constructor))print_register()
|
||||
{
|
||||
register_printf_function(CRL_PRINTF_SPEC, print, print_arginfo);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -494,11 +541,7 @@ crl_t *crl_create_from_chunk(chunk_t chunk)
|
||||
this->public.is_newer = (bool (*) (const crl_t*,const crl_t*))is_newer;
|
||||
this->public.verify = (bool (*) (const crl_t*,const rsa_public_key_t*))verify;
|
||||
this->public.get_status = (void (*) (const crl_t*,certinfo_t*))get_status;
|
||||
this->public.log_crl = (void (*) (const crl_t*,logger_t*,bool,bool))log_crl;
|
||||
this->public.destroy = (void (*) (crl_t*))destroy;
|
||||
|
||||
/* we do not use a per-instance logger right now, since its not always accessible */
|
||||
logger = logger_manager->get_logger(logger_manager, ASN1);
|
||||
|
||||
if (!parse_x509crl(chunk, 0, this))
|
||||
{
|
||||
|
||||
@@ -29,7 +29,13 @@
|
||||
#include <crypto/certinfo.h>
|
||||
#include <utils/identification.h>
|
||||
#include <utils/iterator.h>
|
||||
#include <utils/logger.h>
|
||||
|
||||
/**
|
||||
* printf specifier for printing crls. When using the
|
||||
* #-modifier, an additional bool argument defines if times
|
||||
* are printed in UTC.
|
||||
*/
|
||||
#define CRL_PRINTF_SPEC 'U'
|
||||
|
||||
typedef struct crl_t crl_t;
|
||||
|
||||
@@ -115,16 +121,6 @@ struct crl_t {
|
||||
* @param this crl to destroy
|
||||
*/
|
||||
void (*destroy) (crl_t *this);
|
||||
|
||||
/**
|
||||
* @brief Log x509 crl info.
|
||||
*
|
||||
* @param this crl to log
|
||||
* @param logger logger to be used
|
||||
* @param utc log dates either in UTC or local time
|
||||
* @param strict expiry of nextUpdate is fatal with strict == TRUE
|
||||
*/
|
||||
void (*log_crl) (const crl_t *this, logger_t *logger, bool utc, bool strict);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,27 +28,25 @@
|
||||
#include <crypto/crypters/des_crypter.h>
|
||||
|
||||
|
||||
/**
|
||||
* String mappings for encryption_algorithm_t.
|
||||
*/
|
||||
mapping_t encryption_algorithm_m[] = {
|
||||
{ENCR_UNDEFINED, "UNDEFINED"},
|
||||
{ENCR_DES_IV64, "DES_IV64"},
|
||||
{ENCR_DES, "DES"},
|
||||
{ENCR_3DES, "3DES"},
|
||||
{ENCR_RC5, "RC5"},
|
||||
{ENCR_IDEA, "IDEA"},
|
||||
{ENCR_CAST, "CAST"},
|
||||
{ENCR_BLOWFISH, "BLOWFISH"},
|
||||
{ENCR_3IDEA, "3IDEA"},
|
||||
{ENCR_DES_IV32, "DES_IV32"},
|
||||
{ENCR_NULL, "NULL"},
|
||||
{ENCR_AES_CBC, "AES_CBC"},
|
||||
{ENCR_AES_CTR, "AES_CTR"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
ENUM_BEGIN(encryption_algorithm_names, ENCR_UNDEFINED, ENCR_UNDEFINED,
|
||||
"UNDEFINED");
|
||||
ENUM_NEXT(encryption_algorithm_names, ENCR_DES_IV64, ENCR_DES_IV32, ENCR_UNDEFINED,
|
||||
"DES_IV64",
|
||||
"DES",
|
||||
"3DES",
|
||||
"RC5",
|
||||
"IDEA",
|
||||
"CAST",
|
||||
"BLOWFISH",
|
||||
"3IDEA",
|
||||
"DES_IV32");
|
||||
ENUM_NEXT(encryption_algorithm_names, ENCR_NULL, ENCR_AES_CTR, ENCR_DES_IV32,
|
||||
"NULL",
|
||||
"AES_CBC",
|
||||
"AES_CTR");
|
||||
ENUM_END(encryption_algorithm_names, ENCR_AES_CTR);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
crypter_t *crypter_create(encryption_algorithm_t encryption_algorithm, size_t key_size)
|
||||
|
||||
@@ -57,10 +57,10 @@ enum encryption_algorithm_t {
|
||||
ENCR_AES_CTR = 13
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for encryption_algorithm_t.
|
||||
/**
|
||||
* enum name for encryption_algorithm_t.
|
||||
*/
|
||||
extern mapping_t encryption_algorithm_m[];
|
||||
extern enum_name_t *encryption_algorithm_names;
|
||||
|
||||
|
||||
typedef struct crypter_t crypter_t;
|
||||
|
||||
@@ -23,29 +23,26 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <gmp.h>
|
||||
#include <stdio.h>
|
||||
#include <gmp.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "diffie_hellman.h"
|
||||
|
||||
#include <utils/randomizer.h>
|
||||
|
||||
|
||||
/**
|
||||
* String mappings for diffie_hellman_group_t.
|
||||
*/
|
||||
mapping_t diffie_hellman_group_m[] = {
|
||||
{MODP_NONE, "MODP_NONE"},
|
||||
{MODP_768_BIT, "MODP_768_BIT"},
|
||||
{MODP_1024_BIT, "MODP_1024_BIT"},
|
||||
{MODP_1536_BIT, "MODP_1536_BIT"},
|
||||
{MODP_2048_BIT, "MODP_2048_BIT"},
|
||||
{MODP_3072_BIT, "MODP_3072_BIT"},
|
||||
{MODP_4096_BIT, "MODP_4096_BIT"},
|
||||
{MODP_6144_BIT, "MODP_6144_BIT"},
|
||||
{MODP_8192_BIT, "MODP_8192_BIT"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
ENUM_BEGIN(diffie_hellman_group_names, MODP_NONE, MODP_1024_BIT,
|
||||
"MODP_NONE",
|
||||
"MODP_768_BIT",
|
||||
"MODP_1024_BIT");
|
||||
ENUM_NEXT(diffie_hellman_group_names, MODP_1536_BIT, MODP_1536_BIT, MODP_1024_BIT,
|
||||
"MODP_1536_BIT");
|
||||
ENUM_NEXT(diffie_hellman_group_names, MODP_2048_BIT, MODP_8192_BIT, MODP_1536_BIT,
|
||||
"MODP_2048_BIT",
|
||||
"MODP_3072_BIT",
|
||||
"MODP_4096_BIT",
|
||||
"MODP_6144_BIT",
|
||||
"MODP_8192_BIT");
|
||||
ENUM_END(diffie_hellman_group_names, MODP_8192_BIT);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,10 +50,10 @@ enum diffie_hellman_group_t {
|
||||
MODP_8192_BIT = 18
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for diffie_hellman_group_t.
|
||||
/**
|
||||
* enum name for diffie_hellman_group_t.
|
||||
*/
|
||||
extern mapping_t diffie_hellman_group_m[];
|
||||
extern enum_name_t *diffie_hellman_group_names;
|
||||
|
||||
|
||||
typedef struct diffie_hellman_t diffie_hellman_t;
|
||||
|
||||
@@ -28,18 +28,15 @@
|
||||
#include <crypto/hashers/sha2_hasher.h>
|
||||
#include <crypto/hashers/md5_hasher.h>
|
||||
|
||||
/**
|
||||
* String mappings for hash_algorithm_t.
|
||||
*/
|
||||
mapping_t hash_algorithm_m[] = {
|
||||
{HASH_MD2,"HASH_MD2"},
|
||||
{HASH_MD5,"HASH_MD5"},
|
||||
{HASH_SHA1,"HASH_SHA1"},
|
||||
{HASH_SHA256,"HASH_SHA256"},
|
||||
{HASH_SHA384,"HASH_SHA384"},
|
||||
{HASH_SHA512,"HASH_SHA512"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
ENUM(hash_algorithm_names, HASH_MD2, HASH_SHA512,
|
||||
"HASH_MD2",
|
||||
"HASH_MD5",
|
||||
"HASH_SHA1",
|
||||
"HASH_SHA256",
|
||||
"HASH_SHA384",
|
||||
"HASH_SHA512"
|
||||
);
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
|
||||
@@ -43,17 +43,17 @@ typedef enum hash_algorithm_t hash_algorithm_t;
|
||||
* @ingroup hashers
|
||||
*/
|
||||
enum hash_algorithm_t {
|
||||
HASH_MD2,
|
||||
HASH_MD2 = 0,
|
||||
/** Implemented in class md5_hasher_t */
|
||||
HASH_MD5,
|
||||
HASH_MD5 = 1,
|
||||
/** Implemented in class sha1_hasher_t */
|
||||
HASH_SHA1,
|
||||
HASH_SHA1 = 2,
|
||||
/** Implemented in class sha2_hasher_t */
|
||||
HASH_SHA256,
|
||||
HASH_SHA256 = 3,
|
||||
/** Implemented in class sha2_hasher_t */
|
||||
HASH_SHA384,
|
||||
HASH_SHA384 = 4,
|
||||
/** Implemented in class sha2_hasher_t */
|
||||
HASH_SHA512,
|
||||
HASH_SHA512 = 5,
|
||||
};
|
||||
|
||||
#define HASH_SIZE_MD2 16
|
||||
@@ -65,9 +65,9 @@ enum hash_algorithm_t {
|
||||
#define HASH_SIZE_MAX 64
|
||||
|
||||
/**
|
||||
* String mappings for hash_algorithm_t.
|
||||
* enum names for hash_algorithm_t.
|
||||
*/
|
||||
extern mapping_t hash_algorithm_m[];
|
||||
extern enum_name_t *hash_algorithm_names;
|
||||
|
||||
|
||||
typedef struct hasher_t hasher_t;
|
||||
|
||||
@@ -27,18 +27,14 @@
|
||||
#include <crypto/hashers/hasher.h>
|
||||
#include <crypto/prfs/hmac_prf.h>
|
||||
|
||||
|
||||
/**
|
||||
* String mappings for encryption_algorithm_t.
|
||||
*/
|
||||
mapping_t pseudo_random_function_m[] = {
|
||||
{PRF_UNDEFINED, "PRF_UNDEFINED"},
|
||||
{PRF_HMAC_MD5, "PRF_HMAC_MD5"},
|
||||
{PRF_HMAC_SHA1, "PRF_HMAC_SHA1"},
|
||||
{PRF_HMAC_TIGER, "PRF_HMAC_TIGER"},
|
||||
{PRF_AES128_CBC, "PRF_AES128_CBC"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
ENUM_BEGIN(pseudo_random_function_names, PRF_UNDEFINED, PRF_UNDEFINED,
|
||||
"PRF_UNDEFINED");
|
||||
ENUM_NEXT(pseudo_random_function_names, PRF_HMAC_MD5, PRF_AES128_CBC, PRF_UNDEFINED,
|
||||
"PRF_HMAC_MD5",
|
||||
"PRF_HMAC_SHA1",
|
||||
"PRF_HMAC_TIGER",
|
||||
"PRF_AES128_CBC");
|
||||
ENUM_END(pseudo_random_function_names, PRF_AES128_CBC);
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
|
||||
@@ -47,10 +47,10 @@ enum pseudo_random_function_t {
|
||||
PRF_AES128_CBC = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for encryption_algorithm_t.
|
||||
/**
|
||||
* enum name for encryption_algorithm_t.
|
||||
*/
|
||||
extern mapping_t pseudo_random_function_m[];
|
||||
extern enum_name_t *pseudo_random_function_names;
|
||||
|
||||
|
||||
typedef struct prf_t prf_t;
|
||||
|
||||
@@ -25,19 +25,15 @@
|
||||
|
||||
#include <crypto/signers/hmac_signer.h>
|
||||
|
||||
/**
|
||||
* String mappings for integrity_algorithm_t.
|
||||
*/
|
||||
mapping_t integrity_algorithm_m[] = {
|
||||
{AUTH_UNDEFINED, "UNDEFINED"},
|
||||
{AUTH_HMAC_MD5_96, "HMAC_MD5_96"},
|
||||
{AUTH_HMAC_SHA1_96, "HMAC_SHA1_96"},
|
||||
{AUTH_DES_MAC, "DES_MAC"},
|
||||
{AUTH_KPDK_MD5, "KPDK_MD5"},
|
||||
{AUTH_AES_XCBC_96, "AES_XCBC_96"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
ENUM_BEGIN(integrity_algorithm_names, AUTH_UNDEFINED, AUTH_UNDEFINED,
|
||||
"UNDEFINED");
|
||||
ENUM_NEXT(integrity_algorithm_names, AUTH_HMAC_MD5_96, AUTH_AES_XCBC_96, AUTH_UNDEFINED,
|
||||
"HMAC_MD5_96",
|
||||
"HMAC_SHA1_96",
|
||||
"DES_MAC",
|
||||
"KPDK_MD5",
|
||||
"AES_XCBC_96");
|
||||
ENUM_END(integrity_algorithm_names, AUTH_AES_XCBC_96);
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
|
||||
@@ -49,10 +49,10 @@ enum integrity_algorithm_t {
|
||||
AUTH_AES_XCBC_96 = 5
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for integrity_algorithm_t.
|
||||
/**
|
||||
* enum names for integrity_algorithm_t.
|
||||
*/
|
||||
extern mapping_t integrity_algorithm_m[];
|
||||
extern enum_name_t *integrity_algorithm_names;
|
||||
|
||||
|
||||
typedef struct signer_t signer_t;
|
||||
|
||||
+163
-157
@@ -24,22 +24,21 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <printf.h>
|
||||
|
||||
#include "x509.h"
|
||||
|
||||
#include <types.h>
|
||||
#include <library.h>
|
||||
#include <definitions.h>
|
||||
#include <asn1/oid.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/pem.h>
|
||||
#include <utils/logger_manager.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <utils/identification.h>
|
||||
|
||||
#define CERT_WARNING_INTERVAL 30 /* days */
|
||||
|
||||
static logger_t *logger;
|
||||
|
||||
/**
|
||||
* Different kinds of generalNames
|
||||
*/
|
||||
@@ -422,7 +421,7 @@ static bool parse_basicConstraints(chunk_t blob, int level0)
|
||||
if (objectID == BASIC_CONSTRAINTS_CA)
|
||||
{
|
||||
isCA = object.len && *object.ptr;
|
||||
logger->log(logger, CONTROL|LEVEL2, " %s", isCA ? "TRUE" : "FALSE");
|
||||
DBG2(" %s", isCA ? "TRUE" : "FALSE");
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
@@ -519,7 +518,7 @@ static identification_t *parse_generalName(chunk_t blob, int level0)
|
||||
if (id_type != ID_ANY)
|
||||
{
|
||||
identification_t *gn = identification_create_from_encoding(id_type, object);
|
||||
logger->log(logger, CONTROL|LEVEL2, " '%D'", gn);
|
||||
DBG2(" '%D'", gn);
|
||||
return gn;
|
||||
}
|
||||
objectID++;
|
||||
@@ -670,7 +669,7 @@ static void parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessL
|
||||
{
|
||||
if (asn1_length(&object) == ASN1_INVALID_LENGTH)
|
||||
return;
|
||||
logger->log(logger, CONTROL|LEVEL2, " '%.*s'",(int)object.len, object.ptr);
|
||||
DBG2(" '%.*s'",(int)object.len, object.ptr);
|
||||
/* only HTTP(S) URIs accepted */
|
||||
if (strncasecmp(object.ptr, "http", 4) == 0)
|
||||
{
|
||||
@@ -678,7 +677,7 @@ static void parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessL
|
||||
return;
|
||||
}
|
||||
}
|
||||
logger->log(logger, ERROR|LEVEL2, "ignoring OCSP InfoAccessLocation with unkown protocol");
|
||||
DBG2("ignoring OCSP InfoAccessLocation with unkown protocol");
|
||||
break;
|
||||
default:
|
||||
/* unkown accessMethod, ignoring */
|
||||
@@ -779,7 +778,7 @@ bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
|
||||
break;
|
||||
case X509_OBJ_VERSION:
|
||||
cert->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
|
||||
logger->log(logger, CONTROL|LEVEL2, " v%d", cert->version);
|
||||
DBG2(" v%d", cert->version);
|
||||
break;
|
||||
case X509_OBJ_SERIAL_NUMBER:
|
||||
cert->serialNumber = object;
|
||||
@@ -789,7 +788,7 @@ bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
|
||||
break;
|
||||
case X509_OBJ_ISSUER:
|
||||
cert->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
|
||||
logger->log(logger, CONTROL|LEVEL1, " '%D'", cert->issuer);
|
||||
DBG2(" '%D'", cert->issuer);
|
||||
break;
|
||||
case X509_OBJ_NOT_BEFORE:
|
||||
cert->notBefore = parse_time(object, level);
|
||||
@@ -799,12 +798,12 @@ bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
|
||||
break;
|
||||
case X509_OBJ_SUBJECT:
|
||||
cert->subject = identification_create_from_encoding(ID_DER_ASN1_DN, object);
|
||||
logger->log(logger, CONTROL|LEVEL1, " '%D'", cert->subject);
|
||||
DBG2(" '%D'", cert->subject);
|
||||
break;
|
||||
case X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM:
|
||||
if (parse_algorithmIdentifier(object, level, NULL) != OID_RSA_ENCRYPTION)
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, " unsupported public key algorithm");
|
||||
DBG2(" unsupported public key algorithm");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
@@ -816,7 +815,7 @@ bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, " invalid RSA public key format");
|
||||
DBG2(" invalid RSA public key format");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
@@ -828,7 +827,7 @@ bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
|
||||
break;
|
||||
case X509_OBJ_CRITICAL:
|
||||
critical = object.len && *object.ptr;
|
||||
logger->log(logger, ERROR|LEVEL2, " %s", critical ? "TRUE" : "FALSE");
|
||||
DBG2(" %s", critical ? "TRUE" : "FALSE");
|
||||
break;
|
||||
case X509_OBJ_EXTN_VALUE:
|
||||
{
|
||||
@@ -886,27 +885,26 @@ bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
|
||||
*/
|
||||
static err_t is_valid(const private_x509_t *this, time_t *until)
|
||||
{
|
||||
char buf[TIMETOA_BUF];
|
||||
|
||||
time_t current_time = time(NULL);
|
||||
|
||||
timetoa(buf, BUF_LEN, &this->notBefore, TRUE);
|
||||
logger->log(logger, CONTROL|LEVEL1, " not before : %s", buf);
|
||||
timetoa(buf, BUF_LEN, ¤t_time, TRUE);
|
||||
logger->log(logger, CONTROL|LEVEL1, " current time: %s", buf);
|
||||
timetoa(buf, BUF_LEN, &this->notAfter, TRUE);
|
||||
logger->log(logger, CONTROL|LEVEL1, " not after : %s", buf);
|
||||
DBG2(" not before : %T", this->notBefore);
|
||||
DBG2(" current time: %T", current_time);
|
||||
DBG2(" not after : %T", this->notAfter);
|
||||
|
||||
if (until != NULL
|
||||
&& (*until == UNDEFINED_TIME || this->notAfter < *until))
|
||||
if (until != NULL &&
|
||||
(*until == UNDEFINED_TIME || this->notAfter < *until))
|
||||
{
|
||||
*until = this->notAfter;
|
||||
}
|
||||
if (current_time < this->notBefore)
|
||||
{
|
||||
return "is not valid yet";
|
||||
}
|
||||
if (current_time > this->notAfter)
|
||||
{
|
||||
return "has expired";
|
||||
logger->log(logger, CONTROL|LEVEL1, " certificate is valid", buf);
|
||||
}
|
||||
DBG2(" certificate is valid");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1049,7 +1047,144 @@ static bool verify(const private_x509_t *this, const rsa_public_key_t *signer)
|
||||
}
|
||||
|
||||
/**
|
||||
* destroy
|
||||
* output handler in printf()
|
||||
*/
|
||||
static int print(FILE *stream, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
private_x509_t *this = *((private_x509_t**)(args[0]));
|
||||
iterator_t *iterator;
|
||||
identification_t *san;
|
||||
chunk_t chunk;
|
||||
bool utc = TRUE;
|
||||
int written = 0;
|
||||
|
||||
if (info->alt)
|
||||
{
|
||||
utc = *((bool*)(args[1]));
|
||||
}
|
||||
|
||||
if (this == NULL)
|
||||
{
|
||||
return fprintf(stream, "(null)");
|
||||
}
|
||||
|
||||
/* determine the current time */
|
||||
time_t now = time(NULL);
|
||||
|
||||
written += fprintf(stream, " subject: %D\n", this->subject);
|
||||
if (this->subjectAltNames->get_count(this->subjectAltNames) > 0)
|
||||
{
|
||||
written += fprintf(stream, " altNames: ");
|
||||
iterator = this->subjectAltNames->create_iterator(this->subjectAltNames, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)&san))
|
||||
{
|
||||
written += fprintf(stream, "%D, ", san);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
written += fprintf(stream, "\n");
|
||||
}
|
||||
written += fprintf(stream, " issuer: '%D'\n", this->issuer);
|
||||
written += fprintf(stream, " serial: '%#B'\n", &this->serialNumber);
|
||||
written += fprintf(stream, " installed: %#T\n", this->installed, utc);
|
||||
|
||||
written += fprintf(stream, " validity: not before %#T, ",
|
||||
this->notBefore, utc);
|
||||
if (now < this->notBefore)
|
||||
{
|
||||
written += fprintf(stream, "not valid yet (valid in %V)\n",
|
||||
now, this->notBefore);
|
||||
}
|
||||
else
|
||||
{
|
||||
written += fprintf(stream, "ok\n");
|
||||
}
|
||||
|
||||
written += fprintf(stream, " not after %#T, ",
|
||||
this->notAfter, utc);
|
||||
if (now > this->notAfter)
|
||||
{
|
||||
written += fprintf(stream, "expired (since %V)\n", now, this->notAfter);
|
||||
}
|
||||
else
|
||||
{
|
||||
written += fprintf(stream, "ok");
|
||||
if (now > this->notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
|
||||
{
|
||||
written += fprintf(stream, " (expires in %V)", now, this->notAfter);
|
||||
}
|
||||
written += fprintf(stream, " \n");
|
||||
}
|
||||
|
||||
chunk = this->public_key->get_keyid(this->public_key);
|
||||
written += fprintf(stream, " keyid: %#B\n", &chunk);
|
||||
if (this->subjectKeyID.ptr)
|
||||
{
|
||||
written += fprintf(stream, " subjkey: %#B\n", &this->subjectKeyID);
|
||||
}
|
||||
if (this->authKeyID.ptr)
|
||||
{
|
||||
written += fprintf(stream, " authkey: %#B\n", &this->authKeyID);
|
||||
}
|
||||
if (this->authKeySerialNumber.ptr)
|
||||
{
|
||||
written += fprintf(stream, " aserial: %#B\n", &this->authKeySerialNumber);
|
||||
}
|
||||
|
||||
written += fprintf(stream, " pubkey: RSA %d bits", BITS_PER_BYTE *
|
||||
this->public_key->get_keysize(this->public_key));
|
||||
written += fprintf(stream, ", status %N",
|
||||
cert_status_names, this->status);
|
||||
|
||||
switch (this->status)
|
||||
{
|
||||
case CERT_GOOD:
|
||||
written += fprintf(stream, " until %#T", this->until, utc);
|
||||
break;
|
||||
case CERT_REVOKED:
|
||||
written += fprintf(stream, " on %#T", this->until, utc);
|
||||
break;
|
||||
case CERT_UNKNOWN:
|
||||
case CERT_UNDEFINED:
|
||||
case CERT_UNTRUSTED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
/**
|
||||
* arginfo handler in printf()
|
||||
*/
|
||||
static int print_arginfo(const struct printf_info *info, size_t n, int *argtypes)
|
||||
{
|
||||
if (info->alt)
|
||||
{
|
||||
if (n > 1)
|
||||
{
|
||||
argtypes[0] = PA_INT;
|
||||
argtypes[1] = PA_INT;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
argtypes[0] = PA_INT;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* register printf() handlers
|
||||
*/
|
||||
static void __attribute__ ((constructor))print_register()
|
||||
{
|
||||
register_printf_function(X509_PRINTF_SPEC, print, print_arginfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements x509_t.destroy
|
||||
*/
|
||||
static void destroy(private_x509_t *this)
|
||||
{
|
||||
@@ -1066,138 +1201,13 @@ static void destroy(private_x509_t *this)
|
||||
}
|
||||
this->crlDistributionPoints->destroy(this->crlDistributionPoints);
|
||||
|
||||
if (this->issuer)
|
||||
this->issuer->destroy(this->issuer);
|
||||
|
||||
if (this->subject)
|
||||
this->subject->destroy(this->subject);
|
||||
|
||||
if (this->public_key)
|
||||
this->public_key->destroy(this->public_key);
|
||||
|
||||
DESTROY_IF(this->issuer);
|
||||
DESTROY_IF(this->subject);
|
||||
DESTROY_IF(this->public_key);
|
||||
free(this->certificate.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if the expiration date has been reached and warns during the
|
||||
* warning_interval of the imminent expiration.
|
||||
* strict=TRUE declares a fatal error, strict=FALSE issues a warning upon expiry.
|
||||
*/
|
||||
char* check_expiry(time_t expiration_date, int warning_interval, bool strict)
|
||||
{
|
||||
int time_left;
|
||||
|
||||
if (expiration_date == UNDEFINED_TIME)
|
||||
{
|
||||
return "ok (expires never)";
|
||||
}
|
||||
time_left = (expiration_date - time(NULL));
|
||||
if (time_left < 0)
|
||||
{
|
||||
return strict? "fatal (expired)" : "warning (expired)";
|
||||
}
|
||||
|
||||
{
|
||||
static char buf[35];
|
||||
const char* unit = "second";
|
||||
|
||||
if (time_left > 86400*warning_interval)
|
||||
return "ok";
|
||||
|
||||
if (time_left > 172800)
|
||||
{
|
||||
time_left /= 86400;
|
||||
unit = "day";
|
||||
}
|
||||
else if (time_left > 7200)
|
||||
{
|
||||
time_left /= 3600;
|
||||
unit = "hour";
|
||||
}
|
||||
else if (time_left > 120)
|
||||
{
|
||||
time_left /= 60;
|
||||
unit = "minute";
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "warning (expires in %d %s%s)", time_left, unit, (time_left == 1)?"":"s");
|
||||
|
||||
/* TODO: This is not thread save and may result in corrupted strings. Rewrite this! */
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* log certificate
|
||||
*/
|
||||
static void log_certificate(const private_x509_t *this, logger_t *logger, bool utc, bool has_key)
|
||||
{
|
||||
identification_t *subject = this->subject;
|
||||
identification_t *issuer = this->issuer;
|
||||
rsa_public_key_t *pubkey = this->public_key;
|
||||
|
||||
char buf[BUF_LEN];
|
||||
char time_buf[TIMETOA_BUF];
|
||||
|
||||
/* determine the current time */
|
||||
time_t now = time(NULL);
|
||||
|
||||
timetoa(time_buf, TIMETOA_BUF, &this->installed, utc);
|
||||
logger->log(logger, CONTROL, "%s", time_buf);
|
||||
logger->log(logger, CONTROL, " subject: '%D'", subject);
|
||||
logger->log(logger, CONTROL, " issuer: '%D'", issuer);
|
||||
|
||||
chunk_to_hex(buf, BUF_LEN, this->serialNumber);
|
||||
logger->log(logger, CONTROL, " serial: %s", buf);
|
||||
|
||||
timetoa(time_buf, TIMETOA_BUF, &this->notBefore, utc);
|
||||
logger->log(logger, CONTROL, " validity: not before %s %s", time_buf,
|
||||
(this->notBefore < now)? "ok":"fatal (not valid yet)");
|
||||
|
||||
timetoa(time_buf, TIMETOA_BUF, &this->notAfter, utc);
|
||||
logger->log(logger, CONTROL, " not after %s %s", time_buf,
|
||||
check_expiry(this->notAfter, CERT_WARNING_INTERVAL, TRUE));
|
||||
|
||||
timetoa(time_buf, TIMETOA_BUF, &this->until, utc);
|
||||
switch (this->status)
|
||||
{
|
||||
case CERT_GOOD:
|
||||
snprintf(buf, BUF_LEN, " until %s", time_buf);
|
||||
break;
|
||||
case CERT_REVOKED:
|
||||
snprintf(buf, BUF_LEN, " on %s", time_buf);
|
||||
break;
|
||||
case CERT_UNKNOWN:
|
||||
case CERT_UNDEFINED:
|
||||
case CERT_UNTRUSTED:
|
||||
default:
|
||||
*buf = '\0';
|
||||
}
|
||||
logger->log(logger, CONTROL, " pubkey: RSA %d bits%s, status %s%s",
|
||||
BITS_PER_BYTE * pubkey->get_keysize(pubkey),
|
||||
has_key? ", has private key":"",
|
||||
enum_name(&cert_status_names, this->status), buf);
|
||||
|
||||
chunk_to_hex(buf, BUF_LEN, pubkey->get_keyid(pubkey));
|
||||
logger->log(logger, CONTROL, " keyid: %s", buf);
|
||||
|
||||
if (this->subjectKeyID.ptr != NULL)
|
||||
{
|
||||
chunk_to_hex(buf, BUF_LEN, this->subjectKeyID);
|
||||
logger->log(logger, CONTROL, " subjkey: %s", buf);
|
||||
}
|
||||
if (this->authKeyID.ptr != NULL)
|
||||
{
|
||||
chunk_to_hex(buf, BUF_LEN, this->authKeyID);
|
||||
logger->log(logger, CONTROL, " authkey: %s", buf);
|
||||
}
|
||||
if (this->authKeySerialNumber.ptr != NULL)
|
||||
{
|
||||
chunk_to_hex(buf, BUF_LEN, this->authKeySerialNumber);
|
||||
logger->log(logger, CONTROL, " aserial: %s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
@@ -1235,10 +1245,6 @@ x509_t *x509_create_from_chunk(chunk_t chunk)
|
||||
this->public.get_status = (cert_status_t (*) (const x509_t*))get_status;
|
||||
this->public.verify = (bool (*) (const x509_t*,const rsa_public_key_t*))verify;
|
||||
this->public.destroy = (void (*) (x509_t*))destroy;
|
||||
this->public.log_certificate = (void (*) (const x509_t*,logger_t*,bool,bool))log_certificate;
|
||||
|
||||
/* we do not use a per-instance logger right now, since its not always accessible */
|
||||
logger = logger_manager->get_logger(logger_manager, ASN1);
|
||||
|
||||
if (!parse_x509cert(chunk, 0, this))
|
||||
{
|
||||
|
||||
@@ -29,8 +29,13 @@
|
||||
#include <crypto/certinfo.h>
|
||||
#include <utils/identification.h>
|
||||
#include <utils/iterator.h>
|
||||
#include <utils/logger.h>
|
||||
|
||||
/**
|
||||
* printf specifier for printing certificates. When using the
|
||||
* #-modifier, an additional bool argument defines if times
|
||||
* are printed in UTC.
|
||||
*/
|
||||
#define X509_PRINTF_SPEC 'Q'
|
||||
|
||||
typedef struct x509_t x509_t;
|
||||
|
||||
@@ -203,16 +208,6 @@ struct x509_t {
|
||||
* @param this certificate to destroy
|
||||
*/
|
||||
void (*destroy) (x509_t *this);
|
||||
|
||||
/**
|
||||
* @brief Log x509 certificate info.
|
||||
*
|
||||
* @param this certificate to log
|
||||
* @param logger logger to be used
|
||||
* @param utc log dates either in UTC or local time
|
||||
* @param has_key a matching private key is available
|
||||
*/
|
||||
void (*log_certificate) (const x509_t *this, logger_t *logger, bool utc, bool has_key);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,39 +21,65 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <printf.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
char *mapping_find(mapping_t * maps, int value)
|
||||
{
|
||||
int i = 0;
|
||||
while (maps[i].value != MAPPING_END)
|
||||
{
|
||||
if (maps[i].value == value)
|
||||
{
|
||||
return maps[i].string;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return "INVALID MAPPING";
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
const char *enum_name(enum_names *ed, unsigned long val)
|
||||
static char *enum_name(enum_name_t *e, long val)
|
||||
{
|
||||
enum_names *p;
|
||||
|
||||
for (p = ed; p != NULL; p = p->en_next_range)
|
||||
do
|
||||
{
|
||||
if (p->en_first <= val && val <= p->en_last)
|
||||
return p->en_names[val - p->en_first];
|
||||
if (val >= e->first && val <= e->last)
|
||||
{
|
||||
return e->names[val - e->first];
|
||||
}
|
||||
}
|
||||
while ((e = e->next));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* output handler in printf() for enum names
|
||||
*/
|
||||
static int print_enum(FILE *stream, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
enum_name_t *ed = *((void**)(args[0]));
|
||||
long val = *((size_t*)(args[1]));
|
||||
char *name;
|
||||
|
||||
name = enum_name(ed, val);
|
||||
if (name == NULL)
|
||||
{
|
||||
return fprintf(stream, "(unknown enum value: %ld)", val);
|
||||
}
|
||||
return fprintf(stream, "%s", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* arginfo handler in printf() for enum names
|
||||
*/
|
||||
static int print_enum_arginfo(const struct printf_info *info, size_t n, int *argtypes)
|
||||
{
|
||||
if (n > 1)
|
||||
{
|
||||
/* enum_names ptr */
|
||||
argtypes[0] = PA_POINTER;
|
||||
/* value */
|
||||
argtypes[1] = PA_INT;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* register printf() handlers for enum names
|
||||
*/
|
||||
static void __attribute__ ((constructor))print_register()
|
||||
{
|
||||
register_printf_function(ENUM_PRINTF_SPEC, print_enum, print_enum_arginfo);
|
||||
}
|
||||
|
||||
@@ -27,16 +27,12 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define BITS_PER_BYTE 8
|
||||
#define RSA_MIN_OCTETS (1024 / BITS_PER_BYTE)
|
||||
#define RSA_MIN_OCTETS_UGH "RSA modulus too small for security: less than 1024 bits"
|
||||
#define RSA_MAX_OCTETS (8192 / BITS_PER_BYTE)
|
||||
#define RSA_MAX_OCTETS_UGH "RSA modulus too large: more than 8192 bits"
|
||||
#define BITS_PER_BYTE 8
|
||||
|
||||
/**
|
||||
* Default length for various auxiliary text buffers
|
||||
*/
|
||||
#define BUF_LEN 512
|
||||
#define BUF_LEN 512
|
||||
|
||||
/**
|
||||
* Macro compares two strings for equality
|
||||
@@ -78,55 +74,35 @@
|
||||
*/
|
||||
#define ASSIGN(method, function) (method = (typeof(method))function)
|
||||
|
||||
/**
|
||||
* printf() specifier to resolf enum names, see enum_names
|
||||
*/
|
||||
#define ENUM_PRINTF_SPEC 'N'
|
||||
|
||||
typedef struct enum_name_t enum_name_t;
|
||||
|
||||
/**
|
||||
* Mapping entry which defines the end of a mapping_t array.
|
||||
* Struct to store names for enums. Use the convenience macros
|
||||
* to define these.
|
||||
* For a single range, use:
|
||||
* ENUM(name, first, last, string1, string2, ...)
|
||||
*
|
||||
* For multiple ranges, use:
|
||||
* ENUM_BEGIN(name, first, last, string1, string2, ...)
|
||||
* ENUM_NEXT(name, first, last, last_from_previous, string3, ...)
|
||||
* ENUM_NEXT(name, first, last, last_from_previous, string4, ...)
|
||||
* ENUM_END(name, last_from_previous)
|
||||
*/
|
||||
#define MAPPING_END (-1)
|
||||
|
||||
typedef struct mapping_t mapping_t;
|
||||
|
||||
/**
|
||||
* @brief Mapping entry, where enum-to-string mappings are stored.
|
||||
*/
|
||||
struct mapping_t
|
||||
{
|
||||
/**
|
||||
* Enumeration value.
|
||||
*/
|
||||
int value;
|
||||
|
||||
/**
|
||||
* Mapped string.
|
||||
*/
|
||||
char *string;
|
||||
struct enum_name_t {
|
||||
long first;
|
||||
long last;
|
||||
enum_name_t *next;
|
||||
char *names[];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Find a mapping_string in the mapping[].
|
||||
*
|
||||
* @param mappings mappings array
|
||||
* @param value enum-value to get the string from
|
||||
*
|
||||
*/
|
||||
char *mapping_find(mapping_t *mappings, int value);
|
||||
|
||||
/**
|
||||
* @brief Describes an enumeration
|
||||
* enum_name() returns the name of an enum value, or NULL if invalid.
|
||||
*/
|
||||
typedef const struct enum_names enum_names;
|
||||
|
||||
struct enum_names {
|
||||
unsigned long en_first; /* first value in range */
|
||||
unsigned long en_last; /* last value in range (inclusive) */
|
||||
const char *const *en_names;
|
||||
enum_names *en_next_range; /* descriptor of next range */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Returns the name of an enum value, or NULL if invalid
|
||||
*/
|
||||
const char *enum_name(enum_names *ed, unsigned long val);
|
||||
#define ENUM_BEGIN(name, first, last, ...) static enum_name_t name##last = {first, last, NULL, { __VA_ARGS__ }}
|
||||
#define ENUM_NEXT(name, first, last, prev, ...) static enum_name_t name##last = {first, last, &name##prev, { __VA_ARGS__ }}
|
||||
#define ENUM_END(name, prev) enum_name_t *name = &name##prev;
|
||||
#define ENUM(name, first, last, ...) ENUM_BEGIN(name, first, last, __VA_ARGS__); ENUM_END(name, last)
|
||||
|
||||
#endif /*DEFINITIONS_H_*/
|
||||
|
||||
+15
-16
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @file library.c
|
||||
*
|
||||
*
|
||||
* @brief Library (de-)initialization.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -21,23 +21,22 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <utils/logger_manager.h>
|
||||
#include <utils/leak_detective.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "library.h"
|
||||
|
||||
/**
|
||||
* Called whenever the library is linked from a process
|
||||
* default dbg function which printf all to stderr
|
||||
*/
|
||||
void __attribute__ ((constructor)) library_init(void)
|
||||
static void dbg_stderr(int level, char *fmt, ...)
|
||||
{
|
||||
logger_manager_init();
|
||||
leak_detective_init();
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the library is unlinked from a process
|
||||
*/
|
||||
void __attribute__ ((destructor)) library_cleanup(void)
|
||||
{
|
||||
leak_detective_cleanup();
|
||||
logger_manager_cleanup();
|
||||
}
|
||||
void (*dbg) (int level, char *fmt, ...) = dbg_stderr;
|
||||
|
||||
@@ -84,17 +84,25 @@
|
||||
*
|
||||
* Symmetric signing algorithms,
|
||||
* used to ensure message integrity.
|
||||
*
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup utils utils
|
||||
*
|
||||
*
|
||||
* Generic helper classes.
|
||||
*
|
||||
*
|
||||
* @ingroup libstrongswan
|
||||
*/
|
||||
|
||||
/** debug macros, they call the dbg function hook */
|
||||
#define DBG1(fmt, ...) dbg(1, fmt, ##__VA_ARGS__)
|
||||
#define DBG2(fmt, ...) dbg(2, fmt, ##__VA_ARGS__)
|
||||
#define DBG3(fmt, ...) dbg(3, fmt, ##__VA_ARGS__)
|
||||
#define DBG4(fmt, ...) dbg(4, fmt, ##__VA_ARGS__)
|
||||
|
||||
/** dbg function hook, uses stderr logger by default */
|
||||
extern void (*dbg) (int level, char *fmt, ...);
|
||||
|
||||
#endif /* LIBRARY_H_ */
|
||||
|
||||
+239
-178
@@ -30,24 +30,20 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
ENUM(status_names, SUCCESS, DESTROY_ME,
|
||||
"SUCCESS",
|
||||
"FAILED",
|
||||
"OUT_OF_RES",
|
||||
"ALREADY_DONE",
|
||||
"NOT_SUPPORTED",
|
||||
"INVALID_ARG",
|
||||
"NOT_FOUND",
|
||||
"PARSE_ERROR",
|
||||
"VERIFY_ERROR",
|
||||
"INVALID_STATE",
|
||||
"DESTROY_ME",
|
||||
);
|
||||
|
||||
/**
|
||||
* String mappings for type status_t.
|
||||
*/
|
||||
mapping_t status_m[] = {
|
||||
{SUCCESS, "SUCCESS"},
|
||||
{FAILED, "FAILED"},
|
||||
{OUT_OF_RES, "OUT_OF_RES"},
|
||||
{ALREADY_DONE, "ALREADY_DONE"},
|
||||
{NOT_SUPPORTED, "NOT_SUPPORTED"},
|
||||
{INVALID_ARG, "INVALID_ARG"},
|
||||
{NOT_FOUND, "NOT_FOUND"},
|
||||
{PARSE_ERROR, "PARSE_ERROR"},
|
||||
{VERIFY_ERROR, "VERIFY_ERROR"},
|
||||
{INVALID_STATE, "INVALID_STATE"},
|
||||
{DESTROY_ME, "DESTROY_ME"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
* Empty chunk.
|
||||
@@ -159,151 +155,6 @@ bool chunk_equals_or_null(chunk_t a, chunk_t b)
|
||||
return a.len == b.len && memeq(a.ptr, b.ptr, a.len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
void chunk_to_hex(char *buf, size_t buflen, chunk_t chunk)
|
||||
{
|
||||
bool first = TRUE;
|
||||
|
||||
buflen--; /* reserve space for null termination */
|
||||
|
||||
while (chunk.len > 0 && buflen > 2)
|
||||
{
|
||||
static char hexdig[] = "0123456789abcdef";
|
||||
|
||||
if (first)
|
||||
{
|
||||
first = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*buf++ = ':'; buflen--;
|
||||
}
|
||||
*buf++ = hexdig[(*chunk.ptr >> 4) & 0x0f];
|
||||
*buf++ = hexdig[ *chunk.ptr++ & 0x0f];
|
||||
buflen -= 2; chunk.len--;
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of bytes per line to dump raw data
|
||||
*/
|
||||
#define BYTES_PER_LINE 16
|
||||
|
||||
/**
|
||||
* output handler in printf() for byte ranges
|
||||
*/
|
||||
static int print_bytes(FILE *stream, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
char *bytes = *((void**)(args[0]));
|
||||
int len = *((size_t*)(args[1]));
|
||||
|
||||
char buffer[BYTES_PER_LINE * 3];
|
||||
char ascii_buffer[BYTES_PER_LINE + 1];
|
||||
char *buffer_pos = buffer;
|
||||
char *bytes_pos = bytes;
|
||||
char *bytes_roof = bytes + len;
|
||||
int line_start = 0;
|
||||
int i = 0;
|
||||
int total_written = 0;
|
||||
|
||||
total_written = fprintf(stream, "=> %d bytes @ %p", len, bytes);
|
||||
if (total_written < 0)
|
||||
{
|
||||
return total_written;
|
||||
}
|
||||
|
||||
while (bytes_pos < bytes_roof)
|
||||
{
|
||||
static char hexdig[] = "0123456789ABCDEF";
|
||||
|
||||
*buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
|
||||
*buffer_pos++ = hexdig[ *bytes_pos & 0xF];
|
||||
|
||||
ascii_buffer[i++] =
|
||||
(*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
|
||||
|
||||
if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
|
||||
{
|
||||
int padding = 3 * (BYTES_PER_LINE - i);
|
||||
int written;
|
||||
|
||||
while (padding--)
|
||||
{
|
||||
*buffer_pos++ = ' ';
|
||||
}
|
||||
*buffer_pos++ = '\0';
|
||||
ascii_buffer[i] = '\0';
|
||||
|
||||
written = fprintf(stream, "\n%4d: %s %s",
|
||||
line_start, buffer, ascii_buffer);
|
||||
if (written < 0)
|
||||
{
|
||||
return written;
|
||||
}
|
||||
total_written += written;
|
||||
|
||||
buffer_pos = buffer;
|
||||
line_start += BYTES_PER_LINE;
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer_pos++ = ' ';
|
||||
}
|
||||
}
|
||||
return total_written;
|
||||
}
|
||||
|
||||
/**
|
||||
* output handler in printf() for chunks
|
||||
*/
|
||||
static int print_chunk(FILE *stream, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
chunk_t *chunk = *((chunk_t**)(args[0]));
|
||||
|
||||
const void *new_args[] = {&chunk->ptr, &chunk->len};
|
||||
return print_bytes(stream, info, new_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* arginfo handler in printf() for chunks
|
||||
*/
|
||||
static int print_chunk_arginfo(const struct printf_info *info, size_t n, int *argtypes)
|
||||
{
|
||||
if (n > 0)
|
||||
{
|
||||
argtypes[0] = PA_POINTER;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* arginfo handler in printf() for byte ranges
|
||||
*/
|
||||
static int print_bytes_arginfo(const struct printf_info *info, size_t n, int *argtypes)
|
||||
{
|
||||
if (n > 1)
|
||||
{
|
||||
argtypes[0] = PA_POINTER;
|
||||
argtypes[1] = PA_INT;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* register printf() handlers for chunk and byte ranges
|
||||
*/
|
||||
static void __attribute__ ((constructor))print_register()
|
||||
{
|
||||
register_printf_function(CHUNK_PRINTF_SPEC, print_chunk, print_chunk_arginfo);
|
||||
register_printf_function(BYTES_PRINTF_SPEC, print_bytes, print_bytes_arginfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
@@ -354,27 +205,237 @@ bool ref_put(refcount_t *ref)
|
||||
return !more_refs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Names of the months used by timetoa()
|
||||
/**
|
||||
* Number of bytes per line to dump raw data
|
||||
*/
|
||||
static const char* months[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
#define BYTES_PER_LINE 16
|
||||
|
||||
/*
|
||||
* Described in header file
|
||||
/**
|
||||
* output handler in printf() for byte ranges
|
||||
*/
|
||||
void timetoa(char *buf, size_t buflen, const time_t *time, bool utc)
|
||||
static int print_bytes(FILE *stream, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
if (*time == UNDEFINED_TIME)
|
||||
snprintf(buf, buflen, "--- -- --:--:--%s----", (utc)?" UTC ":" ");
|
||||
char *bytes = *((void**)(args[0]));
|
||||
int len = *((size_t*)(args[1]));
|
||||
|
||||
char buffer[BYTES_PER_LINE * 3];
|
||||
char ascii_buffer[BYTES_PER_LINE + 1];
|
||||
char *buffer_pos = buffer;
|
||||
char *bytes_pos = bytes;
|
||||
char *bytes_roof = bytes + len;
|
||||
int line_start = 0;
|
||||
int i = 0;
|
||||
int written = 0;
|
||||
|
||||
written += fprintf(stream, "=> %d bytes @ %p", len, bytes);
|
||||
|
||||
while (bytes_pos < bytes_roof)
|
||||
{
|
||||
static char hexdig[] = "0123456789ABCDEF";
|
||||
|
||||
*buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
|
||||
*buffer_pos++ = hexdig[ *bytes_pos & 0xF];
|
||||
|
||||
ascii_buffer[i++] =
|
||||
(*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
|
||||
|
||||
if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
|
||||
{
|
||||
int padding = 3 * (BYTES_PER_LINE - i);
|
||||
int written;
|
||||
|
||||
while (padding--)
|
||||
{
|
||||
*buffer_pos++ = ' ';
|
||||
}
|
||||
*buffer_pos++ = '\0';
|
||||
ascii_buffer[i] = '\0';
|
||||
|
||||
written += fprintf(stream, "\n%4d: %s %s",
|
||||
line_start, buffer, ascii_buffer);
|
||||
|
||||
|
||||
buffer_pos = buffer;
|
||||
line_start += BYTES_PER_LINE;
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer_pos++ = ' ';
|
||||
}
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
/**
|
||||
* output handler in printf() for chunks
|
||||
*/
|
||||
static int print_chunk(FILE *stream, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
chunk_t *chunk = *((chunk_t**)(args[0]));
|
||||
bool first = TRUE;
|
||||
chunk_t copy = *chunk;
|
||||
int written = 0;
|
||||
|
||||
if (!info->alt)
|
||||
{
|
||||
const void *new_args[] = {&chunk->ptr, &chunk->len};
|
||||
return print_bytes(stream, info, new_args);
|
||||
}
|
||||
|
||||
while (copy.len > 0)
|
||||
{
|
||||
static char hexdig[] = "0123456789abcdef";
|
||||
if (first)
|
||||
{
|
||||
first = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
written += fprintf(stream, ":");
|
||||
}
|
||||
written += fprintf(stream, "%c%c",
|
||||
hexdig[(*copy.ptr >> 4) & 0x0f],
|
||||
hexdig[ *copy.ptr++ & 0x0f]);
|
||||
copy.len--;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
/**
|
||||
* output handler in printf() for time_t
|
||||
*/
|
||||
static int print_time(FILE *stream, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
static const char* months[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
time_t time = *((time_t*)(args[0]));
|
||||
bool utc = TRUE;
|
||||
struct tm t;
|
||||
|
||||
if (info->alt)
|
||||
{
|
||||
utc = *((bool*)(args[1]));
|
||||
}
|
||||
if (time == UNDEFINED_TIME)
|
||||
{
|
||||
return fprintf(stream, "--- -- --:--:--%s----",
|
||||
info->alt ? " UTC " : " ");
|
||||
}
|
||||
if (utc)
|
||||
{
|
||||
gmtime_r(&time, &t);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct tm *t = (utc)? gmtime(time) : localtime(time);
|
||||
|
||||
snprintf(buf, buflen, "%s %02d %02d:%02d:%02d%s%04d",
|
||||
months[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
|
||||
(utc)?" UTC ":" ", t->tm_year + 1900);
|
||||
localtime_r(&time, &t);
|
||||
}
|
||||
return fprintf(stream, "%s %02d %02d:%02d:%02d%s%04d",
|
||||
months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
|
||||
t.tm_sec, info->alt ? " UTC " : " ", t.tm_year + 1900);
|
||||
}
|
||||
|
||||
/**
|
||||
* output handler in printf() for time deltas
|
||||
*/
|
||||
static int print_time_delta(FILE *stream, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
time_t start = *((time_t*)(args[0]));
|
||||
time_t end = *((time_t*)(args[1]));
|
||||
u_int delta = abs(end - start);
|
||||
char* unit = "second";
|
||||
|
||||
if (delta > 2 * 60 * 60 * 24)
|
||||
{
|
||||
delta /= 60 * 60 * 24;
|
||||
unit = "days";
|
||||
}
|
||||
else if (delta > 2 * 60 * 60)
|
||||
{
|
||||
delta /= 60 * 60;
|
||||
unit = "hours";
|
||||
}
|
||||
else if (delta > 2 * 60)
|
||||
{
|
||||
delta /= 60;
|
||||
unit = "minutes";
|
||||
}
|
||||
return fprintf(stream, "%d %s", delta, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* arginfo handler in printf() for byte ranges
|
||||
*/
|
||||
static int print_bytes_arginfo(const struct printf_info *info, size_t n, int *argtypes)
|
||||
{
|
||||
if (n > 1)
|
||||
{
|
||||
argtypes[0] = PA_POINTER;
|
||||
argtypes[1] = PA_INT;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* arginfo handler in printf() for time deltas
|
||||
*/
|
||||
static int print_time_delta_arginfo(const struct printf_info *info, size_t n, int *argtypes)
|
||||
{
|
||||
if (n > 1)
|
||||
{
|
||||
argtypes[0] = PA_INT;
|
||||
argtypes[1] = PA_INT;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* arginfo handler in printf() for time_t
|
||||
*/
|
||||
static int print_time_arginfo(const struct printf_info *info, size_t n, int *argtypes)
|
||||
{
|
||||
if (info->alt)
|
||||
{
|
||||
if (n > 1)
|
||||
{
|
||||
argtypes[0] = PA_INT;
|
||||
argtypes[1] = PA_INT;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
argtypes[0] = PA_INT;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* arginfo handler in printf() for chunks
|
||||
*/
|
||||
static int print_chunk_arginfo(const struct printf_info *info, size_t n, int *argtypes)
|
||||
{
|
||||
if (n > 0)
|
||||
{
|
||||
argtypes[0] = PA_POINTER;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* register printf() handlers for time_t
|
||||
*/
|
||||
static void __attribute__ ((constructor))print_register()
|
||||
{
|
||||
register_printf_function(CHUNK_PRINTF_SPEC, print_chunk, print_chunk_arginfo);
|
||||
register_printf_function(BYTES_PRINTF_SPEC, print_bytes, print_bytes_arginfo);
|
||||
register_printf_function(TIME_PRINTF_SPEC, print_time, print_time_arginfo);
|
||||
register_printf_function(TIME_DELTA_PRINTF_SPEC, print_time_delta, print_time_delta_arginfo);
|
||||
}
|
||||
|
||||
+20
-16
@@ -106,9 +106,9 @@ enum status_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for type status_t.
|
||||
* enum_names for type status_t.
|
||||
*/
|
||||
extern mapping_t status_m[];
|
||||
extern enum_name_t *status_names;
|
||||
|
||||
/**
|
||||
* Handle struct timeval like an own type.
|
||||
@@ -150,6 +150,8 @@ struct chunk_t {
|
||||
*/
|
||||
extern chunk_t CHUNK_INITIALIZER;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Printf() hook character to dump a chunk using printf.
|
||||
* The argument supplied to printf() is a pointer to a chunk.
|
||||
@@ -165,6 +167,22 @@ extern chunk_t CHUNK_INITIALIZER;
|
||||
*/
|
||||
#define BYTES_PRINTF_SPEC 'b'
|
||||
|
||||
/**
|
||||
* printf specifier for time_t, use #-modifier to print time as UTC
|
||||
*/
|
||||
#define TIME_PRINTF_SPEC 'T'
|
||||
|
||||
/**
|
||||
* printf specifier for time_t deltas, uses two arguments
|
||||
* E.g. printf("%V", begin, end);
|
||||
*/
|
||||
#define TIME_DELTA_PRINTF_SPEC 'V'
|
||||
|
||||
/**
|
||||
* time_t for a not defined time
|
||||
*/
|
||||
#define UNDEFINED_TIME 0
|
||||
|
||||
/**
|
||||
* Initialize a chunk to a static buffer
|
||||
*/
|
||||
@@ -241,18 +259,4 @@ void ref_get(refcount_t *ref);
|
||||
bool ref_put(refcount_t *ref);
|
||||
|
||||
|
||||
#define UNDEFINED_TIME 0
|
||||
#define TIMETOA_BUF 30
|
||||
|
||||
/**
|
||||
* @brief Display a date either in local or UTC time
|
||||
*
|
||||
* @param buf buffer where displayed time will be written to
|
||||
* @param buflen buffer length
|
||||
* @param time time to be displayed
|
||||
* @param utc UTC (TRUE) or local time (FALSE)
|
||||
*
|
||||
*/
|
||||
void timetoa(char *buf, size_t buflen, const time_t *time, bool utc);
|
||||
|
||||
#endif /*TYPES_H_*/
|
||||
|
||||
@@ -35,11 +35,7 @@
|
||||
|
||||
#include <asn1/asn1.h>
|
||||
|
||||
/**
|
||||
* String mappings for id_type_t.
|
||||
*/
|
||||
|
||||
static const char *const id_type_name[] = {
|
||||
ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID,
|
||||
"ID_ANY",
|
||||
"ID_IPV4_ADDR",
|
||||
"ID_FQDN",
|
||||
@@ -51,11 +47,11 @@ static const char *const id_type_name[] = {
|
||||
"ID_IPV6_ADDR_RANGE",
|
||||
"ID_DER_ASN1_DN",
|
||||
"ID_DER_ASN1_GN",
|
||||
"ID_KEY_ID",
|
||||
};
|
||||
"ID_KEY_ID");
|
||||
ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_DER_ASN1_GN_URI, ID_KEY_ID,
|
||||
"ID_DER_ASN1_GN_URI");
|
||||
ENUM_END(id_type_names, ID_DER_ASN1_GN_URI);
|
||||
|
||||
enum_names id_type_names =
|
||||
{ ID_ANY, ID_KEY_ID, id_type_name, NULL };
|
||||
|
||||
/**
|
||||
* X.501 acronyms for well known object identifiers (OIDs)
|
||||
|
||||
@@ -116,9 +116,9 @@ enum id_type_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for id_type_t.
|
||||
* enum names for id_type_t.
|
||||
*/
|
||||
extern enum_names id_type_names;
|
||||
extern enum_name_t *id_type_names;
|
||||
|
||||
typedef struct identification_t identification_t;
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "leak_detective.h"
|
||||
|
||||
#include <types.h>
|
||||
#include <library.h>
|
||||
|
||||
#ifdef LEAK_DETECTIVE
|
||||
|
||||
@@ -116,11 +117,6 @@ static memory_header_t first_header = {
|
||||
next: NULL
|
||||
};
|
||||
|
||||
/**
|
||||
* logger for the leak detective
|
||||
*/
|
||||
static logger_t *logger;
|
||||
|
||||
/**
|
||||
* standard hooks, used to temparily remove hooking
|
||||
*/
|
||||
@@ -149,11 +145,11 @@ static void log_stack_frames(void **stack_frames, int stack_frame_count)
|
||||
|
||||
strings = backtrace_symbols (stack_frames, stack_frame_count);
|
||||
|
||||
logger->log(logger, ERROR, " dumping %d stack frame addresses", stack_frame_count);
|
||||
DBG1(" dumping %d stack frame addresses", stack_frame_count);
|
||||
|
||||
for (i = 0; i < stack_frame_count; i++)
|
||||
{
|
||||
logger->log(logger, ERROR, " %s", strings[i]);
|
||||
DBG1(" %s", strings[i]);
|
||||
}
|
||||
free (strings);
|
||||
}
|
||||
@@ -166,7 +162,7 @@ static void log_stack_frames(void **stack_frames, int stack_frame_count)
|
||||
*
|
||||
* The range_size is calculated using the readelf utility, e.g.:
|
||||
* readelf -s /lib/glibc.so.6
|
||||
* These values may or may not be acceptable for another system.
|
||||
* The values are for glibc-2.4 and may or may not be correct on other systems.
|
||||
*/
|
||||
typedef struct whitelist_t whitelist_t;
|
||||
|
||||
@@ -176,15 +172,16 @@ struct whitelist_t {
|
||||
};
|
||||
|
||||
whitelist_t whitelist[] = {
|
||||
{pthread_create, 381},
|
||||
{pthread_setspecific, 256},
|
||||
{mktime, 60},
|
||||
{tzset, 126},
|
||||
{inet_ntoa, 256},
|
||||
{strerror, 173},
|
||||
{getprotobynumber, 294},
|
||||
{getservbyport, 309},
|
||||
{register_printf_function, 150},
|
||||
{pthread_create, 2542},
|
||||
{pthread_setspecific, 217},
|
||||
{mktime, 60},
|
||||
{tzset, 123},
|
||||
{inet_ntoa, 249},
|
||||
{strerror, 180},
|
||||
{getprotobynumber, 291},
|
||||
{getservbyport, 311},
|
||||
{register_printf_function, 159},
|
||||
{syslog, 45},
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -220,7 +217,7 @@ void report_leaks()
|
||||
{
|
||||
if (!is_whitelisted(hdr->stack_frames, hdr->stack_frame_count))
|
||||
{
|
||||
logger->log(logger, ERROR, "Leak (%d bytes at %p):", hdr->bytes, hdr + 1);
|
||||
DBG1("Leak (%d bytes at %p):", hdr->bytes, hdr + 1);
|
||||
log_stack_frames(hdr->stack_frames, hdr->stack_frame_count);
|
||||
leaks++;
|
||||
}
|
||||
@@ -229,13 +226,13 @@ void report_leaks()
|
||||
switch (leaks)
|
||||
{
|
||||
case 0:
|
||||
logger->log(logger, CONTROL, "No leaks detected");
|
||||
DBG1("No leaks detected");
|
||||
break;
|
||||
case 1:
|
||||
logger->log(logger, ERROR, "One leak detected");
|
||||
DBG1("One leak detected");
|
||||
break;
|
||||
default:
|
||||
logger->log(logger, ERROR, "%d leaks detected", leaks);
|
||||
DBG1("%d leaks detected", leaks);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -322,8 +319,8 @@ void free_hook(void *ptr, const void *caller)
|
||||
uninstall_hooks();
|
||||
if (hdr->magic != MEMORY_HEADER_MAGIC)
|
||||
{
|
||||
logger->log(logger, ERROR, "freeing of invalid memory (%p, MAGIC 0x%x != 0x%x):",
|
||||
ptr, hdr->magic, MEMORY_HEADER_MAGIC);
|
||||
DBG1("freeing of invalid memory (%p, MAGIC 0x%x != 0x%x):",
|
||||
ptr, hdr->magic, MEMORY_HEADER_MAGIC);
|
||||
stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT);
|
||||
log_stack_frames(stack_frames, stack_frame_count);
|
||||
install_hooks();
|
||||
@@ -368,7 +365,7 @@ void *realloc_hook(void *old, size_t bytes, const void *caller)
|
||||
uninstall_hooks();
|
||||
if (hdr->magic != MEMORY_HEADER_MAGIC)
|
||||
{
|
||||
logger->log(logger, ERROR, "reallocation of invalid memory (%p):", old);
|
||||
DBG1("reallocation of invalid memory (%p):", old);
|
||||
stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT);
|
||||
log_stack_frames(stack_frames, stack_frame_count);
|
||||
install_hooks();
|
||||
@@ -397,16 +394,15 @@ void *realloc_hook(void *old, size_t bytes, const void *caller)
|
||||
/**
|
||||
* Setup leak detective
|
||||
*/
|
||||
void leak_detective_init()
|
||||
void __attribute__ ((constructor)) leak_detective_init()
|
||||
{
|
||||
logger = logger_manager->get_logger(logger_manager, LEAK_DETECT);
|
||||
install_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up leak detective
|
||||
*/
|
||||
void leak_detective_cleanup()
|
||||
void __attribute__ ((destructor)) leak_detective_cleanup()
|
||||
{
|
||||
uninstall_hooks();
|
||||
report_leaks();
|
||||
@@ -415,7 +411,7 @@ void leak_detective_cleanup()
|
||||
/**
|
||||
* Log memory allocation statistics
|
||||
*/
|
||||
void leak_detective_status(logger_t *logger)
|
||||
void leak_detective_status(FILE *stream)
|
||||
{
|
||||
u_int blocks = 0;
|
||||
size_t bytes = 0;
|
||||
@@ -429,10 +425,10 @@ void leak_detective_status(logger_t *logger)
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
logger->log(logger, CONTROL|LEVEL1, "allocation statistics:");
|
||||
logger->log(logger, CONTROL|LEVEL1, " call stats: malloc: %d, free: %d, realloc: %d",
|
||||
fprintf(stream, "allocation statistics:\n");
|
||||
fprintf(stream, " call stats: malloc: %d, free: %d, realloc: %d\n",
|
||||
count_malloc, count_free, count_realloc);
|
||||
logger->log(logger, CONTROL|LEVEL1, " allocated %d blocks, total size %d bytes (avg. %d bytes)",
|
||||
fprintf(stream, " allocated %d blocks, total size %d bytes (avg. %d bytes)\n",
|
||||
blocks, bytes, bytes/blocks);
|
||||
}
|
||||
|
||||
@@ -441,7 +437,7 @@ void leak_detective_status(logger_t *logger)
|
||||
/**
|
||||
* Dummy when !using LEAK_DETECTIVE
|
||||
*/
|
||||
void leak_detective_status(logger_t *logger)
|
||||
void leak_detective_status(FILE *stream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -22,36 +22,14 @@
|
||||
#ifndef LEAK_DETECTIVE_H_
|
||||
#define LEAK_DETECTIVE_H_
|
||||
|
||||
|
||||
#include <utils/logger_manager.h>
|
||||
|
||||
/**
|
||||
* Log status information about allocation
|
||||
*/
|
||||
void leak_detective_status(logger_t *logger);
|
||||
|
||||
#ifdef LEAK_DETECTIVE
|
||||
void leak_detective_status(FILE *stream);
|
||||
|
||||
/**
|
||||
* Max number of stack frames to include in a backtrace.
|
||||
*/
|
||||
#define STACK_FRAMES_COUNT 30
|
||||
|
||||
/**
|
||||
* Initialize leak detective, activates it
|
||||
*/
|
||||
void leak_detective_init();
|
||||
|
||||
/**
|
||||
* Cleanup leak detective, deactivates it
|
||||
*/
|
||||
void leak_detective_cleanup();
|
||||
|
||||
#else /* !LEAK_DETECTIVE */
|
||||
|
||||
#define leak_detective_init() {}
|
||||
#define leak_detective_cleanup() {}
|
||||
|
||||
#endif /* LEAK_DETECTIVE */
|
||||
|
||||
#endif /* LEAK_DETECTIVE_H_ */
|
||||
|
||||
@@ -127,6 +127,11 @@ struct private_iterator_t {
|
||||
* Direction of iterator.
|
||||
*/
|
||||
bool forward;
|
||||
|
||||
/**
|
||||
* Mutex to use to synchronize access
|
||||
*/
|
||||
pthread_mutex_t *mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -361,6 +366,10 @@ static void insert_after(private_iterator_t * iterator, void *item)
|
||||
*/
|
||||
static void iterator_destroy(private_iterator_t *this)
|
||||
{
|
||||
if (this->mutex)
|
||||
{
|
||||
pthread_mutex_unlock(this->mutex);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
@@ -372,24 +381,6 @@ static int get_count(private_linked_list_t *this)
|
||||
return this->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.call_on_items.
|
||||
*/
|
||||
static void call_on_items(private_linked_list_t *this, void(*func)(void*))
|
||||
{
|
||||
iterator_t *iterator;
|
||||
void *item;
|
||||
|
||||
iterator = this->public.create_iterator(&this->public,TRUE);
|
||||
|
||||
while (iterator->has_next(iterator))
|
||||
{
|
||||
iterator->current(iterator, &item);
|
||||
(*func)(item);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.insert_first.
|
||||
*/
|
||||
@@ -629,7 +620,7 @@ static status_t get_last(private_linked_list_t *this, void **item)
|
||||
static iterator_t *create_iterator (private_linked_list_t *linked_list, bool forward)
|
||||
{
|
||||
private_iterator_t *this = malloc_thing(private_iterator_t);
|
||||
|
||||
|
||||
this->public.get_count = (bool (*) (iterator_t *this)) get_list_count;
|
||||
this->public.iterate = (bool (*) (iterator_t *this, void **value)) iterate;
|
||||
this->public.has_next = (bool (*) (iterator_t *this)) iterator_has_next;
|
||||
@@ -640,11 +631,26 @@ static iterator_t *create_iterator (private_linked_list_t *linked_list, bool for
|
||||
this->public.remove = (status_t (*) (iterator_t *this)) remove;
|
||||
this->public.reset = (void (*) (iterator_t *this)) iterator_reset;
|
||||
this->public.destroy = (void (*) (iterator_t *this)) iterator_destroy;
|
||||
|
||||
|
||||
this->forward = forward;
|
||||
this->current = NULL;
|
||||
this->list = linked_list;
|
||||
this->mutex = NULL;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.create_iterator_locked.
|
||||
*/
|
||||
static iterator_t *create_iterator_locked(private_linked_list_t *linked_list,
|
||||
pthread_mutex_t *mutex)
|
||||
{
|
||||
private_iterator_t *this = (private_iterator_t*)create_iterator(linked_list, TRUE);
|
||||
this->mutex = mutex;
|
||||
|
||||
pthread_mutex_lock(mutex);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -672,7 +678,7 @@ linked_list_t *linked_list_create()
|
||||
|
||||
this->public.get_count = (int (*) (linked_list_t *)) get_count;
|
||||
this->public.create_iterator = (iterator_t * (*) (linked_list_t *,bool))create_iterator;
|
||||
this->public.call_on_items = (void (*) (linked_list_t *, void(*func)(void*)))call_on_items;
|
||||
this->public.create_iterator_locked = (iterator_t * (*) (linked_list_t *,pthread_mutex_t*))create_iterator_locked;
|
||||
this->public.get_first = (status_t (*) (linked_list_t *, void **item))get_first;
|
||||
this->public.get_last = (status_t (*) (linked_list_t *, void **item))get_last;
|
||||
this->public.insert_first = (void (*) (linked_list_t *, void *item))insert_first;
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#ifndef LINKED_LIST_H_
|
||||
#define LINKED_LIST_H_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <types.h>
|
||||
#include <utils/iterator.h>
|
||||
|
||||
@@ -31,18 +33,13 @@
|
||||
typedef struct linked_list_t linked_list_t;
|
||||
|
||||
/**
|
||||
* @brief Class implementing a double linked list (named only as linked list).
|
||||
* @brief Class implementing a double linked list.
|
||||
*
|
||||
* @warning Access to an object of this type is not thread-save.
|
||||
* General purpose linked list. This list is not synchronized.
|
||||
*
|
||||
* @b Costructors:
|
||||
* - linked_list_create()
|
||||
*
|
||||
* @see
|
||||
* - job_queue_t
|
||||
* - event_queue_t
|
||||
* - send_queue_t
|
||||
*
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct linked_list_t {
|
||||
@@ -64,27 +61,24 @@ struct linked_list_t {
|
||||
* @param forward iterator direction (TRUE: front to end)
|
||||
* @return new iterator_t object
|
||||
*/
|
||||
iterator_t * (*create_iterator) (linked_list_t *linked_list, bool forward);
|
||||
iterator_t *(*create_iterator) (linked_list_t *linked_list, bool forward);
|
||||
|
||||
/**
|
||||
* @brief Call a function with list element as argument.
|
||||
*
|
||||
* This method accepts a function, which will be called for
|
||||
* each list element once. The function must accept the list
|
||||
* element as the first argument. Handy for destruction of
|
||||
* list elements.
|
||||
*
|
||||
* @todo Additional vararg which are passed to the
|
||||
* function would be nice...
|
||||
* @brief Creates a iterator, locking a mutex.
|
||||
*
|
||||
* The supplied mutex is acquired immediately, and released
|
||||
* when the iterator gets destroyed.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param func function to call
|
||||
* @param mutex mutex to use for exclusive access
|
||||
* @return new iterator_t object
|
||||
*/
|
||||
void (*call_on_items) (linked_list_t *linked_list, void(*func)(void*));
|
||||
iterator_t *(*create_iterator_locked) (linked_list_t *linked_list,
|
||||
pthread_mutex_t *mutex);
|
||||
|
||||
/**
|
||||
* @brief Inserts a new item at the beginning of the list.
|
||||
*
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param[in] item item value to insert in list
|
||||
*/
|
||||
|
||||
@@ -1,384 +0,0 @@
|
||||
/**
|
||||
* @file logger.c
|
||||
*
|
||||
* @brief Implementation of logger_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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 <syslog.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
/**
|
||||
* Maximum length of a log entry (only used for logger_s.log).
|
||||
*/
|
||||
#define MAX_LOG 8192
|
||||
|
||||
/**
|
||||
* Maximum number of logged bytes per line
|
||||
*/
|
||||
#define MAX_BYTES 16
|
||||
|
||||
typedef struct private_logger_t private_logger_t;
|
||||
|
||||
/**
|
||||
* @brief Private data of a logger_t object.
|
||||
*/
|
||||
struct private_logger_t {
|
||||
/**
|
||||
* Public data.
|
||||
*/
|
||||
logger_t public;
|
||||
/**
|
||||
* Detail-level of logger.
|
||||
*/
|
||||
log_level_t level;
|
||||
/**
|
||||
* Name of logger.
|
||||
*/
|
||||
char *name;
|
||||
/**
|
||||
* File to write log output to.
|
||||
* NULL for syslog.
|
||||
*/
|
||||
FILE *output;
|
||||
|
||||
/**
|
||||
* Should a thread_id be included in the log?
|
||||
*/
|
||||
bool log_thread_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* thread local storage for get_thread_number
|
||||
*/
|
||||
static pthread_key_t thread_ids;
|
||||
static void make_key(void)
|
||||
{
|
||||
pthread_key_create(&thread_ids, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a unique thread number for a calling thread. Since
|
||||
* pthread_self returns large and ugly numbers, use this function
|
||||
* for logging; these numbers are incremental starting at 1
|
||||
*/
|
||||
static int get_thread_number(void)
|
||||
{
|
||||
static int current_num = 0;
|
||||
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
|
||||
int stored_num;
|
||||
|
||||
pthread_once(&key_once, make_key);
|
||||
stored_num = (int)pthread_getspecific(thread_ids);
|
||||
if (stored_num == 0)
|
||||
{
|
||||
pthread_setspecific(thread_ids, (void*)++current_num);
|
||||
return current_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
return stored_num;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* prepend the logging prefix to string and store it in buffer
|
||||
*/
|
||||
static void prepend_prefix(private_logger_t *this, log_level_t loglevel, const char *string, char *buffer)
|
||||
{
|
||||
char thread_id[3] = "";
|
||||
char log_type, log_details;
|
||||
char *separator = (strlen(this->name) == 0)? "" : ":";
|
||||
|
||||
if (loglevel & CONTROL)
|
||||
{
|
||||
log_type = 'C';
|
||||
}
|
||||
else if (loglevel & ERROR)
|
||||
{
|
||||
log_type = 'E';
|
||||
}
|
||||
else if (loglevel & RAW)
|
||||
{
|
||||
log_type = 'R';
|
||||
}
|
||||
else if (loglevel & PRIVATE)
|
||||
{
|
||||
log_type = 'P';
|
||||
}
|
||||
else if (loglevel & AUDIT)
|
||||
{
|
||||
log_type = 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
log_type = '-';
|
||||
}
|
||||
|
||||
if (loglevel & (LEVEL3 - LEVEL2))
|
||||
{
|
||||
log_details = '3';
|
||||
}
|
||||
else if (loglevel & (LEVEL2 - LEVEL1))
|
||||
{
|
||||
log_details = '2';
|
||||
}
|
||||
else if (loglevel & LEVEL1)
|
||||
{
|
||||
log_details = '1';
|
||||
}
|
||||
else
|
||||
{
|
||||
log_details = '0';
|
||||
}
|
||||
|
||||
if (this->log_thread_id)
|
||||
{
|
||||
snprintf(thread_id, sizeof(thread_id), "%02d", get_thread_number());
|
||||
}
|
||||
snprintf(buffer, MAX_LOG, "%s[%c%c%s%s] %s",
|
||||
thread_id, log_type, log_details, separator, this->name, string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a charon-loglevel to a syslog priority
|
||||
*/
|
||||
static int get_priority(log_level_t loglevel)
|
||||
{
|
||||
if (loglevel & ERROR)
|
||||
{
|
||||
return LOG_AUTHPRIV|LOG_ERR;
|
||||
}
|
||||
if (loglevel & AUDIT)
|
||||
{
|
||||
return LOG_AUTHPRIV|LOG_INFO;
|
||||
}
|
||||
return LOG_AUTHPRIV|LOG_DEBUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.logv.
|
||||
*/
|
||||
static void logv(private_logger_t *this, log_level_t loglevel, const char *format, va_list args)
|
||||
{
|
||||
if ((this->level & loglevel) == loglevel)
|
||||
{
|
||||
char buffer[MAX_LOG];
|
||||
|
||||
if (this->output == NULL)
|
||||
{
|
||||
/* syslog */
|
||||
prepend_prefix(this, loglevel, format, buffer);
|
||||
vsyslog(get_priority(loglevel), buffer, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* File output */
|
||||
prepend_prefix(this, loglevel, format, buffer);
|
||||
vfprintf(this->output, buffer, args);
|
||||
fprintf(this->output, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.log.
|
||||
*/
|
||||
static void logg(private_logger_t *this, log_level_t loglevel, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
logv(this, loglevel, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.log_bytes.
|
||||
*/
|
||||
static void log_bytes(private_logger_t *this, log_level_t loglevel, const char *label, const char *bytes, size_t len)
|
||||
{
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
if ((this->level & loglevel) == loglevel)
|
||||
{
|
||||
char thread_id[3] = "";
|
||||
char buffer[MAX_LOG];
|
||||
char ascii_buffer[MAX_BYTES+1];
|
||||
|
||||
char *buffer_pos = buffer;
|
||||
const char format[] = "%s %d bytes @ %p";
|
||||
const char *bytes_pos = bytes;
|
||||
const char *bytes_roof = bytes + len;
|
||||
|
||||
int line_start = 0;
|
||||
int i = 0;
|
||||
|
||||
/* since me can't do multi-line output to syslog,
|
||||
* we must do multiple syslogs. To avoid
|
||||
* problems in output order, lock this by a mutex.
|
||||
*/
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
prepend_prefix(this, loglevel, format, buffer);
|
||||
|
||||
if (this->log_thread_id)
|
||||
{
|
||||
snprintf(thread_id, sizeof(thread_id), "%02d", get_thread_number());
|
||||
}
|
||||
|
||||
if (this->output == NULL)
|
||||
{
|
||||
syslog(get_priority(loglevel), buffer, label, len, bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(this->output, buffer, label, len, bytes);
|
||||
fprintf(this->output, "\n");
|
||||
}
|
||||
|
||||
while (bytes_pos < bytes_roof)
|
||||
{
|
||||
static char hexdig[] = "0123456789ABCDEF";
|
||||
|
||||
*buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
|
||||
*buffer_pos++ = hexdig[ *bytes_pos & 0xF];
|
||||
|
||||
ascii_buffer[i++] = (*bytes_pos > 31 && *bytes_pos < 127)
|
||||
? *bytes_pos : '.';
|
||||
|
||||
if (++bytes_pos == bytes_roof || i == MAX_BYTES)
|
||||
{
|
||||
int padding = 3 * (MAX_BYTES - i);
|
||||
|
||||
while (padding--)
|
||||
{
|
||||
*buffer_pos++ = ' ';
|
||||
}
|
||||
*buffer_pos++ = '\0';
|
||||
ascii_buffer[i] = '\0';
|
||||
|
||||
if (this->output == NULL)
|
||||
{
|
||||
syslog(get_priority(loglevel), "%s[ :%5d] %s %s", thread_id, line_start, buffer, ascii_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(this->output, "%s[ :%5d] %s %s\n", thread_id, line_start, buffer, ascii_buffer);
|
||||
}
|
||||
buffer_pos = buffer;
|
||||
line_start += MAX_BYTES;
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer_pos++ = ' ';
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.log_chunk.
|
||||
*/
|
||||
static void log_chunk(logger_t *this, log_level_t loglevel, const char *label, chunk_t chunk)
|
||||
{
|
||||
this->log_bytes(this, loglevel, label, chunk.ptr, chunk.len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.enable_level.
|
||||
*/
|
||||
static void enable_level(private_logger_t *this, log_level_t log_level)
|
||||
{
|
||||
this->level |= log_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.disable_level.
|
||||
*/
|
||||
static void disable_level(private_logger_t *this, log_level_t log_level)
|
||||
{
|
||||
this->level &= ~log_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.set_output.
|
||||
*/
|
||||
static void set_output(private_logger_t *this, FILE * output)
|
||||
{
|
||||
this->output = output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.get_level.
|
||||
*/
|
||||
static log_level_t get_level(private_logger_t *this)
|
||||
{
|
||||
return this->level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.destroy.
|
||||
*/
|
||||
static void destroy(private_logger_t *this)
|
||||
{
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
logger_t *logger_create(char *logger_name, log_level_t log_level, bool log_thread_id, FILE * output)
|
||||
{
|
||||
private_logger_t *this = malloc_thing(private_logger_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.log = (void(*)(logger_t*,log_level_t,const char*,...))logg;
|
||||
this->public.logv = (void(*)(logger_t*,log_level_t,const char*,va_list))logv;
|
||||
this->public.log_bytes = (void(*)(logger_t*, log_level_t, const char*, const char*,size_t))log_bytes;
|
||||
this->public.log_chunk = log_chunk;
|
||||
this->public.enable_level = (void(*)(logger_t*,log_level_t))enable_level;
|
||||
this->public.disable_level = (void(*)(logger_t*,log_level_t))disable_level;
|
||||
this->public.get_level = (log_level_t(*)(logger_t*))get_level;
|
||||
this->public.set_output = (void(*)(logger_t*,FILE*))set_output;
|
||||
this->public.destroy = (void(*)(logger_t*))destroy;
|
||||
|
||||
if (logger_name == NULL)
|
||||
{
|
||||
logger_name = "";
|
||||
}
|
||||
|
||||
/* private variables */
|
||||
this->level = log_level;
|
||||
this->log_thread_id = log_thread_id;
|
||||
this->name = malloc(strlen(logger_name) + 1);
|
||||
|
||||
strcpy(this->name,logger_name);
|
||||
this->output = output;
|
||||
|
||||
return (logger_t*)this;
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
/**
|
||||
* @file logger.h
|
||||
*
|
||||
* @brief Interface of logger_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LOGGER_H_
|
||||
#define LOGGER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef enum log_level_t log_level_t;
|
||||
|
||||
/**
|
||||
* @brief Log Levels supported by the logger object.
|
||||
*
|
||||
* Logleves are devided in two different kinds:
|
||||
* - levels to specify the type of the log
|
||||
* - levels to specify the detail-level of the log
|
||||
*
|
||||
* Use combinations of these to build detailed loglevels, such
|
||||
* as CONTROL|LEVEL2 fore a detailed cotrol level, or
|
||||
* use RAW to see all raw data dumps (except private).
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
enum log_level_t {
|
||||
/**
|
||||
* Control flow.
|
||||
*/
|
||||
CONTROL = 1,
|
||||
/**
|
||||
* Error reporting.
|
||||
*/
|
||||
ERROR = 2,
|
||||
/**
|
||||
* Logs important for the sysadmin.
|
||||
*/
|
||||
AUDIT = 4,
|
||||
/**
|
||||
* Raw data dumps.
|
||||
*/
|
||||
RAW = 8,
|
||||
/**
|
||||
* Private data dumps.
|
||||
*/
|
||||
PRIVATE = 16,
|
||||
|
||||
/**
|
||||
* Log most important output, can be omitted.
|
||||
*/
|
||||
LEVEL0 = 0,
|
||||
/**
|
||||
* Log more detailed output.
|
||||
*/
|
||||
LEVEL1 = 32,
|
||||
/**
|
||||
* Log even more detailed output.
|
||||
*/
|
||||
LEVEL2 = LEVEL1 + 64,
|
||||
/**
|
||||
* Use maximum detailed output.
|
||||
*/
|
||||
LEVEL3 = LEVEL2 + 128,
|
||||
|
||||
/**
|
||||
* Summary for all types with all detail-levels.
|
||||
*/
|
||||
FULL = LEVEL3 + CONTROL + ERROR + RAW + PRIVATE + AUDIT
|
||||
};
|
||||
|
||||
typedef struct logger_t logger_t;
|
||||
|
||||
/**
|
||||
* @brief Class to simplify logging.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - logger_create()
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct logger_t {
|
||||
|
||||
/**
|
||||
* @brief Log an entry, using printf()-like params.
|
||||
*
|
||||
* All specified loglevels must be activated that
|
||||
* the log is done.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param loglevel or'ed set of log_level_t's
|
||||
* @param format printf like format string
|
||||
* @param ... printf like parameters
|
||||
*/
|
||||
void (*log) (logger_t *this, log_level_t log_level, const char *format, ...);
|
||||
|
||||
/**
|
||||
* @brief Log an entry, using vprintf() style va_list parameters.
|
||||
*
|
||||
* All specified loglevels must be activated that
|
||||
* the log is done.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param loglevel or'ed set of log_level_t's
|
||||
* @param format printf like format string
|
||||
* @param args va_list argument list
|
||||
*/
|
||||
void (*logv) (logger_t *this, log_level_t log_level, const char *format, va_list args);
|
||||
|
||||
/**
|
||||
* @brief Log some bytes, useful for debugging.
|
||||
*
|
||||
* All specified loglevels must be activated that
|
||||
* the log is done.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param loglevel or'ed set of log_level_t's
|
||||
* @param label a labeling name, logged with the bytes
|
||||
* @param bytes pointer to the bytes to dump
|
||||
* @param len number of bytes to dump
|
||||
*/
|
||||
void (*log_bytes) (logger_t *this, log_level_t loglevel, const char *label, const char *bytes, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Log a chunk, useful for debugging.
|
||||
*
|
||||
* All specified loglevels must be activated that
|
||||
* the log is done.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param loglevel or'ed set of log_level_t's
|
||||
* @param label a labeling name, logged with the bytes
|
||||
* @param chunk chunk to log
|
||||
*/
|
||||
void (*log_chunk) (logger_t *this, log_level_t loglevel, const char *label, chunk_t chunk);
|
||||
|
||||
/**
|
||||
* @brief Enables a loglevel for the current logger_t object.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param log_level loglevel to enable
|
||||
*/
|
||||
void (*enable_level) (logger_t *this, log_level_t log_level);
|
||||
|
||||
/**
|
||||
* @brief Disables a loglevel for the current logger_t object.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param log_level loglevel to enable
|
||||
*/
|
||||
void (*disable_level) (logger_t *this, log_level_t log_level);
|
||||
|
||||
/**
|
||||
* @brief Set the output of the logger.
|
||||
*
|
||||
* Use NULL for syslog.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param output file, where log output should be written
|
||||
*/
|
||||
void (*set_output) (logger_t *this, FILE *output);
|
||||
|
||||
/**
|
||||
* @brief Get the currently used loglevel.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @return currently used loglevel
|
||||
*/
|
||||
log_level_t (*get_level) (logger_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys a logger_t object.
|
||||
*
|
||||
* @param this logger_t object
|
||||
*/
|
||||
void (*destroy) (logger_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor to create a logger_t object.
|
||||
*
|
||||
* @param logger_name name for the logger_t object
|
||||
* @param log_level or'ed set of log_levels to assign to the new logger_t object
|
||||
* @param log_thread_id TRUE if thread id should also be logged
|
||||
* @param output FILE * if log has to go on a file output, NULL for syslog
|
||||
* @return logger_t object
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
logger_t *logger_create(char *logger_name, log_level_t log_level, bool log_thread_id, FILE * output);
|
||||
|
||||
|
||||
#endif /*LOGGER_H_*/
|
||||
@@ -1,220 +0,0 @@
|
||||
/**
|
||||
* @file logger_manager.c
|
||||
*
|
||||
* @brief Implementation of logger_manager_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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 "logger_manager.h"
|
||||
|
||||
#include <definitions.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
/**
|
||||
* String mappings for logger_context_t
|
||||
*/
|
||||
mapping_t logger_context_t_mappings[] = {
|
||||
{PARSER, "PARSER"},
|
||||
{GENERATOR, "GENERATOR"},
|
||||
{IKE_SA, "IKE_SA"},
|
||||
{IKE_SA_MANAGER, "IKE_SA_MANAGER"},
|
||||
{CHILD_SA, "CHILD_SA"},
|
||||
{MESSAGE, "MESSAGE"},
|
||||
{THREAD_POOL, "THREAD_POOL"},
|
||||
{WORKER, "WORKER"},
|
||||
{SCHEDULER, "SCHEDULER"},
|
||||
{SENDER, "SENDER"},
|
||||
{RECEIVER, "RECEIVER"},
|
||||
{SOCKET, "SOCKET"},
|
||||
{TESTER, "TESTER"},
|
||||
{DAEMON, "DAEMON"},
|
||||
{CONFIG, "CONFIG"},
|
||||
{ENCRYPTION_PAYLOAD, "ENCRYPTION_PAYLOAD"},
|
||||
{PAYLOAD, "PAYLOAD"},
|
||||
{DER_DECODER, "DER_DECODER"},
|
||||
{DER_ENCODER, "DER_ENCODER"},
|
||||
{ASN1, "ASN1"},
|
||||
{XFRM, "XFRM"},
|
||||
{LEAK_DETECT, "LEAK_DETECT"},
|
||||
{MAPPING_END, NULL},
|
||||
};
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
log_level_t level;
|
||||
bool log_thread_ids;
|
||||
} logger_defaults[] = {
|
||||
{ "PARSR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* PARSER */
|
||||
{ "GNRAT", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* GENERATOR */
|
||||
{ "IKESA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* IKE_SA */
|
||||
{ "SAMGR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* IKE_SA_MANAGER */
|
||||
{ "CHDSA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* CHILD_SA */
|
||||
{ "MESSG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* MESSAGE */
|
||||
{ "TPOOL", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* THREAD_POOL */
|
||||
{ "WORKR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* WORKER */
|
||||
{ "SCHED", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* SCHEDULER */
|
||||
{ "SENDR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* SENDER */
|
||||
{ "RECVR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* RECEIVER */
|
||||
{ "SOCKT", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* SOCKET */
|
||||
{ "TESTR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* TESTER */
|
||||
{ "DAEMN", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* DAEMON */
|
||||
{ "CONFG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* CONFIG */
|
||||
{ "ENCPL", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* ENCRYPTION_PAYLOAD */
|
||||
{ "PAYLD", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* PAYLOAD */
|
||||
{ "DERDC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* DER_DECODER */
|
||||
{ "DEREC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* DER_ENCODER */
|
||||
{ "ASN_1", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* ASN1 */
|
||||
{ "XFRM ", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* XFRM */
|
||||
{ "LEAKD", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* LEAK_DETECT */
|
||||
};
|
||||
|
||||
|
||||
typedef struct private_logger_manager_t private_logger_manager_t;
|
||||
|
||||
/**
|
||||
* Private data of logger_manager_t object.
|
||||
*/
|
||||
struct private_logger_manager_t {
|
||||
/**
|
||||
* Public data.
|
||||
*/
|
||||
logger_manager_t public;
|
||||
|
||||
/**
|
||||
* Array of loggers, one for each context
|
||||
*/
|
||||
logger_t *loggers[LOGGER_CONTEXT_ROOF];
|
||||
};
|
||||
|
||||
/**
|
||||
* The one and only instance of the logger manager
|
||||
*/
|
||||
static private_logger_manager_t private_logger_manager;
|
||||
|
||||
/**
|
||||
* Exported pointer for the logger manager
|
||||
*/
|
||||
logger_manager_t *logger_manager = (logger_manager_t *)&private_logger_manager;
|
||||
|
||||
/**
|
||||
* Implementation of logger_manager_t.get_logger.
|
||||
*/
|
||||
static logger_t *get_logger(private_logger_manager_t *this, logger_context_t context)
|
||||
{
|
||||
return this->loggers[context];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_manager_t.get_log_level.
|
||||
*/
|
||||
static log_level_t get_log_level (private_logger_manager_t *this, logger_context_t context)
|
||||
{
|
||||
return this->loggers[context]->get_level(this->loggers[context]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_logger_manager_t.enable_log_level.
|
||||
*/
|
||||
static void enable_log_level(private_logger_manager_t *this, logger_context_t context, log_level_t level)
|
||||
{
|
||||
if (context == ALL_LOGGERS)
|
||||
{
|
||||
for (context = 0; context < LOGGER_CONTEXT_ROOF; context++)
|
||||
{
|
||||
this->loggers[context]->enable_level(this->loggers[context], level);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->loggers[context]->enable_level(this->loggers[context], level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_logger_manager_t.disable_log_level.
|
||||
*/
|
||||
static void disable_log_level(private_logger_manager_t *this, logger_context_t context, log_level_t level)
|
||||
{
|
||||
if (context == ALL_LOGGERS)
|
||||
{
|
||||
for (context = 0; context < LOGGER_CONTEXT_ROOF; context++)
|
||||
{
|
||||
this->loggers[context]->disable_level(this->loggers[context], level);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->loggers[context]->disable_level(this->loggers[context], level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_logger_manager_t.set_output.
|
||||
*/
|
||||
static void set_output(private_logger_manager_t *this, logger_context_t context, FILE *output)
|
||||
{
|
||||
if (context == ALL_LOGGERS)
|
||||
{
|
||||
for (context = 0; context < LOGGER_CONTEXT_ROOF; context++)
|
||||
{
|
||||
this->loggers[context]->set_output(this->loggers[context], output);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->loggers[context]->set_output(this->loggers[context], output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the instance of the logger manager at library startup
|
||||
*/
|
||||
void logger_manager_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
logger_manager->get_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context))get_logger;
|
||||
logger_manager->get_log_level = (log_level_t (*)(logger_manager_t *, logger_context_t)) get_log_level;
|
||||
logger_manager->enable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) enable_log_level;
|
||||
logger_manager->disable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) disable_log_level;
|
||||
logger_manager->set_output = (void (*)(logger_manager_t *, logger_context_t, FILE*)) set_output;
|
||||
|
||||
for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
|
||||
{
|
||||
private_logger_manager.loggers[i] = logger_create(logger_defaults[i].name,
|
||||
logger_defaults[i].level,
|
||||
logger_defaults[i].log_thread_ids,
|
||||
INITIAL_LOG_OUTPUT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the logger manager at library exit
|
||||
*/
|
||||
void logger_manager_cleanup()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
|
||||
{
|
||||
private_logger_manager.loggers[i]->destroy(private_logger_manager.loggers[i]);
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
/**
|
||||
* @file logger_manager.h
|
||||
*
|
||||
* @brief Interface of logger_manager_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LOGGER_MANAGER_H_
|
||||
#define LOGGER_MANAGER_H_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <utils/logger.h>
|
||||
|
||||
#define INITIAL_LOG_OUTPUT stdout
|
||||
|
||||
typedef enum logger_context_t logger_context_t;
|
||||
|
||||
/**
|
||||
* @brief Context of a specific logger.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
enum logger_context_t {
|
||||
ALL_LOGGERS = -1,
|
||||
PARSER = 0,
|
||||
GENERATOR,
|
||||
IKE_SA,
|
||||
IKE_SA_MANAGER,
|
||||
CHILD_SA,
|
||||
MESSAGE,
|
||||
THREAD_POOL,
|
||||
WORKER,
|
||||
SCHEDULER,
|
||||
SENDER,
|
||||
RECEIVER,
|
||||
SOCKET,
|
||||
TESTER,
|
||||
DAEMON,
|
||||
CONFIG,
|
||||
ENCRYPTION_PAYLOAD,
|
||||
PAYLOAD,
|
||||
DER_DECODER,
|
||||
DER_ENCODER,
|
||||
ASN1,
|
||||
XFRM,
|
||||
LEAK_DETECT,
|
||||
LOGGER_CONTEXT_ROOF,
|
||||
};
|
||||
|
||||
|
||||
typedef struct logger_manager_t logger_manager_t;
|
||||
|
||||
/**
|
||||
* @brief Class to manage logger_t objects.
|
||||
*
|
||||
* The logger manager manages all logger_t object in a list and
|
||||
* allows their manipulation. Via a logger_context_t, the loglevel
|
||||
* of a specific logging type can be adjusted at runtime.
|
||||
* This class differs from others, as it has no constructor or destroy
|
||||
* function. The one and only instance "logger_manager" is created at
|
||||
* library start and destroyed at exit.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - none, logger_manager is the single instance
|
||||
* use logger_manager_init/logger_manager_cleanup
|
||||
*
|
||||
* @see logger_t
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct logger_manager_t {
|
||||
|
||||
/**
|
||||
* @brief Gets a logger_t object for a specific logger context.
|
||||
*
|
||||
* @param this logger_manager_t object
|
||||
* @param context logger_context to use the logger for
|
||||
* @param name name for the new logger. Context name is already included
|
||||
* and has not to be specified (so NULL is allowed)
|
||||
* @return logger_t object
|
||||
*/
|
||||
logger_t *(*get_logger) (logger_manager_t *this, logger_context_t context);
|
||||
|
||||
/**
|
||||
* @brief Returns the set log_level of a specific context.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param context context to check level
|
||||
* @return log_level for the given logger_context
|
||||
*/
|
||||
log_level_t (*get_log_level) (logger_manager_t *this, logger_context_t context);
|
||||
|
||||
/**
|
||||
* @brief Enables a logger level of a specific context.
|
||||
*
|
||||
* Use context ALL_LOGGERS to manipulate all loggers.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param context context to set level
|
||||
* @param log_level logger level to eanble
|
||||
*/
|
||||
void (*enable_log_level) (logger_manager_t *this, logger_context_t context,log_level_t log_level);
|
||||
|
||||
/**
|
||||
* @brief Disables a logger level of a specific context.
|
||||
*
|
||||
* Use context ALL_LOGGERS to manipulate all loggers.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param context context to set level
|
||||
* @param log_level logger level to disable
|
||||
*/
|
||||
void (*disable_log_level) (logger_manager_t *this, logger_context_t context,log_level_t log_level);
|
||||
|
||||
/**
|
||||
* @brief Sets the output of a logger.
|
||||
*
|
||||
* Use context ALL_LOGGERS to redirect all loggers.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param context context to set output
|
||||
* @param log_level logger level to disable
|
||||
*/
|
||||
void (*set_output) (logger_manager_t *this, logger_context_t context, FILE *output);
|
||||
};
|
||||
|
||||
/**
|
||||
* The single and global instance of the logger_manager
|
||||
*/
|
||||
extern logger_manager_t *logger_manager;
|
||||
|
||||
/**
|
||||
* Initialize the logger manager with all its logger.
|
||||
* Has to be called before logger_manager is accessed.
|
||||
*/
|
||||
void logger_manager_init(void);
|
||||
|
||||
/**
|
||||
* Free any resources hold by the logger manager. Do
|
||||
* not access logger_manager after this call.
|
||||
*/
|
||||
void logger_manager_cleanup(void);
|
||||
|
||||
#endif /*LOGGER_MANAGER_H_*/
|
||||
@@ -1,255 +0,0 @@
|
||||
/**
|
||||
* @file tester.c
|
||||
*
|
||||
* @brief Implementation of tester_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "tester.h"
|
||||
|
||||
|
||||
|
||||
typedef struct private_tester_t private_tester_t;
|
||||
|
||||
/**
|
||||
* @brief Private Data of tester_t class.
|
||||
*
|
||||
*/
|
||||
struct private_tester_t {
|
||||
|
||||
/**
|
||||
* Protected interface of tester_t.
|
||||
*/
|
||||
protected_tester_t protected;
|
||||
|
||||
/**
|
||||
* Runs a specific test.
|
||||
*
|
||||
* @param tester associated tester object
|
||||
* @param test_function test function to perform
|
||||
* @param test_name name for the given test
|
||||
*/
|
||||
void (*run_test) (private_tester_t *tester, void (*test_function) (protected_tester_t * tester), char * test_name);
|
||||
|
||||
/**
|
||||
* Returns the difference of to timeval structs in microseconds.
|
||||
*
|
||||
* @warning this function is also defined in the event queue
|
||||
* in later improvements, this function can be added to a general
|
||||
* class type!
|
||||
*
|
||||
* @param end_time end time
|
||||
* @param start_time start time
|
||||
*
|
||||
* @TODO make object function or move to utils!
|
||||
*
|
||||
* @return difference in microseconds
|
||||
*/
|
||||
long (*time_difference) (private_tester_t *tester,struct timeval *end_time, struct timeval *start_time);
|
||||
|
||||
/**
|
||||
* Output is written into this file.
|
||||
*/
|
||||
FILE* output;
|
||||
|
||||
/**
|
||||
* Number of already performed tests.
|
||||
*/
|
||||
int tests_count;
|
||||
|
||||
/**
|
||||
* Number of failed tests.
|
||||
*/
|
||||
int failed_tests_count;
|
||||
|
||||
/**
|
||||
* Number of failed asserts in current test.
|
||||
*/
|
||||
int failed_asserts_count;
|
||||
|
||||
/**
|
||||
* TRUE if also succeeded asserts should be written to output.
|
||||
*/
|
||||
bool display_succeeded_asserts;
|
||||
|
||||
/**
|
||||
* Mutex to make this class thread-save.
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of tester_t.perform_tests.
|
||||
*/
|
||||
static void perform_tests(private_tester_t *this,test_t **tests)
|
||||
{
|
||||
int current_test = 0;
|
||||
fprintf(this->output,"\nStart testing...\n\n");
|
||||
fprintf(this->output,"_____________________________________________________________________\n");
|
||||
fprintf(this->output,"Testname | running time\n");
|
||||
fprintf(this->output,"_______________________________________________________|_____________\n");
|
||||
|
||||
while (tests[current_test] != NULL)
|
||||
{
|
||||
this->run_test(this,tests[current_test]->test_function,tests[current_test]->test_name);
|
||||
current_test++;
|
||||
}
|
||||
fprintf(this->output,"=====================================================================\n");
|
||||
fprintf(this->output,"End testing. %d of %d tests succeeded\n",this->tests_count - this->failed_tests_count,this->tests_count);
|
||||
fprintf(this->output,"=====================================================================\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of tester_t.perform_test.
|
||||
*/
|
||||
static void perform_test(private_tester_t *this, test_t *test)
|
||||
{
|
||||
test_t *tests[] = {test, NULL};
|
||||
return (perform_tests(this,tests));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference of to timeval structs in microseconds.
|
||||
*
|
||||
* @warning this function is also defined in the event queue
|
||||
* in later improvements, this function can be added to a general
|
||||
* class type!
|
||||
*
|
||||
* @param end_time end time
|
||||
* @param start_time start time
|
||||
*
|
||||
* @TODO make object function or move to utils!
|
||||
*
|
||||
* @return difference in microseconds
|
||||
*/
|
||||
static long time_difference(private_tester_t *this,struct timeval *end_time, struct timeval *start_time)
|
||||
{
|
||||
long seconds, microseconds;
|
||||
|
||||
seconds = (end_time->tv_sec - start_time->tv_sec);
|
||||
microseconds = (end_time->tv_usec - start_time->tv_usec);
|
||||
return ((seconds * 1000000) + microseconds);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of private_tester_t.run_test.
|
||||
*/
|
||||
static void run_test(private_tester_t *this, void (*test_function) (protected_tester_t * tester), char * test_name)
|
||||
{
|
||||
struct timeval start_time, end_time;
|
||||
long timediff;
|
||||
this->tests_count++;
|
||||
this->failed_asserts_count = 0;
|
||||
fprintf(this->output,"%-55s\n", test_name);
|
||||
gettimeofday(&start_time,NULL);
|
||||
test_function(&(this->protected));
|
||||
gettimeofday(&end_time,NULL);
|
||||
timediff = this->time_difference(this,&end_time, &start_time);
|
||||
|
||||
if (this->failed_asserts_count > 0)
|
||||
{
|
||||
fprintf(this->output," => Test failed: %-37s|%10ld us\n",test_name,timediff);
|
||||
}else
|
||||
{
|
||||
fprintf(this->output,"\033[1A\033[55C|%10ld us\033[1B\033[80D",timediff);
|
||||
}
|
||||
if (this->failed_asserts_count > 0)
|
||||
{
|
||||
this->failed_tests_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of tester_t.assert_true.
|
||||
*/
|
||||
static void assert_true(private_tester_t *this, bool to_be_true,char * assert_name)
|
||||
{
|
||||
if (assert_name == NULL)
|
||||
{
|
||||
assert_name = "unknown";
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
if (!to_be_true)
|
||||
{
|
||||
this->failed_asserts_count++;
|
||||
fprintf(this->output," check '%s' failed!\n", assert_name);
|
||||
}else
|
||||
{
|
||||
if (this->display_succeeded_asserts)
|
||||
{
|
||||
fprintf(this->output," check '%s' succeeded\n", assert_name);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of tester_t.assert_false.
|
||||
*/
|
||||
static void assert_false(private_tester_t *this, bool to_be_false,char * assert_name)
|
||||
{
|
||||
this->protected.assert_true(&(this->protected),(!to_be_false),assert_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of tester_t.destroy.
|
||||
*/
|
||||
static void destroy(private_tester_t *tester)
|
||||
{
|
||||
private_tester_t *this = (private_tester_t*) tester;
|
||||
pthread_mutex_destroy(&(this->mutex));
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
tester_t *tester_create(FILE *output, bool display_succeeded_asserts)
|
||||
{
|
||||
private_tester_t *this = malloc_thing(private_tester_t);
|
||||
|
||||
/* public functions */
|
||||
this->protected.public.destroy = (void (*) (tester_t *))destroy;
|
||||
this->protected.public.perform_tests = (void (*) (tester_t *, test_t**)) perform_tests;
|
||||
this->protected.public.perform_test = (void (*) (tester_t *, test_t*))perform_test;
|
||||
this->protected.assert_true = (void (*) (protected_tester_t *, bool, char*)) assert_true;
|
||||
this->protected.assert_false = (void (*) (protected_tester_t *, bool, char*)) assert_false;
|
||||
|
||||
/* private functions */
|
||||
this->run_test = run_test;
|
||||
this->time_difference = time_difference;
|
||||
|
||||
/* private data */
|
||||
this->display_succeeded_asserts = display_succeeded_asserts;
|
||||
this->failed_tests_count = 0;
|
||||
this->tests_count = 0;
|
||||
this->output = output;
|
||||
pthread_mutex_init(&(this->mutex),NULL);
|
||||
|
||||
return &(this->protected.public);
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/**
|
||||
* @file tester.h
|
||||
*
|
||||
* @brief Interface of tester_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TESTER_H_
|
||||
#define TESTER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
|
||||
/* must be defined here cause it is used in test_t */
|
||||
typedef struct protected_tester_t protected_tester_t;
|
||||
|
||||
typedef struct test_t test_t;
|
||||
|
||||
/**
|
||||
* @brief Representing a specified test.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct test_t {
|
||||
/**
|
||||
* Testfunction called for this test.
|
||||
*
|
||||
* @param tester associated tester_t object
|
||||
*/
|
||||
void (*test_function) (protected_tester_t * tester);
|
||||
|
||||
/**
|
||||
* Name of the test.
|
||||
*/
|
||||
char * test_name;
|
||||
};
|
||||
|
||||
|
||||
typedef struct tester_t tester_t;
|
||||
|
||||
/**
|
||||
* @brief A class to perform tests.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - tester_create()
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct tester_t {
|
||||
/**
|
||||
* @brief Test all testcases in array tests with specific tester_t object.
|
||||
*
|
||||
* @param tester tester_t object
|
||||
* @param tests pointer to an array of test_t-pointers.
|
||||
* The last item has to be NULL to mark end of array.
|
||||
*/
|
||||
void (*perform_tests) (tester_t *tester,test_t **tests);
|
||||
|
||||
/**
|
||||
* @brief Run a specific test case.
|
||||
*
|
||||
* @param this tester_t object
|
||||
* @param test pointer to a test_t object which will be performed
|
||||
*/
|
||||
void (*perform_test) (tester_t *tester, test_t *test);
|
||||
|
||||
/**
|
||||
* @brief Destroys a tester_t object.
|
||||
*
|
||||
* @param tester tester_t object
|
||||
*/
|
||||
void (*destroy) (tester_t *tester);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A class used in a specific testcase.
|
||||
*
|
||||
* For each testcase an object of this type is passed to the testfunction. The testfunction uses this
|
||||
* object to check specific asserts with protected_tester_t.assert_true and protected_tester_t.assert_false.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - tester_create()
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct protected_tester_t {
|
||||
|
||||
/**
|
||||
* Public functions of a tester_t object
|
||||
*/
|
||||
tester_t public;
|
||||
|
||||
/**
|
||||
* @brief Is called in a testcase to check a specific situation for TRUE.
|
||||
*
|
||||
* Log-Values to the tester output are protected from multiple access.
|
||||
*
|
||||
* @param this tester_t object
|
||||
* @param to_be_true assert which has to be TRUE
|
||||
* @param assert_name name of the assertion
|
||||
*/
|
||||
void (*assert_true) (protected_tester_t *tester, bool to_be_true, char *assert_name);
|
||||
|
||||
/**
|
||||
* @brief Is called in a testcase to check a specific situation for FALSE.
|
||||
*
|
||||
* Log-Values to the tester output are protected from multiple access.
|
||||
*
|
||||
* @param this tester_t object
|
||||
* @param to_be_false assert which has to be FALSE
|
||||
* @param assert_name name of the assertion
|
||||
*/
|
||||
void (*assert_false) (protected_tester_t *tester, bool to_be_false, char *assert_name);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a tester_t object used to perform tests with.
|
||||
*
|
||||
* @param output test output is written to this output.
|
||||
* @param display_succeeded_asserts has to be TRUE, if all asserts should be displayed,
|
||||
* FALSE otherwise
|
||||
*
|
||||
* @return tester_t object
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
tester_t *tester_create(FILE *output, bool display_succeeded_asserts);
|
||||
|
||||
#endif /*TESTER_H_*/
|
||||
Reference in New Issue
Block a user