This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
tango-certstore/program/src/cert_session.cpp

2370 lines
62 KiB
C++
Raw Normal View History

/*************************************************************************
> File Name: cert_session.c
> Author:
> Mail:
> Created Time: Fri 01 Jun 2018 02:00:56 AM PDT
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <uuid/uuid.h>
#include "rt_string.h"
#include "rt_common.h"
#include "rt_stdlib.h"
#include "rt_time.h"
#include "rt_tmr.h"
#include "json.h"
/* openssl**/
#include <openssl/opensslv.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/crypto.h>
#include <openssl/engine.h>
#include <openssl/pkcs12.h>
#include <openssl/rsa.h>
#include <event2/listener.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <async.h>
2023-03-29 17:34:26 +08:00
#include <MESA/maat.h>
2020-04-09 14:29:13 +08:00
#include <MESA/field_stat2.h>
#include <MESA/MESA_prof_load.h>
2023-03-29 17:34:26 +08:00
#include "cert_store.h"
#include "libevent.h"
#include "cert_session.h"
#include "logging.h"
#define WAIT_FOR_EFFECTIVE_US 1000*1000
#define SG_DATA_SIZE 10240
#define LOCAL_USER_PEN 1
#define LOCAL_USER_DER 2
#define LOCAL_USER_P12 3
#define CM_UPDATE_TYPE_FULL 1
#define CM_UPDATE_TYPE_INC 2
static x509_forge_thread *threads;
enum keypair_action
{
KEYPAIR_ACTION_REQ = 0,
KEYPAIR_ACTION_SQL,
KEYPAIR_ACTION_SIGN,
KEYPAIR_ACTION_ERR,
KEYPAIR_ACTION_MAX
2019-08-21 14:03:53 +08:00
};
struct fs_stats_t{
int field_id[KEYPAIR_ACTION_MAX];
int line_ids[KEYPAIR_ACTION_MAX];
screen_stat_handle_t handle;
char histogram_bins[256];
enum field_calc_algo favorite;
};
static struct fs_stats_t g_FP_instance = {
.field_id = {0},
.line_ids = {0},
.handle = NULL,
.histogram_bins = {0},
};
static const char* FP_HISTOGRAM_BINS="0.50,0.80,0.9,0.95,0.99";
#define sizeof_seconds(x) (x * 24 * 60 * 60)
#define half_hours(x) (x * 1800)
void connectCallback(const struct redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Redis connect error : %s", c->errstr);
return;
}
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "Redis server connected...");
}
void disconnectCallback(const struct redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Redis disconnect error: %s", c->errstr);
return;
}
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Redis server disconnected...");
}
void x509_get_private_key(EVP_PKEY *pkey, char *pubkey)
{
BIO *bp = NULL;
int len = 0;
if ( (bp=BIO_new(BIO_s_mem())) == NULL){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "unable to create BIO for output");
goto finish;
}
PEM_write_bio_PrivateKey(bp, pkey, NULL, NULL, 0, NULL, NULL);
len = BIO_read(bp, pubkey, SG_DATA_SIZE);
if(len <= 0) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error reading signature file");
goto free_err;
}
pubkey[len] = '\0';
free_err:
BIO_free(bp);
finish:
return;
}
#define R_RSA_ALGO_1024 1024
#define R_RSA_ALGO_2048 2048
#define R_RSA_ALGO_4096 4096
#define R_DH_ALGO_1024 1
typedef struct {
const char *name; /* NIST Name of curve */
int nid; /* Curve NID */
} x509_algo_name;
static x509_algo_name algo_name[] = {
{"rsa1024", R_RSA_ALGO_1024},
{"rsa2048", R_RSA_ALGO_2048},
{"rsa4096", R_RSA_ALGO_4096},
{"secp256r1", NID_X9_62_prime256v1},
{"secp384r1",NID_secp384r1}
};
static void fp_stat_latency(struct timespec create_time, int keys)
{
struct timespec end;
long long jiffies_ms=0;
clock_gettime(CLOCK_MONOTONIC,&end);
FS_operate(g_FP_instance.handle, g_FP_instance.line_ids[keys], 0, FS_OP_ADD, 1);
jiffies_ms=(end.tv_sec-create_time.tv_sec)*1000000+(end.tv_nsec-create_time.tv_nsec)/1000;
FS_operate(g_FP_instance.handle, g_FP_instance.field_id[keys], 0, FS_OP_SET, jiffies_ms);
FS_operate(g_FP_instance.handle, g_FP_instance.field_id[KEYPAIR_ACTION_REQ], 0, FS_OP_SET, jiffies_ms);
return;
}
static size_t x509_algo_str2idx(const char *public_algo)
2019-08-21 14:03:53 +08:00
{
size_t i = 0;
if(public_algo == NULL)
2019-08-21 14:03:53 +08:00
{
goto finish;
2019-08-21 14:03:53 +08:00
}
if (0 == strcasecmp(public_algo, "dh1024"))
{
return R_DH_ALGO_1024;
}
for (i = 0; i < sizeof(algo_name) / sizeof(x509_algo_name); i++)
2019-08-21 14:03:53 +08:00
{
if (0 == strcasecmp(public_algo, algo_name[i].name))
{
return algo_name[i].nid;
}
2019-08-21 14:03:53 +08:00
}
finish:
return R_RSA_ALGO_2048;
2019-08-21 14:03:53 +08:00
}
static int ssl_key_gen_rsa(EVP_PKEY** pkey, int nid)
{
RSA *rsa = NULL;
EVP_PKEY *pk = NULL;
if((pk = EVP_PKEY_new()) == NULL){
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "ssl_key_gen_rsa, gen new key failed!");
goto err;
}
rsa = RSA_generate_key(nid, RSA_F4, NULL, NULL);
if(!EVP_PKEY_assign_RSA(pk, rsa)){
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "ssl_key_gen_rsa, assign key failed!");
EVP_PKEY_free(pk);
goto err;
}
rsa = NULL;
*pkey = pk;
return 1;
err:
return 0;
}
int ssl_key_gen_dh(EVP_PKEY** pkey, int nid)
{
EVP_PKEY *pk = NULL;
DH *dh = DH_new();
if(dh == NULL)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "create dh key faild");
goto error;
}
#if 0
dh = DH_generate_parameters(nid, DH_GENERATOR_2, NULL, NULL);
if (dh == NULL)
{
return 0;
}
DH_generate_key(dh);
#endif
if (!DH_generate_parameters_ex(dh, nid, DH_GENERATOR_2, NULL))
{
goto error;
}
if (!DH_generate_key(dh))
{
goto error;
}
if((pk = EVP_PKEY_new()) == NULL){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "ssl_key_gen_ecc, gen new key failed!");
goto error;
}
if(!EVP_PKEY_assign_DH(pk, dh)){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "ssl_key_gen_ecc, assign key failed!");
EVP_PKEY_free(pk);
goto error;
}
*pkey = pk;
return 1;
error:
if(dh!=NULL)
DH_free(dh);
return 0;
}
int ssl_key_gen_ecc(EVP_PKEY** pkey, int nid)
{
EC_GROUP *group = NULL;
EVP_PKEY *pk = NULL;
EC_KEY *eckey = EC_KEY_new();
if(eckey == NULL)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "create ec key faild");
goto error;
}
/** Take an elliptic curve */
group = EC_GROUP_new_by_curve_name(nid);
if (group == NULL)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "unable to create curve (%d)\n", nid);
goto error;
}
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
if (EC_KEY_set_group(eckey, group) == 0)
goto error;
if (!EC_KEY_generate_key(eckey))
{
goto error;
}
if((pk = EVP_PKEY_new()) == NULL){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "ssl_key_gen_ecc, gen new key failed!");
goto error;
}
if(!EVP_PKEY_assign_EC_KEY(pk, eckey)){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "ssl_key_gen_ecc, assign key failed!");
EVP_PKEY_free(pk);
goto error;
}
eckey = NULL;
*pkey = pk;
return 1;
error:
if(eckey!=NULL)
EC_KEY_free(eckey);
return 0;
}
static int ssl_key_gen(EVP_PKEY** pkey, char *pubkey, char *public_algo)
{
int ret = 0, nid = 0;
nid = x509_algo_str2idx(public_algo);
switch(nid)
{
case R_RSA_ALGO_1024:
case R_RSA_ALGO_2048:
case R_RSA_ALGO_4096:
ret = ssl_key_gen_rsa(pkey, nid);
break;
case NID_X9_62_prime256v1:
case NID_secp384r1:
ret = ssl_key_gen_ecc(pkey, nid);
break;
case R_DH_ALGO_1024:
ret = ssl_key_gen_dh(pkey, 1024);
default:
break;
}
if (ret != 1 || pkey == NULL)
return 0;
x509_get_private_key(*pkey, pubkey);
return 1;
}
static X509* base_load_pkcs12(BIO *in, EVP_PKEY **pkey, X509 **x, STACK_OF(X509) **ca)
{
PKCS12 *p12 = NULL;
const char *pass = "";
X509 *_x = NULL;
EVP_PKEY *_pkey;
STACK_OF(X509) *_ca = NULL;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
p12 = d2i_PKCS12_bio(in, NULL);
if (p12 == NULL) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error loading PKCS12 file");
goto finish;
}
if (!PKCS12_parse(p12, pass, &_pkey, &_x, &_ca)) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error parsing PKCS#12 file");
goto finish;
}
if (x)
*x = _x;
if (pkey)
*pkey = _pkey;
if (ca)
*ca = _ca;
finish:
if (p12)
PKCS12_free(p12);
return _x;
}
int x509_get_last_ca(char *file, X509 *cx509)
{
int last = 0;
X509 *x = NULL;
BIO *bio = NULL;
if ((bio = BIO_new(BIO_s_file())) == NULL)
{
goto finish;
}
if (BIO_read_filename(bio, file) <= 0)
{
goto finish;
}
while(NULL!=(x=PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL)))
{
if (0 == X509_NAME_cmp(X509_get_issuer_name(x), X509_get_subject_name(cx509)))
{
last = 1;
X509_free(x);
break;
};
X509_free(x);
}
BIO_free (bio);
finish:
return last;
}
X509* x509_get_root_ca(char *file, int is_send, char *keyring_type, STACK_OF(X509) **stack_ca)
{
int x509_cnt = 0;
BIO *bio = NULL;
STACK_OF(X509) *stack_x509 = NULL;
X509 *certificate = NULL, *issuer = NULL, *caroot = NULL;
if(!file){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Input cert file is empty.");
goto finish;
}
if ((bio = BIO_new(BIO_s_file())) == NULL) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Bio malloc failed.");
goto finish;
}
if (BIO_read_filename(bio, file) <= 0) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error opening %s", file);
goto finish;
}
if ((stack_x509 = sk_X509_new_null()) == NULL)
{
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
goto finish;
}
while(NULL!=(certificate=PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL)))
{
if (0 == X509_NAME_cmp(X509_get_issuer_name(certificate), X509_get_subject_name(certificate)))
{
/*This is caroot ca**/
caroot = certificate;
if (is_send == 0)
continue;
};
/*This is last ca*/
if (x509_get_last_ca(file, certificate) == 0)
{
issuer = certificate;
if (strcasecmp(keyring_type, "end-entity") == 0)
{
continue;
}
}
sk_X509_push(stack_x509, certificate);
x509_cnt++;
}
if (x509_cnt >= 1)
*stack_ca = stack_x509;
if (issuer != NULL)
{
if (is_send == 0)
X509_free(caroot);
}
else
{
issuer = caroot;
}
BIO_free (bio);
finish:
return issuer;
}
EVP_PKEY * cert_base_key_x509 (BIO * bio, int iFormat, const char *strPwd)
{
EVP_PKEY *pkey = NULL;
switch (iFormat){
case LOCAL_USER_PEN:
pkey = PEM_read_bio_PrivateKey (bio, NULL, NULL, (char *)strPwd);
break;
case LOCAL_USER_P12:
base_load_pkcs12(bio, &pkey, NULL, NULL);
break;
default:
break;
}
return pkey;
}
EVP_PKEY * cert_load_key(char *keyfile)
{
EVP_PKEY *pkey = NULL;
BIO *in = NULL;
if(!keyfile){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Input key file is empty.");
goto finish;
}
if ((in = BIO_new(BIO_s_file())) == NULL) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Bio malloc failed.");
goto finish;
}
if (BIO_read_filename(in, keyfile) <= 0) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error opening %s\n", keyfile);
goto finish;
}
if ((pkey = cert_base_key_x509 (in, LOCAL_USER_PEN, "")) != NULL)
goto finish;
(void)BIO_reset (in);
if ((pkey = cert_base_key_x509 (in, LOCAL_USER_P12, "")) != NULL)
goto finish;
finish:
if (in != NULL)
BIO_free (in);
return pkey;
}
void uuid_squeeze(char *s,int c)
{
int i,j;
for (i = 0, j = 0; s[i] != '\0'; i++)
{
if (s[i] != c)
{
s[j++] = s[i];
}
}
s[j] = '\0';
}
int
ssl_x509_set_serial(ASN1_INTEGER *ai)
{
int ret = -1;
uuid_t uu;
char buf[64] = {0};
BIGNUM *bignum = NULL;
uuid_generate(uu);
uuid_unparse(uu, buf);
uuid_squeeze(buf, '-');
BN_hex2bn(&bignum, buf);
if (ai && !BN_to_ASN1_INTEGER(bignum, ai))
goto error;
ret = 1;
error:
if (bignum)
BN_free(bignum);
return ret;
}
/*
* Add a X509v3 extension to a cert and handle errors.
* Returns -1 on errors, 0 on success.
*/
int ssl_x509_v3ext_add(X509V3_CTX * ctx, X509 * crt, const char *k, const char *v)
{
X509_EXTENSION * ext;
if (!(ext = X509V3_EXT_conf(NULL, ctx, k, v)))
{
return -1;
}
if (X509_add_ext(crt, ext, -1) != 1)
{
X509_EXTENSION_free(ext);
return -1;
}
X509_EXTENSION_free(ext);
return 0;
}
int ssl_x509_v3ext_copy_by_nid(X509 *crt, X509 *origcrt, int nid)
{
X509_EXTENSION *ext;
int pos;
pos = X509_get_ext_by_NID(origcrt, nid, -1);
if (pos == -1)
return 0;
ext = X509_get_ext(origcrt, pos);
if (!ext)
return -1;
if (X509_add_ext(crt, ext, -1) != 1)
return -1;
return 1;
}
/*
* Add extension using V3 code: we can set the config file as NULL because we
* wont reference any other sections.
*/
int add_ext(X509 *cacrt, X509 *cert, int nid, char *value)
{
X509_EXTENSION *ex;
X509V3_CTX ctx;
/* This sets the 'context' of the extensions. */
/* No configuration database */
X509V3_set_ctx_nodb(&ctx);
/*
* Issuer and subject certs: both the target since it is self signed, no
* request and no CRL
*/
X509V3_set_ctx(&ctx, cacrt, cert, NULL, NULL, 0);
ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
if (!ex)
return 0;
X509_add_ext(cert, ex, -1);
X509_EXTENSION_free(ex);
return 1;
}
2019-08-07 15:49:38 +08:00
static time_t ASN1_GetTimeT(ASN1_TIME* time)
{
struct tm t; time_t utc_timep;
2019-08-07 15:49:38 +08:00
const char* str = (const char*) time->data;
size_t i = 0;
memset(&t, 0, sizeof(t));
if (time->type == V_ASN1_UTCTIME) {/* two digit year */
t.tm_year = (str[i++] - '0') * 10;
t.tm_year += (str[i++] - '0');
if (t.tm_year < 70)
t.tm_year += 100;
} else if (time->type == V_ASN1_GENERALIZEDTIME) {/* four digit year */
t.tm_year = (str[i++] - '0') * 1000;
t.tm_year+= (str[i++] - '0') * 100;
t.tm_year+= (str[i++] - '0') * 10;
t.tm_year+= (str[i++] - '0');
t.tm_year -= 1900;
}
t.tm_mon = (str[i++] - '0') * 10;
t.tm_mon += (str[i++] - '0') - 1; // -1 since January is 0 not 1.
t.tm_mday = (str[i++] - '0') * 10;
t.tm_mday+= (str[i++] - '0');
t.tm_hour = (str[i++] - '0') * 10;
t.tm_hour+= (str[i++] - '0');
t.tm_min = (str[i++] - '0') * 10;
t.tm_min += (str[i++] - '0');
t.tm_sec = (str[i++] - '0') * 10;
t.tm_sec += (str[i++] - '0');
/* Note: we did not adjust the time based on time zone information */
setenv("TZ", "UTC", 1);
utc_timep = mktime(&t);
unsetenv("TZ");
return utc_timep;
2019-08-07 15:49:38 +08:00
}
void x509_get_private_ecc_key(EC_KEY *key1, char *pubkey)
{
BIO *bp = NULL;
int len = 0;
if ( (bp=BIO_new(BIO_s_mem())) == NULL){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "unable to create BIO for output");
goto finish;
}
PEM_write_bio_ECPrivateKey(bp, key1, NULL, NULL, 0, NULL, NULL);
len = BIO_read(bp, pubkey, SG_DATA_SIZE);
if(len <= 0){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error reading signature file");
goto free_err;
}
pubkey[len] = '\0';
free_err:
BIO_free(bp);
finish:
return;
}
X509 *ssl_x509_forge(X509 *cacrt, EVP_PKEY *cakey, X509 *origcrt, char *pkey, int *expire_time, char *crlurl, char *public_algo)
{
int rv;
X509 *crt = NULL;
EVP_PKEY* key = NULL;
X509_NAME *subject = NULL, *issuer = NULL;
if(!ssl_key_gen(&key, pkey, public_algo)){
goto err;
}
//subjectname,issuername
subject = X509_get_subject_name(origcrt);
issuer = X509_get_subject_name(cacrt);
if (!subject || !issuer)
return NULL;
crt = X509_new();
if (!crt)
return NULL;
//version,subjectname,issuername,serialnum,time,pubkey
if (!X509_set_version(crt, 0x02) ||
!X509_set_subject_name(crt, subject) ||
!X509_set_issuer_name(crt, issuer) ||
ssl_x509_set_serial(X509_get_serialNumber(crt)) == -1 ||
!X509_set_pubkey(crt, key))
goto errout;
2019-08-21 14:03:53 +08:00
if (*expire_time <= 0)
{
int day = 0, sec = 0;
ASN1_TIME_set(X509_get_notBefore(crt), ASN1_GetTimeT(X509_get_notBefore(origcrt)));
ASN1_TIME_set(X509_get_notAfter(crt), ASN1_GetTimeT(X509_get_notAfter(origcrt)));
ASN1_TIME_diff(&day, &sec, X509_get_notBefore(crt), X509_get_notAfter(crt));
*expire_time = MIN(sizeof_seconds(day) + sec, sizeof_seconds(1));
}
else
{
if(!X509_gmtime_adj(X509_get_notBefore(crt), (long)(0 - half_hours(*expire_time))) ||
!X509_gmtime_adj(X509_get_notAfter(crt), (long)(half_hours(*expire_time))))
{
goto errout;
}
2019-08-21 14:03:53 +08:00
*expire_time = half_hours(*expire_time);
}
2019-08-07 15:49:38 +08:00
2018-11-30 19:24:44 +08:00
EVP_PKEY_free(key);
key=NULL;
//extensions
X509V3_CTX ctx;
X509V3_set_ctx(&ctx, cacrt, crt, NULL, NULL, 0);
if (ssl_x509_v3ext_add(&ctx, crt, "subjectKeyIdentifier",
"hash") == -1 ||
ssl_x509_v3ext_add(&ctx, crt, "authorityKeyIdentifier",
"keyid,issuer:always") == -1)
goto errout;
rv = ssl_x509_v3ext_copy_by_nid(crt, origcrt,
NID_basic_constraints);
if (rv == 0)
rv = ssl_x509_v3ext_add(&ctx, crt, "basicConstraints",
"CA:FALSE");
if (rv == -1)
goto errout;
rv = ssl_x509_v3ext_add(&ctx, crt, "keyUsage",
"digitalSignature,"
"keyEncipherment");
if (rv == -1)
goto errout;
rv = ssl_x509_v3ext_copy_by_nid(crt, origcrt,
NID_ext_key_usage);
if (rv == 0)
rv = ssl_x509_v3ext_add(&ctx, crt, "extendedKeyUsage",
"serverAuth");
if (rv == -1)
goto errout;
if (crlurl != NULL && strcasecmp(crlurl, "null")){
mesa_runtime_log(RLOG_LV_DEBUG, MODULE_NAME, "Sign certificate the CRL is %s", crlurl);
char * crlurlval;
if (asprintf(&crlurlval, "URI:%s", crlurl) < 0)
goto errout;
if (ssl_x509_v3ext_add(&ctx, crt, "crlDistributionPoints", crlurlval) == -1)
{
free(crlurlval);
goto errout;
}
free(crlurlval);
}
/* no extraname provided: copy original subjectAltName ext */
if (ssl_x509_v3ext_copy_by_nid(crt, origcrt,
NID_subject_alt_name) == -1)
{
goto errout;
}
#ifdef DEBUG_CERTIFICATE
ssl_x509_v3ext_add(&ctx, crt, "nsComment", "Generated by " PKGLABEL);
#endif /* DEBUG_CERTIFICATE */
const EVP_MD *md;
switch (EVP_PKEY_type(EVP_PKEY_base_id(cakey))) {
#ifndef OPENSSL_NO_RSA
case EVP_PKEY_RSA:
switch (X509_get_signature_nid(origcrt)) {
case NID_md5WithRSAEncryption:
md = EVP_md5();
break;
case NID_ripemd160WithRSA:
md = EVP_ripemd160();
break;
case NID_sha1WithRSAEncryption:
md = EVP_sha1();
break;
case NID_sha224WithRSAEncryption:
md = EVP_sha224();
break;
case NID_sha256WithRSAEncryption:
md = EVP_sha256();
break;
case NID_sha384WithRSAEncryption:
md = EVP_sha384();
break;
case NID_sha512WithRSAEncryption:
md = EVP_sha512();
break;
#ifndef OPENSSL_NO_SHA0
case NID_shaWithRSAEncryption:
md = EVP_sha();
break;
#endif /* !OPENSSL_NO_SHA0 */
default:
md = EVP_sha256();
break;
}
break;
#endif /* !OPENSSL_NO_RSA */
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
switch (X509_get_signature_nid(origcrt)) {
case NID_dsaWithSHA1:
case NID_dsaWithSHA1_2:
md = EVP_sha1();
break;
case NID_dsa_with_SHA224:
md = EVP_sha224();
break;
case NID_dsa_with_SHA256:
md = EVP_sha256();
break;
#ifndef OPENSSL_NO_SHA0
case NID_dsaWithSHA:
md = EVP_sha();
break;
#endif /* !OPENSSL_NO_SHA0 */
default:
md = EVP_sha256();
break;
}
break;
#endif /* !OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_ECDSA
case EVP_PKEY_EC:
switch (X509_get_signature_nid(origcrt)) {
case NID_ecdsa_with_SHA1:
md = EVP_sha1();
break;
case NID_ecdsa_with_SHA224:
md = EVP_sha224();
break;
case NID_ecdsa_with_SHA256:
md = EVP_sha256();
break;
case NID_ecdsa_with_SHA384:
md = EVP_sha384();
break;
case NID_ecdsa_with_SHA512:
md = EVP_sha512();
break;
default:
md = EVP_sha256();
break;
}
break;
#endif /* !OPENSSL_NO_ECDSA */
default:
goto errout;
}
if (!X509_sign(crt, cakey, md))
goto errout;
return crt;
errout:
X509_free(crt);
if(key)
EVP_PKEY_free(key);
err:
return NULL;
}
void x509_get_msg_from_ca(X509 *x509, char **root)
{
BIO *bp = NULL;
int len = 0;
if ( (bp=BIO_new(BIO_s_mem())) == NULL){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "unable to create BIO for output");
return;
}
PEM_write_bio_X509(bp, x509);
char *p = NULL;
len = BIO_get_mem_data(bp, &p);
*root = (char*)malloc(len + 1);
memset(*root, 0, len + 1);
len = BIO_read(bp, *root, len);
if(len <= 0) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error reading signature file");
goto err;
}
err:
BIO_free(bp);
return;
}
X509 *
x509_get_ca_from_msg(const char *cert, int len)
{
BIO *bp;
char *in = NULL;
X509* x509 = NULL;
in = (char *)kmalloc(len, MPF_CLR, -1);
assert(in);
strncpy(in, cert, len);
if ( (bp=BIO_new(BIO_s_mem())) == NULL){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "unable to create BIO for output");
goto finish;
}
BIO_printf(bp, "%s", in);
x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL);
if(NULL == x509) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to read pem file");
goto err;
}
err:
BIO_free(bp);
finish:
free(in);
return x509;
}
2023-03-29 17:34:26 +08:00
void request_destroy(struct http_request *request)
2019-08-08 16:06:23 +08:00
{
if (request->odata)
{
free(request->odata);
request->odata=NULL;
}
if (request->sni)
{
free(request->sni);
request->sni=NULL;
}
free(request);
request = NULL;
}
2023-03-29 17:34:26 +08:00
static int redis_async_connect(struct event_base *base, struct redisAsyncContext **cl_ctx)
{
2023-03-29 17:34:26 +08:00
*cl_ctx = redisAsyncConnect(g_cert_store->local_redis_ip, g_cert_store->local_redis_port);
if((*cl_ctx)->err )
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Redis Connect error : %s", (*cl_ctx)->errstr);
2023-03-29 17:34:26 +08:00
return -1;
}
redisLibeventAttach((*cl_ctx), base);
redisAsyncSetConnectCallback((*cl_ctx), connectCallback);
redisAsyncSetDisconnectCallback((*cl_ctx), disconnectCallback);
2023-03-29 17:34:26 +08:00
return 0;
}
2019-08-21 14:03:53 +08:00
static int
evhttp_socket_send_error(struct evhttp_request *req, int error)
2019-08-21 14:03:53 +08:00
{
FS_operate(g_FP_instance.handle, g_FP_instance.line_ids[KEYPAIR_ACTION_ERR], 0, FS_OP_ADD, 1);
2019-08-21 14:03:53 +08:00
evhttp_send_error(req, error, 0);
return 0;
}
/* Callback used for the /dump URI, and for every non-GET request:
* dumps all information to stdout and gives back a trivial 200 ok */
static int
evhttp_socket_send(struct evhttp_request *req, char *sendbuf)
{
struct evbuffer *evb = NULL;
/* This holds the content we're sending. */
evb = evbuffer_new();
if (sendbuf[0] == '\0' && req == NULL){
goto err;
}
evhttp_add_header(evhttp_request_get_output_headers(req),
"Content-Type", "text/html");
2019-08-21 14:03:53 +08:00
evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "keep-alive");
evbuffer_add_printf(evb, "%s", sendbuf);
evhttp_send_reply(req, HTTP_OK, "OK", evb);
goto done;
err:
evhttp_send_error(req, HTTP_NOTFOUND, "Document was not found");
done:
evbuffer_free(evb);
return 0;
}
static void
redis_reget_callback(redisAsyncContext __attribute__((__unused__))*cl_ctx,
void *r, void *privdata)
{
redisReply *reply = (redisReply*)r;
2023-03-29 17:34:26 +08:00
struct http_request *request = (struct http_request *)privdata;
struct evhttp_request *evh_req = request->evh_req;
evhttp_socket_send(evh_req, reply->str);
2019-08-08 16:06:23 +08:00
request_destroy(request);
return;
}
2023-03-29 17:34:26 +08:00
void keyring_table_free_cb(int table_id, void **ad, long argl, void *argp)
{
if (*ad == NULL)
{
return;
}
struct pxy_obj_keyring* pxy_obj=(struct pxy_obj_keyring*)(*ad);
atomic64_dec(&pxy_obj->ref_cnt);
if (atomic64_read(&pxy_obj->ref_cnt) == 0)
{
if (pxy_obj->issuer)
X509_free(pxy_obj->issuer);
if (pxy_obj->key)
EVP_PKEY_free(pxy_obj->key);
if (pxy_obj->stack_ca)
sk_X509_pop_free(pxy_obj->stack_ca, X509_free);
free(pxy_obj);
pxy_obj = NULL;
*ad=NULL;
}
}
void keyring_table_free(struct pxy_obj_keyring* pxy_obj)
{
keyring_table_free_cb(0, (void **)&pxy_obj, 0, NULL);
}
int add_cert_ctx(X509_NAME* name, char* ctx[], int num)
{
int i = 0;
int max = 0;
int item[] = {NID_commonName, NID_countryName,
NID_stateOrProvinceName, NID_localityName,
NID_organizationName, NID_organizationalUnitName,
NID_pkcs9_emailAddress};
max = sizeof(item)/sizeof(item[0]);
max = max > num ? num : max;
for(i = 0; i< max; ++i){
if(!X509_NAME_add_entry_by_NID(name, item[i], MBSTRING_UTF8, (unsigned char *)ctx[i], -1, -1, 0)){
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "add_cert_ctx, add entry:%d to %s failed!", item[i], ctx[i]);
return 0;
}
}
return 1;
}
int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
{
#define SERIAL_RAND_BITS 124
BIGNUM *btmp;
int ret = 0;
if (b)
btmp = b;
else
btmp = BN_new();
if (!btmp)
return 0;
if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
goto error;
if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
goto error;
ret = 1;
error:
if (!b)
BN_free(btmp);
return ret;
}
char *x509_get_sn(X509 *x509)
{
ASN1_INTEGER *asn1_i = NULL;
BIGNUM *bignum = NULL;
char *serial = NULL;
asn1_i = X509_get_serialNumber(x509);
bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
if (bignum == NULL) {
goto finish;
}
serial = BN_bn2hex(bignum);
if (serial == NULL) {
goto finish;
}
BN_free(bignum);
finish:
return serial;
}
static struct pxy_obj_keyring* get_obj_for_id(int keyring_id)
{
struct pxy_obj_keyring *pxy_obj=NULL;
char cfg_id_str[16] = {0};
snprintf(cfg_id_str, sizeof(cfg_id_str), "%d", keyring_id);
2023-03-29 17:34:26 +08:00
pxy_obj = (struct pxy_obj_keyring*)maat_plugin_table_get_ex_data(g_cert_store->instance, g_cert_store->table_id, cfg_id_str);
return pxy_obj;
}
2023-03-29 17:34:26 +08:00
static int x509_online_append(struct x509_object_ctx *def, struct http_request *request, char **sign, char *pkey,
STACK_OF(X509) **stack_ca)
{
X509* x509 = NULL;
int is_valid = 1; int keyring_id = request->keyring_id;
int expire_time = 0; char *serial = NULL;
X509 *cacrt = NULL; EVP_PKEY *cakey = NULL;
char *v3_ctl=NULL, *public_algo=NULL;
struct pxy_obj_keyring *pxy_obj = get_obj_for_id(keyring_id);
if (NULL == pxy_obj)
{
2023-03-29 17:34:26 +08:00
if (!g_cert_store->local_debug)
{
pxy_obj = get_obj_for_id(keyring_id);
2020-04-09 14:29:13 +08:00
if (pxy_obj == NULL)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Get the default keypair failed, EXIT!!!");
exit(0);
}
else
{
mesa_runtime_log(RLOG_LV_DEBUG, MODULE_NAME, "Get the keypar %d, sign cert", keyring_id);
2020-04-09 14:29:13 +08:00
}
}
else
{
cacrt = (is_valid == 1) ? def->root : def->insec_root;
cakey = (is_valid == 1) ? def->key : def->insec_key;
2023-03-29 17:34:26 +08:00
expire_time = g_cert_store->expire_after;
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Warning: Use local keypair, sign cert!!!");
goto modify;
}
}
if(pxy_obj->use_hsm)
{
cacrt = (is_valid == 1) ? def->root : def->insec_root;
cakey = (is_valid == 1) ? def->key : def->insec_key;
2023-03-29 17:34:26 +08:00
expire_time = g_cert_store->expire_after;
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Warning: HSM is not supported, use local keypair, sign cert!!!");
goto modify;
}
if (!STRCMP(pxy_obj->keyring_type, "end-entity"))
{
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "The certificate(%d) type is an entity",keyring_id);
*stack_ca = pxy_obj->stack_ca;
x509_get_msg_from_ca(pxy_obj->issuer, sign);
x509_get_private_key(pxy_obj->key, pkey);
goto finish;
}
if (!STRCMP(pxy_obj->keyring_type, "intermediate"))
{
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "The certificate(%d) type is intermediate", keyring_id);
}
cacrt = pxy_obj->issuer;
cakey = pxy_obj->key;
v3_ctl = pxy_obj->v3_ctl;
public_algo =pxy_obj->public_algo;
expire_time = pxy_obj->expire_time;
*stack_ca = pxy_obj->stack_ca;
modify:
x509 = ssl_x509_forge(cacrt, cakey, request->origin, pkey, &expire_time, v3_ctl, public_algo);
if (!x509){
goto finish;
}
serial = x509_get_sn(x509);
mesa_runtime_log(RLOG_LV_DEBUG, MODULE_NAME, "The certificate serial number is %s", serial);
OPENSSL_free(serial);
x509_get_msg_from_ca(x509, sign);
2018-11-30 19:24:44 +08:00
if (request->origin)
X509_free(request->origin);
X509_free(x509);
finish:
if (pxy_obj)
keyring_table_free(pxy_obj);
return expire_time;
}
static char readBytes(char *str)
{
char c = '+';
if (str && STRCMP(str, "OK") == 0)
c = '+';
if (!str)
c= '$';
return c;
}
2019-08-21 14:03:53 +08:00
static void
2023-03-29 17:34:26 +08:00
redis_sync_reget_callback(struct http_request *request, struct redisContext *sync)
2019-08-21 14:03:53 +08:00
{
struct evhttp_request *evh_req = request->evh_req;
2019-08-21 14:03:53 +08:00
redisReply *reply = (redisReply *)redisCommand(sync, "GET %s", request->rkey);
if (NULL == reply)
{
goto free;
}
switch (readBytes(reply->str))
{
case '+' :
evhttp_socket_send(evh_req, reply->str);
break;
default :
evhttp_send_error(request->evh_req, HTTP_NOTFOUND, 0);
break;
}
free:
freeReplyObject(reply);
request_destroy(request);
return;
}
static int
2023-03-29 17:34:26 +08:00
rediSyncCommand(redisContext *sync, struct http_request *request, char *odata, int expire_after)
{
int xret = -1;
redisReply *reply;
x509_forge_thread *thread = threads + request->thread_id;
struct evhttp_request *evh_req = request->evh_req;
2019-08-07 15:49:38 +08:00
reply = (redisReply *)redisCommand(thread->sync, "set %s %s ex %d nx", request->rkey, odata, expire_after);
if (NULL == reply)
goto free;
switch (readBytes(reply->str)) {
case '+' :
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "Writing data(%s) to redis successfully", request->rkey);
fp_stat_latency(request->create_time, KEYPAIR_ACTION_SIGN);
evhttp_socket_send(evh_req, request->odata);
goto free;
case '$' :
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "Writing data(%s) to redis failed", request->rkey);
fp_stat_latency(request->create_time, KEYPAIR_ACTION_SQL);
2023-03-29 17:34:26 +08:00
if (g_cert_store->mode){
2019-08-21 14:03:53 +08:00
redisAsyncCommand(thread->cl_ctx, redis_reget_callback, request, "GET %s", request->rkey);
}else{
redis_sync_reget_callback(request, sync);
}
freeReplyObject(reply);
goto finish;
default:
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "Read redis data(%s) return code failed", request->rkey);
evhttp_socket_send_error(request->evh_req, HTTP_NOTFOUND);
goto free;
}
xret = 0;
free:
freeReplyObject(reply);
2019-08-08 16:06:23 +08:00
request_destroy(request);
finish:
return xret;
}
static inline json_object *
web_json_record_array_add_string(char **chain)
{
int i;
json_object *sample_array;
sample_array = json_object_new_array();
if (sample_array == NULL)
goto finish;
for(i = 0; chain[i] != NULL; i++){
json_object_array_add(sample_array, json_object_new_string(chain[i]));
}
finish:
return sample_array;
}
static inline int
json_data_rebuild(const char *data,
size_t size,
char **odata,
size_t *osize)
{
size_t real_size = size + 1; /** 2, '\n' + '\0' */
if (!data || !size)
return -1;
*odata = (char *)malloc (real_size);
if (!*odata)
return -1;
memset (*odata, 0, real_size);
snprintf(*odata, real_size, "%s", data);
*osize = real_size;
return 0;
}
static int web_json_table_add(char *privatekey, char *sign, char **digital_certificates, char **data)
{
int i = 0;
size_t osize = 0;
const char *jstr = NULL;
struct json_object *outline = json_object_new_object();
json_object_object_add(outline, "CERTIFICATE_CHAIN", web_json_record_array_add_string(digital_certificates));
json_object_object_add(outline, "PRIVATE_KEY", json_object_new_string(privatekey));
json_object_object_add(outline, "CERTIFICATE", json_object_new_string(sign));
jstr = json_object_to_json_string (outline);
json_data_rebuild(jstr, strlen(jstr), data, &osize);
json_object_put(outline);
kfree(sign);
for (i = 0; i < 6; i ++){
if (digital_certificates[i] != NULL)
kfree(digital_certificates[i]);
}
return 0;
}
static int
2023-03-29 17:34:26 +08:00
redis_clnt_pdu_send(struct http_request *request)
{
#define MAX_CHAIN_LEN 6
int xret = -1, i = 0;
STACK_OF(X509) *stack_ca = NULL;
x509_forge_thread *thread = threads + request->thread_id;
char *sign = NULL, pkey[SG_DATA_SIZE] = {0};
uint64_t expire_time = x509_online_append(&thread->def, request, &sign, pkey, &stack_ca);
if (sign == NULL || pkey[0] == '\0')
{
if (request->origin)
X509_free(request->origin);
request_destroy(request);
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to sign certificate");
evhttp_socket_send_error(request->evh_req, HTTP_NOTFOUND);
return xret;
}
char *certificate = NULL; char *digital_certificates[MAX_CHAIN_LEN] = {0};
if (stack_ca)
{
for (i = 0; i < sk_X509_num(stack_ca); i++)
{
x509_get_msg_from_ca(sk_X509_value(stack_ca, i), &certificate);
digital_certificates[i] = certificate;
}
}
web_json_table_add(pkey, sign, digital_certificates, &request->odata);
if (thread->sync == NULL)
{
struct evhttp_request *evh_req = request->evh_req;
fp_stat_latency(request->create_time, KEYPAIR_ACTION_SIGN);
evhttp_socket_send(evh_req, request->odata);
2019-08-08 16:06:23 +08:00
request_destroy(request);
xret = 0;
goto finish;
}
xret = rediSyncCommand(thread->sync, request, request->odata, expire_time);
if (xret < 0)
{
goto finish;
}
xret = 0;
finish:
return xret;
}
2023-03-29 17:34:26 +08:00
static int redis_clnt_send(struct http_request *request, redisReply *reply)
{
int xret = -1;
if (!reply && !reply->str){
evhttp_socket_send_error(request->evh_req, HTTP_NOTFOUND);
goto finish;
}
fp_stat_latency(request->create_time, KEYPAIR_ACTION_SQL);
evhttp_socket_send(request->evh_req, reply->str);
finish:
2018-11-30 19:24:44 +08:00
if (request->origin)
X509_free(request->origin);
2019-08-08 16:06:23 +08:00
request_destroy(request);
return xret;
}
2019-08-21 14:03:53 +08:00
void redis_get_callback(redisAsyncContext __attribute__((__unused__))*c, void *r, void *privdata)
{
int __attribute__((__unused__))xret = -1;
redisReply *reply = (redisReply*)r;
2023-03-29 17:34:26 +08:00
struct http_request *request = (struct http_request *)privdata;
switch(reply->type){
case REDIS_REPLY_STRING:
mesa_runtime_log(RLOG_LV_DEBUG, MODULE_NAME, "Sends the certificate information to the requestor");
xret = redis_clnt_send(request, reply);
break;
case REDIS_REPLY_NIL:
mesa_runtime_log(RLOG_LV_DEBUG, MODULE_NAME, "Generating certificate information");
2019-08-21 14:03:53 +08:00
xret = redis_clnt_pdu_send(request);
break;
default:
break;
}
return;
}
int x509_key_pair_init(char *ca_file, EVP_PKEY **key, X509 **root)
{
int xret = -1;
FILE *fp; RSA *rsa = NULL;
*key = EVP_PKEY_new();
if (NULL == *key){
goto finish;
}
rsa = RSA_new();
if (NULL == rsa){
goto pkey_free;
}
fp = fopen(ca_file, "r");
if (NULL == fp){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to open file(%s)", ca_file);
RSA_free(rsa);
goto pkey_free;
}
if ( !PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL) || !EVP_PKEY_assign_RSA(*key,rsa))
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Private key read failed");
goto pkey_free;
}
fclose(fp);
BIO *in;
in = BIO_new_file(ca_file, "r");
if (!in){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to open file(%s)", ca_file);
goto pkey_free;
}
if ((*root = PEM_read_bio_X509(in, NULL, 0, NULL)) == NULL )
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Application for x509 failed");
goto pkey_free;
}
BIO_free(in);
xret = 0;
goto finish;
pkey_free:
EVP_PKEY_free(*key);
finish:
return xret;
}
int hex2dec(char c)
{
if ('0' <= c && c <= '9') {
return c - '0';
} else if ('a' <= c && c <= 'f') {
return c - 'a' + 10;
} else if ('A' <= c && c <= 'F') {
return c - 'A' + 10;
} else {
return -1;
}
}
void _urldecode(char url[])
{
int i = 0;
int len = strlen(url);
int res_len = 0;
char *res = NULL;
res = (char *)malloc(len + 1);
if (!res){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Url alloc faild");
return;
}
if(!strchr(url, '%'))
return;
for (i = 0; i < len; ++i) {
char c = url[i];
if (c != '%') {
res[res_len++] = c;
} else {
char c1 = url[++i];
char c0 = url[++i];
int num = 0;
num = hex2dec(c1) * 16 + hex2dec(c0);
res[res_len++] = num;
}
}
res[res_len] = '\0';
strcpy(url, res);
free(res);
}
2023-03-29 17:34:26 +08:00
static int http_decode_uri(struct evhttp_request *evh_req, struct http_request *request)
{
int rv = 0;
struct evkeyvalq params;
2019-08-08 16:06:23 +08:00
const char *uri = evhttp_request_get_uri(evh_req);
rv = evhttp_parse_query(uri, &params);
if (rv != 0)
{
return -1;
2019-08-08 16:06:23 +08:00
}
const char *health_check = evhttp_find_header(&params, "health_check");
if (health_check)
{
evhttp_clear_headers(&params);
return -2;
}
2019-08-08 16:06:23 +08:00
const char *keyring_id = evhttp_find_header(&params, "keyring_id");
if (keyring_id)
{
request->keyring_id = atoi(keyring_id);
}
2019-08-08 16:06:23 +08:00
const char *is_valid = evhttp_find_header(&params, "is_valid");
if (is_valid)
{
request->is_valid = atoi(is_valid);
}
const char *sni = evhttp_find_header(&params, "sni");
if (sni)
{
request->sni = strdup(sni);
}
evhttp_clear_headers(&params);
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "[Thread %d]Received request for uri, kering_id:%d, sni:%s, valid:%d",
request->thread_id, request->keyring_id, request->sni, request->is_valid);
2019-08-08 16:06:23 +08:00
return 0;
}
static void
evhttp_socket_close_cb(struct evhttp_connection *evcon,
void __attribute__((__unused__))*arg)
{
if (NULL == evcon){
goto finish;
}
2018-11-30 19:24:44 +08:00
finish:
return;
}
static int
x509_get_rkey(X509 *origin, int keyring_id, char *rkey, int is_valid)
{
unsigned int len = 0, i = 0;
char hex[EVP_MAX_MD_SIZE] = {0};
unsigned char fdig[EVP_MAX_MD_SIZE] = {0};
X509_digest(origin, EVP_sha1(), fdig, &len);
for (i = 0; i < len ; ++i){
sprintf(hex + i * sizeof(unsigned char) * 2, "%02x", fdig[i]);
}
/** keyrind_id is 0, sign x509 by default */
/** 0 uninsec, 1 insec*/
if (is_valid == 1 && keyring_id == 0) keyring_id = 1;
if (is_valid == 0 && keyring_id != 0) keyring_id = 0;
struct pxy_obj_keyring *pxy_obj = get_obj_for_id(keyring_id);
if (pxy_obj != NULL)
{
snprintf(rkey, DATALEN, "%d:%lu:%s:%d", keyring_id, pxy_obj->op_time, hex, is_valid);
goto finish;
}
snprintf(rkey, DATALEN, "%d:%s:%d", keyring_id, hex, is_valid);
finish:
if (pxy_obj)
keyring_table_free(pxy_obj);
return 0;
}
2019-08-21 14:03:53 +08:00
static int
2023-03-29 17:34:26 +08:00
redis_sync_command(struct http_request *request, struct redisContext __attribute__((__unused__))*c)
{
2019-08-21 14:03:53 +08:00
int xret = -1;
redisReply *reply;
x509_forge_thread *thread_ctx = threads + request->thread_id;
2019-08-21 14:03:53 +08:00
reply = (redisReply *)redisCommand(thread_ctx->sync, "GET %s", request->rkey);
if (NULL == reply)
goto free;
switch (readBytes(reply->str)) {
case '+' :
mesa_runtime_log(RLOG_LV_DEBUG, MODULE_NAME, "Sends the certificate information to the requestor");
xret = redis_clnt_send(request, reply);
break;
case '$' :
mesa_runtime_log(RLOG_LV_DEBUG, MODULE_NAME, "Generating certificate information");
xret = redis_clnt_pdu_send(request);
goto finish;
default :
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "Read redis data(%s) return code failed", request->rkey);
evhttp_send_error(request->evh_req, HTTP_NOTFOUND, 0);
goto free;
}
xret = 0;
free:
freeReplyObject(reply);
finish:
return xret;
}
2023-03-29 17:34:26 +08:00
static int get_x509_msg(struct http_request *request, char *input, ssize_t inputlen)
{
2019-08-08 16:06:23 +08:00
request->origin = x509_get_ca_from_msg(input, inputlen + 1);
if (request->origin == NULL){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "The certificate is invalid.");
request_destroy(request);
return -1;
}
x509_get_rkey(request->origin, request->keyring_id, request->rkey, request->is_valid);
if (request->rkey[0] == '\0'){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Get the redis key from the certificate failed");
return -1;
}
mesa_runtime_log(RLOG_LV_DEBUG, MODULE_NAME, "Redis key is %s", request->rkey);
2019-08-08 16:06:23 +08:00
return 0;
}
2023-03-29 17:34:26 +08:00
static int get_keypair_cache(x509_forge_thread *info, struct http_request *request, int mode)
{
int xret = 0;
if (info->sync == NULL)
{
2019-08-21 14:03:53 +08:00
xret = redis_clnt_pdu_send(request);
if (xret < 0)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Local sign certificate failed");
}
}else{
if(mode)
2019-08-21 14:03:53 +08:00
{
xret = redisAsyncCommand(info->cl_ctx, redis_get_callback, request, "GET %s", request->rkey);
if (xret < 0)
{
2019-08-21 14:03:53 +08:00
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to get information from redis server");
}
}
else
{
2019-08-21 14:03:53 +08:00
xret = redis_sync_command(request, info->sync);
if (xret < 0)
{
2019-08-21 14:03:53 +08:00
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to get information from redis server");
}
2019-08-21 14:03:53 +08:00
}
}
return xret;
}
void http_get_cb(struct evhttp_request *evh_req, void *arg)
{
int xret = -1;
2023-03-29 17:34:26 +08:00
struct http_request *request = NULL;
struct evbuffer * evbuf_body = NULL;
char *input = NULL; ssize_t inputlen=0;
x509_forge_thread *info = (x509_forge_thread *)arg;
if (evhttp_request_get_command(evh_req) != EVHTTP_REQ_POST) {
mesa_runtime_log(RLOG_LV_DEBUG, MODULE_NAME, "FAILED (post type)");
goto error;
}
2023-03-29 17:34:26 +08:00
request = (struct http_request *) kmalloc (sizeof(struct http_request), MPF_CLR, -1);
request->keyring_id = 0;
request->thread_id = info->id;
request->evh_req = evh_req;
clock_gettime(CLOCK_MONOTONIC,&request->create_time);
xret = http_decode_uri(evh_req, request);
if (xret != 0)
{
if (xret == -2)
{
request_destroy(request);
evhttp_send_reply(evh_req, 200, "OK", NULL);
goto finish;
}
else
{
goto error;
}
}
evhttp_connection_set_closecb(evhttp_request_get_connection(evh_req), evhttp_socket_close_cb, NULL);
evbuf_body = evhttp_request_get_input_buffer(evh_req);
if (!evbuf_body || 0==(inputlen = evbuffer_get_length(evbuf_body))
||!(input = (char *)evbuffer_pullup(evbuf_body,inputlen)))
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to get certificate information.");
goto error;
}
xret = get_x509_msg(request, input, inputlen);
if (xret != 0)
{
goto error;
}
FS_operate(g_FP_instance.handle, g_FP_instance.line_ids[KEYPAIR_ACTION_REQ], 0, FS_OP_ADD, 1);
2023-03-29 17:34:26 +08:00
xret = get_keypair_cache(info, request, g_cert_store->mode);
if (xret >= 0)
{
goto finish;
}
error:
evhttp_socket_send_error(evh_req, HTTP_BADREQUEST);
finish:
return;
}
2023-03-29 17:34:26 +08:00
int redis_sync_connect(struct redisContext **c)
{
2023-03-29 17:34:26 +08:00
struct timeval timeout = { 1, 500000 }; // 1.5 seconds
*c = redisConnectWithTimeout(g_cert_store->local_redis_ip, g_cert_store->local_redis_port, timeout);
if (*c == NULL || (*c)->err)
{
if (*c) {
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Sync connection error: %s", (*c)->errstr);
redisFree(*c);
*c = NULL;
} else {
2023-03-29 17:34:26 +08:00
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Connection error: can't allocate g_cert_store context");
}
2023-03-29 17:34:26 +08:00
return -1;;
}
2023-03-29 17:34:26 +08:00
return 0;
}
2023-03-29 17:34:26 +08:00
int local_redis_connect(struct event_base *base, x509_forge_thread *thread)
{
2023-03-29 17:34:26 +08:00
int ret = -1;
ret = redis_sync_connect(&thread->sync);
if (ret < 0 || !thread->sync)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Initialize the sync redis connection is failure");
}
2023-03-29 17:34:26 +08:00
if(g_cert_store->mode==0)
{
2023-03-29 17:34:26 +08:00
return ret;
2019-08-21 14:03:53 +08:00
}
2023-03-29 17:34:26 +08:00
ret = redis_async_connect(base, &thread->cl_ctx);
if (ret < 0 || !thread->cl_ctx)
{
2023-03-29 17:34:26 +08:00
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Initialize the redis connection is failure");
}
return ret;
}
2023-03-29 17:34:26 +08:00
int load_default_ca(x509_forge_thread *thread)
{
int ret=0;
2023-03-29 17:34:26 +08:00
if(g_cert_store->local_debug == 0)
{
return 0;
}
ret = x509_key_pair_init(g_cert_store->ca_path, &thread->def.key, &thread->def.root);
if (ret < 0 || !(thread->def.key) || !(thread->def.root))
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to initialize the x509 certificate");
goto finish;
}
ret = x509_key_pair_init(g_cert_store->uninsec_path, &thread->def.insec_key, &thread->def.insec_root);
if (ret < 0 || !(thread->def.key) || !(thread->def.root))
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to initialize the insec x509 certificate");
goto finish;
}
finish:
2023-03-29 17:34:26 +08:00
return ret;
}
2023-03-29 17:34:26 +08:00
static void *keyring_work_thread_run(void *arg)
{
int xret = -1;
struct evhttp_bound_socket *bound = NULL;
x509_forge_thread *thread_ctx = (x509_forge_thread *)arg;
struct event_base *base = event_base_new();
if (! base) {
2019-08-08 16:06:23 +08:00
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Can'thread_ctx allocate event base");
return NULL;
}
struct evhttp *http = evhttp_new(base);
if (!http) {
2019-08-08 16:06:23 +08:00
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "couldn'thread_ctx create evhttp. Exiting.");
goto error;
}
2019-08-08 16:06:23 +08:00
thread_ctx->base = base;
2023-03-29 17:34:26 +08:00
local_redis_connect(base, thread_ctx);
2023-03-29 17:34:26 +08:00
xret = load_default_ca(thread_ctx);
if (xret < 0)
{
goto error;
}
2019-08-08 16:06:23 +08:00
evhttp_set_cb(http, "/ca", http_get_cb, thread_ctx);
2019-08-08 16:06:23 +08:00
bound = evhttp_accept_socket_with_handle(http, thread_ctx->accept_fd);
if (bound != NULL) {
2023-03-29 17:34:26 +08:00
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "Bound(%p) to port %d - Awaiting connections ... ", bound, g_cert_store->listen_port);
}
2019-08-21 14:03:53 +08:00
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "Work thread %u is run...", thread_ctx->id);
event_base_dispatch(base);
error:
event_base_free(base);
return NULL;
}
#ifdef SOCK_NONBLOCK
#define EVUTIL_SOCK_NONBLOCK SOCK_NONBLOCK
#else
#define EVUTIL_SOCK_NONBLOCK 0x4000000
#endif
#ifdef SOCK_CLOEXEC
#define EVUTIL_SOCK_CLOEXEC SOCK_CLOEXEC
#else
#define EVUTIL_SOCK_CLOEXEC 0x80000000
#endif
#ifdef EFD_NONBLOCK
#define EVUTIL_EFD_NONBLOCK EFD_NONBLOCK
#else
#define EVUTIL_EFD_NONBLOCK 0x4000
#endif
#ifdef EFD_CLOEXEC
#define EVUTIL_EFD_CLOEXEC EFD_CLOEXEC
#else
#define EVUTIL_EFD_CLOEXEC 0x8000
#endif
static int
evutil_fast_socket_nonblocking(evutil_socket_t fd)
{
#ifdef _WIN32
return evutil_make_socket_nonblocking(fd);
#else
if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
return -1;
}
return 0;
#endif
}
static int
evutil_fast_socket_closeonexec(evutil_socket_t fd)
{
#if !defined(_WIN32) && defined(EVENT__HAVE_SETFD)
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
return -1;
}
#endif
return 0;
}
evutil_socket_t
evutil_socket_(int domain, int type, int protocol)
{
evutil_socket_t r;
#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
r = socket(domain, type, protocol);
if (r >= 0)
return r;
else if ((type & (SOCK_NONBLOCK|SOCK_CLOEXEC)) == 0)
return -1;
#endif
#define SOCKET_TYPE_MASK (~(EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC))
r = socket(domain, type & SOCKET_TYPE_MASK, protocol);
if (r < 0)
return -1;
if (type & EVUTIL_SOCK_NONBLOCK) {
if (evutil_fast_socket_nonblocking(r) < 0) {
evutil_closesocket(r);
return -1;
}
}
if (type & EVUTIL_SOCK_CLOEXEC) {
if (evutil_fast_socket_closeonexec(r) < 0) {
evutil_closesocket(r);
return -1;
}
}
return r;
}
static evutil_socket_t
evhttp_listen_socket_byuser(const struct sockaddr *sa, int socklen,
unsigned flags, int backlog)
{
evutil_socket_t fd;
int on = 1;
int family = sa ? sa->sa_family : AF_UNSPEC;
int socktype = SOCK_STREAM | EVUTIL_SOCK_NONBLOCK;
if (flags & LEV_OPT_CLOSE_ON_EXEC)
socktype |= EVUTIL_SOCK_CLOEXEC;
fd = evutil_socket_(family, socktype, 0);
if (fd == -1)
return fd;
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on))<0)
goto err;
if (flags & LEV_OPT_REUSEABLE) {
if (evutil_make_listen_socket_reuseable(fd) < 0)
goto err;
}
if (flags & LEV_OPT_REUSEABLE_PORT) {
if (evutil_make_listen_socket_reuseable_port(fd) < 0){
goto err;
}
}
if (sa) {
if (bind(fd, sa, socklen)<0)
goto err;
}
if (listen(fd, backlog) == -1) {
goto err;
}
return fd;
err:
evutil_closesocket(fd);
return fd;
}
2023-03-29 17:34:26 +08:00
void redis_link_detection(uint32_t uid, int argc, char **argv)
{
int tid = 0, xret = 0;
x509_forge_thread *info = NULL;
x509_forge_thread *threads = (x509_forge_thread *)argv;
2023-03-29 17:34:26 +08:00
unsigned int thread_nu = g_cert_store->thread_nu;
for (tid = 0; tid < (int)thread_nu; tid++)
{
info = threads + tid;
if(info->sync == NULL && info->base != NULL)
{
2019-08-21 14:03:53 +08:00
redisFree(info->sync);
2023-03-29 17:34:26 +08:00
xret = redis_sync_connect(&info->sync);
if (xret < 0 || !info->sync)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "[%d]trying to connect sync redis failed", tid);
continue;
}
else
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "[%d]trying to connect sync redis success", tid);
}
2023-03-29 17:34:26 +08:00
if(g_cert_store->mode == 0)
{
continue;
}
xret = redis_async_connect(info->base, &info->cl_ctx);
if (xret < 0 || !info->cl_ctx)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "[%d]trying to connect rsync redis failed", tid);
}
else
2019-08-21 14:03:53 +08:00
{
2023-03-29 17:34:26 +08:00
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "[%d]trying to connect rsync redis success", tid);
2019-08-21 14:03:53 +08:00
}
}
}
}
2023-03-29 17:34:26 +08:00
static int keyring_server_init(const char *main_profile)
{
2023-03-29 17:34:26 +08:00
int xret=-1;
unsigned int tid = 0;
x509_forge_thread *thread = NULL;
uint32_t tm_link_detetion = 0;
2023-03-29 17:34:26 +08:00
unsigned int thread_nu = g_cert_store->thread_nu;
/* Create a new evhttp object to handle requests. */
struct sockaddr_in sin;
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
2023-03-29 17:34:26 +08:00
sin.sin_port = htons(g_cert_store->listen_port);
evutil_socket_t accept_fd = evhttp_listen_socket_byuser((struct sockaddr*)&sin, sizeof(struct sockaddr_in), LEV_OPT_REUSEABLE_PORT|LEV_OPT_CLOSE_ON_FREE, -1);
if (accept_fd < 0)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Could not create a listen!");
goto finish;
}
threads = (x509_forge_thread *)calloc(thread_nu, sizeof(x509_forge_thread));
if (! threads)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Can't allocate thread descriptors");
goto finish;
}
memset(threads, 0, thread_nu * sizeof(x509_forge_thread));
/* Create threads after we've done all the libevent setup. */
for (tid = 0; tid < thread_nu; tid++)
{
thread = threads + tid;
thread->id = tid;
thread->accept_fd = accept_fd;
2023-03-29 17:34:26 +08:00
thread->routine = keyring_work_thread_run;
if (pthread_create(&thread->pid, thread->attr, thread->routine, &threads[tid])){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "%s", strerror(errno));
goto finish;
}
if (pthread_detach(thread->pid)){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "%s", strerror(errno));
goto finish;
}
}
#ifdef RT_TMR_ADVANCED
/*Create timers to monitor redis connections **/
tm_link_detetion = tmr_create(1, "Redis link detection",
redis_link_detection, 1, (char **)threads, 5);
if (((int32_t)tm_link_detetion < 0)){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "%s",
"Can not create link-detection timer for redis\n");
}
tmr_start(tm_link_detetion);
#endif
FOREVER{
sleep(1);
}
finish:
return xret;
}
static void
rt_get_pname_by_pid(pid_t pid, char *task_name)
{
#define BUF_SIZE 1024
char proc_pid_path[BUF_SIZE];
char buf[BUF_SIZE];
sprintf(proc_pid_path, "/proc/%d/status", pid);
FILE* fp = fopen(proc_pid_path, "r");
if(NULL != fp){
if( fgets(buf, BUF_SIZE-1, fp)== NULL ){
fclose(fp);
}
fclose(fp);
sscanf(buf, "%*s %s", task_name);
}
}
void sigproc(int __attribute__((__unused__))sig)
{
2023-03-29 17:34:26 +08:00
int tid = 0;
x509_forge_thread *thread = NULL;
2023-03-29 17:34:26 +08:00
for (tid = 0; tid < g_cert_store->thread_nu; tid++)
2020-11-12 15:42:28 +08:00
{
thread = threads + tid;
2020-11-12 15:42:28 +08:00
if (thread->sync)
{
redisAsyncDisconnect(thread->cl_ctx);
redisFree(thread->sync);
}
event_base_free(thread->base);
}
kfree(threads);
2023-03-29 17:34:26 +08:00
if(g_cert_store->instance)
{
maat_free(g_cert_store->instance);
}
kfree(g_cert_store);
exit(1);
}
2023-03-29 17:34:26 +08:00
static int kerying_fs_stat_init(const char *main_profile)
{
2020-11-14 13:22:26 +08:00
int value=0, i=0, prometheus_port =0;
char stat_path[128] ={0}, pname[32]={0};
2020-11-14 13:22:26 +08:00
char prometheus_url_path[1024] = {0};
2023-03-29 17:34:26 +08:00
char statsd_server[32]; int statsd_port;
2023-03-29 17:34:26 +08:00
MESA_load_profile_int_def(main_profile, "stat", "statsd_port", &(statsd_port), 8126);
MESA_load_profile_string_def(main_profile, "stat", "statsd_server", statsd_server, sizeof(statsd_server), "");
MESA_load_profile_int_def(main_profile, "stat", "statsd_set_prometheus_port", &(prometheus_port), 9001);
MESA_load_profile_string_def(main_profile, "stat", "statsd_set_prometheus_url_path", prometheus_url_path, sizeof(prometheus_url_path), "/certstore_prometheus");
g_FP_instance.favorite=FS_CALC_CURRENT;
strcpy(g_FP_instance.histogram_bins, FP_HISTOGRAM_BINS);
2020-11-14 13:22:26 +08:00
FS_library_set_prometheus_port(prometheus_port);
FS_library_set_prometheus_url_path(prometheus_url_path);
FS_library_init();
screen_stat_handle_t fs=NULL;
fs=FS_create_handle();
rt_get_pname_by_pid(getpid(), &pname[0]);
FS_set_para(fs, APP_NAME, pname, strlen(pname)+1);
2020-11-14 13:22:26 +08:00
value=1;
FS_set_para(fs, OUTPUT_PROMETHEUS, &value, sizeof(value));
value=0;
FS_set_para(fs, FLUSH_BY_DATE, &value, sizeof(value));
2020-09-27 18:38:49 +08:00
snprintf(stat_path, 128, "%s/fs2_%s.status", "./logs", pname);
FS_set_para(fs, OUTPUT_DEVICE, stat_path, strlen(stat_path)+1);
value=1;
FS_set_para(fs, PRINT_MODE, &value, sizeof(value));
value=1;
FS_set_para(fs, CREATE_THREAD, &value, sizeof(value));
value=2;
FS_set_para(fs, STAT_CYCLE, &value, sizeof(value));
2023-03-29 17:34:26 +08:00
if(strlen(statsd_server)>0 && statsd_port!=0)
{
2023-03-29 17:34:26 +08:00
FS_set_para(fs, STATS_SERVER_IP, statsd_server, strlen(statsd_server)+1);
FS_set_para(fs, STATS_SERVER_PORT, &(statsd_port), sizeof(statsd_port));
}
FS_set_para(fs, HISTOGRAM_GLOBAL_BINS, g_FP_instance.histogram_bins, strlen(g_FP_instance.histogram_bins)+1);
const char* __str_stat_spec_map[KEYPAIR_ACTION_MAX]={0};
__str_stat_spec_map[KEYPAIR_ACTION_REQ]="ask_kyr_req";
__str_stat_spec_map[KEYPAIR_ACTION_SQL]="rd_cache";
__str_stat_spec_map[KEYPAIR_ACTION_SIGN]="x509_sign";
__str_stat_spec_map[KEYPAIR_ACTION_ERR]="ask_kyr_fail";
for (i = 0; i < KEYPAIR_ACTION_MAX; i++)
{
g_FP_instance.line_ids[i] = FS_register(fs, FS_STYLE_FIELD, FS_CALC_CURRENT, __str_stat_spec_map[i]);
}
FS_start(fs);
g_FP_instance.handle = fs;
for (i = 0; i <= KEYPAIR_ACTION_SIGN; i++)
{
int size = strlen(__str_stat_spec_map[i]) + strlen("(us)");
char buff[size+1];
snprintf(buff,sizeof(buff),"%s(us)",(char*)__str_stat_spec_map[i]);
g_FP_instance.field_id[i]=FS_register_histogram(g_FP_instance.handle, g_FP_instance.favorite, buff,
1, 30*1000,3);
}
return 0;
}
2023-03-29 17:34:26 +08:00
void keyring_table_new_cb(int table_id, const char *key, const char* table_line, void **ad, long argl, void * argp)
{
char profile_name[CT_ARRARY_LEN]={0};
char private_file[CT_STRING_MAX] = {0}, public_file[CT_STRING_MAX]={0};
char __attribute__((__unused__))_priv_file[CT_PATH_MAX] = {0};
char __attribute__((__unused__))_publi_file[CT_PATH_MAX] = {0};
int ret=0;
struct pxy_obj_keyring *pxy_obj = NULL;
pxy_obj = (struct pxy_obj_keyring *)malloc(sizeof(struct pxy_obj_keyring));
if (!pxy_obj)
{
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "Can not alloc, %s", strerror(errno));
goto finish;
}
memset(pxy_obj, 0, sizeof(struct pxy_obj_keyring));
atomic64_set(&pxy_obj->ref_cnt, 1);
ret=sscanf(table_line, "%d\t%s\t%s\t%s\t%s\t%lu\t%s\t%s\t%d\t%d\t%d\t%d", &pxy_obj->keyring_id, profile_name,
pxy_obj->keyring_type, private_file, public_file, &pxy_obj->expire_time, pxy_obj->public_algo,
pxy_obj->v3_ctl, &pxy_obj->is_send, &pxy_obj->use_hsm, &pxy_obj->slot_id, &pxy_obj->is_valid);
if(ret!=12)
{
kfree(pxy_obj);
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "certstore parse config failed: %s", table_line);
goto finish;
}
pxy_obj->op_time = time(NULL);
/*Load PUBLICKEY***/
if ((pxy_obj->issuer = x509_get_root_ca(public_file, pxy_obj->is_send, pxy_obj->keyring_type, &pxy_obj->stack_ca)) == NULL ){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "initialize the x509 publickey failed, the keyring id is %d",
pxy_obj->keyring_id);
goto finish;
}
if(pxy_obj->use_hsm == 0)
{
/*Load PRIVATEKEY**/
if ((pxy_obj->key = cert_load_key(private_file)) == NULL){
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "initialize the x509 privatekey failed, the keyring id is %d",
pxy_obj->keyring_id);
goto finish;
}
}
mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "initialize the x509 certificate, the keyring id is %d",
pxy_obj->keyring_id);
*ad = pxy_obj;
finish:
return;
}
2023-03-29 17:34:26 +08:00
void keyring_table_dup_cb(int table_id, void **to, void **from, long argl, void *argp)
{
struct pxy_obj_keyring* pxy_obj=(struct pxy_obj_keyring*)(*from);
if(pxy_obj==NULL)
{
*to=NULL;
return;
}
atomic64_inc (&pxy_obj->ref_cnt);
*((struct pxy_obj_keyring**)to)=pxy_obj;
}
2023-03-29 17:34:26 +08:00
#define MAAT_INPUT_JSON 1
#define MAAT_INPUT_REDIS 2
#define MAAT_INPUT_FILE 0
struct maat *create_maat_feather(const char * main_profile)
{
struct maat *target=NULL;
int input_mode = 0;
int ret = 0, effect_interval = 60;
int redis_db_idx = 0, deferred_load_on = 0;
char table_info[128]={0}, inc_cfg_dir[128]={0}, ful_cfg_dir[128]={0};
char json_cfg_file[128] = {0};
char redis_server[128]={0},redis_port_range[128]={0};
int redis_port_begin=0, redis_port_end=0;
int redis_port_select=0;
MESA_load_profile_int_def(main_profile, "MAAT", "maat_json_switch", &(input_mode), 0);
MESA_load_profile_string_def(main_profile, "MAAT", "table_info", table_info, sizeof(table_info), "");
MESA_load_profile_int_def(main_profile, "MAAT", "effective_interval", &(effect_interval), 60);
MESA_load_profile_string_def(main_profile, "MAAT", "pxy_obj_keyring", json_cfg_file, sizeof(json_cfg_file), "");
MESA_load_profile_string_def(main_profile, "MAAT", "inc_cfg_dir", inc_cfg_dir, sizeof(inc_cfg_dir), "");
MESA_load_profile_string_def(main_profile, "MAAT", "full_cfg_dir", ful_cfg_dir, sizeof(ful_cfg_dir), "");
MESA_load_profile_int_def(main_profile, "MAAT", "deferred_load_on", &(deferred_load_on), 0);
MESA_load_profile_string_def(main_profile, "MAAT_REDIS", "ip", redis_server, sizeof(redis_server), "");
MESA_load_profile_string_def(main_profile, "MAAT_REDIS", "port", redis_port_range, sizeof(redis_server), "6379");
MESA_load_profile_int_def(main_profile, "MAAT_REDIS", "dbindex", &(redis_db_idx), 0);
ret=sscanf(redis_port_range,"%d-%d", &redis_port_begin, &redis_port_end);
if(ret==1)
{
2023-03-29 17:34:26 +08:00
redis_port_select=redis_port_begin;
}
else if(ret==2)
{
srand(time(NULL));
redis_port_select=redis_port_begin+rand()%(redis_port_end-redis_port_begin);
}
else
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Invalid redis port range %s, MAAT init failed.", redis_port_range);
}
2023-03-29 17:34:26 +08:00
effect_interval *= 1000;//convert s to ms
assert(strlen(inc_cfg_dir) != 0 || strlen(ful_cfg_dir) != 0 || strlen(redis_server)!=0 || strlen(json_cfg_file)!=0);
2023-03-29 17:34:26 +08:00
struct maat_options *opts = maat_options_new();
maat_options_set_instance_name(opts, "certstore");
maat_options_set_caller_thread_number(opts, g_cert_store->thread_nu);
maat_options_set_logger(opts, "logs/maat.log", LOG_LEVEL_TRACE);
switch (input_mode)
{
case MAAT_INPUT_FILE:
maat_options_set_iris(opts, ful_cfg_dir, inc_cfg_dir);
break;
case MAAT_INPUT_JSON:
maat_options_set_json_file(opts, json_cfg_file);
break;
case MAAT_INPUT_REDIS:
maat_options_set_redis(opts, redis_server, redis_port_select, redis_db_idx);
break;
default: mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Invalid MAAT Input Mode: %d.", input_mode);
goto error_out;
break;
}
2023-03-29 17:34:26 +08:00
if (deferred_load_on)
{
maat_options_set_deferred_load_on(opts);
}
maat_options_set_rule_effect_interval_ms(opts, effect_interval);
maat_options_set_foreign_cont_dir(opts, "./foreign_files/");
2023-03-29 17:34:26 +08:00
target = maat_new(opts, table_info);
if (!target)
{
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "%s MAAT init failed.", __FUNCTION__);
goto error_out;
}
maat_options_free(opts);
return target;
2023-03-29 17:34:26 +08:00
error_out:
maat_options_free(opts);
return NULL;
}
2023-03-29 17:34:26 +08:00
int kerying_profile_init(const char * main_profile)
{
int table_id=0;
2023-03-29 17:34:26 +08:00
g_cert_store->instance = create_maat_feather(main_profile);
if(!g_cert_store->instance)
{
2023-03-29 17:34:26 +08:00
goto finish;
}
2023-03-29 17:34:26 +08:00
g_cert_store->table_id=maat_get_table_id(g_cert_store->instance, "PXY_PROFILE_KEYRING");
if(g_cert_store->table_id<0)
{
goto finish;
}
table_id=maat_plugin_table_ex_schema_register(g_cert_store->instance, g_cert_store->table_id, keyring_table_new_cb,keyring_table_free_cb,
keyring_table_dup_cb, 0, NULL);
if(table_id<0)
{
goto finish;
}
return 0;
finish:
mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "certstore register table PXY_PROFILE_KEYRING failed");
exit(1);
return -1;
}
2020-11-14 13:22:26 +08:00
int cert_store_session_init(const char *main_profile)
{
2023-03-29 17:34:26 +08:00
kerying_fs_stat_init(main_profile);
2023-03-29 17:34:26 +08:00
kerying_profile_init(main_profile);
2023-03-29 17:34:26 +08:00
keyring_server_init(main_profile);
return 0;
}