diff --git a/SOURCES/ipmitool-1.8.13-bmc-snmp.patch b/SOURCES/ipmitool-1.8.13-bmc-snmp.patch
new file mode 100644
index 0000000..1fa1b71
--- /dev/null
+++ b/SOURCES/ipmitool-1.8.13-bmc-snmp.patch
@@ -0,0 +1,359 @@
+From f48ce96e7fd0d2fe198845f0e2bd76f95d221fb3 Mon Sep 17 00:00:00 2001
+From: Charles Rose <charles_rose@dell.com>
+Date: Thu, 12 Dec 2013 16:10:11 -0500
+Subject: [PATCH] Incorporate upstream comments to #289, add whitespace, other
+ cleanup
+
+---
+ contrib/bmc-snmp-proxy | 130 +++++++++++++++++++++++++++++--------------------
+ 1 file changed, 76 insertions(+), 54 deletions(-)
+
+diff --git a/contrib/bmc-snmp-proxy b/contrib/bmc-snmp-proxy
+index 1704ef3..98479b9 100644
+--- a/contrib/bmc-snmp-proxy
++++ b/contrib/bmc-snmp-proxy
+@@ -3,7 +3,7 @@
+ #
+ # bmc-snmp-proxy:	Set SNMP proxy to BMC (Baseboard Management Controller)
+ #
+-# version:	0.6
++# version:	0.62
+ #
+ # Authors:	Charles Rose <charles_rose@dell.com>
+ #		Jordan Hargrave <jordan_hargrave@dell.com>
+@@ -20,9 +20,9 @@
+ SYSCONF_DIR="/etc/sysconfig"
+ CONFIG="${SYSCONF_DIR}/bmc-snmp-proxy"
+ 
+-SNMPD_LOCAL_CONF_DIR="/etc/snmp/bmc"
+-SNMPD_LOCAL_CONF="${SNMPD_LOCAL_CONF_DIR}/snmpd.local.conf"
+-TRAPD_LOCAL_CONF="${SNMPD_LOCAL_CONF_DIR}/snmptrapd.local.conf"
++SNMPD_BMC_CONF_DIR="/etc/snmp/bmc"
++SNMPD_BMC_CONF="${SNMPD_BMC_CONF_DIR}/snmpd.local.conf"
++TRAPD_BMC_CONF="${SNMPD_BMC_CONF_DIR}/snmptrapd.local.conf"
+ 
+ TRAPD_CONF="/etc/snmp/snmptrapd.conf"
+ 
+@@ -57,14 +57,16 @@ bmc_info_exists()
+ 	else
+ 		RETVAL=2
+ 	fi
++
+ 	return $RETVAL
+ }
+ 
+ check_snmp()
+ {
+-	if [ ! -d /etc/snmp ] && [ ! -x /usr/sbin/snmpd ]; then
++	if [ ! -d /etc/snmp ] || [ ! -x /usr/sbin/snmpd ]; then
+ 		RETVAL=12
+ 	fi
++
+ 	return $RETVAL
+ }
+ 
+@@ -77,11 +79,12 @@ write_snmp_conf()
+ 	printf "###############################################\n"
+ 	printf "# Automatically created by %s #\n" "${SCRIPT_NAME}"
+ 	printf "###############################################\n"
+-	printf "view bmcview included %s 80\n" "${BMC_OID}"
+-	printf "com2sec -Cn bmc_ctx bmc_sec default bmc_cmty\n"
+-	printf "group bmc_grp v1 bmc_sec\n"
+-	printf "access bmc_grp bmc_ctx any noauth exact bmcview none none\n"
+-	printf "proxy -Cn bmc_ctx -v 1 %s\n" "${PROXY_TOKEN}"
++	printf "#view bmcview included %s 80\n" "${BMC_OID}"
++	printf "#com2sec -Cn bmc_ctx bmc_sec default bmc_cmty\n"
++	printf "#group bmc_grp v1 bmc_sec\n"
++	printf "#access bmc_grp bmc_ctx any noauth exact bmcview none none\n"
++	printf "#proxy -Cn bmc_ctx -v 1 %s\n" "${PROXY_TOKEN}"
++	printf "proxy -v 1 %s\n" "${PROXY_TOKEN}"
+ 	printf "###############################################\n"
+ }
+ 
+@@ -92,6 +95,7 @@ valid_ip()
+ 
+         printf -- "%s" "${1}"| grep -Eq \
+ 		"^${octet}\\.${octet}\\.${octet}\\.${octet}$"
++
+         return $?
+ }
+ 
+@@ -112,37 +116,38 @@ set_snmp_proxy()
+ 	if check_vars; then
+ 		PROXY_TOKEN="-c ${BMC_COMMUNITY} ${BMC_IPv4} ${BMC_OID}"
+ 
+-		if [ ! -d ${SNMPD_LOCAL_CONF_DIR} ] && \
+-			 	mkdir ${SNMPD_LOCAL_CONF_DIR}; then
+-			write_snmp_conf > ${SNMPD_LOCAL_CONF}
+-			[ $? -ne 0 ] && RETVAL=4
++		if [ -d ${SNMPD_BMC_CONF_DIR} ]; then
++			write_snmp_conf > ${SNMPD_BMC_CONF} || RETVAL=4
+ 		fi
+ 	else
+ 		RETVAL=3
+ 	fi
+ }
+ 
+-
+ set_snmpd_conf_path()
+ {
+-	for SYSCONF in ${SYSCONF_DIR}/snmp*d;
++	if [ ! -d ${SNMPD_BMC_CONF_DIR} ]; then
++		mkdir ${SNMPD_BMC_CONF_DIR} || RETVAL=7
++	fi
++
++	# We need SNMPCONFPATH set for both snmpd and snmptrapd
++	for sysconf in ${SYSCONF_DIR}/snmp*d;
+ 	do
+-		if grep -q "${SNMPD_LOCAL_CONF_DIR}" "${SYSCONF}" > \
+-				 /dev/null 2>&1; then
+-			continue
+-		else
+-			printf "SNMPCONFPATH=%s\n" "${SNMPD_LOCAL_CONF_DIR}" \
+-				>> ${SYSCONF} || RETVAL=7
++		if ! grep -q "^SNMPCONFPATH.*${SNMPD_BMC_CONF_DIR}" \
++			"${sysconf}" > /dev/null 2>&1; then
++			printf "SNMPCONFPATH=/etc/snmp:%s\n" \
++				"${SNMPD_BMC_CONF_DIR}" >> ${sysconf} || \
++				RETVAL=7
+ 		fi
+ 	done
++
+ 	return $RETVAL
+ }
+ 
+ disable_snmp_proxy()
+ {
+-	if [ -f ${SNMPD_LOCAL_CONF} ]; then
+-		rm -f ${SNMPD_LOCAL_CONF}
+-		[ $? -ne 0 ] && RETVAL=5
++	if [ -f ${SNMPD_BMC_CONF} ]; then
++		rm -f ${SNMPD_BMC_CONF} || RETVAL=5
+ 	fi
+ }
+ #############################################################################
+@@ -152,6 +157,7 @@ disable_snmp_proxy()
+ pick_alert_dest()
+ {
+ 	test_ip="$1"
++	# We have 4 IPv4 and 4 IPv6 alert dest. We will set IPv4 for now.
+ 	for ALERT_DEST in `seq 1 4`
+ 	do
+ 		temp_ip=$(${IPMITOOL} lan alert print ${CHANNEL} ${ALERT_DEST}\
+@@ -165,12 +171,12 @@ pick_alert_dest()
+ set_alert_dest_ip()
+ {
+ 	${IPMITOOL} lan alert set ${CHANNEL} ${ALERT_DEST} ipaddr ${1} \
+-		retry 4 type pet >/dev/null 2>&1
+-	[ $? -ne 0 ] && RETVAL=8
++		retry 4 type pet >/dev/null 2>&1 || RETVAL=8
+ }
+ 
+-bmc_alert_dest()
++config_bmc_alert_dest()
+ {
++	# call with enable|disable
+ 	# Pick the first active LAN channel
+         for CHANNEL in `seq 1 14`
+         do
+@@ -180,12 +186,12 @@ bmc_alert_dest()
+ 
+ 	# If TRAPD_IP is already set as an alert dest,
+ 	if pick_alert_dest "${TRAPD_IP}"; then
+-		# reset: reset it if we are called with reset
+-		[ "${1}" = "reset" ] && \
++		# disable: reset it if we are called with disable
++		[ "${1}" = "disable" ] && \
+ 			set_alert_dest_ip "0.0.0.0"
+ 	# else, find the next free alert dest,
+ 	elif pick_alert_dest "0.0.0.0"; then
+-		[ "${1}" = "reset" ] && \
++		[ "${1}" = "disable" ] && \
+ 			return $RETVAL
+ 		# set: the TRAPD_IP
+ 		set_alert_dest_ip "${TRAPD_IP}"
+@@ -193,42 +199,54 @@ bmc_alert_dest()
+ 		# No free alert destinations
+ 		RETVAL=9
+ 	fi
++
+ 	return $RETVAL
+ }
+ 
+-set_ipmi_alert()
++set_ipmi_pef()
+ {
+-	${IPMITOOL} lan set ${CHANNEL} alert "${1}" >/dev/null 2>&1
+-	[ $? -ne 0 ] && RETVAL=10
++	# Needs ipmitool-1.8.13 + patches
++	${IPMITOOL} pef setpolicy ${ALERT_DEST} "${1}" >/dev/null 2>&1 || \
++		RETVAL=10
+ }
+ 
+ get_host_ip()
+ {
+-	# Get host's IP that the BMC can reach.
++	# Get host's IP that the BMC can reach. This is at best a hack.
+ 	IFACE=$(/usr/sbin/ip -o -f inet address |awk '!/: lo/ {print $2}')
++
+ 	for dev in ${IFACE}
+ 	do
+-		ping -c 1 -I ${dev} ${BMC_IPv4} > /dev/null 2>&1
++		temp_ping=$(ping -c 1 -I ${dev} ${BMC_IPv4})
++		[ $? -ne 0 ] && continue
++
++		printf -- "%s" "$temp_ping"| awk 'NR==1{print $5}' && break
+ 	done
+ }
+ 
+ config_bmc_alert()
+ {
++	# Do two things
++	# Set/Reset TRAP IP in BMC
++	# Enable/Disable PEF alerting in BMC for TRAP
++
+ 	# Get Host's IP that the BMC can send traps to
+ 	TRAPD_IP=$(get_host_ip)
+ 
+ 	# Set Host's IP as the alert destination in the BMC
+-	valid_ip ${TRAPD_IP} && bmc_alert_dest "${ACTION}"
++	valid_ip ${TRAPD_IP} && config_bmc_alert_dest "${ACTION}"
++
++	# Enable/Disable alerting on the LAN channel
++	[ $RETVAL -eq 0 ] && set_ipmi_pef "${ACTION}"
+ 
+-	# Enable alerting on the LAN channel
+-	[ $RETVAL -eq 0 ] && set_ipmi_alert "${ACTION}"
++	return $RETVAL
+ }
+ 
+ write_trapd_conf()
+ {
+ 	printf "###############################################\n"
+ 	printf "# Automatically created by %s #\n" "${SCRIPT_NAME}"
+-	printf "forward %s %s\n" "${BMC_OID}*" "${FORWARD_HOST}"
++	printf "forward default %s\n" "${FORWARD_HOST}"
+ 	printf "###############################################\n"
+ }
+ 
+@@ -236,10 +254,9 @@ config_trapd()
+ {
+ 	# Proceed only if snmptrapd is available on the system
+ 	if [ -f ${TRAPD_CONF} ]; then
+-		write_trapd_conf > ${TRAPD_LOCAL_CONF}
+-		[ $? -ne 0 ] && RETVAL=11
++		write_trapd_conf > ${TRAPD_BMC_CONF} || RETVAL=11
+ 	else
+-		return 1
++		RETVAL=11
+ 	fi
+ }
+ 
+@@ -249,6 +266,7 @@ trap_sink_exists()
+ 	# multiple
+ 	FORWARD_HOST=$(awk '/^trap.*sink/{print $2}; /^informsink/{print $2}' \
+ 			/etc/snmp/snmpd*conf | head -1)
++
+ 	if [ -z "${FORWARD_HOST}" ]; then
+ 		# there is no trapsink setup.
+ 		return 1
+@@ -261,19 +279,20 @@ trap_sink_exists()
+ trap_forward()
+ {
+ 	NO_TRAP=0
+-	ACTION=${1} # set or reset
++	ACTION=${1} # enable or disable
+ 
+-	if [ "${ACTION}" = "set" ]; then
++	if [ "${ACTION}" = "enable" ]; then
+ 		# Get trapd config,
+ 		if trap_sink_exists; then
+-			config_trapd && config_bmc_alert
++			config_bmc_alert && config_trapd
+ 		else
+ 			# exit silently if there is no sink
+ 			NO_TRAP=1
+ 		fi
+ 	else
+-		if [ -f ${TRAPD_LOCAL_CONF} ]; then
+-			rm -f ${TRAPD_LOCAL_CONF} >/dev/null 2>&1
++		if [ -f ${TRAPD_BMC_CONF} ]; then
++			rm -f ${TRAPD_BMC_CONF} >/dev/null 2>&1
++			config_bmc_alert
+ 		else
+ 			NO_TRAP=1
+ 		fi
+@@ -288,7 +307,6 @@ service_reload()
+ 		service $1 reload
+ 		[ $? -ne 0 ] && RETVAL=6
+ 	fi
+-	return
+ }
+ 
+ #############################################################################
+@@ -296,11 +314,12 @@ start()
+ {
+ 	if bmc_info_exists && check_snmp; then
+ 		touch ${LOCKFILE}
++
+ 		set_snmpd_conf_path && set_snmp_proxy
+ 		[ $RETVAL -eq 0 ] && service_reload snmpd
+ 
+ 		if [ "${TRAP_FORWARD}" = "yes" ]; then
+-			trap_forward "set"
++			trap_forward "enable"
+ 			[ $RETVAL -eq 0 ] && [ $NO_TRAP -eq 0 ] && \
+ 				service_reload snmptrapd
+ 		fi
+@@ -316,10 +335,11 @@ stop()
+ 		[ $RETVAL -eq 0 ] && service_reload snmpd
+ 
+ 		if [ "${TRAP_FORWARD}" = "yes" ]; then
+-			trap_forward "reset"
++			trap_forward "disable"
+ 			[ $RETVAL -eq 0 ] && [ $NO_TRAP -eq 0 ] && \
+ 				service_reload snmptrapd
+ 		fi
++
+ 		rm -f ${LOCKFILE}
+ 	fi
+ }
+@@ -329,12 +349,13 @@ status()
+ {
+ 	eval_gettext "${SCRIPT_NAME}: snmp proxy to BMC is "
+ 	# Checking for lockfile is better.
+-	#if grep -q "^proxy" "${SNMPD_LOCAL_CONF}" > /dev/null 2>&1 ; then
++	#if grep -q "^proxy" "${SNMPD_BMC_CONF}" > /dev/null 2>&1 ; then
+ 	if [ -f ${LOCKFILE} ]; then
+ 		eval_gettext "set"
+ 	else
+ 		eval_gettext "not set"
+ 	fi
++
+ 	echo
+ 	RETVAL=0
+ }
+@@ -360,10 +381,10 @@ case "$RETVAL" in
+ 	0|1) ;;
+ 	2) eval_gettext "${SCRIPT_NAME}: failed to read ${BMC_INFO} " 1>&2 ;;
+ 	3) eval_gettext "${SCRIPT_NAME}: failed to get proxy config." 1>&2 ;;
+-	4) eval_gettext "${SCRIPT_NAME}: failed to set ${SNMPD_LOCAL_CONF}." 1>&2 ;;
++	4) eval_gettext "${SCRIPT_NAME}: failed to set ${SNMPD_BMC_CONF}." 1>&2 ;;
+ 	5) eval_gettext "${SCRIPT_NAME}: failed to disable snmp proxy." 1>&2 ;;
+ 	6) eval_gettext "${SCRIPT_NAME}: failed to reload snmpd." 1>&2 ;;
+-	7) eval_gettext "${SCRIPT_NAME}: failed to update ${SYSCONF}." 1>&2 ;;
++	7) eval_gettext "${SCRIPT_NAME}: failed to set snmpd config." 1>&2 ;;
+ 	8) eval_gettext "${SCRIPT_NAME}: failed to set IPMI alert dest." 1>&2 ;;
+ 	9) eval_gettext "${SCRIPT_NAME}: no free IPMI alert dest." 1>&2 ;;
+ 	10) eval_gettext "${SCRIPT_NAME}: failed to set IPMI PEF." 1>&2 ;;
+@@ -375,6 +396,7 @@ esac
+ if [ ${RETVAL} -gt 1 ]; then
+         eval_gettext " Return code: ${RETVAL}"; echo
+ fi
++
+ exit ${RETVAL}
+ #############################################################################
+ # end of file
+-- 
+1.8.3.1
+
diff --git a/SOURCES/ipmitool-1.8.13-set-kg-key1.patch b/SOURCES/ipmitool-1.8.13-set-kg-key1.patch
new file mode 100644
index 0000000..4dd005c
--- /dev/null
+++ b/SOURCES/ipmitool-1.8.13-set-kg-key1.patch
@@ -0,0 +1,433 @@
+diff -up ./doc/ipmitool.1.kg1 ./doc/ipmitool.1
+--- ./doc/ipmitool.1.kg1	2014-03-05 09:04:19.334742088 +0100
++++ ./doc/ipmitool.1	2014-03-05 09:02:53.011524309 +0100
+@@ -371,6 +371,20 @@ Configure user access information on the
+ 
+ Displays the list of cipher suites supported for the given
+ application (ipmi or sol) on the given channel.
++.TP
++\fIsetkg\fP <\fIhex\fP|\fIplain\fP> <\fBkey\fP> [<\fBchannel\fR>]
++.br
++
++Sets K_g key to given value. Use \fIplain\fP to specify \fBkey\fR as simple ASCII string.
++Use \fIhex\fP to specify \fBkey\fR as sequence of hexadecimal codes of ASCII charactes.
++I.e. following two examples are equivalent:
++
++.RS
++ipmitool channel setkg plain PASSWORD
++
++ipmitool channel setkg hex 50415353574F5244
++.RE
++
+ .RE
+ .RE
+ .TP 
+diff -up ./include/ipmitool/helper.h.kg1 ./include/ipmitool/helper.h
+--- ./include/ipmitool/helper.h.kg1	2014-03-05 09:42:21.546499783 +0100
++++ ./include/ipmitool/helper.h	2014-03-05 09:43:28.095667676 +0100
+@@ -58,6 +58,8 @@
+ # define IPMI_UID_MAX 63
+ #endif
+ 
++#define IPMI_KG_BUFFER_SIZE       21 /* key plus null byte */
++
+ struct ipmi_intf;
+ 
+ struct valstr {
+@@ -100,6 +102,8 @@ uint8_t ipmi_csum(uint8_t * d, int s);
+ FILE * ipmi_open_file(const char * file, int rw);
+ void ipmi_start_daemon(struct ipmi_intf *intf);
+ 
++unsigned char *ipmi_parse_hex(const char *str);
++
+ #define ipmi_open_file_read(file)	ipmi_open_file(file, 0)
+ #define ipmi_open_file_write(file)	ipmi_open_file(file, 1)
+ 
+diff -up ./include/ipmitool/ipmi_channel.h.kg1 ./include/ipmitool/ipmi_channel.h
+--- ./include/ipmitool/ipmi_channel.h.kg1	2014-03-05 09:04:41.707798532 +0100
++++ ./include/ipmitool/ipmi_channel.h	2014-03-05 09:10:00.770603481 +0100
+@@ -48,7 +48,10 @@
+ #define IPMI_GET_USER_NAME             0x46
+ #define IPMI_SET_USER_PASSWORD         0x47
+ #define IPMI_GET_CHANNEL_CIPHER_SUITES 0x54
++#define IPMI_SET_CHANNEL_SECURITY_KEYS 0x56
+ 
++#define IPMI_KG_KEY_ID  1
++#define IPMI_SET_CHANNEL_SECURITY_KEYS_OP_SET 1
+ 
+ /*
+  * The Get Authentication Capabilities response structure
+@@ -246,6 +249,48 @@ struct set_user_access_data {
+ #endif
+ } ATTRIBUTE_PACKING;
+ #ifdef HAVE_PRAGMA_PACK
++#pragma pack(0)
++#endif
++
++#ifdef HAVE_PRAGMA_PACK
++#pragma pack(1)
++#endif
++struct set_channel_security_keys_req {
++#if WORDS_BIGENDIAN
++	uint8_t __reserved1                     :4;
++	uint8_t channel                         :4;
++	uint8_t __reserved2                     :6;
++	uint8_t operation                       :2;
++	uint8_t key_id;
++	unsigned char key_value[IPMI_KG_BUFFER_SIZE-1]; /* we don't want space for '\0' at the end */
++#else
++	uint8_t channel                         :4;
++	uint8_t __reserved1                     :4;
++	uint8_t operation                       :2;
++	uint8_t __reserved2                     :6;
++	uint8_t key_id;
++	unsigned char key_value[IPMI_KG_BUFFER_SIZE-1]; /* we don't want space for '\0' at the end */
++#endif
++} ATTRIBUTE_PACKING;
++#ifdef HAVE_PRAGMA_PACK
++#pragma pack(0)
++#endif
++
++#ifdef HAVE_PRAGMA_PACK
++#pragma pack(1)
++#endif
++struct set_channel_security_keys_rsp {
++#if WORDS_BIGENDIAN
++	uint8_t __reserved1                     :6;
++	uint8_t lock_status                     :2;
++	unsigned char key_value; /* just the first character, use &key_value to explore the rest */
++#else
++	uint8_t lock_status                     :2;
++	uint8_t __reserved1                     :6;
++	unsigned char key_value; /* just the first character, use &key_value to explore the rest */
++#endif
++} ATTRIBUTE_PACKING;
++#ifdef HAVE_PRAGMA_PACK
+ #pragma pack(0)
+ #endif
+ 
+diff -up ./include/ipmitool/ipmi_intf.h.kg1 ./include/ipmitool/ipmi_intf.h
+--- ./include/ipmitool/ipmi_intf.h.kg1	2014-03-05 09:10:45.363715984 +0100
++++ ./include/ipmitool/ipmi_intf.h	2014-03-05 09:11:27.483822244 +0100
+@@ -60,7 +60,7 @@ enum LANPLUS_SESSION_STATE {
+ 
+ #define IPMI_AUTHCODE_BUFFER_SIZE 20
+ #define IPMI_SIK_BUFFER_SIZE      20
+-#define IPMI_KG_BUFFER_SIZE       21 /* key plus null byte */
++/* XXX: remove or modify  # d e fine IPMI_KG_BUFFER_SIZE       21 /* key plus null byte */
+ 
+ struct ipmi_session {
+ 	uint8_t hostname[64];
+diff -up ./lib/helper.c.kg1 ./lib/helper.c
+--- ./lib/helper.c.kg1	2014-03-05 09:11:41.417857400 +0100
++++ ./lib/helper.c	2014-03-05 09:15:11.318386949 +0100
+@@ -667,6 +667,68 @@ ipmi_start_daemon(struct ipmi_intf *intf
+ 	dup(0);
+ }
+ 
++/* ipmi_parse_hex - convert hexadecimal numbers to ascii string
++ *                  Input string must be composed of two-characer hexadecimal numbers.
++ *                  There is no separator between the numbers. Each number results in one character
++ *                  of the converted string.
++ *
++ *                  Example: ipmi_parse_hex("50415353574F5244") returns 'PASSWORD'
++ *
++ * @param str:  input string. It must contain only even number of '0'-'9','a'-'f' and 'A-F' characters.
++ * @returns converted ascii string
++ * @returns NULL on error
++ */
++unsigned char *
++ipmi_parse_hex(const char *str)
++{
++	const char * p;
++	unsigned char * out, *q;
++	unsigned char b = 0;
++	int shift = 4;
++
++	if (strlen(str) == 0)
++		return NULL;
++
++	if (strlen(str) % 2 != 0) {
++		lprintf(LOG_ERR, "Number of hex_kg characters is not even");
++		return NULL;
++	}
++
++	if (strlen(str) > (IPMI_KG_BUFFER_SIZE-1)*2) {
++		lprintf(LOG_ERR, "Kg key is too long");
++		return NULL;
++	}
++
++	out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char));
++	if (out == NULL) {
++		lprintf(LOG_ERR, "malloc failure");
++		return NULL;
++	}
++
++	for (p = str, q = out; *p; p++) {
++		if (!isxdigit(*p)) {
++			lprintf(LOG_ERR, "Kg_hex is not hexadecimal number");
++			free(out);
++			return NULL;
++		}
++
++		if (*p < 'A') /* it must be 0-9 */
++			b = *p - '0';
++		else /* it's A-F or a-f */
++			b = (*p | 0x20) - 'a' + 10; /* convert to lowercase and to 10-15 */
++
++		*q = *q + b << shift;
++		if (shift)
++			shift = 0;
++		else {
++			shift = 4;
++			q++;
++		}
++	}
++
++	return out;
++}
++
+ /* is_fru_id - wrapper for str-2-int FRU ID conversion. Message is printed
+  * on error.
+  * FRU ID range: <0..255>
+diff -up ./lib/ipmi_channel.c.kg1 ./lib/ipmi_channel.c
+--- ./lib/ipmi_channel.c.kg1	2014-03-05 09:15:28.655430688 +0100
++++ ./lib/ipmi_channel.c	2014-03-05 09:37:19.367737427 +0100
+@@ -786,6 +786,90 @@ ipmi_current_channel_medium(struct ipmi_
+ 	return ipmi_get_channel_medium(intf, 0xE);
+ }
+ 
++int 
++ipmi_set_channel_security_keys (struct ipmi_intf *intf, uint8_t channel,
++				const char *method, const char *key)
++{
++	unsigned char* decoded_key = NULL;
++	struct ipmi_rs *rsp;
++	struct ipmi_rq req;
++	struct set_channel_security_keys_req req_data;
++
++	/* convert provided key to array of bytes */
++	if (strcmp(method, "hex") == 0) {
++		if (strlen(key) > (IPMI_KG_BUFFER_SIZE-1)*2) {
++			lprintf(LOG_ERR, "Provided key is too long, max. length is 20 bytes");
++			printf_channel_usage();
++			return -1;
++		}
++		decoded_key = ipmi_parse_hex(key);
++		if (decoded_key == NULL) {
++			/* something went bad, ipmi_parse_hex already reported the error */
++			return -1;
++		}
++	} else if (strcmp(method, "plain") == 0) {
++		if (strlen(key) > IPMI_KG_BUFFER_SIZE-1) {
++			lprintf(LOG_ERR, "Provided key is too long, max. length is 20 bytes");
++			printf_channel_usage();
++			return -1;
++		}
++
++		decoded_key = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char));
++		if (decoded_key == NULL) {
++			lprintf(LOG_ERR, "Cannot allocate memory");
++			return -1;
++		}
++		strncpy(decoded_key, key, IPMI_KG_BUFFER_SIZE-1);
++	} else {
++		printf_channel_usage();
++		return -1;
++	}
++
++	/* assemble and send request to set kg key */
++	memset(&req_data, 0, sizeof(req_data));
++	req_data.channel = channel;
++	req_data.operation = IPMI_SET_CHANNEL_SECURITY_KEYS_OP_SET;
++	req_data.key_id = IPMI_KG_KEY_ID;
++	memcpy(req_data.key_value, decoded_key, IPMI_KG_BUFFER_SIZE-1);
++	free(decoded_key);
++
++	memset(&req, 0, sizeof(req));
++	req.msg.netfn = IPMI_NETFN_APP;
++	req.msg.cmd = IPMI_SET_CHANNEL_SECURITY_KEYS;
++	req.msg.data = (uint8_t*) &req_data;
++	req.msg.data_len = sizeof(req_data);
++
++	rsp = intf->sendrecv(intf, &req);
++	if (rsp == NULL) {
++		lprintf(LOG_ERR, "Set Channel Security Keys command failed");
++		return -1;
++	}
++	if (rsp->ccode > 0) {
++		const char *error = NULL;
++		switch (rsp->ccode) {
++			case 0x80:
++				error = "Key is locked";
++				break;
++			case 0x81:
++				error = "Insufficient key bytes";
++				break;
++			case 0x82:
++				error = "Too many key bytes";
++				break;
++			case 0x83:
++				error = "Key value does not meet criteria for K_g key";
++				break;
++			default:
++				error = val2str(rsp->ccode, completion_code_vals);
++		}
++		lprintf(LOG_ERR, "Error setting security key: %X (%s)", rsp->ccode, error);
++		return -1;
++	}
++
++	lprintf(LOG_NOTICE, "Set Channel Security Keys command succeeded");
++	return 0;
++}
++
+ void
+ printf_channel_usage()
+ {
+@@ -795,6 +879,7 @@ printf_channel_usage()
+ 		"<user id> [callin=on|off] [ipmi=on|off] [link=on|off] [privilege=level]");
+ 	lprintf(LOG_NOTICE, "                  info      [channel number]");
+ 	lprintf(LOG_NOTICE, "                  getciphers <ipmi | sol> [channel]\n");
++	lprintf(LOG_NOTICE, "                  setkg hex|plain <key> [channel]\n");
+ 	lprintf(LOG_NOTICE, "Possible privilege levels are:");
+ 	lprintf(LOG_NOTICE, "   1   Callback level");
+ 	lprintf(LOG_NOTICE, "   2   User level");
+@@ -892,6 +977,21 @@ ipmi_channel_main(struct ipmi_intf * int
+ 								ch);
+ 		}
+ 	}
++	else if (strcmp(argv[0], "setkg") == 0)
++	{
++		if (argc < 3 || argc > 4)
++			printf_channel_usage();
++		else {
++			uint8_t ch = 0xe;
++			char *method = argv[1];
++			char *key = argv[2];
++			if (argc == 4) {
++				ch = (uint8_t)strtol(argv[3], NULL, 0);
++			}
++
++			retval = ipmi_set_channel_security_keys(intf, ch, method, key);
++		}
++	}
+ 	else
+ 	{
+ 		printf("Invalid CHANNEL command: %s\n", argv[0]);
+diff -up ./lib/ipmi_main.c.kg1 ./lib/ipmi_main.c
+--- ./lib/ipmi_main.c.kg1	2014-03-05 09:50:30.905734365 +0100
++++ ./lib/ipmi_main.c	2014-03-05 10:47:04.857296819 +0100
+@@ -275,69 +275,6 @@ void ipmi_catch_sigint()
+ 	exit(-1);
+ }
+ 
+-/* ipmi_parse_hex - convert hexadecimal numbers to ascii string
+- *                  Input string must be composed of two-characer hexadecimal numbers.
+- *                  There is no separator between the numbers. Each number results in one character
+- *                  of the converted string.
+- *
+- *                  Example: ipmi_parse_hex("50415353574F5244") returns 'PASSWORD'
+- *
+- * @param str:  input string. It must contain only even number of '0'-'9','a'-'f' and 'A-F' characters.
+- * @returns converted ascii string
+- * @returns NULL on error
+- */
+-static unsigned char *
+-ipmi_parse_hex(const char *str)
+-{
+-	const char * p;
+-	unsigned char * out, *q;
+-	unsigned char b = 0;
+-	int shift = 4;
+-
+-	if (strlen(str) == 0)
+-		return NULL;
+-
+-	if (strlen(str) % 2 != 0) {
+-		lprintf(LOG_ERR, "Number of hex_kg characters is not even");
+-		return NULL;
+-	}
+-
+-	if (strlen(str) > (IPMI_KG_BUFFER_SIZE-1)*2) {
+-		lprintf(LOG_ERR, "Kg key is too long");
+-		return NULL;
+-	}
+-
+-	out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char));
+-	if (out == NULL) {
+-		lprintf(LOG_ERR, "malloc failure");
+-		return NULL;
+-	}
+-
+-	for (p = str, q = out; *p; p++) {
+-		if (!isxdigit(*p)) {
+-			lprintf(LOG_ERR, "Kg_hex is not hexadecimal number");
+-			free(out);
+-			out = NULL;
+-			return NULL;
+-		}
+-
+-		if (*p < 'A') /* it must be 0-9 */
+-			b = *p - '0';
+-		else /* it's A-F or a-f */
+-			b = (*p | 0x20) - 'a' + 10; /* convert to lowercase and to 10-15 */
+-
+-		*q = *q + b << shift;
+-		if (shift)
+-			shift = 0;
+-		else {
+-			shift = 4;
+-			q++;
+-		}
+-	}
+-
+-	return out;
+-}
+-
+ /* ipmi_parse_options  -  helper function to handle parsing command line options
+  *
+  * @argc:	count of options
+@@ -521,11 +458,12 @@ ipmi_main(int argc, char ** argv,
+ 				free(kgkey);
+ 				kgkey = NULL;
+ 			}
+-			kgkey = strdup(optarg);
++			kgkey = calloc(IPMI_KG_BUFFER_SIZE, 1);
+ 			if (kgkey == NULL) {
+ 				lprintf(LOG_ERR, "%s: malloc failure", progname);
+ 				goto out_free;
+ 			}
++			strncpy(kgkey, optarg, IPMI_KG_BUFFER_SIZE);
+ 			break;
+ 		case 'K':
+ 			if ((tmp_env = getenv("IPMI_KGKEY"))) {
+@@ -533,11 +471,12 @@ ipmi_main(int argc, char ** argv,
+ 					free(kgkey);
+ 					kgkey = NULL;
+ 				}
+-				kgkey = strdup(tmp_env);
++				kgkey = calloc(IPMI_KG_BUFFER_SIZE, 1);
+ 				if (kgkey == NULL) {
+ 					lprintf(LOG_ERR, "%s: malloc failure", progname);
+ 					goto out_free;
+ 				}
++				strncpy(kgkey, tmp_env, IPMI_KG_BUFFER_SIZE);
+ 			} else {
+ 				lprintf(LOG_WARN, "Unable to read kgkey from environment");
+ 			}
+@@ -564,11 +503,14 @@ ipmi_main(int argc, char ** argv,
+ 					kgkey = NULL;
+ 				}
+ 				kgkey = strdup(tmp_pass);
+-				tmp_pass = NULL;
++				kgkey = calloc(IPMI_KG_BUFFER_SIZE, 1);
+ 				if (kgkey == NULL) {
+ 					lprintf(LOG_ERR, "%s: malloc failure", progname);
++					tmp_pass = NULL;
+ 					goto out_free;
+ 				}
++				strncpy(kgkey, tmp_pass, IPMI_KG_BUFFER_SIZE);
++				tmp_pass = NULL;
+ 			}
+ 			break;
+ 		case 'U':
diff --git a/SPECS/ipmitool.spec b/SPECS/ipmitool.spec
index 866022a..8481065 100644
--- a/SPECS/ipmitool.spec
+++ b/SPECS/ipmitool.spec
@@ -1,7 +1,7 @@
 Name:         ipmitool
 Summary:      Utility for IPMI control
 Version:      1.8.13
-Release:      3%{?dist}
+Release:      7%{?dist}
 License:      BSD
 Group:        System Environment/Base
 URL:          http://ipmitool.sourceforge.net/
@@ -36,6 +36,12 @@ Patch4: cxoem-jb-cx6.patch
 #Patch6: ipmitool-1.8.12-fipsman.patch
 # pending https://sourceforge.net/p/ipmitool/bugs/280/
 Patch7: ipmitool-1.8.13-dualbridgedoc.patch
+# pending http://sourceforge.net/p/ipmitool/bugs/289/
+Patch8: ipmitool-1.8.13-bmc-snmp.patch
+# todo
+Patch9: ipmitool-1.8.13-set-kg-key1.patch
+# todo
+#Patch10: ipmitool-1.8.11-set-kg-key2.patch
 
 %description
 This package contains a utility for interfacing with devices that support
@@ -91,6 +97,9 @@ for the host OS to use.
 #patch5 -p0 -b .fips
 #patch6 -p0 -b .fipsman
 %patch7 -p1 -b .dualbridgedoc
+%patch8 -p1 -b .bmcsnmp
+%patch9 -p1 -b .kg1
+#% p atch10 -p1 -b .kegkey2
 
 for f in AUTHORS ChangeLog; do
     iconv -f iso-8859-1 -t utf8 < ${f} > ${f}.utf8
@@ -182,6 +191,18 @@ install -Dm 755 contrib/bmc-snmp-proxy         %{buildroot}%{_libexecdir}/bmc-sn
 %{_libexecdir}/bmc-snmp-proxy
 
 %changelog
+* Wed Mar 05 2014 Ales Ledvinka <aledvink@redhat.com> - 1.8.13-7
+- Allow setting channel Kg key.
+
+* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 1.8.13-6
+- Mass rebuild 2014-01-24
+
+* Mon Jan 20 2014 Ales Ledvinka <aledvink@redhat.com> 1.8.13-5
+- bmc-snmp-proxy upstream bugfixes.
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 1.8.13-4
+- Mass rebuild 2013-12-27
+
 * Tue Nov  5 2013 Ales Ledvinka <aledvink@redhat.com> 1.8.13-3
 - Cleanup of dual bridge option.