前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >lua调用c语言so动态库--以waf中证书检查为例

lua调用c语言so动态库--以waf中证书检查为例

原创
作者头像
stan1ey
修改2021-09-06 11:06:55
1.7K0
修改2021-09-06 11:06:55
举报
文章被收录于专栏:安全开发记录安全开发记录

需求

在基于nginx做waf开发时,nginx+lua+c动态库是常见的开发模式,在lua生态无法满足需求时,就需要我们在lua代码中调用动态库的方式,进行扩展,下面以lua调用c语言+openssl动态库的方式,进行判断证书的创建时间和证书的过期时间为例,进行说明

由于lua没有openss sdk做证书检查校验工作,那么就需要我们基于c语言和openssl库些一个so动态库,以供lua调用去判断证书有效时间、合法性、证书签发者信息等。

c函数从lua获取参数

与lua交互的c函数,所有函数入参参数固定为lua_State *L。

在lua调用c函数时,通过lua_State *L向其传入参数,如果只有一个参数且类型为string,那么在c函数中通过lua_tostring(L,1),获取传来的一个string类型的参数。

若lua向c函数传参时,有两个参数,第一个参数为string类型,第二个参数为number类型。那么在c函数中,需要通过lua_tostring(L,1)和lua_tonumber(L,2),分别获取lua传来的两个参数(即:string类型和number类型)。

代码说明

例如在如下代码中,expire_cert_time函数为获取证书过期时间,create_cert_time函数为获取证书创建时间,函数的参数为证书的路径(即:string类型),那么就可以通过path = lua_tostring(L,1),获取lua传来的证书路径,随后在c语言的函数中调用openssl函数进行一些列的操作。

向lua返回结果

在c函数中处理函数的结尾,通过lua_pushstring(L, buf)向lua返回处理结果,在该例中函数的返回值分别为,证书的创建时间、证书的过期时间,均是字符串类型,所以通过lua_pushstring把返回值push到lua_State L中,如果返回的是数字可以通过lua_pushnumber来实现。

c文件名:libcert.c

代码语言:javascript
复制
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include<sys/time.h>

#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/rsa.h>

#include "tools.h"

static int expire_cert_time(lua_State *L)
{
    const char *path = NULL;
    path = lua_tostring(L,1);

    int reason_code;
    BIO *in;
    int ret = 0;
    X509 *x = NULL;

    in = BIO_new(BIO_s_file());
    if (in == NULL) {

    }

    if (BIO_read_filename(in, path) <= 0) {

    }
    x = PEM_read_bio_X509(in, NULL, NULL, NULL);

    long version;
    X509_NAME *issuer = NULL;
    int entriesNum;
    int i;
    ASN1_TIME *time;

    //获取证书版本  
    version = X509_get_version(x);
    //printf("X509 Version: %ld\n", version);

    //获取证书颁发者信息,X509_NAME结构体保存了多项信息,包括国家、组织、部门、通用名、mail等。  
    issuer = X509_get_issuer_name(x);

    //获取X509_NAME条目个数  
    entriesNum = sk_X509_NAME_ENTRY_num(issuer->entries);
    //printf("entriesNum : %d\n", version);

    time_t  tmp;    //保存证书时间 
    struct tm *p;
    char buf[100];
    char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};

    //获取证书过期日期  
    time = X509_get_notAfter(x);
    tmp = asn1_time_transform(time);
    p = gmtime(&tmp);

    sprintf(buf, "%d%02d%02d %02d:%02d:%02d",(1900+p->tm_year), (1+p->tm_mon),p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);

    lua_pushstring(L, buf);
    return 1;

}

static int create_cert_time(lua_State *L)
{
    const char *path = NULL;
    path = lua_tostring(L,1);

    int reason_code;
    BIO *in;
    int ret = 0;
    X509 *x = NULL;

    in = BIO_new(BIO_s_file());
    if (in == NULL) {

    }

    if (BIO_read_filename(in, path) <= 0) {

    }
    x = PEM_read_bio_X509(in, NULL, NULL, NULL);

    long version;
    X509_NAME *issuer = NULL;
    int entriesNum;
    unsigned char msginfo[1024];
    long Nid;
    int i;
    X509_NAME_ENTRY *name_entry;
    ASN1_TIME *time;   

  
    X509_NAME *subject = NULL;          //X509_NAME结构体,保存证书拥有者信息  
    ASN1_INTEGER *Serial = NULL;        //保存证书序列号  
    EVP_PKEY *pubKey;                   //保存证书公钥  
    unsigned char derpubkey[1024];
    int derpubkeyLen;
    int msginfoLen;
    unsigned short *pUtf8 = NULL;
    int nUtf8;
    int rv;

    //获取证书版本  
    version = X509_get_version(x);
    //printf("X509 Version: %ld\n", version);

    //获取证书颁发者信息,X509_NAME结构体保存了多项信息,包括国家、组织、部门、通用名、mail等。  
    issuer = X509_get_issuer_name(x);


    //获取X509_NAME条目个数  
    entriesNum = sk_X509_NAME_ENTRY_num(issuer->entries);
    //printf("entriesNum : %d\n", version);

    time_t  tmptmp;
    //获取证书生效日期  
    time = X509_get_notBefore(x);
    tmptmp = asn1_time_transform(time);
    struct tm *p;

    char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
    p = gmtime(&tmptmp); 

    char buf[100], buf2[100];
    sprintf(buf, "%d%02d%02d %02d:%02d:%02d",(1900+p->tm_year), (1+p->tm_mon),p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);

    lua_pushstring(L,buf);
    return 1;
}


static const struct luaL_Reg lib[] =
{
    {"create_cert_time", create_cert_time},
    {"expire_cert_time", expire_cert_time},
    {NULL,NULL}
};

int luaopen_libcert(lua_State *L)
{
    luaL_register(L,"libcert",lib);
    return 1;
}

c函数注册至lua

luaL_Reg列表,记录了要注册的函数信息,本例中只有两个函数create_cert_time和expire_cert_time,所以luaL_Reg如下

代码语言:javascript
复制
static const struct luaL_Reg lib[] =
{
    {"create_cert_time", create_cert_time},
    {"expire_cert_time", expire_cert_time},
    {NULL,NULL}
};

c库入口函数

通过luaopen_xxx实现,xxx标识c函数封装so动态库的名称,该例中动态库名称为libcert.so,固函数名为luaopen_libcert,luaL_register参数为lua_State、动态库名称libcert、上面luaL_Reg lib。

代码语言:javascript
复制
int luaopen_libcert(lua_State *L)
{
    luaL_register(L,"libcert",lib);
    return 1;
}

lua代码调用c动态库

代码和说明如下

代码语言:javascript
复制
require("libcert")

--参数为证书路径
c = libcert.create_cert_time("./abc.cert")
e = libcert.expire_cert_time("./abc.cert")

--证书创建时间
print("create time: ",c);
--证书过期时间
print("expire time: ",e);

注意:

本文使用lua5.1版本,在 lua5.2里没有luaL_register函数了,据说是lua不鼓励将模块设置到全局域,可以使用luaL_newlib(L, c)来实现。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 需求
  • c函数从lua获取参数
  • 代码说明
  • 向lua返回结果
  • c函数注册至lua
  • c库入口函数
  • lua代码调用c动态库
  • 注意:
相关产品与服务
移动应用安全
移动应用安全(Mobile Application Security,MS)针对移动应用普遍存在的破解、篡改、重打包等各类安全风险,提供Android应用加固、iOS源码混淆、SDK加固等多种加固技术,拥有丰富的行业经验,已服务于金融、互联网、车联网、物联网,运营商等多个行业。稳定、简单、有效,让移动安全建设不再是一种负担。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档