forked from dagwieers/vsftpd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sslslave.c
128 lines (126 loc) · 3.5 KB
/
sslslave.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
120
121
122
123
124
125
126
127
128
/*
* Part of Very Secure FTPd
* Licence: GPL v2
* Author: Chris Evans
* sslslave.c
*/
#include "sslslave.h"
#include "session.h"
#include "privsock.h"
#include "tunables.h"
#include "sysutil.h"
#include "sysdeputil.h"
#include "utility.h"
#include "ssl.h"
#include "readwrite.h"
#include "defs.h"
void
ssl_slave(struct vsf_session* p_sess)
{
struct mystr data_str = INIT_MYSTR;
str_reserve(&data_str, VSFTP_DATA_BUFSIZE);
/* Before becoming the slave, clear the alarm for the FTP protocol. */
vsf_sysutil_clear_alarm();
/* No need for any further communications with the privileged parent. */
priv_sock_set_parent_context(p_sess);
if (tunable_setproctitle_enable)
{
vsf_sysutil_setproctitle("SSL handler");
}
while (1)
{
char cmd = priv_sock_get_cmd(p_sess->ssl_slave_fd);
int ret;
if (cmd == PRIV_SOCK_GET_USER_CMD)
{
ret = ftp_getline(p_sess, &p_sess->ftp_cmd_str,
p_sess->p_control_line_buf);
priv_sock_send_int(p_sess->ssl_slave_fd, ret);
if (ret >= 0)
{
priv_sock_send_str(p_sess->ssl_slave_fd, &p_sess->ftp_cmd_str);
}
}
else if (cmd == PRIV_SOCK_WRITE_USER_RESP)
{
priv_sock_get_str(p_sess->ssl_slave_fd, &p_sess->ftp_cmd_str);
ret = ftp_write_str(p_sess, &p_sess->ftp_cmd_str, kVSFRWControl);
priv_sock_send_int(p_sess->ssl_slave_fd, ret);
}
else if (cmd == PRIV_SOCK_DO_SSL_HANDSHAKE)
{
char result = PRIV_SOCK_RESULT_BAD;
if (p_sess->data_fd != -1 || p_sess->p_data_ssl != 0)
{
bug("state not clean");
}
p_sess->data_fd = priv_sock_recv_fd(p_sess->ssl_slave_fd);
ret = ssl_accept(p_sess, p_sess->data_fd);
if (ret == 1)
{
result = PRIV_SOCK_RESULT_OK;
}
else
{
vsf_sysutil_close(p_sess->data_fd);
p_sess->data_fd = -1;
}
priv_sock_send_result(p_sess->ssl_slave_fd, result);
}
else if (cmd == PRIV_SOCK_DO_SSL_READ)
{
int size = priv_sock_get_int(p_sess->ssl_slave_fd);
if (size <= 0 || size > VSFTP_DATA_BUFSIZE)
{
bug("bad size");
}
if (p_sess->data_fd == -1 || p_sess->p_data_ssl == 0)
{
bug("invalid state");
}
str_trunc(&data_str, (unsigned int) size);
ret = ssl_read_into_str(p_sess, p_sess->p_data_ssl, &data_str);
priv_sock_send_int(p_sess->ssl_slave_fd, ret);
priv_sock_send_str(p_sess->ssl_slave_fd, &data_str);
}
else if (cmd == PRIV_SOCK_DO_SSL_WRITE)
{
if (p_sess->data_fd == -1 || p_sess->p_data_ssl == 0)
{
bug("invalid state");
}
priv_sock_get_str(p_sess->ssl_slave_fd, &data_str);
ret = ssl_write(p_sess->p_data_ssl,
str_getbuf(&data_str),
str_getlen(&data_str));
priv_sock_send_int(p_sess->ssl_slave_fd, ret);
}
else if (cmd == PRIV_SOCK_DO_SSL_CLOSE)
{
char result = PRIV_SOCK_RESULT_BAD;
if (p_sess->data_fd == -1 && p_sess->p_data_ssl == 0)
{
result = PRIV_SOCK_RESULT_OK;
}
else
{
if (p_sess->data_fd == -1 || p_sess->p_data_ssl == 0)
{
bug("invalid state");
}
ret = ssl_data_close(p_sess);
if (ret == 1)
{
result = PRIV_SOCK_RESULT_OK;
}
vsf_sysutil_close(p_sess->data_fd);
p_sess->data_fd = -1;
}
priv_sock_send_result(p_sess->ssl_slave_fd, result);
}
else
{
die("bad request in process_ssl_slave_req");
}
}
}