1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright (c) 2017, Joyent, Inc.
14 */
15 #include <sys/types.h>
16 #include <sys/debug.h>
17 #include <pthread.h>
18 #include "defs.h"
19 #include "config.h"
20 #include "ikev2_enum.h"
21
22 pthread_rwlock_t cfg_lock = PTHREAD_RWLOCK_INITIALIZER;
23 config_t *config;
24
25 static boolean_t cfg_addr_match(const sockaddr_u_t *restrict,
26 const config_addr_t *restrict);
27
28 config_t *
29 config_get(void)
30 {
31 config_t *cfg = NULL;
32
33 PTH(pthread_rwlock_rdlock(&cfg_lock));
34 cfg = config;
35 CONFIG_REFHOLD(cfg);
36 PTH(pthread_rwlock_unlock(&cfg_lock));
37 return (cfg);
38 }
39
40 void
41 config_xf_log(bunyan_logger_t *b, bunyan_level_t level, const char *msg,
42 const config_xf_t *xf)
43 {
44 getlog(level)(b, msg,
45 BUNYAN_T_STRING, "xf_encralg", ikev2_xf_encr_str(xf->xf_encr),
46 BUNYAN_T_UINT32, "xf_minbits", (uint32_t)xf->xf_minbits,
47 BUNYAN_T_UINT32, "xf_maxbits", (uint32_t)xf->xf_maxbits,
48 BUNYAN_T_STRING, "xf_authalg", ikev2_xf_auth_str(xf->xf_auth),
49 BUNYAN_T_STRING, "xf_authtype",
50 ikev2_auth_type_str(xf->xf_authtype),
51 BUNYAN_T_STRING, "xf_dh", ikev2_dh_str(xf->xf_dh),
52 BUNYAN_T_END);
53 }
54
55 /*
56 * Return the first rule that matches the given local and remote addresses.
57 * If no rule matches, NULL is returned. The config_t instance that holds
58 * the given rule is refheld.
59 */
60 config_rule_t *
61 config_get_rule(sockaddr_u_t *restrict local, sockaddr_u_t *restrict remote)
62 {
63 config_t *cfg = config_get();
64
65 for (size_t i = 0; cfg->cfg_rules[i] != NULL; i++) {
66 config_rule_t *rule = cfg->cfg_rules[i];
67 boolean_t local_match = B_FALSE;
68 boolean_t remote_match = B_FALSE;
69
70 for (size_t j = 0; j < rule->rule_nlocal_addr; j++) {
71 if (cfg_addr_match(local, &rule->rule_local_addr[j])) {
72 local_match = B_TRUE;
73 break;
74 }
75 }
76 for (size_t j = 0; j < rule->rule_nremote_addr; j++) {
77 if (cfg_addr_match(remote,
78 &rule->rule_remote_addr[j])) {
79 remote_match = B_TRUE;
80 break;
81 }
82 }
83 if (local_match && remote_match)
84 return (rule);
85 }
86
87 CONFIG_REFRELE(cfg);
88 return (NULL);
89 }
90
91 static boolean_t
92 cfg_addr_match(const sockaddr_u_t *restrict l, const config_addr_t *restrict r)
93 {
94 uint32_t mask;
95
96 switch (r->cfa_type) {
97 case CFG_ADDR_IPV4:
98 if (l->sau_ss->ss_family != AF_INET)
99 return (B_FALSE);
100 if (l->sau_sin->sin_addr.s_addr != r->cfa_startu.cfa_ip4)
101 return (B_FALSE);
102 return (B_TRUE);
103 case CFG_ADDR_IPV4_PREFIX:
104 /* XXX: this needs testing */
105 if (l->sau_ss->ss_family != AF_INET)
106 return (B_FALSE);
107 mask = (0xffffffff << (32 - r->cfa_endu.cfa_num)) &
108 0xffffffff;
109 if ((l->sau_sin->sin_addr.s_addr & mask) ==
110 (r->cfa_startu.cfa_ip4 &mask))
111 return (B_TRUE);
112 return (B_FALSE);
113 case CFG_ADDR_IPV4_RANGE:
114 if (l->sau_ss->ss_family != AF_INET)
115 return (B_FALSE);
116 if (l->sau_sin->sin_addr.s_addr >= r->cfa_startu.cfa_ip4 &&
117 l->sau_sin->sin_addr.s_addr <= r->cfa_endu.cfa_ip4)
118 return (B_TRUE);
119 return (B_FALSE);
120 case CFG_ADDR_IPV6:
121 if (l->sau_ss->ss_family != AF_INET6)
122 return (B_FALSE);
123 if (IN6_ARE_ADDR_EQUAL(&l->sau_sin6->sin6_addr,
124 &r->cfa_startu.cfa_ip6))
125 return (B_TRUE);
126 return (B_FALSE);
127 case CFG_ADDR_IPV6_PREFIX:
128 if (l->sau_ss->ss_family != AF_INET6)
129 return (B_FALSE);
130 if (IN6_ARE_PREFIXEDADDR_EQUAL(&l->sau_sin6->sin6_addr,
131 &r->cfa_startu.cfa_ip6, r->cfa_endu.cfa_num))
132 return (B_TRUE);
133 return (B_FALSE);
134 case CFG_ADDR_IPV6_RANGE:
135 if (l->sau_ss->ss_family != AF_INET6)
136 return (B_FALSE);
137 for (size_t i = 0; i < 16; i++) {
138 if ((l->sau_sin6->sin6_addr.s6_addr[i] <
139 r->cfa_startu.cfa_ip6.s6_addr[i]) ||
140 (l->sau_sin6->sin6_addr.s6_addr[i] >
141 r->cfa_endu.cfa_ip6.s6_addr[i]))
142 return (B_FALSE);
143 }
144 return (B_TRUE);
145 }
146 return (B_FALSE);
147 }
148
149 void
150 cfg_rule_free(config_rule_t *rule)
151 {
152 if (rule == NULL)
153 return;
154
155 if (rule->rule_xf != NULL) {
156 for (size_t i = 0; rule->rule_xf[i] != NULL; i++)
157 free(rule->rule_xf[i]);
158 }
159
160 free(rule->rule_xf);
161 free(rule->rule_local_addr);
162 free(rule->rule_remote_addr);
163 free(rule->rule_label);
164 free(rule);
165 }
166
167 void
168 cfg_free(config_t *cfg)
169 {
170 if (cfg == NULL)
171 return;
172
173 size_t i;
174
175 VERIFY3U(cfg->cfg_refcnt, ==, 0);
176
177 for (i = 0;
178 cfg->cfg_cert_root != NULL && cfg->cfg_cert_root[i] != NULL;
179 i++)
180 free(cfg->cfg_cert_root[i]);
181
182 if (cfg->cfg_cert_trust != NULL) {
183 for (i = 0; cfg->cfg_cert_trust[i] != NULL; i++)
184 free(cfg->cfg_cert_trust[i]);
185 }
186
187 if (cfg->cfg_xforms != NULL) {
188 for (i = 0; cfg->cfg_xforms[i] != NULL; i++)
189 free(cfg->cfg_xforms[i]);
190 }
191
192 if (cfg->cfg_rules != NULL) {
193 for (i = 0; cfg->cfg_rules[i] != NULL; i++)
194 cfg_rule_free(cfg->cfg_rules[i]);
195 }
196
197 free(cfg->cfg_rules);
198 free(cfg->cfg_xforms);
199 free(cfg->cfg_proxy);
200 free(cfg->cfg_socks);
201 free(cfg->cfg_cert_root);
202 free(cfg->cfg_cert_trust);
203 free(cfg);
204 }