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