add support for ipmiv2 with lanplus interface

from Jeremy Ellington
This commit is contained in:
Duncan Laurie 2004-05-25 20:53:51 +00:00
parent 5750269c28
commit f30ef24600
23 changed files with 5093 additions and 262 deletions

View File

@ -146,6 +146,42 @@ AC_SUBST(PLUGIN_INTF_LAN)
AC_SUBST(STATIC_INTF_LAN)
AC_SUBST(LDFLAGS_INTF_LAN)
PLUGIN_INTF_LANPLUS=
STATIC_INTF_LANPLUS=
LDFLAGS_INTF_LANPLUS=
AC_ARG_ENABLE([intf-lanplus],
[[ --enable-intf-lanplus enable IPMI-over-LAN RMCP+ interface ]]
[[ plugin : build dynamic]]
[[ static : link statically ]]
[[ --diable-intf-lanplus disable IPMI-over-LAN RMCP+ interface [default]]],
[if test "x$enableval" = "xplugin" || test "x$enableval" = "xdynamic"; then
AC_SUBST(INTF_LANPLUS,lanplus)
PLUGIN_INTF_LANPLUS="libintf_lanplus.la"
LDFLAGS_INTF_LANPLUS="-rpath $pluginpath -avoid-version"
DYNAMIC_INTF_LIST="lanplus $DYNAMIC_INTF_LIST"
elif test "x$enableval" = "xstatic" || test "x$enableval" = "xyes"; then
AC_SUBST(INTF_LANPLUS,lanplus)
STATIC_INTF_LANPLUS="libintf_lanplus.la"
STATIC_INTF_LIST="lanplus $STATIC_INTF_LIST"
fi
if test "x$enableval" != "xno"; then
AC_CHECK_LIB(ssl, EVP_aes_128_cbc, [], [
echo "Error! The lanplus interface requires an SSL library with EVP_aes_128_cbc defined."
exit -1
])
fi],
[])
AC_SUBST(PLUGIN_INTF_LANPLUS)
AC_SUBST(STATIC_INTF_LANPLUS)
AC_SUBST(LDFLAGS_INTF_LANPLUS)
PLUGIN_INTF_OPEN=
STATIC_INTF_OPEN=
LDFLAGS_INTF_OPEN=
@ -248,6 +284,7 @@ AC_CONFIG_FILES([ipmitool.spec
src/plugins/ipmi_intf_static.c
src/plugins/Makefile
src/plugins/lan/Makefile
src/plugins/lanplus/Makefile
src/plugins/open/Makefile
src/plugins/lipmi/Makefile])

View File

@ -49,7 +49,7 @@ unsigned short str2val(const char * str, const struct valstr * vs);
unsigned short buf2short(unsigned char * buf);
uint32_t buf2long(unsigned char * buf);
const char * buf2str(unsigned char * buf, int len);
void printbuf(unsigned char * buf, int len, char * desc);
void printbuf(const unsigned char * buf, int len, const char * desc);
void signal_handler(int sig, void * handler);

View File

@ -45,6 +45,17 @@
#define BUF_SIZE 256
/* From table 13.16 of the IPMI v2 specification */
#define IPMI_PAYLOAD_TYPE_IPMI 0x00
#define IPMI_PAYLOAD_TYPE_SOL 0x01
#define IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST 0x10
#define IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE 0x11
#define IPMI_PAYLOAD_TYPE_RAKP_1 0x12
#define IPMI_PAYLOAD_TYPE_RAKP_2 0x13
#define IPMI_PAYLOAD_TYPE_RAKP_3 0x14
#define IPMI_PAYLOAD_TYPE_RAKP_4 0x15
extern int verbose;
extern int csv_output;
@ -57,6 +68,56 @@ struct ipmi_rq {
} msg;
};
/*
* This is what the sendrcv_v2() function would take as an argument. The common case
* is for payload_type to be IPMI_PAYLOAD_TYPE_IPMI.
*/
struct ipmi_v2_payload {
unsigned short payload_length;
unsigned char payload_type;
union {
struct {
unsigned char rq_seq;
struct ipmi_rq * request;
} ipmi_request;
struct {
unsigned char * message;
} sol_message;
/* Only used internally by the lanplus interface */
struct {
unsigned char * request;
} open_session_request;
/* Only used internally by the lanplus interface */
struct {
unsigned char * message;
} rakp_1_message;
/* Only used internally by the lanplus interface */
struct {
unsigned char * message;
} rakp_2_message;
/* Only used internally by the lanplus interface */
struct {
unsigned char * message;
} rakp_3_message;
/* Only used internally by the lanplus interface */
struct {
unsigned char * message;
} rakp_4_message;
} payload;
};
struct ipmi_rq_entry {
struct ipmi_rq req;
struct ipmi_intf * intf;
@ -66,34 +127,81 @@ struct ipmi_rq_entry {
struct ipmi_rq_entry * next;
};
struct ipmi_rs {
unsigned char ccode;
unsigned char data[BUF_SIZE];
/*
* Looks like this is the length of the entire packet, including the RMCP
* stuff, then modified to be the length of the extra IPMI message data
*/
int data_len;
struct {
unsigned char authtype;
uint32_t seq;
uint32_t id;
} session_hdr;
unsigned char msglen;
struct {
unsigned char rq_addr;
unsigned char netfn;
unsigned char rq_lun;
unsigned char rs_addr;
unsigned char rq_seq;
unsigned char rs_lun;
unsigned char cmd;
} header;
unsigned char authtype;
uint32_t seq;
uint32_t id;
unsigned char bEncrypted; /* IPMI v2 only */
unsigned char bAuthenticated; /* IPMI v2 only */
unsigned char payloadtype; /* IPMI v2 only */
unsigned short msglen; /* This is the total length of the payload or
IPMI message. IPMI v2.0 requires this to
be 2 bytes. Not really used for much. */
} session;
/*
* A union of the different possible payload meta-data
*/
union {
struct {
unsigned char rq_addr;
unsigned char netfn;
unsigned char rq_lun;
unsigned char rs_addr;
unsigned char rq_seq;
unsigned char rs_lun;
unsigned char cmd;
} ipmi_response;
struct {
unsigned char message_tag;
unsigned char rakp_return_code;
unsigned char max_priv_level;
unsigned int console_id;
unsigned int bmc_id;
unsigned char auth_alg;
unsigned char integrity_alg;
unsigned char crypt_alg;
} open_session_response;
struct {
unsigned char message_tag;
unsigned char rakp_return_code;
unsigned int console_id;
unsigned char bmc_rand[16]; /* Random number generated by the BMC */
unsigned char bmc_guid[16];
unsigned char key_exchange_auth_code[20];
} rakp2_message;
struct {
unsigned char message_tag;
unsigned char rakp_return_code;
unsigned int console_id;
unsigned char integrity_check_value[20];
} rakp4_message;
} payload;
};
#define IPMI_NETFN_CHASSIS 0x0
#define IPMI_NETFN_BRIDGE 0x2
#define IPMI_NETFN_SE 0x4
#define IPMI_NETFN_APP 0x6
#define IPMI_NETFN_FIRMWARE 0x8
#define IPMI_NETFN_STORAGE 0xa
#define IPMI_NETFN_TRANSPORT 0xc
#define IPMI_NETFN_TRANSPORT 0xc
#define IPMI_NETFN_SOL 0x34
#define IPMI_BMC_SLAVE_ADDR 0x20

View File

@ -45,11 +45,6 @@
#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
#define IPMI_GET_CHANNEL_ACCESS 0x41
#define IPMI_GET_CHANNEL_INFO 0x42
#define IPMI_SET_USER_ACCESS 0x43
#define IPMI_GET_USER_ACCESS 0x44
#define IPMI_SET_USER_NAME 0x45
#define IPMI_GET_USER_NAME 0x46
#define IPMI_SET_USER_PASSWORD 0x47
#define IPMI_1_5_AUTH_TYPE_BIT_NONE 0x01
@ -173,62 +168,6 @@ struct get_channel_access_rsp {
} __attribute__ ((packed));
struct get_user_access_rsp {
#if WORDS_BIGENDIAN
unsigned char __reserved1 : 2;
unsigned char max_user_ids : 6;
unsigned char __reserved2 : 2;
unsigned char enabled_user_ids : 6;
unsigned char __reserved3 : 2;
unsigned char fixed_user_ids : 6;
unsigned char __reserved4 : 1;
unsigned char callin_callback : 1;
unsigned char link_auth : 1;
unsigned char ipmi_messaging : 1;
unsigned char privilege_limit : 4;
#else
unsigned char max_user_ids : 6;
unsigned char __reserved1 : 2;
unsigned char enabled_user_ids : 6;
unsigned char __reserved2 : 2;
unsigned char fixed_user_ids : 6;
unsigned char __reserved3 : 2;
unsigned char privilege_limit : 4;
unsigned char ipmi_messaging : 1;
unsigned char link_auth : 1;
unsigned char callin_callback : 1;
unsigned char __reserved4 : 1;
#endif
} __attribute__ ((packed));
struct set_user_access_data {
#if WORDS_BIGENDIAN
unsigned char change_bits : 1;
unsigned char callin_callback : 1;
unsigned char link_auth : 1;
unsigned char ipmi_messaging : 1;
unsigned char channel : 4;
unsigned char __reserved1 : 2;
unsigned char user_id : 6;
unsigned char __reserved2 : 4;
unsigned char privilege_limit : 4;
unsigned char __reserved3 : 4;
unsigned char session_limit : 4;
#else
unsigned char channel : 4;
unsigned char ipmi_messaging : 1;
unsigned char link_auth : 1;
unsigned char callin_callback : 1;
unsigned char change_bits : 1;
unsigned char user_id : 6;
unsigned char __reserved1 : 2;
unsigned char privilege_limit : 4;
unsigned char __reserved2 : 4;
unsigned char session_limit : 4;
unsigned char __reserved3 : 4;
#endif
} __attribute__ ((packed));
int ipmi_channel_main(struct ipmi_intf *, int, char **);
void ipmi_get_channel_auth_cap(struct ipmi_intf * intf, unsigned char channel, unsigned char priv);

View File

@ -39,11 +39,12 @@
#include <ipmitool/ipmi.h>
#define IPMI_SESSION_AUTHTYPE_NONE 0x0
#define IPMI_SESSION_AUTHTYPE_MD2 0x1
#define IPMI_SESSION_AUTHTYPE_MD5 0x2
#define IPMI_SESSION_AUTHTYPE_KEY 0x4
#define IPMI_SESSION_AUTHTYPE_OEM 0x5
#define IPMI_SESSION_AUTHTYPE_NONE 0x0
#define IPMI_SESSION_AUTHTYPE_MD2 0x1
#define IPMI_SESSION_AUTHTYPE_MD5 0x2
#define IPMI_SESSION_AUTHTYPE_KEY 0x4
#define IPMI_SESSION_AUTHTYPE_OEM 0x5
#define IPMI_SESSION_AUTHTYPE_RMCP_PLUS 0x6
#define IPMI_SESSION_PRIV_CALLBACK 0x1
#define IPMI_SESSION_PRIV_USER 0x2
@ -51,21 +52,71 @@
#define IPMI_SESSION_PRIV_ADMIN 0x4
#define IPMI_SESSION_PRIV_OEM 0x5
/*
* An enumeration that describes every possible session state for
* an IPMIv2 / RMCP+ session.
*/
enum LANPLUS_SESSION_STATE {
LANPLUS_STATE_PRESESSION = 0,
LANPLUS_STATE_OPEN_SESSION_SENT,
LANPLUS_STATE_OPEN_SESSION_RECEIEVED,
LANPLUS_STATE_RAKP_1_SENT,
LANPLUS_STATE_RAKP_2_RECEIVED,
LANPLUS_STATE_RAKP_3_SENT,
LANPLUS_STATE_ACTIVE,
LANPLUS_STATE_CLOSE_SENT,
};
#define IPMI_AUTHCODE_BUFFER_SIZE 16
#define IPMI_SIK_BUFFER_SIZE 20
#define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */
struct ipmi_session {
unsigned char hostname[64];
unsigned char username[16];
unsigned char authcode[16];
unsigned char authcode[IPMI_AUTHCODE_BUFFER_SIZE];
unsigned char challenge[16];
unsigned char authtype;
unsigned char privlvl;
int password;
int port;
int active;
uint32_t session_id;
uint32_t in_seq;
uint32_t out_seq;
/*
* This struct holds state data specific to IMPI v2 / RMCP+ sessions
*/
struct {
enum LANPLUS_SESSION_STATE session_state;
/* These are the algorithms agreed upon for the session */
unsigned char auth_alg;
unsigned char integrity_alg;
unsigned char crypt_alg;
unsigned char max_priv_level;
uint32_t console_id;
uint32_t bmc_id;
/* Values required for RAKP mesages */
unsigned char console_rand[16]; /* Random number generated byt the console */
unsigned char bmc_rand[16]; /* Random number generated by the BMC */
unsigned char bmc_guid[16];
unsigned char requested_role; /* As sent in the RAKP 1 message */
unsigned char rakp2_return_code;
unsigned char sik[IPMI_SIK_BUFFER_SIZE]; /* Session integrity key */
unsigned char kg[IPMI_KG_BUFFER_SIZE]; /* BMC key */
unsigned char k1[20]; /* Used for Integrity checking? */
unsigned char k2[20]; /* First 16 bytes used for AES */
} v2_data;
};
struct ipmi_intf {
int fd;
int opened;
@ -74,6 +125,7 @@ struct ipmi_intf {
int (*open)(struct ipmi_intf *);
void (*close)(struct ipmi_intf *);
struct ipmi_rs *(*sendrecv)(struct ipmi_intf *, struct ipmi_rq *);
struct ipmi_rs *(*sendrecv_v2)(struct ipmi_intf *, struct ipmi_v2_payload *);
struct ipmi_session * session;
};

View File

@ -0,0 +1,99 @@
/*
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.h,v 1.1 2004/05/25 20:53:49 iceblink Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.h is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Removed support for non-ANSI compilers; removed
references to Ghostscript; clarified derivation from RFC 1321;
now handles byte order either statically or dynamically.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
added conditionalization for C++ compilation from Martin
Purschke <purschke@bnl.gov>.
1999-05-03 lpd Original version.
*/
#ifndef md5_INCLUDED
# define md5_INCLUDED
/*
* This package supports both compile-time and run-time determination of CPU
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
* defined as non-zero, the code will be compiled to run only on big-endian
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
* run on either big- or little-endian CPUs, but will run slightly less
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
*/
typedef unsigned char md5_byte_t; /* 8-bit byte */
typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
#ifdef __cplusplus
extern "C"
{
#endif
/* Initialize the algorithm. */
void md5_init(md5_state_t *pms);
/* Append a string to the message. */
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
/* Finish the message and return the digest. */
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
/*
* multi-session authcode generation for md5
* H(password + session_id + msg + session_seq + password)
*/
unsigned char * ipmi_auth_md5(unsigned char * data, int data_len);
#ifdef __cplusplus
} /* end extern "C" */
#endif
#endif /* md5_INCLUDED */

View File

@ -69,7 +69,7 @@ const char * buf2str(unsigned char * buf, int len)
return (const char *)str;
}
void printbuf(unsigned char * buf, int len, char * desc)
void printbuf(const unsigned char * buf, int len, const char * desc)
{
int i;

View File

@ -51,7 +51,6 @@
#include <ipmitool/ipmi_lanp.h>
#include <ipmitool/ipmi_channel.h>
void printf_channel_usage (void);
const struct valstr ipmi_authtype_vals[] = {
{ IPMI_1_5_AUTH_TYPE_BIT_NONE, "NONE" },
@ -175,7 +174,7 @@ void ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
}
memcpy(&auth_cap, rsp->data, sizeof(struct get_channel_auth_cap_rsp));
printbuf(rsp->data, sizeof(struct get_channel_auth_cap_rsp), "the authcap buffer per sizeof");
printf("Channel number : %d\n",
auth_cap.channel_number);
@ -252,6 +251,10 @@ ipmi_get_channel_info(struct ipmi_intf * intf, unsigned char channel)
}
printbuf(rsp->data, rsp->data_len, "the info buffer per data_len");
printbuf(rsp->data, sizeof(struct get_channel_info_rsp), "the info buffer per sizeof");
memcpy(&channel_info, rsp->data, sizeof(struct get_channel_info_rsp));
@ -378,177 +381,57 @@ ipmi_get_channel_info(struct ipmi_intf * intf, unsigned char channel)
static int
ipmi_get_user_access(struct ipmi_intf * intf, unsigned char channel, unsigned char userid)
{
struct ipmi_rs * rsp;
struct ipmi_rq req1, req2;
unsigned char rqdata[2];
struct get_user_access_rsp user_access;
int curr_uid, max_uid, init = 1;
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
curr_uid = userid ? userid : 1;
memset(&req1, 0, sizeof(req1));
req1.msg.netfn = IPMI_NETFN_APP;
req1.msg.cmd = IPMI_GET_USER_ACCESS;
req1.msg.data = rqdata;
req1.msg.data_len = 2;
memset(&req2, 0, sizeof(req2));
req2.msg.netfn = IPMI_NETFN_APP;
req2.msg.cmd = IPMI_GET_USER_NAME;
req2.msg.data = rqdata;
req2.msg.data_len = 1;
do
{
rqdata[0] = channel & 0xf;
rqdata[1] = curr_uid & 0x3f;
rsp = intf->sendrecv(intf, &req1);
if (!rsp || rsp->ccode) {
printf("Error:%x Get User Access Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return -1;
}
memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp));
rqdata[0] = curr_uid & 0x3f;
rsp = intf->sendrecv(intf, &req2);
if (!rsp || rsp->ccode) {
printf("Error:%x Get User Name Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return -1;
}
if (init)
{
printf("Maximum User IDs : %d\n", user_access.max_user_ids);
printf("Enabled User IDs : %d\n", user_access.enabled_user_ids);
max_uid = user_access.max_user_ids;
init = 0;
}
printf("\nUser ID : %d\n", curr_uid);
printf("User Name : %s\n", rsp->data);
printf("Fixed Name : %s\n", curr_uid <= user_access.fixed_user_ids ? "Yes" : "No");
printf("Access Available : %s\n", user_access.callin_callback ? "callback" : "call-in / callback");
printf("Link Authentication : %sabled\n", user_access.link_auth ? "en" : "dis");
printf("IPMI Messaging : %sabled\n", user_access.ipmi_messaging ? "en" : "dis");
printf("Privilege Level : %s\n", val2str(user_access.privilege_limit, ipmi_privlvl_vals));
curr_uid ++;
} while (!userid && curr_uid <= max_uid);
return 0;
}
static void
ipmi_set_user_access(struct ipmi_intf * intf, int argc, char ** argv)
{
unsigned char channel, userid;
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char rqdata[2];
struct get_user_access_rsp user_access;
struct set_user_access_data set_access;
int i;
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
if (argc < 3 || !strncmp(argv[0], "help", 4)) {
printf_channel_usage();
return;
}
channel = (unsigned char)strtol(argv[0], NULL, 0);
userid = (unsigned char)strtol(argv[1], NULL, 0);
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_GET_USER_ACCESS;
req.msg.data = rqdata;
req.msg.data_len = 2;
rqdata[0] = channel & 0xf;
rqdata[1] = userid & 0x3f;
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = 0x44;
req.msg.data = rqdata;
req.msg.data_len = 2;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Get User Access Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return;
return -1;
}
memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp));
printf("Maximum User IDs : %d\n", rsp->data[0] & 0x3f);
printf("Enabled User IDs : %d\n", rsp->data[1] & 0x3f);
printf("Fixed Name User IDs : %d\n", rsp->data[2] & 0x3f);
printf("Access Available : %s\n", (rsp->data[3] & 0x40) ? "callback" : "call-in / callback");
printf("Link Authentication : %sabled\n", (rsp->data[3] & 0x20) ? "en" : "dis");
printf("IPMI Messaging : %sabled\n", (rsp->data[3] & 0x10) ? "en" : "dis");
printf("Privilege Level : %s\n", val2str(rsp->data[3] & 0x0f, ipmi_privlvl_vals));
set_access.change_bits = 1;
set_access.callin_callback = user_access.callin_callback;
set_access.link_auth = user_access.link_auth;
set_access.ipmi_messaging = user_access.ipmi_messaging;
set_access.channel = channel;
set_access.user_id = userid;
set_access.privilege_limit = user_access.privilege_limit;
set_access.session_limit = 0;
for (i = 2; i < argc; i ++)
{
if (!strncmp(argv[i], "callin=", 7)) {
set_access.callin_callback = !strncmp (argv[i]+7, "off", 3);
}
else if (!strncmp(argv[i], "link=", 5)) {
set_access.link_auth = strncmp (argv[i]+5, "off", 3);
}
else if (!strncmp(argv[i], "ipmi=", 5)) {
set_access.ipmi_messaging = strncmp (argv[i]+5, "off", 3);
}
else if (!strncmp(argv[i], "privilege=", 10)) {
set_access.privilege_limit = strtol (argv[i]+10, NULL, 0);
}
else {
printf ("Invalid option: %s\n", argv [i]);
return;
}
}
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_SET_USER_ACCESS;
req.msg.data = (unsigned char *) &set_access;
req.msg.data_len = 4;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Set User Access Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return;
}
return;
return 0;
}
void
printf_channel_usage()
{
printf("Channel Commands: authcap <channel number> <max privilege>\n");
printf(" getaccess <channel number> [user id]\n");
printf(" setaccess <channel number> <user id> [callin=on|off] [ipmi=on|off] [link=on|off] [privilege=level]\n");
printf(" info [channel number]\n");
printf("Channel Commands: authcap <channel number> <max priv>\n");
printf(" user <channel number> [user id]\n");
printf(" info [channel number]\n");
printf("\n");
printf("Possible privilege levels are:\n");
printf("Possible privelige levels are:\n");
printf(" 1 Callback level\n");
printf(" 2 User level\n");
printf(" 3 Operator level\n");
printf(" 4 Administrator level\n");
printf(" 5 OEM Proprietary level\n");
printf(" 15 No access\n");
}
int
ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv)
{
@ -567,22 +450,18 @@ ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv)
(unsigned char)strtol(argv[1], NULL, 0),
(unsigned char)strtol(argv[2], NULL, 0));
}
else if (!strncmp(argv[0], "getaccess", 10))
else if (!strncmp(argv[0], "user", 4))
{
if (argc < 2 || argc > 3)
printf_channel_usage();
else {
unsigned char ch = (unsigned char)strtol(argv[1], NULL, 0);
unsigned char id = 0;
unsigned char id = 1;
if (argc == 3)
id = (unsigned char)strtol(argv[2], NULL, 0);
ipmi_get_user_access(intf, ch, id);
}
}
else if (!strncmp(argv[0], "setaccess", 9))
{
ipmi_set_user_access(intf, argc-1, &(argv[1]));
}
else if (!strncmp(argv[0], "info", 4))
{
if (argc > 2)

View File

@ -38,8 +38,8 @@ INCLUDES = -I$(top_srcdir)/include $(INCLTDL)
MAINTAINERCLEANFILES = Makefile.in ipmi_intf_static.c
EXTRA_DIST = ipmi_intf_static.c.in
SUBDIRS = @INTF_LAN@ @INTF_OPEN@ @INTF_LIPMI@
DIST_SUBDIRS = lan open lipmi
SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@
DIST_SUBDIRS = lan lanplus open lipmi
noinst_LTLIBRARIES = libintf.la
libintf_la_SOURCES = ipmi_intf.c ipmi_intf_static.c

View File

@ -464,51 +464,53 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
}
x = 4;
rsp->session_hdr.authtype = rsp->data[x++];
memcpy(&rsp->session_hdr.seq, rsp->data+x, 4);
rsp->session.authtype = rsp->data[x++];
memcpy(&rsp->session.seq, rsp->data+x, 4);
x += 4;
memcpy(&rsp->session_hdr.id, rsp->data+x, 4);
memcpy(&rsp->session.id, rsp->data+x, 4);
x += 4;
if (intf->session->active && intf->session->authtype)
x += 16;
rsp->msglen = rsp->data[x++];
rsp->header.rq_addr = rsp->data[x++];
rsp->header.netfn = rsp->data[x] >> 2;
rsp->header.rq_lun = rsp->data[x++] & 0x3;
rsp->session.msglen = rsp->data[x++];
rsp->payload.ipmi_response.rq_addr = rsp->data[x++];
rsp->payload.ipmi_response.netfn = rsp->data[x] >> 2;
rsp->payload.ipmi_response.rq_lun = rsp->data[x++] & 0x3;
x++; /* checksum */
rsp->header.rs_addr = rsp->data[x++];
rsp->header.rq_seq = rsp->data[x] >> 2;
rsp->header.rs_lun = rsp->data[x++] & 0x3;
rsp->header.cmd = rsp->data[x++];
rsp->payload.ipmi_response.rs_addr = rsp->data[x++];
rsp->payload.ipmi_response.rq_seq = rsp->data[x] >> 2;
rsp->payload.ipmi_response.rs_lun = rsp->data[x++] & 0x3;
rsp->payload.ipmi_response.cmd = rsp->data[x++];
rsp->ccode = rsp->data[x++];
if (verbose > 2) {
printbuf(rsp->data, x, "ipmi message header");
printbuf(rsp->data, rsp->data_len, "ipmi message header");
printf("<< IPMI Response Session Header\n");
printf("<< Authtype : %s\n",
val2str(rsp->session_hdr.authtype, ipmi_authtype_session_vals));
printf("<< Sequence : 0x%08lx\n", rsp->session_hdr.seq);
printf("<< Session ID : 0x%08lx\n", rsp->session_hdr.id);
val2str(rsp->session.authtype, ipmi_authtype_session_vals));
printf("<< Sequence : 0x%08lx\n", rsp->session.seq);
printf("<< Session ID : 0x%08lx\n", rsp->session.id);
printf("<< IPMI Response Message Header\n");
printf("<< Rq Addr : %02x\n", rsp->header.rq_addr);
printf("<< NetFn : %02x\n", rsp->header.netfn);
printf("<< Rq LUN : %01x\n", rsp->header.rq_lun);
printf("<< Rs Addr : %02x\n", rsp->header.rs_addr);
printf("<< Rq Seq : %02x\n", rsp->header.rq_seq);
printf("<< Rs Lun : %01x\n", rsp->header.rs_lun);
printf("<< Command : %02x\n", rsp->header.cmd);
printf("<< Rq Addr : %02x\n", rsp->payload.ipmi_response.rq_addr);
printf("<< NetFn : %02x\n", rsp->payload.ipmi_response.netfn);
printf("<< Rq LUN : %01x\n", rsp->payload.ipmi_response.rq_lun);
printf("<< Rs Addr : %02x\n", rsp->payload.ipmi_response.rs_addr);
printf("<< Rq Seq : %02x\n", rsp->payload.ipmi_response.rq_seq);
printf("<< Rs Lun : %01x\n", rsp->payload.ipmi_response.rs_lun);
printf("<< Command : %02x\n", rsp->payload.ipmi_response.cmd);
printf("<< Compl Code : 0x%02x\n", rsp->ccode);
}
/* now see if we have oustanding entry in request list */
entry = ipmi_req_lookup_entry(rsp->header.rq_seq, rsp->header.cmd);
entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq,
rsp->payload.ipmi_response.cmd);
if (entry) {
if (verbose > 2)
printf("IPMI Request Match found\n");
ipmi_req_remove_entry(rsp->header.rq_seq, rsp->header.cmd);
ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq,
rsp->payload.ipmi_response.cmd);
} else {
if (verbose)
printf("WARNING: IPMI Request Match NOT FOUND!\n");
@ -537,11 +539,11 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
* | rmcp.seq |
* | rmcp.class |
* +--------------------+
* | session_hdr.authtype | 9 bytes
* | session_hdr.seq |
* | session_hdr.id |
* | session.authtype | 9 bytes
* | session.seq |
* | session.id |
* +--------------------+
* | [session_hdr.authcode] | 16 bytes (AUTHTYPE != none)
* | [session.authcode] | 16 bytes (AUTHTYPE != none)
* +--------------------+
* | message length | 1 byte
* +--------------------+

View File

@ -0,0 +1,47 @@
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistribution of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistribution in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Sun Microsystems, Inc. or the names of
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# This software is provided "AS IS," without a warranty of any kind.
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
#
# You acknowledge that this software is not designed or intended for use
# in the design, construction, operation or maintenance of any nuclear
# facility.
MAINTAINERCLEANFILES = Makefile.in
plugindir = $(pluginpath)
INCLUDES = -I$(top_srcdir)/include
EXTRA_LTLIBRARIES = libintf_lanplus.la
plugin_LTLIBRARIES = @PLUGIN_INTF_LANPLUS@
noinst_LTLIBRARIES = @STATIC_INTF_LANPLUS@
libintf_lanplus_la_LDFLAGS = @LDFLAGS_INTF_LANPLUS@
libintf_lanplus_la_LIBADD = $(top_srcdir)/lib/libipmitool.la
libintf_lanplus_la_SOURCES = lanplus.c lanplus.h rmcp.h lanplus_crypt.h lanplus_crypt.c lanplus_strings.c lanplus_dump.h lanplus_dump.c lanplus_crypt_impl.h lanplus_crypt_impl.c

View File

@ -0,0 +1,74 @@
This interface exists to provide a means of connecting to an IPMIv2 enabled
BMC. In some places, the IPMIv2 specification is either unclear or
inconsistent, and interpretations of the intent of the specification had to
be made at the discretion of the implementor. The purpose of this
document is to make those decisions clear so that 1) they can be reviewed
by others and 2) so that the rationale for those decisions can be made
clear.
* Though it's not stated explicitly with which algorithm the K1 and K2 keys
should be generated, we chose to use the authentication algorithm. The
specification states that K1 and K2 are generated with an HMAC algorithm,
and all of the authentication algorithms (except for "none") are HMAC
algorithms, whereas the integrity algorithms are not all HMAC. See section
13.32 for details about K1 and K2, and section
* The IPMIv2 specification describes a key, Kg, that is the "BMC key".
This key functions as a global key that is required to be known in addition
to the user's key, by authenticating users. If the BMC has a null Kg, the
users key, Kuid, is used in its place in algorithms where Kg is required,
per the specification section 13.33. A user can obtain the status of Kg by
querying the BMC with the Get Channel Authentication Capabilities command.
Currently, this implementation does not provide a way for a user to specify
Kg for BMCs that require it.
* The specification is unclear as to which key is used for HMAC based
integrity checking. One the one hand, section 13.28.4 states explicitly
that HMAC integrity algorithms use the session integrity key as the HMAC
key. Confusing that matter is a statement in section 13.32 regarding the
creation of additional keying material. In this section it is stated that
"all keying material for the RSP integrity and confidentiality algorithms
will be generated by processing a pre-defined set of constants using HMAC
per [RFC2104], keyed by sik". And "For the mandatory-to-implement
integrity and confidentiality algorithms defined in this specification,
processing the first two (2) constants will generate the require amount of
keying material." We decided to use K1 as our HMAC key for the generation
of authentication codes (integrity checking). Furthermore, we are using
all 20 bytes of K1.
* IPMIv2 compliant BMCs are supposed to support 20 byte passwords, as well
store metadata describing whether the password was stored as a 16 byte or
20 byte class password. We do not currently support 20 byte passwords. It
should be noted that there are obvious mistakes in the SET USER PASSWORD
command specification, as it mentions the ability to query for 16/20 byte
password status, but the packet format does not support this.
* The IPMIv2 specification describes a type of login called a "role only
login." This feature allows a user to login providing only a requested
privilege level and a password. We do not currently support this feature.
Supporting this feature would only require the ability to specify
username/privilege lookups in the RAKP 1 message sent from ipmitool. We
currently specify the use of username only lookups for authentication.
* In the IPMIv2 packet description in table 13-8 of the IPMv2
specification, there are two fields that are rather ambiguous in meaning.
The fields are "Pad Length" and "Next Header". Although neither field is
listed as belonging to the IPMIv2 packet format, we include/expect them
both in our IPMIv2 packets. Are rationale is 1) the Next Headers field's
comment states what the value of that field should be for IPMIv2, and 2)
for the most part the ASF and IPMIv2 fields seem to parallel each other,
and we feel that the Pad Length and Next Header fields were left out of the
IPMIv2 column by mistake.
* The GET CHANNEL CIPHER SUITES command documentation seems to have
mistakes. The "start of record" byte is stated to be either 0x30 or 0x31,
whereas the detailed description in table 22-18 leads us to believe that
this byte should really be 0xC0 or 0xC1. Also the description of bits 5:0
in the start of record byte should probably be 00_0000 rather than 00_000.

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_ASF_H
#define IPMI_ASF_H
#include <ipmitool/helper.h>
#include "lanplus.h"
#define ASF_RMCP_IANA 0x000011be
#define ASF_TYPE_PING 0x80
#define ASF_TYPE_PONG 0x40
static const struct valstr asf_type_vals[] __attribute__((unused)) = {
{ 0x10, "Reset" },
{ 0x11, "Power-up" },
{ 0x12, "Unconditional Power-down" },
{ 0x13, "Power Cycle" },
{ 0x40, "Presence Pong" },
{ 0x41, "Capabilities Response" },
{ 0x42, "System State Response" },
{ 0x80, "Presence Ping" },
{ 0x81, "Capabilities Request" },
{ 0x82, "System State Request" },
{ 0x00, NULL }
};
/* ASF message header */
struct asf_hdr {
unsigned long iana;
unsigned char type;
unsigned char tag;
unsigned char __reserved;
unsigned char len;
} __attribute__((packed));
int handle_asf(struct ipmi_intf * intf, unsigned char * data, int data_len);
#endif /* IPMI_ASF_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_LANPLUS_H
#define IPMI_LANPLUS_H
#include <ipmitool/ipmi.h>
#define IPMI_LANPLUS_PORT 0x26f
/*
* RAKP return codes. These values come from table 13-15 of the IPMI v2
* specification.
*/
#define IPMI_RAKP_STATUS_NO_ERRORS 0x00
#define IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_SESSION 0x01
#define IPMI_RAKP_STATUS_INVALID_SESSION_ID 0x02
#define IPMI_RAKP_STATUS_INVALID_PAYLOAD_TYPE 0x03
#define IPMI_RAKP_STATUS_INVALID_AUTHENTICATION_ALGORITHM 0x04
#define IPMI_RAKP_STATUS_INVALID_INTEGRITTY_ALGORITHM 0x05
#define IPMI_RAKP_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD 0x06
#define IPMI_RAKP_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD 0x07
#define IPMI_RAKP_STATUS_INACTIVE_SESSION_ID 0x08
#define IPMI_RAKP_STATUS_INVALID_ROLE 0x09
#define IPMI_RAKP_STATUS_UNAUTHORIZED_ROLE_REQUESTED 0x0A
#define IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_ROLE 0x0B
#define IPMI_RAKP_STATUS_INVALID_NAME_LENGTH 0x0C
#define IPMI_RAKP_STATUS_UNAUTHORIZED_NAME 0x0D
#define IPMI_RAKP_STATUS_UNAUTHORIZED_GUID 0x0E
#define IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE 0x0F
#define IPMI_RAKP_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM 0x10
#define IPMI_RAKP_STATUS_NO_CIPHER_SUITE_MATCH 0x11
#define IPMI_RAKP_STATUS_ILLEGAL_PARAMTER 0x12
#define IPMI_LAN_CHANNEL_1 0x07
#define IPMI_LAN_CHANNEL_2 0x06
#define IPMI_LAN_CHANNEL_E 0x0e
#define IPMI_LAN_TIMEOUT 2
#define IPMI_LAN_RETRY 4
#define IPMI_PRIV_CALLBACK 1
#define IPMI_PRIV_USER 2
#define IPMI_PRIV_OPERATOR 3
#define IPMI_PRIV_ADMIN 4
#define IPMI_PRIV_OEM 5
/* From table 13-17 of the IPMI v2 specification */
#define IPMI_AUTH_RAKP_NONE 0x00
#define IPMI_AUTH_RAKP_HMAC_SHA1 0x01
#define IPMI_AUTH_RAKP_HMAC_MD5 0x02
/* From table 13-18 of the IPMI v2 specification */
#define IPMI_INTEGRITY_NONE 0x00
#define IPMI_INTEGRITY_HMAC_SHA1_96 0x01
#define IPMI_INTEGRITY_HMAC_MD5_128 0x02
#define IPMI_INTEGRITY_MD5_128 0x03
/* From table 13-19 of the IPMI v2 specfication */
#define IPMI_CRYPT_NONE 0x00
#define IPMI_CRYPT_AES_CBC_128 0x01
#define IPMI_CRYPT_XRC4_128 0x02
#define IPMI_CRYPT_XRC4_40 0x03
#define IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE 0x10
/* Session message offsets, from table 13-8 of the v2 specification */
#define IMPI_LANPLUS_OFFSET_AUTHTYPE 0x04
#define IMPI_LANPLUS_OFFSET_PAYLOAD_TYPE 0x05
#define IMPI_LANPLUS_OFFSET_SESSION_ID 0x06
#define IMPI_LANPLUS_OFFSET_SEQUENCE_NUM 0x0A
#define IMPI_LANPLUS_OFFSET_PAYLOAD_SIZE 0x0E
#define IPMI_LANPLUS_OFFSET_PAYLOAD 0x10
#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
/*
* TODO: these are wild guesses and should be checked
*/
#define IPMI_MAX_CONF_HEADER_SIZE 0x20
#define IPMI_MAX_PAYLOAD_SIZE 0x40 /* Includes confidentiality header/trailer */
#define IPMI_MAX_CONF_TRAILER_SIZE 0x20
#define IPMI_MAX_INTEGRITY_PAD_SIZE 0x20
#define IPMI_MAX_AUTH_CODE_SIZE 0x20
#define IPMI_REQUEST_MESSAGE_SIZE 0x07
#define IPMI_MAX_MAC_SIZE 0x14 /* The largest mac we ever expect to generate */
#define IPMI_SHA1_AUTHCODE_SIZE 0x0C
/*
*This is accurate, as long as we're only passing 1 auth algorithm,
* one integrity algorithm, and 1 encyrption alogrithm
*/
#define IPMI_OPEN_SESSION_REQUEST_SIZE 32
#define IPMI_RAKP1_MESSAGE_SIZE 43
#define IPMI_RAKP3_MESSAGE_MAX_SIZE 28
#define IPMI_MAX_USER_NAME_LENGTH 16
extern const struct valstr ipmi_privlvl_vals[];
extern const struct valstr ipmi_authtype_vals[];
extern struct ipmi_session lan_session;
struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
int ipmi_lanplus_open(struct ipmi_intf * intf);
void ipmi_lanplus_close(struct ipmi_intf * intf);
int ipmiv2_lan_ping(struct ipmi_intf * intf);
int lanplus_intf_setup(struct ipmi_intf ** intf);
#endif /*IPMI_LAN_H*/

View File

@ -0,0 +1,835 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <assert.h>
#include "lanplus.h"
#include "lanplus_crypt.h"
#include "lanplus_crypt_impl.h"
/*
* lanplus_rakp2_hmac_matches
*
* param session holds all the state data that we need to generate the hmac
* param hmac is the HMAC sent by the BMC in the RAKP 2 message
*
* The HMAC was generated [per RFC2404] from :
*
* SIDm - Remote console session ID
* SIDc - BMC session ID
* Rm - Remote console random number
* Rc - BMC random number
* GUIDc - BMC guid
* ROLEm - Requested privilege level (entire byte)
* ULENGTHm - Username length
* <UNAMEm> - Username (absent for null user names)
*
* generated by using Kuid. I am aware that the subscripts on the values
* look backwards, but that's the way they are written in the specification.
*
* If the authentication algorithm is IPMI_AUTH_RAKP_NONE, we return success.
*
* return 0 on success (the authcode matches)
* 1 on failure (the authcode does not match)
*/
int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
const unsigned char * bmc_mac)
{
char * buffer;
int bufferLength, i;
unsigned char mac[20];
int macLength;
unsigned int SIDm_lsbf, SIDc_lsbf;
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
return 1;
/* We don't yet support other alogrithms */
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
bufferLength =
4 + /* SIDm */
4 + /* SIDc */
16 + /* Rm */
16 + /* Rc */
16 + /* GUIDc */
1 + /* ROLEm */
1 + /* ULENGTHm */
strlen(session->username); /* optional */
buffer = malloc(bufferLength);
/*
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
* multibyte numbers in use.
*/
/* SIDm */
SIDm_lsbf = session->v2_data.console_id;
#if WORDS_BIGENDIAN
SIDm_lsbf = BSWAP_32(SIDm_lsbf);
#endif
memcpy(buffer, &SIDm_lsbf, 4);
/* SIDc */
SIDc_lsbf = session->v2_data.bmc_id;
#if WORDS_BIGENDIAN
SIDc_lsbf = BSWAP_32(SIDc_lsbf);
#endif
memcpy(buffer + 4, &SIDc_lsbf, 4);
/* Rm */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
buffer[8 + i] = session->v2_data.console_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
buffer[8 + i] = session->v2_data.console_rand[i];
#endif
/* Rc */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
buffer[24 + i] = session->v2_data.bmc_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
buffer[24 + i] = session->v2_data.bmc_rand[i];
#endif
/* GUIDc */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
buffer[40 + i] = session->v2_data.bmc_guid[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
buffer[40 + i] = session->v2_data.bmc_guid[i];
#endif
/* ROLEm */
buffer[56] = session->v2_data.requested_role;
/* ULENGTHm */
buffer[57] = strlen(session->username);
/* UserName [optional] */
for (i = 0; i < buffer[57]; ++i)
buffer[58 + i] = session->username[i];
if (verbose > 2)
{
printbuf(buffer, bufferLength, ">> rakp2 mac input buffer");
printbuf((char*)(session->authcode), IPMI_AUTHCODE_BUFFER_SIZE, ">> rakp2 mac key");
}
/*
* The buffer is complete. Let's hash.
*/
lanplus_HMAC(session->v2_data.auth_alg,
session->authcode,
(session->authcode[IPMI_AUTHCODE_BUFFER_SIZE] == 0?
strlen(session->authcode): IPMI_AUTHCODE_BUFFER_SIZE),
buffer,
bufferLength,
mac,
&macLength);
free(buffer);
if (verbose > 2)
{
printbuf(mac, macLength, ">> rakp2 mac as computed by the remote console");
}
return (memcmp(bmc_mac, mac, macLength) == 0);
}
/*
* lanplus_rakp4_hmac_matches
*
* param session holds all the state data that we need to generate the hmac
* param hmac is the HMAC sent by the BMC in the RAKP 4 message
*
* The HMAC was generated [per RFC2404] from :
*
* Rm - Remote console random number
* SIDc - BMC session ID
* GUIDc - BMC guid
*
* generated by using SIK (the session integrity key). I am aware that the
* subscripts on the values look backwards, but that's the way they are
* written in the specification.
*
* If the authentication algorithm is IPMI_AUTH_RAKP_NONE, we return success.
*
* return 0 on success (the authcode matches)
* 1 on failure (the authcode does not match)
*/
int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
const unsigned char * bmc_mac)
{
char * buffer;
int bufferLength, i;
unsigned char mac[20];
int macLength;
unsigned int SIDm_lsbf, SIDc_lsbf;
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
return 1;
/* We don't yet support other alogrithms */
assert(session->v2_data.auth_alg == IPMI_INTEGRITY_HMAC_SHA1_96);
bufferLength =
16 + /* Rm */
4 + /* SIDc */
16; /* GUIDc */
buffer = (char*)malloc(bufferLength);
/*
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
* multibyte numbers in use.
*/
/* Rm */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
buffer[i] = session->v2_data.console_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
buffer[i] = session->v2_data.console_rand[i];
#endif
/* SIDc */
SIDc_lsbf = session->v2_data.bmc_id;
#if WORDS_BIGENDIAN
SIDc_lsbf = BSWAP_32(SIDc_lsbf);
#endif
memcpy(buffer + 16, &SIDc_lsbf, 4);
/* GUIDc */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
buffer[i + 20] = session->v2_data.bmc_guid[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
buffer[i + 20] = session->v2_data.bmc_guid[i];
#endif
/*
* The buffer is complete. Let's hash.
*/
lanplus_HMAC(session->v2_data.auth_alg,
session->v2_data.sik,
20,
buffer,
bufferLength,
mac,
&macLength);
free(buffer);
assert(macLength == 20);
return (memcmp(bmc_mac, mac, 12) == 0);
}
/*
* lanplus_generate_rakp3_auth_code
*
* This auth code is an HMAC generated with :
*
* Rc - BMC random number
* SIDm - Console session ID
* ROLEm - Requested privilege level (entire byte)
* ULENGTHm - Username length
* <USERNAME> - Usename (absent for null usernames)
*
* The key used to generated the MAC is Kuid
*
* I am aware that the subscripts look backwards, but that is the way they are
* written in the spec.
*
* param output_buffer [out] will hold the generated MAC
* param session [in] holds all the state data we need to generate the auth code
* param mac_length [out] will be set to the length of the auth code
*
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_rakp3_authcode(char * output_buffer,
const struct ipmi_session * session,
unsigned int * mac_length)
{
int ret = 0;
int input_buffer_length, i;
char * input_buffer;
unsigned int SIDm_lsbf;
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
{
*mac_length = 0;
return 0;
}
/* We don't yet support other alogrithms */
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
input_buffer_length =
16 + /* Rc */
4 + /* SIDm */
1 + /* ROLEm */
1 + /* ULENGTHm */
strlen(session->username);
input_buffer = malloc(input_buffer_length);
/*
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
* multibyte numbers in use.
*/
/* Rc */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
input_buffer[i] = session->v2_data.bmc_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
input_buffer[i] = session->v2_data.bmc_rand[i];
#endif
/* SIDm */
SIDm_lsbf = session->v2_data.console_id;
#if WORDS_BIGENDIAN
SIDm_lsbf = BSWAP_32(SIDm_lsbf);
#endif
memcpy(input_buffer + 16, &SIDm_lsbf, 4);
/* ROLEm */
input_buffer[20] = session->v2_data.requested_role;
/* ULENGTHm */
input_buffer[21] = strlen(session->username);
/* USERNAME */
for (i = 0; i < input_buffer[21]; ++i)
input_buffer[22 + i] = session->username[i];
lanplus_HMAC(session->v2_data.auth_alg,
session->authcode,
(session->authcode[IPMI_AUTHCODE_BUFFER_SIZE - 1] == 0?
strlen(session->authcode): IPMI_AUTHCODE_BUFFER_SIZE),
input_buffer,
input_buffer_length,
output_buffer,
mac_length);
free(input_buffer);
return ret;
}
/*
* lanplus_generate_sik
*
* Generate the session integrity key (SIK) used for integrity checking
* during the IPMI v2 / RMCP+ session
*
* This session integrity key is a HMAC generated with :
*
* Rm - Console generated random number
* Rc - BMC generated random number
* ROLEm - Requested privilege level (entire byte)
* ULENGTHm - Username length
* <USERNAME> - Usename (absent for null usernames)
*
* The key used to generated the SIK is Kg if Kg is not null (two-key logins are
* enabled). Otherwise Kuid (the user authcode) is used as the key to genereate
* the SIK.
*
* I am aware that the subscripts look backwards, but that is the way they are
* written in the spec.
*
* param session [in/out] contains our input and output fields.
*
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_sik(struct ipmi_session * session)
{
char * input_buffer;
int input_buffer_length, i;
char * input_key;
int input_key_length;
int mac_length;
memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE);
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
return 0;
/* We don't yet support other alogrithms */
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
input_buffer_length =
16 + /* Rm */
16 + /* Rc */
1 + /* ROLEm */
1 + /* ULENGTHm */
strlen(session->username);
input_buffer = malloc(input_buffer_length);
/*
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
* multibyte numbers in use.
*/
/* Rm */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
input_buffer[i] = session->v2_data.console_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
input_buffer[i] = session->v2_data.console_rand[i];
#endif
/* Rc */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
input_buffer[16 + i] = session->v2_data.bmc_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
input_buffer[16 + i] = session->v2_data.bmc_rand[i];
#endif
/* ROLEm */
input_buffer[32] = session->v2_data.requested_role;
/* ULENGTHm */
input_buffer[33] = strlen(session->username);
/* USERNAME */
for (i = 0; i < input_buffer[33]; ++i)
input_buffer[34 + i] = session->username[i];
if (session->v2_data.kg[0])
{
/* We will be hashing with Kg */
/*
* TODO: Section 13.31 of the IPMI v2 spec describes the SIK creation
* using Kg. It specifies that Kg should not be truncated, but I
* do not know what is meant by that.
*/
printf("lanplus_generate_sik: We dont yet support hashing with Kg");
assert(0);
input_key = session->v2_data.kg;
input_key_length = strlen(session->v2_data.kg);
}
else
{
/* We will be hashing with Kuid */
input_key = session->authcode;
input_key_length = (session->authcode[IPMI_AUTHCODE_BUFFER_SIZE - 1] == 0?
strlen(session->authcode): IPMI_AUTHCODE_BUFFER_SIZE);
}
lanplus_HMAC(session->v2_data.auth_alg,
input_key,
input_key_length,
input_buffer,
input_buffer_length,
session->v2_data.sik,
&mac_length);
free(input_buffer);
assert(mac_length == 20);
/*
* The key MAC generated is 20 bytes, but we will only be using the first
* 12 for SHA1 96
*/
if (verbose >= 2)
printbuf(session->v2_data.sik, 20, "Generated session integrity key");
return 0;
}
/*
* lanplus_generate_k1
*
* Generate K1, the key presumably used to generate integrity authcodes
*
* We use the authentication algorithm to generated the HMAC, using
* the session integrity key (SIK) as our key.
*
* param session [in/out].
*
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_k1(struct ipmi_session * session)
{
unsigned int mac_length;
unsigned char CONST_1[] =
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
memcpy(session->v2_data.k1, CONST_1, 20);
else
{
lanplus_HMAC(session->v2_data.auth_alg,
session->v2_data.sik,
20, /* SIK length */
CONST_1,
20,
session->v2_data.k1,
&mac_length);
assert(mac_length == 20);
}
if (verbose >= 2)
printbuf(session->v2_data.k1, 20, "Generated K1");
return 0;
}
/*
* lanplus_generate_k2
*
* Generate K2, the key used for RMCP+ AES encryption.
*
* We use the authentication algorithm to generated the HMAC, using
* the session integrity key (SIK) as our key.
*
* param session [in/out].
*
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_k2(struct ipmi_session * session)
{
unsigned int mac_length;
unsigned char CONST_2[] =
{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
memcpy(session->v2_data.k2, CONST_2, 20);
else
{
lanplus_HMAC(session->v2_data.auth_alg,
session->v2_data.sik,
20, /* SIK length */
CONST_2,
20,
session->v2_data.k2,
&mac_length);
assert(mac_length == 20);
}
if (verbose >= 2)
printbuf(session->v2_data.k2, 20, "Generated K2");
return 0;
}
/*
* lanplus_encrypt_payload
*
* Perform the appropriate encryption on the input data. Output the encrypted
* data to output, including the required confidentiality header and trailer.
* If the crypt_alg is IPMI_CRYPT_NONE, simply copy the input to the output and
* set bytes_written to input_length.
*
* param crypt_alg specifies the encryption algorithm (from table 13-19 of the
* IPMI v2 spec)
* param key is the used as input to the encryption algorithmf
* param input is the input data to be encrypted
* param input_length is the length of the input data to be encrypted
* param output is the cipher text generated by the encryption process
* param bytes_written is the number of bytes written during the encryption
* process
*
* returns 0 on success
* 1 on failure
*/
int lanplus_encrypt_payload(unsigned char crypt_alg,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned short * bytes_written)
{
unsigned char * padded_input;
unsigned int mod, i, bytes_encrypted;
unsigned char pad_length = 0;
if (crypt_alg == IPMI_CRYPT_NONE)
{
printf("NOT ENCRYPTING\n");
/* Just copy the input to the output */
//memcpy(output, input, input_length);
//printf("input_length : %d\n", input_length);
*bytes_written = input_length;
//printf("bytes_written : %d\n", *bytes_written);
return 0;
}
/* Currently, we only support AES */
assert(crypt_alg == IPMI_CRYPT_AES_CBC_128);
/*
* The input to the AES encryption algorithm has to be a multiple of the block
* size (16 bytes). The extra byte we are adding is the pad length byte.
*/
mod = (input_length + 1) % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE;
if (mod)
pad_length = IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE - mod;
padded_input = (unsigned char*)malloc(input_length + pad_length + 1);
memcpy(padded_input, input, input_length);
/* add the pad */
for (i = 0; i < pad_length; ++i)
padded_input[input_length + i] = i + 1;
/* add the pad length */
padded_input[input_length + pad_length] = pad_length;
/* Generate an initialization vector, IV, for the encryption process */
if (lanplus_rand(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE))
{
printf("lanplus_encrypt_payload: Error generating IV\n");
assert(0);
return 1;
}
if (verbose > 2)
printbuf(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, ">> Initialization vector");
lanplus_encrypt_aes_cbc_128(output, /* IV */
key, /* K2 */
padded_input, /* Data to encrypt */
input_length + pad_length + 1, /* Input length */
output + IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* output */
&bytes_encrypted); /* bytes written */
*bytes_written =
IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE + /* IV */
bytes_encrypted;
return 0;
}
/*
* lanplus_has_valid_auth_code
*
* Determine whether the packets authcode field is valid for packet.
*
* We always return success if any of the following are true.
* - this is not an IPMIv2 packet
* - the session is not yet active
* - the packet specifies that it is not authenticated
* - the integrity algorithm agreed upon during session creation is "none"
*
* The authcode is computed using the specified integrity algorithm starting
* with the AuthType / Format field, and ending with the field immediately
* preceeding the authcode itself.
*
* The key key used to generate the authcode MAC is K1.
*
* param rs holds the response structure.
* param session holds our session state, including our chosen algorithm, key, etc.
*
* returns 1 on success (authcode is valid)
* 0 on failure (autchode integrity check failed)
*/
int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
struct ipmi_session * session)
{
unsigned char * bmc_authcode;
unsigned char generated_authcode[IPMI_MAX_MAC_SIZE];
unsigned int generated_authcode_length;
if ((rs->session.authtype != IPMI_SESSION_AUTHTYPE_RMCP_PLUS) ||
(session->v2_data.session_state != LANPLUS_STATE_ACTIVE) ||
(! rs->session.bAuthenticated) ||
(session->v2_data.integrity_alg == IPMI_INTEGRITY_NONE))
return 1;
/* We only support SHA1-96 now */
assert(session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96);
/*
* For SHA1-96, the authcode will be the last 12 bytes in the packet
*/
bmc_authcode = rs->data + (rs->data_len - IPMI_SHA1_AUTHCODE_SIZE);
lanplus_HMAC(session->v2_data.integrity_alg,
session->v2_data.k1,
20,
rs->data + IMPI_LANPLUS_OFFSET_AUTHTYPE,
rs->data_len - IMPI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE,
generated_authcode,
&generated_authcode_length);
assert(generated_authcode_length == 20);
return (memcmp(bmc_authcode, generated_authcode, 12) == 0);
}
/*
* lanplus_decrypt_payload
*
*
* param input points to the beginning of the payload (which will be the IV if
* we are using AES)
* param payload_size [out] will be set to the size of the payload EXCLUDING
* padding
*
* returns 0 on success (we were able to successfully decrypt the packet)
* 1 on failure (we were unable to successfully decrypt the packet)
*/
int lanplus_decrypt_payload(unsigned char crypt_alg,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned short * payload_size)
{
unsigned char * decrypted_payload;
unsigned int bytes_decrypted;
if (crypt_alg == IPMI_CRYPT_NONE)
{
/* We are not encrypted. The paylaod size is is everything. */
*payload_size = input_length;
memmove(output, input, input_length);
return 0;
}
/* We only support AES */
assert(crypt_alg == IPMI_CRYPT_AES_CBC_128);
decrypted_payload = (unsigned char*)malloc(input_length);
lanplus_decrypt_aes_cbc_128(input, /* IV */
key, /* Key */
input +
IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* Data to decrypt */
input_length -
IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* Input length */
decrypted_payload, /* output */
&bytes_decrypted); /* bytes written */
if (bytes_decrypted != 0)
{
/* Success */
unsigned char conf_pad_length;
int i;
memmove(output,
decrypted_payload,
bytes_decrypted);
/*
* We have to determine the payload size, by substracting the padding, etc.
* The last byte of the decrypted payload is the confidentiality pad length.
*/
conf_pad_length = decrypted_payload[bytes_decrypted - 1];
*payload_size = bytes_decrypted - conf_pad_length - 1;
/*
* Extra test to make sure that the padding looks like it should (should start
* with 0x01, 0x02, 0x03, etc...
*/
for (i = 0; i < conf_pad_length; ++i)
{
if (decrypted_payload[*payload_size + i] == i)
{
printf("ERROR: Malformed payload padding\n");
assert(0);
}
}
}
else
{
printf("ERROR: lanplus_decrypt_aes_cbc_128 decryptd 0 bytes\n");
assert(0);
}
free(decrypted_payload);
return (bytes_decrypted == 0);
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_LANPLUS_CRYPT_H
#define IPMI_LANPLUS_CRYPT_H
#include <ipmitool/ipmi_intf.h>
/*
* See the implementation file for documentation
*/
int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
const unsigned char * hmac);
int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
const unsigned char * hmac);
int lanplus_generate_rakp3_authcode(char * buffer,
const struct ipmi_session * session,
unsigned int * auth_length);
int lanplus_generate_sik(struct ipmi_session * session);
int lanplus_generate_k1(struct ipmi_session * session);
int lanplus_generate_k2(struct ipmi_session * session);
int lanplus_encrypt_payload(unsigned char crypt_alg,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned short * bytesWritten);
int lanplus_decrypt_payload(unsigned char crypt_alg,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned short * payload_size);
int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
struct ipmi_session * session);
#endif /* IPMI_LANPLUS_CRYPT_H */

View File

@ -0,0 +1,292 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include "lanplus.h"
#include "lanplus_crypt_impl.h"
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <assert.h>
/*
* lanplus_seed_prng
*
* Seed our PRNG with the specified number of bytes from /dev/random
*
* param bytes specifies the number of bytes to read from /dev/random
*
* returns 0 on success
* 1 on failure
*/
int lanplus_seed_prng(unsigned int bytes)
{
if (! RAND_load_file("/dev/random", bytes))
return 1;
else
return 0;
}
/*
* lanplus_rand
*
* Generate a random number of the specified size
*
* param num_bytes [in] is the size of the random number to be
* generated
* param buffer [out] is where we will place our random number
*
* return 0 on success
* 1 on failure
*/
int
lanplus_rand(unsigned char * buffer, unsigned int num_bytes)
{
#define IPMI_LANPLUS_FAKE_RAND 1
#ifdef IPMI_LANPLUS_FAKE_RAND
/*
* This code exists so that we can easily find the generated random number
* in the hex dumps.
*/
int i;
for (i = 0; i < num_bytes; ++i)
buffer[i] = 0x70 | i;
return 0;
#else
return (! RAND_bytes(buffer, num_bytes));
#endif
}
/*
* lanplus_HMAC
*
* param mac specifies the algorithm to be used, currently only SHA1 is supported
* param key is the key used for HMAC generation
* param key_len is the lenght of key
* param d is the data to be MAC'd
* param n is the length of the data at d
* param md is the result of the HMAC algorithm
* param md_len is the length of md
*
* returns a pointer to md
*/
unsigned char *
lanplus_HMAC(unsigned char mac,
const void *key,
int key_len,
const unsigned char *d,
int n,
unsigned char *md,
unsigned int *md_len)
{
const EVP_MD *evp_md;
if ((mac == IPMI_AUTH_RAKP_HMAC_SHA1) ||
(mac == IPMI_INTEGRITY_HMAC_SHA1_96))
evp_md = EVP_sha1();
else
{
printf("Invalid mac type 0x%x in lanplus_HMAC\n", mac);
assert(0);
}
return HMAC(evp_md, key, key_len, d, n, md, md_len);
}
/*
* lanplus_encrypt_aes_cbc_128
*
* Encrypt with the AES CBC 128 algorithm
*
* param iv is the 16 byte initialization vector
* param key is the 16 byte key used by the AES algorithm
* param input is the data to be encrypted
* param input_length is the number of bytes to be encrypted. This MUST
* be a multiple of the block size, 16.
* param output is the encrypted output
* param bytes_written is the number of bytes written. This param is set
* to 0 on failure, or if 0 bytes were input.
*/
void
lanplus_encrypt_aes_cbc_128(const unsigned char * iv,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned int * bytes_written)
{
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
*bytes_written = 0;
if (input_length == 0)
return;
if (verbose > 2)
{
printbuf(iv, 16, "encrypting with this IV");
printbuf(key, 16, "encrypting with this key");
printbuf(input, input_length, "encrypting this data");
}
/*
* The default implementation adds a whole block of padding if the input
* data is perfectly aligned. We would like to keep that from happening.
* We have made a point to have our input perfectly padded.
*/
assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
if(!EVP_EncryptUpdate(&ctx, output, bytes_written, input, input_length))
{
/* Error */
*bytes_written = 0;
return;
}
else
{
unsigned int tmplen;
if(!EVP_EncryptFinal_ex(&ctx, output + *bytes_written, &tmplen))
{
*bytes_written = 0;
return; /* Error */
}
else
{
/* Success */
*bytes_written += tmplen;
EVP_CIPHER_CTX_cleanup(&ctx);
}
}
}
/*
* lanplus_decrypt_aes_cbc_128
*
* Decrypt with the AES CBC 128 algorithm
*
* param iv is the 16 byte initialization vector
* param key is the 16 byte key used by the AES algorithm
* param input is the data to be decrypted
* param input_length is the number of bytes to be decrypted. This MUST
* be a multiple of the block size, 16.
* param output is the decrypted output
* param bytes_written is the number of bytes written. This param is set
* to 0 on failure, or if 0 bytes were input.
*/
void
lanplus_decrypt_aes_cbc_128(const unsigned char * iv,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned int * bytes_written)
{
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
if (verbose > 2)
{
printbuf(iv, 16, "decrypting with this IV");
printbuf(key, 16, "decrypting with this key");
printbuf(input, input_length, "decrypting this data");
}
*bytes_written = 0;
if (input_length == 0)
return;
/*
* The default implementation adds a whole block of padding if the input
* data is perfectly aligned. We would like to keep that from happening.
* We have made a point to have our input perfectly padded.
*/
assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
if(!EVP_DecryptUpdate(&ctx, output, bytes_written, input, input_length))
{
/* Error */
printf("ERROR: decrypt update failed\n");
*bytes_written = 0;
return;
}
else
{
unsigned int tmplen;
if(!EVP_DecryptFinal_ex(&ctx, output + *bytes_written, &tmplen))
{
char buffer[1000];
ERR_error_string(ERR_get_error(), buffer);
printf("the ERR error %s\n", buffer);
printf("ERROR: decrypt final failed\n");
*bytes_written = 0;
return; /* Error */
}
else
{
/* Success */
*bytes_written += tmplen;
EVP_CIPHER_CTX_cleanup(&ctx);
}
}
if (verbose > 2)
printbuf(output, *bytes_written, "decrypted this data");
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_LANPLUS_CRYPT_IMPL_H
#define IPMI_LANPLUS_CRYPT_IMPL_H
int
lanplus_seed_prng(unsigned int bytes);
int
lanplus_rand(unsigned char * buffer, unsigned int num_bytes);
unsigned char *
lanplus_HMAC(unsigned char mac, const void *key, int key_len,
const unsigned char *d, int n, unsigned char *md,
unsigned int *md_len);
void
lanplus_encrypt_aes_cbc_128(const unsigned char * iv,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned int * bytes_written);
void
lanplus_decrypt_aes_cbc_128(const unsigned char * iv,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned int * bytes_written);
#endif /* IPMI_LANPLUS_CRYPT_IMPL_H */

View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include "lanplus.h"
#include "lanplus_dump.h"
extern const struct valstr ipmi_rakp_return_codes[];
extern const struct valstr ipmi_priv_levels[];
extern const struct valstr ipmi_auth_algorithms[];
extern const struct valstr ipmi_integrity_algorithms[];
extern const struct valstr ipmi_encryption_algorithms[];
#define DUMP_PREFIX_INCOMING "<< "
void lanplus_dump_open_session_response(const struct ipmi_rs * rsp)
{
printf("%sOPEN SESSION RESPONSE\n", DUMP_PREFIX_INCOMING);
printf("%s Message tag : 0x%02x\n",
DUMP_PREFIX_INCOMING,
rsp->payload.open_session_response.message_tag);
printf("%s RMCP+ status : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.open_session_response.rakp_return_code,
ipmi_rakp_return_codes));
printf("%s Maximum privilege level : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.open_session_response.max_priv_level,
ipmi_priv_levels));
printf("%s Console Session ID : 0x%08lx\n",
DUMP_PREFIX_INCOMING,
rsp->payload.open_session_response.console_id);
printf("%s BMC Session ID : 0x%08lx\n",
DUMP_PREFIX_INCOMING,
rsp->payload.open_session_response.bmc_id);
printf("%s Negotiated authenticatin algorithm : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.open_session_response.auth_alg,
ipmi_auth_algorithms));
printf("%s Negotiated integrity algorithm : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.open_session_response.integrity_alg,
ipmi_integrity_algorithms));
printf("%s Negotiated encryption algorithm : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.open_session_response.crypt_alg,
ipmi_encryption_algorithms));
printf("\n");
}
void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, unsigned char auth_alg)
{
int i;
printf("%sRAKP 2 MESSAGE\n", DUMP_PREFIX_INCOMING);
printf("%s Message tag : 0x%02x\n",
DUMP_PREFIX_INCOMING,
rsp->payload.rakp2_message.message_tag);
printf("%s RMCP+ status : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.rakp2_message.rakp_return_code,
ipmi_rakp_return_codes));
printf("%s Console Session ID : 0x%08lx\n",
DUMP_PREFIX_INCOMING,
rsp->payload.rakp2_message.console_id);
printf("%s BMC random number : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 16; ++i)
printf("%02x", rsp->payload.rakp2_message.bmc_rand[i]);
printf("\n");
printf("%s BMC GUID : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 16; ++i)
printf("%02x", rsp->payload.rakp2_message.bmc_guid[i]);
printf("\n");
switch(auth_alg)
{
case IPMI_AUTH_RAKP_NONE:
printf("%s Key exchange auth code : none\n", DUMP_PREFIX_INCOMING);
break;
case IPMI_AUTH_RAKP_HMAC_SHA1:
printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 20; ++i)
printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
printf("\n");
break;
case IPMI_AUTH_RAKP_HMAC_MD5:
printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 16; ++i)
printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
printf("\n");
break;
default:
printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
}
printf("\n");
}
void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, unsigned char auth_alg)
{
int i;
printf("%sRAKP 4 MESSAGE\n", DUMP_PREFIX_INCOMING);
printf("%s Message tag : 0x%02x\n",
DUMP_PREFIX_INCOMING,
rsp->payload.rakp2_message.message_tag);
printf("%s RMCP+ status : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.rakp2_message.rakp_return_code,
ipmi_rakp_return_codes));
printf("%s Console Session ID : 0x%08lx\n",
DUMP_PREFIX_INCOMING,
rsp->payload.rakp2_message.console_id);
printf("%s BMC random number : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 16; ++i)
printf("%02x", rsp->payload.rakp2_message.bmc_rand[i]);
printf("\n");
printf("%s BMC GUID : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 16; ++i)
printf("%02x", rsp->payload.rakp2_message.bmc_guid[i]);
printf("\n");
switch(auth_alg)
{
case IPMI_AUTH_RAKP_NONE:
printf("%s Key exchange auth code : none\n", DUMP_PREFIX_INCOMING);
break;
case IPMI_AUTH_RAKP_HMAC_SHA1:
printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 12; ++i)
printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
printf("\n");
break;
case IPMI_AUTH_RAKP_HMAC_MD5:
printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 12; ++i)
printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
printf("\n");
break;
default:
printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
}
printf("\n");
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_LANPLUS_DUMP_H
#define IPMI_LANPLUS_DUMP_H
#include <ipmitool/ipmi_intf.h>
/* See the implementation file for documentation */
void lanplus_dump_open_session_response(const struct ipmi_rs * rsp);
void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, unsigned char auth_alg);
#endif /* IPMI_LANPLUS_DUMP_H */

View File

@ -0,0 +1,60 @@
#include "lanplus.h"
const struct valstr ipmi_rakp_return_codes[] = {
{ IPMI_RAKP_STATUS_NO_ERRORS, "no errors" },
{ IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_SESSION, "insufficient resources for session" },
{ IPMI_RAKP_STATUS_INVALID_SESSION_ID, "invalid session ID" },
{ IPMI_RAKP_STATUS_INVALID_PAYLOAD_TYPE, "invalid payload type" },
{ IPMI_RAKP_STATUS_INVALID_AUTHENTICATION_ALGORITHM, "invalid authentication algorithm" },
{ IPMI_RAKP_STATUS_INVALID_INTEGRITTY_ALGORITHM, "invalid integrity algorithm" },
{ IPMI_RAKP_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD, "no matching authentication algorithm"},
{ IPMI_RAKP_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD, "no matching integrity payload" },
{ IPMI_RAKP_STATUS_INACTIVE_SESSION_ID, "inactive session ID" },
{ IPMI_RAKP_STATUS_INVALID_ROLE, "invalid role" },
{ IPMI_RAKP_STATUS_UNAUTHORIZED_ROLE_REQUESTED, "unauthorized role requested" },
{ IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_ROLE, "insufficient resources for role" },
{ IPMI_RAKP_STATUS_INVALID_NAME_LENGTH, "invalid name length" },
{ IPMI_RAKP_STATUS_UNAUTHORIZED_NAME, "unauthorized name" },
{ IPMI_RAKP_STATUS_UNAUTHORIZED_GUID, "unauthorized GUID" },
{ IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE, "invlalid integrity check value" },
{ IPMI_RAKP_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM, "invalid confidentiality algorithm" },
{ IPMI_RAKP_STATUS_NO_CIPHER_SUITE_MATCH, "no matching cipher suite" },
{ IPMI_RAKP_STATUS_ILLEGAL_PARAMTER, "illegal parameter" },
{ 0, 0 },
};
const struct valstr ipmi_priv_levels[] = {
{ IPMI_PRIV_CALLBACK, "callback" },
{ IPMI_PRIV_USER, "user" },
{ IPMI_PRIV_OPERATOR, "operator" },
{ IPMI_PRIV_ADMIN, "admin" },
{ IPMI_PRIV_OEM, "oem" },
{ 0, 0 },
};
const struct valstr ipmi_auth_algorithms[] = {
{ IPMI_AUTH_RAKP_NONE, "none" },
{ IPMI_AUTH_RAKP_HMAC_SHA1, "hmac_sha1" },
{ IPMI_AUTH_RAKP_HMAC_MD5, "hmac_md5" },
{ 0, 0 },
};
const struct valstr ipmi_integrity_algorithms[] = {
{ IPMI_INTEGRITY_NONE, "none" },
{ IPMI_INTEGRITY_HMAC_SHA1_96, "hmac_sha1_96" },
{ IPMI_INTEGRITY_HMAC_MD5_128, "hmac_md5_128" },
{ IPMI_INTEGRITY_MD5_128 , "md5_128" },
{ 0, 0 },
};
const struct valstr ipmi_encryption_algorithms[] = {
{ IPMI_CRYPT_NONE, "none" },
{ IPMI_CRYPT_AES_CBC_128, "aes_cbc_128" },
{ IPMI_CRYPT_XRC4_128, "xrc4_128" },
{ IPMI_CRYPT_XRC4_40, "xrc4_40" },
{ 0, 0 },
};

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_RMCP_H
#define IPMI_RMCP_H
#include <ipmitool/helper.h>
#include "lanplus.h"
#define RMCP_VERSION_1 0x06
#define RMCP_UDP_PORT 0x26f /* port 623 */
#define RMCP_UDP_SECURE_PORT 0x298 /* port 664 */
#define RMCP_TYPE_MASK 0x80
#define RMCP_TYPE_NORM 0x00
#define RMCP_TYPE_ACK 0x01
static const struct valstr rmcp_type_vals[] __attribute__((unused)) = {
{ RMCP_TYPE_NORM, "Normal RMCP" },
{ RMCP_TYPE_ACK, "RMCP ACK" },
{ 0, NULL }
};
#define RMCP_CLASS_MASK 0x1f
#define RMCP_CLASS_ASF 0x06
#define RMCP_CLASS_IPMI 0x07
#define RMCP_CLASS_OEM 0x08
static const struct valstr rmcp_class_vals[] __attribute__((unused)) = {
{ RMCP_CLASS_ASF, "ASF" },
{ RMCP_CLASS_IPMI, "IPMI" },
{ RMCP_CLASS_OEM, "OEM" },
{ 0, NULL }
};
/* RMCP message header */
struct rmcp_hdr {
unsigned char ver;
unsigned char __reserved;
unsigned char seq;
unsigned char class;
} __attribute__((packed));
int handle_rmcp(struct ipmi_intf * intf, unsigned char * data, int data_len);
#endif /* IPMI_RMCP_H */