ssl_stream集成新的client hello解析模块。
This commit is contained in:
@@ -75,6 +75,16 @@ do { MESA_handle_runtime_log(handler, RLOG_LV_DEBUG, "tfe", fmt, ##__VA_ARGS__);
|
|||||||
#define ATOMIC_INC(x) __atomic_fetch_add(x,1,__ATOMIC_RELAXED)
|
#define ATOMIC_INC(x) __atomic_fetch_add(x,1,__ATOMIC_RELAXED)
|
||||||
#define ATOMIC_READ(x) __atomic_fetch_add(x,0,__ATOMIC_RELAXED)
|
#define ATOMIC_READ(x) __atomic_fetch_add(x,0,__ATOMIC_RELAXED)
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int addr_sock_to_layer(struct sockaddr * sock_addr, int sockaddrlen, struct layer_addr * layer_addr);
|
int addr_sock_to_layer(struct sockaddr * sock_addr, int sockaddrlen, struct layer_addr * layer_addr);
|
||||||
int addr_layer_to_sock(struct layer_addr * layer_addr, struct sockaddr * sock_addr);
|
int addr_layer_to_sock(struct layer_addr * layer_addr, struct sockaddr * sock_addr);
|
||||||
char* tfe_strdup(const char* s);
|
char* tfe_strdup(const char* s);
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "ssl_utils.h"
|
#include <ssl_utils.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "tfe_future.h"
|
#include <tfe_future.h>
|
||||||
#include "tfe_utils.h"
|
#include <tfe_utils.h>
|
||||||
#include "MESA/MESA_htable.h"
|
#include <MESA/MESA_htable.h>
|
||||||
#include "event2/event.h"
|
#include <event2/event.h>
|
||||||
|
|
||||||
struct keyring
|
struct keyring
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -179,29 +179,31 @@ int ssl_dnsname_match(const char *, size_t, const char *, size_t);
|
|||||||
char * ssl_wildcardify(const char *);
|
char * ssl_wildcardify(const char *);
|
||||||
|
|
||||||
|
|
||||||
enum parse_chello_result
|
enum chello_parse_result
|
||||||
{
|
{
|
||||||
PARSE_CHELLO_SUCCESS = 0,
|
CHELLO_PARSE_SUCCESS = 0,
|
||||||
PARSE_CHELLO_INVALID_FORMAT = -1,
|
CHELLO_PARSE_INVALID_FORMAT = -1,
|
||||||
PARSE_CHELLO_NOT_ENOUGH_BUFF = -2
|
CHELLO_PARSE_NOT_ENOUGH_BUFF = -2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssl_version
|
struct ssl_version
|
||||||
{
|
{
|
||||||
uint8_t major;
|
|
||||||
uint8_t minor;
|
uint8_t minor;
|
||||||
|
uint8_t major;
|
||||||
|
uint16_t ossl_format;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssl_chello
|
struct ssl_chello
|
||||||
{
|
{
|
||||||
struct ssl_version min_version;
|
struct ssl_version min_version;
|
||||||
struct ssl_version max_version;
|
struct ssl_version max_version;
|
||||||
|
|
||||||
char* sni;
|
char* sni;
|
||||||
char* alpn;
|
char* alpn;
|
||||||
char* cipher_suites;
|
char* cipher_suites;
|
||||||
char* cipher_suites_tls13;
|
char* cipher_suites_tls13;
|
||||||
};
|
};
|
||||||
struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len, enum parse_chello_result* result);
|
struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len, enum chello_parse_result* result);
|
||||||
|
|
||||||
void ssl_chello_free(struct ssl_chello* chello);
|
void ssl_chello_free(struct ssl_chello* chello);
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "MESA/MESA_prof_load.h"
|
#include "MESA/MESA_prof_load.h"
|
||||||
#include "tfe_rpc.h"
|
#include "tfe_rpc.h"
|
||||||
#include "event2/http.h"
|
#include <event2/http.h>
|
||||||
#include "cjson/cJSON.h"
|
#include <cjson/cJSON.h>
|
||||||
#define HTABLE_MAX_KEY_LEN 256
|
#define HTABLE_MAX_KEY_LEN 256
|
||||||
#define KEYRING_EXSITED 0
|
#define KEYRING_EXSITED 0
|
||||||
#define KEYRING_NOT_EXSITED -1
|
#define KEYRING_NOT_EXSITED -1
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ struct ssl_mgr
|
|||||||
unsigned int no_tls12;
|
unsigned int no_tls12;
|
||||||
|
|
||||||
CONST_SSL_METHOD * (* sslmethod)(void); //Parameter of SSL_CTX_new
|
CONST_SSL_METHOD * (* sslmethod)(void); //Parameter of SSL_CTX_new
|
||||||
int sslversion;
|
int ssl_min_version, ssl_max_version;
|
||||||
char ssl_session_context[8];
|
char ssl_session_context[8];
|
||||||
|
|
||||||
unsigned int cache_slots;
|
unsigned int cache_slots;
|
||||||
@@ -116,17 +116,10 @@ struct ssl_stream
|
|||||||
struct __ssl_stream_debug _do_not_use;
|
struct __ssl_stream_debug _do_not_use;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssl_chello
|
|
||||||
{
|
|
||||||
//client hello
|
|
||||||
int version;
|
|
||||||
char * sni;
|
|
||||||
char * cipher_suites;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct peek_client_hello_ctx
|
struct peek_client_hello_ctx
|
||||||
{
|
{
|
||||||
struct ssl_chello chello;
|
struct ssl_chello* chello;
|
||||||
unsigned char sni_peek_retries; /* max 64 SNI parse retries */
|
unsigned char sni_peek_retries; /* max 64 SNI parse retries */
|
||||||
struct event * ev;
|
struct event * ev;
|
||||||
struct event_base * evbase;
|
struct event_base * evbase;
|
||||||
@@ -203,32 +196,10 @@ static void sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr * mgr);
|
|||||||
|
|
||||||
struct ssl_chello * ssl_peek_result_release_chello(future_result_t * result)
|
struct ssl_chello * ssl_peek_result_release_chello(future_result_t * result)
|
||||||
{
|
{
|
||||||
struct ssl_chello * p = (struct ssl_chello *) result, * copy = NULL;
|
struct peek_client_hello_ctx* ctx= (struct peek_client_hello_ctx*) result;
|
||||||
copy = ALLOC(struct ssl_chello, 1);
|
struct ssl_chello * p = ctx->chello;
|
||||||
|
ctx->chello=NULL;
|
||||||
if (p != NULL)
|
return p;
|
||||||
{
|
|
||||||
copy->sni = tfe_strdup(p->sni);
|
|
||||||
copy->cipher_suites = tfe_strdup(p->cipher_suites);
|
|
||||||
copy->version = p->version;
|
|
||||||
}
|
|
||||||
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssl_free_chello(struct ssl_chello * p)
|
|
||||||
{
|
|
||||||
if (p == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(p->sni);
|
|
||||||
p->sni = NULL;
|
|
||||||
free(p->cipher_suites);
|
|
||||||
p->cipher_suites = NULL;
|
|
||||||
free(p);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ssl_stream * ssl_stream_new(struct ssl_mgr * mgr, evutil_socket_t fd, enum tfe_conn_dir dir,
|
struct ssl_stream * ssl_stream_new(struct ssl_mgr * mgr, evutil_socket_t fd, enum tfe_conn_dir dir,
|
||||||
@@ -271,7 +242,7 @@ static void ssl_stream_free(struct ssl_stream * s_stream)
|
|||||||
case CONN_DIR_UPSTREAM:
|
case CONN_DIR_UPSTREAM:
|
||||||
if (s_stream->client_hello != NULL)
|
if (s_stream->client_hello != NULL)
|
||||||
{
|
{
|
||||||
ssl_free_chello(s_stream->client_hello);
|
ssl_chello_free(s_stream->client_hello);
|
||||||
s_stream->client_hello = NULL;
|
s_stream->client_hello = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -369,10 +340,12 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section
|
|||||||
mgr->logger = logger;
|
mgr->logger = logger;
|
||||||
mgr->ev_base_gc=ev_base_gc;
|
mgr->ev_base_gc=ev_base_gc;
|
||||||
mgr->fs_handle=fs;
|
mgr->fs_handle=fs;
|
||||||
MESA_load_profile_string_def(ini_profile, section, "ssl_version", version_str, sizeof(version_str), "tls12");
|
MESA_load_profile_string_def(ini_profile, section, "ssl_min_version", version_str, sizeof(version_str), "ssl3");
|
||||||
mgr->sslversion = sslver_str2num(version_str);
|
mgr->ssl_min_version = sslver_str2num(version_str);
|
||||||
|
MESA_load_profile_string_def(ini_profile, section, "ssl_max_version", version_str, sizeof(version_str), "tls12");
|
||||||
|
mgr->ssl_max_version = sslver_str2num(version_str);
|
||||||
|
|
||||||
if (mgr->sslversion < 0)
|
if (mgr->ssl_min_version < 0)
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(logger, "Unsupported SSL/TLS protocol %s", version_str);
|
TFE_LOG_ERROR(logger, "Unsupported SSL/TLS protocol %s", version_str);
|
||||||
goto error_out;
|
goto error_out;
|
||||||
@@ -479,10 +452,11 @@ void peek_client_hello_ctx_free(struct peek_client_hello_ctx * _ctx)
|
|||||||
{
|
{
|
||||||
event_free(_ctx->ev);
|
event_free(_ctx->ev);
|
||||||
_ctx->ev = NULL;
|
_ctx->ev = NULL;
|
||||||
free(_ctx->chello.sni);
|
if(_ctx->chello!=NULL)
|
||||||
_ctx->chello.sni = NULL;
|
{
|
||||||
free(_ctx->chello.cipher_suites);
|
ssl_chello_free(_ctx->chello);
|
||||||
_ctx->chello.cipher_suites = NULL;
|
_ctx->chello=NULL;
|
||||||
|
}
|
||||||
free(_ctx);
|
free(_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,11 +471,11 @@ static void peek_client_hello_cb(evutil_socket_t fd, short what, void * arg)
|
|||||||
struct promise * promise = (struct promise *) arg;
|
struct promise * promise = (struct promise *) arg;
|
||||||
//use promise_get_ctx instead of promise_dettach_ctx for try more times.
|
//use promise_get_ctx instead of promise_dettach_ctx for try more times.
|
||||||
struct peek_client_hello_ctx * ctx = (struct peek_client_hello_ctx *) promise_get_ctx(promise);
|
struct peek_client_hello_ctx * ctx = (struct peek_client_hello_ctx *) promise_get_ctx(promise);
|
||||||
|
enum chello_parse_result chello_status=CHELLO_PARSE_INVALID_FORMAT;
|
||||||
|
struct ssl_chello* chello=NULL;
|
||||||
const char * reason = NULL;
|
const char * reason = NULL;
|
||||||
unsigned char buf[1024];
|
unsigned char buf[2048];
|
||||||
ssize_t n = 0;
|
ssize_t n = 0;
|
||||||
const unsigned char * chello = NULL;
|
|
||||||
int rv = 0;
|
|
||||||
|
|
||||||
n = recv(fd, buf, sizeof(buf), MSG_PEEK);
|
n = recv(fd, buf, sizeof(buf), MSG_PEEK);
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
@@ -515,26 +489,21 @@ static void peek_client_hello_cb(evutil_socket_t fd, short what, void * arg)
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo: parse version and cipher suites.
|
chello=ssl_chello_parse(buf,n, &chello_status);
|
||||||
//or we should use sni proxy instead? https://github.com/dlundquist/sniproxy/blob/master/src/tls.c
|
switch(chello_status)
|
||||||
rv = ssl_tls_clienthello_parse(buf, n, 0, &chello, &(ctx->chello.sni));
|
{
|
||||||
|
case CHELLO_PARSE_SUCCESS:
|
||||||
if (rv == 0)
|
|
||||||
{
|
{
|
||||||
promise_dettach_ctx(promise);
|
promise_dettach_ctx(promise);
|
||||||
promise_success(promise, &(ctx->chello));
|
ctx->chello=chello;
|
||||||
|
promise_success(promise, ctx);
|
||||||
peek_client_hello_ctx_free(ctx);
|
peek_client_hello_ctx_free(ctx);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
case CHELLO_PARSE_NOT_ENOUGH_BUFF:
|
||||||
{
|
{
|
||||||
if (!chello)
|
ssl_chello_free(chello);
|
||||||
{
|
chello=NULL;
|
||||||
TFE_LOG_ERROR(ctx->logger,
|
|
||||||
"Peeking did not yield a (truncated) ClientHello message, aborting connection\n");
|
|
||||||
reason = "see no client hello";
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->sni_peek_retries++ > MAX_NET_RETRIES)
|
if (ctx->sni_peek_retries++ > MAX_NET_RETRIES)
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(ctx->logger, "Peek failed due to too many retries\n");
|
TFE_LOG_ERROR(ctx->logger, "Peek failed due to too many retries\n");
|
||||||
@@ -556,8 +525,21 @@ static void peek_client_hello_cb(evutil_socket_t fd, short what, void * arg)
|
|||||||
ctx->ev = event_new(ctx->evbase, fd, 0, peek_client_hello_cb, promise);
|
ctx->ev = event_new(ctx->evbase, fd, 0, peek_client_hello_cb, promise);
|
||||||
assert(ctx->ev != NULL);
|
assert(ctx->ev != NULL);
|
||||||
event_add(ctx->ev, &retry_delay);
|
event_add(ctx->ev, &retry_delay);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CHELLO_PARSE_INVALID_FORMAT:
|
||||||
|
{
|
||||||
|
ssl_chello_free(chello);
|
||||||
|
chello=NULL;
|
||||||
|
TFE_LOG_ERROR(ctx->logger,
|
||||||
|
"Peeking did not yield a (truncated) ClientHello message, aborting connection\n");
|
||||||
|
reason = "see no client hello";
|
||||||
|
goto failed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
@@ -592,11 +574,25 @@ static SSL * upstream_ssl_create(struct ssl_mgr * mgr, const struct ssl_chello *
|
|||||||
|
|
||||||
sslctx = SSL_CTX_new(mgr->sslmethod());
|
sslctx = SSL_CTX_new(mgr->sslmethod());
|
||||||
sslctx_set_opts(sslctx, mgr);
|
sslctx_set_opts(sslctx, mgr);
|
||||||
|
int ret=0;
|
||||||
if (mgr->sslversion)
|
if(chello->cipher_suites!=NULL)
|
||||||
{
|
{
|
||||||
if (SSL_CTX_set_min_proto_version(sslctx, chello->version) == 0 ||
|
//SSL_CTX_set_cipher_list() and SSL_set_cipher_list() return 1 if any cipher could be selected and 0 on complete failure.
|
||||||
SSL_CTX_set_max_proto_version(sslctx, chello->version) == 0)
|
ret=SSL_CTX_set_cipher_list(sslctx, chello->cipher_suites);
|
||||||
|
if(ret==0)
|
||||||
|
{
|
||||||
|
TFE_LOG_ERROR(mgr->logger, "SSL_CTX_set_cipher_list %s failed.", chello->cipher_suites);
|
||||||
|
SSL_CTX_set_cipher_list(sslctx, mgr->default_ciphers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret=SSL_CTX_set_cipher_list(sslctx, mgr->default_ciphers);
|
||||||
|
}
|
||||||
|
if (mgr->ssl_min_version)
|
||||||
|
{
|
||||||
|
if (SSL_CTX_set_min_proto_version(sslctx, MAX(chello->min_version.ossl_format, mgr->ssl_min_version)) == 0 ||
|
||||||
|
SSL_CTX_set_max_proto_version(sslctx, MIN(chello->max_version.ossl_format, mgr->ssl_max_version)) == 0)
|
||||||
{
|
{
|
||||||
SSL_CTX_free(sslctx);
|
SSL_CTX_free(sslctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -623,7 +619,7 @@ static SSL * upstream_ssl_create(struct ssl_mgr * mgr, const struct ssl_chello *
|
|||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t addrlen = sizeof(struct sockaddr_storage);
|
socklen_t addrlen = sizeof(struct sockaddr_storage);
|
||||||
|
|
||||||
int ret = getpeername(fd, (struct sockaddr *) (&addr), &addrlen);
|
ret = getpeername(fd, (struct sockaddr *) (&addr), &addrlen);
|
||||||
assert(ret == 0);
|
assert(ret == 0);
|
||||||
|
|
||||||
/* session resuming based on remote endpoint address and port */
|
/* session resuming based on remote endpoint address and port */
|
||||||
@@ -1004,7 +1000,6 @@ static void sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr * mgr)
|
|||||||
|
|
||||||
#endif /* SSL_OP_NO_COMPRESSION */
|
#endif /* SSL_OP_NO_COMPRESSION */
|
||||||
|
|
||||||
SSL_CTX_set_cipher_list(sslctx, mgr->default_ciphers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1019,12 +1014,13 @@ static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt)
|
|||||||
SSL * ssl = NULL;
|
SSL * ssl = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
sslctx_set_opts(sslctx, mgr);
|
sslctx_set_opts(sslctx, mgr);
|
||||||
|
SSL_CTX_set_cipher_list(sslctx, mgr->default_ciphers);
|
||||||
|
|
||||||
//TFE's OPENSSL_VERSION_NUMBER >= 0x10100000L
|
//TFE's OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
if (mgr->sslversion)
|
if (mgr->ssl_min_version)
|
||||||
{
|
{
|
||||||
if (SSL_CTX_set_min_proto_version(sslctx, mgr->sslversion) == 0 ||
|
if (SSL_CTX_set_min_proto_version(sslctx, mgr->ssl_min_version) == 0 ||
|
||||||
SSL_CTX_set_max_proto_version(sslctx, mgr->sslversion) == 0)
|
SSL_CTX_set_max_proto_version(sslctx, mgr->ssl_min_version) == 0)
|
||||||
{
|
{
|
||||||
SSL_CTX_free(sslctx);
|
SSL_CTX_free(sslctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -1785,6 +1785,10 @@ struct cipher_suite cipher_suite_list_tls13[] =
|
|||||||
|
|
||||||
void ssl_chello_free(struct ssl_chello* chello)
|
void ssl_chello_free(struct ssl_chello* chello)
|
||||||
{
|
{
|
||||||
|
if(chello==NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
free(chello->sni);
|
free(chello->sni);
|
||||||
chello->sni = NULL;
|
chello->sni = NULL;
|
||||||
free(chello->alpn);
|
free(chello->alpn);
|
||||||
@@ -1796,23 +1800,23 @@ void ssl_chello_free(struct ssl_chello* chello)
|
|||||||
free(chello);
|
free(chello);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* parse_alpn_extension(const unsigned char* buff, size_t buff_len, enum parse_chello_result* result)
|
static char* parse_alpn_extension(const unsigned char* buff, size_t buff_len, enum chello_parse_result* result)
|
||||||
{
|
{
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
size_t len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
|
size_t len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
|
||||||
if(2 + len != buff_len)
|
if(2 + len != buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
char* alpn = (char*)malloc(len + 1);
|
char* alpn = (char*)malloc(len + 1);
|
||||||
strncpy(alpn, (const char*)buff + 2, len);
|
strncpy(alpn, (const char*)buff + 2, len);
|
||||||
alpn[len] = '\0';
|
alpn[len] = '\0';
|
||||||
*result = PARSE_CHELLO_SUCCESS;
|
*result = CHELLO_PARSE_SUCCESS;
|
||||||
return alpn;
|
return alpn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* parse_server_name_extension(const unsigned char* buff, size_t buff_len, enum parse_chello_result* result)
|
static char* parse_server_name_extension(const unsigned char* buff, size_t buff_len, enum chello_parse_result* result)
|
||||||
{
|
{
|
||||||
size_t pos = 2; /* skip server name list length */
|
size_t pos = 2; /* skip server name list length */
|
||||||
size_t len;
|
size_t len;
|
||||||
@@ -1822,7 +1826,7 @@ static char* parse_server_name_extension(const unsigned char* buff, size_t buff
|
|||||||
len = ((size_t)buff[pos + 1] << 8) + (size_t)buff[pos + 2];
|
len = ((size_t)buff[pos + 1] << 8) + (size_t)buff[pos + 2];
|
||||||
if (pos + 3 + len > buff_len)
|
if (pos + 3 + len > buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
switch (buff[pos])
|
switch (buff[pos])
|
||||||
@@ -1831,18 +1835,18 @@ static char* parse_server_name_extension(const unsigned char* buff, size_t buff
|
|||||||
sni = (char*)malloc(len + 1);
|
sni = (char*)malloc(len + 1);
|
||||||
strncpy(sni, (const char*)buff + pos + 3, len);
|
strncpy(sni, (const char*)buff + pos + 3, len);
|
||||||
sni[len] = '\0';
|
sni[len] = '\0';
|
||||||
*result = PARSE_CHELLO_SUCCESS;
|
*result = CHELLO_PARSE_SUCCESS;
|
||||||
}
|
}
|
||||||
pos += 3 + len;
|
pos += 3 + len;
|
||||||
}
|
}
|
||||||
if (pos != buff_len)
|
if (pos != buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
}
|
}
|
||||||
return sni;
|
return sni;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum parse_chello_result parse_extensions(const unsigned char* buff, size_t buff_len, struct ssl_chello* chello) {
|
static enum chello_parse_result parse_extensions(const unsigned char* buff, size_t buff_len, struct ssl_chello* chello) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
/* Parse each 4 bytes for the extension header */
|
/* Parse each 4 bytes for the extension header */
|
||||||
while (pos + 4 <= buff_len)
|
while (pos + 4 <= buff_len)
|
||||||
@@ -1853,11 +1857,11 @@ static enum parse_chello_result parse_extensions(const unsigned char* buff, size
|
|||||||
{
|
{
|
||||||
if (pos + 4 + len > buff_len)
|
if (pos + 4 + len > buff_len)
|
||||||
{
|
{
|
||||||
return PARSE_CHELLO_INVALID_FORMAT;
|
return CHELLO_PARSE_INVALID_FORMAT;
|
||||||
}
|
}
|
||||||
enum parse_chello_result result = PARSE_CHELLO_SUCCESS;
|
enum chello_parse_result result = CHELLO_PARSE_SUCCESS;
|
||||||
chello->sni = parse_server_name_extension(buff + pos + 4, len, &result);
|
chello->sni = parse_server_name_extension(buff + pos + 4, len, &result);
|
||||||
if(result != PARSE_CHELLO_SUCCESS)
|
if(result != CHELLO_PARSE_SUCCESS)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1867,11 +1871,11 @@ static enum parse_chello_result parse_extensions(const unsigned char* buff, size
|
|||||||
{
|
{
|
||||||
if (pos + 4 + len > buff_len)
|
if (pos + 4 + len > buff_len)
|
||||||
{
|
{
|
||||||
return PARSE_CHELLO_INVALID_FORMAT;
|
return CHELLO_PARSE_INVALID_FORMAT;
|
||||||
}
|
}
|
||||||
enum parse_chello_result result = PARSE_CHELLO_SUCCESS;
|
enum chello_parse_result result = CHELLO_PARSE_SUCCESS;
|
||||||
chello->alpn = parse_alpn_extension(buff + pos + 4, len, &result);
|
chello->alpn = parse_alpn_extension(buff + pos + 4, len, &result);
|
||||||
if(result != PARSE_CHELLO_SUCCESS)
|
if(result != CHELLO_PARSE_SUCCESS)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1881,12 +1885,12 @@ static enum parse_chello_result parse_extensions(const unsigned char* buff, size
|
|||||||
/* Check we ended where we expected to */
|
/* Check we ended where we expected to */
|
||||||
if (pos != buff_len)
|
if (pos != buff_len)
|
||||||
{
|
{
|
||||||
return PARSE_CHELLO_INVALID_FORMAT;
|
return CHELLO_PARSE_INVALID_FORMAT;
|
||||||
}
|
}
|
||||||
return PARSE_CHELLO_SUCCESS;
|
return CHELLO_PARSE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* parse_cipher_suites(struct cipher_suite* _cipher_suite_list, int n, const unsigned char* buff, size_t buff_len, enum parse_chello_result* result)
|
static char* parse_cipher_suites(struct cipher_suite* _cipher_suite_list, int n, const unsigned char* buff, size_t buff_len, enum chello_parse_result* result)
|
||||||
{
|
{
|
||||||
char* cipher_suites_str = (char* )malloc(TFE_STRING_MAX);
|
char* cipher_suites_str = (char* )malloc(TFE_STRING_MAX);
|
||||||
cipher_suites_str[0] = '\0';
|
cipher_suites_str[0] = '\0';
|
||||||
@@ -1909,28 +1913,28 @@ static char* parse_cipher_suites(struct cipher_suite* _cipher_suite_list, int n,
|
|||||||
cipher_suites_str[len-1] = '\0';
|
cipher_suites_str[len-1] = '\0';
|
||||||
if(pos != buff_len)
|
if(pos != buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*result = PARSE_CHELLO_SUCCESS;
|
*result = CHELLO_PARSE_SUCCESS;
|
||||||
return cipher_suites_str;
|
return cipher_suites_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len, enum parse_chello_result* result)
|
struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len, enum chello_parse_result* result)
|
||||||
{
|
{
|
||||||
if(buff == NULL)
|
if(buff == NULL)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(buff_len < 1)
|
if(buff_len < 1)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_NOT_ENOUGH_BUFF;
|
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(buff[0] != 0x80 && buff[0] != 0x16)
|
if(buff[0] != 0x80 && buff[0] != 0x16)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* SSL 2.0 compatible Client Hello
|
/* SSL 2.0 compatible Client Hello
|
||||||
@@ -1944,13 +1948,13 @@ struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len,
|
|||||||
_chello->min_version.major = 0x02;
|
_chello->min_version.major = 0x02;
|
||||||
if(buff_len < 2)
|
if(buff_len < 2)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_NOT_ENOUGH_BUFF;
|
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
size_t len = (size_t)buff[1];
|
size_t len = (size_t)buff[1];
|
||||||
if (buff_len < len + 2)
|
if (buff_len < len + 2)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_NOT_ENOUGH_BUFF;
|
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
buff_len = len + 2;
|
buff_len = len + 2;
|
||||||
@@ -1958,41 +1962,43 @@ struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len,
|
|||||||
/* Handshark Message Type: Client Hello */
|
/* Handshark Message Type: Client Hello */
|
||||||
if (pos + 1 > buff_len)
|
if (pos + 1 > buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
if (buff[pos] != 0x01)
|
if (buff[pos] != 0x01)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
pos += 1;
|
pos += 1;
|
||||||
/* Version */
|
/* Version */
|
||||||
if(pos + 2 > buff_len)
|
if(pos + 2 > buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
_chello->max_version.major = buff[pos];
|
_chello->max_version.major = buff[pos];
|
||||||
_chello->max_version.minor = buff[pos + 1];
|
_chello->max_version.minor = buff[pos + 1];
|
||||||
*result = PARSE_CHELLO_SUCCESS;
|
_chello->max_version.ossl_format=(uint16_t)_chello->max_version.major<<8|_chello->max_version.minor;
|
||||||
|
*result = CHELLO_PARSE_SUCCESS;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (buff_len < 5)
|
if (buff_len < 5)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_NOT_ENOUGH_BUFF;
|
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(buff[1] != 3 || buff[2] > 4 || buff[2] < 0)
|
if(buff[1] != 3 || buff[2] > 4 || buff[2] < 0)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
struct ssl_chello* _chello = (struct ssl_chello*)ALLOC(struct ssl_chello, 1);
|
struct ssl_chello* _chello = (struct ssl_chello*)ALLOC(struct ssl_chello, 1);
|
||||||
_chello->min_version.major = buff[1];
|
_chello->min_version.major = buff[1];
|
||||||
_chello->min_version.minor = buff[2];
|
_chello->min_version.minor = buff[2];
|
||||||
|
_chello->min_version.ossl_format=(uint16_t)_chello->min_version.major<<8|_chello->min_version.minor;
|
||||||
_chello->max_version.major = -1;
|
_chello->max_version.major = -1;
|
||||||
_chello->max_version.minor = -1;
|
_chello->max_version.minor = -1;
|
||||||
_chello->sni = NULL;
|
_chello->sni = NULL;
|
||||||
@@ -2003,34 +2009,36 @@ struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len,
|
|||||||
size_t len = ((size_t)buff[3] << 8) + (size_t)buff[4] + 5;
|
size_t len = ((size_t)buff[3] << 8) + (size_t)buff[4] + 5;
|
||||||
if (buff_len < len)
|
if (buff_len < len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_NOT_ENOUGH_BUFF;
|
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
buff_len = len;
|
buff_len = len;
|
||||||
size_t pos = 5;
|
size_t pos = 5;
|
||||||
if (pos + 1 > buff_len)
|
if (pos + 1 > buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
if (buff[pos] != 0x01)
|
if (buff[pos] != 0x01)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if(pos + 2 > buff_len)
|
if(pos + 2 > buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
_chello->max_version.major = buff[pos];
|
_chello->max_version.major = buff[pos];
|
||||||
_chello->max_version.minor = buff[pos+1];
|
_chello->max_version.minor = buff[pos+1];
|
||||||
|
_chello->max_version.ossl_format=(uint16_t)_chello->max_version.major<<8|_chello->max_version.minor;
|
||||||
|
|
||||||
pos += 34;
|
pos += 34;
|
||||||
/* Session ID */
|
/* Session ID */
|
||||||
if (pos + 1 > buff_len)
|
if (pos + 1 > buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
len = (size_t)buff[pos];
|
len = (size_t)buff[pos];
|
||||||
@@ -2038,25 +2046,25 @@ struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len,
|
|||||||
/* Cipher Suites */
|
/* Cipher Suites */
|
||||||
if (pos + 2 > buff_len)
|
if (pos + 2 > buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
|
len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
|
||||||
pos += 2;
|
pos += 2;
|
||||||
if(pos + len > buff_len)
|
if(pos + len > buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
int n = sizeof(cipher_suite_list) / sizeof(struct cipher_suite);
|
int n = sizeof(cipher_suite_list) / sizeof(struct cipher_suite);
|
||||||
_chello->cipher_suites = parse_cipher_suites(cipher_suite_list, n, buff + pos, len, result);
|
_chello->cipher_suites = parse_cipher_suites(cipher_suite_list, n, buff + pos, len, result);
|
||||||
if(*result != PARSE_CHELLO_SUCCESS)
|
if(*result != CHELLO_PARSE_SUCCESS)
|
||||||
{
|
{
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
n = sizeof(cipher_suite_list_tls13) / sizeof(struct cipher_suite);
|
n = sizeof(cipher_suite_list_tls13) / sizeof(struct cipher_suite);
|
||||||
_chello->cipher_suites_tls13 = parse_cipher_suites(cipher_suite_list_tls13, n, buff + pos, len, result);
|
_chello->cipher_suites_tls13 = parse_cipher_suites(cipher_suite_list_tls13, n, buff + pos, len, result);
|
||||||
if(*result != PARSE_CHELLO_SUCCESS)
|
if(*result != CHELLO_PARSE_SUCCESS)
|
||||||
{
|
{
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
@@ -2064,7 +2072,7 @@ struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len,
|
|||||||
/* Compression Methods */
|
/* Compression Methods */
|
||||||
if (pos >= buff_len)
|
if (pos >= buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
len = (size_t)buff[pos];
|
len = (size_t)buff[pos];
|
||||||
@@ -2074,29 +2082,29 @@ struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len,
|
|||||||
{
|
{
|
||||||
if(pos == buff_len)
|
if(pos == buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_SUCCESS;
|
*result = CHELLO_PARSE_SUCCESS;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Extensions */
|
/* Extensions */
|
||||||
if (pos + 2 > buff_len)
|
if (pos + 2 > buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
|
len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
|
||||||
pos += 2;
|
pos += 2;
|
||||||
if (pos + len > buff_len)
|
if (pos + len > buff_len)
|
||||||
{
|
{
|
||||||
*result = PARSE_CHELLO_INVALID_FORMAT;
|
*result = CHELLO_PARSE_INVALID_FORMAT;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
enum parse_chello_result rtn = parse_extensions(buff + pos, len, _chello);
|
enum chello_parse_result rtn = parse_extensions(buff + pos, len, _chello);
|
||||||
*result = rtn;
|
*result = rtn;
|
||||||
return _chello;
|
return _chello;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ int main()
|
|||||||
0x69
|
0x69
|
||||||
};
|
};
|
||||||
size_t buff_len = sizeof(buff) / sizeof(char);
|
size_t buff_len = sizeof(buff) / sizeof(char);
|
||||||
enum parse_chello_result result;
|
enum chello_parse_result result;
|
||||||
struct ssl_chello* chello = ssl_chello_parse(buff, buff_len, &result);
|
struct ssl_chello* chello = ssl_chello_parse(buff, buff_len, &result);
|
||||||
printf("-----------------------------ssl2.0 only parse version --------------------------------\n");
|
printf("-----------------------------ssl2.0 only parse version --------------------------------\n");
|
||||||
printf("result is %d\n", result);
|
printf("result is %d\n", result);
|
||||||
@@ -66,7 +66,7 @@ int main()
|
|||||||
0x00, 0x14, 0x00, 0x11, 0x01, 0x00
|
0x00, 0x14, 0x00, 0x11, 0x01, 0x00
|
||||||
};
|
};
|
||||||
size_t buff1_len = sizeof(buff1) / sizeof(char);
|
size_t buff1_len = sizeof(buff1) / sizeof(char);
|
||||||
enum parse_chello_result result1;
|
enum chello_parse_result result1;
|
||||||
struct ssl_chello* chello1 = ssl_chello_parse(buff1, buff1_len, &result1);
|
struct ssl_chello* chello1 = ssl_chello_parse(buff1, buff1_len, &result1);
|
||||||
printf("--------------------------------ssl3.0, no extensions --------------------------------\n");
|
printf("--------------------------------ssl3.0, no extensions --------------------------------\n");
|
||||||
printf("result is %d\n", result1);
|
printf("result is %d\n", result1);
|
||||||
@@ -138,12 +138,12 @@ int main()
|
|||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
size_t buff2_len = sizeof(buff2) / sizeof(char);
|
size_t buff2_len = sizeof(buff2) / sizeof(char);
|
||||||
enum parse_chello_result result2;
|
enum chello_parse_result result2;
|
||||||
struct ssl_chello* chello2 = ssl_chello_parse(buff2, buff2_len, &result2);
|
struct ssl_chello* chello2 = ssl_chello_parse(buff2, buff2_len, &result2);
|
||||||
printf("---------------------------tls1.2 --------------------------------\n");
|
printf("---------------------------tls1.2 --------------------------------\n");
|
||||||
printf("result is %d\n", result2);
|
printf("result is %d\n", result2);
|
||||||
printf("min version: %d, %d\n", chello2->min_version.major, chello2->min_version.minor);
|
printf("min version: %d, %d, ossl format: %x\n", chello2->min_version.major, chello2->min_version.minor, chello2->min_version.ossl_format);
|
||||||
printf("max version: %d, %d\n", chello2->max_version.major, chello2->max_version.minor);
|
printf("max version: %d, %d, ossl format: %x\n", chello2->max_version.major, chello2->max_version.minor, chello2->max_version.ossl_format);
|
||||||
printf("cipher suites: %s\n", chello2->cipher_suites);
|
printf("cipher suites: %s\n", chello2->cipher_suites);
|
||||||
printf("cipher suites for tls1.3: %s\n", chello2->cipher_suites_tls13);
|
printf("cipher suites for tls1.3: %s\n", chello2->cipher_suites_tls13);
|
||||||
printf("sni: %s\n", chello2->sni);
|
printf("sni: %s\n", chello2->sni);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "cjson/cJSON.h"
|
#include "cjson/cJSON.h"
|
||||||
#include "ssl_utils.h"
|
#include "ssl_utils.h"
|
||||||
#include "key_keeper.h"
|
#include "key_keeper.h"
|
||||||
|
#include <assert.h>
|
||||||
struct keyring_private
|
struct keyring_private
|
||||||
{
|
{
|
||||||
struct keyring head;
|
struct keyring head;
|
||||||
@@ -29,15 +29,6 @@ static struct keyring_private* keyring_new(void)
|
|||||||
return kyr;
|
return kyr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Increment reference count.
|
|
||||||
static void keyring_ref_inc(struct keyring_private* kyr)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&kyr->mutex);
|
|
||||||
kyr->references++;
|
|
||||||
pthread_mutex_unlock(&kyr->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Thread-safe setter functions; they copy the value (refcounts are inc'd).
|
* Thread-safe setter functions; they copy the value (refcounts are inc'd).
|
||||||
*/
|
*/
|
||||||
@@ -216,6 +207,7 @@ static void tfe_rpc_on_succ(void* result, void* user)
|
|||||||
//printf("data is %s\n", data);
|
//printf("data is %s\n", data);
|
||||||
printf("len is %d\n", len);
|
printf("len is %d\n", len);
|
||||||
struct keyring* kyr = get_keyring_from_response(data);
|
struct keyring* kyr = get_keyring_from_response(data);
|
||||||
|
assert(kyr!=NULL);
|
||||||
//add to hash table
|
//add to hash table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user