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