2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A * This file contains support functions that are shared by the ipsec 2N/A * utilities and daemons including ipseckey(1m), ikeadm(1m) and in.iked(1m). 2N/A/* Limits for interactive mode. */ 2N/A * Print errno and exit if cmdline or readfile, reset state if interactive 2N/A * The error string *what should be dgettext()'d before calling bail(). 2N/A * Print caller-supplied variable-arg error msg, then exit if cmdline or 2N/A * readfile, or reset state if interactive. 2N/A * bytecnt2str() wrapper. Zeroes out the input buffer and if the number 2N/A * of bytes to be converted is more than 1K, it will produce readable string 2N/A * in parentheses, store it in the original buffer and return the pointer to it. 2N/A * Maximum length of the returned string is 14 characters (not including 2N/A * the terminating zero). 2N/A /* Return empty string in case of out-of-memory. */ 2N/A /* Detect overflow. */ 2N/A /* Emit nothing in case of overflow. */ 2N/A * Convert 64-bit number to human readable string. Useful mainly for the 2N/A * byte lifetime counters. Returns pointer to the user supplied buffer. 2N/A * Able to convert up to Exabytes. Maximum length of the string produced 2N/A * is 9 characters (not counting the terminating zero). 2N/A /* The field has all units this function can represent. */ 2N/A /* Otherwise display 2 precision digits. */ 2N/A * secs2str() wrapper. Zeroes out the input buffer and if the number of 2N/A * seconds to be converted is more than minute, it will produce readable 2N/A * string in parentheses, store it in the original buffer and return the 2N/A /* Return empty string in case of out-of-memory. */ 2N/A /* Detect overflow. */ 2N/A /* Emit nothing in case of overflow. */ 2N/A * Convert number of seconds to human readable string. Useful mainly for 2N/A * the lifetime counters. Returns pointer to the user supplied buffer. 2N/A * Able to convert up to days. 2N/A /* Emit nothing in case of overflow. */ 2N/A * dump_XXX functions produce ASCII output from various structures. 2N/A * Because certain errors need to do this to stderr, dump_XXX functions 2N/A * take a FILE pointer. 2N/A * If an error occured while writing to the specified file, these 2N/A * functions return -1, zero otherwise. 2N/A /* Add 4 chars to hold '/nnn' for prefixes. */ 2N/A /* LINTED E_BAD_PTR_CAST_ALIGN */ 2N/A /* LINTED E_BAD_PTR_CAST_ALIGN */ 2N/A char prefix[
5];
/* "/nnn" with terminator. */ 2N/A * Do AF_independent reverse hostname lookup here. 2N/A " <unspecified>")) < 0)
2N/A * Dump a key, any salt and bitlen. 2N/A * The key is made up of a stream of bits. If the algorithm requires a salt 2N/A * value, this will also be part of the dumped key. The last "saltbits" of the 2N/A * key string, reading left to right will be the salt value. To make it easier 2N/A * to see which bits make up the key, the salt value is enclosed in []'s. 2N/A * This function can also be called when ipseckey(1m) -s is run, this "saves" 2N/A * the SAs, including the key to a file. When this is the case, the []'s are 2N/A * The implementation allows the kernel to be told about the length of the salt 2N/A * in whole bytes only. If this changes, this function will need to be updated. 2N/A /* The & 0x7 is to check for leftover bits. */ 2N/A /* Print no keys if paranoid */ 2N/A * Print an authentication or encryption algorithm 2N/A * Special-case <none> for backward output compat. 2N/A * Assume that SADB_AALG_NONE == SADB_EALG_NONE. 2N/A * Print an SADB_IDENTTYPE string 2N/A * Also return TRUE if the actual ident may be printed, FALSE if not. 2N/A * If rc is not NULL, set its value to -1 if an error occured while writing 2N/A * to the specified file, zero otherwise. 2N/A * Slice an argv/argc vector from an interactive line or a read-file line. 2N/A /* Regrow ***thisargv. */ 2N/A /* Double the allocation. */ 2N/A * Tricky corner case... 2N/A * I've parsed _exactly_ the amount of args as I have space. It 2N/A * won't return NULL-terminated, and bad things will happen to 2N/A * init interactive mode if needed and not yet initialized 2N/A "tecla initialization failed"));
2N/A "tab completion failed to initialize"));
2N/A * In interactive mode we only want to terminate 2N/A * when explicitly requested (e.g. by a command). 2N/A * free tecla data structure 2N/A * Get single input line, wrapping around interactive and non-interactive 2N/A * If the user hits ^C then we want to catch it and 2N/A * start over. If the user hits EOF then we want to 2N/A "Line too long (max=%d chars)"),
2N/A * Enter a mode where commands are read from a file. Treat stdin special. 2N/A * Check byte IBUF_SIZE - 2, because byte IBUF_SIZE - 1 will 2N/A * be null-terminated because of fgets(). 2N/A /* do_getstr() issued a warning already */ 2N/A /* Use -2 because of \n from fgets. */ 2N/A * Can use strcpy here, I've checked the 2N/A /* Remove the CONT_CHAR from the string. */ 2N/A /* Handle continuations... */ 2N/A "Command buffer overrun."));
2N/A /* Use - 2 because of \n from fgets. */ 2N/A /* Remove the CONT_CHAR from the string. */ 2N/A * I've already checked the length... 2N/A * Just in case the command fails keep a copy of the 2N/A * command buffer for diagnostic output. 2N/A * The error buffer needs to be big enough to 2N/A * hold the longest command string, plus 2N/A * some extra text, see below. 2N/A "Memory allocation error."));
2N/A "Config file entry near line %u " 2N/A "caused error(s) or warnings:\n\n%s\n\n"),
2N/A * The following code is ipseckey specific. This should never be 2N/A * used by ikeadm which also calls this function because ikeadm 2N/A * only runs interactively. If this ever changes this code block 2N/A * sould be revisited. 2N/A "contain any valid SAs"));
2N/A * There were errors. Putting the service in maintenance mode. 2N/A * When svc.startd(1M) allows services to degrade themselves, 2N/A * this should be revisited. 2N/A * If this function was called from a program running as a 2N/A * smf_method(5), print a warning message. Don't spew out the 2N/A * errors as these will end up in the smf(5) log file which is 2N/A * publically readable, the errors may contain sensitive 2N/A "The configuration file contained %d " 2N/A "Manually check the configuration with:\n" 2N/A "Use svcadm(1M) to clear maintenance " 2N/A "condition when errors are resolved.\n"),
2N/A "%d actions successfully processed."),
2N/A /* no newline upon Ctrl-D */ 2N/A * Functions to parse strings that represent a debug or privilege level. 2N/A * If this file evolves into a common library that may be used by in.iked 2N/A * as well as the usr.sbin utilities, those duplicate functions should be 2N/A * A privilege level may be represented by a simple keyword, corresponding 2N/A * to one of the possible levels. A debug level may be represented by a 2N/A * series of keywords, separated by '+' or '-', indicating categories to 2N/A * be added or removed from the set of categories in the debug level. 2N/A * For example, +all-op corresponds to level 0xfffffffb (all flags except 2N/A * for D_OP set); while p1+p2+pfkey corresponds to level 0x38. Note that 2N/A * the leading '+' is implicit; the first keyword in the list must be for 2N/A * a category that is to be added. 2N/A * These parsing functions make use of a local version of strtok, strtok_d, 2N/A * which includes an additional parameter, char *delim. This param is filled 2N/A * in with the character which ends the returned token. In other words, 2N/A * this version of strtok, in addition to returning the token, also returns 2N/A * the single character delimiter from the original string which marked the 2N/A /* first or subsequent call */ 2N/A if (
string == 0)
/* return if no tokens remaining */ 2N/A if (*q ==
'\0')
/* return if no tokens remaining */ 2N/A lasts = 0;
/* indicate that this is last token */ 2N/A /* we encountered an invalid keywd */ 2N/A * functions to manipulate the kmcookie-label mapping file 2N/A * Open, lockf, fdopen the given file, returning a FILE * on success, 2N/A * or NULL on failure. 2N/A /* save errno in case fclose changes it */ 2N/A * Extract an integer cookie and string label from a line from the 2N/A * kmcookie-label file. Return -1 on failure, 0 on success. 2N/A /* Everything that follows, up to the newline, is the label. */ 2N/A * Insert a mapping into the file (if it's not already there), given the 2N/A * new label. Return the assigned cookie, or -1 on error. 2N/A /* open and lock the file; will sleep until lock is available */ 2N/A /* kmc_open_and_lock() sets errno appropriately */ 2N/A /* Skip blank lines, which often come near EOF. */ 2N/A * Lookup the given cookie and return its corresponding label. Return 2N/A * a pointer to the label on success, NULL on error (or if the label is 2N/A * not found). Note that the returned label pointer points to a static 2N/A * string, so the label will be overwritten by a subsequent call to the 2N/A * function; the function is also not thread-safe as a result. 2N/A * Parse basic extension headers and return in the passed-in pointer vector. 2N/A * Return values include: 2N/A * KGE_OK Everything's nice and parsed out. 2N/A * If there are no extensions, place NULL in extv[0]. 2N/A * KGE_DUP There is a duplicate extension. 2N/A * First instance in appropriate bin. First duplicate in 2N/A * KGE_UNK Unknown extension type encountered. extv[0] contains 2N/A * KGE_LEN Extension length error. 2N/A * KGE_CHK High-level reality check failed on specific extension. 2N/A * My apologies for some of the pointer arithmetic in here. I'm thinking 2N/A * like an assembly programmer, yet trying to make the compiler happy. 2N/A /* Use extv[0] as the "current working pointer". */ 2N/A /* Check for unknown headers. */ 2N/A "spdsock ext 0x%X unknown: 0x%X",
2N/A * Check length. Use uint64_t because extlen is in units 2N/A * of 64-bit words. If length goes beyond the msgsize, 2N/A * return an error. (Zero length also qualifies here.) 2N/A /* Check for redundant headers. */ 2N/A /* If I make it here, assign the appropriate bin. */ 2N/A /* Advance pointer (See above for uint64_t ptr reasoning.) */ 2N/A /* Everything's cool. */ 2N/A * If extv[0] == NULL, then there are no extension headers in this 2N/A * message. Ensure that this is the case. 2N/A "unsupported ESP encryption algorithm"));
2N/A "unsupported ESP authentication algorithm"));
2N/A "unsupported ESP encryption key size"));
2N/A "unsupported ESP authentication key size"));
2N/A "number of key sizes inconsistent"));
2N/A "number of block sizes inconsistent"));
2N/A "operation not applicable to all policies"));
2N/A "using selectors on a transport-mode tunnel"));
2N/A * PF_KEY Diagnostic table. 2N/A * PF_KEY NOTE: If you change pfkeyv2.h's SADB_X_DIAGNOSTIC_* space, this is 2N/A * where you need to add new messages. 2N/A "Unknown Security Association type"));
2N/A "Specific Security Association type needed"));
2N/A "No Security Association Databases present"));
2N/A "No extensions needed for message"));
2N/A "Bad destination address family"));
2N/A "Bad inner-source address family"));
2N/A "Soft allocations limit more than hard limit"));
2N/A "Soft bytes limit more than hard limit"));
2N/A "than hard expiration time"));
2N/A "than hard expiration time"));
2N/A "Supported algorithms extension not needed"));
2N/A "Unsupported authentication algorithm"));
2N/A "Unsupported encryption algorithm"));
2N/A "Bad number of authentication bits"));
2N/A "Bad number of encryption bits"));
2N/A "Encryption not supported for this SA type"));
2N/A "Duplicate key management protocol"));
2N/A "Duplicate key management cookie"));
2N/A "Duplicate NAT-T remote address"));
2N/A "Malformed NAT-T remote address"));
2N/A "Missing inner destination address"));
2N/A "Duplicate inner source address"));
2N/A "Duplicate inner destination address"));
2N/A "Malformed inner source address"));
2N/A "Malformed inner destination address"));
2N/A "Invalid inner-source prefix length "));
2N/A "Invalid inner-destination prefix length"));
2N/A "Bad inner-destination address family"));
2N/A "Bad NAT-T remote address family"));
2N/A "Bad NAT-T local address family"));
2N/A "Both inner ports and outer ports are set"));
2N/A "Pairing failed, target SA unsuitable for pairing"));
2N/A "Already paired with another security association"));
2N/A "Command failed, pair security association not found"));
2N/A "Inappropriate SA direction"));
2N/A "Security association not found"));
2N/A "Security association is not valid"));
2N/A "Algorithm invalid or not supported by Crypto Framework"));
2N/A "Invalid Replay counter"));
2N/A "Inappropriate lifetimes"));
2N/A * Convert an IPv6 mask to a prefix len. I assume all IPv6 masks are 2N/A * contiguous, so I stop at the first zero bit! 2N/A * Expand the diagnostic code into a message. 2N/A /* Use two spaces so above strings can fit on the line. */ 2N/A " Diagnostic code %u: %s.\n"),
2N/A * Prints the base PF_KEY message. 2N/A "Base message (version %u) type "),
2N/A "RESERVED (warning: set to 0)"));
2N/A "Error %s from PF_KEY.\n"),
2N/A "Message length %u bytes, seq=%u, pid=%u.\n"),
2N/A * Print the SA extension for PF_KEY. 2N/A "WARNING: SA info extension length (%u) is bad."),
2N/A "%sSADB_ASSOC spi=0x%x, replay window size=%u, state="),
2N/A "ACTIVE_ELSEWHERE"));
2N/A "\n%sAuthentication algorithm = "),
2N/A /* BEGIN Solaris-specific flags. */ 2N/A /* END Solaris-specific flags. */ 2N/A * Print the SA lifetime information. (An SADB_EXT_LIFETIME_* extension.) 2N/A "WARNING: CURRENT lifetime extension length (%u) is bad."),
2N/A "WARNING: HARD lifetime extension length (%u) is bad."),
2N/A "WARNING: SOFT lifetime extension length (%u) is bad."),
2N/A "WARNING: IDLE lifetime extension length (%u) is bad."),
2N/A /* Express values as current values. */ 2N/A "%sCurrent lifetime information:\n"),
2N/A "%s%" PRIu64 " bytes %sprotected, %u allocations " 2N/A "%sSA first used at time %s\n"),
2N/A "%sSoft lifetime information:\n"),
2N/A "%s%" PRIu64 " bytes %sof lifetime, %u allocations.\n"),
2N/A "%s%" PRIu64 " seconds %sof post-add lifetime.\n"),
2N/A "%s%" PRIu64 " seconds %sof post-use lifetime.\n"),
2N/A /* If possible, express values as time remaining. */ 2N/A "Soft expiration occurs in %" 2N/A "Soft expiration occurred\n"));
2N/A "%sTime of expiration: %s.\n"),
2N/A "%s%" PRIu64 " bytes %sof lifetime, %u allocations.\n"),
2N/A "%s%" PRIu64 " seconds %sof post-add lifetime.\n"),
2N/A "%s%" PRIu64 " seconds %sof post-use lifetime.\n"),
2N/A /* If possible, express values as time remaining. */ 2N/A "Hard expiration occurs in %" 2N/A "Hard expiration occurred\n"));
2N/A "%sTime of expiration: %s.\n"),
2N/A "%s%" PRIu64 " seconds %sof post-add lifetime.\n"),
2N/A "%s%" PRIu64 " seconds %sof post-use lifetime.\n"),
2N/A * Print an SADB_EXT_ADDRESS_* extension. 2N/A "Inner source address "));
2N/A "Destination address "));
2N/A "Inner destination address "));
2N/A "NAT-T local address "));
2N/A "NAT-T remote address "));
2N/A * Print an SADB_EXT_KEY extension. 2N/A * Print an SADB_EXT_IDENTITY_* extension. 2N/A * Convert sadb_sens extension into binary security label. 2N/A "** Label conversion failed **"));
2N/A "** Label conversion failed **"));
2N/A * Print an SADB_SENSITIVITY extension. 2N/A "%s%s DPD %d, sens level=%d, integ level=%d, flags=%x\n"),
2N/A "%s %s BM extended word %d 0x%" PRIx64 "\n"),
2N/A "%s %s Label: %s (%s)\n"),
2N/A "%s Integrity BM extended word %d 0x%" PRIx64 "\n"),
2N/A * Print an SADB_EXT_PROPOSAL extension. 2N/A "%sProposal, replay counter = %u.\n"),
prefix,
2N/A "Authentication = "));
2N/A " minbits=%u, maxbits=%u.\n%s "),
2N/A " minbits=%u, maxbits=%u.\n%s "),
2N/A * Print an extended proposal (SADB_X_EXT_EPROP). 2N/A "%sExtended Proposal, replay counter = %u, "),
prefix,
2N/A "%s Extended combination #%u:\n"),
prefix, ++i);
2N/A "Authentication = "));
2N/A "algtype(%d) = alg(%d)"),
2N/A " minbits=%u, maxbits=%u, saltbits=%u\n"),
2N/A * Print an SADB_EXT_SUPPORTED extension. 2N/A " minbits=%u, maxbits=%u, ivlen=%u, saltbits=%u"),
2N/A * Print an SADB_EXT_SPIRANGE extension. 2N/A "%sSPI Range, min=0x%x, max=0x%x\n"),
prefix,
2N/A * Print an SADB_X_EXT_KM_COOKIE extension. 2N/A "%sProtocol %u, cookie=\"%s\" (%u)\n"),
prefix,
2N/A * Print an SADB_X_EXT_REPLAY_CTR extension. 2N/A "<Value not found.>"));
2N/A * We currently do not support a 64-bit replay value. 2N/A * RFC 4301 will require one, however, and we have a field 2N/A * in place when 4301 is built. 2N/A * Print an SADB_X_EXT_PAIR extension. 2N/A * Take a PF_KEY message pointed to buffer and print it. Useful for DUMP 2N/A * Pluck out lifetimes and print them at the end. This is 2N/A * to show relative lifetimes. 2N/A "UNK: Unknown ext. %d, len %d.\n"),
2N/A * Print lifetimes NOW. 2N/A "WARNING: insufficient buffer space or corrupt message."));
2N/A * save_XXX functions are used when "saving" the SA tables to either a 2N/A * file or standard output. They use the dump_XXX functions where needed, 2N/A * but mostly they use the rparseXXX functions. 2N/A * Print save information for a lifetime extension. 2N/A * NOTE : It saves the lifetime in absolute terms. For example, if you 2N/A * had a hard_usetime of 60 seconds, you'll save it as 60 seconds, even though 2N/A * there may have been 59 seconds burned off the clock. 2N/A * Print save information for an address extension. 2N/A * Address-family reality check. 2N/A * Do not do address-to-name translation, given that we live in 2N/A * an age of names that explode into many addresses. 2N/A * The port is in the same position for struct sockaddr_in and 2N/A * struct sockaddr_in6. We exploit that property here. 2N/A * Print save information for a key extension. Returns whether writing 2N/A * to the specified output file was successful or not. 2N/A * Print save information for an identity extension. 2N/A "<can-not-print>")) < 0)
2N/A * "Save" a security association to an output file. 2N/A * NOTE the lack of calls to dgettext() because I'm outputting parseable stuff. 2N/A * ALSO NOTE that if you change keywords (see parsecmd()), you'll have to 2N/A * change them here as well. 2N/A "save_assoc: Opening comment of SA"));
2N/A "or dead.\n") < 0) {
2N/A "save_assoc: fprintf not mature"));
2N/A "save_assoc: fprintf spi"));
2N/A "save_assoc: fprintf encrypt"));
2N/A "save_assoc: fprintf auth"));
2N/A "save_assoc: fprintf replay"));
2N/A "save_assoc: fprintf encap"));
2N/A "save_assoc: fprintf replay value"));
2N/A /* Skip over irrelevant extensions. */ 2N/A * Open the output file for the "save" command. 2N/A * If the user specifies "-" or doesn't give a filename, then 2N/A * dump to stdout. Make sure to document the dangers of files 2N/A * that are NFS, directing your output to strange places, etc. 2N/A * open the file with the create bits set. Since I check for 2N/A * real UID == root in main(), I won't worry about the ownership 2N/A "WARNING: Save file already exists with " 2N/A "Normal users may be able to read IPsec " 2N/A "keying material."));
2N/A /* Okay, we have an FD. Assign it to a stdio FILE pointer. */ 2N/A * Parse and reverse parse a specific SA type (AH, ESP, etc.). 2N/A {
NULL, 0}
/* Token value is irrelevant for this entry. */ 2N/A * Return a string containing the name of the specified numerical algorithm 2N/A * This is a general purpose exit function, calling functions can specify an 2N/A * error type. If the command calling this function was started by smf(5) the 2N/A * error type could be used as a hint to the restarter. In the future this 2N/A * function could be used to do something more intelligent with a process that 2N/A * encounters an error. If exit() is called with an error code other than those 2N/A * defined by smf(5), the program will just get restarted. Unless restarting 2N/A * is likely to resolve the error condition, its probably sensible to just 2N/A * log the error and keep running. 2N/A * The SERVICE_* exit_types mean nothing if the command was run from the 2N/A * command line, just exit(). There are two special cases: 2N/A * SERVICE_DEGRADE - Not implemented in smf(5), one day it could hint that 2N/A * the service is not running as well is it could. For 2N/A * now, don't do anything, just record the error. 2N/A * DEBUG_FATAL - Something happened, if the command was being run in debug 2N/A * mode, exit() as you really want to know something happened, 2N/A * otherwise just keep running. This is ignored when running 2N/A * The function will handle an optional variable args error message, this 2N/A * will be written to the error stream, typically a log file or stderr. 2N/A /* Command being run directly from a shell. */ 2N/A /* Command being run as a smf(5) method. */ 2N/A /* Keep running, don't exit(). */ 2N/A "Permission error with %s."),
fmri);
2N/A "Bad configuration of service %s."),
fmri);
2N/A "Service %s needs maintenance."),
fmri);