1 /*
2  * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
3  * All rights reserved
4  *
5  * "THE BEER-WARE LICENSE" (Revision 42):
6  * Sergey Lyubka wrote this file.  As long as you retain this notice you
7  * can do whatever you want with this stuff. If we meet some day, and you think
8  * this stuff is worth it, you can buy me a beer in return.
9  */
10 
11 #ifndef DEFS_HEADER_DEFINED
12 #define	DEFS_HEADER_DEFINED
13 
14 #include "std_includes.h"
15 #include "llist.h"
16 #include "io.h"
17 #include "md5.h"
18 #include "config.h"
19 #include "shttpd.h"
20 
21 #define	NELEMS(ar)	(sizeof(ar) / sizeof(ar[0]))
22 
23 #ifdef _DEBUG
24 #define	DBG(x)	do { printf x ; putchar('\n'); fflush(stdout); } while (0)
25 #else
26 #define	DBG(x)
27 #endif /* DEBUG */
28 
29 /*
30  * Darwin prior to 7.0 and Win32 do not have socklen_t
31  */
32 #ifdef NO_SOCKLEN_T
33 typedef int socklen_t;
34 #endif /* NO_SOCKLEN_T */
35 
36 /*
37  * For parsing. This guy represents a substring.
38  */
39 struct vec {
40 	const char	*ptr;
41 	int		len;
42 };
43 
44 #if !defined(FALSE)
45 enum {FALSE, TRUE};
46 #endif /* !FALSE */
47 
48 enum {METHOD_GET, METHOD_POST, METHOD_PUT, METHOD_DELETE, METHOD_HEAD};
49 enum {HDR_DATE, HDR_INT, HDR_STRING};	/* HTTP header types		*/
50 enum {E_FATAL = 1, E_LOG = 2};		/* Flags for elog() function	*/
51 typedef unsigned long big_int_t;	/* Type for Content-Length	*/
52 
53 /*
54  * Unified socket address
55  */
56 struct usa {
57 	socklen_t len;
58 	union {
59 		struct sockaddr	sa;
60 		struct sockaddr_in sin;
61 	} u;
62 };
63 
64 /*
65  * This thing is aimed to hold values of any type.
66  * Used to store parsed headers' values.
67  */
68 union variant {
69 	char		*v_str;
70 	int		v_int;
71 	big_int_t	v_big_int;
72 	time_t		v_time;
73 	void		(*v_func)(void);
74 	void		*v_void;
75 	struct vec	v_vec;
76 };
77 
78 /*
79  * This is used only in embedded configuration. This structure holds a
80  * registered URI, associated callback function with callback data.
81  * For non-embedded compilation shttpd_callback_t is not defined, so
82  * we use union variant to keep the compiler silent.
83  */
84 struct registered_uri {
85 	struct llhead	link;
86 	const char	*uri;
87 	union variant	callback;
88 	void		*callback_data;
89 };
90 
91 /*
92  * User may want to handle certain errors. This structure holds the
93  * handlers for corresponding error codes.
94  */
95 struct error_handler {
96 	struct llhead	link;
97 	int		code;
98 	union variant	callback;
99 	void		*callback_data;
100 };
101 
102 struct http_header {
103 	int		len;		/* Header name length		*/
104 	int		type;		/* Header type			*/
105 	size_t		offset;		/* Value placeholder		*/
106 	const char	*name;		/* Header name			*/
107 };
108 
109 /*
110  * This guy holds parsed HTTP headers
111  */
112 struct headers {
113 	union variant	cl;		/* Content-Length:		*/
114 	union variant	ct;		/* Content-Type:		*/
115 	union variant	connection;	/* Connection:			*/
116 	union variant	ims;		/* If-Modified-Since:		*/
117 	union variant	user;		/* Remote user name		*/
118 	union variant	auth;		/* Authorization		*/
119 	union variant	useragent;	/* User-Agent:			*/
120 	union variant	referer;	/* Referer:			*/
121 	union variant	cookie;		/* Cookie:			*/
122 	union variant	location;	/* Location:			*/
123 	union variant	range;		/* Range:			*/
124 	union variant	status;		/* Status:			*/
125 	union variant	transenc;	/* Transfer-Encoding:		*/
126 };
127 
128 /* Must go after union variant definition */
129 #include "ssl.h"
130 
131 /*
132  * The communication channel
133  */
134 union channel {
135 	int		fd;		/* Regular static file		*/
136 	int		sock;		/* Connected socket		*/
137 	struct {
138 		int		sock;	/* XXX important. must be first	*/
139 		SSL		*ssl;	/* shttpd_poll() assumes that	*/
140 	} ssl;				/* SSL-ed socket		*/
141 	struct {
142 		DIR	*dirp;
143 		char	*path;
144 	} dir;				/* Opened directory		*/
145 	struct {
146 		void		*state;	/* For keeping state		*/
147 		union variant	func;	/* User callback function	*/
148 		void		*data;	/* User defined parameters	*/
149 	} emb;				/* Embedded, user callback	*/
150 };
151 
152 struct stream;
153 
154 /*
155  * IO class descriptor (file, directory, socket, SSL, CGI, etc)
156  * These classes are defined in io_*.c files.
157  */
158 struct io_class {
159 	const char *name;
160 	int (*read)(struct stream *, void *buf, size_t len);
161 	int (*write)(struct stream *, const void *buf, size_t len);
162 	void (*close)(struct stream *);
163 };
164 
165 /*
166  * Data exchange stream. It is backed by some communication channel:
167  * opened file, socket, etc. The 'read' and 'write' methods are
168  * determined by a communication channel.
169  */
170 struct stream {
171 	struct conn		*conn;
172 	union channel		chan;		/* Descriptor		*/
173 	struct io		io;		/* IO buffer		*/
174 	const struct io_class	*io_class;	/* IO class		*/
175 	int			headers_len;
176 	big_int_t		content_len;
177 	unsigned int		flags;
178 #define	FLAG_HEADERS_PARSED	1
179 #define	FLAG_SSL_ACCEPTED	2
180 #define	FLAG_R			4		/* Can read in general	*/
181 #define	FLAG_W			8		/* Can write in general	*/
182 #define	FLAG_CLOSED		16
183 #define	FLAG_DONT_CLOSE		32
184 #define	FLAG_ALWAYS_READY	64		/* File, dir, user_func	*/
185 #define	FLAG_SUSPEND		128
186 };
187 
188 struct worker {
189 	struct llhead	link;
190 	int		num_conns;	/* Num of active connections 	*/
191 	int		exit_flag;	/* Ditto - exit flag		*/
192 	int		ctl[2];		/* Control socket pair		*/
193 	struct shttpd_ctx *ctx;		/* Context reference		*/
194 	struct llhead	connections;	/* List of connections		*/
195 };
196 
197 struct conn {
198 	struct llhead	link;		/* Connections chain		*/
199 	struct worker	*worker;	/* Worker this conn belongs to	*/
200 	struct shttpd_ctx *ctx;		/* Context this conn belongs to */
201 	struct usa	sa;		/* Remote socket address	*/
202 	time_t		birth_time;	/* Creation time		*/
203 	time_t		expire_time;	/* Expiration time		*/
204 
205 	int		loc_port;	/* Local port			*/
206 	int		status;		/* Reply status code		*/
207 	int		method;		/* Request method		*/
208 	char		*uri;		/* Decoded URI			*/
209 	unsigned long	major_version;	/* Major HTTP version number    */
210 	unsigned long	minor_version;	/* Minor HTTP version number    */
211 	char		*request;	/* Request line			*/
212 	char		*headers;	/* Request headers		*/
213 	char		*query;		/* QUERY_STRING part of the URI	*/
214 	char		*path_info;	/* PATH_INFO thing		*/
215 	struct vec	mime_type;	/* Mime type			*/
216 
217 	struct headers	ch;		/* Parsed client headers	*/
218 
219 	struct stream	loc;		/* Local stream			*/
220 	struct stream	rem;		/* Remote stream		*/
221 
222 #if !defined(NO_SSI)
223 	void			*ssi;	/* SSI descriptor		*/
224 #endif /* NO_SSI */
225 };
226 
227 enum {
228 	OPT_ROOT, OPT_INDEX_FILES, OPT_PORTS, OPT_DIR_LIST,
229 	OPT_CGI_EXTENSIONS, OPT_CGI_INTERPRETER, OPT_CGI_ENVIRONMENT,
230 	OPT_SSI_EXTENSIONS, OPT_AUTH_REALM, OPT_AUTH_GPASSWD,
231 	OPT_AUTH_PUT, OPT_ACCESS_LOG, OPT_ERROR_LOG, OPT_MIME_TYPES,
232 	OPT_SSL_CERTIFICATE, OPT_ALIASES, OPT_ACL, OPT_INETD, OPT_UID,
233 	OPT_CFG_URI, OPT_PROTECT, OPT_SERVICE, OPT_HIDE, OPT_THREADS,
234 	NUM_OPTIONS
235 };
236 
237 /*
238  * SHTTPD context
239  */
240 struct shttpd_ctx {
241 	SSL_CTX		*ssl_ctx;	/* SSL context			*/
242 
243 	struct llhead	registered_uris;/* User urls			*/
244 	struct llhead	error_handlers;	/* Embedded error handlers	*/
245 	struct llhead	acl;		/* Access control list		*/
246 	struct llhead	ssi_funcs;	/* SSI callback functions	*/
247 	struct llhead	listeners;	/* Listening sockets		*/
248 	struct llhead	workers;	/* Worker workers		*/
249 
250 	FILE		*access_log;	/* Access log stream		*/
251 	FILE		*error_log;	/* Error log stream		*/
252 
253 	char	*options[NUM_OPTIONS];	/* Configurable options		*/
254 #if defined(__rtems__)
255 	rtems_id         mutex;
256 #endif /* _WIN32 */
257 };
258 
259 struct listener {
260 	struct llhead		link;
261 	struct shttpd_ctx	*ctx;	/* Context that socket belongs	*/
262 	int			sock;	/* Listening socket		*/
263 	int			is_ssl;	/* Should be SSL-ed		*/
264 };
265 
266 /* Types of messages that could be sent over the control socket */
267 enum {CTL_PASS_SOCKET, CTL_WAKEUP};
268 
269 /*
270  * In SHTTPD, list of values are represented as comma or space separated
271  * string. For example, list of CGI extensions can be represented as
272  * ".cgi,.php,.pl", or ".cgi .php .pl". The macro that follows allows to
273  * loop through the individual values in that list.
274  *
275  * A "const char *" pointer and size_t variable must be passed to the macro.
276  * Spaces or commas can be used as delimiters (macro DELIM_CHARS).
277  *
278  * In every iteration of the loop, "s" points to the current value, and
279  * "len" specifies its length. The code inside loop must not change
280  * "s" and "len" parameters.
281  */
282 #define	FOR_EACH_WORD_IN_LIST(s,len)					\
283 	for (; s != NULL && (len = strcspn(s, DELIM_CHARS)) != 0;	\
284 			s += len, s+= strspn(s, DELIM_CHARS))
285 
286 /*
287  * IPv4 ACL entry. Specifies subnet with deny/allow flag
288  */
289 struct acl {
290 	struct llhead	link;
291 	uint32_t	ip;		/* IP, in network byte order	*/
292 	uint32_t	mask;		/* Also in network byte order	*/
293 	int		flag;		/* Either '+' or '-'		*/
294 };
295 
296 /*
297  * shttpd.c
298  */
299 extern time_t	_shttpd_current_time;	/* Current UTC time		*/
300 extern int	_shttpd_tz_offset;	/* Offset from GMT time zone	*/
301 extern const struct vec _shttpd_known_http_methods[];
302 
303 extern void	_shttpd_stop_stream(struct stream *stream);
304 extern int	_shttpd_url_decode(const char *, int, char *dst, int);
305 extern void	_shttpd_send_server_error(struct conn *, int, const char *);
306 extern int	_shttpd_get_headers_len(const char *buf, size_t buflen);
307 extern void	_shttpd_parse_headers(const char *s, int, struct headers *);
308 extern int	_shttpd_is_true(const char *str);
309 extern int	_shttpd_socketpair(int pair[2]);
310 extern void	_shttpd_get_mime_type(struct shttpd_ctx *,
311 			const char *, int, struct vec *);
312 
313 #define	IS_TRUE(ctx, opt)	_shttpd_is_true((ctx)->options[opt])
314 
315 /*
316  * config.c
317  */
318 extern void	_shttpd_usage(const char *prog);
319 
320 /*
321  * log.c
322  */
323 extern void	_shttpd_elog(int flags, struct conn *c, const char *fmt, ...);
324 extern void	_shttpd_log_access(FILE *fp, const struct conn *c);
325 
326 /*
327  * string.c
328  */
329 extern void	_shttpd_strlcpy(register char *, register const char *, size_t);
330 extern int	_shttpd_strncasecmp(register const char *,
331 			register const char *, size_t);
332 extern char	*_shttpd_strndup(const char *ptr, size_t len);
333 extern char	*_shttpd_strdup(const char *str);
334 extern int	_shttpd_snprintf(char *buf, size_t len, const char *fmt, ...);
335 extern int	_shttpd_match_extension(const char *path, const char *ext_list);
336 
337 /*
338  * compat_*.c
339  */
340 extern void	_shttpd_set_close_on_exec(int fd);
341 extern int	_shttpd_set_non_blocking_mode(int fd);
342 extern int	_shttpd_stat(const char *, struct stat *stp);
343 extern int	_shttpd_open(const char *, int flags, int mode);
344 extern int	_shttpd_remove(const char *);
345 extern int	_shttpd_rename(const char *, const char *);
346 extern int	_shttpd_mkdir(const char *, int);
347 extern char *	_shttpd_getcwd(char *, int);
348 extern int	_shttpd_spawn_process(struct conn *c, const char *prog,
349 			char *envblk, char *envp[], int sock, const char *dir);
350 
351 extern int	_shttpd_set_nt_service(struct shttpd_ctx *, const char *);
352 extern int	_shttpd_set_systray(struct shttpd_ctx *, const char *);
353 extern void	_shttpd_try_to_run_as_nt_service(void);
354 
355 /*
356  * io_*.c
357  */
358 extern const struct io_class	_shttpd_io_file;
359 extern const struct io_class	_shttpd_io_socket;
360 extern const struct io_class	_shttpd_io_ssl;
361 extern const struct io_class	_shttpd_io_cgi;
362 extern const struct io_class	_shttpd_io_dir;
363 extern const struct io_class	_shttpd_io_embedded;
364 extern const struct io_class	_shttpd_io_ssi;
365 
366 extern int	_shttpd_put_dir(const char *path);
367 extern void	_shttpd_get_dir(struct conn *c);
368 extern void	_shttpd_get_file(struct conn *c, struct stat *stp);
369 extern void	_shttpd_ssl_handshake(struct stream *stream);
370 extern void	_shttpd_setup_embedded_stream(struct conn *,
371 			union variant, void *);
372 extern struct registered_uri *_shttpd_is_registered_uri(struct shttpd_ctx *,
373 			const char *uri);
374 extern void	_shttpd_do_ssi(struct conn *);
375 extern void	_shttpd_ssi_func_destructor(struct llhead *lp);
376 
377 /*
378  * auth.c
379  */
380 extern int	_shttpd_check_authorization(struct conn *c, const char *path);
381 extern int	_shttpd_is_authorized_for_put(struct conn *c);
382 extern void	_shttpd_send_authorization_request(struct conn *c);
383 extern int	_shttpd_edit_passwords(const char *fname, const char *domain,
384 			const char *user, const char *pass);
385 
386 /*
387  * cgi.c
388  */
389 extern int	_shttpd_run_cgi(struct conn *c, const char *prog);
390 extern void	_shttpd_do_cgi(struct conn *c);
391 
392 #define CGI_REPLY	"HTTP/1.1     OK\r\n"
393 #define	CGI_REPLY_LEN	(sizeof(CGI_REPLY) - 1)
394 
395 #endif /* DEFS_HEADER_DEFINED */
396