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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
23 */
24
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <sys/sysconf.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <libintl.h>
33 #include <locale.h>
34 #include <ctype.h>
35 #include <time.h>
36 #include <sys/sysmacros.h>
37 #include <sys/stat.h>
38 #include <sys/mman.h>
39 #include <fcntl.h>
40 #include <sys/socket.h>
41 #include <netdb.h>
42 #include <errno.h>
43 #include <assert.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 #include <door.h>
47 #include <setjmp.h>
48
49 #include <ipsec_util.h>
50 #include <ikedoor.h>
51
52 static int doorfd = -1;
53
54 /*
55 * These are additional return values for the command line parsing
56 * function (parsecmd()). They are specific to this utility, but
57 * need to share the same space as the IKE_SVC_* defs, without conflicts.
58 * So they're defined relative to the end of that range.
59 */
60 #define IKEADM_HELP_GENERAL IKE_SVC_MAX + 1
61 #define IKEADM_HELP_GET IKE_SVC_MAX + 2
62 #define IKEADM_HELP_SET IKE_SVC_MAX + 3
63 #define IKEADM_HELP_ADD IKE_SVC_MAX + 4
64 #define IKEADM_HELP_DEL IKE_SVC_MAX + 5
65 #define IKEADM_HELP_DUMP IKE_SVC_MAX + 6
66 #define IKEADM_HELP_FLUSH IKE_SVC_MAX + 7
67 #define IKEADM_HELP_READ IKE_SVC_MAX + 8
68 #define IKEADM_HELP_WRITE IKE_SVC_MAX + 9
69 #define IKEADM_HELP_HELP IKE_SVC_MAX + 10
70 #define IKEADM_EXIT IKE_SVC_MAX + 11
71
72 static void
73 command_complete(int s)
74 {
75 if (interactive) {
76 longjmp(env, 1);
77 } else {
78 exit(s);
79 }
80 }
81
82 static void
83 usage()
84 {
85 if (!interactive) {
86 (void) fprintf(stderr, gettext("Usage:\t"
87 "ikeadm [ -hnp ] cmd obj [cmd-specific options]\n"));
88 (void) fprintf(stderr, gettext(" \tikeadm help\n"));
89 }
90
91 command_complete(1);
92 }
93
94 static void
95 print_help()
96 {
97 (void) printf(gettext("Valid commands and objects:\n"));
98 (void) printf(
99 "\tget debug|priv|stats|p1|rule|preshared|defaults [%s]\n",
100 gettext("identifier"));
101 (void) printf("\tset priv %s\n", gettext("level"));
102 (void) printf("\tset debug %s [%s]\n",
103 gettext("level"), gettext("filename"));
104 (void) printf("\tadd rule|preshared {%s}|%s\n",
105 gettext("definition"), gettext("filename"));
106 (void) printf("\tdel p1|rule|preshared %s\n", gettext("identifier"));
107 (void) printf("\tdump p1|rule|preshared\n");
108 (void) printf("\tflush p1\n");
109 (void) printf("\tread rule|preshared [%s]\n", gettext("filename"));
110 (void) printf("\twrite rule|preshared %s\n", gettext("filename"));
111 (void) printf(
112 "\thelp [get|set|add|del|dump|flush|read|write|help]\n");
113 (void) printf("\texit %s\n", gettext("exit the program"));
114 (void) printf("\tquit %s\n", gettext("exit the program"));
115 (void) printf("\n");
116
117 command_complete(0);
118 }
119
120 static void
121 print_get_help()
122 {
123 (void) printf(
124 gettext("This command gets information from in.iked.\n\n"));
125 (void) printf(gettext("Objects that may be retrieved include:\n"));
126 (void) printf("\tdebug\t\t");
127 (void) printf(gettext("the current debug level\n"));
128 (void) printf("\tpriv\t\t");
129 (void) printf(gettext("the current privilege level\n"));
130 (void) printf("\tstats\t\t");
131 (void) printf(gettext("current usage statistics\n"));
132 (void) printf("\tp1\t\t");
133 (void) printf(gettext("a phase 1 SA, identified by\n"));
134 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n"));
135 (void) printf(gettext("\t\t\t init_cookie resp_cookie\n"));
136 (void) printf("\trule\t\t");
137 (void) printf(gettext("a phase 1 rule, identified by its label\n"));
138 (void) printf("\tpreshared\t");
139 (void) printf(gettext("a preshared key, identified by\n"));
140 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n"));
141 (void) printf(gettext("\t\t\t local_id remote_id\n"));
142 (void) printf("\n");
143
144 command_complete(0);
145 }
146
147 static void
148 print_set_help()
149 {
150 (void) printf(gettext("This command sets values in in.iked.\n\n"));
151 (void) printf(gettext("Objects that may be set include:\n"));
152 (void) printf("\tdebug\t\t");
153 (void) printf(gettext("change the debug level\n"));
154 (void) printf("\tpriv\t\t");
155 (void) printf(
156 gettext("change the privilege level (may only be lowered)\n"));
157 (void) printf("\n");
158
159 command_complete(0);
160 }
161
162 static void
163 print_add_help()
164 {
165 (void) printf(
166 gettext("This command adds items to in.iked's tables.\n\n"));
167 (void) printf(gettext("Objects that may be set include:\n"));
168 (void) printf("\trule\t\t");
169 (void) printf(gettext("a phase 1 policy rule\n"));
170 (void) printf("\tpreshared\t");
171 (void) printf(gettext("a preshared key\n"));
172 (void) printf(
173 gettext("\nObjects may be entered on the command-line, as a\n"));
174 (void) printf(
175 gettext("series of keywords and tokens contained in curly\n"));
176 (void) printf(
177 gettext("braces ('{', '}'); or the name of a file containing\n"));
178 (void) printf(gettext("the object definition may be provided.\n\n"));
179 (void) printf(
180 gettext("For security purposes, preshared keys may only be\n"));
181 (void) printf(
182 gettext("entered on the command-line if ikeadm is running in\n"));
183 (void) printf(gettext("interactive mode.\n"));
184 (void) printf("\n");
185
186 command_complete(0);
187 }
188
189 static void
190 print_del_help()
191 {
192 (void) printf(
193 gettext("This command deletes an item from in.iked's tables.\n\n"));
194 (void) printf(gettext("Objects that may be deleted include:\n"));
195 (void) printf("\tp1\t\t");
196 (void) printf(gettext("a phase 1 SA, identified by\n"));
197 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n"));
198 (void) printf(gettext("\t\t\t init_cookie resp_cookie\n"));
199 (void) printf("\trule\t\t");
200 (void) printf(gettext("a phase 1 rule, identified by its label\n"));
201 (void) printf("\tpreshared\t");
202 (void) printf(gettext("a preshared key, identified by\n"));
203 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n"));
204 (void) printf(gettext("\t\t\t local_id remote_id\n"));
205 (void) printf("\n");
206
207 command_complete(0);
208 }
209
210 static void
211 print_dump_help()
212 {
213 (void) printf(
214 gettext("This command dumps one of in.iked's tables.\n\n"));
215 (void) printf(gettext("Tables that may be dumped include:\n"));
216 (void) printf("\tp1\t\t");
217 (void) printf(gettext("all phase 1 SAs\n"));
218 (void) printf("\trule\t\t");
219 (void) printf(gettext("all phase 1 rules\n"));
220 (void) printf("\tpreshared\t");
221 (void) printf(gettext("all preshared keys\n"));
222 (void) printf("\n");
223
224 command_complete(0);
225 }
226
227 static void
228 print_flush_help()
229 {
230 (void) printf(
231 gettext("This command clears one of in.iked's tables.\n\n"));
232 (void) printf(gettext("Tables that may be flushed include:\n"));
233 (void) printf("\tp1\t\t");
234 (void) printf(gettext("all phase 1 SAs\n"));
235 (void) printf("\n");
236
237 command_complete(0);
238 }
239
240 static void
241 print_read_help()
242 {
243 (void) printf(
244 gettext("This command reads a new configuration file into\n"));
245 (void) printf(
246 gettext("in.iked, discarding the old configuration info.\n\n"));
247 (void) printf(gettext("Sets of data that may be read include:\n"));
248 (void) printf("\trule\t\t");
249 (void) printf(gettext("all phase 1 rules\n"));
250 (void) printf("\tpreshared\t");
251 (void) printf(gettext("all preshared keys\n\n"));
252 (void) printf(
253 gettext("A filename may be provided to specify a source file\n"));
254 (void) printf(gettext("other than the default.\n"));
255 (void) printf("\n");
256
257 command_complete(0);
258 }
259
260 static void
261 print_write_help()
262 {
263 (void) printf(
264 gettext("This command writes in.iked's current configuration\n"));
265 (void) printf(gettext("out to a config file.\n\n"));
266 (void) printf(gettext("Sets of data that may be written include:\n"));
267 (void) printf("\trule\t\t");
268 (void) printf(gettext("all phase 1 rules\n"));
269 (void) printf("\tpreshared\t");
270 (void) printf(gettext("all preshared keys\n\n"));
271 (void) printf(
272 gettext("A filename must be provided to specify the file to\n"));
273 (void) printf(gettext("which the information should be written.\n"));
274 (void) printf("\n");
275
276 command_complete(0);
277 }
278
279 static void
280 print_help_help()
281 {
282 (void) printf(
283 gettext("This command provides information about commands.\n\n"));
284 (void) printf(
285 gettext("The 'help' command alone provides a list of valid\n"));
286 (void) printf(
287 gettext("commands, along with the valid objects for each.\n"));
288 (void) printf(
289 gettext("'help' followed by a valid command name provides\n"));
290 (void) printf(gettext("further information about that command.\n"));
291 (void) printf("\n");
292
293 command_complete(0);
294 }
295
296 /*PRINTFLIKE1*/
297 static void
298 message(char *fmt, ...)
299 {
300 va_list ap;
301 char msgbuf[BUFSIZ];
302
303 va_start(ap, fmt);
304 (void) vsnprintf(msgbuf, BUFSIZ, fmt, ap);
305 (void) fprintf(stderr, gettext("ikeadm: %s\n"), msgbuf);
306 va_end(ap);
307 }
308
309 static int
310 open_door(void)
311 {
312 if (doorfd >= 0)
313 (void) close(doorfd);
314 doorfd = open(DOORNM, O_RDWR);
315 return (doorfd);
316 }
317
318 static ike_service_t *
319 ikedoor_call(char *reqp, int size, door_desc_t *descp, int ndesc)
320 {
321 door_arg_t arg;
322 int retries = 0;
323
324 arg.data_ptr = reqp;
325 arg.data_size = size;
326 arg.desc_ptr = descp;
327 arg.desc_num = ndesc;
328 arg.rbuf = (char *)NULL;
329 arg.rsize = 0;
330
331 retry:
332 if (door_call(doorfd, &arg) < 0) {
333 if ((errno == EBADF) && ((++retries < 2) &&
334 (open_door() >= 0)))
335 goto retry;
336 (void) fprintf(stderr,
337 gettext("Unable to communicate with in.iked\n"));
338 Bail("door_call failed");
339 }
340
341 if ((ndesc > 0) && (descp->d_attributes & DOOR_RELEASE) &&
342 ((errno == EBADF) || (errno == EFAULT))) {
343 /* callers assume passed fds will be closed no matter what */
344 (void) close(descp->d_data.d_desc.d_descriptor);
345 }
346
347 /* LINTED E_BAD_PTR_CAST_ALIGN */
348 return ((ike_service_t *)arg.rbuf);
349 }
350
351 /*
352 * Parsing functions
353 */
354
355 /* stolen from ipseckey.c, with a second tier added */
356 static int
357 parsecmd(char *cmdstr, char *objstr)
358 {
359 #define MAXOBJS 10
360 struct objtbl {
361 char *obj;
362 int token;
363 };
364 static struct cmdtbl {
365 char *cmd;
366 int null_obj_token;
367 struct objtbl objt[MAXOBJS];
368 } table[] = {
369 {"get", IKE_SVC_ERROR, {
370 {"debug", IKE_SVC_GET_DBG},
371 {"priv", IKE_SVC_GET_PRIV},
372 {"stats", IKE_SVC_GET_STATS},
373 {"p1", IKE_SVC_GET_P1},
374 {"rule", IKE_SVC_GET_RULE},
375 {"preshared", IKE_SVC_GET_PS},
376 {"defaults", IKE_SVC_GET_DEFS},
377 {NULL, IKE_SVC_ERROR}
378 }
379 },
380 {"set", IKE_SVC_ERROR, {
381 {"debug", IKE_SVC_SET_DBG},
382 {"priv", IKE_SVC_SET_PRIV},
383 {NULL, IKE_SVC_ERROR}
384 }
385 },
386 {"add", IKE_SVC_ERROR, {
387 {"rule", IKE_SVC_NEW_RULE},
388 {"preshared", IKE_SVC_NEW_PS},
389 {NULL, IKE_SVC_ERROR}
390 }
391 },
392 {"del", IKE_SVC_ERROR, {
393 {"p1", IKE_SVC_DEL_P1},
394 {"rule", IKE_SVC_DEL_RULE},
395 {"preshared", IKE_SVC_DEL_PS},
396 {NULL, IKE_SVC_ERROR}
397 }
398 },
399 {"dump", IKE_SVC_ERROR, {
400 {"p1", IKE_SVC_DUMP_P1S},
401 {"rule", IKE_SVC_DUMP_RULES},
402 {"preshared", IKE_SVC_DUMP_PS},
403 {NULL, IKE_SVC_ERROR}
404 }
405 },
406 {"flush", IKE_SVC_ERROR, {
407 {"p1", IKE_SVC_FLUSH_P1S},
408 {NULL, IKE_SVC_ERROR}
409 }
410 },
411 {"read", IKE_SVC_ERROR, {
412 {"rule", IKE_SVC_READ_RULES},
413 {"preshared", IKE_SVC_READ_PS},
414 {NULL, IKE_SVC_ERROR}
415 }
416 },
417 {"write", IKE_SVC_ERROR, {
418 {"rule", IKE_SVC_WRITE_RULES},
419 {"preshared", IKE_SVC_WRITE_PS},
420 {NULL, IKE_SVC_ERROR}
421 }
422 },
423 {"help", IKEADM_HELP_GENERAL, {
424 {"get", IKEADM_HELP_GET},
425 {"set", IKEADM_HELP_SET},
426 {"add", IKEADM_HELP_ADD},
427 {"del", IKEADM_HELP_DEL},
428 {"dump", IKEADM_HELP_DUMP},
429 {"flush", IKEADM_HELP_FLUSH},
430 {"read", IKEADM_HELP_READ},
431 {"write", IKEADM_HELP_WRITE},
432 {"help", IKEADM_HELP_HELP},
433 {NULL, IKE_SVC_ERROR}
434 }
435 },
436 {"exit", IKEADM_EXIT, {
437 {NULL, IKE_SVC_ERROR}
438 }
439 },
440 {"quit", IKEADM_EXIT, {
441 {NULL, IKE_SVC_ERROR}
442 }
443 },
444 {"dbg", IKE_SVC_ERROR, {
445 {"rbdump", IKE_SVC_DBG_RBDUMP},
446 {NULL, IKE_SVC_ERROR}
447 }
448 },
449 {NULL, IKE_SVC_ERROR, {
450 {NULL, IKE_SVC_ERROR}
451 }
452 }
453 };
454 struct cmdtbl *ct = table;
455 struct objtbl *ot;
456
457 if (cmdstr == NULL) {
458 return (IKE_SVC_ERROR);
459 }
460
461 while (ct->cmd != NULL && strcmp(ct->cmd, cmdstr) != 0)
462 ct++;
463 ot = ct->objt;
464
465 if (ct->cmd == NULL) {
466 message(gettext("Unrecognized command '%s'"), cmdstr);
467 return (ot->token);
468 }
469
470 if (objstr == NULL) {
471 return (ct->null_obj_token);
472 }
473
474 while (ot->obj != NULL && strcmp(ot->obj, objstr) != 0)
475 ot++;
476
477 if (ot->obj == NULL)
478 message(gettext("Unrecognized object '%s'"), objstr);
479
480 return (ot->token);
481 }
482
483 /*
484 * Parsing functions:
485 * Parse command-line identification info. All return -1 on failure,
486 * or the number of cmd-line args "consumed" on success (though argc
487 * and argv params are not actually modified).
488 */
489
490 static int
491 parse_label(int argc, char **argv, char *label)
492 {
493 if ((argc < 1) || (argv == NULL))
494 return (-1);
495
496 if (strlcpy(label, argv[0], MAX_LABEL_LEN) >= MAX_LABEL_LEN)
497 return (-1);
498
499 return (1);
500 }
501
502 /*
503 * Parse an address off the command line. In the hpp param, either
504 * return a hostent pointer (caller frees) or a pointer to a dummy_he_t
505 * (must also be freed by the caller; both cases are handled by the
506 * macro FREE_HE). The new getipnodebyname() call does the Right Thing
507 * (TM), even with raw addresses (colon-separated IPv6 or dotted decimal
508 * IPv4).
509 * (mostly stolen from ipseckey.c, though some tweaks were made
510 * to better serve our purposes here.)
511 */
512
513 typedef struct {
514 struct hostent he;
515 char *addtl[2];
516 } dummy_he_t;
517
518 static int
519 parse_addr(int argc, char **argv, struct hostent **hpp)
520 {
521 int hp_errno;
522 struct hostent *hp = NULL;
523 dummy_he_t *dhp;
524 char *addr1;
525
526 if ((argc < 1) || (argv == NULL) || (argv[0] == NULL))
527 return (-1);
528
529 if (!nflag) {
530 /*
531 * Try name->address first. Assume AF_INET6, and
532 * get IPV4s, plus IPv6s iff IPv6 is configured.
533 */
534 hp = getipnodebyname(argv[0], AF_INET6, AI_DEFAULT | AI_ALL,
535 &hp_errno);
536 } else {
537 /*
538 * Try a normal address conversion only. malloc a
539 * dummy_he_t to construct a fake hostent. Caller
540 * will know to free this one using free_he().
541 */
542 dhp = (dummy_he_t *)malloc(sizeof (dummy_he_t));
543 addr1 = (char *)malloc(sizeof (struct in6_addr));
544 if (inet_pton(AF_INET6, argv[0], addr1) == 1) {
545 dhp->he.h_addr_list = dhp->addtl;
546 dhp->addtl[0] = addr1;
547 dhp->addtl[1] = NULL;
548 hp = &dhp->he;
549 dhp->he.h_addrtype = AF_INET6;
550 dhp->he.h_length = sizeof (struct in6_addr);
551 } else if (inet_pton(AF_INET, argv[0], addr1) == 1) {
552 dhp->he.h_addr_list = dhp->addtl;
553 dhp->addtl[0] = addr1;
554 dhp->addtl[1] = NULL;
555 hp = &dhp->he;
556 dhp->he.h_addrtype = AF_INET;
557 dhp->he.h_length = sizeof (struct in_addr);
558 } else {
559 hp = NULL;
560 }
561 }
562
563 *hpp = hp;
564
565 if (hp == NULL) {
566 message(gettext("Unknown address %s."), argv[0]);
567 return (-1);
568 }
569
570 return (1);
571 }
572
573 /*
574 * Free a dummy_he_t structure that was malloc'd in parse_addr().
575 * Unfortunately, callers of parse_addr don't want to know about
576 * dummy_he_t structs, so all they have is a pointer to the struct
577 * hostent; so that's what's passed in. To manage this, we make
578 * the assumption that the struct hostent is the first field in
579 * the dummy_he_t, and therefore a pointer to it is a pointer to
580 * the dummy_he_t.
581 */
582 static void
583 free_he(struct hostent *hep)
584 {
585 dummy_he_t *p = (dummy_he_t *)hep;
586
587 assert(p != NULL);
588
589 if (p->addtl[0])
590 free(p->addtl[0]);
591 if (p->addtl[1])
592 free(p->addtl[1]);
593
594 free(p);
595 }
596
597 #define FREE_HE(x) \
598 if (nflag) \
599 free_he(x); \
600 else \
601 freehostent(x)
602
603 static void
604 headdr2sa(char *hea, struct sockaddr_storage *sa, int len)
605 {
606 struct sockaddr_in *sin;
607 struct sockaddr_in6 *sin6;
608
609 if (len == sizeof (struct in6_addr)) {
610 /* LINTED E_BAD_PTR_CAST_ALIGN */
611 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)hea)) {
612 sin = (struct sockaddr_in *)sa;
613 (void) memset(sin, 0, sizeof (*sin));
614 /* LINTED E_BAD_PTR_CAST_ALIGN */
615 IN6_V4MAPPED_TO_INADDR((struct in6_addr *)hea,
616 &sin->sin_addr);
617 sin->sin_family = AF_INET;
618 } else {
619 sin6 = (struct sockaddr_in6 *)sa;
620 (void) memset(sin6, 0, sizeof (*sin6));
621 (void) memcpy(&sin6->sin6_addr, hea,
622 sizeof (struct in6_addr));
623 sin6->sin6_family = AF_INET6;
624 }
625 } else {
626 sin = (struct sockaddr_in *)sa;
627 (void) memset(sin, 0, sizeof (*sin));
628 (void) memcpy(&sin->sin_addr, hea, sizeof (struct in_addr));
629 sin->sin_family = AF_INET;
630 }
631 }
632
633 /*
634 * The possible ident-type keywords that might be used on the command
635 * line. This is a superset of the ones supported by ipseckey, those
636 * in the ike config file, and those in ike.preshared.
637 */
638 static keywdtab_t idtypes[] = {
639 /* ip, ipv4, and ipv6 are valid for preshared keys... */
640 {SADB_IDENTTYPE_RESERVED, "ip"},
641 {SADB_IDENTTYPE_RESERVED, "ipv4"},
642 {SADB_IDENTTYPE_RESERVED, "ipv6"},
643 {SADB_IDENTTYPE_PREFIX, "prefix"},
644 {SADB_IDENTTYPE_PREFIX, "ipv4-prefix"},
645 {SADB_IDENTTYPE_PREFIX, "ipv6-prefix"},
646 {SADB_IDENTTYPE_PREFIX, "subnet"},
647 {SADB_IDENTTYPE_PREFIX, "subnetv4"},
648 {SADB_IDENTTYPE_PREFIX, "subnetv6"},
649 {SADB_IDENTTYPE_FQDN, "fqdn"},
650 {SADB_IDENTTYPE_FQDN, "dns"},
651 {SADB_IDENTTYPE_FQDN, "domain"},
652 {SADB_IDENTTYPE_FQDN, "domainname"},
653 {SADB_IDENTTYPE_USER_FQDN, "user_fqdn"},
654 {SADB_IDENTTYPE_USER_FQDN, "mbox"},
655 {SADB_IDENTTYPE_USER_FQDN, "mailbox"},
656 {SADB_X_IDENTTYPE_DN, "dn"},
657 {SADB_X_IDENTTYPE_DN, "asn1dn"},
658 {SADB_X_IDENTTYPE_GN, "gn"},
659 {SADB_X_IDENTTYPE_GN, "asn1gn"},
660 {SADB_X_IDENTTYPE_ADDR_RANGE, "ipv4-range"},
661 {SADB_X_IDENTTYPE_ADDR_RANGE, "ipv6-range"},
662 {SADB_X_IDENTTYPE_ADDR_RANGE, "rangev4"},
663 {SADB_X_IDENTTYPE_ADDR_RANGE, "rangev6"},
664 {SADB_X_IDENTTYPE_KEY_ID, "keyid"},
665 {NULL, 0}
666 };
667
668 static int
669 parse_idtype(char *type, uint16_t *idnum)
670 {
671 keywdtab_t *idp;
672
673 if (type == NULL)
674 return (-1);
675
676 for (idp = idtypes; idp->kw_str != NULL; idp++) {
677 if (strcasecmp(idp->kw_str, type) == 0) {
678 if (idnum != NULL)
679 *idnum = idp->kw_tag;
680 return (1);
681 }
682 }
683
684 return (-1);
685 }
686
687 /*
688 * The sadb_ident_t is malloc'd, since its length varies;
689 * so the caller must free() it when done with the data.
690 */
691 static int
692 parse_ident(int argc, char **argv, sadb_ident_t **idpp)
693 {
694 int alloclen, consumed;
695 sadb_ident_t *idp;
696 if ((argc < 2) || (argv == NULL) || (argv[0] == NULL) ||
697 (argv[1] == NULL))
698 return (-1);
699
700 alloclen = sizeof (sadb_ident_t) + IKEDOORROUNDUP(strlen(argv[1]) + 1);
701 *idpp = idp = (sadb_ident_t *)malloc(alloclen);
702 if (idp == NULL)
703 Bail("parsing identity");
704
705 if ((consumed = parse_idtype(argv[0], &idp->sadb_ident_type)) < 0) {
706 message(gettext("unknown identity type %s."), argv[0]);
707 return (-1);
708 }
709
710 idp->sadb_ident_len = SADB_8TO64(alloclen);
711 idp->sadb_ident_reserved = 0;
712 idp->sadb_ident_id = 0;
713
714 /* now copy in identity param */
715 (void) strlcpy((char *)(idp + 1), argv[1],
716 alloclen - (sizeof (sadb_ident_t)));
717
718 return (++consumed);
719 }
720
721 static int
722 parse_cky(int argc, char **argv, uint64_t *ckyp)
723 {
724 u_longlong_t arg;
725
726 if ((argc < 1) || (argv[0] == NULL))
727 return (-1);
728
729 errno = 0;
730 arg = strtoull(argv[0], NULL, 0);
731 if (errno != 0) {
732 message(gettext("failed to parse cookie %s."), argv[0]);
733 return (-1);
734 }
735
736 *ckyp = (uint64_t)arg;
737
738 return (1);
739 }
740
741 static int
742 parse_addr_pr(int argc, char **argv, struct hostent **h1pp,
743 struct hostent **h2pp)
744 {
745 int rtn, consumed = 0;
746
747 if ((rtn = parse_addr(argc, argv, h1pp)) < 0) {
748 return (-1);
749 }
750 consumed = rtn;
751 argc -= rtn;
752 argv += rtn;
753
754 if ((rtn = parse_addr(argc, argv, h2pp)) < 0) {
755 FREE_HE(*h1pp);
756 return (-1);
757 }
758 consumed += rtn;
759
760 return (consumed);
761 }
762
763 /*
764 * The sadb_ident_ts are malloc'd, since their length varies;
765 * so the caller must free() them when done with the data.
766 */
767 static int
768 parse_ident_pr(int argc, char **argv, sadb_ident_t **id1pp,
769 sadb_ident_t **id2pp)
770 {
771 int rtn, consumed = 0;
772
773 if ((rtn = parse_ident(argc, argv, id1pp)) < 0) {
774 return (-1);
775 }
776 consumed = rtn;
777 argc -= rtn;
778 argv += rtn;
779
780 (*id1pp)->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
781
782 if ((rtn = parse_ident(argc, argv, id2pp)) < 0) {
783 free(*id1pp);
784 return (-1);
785 }
786 consumed += rtn;
787
788 (*id2pp)->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
789
790 return (consumed);
791 }
792
793 static int
794 parse_cky_pr(int argc, char **argv, ike_cky_pr_t *cpr)
795 {
796 int rtn, consumed = 0;
797
798 if ((rtn = parse_cky(argc, argv, &cpr->cky_i)) < 0) {
799 return (-1);
800 }
801 consumed = rtn;
802 argc -= rtn;
803 argv += rtn;
804
805 if ((rtn = parse_cky(argc, argv, &cpr->cky_r)) < 0) {
806 return (-1);
807 }
808 consumed += rtn;
809
810 return (consumed);
811 }
812
813 /*
814 * Preshared key field types...used for parsing preshared keys that
815 * have been entered on the command line. The code to parse preshared
816 * keys (parse_ps, parse_key, parse_psfldid, parse_ikmtype, ...) is
817 * mostly duplicated from in.iked's readps.c.
818 */
819 #define PSFLD_LOCID 1
820 #define PSFLD_LOCIDTYPE 2
821 #define PSFLD_REMID 3
822 #define PSFLD_REMIDTYPE 4
823 #define PSFLD_MODE 5
824 #define PSFLD_KEY 6
825
826 static keywdtab_t psfldtypes[] = {
827 {PSFLD_LOCID, "localid"},
828 {PSFLD_LOCIDTYPE, "localidtype"},
829 {PSFLD_REMID, "remoteid"},
830 {PSFLD_REMIDTYPE, "remoteidtype"},
831 {PSFLD_MODE, "ike_mode"},
832 {PSFLD_KEY, "key"},
833 {NULL, 0}
834 };
835
836 static int
837 parse_psfldid(char *type, uint16_t *idnum)
838 {
839 keywdtab_t *pfp;
840
841 if (type == NULL)
842 return (-1);
843
844 for (pfp = psfldtypes; pfp->kw_str != NULL; pfp++) {
845 if (strcasecmp(pfp->kw_str, type) == 0) {
846 if (idnum != NULL)
847 *idnum = pfp->kw_tag;
848 return (1);
849 }
850 }
851
852 return (-1);
853 }
854
855 static keywdtab_t ikemodes[] = {
856 {IKE_XCHG_IDENTITY_PROTECT, "main"},
857 {IKE_XCHG_AGGRESSIVE, "aggressive"},
858 {IKE_XCHG_IP_AND_AGGR, "both"},
859 {NULL, 0}
860 };
861
862 static int
863 parse_ikmtype(char *mode, uint16_t *modenum)
864 {
865 keywdtab_t *ikmp;
866
867 if (mode == NULL)
868 return (-1);
869
870 for (ikmp = ikemodes; ikmp->kw_str != NULL; ikmp++) {
871 if (strcasecmp(ikmp->kw_str, mode) == 0) {
872 if (modenum != NULL)
873 *modenum = ikmp->kw_tag;
874 return (1);
875 }
876 }
877
878 return (-1);
879 }
880
881 #define hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \
882 (((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10)))
883
884 static uint8_t *
885 parse_key(char *input, uint_t *keybuflen, uint_t *lbits)
886 {
887 uint8_t *keyp, *keybufp;
888 uint_t i, hexlen = 0, bits, alloclen;
889
890 for (i = 0; input[i] != '\0' && input[i] != '/'; i++)
891 hexlen++;
892
893 if (input[i] == '\0') {
894 bits = 0;
895 } else {
896 /* Have /nn. */
897 input[i] = '\0';
898 if (sscanf((input + i + 1), "%u", &bits) != 1)
899 return (NULL);
900
901 /* hexlen is in nibbles */
902 if (((bits + 3) >> 2) > hexlen)
903 return (NULL);
904
905 /*
906 * Adjust hexlen down if user gave us too small of a bit
907 * count.
908 */
909 if ((hexlen << 2) > bits + 3) {
910 hexlen = (bits + 3) >> 2;
911 input[hexlen] = '\0';
912 }
913 }
914
915 /*
916 * Allocate. Remember, hexlen is in nibbles.
917 */
918
919 alloclen = (hexlen/2 + (hexlen & 0x1));
920 keyp = malloc(alloclen);
921
922 if (keyp == NULL)
923 return (NULL);
924
925 keybufp = keyp;
926 *keybuflen = alloclen;
927 if (bits == 0)
928 *lbits = (hexlen + (hexlen & 0x1)) << 2;
929 else
930 *lbits = bits;
931
932 /*
933 * Read in nibbles. Read in odd-numbered as shifted high.
934 * (e.g. 123 becomes 0x1230).
935 */
936 for (i = 0; input[i] != '\0'; i += 2) {
937 boolean_t second = (input[i + 1] != '\0');
938
939 if (!isxdigit(input[i]) ||
940 (!isxdigit(input[i + 1]) && second)) {
941 free(keyp);
942 return (NULL);
943 }
944 *keyp = (hd2num(input[i]) << 4);
945 if (second)
946 *keyp |= hd2num(input[i + 1]);
947 else
948 break; /* out of for loop. */
949 keyp++;
950 }
951
952 /* zero the remaining bits if we're a non-octet amount. */
953 if (bits & 0x7)
954 *((input[i] == '\0') ? keyp - 1 : keyp) &=
955 0xff << (8 - (bits & 0x7));
956 return (keybufp);
957 }
958
959 /*
960 * the ike_ps_t struct (plus trailing data) will be allocated here,
961 * so it will need to be freed by the caller.
962 */
963 static int
964 parse_ps(int argc, char **argv, ike_ps_t **presharedpp, int *len)
965 {
966 uint_t c = 0, locidlen, remidlen, keylen, keybits;
967 uint_t a_locidtotal = 0, a_remidtotal = 0;
968 char *locid, *remid;
969 uint8_t *keyp = NULL;
970 uint16_t fldid, locidtype, remidtype, mtype;
971 struct hostent *loche = NULL, *remhe = NULL;
972 ike_ps_t *psp = NULL;
973 sadb_ident_t *sidp;
974 boolean_t whacked = B_FALSE;
975
976 if ((argv[c] == NULL) || (argv[c][0] != '{'))
977 return (-1);
978 if (argv[c][1] != 0) {
979 /* no space between '{' and first token */
980 argv[c]++;
981 } else {
982 c++;
983 }
984 if ((argv[argc - 1][strlen(argv[argc - 1]) - 1] == '}') &&
985 (argv[argc - 1][0] != '}')) {
986 /*
987 * whack '}' without a space before it or parsers break.
988 * Remember this trailing character for later
989 */
990 argv[argc - 1][strlen(argv[argc - 1]) - 1] = '\0';
991 whacked = B_TRUE;
992 }
993
994 while ((c < argc) && (argv[c] != NULL) && (argv[c][0] != '}')) {
995 if ((argv[c + 1] == NULL) || (argv[c + 1][0] == '}'))
996 goto bail;
997 if (parse_psfldid(argv[c++], &fldid) < 0)
998 goto bail;
999 switch (fldid) {
1000 case PSFLD_LOCID:
1001 locid = argv[c++];
1002 locidlen = strlen(locid) + 1;
1003 break;
1004 case PSFLD_LOCIDTYPE:
1005 if (parse_idtype(argv[c++], &locidtype) < 0)
1006 goto bail;
1007 break;
1008 case PSFLD_REMID:
1009 remid = argv[c++];
1010 remidlen = strlen(remid) + 1;
1011 break;
1012 case PSFLD_REMIDTYPE:
1013 if (parse_idtype(argv[c++], &remidtype) < 0)
1014 goto bail;
1015 break;
1016 case PSFLD_MODE:
1017 if (parse_ikmtype(argv[c++], &mtype) < 0)
1018 goto bail;
1019 break;
1020 case PSFLD_KEY:
1021 keyp = parse_key(argv[c++], &keylen, &keybits);
1022 if (keyp == NULL)
1023 goto bail;
1024 break;
1025 }
1026 }
1027
1028 /* Make sure the line was terminated with '}' */
1029 if (argv[c] == NULL) {
1030 if (!whacked)
1031 goto bail;
1032 } else if (argv[c][0] != '}') {
1033 goto bail;
1034 }
1035
1036 /*
1037 * make sure we got all the required fields. If no idtype, assume
1038 * ip addr; if that translation fails, we'll catch the error then.
1039 */
1040 if (locid == NULL || remid == NULL || keyp == NULL || mtype == 0)
1041 goto bail;
1042
1043 /* figure out the size buffer we need */
1044 *len = sizeof (ike_ps_t);
1045 if (locidtype != SADB_IDENTTYPE_RESERVED) {
1046 a_locidtotal = IKEDOORROUNDUP(sizeof (sadb_ident_t) + locidlen);
1047 *len += a_locidtotal;
1048 }
1049 if (remidtype != SADB_IDENTTYPE_RESERVED) {
1050 a_remidtotal = IKEDOORROUNDUP(sizeof (sadb_ident_t) + remidlen);
1051 *len += a_remidtotal;
1052 }
1053 *len += keylen;
1054
1055 psp = malloc(*len);
1056 if (psp == NULL)
1057 goto bail;
1058 (void) memset(psp, 0, *len);
1059
1060 psp->ps_ike_mode = mtype;
1061
1062 psp->ps_localid_off = sizeof (ike_ps_t);
1063 if (locidtype == SADB_IDENTTYPE_RESERVED) {
1064 /*
1065 * this is an ip address, store in the sockaddr field;
1066 * we won't use an sadb_ident_t.
1067 */
1068 psp->ps_localid_len = 0;
1069 if (parse_addr(1, &locid, &loche) < 0)
1070 goto bail;
1071 if (loche->h_addr_list[1] != NULL) {
1072 message(gettext("preshared key identifier cannot "
1073 "match multiple IP addresses"));
1074 goto bail;
1075 }
1076 headdr2sa(loche->h_addr_list[0], &psp->ps_ipaddrs.loc_addr,
1077 loche->h_length);
1078 FREE_HE(loche);
1079 } else {
1080 psp->ps_localid_len = sizeof (sadb_ident_t) + locidlen;
1081 sidp = (sadb_ident_t *)((int)psp + psp->ps_localid_off);
1082 sidp->sadb_ident_len = psp->ps_localid_len;
1083 sidp->sadb_ident_type = locidtype;
1084 (void) strlcpy((char *)(sidp + 1), locid, a_locidtotal);
1085 }
1086
1087 psp->ps_remoteid_off = psp->ps_localid_off + a_locidtotal;
1088 if (remidtype == SADB_IDENTTYPE_RESERVED) {
1089 /*
1090 * this is an ip address, store in the sockaddr field;
1091 * we won't use an sadb_ident_t.
1092 */
1093 psp->ps_remoteid_len = 0;
1094 if (parse_addr(1, &remid, &remhe) < 0)
1095 goto bail;
1096 if (remhe->h_addr_list[1] != NULL) {
1097 message(gettext("preshared key identifier cannot "
1098 "match multiple IP addresses"));
1099 goto bail;
1100 }
1101 headdr2sa(remhe->h_addr_list[0], &psp->ps_ipaddrs.rem_addr,
1102 remhe->h_length);
1103 FREE_HE(remhe);
1104 } else {
1105 /* make sure we have at least 16-bit alignment */
1106 if (remidlen & 0x1)
1107 remidlen++;
1108 psp->ps_remoteid_len = sizeof (sadb_ident_t) + remidlen;
1109 sidp = (sadb_ident_t *)((int)psp + psp->ps_remoteid_off);
1110 sidp->sadb_ident_len = psp->ps_remoteid_len;
1111 sidp->sadb_ident_type = remidtype;
1112 (void) strlcpy((char *)(sidp + 1), remid, a_remidtotal);
1113 }
1114
1115 psp->ps_key_off = psp->ps_remoteid_off + a_remidtotal;
1116 psp->ps_key_len = keylen;
1117 psp->ps_key_bits = keybits;
1118 (void) memcpy((uint8_t *)((int)psp + psp->ps_key_off), keyp, keylen);
1119
1120 *presharedpp = psp;
1121
1122 return (c);
1123
1124 bail:
1125 if (loche != NULL)
1126 FREE_HE(loche);
1127 if (remhe != NULL)
1128 FREE_HE(remhe);
1129 if (keyp != NULL)
1130 free(keyp);
1131 if (psp != NULL)
1132 free(psp);
1133
1134 *presharedpp = NULL;
1135
1136 return (-1);
1137 }
1138
1139 /*
1140 * Printing functions
1141 *
1142 * A potential point of confusion here is that the ikeadm-specific string-
1143 * producing functions do not match the ipsec_util.c versions in style: the
1144 * ikeadm-specific functions return a string (and are named foostr), while
1145 * the ipsec_util.c functions actually print the string to the file named
1146 * in the second arg to the function (and are named dump_foo).
1147 *
1148 * Localization for ikeadm seems more straightforward when complete
1149 * phrases are translated rather than: a part of a phrase, a call to
1150 * dump_foo(), and more of the phrase. It could also accommodate
1151 * non-English grammar more easily.
1152 */
1153
1154 static char *
1155 errstr(int err)
1156 {
1157 static char rtn[MAXLINESIZE];
1158
1159 switch (err) {
1160 case IKE_ERR_NO_OBJ:
1161 return (gettext("No data returned"));
1162 case IKE_ERR_NO_DESC:
1163 return (gettext("No destination provided"));
1164 case IKE_ERR_ID_INVALID:
1165 return (gettext("Id info invalid"));
1166 case IKE_ERR_LOC_INVALID:
1167 return (gettext("Destination invalid"));
1168 case IKE_ERR_CMD_INVALID:
1169 return (gettext("Command invalid"));
1170 case IKE_ERR_DATA_INVALID:
1171 return (gettext("Supplied data invalid"));
1172 case IKE_ERR_CMD_NOTSUP:
1173 return (gettext("Unknown command"));
1174 case IKE_ERR_REQ_INVALID:
1175 return (gettext("Request invalid"));
1176 case IKE_ERR_NO_PRIV:
1177 return (gettext("Not allowed at current privilege level"));
1178 case IKE_ERR_SYS_ERR:
1179 return (gettext("System error"));
1180 case IKE_ERR_DUP_IGNORED:
1181 return (gettext("One or more duplicate entries ignored"));
1182 default:
1183 (void) snprintf(rtn, MAXLINESIZE,
1184 gettext("<unknown error %d>"), err);
1185 return (rtn);
1186 }
1187 }
1188
1189 static char *
1190 dbgstr(int bit)
1191 {
1192 static char rtn[MAXLINESIZE];
1193
1194 switch (bit) {
1195 case D_CERT:
1196 return (gettext("Certificate management"));
1197 case D_KEY:
1198 return (gettext("Key management"));
1199 case D_OP:
1200 return (gettext("Operational"));
1201 case D_P1:
1202 return (gettext("Phase 1 SA creation"));
1203 case D_P2:
1204 return (gettext("Phase 2 SA creation"));
1205 case D_PFKEY:
1206 return (gettext("PF_KEY interface"));
1207 case D_POL:
1208 return (gettext("Policy management"));
1209 case D_PROP:
1210 return (gettext("Proposal construction"));
1211 case D_DOOR:
1212 return (gettext("Door interface"));
1213 case D_CONFIG:
1214 return (gettext("Config file processing"));
1215 default:
1216 (void) snprintf(rtn, MAXLINESIZE,
1217 gettext("<unknown flag 0x%x>"), bit);
1218 return (rtn);
1219 }
1220 }
1221
1222 static char *
1223 privstr(int priv)
1224 {
1225 static char rtn[MAXLINESIZE];
1226
1227 switch (priv) {
1228 case IKE_PRIV_MINIMUM:
1229 return (gettext("base privileges"));
1230 case IKE_PRIV_MODKEYS:
1231 return (gettext("access to preshared key information"));
1232 case IKE_PRIV_KEYMAT:
1233 return (gettext("access to keying material"));
1234 default:
1235 (void) snprintf(rtn, MAXLINESIZE,
1236 gettext("<unknown level %d>"), priv);
1237 return (rtn);
1238 }
1239 }
1240
1241 static char *
1242 xchgstr(int xchg)
1243 {
1244 static char rtn[MAXLINESIZE];
1245
1246 switch (xchg) {
1247 case IKE_XCHG_NONE:
1248 return (gettext("<unspecified>"));
1249 case IKE_XCHG_BASE:
1250 return (gettext("base"));
1251 case IKE_XCHG_IDENTITY_PROTECT:
1252 return (gettext("main mode (identity protect)"));
1253 case IKE_XCHG_AUTH_ONLY:
1254 return (gettext("authentication only"));
1255 case IKE_XCHG_AGGRESSIVE:
1256 return (gettext("aggressive mode"));
1257 case IKE_XCHG_IP_AND_AGGR:
1258 return (gettext("main and aggressive mode"));
1259 case IKE_XCHG_ANY:
1260 return (gettext("any mode"));
1261 default:
1262 (void) snprintf(rtn, MAXLINESIZE,
1263 gettext("<unknown %d>"), xchg);
1264 return (rtn);
1265 }
1266 }
1267
1268 static char *
1269 statestr(int state)
1270 {
1271 static char rtn[MAXLINESIZE];
1272
1273 switch (state) {
1274 case IKE_SA_STATE_INIT:
1275 return (gettext("INITIALIZING"));
1276 case IKE_SA_STATE_SENT_SA:
1277 return (gettext("SENT FIRST MSG (SA)"));
1278 case IKE_SA_STATE_SENT_KE:
1279 return (gettext("SENT SECOND MSG (KE)"));
1280 case IKE_SA_STATE_SENT_LAST:
1281 return (gettext("SENT FINAL MSG"));
1282 case IKE_SA_STATE_DONE:
1283 return (gettext("ACTIVE"));
1284 case IKE_SA_STATE_DELETED:
1285 return (gettext("DELETED"));
1286 case IKE_SA_STATE_INVALID:
1287 return (gettext("<invalid>"));
1288 default:
1289 (void) snprintf(rtn, MAXLINESIZE,
1290 gettext("<unknown %d>"), state);
1291 return (rtn);
1292 }
1293 }
1294
1295 static char *
1296 authmethstr(int meth)
1297 {
1298 static char rtn[MAXLINESIZE];
1299
1300 switch (meth) {
1301 case IKE_AUTH_METH_PRE_SHARED_KEY:
1302 return (gettext("pre-shared key"));
1303 case IKE_AUTH_METH_DSS_SIG:
1304 return (gettext("DSS signatures"));
1305 case IKE_AUTH_METH_RSA_SIG:
1306 return (gettext("RSA signatures"));
1307 case IKE_AUTH_METH_RSA_ENCR:
1308 return (gettext("RSA Encryption"));
1309 case IKE_AUTH_METH_RSA_ENCR_REVISED:
1310 return (gettext("Revised RSA Encryption"));
1311 default:
1312 (void) snprintf(rtn, MAXLINESIZE,
1313 gettext("<unknown %d>"), meth);
1314 return (rtn);
1315 }
1316 }
1317
1318 static char *
1319 prfstr(int prf)
1320 {
1321 static char rtn[MAXLINESIZE];
1322
1323 switch (prf) {
1324 case IKE_PRF_NONE:
1325 return (gettext("<none/unavailable>"));
1326 case IKE_PRF_HMAC_MD5:
1327 return ("HMAC MD5");
1328 case IKE_PRF_HMAC_SHA1:
1329 return ("HMAC SHA1");
1330 case IKE_PRF_HMAC_SHA256:
1331 return ("HMAC SHA256");
1332 case IKE_PRF_HMAC_SHA384:
1333 return ("HMAC SHA384");
1334 case IKE_PRF_HMAC_SHA512:
1335 return ("HMAC SHA512");
1336 default:
1337 (void) snprintf(rtn, MAXLINESIZE,
1338 gettext("<unknown %d>"), prf);
1339 return (rtn);
1340 }
1341 }
1342
1343 static char *
1344 dhstr(int grp)
1345 {
1346 static char rtn[MAXLINESIZE];
1347
1348 switch (grp) {
1349 case 0:
1350 return (gettext("<unavailable>"));
1351 case IKE_GRP_DESC_MODP_768:
1352 return (gettext("768-bit MODP (group 1)"));
1353 case IKE_GRP_DESC_MODP_1024:
1354 return (gettext("1024-bit MODP (group 2)"));
1355 case IKE_GRP_DESC_EC2N_155:
1356 return (gettext("EC2N group on GP[2^155]"));
1357 case IKE_GRP_DESC_EC2N_185:
1358 return (gettext("EC2N group on GP[2^185]"));
1359 case IKE_GRP_DESC_MODP_1536:
1360 return (gettext("1536-bit MODP (group 5)"));
1361 case IKE_GRP_DESC_MODP_2048:
1362 return (gettext("2048-bit MODP (group 14)"));
1363 case IKE_GRP_DESC_MODP_3072:
1364 return (gettext("3072-bit MODP (group 15)"));
1365 case IKE_GRP_DESC_MODP_4096:
1366 return (gettext("4096-bit MODP (group 16)"));
1367 case IKE_GRP_DESC_MODP_6144:
1368 return (gettext("6144-bit MODP (group 17)"));
1369 case IKE_GRP_DESC_MODP_8192:
1370 return (gettext("8192-bit MODP (group 18)"));
1371 default:
1372 (void) snprintf(rtn, MAXLINESIZE, gettext("<unknown %d>"), grp);
1373 return (rtn);
1374 }
1375 }
1376
1377 static void
1378 print_hdr(char *prefix, ike_p1_hdr_t *hdrp)
1379 {
1380 (void) printf(
1381 gettext("%s Cookies: Initiator 0x%llx Responder 0x%llx\n"),
1382 prefix, ntohll(hdrp->p1hdr_cookies.cky_i),
1383 ntohll(hdrp->p1hdr_cookies.cky_r));
1384 (void) printf(gettext("%s The local host is the %s.\n"), prefix,
1385 hdrp->p1hdr_isinit ? gettext("initiator") : gettext("responder"));
1386 (void) printf(gettext("%s ISAKMP version %d.%d; %s exchange\n"), prefix,
1387 hdrp->p1hdr_major, hdrp->p1hdr_minor, xchgstr(hdrp->p1hdr_xchg));
1388 (void) printf(gettext("%s Current state is %s"), prefix,
1389 statestr(hdrp->p1hdr_state));
1390 (void) printf("\n");
1391 }
1392
1393 static void
1394 print_lt_limits(char *prefix, ike_p1_xform_t *xfp)
1395 {
1396 (void) printf(gettext("%s Lifetime limits:\n"), prefix);
1397 (void) printf(gettext("%s %u seconds; %u kbytes protected; "),
1398 prefix, xfp->p1xf_max_secs, xfp->p1xf_max_kbytes);
1399 (void) printf(gettext("%u keymat provided.\n"), xfp->p1xf_max_keyuses);
1400 }
1401
1402 #define LT_USAGE_LEN 16 /* 1 uint64 + 2 uint32s */
1403 static void
1404 print_lt_usage(char *prefix, ike_p1_stats_t *sp)
1405 {
1406 time_t scratch;
1407 char tbuf[TBUF_SIZE];
1408
1409 (void) printf(gettext("%s Current usage:\n"), prefix);
1410 scratch = (time_t)sp->p1stat_start;
1411 if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&scratch)) == 0)
1412 (void) strlcpy(tbuf, gettext("<time conversion failed>"),
1413 TBUF_SIZE);
1414 (void) printf(gettext("%s SA was created at %s\n"), prefix, tbuf);
1415 (void) printf(gettext("%s %u kbytes protected; %u keymat provided.\n"),
1416 prefix, sp->p1stat_kbytes, sp->p1stat_keyuses);
1417 }
1418
1419 static void
1420 print_xform(char *prefix, ike_p1_xform_t *xfp, boolean_t print_lifetimes)
1421 {
1422 (void) printf(gettext("%s Authentication method: %s"), prefix,
1423 authmethstr(xfp->p1xf_auth_meth));
1424 (void) printf(gettext("\n%s Encryption alg: "), prefix);
1425 (void) dump_ealg(xfp->p1xf_encr_alg, stdout);
1426 if (xfp->p1xf_encr_low_bits != 0) {
1427 (void) printf(gettext("(%d..%d)"), xfp->p1xf_encr_low_bits,
1428 xfp->p1xf_encr_high_bits);
1429 } else if ((xfp->p1xf_encr_low_bits == 0) &&
1430 (xfp->p1xf_encr_high_bits != 0)) {
1431 /*
1432 * High bits is a placeholder for
1433 * negotiated algorithm strength
1434 */
1435 (void) printf(gettext("(%d)"), xfp->p1xf_encr_high_bits);
1436 }
1437 (void) printf(gettext("; Authentication alg: "));
1438 (void) dump_aalg(xfp->p1xf_auth_alg, stdout);
1439 (void) printf("\n%s ", prefix);
1440 if (xfp->p1xf_prf != 0)
1441 (void) printf(gettext("PRF: %s ; "), prfstr(xfp->p1xf_prf));
1442 (void) printf(gettext("Oakley Group: %s\n"),
1443 dhstr(xfp->p1xf_dh_group));
1444 if (xfp->p1xf_pfs == 0) {
1445 (void) printf(gettext("%s Phase 2 PFS is not used\n"), prefix);
1446 } else {
1447 (void) printf(gettext(
1448 "%s Phase 2 PFS is required (Oakley Group: %s)\n"),
1449 prefix, dhstr(xfp->p1xf_pfs));
1450 }
1451
1452 if (print_lifetimes)
1453 print_lt_limits(prefix, xfp);
1454 }
1455
1456 static void
1457 print_lifetime(char *prefix, ike_p1_xform_t *xfp, ike_p1_stats_t *sp,
1458 int statlen)
1459 {
1460 time_t current, remain, exp;
1461 char tbuf[TBUF_SIZE];
1462
1463 current = time(NULL);
1464
1465 print_lt_limits(prefix, xfp);
1466
1467 /*
1468 * make sure the stats struct we've been passed is as big
1469 * as we expect it to be. The usage stats are at the end,
1470 * so anything less than the size we expect won't work.
1471 */
1472 if (statlen >= sizeof (ike_p1_stats_t)) {
1473 print_lt_usage(prefix, sp);
1474 } else {
1475 return;
1476 }
1477
1478 (void) printf(gettext("%s Expiration info:\n"), prefix);
1479
1480 if (xfp->p1xf_max_kbytes != 0)
1481 (void) printf(gettext("%s %u more bytes can be protected.\n"),
1482 prefix, xfp->p1xf_max_kbytes - sp->p1stat_kbytes);
1483
1484 if (xfp->p1xf_max_keyuses != 0)
1485 (void) printf(gettext("%s Keying material can be provided "
1486 "%u more times.\n"), prefix,
1487 xfp->p1xf_max_keyuses - sp->p1stat_keyuses);
1488
1489 if (xfp->p1xf_max_secs != 0) {
1490 exp = (time_t)sp->p1stat_start + (time_t)xfp->p1xf_max_secs;
1491 remain = exp - current;
1492 if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&exp)) == 0)
1493 (void) strlcpy(tbuf,
1494 gettext("<time conversion failed>"), TBUF_SIZE);
1495 /*
1496 * The SA may have expired but still exist because libike
1497 * has not freed it yet.
1498 */
1499 if (remain > 0)
1500 (void) printf(gettext(
1501 "%s SA expires in %lu seconds, at %s\n"),
1502 prefix, remain, tbuf);
1503 else
1504 (void) printf(gettext("%s SA Expired at %s\n"),
1505 prefix, tbuf);
1506 }
1507 }
1508
1509 /* used to verify structure lengths... */
1510 #define COUNTER_32BIT 4
1511 #define COUNTER_PAIR 8
1512
1513 static void
1514 print_p1stats(char *prefix, ike_p1_stats_t *sp, int statlen,
1515 boolean_t print_lifetimes)
1516 {
1517 if (statlen < COUNTER_PAIR)
1518 return;
1519 (void) printf(gettext("%s %u Quick Mode SAs created; "), prefix,
1520 sp->p1stat_new_qm_sas);
1521 (void) printf(gettext("%u Quick Mode SAs deleted\n"),
1522 sp->p1stat_del_qm_sas);
1523 statlen -= COUNTER_PAIR;
1524
1525 if ((print_lifetimes) && (statlen >= LT_USAGE_LEN))
1526 print_lt_usage(prefix, sp);
1527 }
1528
1529 static void
1530 print_errs(char *prefix, ike_p1_errors_t *errp, int errlen)
1531 {
1532 /*
1533 * Don't try to break this one up; it's either all or nothing!
1534 */
1535 if (errlen < sizeof (ike_p1_errors_t))
1536 return;
1537
1538 (void) printf(gettext("%s %u RX errors: "), prefix,
1539 errp->p1err_decrypt + errp->p1err_hash + errp->p1err_otherrx);
1540 (void) printf(gettext("%u decryption, %u hash, %u other\n"),
1541 errp->p1err_decrypt, errp->p1err_hash, errp->p1err_otherrx);
1542 (void) printf(gettext("%s %u TX errors\n"), prefix, errp->p1err_tx);
1543 }
1544
1545 static void
1546 print_addr_range(char *prefix, ike_addr_pr_t *pr)
1547 {
1548 boolean_t range = B_TRUE;
1549 struct sockaddr_storage *beg, *end;
1550 struct sockaddr_in *bsin, *esin;
1551 struct sockaddr_in6 *bsin6, *esin6;
1552
1553 beg = &pr->beg_iprange;
1554 end = &pr->end_iprange;
1555
1556 if (beg->ss_family != end->ss_family) {
1557 (void) printf(gettext("%s invalid address range\n"), prefix);
1558 return;
1559 }
1560
1561 switch (beg->ss_family) {
1562 case AF_INET:
1563 bsin = (struct sockaddr_in *)beg;
1564 esin = (struct sockaddr_in *)end;
1565 if ((uint32_t)bsin->sin_addr.s_addr ==
1566 (uint32_t)esin->sin_addr.s_addr)
1567 range = B_FALSE;
1568 break;
1569 case AF_INET6:
1570 bsin6 = (struct sockaddr_in6 *)beg;
1571 esin6 = (struct sockaddr_in6 *)end;
1572 if (IN6_ARE_ADDR_EQUAL(&bsin6->sin6_addr, &esin6->sin6_addr))
1573 range = B_FALSE;
1574 break;
1575 default:
1576 (void) printf(gettext("%s invalid address range\n"), prefix);
1577 return;
1578 }
1579
1580 (void) printf("%s ", prefix);
1581 (void) dump_sockaddr((struct sockaddr *)beg, 0, B_TRUE, stdout, nflag);
1582 if (range) {
1583 (void) printf(" - ");
1584 (void) dump_sockaddr((struct sockaddr *)end, 0, B_TRUE, stdout,
1585 nflag);
1586 }
1587 (void) printf("\n");
1588
1589 }
1590
1591 /*
1592 * used to tell printing function if info should be identified
1593 * as belonging to initiator, responder, or neither
1594 */
1595 #define IS_INITIATOR 1
1596 #define IS_RESPONDER 2
1597 #define DONT_PRINT_INIT 3
1598
1599 static void
1600 print_addr(char *prefix, struct sockaddr_storage *sa, int init_instr)
1601 {
1602 (void) printf(gettext("%s Address"), prefix);
1603
1604 if (init_instr != DONT_PRINT_INIT)
1605 (void) printf(" (%s):\n", (init_instr == IS_INITIATOR) ?
1606 gettext("Initiator") : gettext("Responder"));
1607 else
1608 (void) printf(":\n");
1609
1610 (void) printf("%s ", prefix);
1611 (void) dump_sockaddr((struct sockaddr *)sa, 0, B_FALSE, stdout, nflag);
1612 }
1613
1614 static void
1615 print_id(char *prefix, sadb_ident_t *idp, int init_instr)
1616 {
1617 boolean_t canprint;
1618
1619 switch (init_instr) {
1620 case IS_INITIATOR:
1621 (void) printf(gettext("%s Initiator identity, "), prefix);
1622 break;
1623 case IS_RESPONDER:
1624 (void) printf(gettext("%s Responder identity, "), prefix);
1625 break;
1626 case DONT_PRINT_INIT:
1627 (void) printf(gettext("%s Identity, "), prefix);
1628 break;
1629 default:
1630 (void) printf(gettext("<invalid identity>\n"));
1631 return;
1632 }
1633 (void) printf(gettext("uid=%d, type "), idp->sadb_ident_id);
1634 canprint = dump_sadb_idtype(idp->sadb_ident_type, stdout, NULL);
1635 if (canprint) {
1636 (void) printf("\n%s %s\n", prefix, (char *)(idp + 1));
1637 } else {
1638 (void) printf(gettext("\n%s "), prefix);
1639 print_asn1_name(stdout,
1640 (const unsigned char *)(idp + 1),
1641 SADB_64TO8(idp->sadb_ident_len) - sizeof (sadb_ident_t));
1642 }
1643 }
1644
1645 static void
1646 print_idspec(char *prefix, char *idp, int icnt, int ecnt)
1647 {
1648 int i;
1649
1650 (void) printf(gettext("%s Identity descriptors:\n"), prefix);
1651
1652 for (i = 0; i < icnt; i++) {
1653 if (i == 0)
1654 (void) printf(gettext("%s Includes:\n"), prefix);
1655 (void) printf("%s %s\n", prefix, idp);
1656 idp += strlen(idp) + 1;
1657 }
1658
1659 for (i = 0; i < ecnt; i++) {
1660 if (i == 0)
1661 (void) printf(gettext("%s Excludes:\n"), prefix);
1662 (void) printf("%s %s\n", prefix, idp);
1663 idp += strlen(idp) + 1;
1664 }
1665 }
1666
1667 static void
1668 print_keys(char *prefix, ike_p1_key_t *keyp, int size)
1669 {
1670 uint32_t *curp;
1671 ike_p1_key_t *p;
1672 int ssize;
1673
1674 curp = (uint32_t *)keyp;
1675
1676 ssize = sizeof (ike_p1_key_t);
1677
1678 while ((intptr_t)curp - (intptr_t)keyp < size) {
1679 size_t p1klen, len;
1680
1681 p = (ike_p1_key_t *)curp;
1682 p1klen = p->p1key_len;
1683 len = p1klen - ssize;
1684
1685 p1klen = roundup(p1klen, sizeof (ike_p1_key_t));
1686 if (p1klen < ssize) {
1687 (void) printf(gettext("Short key\n"));
1688 break;
1689 }
1690
1691 switch (p->p1key_type) {
1692 case IKE_KEY_PRESHARED:
1693 (void) printf(gettext("%s Pre-shared key (%d bytes): "),
1694 prefix, len);
1695 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1696 stdout);
1697 break;
1698 case IKE_KEY_SKEYID:
1699 (void) printf(gettext("%s SKEYID (%d bytes): "),
1700 prefix, len);
1701 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1702 stdout);
1703 break;
1704 case IKE_KEY_SKEYID_D:
1705 (void) printf(gettext("%s SKEYID_d (%d bytes): "),
1706 prefix, len);
1707 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1708 stdout);
1709 break;
1710 case IKE_KEY_SKEYID_A:
1711 (void) printf(gettext("%s SKEYID_a (%d bytes): "),
1712 prefix, len);
1713 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1714 stdout);
1715 break;
1716 case IKE_KEY_SKEYID_E:
1717 (void) printf(gettext("%s SKEYID_e (%d bytes): "),
1718 prefix, len);
1719 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1720 stdout);
1721 break;
1722 case IKE_KEY_ENCR:
1723 (void) printf(gettext("%s Encryption key (%d bytes): "),
1724 prefix, len);
1725 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1726 stdout);
1727 break;
1728 case IKE_KEY_IV:
1729 (void) printf(
1730 gettext("%s Initialization vector (%d bytes): "),
1731 prefix, len);
1732 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1733 stdout);
1734 break;
1735 default:
1736 (void) printf(gettext("%s Unidentified key info %p %d"),
1737 prefix, p, p1klen);
1738 }
1739 (void) printf("\n");
1740 assert(IS_P2ALIGNED(p1klen, 8));
1741 curp += (p1klen >> 2);
1742 }
1743 }
1744
1745 static void
1746 print_p1(ike_p1_sa_t *p1)
1747 {
1748 ike_p1_stats_t *sp;
1749 ike_p1_errors_t *ep;
1750 ike_p1_key_t *kp;
1751 sadb_ident_t *lidp, *ridp;
1752 int lstat, rstat;
1753
1754 (void) printf("\n");
1755 print_hdr("IKESA:", &p1->p1sa_hdr);
1756 print_xform("XFORM:", &p1->p1sa_xform, B_FALSE);
1757
1758 if (p1->p1sa_hdr.p1hdr_isinit) {
1759 lstat = IS_INITIATOR;
1760 rstat = IS_RESPONDER;
1761 } else {
1762 lstat = IS_RESPONDER;
1763 rstat = IS_INITIATOR;
1764 }
1765 print_addr("LOCIP:", &p1->p1sa_ipaddrs.loc_addr, lstat);
1766 print_addr("REMIP:", &p1->p1sa_ipaddrs.rem_addr, rstat);
1767
1768 /*
1769 * the stat len might be 0; but still make the call
1770 * to print_lifetime() to pick up the xform info
1771 */
1772 sp = (ike_p1_stats_t *)((int)(p1) + p1->p1sa_stat_off);
1773 print_lifetime("LIFTM:", &p1->p1sa_xform, sp, p1->p1sa_stat_len);
1774
1775 if (p1->p1sa_stat_len > 0) {
1776 print_p1stats("STATS:", sp, p1->p1sa_stat_len, B_FALSE);
1777 }
1778
1779 if (p1->p1sa_error_len > 0) {
1780 ep = (ike_p1_errors_t *)((int)(p1) + p1->p1sa_error_off);
1781 print_errs("ERRS: ", ep, p1->p1sa_error_len);
1782 }
1783
1784 if (p1->p1sa_localid_len > 0) {
1785 lidp = (sadb_ident_t *)((int)(p1) + p1->p1sa_localid_off);
1786 print_id("LOCID:", lidp, lstat);
1787 }
1788
1789 if (p1->p1sa_remoteid_len > 0) {
1790 ridp = (sadb_ident_t *)((int)(p1) + p1->p1sa_remoteid_off);
1791 print_id("REMID:", ridp, rstat);
1792 }
1793
1794 if (p1->p1sa_key_len > 0) {
1795 kp = (ike_p1_key_t *)((int)(p1) + p1->p1sa_key_off);
1796 print_keys("KEY: ", kp, p1->p1sa_key_len);
1797 }
1798 }
1799
1800 static void
1801 print_ps(ike_ps_t *ps)
1802 {
1803 sadb_ident_t *lidp, *ridp;
1804 uint8_t *keyp;
1805
1806 (void) printf("\n");
1807
1808 (void) printf(gettext("PSKEY: For %s exchanges\n"),
1809 xchgstr(ps->ps_ike_mode));
1810
1811 if (ps->ps_key_len > 0) {
1812 keyp = (uint8_t *)((int)(ps) + ps->ps_key_off);
1813 (void) printf(gettext("PSKEY: Pre-shared key (%d bytes): "),
1814 ps->ps_key_len);
1815 (void) dump_key(keyp, ps->ps_key_bits, stdout);
1816 (void) printf("\n");
1817 }
1818
1819 /*
1820 * We get *either* and address or an ident, never both. So if
1821 * the ident is there, don't try printing an address.
1822 */
1823 if (ps->ps_localid_len > 0) {
1824 lidp = (sadb_ident_t *)
1825 ((int)(ps) + ps->ps_localid_off);
1826 print_id("LOCID:", lidp, DONT_PRINT_INIT);
1827 } else {
1828 print_addr("LOCIP:", &ps->ps_ipaddrs.loc_addr, DONT_PRINT_INIT);
1829 }
1830
1831 if (ps->ps_remoteid_len > 0) {
1832 ridp = (sadb_ident_t *)
1833 ((int)(ps) + ps->ps_remoteid_off);
1834 print_id("REMID:", ridp, DONT_PRINT_INIT);
1835 } else {
1836 print_addr("REMIP:", &ps->ps_ipaddrs.rem_addr, DONT_PRINT_INIT);
1837 }
1838 }
1839
1840 #define PREFIXLEN 16
1841
1842 static void
1843 print_rule(ike_rule_t *rp)
1844 {
1845 char prefix[PREFIXLEN];
1846 int i;
1847 ike_p1_xform_t *xfp;
1848 ike_addr_pr_t *lipp, *ripp;
1849 char *lidp, *ridp;
1850
1851 (void) printf("\n");
1852 (void) printf(gettext("GLOBL: Label '%s', key manager cookie %u\n"),
1853 rp->rule_label, rp->rule_kmcookie);
1854 (void) printf(gettext("GLOBL: local_idtype="));
1855 (void) dump_sadb_idtype(rp->rule_local_idtype, stdout, NULL);
1856 (void) printf(gettext(", ike_mode=%s\n"), xchgstr(rp->rule_ike_mode));
1857 (void) printf(gettext(
1858 "GLOBL: p1_nonce_len=%u, p2_nonce_len=%u, p2_pfs=%s (group %u)\n"),
1859 rp->rule_p1_nonce_len, rp->rule_p2_nonce_len,
1860 (rp->rule_p2_pfs) ? gettext("true") : gettext("false"),
1861 rp->rule_p2_pfs);
1862 (void) printf(
1863 gettext("GLOBL: p2_lifetime=%u seconds, p2_softlife=%u seconds\n"),
1864 rp->rule_p2_lifetime_secs, rp->rule_p2_softlife_secs);
1865 (void) printf(
1866 gettext("GLOBL: p2_lifetime_kb=%u seconds,"
1867 " p2_softlife_kb=%u seconds\n"),
1868 rp->rule_p2_lifetime_kb, rp->rule_p2_softlife_kb);
1869
1870 if (rp->rule_locip_cnt > 0) {
1871 (void) printf(gettext("LOCIP: IP address range(s):\n"));
1872 lipp = (ike_addr_pr_t *)((int)rp + rp->rule_locip_off);
1873 for (i = 0; i < rp->rule_locip_cnt; i++, lipp++) {
1874 print_addr_range("LOCIP:", lipp);
1875 }
1876 }
1877
1878 if (rp->rule_remip_cnt > 0) {
1879 (void) printf(gettext("REMIP: IP address range(s):\n"));
1880 ripp = (ike_addr_pr_t *)((int)rp + rp->rule_remip_off);
1881 for (i = 0; i < rp->rule_remip_cnt; i++, ripp++) {
1882 print_addr_range("REMIP:", ripp);
1883 }
1884 }
1885
1886 if (rp->rule_locid_inclcnt + rp->rule_locid_exclcnt > 0) {
1887 lidp = (char *)((int)rp + rp->rule_locid_off);
1888 print_idspec("LOCID:", lidp, rp->rule_locid_inclcnt,
1889 rp->rule_locid_exclcnt);
1890 }
1891
1892 if (rp->rule_remid_inclcnt + rp->rule_remid_exclcnt > 0) {
1893 ridp = (char *)((int)rp + rp->rule_remid_off);
1894 print_idspec("REMID:", ridp, rp->rule_remid_inclcnt,
1895 rp->rule_remid_exclcnt);
1896 }
1897
1898 if (rp->rule_xform_cnt > 0) {
1899 (void) printf(gettext("XFRMS: Available Transforms:\n"));
1900 xfp = (ike_p1_xform_t *)((int)rp + rp->rule_xform_off);
1901 for (i = 0; i < rp->rule_xform_cnt; i++, xfp++) {
1902 (void) snprintf(prefix, PREFIXLEN, "XF %2u:", i);
1903 print_xform(prefix, xfp, B_TRUE);
1904 }
1905 }
1906 }
1907
1908 #undef PREFIXLEN
1909
1910 #define PRSACNTS(init, resp) \
1911 (void) printf(gettext("initiator: %10u responder: %10u\n"), \
1912 (init), (resp))
1913
1914 static void
1915 print_stats(ike_stats_t *sp, int len)
1916 {
1917 /*
1918 * before printing each line, make sure the structure we were
1919 * given is big enough to include the fields needed.
1920 */
1921 if (len < COUNTER_PAIR)
1922 return;
1923 (void) printf(gettext("Phase 1 SA counts:\n"));
1924 (void) printf(gettext("Current: "));
1925 PRSACNTS(sp->st_init_p1_current, sp->st_resp_p1_current);
1926 len -= COUNTER_PAIR;
1927
1928 if (len < COUNTER_PAIR)
1929 return;
1930 (void) printf(gettext("Total: "));
1931 PRSACNTS(sp->st_init_p1_total, sp->st_resp_p1_total);
1932 len -= COUNTER_PAIR;
1933
1934 if (len < COUNTER_PAIR)
1935 return;
1936 (void) printf(gettext("Attempted: "));
1937 PRSACNTS(sp->st_init_p1_attempts, sp->st_resp_p1_attempts);
1938 len -= COUNTER_PAIR;
1939
1940 if (len < (COUNTER_PAIR + COUNTER_32BIT))
1941 return;
1942 (void) printf(gettext("Failed: "));
1943 PRSACNTS(sp->st_init_p1_noresp + sp->st_init_p1_respfail,
1944 sp->st_resp_p1_fail);
1945 (void) printf(
1946 gettext(" initiator fails include %u time-out(s)\n"),
1947 sp->st_init_p1_noresp);
1948
1949 if (len < PATH_MAX)
1950 return;
1951 if (*(sp->st_pkcs11_libname) != '\0')
1952 (void) printf(gettext("PKCS#11 library linked in from %s\n"),
1953 sp->st_pkcs11_libname);
1954 }
1955
1956 static void
1957 print_defaults(char *label, char *description, char *unit, boolean_t kbytes,
1958 uint_t current, uint_t def)
1959 {
1960 (void) printf("%-18s%-10s%14u%s%-10s%-26s\n", label,
1961 (current != def) ? gettext("config") : gettext("default"),
1962 (current != def) ? current : def, (kbytes) ? "K " : " ",
1963 unit, description);
1964 }
1965
1966 /*
1967 * Print out defaults used by in.iked, the argument is a buffer containing
1968 * two ike_defaults_t's, the first contains the hard coded defaults, the second
1969 * contains the actual values used. If these differ, then the defaults have been
1970 * changed via a config file entry. Note that "-" indicates this default
1971 * is not tunable.
1972 */
1973 static void
1974 do_print_defaults(ike_defaults_t *dp)
1975 {
1976 ike_defaults_t *ddp;
1977 ddp = (ike_defaults_t *)(dp + 1);
1978
1979 (void) printf(gettext("\nGlobal defaults. Some values can be"
1980 " over-ridden on a per rule basis.\n\n"));
1981
1982 (void) printf("%-18s%-10s%-16s%-10s%-26s\n\n",
1983 gettext("Token:"), gettext("Source:"), gettext("Value:"),
1984 gettext("Unit:"), gettext("Description:"));
1985
1986 print_defaults("p1_lifetime_secs", gettext("phase 1 lifetime"),
1987 gettext("seconds"), B_FALSE, ddp->rule_p1_lifetime_secs,
1988 dp->rule_p1_lifetime_secs);
1989
1990 print_defaults("-", gettext("minimum phase 1 lifetime"),
1991 gettext("seconds"), B_FALSE, ddp->rule_p1_minlife,
1992 dp->rule_p1_minlife);
1993
1994 print_defaults("p1_nonce_len", gettext("phase 1 nonce length"),
1995 gettext("bytes"), B_FALSE, ddp->rule_p1_nonce_len,
1996 dp->rule_p1_nonce_len);
1997
1998 print_defaults("p2_lifetime_secs", gettext("phase 2 lifetime"),
1999 gettext("seconds"), B_FALSE, ddp->rule_p2_lifetime_secs,
2000 dp->rule_p2_lifetime_secs);
2001
2002 print_defaults("p2_softlife_secs", gettext("phase 2 soft lifetime"),
2003 gettext("seconds"), B_FALSE, ddp->rule_p2_softlife_secs,
2004 dp->rule_p2_softlife_secs);
2005
2006 print_defaults("-", gettext("system phase 2 lifetime"),
2007 gettext("seconds"), B_FALSE, ddp->sys_p2_lifetime_secs,
2008 dp->sys_p2_lifetime_secs);
2009
2010 print_defaults("-", gettext("system phase 2 soft lifetime"),
2011 gettext("seconds"), B_FALSE, ddp->sys_p2_softlife_secs,
2012 dp->sys_p2_softlife_secs);
2013
2014 print_defaults("p2_lifetime_kb", gettext("phase 2 lifetime"),
2015 gettext("bytes"), B_TRUE, ddp->rule_p2_lifetime_kb,
2016 dp->rule_p2_lifetime_kb);
2017
2018 print_defaults("p2_softlife_kb", gettext("phase 2 soft lifetime"),
2019 gettext("bytes"), B_TRUE, ddp->rule_p2_softlife_kb,
2020 dp->rule_p2_softlife_kb);
2021
2022 print_defaults("-", gettext("system phase 2 lifetime"),
2023 gettext("bytes"), B_FALSE, ddp->sys_p2_lifetime_bytes,
2024 dp->sys_p2_lifetime_bytes);
2025
2026 print_defaults("-", gettext("system phase 2 soft lifetime"),
2027 gettext("bytes"), B_FALSE, ddp->sys_p2_softlife_bytes,
2028 dp->sys_p2_softlife_bytes);
2029
2030 print_defaults("-", gettext("minimum phase 2 lifetime"),
2031 gettext("seconds"), B_FALSE, ddp->rule_p2_minlife,
2032 dp->rule_p2_minlife);
2033
2034 print_defaults("p2_nonce_len", gettext("phase 2 nonce length"),
2035 gettext("bytes"), B_FALSE, ddp->rule_p2_nonce_len,
2036 dp->rule_p2_nonce_len);
2037
2038 print_defaults("-", gettext("default phase 2 lifetime"),
2039 gettext("seconds"), B_FALSE, ddp->rule_p2_def_minlife,
2040 dp->rule_p2_def_minlife);
2041
2042 print_defaults("-", gettext("minimum phase 2 soft delta"),
2043 gettext("seconds"), B_FALSE, ddp->rule_p2_minsoft,
2044 dp->rule_p2_minsoft);
2045
2046 print_defaults("p2_pfs", gettext("phase 2 PFS"),
2047 " ", B_FALSE, ddp->rule_p2_pfs, dp->rule_p2_pfs);
2048
2049 print_defaults("max_certs", gettext("max certificates"),
2050 " ", B_FALSE, ddp->rule_max_certs, dp->rule_max_certs);
2051
2052 print_defaults("-", gettext("IKE port number"),
2053 " ", B_FALSE, ddp->rule_ike_port, dp->rule_ike_port);
2054
2055 print_defaults("-", gettext("NAT-T port number"),
2056 " ", B_FALSE, ddp->rule_natt_port, dp->rule_natt_port);
2057 }
2058
2059 static void
2060 print_categories(int level)
2061 {
2062 int mask;
2063
2064 if (level == 0) {
2065 (void) printf(gettext("No debug categories enabled.\n"));
2066 return;
2067 }
2068
2069 (void) printf(gettext("Debug categories enabled:"));
2070 for (mask = 1; mask <= D_HIGHBIT; mask <<= 1) {
2071 if (level & mask)
2072 (void) printf("\n\t%s", dbgstr(mask));
2073 }
2074 (void) printf("\n");
2075 }
2076
2077 /*PRINTFLIKE2*/
2078 static void
2079 ikeadm_err_exit(ike_err_t *err, char *fmt, ...)
2080 {
2081 va_list ap;
2082 char bailbuf[BUFSIZ];
2083
2084 va_start(ap, fmt);
2085 (void) vsnprintf(bailbuf, BUFSIZ, fmt, ap);
2086 va_end(ap);
2087 if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) {
2088 bail_msg("%s: %s", bailbuf, (err->ike_err_unix == 0) ?
2089 gettext("<unknown error>") : strerror(err->ike_err_unix));
2090 } else {
2091 bail_msg("%s: %s", bailbuf, (err == NULL) ?
2092 gettext("<unknown error>") : errstr(err->ike_err));
2093 }
2094 }
2095
2096 /*PRINTFLIKE2*/
2097 static void
2098 ikeadm_err_msg(ike_err_t *err, char *fmt, ...)
2099 {
2100 va_list ap;
2101 char mbuf[BUFSIZ];
2102
2103 va_start(ap, fmt);
2104 (void) vsnprintf(mbuf, BUFSIZ, fmt, ap);
2105 va_end(ap);
2106 if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) {
2107 message("%s: %s", mbuf, (err->ike_err_unix == 0) ?
2108 gettext("<unknown error>") :
2109 ((err->ike_err_unix == EEXIST) ?
2110 gettext("Duplicate entry") :
2111 strerror(err->ike_err_unix)));
2112 } else {
2113 message("%s: %s", mbuf, (err == NULL) ?
2114 gettext("<unknown error>") : errstr(err->ike_err));
2115 }
2116 }
2117
2118
2119 /*
2120 * Command functions
2121 */
2122
2123 /*
2124 * Exploit the fact that ike_dbg_t and ike_priv_t have identical
2125 * formats in the following two functions.
2126 */
2127 static void
2128 do_getvar(int cmd)
2129 {
2130 ike_service_t req, *rtn;
2131 ike_dbg_t *dreq;
2132 char *varname;
2133
2134 switch (cmd) {
2135 case IKE_SVC_GET_DBG:
2136 varname = gettext("debug");
2137 break;
2138 case IKE_SVC_GET_PRIV:
2139 varname = gettext("privilege");
2140 break;
2141 default:
2142 bail_msg(gettext("unrecognized get command (%d)"), cmd);
2143 }
2144
2145 dreq = &req.svc_dbg;
2146 dreq->cmd = cmd;
2147 dreq->dbg_level = 0;
2148
2149 rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), NULL, 0);
2150
2151 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2152 ikeadm_err_exit(&rtn->svc_err,
2153 gettext("error getting %s level"), varname);
2154 }
2155 dreq = &rtn->svc_dbg;
2156 (void) printf(gettext("Current %s level is 0x%x"),
2157 varname, dreq->dbg_level);
2158
2159 if (cmd == IKE_SVC_GET_DBG) {
2160 (void) printf("\n");
2161 print_categories(dreq->dbg_level);
2162 } else {
2163 (void) printf(gettext(", %s enabled\n"),
2164 privstr(dreq->dbg_level));
2165 }
2166 }
2167
2168 static void
2169 do_setvar(int cmd, int argc, char **argv)
2170 {
2171 ike_service_t req, *rtn;
2172 ike_dbg_t *dreq;
2173 door_desc_t *descp = NULL, desc;
2174 int fd, ndesc = 0;
2175 uint32_t reqlevel;
2176 char *varname;
2177
2178 if (argc < 1)
2179 Bail("unspecified level");
2180 reqlevel = strtoul(argv[0], NULL, 0);
2181
2182 switch (cmd) {
2183 case IKE_SVC_SET_DBG:
2184 if (argc > 2)
2185 Bail("Too many arguments to \"set debug\"");
2186 varname = gettext("debug");
2187 if (reqlevel == 0) {
2188 /* check for a string... */
2189 reqlevel = parsedbgopts(argv[0]);
2190 }
2191 if (reqlevel == D_INVALID)
2192 bail_msg(gettext("Bad debug flag: %s"), argv[0]);
2193 break;
2194 case IKE_SVC_SET_PRIV:
2195 if (argc > 1)
2196 Bail("Too many arguments to \"set priv\"");
2197
2198 varname = gettext("privilege");
2199 if (reqlevel == 0) {
2200 /* check for a string... */
2201 reqlevel = privstr2num(argv[0]);
2202 }
2203 if (reqlevel > IKE_PRIV_MAXIMUM)
2204 bail_msg(gettext("Bad privilege flag: %s"), argv[0]);
2205 break;
2206 default:
2207 bail_msg(gettext("unrecognized set command (%d)"), cmd);
2208 }
2209
2210 dreq = &req.svc_dbg;
2211 dreq->cmd = cmd;
2212 dreq->dbg_level = reqlevel;
2213
2214 if ((argc == 2) && (cmd == IKE_SVC_SET_DBG)) {
2215 fd = open(argv[1], O_RDWR | O_CREAT | O_APPEND,
2216 S_IRUSR | S_IWUSR);
2217 if (fd < 0)
2218 Bail("open debug file");
2219 desc.d_data.d_desc.d_descriptor = fd;
2220 desc.d_attributes = DOOR_DESCRIPTOR;
2221 descp = &desc;
2222 ndesc = 1;
2223 }
2224
2225 rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), descp, ndesc);
2226
2227 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2228 ikeadm_err_exit(&rtn->svc_err,
2229 gettext("error setting %s level"), varname);
2230 }
2231 dreq = &rtn->svc_dbg;
2232 (void) printf(
2233 gettext("Successfully changed %s level from 0x%x to 0x%x\n"),
2234 varname, dreq->dbg_level, reqlevel);
2235
2236 if (cmd == IKE_SVC_SET_DBG) {
2237 print_categories(reqlevel);
2238 } else {
2239 (void) printf(gettext("New privilege level 0x%x enables %s\n"),
2240 reqlevel, privstr(reqlevel));
2241 }
2242 }
2243
2244 static void
2245 do_getstats(int cmd)
2246 {
2247 ike_service_t *rtn;
2248 ike_statreq_t sreq, *sreqp;
2249 ike_stats_t *sp;
2250
2251 sreq.cmd = cmd;
2252
2253 rtn = ikedoor_call((char *)&sreq, sizeof (ike_statreq_t), NULL, 0);
2254 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2255 ikeadm_err_exit(&rtn->svc_err, gettext("error getting stats"));
2256 }
2257
2258 sreqp = &rtn->svc_stats;
2259 sp = (ike_stats_t *)(sreqp + 1);
2260 print_stats(sp, sreqp->stat_len);
2261 }
2262
2263 static void
2264 do_getdefs(int cmd)
2265 {
2266 ike_service_t *rtn;
2267 ike_defreq_t dreq, *dreqp;
2268 ike_defaults_t *dp;
2269
2270 dreq.cmd = cmd;
2271
2272 rtn = ikedoor_call((char *)&dreq, sizeof (ike_defreq_t), NULL, 0);
2273 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2274 ikeadm_err_exit(&rtn->svc_err,
2275 gettext("error getting defaults"));
2276 }
2277
2278 dreqp = &rtn->svc_defaults;
2279 dp = (ike_defaults_t *)(dreqp + 1);
2280
2281 /*
2282 * Before printing each line, make sure the structure we were
2283 * given is big enough to include the fields needed.
2284 * Silently bail out of there is a version mismatch.
2285 */
2286 if (dreqp->stat_len < ((2 * sizeof (ike_defaults_t))
2287 + sizeof (ike_defreq_t)) || dreqp->version != DOORVER) {
2288 return;
2289 }
2290 do_print_defaults(dp);
2291 }
2292
2293 static void
2294 do_dump(int cmd)
2295 {
2296 char *name;
2297 ike_service_t req, *rtn;
2298 ike_dump_t *dreq, *dump;
2299
2300 switch (cmd) {
2301 case IKE_SVC_DUMP_P1S:
2302 name = gettext("phase 1 SA info");
2303 break;
2304 case IKE_SVC_DUMP_RULES:
2305 name = gettext("policy rules");
2306 break;
2307 case IKE_SVC_DUMP_PS:
2308 name = gettext("preshared keys");
2309 break;
2310 default:
2311 bail_msg(gettext("unrecognized dump command (%d)"), cmd);
2312 }
2313
2314 dreq = &req.svc_dump;
2315 dreq->cmd = cmd;
2316 dreq->dump_len = 0;
2317 dreq->dump_next = 0;
2318 do {
2319 rtn = ikedoor_call((char *)&req, sizeof (ike_dump_t),
2320 NULL, 0);
2321 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2322 if (rtn && (rtn->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
2323 /* no entries to print */
2324 break;
2325 }
2326 ikeadm_err_exit(&rtn->svc_err,
2327 gettext("error getting %s"), name);
2328 }
2329 dump = &rtn->svc_dump;
2330
2331 switch (cmd) {
2332 case IKE_SVC_DUMP_P1S:
2333 print_p1((ike_p1_sa_t *)(dump + 1));
2334 break;
2335 case IKE_SVC_DUMP_RULES:
2336 print_rule((ike_rule_t *)(dump + 1));
2337 break;
2338 case IKE_SVC_DUMP_PS:
2339 print_ps((ike_ps_t *)(dump + 1));
2340 break;
2341 }
2342
2343 dreq->dump_next = dump->dump_next;
2344
2345 (void) munmap((char *)rtn, dump->dump_len);
2346
2347 } while (dreq->dump_next);
2348
2349 (void) printf(gettext("\nCompleted dump of %s\n"), name);
2350 }
2351
2352 static void
2353 do_getdel_doorcall(int cmd, int idlen, int idtype, char *idp, char *name)
2354 {
2355 int totallen;
2356 char *p;
2357 ike_service_t *reqp, *rtnp;
2358 ike_get_t *getp;
2359 boolean_t getcmd;
2360
2361 getcmd = ((cmd == IKE_SVC_GET_P1) || (cmd == IKE_SVC_GET_RULE) ||
2362 (cmd == IKE_SVC_GET_PS));
2363
2364 /*
2365 * WARNING: to avoid being redundant, this code takes advantage
2366 * of the fact that the ike_get_t and ike_del_t structures are
2367 * identical (only the field names differ, their function and
2368 * size are the same). If for some reason those structures
2369 * change, this code will need to be re-written to accomodate
2370 * that difference.
2371 */
2372 totallen = sizeof (ike_get_t) + idlen;
2373 if ((reqp = (ike_service_t *)malloc(totallen)) == NULL)
2374 Bail("malloc(id)");
2375
2376 getp = &reqp->svc_get;
2377 getp->cmd = cmd;
2378 getp->get_len = totallen;
2379 getp->get_idtype = idtype;
2380 p = (char *)(getp + 1);
2381
2382 (void) memcpy(p, idp, idlen);
2383
2384 rtnp = ikedoor_call((char *)reqp, totallen, NULL, 0);
2385 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
2386 if (rtnp && (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
2387 message(gettext("Could not find requested %s."), name);
2388 } else {
2389 ikeadm_err_msg(&rtnp->svc_err, gettext("error %s %s"),
2390 (getcmd) ? gettext("getting") : gettext("deleting"),
2391 name);
2392 }
2393 free(reqp);
2394 return;
2395 }
2396 getp = &rtnp->svc_get;
2397
2398 if (getcmd) {
2399 switch (cmd) {
2400 case IKE_SVC_GET_P1:
2401 print_p1((ike_p1_sa_t *)(getp + 1));
2402 break;
2403 case IKE_SVC_GET_PS:
2404 print_ps((ike_ps_t *)(getp + 1));
2405 break;
2406 case IKE_SVC_GET_RULE:
2407 print_rule((ike_rule_t *)(getp + 1));
2408 break;
2409 }
2410 } else {
2411 message(gettext("Successfully deleted selected %s."), name);
2412 }
2413
2414 (void) munmap((char *)rtnp, getp->get_len);
2415 free(reqp);
2416 }
2417
2418 static void
2419 do_getdel(int cmd, int argc, char **argv)
2420 {
2421 int idlen, idtype = 0, i, j;
2422 int bytelen1, bytelen2;
2423 char *name, *idp, *p, *p1, *p2;
2424 ike_addr_pr_t apr;
2425 ike_cky_pr_t cpr;
2426 sadb_ident_t *sid1p, *sid2p;
2427 struct hostent *he1p, *he2p;
2428 char label[MAX_LABEL_LEN];
2429
2430 if ((argc < 1) || (argv[0] == NULL)) {
2431 Bail("not enough identification info");
2432 }
2433
2434 switch (cmd) {
2435 case IKE_SVC_GET_P1:
2436 case IKE_SVC_DEL_P1:
2437 name = gettext("phase 1 SA");
2438 /*
2439 * The first token must either be an address (or hostname)
2440 * or a cookie. We require cookies to be entered as hex
2441 * numbers, beginning with 0x; so if our token starts with
2442 * that, it's a cookie.
2443 */
2444 if (strncmp(argv[0], "0x", 2) == 0) {
2445 if (parse_cky_pr(argc, argv, &cpr) >= 0) {
2446 idtype = IKE_ID_CKY_PAIR;
2447 idlen = sizeof (ike_cky_pr_t);
2448 idp = (char *)&cpr;
2449 }
2450 } else {
2451 if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) {
2452 idtype = IKE_ID_ADDR_PAIR;
2453 idlen = sizeof (ike_addr_pr_t);
2454 }
2455 }
2456 break;
2457
2458 case IKE_SVC_GET_RULE:
2459 case IKE_SVC_DEL_RULE:
2460 name = gettext("policy rule");
2461 if (parse_label(argc, argv, label) >= 0) {
2462 idtype = IKE_ID_LABEL;
2463 idlen = MAX_LABEL_LEN;
2464 idp = label;
2465 }
2466 break;
2467
2468 case IKE_SVC_GET_PS:
2469 case IKE_SVC_DEL_PS:
2470 name = gettext("preshared key");
2471 /*
2472 * The first token must either be an address or an ident
2473 * type. Check for an ident type to determine which it is.
2474 */
2475 if (parse_idtype(argv[0], NULL) >= 0) {
2476 if (parse_ident_pr(argc, argv, &sid1p, &sid2p) >= 0) {
2477 idtype = IKE_ID_IDENT_PAIR;
2478 idlen = SADB_64TO8(sid1p->sadb_ident_len) +
2479 SADB_64TO8(sid2p->sadb_ident_len);
2480 }
2481 } else {
2482 if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) {
2483 idtype = IKE_ID_ADDR_PAIR;
2484 idlen = sizeof (ike_addr_pr_t);
2485 }
2486 }
2487 break;
2488
2489 default:
2490 bail_msg(gettext("unrecognized get/del command (%d)"), cmd);
2491 }
2492
2493 switch (idtype) {
2494 case IKE_ID_ADDR_PAIR:
2495 /*
2496 * we might have exploding addrs here; do every possible
2497 * combination.
2498 */
2499 i = 0;
2500 j = 0;
2501 while ((p1 = he1p->h_addr_list[i++]) != NULL) {
2502 headdr2sa(p1, &apr.loc_addr, he1p->h_length);
2503
2504 while ((p2 = he2p->h_addr_list[j++]) != NULL) {
2505 headdr2sa(p2, &apr.rem_addr, he2p->h_length);
2506 do_getdel_doorcall(cmd, idlen, idtype,
2507 (char *)&apr, name);
2508 }
2509 }
2510 FREE_HE(he1p);
2511 FREE_HE(he2p);
2512 break;
2513
2514 case IKE_ID_IDENT_PAIR:
2515 bytelen1 = SADB_64TO8(sid1p->sadb_ident_len);
2516 bytelen2 = SADB_64TO8(sid2p->sadb_ident_len);
2517 if (idlen != bytelen1 + bytelen2)
2518 Bail("ident syntax error");
2519 idp = p = (char *)malloc(idlen);
2520 if (p == NULL)
2521 Bail("malloc(id)");
2522 (void) memcpy(p, (char *)sid1p, bytelen1);
2523 p += bytelen1;
2524 (void) memcpy(p, (char *)sid2p, bytelen2);
2525 do_getdel_doorcall(cmd, idlen, idtype, idp, name);
2526 free(idp);
2527 free(sid1p);
2528 free(sid2p);
2529 break;
2530
2531 case IKE_ID_CKY_PAIR:
2532 case IKE_ID_LABEL:
2533 do_getdel_doorcall(cmd, idlen, idtype, idp, name);
2534 break;
2535
2536 case 0:
2537 default:
2538 bail_msg(gettext("invalid %s identification\n"), name);
2539 }
2540 }
2541
2542 /*
2543 * Copy source into target, inserting an escape character ('\') before
2544 * any quotes that appear. Return true on success, false on failure.
2545 */
2546 static boolean_t
2547 escapequotes(char *target, char *source, int tlen)
2548 {
2549 int s, t, len = strlen(source) + 1;
2550
2551 if (tlen < len)
2552 return (B_FALSE);
2553
2554 for (s = 0, t = 0; s < len && t < tlen; s++) {
2555 if (source[s] == '\"')
2556 target[t++] = '\\';
2557 target[t++] = source[s];
2558 }
2559
2560 if ((t == tlen) && (s < len))
2561 return (B_FALSE);
2562
2563 return (B_TRUE);
2564 }
2565
2566 /*
2567 * Return true if the arg following the given keyword should
2568 * be in quotes (i.e. is a string), false if not.
2569 */
2570 static boolean_t
2571 quotedfield(char *keywd)
2572 {
2573 if ((strncmp(keywd, "label", strlen("label") + 1) == 0) ||
2574 (strncmp(keywd, "local_id", strlen("local_id") + 1) == 0) ||
2575 (strncmp(keywd, "remote_id", strlen("remote_id") + 1) == 0))
2576 return (B_TRUE);
2577
2578 return (B_FALSE);
2579 }
2580
2581 static void
2582 do_new(int cmd, int argc, char **argv)
2583 {
2584 ike_service_t *rtn;
2585 ike_new_t new, *newp = NULL;
2586 door_desc_t desc, *descp = NULL;
2587 int i, fd, ndesc = 0, buflen;
2588 char *name, tmpfilepath[32];
2589 FILE *tmpfile;
2590
2591 switch (cmd) {
2592 case IKE_SVC_NEW_PS:
2593 name = gettext("preshared key");
2594 break;
2595 case IKE_SVC_NEW_RULE:
2596 name = gettext("policy rule");
2597 break;
2598 default:
2599 bail_msg(gettext("unrecognized new command (%d)"), cmd);
2600 }
2601
2602 if (argc == 1) {
2603 /* We've been given a file to read from */
2604 fd = open(argv[0], O_RDONLY);
2605 if (fd < 0)
2606 Bail("open source file");
2607
2608 desc.d_data.d_desc.d_descriptor = fd;
2609 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
2610 descp = &desc;
2611 ndesc = 1;
2612
2613 new.cmd = cmd;
2614 new.new_len = 0;
2615 newp = &new;
2616 buflen = sizeof (ike_new_t);
2617
2618 } else if ((argc > 1) && (cmd == IKE_SVC_NEW_PS)) {
2619 /*
2620 * This is an alternative to using the tmpfile method
2621 * for preshared keys. It means we're duplicating the
2622 * parsing effort that happens in readps.c; but it
2623 * does avoid having the key sitting in a file.
2624 */
2625 ike_ps_t *psp;
2626 int pslen;
2627
2628 /*
2629 * must be in interactive mode; don't want keys in
2630 * the process args.
2631 */
2632 if (!interactive)
2633 Bail("Must be in interactive mode to add key info.");
2634 if (parse_ps(argc, argv, &psp, &pslen) < 0) {
2635 errno = 0;
2636 Bail("invalid preshared key definition");
2637 }
2638 newp = malloc(sizeof (ike_new_t) + pslen);
2639 if (newp == NULL)
2640 Bail("alloc pskey");
2641 newp->cmd = cmd;
2642 newp->new_len = sizeof (ike_new_t) + pslen;
2643 (void) memcpy((char *)(newp + 1), psp, pslen);
2644 buflen = newp->new_len;
2645 /* parse_ps allocated the ike_ps_t buffer; free it now */
2646 free(psp);
2647
2648 } else if ((argc > 1) && (cmd == IKE_SVC_NEW_RULE)) {
2649 /*
2650 * We've been given the item in argv. However, parsing
2651 * rules can get more than a little messy, and in.iked
2652 * already has a great parser for this stuff! So don't
2653 * fool around with trying to do the parsing here. Just
2654 * write it out to a tempfile, and send the fd to in.iked.
2655 *
2656 * We could conceivably do this for preshared keys,
2657 * rather than duplicating the parsing effort; but that
2658 * would mean the key would be written out to a file,
2659 * which isn't such a good idea.
2660 */
2661 boolean_t doquotes = B_FALSE;
2662 int rtn;
2663
2664 if ((argv[0][0] != '{') ||
2665 (argv[argc - 1][strlen(argv[argc - 1]) - 1] != '}'))
2666 bail_msg(gettext("improperly formatted %s"), name);
2667
2668 /* attempt to use a fairly unpredictable file name... */
2669 (void) sprintf(tmpfilepath, "/var/run/%x", (int)gethrtime());
2670 fd = open(tmpfilepath, O_RDWR | O_CREAT | O_EXCL,
2671 S_IRUSR | S_IWUSR);
2672 if (fd < 0)
2673 Bail("cannot open tmpfile");
2674
2675 /* and make it inaccessible asap */
2676 if (unlink(tmpfilepath) < 0) {
2677 (void) close(fd);
2678 Bail("tmpfile error");
2679 }
2680
2681 tmpfile = fdopen(fd, "w");
2682 if (tmpfile == NULL) {
2683 (void) close(fd);
2684 Bail("cannot write to tmpfile");
2685 }
2686
2687 for (i = 0; i < argc; i++) {
2688 /*
2689 * We have to do some gyrations with our string here,
2690 * to properly handle quotes. There are two issues:
2691 * - some of the fields of a rule may have embedded
2692 * whitespace, and thus must be quoted on the cmd
2693 * line. The shell removes the quotes, and gives
2694 * us a single argv string; but we need to put the
2695 * quotes back in when we write the string out to
2696 * file. The doquotes boolean is set when we
2697 * process a keyword which will be followed by a
2698 * string value (so the NEXT argv element will be
2699 * quoted).
2700 * - there might be a quote character in a field,
2701 * that was escaped on the cmdline. The shell
2702 * removes the escape char, and leaves the quote
2703 * in the string it gives us. We need to put the
2704 * escape char back in before writing to file.
2705 */
2706 char field[MAXLINESIZE];
2707 if (!escapequotes(field, argv[i], MAXLINESIZE))
2708 Bail("write to tmpfile failed (arg too big)");
2709 if (doquotes) {
2710 rtn = fprintf(tmpfile, "\"%s\"\n", field);
2711 doquotes = B_FALSE;
2712 } else {
2713 rtn = fprintf(tmpfile, "%s\n", field);
2714 }
2715 if (rtn < 0)
2716 Bail("write to tmpfile failed");
2717 /*
2718 * check if this is a keyword identifying
2719 * a field that needs to be quoted.
2720 */
2721 doquotes = quotedfield(argv[i]);
2722 }
2723 if (fflush(tmpfile) == EOF)
2724 Bail("write to tmpfile failed");
2725 /* rewind so that the daemon will get the beginning */
2726 rewind(tmpfile);
2727
2728 desc.d_data.d_desc.d_descriptor = fd;
2729 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
2730 descp = &desc;
2731 ndesc = 1;
2732
2733 new.cmd = cmd;
2734 new.new_len = 0;
2735 newp = &new;
2736 buflen = sizeof (ike_new_t);
2737
2738 } else {
2739 /* not enough information! */
2740 bail_msg(gettext("missing %s description or file name"), name);
2741 }
2742
2743 rtn = ikedoor_call((char *)newp, buflen, descp, ndesc);
2744
2745 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2746 ikeadm_err_msg(&rtn->svc_err,
2747 gettext("error creating new %s"), name);
2748 } else {
2749 message(gettext("Successfully created new %s."), name);
2750 }
2751 }
2752
2753 static void
2754 do_flush(int cmd)
2755 {
2756 ike_service_t *rtnp;
2757 ike_flush_t flush;
2758
2759 if (cmd != IKE_SVC_FLUSH_P1S) {
2760 bail_msg(gettext("unrecognized flush command (%d)."), cmd);
2761 }
2762
2763 flush.cmd = cmd;
2764
2765 rtnp = ikedoor_call((char *)&flush, sizeof (ike_flush_t), NULL, 0);
2766 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
2767 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush"));
2768 }
2769 message(gettext("Successfully flushed P1 SAs."));
2770 }
2771
2772 static void
2773 do_rw(int cmd, int argc, char **argv)
2774 {
2775 ike_service_t *rtnp;
2776 ike_rw_t rw;
2777 door_desc_t desc, *descp = NULL;
2778 int oflag, omode, fd, ndesc = 0;
2779 char *op, *obj = NULL;
2780 boolean_t writing = B_FALSE;
2781
2782 switch (cmd) {
2783 case IKE_SVC_READ_PS:
2784 obj = gettext("preshared key");
2785 /* FALLTHRU */
2786 case IKE_SVC_READ_RULES:
2787 if (obj == NULL)
2788 obj = gettext("policy rule");
2789 op = gettext("read");
2790 oflag = O_RDONLY;
2791 omode = 0;
2792 break;
2793
2794 case IKE_SVC_WRITE_PS:
2795 obj = gettext("preshared key");
2796 /* FALLTHRU */
2797 case IKE_SVC_WRITE_RULES:
2798 if (obj == NULL)
2799 obj = gettext("policy rule");
2800 op = gettext("write");
2801 oflag = O_RDWR | O_CREAT | O_EXCL;
2802 omode = S_IRUSR | S_IWUSR;
2803
2804 /* for write commands, dest location must be specified */
2805 if (argc < 1) {
2806 bail_msg(gettext("destination location required "
2807 "to write %ss"), obj);
2808 }
2809 writing = B_TRUE;
2810 break;
2811
2812 default:
2813 bail_msg(gettext("unrecognized read/write command (%d)."), cmd);
2814 }
2815
2816 rw.cmd = cmd;
2817
2818 if (argc >= 1) {
2819 rw.rw_loc = IKE_RW_LOC_USER_SPEC;
2820 fd = open(argv[0], oflag, omode);
2821 if (fd < 0)
2822 Bail("open user-specified file");
2823
2824 desc.d_data.d_desc.d_descriptor = fd;
2825 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
2826 descp = &desc;
2827 ndesc = 1;
2828 } else {
2829 rw.rw_loc = IKE_RW_LOC_DEFAULT;
2830 }
2831
2832 rtnp = ikedoor_call((char *)&rw, sizeof (ike_rw_t), descp, ndesc);
2833 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
2834 /*
2835 * Need to remove the target file in the
2836 * case of a failed write command.
2837 */
2838 if (writing) {
2839 /*
2840 * argv[0] must be valid if we're writing; we
2841 * exit before setting this boolean if not.
2842 */
2843 (void) unlink(argv[0]);
2844 (void) close(fd);
2845
2846 if ((rtnp != NULL) &&
2847 (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
2848 message(gettext("No %s information to write."),
2849 obj);
2850 return;
2851 }
2852 }
2853 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing %s"), op);
2854 }
2855 message(gettext("Completed %s of %s configuration information."),
2856 op, obj);
2857 }
2858
2859 static void
2860 do_rbdump()
2861 {
2862 ike_cmd_t req;
2863 ike_service_t *rtnp;
2864
2865 req.cmd = IKE_SVC_DBG_RBDUMP;
2866
2867 rtnp = ikedoor_call((char *)&req, sizeof (ike_cmd_t), NULL, 0);
2868 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
2869 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush"));
2870 }
2871 message(gettext("Successfully dumped rulebase; check iked dbg"));
2872 }
2873
2874 #define REQ_ARG_CNT 1
2875
2876 /*ARGSUSED*/
2877 static void
2878 parseit(int argc, char **argv, char *notused, boolean_t notused_either)
2879 {
2880 int cmd, cmd_obj_args = 1;
2881 char *cmdstr, *objstr;
2882
2883 if (interactive) {
2884 if (argc == 0)
2885 return;
2886 }
2887
2888 if (argc < REQ_ARG_CNT) {
2889 usage();
2890 }
2891
2892 cmdstr = argv[0];
2893 if (argc > REQ_ARG_CNT) {
2894 cmd_obj_args++;
2895 objstr = argv[1];
2896 } else {
2897 objstr = NULL;
2898 }
2899 cmd = parsecmd(cmdstr, objstr);
2900
2901 /* skip over args specifying command/object */
2902 argc -= cmd_obj_args;
2903 argv += cmd_obj_args;
2904
2905 switch (cmd) {
2906 case IKE_SVC_GET_DEFS:
2907 do_getdefs(cmd);
2908 break;
2909 case IKE_SVC_GET_DBG:
2910 case IKE_SVC_GET_PRIV:
2911 do_getvar(cmd);
2912 break;
2913 case IKE_SVC_GET_STATS:
2914 do_getstats(cmd);
2915 break;
2916 case IKE_SVC_SET_DBG:
2917 case IKE_SVC_SET_PRIV:
2918 do_setvar(cmd, argc, argv);
2919 break;
2920 case IKE_SVC_DUMP_P1S:
2921 case IKE_SVC_DUMP_RULES:
2922 case IKE_SVC_DUMP_PS:
2923 do_dump(cmd);
2924 break;
2925 case IKE_SVC_GET_P1:
2926 case IKE_SVC_GET_RULE:
2927 case IKE_SVC_GET_PS:
2928 case IKE_SVC_DEL_P1:
2929 case IKE_SVC_DEL_RULE:
2930 case IKE_SVC_DEL_PS:
2931 do_getdel(cmd, argc, argv);
2932 break;
2933 case IKE_SVC_NEW_RULE:
2934 case IKE_SVC_NEW_PS:
2935 do_new(cmd, argc, argv);
2936 break;
2937 case IKE_SVC_FLUSH_P1S:
2938 do_flush(cmd);
2939 break;
2940 case IKE_SVC_READ_RULES:
2941 case IKE_SVC_READ_PS:
2942 case IKE_SVC_WRITE_RULES:
2943 case IKE_SVC_WRITE_PS:
2944 do_rw(cmd, argc, argv);
2945 break;
2946 case IKEADM_HELP_GENERAL:
2947 print_help();
2948 break;
2949 case IKEADM_HELP_GET:
2950 print_get_help();
2951 break;
2952 case IKEADM_HELP_SET:
2953 print_set_help();
2954 break;
2955 case IKEADM_HELP_ADD:
2956 print_add_help();
2957 break;
2958 case IKEADM_HELP_DEL:
2959 print_del_help();
2960 break;
2961 case IKEADM_HELP_DUMP:
2962 print_dump_help();
2963 break;
2964 case IKEADM_HELP_FLUSH:
2965 print_flush_help();
2966 break;
2967 case IKEADM_HELP_READ:
2968 print_read_help();
2969 break;
2970 case IKEADM_HELP_WRITE:
2971 print_write_help();
2972 break;
2973 case IKEADM_HELP_HELP:
2974 print_help_help();
2975 break;
2976 case IKEADM_EXIT:
2977 if (interactive)
2978 exit(0);
2979 break;
2980 case IKE_SVC_DBG_RBDUMP:
2981 do_rbdump();
2982 break;
2983 case IKE_SVC_ERROR:
2984 usage();
2985 default:
2986 exit(0);
2987 }
2988 }
2989
2990 int
2991 main(int argc, char **argv)
2992 {
2993 char ch;
2994
2995 (void) setlocale(LC_ALL, "");
2996 #if !defined(TEXT_DOMAIN)
2997 #define TEXT_DOMAIN "SYS_TEST"
2998 #endif
2999 (void) textdomain(TEXT_DOMAIN);
3000
3001 while ((ch = getopt(argc, argv, "hpn")) != EOF) {
3002 switch (ch) {
3003 case 'h':
3004 print_help();
3005 return (0);
3006 case 'p':
3007 pflag = B_TRUE;
3008 break;
3009 case 'n':
3010 nflag = B_TRUE;
3011 break;
3012 default:
3013 usage();
3014 }
3015 }
3016 argc -= optind;
3017 argv += optind;
3018
3019 if (open_door() < 0) {
3020 (void) fprintf(stderr,
3021 gettext("Unable to communicate with in.iked\n"));
3022 Bail("open_door failed");
3023 }
3024
3025 if (*argv == NULL) {
3026 /* no cmd-line args, do interactive mode */
3027 do_interactive(stdin, NULL, "ikeadm> ", NULL, parseit);
3028 }
3029
3030 parseit(argc, argv, NULL, B_FALSE);
3031
3032 return (0);
3033 }