mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 18:47:22 +00:00
add support for ipmiv2 with lanplus interface
from Jeremy Ellington
This commit is contained in:
parent
5750269c28
commit
f30ef24600
@ -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])
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
99
ipmitool/include/ipmitool/md5.h
Normal file
99
ipmitool/include/ipmitool/md5.h
Normal 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 */
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
* +--------------------+
|
||||
|
47
ipmitool/src/plugins/lanplus/Makefile.am
Normal file
47
ipmitool/src/plugins/lanplus/Makefile.am
Normal 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
|
||||
|
74
ipmitool/src/plugins/lanplus/README.lanplus
Normal file
74
ipmitool/src/plugins/lanplus/README.lanplus
Normal 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.
|
||||
|
73
ipmitool/src/plugins/lanplus/asf.h
Normal file
73
ipmitool/src/plugins/lanplus/asf.h
Normal 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 */
|
2720
ipmitool/src/plugins/lanplus/lanplus.c
Normal file
2720
ipmitool/src/plugins/lanplus/lanplus.c
Normal file
File diff suppressed because it is too large
Load Diff
151
ipmitool/src/plugins/lanplus/lanplus.h
Normal file
151
ipmitool/src/plugins/lanplus/lanplus.h
Normal 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*/
|
835
ipmitool/src/plugins/lanplus/lanplus_crypt.c
Normal file
835
ipmitool/src/plugins/lanplus/lanplus_crypt.c
Normal 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);
|
||||
}
|
||||
|
74
ipmitool/src/plugins/lanplus/lanplus_crypt.h
Normal file
74
ipmitool/src/plugins/lanplus/lanplus_crypt.h
Normal 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 */
|
292
ipmitool/src/plugins/lanplus/lanplus_crypt_impl.c
Normal file
292
ipmitool/src/plugins/lanplus/lanplus_crypt_impl.c
Normal 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");
|
||||
}
|
||||
|
70
ipmitool/src/plugins/lanplus/lanplus_crypt_impl.h
Normal file
70
ipmitool/src/plugins/lanplus/lanplus_crypt_impl.h
Normal 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 */
|
191
ipmitool/src/plugins/lanplus/lanplus_dump.c
Normal file
191
ipmitool/src/plugins/lanplus/lanplus_dump.c
Normal 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");
|
||||
}
|
||||
|
48
ipmitool/src/plugins/lanplus/lanplus_dump.h
Normal file
48
ipmitool/src/plugins/lanplus/lanplus_dump.h
Normal 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 */
|
60
ipmitool/src/plugins/lanplus/lanplus_strings.c
Normal file
60
ipmitool/src/plugins/lanplus/lanplus_strings.c
Normal 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 },
|
||||
};
|
||||
|
80
ipmitool/src/plugins/lanplus/rmcp.h
Normal file
80
ipmitool/src/plugins/lanplus/rmcp.h
Normal 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 */
|
Loading…
x
Reference in New Issue
Block a user