1 /* This case tests digest authentication.
2 HA1 = MD5("name:NetX Duo HTTP demo:password")
3 = 01bb2595c9221423951ee86f3573b465
4 HA2 = MD5("GET:/index.htm")
5 = d4b1da8c7955d2e98bc56ffc93003b44
6 Response = MD5("01bb2595c9221423951ee86f3573b465:
7 nonce:
8 00000001:0a4f113b:auth:
9 d4b1da8c7955d2e98bc56ffc93003b44")
10 */
11 #include "tx_api.h"
12 #include "nx_api.h"
13 #include "fx_api.h"
14 #include "nx_web_http_client.h"
15 #include "nx_web_http_server.h"
16
17 extern void test_control_return(UINT);
18
19 #if !defined(NX_DISABLE_IPV4) && defined(NX_WEB_HTTP_DIGEST_ENABLE) && !defined(NX_WEB_HTTP_KEEPALIVE_DISABLE)
20
21 #include "http_digest_authentication.c"
22
23 #define DEMO_STACK_SIZE 4096
24
25 /* Set up FileX and file memory resources. */
26 static CHAR ram_disk_memory[4096];
27 static FX_MEDIA ram_disk;
28 static UCHAR media_memory[4096];
29
30 static UCHAR server_stack[16000];
31
32 /* Define device drivers. */
33 extern void _fx_ram_driver(FX_MEDIA *media_ptr);
34 extern void _nx_ram_network_driver_1024(NX_IP_DRIVER *driver_req_ptr);
35
36 /* Set up the HTTP client global variables. */
37
38 #define CLIENT_PACKET_SIZE (NX_WEB_HTTP_CLIENT_MIN_PACKET_SIZE * 2)
39
40 static TX_THREAD client_thread;
41 static NX_PACKET_POOL client_pool;
42 static NX_IP client_ip;
43 static UINT error_counter;
44
45 /* Set up the HTTP server global variables */
46
47 #define SERVER_PACKET_SIZE (NX_WEB_HTTP_SERVER_MIN_PACKET_SIZE * 2)
48
49 static NX_WEB_HTTP_SERVER my_server;
50 static NX_PACKET_POOL server_pool;
51 static TX_THREAD server_thread;
52 static NX_IP server_ip;
53 static NX_TCP_SOCKET client_socket;
54 #ifdef __PRODUCT_NETXDUO__
55 static NXD_ADDRESS server_ip_address;
56 #else
57 static ULONG server_ip_address;
58 #endif
59
60 static void thread_client_entry(ULONG thread_input);
61 static void thread_server_entry(ULONG thread_input);
62
63 #define HTTP_SERVER_ADDRESS IP_ADDRESS(1,2,3,4)
64 #define HTTP_CLIENT_ADDRESS IP_ADDRESS(1,2,3,5)
65
66
67 static TX_SEMAPHORE server_start;
68 static TX_SEMAPHORE client_stop;
69
70 static UINT authentication_check(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type,
71 CHAR *resource, CHAR **name, CHAR **password, CHAR **realm);
72 static UINT authentication_check_extended(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, CHAR **name, UINT *name_length,
73 CHAR **password, UINT *password_length, CHAR **realm, UINT *realm_length);
74 extern UINT _nx_web_http_client_receive(NX_WEB_HTTP_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option);
75
76 static CHAR nonce_buffer[NX_WEB_HTTP_SERVER_NONCE_SIZE + 1];
77 static CHAR temp_nonce_buffer[NX_WEB_HTTP_SERVER_NONCE_SIZE + 1];
78 static CHAR response_buffer[32 + 1];
79 static NX_MD5 client_md5data;
80
81 static char pkt[] = {
82 0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x20, /* GET /index.htm */
83 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, /* HTTP/1.1.. */
84 };
85
86 static UINT test_count;
87
88 #ifdef CTEST
test_application_define(void * first_unused_memory)89 VOID test_application_define(void *first_unused_memory)
90 #else
91 void netx_web_digest_authenticate_test_2_application_define(void *first_unused_memory)
92 #endif
93 {
94 CHAR *pointer;
95 UINT status;
96
97
98 error_counter = 0;
99
100 /* Setup the working pointer. */
101 pointer = (CHAR *) first_unused_memory;
102
103 /* Create a helper thread for the server. */
104 tx_thread_create(&server_thread, "HTTP Server thread", thread_server_entry, 0,
105 pointer, DEMO_STACK_SIZE,
106 NX_WEB_HTTP_SERVER_PRIORITY, NX_WEB_HTTP_SERVER_PRIORITY, TX_NO_TIME_SLICE, TX_AUTO_START);
107
108 pointer = pointer + DEMO_STACK_SIZE;
109
110 /* Initialize the NetX system. */
111 nx_system_initialize();
112
113 /* Create the server packet pool. */
114 status = nx_packet_pool_create(&server_pool, "HTTP Server Packet Pool", SERVER_PACKET_SIZE,
115 pointer, SERVER_PACKET_SIZE*8);
116 pointer = pointer + SERVER_PACKET_SIZE * 8;
117 if (status)
118 error_counter++;
119
120 /* Create an IP instance. */
121 status = nx_ip_create(&server_ip, "HTTP Server IP", HTTP_SERVER_ADDRESS,
122 0xFFFFFF00UL, &server_pool, _nx_ram_network_driver_1024,
123 pointer, 4096, 1);
124 pointer = pointer + 4096;
125 if (status)
126 error_counter++;
127
128 /* Enable ARP and supply ARP cache memory for the server IP instance. */
129 status = nx_arp_enable(&server_ip, (void *) pointer, 1024);
130 pointer = pointer + 1024;
131 if (status)
132 error_counter++;
133
134
135 /* Enable TCP traffic. */
136 status = nx_tcp_enable(&server_ip);
137 if (status)
138 error_counter++;
139
140 /* Create the HTTP Client thread. */
141 status = tx_thread_create(&client_thread, "HTTP Client", thread_client_entry, 0,
142 pointer, DEMO_STACK_SIZE,
143 NX_WEB_HTTP_SERVER_PRIORITY + 2, NX_WEB_HTTP_SERVER_PRIORITY + 2, TX_NO_TIME_SLICE, TX_AUTO_START);
144 pointer = pointer + DEMO_STACK_SIZE;
145 if (status)
146 error_counter++;
147
148 /* Create the Client packet pool. */
149 status = nx_packet_pool_create(&client_pool, "HTTP Client Packet Pool", CLIENT_PACKET_SIZE,
150 pointer, CLIENT_PACKET_SIZE*8);
151 pointer = pointer + CLIENT_PACKET_SIZE * 8;
152 if (status)
153 error_counter++;
154
155 /* Create an IP instance. */
156 status = nx_ip_create(&client_ip, "HTTP Client IP", HTTP_CLIENT_ADDRESS,
157 0xFFFFFF00UL, &client_pool, _nx_ram_network_driver_1024,
158 pointer, 2048, 1);
159 pointer = pointer + 2048;
160 if (status)
161 error_counter++;
162
163 status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
164 pointer = pointer + 2048;
165 if (status)
166 error_counter++;
167
168 /* Enable TCP traffic. */
169 status = nx_tcp_enable(&client_ip);
170 if (status)
171 error_counter++;
172
173 tx_semaphore_create(&server_start, "server start", 0);
174 tx_semaphore_create(&client_stop, "client stop", 0);
175 }
176
thread_client_entry(ULONG thread_input)177 void thread_client_entry(ULONG thread_input)
178 {
179 UINT status;
180 NX_PACKET *send_packet;
181 NX_PACKET *recv_packet;
182 CHAR *buffer_ptr;
183
184
185 /* Give IP task and driver a chance to initialize the system. */
186 tx_thread_sleep(NX_IP_PERIODIC_RATE);
187
188 /* Set server IP address. */
189 #ifdef __PRODUCT_NETXDUO__
190 server_ip_address.nxd_ip_address.v4 = HTTP_SERVER_ADDRESS;
191 server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
192 #else
193 server_ip_address = HTTP_SERVER_ADDRESS;
194 #endif
195
196 /* Create an HTTP client instance. */
197 status = nx_tcp_socket_create(&client_ip, &client_socket, "Socket 0",
198 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 200,
199 NX_NULL, NX_NULL);
200
201 /* Check status. */
202 if (status)
203 error_counter++;
204
205 for (test_count = 0; test_count < 2; test_count++)
206 {
207 tx_semaphore_get(&server_start, NX_WAIT_FOREVER);
208
209 /* Bind the client socket. */
210 status = nx_tcp_client_socket_bind(&client_socket, NX_ANY_PORT, NX_WAIT_FOREVER);
211
212 /* Check status of the bind. */
213 if (status)
214 error_counter++;
215
216 /* Connect to the HTTP server. */
217 /* Invoke the 'Duo' (supports IPv6/IPv4) connection call. */
218 status = nxd_tcp_client_socket_connect(&client_socket, &server_ip_address,
219 NX_WEB_HTTP_SERVER_PORT, NX_WAIT_FOREVER);
220
221 /* Check status. */
222 if (status)
223 error_counter++;
224
225 /* Allocate a packet. */
226 status = nx_packet_allocate(&client_pool, &send_packet, NX_TCP_PACKET, NX_WAIT_FOREVER);
227 if (status)
228 error_counter++;
229
230 nx_packet_data_append(send_packet, pkt, sizeof(pkt), &client_pool, NX_WAIT_FOREVER);
231 nx_packet_data_append(send_packet, "\r\n", 2, &client_pool, NX_WAIT_FOREVER);
232
233 /* Initialize the buffer. */
234 memset(nonce_buffer, 0, sizeof(nonce_buffer));
235 memset(response_buffer, 0, sizeof(response_buffer));
236
237 /* Send the request. */
238 status = nx_tcp_socket_send(&client_socket, send_packet, NX_WAIT_FOREVER);
239
240 /* Check status. */
241 if (status)
242 error_counter++;
243
244 /* Pickup the response from the Server. */
245 status = nx_tcp_socket_receive(&client_socket, &recv_packet, NX_WAIT_FOREVER);
246
247 /* Check status. */
248 if (status)
249 error_counter++;
250 else
251 {
252 status = http_nonce_retrieve(recv_packet, nonce_buffer);
253 if (status)
254 error_counter++;
255 nx_packet_release(recv_packet);
256
257 /* Check if the nonce is regenerated. */
258 if (test_count == 0)
259 {
260 memcpy(temp_nonce_buffer, nonce_buffer, sizeof(nonce_buffer));
261 }
262 else
263 {
264 if (memcmp(temp_nonce_buffer, nonce_buffer, sizeof(nonce_buffer)) == 0)
265 {
266 error_counter++;
267 }
268 }
269 }
270
271 http_digest_response_calculate(&client_md5data, "name", "NetX Duo HTTP demo", "password", nonce_buffer, "GET",
272 "/index.htm", "00000001", "0a4f113b", response_buffer);
273
274 /* Allocate a packet. */
275 status = nx_packet_allocate(&client_pool, &send_packet, NX_TCP_PACKET, NX_WAIT_FOREVER);
276 if (status)
277 error_counter++;
278
279 nx_packet_data_append(send_packet, pkt, sizeof(pkt), &client_pool, NX_WAIT_FOREVER);
280
281 /* Build the Authorization header. */
282 nx_packet_data_append(send_packet, "Authorization: Digest", 21, &client_pool, NX_WAIT_FOREVER);
283 nx_packet_data_append(send_packet, " username=\"name\",", 17, &client_pool, NX_WAIT_FOREVER);
284 nx_packet_data_append(send_packet, " realm=\"NetX Duo HTTP demo\",", 28, &client_pool, NX_WAIT_FOREVER);
285 nx_packet_data_append(send_packet, " nonce=\"", 8, &client_pool, NX_WAIT_FOREVER);
286 nx_packet_data_append(send_packet, nonce_buffer, NX_WEB_HTTP_SERVER_NONCE_SIZE, &client_pool, NX_WAIT_FOREVER);
287 nx_packet_data_append(send_packet, "\",", 2, &client_pool, NX_WAIT_FOREVER);
288 nx_packet_data_append(send_packet, " uri=\"/index.htm\",", 17, &client_pool, NX_WAIT_FOREVER);
289 nx_packet_data_append(send_packet, " qop=auth,", 10, &client_pool, NX_WAIT_FOREVER);
290 nx_packet_data_append(send_packet, " nc=00000001,", 13, &client_pool, NX_WAIT_FOREVER);
291 nx_packet_data_append(send_packet, " cnonce=\"0a4f113b\",", 19, &client_pool, NX_WAIT_FOREVER);
292 nx_packet_data_append(send_packet, " response=\"", 11, &client_pool, NX_WAIT_FOREVER);
293 nx_packet_data_append(send_packet, response_buffer, 32, &client_pool, NX_WAIT_FOREVER);
294 nx_packet_data_append(send_packet, "\",", 2, &client_pool, NX_WAIT_FOREVER);
295 nx_packet_data_append(send_packet, " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"\r\n", 44, &client_pool, NX_WAIT_FOREVER);
296
297 nx_packet_data_append(send_packet, "\r\n", 2, &client_pool, NX_WAIT_FOREVER);
298
299 /* Now send the packet to the HTTP server. */
300 status = nx_tcp_socket_send(&client_socket, send_packet, NX_WAIT_FOREVER);
301
302 /* Check status. */
303 if (status)
304 error_counter++;
305
306 /* Pickup the response from the Server. */
307 status = nx_tcp_socket_receive(&client_socket, &recv_packet, NX_WAIT_FOREVER);
308
309 /* Check status. */
310 if (status)
311 {
312 error_counter++;
313 }
314 else
315 {
316 buffer_ptr = (CHAR *)recv_packet->nx_packet_prepend_ptr;
317
318 if (test_count == 0)
319 {
320 /* Check the status, If authentication success , it should be 200. */
321 if ((buffer_ptr[9] != '2') || (buffer_ptr[10] != '0') || (buffer_ptr[11] != '0'))
322 error_counter++;
323 }
324 else
325 {
326 /* Check the status, If authentication fail , it should be 401. */
327 if ((buffer_ptr[9] != '4') || (buffer_ptr[10] != '0') || (buffer_ptr[11] != '1'))
328 error_counter++;
329 }
330
331 nx_packet_release(recv_packet);
332 }
333
334 /* Disconnect and unbind the socket. */
335 nx_tcp_socket_disconnect(&client_socket, NX_WEB_HTTP_CLIENT_TIMEOUT);
336 nx_tcp_client_socket_unbind(&client_socket);
337
338 tx_semaphore_put(&client_stop);
339 }
340
341 status = nx_tcp_socket_delete(&client_socket);
342 if (status)
343 error_counter++;
344
345 if(error_counter)
346 {
347 printf("ERROR!\n");
348 test_control_return(1);
349 }
350 else
351 {
352 printf("SUCCESS!\n");
353 test_control_return(0);
354 }
355 }
356
digest_authenticate_callback(NX_WEB_HTTP_SERVER * server_ptr,CHAR * name_ptr,CHAR * realm_ptr,CHAR * password_ptr,CHAR * method,CHAR * authorization_uri,CHAR * authorization_nc,CHAR * authorization_cnonce)357 static UINT digest_authenticate_callback(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name_ptr,
358 CHAR *realm_ptr, CHAR *password_ptr, CHAR *method,
359 CHAR *authorization_uri, CHAR *authorization_nc,
360 CHAR *authorization_cnonce)
361 {
362
363 if (memcmp(authorization_nc, "00000001", 8) != 0)
364 {
365 return 1;
366 }
367
368 if (test_count == 0)
369 {
370 /* Test authentication success. */
371 return 0;
372 }
373 else
374 {
375 /* Test authentication fail. */
376 return 1;
377 }
378 }
379
380 /* Define the helper HTTP server thread. */
thread_server_entry(ULONG thread_input)381 void thread_server_entry(ULONG thread_input)
382 {
383 UINT status;
384 FX_FILE my_file;
385
386
387 /* Print out test information banner. */
388 printf("NetX Test: Web Digest Authenticate Test2.............................");
389
390 /* Check for earlier error. */
391 if(error_counter)
392 {
393 printf("ERROR!\n");
394 test_control_return(1);
395 }
396
397 fx_media_format(&ram_disk,
398 _fx_ram_driver, // Driver entry
399 ram_disk_memory, // RAM disk memory pointer
400 media_memory, // Media buffer pointer
401 sizeof(media_memory), // Media buffer size
402 "MY_RAM_DISK", // Volume Name
403 1, // Number of FATs
404 32, // Directory Entries
405 0, // Hidden sectors
406 256, // Total sectors
407 512, // Sector size
408 8, // Sectors per cluster
409 1, // Heads
410 1); // Sectors per track
411
412 /* Open the RAM disk. */
413 status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory, media_memory, sizeof(media_memory)) ;
414 if(status)
415 error_counter++;
416
417 /* Give NetX a chance to initialize the system. */
418 tx_thread_sleep(NX_IP_PERIODIC_RATE);
419
420 status = fx_file_create(&ram_disk, "index.htm");
421 status += fx_file_open(&ram_disk, &my_file, "index.htm", FX_OPEN_FOR_WRITE);
422 status += fx_file_write(&my_file, "https server", 12);
423 status += fx_file_close(&my_file);
424 if (status)
425 error_counter++;
426
427 /* Create the HTTP Server. */
428 status = nx_web_http_server_create(&my_server, "My HTTP Server", &server_ip, NX_WEB_HTTP_SERVER_PORT, &ram_disk,
429 &server_stack, sizeof(server_stack), &server_pool,
430 authentication_check, NX_NULL);
431 if (status)
432 error_counter++;
433
434 nx_web_http_server_digest_authenticate_notify_set(&my_server, digest_authenticate_callback);
435
436 /* OK to start the HTTP Server. */
437 status = nx_web_http_server_start(&my_server);
438 if (status)
439 error_counter++;
440
441 tx_semaphore_put(&server_start);
442 tx_semaphore_get(&client_stop, NX_WAIT_FOREVER);
443
444 status = nx_web_http_server_authentication_check_set(&my_server, authentication_check_extended);
445 if (status)
446 error_counter++;
447
448 tx_semaphore_put(&server_start);
449 }
450
451 /* Define the application's authentication check. This is called by
452 the HTTP server whenever a new request is received. */
authentication_check(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,CHAR ** password,CHAR ** realm)453 static UINT authentication_check(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type,
454 CHAR *resource, CHAR **name, CHAR **password, CHAR **realm)
455 {
456
457 /* Just use a simple name, password, and realm for all
458 requests and resources. */
459 *name = "name";
460 *password = "password";
461 *realm = "NetX Duo HTTP demo";
462
463 /* Request digest authentication. */
464 return(NX_WEB_HTTP_DIGEST_AUTHENTICATE);
465 }
466
authentication_check_extended(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,UINT * name_length,CHAR ** password,UINT * password_length,CHAR ** realm,UINT * realm_length)467 static UINT authentication_check_extended(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, CHAR **name, UINT *name_length,
468 CHAR **password, UINT *password_length, CHAR **realm, UINT *realm_length)
469 {
470
471 /* Just use a simple name, password, and realm for all
472 requests and resources. */
473 *name = "name";
474 *password = "password";
475 *realm = "NetX Duo HTTP demo";
476 *name_length = 4;
477 *password_length = 8;
478 *realm_length = 18;
479
480 /* Request digest authentication. */
481 return(NX_WEB_HTTP_DIGEST_AUTHENTICATE);
482 }
483
484 #else
485
486 #ifdef CTEST
test_application_define(void * first_unused_memory)487 VOID test_application_define(void *first_unused_memory)
488 #else
489 void netx_web_digest_authenticate_test_2_application_define(void *first_unused_memory)
490 #endif
491 {
492
493 /* Print out test information banner. */
494 printf("NetX Test: Web Digest Authenticate Test2.............................N/A\n");
495
496 test_control_return(3);
497 }
498 #endif
499
500