1 #ifndef _GATLING_H
2 #define _GATLING_H
3 
4 #define _FILE_OFFSET_BITS 64
5 
6 #include "gatling_features.h"
7 #include "io.h"
8 #include "iob.h"
9 #include "array.h"
10 #include "buffer.h"
11 #include "uint16.h"
12 #include "uint32.h"
13 #include "uint64.h"
14 
15 #include <sys/stat.h>
16 #include <regex.h>
17 #include <sys/un.h>
18 
19 #include <time.h>
20 
21 #ifdef STATE_DEBUG
22 #include <stdio.h>
23 #endif
24 
25 #ifdef SUPPORT_FTP
26 enum ftpstate {
27   GREETING,
28   WAITINGFORUSER,
29   LOGGEDIN,
30   WAITCONNECT,
31   DOWNLOADING,
32   UPLOADING,
33 };
34 
35 extern int askforpassword;
36 #endif
37 
38 #ifdef SUPPORT_PROXY
39 enum proxyprotocol {
40   HTTP,
41   FASTCGI,
42   SCGI,
43 };
44 #endif
45 
46 enum encoding {
47   NORMAL=0,
48   GZIP=1,
49 #ifdef SUPPORT_BZIP2
50   BZIP2=2,
51 #endif
52 #ifdef SUPPORT_BROTLI
53   BROTLI=3,
54 #endif
55 };
56 
57 enum conntype {
58   UNUSED,
59 
60   HTTPSERVER6,	/* call socket_accept6() */
61   HTTPSERVER4,	/* call socket_accept4() */
62   HTTPREQUEST,	/* read and handle http request */
63 
64 #ifdef SUPPORT_FTP
65   FTPSERVER6,	/* call socket_accept6() */
66   FTPSERVER4,	/* call socket_accept4() */
67   FTPCONTROL6,	/* read and handle ftp commands */
68   FTPCONTROL4,	/* read and handle ftp commands */
69   FTPPASSIVE,	/* accept a slave connection */
70   FTPACTIVE,	/* still need to connect slave connection */
71   FTPSLAVE,	/* send/receive files */
72 #endif
73 
74 #ifdef SUPPORT_SMB
75   SMBSERVER6,	/* call socket_accept6() */
76   SMBSERVER4,	/* call socket_accept4() */
77   SMBREQUEST,	/* read and handle SMB request */
78 #endif
79 
80 #ifdef SUPPORT_PROXY
81   PROXYSLAVE,	/* write-to-proxy connection. */
82 		/* write HTTP header; switch type to PROXYPOST */
83   PROXYPOST,	/* while still_to_copy>0: write POST data; relay answer */
84   HTTPPOST,	/* type of HTTP request with POST data
85 		   read post data and write them to proxy (ctx->buddy) */
86 #endif
87 
88 #ifdef SUPPORT_HTTPS
89   HTTPSSERVER4,	/* call socket_accept6() */
90   HTTPSSERVER6,	/* call socket_accept4() */
91   HTTPSACCEPT,	/* call SSL_accept() */
92   HTTPSACCEPT_CHECK,	/* check whether input looks like SSL, then call SSL_accept() */
93   HTTPSREQUEST,	/* read and handle https request */
94   HTTPSRESPONSE,	/* write response to https request */
95   HTTPSPOST,	/* like HTTPPOST but using SSL */
96 #endif
97 
98   PUNISHMENT,	/* if we detected a DoS and tarpit someone */
99 
100   LAST_UNUNSED
101 };
102 
103 #ifdef SUPPORT_HTTPS
104 
105 #ifdef USE_POLARSSL
106 #undef USE_OPENSSL
107 #else
108 #define USE_OPENSSL
109 #endif
110 
111 #ifdef USE_OPENSSL
112 /* in ssl.c */
113 #include <openssl/ssl.h>
114 #include <openssl/err.h>
115 #include <openssl/engine.h>
116 extern int init_serverside_tls(SSL** ssl,int sock);
117 #endif
118 
119 #ifdef USE_POLARSSL
120 /* in pssl.c */
121 #include <mbedtls/config.h>
122 #include <mbedtls/platform.h>
123 #include <mbedtls/ssl.h>
124 #include <mbedtls/net.h>
125 #include <mbedtls/error.h>
126 #include "pssl.h"
127 
128 #endif
129 
130 void free_tls_memory(void);
131 
132 #endif
133 
134 /* the tree id is always 1 (we export exactly one tree in TreeConnectAndX)
135  * the user id is always 1, too (we hand it out in SessionSetupAndX)
136  * we need to hand out file handles relative to the PID though */
137 struct handle {
138   uint32_t pid,handle;
139   int fd;
140   off_t size,cur;
141   unsigned short* filename;
142 };
143 
144 struct handles {
145   size_t u,a;	/* used, allocated */
146   struct handle* h;
147 };
148 
149 #ifdef SUPPORT_PROXY
150 
151 static const unsigned long long UNKNOWN=-1;
152 static const unsigned long long CHUNKED=-2;
153 
154 struct httpstreamstate {
155   enum {
156     HSS_HEADER,		// have not seen full header yet
157 
158     HSS_HEADER_C,	// inside header, saw \nC
159     HSS_HEADER_CO,	// inside header, saw \nCo
160     HSS_HEADER_CON,	// inside header, saw \nCon
161     HSS_HEADER_CONT,	// inside header, saw \nCont
162     HSS_HEADER_CONTE,	// inside header, saw \nConte
163     HSS_HEADER_CONTEN,	// inside header, saw \nConten
164     HSS_HEADER_CONTENT,	// inside header, saw \nContent
165     HSS_HEADER_CONTENT_,	// inside header, saw \nContent-
166     HSS_HEADER_CONTENT_L,	// inside header, saw \nContent-L
167     HSS_HEADER_CONTENT_LE,	// inside header, saw \nContent-Le
168     HSS_HEADER_CONTENT_LEN,	// inside header, saw \nContent-Len
169     HSS_HEADER_CONTENT_LENG,	// inside header, saw \nContent-Leng
170     HSS_HEADER_CONTENT_LENGT,	// inside header, saw \nContent-Lengt
171     HSS_HEADER_CONTENT_LENGTH,	// inside header, saw \nContent-Length
172     HSS_HEADER_CONTENT_LENGTH_,	// inside header, saw \nContent-Length:
173     HSS_HEADER_CONTENT_LENGTH_NUM,	// inside header, saw \nContent-Length: *[0-9]
174 
175     HSS_HEADER_T,	// inside header, saw \nT
176     HSS_HEADER_TR,	// inside header, saw \nTr
177     HSS_HEADER_TRA,	// inside header, saw \nTra
178     HSS_HEADER_TRAN,	// inside header, saw \nTran
179     HSS_HEADER_TRANS,	// inside header, saw \nTrans
180     HSS_HEADER_TRANSF,	// inside header, saw \nTransf
181     HSS_HEADER_TRANSFE,	// inside header, saw \nTransfe
182     HSS_HEADER_TRANSFER,	// inside header, saw \nTransfer
183     HSS_HEADER_TRANSFER_,	// inside header, saw \nTransfer-
184     HSS_HEADER_TRANSFER_E,	// inside header, saw \nTransfer-E
185     HSS_HEADER_TRANSFER_EN,	// inside header, saw \nTransfer-En
186     HSS_HEADER_TRANSFER_ENC,	// inside header, saw \nTransfer-Enc
187     HSS_HEADER_TRANSFER_ENCO,	// inside header, saw \nTransfer-Enco
188     HSS_HEADER_TRANSFER_ENCOD,	// inside header, saw \nTransfer-Encod
189     HSS_HEADER_TRANSFER_ENCODI,	// inside header, saw \nTransfer-Encodi
190     HSS_HEADER_TRANSFER_ENCODIN,	// inside header, saw \nTransfer-Encodin
191     HSS_HEADER_TRANSFER_ENCODING,	// inside header, saw \nTransfer-Encoding
192     HSS_HEADER_TRANSFER_ENCODING_,	// inside header, saw \nTransfer-Encoding:
193     HSS_HEADER_TRANSFER_ENCODING_C,	// inside header, saw \nTransfer-Encoding: *c
194     HSS_HEADER_TRANSFER_ENCODING_CH,	// inside header, saw \nTransfer-Encoding: *ch
195     HSS_HEADER_TRANSFER_ENCODING_CHU,	// inside header, saw \nTransfer-Encoding: *chu
196     HSS_HEADER_TRANSFER_ENCODING_CHUN,	// inside header, saw \nTransfer-Encoding: *chun
197     HSS_HEADER_TRANSFER_ENCODING_CHUNK,	// inside header, saw \nTransfer-Encoding: *chunk
198     HSS_HEADER_TRANSFER_ENCODING_CHUNKE,	// inside header, saw \nTransfer-Encoding: *chunke
199     HSS_HEADER_TRANSFER_ENCODING_CHUNKED,	// inside header, saw \nTransfer-Encoding: *chunked
200 
201     HSS_HEADER_OTHER,	// inside some other header line
202 
203     HSS_HEADER_CR,	// inside header, saw \r
204     HSS_HEADER_CRLF,	// inside header, saw \r\n
205     HSS_HEADER_CRLFCR,	// inside header, saw \r\n\r
206     HSS_KNOWLENGTH,	// have seen header, know number of bytes left
207     HSS_INFINITE,	// neither content-length nor chunked encoding found
208 
209     HSS_HEADER_CHUNKED,	// reading chunked encoding header
210     HSS_HEADER_CHUNKED_CR,	// reading chunked encoding header, saw \r
211     HSS_HEADER_CHUNKED_CRLF,	// reading chunked encoding header, saw \r\n
212     HSS_HEADER_CHUNKED_CRLF_NUM,	// reading chunked encoding header, saw \r\n[0-9]+
213     HSS_HEADER_CHUNKED_CRLF_NUM_CR,	// reading chunked encoding header, saw \r\n[0-9]+\r
214 
215     HSS_KNOWLENGTH_CHUNKED,	// read chunk header, know length of it, and it's > 0
216 
217     HSS_DONE		// we saw all we need
218   } state;
219   enum {
220     DONTKNOW=0,
221     REQUEST=1,
222     POSTREQUEST=2,
223     RESPONSE_MAYBE=3,
224     RESPONSE=4,
225   } type;
226   unsigned long long bytesleft;
227 };
228 
229 void httpstream_initstate(struct httpstreamstate* hss);
230 int httpstream_update(struct httpstreamstate* hss,char c);
231 size_t httpstream(struct httpstreamstate* hss,
232 		  const char* buf, size_t len);
233 #endif
234 
235 struct http_data {
236   enum conntype t;
237 #ifdef SUPPORT_FTP
238   enum ftpstate f;
239 #endif
240   array r;
241   io_batch iob;
242   char myip[16];	/* this is needed for virtual hosting */
243   uint32 myscope_id;	/* in the absence of a Host header */
244   uint16 myport,peerport;
245   uint16 destport;	/* port on remote system, used for active FTP */
246   char* hdrbuf,* bodybuf;
247   const char *mimetype;
248   int hlen,blen;	/* hlen == length of hdrbuf, blen == length of bodybuf */
249   int keepalive;	/* 1 if we want the TCP connection to stay connected */
250 			/* this is always 1 for FTP except after the client said QUIT */
251   int filefd;		/* -1 or the descriptor of the file we are sending out */
252   int buddy;		/* descriptor for the other connection, used for FTP and proxy/CGI */
253   char peerip[16];	/* needed for active FTP */
254   unsigned long long received,sent;
255   enum encoding encoding;
256 #if defined(SUPPORT_FTP) || defined(SUPPORT_SMB)
257   char* ftppath;	/* for FTP we store the path here, for SMB the last FIRST_FIRST2 glob expression */
258 #endif
259 #ifdef SUPPORT_SMB
260   uint32_t smbattrs;	/* attributes from FIND_FIRST2 so FIND_NEXT2 knows whether to return directories */
261 #endif
262 #ifdef SUPPORT_FTP
263   uint64 ftp_rest;	/* offset to start transfer at */
264 #endif
265   uint64 sent_until,prefetched_until;
266 #ifdef SUPPORT_PROXY
267   enum proxyprotocol proxyproto;
268   unsigned long long still_to_copy;	/* for POST/PUT requests */
269   int havefirst;	/* first read contains cgi header */
270   char* oldheader;	/* old, unmodified request */
271   struct httpstreamstate hss;
272 #endif
273 #ifdef SUPPORT_HTTPS
274 #ifdef USE_POLARSSL
275   struct ssl_data* ssldata;
276 #endif
277 #ifdef USE_OPENSSL
278   SSL* ssl;
279 #endif
280 #if 0
281   int writefail;
282 #endif
283 #endif
284 #ifdef SUPPORT_SMB
285   struct handles h;
286 #endif
287 #ifdef SUPPORT_THREADED_OPEN
288   int try_encoding;
289   int cwd;
290   char* name_of_file_to_open;
291   struct stat ss;
292 #endif
293 #ifdef STATE_DEBUG
294   int myfd;
295 #endif
296 };
297 
298 #ifdef STATE_DEBUG
299 extern const char* state2string(enum conntype t);
300 #endif
301 
changestate(struct http_data * x,enum conntype t)302 static inline void changestate(struct http_data* x,enum conntype t) {
303 #ifdef STATE_DEBUG
304   if (x->t==UNUSED)
305     printf("STATE: new fd %d: state %s\n",x->myfd,state2string(t));
306   else
307     printf("STATE: fd %d: state change from %s to %s\n",x->myfd,state2string(x->t),state2string(t));
308 #endif
309   x->t=t;
310 }
311 
312 #ifdef SUPPORT_HTTPS
313 extern char* sshd;
314 #endif
315 
316 extern size_t max_handles;
317 
318 extern struct handle* alloc_handle(struct handles* h);
319 extern struct handle* deref_handle(struct handles* h,uint32_t handle);
320 extern void close_handle(struct handle* h);
321 extern void close_all_handles(struct handles* h);
322 
323 extern int virtual_hosts;
324 extern int transproxy;
325 extern int directory_index;
326 extern int logging;
327 extern int nouploads;
328 extern int chmoduploads;
329 extern const char months[];
330 #ifdef __MINGW32__
331 extern char origdir[PATH_MAX];
332 #else
333 extern int64 origdir;
334 #endif
335 
336 typedef struct de {
337   long name;	/* offset within b */
338   struct stat ss;
339   int todir;
340 } de;
341 extern char* base;
342 
343 extern int sort_name_a(de* x,de* y);
344 extern int sort_name_d(de* x,de* y);
345 extern int sort_mtime_a(de* x,de* y);
346 extern int sort_mtime_d(de* x,de* y);
347 extern int sort_size_a(de* x,de* y);
348 extern int sort_size_d(de* x,de* y);
349 
350 extern unsigned long connections;
351 extern unsigned long http_connections, https_connections, ftp_connections, smb_connections;
352 extern unsigned long cps,cps1;	/* connections per second */
353 extern unsigned long rps,rps1;	/* requests per second */
354 extern unsigned long eps,eps1;	/* events per second */
355 extern unsigned long long tin,tin1;	/* traffic inbound */
356 extern unsigned long long tout,tout1;	/* traffic outbound */
357 
358 extern int open_for_reading(int64* fd,const char* name,struct stat* SS,int dirfd);
359 extern unsigned int fmt_2digits(char* dest,int i);
360 extern int canonpath(char* s);
361 extern int open_for_writing(int64* fd,const char* name,int dirfd);
362 
363 #ifdef SUPPORT_FTP
364 extern void ftpresponse(struct http_data* h,int64 s);
365 extern void handle_read_ftppassive(int64 i,struct http_data* H);
366 extern void handle_write_ftpactive(int64 i,struct http_data* h);
367 #endif
368 
369 #if defined(SUPPORT_PROXY) || defined(SUPPORT_CGI)
370 /* You configure a list of regular expressions, and if a request matches
371  * one of them, the request is forwarded to some other IP:port.  You can
372  * run another httpd there that can handle CGI, PHP, JSP and whatnot. */
373 struct cgi_proxy {
374   regex_t r;
375   int file_executable;
376   char ip[16];
377   uint32 port,scope_id;
378   struct sockaddr_un uds;
379   struct cgi_proxy* next;
380 #ifdef SUPPORT_PROXY
381   enum proxyprotocol proxyproto;
382 #endif
383 };
384 extern struct cgi_proxy* last,* cgis;
385 extern char** _envp;
386 #endif
387 
388 #ifdef SUPPORT_CGI
389 extern int forksock[2];
390 #endif
391 
392 extern void httpresponse(struct http_data* h,int64 s,long headerlen);
393 extern char* http_header(struct http_data* r,char* h);
394 
395 /* returns dirfd for openat (or -2 for error) */
396 extern int ip_vhost(struct http_data* h);
397 
398 #ifdef SUPPORT_FALLBACK_REDIR
399 extern const char* redir;
400 #endif
401 
402 extern tai6464 now,next;
403 extern unsigned long timeout_secs;
404 extern const char* mimetypesfilename;
405 extern const char* mimetype(const char* filename,int fd);
406 
407 extern int add_proxy(const char* c);
408 extern int handle_read_proxypost(int64 i,struct http_data* H);
409 extern void handle_read_httppost(int64 i,struct http_data* H);
410 extern int handle_write_proxypost(int64 i,struct http_data* h);
411 extern void handle_write_httppost(int64 i,struct http_data* h);
412 extern void handle_write_proxyslave(int64 i,struct http_data* h);
413 
414 extern void cleanup(int64 sock);
415 extern size_t header_complete(struct http_data* r,int64 sock);
416 
417 extern void httperror_realm(struct http_data* r,const char* title,const char* message,const char* realm,int nobody);
418 extern void httperror(struct http_data* r,const char* title,const char* message,int nobody);
419 
420 extern int buffer_putlogstr(buffer* b,const char* s);
421 
422 extern char fsbuf[8192];
423 extern void forkslave(int fd,buffer* in,int savedir,const char* chroot_to);
424 
425 #ifdef USE_ZLIB
426 #include <zlib.h>
427 #endif
428 
429 #ifdef SUPPORT_SMB
430 extern int smbresponse(struct http_data* h,int64 s);
431 
432 extern char workgroup[20];
433 extern int wglen;
434 extern char workgroup_utf16[100];
435 extern int wglen16;
436 #endif
437 
438 extern int64 origdir;
439 
440 #include "version.h"
441 #define RELEASE "Gatling/" VERSION
442 
443 extern unsigned int max_requests_per_minute;
444 
445 /* call this function when a request comes in, with the peer's IP
446  * address as argument */
447 int new_request_from_ip(const char ip[16],time_t now);
448 /* returns 0 if the request was added and should be serviced.
449  * returns 1 if a denial of service attack from this IP was detected and
450  *           the request should not be serviced
451  * returns -1 if we ran out of memory trying to add the request */
452 
453 #ifdef SUPPORT_HTTPS
454 extern int64 https_write_callback(int64 sock,const void* buf,uint64 n);
455 extern int handle_ssl_error_code(int sock,int code,int reading);
456 #endif
457 
458 extern char* magicelfvalue;
459 extern char serverroot[];
460 extern char* defaultindex;
461 
462 #ifdef DEBUG_EVENTS
463 #include "fmt.h"
464 
new_io_wantwrite(int64 s,const char * file,unsigned int line)465 static void new_io_wantwrite(int64 s,const char* file,unsigned int line) {
466   char a[FMT_ULONG];
467   char b[FMT_ULONG];
468   char c[100];
469 #ifdef STATE_DEBUG
470   struct http_data* h=io_getcookie(s);
471   if (h)
472     c[fmt_strm(c," [state ",state2string(h->t),"]")]=0;
473   else
474     strcpy(c," [cookie is NULL]");
475 #else
476   c[0]=0;
477 #endif
478   a[fmt_ulong(a,s)]=0;
479   b[fmt_ulong(b,line)]=0;
480   buffer_putmflush(buffer_2,"DEBUG: ",file,":",b,": io_wantwrite(",a,")",c,"\n");
481   io_wantwrite(s);
482 }
483 
new_io_dontwantwrite(int64 s,const char * file,unsigned int line)484 static void new_io_dontwantwrite(int64 s,const char* file,unsigned int line) {
485   char a[FMT_ULONG];
486   char b[FMT_ULONG];
487   char c[100];
488 #ifdef STATE_DEBUG
489   struct http_data* h=io_getcookie(s);
490   if (h)
491     c[fmt_strm(c," [state ",state2string(h->t),"]")]=0;
492   else
493     strcpy(c," [cookie is NULL]");
494 #else
495   c[0]=0;
496 #endif
497   a[fmt_ulong(a,s)]=0;
498   b[fmt_ulong(b,line)]=0;
499   buffer_putmflush(buffer_2,"DEBUG: ",file,":",b,": io_dontwantwrite(",a,")",c,"\n");
500   io_dontwantwrite(s);
501 }
502 
new_io_wantread(int64 s,const char * file,unsigned int line)503 static void new_io_wantread(int64 s,const char* file,unsigned int line) {
504   char a[FMT_ULONG];
505   char b[FMT_ULONG];
506   char c[100];
507 #ifdef STATE_DEBUG
508   struct http_data* h=io_getcookie(s);
509   if (h)
510     c[fmt_strm(c," [state ",state2string(h->t),"]")]=0;
511   else
512     strcpy(c," [cookie is NULL]");
513 #else
514   c[0]=0;
515 #endif
516   a[fmt_ulong(a,s)]=0;
517   b[fmt_ulong(b,line)]=0;
518   buffer_putmflush(buffer_2,"DEBUG: ",file,":",b,": io_wantread(",a,")",c,"\n");
519   io_wantread(s);
520 }
521 
new_io_dontwantread(int64 s,const char * file,unsigned int line)522 static void new_io_dontwantread(int64 s,const char* file,unsigned int line) {
523   char a[FMT_ULONG];
524   char b[FMT_ULONG];
525   struct http_data* h=io_getcookie(s);
526   char c[100];
527   c[0]=0;
528 #ifdef STATE_DEBUG
529   if (h)
530     c[fmt_strm(c," [state ",state2string(h->t),"]")]=0;
531   else
532     strcpy(c," [cookie is NULL]");
533 #endif
534   a[fmt_ulong(a,s)]=0;
535   b[fmt_ulong(b,line)]=0;
536   buffer_putmflush(buffer_2,"DEBUG: ",file,":",b,": io_dontwantread(",a,")",c,"\n");
537   io_dontwantread(s);
538 }
539 
540 #define io_wantwrite(s) new_io_wantwrite(s,__FILE__,__LINE__)
541 #define io_wantread(s) new_io_wantread(s,__FILE__,__LINE__)
542 #define io_dontwantwrite(s) new_io_dontwantwrite(s,__FILE__,__LINE__)
543 #define io_dontwantread(s) new_io_dontwantread(s,__FILE__,__LINE__)
544 #endif
545 
546 #ifndef HAVE_EAGAIN_READWRITE
547 #warning you are building gatling against an old version of libowfat
io_eagain_read(int64 d)548 static inline void io_eagain_read(int64 d) { io_eagain(d); }
io_eagain_write(int64 d)549 static inline void io_eagain_write(int64 d) { io_eagain(d); }
550 #endif
551 
552 #endif
553