/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* sckmd - Starcat Key Management Daemon
*
* The sckmd is a daemon that runs on a domain and is responsible for
* establishing security associations (SAs) for secure communication
* with the System Controller (SC). All SAs are created on the SC
* and propogated to the sckmd through the sckm driver running on
* the domain. The sckmd then passes the SA to the key engine via the
* PF_KEY interface.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <syslog.h>
#include <ipsec_util.h>
#ifdef SCKMD_DEBUG
#else /* SCKMD_DEBUG */
#endif /* SCKMD_DEBUG */
static int standalone;
static int debug;
static int keysock;
static struct sadb_msg *read_pfkey_msg(void);
/*
* main:
*
* Initialize sckmd and enter an infinite loop. The loop waits for
* sckm messages from the sckm driver and dispatches each message
* to be processed synchronously.
*/
int
{
int opt;
int fd;
/*
* Set defaults
*/
standalone = 0;
debug = 0;
/*
* Check command line options
*/
opterr = 0; /* disable getopt error messages */
switch (opt) {
case 'd':
debug++;
break;
case 's':
standalone++;
break;
default:
exit(1);
}
}
/*
* IPsec must get loaded in-kernel. The easiest way to do this is
* to open (then close) a PF_KEY socket.
*/
exit(1);
}
/* must be root */
if (geteuid() != 0) {
exit(1);
}
if (standalone == 0) {
int i;
for (i = 0; i < NOFILE; i++) {
(void) close(i);
}
(void) chdir("/");
(void) umask(0);
if (fork() != 0) {
exit(0);
}
(void) setpgrp();
/* reinitialize syslog after closing all fds */
}
/* open driver */
exit(1);
}
/*
* Main processing loop
*/
for (;;) {
/* initialize the ioctl request */
/* wait for the next message */
continue;
}
/* pass the message to pf_key */
continue;
}
}
/*NOTREACHED*/
return (0);
}
/*
* process_sckm_req:
*
* Process a sckm request message. If the message is valid, pass the
* included SADB message to PF_KEY and return status to the sckm driver.
* The function only fails if it is unable to return a status message
* to the driver.
*/
static int
{
unsigned int msg_ver;
unsigned int msg_type;
unsigned int msg_len;
int err;
return (-1);
}
/* initialize a reply message */
/* currently, we only support sadb messages */
}
/* check that we have at least the sadb header */
}
/* LINTED Pointer Cast Alignment Warning */
/* check for an unsupported PF_KEY version */
msg_ver);
}
/* convert the PF_KEY message if necessary */
if (msg_ver != SCKMD_CURR_PFKEY_VER) {
}
}
/*
* Process the PF_KEY message
*/
switch (msg_type) {
case SADB_UPDATE:
case SADB_ADD:
case SADB_DELETE:
/*
* Only update, add, and delete are supported. Pass the
* message directly to PF_KEY.
*/
break;
default:
"from client (%d)\n", msg_type);
}
/* initialize global key socket */
}
/* send the PF_KEY message */
}
/* wait for key engine reply */
if (err == SCKM_IOCTL_STAT_ERR_PFKEY) {
}
} else {
}
}
/*
* send_sckm_status:
*
* Send a sckm status message to the sckm driver
*/
static int
{
return (-1);
}
return (0);
}
/*
* get_pfkey_reply:
*
* Wait for a reply from PF_KEY. Get the reply from the socket using
* the global file desciptor 'keysock'. If PF_KEY returns an error,
* the global errno is set to the error returned in the reply message.
* If an error occurs, the parameter 'err' is set to one of the error
* codes prefixed by SCKM_IOCTL_STAT_ERR to indicate the overall status
* of the operation.
*/
static int
{
int timeout;
int pollstatus;
double diff;
static char *pfkey_msg_type[] = {
"RESERVED",
"GETSPI",
"UPDATE",
"ADD",
"DELETE",
"GET",
"ACQUIRE",
"REGISTER",
"EXPIRE",
"FLUSH",
"DUMP",
"X_PROMISC",
"X_INVERSE_ACQUIRE",
};
while (timeout > 0) {
/* check for a timeout */
if (pollstatus == 0) {
"reply\n");
return (-1);
}
/* read in the next PF_KEY message */
msg = read_pfkey_msg();
return (-1);
}
/* check if the message is intended for us */
break;
}
}
/* check for a timeout */
if (timeout <= 0) {
"reply\n");
return (-1);
}
/* did we get what we were expecting? */
msg->sadb_msg_type);
return (-1);
}
/*
* Check for errors in SADB message, but ignore the
* ESRCH error for DELETE operation. This can happen if the SP
* sends a DELETE request first before sending the ADD
* request, just to make sure the keys are installed without a failure.
*/
int unknown_type = 0;
int arr_sz;
const char *diagnostic_str;
/* generate unknown type string, if necessary */
(void) snprintf(unknown_type_str,
sizeof (unknown_type_str), "UNKNOWN-%d",
msg->sadb_msg_type);
unknown_type = 1;
}
/* use libipsecutil to lookup the SADB diagnostic string */
"diagnostic code=%d: %s\n",
(unknown_type) ? unknown_type_str :
return (-1);
}
return (0);
}
/*
* read_pfkey_msg:
*
* Get a PF_KEY message from the socket using the global file descriptor
* 'keysock'. Data is stored in the global buffer 'msg_buf'. The function
* returns a pointer to the next PF_KEY message. Note that this is not
* necessarily at the start of 'msg_buf'. NULL is returned for errors.
*/
static struct sadb_msg *
read_pfkey_msg(void)
{
static int len;
/* Assume offset and len are initialized to NULL and 0 */
/* read a new block from the socket. */
if (len == -1) {
return (NULL);
}
}
"message length %d exceeds boundary %d\n",
return (NULL);
}
return (retval);
}
/*
* convert_pfkey_msg:
*
* Convert a lower version PF_KEY message to the current version
* being used by sckmd.
*
* Currently, there is only one implemented version of PF_KEY (v2).
* If future versions are added to the PF_KEY specification (RFC 2367),
* this function should be updated to provide backwards compatibility
* with version 2 and above.
*/
static int
{
switch (msg->sadb_msg_version) {
case PF_KEY_V2:
/*
* Current supported version:
* No conversion required
*/
break;
default:
return (-1);
}
return (0);
}
/*
* sckmd_log:
*
* Log a message using the syslog facility. If sckmd is running in
* standalone mode (global flag 'standalone' set), messages are also
* sent to stderr.
*/
static void
{
/* if this is a debug message, check if debugging is enabled */
return;
}
/* send message to stderr if in standalone mode */
if (standalone != 0) {
}
/* always log the message */
}