kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

domain.c (4537B)



      1 /*
      2  * Copyright (c) 2013-2022 Joris Vink <joris@coders.se>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #include <sys/param.h>
     18 #include <sys/types.h>
     19 
     20 #include <fnmatch.h>
     21 
     22 #include "kore.h"
     23 
     24 #if !defined(KORE_NO_HTTP)
     25 #include "http.h"
     26 #endif
     27 
     28 #if defined(KORE_USE_ACME)
     29 #include "acme.h"
     30 #endif
     31 
     32 #define KORE_DOMAIN_CACHE	16
     33 
     34 static u_int16_t		domain_id = 0;
     35 struct kore_domain		*primary_dom = NULL;
     36 static struct kore_domain	*cached[KORE_DOMAIN_CACHE];
     37 
     38 void
     39 kore_domain_init(void)
     40 {
     41 	int		i;
     42 
     43 	for (i = 0; i < KORE_DOMAIN_CACHE; i++)
     44 		cached[i] = NULL;
     45 }
     46 
     47 void
     48 kore_domain_cleanup(void)
     49 {
     50 }
     51 
     52 struct kore_domain *
     53 kore_domain_new(const char *domain)
     54 {
     55 	struct kore_domain	*dom;
     56 
     57 	dom = kore_calloc(1, sizeof(*dom));
     58 	dom->id = domain_id++;
     59 
     60 	dom->accesslog = -1;
     61 	dom->x509_verify_depth = 1;
     62 
     63 	dom->domain = kore_strdup(domain);
     64 
     65 #if !defined(KORE_NO_HTTP)
     66 	TAILQ_INIT(&dom->routes);
     67 	TAILQ_INIT(&dom->redirects);
     68 #endif
     69 
     70 	if (dom->id < KORE_DOMAIN_CACHE) {
     71 		if (cached[dom->id] != NULL)
     72 			fatal("non free domain cache slot");
     73 		cached[dom->id] = dom;
     74 	}
     75 
     76 	if (primary_dom == NULL)
     77 		primary_dom = dom;
     78 
     79 	return (dom);
     80 }
     81 
     82 int
     83 kore_domain_attach(struct kore_domain *dom, struct kore_server *server)
     84 {
     85 	struct kore_domain	*d;
     86 
     87 	if (dom->server != NULL)
     88 		return (KORE_RESULT_ERROR);
     89 
     90 	TAILQ_FOREACH(d, &server->domains, list) {
     91 		if (!strcmp(d->domain, dom->domain))
     92 			return (KORE_RESULT_ERROR);
     93 	}
     94 
     95 	dom->server = server;
     96 	TAILQ_INSERT_TAIL(&server->domains, dom, list);
     97 
     98 	/* The primary domain should be attached to a TLS context. */
     99 	if (server->tls == 0 && dom == primary_dom)
    100 		primary_dom = NULL;
    101 
    102 	return (KORE_RESULT_OK);
    103 }
    104 
    105 void
    106 kore_domain_free(struct kore_domain *dom)
    107 {
    108 #if !defined(KORE_NO_HTTP)
    109 	struct kore_route		*rt;
    110 	struct http_redirect		*rdr;
    111 #endif
    112 	if (dom == NULL)
    113 		return;
    114 
    115 	if (primary_dom == dom)
    116 		primary_dom = NULL;
    117 
    118 	TAILQ_REMOVE(&dom->server->domains, dom, list);
    119 
    120 	if (dom->domain != NULL)
    121 		kore_free(dom->domain);
    122 
    123 	kore_tls_domain_cleanup(dom);
    124 
    125 	kore_free(dom->cafile);
    126 	kore_free(dom->certkey);
    127 	kore_free(dom->certfile);
    128 	kore_free(dom->crlfile);
    129 
    130 #if !defined(KORE_NO_HTTP)
    131 	/* Drop all handlers associated with this domain */
    132 	while ((rt = TAILQ_FIRST(&dom->routes)) != NULL) {
    133 		TAILQ_REMOVE(&dom->routes, rt, list);
    134 		kore_route_free(rt);
    135 	}
    136 
    137 	while ((rdr = TAILQ_FIRST(&(dom->redirects))) != NULL) {
    138 		TAILQ_REMOVE(&(dom->redirects), rdr, list);
    139 		regfree(&rdr->rctx);
    140 		kore_free(rdr->target);
    141 		kore_free(rdr);
    142 	}
    143 #endif
    144 	kore_free(dom);
    145 }
    146 
    147 void
    148 kore_domain_callback(void (*cb)(struct kore_domain *))
    149 {
    150 	struct kore_server	*srv;
    151 	struct kore_domain	*dom;
    152 
    153 	LIST_FOREACH(srv, &kore_servers, list) {
    154 		TAILQ_FOREACH(dom, &srv->domains, list) {
    155 			cb(dom);
    156 		}
    157 	}
    158 }
    159 
    160 struct kore_domain *
    161 kore_domain_lookup(struct kore_server *srv, const char *domain)
    162 {
    163 	struct kore_domain	*dom;
    164 
    165 	TAILQ_FOREACH(dom, &srv->domains, list) {
    166 		if (!strcmp(dom->domain, domain))
    167 			return (dom);
    168 		if (!fnmatch(dom->domain, domain, FNM_CASEFOLD))
    169 			return (dom);
    170 	}
    171 
    172 	return (NULL);
    173 }
    174 
    175 struct kore_domain *
    176 kore_domain_byid(u_int16_t id)
    177 {
    178 	struct kore_server	*srv;
    179 	struct kore_domain	*dom;
    180 
    181 	if (id < KORE_DOMAIN_CACHE)
    182 		return (cached[id]);
    183 
    184 	LIST_FOREACH(srv, &kore_servers, list) {
    185 		TAILQ_FOREACH(dom, &srv->domains, list) {
    186 			if (dom->id == id)
    187 				return (dom);
    188 		}
    189 	}
    190 
    191 	return (NULL);
    192 }
    193 
    194 /*
    195  * Called by the worker processes to close the file descriptor towards
    196  * the accesslog as they do not need it locally.
    197  */
    198 void
    199 kore_domain_closelogs(void)
    200 {
    201 	struct kore_server	*srv;
    202 	struct kore_domain	*dom;
    203 
    204 	LIST_FOREACH(srv, &kore_servers, list) {
    205 		TAILQ_FOREACH(dom, &srv->domains, list) {
    206 			if (dom->accesslog != -1) {
    207 				(void)close(dom->accesslog);
    208 				/*
    209 				 * Turn into flag to indicate accesslogs
    210 				 * are active.
    211 				 */
    212 				dom->accesslog = 1;
    213 			} else {
    214 				dom->accesslog = 0;
    215 			}
    216 		}
    217 	}
    218 }