1 /*
2  * headers.h
3  * (C)1997-2011 by Marc Huber <Marc.Huber@web.de>
4  * All rights reserved.
5  *
6  * $Id: headers.h,v 1.30 2011/08/06 20:28:33 marc Exp marc $
7  *
8  */
9 
10 #ifndef __HEADERS_H_
11 #  define __HEADERS_H_
12 
13 #  include "misc/sysconf.h"
14 
15 #  include <sys/time.h>
16 #  include <sys/types.h>
17 #  include <netinet/in.h>
18 #  include <limits.h>
19 #  include <dirent.h>
20 #  include <unistd.h>
21 #  include <fcntl.h>
22 #  include <errno.h>
23 #  include <stdio.h>
24 #  include <string.h>
25 #  include <arpa/inet.h>
26 #  include <sys/stat.h>
27 #  include <utime.h>
28 #  include <time.h>
29 #  include <stdlib.h>
30 #  include <signal.h>
31 #  include <ctype.h>
32 #  include <sys/time.h>
33 #  include <sys/wait.h>
34 #  include <sys/resource.h>
35 #  include <sysexits.h>
36 #  include <setjmp.h>
37 
38 #  include "misc/sysconf.h"
39 #  include "misc/strops.h"
40 #  include "mavis/mavis.h"
41 #  include "misc/memops.h"
42 #  include "mavis/debug.h"
43 #  include "mavis/log.h"
44 #  include "misc/memops.h"
45 #  include "misc/io.h"
46 #  include "misc/rb.h"
47 #  include "misc/io_sched.h"
48 #  include "misc/io_child.h"
49 
50 #  ifdef WITH_ZLIB
51 #    include <zlib.h>
52 #  endif
53 
54 #  ifdef WITH_LWRES
55 #    include "misc/io_dns_revmap.h"
56 #  endif
57 
58 #  ifdef WITH_PCRE
59 #    include <pcre.h>
60 #  endif
61 
62 #  ifdef WITH_PCRE2
63 #    include <pcre2.h>
64 #  endif
65 
66 #  include <regex.h>
67 
68 #  include "messages.h"
69 #  include "misc/net.h"
70 #  include "mavis/set_proctitle.h"
71 #  include "misc/setproctitle.h"
72 
73 #  ifdef __MAIN__
74 #    define WHERE
75 #    define INITVAL(x) = x
76 #  else
77 #    define WHERE extern
78 #    define INITVAL(x)
79 #  endif			/* __MAIN__ */
80 
81 #  ifdef WITH_SSL
82 #    include <openssl/ssl.h>
83 #    include <openssl/err.h>
84 #    include <openssl/bio.h>
85 #    include <openssl/pem.h>
86 #    include <openssl/evp.h>
87 
88 WHERE SSL_CTX *ssl_ctx INITVAL(NULL);
89 WHERE char *ssl_cert INITVAL(NULL);
90 WHERE char *ssl_key INITVAL(NULL);
91 WHERE char *ssl_pass INITVAL(NULL);
92 WHERE char *ssl_ciphers INITVAL(NULL);
93 WHERE int ssl_auth INITVAL(0);
94 WHERE int ssl_auth_req INITVAL(0);
95 WHERE int ssl_old_draft INITVAL(0);
96 WHERE int ssl_depth INITVAL(5);
97 WHERE char *ssl_cafile INITVAL(NULL);
98 WHERE char *ssl_capath INITVAL(NULL);
99 #  endif			/* WITH_SSL */
100 
101 #  include "misc/mymd5.h"
102 
103 #  include "misc/crc32.h"
104 #  include "foobar.h"
105 #  include "defaults.h"
106 
107 #  define TMPBUFSIZE 2 * PATH_MAX
108 #  define MAXBUFSIZE1413	1000
109 
110 #  define LOG_NONE	0
111 #  define LOG_COMMAND	1
112 #  define LOG_TRANSFER	2
113 #  define LOG_EVENT	4
114 #  define LOG_IDENT	8
115 #  define LOG_OVERRIDE	16
116 
117 #  ifdef WITH_LWRES
118 WHERE struct io_dns_ctx *idc INITVAL(NULL);
119 #  endif
120 
121 WHERE uid_t current_uid INITVAL(0);
122 WHERE gid_t current_gid INITVAL(0);
123 WHERE uid_t real_uid INITVAL(0);
124 WHERE gid_t real_gid INITVAL(0);
125 WHERE int update_ids INITVAL(0);
126 WHERE char *logformat_transfer INITVAL(NULL);
127 WHERE char *logformat_command INITVAL(NULL);
128 WHERE char *logformat_event INITVAL(NULL);
129 WHERE char logformat_delimiter INITVAL('|');
130 WHERE char logformat_substitute INITVAL('_');
131 WHERE int die_when_idle INITVAL(0);
132 WHERE int nlst_files_only INITVAL(0);
133 WHERE int hide_version INITVAL(0);
134 WHERE u_long id_max INITVAL(0);
135 WHERE mavis_ctx *mcx INITVAL(NULL);
136 WHERE int sigbus_cur INITVAL(-1);
137 WHERE jmp_buf sigbus_jmpbuf;
138 WHERE struct context *ctx_spawnd INITVAL(NULL);
139 WHERE struct io_context *io INITVAL(NULL);
140 WHERE int nfds_max;
141 
142 #  define BUFSIZE			32768
143 WHERE size_t bufsize INITVAL(BUFSIZE);
144 
145 #  ifdef WITH_MMAP
146 #    ifdef _LP64
147 #      define BUFSIZE_MMAP		0
148 #    else
149 #      define BUFSIZE_MMAP		262144
150 #    endif
151 WHERE int use_mmap INITVAL(-1);
152 WHERE int pagesize;
153 WHERE size_t bufsize_mmap INITVAL(BUFSIZE_MMAP);
154 #  endif			/* WITH_MMAP */
155 
156 #  ifdef WITH_SENDFILE
157 WHERE int use_sendfile INITVAL(-1);
158 #  endif			/* WITH_SENDFILE */
159 
160 struct acl_rule;
161 
162 struct acl_set {
163     //char *name;                       /* name of referred access list */
164     struct ftp_acl *acl;	/* pointer to access list */
165     u_int log:1;		/* log command */
166     u_int negate:1;		/* negate result */
167     u_int permit:1;		/* permit on match (commands only) */
168     struct acl_set *next;	/* pointer to next acl_set */
169 };
170 
171 WHERE struct acl_set **requests_aclset INITVAL(NULL);
172 WHERE struct acl_set **requests_site_aclset INITVAL(NULL);
173 
174 struct context;
175 
176 struct md_method {
177     char *ftp_name;
178     char *openssl_name;
179 #ifdef WITH_SSL
180     const EVP_MD *md;
181 #endif
182     void (*init) (struct context *);
183     void (*update) (struct context *, u_char *, size_t);
184     char *(*final) (struct context *);
185 
186     struct md_method *next;
187 };
188 
189 WHERE struct md_method *md_methods INITVAL(NULL);
190 struct md_method *md_method_find(struct md_method *, char *);
191 void md_init(void);
192 
193 int acl_add(char *, char *, char *, char *, char *, char *);
194 void acl_calc(struct context *);
195 void acl_init(void);
196 void acl_finish(void);
197 void acl_conf_readme(struct context *);
198 int acl_binary_only(struct context *, char *, char *);
199 int acl_compression(struct context *, char *, char *);
200 int acl_checksum(struct context *, char *, char *);
201 void acl_set_umask(struct context *, char *, char *);
202 void acl_set_deflate_level(struct context *);
203 void acl_check(struct context *, struct acl_rule *, char *, char *);
204 enum token eval_ftp_acl(struct context *, struct ftp_acl *, char *,
205 			char *);
206 
207 
208 void read_mimetypes(char *);
209 
210 #  define SYMLINKS_NO	0x0
211 #  define SYMLINKS_YES	0x1
212 #  define SYMLINKS_ROOT	0x2
213 #  define SYMLINKS_SAME	0x4
214 #  define SYMLINKS_REAL	0x8
215 
216 #  undef MIN
217 #  define MIN(A,B) (((A) < (B)) ? (A) : (B))
218 
219 #  include "misc/buffer.h"
220 
221 int conf(int, char **);
222 void file2control(struct context *, char *, char *);
223 void set_maxfd(int);
224 void clr_maxfd(int);
225 void setup_signals(void);
226 void process_signals(void);
227 int setup_socket(sockaddr_union *, u_int);
228 void setup_invalid_callbacks(struct io_context *);
229 
230 void ftp_log(struct context *, uint, char *);
231 
232 void parse_decls(struct sym *);
233 
234 void checkcmd(struct context *, char *);
235 void reply(struct context *, char *);
236 void replyf(struct context *, char *, ...)
237     __attribute__ ((format(printf, 2, 3)));
238 struct buffer *buffer_reply(struct buffer *, char *, size_t);
239 
240 char *parsepath(struct context *, char *);
241 char *buildpath(struct context *, char *);
242 
243 int check_incoming(struct context *, char *, u_int);
244 
245 char *lookup_uid(struct context *, uid_t);
246 char *lookup_gid(struct context *, gid_t);
247 
248 void auth_mavis(struct context *, char *);
249 void readcmd(struct context *, int);
250 void cleanup(struct context *, int);
251 void cleanup_data(struct context *, int);
252 void cleanup_data_reuse(struct context *, int);
253 void cleanup_control(struct context *, int);
254 void cleanup_data_ssl_error(struct context *, int);
255 void cleanup_control_ssl_error(struct context *, int);
256 void cleanup_ident(struct context *, int);
257 void cleanup_spawnd(struct context *, int);
258 int cleanup_file(struct context *, int);
259 
260 void ident_init(void);
261 void ident_out(struct context *);
262 
263 void message_init(void);
264 char *cook(struct context *cur, char *, char *, char *, int);
265 
266 void catchhup(int);
267 
268 void setup_sig_bus(void);
269 
270 int chunk_get(struct context *, off_t *);
271 int chunk_release(struct context *, off_t);
272 
273 #  define chunk_remaining(A) (A->remaining || A->dbufi)
274 
275 void quota_add(struct context *, long long);
276 
277 #  if defined(WITH_PCRE) || defined(WITH_PCRE2)
278 int PCRE_add(char *, char *, char *);
279 int PCRE_exec(const char *, char *, size_t);
280 #  endif
281 
282 int convstat(struct context *, struct stat *, char *);
283 int pickystat(struct context *, struct stat *, char *);
284 int pickystat_path(struct context *, struct stat *, char *);
285 
286 void h_site_idle(struct context *, char *);
287 void h_site_checkmethod(struct context *, char *);
288 void h_hash(struct context *, char *);
289 void h_site_checksum(struct context *, char *);
290 void h_site_chmod(struct context *, char *);
291 void h_site_help(struct context *, char *);
292 void h_site_id(struct context *, char *);
293 void h_site_groups(struct context *, char *);
294 void h_site_group(struct context *, char *);
295 void h_site_umask(struct context *, char *);
296 
297 void h_mdtm(struct context *, char *);
298 void h_size(struct context *, char *);
299 void h_port(struct context *, char *);
300 void h_pasv(struct context *, char *);
301 void h_list(struct context *, char *);
302 void h_nlst(struct context *, char *);
303 void h_user(struct context *, char *);
304 void h_pass(struct context *, char *);
305 void h_cdup(struct context *, char *);
306 void h_rein(struct context *, char *);
307 void h_quit(struct context *, char *);
308 void h_type(struct context *, char *);
309 void h_mode(struct context *, char *);
310 void h_retr(struct context *, char *);
311 void h_dele(struct context *, char *);
312 void h_mkd(struct context *, char *);
313 void h_rmd(struct context *, char *);
314 void h_rnfr(struct context *, char *);
315 void h_rnto(struct context *, char *);
316 void h_appe(struct context *, char *);
317 void h_stor(struct context *, char *);
318 void h_stou(struct context *, char *);
319 void h_rang(struct context *, char *);
320 void h_rest(struct context *, char *);
321 void h_abor(struct context *, char *);
322 void h_cwd(struct context *, char *);
323 void h_pwd(struct context *, char *);
324 void h_syst(struct context *, char *);
325 void h_stat(struct context *, char *);
326 void h_help(struct context *, char *);
327 void h_noop(struct context *, char *);
328 
329 void h_lprt(struct context *, char *);
330 void h_lpsv(struct context *, char *);
331 void h_eprt(struct context *, char *);
332 void h_epsv(struct context *, char *);
333 
334 void h_feat(struct context *, char *);
335 void h_opts(struct context *, char *);
336 void h_host(struct context *, char *);
337 void h_mlst(struct context *, char *);
338 void h_mlsd(struct context *, char *);
339 void h_lang(struct context *, char *);
340 
341 void h_esta(struct context *, char *);
342 void h_estp(struct context *, char *);
343 
344 #  ifdef WITH_SSL
345 void h_auth(struct context *, char *);
346 void h_pbsz(struct context *, char *);
347 void h_prot(struct context *, char *);
348 void h_ccc(struct context *, char *);
349 #  endif
350 
351 void h_mff(struct context *, char *);
352 void h_mfmt(struct context *, char *);
353 
354 void print_banner(struct context *);
355 
356 int is_connected(int);
357 void connect_port(struct context *);
358 void do_accept_c(struct context *, int);
359 void accept_data(struct context *, int);
360 void connect_data(struct context *, int);
361 void accept_control(struct context *, int);
362 void buffer2socket(struct context *, int);
363 void socket2buffer(struct context *, int);
364 void file2buffer(struct context *, int);
365 void buffer2file(struct context *, int);
366 void socket2control(struct context *, int);
367 void control2socket(struct context *, int);
368 void do_connect_d(struct context *, int);
369 void accept_control_raw(int, struct scm_data_accept *);
370 
371 void ident_connect_out(struct context *, int);
372 void ident_connected(struct context *, int);
373 void ident_buffer2socket(struct context *, int);
374 void ident_socket2buffer(struct context *, int);
375 
376 void invalid_infn(struct context *, int);
377 void invalid_outfn(struct context *, int);
378 int check_gids(struct context *, gid_t);
379 void cfg_init(void);
380 
381 char *digest2string(u_char *);
382 
383 enum list_mode {
384     List_nlst, List_list, List_mlsd, List_mlst
385 };
386 
387 void list(struct context *, char *, enum list_mode);
388 void list_stat(struct context *, char *);
389 void list_mlst(struct context *, char *);
390 
391 #  define CONV_NONE	0
392 #  define CONV_MD5	1
393 #  define CONV_CRC	2
394 #  define CONV_GZ	3
395 
396 struct visited_dirs;
397 struct context;
398 
399 struct context *new_context(struct io_context *);
400 
401 #  define SC (struct context *)
402 
403 struct list_struct {
404     u_int flag;
405     char *fact;
406 };
407 
408 
409 #  ifdef __H_FEAT_C__
410 #    define LIST_ITEM(A,B,C) {A,B,},
411 #  else
412 #    define LIST_ITEM(A,B,C)
413 #  endif
414 
415 #  ifdef __H_FEAT_C__
416 struct list_struct MLST_fact[] = {
417 #  endif
418 #  define MLST_fact_type	0x0001
419     LIST_ITEM(MLST_fact_type, "Type",)
420 #  define MLST_fact_size	0x0002
421 	LIST_ITEM(MLST_fact_size, "Size",)
422 #  define MLST_fact_modify	0x0004
423 	LIST_ITEM(MLST_fact_modify, "Modify",)
424 #  define MLST_fact_change	0x0008
425 	LIST_ITEM(MLST_fact_change, "Change",)
426 #  define MLST_fact_unique	0x0010
427 	LIST_ITEM(MLST_fact_unique, "Unique",)
428 #  define MLST_fact_perm	0x0020
429 	LIST_ITEM(MLST_fact_perm, "Perm",)
430 #  define MLST_fact_mediatype	0x0040
431 	LIST_ITEM(MLST_fact_mediatype, "Media-Type",)
432 #  define MLST_fact_UNIX_mode	0x0080
433 	LIST_ITEM(MLST_fact_UNIX_mode, "UNIX.mode",)
434 #  define MLST_fact_UNIX_owner	0x0100
435 	LIST_ITEM(MLST_fact_UNIX_owner, "UNIX.owner",)
436 #  define MLST_fact_UNIX_group	0x0200
437 	LIST_ITEM(MLST_fact_UNIX_group, "UNIX.group",)
438 #  ifdef __H_FEAT_C__
439     {0, NULL,}
440 };
441 #  endif
442 
443 #  ifdef __H_FEAT_C__
444 struct list_struct mode_z_opt[] = {
445 #  endif
446 #  define MODE_Z_ENGINE		0x01
447     LIST_ITEM(MODE_Z_ENGINE, "engine",)
448 #  define MODE_Z_METHOD		0x02
449 	LIST_ITEM(MODE_Z_METHOD, "method",)
450 #  define MODE_Z_LEVEL		0x04
451 	LIST_ITEM(MODE_Z_LEVEL, "level",)
452 #  define MODE_Z_EXTRA		0x08
453 	LIST_ITEM(MODE_Z_EXTRA, "extra",)
454 #  define MODE_Z_BLOCKSIZE	0x10
455 	LIST_ITEM(MODE_Z_BLOCKSIZE, "blocksize",)
456 #  ifdef __H_FEAT_C__
457     {0, NULL,}
458 };
459 #  endif
460 
461 typedef long long set64;
462 #  define SET64_ISSET(i,s) (s & (1LL << i))
463 #  define SET64_SET(i,s) (s |= (1LL << i))
464 #  define SET64_CLR(i,s) (s &= ~(1LL << i))
465 #  define SET64_ZERO(s) s = 0LL
466 
467 struct context {
468     struct io_context *io;
469     struct buffer *dbuf;	/* buffer for data connection */
470     struct buffer *cbufo;	/* outgoing buffer for control connection */
471     struct buffer *cbufi;	/* incoming buffer for control connection */
472     struct buffer *dbufi;	/* read-only data, ready for processing */
473     char *ident_buf;		/* buffer for RFC1413 lookup */
474     size_t ident_buflen;	/* internal data for RFC1413 lookup */
475     size_t ident_bufoff;	/* internal data for RFC1413 lookup */
476     char *user;			/* user name (from USER command) */
477     char *email;		/* email address for anonymous ftp */
478     char *ident_user;		/* user name (from RFC 1413 lookup) */
479 #  ifdef WITH_LWRES
480     char *reverse;		/* reverse mapping of client IP */
481 #  endif
482     char *vhost;		/* virtual host (HOST vhost/USER user@vhost */
483     char root[PATH_MAX + 1];	/* virtual root directory */
484     u_int rootlen;		/* length of root */
485     dev_t root_dev;		/* device and ... */
486     ino_t root_ino;		/* ... inode number of root directory */
487     char cwd[PATH_MAX + 1];	/* current working directory */
488     char home[PATH_MAX + 1];	/* home directory */
489     u_int cwdlen;		/* length of cwd */
490     u_int homelen;		/* length of home */
491     char filename[PATH_MAX + 1];
492     int sctp_fn;		/* sctp socket file number, if any */
493     int cfn;			/* control socket file number */
494     int dfn;			/* data socket file number */
495     int ffn;			/* file file number */
496     int dirfn;			/* directory file number */
497     int ifn;			/* data socket for RFC 1413 lookups */
498     off_t filesize;
499     off_t bytecount;
500     sockaddr_union sa_c_remote;	/* remote cep of control connection */
501     sockaddr_union sa_c_local;	/* local cep of control connection */
502     sockaddr_union sa_d_remote;	/* remote cep of data connection */
503     sockaddr_union sa_d_estp;	/* remote cep specified by ESTP command */
504     struct in6_addr in6_remote;
505     struct in6_addr in6_local;
506     u_long id;			/* session id */
507     int protocol;		/* 0, IPPROTO_TCP, IPPROTO_SCTP */
508     time_t transferstart;
509     off_t io_offset;
510     off_t io_offset_start;
511     off_t io_offset_end;
512     off_t remaining;		/* number of bytes still to read */
513     off_t offset;		/* where to continue reading */
514     char *chunk_start;
515     size_t chunk_length;
516     int authfailures;
517     char lastchar;
518     char conversion;
519     u_int mlst_facts;
520 #  define ST_conn        0
521 #  define ST_user        1
522 #  define ST_pass        2
523 #  define ST_asyncauth   4
524     u_int state:3;
525     u_int auth_in_progress:1;
526     u_int login_logged:1;
527     u_int address_mismatch:1;
528     u_int accept:1;
529     u_int estp:1;
530     u_int estp_valid:1;
531     u_int passive_transfer:1;
532     u_int epsv_all:1;
533     u_int transfer_in_progress:1;
534     u_int outgoing_data:1;
535     u_int use_ascii:1;
536     u_int list_to_cc:1;
537     u_int is_client:1;
538     u_int use_tls_c:1;		/* use ssl on control channel */
539     u_int use_tls_d:1;		/* use ssl on data channel */
540     u_int last_command_was_rnfr:1;
541     u_int buffer_filled:1;	/* actually true for empty buffer, too */
542     u_int ascii_in_buffer:1;
543     u_int real:1;
544     u_int anonymous:1;
545     u_int multiline_banners:1;
546     u_int umask_set:1;
547 #  ifdef WITH_BZLIB
548 #  endif			/* WITH_BZLIB */
549 #  ifdef WITH_ZLIB
550     u_int allow_mode_z:1;
551     int deflate_level_min;
552     int deflate_level_max;
553     int deflate_level_dfl;
554 #  endif			/* WITH_ZLIB */
555     u_int md_hash:1;
556     struct md_method *md_method_hash;
557     struct md_method *md_method_checksum;
558 
559     u_int iomode:2;
560 
561 #  define IOMODE_dunno 0
562 #  define IOMODE_sendfile 1
563 #  define IOMODE_mmap 2
564 #  define IOMODE_read 3
565 
566     u_int iomode_fixed:1;
567     u_int pst_valid:1;
568 
569 /* START acl dependant configuration variables */
570     u_int resolve_ids:1;
571     u_int allow_dotfiles:1;
572     u_int allow_conv_gzip:1;
573     u_int readme_notify:1;
574     u_int readme_once:1;
575     u_int allow_symlinks:4;
576     u_int banner_bye:1;
577     u_int welcome_bye:1;
578     u_int ident_query:1;
579 
580     u_int picky_uidcheck:1;
581     u_int picky_gidcheck:1;
582     u_int picky_permcheck:1;
583 
584     u_int iac_state:2;
585 
586     u_int loglevel:8;
587 
588     u_int chmod_dirmask:16;
589     u_int chmod_filemask:16;
590 
591     time_t accept_timeout;
592     time_t conn_timeout;
593     time_t idle_timeout;
594     time_t idle_timeout_dfl;
595     time_t idle_timeout_min;
596     time_t idle_timeout_max;
597     u_long shape_bandwidth;
598 
599     int pasv_ports_first;
600     int pasv_ports_last;
601 
602     int authfailures_max;
603     int authfailures_bye;
604     u_int umask;
605 
606     char *ftpuser;
607     char *ftpgroup;
608     char *welcome;
609     char *readme;
610     char *banner;
611     char *greeting;
612     char *goodbye;
613     char *maintainer;
614     char *hostname;
615 
616     sockaddr_union *passive_addr;
617 /* END acl dependant configuration variables */
618 
619 #  ifdef WITH_ZLIB
620     z_stream *zstream;
621     u_int zcrc32;
622     int deflate_level;
623     u_int deflate_extra:1;
624 #  endif			/* WITH_ZLIB */
625     char mode;
626 
627     u_int quota_update_on_close:1;
628     char *quota_path;
629     long long quota_ondisk;
630     long long quota_limit;
631     long long quota_filesize_before_stor;
632     struct visited_dirs *visited_dirs;
633     uid_t uid;
634     gid_t gid;
635     int gids_size;
636     gid_t gids[NGROUPS_MAX];
637     u_int lang;
638     regex_t *incoming;
639 #  ifdef WITH_SSL
640     char *certsubj;		/* authenticated certificate subject */
641     char *certsubjaltname;	/* authenticated subject alternative name */
642     int certdepth;
643     SSL *ssl_c;			/* control connection TLS context */
644     SSL *ssl_d;			/* data connection TLS context */
645 #  endif			/* WITH_SSL */
646     ssize_t ascii_size_limit;
647     size_t protected_buffer_size;
648     enum list_mode list_mode;
649     struct stat pst;
650     rb_tree_t *filelist;
651     struct timeval tv_shape;
652     char *stat_reply;
653     union {
654 	u_int crc32;
655 	myMD5_CTX md5context;
656 #  ifdef WITH_SSL
657 	EVP_MD_CTX mdctx;
658 #  endif
659     } checksum;
660     set64 requests;
661     set64 requests_dunno;
662     set64 requests_site;
663     set64 requests_site_dunno;
664     set64 requests_log;
665     set64 requests_site_log;
666 
667     long long traffic_files;
668     long long traffic_total;
669     int count_files;
670     int count_total;
671 
672     char iac[3];
673 };
674 
675 struct service_req {
676     char *cmd;
677     void (*handler) (struct context *, char *);
678     u_int arg_needed:1;		/* command requires argument */
679     u_int changeuid:1;		/* command requires uid change */
680     u_int buildpath:1;		/* command argument needs to be checked */
681     int help;
682     char *acl_default_name;
683 };
684 
685 int get_request_index(struct service_req *, char *);
686 
687 #  define ACL_CONNECT	"connect"
688 #  define ACL_SECURE	"secure"
689 #  define ACL_LOGIN	"login"
690 #  define ACL_REAL	"real"
691 #  define ACL_ANON	"anon"
692 
693 #  ifdef __MAIN__
694 struct service_req requests[] = {
695     {"ABOR", h_abor, 0, 0, 0, IDX_ABOR, ACL_LOGIN,},
696     {"APPE", h_appe, 1, 1, 1, IDX_APPE, ACL_REAL,},
697 #    ifdef WITH_SSL
698     {"AUTH", h_auth, 1, 0, 0, IDX_AUTH, ACL_CONNECT,},
699     {"CCC", h_ccc, 0, 0, 0, IDX_CCC, ACL_CONNECT,},
700 #    endif
701     {"CDUP", h_cdup, 0, 1, 1, IDX_CDUP, ACL_LOGIN,},
702     {"CWD", h_cwd, 1, 1, 1, IDX_CWD, ACL_LOGIN,},
703     {"DELE", h_dele, 1, 1, 1, IDX_DELE, ACL_REAL,},
704     {"EPRT", h_eprt, 1, 0, 0, IDX_EPRT, ACL_LOGIN,},
705     {"EPSV", h_epsv, 0, 0, 0, IDX_EPSV, ACL_LOGIN,},
706     {"ESTA", h_esta, 0, 0, 0, IDX_ESTA, ACL_LOGIN,},
707     {"ESTP", h_estp, 0, 0, 0, IDX_ESTP, ACL_LOGIN,},
708     {"FEAT", h_feat, 0, 0, 0, IDX_FEAT, ACL_CONNECT,},
709     {"HASH", h_hash, 0, 0, 0, IDX_HASH, ACL_CONNECT,},
710     {"HELP", h_hash, 0, 0, 0, IDX_HASH, ACL_CONNECT,},
711     {"HELP", h_help, 0, 0, 0, IDX_HELP, ACL_CONNECT,},
712     {"HOST", h_host, 1, 0, 0, IDX_HOST, ACL_CONNECT,},
713     {"LANG", h_lang, 0, 0, 0, IDX_LANG, ACL_CONNECT,},
714     {"LIST", h_list, 0, 1, 1, IDX_LIST, ACL_LOGIN,},
715     {"LPRT", h_lprt, 1, 0, 0, IDX_LPRT, ACL_LOGIN,},
716     {"LPSV", h_lpsv, 0, 0, 0, IDX_LPSV, ACL_LOGIN,},
717     {"MDTM", h_mdtm, 1, 1, 1, IDX_MDTM, ACL_LOGIN,},
718     {"MFF", h_mff, 1, 1, 1, IDX_MFF, ACL_REAL,},
719     {"MFMT", h_mfmt, 1, 1, 1, IDX_MFMT, ACL_REAL,},
720     {"MKD", h_mkd, 1, 1, 1, IDX_MKD, ACL_LOGIN,},
721     {"MLSD", h_mlsd, 0, 1, 1, IDX_MLSD, ACL_LOGIN,},
722     {"MLST", h_mlst, 0, 1, 1, IDX_MLST, ACL_LOGIN,},
723     {"MODE", h_mode, 1, 0, 0, IDX_MODE, ACL_LOGIN,},
724     {"NLST", h_nlst, 0, 1, 1, IDX_NLST, ACL_LOGIN,},
725     {"NOOP", h_noop, 0, 0, 0, IDX_NOOP, ACL_LOGIN,},
726     {"OPTS", h_opts, 1, 0, 0, IDX_OPTS, ACL_CONNECT,},
727     {"PASS", h_pass, 1, 0, 0, IDX_PASS, ACL_CONNECT,},
728     {"PASV", h_pasv, 0, 0, 0, IDX_PASV, ACL_LOGIN,},
729 #    ifdef WITH_SSL
730     {"PBSZ", h_pbsz, 1, 0, 0, IDX_PBSZ, ACL_CONNECT,},
731 #    endif
732     {"PORT", h_port, 1, 0, 0, IDX_PORT, ACL_LOGIN,},
733 #    ifdef WITH_SSL
734     {"PROT", h_prot, 1, 0, 0, IDX_PROT, ACL_CONNECT,},
735 #    endif
736     {"PWD", h_pwd, 0, 0, 0, IDX_PWD, ACL_LOGIN,},
737     {"QUIT", h_quit, 0, 0, 0, IDX_QUIT, ACL_CONNECT,},
738     {"RANG", h_rang, 1, 0, 0, IDX_RANG, ACL_LOGIN,},
739     {"REIN", h_rein, 0, 0, 0, IDX_REIN, ACL_CONNECT,},
740     {"REST", h_rest, 1, 0, 0, IDX_REST, ACL_LOGIN,},
741     {"RETR", h_retr, 1, 1, 1, IDX_RETR, ACL_LOGIN,},
742     {"RMD", h_rmd, 1, 1, 0, IDX_RMD, ACL_REAL,},
743     {"RNFR", h_rnfr, 1, 1, 1, IDX_RNFR, ACL_REAL,},
744     {"RNTO", h_rnto, 1, 1, 1, IDX_RNTO, ACL_REAL,},
745     {"SITE", h_noop, 1, 0, 0, IDX_SITE, ACL_CONNECT,},
746     {"SIZE", h_size, 1, 1, 1, IDX_SIZE, ACL_LOGIN,},
747     {"STAT", h_stat, 0, 0, 1, IDX_STAT, ACL_LOGIN,},
748     {"STOR", h_stor, 1, 1, 1, IDX_STOR, ACL_LOGIN,},
749     {"STOU", h_stou, 0, 1, 1, IDX_STOU, ACL_LOGIN,},
750     {"SYST", h_syst, 0, 0, 0, IDX_SYST, ACL_LOGIN,},
751     {"TYPE", h_type, 1, 0, 0, IDX_TYPE, ACL_LOGIN,},
752     {"USER", h_user, 1, 0, 0, IDX_USER, ACL_CONNECT,},
753     {"XCUP", h_cdup, 0, 1, 1, IDX_CDUP, ACL_LOGIN,},
754     {"XCWD", h_cwd, 1, 1, 1, IDX_CWD, ACL_LOGIN,},
755     {"XMKD", h_mkd, 1, 1, 1, IDX_MKD, ACL_LOGIN,},
756     {"XPWD", h_pwd, 0, 0, 0, IDX_PWD, ACL_LOGIN,},
757     {"XRMD", h_rmd, 1, 1, 1, IDX_RMD, ACL_REAL,},
758     {NULL, NULL, 0, 0, 0, 0, ACL_CONNECT,},
759 };
760 
761 struct service_req requests_site[] = {
762     {"CHECKMETHOD", h_site_checkmethod, 0, 0, 0, IDX_SITE_CHECKMTH,
763      ACL_LOGIN,},
764     {"CHECKSUM", h_site_checksum, 0, 1, 1, IDX_SITE_CHECKSUM, ACL_LOGIN,},
765     {"CHMOD", h_site_chmod, 1, 1, 1, IDX_SITE_CHMOD, ACL_REAL,},
766     {"GROUP", h_site_group, 1, 0, 0, IDX_SITE_GROUP, ACL_REAL,},
767     {"GROUPS", h_site_groups, 0, 0, 0, IDX_SITE_GROUPS, ACL_REAL,},
768     {"HELP", h_site_help, 0, 0, 0, IDX_SITE_HELP, ACL_CONNECT,},
769     {"ID", h_site_id, 0, 0, 0, IDX_SITE_ID, ACL_REAL,},
770     {"IDLE", h_site_idle, 0, 0, 0, IDX_SITE_IDLE, ACL_LOGIN,},
771     {"UMASK", h_site_umask, 0, 0, 1, IDX_SITE_UMASK, ACL_REAL,},
772     {NULL, NULL, 0, 0, 0, 0, ACL_CONNECT,},
773 };
774 
775 #  else				/* __MAIN__ */
776 extern struct service_req requests[];
777 extern struct service_req requests_site[];
778 #  endif			/* __MAIN__ */
779 #endif				/* __HEADERS_H_ */
780