Compare commits
207 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acb79bcf1f | ||
|
|
75adc0a669 | ||
|
|
2ef0200276 | ||
|
|
7940a4f949 | ||
|
|
81779637ba | ||
|
|
91d6129426 | ||
|
|
d333533639 | ||
|
|
2429f79721 | ||
|
|
044626152c | ||
|
|
0d7643ceb1 | ||
|
|
0e581ebf6f | ||
|
|
2fcfa6a001 | ||
|
|
546dfb74d3 | ||
|
|
a02a5a19c7 | ||
|
|
09b67f7dc6 | ||
|
|
731584cbd3 | ||
|
|
25a994213f | ||
|
|
c4a9f4c97e | ||
|
|
a56d0d4d58 | ||
|
|
9f01265981 | ||
|
|
1e96d85f88 | ||
|
|
a668a6deff | ||
|
|
9ae47ffaa4 | ||
|
|
8d1c6f69ca | ||
|
|
4bcc36489b | ||
|
|
e9e2bf759a | ||
|
|
c6e3af8ac8 | ||
|
|
5ab2ac455d | ||
|
|
ddc3aff29b | ||
|
|
8f75d7c40c | ||
|
|
3c02e4fbc4 | ||
|
|
5b2b3a63ab | ||
|
|
b96e3d9364 | ||
|
|
f9636ce89c | ||
|
|
c1b7585cd5 | ||
|
|
6f350a33d5 | ||
|
|
b3efc1087a | ||
|
|
e57a99cf6a | ||
|
|
571de7556d | ||
|
|
2ffa39e7cb | ||
|
|
1aba513a05 | ||
|
|
5d0d1f105e | ||
|
|
cb95f86b08 | ||
|
|
7028aa3baa | ||
|
|
94314af51a | ||
|
|
b587a2d30f | ||
|
|
f2e482aa2e | ||
|
|
bf4a66f554 | ||
|
|
d2b85c64b6 | ||
|
|
2fc391d8a0 | ||
|
|
253432601e | ||
|
|
2f3eb22ad9 | ||
|
|
0452348207 | ||
|
|
cf4f937c25 | ||
|
|
9c2d183c84 | ||
|
|
b28fbd316f | ||
|
|
2e5637d916 | ||
|
|
2cb82c3c61 | ||
|
|
06582cc998 | ||
|
|
c8641376aa | ||
|
|
1b4f677849 | ||
|
|
83d0ffe5f0 | ||
|
|
0914758eb1 | ||
|
|
878d544174 | ||
|
|
f8cb721589 | ||
|
|
f23ab1b528 | ||
|
|
154be51eb1 | ||
|
|
a3d6c4c5d5 | ||
|
|
8e6f963f8e | ||
|
|
3efda5f37c | ||
|
|
c1bc883f50 | ||
|
|
bff9cbdd1f | ||
|
|
1680f814d6 | ||
|
|
1e2b79d2aa | ||
|
|
02348cca62 | ||
|
|
6eb8eb3dd9 | ||
|
|
f795e93b07 | ||
|
|
93f7d19a44 | ||
|
|
da6b6e4d42 | ||
|
|
c4374a7ac6 | ||
|
|
9888eaee0f | ||
|
|
a606e6c69f | ||
|
|
de68f1bdc2 | ||
|
|
ef7e3c11bd | ||
|
|
cf01fcfdfa | ||
|
|
57c37f0431 | ||
|
|
fe86a827c1 | ||
|
|
82f811636b | ||
|
|
5a070f5177 | ||
|
|
79829448a3 | ||
|
|
1af77ad396 | ||
|
|
c811f06be5 | ||
|
|
d55ddc1617 | ||
|
|
2052cb7aaf | ||
|
|
2cb775bb6a | ||
|
|
6270914f8b | ||
|
|
4098a52dfb | ||
|
|
5abc4e7144 | ||
|
|
8a74157dd0 | ||
|
|
303beb044d | ||
|
|
d8b63a151a | ||
|
|
cb4db43dad | ||
|
|
9bbaf98ba1 | ||
|
|
c220c32543 | ||
|
|
ddc0ec168e | ||
|
|
c38b46bcbc | ||
|
|
718f663e0f | ||
|
|
6dbe902494 | ||
|
|
25d3e48ad2 | ||
|
|
b701a544bf | ||
|
|
9c3b309acb | ||
|
|
fe3c2c129b | ||
|
|
88d97b2aa4 | ||
|
|
d526cde22b | ||
|
|
f715eec29d | ||
|
|
156db9a0b2 | ||
|
|
4a9c880b9f | ||
|
|
e8666b7d15 | ||
|
|
9a817b14d3 | ||
|
|
036eb47da3 | ||
|
|
b45917435f | ||
|
|
e226e1b856 | ||
|
|
05b81daf40 | ||
|
|
779055fc72 | ||
|
|
0709ddd9fe | ||
|
|
ca464375ae | ||
|
|
6d5aeabf82 | ||
|
|
83155c48db | ||
|
|
efb6b23829 | ||
|
|
ceb5bbc95c | ||
|
|
aad98510ac | ||
|
|
56851a8848 | ||
|
|
3162a3d114 | ||
|
|
6ad4d4543e | ||
|
|
33fe62bbcc | ||
|
|
4582aedb33 | ||
|
|
81c33b4b4d | ||
|
|
8353c07059 | ||
|
|
3bf8cd11af | ||
|
|
df1d47a263 | ||
|
|
ebc8780514 | ||
|
|
8407c65f8a | ||
|
|
7c2171ae39 | ||
|
|
1d5e76939a | ||
|
|
02075a5259 | ||
|
|
9736e1c6a3 | ||
|
|
d0b41c747c | ||
|
|
a195307977 | ||
|
|
78de83b6a3 | ||
|
|
c82f0b3319 | ||
|
|
485fbcdc80 | ||
|
|
2c0507bf3c | ||
|
|
177955db92 | ||
|
|
0cfe4723b9 | ||
|
|
e77b734ac4 | ||
|
|
6c898dfe9e | ||
|
|
47ed1930a8 | ||
|
|
6d631931a5 | ||
|
|
e5d337d2c0 | ||
|
|
d593ee1863 | ||
|
|
0fb850f622 | ||
|
|
108285b26c | ||
|
|
f7a15bd4f1 | ||
|
|
f1910e5cf7 | ||
|
|
3a4b6e0e82 | ||
|
|
996fecbd5c | ||
|
|
5f086651b9 | ||
|
|
c814efda45 | ||
|
|
a7d430fa91 | ||
|
|
ddb2d9fcc5 | ||
|
|
d2ab1fd8e3 | ||
|
|
b8a411f9e5 | ||
|
|
a0aacad505 | ||
|
|
d7666dbcd5 | ||
|
|
1012f14e73 | ||
|
|
4a684ca912 | ||
|
|
59f228ff80 | ||
|
|
f1e7c10841 | ||
|
|
59dd6def8e | ||
|
|
25987974fe | ||
|
|
d020ed6a37 | ||
|
|
7a9798518b | ||
|
|
adb2edac37 | ||
|
|
f3cf93e308 | ||
|
|
e49eeedec1 | ||
|
|
435a531555 | ||
|
|
148e6a20c9 | ||
|
|
b24f4ddc3c | ||
|
|
6e6be02218 | ||
|
|
321a1fd816 | ||
|
|
ab4cf89542 | ||
|
|
a33af765c5 | ||
|
|
0f3100fa7d | ||
|
|
f4b86e4ca8 | ||
|
|
2d1d1d675b | ||
|
|
449da60529 | ||
|
|
1d32f7ce92 | ||
|
|
59f231462c | ||
|
|
80f6afb6d4 | ||
|
|
40fe88a0db | ||
|
|
8dea9caeaa | ||
|
|
defc63a726 | ||
|
|
7c39e9caa8 | ||
|
|
ab9580287c | ||
|
|
df4d2b0904 | ||
|
|
6ef9ab241c | ||
|
|
fc50424ab6 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -39,6 +39,7 @@ Makefile
|
||||
cmake_install.cmake
|
||||
|
||||
# bin generated
|
||||
xfrp_client
|
||||
xfrpc
|
||||
xfrp_test_server
|
||||
bin
|
||||
bin
|
||||
.vscode
|
||||
|
||||
@@ -2,21 +2,27 @@ 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
|
||||
proxy_tcp.c
|
||||
proxy_ftp.c
|
||||
proxy.c
|
||||
)
|
||||
|
||||
set(libs
|
||||
@@ -31,14 +37,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
|
||||
)
|
||||
|
||||
42
README.md
42
README.md
@@ -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,10 @@
|
||||
|
||||
## What is xfrp and why start xfrp
|
||||
|
||||
xfrp was [frp](https://github.com/fatedier/frp) client implemented by c for OpenWRT system
|
||||
`xfrp` is [xfrps](https://github.com/KunTengRom/xfrp) client implemented by c for [OpenWRT](https://github.com/openwrt/openwrt) and [LEDE](https://github.com/lede-project/source) 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 device 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 wireless router which has little ROM and RAM space, however golang always need more space and memory; therefore we start xfrp project
|
||||
|
||||
## Compile
|
||||
|
||||
@@ -46,19 +45,48 @@ make
|
||||
|
||||
## Quick start
|
||||
|
||||
**before using xfrp, you should have built the proxy server: [xfrps](https://github.com/KunTengRom/xfrp), It's no difference with frp at usage, but support `FTP` and more embedded-client-friendly for linux.**
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
## FTP support
|
||||
|
||||
xfrp support ftp proxy after version [0.07.451](https://github.com/KunTengRom/xfrp/tree/0.07.451). **Hypothesize you have built [xfrps](https://github.com/KunTengRom/xfrp) succeed!**
|
||||
|
||||
Configure ftp in frpc.ini
|
||||
|
||||
```
|
||||
[common]
|
||||
server_addr = 111.112.113.114
|
||||
server_port = 7001
|
||||
|
||||
[router_ftp_example]
|
||||
type = ftp
|
||||
local_port = 21
|
||||
remote_port = 30621
|
||||
remote_data_port = 30622
|
||||
```
|
||||
|
||||
`remote_port` is the reporxy port of FTP command tunnel, and `remote_data_port` is FTP-DATA port reporxy.
|
||||
|
||||
Use `-p` (PASV Mode) of `ftp` command to connect to proxy ftp server:
|
||||
|
||||
```
|
||||
ftp -p 111.112.113.114 30621
|
||||
```
|
||||
|
||||
In [Master](https://github.com/KunTengRom/xfrp) version `server_addr` can use domain name intead of IP address in FTP proxy. [Issue #4](https://github.com/KunTengRom/xfrp/issues/4) and [Issue #5](https://github.com/KunTengRom/xfrp/issues/5).
|
||||
|
||||
----
|
||||
|
||||
## Todo list
|
||||
|
||||
10
bin/frpc.ini
Normal file
10
bin/frpc.ini
Normal 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
|
||||
|
||||
165
client.c
165
client.c
@@ -52,6 +52,8 @@
|
||||
#include "const.h"
|
||||
#include "uthash.h"
|
||||
#include "zip.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
|
||||
#define MAX_OUTPUT (512*1024)
|
||||
|
||||
@@ -61,7 +63,8 @@ static void xfrp_event_cb(struct bufferevent *bev, short what, void *ctx);
|
||||
static void
|
||||
xfrp_read_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
@@ -72,13 +75,14 @@ xfrp_read_cb(struct bufferevent *bev, void *ctx)
|
||||
}
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
struct proxy *p_l = new_proxy_buf(bev);
|
||||
|
||||
if (evbuffer_get_length(dst) >= MAX_OUTPUT) {
|
||||
/* We're giving the other side data faster than it can
|
||||
* pass it on. Stop reading here until we have drained the
|
||||
* other side to MAX_OUTPUT/2 bytes. */
|
||||
bufferevent_setcb(partner, xfrp_read_cb, drained_writecb,
|
||||
xfrp_event_cb, bev);
|
||||
xfrp_event_cb, p_l);
|
||||
bufferevent_setwatermark(partner, EV_WRITE, MAX_OUTPUT/2,
|
||||
MAX_OUTPUT);
|
||||
bufferevent_disable(bev, EV_READ);
|
||||
@@ -88,11 +92,12 @@ xfrp_read_cb(struct bufferevent *bev, void *ctx)
|
||||
static void
|
||||
drained_writecb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
|
||||
/* We were choking the other side until we drained our outbuf a bit.
|
||||
* Now it seems drained. */
|
||||
bufferevent_setcb(bev, xfrp_read_cb, NULL, xfrp_event_cb, partner);
|
||||
bufferevent_setcb(bev, xfrp_read_cb, NULL, xfrp_event_cb, p);
|
||||
bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
|
||||
if (partner)
|
||||
bufferevent_enable(partner, EV_READ);
|
||||
@@ -111,98 +116,128 @@ close_on_finished_writecb(struct bufferevent *bev, void *ctx)
|
||||
static void
|
||||
xfrp_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
|
||||
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);
|
||||
xfrp_read_cb(bev, p);
|
||||
|
||||
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
|
||||
* side; close it. */
|
||||
bufferevent_free(partner);
|
||||
free_proxy(p);
|
||||
}
|
||||
}
|
||||
bufferevent_free(bev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xfrp_decrypt_cb(struct bufferevent *bev, void *ctx)
|
||||
int is_ftp_proxy(const struct proxy_service *ps)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (! ps || ! ps->proxy_type)
|
||||
return 0;
|
||||
|
||||
static void
|
||||
xfrp_encrypt_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 > 0) {
|
||||
dst = bufferevent_get_output(partner);
|
||||
unsigned int header = htonl(len);
|
||||
evbuffer_prepend(src, &header, sizeof(unsigned int));
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
if (0 == strcmp(ps->proxy_type, "ftp") && ps->remote_data_port > 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create frp tunnel for service
|
||||
void start_frp_tunnel(const struct proxy_client *client)
|
||||
void start_xfrp_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) {
|
||||
if (! client->ctl_bev) {
|
||||
debug(LOG_ERR, "proxy client control bev is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
struct bufferevent *b_clt = connect_server(client, client->local_ip, client->local_port);
|
||||
if (!b_clt) {
|
||||
bufferevent_free(b_svr);
|
||||
|
||||
struct event_base *base = client->base;
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct proxy_service *ps = client->ps;
|
||||
|
||||
if (! base) {
|
||||
debug(LOG_ERR, "service event base get failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (! ps) {
|
||||
debug(LOG_ERR, "service tunnel started failed, no proxy service resource.");
|
||||
return;
|
||||
}
|
||||
|
||||
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,
|
||||
ps->remote_port,
|
||||
ps->local_ip ? ps->local_ip:"::1",
|
||||
ps->local_port);
|
||||
|
||||
struct proxy *ctl_prox = new_proxy_buf(client->ctl_bev);
|
||||
struct proxy *local_prox = new_proxy_buf(client->local_proxy_bev);
|
||||
bufferevent_data_cb proxy_s2c_cb, proxy_c2s_cb;
|
||||
if (is_ftp_proxy(client->ps)) {
|
||||
proxy_c2s_cb = ftp_proxy_c2s_cb;
|
||||
proxy_s2c_cb = ftp_proxy_s2c_cb;
|
||||
ctl_prox->remote_data_port = client->ps->remote_data_port;
|
||||
ctl_prox->proxy_name = strdup(ps->proxy_name);
|
||||
} else {
|
||||
proxy_c2s_cb = tcp_proxy_c2s_cb;
|
||||
proxy_s2c_cb = tcp_proxy_s2c_cb;
|
||||
}
|
||||
|
||||
bufferevent_setcb(client->ctl_bev,
|
||||
proxy_s2c_cb,
|
||||
NULL,
|
||||
xfrp_event_cb,
|
||||
local_prox);
|
||||
|
||||
bufferevent_setcb(client->local_proxy_bev,
|
||||
proxy_c2s_cb,
|
||||
NULL,
|
||||
xfrp_event_cb,
|
||||
ctl_prox);
|
||||
|
||||
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 +256,19 @@ 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;
|
||||
}
|
||||
|
||||
struct proxy_client *new_proxy_client()
|
||||
{
|
||||
struct proxy_client *client = calloc(1, sizeof(struct proxy_client));
|
||||
assert(client);
|
||||
return client;
|
||||
}
|
||||
54
client.h
54
client.h
@@ -27,29 +27,59 @@
|
||||
#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;
|
||||
int local_port;
|
||||
int remote_port;
|
||||
|
||||
char *custom_domains;
|
||||
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 +87,18 @@ 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_xfrp_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);
|
||||
|
||||
int is_ftp_proxy(const struct proxy_service *ps);
|
||||
struct proxy_client *new_proxy_client();
|
||||
|
||||
#endif //_CLIENT_H_
|
||||
|
||||
@@ -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
24
common.c
Normal 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
40
common.h
Normal 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_
|
||||
304
config.c
304
config.c
@@ -27,18 +27,25 @@
|
||||
#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 "utils.h"
|
||||
#include "version.h"
|
||||
|
||||
static struct common_conf *c_conf;
|
||||
static struct proxy_client *p_clients;
|
||||
static struct proxy_service *p_services;
|
||||
|
||||
static void new_ftp_data_proxy_service(struct proxy_service *ftp_ps);
|
||||
|
||||
struct common_conf *get_common_config()
|
||||
{
|
||||
@@ -56,17 +63,22 @@ void free_common_config()
|
||||
if (c_conf->log_level) free(c_conf->log_level);
|
||||
if (c_conf->auth_token) free(c_conf->auth_token);
|
||||
if (c_conf->privilege_token) free(c_conf->privilege_token);
|
||||
SAFE_FREE(c_conf->server_ip);
|
||||
};
|
||||
|
||||
void set_common_server_ip(const char *ip)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
c_conf->server_ip = strdup(ip);
|
||||
assert(c_conf->server_ip);
|
||||
}
|
||||
|
||||
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 +87,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 +100,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;
|
||||
@@ -98,7 +120,7 @@ static char *get_valid_type(const char *val)
|
||||
|
||||
static void dump_common_conf()
|
||||
{
|
||||
if(!c_conf) {
|
||||
if(! c_conf) {
|
||||
debug(LOG_ERR, "Error: c_conf is NULL");
|
||||
return;
|
||||
}
|
||||
@@ -107,120 +129,176 @@ 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",
|
||||
ps->proxy_name);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
new_ftp_data_proxy_service(ps);
|
||||
}
|
||||
|
||||
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)
|
||||
// create a new proxy service with suffix "_ftp_data_proxy"
|
||||
static void new_ftp_data_proxy_service(struct proxy_service *ftp_ps)
|
||||
{
|
||||
struct proxy_client *pc = NULL;
|
||||
struct proxy_service *ps = NULL;
|
||||
char *ftp_data_proxy_name = get_ftp_data_proxy_name((const char *)ftp_ps->proxy_name);
|
||||
|
||||
if (strcmp(section, "common") == 0)
|
||||
HASH_FIND_STR(p_services, ftp_data_proxy_name, ps);
|
||||
if (!ps) {
|
||||
ps = new_proxy_service(ftp_data_proxy_name);
|
||||
if (! ps) {
|
||||
debug(LOG_ERR,
|
||||
"cannot create ftp data proxy service, it should not happenned!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ps->proxy_type = strdup("tcp");
|
||||
ps->remote_port = ftp_ps->remote_data_port;
|
||||
ps->local_ip = ftp_ps->local_ip;
|
||||
ps->local_port = 0; //will be init in working tunnel connectting
|
||||
|
||||
HASH_ADD_KEYPTR(hh, p_services, ps->proxy_name, strlen(ps->proxy_name), ps);
|
||||
}
|
||||
|
||||
free(ftp_data_proxy_name);
|
||||
}
|
||||
|
||||
static int
|
||||
proxy_service_handler(void *user, const char *sect, const char *nm, const char *value)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
|
||||
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("remote_data_port")) {
|
||||
ps->remote_data_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 +308,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 +359,48 @@ 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;
|
||||
config->server_ip = NULL;
|
||||
}
|
||||
|
||||
// it should be free after using
|
||||
// because of assert it will never return NULL
|
||||
char *get_ftp_data_proxy_name(const char *ftp_proxy_name)
|
||||
{
|
||||
char *ftp_tail_data_name = FTP_DATA_PROXY_SUFFIX;
|
||||
char *ftp_data_proxy_name = (char *)calloc(1,
|
||||
strlen(ftp_proxy_name)+strlen(ftp_tail_data_name)+1);
|
||||
assert(ftp_data_proxy_name);
|
||||
|
||||
snprintf(ftp_data_proxy_name,
|
||||
strlen(ftp_proxy_name) + strlen(ftp_tail_data_name) + 1,
|
||||
"%s%s",
|
||||
ftp_proxy_name,
|
||||
ftp_tail_data_name);
|
||||
|
||||
return ftp_data_proxy_name;
|
||||
}
|
||||
|
||||
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 +419,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();
|
||||
}
|
||||
|
||||
18
config.h
18
config.h
@@ -26,24 +26,27 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
|
||||
#define FTP_DATA_PROXY_SUFFIX "_ftp_data_proxy"
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
// common config
|
||||
struct common_conf {
|
||||
char *server_addr; /* default 0.0.0.0 */
|
||||
char *server_ip;
|
||||
int server_port; /* default 7000 */
|
||||
char *http_proxy;
|
||||
char *log_file; /* default consol */
|
||||
@@ -54,9 +57,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();
|
||||
|
||||
@@ -65,5 +71,7 @@ void free_base_config(struct base_conf *bconf);
|
||||
struct proxy_client *get_all_pc();
|
||||
|
||||
void load_config(const char *confile);
|
||||
char *get_ftp_data_proxy_name(const char *ftp_proxy_name);
|
||||
void set_common_server_ip(const char *ip);
|
||||
|
||||
#endif
|
||||
#endif //_CONFIG_H_
|
||||
|
||||
18
const.h
18
const.h
@@ -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
|
||||
|
||||
41
control.h
41
control.h
@@ -24,13 +24,50 @@
|
||||
@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);
|
||||
#endif //_CONTROL_H_
|
||||
281
crypto.c
Normal file
281
crypto.c
Normal 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
33
crypto.h
Normal 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
399
fastpbkdf2.c
Normal 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
71
fastpbkdf2.h
Normal 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
70
frame.c
Normal 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
40
frame.h
Normal 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
2
install_manifest.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
/usr/bin/xfrpc
|
||||
/usr/bin/xfrp_test_server
|
||||
89
login.c
Normal file
89
login.c
Normal 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
38
login.h
Normal 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
7
main.c
@@ -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();
|
||||
}
|
||||
|
||||
358
msg.c
358
msg.c
@@ -28,109 +28,286 @@
|
||||
#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"
|
||||
#include "client.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 (is_ftp_proxy(np_req)) {
|
||||
JSON_MARSHAL_TYPE(j_np_req, "remote_data_port", int, np_req->remote_data_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 +317,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;
|
||||
}
|
||||
84
msg.h
84
msg.h
@@ -24,45 +24,81 @@
|
||||
@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;
|
||||
char *msg;
|
||||
};
|
||||
|
||||
// messages between control connections of frpc and frps
|
||||
struct control_request {
|
||||
int type;
|
||||
char *proxy_name;
|
||||
char *auth_key;
|
||||
int use_encryption;
|
||||
int use_gzip;
|
||||
int pool_count;
|
||||
|
||||
int privilege_mode;
|
||||
char *privilege_key;
|
||||
char *proxy_type;
|
||||
int remote_port;
|
||||
char *custom_domains;
|
||||
char *locations;
|
||||
char *host_header_rewrite;
|
||||
char *http_username;
|
||||
char *http_password;
|
||||
char *subdomain;
|
||||
long timestamp;
|
||||
};
|
||||
|
||||
|
||||
struct control_response {
|
||||
int type;
|
||||
int code;
|
||||
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_
|
||||
36
proxy.c
Normal file
36
proxy.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
|
||||
struct proxy *new_proxy_buf(struct bufferevent *bev)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)calloc(1, sizeof(struct proxy));
|
||||
assert(p);
|
||||
p->bev = bev;
|
||||
p->remote_data_port = -1;
|
||||
p->proxy_name = NULL;
|
||||
return p;
|
||||
}
|
||||
|
||||
void free_proxy(struct proxy *p)
|
||||
{
|
||||
SAFE_FREE(p->proxy_name);
|
||||
SAFE_FREE(p);
|
||||
}
|
||||
37
proxy.h
Normal file
37
proxy.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef _PROXY_H_
|
||||
#define _PROXY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
|
||||
#define IP_LEN 16
|
||||
|
||||
struct ftp_pasv {
|
||||
int code;
|
||||
char ftp_server_ip[IP_LEN];
|
||||
int ftp_server_port;
|
||||
};
|
||||
|
||||
struct proxy {
|
||||
struct bufferevent *bev;
|
||||
char *proxy_name;
|
||||
int remote_data_port; //used in ftp proxy
|
||||
};
|
||||
|
||||
void tcp_proxy_c2s_cb(struct bufferevent *bev, void *ctx);
|
||||
void tcp_proxy_s2c_cb(struct bufferevent *bev, void *ctx);
|
||||
void ftp_proxy_c2s_cb(struct bufferevent *bev, void *ctx);
|
||||
void ftp_proxy_s2c_cb(struct bufferevent *bev, void *ctx);
|
||||
struct proxy *new_proxy_buf(struct bufferevent *bev);
|
||||
void free_proxy(struct proxy *p);
|
||||
void set_ftp_data_proxy_tunnel(const char *ftp_proxy_name,
|
||||
struct ftp_pasv *local_fp,
|
||||
struct ftp_pasv *remote_fp);
|
||||
#endif //_PROXY_H_
|
||||
267
proxy_ftp.c
Normal file
267
proxy_ftp.c
Normal file
@@ -0,0 +1,267 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
#include "client.h"
|
||||
|
||||
#define FTP_PRO_BUF 256
|
||||
#define FTP_PASV_PORT_BLOCK 256
|
||||
|
||||
static struct ftp_pasv *new_ftp_pasv();
|
||||
static void free_ftp_pasv(struct ftp_pasv *fp);
|
||||
static struct ftp_pasv * pasv_unpack(char *data);
|
||||
static size_t pasv_pack(struct ftp_pasv *fp, char **pack_p);
|
||||
|
||||
void set_ftp_data_proxy_tunnel(const char *ftp_proxy_name,
|
||||
struct ftp_pasv *local_fp,
|
||||
struct ftp_pasv *remote_fp)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
char *ftp_data_proxy_name = get_ftp_data_proxy_name(ftp_proxy_name);
|
||||
|
||||
struct proxy_service *p_services = get_all_proxy_services();
|
||||
HASH_FIND_STR(p_services, ftp_data_proxy_name, ps);
|
||||
if (!ps) {
|
||||
debug(LOG_ERR,
|
||||
"error: ftp data proxy not inserted in proxy-service queue, it should not happend!");
|
||||
goto FTP_DATA_PROXY_TUNNEL_END;
|
||||
}
|
||||
|
||||
ps->local_port = local_fp->ftp_server_port;
|
||||
ps->local_ip = strdup(local_fp->ftp_server_ip);
|
||||
assert(ps->local_ip);
|
||||
|
||||
ps->remote_port = remote_fp->ftp_server_port;
|
||||
|
||||
debug(LOG_DEBUG,
|
||||
"set ftp proxy DATA port [local:remote] = [%d:%d]",
|
||||
ps->local_port, ps->remote_port);
|
||||
|
||||
FTP_DATA_PROXY_TUNNEL_END:
|
||||
free(ftp_data_proxy_name);
|
||||
}
|
||||
|
||||
// read from client-working host port
|
||||
void ftp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
assert(p);
|
||||
struct bufferevent *partner = p->bev;
|
||||
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
len = evbuffer_get_length(src);
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
dst = bufferevent_get_output(partner);
|
||||
assert(dst);
|
||||
|
||||
unsigned char *buf = calloc(1, len);
|
||||
assert(buf);
|
||||
size_t read_n = 0;
|
||||
read_n = evbuffer_remove(src, buf, len);
|
||||
|
||||
// #define FTP_P_DEBUG 1
|
||||
#ifdef FTP_P_DEBUG
|
||||
char *dbg_buf = calloc(1, read_n * 7 + 1);
|
||||
assert(dbg_buf);
|
||||
unsigned int i = 0;
|
||||
for(i = 0; i<read_n && ((2 * i) < (read_n * 2 + 1)); i++) {
|
||||
snprintf(dbg_buf + 7*i, 8, "%3u[%c] ",
|
||||
(unsigned char)buf[i],
|
||||
(unsigned char)buf[i]);
|
||||
}
|
||||
debug(LOG_DEBUG, "FTP Client RECV ctl byte:%s", dbg_buf);
|
||||
debug(LOG_DEBUG, "FTP Client RECV ctl stri:%s", buf);
|
||||
SAFE_FREE(dbg_buf);
|
||||
#endif //FTP_P_DEBUG
|
||||
|
||||
struct ftp_pasv *local_fp = pasv_unpack((char *)buf);
|
||||
|
||||
if (local_fp) {
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct ftp_pasv *r_fp = new_ftp_pasv();
|
||||
r_fp->code = local_fp->code;
|
||||
|
||||
if (! c_conf->server_ip) {
|
||||
debug(LOG_ERR, "error: FTP proxy without server ip!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
strncpy(r_fp->ftp_server_ip, c_conf->server_ip, IP_LEN);
|
||||
r_fp->ftp_server_port = p->remote_data_port;
|
||||
|
||||
if (r_fp->ftp_server_port <= 0) {
|
||||
debug(LOG_ERR, "error: remote ftp data port is not init!");
|
||||
goto FTP_C2S_CB_END;
|
||||
}
|
||||
|
||||
char *pasv_msg = NULL;
|
||||
size_t pack_len = pasv_pack(r_fp, &pasv_msg);
|
||||
if ( ! pack_len){
|
||||
debug(LOG_ERR, "error: ftp proxy replace failed!");
|
||||
SAFE_FREE(pasv_msg);
|
||||
goto FTP_C2S_CB_END;
|
||||
}
|
||||
|
||||
#ifdef FTP_P_DEBUG
|
||||
debug(LOG_DEBUG, "ftp pack result:%s", pasv_msg);
|
||||
#endif //FTP_P_DEBUG
|
||||
|
||||
set_ftp_data_proxy_tunnel(p->proxy_name, local_fp, r_fp);
|
||||
evbuffer_add(dst, pasv_msg, pack_len);
|
||||
SAFE_FREE(pasv_msg);
|
||||
} else {
|
||||
evbuffer_add(dst, buf, read_n);
|
||||
}
|
||||
|
||||
FTP_C2S_CB_END:
|
||||
SAFE_FREE(buf);
|
||||
free_ftp_pasv(local_fp);
|
||||
return;
|
||||
}
|
||||
|
||||
void ftp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
tcp_proxy_s2c_cb(bev, ctx);
|
||||
}
|
||||
|
||||
static struct ftp_pasv *pasv_unpack(char *data)
|
||||
{
|
||||
char cd_buf[4] = {0};
|
||||
snprintf(cd_buf, 4, "%s", data);
|
||||
int code = atoi(cd_buf);
|
||||
if (code != 227 && code != 211 && code != 229)
|
||||
return NULL;
|
||||
|
||||
struct ftp_pasv *fp = new_ftp_pasv();
|
||||
assert(fp);
|
||||
|
||||
fp->code = code;
|
||||
switch(fp->code) {
|
||||
case 227:
|
||||
{
|
||||
int i = 0, ip_i = 0, port_i = 0, ip_start = 0, comma_n = 0;
|
||||
char port[2][4] = { {0}, {0} };
|
||||
for (i=0; i<strlen(data) && ip_i<IP_LEN; i++) {
|
||||
if (data[i] == '(') {
|
||||
ip_start = 1;
|
||||
continue;
|
||||
}
|
||||
if (! ip_start)
|
||||
continue;
|
||||
|
||||
if (data[i] == ')')
|
||||
break;
|
||||
|
||||
if (data[i] == ','){
|
||||
comma_n++;
|
||||
port_i = 0;
|
||||
if (comma_n < 4){
|
||||
fp->ftp_server_ip[ip_i] = '.';
|
||||
ip_i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (comma_n >= 4 && port_i < 4) {
|
||||
port[comma_n - 4][port_i] = data[i];
|
||||
port_i++;
|
||||
continue;
|
||||
}
|
||||
fp->ftp_server_ip[ip_i] = data[i];
|
||||
ip_i++;
|
||||
}
|
||||
|
||||
fp->ftp_server_port = atoi(port[0]) * FTP_PASV_PORT_BLOCK + atoi(port[1]);
|
||||
debug(LOG_DEBUG, "ftp pasv unpack:[%s:%d]", fp->ftp_server_ip, fp->ftp_server_port);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
free_ftp_pasv(fp);
|
||||
break;
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
// the value returned need FREE after using
|
||||
static size_t pasv_pack(struct ftp_pasv *fp, char **pack_p)
|
||||
{
|
||||
*pack_p = (char *)calloc(1, FTP_PRO_BUF);
|
||||
assert(*pack_p);
|
||||
size_t pack_len = 0;
|
||||
|
||||
switch (fp->code){
|
||||
case 227:
|
||||
{
|
||||
char ftp_ip[IP_LEN] = {0};
|
||||
int i =0;
|
||||
for (i=0; i<strlen(fp->ftp_server_ip) && i < IP_LEN; i++) {
|
||||
if (fp->ftp_server_ip[i] == '.') {
|
||||
ftp_ip[i] = ',';
|
||||
continue;
|
||||
}
|
||||
|
||||
ftp_ip[i] = fp->ftp_server_ip[i];
|
||||
}
|
||||
snprintf(*pack_p,
|
||||
FTP_PRO_BUF,
|
||||
"227 Entering Passive Mode (%s,%d,%d).\n",
|
||||
ftp_ip,
|
||||
fp->ftp_server_port / FTP_PASV_PORT_BLOCK,
|
||||
fp->ftp_server_port % FTP_PASV_PORT_BLOCK);
|
||||
|
||||
pack_len = strlen(*pack_p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
debug(LOG_DEBUG, "ftp pasv protocol data not supportted in pasv_pack");
|
||||
free(*pack_p);
|
||||
break;
|
||||
}
|
||||
|
||||
return pack_len;
|
||||
}
|
||||
|
||||
// need be free after using
|
||||
static struct ftp_pasv *new_ftp_pasv()
|
||||
{
|
||||
struct ftp_pasv *fp = (struct ftp_pasv *)calloc(1, sizeof(struct ftp_pasv));
|
||||
if (! fp)
|
||||
return NULL;
|
||||
|
||||
memset(fp->ftp_server_ip, 0, IP_LEN);
|
||||
fp->ftp_server_port = -1;
|
||||
fp->code = -1;
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
// can be used to free NULL pointer also
|
||||
static void free_ftp_pasv(struct ftp_pasv *fp)
|
||||
{
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
SAFE_FREE(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
44
proxy_tcp.c
Normal file
44
proxy_tcp.c
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
|
||||
// read from client-working host port
|
||||
void tcp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
len = evbuffer_get_length(src);
|
||||
if (len > 0) {
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
struct evbuffer *src, *dst;
|
||||
src = bufferevent_get_input(bev);
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
52
session.c
Normal file
52
session.c
Normal 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
11
session.h
Normal 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
167
testfastpbkdf2.c
Normal 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;
|
||||
}
|
||||
31
utils.c
Normal file
31
utils.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
// is_valid_ip_address:
|
||||
// return 0:ipaddress unlegal
|
||||
int is_valid_ip_address(const char *ip_address)
|
||||
{
|
||||
struct sockaddr_in sa;
|
||||
int result = inet_pton(AF_INET, ip_address, &(sa.sin_addr));
|
||||
return result;
|
||||
}
|
||||
10
utils.h
Normal file
10
utils.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
|
||||
void s_sleep(unsigned int s, unsigned int u);
|
||||
|
||||
// is_valid_ip_address:
|
||||
// return 0:ipaddress unlegal
|
||||
int is_valid_ip_address(const char *ip_address);
|
||||
|
||||
#endif //_UTILS_H_
|
||||
@@ -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_
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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_
|
||||
Reference in New Issue
Block a user