1 /*
2  * Part of Very Secure FTPd
3  * Licence: GPL v2
4  * Author: Chris Evans
5  * readwrite.c
6  *
7  * Routines to encapsulate the underlying read / write mechanism (OpenSSL vs.
8  * plain read()/write()).
9  */
10 
11 #include "readwrite.h"
12 #include "session.h"
13 #include "netstr.h"
14 #include "ssl.h"
15 #include "privsock.h"
16 #include "defs.h"
17 #include "sysutil.h"
18 
19 static int plain_peek_adapter(struct vsf_session* p_sess,
20                               char* p_buf,
21                               unsigned int len);
22 static int plain_read_adapter(struct vsf_session* p_sess,
23                               char* p_buf,
24                               unsigned int len);
25 static int ssl_peek_adapter(struct vsf_session* p_sess,
26                             char* p_buf,
27                             unsigned int len);
28 static int ssl_read_adapter(struct vsf_session* p_sess,
29                             char* p_buf,
30                             unsigned int len);
31 
32 int
ftp_write_str(const struct vsf_session * p_sess,const struct mystr * p_str,enum EVSFRWTarget target)33 ftp_write_str(const struct vsf_session* p_sess, const struct mystr* p_str,
34               enum EVSFRWTarget target)
35 {
36   if (target == kVSFRWData)
37   {
38     if (p_sess->data_use_ssl && p_sess->ssl_slave_active)
39     {
40       int ret = -1;
41       int written;
42       priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_WRITE);
43       priv_sock_send_str(p_sess->ssl_consumer_fd, p_str);
44       written = priv_sock_get_int(p_sess->ssl_consumer_fd);
45       if (written > 0 && written == (int) str_getlen(p_str))
46       {
47         ret = 0;
48       }
49       return ret;
50     }
51     else if (p_sess->data_use_ssl)
52     {
53       return ssl_write_str(p_sess->p_data_ssl, p_str);
54     }
55     else
56     {
57       return str_netfd_write(p_str, p_sess->data_fd);
58     }
59   }
60   else
61   {
62     if (p_sess->control_use_ssl && p_sess->ssl_slave_active)
63     {
64       priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_WRITE_USER_RESP);
65       priv_sock_send_str(p_sess->ssl_consumer_fd, p_str);
66       return priv_sock_get_int(p_sess->ssl_consumer_fd);
67     }
68     else if (p_sess->control_use_ssl)
69     {
70       return ssl_write_str(p_sess->p_control_ssl, p_str);
71     }
72     else
73     {
74       return str_netfd_write(p_str, VSFTP_COMMAND_FD);
75     }
76   }
77 }
78 
79 int
ftp_read_data(struct vsf_session * p_sess,char * p_buf,unsigned int len)80 ftp_read_data(struct vsf_session* p_sess, char* p_buf, unsigned int len)
81 {
82   if (p_sess->data_use_ssl && p_sess->ssl_slave_active)
83   {
84     int ret;
85     priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_READ);
86     priv_sock_send_int(p_sess->ssl_consumer_fd, len);
87     ret = priv_sock_get_int(p_sess->ssl_consumer_fd);
88     priv_sock_recv_buf(p_sess->ssl_consumer_fd, p_buf, len);
89     /* Need to do this here too because it is useless in the slave process. */
90     vsf_sysutil_check_pending_actions(kVSFSysUtilIO, ret, p_sess->data_fd);
91     return ret;
92   }
93   else if (p_sess->data_use_ssl)
94   {
95     return ssl_read(p_sess, p_sess->p_data_ssl, p_buf, len);
96   }
97   else
98   {
99     return vsf_sysutil_read(p_sess->data_fd, p_buf, len);
100   }
101 }
102 
103 int
ftp_write_data(const struct vsf_session * p_sess,const char * p_buf,unsigned int len)104 ftp_write_data(const struct vsf_session* p_sess, const char* p_buf,
105                unsigned int len)
106 {
107   if (p_sess->data_use_ssl && p_sess->ssl_slave_active)
108   {
109     int ret;
110     priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_WRITE);
111     priv_sock_send_buf(p_sess->ssl_consumer_fd, p_buf, len);
112     ret = priv_sock_get_int(p_sess->ssl_consumer_fd);
113     /* Need to do this here too because it is useless in the slave process. */
114     vsf_sysutil_check_pending_actions(kVSFSysUtilIO, ret, p_sess->data_fd);
115     return ret;
116   }
117   else if (p_sess->data_use_ssl)
118   {
119     return ssl_write(p_sess->p_data_ssl, p_buf, len);
120   }
121   else
122   {
123     return vsf_sysutil_write_loop(p_sess->data_fd, p_buf, len);
124   }
125 }
126 
127 int
ftp_getline(struct vsf_session * p_sess,struct mystr * p_str,char * p_buf)128 ftp_getline(struct vsf_session* p_sess, struct mystr* p_str, char* p_buf)
129 {
130   if (p_sess->control_use_ssl && p_sess->ssl_slave_active)
131   {
132     int ret;
133     priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_GET_USER_CMD);
134     ret = priv_sock_get_int(p_sess->ssl_consumer_fd);
135     if (ret >= 0)
136     {
137       priv_sock_get_str(p_sess->ssl_consumer_fd, p_str);
138     }
139     return ret;
140   }
141   else
142   {
143     str_netfd_read_t p_peek = plain_peek_adapter;
144     str_netfd_read_t p_read = plain_read_adapter;
145     if (p_sess->control_use_ssl)
146     {
147       p_peek = ssl_peek_adapter;
148       p_read = ssl_read_adapter;
149     }
150     return str_netfd_alloc(p_sess,
151                            p_str,
152                            '\n',
153                            p_buf,
154                            VSFTP_MAX_COMMAND_LINE,
155                            p_peek,
156                            p_read);
157   }
158 }
159 
160 static int
plain_peek_adapter(struct vsf_session * p_sess,char * p_buf,unsigned int len)161 plain_peek_adapter(struct vsf_session* p_sess, char* p_buf, unsigned int len)
162 {
163   (void) p_sess;
164   return vsf_sysutil_recv_peek(VSFTP_COMMAND_FD, p_buf, len);
165 }
166 
167 static int
plain_read_adapter(struct vsf_session * p_sess,char * p_buf,unsigned int len)168 plain_read_adapter(struct vsf_session* p_sess, char* p_buf, unsigned int len)
169 {
170   (void) p_sess;
171   return vsf_sysutil_read_loop(VSFTP_COMMAND_FD, p_buf, len);
172 }
173 
174 static int
ssl_peek_adapter(struct vsf_session * p_sess,char * p_buf,unsigned int len)175 ssl_peek_adapter(struct vsf_session* p_sess, char* p_buf, unsigned int len)
176 {
177   return ssl_peek(p_sess, p_sess->p_control_ssl, p_buf, len);
178 }
179 
180 static int
ssl_read_adapter(struct vsf_session * p_sess,char * p_buf,unsigned int len)181 ssl_read_adapter(struct vsf_session* p_sess, char* p_buf, unsigned int len)
182 {
183   return ssl_read(p_sess, p_sess->p_control_ssl, p_buf, len);
184 }
185