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