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