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