172 Commits

Author SHA1 Message Date
KerwinKoo
6f350a33d5 change binary name from xfrp_client to xfrpc 2017-07-05 15:24:45 +08:00
KerwinKoo
b3efc1087a remove unused filed in proxy_client struct 2017-07-05 10:00:23 +08:00
KerwinKoo
e57a99cf6a remove unused field in base_conf struct 2017-07-05 09:44:16 +08:00
KerwinKoo
571de7556d add assert after strdup 2017-07-04 17:08:33 +08:00
KerwinKoo
2ffa39e7cb reset heartbeat interval to 30s 2017-07-04 16:37:11 +08:00
KerwinKoo
1aba513a05 update config.c 2017-07-04 16:32:54 +08:00
KerwinKoo
5d0d1f105e update code 2017-07-04 16:29:21 +08:00
KerwinKoo
cb95f86b08 update code 2017-07-04 16:27:42 +08:00
KerwinKoo
7028aa3baa fix bug 9+16*x bits bug 2017-07-04 16:18:12 +08:00
KerwinKoo
94314af51a add declearation warnming in cmake 2017-07-04 10:56:24 +08:00
KerwinKoo
b587a2d30f add tcp_mux in send_msg_frp_server func 2017-07-04 10:53:39 +08:00
KerwinKoo
f2e482aa2e add ftp support check 2017-07-04 10:50:27 +08:00
KerwinKoo
bf4a66f554 using json_object_object_get_ex instead of json_object_object_get func 2017-07-03 17:53:21 +08:00
KerwinKoo
d2b85c64b6 rewrite debug info 2017-07-03 16:44:56 +08:00
KerwinKoo
2fc391d8a0 safe free 2017-07-03 16:35:23 +08:00
KerwinKoo
253432601e using SAFE_FREE instead of normal free 2017-07-03 16:27:04 +08:00
KerwinKoo
2f3eb22ad9 add service type check 2017-07-03 16:21:03 +08:00
KerwinKoo
0452348207 remove debug infor 2017-07-03 16:12:01 +08:00
KerwinKoo
cf4f937c25 gukq 20170703 xfrpc update
fix 25 bits length error bug

Signed-off-by: KerwinKoo <gukaiqiang@gmail.com>
2017-07-03 16:06:28 +08:00
KerwinKoo
9c2d183c84 dbg 2017-06-29 17:56:51 +08:00
KerwinKoo
b28fbd316f dbng 2017-06-29 17:53:40 +08:00
KerwinKoo
2e5637d916 dbg 2017-06-29 17:46:32 +08:00
KerwinKoo
2cb82c3c61 dbg 2017-06-29 17:34:24 +08:00
KerwinKoo
06582cc998 dbg 2017-06-29 17:24:21 +08:00
KerwinKoo
c8641376aa DBG 2017-06-29 17:19:35 +08:00
Dengfeng Liu
1b4f677849 Update README.md 2017-06-29 16:38:12 +08:00
Dengfeng Liu
83d0ffe5f0 Update README.md 2017-06-29 16:36:06 +08:00
KerwinKoo
0914758eb1 fix code fromat 2017-06-29 16:29:10 +08:00
KerwinKoo
878d544174 free some calloc func 2017-06-29 16:25:09 +08:00
KerwinKoo
f8cb721589 rewrite connect_server func 2017-06-29 15:13:33 +08:00
KerwinKoo
f23ab1b528 move login_resp_check to login file 2017-06-29 11:58:11 +08:00
KerwinKoo
154be51eb1 add frame free in base_control_ping 2017-06-29 11:49:45 +08:00
KerwinKoo
a3d6c4c5d5 fix control.c 2017-06-29 11:27:50 +08:00
KerwinKoo
8e6f963f8e add tcp mux check in ping 2017-06-29 11:16:32 +08:00
KerwinKoo
3efda5f37c only init_sid_index when used tcp mux 2017-06-29 10:54:01 +08:00
KerwinKoo
c1bc883f50 fix frame free 2017-06-29 10:47:11 +08:00
KerwinKoo
bff9cbdd1f add free in send_msg_frp_server 2017-06-29 10:44:47 +08:00
KerwinKoo
1680f814d6 fix main_ctl not inited bug 2017-06-29 10:26:44 +08:00
KerwinKoo
1e2b79d2aa add free frame 2017-06-29 10:22:51 +08:00
KerwinKoo
02348cca62 move some code to login 2017-06-29 10:17:20 +08:00
KerwinKoo
6eb8eb3dd9 reworite connect_event_cb func 2017-06-28 17:24:03 +08:00
KerwinKoo
f795e93b07 rewrite control event funcs 2017-06-28 17:11:06 +08:00
KerwinKoo
93f7d19a44 add free_control func 2017-06-28 16:29:48 +08:00
KerwinKoo
da6b6e4d42 set tcp_mux to default: false 2017-06-28 16:09:19 +08:00
KerwinKoo
c4374a7ac6 remove main_control_conn func 2017-06-28 16:03:03 +08:00
KerwinKoo
9888eaee0f rewrite init_main_control type to void 2017-06-28 15:57:18 +08:00
KerwinKoo
a606e6c69f move login code to login file 2017-06-28 15:55:14 +08:00
KerwinKoo
de68f1bdc2 add login source file 2017-06-28 15:43:41 +08:00
KerwinKoo
ef7e3c11bd remove unused codes from cofig 2017-06-28 15:30:22 +08:00
KerwinKoo
cf01fcfdfa rm xfrp_test_server 2017-06-28 14:22:40 +08:00
KerwinKoo
57c37f0431 add user support in login 2017-06-28 14:09:06 +08:00
KerwinKoo
fe86a827c1 reconnect when login failed 2017-06-22 16:12:17 +08:00
KerwinKoo
82f811636b to fix login error ...... 2017-06-21 18:05:12 +08:00
KerwinKoo
5a070f5177 add dnsbase 2017-06-20 20:43:33 +08:00
KerwinKoo
79829448a3 fix some code 2017-06-20 20:14:27 +08:00
KerwinKoo
1af77ad396 Merge pull request #1 from KunTengRom/dev
Dev
2017-06-20 19:56:15 +08:00
KerwinKoo
c811f06be5 Merge branch 'master' into dev 2017-06-20 19:56:02 +08:00
KerwinKoo
d55ddc1617 remove some debug code 2017-06-20 19:29:53 +08:00
KerwinKoo
2052cb7aaf add dnsbase from master 2017-06-20 17:52:41 +08:00
KerwinKoo
2cb775bb6a fix code for LEDE linux 2017-06-20 16:46:52 +08:00
KerwinKoo
6270914f8b dbg for LEDE 2017-06-20 16:39:39 +08:00
KerwinKoo
4098a52dfb add custom_domains fild marshal 2017-06-20 16:13:20 +08:00
KerwinKoo
5abc4e7144 fix some unused coude 2017-06-20 15:18:27 +08:00
KerwinKoo
8a74157dd0 remove some debug message 2017-06-20 15:15:07 +08:00
KerwinKoo
303beb044d match KunTengTeam xfrps 2017-06-20 15:09:41 +08:00
KerwinKoo
d8b63a151a update save at 0619 2017-06-19 18:35:51 +08:00
KerwinKoo
cb4db43dad rewirte send_msg_frp_server debug info 2017-06-19 18:25:14 +08:00
KerwinKoo
9bbaf98ba1 update code 2017-06-19 17:39:40 +08:00
KerwinKoo
c220c32543 fix multy data recved from frps once time
using data tail func
2017-06-19 17:29:51 +08:00
KerwinKoo
ddc0ec168e update the new arch 2017-06-19 16:13:24 +08:00
KerwinKoo
c38b46bcbc using proxy_servce instead of client single
remove new_proxy struct, client struct only as a shell for proxy_service struct
2017-06-19 14:44:24 +08:00
KerwinKoo
718f663e0f update 0616 night 2017-06-16 21:18:48 +08:00
KerwinKoo
6dbe902494 add porxy_service and proxy_service_handler 2017-06-16 18:16:24 +08:00
KerwinKoo
25d3e48ad2 v1 2017-06-16 15:27:42 +08:00
KerwinKoo
b701a544bf fix some compile warning 2017-06-16 14:52:59 +08:00
KerwinKoo
9c3b309acb fix 2017-06-16 10:42:43 +08:00
KerwinKoo
fe3c2c129b fix commit codes 2017-06-15 20:46:12 +08:00
KerwinKoo
88d97b2aa4 debug 2017-06-15 20:40:52 +08:00
KerwinKoo
d526cde22b remove some debug info 2017-06-15 20:40:28 +08:00
KerwinKoo
f715eec29d finish version 1 2017-06-15 20:01:30 +08:00
KerwinKoo
156db9a0b2 fallow client message 2017-06-15 16:07:39 +08:00
KerwinKoo
4a9c880b9f do client channel 2017-06-15 13:46:03 +08:00
KerwinKoo
e8666b7d15 start new proxy work connect to server 2017-06-15 11:47:27 +08:00
KerwinKoo
9a817b14d3 dbg 2017-06-14 18:36:16 +08:00
KerwinKoo
036eb47da3 finish multy_recv_buffer_raw 2017-06-14 17:13:24 +08:00
KerwinKoo
b45917435f write multy_recv_buffer_raw again 2017-06-14 17:11:37 +08:00
KerwinKoo
e226e1b856 add multy_recv_buffer_raw func
fix multy tcp buffer recved at once
2017-06-14 16:48:42 +08:00
KerwinKoo
05b81daf40 split recv_cb 2017-06-14 11:57:52 +08:00
KerwinKoo
779055fc72 debug 2017-06-13 18:28:33 +08:00
KerwinKoo
0709ddd9fe ADD Free 2017-06-13 14:16:44 +08:00
KerwinKoo
ca464375ae add tcp-mux match
close tcp-mux now
2017-06-13 14:12:02 +08:00
KerwinKoo
6d5aeabf82 dong start work connection 2017-06-13 11:30:19 +08:00
KerwinKoo
83155c48db fix ping method 2017-06-13 10:43:14 +08:00
KerwinKoo
efb6b23829 add free and debug 2017-06-12 16:10:51 +08:00
KerwinKoo
ceb5bbc95c fix ping error 2017-06-12 15:35:00 +08:00
KerwinKoo
aad98510ac rewrite TypePong func 2017-06-12 15:21:48 +08:00
KerwinKoo
56851a8848 add poong 2017-06-12 15:04:37 +08:00
KerwinKoo
3162a3d114 add and use new_work_conn_marshal 2017-06-12 14:12:22 +08:00
KerwinKoo
6ad4d4543e using session funcs to control 2017-06-12 11:48:28 +08:00
KerwinKoo
33fe62bbcc add session funcs cfile 2017-06-12 11:13:10 +08:00
KerwinKoo
4582aedb33 save 2017-06-09 18:12:57 +08:00
KerwinKoo
81c33b4b4d add login_resp_unmarshal free 2017-06-09 17:34:27 +08:00
KerwinKoo
8353c07059 fix login failed bug when privilege_token is nil 2017-06-09 16:05:34 +08:00
KerwinKoo
3bf8cd11af debug without encrypt fuck!!!! 2017-06-09 15:28:58 +08:00
KerwinKoo
df1d47a263 debug 2017-06-09 10:14:56 +08:00
KerwinKoo
ebc8780514 fuck 2017-06-09 10:14:20 +08:00
KerwinKoo
8407c65f8a fuck encrypt! 2017-06-08 21:00:48 +08:00
KerwinKoo
7c2171ae39 fix encrypt bug
even though i don't know what happend,Its OK after if close debug code ...
2017-06-08 15:33:17 +08:00
KerwinKoo
1d5e76939a rewrite debug mode for encrypt 2017-06-08 11:29:57 +08:00
KerwinKoo
02075a5259 dbg 2017-06-08 11:08:00 +08:00
KerwinKoo
9736e1c6a3 dbg 2017-06-08 11:07:36 +08:00
KerwinKoo
d0b41c747c do again crypt 2017-06-08 11:05:58 +08:00
KerwinKoo
a195307977 do decode debug 2017-06-07 20:55:02 +08:00
KerwinKoo
78de83b6a3 rewrite decrypt_data func 2017-06-07 20:08:10 +08:00
KerwinKoo
c82f0b3319 do again crypt 2017-06-07 19:56:12 +08:00
KerwinKoo
485fbcdc80 handle some unused funcs 2017-06-07 19:33:35 +08:00
KerwinKoo
2c0507bf3c do again new_proxy_request_marshal 2017-06-07 18:01:03 +08:00
KerwinKoo
177955db92 finish encoder 2017-06-07 17:42:48 +08:00
KerwinKoo
0cfe4723b9 finish encrypt example with frp 2017-06-07 15:12:10 +08:00
KerwinKoo
e77b734ac4 udpate 0606 2017-06-06 21:10:27 +08:00
KerwinKoo
6c898dfe9e add test_code for decoder and encoder 2017-06-06 16:32:29 +08:00
KerwinKoo
47ed1930a8 add encrypt data func 2017-06-06 14:46:06 +08:00
KerwinKoo
6d631931a5 todo encrypt_data func 2017-06-05 18:32:51 +08:00
KerwinKoo
e5d337d2c0 add msg reader and writer init funcs 2017-06-05 16:40:59 +08:00
KerwinKoo
d593ee1863 add login_mutex lock 2017-06-05 15:36:26 +08:00
KerwinKoo
0fb850f622 debug 05 2017-06-05 02:53:07 +08:00
KerwinKoo
108285b26c add decoder_init funcs 2017-06-04 16:10:29 +08:00
KerwinKoo
f7a15bd4f1 fix frps iv recved failed bug 2017-06-04 15:25:56 +08:00
KerwinKoo
f1910e5cf7 now working on recv_login_resp_cb 2017-06-02 21:56:56 +08:00
KerwinKoo
3a4b6e0e82 add msg_type_valid_check func 2017-06-02 17:56:52 +08:00
KerwinKoo
996fecbd5c fix login not succed bug 2017-06-02 17:23:22 +08:00
KerwinKoo
5f086651b9 update 2017-06-01 20:32:57 +08:00
KerwinKoo
c814efda45 rename encoder to crypto 2017-06-01 15:57:43 +08:00
KerwinKoo
a7d430fa91 add login_resp_unmarshal 2017-06-01 15:19:01 +08:00
KerwinKoo
ddb2d9fcc5 add debug info 2017-06-01 14:46:21 +08:00
KerwinKoo
d2ab1fd8e3 update 0527
Signed-off-by: KerwinKoo <gukaiqiang@gmail.com>
2017-05-27 19:00:45 +08:00
KerwinKoo
b8a411f9e5 update encode 2017-05-27 15:51:37 +08:00
KerwinKoo
a0aacad505 dbug auth_key to login message 2017-05-27 15:50:24 +08:00
KerwinKoo
d7666dbcd5 update 2017-05-25 21:13:09 +08:00
KerwinKoo
1012f14e73 add main encoder init into mainfuncs 2017-05-25 18:11:11 +08:00
KerwinKoo
4a684ca912 add init_main_encoder funcs 2017-05-25 17:50:53 +08:00
KerwinKoo
59f228ff80 tested encryp_key
the result is

29 201 136 254 206 150 233 65 13 82 120 149 203 228 122 128

same to frpc written by go
2017-05-25 16:05:05 +08:00
KerwinKoo
f1e7c10841 update control for encode 2017-05-25 15:32:26 +08:00
KerwinKoo
59dd6def8e add fastpbkdf2 to CMakefile 2017-05-25 14:20:48 +08:00
KerwinKoo
25987974fe add fastpbkdf2.h for encoder
fastpbkdf2.h is clone from https://github.com/ctz/fastpbkdf2.git
2017-05-25 14:16:51 +08:00
KerwinKoo
d020ed6a37 add encode.c
Frp data connection is encoded by pbkdf2
2017-05-25 11:40:43 +08:00
KerwinKoo
7a9798518b after do send TypeNewProxy 2017-05-25 09:28:35 +08:00
KerwinKoo
adb2edac37 complate send_new_proxy
start send_msg_frp_server with TypeNewProxy
2017-05-24 18:02:26 +08:00
KerwinKoo
f3cf93e308 complate raw_new_proxy func 2017-05-24 15:16:07 +08:00
KerwinKoo
e49eeedec1 add raw_new_proxy func 2017-05-24 14:15:20 +08:00
KerwinKoo
435a531555 add new_proxy struct 2017-05-24 11:46:21 +08:00
KerwinKoo
148e6a20c9 start do proxy_service_start functions 2017-05-24 11:30:06 +08:00
KerwinKoo
b24f4ddc3c fix bug when use unpack 2017-05-24 10:56:27 +08:00
KerwinKoo
6e6be02218 add unpack func 2017-05-24 10:38:13 +08:00
KerwinKoo
321a1fd816 now doing unpack 2017-05-23 21:09:19 +08:00
KerwinKoo
ab4cf89542 add auth ky in login struct 2017-05-23 18:22:46 +08:00
KerwinKoo
a33af765c5 complate login test 2017-05-23 17:33:45 +08:00
KerwinKoo
0f3100fa7d complate frame funcs 2017-05-23 17:14:50 +08:00
KerwinKoo
f4b86e4ca8 finish login and create send_msg_frp_server func 2017-05-23 16:16:22 +08:00
KerwinKoo
2d1d1d675b add puck and msg type in msg model 2017-05-23 14:54:38 +08:00
KerwinKoo
449da60529 add ping func
send cmdNOP and do ticker ping to keep alive with frp
2017-05-23 11:49:24 +08:00
KerwinKoo
1d32f7ce92 add cmd switch into control 2017-05-23 03:37:32 +08:00
KerwinKoo
59f231462c remove session and rewrite frame struct 2017-05-22 18:49:39 +08:00
KerwinKoo
80f6afb6d4 complate request func 2017-05-22 17:50:01 +08:00
KerwinKoo
40fe88a0db create open_session succeed
using open_session connected frps
2017-05-22 17:23:22 +08:00
KerwinKoo
8dea9caeaa add frame struct 2017-05-22 15:32:58 +08:00
KerwinKoo
defc63a726 add control struct 2017-05-22 14:13:26 +08:00
KerwinKoo
7c39e9caa8 compile continue. but tomorry is weekday
I will develop in home NOT IN company

Signed-off-by: KerwinKoo <gukaiqiang@gmail.com>
2017-05-19 21:08:43 +08:00
KerwinKoo
ab9580287c update type enum
Signed-off-by: KerwinKoo <gukaiqiang@gmail.com>
2017-05-19 21:01:40 +08:00
KerwinKoo
df4d2b0904 update msg_type to match frp 0.10.0
Signed-off-by: KerwinKoo <gukaiqiang@gmail.com>
2017-05-19 19:27:46 +08:00
KerwinKoo
6ef9ab241c fix forward-declare forbiden bug
ISO C++ Standard will WARNING forward-declare forbiden of enum type because without knowing the type of enum.

Signed-off-by: KerwinKoo <gukaiqiang@gmail.com>
2017-05-19 14:04:03 +08:00
KerwinKoo
fc50424ab6 add login protocol struct
Signed-off-by: KerwinKoo <gukaiqiang@gmail.com>
2017-05-19 13:33:09 +08:00
35 changed files with 2985 additions and 511 deletions

5
.gitignore vendored
View File

@@ -39,6 +39,7 @@ Makefile
cmake_install.cmake
# bin generated
xfrp_client
xfrpc
xfrp_test_server
bin
bin
.vscode

View File

@@ -2,21 +2,24 @@ cmake_minimum_required(VERSION 2.6)
project(xfrp C)
set(src_xfrp_test_server
xfrp_test_server.c
)
set(src_xfrp_client
set(src_xfrpc
main.c
client.c
config.c
control.c
frame.c
ini.c
msg.c
xfrp_client.c
xfrpc.c
debug.c
zip.c
commandline.c
crypto.c
fastpbkdf2.c
utils.c
session.c
common.c
login.c
)
set(libs
@@ -31,14 +34,11 @@ set(test_libs
event
)
ADD_DEFINITIONS(-Wall -g --std=gnu99 -Wmissing-declarations)
ADD_DEFINITIONS(-Wall -g --std=gnu99)
add_executable(xfrp_client ${src_xfrp_client})
target_link_libraries(xfrp_client ${libs})
add_executable(xfrpc ${src_xfrpc})
target_link_libraries(xfrpc ${libs})
add_executable(xfrp_test_server ${src_xfrp_test_server})
target_link_libraries(xfrp_test_server ${test_libs})
install(TARGETS xfrp_client xfrp_test_server
install(TARGETS xfrpc
RUNTIME DESTINATION bin
)

View File

@@ -14,8 +14,8 @@
[4]: https://github.com/KunTengRom/xfrp/blob/master/LICENSE
[5]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=plastic
[6]: https://github.com/KunTengRom/xfrp/pulls
[7]: https://img.shields.io/badge/FRP-Supported-blue.svg?style=plastic
[8]: https://github.com/fatedier/frp
[7]: https://img.shields.io/badge/XFRPS-Supported-blue.svg?style=plastic
[8]: https://github.com/KunTengRom/xfrps
[9]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=plastic
[10]: https://github.com/KunTengRom/xfrp/issues/new
[11]: https://img.shields.io/badge/Platform-%20OpenWRT%20%7CLEDE%20-brightgreen.svg?style=plastic
@@ -25,11 +25,9 @@
## What is xfrp and why start xfrp
xfrp was [frp](https://github.com/fatedier/frp) client implemented by c for OpenWRT system
xfrp was [xfrps](https://github.com/KunTengRom/xfrp) client implemented by c for OpenWRT system
If you dont know what is frp, please visit [this](https://github.com/fatedier/frp)
The motivation to start xfrp project is that we are OpenWRTer, and openwrt usually ran in wireless router which has little ROM and RAM space, however golang always need more space and memory; therefore we start xfrp project
The motivation to start xfrp project is that we are OpenWRTer, and openwrt usually ran in device which has little ROM and RAM space, however golang always need more space and memory; therefore we start xfrp project
## Compile
@@ -50,13 +48,13 @@ make
Run in debug mode :
```shell
xfrp_client -c frpc_mini.ini -f -d 7
xfrpc -c frpc_mini.ini -f -d 7
```
Run in release mode :
```shell
xfrp_client -c frpc_mini.ini -d 0
xfrpc -c frpc_mini.ini -d 0
```
----

10
bin/frpc.ini Normal file
View File

@@ -0,0 +1,10 @@
[common]
server_addr = 127.0.0.1
server_port = 7001
tcp_mux = false
[G_22]
type = tcp
local_port = 22
remote_port = 20099

View File

@@ -52,6 +52,8 @@
#include "const.h"
#include "uthash.h"
#include "zip.h"
#include "msg.h"
#include "common.h"
#define MAX_OUTPUT (512*1024)
@@ -114,18 +116,19 @@ xfrp_event_cb(struct bufferevent *bev, short what, void *ctx)
struct bufferevent *partner = ctx;
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
debug(LOG_DEBUG, "working connection closed");
if (partner) {
/* Flush all pending data */
xfrp_read_cb(bev, ctx);
if (evbuffer_get_length(
bufferevent_get_output(partner))) {
if (evbuffer_get_length(bufferevent_get_output(partner))) {
/* We still have to flush data from the other
* side, but when that's done, close the other
* side. */
bufferevent_setcb(partner,
NULL, close_on_finished_writecb,
xfrp_event_cb, NULL);
bufferevent_disable(partner, EV_READ);
} else {
/* We have nothing left to say to the other
@@ -142,14 +145,9 @@ xfrp_decrypt_cb(struct bufferevent *bev, void *ctx)
{
struct bufferevent *partner = ctx;
struct evbuffer *src, *dst;
size_t len;
src = bufferevent_get_input(bev);
len = evbuffer_get_length(src);
if (len > 4) {
dst = bufferevent_get_output(partner);
evbuffer_drain(src, 4);
evbuffer_add_buffer(dst, src);
}
dst = bufferevent_get_output(partner);
evbuffer_add_buffer(dst, src);
}
static void
@@ -162,46 +160,69 @@ xfrp_encrypt_cb(struct bufferevent *bev, void *ctx)
len = evbuffer_get_length(src);
if (len > 0) {
dst = bufferevent_get_output(partner);
unsigned int header = htonl(len);
evbuffer_prepend(src, &header, sizeof(unsigned int));
evbuffer_add_buffer(dst, src);
}
}
// create frp tunnel for service
void start_frp_tunnel(const struct proxy_client *client)
void start_frp_tunnel(struct proxy_client *client)
{
struct event_base *base = client->base;
struct common_conf *c_conf = get_common_config();
struct bufferevent *b_svr = connect_server(client, c_conf->server_addr, c_conf->server_port);
if (!b_svr) {
struct proxy_service *ps = client->ps;
if (! ps) {
debug(LOG_ERR, "service tunnel started failed, no proxy service resource.");
return;
}
struct bufferevent *b_clt = connect_server(client, client->local_ip, client->local_port);
if (!b_clt) {
bufferevent_free(b_svr);
if (! ps->local_port) {
debug(LOG_ERR, "service tunnel started failed, proxy service resource unvalid.");
return;
}
client->local_proxy_bev = connect_server(base, ps->local_ip, ps->local_port);
if (!client->local_proxy_bev) {
debug(LOG_ERR, "frpc tunnel connect local proxy port [%d] failed!", ps->local_port);
bufferevent_free(client->ctl_bev);
return;
}
debug(LOG_DEBUG, "proxy server [%s:%d] <---> client [%s:%d]",
c_conf->server_addr, c_conf->server_port, client->local_ip, client->local_port);
bufferevent_setcb(b_svr, xfrp_decrypt_cb, NULL, xfrp_event_cb, b_clt);
bufferevent_setcb(b_clt, xfrp_encrypt_cb, NULL, xfrp_event_cb, b_svr);
bufferevent_enable(b_svr, EV_READ|EV_WRITE);
bufferevent_enable(b_clt, EV_READ|EV_WRITE);
send_msg_frp_server(NewWorkConn, client, b_svr);
c_conf->server_addr,
c_conf->server_port,
ps->local_ip ? ps->local_ip:"::1",
ps->local_port);
bufferevent_setcb(client->ctl_bev,
xfrp_decrypt_cb,
NULL,
xfrp_event_cb,
client->local_proxy_bev);
bufferevent_setcb(client->local_proxy_bev,
xfrp_encrypt_cb,
NULL,
xfrp_event_cb,
client->ctl_bev);
bufferevent_enable(client->ctl_bev, EV_READ|EV_WRITE);
bufferevent_enable(client->local_proxy_bev, EV_READ|EV_WRITE);
}
int send_client_data_tail(struct proxy_client *client)
{
int send_l = 0;
if (client->data_tail && client->data_tail_size && client->local_proxy_bev) {
send_l = bufferevent_write(client->local_proxy_bev, client->data_tail, client->data_tail_size);
}
return send_l;
}
void free_proxy_client(struct proxy_client *client)
{
if (client->name) free(client->name);
if (client->local_ip) free(client->local_ip);
if (client->custom_domains) free(client->custom_domains);
if (client->locations) free(client->locations);
free_base_config(client->bconf);
@@ -221,3 +242,12 @@ void del_proxy_client(struct proxy_client *client)
free_proxy_client(client);
}
// Return NULL if proxy service not found with proxy_name
struct proxy_service *get_proxy_service(const char *proxy_name)
{
struct proxy_service *ps = NULL;
struct proxy_service *all_ps = get_all_proxy_services();
HASH_FIND_STR(all_ps, proxy_name, ps);
return ps;
}

View File

@@ -27,29 +27,63 @@
#ifndef _CLIENT_H_
#define _CLIENT_H_
#include <stdint.h>
#include "uthash.h"
#include "common.h"
struct event_base;
struct base_conf;
struct bufferevent;
struct event;
struct evdns_base;
struct proxy_service;
struct proxy_client {
struct event_base *base;
struct evdns_base *dnsbase;
struct bufferevent *ctl_bev;
struct bufferevent *local_proxy_bev;
struct event *ev_timeout;
struct base_conf *bconf;
char *name; // pointer to bconf->name
char *local_ip;
char *type;
int local_port;
int remote_port;
char *custom_domains;
char *subdomain;
char *locations;
char *host_header_rewrite;
//provate arguments
UT_hash_handle hh;
int connected;
int work_started;
struct proxy_service *ps;
unsigned char *data_tail; // storage untrated data
size_t data_tail_size;
};
struct proxy_service {
char *proxy_name;
char *proxy_type;
int use_encryption;
int use_compression;
char *local_ip;
int remote_port;
int remote_data_port;
int local_port;
// http and https only
char *custom_domains;
char *subdomain;
char *locations;
char *host_header_rewrite;
char *http_user;
char *http_pwd;
//provate arguments
UT_hash_handle hh;
};
@@ -57,10 +91,15 @@ struct proxy_client {
// frp server send xfrp client NoticeUserConn request
// when xfrp client receive that request, it will start
// frp tunnel
void start_frp_tunnel(const struct proxy_client *client);
// if client has data-tail(not NULL), client value will be changed
void start_frp_tunnel(struct proxy_client *client);
void del_proxy_client(struct proxy_client *client);
void free_proxy_client(struct proxy_client *client);
#endif
struct proxy_service *get_proxy_service(const char *proxy_name);
int send_client_data_tail(struct proxy_client *client);
#endif //_CLIENT_H_

View File

@@ -30,6 +30,7 @@
#include <string.h>
#include <signal.h>
#include <syslog.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -145,7 +146,9 @@ parse_commandline(int argc, char **argv)
case 'c':
if (optarg) {
confile = strdup(optarg);
confile = strdup(optarg); //never free it
assert(confile);
flag = 1;
}
break;

24
common.c Normal file
View File

@@ -0,0 +1,24 @@
#include "uthash.h"
#include "common.h"
uint64_t ntoh64(const uint64_t input)
{
uint64_t rval;
uint8_t *data = (uint8_t *)&rval;
data[0] = input >> 56;
data[1] = input >> 48;
data[2] = input >> 40;
data[3] = input >> 32;
data[4] = input >> 24;
data[5] = input >> 16;
data[6] = input >> 8;
data[7] = input >> 0;
return rval;
}
uint64_t hton64(const uint64_t input)
{
return (ntoh64(input));
}

40
common.h Normal file
View File

@@ -0,0 +1,40 @@
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include "uthash.h"
// #define BIGENDIAN_64BIT 0
#define BIGENDIAN_32BIT 1
#define SAFE_FREE(m) \
if (m) free(m)
uint64_t ntoh64(const uint64_t input);
uint64_t hton64(const uint64_t input);
#ifdef BIGENDIAN_64BIT
typedef uint64_t msg_size_t;
#define msg_ntoh(l) \
ntoh64(l)
#define msg_hton(b) \
hton64(b)
#elif BIGENDIAN_32BIT
#define msg_ntoh(l) \
ntohl(l)
#define msg_hton(b) \
htonl(b)
typedef uint32_t msg_size_t;
#endif //BIGENDIAN_64BIT
typedef unsigned short ushort;
#endif //_COMMON_H_

241
config.c
View File

@@ -27,17 +27,22 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include <syslog.h>
#include <sys/utsname.h>
#include "ini.h"
#include "uthash.h"
#include "config.h"
#include "client.h"
#include "debug.h"
#include "msg.h"
#include "version.h"
static struct common_conf *c_conf;
static struct proxy_client *p_clients;
static struct proxy_service *p_services;
struct common_conf *get_common_config()
@@ -62,11 +67,8 @@ void free_base_config(struct base_conf *bconf)
{
if (bconf->name) free(bconf->name);
if (bconf->auth_token) free(bconf->auth_token);
if (bconf->type) free(bconf->type);
if (bconf->privilege_token) free(bconf->privilege_token);
if (bconf->host_header_rewrite) free(bconf->host_header_rewrite);
if (bconf->http_username) free(bconf->http_username);
if (bconf->http_password) free(bconf->http_password);
if (bconf->subdomain) free(bconf->subdomain);
}
@@ -75,6 +77,11 @@ struct proxy_client *get_all_pc()
return p_clients;
}
struct proxy_service *get_all_proxy_services()
{
return p_services;
}
static int is_true(const char *val)
{
if (val && (strcmp(val, "true") == 0 || strcmp(val, "1") == 0))
@@ -83,14 +90,19 @@ static int is_true(const char *val)
return 0;
}
static char *get_valid_type(const char *val)
static const char *get_valid_type(const char *val)
{
if (!val)
return NULL;
#define MATCH_VALUE(s) strcmp(val, s) == 0
if (MATCH_VALUE("tcp") || MATCH_VALUE("http") || MATCH_VALUE("https") || MATCH_VALUE("udp")) {
return strdup(val);
if (MATCH_VALUE("tcp") ||
MATCH_VALUE("http") ||
MATCH_VALUE("https") ||
MATCH_VALUE("udp") ||
MATCH_VALUE("ftp")) {
return val;
}
return NULL;
@@ -107,120 +119,144 @@ static void dump_common_conf()
c_conf->server_addr, c_conf->server_port, c_conf->auth_token, c_conf->privilege_token, c_conf->heartbeat_interval, c_conf->heartbeat_timeout);
}
static void dump_proxy_client(const int index, const struct proxy_client *pc)
static void dump_proxy_service(const int index, struct proxy_service *ps)
{
if (!pc || !pc->bconf)
if (!ps)
return;
if (NULL == pc->bconf->type) {
pc->bconf->type = strdup("tcp");
}
if (1 == pc->bconf->privilege_mode) {
if (NULL == pc->bconf->privilege_token) {
debug(LOG_ERR, "Proxy [%s] error: privilege_token must be set when privilege_mode = true", pc->bconf->name);
exit(0);
}
if ((strcmp(pc->bconf->type, "http") != 0) && (strcmp(pc->bconf->type, "https"))) {
if (0 > pc->remote_port) {
debug(LOG_ERR, "Proxy [%s] error: remote_port must be set when privilege_mode = true", pc->bconf->name);
exit(0);
}
}
}
if (0 > pc->local_port) {
debug(LOG_ERR, "Proxy [%s] error: local_port not found", pc->bconf->name);
if (0 > ps->local_port) {
debug(LOG_ERR, "Proxy [%s] error: local_port not found", ps->proxy_name);
exit(0);
}
debug(LOG_DEBUG, "Proxy %d: {name:%s, local_port:%d, type:%s}", index, pc->bconf->name, pc->local_port, pc->bconf->type);
if (NULL == ps->proxy_type) {
ps->proxy_type = strdup("tcp");
assert(ps->proxy_type);
} else if (strcmp(ps->proxy_type, "ftp") == 0) {
if (ps->remote_data_port <= 0) {
debug(LOG_ERR,
"Proxy [%s] error: remote_data_port must be exist when type is ftp");
}
}
debug(LOG_DEBUG,
"Proxy service %d: {name:%s, local_port:%d, type:%s}",
index,
ps->proxy_name,
ps->local_port,
ps->proxy_type);
}
static void dump_all_pc()
static void dump_all_ps()
{
struct proxy_client *s = NULL, *tmp = NULL;
struct proxy_service *ps = NULL, *tmp = NULL;
int index = 0;
HASH_ITER(hh, p_clients, s, tmp) {
dump_proxy_client(index++, s);
HASH_ITER(hh, p_services, ps, tmp) {
dump_proxy_service(index++, ps);
}
}
static struct proxy_client *new_proxy_client(const char *name)
static struct proxy_service *new_proxy_service(const char *name)
{
struct proxy_client *pc = calloc(sizeof(struct proxy_client), 1);
assert(pc);
struct base_conf *bc = calloc(sizeof(struct base_conf), 1);
assert(bc);
if (! name)
return NULL;
struct proxy_service *ps = (struct proxy_service *)calloc(sizeof(struct proxy_service), 1);
assert(ps);
assert(c_conf);
bc->name = strdup(name);
bc->use_encryption = 0;
bc->use_gzip = 0;
bc->privilege_mode = 0;
bc->pool_count = 0;
pc->bconf = bc;
pc->name = strdup(name);
pc->local_port = -1;
pc->remote_port = -1;
ps->proxy_name = strdup(name);
assert(ps->proxy_name);
if (c_conf->auth_token)
bc->auth_token = strdup(c_conf->auth_token);
if (c_conf->privilege_token)
bc->privilege_token = strdup(c_conf->privilege_token);
ps->proxy_type = NULL;
ps->use_encryption = 0;
ps->local_port = -1;
ps->remote_port = -1;
ps->remote_data_port = -1;
ps->use_compression = 0;
ps->use_encryption = 0;
return pc;
ps->custom_domains = NULL;
ps->subdomain = NULL;
ps->locations = NULL;
ps->host_header_rewrite = NULL;
ps->http_user = NULL;
ps->http_pwd = NULL;
return ps;
}
static int service_handler(void *user, const char *section, const char *nm, const char *value)
static int
proxy_service_handler(void *user, const char *sect, const char *nm, const char *value)
{
struct proxy_client *pc = NULL;
struct proxy_service *ps = NULL;
if (strcmp(section, "common") == 0)
char *section = NULL;
section = strdup(sect);
assert(section);
if (strcmp(section, "common") == 0) {
SAFE_FREE(section);
return 0;
HASH_FIND_STR(p_clients, section, pc);
if (!pc) {
pc = new_proxy_client(section);
HASH_ADD_KEYPTR(hh, p_clients, pc->name, strlen(pc->name), pc);
debug(LOG_DEBUG, "Section[%s] not found in p_clients, add pc[%s]",
section, pc->name);
}
HASH_FIND_STR(p_services, section, ps);
if (!ps) {
ps = new_proxy_service(section);
if (! ps) {
debug(LOG_ERR, "cannot create proxy service, it should not happenned!");
exit(0);
}
HASH_ADD_KEYPTR(hh, p_services, ps->proxy_name, strlen(ps->proxy_name), ps);
}
#define MATCH_NAME(s) strcmp(nm, s) == 0
#define TO_BOOL(v) strcmp(value, "true") ? 0:1
if (MATCH_NAME("type")) {
pc->bconf->type = get_valid_type(value);
if (! get_valid_type(value)) {
debug(LOG_ERR, "proxy service type %s is not supportted", value);
SAFE_FREE(section);
exit(0);
}
ps->proxy_type = strdup(value);
assert(ps->proxy_type);
} else if (MATCH_NAME("local_ip")) {
pc->local_ip = strdup(value);
ps->local_ip = strdup(value);
assert(ps->local_ip);
} else if (MATCH_NAME("local_port")) {
pc->local_port = atoi(value);
ps->local_port = atoi(value);
} else if (MATCH_NAME("use_encryption")) {
pc->bconf->use_encryption = is_true(value);
} else if (MATCH_NAME("use_gzip")) {
pc->bconf->use_gzip = is_true(value);
} else if (MATCH_NAME("privilege_mode")) {
pc->bconf->privilege_mode = is_true(value);
} else if (MATCH_NAME("pool_count")) {
pc->bconf->pool_count = atoi(value);
ps->use_encryption = is_true(value);
} else if (MATCH_NAME("remote_port")) {
pc->remote_port = atoi(value);
ps->remote_port = atoi(value);
} else if (MATCH_NAME("http_user")) {
pc->bconf->http_username = strdup(value);
ps->http_user = strdup(value);
assert(ps->http_user);
} else if (MATCH_NAME("http_pwd")) {
pc->bconf->http_password = strdup(value);
ps->http_pwd = strdup(value);
assert(ps->http_pwd);
} else if (MATCH_NAME("subdomain")) {
pc->bconf->subdomain= strdup(value);
ps->subdomain = strdup(value);
assert(ps->http_pwd);
} else if (MATCH_NAME("custom_domains")) {
pc->custom_domains= strdup(value);
ps->custom_domains = strdup(value);
assert(ps->custom_domains);
} else if (MATCH_NAME("locations")) {
pc->locations= strdup(value);
ps->locations = strdup(value);
assert(ps->locations);
} else if (MATCH_NAME("host_header_rewrite")) {
pc->bconf->host_header_rewrite= strdup(value);
ps->host_header_rewrite = strdup(value);
assert(ps->host_header_rewrite);
} else if (MATCH_NAME("use_encryption")) {
ps->use_encryption = TO_BOOL(value);
} else if (MATCH_NAME("use_compression")) {
ps->use_compression = TO_BOOL(value);
}
SAFE_FREE(section);
return 1;
}
@@ -230,33 +266,48 @@ static int common_handler(void *user, const char *section, const char *name, con
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
if (MATCH("common", "server_addr")) {
if (config->server_addr) free(config->server_addr);
SAFE_FREE(config->server_addr);
config->server_addr = strdup(value);
assert(config->server_addr);
} else if (MATCH("common", "server_port")) {
config->server_port = atoi(value);
} else if (MATCH("common", "http_proxy")) {
SAFE_FREE(config->http_proxy);
config->http_proxy = strdup(value);
assert(config->http_proxy);
} else if (MATCH("common", "log_file")) {
if (config->log_file) free(config->log_file);
SAFE_FREE(config->log_file);
config->log_file = strdup(value);
assert(config->log_file);
} else if (MATCH("common", "log_way")) {
if (config->log_way) free(config->log_way);
SAFE_FREE(config->log_way);
config->log_way = strdup(value);
assert(config->log_way);
} else if (MATCH("common", "log_level")) {
if (config->log_level) free(config->log_level);
SAFE_FREE(config->log_level);
config->log_level = strdup(value);
assert(config->log_level);
} else if (MATCH("common", "log_max_days")) {
config->log_max_days = atoi(value);
} else if (MATCH("common", "privilege_token")) {
SAFE_FREE(config->privilege_token);
config->privilege_token = strdup(value);
assert(config->privilege_token);
} else if (MATCH("common", "heartbeat_interval")) {
config->heartbeat_interval = atoi(value);
} else if (MATCH("common", "heartbeat_timeout")) {
config->heartbeat_timeout = atoi(value);
} else if (MATCH("common", "auth_token")) {
SAFE_FREE(config->auth_token);
config->auth_token = strdup(value);
assert(config->auth_token);
} else if (MATCH("common", "user")) {
SAFE_FREE(config->user);
config->user = strdup(value);
assert(config->user);
} else if (MATCH("common", "tcp_mux")) {
config->tcp_mux = 0; // set tcp_mux to default: false
}
return 1;
}
@@ -266,23 +317,29 @@ static void init_common_conf(struct common_conf *config)
return;
config->server_addr = strdup("0.0.0.0");
assert(config->server_addr);
config->server_port = 7000;
config->log_file = strdup("console");
assert(config->log_file);
config->log_way = strdup("console");
assert(config->log_way);
config->log_level = strdup("info");
assert(config->log_level);
config->log_max_days = 3;
config->heartbeat_interval = 10;
config->heartbeat_timeout = 30;
config->heartbeat_interval = 30;
config->heartbeat_timeout = 60;
config->tcp_mux = 0;
config->user = NULL;
}
void load_config(const char *confile)
{
c_conf = calloc(sizeof(struct common_conf), 1);
c_conf = (struct common_conf *)calloc(sizeof(struct common_conf), 1);
assert(c_conf);
init_common_conf(c_conf);
debug(LOG_INFO, "Reading configuration file '%s'", confile);
debug(LOG_DEBUG, "Reading configuration file '%s'", confile);
if (ini_parse(confile, common_handler, c_conf) < 0) {
debug(LOG_ERR, "Config file parse failed");
@@ -301,7 +358,7 @@ void load_config(const char *confile)
exit(0);
}
ini_parse(confile, service_handler, NULL);
ini_parse(confile, proxy_service_handler, NULL);
dump_all_pc();
dump_all_ps();
}

View File

@@ -26,18 +26,18 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include "client.h"
#include "common.h"
struct base_conf{
char *name;
char *auth_token;
char *type;
int use_encryption;
int use_gzip;
int privilege_mode;
char *privilege_token;
int pool_count;
char *host_header_rewrite;
char *http_username;
char *http_password;
char *subdomain;
};
@@ -54,9 +54,12 @@ struct common_conf {
char *auth_token;
int heartbeat_interval; /* default 10 */
int heartbeat_timeout; /* default 30 */
int tcp_mux; /* default 0 */
char *user;
};
struct common_conf *get_common_config();
struct proxy_service *get_all_proxy_services();
void free_common_config();
@@ -66,4 +69,4 @@ struct proxy_client *get_all_pc();
void load_config(const char *confile);
#endif
#endif //_CONFIG_H_

18
const.h
View File

@@ -35,14 +35,14 @@ enum server_status {
};
// msg type
enum msg_type {
NewCtlConn = 0,
NewWorkConn,
NoticeUserConn,
NewCtlConnRes,
HeartbeatReq,
HeartbeatRes,
NewWorkConnUdp
};
// enum msg_type {
// NewCtlConn = 0,
// NewWorkConn,
// NoticeUserConn,
// NewCtlConnRes,
// HeartbeatReq,
// HeartbeatRes,
// NewWorkConnUdp
// };
#endif

1066
control.c

File diff suppressed because it is too large Load Diff

View File

@@ -24,13 +24,52 @@
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
*/
#ifndef _CONTROL_H_
#define _CONTROL_H_
#include "const.h"
#include "uthash.h"
#include "msg.h"
struct proxy_client;
struct bufferevent;
struct event_base;
enum msg_type;
struct control {
struct event_base *connect_base; //main netevent
struct evdns_base *dnsbase;
struct bufferevent *connect_bev; //main io evet buf
char session_id;
struct event *ticker_ping; //heartbeat timer
};
void connect_eventcb(struct bufferevent *bev, short events, void *ptr);
void sync_iv(unsigned char *iv);
void start_base_connect();
void sync_session_id(uint32_t sid);
void init_main_control();
void run_control();
struct control *get_main_control();
void close_main_control();
void start_login_frp_server(struct event_base *base);
void send_login_frp_server(struct bufferevent *bev);
void login();
void free_control();
void sync_session_id(uint32_t sid);
void send_msg_frp_server(struct bufferevent *bev,
const enum msg_type type,
const char *msg,
const size_t msg_len,
uint32_t sid);
void control_process(struct proxy_client *client);
void send_new_proxy(struct proxy_service *ps);
struct bufferevent *connect_server(struct proxy_client *client, const char *name, const int port);
struct bufferevent
*connect_server(struct event_base *base, const char *name, const int port);
void send_msg_frp_server(enum msg_type type, const struct proxy_client *client, struct bufferevent *bev);
void control_request_free(struct control_request *req);
#endif //_CONTROL_H_

281
crypto.c Normal file
View File

@@ -0,0 +1,281 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <syslog.h>
#include <openssl/ssl.h>
#include "fastpbkdf2.h"
#include "crypto.h"
#include "config.h"
#include "common.h"
#include "debug.h"
// #define ENC_DEBUG 1
static const char *default_salt = "frp";
static const size_t block_size = 16;
static struct frp_coder *main_encoder = NULL;
static struct frp_coder *main_decoder = NULL;
size_t get_block_size()
{
return block_size;
}
// TODO: NEED free
struct frp_coder *new_coder(const char *privilege_token, const char *salt)
{
struct frp_coder *enc = calloc(sizeof(struct frp_coder), 1);
assert(enc);
enc->privilege_token = privilege_token ? strdup(privilege_token):"\0";
assert(enc->privilege_token);
enc->key_len = block_size;
enc->salt = strdup(salt);
assert(enc->salt);
enc->key = encrypt_key(enc->privilege_token, strlen(enc->privilege_token), enc->salt);
enc->iv = calloc(block_size, 1);
encrypt_iv(enc->iv, block_size);
return enc;
}
size_t get_encrypt_block_size()
{
return block_size;
}
struct frp_coder *init_main_encoder()
{
struct common_conf *c_conf = get_common_config();
main_encoder = new_coder(c_conf->privilege_token, default_salt);
assert(main_encoder);
assert(main_encoder->key);
return main_encoder;
}
struct frp_coder *init_main_decoder(unsigned char *iv)
{
struct common_conf *c_conf = get_common_config();
main_decoder = new_coder(c_conf->privilege_token, default_salt);
assert(main_encoder);
assert(main_encoder->key);
memcpy(main_decoder->iv, iv, block_size);
return main_decoder;
}
struct frp_coder *get_main_encoder()
{
return main_encoder;
}
struct frp_coder *get_main_decoder()
{
return main_decoder;
}
int is_encoder_inited()
{
struct frp_coder *e = get_main_encoder();
return e != NULL;
}
int is_decoder_inited()
{
struct frp_coder *d = get_main_decoder();
return d != NULL;
}
// 29 201 136 254 206 150 233 65 13 82 120 149 203 228 122 128
// key_ret buffer len must be 16
// the result should be free after using
unsigned char *encrypt_key(const char *token, size_t token_len, const char *salt)
{
unsigned char *key_ret = calloc(block_size, 1);
fastpbkdf2_hmac_sha1((void *)token,
token_len, (void *)salt,
strlen(salt),
64,
(void *)key_ret,
block_size);
/* debug */
#ifdef ENC_DEBUG
printf("encrypt_key = ");
int i = 0;
for(i=0; i<block_size; i++ ) {
printf("%u ", *(key_ret + i));
}
printf("\n");
/* debug end */
#endif //ENC_DEBUG
if (! key_ret)
fprintf(stderr, "key result buffer not applied!\n");
return key_ret;
}
// the result should be free after using
unsigned char *encrypt_iv(unsigned char *iv_buf, size_t iv_len)
{
if (iv_len < block_size || iv_buf == NULL) {
return NULL;
}
srand((unsigned int) time(NULL));
size_t i;
for(i=0; i<iv_len; i++) {
iv_buf[i] = (rand() % 254 ) + 1;
}
return iv_buf;
}
// using aes-128-cfb and nopadding
size_t encrypt_data(const unsigned char *src_data, size_t srclen, struct frp_coder *encoder, unsigned char **ret)
{
unsigned char *intext = calloc(srclen, 1); // free in func
assert(intext);
memcpy(intext, src_data, srclen);
unsigned char *outbuf = calloc(srclen, 1);
assert(outbuf);
*ret = outbuf;
int outlen = 0, tmplen = 0;
struct frp_coder *c = encoder;
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
if(!EVP_EncryptUpdate(&ctx, outbuf, &outlen, intext, (int)srclen)) {
debug(LOG_ERR, "EVP_EncryptUpdate error!");
goto E_END;
}
if(!EVP_EncryptFinal_ex(&ctx, outbuf+outlen, &tmplen)) {
debug(LOG_ERR, "EVP_EncryptFinal_ex error!");
goto E_END;
}
outlen += tmplen;
EVP_CIPHER_CTX_cleanup(&ctx);
#ifdef ENC_DEBUG
int j = 0;
debug(LOG_DEBUG, "encoder iv=");
for (j=0; j<16; j++){
printf("%u ", (unsigned char)c->iv[j]) ;
}
printf("\n");
debug(LOG_DEBUG, "encoder KEY=");
for (j=0; j<16; j++){
printf("%u ", (unsigned char)c->key[j]);
}
printf("\n");
debug(LOG_DEBUG, "encoder result 10 =");
for (j = 0; j<outlen; j++) {
printf("%d ", (unsigned char)outbuf[j]);
}
printf("\n");
#endif //ENC_DEBUG
E_END:
free(intext);
return outlen;
}
size_t decrypt_data(const unsigned char *enc_data, size_t enc_len, struct frp_coder *decoder, unsigned char **ret)
{
unsigned char *inbuf = malloc(enc_len);
assert(inbuf);
memcpy(inbuf, enc_data, enc_len);
unsigned char *outbuf = malloc(enc_len);
assert(outbuf);
*ret = outbuf;
int outlen = 0, tmplen = 0;
struct frp_coder *c = decoder;
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
EVP_CIPHER_CTX_set_padding(&ctx, 0);
int loop_times = enc_len / 10;
int latest_len = enc_len % 10;
int i = 0;
int totol_len = 0;
int enc_per_len;
for(i=0; i<=loop_times; i++) {
if (i == loop_times) {
enc_per_len = latest_len;
} else {
enc_per_len = 10;
}
if(!EVP_DecryptUpdate(&ctx, outbuf + (i*10), &outlen, inbuf + (i*10), enc_per_len)) {
debug(LOG_ERR, "EVP_DecryptUpdate error!");
goto D_END;
}
totol_len += outlen;
}
if(!EVP_DecryptFinal_ex(&ctx, outbuf+totol_len, &tmplen)) {
debug(LOG_ERR, "EVP_DecryptFinal_ex error");
goto D_END;
}
totol_len += tmplen;
EVP_CIPHER_CTX_cleanup(&ctx);
#ifdef ENC_DEBUG
debug(LOG_DEBUG, "DEC_LEN:%lu", enc_len);
int j = 0;
debug(LOG_DEBUG, "decoder IV=");
for (j=0; j<16; j++){
printf("%u ", (unsigned char)c->iv[j] );
}
printf("\n");
debug(LOG_DEBUG, "decoder KEY=");
for (j=0; j<16; j++){
printf("%u ", (unsigned char)c->key[j] );
}
printf("\n");
debug(LOG_DEBUG, "decoder source=");
for (j=0; j<enc_len; j++){
printf("%u ", (unsigned char)inbuf[j]);
}
printf("\n");
debug(LOG_DEBUG, "decoder result=");
for (j = 0; j<totol_len; j++) {
printf("%u ", (unsigned char)(*ret)[j]);
}
printf("\n");
debug(LOG_DEBUG, "decode string=%s", outbuf);
#endif //ENC_DEBUG
D_END:
return totol_len;
}
void free_encoder(struct frp_coder *encoder) {
if (encoder) {
SAFE_FREE(encoder->privilege_token);
SAFE_FREE(encoder->salt);
SAFE_FREE(encoder->key);
SAFE_FREE(encoder->iv);
SAFE_FREE(encoder);
}
}

33
crypto.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef _CRYPTO_H_
#define _CRYPTO_H_
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "common.h"
struct frp_coder {
unsigned char *key;
ushort key_len;
char *salt;
unsigned char *iv;
char *privilege_token;
};
size_t get_encrypt_block_size();
size_t decrypt_data(const unsigned char *enc_data, size_t enc_len, struct frp_coder *decoder, unsigned char **ret);
int is_encoder_inited();
int is_decoder_inited();
struct frp_coder *init_main_encoder();
struct frp_coder *init_main_decoder(unsigned char *iv);
struct frp_coder *new_coder(const char *privilege_token, const char *salt);
unsigned char *encrypt_key(const char *token, size_t token_len, const char *salt);
unsigned char *encrypt_iv(unsigned char *iv_buf, size_t iv_len);
size_t encrypt_data(const unsigned char *src_data, size_t srclen, struct frp_coder *encoder, unsigned char **ret);
struct frp_coder *get_main_encoder();
struct frp_coder *get_main_decoder();
size_t get_block_size();
void free_encoder(struct frp_coder *encoder);
#endif // _CRYPTO_H_

399
fastpbkdf2.c Normal file
View File

@@ -0,0 +1,399 @@
/*
* fast-pbkdf2 - Optimal PBKDF2-HMAC calculation
* Written in 2015 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "fastpbkdf2.h"
#include <assert.h>
#include <string.h>
#include <openssl/sha.h>
/* --- MSVC doesn't support C99 --- */
#ifdef _MSC_VER
#define restrict
#define _Pragma __pragma
#endif
/* --- Common useful things --- */
#define MIN(a, b) ((a) > (b)) ? (b) : (a)
static inline void write32_be(uint32_t n, uint8_t out[4])
{
#if defined(__GNUC__) && __GNUC__ >= 4 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
*(uint32_t *)(out) = __builtin_bswap32(n);
#else
out[0] = (n >> 24) & 0xff;
out[1] = (n >> 16) & 0xff;
out[2] = (n >> 8) & 0xff;
out[3] = n & 0xff;
#endif
}
static inline void write64_be(uint64_t n, uint8_t out[8])
{
#if defined(__GNUC__) && __GNUC__ >= 4 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
*(uint64_t *)(out) = __builtin_bswap64(n);
#else
write32_be((n >> 32) & 0xffffffff, out);
write32_be(n & 0xffffffff, out + 4);
#endif
}
/* --- Optional OpenMP parallelisation of consecutive blocks --- */
#ifdef WITH_OPENMP
# define OPENMP_PARALLEL_FOR _Pragma("omp parallel for")
#else
# define OPENMP_PARALLEL_FOR
#endif
/* Prepare block (of blocksz bytes) to contain md padding denoting a msg-size
* message (in bytes). block has a prefix of used bytes.
*
* Message length is expressed in 32 bits (so suitable for sha1, sha256, sha512). */
static inline void md_pad(uint8_t *block, size_t blocksz, size_t used, size_t msg)
{
memset(block + used, 0, blocksz - used - 4);
block[used] = 0x80;
block += blocksz - 4;
write32_be((uint32_t) (msg * 8), block);
}
/* Internal function/type names for hash-specific things. */
#define HMAC_CTX(_name) HMAC_ ## _name ## _ctx
#define HMAC_INIT(_name) HMAC_ ## _name ## _init
#define HMAC_UPDATE(_name) HMAC_ ## _name ## _update
#define HMAC_FINAL(_name) HMAC_ ## _name ## _final
#define PBKDF2_F(_name) pbkdf2_f_ ## _name
#define PBKDF2(_name) pbkdf2_ ## _name
/* This macro expands to decls for the whole implementation for a given
* hash function. Arguments are:
*
* _name like 'sha1', added to symbol names
* _blocksz block size, in bytes
* _hashsz digest output, in bytes
* _ctx hash context type
* _init hash context initialisation function
* args: (_ctx *c)
* _update hash context update function
* args: (_ctx *c, const void *data, size_t ndata)
* _final hash context finish function
* args: (void *out, _ctx *c)
* _xform hash context raw block update function
* args: (_ctx *c, const void *data)
* _xcpy hash context raw copy function (only need copy hash state)
* args: (_ctx * restrict out, const _ctx *restrict in)
* _xtract hash context state extraction
* args: args (_ctx *restrict c, uint8_t *restrict out)
* _xxor hash context xor function (only need xor hash state)
* args: (_ctx *restrict out, const _ctx *restrict in)
*
* The resulting function is named PBKDF2(_name).
*/
#define DECL_PBKDF2(_name, _blocksz, _hashsz, _ctx, \
_init, _update, _xform, _final, _xcpy, _xtract, _xxor) \
typedef struct { \
_ctx inner; \
_ctx outer; \
} HMAC_CTX(_name); \
\
static inline void HMAC_INIT(_name)(HMAC_CTX(_name) *ctx, \
const uint8_t *key, size_t nkey) \
{ \
/* Prepare key: */ \
uint8_t k[_blocksz]; \
\
/* Shorten long keys. */ \
if (nkey > _blocksz) \
{ \
_init(&ctx->inner); \
_update(&ctx->inner, key, nkey); \
_final(k, &ctx->inner); \
\
key = k; \
nkey = _hashsz; \
} \
\
/* Standard doesn't cover case where blocksz < hashsz. */ \
assert(nkey <= _blocksz); \
\
/* Right zero-pad short keys. */ \
if (k != key) \
memcpy(k, key, nkey); \
if (_blocksz > nkey) \
memset(k + nkey, 0, _blocksz - nkey); \
\
/* Start inner hash computation */ \
uint8_t blk_inner[_blocksz]; \
uint8_t blk_outer[_blocksz]; \
\
for (size_t i = 0; i < _blocksz; i++) \
{ \
blk_inner[i] = 0x36 ^ k[i]; \
blk_outer[i] = 0x5c ^ k[i]; \
} \
\
_init(&ctx->inner); \
_update(&ctx->inner, blk_inner, sizeof blk_inner); \
\
/* And outer. */ \
_init(&ctx->outer); \
_update(&ctx->outer, blk_outer, sizeof blk_outer); \
} \
\
static inline void HMAC_UPDATE(_name)(HMAC_CTX(_name) *ctx, \
const void *data, size_t ndata) \
{ \
_update(&ctx->inner, data, ndata); \
} \
\
static inline void HMAC_FINAL(_name)(HMAC_CTX(_name) *ctx, \
uint8_t out[_hashsz]) \
{ \
_final(out, &ctx->inner); \
_update(&ctx->outer, out, _hashsz); \
_final(out, &ctx->outer); \
} \
\
\
/* --- PBKDF2 --- */ \
static inline void PBKDF2_F(_name)(const HMAC_CTX(_name) *startctx, \
uint32_t counter, \
const uint8_t *salt, size_t nsalt, \
uint32_t iterations, \
uint8_t *out) \
{ \
uint8_t countbuf[4]; \
write32_be(counter, countbuf); \
\
/* Prepare loop-invariant padding block. */ \
uint8_t Ublock[_blocksz]; \
md_pad(Ublock, _blocksz, _hashsz, _blocksz + _hashsz); \
\
/* First iteration: \
* U_1 = PRF(P, S || INT_32_BE(i)) \
*/ \
HMAC_CTX(_name) ctx = *startctx; \
HMAC_UPDATE(_name)(&ctx, salt, nsalt); \
HMAC_UPDATE(_name)(&ctx, countbuf, sizeof countbuf); \
HMAC_FINAL(_name)(&ctx, Ublock); \
_ctx result = ctx.outer; \
\
/* Subsequent iterations: \
* U_c = PRF(P, U_{c-1}) \
*/ \
for (uint32_t i = 1; i < iterations; i++) \
{ \
/* Complete inner hash with previous U */ \
_xcpy(&ctx.inner, &startctx->inner); \
_xform(&ctx.inner, Ublock); \
_xtract(&ctx.inner, Ublock); \
/* Complete outer hash with inner output */ \
_xcpy(&ctx.outer, &startctx->outer); \
_xform(&ctx.outer, Ublock); \
_xtract(&ctx.outer, Ublock); \
_xxor(&result, &ctx.outer); \
} \
\
/* Reform result into output buffer. */ \
_xtract(&result, out); \
} \
\
static inline void PBKDF2(_name)(const uint8_t *pw, size_t npw, \
const uint8_t *salt, size_t nsalt, \
uint32_t iterations, \
uint8_t *out, size_t nout) \
{ \
assert(iterations); \
assert(out && nout); \
\
/* Starting point for inner loop. */ \
HMAC_CTX(_name) ctx; \
HMAC_INIT(_name)(&ctx, pw, npw); \
\
/* How many blocks do we need? */ \
uint32_t blocks_needed = (uint32_t)(nout + _hashsz - 1) / _hashsz; \
\
OPENMP_PARALLEL_FOR \
for (uint32_t counter = 1; counter <= blocks_needed; counter++) \
{ \
uint8_t block[_hashsz]; \
PBKDF2_F(_name)(&ctx, counter, salt, nsalt, iterations, block); \
\
size_t offset = (counter - 1) * _hashsz; \
size_t taken = MIN(nout - offset, _hashsz); \
memcpy(out + offset, block, taken); \
} \
}
static inline void sha1_extract(SHA_CTX *restrict ctx, uint8_t *restrict out)
{
write32_be(ctx->h0, out);
write32_be(ctx->h1, out + 4);
write32_be(ctx->h2, out + 8);
write32_be(ctx->h3, out + 12);
write32_be(ctx->h4, out + 16);
}
static inline void sha1_cpy(SHA_CTX *restrict out, const SHA_CTX *restrict in)
{
out->h0 = in->h0;
out->h1 = in->h1;
out->h2 = in->h2;
out->h3 = in->h3;
out->h4 = in->h4;
}
static inline void sha1_xor(SHA_CTX *restrict out, const SHA_CTX *restrict in)
{
out->h0 ^= in->h0;
out->h1 ^= in->h1;
out->h2 ^= in->h2;
out->h3 ^= in->h3;
out->h4 ^= in->h4;
}
DECL_PBKDF2(sha1,
SHA_CBLOCK,
SHA_DIGEST_LENGTH,
SHA_CTX,
SHA1_Init,
SHA1_Update,
SHA1_Transform,
SHA1_Final,
sha1_cpy,
sha1_extract,
sha1_xor)
static inline void sha256_extract(SHA256_CTX *restrict ctx, uint8_t *restrict out)
{
write32_be(ctx->h[0], out);
write32_be(ctx->h[1], out + 4);
write32_be(ctx->h[2], out + 8);
write32_be(ctx->h[3], out + 12);
write32_be(ctx->h[4], out + 16);
write32_be(ctx->h[5], out + 20);
write32_be(ctx->h[6], out + 24);
write32_be(ctx->h[7], out + 28);
}
static inline void sha256_cpy(SHA256_CTX *restrict out, const SHA256_CTX *restrict in)
{
out->h[0] = in->h[0];
out->h[1] = in->h[1];
out->h[2] = in->h[2];
out->h[3] = in->h[3];
out->h[4] = in->h[4];
out->h[5] = in->h[5];
out->h[6] = in->h[6];
out->h[7] = in->h[7];
}
static inline void sha256_xor(SHA256_CTX *restrict out, const SHA256_CTX *restrict in)
{
out->h[0] ^= in->h[0];
out->h[1] ^= in->h[1];
out->h[2] ^= in->h[2];
out->h[3] ^= in->h[3];
out->h[4] ^= in->h[4];
out->h[5] ^= in->h[5];
out->h[6] ^= in->h[6];
out->h[7] ^= in->h[7];
}
DECL_PBKDF2(sha256,
SHA256_CBLOCK,
SHA256_DIGEST_LENGTH,
SHA256_CTX,
SHA256_Init,
SHA256_Update,
SHA256_Transform,
SHA256_Final,
sha256_cpy,
sha256_extract,
sha256_xor)
static inline void sha512_extract(SHA512_CTX *restrict ctx, uint8_t *restrict out)
{
write64_be(ctx->h[0], out);
write64_be(ctx->h[1], out + 8);
write64_be(ctx->h[2], out + 16);
write64_be(ctx->h[3], out + 24);
write64_be(ctx->h[4], out + 32);
write64_be(ctx->h[5], out + 40);
write64_be(ctx->h[6], out + 48);
write64_be(ctx->h[7], out + 56);
}
static inline void sha512_cpy(SHA512_CTX *restrict out, const SHA512_CTX *restrict in)
{
out->h[0] = in->h[0];
out->h[1] = in->h[1];
out->h[2] = in->h[2];
out->h[3] = in->h[3];
out->h[4] = in->h[4];
out->h[5] = in->h[5];
out->h[6] = in->h[6];
out->h[7] = in->h[7];
}
static inline void sha512_xor(SHA512_CTX *restrict out, const SHA512_CTX *restrict in)
{
out->h[0] ^= in->h[0];
out->h[1] ^= in->h[1];
out->h[2] ^= in->h[2];
out->h[3] ^= in->h[3];
out->h[4] ^= in->h[4];
out->h[5] ^= in->h[5];
out->h[6] ^= in->h[6];
out->h[7] ^= in->h[7];
}
DECL_PBKDF2(sha512,
SHA512_CBLOCK,
SHA512_DIGEST_LENGTH,
SHA512_CTX,
SHA512_Init,
SHA512_Update,
SHA512_Transform,
SHA512_Final,
sha512_cpy,
sha512_extract,
sha512_xor)
void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout)
{
PBKDF2(sha1)(pw, npw, salt, nsalt, iterations, out, nout);
}
void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout)
{
PBKDF2(sha256)(pw, npw, salt, nsalt, iterations, out, nout);
}
void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout)
{
PBKDF2(sha512)(pw, npw, salt, nsalt, iterations, out, nout);
}

71
fastpbkdf2.h Normal file
View File

@@ -0,0 +1,71 @@
/*
* fastpbkdf2 - Faster PBKDF2-HMAC calculation
* Written in 2015 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef FASTPBKDF2_H
#define FASTPBKDF2_H
#include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Calculates PBKDF2-HMAC-SHA1.
*
* @p npw bytes at @p pw are the password input.
* @p nsalt bytes at @p salt are the salt input.
* @p iterations is the PBKDF2 iteration count and must be non-zero.
* @p nout bytes of output are written to @p out. @p nout must be non-zero.
*
* This function cannot fail; it does not report errors.
*/
void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout);
/** Calculates PBKDF2-HMAC-SHA256.
*
* @p npw bytes at @p pw are the password input.
* @p nsalt bytes at @p salt are the salt input.
* @p iterations is the PBKDF2 iteration count and must be non-zero.
* @p nout bytes of output are written to @p out. @p nout must be non-zero.
*
* This function cannot fail; it does not report errors.
*/
void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout);
/** Calculates PBKDF2-HMAC-SHA512.
*
* @p npw bytes at @p pw are the password input.
* @p nsalt bytes at @p salt are the salt input.
* @p iterations is the PBKDF2 iteration count and must be non-zero.
* @p nout bytes of output are written to @p out. @p nout must be non-zero.
*
* This function cannot fail; it does not report errors.
*/
void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout);
#ifdef __cplusplus
}
#endif
#endif

70
frame.c Normal file
View File

@@ -0,0 +1,70 @@
#include "frame.h"
#include "session.h"
#include "version.h"
#include "common.h"
const static int size_of_ver = 1;
const static int size_of_cmd = 1;
const static int size_of_length = 2;
const static int size_of_sid = 4;
const static char version = 1;
int get_header_size() {
return size_of_ver + size_of_cmd + size_of_length + size_of_sid;
}
struct frame *new_frame(char cmd, uint32_t sid) {
struct frame *f = calloc(sizeof(struct frame), 1);
if (f != NULL) {
f->ver = version;
f->cmd = cmd;
f->sid = sid;
f->len = 0;
f->data = NULL;
}
return f;
}
// f->len is rawed in this func
struct frame *raw_frame(unsigned char *buf, const size_t buf_len)
{
int header_size = get_header_size();
if (buf_len < header_size) {
return NULL;
}
char ver = buf[VERI];
char cmd = buf[CMDI];
uint32_t sid = htonl(*(uint32_t *)(buf + SIDI));
struct frame *f = new_frame(cmd, sid);
f->ver = ver;
f->len = *(ushort *)(buf + LENI);
f->data = buf_len > header_size ? (unsigned char *)(buf + header_size) : NULL;
return f;
}
struct frame *raw_frame_only_msg(unsigned char *buf, const size_t buf_len)
{
struct frame *f = new_frame(0, 0);
f->ver = CLIENT_V;
f->len = (ushort)buf_len;
f->data = buf;
return f;
}
void set_frame_cmd(struct frame *f, char cmd)
{
f->cmd = cmd;
}
void set_frame_len(struct frame *f, ushort data_len)
{
f->len = data_len;
}
void free_frame(struct frame *f) {
SAFE_FREE(f);
}

40
frame.h Normal file
View File

@@ -0,0 +1,40 @@
#ifndef _FRAME_H_
#define _FRAME_H_
#include <stdlib.h>
#include <stdio.h>
#include "uthash.h"
#include "common.h"
#define VERI 0
#define CMDI 1
#define LENI 2
#define SIDI 4
#define DATAI 8
// cmds
enum cmd_type {
cmdSYN = 0, // stream open
cmdFIN, // stream close, a.k.a EOF mark
cmdPSH, // data push
cmdNOP, // no operation
};
struct frame {
char ver;
char cmd;
ushort len;
uint32_t sid;
unsigned char *data;
};
struct frame *new_frame(char cmd, uint32_t sid);
int get_header_size();
struct frame *raw_frame(unsigned char *buf, const size_t buf_len);
struct frame *raw_frame_only_msg(unsigned char *buf, const size_t buf_len);
void set_frame_cmd(struct frame *f, char cmd);
void set_frame_len(struct frame *f, ushort data_len);
void free_frame(struct frame *f);
#endif //_FRAME_H_

2
install_manifest.txt Normal file
View File

@@ -0,0 +1,2 @@
/usr/bin/xfrpc
/usr/bin/xfrp_test_server

89
login.c Normal file
View File

@@ -0,0 +1,89 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include <syslog.h>
#include <sys/utsname.h>
#include "ini.h"
#include "uthash.h"
#include "config.h"
#include "client.h"
#include "debug.h"
#include "msg.h"
#include "version.h"
#include "login.h"
static struct login *c_login;
char *get_run_id()
{
return c_login->run_id;
}
struct login *get_common_login_config()
{
return c_login;
}
int is_logged()
{
return c_login->logged;
}
void init_login()
{
if (! c_login)
c_login = calloc(sizeof(struct login), 1);
assert(c_login);
struct common_conf *c_conf = get_common_config();
assert(c_conf);
struct utsname uname_buf;
if (uname(&uname_buf)) {
return;
}
c_login->version = strdup(PROTOCOL_VERESION);
assert(c_login->version);
c_login->hostname = NULL;
c_login->os = strdup(uname_buf.sysname);
assert(c_login->os);
c_login->arch = strdup(uname_buf.machine);
assert(c_login->arch);
c_login->user = NULL;
c_login->timestamp = 0;
c_login->run_id = NULL;
c_login->pool_count = 1;
c_login->privilege_key = NULL;
c_login->user = c_conf->user;
c_login->logged = 0;
}
int login_resp_check(struct login_resp *lr)
{
if (lr->run_id == NULL || strlen(lr->run_id) <= 1) {
if (lr->error && strlen(lr->error) > 0) {
debug(LOG_ERR, "login response error: %s", lr->error);
}
debug(LOG_ERR, "login falied!");
c_login->logged = 0;
} else {
c_login->logged = 1;
debug(LOG_DEBUG, "xfrp login response: run_id: [%s], version: [%s]",
lr->run_id,
lr->version);
SAFE_FREE(c_login->run_id);
c_login->run_id = strdup(lr->run_id);
assert(c_login->run_id);
}
return c_login->logged;
}

38
login.h Normal file
View File

@@ -0,0 +1,38 @@
#ifndef _LOGIN_H_
#define _LOGIN_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include "uthash.h"
struct login {
char *version;
char *hostname;
char *os;
char *arch;
char *user;
char *privilege_key;
long int timestamp;
char *run_id;
int pool_count;
/* fields not need json marshal */
int logged; //0 not login 1:logged
};
struct login_resp {
char *version;
char *run_id;
char *error;
};
void init_login();
char *get_run_id();
struct login *get_common_login_config();
int is_logged();
int login_resp_check(struct login_resp *lr);
#endif //_LOGIN_H_

7
main.c
View File

@@ -24,12 +24,13 @@
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
*/
#include "xfrp_client.h"
#include "xfrpc.h"
#include "commandline.h"
#include "login.h"
int main(int argc, char **argv)
{
parse_commandline(argc, argv);
xfrp_client_loop();
init_login();
xfrpc_loop();
}

353
msg.c
View File

@@ -28,109 +28,281 @@
#include <stdio.h>
#include <json-c/json.h>
#include <json-c/bits.h>
#include <openssl/md5.h>
#include <time.h>
#include <assert.h>
#include <syslog.h>
#include <netinet/in.h>
#include "msg.h"
#include "const.h"
#include "config.h"
#include "frame.h"
#include "debug.h"
#include "common.h"
#include "login.h"
#define JSON_MARSHAL_TYPE(jobj,key,jtype,item) \
json_object_object_add(jobj, key, json_object_new_##jtype((item)));
#define SAFE_JSON_STRING(str_target) \
str_target?str_target:"\0"
const char msg_typs[] = {TypeLogin, TypeLoginResp, TypeNewProxy, TypeNewProxyResp,
TypeNewWorkConn, TypeReqWorkConn, TypeStartWorkConn, TypePing, TypePong, TypeUdpPacket};
char *calc_md5(const char *data, int datalen)
{
unsigned char digest[16] = {0};
char *out = (char*)malloc(33);
assert(out);
MD5_CTX md5;
MD5_Init(&md5);
MD5_Update(&md5, data, datalen);
MD5_Final(digest, &md5);
for (int n = 0; n < 16; ++n) {
snprintf(&(out[n*2]), 3, "%02x", (unsigned int)digest[n]);
}
return out;
}
static void fill_custom_domains(struct json_object *j_ctl_req, const char *custom_domains)
{
struct json_object *jarray_cdomains = json_object_new_array();
assert(jarray_cdomains);
char *tmp = strdup(custom_domains);
assert(tmp);
char *tok = tmp, *end = tmp;
while (tok != NULL) {
strsep(&end, ",");
json_object_array_add(jarray_cdomains, json_object_new_string(tok));
tok = end;
}
free(tmp);
SAFE_FREE(tmp);
json_object_object_add(j_ctl_req, "custom_domains", jarray_cdomains);
}
int control_request_marshal(const struct control_request *req, char **msg)
// NEED FREE
struct message *new_message() {
struct message *msg = calloc(1, sizeof(struct message)); //TODO: FREE
if (msg)
{
msg->data_p = NULL;
msg->data_len = 0;
}
return msg;
}
struct work_conn *new_work_conn() {
struct work_conn *work_c = calloc(1, sizeof(struct work_conn));
if (work_c)
work_c->run_id = NULL;
return work_c;
}
char *get_auth_key(const char *token, long int *timestamp)
{
const char *tmp = NULL;
int nret = 0;
struct json_object *j_ctl_req = json_object_new_object();
if (!j_ctl_req)
char seed[128] = {0};
*timestamp = time(NULL);
if (token)
snprintf(seed, 128, "%s%ld", token, *timestamp);
else
snprintf(seed, 128, "%ld", *timestamp);
return calc_md5(seed, strlen(seed));
}
size_t login_request_marshal(char **msg)
{
size_t nret = 0;
struct json_object *j_login_req = json_object_new_object();
if (is_error(j_login_req))
return 0;
json_object_object_add(j_ctl_req, "type", json_object_new_int(req->type));
json_object_object_add(j_ctl_req, "proxy_name", json_object_new_string(req->proxy_name));
json_object_object_add(j_ctl_req, "auth_key",
json_object_new_string(req->auth_key?req->auth_key:""));
if (req->type == HeartbeatReq)
goto end_process;
json_object_object_add(j_ctl_req, "use_encryption", json_object_new_boolean(req->use_encryption));
json_object_object_add(j_ctl_req, "use_gzip", json_object_new_boolean(req->use_gzip));
json_object_object_add(j_ctl_req, "pool_count", json_object_new_int(req->pool_count));
json_object_object_add(j_ctl_req, "privilege_mode", json_object_new_boolean(req->privilege_mode));
json_object_object_add(j_ctl_req, "privilege_key",
json_object_new_string(req->privilege_key?req->privilege_key:""));
json_object_object_add(j_ctl_req, "proxy_type",
json_object_new_string(req->proxy_type?req->proxy_type:""));
json_object_object_add(j_ctl_req, "remote_port", json_object_new_int(req->remote_port));
if (!req->custom_domains)
json_object_object_add(j_ctl_req, "custom_domains", NULL);
else {
fill_custom_domains(j_ctl_req, req->custom_domains);
}
if (!req->locations)
json_object_object_add(j_ctl_req, "locations", NULL);
else {
// need to implement it
;
}
json_object_object_add(j_ctl_req, "host_header_rewrite",
json_object_new_string(req->host_header_rewrite?req->host_header_rewrite:""));
json_object_object_add(j_ctl_req, "http_username",
json_object_new_string(req->http_username?req->http_username:""));
json_object_object_add(j_ctl_req, "http_password",
json_object_new_string(req->http_password?req->http_password:""));
json_object_object_add(j_ctl_req, "subdomain",
json_object_new_string(req->subdomain?req->subdomain:""));
json_object_object_add(j_ctl_req, "timestamp", json_object_new_int(req->timestamp));
struct login *lg = get_common_login_config();
if (!lg)
return 0;
SAFE_FREE(lg->privilege_key);
struct common_conf *cf = get_common_config();
char *auth_key = get_auth_key(cf->privilege_token, &lg->timestamp);
lg->privilege_key = strdup(auth_key);
assert(lg->privilege_key);
end_process:
tmp = json_object_to_json_string(j_ctl_req);
JSON_MARSHAL_TYPE(j_login_req, "version", string, lg->version);
JSON_MARSHAL_TYPE(j_login_req, "hostname", string, SAFE_JSON_STRING(lg->hostname));
JSON_MARSHAL_TYPE(j_login_req, "os", string, lg->os);
JSON_MARSHAL_TYPE(j_login_req, "arch", string, lg->arch);
JSON_MARSHAL_TYPE(j_login_req, "user", string, SAFE_JSON_STRING(lg->user));
JSON_MARSHAL_TYPE(j_login_req, "privilege_key", string, SAFE_JSON_STRING(lg->privilege_key));
JSON_MARSHAL_TYPE(j_login_req, "timestamp", int64, lg->timestamp);
JSON_MARSHAL_TYPE(j_login_req, "run_id", string, SAFE_JSON_STRING(lg->run_id));
JSON_MARSHAL_TYPE(j_login_req, "pool_count", int, lg->pool_count);
const char *tmp = NULL;
tmp = json_object_to_json_string(j_login_req);
if (tmp && strlen(tmp) > 0) {
nret = strlen(tmp);
*msg = strdup(tmp);
assert(*msg);
}
json_object_put(j_ctl_req);
json_object_put(j_login_req);
SAFE_FREE(auth_key);
return nret;
}
int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg)
{
const char *tmp = NULL;
int nret = 0;
struct json_object *j_np_req = json_object_new_object();
if ( ! j_np_req)
return 0;
JSON_MARSHAL_TYPE(j_np_req, "proxy_name", string, np_req->proxy_name);
JSON_MARSHAL_TYPE(j_np_req, "proxy_type", string, np_req->proxy_type);
JSON_MARSHAL_TYPE(j_np_req, "use_encryption", boolean, np_req->use_encryption);
JSON_MARSHAL_TYPE(j_np_req, "use_compression", boolean, np_req->use_compression);
JSON_MARSHAL_TYPE(j_np_req, "remote_port", int, np_req->remote_port);
if (np_req->custom_domains) {
fill_custom_domains(j_np_req, np_req->custom_domains);
} else {
json_object_object_add(j_np_req, "custom_domains", NULL);
}
JSON_MARSHAL_TYPE(j_np_req, "subdomain", string, SAFE_JSON_STRING(np_req->subdomain));
json_object *j_location_array = json_object_new_array();
if (np_req->locations) {
json_object_object_add(j_np_req, "locations", j_location_array);
} else {
json_object_object_add(j_np_req, "locations", NULL);
}
JSON_MARSHAL_TYPE(j_np_req, "host_header_rewrite", string, SAFE_JSON_STRING(np_req->host_header_rewrite));
JSON_MARSHAL_TYPE(j_np_req, "http_user", string, SAFE_JSON_STRING(np_req->http_user));
JSON_MARSHAL_TYPE(j_np_req, "http_pwd", string, SAFE_JSON_STRING(np_req->http_pwd));
tmp = json_object_to_json_string(j_np_req);
if (tmp && strlen(tmp) > 0) {
nret = strlen(tmp);
*msg = strdup(tmp);
assert(*msg);
}
json_object_put(j_np_req);
return nret;
}
int new_work_conn_marshal(const struct work_conn *work_c, char **msg)
{
const char *tmp = NULL;
int nret = 0;
struct json_object *j_new_work_conn = json_object_new_object();
if (! j_new_work_conn)
return 0;
JSON_MARSHAL_TYPE(j_new_work_conn, "run_id", string, SAFE_JSON_STRING(work_c->run_id));
tmp = json_object_to_json_string(j_new_work_conn);
if (tmp && strlen(tmp) > 0) {
nret = strlen(tmp);
*msg = strdup(tmp);
assert(*msg);
}
json_object_put(j_new_work_conn);
return nret;
}
// login_resp_unmarshal NEED FREE
struct login_resp *login_resp_unmarshal(const char *jres)
{
struct json_object *j_lg_res = json_tokener_parse(jres);
if (is_error(j_lg_res))
return NULL;
struct login_resp *lr = calloc(1, sizeof(struct login_resp));
assert(lr);
struct json_object *l_version = NULL;
if (! json_object_object_get_ex(j_lg_res, "version", &l_version))
goto END_ERROR;
lr->version = strdup(json_object_get_string(l_version));
assert(lr->version);
struct json_object *l_run_id = NULL;
if (! json_object_object_get_ex(j_lg_res, "run_id", &l_run_id))
goto END_ERROR;
lr->run_id = strdup(json_object_get_string(l_run_id));
assert(lr->run_id);
struct json_object *l_error = NULL;
if(! json_object_object_get_ex(j_lg_res, "error", &l_error))
goto END_ERROR;
lr->error = strdup(json_object_get_string(l_error));
assert(lr->error);
END_ERROR:
json_object_put(j_lg_res);
return lr;
}
struct start_work_conn_resp *start_work_conn_resp_unmarshal(const char *resp_msg)
{
struct json_object *j_start_w_res = json_tokener_parse(resp_msg);
if (is_error(j_start_w_res))
return NULL;
struct start_work_conn_resp *sr = calloc(1, sizeof(struct start_work_conn_resp));
assert(sr);
struct json_object *pn = NULL;
if(! json_object_object_get_ex(j_start_w_res, "proxy_name", &pn))
goto START_W_C_R_END;
sr->proxy_name = strdup(json_object_get_string(pn));
assert(sr->proxy_name);
START_W_C_R_END:
json_object_put(j_start_w_res);
return sr;
}
struct control_response *control_response_unmarshal(const char *jres)
{
struct json_object *j_ctl_res = json_tokener_parse(jres);
if (is_error(j_ctl_res))
return NULL;
struct control_response *ctl_res = calloc(sizeof(struct control_response), 1);
if (ctl_res == NULL) {
goto error;
}
assert(ctl_res);
struct json_object *jtype = json_object_object_get(j_ctl_res, "type");
if (jtype == NULL) {
goto error;
}
struct json_object *jtype = NULL;
if(! json_object_object_get_ex(j_ctl_res, "type", &jtype))
goto END_ERROR;
ctl_res->type = json_object_get_int(jtype);
struct json_object *jcode = json_object_object_get(j_ctl_res, "code");
if (jcode == NULL)
goto error;
struct json_object *jcode = NULL;
if(! json_object_object_get_ex(j_ctl_res, "code", &jcode))
goto END_ERROR;
ctl_res->code = json_object_get_int(jcode);
struct json_object *jmsg = json_object_object_get(j_ctl_res, "msg");
if (jmsg)
struct json_object *jmsg = NULL;
if(json_object_object_get_ex(j_ctl_res, "msg", &jmsg)) {
ctl_res->msg = strdup(json_object_get_string(jmsg));
error:
assert(ctl_res->msg);
}
END_ERROR:
json_object_put(j_ctl_res);
return ctl_res;
}
@@ -140,7 +312,64 @@ void control_response_free(struct control_response *res)
if (!res)
return;
if (res->msg) free(res->msg);
free(res);
SAFE_FREE(res->msg);
SAFE_FREE(res);
}
int msg_type_valid_check(char msg_type)
{
int i = 0;
for(i = 0; i<(sizeof(msg_typs) / sizeof(*msg_typs)); i++) {
if (msg_typs[i] == msg_type)
return 1;
}
return 0;
}
// only handle recved message with right message type
struct message *unpack(unsigned char *recv_msg, const ushort len)
{
struct message *msg = new_message();
msg->type = *(recv_msg + MSG_TYPE_I);
if (! msg_type_valid_check(msg->type) ) {
debug(LOG_ERR, "message recved type is invalid!");
return NULL;
}
msg_size_t data_len_bigend;
data_len_bigend = *(msg_size_t *)(recv_msg + MSG_LEN_I);
msg->data_len = msg_ntoh(data_len_bigend);
if (msg->data_len > 0) {
msg->data_p = calloc(msg->data_len + 1, 1);
assert(msg->data_p);
memcpy(msg->data_p, recv_msg + MSG_DATA_I, msg->data_len);
}
return msg;
}
size_t pack(struct message *req_msg, unsigned char **ret_buf)
{
int endian_check = 1;
// little endian if true
msg_size_t data_len_bigend;
if(*(char *)&endian_check == 1)
data_len_bigend = msg_hton(req_msg->data_len);
else
data_len_bigend = req_msg->data_len;
size_t buf_len = TYPE_LEN + sizeof(data_len_bigend) + req_msg->data_len;
*ret_buf = calloc(1, buf_len);
assert(*ret_buf);
*(*ret_buf + MSG_TYPE_I) = req_msg->type;
*(msg_size_t *)(*ret_buf + MSG_LEN_I) = data_len_bigend;
memcpy((char *)*ret_buf+TYPE_LEN+sizeof(data_len_bigend), req_msg->data_p, req_msg->data_len);
return buf_len;
}

60
msg.h
View File

@@ -24,6 +24,37 @@
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
*/
#ifndef _MSG_H_
#define _MSG_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include "client.h"
#include "common.h"
#define TYPE_LEN 1 //byte, char
#define MSG_TYPE_I 0
#define MSG_LEN_I 1
#define MSG_DATA_I 5
// msg_type match frp v0.10.0
enum msg_type {
TypeLogin = 'o',
TypeLoginResp = '1',
TypeNewProxy = 'p',
TypeNewProxyResp = '2',
TypeNewWorkConn = 'w',
TypeReqWorkConn = 'r',
TypeStartWorkConn = 's',
TypePing = 'h',
TypePong = '4',
TypeUdpPacket = 'u',
};
struct general_response {
int code;
@@ -59,10 +90,39 @@ struct control_response {
char *msg;
};
struct work_conn {
char *run_id;
};
struct message {
char type;
char *data_p;
size_t data_len;
};
struct start_work_conn_resp {
char *proxy_name;
};
int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg);
int msg_type_valid_check(char msg_type);
struct message *new_message();
char *calc_md5(const char *data, int datalen);
char *get_auth_key(const char *token, long int *timestamp);
size_t login_request_marshal(char **msg);
size_t pack(struct message *req_msg, unsigned char **ret_buf);
struct message *unpack(unsigned char *recv_msg, const ushort len);
// tranlate control request to json string
int control_request_marshal(const struct control_request *req, char **msg);
struct login_resp *login_resp_unmarshal(const char *jres);
struct start_work_conn_resp *start_work_conn_resp_unmarshal(const char *resp_msg);
// parse json string to control response
struct control_response *control_response_unmarshal(const char *jres);
struct work_conn *new_work_conn();
int new_work_conn_marshal(const struct work_conn *work_c, char **msg);
void control_response_free(struct control_response *res);
#endif //_MSG_H_

52
session.c Normal file
View File

@@ -0,0 +1,52 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <syslog.h>
#include "uthash.h"
#include "session.h"
#include "version.h"
#include "debug.h"
#include "frame.h"
uint32_t *sid_index = NULL;
// need free
uint32_t *init_sid_index()
{
if (NULL == sid_index) {
sid_index = (uint32_t *)calloc(1, sizeof(uint32_t));
if (NULL == sid_index)
return sid_index;
#ifdef CLIENT_V
*sid_index = 1;
#elif SERVER
*sid_index = 0;
#endif
}
*sid_index += 2; //xfrp client session id start from 3
return sid_index;
}
uint32_t get_current_sid_index()
{
if (NULL == sid_index) {
return *init_sid_index();
}
return *sid_index;
}
uint32_t new_sid()
{
if (NULL == sid_index) {
init_sid_index();
return get_current_sid_index();
}
*sid_index += 2;
return *sid_index;
}

11
session.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef _SESSION_H_
#define _SESSION_H_
#include "uthash.h"
#include "common.h"
uint32_t *init_sid_index();
uint32_t get_current_sid_index();
uint32_t new_sid();
#endif //_SESSION_H_

167
testfastpbkdf2.c Normal file
View File

@@ -0,0 +1,167 @@
#include "fastpbkdf2.h"
#include <stdio.h>
#include <assert.h>
#include <string.h>
typedef void (*pbkdf2_fn)(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout);
static void dump(const char *label, const uint8_t *data, size_t n)
{
printf("%s: ", label);
for (size_t i = 0; i < n; i++)
printf("%02x", data[i]);
printf("\n");
}
static void check(pbkdf2_fn fn,
const void *pw, size_t npw,
const void *salt, size_t nsalt,
unsigned iterations,
const void *expect, size_t nexpect)
{
uint8_t out[128];
assert(nexpect < sizeof(out));
fn(pw, npw,
salt, nsalt,
iterations,
out, nexpect);
dump("expect", expect, nexpect);
dump("got ", out, nexpect);
assert(memcmp(expect, out, nexpect) == 0);
printf("- test passed\n");
}
int main(void)
{
/* nb. do not edit this code. edit gentests.py instead. */
printf("sha1 (6 tests):\n");
check(fastpbkdf2_hmac_sha1,
"password", 8,
"salt", 4,
1,
"\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", 20);
check(fastpbkdf2_hmac_sha1,
"password", 8,
"salt", 4,
2,
"\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", 20);
check(fastpbkdf2_hmac_sha1,
"password", 8,
"salt", 4,
4096,
"K\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20);
check(fastpbkdf2_hmac_sha1,
"password", 8,
"salt", 4,
16777216,
"\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", 20);
check(fastpbkdf2_hmac_sha1,
"passwordPASSWORDpassword", 24,
"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
4096,
"\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96\x4c\xf2\xf0\x70\x38", 25);
check(fastpbkdf2_hmac_sha1,
"pass\x00\x77\x6f\x72\x64", 9,
"sa\x00\x6c\x74", 5,
4096,
"V\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34\x25\xe0\xc3", 16);
printf("ok\n");
printf("sha256 (9 tests):\n");
check(fastpbkdf2_hmac_sha256,
"passwd", 6,
"salt", 4,
1,
"U\xac\x04\x6e\x56\xe3\x08\x9f\xec\x16\x91\xc2\x25\x44\xb6\x05\xf9\x41\x85\x21\x6d\xde\x04\x65\xe6\x8b\x9d\x57\xc2\x0d\xac\xbc\x49\xca\x9c\xcc\xf1\x79\xb6\x45\x99\x16\x64\xb3\x9d\x77\xef\x31\x7c\x71\xb8\x45\xb1\xe3\x0b\xd5\x09\x11\x20\x41\xd3\xa1\x97\x83", 64);
check(fastpbkdf2_hmac_sha256,
"Password", 8,
"NaCl", 4,
80000,
"M\xdc\xd8\xf6\x0b\x98\xbe\x21\x83\x0c\xee\x5e\xf2\x27\x01\xf9\x64\x1a\x44\x18\xd0\x4c\x04\x14\xae\xff\x08\x87\x6b\x34\xab\x56\xa1\xd4\x25\xa1\x22\x58\x33\x54\x9a\xdb\x84\x1b\x51\xc9\xb3\x17\x6a\x27\x2b\xde\xbb\xa1\xd0\x78\x47\x8f\x62\xb3\x97\xf3\x3c\x8d", 64);
check(fastpbkdf2_hmac_sha256,
"password", 8,
"salt", 4,
1,
"\x12\x0f\xb6\xcf\xfc\xf8\xb3\x2c\x43\xe7\x22\x52\x56\xc4\xf8\x37\xa8\x65\x48\xc9\x2c\xcc\x35\x48\x08\x05\x98\x7c\xb7\x0b\xe1\x7b", 32);
check(fastpbkdf2_hmac_sha256,
"password", 8,
"salt", 4,
2,
"\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9\x28\xf0\x6d\xd0\x2a\x30\x3f\x8e\xf3\xc2\x51\xdf\xd6\xe2\xd8\x5a\x95\x47\x4c\x43", 32);
check(fastpbkdf2_hmac_sha256,
"password", 8,
"salt", 4,
4096,
"\xc5\xe4\x78\xd5\x92\x88\xc8\x41\xaa\x53\x0d\xb6\x84\x5c\x4c\x8d\x96\x28\x93\xa0\x01\xce\x4e\x11\xa4\x96\x38\x73\xaa\x98\x13\x4a", 32);
check(fastpbkdf2_hmac_sha256,
"passwordPASSWORDpassword", 24,
"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
4096,
"\x34\x8c\x89\xdb\xcb\xd3\x2b\x2f\x32\xd8\x14\xb8\x11\x6e\x84\xcf\x2b\x17\x34\x7e\xbc\x18\x00\x18\x1c\x4e\x2a\x1f\xb8\xdd\x53\xe1\xc6\x35\x51\x8c\x7d\xac\x47\xe9", 40);
check(fastpbkdf2_hmac_sha256,
"", 0,
"salt", 4,
1024,
"\x9e\x83\xf2\x79\xc0\x40\xf2\xa1\x1a\xa4\xa0\x2b\x24\xc4\x18\xf2\xd3\xcb\x39\x56\x0c\x96\x27\xfa\x4f\x47\xe3\xbc\xc2\x89\x7c\x3d", 32);
check(fastpbkdf2_hmac_sha256,
"password", 8,
"", 0,
1024,
"\xea\x58\x08\x41\x1e\xb0\xc7\xe8\x30\xde\xab\x55\x09\x6c\xee\x58\x27\x61\xe2\x2a\x9b\xc0\x34\xe3\xec\xe9\x25\x22\x5b\x07\xbf\x46", 32);
check(fastpbkdf2_hmac_sha256,
"pass\x00\x77\x6f\x72\x64", 9,
"sa\x00\x6c\x74", 5,
4096,
"\x89\xb6\x9d\x05\x16\xf8\x29\x89\x3c\x69\x62\x26\x65\x0a\x86\x87", 16);
printf("ok\n");
printf("sha512 (4 tests):\n");
check(fastpbkdf2_hmac_sha512,
"password", 8,
"salt", 4,
1,
"\x86\x7f\x70\xcf\x1a\xde\x02\xcf\xf3\x75\x25\x99\xa3\xa5\x3d\xc4\xaf\x34\xc7\xa6\x69\x81\x5a\xe5\xd5\x13\x55\x4e\x1c\x8c\xf2\x52", 32);
check(fastpbkdf2_hmac_sha512,
"password", 8,
"salt", 4,
2,
"\xe1\xd9\xc1\x6a\xa6\x81\x70\x8a\x45\xf5\xc7\xc4\xe2\x15\xce\xb6\x6e\x01\x1a\x2e\x9f\x00\x40\x71\x3f\x18\xae\xfd\xb8\x66\xd5\x3c", 32);
check(fastpbkdf2_hmac_sha512,
"password", 8,
"salt", 4,
4096,
"\xd1\x97\xb1\xb3\x3d\xb0\x14\x3e\x01\x8b\x12\xf3\xd1\xd1\x47\x9e\x6c\xde\xbd\xcc\x97\xc5\xc0\xf8\x7f\x69\x02\xe0\x72\xf4\x57\xb5", 32);
check(fastpbkdf2_hmac_sha512,
"passwordPASSWORDpassword", 24,
"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
1,
"n\x23\xf2\x76\x38\x08\x4b\x0f\x7e\xa1\x73\x4e\x0d\x98\x41\xf5\x5d\xd2\x9e\xa6\x0a\x83\x44\x66\xf3\x39\x6b\xac\x80\x1f\xac\x1e\xeb\x63\x80\x2f\x03\xa0\xb4\xac\xd7\x60\x3e\x36\x99\xc8\xb7\x44\x37\xbe\x83\xff\x01\xad\x7f\x55\xda\xc1\xef\x60\xf4\xd5\x64\x80\xc3\x5e\xe6\x8f\xd5\x2c\x69\x36", 72);
printf("ok\n");
return 0;
}

22
utils.c Normal file
View File

@@ -0,0 +1,22 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <errno.h>
#include "utils.h"
// s_sleep using select instead of sleep
// s: second, u: usec 10^6usec = 1s
void s_sleep(unsigned int s, unsigned int u)
{
struct timeval timeout;
timeout.tv_sec = s;
timeout.tv_usec = u;
select(0, NULL, NULL, NULL, &timeout);
}

6
utils.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef _UTILS_H_
#define _UTILS_H_
void s_sleep(unsigned int s, unsigned int u);
#endif //_UTILS_H_

View File

@@ -2,5 +2,7 @@
#define _VERSION_H_
#define VERSION "0.05."
#define PROTOCOL_VERESION "0.10.0"
#define CLIENT_V 1
#endif
#endif //_VERSION_H_

View File

@@ -1,80 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#define PORT 7000
#define BACKLOG 100
void readcb(struct bufferevent *bufev, void *arg)
{
char buf[1024] = {0};
size_t readlen;
int res;
readlen = bufferevent_read(bufev, buf, sizeof(buf));
printf("buf:[%s]\n", buf);
}
void writecb(struct bufferevent *bufev, void *arg)
{
}
void errorcb(struct bufferevent *bufev, short event, void *arg)
{
if (event & BEV_EVENT_EOF) {
bufferevent_free(bufev);
printf("Disconnect\n");
} else if (event & BEV_EVENT_ERROR) {
bufferevent_free(bufev);
printf("Got error\n");
} else if (event & BEV_EVENT_TIMEOUT) {
printf("Timeout\n");
}
}
void accept_handler(int fd, short event, void *arg)
{
struct event_base *evbase;
struct bufferevent *bufev;
int sock;
struct sockaddr_in addr;
socklen_t addrlen;
evbase = (struct event_base *)arg;
if (event & EV_READ) {
sock = accept(fd, (struct sockaddr*)&addr, &addrlen);
bufev = bufferevent_socket_new(evbase, sock, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bufev, readcb, writecb, errorcb, NULL);
bufferevent_enable(bufev, EV_READ | EV_WRITE);
}
}
int main(int argc, char** argv)
{
struct event_base *evbase;
struct event *ev;
struct sockaddr_in sin;
int sock;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(PORT);
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(sock, (struct sockaddr*)&sin, sizeof(sin));
listen(sock, BACKLOG);
evbase = event_base_new();
ev = event_new(evbase, sock, EV_READ | EV_PERSIST, accept_handler, evbase);
event_add(ev, NULL);
event_base_dispatch(evbase);
event_free(ev);
event_base_free(evbase);
return 0;
}

View File

@@ -19,7 +19,7 @@
* *
\********************************************************************/
/** @file xfrp_client.c
/** @file xfrpc.c
@brief xfrp client
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
*/
@@ -29,17 +29,11 @@
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <json-c/json.h>
#include <syslog.h>
#include <event2/event.h>
#include <event2/dns.h>
#include "commandline.h"
#include "client.h"
@@ -47,49 +41,15 @@
#include "uthash.h"
#include "control.h"
#include "debug.h"
#include "xfrp_client.h"
#include "xfrpc.h"
#include "crypto.h"
#include "msg.h"
#include "utils.h"
static void start_xfrp_client(struct event_base *base, struct evdns_base *dnsbase)
void xfrpc_loop()
{
struct proxy_client *all_pc = get_all_pc();
struct proxy_client *pc = NULL, *tmp = NULL;
init_main_control();
run_control();
debug(LOG_INFO, "Start xfrp client");
HASH_ITER(hh, all_pc, pc, tmp) {
pc->base = base;
pc->dnsbase = dnsbase;
control_process(pc);
}
}
void xfrp_client_loop()
{
struct event_base *base = NULL;
struct evdns_base *dnsbase = NULL;
base = event_base_new();
if (!base) {
debug(LOG_ERR, "event_base_new() error");
exit(0);
}
dnsbase = evdns_base_new(base, 1);
if (!dnsbase) {
exit(0);
}
evdns_base_set_option(dnsbase, "timeout", "1.0");
// thanks to the following article
// http://www.wuqiong.info/archives/13/
evdns_base_set_option(dnsbase, "randomize-case:", "0");//TurnOff DNS-0x20 encoding
evdns_base_nameserver_ip_add(dnsbase, "180.76.76.76");//BaiduDNS
evdns_base_nameserver_ip_add(dnsbase, "223.5.5.5");//AliDNS
evdns_base_nameserver_ip_add(dnsbase, "223.6.6.6");//AliDNS
evdns_base_nameserver_ip_add(dnsbase, "114.114.114.114");//114DNS
start_xfrp_client(base, dnsbase);
event_base_dispatch(base);
evdns_base_free(dnsbase, 0);
event_base_free(base);
close_main_control();
}

View File

@@ -19,9 +19,14 @@
* *
\********************************************************************/
/** @file xfrp_client.h
/** @file xfrpc.h
@brief xfrp client header file
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
*/
void xfrp_client_loop();
#ifndef _XFRPC_H_
#define _XFRPC_H_
void xfrpc_loop();
#endif //_XFRPC_H_