Blob
Date:
Fri Apr 8 13:52:35 2022
UTC
Message:
don't load the built-in list when using `types'
/** Copyright (c) 2020, 2021, 2022 Omar Polo <op@omarpolo.com>** Permission to use, copy, modify, and distribute this software for any* purpose with or without fee is hereby granted, provided that the above* copyright notice and this permission notice appear in all copies.** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.*/#ifndef GMID_H#define GMID_H#include "config.h"#include <sys/socket.h>#include <sys/types.h>#include <arpa/inet.h>#include <netinet/in.h>#include <dirent.h>#include <limits.h>#include <netdb.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <time.h>#include <tls.h>#include <unistd.h>#include <openssl/x509.h>#if HAVE_EVENT2# include <event2/event.h># include <event2/event_compat.h># include <event2/event_struct.h># include <event2/buffer.h># include <event2/buffer_compat.h># include <event2/bufferevent.h># include <event2/bufferevent_struct.h># include <event2/bufferevent_compat.h>#else# include <event.h>#endif#define GMID_STRING "gmid " VERSION#define GMID_VERSION "gmid/" VERSION#define GEMINI_URL_LEN (1024+3) /* URL max len + \r\n + \0 */#define SUCCESS 20#define TEMP_REDIRECT 30#define TEMP_FAILURE 40#define CGI_ERROR 42#define PROXY_ERROR 43#define NOT_FOUND 51#define PROXY_REFUSED 53#define BAD_REQUEST 59#define CLIENT_CERT_REQ 60#define CERT_NOT_AUTH 61/* maximum hostname and label length, +1 for the NUL-terminator */#define DOMAIN_NAME_LEN (253+1)#define LABEL_LEN (63+1)#define FCGI_MAX 32#define PROC_MAX 16struct iri {char *schema;char *host;char *port;uint16_t port_no;char *path;char *query;char *fragment;};struct parser {char *iri;struct iri *parsed;const char *err;};struct fcgi {int id;char *path;char *port;char *prog;};extern struct fcgi fcgi[FCGI_MAX];TAILQ_HEAD(proxyhead, proxy);struct proxy {char *match_proto;char *match_host;const char *match_port;char *host;const char *port;char *sni;int notls;uint32_t protocols;int noverifyname;uint8_t *cert;size_t certlen;uint8_t *key;size_t keylen;X509_STORE *reqca;TAILQ_ENTRY(proxy) proxies;};TAILQ_HEAD(lochead, location);struct location {const char *match;const char *lang;const char *default_mime;const char *index;int auto_index; /* 0 auto, -1 off, 1 on */int block_code;const char *block_fmt;int strip;X509_STORE *reqca;int disable_log;int fcgi;const char *dir;int dirfd;TAILQ_ENTRY(location) locations;};TAILQ_HEAD(envhead, envlist);struct envlist {char *name;char *value;TAILQ_ENTRY(envlist) envs;};TAILQ_HEAD(aliashead, alist);struct alist {char *alias;TAILQ_ENTRY(alist) aliases;};extern TAILQ_HEAD(vhosthead, vhost) hosts;struct vhost {const char *domain;const char *cert;const char *key;const char *ocsp;const char *cgi;const char *entrypoint;TAILQ_ENTRY(vhost) vhosts;/** the first location rule is always '*' and holds the default* settings for the vhost, then follows the "real" location* rules as specified in the configuration.*/struct lochead locations;struct envhead env;struct envhead params;struct aliashead aliases;struct proxyhead proxies;};struct etm { /* extension to mime */char *mime;char *ext;};struct mime {struct etm *t;size_t len;size_t cap;/** Backward compatibility: types override the built-in list,* but the deprecated `mime' and `map' don't. It's still too* early to remove `mime' and `map' from the config parser.*/int skip_defaults;};struct conf {/* from command line */int foreground;int verbose;/* in the config */int port;int ipv6;uint32_t protos;struct mime mime;char *chroot;char *user;int prefork;};extern const char *config_path;extern struct conf conf;extern struct imsgbuf logibuf, exibuf, servibuf[PROC_MAX];extern int servpipes[PROC_MAX];typedef void (imsg_handlerfn)(struct imsgbuf*, struct imsg*, size_t);enum {REQUEST_UNDECIDED,REQUEST_FILE,REQUEST_DIR,REQUEST_CGI,REQUEST_FCGI,REQUEST_PROXY,REQUEST_DONE,};#define IS_INTERNAL_REQUEST(x) \((x) != REQUEST_CGI && \(x) != REQUEST_FCGI && \(x) != REQUEST_PROXY)struct client {uint32_t id;struct tls *ctx;char *req;size_t reqlen;struct iri iri;char domain[DOMAIN_NAME_LEN];struct bufferevent *bev;int type;struct bufferevent *cgibev;struct proxy *proxy;struct bufferevent *proxybev;struct tls *proxyctx;int proxyevset;struct event proxyev;char *header;int code;const char *meta;int fd, pfd;struct dirent **dir;int dirlen, diroff;/* big enough to store STATUS + SPACE + META + CRLF */char sbuf[1029];ssize_t len, off;struct sockaddr_storage addr;struct vhost *host; /* host they're talking to */size_t loc; /* location matched */SPLAY_ENTRY(client) entry;};SPLAY_HEAD(client_tree_id, client);extern struct client_tree_id clients;struct cgireq {char buf[GEMINI_URL_LEN];size_t iri_schema_off;size_t iri_host_off;size_t iri_port_off;size_t iri_path_off;size_t iri_query_off;size_t iri_fragment_off;int iri_portno;char spath[PATH_MAX+1];char relpath[PATH_MAX+1];char addr[NI_MAXHOST+1];/* AFAIK there isn't an upper limit for these two fields. */char subject[64+1];char issuer[64+1];char hash[128+1];char version[8];char cipher[32];int cipher_strength;time_t notbefore;time_t notafter;size_t host_off;size_t loc_off;};struct connreq {char host[NI_MAXHOST];char port[NI_MAXSERV];int flag;};enum {FILE_EXISTS,FILE_EXECUTABLE,FILE_DIRECTORY,FILE_MISSING,};enum imsg_type {IMSG_CGI_REQ,IMSG_CGI_RES,IMSG_FCGI_REQ,IMSG_FCGI_FD,IMSG_CONN_REQ,IMSG_CONN_FD,IMSG_LOG,IMSG_LOG_REQUEST,IMSG_LOG_TYPE,IMSG_QUIT,};/* gmid.c */char *data_dir(void);void load_local_cert(const char*, const char*);void load_vhosts(void);int make_socket(int, int);void setup_tls(void);void init_config(void);void free_config(void);void drop_priv(void);void yyerror(const char*, ...);void parse_conf(const char*);void print_conf(void);int cmdline_symset(char *);/* log.c */void fatal(const char*, ...)__attribute__((format (printf, 1, 2)))__attribute__((__noreturn__));#define LOG_ATTR_FMT __attribute__((format (printf, 2, 3)))void log_err(struct client*, const char*, ...) LOG_ATTR_FMT;void log_warn(struct client*, const char*, ...) LOG_ATTR_FMT;void log_notice(struct client*, const char*, ...) LOG_ATTR_FMT;void log_info(struct client*, const char*, ...) LOG_ATTR_FMT;void log_debug(struct client*, const char*, ...) LOG_ATTR_FMT;void log_request(struct client*, char*, size_t);int logger_main(int, struct imsgbuf*);/* mime.c */void init_mime(struct mime*);int add_mime(struct mime*, const char*, const char*);int load_default_mime(struct mime*);const char *mime(struct vhost*, const char*);void free_mime(struct mime *);/* server.c */extern int shutting_down;const char *vhost_lang(struct vhost*, const char*);const char *vhost_default_mime(struct vhost*, const char*);const char *vhost_index(struct vhost*, const char*);int vhost_auto_index(struct vhost*, const char*);int vhost_block_return(struct vhost*, const char*, int*, const char**);int vhost_fastcgi(struct vhost*, const char*);int vhost_dirfd(struct vhost*, const char*, size_t*);int vhost_strip(struct vhost*, const char*);X509_STORE *vhost_require_ca(struct vhost*, const char*);int vhost_disable_log(struct vhost*, const char*);void mark_nonblock(int);void client_write(struct bufferevent *, void *);void start_reply(struct client*, int, const char*);void client_close(struct client *);struct client *client_by_id(int);void loop(struct tls*, int, int, struct imsgbuf*);int client_tree_cmp(struct client *, struct client *);SPLAY_PROTOTYPE(client_tree_id, client, entry, client_tree_cmp);/* dirs.c */int scandir_fd(int, struct dirent***, int(*)(const struct dirent*),int(*)(const struct dirent**, const struct dirent**));int select_non_dot(const struct dirent*);int select_non_dotdot(const struct dirent*);/* ex.c */int send_string(int, const char*);int recv_string(int, char**);int send_iri(int, struct iri*);int recv_iri(int, struct iri*);void free_recvd_iri(struct iri*);int send_vhost(int, struct vhost*);int recv_vhost(int, struct vhost**);int send_time(int, time_t);int recv_time(int, time_t*);int send_fd(int, int);int recv_fd(int);int executor_main(struct imsgbuf*);/* fcgi.c */void fcgi_read(struct bufferevent *, void *);void fcgi_write(struct bufferevent *, void *);void fcgi_error(struct bufferevent *, short, void *);void fcgi_req(struct client *);/* sandbox.c */void sandbox_server_process(void);void sandbox_executor_process(void);void sandbox_logger_process(void);/* utf8.c */int valid_multibyte_utf8(struct parser*);char *utf8_nth(char*, size_t);/* iri.c */int parse_iri(char*, struct iri*, const char**);int serialize_iri(struct iri*, char*, size_t);char *pct_decode_str(char *);/* proxy.c */int proxy_init(struct client *);/* puny.c */int puny_decode(const char*, char*, size_t, const char**);/* utils.c */void block_signals(void);void unblock_signals(void);int starts_with(const char*, const char*);int ends_with(const char*, const char*);ssize_t filesize(int);char *absolutify_path(const char*);char *xstrdup(const char*);void *xcalloc(size_t, size_t);void gen_certificate(const char*, const char*, const char*);X509_STORE *load_ca(const char*);int validate_against_ca(X509_STORE*, const uint8_t*, size_t);void dispatch_imsg(struct imsgbuf*, imsg_handlerfn**, size_t);#endif
Omar Polo