]> git.saurik.com Git - apple/network_cmds.git/blame - ipsec/policy_parse.y
network_cmds-115.tar.gz
[apple/network_cmds.git] / ipsec / policy_parse.y
CommitLineData
7ba0088d
A
1/* $FreeBSD: src/lib/libipsec/policy_parse.y,v 1.1.2.1 2000/07/15 07:24:04 kris Exp $ */
2/* $KAME: policy_parse.y,v 1.10 2000/05/07 05:25:03 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * IN/OUT bound policy configuration take place such below:
35 * in <policy>
36 * out <policy>
37 *
38 * <policy> is one of following:
39 * "discard", "none", "ipsec <requests>", "entrust", "bypass",
40 *
41 * The following requests are accepted as <requests>:
42 *
43 * protocol/mode/src-dst/level
44 * protocol/mode/src-dst parsed as protocol/mode/src-dst/default
45 * protocol/mode/src-dst/ parsed as protocol/mode/src-dst/default
46 * protocol/transport parsed as protocol/mode/any-any/default
47 * protocol/transport//level parsed as protocol/mode/any-any/level
48 *
49 * You can concatenate these requests with either ' '(single space) or '\n'.
50 */
51
52%{
53#include <sys/types.h>
54#include <sys/param.h>
55#include <sys/socket.h>
56
57#include <netinet/in.h>
58#include <netinet6/ipsec.h>
59
60#include <stdlib.h>
61#include <stdio.h>
62#include <string.h>
63#include <netdb.h>
64
65#include "ipsec_strerror.h"
66
67#define ATOX(c) \
68 (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) ))
69
70static caddr_t pbuf = NULL; /* sadb_x_policy buffer */
71static int tlen = 0; /* total length of pbuf */
72static int offset = 0; /* offset of pbuf */
73static int p_dir, p_type, p_protocol, p_mode, p_level, p_reqid;
74static struct sockaddr *p_src = NULL;
75static struct sockaddr *p_dst = NULL;
76
77struct _val;
78extern void yyerror __P((char *msg));
79static struct sockaddr *parse_sockaddr __P((struct _val *buf));
80static int rule_check __P((void));
81static int init_x_policy __P((void));
82static int set_x_request __P((struct sockaddr *src, struct sockaddr *dst));
83static int set_sockaddr __P((struct sockaddr *addr));
84static void policy_parse_request_init __P((void));
85static caddr_t policy_parse __P((char *msg, int msglen));
86
87extern void __policy__strbuffer__init__ __P((char *msg));
88extern int yyparse __P((void));
89extern int yylex __P((void));
90
91%}
92
93%union {
94 u_int num;
95 struct _val {
96 int len;
97 char *buf;
98 } val;
99}
100
101%token DIR ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY
102%token IPADDRESS
103%token ME ANY
104%token SLASH HYPHEN
105%type <num> DIR ACTION PROTOCOL MODE LEVEL
106%type <val> IPADDRESS LEVEL_SPECIFY
107
108%%
109policy_spec
110 : DIR ACTION
111 {
112 p_dir = $1;
113 p_type = $2;
114
115 if (init_x_policy())
116 return -1;
117 }
118 rules
119 | DIR
120 {
121 p_dir = $1;
122 p_type = 0; /* ignored it by kernel */
123
124 if (init_x_policy())
125 return -1;
126 }
127 ;
128
129rules
130 : /*NOTHING*/
131 | rules rule {
132 if (rule_check() < 0)
133 return -1;
134
135 if (set_x_request(p_src, p_dst) < 0)
136 return -1;
137
138 policy_parse_request_init();
139 }
140 ;
141
142rule
143 : protocol SLASH mode SLASH addresses SLASH level
144 | protocol SLASH mode SLASH addresses SLASH
145 | protocol SLASH mode SLASH addresses
146 | protocol SLASH mode SLASH
147 | protocol SLASH mode SLASH SLASH level
148 | protocol SLASH mode
149 | protocol SLASH {
150 __ipsec_errcode = EIPSEC_FEW_ARGUMENTS;
151 return -1;
152 }
153 | protocol {
154 __ipsec_errcode = EIPSEC_FEW_ARGUMENTS;
155 return -1;
156 }
157 ;
158
159protocol
160 : PROTOCOL { p_protocol = $1; }
161 ;
162
163mode
164 : MODE { p_mode = $1; }
165 ;
166
167level
168 : LEVEL {
169 p_level = $1;
170 p_reqid = 0;
171 }
172 | LEVEL_SPECIFY {
173 p_level = IPSEC_LEVEL_UNIQUE;
174 p_reqid = atol($1.buf); /* atol() is good. */
175 }
176 ;
177
178addresses
179 : IPADDRESS {
180 p_src = parse_sockaddr(&$1);
181 if (p_src == NULL)
182 return -1;
183 }
184 HYPHEN
185 IPADDRESS {
186 p_dst = parse_sockaddr(&$4);
187 if (p_dst == NULL)
188 return -1;
189 }
190 | ME HYPHEN ANY {
191 if (p_dir != IPSEC_DIR_OUTBOUND) {
192 __ipsec_errcode = EIPSEC_INVAL_DIR;
193 return -1;
194 }
195 }
196 | ANY HYPHEN ME {
197 if (p_dir != IPSEC_DIR_INBOUND) {
198 __ipsec_errcode = EIPSEC_INVAL_DIR;
199 return -1;
200 }
201 }
202 /*
203 | ME HYPHEN ME
204 */
205 ;
206
207%%
208
209void
210yyerror(msg)
211 char *msg;
212{
213 extern char *__libipsecyytext; /*XXX*/
214
215 fprintf(stderr, "libipsec: %s while parsing \"%s\"\n",
216 msg, __libipsecyytext);
217
218 return;
219}
220
221static struct sockaddr *
222parse_sockaddr(buf)
223 struct _val *buf;
224{
225 struct addrinfo hints, *res;
226 char *serv = NULL;
227 int error;
228 struct sockaddr *newaddr = NULL;
229
230 memset(&hints, 0, sizeof(hints));
231 hints.ai_family = PF_UNSPEC;
232 hints.ai_flags = AI_NUMERICHOST;
233 error = getaddrinfo(buf->buf, serv, &hints, &res);
234 if (error != 0) {
235 yyerror("invalid IP address");
236 __ipsec_set_strerror(gai_strerror(error));
237 return NULL;
238 }
239
240 if (res->ai_addr == NULL) {
241 yyerror("invalid IP address");
242 __ipsec_set_strerror(gai_strerror(error));
243 return NULL;
244 }
245
246 newaddr = malloc(res->ai_addr->sa_len);
247 if (newaddr == NULL) {
248 __ipsec_errcode = EIPSEC_NO_BUFS;
249 freeaddrinfo(res);
250 return NULL;
251 }
252 memcpy(newaddr, res->ai_addr, res->ai_addr->sa_len);
253
254 freeaddrinfo(res);
255
256 __ipsec_errcode = EIPSEC_NO_ERROR;
257 return newaddr;
258}
259
260static int
261rule_check()
262{
263 if (p_type == IPSEC_POLICY_IPSEC) {
264 if (p_protocol == IPPROTO_IP) {
265 __ipsec_errcode = EIPSEC_NO_PROTO;
266 return -1;
267 }
268
269 if (p_mode != IPSEC_MODE_TRANSPORT
270 && p_mode != IPSEC_MODE_TUNNEL) {
271 __ipsec_errcode = EIPSEC_INVAL_MODE;
272 return -1;
273 }
274
275 if (p_src == NULL && p_dst == NULL) {
276 if (p_mode != IPSEC_MODE_TRANSPORT) {
277 __ipsec_errcode = EIPSEC_INVAL_ADDRESS;
278 return -1;
279 }
280 }
281 else if (p_src->sa_family != p_dst->sa_family) {
282 __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
283 return -1;
284 }
285 }
286
287 __ipsec_errcode = EIPSEC_NO_ERROR;
288 return 0;
289}
290
291static int
292init_x_policy()
293{
294 struct sadb_x_policy *p;
295
296 tlen = sizeof(struct sadb_x_policy);
297
298 pbuf = malloc(tlen);
299 if (pbuf == NULL) {
300 __ipsec_errcode = EIPSEC_NO_BUFS;
301 return -1;
302 }
303 p = (struct sadb_x_policy *)pbuf;
304 p->sadb_x_policy_len = 0; /* must update later */
305 p->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
306 p->sadb_x_policy_type = p_type;
307 p->sadb_x_policy_dir = p_dir;
308 p->sadb_x_policy_reserved = 0;
309 offset = tlen;
310
311 __ipsec_errcode = EIPSEC_NO_ERROR;
312 return 0;
313}
314
315static int
316set_x_request(src, dst)
317 struct sockaddr *src, *dst;
318{
319 struct sadb_x_ipsecrequest *p;
320 int reqlen;
321
322 reqlen = sizeof(*p)
323 + (src ? src->sa_len : 0)
324 + (dst ? dst->sa_len : 0);
325 tlen += reqlen; /* increment to total length */
326
327 pbuf = realloc(pbuf, tlen);
328 if (pbuf == NULL) {
329 __ipsec_errcode = EIPSEC_NO_BUFS;
330 return -1;
331 }
332 p = (struct sadb_x_ipsecrequest *)&pbuf[offset];
333 p->sadb_x_ipsecrequest_len = reqlen;
334 p->sadb_x_ipsecrequest_proto = p_protocol;
335 p->sadb_x_ipsecrequest_mode = p_mode;
336 p->sadb_x_ipsecrequest_level = p_level;
337 p->sadb_x_ipsecrequest_reqid = p_reqid;
338 offset += sizeof(*p);
339
340 if (set_sockaddr(src) || set_sockaddr(dst))
341 return -1;
342
343 __ipsec_errcode = EIPSEC_NO_ERROR;
344 return 0;
345}
346
347static int
348set_sockaddr(addr)
349 struct sockaddr *addr;
350{
351 if (addr == NULL) {
352 __ipsec_errcode = EIPSEC_NO_ERROR;
353 return 0;
354 }
355
356 /* tlen has already incremented */
357
358 memcpy(&pbuf[offset], addr, addr->sa_len);
359
360 offset += addr->sa_len;
361
362 __ipsec_errcode = EIPSEC_NO_ERROR;
363 return 0;
364}
365
366static void
367policy_parse_request_init()
368{
369 p_protocol = IPPROTO_IP;
370 p_mode = IPSEC_MODE_ANY;
371 p_level = IPSEC_LEVEL_DEFAULT;
372 p_reqid = 0;
373 if (p_src != NULL) {
374 free(p_src);
375 p_src = NULL;
376 }
377 if (p_dst != NULL) {
378 free(p_dst);
379 p_dst = NULL;
380 }
381
382 return;
383}
384
385static caddr_t
386policy_parse(msg, msglen)
387 char *msg;
388 int msglen;
389{
390 int error;
391 pbuf = NULL;
392 tlen = 0;
393
394 /* initialize */
395 p_dir = IPSEC_DIR_INVALID;
396 p_type = IPSEC_POLICY_DISCARD;
397 policy_parse_request_init();
398 __policy__strbuffer__init__(msg);
399
400 error = yyparse(); /* it must be set errcode. */
401 if (error) {
402 if (pbuf != NULL)
403 free(pbuf);
404 return NULL;
405 }
406
407 /* update total length */
408 ((struct sadb_x_policy *)pbuf)->sadb_x_policy_len = PFKEY_UNIT64(tlen);
409
410 __ipsec_errcode = EIPSEC_NO_ERROR;
411
412 return pbuf;
413}
414
415caddr_t
416ipsec_set_policy(msg, msglen)
417 char *msg;
418 int msglen;
419{
420 caddr_t policy;
421
422 policy = policy_parse(msg, msglen);
423 if (policy == NULL) {
424 if (__ipsec_errcode == EIPSEC_NO_ERROR)
425 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
426 return NULL;
427 }
428
429 __ipsec_errcode = EIPSEC_NO_ERROR;
430 return policy;
431}
432