ikeadm.c revision 349233ace357d403f2fb770a150c3150994ac8ab
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <unistd.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <libintl.h>
#include <locale.h>
#include <ctype.h>
#include <time.h>
#include <sys/sysmacros.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#include <assert.h>
#include <door.h>
#include <setjmp.h>
#include <ipsec_util.h>
#include <ikedoor.h>
static int doorfd = -1;
/*
* These are additional return values for the command line parsing
* function (parsecmd()). They are specific to this utility, but
* need to share the same space as the IKE_SVC_* defs, without conflicts.
* So they're defined relative to the end of that range.
*/
static void
command_complete(int s)
{
if (interactive) {
} else {
exit(s);
}
}
static void
usage()
{
if (!interactive) {
"ikeadm [ -hnp ] cmd obj [cmd-specific options]\n"));
}
command_complete(1);
}
static void
{
(void) printf(
"\tget debug|priv|stats|p1|rule|preshared|defaults [%s]\n",
gettext("identifier"));
(void) printf("\tset debug %s [%s]\n",
(void) printf("\tadd rule|preshared {%s}|%s\n",
(void) printf("\tdump p1|rule|preshared\n");
(void) printf("\tflush p1\n");
(void) printf(
"\thelp [get|set|add|del|dump|flush|read|write|help]\n");
(void) printf("\n");
command_complete(0);
}
static void
{
(void) printf(
gettext("This command gets information from in.iked.\n\n"));
(void) printf("\tdebug\t\t");
(void) printf("\tpriv\t\t");
(void) printf("\tstats\t\t");
(void) printf("\tp1\t\t");
(void) printf("\trule\t\t");
(void) printf("\tpreshared\t");
(void) printf("\n");
command_complete(0);
}
static void
{
(void) printf("\tdebug\t\t");
(void) printf("\tpriv\t\t");
(void) printf(
gettext("change the privilege level (may only be lowered)\n"));
(void) printf("\n");
command_complete(0);
}
static void
{
(void) printf(
gettext("This command adds items to in.iked's tables.\n\n"));
(void) printf("\trule\t\t");
(void) printf("\tpreshared\t");
(void) printf(
gettext("\nObjects may be entered on the command-line, as a\n"));
(void) printf(
gettext("series of keywords and tokens contained in curly\n"));
(void) printf(
gettext("braces ('{', '}'); or the name of a file containing\n"));
(void) printf(
gettext("For security purposes, preshared keys may only be\n"));
(void) printf(
gettext("entered on the command-line if ikeadm is running in\n"));
(void) printf("\n");
command_complete(0);
}
static void
{
(void) printf(
gettext("This command deletes an item from in.iked's tables.\n\n"));
(void) printf("\tp1\t\t");
(void) printf("\trule\t\t");
(void) printf("\tpreshared\t");
(void) printf("\n");
command_complete(0);
}
static void
{
(void) printf(
gettext("This command dumps one of in.iked's tables.\n\n"));
(void) printf("\tp1\t\t");
(void) printf("\trule\t\t");
(void) printf("\tpreshared\t");
(void) printf("\n");
command_complete(0);
}
static void
{
(void) printf(
gettext("This command clears one of in.iked's tables.\n\n"));
(void) printf("\tp1\t\t");
(void) printf("\n");
command_complete(0);
}
static void
{
(void) printf(
gettext("This command reads a new configuration file into\n"));
(void) printf(
gettext("in.iked, discarding the old configuration info.\n\n"));
(void) printf("\trule\t\t");
(void) printf("\tpreshared\t");
(void) printf(
gettext("A filename may be provided to specify a source file\n"));
(void) printf("\n");
command_complete(0);
}
static void
{
(void) printf(
gettext("This command writes in.iked's current configuration\n"));
(void) printf("\trule\t\t");
(void) printf("\tpreshared\t");
(void) printf(
gettext("A filename must be provided to specify the file to\n"));
(void) printf("\n");
command_complete(0);
}
static void
{
(void) printf(
gettext("This command provides information about commands.\n\n"));
(void) printf(
gettext("The 'help' command alone provides a list of valid\n"));
(void) printf(
gettext("commands, along with the valid objects for each.\n"));
(void) printf(
gettext("'help' followed by a valid command name provides\n"));
(void) printf("\n");
command_complete(0);
}
/*PRINTFLIKE1*/
static void
{
}
static int
open_door(void)
{
if (doorfd >= 0)
return (doorfd);
}
static ike_service_t *
{
int retries = 0;
(open_door() >= 0)))
goto retry;
gettext("Unable to communicate with in.iked\n"));
Bail("door_call failed");
}
/* callers assume passed fds will be closed no matter what */
}
/* LINTED E_BAD_PTR_CAST_ALIGN */
}
/*
* Parsing functions
*/
/* stolen from ipseckey.c, with a second tier added */
static int
{
#define MAXOBJS 10
struct objtbl {
char *obj;
int token;
};
static struct cmdtbl {
char *cmd;
int null_obj_token;
} table[] = {
{"get", IKE_SVC_ERROR, {
{"debug", IKE_SVC_GET_DBG},
{"priv", IKE_SVC_GET_PRIV},
{"stats", IKE_SVC_GET_STATS},
{"p1", IKE_SVC_GET_P1},
{"rule", IKE_SVC_GET_RULE},
{"preshared", IKE_SVC_GET_PS},
{"defaults", IKE_SVC_GET_DEFS},
{NULL, IKE_SVC_ERROR},
}
},
{"set", IKE_SVC_ERROR, {
{"debug", IKE_SVC_SET_DBG},
{"priv", IKE_SVC_SET_PRIV},
{NULL, IKE_SVC_ERROR},
}
},
{"add", IKE_SVC_ERROR, {
{"rule", IKE_SVC_NEW_RULE},
{"preshared", IKE_SVC_NEW_PS},
{NULL, IKE_SVC_ERROR},
}
},
{"del", IKE_SVC_ERROR, {
{"p1", IKE_SVC_DEL_P1},
{"rule", IKE_SVC_DEL_RULE},
{"preshared", IKE_SVC_DEL_PS},
{NULL, IKE_SVC_ERROR},
}
},
{"dump", IKE_SVC_ERROR, {
{"p1", IKE_SVC_DUMP_P1S},
{"rule", IKE_SVC_DUMP_RULES},
{"preshared", IKE_SVC_DUMP_PS},
{NULL, IKE_SVC_ERROR},
}
},
{"flush", IKE_SVC_ERROR, {
{"p1", IKE_SVC_FLUSH_P1S},
{NULL, IKE_SVC_ERROR},
}
},
{"read", IKE_SVC_ERROR, {
{"rule", IKE_SVC_READ_RULES},
{"preshared", IKE_SVC_READ_PS},
{NULL, IKE_SVC_ERROR},
}
},
{"write", IKE_SVC_ERROR, {
{"rule", IKE_SVC_WRITE_RULES},
{"preshared", IKE_SVC_WRITE_PS},
{NULL, IKE_SVC_ERROR},
}
},
{"help", IKEADM_HELP_GENERAL, {
{"get", IKEADM_HELP_GET},
{"set", IKEADM_HELP_SET},
{"add", IKEADM_HELP_ADD},
{"del", IKEADM_HELP_DEL},
{"dump", IKEADM_HELP_DUMP},
{"flush", IKEADM_HELP_FLUSH},
{"read", IKEADM_HELP_READ},
{"write", IKEADM_HELP_WRITE},
{"help", IKEADM_HELP_HELP},
{NULL, IKE_SVC_ERROR},
}
},
{"exit", IKEADM_EXIT, {
{NULL, IKE_SVC_ERROR},
}
},
{"quit", IKEADM_EXIT, {
{NULL, IKE_SVC_ERROR},
}
},
{"dbg", IKE_SVC_ERROR, {
{"rbdump", IKE_SVC_DBG_RBDUMP},
{NULL, IKE_SVC_ERROR},
}
},
{NULL, IKE_SVC_ERROR, {
{NULL, IKE_SVC_ERROR},
}
},
};
return (IKE_SVC_ERROR);
}
ct++;
}
return (ct->null_obj_token);
}
ot++;
}
/*
* Parsing functions:
* Parse command-line identification info. All return -1 on failure,
* or the number of cmd-line args "consumed" on success (though argc
* and argv params are not actually modified).
*/
static int
{
return (-1);
return (-1);
return (1);
}
/*
* Parse an address off the command line. In the hpp param, either
* return a hostent pointer (caller frees) or a pointer to a dummy_he_t
* (must also be freed by the caller; both cases are handled by the
* macro FREE_HE). The new getipnodebyname() call does the Right Thing
* (TM), even with raw addresses (colon-separated IPv6 or dotted decimal
* IPv4).
* (mostly stolen from ipseckey.c, though some tweaks were made
* to better serve our purposes here.)
*/
typedef struct {
char *addtl[2];
} dummy_he_t;
static int
{
int hp_errno;
char *addr1;
return (-1);
if (!nflag) {
/*
* Try name->address first. Assume AF_INET6, and
* get IPV4s, plus IPv6s iff IPv6 is configured.
*/
&hp_errno);
} else {
/*
* Try a normal address conversion only. malloc a
* dummy_he_t to construct a fake hostent. Caller
* will know to free this one using free_he().
*/
} else {
}
}
return (-1);
}
return (1);
}
/*
* Free a dummy_he_t structure that was malloc'd in parse_addr().
* Unfortunately, callers of parse_addr don't want to know about
* dummy_he_t structs, so all they have is a pointer to the struct
* hostent; so that's what's passed in. To manage this, we make
* the assumption that the struct hostent is the first field in
* the dummy_he_t, and therefore a pointer to it is a pointer to
* the dummy_he_t.
*/
static void
{
if (p->addtl[0])
if (p->addtl[1])
free(p);
}
#define FREE_HE(x) \
if (nflag) \
free_he(x); \
else \
freehostent(x)
static void
{
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
/* LINTED E_BAD_PTR_CAST_ALIGN */
/* LINTED E_BAD_PTR_CAST_ALIGN */
} else {
sizeof (struct in6_addr));
}
} else {
}
}
/*
* The possible ident-type keywords that might be used on the command
* line. This is a superset of the ones supported by ipseckey, those
* in the ike config file, and those in ike.preshared.
*/
static keywdtab_t idtypes[] = {
/* ip, ipv4, and ipv6 are valid for preshared keys... */
{SADB_IDENTTYPE_RESERVED, "ip"},
{SADB_IDENTTYPE_RESERVED, "ipv4"},
{SADB_IDENTTYPE_RESERVED, "ipv6"},
{SADB_IDENTTYPE_PREFIX, "prefix"},
{SADB_IDENTTYPE_PREFIX, "ipv4-prefix"},
{SADB_IDENTTYPE_PREFIX, "ipv6-prefix"},
{SADB_IDENTTYPE_PREFIX, "subnet"},
{SADB_IDENTTYPE_PREFIX, "subnetv4"},
{SADB_IDENTTYPE_PREFIX, "subnetv6"},
{SADB_IDENTTYPE_FQDN, "fqdn"},
{SADB_IDENTTYPE_FQDN, "dns"},
{SADB_IDENTTYPE_FQDN, "domain"},
{SADB_IDENTTYPE_FQDN, "domainname"},
{SADB_IDENTTYPE_USER_FQDN, "user_fqdn"},
{SADB_IDENTTYPE_USER_FQDN, "mbox"},
{SADB_IDENTTYPE_USER_FQDN, "mailbox"},
{SADB_X_IDENTTYPE_DN, "dn"},
{SADB_X_IDENTTYPE_DN, "asn1dn"},
{SADB_X_IDENTTYPE_GN, "gn"},
{SADB_X_IDENTTYPE_GN, "asn1gn"},
{SADB_X_IDENTTYPE_ADDR_RANGE, "ipv4-range"},
{SADB_X_IDENTTYPE_ADDR_RANGE, "ipv6-range"},
{SADB_X_IDENTTYPE_ADDR_RANGE, "rangev4"},
{SADB_X_IDENTTYPE_ADDR_RANGE, "rangev6"},
{SADB_X_IDENTTYPE_KEY_ID, "keyid"},
{NULL, 0}
};
static int
{
return (-1);
return (1);
}
}
return (-1);
}
/*
* The sadb_ident_t is malloc'd, since its length varies;
* so the caller must free() it when done with the data.
*/
static int
{
return (-1);
Bail("parsing identity");
return (-1);
}
idp->sadb_ident_reserved = 0;
idp->sadb_ident_id = 0;
/* now copy in identity param */
alloclen - (sizeof (sadb_ident_t)));
return (++consumed);
}
static int
{
return (-1);
errno = 0;
if (errno != 0) {
return (-1);
}
return (1);
}
static int
{
return (-1);
}
return (-1);
}
return (consumed);
}
/*
* The sadb_ident_ts are malloc'd, since their length varies;
* so the caller must free() them when done with the data.
*/
static int
{
return (-1);
}
return (-1);
}
return (consumed);
}
static int
{
return (-1);
}
return (-1);
}
return (consumed);
}
/*
* Preshared key field types...used for parsing preshared keys that
* have been entered on the command line. The code to parse preshared
* keys (parse_ps, parse_key, parse_psfldid, parse_ikmtype, ...) is
* mostly duplicated from in.iked's readps.c.
*/
#define PSFLD_LOCID 1
#define PSFLD_LOCIDTYPE 2
#define PSFLD_REMID 3
#define PSFLD_REMIDTYPE 4
#define PSFLD_MODE 5
#define PSFLD_KEY 6
static keywdtab_t psfldtypes[] = {
{PSFLD_LOCID, "localid"},
{PSFLD_LOCIDTYPE, "localidtype"},
{PSFLD_REMID, "remoteid"},
{PSFLD_REMIDTYPE, "remoteidtype"},
{PSFLD_MODE, "ike_mode"},
{PSFLD_KEY, "key"},
{NULL, 0}
};
static int
{
return (-1);
return (1);
}
}
return (-1);
}
static keywdtab_t ikemodes[] = {
{IKE_XCHG_IDENTITY_PROTECT, "main"},
{IKE_XCHG_AGGRESSIVE, "aggressive"},
{IKE_XCHG_IP_AND_AGGR, "both"},
{NULL, 0}
};
static int
{
return (-1);
return (1);
}
}
return (-1);
}
static uint8_t *
{
hexlen++;
if (input[i] == '\0') {
bits = 0;
} else {
/* Have /nn. */
input[i] = '\0';
return (NULL);
/* hexlen is in nibbles */
return (NULL);
/*
* Adjust hexlen down if user gave us too small of a bit
* count.
*/
}
}
/*
* Allocate. Remember, hexlen is in nibbles.
*/
return (NULL);
if (bits == 0)
else
/*
* Read in nibbles. Read in odd-numbered as shifted high.
* (e.g. 123 becomes 0x1230).
*/
return (NULL);
}
if (second)
else
break; /* out of for loop. */
keyp++;
}
/* zero the remaining bits if we're a non-octet amount. */
if (bits & 0x7)
return (keybufp);
}
/*
* the ike_ps_t struct (plus trailing data) will be allocated here,
* so it will need to be freed by the caller.
*/
static int
{
return (-1);
if (argv[c][1] != 0) {
/* no space between '{' and first token */
argv[c]++;
} else {
c++;
}
/*
* whack '}' without a space before it or parsers break.
* Remember this trailing character for later
*/
}
goto bail;
goto bail;
switch (fldid) {
case PSFLD_LOCID:
break;
case PSFLD_LOCIDTYPE:
goto bail;
break;
case PSFLD_REMID:
break;
case PSFLD_REMIDTYPE:
goto bail;
break;
case PSFLD_MODE:
goto bail;
break;
case PSFLD_KEY:
goto bail;
break;
}
}
/* Make sure the line was terminated with '}' */
if (!whacked)
goto bail;
} else if (argv[c][0] != '}') {
goto bail;
}
/*
* make sure we got all the required fields. If no idtype, assume
* ip addr; if that translation fails, we'll catch the error then.
*/
goto bail;
/* figure out the size buffer we need */
if (locidtype != SADB_IDENTTYPE_RESERVED) {
*len += a_locidtotal;
}
if (remidtype != SADB_IDENTTYPE_RESERVED) {
*len += a_remidtotal;
}
goto bail;
if (locidtype == SADB_IDENTTYPE_RESERVED) {
/*
* this is an ip address, store in the sockaddr field;
* we won't use an sadb_ident_t.
*/
psp->ps_localid_len = 0;
goto bail;
"match multiple IP addresses"));
goto bail;
}
} else {
}
if (remidtype == SADB_IDENTTYPE_RESERVED) {
/*
* this is an ip address, store in the sockaddr field;
* we won't use an sadb_ident_t.
*/
psp->ps_remoteid_len = 0;
goto bail;
"match multiple IP addresses"));
goto bail;
}
} else {
/* make sure we have at least 16-bit alignment */
if (remidlen & 0x1)
remidlen++;
}
*presharedpp = psp;
return (c);
bail:
*presharedpp = NULL;
return (-1);
}
/* stolen from libdhcputil (dhcp_inittab.c) */
static uint64_t
{
#ifdef _LITTLE_ENDIAN
#else
return (nll);
#endif
}
/*
* Printing functions
*
* A potential point of confusion here is that the ikeadm-specific string-
* producing functions do not match the ipsec_util.c versions in style: the
* ikeadm-specific functions return a string (and are named foostr), while
* the ipsec_util.c functions actually print the string to the file named
* in the second arg to the function (and are named dump_foo).
*
* The reason for this is that in the context of the ikeadm output, it
* seemed like the localization of the text would be more straightforward
* (and could more easily accomodate non-english grammar!) if more complete
* phrases were being translated, rather than a bit of a phrase followed by
* a call to dump_foo() followed by more of the phrase.
*/
static char *
{
static char rtn[MAXLINESIZE];
switch (err) {
case IKE_ERR_NO_OBJ:
return (gettext("No data returned"));
case IKE_ERR_NO_DESC:
return (gettext("No destination provided"));
case IKE_ERR_ID_INVALID:
return (gettext("Id info invalid"));
case IKE_ERR_LOC_INVALID:
return (gettext("Destination invalid"));
case IKE_ERR_CMD_INVALID:
return (gettext("Command invalid"));
case IKE_ERR_DATA_INVALID:
return (gettext("Supplied data invalid"));
case IKE_ERR_CMD_NOTSUP:
return (gettext("Unknown command"));
case IKE_ERR_REQ_INVALID:
return (gettext("Request invalid"));
case IKE_ERR_NO_PRIV:
return (gettext("Not allowed at current privilege level"));
case IKE_ERR_SYS_ERR:
return (gettext("System error"));
case IKE_ERR_DUP_IGNORED:
return (gettext("One or more duplicate entries ignored"));
default:
return (rtn);
}
}
static char *
{
static char rtn[MAXLINESIZE];
switch (bit) {
case D_CERT:
return (gettext("Certificate management"));
case D_KEY:
return (gettext("Key management"));
case D_OP:
return (gettext("Operational"));
case D_P1:
return (gettext("Phase 1 SA creation"));
case D_P2:
return (gettext("Phase 2 SA creation"));
case D_PFKEY:
return (gettext("PF_KEY interface"));
case D_POL:
return (gettext("Policy management"));
case D_PROP:
return (gettext("Proposal construction"));
case D_DOOR:
return (gettext("Door interface"));
case D_CONFIG:
return (gettext("Config file processing"));
default:
return (rtn);
}
}
static char *
{
static char rtn[MAXLINESIZE];
switch (priv) {
case IKE_PRIV_MINIMUM:
return (gettext("base privileges"));
case IKE_PRIV_MODKEYS:
return (gettext("access to preshared key information"));
case IKE_PRIV_KEYMAT:
return (gettext("access to keying material"));
default:
return (rtn);
}
}
static char *
{
static char rtn[MAXLINESIZE];
switch (xchg) {
case IKE_XCHG_NONE:
return (gettext("<unspecified>"));
case IKE_XCHG_BASE:
return (gettext("base"));
return (gettext("main mode (identity protect)"));
case IKE_XCHG_AUTH_ONLY:
return (gettext("authentication only"));
case IKE_XCHG_AGGRESSIVE:
return (gettext("aggressive mode"));
case IKE_XCHG_IP_AND_AGGR:
return (gettext("main and aggressive mode"));
case IKE_XCHG_ANY:
return (gettext("any mode"));
default:
return (rtn);
}
}
static char *
{
static char rtn[MAXLINESIZE];
switch (state) {
case IKE_SA_STATE_INIT:
return (gettext("INITIALIZING"));
case IKE_SA_STATE_SENT_SA:
return (gettext("SENT FIRST MSG (SA)"));
case IKE_SA_STATE_SENT_KE:
return (gettext("SENT SECOND MSG (KE)"));
case IKE_SA_STATE_SENT_LAST:
return (gettext("SENT FINAL MSG"));
case IKE_SA_STATE_DONE:
return (gettext("ACTIVE"));
case IKE_SA_STATE_DELETED:
return (gettext("DELETED"));
case IKE_SA_STATE_INVALID:
return (gettext("<invalid>"));
default:
return (rtn);
}
}
static char *
authmethstr(int meth)
{
static char rtn[MAXLINESIZE];
switch (meth) {
return (gettext("pre-shared key"));
case IKE_AUTH_METH_DSS_SIG:
return (gettext("DSS signatures"));
case IKE_AUTH_METH_RSA_SIG:
return (gettext("RSA signatures"));
case IKE_AUTH_METH_RSA_ENCR:
return (gettext("RSA Encryption"));
return (gettext("Revised RSA Encryption"));
default:
return (rtn);
}
}
static char *
{
static char rtn[MAXLINESIZE];
switch (prf) {
case IKE_PRF_NONE:
return (gettext("<none/unavailable>"));
case IKE_PRF_HMAC_MD5:
return ("HMAC MD5");
case IKE_PRF_HMAC_SHA1:
return ("HMAC SHA1");
case IKE_PRF_HMAC_SHA256:
return ("HMAC SHA256");
case IKE_PRF_HMAC_SHA384:
return ("HMAC SHA384");
case IKE_PRF_HMAC_SHA512:
return ("HMAC SHA512");
default:
return (rtn);
}
}
static char *
{
static char rtn[MAXLINESIZE];
switch (grp) {
case 0:
return (gettext("<unavailable>"));
case IKE_GRP_DESC_MODP_768:
return (gettext("768-bit MODP (group 1)"));
case IKE_GRP_DESC_MODP_1024:
return (gettext("1024-bit MODP (group 2)"));
case IKE_GRP_DESC_EC2N_155:
return (gettext("EC2N group on GP[2^155]"));
case IKE_GRP_DESC_EC2N_185:
return (gettext("EC2N group on GP[2^185]"));
case IKE_GRP_DESC_MODP_1536:
return (gettext("1536-bit MODP (group 5)"));
case IKE_GRP_DESC_MODP_2048:
return (gettext("2048-bit MODP (group 14)"));
case IKE_GRP_DESC_MODP_3072:
return (gettext("3072-bit MODP (group 15)"));
case IKE_GRP_DESC_MODP_4096:
return (gettext("4096-bit MODP (group 16)"));
case IKE_GRP_DESC_MODP_6144:
return (gettext("6144-bit MODP (group 17)"));
case IKE_GRP_DESC_MODP_8192:
return (gettext("8192-bit MODP (group 18)"));
default:
return (rtn);
}
}
static void
{
(void) printf(
gettext("%s Cookies: Initiator 0x%llx Responder 0x%llx\n"),
(void) printf("\n");
}
static void
{
}
static void
{
}
static void
{
if (xfp->p1xf_encr_low_bits != 0) {
} else if ((xfp->p1xf_encr_low_bits == 0) &&
(xfp->p1xf_encr_high_bits != 0)) {
/*
* High bits is a placeholder for
* negotiated algorithm strength
*/
}
} else {
"%s Phase 2 PFS is required (Oakley Group: %s)\n"),
}
if (print_lifetimes)
}
static void
int statlen)
{
/*
* make sure the stats struct we've been passed is as big
* as we expect it to be. The usage stats are at the end,
* so anything less than the size we expect won't work.
*/
if (statlen >= sizeof (ike_p1_stats_t)) {
} else {
return;
}
if (xfp->p1xf_max_kbytes != 0)
if (xfp->p1xf_max_keyuses != 0)
"%u more times.\n"), prefix,
if (xfp->p1xf_max_secs != 0) {
/*
* The SA may have expired but still exist because libike
* has not freed it yet.
*/
if (remain > 0)
"%s SA expires in %lu seconds, at %s\n"),
else
}
}
/* used to verify structure lengths... */
#define COUNTER_32BIT 4
#define COUNTER_PAIR 8
static void
{
if (statlen < COUNTER_PAIR)
return;
statlen -= COUNTER_PAIR;
}
static void
{
/*
* Don't try to break this one up; it's either all or nothing!
*/
if (errlen < sizeof (ike_p1_errors_t))
return;
}
static void
{
return;
}
case AF_INET:
break;
case AF_INET6:
break;
default:
return;
}
if (range) {
(void) printf(" - ");
nflag);
}
(void) printf("\n");
}
/*
* used to tell printing function if info should be identified
* as belonging to initiator, responder, or neither
*/
#define IS_INITIATOR 1
#define IS_RESPONDER 2
#define DONT_PRINT_INIT 3
static void
{
if (init_instr != DONT_PRINT_INIT)
else
(void) printf(":\n");
}
static void
{
switch (init_instr) {
case IS_INITIATOR:
break;
case IS_RESPONDER:
break;
case DONT_PRINT_INIT:
break;
default:
return;
}
if (canprint) {
} else {
(const unsigned char *)(idp + 1),
}
}
static void
{
int i;
for (i = 0; i < icnt; i++) {
if (i == 0)
}
for (i = 0; i < ecnt; i++) {
if (i == 0)
}
}
static void
{
ike_p1_key_t *p;
int ssize;
ssize = sizeof (ike_p1_key_t);
p = (ike_p1_key_t *)curp;
break;
}
switch (p->p1key_type) {
case IKE_KEY_PRESHARED:
stdout);
break;
case IKE_KEY_SKEYID:
stdout);
break;
case IKE_KEY_SKEYID_D:
stdout);
break;
case IKE_KEY_SKEYID_A:
stdout);
break;
case IKE_KEY_SKEYID_E:
stdout);
break;
case IKE_KEY_ENCR:
stdout);
break;
case IKE_KEY_IV:
(void) printf(
gettext("%s Initialization vector (%d bytes): "),
stdout);
break;
default:
}
(void) printf("\n");
}
}
static void
{
(void) printf("\n");
} else {
}
/*
* the stat len might be 0; but still make the call
* to print_lifetime() to pick up the xform info
*/
if (p1->p1sa_stat_len > 0) {
}
if (p1->p1sa_error_len > 0) {
}
if (p1->p1sa_localid_len > 0) {
}
if (p1->p1sa_remoteid_len > 0) {
}
if (p1->p1sa_key_len > 0) {
}
}
static void
{
(void) printf("\n");
if (ps->ps_key_len > 0) {
ps->ps_key_len);
(void) printf("\n");
}
/*
* We get *either* and address or an ident, never both. So if
* the ident is there, don't try printing an address.
*/
if (ps->ps_localid_len > 0) {
lidp = (sadb_ident_t *)
} else {
}
if (ps->ps_remoteid_len > 0) {
ridp = (sadb_ident_t *)
} else {
}
}
#define PREFIXLEN 16
static void
{
int i;
(void) printf("\n");
"GLOBL: p1_nonce_len=%u, p2_nonce_len=%u, p2_pfs=%s (group %u)\n"),
rp->rule_p2_pfs);
(void) printf(
gettext("GLOBL: p2_lifetime=%u seconds, p2_softlife=%u seconds\n"),
(void) printf(
gettext("GLOBL: p2_lifetime_kb=%u seconds,"
" p2_softlife_kb=%u seconds\n"),
if (rp->rule_locip_cnt > 0) {
}
}
if (rp->rule_remip_cnt > 0) {
}
}
}
}
if (rp->rule_xform_cnt > 0) {
}
}
}
static void
{
/*
* before printing each line, make sure the structure we were
* given is big enough to include the fields needed.
*/
if (len < COUNTER_PAIR)
return;
len -= COUNTER_PAIR;
if (len < COUNTER_PAIR)
return;
len -= COUNTER_PAIR;
if (len < COUNTER_PAIR)
return;
len -= COUNTER_PAIR;
return;
(void) printf(
gettext(" initiator fails include %u time-out(s)\n"),
return;
}
static void
{
unit, description);
}
/*
* Print out defaults used by in.iked, the argument is a buffer containing
* two ike_defaults_t's, the first contains the hard coded defaults, the second
* contains the actual values used. If these differ, then the defaults have been
* changed via a config file entry. Note that "-" indicates this default
* is not tunable.
*/
static void
{
" over-ridden on a per rule basis.\n\n"));
(void) printf("%-18s%-10s%-16s%-10s%-26s\n\n",
}
static void
print_categories(int level)
{
int mask;
if (level == 0) {
return;
}
}
(void) printf("\n");
}
/*PRINTFLIKE2*/
static void
{
} else {
}
}
/*PRINTFLIKE2*/
static void
{
gettext("<unknown error>") :
gettext("Duplicate entry") :
} else {
}
}
/*
* Command functions
*/
/*
* Exploit the fact that ike_dbg_t and ike_priv_t have identical
* formats in the following two functions.
*/
static void
{
char *varname;
switch (cmd) {
case IKE_SVC_GET_DBG:
break;
case IKE_SVC_GET_PRIV:
break;
default:
}
}
if (cmd == IKE_SVC_GET_DBG) {
(void) printf("\n");
} else {
}
}
static void
{
char *varname;
if (argc < 1)
Bail("unspecified level");
switch (cmd) {
case IKE_SVC_SET_DBG:
if (argc > 2)
Bail("Too many arguments to \"set debug\"");
if (reqlevel == 0) {
/* check for a string... */
}
break;
case IKE_SVC_SET_PRIV:
if (argc > 1)
Bail("Too many arguments to \"set priv\"");
if (reqlevel == 0) {
/* check for a string... */
}
if (reqlevel > IKE_PRIV_MAXIMUM)
break;
default:
}
if (fd < 0)
Bail("open debug file");
ndesc = 1;
}
}
(void) printf(
gettext("Successfully changed %s level from 0x%x to 0x%x\n"),
if (cmd == IKE_SVC_SET_DBG) {
} else {
}
}
static void
do_getstats(int cmd)
{
}
}
static void
do_getdefs(int cmd)
{
gettext("error getting defaults"));
}
/*
* Before printing each line, make sure the structure we were
* given is big enough to include the fields needed.
* Silently bail out of there is a version mismatch.
*/
return;
}
}
static void
{
char *name;
switch (cmd) {
case IKE_SVC_DUMP_P1S:
break;
case IKE_SVC_DUMP_RULES:
break;
case IKE_SVC_DUMP_PS:
break;
default:
}
do {
NULL, 0);
/* no entries to print */
break;
}
}
switch (cmd) {
case IKE_SVC_DUMP_P1S:
break;
case IKE_SVC_DUMP_RULES:
break;
case IKE_SVC_DUMP_PS:
break;
}
}
static void
{
int totallen;
char *p;
(cmd == IKE_SVC_GET_PS));
/*
* WARNING: to avoid being redundant, this code takes advantage
* of the fact that the ike_get_t and ike_del_t structures are
* identical (only the field names differ, their function and
* size are the same). If for some reason those structures
* change, this code will need to be re-written to accomodate
* that difference.
*/
Bail("malloc(id)");
p = (char *)(getp + 1);
} else {
name);
}
return;
}
if (getcmd) {
switch (cmd) {
case IKE_SVC_GET_P1:
break;
case IKE_SVC_GET_PS:
break;
case IKE_SVC_GET_RULE:
break;
}
} else {
}
}
static void
{
char label[MAX_LABEL_LEN];
Bail("not enough identification info");
}
switch (cmd) {
case IKE_SVC_GET_P1:
case IKE_SVC_DEL_P1:
/*
* The first token must either be an address (or hostname)
* or a cookie. We require cookies to be entered as hex
* numbers, beginning with 0x; so if our token starts with
* that, it's a cookie.
*/
idlen = sizeof (ike_cky_pr_t);
}
} else {
idlen = sizeof (ike_addr_pr_t);
}
}
break;
case IKE_SVC_GET_RULE:
case IKE_SVC_DEL_RULE:
}
break;
case IKE_SVC_GET_PS:
case IKE_SVC_DEL_PS:
/*
* The first token must either be an address or an ident
* type. Check for an ident type to determine which it is.
*/
}
} else {
idlen = sizeof (ike_addr_pr_t);
}
}
break;
default:
}
switch (idtype) {
case IKE_ID_ADDR_PAIR:
/*
* we might have exploding addrs here; do every possible
* combination.
*/
i = 0;
j = 0;
}
}
break;
case IKE_ID_IDENT_PAIR:
Bail("ident syntax error");
if (p == NULL)
Bail("malloc(id)");
p += bytelen1;
break;
case IKE_ID_CKY_PAIR:
case IKE_ID_LABEL:
break;
case 0:
default:
}
}
/*
* Copy source into target, inserting an escape character ('\') before
* any quotes that appear. Return true on success, false on failure.
*/
static boolean_t
{
return (B_FALSE);
if (source[s] == '\"')
target[t++] = '\\';
}
return (B_FALSE);
return (B_TRUE);
}
/*
* Return true if the arg following the given keyword should
* be in quotes (i.e. is a string), false if not.
*/
static boolean_t
quotedfield(char *keywd)
{
return (B_TRUE);
return (B_FALSE);
}
static void
{
switch (cmd) {
case IKE_SVC_NEW_PS:
break;
case IKE_SVC_NEW_RULE:
break;
default:
}
if (argc == 1) {
/* We've been given a file to read from */
if (fd < 0)
Bail("open source file");
ndesc = 1;
/*
* This is an alternative to using the tmpfile method
* for preshared keys. It means we're duplicating the
* parsing effort that happens in readps.c; but it
* does avoid having the key sitting in a file.
*/
int pslen;
/*
* must be in interactive mode; don't want keys in
* the process args.
*/
if (!interactive)
Bail("Must be in interactive mode to add key info.");
errno = 0;
Bail("invalid preshared key definition");
}
Bail("alloc pskey");
/* parse_ps allocated the ike_ps_t buffer; free it now */
/*
* We've been given the item in argv. However, parsing
* rules can get more than a little messy, and in.iked
* already has a great parser for this stuff! So don't
* fool around with trying to do the parsing here. Just
* write it out to a tempfile, and send the fd to in.iked.
*
* We could conceivably do this for preshared keys,
* rather than duplicating the parsing effort; but that
* would mean the key would be written out to a file,
* which isn't such a good idea.
*/
int rtn;
if ((argv[0][0] != '{') ||
/* attempt to use a fairly unpredictable file name... */
if (fd < 0)
Bail("cannot open tmpfile");
/* and make it inaccessible asap */
if (unlink(tmpfilepath) < 0) {
Bail("tmpfile error");
}
Bail("cannot write to tmpfile");
}
for (i = 0; i < argc; i++) {
/*
* We have to do some gyrations with our string here,
* to properly handle quotes. There are two issues:
* - some of the fields of a rule may have embedded
* whitespace, and thus must be quoted on the cmd
* line. The shell removes the quotes, and gives
* us a single argv string; but we need to put the
* quotes back in when we write the string out to
* file. The doquotes boolean is set when we
* process a keyword which will be followed by a
* string value (so the NEXT argv element will be
* quoted).
* - there might be a quote character in a field,
* that was escaped on the cmdline. The shell
* removes the escape char, and leaves the quote
* in the string it gives us. We need to put the
* escape char back in before writing to file.
*/
char field[MAXLINESIZE];
Bail("write to tmpfile failed (arg too big)");
if (doquotes) {
} else {
}
if (rtn < 0)
Bail("write to tmpfile failed");
/*
* check if this is a keyword identifying
* a field that needs to be quoted.
*/
}
Bail("write to tmpfile failed");
/* rewind so that the daemon will get the beginning */
ndesc = 1;
} else {
/* not enough information! */
}
} else {
}
}
static void
{
if (cmd != IKE_SVC_FLUSH_P1S) {
}
}
}
static void
{
switch (cmd) {
case IKE_SVC_READ_PS:
/* FALLTHRU */
case IKE_SVC_READ_RULES:
omode = 0;
break;
case IKE_SVC_WRITE_PS:
/* FALLTHRU */
case IKE_SVC_WRITE_RULES:
/* for write commands, dest location must be specified */
if (argc < 1) {
"to write %ss"), obj);
}
break;
default:
}
if (argc >= 1) {
if (fd < 0)
Bail("open user-specified file");
ndesc = 1;
} else {
}
/*
* Need to remove the target file in the
* case of a failed write command.
*/
if (writing) {
/*
* argv[0] must be valid if we're writing; we
* exit before setting this boolean if not.
*/
obj);
return;
}
}
}
}
static void
{
}
}
#define REQ_ARG_CNT 1
/*ARGSUSED*/
static void
{
if (interactive) {
if (argc == 0)
return;
}
if (argc < REQ_ARG_CNT) {
usage();
}
if (argc > REQ_ARG_CNT) {
cmd_obj_args++;
} else {
}
argc -= cmd_obj_args;
argv += cmd_obj_args;
switch (cmd) {
case IKE_SVC_GET_DEFS:
break;
case IKE_SVC_GET_DBG:
case IKE_SVC_GET_PRIV:
break;
case IKE_SVC_GET_STATS:
break;
case IKE_SVC_SET_DBG:
case IKE_SVC_SET_PRIV:
break;
case IKE_SVC_DUMP_P1S:
case IKE_SVC_DUMP_RULES:
case IKE_SVC_DUMP_PS:
break;
case IKE_SVC_GET_P1:
case IKE_SVC_GET_RULE:
case IKE_SVC_GET_PS:
case IKE_SVC_DEL_P1:
case IKE_SVC_DEL_RULE:
case IKE_SVC_DEL_PS:
break;
case IKE_SVC_NEW_RULE:
case IKE_SVC_NEW_PS:
break;
case IKE_SVC_FLUSH_P1S:
break;
case IKE_SVC_READ_RULES:
case IKE_SVC_READ_PS:
case IKE_SVC_WRITE_RULES:
case IKE_SVC_WRITE_PS:
break;
case IKEADM_HELP_GENERAL:
print_help();
break;
case IKEADM_HELP_GET:
break;
case IKEADM_HELP_SET:
break;
case IKEADM_HELP_ADD:
break;
case IKEADM_HELP_DEL:
break;
case IKEADM_HELP_DUMP:
break;
case IKEADM_HELP_FLUSH:
break;
case IKEADM_HELP_READ:
break;
case IKEADM_HELP_WRITE:
break;
case IKEADM_HELP_HELP:
break;
case IKEADM_EXIT:
if (interactive)
exit(0);
break;
case IKE_SVC_DBG_RBDUMP:
do_rbdump();
break;
case IKE_SVC_ERROR:
usage();
default:
exit(0);
}
}
int
{
char ch;
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
switch (ch) {
case 'h':
print_help();
return (0);
case 'p':
break;
case 'n':
break;
default:
usage();
}
}
if (open_door() < 0) {
gettext("Unable to communicate with in.iked\n"));
Bail("open_door failed");
}
/* no cmd-line args, do interactive mode */
}
return (0);
}