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 (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * NOTE:I'm trying to use "struct sadb_foo" instead of "sadb_foo_t"
27 * as a maximal PF_KEY portability test.
28 *
29 * Also, this is a deliberately single-threaded app, also for portability
30 * to systems without POSIX threads.
31 */
32
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/socket.h>
36 #include <sys/sysmacros.h>
37 #include <sys/fcntl.h>
38 #include <net/pfkeyv2.h>
39 #include <arpa/inet.h>
40 #include <netinet/in.h>
41 #include <sys/uio.h>
42
43 #include <syslog.h>
44 #include <signal.h>
45 #include <unistd.h>
46 #include <limits.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <stdarg.h>
50 #include <netdb.h>
51 #include <pwd.h>
52 #include <errno.h>
53 #include <libintl.h>
54 #include <locale.h>
55 #include <fcntl.h>
56 #include <strings.h>
57 #include <ctype.h>
58 #include <sys/cladm.h>
59
60 #include <ipsec_util.h>
61
62 static int keysock;
63 static int cluster_socket;
64 static uint32_t seq;
65 static pid_t mypid;
66 static boolean_t vflag = B_FALSE; /* Verbose? */
67 static boolean_t cflag = B_FALSE; /* Check Only */
68
69 char *my_fmri = NULL;
70 FILE *debugfile = stdout;
71 static struct sockaddr_in cli_addr;
72 static boolean_t in_cluster_mode = B_FALSE;
73
74 #define MAX_GET_SIZE 1024
75 /*
76 * WARN() and ERROR() do the same thing really, with ERROR() the function
77 * that prints the error buffer needs to be called at the end of a code block
78 * This will print out all accumulated errors before bailing. The WARN()
79 * macro calls handle_errors() in such a way that it prints the message
80 * then continues.
81 * If the FATAL() macro used call handle_errors() immediately.
82 */
83 #define ERROR(x, y, z) x = record_error(x, y, z)
84 #define ERROR1(w, x, y, z) w = record_error(w, x, y, z)
85 #define ERROR2(v, w, x, y, z) v = record_error(v, w, x, y, z)
86 #define WARN(x, y, z) ERROR(x, y, z);\
87 handle_errors(x, NULL, B_FALSE, B_FALSE); x = NULL
88 #define WARN1(w, x, y, z) ERROR1(w, x, y, z);\
89 handle_errors(w, NULL, B_FALSE, B_FALSE); w = NULL
90 #define WARN2(v, w, x, y, z) ERROR2(v, w, x, y, z);\
91 handle_errors(v, NULL, B_FALSE, B_FALSE); v = NULL
92 #define FATAL(x, y, z) ERROR(x, y, z);\
93 handle_errors(x, y, B_TRUE, B_TRUE)
94 #define FATAL1(w, x, y, z) ERROR1(w, x, y, z);\
95 handle_errors(w, x, B_TRUE, B_TRUE)
96
97 /* Defined as a uint64_t array for alignment purposes. */
98 static uint64_t get_buffer[MAX_GET_SIZE];
99
100 /*
101 * Disable default TAB completion for now (until some brave soul tackles it).
102 */
103 /* ARGSUSED */
104 static
CPL_MATCH_FN(no_match)105 CPL_MATCH_FN(no_match)
106 {
107 return (0);
108 }
109
110 /*
111 * Create/Grow a buffer large enough to hold error messages. If *ebuf
112 * is not NULL then it will contain a copy of the command line that
113 * triggered the error/warning, copy this into a new buffer or
114 * append new messages to the existing buffer.
115 */
116 /*PRINTFLIKE1*/
117 char *
record_error(char * ep,char * ebuf,char * fmt,...)118 record_error(char *ep, char *ebuf, char *fmt, ...)
119 {
120 char *err_ptr;
121 char tmp_buff[1024];
122 va_list ap;
123 int length = 0;
124 err_ptr = ep;
125
126 va_start(ap, fmt);
127 length = vsnprintf(tmp_buff, sizeof (tmp_buff), fmt, ap);
128 va_end(ap);
129
130 /* There is a new line character */
131 length++;
132
133 if (ep == NULL) {
134 if (ebuf != NULL)
135 length += strlen(ebuf);
136 } else {
137 length += strlen(ep);
138 }
139
140 if (err_ptr == NULL)
141 err_ptr = calloc(length, sizeof (char));
142 else
143 err_ptr = realloc(err_ptr, length);
144
145 if (err_ptr == NULL)
146 Bail("realloc() failure");
147
148 /*
149 * If (ep == NULL) then this is the first error to record,
150 * copy in the command line that triggered this error/warning.
151 */
152 if (ep == NULL && ebuf != NULL)
153 (void) strlcpy(err_ptr, ebuf, length);
154
155 /*
156 * Now the actual error.
157 */
158 (void) strlcat(err_ptr, tmp_buff, length);
159 return (err_ptr);
160 }
161
162 /*
163 * If not in interactive mode print usage message and exit.
164 */
165 static void
usage(void)166 usage(void)
167 {
168 if (!interactive) {
169 (void) fprintf(stderr, gettext("Usage:\t"
170 "ipseckey [ -nvp ] | cmd [sa_type] [extfield value]*\n"));
171 (void) fprintf(stderr,
172 gettext("\tipseckey [ -nvp ] -f infile\n"));
173 (void) fprintf(stderr,
174 gettext("\tipseckey [ -nvp ] -s outfile\n"));
175 EXIT_FATAL(NULL);
176 } else {
177 (void) fprintf(stderr,
178 gettext("Type help or ? for usage info\n"));
179 }
180 }
181
182
183 /*
184 * Print out any errors, tidy up as required.
185 * error pointer ep will be free()'d
186 */
187 void
handle_errors(char * ep,char * ebuf,boolean_t fatal,boolean_t done)188 handle_errors(char *ep, char *ebuf, boolean_t fatal, boolean_t done)
189 {
190 if (ep != NULL) {
191 if (my_fmri == NULL) {
192 /*
193 * For now suppress the errors when run from smf(5)
194 * because potentially sensitive information could
195 * end up in a publicly readable logfile.
196 */
197 (void) fprintf(stdout, "%s\n", ep);
198 (void) fflush(stdout);
199 }
200 free(ep);
201 if (fatal) {
202 if (ebuf != NULL) {
203 free(ebuf);
204 }
205 /* reset command buffer */
206 if (interactive)
207 longjmp(env, 1);
208 } else {
209 return;
210 }
211 } else {
212 /*
213 * No errors, if this is the last time that this function
214 * is called, free(ebuf) and reset command buffer.
215 */
216 if (done) {
217 if (ebuf != NULL) {
218 free(ebuf);
219 }
220 /* reset command buffer */
221 if (interactive)
222 longjmp(env, 1);
223 }
224 return;
225 }
226 EXIT_FATAL(NULL);
227 }
228
229 /*
230 * Initialize a PF_KEY base message.
231 */
232 static void
msg_init(struct sadb_msg * msg,uint8_t type,uint8_t satype)233 msg_init(struct sadb_msg *msg, uint8_t type, uint8_t satype)
234 {
235 msg->sadb_msg_version = PF_KEY_V2;
236 msg->sadb_msg_type = type;
237 msg->sadb_msg_errno = 0;
238 msg->sadb_msg_satype = satype;
239 /* For starters... */
240 msg->sadb_msg_len = SADB_8TO64(sizeof (*msg));
241 msg->sadb_msg_reserved = 0;
242 msg->sadb_msg_seq = ++seq;
243 msg->sadb_msg_pid = mypid;
244 }
245
246 /*
247 * parseXXX and rparseXXX commands parse input and convert them to PF_KEY
248 * field values, or do the reverse for the purposes of saving the SA tables.
249 * (See the save_XXX functions.)
250 */
251
252 #define CMD_NONE 0
253 #define CMD_UPDATE 2
254 #define CMD_UPDATE_PAIR 3
255 #define CMD_ADD 4
256 #define CMD_DELETE 5
257 #define CMD_DELETE_PAIR 6
258 #define CMD_GET 7
259 #define CMD_FLUSH 9
260 #define CMD_DUMP 10
261 #define CMD_MONITOR 11
262 #define CMD_PMONITOR 12
263 #define CMD_QUIT 13
264 #define CMD_SAVE 14
265 #define CMD_HELP 15
266
267 /*
268 * Parse the command.
269 */
270 static int
parsecmd(char * cmdstr)271 parsecmd(char *cmdstr)
272 {
273 static struct cmdtable {
274 char *cmd;
275 int token;
276 } table[] = {
277 /*
278 * Q: Do we want to do GETSPI?
279 * A: No, it's for automated key mgmt. only. Either that,
280 * or it isn't relevant until we support non IPsec SA types.
281 */
282 {"update", CMD_UPDATE},
283 {"update-pair", CMD_UPDATE_PAIR},
284 {"add", CMD_ADD},
285 {"delete", CMD_DELETE},
286 {"delete-pair", CMD_DELETE_PAIR},
287 {"get", CMD_GET},
288 /*
289 * Q: And ACQUIRE and REGISTER and EXPIRE?
290 * A: not until we support non IPsec SA types.
291 */
292 {"flush", CMD_FLUSH},
293 {"dump", CMD_DUMP},
294 {"monitor", CMD_MONITOR},
295 {"passive_monitor", CMD_PMONITOR},
296 {"pmonitor", CMD_PMONITOR},
297 {"quit", CMD_QUIT},
298 {"exit", CMD_QUIT},
299 {"save", CMD_SAVE},
300 {"help", CMD_HELP},
301 {"?", CMD_HELP},
302 {NULL, CMD_NONE}
303 };
304 struct cmdtable *ct = table;
305
306 while (ct->cmd != NULL && strcmp(ct->cmd, cmdstr) != 0)
307 ct++;
308 return (ct->token);
309 }
310
311 /*
312 * Convert a number from a command line. I picked "u_longlong_t" for the
313 * number because we need the largest number available. Also, the strto<num>
314 * calls don't deal in units of uintNN_t.
315 */
316 static u_longlong_t
parsenum(char * num,boolean_t bail,char * ebuf)317 parsenum(char *num, boolean_t bail, char *ebuf)
318 {
319 u_longlong_t rc = 0;
320 char *end = NULL;
321 char *ep = NULL;
322
323 if (num == NULL) {
324 FATAL(ep, ebuf, gettext("Unexpected end of command line,"
325 " was expecting a number.\n"));
326 /* NOTREACHED */
327 }
328
329 errno = 0;
330 rc = strtoull(num, &end, 0);
331 if (errno != 0 || end == num || *end != '\0') {
332 if (bail) {
333 FATAL1(ep, ebuf, gettext(
334 "Expecting a number, not \"%s\"!\n"), num);
335 } else {
336 /*
337 * -1, while not optimal, is sufficiently out of range
338 * for most of this function's applications when
339 * we don't just bail.
340 */
341 return ((u_longlong_t)-1);
342 }
343 }
344 handle_errors(ep, NULL, B_FALSE, B_FALSE);
345 return (rc);
346 }
347
348 /*
349 * Parse and reverse parse a specific SA type (AH, ESP, etc.).
350 */
351 static struct typetable {
352 char *type;
353 int token;
354 } type_table[] = {
355 {"all", SADB_SATYPE_UNSPEC},
356 {"ah", SADB_SATYPE_AH},
357 {"esp", SADB_SATYPE_ESP},
358 /* PF_KEY NOTE: More to come if net/pfkeyv2.h gets updated. */
359 {NULL, 0} /* Token value is irrelevant for this entry. */
360 };
361
362
363 static int
parsesatype(char * type,char * ebuf)364 parsesatype(char *type, char *ebuf)
365 {
366 struct typetable *tt = type_table;
367 char *ep = NULL;
368
369 if (type == NULL)
370 return (SADB_SATYPE_UNSPEC);
371
372 while (tt->type != NULL && strcasecmp(tt->type, type) != 0)
373 tt++;
374
375 /*
376 * New SA types (including ones keysock maintains for user-land
377 * protocols) may be added, so parse a numeric value if possible.
378 */
379 if (tt->type == NULL) {
380 tt->token = (int)parsenum(type, B_FALSE, ebuf);
381 if (tt->token == -1) {
382 ERROR1(ep, ebuf, gettext(
383 "Unknown SA type (%s).\n"), type);
384 tt->token = SADB_SATYPE_UNSPEC;
385 }
386 }
387 handle_errors(ep, NULL, interactive ? B_TRUE : B_FALSE, B_FALSE);
388 return (tt->token);
389 }
390
391 #define NEXTEOF 0
392 #define NEXTNONE 1
393 #define NEXTNUM 2
394 #define NEXTSTR 3
395 #define NEXTNUMSTR 4
396 #define NEXTADDR 5
397 #define NEXTHEX 6
398 #define NEXTIDENT 7
399 #define NEXTADDR4 8
400 #define NEXTADDR6 9
401 #define NEXTLABEL 10
402
403 #define TOK_EOF 0
404 #define TOK_UNKNOWN 1
405 #define TOK_SPI 2
406 #define TOK_REPLAY 3
407 #define TOK_STATE 4
408 #define TOK_AUTHALG 5
409 #define TOK_ENCRALG 6
410 #define TOK_FLAGS 7
411 #define TOK_SOFT_ALLOC 8
412 #define TOK_SOFT_BYTES 9
413 #define TOK_SOFT_ADDTIME 10
414 #define TOK_SOFT_USETIME 11
415 #define TOK_HARD_ALLOC 12
416 #define TOK_HARD_BYTES 13
417 #define TOK_HARD_ADDTIME 14
418 #define TOK_HARD_USETIME 15
419 #define TOK_CURRENT_ALLOC 16
420 #define TOK_CURRENT_BYTES 17
421 #define TOK_CURRENT_ADDTIME 18
422 #define TOK_CURRENT_USETIME 19
423 #define TOK_SRCADDR 20
424 #define TOK_DSTADDR 21
425 #define TOK_PROXYADDR 22
426 #define TOK_AUTHKEY 23
427 #define TOK_ENCRKEY 24
428 #define TOK_SRCIDTYPE 25
429 #define TOK_DSTIDTYPE 26
430 #define TOK_DPD 27
431 #define TOK_SENS_LEVEL 28
432 #define TOK_SENS_MAP 29
433 #define TOK_INTEG_LEVEL 30
434 #define TOK_INTEG_MAP 31
435 #define TOK_SRCADDR6 32
436 #define TOK_DSTADDR6 33
437 #define TOK_PROXYADDR6 34
438 #define TOK_SRCPORT 35
439 #define TOK_DSTPORT 36
440 #define TOK_PROTO 37
441 #define TOK_ENCAP 38
442 #define TOK_NATLOC 39
443 #define TOK_NATREM 40
444 #define TOK_NATLPORT 41
445 #define TOK_NATRPORT 42
446 #define TOK_IPROTO 43
447 #define TOK_IDSTADDR 44
448 #define TOK_IDSTADDR6 45
449 #define TOK_ISRCPORT 46
450 #define TOK_IDSTPORT 47
451 #define TOK_PAIR_SPI 48
452 #define TOK_FLAG_INBOUND 49
453 #define TOK_FLAG_OUTBOUND 50
454 #define TOK_REPLAY_VALUE 51
455 #define TOK_IDLE_ADDTIME 52
456 #define TOK_IDLE_USETIME 53
457 #define TOK_RESERVED 54
458 #define TOK_LABEL 55
459 #define TOK_OLABEL 56
460 #define TOK_IMPLABEL 57
461
462
463 static struct toktable {
464 char *string;
465 int token;
466 int next;
467 } tokens[] = {
468 /* "String", token value, next arg is */
469 {"spi", TOK_SPI, NEXTNUM},
470 {"pair-spi", TOK_PAIR_SPI, NEXTNUM},
471 {"replay", TOK_REPLAY, NEXTNUM},
472 {"state", TOK_STATE, NEXTNUMSTR},
473 {"auth_alg", TOK_AUTHALG, NEXTNUMSTR},
474 {"authalg", TOK_AUTHALG, NEXTNUMSTR},
475 {"encr_alg", TOK_ENCRALG, NEXTNUMSTR},
476 {"encralg", TOK_ENCRALG, NEXTNUMSTR},
477 {"flags", TOK_FLAGS, NEXTNUM},
478 {"soft_alloc", TOK_SOFT_ALLOC, NEXTNUM},
479 {"soft_bytes", TOK_SOFT_BYTES, NEXTNUM},
480 {"soft_addtime", TOK_SOFT_ADDTIME, NEXTNUM},
481 {"soft_usetime", TOK_SOFT_USETIME, NEXTNUM},
482 {"hard_alloc", TOK_HARD_ALLOC, NEXTNUM},
483 {"hard_bytes", TOK_HARD_BYTES, NEXTNUM},
484 {"hard_addtime", TOK_HARD_ADDTIME, NEXTNUM},
485 {"hard_usetime", TOK_HARD_USETIME, NEXTNUM},
486 {"current_alloc", TOK_CURRENT_ALLOC, NEXTNUM},
487 {"current_bytes", TOK_CURRENT_BYTES, NEXTNUM},
488 {"current_addtime", TOK_CURRENT_ADDTIME, NEXTNUM},
489 {"current_usetime", TOK_CURRENT_USETIME, NEXTNUM},
490
491 {"saddr", TOK_SRCADDR, NEXTADDR},
492 {"srcaddr", TOK_SRCADDR, NEXTADDR},
493 {"src", TOK_SRCADDR, NEXTADDR},
494 {"daddr", TOK_DSTADDR, NEXTADDR},
495 {"dstaddr", TOK_DSTADDR, NEXTADDR},
496 {"dst", TOK_DSTADDR, NEXTADDR},
497 {"proxyaddr", TOK_PROXYADDR, NEXTADDR},
498 {"proxy", TOK_PROXYADDR, NEXTADDR},
499 {"innersrc", TOK_PROXYADDR, NEXTADDR},
500 {"isrc", TOK_PROXYADDR, NEXTADDR},
501 {"innerdst", TOK_IDSTADDR, NEXTADDR},
502 {"idst", TOK_IDSTADDR, NEXTADDR},
503
504 {"sport", TOK_SRCPORT, NEXTNUM},
505 {"dport", TOK_DSTPORT, NEXTNUM},
506 {"innersport", TOK_ISRCPORT, NEXTNUM},
507 {"isport", TOK_ISRCPORT, NEXTNUM},
508 {"innerdport", TOK_IDSTPORT, NEXTNUM},
509 {"idport", TOK_IDSTPORT, NEXTNUM},
510 {"proto", TOK_PROTO, NEXTNUM},
511 {"ulp", TOK_PROTO, NEXTNUM},
512 {"iproto", TOK_IPROTO, NEXTNUM},
513 {"iulp", TOK_IPROTO, NEXTNUM},
514
515 {"saddr6", TOK_SRCADDR6, NEXTADDR},
516 {"srcaddr6", TOK_SRCADDR6, NEXTADDR},
517 {"src6", TOK_SRCADDR6, NEXTADDR},
518 {"daddr6", TOK_DSTADDR6, NEXTADDR},
519 {"dstaddr6", TOK_DSTADDR6, NEXTADDR},
520 {"dst6", TOK_DSTADDR6, NEXTADDR},
521 {"proxyaddr6", TOK_PROXYADDR6, NEXTADDR},
522 {"proxy6", TOK_PROXYADDR6, NEXTADDR},
523 {"innersrc6", TOK_PROXYADDR6, NEXTADDR},
524 {"isrc6", TOK_PROXYADDR6, NEXTADDR},
525 {"innerdst6", TOK_IDSTADDR6, NEXTADDR},
526 {"idst6", TOK_IDSTADDR6, NEXTADDR},
527
528 {"authkey", TOK_AUTHKEY, NEXTHEX},
529 {"encrkey", TOK_ENCRKEY, NEXTHEX},
530 {"srcidtype", TOK_SRCIDTYPE, NEXTIDENT},
531 {"dstidtype", TOK_DSTIDTYPE, NEXTIDENT},
532 {"dpd", TOK_DPD, NEXTNUM},
533 {"sens_level", TOK_SENS_LEVEL, NEXTNUM},
534 {"sens_map", TOK_SENS_MAP, NEXTHEX},
535 {"integ_level", TOK_INTEG_LEVEL, NEXTNUM},
536 {"integ_map", TOK_INTEG_MAP, NEXTHEX},
537 {"nat_loc", TOK_NATLOC, NEXTADDR},
538 {"nat_rem", TOK_NATREM, NEXTADDR},
539 {"nat_lport", TOK_NATLPORT, NEXTNUM},
540 {"nat_rport", TOK_NATRPORT, NEXTNUM},
541 {"encap", TOK_ENCAP, NEXTNUMSTR},
542
543 {"outbound", TOK_FLAG_OUTBOUND, NULL},
544 {"inbound", TOK_FLAG_INBOUND, NULL},
545
546 {"reserved_bits", TOK_RESERVED, NEXTNUM},
547 {"replay_value", TOK_REPLAY_VALUE, NEXTNUM},
548 {"idle_addtime", TOK_IDLE_ADDTIME, NEXTNUM},
549 {"idle_usetime", TOK_IDLE_USETIME, NEXTNUM},
550
551 {"label", TOK_LABEL, NEXTLABEL},
552 {"outer-label", TOK_OLABEL, NEXTLABEL},
553 {"implicit-label", TOK_IMPLABEL, NEXTLABEL},
554
555 {NULL, TOK_UNKNOWN, NEXTEOF}
556 };
557
558 /*
559 * Q: Do I need stuff for proposals, combinations, supported algorithms,
560 * or SPI ranges?
561 *
562 * A: Probably not, but you never know.
563 *
564 * Parse out extension header type values.
565 */
566 static int
parseextval(char * value,int * next)567 parseextval(char *value, int *next)
568 {
569 struct toktable *tp;
570
571 if (value == NULL)
572 return (TOK_EOF);
573
574 for (tp = tokens; tp->string != NULL; tp++)
575 if (strcmp(value, tp->string) == 0)
576 break;
577
578 /*
579 * Since the OS controls what extensions are available, we don't have
580 * to parse numeric values here.
581 */
582
583 *next = tp->next;
584 return (tp->token);
585 }
586
587 /*
588 * Parse possible state values.
589 */
590 static uint8_t
parsestate(char * state,char * ebuf)591 parsestate(char *state, char *ebuf)
592 {
593 struct states {
594 char *state;
595 uint8_t retval;
596 } states[] = {
597 {"larval", SADB_SASTATE_LARVAL},
598 {"mature", SADB_SASTATE_MATURE},
599 {"dying", SADB_SASTATE_DYING},
600 {"dead", SADB_SASTATE_DEAD},
601 {NULL, 0}
602 };
603 struct states *sp;
604 char *ep = NULL;
605
606 if (state == NULL) {
607 FATAL(ep, ebuf, "Unexpected end of command line "
608 "was expecting a state.\n");
609 }
610
611 for (sp = states; sp->state != NULL; sp++) {
612 if (strcmp(sp->state, state) == 0)
613 return (sp->retval);
614 }
615 ERROR1(ep, ebuf, gettext("Unknown state type \"%s\"\n"), state);
616 handle_errors(ep, NULL, B_FALSE, B_FALSE);
617 return (0);
618 }
619
620 /*
621 * Return the numerical algorithm identifier corresponding to the specified
622 * algorithm name.
623 */
624 static uint8_t
parsealg(char * alg,int proto_num,char * ebuf)625 parsealg(char *alg, int proto_num, char *ebuf)
626 {
627 u_longlong_t invalue;
628 struct ipsecalgent *algent;
629 char *ep = NULL;
630
631 if (alg == NULL) {
632 FATAL(ep, ebuf, gettext("Unexpected end of command line, "
633 "was expecting an algorithm name.\n"));
634 }
635
636 algent = getipsecalgbyname(alg, proto_num, NULL);
637 if (algent != NULL) {
638 uint8_t alg_num;
639
640 alg_num = algent->a_alg_num;
641 if (ALG_FLAG_COUNTERMODE & algent->a_alg_flags)
642 WARN1(ep, ebuf, gettext(
643 "Using manual keying with a Counter mode algorithm "
644 "such as \"%s\" may be insecure!\n"),
645 algent->a_names[0]);
646 freeipsecalgent(algent);
647
648 return (alg_num);
649 }
650
651 /*
652 * Since algorithms can be loaded during kernel run-time, check for
653 * numeric algorithm values too. PF_KEY can catch bad ones with EINVAL.
654 */
655 invalue = parsenum(alg, B_FALSE, ebuf);
656 if (invalue != (u_longlong_t)-1 &&
657 (u_longlong_t)(invalue & (u_longlong_t)0xff) == invalue)
658 return ((uint8_t)invalue);
659
660 if (proto_num == IPSEC_PROTO_ESP) {
661 ERROR1(ep, ebuf, gettext(
662 "Unknown encryption algorithm type \"%s\"\n"), alg);
663 } else {
664 ERROR1(ep, ebuf, gettext(
665 "Unknown authentication algorithm type \"%s\"\n"), alg);
666 }
667 handle_errors(ep, NULL, B_FALSE, B_FALSE);
668 return (0);
669 }
670
671 /*
672 * Parse and reverse parse out a source/destination ID type.
673 */
674 static struct idtypes {
675 char *idtype;
676 uint8_t retval;
677 } idtypes[] = {
678 {"prefix", SADB_IDENTTYPE_PREFIX},
679 {"fqdn", SADB_IDENTTYPE_FQDN},
680 {"domain", SADB_IDENTTYPE_FQDN},
681 {"domainname", SADB_IDENTTYPE_FQDN},
682 {"user_fqdn", SADB_IDENTTYPE_USER_FQDN},
683 {"mailbox", SADB_IDENTTYPE_USER_FQDN},
684 {"der_dn", SADB_X_IDENTTYPE_DN},
685 {"der_gn", SADB_X_IDENTTYPE_GN},
686 {NULL, 0}
687 };
688
689 static uint16_t
parseidtype(char * type,char * ebuf)690 parseidtype(char *type, char *ebuf)
691 {
692 struct idtypes *idp;
693 u_longlong_t invalue;
694 char *ep = NULL;
695
696 if (type == NULL) {
697 /* Shouldn't reach here, see callers for why. */
698 FATAL(ep, ebuf, gettext("Unexpected end of command line, "
699 "was expecting a type.\n"));
700 }
701
702 for (idp = idtypes; idp->idtype != NULL; idp++) {
703 if (strcasecmp(idp->idtype, type) == 0)
704 return (idp->retval);
705 }
706 /*
707 * Since identity types are almost arbitrary, check for numeric
708 * algorithm values too. PF_KEY can catch bad ones with EINVAL.
709 */
710 invalue = parsenum(type, B_FALSE, ebuf);
711 if (invalue != (u_longlong_t)-1 &&
712 (u_longlong_t)(invalue & (u_longlong_t)0xffff) == invalue)
713 return ((uint16_t)invalue);
714
715
716 ERROR1(ep, ebuf, gettext("Unknown identity type \"%s\"\n"), type);
717
718 handle_errors(ep, NULL, B_FALSE, B_FALSE);
719 return (0);
720 }
721
722 /*
723 * Parse an address off the command line. Return length of sockaddr,
724 * and either return a hostent pointer (caller frees). The new
725 * getipnodebyname() call does the Right Thing (TM), even with
726 * raw addresses (colon-separated IPv6 or dotted decimal IPv4).
727 */
728
729 static struct {
730 struct hostent he;
731 char *addtl[2];
732 } dummy;
733 static union {
734 struct in6_addr ipv6;
735 struct in_addr ipv4;
736 uint64_t aligner;
737 } addr1;
738
739 static int
parseaddr(char * addr,struct hostent ** hpp,boolean_t v6only,char * ebuf)740 parseaddr(char *addr, struct hostent **hpp, boolean_t v6only, char *ebuf)
741 {
742 int hp_errno;
743 struct hostent *hp = NULL;
744 char *ep = NULL;
745
746 if (addr == NULL) {
747 FATAL(ep, ebuf, gettext("Unexpected end of command line, "
748 "was expecting an address.\n"));
749 }
750
751 if (!nflag) {
752 /*
753 * Try name->address first. Assume AF_INET6, and
754 * get IPv4's, plus IPv6's if and only if IPv6 is configured.
755 * This means to add IPv6 SAs, you must have IPv6
756 * up-and-running. (AI_DEFAULT works here.)
757 */
758 hp = getipnodebyname(addr, AF_INET6,
759 (v6only ? AI_ADDRCONFIG : (AI_DEFAULT | AI_ALL)),
760 &hp_errno);
761 } else {
762 /*
763 * Try a normal address conversion only. Use "dummy"
764 * to construct a fake hostent. Caller will know not
765 * to free this one.
766 */
767 if (inet_pton(AF_INET6, addr, &addr1) == 1) {
768 dummy.he.h_addr_list = dummy.addtl;
769 dummy.addtl[0] = (char *)&addr1;
770 dummy.addtl[1] = NULL;
771 hp = &dummy.he;
772 dummy.he.h_addrtype = AF_INET6;
773 dummy.he.h_length = sizeof (struct in6_addr);
774 } else if (inet_pton(AF_INET, addr, &addr1) == 1) {
775 /*
776 * Remap to AF_INET6 anyway.
777 */
778 dummy.he.h_addr_list = dummy.addtl;
779 dummy.addtl[0] = (char *)&addr1;
780 dummy.addtl[1] = NULL;
781 hp = &dummy.he;
782 dummy.he.h_addrtype = AF_INET6;
783 dummy.he.h_length = sizeof (struct in6_addr);
784 /*
785 * NOTE: If macro changes to disallow in-place
786 * conversion, rewhack this.
787 */
788 IN6_INADDR_TO_V4MAPPED(&addr1.ipv4, &addr1.ipv6);
789 } else {
790 hp = NULL;
791 }
792 }
793
794 if (hp == NULL)
795 WARN1(ep, ebuf, gettext("Unknown address %s."), addr);
796
797 *hpp = hp;
798 /* Always return sockaddr_in6 for now. */
799 handle_errors(ep, NULL, B_FALSE, B_FALSE);
800 return (sizeof (struct sockaddr_in6));
801 }
802
803 /*
804 * Parse a hex character for a key. A string will take the form:
805 * xxxxxxxxx/nn
806 * where
807 * xxxxxxxxx == a string of hex characters ([0-9][a-f][A-F])
808 * nn == an optional decimal "mask". If it is not present, it
809 * is assumed that the hex string will be rounded to the nearest
810 * byte, where odd nibbles, like 123 will become 0x0123.
811 *
812 * NOTE:Unlike the expression of IP addresses, I will not allow an
813 * excessive "mask". For example 2112/50 is very illegal.
814 * NOTE2: This key should be in canonical order. Consult your man
815 * pages per algorithm about said order.
816 */
817
818 #define hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \
819 (((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10)))
820
821 static struct sadb_key *
parsekey(char * input,char * ebuf,uint_t reserved_bits)822 parsekey(char *input, char *ebuf, uint_t reserved_bits)
823 {
824 struct sadb_key *retval;
825 uint_t i, hexlen = 0, bits, alloclen;
826 uint8_t *key;
827 char *ep = NULL;
828
829 if (input == NULL) {
830 FATAL(ep, ebuf, gettext("Unexpected end of command line, "
831 "was expecting a key.\n"));
832 }
833 /* Allow hex values prepended with 0x convention */
834 if ((strnlen(input, sizeof (hexlen)) > 2) &&
835 (strncasecmp(input, "0x", 2) == 0))
836 input += 2;
837
838 for (i = 0; input[i] != '\0' && input[i] != '/'; i++)
839 hexlen++;
840
841 if (input[i] == '\0') {
842 bits = 0;
843 } else {
844 /* Have /nn. */
845 input[i] = '\0';
846 if (sscanf((input + i + 1), "%u", &bits) != 1) {
847 FATAL1(ep, ebuf, gettext(
848 "\"%s\" is not a bit specifier.\n"),
849 (input + i + 1));
850 }
851 /* hexlen in nibbles */
852 if (((bits + 3) >> 2) > hexlen) {
853 ERROR2(ep, ebuf, gettext(
854 "bit length %d is too big for %s.\n"), bits, input);
855 }
856 /*
857 * Adjust hexlen down if user gave us too small of a bit
858 * count.
859 */
860 if ((hexlen << 2) > bits + 3) {
861 WARN2(ep, ebuf, gettext(
862 "WARNING: Lower bits will be truncated "
863 "for:\n\t%s/%d.\n"), input, bits);
864 hexlen = (bits + 3) >> 2;
865 input[hexlen] = '\0';
866 }
867 }
868
869 /*
870 * Allocate. Remember, hexlen is in nibbles.
871 */
872
873 alloclen = sizeof (*retval) + roundup((hexlen/2 + (hexlen & 0x1)), 8);
874 retval = malloc(alloclen);
875
876 if (retval == NULL)
877 Bail("malloc(parsekey)");
878 retval->sadb_key_len = SADB_8TO64(alloclen);
879
880 retval->sadb_key_reserved = reserved_bits;
881
882 if (bits == 0)
883 retval->sadb_key_bits = (hexlen + (hexlen & 0x1)) << 2;
884 else
885 retval->sadb_key_bits = bits;
886
887 /*
888 * Read in nibbles. Read in odd-numbered as shifted high.
889 * (e.g. 123 becomes 0x1230).
890 */
891
892 key = (uint8_t *)(retval + 1);
893 for (i = 0; input[i] != '\0'; i += 2) {
894 boolean_t second = (input[i + 1] != '\0');
895
896 if (!isxdigit(input[i]) ||
897 (!isxdigit(input[i + 1]) && second)) {
898 ERROR1(ep, ebuf, gettext(
899 "string '%s' not a hex value.\n"), input);
900 free(retval);
901 retval = NULL;
902 break;
903 }
904 *key = (hd2num(input[i]) << 4);
905 if (second)
906 *key |= hd2num(input[i + 1]);
907 else
908 break; /* out of for loop. */
909 key++;
910 }
911
912 /* bzero the remaining bits if we're a non-octet amount. */
913 if (bits & 0x7)
914 *((input[i] == '\0') ? key - 1 : key) &=
915 0xff << (8 - (bits & 0x7));
916
917 handle_errors(ep, NULL, B_FALSE, B_FALSE);
918 return (retval);
919 }
920
921 #include <tsol/label.h>
922
923 #define PARSELABEL_BAD_TOKEN ((struct sadb_sens *)-1)
924
925 static struct sadb_sens *
parselabel(int token,char * label)926 parselabel(int token, char *label)
927 {
928 bslabel_t *sl = NULL;
929 int err, len;
930 sadb_sens_t *sens;
931 int doi = 1; /* XXX XXX DEFAULT_DOI XXX XXX */
932
933 err = str_to_label(label, &sl, MAC_LABEL, L_DEFAULT, NULL);
934 if (err < 0)
935 return (NULL);
936
937 len = ipsec_convert_sl_to_sens(doi, sl, NULL);
938
939 sens = malloc(len);
940 if (sens == NULL) {
941 Bail("malloc parsed label");
942 /* Should exit before reaching here... */
943 return (NULL);
944 }
945
946 (void) ipsec_convert_sl_to_sens(doi, sl, sens);
947
948 switch (token) {
949 case TOK_LABEL:
950 break;
951
952 case TOK_OLABEL:
953 sens->sadb_sens_exttype = SADB_X_EXT_OUTER_SENS;
954 break;
955
956 case TOK_IMPLABEL:
957 sens->sadb_sens_exttype = SADB_X_EXT_OUTER_SENS;
958 sens->sadb_x_sens_flags = SADB_X_SENS_IMPLICIT;
959 break;
960
961 default:
962 free(sens);
963 /*
964 * Return a different return code for a bad label, but really,
965 * this would be a caller error.
966 */
967 return (PARSELABEL_BAD_TOKEN);
968 }
969
970 return (sens);
971 }
972
973 /*
974 * Write a message to the PF_KEY socket. If verbose, print the message
975 * heading into the kernel.
976 */
977 static int
key_write(int fd,void * msg,size_t len)978 key_write(int fd, void *msg, size_t len)
979 {
980 if (vflag) {
981 (void) printf(
982 gettext("VERBOSE ON: Message to kernel looks like:\n"));
983 (void) printf("==========================================\n");
984 print_samsg(stdout, msg, B_FALSE, vflag, nflag);
985 (void) printf("==========================================\n");
986 }
987
988 return (write(fd, msg, len));
989 }
990
991 /*
992 * SIGALRM handler for time_critical_enter.
993 */
994 static void
time_critical_catch(int signal)995 time_critical_catch(int signal)
996 {
997 if (signal == SIGALRM) {
998 errx(1, gettext("Reply message from PF_KEY timed out."));
999 } else {
1000 errx(1, gettext("Caught signal %d while trying to receive"
1001 "PF_KEY reply message"), signal);
1002 }
1003 /* errx() calls exit. */
1004 }
1005
1006 #define TIME_CRITICAL_TIME 10 /* In seconds */
1007
1008 /*
1009 * Enter a "time critical" section where key is waiting for a return message.
1010 */
1011 static void
time_critical_enter(void)1012 time_critical_enter(void)
1013 {
1014 (void) signal(SIGALRM, time_critical_catch);
1015 (void) alarm(TIME_CRITICAL_TIME);
1016 }
1017
1018 /*
1019 * Exit the "time critical" section after getting an appropriate return
1020 * message.
1021 */
1022 static void
time_critical_exit(void)1023 time_critical_exit(void)
1024 {
1025 (void) alarm(0);
1026 (void) signal(SIGALRM, SIG_DFL);
1027 }
1028
1029 /*
1030 * Construct a PF_KEY FLUSH message for the SA type specified.
1031 */
1032 static void
doflush(int satype)1033 doflush(int satype)
1034 {
1035 struct sadb_msg msg;
1036 int rc;
1037
1038 msg_init(&msg, SADB_FLUSH, (uint8_t)satype);
1039 rc = key_write(keysock, &msg, sizeof (msg));
1040 if (rc == -1)
1041 Bail("write() to PF_KEY socket failed (in doflush)");
1042
1043 time_critical_enter();
1044 do {
1045 rc = read(keysock, &msg, sizeof (msg));
1046 if (rc == -1)
1047 Bail("read (in doflush)");
1048 } while (msg.sadb_msg_seq != seq || msg.sadb_msg_pid != mypid);
1049 time_critical_exit();
1050
1051 /*
1052 * I should _never_ hit the following unless:
1053 *
1054 * 1. There is a kernel bug.
1055 * 2. There is another process filling in its pid with mine, and
1056 * issuing a different message that would cause a different result.
1057 */
1058 if (msg.sadb_msg_type != SADB_FLUSH ||
1059 msg.sadb_msg_satype != (uint8_t)satype) {
1060 syslog((LOG_NOTICE|LOG_AUTH),
1061 gettext("doflush: Return message not of type SADB_FLUSH!"));
1062 Bail("doflush: Return message not of type SADB_FLUSH!");
1063 }
1064
1065 if (msg.sadb_msg_errno != 0) {
1066 errno = msg.sadb_msg_errno;
1067 if (errno == EINVAL) {
1068 print_diagnostic(stderr, msg.sadb_x_msg_diagnostic);
1069 warnx(gettext("Cannot flush SA type %d."), satype);
1070 }
1071 Bail("return message (in doflush)");
1072 }
1073 }
1074
1075 /*
1076 * save_XXX functions are used when "saving" the SA tables to either a
1077 * file or standard output. They use the dump_XXX functions where needed,
1078 * but mostly they use the rparseXXX functions.
1079 */
1080
1081 /*
1082 * Because "save" and "dump" both use the SADB_DUMP message, fold both
1083 * into the same function.
1084 */
1085 static void
dodump(int satype,FILE * ofile)1086 dodump(int satype, FILE *ofile)
1087 {
1088 struct sadb_msg *msg = (struct sadb_msg *)get_buffer;
1089 int rc;
1090
1091 if (ofile != NULL) {
1092 (void) fprintf(ofile,
1093 gettext("# This key file was generated by the"));
1094 (void) fprintf(ofile,
1095 gettext(" ipseckey(1m) command's 'save' feature.\n\n"));
1096 }
1097 msg_init(msg, SADB_DUMP, (uint8_t)satype);
1098 rc = key_write(keysock, msg, sizeof (*msg));
1099 if (rc == -1)
1100 Bail("write to PF_KEY socket failed (in dodump)");
1101
1102 do {
1103 /*
1104 * For DUMP, do only the read as a time critical section.
1105 */
1106 time_critical_enter();
1107 rc = read(keysock, get_buffer, sizeof (get_buffer));
1108 time_critical_exit();
1109 if (rc == -1)
1110 Bail("read (in dodump)");
1111 if (msg->sadb_msg_pid == mypid &&
1112 msg->sadb_msg_type == SADB_DUMP &&
1113 msg->sadb_msg_seq != 0 &&
1114 msg->sadb_msg_errno == 0) {
1115 if (ofile == NULL) {
1116 print_samsg(stdout, get_buffer, B_FALSE, vflag,
1117 nflag);
1118 (void) putchar('\n');
1119 } else {
1120 save_assoc(get_buffer, ofile);
1121 }
1122 }
1123 } while (msg->sadb_msg_pid != mypid ||
1124 (msg->sadb_msg_errno == 0 && msg->sadb_msg_seq != 0));
1125
1126 if (ofile != NULL && ofile != stdout)
1127 (void) fclose(ofile);
1128
1129 if (msg->sadb_msg_errno == 0) {
1130 if (ofile == NULL)
1131 (void) printf(
1132 gettext("Dump succeeded for SA type %d.\n"),
1133 satype);
1134 } else {
1135 print_diagnostic(stderr, msg->sadb_x_msg_diagnostic);
1136 errno = msg->sadb_msg_errno;
1137 Bail("Dump failed");
1138 }
1139 }
1140
1141 #define SCOPE_UNSPEC 0
1142 #define SCOPE_LINKLOCAL 1
1143 #define SCOPE_SITELOCAL 2
1144 #define SCOPE_GLOBAL 3
1145 #define SCOPE_V4COMPAT 4
1146 #define SCOPE_LOOPBACK 5 /* Pedantic, yes, but necessary. */
1147
1148 static int
ipv6_addr_scope(struct in6_addr * addr)1149 ipv6_addr_scope(struct in6_addr *addr)
1150 {
1151 /* Don't return anything regarding multicast for now... */
1152
1153 if (IN6_IS_ADDR_UNSPECIFIED(addr))
1154 return (SCOPE_UNSPEC);
1155
1156 if (IN6_IS_ADDR_LINKLOCAL(addr))
1157 return (SCOPE_LINKLOCAL);
1158
1159 if (IN6_IS_ADDR_SITELOCAL(addr))
1160 return (SCOPE_SITELOCAL);
1161
1162 if (IN6_IS_ADDR_V4COMPAT(addr))
1163 return (SCOPE_V4COMPAT);
1164
1165 if (IN6_IS_ADDR_LOOPBACK(addr))
1166 return (SCOPE_LOOPBACK);
1167
1168 /* For now, return global by default. */
1169 return (SCOPE_GLOBAL);
1170 }
1171
1172 /*
1173 * doaddresses():
1174 *
1175 * Used by doaddup() and dodelget() to create new SA's based on the
1176 * provided source and destination addresses hostent.
1177 *
1178 * sadb_msg_type: expected PF_KEY reply message type
1179 * sadb_msg_satype: expected PF_KEY reply satype
1180 * cmd: user command
1181 * srchp: hostent for the source address(es)
1182 * dsthp: hostent for the destination address(es)
1183 * src: points to the SADB source address extension
1184 * dst: points to the SADB destination address extension
1185 * unspec_src: indicates an unspecified source address.
1186 * buffer: pointer to the SADB buffer to use with PF_KEY
1187 * buffer_size: size of buffer
1188 * spi: spi for this message (set by caller)
1189 * srcport: source port if specified
1190 * dstport: destination port if specified
1191 * proto: IP protocol number if specified
1192 * iproto: Inner (tunnel mode) IP protocol number if specified
1193 * NATT note: we are going to assume a semi-sane world where NAT
1194 * boxen don't explode to multiple addresses.
1195 */
1196 static void
doaddresses(uint8_t sadb_msg_type,uint8_t sadb_msg_satype,int cmd,struct hostent * srchp,struct hostent * dsthp,struct sadb_address * src,struct sadb_address * dst,boolean_t unspec_src,uint64_t * buffer,int buffer_size,uint32_t spi,char * ebuf)1197 doaddresses(uint8_t sadb_msg_type, uint8_t sadb_msg_satype, int cmd,
1198 struct hostent *srchp, struct hostent *dsthp,
1199 struct sadb_address *src, struct sadb_address *dst,
1200 boolean_t unspec_src, uint64_t *buffer, int buffer_size, uint32_t spi,
1201 char *ebuf)
1202 {
1203 boolean_t last_dst;
1204 struct sockaddr_in6 *sin6;
1205 struct sadb_msg *msgp;
1206 int i, rc;
1207 char **walker; /* For the SRC and PROXY walking functions. */
1208 char *first_match;
1209 uint64_t savebuf[MAX_GET_SIZE];
1210 uint16_t srcport = 0, dstport = 0;
1211 char *ep = NULL;
1212
1213 /*
1214 * Okay, now we have "src", "dst", and maybe "proxy" reassigned
1215 * to point into the buffer to be written to PF_KEY, we can do
1216 * potentially several writes based on destination address.
1217 *
1218 * First, obtain port numbers from passed-in extensions.
1219 */
1220
1221 if (src != NULL) {
1222 sin6 = (struct sockaddr_in6 *)(src + 1);
1223 srcport = ntohs(sin6->sin6_port);
1224 }
1225 if (dst != NULL) {
1226 sin6 = (struct sockaddr_in6 *)(dst + 1);
1227 dstport = ntohs(sin6->sin6_port);
1228 }
1229
1230 /*
1231 * The rules for ADD, GET, and UPDATE: (NOTE: This assumes IPsec.
1232 * If other consumers of PF_KEY happen, this will have to be
1233 * rewhacked.):
1234 *
1235 * Do a message for every possible DST address.
1236 *
1237 * If a source or proxy address explodes, keep unspecified
1238 * (and mention unspecified).
1239 *
1240 * DELETE is different, because you can leave either "src" or "dst"
1241 * blank! You need to explode if one of them is full, and not assume
1242 * that the other is set.
1243 */
1244
1245 if (dsthp == NULL) {
1246 /*
1247 * No destination address specified.
1248 * With extended diagnostics, we don't have to bail the
1249 * non-DELETE cases here. The EINVAL diagnostics will be
1250 * enough to inform the user(s) what happened.
1251 */
1252 i = 0;
1253 do {
1254 if (srchp == &dummy.he) {
1255 /* Just to be sure... */
1256 srchp->h_addr_list[1] = NULL;
1257 } else if (srchp != NULL) {
1258 /* Degenerate case, h_addr_list[0] == NULL. */
1259 if (srchp->h_addr_list[i] == NULL)
1260 Bail("Empty source address list");
1261
1262 /*
1263 * Fill in the src sockaddr.
1264 */
1265 sin6 = (struct sockaddr_in6 *)(src + 1);
1266 bzero(sin6, sizeof (*sin6));
1267 bcopy(srchp->h_addr_list[i], &sin6->sin6_addr,
1268 sizeof (struct in6_addr));
1269 sin6->sin6_family = AF_INET6;
1270 sin6->sin6_port = htons(srcport);
1271 }
1272
1273 /* Save off a copy for later writing... */
1274 msgp = (struct sadb_msg *)buffer;
1275 bcopy(buffer, savebuf, SADB_64TO8(msgp->sadb_msg_len));
1276
1277 rc = key_write(keysock, buffer,
1278 SADB_64TO8(msgp->sadb_msg_len));
1279 if (rc == -1)
1280 Bail("write() to PF_KEY socket "
1281 "(in doaddresses)");
1282 /*
1283 * Sends the message to the Solaris Cluster daemon
1284 */
1285
1286 if (in_cluster_mode) {
1287 (void) sendto(cluster_socket, buffer,
1288 SADB_64TO8(msgp->sadb_msg_len), 0,
1289 (struct sockaddr *)&cli_addr,
1290 sizeof (cli_addr));
1291 }
1292
1293 time_critical_enter();
1294 do {
1295 rc = read(keysock, buffer, buffer_size);
1296 if (rc == -1)
1297 Bail("read (in doaddresses)");
1298 } while (msgp->sadb_msg_seq != seq ||
1299 msgp->sadb_msg_pid != mypid);
1300 time_critical_exit();
1301
1302 if (msgp->sadb_msg_type != sadb_msg_type ||
1303 msgp->sadb_msg_satype != sadb_msg_satype) {
1304 syslog((LOG_NOTICE|LOG_AUTH), gettext(
1305 "doaddresses: Unexpected returned message "
1306 "(%d exp %d)\n"), msgp->sadb_msg_type,
1307 sadb_msg_type);
1308 Bail("doaddresses: Unexpected returned "
1309 "message");
1310 }
1311
1312 errno = msgp->sadb_msg_errno;
1313 if (errno != 0) {
1314 if (errno == EINVAL) {
1315 WARN(ep, ebuf, gettext(
1316 "One of the entered "
1317 "values is incorrect."));
1318 print_diagnostic(stderr,
1319 msgp->sadb_x_msg_diagnostic);
1320 } else {
1321 Bail("return message (in doaddresses)");
1322 }
1323 }
1324
1325 /* ...and then restore the saved buffer. */
1326 msgp = (struct sadb_msg *)savebuf;
1327 bcopy(savebuf, buffer, SADB_64TO8(msgp->sadb_msg_len));
1328 } while (srchp != NULL && srchp->h_addr_list[++i] != NULL);
1329 return;
1330 }
1331
1332 /*
1333 * Go through the list of all dst addresses, trying to find matching
1334 * src address for each. If the first address is == dummy.he we will go
1335 * through the loop just once. If any other hp is == dummy.he, then we
1336 * don't have to apply any silly rules.
1337 */
1338 for (i = 0; dsthp->h_addr_list[i] != NULL; i++) {
1339 if (dsthp == &dummy.he) {
1340 /* Just to be sure... */
1341 dsthp->h_addr_list[1] = NULL;
1342 } else {
1343 /*
1344 * Fill in the dst sockaddr.
1345 */
1346 sin6 = (struct sockaddr_in6 *)(dst + 1);
1347 bzero(sin6, sizeof (*sin6));
1348 bcopy(dsthp->h_addr_list[i], &sin6->sin6_addr,
1349 sizeof (struct in6_addr));
1350 sin6->sin6_family = AF_INET6;
1351 sin6->sin6_port = htons(dstport);
1352 }
1353
1354 last_dst = (dsthp->h_addr_list[i + 1] == NULL);
1355
1356 /*
1357 * Try and assign src, if there's any ambiguity.
1358 */
1359 if (!unspec_src && srchp != &dummy.he) {
1360 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1361 /*
1362 * IPv4 address. Find an IPv4 address, then
1363 * keep looking for a second one. If a second
1364 * exists, print a message, and fill in the
1365 * unspecified address.
1366 */
1367 first_match = NULL;
1368
1369 for (walker = srchp->h_addr_list;
1370 *walker != NULL; walker++) {
1371 /* LINTED E_BAD_PTR_CAST_ALIGN */
1372 if (IN6_IS_ADDR_V4MAPPED(
1373 (struct in6_addr *)*walker)) {
1374 if (first_match != NULL)
1375 break;
1376 else
1377 first_match = *walker;
1378 }
1379 }
1380 sin6 = (struct sockaddr_in6 *)(src + 1);
1381 bzero(sin6, sizeof (*sin6));
1382
1383 if (first_match == NULL) {
1384 /*
1385 * No IPv4 hits. Is this the last
1386 * destination address in the list ?
1387 */
1388 ERROR1(ep, ebuf, gettext(
1389 "No IPv4 source address "
1390 "for name %s.\n"), srchp->h_name);
1391 if (last_dst) {
1392 FATAL(ep, ebuf, gettext(
1393 "No match for destination "
1394 "IP address.\n"));
1395 } else {
1396 /* Continue, but do I print? */
1397 continue; /* for loop */
1398 }
1399
1400 /* I should never reach here. */
1401 }
1402
1403 sin6->sin6_family = AF_INET6;
1404 sin6->sin6_port = htons(srcport);
1405 if (*walker != NULL) {
1406 /*
1407 * Early loop exit. It must've been
1408 * multiple hits...
1409 *
1410 * Issue a null-source warning?
1411 */
1412 WARN1(ep, ebuf, gettext(
1413 "Multiple IPv4 source addresses "
1414 "for %s, using unspecified source "
1415 "instead."), srchp->h_name);
1416 } else {
1417 /*
1418 * If I reach here w/o hitting the
1419 * previous if statements, I have a
1420 * single source address for this
1421 * destination.
1422 */
1423 bcopy(first_match, &sin6->sin6_addr,
1424 sizeof (struct in6_addr));
1425 }
1426 } else {
1427 /*
1428 * IPv6 address. Find an IPv6 address.
1429 * Unlike IPv4 addresses, things can get a
1430 * little more sticky with scopes, etc.
1431 */
1432 int dst_scope, src_scope;
1433
1434 dst_scope = ipv6_addr_scope(&sin6->sin6_addr);
1435
1436 first_match = NULL;
1437 for (walker = srchp->h_addr_list;
1438 *walker != NULL; walker++) {
1439 /* LINTED E_BAD_PTR_CAST_ALIGN */
1440 if (!IN6_IS_ADDR_V4MAPPED(
1441 (struct in6_addr *)*walker)) {
1442 /*
1443 * Set first-match, etc.
1444 * Take into account scopes,
1445 * and other IPv6 thingies.
1446 */
1447 src_scope = ipv6_addr_scope(
1448 /* LINTED E_BAD_PTR_CAST */
1449 (struct in6_addr *)*walker);
1450 if (src_scope == SCOPE_UNSPEC ||
1451 src_scope == dst_scope) {
1452 if (first_match !=
1453 NULL)
1454 break;
1455 else
1456 first_match =
1457 *walker;
1458 }
1459 }
1460 }
1461
1462 sin6 = (struct sockaddr_in6 *)(src + 1);
1463 bzero(sin6, sizeof (*sin6));
1464 sin6->sin6_port = htons(srcport);
1465 if (first_match == NULL) {
1466 /*
1467 * No IPv6 hits. Is this the last
1468 * destination address in the list ?
1469 */
1470 ERROR1(ep, ebuf, gettext(
1471 "No IPv6 source address of "
1472 "matching scope for name %s.\n"),
1473 srchp->h_name);
1474 if (last_dst) {
1475 FATAL(ep, ebuf, gettext(
1476 "No match for IPV6 "
1477 "destination "
1478 "address.\n"));
1479 } else {
1480 /* Continue, but do I print? */
1481 continue; /* for loop */
1482 }
1483
1484 /* I should never reach here. */
1485 }
1486 sin6->sin6_family = AF_INET6;
1487 if (*walker != NULL) {
1488 /*
1489 * Early loop exit. Issue a
1490 * null-source warning?
1491 */
1492 WARN1(ep, ebuf, gettext(
1493 "Multiple IPv6 source addresses "
1494 "for %s of the same scope, using "
1495 "unspecified source instead.\n"),
1496 srchp->h_name);
1497 } else {
1498 /*
1499 * If I reach here w/o hitting the
1500 * previous if statements, I have a
1501 * single source address for this
1502 * destination.
1503 */
1504 bcopy(first_match, &sin6->sin6_addr,
1505 sizeof (struct in6_addr));
1506 }
1507 }
1508 }
1509
1510 /*
1511 * If there are errors at this point there is no
1512 * point sending anything to PF_KEY.
1513 */
1514 handle_errors(ep, ebuf, B_TRUE, B_FALSE);
1515
1516 /* Save off a copy for later writing... */
1517 msgp = (struct sadb_msg *)buffer;
1518 bcopy(buffer, savebuf, SADB_64TO8(msgp->sadb_msg_len));
1519
1520 rc = key_write(keysock, buffer, SADB_64TO8(msgp->sadb_msg_len));
1521 if (rc == -1)
1522 Bail("write() to PF_KEY socket (in doaddresses)");
1523
1524 if (in_cluster_mode) {
1525 (void) sendto(cluster_socket, buffer,
1526 SADB_64TO8(msgp->sadb_msg_len), 0,
1527 (struct sockaddr *)&cli_addr,
1528 sizeof (cli_addr));
1529 }
1530 /* Blank the key for paranoia's sake. */
1531 bzero(buffer, buffer_size);
1532 time_critical_enter();
1533 do {
1534 rc = read(keysock, buffer, buffer_size);
1535 if (rc == -1)
1536 Bail("read (in doaddresses)");
1537 } while (msgp->sadb_msg_seq != seq ||
1538 msgp->sadb_msg_pid != mypid);
1539 time_critical_exit();
1540
1541 /*
1542 * I should _never_ hit the following unless:
1543 *
1544 * 1. There is a kernel bug.
1545 * 2. Another process is mistakenly using my pid in a PF_KEY
1546 * message.
1547 */
1548 if (msgp->sadb_msg_type != sadb_msg_type ||
1549 msgp->sadb_msg_satype != sadb_msg_satype) {
1550 syslog((LOG_NOTICE|LOG_AUTH), gettext(
1551 "doaddresses: Unexpected returned message "
1552 "(%d exp %d)\n"), msgp->sadb_msg_type,
1553 sadb_msg_type);
1554 Bail("doaddresses: Unexpected returned message");
1555 }
1556
1557 if (msgp->sadb_msg_errno != 0) {
1558 char addrprint[INET6_ADDRSTRLEN];
1559 int on_errno = 0;
1560 char *on_errno_msg;
1561
1562 /*
1563 * Print different error messages depending
1564 * on the SADB message type being processed.
1565 * If we get a ESRCH error for a GET/DELETE
1566 * messages, we report that the SA does not
1567 * exist. If we get a EEXIST error for a
1568 * ADD/UPDATE message, we report that the
1569 * SA already exists.
1570 */
1571 if (sadb_msg_type == SADB_GET ||
1572 sadb_msg_type == SADB_DELETE) {
1573 on_errno = ESRCH;
1574 on_errno_msg = "does not exist";
1575 } else if (sadb_msg_type == SADB_ADD ||
1576 sadb_msg_type == SADB_UPDATE) {
1577 on_errno = EEXIST;
1578 on_errno_msg = "already exists";
1579 }
1580
1581 errno = msgp->sadb_msg_errno;
1582 if (errno == on_errno) {
1583 ERROR2(ep, ebuf, gettext(
1584 "Association (type = %s) "
1585 "with spi 0x%x and addr\n"),
1586 rparsesatype(msgp->sadb_msg_satype),
1587 ntohl(spi));
1588 ERROR2(ep, ebuf, "%s %s.\n",
1589 do_inet_ntop(dsthp->h_addr_list[i],
1590 addrprint, sizeof (addrprint)),
1591 on_errno_msg);
1592 msgp = (struct sadb_msg *)savebuf;
1593 bcopy(savebuf, buffer,
1594 SADB_64TO8(msgp->sadb_msg_len));
1595 continue;
1596 } else {
1597 if (errno == EINVAL || errno == ESRCH) {
1598 ERROR2(ep, ebuf, gettext(
1599 "PF_KEY Diagnostic code %u: %s.\n"),
1600 msgp->sadb_x_msg_diagnostic,
1601 keysock_diag(
1602 msgp->sadb_x_msg_diagnostic));
1603 } else {
1604 Bail("return message (in doaddresses)");
1605 }
1606 }
1607 }
1608
1609 if (cmd == CMD_GET) {
1610 if (msgp->sadb_msg_len > MAX_GET_SIZE) {
1611 WARN1(ep, ebuf, gettext("WARNING: "
1612 "SA information bigger than %d bytes.\n"),
1613 SADB_64TO8(MAX_GET_SIZE));
1614 }
1615 print_samsg(stdout, buffer, B_FALSE, vflag, nflag);
1616 }
1617
1618 handle_errors(ep, ebuf, B_TRUE, B_FALSE);
1619
1620 /* ...and then restore the saved buffer. */
1621 msgp = (struct sadb_msg *)savebuf;
1622 bcopy(savebuf, buffer, SADB_64TO8(msgp->sadb_msg_len));
1623 lines_added++;
1624 }
1625
1626 /* Degenerate case, h_addr_list[0] == NULL. */
1627 if (i == 0)
1628 Bail("Empty destination address list");
1629
1630 /*
1631 * free(ebuf) even if there are no errors.
1632 * handle_errors() won't return here.
1633 */
1634 handle_errors(ep, ebuf, B_TRUE, B_TRUE);
1635 }
1636
1637 /*
1638 * Perform an add or an update. ADD and UPDATE are similar in the extensions
1639 * they need.
1640 */
1641 static void
doaddup(int cmd,int satype,char * argv[],char * ebuf)1642 doaddup(int cmd, int satype, char *argv[], char *ebuf)
1643 {
1644 uint64_t *buffer, *nexthdr;
1645 struct sadb_msg msg;
1646 struct sadb_sa *assoc = NULL;
1647 struct sadb_x_pair *sadb_pair = NULL;
1648 struct sadb_address *src = NULL, *dst = NULL;
1649 struct sadb_address *isrc = NULL, *idst = NULL;
1650 struct sadb_address *natt_local = NULL, *natt_remote = NULL;
1651 struct sadb_key *encrypt = NULL, *auth = NULL;
1652 struct sadb_ident *srcid = NULL, *dstid = NULL;
1653 struct sadb_lifetime *hard = NULL, *soft = NULL; /* Current? */
1654 struct sadb_lifetime *idle = NULL;
1655 struct sadb_x_replay_ctr *replay_ctr = NULL;
1656 struct sadb_sens *label = NULL, *olabel = NULL;
1657 struct sockaddr_in6 *sin6;
1658 /* MLS TODO: Need sensitivity eventually. */
1659 int next, token, sa_len, alloclen, totallen = sizeof (msg), prefix;
1660 uint32_t spi = 0;
1661 uint_t reserved_bits = 0;
1662 uint8_t sadb_msg_type;
1663 char *thiscmd, *pstr;
1664 boolean_t readstate = B_FALSE, unspec_src = B_FALSE;
1665 boolean_t alloc_inner = B_FALSE, use_natt = B_FALSE;
1666 struct hostent *srchp = NULL, *dsthp = NULL, *isrchp = NULL,
1667 *idsthp = NULL;
1668 struct hostent *natt_lhp = NULL, *natt_rhp = NULL;
1669 uint16_t srcport = 0, dstport = 0, natt_lport = 0, natt_rport = 0,
1670 isrcport = 0, idstport = 0;
1671 uint8_t proto = 0, iproto = 0;
1672 char *ep = NULL;
1673
1674 switch (cmd) {
1675 case CMD_ADD:
1676 thiscmd = "add";
1677 sadb_msg_type = SADB_ADD;
1678 break;
1679 case CMD_UPDATE:
1680 thiscmd = "update";
1681 sadb_msg_type = SADB_UPDATE;
1682 break;
1683 case CMD_UPDATE_PAIR:
1684 thiscmd = "update-pair";
1685 sadb_msg_type = SADB_X_UPDATEPAIR;
1686 break;
1687 }
1688
1689 msg_init(&msg, sadb_msg_type, (uint8_t)satype);
1690 /* Assume last element in argv is set to NULL. */
1691 do {
1692 token = parseextval(*argv, &next);
1693 argv++;
1694 switch (token) {
1695 case TOK_EOF:
1696 /* Do nothing, I'm done. */
1697 break;
1698 case TOK_UNKNOWN:
1699 ERROR1(ep, ebuf, gettext(
1700 "Unknown extension field \"%s\" \n"), *(argv - 1));
1701 break;
1702 case TOK_SPI:
1703 case TOK_PAIR_SPI:
1704 case TOK_REPLAY:
1705 case TOK_STATE:
1706 case TOK_AUTHALG:
1707 case TOK_ENCRALG:
1708 case TOK_ENCAP:
1709 /*
1710 * May want to place this chunk of code in a function.
1711 *
1712 * This code checks for duplicate entries on a command
1713 * line.
1714 */
1715
1716 /* Allocate the SADB_EXT_SA extension. */
1717 if (assoc == NULL) {
1718 assoc = malloc(sizeof (*assoc));
1719 if (assoc == NULL)
1720 Bail("malloc(assoc)");
1721 bzero(assoc, sizeof (*assoc));
1722 assoc->sadb_sa_exttype = SADB_EXT_SA;
1723 assoc->sadb_sa_len =
1724 SADB_8TO64(sizeof (*assoc));
1725 totallen += sizeof (*assoc);
1726 }
1727 switch (token) {
1728 case TOK_SPI:
1729 /*
1730 * If some cretin types in "spi 0" then he/she
1731 * can type in another SPI.
1732 */
1733 if (assoc->sadb_sa_spi != 0) {
1734 ERROR(ep, ebuf, gettext(
1735 "Can only specify "
1736 "single SPI value.\n"));
1737 break;
1738 }
1739 /* Must convert SPI to network order! */
1740 assoc->sadb_sa_spi =
1741 htonl((uint32_t)parsenum(*argv, B_TRUE,
1742 ebuf));
1743 if (assoc->sadb_sa_spi == 0) {
1744 ERROR(ep, ebuf, gettext(
1745 "Invalid SPI value \"0\" .\n"));
1746 }
1747 break;
1748 case TOK_PAIR_SPI:
1749 if (cmd == CMD_UPDATE_PAIR) {
1750 ERROR(ep, ebuf, gettext(
1751 "pair-spi can not be used with the "
1752 "\"update-pair\" command.\n"));
1753 }
1754 if (sadb_pair == NULL) {
1755 sadb_pair = malloc(sizeof (*sadb_pair));
1756 if (assoc == NULL)
1757 Bail("malloc(assoc)");
1758 bzero(sadb_pair, sizeof (*sadb_pair));
1759 totallen += sizeof (*sadb_pair);
1760 }
1761 if (sadb_pair->sadb_x_pair_spi != 0) {
1762 ERROR(ep, ebuf, gettext(
1763 "Can only specify "
1764 "single pair SPI value.\n"));
1765 break;
1766 }
1767 /* Must convert SPI to network order! */
1768 sadb_pair->sadb_x_pair_len =
1769 SADB_8TO64(sizeof (*sadb_pair));
1770 sadb_pair->sadb_x_pair_exttype =
1771 SADB_X_EXT_PAIR;
1772 sadb_pair->sadb_x_pair_spi =
1773 htonl((uint32_t)parsenum(*argv, B_TRUE,
1774 ebuf));
1775 if (sadb_pair->sadb_x_pair_spi == 0) {
1776 ERROR(ep, ebuf, gettext(
1777 "Invalid SPI value \"0\" .\n"));
1778 }
1779 assoc->sadb_sa_flags |=
1780 SADB_X_SAFLAGS_PAIRED;
1781 break;
1782 case TOK_REPLAY:
1783 /*
1784 * That same cretin can do the same with
1785 * replay.
1786 */
1787 if (assoc->sadb_sa_replay != 0) {
1788 ERROR(ep, ebuf, gettext(
1789 "Can only specify "
1790 "single replay window size.\n"));
1791 break;
1792 }
1793 assoc->sadb_sa_replay =
1794 (uint8_t)parsenum(*argv, B_TRUE, ebuf);
1795 if (assoc->sadb_sa_replay != 0) {
1796 WARN(ep, ebuf, gettext(
1797 "WARNING: Replay with manual"
1798 " keying considered harmful.\n"));
1799 }
1800 break;
1801 case TOK_STATE:
1802 /*
1803 * 0 is an actual state value, LARVAL. This
1804 * means that one can type in the larval state
1805 * and then type in another state on the same
1806 * command line.
1807 */
1808 if (assoc->sadb_sa_state != 0) {
1809 ERROR(ep, ebuf, gettext(
1810 "Can only specify "
1811 "single SA state.\n"));
1812 break;
1813 }
1814 assoc->sadb_sa_state = parsestate(*argv,
1815 ebuf);
1816 readstate = B_TRUE;
1817 break;
1818 case TOK_AUTHALG:
1819 if (assoc->sadb_sa_auth != 0) {
1820 ERROR(ep, ebuf, gettext(
1821 "Can only specify "
1822 "single auth algorithm.\n"));
1823 break;
1824 }
1825 assoc->sadb_sa_auth = parsealg(*argv,
1826 IPSEC_PROTO_AH, ebuf);
1827 break;
1828 case TOK_ENCRALG:
1829 if (satype == SADB_SATYPE_AH) {
1830 ERROR(ep, ebuf, gettext("Cannot specify"
1831 " encryption with SA type ah.\n"));
1832 break;
1833 }
1834 if (assoc->sadb_sa_encrypt != 0) {
1835 ERROR(ep, ebuf, gettext(
1836 "Can only specify "
1837 "single encryption algorithm.\n"));
1838 break;
1839 }
1840 assoc->sadb_sa_encrypt = parsealg(*argv,
1841 IPSEC_PROTO_ESP, ebuf);
1842 break;
1843 case TOK_ENCAP:
1844 if (use_natt) {
1845 ERROR(ep, ebuf, gettext(
1846 "Can only specify single"
1847 " encapsulation.\n"));
1848 break;
1849 }
1850 if (strncmp(*argv, "udp", 3)) {
1851 ERROR(ep, ebuf, gettext(
1852 "Can only specify udp"
1853 " encapsulation.\n"));
1854 break;
1855 }
1856 use_natt = B_TRUE;
1857 /* set assoc flags later */
1858 break;
1859 }
1860 argv++;
1861 break;
1862 case TOK_SRCPORT:
1863 if (srcport != 0) {
1864 ERROR(ep, ebuf, gettext("Can only specify "
1865 "single source port.\n"));
1866 break;
1867 }
1868 srcport = parsenum(*argv, B_TRUE, ebuf);
1869 argv++;
1870 break;
1871 case TOK_DSTPORT:
1872 if (dstport != 0) {
1873 ERROR(ep, ebuf, gettext("Can only specify "
1874 "single destination port.\n"));
1875 break;
1876 }
1877 dstport = parsenum(*argv, B_TRUE, ebuf);
1878 argv++;
1879 break;
1880 case TOK_ISRCPORT:
1881 alloc_inner = B_TRUE;
1882 if (isrcport != 0) {
1883 ERROR(ep, ebuf, gettext(
1884 "Can only specify "
1885 "single inner-source port.\n"));
1886 break;
1887 }
1888 isrcport = parsenum(*argv, B_TRUE, ebuf);
1889 argv++;
1890 break;
1891 case TOK_IDSTPORT:
1892 alloc_inner = B_TRUE;
1893 if (idstport != 0) {
1894 ERROR(ep, ebuf, gettext(
1895 "Can only specify "
1896 "single inner-destination port.\n"));
1897 break;
1898 }
1899 idstport = parsenum(*argv, B_TRUE, ebuf);
1900 argv++;
1901 break;
1902 case TOK_NATLPORT:
1903 if (natt_lport != 0) {
1904 ERROR(ep, ebuf, gettext(
1905 "Can only specify "
1906 "single NAT-T local port.\n"));
1907 break;
1908 }
1909 natt_lport = parsenum(*argv, B_TRUE, ebuf);
1910 argv++;
1911 break;
1912 case TOK_NATRPORT:
1913 if (natt_rport != 0) {
1914 ERROR(ep, ebuf, gettext(
1915 "Can only specify "
1916 "single NAT-T remote port.\n"));
1917 break;
1918 }
1919 natt_rport = parsenum(*argv, B_TRUE, ebuf);
1920 argv++;
1921 break;
1922
1923 case TOK_PROTO:
1924 if (proto != 0) {
1925 ERROR(ep, ebuf, gettext(
1926 "Can only specify "
1927 "single protocol.\n"));
1928 break;
1929 }
1930 proto = parsenum(*argv, B_TRUE, ebuf);
1931 argv++;
1932 break;
1933 case TOK_IPROTO:
1934 alloc_inner = B_TRUE;
1935 if (iproto != 0) {
1936 ERROR(ep, ebuf, gettext(
1937 "Can only specify "
1938 "single inner protocol.\n"));
1939 break;
1940 }
1941 iproto = parsenum(*argv, B_TRUE, ebuf);
1942 argv++;
1943 break;
1944 case TOK_SRCADDR:
1945 case TOK_SRCADDR6:
1946 if (src != NULL) {
1947 ERROR(ep, ebuf, gettext(
1948 "Can only specify "
1949 "single source address.\n"));
1950 break;
1951 }
1952 sa_len = parseaddr(*argv, &srchp,
1953 (token == TOK_SRCADDR6), ebuf);
1954 if (srchp == NULL) {
1955 ERROR1(ep, ebuf, gettext(
1956 "Unknown src address \"%s\"\n"), *argv);
1957 break;
1958 }
1959 argv++;
1960 /*
1961 * Round of the sockaddr length to an 8 byte
1962 * boundary to make PF_KEY happy.
1963 */
1964 alloclen = sizeof (*src) + roundup(sa_len, 8);
1965 src = malloc(alloclen);
1966 if (src == NULL)
1967 Bail("malloc(src)");
1968 totallen += alloclen;
1969 src->sadb_address_len = SADB_8TO64(alloclen);
1970 src->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1971 src->sadb_address_reserved = 0;
1972 src->sadb_address_prefixlen = 0;
1973 src->sadb_address_proto = 0;
1974 if (srchp == &dummy.he) {
1975 /*
1976 * Single address with -n flag.
1977 */
1978 sin6 = (struct sockaddr_in6 *)(src + 1);
1979 bzero(sin6, sizeof (*sin6));
1980 sin6->sin6_family = AF_INET6;
1981 bcopy(srchp->h_addr_list[0], &sin6->sin6_addr,
1982 sizeof (struct in6_addr));
1983 }
1984 break;
1985 case TOK_DSTADDR:
1986 case TOK_DSTADDR6:
1987 if (dst != NULL) {
1988 ERROR(ep, ebuf, gettext(
1989 "Can only specify single "
1990 "destination address.\n"));
1991 break;
1992 }
1993 sa_len = parseaddr(*argv, &dsthp,
1994 (token == TOK_DSTADDR6), ebuf);
1995 if (dsthp == NULL) {
1996 ERROR1(ep, ebuf, gettext(
1997 "Unknown dst address \"%s\"\n"), *argv);
1998 break;
1999 }
2000 argv++;
2001 alloclen = sizeof (*dst) + roundup(sa_len, 8);
2002 dst = malloc(alloclen);
2003 if (dst == NULL)
2004 Bail("malloc(dst)");
2005 totallen += alloclen;
2006 dst->sadb_address_len = SADB_8TO64(alloclen);
2007 dst->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
2008 dst->sadb_address_reserved = 0;
2009 dst->sadb_address_prefixlen = 0;
2010 dst->sadb_address_proto = 0;
2011 if (dsthp == &dummy.he) {
2012 /*
2013 * Single address with -n flag.
2014 */
2015 sin6 = (struct sockaddr_in6 *)(dst + 1);
2016 bzero(sin6, sizeof (*sin6));
2017 sin6->sin6_family = AF_INET6;
2018 bcopy(dsthp->h_addr_list[0], &sin6->sin6_addr,
2019 sizeof (struct in6_addr));
2020 }
2021 break;
2022 case TOK_PROXYADDR:
2023 case TOK_PROXYADDR6:
2024 if (isrc != NULL) {
2025 ERROR(ep, ebuf, gettext(
2026 "Can only specify single "
2027 "proxy/inner-source address.\n"));
2028 break;
2029 }
2030 if ((pstr = strchr(*argv, '/')) != NULL) {
2031 /* Parse out the prefix. */
2032 errno = 0;
2033 prefix = strtol(pstr + 1, NULL, 10);
2034 if (errno != 0) {
2035 ERROR1(ep, ebuf, gettext(
2036 "Invalid prefix %s."), pstr);
2037 break;
2038 }
2039 /* Recycle pstr */
2040 alloclen = (int)(pstr - *argv);
2041 pstr = malloc(alloclen + 1);
2042 if (pstr == NULL) {
2043 Bail("malloc(pstr)");
2044 }
2045 (void) strlcpy(pstr, *argv, alloclen + 1);
2046 } else {
2047 pstr = *argv;
2048 /*
2049 * Assume mapping to AF_INET6, and we're a host.
2050 * XXX some miscreants may still make classful
2051 * assumptions. If this is a problem, fix it
2052 * here.
2053 */
2054 prefix = 128;
2055 }
2056 sa_len = parseaddr(pstr, &isrchp,
2057 (token == TOK_PROXYADDR6), ebuf);
2058 if (isrchp == NULL) {
2059 ERROR1(ep, ebuf, gettext(
2060 "Unknown proxy/inner-source address "
2061 "\"%s\"\n"), *argv);
2062 break;
2063 }
2064 if (pstr != *argv)
2065 free(pstr);
2066 argv++;
2067 alloclen = sizeof (*isrc) + roundup(sa_len, 8);
2068 isrc = malloc(alloclen);
2069 if (isrc == NULL)
2070 Bail("malloc(isrc)");
2071 totallen += alloclen;
2072 isrc->sadb_address_len = SADB_8TO64(alloclen);
2073 isrc->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
2074 isrc->sadb_address_reserved = 0;
2075 isrc->sadb_address_prefixlen = prefix;
2076 isrc->sadb_address_proto = 0;
2077 if (isrchp == &dummy.he ||
2078 isrchp->h_addr_list[1] == NULL) {
2079 /*
2080 * Single address with -n flag or single name.
2081 */
2082 sin6 = (struct sockaddr_in6 *)(isrc + 1);
2083 bzero(sin6, sizeof (*sin6));
2084 sin6->sin6_family = AF_INET6;
2085 bcopy(isrchp->h_addr_list[0], &sin6->sin6_addr,
2086 sizeof (struct in6_addr));
2087 /*
2088 * normalize prefixlen for IPv4-mapped
2089 * addresses.
2090 */
2091 if (prefix <= 32 &&
2092 IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
2093 isrc->sadb_address_prefixlen += 96;
2094 alloc_inner = B_TRUE;
2095 } else {
2096 /*
2097 * If the proxy/isrc address is vague, don't
2098 * bother.
2099 */
2100 totallen -= alloclen;
2101 free(isrc);
2102 isrc = NULL;
2103 WARN1(ep, ebuf, gettext(
2104 "Proxy/inner-source address %s "
2105 "is vague, not using.\n"), isrchp->h_name);
2106 freehostent(isrchp);
2107 isrchp = NULL;
2108 break;
2109 }
2110 break;
2111 case TOK_IDSTADDR:
2112 case TOK_IDSTADDR6:
2113 if (idst != NULL) {
2114 ERROR(ep, ebuf, gettext(
2115 "Can only specify single "
2116 "inner-destination address.\n"));
2117 break;
2118 }
2119 if ((pstr = strchr(*argv, '/')) != NULL) {
2120 /* Parse out the prefix. */
2121 errno = 0;
2122 prefix = strtol(pstr + 1, NULL, 10);
2123 if (errno != 0) {
2124 ERROR1(ep, ebuf, gettext(
2125 "Invalid prefix %s.\n"), pstr);
2126 break;
2127 }
2128 /* Recycle pstr */
2129 alloclen = (int)(pstr - *argv);
2130 pstr = malloc(alloclen + 1);
2131 if (pstr == NULL) {
2132 Bail("malloc(pstr)");
2133 }
2134 (void) strlcpy(pstr, *argv, alloclen + 1);
2135 } else {
2136 pstr = *argv;
2137 /*
2138 * Assume mapping to AF_INET6, and we're a host.
2139 * XXX some miscreants may still make classful
2140 * assumptions. If this is a problem, fix it
2141 * here.
2142 */
2143 prefix = 128;
2144 }
2145 sa_len = parseaddr(pstr, &idsthp,
2146 (token == TOK_IDSTADDR6), ebuf);
2147 if (idsthp == NULL) {
2148 ERROR1(ep, ebuf, gettext(
2149 "Unknown Inner Src address "
2150 " \"%s\"\n"), *argv);
2151 break;
2152 }
2153 if (pstr != *argv)
2154 free(pstr);
2155 argv++;
2156 alloclen = sizeof (*idst) + roundup(sa_len, 8);
2157 idst = malloc(alloclen);
2158 if (idst == NULL)
2159 Bail("malloc(idst)");
2160 totallen += alloclen;
2161 idst->sadb_address_len = SADB_8TO64(alloclen);
2162 idst->sadb_address_exttype =
2163 SADB_X_EXT_ADDRESS_INNER_DST;
2164 idst->sadb_address_reserved = 0;
2165 idst->sadb_address_prefixlen = prefix;
2166 idst->sadb_address_proto = 0;
2167 if (idsthp == &dummy.he ||
2168 idsthp->h_addr_list[1] == NULL) {
2169 /*
2170 * Single address with -n flag or single name.
2171 */
2172 sin6 = (struct sockaddr_in6 *)(idst + 1);
2173 bzero(sin6, sizeof (*sin6));
2174 sin6->sin6_family = AF_INET6;
2175 bcopy(idsthp->h_addr_list[0], &sin6->sin6_addr,
2176 sizeof (struct in6_addr));
2177 /*
2178 * normalize prefixlen for IPv4-mapped
2179 * addresses.
2180 */
2181 if (prefix <= 32 &&
2182 IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
2183 idst->sadb_address_prefixlen += 96;
2184 alloc_inner = B_TRUE;
2185 } else {
2186 /*
2187 * If the idst address is vague, don't bother.
2188 */
2189 totallen -= alloclen;
2190 free(idst);
2191 idst = NULL;
2192 WARN1(ep, ebuf, gettext(
2193 "Inner destination address %s "
2194 "is vague, not using.\n"), idsthp->h_name);
2195 freehostent(idsthp);
2196 idsthp = NULL;
2197 break;
2198 }
2199 break;
2200 case TOK_NATLOC:
2201 if (natt_local != NULL) {
2202 ERROR(ep, ebuf, gettext(
2203 "Can only specify "
2204 "single NAT-T local address.\n"));
2205 break;
2206 }
2207 sa_len = parseaddr(*argv, &natt_lhp, 0, ebuf);
2208 if (natt_lhp == NULL) {
2209 ERROR1(ep, ebuf, gettext(
2210 "Unknown NAT-T local address \"%s\"\n"),
2211 *argv);
2212 break;
2213 }
2214 argv++;
2215 /*
2216 * Round of the sockaddr length to an 8 byte
2217 * boundary to make PF_KEY happy.
2218 */
2219 alloclen = sizeof (*natt_local) + roundup(sa_len, 8);
2220 natt_local = malloc(alloclen);
2221 if (natt_local == NULL)
2222 Bail("malloc(natt_local)");
2223 totallen += alloclen;
2224 natt_local->sadb_address_len = SADB_8TO64(alloclen);
2225 natt_local->sadb_address_exttype =
2226 SADB_X_EXT_ADDRESS_NATT_LOC;
2227 natt_local->sadb_address_reserved = 0;
2228 natt_local->sadb_address_prefixlen = 0;
2229 natt_local->sadb_address_proto = 0;
2230 if (natt_lhp == &dummy.he ||
2231 natt_lhp->h_addr_list[1] == NULL) {
2232 /*
2233 * Single address with -n flag or single name.
2234 */
2235 sin6 = (struct sockaddr_in6 *)(natt_local + 1);
2236 bzero(sin6, sizeof (*sin6));
2237 sin6->sin6_family = AF_INET6;
2238 bcopy(natt_lhp->h_addr_list[0],
2239 &sin6->sin6_addr, sizeof (struct in6_addr));
2240 } else {
2241 /*
2242 * If the nat-local address is vague, don't
2243 * bother.
2244 */
2245 totallen -= alloclen;
2246 free(natt_local);
2247 natt_local = NULL;
2248 WARN1(ep, ebuf, gettext(
2249 "NAT-T local address %s "
2250 "is vague, not using.\n"),
2251 natt_lhp->h_name);
2252 freehostent(natt_lhp);
2253 natt_lhp = NULL;
2254 break;
2255 }
2256 break;
2257 case TOK_NATREM:
2258 if (natt_remote != NULL) {
2259 ERROR(ep, ebuf, gettext(
2260 "Can only specify "
2261 "single NAT-T remote address.\n"));
2262 break;
2263 }
2264 sa_len = parseaddr(*argv, &natt_rhp, 0, ebuf);
2265 if (natt_rhp == NULL) {
2266 ERROR1(ep, ebuf, gettext(
2267 "Unknown NAT-T remote address \"%s\"\n"),
2268 *argv);
2269 break;
2270 }
2271 argv++;
2272 /*
2273 * Round of the sockaddr length to an 8 byte
2274 * boundary to make PF_KEY happy.
2275 */
2276 alloclen = sizeof (*natt_remote) + roundup(sa_len, 8);
2277 natt_remote = malloc(alloclen);
2278 if (natt_remote == NULL)
2279 Bail("malloc(natt_remote)");
2280 totallen += alloclen;
2281 natt_remote->sadb_address_len = SADB_8TO64(alloclen);
2282 natt_remote->sadb_address_exttype =
2283 SADB_X_EXT_ADDRESS_NATT_REM;
2284 natt_remote->sadb_address_reserved = 0;
2285 natt_remote->sadb_address_prefixlen = 0;
2286 natt_remote->sadb_address_proto = 0;
2287 if (natt_rhp == &dummy.he ||
2288 natt_rhp->h_addr_list[1] == NULL) {
2289 /*
2290 * Single address with -n flag or single name.
2291 */
2292 sin6 = (struct sockaddr_in6 *)(natt_remote + 1);
2293 bzero(sin6, sizeof (*sin6));
2294 sin6->sin6_family = AF_INET6;
2295 bcopy(natt_rhp->h_addr_list[0],
2296 &sin6->sin6_addr, sizeof (struct in6_addr));
2297 } else {
2298 /*
2299 * If the nat-renote address is vague, don't
2300 * bother.
2301 */
2302 totallen -= alloclen;
2303 free(natt_remote);
2304 natt_remote = NULL;
2305 WARN1(ep, ebuf, gettext(
2306 "NAT-T remote address %s "
2307 "is vague, not using.\n"),
2308 natt_rhp->h_name);
2309 freehostent(natt_rhp);
2310 natt_rhp = NULL;
2311 break;
2312 }
2313 break;
2314 case TOK_ENCRKEY:
2315 if (encrypt != NULL) {
2316 ERROR(ep, ebuf, gettext(
2317 "Can only specify "
2318 "single encryption key.\n"));
2319 break;
2320 }
2321 if (assoc != NULL &&
2322 assoc->sadb_sa_encrypt == SADB_EALG_NULL) {
2323 FATAL(ep, ebuf, gettext(
2324 "Cannot specify a key with NULL "
2325 "encryption algorithm.\n"));
2326 break;
2327 }
2328 encrypt = parsekey(*argv, ebuf, reserved_bits);
2329 argv++;
2330 if (encrypt == NULL) {
2331 ERROR(ep, ebuf, gettext(
2332 "Invalid encryption key.\n"));
2333 break;
2334 }
2335 totallen += SADB_64TO8(encrypt->sadb_key_len);
2336 encrypt->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
2337 break;
2338 case TOK_AUTHKEY:
2339 if (auth != NULL) {
2340 ERROR(ep, ebuf, gettext(
2341 "Can only specify single"
2342 " authentication key.\n"));
2343 break;
2344 }
2345 auth = parsekey(*argv, ebuf, 0);
2346 argv++;
2347 if (auth == NULL) {
2348 ERROR(ep, ebuf, gettext(
2349 "Invalid authentication key.\n"));
2350 break;
2351 }
2352 totallen += SADB_64TO8(auth->sadb_key_len);
2353 auth->sadb_key_exttype = SADB_EXT_KEY_AUTH;
2354 break;
2355 case TOK_SRCIDTYPE:
2356 if (*argv == NULL || *(argv + 1) == NULL) {
2357 FATAL(ep, ebuf, gettext(
2358 "Unexpected end of command "
2359 "line - Expecting Src Type.\n"));
2360 /* NOTREACHED */
2361 break;
2362 }
2363 if (srcid != NULL) {
2364 ERROR(ep, ebuf, gettext(
2365 "Can only specify single"
2366 " source certificate identity.\n"));
2367 break;
2368 }
2369 alloclen = sizeof (*srcid) +
2370 roundup(strlen(*(argv + 1)) + 1, 8);
2371 srcid = malloc(alloclen);
2372 if (srcid == NULL)
2373 Bail("malloc(srcid)");
2374 totallen += alloclen;
2375 srcid->sadb_ident_type = parseidtype(*argv, ebuf);
2376 argv++;
2377 srcid->sadb_ident_len = SADB_8TO64(alloclen);
2378 srcid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
2379 srcid->sadb_ident_reserved = 0;
2380 srcid->sadb_ident_id = 0; /* Not useful here. */
2381 (void) strlcpy((char *)(srcid + 1), *argv, alloclen);
2382 argv++;
2383 break;
2384 case TOK_DSTIDTYPE:
2385 if (*argv == NULL || *(argv + 1) == NULL) {
2386 ERROR(ep, ebuf, gettext(
2387 "Unexpected end of command"
2388 " line - expecting dst type.\n"));
2389 break;
2390 }
2391 if (dstid != NULL) {
2392 ERROR(ep, ebuf, gettext(
2393 "Can only specify single destination "
2394 "certificate identity.\n"));
2395 break;
2396 }
2397 alloclen = sizeof (*dstid) +
2398 roundup(strlen(*(argv + 1)) + 1, 8);
2399 dstid = malloc(alloclen);
2400 if (dstid == NULL)
2401 Bail("malloc(dstid)");
2402 totallen += alloclen;
2403 dstid->sadb_ident_type = parseidtype(*argv, ebuf);
2404 argv++;
2405 dstid->sadb_ident_len = SADB_8TO64(alloclen);
2406 dstid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
2407 dstid->sadb_ident_reserved = 0;
2408 dstid->sadb_ident_id = 0; /* Not useful here. */
2409 (void) strlcpy((char *)(dstid + 1), *argv, alloclen);
2410 argv++;
2411 break;
2412 case TOK_HARD_ALLOC:
2413 case TOK_HARD_BYTES:
2414 case TOK_HARD_ADDTIME:
2415 case TOK_HARD_USETIME:
2416 if (hard == NULL) {
2417 hard = malloc(sizeof (*hard));
2418 if (hard == NULL)
2419 Bail("malloc(hard_lifetime)");
2420 bzero(hard, sizeof (*hard));
2421 hard->sadb_lifetime_exttype =
2422 SADB_EXT_LIFETIME_HARD;
2423 hard->sadb_lifetime_len =
2424 SADB_8TO64(sizeof (*hard));
2425 totallen += sizeof (*hard);
2426 }
2427 switch (token) {
2428 case TOK_HARD_ALLOC:
2429 if (hard->sadb_lifetime_allocations != 0) {
2430 ERROR(ep, ebuf, gettext(
2431 "Can only specify single"
2432 " hard allocation limit.\n"));
2433 break;
2434 }
2435 hard->sadb_lifetime_allocations =
2436 (uint32_t)parsenum(*argv, B_TRUE, ebuf);
2437 break;
2438 case TOK_HARD_BYTES:
2439 if (hard->sadb_lifetime_bytes != 0) {
2440 ERROR(ep, ebuf, gettext(
2441 "Can only specify "
2442 "single hard byte limit.\n"));
2443 break;
2444 }
2445 hard->sadb_lifetime_bytes = parsenum(*argv,
2446 B_TRUE, ebuf);
2447 break;
2448 case TOK_HARD_ADDTIME:
2449 if (hard->sadb_lifetime_addtime != 0) {
2450 ERROR(ep, ebuf, gettext(
2451 "Can only specify "
2452 "single past-add lifetime.\n"));
2453 break;
2454 }
2455 hard->sadb_lifetime_addtime = parsenum(*argv,
2456 B_TRUE, ebuf);
2457 break;
2458 case TOK_HARD_USETIME:
2459 if (hard->sadb_lifetime_usetime != 0) {
2460 ERROR(ep, ebuf, gettext(
2461 "Can only specify "
2462 "single past-use lifetime.\n"));
2463 break;
2464 }
2465 hard->sadb_lifetime_usetime = parsenum(*argv,
2466 B_TRUE, ebuf);
2467 break;
2468 }
2469 argv++;
2470 break;
2471 case TOK_SOFT_ALLOC:
2472 case TOK_SOFT_BYTES:
2473 case TOK_SOFT_ADDTIME:
2474 case TOK_SOFT_USETIME:
2475 if (soft == NULL) {
2476 soft = malloc(sizeof (*soft));
2477 if (soft == NULL)
2478 Bail("malloc(soft_lifetime)");
2479 bzero(soft, sizeof (*soft));
2480 soft->sadb_lifetime_exttype =
2481 SADB_EXT_LIFETIME_SOFT;
2482 soft->sadb_lifetime_len =
2483 SADB_8TO64(sizeof (*soft));
2484 totallen += sizeof (*soft);
2485 }
2486 switch (token) {
2487 case TOK_SOFT_ALLOC:
2488 if (soft->sadb_lifetime_allocations != 0) {
2489 ERROR(ep, ebuf, gettext(
2490 "Can only specify single"
2491 " soft allocation limit.\n"));
2492 break;
2493 }
2494 soft->sadb_lifetime_allocations =
2495 (uint32_t)parsenum(*argv, B_TRUE, ebuf);
2496 break;
2497 case TOK_SOFT_BYTES:
2498 if (soft->sadb_lifetime_bytes != 0) {
2499 ERROR(ep, ebuf, gettext(
2500 "Can only specify single"
2501 " soft byte limit.\n"));
2502 break;
2503 }
2504 soft->sadb_lifetime_bytes = parsenum(*argv,
2505 B_TRUE, ebuf);
2506 break;
2507 case TOK_SOFT_ADDTIME:
2508 if (soft->sadb_lifetime_addtime != 0) {
2509 ERROR(ep, ebuf, gettext(
2510 "Can only specify single"
2511 " past-add lifetime.\n"));
2512 break;
2513 }
2514 soft->sadb_lifetime_addtime = parsenum(*argv,
2515 B_TRUE, ebuf);
2516 break;
2517 case TOK_SOFT_USETIME:
2518 if (soft->sadb_lifetime_usetime != 0) {
2519 ERROR(ep, ebuf, gettext(
2520 "Can only specify single"
2521 " past-use lifetime.\n"));
2522 break;
2523 }
2524 soft->sadb_lifetime_usetime = parsenum(*argv,
2525 B_TRUE, ebuf);
2526 break;
2527 }
2528 argv++;
2529 break;
2530 case TOK_FLAG_INBOUND:
2531 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_INBOUND;
2532 break;
2533 case TOK_FLAG_OUTBOUND:
2534 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_OUTBOUND;
2535 break;
2536 case TOK_REPLAY_VALUE:
2537 if (replay_ctr != NULL) {
2538 ERROR(ep, ebuf, gettext(
2539 "Can only specify single "
2540 "replay value."));
2541 break;
2542 }
2543 replay_ctr = calloc(1, sizeof (*replay_ctr));
2544 if (replay_ctr == NULL) {
2545 Bail("malloc(replay value)");
2546 }
2547 /*
2548 * We currently do not support a 64-bit
2549 * replay value. RFC 4301 will require one,
2550 * however, and we have a field in place when
2551 * 4301 is built.
2552 */
2553 replay_ctr->sadb_x_rc_exttype = SADB_X_EXT_REPLAY_VALUE;
2554 replay_ctr->sadb_x_rc_len =
2555 SADB_8TO64(sizeof (*replay_ctr));
2556 totallen += sizeof (*replay_ctr);
2557 replay_ctr->sadb_x_rc_replay32 = (uint32_t)parsenum(
2558 *argv, B_TRUE, ebuf);
2559 argv++;
2560 break;
2561 case TOK_IDLE_ADDTIME:
2562 case TOK_IDLE_USETIME:
2563 if (idle == NULL) {
2564 idle = calloc(1, sizeof (*idle));
2565 if (idle == NULL) {
2566 Bail("malloc idle lifetime");
2567 }
2568 idle->sadb_lifetime_exttype =
2569 SADB_X_EXT_LIFETIME_IDLE;
2570 idle->sadb_lifetime_len =
2571 SADB_8TO64(sizeof (*idle));
2572 totallen += sizeof (*idle);
2573 }
2574 switch (token) {
2575 case TOK_IDLE_ADDTIME:
2576 idle->sadb_lifetime_addtime =
2577 (uint32_t)parsenum(*argv,
2578 B_TRUE, ebuf);
2579 break;
2580 case TOK_IDLE_USETIME:
2581 idle->sadb_lifetime_usetime =
2582 (uint32_t)parsenum(*argv,
2583 B_TRUE, ebuf);
2584 break;
2585 }
2586 argv++;
2587 break;
2588 case TOK_RESERVED:
2589 if (encrypt != NULL)
2590 ERROR(ep, ebuf, gettext(
2591 "Reserved bits need to be "
2592 "specified before key.\n"));
2593 reserved_bits = (uint_t)parsenum(*argv,
2594 B_TRUE, ebuf);
2595 argv++;
2596 break;
2597 case TOK_LABEL:
2598 label = parselabel(token, *argv);
2599 argv++;
2600 if (label == NULL) {
2601 ERROR(ep, ebuf,
2602 gettext("Malformed security label\n"));
2603 break;
2604 } else if (label == PARSELABEL_BAD_TOKEN) {
2605 Bail("Internal token value error");
2606 }
2607 totallen += SADB_64TO8(label->sadb_sens_len);
2608 break;
2609
2610 case TOK_OLABEL:
2611 case TOK_IMPLABEL:
2612 olabel = parselabel(token, *argv);
2613 argv++;
2614 if (label == NULL) {
2615 ERROR(ep, ebuf,
2616 gettext("Malformed security label\n"));
2617 break;
2618 } else if (label == PARSELABEL_BAD_TOKEN) {
2619 Bail("Internal token value error");
2620 }
2621 totallen += SADB_64TO8(olabel->sadb_sens_len);
2622 break;
2623 default:
2624 ERROR1(ep, ebuf, gettext(
2625 "Don't use extension %s for add/update.\n"),
2626 *(argv - 1));
2627 break;
2628 }
2629 } while (token != TOK_EOF);
2630
2631 handle_errors(ep, ebuf, B_TRUE, B_FALSE);
2632
2633 #define PORT_ONLY_ALLOCATE(af, socktype, exttype, extvar, port) { \
2634 alloclen = sizeof (sadb_address_t) + roundup(sizeof (socktype), 8); \
2635 (extvar) = calloc(1, alloclen); \
2636 if ((extvar) == NULL) { \
2637 Bail("malloc(implicit port)"); \
2638 } \
2639 totallen += alloclen; \
2640 (extvar)->sadb_address_len = SADB_8TO64(alloclen); \
2641 (extvar)->sadb_address_exttype = (exttype); \
2642 /* sin/sin6 has equivalent offsets for ports! */ \
2643 sin6 = (struct sockaddr_in6 *)((extvar) + 1); \
2644 sin6->sin6_family = (af); \
2645 sin6->sin6_port = (port); \
2646 }
2647
2648 /*
2649 * If we specify inner ports or NAT ports w/o addresses, we still need
2650 * to allocate. Also, if we have one inner address, we need the
2651 * other, even if we don't specify anything.
2652 */
2653 if (use_natt) {
2654 if (natt_lport != 0 && natt_local == NULL) {
2655 PORT_ONLY_ALLOCATE(AF_INET, struct sockaddr_in,
2656 SADB_X_EXT_ADDRESS_NATT_LOC, natt_local,
2657 natt_lport);
2658 }
2659
2660 if (natt_rport != 0 && natt_remote == NULL) {
2661 PORT_ONLY_ALLOCATE(AF_INET, struct sockaddr_in,
2662 SADB_X_EXT_ADDRESS_NATT_REM, natt_remote,
2663 natt_rport);
2664 }
2665 } else {
2666 if (natt_lport != 0 || natt_rport != 0) {
2667 ERROR(ep, ebuf, gettext("Must specify 'encap udp' "
2668 "with any NAT-T port.\n"));
2669 } else if (natt_local != NULL || natt_remote != NULL) {
2670 ERROR(ep, ebuf, gettext("Must specify 'encap udp' "
2671 "with any NAT-T address.\n"));
2672 }
2673 }
2674
2675 if (alloc_inner && idst == NULL) {
2676 PORT_ONLY_ALLOCATE(AF_INET6, struct sockaddr_in6,
2677 SADB_X_EXT_ADDRESS_INNER_DST, idst, 0);
2678 }
2679
2680 if (alloc_inner && isrc == NULL) {
2681 PORT_ONLY_ALLOCATE(AF_INET6, struct sockaddr_in6,
2682 SADB_X_EXT_ADDRESS_INNER_SRC, isrc, 0);
2683 }
2684 #undef PORT_ONLY_ALLOCATE
2685
2686 /*
2687 * Okay, so now I have all of the potential extensions!
2688 * Allocate a single contiguous buffer. Keep in mind that it'll
2689 * be enough because the key itself will be yanked.
2690 */
2691
2692 if (src == NULL && dst != NULL) {
2693 /*
2694 * Set explicit unspecified source address.
2695 */
2696 size_t lenbytes = SADB_64TO8(dst->sadb_address_len);
2697
2698 unspec_src = B_TRUE;
2699 totallen += lenbytes;
2700 src = malloc(lenbytes);
2701 if (src == NULL)
2702 Bail("malloc(implicit src)");
2703 /* Confusing, but we're copying from DST to SRC. :) */
2704 bcopy(dst, src, lenbytes);
2705 src->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
2706 sin6 = (struct sockaddr_in6 *)(src + 1);
2707 bzero(sin6, sizeof (*sin6));
2708 sin6->sin6_family = AF_INET6;
2709 }
2710
2711 msg.sadb_msg_len = SADB_8TO64(totallen);
2712
2713 buffer = malloc(totallen);
2714 nexthdr = buffer;
2715 bcopy(&msg, nexthdr, sizeof (msg));
2716 nexthdr += SADB_8TO64(sizeof (msg));
2717 if (assoc != NULL) {
2718 if (assoc->sadb_sa_spi == 0) {
2719 ERROR1(ep, ebuf, gettext(
2720 "The SPI value is missing for "
2721 "the association you wish to %s.\n"), thiscmd);
2722 }
2723 if (assoc->sadb_sa_auth == 0 && assoc->sadb_sa_encrypt == 0 &&
2724 cmd == CMD_ADD) {
2725 free(assoc);
2726 FATAL(ep, ebuf, gettext(
2727 "Select at least one algorithm "
2728 "for this add.\n"));
2729 }
2730
2731 /* Hack to let user specify NULL ESP implicitly. */
2732 if (msg.sadb_msg_satype == SADB_SATYPE_ESP &&
2733 assoc->sadb_sa_encrypt == 0)
2734 assoc->sadb_sa_encrypt = SADB_EALG_NULL;
2735
2736 /* 0 is an actual value. Print a warning if it was entered. */
2737 if (assoc->sadb_sa_state == 0) {
2738 if (readstate) {
2739 ERROR(ep, ebuf, gettext(
2740 "WARNING: Cannot set LARVAL SA state.\n"));
2741 }
2742 assoc->sadb_sa_state = SADB_SASTATE_MATURE;
2743 }
2744
2745 if (use_natt) {
2746 if (natt_remote != NULL)
2747 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_NATT_REM;
2748 if (natt_local != NULL)
2749 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_NATT_LOC;
2750 }
2751
2752 if (alloc_inner) {
2753 /*
2754 * For now, assume RFC 3884's dream of transport-mode
2755 * SAs with inner IP address selectors will not
2756 * happen.
2757 */
2758 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_TUNNEL;
2759 if (proto != 0 && proto != IPPROTO_ENCAP &&
2760 proto != IPPROTO_IPV6) {
2761 ERROR1(ep, ebuf, gettext(
2762 "WARNING: Protocol type %d not "
2763 "for use with Tunnel-Mode SA.\n"), proto);
2764 /* Continue and let PF_KEY scream... */
2765 }
2766 }
2767
2768 bcopy(assoc, nexthdr, SADB_64TO8(assoc->sadb_sa_len));
2769 nexthdr += assoc->sadb_sa_len;
2770 /* Save the SPI for the case of an error. */
2771 spi = assoc->sadb_sa_spi;
2772 free(assoc);
2773 } else {
2774 if (spi == 0)
2775 ERROR1(ep, ebuf, gettext(
2776 "Need to define SPI for %s.\n"), thiscmd);
2777 ERROR1(ep, ebuf, gettext(
2778 "Need SA parameters for %s.\n"), thiscmd);
2779 }
2780
2781 if (sadb_pair != NULL) {
2782 if (sadb_pair->sadb_x_pair_spi == 0) {
2783 ERROR1(ep, ebuf, gettext(
2784 "The SPI value is missing for the "
2785 "association you wish to %s.\n"), thiscmd);
2786 }
2787 bcopy(sadb_pair, nexthdr,
2788 SADB_64TO8(sadb_pair->sadb_x_pair_len));
2789 nexthdr += sadb_pair->sadb_x_pair_len;
2790 free(sadb_pair);
2791 }
2792
2793 if (hard != NULL) {
2794 bcopy(hard, nexthdr, SADB_64TO8(hard->sadb_lifetime_len));
2795 nexthdr += hard->sadb_lifetime_len;
2796 free(hard);
2797 }
2798
2799 if (soft != NULL) {
2800 bcopy(soft, nexthdr, SADB_64TO8(soft->sadb_lifetime_len));
2801 nexthdr += soft->sadb_lifetime_len;
2802 free(soft);
2803 }
2804
2805 if (idle != NULL) {
2806 bcopy(idle, nexthdr, SADB_64TO8(idle->sadb_lifetime_len));
2807 nexthdr += idle->sadb_lifetime_len;
2808 free(idle);
2809 }
2810
2811 if (encrypt == NULL && auth == NULL && cmd == CMD_ADD) {
2812 ERROR(ep, ebuf, gettext(
2813 "Must have at least one key for an add.\n"));
2814 }
2815
2816 if (encrypt != NULL) {
2817 bcopy(encrypt, nexthdr, SADB_64TO8(encrypt->sadb_key_len));
2818 nexthdr += encrypt->sadb_key_len;
2819 bzero(encrypt, SADB_64TO8(encrypt->sadb_key_len));
2820 free(encrypt);
2821 }
2822
2823 if (auth != NULL) {
2824 bcopy(auth, nexthdr, SADB_64TO8(auth->sadb_key_len));
2825 nexthdr += auth->sadb_key_len;
2826 bzero(auth, SADB_64TO8(auth->sadb_key_len));
2827 free(auth);
2828 }
2829
2830 if (srcid != NULL) {
2831 bcopy(srcid, nexthdr, SADB_64TO8(srcid->sadb_ident_len));
2832 nexthdr += srcid->sadb_ident_len;
2833 free(srcid);
2834 }
2835
2836 if (dstid != NULL) {
2837 bcopy(dstid, nexthdr, SADB_64TO8(dstid->sadb_ident_len));
2838 nexthdr += dstid->sadb_ident_len;
2839 free(dstid);
2840 }
2841
2842 if (dst != NULL) {
2843 bcopy(dst, nexthdr, SADB_64TO8(dst->sadb_address_len));
2844 free(dst);
2845 dst = (struct sadb_address *)nexthdr;
2846 dst->sadb_address_proto = proto;
2847 ((struct sockaddr_in6 *)(dst + 1))->sin6_port = htons(dstport);
2848 nexthdr += dst->sadb_address_len;
2849 } else {
2850 FATAL1(ep, ebuf, gettext(
2851 "Need destination address for %s.\n"), thiscmd);
2852 }
2853
2854 if (use_natt) {
2855 if (natt_remote == NULL && natt_local == NULL) {
2856 ERROR(ep, ebuf, gettext(
2857 "Must specify NAT-T remote or local address "
2858 "for UDP encapsulation.\n"));
2859 }
2860
2861 if (natt_remote != NULL) {
2862 bcopy(natt_remote, nexthdr,
2863 SADB_64TO8(natt_remote->sadb_address_len));
2864 free(natt_remote);
2865 natt_remote = (struct sadb_address *)nexthdr;
2866 nexthdr += natt_remote->sadb_address_len;
2867 ((struct sockaddr_in6 *)(natt_remote + 1))->sin6_port =
2868 htons(natt_rport);
2869 }
2870
2871 if (natt_local != NULL) {
2872 bcopy(natt_local, nexthdr,
2873 SADB_64TO8(natt_local->sadb_address_len));
2874 free(natt_local);
2875 natt_local = (struct sadb_address *)nexthdr;
2876 nexthdr += natt_local->sadb_address_len;
2877 ((struct sockaddr_in6 *)(natt_local + 1))->sin6_port =
2878 htons(natt_lport);
2879 }
2880 }
2881
2882 handle_errors(ep, ebuf, B_TRUE, B_FALSE);
2883
2884 /*
2885 * PF_KEY requires a source address extension, even if the source
2886 * address itself is unspecified. (See "Set explicit unspecified..."
2887 * code fragment above. Destination reality check was above.)
2888 */
2889 bcopy(src, nexthdr, SADB_64TO8(src->sadb_address_len));
2890 free(src);
2891 src = (struct sadb_address *)nexthdr;
2892 src->sadb_address_proto = proto;
2893 ((struct sockaddr_in6 *)(src + 1))->sin6_port = htons(srcport);
2894 nexthdr += src->sadb_address_len;
2895
2896 if (isrc != NULL) {
2897 bcopy(isrc, nexthdr, SADB_64TO8(isrc->sadb_address_len));
2898 free(isrc);
2899 isrc = (struct sadb_address *)nexthdr;
2900 isrc->sadb_address_proto = iproto;
2901 ((struct sockaddr_in6 *)(isrc + 1))->sin6_port =
2902 htons(isrcport);
2903 nexthdr += isrc->sadb_address_len;
2904 }
2905
2906 if (idst != NULL) {
2907 bcopy(idst, nexthdr, SADB_64TO8(idst->sadb_address_len));
2908 free(idst);
2909 idst = (struct sadb_address *)nexthdr;
2910 idst->sadb_address_proto = iproto;
2911 ((struct sockaddr_in6 *)(idst + 1))->sin6_port =
2912 htons(idstport);
2913 nexthdr += idst->sadb_address_len;
2914 }
2915
2916 if (replay_ctr != NULL) {
2917 bcopy(replay_ctr, nexthdr,
2918 SADB_64TO8(replay_ctr->sadb_x_rc_len));
2919 nexthdr += replay_ctr->sadb_x_rc_len;
2920 free(replay_ctr);
2921 }
2922
2923 if (label != NULL) {
2924 bcopy(label, nexthdr, SADB_64TO8(label->sadb_sens_len));
2925 nexthdr += label->sadb_sens_len;
2926 free(label);
2927 label = NULL;
2928 }
2929
2930 if (olabel != NULL) {
2931 bcopy(olabel, nexthdr, SADB_64TO8(olabel->sadb_sens_len));
2932 nexthdr += olabel->sadb_sens_len;
2933 free(olabel);
2934 olabel = NULL;
2935 }
2936
2937 if (cflag) {
2938 /*
2939 * Assume the checked cmd would have worked if it was actually
2940 * used. doaddresses() will increment lines_added if it
2941 * succeeds.
2942 */
2943 lines_added++;
2944 } else {
2945 doaddresses(sadb_msg_type, satype,
2946 cmd, srchp, dsthp, src, dst, unspec_src, buffer, totallen,
2947 spi, ebuf);
2948 }
2949
2950 if (isrchp != NULL && isrchp != &dummy.he)
2951 freehostent(isrchp);
2952 if (idsthp != NULL && idsthp != &dummy.he)
2953 freehostent(idsthp);
2954 if (srchp != NULL && srchp != &dummy.he)
2955 freehostent(srchp);
2956 if (dsthp != NULL && dsthp != &dummy.he)
2957 freehostent(dsthp);
2958 if (natt_lhp != NULL && natt_lhp != &dummy.he)
2959 freehostent(natt_lhp);
2960 if (natt_rhp != NULL && natt_rhp != &dummy.he)
2961 freehostent(natt_rhp);
2962 free(ebuf);
2963 free(buffer);
2964 }
2965
2966 /*
2967 * DELETE and GET are similar, in that they only need the extensions
2968 * required to _find_ an SA, and then either delete it or obtain its
2969 * information.
2970 */
2971 static void
dodelget(int cmd,int satype,char * argv[],char * ebuf)2972 dodelget(int cmd, int satype, char *argv[], char *ebuf)
2973 {
2974 struct sadb_msg *msg = (struct sadb_msg *)get_buffer;
2975 uint64_t *nextext;
2976 struct sadb_sa *assoc = NULL;
2977 struct sadb_address *src = NULL, *dst = NULL;
2978 int next, token, sa_len;
2979 char *thiscmd;
2980 uint32_t spi;
2981 uint8_t sadb_msg_type;
2982 struct hostent *srchp = NULL, *dsthp = NULL;
2983 struct sockaddr_in6 *sin6;
2984 boolean_t unspec_src = B_TRUE;
2985 uint16_t srcport = 0, dstport = 0;
2986 uint8_t proto = 0;
2987 char *ep = NULL;
2988 uint32_t sa_flags = 0;
2989
2990 /* Set the first extension header to right past the base message. */
2991 nextext = (uint64_t *)(msg + 1);
2992 bzero(nextext, sizeof (get_buffer) - sizeof (*msg));
2993
2994 switch (cmd) {
2995 case CMD_GET:
2996 thiscmd = "get";
2997 sadb_msg_type = SADB_GET;
2998 break;
2999 case CMD_DELETE:
3000 thiscmd = "delete";
3001 sadb_msg_type = SADB_DELETE;
3002 break;
3003 case CMD_DELETE_PAIR:
3004 thiscmd = "delete-pair";
3005 sadb_msg_type = SADB_X_DELPAIR;
3006 break;
3007 }
3008
3009 msg_init(msg, sadb_msg_type, (uint8_t)satype);
3010
3011 #define ALLOC_ADDR_EXT(ext, exttype) \
3012 (ext) = (struct sadb_address *)nextext; \
3013 nextext = (uint64_t *)((ext) + 1); \
3014 nextext += SADB_8TO64(roundup(sa_len, 8)); \
3015 (ext)->sadb_address_exttype = exttype; \
3016 (ext)->sadb_address_len = nextext - ((uint64_t *)ext);
3017
3018 /* Assume last element in argv is set to NULL. */
3019 do {
3020 token = parseextval(*argv, &next);
3021 argv++;
3022 switch (token) {
3023 case TOK_EOF:
3024 /* Do nothing, I'm done. */
3025 break;
3026 case TOK_UNKNOWN:
3027 ERROR1(ep, ebuf, gettext(
3028 "Unknown extension field \"%s\"\n"), *(argv - 1));
3029 break;
3030 case TOK_SPI:
3031 if (assoc != NULL) {
3032 ERROR(ep, ebuf, gettext(
3033 "Can only specify single SPI value.\n"));
3034 break;
3035 }
3036 assoc = (struct sadb_sa *)nextext;
3037 nextext = (uint64_t *)(assoc + 1);
3038 assoc->sadb_sa_len = SADB_8TO64(sizeof (*assoc));
3039 assoc->sadb_sa_exttype = SADB_EXT_SA;
3040 assoc->sadb_sa_spi = htonl((uint32_t)parsenum(*argv,
3041 B_TRUE, ebuf));
3042 spi = assoc->sadb_sa_spi;
3043 argv++;
3044 break;
3045 case TOK_SRCPORT:
3046 if (srcport != 0) {
3047 ERROR(ep, ebuf, gettext(
3048 "Can only specify single source port.\n"));
3049 break;
3050 }
3051 srcport = parsenum(*argv, B_TRUE, ebuf);
3052 argv++;
3053 break;
3054 case TOK_DSTPORT:
3055 if (dstport != 0) {
3056 ERROR(ep, ebuf, gettext(
3057 "Can only "
3058 "specify single destination port.\n"));
3059 break;
3060 }
3061 dstport = parsenum(*argv, B_TRUE, ebuf);
3062 argv++;
3063 break;
3064 case TOK_PROTO:
3065 if (proto != 0) {
3066 ERROR(ep, ebuf, gettext(
3067 "Can only specify single protocol.\n"));
3068 break;
3069 }
3070 proto = parsenum(*argv, B_TRUE, ebuf);
3071 argv++;
3072 break;
3073 case TOK_SRCADDR:
3074 case TOK_SRCADDR6:
3075 if (src != NULL) {
3076 ERROR(ep, ebuf, gettext(
3077 "Can only specify single source addr.\n"));
3078 break;
3079 }
3080 sa_len = parseaddr(*argv, &srchp,
3081 (token == TOK_SRCADDR6), ebuf);
3082 if (srchp == NULL) {
3083 ERROR1(ep, ebuf, gettext(
3084 "Unknown source address \"%s\"\n"), *argv);
3085 break;
3086 }
3087 argv++;
3088
3089 unspec_src = B_FALSE;
3090
3091 ALLOC_ADDR_EXT(src, SADB_EXT_ADDRESS_SRC);
3092
3093 if (srchp == &dummy.he) {
3094 /*
3095 * Single address with -n flag.
3096 */
3097 sin6 = (struct sockaddr_in6 *)(src + 1);
3098 bzero(sin6, sizeof (*sin6));
3099 sin6->sin6_family = AF_INET6;
3100 bcopy(srchp->h_addr_list[0], &sin6->sin6_addr,
3101 sizeof (struct in6_addr));
3102 }
3103 /* The rest is pre-bzeroed for us. */
3104 break;
3105 case TOK_DSTADDR:
3106 case TOK_DSTADDR6:
3107 if (dst != NULL) {
3108 ERROR(ep, ebuf, gettext(
3109 "Can only specify single destination "
3110 "address.\n"));
3111 break;
3112 }
3113 sa_len = parseaddr(*argv, &dsthp,
3114 (token == TOK_SRCADDR6), ebuf);
3115 if (dsthp == NULL) {
3116 ERROR1(ep, ebuf, gettext(
3117 "Unknown destination address \"%s\"\n"),
3118 *argv);
3119 break;
3120 }
3121 argv++;
3122
3123 ALLOC_ADDR_EXT(dst, SADB_EXT_ADDRESS_DST);
3124
3125 if (dsthp == &dummy.he) {
3126 /*
3127 * Single address with -n flag.
3128 */
3129 sin6 = (struct sockaddr_in6 *)(dst + 1);
3130 bzero(sin6, sizeof (*sin6));
3131 sin6->sin6_family = AF_INET6;
3132 bcopy(dsthp->h_addr_list[0], &sin6->sin6_addr,
3133 sizeof (struct in6_addr));
3134 }
3135 /* The rest is pre-bzeroed for us. */
3136 break;
3137 case TOK_FLAG_INBOUND:
3138 sa_flags |= SADB_X_SAFLAGS_INBOUND;
3139 break;
3140 case TOK_FLAG_OUTBOUND:
3141 sa_flags |= SADB_X_SAFLAGS_OUTBOUND;
3142 break;
3143 default:
3144 ERROR2(ep, ebuf, gettext(
3145 "Don't use extension %s for '%s' command.\n"),
3146 *(argv - 1), thiscmd);
3147 break;
3148 }
3149 } while (token != TOK_EOF);
3150
3151 handle_errors(ep, ebuf, B_TRUE, B_FALSE);
3152
3153 if (assoc == NULL) {
3154 FATAL1(ep, ebuf, gettext(
3155 "Need SA parameters for %s.\n"), thiscmd);
3156 }
3157
3158 /* We can set the flags now with valid assoc in hand. */
3159 assoc->sadb_sa_flags |= sa_flags;
3160
3161 if ((srcport != 0) && (src == NULL)) {
3162 ALLOC_ADDR_EXT(src, SADB_EXT_ADDRESS_SRC);
3163 sin6 = (struct sockaddr_in6 *)(src + 1);
3164 src->sadb_address_proto = proto;
3165 bzero(sin6, sizeof (*sin6));
3166 sin6->sin6_family = AF_INET6;
3167 sin6->sin6_port = htons(srcport);
3168 }
3169
3170 if ((dstport != 0) && (dst == NULL)) {
3171 ALLOC_ADDR_EXT(dst, SADB_EXT_ADDRESS_DST);
3172 sin6 = (struct sockaddr_in6 *)(dst + 1);
3173 src->sadb_address_proto = proto;
3174 bzero(sin6, sizeof (*sin6));
3175 sin6->sin6_family = AF_INET6;
3176 sin6->sin6_port = htons(dstport);
3177 }
3178
3179 /* So I have enough of the message to send it down! */
3180 msg->sadb_msg_len = nextext - get_buffer;
3181
3182 if (cflag) {
3183 /*
3184 * Assume the checked cmd would have worked if it was actually
3185 * used. doaddresses() will increment lines_added if it
3186 * succeeds.
3187 */
3188 lines_added++;
3189 } else {
3190 doaddresses(sadb_msg_type, satype,
3191 cmd, srchp, dsthp, src, dst, unspec_src, get_buffer,
3192 sizeof (get_buffer), spi, NULL);
3193 }
3194
3195 if (srchp != NULL && srchp != &dummy.he)
3196 freehostent(srchp);
3197 if (dsthp != NULL && dsthp != &dummy.he)
3198 freehostent(dsthp);
3199 }
3200
3201 /*
3202 * "ipseckey monitor" should exit very gracefully if ^C is tapped provided
3203 * it is not running in interactive mode.
3204 */
3205 static void
monitor_catch(int signal)3206 monitor_catch(int signal)
3207 {
3208 if (!interactive)
3209 errx(signal, gettext("Bailing on signal %d."), signal);
3210 }
3211
3212 /*
3213 * Loop forever, listening on PF_KEY messages.
3214 */
3215 static void
domonitor(boolean_t passive)3216 domonitor(boolean_t passive)
3217 {
3218 struct sadb_msg *samsg;
3219 struct sigaction newsig, oldsig;
3220 int rc;
3221
3222 /* Catch ^C. */
3223 newsig.sa_handler = monitor_catch;
3224 newsig.sa_flags = 0;
3225 (void) sigemptyset(&newsig.sa_mask);
3226 (void) sigaddset(&newsig.sa_mask, SIGINT);
3227 (void) sigaction(SIGINT, &newsig, &oldsig);
3228
3229 samsg = (struct sadb_msg *)get_buffer;
3230 if (!passive) {
3231 (void) printf(gettext("Actively"));
3232 msg_init(samsg, SADB_X_PROMISC, 1); /* Turn ON promisc. */
3233 rc = key_write(keysock, samsg, sizeof (*samsg));
3234 if (rc == -1)
3235 Bail("write (SADB_X_PROMISC)");
3236 } else {
3237 (void) printf(gettext("Passively"));
3238 }
3239 (void) printf(gettext(" monitoring the PF_KEY socket.\n"));
3240
3241 for (; ; ) {
3242 /*
3243 * I assume that read() is non-blocking, and will never
3244 * return 0.
3245 */
3246 rc = read(keysock, samsg, sizeof (get_buffer));
3247 if (rc == -1) {
3248 if (errno == EINTR && interactive)
3249 goto out;
3250 else
3251 Bail("read (in domonitor)");
3252 }
3253 (void) printf(gettext("Read %d bytes.\n"), rc);
3254 /*
3255 * Q: Should I use the same method of printing as GET does?
3256 * A: For now, yes.
3257 */
3258 print_samsg(stdout, get_buffer, B_TRUE, vflag, nflag);
3259 (void) putchar('\n');
3260 }
3261
3262 out:
3263 if (interactive)
3264 /* restore SIGINT behavior */
3265 (void) sigaction(SIGINT, &oldsig, NULL);
3266 }
3267
3268 /*
3269 * Either mask or unmask all relevant signals.
3270 */
3271 static void
mask_signals(boolean_t unmask)3272 mask_signals(boolean_t unmask)
3273 {
3274 sigset_t set;
3275 static sigset_t oset;
3276
3277 if (unmask) {
3278 (void) sigprocmask(SIG_SETMASK, &oset, NULL);
3279 } else {
3280 (void) sigfillset(&set);
3281 (void) sigprocmask(SIG_SETMASK, &set, &oset);
3282 }
3283 }
3284
3285 /*
3286 * Assorted functions to print help text.
3287 */
3288 #define puts_tr(s) (void) puts(gettext(s))
3289
3290 static void
doattrhelp()3291 doattrhelp()
3292 {
3293 int i;
3294
3295 puts_tr("\nSA attributes:");
3296
3297 for (i = 0; tokens[i].string != NULL; i++) {
3298 if (i%3 == 0)
3299 (void) printf("\n");
3300 (void) printf(" %-15.15s", tokens[i].string);
3301 }
3302 (void) printf("\n");
3303 }
3304
3305 static void
dohelpcmd(char * cmds)3306 dohelpcmd(char *cmds)
3307 {
3308 int cmd;
3309
3310 if (strcmp(cmds, "attr") == 0) {
3311 doattrhelp();
3312 return;
3313 }
3314
3315 cmd = parsecmd(cmds);
3316 switch (cmd) {
3317 case CMD_UPDATE:
3318 puts_tr("update - Update an existing SA");
3319 break;
3320 case CMD_UPDATE_PAIR:
3321 puts_tr("update-pair - Update an existing pair of SA's");
3322 break;
3323 case CMD_ADD:
3324 puts_tr("add - Add a new security association (SA)");
3325 break;
3326 case CMD_DELETE:
3327 puts_tr("delete - Delete an SA");
3328 break;
3329 case CMD_DELETE_PAIR:
3330 puts_tr("delete-pair - Delete a pair of SA's");
3331 break;
3332 case CMD_GET:
3333 puts_tr("get - Display an SA");
3334 break;
3335 case CMD_FLUSH:
3336 puts_tr("flush - Delete all SAs");
3337 puts_tr("");
3338 puts_tr("Optional arguments:");
3339 puts_tr("all delete all SAs");
3340 puts_tr("esp delete just ESP SAs");
3341 puts_tr("ah delete just AH SAs");
3342 puts_tr("<number> delete just SAs with type given by number");
3343 puts_tr("");
3344 break;
3345 case CMD_DUMP:
3346 puts_tr("dump - Display all SAs");
3347 puts_tr("");
3348 puts_tr("Optional arguments:");
3349 puts_tr("all display all SAs");
3350 puts_tr("esp display just ESP SAs");
3351 puts_tr("ah display just AH SAs");
3352 puts_tr("<number> display just SAs with type "
3353 "given by number");
3354 puts_tr("");
3355 break;
3356 case CMD_MONITOR:
3357 puts_tr("monitor - Monitor all PF_KEY reply messages.");
3358 break;
3359 case CMD_PMONITOR:
3360 puts_tr(
3361 "pmonitor, passive_monitor - Monitor PF_KEY messages that");
3362 puts_tr(
3363 " reply to all PF_KEY sockets.");
3364 break;
3365
3366 case CMD_QUIT:
3367 puts_tr("quit, exit - Exit the program");
3368 break;
3369 case CMD_SAVE:
3370 puts_tr("save - Saves all SAs to a file");
3371 break;
3372 case CMD_HELP:
3373 puts_tr("help - Display list of commands");
3374 puts_tr("help <cmd> - Display help for command");
3375 puts_tr("help attr - Display possible SA attributes");
3376 break;
3377 default:
3378 (void) printf(gettext("%s: Unknown command\n"), cmds);
3379 break;
3380 }
3381 }
3382
3383
3384 static void
dohelp(char * cmds)3385 dohelp(char *cmds)
3386 {
3387 if (cmds != NULL) {
3388 dohelpcmd(cmds);
3389 return;
3390 }
3391 puts_tr("Commands");
3392 puts_tr("--------");
3393 puts_tr("?, help - Display this list");
3394 puts_tr("help <cmd> - Display help for command");
3395 puts_tr("help attr - Display possible SA attributes");
3396 puts_tr("quit, exit - Exit the program");
3397 puts_tr("monitor - Monitor all PF_KEY reply messages.");
3398 puts_tr("pmonitor, passive_monitor - Monitor PF_KEY messages that");
3399 puts_tr(" reply to all PF_KEY sockets.");
3400 puts_tr("");
3401 puts_tr("The following commands are of the form:");
3402 puts_tr(" <command> {SA type} {attribute value}*");
3403 puts_tr("");
3404 puts_tr("add (interactive only) - Add a new security association (SA)");
3405 puts_tr("update (interactive only) - Update an existing SA");
3406 puts_tr("update-pair (interactive only) - Update an existing SA pair");
3407 puts_tr("delete - Delete an SA");
3408 puts_tr("delete-pair - Delete an SA pair");
3409 puts_tr("get - Display an SA");
3410 puts_tr("flush - Delete all SAs");
3411 puts_tr("dump - Display all SAs");
3412 puts_tr("save - Saves all SAs to a file");
3413 }
3414
3415 /*
3416 * "Parse" a command line from argv.
3417 */
3418 static void
parseit(int argc,char * argv[],char * ebuf,boolean_t read_cmdfile)3419 parseit(int argc, char *argv[], char *ebuf, boolean_t read_cmdfile)
3420 {
3421 int cmd, satype;
3422 char *ep = NULL;
3423
3424 if (argc == 0)
3425 return;
3426 cmd = parsecmd(*argv++);
3427
3428 /*
3429 * Some commands loop forever and should only be run from the command
3430 * line, they should never be run from a command file as this may
3431 * be used at boot time.
3432 */
3433 switch (cmd) {
3434 case CMD_HELP:
3435 if (read_cmdfile)
3436 ERROR(ep, ebuf, gettext("Help not appropriate in "
3437 "config file."));
3438 else
3439 dohelp(*argv);
3440 return;
3441 case CMD_MONITOR:
3442 if (read_cmdfile)
3443 ERROR(ep, ebuf, gettext("Monitor not appropriate in "
3444 "config file."));
3445 else {
3446 domonitor(B_FALSE);
3447 /*
3448 * Return from the function in interactive mode to
3449 * avoid error message in the next switch statement.
3450 * Also print newline to prevent prompt clobbering.
3451 * The same is done for CMD_PMONITOR.
3452 */
3453 if (interactive) {
3454 (void) printf("\n");
3455 return;
3456 }
3457 }
3458 break;
3459 case CMD_PMONITOR:
3460 if (read_cmdfile)
3461 ERROR(ep, ebuf, gettext("Monitor not appropriate in "
3462 "config file."));
3463 else {
3464 domonitor(B_TRUE);
3465 if (interactive) {
3466 (void) printf("\n");
3467 return;
3468 }
3469 }
3470 break;
3471 case CMD_QUIT:
3472 EXIT_OK(NULL);
3473 }
3474
3475 handle_errors(ep, ebuf, B_FALSE, B_FALSE);
3476
3477 satype = parsesatype(*argv, ebuf);
3478
3479 if (satype != SADB_SATYPE_UNSPEC) {
3480 argv++;
3481 } else {
3482 /*
3483 * You must specify either "all" or a specific SA type
3484 * for the "save" command.
3485 */
3486 if (cmd == CMD_SAVE)
3487 if (*argv == NULL) {
3488 FATAL(ep, ebuf, gettext(
3489 "Must specify a specific "
3490 "SA type for save.\n"));
3491 } else {
3492 argv++;
3493 }
3494 }
3495
3496 switch (cmd) {
3497 case CMD_FLUSH:
3498 if (argc > 2) {
3499 ERROR(ep, ebuf, gettext("Too many arguments for "
3500 "flush command"));
3501 handle_errors(ep, ebuf,
3502 interactive ? B_TRUE : B_FALSE, B_FALSE);
3503 }
3504 if (!cflag)
3505 doflush(satype);
3506 /*
3507 * If this was called because of an entry in a cmd file
3508 * then this action needs to be counted to prevent
3509 * do_interactive() treating this as an error.
3510 */
3511 lines_added++;
3512 break;
3513 case CMD_ADD:
3514 case CMD_UPDATE:
3515 case CMD_UPDATE_PAIR:
3516 /*
3517 * NOTE: Shouldn't allow ADDs or UPDATEs with keying material
3518 * from the command line.
3519 */
3520 if (!interactive) {
3521 errx(1, gettext(
3522 "can't do ADD or UPDATE from the command line.\n"));
3523 }
3524 if (satype == SADB_SATYPE_UNSPEC) {
3525 FATAL(ep, ebuf, gettext(
3526 "Must specify a specific SA type."));
3527 /* NOTREACHED */
3528 }
3529 /* Parse for extensions, including keying material. */
3530 doaddup(cmd, satype, argv, ebuf);
3531 break;
3532 case CMD_DELETE:
3533 case CMD_DELETE_PAIR:
3534 case CMD_GET:
3535 if (satype == SADB_SATYPE_UNSPEC) {
3536 FATAL(ep, ebuf, gettext(
3537 "Must specify a single SA type."));
3538 /* NOTREACHED */
3539 }
3540 /* Parse for bare minimum to locate an SA. */
3541 dodelget(cmd, satype, argv, ebuf);
3542 break;
3543 case CMD_DUMP:
3544 if (read_cmdfile)
3545 ERROR(ep, ebuf, gettext("Dump not appropriate in "
3546 "config file."));
3547 else {
3548 if (argc > 2) {
3549 ERROR(ep, ebuf, gettext("Too many arguments "
3550 "for dump command"));
3551 handle_errors(ep, ebuf,
3552 interactive ? B_TRUE : B_FALSE, B_FALSE);
3553 }
3554 dodump(satype, NULL);
3555 }
3556 break;
3557 case CMD_SAVE:
3558 if (read_cmdfile) {
3559 ERROR(ep, ebuf, gettext("Save not appropriate in "
3560 "config file."));
3561 } else {
3562 mask_signals(B_FALSE); /* Mask signals */
3563 dodump(satype, opensavefile(argv[0]));
3564 mask_signals(B_TRUE); /* Unmask signals */
3565 }
3566 break;
3567 default:
3568 warnx(gettext("Unknown command (%s).\n"),
3569 *(argv - ((satype == SADB_SATYPE_UNSPEC) ? 1 : 2)));
3570 usage();
3571 }
3572 handle_errors(ep, ebuf, B_FALSE, B_FALSE);
3573 }
3574
3575 int
main(int argc,char * argv[])3576 main(int argc, char *argv[])
3577 {
3578 int ch;
3579 FILE *infile = stdin, *savefile;
3580 boolean_t dosave = B_FALSE, readfile = B_FALSE;
3581 char *configfile = NULL;
3582 struct stat sbuf;
3583 int bootflags;
3584
3585 (void) setlocale(LC_ALL, "");
3586 #if !defined(TEXT_DOMAIN)
3587 #define TEXT_DOMAIN "SYS_TEST"
3588 #endif
3589 (void) textdomain(TEXT_DOMAIN);
3590
3591 /*
3592 * Check to see if the command is being run from smf(5).
3593 */
3594 my_fmri = getenv("SMF_FMRI");
3595
3596 openlog("ipseckey", LOG_CONS, LOG_AUTH);
3597 if (getuid() != 0) {
3598 errx(1, "Insufficient privileges to run ipseckey.");
3599 }
3600
3601 /* umask me to paranoid, I only want to create files read-only */
3602 (void) umask((mode_t)00377);
3603
3604 while ((ch = getopt(argc, argv, "pnvf:s:c:")) != EOF)
3605 switch (ch) {
3606 case 'p':
3607 pflag = B_TRUE;
3608 break;
3609 case 'n':
3610 nflag = B_TRUE;
3611 break;
3612 case 'v':
3613 vflag = B_TRUE;
3614 break;
3615 case 'c':
3616 cflag = B_TRUE;
3617 /* FALLTHRU */
3618 case 'f':
3619 if (dosave)
3620 usage();
3621
3622 /*
3623 * Use stat() to check and see if the user inadvertently
3624 * passed in a bad pathname, or the name of a directory.
3625 * We should also check to see if the filename is a
3626 * pipe. We use stat() here because fopen() will block
3627 * unless the other end of the pipe is open. This would
3628 * be undesirable, especially if this is called at boot
3629 * time. If we ever need to support reading from a pipe
3630 * or special file, this should be revisited.
3631 */
3632 if (stat(optarg, &sbuf) == -1) {
3633 EXIT_BADCONFIG2("Invalid pathname: %s\n",
3634 optarg);
3635 }
3636 if (!(sbuf.st_mode & S_IFREG)) {
3637 EXIT_BADCONFIG2("%s - Not a regular file\n",
3638 optarg);
3639 }
3640 infile = fopen(optarg, "r");
3641 if (infile == NULL) {
3642 EXIT_BADCONFIG2("Unable to open configuration "
3643 "file: %s\n", optarg);
3644 }
3645 /*
3646 * The input file contains keying information, because
3647 * this is sensative, we should only accept data from
3648 * this file if the file is root owned and only readable
3649 * by privileged users. If the command is being run by
3650 * the administrator, issue a warning, if this is run by
3651 * smf(5) (IE: boot time) and the permissions are too
3652 * open, we will fail, the SMF service will end up in
3653 * maintenace mode. The check is made with fstat() to
3654 * eliminate any possible TOT to TOU window.
3655 */
3656 if (fstat(fileno(infile), &sbuf) == -1) {
3657 (void) fclose(infile);
3658 EXIT_BADCONFIG2("Unable to stat configuration "
3659 "file: %s\n", optarg);
3660 }
3661 if (INSECURE_PERMS(sbuf)) {
3662 if (my_fmri != NULL) {
3663 (void) fclose(infile);
3664 EXIT_BADCONFIG2("Config file "
3665 "%s has insecure permissions.",
3666 optarg);
3667 } else {
3668 (void) fprintf(stderr, gettext(
3669 "Config file %s has insecure "
3670 "permissions, will be rejected in "
3671 "permanent config.\n"), optarg);
3672 }
3673 }
3674 configfile = strdup(optarg);
3675 readfile = B_TRUE;
3676 break;
3677 case 's':
3678 if (readfile)
3679 usage();
3680 dosave = B_TRUE;
3681 savefile = opensavefile(optarg);
3682 break;
3683 default:
3684 usage();
3685 }
3686
3687 argc -= optind;
3688 argv += optind;
3689
3690 mypid = getpid();
3691
3692 keysock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
3693
3694 if (keysock == -1) {
3695 if (errno == EPERM) {
3696 EXIT_BADPERM("Insufficient privileges to open "
3697 "PF_KEY socket.\n");
3698 } else {
3699 /* some other reason */
3700 EXIT_FATAL("Opening PF_KEY socket");
3701 }
3702 }
3703
3704 if ((_cladm(CL_INITIALIZE, CL_GET_BOOTFLAG, &bootflags) != 0) ||
3705 (bootflags & CLUSTER_BOOTED)) {
3706 in_cluster_mode = B_TRUE;
3707 cluster_socket = socket(AF_INET, SOCK_DGRAM, 0);
3708 cli_addr.sin_family = AF_INET;
3709 cli_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
3710 cli_addr.sin_port = htons(CLUSTER_UDP_PORT);
3711 }
3712
3713 if (dosave) {
3714 mask_signals(B_FALSE); /* Mask signals */
3715 dodump(SADB_SATYPE_UNSPEC, savefile);
3716 mask_signals(B_TRUE); /* Unmask signals */
3717 EXIT_OK(NULL);
3718 }
3719
3720 /*
3721 * When run from smf(5) flush any existing SA's first
3722 * otherwise you will end up in maintenance mode.
3723 */
3724 if ((my_fmri != NULL) && readfile) {
3725 (void) fprintf(stdout, gettext(
3726 "Flushing existing SA's before adding new SA's\n"));
3727 (void) fflush(stdout);
3728 doflush(SADB_SATYPE_UNSPEC);
3729 }
3730 if (infile != stdin || argc == 0) {
3731 /* Go into interactive mode here. */
3732 do_interactive(infile, configfile, "ipseckey> ", my_fmri,
3733 parseit, no_match);
3734 }
3735 parseit(argc, argv, NULL, B_FALSE);
3736
3737 return (0);
3738 }
3739