summaryrefslogtreecommitdiff
path: root/test/regression/web_test/http_digest_authentication.c
blob: 30a28010902a0a36378d9d460b28fb4994d52a50 (plain)
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/***************************************************************************/
/* Copyright (c) 2024 Microsoft Corporation                                */
/* Copyright (c) 2026 Eclipse ThreadX contributors                         */
/*                                                                         */
/* This program and the accompanying materials are made available under    */
/* the terms of the MIT License which is available at                      */
/* https://opensource.org/licenses/MIT.                                    */
/*                                                                         */
/* SPDX-License-Identifier: MIT                                            */
/***************************************************************************/


#define HTTP_MAX_BINARY_MD5              16
#define HTTP_MAX_ASCII_MD5               32
#define HTTP_SERVER_NONCE_SIZE           32
#define HTTP_MAX_RESOURCE                64

VOID http_hex_ascii_convert(CHAR *source, UINT source_length, CHAR *destination)
{

UINT    i,j;
CHAR    digit;


    /* Setup destination index.  */
    j =  0;

    /* Loop to process the entire source string.  */
    for (i = 0; i < source_length; i++)
    {

        /* Pickup the first nibble.  */
        digit =  (source[i] >> 4) & 0xF;

        /* Convert to ASCII and store.  */
        if (digit <= 9)
            destination[j++] =  (CHAR)(digit + '0');
        else
            destination[j++] =  (CHAR)(digit + 'a' - 10);

        /* Pickup the second nibble.  */
        digit =  source[i] & 0xF;

        /* Convert to ASCII and store.  */
        if (digit <= 9)
            destination[j++] =  (CHAR)(digit + '0');
        else
            destination[j++] =  (CHAR)(digit + 'a' - 10);
    }

    /* Finally, place a NULL in the destination string.  */
    destination[j] =  (CHAR) NX_NULL;
}

UINT http_nonce_retrieve(NX_PACKET *packet_ptr, CHAR *nonce)
{
UINT    length;
UINT    found;
CHAR    *buffer_ptr;

    found = NX_FALSE;
    length = 0;
    nonce[0] = NX_NULL;

    buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;

    while (((buffer_ptr + 6) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
    {

        /* Check for the uri token.  */
        if (((*(buffer_ptr) ==  'n') || (*(buffer_ptr) ==  'N')) &&
            ((*(buffer_ptr+1) ==  'o') || (*(buffer_ptr+1) ==  'O')) &&
            ((*(buffer_ptr+2) ==  'n') || (*(buffer_ptr+2) ==  'N')) &&
            ((*(buffer_ptr+3) ==  'c') || (*(buffer_ptr+3) ==  'C')) &&
            ((*(buffer_ptr+4) ==  'e') || (*(buffer_ptr+4) ==  'E')) &&
            (*(buffer_ptr+5) == '='))
        {

            /* Move the pointer up to the actual authorization string.  */
            buffer_ptr =  buffer_ptr + 6;
            found = NX_TRUE;

            break;
        }

        /* Move the pointer up to the next character.  */
        buffer_ptr++;
    }

    if (found == NX_FALSE)
    {
        return(NX_NOT_FOUND);
    }

    /* Now remove any extra blanks and quotes.  */
    while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
    {

        /* Move the pointer up one character.  */
        buffer_ptr++;
    }

    /* Now pickup the nonce string.  */
    length =  0;
    while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13) && (length < HTTP_SERVER_NONCE_SIZE))
    {

        /* Determine if the ending quote is present.  */
        if (*buffer_ptr == (CHAR) 0x22)
        {

            break;
        }

        /* Copy a character of the authorization string into the destination.  */
        nonce[length++] =  *buffer_ptr++;
    }

    nonce[length] = NX_NULL;
    return(NX_SUCCESS);
}

VOID http_digest_response_calculate(NX_MD5 *md5data, CHAR *username, CHAR *realm, CHAR *password, CHAR *nonce, CHAR *method, CHAR *uri, CHAR *nc, CHAR *cnonce, CHAR *result)
{

CHAR    md5_binary[HTTP_MAX_BINARY_MD5];
CHAR    ha1_string[HTTP_MAX_ASCII_MD5 + 1];
CHAR    ha2_string[HTTP_MAX_ASCII_MD5 + 1];
UINT    username_length;
UINT    password_length;
UINT    realm_length;
UINT    method_length;
UINT    uri_length;
UINT    nc_length;
UINT    cnonce_length;

    /* Get string length.  */
    username_length = strlen(username);
    password_length = strlen(password);
    realm_length = strlen(realm);
    method_length = strlen(method);
    uri_length = strlen(uri);
    nc_length = strlen(nc);
    cnonce_length = strlen(cnonce);


    /* Calculate the H(A1) portion of the digest.  */
    _nx_md5_initialize(md5data);
    _nx_md5_update(md5data, (unsigned char *) username, username_length);
    _nx_md5_update(md5data, (unsigned char *) ":", 1);
    _nx_md5_update(md5data, (unsigned char *) realm, realm_length);
    _nx_md5_update(md5data, (unsigned char *) ":", 1);
    _nx_md5_update(md5data, (unsigned char *) password, password_length);
    _nx_md5_digest_calculate(md5data, (unsigned char *) md5_binary);

    /* Convert this H(A1) portion to ASCII Hex representation.  */
    http_hex_ascii_convert(md5_binary, HTTP_MAX_BINARY_MD5, ha1_string);

    /* Make the H(A2) portion of the digest.  */
    _nx_md5_initialize(md5data);
    _nx_md5_update(md5data, (unsigned char *) method, method_length);
    _nx_md5_update(md5data, (unsigned char *) ":", 1);
    _nx_md5_update(md5data, (unsigned char *) uri, uri_length);
    _nx_md5_digest_calculate(md5data, (unsigned char *) md5_binary);

    /* Convert this H(A2) portion to ASCII Hex representation.  */
    http_hex_ascii_convert(md5_binary, HTTP_MAX_BINARY_MD5, ha2_string);

    /* Now make the final MD5 digest.  */
    _nx_md5_initialize(md5data);
    _nx_md5_update(md5data, (unsigned char *) ha1_string, sizeof(ha1_string) - 1);
    _nx_md5_update(md5data, (unsigned char *) ":", 1);
    _nx_md5_update(md5data, (unsigned char *) nonce, HTTP_SERVER_NONCE_SIZE);

    /* Start of Internet Explorer bug work-around.  */
    _nx_md5_update(md5data, (unsigned char *) ":", 1);
    _nx_md5_update(md5data, (unsigned char *) nc, nc_length);
    _nx_md5_update(md5data, (unsigned char *) ":", 1);
    _nx_md5_update(md5data, (unsigned char *) cnonce, cnonce_length);
    _nx_md5_update(md5data, (unsigned char *) ":auth", 5);
    /* End of Internet Explorer bug work-around.  */

    _nx_md5_update(md5data, (unsigned char *) ":", 1);
    _nx_md5_update(md5data, (unsigned char *) ha2_string, sizeof(ha2_string) - 1);
    _nx_md5_digest_calculate(md5data, (unsigned char *) md5_binary);

    /* Finally, convert the response back to an ASCII string and place in
       the destination.  */
    http_hex_ascii_convert(md5_binary, HTTP_MAX_BINARY_MD5, result);
}