1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright (c) 2017, Joyent, Inc.
26 */
27
28 #include <sys/types.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <strings.h>
32 #include <errno.h>
33 #include <ctype.h>
34 #include <libintl.h>
35 #include <arpa/inet.h>
36 #include <sys/socket.h>
37 #include <netdb.h>
38 #include <net/pfkeyv2.h>
39 #include <pthread.h>
40 #include <synch.h>
41 #include <assert.h>
42 #include <bunyan.h>
43 #include <err.h>
44
45 #include "preshared.h"
46 #include "defs.h"
47 #include <ipsec_util.h>
48
49 static FILE *fp;
50
51 /* Preshared key lock */
52 static pthread_rwlock_t ps_rwlock = PTHREAD_RWLOCK_INITIALIZER;
53
54 #define hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \
55 (((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10)))
56
57 #define ADDRBITS_V4 32 /* number of bits in IPv4 address */
58 #define ADDRBITS_V6 128 /* number of bits in IPv6 address */
59
60
61 #define CHR_CURLY_BRACE_OPEN '{'
62 #define CHR_CURLY_BRACE_CLOSE '}'
63 #define CHR_COMMENT_BEGIN '#'
64 #define CHR_COLON ':'
65 #define CHR_SLASH '/'
66 #define CHR_BACKSLASH '\\'
67 #define CHR_DOUBLEQUOTE '"'
68 #define CHR_SPACE ' '
69 #define CHR_NEWLINE '\n'
70 #define CHR_TAB '\t'
71 #define CHR_NULL '\0'
72
73 /*
74 * Error message strings
75 */
76
77 static const char *err_arr [] = {
78 #define ERR_LOCID_MISMATCH 0
79 "Local Id value does not match the specified Localid type",
80 #define ERR_REMID_MISMATCH 1
81 "Remote Id does not match the remoteid type",
82 #define ERR_MAINMODE_LOCID_NOTIP 2
83 "Local Id can only be an IP address",
84 #define ERR_MAINMODE_REMID_NOTIP 3
85 "Remote Id can only be an IP address",
86 #define ERR_ENTRY_NOBEGINBRACE 4
87 "Syntax error - Entry does not start with an open brace",
88 #define ERR_INVALID_FIELDNAME 5
89 "Invalid attribute field name",
90 #define ERR_REPEATED_FIELD 6
91 "Field in an entry is repeated",
92 #define ERR_INVALID_LOCALID_TYPE 7
93 "Invalid Local Id type",
94 #define ERR_MISSING_LOCALID 8
95 "localid not defined",
96 #define ERR_MISSING_REMID 9
97 "remotedid not defined",
98 #define ERR_INVALID_REMID_TYPE 10
99 "Invalid Remote Id type",
100 #define ERR_INVALID_IKE_MODE 11
101 "Invalid Ike Mode",
102 #define ERR_INVALID_BIT_SPECIFIER 12
103 "Invalid Bit Specifier",
104 #define ERR_BITLEN2BIG 13
105 "Bit length too large",
106 #define ERR_WARN_LOWBITS_TRUNC 14
107 "Lower bits will be truncated",
108 #define ERR_STRING_NOT_HEX 15
109 "Invalid string format - hex string expected",
110 #define ERR_BADADDR_PREFIXLEN_PART 16
111 "Invalid prefix length format in address",
112 #define ERR_BADADDR_SLASH_UNEXPECTED 17
113 "Unxpected '/' in address string",
114 #define ERR_BADADDR_TRY_AGAIN 18
115 "Bad address string - try again later",
116 #define ERR_BADADDR_ADDRESS 19
117 "Bad address string",
118 #define ERR_BADADDR_MISMATCH 20
119 "Address versions do not match",
120 #define ERR_BADADDR_MCAST 21
121 "Multicast address not allowed",
122 #define ERR_BADADDR_4MAPPED 22
123 "V4 mapped in v6 address not allowed",
124 #define ERR_BADADDR_4COMPAT 23
125 "V4 compatible in v6 address not allowed",
126 #define ERR_INVALID_ASCII_STRING 24
127 "Syntax error in ASCII string or quotes",
128 };
129
130
131 /*
132 * Buffer to hold input line
133 */
134 static char linebuf[1024];
135
136
137 /*
138 * Types of tokens
139 */
140 #define PS_TOK_BEGIN_CURLY_BRACE 1
141 #define PS_TOK_END_CURLY_BRACE 2
142 #define PS_TOK_FLD_TYPE 3
143 #define PS_TOK_FLD_VALUE 4
144
145
146 /*
147 * The prototype syntax of this file used, e.g. "localid" and "localidtype".
148 * The aliases support transitioning to using same keywords as the ike/config
149 * parser, e.g. "local_id" and "local_id_type".
150 *
151 * Also, {local,remote}_addr are aliases for {local,remote}_id for now,
152 * eventually they should be handled differently.
153 */
154 static const keywdtab_t fldstab[] = {
155 { PS_FLD_LOCID, "localid" },
156 { PS_FLD_LOCID, "local_id" },
157 { PS_FLD_LOCID, "local_addr" },
158 { PS_FLD_LOCID_TYPE, "localidtype" },
159 { PS_FLD_LOCID_TYPE, "local_id_type" },
160 { PS_FLD_REMID, "remoteid" },
161 { PS_FLD_REMID, "remote_id" },
162 { PS_FLD_REMID, "remote_addr" },
163 { PS_FLD_REMID_TYPE, "remoteidtype" },
164 { PS_FLD_REMID_TYPE, "remote_id_type" },
165 { PS_FLD_IKE_MODE, "ike_mode" },
166 { PS_FLD_IKE_MODE, "mode" },
167 { PS_FLD_KEY, "key" },
168 };
169
170 static const keywdtab_t idstab[] = {
171 { PS_ID_IP, "IP" },
172 { PS_ID_IP4, "IPv4" },
173 { PS_ID_IP6, "IPv6" },
174 { PS_ID_IP, "IP_SUBNET" },
175 { PS_ID_IP4, "IPv4_SUBNET" },
176 { PS_ID_IP6, "IPv6_SUBNET" },
177 };
178
179 static const keywdtab_t ikmstab[] = {
180 { PS_IKM_MAIN, "main" },
181 };
182
183 /*
184 * Head and tail of linked list of entry data structures
185 */
186 static preshared_entry_t *ps_head, *ps_tail;
187
188 /*
189 * Global counters for use in reporting approximate error location
190 * in config file
191 */
192 static int err_line_number;
193 static int err_entry_number;
194
195 /*
196 * Function prototypes
197 */
198 static int getidtype(char *);
199 static int getfldtype(char *);
200 static int getikmtype(char *);
201 static int postprocess_entry(preshared_entry_t *, char **);
202 static char *get_next_token(char **);
203 static char *readnextline(FILE *);
204 static preshared_entry_t *getnextentry(FILE *, char **);
205 static uint8_t *parsekey(char *, uint_t *, uint_t *, char **);
206 /* Note: in_get{prefilen,addr}, in6_getaddr stolen from ifconfig.c */
207 static int in_getprefixlen(char *, boolean_t, int);
208 static int in_getaddr(char *, struct sockaddr_storage *, int *, char **);
209 static int in6_getaddr(char *, struct sockaddr_storage *, int *, char **);
210 static boolean_t check_if_v6(char *);
211
212
213 /*
214 * Functions
215 */
216
217 /*
218 * Check for same preshared entry.
219 * Caller holds ps_rwlock as reader
220 */
221 static boolean_t
222 same_psent(preshared_entry_t *ptr, preshared_entry_t *ps)
223 {
224 struct sockaddr_in *ptr_v4, *ps_v4;
225 struct sockaddr_in6 *ptr_v6, *ps_v6;
226
227 assert(RW_LOCK_HELD(&ps_rwlock));
228
229 /*
230 * Check for duplicate entries. Preshared type
231 * of IPv4/IPv6 has a NULL locid/remid string and
232 * has the sockaddr_storages structures populated.
233 * All others store themselves in the aforementioned
234 * strings.
235 */
236
237 /* Local and Remote ID types must match */
238 if ((ptr->pe_locidtype != ps->pe_locidtype) ||
239 (ptr->pe_remidtype != ps->pe_remidtype))
240 return (B_FALSE);
241
242 /* Check local ids */
243 switch (ptr->pe_locidtype) {
244 case PS_ID_IP:
245 case PS_ID_IP4:
246 case PS_ID_SUBNET4:
247 ptr_v4 = (struct sockaddr_in *)&ptr->pe_locid_sa;
248 ps_v4 = (struct sockaddr_in *)&ps->pe_locid_sa;
249 if ((uint32_t)ptr_v4->sin_addr.s_addr !=
250 (uint32_t)ps_v4->sin_addr.s_addr)
251 return (B_FALSE);
252 /*
253 * Prefix length either same number or same error
254 * PS_PLEN_NO_PREFIX for non subnet
255 */
256 if (&ptr->pe_locid_plen != &ps->pe_locid_plen)
257 return (B_FALSE);
258 break;
259 case PS_ID_IP6:
260 case PS_ID_SUBNET6:
261 ptr_v6 = (struct sockaddr_in6 *)&ptr->pe_locid_sa;
262 ps_v6 = (struct sockaddr_in6 *)&ps->pe_locid_sa;
263 if (!(IN6_ARE_ADDR_EQUAL(&ptr_v6->sin6_addr,
264 &ps_v6->sin6_addr)))
265 return (B_FALSE);
266 /*
267 * Prefix length either same number or same error
268 * PS_PLEN_NO_PREFIX for non subnet
269 */
270 if (&ptr->pe_locid_plen != &ps->pe_locid_plen)
271 return (B_FALSE);
272 break;
273 default:
274 if (strcmp(ptr->pe_locid, ps->pe_locid) != 0)
275 return (B_FALSE);
276 }
277
278 /* Check remote ids */
279 switch (ptr->pe_remidtype) {
280 case PS_ID_IP:
281 case PS_ID_IP4:
282 ptr_v4 = (struct sockaddr_in *)&ptr->pe_remid_sa;
283 ps_v4 = (struct sockaddr_in *)&ps->pe_remid_sa;
284 if ((uint32_t)ptr_v4->sin_addr.s_addr !=
285 (uint32_t)ps_v4->sin_addr.s_addr)
286 return (B_FALSE);
287 /*
288 * Prefix length either same number or same error
289 * PS_PLEN_NO_PREFIX for non subnet
290 */
291 if (&ptr->pe_remid_plen != &ps->pe_remid_plen)
292 return (B_FALSE);
293 break;
294 case PS_ID_IP6:
295 ptr_v6 = (struct sockaddr_in6 *)&ptr->pe_remid_sa;
296 ps_v6 = (struct sockaddr_in6 *)&ps->pe_remid_sa;
297 if (!(IN6_ARE_ADDR_EQUAL(&ptr_v6->sin6_addr,
298 &ps_v6->sin6_addr)))
299 return (B_FALSE);
300 /*
301 * Prefix length either same number or same error
302 * PS_PLEN_NO_PREFIX for non subnet
303 */
304 if (&ptr->pe_remid_plen != &ps->pe_remid_plen)
305 return (B_FALSE);
306 break;
307 default:
308 if (strcmp(ptr->pe_remid, ps->pe_remid) != 0)
309 return (B_FALSE);
310 }
311 return (B_TRUE);
312 }
313
314 /*
315 * Check for duplicate preshared entry.
316 * Caller holds ps_rwlock as reader
317 */
318 static boolean_t
319 has_dup(preshared_entry_t *ps, preshared_entry_t **head)
320 {
321 preshared_entry_t *ptr;
322
323 assert(RW_LOCK_HELD(&ps_rwlock));
324
325 if (ps == NULL) /* no op */
326 return (B_FALSE);
327
328 ptr = *head;
329
330 while (ptr != NULL) {
331 if (same_psent(ptr, ps))
332 return (B_TRUE);
333 ptr = ptr->pe_next;
334 }
335 return (B_FALSE);
336 }
337
338 /*
339 * Append entries to list.
340 * Caller holds ps_rwlock as writer
341 */
342 static boolean_t
343 append_to_list(preshared_entry_t *ps, preshared_entry_t **head,
344 preshared_entry_t **tail)
345 {
346 assert(RW_WRITE_HELD(&ps_rwlock));
347
348 if (ps == NULL) /* no op */
349 return (B_TRUE);
350 assert(ps->pe_refcnt > 0);
351 if (has_dup(ps, head)) {
352 (void) fprintf(stderr,
353 gettext("Ignoring duplicate preshared entry.\n"));
354 PE_REFRELE(ps);
355 return (B_FALSE);
356 }
357 ps->pe_next = NULL; /* will be last entry */
358 if (*head == NULL) {
359 /* list initialization */
360 *head = *tail = ps;
361 } else {
362 (*tail)->pe_next = ps;
363 *tail = (*tail)->pe_next;
364 }
365 return (B_TRUE);
366 }
367
368 /*
369 * Appends preshared entry to list
370 * Holds ps_rwlock as writer
371 */
372 boolean_t
373 append_preshared_entry(preshared_entry_t *ps)
374 {
375 boolean_t rc;
376
377 (void) pthread_rwlock_wrlock(&ps_rwlock);
378 rc = append_to_list(ps, &ps_head, &ps_tail);
379 (void) pthread_rwlock_unlock(&ps_rwlock);
380 return (rc);
381 }
382
383 /*
384 * Frees preshared list
385 * Caller holds ps_rwlock as writer
386 */
387 static void
388 free_preshared_list(preshared_entry_t **head, preshared_entry_t **tail)
389 {
390 preshared_entry_t *ps;
391
392 assert(RW_WRITE_HELD(&ps_rwlock));
393
394 while (*head != NULL) {
395 /* Zero the old list in case of reloading. */
396 ps = *head;
397 if (ps == *tail)
398 *tail = NULL;
399 *head = ps->pe_next;
400 PE_REFRELE(ps);
401 }
402 }
403
404 static char *
405 getidstr(int val)
406 {
407 const keywdtab_t *idt;
408
409 for (idt = idstab; idt < A_END(idstab); idt++) {
410 if (val == idt->kw_tag)
411 return (idt->kw_str);
412 }
413 return (NULL); /* not found */
414 }
415
416 static int
417 getidtype(char *valp)
418 {
419 const keywdtab_t *idt;
420
421 for (idt = idstab; idt < A_END(idstab); idt++) {
422 if (strcasecmp(valp, idt->kw_str) == 0)
423 return (idt->kw_tag);
424 }
425 return (-1); /* not found */
426 }
427
428 static int
429 getfldtype(char *valp)
430 {
431 const keywdtab_t *fldt;
432
433 for (fldt = fldstab; fldt < A_END(fldstab); fldt++) {
434 if (strcasecmp(valp, fldt->kw_str) == 0)
435 return (fldt->kw_tag);
436 }
437 return (-1); /* not found */
438 }
439
440 static char *
441 getikmstr(int val)
442 {
443 const keywdtab_t *idt;
444
445 for (idt = ikmstab; idt < A_END(ikmstab); idt++) {
446 if (val == idt->kw_tag)
447 return (idt->kw_str);
448 }
449 return (NULL); /* not found */
450 }
451
452 static int
453 getikmtype(char *valp)
454 {
455 const keywdtab_t *ikmt;
456
457 for (ikmt = ikmstab; ikmt < A_END(ikmstab); ikmt++) {
458 if (strcasecmp(valp, ikmt->kw_str) == 0)
459 return (ikmt->kw_tag);
460 }
461 return (-1); /* not found */
462
463 }
464
465 /*
466 * unlike the other get*str functions, this one mallocs the returned
467 * string, so the caller will need to free it.
468 */
469 char *
470 getkeystr(uint8_t *key, uint_t bytes, uint_t bits)
471 {
472 uint8_t *sp;
473 char *dp, *buf;
474 uint_t len;
475
476 /* assume two digits per byte, and no more than 4 digits of bitlen */
477 len = (bytes < 1) + 6;
478 if ((buf = malloc(len)) == NULL)
479 return (NULL);
480
481 sp = key;
482 dp = buf;
483 while (bytes-- != 0) {
484 (void) sprintf(dp, "%02x", *sp++);
485 dp += 2;
486 }
487 (void) sprintf(dp, "/%d", bits);
488
489 return (buf);
490 }
491
492 /*
493 * Parsing for hex key values.
494 * Return value:
495 * Pointer to allocated buffer containing the key
496 * Parameter, "len" contains length of key buffer on successful return
497 * Parameter, "lbits" contains length of key in bits in the key buffer.
498 * Note:Stolen from ipseckey.c and then adapted for use here.
499 */
500 static uint8_t *
501 parsehexkey(char *input, uint_t *keybuflen, uint_t *lbits, char **errp)
502 {
503 uint8_t *keyp, *keybufp;
504 uint_t i, hexlen = 0, bits, alloclen;
505
506 for (i = 0; input[i] != CHR_NULL && input[i] != CHR_SLASH; i++)
507 hexlen++;
508
509 if (input[i] == CHR_NULL) {
510 bits = 0;
511 } else {
512 /* Have /nn. */
513 input[i] = CHR_NULL;
514 if (sscanf((input + i + 1), "%u", &bits) != 1) {
515 *errp = (char *)err_arr[ERR_INVALID_BIT_SPECIFIER];
516 return (NULL);
517 }
518
519 /* hexlen in nibbles */
520 if (((bits + 3) >> 2) > hexlen) {
521 *errp = (char *)err_arr[ERR_BITLEN2BIG];
522 return (NULL);
523 }
524
525 /*
526 * Adjust hexlen down if user gave us too small of a bit
527 * count.
528 */
529 if ((hexlen << 2) > bits + 3) {
530 /*
531 * NOTE: Callers don't necessarily handle warnings
532 * a successful return.
533 */
534 *errp = (char *)err_arr[ERR_WARN_LOWBITS_TRUNC];
535 hexlen = (bits + 3) >> 2;
536 input[hexlen] = CHR_NULL;
537 }
538 }
539
540 /*
541 * Allocate. Remember, hexlen is in nibbles.
542 */
543
544 alloclen = (hexlen/2 + (hexlen & 0x1));
545 keyp = malloc(alloclen);
546
547 if (keyp == NULL) {
548 *errp = strerror(errno);
549 return (NULL);
550 }
551
552 keybufp = keyp;
553 *keybuflen = alloclen;
554 if (bits == 0)
555 *lbits = (hexlen + (hexlen & 0x1)) << 2;
556 else
557 *lbits = bits;
558
559 /*
560 * Read in nibbles. Read in odd-numbered as shifted high.
561 * (e.g. 123 becomes 0x1230).
562 */
563
564 for (i = 0; input[i] != CHR_NULL; i += 2) {
565 boolean_t second = (input[i + 1] != CHR_NULL);
566
567 if (!isxdigit(input[i]) ||
568 (!isxdigit(input[i + 1]) && second)) {
569 free(keybufp); /* free allocated memory on error */
570 *errp = (char *)err_arr[ERR_STRING_NOT_HEX];
571 return (NULL);
572 }
573 *keyp = (hd2num(input[i]) << 4);
574 if (second)
575 *keyp |= hd2num(input[i + 1]);
576 else
577 break; /* out of for loop. */
578 keyp++;
579 }
580
581 /* bzero the remaining bits if we're a non-octet amount. */
582 if (bits & 0x7)
583 *((input[i] == CHR_NULL) ? keyp - 1 : keyp) &=
584 0xff << (8 - (bits & 0x7));
585 return (keybufp);
586 }
587 /*
588 * Parsing for ASCII key values.
589 * Return value:
590 * Pointer to allocated buffer containing the key
591 * Parameter, "len" contains length of key buffer on successful return
592 * Parameter, "lbits" contains length of key in bits in the key buffer.
593 * Note:Stolen from ipseckey.c and then adapted for use here.
594 */
595 static uint8_t *
596 parseasciikey(char *input, uint_t *keybuflen, uint_t *lbits, char **errp)
597 {
598 uint8_t *keyp, *keybufp;
599 uint_t i, asciilen = 0;
600
601 /* Make sure the first and last characters are '"', unescaped */
602
603 if (input[0] != CHR_DOUBLEQUOTE)
604 goto invalid_ascii_string;
605
606 /* Set pointer past first quote, then find the end */
607 input++;
608
609 for (i = 0; input[i] != CHR_NULL; i++)
610 asciilen++;
611 /*
612 * Length without trailing \0 and leading quote lopped off
613 * from before must be at least 3 for a well formed key
614 */
615 if (--asciilen < 3)
616 goto invalid_ascii_string;
617 /*
618 * Make sure the last quote exists and is not escaped,
619 * but also watch for valid "this string\\" syntax.
620 */
621 if (input[asciilen] != CHR_DOUBLEQUOTE)
622 goto invalid_ascii_string;
623
624 /* We know we can dereference these because of length check above */
625 if ((input[asciilen - 1] == CHR_BACKSLASH) &&
626 (input[asciilen - 2] != CHR_BACKSLASH))
627 goto invalid_ascii_string;
628
629 input[asciilen] = CHR_NULL;
630
631 /* Now we have something well-formed in quotes and length set */
632
633 /*
634 * Allocate. If we have backslashes, we can shrink later
635 */
636
637 keyp = malloc(asciilen);
638 if (keyp == NULL) {
639 *errp = strerror(errno);
640 return (NULL);
641 }
642
643 keybufp = keyp;
644 /*
645 * Read in bytes, but be aware of next byte for escape purposes
646 */
647
648 for (i = 0; input[i] != CHR_NULL; i++) {
649 boolean_t second = (input[i + 1] != CHR_NULL);
650
651 if (!isascii(input[i]) ||
652 (second && !isascii(input[i + 1]))) {
653 goto free_key_buffer;
654 }
655 /*
656 * Consider backslash an escape character for
657 * itself, single and double quotes, but not
658 * for anything else
659 */
660 if (second && (input[i] == CHR_BACKSLASH)) {
661 if (input[i + 1] == CHR_DOUBLEQUOTE ||
662 input[i + 1] == CHR_BACKSLASH) {
663 *keyp = input[i + 1];
664 i++;
665 keyp++;
666 asciilen--;
667 continue; /* for loop */
668 }
669 }
670 *keyp = input[i];
671 keyp++;
672 }
673 /* Shrink to fit */
674 *keybuflen = asciilen;
675 *lbits = asciilen << 3;
676 keybufp = realloc(keybufp, asciilen);
677
678 return (keybufp);
679
680 free_key_buffer:
681 free(keybufp);
682 invalid_ascii_string:
683 *errp = (char *)err_arr[ERR_INVALID_ASCII_STRING];
684 return (NULL);
685 }
686
687 static uint8_t *
688 parsekey(char *input, uint_t *keybuflen, uint_t *lbits, char **errp)
689 {
690 /* Determine if this is an ASCII key or hex key */
691 if (input[0] == CHR_DOUBLEQUOTE) {
692 return (parseasciikey(input, keybuflen, lbits, errp));
693 } else {
694 return (parsehexkey(input, keybuflen, lbits, errp));
695 }
696 }
697
698 static boolean_t
699 check_if_v6(char *abuf)
700 {
701 char *cp;
702 for (cp = abuf; *cp != CHR_NULL; cp++) {
703 if (*cp == CHR_COLON)
704 return (B_TRUE);
705 }
706 return (B_FALSE);
707 }
708
709 static boolean_t
710 valid_ip6_address(struct sockaddr_in6 *addr, char **errmsgp)
711 {
712
713 /* is it mcast */
714 if (IN6_IS_ADDR_MULTICAST(&addr->sin6_addr)) {
715 *errmsgp = (char *)err_arr[ERR_BADADDR_MCAST];
716 return (B_FALSE);
717 }
718 /* is it v4 mapped */
719 if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) {
720 *errmsgp = (char *)err_arr[ERR_BADADDR_4MAPPED];
721 return (B_FALSE);
722 }
723 /* is it v4 compat */
724 if (IN6_IS_ADDR_V4COMPAT(&addr->sin6_addr)) {
725 *errmsgp = (char *)err_arr[ERR_BADADDR_4COMPAT];
726 return (B_FALSE);
727 }
728
729 return (B_TRUE);
730 }
731
732 /*
733 * Post process preshared key entry.
734 * Caller holds ps_rwlock as reader
735 */
736 static int
737 postprocess_entry(preshared_entry_t *ps, char **errmsgp)
738 {
739 assert(RW_LOCK_HELD(&ps_rwlock));
740
741 /* ID types default to IP. */
742 if ((ps->pe_flds_mask & PS_FLD_LOCID_TYPE) == 0) {
743 ps->pe_flds_mask |= PS_FLD_LOCID_TYPE;
744 ps->pe_locidtype = PS_ID_IP;
745 }
746 if ((ps->pe_flds_mask & PS_FLD_REMID_TYPE) == 0) {
747 ps->pe_flds_mask |= PS_FLD_REMID_TYPE;
748 ps->pe_remidtype = PS_ID_IP;
749 }
750
751 /*
752 * Verify that all mandatory fields are there.
753 * mandatory: local_id and remote_id (or local_addr and remote_addr),
754 * mode, and key.
755 */
756
757 /*
758 * Note: verify that semantic relationships among fields is fine
759 * Since we only support main mode, we force the mode to be main.
760 */
761
762 ps->pe_ike_mode = PS_IKM_MAIN;
763 if ((ps->pe_locidtype != PS_ID_IP) &&
764 (ps->pe_locidtype != PS_ID_IP4) &&
765 (ps->pe_locidtype != PS_ID_IP6)) {
766 *errmsgp = (char *)err_arr[ERR_MAINMODE_LOCID_NOTIP];
767 return (-1);
768 }
769 if ((ps->pe_remidtype != PS_ID_IP) &&
770 (ps->pe_remidtype != PS_ID_IP4) &&
771 (ps->pe_remidtype != PS_ID_IP6)) {
772 *errmsgp = (char *)err_arr[ERR_MAINMODE_REMID_NOTIP];
773 return (-1);
774 }
775
776 /*
777 * Parse "id" values now and verify that they match the
778 * "idtype" associated with them.
779 * NOTE: Real work is TBD
780 */
781 if (ps->pe_flds_mask & PS_FLD_LOCID_TYPE) {
782 int retval;
783
784 if (ps->pe_locid == NULL) {
785 *errmsgp = (char *)err_arr[ERR_MISSING_LOCALID];
786 return (-1);
787 }
788
789 switch (ps->pe_locidtype) {
790 case PS_ID_IP:
791 {
792 boolean_t isv6 = check_if_v6(ps->pe_locid);
793 if (isv6) {
794 ps->pe_locidtype = PS_ID_IP6;
795 retval = in6_getaddr(ps->pe_locid,
796 &ps->pe_locid_sa, &ps->pe_locid_plen,
797 errmsgp);
798 } else {
799 ps->pe_locidtype = PS_ID_IP4;
800 retval = in_getaddr(ps->pe_locid,
801 &ps->pe_locid_sa, &ps->pe_locid_plen,
802 errmsgp);
803 }
804 if (retval < 0)
805 return (-1);
806 }
807 break;
808 case PS_ID_IP4:
809 case PS_ID_SUBNET4:
810 retval = in_getaddr(ps->pe_locid, &ps->pe_locid_sa,
811 &ps->pe_locid_plen, errmsgp);
812 if (retval < 0)
813 return (-1);
814 break;
815 case PS_ID_IP6:
816 case PS_ID_SUBNET6:
817 retval = in6_getaddr(ps->pe_locid, &ps->pe_locid_sa,
818 &ps->pe_locid_plen, errmsgp);
819 if (retval < 0)
820 return (-1);
821 break;
822 case PS_ID_SUBNET:
823 {
824 boolean_t isv6 = check_if_v6(ps->pe_locid);
825 if (isv6) {
826 ps->pe_locidtype = PS_ID_SUBNET6;
827 retval = in6_getaddr(ps->pe_locid,
828 &ps->pe_locid_sa, &ps->pe_locid_plen,
829 errmsgp);
830 } else {
831 ps->pe_locidtype = PS_ID_SUBNET4;
832 retval = in_getaddr(ps->pe_locid,
833 &ps->pe_locid_sa, &ps->pe_locid_plen,
834 errmsgp);
835 }
836 if (retval < 0)
837 return (-1);
838 }
839 break;
840 case PS_ID_RANGE:
841 break;
842 case PS_ID_RANGE4:
843 break;
844 case PS_ID_RANGE6:
845 break;
846 case PS_ID_ASN1DN:
847 break;
848 case PS_ID_ASN1GN:
849 break;
850 case PS_ID_KEYID:
851 break;
852 case PS_ID_FQDN:
853 break;
854 case PS_ID_USER_FQDN:
855 break;
856 }
857 }
858 if (ps->pe_flds_mask & PS_FLD_REMID_TYPE) {
859 int retval;
860
861 if (ps->pe_remid == NULL) {
862 *errmsgp = (char *)err_arr[ERR_MISSING_REMID];
863 return (-1);
864 }
865 switch (ps->pe_remidtype) {
866 case PS_ID_IP:
867 {
868 boolean_t isv6 = check_if_v6(ps->pe_remid);
869 if (isv6) {
870 ps->pe_remidtype = PS_ID_IP6;
871 retval = in6_getaddr(ps->pe_remid,
872 &ps->pe_remid_sa, &ps->pe_remid_plen,
873 errmsgp);
874 } else {
875 ps->pe_remidtype = PS_ID_IP4;
876 retval = in_getaddr(ps->pe_remid,
877 &ps->pe_remid_sa, &ps->pe_remid_plen,
878 errmsgp);
879 }
880 if (retval < 0)
881 return (-1);
882 }
883 break;
884 case PS_ID_IP4:
885 case PS_ID_SUBNET4:
886 retval = in_getaddr(ps->pe_remid, &ps->pe_remid_sa,
887 &ps->pe_remid_plen, errmsgp);
888 if (retval < 0)
889 return (-1);
890 break;
891 case PS_ID_IP6:
892 case PS_ID_SUBNET6:
893 retval = in6_getaddr(ps->pe_remid, &ps->pe_remid_sa,
894 &ps->pe_remid_plen, errmsgp);
895 if (retval < 0)
896 return (-1);
897 break;
898 case PS_ID_SUBNET:
899 {
900 boolean_t isv6 = check_if_v6(ps->pe_remid);
901 if (isv6) {
902 ps->pe_remidtype = PS_ID_SUBNET6;
903 retval = in6_getaddr(ps->pe_remid,
904 &ps->pe_remid_sa, &ps->pe_remid_plen,
905 errmsgp);
906 } else {
907 ps->pe_remidtype = PS_ID_SUBNET4;
908 retval = in_getaddr(ps->pe_remid,
909 &ps->pe_remid_sa, &ps->pe_remid_plen,
910 errmsgp);
911 }
912 if (retval < 0)
913 return (-1);
914 }
915 break;
916 case PS_ID_RANGE:
917 break;
918 case PS_ID_RANGE4:
919 break;
920 case PS_ID_RANGE6:
921 break;
922 case PS_ID_ASN1DN:
923 break;
924 case PS_ID_ASN1GN:
925 break;
926 case PS_ID_KEYID:
927 break;
928 case PS_ID_FQDN:
929 break;
930 case PS_ID_USER_FQDN:
931 break;
932 }
933 }
934
935 /*
936 * Reality check address families
937 * Remote and local address families must match
938 */
939 if (check_if_v6(ps->pe_locid) != check_if_v6(ps->pe_remid)) {
940 *errmsgp = (char *)err_arr[ERR_BADADDR_MISMATCH];
941 return (-1);
942 }
943
944 /* v6 */
945 if (ps->pe_remidtype == PS_ID_IP6 ||
946 ps->pe_remidtype == PS_ID_SUBNET6) {
947 struct sockaddr_in6 *local =
948 (struct sockaddr_in6 *)(&ps->pe_locid_sa);
949 struct sockaddr_in6 *remote =
950 (struct sockaddr_in6 *)(&ps->pe_remid_sa);
951
952 if (!valid_ip6_address(local, errmsgp) ||
953 !valid_ip6_address(remote, errmsgp)) {
954 return (-1);
955 }
956 } else {
957 /* v4 */
958 struct sockaddr_in *local =
959 (struct sockaddr_in *)(&ps->pe_locid_sa);
960 struct sockaddr_in *remote =
961 (struct sockaddr_in *)(&ps->pe_remid_sa);
962
963 /* are either mcast */
964 if (IN_MULTICAST(ntohl(local->sin_addr.s_addr)) ||
965 IN_MULTICAST(ntohl(remote->sin_addr.s_addr))) {
966 *errmsgp = (char *)err_arr[ERR_BADADDR_MCAST];
967 return (-1);
968 }
969 }
970
971 return (0); /* OK return */
972 }
973
974 /*
975 * Note: Code stolen from ifconfig.c and adapted.
976 *
977 * If "slash" is zero this parses the whole string as
978 * an integer. With "slash" non zero it parses the tail part as an integer.
979 *
980 * If it is not a valid integer this returns BAD_ADDR.
981 * If there is /<n> present this returns PS_PLEN_NO_PREFIX.
982 */
983 static int
984 in_getprefixlen(char *addr, boolean_t slash, int max_plen)
985 {
986 int prefixlen;
987 char *str, *end;
988
989 if (slash) {
990 str = strchr(addr, CHR_SLASH);
991 if (str == NULL)
992 return (PS_PLEN_NO_PREFIX);
993 str++;
994 } else
995 str = addr;
996
997 prefixlen = strtol(str, &end, 10);
998 if (prefixlen < 0)
999 return (PS_PLEN_BAD_ADDR);
1000 if (str == end)
1001 return (PS_PLEN_BAD_ADDR);
1002 if (max_plen != 0 && max_plen < prefixlen)
1003 return (PS_PLEN_BAD_ADDR);
1004 return (prefixlen);
1005 }
1006
1007
1008 /*
1009 * Note: code stolen from ifconfig.c and adapted
1010 *
1011 * If the last argument is non-NULL allow a <addr>/<n> syntax and
1012 * pass out <n> in *plenp.
1013 * If <n> doesn't parse return PS_PLEN_BAD_ADDR as *plenp.
1014 * If no /<n> is present return PS_PLEN_NO_PREFIX as *plenp.
1015 */
1016 static int
1017 in_getaddr(char *s, struct sockaddr_storage *saddr, int *plenp, char **errp)
1018 {
1019 struct sockaddr_in *sin = (struct sockaddr_in *)saddr;
1020 struct hostent *hp;
1021 struct netent *np;
1022 char str[BUFSIZ];
1023 int error_num;
1024
1025 (void) strncpy(str, s, sizeof (str));
1026
1027 /*
1028 * Look for '/'<n> (CHR_SLASH)is plenp
1029 */
1030 if (plenp != NULL) {
1031 char *cp;
1032
1033 *plenp = in_getprefixlen(str, B_TRUE, ADDRBITS_V4);
1034 if (*plenp == PS_PLEN_BAD_ADDR) {
1035 *errp = (char *)err_arr[ERR_BADADDR_PREFIXLEN_PART];
1036 return (-1);
1037 }
1038 cp = strchr(str, CHR_SLASH);
1039 if (cp != NULL)
1040 *cp = CHR_NULL;
1041 } else if (strchr(str, CHR_SLASH) != NULL) {
1042 *errp = (char *)err_arr[ERR_BADADDR_SLASH_UNEXPECTED];
1043 return (-1);
1044 }
1045
1046 (void) memset(sin, 0, sizeof (*sin));
1047
1048 /*
1049 * Try to catch attempts to set the broadcast address to all 1's.
1050 */
1051 if (strcmp(str, "255.255.255.255") == 0 ||
1052 (strtoul(str, (char **)NULL, 0) == 0xffffffffUL)) {
1053 sin->sin_family = AF_INET;
1054 sin->sin_addr.s_addr = 0xffffffff;
1055 return (0);
1056 }
1057
1058 hp = getipnodebyname(str, AF_INET, 0, &error_num);
1059 if (hp) {
1060 sin->sin_family = hp->h_addrtype;
1061 (void) memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
1062 freehostent(hp);
1063 return (0);
1064 }
1065 np = getnetbyname(str);
1066 if (np) {
1067 sin->sin_family = np->n_addrtype;
1068 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
1069 return (0);
1070 }
1071 if (error_num == TRY_AGAIN) {
1072 *errp = (char *)err_arr[ERR_BADADDR_TRY_AGAIN];
1073 } else {
1074 *errp = (char *)err_arr[ERR_BADADDR_ADDRESS];
1075 }
1076 return (-1);
1077 }
1078
1079 /*
1080 * Note: Code stolen from ifconfig.c and adapted.
1081 *
1082 * If the third argument is non-NULL allow a <addr>/<n> syntax and
1083 * pass out <n> in *plenp.
1084 * If <n> doesn't parse return PS_PLEN_BAD_ADDR as *plenp.
1085 * If no /<n> is present return PS_PLEN_NO_PREFIX as *plenp.
1086 */
1087 static int
1088 in6_getaddr(char *s, struct sockaddr_storage *saddr, int *plenp, char **errp)
1089 {
1090 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)saddr;
1091 struct hostent *hp;
1092 char str[BUFSIZ];
1093 int error_num;
1094
1095 (void) strncpy(str, s, sizeof (str));
1096
1097 /*
1098 * Look for '/'<n> (CHR_SLASH) is plenp
1099 */
1100 if (plenp != NULL) {
1101 char *cp;
1102
1103 *plenp = in_getprefixlen(str, B_TRUE, ADDRBITS_V6);
1104 if (*plenp == PS_PLEN_BAD_ADDR) {
1105 *errp = (char *)err_arr[ERR_BADADDR_PREFIXLEN_PART];
1106 return (-1);
1107 }
1108 cp = strchr(str, CHR_SLASH);
1109 if (cp != NULL)
1110 *cp = CHR_NULL;
1111 } else if (strchr(str, CHR_SLASH) != NULL) {
1112 *errp = (char *)err_arr[ERR_BADADDR_SLASH_UNEXPECTED];
1113 return (-1);
1114 }
1115
1116 (void) memset(sin6, 0, sizeof (*sin6));
1117
1118 hp = getipnodebyname(str, AF_INET6, 0, &error_num);
1119 if (hp) {
1120 sin6->sin6_family = hp->h_addrtype;
1121 (void) memcpy(&sin6->sin6_addr, hp->h_addr, hp->h_length);
1122 freehostent(hp);
1123 return (0);
1124 }
1125 if (error_num == TRY_AGAIN) {
1126 *errp = (char *)err_arr[ERR_BADADDR_TRY_AGAIN];
1127 } else {
1128 *errp = (char *)err_arr[ERR_BADADDR_ADDRESS];
1129 }
1130 return (-1);
1131 }
1132
1133 /*
1134 * char *get_next_token(cpp)
1135 * cpp - on input should point within a null terminated buffer.
1136 * return value - on output will point to past spaces to first
1137 * non-space character that starts a token
1138 * cpp - on output will point past non-space token string pointed
1139 * by return value.
1140 * Side-effects: modifies a potential space character after token
1141 * to null to form a null terminated token unless a
1142 * double-quote has been seen in the token
1143 */
1144 static char *
1145 get_next_token(char **cpp)
1146 {
1147 char *cp = *cpp;
1148 char *startcp, *endcp;
1149 boolean_t quote_seen = B_FALSE;
1150
1151 /* skip leading whitespaces */
1152 while (*cp == CHR_SPACE || *cp == CHR_TAB || *cp == CHR_NEWLINE)
1153 cp++;
1154
1155 if (*cp == CHR_NULL) { /* end of string */
1156 *cpp = NULL;
1157 return (NULL);
1158 }
1159
1160 startcp = endcp = cp;
1161 while (*endcp != CHR_NULL &&
1162 ((*endcp != CHR_SPACE && *endcp != CHR_TAB) || quote_seen) &&
1163 *endcp != CHR_NEWLINE) {
1164 /*
1165 * Within quotes, ignore spaces and tabs as delimiters
1166 * and take note of start and end quotes, ignoring
1167 * backslash escaped characters.
1168 */
1169 if (*endcp == CHR_DOUBLEQUOTE &&
1170 ((endcp == startcp) ||
1171 ((endcp > startcp) && *(endcp - 1) != CHR_BACKSLASH)))
1172 quote_seen = !quote_seen;
1173 endcp++;
1174 }
1175 if (*endcp != CHR_NULL)
1176 *endcp++ = CHR_NULL;
1177 *cpp = endcp;
1178 return (startcp);
1179 }
1180
1181 static char *
1182 readnextline(FILE *fp)
1183 {
1184 char *cp;
1185
1186 while ((cp = fgets(linebuf, sizeof (linebuf), fp)) != NULL) {
1187 err_line_number++; /* NOTE approx - if long lines */
1188 if (*cp == CHR_NEWLINE || *cp == CHR_COMMENT_BEGIN)
1189 continue;
1190 break;
1191 }
1192 if (cp == NULL)
1193 return (NULL);
1194 return (linebuf);
1195 }
1196
1197
1198 /*
1199 * static preshared_entry_t *getnextentry(fp, errmpp)
1200 * fp
1201 * file pointer to open config file.
1202 * errmpp
1203 * pointer to pointer to buffer containing error message
1204 * return value
1205 * NULL when EOF is reached
1206 * pointer to valid entry otherwise
1207 *
1208 * Function scans open input file to get the next entry read from
1209 * the file and instantiated in the preshared_entry_t data structure.
1210 * In case of invalid syntax entries the function exits and does
1211 * not return and process exits.
1212 *
1213 * Caller holds ps_rwlock as reader.
1214 */
1215 static preshared_entry_t *
1216 getnextentry(FILE *fp, char **errmpp)
1217 {
1218 preshared_entry_t *ps;
1219 char *cp; /* pointer to scan input */
1220 char *tp;
1221 char *errmsg = NULL;
1222 int cur_fld_type = -1; /* "uninitialized" */
1223 int entry_done = FALSE;
1224 int next_token_expected = PS_TOK_BEGIN_CURLY_BRACE;
1225
1226 assert(RW_LOCK_HELD(&ps_rwlock));
1227
1228 *errmpp = NULL;
1229
1230 ps = calloc(1, sizeof (preshared_entry_t)); /* Auto-zeroes... */
1231 if (ps == NULL) {
1232 errmsg = strerror(errno);
1233 goto fatal_error;
1234 }
1235 ps->pe_refcnt = 1;
1236 nextline:
1237 /* get next line */
1238
1239 /* skip comment and null lines */
1240 while (((cp = readnextline(fp)) != NULL) &&
1241 (*cp == CHR_COMMENT_BEGIN || *cp == CHR_NULL))
1242 ;
1243
1244 if (cp == NULL) {
1245 /* EOF */
1246 PE_REFRELE(ps);
1247 return (NULL);
1248 }
1249
1250 for (;;) {
1251 if (entry_done == TRUE)
1252 break;
1253 tp = get_next_token(&cp);
1254 if (tp == NULL)
1255 goto nextline;
1256 process_newtoken:
1257 /* skip rest of line if comment token */
1258 if (*tp == CHR_COMMENT_BEGIN)
1259 goto nextline;
1260
1261 switch (next_token_expected) {
1262
1263 case PS_TOK_BEGIN_CURLY_BRACE:
1264 if (*tp != CHR_CURLY_BRACE_OPEN) {
1265 errmsg = (char *)err_arr[
1266 ERR_ENTRY_NOBEGINBRACE];
1267 goto bad_syntax;
1268 }
1269 err_entry_number++;
1270 next_token_expected = PS_TOK_FLD_TYPE;
1271
1272 /*
1273 * Note: We skip tokens assuming whitespace
1274 * termination but relax that for this token.
1275 *
1276 * Reset scan pointer past this token (one character)
1277 * so pointer does not miss any tokens that may
1278 * be glued to this one with no whitespaces.
1279 */
1280 tp++; /* past brace */
1281 if (*tp == CHR_NULL) {
1282 /* past whitespace terminated brace */
1283 tp++;
1284 }
1285 cp = tp;
1286 break;
1287
1288 case PS_TOK_END_CURLY_BRACE:
1289 /*
1290 * Do sanity checks on entry and other
1291 * post-processing
1292 */
1293 if (postprocess_entry(ps, &errmsg) < 0)
1294 goto bad_semantics;
1295 entry_done = TRUE;
1296 break;
1297
1298 case PS_TOK_FLD_TYPE:
1299 /*
1300 * Note: could be end-of-entry too...
1301 * here we assume the closing brace is
1302 * preceded by a whitespace. We gave some latitude to
1303 * opening brace, but not to the closing brace
1304 */
1305 if (*tp == CHR_CURLY_BRACE_CLOSE) {
1306 /*
1307 * End of fields, reset expected token,
1308 * Also reset scan token so this
1309 */
1310 next_token_expected = PS_TOK_END_CURLY_BRACE;
1311 goto process_newtoken;
1312 }
1313
1314 /* initialize cur_fld_type */
1315 if ((cur_fld_type = getfldtype(tp)) < 0) {
1316 errmsg = (char *)err_arr[ERR_INVALID_FIELDNAME];
1317 goto bad_syntax;
1318 }
1319
1320 if ((ps->pe_flds_mask & cur_fld_type) != 0) {
1321 errmsg = (char *)err_arr[ERR_REPEATED_FIELD];
1322 goto bad_syntax;
1323 }
1324
1325 ps->pe_flds_mask |= cur_fld_type;
1326
1327 next_token_expected = PS_TOK_FLD_VALUE;
1328 break;
1329
1330 case PS_TOK_FLD_VALUE:
1331
1332 /*
1333 * Note: we assume all value fields do
1334 * not embed any whitespace even for complicated
1335 * value syntax such as for "range". Is that a
1336 * "reasonable" assumption ?
1337 *
1338 * Note++: All things being strdup()'d below need
1339 * to be parsed and put into context dependent data
1340 * structures at some point (after entry is read or
1341 * right here).
1342 */
1343 switch (cur_fld_type) {
1344 case PS_FLD_LOCID_TYPE:
1345 if ((ps->pe_locidtype = getidtype(tp)) < 0) {
1346 errmsg = (char *)err_arr[
1347 ERR_INVALID_LOCALID_TYPE];
1348 goto bad_syntax;
1349 }
1350 break;
1351 case PS_FLD_LOCID:
1352 ps->pe_locid = strdup(tp);
1353 if (ps->pe_locid == NULL) {
1354 errmsg = strerror(errno);
1355 goto fatal_error;
1356 }
1357 break;
1358 case PS_FLD_REMID_TYPE:
1359 if ((ps->pe_remidtype = getidtype(tp)) < 0) {
1360 errmsg = (char *)err_arr[
1361 ERR_INVALID_REMID_TYPE];
1362 goto bad_syntax;
1363 }
1364 break;
1365 case PS_FLD_REMID:
1366 ps->pe_remid = strdup(tp);
1367 if (ps->pe_remid == NULL) {
1368 errmsg = strerror(errno);
1369 goto fatal_error;
1370 }
1371 break;
1372 case PS_FLD_IKE_MODE:
1373 if ((ps->pe_ike_mode = getikmtype(tp)) < 0) {
1374 errmsg = (char *)err_arr[
1375 ERR_INVALID_IKE_MODE];
1376 goto bad_syntax;
1377 }
1378 break;
1379 case PS_FLD_KEY:
1380 ps->pe_keybuf = parsekey(tp,
1381 &ps->pe_keybuf_bytes,
1382 &ps->pe_keybuf_lbits, &errmsg);
1383 if (ps->pe_keybuf == NULL)
1384 goto fatal_error;
1385 else if (errmsg != NULL) {
1386 /*
1387 * Utter warning on otherwise okay
1388 * input.
1389 */
1390 (void) fprintf(stderr,
1391 gettext("read_preshared: %s\n"),
1392 errmsg);
1393 }
1394 break;
1395 default:
1396 /* Should never happen - assert ? */
1397 errmsg = (char *)err_arr[
1398 ERR_INVALID_FIELDNAME];
1399 goto fatal_error;
1400 }
1401
1402 next_token_expected = PS_TOK_FLD_TYPE;
1403 break;
1404 }
1405 }
1406 return (ps);
1407 /*
1408 * TBD any differentiation in these errors ?
1409 */
1410 bad_semantics:
1411 bad_syntax:
1412 fatal_error:
1413 if (ps != NULL)
1414 PE_REFRELE(ps);
1415 *errmpp = errmsg;
1416 return (NULL);
1417 }
1418
1419
1420 /*
1421 * Load any preshared keys.
1422 * Boolean parameter 'replace' determines whether the newly-read entries
1423 * will replace the existing list, or be appended to it.
1424 * On success, returns a linked list of preshared entries, and sets the
1425 * error message pointer *errmp to NULL.
1426 * On failure, returns NULL and sets *errmp to an error message string.
1427 *
1428 * Holds ps_rwlock as writer.
1429 */
1430 char *
1431 preshared_load(const char *ps_filename, int ps_fd, boolean_t replace)
1432 {
1433 preshared_entry_t *ps, *tmp_head = NULL, *tmp_tail = NULL;
1434 char *errmp;
1435 boolean_t dupfound = B_FALSE;
1436
1437 (void) pthread_rwlock_wrlock(&ps_rwlock);
1438
1439 /* TODO more paranoia/permissions checks on file needed */
1440
1441 if (ps_filename == NULL)
1442 fp = fdopen(ps_fd, "r");
1443 else
1444 fp = fopen(ps_filename, "r");
1445 if (fp == NULL) {
1446 (void) pthread_rwlock_unlock(&ps_rwlock);
1447 if (errno == ENOENT)
1448 return (NULL); /* no file == empty file */
1449 return (strerror(errno));
1450 }
1451
1452 while ((ps = getnextentry(fp, &errmp)) != NULL) {
1453 /* process the new entry */
1454
1455 /*
1456 * For now, create a list of just the new entries
1457 */
1458 if (!replace) {
1459 if (has_dup(ps, &ps_head)) {
1460 /* Skip duplicates in master list */
1461 PE_REFRELE(ps);
1462 dupfound = B_TRUE;
1463 continue;
1464 }
1465 }
1466 assert(ps->pe_refcnt >= 1);
1467 if (!append_to_list(ps, &tmp_head, &tmp_tail)) {
1468 /* Duplicate found within new list */
1469 dupfound = B_TRUE;
1470 }
1471 }
1472
1473 (void) fclose(fp);
1474
1475 if (errmp == NULL) {
1476 /*
1477 * we read the list in successfully; either
1478 * replace or append to global list now.
1479 */
1480 if (replace || ps_tail == NULL) {
1481 free_preshared_list(&ps_head, &ps_tail);
1482 ps_head = tmp_head;
1483 ps_tail = tmp_tail;
1484 } else {
1485 ps_tail->pe_next = tmp_head;
1486 ps_tail = tmp_tail;
1487 }
1488 } else {
1489 /*
1490 * had problems reading new list; free it
1491 */
1492 free_preshared_list(&tmp_head, &tmp_tail);
1493 }
1494
1495 if (dupfound && (errmp == NULL)) {
1496 /* Hack to key off of later, not user visible */
1497 (void) pthread_rwlock_unlock(&ps_rwlock);
1498 return ("DUP");
1499 }
1500
1501 (void) pthread_rwlock_unlock(&ps_rwlock);
1502 return (errmp);
1503 }
1504
1505 /*
1506 * Returns 0 if requested entry not found; 1 if deleted successfully.
1507 * Holds ps_rwlock as writer.
1508 */
1509 int
1510 delete_ps(preshared_entry_t *delp)
1511 {
1512 preshared_entry_t *curp, *prevp;
1513
1514 (void) pthread_rwlock_wrlock(&ps_rwlock);
1515 if (ps_head == NULL) {
1516 (void) pthread_rwlock_unlock(&ps_rwlock);
1517 return (0);
1518 }
1519
1520 if (delp == ps_head) {
1521 /* CORNER CASE: Deletion of last entry */
1522 if (ps_head == ps_tail)
1523 ps_tail = NULL;
1524 ps_head = delp->pe_next;
1525 (void) pthread_rwlock_unlock(&ps_rwlock);
1526 PE_REFRELE(delp);
1527 return (1);
1528 }
1529
1530 for (prevp = ps_head, curp = ps_head->pe_next; curp != NULL;
1531 prevp = curp, curp = curp->pe_next) {
1532 if (curp == delp)
1533 break;
1534 }
1535 if (curp == NULL) {
1536 (void) pthread_rwlock_unlock(&ps_rwlock);
1537 return (0);
1538 }
1539
1540 prevp->pe_next = curp->pe_next;
1541 if (curp == ps_tail)
1542 ps_tail = prevp;
1543 (void) pthread_rwlock_unlock(&ps_rwlock);
1544 PE_REFRELE(curp);
1545 return (1);
1546 }
1547
1548 /*
1549 * return -1 on error, number of preshared entries written on success
1550 * Holds ps_rwlock as reader
1551 */
1552 int
1553 write_preshared(int fd, char **errmp)
1554 {
1555 preshared_entry_t *pep;
1556 FILE *ofile;
1557 char *keyp;
1558 int written = 0;
1559
1560 (void) pthread_rwlock_rdlock(&ps_rwlock);
1561 if ((ofile = fdopen(fd, "w+")) == NULL) {
1562 *errmp = strerror(errno);
1563 (void) pthread_rwlock_unlock(&ps_rwlock);
1564 return (-1);
1565 }
1566
1567 for (pep = ps_head; pep != NULL; pep = pep->pe_next) {
1568 const char *mdstr;
1569
1570 if ((keyp = getkeystr(pep->pe_keybuf, pep->pe_keybuf_bytes,
1571 pep->pe_keybuf_lbits)) == NULL) {
1572 *errmp = strerror(errno);
1573 (void) pthread_rwlock_unlock(&ps_rwlock);
1574 return (-1);
1575 }
1576
1577 if (pep->pe_locid != NULL) {
1578 (void) fprintf(ofile, "{\n"
1579 "\tlocalidtype %s\n\tlocalid %s\n",
1580 getidstr(pep->pe_locidtype), pep->pe_locid);
1581 } else {
1582 (void) fprintf(ofile,
1583 "{\n\tlocalidtype %s\n\tlocalid ",
1584 getidstr(pep->pe_locidtype));
1585 (void) dump_sockaddr(
1586 (struct sockaddr *)&pep->pe_locid_sa,
1587 (pep->pe_locid_plen > 0) ? pep->pe_locid_plen : 0,
1588 B_TRUE, ofile, B_FALSE);
1589 (void) fprintf(ofile, "\n");
1590 }
1591
1592 if (pep->pe_remid != NULL) {
1593 (void) fprintf(ofile,
1594 "\tremoteidtype %s\n\tremoteid %s\n",
1595 getidstr(pep->pe_remidtype), pep->pe_remid);
1596 } else {
1597 (void) fprintf(ofile,
1598 "\tremoteidtype %s\n\tremoteid ",
1599 getidstr(pep->pe_remidtype));
1600 (void) dump_sockaddr(
1601 (struct sockaddr *)&pep->pe_remid_sa,
1602 (pep->pe_remid_plen > 0) ? pep->pe_remid_plen : 0,
1603 B_TRUE, ofile, B_FALSE);
1604 (void) fprintf(ofile, "\n");
1605 }
1606
1607 mdstr = getikmstr(pep->pe_ike_mode);
1608 if (mdstr != NULL)
1609 (void) fprintf(ofile, "\tike_mode %s\n", mdstr);
1610
1611 (void) fprintf(ofile, "\tkey %s\n}\n", keyp);
1612 free(memset(keyp, 0, strlen(keyp)));
1613 written++;
1614 }
1615 (void) fclose(ofile);
1616
1617 (void) pthread_rwlock_unlock(&ps_rwlock);
1618 return (written);
1619 }
1620
1621 /*
1622 * Convert a PS_ID_* to an SADB_IDENTTYPE_* constant.
1623 * Returns SADB_IDENTTYPE_RESERVED on failure.
1624 */
1625 int
1626 psid2sadb(int psid)
1627 {
1628 switch (psid) {
1629 case PS_ID_IP:
1630 case PS_ID_IP4:
1631 case PS_ID_IP6:
1632 return (SADB_IDENTTYPE_RESERVED);
1633 case PS_ID_SUBNET:
1634 case PS_ID_SUBNET4:
1635 case PS_ID_SUBNET6:
1636 return (SADB_IDENTTYPE_PREFIX);
1637 case PS_ID_RANGE:
1638 case PS_ID_RANGE4:
1639 case PS_ID_RANGE6:
1640 return (SADB_X_IDENTTYPE_ADDR_RANGE);
1641 case PS_ID_ASN1DN:
1642 return (SADB_X_IDENTTYPE_DN);
1643 case PS_ID_ASN1GN:
1644 return (SADB_X_IDENTTYPE_GN);
1645 case PS_ID_KEYID:
1646 return (SADB_X_IDENTTYPE_KEY_ID);
1647 case PS_ID_FQDN:
1648 return (SADB_IDENTTYPE_FQDN);
1649 case PS_ID_USER_FQDN:
1650 return (SADB_IDENTTYPE_USER_FQDN);
1651 }
1652 return (SADB_IDENTTYPE_RESERVED);
1653 }
1654
1655 int
1656 sadb2psid(int sadb)
1657 {
1658 switch (sadb) {
1659 case SADB_IDENTTYPE_PREFIX:
1660 return (PS_ID_SUBNET);
1661 case SADB_X_IDENTTYPE_ADDR_RANGE:
1662 return (PS_ID_RANGE);
1663 case SADB_X_IDENTTYPE_DN:
1664 return (PS_ID_ASN1DN);
1665 case SADB_X_IDENTTYPE_GN:
1666 return (PS_ID_ASN1GN);
1667 case SADB_X_IDENTTYPE_KEY_ID:
1668 return (PS_ID_KEYID);
1669 case SADB_IDENTTYPE_FQDN:
1670 return (PS_ID_FQDN);
1671 case SADB_IDENTTYPE_USER_FQDN:
1672 return (PS_ID_USER_FQDN);
1673 }
1674 return (0);
1675 }
1676
1677 /*
1678 * Lookup preshared entry by ident
1679 * Holds ps_rwlock as reader
1680 */
1681 preshared_entry_t *
1682 lookup_ps_by_ident(sadb_ident_t *local, sadb_ident_t *remote)
1683 {
1684 int ltype, rtype;
1685 char *lid, *rid;
1686 preshared_entry_t *ps;
1687
1688 if (local == NULL || remote == NULL)
1689 return (NULL);
1690
1691 lid = (char *)(local + 1);
1692 rid = (char *)(remote + 1);
1693
1694 (void) pthread_rwlock_rdlock(&ps_rwlock);
1695 for (ps = ps_head; ps != NULL; ps = ps->pe_next) {
1696
1697 /*
1698 * Have to convert for each preshared (rather than converting
1699 * the passed-in sadb ids just once to preshared-style)
1700 * because there are multiple PS_ID_* for each SADB_IDENT_*.
1701 */
1702 ltype = psid2sadb(ps->pe_locidtype);
1703 rtype = psid2sadb(ps->pe_remidtype);
1704
1705 if ((local->sadb_ident_type != ltype) ||
1706 (remote->sadb_ident_type != rtype))
1707 continue;
1708
1709 if (ps->pe_locidtype == PS_ID_FQDN ||
1710 ps->pe_locidtype == PS_ID_USER_FQDN) {
1711 /*
1712 * Check for case insensitive match.
1713 */
1714 if ((strcasecmp(ps->pe_locid, lid) == 0) &&
1715 (strcasecmp(ps->pe_remid, rid) == 0))
1716 break;
1717 } else {
1718 /*
1719 * Otherwise just go for an exact match.
1720 */
1721 if ((strcmp(ps->pe_locid, lid) == 0) &&
1722 (strcmp(ps->pe_remid, rid) == 0))
1723 break;
1724 }
1725 }
1726 if (ps != NULL)
1727 PE_REFHOLD(ps);
1728 (void) pthread_rwlock_unlock(&ps_rwlock);
1729 return (ps);
1730 }
1731
1732 /*
1733 * Stolen from kernel spd.c - maybe this should go in libipsecutil
1734 *
1735 * sleazy prefix-length-based compare.
1736 */
1737 boolean_t
1738 ip_addr_match(uint8_t *addr1, int pfxlen, in6_addr_t *addr2p)
1739 {
1740 int offset = pfxlen>>3;
1741 int bitsleft = pfxlen & 7;
1742 uint8_t *addr2 = (uint8_t *)addr2p;
1743
1744 /*
1745 * and there was much evil..
1746 * XXX should inline-expand the bcmp here and do this 32 bits
1747 * or 64 bits at a time..
1748 */
1749 return ((bcmp(addr1, addr2, offset) == 0) &&
1750 ((bitsleft == 0) ||
1751 (((addr1[offset] ^ addr2[offset]) & (0xff<<(8-bitsleft))) == 0)));
1752 }
1753
1754 /*
1755 * Lookup preshared entry by v4 or v4 mapped v6 address
1756 * Holds ps_rwlock as reader
1757 */
1758 preshared_entry_t *
1759 lookup_ps_by_in_addr(struct in_addr *local, struct in_addr *remote)
1760 {
1761 struct in_addr *inp;
1762 struct in_addr in;
1763 struct sockaddr_in *loc_sin, *rem_sin;
1764 struct sockaddr_in6 *loc_sin6, *rem_sin6;
1765 preshared_entry_t *ps;
1766 boolean_t loc_is_v6, rem_is_v6;
1767 int pfxlen;
1768
1769 if (local == NULL || remote == NULL)
1770 return (NULL);
1771
1772 bzero(&in, sizeof (struct in_addr));
1773
1774 (void) pthread_rwlock_rdlock(&ps_rwlock);
1775 /*
1776 * Also looks up IPv6 id type entries for mapped addresses
1777 */
1778
1779 for (ps = ps_head; ps != NULL; ps = ps->pe_next) {
1780
1781 /* filter on relevant id type first */
1782 if ((ps->pe_locidtype != PS_ID_IP4 &&
1783 ps->pe_locidtype != PS_ID_IP6 &&
1784 ps->pe_locidtype != PS_ID_IP &&
1785 ps->pe_locidtype != PS_ID_SUBNET4 &&
1786 ps->pe_locidtype != PS_ID_SUBNET6 &&
1787 ps->pe_locidtype != PS_ID_SUBNET) ||
1788 (ps->pe_remidtype != PS_ID_IP4 &&
1789 ps->pe_remidtype != PS_ID_IP6 &&
1790 ps->pe_remidtype != PS_ID_IP &&
1791 ps->pe_remidtype != PS_ID_SUBNET4 &&
1792 ps->pe_remidtype != PS_ID_SUBNET6 &&
1793 ps->pe_remidtype != PS_ID_SUBNET))
1794 continue; /* local and/or remote id types invalid */
1795
1796 /* establish format of address */
1797 if ((ps->pe_locidtype == PS_ID_IP6 ||
1798 ps->pe_locidtype == PS_ID_SUBNET6) ||
1799 ((ps->pe_locidtype == PS_ID_IP ||
1800 ps->pe_locidtype == PS_ID_SUBNET) &&
1801 check_if_v6(ps->pe_locid)))
1802 loc_is_v6 = B_TRUE;
1803 else
1804 loc_is_v6 = B_FALSE;
1805 if ((ps->pe_remidtype == PS_ID_IP6 ||
1806 ps->pe_remidtype == PS_ID_SUBNET6) ||
1807 ((ps->pe_locidtype == PS_ID_IP ||
1808 ps->pe_locidtype == PS_ID_SUBNET) &&
1809 check_if_v6(ps->pe_remid)))
1810 rem_is_v6 = B_TRUE;
1811 else
1812 rem_is_v6 = B_FALSE;
1813
1814 loc_sin = (struct sockaddr_in *)&ps->pe_locid_sa;
1815 rem_sin = (struct sockaddr_in *)&ps->pe_remid_sa;
1816 loc_sin6 = (struct sockaddr_in6 *)&ps->pe_locid_sa;
1817 rem_sin6 = (struct sockaddr_in6 *)&ps->pe_remid_sa;
1818
1819 /* if v6 format, it is only interesting if v4mapped */
1820 if (loc_is_v6 && !IN6_IS_ADDR_V4MAPPED(&loc_sin6->sin6_addr))
1821 continue; /* not v4 mapped v6 address */
1822 if (rem_is_v6 && !IN6_IS_ADDR_V4MAPPED(&rem_sin6->sin6_addr))
1823 continue; /* not v4 mapped v6 address */
1824
1825
1826 /* match localid */
1827 if (loc_is_v6) {
1828 IN6_V4MAPPED_TO_INADDR(&loc_sin6->sin6_addr, &in);
1829 inp = ∈
1830 } else {
1831 inp = &loc_sin->sin_addr;
1832 }
1833
1834 if (ps->pe_locid_plen < 0)
1835 pfxlen = ADDRBITS_V4;
1836 else
1837 pfxlen = ps->pe_locid_plen;
1838 if (!ip_addr_match((uint8_t *)&inp->s_addr, pfxlen,
1839 (in6_addr_t *)&local->s_addr))
1840 continue; /* local id mismatched */
1841
1842 /* match remote id */
1843 if (rem_is_v6) {
1844 IN6_V4MAPPED_TO_INADDR(&rem_sin6->sin6_addr, &in);
1845 inp = ∈
1846 } else {
1847 inp = &rem_sin->sin_addr;
1848 }
1849
1850 if (ps->pe_remid_plen < 0)
1851 pfxlen = ADDRBITS_V4;
1852 else
1853 pfxlen = ps->pe_remid_plen;
1854 if (!ip_addr_match((uint8_t *)&inp->s_addr, pfxlen,
1855 (in6_addr_t *)&remote->s_addr))
1856 continue; /* remote id mismatched */
1857
1858 /* match found for both local and remote id */
1859 break; /* out of loop */
1860 }
1861 if (ps != NULL)
1862 PE_REFHOLD(ps);
1863 (void) pthread_rwlock_unlock(&ps_rwlock);
1864 return (ps); /* NULL if loop expires on its own */
1865 }
1866
1867 /*
1868 * Lookup preshared entry by v6 address
1869 * Holds ps_rwlock as reader
1870 */
1871 preshared_entry_t *
1872 lookup_ps_by_in6_addr(struct in6_addr *local, struct in6_addr *remote)
1873 {
1874 preshared_entry_t *ps;
1875 struct sockaddr_in6 *loc_sin6, *rem_sin6;
1876 int pfxlen;
1877
1878 if (local == NULL || remote == NULL)
1879 return (NULL);
1880
1881 (void) pthread_rwlock_rdlock(&ps_rwlock);
1882 for (ps = ps_head; ps != NULL; ps = ps->pe_next) {
1883
1884 /* filter on relevant id type first */
1885 if ((ps->pe_locidtype != PS_ID_IP6 &&
1886 ps->pe_locidtype != PS_ID_IP &&
1887 ps->pe_locidtype != PS_ID_SUBNET &&
1888 ps->pe_locidtype != PS_ID_SUBNET6) ||
1889 (ps->pe_remidtype != PS_ID_IP6 &&
1890 ps->pe_remidtype != PS_ID_IP &&
1891 ps->pe_remidtype != PS_ID_SUBNET &&
1892 ps->pe_remidtype != PS_ID_SUBNET6))
1893 continue; /* local and/or remote id types invalid */
1894
1895 /*
1896 * if PS_ID_IP or PS_ID_SUBNET, it is
1897 * only interesting if v6 format
1898 */
1899 if ((ps->pe_locidtype == PS_ID_IP ||
1900 ps->pe_locidtype == PS_ID_SUBNET) &&
1901 !check_if_v6(ps->pe_locid))
1902 continue; /* not v6 address */
1903 if ((ps->pe_remidtype == PS_ID_IP ||
1904 ps->pe_remidtype == PS_ID_SUBNET) &&
1905 !check_if_v6(ps->pe_remid))
1906 continue; /* not v6 address */
1907
1908 loc_sin6 = (struct sockaddr_in6 *)&ps->pe_locid_sa;
1909 rem_sin6 = (struct sockaddr_in6 *)&ps->pe_remid_sa;
1910
1911 if (ps->pe_locid_plen < 0)
1912 pfxlen = ADDRBITS_V6;
1913 else
1914 pfxlen = ps->pe_locid_plen;
1915 if (!ip_addr_match((uint8_t *)&loc_sin6->sin6_addr, pfxlen,
1916 (in6_addr_t *)local))
1917 continue; /* local id mismatched */
1918
1919 if (ps->pe_remid_plen < 0)
1920 pfxlen = ADDRBITS_V6;
1921 else
1922 pfxlen = ps->pe_remid_plen;
1923 if (!ip_addr_match((uint8_t *)&rem_sin6->sin6_addr, pfxlen,
1924 (in6_addr_t *)remote))
1925 continue; /* remote id mismatched */
1926 /* match found for both local and remote id */
1927 break; /* out of loop */
1928 }
1929 if (ps != NULL)
1930 PE_REFHOLD(ps);
1931 (void) pthread_rwlock_unlock(&ps_rwlock);
1932 return (ps); /* NULL if loop expires on its own */
1933 }
1934
1935 /*
1936 * Lookup nth preshared key entry
1937 * Holds ps_rwlock as reader
1938 */
1939 preshared_entry_t *
1940 lookup_nth_ps(int n)
1941 {
1942 preshared_entry_t *ps;
1943 int cnt;
1944
1945 (void) pthread_rwlock_rdlock(&ps_rwlock);
1946 for (cnt = 0, ps = ps_head; (cnt < n) && (ps != NULL);
1947 cnt++, ps = ps->pe_next)
1948 ;
1949 if (ps != NULL)
1950 PE_REFHOLD(ps);
1951 (void) pthread_rwlock_unlock(&ps_rwlock);
1952 return (ps);
1953 }
1954
1955 /*
1956 * Actual freeing function.
1957 */
1958 void
1959 free_preshared(preshared_entry_t *pe)
1960 {
1961 assert(pe->pe_refcnt == 0);
1962 free(pe->pe_locid);
1963 free(pe->pe_remid);
1964 /* Use memset()'s return value to our advantage. */
1965 free(memset(pe->pe_keybuf, 0, pe->pe_keybuf_bytes));
1966 free(pe);
1967 }
1968
1969 /*
1970 * Read in a list of pre-shared keys. Called from main() when the daemon first
1971 * starts.
1972 */
1973 void
1974 preshared_init(boolean_t ignore_errors)
1975 {
1976 const char *filename = PRESHARED_KEY_FILE;
1977 char *errorstr;
1978
1979 bunyan_info(log, "Loading preshared keys", BUNYAN_T_END);
1980 errorstr = preshared_load(filename, -1, B_TRUE);
1981
1982 if (errorstr != NULL) {
1983 if (strncmp(errorstr, "DUP", 3) == 0)
1984 errorstr = gettext("Duplicate entries ignored\n");
1985 /*
1986 * Error handling... Print to terminal, if exists.
1987 * Debug logging already taken care of by other functions.
1988 * Don't exit because we want to load other policy.
1989 */
1990 bunyan_error(log, "Error reading preshared file",
1991 BUNYAN_T_STRING, "filename", filename,
1992 BUNYAN_T_STRING, "errmsg", errorstr);
1993 if (!ignore_errors)
1994 err(EXIT_FAILURE, "Fatal errors in %s", filename);
1995 }
1996 }
1997
1998 /*
1999 * Called when the daemon catches SIGHUP.
2000 * Currently equivalent to preshared_init().
2001 */
2002 void
2003 preshared_reload(void)
2004 {
2005 preshared_init(B_FALSE);
2006 }
2007
2008 /*
2009 * Random Notes:
2010 * (a)
2011 * Maybe a better syntax for fields is following which eliminates
2012 * semantic relationships between two different fields (id and idtype) ???
2013 * E.g.
2014 * {
2015 * ...
2016 * localid ipv4 1.2.3.4
2017 * remoteid rangev4 1.2.3.4-5.6.7.8
2018 * ...
2019 * }
2020 * Current design causes us to delay certain verifications into a
2021 * postprocess_XXX() routine which otherwise could be done while
2022 * parsing if syntax was as above.
2023 *
2024 * (b)
2025 * Current error handling has a generic design that prints only
2026 * error message, entry number and line number. Other options are
2027 * possible (e.g. parsekey() "original" code from danmcd prints
2028 * error messages specific to the error context which have more
2029 * detailed context). Perhaps we should change to direct printing
2030 * of specific error messages globally later, but for now stick
2031 * to the simple model coded above.
2032 * (c) The getnexttoken() part can be improved by passing it some context
2033 * such as "expected token" and maybe the fieldname. This *may* help
2034 * allow a more flexible syntax for complex tokens such as ranges.
2035 * which cannot currently embed spaces but it would be nice to allow
2036 * them to do that and be delimited with a context sensitive delimiter.
2037 * (d) Needs detection of duplicates in the database before inserting new
2038 * entry.
2039 * (e) Can be enhanced to do hashes and better structures than a linked list
2040 * of entries.
2041 */