[gPXE-devel] [PATCHv2 2/2] [iscsi] Add base64 support for CHAP.

Piotr Jaroszyński p.jaroszynski at gmail.com
Fri Apr 2 21:10:26 EDT 2010


Signed-off-by: Piotr Jaroszyński <p.jaroszynski at gmail.com>
---
 src/net/tcp/iscsi.c |   89 +++++++++++++++++++++++++++------------------------
 1 files changed, 47 insertions(+), 42 deletions(-)

diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c
index b13a107..c6708ae 100644
--- a/src/net/tcp/iscsi.c
+++ b/src/net/tcp/iscsi.c
@@ -35,6 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <gpxe/tcpip.h>
 #include <gpxe/settings.h>
 #include <gpxe/features.h>
+#include <gpxe/base64.h>
 #include <gpxe/iscsi.h>
 
 /** @file
@@ -731,6 +732,38 @@ static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
 	return 0;
 }
 
+static int iscsi_decode_hex ( const char * encoded, char * raw )
+{
+	char *endp;
+	char buf[3];
+	unsigned int i;
+
+	buf[2] = 0;
+
+	for ( i = 0 ; ( encoded[0] && encoded[1] ) ; encoded += 2, i++ ) {
+		memcpy ( buf, encoded, 2 );
+		raw[i] = strtoul ( buf, &endp, 16 );
+		if ( *endp != '\0' ) {
+			return -1;
+		}
+	}
+
+	return i;
+}
+
+static int iscsi_decode_large_binary ( const char * encoded, char * raw )
+{
+	if ( encoded[0] != '0' )
+		return -1;
+
+	if ( ( encoded[1] == 'x' ) || ( encoded[1] == 'X' ) )
+		return iscsi_decode_hex ( encoded + 2, raw );
+	if ( ( encoded[1] == 'b' ) || ( encoded[1] == 'B' ) )
+		return base64_decode ( encoded + 2, raw );
+
+	return -1;
+}
+
 /**
  * Handle iSCSI CHAP_C text value
  *
@@ -740,31 +773,17 @@ static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
  */
 static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi,
 				       const char *value ) {
-	char buf[3];
-	char *endp;
-	uint8_t byte;
 	unsigned int i;
+	char raw[ base64_decode_buf_len ( strlen ( value ) ) ];
+	int len;
 
-	/* Check and strip leading "0x" */
-	if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
+	if ( ( len = iscsi_decode_large_binary ( value, raw ) ) < 0 ) {
 		DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge \"%s\"\n",
 		       iscsi, value );
 		return -EPROTO_INVALID_CHAP_CHALLENGE;
 	}
-	value += 2;
 
-	/* Process challenge an octet at a time */
-	for ( ; ( value[0] && value[1] ) ; value += 2 ) {
-		memcpy ( buf, value, 2 );
-		buf[2] = 0;
-		byte = strtoul ( buf, &endp, 16 );
-		if ( *endp != '\0' ) {
-			DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge "
-			       "byte \"%s\"\n", iscsi, buf );
-			return -EPROTO_INVALID_CHAP_CHALLENGE;
-		}
-		chap_update ( &iscsi->chap, &byte, sizeof ( byte ) );
-	}
+	chap_update ( &iscsi->chap, raw, len );
 
 	/* Build CHAP response */
 	DBGC ( iscsi, "iSCSI %p sending CHAP response\n", iscsi );
@@ -821,11 +840,9 @@ static int iscsi_handle_chap_n_value ( struct iscsi_session *iscsi,
  */
 static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi,
 				       const char *value ) {
-	char buf[3];
-	char *endp;
-	uint8_t byte;
-	unsigned int i;
 	int rc;
+	char raw[ base64_decode_buf_len ( strlen ( value ) ) ];
+	size_t len;
 
 	/* Generate CHAP response for verification */
 	chap_finish ( &iscsi->chap );
@@ -843,38 +860,26 @@ static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi,
 		      ( sizeof ( iscsi->chap_challenge ) - 1 ) );
 	chap_respond ( &iscsi->chap );
 
-	/* Check and strip leading "0x" */
-	if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
+	if ( ( rc = iscsi_decode_large_binary ( value, raw ) ) < 0 ) {
 		DBGC ( iscsi, "iSCSI %p saw invalid CHAP response \"%s\"\n",
 		       iscsi, value );
 		return -EPROTO_INVALID_CHAP_RESPONSE;
 	}
-	value += 2;
+
+	len = rc;
 
 	/* Check CHAP response length */
-	if ( strlen ( value ) != ( 2 * iscsi->chap.response_len ) ) {
+	if ( len != iscsi->chap.response_len ) {
 		DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n",
 		       iscsi );
 		return -EPROTO_INVALID_CHAP_RESPONSE;
 	}
 
-	/* Process response an octet at a time */
-	for ( i = 0 ; ( value[0] && value[1] ) ; value += 2, i++ ) {
-		memcpy ( buf, value, 2 );
-		buf[2] = 0;
-		byte = strtoul ( buf, &endp, 16 );
-		if ( *endp != '\0' ) {
-			DBGC ( iscsi, "iSCSI %p saw invalid CHAP response "
-			       "byte \"%s\"\n", iscsi, buf );
-			return -EPROTO_INVALID_CHAP_RESPONSE;
-		}
-		if ( byte != iscsi->chap.response[i] ) {
-			DBGC ( iscsi, "iSCSI %p saw incorrect CHAP "
-			       "response\n", iscsi );
-			return -EACCES_INCORRECT_TARGET_PASSWORD;
-		}
+	if ( memcmp ( raw, iscsi->chap.response, len ) != 0 ) {
+		DBGC ( iscsi, "iSCSI %p saw incorrect CHAP "
+			"response\n", iscsi );
+		return -EACCES_INCORRECT_TARGET_PASSWORD;
 	}
-	assert ( i == iscsi->chap.response_len );
 
 	/* Mark session as authenticated */
 	iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK;
-- 
1.7.0.3



More information about the gPXE-devel mailing list