Signed-off-by: Piotr Jaroszyński <[email protected]>
---
 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

_______________________________________________
gPXE-devel mailing list
[email protected]
http://etherboot.org/mailman/listinfo/gpxe-devel

Reply via email to