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 (4582B)



      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 	kore_debug("kore_domain_new(%s)", domain);
     58 
     59 	dom = kore_calloc(1, sizeof(*dom));
     60 	dom->id = domain_id++;
     61 
     62 	dom->accesslog = -1;
     63 	dom->x509_verify_depth = 1;
     64 
     65 	dom->domain = kore_strdup(domain);
     66 
     67 #if !defined(KORE_NO_HTTP)
     68 	TAILQ_INIT(&dom->routes);
     69 	TAILQ_INIT(&dom->redirects);
     70 #endif
     71 
     72 	if (dom->id < KORE_DOMAIN_CACHE) {
     73 		if (cached[dom->id] != NULL)
     74 			fatal("non free domain cache slot");
     75 		cached[dom->id] = dom;
     76 	}
     77 
     78 	if (primary_dom == NULL)
     79 		primary_dom = dom;
     80 
     81 	return (dom);
     82 }
     83 
     84 int
     85 kore_domain_attach(struct kore_domain *dom, struct kore_server *server)
     86 {
     87 	struct kore_domain	*d;
     88 
     89 	if (dom->server != NULL)
     90 		return (KORE_RESULT_ERROR);
     91 
     92 	TAILQ_FOREACH(d, &server->domains, list) {
     93 		if (!strcmp(d->domain, dom->domain))
     94 			return (KORE_RESULT_ERROR);
     95 	}
     96 
     97 	dom->server = server;
     98 	TAILQ_INSERT_TAIL(&server->domains, dom, list);
     99 
    100 	/* The primary domain should be attached to a TLS context. */
    101 	if (server->tls == 0 && dom == primary_dom)
    102 		primary_dom = NULL;
    103 
    104 	return (KORE_RESULT_OK);
    105 }
    106 
    107 void
    108 kore_domain_free(struct kore_domain *dom)
    109 {
    110 #if !defined(KORE_NO_HTTP)
    111 	struct kore_route		*rt;
    112 	struct http_redirect		*rdr;
    113 #endif
    114 	if (dom == NULL)
    115 		return;
    116 
    117 	if (primary_dom == dom)
    118 		primary_dom = NULL;
    119 
    120 	TAILQ_REMOVE(&dom->server->domains, dom, list);
    121 
    122 	if (dom->domain != NULL)
    123 		kore_free(dom->domain);
    124 
    125 	kore_tls_domain_cleanup(dom);
    126 
    127 	kore_free(dom->cafile);
    128 	kore_free(dom->certkey);
    129 	kore_free(dom->certfile);
    130 	kore_free(dom->crlfile);
    131 
    132 #if !defined(KORE_NO_HTTP)
    133 	/* Drop all handlers associated with this domain */
    134 	while ((rt = TAILQ_FIRST(&dom->routes)) != NULL) {
    135 		TAILQ_REMOVE(&dom->routes, rt, list);
    136 		kore_route_free(rt);
    137 	}
    138 
    139 	while ((rdr = TAILQ_FIRST(&(dom->redirects))) != NULL) {
    140 		TAILQ_REMOVE(&(dom->redirects), rdr, list);
    141 		regfree(&rdr->rctx);
    142 		kore_free(rdr->target);
    143 		kore_free(rdr);
    144 	}
    145 #endif
    146 	kore_free(dom);
    147 }
    148 
    149 void
    150 kore_domain_callback(void (*cb)(struct kore_domain *))
    151 {
    152 	struct kore_server	*srv;
    153 	struct kore_domain	*dom;
    154 
    155 	LIST_FOREACH(srv, &kore_servers, list) {
    156 		TAILQ_FOREACH(dom, &srv->domains, list) {
    157 			cb(dom);
    158 		}
    159 	}
    160 }
    161 
    162 struct kore_domain *
    163 kore_domain_lookup(struct kore_server *srv, const char *domain)
    164 {
    165 	struct kore_domain	*dom;
    166 
    167 	TAILQ_FOREACH(dom, &srv->domains, list) {
    168 		if (!strcmp(dom->domain, domain))
    169 			return (dom);
    170 		if (!fnmatch(dom->domain, domain, FNM_CASEFOLD))
    171 			return (dom);
    172 	}
    173 
    174 	return (NULL);
    175 }
    176 
    177 struct kore_domain *
    178 kore_domain_byid(u_int16_t id)
    179 {
    180 	struct kore_server	*srv;
    181 	struct kore_domain	*dom;
    182 
    183 	if (id < KORE_DOMAIN_CACHE)
    184 		return (cached[id]);
    185 
    186 	LIST_FOREACH(srv, &kore_servers, list) {
    187 		TAILQ_FOREACH(dom, &srv->domains, list) {
    188 			if (dom->id == id)
    189 				return (dom);
    190 		}
    191 	}
    192 
    193 	return (NULL);
    194 }
    195 
    196 /*
    197  * Called by the worker processes to close the file descriptor towards
    198  * the accesslog as they do not need it locally.
    199  */
    200 void
    201 kore_domain_closelogs(void)
    202 {
    203 	struct kore_server	*srv;
    204 	struct kore_domain	*dom;
    205 
    206 	LIST_FOREACH(srv, &kore_servers, list) {
    207 		TAILQ_FOREACH(dom, &srv->domains, list) {
    208 			if (dom->accesslog != -1) {
    209 				(void)close(dom->accesslog);
    210 				/*
    211 				 * Turn into flag to indicate accesslogs
    212 				 * are active.
    213 				 */
    214 				dom->accesslog = 1;
    215 			} else {
    216 				dom->accesslog = 0;
    217 			}
    218 		}
    219 	}
    220 }