All files / src/http zcl_abapgit_http_digest.clas.abap

68.86% Statements 115/167
100% Branches 0/0
0% Functions 0/2
68.86% Lines 115/167

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 1681x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                       1x 1x 1x                                                                                   1x  
CLASS zcl_abapgit_http_digest DEFINITION
  PUBLIC
  CREATE PUBLIC .
 
  PUBLIC SECTION.
 
    METHODS constructor
      IMPORTING
        !ii_client   TYPE REF TO if_http_client
        !iv_username TYPE string
        !iv_password TYPE string
      RAISING
        zcx_abapgit_exception.
    METHODS run
      IMPORTING
        !ii_client TYPE REF TO if_http_client
      RAISING
        zcx_abapgit_exception.
 
  PROTECTED SECTION.
  PRIVATE SECTION.
    DATA: mv_ha1      TYPE string,
          mv_username TYPE string,
          mv_realm    TYPE string,
          mv_qop      TYPE string,
          mv_nonce    TYPE string.
 
    CLASS-DATA: gv_nc TYPE n LENGTH 8.
 
    CLASS-METHODS:
      md5
        IMPORTING
                  iv_data        TYPE string
        RETURNING
                  VALUE(rv_hash) TYPE string
        RAISING   zcx_abapgit_exception.
 
    METHODS:
      hash
        IMPORTING
                  iv_qop             TYPE string
                  iv_nonce           TYPE string
                  iv_uri             TYPE string
                  iv_method          TYPE string
                  iv_cnonse          TYPE string
        RETURNING
                  VALUE(rv_response) TYPE string
        RAISING   zcx_abapgit_exception,
      parse
        IMPORTING
          ii_client TYPE REF TO if_http_client.
 
ENDCLASS.
 
 
 
CLASS ZCL_ABAPGIT_HTTP_DIGEST IMPLEMENTATION.
 
 
  METHOD constructor.
 
    parse( ii_client ).
 
    mv_ha1 = md5( |{ iv_username }:{ mv_realm }:{ iv_password }| ).
 
    mv_username = iv_username.
 
  ENDMETHOD.
 
 
  METHOD hash.
 
    DATA: lv_ha2 TYPE string.
 
 
    lv_ha2 = md5( |{ iv_method }:{ iv_uri }| ).
 
    ASSERT NOT iv_cnonse IS INITIAL.
 
    rv_response = md5( |{ mv_ha1 }:{ iv_nonce }:{ gv_nc }:{ iv_cnonse }:{ iv_qop }:{ lv_ha2 }| ).
 
  ENDMETHOD.
 
 
  METHOD md5.
 
    DATA lv_xstr TYPE xstring.
    DATA lv_hash TYPE xstring.
    DATA lv_empty TYPE xstring.
 
    lv_xstr = zcl_abapgit_convert=>string_to_xstring_utf8( iv_data ).
 
    TRY.
        cl_abap_hmac=>calculate_hmac_for_raw(
          EXPORTING
            if_algorithm   = 'MD5'
            if_key         = lv_empty
            if_data        = lv_xstr
          IMPORTING
            ef_hmacxstring = lv_hash ).
      CATCH cx_abap_message_digest.
        zcx_abapgit_exception=>raise( 'error calculating md5' ).
    ENDTRY.
 
    rv_hash = lv_hash.
    TRANSLATE rv_hash TO LOWER CASE.
 
  ENDMETHOD.
 
 
  METHOD parse.

    DATA: lv_value TYPE string.


    lv_value = ii_client->response->get_header_field( 'www-authenticate' ).

    FIND REGEX 'realm="([\w ]+)"' IN lv_value SUBMATCHES mv_realm.
    FIND REGEX 'qop="(\w+)"' IN lv_value SUBMATCHES mv_qop.
    FIND REGEX 'nonce="([\w=/+\$]+)"' IN lv_value SUBMATCHES mv_nonce.

  ENDMETHOD.
 
 
  METHOD run.

    DATA: lv_response TYPE string,
          lv_method   TYPE string,
          lv_cnonce   TYPE string,
          lv_uri      TYPE string,
          lv_auth     TYPE string.


    ASSERT NOT mv_nonce IS INITIAL.

    lv_method = ii_client->request->get_header_field( '~request_method' ).
    lv_uri = ii_client->request->get_header_field( '~request_uri' ).

    CALL FUNCTION 'GENERAL_GET_RANDOM_STRING'
      EXPORTING
        number_chars  = 24
      IMPORTING
        random_string = lv_cnonce.

    lv_response = hash(
      iv_qop    = mv_qop
      iv_nonce  = mv_nonce
      iv_uri    = lv_uri
      iv_method = lv_method
      iv_cnonse = lv_cnonce ).

* client response
    lv_auth = |Digest username="{ mv_username
      }", realm="{ mv_realm
      }", nonce="{ mv_nonce
      }", uri="{ lv_uri
      }", qop={ mv_qop
      }, nc={ gv_nc
      }, cnonce="{ lv_cnonce
      }", response="{ lv_response }"|.

    ii_client->request->set_header_field(
      name  = 'Authorization'
      value = lv_auth ).

  ENDMETHOD.
ENDCLASS.