| @@ -1,2185 +1,2184 @@ | | | @@ -1,2185 +1,2184 @@ |
1 | /* $NetBSD: ipsec_doi.c,v 1.48 2012/11/29 15:31:25 vanhu Exp $ */ | | 1 | /* $NetBSD: ipsec_doi.c,v 1.49 2013/06/18 05:39:50 tteras Exp $ */ |
2 | | | 2 | |
3 | /* Id: ipsec_doi.c,v 1.55 2006/08/17 09:20:41 vanhu Exp */ | | 3 | /* Id: ipsec_doi.c,v 1.55 2006/08/17 09:20:41 vanhu 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 <netinet/in.h> | | 40 | #include <netinet/in.h> |
41 | | | 41 | |
42 | #include PATH_IPSEC_H | | 42 | #include PATH_IPSEC_H |
43 | | | 43 | |
44 | #include <stdlib.h> | | 44 | #include <stdlib.h> |
45 | #include <stdio.h> | | 45 | #include <stdio.h> |
46 | #include <string.h> | | 46 | #include <string.h> |
47 | #include <errno.h> | | 47 | #include <errno.h> |
48 | #include <netdb.h> | | 48 | #include <netdb.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 | | | 59 | |
60 | #include "var.h" | | 60 | #include "var.h" |
61 | #include "vmbuf.h" | | 61 | #include "vmbuf.h" |
62 | #include "misc.h" | | 62 | #include "misc.h" |
63 | #include "plog.h" | | 63 | #include "plog.h" |
64 | #include "debug.h" | | 64 | #include "debug.h" |
65 | | | 65 | |
66 | #include "cfparse_proto.h" | | 66 | #include "cfparse_proto.h" |
67 | #include "isakmp_var.h" | | 67 | #include "isakmp_var.h" |
68 | #include "isakmp.h" | | 68 | #include "isakmp.h" |
69 | #include "ipsec_doi.h" | | 69 | #include "ipsec_doi.h" |
70 | #include "oakley.h" | | 70 | #include "oakley.h" |
71 | #include "remoteconf.h" | | 71 | #include "remoteconf.h" |
72 | #include "localconf.h" | | 72 | #include "localconf.h" |
73 | #include "sockmisc.h" | | 73 | #include "sockmisc.h" |
74 | #include "handler.h" | | 74 | #include "handler.h" |
75 | #include "policy.h" | | 75 | #include "policy.h" |
76 | #include "algorithm.h" | | 76 | #include "algorithm.h" |
77 | #include "sainfo.h" | | 77 | #include "sainfo.h" |
78 | #include "proposal.h" | | 78 | #include "proposal.h" |
79 | #include "crypto_openssl.h" | | 79 | #include "crypto_openssl.h" |
80 | #include "strnames.h" | | 80 | #include "strnames.h" |
81 | #include "gcmalloc.h" | | 81 | #include "gcmalloc.h" |
82 | | | 82 | |
83 | #ifdef ENABLE_NATT | | 83 | #ifdef ENABLE_NATT |
84 | #include "nattraversal.h" | | 84 | #include "nattraversal.h" |
85 | #endif | | 85 | #endif |
86 | | | 86 | |
87 | #ifdef HAVE_GSSAPI | | 87 | #ifdef HAVE_GSSAPI |
88 | #include <iconv.h> | | 88 | #include <iconv.h> |
89 | #include "gssapi.h" | | 89 | #include "gssapi.h" |
90 | #ifdef HAVE_ICONV_2ND_CONST | | 90 | #ifdef HAVE_ICONV_2ND_CONST |
91 | #define __iconv_const const | | 91 | #define __iconv_const const |
92 | #else | | 92 | #else |
93 | #define __iconv_const | | 93 | #define __iconv_const |
94 | #endif | | 94 | #endif |
95 | #endif | | 95 | #endif |
96 | | | 96 | |
97 | static vchar_t *get_ph1approval __P((struct ph1handle *, u_int32_t, u_int32_t, | | 97 | static vchar_t *get_ph1approval __P((struct ph1handle *, u_int32_t, u_int32_t, |
98 | struct prop_pair **)); | | 98 | struct prop_pair **)); |
99 | static int get_ph1approvalx __P((struct remoteconf *, void *)); | | 99 | static int get_ph1approvalx __P((struct remoteconf *, void *)); |
100 | | | 100 | |
101 | static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *, u_int32_t)); | | 101 | static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *, u_int32_t)); |
102 | static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *)); | | 102 | static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *)); |
103 | static struct prop_pair *get_ph2approval __P((struct ph2handle *, | | 103 | static struct prop_pair *get_ph2approval __P((struct ph2handle *, |
104 | struct prop_pair **)); | | 104 | struct prop_pair **)); |
105 | static struct prop_pair *get_ph2approvalx __P((struct ph2handle *, | | 105 | static struct prop_pair *get_ph2approvalx __P((struct ph2handle *, |
106 | struct prop_pair *)); | | 106 | struct prop_pair *)); |
107 | static void free_proppair0 __P((struct prop_pair *)); | | 107 | static void free_proppair0 __P((struct prop_pair *)); |
108 | static struct prop_pair ** get_proppair_and_doi_sit __P((vchar_t *, int, | | 108 | static struct prop_pair ** get_proppair_and_doi_sit __P((vchar_t *, int, |
109 | u_int32_t *, u_int32_t *)); | | 109 | u_int32_t *, u_int32_t *)); |
110 | | | 110 | |
111 | static int get_transform | | 111 | static int get_transform |
112 | __P((struct isakmp_pl_p *, struct prop_pair **, int *)); | | 112 | __P((struct isakmp_pl_p *, struct prop_pair **, int *)); |
113 | static u_int32_t ipsecdoi_set_ld __P((vchar_t *)); | | 113 | static u_int32_t ipsecdoi_set_ld __P((vchar_t *)); |
114 | | | 114 | |
115 | static int check_doi __P((u_int32_t)); | | 115 | static int check_doi __P((u_int32_t)); |
116 | static int check_situation __P((u_int32_t)); | | 116 | static int check_situation __P((u_int32_t)); |
117 | | | 117 | |
118 | static int check_prot_main __P((int)); | | 118 | static int check_prot_main __P((int)); |
119 | static int check_prot_quick __P((int)); | | 119 | static int check_prot_quick __P((int)); |
120 | static int (*check_protocol[]) __P((int)) = { | | 120 | static int (*check_protocol[]) __P((int)) = { |
121 | check_prot_main, /* IPSECDOI_TYPE_PH1 */ | | 121 | check_prot_main, /* IPSECDOI_TYPE_PH1 */ |
122 | check_prot_quick, /* IPSECDOI_TYPE_PH2 */ | | 122 | check_prot_quick, /* IPSECDOI_TYPE_PH2 */ |
123 | }; | | 123 | }; |
124 | | | 124 | |
125 | static int check_spi_size __P((int, int)); | | 125 | static int check_spi_size __P((int, int)); |
126 | | | 126 | |
127 | static int check_trns_isakmp __P((int)); | | 127 | static int check_trns_isakmp __P((int)); |
128 | static int check_trns_ah __P((int)); | | 128 | static int check_trns_ah __P((int)); |
129 | static int check_trns_esp __P((int)); | | 129 | static int check_trns_esp __P((int)); |
130 | static int check_trns_ipcomp __P((int)); | | 130 | static int check_trns_ipcomp __P((int)); |
131 | static int (*check_transform[]) __P((int)) = { | | 131 | static int (*check_transform[]) __P((int)) = { |
132 | 0, | | 132 | 0, |
133 | check_trns_isakmp, /* IPSECDOI_PROTO_ISAKMP */ | | 133 | check_trns_isakmp, /* IPSECDOI_PROTO_ISAKMP */ |
134 | check_trns_ah, /* IPSECDOI_PROTO_IPSEC_AH */ | | 134 | check_trns_ah, /* IPSECDOI_PROTO_IPSEC_AH */ |
135 | check_trns_esp, /* IPSECDOI_PROTO_IPSEC_ESP */ | | 135 | check_trns_esp, /* IPSECDOI_PROTO_IPSEC_ESP */ |
136 | check_trns_ipcomp, /* IPSECDOI_PROTO_IPCOMP */ | | 136 | check_trns_ipcomp, /* IPSECDOI_PROTO_IPCOMP */ |
137 | }; | | 137 | }; |
138 | | | 138 | |
139 | static int check_attr_isakmp __P((struct isakmp_pl_t *)); | | 139 | static int check_attr_isakmp __P((struct isakmp_pl_t *)); |
140 | static int check_attr_ah __P((struct isakmp_pl_t *)); | | 140 | static int check_attr_ah __P((struct isakmp_pl_t *)); |
141 | static int check_attr_esp __P((struct isakmp_pl_t *)); | | 141 | static int check_attr_esp __P((struct isakmp_pl_t *)); |
142 | static int check_attr_ipsec __P((int, struct isakmp_pl_t *)); | | 142 | static int check_attr_ipsec __P((int, struct isakmp_pl_t *)); |
143 | static int check_attr_ipcomp __P((struct isakmp_pl_t *)); | | 143 | static int check_attr_ipcomp __P((struct isakmp_pl_t *)); |
144 | static int (*check_attributes[]) __P((struct isakmp_pl_t *)) = { | | 144 | static int (*check_attributes[]) __P((struct isakmp_pl_t *)) = { |
145 | 0, | | 145 | 0, |
146 | check_attr_isakmp, /* IPSECDOI_PROTO_ISAKMP */ | | 146 | check_attr_isakmp, /* IPSECDOI_PROTO_ISAKMP */ |
147 | check_attr_ah, /* IPSECDOI_PROTO_IPSEC_AH */ | | 147 | check_attr_ah, /* IPSECDOI_PROTO_IPSEC_AH */ |
148 | check_attr_esp, /* IPSECDOI_PROTO_IPSEC_ESP */ | | 148 | check_attr_esp, /* IPSECDOI_PROTO_IPSEC_ESP */ |
149 | check_attr_ipcomp, /* IPSECDOI_PROTO_IPCOMP */ | | 149 | check_attr_ipcomp, /* IPSECDOI_PROTO_IPCOMP */ |
150 | }; | | 150 | }; |
151 | | | 151 | |
152 | static int setph1prop __P((struct isakmpsa *, caddr_t)); | | 152 | static int setph1prop __P((struct isakmpsa *, caddr_t)); |
153 | static int setph1trns __P((struct isakmpsa *, caddr_t)); | | 153 | static int setph1trns __P((struct isakmpsa *, caddr_t)); |
154 | static int setph1attr __P((struct isakmpsa *, caddr_t)); | | 154 | static int setph1attr __P((struct isakmpsa *, caddr_t)); |
155 | static vchar_t *setph2proposal0 __P((const struct ph2handle *, | | 155 | static vchar_t *setph2proposal0 __P((const struct ph2handle *, |
156 | const struct saprop *, const struct saproto *)); | | 156 | const struct saprop *, const struct saproto *)); |
157 | | | 157 | |
158 | struct ph1approvalx_ctx { | | 158 | struct ph1approvalx_ctx { |
159 | struct prop_pair *p; | | 159 | struct prop_pair *p; |
160 | struct isakmpsa *sa; | | 160 | struct isakmpsa *sa; |
161 | }; | | 161 | }; |
162 | | | 162 | |
163 | /*%%%*/ | | 163 | /*%%%*/ |
164 | /* | | 164 | /* |
165 | * check phase 1 SA payload. | | 165 | * check phase 1 SA payload. |
166 | * make new SA payload to be replyed not including general header. | | 166 | * make new SA payload to be replyed not including general header. |
167 | * the pointer to one of isakmpsa in proposal is set into iph1->approval. | | 167 | * the pointer to one of isakmpsa in proposal is set into iph1->approval. |
168 | * OUT: | | 168 | * OUT: |
169 | * positive: the pointer to new buffer of SA payload. | | 169 | * positive: the pointer to new buffer of SA payload. |
170 | * network byte order. | | 170 | * network byte order. |
171 | * NULL : error occurd. | | 171 | * NULL : error occurd. |
172 | */ | | 172 | */ |
173 | int | | 173 | int |
174 | ipsecdoi_checkph1proposal(sa, iph1) | | 174 | ipsecdoi_checkph1proposal(sa, iph1) |
175 | vchar_t *sa; | | 175 | vchar_t *sa; |
176 | struct ph1handle *iph1; | | 176 | struct ph1handle *iph1; |
177 | { | | 177 | { |
178 | vchar_t *newsa; /* new SA payload approved. */ | | 178 | vchar_t *newsa; /* new SA payload approved. */ |
179 | struct prop_pair **pair; | | 179 | struct prop_pair **pair; |
180 | u_int32_t doitype, sittype; | | 180 | u_int32_t doitype, sittype; |
181 | | | 181 | |
182 | /* get proposal pair */ | | 182 | /* get proposal pair */ |
183 | pair = get_proppair_and_doi_sit(sa, IPSECDOI_TYPE_PH1, | | 183 | pair = get_proppair_and_doi_sit(sa, IPSECDOI_TYPE_PH1, |
184 | &doitype, &sittype); | | 184 | &doitype, &sittype); |
185 | if (pair == NULL) | | 185 | if (pair == NULL) |
186 | return -1; | | 186 | return -1; |
187 | | | 187 | |
188 | /* check and get one SA for use */ | | 188 | /* check and get one SA for use */ |
189 | newsa = get_ph1approval(iph1, doitype, sittype, pair); | | 189 | newsa = get_ph1approval(iph1, doitype, sittype, pair); |
190 | free_proppair(pair); | | 190 | free_proppair(pair); |
191 | | | 191 | |
192 | if (newsa == NULL) | | 192 | if (newsa == NULL) |
193 | return -1; | | 193 | return -1; |
194 | | | 194 | |
195 | iph1->sa_ret = newsa; | | 195 | iph1->sa_ret = newsa; |
196 | return 0; | | 196 | return 0; |
197 | } | | 197 | } |
198 | | | 198 | |
199 | static void | | 199 | static void |
200 | print_ph1proposal(pair, s) | | 200 | print_ph1proposal(pair, s) |
201 | struct prop_pair *pair; | | 201 | struct prop_pair *pair; |
202 | struct isakmpsa *s; | | 202 | struct isakmpsa *s; |
203 | { | | 203 | { |
204 | struct isakmp_pl_p *prop = pair->prop; | | 204 | struct isakmp_pl_p *prop = pair->prop; |
205 | struct isakmp_pl_t *trns = pair->trns; | | 205 | struct isakmp_pl_t *trns = pair->trns; |
206 | | | 206 | |
207 | plog(LLV_DEBUG, LOCATION, NULL, | | 207 | plog(LLV_DEBUG, LOCATION, NULL, |
208 | "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n", | | 208 | "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n", |
209 | prop->p_no, s_ipsecdoi_proto(prop->proto_id), | | 209 | prop->p_no, s_ipsecdoi_proto(prop->proto_id), |
210 | prop->spi_size, prop->num_t); | | 210 | prop->spi_size, prop->num_t); |
211 | plog(LLV_DEBUG, LOCATION, NULL, | | 211 | plog(LLV_DEBUG, LOCATION, NULL, |
212 | "trns#=%d, trns-id=%s\n", | | 212 | "trns#=%d, trns-id=%s\n", |
213 | trns->t_no, s_ipsecdoi_trns(prop->proto_id, trns->t_id)); | | 213 | trns->t_no, s_ipsecdoi_trns(prop->proto_id, trns->t_id)); |
214 | plog(LLV_DEBUG, LOCATION, NULL, | | 214 | plog(LLV_DEBUG, LOCATION, NULL, |
215 | " lifetime = %ld\n", (long) s->lifetime); | | 215 | " lifetime = %ld\n", (long) s->lifetime); |
216 | plog(LLV_DEBUG, LOCATION, NULL, | | 216 | plog(LLV_DEBUG, LOCATION, NULL, |
217 | " lifebyte = %zu\n", s->lifebyte); | | 217 | " lifebyte = %zu\n", s->lifebyte); |
218 | plog(LLV_DEBUG, LOCATION, NULL, | | 218 | plog(LLV_DEBUG, LOCATION, NULL, |
219 | " enctype = %s\n", | | 219 | " enctype = %s\n", |
220 | s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, s->enctype)); | | 220 | s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, s->enctype)); |
221 | plog(LLV_DEBUG, LOCATION, NULL, | | 221 | plog(LLV_DEBUG, LOCATION, NULL, |
222 | " encklen = %d\n", s->encklen); | | 222 | " encklen = %d\n", s->encklen); |
223 | plog(LLV_DEBUG, LOCATION, NULL, | | 223 | plog(LLV_DEBUG, LOCATION, NULL, |
224 | " hashtype = %s\n", | | 224 | " hashtype = %s\n", |
225 | s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, s->hashtype)); | | 225 | s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, s->hashtype)); |
226 | plog(LLV_DEBUG, LOCATION, NULL, | | 226 | plog(LLV_DEBUG, LOCATION, NULL, |
227 | " authmethod = %s\n", | | 227 | " authmethod = %s\n", |
228 | s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, s->authmethod)); | | 228 | s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, s->authmethod)); |
229 | plog(LLV_DEBUG, LOCATION, NULL, | | 229 | plog(LLV_DEBUG, LOCATION, NULL, |
230 | " dh_group = %s\n", | | 230 | " dh_group = %s\n", |
231 | s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, s->dh_group)); | | 231 | s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, s->dh_group)); |
232 | } | | 232 | } |
233 | | | 233 | |
234 | | | 234 | |
235 | /* | | 235 | /* |
236 | * acceptable check for remote configuration. | | 236 | * acceptable check for remote configuration. |
237 | * return a new SA payload to be reply to peer. | | 237 | * return a new SA payload to be reply to peer. |
238 | */ | | 238 | */ |
239 | | | 239 | |
240 | static vchar_t * | | 240 | static vchar_t * |
241 | get_ph1approval(iph1, doitype, sittype, pair) | | 241 | get_ph1approval(iph1, doitype, sittype, pair) |
242 | struct ph1handle *iph1; | | 242 | struct ph1handle *iph1; |
243 | u_int32_t doitype, sittype; | | 243 | u_int32_t doitype, sittype; |
244 | struct prop_pair **pair; | | 244 | struct prop_pair **pair; |
245 | { | | 245 | { |
246 | vchar_t *newsa; | | 246 | vchar_t *newsa; |
247 | struct ph1approvalx_ctx ctx; | | 247 | struct ph1approvalx_ctx ctx; |
248 | struct prop_pair *s, *p; | | 248 | struct prop_pair *s, *p; |
249 | struct rmconfselector rmsel; | | 249 | struct rmconfselector rmsel; |
250 | struct isakmpsa *sa; | | 250 | struct isakmpsa *sa; |
251 | int i; | | 251 | int i; |
252 | | | 252 | |
253 | memset(&rmsel, 0, sizeof(rmsel)); | | 253 | memset(&rmsel, 0, sizeof(rmsel)); |
254 | rmsel.remote = iph1->remote; | | 254 | rmsel.remote = iph1->remote; |
255 | | | 255 | |
256 | if (iph1->approval) { | | 256 | if (iph1->approval) { |
257 | delisakmpsa(iph1->approval); | | 257 | delisakmpsa(iph1->approval); |
258 | iph1->approval = NULL; | | 258 | iph1->approval = NULL; |
259 | } | | 259 | } |
260 | | | 260 | |
261 | for (i = 0; i < MAXPROPPAIRLEN; i++) { | | 261 | for (i = 0; i < MAXPROPPAIRLEN; i++) { |
262 | if (pair[i] == NULL) | | 262 | if (pair[i] == NULL) |
263 | continue; | | 263 | continue; |
264 | for (s = pair[i]; s; s = s->next) { | | 264 | for (s = pair[i]; s; s = s->next) { |
265 | /* compare proposal and select one */ | | 265 | /* compare proposal and select one */ |
266 | for (p = s; p; p = p->tnext) { | | 266 | for (p = s; p; p = p->tnext) { |
267 | struct isakmp_pl_p *prop = p->prop; | | 267 | struct isakmp_pl_p *prop = p->prop; |
268 | | | 268 | |
269 | sa = newisakmpsa(); | | 269 | sa = newisakmpsa(); |
270 | ctx.p = p; | | 270 | ctx.p = p; |
271 | ctx.sa = sa; | | 271 | ctx.sa = sa; |
272 | if (t2isakmpsa(p->trns, sa, | | 272 | if (t2isakmpsa(p->trns, sa, |
273 | iph1->vendorid_mask) < 0) | | 273 | iph1->vendorid_mask) < 0) |
274 | continue; | | 274 | continue; |
275 | print_ph1proposal(p, sa); | | 275 | print_ph1proposal(p, sa); |
276 | if (iph1->rmconf != NULL) { | | 276 | if (iph1->rmconf != NULL) { |
277 | if (get_ph1approvalx(iph1->rmconf, &ctx)) | | 277 | if (get_ph1approvalx(iph1->rmconf, &ctx)) |
278 | goto found; | | 278 | goto found; |
279 | } else { | | 279 | } else { |
280 | if (enumrmconf(&rmsel, get_ph1approvalx, &ctx)) | | 280 | if (enumrmconf(&rmsel, get_ph1approvalx, &ctx)) |
281 | goto found; | | 281 | goto found; |
282 | } | | 282 | } |
283 | delisakmpsa(sa); | | 283 | delisakmpsa(sa); |
284 | } | | 284 | } |
285 | } | | 285 | } |
286 | } | | 286 | } |
287 | | | 287 | |
288 | plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n"); | | 288 | plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n"); |
289 | | | 289 | |
290 | return NULL; | | 290 | return NULL; |
291 | | | 291 | |
292 | found: | | 292 | found: |
293 | sa = ctx.sa; | | 293 | sa = ctx.sa; |
294 | plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n"); | | 294 | plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n"); |
295 | | | 295 | |
296 | /* check DH group settings */ | | 296 | /* check DH group settings */ |
297 | if (sa->dhgrp) { | | 297 | if (sa->dhgrp) { |
298 | if (sa->dhgrp->prime && sa->dhgrp->gen1) { | | 298 | if (sa->dhgrp->prime && sa->dhgrp->gen1) { |
299 | /* it's ok */ | | 299 | /* it's ok */ |
300 | goto saok; | | 300 | goto saok; |
301 | } | | 301 | } |
302 | plog(LLV_WARNING, LOCATION, NULL, | | 302 | plog(LLV_WARNING, LOCATION, NULL, |
303 | "invalid DH parameter found, use default.\n"); | | 303 | "invalid DH parameter found, use default.\n"); |
304 | oakley_dhgrp_free(sa->dhgrp); | | 304 | oakley_dhgrp_free(sa->dhgrp); |
305 | sa->dhgrp=NULL; | | 305 | sa->dhgrp=NULL; |
306 | } | | 306 | } |
307 | | | 307 | |
308 | if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) { | | 308 | if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) { |
309 | sa->dhgrp = NULL; | | 309 | sa->dhgrp = NULL; |
310 | delisakmpsa(sa); | | 310 | delisakmpsa(sa); |
311 | return NULL; | | 311 | return NULL; |
312 | } | | 312 | } |
313 | | | 313 | |
314 | saok: | | 314 | saok: |
315 | #ifdef HAVE_GSSAPI | | 315 | #ifdef HAVE_GSSAPI |
316 | if (sa->gssid != NULL) | | 316 | if (sa->gssid != NULL) |
317 | plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n", | | 317 | plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n", |
318 | (int)sa->gssid->l, sa->gssid->v); | | 318 | (int)sa->gssid->l, sa->gssid->v); |
319 | if (iph1->side == INITIATOR) { | | 319 | if (iph1->side == INITIATOR) { |
320 | if (iph1->rmconf->proposal->gssid != NULL) | | 320 | if (iph1->rmconf->proposal->gssid != NULL) |
321 | iph1->gi_i = vdup(iph1->rmconf->proposal->gssid); | | 321 | iph1->gi_i = vdup(iph1->rmconf->proposal->gssid); |
322 | if (sa->gssid != NULL) | | 322 | if (sa->gssid != NULL) |
323 | iph1->gi_r = vdup(sa->gssid); | | 323 | iph1->gi_r = vdup(sa->gssid); |
324 | } else { | | 324 | } else { |
325 | if (sa->gssid != NULL) { | | 325 | if (sa->gssid != NULL) { |
326 | iph1->gi_r = vdup(sa->gssid); | | 326 | iph1->gi_r = vdup(sa->gssid); |
327 | iph1->gi_i = gssapi_get_id(iph1); | | 327 | iph1->gi_i = gssapi_get_id(iph1); |
328 | } | | 328 | } |
329 | } | | 329 | } |
330 | if (iph1->gi_i != NULL) | | 330 | if (iph1->gi_i != NULL) |
331 | plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n", | | 331 | plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n", |
332 | (int)iph1->gi_i->l, iph1->gi_i->v); | | 332 | (int)iph1->gi_i->l, iph1->gi_i->v); |
333 | if (iph1->gi_r != NULL) | | 333 | if (iph1->gi_r != NULL) |
334 | plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n", | | 334 | plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n", |
335 | (int)iph1->gi_r->l, iph1->gi_r->v); | | 335 | (int)iph1->gi_r->l, iph1->gi_r->v); |
336 | #endif | | 336 | #endif |
337 | plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n", | | 337 | plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n", |
338 | s_oakley_attr_method(sa->authmethod)); | | 338 | s_oakley_attr_method(sa->authmethod)); |
339 | | | 339 | |
340 | newsa = get_sabyproppair(doitype, sittype, p); | | 340 | newsa = get_sabyproppair(doitype, sittype, p); |
341 | if (newsa == NULL) | | 341 | if (newsa == NULL) |
342 | delisakmpsa(sa); | | 342 | delisakmpsa(sa); |
343 | else | | 343 | else |
344 | iph1->approval = sa; | | 344 | iph1->approval = sa; |
345 | | | 345 | |
346 | return newsa; | | 346 | return newsa; |
347 | } | | 347 | } |
348 | | | 348 | |
349 | /* | | 349 | /* |
350 | * compare peer's single proposal and all of my proposal. | | 350 | * compare peer's single proposal and all of my proposal. |
351 | * and select one if suiatable. | | 351 | * and select one if suiatable. |
352 | */ | | 352 | */ |
353 | static int | | 353 | static int |
354 | get_ph1approvalx(rmconf, ctx) | | 354 | get_ph1approvalx(rmconf, ctx) |
355 | struct remoteconf *rmconf; | | 355 | struct remoteconf *rmconf; |
356 | void *ctx; | | 356 | void *ctx; |
357 | { | | 357 | { |
358 | struct ph1approvalx_ctx *pctx = (struct ph1approvalx_ctx *) ctx; | | 358 | struct ph1approvalx_ctx *pctx = (struct ph1approvalx_ctx *) ctx; |
359 | struct isakmpsa *sa; | | 359 | struct isakmpsa *sa; |
360 | | | 360 | |
361 | /* do the hard work */ | | 361 | /* do the hard work */ |
362 | sa = checkisakmpsa(rmconf->pcheck_level, pctx->sa, rmconf->proposal); | | 362 | sa = checkisakmpsa(rmconf->pcheck_level, pctx->sa, rmconf->proposal); |
363 | if (sa == NULL) | | 363 | if (sa == NULL) |
364 | return 0; | | 364 | return 0; |
365 | | | 365 | |
366 | /* duplicate and modify the found SA to match proposal */ | | 366 | /* duplicate and modify the found SA to match proposal */ |
367 | sa = dupisakmpsa(sa); | | 367 | sa = dupisakmpsa(sa); |
368 | | | 368 | |
369 | switch (rmconf->pcheck_level) { | | 369 | switch (rmconf->pcheck_level) { |
370 | case PROP_CHECK_OBEY: | | 370 | case PROP_CHECK_OBEY: |
371 | sa->lifetime = pctx->sa->lifetime; | | 371 | sa->lifetime = pctx->sa->lifetime; |
372 | sa->lifebyte = pctx->sa->lifebyte; | | 372 | sa->lifebyte = pctx->sa->lifebyte; |
373 | sa->encklen = pctx->sa->encklen; | | 373 | sa->encklen = pctx->sa->encklen; |
374 | break; | | 374 | break; |
375 | case PROP_CHECK_CLAIM: | | 375 | case PROP_CHECK_CLAIM: |
376 | case PROP_CHECK_STRICT: | | 376 | case PROP_CHECK_STRICT: |
377 | if (pctx->sa->lifetime < sa->lifetime) | | 377 | if (pctx->sa->lifetime < sa->lifetime) |
378 | sa->lifetime = pctx->sa->lifetime; | | 378 | sa->lifetime = pctx->sa->lifetime; |
379 | if (pctx->sa->lifebyte < sa->lifebyte) | | 379 | if (pctx->sa->lifebyte < sa->lifebyte) |
380 | sa->lifebyte = pctx->sa->lifebyte; | | 380 | sa->lifebyte = pctx->sa->lifebyte; |
381 | if (pctx->sa->encklen > sa->encklen) | | 381 | if (pctx->sa->encklen > sa->encklen) |
382 | sa->encklen = pctx->sa->encklen; | | 382 | sa->encklen = pctx->sa->encklen; |
383 | break; | | 383 | break; |
384 | default: | | 384 | default: |
385 | break; | | 385 | break; |
386 | } | | 386 | } |
387 | | | 387 | |
388 | /* replace the proposal with our approval sa */ | | 388 | /* replace the proposal with our approval sa */ |
389 | delisakmpsa(pctx->sa); | | 389 | delisakmpsa(pctx->sa); |
390 | pctx->sa = sa; | | 390 | pctx->sa = sa; |
391 | | | 391 | |
392 | return 1; | | 392 | return 1; |
393 | } | | 393 | } |
394 | | | 394 | |
395 | /* | | 395 | /* |
396 | * get ISAKMP data attributes | | 396 | * get ISAKMP data attributes |
397 | */ | | 397 | */ |
398 | static int | | 398 | static int |
399 | t2isakmpsa(trns, sa, vendorid_mask) | | 399 | t2isakmpsa(trns, sa, vendorid_mask) |
400 | struct isakmp_pl_t *trns; | | 400 | struct isakmp_pl_t *trns; |
401 | struct isakmpsa *sa; | | 401 | struct isakmpsa *sa; |
402 | u_int32_t vendorid_mask; | | 402 | u_int32_t vendorid_mask; |
403 | { | | 403 | { |
404 | struct isakmp_data *d, *prev; | | 404 | struct isakmp_data *d, *prev; |
405 | int flag, type; | | 405 | int flag, type; |
406 | int error = -1; | | 406 | int error = -1; |
407 | int life_t; | | 407 | int life_t; |
408 | int keylen = 0; | | 408 | int keylen = 0; |
409 | vchar_t *val = NULL; | | 409 | vchar_t *val = NULL; |
410 | int len, tlen; | | 410 | int len, tlen; |
411 | u_char *p; | | 411 | u_char *p; |
412 | | | 412 | |
413 | tlen = ntohs(trns->h.len) - sizeof(*trns); | | 413 | tlen = ntohs(trns->h.len) - sizeof(*trns); |
414 | prev = (struct isakmp_data *)NULL; | | 414 | prev = (struct isakmp_data *)NULL; |
415 | d = (struct isakmp_data *)(trns + 1); | | 415 | d = (struct isakmp_data *)(trns + 1); |
416 | | | 416 | |
417 | /* default */ | | 417 | /* default */ |
418 | life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT; | | 418 | life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT; |
419 | sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT; | | 419 | sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT; |
420 | sa->lifebyte = 0; | | 420 | sa->lifebyte = 0; |
421 | sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup)); | | 421 | sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup)); |
422 | if (!sa->dhgrp) | | 422 | if (!sa->dhgrp) |
423 | goto err; | | 423 | goto err; |
424 | | | 424 | |
425 | while (tlen > 0) { | | 425 | while (tlen > 0) { |
426 | | | 426 | |
427 | type = ntohs(d->type) & ~ISAKMP_GEN_MASK; | | 427 | type = ntohs(d->type) & ~ISAKMP_GEN_MASK; |
428 | flag = ntohs(d->type) & ISAKMP_GEN_MASK; | | 428 | flag = ntohs(d->type) & ISAKMP_GEN_MASK; |
429 | | | 429 | |
430 | plog(LLV_DEBUG, LOCATION, NULL, | | 430 | plog(LLV_DEBUG, LOCATION, NULL, |
431 | "type=%s, flag=0x%04x, lorv=%s\n", | | 431 | "type=%s, flag=0x%04x, lorv=%s\n", |
432 | s_oakley_attr(type), flag, | | 432 | s_oakley_attr(type), flag, |
433 | s_oakley_attr_v(type, ntohs(d->lorv))); | | 433 | s_oakley_attr_v(type, ntohs(d->lorv))); |
434 | | | 434 | |
435 | /* get variable-sized item */ | | 435 | /* get variable-sized item */ |
436 | switch (type) { | | 436 | switch (type) { |
437 | case OAKLEY_ATTR_GRP_PI: | | 437 | case OAKLEY_ATTR_GRP_PI: |
438 | case OAKLEY_ATTR_GRP_GEN_ONE: | | 438 | case OAKLEY_ATTR_GRP_GEN_ONE: |
439 | case OAKLEY_ATTR_GRP_GEN_TWO: | | 439 | case OAKLEY_ATTR_GRP_GEN_TWO: |
440 | case OAKLEY_ATTR_GRP_CURVE_A: | | 440 | case OAKLEY_ATTR_GRP_CURVE_A: |
441 | case OAKLEY_ATTR_GRP_CURVE_B: | | 441 | case OAKLEY_ATTR_GRP_CURVE_B: |
442 | case OAKLEY_ATTR_SA_LD: | | 442 | case OAKLEY_ATTR_SA_LD: |
443 | case OAKLEY_ATTR_GRP_ORDER: | | 443 | case OAKLEY_ATTR_GRP_ORDER: |
444 | if (flag) { /*TV*/ | | 444 | if (flag) { /*TV*/ |
445 | len = 2; | | 445 | len = 2; |
446 | p = (u_char *)&d->lorv; | | 446 | p = (u_char *)&d->lorv; |
447 | } else { /*TLV*/ | | 447 | } else { /*TLV*/ |
448 | len = ntohs(d->lorv); | | 448 | len = ntohs(d->lorv); |
449 | p = (u_char *)(d + 1); | | 449 | p = (u_char *)(d + 1); |
450 | } | | 450 | } |
451 | val = vmalloc(len); | | 451 | val = vmalloc(len); |
452 | if (!val) | | 452 | if (!val) |
453 | return -1; | | 453 | return -1; |
454 | memcpy(val->v, p, len); | | 454 | memcpy(val->v, p, len); |
455 | break; | | 455 | break; |
456 | | | 456 | |
457 | default: | | 457 | default: |
458 | break; | | 458 | break; |
459 | } | | 459 | } |
460 | | | 460 | |
461 | switch (type) { | | 461 | switch (type) { |
462 | case OAKLEY_ATTR_ENC_ALG: | | 462 | case OAKLEY_ATTR_ENC_ALG: |
463 | sa->enctype = (u_int16_t)ntohs(d->lorv); | | 463 | sa->enctype = (u_int16_t)ntohs(d->lorv); |
464 | break; | | 464 | break; |
465 | | | 465 | |
466 | case OAKLEY_ATTR_HASH_ALG: | | 466 | case OAKLEY_ATTR_HASH_ALG: |
467 | sa->hashtype = (u_int16_t)ntohs(d->lorv); | | 467 | sa->hashtype = (u_int16_t)ntohs(d->lorv); |
468 | break; | | 468 | break; |
469 | | | 469 | |
470 | case OAKLEY_ATTR_AUTH_METHOD: | | 470 | case OAKLEY_ATTR_AUTH_METHOD: |
471 | sa->authmethod = ntohs(d->lorv); | | 471 | sa->authmethod = ntohs(d->lorv); |
472 | #ifdef HAVE_GSSAPI | | 472 | #ifdef HAVE_GSSAPI |
473 | if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB_REAL && | | 473 | if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB_REAL && |
474 | (vendorid_mask & VENDORID_GSSAPI_MASK)) | | 474 | (vendorid_mask & VENDORID_GSSAPI_MASK)) |
475 | sa->authmethod = OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB; | | 475 | sa->authmethod = OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB; |
476 | #endif | | 476 | #endif |
477 | break; | | 477 | break; |
478 | | | 478 | |
479 | case OAKLEY_ATTR_GRP_DESC: | | 479 | case OAKLEY_ATTR_GRP_DESC: |
480 | sa->dh_group = (u_int16_t)ntohs(d->lorv); | | 480 | sa->dh_group = (u_int16_t)ntohs(d->lorv); |
481 | break; | | 481 | break; |
482 | | | 482 | |
483 | case OAKLEY_ATTR_GRP_TYPE: | | 483 | case OAKLEY_ATTR_GRP_TYPE: |
484 | { | | 484 | { |
485 | int type = (int)ntohs(d->lorv); | | 485 | int type = (int)ntohs(d->lorv); |
486 | if (type == OAKLEY_ATTR_GRP_TYPE_MODP) | | 486 | if (type == OAKLEY_ATTR_GRP_TYPE_MODP) |
487 | sa->dhgrp->type = type; | | 487 | sa->dhgrp->type = type; |
488 | else | | 488 | else |
489 | return -1; | | 489 | return -1; |
490 | break; | | 490 | break; |
491 | } | | 491 | } |
492 | case OAKLEY_ATTR_GRP_PI: | | 492 | case OAKLEY_ATTR_GRP_PI: |
493 | sa->dhgrp->prime = val; | | 493 | sa->dhgrp->prime = val; |
494 | break; | | 494 | break; |
495 | | | 495 | |
496 | case OAKLEY_ATTR_GRP_GEN_ONE: | | 496 | case OAKLEY_ATTR_GRP_GEN_ONE: |
497 | vfree(val); | | 497 | vfree(val); |
498 | if (!flag) | | 498 | if (!flag) |
499 | sa->dhgrp->gen1 = ntohs(d->lorv); | | 499 | sa->dhgrp->gen1 = ntohs(d->lorv); |
500 | else { | | 500 | else { |
501 | int len = ntohs(d->lorv); | | 501 | int len = ntohs(d->lorv); |
502 | sa->dhgrp->gen1 = 0; | | 502 | sa->dhgrp->gen1 = 0; |
503 | if (len > 4) | | 503 | if (len > 4) |
504 | return -1; | | 504 | return -1; |
505 | memcpy(&sa->dhgrp->gen1, d + 1, len); | | 505 | memcpy(&sa->dhgrp->gen1, d + 1, len); |
506 | sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1); | | 506 | sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1); |
507 | } | | 507 | } |
508 | break; | | 508 | break; |
509 | | | 509 | |
510 | case OAKLEY_ATTR_GRP_GEN_TWO: | | 510 | case OAKLEY_ATTR_GRP_GEN_TWO: |
511 | vfree(val); | | 511 | vfree(val); |
512 | if (!flag) | | 512 | if (!flag) |
513 | sa->dhgrp->gen2 = ntohs(d->lorv); | | 513 | sa->dhgrp->gen2 = ntohs(d->lorv); |
514 | else { | | 514 | else { |
515 | int len = ntohs(d->lorv); | | 515 | int len = ntohs(d->lorv); |
516 | sa->dhgrp->gen2 = 0; | | 516 | sa->dhgrp->gen2 = 0; |
517 | if (len > 4) | | 517 | if (len > 4) |
518 | return -1; | | 518 | return -1; |
519 | memcpy(&sa->dhgrp->gen2, d + 1, len); | | 519 | memcpy(&sa->dhgrp->gen2, d + 1, len); |
520 | sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2); | | 520 | sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2); |
521 | } | | 521 | } |
522 | break; | | 522 | break; |
523 | | | 523 | |
524 | case OAKLEY_ATTR_GRP_CURVE_A: | | 524 | case OAKLEY_ATTR_GRP_CURVE_A: |
525 | sa->dhgrp->curve_a = val; | | 525 | sa->dhgrp->curve_a = val; |
526 | break; | | 526 | break; |
527 | | | 527 | |
528 | case OAKLEY_ATTR_GRP_CURVE_B: | | 528 | case OAKLEY_ATTR_GRP_CURVE_B: |
529 | sa->dhgrp->curve_b = val; | | 529 | sa->dhgrp->curve_b = val; |
530 | break; | | 530 | break; |
531 | | | 531 | |
532 | case OAKLEY_ATTR_SA_LD_TYPE: | | 532 | case OAKLEY_ATTR_SA_LD_TYPE: |
533 | { | | 533 | { |
534 | int type = (int)ntohs(d->lorv); | | 534 | int type = (int)ntohs(d->lorv); |
535 | switch (type) { | | 535 | switch (type) { |
536 | case OAKLEY_ATTR_SA_LD_TYPE_SEC: | | 536 | case OAKLEY_ATTR_SA_LD_TYPE_SEC: |
537 | case OAKLEY_ATTR_SA_LD_TYPE_KB: | | 537 | case OAKLEY_ATTR_SA_LD_TYPE_KB: |
538 | life_t = type; | | 538 | life_t = type; |
539 | break; | | 539 | break; |
540 | default: | | 540 | default: |
541 | life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT; | | 541 | life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT; |
542 | break; | | 542 | break; |
543 | } | | 543 | } |
544 | break; | | 544 | break; |
545 | } | | 545 | } |
546 | case OAKLEY_ATTR_SA_LD: | | 546 | case OAKLEY_ATTR_SA_LD: |
547 | if (!prev | | 547 | if (!prev |
548 | || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) != | | 548 | || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) != |
549 | OAKLEY_ATTR_SA_LD_TYPE) { | | 549 | OAKLEY_ATTR_SA_LD_TYPE) { |
550 | plog(LLV_ERROR, LOCATION, NULL, | | 550 | plog(LLV_ERROR, LOCATION, NULL, |
551 | "life duration must follow ltype\n"); | | 551 | "life duration must follow ltype\n"); |
552 | break; | | 552 | break; |
553 | } | | 553 | } |
554 | | | 554 | |
555 | switch (life_t) { | | 555 | switch (life_t) { |
556 | case IPSECDOI_ATTR_SA_LD_TYPE_SEC: | | 556 | case IPSECDOI_ATTR_SA_LD_TYPE_SEC: |
557 | sa->lifetime = ipsecdoi_set_ld(val); | | 557 | sa->lifetime = ipsecdoi_set_ld(val); |
558 | vfree(val); | | 558 | vfree(val); |
559 | if (sa->lifetime == 0) { | | 559 | if (sa->lifetime == 0) { |
560 | plog(LLV_ERROR, LOCATION, NULL, | | 560 | plog(LLV_ERROR, LOCATION, NULL, |
561 | "invalid life duration.\n"); | | 561 | "invalid life duration.\n"); |
562 | goto err; | | 562 | goto err; |
563 | } | | 563 | } |
564 | break; | | 564 | break; |
565 | case IPSECDOI_ATTR_SA_LD_TYPE_KB: | | 565 | case IPSECDOI_ATTR_SA_LD_TYPE_KB: |
566 | sa->lifebyte = ipsecdoi_set_ld(val); | | 566 | sa->lifebyte = ipsecdoi_set_ld(val); |
567 | vfree(val); | | 567 | vfree(val); |
568 | if (sa->lifebyte == 0) { | | 568 | if (sa->lifebyte == 0) { |
569 | plog(LLV_ERROR, LOCATION, NULL, | | 569 | plog(LLV_ERROR, LOCATION, NULL, |
570 | "invalid life duration.\n"); | | 570 | "invalid life duration.\n"); |
571 | goto err; | | 571 | goto err; |
572 | } | | 572 | } |
573 | break; | | 573 | break; |
574 | default: | | 574 | default: |
575 | vfree(val); | | 575 | vfree(val); |
576 | plog(LLV_ERROR, LOCATION, NULL, | | 576 | plog(LLV_ERROR, LOCATION, NULL, |
577 | "invalid life type: %d\n", life_t); | | 577 | "invalid life type: %d\n", life_t); |
578 | goto err; | | 578 | goto err; |
579 | } | | 579 | } |
580 | break; | | 580 | break; |
581 | | | 581 | |
582 | case OAKLEY_ATTR_KEY_LEN: | | 582 | case OAKLEY_ATTR_KEY_LEN: |
583 | { | | 583 | { |
584 | int len = ntohs(d->lorv); | | 584 | int len = ntohs(d->lorv); |
585 | if (len % 8 != 0) { | | 585 | if (len % 8 != 0) { |
586 | plog(LLV_ERROR, LOCATION, NULL, | | 586 | plog(LLV_ERROR, LOCATION, NULL, |
587 | "keylen %d: not multiple of 8\n", | | 587 | "keylen %d: not multiple of 8\n", |
588 | len); | | 588 | len); |
589 | goto err; | | 589 | goto err; |
590 | } | | 590 | } |
591 | sa->encklen = (u_int16_t)len; | | 591 | sa->encklen = (u_int16_t)len; |
592 | keylen++; | | 592 | keylen++; |
593 | break; | | 593 | break; |
594 | } | | 594 | } |
595 | case OAKLEY_ATTR_PRF: | | 595 | case OAKLEY_ATTR_PRF: |
596 | case OAKLEY_ATTR_FIELD_SIZE: | | 596 | case OAKLEY_ATTR_FIELD_SIZE: |
597 | /* unsupported */ | | 597 | /* unsupported */ |
598 | break; | | 598 | break; |
599 | | | 599 | |
600 | case OAKLEY_ATTR_GRP_ORDER: | | 600 | case OAKLEY_ATTR_GRP_ORDER: |
601 | sa->dhgrp->order = val; | | 601 | sa->dhgrp->order = val; |
602 | break; | | 602 | break; |
603 | #ifdef HAVE_GSSAPI | | 603 | #ifdef HAVE_GSSAPI |
604 | case OAKLEY_ATTR_GSS_ID: | | 604 | case OAKLEY_ATTR_GSS_ID: |
605 | { | | 605 | { |
606 | int error = -1; | | 606 | int error = -1; |
607 | iconv_t cd = (iconv_t) -1; | | 607 | iconv_t cd = (iconv_t) -1; |
608 | size_t srcleft, dstleft, rv; | | 608 | size_t srcleft, dstleft, rv; |
609 | __iconv_const char *src; | | 609 | __iconv_const char *src; |
610 | char *dst; | | 610 | char *dst; |
611 | int len = ntohs(d->lorv); | | 611 | int len = ntohs(d->lorv); |
612 | | | 612 | |
613 | /* | | 613 | /* |
614 | * Older verions of racoon just placed the | | 614 | * Older verions of racoon just placed the |
615 | * ISO-Latin-1 string on the wire directly. | | 615 | * ISO-Latin-1 string on the wire directly. |
616 | * Check to see if we are configured to be | | 616 | * Check to see if we are configured to be |
617 | * compatible with this behavior. | | 617 | * compatible with this behavior. |
618 | */ | | 618 | */ |
619 | if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) { | | 619 | if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) { |
620 | if ((sa->gssid = vmalloc(len)) == NULL) { | | 620 | if ((sa->gssid = vmalloc(len)) == NULL) { |
621 | plog(LLV_ERROR, LOCATION, NULL, | | 621 | plog(LLV_ERROR, LOCATION, NULL, |
622 | "failed to allocate memory\n"); | | 622 | "failed to allocate memory\n"); |
623 | goto out; | | 623 | goto out; |
624 | } | | 624 | } |
625 | memcpy(sa->gssid->v, d + 1, len); | | 625 | memcpy(sa->gssid->v, d + 1, len); |
626 | plog(LLV_DEBUG, LOCATION, NULL, | | 626 | plog(LLV_DEBUG, LOCATION, NULL, |
627 | "received old-style gss " | | 627 | "received old-style gss " |
628 | "id '%.*s' (len %zu)\n", | | 628 | "id '%.*s' (len %zu)\n", |
629 | (int)sa->gssid->l, sa->gssid->v, | | 629 | (int)sa->gssid->l, sa->gssid->v, |
630 | sa->gssid->l); | | 630 | sa->gssid->l); |
631 | error = 0; | | 631 | error = 0; |
632 | goto out; | | 632 | goto out; |
633 | } | | 633 | } |
634 | | | 634 | |
635 | /* | | 635 | /* |
636 | * For Windows 2000 compatibility, we expect | | 636 | * For Windows 2000 compatibility, we expect |
637 | * the GSS ID attribute on the wire to be | | 637 | * the GSS ID attribute on the wire to be |
638 | * encoded in UTF-16LE. Internally, we work | | 638 | * encoded in UTF-16LE. Internally, we work |
639 | * in ISO-Latin-1. Therefore, we should need | | 639 | * in ISO-Latin-1. Therefore, we should need |
640 | * 1/2 the specified length, which should always | | 640 | * 1/2 the specified length, which should always |
641 | * be a multiple of 2 octets. | | 641 | * be a multiple of 2 octets. |
642 | */ | | 642 | */ |
643 | cd = iconv_open("latin1", "utf-16le"); | | 643 | cd = iconv_open("latin1", "utf-16le"); |
644 | if (cd == (iconv_t) -1) { | | 644 | if (cd == (iconv_t) -1) { |
645 | plog(LLV_ERROR, LOCATION, NULL, | | 645 | plog(LLV_ERROR, LOCATION, NULL, |
646 | "unable to initialize utf-16le -> latin1 " | | 646 | "unable to initialize utf-16le -> latin1 " |
647 | "conversion descriptor: %s\n", | | 647 | "conversion descriptor: %s\n", |
648 | strerror(errno)); | | 648 | strerror(errno)); |
649 | goto out; | | 649 | goto out; |
650 | } | | 650 | } |
651 | | | 651 | |
652 | if ((sa->gssid = vmalloc(len / 2)) == NULL) { | | 652 | if ((sa->gssid = vmalloc(len / 2)) == NULL) { |
653 | plog(LLV_ERROR, LOCATION, NULL, | | 653 | plog(LLV_ERROR, LOCATION, NULL, |
654 | "failed to allocate memory\n"); | | 654 | "failed to allocate memory\n"); |
655 | goto out; | | 655 | goto out; |
656 | } | | 656 | } |
657 | | | 657 | |
658 | src = (__iconv_const char *)(d + 1); | | 658 | src = (__iconv_const char *)(d + 1); |
659 | srcleft = len; | | 659 | srcleft = len; |
660 | | | 660 | |
661 | dst = sa->gssid->v; | | 661 | dst = sa->gssid->v; |
662 | dstleft = len / 2; | | 662 | dstleft = len / 2; |
663 | | | 663 | |
664 | rv = iconv(cd, (__iconv_const char **)&src, &srcleft, | | 664 | rv = iconv(cd, (__iconv_const char **)&src, &srcleft, |
665 | &dst, &dstleft); | | 665 | &dst, &dstleft); |
666 | if (rv != 0) { | | 666 | if (rv != 0) { |
667 | if (rv == -1) { | | 667 | if (rv == -1) { |
668 | plog(LLV_ERROR, LOCATION, NULL, | | 668 | plog(LLV_ERROR, LOCATION, NULL, |
669 | "unable to convert GSS ID from " | | 669 | "unable to convert GSS ID from " |
670 | "utf-16le -> latin1: %s\n", | | 670 | "utf-16le -> latin1: %s\n", |
671 | strerror(errno)); | | 671 | strerror(errno)); |
672 | } else { | | 672 | } else { |
673 | plog(LLV_ERROR, LOCATION, NULL, | | 673 | plog(LLV_ERROR, LOCATION, NULL, |
674 | "%zd character%s in GSS ID cannot " | | 674 | "%zd character%s in GSS ID cannot " |
675 | "be represented in latin1\n", | | 675 | "be represented in latin1\n", |
676 | rv, rv == 1 ? "" : "s"); | | 676 | rv, rv == 1 ? "" : "s"); |
677 | } | | 677 | } |
678 | goto out; | | 678 | goto out; |
679 | } | | 679 | } |
680 | | | 680 | |
681 | /* XXX dstleft should always be 0; assert it? */ | | 681 | /* XXX dstleft should always be 0; assert it? */ |
682 | sa->gssid->l = (len / 2) - dstleft; | | 682 | sa->gssid->l = (len / 2) - dstleft; |
683 | | | 683 | |
684 | plog(LLV_DEBUG, LOCATION, NULL, | | 684 | plog(LLV_DEBUG, LOCATION, NULL, |
685 | "received gss id '%.*s' (len %zu)\n", | | 685 | "received gss id '%.*s' (len %zu)\n", |
686 | (int)sa->gssid->l, sa->gssid->v, sa->gssid->l); | | 686 | (int)sa->gssid->l, sa->gssid->v, sa->gssid->l); |
687 | | | 687 | |
688 | error = 0; | | 688 | error = 0; |
689 | out: | | 689 | out: |
690 | if (cd != (iconv_t)-1) | | 690 | if (cd != (iconv_t)-1) |
691 | (void)iconv_close(cd); | | 691 | (void)iconv_close(cd); |
692 | | | 692 | |
693 | if ((error != 0) && (sa->gssid != NULL)) { | | 693 | if ((error != 0) && (sa->gssid != NULL)) { |
694 | vfree(sa->gssid); | | 694 | vfree(sa->gssid); |
695 | sa->gssid = NULL; | | 695 | sa->gssid = NULL; |
696 | } | | 696 | } |
697 | break; | | 697 | break; |
698 | } | | 698 | } |
699 | #endif /* HAVE_GSSAPI */ | | 699 | #endif /* HAVE_GSSAPI */ |
700 | | | 700 | |
701 | default: | | 701 | default: |
702 | break; | | 702 | break; |
703 | } | | 703 | } |
704 | | | 704 | |
705 | prev = d; | | 705 | prev = d; |
706 | if (flag) { | | 706 | if (flag) { |
707 | tlen -= sizeof(*d); | | 707 | tlen -= sizeof(*d); |
708 | d = (struct isakmp_data *)((char *)d + sizeof(*d)); | | 708 | d = (struct isakmp_data *)((char *)d + sizeof(*d)); |
709 | } else { | | 709 | } else { |
710 | tlen -= (sizeof(*d) + ntohs(d->lorv)); | | 710 | tlen -= (sizeof(*d) + ntohs(d->lorv)); |
711 | d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv)); | | 711 | d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv)); |
712 | } | | 712 | } |
713 | } | | 713 | } |
714 | | | 714 | |
715 | /* key length must not be specified on some algorithms */ | | 715 | /* key length must not be specified on some algorithms */ |
716 | if (keylen) { | | 716 | if (keylen) { |
717 | if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES | | 717 | if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES |
718 | #ifdef HAVE_OPENSSL_IDEA_H | | 718 | #ifdef HAVE_OPENSSL_IDEA_H |
719 | || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA | | 719 | || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA |
720 | #endif | | 720 | #endif |
721 | || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) { | | 721 | || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) { |
722 | plog(LLV_ERROR, LOCATION, NULL, | | 722 | plog(LLV_ERROR, LOCATION, NULL, |
723 | "keylen must not be specified " | | 723 | "keylen must not be specified " |
724 | "for encryption algorithm %d\n", | | 724 | "for encryption algorithm %d\n", |
725 | sa->enctype); | | 725 | sa->enctype); |
726 | return -1; | | 726 | return -1; |
727 | } | | 727 | } |
728 | } | | 728 | } |
729 | | | 729 | |
730 | return 0; | | 730 | return 0; |
731 | err: | | 731 | err: |
732 | return error; | | 732 | return error; |
733 | } | | 733 | } |
734 | | | 734 | |
735 | /*%%%*/ | | 735 | /*%%%*/ |
736 | /* | | 736 | /* |
737 | * check phase 2 SA payload and select single proposal. | | 737 | * check phase 2 SA payload and select single proposal. |
738 | * make new SA payload to be replyed not including general header. | | 738 | * make new SA payload to be replyed not including general header. |
739 | * This function is called by responder only. | | 739 | * This function is called by responder only. |
740 | * OUT: | | 740 | * OUT: |
741 | * 0: succeed. | | 741 | * 0: succeed. |
742 | * -1: error occured. | | 742 | * -1: error occured. |
743 | */ | | 743 | */ |
744 | int | | 744 | int |
745 | ipsecdoi_selectph2proposal(iph2) | | 745 | ipsecdoi_selectph2proposal(iph2) |
746 | struct ph2handle *iph2; | | 746 | struct ph2handle *iph2; |
747 | { | | 747 | { |
748 | struct prop_pair **pair; | | 748 | struct prop_pair **pair; |
749 | struct prop_pair *ret; | | 749 | struct prop_pair *ret; |
750 | u_int32_t doitype, sittype; | | 750 | u_int32_t doitype, sittype; |
751 | | | 751 | |
752 | /* get proposal pair */ | | 752 | /* get proposal pair */ |
753 | pair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2, | | 753 | pair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2, |
754 | &doitype, &sittype); | | 754 | &doitype, &sittype); |
755 | if (pair == NULL) | | 755 | if (pair == NULL) |
756 | return -1; | | 756 | return -1; |
757 | | | 757 | |
758 | /* check and select a proposal. */ | | 758 | /* check and select a proposal. */ |
759 | ret = get_ph2approval(iph2, pair); | | 759 | ret = get_ph2approval(iph2, pair); |
760 | free_proppair(pair); | | 760 | free_proppair(pair); |
761 | if (ret == NULL) | | 761 | if (ret == NULL) |
762 | return -1; | | 762 | return -1; |
763 | | | 763 | |
764 | /* make a SA to be replayed. */ | | 764 | /* make a SA to be replayed. */ |
765 | /* SPI must be updated later. */ | | 765 | /* SPI must be updated later. */ |
766 | iph2->sa_ret = get_sabyproppair(doitype, sittype, ret); | | 766 | iph2->sa_ret = get_sabyproppair(doitype, sittype, ret); |
767 | free_proppair0(ret); | | 767 | free_proppair0(ret); |
768 | if (iph2->sa_ret == NULL) | | 768 | if (iph2->sa_ret == NULL) |
769 | return -1; | | 769 | return -1; |
770 | | | 770 | |
771 | return 0; | | 771 | return 0; |
772 | } | | 772 | } |
773 | | | 773 | |
774 | /* | | 774 | /* |
775 | * check phase 2 SA payload returned from responder. | | 775 | * check phase 2 SA payload returned from responder. |
776 | * This function is called by initiator only. | | 776 | * This function is called by initiator only. |
777 | * OUT: | | 777 | * OUT: |
778 | * 0: valid. | | 778 | * 0: valid. |
779 | * -1: invalid. | | 779 | * -1: invalid. |
780 | */ | | 780 | */ |
781 | int | | 781 | int |
782 | ipsecdoi_checkph2proposal(iph2) | | 782 | ipsecdoi_checkph2proposal(iph2) |
783 | struct ph2handle *iph2; | | 783 | struct ph2handle *iph2; |
784 | { | | 784 | { |
785 | struct prop_pair **rpair = NULL, **spair = NULL; | | 785 | struct prop_pair **rpair = NULL, **spair = NULL; |
786 | struct prop_pair *p; | | 786 | struct prop_pair *p; |
787 | int i, n, num; | | 787 | int i, n, num; |
788 | int error = -1; | | 788 | int error = -1; |
789 | vchar_t *sa_ret = NULL; | | 789 | vchar_t *sa_ret = NULL; |
790 | u_int32_t doitype, sittype; | | 790 | u_int32_t doitype, sittype; |
791 | | | 791 | |
792 | /* get proposal pair of SA sent. */ | | 792 | /* get proposal pair of SA sent. */ |
793 | spair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2, | | 793 | spair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2, |
794 | &doitype, &sittype); | | 794 | &doitype, &sittype); |
795 | if (spair == NULL) { | | 795 | if (spair == NULL) { |
796 | plog(LLV_ERROR, LOCATION, NULL, | | 796 | plog(LLV_ERROR, LOCATION, NULL, |
797 | "failed to get prop pair.\n"); | | 797 | "failed to get prop pair.\n"); |
798 | goto end; | | 798 | goto end; |
799 | } | | 799 | } |
800 | | | 800 | |
801 | /* XXX should check the number of transform */ | | 801 | /* XXX should check the number of transform */ |
802 | | | 802 | |
803 | /* get proposal pair of SA replayed */ | | 803 | /* get proposal pair of SA replayed */ |
804 | rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2); | | 804 | rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2); |
805 | if (rpair == NULL) { | | 805 | if (rpair == NULL) { |
806 | plog(LLV_ERROR, LOCATION, NULL, | | 806 | plog(LLV_ERROR, LOCATION, NULL, |
807 | "failed to get prop pair.\n"); | | 807 | "failed to get prop pair.\n"); |
808 | goto end; | | 808 | goto end; |
809 | } | | 809 | } |
810 | | | 810 | |
811 | /* check proposal is only one ? */ | | 811 | /* check proposal is only one ? */ |
812 | n = 0; | | 812 | n = 0; |
813 | num = 0; | | 813 | num = 0; |
814 | for (i = 0; i < MAXPROPPAIRLEN; i++) { | | 814 | for (i = 0; i < MAXPROPPAIRLEN; i++) { |
815 | if (rpair[i]) { | | 815 | if (rpair[i]) { |
816 | n = i; | | 816 | n = i; |
817 | num++; | | 817 | num++; |
818 | } | | 818 | } |
819 | } | | 819 | } |
820 | if (num == 0) { | | 820 | if (num == 0) { |
821 | plog(LLV_ERROR, LOCATION, NULL, | | 821 | plog(LLV_ERROR, LOCATION, NULL, |
822 | "no proposal received.\n"); | | 822 | "no proposal received.\n"); |
823 | goto end; | | 823 | goto end; |
824 | } | | 824 | } |
825 | if (num != 1) { | | 825 | if (num != 1) { |
826 | plog(LLV_ERROR, LOCATION, NULL, | | 826 | plog(LLV_ERROR, LOCATION, NULL, |
827 | "some proposals received.\n"); | | 827 | "some proposals received.\n"); |
828 | goto end; | | 828 | goto end; |
829 | } | | 829 | } |
830 | | | 830 | |
831 | if (spair[n] == NULL) { | | 831 | if (spair[n] == NULL) { |
832 | plog(LLV_WARNING, LOCATION, NULL, | | 832 | plog(LLV_WARNING, LOCATION, NULL, |
833 | "invalid proposal number:%d received.\n", i); | | 833 | "invalid proposal number:%d received.\n", i); |
834 | } | | 834 | } |
835 | | | 835 | |
836 | | | 836 | |
837 | if (rpair[n]->tnext != NULL) { | | 837 | if (rpair[n]->tnext != NULL) { |
838 | plog(LLV_ERROR, LOCATION, NULL, | | 838 | plog(LLV_ERROR, LOCATION, NULL, |
839 | "multi transforms replyed.\n"); | | 839 | "multi transforms replyed.\n"); |
840 | goto end; | | 840 | goto end; |
841 | } | | 841 | } |
842 | | | 842 | |
843 | if (cmp_aproppair_i(rpair[n], spair[n])) { | | 843 | if (cmp_aproppair_i(rpair[n], spair[n])) { |
844 | plog(LLV_ERROR, LOCATION, NULL, | | 844 | plog(LLV_ERROR, LOCATION, NULL, |
845 | "proposal mismathed.\n"); | | 845 | "proposal mismathed.\n"); |
846 | goto end; | | 846 | goto end; |
847 | } | | 847 | } |
848 | | | 848 | |
849 | /* | | 849 | /* |
850 | * check and select a proposal. | | 850 | * check and select a proposal. |
851 | * ensure that there is no modification of the proposal by | | 851 | * ensure that there is no modification of the proposal by |
852 | * cmp_aproppair_i() | | 852 | * cmp_aproppair_i() |
853 | */ | | 853 | */ |
854 | p = get_ph2approval(iph2, rpair); | | 854 | p = get_ph2approval(iph2, rpair); |
855 | if (p == NULL) | | 855 | if (p == NULL) |
856 | goto end; | | 856 | goto end; |
857 | | | 857 | |
858 | /* make a SA to be replayed. */ | | 858 | /* make a SA to be replayed. */ |
859 | sa_ret = iph2->sa_ret; | | 859 | sa_ret = iph2->sa_ret; |
860 | iph2->sa_ret = get_sabyproppair(doitype, sittype, p); | | 860 | iph2->sa_ret = get_sabyproppair(doitype, sittype, p); |
861 | free_proppair0(p); | | 861 | free_proppair0(p); |
862 | if (iph2->sa_ret == NULL) | | 862 | if (iph2->sa_ret == NULL) |
863 | goto end; | | 863 | goto end; |
864 | | | 864 | |
865 | error = 0; | | 865 | error = 0; |
866 | | | 866 | |
867 | end: | | 867 | end: |
868 | if (rpair) | | 868 | if (rpair) |
869 | free_proppair(rpair); | | 869 | free_proppair(rpair); |
870 | if (spair) | | 870 | if (spair) |
871 | free_proppair(spair); | | 871 | free_proppair(spair); |
872 | if (sa_ret) | | 872 | if (sa_ret) |
873 | vfree(sa_ret); | | 873 | vfree(sa_ret); |
874 | | | 874 | |
875 | return error; | | 875 | return error; |
876 | } | | 876 | } |
877 | | | 877 | |
878 | /* | | 878 | /* |
879 | * compare two prop_pair which is assumed to have same proposal number. | | 879 | * compare two prop_pair which is assumed to have same proposal number. |
880 | * the case of bundle or single SA, NOT multi transforms. | | 880 | * the case of bundle or single SA, NOT multi transforms. |
881 | * a: a proposal that is multi protocols and single transform, usually replyed. | | 881 | * a: a proposal that is multi protocols and single transform, usually replyed. |
882 | * b: a proposal that is multi protocols and multi transform, usually sent. | | 882 | * b: a proposal that is multi protocols and multi transform, usually sent. |
883 | * NOTE: this function is for initiator. | | 883 | * NOTE: this function is for initiator. |
884 | * OUT | | 884 | * OUT |
885 | * 0: equal | | 885 | * 0: equal |
886 | * 1: not equal | | 886 | * 1: not equal |
887 | * XXX cannot understand the comment! | | 887 | * XXX cannot understand the comment! |
888 | */ | | 888 | */ |
889 | static int | | 889 | static int |
890 | cmp_aproppair_i(a, b) | | 890 | cmp_aproppair_i(a, b) |
891 | struct prop_pair *a, *b; | | 891 | struct prop_pair *a, *b; |
892 | { | | 892 | { |
893 | struct prop_pair *p, *q, *r; | | 893 | struct prop_pair *p, *q, *r; |
894 | int len; | | 894 | int len; |
895 | | | 895 | |
896 | for (p = a, q = b; p && q; p = p->next, q = q->next) { | | 896 | for (p = a, q = b; p && q; p = p->next, q = q->next) { |
897 | for (r = q; r; r = r->tnext) { | | 897 | for (r = q; r; r = r->tnext) { |
898 | /* compare trns */ | | 898 | /* compare trns */ |
899 | if (p->trns->t_no == r->trns->t_no) | | 899 | if (p->trns->t_no == r->trns->t_no) |
900 | break; | | 900 | break; |
901 | } | | 901 | } |
902 | if (!r) { | | 902 | if (!r) { |
903 | /* no suitable transform found */ | | 903 | /* no suitable transform found */ |
904 | plog(LLV_ERROR, LOCATION, NULL, | | 904 | plog(LLV_ERROR, LOCATION, NULL, |
905 | "no suitable transform found.\n"); | | 905 | "no suitable transform found.\n"); |
906 | return -1; | | 906 | return -1; |
907 | } | | 907 | } |
908 | | | 908 | |
909 | /* compare prop */ | | 909 | /* compare prop */ |
910 | if (p->prop->p_no != r->prop->p_no) { | | 910 | if (p->prop->p_no != r->prop->p_no) { |
911 | plog(LLV_WARNING, LOCATION, NULL, | | 911 | plog(LLV_WARNING, LOCATION, NULL, |
912 | "proposal #%d mismatched, " | | 912 | "proposal #%d mismatched, " |
913 | "expected #%d.\n", | | 913 | "expected #%d.\n", |
914 | r->prop->p_no, p->prop->p_no); | | 914 | r->prop->p_no, p->prop->p_no); |
915 | /*FALLTHROUGH*/ | | 915 | /*FALLTHROUGH*/ |
916 | } | | 916 | } |
917 | | | 917 | |
918 | if (p->prop->proto_id != r->prop->proto_id) { | | 918 | if (p->prop->proto_id != r->prop->proto_id) { |
919 | plog(LLV_ERROR, LOCATION, NULL, | | 919 | plog(LLV_ERROR, LOCATION, NULL, |
920 | "proto_id mismathed: my:%d peer:%d\n", | | 920 | "proto_id mismathed: my:%d peer:%d\n", |
921 | r->prop->proto_id, p->prop->proto_id); | | 921 | r->prop->proto_id, p->prop->proto_id); |
922 | return -1; | | 922 | return -1; |
923 | } | | 923 | } |
924 | | | 924 | |
925 | if (p->prop->spi_size != r->prop->spi_size) { | | 925 | if (p->prop->spi_size != r->prop->spi_size) { |
926 | plog(LLV_ERROR, LOCATION, NULL, | | 926 | plog(LLV_ERROR, LOCATION, NULL, |
927 | "invalid spi size: %d.\n", | | 927 | "invalid spi size: %d.\n", |
928 | p->prop->spi_size); | | 928 | p->prop->spi_size); |
929 | return -1; | | 929 | return -1; |
930 | } | | 930 | } |
931 | | | 931 | |
932 | /* check #of transforms */ | | 932 | /* check #of transforms */ |
933 | if (p->prop->num_t != 1) { | | 933 | if (p->prop->num_t != 1) { |
934 | plog(LLV_WARNING, LOCATION, NULL, | | 934 | plog(LLV_WARNING, LOCATION, NULL, |
935 | "#of transform is %d, " | | 935 | "#of transform is %d, " |
936 | "but expected 1.\n", p->prop->num_t); | | 936 | "but expected 1.\n", p->prop->num_t); |
937 | /*FALLTHROUGH*/ | | 937 | /*FALLTHROUGH*/ |
938 | } | | 938 | } |
939 | | | 939 | |
940 | if (p->trns->t_id != r->trns->t_id) { | | 940 | if (p->trns->t_id != r->trns->t_id) { |
941 | plog(LLV_WARNING, LOCATION, NULL, | | 941 | plog(LLV_WARNING, LOCATION, NULL, |
942 | "transform number has been modified.\n"); | | 942 | "transform number has been modified.\n"); |
943 | /*FALLTHROUGH*/ | | 943 | /*FALLTHROUGH*/ |
944 | } | | 944 | } |
945 | if (p->trns->reserved != r->trns->reserved) { | | 945 | if (p->trns->reserved != r->trns->reserved) { |
946 | plog(LLV_WARNING, LOCATION, NULL, | | 946 | plog(LLV_WARNING, LOCATION, NULL, |
947 | "reserved field should be zero.\n"); | | 947 | "reserved field should be zero.\n"); |
948 | /*FALLTHROUGH*/ | | 948 | /*FALLTHROUGH*/ |
949 | } | | 949 | } |
950 | | | 950 | |
951 | /* compare attribute */ | | 951 | /* compare attribute */ |
952 | len = ntohs(r->trns->h.len) - sizeof(*p->trns); | | 952 | len = ntohs(r->trns->h.len) - sizeof(*p->trns); |
953 | if (memcmp(p->trns + 1, r->trns + 1, len) != 0) { | | 953 | if (memcmp(p->trns + 1, r->trns + 1, len) != 0) { |
954 | plog(LLV_WARNING, LOCATION, NULL, | | 954 | plog(LLV_WARNING, LOCATION, NULL, |
955 | "attribute has been modified.\n"); | | 955 | "attribute has been modified.\n"); |
956 | /*FALLTHROUGH*/ | | 956 | /*FALLTHROUGH*/ |
957 | } | | 957 | } |
958 | } | | 958 | } |
959 | if ((p && !q) || (!p && q)) { | | 959 | if ((p && !q) || (!p && q)) { |
960 | /* # of protocols mismatched */ | | 960 | /* # of protocols mismatched */ |
961 | plog(LLV_ERROR, LOCATION, NULL, | | 961 | plog(LLV_ERROR, LOCATION, NULL, |
962 | "#of protocols mismatched.\n"); | | 962 | "#of protocols mismatched.\n"); |
963 | return -1; | | 963 | return -1; |
964 | } | | 964 | } |
965 | | | 965 | |
966 | return 0; | | 966 | return 0; |
967 | } | | 967 | } |
968 | | | 968 | |
969 | /* | | 969 | /* |
970 | * acceptable check for policy configuration. | | 970 | * acceptable check for policy configuration. |
971 | * return a new SA payload to be reply to peer. | | 971 | * return a new SA payload to be reply to peer. |
972 | */ | | 972 | */ |
973 | static struct prop_pair * | | 973 | static struct prop_pair * |
974 | get_ph2approval(iph2, pair) | | 974 | get_ph2approval(iph2, pair) |
975 | struct ph2handle *iph2; | | 975 | struct ph2handle *iph2; |
976 | struct prop_pair **pair; | | 976 | struct prop_pair **pair; |
977 | { | | 977 | { |
978 | struct prop_pair *ret; | | 978 | struct prop_pair *ret; |
979 | int i; | | 979 | int i; |
980 | | | 980 | |
981 | iph2->approval = NULL; | | 981 | iph2->approval = NULL; |
982 | | | 982 | |
983 | plog(LLV_DEBUG, LOCATION, NULL, | | 983 | plog(LLV_DEBUG, LOCATION, NULL, |
984 | "begin compare proposals.\n"); | | 984 | "begin compare proposals.\n"); |
985 | | | 985 | |
986 | for (i = 0; i < MAXPROPPAIRLEN; i++) { | | 986 | for (i = 0; i < MAXPROPPAIRLEN; i++) { |
987 | if (pair[i] == NULL) | | 987 | if (pair[i] == NULL) |
988 | continue; | | 988 | continue; |
989 | plog(LLV_DEBUG, LOCATION, NULL, | | 989 | plog(LLV_DEBUG, LOCATION, NULL, |
990 | "pair[%d]: %p\n", i, pair[i]); | | 990 | "pair[%d]: %p\n", i, pair[i]); |
991 | print_proppair(LLV_DEBUG, pair[i]);; | | 991 | print_proppair(LLV_DEBUG, pair[i]);; |
992 | | | 992 | |
993 | /* compare proposal and select one */ | | 993 | /* compare proposal and select one */ |
994 | ret = get_ph2approvalx(iph2, pair[i]); | | 994 | ret = get_ph2approvalx(iph2, pair[i]); |
995 | if (ret != NULL) { | | 995 | if (ret != NULL) { |
996 | /* found */ | | 996 | /* found */ |
997 | return ret; | | 997 | return ret; |
998 | } | | 998 | } |
999 | } | | 999 | } |
1000 | | | 1000 | |
1001 | plog(LLV_ERROR, LOCATION, NULL, "no suitable policy found.\n"); | | 1001 | plog(LLV_ERROR, LOCATION, NULL, "no suitable policy found.\n"); |
1002 | | | 1002 | |
1003 | return NULL; | | 1003 | return NULL; |
1004 | } | | 1004 | } |
1005 | | | 1005 | |
1006 | /* | | 1006 | /* |
1007 | * compare my proposal and peers just one proposal. | | 1007 | * compare my proposal and peers just one proposal. |
1008 | * set a approval. | | 1008 | * set a approval. |
1009 | */ | | 1009 | */ |
1010 | static struct prop_pair * | | 1010 | static struct prop_pair * |
1011 | get_ph2approvalx(iph2, pp) | | 1011 | get_ph2approvalx(iph2, pp) |
1012 | struct ph2handle *iph2; | | 1012 | struct ph2handle *iph2; |
1013 | struct prop_pair *pp; | | 1013 | struct prop_pair *pp; |
1014 | { | | 1014 | { |
1015 | struct prop_pair *ret = NULL; | | 1015 | struct prop_pair *ret = NULL; |
1016 | struct saprop *pr0, *pr = NULL; | | 1016 | struct saprop *pr0, *pr = NULL; |
1017 | struct saprop *q1, *q2; | | 1017 | struct saprop *q1, *q2; |
1018 | | | 1018 | |
1019 | pr0 = aproppair2saprop(pp); | | 1019 | pr0 = aproppair2saprop(pp); |
1020 | if (pr0 == NULL) | | 1020 | if (pr0 == NULL) |
1021 | return NULL; | | 1021 | return NULL; |
1022 | | | 1022 | |
1023 | for (q1 = pr0; q1; q1 = q1->next) { | | 1023 | for (q1 = pr0; q1; q1 = q1->next) { |
1024 | for (q2 = iph2->proposal; q2; q2 = q2->next) { | | 1024 | for (q2 = iph2->proposal; q2; q2 = q2->next) { |
1025 | plog(LLV_DEBUG, LOCATION, NULL, | | 1025 | plog(LLV_DEBUG, LOCATION, NULL, |
1026 | "peer's single bundle:\n"); | | 1026 | "peer's single bundle:\n"); |
1027 | printsaprop0(LLV_DEBUG, q1); | | 1027 | printsaprop0(LLV_DEBUG, q1); |
1028 | plog(LLV_DEBUG, LOCATION, NULL, | | 1028 | plog(LLV_DEBUG, LOCATION, NULL, |
1029 | "my single bundle:\n"); | | 1029 | "my single bundle:\n"); |
1030 | printsaprop0(LLV_DEBUG, q2); | | 1030 | printsaprop0(LLV_DEBUG, q2); |
1031 | | | 1031 | |
1032 | pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side); | | 1032 | pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side); |
1033 | if (pr != NULL) | | 1033 | if (pr != NULL) |
1034 | goto found; | | 1034 | goto found; |
1035 | | | 1035 | |
1036 | plog(LLV_ERROR, LOCATION, NULL, | | 1036 | plog(LLV_ERROR, LOCATION, NULL, |
1037 | "not matched\n"); | | 1037 | "not matched\n"); |
1038 | } | | 1038 | } |
1039 | } | | 1039 | } |
1040 | /* no proposal matching */ | | 1040 | /* no proposal matching */ |
1041 | err: | | 1041 | err: |
1042 | flushsaprop(pr0); | | 1042 | flushsaprop(pr0); |
1043 | return NULL; | | 1043 | return NULL; |
1044 | | | 1044 | |
1045 | found: | | 1045 | found: |
1046 | flushsaprop(pr0); | | 1046 | flushsaprop(pr0); |
1047 | plog(LLV_DEBUG, LOCATION, NULL, "matched\n"); | | 1047 | plog(LLV_DEBUG, LOCATION, NULL, "matched\n"); |
1048 | iph2->approval = pr; | | 1048 | iph2->approval = pr; |
1049 | | | 1049 | |
1050 | { | | 1050 | { |
1051 | struct saproto *sp; | | 1051 | struct saproto *sp; |
1052 | struct prop_pair *p, *x; | | 1052 | struct prop_pair *p, *x; |
1053 | struct prop_pair *n = NULL; | | 1053 | struct prop_pair *n = NULL; |
1054 | | | 1054 | |
1055 | ret = NULL; | | 1055 | ret = NULL; |
1056 | | | 1056 | |
1057 | for (p = pp; p; p = p->next) { | | 1057 | for (p = pp; p; p = p->next) { |
1058 | /* | | 1058 | /* |
1059 | * find a proposal with matching proto_id. | | 1059 | * find a proposal with matching proto_id. |
1060 | * we have analyzed validity already, in cmpsaprop_alloc(). | | 1060 | * we have analyzed validity already, in cmpsaprop_alloc(). |
1061 | */ | | 1061 | */ |
1062 | for (sp = pr->head; sp; sp = sp->next) { | | 1062 | for (sp = pr->head; sp; sp = sp->next) { |
1063 | if (sp->proto_id == p->prop->proto_id) | | 1063 | if (sp->proto_id == p->prop->proto_id) |
1064 | break; | | 1064 | break; |
1065 | } | | 1065 | } |
1066 | if (!sp) | | 1066 | if (!sp) |
1067 | goto err; | | 1067 | goto err; |
1068 | if (sp->head->next) | | 1068 | if (sp->head->next) |
1069 | goto err; /* XXX */ | | 1069 | goto err; /* XXX */ |
1070 | | | 1070 | |
1071 | for (x = p; x; x = x->tnext) | | 1071 | for (x = p; x; x = x->tnext) |
1072 | if (sp->head->trns_no == x->trns->t_no) | | 1072 | if (sp->head->trns_no == x->trns->t_no) |
1073 | break; | | 1073 | break; |
1074 | if (!x) | | 1074 | if (!x) |
1075 | goto err; /* XXX */ | | 1075 | goto err; /* XXX */ |
1076 | | | 1076 | |
1077 | n = racoon_calloc(1, sizeof(struct prop_pair)); | | 1077 | n = racoon_calloc(1, sizeof(struct prop_pair)); |
1078 | if (n == NULL) { | | 1078 | if (n == NULL) { |
1079 | plog(LLV_ERROR, LOCATION, NULL, | | 1079 | plog(LLV_ERROR, LOCATION, NULL, |
1080 | "failed to get buffer.\n"); | | 1080 | "failed to get buffer.\n"); |
1081 | goto err; | | 1081 | goto err; |
1082 | } | | 1082 | } |
1083 | | | 1083 | |
1084 | n->prop = x->prop; | | 1084 | n->prop = x->prop; |
1085 | n->trns = x->trns; | | 1085 | n->trns = x->trns; |
1086 | | | 1086 | |
1087 | /* need to preserve the order */ | | 1087 | /* need to preserve the order */ |
1088 | for (x = ret; x && x->next; x = x->next) | | 1088 | for (x = ret; x && x->next; x = x->next) |
1089 | ; | | 1089 | ; |
1090 | if (x && x->prop == n->prop) { | | 1090 | if (x && x->prop == n->prop) { |
1091 | for (/*nothing*/; x && x->tnext; x = x->tnext) | | 1091 | for (/*nothing*/; x && x->tnext; x = x->tnext) |
1092 | ; | | 1092 | ; |
1093 | x->tnext = n; | | 1093 | x->tnext = n; |
1094 | } else { | | 1094 | } else { |
1095 | if (x) | | 1095 | if (x) |
1096 | x->next = n; | | 1096 | x->next = n; |
1097 | else { | | 1097 | else { |
1098 | ret = n; | | 1098 | ret = n; |
1099 | } | | 1099 | } |
1100 | } | | 1100 | } |
1101 | | | 1101 | |
1102 | /* #of transforms should be updated ? */ | | 1102 | /* #of transforms should be updated ? */ |
1103 | } | | 1103 | } |
1104 | } | | 1104 | } |
1105 | | | 1105 | |
1106 | return ret; | | 1106 | return ret; |
1107 | } | | 1107 | } |
1108 | | | 1108 | |
1109 | void | | 1109 | void |
1110 | free_proppair(pair) | | 1110 | free_proppair(pair) |
1111 | struct prop_pair **pair; | | 1111 | struct prop_pair **pair; |
1112 | { | | 1112 | { |
1113 | int i; | | 1113 | int i; |
1114 | | | 1114 | |
1115 | for (i = 0; i < MAXPROPPAIRLEN; i++) { | | 1115 | for (i = 0; i < MAXPROPPAIRLEN; i++) { |
1116 | free_proppair0(pair[i]); | | 1116 | free_proppair0(pair[i]); |
1117 | pair[i] = NULL; | | 1117 | pair[i] = NULL; |
1118 | } | | 1118 | } |
1119 | racoon_free(pair); | | 1119 | racoon_free(pair); |
1120 | } | | 1120 | } |
1121 | | | 1121 | |
1122 | static void | | 1122 | static void |
1123 | free_proppair0(pair) | | 1123 | free_proppair0(pair) |
1124 | struct prop_pair *pair; | | 1124 | struct prop_pair *pair; |
1125 | { | | 1125 | { |
1126 | struct prop_pair *p, *q, *r, *s; | | 1126 | struct prop_pair *p, *q, *r, *s; |
1127 | | | 1127 | |
1128 | p = pair; | | 1128 | p = pair; |
1129 | while (p) { | | 1129 | while (p) { |
1130 | q = p->next; | | 1130 | q = p->next; |
1131 | r = p; | | 1131 | r = p; |
1132 | while (r) { | | 1132 | while (r) { |
1133 | s = r->tnext; | | 1133 | s = r->tnext; |
1134 | racoon_free(r); | | 1134 | racoon_free(r); |
1135 | r = s; | | 1135 | r = s; |
1136 | } | | 1136 | } |
1137 | p = q; | | 1137 | p = q; |
1138 | } | | 1138 | } |
1139 | } | | 1139 | } |
1140 | | | 1140 | |
1141 | /* | | 1141 | /* |
1142 | * get proposal pairs from SA payload. | | 1142 | * get proposal pairs from SA payload. |
1143 | * tiny check for proposal payload. | | 1143 | * tiny check for proposal payload. |
1144 | */ | | 1144 | */ |
1145 | static struct prop_pair ** | | 1145 | static struct prop_pair ** |
1146 | get_proppair_and_doi_sit(sa, mode, doitype, sittype) | | 1146 | get_proppair_and_doi_sit(sa, mode, doitype, sittype) |
1147 | vchar_t *sa; | | 1147 | vchar_t *sa; |
1148 | int mode; | | 1148 | int mode; |
1149 | u_int32_t *doitype, *sittype; | | 1149 | u_int32_t *doitype, *sittype; |
1150 | { | | 1150 | { |
1151 | struct prop_pair **pair = NULL; | | 1151 | struct prop_pair **pair = NULL; |
1152 | int num_p = 0; /* number of proposal for use */ | | 1152 | int num_p = 0; /* number of proposal for use */ |
1153 | int tlen; | | 1153 | int tlen; |
1154 | caddr_t bp; | | 1154 | caddr_t bp; |
1155 | int i; | | 1155 | int i; |
1156 | struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v; | | 1156 | struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v; |
1157 | | | 1157 | |
1158 | plog(LLV_DEBUG, LOCATION, NULL, "total SA len=%zu\n", sa->l); | | 1158 | plog(LLV_DEBUG, LOCATION, NULL, "total SA len=%zu\n", sa->l); |
1159 | plogdump(LLV_DEBUG, sa->v, sa->l); | | 1159 | plogdump(LLV_DEBUG, sa->v, sa->l); |
1160 | | | 1160 | |
1161 | /* check SA payload size */ | | 1161 | /* check SA payload size */ |
1162 | if (sa->l < sizeof(*sab)) { | | 1162 | if (sa->l < sizeof(*sab)) { |
1163 | plog(LLV_ERROR, LOCATION, NULL, | | 1163 | plog(LLV_ERROR, LOCATION, NULL, |
1164 | "Invalid SA length = %zu.\n", sa->l); | | 1164 | "Invalid SA length = %zu.\n", sa->l); |
1165 | goto bad; | | 1165 | goto bad; |
1166 | } | | 1166 | } |
1167 | | | 1167 | |
1168 | /* check DOI */ | | 1168 | /* check DOI */ |
1169 | if (check_doi(ntohl(sab->doi)) < 0) | | 1169 | if (check_doi(ntohl(sab->doi)) < 0) |
1170 | goto bad; | | 1170 | goto bad; |
1171 | if (doitype != NULL) | | 1171 | if (doitype != NULL) |
1172 | *doitype = ntohl(sab->doi); | | 1172 | *doitype = ntohl(sab->doi); |
1173 | | | 1173 | |
1174 | /* check SITUATION */ | | 1174 | /* check SITUATION */ |
1175 | if (check_situation(ntohl(sab->sit)) < 0) | | 1175 | if (check_situation(ntohl(sab->sit)) < 0) |
1176 | goto bad; | | 1176 | goto bad; |
1177 | if (sittype != NULL) | | 1177 | if (sittype != NULL) |
1178 | *sittype = ntohl(sab->sit); | | 1178 | *sittype = ntohl(sab->sit); |
1179 | | | 1179 | |
1180 | pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair)); | | 1180 | pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair)); |
1181 | if (pair == NULL) { | | 1181 | if (pair == NULL) { |
1182 | plog(LLV_ERROR, LOCATION, NULL, | | 1182 | plog(LLV_ERROR, LOCATION, NULL, |
1183 | "failed to get buffer.\n"); | | 1183 | "failed to get buffer.\n"); |
1184 | goto bad; | | 1184 | goto bad; |
1185 | } | | 1185 | } |
1186 | memset(pair, 0, sizeof(pair)); | | | |
1187 | | | 1186 | |
1188 | bp = (caddr_t)(sab + 1); | | 1187 | bp = (caddr_t)(sab + 1); |
1189 | tlen = sa->l - sizeof(*sab); | | 1188 | tlen = sa->l - sizeof(*sab); |
1190 | | | 1189 | |
1191 | { | | 1190 | { |
1192 | struct isakmp_pl_p *prop; | | 1191 | struct isakmp_pl_p *prop; |
1193 | int proplen; | | 1192 | int proplen; |
1194 | vchar_t *pbuf = NULL; | | 1193 | vchar_t *pbuf = NULL; |
1195 | struct isakmp_parse_t *pa; | | 1194 | struct isakmp_parse_t *pa; |
1196 | | | 1195 | |
1197 | pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen); | | 1196 | pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen); |
1198 | if (pbuf == NULL) | | 1197 | if (pbuf == NULL) |
1199 | goto bad; | | 1198 | goto bad; |
1200 | | | 1199 | |
1201 | for (pa = (struct isakmp_parse_t *)pbuf->v; | | 1200 | for (pa = (struct isakmp_parse_t *)pbuf->v; |
1202 | pa->type != ISAKMP_NPTYPE_NONE; | | 1201 | pa->type != ISAKMP_NPTYPE_NONE; |
1203 | pa++) { | | 1202 | pa++) { |
1204 | /* check the value of next payload */ | | 1203 | /* check the value of next payload */ |
1205 | if (pa->type != ISAKMP_NPTYPE_P) { | | 1204 | if (pa->type != ISAKMP_NPTYPE_P) { |
1206 | plog(LLV_ERROR, LOCATION, NULL, | | 1205 | plog(LLV_ERROR, LOCATION, NULL, |
1207 | "Invalid payload type=%u\n", pa->type); | | 1206 | "Invalid payload type=%u\n", pa->type); |
1208 | vfree(pbuf); | | 1207 | vfree(pbuf); |
1209 | goto bad; | | 1208 | goto bad; |
1210 | } | | 1209 | } |
1211 | | | 1210 | |
1212 | prop = (struct isakmp_pl_p *)pa->ptr; | | 1211 | prop = (struct isakmp_pl_p *)pa->ptr; |
1213 | proplen = pa->len; | | 1212 | proplen = pa->len; |
1214 | | | 1213 | |
1215 | plog(LLV_DEBUG, LOCATION, NULL, | | 1214 | plog(LLV_DEBUG, LOCATION, NULL, |
1216 | "proposal #%u len=%d\n", prop->p_no, proplen); | | 1215 | "proposal #%u len=%d\n", prop->p_no, proplen); |
1217 | | | 1216 | |
1218 | if (proplen == 0) { | | 1217 | if (proplen == 0) { |
1219 | plog(LLV_ERROR, LOCATION, NULL, | | 1218 | plog(LLV_ERROR, LOCATION, NULL, |
1220 | "invalid proposal with length %d\n", proplen); | | 1219 | "invalid proposal with length %d\n", proplen); |
1221 | vfree(pbuf); | | 1220 | vfree(pbuf); |
1222 | goto bad; | | 1221 | goto bad; |
1223 | } | | 1222 | } |
1224 | | | 1223 | |
1225 | /* check Protocol ID */ | | 1224 | /* check Protocol ID */ |
1226 | if (!check_protocol[mode]) { | | 1225 | if (!check_protocol[mode]) { |
1227 | plog(LLV_ERROR, LOCATION, NULL, | | 1226 | plog(LLV_ERROR, LOCATION, NULL, |
1228 | "unsupported mode %d\n", mode); | | 1227 | "unsupported mode %d\n", mode); |
1229 | continue; | | 1228 | continue; |
1230 | } | | 1229 | } |
1231 | | | 1230 | |
1232 | if (check_protocol[mode](prop->proto_id) < 0) | | 1231 | if (check_protocol[mode](prop->proto_id) < 0) |
1233 | continue; | | 1232 | continue; |
1234 | | | 1233 | |
1235 | /* check SPI length when IKE. */ | | 1234 | /* check SPI length when IKE. */ |
1236 | if (check_spi_size(prop->proto_id, prop->spi_size) < 0) | | 1235 | if (check_spi_size(prop->proto_id, prop->spi_size) < 0) |
1237 | continue; | | 1236 | continue; |
1238 | | | 1237 | |
1239 | /* get transform */ | | 1238 | /* get transform */ |
1240 | if (get_transform(prop, pair, &num_p) < 0) { | | 1239 | if (get_transform(prop, pair, &num_p) < 0) { |
1241 | vfree(pbuf); | | 1240 | vfree(pbuf); |
1242 | goto bad; | | 1241 | goto bad; |
1243 | } | | 1242 | } |
1244 | } | | 1243 | } |
1245 | vfree(pbuf); | | 1244 | vfree(pbuf); |
1246 | pbuf = NULL; | | 1245 | pbuf = NULL; |
1247 | } | | 1246 | } |
1248 | | | 1247 | |
1249 | { | | 1248 | { |
1250 | int notrans, nprop; | | 1249 | int notrans, nprop; |
1251 | struct prop_pair *p, *q; | | 1250 | struct prop_pair *p, *q; |
1252 | | | 1251 | |
1253 | /* check for proposals with no transforms */ | | 1252 | /* check for proposals with no transforms */ |
1254 | for (i = 0; i < MAXPROPPAIRLEN; i++) { | | 1253 | for (i = 0; i < MAXPROPPAIRLEN; i++) { |
1255 | if (!pair[i]) | | 1254 | if (!pair[i]) |
1256 | continue; | | 1255 | continue; |
1257 | | | 1256 | |
1258 | plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i); | | 1257 | plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i); |
1259 | print_proppair(LLV_DEBUG, pair[i]); | | 1258 | print_proppair(LLV_DEBUG, pair[i]); |
1260 | | | 1259 | |
1261 | notrans = nprop = 0; | | 1260 | notrans = nprop = 0; |
1262 | for (p = pair[i]; p; p = p->next) { | | 1261 | for (p = pair[i]; p; p = p->next) { |
1263 | if (p->trns == NULL) { | | 1262 | if (p->trns == NULL) { |
1264 | notrans++; | | 1263 | notrans++; |
1265 | break; | | 1264 | break; |
1266 | } | | 1265 | } |
1267 | for (q = p; q; q = q->tnext) | | 1266 | for (q = p; q; q = q->tnext) |
1268 | nprop++; | | 1267 | nprop++; |
1269 | } | | 1268 | } |
1270 | | | 1269 | |
1271 | #if 0 | | 1270 | #if 0 |
1272 | /* | | 1271 | /* |
1273 | * XXX at this moment, we cannot accept proposal group | | 1272 | * XXX at this moment, we cannot accept proposal group |
1274 | * with multiple proposals. this should be fixed. | | 1273 | * with multiple proposals. this should be fixed. |
1275 | */ | | 1274 | */ |
1276 | if (pair[i]->next) { | | 1275 | if (pair[i]->next) { |
1277 | plog(LLV_WARNING, LOCATION, NULL, | | 1276 | plog(LLV_WARNING, LOCATION, NULL, |
1278 | "proposal #%u ignored " | | 1277 | "proposal #%u ignored " |
1279 | "(multiple proposal not supported)\n", | | 1278 | "(multiple proposal not supported)\n", |
1280 | pair[i]->prop->p_no); | | 1279 | pair[i]->prop->p_no); |
1281 | notrans++; | | 1280 | notrans++; |
1282 | } | | 1281 | } |
1283 | #endif | | 1282 | #endif |
1284 | | | 1283 | |
1285 | if (notrans) { | | 1284 | if (notrans) { |
1286 | for (p = pair[i]; p; p = q) { | | 1285 | for (p = pair[i]; p; p = q) { |
1287 | q = p->next; | | 1286 | q = p->next; |
1288 | racoon_free(p); | | 1287 | racoon_free(p); |
1289 | } | | 1288 | } |
1290 | pair[i] = NULL; | | 1289 | pair[i] = NULL; |
1291 | num_p--; | | 1290 | num_p--; |
1292 | } else { | | 1291 | } else { |
1293 | plog(LLV_DEBUG, LOCATION, NULL, | | 1292 | plog(LLV_DEBUG, LOCATION, NULL, |
1294 | "proposal #%u: %d transform\n", | | 1293 | "proposal #%u: %d transform\n", |
1295 | pair[i]->prop->p_no, nprop); | | 1294 | pair[i]->prop->p_no, nprop); |
1296 | } | | 1295 | } |
1297 | } | | 1296 | } |
1298 | } | | 1297 | } |
1299 | | | 1298 | |
1300 | /* bark if no proposal is found. */ | | 1299 | /* bark if no proposal is found. */ |
1301 | if (num_p <= 0) { | | 1300 | if (num_p <= 0) { |
1302 | plog(LLV_ERROR, LOCATION, NULL, | | 1301 | plog(LLV_ERROR, LOCATION, NULL, |
1303 | "no Proposal found.\n"); | | 1302 | "no Proposal found.\n"); |
1304 | goto bad; | | 1303 | goto bad; |
1305 | } | | 1304 | } |
1306 | | | 1305 | |
1307 | return pair; | | 1306 | return pair; |
1308 | bad: | | 1307 | bad: |
1309 | if (pair != NULL) | | 1308 | if (pair != NULL) |
1310 | racoon_free(pair); | | 1309 | racoon_free(pair); |
1311 | return NULL; | | 1310 | return NULL; |
1312 | } | | 1311 | } |
1313 | | | 1312 | |
1314 | struct prop_pair ** | | 1313 | struct prop_pair ** |
1315 | get_proppair(sa, mode) | | 1314 | get_proppair(sa, mode) |
1316 | vchar_t *sa; | | 1315 | vchar_t *sa; |
1317 | int mode; | | 1316 | int mode; |
1318 | { | | 1317 | { |
1319 | return get_proppair_and_doi_sit(sa, mode, NULL, NULL); | | 1318 | return get_proppair_and_doi_sit(sa, mode, NULL, NULL); |
1320 | } | | 1319 | } |
1321 | | | 1320 | |
1322 | | | 1321 | |
1323 | /* | | 1322 | /* |
1324 | * check transform payload. | | 1323 | * check transform payload. |
1325 | * OUT: | | 1324 | * OUT: |
1326 | * positive: return the pointer to the payload of valid transform. | | 1325 | * positive: return the pointer to the payload of valid transform. |
1327 | * 0 : No valid transform found. | | 1326 | * 0 : No valid transform found. |
1328 | */ | | 1327 | */ |
1329 | static int | | 1328 | static int |
1330 | get_transform(prop, pair, num_p) | | 1329 | get_transform(prop, pair, num_p) |
1331 | struct isakmp_pl_p *prop; | | 1330 | struct isakmp_pl_p *prop; |
1332 | struct prop_pair **pair; | | 1331 | struct prop_pair **pair; |
1333 | int *num_p; | | 1332 | int *num_p; |
1334 | { | | 1333 | { |
1335 | int tlen; /* total length of all transform in a proposal */ | | 1334 | int tlen; /* total length of all transform in a proposal */ |
1336 | caddr_t bp; | | 1335 | caddr_t bp; |
1337 | struct isakmp_pl_t *trns; | | 1336 | struct isakmp_pl_t *trns; |
1338 | int trnslen; | | 1337 | int trnslen; |
1339 | vchar_t *pbuf = NULL; | | 1338 | vchar_t *pbuf = NULL; |
1340 | struct isakmp_parse_t *pa; | | 1339 | struct isakmp_parse_t *pa; |
1341 | struct prop_pair *p = NULL, *q; | | 1340 | struct prop_pair *p = NULL, *q; |
1342 | int num_t; | | 1341 | int num_t; |
1343 | | | 1342 | |
1344 | bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size; | | 1343 | bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size; |
1345 | tlen = ntohs(prop->h.len) | | 1344 | tlen = ntohs(prop->h.len) |
1346 | - (sizeof(struct isakmp_pl_p) + prop->spi_size); | | 1345 | - (sizeof(struct isakmp_pl_p) + prop->spi_size); |
1347 | pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen); | | 1346 | pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen); |
1348 | if (pbuf == NULL) | | 1347 | if (pbuf == NULL) |
1349 | return -1; | | 1348 | return -1; |
1350 | | | 1349 | |
1351 | /* check and get transform for use */ | | 1350 | /* check and get transform for use */ |
1352 | num_t = 0; | | 1351 | num_t = 0; |
1353 | for (pa = (struct isakmp_parse_t *)pbuf->v; | | 1352 | for (pa = (struct isakmp_parse_t *)pbuf->v; |
1354 | pa->type != ISAKMP_NPTYPE_NONE; | | 1353 | pa->type != ISAKMP_NPTYPE_NONE; |
1355 | pa++) { | | 1354 | pa++) { |
1356 | | | 1355 | |
1357 | num_t++; | | 1356 | num_t++; |
1358 | | | 1357 | |
1359 | /* check the value of next payload */ | | 1358 | /* check the value of next payload */ |
1360 | if (pa->type != ISAKMP_NPTYPE_T) { | | 1359 | if (pa->type != ISAKMP_NPTYPE_T) { |
1361 | plog(LLV_ERROR, LOCATION, NULL, | | 1360 | plog(LLV_ERROR, LOCATION, NULL, |
1362 | "Invalid payload type=%u\n", pa->type); | | 1361 | "Invalid payload type=%u\n", pa->type); |
1363 | break; | | 1362 | break; |
1364 | } | | 1363 | } |
1365 | | | 1364 | |
1366 | trns = (struct isakmp_pl_t *)pa->ptr; | | 1365 | trns = (struct isakmp_pl_t *)pa->ptr; |
1367 | trnslen = pa->len; | | 1366 | trnslen = pa->len; |
1368 | | | 1367 | |
1369 | plog(LLV_DEBUG, LOCATION, NULL, | | 1368 | plog(LLV_DEBUG, LOCATION, NULL, |
1370 | "transform #%u len=%u\n", trns->t_no, trnslen); | | 1369 | "transform #%u len=%u\n", trns->t_no, trnslen); |
1371 | | | 1370 | |
1372 | /* check transform ID */ | | 1371 | /* check transform ID */ |
1373 | if (prop->proto_id >= ARRAYLEN(check_transform)) { | | 1372 | if (prop->proto_id >= ARRAYLEN(check_transform)) { |
1374 | plog(LLV_WARNING, LOCATION, NULL, | | 1373 | plog(LLV_WARNING, LOCATION, NULL, |
1375 | "unsupported proto_id %u\n", | | 1374 | "unsupported proto_id %u\n", |
1376 | prop->proto_id); | | 1375 | prop->proto_id); |
1377 | continue; | | 1376 | continue; |
1378 | } | | 1377 | } |
1379 | if (prop->proto_id >= ARRAYLEN(check_attributes)) { | | 1378 | if (prop->proto_id >= ARRAYLEN(check_attributes)) { |
1380 | plog(LLV_WARNING, LOCATION, NULL, | | 1379 | plog(LLV_WARNING, LOCATION, NULL, |
1381 | "unsupported proto_id %u\n", | | 1380 | "unsupported proto_id %u\n", |
1382 | prop->proto_id); | | 1381 | prop->proto_id); |
1383 | continue; | | 1382 | continue; |
1384 | } | | 1383 | } |
1385 | | | 1384 | |
1386 | if (!check_transform[prop->proto_id] | | 1385 | if (!check_transform[prop->proto_id] |
1387 | || !check_attributes[prop->proto_id]) { | | 1386 | || !check_attributes[prop->proto_id]) { |
1388 | plog(LLV_WARNING, LOCATION, NULL, | | 1387 | plog(LLV_WARNING, LOCATION, NULL, |
1389 | "unsupported proto_id %u\n", | | 1388 | "unsupported proto_id %u\n", |
1390 | prop->proto_id); | | 1389 | prop->proto_id); |
1391 | continue; | | 1390 | continue; |
1392 | } | | 1391 | } |
1393 | if (check_transform[prop->proto_id](trns->t_id) < 0) | | 1392 | if (check_transform[prop->proto_id](trns->t_id) < 0) |
1394 | continue; | | 1393 | continue; |
1395 | | | 1394 | |
1396 | /* check data attributes */ | | 1395 | /* check data attributes */ |
1397 | if (check_attributes[prop->proto_id](trns) != 0) | | 1396 | if (check_attributes[prop->proto_id](trns) != 0) |
1398 | continue; | | 1397 | continue; |
1399 | | | 1398 | |
1400 | p = racoon_calloc(1, sizeof(*p)); | | 1399 | p = racoon_calloc(1, sizeof(*p)); |
1401 | if (p == NULL) { | | 1400 | if (p == NULL) { |
1402 | plog(LLV_ERROR, LOCATION, NULL, | | 1401 | plog(LLV_ERROR, LOCATION, NULL, |
1403 | "failed to get buffer.\n"); | | 1402 | "failed to get buffer.\n"); |
1404 | vfree(pbuf); | | 1403 | vfree(pbuf); |
1405 | return -1; | | 1404 | return -1; |
1406 | } | | 1405 | } |
1407 | p->prop = prop; | | 1406 | p->prop = prop; |
1408 | p->trns = trns; | | 1407 | p->trns = trns; |
1409 | | | 1408 | |
1410 | /* need to preserve the order */ | | 1409 | /* need to preserve the order */ |
1411 | for (q = pair[prop->p_no]; q && q->next; q = q->next) | | 1410 | for (q = pair[prop->p_no]; q && q->next; q = q->next) |
1412 | ; | | 1411 | ; |
1413 | if (q && q->prop == p->prop) { | | 1412 | if (q && q->prop == p->prop) { |
1414 | for (/*nothing*/; q && q->tnext; q = q->tnext) | | 1413 | for (/*nothing*/; q && q->tnext; q = q->tnext) |
1415 | ; | | 1414 | ; |
1416 | q->tnext = p; | | 1415 | q->tnext = p; |
1417 | } else { | | 1416 | } else { |
1418 | if (q) | | 1417 | if (q) |
1419 | q->next = p; | | 1418 | q->next = p; |
1420 | else { | | 1419 | else { |
1421 | pair[prop->p_no] = p; | | 1420 | pair[prop->p_no] = p; |
1422 | (*num_p)++; | | 1421 | (*num_p)++; |
1423 | } | | 1422 | } |
1424 | } | | 1423 | } |
1425 | } | | 1424 | } |
1426 | | | 1425 | |
1427 | vfree(pbuf); | | 1426 | vfree(pbuf); |
1428 | | | 1427 | |
1429 | return 0; | | 1428 | return 0; |
1430 | } | | 1429 | } |
1431 | | | 1430 | |
1432 | /* | | 1431 | /* |
1433 | * make a new SA payload from prop_pair. | | 1432 | * make a new SA payload from prop_pair. |
1434 | * NOTE: this function make spi value clear. | | 1433 | * NOTE: this function make spi value clear. |
1435 | */ | | 1434 | */ |
1436 | vchar_t * | | 1435 | vchar_t * |
1437 | get_sabyproppair(doitype, sittype, pair) | | 1436 | get_sabyproppair(doitype, sittype, pair) |
1438 | u_int32_t doitype, sittype; | | 1437 | u_int32_t doitype, sittype; |
1439 | struct prop_pair *pair; | | 1438 | struct prop_pair *pair; |
1440 | { | | 1439 | { |
1441 | vchar_t *newsa; | | 1440 | vchar_t *newsa; |
1442 | int newtlen; | | 1441 | int newtlen; |
1443 | u_int8_t *np_p = NULL; | | 1442 | u_int8_t *np_p = NULL; |
1444 | struct prop_pair *p; | | 1443 | struct prop_pair *p; |
1445 | int prophlen, trnslen; | | 1444 | int prophlen, trnslen; |
1446 | caddr_t bp; | | 1445 | caddr_t bp; |
1447 | | | 1446 | |
1448 | newtlen = sizeof(struct ipsecdoi_sa_b); | | 1447 | newtlen = sizeof(struct ipsecdoi_sa_b); |
1449 | for (p = pair; p; p = p->next) { | | 1448 | for (p = pair; p; p = p->next) { |
1450 | newtlen += sizeof(struct isakmp_pl_p); | | 1449 | newtlen += sizeof(struct isakmp_pl_p); |
1451 | newtlen += p->prop->spi_size; | | 1450 | newtlen += p->prop->spi_size; |
1452 | newtlen += ntohs(p->trns->h.len); | | 1451 | newtlen += ntohs(p->trns->h.len); |
1453 | } | | 1452 | } |
1454 | | | 1453 | |
1455 | newsa = vmalloc(newtlen); | | 1454 | newsa = vmalloc(newtlen); |
1456 | if (newsa == NULL) { | | 1455 | if (newsa == NULL) { |
1457 | plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n"); | | 1456 | plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n"); |
1458 | return NULL; | | 1457 | return NULL; |
1459 | } | | 1458 | } |
1460 | bp = newsa->v; | | 1459 | bp = newsa->v; |
1461 | | | 1460 | |
1462 | ((struct isakmp_gen *)bp)->len = htons(newtlen); | | 1461 | ((struct isakmp_gen *)bp)->len = htons(newtlen); |
1463 | | | 1462 | |
1464 | /* update some of values in SA header */ | | 1463 | /* update some of values in SA header */ |
1465 | ((struct ipsecdoi_sa_b *)bp)->doi = htonl(doitype); | | 1464 | ((struct ipsecdoi_sa_b *)bp)->doi = htonl(doitype); |
1466 | ((struct ipsecdoi_sa_b *)bp)->sit = htonl(sittype); | | 1465 | ((struct ipsecdoi_sa_b *)bp)->sit = htonl(sittype); |
1467 | bp += sizeof(struct ipsecdoi_sa_b); | | 1466 | bp += sizeof(struct ipsecdoi_sa_b); |
1468 | | | 1467 | |
1469 | /* create proposal payloads */ | | 1468 | /* create proposal payloads */ |
1470 | for (p = pair; p; p = p->next) { | | 1469 | for (p = pair; p; p = p->next) { |
1471 | prophlen = sizeof(struct isakmp_pl_p) | | 1470 | prophlen = sizeof(struct isakmp_pl_p) |
1472 | + p->prop->spi_size; | | 1471 | + p->prop->spi_size; |
1473 | trnslen = ntohs(p->trns->h.len); | | 1472 | trnslen = ntohs(p->trns->h.len); |
1474 | | | 1473 | |
1475 | if (np_p) | | 1474 | if (np_p) |
1476 | *np_p = ISAKMP_NPTYPE_P; | | 1475 | *np_p = ISAKMP_NPTYPE_P; |
1477 | | | 1476 | |
1478 | /* create proposal */ | | 1477 | /* create proposal */ |
1479 | | | 1478 | |
1480 | memcpy(bp, p->prop, prophlen); | | 1479 | memcpy(bp, p->prop, prophlen); |
1481 | ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE; | | 1480 | ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE; |
1482 | ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen); | | 1481 | ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen); |
1483 | ((struct isakmp_pl_p *)bp)->num_t = 1; | | 1482 | ((struct isakmp_pl_p *)bp)->num_t = 1; |
1484 | np_p = &((struct isakmp_pl_p *)bp)->h.np; | | 1483 | np_p = &((struct isakmp_pl_p *)bp)->h.np; |
1485 | memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size); | | 1484 | memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size); |
1486 | bp += prophlen; | | 1485 | bp += prophlen; |
1487 | | | 1486 | |
1488 | /* create transform */ | | 1487 | /* create transform */ |
1489 | memcpy(bp, p->trns, trnslen); | | 1488 | memcpy(bp, p->trns, trnslen); |
1490 | ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE; | | 1489 | ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE; |
1491 | ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen); | | 1490 | ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen); |
1492 | bp += trnslen; | | 1491 | bp += trnslen; |
1493 | } | | 1492 | } |
1494 | | | 1493 | |
1495 | return newsa; | | 1494 | return newsa; |
1496 | } | | 1495 | } |
1497 | | | 1496 | |
1498 | /* | | 1497 | /* |
1499 | * update responder's spi | | 1498 | * update responder's spi |
1500 | */ | | 1499 | */ |
1501 | int | | 1500 | int |
1502 | ipsecdoi_updatespi(iph2) | | 1501 | ipsecdoi_updatespi(iph2) |
1503 | struct ph2handle *iph2; | | 1502 | struct ph2handle *iph2; |
1504 | { | | 1503 | { |
1505 | struct prop_pair **pair, *p; | | 1504 | struct prop_pair **pair, *p; |
1506 | struct saprop *pp; | | 1505 | struct saprop *pp; |
1507 | struct saproto *pr; | | 1506 | struct saproto *pr; |
1508 | int i; | | 1507 | int i; |
1509 | int error = -1; | | 1508 | int error = -1; |
1510 | u_int8_t *spi; | | 1509 | u_int8_t *spi; |
1511 | | | 1510 | |
1512 | pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2); | | 1511 | pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2); |
1513 | if (pair == NULL) | | 1512 | if (pair == NULL) |
1514 | return -1; | | 1513 | return -1; |
1515 | for (i = 0; i < MAXPROPPAIRLEN; i++) { | | 1514 | for (i = 0; i < MAXPROPPAIRLEN; i++) { |
1516 | if (pair[i]) | | 1515 | if (pair[i]) |
1517 | break; | | 1516 | break; |
1518 | } | | 1517 | } |
1519 | if (i == MAXPROPPAIRLEN || pair[i]->tnext) { | | 1518 | if (i == MAXPROPPAIRLEN || pair[i]->tnext) { |
1520 | /* multiple transform must be filtered by selectph2proposal.*/ | | 1519 | /* multiple transform must be filtered by selectph2proposal.*/ |
1521 | goto end; | | 1520 | goto end; |
1522 | } | | 1521 | } |
1523 | | | 1522 | |
1524 | pp = iph2->approval; | | 1523 | pp = iph2->approval; |
1525 | | | 1524 | |
1526 | /* create proposal payloads */ | | 1525 | /* create proposal payloads */ |
1527 | for (p = pair[i]; p; p = p->next) { | | 1526 | for (p = pair[i]; p; p = p->next) { |
1528 | /* | | 1527 | /* |
1529 | * find a proposal/transform with matching proto_id/t_id. | | 1528 | * find a proposal/transform with matching proto_id/t_id. |
1530 | * we have analyzed validity already, in cmpsaprop_alloc(). | | 1529 | * we have analyzed validity already, in cmpsaprop_alloc(). |
1531 | */ | | 1530 | */ |
1532 | for (pr = pp->head; pr; pr = pr->next) { | | 1531 | for (pr = pp->head; pr; pr = pr->next) { |
1533 | if (p->prop->proto_id == pr->proto_id && | | 1532 | if (p->prop->proto_id == pr->proto_id && |
1534 | p->trns->t_id == pr->head->trns_id) { | | 1533 | p->trns->t_id == pr->head->trns_id) { |
1535 | break; | | 1534 | break; |
1536 | } | | 1535 | } |
1537 | } | | 1536 | } |
1538 | if (!pr) | | 1537 | if (!pr) |
1539 | goto end; | | 1538 | goto end; |
1540 | | | 1539 | |
1541 | /* | | 1540 | /* |
1542 | * XXX SPI bits are left-filled, for use with IPComp. | | 1541 | * XXX SPI bits are left-filled, for use with IPComp. |
1543 | * we should be switching to variable-length spi field... | | 1542 | * we should be switching to variable-length spi field... |
1544 | */ | | 1543 | */ |
1545 | spi = (u_int8_t *)&pr->spi; | | 1544 | spi = (u_int8_t *)&pr->spi; |
1546 | spi += sizeof(pr->spi); | | 1545 | spi += sizeof(pr->spi); |
1547 | spi -= pr->spisize; | | 1546 | spi -= pr->spisize; |
1548 | memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize); | | 1547 | memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize); |
1549 | } | | 1548 | } |
1550 | | | 1549 | |
1551 | error = 0; | | 1550 | error = 0; |
1552 | end: | | 1551 | end: |
1553 | free_proppair(pair); | | 1552 | free_proppair(pair); |
1554 | return error; | | 1553 | return error; |
1555 | } | | 1554 | } |
1556 | | | 1555 | |
1557 | /* | | 1556 | /* |
1558 | * make a new SA payload from prop_pair. | | 1557 | * make a new SA payload from prop_pair. |
1559 | */ | | 1558 | */ |
1560 | vchar_t * | | 1559 | vchar_t * |
1561 | get_sabysaprop(pp0, sa0) | | 1560 | get_sabysaprop(pp0, sa0) |
1562 | struct saprop *pp0; | | 1561 | struct saprop *pp0; |
1563 | vchar_t *sa0; | | 1562 | vchar_t *sa0; |
1564 | { | | 1563 | { |
1565 | struct prop_pair **pair = NULL; | | 1564 | struct prop_pair **pair = NULL; |
1566 | vchar_t *newsa = NULL; | | 1565 | vchar_t *newsa = NULL; |
1567 | int newtlen; | | 1566 | int newtlen; |
1568 | u_int8_t *np_p = NULL; | | 1567 | u_int8_t *np_p = NULL; |
1569 | struct prop_pair *p = NULL; | | 1568 | struct prop_pair *p = NULL; |
1570 | struct saprop *pp; | | 1569 | struct saprop *pp; |
1571 | struct saproto *pr; | | 1570 | struct saproto *pr; |
1572 | struct satrns *tr; | | 1571 | struct satrns *tr; |
1573 | int prophlen, trnslen; | | 1572 | int prophlen, trnslen; |
1574 | caddr_t bp; | | 1573 | caddr_t bp; |
1575 | int error = -1; | | 1574 | int error = -1; |
1576 | | | 1575 | |
1577 | /* get proposal pair */ | | 1576 | /* get proposal pair */ |
1578 | pair = get_proppair(sa0, IPSECDOI_TYPE_PH2); | | 1577 | pair = get_proppair(sa0, IPSECDOI_TYPE_PH2); |
1579 | if (pair == NULL) | | 1578 | if (pair == NULL) |
1580 | goto out; | | 1579 | goto out; |
1581 | | | 1580 | |
1582 | newtlen = sizeof(struct ipsecdoi_sa_b); | | 1581 | newtlen = sizeof(struct ipsecdoi_sa_b); |
1583 | for (pp = pp0; pp; pp = pp->next) { | | 1582 | for (pp = pp0; pp; pp = pp->next) { |
1584 | | | 1583 | |
1585 | if (pair[pp->prop_no] == NULL) | | 1584 | if (pair[pp->prop_no] == NULL) |
1586 | goto out; | | 1585 | goto out; |
1587 | | | 1586 | |
1588 | for (pr = pp->head; pr; pr = pr->next) { | | 1587 | for (pr = pp->head; pr; pr = pr->next) { |
1589 | newtlen += (sizeof(struct isakmp_pl_p) | | 1588 | newtlen += (sizeof(struct isakmp_pl_p) |
1590 | + pr->spisize); | | 1589 | + pr->spisize); |
1591 | | | 1590 | |
1592 | for (tr = pr->head; tr; tr = tr->next) { | | 1591 | for (tr = pr->head; tr; tr = tr->next) { |
1593 | for (p = pair[pp->prop_no]; p; p = p->tnext) { | | 1592 | for (p = pair[pp->prop_no]; p; p = p->tnext) { |
1594 | if (tr->trns_no == p->trns->t_no) | | 1593 | if (tr->trns_no == p->trns->t_no) |
1595 | break; | | 1594 | break; |
1596 | } | | 1595 | } |
1597 | if (p == NULL) | | 1596 | if (p == NULL) |
1598 | goto out; | | 1597 | goto out; |
1599 | | | 1598 | |
1600 | newtlen += ntohs(p->trns->h.len); | | 1599 | newtlen += ntohs(p->trns->h.len); |
1601 | } | | 1600 | } |
1602 | } | | 1601 | } |
1603 | } | | 1602 | } |
1604 | | | 1603 | |
1605 | newsa = vmalloc(newtlen); | | 1604 | newsa = vmalloc(newtlen); |
1606 | if (newsa == NULL) { | | 1605 | if (newsa == NULL) { |
1607 | plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n"); | | 1606 | plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n"); |
1608 | goto out; | | 1607 | goto out; |
1609 | } | | 1608 | } |
1610 | bp = newsa->v; | | 1609 | bp = newsa->v; |
1611 | | | 1610 | |
1612 | /* some of values of SA must be updated in the out of this function */ | | 1611 | /* some of values of SA must be updated in the out of this function */ |
1613 | ((struct isakmp_gen *)bp)->len = htons(newtlen); | | 1612 | ((struct isakmp_gen *)bp)->len = htons(newtlen); |
1614 | bp += sizeof(struct ipsecdoi_sa_b); | | 1613 | bp += sizeof(struct ipsecdoi_sa_b); |
1615 | | | 1614 | |
1616 | /* create proposal payloads */ | | 1615 | /* create proposal payloads */ |
1617 | for (pp = pp0; pp; pp = pp->next) { | | 1616 | for (pp = pp0; pp; pp = pp->next) { |
1618 | | | 1617 | |
1619 | for (pr = pp->head; pr; pr = pr->next) { | | 1618 | for (pr = pp->head; pr; pr = pr->next) { |
1620 | prophlen = sizeof(struct isakmp_pl_p) | | 1619 | prophlen = sizeof(struct isakmp_pl_p) |
1621 | + p->prop->spi_size; | | 1620 | + p->prop->spi_size; |
1622 | | | 1621 | |
1623 | for (tr = pr->head; tr; tr = tr->next) { | | 1622 | for (tr = pr->head; tr; tr = tr->next) { |
1624 | for (p = pair[pp->prop_no]; p; p = p->tnext) { | | 1623 | for (p = pair[pp->prop_no]; p; p = p->tnext) { |
1625 | if (tr->trns_no == p->trns->t_no) | | 1624 | if (tr->trns_no == p->trns->t_no) |
1626 | break; | | 1625 | break; |
1627 | } | | 1626 | } |
1628 | if (p == NULL) | | 1627 | if (p == NULL) |
1629 | goto out; | | 1628 | goto out; |
1630 | | | 1629 | |
1631 | trnslen = ntohs(p->trns->h.len); | | 1630 | trnslen = ntohs(p->trns->h.len); |
1632 | | | 1631 | |
1633 | if (np_p) | | 1632 | if (np_p) |
1634 | *np_p = ISAKMP_NPTYPE_P; | | 1633 | *np_p = ISAKMP_NPTYPE_P; |
1635 | | | 1634 | |
1636 | /* create proposal */ | | 1635 | /* create proposal */ |
1637 | | | 1636 | |
1638 | memcpy(bp, p->prop, prophlen); | | 1637 | memcpy(bp, p->prop, prophlen); |
1639 | ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE; | | 1638 | ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE; |
1640 | ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen); | | 1639 | ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen); |
1641 | ((struct isakmp_pl_p *)bp)->num_t = 1; | | 1640 | ((struct isakmp_pl_p *)bp)->num_t = 1; |
1642 | np_p = &((struct isakmp_pl_p *)bp)->h.np; | | 1641 | np_p = &((struct isakmp_pl_p *)bp)->h.np; |
1643 | bp += prophlen; | | 1642 | bp += prophlen; |
1644 | | | 1643 | |
1645 | /* create transform */ | | 1644 | /* create transform */ |
1646 | memcpy(bp, p->trns, trnslen); | | 1645 | memcpy(bp, p->trns, trnslen); |
1647 | ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE; | | 1646 | ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE; |
1648 | ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen); | | 1647 | ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen); |
1649 | bp += trnslen; | | 1648 | bp += trnslen; |
1650 | } | | 1649 | } |
1651 | } | | 1650 | } |
1652 | } | | 1651 | } |
1653 | | | 1652 | |
1654 | error = 0; | | 1653 | error = 0; |
1655 | out: | | 1654 | out: |
1656 | if (pair != NULL) | | 1655 | if (pair != NULL) |
1657 | racoon_free(pair); | | 1656 | racoon_free(pair); |
1658 | | | 1657 | |
1659 | if (error != 0) { | | 1658 | if (error != 0) { |
1660 | if (newsa != NULL) { | | 1659 | if (newsa != NULL) { |
1661 | vfree(newsa); | | 1660 | vfree(newsa); |
1662 | newsa = NULL; | | 1661 | newsa = NULL; |
1663 | } | | 1662 | } |
1664 | } | | 1663 | } |
1665 | | | 1664 | |
1666 | return newsa; | | 1665 | return newsa; |
1667 | } | | 1666 | } |
1668 | | | 1667 | |
1669 | /* | | 1668 | /* |
1670 | * If some error happens then return 0. Although 0 means that lifetime is zero, | | 1669 | * If some error happens then return 0. Although 0 means that lifetime is zero, |
1671 | * such a value should not be accepted. | | 1670 | * such a value should not be accepted. |
1672 | * Also 0 of lifebyte should not be included in a packet although 0 means not | | 1671 | * Also 0 of lifebyte should not be included in a packet although 0 means not |
1673 | * to care of it. | | 1672 | * to care of it. |
1674 | */ | | 1673 | */ |
1675 | static u_int32_t | | 1674 | static u_int32_t |
1676 | ipsecdoi_set_ld(buf) | | 1675 | ipsecdoi_set_ld(buf) |
1677 | vchar_t *buf; | | 1676 | vchar_t *buf; |
1678 | { | | 1677 | { |
1679 | u_int32_t ld; | | 1678 | u_int32_t ld; |
1680 | | | 1679 | |
1681 | if (buf == 0) | | 1680 | if (buf == 0) |
1682 | return 0; | | 1681 | return 0; |
1683 | | | 1682 | |
1684 | switch (buf->l) { | | 1683 | switch (buf->l) { |
1685 | case 2: | | 1684 | case 2: |
1686 | ld = ntohs(*(u_int16_t *)buf->v); | | 1685 | ld = ntohs(*(u_int16_t *)buf->v); |
1687 | break; | | 1686 | break; |
1688 | case 4: | | 1687 | case 4: |
1689 | ld = ntohl(*(u_int32_t *)buf->v); | | 1688 | ld = ntohl(*(u_int32_t *)buf->v); |
1690 | break; | | 1689 | break; |
1691 | default: | | 1690 | default: |
1692 | plog(LLV_ERROR, LOCATION, NULL, | | 1691 | plog(LLV_ERROR, LOCATION, NULL, |
1693 | "length %zu of life duration " | | 1692 | "length %zu of life duration " |
1694 | "isn't supported.\n", buf->l); | | 1693 | "isn't supported.\n", buf->l); |
1695 | return 0; | | 1694 | return 0; |
1696 | } | | 1695 | } |
1697 | | | 1696 | |
1698 | return ld; | | 1697 | return ld; |
1699 | } | | 1698 | } |
1700 | | | 1699 | |
1701 | /* | | 1700 | /* |
1702 | * parse responder-lifetime attributes from payload | | 1701 | * parse responder-lifetime attributes from payload |
1703 | */ | | 1702 | */ |
1704 | int | | 1703 | int |
1705 | ipsecdoi_parse_responder_lifetime(notify, lifetime_sec, lifetime_kb) | | 1704 | ipsecdoi_parse_responder_lifetime(notify, lifetime_sec, lifetime_kb) |
1706 | struct isakmp_pl_n *notify; | | 1705 | struct isakmp_pl_n *notify; |
1707 | u_int32_t *lifetime_sec; | | 1706 | u_int32_t *lifetime_sec; |
1708 | u_int32_t *lifetime_kb; | | 1707 | u_int32_t *lifetime_kb; |
1709 | { | | 1708 | { |
1710 | struct isakmp_data *d; | | 1709 | struct isakmp_data *d; |
1711 | int flag, type, tlen, ld_type = -1; | | 1710 | int flag, type, tlen, ld_type = -1; |
1712 | u_int16_t lorv; | | 1711 | u_int16_t lorv; |
1713 | u_int32_t value; | | 1712 | u_int32_t value; |
1714 | | | 1713 | |
1715 | tlen = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size; | | 1714 | tlen = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size; |
1716 | d = (struct isakmp_data *)((char *)(notify + 1) + | | 1715 | d = (struct isakmp_data *)((char *)(notify + 1) + |
1717 | notify->spi_size); | | 1716 | notify->spi_size); |
1718 | | | 1717 | |
1719 | while (tlen >= sizeof(struct isakmp_data)) { | | 1718 | while (tlen >= sizeof(struct isakmp_data)) { |
1720 | type = ntohs(d->type) & ~ISAKMP_GEN_MASK; | | 1719 | type = ntohs(d->type) & ~ISAKMP_GEN_MASK; |
1721 | flag = ntohs(d->type) & ISAKMP_GEN_MASK; | | 1720 | flag = ntohs(d->type) & ISAKMP_GEN_MASK; |
1722 | lorv = ntohs(d->lorv); | | 1721 | lorv = ntohs(d->lorv); |
1723 | | | 1722 | |
1724 | plog(LLV_DEBUG, LOCATION, NULL, | | 1723 | plog(LLV_DEBUG, LOCATION, NULL, |
1725 | "type=%s, flag=0x%04x, lorv=%s\n", | | 1724 | "type=%s, flag=0x%04x, lorv=%s\n", |
1726 | s_ipsecdoi_attr(type), flag, | | 1725 | s_ipsecdoi_attr(type), flag, |
1727 | s_ipsecdoi_attr_v(type, lorv)); | | 1726 | s_ipsecdoi_attr_v(type, lorv)); |
1728 | | | 1727 | |
1729 | switch (type) { | | 1728 | switch (type) { |
1730 | case IPSECDOI_ATTR_SA_LD_TYPE: | | 1729 | case IPSECDOI_ATTR_SA_LD_TYPE: |
1731 | if (! flag) { | | 1730 | if (! flag) { |
1732 | plog(LLV_ERROR, LOCATION, NULL, | | 1731 | plog(LLV_ERROR, LOCATION, NULL, |
1733 | "must be TV when LD_TYPE.\n"); | | 1732 | "must be TV when LD_TYPE.\n"); |
1734 | return -1; | | 1733 | return -1; |
1735 | } | | 1734 | } |
1736 | ld_type = lorv; | | 1735 | ld_type = lorv; |
1737 | break; | | 1736 | break; |
1738 | case IPSECDOI_ATTR_SA_LD: | | 1737 | case IPSECDOI_ATTR_SA_LD: |
1739 | if (flag) | | 1738 | if (flag) |
1740 | value = lorv; | | 1739 | value = lorv; |
1741 | else if (lorv == 2) | | 1740 | else if (lorv == 2) |
1742 | value = ntohs(*(u_int16_t *)(d + 1)); | | 1741 | value = ntohs(*(u_int16_t *)(d + 1)); |
1743 | else if (lorv == 4) | | 1742 | else if (lorv == 4) |
1744 | value = ntohl(*(u_int32_t *)(d + 1)); | | 1743 | value = ntohl(*(u_int32_t *)(d + 1)); |
1745 | else { | | 1744 | else { |
1746 | plog(LLV_ERROR, LOCATION, NULL, | | 1745 | plog(LLV_ERROR, LOCATION, NULL, |
1747 | "payload length %d for lifetime " | | 1746 | "payload length %d for lifetime " |
1748 | "data length is unsupported.\n", lorv); | | 1747 | "data length is unsupported.\n", lorv); |
1749 | return -1; | | 1748 | return -1; |
1750 | } | | 1749 | } |
1751 | | | 1750 | |
1752 | switch (ld_type) { | | 1751 | switch (ld_type) { |
1753 | case IPSECDOI_ATTR_SA_LD_TYPE_SEC: | | 1752 | case IPSECDOI_ATTR_SA_LD_TYPE_SEC: |
1754 | if (lifetime_sec != NULL) | | 1753 | if (lifetime_sec != NULL) |
1755 | *lifetime_sec = value; | | 1754 | *lifetime_sec = value; |
1756 | plog(LLV_INFO, LOCATION, NULL, | | 1755 | plog(LLV_INFO, LOCATION, NULL, |
1757 | "received RESPONDER-LIFETIME: %d " | | 1756 | "received RESPONDER-LIFETIME: %d " |
1758 | "seconds\n", value); | | 1757 | "seconds\n", value); |
1759 | break; | | 1758 | break; |
1760 | case IPSECDOI_ATTR_SA_LD_TYPE_KB: | | 1759 | case IPSECDOI_ATTR_SA_LD_TYPE_KB: |
1761 | if (lifetime_kb != NULL) | | 1760 | if (lifetime_kb != NULL) |
1762 | *lifetime_kb = value; | | 1761 | *lifetime_kb = value; |
1763 | plog(LLV_INFO, LOCATION, NULL, | | 1762 | plog(LLV_INFO, LOCATION, NULL, |
1764 | "received RESPONDER-LIFETIME: %d " | | 1763 | "received RESPONDER-LIFETIME: %d " |
1765 | "kbytes\n", value); | | 1764 | "kbytes\n", value); |
1766 | break; | | 1765 | break; |
1767 | default: | | 1766 | default: |
1768 | plog(LLV_ERROR, LOCATION, NULL, | | 1767 | plog(LLV_ERROR, LOCATION, NULL, |
1769 | "lifetime data received without " | | 1768 | "lifetime data received without " |
1770 | "lifetime data type.\n"); | | 1769 | "lifetime data type.\n"); |
1771 | return -1; | | 1770 | return -1; |
1772 | } | | 1771 | } |
1773 | break; | | 1772 | break; |
1774 | } | | 1773 | } |
1775 | | | 1774 | |
1776 | if (flag) { | | 1775 | if (flag) { |
1777 | tlen -= sizeof(*d); | | 1776 | tlen -= sizeof(*d); |
1778 | d = (struct isakmp_data *)((char *)d | | 1777 | d = (struct isakmp_data *)((char *)d |
1779 | + sizeof(*d)); | | 1778 | + sizeof(*d)); |
1780 | } else { | | 1779 | } else { |
1781 | tlen -= (sizeof(*d) + lorv); | | 1780 | tlen -= (sizeof(*d) + lorv); |
1782 | d = (struct isakmp_data *)((char *)d | | 1781 | d = (struct isakmp_data *)((char *)d |
1783 | + sizeof(*d) + lorv); | | 1782 | + sizeof(*d) + lorv); |
1784 | } | | 1783 | } |
1785 | } | | 1784 | } |
1786 | | | 1785 | |
1787 | return 0; | | 1786 | return 0; |
1788 | } | | 1787 | } |
1789 | | | 1788 | |
1790 | | | 1789 | |
1791 | /*%%%*/ | | 1790 | /*%%%*/ |
1792 | /* | | 1791 | /* |
1793 | * check DOI | | 1792 | * check DOI |
1794 | */ | | 1793 | */ |
1795 | static int | | 1794 | static int |
1796 | check_doi(doi) | | 1795 | check_doi(doi) |
1797 | u_int32_t doi; | | 1796 | u_int32_t doi; |
1798 | { | | 1797 | { |
1799 | switch (doi) { | | 1798 | switch (doi) { |
1800 | case IPSEC_DOI: | | 1799 | case IPSEC_DOI: |
1801 | return 0; | | 1800 | return 0; |
1802 | default: | | 1801 | default: |
1803 | plog(LLV_ERROR, LOCATION, NULL, | | 1802 | plog(LLV_ERROR, LOCATION, NULL, |
1804 | "invalid value of DOI 0x%08x.\n", doi); | | 1803 | "invalid value of DOI 0x%08x.\n", doi); |
1805 | return -1; | | 1804 | return -1; |
1806 | } | | 1805 | } |
1807 | /* NOT REACHED */ | | 1806 | /* NOT REACHED */ |
1808 | } | | 1807 | } |
1809 | | | 1808 | |
1810 | /* | | 1809 | /* |
1811 | * check situation | | 1810 | * check situation |
1812 | */ | | 1811 | */ |
1813 | static int | | 1812 | static int |
1814 | check_situation(sit) | | 1813 | check_situation(sit) |
1815 | u_int32_t sit; | | 1814 | u_int32_t sit; |
1816 | { | | 1815 | { |
1817 | switch (sit) { | | 1816 | switch (sit) { |
1818 | case IPSECDOI_SIT_IDENTITY_ONLY: | | 1817 | case IPSECDOI_SIT_IDENTITY_ONLY: |
1819 | return 0; | | 1818 | return 0; |
1820 | | | 1819 | |
1821 | case IPSECDOI_SIT_SECRECY: | | 1820 | case IPSECDOI_SIT_SECRECY: |
1822 | case IPSECDOI_SIT_INTEGRITY: | | 1821 | case IPSECDOI_SIT_INTEGRITY: |
1823 | plog(LLV_ERROR, LOCATION, NULL, | | 1822 | plog(LLV_ERROR, LOCATION, NULL, |
1824 | "situation 0x%08x unsupported yet.\n", sit); | | 1823 | "situation 0x%08x unsupported yet.\n", sit); |
1825 | return -1; | | 1824 | return -1; |
1826 | | | 1825 | |
1827 | default: | | 1826 | default: |
1828 | plog(LLV_ERROR, LOCATION, NULL, | | 1827 | plog(LLV_ERROR, LOCATION, NULL, |
1829 | "invalid situation 0x%08x.\n", sit); | | 1828 | "invalid situation 0x%08x.\n", sit); |
1830 | return -1; | | 1829 | return -1; |
1831 | } | | 1830 | } |
1832 | /* NOT REACHED */ | | 1831 | /* NOT REACHED */ |
1833 | } | | 1832 | } |
1834 | | | 1833 | |
1835 | /* | | 1834 | /* |
1836 | * check protocol id in main mode | | 1835 | * check protocol id in main mode |
1837 | */ | | 1836 | */ |
1838 | static int | | 1837 | static int |
1839 | check_prot_main(proto_id) | | 1838 | check_prot_main(proto_id) |
1840 | int proto_id; | | 1839 | int proto_id; |
1841 | { | | 1840 | { |
1842 | switch (proto_id) { | | 1841 | switch (proto_id) { |
1843 | case IPSECDOI_PROTO_ISAKMP: | | 1842 | case IPSECDOI_PROTO_ISAKMP: |
1844 | return 0; | | 1843 | return 0; |
1845 | | | 1844 | |
1846 | default: | | 1845 | default: |
1847 | plog(LLV_ERROR, LOCATION, NULL, | | 1846 | plog(LLV_ERROR, LOCATION, NULL, |
1848 | "Illegal protocol id=%u.\n", proto_id); | | 1847 | "Illegal protocol id=%u.\n", proto_id); |
1849 | return -1; | | 1848 | return -1; |
1850 | } | | 1849 | } |
1851 | /* NOT REACHED */ | | 1850 | /* NOT REACHED */ |
1852 | } | | 1851 | } |
1853 | | | 1852 | |
1854 | /* | | 1853 | /* |
1855 | * check protocol id in quick mode | | 1854 | * check protocol id in quick mode |
1856 | */ | | 1855 | */ |
1857 | static int | | 1856 | static int |
1858 | check_prot_quick(proto_id) | | 1857 | check_prot_quick(proto_id) |
1859 | int proto_id; | | 1858 | int proto_id; |
1860 | { | | 1859 | { |
1861 | switch (proto_id) { | | 1860 | switch (proto_id) { |
1862 | case IPSECDOI_PROTO_IPSEC_AH: | | 1861 | case IPSECDOI_PROTO_IPSEC_AH: |
1863 | case IPSECDOI_PROTO_IPSEC_ESP: | | 1862 | case IPSECDOI_PROTO_IPSEC_ESP: |
1864 | return 0; | | 1863 | return 0; |
1865 | | | 1864 | |
1866 | case IPSECDOI_PROTO_IPCOMP: | | 1865 | case IPSECDOI_PROTO_IPCOMP: |
1867 | return 0; | | 1866 | return 0; |
1868 | | | 1867 | |
1869 | default: | | 1868 | default: |
1870 | plog(LLV_ERROR, LOCATION, NULL, | | 1869 | plog(LLV_ERROR, LOCATION, NULL, |
1871 | "invalid protocol id %d.\n", proto_id); | | 1870 | "invalid protocol id %d.\n", proto_id); |
1872 | return -1; | | 1871 | return -1; |
1873 | } | | 1872 | } |
1874 | /* NOT REACHED */ | | 1873 | /* NOT REACHED */ |
1875 | } | | 1874 | } |
1876 | | | 1875 | |
1877 | static int | | 1876 | static int |
1878 | check_spi_size(proto_id, size) | | 1877 | check_spi_size(proto_id, size) |
1879 | int proto_id, size; | | 1878 | int proto_id, size; |
1880 | { | | 1879 | { |
1881 | switch (proto_id) { | | 1880 | switch (proto_id) { |
1882 | case IPSECDOI_PROTO_ISAKMP: | | 1881 | case IPSECDOI_PROTO_ISAKMP: |
1883 | if (size != 0) { | | 1882 | if (size != 0) { |
1884 | /* WARNING */ | | 1883 | /* WARNING */ |
1885 | plog(LLV_WARNING, LOCATION, NULL, | | 1884 | plog(LLV_WARNING, LOCATION, NULL, |
1886 | "SPI size isn't zero, but IKE proposal.\n"); | | 1885 | "SPI size isn't zero, but IKE proposal.\n"); |
1887 | } | | 1886 | } |
1888 | return 0; | | 1887 | return 0; |
1889 | | | 1888 | |
1890 | case IPSECDOI_PROTO_IPSEC_AH: | | 1889 | case IPSECDOI_PROTO_IPSEC_AH: |
1891 | case IPSECDOI_PROTO_IPSEC_ESP: | | 1890 | case IPSECDOI_PROTO_IPSEC_ESP: |
1892 | if (size != 4) { | | 1891 | if (size != 4) { |
1893 | plog(LLV_ERROR, LOCATION, NULL, | | 1892 | plog(LLV_ERROR, LOCATION, NULL, |
1894 | "invalid SPI size=%d for IPSEC proposal.\n", | | 1893 | "invalid SPI size=%d for IPSEC proposal.\n", |
1895 | size); | | 1894 | size); |
1896 | return -1; | | 1895 | return -1; |
1897 | } | | 1896 | } |
1898 | return 0; | | 1897 | return 0; |
1899 | | | 1898 | |
1900 | case IPSECDOI_PROTO_IPCOMP: | | 1899 | case IPSECDOI_PROTO_IPCOMP: |
1901 | if (size != 2 && size != 4) { | | 1900 | if (size != 2 && size != 4) { |
1902 | plog(LLV_ERROR, LOCATION, NULL, | | 1901 | plog(LLV_ERROR, LOCATION, NULL, |
1903 | "invalid SPI size=%d for IPCOMP proposal.\n", | | 1902 | "invalid SPI size=%d for IPCOMP proposal.\n", |
1904 | size); | | 1903 | size); |
1905 | return -1; | | 1904 | return -1; |
1906 | } | | 1905 | } |
1907 | return 0; | | 1906 | return 0; |
1908 | | | 1907 | |
1909 | default: | | 1908 | default: |
1910 | /* ??? */ | | 1909 | /* ??? */ |
1911 | return -1; | | 1910 | return -1; |
1912 | } | | 1911 | } |
1913 | /* NOT REACHED */ | | 1912 | /* NOT REACHED */ |
1914 | } | | 1913 | } |
1915 | | | 1914 | |
1916 | /* | | 1915 | /* |
1917 | * check transform ID in ISAKMP. | | 1916 | * check transform ID in ISAKMP. |
1918 | */ | | 1917 | */ |
1919 | static int | | 1918 | static int |
1920 | check_trns_isakmp(t_id) | | 1919 | check_trns_isakmp(t_id) |
1921 | int t_id; | | 1920 | int t_id; |
1922 | { | | 1921 | { |
1923 | switch (t_id) { | | 1922 | switch (t_id) { |
1924 | case IPSECDOI_KEY_IKE: | | 1923 | case IPSECDOI_KEY_IKE: |
1925 | return 0; | | 1924 | return 0; |
1926 | default: | | 1925 | default: |
1927 | plog(LLV_ERROR, LOCATION, NULL, | | 1926 | plog(LLV_ERROR, LOCATION, NULL, |
1928 | "invalid transform-id=%u in proto_id=%u.\n", | | 1927 | "invalid transform-id=%u in proto_id=%u.\n", |
1929 | t_id, IPSECDOI_KEY_IKE); | | 1928 | t_id, IPSECDOI_KEY_IKE); |
1930 | return -1; | | 1929 | return -1; |
1931 | } | | 1930 | } |
1932 | /* NOT REACHED */ | | 1931 | /* NOT REACHED */ |
1933 | } | | 1932 | } |
1934 | | | 1933 | |
1935 | /* | | 1934 | /* |
1936 | * check transform ID in AH. | | 1935 | * check transform ID in AH. |
1937 | */ | | 1936 | */ |
1938 | static int | | 1937 | static int |
1939 | check_trns_ah(t_id) | | 1938 | check_trns_ah(t_id) |
1940 | int t_id; | | 1939 | int t_id; |
1941 | { | | 1940 | { |
1942 | switch (t_id) { | | 1941 | switch (t_id) { |
1943 | case IPSECDOI_AH_MD5: | | 1942 | case IPSECDOI_AH_MD5: |
1944 | case IPSECDOI_AH_SHA: | | 1943 | case IPSECDOI_AH_SHA: |
1945 | case IPSECDOI_AH_SHA256: | | 1944 | case IPSECDOI_AH_SHA256: |
1946 | case IPSECDOI_AH_SHA384: | | 1945 | case IPSECDOI_AH_SHA384: |
1947 | case IPSECDOI_AH_SHA512: | | 1946 | case IPSECDOI_AH_SHA512: |
1948 | return 0; | | 1947 | return 0; |
1949 | case IPSECDOI_AH_DES: | | 1948 | case IPSECDOI_AH_DES: |
1950 | plog(LLV_ERROR, LOCATION, NULL, | | 1949 | plog(LLV_ERROR, LOCATION, NULL, |
1951 | "not support transform-id=%u in AH.\n", t_id); | | 1950 | "not support transform-id=%u in AH.\n", t_id); |
1952 | return -1; | | 1951 | return -1; |
1953 | default: | | 1952 | default: |
1954 | plog(LLV_ERROR, LOCATION, NULL, | | 1953 | plog(LLV_ERROR, LOCATION, NULL, |
1955 | "invalid transform-id=%u in AH.\n", t_id); | | 1954 | "invalid transform-id=%u in AH.\n", t_id); |
1956 | return -1; | | 1955 | return -1; |
1957 | } | | 1956 | } |
1958 | /* NOT REACHED */ | | 1957 | /* NOT REACHED */ |
1959 | } | | 1958 | } |
1960 | | | 1959 | |
1961 | /* | | 1960 | /* |
1962 | * check transform ID in ESP. | | 1961 | * check transform ID in ESP. |
1963 | */ | | 1962 | */ |
1964 | static int | | 1963 | static int |
1965 | check_trns_esp(t_id) | | 1964 | check_trns_esp(t_id) |
1966 | int t_id; | | 1965 | int t_id; |
1967 | { | | 1966 | { |
1968 | switch (t_id) { | | 1967 | switch (t_id) { |
1969 | case IPSECDOI_ESP_DES: | | 1968 | case IPSECDOI_ESP_DES: |
1970 | case IPSECDOI_ESP_3DES: | | 1969 | case IPSECDOI_ESP_3DES: |
1971 | case IPSECDOI_ESP_NULL: | | 1970 | case IPSECDOI_ESP_NULL: |
1972 | case IPSECDOI_ESP_RC5: | | 1971 | case IPSECDOI_ESP_RC5: |
1973 | case IPSECDOI_ESP_CAST: | | 1972 | case IPSECDOI_ESP_CAST: |
1974 | case IPSECDOI_ESP_BLOWFISH: | | 1973 | case IPSECDOI_ESP_BLOWFISH: |
1975 | case IPSECDOI_ESP_AES: | | 1974 | case IPSECDOI_ESP_AES: |
1976 | case IPSECDOI_ESP_AESGCM16: | | 1975 | case IPSECDOI_ESP_AESGCM16: |
1977 | case IPSECDOI_ESP_TWOFISH: | | 1976 | case IPSECDOI_ESP_TWOFISH: |
1978 | case IPSECDOI_ESP_CAMELLIA: | | 1977 | case IPSECDOI_ESP_CAMELLIA: |
1979 | return 0; | | 1978 | return 0; |
1980 | case IPSECDOI_ESP_DES_IV32: | | 1979 | case IPSECDOI_ESP_DES_IV32: |
1981 | case IPSECDOI_ESP_DES_IV64: | | 1980 | case IPSECDOI_ESP_DES_IV64: |
1982 | case IPSECDOI_ESP_IDEA: | | 1981 | case IPSECDOI_ESP_IDEA: |
1983 | case IPSECDOI_ESP_3IDEA: | | 1982 | case IPSECDOI_ESP_3IDEA: |
1984 | case IPSECDOI_ESP_RC4: | | 1983 | case IPSECDOI_ESP_RC4: |
1985 | plog(LLV_ERROR, LOCATION, NULL, | | 1984 | plog(LLV_ERROR, LOCATION, NULL, |
1986 | "not support transform-id=%u in ESP.\n", t_id); | | 1985 | "not support transform-id=%u in ESP.\n", t_id); |
1987 | return -1; | | 1986 | return -1; |
1988 | default: | | 1987 | default: |
1989 | plog(LLV_ERROR, LOCATION, NULL, | | 1988 | plog(LLV_ERROR, LOCATION, NULL, |
1990 | "invalid transform-id=%u in ESP.\n", t_id); | | 1989 | "invalid transform-id=%u in ESP.\n", t_id); |
1991 | return -1; | | 1990 | return -1; |
1992 | } | | 1991 | } |
1993 | /* NOT REACHED */ | | 1992 | /* NOT REACHED */ |
1994 | } | | 1993 | } |
1995 | | | 1994 | |
1996 | /* | | 1995 | /* |
1997 | * check transform ID in IPCOMP. | | 1996 | * check transform ID in IPCOMP. |
1998 | */ | | 1997 | */ |
1999 | static int | | 1998 | static int |
2000 | check_trns_ipcomp(t_id) | | 1999 | check_trns_ipcomp(t_id) |
2001 | int t_id; | | 2000 | int t_id; |
2002 | { | | 2001 | { |
2003 | switch (t_id) { | | 2002 | switch (t_id) { |
2004 | case IPSECDOI_IPCOMP_OUI: | | 2003 | case IPSECDOI_IPCOMP_OUI: |
2005 | case IPSECDOI_IPCOMP_DEFLATE: | | 2004 | case IPSECDOI_IPCOMP_DEFLATE: |
2006 | case IPSECDOI_IPCOMP_LZS: | | 2005 | case IPSECDOI_IPCOMP_LZS: |
2007 | return 0; | | 2006 | return 0; |
2008 | default: | | 2007 | default: |
2009 | plog(LLV_ERROR, LOCATION, NULL, | | 2008 | plog(LLV_ERROR, LOCATION, NULL, |
2010 | "invalid transform-id=%u in IPCOMP.\n", t_id); | | 2009 | "invalid transform-id=%u in IPCOMP.\n", t_id); |
2011 | return -1; | | 2010 | return -1; |
2012 | } | | 2011 | } |
2013 | /* NOT REACHED */ | | 2012 | /* NOT REACHED */ |
2014 | } | | 2013 | } |
2015 | | | 2014 | |
2016 | /* | | 2015 | /* |
2017 | * check data attributes in IKE. | | 2016 | * check data attributes in IKE. |
2018 | */ | | 2017 | */ |
2019 | static int | | 2018 | static int |
2020 | check_attr_isakmp(trns) | | 2019 | check_attr_isakmp(trns) |
2021 | struct isakmp_pl_t *trns; | | 2020 | struct isakmp_pl_t *trns; |
2022 | { | | 2021 | { |
2023 | struct isakmp_data *d; | | 2022 | struct isakmp_data *d; |
2024 | int tlen; | | 2023 | int tlen; |
2025 | int flag, type; | | 2024 | int flag, type; |
2026 | u_int16_t lorv; | | 2025 | u_int16_t lorv; |
2027 | | | 2026 | |
2028 | tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t); | | 2027 | tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t); |
2029 | d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t)); | | 2028 | d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t)); |
2030 | | | 2029 | |
2031 | while (tlen > 0) { | | 2030 | while (tlen > 0) { |
2032 | type = ntohs(d->type) & ~ISAKMP_GEN_MASK; | | 2031 | type = ntohs(d->type) & ~ISAKMP_GEN_MASK; |
2033 | flag = ntohs(d->type) & ISAKMP_GEN_MASK; | | 2032 | flag = ntohs(d->type) & ISAKMP_GEN_MASK; |
2034 | lorv = ntohs(d->lorv); | | 2033 | lorv = ntohs(d->lorv); |
2035 | | | 2034 | |
2036 | plog(LLV_DEBUG, LOCATION, NULL, | | 2035 | plog(LLV_DEBUG, LOCATION, NULL, |
2037 | "type=%s, flag=0x%04x, lorv=%s\n", | | 2036 | "type=%s, flag=0x%04x, lorv=%s\n", |
2038 | s_oakley_attr(type), flag, | | 2037 | s_oakley_attr(type), flag, |
2039 | s_oakley_attr_v(type, lorv)); | | 2038 | s_oakley_attr_v(type, lorv)); |
2040 | | | 2039 | |
2041 | /* | | 2040 | /* |
2042 | * some of the attributes must be encoded in TV. | | 2041 | * some of the attributes must be encoded in TV. |
2043 | * see RFC2409 Appendix A "Attribute Classes". | | 2042 | * see RFC2409 Appendix A "Attribute Classes". |
2044 | */ | | 2043 | */ |
2045 | switch (type) { | | 2044 | switch (type) { |
2046 | case OAKLEY_ATTR_ENC_ALG: | | 2045 | case OAKLEY_ATTR_ENC_ALG: |
2047 | case OAKLEY_ATTR_HASH_ALG: | | 2046 | case OAKLEY_ATTR_HASH_ALG: |
2048 | case OAKLEY_ATTR_AUTH_METHOD: | | 2047 | case OAKLEY_ATTR_AUTH_METHOD: |
2049 | case OAKLEY_ATTR_GRP_DESC: | | 2048 | case OAKLEY_ATTR_GRP_DESC: |
2050 | case OAKLEY_ATTR_GRP_TYPE: | | 2049 | case OAKLEY_ATTR_GRP_TYPE: |
2051 | case OAKLEY_ATTR_SA_LD_TYPE: | | 2050 | case OAKLEY_ATTR_SA_LD_TYPE: |
2052 | case OAKLEY_ATTR_PRF: | | 2051 | case OAKLEY_ATTR_PRF: |
2053 | case OAKLEY_ATTR_KEY_LEN: | | 2052 | case OAKLEY_ATTR_KEY_LEN: |
2054 | case OAKLEY_ATTR_FIELD_SIZE: | | 2053 | case OAKLEY_ATTR_FIELD_SIZE: |
2055 | if (!flag) { /* TLV*/ | | 2054 | if (!flag) { /* TLV*/ |
2056 | plog(LLV_ERROR, LOCATION, NULL, | | 2055 | plog(LLV_ERROR, LOCATION, NULL, |
2057 | "oakley attribute %d must be TV.\n", | | 2056 | "oakley attribute %d must be TV.\n", |
2058 | type); | | 2057 | type); |
2059 | return -1; | | 2058 | return -1; |
2060 | } | | 2059 | } |
2061 | break; | | 2060 | break; |
2062 | } | | 2061 | } |
2063 | | | 2062 | |
2064 | /* sanity check for TLV. length must be specified. */ | | 2063 | /* sanity check for TLV. length must be specified. */ |
2065 | if (!flag && lorv == 0) { /*TLV*/ | | 2064 | if (!flag && lorv == 0) { /*TLV*/ |
2066 | plog(LLV_ERROR, LOCATION, NULL, | | 2065 | plog(LLV_ERROR, LOCATION, NULL, |
2067 | "invalid length %d for TLV attribute %d.\n", | | 2066 | "invalid length %d for TLV attribute %d.\n", |
2068 | lorv, type); | | 2067 | lorv, type); |
2069 | return -1; | | 2068 | return -1; |
2070 | } | | 2069 | } |
2071 | | | 2070 | |
2072 | switch (type) { | | 2071 | switch (type) { |
2073 | case OAKLEY_ATTR_ENC_ALG: | | 2072 | case OAKLEY_ATTR_ENC_ALG: |
2074 | if (!alg_oakley_encdef_ok(lorv)) { | | 2073 | if (!alg_oakley_encdef_ok(lorv)) { |
2075 | plog(LLV_ERROR, LOCATION, NULL, | | 2074 | plog(LLV_ERROR, LOCATION, NULL, |
2076 | "invalied encryption algorithm=%d.\n", | | 2075 | "invalied encryption algorithm=%d.\n", |
2077 | lorv); | | 2076 | lorv); |
2078 | return -1; | | 2077 | return -1; |
2079 | } | | 2078 | } |
2080 | break; | | 2079 | break; |
2081 | | | 2080 | |
2082 | case OAKLEY_ATTR_HASH_ALG: | | 2081 | case OAKLEY_ATTR_HASH_ALG: |
2083 | if (!alg_oakley_hashdef_ok(lorv)) { | | 2082 | if (!alg_oakley_hashdef_ok(lorv)) { |
2084 | plog(LLV_ERROR, LOCATION, NULL, | | 2083 | plog(LLV_ERROR, LOCATION, NULL, |
2085 | "invalied hash algorithm=%d.\n", | | 2084 | "invalied hash algorithm=%d.\n", |
2086 | lorv); | | 2085 | lorv); |
2087 | return -1; | | 2086 | return -1; |
2088 | } | | 2087 | } |
2089 | break; | | 2088 | break; |
2090 | | | 2089 | |
2091 | case OAKLEY_ATTR_AUTH_METHOD: | | 2090 | case OAKLEY_ATTR_AUTH_METHOD: |
2092 | switch (lorv) { | | 2091 | switch (lorv) { |
2093 | case OAKLEY_ATTR_AUTH_METHOD_PSKEY: | | 2092 | case OAKLEY_ATTR_AUTH_METHOD_PSKEY: |
2094 | case OAKLEY_ATTR_AUTH_METHOD_RSASIG: | | 2093 | case OAKLEY_ATTR_AUTH_METHOD_RSASIG: |
2095 | #ifdef ENABLE_HYBRID | | 2094 | #ifdef ENABLE_HYBRID |
2096 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: | | 2095 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: |
2097 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: | | 2096 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: |
2098 | #endif | | 2097 | #endif |
2099 | #if defined(ENABLE_HYBRID) || defined(HAVE_GSSAPI) | | 2098 | #if defined(ENABLE_HYBRID) || defined(HAVE_GSSAPI) |
2100 | /* These two authentication method IDs overlap. */ | | 2099 | /* These two authentication method IDs overlap. */ |
2101 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I: | | 2100 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I: |
2102 | /*case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:*/ | | 2101 | /*case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:*/ |
2103 | #endif | | 2102 | #endif |
2104 | break; | | 2103 | break; |
2105 | case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: | | 2104 | case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: |
2106 | #ifdef ENABLE_HYBRID | | 2105 | #ifdef ENABLE_HYBRID |
2107 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: | | 2106 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: |
2108 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: | | 2107 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: |
2109 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: | | 2108 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: |
2110 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: | | 2109 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: |
2111 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: | | 2110 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: |
2112 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: | | 2111 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: |
2113 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: | | 2112 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: |
2114 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: | | 2113 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: |
2115 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: | | 2114 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: |
2116 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: | | 2115 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: |
2117 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: | | 2116 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: |
2118 | #endif | | 2117 | #endif |
2119 | case OAKLEY_ATTR_AUTH_METHOD_RSAENC: | | 2118 | case OAKLEY_ATTR_AUTH_METHOD_RSAENC: |
2120 | case OAKLEY_ATTR_AUTH_METHOD_RSAREV: | | 2119 | case OAKLEY_ATTR_AUTH_METHOD_RSAREV: |
2121 | plog(LLV_ERROR, LOCATION, NULL, | | 2120 | plog(LLV_ERROR, LOCATION, NULL, |
2122 | "auth method %s isn't supported.\n", | | 2121 | "auth method %s isn't supported.\n", |
2123 | s_oakley_attr_method(lorv)); | | 2122 | s_oakley_attr_method(lorv)); |
2124 | return -1; | | 2123 | return -1; |
2125 | default: | | 2124 | default: |
2126 | plog(LLV_ERROR, LOCATION, NULL, | | 2125 | plog(LLV_ERROR, LOCATION, NULL, |
2127 | "invalid auth method %d.\n", | | 2126 | "invalid auth method %d.\n", |
2128 | lorv); | | 2127 | lorv); |
2129 | return -1; | | 2128 | return -1; |
2130 | } | | 2129 | } |
2131 | break; | | 2130 | break; |
2132 | | | 2131 | |
2133 | case OAKLEY_ATTR_GRP_DESC: | | 2132 | case OAKLEY_ATTR_GRP_DESC: |
2134 | if (!alg_oakley_dhdef_ok(lorv)) { | | 2133 | if (!alg_oakley_dhdef_ok(lorv)) { |
2135 | plog(LLV_ERROR, LOCATION, NULL, | | 2134 | plog(LLV_ERROR, LOCATION, NULL, |
2136 | "invalid DH group %d.\n", | | 2135 | "invalid DH group %d.\n", |
2137 | lorv); | | 2136 | lorv); |
2138 | return -1; | | 2137 | return -1; |
2139 | } | | 2138 | } |
2140 | break; | | 2139 | break; |
2141 | | | 2140 | |
2142 | case OAKLEY_ATTR_GRP_TYPE: | | 2141 | case OAKLEY_ATTR_GRP_TYPE: |
2143 | switch (lorv) { | | 2142 | switch (lorv) { |
2144 | case OAKLEY_ATTR_GRP_TYPE_MODP: | | 2143 | case OAKLEY_ATTR_GRP_TYPE_MODP: |
2145 | break; | | 2144 | break; |
2146 | default: | | 2145 | default: |
2147 | plog(LLV_ERROR, LOCATION, NULL, | | 2146 | plog(LLV_ERROR, LOCATION, NULL, |
2148 | "unsupported DH group type %d.\n", | | 2147 | "unsupported DH group type %d.\n", |
2149 | lorv); | | 2148 | lorv); |
2150 | return -1; | | 2149 | return -1; |
2151 | } | | 2150 | } |
2152 | break; | | 2151 | break; |
2153 | | | 2152 | |
2154 | case OAKLEY_ATTR_GRP_PI: | | 2153 | case OAKLEY_ATTR_GRP_PI: |
2155 | case OAKLEY_ATTR_GRP_GEN_ONE: | | 2154 | case OAKLEY_ATTR_GRP_GEN_ONE: |
2156 | /* sanity checks? */ | | 2155 | /* sanity checks? */ |
2157 | break; | | 2156 | break; |
2158 | | | 2157 | |
2159 | case OAKLEY_ATTR_GRP_GEN_TWO: | | 2158 | case OAKLEY_ATTR_GRP_GEN_TWO: |
2160 | case OAKLEY_ATTR_GRP_CURVE_A: | | 2159 | case OAKLEY_ATTR_GRP_CURVE_A: |
2161 | case OAKLEY_ATTR_GRP_CURVE_B: | | 2160 | case OAKLEY_ATTR_GRP_CURVE_B: |
2162 | plog(LLV_ERROR, LOCATION, NULL, | | 2161 | plog(LLV_ERROR, LOCATION, NULL, |
2163 | "attr type=%u isn't supported.\n", type); | | 2162 | "attr type=%u isn't supported.\n", type); |
2164 | return -1; | | 2163 | return -1; |
2165 | | | 2164 | |
2166 | case OAKLEY_ATTR_SA_LD_TYPE: | | 2165 | case OAKLEY_ATTR_SA_LD_TYPE: |
2167 | switch (lorv) { | | 2166 | switch (lorv) { |
2168 | case OAKLEY_ATTR_SA_LD_TYPE_SEC: | | 2167 | case OAKLEY_ATTR_SA_LD_TYPE_SEC: |
2169 | case OAKLEY_ATTR_SA_LD_TYPE_KB: | | 2168 | case OAKLEY_ATTR_SA_LD_TYPE_KB: |
2170 | break; | | 2169 | break; |
2171 | default: | | 2170 | default: |
2172 | plog(LLV_ERROR, LOCATION, NULL, | | 2171 | plog(LLV_ERROR, LOCATION, NULL, |
2173 | "invalid life type %d.\n", lorv); | | 2172 | "invalid life type %d.\n", lorv); |
2174 | return -1; | | 2173 | return -1; |
2175 | } | | 2174 | } |
2176 | break; | | 2175 | break; |
2177 | | | 2176 | |
2178 | case OAKLEY_ATTR_SA_LD: | | 2177 | case OAKLEY_ATTR_SA_LD: |
2179 | /* should check the value */ | | 2178 | /* should check the value */ |
2180 | break; | | 2179 | break; |
2181 | | | 2180 | |
2182 | case OAKLEY_ATTR_PRF: | | 2181 | case OAKLEY_ATTR_PRF: |
2183 | case OAKLEY_ATTR_KEY_LEN: | | 2182 | case OAKLEY_ATTR_KEY_LEN: |
2184 | break; | | 2183 | break; |
2185 | | | 2184 | |