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