| @@ -1,1494 +1,1494 @@ | | | @@ -1,1494 +1,1494 @@ |
1 | /* $NetBSD: isakmp_inf.c,v 1.48 2012/08/29 12:01:30 tteras Exp $ */ | | 1 | /* $NetBSD: isakmp_inf.c,v 1.49 2013/01/24 06:47:50 tteras Exp $ */ |
2 | | | 2 | |
3 | /* Id: isakmp_inf.c,v 1.44 2006/05/06 20:45:52 manubsd Exp */ | | 3 | /* Id: isakmp_inf.c,v 1.44 2006/05/06 20:45:52 manubsd Exp */ |
4 | | | 4 | |
5 | /* | | 5 | /* |
6 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | | 6 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
7 | * All rights reserved. | | 7 | * All rights reserved. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | | 16 | * documentation and/or other materials provided with the distribution. |
17 | * 3. Neither the name of the project nor the names of its contributors | | 17 | * 3. Neither the name of the project nor the names of its contributors |
18 | * may be used to endorse or promote products derived from this software | | 18 | * may be used to endorse or promote products derived from this software |
19 | * without specific prior written permission. | | 19 | * without specific prior written permission. |
20 | * | | 20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | | 21 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | | 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
31 | * SUCH DAMAGE. | | 31 | * SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #include "config.h" | | 34 | #include "config.h" |
35 | | | 35 | |
36 | #include <sys/types.h> | | 36 | #include <sys/types.h> |
37 | #include <sys/param.h> | | 37 | #include <sys/param.h> |
38 | #include <sys/socket.h> | | 38 | #include <sys/socket.h> |
39 | | | 39 | |
40 | #include <net/pfkeyv2.h> | | 40 | #include <net/pfkeyv2.h> |
41 | #include <netinet/in.h> | | 41 | #include <netinet/in.h> |
42 | #include <sys/queue.h> | | 42 | #include <sys/queue.h> |
43 | #include PATH_IPSEC_H | | 43 | #include PATH_IPSEC_H |
44 | | | 44 | |
45 | #include <stdlib.h> | | 45 | #include <stdlib.h> |
46 | #include <stdio.h> | | 46 | #include <stdio.h> |
47 | #include <string.h> | | 47 | #include <string.h> |
48 | #include <errno.h> | | 48 | #include <errno.h> |
49 | #if TIME_WITH_SYS_TIME | | 49 | #if TIME_WITH_SYS_TIME |
50 | # include <sys/time.h> | | 50 | # include <sys/time.h> |
51 | # include <time.h> | | 51 | # include <time.h> |
52 | #else | | 52 | #else |
53 | # if HAVE_SYS_TIME_H | | 53 | # if HAVE_SYS_TIME_H |
54 | # include <sys/time.h> | | 54 | # include <sys/time.h> |
55 | # else | | 55 | # else |
56 | # include <time.h> | | 56 | # include <time.h> |
57 | # endif | | 57 | # endif |
58 | #endif | | 58 | #endif |
59 | #ifdef ENABLE_HYBRID | | 59 | #ifdef ENABLE_HYBRID |
60 | #include <resolv.h> | | 60 | #include <resolv.h> |
61 | #endif | | 61 | #endif |
62 | | | 62 | |
63 | #include "libpfkey.h" | | 63 | #include "libpfkey.h" |
64 | | | 64 | |
65 | #include "var.h" | | 65 | #include "var.h" |
66 | #include "vmbuf.h" | | 66 | #include "vmbuf.h" |
67 | #include "schedule.h" | | 67 | #include "schedule.h" |
68 | #include "str2val.h" | | 68 | #include "str2val.h" |
69 | #include "misc.h" | | 69 | #include "misc.h" |
70 | #include "plog.h" | | 70 | #include "plog.h" |
71 | #include "debug.h" | | 71 | #include "debug.h" |
72 | | | 72 | |
73 | #include "localconf.h" | | 73 | #include "localconf.h" |
74 | #include "remoteconf.h" | | 74 | #include "remoteconf.h" |
75 | #include "sockmisc.h" | | 75 | #include "sockmisc.h" |
76 | #include "handler.h" | | 76 | #include "handler.h" |
77 | #include "policy.h" | | 77 | #include "policy.h" |
78 | #include "proposal.h" | | 78 | #include "proposal.h" |
79 | #include "isakmp_var.h" | | 79 | #include "isakmp_var.h" |
80 | #include "evt.h" | | 80 | #include "evt.h" |
81 | #include "isakmp.h" | | 81 | #include "isakmp.h" |
82 | #ifdef ENABLE_HYBRID | | 82 | #ifdef ENABLE_HYBRID |
83 | #include "isakmp_xauth.h" | | 83 | #include "isakmp_xauth.h" |
84 | #include "isakmp_unity.h" | | 84 | #include "isakmp_unity.h" |
85 | #include "isakmp_cfg.h" | | 85 | #include "isakmp_cfg.h" |
86 | #endif | | 86 | #endif |
87 | #include "isakmp_inf.h" | | 87 | #include "isakmp_inf.h" |
88 | #include "oakley.h" | | 88 | #include "oakley.h" |
89 | #include "ipsec_doi.h" | | 89 | #include "ipsec_doi.h" |
90 | #include "crypto_openssl.h" | | 90 | #include "crypto_openssl.h" |
91 | #include "pfkey.h" | | 91 | #include "pfkey.h" |
92 | #include "policy.h" | | 92 | #include "policy.h" |
93 | #include "algorithm.h" | | 93 | #include "algorithm.h" |
94 | #include "proposal.h" | | 94 | #include "proposal.h" |
95 | #include "admin.h" | | 95 | #include "admin.h" |
96 | #include "strnames.h" | | 96 | #include "strnames.h" |
97 | #ifdef ENABLE_NATT | | 97 | #ifdef ENABLE_NATT |
98 | #include "nattraversal.h" | | 98 | #include "nattraversal.h" |
99 | #endif | | 99 | #endif |
100 | | | 100 | |
101 | /* information exchange */ | | 101 | /* information exchange */ |
102 | static int isakmp_info_recv_n (struct ph1handle *, struct isakmp_pl_n *, u_int32_t, int); | | 102 | static int isakmp_info_recv_n (struct ph1handle *, struct isakmp_pl_n *, u_int32_t, int); |
103 | static int isakmp_info_recv_d (struct ph1handle *, struct isakmp_pl_d *, u_int32_t, int); | | 103 | static int isakmp_info_recv_d (struct ph1handle *, struct isakmp_pl_d *, u_int32_t, int); |
104 | | | 104 | |
105 | #ifdef ENABLE_DPD | | 105 | #ifdef ENABLE_DPD |
106 | static int isakmp_info_recv_r_u __P((struct ph1handle *, | | 106 | static int isakmp_info_recv_r_u __P((struct ph1handle *, |
107 | struct isakmp_pl_ru *, u_int32_t)); | | 107 | struct isakmp_pl_ru *, u_int32_t)); |
108 | static int isakmp_info_recv_r_u_ack __P((struct ph1handle *, | | 108 | static int isakmp_info_recv_r_u_ack __P((struct ph1handle *, |
109 | struct isakmp_pl_ru *, u_int32_t)); | | 109 | struct isakmp_pl_ru *, u_int32_t)); |
110 | static void isakmp_info_send_r_u __P((struct sched *)); | | 110 | static void isakmp_info_send_r_u __P((struct sched *)); |
111 | #endif | | 111 | #endif |
112 | | | 112 | |
113 | static void purge_isakmp_spi __P((int, isakmp_index *, size_t)); | | 113 | static void purge_isakmp_spi __P((int, isakmp_index *, size_t)); |
114 | | | 114 | |
115 | /* %%% | | 115 | /* %%% |
116 | * Information Exchange | | 116 | * Information Exchange |
117 | */ | | 117 | */ |
118 | /* | | 118 | /* |
119 | * receive Information | | 119 | * receive Information |
120 | */ | | 120 | */ |
121 | int | | 121 | int |
122 | isakmp_info_recv(iph1, msg0) | | 122 | isakmp_info_recv(iph1, msg0) |
123 | struct ph1handle *iph1; | | 123 | struct ph1handle *iph1; |
124 | vchar_t *msg0; | | 124 | vchar_t *msg0; |
125 | { | | 125 | { |
126 | vchar_t *msg = NULL; | | 126 | vchar_t *msg = NULL; |
127 | vchar_t *pbuf = NULL; | | 127 | vchar_t *pbuf = NULL; |
128 | u_int32_t msgid = 0; | | 128 | u_int32_t msgid = 0; |
129 | int error = -1; | | 129 | int error = -1; |
130 | struct isakmp *isakmp; | | 130 | struct isakmp *isakmp; |
131 | struct isakmp_gen *gen; | | 131 | struct isakmp_gen *gen; |
132 | struct isakmp_parse_t *pa, *pap; | | 132 | struct isakmp_parse_t *pa, *pap; |
133 | void *p; | | 133 | void *p; |
134 | vchar_t *hash, *payload; | | 134 | vchar_t *hash, *payload; |
135 | struct isakmp_gen *nd; | | 135 | struct isakmp_gen *nd; |
136 | u_int8_t np; | | 136 | u_int8_t np; |
137 | int encrypted; | | 137 | int encrypted; |
138 | | | 138 | |
139 | plog(LLV_DEBUG, LOCATION, NULL, "receive Information.\n"); | | 139 | plog(LLV_DEBUG, LOCATION, NULL, "receive Information.\n"); |
140 | | | 140 | |
141 | encrypted = ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E); | | 141 | encrypted = ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E); |
142 | msgid = ((struct isakmp *)msg0->v)->msgid; | | 142 | msgid = ((struct isakmp *)msg0->v)->msgid; |
143 | | | 143 | |
144 | /* Use new IV to decrypt Informational message. */ | | 144 | /* Use new IV to decrypt Informational message. */ |
145 | if (encrypted) { | | 145 | if (encrypted) { |
146 | struct isakmp_ivm *ivm; | | 146 | struct isakmp_ivm *ivm; |
147 | | | 147 | |
148 | if (iph1->ivm == NULL) { | | 148 | if (iph1->ivm == NULL) { |
149 | plog(LLV_ERROR, LOCATION, NULL, "iph1->ivm == NULL\n"); | | 149 | plog(LLV_ERROR, LOCATION, NULL, "iph1->ivm == NULL\n"); |
150 | return -1; | | 150 | return -1; |
151 | } | | 151 | } |
152 | | | 152 | |
153 | /* compute IV */ | | 153 | /* compute IV */ |
154 | ivm = oakley_newiv2(iph1, ((struct isakmp *)msg0->v)->msgid); | | 154 | ivm = oakley_newiv2(iph1, ((struct isakmp *)msg0->v)->msgid); |
155 | if (ivm == NULL) | | 155 | if (ivm == NULL) |
156 | return -1; | | 156 | return -1; |
157 | | | 157 | |
158 | msg = oakley_do_decrypt(iph1, msg0, ivm->iv, ivm->ive); | | 158 | msg = oakley_do_decrypt(iph1, msg0, ivm->iv, ivm->ive); |
159 | oakley_delivm(ivm); | | 159 | oakley_delivm(ivm); |
160 | if (msg == NULL) | | 160 | if (msg == NULL) |
161 | return -1; | | 161 | return -1; |
162 | | | 162 | |
163 | } else | | 163 | } else |
164 | msg = vdup(msg0); | | 164 | msg = vdup(msg0); |
165 | | | 165 | |
166 | /* Safety check */ | | 166 | /* Safety check */ |
167 | if (msg->l < sizeof(*isakmp) + sizeof(*gen)) { | | 167 | if (msg->l < sizeof(*isakmp) + sizeof(*gen)) { |
168 | plog(LLV_ERROR, LOCATION, NULL, | | 168 | plog(LLV_ERROR, LOCATION, NULL, |
169 | "ignore information because the " | | 169 | "ignore information because the " |
170 | "message is way too short - %zu byte(s).\n", | | 170 | "message is way too short - %zu byte(s).\n", |
171 | msg->l); | | 171 | msg->l); |
172 | goto end; | | 172 | goto end; |
173 | } | | 173 | } |
174 | | | 174 | |
175 | isakmp = (struct isakmp *)msg->v; | | 175 | isakmp = (struct isakmp *)msg->v; |
176 | gen = (struct isakmp_gen *)((caddr_t)isakmp + sizeof(struct isakmp)); | | 176 | gen = (struct isakmp_gen *)((caddr_t)isakmp + sizeof(struct isakmp)); |
177 | np = gen->np; | | 177 | np = gen->np; |
178 | | | 178 | |
179 | if (encrypted) { | | 179 | if (encrypted) { |
180 | if (isakmp->np != ISAKMP_NPTYPE_HASH) { | | 180 | if (isakmp->np != ISAKMP_NPTYPE_HASH) { |
181 | plog(LLV_ERROR, LOCATION, NULL, | | 181 | plog(LLV_ERROR, LOCATION, NULL, |
182 | "ignore information because the " | | 182 | "ignore information because the " |
183 | "message has no hash payload.\n"); | | 183 | "message has no hash payload.\n"); |
184 | goto end; | | 184 | goto end; |
185 | } | | 185 | } |
186 | | | 186 | |
187 | if (iph1->status != PHASE1ST_ESTABLISHED && | | 187 | if (iph1->status != PHASE1ST_ESTABLISHED && |
188 | iph1->status != PHASE1ST_DYING) { | | 188 | iph1->status != PHASE1ST_DYING) { |
189 | plog(LLV_ERROR, LOCATION, NULL, | | 189 | plog(LLV_ERROR, LOCATION, NULL, |
190 | "ignore information because ISAKMP-SA " | | 190 | "ignore information because ISAKMP-SA " |
191 | "has not been established yet.\n"); | | 191 | "has not been established yet.\n"); |
192 | goto end; | | 192 | goto end; |
193 | } | | 193 | } |
194 | | | 194 | |
195 | /* Safety check */ | | 195 | /* Safety check */ |
196 | if (msg->l < sizeof(*isakmp) + ntohs(gen->len) + sizeof(*nd)) { | | 196 | if (msg->l < sizeof(*isakmp) + ntohs(gen->len) + sizeof(*nd)) { |
197 | plog(LLV_ERROR, LOCATION, NULL, | | 197 | plog(LLV_ERROR, LOCATION, NULL, |
198 | "ignore information because the " | | 198 | "ignore information because the " |
199 | "message is too short - %zu byte(s).\n", | | 199 | "message is too short - %zu byte(s).\n", |
200 | msg->l); | | 200 | msg->l); |
201 | goto end; | | 201 | goto end; |
202 | } | | 202 | } |
203 | | | 203 | |
204 | p = (caddr_t) gen + sizeof(struct isakmp_gen); | | 204 | p = (caddr_t) gen + sizeof(struct isakmp_gen); |
205 | nd = (struct isakmp_gen *) ((caddr_t) gen + ntohs(gen->len)); | | 205 | nd = (struct isakmp_gen *) ((caddr_t) gen + ntohs(gen->len)); |
206 | | | 206 | |
207 | /* nd length check */ | | 207 | /* nd length check */ |
208 | if (ntohs(nd->len) > msg->l - (sizeof(struct isakmp) + | | 208 | if (ntohs(nd->len) > msg->l - (sizeof(struct isakmp) + |
209 | ntohs(gen->len))) { | | 209 | ntohs(gen->len))) { |
210 | plog(LLV_ERROR, LOCATION, NULL, | | 210 | plog(LLV_ERROR, LOCATION, NULL, |
211 | "too long payload length (broken message?)\n"); | | 211 | "too long payload length (broken message?)\n"); |
212 | goto end; | | 212 | goto end; |
213 | } | | 213 | } |
214 | | | 214 | |
215 | if (ntohs(nd->len) < sizeof(*nd)) { | | 215 | if (ntohs(nd->len) < sizeof(*nd)) { |
216 | plog(LLV_ERROR, LOCATION, NULL, | | 216 | plog(LLV_ERROR, LOCATION, NULL, |
217 | "too short payload length (broken message?)\n"); | | 217 | "too short payload length (broken message?)\n"); |
218 | goto end; | | 218 | goto end; |
219 | } | | 219 | } |
220 | | | 220 | |
221 | payload = vmalloc(ntohs(nd->len)); | | 221 | payload = vmalloc(ntohs(nd->len)); |
222 | if (payload == NULL) { | | 222 | if (payload == NULL) { |
223 | plog(LLV_ERROR, LOCATION, NULL, | | 223 | plog(LLV_ERROR, LOCATION, NULL, |
224 | "cannot allocate memory\n"); | | 224 | "cannot allocate memory\n"); |
225 | goto end; | | 225 | goto end; |
226 | } | | 226 | } |
227 | | | 227 | |
228 | memcpy(payload->v, (caddr_t) nd, ntohs(nd->len)); | | 228 | memcpy(payload->v, (caddr_t) nd, ntohs(nd->len)); |
229 | | | 229 | |
230 | /* compute HASH */ | | 230 | /* compute HASH */ |
231 | hash = oakley_compute_hash1(iph1, isakmp->msgid, payload); | | 231 | hash = oakley_compute_hash1(iph1, isakmp->msgid, payload); |
232 | if (hash == NULL) { | | 232 | if (hash == NULL) { |
233 | plog(LLV_ERROR, LOCATION, NULL, | | 233 | plog(LLV_ERROR, LOCATION, NULL, |
234 | "cannot compute hash\n"); | | 234 | "cannot compute hash\n"); |
235 | | | 235 | |
236 | vfree(payload); | | 236 | vfree(payload); |
237 | goto end; | | 237 | goto end; |
238 | } | | 238 | } |
239 | | | 239 | |
240 | if (ntohs(gen->len) - sizeof(struct isakmp_gen) != hash->l) { | | 240 | if (ntohs(gen->len) - sizeof(struct isakmp_gen) != hash->l) { |
241 | plog(LLV_ERROR, LOCATION, NULL, | | 241 | plog(LLV_ERROR, LOCATION, NULL, |
242 | "ignore information due to hash length mismatch\n"); | | 242 | "ignore information due to hash length mismatch\n"); |
243 | | | 243 | |
244 | vfree(hash); | | 244 | vfree(hash); |
245 | vfree(payload); | | 245 | vfree(payload); |
246 | goto end; | | 246 | goto end; |
247 | } | | 247 | } |
248 | | | 248 | |
249 | if (memcmp(p, hash->v, hash->l) != 0) { | | 249 | if (memcmp(p, hash->v, hash->l) != 0) { |
250 | plog(LLV_ERROR, LOCATION, NULL, | | 250 | plog(LLV_ERROR, LOCATION, NULL, |
251 | "ignore information due to hash mismatch\n"); | | 251 | "ignore information due to hash mismatch\n"); |
252 | | | 252 | |
253 | vfree(hash); | | 253 | vfree(hash); |
254 | vfree(payload); | | 254 | vfree(payload); |
255 | goto end; | | 255 | goto end; |
256 | } | | 256 | } |
257 | | | 257 | |
258 | plog(LLV_DEBUG, LOCATION, NULL, "hash validated.\n"); | | 258 | plog(LLV_DEBUG, LOCATION, NULL, "hash validated.\n"); |
259 | | | 259 | |
260 | vfree(hash); | | 260 | vfree(hash); |
261 | vfree(payload); | | 261 | vfree(payload); |
262 | } else { | | 262 | } else { |
263 | /* make sure the packet was encrypted after the beginning of phase 1. */ | | 263 | /* make sure the packet was encrypted after the beginning of phase 1. */ |
264 | switch (iph1->etype) { | | 264 | switch (iph1->etype) { |
265 | case ISAKMP_ETYPE_AGG: | | 265 | case ISAKMP_ETYPE_AGG: |
266 | case ISAKMP_ETYPE_BASE: | | 266 | case ISAKMP_ETYPE_BASE: |
267 | case ISAKMP_ETYPE_IDENT: | | 267 | case ISAKMP_ETYPE_IDENT: |
268 | if ((iph1->side == INITIATOR && iph1->status < PHASE1ST_MSG3SENT) | | 268 | if ((iph1->side == INITIATOR && iph1->status < PHASE1ST_MSG3SENT) |
269 | || (iph1->side == RESPONDER && iph1->status < PHASE1ST_MSG2SENT)) { | | 269 | || (iph1->side == RESPONDER && iph1->status < PHASE1ST_MSG2SENT)) { |
270 | break; | | 270 | break; |
271 | } | | 271 | } |
272 | /*FALLTHRU*/ | | 272 | /*FALLTHRU*/ |
273 | default: | | 273 | default: |
274 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 274 | plog(LLV_ERROR, LOCATION, iph1->remote, |
275 | "%s message must be encrypted\n", | | 275 | "%s message must be encrypted\n", |
276 | s_isakmp_nptype(np)); | | 276 | s_isakmp_nptype(np)); |
277 | error = 0; | | 277 | error = 0; |
278 | goto end; | | 278 | goto end; |
279 | } | | 279 | } |
280 | } | | 280 | } |
281 | | | 281 | |
282 | if (!(pbuf = isakmp_parse(msg))) { | | 282 | if (!(pbuf = isakmp_parse(msg))) { |
283 | error = -1; | | 283 | error = -1; |
284 | goto end; | | 284 | goto end; |
285 | } | | 285 | } |
286 | | | 286 | |
287 | error = 0; | | 287 | error = 0; |
288 | for (pa = (struct isakmp_parse_t *)pbuf->v; pa->type; pa++) { | | 288 | for (pa = (struct isakmp_parse_t *)pbuf->v; pa->type; pa++) { |
289 | switch (pa->type) { | | 289 | switch (pa->type) { |
290 | case ISAKMP_NPTYPE_HASH: | | 290 | case ISAKMP_NPTYPE_HASH: |
291 | /* Handled above */ | | 291 | /* Handled above */ |
292 | break; | | 292 | break; |
293 | case ISAKMP_NPTYPE_N: | | 293 | case ISAKMP_NPTYPE_N: |
294 | error = isakmp_info_recv_n(iph1, | | 294 | error = isakmp_info_recv_n(iph1, |
295 | (struct isakmp_pl_n *)pa->ptr, | | 295 | (struct isakmp_pl_n *)pa->ptr, |
296 | msgid, encrypted); | | 296 | msgid, encrypted); |
297 | break; | | 297 | break; |
298 | case ISAKMP_NPTYPE_D: | | 298 | case ISAKMP_NPTYPE_D: |
299 | error = isakmp_info_recv_d(iph1, | | 299 | error = isakmp_info_recv_d(iph1, |
300 | (struct isakmp_pl_d *)pa->ptr, | | 300 | (struct isakmp_pl_d *)pa->ptr, |
301 | msgid, encrypted); | | 301 | msgid, encrypted); |
302 | break; | | 302 | break; |
303 | case ISAKMP_NPTYPE_NONCE: | | 303 | case ISAKMP_NPTYPE_NONCE: |
304 | /* XXX to be 6.4.2 ike-01.txt */ | | 304 | /* XXX to be 6.4.2 ike-01.txt */ |
305 | /* XXX IV is to be synchronized. */ | | 305 | /* XXX IV is to be synchronized. */ |
306 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 306 | plog(LLV_ERROR, LOCATION, iph1->remote, |
307 | "ignore Acknowledged Informational\n"); | | 307 | "ignore Acknowledged Informational\n"); |
308 | break; | | 308 | break; |
309 | default: | | 309 | default: |
310 | /* don't send information, see isakmp_ident_r1() */ | | 310 | /* don't send information, see isakmp_ident_r1() */ |
311 | error = 0; | | 311 | error = 0; |
312 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 312 | plog(LLV_ERROR, LOCATION, iph1->remote, |
313 | "reject the packet, " | | 313 | "reject the packet, " |
314 | "received unexpected payload type %s.\n", | | 314 | "received unexpected payload type %s.\n", |
315 | s_isakmp_nptype(gen->np)); | | 315 | s_isakmp_nptype(gen->np)); |
316 | } | | 316 | } |
317 | if (error < 0) | | 317 | if (error < 0) |
318 | break; | | 318 | break; |
319 | } | | 319 | } |
320 | end: | | 320 | end: |
321 | if (msg != NULL) | | 321 | if (msg != NULL) |
322 | vfree(msg); | | 322 | vfree(msg); |
323 | if (pbuf != NULL) | | 323 | if (pbuf != NULL) |
324 | vfree(pbuf); | | 324 | vfree(pbuf); |
325 | return error; | | 325 | return error; |
326 | } | | 326 | } |
327 | | | 327 | |
328 | | | 328 | |
329 | /* | | 329 | /* |
330 | * log unhandled / unallowed Notification payload | | 330 | * log unhandled / unallowed Notification payload |
331 | */ | | 331 | */ |
332 | int | | 332 | int |
333 | isakmp_log_notify(iph1, notify, exchange) | | 333 | isakmp_log_notify(iph1, notify, exchange) |
334 | struct ph1handle *iph1; | | 334 | struct ph1handle *iph1; |
335 | struct isakmp_pl_n *notify; | | 335 | struct isakmp_pl_n *notify; |
336 | const char *exchange; | | 336 | const char *exchange; |
337 | { | | 337 | { |
338 | u_int type; | | 338 | u_int type; |
339 | char *nraw, *ndata, *nhex; | | 339 | char *nraw, *ndata, *nhex; |
340 | size_t l; | | 340 | size_t l; |
341 | | | 341 | |
342 | type = ntohs(notify->type); | | 342 | type = ntohs(notify->type); |
343 | if (ntohs(notify->h.len) < sizeof(*notify) + notify->spi_size) { | | 343 | if (ntohs(notify->h.len) < sizeof(*notify) + notify->spi_size) { |
344 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 344 | plog(LLV_ERROR, LOCATION, iph1->remote, |
345 | "invalid spi_size in %s notification in %s.\n", | | 345 | "invalid spi_size in %s notification in %s.\n", |
346 | s_isakmp_notify_msg(type), exchange); | | 346 | s_isakmp_notify_msg(type), exchange); |
347 | return -1; | | 347 | return -1; |
348 | } | | 348 | } |
349 | | | 349 | |
350 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 350 | plog(LLV_ERROR, LOCATION, iph1->remote, |
351 | "notification %s received in %s.\n", | | 351 | "notification %s received in %s.\n", |
352 | s_isakmp_notify_msg(type), exchange); | | 352 | s_isakmp_notify_msg(type), exchange); |
353 | | | 353 | |
354 | nraw = ((char*) notify) + sizeof(*notify) + notify->spi_size; | | 354 | nraw = ((char*) notify) + sizeof(*notify) + notify->spi_size; |
355 | l = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size; | | 355 | l = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size; |
356 | if (l > 0) { | | 356 | if (l > 0) { |
357 | if (type >= ISAKMP_NTYPE_MINERROR && | | 357 | if (type >= ISAKMP_NTYPE_MINERROR && |
358 | type <= ISAKMP_NTYPE_MAXERROR) { | | 358 | type <= ISAKMP_NTYPE_MAXERROR) { |
359 | ndata = binsanitize(nraw, l); | | 359 | ndata = binsanitize(nraw, l); |
360 | if (ndata != NULL) { | | 360 | if (ndata != NULL) { |
361 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 361 | plog(LLV_ERROR, LOCATION, iph1->remote, |
362 | "error message: '%s'.\n", | | 362 | "error message: '%s'.\n", |
363 | ndata); | | 363 | ndata); |
364 | racoon_free(ndata); | | 364 | racoon_free(ndata); |
365 | } else { | | 365 | } else { |
366 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 366 | plog(LLV_ERROR, LOCATION, iph1->remote, |
367 | "Cannot allocate memory\n"); | | 367 | "Cannot allocate memory\n"); |
368 | } | | 368 | } |
369 | } else { | | 369 | } else { |
370 | nhex = val2str(nraw, l); | | 370 | nhex = val2str(nraw, l); |
371 | if (nhex != NULL) { | | 371 | if (nhex != NULL) { |
372 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 372 | plog(LLV_ERROR, LOCATION, iph1->remote, |
373 | "notification payload: %s.\n", | | 373 | "notification payload: %s.\n", |
374 | nhex); | | 374 | nhex); |
375 | racoon_free(nhex); | | 375 | racoon_free(nhex); |
376 | } else { | | 376 | } else { |
377 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 377 | plog(LLV_ERROR, LOCATION, iph1->remote, |
378 | "Cannot allocate memory\n"); | | 378 | "Cannot allocate memory\n"); |
379 | } | | 379 | } |
380 | } | | 380 | } |
381 | } | | 381 | } |
382 | | | 382 | |
383 | return 0; | | 383 | return 0; |
384 | } | | 384 | } |
385 | | | 385 | |
386 | | | 386 | |
387 | /* | | 387 | /* |
388 | * handling of Notification payload | | 388 | * handling of Notification payload |
389 | */ | | 389 | */ |
390 | static int | | 390 | static int |
391 | isakmp_info_recv_n(iph1, notify, msgid, encrypted) | | 391 | isakmp_info_recv_n(iph1, notify, msgid, encrypted) |
392 | struct ph1handle *iph1; | | 392 | struct ph1handle *iph1; |
393 | struct isakmp_pl_n *notify; | | 393 | struct isakmp_pl_n *notify; |
394 | u_int32_t msgid; | | 394 | u_int32_t msgid; |
395 | int encrypted; | | 395 | int encrypted; |
396 | { | | 396 | { |
397 | u_int type; | | 397 | u_int type; |
398 | | | 398 | |
399 | type = ntohs(notify->type); | | 399 | type = ntohs(notify->type); |
400 | switch (type) { | | 400 | switch (type) { |
401 | case ISAKMP_NTYPE_CONNECTED: | | 401 | case ISAKMP_NTYPE_CONNECTED: |
402 | case ISAKMP_NTYPE_RESPONDER_LIFETIME: | | 402 | case ISAKMP_NTYPE_RESPONDER_LIFETIME: |
403 | case ISAKMP_NTYPE_REPLAY_STATUS: | | 403 | case ISAKMP_NTYPE_REPLAY_STATUS: |
404 | #ifdef ENABLE_HYBRID | | 404 | #ifdef ENABLE_HYBRID |
405 | case ISAKMP_NTYPE_UNITY_HEARTBEAT: | | 405 | case ISAKMP_NTYPE_UNITY_HEARTBEAT: |
406 | #endif | | 406 | #endif |
407 | /* do something */ | | 407 | /* do something */ |
408 | break; | | 408 | break; |
409 | case ISAKMP_NTYPE_INITIAL_CONTACT: | | 409 | case ISAKMP_NTYPE_INITIAL_CONTACT: |
410 | if (encrypted) | | 410 | if (encrypted) |
411 | return isakmp_info_recv_initialcontact(iph1, NULL); | | 411 | return isakmp_info_recv_initialcontact(iph1, NULL); |
412 | break; | | 412 | break; |
413 | #ifdef ENABLE_DPD | | 413 | #ifdef ENABLE_DPD |
414 | case ISAKMP_NTYPE_R_U_THERE: | | 414 | case ISAKMP_NTYPE_R_U_THERE: |
415 | if (encrypted) | | 415 | if (encrypted) |
416 | return isakmp_info_recv_r_u(iph1, | | 416 | return isakmp_info_recv_r_u(iph1, |
417 | (struct isakmp_pl_ru *)notify, msgid); | | 417 | (struct isakmp_pl_ru *)notify, msgid); |
418 | break; | | 418 | break; |
419 | case ISAKMP_NTYPE_R_U_THERE_ACK: | | 419 | case ISAKMP_NTYPE_R_U_THERE_ACK: |
420 | if (encrypted) | | 420 | if (encrypted) |
421 | return isakmp_info_recv_r_u_ack(iph1, | | 421 | return isakmp_info_recv_r_u_ack(iph1, |
422 | (struct isakmp_pl_ru *)notify, msgid); | | 422 | (struct isakmp_pl_ru *)notify, msgid); |
423 | break; | | 423 | break; |
424 | #endif | | 424 | #endif |
425 | } | | 425 | } |
426 | | | 426 | |
427 | /* If we receive a error notification we should delete the related | | 427 | /* If we receive a error notification we should delete the related |
428 | * phase1 / phase2 handle, and send an event to racoonctl. | | 428 | * phase1 / phase2 handle, and send an event to racoonctl. |
429 | * However, since phase1 error notifications are not encrypted and | | 429 | * However, since phase1 error notifications are not encrypted and |
430 | * can not be authenticated, it would allow a DoS attack possibility | | 430 | * can not be authenticated, it would allow a DoS attack possibility |
431 | * to handle them. | | 431 | * to handle them. |
432 | * Phase2 error notifications should be encrypted, so we could handle | | 432 | * Phase2 error notifications should be encrypted, so we could handle |
433 | * those, but it needs implementing (the old code didn't implement | | 433 | * those, but it needs implementing (the old code didn't implement |
434 | * that either). | | 434 | * that either). |
435 | * So we are good to just log the messages here. | | 435 | * So we are good to just log the messages here. |
436 | */ | | 436 | */ |
437 | if (encrypted) | | 437 | if (encrypted) |
438 | isakmp_log_notify(iph1, notify, "informational exchange"); | | 438 | isakmp_log_notify(iph1, notify, "informational exchange"); |
439 | else | | 439 | else |
440 | isakmp_log_notify(iph1, notify, "unencrypted informational exchange"); | | 440 | isakmp_log_notify(iph1, notify, "unencrypted informational exchange"); |
441 | | | 441 | |
442 | return 0; | | 442 | return 0; |
443 | } | | 443 | } |
444 | | | 444 | |
445 | /* | | 445 | /* |
446 | * handling of Deletion payload | | 446 | * handling of Deletion payload |
447 | */ | | 447 | */ |
448 | static int | | 448 | static int |
449 | isakmp_info_recv_d(iph1, delete, msgid, encrypted) | | 449 | isakmp_info_recv_d(iph1, delete, msgid, encrypted) |
450 | struct ph1handle *iph1; | | 450 | struct ph1handle *iph1; |
451 | struct isakmp_pl_d *delete; | | 451 | struct isakmp_pl_d *delete; |
452 | u_int32_t msgid; | | 452 | u_int32_t msgid; |
453 | int encrypted; | | 453 | int encrypted; |
454 | { | | 454 | { |
455 | int tlen, num_spi; | | 455 | int tlen, num_spi; |
456 | vchar_t *pbuf; | | 456 | vchar_t *pbuf; |
457 | int protected = 0; | | 457 | int protected = 0; |
458 | struct ph1handle *del_ph1; | | 458 | struct ph1handle *del_ph1; |
459 | struct ph2handle *iph2; | | 459 | struct ph2handle *iph2; |
460 | union { | | 460 | union { |
461 | u_int32_t spi32; | | 461 | u_int32_t spi32; |
462 | u_int16_t spi16[2]; | | 462 | u_int16_t spi16[2]; |
463 | } spi; | | 463 | } spi; |
464 | | | 464 | |
465 | if (ntohl(delete->doi) != IPSEC_DOI) { | | 465 | if (ntohl(delete->doi) != IPSEC_DOI) { |
466 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 466 | plog(LLV_ERROR, LOCATION, iph1->remote, |
467 | "delete payload with invalid doi:%d.\n", | | 467 | "delete payload with invalid doi:%d.\n", |
468 | ntohl(delete->doi)); | | 468 | ntohl(delete->doi)); |
469 | #ifdef ENABLE_HYBRID | | 469 | #ifdef ENABLE_HYBRID |
470 | /* | | 470 | /* |
471 | * At deconnexion time, Cisco VPN client does this | | 471 | * At deconnexion time, Cisco VPN client does this |
472 | * with a zero DOI. Don't give up in that situation. | | 472 | * with a zero DOI. Don't give up in that situation. |
473 | */ | | 473 | */ |
474 | if (((iph1->mode_cfg->flags & | | 474 | if (((iph1->mode_cfg->flags & |
475 | ISAKMP_CFG_VENDORID_UNITY) == 0) || (delete->doi != 0)) | | 475 | ISAKMP_CFG_VENDORID_UNITY) == 0) || (delete->doi != 0)) |
476 | return 0; | | 476 | return 0; |
477 | #else | | 477 | #else |
478 | return 0; | | 478 | return 0; |
479 | #endif | | 479 | #endif |
480 | } | | 480 | } |
481 | | | 481 | |
482 | num_spi = ntohs(delete->num_spi); | | 482 | num_spi = ntohs(delete->num_spi); |
483 | tlen = ntohs(delete->h.len) - sizeof(struct isakmp_pl_d); | | 483 | tlen = ntohs(delete->h.len) - sizeof(struct isakmp_pl_d); |
484 | | | 484 | |
485 | if (tlen != num_spi * delete->spi_size) { | | 485 | if (tlen != num_spi * delete->spi_size) { |
486 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 486 | plog(LLV_ERROR, LOCATION, iph1->remote, |
487 | "deletion payload with invalid length.\n"); | | 487 | "deletion payload with invalid length.\n"); |
488 | return 0; | | 488 | return 0; |
489 | } | | 489 | } |
490 | | | 490 | |
491 | plog(LLV_DEBUG, LOCATION, iph1->remote, | | 491 | plog(LLV_DEBUG, LOCATION, iph1->remote, |
492 | "delete payload for protocol %s\n", | | 492 | "delete payload for protocol %s\n", |
493 | s_ipsecdoi_proto(delete->proto_id)); | | 493 | s_ipsecdoi_proto(delete->proto_id)); |
494 | | | 494 | |
495 | if(!iph1->rmconf->weak_phase1_check && !encrypted) { | | 495 | if((iph1 == NULL || !iph1->rmconf->weak_phase1_check) && !encrypted) { |
496 | plog(LLV_WARNING, LOCATION, iph1->remote, | | 496 | plog(LLV_WARNING, LOCATION, iph1->remote, |
497 | "Ignoring unencrypted delete payload " | | 497 | "Ignoring unencrypted delete payload " |
498 | "(check the weak_phase1_check option)\n"); | | 498 | "(check the weak_phase1_check option)\n"); |
499 | return 0; | | 499 | return 0; |
500 | } | | 500 | } |
501 | | | 501 | |
502 | switch (delete->proto_id) { | | 502 | switch (delete->proto_id) { |
503 | case IPSECDOI_PROTO_ISAKMP: | | 503 | case IPSECDOI_PROTO_ISAKMP: |
504 | if (delete->spi_size != sizeof(isakmp_index)) { | | 504 | if (delete->spi_size != sizeof(isakmp_index)) { |
505 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 505 | plog(LLV_ERROR, LOCATION, iph1->remote, |
506 | "delete payload with strange spi " | | 506 | "delete payload with strange spi " |
507 | "size %d(proto_id:%d)\n", | | 507 | "size %d(proto_id:%d)\n", |
508 | delete->spi_size, delete->proto_id); | | 508 | delete->spi_size, delete->proto_id); |
509 | return 0; | | 509 | return 0; |
510 | } | | 510 | } |
511 | | | 511 | |
512 | del_ph1=getph1byindex((isakmp_index *)(delete + 1)); | | 512 | del_ph1=getph1byindex((isakmp_index *)(delete + 1)); |
513 | if(del_ph1 != NULL){ | | 513 | if(del_ph1 != NULL){ |
514 | | | 514 | |
515 | evt_phase1(iph1, EVT_PHASE1_PEER_DELETED, NULL); | | 515 | evt_phase1(iph1, EVT_PHASE1_PEER_DELETED, NULL); |
516 | sched_cancel(&del_ph1->scr); | | 516 | sched_cancel(&del_ph1->scr); |
517 | | | 517 | |
518 | /* | | 518 | /* |
519 | * Delete also IPsec-SAs if rekeying is enabled. | | 519 | * Delete also IPsec-SAs if rekeying is enabled. |
520 | */ | | 520 | */ |
521 | if (ph1_rekey_enabled(del_ph1)) | | 521 | if (ph1_rekey_enabled(del_ph1)) |
522 | purge_remote(del_ph1); | | 522 | purge_remote(del_ph1); |
523 | else | | 523 | else |
524 | isakmp_ph1expire(del_ph1); | | 524 | isakmp_ph1expire(del_ph1); |
525 | } | | 525 | } |
526 | break; | | 526 | break; |
527 | | | 527 | |
528 | case IPSECDOI_PROTO_IPSEC_AH: | | 528 | case IPSECDOI_PROTO_IPSEC_AH: |
529 | case IPSECDOI_PROTO_IPSEC_ESP: | | 529 | case IPSECDOI_PROTO_IPSEC_ESP: |
530 | if (delete->spi_size != sizeof(u_int32_t)) { | | 530 | if (delete->spi_size != sizeof(u_int32_t)) { |
531 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 531 | plog(LLV_ERROR, LOCATION, iph1->remote, |
532 | "delete payload with strange spi " | | 532 | "delete payload with strange spi " |
533 | "size %d(proto_id:%d)\n", | | 533 | "size %d(proto_id:%d)\n", |
534 | delete->spi_size, delete->proto_id); | | 534 | delete->spi_size, delete->proto_id); |
535 | return 0; | | 535 | return 0; |
536 | } | | 536 | } |
537 | purge_ipsec_spi(iph1->remote, delete->proto_id, | | 537 | purge_ipsec_spi(iph1->remote, delete->proto_id, |
538 | (u_int32_t *)(delete + 1), num_spi); | | 538 | (u_int32_t *)(delete + 1), num_spi); |
539 | break; | | 539 | break; |
540 | | | 540 | |
541 | case IPSECDOI_PROTO_IPCOMP: | | 541 | case IPSECDOI_PROTO_IPCOMP: |
542 | /* need to handle both 16bit/32bit SPI */ | | 542 | /* need to handle both 16bit/32bit SPI */ |
543 | memset(&spi, 0, sizeof(spi)); | | 543 | memset(&spi, 0, sizeof(spi)); |
544 | if (delete->spi_size == sizeof(spi.spi16[1])) { | | 544 | if (delete->spi_size == sizeof(spi.spi16[1])) { |
545 | memcpy(&spi.spi16[1], delete + 1, | | 545 | memcpy(&spi.spi16[1], delete + 1, |
546 | sizeof(spi.spi16[1])); | | 546 | sizeof(spi.spi16[1])); |
547 | } else if (delete->spi_size == sizeof(spi.spi32)) | | 547 | } else if (delete->spi_size == sizeof(spi.spi32)) |
548 | memcpy(&spi.spi32, delete + 1, sizeof(spi.spi32)); | | 548 | memcpy(&spi.spi32, delete + 1, sizeof(spi.spi32)); |
549 | else { | | 549 | else { |
550 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 550 | plog(LLV_ERROR, LOCATION, iph1->remote, |
551 | "delete payload with strange spi " | | 551 | "delete payload with strange spi " |
552 | "size %d(proto_id:%d)\n", | | 552 | "size %d(proto_id:%d)\n", |
553 | delete->spi_size, delete->proto_id); | | 553 | delete->spi_size, delete->proto_id); |
554 | return 0; | | 554 | return 0; |
555 | } | | 555 | } |
556 | purge_ipsec_spi(iph1->remote, delete->proto_id, | | 556 | purge_ipsec_spi(iph1->remote, delete->proto_id, |
557 | &spi.spi32, num_spi); | | 557 | &spi.spi32, num_spi); |
558 | break; | | 558 | break; |
559 | | | 559 | |
560 | default: | | 560 | default: |
561 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 561 | plog(LLV_ERROR, LOCATION, iph1->remote, |
562 | "deletion message received, " | | 562 | "deletion message received, " |
563 | "invalid proto_id: %d\n", | | 563 | "invalid proto_id: %d\n", |
564 | delete->proto_id); | | 564 | delete->proto_id); |
565 | return 0; | | 565 | return 0; |
566 | } | | 566 | } |
567 | | | 567 | |
568 | plog(LLV_DEBUG, LOCATION, NULL, "purged SAs.\n"); | | 568 | plog(LLV_DEBUG, LOCATION, NULL, "purged SAs.\n"); |
569 | | | 569 | |
570 | return 0; | | 570 | return 0; |
571 | } | | 571 | } |
572 | | | 572 | |
573 | /* | | 573 | /* |
574 | * send Delete payload (for ISAKMP SA) in Informational exchange. | | 574 | * send Delete payload (for ISAKMP SA) in Informational exchange. |
575 | */ | | 575 | */ |
576 | int | | 576 | int |
577 | isakmp_info_send_d1(iph1) | | 577 | isakmp_info_send_d1(iph1) |
578 | struct ph1handle *iph1; | | 578 | struct ph1handle *iph1; |
579 | { | | 579 | { |
580 | struct isakmp_pl_d *d; | | 580 | struct isakmp_pl_d *d; |
581 | vchar_t *payload = NULL; | | 581 | vchar_t *payload = NULL; |
582 | int tlen; | | 582 | int tlen; |
583 | int error = 0; | | 583 | int error = 0; |
584 | | | 584 | |
585 | if (iph1->status != PHASE2ST_ESTABLISHED) | | 585 | if (iph1->status != PHASE2ST_ESTABLISHED) |
586 | return 0; | | 586 | return 0; |
587 | | | 587 | |
588 | /* create delete payload */ | | 588 | /* create delete payload */ |
589 | | | 589 | |
590 | /* send SPIs of inbound SAs. */ | | 590 | /* send SPIs of inbound SAs. */ |
591 | /* XXX should send outbound SAs's ? */ | | 591 | /* XXX should send outbound SAs's ? */ |
592 | tlen = sizeof(*d) + sizeof(isakmp_index); | | 592 | tlen = sizeof(*d) + sizeof(isakmp_index); |
593 | payload = vmalloc(tlen); | | 593 | payload = vmalloc(tlen); |
594 | if (payload == NULL) { | | 594 | if (payload == NULL) { |
595 | plog(LLV_ERROR, LOCATION, NULL, | | 595 | plog(LLV_ERROR, LOCATION, NULL, |
596 | "failed to get buffer for payload.\n"); | | 596 | "failed to get buffer for payload.\n"); |
597 | return errno; | | 597 | return errno; |
598 | } | | 598 | } |
599 | | | 599 | |
600 | d = (struct isakmp_pl_d *)payload->v; | | 600 | d = (struct isakmp_pl_d *)payload->v; |
601 | d->h.np = ISAKMP_NPTYPE_NONE; | | 601 | d->h.np = ISAKMP_NPTYPE_NONE; |
602 | d->h.len = htons(tlen); | | 602 | d->h.len = htons(tlen); |
603 | d->doi = htonl(IPSEC_DOI); | | 603 | d->doi = htonl(IPSEC_DOI); |
604 | d->proto_id = IPSECDOI_PROTO_ISAKMP; | | 604 | d->proto_id = IPSECDOI_PROTO_ISAKMP; |
605 | d->spi_size = sizeof(isakmp_index); | | 605 | d->spi_size = sizeof(isakmp_index); |
606 | d->num_spi = htons(1); | | 606 | d->num_spi = htons(1); |
607 | memcpy(d + 1, &iph1->index, sizeof(isakmp_index)); | | 607 | memcpy(d + 1, &iph1->index, sizeof(isakmp_index)); |
608 | | | 608 | |
609 | error = isakmp_info_send_common(iph1, payload, | | 609 | error = isakmp_info_send_common(iph1, payload, |
610 | ISAKMP_NPTYPE_D, 0); | | 610 | ISAKMP_NPTYPE_D, 0); |
611 | vfree(payload); | | 611 | vfree(payload); |
612 | | | 612 | |
613 | return error; | | 613 | return error; |
614 | } | | 614 | } |
615 | | | 615 | |
616 | /* | | 616 | /* |
617 | * send Delete payload (for IPsec SA) in Informational exchange, based on | | 617 | * send Delete payload (for IPsec SA) in Informational exchange, based on |
618 | * pfkey msg. It sends always single SPI. | | 618 | * pfkey msg. It sends always single SPI. |
619 | */ | | 619 | */ |
620 | int | | 620 | int |
621 | isakmp_info_send_d2(iph2) | | 621 | isakmp_info_send_d2(iph2) |
622 | struct ph2handle *iph2; | | 622 | struct ph2handle *iph2; |
623 | { | | 623 | { |
624 | struct ph1handle *iph1; | | 624 | struct ph1handle *iph1; |
625 | struct saproto *pr; | | 625 | struct saproto *pr; |
626 | struct isakmp_pl_d *d; | | 626 | struct isakmp_pl_d *d; |
627 | vchar_t *payload = NULL; | | 627 | vchar_t *payload = NULL; |
628 | int tlen; | | 628 | int tlen; |
629 | int error = 0; | | 629 | int error = 0; |
630 | u_int8_t *spi; | | 630 | u_int8_t *spi; |
631 | | | 631 | |
632 | if (iph2->status != PHASE2ST_ESTABLISHED) | | 632 | if (iph2->status != PHASE2ST_ESTABLISHED) |
633 | return 0; | | 633 | return 0; |
634 | | | 634 | |
635 | /* | | 635 | /* |
636 | * don't send delete information if there is no phase 1 handler. | | 636 | * don't send delete information if there is no phase 1 handler. |
637 | * It's nonsensical to negotiate phase 1 to send the information. | | 637 | * It's nonsensical to negotiate phase 1 to send the information. |
638 | */ | | 638 | */ |
639 | iph1 = getph1byaddr(iph2->src, iph2->dst, 0); | | 639 | iph1 = getph1byaddr(iph2->src, iph2->dst, 0); |
640 | if (iph1 == NULL){ | | 640 | if (iph1 == NULL){ |
641 | plog(LLV_DEBUG2, LOCATION, NULL, | | 641 | plog(LLV_DEBUG2, LOCATION, NULL, |
642 | "No ph1 handler found, could not send DELETE_SA\n"); | | 642 | "No ph1 handler found, could not send DELETE_SA\n"); |
643 | return 0; | | 643 | return 0; |
644 | } | | 644 | } |
645 | | | 645 | |
646 | /* create delete payload */ | | 646 | /* create delete payload */ |
647 | for (pr = iph2->approval->head; pr != NULL; pr = pr->next) { | | 647 | for (pr = iph2->approval->head; pr != NULL; pr = pr->next) { |
648 | | | 648 | |
649 | /* send SPIs of inbound SAs. */ | | 649 | /* send SPIs of inbound SAs. */ |
650 | /* | | 650 | /* |
651 | * XXX should I send outbound SAs's ? | | 651 | * XXX should I send outbound SAs's ? |
652 | * I send inbound SAs's SPI only at the moment because I can't | | 652 | * I send inbound SAs's SPI only at the moment because I can't |
653 | * decode any more if peer send encoded packet without aware of | | 653 | * decode any more if peer send encoded packet without aware of |
654 | * deletion of SA. Outbound SAs don't come under the situation. | | 654 | * deletion of SA. Outbound SAs don't come under the situation. |
655 | */ | | 655 | */ |
656 | tlen = sizeof(*d) + pr->spisize; | | 656 | tlen = sizeof(*d) + pr->spisize; |
657 | payload = vmalloc(tlen); | | 657 | payload = vmalloc(tlen); |
658 | if (payload == NULL) { | | 658 | if (payload == NULL) { |
659 | plog(LLV_ERROR, LOCATION, NULL, | | 659 | plog(LLV_ERROR, LOCATION, NULL, |
660 | "failed to get buffer for payload.\n"); | | 660 | "failed to get buffer for payload.\n"); |
661 | return errno; | | 661 | return errno; |
662 | } | | 662 | } |
663 | | | 663 | |
664 | d = (struct isakmp_pl_d *)payload->v; | | 664 | d = (struct isakmp_pl_d *)payload->v; |
665 | d->h.np = ISAKMP_NPTYPE_NONE; | | 665 | d->h.np = ISAKMP_NPTYPE_NONE; |
666 | d->h.len = htons(tlen); | | 666 | d->h.len = htons(tlen); |
667 | d->doi = htonl(IPSEC_DOI); | | 667 | d->doi = htonl(IPSEC_DOI); |
668 | d->proto_id = pr->proto_id; | | 668 | d->proto_id = pr->proto_id; |
669 | d->spi_size = pr->spisize; | | 669 | d->spi_size = pr->spisize; |
670 | d->num_spi = htons(1); | | 670 | d->num_spi = htons(1); |
671 | /* | | 671 | /* |
672 | * XXX SPI bits are left-filled, for use with IPComp. | | 672 | * XXX SPI bits are left-filled, for use with IPComp. |
673 | * we should be switching to variable-length spi field... | | 673 | * we should be switching to variable-length spi field... |
674 | */ | | 674 | */ |
675 | spi = (u_int8_t *)&pr->spi; | | 675 | spi = (u_int8_t *)&pr->spi; |
676 | spi += sizeof(pr->spi); | | 676 | spi += sizeof(pr->spi); |
677 | spi -= pr->spisize; | | 677 | spi -= pr->spisize; |
678 | memcpy(d + 1, spi, pr->spisize); | | 678 | memcpy(d + 1, spi, pr->spisize); |
679 | | | 679 | |
680 | error = isakmp_info_send_common(iph1, payload, | | 680 | error = isakmp_info_send_common(iph1, payload, |
681 | ISAKMP_NPTYPE_D, 0); | | 681 | ISAKMP_NPTYPE_D, 0); |
682 | vfree(payload); | | 682 | vfree(payload); |
683 | } | | 683 | } |
684 | | | 684 | |
685 | return error; | | 685 | return error; |
686 | } | | 686 | } |
687 | | | 687 | |
688 | /* | | 688 | /* |
689 | * send Notification payload (for without ISAKMP SA) in Informational exchange | | 689 | * send Notification payload (for without ISAKMP SA) in Informational exchange |
690 | */ | | 690 | */ |
691 | int | | 691 | int |
692 | isakmp_info_send_nx(isakmp, remote, local, type, data) | | 692 | isakmp_info_send_nx(isakmp, remote, local, type, data) |
693 | struct isakmp *isakmp; | | 693 | struct isakmp *isakmp; |
694 | struct sockaddr *remote, *local; | | 694 | struct sockaddr *remote, *local; |
695 | int type; | | 695 | int type; |
696 | vchar_t *data; | | 696 | vchar_t *data; |
697 | { | | 697 | { |
698 | struct ph1handle *iph1 = NULL; | | 698 | struct ph1handle *iph1 = NULL; |
699 | vchar_t *payload = NULL; | | 699 | vchar_t *payload = NULL; |
700 | int tlen; | | 700 | int tlen; |
701 | int error = -1; | | 701 | int error = -1; |
702 | struct isakmp_pl_n *n; | | 702 | struct isakmp_pl_n *n; |
703 | int spisiz = 0; /* see below */ | | 703 | int spisiz = 0; /* see below */ |
704 | | | 704 | |
705 | /* add new entry to isakmp status table. */ | | 705 | /* add new entry to isakmp status table. */ |
706 | iph1 = newph1(); | | 706 | iph1 = newph1(); |
707 | if (iph1 == NULL) | | 707 | if (iph1 == NULL) |
708 | return -1; | | 708 | return -1; |
709 | | | 709 | |
710 | memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(cookie_t)); | | 710 | memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(cookie_t)); |
711 | isakmp_newcookie((char *)&iph1->index.r_ck, remote, local); | | 711 | isakmp_newcookie((char *)&iph1->index.r_ck, remote, local); |
712 | iph1->status = PHASE1ST_START; | | 712 | iph1->status = PHASE1ST_START; |
713 | iph1->side = INITIATOR; | | 713 | iph1->side = INITIATOR; |
714 | iph1->version = isakmp->v; | | 714 | iph1->version = isakmp->v; |
715 | iph1->flags = 0; | | 715 | iph1->flags = 0; |
716 | iph1->msgid = 0; /* XXX */ | | 716 | iph1->msgid = 0; /* XXX */ |
717 | #ifdef ENABLE_HYBRID | | 717 | #ifdef ENABLE_HYBRID |
718 | if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) | | 718 | if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) |
719 | goto end; | | 719 | goto end; |
720 | #endif | | 720 | #endif |
721 | #ifdef ENABLE_FRAG | | 721 | #ifdef ENABLE_FRAG |
722 | iph1->frag = 0; | | 722 | iph1->frag = 0; |
723 | iph1->frag_chain = NULL; | | 723 | iph1->frag_chain = NULL; |
724 | #endif | | 724 | #endif |
725 | | | 725 | |
726 | /* copy remote address */ | | 726 | /* copy remote address */ |
727 | if (copy_ph1addresses(iph1, NULL, remote, local) < 0) | | 727 | if (copy_ph1addresses(iph1, NULL, remote, local) < 0) |
728 | goto end; | | 728 | goto end; |
729 | | | 729 | |
730 | tlen = sizeof(*n) + spisiz; | | 730 | tlen = sizeof(*n) + spisiz; |
731 | if (data) | | 731 | if (data) |
732 | tlen += data->l; | | 732 | tlen += data->l; |
733 | payload = vmalloc(tlen); | | 733 | payload = vmalloc(tlen); |
734 | if (payload == NULL) { | | 734 | if (payload == NULL) { |
735 | plog(LLV_ERROR, LOCATION, NULL, | | 735 | plog(LLV_ERROR, LOCATION, NULL, |
736 | "failed to get buffer to send.\n"); | | 736 | "failed to get buffer to send.\n"); |
737 | goto end; | | 737 | goto end; |
738 | } | | 738 | } |
739 | | | 739 | |
740 | n = (struct isakmp_pl_n *)payload->v; | | 740 | n = (struct isakmp_pl_n *)payload->v; |
741 | n->h.np = ISAKMP_NPTYPE_NONE; | | 741 | n->h.np = ISAKMP_NPTYPE_NONE; |
742 | n->h.len = htons(tlen); | | 742 | n->h.len = htons(tlen); |
743 | n->doi = htonl(IPSEC_DOI); | | 743 | n->doi = htonl(IPSEC_DOI); |
744 | n->proto_id = IPSECDOI_KEY_IKE; | | 744 | n->proto_id = IPSECDOI_KEY_IKE; |
745 | n->spi_size = spisiz; | | 745 | n->spi_size = spisiz; |
746 | n->type = htons(type); | | 746 | n->type = htons(type); |
747 | if (spisiz) | | 747 | if (spisiz) |
748 | memset(n + 1, 0, spisiz); /* XXX spisiz is always 0 */ | | 748 | memset(n + 1, 0, spisiz); /* XXX spisiz is always 0 */ |
749 | if (data) | | 749 | if (data) |
750 | memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l); | | 750 | memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l); |
751 | | | 751 | |
752 | error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0); | | 752 | error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0); |
753 | vfree(payload); | | 753 | vfree(payload); |
754 | | | 754 | |
755 | end: | | 755 | end: |
756 | if (iph1 != NULL) | | 756 | if (iph1 != NULL) |
757 | delph1(iph1); | | 757 | delph1(iph1); |
758 | | | 758 | |
759 | return error; | | 759 | return error; |
760 | } | | 760 | } |
761 | | | 761 | |
762 | /* | | 762 | /* |
763 | * send Notification payload (for ISAKMP SA) in Informational exchange | | 763 | * send Notification payload (for ISAKMP SA) in Informational exchange |
764 | */ | | 764 | */ |
765 | int | | 765 | int |
766 | isakmp_info_send_n1(iph1, type, data) | | 766 | isakmp_info_send_n1(iph1, type, data) |
767 | struct ph1handle *iph1; | | 767 | struct ph1handle *iph1; |
768 | int type; | | 768 | int type; |
769 | vchar_t *data; | | 769 | vchar_t *data; |
770 | { | | 770 | { |
771 | vchar_t *payload = NULL; | | 771 | vchar_t *payload = NULL; |
772 | int tlen; | | 772 | int tlen; |
773 | int error = 0; | | 773 | int error = 0; |
774 | struct isakmp_pl_n *n; | | 774 | struct isakmp_pl_n *n; |
775 | int spisiz; | | 775 | int spisiz; |
776 | | | 776 | |
777 | /* | | 777 | /* |
778 | * note on SPI size: which description is correct? I have chosen | | 778 | * note on SPI size: which description is correct? I have chosen |
779 | * this to be 0. | | 779 | * this to be 0. |
780 | * | | 780 | * |
781 | * RFC2408 3.1, 2nd paragraph says: ISAKMP SA is identified by | | 781 | * RFC2408 3.1, 2nd paragraph says: ISAKMP SA is identified by |
782 | * Initiator/Responder cookie and SPI has no meaning, SPI size = 0. | | 782 | * Initiator/Responder cookie and SPI has no meaning, SPI size = 0. |
783 | * RFC2408 3.1, first paragraph on page 40: ISAKMP SA is identified | | 783 | * RFC2408 3.1, first paragraph on page 40: ISAKMP SA is identified |
784 | * by cookie and SPI has no meaning, 0 <= SPI size <= 16. | | 784 | * by cookie and SPI has no meaning, 0 <= SPI size <= 16. |
785 | * RFC2407 4.6.3.3, INITIAL-CONTACT is required to set to 16. | | 785 | * RFC2407 4.6.3.3, INITIAL-CONTACT is required to set to 16. |
786 | */ | | 786 | */ |
787 | if (type == ISAKMP_NTYPE_INITIAL_CONTACT) | | 787 | if (type == ISAKMP_NTYPE_INITIAL_CONTACT) |
788 | spisiz = sizeof(isakmp_index); | | 788 | spisiz = sizeof(isakmp_index); |
789 | else | | 789 | else |
790 | spisiz = 0; | | 790 | spisiz = 0; |
791 | | | 791 | |
792 | tlen = sizeof(*n) + spisiz; | | 792 | tlen = sizeof(*n) + spisiz; |
793 | if (data) | | 793 | if (data) |
794 | tlen += data->l; | | 794 | tlen += data->l; |
795 | payload = vmalloc(tlen); | | 795 | payload = vmalloc(tlen); |
796 | if (payload == NULL) { | | 796 | if (payload == NULL) { |
797 | plog(LLV_ERROR, LOCATION, NULL, | | 797 | plog(LLV_ERROR, LOCATION, NULL, |
798 | "failed to get buffer to send.\n"); | | 798 | "failed to get buffer to send.\n"); |
799 | return errno; | | 799 | return errno; |
800 | } | | 800 | } |
801 | | | 801 | |
802 | n = (struct isakmp_pl_n *)payload->v; | | 802 | n = (struct isakmp_pl_n *)payload->v; |
803 | n->h.np = ISAKMP_NPTYPE_NONE; | | 803 | n->h.np = ISAKMP_NPTYPE_NONE; |
804 | n->h.len = htons(tlen); | | 804 | n->h.len = htons(tlen); |
805 | n->doi = htonl(iph1->rmconf->doitype); | | 805 | n->doi = htonl(iph1->rmconf->doitype); |
806 | n->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX to be configurable ? */ | | 806 | n->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX to be configurable ? */ |
807 | n->spi_size = spisiz; | | 807 | n->spi_size = spisiz; |
808 | n->type = htons(type); | | 808 | n->type = htons(type); |
809 | if (spisiz) | | 809 | if (spisiz) |
810 | memcpy(n + 1, &iph1->index, sizeof(isakmp_index)); | | 810 | memcpy(n + 1, &iph1->index, sizeof(isakmp_index)); |
811 | if (data) | | 811 | if (data) |
812 | memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l); | | 812 | memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l); |
813 | | | 813 | |
814 | error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph1->flags); | | 814 | error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph1->flags); |
815 | vfree(payload); | | 815 | vfree(payload); |
816 | | | 816 | |
817 | return error; | | 817 | return error; |
818 | } | | 818 | } |
819 | | | 819 | |
820 | /* | | 820 | /* |
821 | * send Notification payload (for IPsec SA) in Informational exchange | | 821 | * send Notification payload (for IPsec SA) in Informational exchange |
822 | */ | | 822 | */ |
823 | int | | 823 | int |
824 | isakmp_info_send_n2(iph2, type, data) | | 824 | isakmp_info_send_n2(iph2, type, data) |
825 | struct ph2handle *iph2; | | 825 | struct ph2handle *iph2; |
826 | int type; | | 826 | int type; |
827 | vchar_t *data; | | 827 | vchar_t *data; |
828 | { | | 828 | { |
829 | struct ph1handle *iph1 = iph2->ph1; | | 829 | struct ph1handle *iph1 = iph2->ph1; |
830 | vchar_t *payload = NULL; | | 830 | vchar_t *payload = NULL; |
831 | int tlen; | | 831 | int tlen; |
832 | int error = 0; | | 832 | int error = 0; |
833 | struct isakmp_pl_n *n; | | 833 | struct isakmp_pl_n *n; |
834 | struct saproto *pr; | | 834 | struct saproto *pr; |
835 | | | 835 | |
836 | if (!iph2->approval) | | 836 | if (!iph2->approval) |
837 | return EINVAL; | | 837 | return EINVAL; |
838 | | | 838 | |
839 | pr = iph2->approval->head; | | 839 | pr = iph2->approval->head; |
840 | | | 840 | |
841 | /* XXX must be get proper spi */ | | 841 | /* XXX must be get proper spi */ |
842 | tlen = sizeof(*n) + pr->spisize; | | 842 | tlen = sizeof(*n) + pr->spisize; |
843 | if (data) | | 843 | if (data) |
844 | tlen += data->l; | | 844 | tlen += data->l; |
845 | payload = vmalloc(tlen); | | 845 | payload = vmalloc(tlen); |
846 | if (payload == NULL) { | | 846 | if (payload == NULL) { |
847 | plog(LLV_ERROR, LOCATION, NULL, | | 847 | plog(LLV_ERROR, LOCATION, NULL, |
848 | "failed to get buffer to send.\n"); | | 848 | "failed to get buffer to send.\n"); |
849 | return errno; | | 849 | return errno; |
850 | } | | 850 | } |
851 | | | 851 | |
852 | n = (struct isakmp_pl_n *)payload->v; | | 852 | n = (struct isakmp_pl_n *)payload->v; |
853 | n->h.np = ISAKMP_NPTYPE_NONE; | | 853 | n->h.np = ISAKMP_NPTYPE_NONE; |
854 | n->h.len = htons(tlen); | | 854 | n->h.len = htons(tlen); |
855 | n->doi = htonl(IPSEC_DOI); /* IPSEC DOI (1) */ | | 855 | n->doi = htonl(IPSEC_DOI); /* IPSEC DOI (1) */ |
856 | n->proto_id = pr->proto_id; /* IPSEC AH/ESP/whatever*/ | | 856 | n->proto_id = pr->proto_id; /* IPSEC AH/ESP/whatever*/ |
857 | n->spi_size = pr->spisize; | | 857 | n->spi_size = pr->spisize; |
858 | n->type = htons(type); | | 858 | n->type = htons(type); |
859 | *(u_int32_t *)(n + 1) = pr->spi; | | 859 | *(u_int32_t *)(n + 1) = pr->spi; |
860 | if (data) | | 860 | if (data) |
861 | memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l); | | 861 | memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l); |
862 | | | 862 | |
863 | iph2->flags |= ISAKMP_FLAG_E; /* XXX Should we do FLAG_A ? */ | | 863 | iph2->flags |= ISAKMP_FLAG_E; /* XXX Should we do FLAG_A ? */ |
864 | error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph2->flags); | | 864 | error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph2->flags); |
865 | vfree(payload); | | 865 | vfree(payload); |
866 | | | 866 | |
867 | return error; | | 867 | return error; |
868 | } | | 868 | } |
869 | | | 869 | |
870 | /* | | 870 | /* |
871 | * send Information | | 871 | * send Information |
872 | * When ph1->skeyid_a == NULL, send message without encoding. | | 872 | * When ph1->skeyid_a == NULL, send message without encoding. |
873 | */ | | 873 | */ |
874 | int | | 874 | int |
875 | isakmp_info_send_common(iph1, payload, np, flags) | | 875 | isakmp_info_send_common(iph1, payload, np, flags) |
876 | struct ph1handle *iph1; | | 876 | struct ph1handle *iph1; |
877 | vchar_t *payload; | | 877 | vchar_t *payload; |
878 | u_int32_t np; | | 878 | u_int32_t np; |
879 | int flags; | | 879 | int flags; |
880 | { | | 880 | { |
881 | struct ph2handle *iph2 = NULL; | | 881 | struct ph2handle *iph2 = NULL; |
882 | vchar_t *hash = NULL; | | 882 | vchar_t *hash = NULL; |
883 | struct isakmp *isakmp; | | 883 | struct isakmp *isakmp; |
884 | struct isakmp_gen *gen; | | 884 | struct isakmp_gen *gen; |
885 | char *p; | | 885 | char *p; |
886 | int tlen; | | 886 | int tlen; |
887 | int error = -1; | | 887 | int error = -1; |
888 | | | 888 | |
889 | /* add new entry to isakmp status table */ | | 889 | /* add new entry to isakmp status table */ |
890 | iph2 = newph2(); | | 890 | iph2 = newph2(); |
891 | if (iph2 == NULL) | | 891 | if (iph2 == NULL) |
892 | goto end; | | 892 | goto end; |
893 | | | 893 | |
894 | iph2->dst = dupsaddr(iph1->remote); | | 894 | iph2->dst = dupsaddr(iph1->remote); |
895 | if (iph2->dst == NULL) { | | 895 | if (iph2->dst == NULL) { |
896 | delph2(iph2); | | 896 | delph2(iph2); |
897 | goto end; | | 897 | goto end; |
898 | } | | 898 | } |
899 | iph2->src = dupsaddr(iph1->local); | | 899 | iph2->src = dupsaddr(iph1->local); |
900 | if (iph2->src == NULL) { | | 900 | if (iph2->src == NULL) { |
901 | delph2(iph2); | | 901 | delph2(iph2); |
902 | goto end; | | 902 | goto end; |
903 | } | | 903 | } |
904 | iph2->side = INITIATOR; | | 904 | iph2->side = INITIATOR; |
905 | iph2->status = PHASE2ST_START; | | 905 | iph2->status = PHASE2ST_START; |
906 | iph2->msgid = isakmp_newmsgid2(iph1); | | 906 | iph2->msgid = isakmp_newmsgid2(iph1); |
907 | | | 907 | |
908 | /* get IV and HASH(1) if skeyid_a was generated. */ | | 908 | /* get IV and HASH(1) if skeyid_a was generated. */ |
909 | if (iph1->skeyid_a != NULL) { | | 909 | if (iph1->skeyid_a != NULL) { |
910 | iph2->ivm = oakley_newiv2(iph1, iph2->msgid); | | 910 | iph2->ivm = oakley_newiv2(iph1, iph2->msgid); |
911 | if (iph2->ivm == NULL) { | | 911 | if (iph2->ivm == NULL) { |
912 | delph2(iph2); | | 912 | delph2(iph2); |
913 | goto end; | | 913 | goto end; |
914 | } | | 914 | } |
915 | | | 915 | |
916 | /* generate HASH(1) */ | | 916 | /* generate HASH(1) */ |
917 | hash = oakley_compute_hash1(iph1, iph2->msgid, payload); | | 917 | hash = oakley_compute_hash1(iph1, iph2->msgid, payload); |
918 | if (hash == NULL) { | | 918 | if (hash == NULL) { |
919 | delph2(iph2); | | 919 | delph2(iph2); |
920 | goto end; | | 920 | goto end; |
921 | } | | 921 | } |
922 | | | 922 | |
923 | /* initialized total buffer length */ | | 923 | /* initialized total buffer length */ |
924 | tlen = hash->l; | | 924 | tlen = hash->l; |
925 | tlen += sizeof(*gen); | | 925 | tlen += sizeof(*gen); |
926 | } else { | | 926 | } else { |
927 | /* IKE-SA is not established */ | | 927 | /* IKE-SA is not established */ |
928 | hash = NULL; | | 928 | hash = NULL; |
929 | | | 929 | |
930 | /* initialized total buffer length */ | | 930 | /* initialized total buffer length */ |
931 | tlen = 0; | | 931 | tlen = 0; |
932 | } | | 932 | } |
933 | if ((flags & ISAKMP_FLAG_A) == 0) | | 933 | if ((flags & ISAKMP_FLAG_A) == 0) |
934 | iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E); | | 934 | iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E); |
935 | else | | 935 | else |
936 | iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A); | | 936 | iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A); |
937 | | | 937 | |
938 | insph2(iph2); | | 938 | insph2(iph2); |
939 | bindph12(iph1, iph2); | | 939 | bindph12(iph1, iph2); |
940 | | | 940 | |
941 | tlen += sizeof(*isakmp) + payload->l; | | 941 | tlen += sizeof(*isakmp) + payload->l; |
942 | | | 942 | |
943 | /* create buffer for isakmp payload */ | | 943 | /* create buffer for isakmp payload */ |
944 | iph2->sendbuf = vmalloc(tlen); | | 944 | iph2->sendbuf = vmalloc(tlen); |
945 | if (iph2->sendbuf == NULL) { | | 945 | if (iph2->sendbuf == NULL) { |
946 | plog(LLV_ERROR, LOCATION, NULL, | | 946 | plog(LLV_ERROR, LOCATION, NULL, |
947 | "failed to get buffer to send.\n"); | | 947 | "failed to get buffer to send.\n"); |
948 | goto err; | | 948 | goto err; |
949 | } | | 949 | } |
950 | | | 950 | |
951 | /* create isakmp header */ | | 951 | /* create isakmp header */ |
952 | isakmp = (struct isakmp *)iph2->sendbuf->v; | | 952 | isakmp = (struct isakmp *)iph2->sendbuf->v; |
953 | memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t)); | | 953 | memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t)); |
954 | memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t)); | | 954 | memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t)); |
955 | isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH; | | 955 | isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH; |
956 | isakmp->v = iph1->version; | | 956 | isakmp->v = iph1->version; |
957 | isakmp->etype = ISAKMP_ETYPE_INFO; | | 957 | isakmp->etype = ISAKMP_ETYPE_INFO; |
958 | isakmp->flags = iph2->flags; | | 958 | isakmp->flags = iph2->flags; |
959 | memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid)); | | 959 | memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid)); |
960 | isakmp->len = htonl(tlen); | | 960 | isakmp->len = htonl(tlen); |
961 | p = (char *)(isakmp + 1); | | 961 | p = (char *)(isakmp + 1); |
962 | | | 962 | |
963 | /* create HASH payload */ | | 963 | /* create HASH payload */ |
964 | if (hash != NULL) { | | 964 | if (hash != NULL) { |
965 | gen = (struct isakmp_gen *)p; | | 965 | gen = (struct isakmp_gen *)p; |
966 | gen->np = np & 0xff; | | 966 | gen->np = np & 0xff; |
967 | gen->len = htons(sizeof(*gen) + hash->l); | | 967 | gen->len = htons(sizeof(*gen) + hash->l); |
968 | p += sizeof(*gen); | | 968 | p += sizeof(*gen); |
969 | memcpy(p, hash->v, hash->l); | | 969 | memcpy(p, hash->v, hash->l); |
970 | p += hash->l; | | 970 | p += hash->l; |
971 | } | | 971 | } |
972 | | | 972 | |
973 | /* add payload */ | | 973 | /* add payload */ |
974 | memcpy(p, payload->v, payload->l); | | 974 | memcpy(p, payload->v, payload->l); |
975 | p += payload->l; | | 975 | p += payload->l; |
976 | | | 976 | |
977 | #ifdef HAVE_PRINT_ISAKMP_C | | 977 | #ifdef HAVE_PRINT_ISAKMP_C |
978 | isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1); | | 978 | isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1); |
979 | #endif | | 979 | #endif |
980 | | | 980 | |
981 | /* encoding */ | | 981 | /* encoding */ |
982 | if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) { | | 982 | if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) { |
983 | vchar_t *tmp; | | 983 | vchar_t *tmp; |
984 | | | 984 | |
985 | tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf, iph2->ivm->ive, | | 985 | tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf, iph2->ivm->ive, |
986 | iph2->ivm->iv); | | 986 | iph2->ivm->iv); |
987 | VPTRINIT(iph2->sendbuf); | | 987 | VPTRINIT(iph2->sendbuf); |
988 | if (tmp == NULL) | | 988 | if (tmp == NULL) |
989 | goto err; | | 989 | goto err; |
990 | iph2->sendbuf = tmp; | | 990 | iph2->sendbuf = tmp; |
991 | } | | 991 | } |
992 | | | 992 | |
993 | /* HDR*, HASH(1), N */ | | 993 | /* HDR*, HASH(1), N */ |
994 | if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) { | | 994 | if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) { |
995 | VPTRINIT(iph2->sendbuf); | | 995 | VPTRINIT(iph2->sendbuf); |
996 | goto err; | | 996 | goto err; |
997 | } | | 997 | } |
998 | | | 998 | |
999 | plog(LLV_DEBUG, LOCATION, NULL, | | 999 | plog(LLV_DEBUG, LOCATION, NULL, |
1000 | "sendto Information %s.\n", s_isakmp_nptype(np)); | | 1000 | "sendto Information %s.\n", s_isakmp_nptype(np)); |
1001 | | | 1001 | |
1002 | /* | | 1002 | /* |
1003 | * don't resend notify message because peer can use Acknowledged | | 1003 | * don't resend notify message because peer can use Acknowledged |
1004 | * Informational if peer requires the reply of the notify message. | | 1004 | * Informational if peer requires the reply of the notify message. |
1005 | */ | | 1005 | */ |
1006 | | | 1006 | |
1007 | /* XXX If Acknowledged Informational required, don't delete ph2handle */ | | 1007 | /* XXX If Acknowledged Informational required, don't delete ph2handle */ |
1008 | error = 0; | | 1008 | error = 0; |
1009 | VPTRINIT(iph2->sendbuf); | | 1009 | VPTRINIT(iph2->sendbuf); |
1010 | goto err; /* XXX */ | | 1010 | goto err; /* XXX */ |
1011 | | | 1011 | |
1012 | end: | | 1012 | end: |
1013 | if (hash) | | 1013 | if (hash) |
1014 | vfree(hash); | | 1014 | vfree(hash); |
1015 | return error; | | 1015 | return error; |
1016 | | | 1016 | |
1017 | err: | | 1017 | err: |
1018 | remph2(iph2); | | 1018 | remph2(iph2); |
1019 | delph2(iph2); | | 1019 | delph2(iph2); |
1020 | goto end; | | 1020 | goto end; |
1021 | } | | 1021 | } |
1022 | | | 1022 | |
1023 | /* | | 1023 | /* |
1024 | * add a notify payload to buffer by reallocating buffer. | | 1024 | * add a notify payload to buffer by reallocating buffer. |
1025 | * If buf == NULL, the function only create a notify payload. | | 1025 | * If buf == NULL, the function only create a notify payload. |
1026 | * | | 1026 | * |
1027 | * XXX Which is SPI to be included, inbound or outbound ? | | 1027 | * XXX Which is SPI to be included, inbound or outbound ? |
1028 | */ | | 1028 | */ |
1029 | vchar_t * | | 1029 | vchar_t * |
1030 | isakmp_add_pl_n(buf0, np_p, type, pr, data) | | 1030 | isakmp_add_pl_n(buf0, np_p, type, pr, data) |
1031 | vchar_t *buf0; | | 1031 | vchar_t *buf0; |
1032 | u_int8_t **np_p; | | 1032 | u_int8_t **np_p; |
1033 | int type; | | 1033 | int type; |
1034 | struct saproto *pr; | | 1034 | struct saproto *pr; |
1035 | vchar_t *data; | | 1035 | vchar_t *data; |
1036 | { | | 1036 | { |
1037 | vchar_t *buf = NULL; | | 1037 | vchar_t *buf = NULL; |
1038 | struct isakmp_pl_n *n; | | 1038 | struct isakmp_pl_n *n; |
1039 | int tlen; | | 1039 | int tlen; |
1040 | int oldlen = 0; | | 1040 | int oldlen = 0; |
1041 | | | 1041 | |
1042 | if (*np_p) | | 1042 | if (*np_p) |
1043 | **np_p = ISAKMP_NPTYPE_N; | | 1043 | **np_p = ISAKMP_NPTYPE_N; |
1044 | | | 1044 | |
1045 | tlen = sizeof(*n) + pr->spisize; | | 1045 | tlen = sizeof(*n) + pr->spisize; |
1046 | | | 1046 | |
1047 | if (data) | | 1047 | if (data) |
1048 | tlen += data->l; | | 1048 | tlen += data->l; |
1049 | if (buf0) { | | 1049 | if (buf0) { |
1050 | oldlen = buf0->l; | | 1050 | oldlen = buf0->l; |
1051 | buf = vrealloc(buf0, buf0->l + tlen); | | 1051 | buf = vrealloc(buf0, buf0->l + tlen); |
1052 | } else | | 1052 | } else |
1053 | buf = vmalloc(tlen); | | 1053 | buf = vmalloc(tlen); |
1054 | if (!buf) { | | 1054 | if (!buf) { |
1055 | plog(LLV_ERROR, LOCATION, NULL, | | 1055 | plog(LLV_ERROR, LOCATION, NULL, |
1056 | "failed to get a payload buffer.\n"); | | 1056 | "failed to get a payload buffer.\n"); |
1057 | return NULL; | | 1057 | return NULL; |
1058 | } | | 1058 | } |
1059 | | | 1059 | |
1060 | n = (struct isakmp_pl_n *)(buf->v + oldlen); | | 1060 | n = (struct isakmp_pl_n *)(buf->v + oldlen); |
1061 | n->h.np = ISAKMP_NPTYPE_NONE; | | 1061 | n->h.np = ISAKMP_NPTYPE_NONE; |
1062 | n->h.len = htons(tlen); | | 1062 | n->h.len = htons(tlen); |
1063 | n->doi = htonl(IPSEC_DOI); /* IPSEC DOI (1) */ | | 1063 | n->doi = htonl(IPSEC_DOI); /* IPSEC DOI (1) */ |
1064 | n->proto_id = pr->proto_id; /* IPSEC AH/ESP/whatever*/ | | 1064 | n->proto_id = pr->proto_id; /* IPSEC AH/ESP/whatever*/ |
1065 | n->spi_size = pr->spisize; | | 1065 | n->spi_size = pr->spisize; |
1066 | n->type = htons(type); | | 1066 | n->type = htons(type); |
1067 | *(u_int32_t *)(n + 1) = pr->spi; /* XXX */ | | 1067 | *(u_int32_t *)(n + 1) = pr->spi; /* XXX */ |
1068 | if (data) | | 1068 | if (data) |
1069 | memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l); | | 1069 | memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l); |
1070 | | | 1070 | |
1071 | /* save the pointer of next payload type */ | | 1071 | /* save the pointer of next payload type */ |
1072 | *np_p = &n->h.np; | | 1072 | *np_p = &n->h.np; |
1073 | | | 1073 | |
1074 | return buf; | | 1074 | return buf; |
1075 | } | | 1075 | } |
1076 | | | 1076 | |
1077 | static void | | 1077 | static void |
1078 | purge_isakmp_spi(proto, spi, n) | | 1078 | purge_isakmp_spi(proto, spi, n) |
1079 | int proto; | | 1079 | int proto; |
1080 | isakmp_index *spi; /*network byteorder*/ | | 1080 | isakmp_index *spi; /*network byteorder*/ |
1081 | size_t n; | | 1081 | size_t n; |
1082 | { | | 1082 | { |
1083 | struct ph1handle *iph1; | | 1083 | struct ph1handle *iph1; |
1084 | size_t i; | | 1084 | size_t i; |
1085 | | | 1085 | |
1086 | for (i = 0; i < n; i++) { | | 1086 | for (i = 0; i < n; i++) { |
1087 | iph1 = getph1byindex(&spi[i]); | | 1087 | iph1 = getph1byindex(&spi[i]); |
1088 | if (!iph1) | | 1088 | if (!iph1) |
1089 | continue; | | 1089 | continue; |
1090 | | | 1090 | |
1091 | plog(LLV_INFO, LOCATION, NULL, | | 1091 | plog(LLV_INFO, LOCATION, NULL, |
1092 | "purged ISAKMP-SA proto_id=%s spi=%s.\n", | | 1092 | "purged ISAKMP-SA proto_id=%s spi=%s.\n", |
1093 | s_ipsecdoi_proto(proto), | | 1093 | s_ipsecdoi_proto(proto), |
1094 | isakmp_pindex(&spi[i], 0)); | | 1094 | isakmp_pindex(&spi[i], 0)); |
1095 | | | 1095 | |
1096 | iph1->status = PHASE1ST_EXPIRED; | | 1096 | iph1->status = PHASE1ST_EXPIRED; |
1097 | isakmp_ph1delete(iph1); | | 1097 | isakmp_ph1delete(iph1); |
1098 | } | | 1098 | } |
1099 | } | | 1099 | } |
1100 | | | 1100 | |
1101 | | | 1101 | |
1102 | | | 1102 | |
1103 | void | | 1103 | void |
1104 | purge_ipsec_spi(dst0, proto, spi, n) | | 1104 | purge_ipsec_spi(dst0, proto, spi, n) |
1105 | struct sockaddr *dst0; | | 1105 | struct sockaddr *dst0; |
1106 | int proto; | | 1106 | int proto; |
1107 | u_int32_t *spi; /*network byteorder*/ | | 1107 | u_int32_t *spi; /*network byteorder*/ |
1108 | size_t n; | | 1108 | size_t n; |
1109 | { | | 1109 | { |
1110 | vchar_t *buf = NULL; | | 1110 | vchar_t *buf = NULL; |
1111 | struct sadb_msg *msg, *next, *end; | | 1111 | struct sadb_msg *msg, *next, *end; |
1112 | struct sadb_sa *sa; | | 1112 | struct sadb_sa *sa; |
1113 | struct sadb_lifetime *lt; | | 1113 | struct sadb_lifetime *lt; |
1114 | struct sockaddr *src, *dst; | | 1114 | struct sockaddr *src, *dst; |
1115 | struct ph2handle *iph2; | | 1115 | struct ph2handle *iph2; |
1116 | u_int64_t created; | | 1116 | u_int64_t created; |
1117 | size_t i; | | 1117 | size_t i; |
1118 | caddr_t mhp[SADB_EXT_MAX + 1]; | | 1118 | caddr_t mhp[SADB_EXT_MAX + 1]; |
1119 | | | 1119 | |
1120 | plog(LLV_DEBUG2, LOCATION, NULL, | | 1120 | plog(LLV_DEBUG2, LOCATION, NULL, |
1121 | "purge_ipsec_spi:\n"); | | 1121 | "purge_ipsec_spi:\n"); |
1122 | plog(LLV_DEBUG2, LOCATION, NULL, "dst0: %s\n", saddr2str(dst0)); | | 1122 | plog(LLV_DEBUG2, LOCATION, NULL, "dst0: %s\n", saddr2str(dst0)); |
1123 | plog(LLV_DEBUG2, LOCATION, NULL, "SPI: %08X\n", ntohl(spi[0])); | | 1123 | plog(LLV_DEBUG2, LOCATION, NULL, "SPI: %08X\n", ntohl(spi[0])); |
1124 | | | 1124 | |
1125 | buf = pfkey_dump_sadb(ipsecdoi2pfkey_proto(proto)); | | 1125 | buf = pfkey_dump_sadb(ipsecdoi2pfkey_proto(proto)); |
1126 | if (buf == NULL) { | | 1126 | if (buf == NULL) { |
1127 | plog(LLV_DEBUG, LOCATION, NULL, | | 1127 | plog(LLV_DEBUG, LOCATION, NULL, |
1128 | "pfkey_dump_sadb returned nothing.\n"); | | 1128 | "pfkey_dump_sadb returned nothing.\n"); |
1129 | return; | | 1129 | return; |
1130 | } | | 1130 | } |
1131 | | | 1131 | |
1132 | msg = (struct sadb_msg *)buf->v; | | 1132 | msg = (struct sadb_msg *)buf->v; |
1133 | end = (struct sadb_msg *)(buf->v + buf->l); | | 1133 | end = (struct sadb_msg *)(buf->v + buf->l); |
1134 | | | 1134 | |
1135 | while (msg < end) { | | 1135 | while (msg < end) { |
1136 | if ((msg->sadb_msg_len << 3) < sizeof(*msg)) | | 1136 | if ((msg->sadb_msg_len << 3) < sizeof(*msg)) |
1137 | break; | | 1137 | break; |
1138 | next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3)); | | 1138 | next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3)); |
1139 | if (msg->sadb_msg_type != SADB_DUMP) { | | 1139 | if (msg->sadb_msg_type != SADB_DUMP) { |
1140 | msg = next; | | 1140 | msg = next; |
1141 | continue; | | 1141 | continue; |
1142 | } | | 1142 | } |
1143 | | | 1143 | |
1144 | if (pfkey_align(msg, mhp) || pfkey_check(mhp)) { | | 1144 | if (pfkey_align(msg, mhp) || pfkey_check(mhp)) { |
1145 | plog(LLV_ERROR, LOCATION, NULL, | | 1145 | plog(LLV_ERROR, LOCATION, NULL, |
1146 | "pfkey_check (%s)\n", ipsec_strerror()); | | 1146 | "pfkey_check (%s)\n", ipsec_strerror()); |
1147 | msg = next; | | 1147 | msg = next; |
1148 | continue; | | 1148 | continue; |
1149 | } | | 1149 | } |
1150 | | | 1150 | |
1151 | sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]); | | 1151 | sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]); |
1152 | if (!sa | | 1152 | if (!sa |
1153 | || !mhp[SADB_EXT_ADDRESS_SRC] | | 1153 | || !mhp[SADB_EXT_ADDRESS_SRC] |
1154 | || !mhp[SADB_EXT_ADDRESS_DST]) { | | 1154 | || !mhp[SADB_EXT_ADDRESS_DST]) { |
1155 | msg = next; | | 1155 | msg = next; |
1156 | continue; | | 1156 | continue; |
1157 | } | | 1157 | } |
1158 | pk_fixup_sa_addresses(mhp); | | 1158 | pk_fixup_sa_addresses(mhp); |
1159 | src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); | | 1159 | src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); |
1160 | dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); | | 1160 | dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); |
1161 | lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD]; | | 1161 | lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD]; |
1162 | if(lt != NULL) | | 1162 | if(lt != NULL) |
1163 | created = lt->sadb_lifetime_addtime; | | 1163 | created = lt->sadb_lifetime_addtime; |
1164 | else | | 1164 | else |
1165 | created = 0; | | 1165 | created = 0; |
1166 | | | 1166 | |
1167 | if (sa->sadb_sa_state != SADB_SASTATE_MATURE | | 1167 | if (sa->sadb_sa_state != SADB_SASTATE_MATURE |
1168 | && sa->sadb_sa_state != SADB_SASTATE_DYING) { | | 1168 | && sa->sadb_sa_state != SADB_SASTATE_DYING) { |
1169 | msg = next; | | 1169 | msg = next; |
1170 | continue; | | 1170 | continue; |
1171 | } | | 1171 | } |
1172 | | | 1172 | |
1173 | plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(src)); | | 1173 | plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(src)); |
1174 | plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(dst)); | | 1174 | plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(dst)); |
1175 | | | 1175 | |
1176 | /* XXX n^2 algorithm, inefficient */ | | 1176 | /* XXX n^2 algorithm, inefficient */ |
1177 | | | 1177 | |
1178 | /* don't delete inbound SAs at the moment */ | | 1178 | /* don't delete inbound SAs at the moment */ |
1179 | /* XXX should we remove SAs with opposite direction as well? */ | | 1179 | /* XXX should we remove SAs with opposite direction as well? */ |
1180 | if (cmpsaddr(dst0, dst) != CMPSADDR_MATCH) { | | 1180 | if (cmpsaddr(dst0, dst) != CMPSADDR_MATCH) { |
1181 | msg = next; | | 1181 | msg = next; |
1182 | continue; | | 1182 | continue; |
1183 | } | | 1183 | } |
1184 | | | 1184 | |
1185 | for (i = 0; i < n; i++) { | | 1185 | for (i = 0; i < n; i++) { |
1186 | plog(LLV_DEBUG, LOCATION, NULL, | | 1186 | plog(LLV_DEBUG, LOCATION, NULL, |
1187 | "check spi(packet)=%u spi(db)=%u.\n", | | 1187 | "check spi(packet)=%u spi(db)=%u.\n", |
1188 | ntohl(spi[i]), ntohl(sa->sadb_sa_spi)); | | 1188 | ntohl(spi[i]), ntohl(sa->sadb_sa_spi)); |
1189 | if (spi[i] != sa->sadb_sa_spi) | | 1189 | if (spi[i] != sa->sadb_sa_spi) |
1190 | continue; | | 1190 | continue; |
1191 | | | 1191 | |
1192 | pfkey_send_delete(lcconf->sock_pfkey, | | 1192 | pfkey_send_delete(lcconf->sock_pfkey, |
1193 | msg->sadb_msg_satype, | | 1193 | msg->sadb_msg_satype, |
1194 | IPSEC_MODE_ANY, | | 1194 | IPSEC_MODE_ANY, |
1195 | src, dst, sa->sadb_sa_spi); | | 1195 | src, dst, sa->sadb_sa_spi); |
1196 | | | 1196 | |
1197 | /* | | 1197 | /* |
1198 | * delete a relative phase 2 handler. | | 1198 | * delete a relative phase 2 handler. |
1199 | * continue to process if no relative phase 2 handler | | 1199 | * continue to process if no relative phase 2 handler |
1200 | * exists. | | 1200 | * exists. |
1201 | */ | | 1201 | */ |
1202 | iph2 = getph2bysaidx(src, dst, proto, spi[i]); | | 1202 | iph2 = getph2bysaidx(src, dst, proto, spi[i]); |
1203 | if(iph2 != NULL){ | | 1203 | if(iph2 != NULL){ |
1204 | delete_spd(iph2, created); | | 1204 | delete_spd(iph2, created); |
1205 | remph2(iph2); | | 1205 | remph2(iph2); |
1206 | delph2(iph2); | | 1206 | delph2(iph2); |
1207 | } | | 1207 | } |
1208 | | | 1208 | |
1209 | plog(LLV_INFO, LOCATION, NULL, | | 1209 | plog(LLV_INFO, LOCATION, NULL, |
1210 | "purged IPsec-SA proto_id=%s spi=%u.\n", | | 1210 | "purged IPsec-SA proto_id=%s spi=%u.\n", |
1211 | s_ipsecdoi_proto(proto), | | 1211 | s_ipsecdoi_proto(proto), |
1212 | ntohl(spi[i])); | | 1212 | ntohl(spi[i])); |
1213 | } | | 1213 | } |
1214 | | | 1214 | |
1215 | msg = next; | | 1215 | msg = next; |
1216 | } | | 1216 | } |
1217 | | | 1217 | |
1218 | if (buf) | | 1218 | if (buf) |
1219 | vfree(buf); | | 1219 | vfree(buf); |
1220 | } | | 1220 | } |
1221 | | | 1221 | |
1222 | /* | | 1222 | /* |
1223 | * delete all phase2 sa relatived to the destination address | | 1223 | * delete all phase2 sa relatived to the destination address |
1224 | * (except the phase2 within which the INITIAL-CONTACT was received). | | 1224 | * (except the phase2 within which the INITIAL-CONTACT was received). |
1225 | * Don't delete Phase 1 handlers on INITIAL-CONTACT, and don't ignore | | 1225 | * Don't delete Phase 1 handlers on INITIAL-CONTACT, and don't ignore |
1226 | * an INITIAL-CONTACT if we have contacted the peer. This matches the | | 1226 | * an INITIAL-CONTACT if we have contacted the peer. This matches the |
1227 | * Sun IKE behavior, and makes rekeying work much better when the peer | | 1227 | * Sun IKE behavior, and makes rekeying work much better when the peer |
1228 | * restarts. | | 1228 | * restarts. |
1229 | */ | | 1229 | */ |
1230 | int | | 1230 | int |
1231 | isakmp_info_recv_initialcontact(iph1, protectedph2) | | 1231 | isakmp_info_recv_initialcontact(iph1, protectedph2) |
1232 | struct ph1handle *iph1; | | 1232 | struct ph1handle *iph1; |
1233 | struct ph2handle *protectedph2; | | 1233 | struct ph2handle *protectedph2; |
1234 | { | | 1234 | { |
1235 | vchar_t *buf = NULL; | | 1235 | vchar_t *buf = NULL; |
1236 | struct sadb_msg *msg, *next, *end; | | 1236 | struct sadb_msg *msg, *next, *end; |
1237 | struct sadb_sa *sa; | | 1237 | struct sadb_sa *sa; |
1238 | struct sockaddr *src, *dst; | | 1238 | struct sockaddr *src, *dst; |
1239 | caddr_t mhp[SADB_EXT_MAX + 1]; | | 1239 | caddr_t mhp[SADB_EXT_MAX + 1]; |
1240 | int proto_id, i; | | 1240 | int proto_id, i; |
1241 | struct ph2handle *iph2; | | 1241 | struct ph2handle *iph2; |
1242 | #if 0 | | 1242 | #if 0 |
1243 | char *loc, *rem; | | 1243 | char *loc, *rem; |
1244 | #endif | | 1244 | #endif |
1245 | | | 1245 | |
1246 | plog(LLV_INFO, LOCATION, iph1->remote, "received INITIAL-CONTACT\n"); | | 1246 | plog(LLV_INFO, LOCATION, iph1->remote, "received INITIAL-CONTACT\n"); |
1247 | | | 1247 | |
1248 | if (f_local) | | 1248 | if (f_local) |
1249 | return 0; | | 1249 | return 0; |
1250 | | | 1250 | |
1251 | #if 0 | | 1251 | #if 0 |
1252 | loc = racoon_strdup(saddrwop2str(iph1->local)); | | 1252 | loc = racoon_strdup(saddrwop2str(iph1->local)); |
1253 | rem = racoon_strdup(saddrwop2str(iph1->remote)); | | 1253 | rem = racoon_strdup(saddrwop2str(iph1->remote)); |
1254 | STRDUP_FATAL(loc); | | 1254 | STRDUP_FATAL(loc); |
1255 | STRDUP_FATAL(rem); | | 1255 | STRDUP_FATAL(rem); |
1256 | | | 1256 | |
1257 | /* | | 1257 | /* |
1258 | * Purge all IPSEC-SAs for the peer. We can do this | | 1258 | * Purge all IPSEC-SAs for the peer. We can do this |
1259 | * the easy way (using a PF_KEY SADB_DELETE extension) | | 1259 | * the easy way (using a PF_KEY SADB_DELETE extension) |
1260 | * or we can do it the hard way. | | 1260 | * or we can do it the hard way. |
1261 | */ | | 1261 | */ |
1262 | for (i = 0; i < pfkey_nsatypes; i++) { | | 1262 | for (i = 0; i < pfkey_nsatypes; i++) { |
1263 | proto_id = pfkey2ipsecdoi_proto(pfkey_satypes[i].ps_satype); | | 1263 | proto_id = pfkey2ipsecdoi_proto(pfkey_satypes[i].ps_satype); |
1264 | | | 1264 | |
1265 | plog(LLV_INFO, LOCATION, NULL, | | 1265 | plog(LLV_INFO, LOCATION, NULL, |
1266 | "purging %s SAs for %s -> %s\n", | | 1266 | "purging %s SAs for %s -> %s\n", |
1267 | pfkey_satypes[i].ps_name, loc, rem); | | 1267 | pfkey_satypes[i].ps_name, loc, rem); |
1268 | if (pfkey_send_delete_all(lcconf->sock_pfkey, | | 1268 | if (pfkey_send_delete_all(lcconf->sock_pfkey, |
1269 | pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY, | | 1269 | pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY, |
1270 | iph1->local, iph1->remote) == -1) { | | 1270 | iph1->local, iph1->remote) == -1) { |
1271 | plog(LLV_ERROR, LOCATION, NULL, | | 1271 | plog(LLV_ERROR, LOCATION, NULL, |
1272 | "delete_all %s -> %s failed for %s (%s)\n", | | 1272 | "delete_all %s -> %s failed for %s (%s)\n", |
1273 | loc, rem, | | 1273 | loc, rem, |
1274 | pfkey_satypes[i].ps_name, ipsec_strerror()); | | 1274 | pfkey_satypes[i].ps_name, ipsec_strerror()); |
1275 | goto the_hard_way; | | 1275 | goto the_hard_way; |
1276 | } | | 1276 | } |
1277 | | | 1277 | |
1278 | deleteallph2(iph1->local, iph1->remote, proto_id); | | 1278 | deleteallph2(iph1->local, iph1->remote, proto_id); |
1279 | | | 1279 | |
1280 | plog(LLV_INFO, LOCATION, NULL, | | 1280 | plog(LLV_INFO, LOCATION, NULL, |
1281 | "purging %s SAs for %s -> %s\n", | | 1281 | "purging %s SAs for %s -> %s\n", |
1282 | pfkey_satypes[i].ps_name, rem, loc); | | 1282 | pfkey_satypes[i].ps_name, rem, loc); |
1283 | if (pfkey_send_delete_all(lcconf->sock_pfkey, | | 1283 | if (pfkey_send_delete_all(lcconf->sock_pfkey, |
1284 | pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY, | | 1284 | pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY, |
1285 | iph1->remote, iph1->local) == -1) { | | 1285 | iph1->remote, iph1->local) == -1) { |
1286 | plog(LLV_ERROR, LOCATION, NULL, | | 1286 | plog(LLV_ERROR, LOCATION, NULL, |
1287 | "delete_all %s -> %s failed for %s (%s)\n", | | 1287 | "delete_all %s -> %s failed for %s (%s)\n", |
1288 | rem, loc, | | 1288 | rem, loc, |
1289 | pfkey_satypes[i].ps_name, ipsec_strerror()); | | 1289 | pfkey_satypes[i].ps_name, ipsec_strerror()); |
1290 | goto the_hard_way; | | 1290 | goto the_hard_way; |
1291 | } | | 1291 | } |
1292 | | | 1292 | |
1293 | deleteallph2(iph1->remote, iph1->local, proto_id); | | 1293 | deleteallph2(iph1->remote, iph1->local, proto_id); |
1294 | } | | 1294 | } |
1295 | | | 1295 | |
1296 | racoon_free(loc); | | 1296 | racoon_free(loc); |
1297 | racoon_free(rem); | | 1297 | racoon_free(rem); |
1298 | return 0; | | 1298 | return 0; |
1299 | | | 1299 | |
1300 | the_hard_way: | | 1300 | the_hard_way: |
1301 | racoon_free(loc); | | 1301 | racoon_free(loc); |
1302 | racoon_free(rem); | | 1302 | racoon_free(rem); |
1303 | #endif | | 1303 | #endif |
1304 | | | 1304 | |
1305 | buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC); | | 1305 | buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC); |
1306 | if (buf == NULL) { | | 1306 | if (buf == NULL) { |
1307 | plog(LLV_DEBUG, LOCATION, NULL, | | 1307 | plog(LLV_DEBUG, LOCATION, NULL, |
1308 | "pfkey_dump_sadb returned nothing.\n"); | | 1308 | "pfkey_dump_sadb returned nothing.\n"); |
1309 | return 0; | | 1309 | return 0; |
1310 | } | | 1310 | } |
1311 | | | 1311 | |
1312 | msg = (struct sadb_msg *)buf->v; | | 1312 | msg = (struct sadb_msg *)buf->v; |
1313 | end = (struct sadb_msg *)(buf->v + buf->l); | | 1313 | end = (struct sadb_msg *)(buf->v + buf->l); |
1314 | | | 1314 | |
1315 | for (; msg < end; msg = next) { | | 1315 | for (; msg < end; msg = next) { |
1316 | if ((msg->sadb_msg_len << 3) < sizeof(*msg)) | | 1316 | if ((msg->sadb_msg_len << 3) < sizeof(*msg)) |
1317 | break; | | 1317 | break; |
1318 | | | 1318 | |
1319 | next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3)); | | 1319 | next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3)); |
1320 | if (msg->sadb_msg_type != SADB_DUMP) | | 1320 | if (msg->sadb_msg_type != SADB_DUMP) |
1321 | continue; | | 1321 | continue; |
1322 | | | 1322 | |
1323 | if (pfkey_align(msg, mhp) || pfkey_check(mhp)) { | | 1323 | if (pfkey_align(msg, mhp) || pfkey_check(mhp)) { |
1324 | plog(LLV_ERROR, LOCATION, NULL, | | 1324 | plog(LLV_ERROR, LOCATION, NULL, |
1325 | "pfkey_check (%s)\n", ipsec_strerror()); | | 1325 | "pfkey_check (%s)\n", ipsec_strerror()); |
1326 | continue; | | 1326 | continue; |
1327 | } | | 1327 | } |
1328 | | | 1328 | |
1329 | if (mhp[SADB_EXT_SA] == NULL | | 1329 | if (mhp[SADB_EXT_SA] == NULL |
1330 | || mhp[SADB_EXT_ADDRESS_SRC] == NULL | | 1330 | || mhp[SADB_EXT_ADDRESS_SRC] == NULL |
1331 | || mhp[SADB_EXT_ADDRESS_DST] == NULL) | | 1331 | || mhp[SADB_EXT_ADDRESS_DST] == NULL) |
1332 | continue; | | 1332 | continue; |
1333 | | | 1333 | |
1334 | sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; | | 1334 | sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; |
1335 | pk_fixup_sa_addresses(mhp); | | 1335 | pk_fixup_sa_addresses(mhp); |
1336 | src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); | | 1336 | src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); |
1337 | dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); | | 1337 | dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); |
1338 | | | 1338 | |
1339 | if (sa->sadb_sa_state != SADB_SASTATE_MATURE | | 1339 | if (sa->sadb_sa_state != SADB_SASTATE_MATURE |
1340 | && sa->sadb_sa_state != SADB_SASTATE_DYING) | | 1340 | && sa->sadb_sa_state != SADB_SASTATE_DYING) |
1341 | continue; | | 1341 | continue; |
1342 | | | 1342 | |
1343 | /* | | 1343 | /* |
1344 | * RFC2407 4.6.3.3 INITIAL-CONTACT is the message that | | 1344 | * RFC2407 4.6.3.3 INITIAL-CONTACT is the message that |
1345 | * announces the sender of the message was rebooted. | | 1345 | * announces the sender of the message was rebooted. |
1346 | * it is interpreted to delete all SAs which source address | | 1346 | * it is interpreted to delete all SAs which source address |
1347 | * is the sender of the message. | | 1347 | * is the sender of the message. |
1348 | * racoon only deletes SA which is matched both the | | 1348 | * racoon only deletes SA which is matched both the |
1349 | * source address and the destination accress. | | 1349 | * source address and the destination accress. |
1350 | */ | | 1350 | */ |
1351 | | | 1351 | |
1352 | /* | | 1352 | /* |
1353 | * Check that the IP and port match. But this is not optimal, | | 1353 | * Check that the IP and port match. But this is not optimal, |
1354 | * since NAT-T can make the peer have multiple different | | 1354 | * since NAT-T can make the peer have multiple different |
1355 | * ports. Correct thing to do is delete all entries with | | 1355 | * ports. Correct thing to do is delete all entries with |
1356 | * same identity. -TT | | 1356 | * same identity. -TT |
1357 | */ | | 1357 | */ |
1358 | if ((cmpsaddr(iph1->local, src) != CMPSADDR_MATCH || | | 1358 | if ((cmpsaddr(iph1->local, src) != CMPSADDR_MATCH || |
1359 | cmpsaddr(iph1->remote, dst) != CMPSADDR_MATCH) && | | 1359 | cmpsaddr(iph1->remote, dst) != CMPSADDR_MATCH) && |
1360 | (cmpsaddr(iph1->local, dst) != CMPSADDR_MATCH || | | 1360 | (cmpsaddr(iph1->local, dst) != CMPSADDR_MATCH || |
1361 | cmpsaddr(iph1->remote, src) != CMPSADDR_MATCH)) | | 1361 | cmpsaddr(iph1->remote, src) != CMPSADDR_MATCH)) |
1362 | continue; | | 1362 | continue; |
1363 | | | 1363 | |
1364 | /* | | 1364 | /* |
1365 | * Make sure this is an SATYPE that we manage. | | 1365 | * Make sure this is an SATYPE that we manage. |
1366 | * This is gross; too bad we couldn't do it the | | 1366 | * This is gross; too bad we couldn't do it the |
1367 | * easy way. | | 1367 | * easy way. |
1368 | */ | | 1368 | */ |
1369 | for (i = 0; i < pfkey_nsatypes; i++) { | | 1369 | for (i = 0; i < pfkey_nsatypes; i++) { |
1370 | if (pfkey_satypes[i].ps_satype == | | 1370 | if (pfkey_satypes[i].ps_satype == |
1371 | msg->sadb_msg_satype) | | 1371 | msg->sadb_msg_satype) |
1372 | break; | | 1372 | break; |
1373 | } | | 1373 | } |
1374 | if (i == pfkey_nsatypes) | | 1374 | if (i == pfkey_nsatypes) |
1375 | continue; | | 1375 | continue; |
1376 | | | 1376 | |
1377 | plog(LLV_INFO, LOCATION, NULL, | | 1377 | plog(LLV_INFO, LOCATION, NULL, |
1378 | "purging spi=%u.\n", ntohl(sa->sadb_sa_spi)); | | 1378 | "purging spi=%u.\n", ntohl(sa->sadb_sa_spi)); |
1379 | pfkey_send_delete(lcconf->sock_pfkey, | | 1379 | pfkey_send_delete(lcconf->sock_pfkey, |
1380 | msg->sadb_msg_satype, | | 1380 | msg->sadb_msg_satype, |
1381 | IPSEC_MODE_ANY, src, dst, sa->sadb_sa_spi); | | 1381 | IPSEC_MODE_ANY, src, dst, sa->sadb_sa_spi); |
1382 | | | 1382 | |
1383 | /* | | 1383 | /* |
1384 | * delete a relative phase 2 handler. | | 1384 | * delete a relative phase 2 handler. |
1385 | * continue to process if no relative phase 2 handler | | 1385 | * continue to process if no relative phase 2 handler |
1386 | * exists. | | 1386 | * exists. |
1387 | */ | | 1387 | */ |
1388 | proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype); | | 1388 | proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype); |
1389 | iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi); | | 1389 | iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi); |
1390 | if (iph2 && iph2 != protectedph2) { | | 1390 | if (iph2 && iph2 != protectedph2) { |
1391 | delete_spd(iph2, 0); | | 1391 | delete_spd(iph2, 0); |
1392 | remph2(iph2); | | 1392 | remph2(iph2); |
1393 | delph2(iph2); | | 1393 | delph2(iph2); |
1394 | } | | 1394 | } |
1395 | } | | 1395 | } |
1396 | | | 1396 | |
1397 | vfree(buf); | | 1397 | vfree(buf); |
1398 | return 0; | | 1398 | return 0; |
1399 | } | | 1399 | } |
1400 | | | 1400 | |
1401 | | | 1401 | |
1402 | #ifdef ENABLE_DPD | | 1402 | #ifdef ENABLE_DPD |
1403 | static int | | 1403 | static int |
1404 | isakmp_info_recv_r_u (iph1, ru, msgid) | | 1404 | isakmp_info_recv_r_u (iph1, ru, msgid) |
1405 | struct ph1handle *iph1; | | 1405 | struct ph1handle *iph1; |
1406 | struct isakmp_pl_ru *ru; | | 1406 | struct isakmp_pl_ru *ru; |
1407 | u_int32_t msgid; | | 1407 | u_int32_t msgid; |
1408 | { | | 1408 | { |
1409 | struct isakmp_pl_ru *ru_ack; | | 1409 | struct isakmp_pl_ru *ru_ack; |
1410 | vchar_t *payload = NULL; | | 1410 | vchar_t *payload = NULL; |
1411 | int tlen; | | 1411 | int tlen; |
1412 | int error = 0; | | 1412 | int error = 0; |
1413 | | | 1413 | |
1414 | plog(LLV_DEBUG, LOCATION, iph1->remote, | | 1414 | plog(LLV_DEBUG, LOCATION, iph1->remote, |
1415 | "DPD R-U-There received\n"); | | 1415 | "DPD R-U-There received\n"); |
1416 | | | 1416 | |
1417 | /* XXX should compare cookies with iph1->index? | | 1417 | /* XXX should compare cookies with iph1->index? |
1418 | Or is this already done by calling function? */ | | 1418 | Or is this already done by calling function? */ |
1419 | tlen = sizeof(*ru_ack); | | 1419 | tlen = sizeof(*ru_ack); |
1420 | payload = vmalloc(tlen); | | 1420 | payload = vmalloc(tlen); |
1421 | if (payload == NULL) { | | 1421 | if (payload == NULL) { |
1422 | plog(LLV_ERROR, LOCATION, NULL, | | 1422 | plog(LLV_ERROR, LOCATION, NULL, |
1423 | "failed to get buffer to send.\n"); | | 1423 | "failed to get buffer to send.\n"); |
1424 | return errno; | | 1424 | return errno; |
1425 | } | | 1425 | } |
1426 | | | 1426 | |
1427 | ru_ack = (struct isakmp_pl_ru *)payload->v; | | 1427 | ru_ack = (struct isakmp_pl_ru *)payload->v; |
1428 | ru_ack->h.np = ISAKMP_NPTYPE_NONE; | | 1428 | ru_ack->h.np = ISAKMP_NPTYPE_NONE; |
1429 | ru_ack->h.len = htons(tlen); | | 1429 | ru_ack->h.len = htons(tlen); |
1430 | ru_ack->doi = htonl(IPSEC_DOI); | | 1430 | ru_ack->doi = htonl(IPSEC_DOI); |
1431 | ru_ack->type = htons(ISAKMP_NTYPE_R_U_THERE_ACK); | | 1431 | ru_ack->type = htons(ISAKMP_NTYPE_R_U_THERE_ACK); |
1432 | ru_ack->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ? */ | | 1432 | ru_ack->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ? */ |
1433 | ru_ack->spi_size = sizeof(isakmp_index); | | 1433 | ru_ack->spi_size = sizeof(isakmp_index); |
1434 | memcpy(ru_ack->i_ck, ru->i_ck, sizeof(cookie_t)); | | 1434 | memcpy(ru_ack->i_ck, ru->i_ck, sizeof(cookie_t)); |
1435 | memcpy(ru_ack->r_ck, ru->r_ck, sizeof(cookie_t)); | | 1435 | memcpy(ru_ack->r_ck, ru->r_ck, sizeof(cookie_t)); |
1436 | ru_ack->data = ru->data; | | 1436 | ru_ack->data = ru->data; |
1437 | | | 1437 | |
1438 | /* XXX Should we do FLAG_A ? */ | | 1438 | /* XXX Should we do FLAG_A ? */ |
1439 | error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, | | 1439 | error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, |
1440 | ISAKMP_FLAG_E); | | 1440 | ISAKMP_FLAG_E); |
1441 | vfree(payload); | | 1441 | vfree(payload); |
1442 | | | 1442 | |
1443 | plog(LLV_DEBUG, LOCATION, NULL, "received a valid R-U-THERE, ACK sent\n"); | | 1443 | plog(LLV_DEBUG, LOCATION, NULL, "received a valid R-U-THERE, ACK sent\n"); |
1444 | | | 1444 | |
1445 | /* Should we mark tunnel as active ? */ | | 1445 | /* Should we mark tunnel as active ? */ |
1446 | return error; | | 1446 | return error; |
1447 | } | | 1447 | } |
1448 | | | 1448 | |
1449 | static int | | 1449 | static int |
1450 | isakmp_info_recv_r_u_ack (iph1, ru, msgid) | | 1450 | isakmp_info_recv_r_u_ack (iph1, ru, msgid) |
1451 | struct ph1handle *iph1; | | 1451 | struct ph1handle *iph1; |
1452 | struct isakmp_pl_ru *ru; | | 1452 | struct isakmp_pl_ru *ru; |
1453 | u_int32_t msgid; | | 1453 | u_int32_t msgid; |
1454 | { | | 1454 | { |
1455 | u_int32_t seq; | | 1455 | u_int32_t seq; |
1456 | | | 1456 | |
1457 | plog(LLV_DEBUG, LOCATION, iph1->remote, | | 1457 | plog(LLV_DEBUG, LOCATION, iph1->remote, |
1458 | "DPD R-U-There-Ack received\n"); | | 1458 | "DPD R-U-There-Ack received\n"); |
1459 | | | 1459 | |
1460 | seq = ntohl(ru->data); | | 1460 | seq = ntohl(ru->data); |
1461 | if (seq <= iph1->dpd_last_ack || seq > iph1->dpd_seq) { | | 1461 | if (seq <= iph1->dpd_last_ack || seq > iph1->dpd_seq) { |
1462 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 1462 | plog(LLV_ERROR, LOCATION, iph1->remote, |
1463 | "Wrong DPD sequence number (%d; last_ack=%d, seq=%d).\n", | | 1463 | "Wrong DPD sequence number (%d; last_ack=%d, seq=%d).\n", |
1464 | seq, iph1->dpd_last_ack, iph1->dpd_seq); | | 1464 | seq, iph1->dpd_last_ack, iph1->dpd_seq); |
1465 | return 0; | | 1465 | return 0; |
1466 | } | | 1466 | } |
1467 | | | 1467 | |
1468 | /* accept cookies in original or reversed order */ | | 1468 | /* accept cookies in original or reversed order */ |
1469 | if ((memcmp(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t)) || | | 1469 | if ((memcmp(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t)) || |
1470 | memcmp(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t))) && | | 1470 | memcmp(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t))) && |
1471 | (memcmp(ru->r_ck, iph1->index.i_ck, sizeof(cookie_t)) || | | 1471 | (memcmp(ru->r_ck, iph1->index.i_ck, sizeof(cookie_t)) || |
1472 | memcmp(ru->i_ck, iph1->index.r_ck, sizeof(cookie_t)))) { | | 1472 | memcmp(ru->i_ck, iph1->index.r_ck, sizeof(cookie_t)))) { |
1473 | plog(LLV_ERROR, LOCATION, iph1->remote, | | 1473 | plog(LLV_ERROR, LOCATION, iph1->remote, |
1474 | "Cookie mismatch in DPD ACK!.\n"); | | 1474 | "Cookie mismatch in DPD ACK!.\n"); |
1475 | return 0; | | 1475 | return 0; |
1476 | } | | 1476 | } |
1477 | | | 1477 | |
1478 | iph1->dpd_fails = 0; | | 1478 | iph1->dpd_fails = 0; |
1479 | iph1->dpd_last_ack = seq; | | 1479 | iph1->dpd_last_ack = seq; |
1480 | sched_cancel(&iph1->dpd_r_u); | | 1480 | sched_cancel(&iph1->dpd_r_u); |
1481 | isakmp_sched_r_u(iph1, 0); | | 1481 | isakmp_sched_r_u(iph1, 0); |
1482 | | | 1482 | |
1483 | plog(LLV_DEBUG, LOCATION, iph1->remote, "received an R-U-THERE-ACK\n"); | | 1483 | plog(LLV_DEBUG, LOCATION, iph1->remote, "received an R-U-THERE-ACK\n"); |
1484 | | | 1484 | |
1485 | return 0; | | 1485 | return 0; |
1486 | } | | 1486 | } |
1487 | | | 1487 | |
1488 | | | 1488 | |
1489 | | | 1489 | |
1490 | | | 1490 | |
1491 | /* | | 1491 | /* |
1492 | * send DPD R-U-THERE payload in Informational exchange. | | 1492 | * send DPD R-U-THERE payload in Informational exchange. |
1493 | */ | | 1493 | */ |
1494 | static void | | 1494 | static void |