]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/cfparse.y
ipsec-34.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / cfparse.y
1 /* $Id: cfparse.y,v 1.37.2.7 2006/02/02 14:37:17 vanhu Exp $ */
2
3 %{
4 /*
5 * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 and 2003 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 #include "config.h"
34
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/queue.h>
38 #include <sys/socket.h>
39
40 #include <netinet/in.h>
41 #ifdef HAVE_NETINET6_IPSEC
42 # include <netinet6/ipsec.h>
43 #else
44 # include <netinet/ipsec.h>
45 #endif
46
47 #ifdef ENABLE_HYBRID
48 #include <arpa/inet.h>
49 #endif
50
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <errno.h>
55 #include <netdb.h>
56 #include <pwd.h>
57 #include <grp.h>
58
59 #include "var.h"
60 #include "misc.h"
61 #include "vmbuf.h"
62 #include "plog.h"
63 #include "sockmisc.h"
64 #include "str2val.h"
65 #include "genlist.h"
66 #include "debug.h"
67
68 #include "admin.h"
69 #include "privsep.h"
70 #include "cfparse_proto.h"
71 #include "cftoken_proto.h"
72 #include "algorithm.h"
73 #include "localconf.h"
74 #include "policy.h"
75 #include "sainfo.h"
76 #include "oakley.h"
77 #include "pfkey.h"
78 #include "remoteconf.h"
79 #include "grabmyaddr.h"
80 #include "isakmp_var.h"
81 #include "handler.h"
82 #include "isakmp.h"
83 #ifdef ENABLE_HYBRID
84 #include "isakmp_xauth.h"
85 #include "isakmp_cfg.h"
86 #endif
87 #include "ipsec_doi.h"
88 #include "strnames.h"
89 #include "gcmalloc.h"
90 #ifdef HAVE_GSSAPI
91 #include "gssapi.h"
92 #endif
93 #include "vendorid.h"
94 #include "rsalist.h"
95
96
97 static int num2dhgroup[] = {
98 0,
99 OAKLEY_ATTR_GRP_DESC_MODP768,
100 OAKLEY_ATTR_GRP_DESC_MODP1024,
101 OAKLEY_ATTR_GRP_DESC_EC2N155,
102 OAKLEY_ATTR_GRP_DESC_EC2N185,
103 OAKLEY_ATTR_GRP_DESC_MODP1536,
104 0,
105 0,
106 0,
107 0,
108 0,
109 0,
110 0,
111 0,
112 OAKLEY_ATTR_GRP_DESC_MODP2048,
113 OAKLEY_ATTR_GRP_DESC_MODP3072,
114 OAKLEY_ATTR_GRP_DESC_MODP4096,
115 OAKLEY_ATTR_GRP_DESC_MODP6144,
116 OAKLEY_ATTR_GRP_DESC_MODP8192
117 };
118
119 static struct remoteconf *cur_rmconf;
120 static int tmpalgtype[MAXALGCLASS];
121 static struct sainfo *cur_sainfo;
122 static int cur_algclass;
123
124 static struct proposalspec *newprspec __P((void));
125 static void insprspec __P((struct proposalspec *, struct proposalspec **));
126 static struct secprotospec *newspspec __P((void));
127 static void insspspec __P((struct secprotospec *, struct proposalspec **));
128 static void adminsock_conf __P((vchar_t *, vchar_t *, vchar_t *, int));
129
130 static int set_isakmp_proposal
131 __P((struct remoteconf *, struct proposalspec *));
132 static void clean_tmpalgtype __P((void));
133 static int expand_isakmpspec __P((int, int, int *,
134 int, int, time_t, int, int, int, char *, struct remoteconf *));
135 static int listen_addr __P((struct sockaddr *addr, int udp_encap));
136
137 void freeetypes (struct etypes **etypes);
138
139 #if 0
140 static int fix_lifebyte __P((u_long));
141 #endif
142 %}
143
144 %union {
145 unsigned long num;
146 vchar_t *val;
147 struct remoteconf *rmconf;
148 struct sockaddr *saddr;
149 struct sainfoalg *alg;
150 }
151
152 /* privsep */
153 %token PRIVSEP USER GROUP CHROOT
154 /* path */
155 %token PATH PATHTYPE
156 /* include */
157 %token INCLUDE
158 /* self information */
159 %token IDENTIFIER VENDORID
160 /* logging */
161 %token LOGGING LOGLEV
162 /* padding */
163 %token PADDING PAD_RANDOMIZE PAD_RANDOMIZELEN PAD_MAXLEN PAD_STRICT PAD_EXCLTAIL
164 /* listen */
165 %token LISTEN X_ISAKMP X_ISAKMP_NATT X_ADMIN STRICT_ADDRESS ADMINSOCK DISABLED
166 /* modecfg */
167 %token MODECFG CFG_NET4 CFG_MASK4 CFG_DNS4 CFG_NBNS4
168 %token CFG_AUTH_SOURCE CFG_SYSTEM CFG_RADIUS CFG_PAM CFG_LOCAL CFG_NONE
169 %token CFG_ACCOUNTING CFG_CONF_SOURCE CFG_MOTD CFG_POOL_SIZE CFG_AUTH_THROTTLE
170 %token CFG_PFS_GROUP CFG_SAVE_PASSWD
171 /* timer */
172 %token RETRY RETRY_COUNTER RETRY_INTERVAL RETRY_PERSEND
173 %token RETRY_PHASE1 RETRY_PHASE2 NATT_KA AUTO_EXIT_DELAY
174 /* algorithm */
175 %token ALGORITHM_CLASS ALGORITHMTYPE STRENGTHTYPE
176 /* sainfo */
177 %token SAINFO FROM
178 /* remote */
179 %token REMOTE ANONYMOUS INHERIT
180 %token EXCHANGE_MODE EXCHANGETYPE DOI DOITYPE SITUATION SITUATIONTYPE
181 %token CERTIFICATE_TYPE CERTTYPE PEERS_CERTFILE CA_TYPE
182 %token VERIFY_CERT SEND_CERT SEND_CR
183 %token IDENTIFIERTYPE MY_IDENTIFIER PEERS_IDENTIFIER VERIFY_IDENTIFIER
184 %token SHARED_SECRET SECRETTYPE
185 %token OPEN_DIR_AUTH_GROUP IN_KEYCHAIN
186 %token CERTIFICATE_VERIFICATION VERIFICATION_MODULE VERIFICATION_OPTION
187 %token DNSSEC CERT_X509 CERT_PLAINRSA
188 %token NONCE_SIZE DH_GROUP KEEPALIVE PASSIVE INITIAL_CONTACT
189 %token NAT_TRAVERSAL NAT_TRAVERSAL_LEVEL NAT_TRAVERSAL_MULTI_USER
190 %token PROPOSAL_CHECK PROPOSAL_CHECK_LEVEL
191 %token GENERATE_POLICY SUPPORT_PROXY
192 %token PROPOSAL
193 %token EXEC_PATH EXEC_COMMAND EXEC_SUCCESS EXEC_FAILURE
194 %token GSS_ID GSS_ID_ENC GSS_ID_ENCTYPE
195 %token COMPLEX_BUNDLE
196 %token DPD DPD_DELAY DPD_RETRY DPD_MAXFAIL
197 %token XAUTH_LOGIN
198
199 %token PREFIX PORT PORTANY UL_PROTO ANY IKE_FRAG ESP_FRAG MODE_CFG
200 %token PFS_GROUP LIFETIME LIFETYPE_TIME LIFETYPE_BYTE STRENGTH
201
202 %token SCRIPT PHASE1_UP PHASE1_DOWN
203
204 %token NUMBER SWITCH BOOLEAN
205 %token HEXSTRING QUOTEDSTRING ADDRSTRING
206 %token UNITTYPE_BYTE UNITTYPE_KBYTES UNITTYPE_MBYTES UNITTYPE_TBYTES
207 %token UNITTYPE_SEC UNITTYPE_MIN UNITTYPE_HOUR
208 %token EOS BOC EOC COMMA
209
210 %type <num> NUMBER BOOLEAN SWITCH keylength
211 %type <num> PATHTYPE IDENTIFIERTYPE LOGLEV GSS_ID_ENCTYPE
212 %type <num> SECRETTYPE
213 %type <num> ALGORITHM_CLASS dh_group_num
214 %type <num> ALGORITHMTYPE STRENGTHTYPE
215 %type <num> PREFIX prefix PORT port ike_port
216 %type <num> ul_proto UL_PROTO
217 %type <num> EXCHANGETYPE DOITYPE SITUATIONTYPE
218 %type <num> CERTTYPE CERT_X509 CERT_PLAINRSA PROPOSAL_CHECK_LEVEL NAT_TRAVERSAL_LEVEL
219 %type <num> VERIFICATION_MODULE VERIFICATION_OPTION
220 %type <num> unittype_time unittype_byte
221 %type <val> QUOTEDSTRING HEXSTRING ADDRSTRING sainfo_id
222 %type <val> identifierstring
223 %type <saddr> remote_index ike_addrinfo_port
224 %type <alg> algorithm
225
226 %%
227
228 statements
229 : /* nothing */
230 | statements statement
231 ;
232 statement
233 : privsep_statement
234 | path_statement
235 | include_statement
236 | gssenc_statement
237 | identifier_statement
238 | logging_statement
239 | padding_statement
240 | listen_statement
241 | modecfg_statement
242 | timer_statement
243 | sainfo_statement
244 | remote_statement
245 | special_statement
246 ;
247
248 /* privsep */
249 privsep_statement
250 : PRIVSEP BOC privsep_stmts EOC
251 ;
252 privsep_stmts
253 : /* nothing */
254 | privsep_stmts privsep_stmt
255 ;
256 privsep_stmt
257 : USER QUOTEDSTRING
258 {
259 struct passwd *pw;
260
261 if ((pw = getpwnam($2->v)) == NULL) {
262 yyerror("unkown user \"%s\"", $2->v);
263 return -1;
264 }
265 lcconf->uid = pw->pw_uid;
266 }
267 EOS
268 | USER NUMBER { lcconf->uid = $2; } EOS
269 | GROUP QUOTEDSTRING
270 {
271 struct group *gr;
272
273 if ((gr = getgrnam($2->v)) == NULL) {
274 yyerror("unkown group \"%s\"", $2->v);
275 return -1;
276 }
277 lcconf->gid = gr->gr_gid;
278 }
279 EOS
280 | GROUP NUMBER { lcconf->gid = $2; } EOS
281 | CHROOT QUOTEDSTRING { lcconf->chroot = $2->v; } EOS
282 ;
283
284 /* path */
285 path_statement
286 : PATH PATHTYPE QUOTEDSTRING
287 {
288 if ($2 >= LC_PATHTYPE_MAX) {
289 yyerror("invalid path type %d", $2);
290 return -1;
291 }
292
293 /* free old pathinfo */
294 if (lcconf->pathinfo[$2])
295 racoon_free(lcconf->pathinfo[$2]);
296
297 /* set new pathinfo */
298 lcconf->pathinfo[$2] = strdup($3->v);
299 vfree($3);
300 }
301 EOS
302 ;
303
304 /* special */
305 special_statement
306 : COMPLEX_BUNDLE SWITCH { lcconf->complex_bundle = $2; } EOS
307 ;
308
309 /* include */
310 include_statement
311 : INCLUDE QUOTEDSTRING EOS
312 {
313 char path[MAXPATHLEN];
314
315 getpathname(path, sizeof(path),
316 LC_PATHTYPE_INCLUDE, $2->v);
317 vfree($2);
318 if (yycf_switch_buffer(path) != 0)
319 return -1;
320 }
321 ;
322
323 /* gss_id_enc */
324 gssenc_statement
325 : GSS_ID_ENC GSS_ID_ENCTYPE EOS
326 {
327 if ($2 >= LC_GSSENC_MAX) {
328 yyerror("invalid GSS ID encoding %d", $2);
329 return -1;
330 }
331 lcconf->gss_id_enc = $2;
332 }
333 ;
334
335 /* self infomation */
336 identifier_statement
337 : IDENTIFIER identifier_stmt
338 ;
339 identifier_stmt
340 : VENDORID
341 {
342 /*XXX to be deleted */
343 }
344 QUOTEDSTRING EOS
345 | IDENTIFIERTYPE QUOTEDSTRING
346 {
347 /*XXX to be deleted */
348 $2->l--; /* nuke '\0' */
349 lcconf->ident[$1] = $2;
350 if (lcconf->ident[$1] == NULL) {
351 yyerror("failed to set my ident: %s",
352 strerror(errno));
353 return -1;
354 }
355 }
356 EOS
357 ;
358
359 /* logging */
360 logging_statement
361 : LOGGING log_level EOS
362 ;
363 log_level
364 : HEXSTRING
365 {
366 /*
367 * XXX ignore it because this specification
368 * will be obsoleted.
369 */
370 yywarn("see racoon.conf(5), such a log specification will be obsoleted.");
371 vfree($1);
372 }
373 | LOGLEV
374 {
375 /*
376 * set the loglevel by configuration file only when
377 * the command line did not specify any loglevel.
378 */
379 if (loglevel <= LLV_BASE)
380 loglevel += $1;
381 }
382 ;
383
384 /* padding */
385 padding_statement
386 : PADDING BOC padding_stmts EOC
387 ;
388 padding_stmts
389 : /* nothing */
390 | padding_stmts padding_stmt
391 ;
392 padding_stmt
393 : PAD_RANDOMIZE SWITCH { lcconf->pad_random = $2; } EOS
394 | PAD_RANDOMIZELEN SWITCH { lcconf->pad_randomlen = $2; } EOS
395 | PAD_MAXLEN NUMBER { lcconf->pad_maxsize = $2; } EOS
396 | PAD_STRICT SWITCH { lcconf->pad_strict = $2; } EOS
397 | PAD_EXCLTAIL SWITCH { lcconf->pad_excltail = $2; } EOS
398 ;
399
400 /* listen */
401 listen_statement
402 : LISTEN BOC listen_stmts EOC
403 ;
404 listen_stmts
405 : /* nothing */
406 | listen_stmts listen_stmt
407 ;
408 listen_stmt
409 : X_ISAKMP ike_addrinfo_port
410 {
411 listen_addr ($2, 0);
412 }
413 EOS
414 | X_ISAKMP_NATT ike_addrinfo_port
415 {
416 #ifdef ENABLE_NATT
417 listen_addr ($2, 1);
418 #else
419 yyerror("NAT-T support not compiled in.");
420 #endif
421 }
422 EOS
423 | X_ADMIN
424 {
425 yyerror("admin directive is obsoleted.");
426 }
427 PORT EOS
428 | ADMINSOCK QUOTEDSTRING QUOTEDSTRING QUOTEDSTRING NUMBER
429 {
430 #ifdef ENABLE_ADMINPORT
431 adminsock_conf($2, $3, $4, $5);
432 #else
433 yywarn("admin port support not compiled in");
434 #endif
435 }
436 EOS
437 | ADMINSOCK QUOTEDSTRING
438 {
439 #ifdef ENABLE_ADMINPORT
440 adminsock_conf($2, NULL, NULL, -1);
441 #else
442 yywarn("admin port support not compiled in");
443 #endif
444 }
445 EOS
446 | ADMINSOCK DISABLED
447 {
448 #ifdef ENABLE_ADMINPORT
449 adminsock_path = NULL;
450 #else
451 yywarn("admin port support not compiled in");
452 #endif
453 }
454 EOS
455 | STRICT_ADDRESS { lcconf->strict_address = TRUE; } EOS
456 ;
457 ike_addrinfo_port
458 : ADDRSTRING ike_port
459 {
460 char portbuf[10];
461
462 snprintf(portbuf, sizeof(portbuf), "%ld", $2);
463 $$ = str2saddr($1->v, portbuf);
464 vfree($1);
465 if (!$$)
466 return -1;
467 }
468 ;
469 ike_port
470 : /* nothing */ { $$ = PORT_ISAKMP; }
471 | PORT { $$ = $1; }
472 ;
473 /* modecfg */
474 modecfg_statement
475 : MODECFG BOC modecfg_stmts EOC
476 ;
477 modecfg_stmts
478 : /* nothing */
479 | modecfg_stmts modecfg_stmt
480 ;
481 modecfg_stmt
482 : CFG_NET4 ADDRSTRING
483 {
484 #ifdef ENABLE_HYBRID
485 if (inet_pton(AF_INET, $2->v,
486 &isakmp_cfg_config.network4) != 1)
487 yyerror("bad IPv4 network address.");
488 #else
489 yyerror("racoon not configured with --enable-hybrid");
490 #endif
491 }
492 EOS
493 | CFG_MASK4 ADDRSTRING
494 {
495 #ifdef ENABLE_HYBRID
496 if (inet_pton(AF_INET, $2->v,
497 &isakmp_cfg_config.netmask4) != 1)
498 yyerror("bad IPv4 netmask address.");
499 #else
500 yyerror("racoon not configured with --enable-hybrid");
501 #endif
502 }
503 EOS
504 | CFG_DNS4 ADDRSTRING
505 {
506 #ifdef ENABLE_HYBRID
507 if (inet_pton(AF_INET, $2->v,
508 &isakmp_cfg_config.dns4) != 1)
509 yyerror("bad IPv4 DNS address.");
510 #else
511 yyerror("racoon not configured with --enable-hybrid");
512 #endif
513 }
514 EOS
515 | CFG_NBNS4 ADDRSTRING
516 {
517 #ifdef ENABLE_HYBRID
518 if (inet_pton(AF_INET, $2->v,
519 &isakmp_cfg_config.nbns4) != 1)
520 yyerror("bad IPv4 WINS address.");
521 #else
522 yyerror("racoon not configured with --enable-hybrid");
523 #endif
524 }
525 EOS
526 | CFG_AUTH_SOURCE CFG_SYSTEM
527 {
528 #ifdef ENABLE_HYBRID
529 isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_SYSTEM;
530 #else
531 yyerror("racoon not configured with --enable-hybrid");
532 #endif
533 }
534 EOS
535 | CFG_AUTH_SOURCE CFG_RADIUS
536 {
537 #ifdef ENABLE_HYBRID
538 #ifdef HAVE_LIBRADIUS
539 isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_RADIUS;
540 #else /* HAVE_LIBRADIUS */
541 yyerror("racoon not configured with --with-libradius");
542 #endif /* HAVE_LIBRADIUS */
543 #else /* ENABLE_HYBRID */
544 yyerror("racoon not configured with --enable-hybrid");
545 #endif /* ENABLE_HYBRID */
546 }
547 EOS
548 | CFG_AUTH_SOURCE CFG_PAM
549 {
550 #ifdef ENABLE_HYBRID
551 #ifdef HAVE_LIBPAM
552 isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_PAM;
553 #else /* HAVE_LIBPAM */
554 yyerror("racoon not configured with --with-libpam");
555 #endif /* HAVE_LIBPAM */
556 #else /* ENABLE_HYBRID */
557 yyerror("racoon not configured with --enable-hybrid");
558 #endif /* ENABLE_HYBRID */
559 }
560 EOS
561 | CFG_ACCOUNTING CFG_NONE
562 {
563 #ifdef ENABLE_HYBRID
564 isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_NONE;
565 #else
566 yyerror("racoon not configured with --enable-hybrid");
567 #endif
568 }
569 EOS
570 | CFG_ACCOUNTING CFG_RADIUS
571 {
572 #ifdef ENABLE_HYBRID
573 #ifdef HAVE_LIBRADIUS
574 isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_RADIUS;
575 #else /* HAVE_LIBRADIUS */
576 yyerror("racoon not configured with --with-libradius");
577 #endif /* HAVE_LIBRADIUS */
578 #else /* ENABLE_HYBRID */
579 yyerror("racoon not configured with --enable-hybrid");
580 #endif /* ENABLE_HYBRID */
581 }
582 EOS
583 | CFG_ACCOUNTING CFG_PAM
584 {
585 #ifdef ENABLE_HYBRID
586 #ifdef HAVE_LIBPAM
587 isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_PAM;
588 #else /* HAVE_LIBPAM */
589 yyerror("racoon not configured with --with-libpam");
590 #endif /* HAVE_LIBPAM */
591 #else /* ENABLE_HYBRID */
592 yyerror("racoon not configured with --enable-hybrid");
593 #endif /* ENABLE_HYBRID */
594 }
595 EOS
596 | CFG_POOL_SIZE NUMBER
597 {
598 #ifdef ENABLE_HYBRID
599 size_t len;
600
601 isakmp_cfg_config.pool_size = $2;
602
603 len = $2 * sizeof(*isakmp_cfg_config.port_pool);
604 isakmp_cfg_config.port_pool = racoon_malloc(len);
605 if (isakmp_cfg_config.port_pool == NULL)
606 yyerror("cannot allocate memory for pool");
607 bzero(isakmp_cfg_config.port_pool, len);
608 #else /* ENABLE_HYBRID */
609 yyerror("racoon not configured with --enable-hybrid");
610 #endif /* ENABLE_HYBRID */
611 }
612 EOS
613 | CFG_PFS_GROUP NUMBER
614 {
615 #ifdef ENABLE_HYBRID
616 isakmp_cfg_config.pfs_group = $2;
617 #else /* ENABLE_HYBRID */
618 yyerror("racoon not configured with --enable-hybrid");
619 #endif /* ENABLE_HYBRID */
620 }
621 EOS
622 | CFG_SAVE_PASSWD SWITCH
623 {
624 #ifdef ENABLE_HYBRID
625 isakmp_cfg_config.save_passwd = $2;
626 #else /* ENABLE_HYBRID */
627 yyerror("racoon not configured with --enable-hybrid");
628 #endif /* ENABLE_HYBRID */
629 }
630 EOS
631 | CFG_AUTH_THROTTLE NUMBER
632 {
633 #ifdef ENABLE_HYBRID
634 isakmp_cfg_config.auth_throttle = $2;
635 #else /* ENABLE_HYBRID */
636 yyerror("racoon not configured with --enable-hybrid");
637 #endif /* ENABLE_HYBRID */
638 }
639 EOS
640 | CFG_CONF_SOURCE CFG_LOCAL
641 {
642 #ifdef ENABLE_HYBRID
643 isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LOCAL;
644 #else /* ENABLE_HYBRID */
645 yyerror("racoon not configured with --enable-hybrid");
646 #endif /* ENABLE_HYBRID */
647 }
648 EOS
649 | CFG_CONF_SOURCE CFG_RADIUS
650 {
651 #ifdef ENABLE_HYBRID
652 #ifdef HAVE_LIBRADIUS
653 isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_RADIUS;
654 #else /* HAVE_LIBRADIUS */
655 yyerror("racoon not configured with --with-libradius");
656 #endif /* HAVE_LIBRADIUS */
657 #else /* ENABLE_HYBRID */
658 yyerror("racoon not configured with --enable-hybrid");
659 #endif /* ENABLE_HYBRID */
660 }
661 EOS
662 | CFG_MOTD QUOTEDSTRING
663 {
664 #ifdef ENABLE_HYBRID
665 strncpy(&isakmp_cfg_config.motd[0], $2->v, MAXPATHLEN);
666 isakmp_cfg_config.motd[MAXPATHLEN] = '\0';
667 vfree($2);
668 #else
669 yyerror("racoon not configured with --enable-hybrid");
670 #endif
671 }
672 EOS
673 ;
674
675 /* timer */
676 timer_statement
677 : RETRY BOC timer_stmts EOC
678 ;
679 timer_stmts
680 : /* nothing */
681 | timer_stmts timer_stmt
682 ;
683 timer_stmt
684 : RETRY_COUNTER NUMBER
685 {
686 lcconf->retry_counter = $2;
687 }
688 EOS
689 | RETRY_INTERVAL NUMBER unittype_time
690 {
691 lcconf->retry_interval = $2 * $3;
692 }
693 EOS
694 | RETRY_PERSEND NUMBER
695 {
696 lcconf->count_persend = $2;
697 }
698 EOS
699 | RETRY_PHASE1 NUMBER unittype_time
700 {
701 lcconf->retry_checkph1 = $2 * $3;
702 }
703 EOS
704 | RETRY_PHASE2 NUMBER unittype_time
705 {
706 lcconf->wait_ph2complete = $2 * $3;
707 }
708 EOS
709 | AUTO_EXIT_DELAY NUMBER unittype_time
710 {
711 lcconf->auto_exit_delay = $2 * $3;
712 lcconf->auto_exit_state |= LC_AUTOEXITSTATE_SET;
713 }
714 EOS
715
716 | NATT_KA NUMBER unittype_time
717 {
718 #ifdef ENABLE_NATT
719 lcconf->natt_ka_interval = $2 * $3;
720 #else
721 yyerror("NAT-T support not compiled in.");
722 #endif
723 }
724 EOS
725 ;
726
727 /* sainfo */
728 sainfo_statement
729 : SAINFO
730 {
731 cur_sainfo = newsainfo();
732 if (cur_sainfo == NULL) {
733 yyerror("failed to allocate sainfo");
734 return -1;
735 }
736 }
737 sainfo_name sainfo_peer BOC sainfo_specs
738 {
739 struct sainfo *check;
740
741 /* default */
742 if (cur_sainfo->algs[algclass_ipsec_enc] == 0) {
743 yyerror("no encryption algorithm at %s",
744 sainfo2str(cur_sainfo));
745 return -1;
746 }
747 if (cur_sainfo->algs[algclass_ipsec_auth] == 0) {
748 yyerror("no authentication algorithm at %s",
749 sainfo2str(cur_sainfo));
750 return -1;
751 }
752 if (cur_sainfo->algs[algclass_ipsec_comp] == 0) {
753 yyerror("no compression algorithm at %s",
754 sainfo2str(cur_sainfo));
755 return -1;
756 }
757
758 /* duplicate check */
759 check = getsainfo(cur_sainfo->idsrc,
760 cur_sainfo->iddst,
761 cur_sainfo->id_i);
762 if (check && (!check->idsrc && !cur_sainfo->idsrc)) {
763 yyerror("duplicated sainfo: %s",
764 sainfo2str(cur_sainfo));
765 return -1;
766 }
767 inssainfo(cur_sainfo);
768 }
769 EOC
770 ;
771 sainfo_name
772 : ANONYMOUS
773 {
774 cur_sainfo->idsrc = NULL;
775 cur_sainfo->iddst = NULL;
776 }
777 | sainfo_id sainfo_id
778 {
779 cur_sainfo->idsrc = $1;
780 cur_sainfo->iddst = $2;
781 }
782 ;
783 sainfo_id
784 : IDENTIFIERTYPE ADDRSTRING prefix port ul_proto
785 {
786 char portbuf[10];
787 struct sockaddr *saddr;
788
789 if (($5 == IPPROTO_ICMP || $5 == IPPROTO_ICMPV6)
790 && ($4 != IPSEC_PORT_ANY || $4 != IPSEC_PORT_ANY)) {
791 yyerror("port number must be \"any\".");
792 return -1;
793 }
794
795 snprintf(portbuf, sizeof(portbuf), "%lu", $4);
796 saddr = str2saddr($2->v, portbuf);
797 vfree($2);
798 if (saddr == NULL)
799 return -1;
800
801 switch (saddr->sa_family) {
802 case AF_INET:
803 if ($5 == IPPROTO_ICMPV6) {
804 yyerror("upper layer protocol mismatched.\n");
805 racoon_free(saddr);
806 return -1;
807 }
808 $$ = ipsecdoi_sockaddr2id(saddr,
809 #if 0
810 $3 == (sizeof(struct in_addr) << 3) &&
811 $1 == IDTYPE_ADDRESS
812 ? ~0 : $3,
813 #else
814 $3 == ~0 ? (sizeof(struct in_addr) << 3): $3,
815 #endif
816 $5);
817 break;
818 #ifdef INET6
819 case AF_INET6:
820 if ($5 == IPPROTO_ICMP) {
821 yyerror("upper layer protocol mismatched.\n");
822 racoon_free(saddr);
823 return -1;
824 }
825 $$ = ipsecdoi_sockaddr2id(saddr,
826 #if 0
827 $3 == (sizeof(struct in6_addr) << 3) &&
828 $1 == IDTYPE_ADDRESS
829 ? ~0 : $3,
830 #else
831 $3 == ~0 ? (sizeof(struct in6_addr) << 3): $3,
832 #endif
833 $5);
834 break;
835 #endif
836 default:
837 yyerror("invalid family: %d", saddr->sa_family);
838 $$ = NULL;
839 break;
840 }
841 racoon_free(saddr);
842 if ($$ == NULL)
843 return -1;
844 }
845 | IDENTIFIERTYPE QUOTEDSTRING
846 {
847 struct ipsecdoi_id_b *id_b;
848
849 if ($1 == IDTYPE_ASN1DN) {
850 yyerror("id type forbidden: %d", $1);
851 $$ = NULL;
852 return -1;
853 }
854
855 $2->l--;
856
857 $$ = vmalloc(sizeof(*id_b) + $2->l);
858 if ($$ == NULL) {
859 yyerror("failed to allocate identifier");
860 return -1;
861 }
862
863 id_b = (struct ipsecdoi_id_b *)$$->v;
864 id_b->type = idtype2doi($1);
865
866 id_b->proto_id = 0;
867 id_b->port = 0;
868
869 memcpy($$->v + sizeof(*id_b), $2->v, $2->l);
870 }
871 ;
872 sainfo_peer
873 : /* nothing */
874 {
875 cur_sainfo->id_i = NULL;
876 }
877
878 | FROM IDENTIFIERTYPE identifierstring
879 {
880 struct ipsecdoi_id_b *id_b;
881 vchar_t *idv;
882
883 if (set_identifier(&idv, $2, $3) != 0) {
884 yyerror("failed to set identifer.\n");
885 return -1;
886 }
887 cur_sainfo->id_i = vmalloc(sizeof(*id_b) + idv->l);
888 if (cur_sainfo->id_i == NULL) {
889 yyerror("failed to allocate identifier");
890 return -1;
891 }
892
893 id_b = (struct ipsecdoi_id_b *)cur_sainfo->id_i->v;
894 id_b->type = idtype2doi($2);
895
896 id_b->proto_id = 0;
897 id_b->port = 0;
898
899 memcpy(cur_sainfo->id_i->v + sizeof(*id_b),
900 idv->v, idv->l);
901 vfree(idv);
902 }
903 ;
904 sainfo_specs
905 : /* nothing */
906 | sainfo_specs sainfo_spec
907 ;
908 sainfo_spec
909 : PFS_GROUP dh_group_num
910 {
911 cur_sainfo->pfs_group = $2;
912 }
913 EOS
914 | LIFETIME LIFETYPE_TIME NUMBER unittype_time
915 {
916 cur_sainfo->lifetime = $3 * $4;
917 }
918 EOS
919 | LIFETIME LIFETYPE_BYTE NUMBER unittype_byte
920 {
921 #if 1
922 yyerror("byte lifetime support is deprecated");
923 return -1;
924 #else
925 cur_sainfo->lifebyte = fix_lifebyte($3 * $4);
926 if (cur_sainfo->lifebyte == 0)
927 return -1;
928 #endif
929 }
930 EOS
931 | ALGORITHM_CLASS {
932 cur_algclass = $1;
933 }
934 algorithms EOS
935 | IDENTIFIER IDENTIFIERTYPE
936 {
937 yyerror("it's deprecated to specify a identifier in phase 2");
938 }
939 EOS
940 | MY_IDENTIFIER IDENTIFIERTYPE QUOTEDSTRING
941 {
942 yyerror("it's deprecated to specify a identifier in phase 2");
943 }
944 EOS
945 ;
946
947 algorithms
948 : algorithm
949 {
950 inssainfoalg(&cur_sainfo->algs[cur_algclass], $1);
951 }
952 | algorithm
953 {
954 inssainfoalg(&cur_sainfo->algs[cur_algclass], $1);
955 }
956 COMMA algorithms
957 ;
958 algorithm
959 : ALGORITHMTYPE keylength
960 {
961 int defklen;
962
963 $$ = newsainfoalg();
964 if ($$ == NULL) {
965 yyerror("failed to get algorithm allocation");
966 return -1;
967 }
968
969 $$->alg = algtype2doi(cur_algclass, $1);
970 if ($$->alg == -1) {
971 yyerror("algorithm mismatched");
972 racoon_free($$);
973 $$ = NULL;
974 return -1;
975 }
976
977 defklen = default_keylen(cur_algclass, $1);
978 if (defklen == 0) {
979 if ($2) {
980 yyerror("keylen not allowed");
981 racoon_free($$);
982 $$ = NULL;
983 return -1;
984 }
985 } else {
986 if ($2 && check_keylen(cur_algclass, $1, $2) < 0) {
987 yyerror("invalid keylen %d", $2);
988 racoon_free($$);
989 $$ = NULL;
990 return -1;
991 }
992 }
993
994 if ($2)
995 $$->encklen = $2;
996 else
997 $$->encklen = defklen;
998
999 /* check if it's supported algorithm by kernel */
1000 if (!(cur_algclass == algclass_ipsec_auth && $1 == algtype_non_auth)
1001 && pk_checkalg(cur_algclass, $1, $$->encklen)) {
1002 int a = algclass2doi(cur_algclass);
1003 int b = algtype2doi(cur_algclass, $1);
1004 if (a == IPSECDOI_ATTR_AUTH)
1005 a = IPSECDOI_PROTO_IPSEC_AH;
1006 yyerror("algorithm %s not supported by the kernel (missing module?)",
1007 s_ipsecdoi_trns(a, b));
1008 racoon_free($$);
1009 $$ = NULL;
1010 return -1;
1011 }
1012 }
1013 ;
1014 prefix
1015 : /* nothing */ { $$ = ~0; }
1016 | PREFIX { $$ = $1; }
1017 ;
1018 port
1019 : /* nothing */ { $$ = IPSEC_PORT_ANY; }
1020 | PORT { $$ = $1; }
1021 | PORTANY { $$ = IPSEC_PORT_ANY; }
1022 ;
1023 ul_proto
1024 : NUMBER { $$ = $1; }
1025 | UL_PROTO { $$ = $1; }
1026 | ANY { $$ = IPSEC_ULPROTO_ANY; }
1027 ;
1028 keylength
1029 : /* nothing */ { $$ = 0; }
1030 | NUMBER { $$ = $1; }
1031 ;
1032
1033 /* remote */
1034 remote_statement
1035 : REMOTE remote_index INHERIT remote_index
1036 {
1037 struct remoteconf *new;
1038 struct proposalspec *prspec;
1039
1040 new = copyrmconf($4);
1041 if (new == NULL) {
1042 yyerror("failed to get remoteconf for %s.", saddr2str ($4));
1043 return -1;
1044 }
1045
1046 new->remote = $2;
1047 new->inherited_from = getrmconf_strict($4, 1);
1048 new->proposal = NULL;
1049 new->prhead = NULL;
1050 cur_rmconf = new;
1051
1052 prspec = newprspec();
1053 if (prspec == NULL || !cur_rmconf->inherited_from
1054 || !cur_rmconf->inherited_from->proposal)
1055 return -1;
1056 prspec->lifetime = cur_rmconf->inherited_from->proposal->lifetime;
1057 prspec->lifebyte = cur_rmconf->inherited_from->proposal->lifebyte;
1058 insprspec(prspec, &cur_rmconf->prhead);
1059 }
1060 remote_specs_block
1061 | REMOTE remote_index
1062 {
1063 struct remoteconf *new;
1064 struct proposalspec *prspec;
1065
1066 new = newrmconf();
1067 if (new == NULL) {
1068 yyerror("failed to get new remoteconf.");
1069 return -1;
1070 }
1071
1072 new->remote = $2;
1073 cur_rmconf = new;
1074
1075 prspec = newprspec();
1076 if (prspec == NULL)
1077 return -1;
1078 prspec->lifetime = oakley_get_defaultlifetime();
1079 insprspec(prspec, &cur_rmconf->prhead);
1080 }
1081 remote_specs_block
1082 ;
1083
1084 remote_specs_block
1085 : BOC remote_specs EOC
1086 {
1087 /* check a exchange mode */
1088 if (cur_rmconf->etypes == NULL) {
1089 yyerror("no exchange mode specified.\n");
1090 return -1;
1091 }
1092
1093 if (cur_rmconf->idvtype == IDTYPE_UNDEFINED)
1094 cur_rmconf->idvtype = IDTYPE_ADDRESS;
1095
1096
1097 if (cur_rmconf->idvtype == IDTYPE_ASN1DN) {
1098 if (cur_rmconf->mycertfile
1099 #ifdef __APPLE__
1100 || cur_rmconf->identity_in_keychain)
1101 #endif
1102 {
1103 if (cur_rmconf->idv)
1104 yywarn("Both CERT and ASN1 ID "
1105 "are set. Hope this is OK.\n");
1106 /* TODO: Preparse the DN here */
1107 } else if (cur_rmconf->idv) {
1108 /* OK, using asn1dn without X.509. */
1109 } else {
1110 yyerror("ASN1 ID not specified "
1111 "and no CERT defined!\n");
1112 return -1;
1113 }
1114 }
1115
1116 #ifdef __APPLE__
1117 if (cur_rmconf->cert_verification_option == VERIFICATION_OPTION_PEERS_IDENTIFIER) {
1118 struct genlist_entry *gpb;
1119 if (genlist_next(cur_rmconf->idvl_p, &gpb) == NULL) {
1120 yyerror("peers_identifier required for specified certificate "
1121 "verification option.\n");
1122 return -1;
1123 }
1124 }
1125 #endif
1126
1127 if (cur_rmconf->prhead->spspec == NULL
1128 && cur_rmconf->inherited_from
1129 && cur_rmconf->inherited_from->prhead) {
1130 cur_rmconf->prhead->spspec = cur_rmconf->inherited_from->prhead->spspec;
1131 }
1132 if (set_isakmp_proposal(cur_rmconf, cur_rmconf->prhead) != 0)
1133 return -1;
1134
1135 /* DH group settting if aggressive mode is there. */
1136 if (check_etypeok(cur_rmconf, ISAKMP_ETYPE_AGG) != NULL) {
1137 struct isakmpsa *p;
1138 int b = 0;
1139
1140 /* DH group */
1141 for (p = cur_rmconf->proposal; p; p = p->next) {
1142 if (b == 0 || (b && b == p->dh_group)) {
1143 b = p->dh_group;
1144 continue;
1145 }
1146 yyerror("DH group must be equal "
1147 "in all proposals "
1148 "when aggressive mode is "
1149 "used.\n");
1150 return -1;
1151 }
1152 cur_rmconf->dh_group = b;
1153
1154 if (cur_rmconf->dh_group == 0) {
1155 yyerror("DH group must be set in the proposal.\n");
1156 return -1;
1157 }
1158
1159 /* DH group settting if PFS is required. */
1160 if (oakley_setdhgroup(cur_rmconf->dh_group,
1161 &cur_rmconf->dhgrp) < 0) {
1162 yyerror("failed to set DH value.\n");
1163 return -1;
1164 }
1165 }
1166
1167 insrmconf(cur_rmconf);
1168 }
1169 ;
1170 remote_index
1171 : ANONYMOUS ike_port
1172 {
1173 $$ = newsaddr(sizeof(struct sockaddr));
1174 $$->sa_family = AF_UNSPEC;
1175 ((struct sockaddr_in *)$$)->sin_port = htons($2);
1176 }
1177 | ike_addrinfo_port
1178 {
1179 $$ = $1;
1180 if ($$ == NULL) {
1181 yyerror("failed to allocate sockaddr");
1182 return -1;
1183 }
1184 }
1185 ;
1186 remote_specs
1187 : /* nothing */
1188 | remote_specs remote_spec
1189 ;
1190 remote_spec
1191 : EXCHANGE_MODE
1192 {
1193 cur_rmconf->etypes = NULL;
1194 }
1195 exchange_types EOS
1196 | DOI DOITYPE { cur_rmconf->doitype = $2; } EOS
1197 | SITUATION SITUATIONTYPE { cur_rmconf->sittype = $2; } EOS
1198 | CERTIFICATE_TYPE cert_spec
1199 | PEERS_CERTFILE QUOTEDSTRING
1200 {
1201 yywarn("This directive without certtype will be removed!\n");
1202 yywarn("Please use 'peers_certfile x509 \"%s\";' instead\n", $2->v);
1203 cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
1204 cur_rmconf->peerscertfile = strdup($2->v);
1205 vfree($2);
1206 }
1207 EOS
1208 | CA_TYPE CERT_X509 QUOTEDSTRING
1209 {
1210 cur_rmconf->cacerttype = $2;
1211 cur_rmconf->getcacert_method = ISAKMP_GETCERT_LOCALFILE;
1212 cur_rmconf->cacertfile = strdup($3->v);
1213 vfree($3);
1214 }
1215 EOS
1216 | PEERS_CERTFILE CERT_X509 QUOTEDSTRING
1217 {
1218 cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
1219 cur_rmconf->peerscertfile = strdup($3->v);
1220 vfree($3);
1221 }
1222 EOS
1223 | PEERS_CERTFILE CERT_PLAINRSA QUOTEDSTRING
1224 {
1225 char path[MAXPATHLEN];
1226 int ret = 0;
1227
1228 getpathname(path, sizeof(path),
1229 LC_PATHTYPE_CERT, $3->v);
1230 vfree($3);
1231
1232 if (cur_rmconf->getcert_method == ISAKMP_GETCERT_DNS) {
1233 yyerror("Different peers_certfile method "
1234 "already defined: %d!\n",
1235 cur_rmconf->getcert_method);
1236 return -1;
1237 }
1238 cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
1239 if (rsa_parse_file(cur_rmconf->rsa_public, path, RSA_TYPE_PUBLIC)) {
1240 yyerror("Couldn't parse keyfile.\n", path);
1241 return -1;
1242 }
1243 plog(LLV_DEBUG, LOCATION, NULL, "Public PlainRSA keyfile parsed: %s\n", path);
1244 }
1245 EOS
1246 | PEERS_CERTFILE DNSSEC
1247 {
1248 if (cur_rmconf->getcert_method) {
1249 yyerror("Different peers_certfile method already defined!\n");
1250 return -1;
1251 }
1252 cur_rmconf->getcert_method = ISAKMP_GETCERT_DNS;
1253 cur_rmconf->peerscertfile = NULL;
1254 }
1255 EOS
1256 | VERIFY_CERT SWITCH { cur_rmconf->verify_cert = $2; } EOS
1257 | SEND_CERT SWITCH { cur_rmconf->send_cert = $2; } EOS
1258 | SEND_CR SWITCH { cur_rmconf->send_cr = $2; } EOS
1259 | CERTIFICATE_VERIFICATION VERIFICATION_MODULE
1260 {
1261 #ifdef __APPLE__
1262 cur_rmconf->cert_verification = $2;
1263 #else
1264 yyerror("Apple specific features not compiled in.");
1265 return -1;
1266 #endif
1267 } EOS
1268 | CERTIFICATE_VERIFICATION VERIFICATION_MODULE VERIFICATION_OPTION
1269 {
1270 #ifdef __APPLE__
1271 cur_rmconf->cert_verification = $2;
1272 cur_rmconf->cert_verification_option = $3;
1273 #else
1274 yyerror("Apple specific features not compiled in.");
1275 return -1;
1276 #endif
1277 }
1278 EOS
1279 | OPEN_DIR_AUTH_GROUP QUOTEDSTRING
1280 {
1281 #ifdef __APPLE__
1282 cur_rmconf->open_dir_auth_group = $2;
1283 #else
1284 yyerror("Apple specific features not compiled in.");
1285 return -1;
1286 #endif
1287 } EOS
1288 | MY_IDENTIFIER IDENTIFIERTYPE identifierstring
1289 {
1290 if (set_identifier(&cur_rmconf->idv, $2, $3) != 0) {
1291 yyerror("failed to set identifer.\n");
1292 vfree($3); //%%% BUG FIX - memory leak
1293 return -1;
1294 }
1295 vfree($3); //%%% BUG FIX - memory leak
1296 cur_rmconf->idvtype = $2;
1297 }
1298 EOS
1299 | XAUTH_LOGIN identifierstring
1300 {
1301 #ifdef ENABLE_HYBRID
1302 /* formerly identifier type login */
1303 cur_rmconf->idvtype = IDTYPE_LOGIN;
1304 if (set_identifier(&cur_rmconf->idv, IDTYPE_LOGIN, $2) != 0) {
1305 yyerror("failed to set identifer.\n");
1306 return -1;
1307 }
1308 /* cur_rmconf->use_xauth = 1; */
1309 #else
1310 yyerror("racoon not configured with --enable-hybrid");
1311 #endif
1312 }
1313 EOS
1314 | PEERS_IDENTIFIER IDENTIFIERTYPE identifierstring
1315 {
1316 struct idspec *id;
1317 id = newidspec();
1318 if (id == NULL) {
1319 yyerror("failed to allocate idspec");
1320 return -1;
1321 }
1322 if (set_identifier(&id->id, $2, $3) != 0) {
1323 yyerror("failed to set identifer.\n");
1324 racoon_free(id);
1325 vfree($3); //%%% BUG FIX - memory leak
1326 return -1;
1327 }
1328 vfree($3); //%%% BUG FIX - memory leak
1329 id->idtype = $2;
1330 genlist_append (cur_rmconf->idvl_p, id);
1331 }
1332 EOS
1333 | VERIFY_IDENTIFIER SWITCH { cur_rmconf->verify_identifier = $2; } EOS
1334 | SHARED_SECRET SECRETTYPE QUOTEDSTRING
1335 {
1336 #ifdef __APPLE__
1337 cur_rmconf->secrettype = $2;
1338 cur_rmconf->shared_secret = $3;
1339 #else
1340 yyerror("Apple specific features not compiled in.");
1341 return -1;
1342 #endif
1343 } EOS
1344 | SHARED_SECRET SECRETTYPE
1345 {
1346 #ifdef __APPLE__
1347 if ($2 != SECRETTYPE_KEYCHAIN_BY_ID) {
1348 yyerror("shared secret value missing.\n");
1349 return -1;
1350 }
1351 cur_rmconf->secrettype = $2;
1352 #else
1353 yyerror("Apple specific features not compiled in.");
1354 return -1;
1355 #endif
1356
1357 } EOS
1358 | NONCE_SIZE NUMBER { cur_rmconf->nonce_size = $2; } EOS
1359 | DH_GROUP
1360 {
1361 yyerror("dh_group cannot be defined here.");
1362 return -1;
1363 }
1364 dh_group_num EOS
1365 | PASSIVE SWITCH { cur_rmconf->passive = $2; } EOS
1366 | IKE_FRAG SWITCH { cur_rmconf->ike_frag = $2; } EOS
1367 | ESP_FRAG NUMBER {
1368 #ifdef SADB_X_EXT_NAT_T_FRAG
1369 cur_rmconf->esp_frag = $2;
1370 #else
1371 yywarn("Your kernel does not support esp_frag");
1372 #endif
1373 } EOS
1374 | SCRIPT QUOTEDSTRING PHASE1_UP {
1375 cur_rmconf->script[SCRIPT_PHASE1_UP] =
1376 script_path_add(vdup($2));
1377 } EOS
1378 | SCRIPT QUOTEDSTRING PHASE1_DOWN {
1379 cur_rmconf->script[SCRIPT_PHASE1_DOWN] =
1380 script_path_add(vdup($2));
1381 } EOS
1382 | MODE_CFG SWITCH { cur_rmconf->mode_cfg = $2; } EOS
1383 | GENERATE_POLICY SWITCH { cur_rmconf->gen_policy = $2; } EOS
1384 | SUPPORT_PROXY SWITCH { cur_rmconf->support_proxy = $2; } EOS
1385 | INITIAL_CONTACT SWITCH { cur_rmconf->ini_contact = $2; } EOS
1386 | NAT_TRAVERSAL SWITCH
1387 {
1388 #ifdef ENABLE_NATT
1389 cur_rmconf->nat_traversal = $2;
1390 #else
1391 yyerror("NAT-T support not compiled in.");
1392 #endif
1393 } EOS
1394 | NAT_TRAVERSAL NAT_TRAVERSAL_LEVEL
1395 {
1396 #ifdef ENABLE_NATT
1397 cur_rmconf->nat_traversal = $2;
1398 #else
1399 yyerror("NAT-T support not compiled in.");
1400 #endif
1401 } EOS
1402 | NAT_TRAVERSAL_MULTI_USER SWITCH
1403 {
1404 #ifdef ENABLE_NATT
1405 #ifdef __APPLE__
1406 cur_rmconf->natt_multiple_user = $2;
1407 #else
1408 yyerror("Apple specific features not compiled in.");
1409 #endif
1410 #else
1411 yyerror("NAT-T support not compiled in.");
1412 #endif
1413 } EOS
1414 | DPD SWITCH
1415 {
1416 #ifdef ENABLE_DPD
1417 cur_rmconf->dpd = $2;
1418 #else
1419 yyerror("DPD support not compiled in.");
1420 #endif
1421 } EOS
1422 | DPD_DELAY NUMBER
1423 {
1424 #ifdef ENABLE_DPD
1425 cur_rmconf->dpd_interval = $2;
1426 #else
1427 yyerror("DPD support not compiled in.");
1428 #endif
1429 }
1430 EOS
1431 | DPD_RETRY NUMBER
1432 {
1433 #ifdef ENABLE_DPD
1434 cur_rmconf->dpd_retry = $2;
1435 #else
1436 yyerror("DPD support not compiled in.");
1437 #endif
1438 }
1439 EOS
1440 | DPD_MAXFAIL NUMBER
1441 {
1442 #ifdef ENABLE_DPD
1443 cur_rmconf->dpd_maxfails = $2;
1444 #else
1445 yyerror("DPD support not compiled in.");
1446 #endif
1447 }
1448 EOS
1449 | LIFETIME LIFETYPE_TIME NUMBER unittype_time
1450 {
1451 cur_rmconf->prhead->lifetime = $3 * $4;
1452 }
1453 EOS
1454 | PROPOSAL_CHECK PROPOSAL_CHECK_LEVEL { cur_rmconf->pcheck_level = $2; } EOS
1455 | LIFETIME LIFETYPE_BYTE NUMBER unittype_byte
1456 {
1457 #if 1
1458 yyerror("byte lifetime support is deprecated in Phase1");
1459 return -1;
1460 #else
1461 yywarn("the lifetime of bytes in phase 1 "
1462 "will be ignored at the moment.");
1463 cur_rmconf->prhead->lifebyte = fix_lifebyte($3 * $4);
1464 if (cur_rmconf->prhead->lifebyte == 0)
1465 return -1;
1466 #endif
1467 }
1468 EOS
1469 | PROPOSAL
1470 {
1471 struct secprotospec *spspec;
1472
1473 spspec = newspspec();
1474 if (spspec == NULL)
1475 return -1;
1476 insspspec(spspec, &cur_rmconf->prhead);
1477 }
1478 BOC isakmpproposal_specs EOC
1479 ;
1480 exchange_types
1481 : /* nothing */
1482 | exchange_types EXCHANGETYPE
1483 {
1484 struct etypes *new;
1485 new = racoon_malloc(sizeof(struct etypes));
1486 if (new == NULL) {
1487 yyerror("filed to allocate etypes");
1488 return -1;
1489 }
1490 new->type = $2;
1491 new->next = NULL;
1492 if (cur_rmconf->etypes == NULL)
1493 cur_rmconf->etypes = new;
1494 else {
1495 struct etypes *p;
1496 for (p = cur_rmconf->etypes;
1497 p->next != NULL;
1498 p = p->next)
1499 ;
1500 p->next = new;
1501 }
1502 }
1503 ;
1504 cert_spec
1505 : CERT_X509 QUOTEDSTRING QUOTEDSTRING
1506 {
1507 cur_rmconf->certtype = $1;
1508 cur_rmconf->mycertfile = strdup($2->v);
1509 vfree($2);
1510 cur_rmconf->myprivfile = strdup($3->v);
1511 vfree($3);
1512 }
1513 EOS
1514 | CERT_X509 IN_KEYCHAIN
1515 {
1516 #ifdef __APPLE__
1517 cur_rmconf->certtype = $1;
1518 cur_rmconf->identity_in_keychain = 1;
1519 cur_rmconf->keychainCertRef = NULL;
1520 #endif
1521 }
1522 EOS
1523 ;
1524 | CERT_X509 IN_KEYCHAIN QUOTEDSTRING
1525 {
1526 #ifdef __APPLE__
1527
1528 cur_rmconf->certtype = $1;
1529 cur_rmconf->identity_in_keychain = 1;
1530 cur_rmconf->keychainCertRef = $3;
1531 #endif
1532 }
1533 EOS
1534 ;
1535 | CERT_PLAINRSA QUOTEDSTRING
1536 {
1537 char path[MAXPATHLEN];
1538 int ret = 0;
1539
1540 getpathname(path, sizeof(path),
1541 LC_PATHTYPE_CERT, $2->v);
1542 vfree($2);
1543
1544 cur_rmconf->certtype = $1;
1545 cur_rmconf->send_cr = FALSE;
1546 cur_rmconf->send_cert = FALSE;
1547 cur_rmconf->verify_cert = FALSE;
1548 if (rsa_parse_file(cur_rmconf->rsa_private, path, RSA_TYPE_PRIVATE)) {
1549 yyerror("Couldn't parse keyfile.\n", path);
1550 return -1;
1551 }
1552 plog(LLV_DEBUG, LOCATION, NULL, "Private PlainRSA keyfile parsed: %s\n", path);
1553 }
1554 EOS
1555 ;
1556 dh_group_num
1557 : ALGORITHMTYPE
1558 {
1559 $$ = algtype2doi(algclass_isakmp_dh, $1);
1560 if ($$ == -1) {
1561 yyerror("must be DH group");
1562 return -1;
1563 }
1564 }
1565 | NUMBER
1566 {
1567 if (ARRAYLEN(num2dhgroup) > $1 && num2dhgroup[$1] != 0) {
1568 $$ = num2dhgroup[$1];
1569 } else {
1570 yyerror("must be DH group");
1571 $$ = 0;
1572 return -1;
1573 }
1574 }
1575 ;
1576 identifierstring
1577 : /* nothing */ { $$ = NULL; }
1578 | ADDRSTRING { $$ = $1; }
1579 | QUOTEDSTRING { $$ = $1; }
1580 ;
1581 isakmpproposal_specs
1582 : /* nothing */
1583 | isakmpproposal_specs isakmpproposal_spec
1584 ;
1585 isakmpproposal_spec
1586 : STRENGTH
1587 {
1588 yyerror("strength directive is obsoleted.");
1589 } STRENGTHTYPE EOS
1590 | LIFETIME LIFETYPE_TIME NUMBER unittype_time
1591 {
1592 cur_rmconf->prhead->spspec->lifetime = $3 * $4;
1593 }
1594 EOS
1595 | LIFETIME LIFETYPE_BYTE NUMBER unittype_byte
1596 {
1597 #if 1
1598 yyerror("byte lifetime support is deprecated");
1599 return -1;
1600 #else
1601 cur_rmconf->prhead->spspec->lifebyte = fix_lifebyte($3 * $4);
1602 if (cur_rmconf->prhead->spspec->lifebyte == 0)
1603 return -1;
1604 #endif
1605 }
1606 EOS
1607 | DH_GROUP dh_group_num
1608 {
1609 cur_rmconf->prhead->spspec->algclass[algclass_isakmp_dh] = $2;
1610 }
1611 EOS
1612 | GSS_ID QUOTEDSTRING
1613 {
1614 if (cur_rmconf->prhead->spspec->vendorid != VENDORID_GSSAPI) {
1615 yyerror("wrong Vendor ID for gssapi_id");
1616 return -1;
1617 }
1618 cur_rmconf->prhead->spspec->gssid = strdup($2->v);
1619 }
1620 EOS
1621 | ALGORITHM_CLASS ALGORITHMTYPE keylength
1622 {
1623 int doi;
1624 int defklen;
1625
1626 doi = algtype2doi($1, $2);
1627 if (doi == -1) {
1628 yyerror("algorithm mismatched 1");
1629 return -1;
1630 }
1631
1632 switch ($1) {
1633 case algclass_isakmp_enc:
1634 /* reject suppressed algorithms */
1635 #ifndef HAVE_OPENSSL_RC5_H
1636 if ($2 == algtype_rc5) {
1637 yyerror("algorithm %s not supported",
1638 s_attr_isakmp_enc(doi));
1639 return -1;
1640 }
1641 #endif
1642 #ifndef HAVE_OPENSSL_IDEA_H
1643 if ($2 == algtype_idea) {
1644 yyerror("algorithm %s not supported",
1645 s_attr_isakmp_enc(doi));
1646 return -1;
1647 }
1648 #endif
1649
1650 cur_rmconf->prhead->spspec->algclass[algclass_isakmp_enc] = doi;
1651 defklen = default_keylen($1, $2);
1652 if (defklen == 0) {
1653 if ($3) {
1654 yyerror("keylen not allowed");
1655 return -1;
1656 }
1657 } else {
1658 if ($3 && check_keylen($1, $2, $3) < 0) {
1659 yyerror("invalid keylen %d", $3);
1660 return -1;
1661 }
1662 }
1663 if ($3)
1664 cur_rmconf->prhead->spspec->encklen = $3;
1665 else
1666 cur_rmconf->prhead->spspec->encklen = defklen;
1667 break;
1668 case algclass_isakmp_hash:
1669 cur_rmconf->prhead->spspec->algclass[algclass_isakmp_hash] = doi;
1670 break;
1671 case algclass_isakmp_ameth:
1672 cur_rmconf->prhead->spspec->algclass[algclass_isakmp_ameth] = doi;
1673 /*
1674 * We may have to set the Vendor ID for the
1675 * authentication method we're using.
1676 */
1677 switch ($2) {
1678 case algtype_gssapikrb:
1679 if (cur_rmconf->prhead->spspec->vendorid !=
1680 VENDORID_UNKNOWN) {
1681 yyerror("Vendor ID mismatch "
1682 "for auth method");
1683 return -1;
1684 }
1685 /*
1686 * For interoperability with Win2k,
1687 * we set the Vendor ID to "GSSAPI".
1688 */
1689 cur_rmconf->prhead->spspec->vendorid =
1690 VENDORID_GSSAPI;
1691 break;
1692 case algtype_rsasig:
1693 if (cur_rmconf->certtype == ISAKMP_CERT_PLAINRSA) {
1694 if (rsa_list_count(cur_rmconf->rsa_private) == 0) {
1695 yyerror ("Private PlainRSA key not set. "
1696 "Use directive 'certificate_type plainrsa ...'\n");
1697 return -1;
1698 }
1699 if (rsa_list_count(cur_rmconf->rsa_public) == 0) {
1700 yyerror ("Public PlainRSA keys not set. "
1701 "Use directive 'peers_certfile plainrsa ...'\n");
1702 return -1;
1703 }
1704 }
1705 break;
1706 default:
1707 break;
1708 }
1709 break;
1710 default:
1711 yyerror("algorithm mismatched 2");
1712 return -1;
1713 }
1714 }
1715 EOS
1716 ;
1717
1718 unittype_time
1719 : UNITTYPE_SEC { $$ = 1; }
1720 | UNITTYPE_MIN { $$ = 60; }
1721 | UNITTYPE_HOUR { $$ = (60 * 60); }
1722 ;
1723 unittype_byte
1724 : UNITTYPE_BYTE { $$ = 1; }
1725 | UNITTYPE_KBYTES { $$ = 1024; }
1726 | UNITTYPE_MBYTES { $$ = (1024 * 1024); }
1727 | UNITTYPE_TBYTES { $$ = (1024 * 1024 * 1024); }
1728 ;
1729 %%
1730
1731 static struct proposalspec *
1732 newprspec()
1733 {
1734 struct proposalspec *new;
1735
1736 new = racoon_calloc(1, sizeof(*new));
1737 if (new == NULL)
1738 yyerror("failed to allocate proposal");
1739
1740 return new;
1741 }
1742
1743 /*
1744 * insert into head of list.
1745 */
1746 static void
1747 insprspec(prspec, head)
1748 struct proposalspec *prspec;
1749 struct proposalspec **head;
1750 {
1751 if (*head != NULL)
1752 (*head)->prev = prspec;
1753 prspec->next = *head;
1754 *head = prspec;
1755 }
1756
1757 static struct secprotospec *
1758 newspspec()
1759 {
1760 struct secprotospec *new;
1761
1762 new = racoon_calloc(1, sizeof(*new));
1763 if (new == NULL) {
1764 yyerror("failed to allocate spproto");
1765 return NULL;
1766 }
1767
1768 new->encklen = 0; /*XXX*/
1769
1770 /*
1771 * Default to "uknown" vendor -- we will override this
1772 * as necessary. When we send a Vendor ID payload, an
1773 * "unknown" will be translated to a KAME/racoon ID.
1774 */
1775 new->vendorid = VENDORID_UNKNOWN;
1776
1777 return new;
1778 }
1779
1780 /*
1781 * insert into head of list.
1782 */
1783 static void
1784 insspspec(spspec, head)
1785 struct secprotospec *spspec;
1786 struct proposalspec **head;
1787 {
1788 spspec->back = *head;
1789
1790 if ((*head)->spspec != NULL)
1791 (*head)->spspec->prev = spspec;
1792 spspec->next = (*head)->spspec;
1793 (*head)->spspec = spspec;
1794 }
1795
1796 /* set final acceptable proposal */
1797 static int
1798 set_isakmp_proposal(rmconf, prspec)
1799 struct remoteconf *rmconf;
1800 struct proposalspec *prspec;
1801 {
1802 struct proposalspec *p;
1803 struct secprotospec *s;
1804 int prop_no = 1;
1805 int trns_no = 1;
1806 int32_t types[MAXALGCLASS];
1807
1808 p = prspec;
1809 if (p->next != 0) {
1810 plog(LLV_ERROR, LOCATION, NULL,
1811 "multiple proposal definition.\n");
1812 return -1;
1813 }
1814
1815 /* mandatory check */
1816 if (p->spspec == NULL) {
1817 yyerror("no remote specification found: %s.\n",
1818 saddr2str(rmconf->remote));
1819 return -1;
1820 }
1821 for (s = p->spspec; s != NULL; s = s->next) {
1822 /* XXX need more to check */
1823 if (s->algclass[algclass_isakmp_enc] == 0) {
1824 yyerror("encryption algorithm required.");
1825 return -1;
1826 }
1827 if (s->algclass[algclass_isakmp_hash] == 0) {
1828 yyerror("hash algorithm required.");
1829 return -1;
1830 }
1831 if (s->algclass[algclass_isakmp_dh] == 0) {
1832 yyerror("DH group required.");
1833 return -1;
1834 }
1835 if (s->algclass[algclass_isakmp_ameth] == 0) {
1836 yyerror("authentication method required.");
1837 return -1;
1838 }
1839 }
1840
1841 /* skip to last part */
1842 for (s = p->spspec; s->next != NULL; s = s->next)
1843 ;
1844
1845 while (s != NULL) {
1846 plog(LLV_DEBUG2, LOCATION, NULL,
1847 "lifetime = %ld\n", (long)
1848 (s->lifetime ? s->lifetime : p->lifetime));
1849 plog(LLV_DEBUG2, LOCATION, NULL,
1850 "lifebyte = %d\n",
1851 s->lifebyte ? s->lifebyte : p->lifebyte);
1852 plog(LLV_DEBUG2, LOCATION, NULL,
1853 "encklen=%d\n", s->encklen);
1854
1855 memset(types, 0, ARRAYLEN(types));
1856 types[algclass_isakmp_enc] = s->algclass[algclass_isakmp_enc];
1857 types[algclass_isakmp_hash] = s->algclass[algclass_isakmp_hash];
1858 types[algclass_isakmp_dh] = s->algclass[algclass_isakmp_dh];
1859 types[algclass_isakmp_ameth] =
1860 s->algclass[algclass_isakmp_ameth];
1861
1862 /* expanding spspec */
1863 clean_tmpalgtype();
1864 trns_no = expand_isakmpspec(prop_no, trns_no, types,
1865 algclass_isakmp_enc, algclass_isakmp_ameth + 1,
1866 s->lifetime ? s->lifetime : p->lifetime,
1867 s->lifebyte ? s->lifebyte : p->lifebyte,
1868 s->encklen, s->vendorid, s->gssid,
1869 rmconf);
1870 if (trns_no == -1) {
1871 plog(LLV_ERROR, LOCATION, NULL,
1872 "failed to expand isakmp proposal.\n");
1873 return -1;
1874 }
1875
1876 s = s->prev;
1877 }
1878
1879 if (rmconf->proposal == NULL) {
1880 plog(LLV_ERROR, LOCATION, NULL,
1881 "no proposal found.\n");
1882 return -1;
1883 }
1884
1885 return 0;
1886 }
1887
1888 static void
1889 clean_tmpalgtype()
1890 {
1891 int i;
1892 for (i = 0; i < MAXALGCLASS; i++)
1893 tmpalgtype[i] = 0; /* means algorithm undefined. */
1894 }
1895
1896 static int
1897 expand_isakmpspec(prop_no, trns_no, types,
1898 class, last, lifetime, lifebyte, encklen, vendorid, gssid,
1899 rmconf)
1900 int prop_no, trns_no;
1901 int *types, class, last;
1902 time_t lifetime;
1903 int lifebyte;
1904 int encklen;
1905 int vendorid;
1906 char *gssid;
1907 struct remoteconf *rmconf;
1908 {
1909 struct isakmpsa *new;
1910
1911 /* debugging */
1912 {
1913 int j;
1914 char tb[10];
1915 plog(LLV_DEBUG2, LOCATION, NULL,
1916 "p:%d t:%d\n", prop_no, trns_no);
1917 for (j = class; j < MAXALGCLASS; j++) {
1918 snprintf(tb, sizeof(tb), "%d", types[j]);
1919 plog(LLV_DEBUG2, LOCATION, NULL,
1920 "%s%s%s%s\n",
1921 s_algtype(j, types[j]),
1922 types[j] ? "(" : "",
1923 tb[0] == '0' ? "" : tb,
1924 types[j] ? ")" : "");
1925 }
1926 plog(LLV_DEBUG2, LOCATION, NULL, "\n");
1927 }
1928
1929 #define TMPALGTYPE2STR(n) \
1930 s_algtype(algclass_isakmp_##n, types[algclass_isakmp_##n])
1931 /* check mandatory values */
1932 if (types[algclass_isakmp_enc] == 0
1933 || types[algclass_isakmp_ameth] == 0
1934 || types[algclass_isakmp_hash] == 0
1935 || types[algclass_isakmp_dh] == 0) {
1936 yyerror("few definition of algorithm "
1937 "enc=%s ameth=%s hash=%s dhgroup=%s.\n",
1938 TMPALGTYPE2STR(enc),
1939 TMPALGTYPE2STR(ameth),
1940 TMPALGTYPE2STR(hash),
1941 TMPALGTYPE2STR(dh));
1942 return -1;
1943 }
1944 #undef TMPALGTYPE2STR
1945
1946 /* set new sa */
1947 new = newisakmpsa();
1948 if (new == NULL) {
1949 yyerror("failed to allocate isakmp sa");
1950 return -1;
1951 }
1952 new->prop_no = prop_no;
1953 new->trns_no = trns_no++;
1954 new->lifetime = lifetime;
1955 new->lifebyte = lifebyte;
1956 new->enctype = types[algclass_isakmp_enc];
1957 new->encklen = encklen;
1958 new->authmethod = types[algclass_isakmp_ameth];
1959 new->hashtype = types[algclass_isakmp_hash];
1960 new->dh_group = types[algclass_isakmp_dh];
1961 new->vendorid = vendorid;
1962 #ifdef HAVE_GSSAPI
1963 if (new->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
1964 if (gssid != NULL) {
1965 new->gssid = vmalloc(strlen(gssid));
1966 memcpy(new->gssid->v, gssid, new->gssid->l);
1967 racoon_free(gssid);
1968 } else {
1969 /*
1970 * Allocate the default ID so that it gets put
1971 * into a GSS ID attribute during the Phase 1
1972 * exchange.
1973 */
1974 new->gssid = gssapi_get_default_gss_id();
1975 }
1976 }
1977 #endif
1978 insisakmpsa(new, rmconf);
1979
1980 return trns_no;
1981 }
1982
1983 static int
1984 listen_addr (struct sockaddr *addr, int udp_encap)
1985 {
1986 struct myaddrs *p;
1987
1988 p = newmyaddr();
1989 if (p == NULL) {
1990 yyerror("failed to allocate myaddrs");
1991 return -1;
1992 }
1993 p->addr = addr;
1994 if (p->addr == NULL) {
1995 yyerror("failed to copy sockaddr ");
1996 delmyaddr(p);
1997 return -1;
1998 }
1999 p->udp_encap = udp_encap;
2000 #ifdef __APPLE__
2001 /* These need to be initialized for Apple modifications
2002 * to open code for isakmp sockets
2003 */
2004 p->sock = -1;
2005 p->in_use = 1;
2006 #endif
2007
2008 insmyaddr(p, &lcconf->myaddrs);
2009
2010 lcconf->autograbaddr = 0;
2011 return 0;
2012 }
2013
2014 #if 0
2015 /*
2016 * fix lifebyte.
2017 * Must be more than 1024B because its unit is kilobytes.
2018 * That is defined RFC2407.
2019 */
2020 static int
2021 fix_lifebyte(t)
2022 unsigned long t;
2023 {
2024 if (t < 1024) {
2025 yyerror("byte size should be more than 1024B.");
2026 return 0;
2027 }
2028
2029 return(t / 1024);
2030 }
2031 #endif
2032
2033 int
2034 cfparse()
2035 {
2036 int error;
2037
2038 plog(LLV_DEBUG, LOCATION, NULL, "===== parse config\n");
2039
2040 yycf_init_buffer();
2041
2042 if (yycf_switch_buffer(lcconf->racoon_conf) != 0)
2043 return -1;
2044
2045 error = yyparse();
2046 if (error != 0) {
2047 if (yyerrorcount) {
2048 plog(LLV_ERROR, LOCATION, NULL,
2049 "fatal parse failure (%d errors)\n",
2050 yyerrorcount);
2051 } else {
2052 plog(LLV_ERROR, LOCATION, NULL,
2053 "fatal parse failure.\n");
2054 }
2055 return -1;
2056 }
2057
2058 if (error == 0 && yyerrorcount) {
2059 plog(LLV_ERROR, LOCATION, NULL,
2060 "parse error is nothing, but yyerrorcount is %d.\n",
2061 yyerrorcount);
2062 exit(1);
2063 }
2064
2065 yycf_clean_buffer();
2066
2067 plog(LLV_DEBUG2, LOCATION, NULL, "parse successed.\n");
2068
2069 return 0;
2070 }
2071
2072 int
2073 cfreparse()
2074 {
2075 plog(LLV_DEBUG, LOCATION, NULL, "==== Got HUP signal - re-parsing.\n");
2076 flushph2();
2077 flushph1();
2078 flushrmconf();
2079 flushsainfo();
2080 flushlcconf();
2081 check_auto_exit(); /* check/change state of auto exit */
2082 clean_tmpalgtype();
2083
2084 return(cfparse());
2085 }
2086
2087
2088 #ifdef ENABLE_ADMINPORT
2089 static void
2090 adminsock_conf(path, owner, group, mode_dec)
2091 vchar_t *path;
2092 vchar_t *owner;
2093 vchar_t *group;
2094 int mode_dec;
2095 {
2096 struct passwd *pw = NULL;
2097 struct group *gr = NULL;
2098 mode_t mode = 0;
2099 uid_t uid;
2100 gid_t gid;
2101 int isnum;
2102
2103 adminsock_path = path->v;
2104
2105 if (owner == NULL)
2106 return;
2107
2108 errno = 0;
2109 uid = atoi(owner->v);
2110 isnum = !errno;
2111 if (((pw = getpwnam(owner->v)) == NULL) && !isnum)
2112 yyerror("User \"%s\" does not exist", owner->v);
2113
2114 if (pw)
2115 adminsock_owner = pw->pw_uid;
2116 else
2117 adminsock_owner = uid;
2118
2119 if (group == NULL)
2120 return;
2121
2122 errno = 0;
2123 gid = atoi(group->v);
2124 isnum = !errno;
2125 if (((gr = getgrnam(group->v)) == NULL) && !isnum)
2126 yyerror("Group \"%s\" does not exist", group->v);
2127
2128 if (gr)
2129 adminsock_group = gr->gr_gid;
2130 else
2131 adminsock_group = gid;
2132
2133 if (mode_dec == -1)
2134 return;
2135
2136 if (mode_dec > 777)
2137 yyerror("Mode 0%03o is invalid", mode_dec);
2138 if (mode_dec >= 400) { mode += 0400; mode_dec -= 400; }
2139 if (mode_dec >= 200) { mode += 0200; mode_dec -= 200; }
2140 if (mode_dec >= 100) { mode += 0200; mode_dec -= 100; }
2141
2142 if (mode_dec > 77)
2143 yyerror("Mode 0%03o is invalid", mode_dec);
2144 if (mode_dec >= 40) { mode += 040; mode_dec -= 40; }
2145 if (mode_dec >= 20) { mode += 020; mode_dec -= 20; }
2146 if (mode_dec >= 10) { mode += 020; mode_dec -= 10; }
2147
2148 if (mode_dec > 7)
2149 yyerror("Mode 0%03o is invalid", mode_dec);
2150 if (mode_dec >= 4) { mode += 04; mode_dec -= 4; }
2151 if (mode_dec >= 2) { mode += 02; mode_dec -= 2; }
2152 if (mode_dec >= 1) { mode += 02; mode_dec -= 1; }
2153
2154 adminsock_mode = mode;
2155
2156 return;
2157 }
2158 #endif