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 }