openssl s_server源码剥离

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。

源码指引:github源码指引_初级代码游戏的博客-CSDN博客


网上找SSL/TLS服务端代码,怎么试都不成功(我好像记得很多年以前成功过的)。怀疑证书文件有问题,用openssl自带的"openssl s_server"命令来测试,正常的,所以彻底没招了,于是就想把s_server的代码弄出来,折腾了两天,不难。

剥出来的源码见apps目录。

目录

关于版本

openssl命令

剥离代码

代码解读


关于版本

我代码用的openssl版本是1.1.1k,与我用的Ubuntu18.04自带的不一致,手贱升了一下级,把系统搞垮了,登录不进去,SSH服务启动失败。最后重装了虚拟机。

不同版本的openssl头文件不太一样,所以会编译不过去,单独提供一套头文件就可以了(1.1.x都行)。只要主版本号和次版本号一致,so提供的接口就是相同的,x只代表BUG修复。

openssl已经到3点几了为什么我还在用1.1呢?因为旧代码都是1.1的,没有特别需要是不会升级的。

openssl命令

openssl除了两个库还有一个程序openssl(以前没怎么关心过openssl程序,就生成一下证书),包含很多功能,输入"openssl help"可以显示这些命令:

cpp 复制代码
$ openssl help
Standard commands
asn1parse         ca                ciphers           cms
crl               crl2pkcs7         dgst              dhparam
dsa               dsaparam          ec                ecparam
enc               engine            errstr            gendsa
genpkey           genrsa            help              list
nseq              ocsp              passwd            pkcs12
pkcs7             pkcs8             pkey              pkeyparam
pkeyutl           prime             rand              rehash
req               rsa               rsautl            s_client
s_server          s_time            sess_id           smime
speed             spkac             srp               storeutl
ts                verify            version           x509

Message Digest commands (see the `dgst' command for more details)
blake2b512        blake2s256        gost              md4
md5               rmd160            sha1              sha224
sha256            sha3-224          sha3-256          sha3-384
sha3-512          sha384            sha512            sha512-224
sha512-256        shake128          shake256          sm3

Cipher commands (see the `enc' command for more details)
aes-128-cbc       aes-128-ecb       aes-192-cbc       aes-192-ecb
aes-256-cbc       aes-256-ecb       aria-128-cbc      aria-128-cfb
aria-128-cfb1     aria-128-cfb8     aria-128-ctr      aria-128-ecb
aria-128-ofb      aria-192-cbc      aria-192-cfb      aria-192-cfb1
aria-192-cfb8     aria-192-ctr      aria-192-ecb      aria-192-ofb
aria-256-cbc      aria-256-cfb      aria-256-cfb1     aria-256-cfb8
aria-256-ctr      aria-256-ecb      aria-256-ofb      base64
bf                bf-cbc            bf-cfb            bf-ecb
bf-ofb            camellia-128-cbc  camellia-128-ecb  camellia-192-cbc
camellia-192-ecb  camellia-256-cbc  camellia-256-ecb  cast
cast-cbc          cast5-cbc         cast5-cfb         cast5-ecb
cast5-ofb         des               des-cbc           des-cfb
des-ecb           des-ede           des-ede-cbc       des-ede-cfb
des-ede-ofb       des-ede3          des-ede3-cbc      des-ede3-cfb
des-ede3-ofb      des-ofb           des3              desx
rc2               rc2-40-cbc        rc2-64-cbc        rc2-cbc
rc2-cfb           rc2-ecb           rc2-ofb           rc4
rc4-40            seed              seed-cbc          seed-cfb
seed-ecb          seed-ofb          sm4-cbc           sm4-cfb
sm4-ctr           sm4-ecb           sm4-ofb

命令s_server和s_client功能的源码位于apps目录下:

s_server.c和s_client.c就是命令s_server和s_client的源码入口。每个里面有个对应的入口点,例如s_server.c的入口点:

cpp 复制代码
int s_server_main(int argc, char *argv[])

openssl程序会调用这些入口点。我只要从这个入口点开始剥离代码就可以了。

剥离代码

apps目录下的文件除了依赖标准的openssl头文件之外还依赖include\internal目录下的头文件,为了方便可以把internal目录复制到apps下面。

编译整个apps目录很容易,只要编译所有的c文件即可,编译参数为"-std=gnu90",用C89/C90不行,会报错。

为了单独编译s_server,首先我们要把入口点改成main,这样才能编译出可执行程序,才能验证是否包含了所有必须的代码。只需要把s_server_main改成main即可。

然后就是从编译s_server.c开始寻找所需的最少的文件。因为头文件都在,所以编译不会出问题,而链接的时候会发生找不到符号入口点,逐个搜索,找到符号的c文件,添加进来。最后会发现有几个全局变量在s_client.c里面,因为我们不需要客户端,所以把那几个定义挪过来就可以了:

cpp 复制代码
BIO* bio_in = NULL;
BIO* bio_out = NULL;
BIO* bio_err = NULL;
char* default_config_file = NULL;
const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };

上面的代码放在s_server.c里面。

最后总结下来,所需的文件是这些:

(如果发现有文件不存在,那就openssl编译的时候生成的,搜索一下,复制过来即可)。

现在代码就可以编译了,用法和去掉openssl的命令完全相同。

但是一运行就挂?不奇怪,openssl的main函数执行了一些初始化,复制过来放在新的main函数入口处即可:

cpp 复制代码
int main(int argc, char *argv[])
{
    /* Set up some of the environment. */
    default_config_file = "";
    bio_in = dup_bio_in(FORMAT_TEXT);
    bio_out = dup_bio_out(FORMAT_TEXT);
    bio_err = dup_bio_err(FORMAT_TEXT);

然后就可以运行了:

cpp 复制代码
s_server.exe -CAfile ca.cer -cert server.cer -key server.key -WWW -accept 443

(不要奇怪后缀名是.exe,谁规定linux可执行程序不可以有后缀名?)

你可以用浏览器访问,可以获取当前目录下的文件。请求"/"会返回内部状态。

当然因为浏览器可能认为服务器证书有问题,提示不安全,不过这不影响我们所需的功能。

代码解读

main函数首先解析了参数,然后启动一个服务(do_server),参数包含服务处理函数指针,s_server.c文件里面实现了三个处理函数:rev_body,sv_body,www_body,根据参数不同调用不同的处理函数,我关心的是www_body。

www_body不复杂,但是写得有BUG,按照说明参数-HTTP对应www=3,处理方式为带头标,不过实际上连请求头都没有输出(所以浏览器报告错误的应答)。

我们只需要修改www_body里面的处理循环,使用输入输出对象即可实现所需要的功能。上面图示的"test"就是下面的代码输出的:

剩下的就是自己的事了。


(这里是文档结束)

吐血啊,突然搞明白网上的例程为什么失败了:

浏览器不断做了尝试,第一次是失败的,而例程出错就退出了。改成循环就没问题了。

相关推荐
计算机毕设定制辅导-无忧学长6 小时前
HTTP 安全:HTTPS 原理与配置
安全·http·https
web2u8 小时前
【鱼皮大佬API开放平台项目】Spring Cloud Gateway HTTPS 配置问题解决方案总结
vue.js·nginx·http·spring cloud·https·vue·springboot
web2u9 小时前
springboot 项目配置https
spring boot·后端·https
Themberfue1 天前
HTTP/HTTPS ④-对称加密 || 非对称加密
网络·网络协议·计算机网络·http·https
会飞的爱迪生1 天前
nginx反向代理http 和 https(案例)
nginx·http·https
QC七哥1 天前
openssl在windows下的编译
windows·openssl·vs2022
挥之以墨1 天前
【WEB】网络传输中的信息安全 - 加密、签名、数字证书与HTTPS
网络·网络协议·https
打工人你好1 天前
HTTPS SSL/TLS 工作流程
网络协议·https·ssl
Web极客码1 天前
HTTP 到 HTTPS – 以下是操作步骤
网络协议·http·https