updated hashmap, rewritten name_descs.c
This commit is contained in:
parent
d3235a80cc
commit
71375a1f55
|
@ -1,4 +1,4 @@
|
|||
[submodule "core/hashmap"]
|
||||
path = core/hashmap
|
||||
[submodule "hashmap"]
|
||||
path = hashmap
|
||||
url = https://git.tcp.direct/aiden/hashmap.git
|
||||
branch = main
|
||||
branch = main
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
ISC License
|
||||
|
||||
Copyright (c) 2022, aiden (aiden@citalopram.reviews)
|
||||
Copyright (c) 2023, aiden (aiden@cmp.bz)
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__services__h
|
||||
#define bidirectiond_core__services__h
|
||||
#ifndef bidirectiond__services__h
|
||||
#define bidirectiond__services__h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "../src/headers/bdd_event.h"
|
||||
#include "../src/headers/bdd_service.h"
|
||||
#include "../src/headers/bdd_name_descs.h"
|
||||
#include "../src/headers/name_descs.h"
|
||||
#include "../src/headers/bdd_cont.h"
|
||||
#include "../src/headers/bdd_shutdown_status.h"
|
||||
#include "../src/headers/bidirectiond_n_io.h"
|
||||
|
@ -43,7 +43,6 @@ void bdd_set_associated(
|
|||
);
|
||||
void *bdd_get_associated(struct bdd_conversation *conversation);
|
||||
bool bdd_name_descs_add_service_instance(
|
||||
struct bdd_name_descs *name_descs,
|
||||
const char *scope,
|
||||
size_t scope_sz,
|
||||
const struct bdd_service *service,
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef bidirectiond__settings__h
|
||||
#define bidirectiond__settings__h
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../src/headers/name_descs.h"
|
||||
#include "../src/headers/bdd_settings.h"
|
||||
#include "../src/headers/bdd_service.h"
|
||||
#include "../src/headers/bdd_stop.h"
|
||||
|
||||
struct bdd_name_descs;
|
||||
struct bdd_instance *bdd_go(struct bdd_settings settings);
|
||||
void bdd_wait(void);
|
||||
void bdd_destroy(void);
|
||||
|
||||
void bdd_name_descs_use_cert_pkey(
|
||||
X509 *x509,
|
||||
EVP_PKEY *pkey
|
||||
);
|
||||
|
||||
bool bdd_name_descs_create(uint16_t n_threads);
|
||||
void bdd_name_descs_destroy(void);
|
||||
|
||||
#endif
|
|
@ -1,4 +1,5 @@
|
|||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <poll.h>
|
||||
|
@ -11,12 +12,14 @@
|
|||
|
||||
#include "headers/instance.h"
|
||||
#include "headers/accept.h"
|
||||
#include "headers/serve.h"
|
||||
#include "headers/unlikely.h"
|
||||
#include "headers/debug_log.h"
|
||||
#include "headers/conversations.h"
|
||||
#include "headers/name_descs.h"
|
||||
#include "headers/bdd_service.h"
|
||||
#include "headers/bdd_stop.h"
|
||||
#include "headers/hashmap.h"
|
||||
|
||||
int bdd_alpn_cb(
|
||||
SSL *client_ssl,
|
||||
|
@ -24,9 +27,9 @@ int bdd_alpn_cb(
|
|||
unsigned char *outlen,
|
||||
const unsigned char *_,
|
||||
unsigned int __,
|
||||
struct bdd_conversation *conversation
|
||||
struct bdd_ssl_cb_ctx *ctx
|
||||
) {
|
||||
const unsigned char *protocol_name = conversation->aopn.pn.protocol_name;
|
||||
const unsigned char *protocol_name = ctx->protocol_name;
|
||||
if (protocol_name == NULL) {
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
|
@ -35,9 +38,10 @@ int bdd_alpn_cb(
|
|||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_conversation *conversation) {
|
||||
int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_ssl_cb_ctx *ctx) {
|
||||
struct bdd_conversation *conversation = ctx->conversation;
|
||||
struct hashmap *name_descs = bdd_gv.name_descs;
|
||||
struct hashmap_key key = HASHMAP_KEY_INITIALIZER;
|
||||
struct hashmap_key key;
|
||||
int r = SSL_CLIENT_HELLO_ERROR;
|
||||
const unsigned char *extension;
|
||||
size_t extension_sz;
|
||||
|
@ -47,7 +51,7 @@ int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_conversation *conversat
|
|||
if (extension == NULL) {
|
||||
return SSL_CLIENT_HELLO_ERROR;
|
||||
}
|
||||
if (extension_sz <= 4) {
|
||||
if (extension_sz < 5) {
|
||||
return SSL_CLIENT_HELLO_ERROR;
|
||||
}
|
||||
if (unlikely(extension[2] != TLSEXT_NAMETYPE_host_name)) {
|
||||
|
@ -55,9 +59,15 @@ int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_conversation *conversat
|
|||
}
|
||||
|
||||
size_t name_sz = (size_t)ntohs(*(unsigned short int *)(&(extension[3])));
|
||||
const unsigned char *name = (const unsigned char *)&(extension[5]);
|
||||
if (extension_sz != 5 + name_sz) {
|
||||
return SSL_CLIENT_HELLO_ERROR;
|
||||
}
|
||||
const char *name = (const char *)&(extension[5]);
|
||||
|
||||
bdd_name_trim(name, &(name_sz));
|
||||
name = bdd_name(name, &(name_sz));
|
||||
if (unlikely(name == NULL)) {
|
||||
return SSL_CLIENT_HELLO_ERROR;
|
||||
}
|
||||
|
||||
const unsigned char *alpn;
|
||||
size_t alpn_sz;
|
||||
|
@ -81,16 +91,16 @@ int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_conversation *conversat
|
|||
|
||||
uint8_t found_req = 0;
|
||||
for (size_t idx = 0;;) {
|
||||
hashmap_key_obtain(
|
||||
name_descs,
|
||||
&(key),
|
||||
&(name[idx]),
|
||||
name_sz
|
||||
hashmap_key(
|
||||
(void *)&(name[idx]),
|
||||
name_sz,
|
||||
&(key)
|
||||
);
|
||||
struct bdd_name_desc *name_desc;
|
||||
if (hashmap_get(name_descs, &(key), (void *)&(name_desc))) {
|
||||
if (hashmap_cas(name_descs, ctx->area, &(key), (void **)&(name_desc), NULL, hashmap_cas_get, (void *)1) == hashmap_cas_again) {
|
||||
if (!(found_req & 0b01) && name_desc->x509 != NULL) {
|
||||
found_req |= 0b01;
|
||||
// this does up the rc
|
||||
SSL_use_certificate(client_ssl, name_desc->x509);
|
||||
SSL_use_PrivateKey(client_ssl, name_desc->pkey);
|
||||
}
|
||||
|
@ -116,8 +126,8 @@ int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_conversation *conversat
|
|||
if (found == NULL) {
|
||||
// ...then use this service
|
||||
found = inst;
|
||||
assert(conversation->aopn.pn.protocol_name == NULL);
|
||||
assert(conversation->aopn.pn.cstr_protocol_name == NULL);
|
||||
assert(ctx->protocol_name == NULL);
|
||||
assert(ctx->cstr_protocol_name == NULL);
|
||||
}
|
||||
// skip the for loop
|
||||
goto alpn_find_iter;
|
||||
|
@ -128,6 +138,7 @@ int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_conversation *conversat
|
|||
uint8_t alpn_len = alpn[alpn_idx];
|
||||
// bounds checking
|
||||
if (alpn_len == 0 || alpn_sz - 1 - alpn_idx < alpn_len) {
|
||||
pthread_rwlock_unlock(&(name_desc->rwlock));
|
||||
return SSL_CLIENT_HELLO_ERROR;
|
||||
}
|
||||
// loop through the list of the service's supported protocols' names,
|
||||
|
@ -141,8 +152,8 @@ int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_conversation *conversat
|
|||
) == 0
|
||||
) {
|
||||
alpn_sz = alpn_idx; // includes the length byte
|
||||
conversation->aopn.pn.protocol_name = &(alpn[alpn_idx]);
|
||||
conversation->aopn.pn.cstr_protocol_name = sp[sp_idx];
|
||||
ctx->protocol_name = &(alpn[alpn_idx]);
|
||||
ctx->cstr_protocol_name = sp[sp_idx];
|
||||
found = inst;
|
||||
// the rest of the service's implemented protocols
|
||||
// cannot be more preferred by the client
|
||||
|
@ -166,30 +177,28 @@ int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_conversation *conversat
|
|||
found_req |= 0b10;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_rwlock_unlock(&(name_desc->rwlock));
|
||||
|
||||
if (found_req == 0b11) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name_sz == 0) {
|
||||
*alert = SSL_AD_UNRECOGNIZED_NAME;
|
||||
goto out;
|
||||
return SSL_AD_UNRECOGNIZED_NAME;
|
||||
}
|
||||
do {
|
||||
idx += 1;
|
||||
name_sz -= 1;
|
||||
} while (name_sz != 0 && name[idx] != '.');
|
||||
}
|
||||
r = SSL_CLIENT_HELLO_SUCCESS;
|
||||
out:;
|
||||
hashmap_key_release(bdd_gv.name_descs, &(key), false);
|
||||
return r;
|
||||
|
||||
return SSL_CLIENT_HELLO_SUCCESS;
|
||||
}
|
||||
|
||||
enum bdd_cont bdd_accept_continue(struct bdd_conversation *conversation) {
|
||||
enum bdd_cont bdd_accept_continue(struct bdd_ssl_cb_ctx *ctx) {
|
||||
struct bdd_conversation *conversation = ctx->conversation;
|
||||
struct bdd_io *io = conversation->io_array;
|
||||
SSL_CTX *ssl_ctx = SSL_get_SSL_CTX(io->io.ssl);
|
||||
SSL_CTX_set_client_hello_cb(ssl_ctx, (void *)bdd_hello_cb, conversation);
|
||||
SSL_CTX_set_alpn_select_cb(ssl_ctx, (void *)bdd_alpn_cb, conversation);
|
||||
int r = SSL_accept(io->io.ssl);
|
||||
if (r <= 0) {
|
||||
r = SSL_get_error(io->io.ssl, r);
|
||||
|
@ -203,9 +212,9 @@ enum bdd_cont bdd_accept_continue(struct bdd_conversation *conversation) {
|
|||
|
||||
struct bdd_service_instance *service_inst = conversation->sosi.service_instance;
|
||||
conversation->sosi.service = service_inst->service;
|
||||
const char *cstr_protocol_name = conversation->aopn.pn.cstr_protocol_name;
|
||||
conversation->aopn.associated.data = NULL;
|
||||
conversation->aopn.associated.destructor = NULL;
|
||||
const char *cstr_protocol_name = ctx->cstr_protocol_name;
|
||||
conversation->associated.data = NULL;
|
||||
conversation->associated.destructor = NULL;
|
||||
conversation->state = bdd_conversation_established;
|
||||
|
||||
struct sockaddr sockaddr;
|
|
@ -15,7 +15,7 @@
|
|||
#include "headers/bdd_event.h"
|
||||
|
||||
void *bdd_get_associated(struct bdd_conversation *conversation) {
|
||||
return conversation->aopn.associated.data;
|
||||
return conversation->associated.data;
|
||||
}
|
||||
void bdd_set_associated(
|
||||
struct bdd_conversation *conversation,
|
||||
|
@ -23,11 +23,11 @@ void bdd_set_associated(
|
|||
void (*destructor)(void *)
|
||||
) {
|
||||
assert(conversation != NULL);
|
||||
if (conversation->aopn.associated.destructor != NULL) {
|
||||
conversation->aopn.associated.destructor(conversation->aopn.associated.data);
|
||||
if (conversation->associated.destructor != NULL) {
|
||||
conversation->associated.destructor(conversation->associated.data);
|
||||
}
|
||||
conversation->aopn.associated.data = data;
|
||||
conversation->aopn.associated.destructor = destructor;
|
||||
conversation->associated.data = data;
|
||||
conversation->associated.destructor = destructor;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -94,8 +94,8 @@ struct bdd_conversation *bdd_conversation_obtain(int epoll_fd) {
|
|||
conversation->n_blocking = 0;
|
||||
conversation->n_in_epoll_with_events = 0;
|
||||
conversation->n_ev = 0;
|
||||
conversation->aopn.pn.protocol_name = NULL;
|
||||
conversation->aopn.pn.cstr_protocol_name = NULL;
|
||||
conversation->associated.data = NULL;
|
||||
conversation->associated.destructor = NULL;
|
||||
return conversation;
|
||||
}
|
||||
void bdd_conversation_discard(struct bdd_conversation *conversation) {
|
|
@ -1,24 +1,25 @@
|
|||
#ifndef bidirectiond_core__accept__h
|
||||
#define bidirectiond_core__accept__h
|
||||
#ifndef bidirectiond__accept__h
|
||||
#define bidirectiond__accept__h
|
||||
|
||||
#include <hashmap/hashmap.h>
|
||||
#include "bdd_cont.h"
|
||||
|
||||
struct bdd_conversation;
|
||||
struct bdd_io;
|
||||
|
||||
struct bdd_ssl_cb_ctx;
|
||||
int bdd_alpn_cb(
|
||||
SSL *client_ssl,
|
||||
const unsigned char **out,
|
||||
unsigned char *outlen,
|
||||
const unsigned char *_,
|
||||
unsigned int __,
|
||||
struct bdd_conversation *conversation
|
||||
struct bdd_ssl_cb_ctx *ctx
|
||||
);
|
||||
int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_conversation *conversation);
|
||||
struct bdd_ssl_cb_ctx;
|
||||
int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_ssl_cb_ctx *ctx);
|
||||
struct bdd_worker_data;
|
||||
void bdd_accept(struct bdd_worker_data *worker_data);
|
||||
enum bdd_cont bdd_connect_continue(struct bdd_io *io);
|
||||
enum bdd_cont bdd_accept_continue(struct bdd_conversation *conversation);
|
||||
enum bdd_cont bdd_accept_continue(struct bdd_ssl_cb_ctx *ctx);
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__bdd_cont__h
|
||||
#define bidirectiond_core__bdd_cont__h
|
||||
#ifndef bidirectiond__bdd_cont__h
|
||||
#define bidirectiond__bdd_cont__h
|
||||
|
||||
enum bdd_cont {
|
||||
bdd_cont_conversation_discard,
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__bdd_event__h
|
||||
#define bidirectiond_core__bdd_event__h
|
||||
#ifndef bidirectiond__bdd_event__h
|
||||
#define bidirectiond__bdd_event__h
|
||||
|
||||
#include "bidirectiond_n_io.h"
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__bdd_io__h
|
||||
#define bidirectiond_core__bdd_io__h
|
||||
#ifndef bidirectiond__bdd_io__h
|
||||
#define bidirectiond__bdd_io__h
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <stdint.h>
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__bdd_service__h
|
||||
#define bidirectiond_core__bdd_service__h
|
||||
#ifndef bidirectiond__bdd_service__h
|
||||
#define bidirectiond__bdd_service__h
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -20,7 +20,6 @@ struct bdd_service {
|
|||
|
||||
void (*instance_info_destructor)(void *instance_info);
|
||||
bool (*instantiate)(
|
||||
struct bdd_name_descs *name_descs,
|
||||
const struct bdd_service *service,
|
||||
size_t n_arguments,
|
||||
const char **arguments
|
|
@ -1,17 +1,14 @@
|
|||
#ifndef bidirectiond_core__bdd_settings__h
|
||||
#define bidirectiond_core__bdd_settings__h
|
||||
#ifndef bidirectiond__bdd_settings__h
|
||||
#define bidirectiond__bdd_settings__h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
|
||||
struct bdd_settings {
|
||||
struct bdd_name_descs *name_descs;
|
||||
|
||||
int epoll_timeout;
|
||||
|
||||
int n_conversations;
|
||||
int n_epoll_oevents;
|
||||
unsigned short int n_worker_threads;
|
||||
|
||||
sigset_t sigmask;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__bdd_shutdown_status__h
|
||||
#define bidirectiond_core__bdd_shutdown_status__h
|
||||
#ifndef bidirectiond__bdd_shutdown_status__h
|
||||
#define bidirectiond__bdd_shutdown_status__h
|
||||
|
||||
enum bdd_shutdown_status {
|
||||
bdd_shutdown_conversation_discard,
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef bidirectiond__bdd_stop__h
|
||||
#define bidirectiond__bdd_stop__h
|
||||
|
||||
void bdd_stop(void);
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__conversations__h
|
||||
#define bidirectiond_core__conversations__h
|
||||
#ifndef bidirectiond__conversations__h
|
||||
#define bidirectiond__conversations__h
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -55,13 +55,7 @@ struct bdd_conversation {
|
|||
|
||||
bdd_io_id n_ev;
|
||||
|
||||
union {
|
||||
struct bdd_associated associated;
|
||||
struct {
|
||||
const unsigned char *protocol_name;
|
||||
const char *cstr_protocol_name;
|
||||
} pn;
|
||||
} aopn;
|
||||
struct bdd_associated associated;
|
||||
};
|
||||
|
||||
enum bdd_conversation_init_status {
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__debug_log__h
|
||||
#define bidirectiond_core__debug_log__h
|
||||
#ifndef bidirectiond__debug_log__h
|
||||
#define bidirectiond__debug_log__h
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef bidriectiond__hashmap__h
|
||||
#define bidriectiond__hashmap__h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static bool chcd(char ch, uint8_t *cd) {
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
*cd = ch - '0';
|
||||
} else if (ch >= 'a' && ch <= 'z') {
|
||||
*cd = ch - 'a' + 10;
|
||||
} else if (ch == '-') {
|
||||
*cd = 10 + 26;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static uint32_t HASHMAP_HASH_FUNCTION(char *input, uint32_t sz) {
|
||||
uint8_t bytes[4] = { 0, 0, 0, 0, };
|
||||
uint8_t prev[4] = { 0, 0, 0, 0, };
|
||||
uint8_t bytes_idx = 0, cd;
|
||||
for (uint32_t idx = 0; idx < sz; ++idx) {
|
||||
if (!chcd(input[idx], &(cd))) {
|
||||
*(uint32_t *)bytes *= 37;
|
||||
bytes_idx = 0;
|
||||
continue;
|
||||
}
|
||||
bytes[bytes_idx] += ((idx + cd) * (prev[bytes_idx] + 1));
|
||||
prev[bytes_idx] = cd;
|
||||
bytes_idx = (bytes_idx + 1) & 0b11;
|
||||
}
|
||||
return *(uint32_t *)bytes;
|
||||
}
|
||||
#include <hashmap.h>
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__instance__h
|
||||
#define bidirectiond_core__instance__h
|
||||
#ifndef bidirectiond__instance__h
|
||||
#define bidirectiond__instance__h
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdatomic.h>
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__name_descs__h
|
||||
#define bidirectiond_core__name_descs__h
|
||||
#ifndef bidirectiond__name_descs__h
|
||||
#define bidirectiond__name_descs__h
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
|
@ -10,11 +10,16 @@ struct bdd_service_instance {
|
|||
struct bdd_service_instance *next;
|
||||
};
|
||||
struct bdd_name_desc {
|
||||
// one writer, multiple readers
|
||||
// only protects this struct's members!! (obviously not the struct itself!!)
|
||||
pthread_rwlock_t rwlock;
|
||||
|
||||
X509 *x509;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
struct bdd_service_instance *service_instances;
|
||||
};
|
||||
|
||||
void bdd_name_trim(const unsigned char *name, size_t *name_sz);
|
||||
const char *bdd_name(const char *name, size_t *name_sz);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef bidirectiond__serve__h
|
||||
#define bidirectiond__serve__h
|
||||
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include "timeout_list.h"
|
||||
|
||||
struct hashmap_area;
|
||||
struct bdd_conversation;
|
||||
struct bdd_ssl_cb_ctx {
|
||||
struct hashmap_area *area;
|
||||
struct bdd_conversation *conversation;
|
||||
const unsigned char *protocol_name;
|
||||
const char *cstr_protocol_name;
|
||||
};
|
||||
struct bdd_worker_data {
|
||||
int epoll_fd;
|
||||
int serve_fd;
|
||||
SSL_CTX *ssl_ctx;
|
||||
struct bdd_ssl_cb_ctx ssl_cb_ctx;
|
||||
struct bdd_tl timeout_list;
|
||||
struct epoll_event events[];
|
||||
};
|
||||
void *bdd_serve(struct bdd_worker_data *worker_data);
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef bidirectiond_core__timeout_list__h
|
||||
#define bidirectiond_core__timeout_list__h
|
||||
#ifndef bidirectiond__timeout_list__h
|
||||
#define bidirectiond__timeout_list__h
|
||||
|
||||
#include <pthread.h>
|
||||
#include "conversations.h"
|
|
@ -7,6 +7,7 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "headers/hashmap.h"
|
||||
#include "headers/instance.h"
|
||||
#include "headers/conversations.h"
|
||||
#include "headers/bdd_settings.h"
|
||||
|
@ -21,8 +22,6 @@ struct bdd_gv bdd_gv = {
|
|||
.n_running_threads_mutex = PTHREAD_MUTEX_INITIALIZER,
|
||||
.n_running_threads_cond = PTHREAD_COND_INITIALIZER,
|
||||
|
||||
.name_descs = NULL,
|
||||
|
||||
|
||||
.eventfd = -1,
|
||||
|
||||
|
@ -104,6 +103,7 @@ void bdd_destroy(void) {
|
|||
struct bdd_worker_data *worker = bdd_gv_worker(idx);
|
||||
close(worker->epoll_fd);
|
||||
SSL_CTX_free(worker->ssl_ctx);
|
||||
hashmap_area_release(bdd_gv.name_descs, worker->ssl_cb_ctx.area);
|
||||
}
|
||||
|
||||
for (
|
||||
|
@ -126,12 +126,12 @@ bool bdd_go(struct bdd_settings settings) {
|
|||
if (
|
||||
settings.sockfds == NULL ||
|
||||
settings.n_conversations <= 0 ||
|
||||
settings.n_epoll_oevents <= 0 ||
|
||||
settings.name_descs == NULL ||
|
||||
settings.n_worker_threads <= 0
|
||||
settings.n_epoll_oevents <= 0
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bdd_gv.n_workers = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
|
||||
bool locked = false;
|
||||
|
||||
|
@ -158,8 +158,6 @@ bool bdd_go(struct bdd_settings settings) {
|
|||
// epoll
|
||||
bdd_gv.n_epoll_oevents = settings.n_epoll_oevents;
|
||||
bdd_gv.epoll_timeout = settings.epoll_timeout;
|
||||
// name_descs
|
||||
bdd_gv.name_descs = settings.name_descs;
|
||||
// conversations
|
||||
bdd_gv.n_conversations = settings.n_conversations;
|
||||
bdd_gv.conversations = malloc(
|
||||
|
@ -168,7 +166,7 @@ bool bdd_go(struct bdd_settings settings) {
|
|||
((
|
||||
sizeof(struct bdd_worker_data) +
|
||||
(settings.n_epoll_oevents * sizeof(struct epoll_event))
|
||||
) * settings.n_worker_threads) // workers
|
||||
) * bdd_gv.n_workers) // workers
|
||||
);
|
||||
if (bdd_gv.conversations == NULL) {
|
||||
goto err;
|
||||
|
@ -201,10 +199,9 @@ bool bdd_go(struct bdd_settings settings) {
|
|||
locked = true;
|
||||
struct bdd_worker_data *worker_data = (struct bdd_worker_data *)&(bdd_gv.available_conversations.ids[settings.n_conversations]);
|
||||
bdd_gv.worker = worker_data;
|
||||
bdd_gv.n_workers = settings.n_worker_threads;
|
||||
#define next_worker_data \
|
||||
(struct bdd_worker_data *)((char *)worker_data + sizeof(struct bdd_worker_data) + (sizeof(struct epoll_event) * settings.n_epoll_oevents))
|
||||
for (bdd_gv.workers_idx = 0; bdd_gv.workers_idx < settings.n_worker_threads; ++bdd_gv.workers_idx) {
|
||||
for (bdd_gv.workers_idx = 0; bdd_gv.workers_idx < bdd_gv.n_workers; ++bdd_gv.workers_idx) {
|
||||
int epoll_fd = epoll_create1(0);
|
||||
SSL_CTX *ssl_ctx = bdd_ssl_ctx_skel();
|
||||
bdd_tl_init(&(worker_data->timeout_list));
|
||||
|
@ -217,6 +214,9 @@ bool bdd_go(struct bdd_settings settings) {
|
|||
};
|
||||
worker_data->epoll_fd = epoll_fd;
|
||||
worker_data->ssl_ctx = ssl_ctx;
|
||||
worker_data->ssl_cb_ctx.area = hashmap_area(bdd_gv.name_descs);
|
||||
SSL_CTX_set_client_hello_cb(ssl_ctx, (void *)bdd_hello_cb, &(worker_data->ssl_cb_ctx));
|
||||
SSL_CTX_set_alpn_select_cb(ssl_ctx, (void *)bdd_alpn_cb, &(worker_data->ssl_cb_ctx));
|
||||
worker_data->serve_fd = settings.sockfds[bdd_gv.workers_idx];
|
||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, worker_data->serve_fd, &(event)) != 0) {
|
||||
goto worker_create_err;
|
|
@ -0,0 +1,537 @@
|
|||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "headers/hashmap.h"
|
||||
|
||||
#include "headers/name_descs.h"
|
||||
#include "headers/bdd_service.h"
|
||||
#include "headers/instance.h"
|
||||
|
||||
#define HASHMAP bdd_gv.name_descs
|
||||
static struct hashmap_area *AREA = NULL;
|
||||
|
||||
// name_descs: hashmap of name_desc
|
||||
// name_desc: see `struct bdd_name_desc` in name_descs.h
|
||||
|
||||
// struct bdd_name_desc
|
||||
static struct bdd_name_desc *alloc_name_desc(void) {
|
||||
struct bdd_name_desc *name_desc = malloc(sizeof(struct bdd_name_desc));
|
||||
if (name_desc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (pthread_rwlock_init(&(name_desc->rwlock), NULL) != 0) {
|
||||
free(name_desc);
|
||||
return NULL;
|
||||
}
|
||||
name_desc->x509 = NULL;
|
||||
name_desc->pkey = NULL;
|
||||
name_desc->service_instances = NULL;
|
||||
return name_desc;
|
||||
}
|
||||
|
||||
static inline void remove_cert_pkey(struct bdd_name_desc *name_desc) {
|
||||
if (name_desc->x509 == NULL) {
|
||||
assert(name_desc->pkey == NULL);
|
||||
return;
|
||||
}
|
||||
assert(name_desc->pkey != NULL);
|
||||
|
||||
// misleading function name; it
|
||||
// actually decs the ref count and
|
||||
// frees the shit if the rc hits 0
|
||||
X509_free(name_desc->x509);
|
||||
EVP_PKEY_free(name_desc->pkey);
|
||||
name_desc->x509 = NULL;
|
||||
name_desc->pkey = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void remove_service_insts(struct bdd_name_desc *name_desc) {
|
||||
for (
|
||||
struct bdd_service_instance **service_inst = &(name_desc->service_instances);
|
||||
(*service_inst) != NULL;
|
||||
) {
|
||||
struct bdd_service_instance *curr = (*service_inst);
|
||||
(*service_inst) = curr->next;
|
||||
if (curr->instance_info != NULL) {
|
||||
curr->service->instance_info_destructor((void *)curr->instance_info);
|
||||
}
|
||||
free(curr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static bool add_service_inst(
|
||||
struct bdd_name_desc *name_desc,
|
||||
struct bdd_service_instance *service_inst
|
||||
) {
|
||||
const char *const *inst_sp = service_inst->service->supported_protocols;
|
||||
|
||||
// iterate over the service instances
|
||||
// currently reachable from this name
|
||||
struct bdd_service_instance **curr = &(name_desc->service_instances);
|
||||
for (; (*curr) != NULL; curr = &((*curr)->next)) {
|
||||
const char *const *curr_sp = (*curr)->service->supported_protocols;
|
||||
|
||||
// services without a protocol list can, with low
|
||||
// priority (see: accept.c), handle any protocol
|
||||
// a NULL protocol list is effectively a wildcard
|
||||
if (inst_sp == NULL || curr_sp == NULL) {
|
||||
// if inst_sp is NULL, and curr_sp is NULL, then
|
||||
// return false as to not have multiple wildcard services
|
||||
if (inst_sp == curr_sp) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// prevent conflicts where a protocol
|
||||
// is listed by multiple services
|
||||
for (size_t idx = 0; curr_sp[idx]; ++idx) {
|
||||
for (size_t idx2 = 0; inst_sp[idx2]; ++idx2) {
|
||||
if (strcmp(curr_sp[idx], inst_sp[idx2]) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(*curr) = service_inst;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void set_cert_pkey(struct bdd_name_desc *name_desc, X509 *x509, EVP_PKEY *pkey) {
|
||||
name_desc->x509 = x509;
|
||||
name_desc->pkey = pkey;
|
||||
return;
|
||||
}
|
||||
|
||||
static void free_name_desc(struct bdd_name_desc *name_desc) {
|
||||
pthread_rwlock_destroy(&(name_desc->rwlock));
|
||||
remove_cert_pkey(name_desc);
|
||||
remove_service_insts(name_desc);
|
||||
free(name_desc);
|
||||
return;
|
||||
}
|
||||
|
||||
// name_descs hashmap
|
||||
static bool punycode_check(const char *input, unsigned int len, unsigned int n_basic) {
|
||||
// adapted from https://www.rfc-editor.org/rfc/rfc3492#appendix-C
|
||||
enum {
|
||||
base = 36, initial_bias = 72, initial_n = 0x80, tmin = 1, tmax = 26,
|
||||
skew = 38, damp = 700,
|
||||
};
|
||||
unsigned int
|
||||
n = initial_n,
|
||||
bias = initial_bias,
|
||||
out = n_basic;
|
||||
|
||||
// process after delimiter
|
||||
for (
|
||||
unsigned int i = 0, in = 0, oldi;
|
||||
in < len; // break after in >= len
|
||||
++out
|
||||
) {
|
||||
oldi = i;
|
||||
|
||||
unsigned int
|
||||
w = 1,
|
||||
k = base;
|
||||
|
||||
for (;; k += base) {
|
||||
if (in == len) {
|
||||
return false;
|
||||
}
|
||||
unsigned int digit = input[in++];
|
||||
|
||||
if (digit - 48 < 10) {
|
||||
digit -= 22;
|
||||
} else if (digit - 65 < 26) {
|
||||
digit -= 65;
|
||||
} else if (digit - 97 < 26) {
|
||||
digit -= 97;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (digit >= base) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (digit > (UINT_MAX - i) / w) {
|
||||
// `i += digit * w` would overflow
|
||||
return false;
|
||||
}
|
||||
i += digit * w;
|
||||
|
||||
unsigned int t;
|
||||
if (k <= bias) {
|
||||
t = tmin;
|
||||
} else if (k >= bias + tmax) {
|
||||
t = tmax;
|
||||
} else {
|
||||
t = k - bias;
|
||||
}
|
||||
if (digit < t) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (w > UINT_MAX / (base - t)) {
|
||||
// `w *= (base - t)` would overflow
|
||||
return false;
|
||||
}
|
||||
w *= (base - t);
|
||||
}
|
||||
|
||||
// `out + 1` to adapt for the character we're processing
|
||||
// (we'll increment `out` after this iteration with `++out` in the for loop's post statement)
|
||||
unsigned int numpoints = out + 1;
|
||||
unsigned int delta = (i - oldi) / (oldi == 0 ? damp : 2);
|
||||
delta += delta / numpoints;
|
||||
|
||||
for (k = 0; delta > ((base - tmin) * tmax) / 2; k += base) {
|
||||
delta /= base - tmin;
|
||||
}
|
||||
|
||||
bias = k + (base - tmin + 1) * delta / (delta + skew);
|
||||
|
||||
// add the amount of times wrapped around to n
|
||||
if (i / (out + 1) > UINT_MAX - n) {
|
||||
// `n += i / (out + 1)` would overflow
|
||||
return false;
|
||||
}
|
||||
n += i / (out + 1);
|
||||
|
||||
// wrap i around
|
||||
i %= (out + 1);
|
||||
|
||||
// to-do: xn--iea should return false (uppercase; \u0114)
|
||||
// (we already have `i` and `n`)
|
||||
// i'm not passionate enough to implement this; i don't
|
||||
// get paid enough ($0) and i'm rich anyway ($999,999,999).
|
||||
// am i the richest person ever? prolly.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// idna2008
|
||||
const char *bdd_name(const char *name, size_t *name_sz) {
|
||||
size_t sz = *name_sz;
|
||||
size_t idx = 0;
|
||||
if (sz >= 1 && name[sz - 1] == '.') {
|
||||
// conceptually remove the period
|
||||
// from the end of the string
|
||||
sz -= 1;
|
||||
}
|
||||
// max length for a fully-qualified dns
|
||||
// name is 255. if the domain name passed
|
||||
// to the function ends with a period, then
|
||||
// we decrement its size by 1. this code will
|
||||
// then treat the dns name as though it does end
|
||||
// with a period. (since the dns name is assumed to
|
||||
// end with a period, the maximum amount of octets
|
||||
// that can come before it must be 254.)
|
||||
if (sz > 254) {
|
||||
return NULL;
|
||||
}
|
||||
bool req_prd;
|
||||
if (sz > 0 && name[0] == '*') {
|
||||
// conceptually remove the
|
||||
// asterisk from the string
|
||||
sz -= 1;
|
||||
name += 1;
|
||||
req_prd = true;
|
||||
} else {
|
||||
req_prd = false;
|
||||
}
|
||||
if (sz > 0 && name[0] == '.') {
|
||||
if (sz == 254) {
|
||||
// invalid wildcard; name
|
||||
// guaranteed to exceed 255 octets
|
||||
return NULL;
|
||||
}
|
||||
// skip period
|
||||
idx = 1;
|
||||
} else if (req_prd) {
|
||||
// a period MUST follow an asterisk
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sz == 0) {
|
||||
goto success;
|
||||
}
|
||||
|
||||
bool name_contains_alphabetic_character = false;
|
||||
enum label_type { nr_ldh, a, }
|
||||
label_type = nr_ldh;
|
||||
size_t
|
||||
label_sz = 0,
|
||||
dash_idx;
|
||||
for (;; ++idx) {
|
||||
if (idx == sz || name[idx] == '.') {
|
||||
if (label_sz == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (label_type == a) {
|
||||
unsigned int label_idx = idx - label_sz;
|
||||
unsigned int before_idx = label_idx + 4 /* xn-- */;
|
||||
unsigned int
|
||||
n_after_delim = idx - (dash_idx + 1),
|
||||
n_before_delim = dash_idx < before_idx ? 0 : dash_idx - before_idx;
|
||||
if (n_after_delim == 0 || !punycode_check(&(name[dash_idx + 1]), n_after_delim, n_before_delim)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (idx == sz) {
|
||||
break;
|
||||
} else {
|
||||
label_sz = 0;
|
||||
label_type = nr_ldh;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (label_sz == 63) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (name[idx] == '-') {
|
||||
dash_idx = idx;
|
||||
if (
|
||||
// first character in label
|
||||
label_sz == 0 ||
|
||||
// last character in the entire string
|
||||
// or the last character of the label
|
||||
(idx + 1 == sz || name[idx + 1] == '.')
|
||||
) {
|
||||
return NULL;
|
||||
}
|
||||
if (label_sz == 3 && name[idx - 1] == '-') {
|
||||
if (strncasecmp(&(name[idx - 3]), "xn", 2) != 0) {
|
||||
// label[2..=3] is "--", but label[0..=1] isn't "xn"
|
||||
return NULL;
|
||||
} else {
|
||||
assert(label_type == nr_ldh);
|
||||
label_type = a;
|
||||
}
|
||||
}
|
||||
} else if (name[idx] < '0' || name[idx] > '9') {
|
||||
if ((name[idx] | 0x20) >= 'a' && (name[idx] | 0x20) <= 'z') {
|
||||
name_contains_alphabetic_character = true;
|
||||
} else {
|
||||
// u-labels are unsupported
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
label_sz += 1;
|
||||
}
|
||||
if (!name_contains_alphabetic_character) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
success:;
|
||||
*name_sz = sz;
|
||||
return name;
|
||||
}
|
||||
|
||||
static struct bdd_name_desc *wlock_name_desc(struct hashmap_key *key/*, bool *created*/) {
|
||||
assert(key != NULL/* && created != NULL*/);
|
||||
|
||||
struct bdd_name_desc *expected = NULL;
|
||||
enum hashmap_cas_result r;
|
||||
|
||||
r = hashmap_cas(
|
||||
HASHMAP, AREA, key,
|
||||
(void **)&(expected), NULL,
|
||||
hashmap_cas_get, (void *)0
|
||||
);
|
||||
|
||||
if (r == hashmap_cas_again) {
|
||||
//*created = false;
|
||||
return expected;
|
||||
}
|
||||
|
||||
struct bdd_name_desc *name_desc = alloc_name_desc();
|
||||
if (name_desc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
pthread_rwlock_wrlock(&(name_desc->rwlock));
|
||||
// works because only the command thread (this thread) can mutate HASHMAP
|
||||
r = hashmap_cas(
|
||||
HASHMAP, AREA, key,
|
||||
(void **)&(expected), name_desc,
|
||||
hashmap_cas_set, NULL
|
||||
);
|
||||
|
||||
if (r != hashmap_cas_success) {
|
||||
pthread_rwlock_unlock(&(name_desc->rwlock));
|
||||
free_name_desc(name_desc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//*created = true;
|
||||
return name_desc;
|
||||
}
|
||||
|
||||
// exposed function
|
||||
// bdd_name_descs_add_service_instance **cannot** replace a service instance.
|
||||
// it may only add service instances.
|
||||
bool bdd_name_descs_add_service_instance(
|
||||
const char *scope,
|
||||
size_t scope_sz,
|
||||
|
||||
const struct bdd_service *service,
|
||||
const void *instance_info
|
||||
) {
|
||||
// normalize scope
|
||||
scope = bdd_name(scope, &(scope_sz));
|
||||
if (scope == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct bdd_service_instance *service_inst = malloc(sizeof(struct bdd_service_instance));
|
||||
if (service_inst == NULL) {
|
||||
return false;
|
||||
}
|
||||
service_inst->service = service;
|
||||
service_inst->instance_info = instance_info;
|
||||
service_inst->next = NULL;
|
||||
|
||||
struct hashmap_key key;
|
||||
hashmap_key((void *)scope, scope_sz, &(key));
|
||||
struct bdd_name_desc *name_desc = wlock_name_desc(&(key));
|
||||
if (name_desc == NULL) {
|
||||
err:;
|
||||
free(service_inst);
|
||||
return false;
|
||||
}
|
||||
bool success = add_service_inst(name_desc, service_inst);
|
||||
pthread_rwlock_unlock(&(name_desc->rwlock));
|
||||
if (!success) {
|
||||
goto err;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// internal function
|
||||
// cannot be called concurrently
|
||||
static bool hashmap_set_cert_pkey(
|
||||
const char *scope,
|
||||
size_t scope_sz,
|
||||
|
||||
X509 *x509,
|
||||
EVP_PKEY *pkey
|
||||
) {
|
||||
// normalize scope
|
||||
scope = bdd_name(scope, &(scope_sz));
|
||||
if (scope == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// create or retrieve the name's description
|
||||
struct hashmap_key key;
|
||||
hashmap_key((void *)scope, scope_sz, &(key));
|
||||
struct bdd_name_desc *name_desc = wlock_name_desc(&(key));
|
||||
if (name_desc == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// set its certificate and private key
|
||||
set_cert_pkey(name_desc, x509, pkey);
|
||||
|
||||
pthread_rwlock_unlock(&(name_desc->rwlock));
|
||||
return true;
|
||||
}
|
||||
|
||||
// exposed function
|
||||
// cannot be called concurrently
|
||||
void bdd_name_descs_use_cert_pkey(
|
||||
X509 *x509,
|
||||
EVP_PKEY *pkey
|
||||
) {
|
||||
// to-do: support for (owned/reserved) ip addresses?
|
||||
|
||||
#define update() \
|
||||
if (hashmap_set_cert_pkey( \
|
||||
(const char *)asn1_str->data, \
|
||||
asn1_str->length, \
|
||||
x509, \
|
||||
pkey \
|
||||
)) { \
|
||||
printf("updated %.*s\n", asn1_str->length, asn1_str->data); \
|
||||
X509_up_ref(x509); \
|
||||
EVP_PKEY_up_ref(pkey); \
|
||||
}
|
||||
GENERAL_NAMES *dns_alt_names = X509_get_ext_d2i(x509, NID_subject_alt_name, 0, 0);
|
||||
X509_NAME *dns_subject_names = X509_get_subject_name(x509);
|
||||
if (dns_alt_names != NULL) {
|
||||
int n_dns_alt_names = sk_GENERAL_NAME_num(dns_alt_names);
|
||||
for (int idx = 0; idx < n_dns_alt_names; ++idx) {
|
||||
GENERAL_NAME *entry = sk_GENERAL_NAME_value(dns_alt_names, idx);
|
||||
if (entry->type != GEN_DNS) {
|
||||
continue;
|
||||
}
|
||||
ASN1_IA5STRING *asn1_str = entry->d.dNSName;
|
||||
update();
|
||||
}
|
||||
GENERAL_NAMES_free(dns_alt_names);
|
||||
} else if (dns_subject_names != NULL) {
|
||||
int n_dns_subject_names = X509_NAME_entry_count(dns_subject_names);
|
||||
for (int idx = 0; idx < n_dns_subject_names; ++idx) {
|
||||
X509_NAME_ENTRY *entry = X509_NAME_get_entry(dns_subject_names, idx);
|
||||
ASN1_OBJECT *asn1_obj = X509_NAME_ENTRY_get_object(entry);
|
||||
ASN1_STRING *asn1_str = X509_NAME_ENTRY_get_data(entry);
|
||||
if (
|
||||
asn1_obj == NULL || asn1_str == NULL ||
|
||||
OBJ_obj2nid(asn1_obj) != NID_commonName
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
update();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void acq(struct bdd_name_desc *name_desc, enum hashmap_callback_reason reason, uintptr_t md) {
|
||||
assert(name_desc != NULL && md <= 1);
|
||||
static_assert(sizeof(uintptr_t) >= sizeof(char) /* 1 */, "what");
|
||||
switch (reason) {
|
||||
case (hashmap_acquire): {
|
||||
if (md == 0) {
|
||||
pthread_rwlock_wrlock(&(name_desc->rwlock));
|
||||
} else {
|
||||
pthread_rwlock_rdlock(&(name_desc->rwlock));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (hashmap_drop_destroy): {
|
||||
free_name_desc(name_desc);
|
||||
break;
|
||||
}
|
||||
default: abort();
|
||||
}
|
||||
return;
|
||||
}
|
||||
bool bdd_name_descs_create(uint16_t n_threads) {
|
||||
HASHMAP = hashmap_create(n_threads, 64, 0.94, 2, (hashmap_callback)acq);
|
||||
if (HASHMAP != NULL) {
|
||||
AREA = hashmap_area(bdd_gv.name_descs);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void bdd_name_descs_destroy(void) {
|
||||
if (HASHMAP != NULL) {
|
||||
hashmap_area_release(HASHMAP, AREA);
|
||||
hashmap_destroy(HASHMAP);
|
||||
}
|
||||
return;
|
||||
}
|
|
@ -92,7 +92,10 @@ void *bdd_serve(struct bdd_worker_data *worker_data) {
|
|||
}
|
||||
switch (conversation->state) {
|
||||
case (bdd_conversation_accept): {
|
||||
if (bdd_accept_continue(conversation) == bdd_cont_conversation_discard) {
|
||||
worker_data->ssl_cb_ctx.conversation = conversation;
|
||||
worker_data->ssl_cb_ctx.protocol_name =
|
||||
(void *)(worker_data->ssl_cb_ctx.cstr_protocol_name = NULL);
|
||||
if (bdd_accept_continue(&(worker_data->ssl_cb_ctx)) == bdd_cont_conversation_discard) {
|
||||
if (conversation->n_ev >= 1) {
|
||||
process_unlink(&(process_list), conversation);
|
||||
}
|
7
build.py
7
build.py
|
@ -10,14 +10,15 @@ gcc = [
|
|||
|
||||
"-o", os.path.join(file_dirname, "output", "bidirectiond"),
|
||||
|
||||
"-I" + os.path.join(file_dirname, "inc")
|
||||
"-I" + os.path.join(file_dirname, "bdd", "headers"),
|
||||
"-I" + os.path.join(file_dirname, "hashmap", "src"),
|
||||
]
|
||||
for directory, _, files in os.walk(os.path.join(file_dirname, "bidirectiond")):
|
||||
for directory, _, files in os.walk(os.path.join(file_dirname, "cmd")):
|
||||
for file_name in files:
|
||||
if file_name[-2:] != ".c":
|
||||
continue
|
||||
gcc.append(os.path.join(directory, file_name))
|
||||
for directory, _, files in os.walk(os.path.join(file_dirname, "core")):
|
||||
for directory, _, files in os.walk(os.path.join(file_dirname, "bdd")):
|
||||
for file_name in files:
|
||||
if file_name[-2:] != ".c":
|
||||
continue
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef bidirectiond__core_settings__h
|
||||
#define bidirectiond__core_settings__h
|
||||
|
||||
#include <bdd-core/settings.h>
|
||||
#include <settings.h>
|
||||
|
||||
extern const struct bdd_service services[];
|
||||
extern struct bdd_settings settings;
|
|
@ -112,44 +112,44 @@ void input_processor(int sfd, char *br_buf, int br_buf_sz) {
|
|||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
if (bio == NULL) {
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!buffered_read()) {
|
||||
e |= 0b1;
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
if (br_ctx.byte == 0) {
|
||||
break;
|
||||
}
|
||||
if (br_ctx.byte == 1 || BIO_write(bio, &(br_ctx.byte), 1) != 1) {
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
}
|
||||
|
||||
// deserialize the certificate
|
||||
x509 = PEM_read_bio_X509(bio, NULL, NULL, "");
|
||||
if (x509 == NULL) {
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
|
||||
BIO_free(bio);
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
if (bio == NULL) {
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!buffered_read()) {
|
||||
e |= 0b1;
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
if (br_ctx.byte == 0) {
|
||||
break;
|
||||
}
|
||||
if (br_ctx.byte == 1 || BIO_write(bio, &(br_ctx.byte), 1) != 1) {
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ void input_processor(int sfd, char *br_buf, int br_buf_sz) {
|
|||
char env_variable_name[0x100];
|
||||
for (size_t idx = 0;; ++idx) {
|
||||
if (idx == sizeof(env_variable_name)) {
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
env_variable_name[idx] = br_ctx.byte;
|
||||
if (br_ctx.byte == 0) {
|
||||
|
@ -173,11 +173,11 @@ void input_processor(int sfd, char *br_buf, int br_buf_sz) {
|
|||
break;
|
||||
}
|
||||
if (br_ctx.byte == 1) {
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
if (!buffered_read()) {
|
||||
e |= 0b1;
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -185,14 +185,12 @@ void input_processor(int sfd, char *br_buf, int br_buf_sz) {
|
|||
// deserialize the private key
|
||||
pkey = PEM_read_bio_PrivateKey(bio, NULL, cp_pwd, &(cp_ctx));
|
||||
if (pkey == NULL) {
|
||||
goto tls_pem_load_err;
|
||||
goto tls_pem_load_out;
|
||||
}
|
||||
|
||||
if (bdd_name_descs_use_cert_pkey(settings.name_descs, &(x509), &(pkey))) {
|
||||
e |= 0b10;
|
||||
}
|
||||
bdd_name_descs_use_cert_pkey(x509, pkey);
|
||||
|
||||
tls_pem_load_err:;
|
||||
tls_pem_load_out:;
|
||||
if (bio != NULL) {
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
@ -202,11 +200,7 @@ void input_processor(int sfd, char *br_buf, int br_buf_sz) {
|
|||
if (pkey != NULL) {
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
if (e & 0b10) {
|
||||
puts("added SSL_CTX");
|
||||
} else {
|
||||
puts("failed to add SSL_CTX");
|
||||
}
|
||||
|
||||
if (e & 0b1) {
|
||||
goto err;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#include <poll.h>
|
||||
#include <assert.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <bdd-core/settings.h>
|
||||
#include <settings.h>
|
||||
#include <fcntl.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/err.h>
|
||||
|
@ -28,10 +28,8 @@
|
|||
#endif
|
||||
|
||||
struct bdd_settings settings = {
|
||||
.name_descs = NULL,
|
||||
.n_conversations = 0x100,
|
||||
.n_epoll_oevents = 0x200,
|
||||
.n_worker_threads = 16,
|
||||
.epoll_timeout = -1,
|
||||
.sockfds = NULL,
|
||||
};
|
||||
|
@ -76,7 +74,6 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
SSL_library_init();
|
||||
OpenSSL_add_all_algorithms();
|
||||
SSL_load_error_strings();
|
||||
ERR_load_BIO_strings();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
bool bdd_instance;
|
||||
|
@ -89,9 +86,11 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
};
|
||||
int sig_fd = -1;
|
||||
|
||||
size_t n_threads = sysconf(_SC_NPROCESSORS_ONLN) /* workers */;
|
||||
|
||||
// name_descs
|
||||
if ((settings.name_descs = bdd_name_descs_create()) == NULL) {
|
||||
fputs("failed to allocate settings.name_descs\n", stderr);
|
||||
if (!bdd_name_descs_create(n_threads + 1)) {
|
||||
fputs("failed to allocate name_descs\n", stderr);
|
||||
goto clean_up;
|
||||
}
|
||||
// args
|
||||
|
@ -145,11 +144,7 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
}
|
||||
arg_iter:;
|
||||
while ((*arg) != NULL) {
|
||||
if (strcmp((*arg), "--n-worker-threads") == 0 || strcmp((*arg), "-t") == 0) {
|
||||
EXPECT_ARGS(1);
|
||||
EXPECT(stousi(&(settings.n_worker_threads), arg[1]));
|
||||
arg += 2;
|
||||
} else if (strcmp((*arg), "-l") == 0) {
|
||||
if (strcmp((*arg), "-l") == 0) {
|
||||
EXPECT_ARGS(2);
|
||||
struct rlimit rlimit;
|
||||
EXPECT(storlim(&(rlimit.rlim_cur), arg[1]));
|
||||
|
@ -185,6 +180,7 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
sigaction(SIGHUP, &(action), 0);
|
||||
arg += 1;
|
||||
} else if (strcmp((*arg), "--tls-credentials") == 0 || strcmp((*arg), "-c") == 0) {
|
||||
// to-do: support omission of 3rd argument
|
||||
EXPECT_ARGS(3);
|
||||
X509 *x509 = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
@ -194,7 +190,7 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
FILE *file = fopen(arg[1], "r");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "couldn't access certificate file (%s)\n", arg[1]);
|
||||
goto arg_creds_err;
|
||||
goto arg_creds_out;
|
||||
}
|
||||
|
||||
x509 = PEM_read_X509(file, NULL, NULL, NULL);
|
||||
|
@ -202,7 +198,7 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
|
||||
if (x509 == NULL) {
|
||||
fprintf(stderr, "invalid certificate file (%s)\n", arg[1]);
|
||||
goto arg_creds_err;
|
||||
goto arg_creds_out;
|
||||
}
|
||||
|
||||
// read private key //
|
||||
|
@ -215,7 +211,7 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
file = fopen(arg[2], "r");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "couldn't access private key file (%s)\n", arg[1]);
|
||||
goto arg_creds_err;
|
||||
goto arg_creds_out;
|
||||
}
|
||||
|
||||
pkey = PEM_read_PrivateKey(file, NULL, &(cp_pwd), &(cp_ctx));
|
||||
|
@ -223,19 +219,15 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
|
||||
if (pkey == NULL) {
|
||||
fprintf(stderr, "invalid private key file (%s)\n", arg[2]);
|
||||
goto arg_creds_err;
|
||||
goto arg_creds_out;
|
||||
}
|
||||
if (!cp_ctx.success) {
|
||||
fputs("the private key file must be encrypted\n", stderr);
|
||||
goto arg_creds_err;
|
||||
fputs("the private key file should be encrypted\n", stderr);
|
||||
}
|
||||
|
||||
if (!bdd_name_descs_use_cert_pkey(settings.name_descs, &(x509), &(pkey))) {
|
||||
fputs("seemingly invalid certificate file\n", stderr);
|
||||
goto arg_creds_err;
|
||||
}
|
||||
bdd_name_descs_use_cert_pkey(x509, pkey);
|
||||
|
||||
arg_creds_err:;
|
||||
arg_creds_out:;
|
||||
if (x509 != NULL) {
|
||||
X509_free(x509);
|
||||
}
|
||||
|
@ -285,7 +277,6 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
n += 1;
|
||||
}
|
||||
if (!services[idx].instantiate(
|
||||
settings.name_descs,
|
||||
&(services[idx]),
|
||||
n,
|
||||
(const char **)arg
|
||||
|
@ -299,7 +290,6 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
}
|
||||
arg_err:;
|
||||
fputs("argument parsing failed\n"
|
||||
"-t: set the amount of worker threads\n"
|
||||
"--epoll-timeout: set the timeout (in ms) for "
|
||||
"bdd_conversation structs\n"
|
||||
"-l: set the rlimits for open files (soft limit, "
|
||||
|
@ -353,11 +343,11 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
sv_addr.inet6.sin6_port = htons(port);
|
||||
}
|
||||
// try to bind to port
|
||||
sockfds = malloc(sizeof(int) * settings.n_worker_threads);
|
||||
sockfds = malloc(sizeof(int) * n_threads);
|
||||
if (sockfds == NULL) {
|
||||
goto clean_up;
|
||||
}
|
||||
for (; fuck_idx < settings.n_worker_threads; ++fuck_idx) {
|
||||
for (; fuck_idx < n_threads; ++fuck_idx) {
|
||||
int fd = socket(af, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "failed to create sv_socket! errno: %i\n", errno);
|
||||
|
@ -496,9 +486,7 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
free(sockfds);
|
||||
}
|
||||
// aight
|
||||
if (settings.name_descs != NULL) {
|
||||
bdd_name_descs_destroy(&(settings.name_descs));
|
||||
}
|
||||
bdd_name_descs_destroy();
|
||||
// https://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
|
||||
// FIPS_mode_set(0);
|
||||
CRYPTO_set_locking_callback(NULL);
|
|
@ -0,0 +1 @@
|
|||
-I./hashmap/src
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 3bfff93ccd5e7f19e604b578b9e647bf0a995516
|
|
@ -1,26 +0,0 @@
|
|||
#ifndef bidirectiond_core__settings__h
|
||||
#define bidirectiond_core__settings__h
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../src/headers/bdd_name_descs.h"
|
||||
#include "../src/headers/bdd_settings.h"
|
||||
#include "../src/headers/bdd_service.h"
|
||||
#include "../src/headers/bdd_stop.h"
|
||||
|
||||
struct bdd_name_descs;
|
||||
struct bdd_instance *bdd_go(struct bdd_settings settings);
|
||||
void bdd_wait(void);
|
||||
void bdd_destroy(void);
|
||||
|
||||
bool bdd_name_descs_use_cert_pkey(
|
||||
struct bdd_name_descs *name_descriptions,
|
||||
X509 **x509_ref,
|
||||
EVP_PKEY **pkey_ref
|
||||
);
|
||||
|
||||
struct bdd_name_descs *bdd_name_descs_create(void);
|
||||
void bdd_name_descs_destroy(struct bdd_name_descs **name_descs);
|
||||
|
||||
#endif
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef bidirectiond_core__bdd_name_descs__h
|
||||
#define bidirectiond_core__bdd_name_descs__h
|
||||
|
||||
struct bdd_name_descs;
|
||||
|
||||
#endif
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef bidirectiond_core__bdd_stop__h
|
||||
#define bidirectiond_core__bdd_stop__h
|
||||
|
||||
void bdd_stop(void);
|
||||
|
||||
#endif
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef bidirectiond_core__serve__h
|
||||
#define bidirectiond_core__serve__h
|
||||
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include "timeout_list.h"
|
||||
|
||||
struct bdd_worker_data {
|
||||
int epoll_fd;
|
||||
int serve_fd;
|
||||
SSL_CTX *ssl_ctx;
|
||||
struct bdd_tl timeout_list;
|
||||
struct epoll_event events[];
|
||||
};
|
||||
void *bdd_serve(struct bdd_worker_data *worker_data);
|
||||
|
||||
#endif
|
|
@ -1,296 +0,0 @@
|
|||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <hashmap/hashmap.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "headers/name_descs.h"
|
||||
#include "headers/bdd_name_descs.h"
|
||||
#include "headers/bdd_service.h"
|
||||
|
||||
// struct bdd_name_desc
|
||||
struct bdd_name_desc *bdd_name_desc_alloc(void) {
|
||||
struct bdd_name_desc *name_desc = malloc(sizeof(struct bdd_name_desc));
|
||||
if (name_desc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
name_desc->x509 = NULL;
|
||||
name_desc->pkey = NULL;
|
||||
name_desc->service_instances = NULL;
|
||||
return name_desc;
|
||||
}
|
||||
|
||||
void bdd_name_desc_clean_cert_pkey(struct bdd_name_desc *name_desc) {
|
||||
if (name_desc->x509 != NULL) {
|
||||
// misleading function name; it actually
|
||||
// decs the ref count and frees the shit
|
||||
// if the rc hits 0
|
||||
X509_free(name_desc->x509);
|
||||
EVP_PKEY_free(name_desc->pkey);
|
||||
name_desc->x509 = NULL;
|
||||
name_desc->pkey = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void bdd_name_desc_clean_services(struct bdd_name_desc *name_desc) {
|
||||
for (
|
||||
struct bdd_service_instance **service_inst = &(name_desc->service_instances);
|
||||
(*service_inst) != NULL;
|
||||
) {
|
||||
struct bdd_service_instance *curr = (*service_inst);
|
||||
(*service_inst) = curr->next;
|
||||
if (curr->instance_info != NULL) {
|
||||
curr->service->instance_info_destructor((void *)curr->instance_info);
|
||||
}
|
||||
free(curr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool bdd_name_desc_add_service_instance(
|
||||
struct bdd_name_desc *name_desc,
|
||||
struct bdd_service_instance *service_inst
|
||||
) {
|
||||
struct bdd_service_instance **curr = &(name_desc->service_instances);
|
||||
const char *const *inst_sp = service_inst->service->supported_protocols;
|
||||
for (; (*curr) != NULL; curr = &((*curr)->next)) {
|
||||
const char *const *curr_sp = (*curr)->service->supported_protocols;
|
||||
if (inst_sp == NULL || curr_sp == NULL) {
|
||||
if (inst_sp == curr_sp) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (size_t idx = 0; curr_sp[idx]; ++idx) {
|
||||
for (size_t idx2 = 0; inst_sp[idx2]; ++idx2) {
|
||||
if (strcmp(curr_sp[idx], inst_sp[idx2]) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(*curr) = service_inst;
|
||||
return true;
|
||||
}
|
||||
|
||||
void bdd_name_desc_set_cert_pkey(struct bdd_name_desc *name_desc, X509 *x509, EVP_PKEY *pkey) {
|
||||
bdd_name_desc_clean_cert_pkey(name_desc);
|
||||
name_desc->x509 = x509;
|
||||
name_desc->pkey = pkey;
|
||||
return;
|
||||
}
|
||||
|
||||
void bdd_name_desc_destroy(struct bdd_name_desc *name_desc) {
|
||||
bdd_name_desc_clean_services(name_desc);
|
||||
bdd_name_desc_clean_cert_pkey(name_desc);
|
||||
free(name_desc);
|
||||
return;
|
||||
}
|
||||
|
||||
void bdd_name_desc_destroy_hm(struct bdd_name_desc *name_desc, enum hashmap_drop_mode _) {
|
||||
bdd_name_desc_destroy(name_desc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// name_descs hashmap
|
||||
void bdd_name_trim(const unsigned char *name, size_t *name_sz) {
|
||||
if ((*name_sz) >= 1 && name[(*name_sz) - 1] == '.') { \
|
||||
(*name_sz) -= 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#define bdd_name_descs_prelude() \
|
||||
bool r = false; \
|
||||
struct hashmap *name_descs = (struct hashmap *)bdd_name_descs; \
|
||||
bdd_name_trim(scope, &(scope_sz)); \
|
||||
if (scope_sz > 0 && scope[0] == '*') { \
|
||||
if (scope_sz > 1 && scope[1] != '.') { \
|
||||
return false; \
|
||||
} \
|
||||
scope += 1; \
|
||||
scope_sz -= 1; \
|
||||
} \
|
||||
struct hashmap_key key = HASHMAP_KEY_INITIALIZER; \
|
||||
hashmap_key_obtain(name_descs, &(key), scope, scope_sz); \
|
||||
struct bdd_name_desc *name_desc; \
|
||||
bool created_name_desc; \
|
||||
if (!hashmap_get(name_descs, &(key), (void *)&(name_desc))) { \
|
||||
if ((name_desc = bdd_name_desc_alloc()) == NULL) { \
|
||||
goto out; \
|
||||
} \
|
||||
created_name_desc = true; \
|
||||
} else { \
|
||||
created_name_desc = false; \
|
||||
}
|
||||
#define bdd_name_descs_out() \
|
||||
out:; \
|
||||
hashmap_key_release(name_descs, &(key), false); \
|
||||
return r;
|
||||
|
||||
// exposed function
|
||||
// bdd_name_descs_add_service_instance **cannot** replace a service instance;
|
||||
// it may only add service instances.
|
||||
bool bdd_name_descs_add_service_instance(
|
||||
struct bdd_name_descs *bdd_name_descs,
|
||||
const unsigned char *scope,
|
||||
size_t scope_sz,
|
||||
const struct bdd_service *service,
|
||||
const void **instance_info
|
||||
) {
|
||||
bdd_name_descs_prelude();
|
||||
|
||||
struct bdd_service_instance *service_inst = malloc(sizeof(struct bdd_service_instance));
|
||||
if (service_inst == NULL) {
|
||||
goto out;
|
||||
}
|
||||
service_inst->service = service;
|
||||
service_inst->next = NULL;
|
||||
if (!bdd_name_desc_add_service_instance(name_desc, service_inst)) {
|
||||
if (created_name_desc) {
|
||||
bdd_name_desc_destroy(name_desc);
|
||||
}
|
||||
free(service_inst);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (created_name_desc) {
|
||||
if (!hashmap_set(name_descs, &(key), name_desc)) {
|
||||
// will free service_inst
|
||||
bdd_name_desc_destroy(name_desc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
service_inst->instance_info = *instance_info;
|
||||
*instance_info = NULL;
|
||||
r = true;
|
||||
|
||||
goto out;
|
||||
|
||||
bdd_name_descs_out();
|
||||
}
|
||||
|
||||
// internal function
|
||||
bool bdd_name_descs_set_cert_pkey(
|
||||
struct bdd_name_descs *bdd_name_descs,
|
||||
const unsigned char *scope,
|
||||
size_t scope_sz,
|
||||
X509 *x509,
|
||||
EVP_PKEY *pkey
|
||||
) {
|
||||
bdd_name_descs_prelude();
|
||||
|
||||
bdd_name_desc_set_cert_pkey(name_desc, x509, pkey);
|
||||
|
||||
if (created_name_desc) {
|
||||
if (!hashmap_set(name_descs, &(key), name_desc)) {
|
||||
bdd_name_desc_destroy(name_desc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
r = true;
|
||||
goto out;
|
||||
|
||||
bdd_name_descs_out();
|
||||
}
|
||||
|
||||
// exposed function
|
||||
bool bdd_name_descs_use_cert_pkey(
|
||||
struct bdd_name_descs *bdd_name_descs,
|
||||
X509 **x509_ref,
|
||||
EVP_PKEY **pkey_ref
|
||||
) {
|
||||
X509 *x509 = *x509_ref;
|
||||
EVP_PKEY *pkey = *pkey_ref;
|
||||
|
||||
bool should_up_rc = false;
|
||||
GENERAL_NAMES *dns_alt_names = X509_get_ext_d2i(x509, NID_subject_alt_name, 0, 0);
|
||||
if (dns_alt_names != NULL) {
|
||||
int n_dns_alt_names = sk_GENERAL_NAME_num(dns_alt_names);
|
||||
if (n_dns_alt_names < 0) {
|
||||
n_dns_alt_names = 0;
|
||||
}
|
||||
for (int idx = 0; idx < n_dns_alt_names; ++idx) {
|
||||
GENERAL_NAME *entry = sk_GENERAL_NAME_value(dns_alt_names, idx);
|
||||
if (entry->type != GEN_DNS) {
|
||||
continue;
|
||||
}
|
||||
ASN1_IA5STRING *asn1_str = entry->d.dNSName;
|
||||
int data_length = asn1_str->length;
|
||||
bool s = bdd_name_descs_set_cert_pkey(
|
||||
bdd_name_descs,
|
||||
(const unsigned char *)asn1_str->data,
|
||||
data_length,
|
||||
x509,
|
||||
pkey
|
||||
);
|
||||
if (s) {
|
||||
if (should_up_rc) {
|
||||
X509_up_ref(x509);
|
||||
EVP_PKEY_up_ref(pkey);
|
||||
} else {
|
||||
should_up_rc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
GENERAL_NAMES_free(dns_alt_names);
|
||||
} else { // rfc6125
|
||||
X509_NAME *dns_subject_names = X509_get_subject_name(x509);
|
||||
if (dns_subject_names != NULL) {
|
||||
int n_dns_subject_names = X509_NAME_entry_count(dns_subject_names);
|
||||
if (n_dns_subject_names < 0) {
|
||||
n_dns_subject_names = 0;
|
||||
}
|
||||
for (int idx = 0; idx < n_dns_subject_names; ++idx) {
|
||||
X509_NAME_ENTRY *entry = X509_NAME_get_entry(dns_subject_names, idx);
|
||||
ASN1_OBJECT *asn1_obj = X509_NAME_ENTRY_get_object(entry);
|
||||
ASN1_STRING *asn1_str = X509_NAME_ENTRY_get_data(entry);
|
||||
if (asn1_obj == NULL || asn1_str == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (OBJ_obj2nid(asn1_obj) != NID_commonName) {
|
||||
continue;
|
||||
}
|
||||
int data_length = asn1_str->length;
|
||||
bool s = bdd_name_descs_set_cert_pkey(
|
||||
bdd_name_descs,
|
||||
(const unsigned char *)asn1_str->data,
|
||||
data_length,
|
||||
x509,
|
||||
pkey
|
||||
);
|
||||
if (s) {
|
||||
if (should_up_rc) {
|
||||
X509_up_ref(x509);
|
||||
EVP_PKEY_up_ref(pkey);
|
||||
} else {
|
||||
should_up_rc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!should_up_rc) {
|
||||
// x509 and pkey's ref counts will be the same as
|
||||
// they were before this function was called
|
||||
return false;
|
||||
}
|
||||
|
||||
// invalidate some pointers
|
||||
*x509_ref = NULL;
|
||||
*pkey_ref = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct bdd_name_descs *bdd_name_descs_create(void) {
|
||||
return (struct bdd_name_descs *)hashmap_create(183, 16, (void *)&(bdd_name_desc_destroy_hm));
|
||||
}
|
||||
|
||||
void bdd_name_descs_destroy(struct bdd_name_descs **name_descs) {
|
||||
hashmap_destroy_ref((struct hashmap **)name_descs);
|
||||
return;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 8ff5db70a63331b7e8d4264c50d8a4dbd32cfef3
|
|
@ -1 +0,0 @@
|
|||
../core/headers
|
|
@ -1 +0,0 @@
|
|||
../core/hashmap/headers/
|
|
@ -35,7 +35,7 @@ def append_service(service):
|
|||
value = service[key]
|
||||
if type(value) != str:
|
||||
raise Exception("error")
|
||||
declarations += f"bool {value}(struct bdd_name_descs *name_descs, const struct bdd_service *service, size_t n_arguments, const char **arguments);"
|
||||
declarations += f"bool {value}(const struct bdd_service *service, size_t n_arguments, const char **arguments);"
|
||||
service_str += f".{key} = &({value}),"
|
||||
#
|
||||
key = "handle_events"
|
||||
|
@ -90,7 +90,7 @@ for path in glob.glob(os.path.join(dir_path, "*/service.json")):
|
|||
services += "};const size_t n_services = " + str(n_services) + ";"
|
||||
|
||||
fd = tempfile.NamedTemporaryFile(delete=False, suffix=".c")
|
||||
fd.write(b"#include <bdd-core/settings.h>\n" + bytes(declarations, "ascii") + bytes(services, "ascii"))
|
||||
fd.write(b"#include <settings.h>\n" + bytes(declarations, "ascii") + bytes(services, "ascii"))
|
||||
fd.close()
|
||||
subprocess.run([
|
||||
"gcc",
|
||||
|
@ -98,6 +98,6 @@ subprocess.run([
|
|||
"-c", fd.name,
|
||||
"-o", os.path.join(dir_path, "..", "output", "glue.o"),
|
||||
|
||||
"-I" + os.path.join(dir_path, "..", "inc"),
|
||||
"-I" + os.path.join(dir_path, "..", "bdd", "headers"),
|
||||
])
|
||||
os.unlink(fd.name)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <bdd-core/services.h>
|
||||
#include "../../bdd/headers/services.h"
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
@ -127,7 +127,7 @@ bool general_service__conversation_init(
|
|||
if (a == NULL) {
|
||||
return false;
|
||||
}
|
||||
bdd_set_associated(conversation, a, NULL);
|
||||
bdd_set_associated(conversation, a, free);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,6 @@ void general_service__instance_info_destructor(void *hint) {
|
|||
return;
|
||||
}
|
||||
static bool handle_s(
|
||||
struct bdd_name_descs *name_descriptions,
|
||||
const struct bdd_service *service,
|
||||
const char *scope,
|
||||
const char *addr,
|
||||
|
@ -174,17 +173,15 @@ static bool handle_s(
|
|||
info->addrinfo = res;
|
||||
res = NULL;
|
||||
|
||||
if (!bdd_name_descs_add_service_instance(name_descriptions, scope, strlen(scope), service, (void *)&(info))) {
|
||||
goto err;
|
||||
if (bdd_name_descs_add_service_instance(scope, strlen(scope), service, (void *)info)) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
err:;
|
||||
general_service__instance_info_destructor(info);
|
||||
return false;
|
||||
}
|
||||
bool general_service__instantiate(
|
||||
struct bdd_name_descs *name_descriptions,
|
||||
const struct bdd_service *service,
|
||||
size_t argc,
|
||||
const char **argv
|
||||
|
@ -201,7 +198,7 @@ bool general_service__instantiate(
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
return handle_s(name_descriptions, service, argv[1], argv[2], argv[3], use_tls);
|
||||
return handle_s(service, argv[1], argv[2], argv[3], use_tls);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue