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 }