-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathprivparent.c
120 lines (107 loc) · 3.18 KB
/
privparent.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "privparent.h"
#include "privsock.h"
#include "tunable.h"
#include "common.h"
static void privop_pasv_get_data_sock(session_t *sess);
static void privop_pasv_active(session_t *sess);
static void privop_pasv_listen(session_t *sess);
static void privop_pasv_accept(session_t *sess);
int capset(cap_user_header_t hdrp, const cap_user_data_t datap){
return syscall(__NR_capset,hdrp,datap);
}
void get_privilege(){
//改变权限
struct passwd *pw = getpwnam("nobody");
if(pw == NULL) return;
if(setegid(pw->pw_gid) < 0) ERR_EXIT("setegid");
if(seteuid(pw->pw_uid) < 0) ERR_EXIT("seteuid");
//add capability
struct __user_cap_header_struct cap_header;
struct __user_cap_data_struct cap_data;
memset(&cap_header, 0 ,sizeof(cap_header));
memset(&cap_data, 0, sizeof(cap_data));
cap_header.version = _LINUX_CAPABILITY_VERSION_1; //x64
cap_header.pid = 0;
__u32 cap_mask = 0;
cap_mask |= (1 << CAP_NET_BIND_SERVICE);
cap_data.effective = cap_data.permitted = cap_mask;
cap_data.inheritable = 0;
//end_add
capset(&cap_header, &cap_data);
}
void handle_parent(session_t *sess){
get_privilege();
while(1){
char cmd = priv_sock_get_cmd(sess->parent_fd);
//解析内部命令
//处理内部命令
switch(cmd){
case PRIV_SOCK_GET_DATA_SOCK:
privop_pasv_get_data_sock(sess);
break;
case PRIV_SOCK_PASV_ACTIVE:
privop_pasv_active(sess);
break;
case PRIV_SOCK_PASV_LISTEN:
privop_pasv_listen(sess);
break;
case PRIV_SOCK_PASV_ACCEPT:
privop_pasv_accept(sess);
break;
}
}
}
void privop_pasv_get_data_sock(session_t *sess){
unsigned short port = (unsigned short)priv_sock_get_int(sess->parent_fd);
char ip[16] = {0};
priv_sock_recv_buf(sess->parent_fd, ip, sizeof(ip));
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
inet_aton(ip, &addr.sin_addr);
int fd = tcp_client(20);
if(fd == -1){
priv_sock_send_cmd(sess->parent_fd, PRIV_SOCK_RESULT_BAD);
return;
}
//connect
if(connect_timeout(fd, &addr, tunable_connect_timeout) < 0){
priv_sock_send_cmd(sess->parent_fd, PRIV_SOCK_RESULT_BAD);
close(fd);
return;
}
printf("=====Transfer Success====\n");
priv_sock_send_cmd(sess->parent_fd, PRIV_SOCK_RESULT_OK);
priv_sock_send_fd(sess->parent_fd, fd);
close(fd);
}
void privop_pasv_active(session_t *sess){
int active = 0;
if(sess->pasv_listen_fd != -1) active = 1;
priv_sock_send_int(sess->parent_fd, active);
}
void privop_pasv_listen(session_t *sess){
char ip[16] = {0};
getlocalip(ip);
int fd = tcp_server(ip, 0);
struct sockaddr_in addr;
socklen_t addrlen = sizeof(struct sockaddr);
if(getsockname(fd, (struct sockaddr*)&addr, &addrlen) < 0)
ERR_EXIT("getsockname");
unsigned short port = ntohs(addr.sin_port);
priv_sock_send_int(sess->parent_fd, (int)port);
sess->pasv_listen_fd = fd;
}
void privop_pasv_accept(session_t *sess){
int conn = accept_timeout(sess->pasv_listen_fd, NULL, tunable_accept_timeout);
close(sess->pasv_listen_fd);
sess->pasv_listen_fd = -1;
if(conn < 0){
priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD);
return;
}
priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_OK);
priv_sock_send_fd(sess->parent_fd, conn);
close(conn);
}