1 /*
2  * part of owftpd By Paul H Alfille
3  * The whole is GPLv2 licenced though the ftp code was more liberally licenced when first used.
4  */
5 
6 #ifndef OWFTPD_H
7 #define OWFTPD_H
8 
9 #include <config.h>
10 #include "owfs_config.h"
11 #include "ow.h"
12 #include "ow_connection.h"
13 
14 #ifdef HAVE_LIMITS_H
15 #include <limits.h>
16 #endif
17 #include <arpa/inet.h>
18 #include <netinet/tcp.h>
19 #include <assert.h>
20 
21 /* _x_ must be a pointer to a sockaddr structure */
22 
23 #define SAFAM(_x_)  (((struct sockaddr *)(_x_))->sa_family)
24 #define cSAFAM(_x_)  (((const struct sockaddr *)(_x_))->sa_family)
25 
26 #define SIN4ADDR(_x_)   (((struct sockaddr_in *)(_x_))->sin_addr)
27 #define SIN4PORT(_x_)   (((struct sockaddr_in *)(_x_))->sin_port)
28 #define SIN6ADDR(_x_)   (((struct sockaddr_in6 *)(_x_))->sin6_addr)
29 #define SIN6PORT(_x_)   (((struct sockaddr_in6 *)(_x_))->sin6_port)
30 #define cSIN4ADDR(_x_)   (((const struct sockaddr_in *)(_x_))->sin_addr)
31 #define cSIN4PORT(_x_)   (((const struct sockaddr_in *)(_x_))->sin_port)
32 #define cSIN6ADDR(_x_)   (((const struct sockaddr_in6 *)(_x_))->sin6_addr)
33 #define cSIN6PORT(_x_)   (((const struct sockaddr_in6 *)(_x_))->sin6_port)
34 
35 #ifdef INET6
36 #define SINADDR(_x_)    ((SAFAM(_x_)==AF_INET6) ? SIN6ADDR(_x_) : SIN4ADDR(_x_))
37 #define SINPORT(_x_)    ((SAFAM(_x_)==AF_INET6) ? SIN6PORT(_x_) : SIN4PORT(_x_))
38 #define cSINADDR(_x_)    ((cSAFAM(_x_)==AF_INET6) ? cSIN6ADDR(_x_) : cSIN4ADDR(_x_))
39 #define cSINPORT(_x_)    ((cSAFAM(_x_)==AF_INET6) ? cSIN6PORT(_x_) : cSIN4PORT(_x_))
40 #else
41 #define SINADDR(_x_)    SIN4ADDR(_x_)
42 #define SINPORT(_x_)    SIN4PORT(_x_)
43 #define cSINADDR(_x_)    cSIN4ADDR(_x_)
44 #define cSINPORT(_x_)    cSIN4PORT(_x_)
45 #endif
46 
47 #ifndef INET_ADDRSTRLEN
48 #define INET_ADDRSTRLEN 16
49 #endif
50 
51 #ifndef INET6_ADDRSTRLEN
52 #define INET6_ADDRSTRLEN 46
53 #endif
54 
55 #ifdef INET6
56 #define IP6_ADDRSTRLEN INET6_ADDRSTRLEN
57 #define IP4_ADDRSTRLEN INET_ADDRSTRLEN
58 #define IP_ADDRSTRLEN INET6_ADDRSTRLEN
59 #else
60 #define IP_ADDRSTRLEN INET_ADDRSTRLEN
61 #endif
62 
63 #if defined(INET6) && defined(HAVE_STRUCT_SOCKADDR_STORAGE)
64 typedef struct sockaddr_storage sockaddr_storage_t;
65 #define SSFAM(_x_)  (((sockaddr_storage_t *)(_x_))->ss_family)
66 #define cSSFAM(_x_)  (((const sockaddr_storage_t *)(_x_))->ss_family)
67 #else
68 typedef struct sockaddr_in sockaddr_storage_t;
69 #define SSFAM(_x_)  (((sockaddr_storage_t *)(_x_))->sin_family)
70 #define cSSFAM(_x_)  (((const sockaddr_storage_t *)(_x_))->sin_family)
71 #endif
72 
73 #ifdef HAVE_BROKEN_SS_FAMILY
74 #undef SSFAM
75 #undef cSSFAM
76 #define SSFAM(_x_)  (((sockaddr_storage_t *)(_x_))->__ss_family)
77 #define cSSFAM(_x_)  (((const sockaddr_storage_t *)(_x_))->__ss_family)
78 #endif
79 
80 
81 /* address to listen on (use NULL to listen on all addresses) */
82 #define FTP_ADDRESS NULL
83 
84 /* default port FTP server listens on (use 0 to listen on default port) */
85 #define FTP_PORT 0
86 
87 /* ranges possible for command-line specified port numbers */
88 #define MIN_PORT 0
89 #define MAX_PORT 65535
90 
91 /* default port FTP server listens on (use 0 to listen on default port) */
92 #define DEFAULT_PORTNAME "0.0.0.0:21"
93 
94 /* bounds on command-line specified number of clients */
95 #define MIN_NUM_CLIENTS 1
96 #define MAX_NUM_CLIENTS 300
97 
98 enum parse_status_e {
99 	parse_status_init,			// need to test for initial /
100 	parse_status_init2,			// need to test for virginity (no wildness)
101 	parse_status_back,			// .. still allowed
102 	parse_status_next,			// figure out this level
103 	parse_status_last,			// last level
104 	parse_status_tame,			// no wildcard at all
105 };
106 
107 enum file_list_e {
108 	file_list_list,
109 	file_list_nlst,
110 };
111 
112 struct file_parse_s {
113 	ASCII buffer[PATH_MAX + 1];
114 	ASCII *rest;
115 	enum parse_status_e pse;	// state machine
116 	enum file_list_e fle;		// long or short listing flag
117 	FILE_DESCRIPTOR_OR_ERROR out;					// file descriptor to send result
118 	int ret;					// return status
119 	int start;
120 };
121 
122 struct cd_parse_s {
123 	ASCII buffer[PATH_MAX + 1];	// working copy of current directory
124 	ASCII *rest;
125 	enum parse_status_e pse;	// state machine
126 	int ret;					// return status
127 	int solutions;				// is the solution unique?
128 	ASCII *dir;
129 };
130 
131 void FileLexParse(struct file_parse_s *fps);
132 void FileLexCD(struct cd_parse_s *cps);
133 
134 /* each watched thread gets one of these structures */
135 struct watched_s {
136 	/* thread to monitor */
137 	pthread_t watched_thread;
138 
139 	/* flag whether in a watchdog list */
140 	int in_list;
141 
142 	/* time when to cancel thread if no activity */
143 	time_t alarm_time;
144 
145 	/* for location in doubly-linked list */
146 	struct watched_s *older;
147 	struct watched_s *newer;
148 
149 	/* watchdog that this watched_s is in */
150 	void *watchdog;
151 };
152 
153 /* the watchdog keeps track of all information */
154 struct watchdog_s {
155 	pthread_mutex_t mutex;
156 	int inactivity_timeout;
157 
158 	/* the head and tail of our list */
159 	struct watched_s *oldest;
160 	struct watched_s *newest;
161 };
162 
163 int watchdog_init(struct watchdog_s *w, int inactivity_timeout);
164 void watchdog_add_watched(struct watchdog_s *w, struct watched_s *watched);
165 void watchdog_defer_watched(struct watched_s *watched);
166 void watchdog_remove_watched(struct watched_s *watched);
167 
168 
169 /* size of buffer */
170 #define BUF_LEN 2048
171 
172 /* information on a telnet session */
173 struct telnet_session_s {
174 	FILE_DESCRIPTOR_OR_ERROR in_fd;
175 	int in_errno;
176 	int in_eof;
177 	int in_take;
178 	int in_add;
179 	char in_buf[BUF_LEN];
180 	int in_buflen;
181 
182 	int in_status;
183 
184 	FILE_DESCRIPTOR_OR_ERROR out_fd;
185 	int out_errno;
186 	int out_eof;
187 	int out_take;
188 	int out_add;
189 	char out_buf[BUF_LEN];
190 	int out_buflen;
191 };
192 
193 #ifdef NDEBUG
194 
195 #define daemon_assert(expr)
196 
197 #else							/* NDEBUG */
198 
199 void daemon_assert_fail(const char *assertion, const char *file, int line, const char *function);
200 
201 #ifndef __STRING
202 #define __STRING(x) #x
203 #endif
204 
205 #define daemon_assert(expr)                                                   \
206            ((expr) ? 0 :                                                      \
207             (daemon_assert_fail(__STRING(expr), __FILE__, __LINE__, __func__)));\
208 			assert(expr)
209 
210 // last assert is to silence static analyzers
211 
212 #endif							/* NDEBUG */
213 
214 /* data representation types supported */
215 #define TYPE_ASCII  0
216 #define TYPE_IMAGE  1
217 
218 /* file structure types supported */
219 #define STRU_FILE   0
220 #define STRU_RECORD 1
221 
222 /* data path chosen */
223 #define DATA_PORT     0
224 #define DATA_PASSIVE  1
225 
226 /* space required for text representation of address and port,
227    e.g. "192.168.0.1 port 1024" or
228         "2001:3333:DEAD:BEEF:0666:0013:0069:0042 port 65535" */
229 #define ADDRPORT_STRLEN 58
230 
231 /* structure encapsulating an FTP session's information */
232 struct ftp_session_s {
233 	/* flag whether session is active */
234 	int session_active;
235 
236 	/* incremented for each command */
237 	unsigned long command_number;
238 
239 	/* options about transfer set by user */
240 	int data_type;
241 	int file_structure;
242 
243 	/* offset to begin sending file from */
244 	off_t file_offset;
245 	unsigned long file_offset_command_number;
246 
247 	/* flag set if client requests ESPV ALL - this prevents subsequent
248 	   use of PORT, PASV, LPRT, LPSV, or EPRT */
249 	int epsv_all_set;
250 
251 	/* address of client */
252 	sockaddr_storage_t client_addr;
253 	char client_addr_str[ADDRPORT_STRLEN];
254 
255 	/* address of server (including IPv4 version) */
256 	sockaddr_storage_t server_addr;
257 	struct sockaddr_in server_ipv4_addr;
258 
259 	/* telnet session to encapsulate control channel logic */
260 	struct telnet_session_s *telnet_session;
261 
262 	/* current working directory of this connection */
263 	char dir[PATH_MAX + 1];
264 
265 	/* data channel information, including type,
266 	   and client address or server port depending on type */
267 	int data_channel;
268 	sockaddr_storage_t data_port;
269 	FILE_DESCRIPTOR_OR_ERROR server_fd;
270 
271 	/* watchdog to handle timeout */
272 	struct watched_s *watched;
273 };
274 
275 int ftp_session_init(struct ftp_session_s *f,
276 					 const sockaddr_storage_t * client_addr, const sockaddr_storage_t * server_addr, struct telnet_session_s *t, const char *dir);
277 void ftp_session_drop(struct ftp_session_s *f, const char *reason);
278 void ftp_session_run(struct ftp_session_s *f, struct watched_s *watched);
279 void ftp_session_destroy(struct ftp_session_s *f);
280 
281 struct ftp_listener_s {
282 
283 	/* file descriptor incoming connections arrive on */
284 	FILE_DESCRIPTOR_OR_ERROR file_descriptor;
285 
286 	/* maximum number of connections */
287 	int max_connections;
288 
289 	/* current number of connections */
290 	int num_connections;
291 
292 	/* timeout (in seconds) for connections */
293 	int inactivity_timeout;
294 
295 	/* watchdog monitoring this listener's connections */
296 	struct watchdog_s watchdog;
297 
298 	/* mutext to lock changes to this structure */
299 	pthread_mutex_t mutex;
300 
301 	/* starting directory */
302 	char dir[3];				// only root directory for OWFS
303 
304 	/* boolean defining whether listener is running or not */
305 	int listener_running;
306 
307 	/* thread identifier for listener */
308 	pthread_t listener_thread;
309 
310 	/* end of pipe to wake up listening thread with */
311 	/* end of pipe listening thread waits on */
312 	FILE_DESCRIPTOR_OR_ERROR shutdown_request_fd[2];
313 
314 	/* condition to signal thread requesting shutdown */
315 	pthread_cond_t shutdown_cond;
316 
317 };
318 
319 int ftp_listener_init(struct ftp_listener_s *f);
320 int ftp_listener_start(struct ftp_listener_s *f);
321 void ftp_listener_stop(struct ftp_listener_s *f);
322 
323 /* special macro for handling EPSV ALL requests */
324 #define EPSV_ALL (-1)
325 
326 /* maximum possible number of arguments */
327 #define MAX_ARG 2
328 
329 /* maximum string length */
330 #define MAX_STRING_LEN PATH_MAX
331 
332 struct ftp_command_s {
333 	char command[5];
334 	int num_arg;
335 	union {
336 		char string[MAX_STRING_LEN + 1];
337 		sockaddr_storage_t host_port;
338 		int num;
339 		off_t offset;
340 	} arg[MAX_ARG];
341 };
342 
343 /* methods */
344 int ftp_command_parse(const char *input, struct ftp_command_s *cmd);
345 
346 /* functions */
347 void telnet_session_init(struct telnet_session_s *t, FILE_DESCRIPTOR_OR_ERROR in, FILE_DESCRIPTOR_OR_ERROR out);
348 int telnet_session_print(struct telnet_session_s *t, const char *s);
349 int telnet_session_println(struct telnet_session_s *t, const char *s);
350 int telnet_session_readln(struct telnet_session_s *t, char *buf, int buflen);
351 void telnet_session_destroy(struct telnet_session_s *t);
352 
353 #endif							/* OWFTPD_H */
354