]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/http.c
More HTTP request timeout changes.
[thirdparty/cups.git] / cups / http.c
1 /*
2 * "$Id: http.c,v 1.117 2003/05/09 16:05:27 mike Exp $"
3 *
4 * HTTP routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2003 by Easy Software Products, all rights reserved.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * httpInitialize() - Initialize the HTTP interface library and set the
29 * default HTTP proxy (if any).
30 * httpCheck() - Check to see if there is a pending response from
31 * the server.
32 * httpClearCookie() - Clear the cookie value(s).
33 * httpClose() - Close an HTTP connection...
34 * httpConnect() - Connect to a HTTP server.
35 * httpConnectEncrypt() - Connect to a HTTP server using encryption.
36 * httpEncryption() - Set the required encryption on the link.
37 * httpReconnect() - Reconnect to a HTTP server...
38 * httpGetSubField() - Get a sub-field value.
39 * httpSetField() - Set the value of an HTTP header.
40 * httpDelete() - Send a DELETE request to the server.
41 * httpGet() - Send a GET request to the server.
42 * httpHead() - Send a HEAD request to the server.
43 * httpOptions() - Send an OPTIONS request to the server.
44 * httpPost() - Send a POST request to the server.
45 * httpPut() - Send a PUT request to the server.
46 * httpTrace() - Send an TRACE request to the server.
47 * httpFlush() - Flush data from a HTTP connection.
48 * httpRead() - Read data from a HTTP connection.
49 * httpSetCookie() - Set the cookie value(s)...
50 * httpWait() - Wait for data available on a connection.
51 * httpWrite() - Write data to a HTTP connection.
52 * httpGets() - Get a line of text from a HTTP connection.
53 * httpPrintf() - Print a formatted string to a HTTP connection.
54 * httpGetDateString() - Get a formatted date/time string from a time value.
55 * httpGetDateTime() - Get a time value from a formatted date/time string.
56 * httpUpdate() - Update the current HTTP state for incoming data.
57 * httpDecode64() - Base64-decode a string.
58 * httpEncode64() - Base64-encode a string.
59 * httpGetLength() - Get the amount of data remaining from the
60 * content-length or transfer-encoding fields.
61 * http_field() - Return the field index for a field name.
62 * http_send() - Send a request with all fields and the trailing
63 * blank line.
64 * http_upgrade() - Force upgrade to TLS encryption.
65 * http_setup_ssl() - Set up SSL/TLS on a connection.
66 * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
67 * http_read_ssl() - Read from a SSL/TLS connection.
68 * http_write_ssl() - Write to a SSL/TLS connection.
69 * CDSAReadFunc() - Read function for CDSA decryption code.
70 * CDSAWriteFunc() - Write function for CDSA encryption code.
71 */
72
73 /*
74 * Include necessary headers...
75 */
76
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <stdarg.h>
80 #include <ctype.h>
81 #include "string.h"
82 #include <fcntl.h>
83 #include <errno.h>
84
85 #include "http.h"
86 #include "http-private.h"
87 #include "debug.h"
88
89 #ifndef WIN32
90 # include <signal.h>
91 # include <sys/time.h>
92 # include <sys/resource.h>
93 #endif /* !WIN32 */
94
95
96 /*
97 * Some operating systems have done away with the Fxxxx constants for
98 * the fcntl() call; this works around that "feature"...
99 */
100
101 #ifndef FNONBLK
102 # define FNONBLK O_NONBLOCK
103 #endif /* !FNONBLK */
104
105
106 /*
107 * Local functions...
108 */
109
110 static http_field_t http_field(const char *name);
111 static int http_send(http_t *http, http_state_t request,
112 const char *uri);
113 #ifdef HAVE_SSL
114 static int http_upgrade(http_t *http);
115 static int http_setup_ssl(http_t *http);
116 static void http_shutdown_ssl(http_t *http);
117 static int http_read_ssl(http_t *http, char *buf, int len);
118 static int http_write_ssl(http_t *http, const char *buf, int len);
119 # ifdef HAVE_CDSASSL
120 static OSStatus CDSAReadFunc(SSLConnectionRef connection, void *data, size_t *dataLength);
121 static OSStatus CDSAWriteFunc(SSLConnectionRef connection, const void *data, size_t *dataLength);
122 # endif /* HAVE_CDSASSL */
123 #endif /* HAVE_SSL */
124
125
126 /*
127 * Local globals...
128 */
129
130 static const char * const http_fields[] =
131 {
132 "Accept-Language",
133 "Accept-Ranges",
134 "Authorization",
135 "Connection",
136 "Content-Encoding",
137 "Content-Language",
138 "Content-Length",
139 "Content-Location",
140 "Content-MD5",
141 "Content-Range",
142 "Content-Type",
143 "Content-Version",
144 "Date",
145 "Host",
146 "If-Modified-Since",
147 "If-Unmodified-since",
148 "Keep-Alive",
149 "Last-Modified",
150 "Link",
151 "Location",
152 "Range",
153 "Referer",
154 "Retry-After",
155 "Transfer-Encoding",
156 "Upgrade",
157 "User-Agent",
158 "WWW-Authenticate"
159 };
160 static const char * const days[7] =
161 {
162 "Sun",
163 "Mon",
164 "Tue",
165 "Wed",
166 "Thu",
167 "Fri",
168 "Sat"
169 };
170 static const char * const months[12] =
171 {
172 "Jan",
173 "Feb",
174 "Mar",
175 "Apr",
176 "May",
177 "Jun",
178 "Jul",
179 "Aug",
180 "Sep",
181 "Oct",
182 "Nov",
183 "Dec"
184 };
185
186
187 /*
188 * 'httpInitialize()' - Initialize the HTTP interface library and set the
189 * default HTTP proxy (if any).
190 */
191
192 void
193 httpInitialize(void)
194 {
195 #ifdef HAVE_LIBSSL
196 # ifndef WIN32
197 struct timeval curtime; /* Current time in microseconds */
198 # endif /* !WIN32 */
199 int i; /* Looping var */
200 unsigned char data[1024]; /* Seed data */
201 #endif /* HAVE_LIBSSL */
202
203 #ifdef WIN32
204 WSADATA winsockdata; /* WinSock data */
205 static int initialized = 0;/* Has WinSock been initialized? */
206
207
208 if (!initialized)
209 WSAStartup(MAKEWORD(1,1), &winsockdata);
210 #elif defined(HAVE_SIGSET)
211 sigset(SIGPIPE, SIG_IGN);
212 #elif defined(HAVE_SIGACTION)
213 struct sigaction action; /* POSIX sigaction data */
214
215
216 /*
217 * Ignore SIGPIPE signals...
218 */
219
220 memset(&action, 0, sizeof(action));
221 action.sa_handler = SIG_IGN;
222 sigaction(SIGPIPE, &action, NULL);
223 #else
224 signal(SIGPIPE, SIG_IGN);
225 #endif /* WIN32 */
226
227 #ifdef HAVE_GNUTLS
228 gnutls_global_init();
229 #endif /* HAVE_GNUTLS */
230
231 #ifdef HAVE_LIBSSL
232 SSL_load_error_strings();
233 SSL_library_init();
234
235 /*
236 * Using the current time is a dubious random seed, but on some systems
237 * it is the best we can do (on others, this seed isn't even used...)
238 */
239
240 #ifdef WIN32
241 #else
242 gettimeofday(&curtime, NULL);
243 srand(curtime.tv_sec + curtime.tv_usec);
244 #endif /* WIN32 */
245
246 for (i = 0; i < sizeof(data); i ++)
247 data[i] = rand(); /* Yes, this is a poor source of random data... */
248
249 RAND_seed(&data, sizeof(data));
250 #endif /* HAVE_LIBSSL */
251 }
252
253
254 /*
255 * 'httpCheck()' - Check to see if there is a pending response from the server.
256 */
257
258 int /* O - 0 = no data, 1 = data available */
259 httpCheck(http_t *http) /* I - HTTP connection */
260 {
261 return (httpWait(http, 0));
262 }
263
264
265 /*
266 * 'httpClearCookie()' - Clear the cookie value(s).
267 */
268
269 void
270 httpClearCookie(http_t *http) /* I - Connection */
271 {
272 if (!http)
273 return;
274
275 if (http->cookie)
276 {
277 free(http->cookie);
278 http->cookie = NULL;
279 }
280 }
281
282
283 /*
284 * 'httpClose()' - Close an HTTP connection...
285 */
286
287 void
288 httpClose(http_t *http) /* I - Connection to close */
289 {
290 if (!http)
291 return;
292
293 if (http->input_set)
294 free(http->input_set);
295
296 if (http->cookie)
297 free(http->cookie);
298
299 #ifdef HAVE_SSL
300 if (http->tls)
301 http_shutdown_ssl(http);
302 #endif /* HAVE_SSL */
303
304 #ifdef WIN32
305 closesocket(http->fd);
306 #else
307 close(http->fd);
308 #endif /* WIN32 */
309
310 free(http);
311 }
312
313
314 /*
315 * 'httpConnect()' - Connect to a HTTP server.
316 */
317
318 http_t * /* O - New HTTP connection */
319 httpConnect(const char *host, /* I - Host to connect to */
320 int port) /* I - Port number */
321 {
322 http_encryption_t encrypt;/* Type of encryption to use */
323
324
325 /*
326 * Set the default encryption status...
327 */
328
329 if (port == 443)
330 encrypt = HTTP_ENCRYPT_ALWAYS;
331 else
332 encrypt = HTTP_ENCRYPT_IF_REQUESTED;
333
334 return (httpConnectEncrypt(host, port, encrypt));
335 }
336
337
338 /*
339 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
340 */
341
342 http_t * /* O - New HTTP connection */
343 httpConnectEncrypt(const char *host, /* I - Host to connect to */
344 int port, /* I - Port number */
345 http_encryption_t encrypt)
346 /* I - Type of encryption to use */
347 {
348 int i; /* Looping var */
349 http_t *http; /* New HTTP connection */
350 struct hostent *hostaddr; /* Host address data */
351
352
353 if (host == NULL)
354 return (NULL);
355
356 httpInitialize();
357
358 /*
359 * Lookup the host...
360 */
361
362 if ((hostaddr = httpGetHostByName(host)) == NULL)
363 {
364 /*
365 * This hack to make users that don't have a localhost entry in
366 * their hosts file or DNS happy...
367 */
368
369 if (strcasecmp(host, "localhost") != 0)
370 return (NULL);
371 else if ((hostaddr = httpGetHostByName("127.0.0.1")) == NULL)
372 return (NULL);
373 }
374
375 /*
376 * Verify that it is an IPv4 address (IPv6 support will come in CUPS 1.2...)
377 */
378
379 if (hostaddr->h_addrtype != AF_INET || hostaddr->h_length != 4)
380 return (NULL);
381
382 /*
383 * Allocate memory for the structure...
384 */
385
386 http = calloc(sizeof(http_t), 1);
387 if (http == NULL)
388 return (NULL);
389
390 http->version = HTTP_1_1;
391 http->blocking = 1;
392 http->activity = time(NULL);
393 http->fd = -1;
394
395 /*
396 * Copy the hostname and port and then "reconnect"...
397 */
398
399 strlcpy(http->hostname, host, sizeof(http->hostname));
400 http->hostaddr.sin_family = hostaddr->h_addrtype;
401 #ifdef WIN32
402 http->hostaddr.sin_port = htons((u_short)port);
403 #else
404 http->hostaddr.sin_port = htons(port);
405 #endif /* WIN32 */
406
407 /*
408 * Set the encryption status...
409 */
410
411 if (port == 443) /* Always use encryption for https */
412 http->encryption = HTTP_ENCRYPT_ALWAYS;
413 else
414 http->encryption = encrypt;
415
416 /*
417 * Loop through the addresses we have until one of them connects...
418 */
419
420 strlcpy(http->hostname, host, sizeof(http->hostname));
421
422 for (i = 0; hostaddr->h_addr_list[i]; i ++)
423 {
424 /*
425 * Load the address...
426 */
427
428 memcpy((char *)&(http->hostaddr.sin_addr), hostaddr->h_addr_list[i],
429 hostaddr->h_length);
430
431 /*
432 * Connect to the remote system...
433 */
434
435 if (!httpReconnect(http))
436 return (http);
437 }
438
439 /*
440 * Could not connect to any known address - bail out!
441 */
442
443 free(http);
444 return (NULL);
445 }
446
447
448 /*
449 * 'httpEncryption()' - Set the required encryption on the link.
450 */
451
452 int /* O - -1 on error, 0 on success */
453 httpEncryption(http_t *http, /* I - HTTP data */
454 http_encryption_t e) /* I - New encryption preference */
455 {
456 #ifdef HAVE_SSL
457 if (!http)
458 return (0);
459
460 http->encryption = e;
461
462 if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
463 (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
464 return (httpReconnect(http));
465 else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
466 return (http_upgrade(http));
467 else
468 return (0);
469 #else
470 if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
471 return (-1);
472 else
473 return (0);
474 #endif /* HAVE_SSL */
475 }
476
477
478 /*
479 * 'httpReconnect()' - Reconnect to a HTTP server...
480 */
481
482 int /* O - 0 on success, non-zero on failure */
483 httpReconnect(http_t *http) /* I - HTTP data */
484 {
485 int val; /* Socket option value */
486
487 #ifdef HAVE_SSL
488 if (http->tls)
489 http_shutdown_ssl(http);
490 #endif /* HAVE_SSL */
491
492 /*
493 * Close any previously open socket...
494 */
495
496 if (http->fd >= 0)
497 #ifdef WIN32
498 closesocket(http->fd);
499 #else
500 close(http->fd);
501 #endif /* WIN32 */
502
503 /*
504 * Create the socket and set options to allow reuse.
505 */
506
507 if ((http->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
508 {
509 #ifdef WIN32
510 http->error = WSAGetLastError();
511 #else
512 http->error = errno;
513 #endif /* WIN32 */
514 http->status = HTTP_ERROR;
515 return (-1);
516 }
517
518 #ifdef FD_CLOEXEC
519 fcntl(http->fd, F_SETFD, FD_CLOEXEC); /* Close this socket when starting *
520 * other processes... */
521 #endif /* FD_CLOEXEC */
522
523 val = 1;
524 setsockopt(http->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
525
526 #ifdef SO_REUSEPORT
527 val = 1;
528 setsockopt(http->fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
529 #endif /* SO_REUSEPORT */
530
531 /*
532 * Using TCP_NODELAY improves responsiveness, especially on systems
533 * with a slow loopback interface... Since we write large buffers
534 * when sending print files and requests, there shouldn't be any
535 * performance penalty for this...
536 */
537
538 val = 1;
539 setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
540
541 /*
542 * Connect to the server...
543 */
544
545 if (connect(http->fd, (struct sockaddr *)&(http->hostaddr),
546 sizeof(http->hostaddr)) < 0)
547 {
548 #ifdef WIN32
549 http->error = WSAGetLastError();
550 #else
551 http->error = errno;
552 #endif /* WIN32 */
553 http->status = HTTP_ERROR;
554
555 #ifdef WIN32
556 closesocket(http->fd);
557 #else
558 close(http->fd);
559 #endif
560
561 http->fd = -1;
562
563 return (-1);
564 }
565
566 http->error = 0;
567 http->status = HTTP_CONTINUE;
568
569 #ifdef HAVE_SSL
570 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
571 {
572 /*
573 * Always do encryption via SSL.
574 */
575
576 if (http_setup_ssl(http) != 0)
577 {
578 #ifdef WIN32
579 closesocket(http->fd);
580 #else
581 close(http->fd);
582 #endif /* WIN32 */
583
584 return (-1);
585 }
586 }
587 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
588 return (http_upgrade(http));
589 #endif /* HAVE_SSL */
590
591 return (0);
592 }
593
594
595 /*
596 * 'httpGetSubField()' - Get a sub-field value.
597 */
598
599 char * /* O - Value or NULL */
600 httpGetSubField(http_t *http, /* I - HTTP data */
601 http_field_t field, /* I - Field index */
602 const char *name, /* I - Name of sub-field */
603 char *value) /* O - Value string */
604 {
605 const char *fptr; /* Pointer into field */
606 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
607 *ptr; /* Pointer into string buffer */
608
609
610 if (http == NULL ||
611 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
612 field > HTTP_FIELD_WWW_AUTHENTICATE ||
613 name == NULL || value == NULL)
614 return (NULL);
615
616 DEBUG_printf(("httpGetSubField(%p, %d, \"%s\", %p)\n",
617 http, field, name, value));
618
619 for (fptr = http->fields[field]; *fptr;)
620 {
621 /*
622 * Skip leading whitespace...
623 */
624
625 while (isspace(*fptr))
626 fptr ++;
627
628 if (*fptr == ',')
629 {
630 fptr ++;
631 continue;
632 }
633
634 /*
635 * Get the sub-field name...
636 */
637
638 for (ptr = temp;
639 *fptr && *fptr != '=' && !isspace(*fptr) && ptr < (temp + sizeof(temp) - 1);
640 *ptr++ = *fptr++);
641
642 *ptr = '\0';
643
644 DEBUG_printf(("name = \"%s\"\n", temp));
645
646 /*
647 * Skip trailing chars up to the '='...
648 */
649
650 while (isspace(*fptr))
651 fptr ++;
652
653 if (!*fptr)
654 break;
655
656 if (*fptr != '=')
657 continue;
658
659 /*
660 * Skip = and leading whitespace...
661 */
662
663 fptr ++;
664
665 while (isspace(*fptr))
666 fptr ++;
667
668 if (*fptr == '\"')
669 {
670 /*
671 * Read quoted string...
672 */
673
674 for (ptr = value, fptr ++;
675 *fptr && *fptr != '\"' && ptr < (value + HTTP_MAX_VALUE - 1);
676 *ptr++ = *fptr++);
677
678 *ptr = '\0';
679
680 while (*fptr && *fptr != '\"')
681 fptr ++;
682
683 if (*fptr)
684 fptr ++;
685 }
686 else
687 {
688 /*
689 * Read unquoted string...
690 */
691
692 for (ptr = value;
693 *fptr && !isspace(*fptr) && *fptr != ',' && ptr < (value + HTTP_MAX_VALUE - 1);
694 *ptr++ = *fptr++);
695
696 *ptr = '\0';
697
698 while (*fptr && !isspace(*fptr) && *fptr != ',')
699 fptr ++;
700 }
701
702 DEBUG_printf(("value = \"%s\"\n", value));
703
704 /*
705 * See if this is the one...
706 */
707
708 if (strcmp(name, temp) == 0)
709 return (value);
710 }
711
712 value[0] = '\0';
713
714 return (NULL);
715 }
716
717
718 /*
719 * 'httpSetField()' - Set the value of an HTTP header.
720 */
721
722 void
723 httpSetField(http_t *http, /* I - HTTP data */
724 http_field_t field, /* I - Field index */
725 const char *value) /* I - Value */
726 {
727 if (http == NULL ||
728 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
729 field > HTTP_FIELD_WWW_AUTHENTICATE ||
730 value == NULL)
731 return;
732
733 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
734 }
735
736
737 /*
738 * 'httpDelete()' - Send a DELETE request to the server.
739 */
740
741 int /* O - Status of call (0 = success) */
742 httpDelete(http_t *http, /* I - HTTP data */
743 const char *uri) /* I - URI to delete */
744 {
745 return (http_send(http, HTTP_DELETE, uri));
746 }
747
748
749 /*
750 * 'httpGet()' - Send a GET request to the server.
751 */
752
753 int /* O - Status of call (0 = success) */
754 httpGet(http_t *http, /* I - HTTP data */
755 const char *uri) /* I - URI to get */
756 {
757 return (http_send(http, HTTP_GET, uri));
758 }
759
760
761 /*
762 * 'httpHead()' - Send a HEAD request to the server.
763 */
764
765 int /* O - Status of call (0 = success) */
766 httpHead(http_t *http, /* I - HTTP data */
767 const char *uri) /* I - URI for head */
768 {
769 return (http_send(http, HTTP_HEAD, uri));
770 }
771
772
773 /*
774 * 'httpOptions()' - Send an OPTIONS request to the server.
775 */
776
777 int /* O - Status of call (0 = success) */
778 httpOptions(http_t *http, /* I - HTTP data */
779 const char *uri) /* I - URI for options */
780 {
781 return (http_send(http, HTTP_OPTIONS, uri));
782 }
783
784
785 /*
786 * 'httpPost()' - Send a POST request to the server.
787 */
788
789 int /* O - Status of call (0 = success) */
790 httpPost(http_t *http, /* I - HTTP data */
791 const char *uri) /* I - URI for post */
792 {
793 httpGetLength(http);
794
795 return (http_send(http, HTTP_POST, uri));
796 }
797
798
799 /*
800 * 'httpPut()' - Send a PUT request to the server.
801 */
802
803 int /* O - Status of call (0 = success) */
804 httpPut(http_t *http, /* I - HTTP data */
805 const char *uri) /* I - URI to put */
806 {
807 httpGetLength(http);
808
809 return (http_send(http, HTTP_PUT, uri));
810 }
811
812
813 /*
814 * 'httpTrace()' - Send an TRACE request to the server.
815 */
816
817 int /* O - Status of call (0 = success) */
818 httpTrace(http_t *http, /* I - HTTP data */
819 const char *uri) /* I - URI for trace */
820 {
821 return (http_send(http, HTTP_TRACE, uri));
822 }
823
824
825 /*
826 * 'httpFlush()' - Flush data from a HTTP connection.
827 */
828
829 void
830 httpFlush(http_t *http) /* I - HTTP data */
831 {
832 char buffer[8192]; /* Junk buffer */
833
834
835 if (http->state != HTTP_WAITING)
836 {
837 while (httpRead(http, buffer, sizeof(buffer)) > 0);
838 }
839 }
840
841
842 /*
843 * 'httpRead()' - Read data from a HTTP connection.
844 */
845
846 int /* O - Number of bytes read */
847 httpRead(http_t *http, /* I - HTTP data */
848 char *buffer, /* I - Buffer for data */
849 int length) /* I - Maximum number of bytes */
850 {
851 int bytes; /* Bytes read */
852 char len[32]; /* Length string */
853
854
855 DEBUG_printf(("httpRead(%p, %p, %d)\n", http, buffer, length));
856
857 if (http == NULL || buffer == NULL)
858 return (-1);
859
860 http->activity = time(NULL);
861
862 if (length <= 0)
863 return (0);
864
865 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
866 http->data_remaining <= 0)
867 {
868 DEBUG_puts("httpRead: Getting chunk length...");
869
870 if (httpGets(len, sizeof(len), http) == NULL)
871 {
872 DEBUG_puts("httpRead: Could not get length!");
873 return (0);
874 }
875
876 http->data_remaining = strtol(len, NULL, 16);
877 if (http->data_remaining < 0)
878 {
879 DEBUG_puts("httpRead: Negative chunk length!");
880 return (0);
881 }
882 }
883
884 DEBUG_printf(("httpRead: data_remaining = %d\n", http->data_remaining));
885
886 if (http->data_remaining <= 0)
887 {
888 /*
889 * A zero-length chunk ends a transfer; unless we are reading POST
890 * data, go idle...
891 */
892
893 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
894 httpGets(len, sizeof(len), http);
895
896 if (http->state == HTTP_POST_RECV)
897 http->state ++;
898 else
899 http->state = HTTP_WAITING;
900
901 return (0);
902 }
903 else if (length > http->data_remaining)
904 length = http->data_remaining;
905
906 if (http->used == 0 && length <= 256)
907 {
908 /*
909 * Buffer small reads for better performance...
910 */
911
912 if (http->data_remaining > sizeof(http->buffer))
913 bytes = sizeof(http->buffer);
914 else
915 bytes = http->data_remaining;
916
917 if (!http->blocking && !httpWait(http, 1000))
918 return (0);
919
920 #ifdef HAVE_SSL
921 if (http->tls)
922 bytes = http_read_ssl(http, http->buffer, bytes);
923 else
924 #endif /* HAVE_SSL */
925 {
926 DEBUG_printf(("httpRead: reading %d bytes from socket into buffer...\n",
927 bytes));
928
929 bytes = recv(http->fd, http->buffer, bytes, 0);
930
931 DEBUG_printf(("httpRead: read %d bytes from socket into buffer...\n",
932 bytes));
933 }
934
935 if (bytes > 0)
936 http->used = bytes;
937 else if (bytes < 0)
938 {
939 #ifdef WIN32
940 http->error = WSAGetLastError();
941 return (-1);
942 #else
943 if (errno != EINTR)
944 {
945 http->error = errno;
946 return (-1);
947 }
948 #endif /* WIN32 */
949 }
950 else if (bytes == 0)
951 {
952 http->error = EPIPE;
953 return (0);
954 }
955 }
956
957 if (http->used > 0)
958 {
959 if (length > http->used)
960 length = http->used;
961
962 bytes = length;
963
964 DEBUG_printf(("httpRead: grabbing %d bytes from input buffer...\n", bytes));
965
966 memcpy(buffer, http->buffer, length);
967 http->used -= length;
968
969 if (http->used > 0)
970 memmove(http->buffer, http->buffer + length, http->used);
971 }
972 #ifdef HAVE_SSL
973 else if (http->tls)
974 {
975 if (!http->blocking && !httpWait(http, 1000))
976 return (0);
977 bytes = http_read_ssl(http, buffer, length);
978 }
979 #endif /* HAVE_SSL */
980 else
981 {
982 if (!http->blocking && !httpWait(http, 1000))
983 return (0);
984 DEBUG_printf(("httpRead: reading %d bytes from socket...\n", length));
985 bytes = recv(http->fd, buffer, length, 0);
986 DEBUG_printf(("httpRead: read %d bytes from socket...\n", bytes));
987 }
988
989 if (bytes > 0)
990 http->data_remaining -= bytes;
991 else if (bytes < 0)
992 {
993 #ifdef WIN32
994 http->error = WSAGetLastError();
995 #else
996 if (errno == EINTR)
997 bytes = 0;
998 else
999 http->error = errno;
1000 #endif /* WIN32 */
1001 }
1002 else if (bytes == 0)
1003 {
1004 http->error = EPIPE;
1005 return 0;
1006 }
1007
1008 if (http->data_remaining == 0)
1009 {
1010 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1011 httpGets(len, sizeof(len), http);
1012
1013 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
1014 {
1015 if (http->state == HTTP_POST_RECV)
1016 http->state ++;
1017 else
1018 http->state = HTTP_WAITING;
1019 }
1020 }
1021
1022 #ifdef DEBUG
1023 {
1024 int i, j, ch;
1025 printf("httpRead: Read %d bytes:\n", bytes);
1026 for (i = 0; i < bytes; i += 16)
1027 {
1028 printf(" ");
1029
1030 for (j = 0; j < 16 && (i + j) < bytes; j ++)
1031 printf(" %02X", buffer[i + j] & 255);
1032
1033 while (j < 16)
1034 {
1035 printf(" ");
1036 j ++;
1037 }
1038
1039 printf(" ");
1040 for (j = 0; j < 16 && (i + j) < bytes; j ++)
1041 {
1042 ch = buffer[i + j] & 255;
1043
1044 if (ch < ' ' || ch == 127)
1045 ch = '.';
1046
1047 putchar(ch);
1048 }
1049 putchar('\n');
1050 }
1051 }
1052 #endif /* DEBUG */
1053
1054 return (bytes);
1055 }
1056
1057
1058 /*
1059 * 'httpSetCookie()' - Set the cookie value(s)...
1060 */
1061
1062 void
1063 httpSetCookie(http_t *http, /* I - Connection */
1064 const char *cookie) /* I - Cookie string */
1065 {
1066 if (!http)
1067 return;
1068
1069 if (http->cookie)
1070 free(http->cookie);
1071
1072 if (cookie)
1073 http->cookie = strdup(cookie);
1074 else
1075 http->cookie = NULL;
1076 }
1077
1078
1079 /*
1080 * 'httpWait()' - Wait for data available on a connection.
1081 */
1082
1083 int /* O - 1 if data is available, 0 otherwise */
1084 httpWait(http_t *http, /* I - HTTP data */
1085 int msec) /* I - Milliseconds to wait */
1086 {
1087 #ifndef WIN32
1088 struct rlimit limit; /* Runtime limit */
1089 #endif /* !WIN32 */
1090 struct timeval timeout; /* Timeout */
1091 int nfds; /* Result from select() */
1092
1093
1094 /*
1095 * First see if there is data in the buffer...
1096 */
1097
1098 if (http == NULL)
1099 return (0);
1100
1101 if (http->used)
1102 return (1);
1103
1104 /*
1105 * Then try doing a select() to poll the socket...
1106 */
1107
1108 if (!http->input_set)
1109 {
1110 #ifdef WIN32
1111 /*
1112 * Windows has a fixed-size select() structure, different (surprise,
1113 * surprise!) from all UNIX implementations. Just allocate this
1114 * fixed structure...
1115 */
1116
1117 http->input_set = calloc(1, sizeof(fd_set));
1118 #else
1119 /*
1120 * Allocate the select() input set based upon the max number of file
1121 * descriptors available for this process...
1122 */
1123
1124 getrlimit(RLIMIT_NOFILE, &limit);
1125
1126 http->input_set = calloc(1, (limit.rlim_cur + 7) / 8);
1127 #endif /* WIN32 */
1128
1129 if (!http->input_set)
1130 return (0);
1131 }
1132
1133 FD_SET(http->fd, http->input_set);
1134
1135 if (msec >= 0)
1136 {
1137 timeout.tv_sec = msec / 1000;
1138 timeout.tv_usec = (msec % 1000) * 1000;
1139
1140 nfds = select(http->fd + 1, http->input_set, NULL, NULL, &timeout);
1141 }
1142 else
1143 nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL);
1144
1145 FD_CLR(http->fd, http->input_set);
1146
1147 return (nfds > 0);
1148 }
1149
1150
1151 /*
1152 * 'httpWrite()' - Write data to a HTTP connection.
1153 */
1154
1155 int /* O - Number of bytes written */
1156 httpWrite(http_t *http, /* I - HTTP data */
1157 const char *buffer, /* I - Buffer for data */
1158 int length) /* I - Number of bytes to write */
1159 {
1160 int tbytes, /* Total bytes sent */
1161 bytes; /* Bytes sent */
1162
1163
1164 if (http == NULL || buffer == NULL)
1165 return (-1);
1166
1167 http->activity = time(NULL);
1168
1169 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1170 {
1171 if (httpPrintf(http, "%x\r\n", length) < 0)
1172 return (-1);
1173
1174 if (length == 0)
1175 {
1176 /*
1177 * A zero-length chunk ends a transfer; unless we are sending POST
1178 * data, go idle...
1179 */
1180
1181 DEBUG_puts("httpWrite: changing states...");
1182
1183 if (http->state == HTTP_POST_RECV)
1184 http->state ++;
1185 else if (http->state == HTTP_PUT_RECV)
1186 http->state = HTTP_STATUS;
1187 else
1188 http->state = HTTP_WAITING;
1189
1190 if (httpPrintf(http, "\r\n") < 0)
1191 return (-1);
1192
1193 return (0);
1194 }
1195 }
1196
1197 tbytes = 0;
1198
1199 while (length > 0)
1200 {
1201 #ifdef HAVE_SSL
1202 if (http->tls)
1203 bytes = http_write_ssl(http, buffer, length);
1204 else
1205 #endif /* HAVE_SSL */
1206 bytes = send(http->fd, buffer, length, 0);
1207
1208 if (bytes < 0)
1209 {
1210 #ifdef WIN32
1211 if (WSAGetLastError() != http->error)
1212 {
1213 http->error = WSAGetLastError();
1214 continue;
1215 }
1216 #else
1217 if (errno == EINTR)
1218 continue;
1219 else if (errno != http->error)
1220 {
1221 http->error = errno;
1222 continue;
1223 }
1224 #endif /* WIN32 */
1225
1226 DEBUG_puts("httpWrite: error writing data...\n");
1227
1228 return (-1);
1229 }
1230
1231 buffer += bytes;
1232 tbytes += bytes;
1233 length -= bytes;
1234 if (http->data_encoding == HTTP_ENCODE_LENGTH)
1235 http->data_remaining -= bytes;
1236 }
1237
1238 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1239 if (httpPrintf(http, "\r\n") < 0)
1240 return (-1);
1241
1242 if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODE_LENGTH)
1243 {
1244 /*
1245 * Finished with the transfer; unless we are sending POST data, go idle...
1246 */
1247
1248 DEBUG_puts("httpWrite: changing states...");
1249
1250 if (http->state == HTTP_POST_RECV)
1251 http->state ++;
1252 else
1253 http->state = HTTP_WAITING;
1254 }
1255
1256 #ifdef DEBUG
1257 {
1258 int i, j, ch;
1259 printf("httpWrite: wrote %d bytes: \n", tbytes);
1260 for (i = 0, buffer -= tbytes; i < tbytes; i += 16)
1261 {
1262 printf(" ");
1263
1264 for (j = 0; j < 16 && (i + j) < tbytes; j ++)
1265 printf(" %02X", buffer[i + j] & 255);
1266
1267 while (j < 16)
1268 {
1269 printf(" ");
1270 j ++;
1271 }
1272
1273 printf(" ");
1274 for (j = 0; j < 16 && (i + j) < tbytes; j ++)
1275 {
1276 ch = buffer[i + j] & 255;
1277
1278 if (ch < ' ' || ch == 127)
1279 ch = '.';
1280
1281 putchar(ch);
1282 }
1283 putchar('\n');
1284 }
1285 }
1286 #endif /* DEBUG */
1287 return (tbytes);
1288 }
1289
1290
1291 /*
1292 * 'httpGets()' - Get a line of text from a HTTP connection.
1293 */
1294
1295 char * /* O - Line or NULL */
1296 httpGets(char *line, /* I - Line to read into */
1297 int length, /* I - Max length of buffer */
1298 http_t *http) /* I - HTTP data */
1299 {
1300 char *lineptr, /* Pointer into line */
1301 *bufptr, /* Pointer into input buffer */
1302 *bufend; /* Pointer to end of buffer */
1303 int bytes; /* Number of bytes read */
1304
1305
1306 DEBUG_printf(("httpGets(%p, %d, %p)\n", line, length, http));
1307
1308 if (http == NULL || line == NULL)
1309 return (NULL);
1310
1311 /*
1312 * Pre-scan the buffer and see if there is a newline in there...
1313 */
1314
1315 #ifdef WIN32
1316 WSASetLastError(0);
1317 #else
1318 errno = 0;
1319 #endif /* WIN32 */
1320
1321 do
1322 {
1323 bufptr = http->buffer;
1324 bufend = http->buffer + http->used;
1325
1326 while (bufptr < bufend)
1327 if (*bufptr == 0x0a)
1328 break;
1329 else
1330 bufptr ++;
1331
1332 if (bufptr >= bufend && http->used < HTTP_MAX_BUFFER)
1333 {
1334 /*
1335 * No newline; see if there is more data to be read...
1336 */
1337
1338 if (!http->blocking && !httpWait(http, 1000))
1339 return (NULL);
1340
1341 #ifdef HAVE_SSL
1342 if (http->tls)
1343 bytes = http_read_ssl(http, bufend, HTTP_MAX_BUFFER - http->used);
1344 else
1345 #endif /* HAVE_SSL */
1346 bytes = recv(http->fd, bufend, HTTP_MAX_BUFFER - http->used, 0);
1347
1348 if (bytes < 0)
1349 {
1350 /*
1351 * Nope, can't get a line this time...
1352 */
1353
1354 #ifdef WIN32
1355 if (WSAGetLastError() != http->error)
1356 {
1357 http->error = WSAGetLastError();
1358 continue;
1359 }
1360
1361 DEBUG_printf(("httpGets(): recv() error %d!\n", WSAGetLastError()));
1362 #else
1363 if (errno == EINTR)
1364 continue;
1365 else if (errno != http->error)
1366 {
1367 http->error = errno;
1368 continue;
1369 }
1370
1371 DEBUG_printf(("httpGets(): recv() error %d!\n", errno));
1372 #endif /* WIN32 */
1373
1374 return (NULL);
1375 }
1376 else if (bytes == 0)
1377 {
1378 http->error = EPIPE;
1379
1380 return (NULL);
1381 }
1382
1383 /*
1384 * Yup, update the amount used and the end pointer...
1385 */
1386
1387 http->used += bytes;
1388 bufend += bytes;
1389 bufptr = bufend;
1390 }
1391 }
1392 while (bufptr >= bufend && http->used < HTTP_MAX_BUFFER);
1393
1394 http->activity = time(NULL);
1395
1396 /*
1397 * Read a line from the buffer...
1398 */
1399
1400 lineptr = line;
1401 bufptr = http->buffer;
1402 bytes = 0;
1403 length --;
1404
1405 while (bufptr < bufend && bytes < length)
1406 {
1407 bytes ++;
1408
1409 if (*bufptr == 0x0a)
1410 {
1411 bufptr ++;
1412 break;
1413 }
1414 else if (*bufptr == 0x0d)
1415 bufptr ++;
1416 else
1417 *lineptr++ = *bufptr++;
1418 }
1419
1420 if (bytes > 0)
1421 {
1422 *lineptr = '\0';
1423
1424 http->used -= bytes;
1425 if (http->used > 0)
1426 memmove(http->buffer, bufptr, http->used);
1427
1428 DEBUG_printf(("httpGets(): Returning \"%s\"\n", line));
1429 return (line);
1430 }
1431
1432 DEBUG_puts("httpGets(): No new line available!");
1433
1434 return (NULL);
1435 }
1436
1437
1438 /*
1439 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
1440 */
1441
1442 int /* O - Number of bytes written */
1443 httpPrintf(http_t *http, /* I - HTTP data */
1444 const char *format, /* I - printf-style format string */
1445 ...) /* I - Additional args as needed */
1446 {
1447 int bytes, /* Number of bytes to write */
1448 nbytes, /* Number of bytes written */
1449 tbytes; /* Number of bytes all together */
1450 char buf[HTTP_MAX_BUFFER], /* Buffer for formatted string */
1451 *bufptr; /* Pointer into buffer */
1452 va_list ap; /* Variable argument pointer */
1453
1454
1455 va_start(ap, format);
1456 bytes = vsnprintf(buf, sizeof(buf), format, ap);
1457 va_end(ap);
1458
1459 DEBUG_printf(("httpPrintf: %s", buf));
1460
1461 for (tbytes = 0, bufptr = buf; tbytes < bytes; tbytes += nbytes, bufptr += nbytes)
1462 {
1463 #ifdef HAVE_SSL
1464 if (http->tls)
1465 nbytes = http_write_ssl(http, bufptr, bytes - tbytes);
1466 else
1467 #endif /* HAVE_SSL */
1468 nbytes = send(http->fd, bufptr, bytes - tbytes, 0);
1469
1470 if (nbytes < 0)
1471 {
1472 nbytes = 0;
1473
1474 #ifdef WIN32
1475 if (WSAGetLastError() != http->error)
1476 {
1477 http->error = WSAGetLastError();
1478 continue;
1479 }
1480 #else
1481 if (errno == EINTR)
1482 continue;
1483 else if (errno != http->error)
1484 {
1485 http->error = errno;
1486 continue;
1487 }
1488 #endif /* WIN32 */
1489
1490 return (-1);
1491 }
1492 }
1493
1494 return (bytes);
1495 }
1496
1497
1498 /*
1499 * 'httpGetDateString()' - Get a formatted date/time string from a time value.
1500 */
1501
1502 const char * /* O - Date/time string */
1503 httpGetDateString(time_t t) /* I - UNIX time */
1504 {
1505 struct tm *tdate;
1506 static char datetime[256];
1507
1508
1509 tdate = gmtime(&t);
1510 snprintf(datetime, sizeof(datetime), "%s, %02d %s %d %02d:%02d:%02d GMT",
1511 days[tdate->tm_wday], tdate->tm_mday, months[tdate->tm_mon],
1512 tdate->tm_year + 1900, tdate->tm_hour, tdate->tm_min, tdate->tm_sec);
1513
1514 return (datetime);
1515 }
1516
1517
1518 /*
1519 * 'httpGetDateTime()' - Get a time value from a formatted date/time string.
1520 */
1521
1522 time_t /* O - UNIX time */
1523 httpGetDateTime(const char *s) /* I - Date/time string */
1524 {
1525 int i; /* Looping var */
1526 struct tm tdate; /* Time/date structure */
1527 char mon[16]; /* Abbreviated month name */
1528 int day, year; /* Day of month and year */
1529 int hour, min, sec; /* Time */
1530
1531
1532 if (sscanf(s, "%*s%d%15s%d%d:%d:%d", &day, mon, &year, &hour, &min, &sec) < 6)
1533 return (0);
1534
1535 for (i = 0; i < 12; i ++)
1536 if (strcasecmp(mon, months[i]) == 0)
1537 break;
1538
1539 if (i >= 12)
1540 return (0);
1541
1542 tdate.tm_mon = i;
1543 tdate.tm_mday = day;
1544 tdate.tm_year = year - 1900;
1545 tdate.tm_hour = hour;
1546 tdate.tm_min = min;
1547 tdate.tm_sec = sec;
1548 tdate.tm_isdst = 0;
1549
1550 return (mktime(&tdate));
1551 }
1552
1553
1554 /*
1555 * 'httpUpdate()' - Update the current HTTP state for incoming data.
1556 */
1557
1558 http_status_t /* O - HTTP status */
1559 httpUpdate(http_t *http) /* I - HTTP data */
1560 {
1561 char line[1024], /* Line from connection... */
1562 *value; /* Pointer to value on line */
1563 http_field_t field; /* Field index */
1564 int major, minor; /* HTTP version numbers */
1565 http_status_t status; /* Authorization status */
1566
1567
1568 DEBUG_printf(("httpUpdate(%p)\n", http));
1569
1570 /*
1571 * If we haven't issued any commands, then there is nothing to "update"...
1572 */
1573
1574 if (http->state == HTTP_WAITING)
1575 return (HTTP_CONTINUE);
1576
1577 /*
1578 * Grab all of the lines we can from the connection...
1579 */
1580
1581 while (httpGets(line, sizeof(line), http) != NULL)
1582 {
1583 DEBUG_puts(line);
1584
1585 if (line[0] == '\0')
1586 {
1587 /*
1588 * Blank line means the start of the data section (if any). Return
1589 * the result code, too...
1590 *
1591 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
1592 * Instead, we just return HTTP_CONTINUE to the caller and keep on
1593 * tryin'...
1594 */
1595
1596 if (http->status == HTTP_CONTINUE)
1597 return (http->status);
1598
1599 #ifdef HAVE_SSL
1600 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
1601 {
1602 if (http_setup_ssl(http) != 0)
1603 {
1604 #ifdef WIN32
1605 closesocket(http->fd);
1606 #else
1607 close(http->fd);
1608 #endif
1609
1610 return (HTTP_ERROR);
1611 }
1612
1613 return (HTTP_CONTINUE);
1614 }
1615 #endif /* HAVE_SSL */
1616
1617 httpGetLength(http);
1618
1619 switch (http->state)
1620 {
1621 case HTTP_GET :
1622 case HTTP_POST :
1623 case HTTP_POST_RECV :
1624 case HTTP_PUT :
1625 http->state ++;
1626 case HTTP_POST_SEND :
1627 break;
1628
1629 default :
1630 http->state = HTTP_WAITING;
1631 break;
1632 }
1633
1634 return (http->status);
1635 }
1636 else if (strncmp(line, "HTTP/", 5) == 0)
1637 {
1638 /*
1639 * Got the beginning of a response...
1640 */
1641
1642 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, (int *)&status) != 3)
1643 return (HTTP_ERROR);
1644
1645 http->version = (http_version_t)(major * 100 + minor);
1646 http->status = status;
1647 }
1648 else if ((value = strchr(line, ':')) != NULL)
1649 {
1650 /*
1651 * Got a value...
1652 */
1653
1654 *value++ = '\0';
1655 while (isspace(*value))
1656 value ++;
1657
1658 /*
1659 * Be tolerants of servers that send unknown attribute fields...
1660 */
1661
1662 if (!strcasecmp(line, "expect"))
1663 {
1664 /*
1665 * "Expect: 100-continue" or similar...
1666 */
1667
1668 http->expect = (http_status_t)atoi(value);
1669 }
1670 else if (!strcasecmp(line, "cookie"))
1671 {
1672 /*
1673 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
1674 */
1675
1676 httpSetCookie(http, value);
1677 }
1678 else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
1679 {
1680 DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line));
1681 continue;
1682 }
1683 else
1684 httpSetField(http, field, value);
1685 }
1686 else
1687 {
1688 http->status = HTTP_ERROR;
1689 return (HTTP_ERROR);
1690 }
1691 }
1692
1693 /*
1694 * See if there was an error...
1695 */
1696
1697 if (http->error)
1698 {
1699 http->status = HTTP_ERROR;
1700 return (HTTP_ERROR);
1701 }
1702
1703 /*
1704 * If we haven't already returned, then there is nothing new...
1705 */
1706
1707 return (HTTP_CONTINUE);
1708 }
1709
1710
1711 /*
1712 * 'httpDecode64()' - Base64-decode a string.
1713 */
1714
1715 char * /* O - Decoded string */
1716 httpDecode64(char *out, /* I - String to write to */
1717 const char *in) /* I - String to read from */
1718 {
1719 int pos, /* Bit position */
1720 base64; /* Value of this character */
1721 char *outptr; /* Output pointer */
1722
1723
1724 for (outptr = out, pos = 0; *in != '\0'; in ++)
1725 {
1726 /*
1727 * Decode this character into a number from 0 to 63...
1728 */
1729
1730 if (*in >= 'A' && *in <= 'Z')
1731 base64 = *in - 'A';
1732 else if (*in >= 'a' && *in <= 'z')
1733 base64 = *in - 'a' + 26;
1734 else if (*in >= '0' && *in <= '9')
1735 base64 = *in - '0' + 52;
1736 else if (*in == '+')
1737 base64 = 62;
1738 else if (*in == '/')
1739 base64 = 63;
1740 else if (*in == '=')
1741 break;
1742 else
1743 continue;
1744
1745 /*
1746 * Store the result in the appropriate chars...
1747 */
1748
1749 switch (pos)
1750 {
1751 case 0 :
1752 *outptr = base64 << 2;
1753 pos ++;
1754 break;
1755 case 1 :
1756 *outptr++ |= (base64 >> 4) & 3;
1757 *outptr = (base64 << 4) & 255;
1758 pos ++;
1759 break;
1760 case 2 :
1761 *outptr++ |= (base64 >> 2) & 15;
1762 *outptr = (base64 << 6) & 255;
1763 pos ++;
1764 break;
1765 case 3 :
1766 *outptr++ |= base64;
1767 pos = 0;
1768 break;
1769 }
1770 }
1771
1772 *outptr = '\0';
1773
1774 /*
1775 * Return the decoded string...
1776 */
1777
1778 return (out);
1779 }
1780
1781
1782 /*
1783 * 'httpEncode64()' - Base64-encode a string.
1784 */
1785
1786 char * /* O - Encoded string */
1787 httpEncode64(char *out, /* I - String to write to */
1788 const char *in) /* I - String to read from */
1789 {
1790 char *outptr; /* Output pointer */
1791 static const char base64[] = /* Base64 characters... */
1792 {
1793 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1794 "abcdefghijklmnopqrstuvwxyz"
1795 "0123456789"
1796 "+/"
1797 };
1798
1799
1800 for (outptr = out; *in != '\0'; in ++)
1801 {
1802 /*
1803 * Encode the up to 3 characters as 4 Base64 numbers...
1804 */
1805
1806 *outptr ++ = base64[in[0] >> 2];
1807 *outptr ++ = base64[((in[0] << 4) | (in[1] >> 4)) & 63];
1808
1809 in ++;
1810 if (*in == '\0')
1811 {
1812 *outptr ++ = '=';
1813 break;
1814 }
1815
1816 *outptr ++ = base64[((in[0] << 2) | (in[1] >> 6)) & 63];
1817
1818 in ++;
1819 if (*in == '\0')
1820 break;
1821
1822 *outptr ++ = base64[in[0] & 63];
1823 }
1824
1825 *outptr ++ = '=';
1826 *outptr = '\0';
1827
1828 /*
1829 * Return the encoded string...
1830 */
1831
1832 return (out);
1833 }
1834
1835
1836 /*
1837 * 'httpGetLength()' - Get the amount of data remaining from the
1838 * content-length or transfer-encoding fields.
1839 */
1840
1841 int /* O - Content length */
1842 httpGetLength(http_t *http) /* I - HTTP data */
1843 {
1844 DEBUG_printf(("httpGetLength(%p), state = %d\n", http, http->state));
1845
1846 if (strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked") == 0)
1847 {
1848 DEBUG_puts("httpGetLength: chunked request!");
1849
1850 http->data_encoding = HTTP_ENCODE_CHUNKED;
1851 http->data_remaining = 0;
1852 }
1853 else
1854 {
1855 http->data_encoding = HTTP_ENCODE_LENGTH;
1856
1857 /*
1858 * The following is a hack for HTTP servers that don't send a
1859 * content-length or transfer-encoding field...
1860 *
1861 * If there is no content-length then the connection must close
1862 * after the transfer is complete...
1863 */
1864
1865 if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
1866 http->data_remaining = 2147483647;
1867 else
1868 http->data_remaining = atoi(http->fields[HTTP_FIELD_CONTENT_LENGTH]);
1869
1870 DEBUG_printf(("httpGetLength: content_length = %d\n", http->data_remaining));
1871 }
1872
1873 return (http->data_remaining);
1874 }
1875
1876
1877 /*
1878 * 'http_field()' - Return the field index for a field name.
1879 */
1880
1881 static http_field_t /* O - Field index */
1882 http_field(const char *name) /* I - String name */
1883 {
1884 int i; /* Looping var */
1885
1886
1887 for (i = 0; i < HTTP_FIELD_MAX; i ++)
1888 if (strcasecmp(name, http_fields[i]) == 0)
1889 return ((http_field_t)i);
1890
1891 return (HTTP_FIELD_UNKNOWN);
1892 }
1893
1894
1895 /*
1896 * 'http_send()' - Send a request with all fields and the trailing blank line.
1897 */
1898
1899 static int /* O - 0 on success, non-zero on error */
1900 http_send(http_t *http, /* I - HTTP data */
1901 http_state_t request, /* I - Request code */
1902 const char *uri) /* I - URI */
1903 {
1904 int i; /* Looping var */
1905 char *ptr, /* Pointer in buffer */
1906 buf[1024]; /* Encoded URI buffer */
1907 static const char * const codes[] =
1908 { /* Request code strings */
1909 NULL,
1910 "OPTIONS",
1911 "GET",
1912 NULL,
1913 "HEAD",
1914 "POST",
1915 NULL,
1916 NULL,
1917 "PUT",
1918 NULL,
1919 "DELETE",
1920 "TRACE",
1921 "CLOSE"
1922 };
1923 static const char hex[] = "0123456789ABCDEF";
1924 /* Hex digits */
1925
1926
1927 if (http == NULL || uri == NULL)
1928 return (-1);
1929
1930 /*
1931 * Encode the URI as needed...
1932 */
1933
1934 for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++)
1935 if (*uri <= ' ' || *uri >= 127)
1936 {
1937 if (ptr < (buf + sizeof(buf) - 1))
1938 *ptr ++ = '%';
1939 if (ptr < (buf + sizeof(buf) - 1))
1940 *ptr ++ = hex[(*uri >> 4) & 15];
1941 if (ptr < (buf + sizeof(buf) - 1))
1942 *ptr ++ = hex[*uri & 15];
1943 }
1944 else
1945 *ptr ++ = *uri;
1946
1947 *ptr = '\0';
1948
1949 /*
1950 * See if we had an error the last time around; if so, reconnect...
1951 */
1952
1953 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
1954 httpReconnect(http);
1955
1956 /*
1957 * Send the request header...
1958 */
1959
1960 http->state = request;
1961 if (request == HTTP_POST || request == HTTP_PUT)
1962 http->state ++;
1963
1964 http->status = HTTP_CONTINUE;
1965
1966 #ifdef HAVE_SSL
1967 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
1968 {
1969 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
1970 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
1971 }
1972 #endif /* HAVE_SSL */
1973
1974 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
1975 {
1976 http->status = HTTP_ERROR;
1977 return (-1);
1978 }
1979
1980 for (i = 0; i < HTTP_FIELD_MAX; i ++)
1981 if (http->fields[i][0] != '\0')
1982 {
1983 DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i]));
1984
1985 if (httpPrintf(http, "%s: %s\r\n", http_fields[i], http->fields[i]) < 1)
1986 {
1987 http->status = HTTP_ERROR;
1988 return (-1);
1989 }
1990 }
1991
1992 if (httpPrintf(http, "\r\n") < 1)
1993 {
1994 http->status = HTTP_ERROR;
1995 return (-1);
1996 }
1997
1998 httpClearFields(http);
1999
2000 return (0);
2001 }
2002
2003
2004 #ifdef HAVE_SSL
2005 /*
2006 * 'http_upgrade()' - Force upgrade to TLS encryption.
2007 */
2008
2009 static int /* O - Status of connection */
2010 http_upgrade(http_t *http) /* I - HTTP data */
2011 {
2012 int ret; /* Return value */
2013 http_t myhttp; /* Local copy of HTTP data */
2014
2015
2016 DEBUG_printf(("http_upgrade(%p)\n", http));
2017
2018 /*
2019 * Copy the HTTP data to a local variable so we can do the OPTIONS
2020 * request without interfering with the existing request data...
2021 */
2022
2023 memcpy(&myhttp, http, sizeof(myhttp));
2024
2025 /*
2026 * Send an OPTIONS request to the server, requiring SSL or TLS
2027 * encryption on the link...
2028 */
2029
2030 httpClearFields(&myhttp);
2031 httpSetField(&myhttp, HTTP_FIELD_CONNECTION, "upgrade");
2032 httpSetField(&myhttp, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
2033
2034 if ((ret = httpOptions(&myhttp, "*")) == 0)
2035 {
2036 /*
2037 * Wait for the secure connection...
2038 */
2039
2040 while (httpUpdate(&myhttp) == HTTP_CONTINUE);
2041 }
2042
2043 httpFlush(&myhttp);
2044
2045 /*
2046 * Copy the HTTP data back over, if any...
2047 */
2048
2049 http->fd = myhttp.fd;
2050 http->error = myhttp.error;
2051 http->activity = myhttp.activity;
2052 http->status = myhttp.status;
2053 http->version = myhttp.version;
2054 http->keep_alive = myhttp.keep_alive;
2055 http->used = myhttp.used;
2056
2057 if (http->used)
2058 memcpy(http->buffer, myhttp.buffer, http->used);
2059
2060 http->auth_type = myhttp.auth_type;
2061 http->nonce_count = myhttp.nonce_count;
2062
2063 memcpy(http->nonce, myhttp.nonce, sizeof(http->nonce));
2064
2065 http->tls = myhttp.tls;
2066 http->encryption = myhttp.encryption;
2067
2068 /*
2069 * See if we actually went secure...
2070 */
2071
2072 if (!http->tls)
2073 {
2074 /*
2075 * Server does not support HTTP upgrade...
2076 */
2077
2078 DEBUG_puts("Server does not support HTTP upgrade!");
2079
2080 # ifdef WIN32
2081 closesocket(http->fd);
2082 # else
2083 close(http->fd);
2084 # endif
2085
2086 http->fd = -1;
2087
2088 return (-1);
2089 }
2090 else
2091 return (ret);
2092 }
2093
2094
2095 /*
2096 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
2097 */
2098
2099 static int /* O - Status of connection */
2100 http_setup_ssl(http_t *http) /* I - HTTP data */
2101 {
2102 # ifdef HAVE_LIBSSL
2103 SSL_CTX *context; /* Context for encryption */
2104 SSL *conn; /* Connection for encryption */
2105 # elif defined(HAVE_GNUTLS)
2106 http_tls_t *conn; /* TLS session object */
2107 gnutls_certificate_client_credentials *credentials;
2108 /* TLS credentials */
2109 # elif defined(HAVE_CDSASSL)
2110 SSLContextRef conn; /* Context for encryption */
2111 OSStatus error; /* Error info */
2112 # endif /* HAVE_LIBSSL */
2113
2114
2115 # ifdef HAVE_LIBSSL
2116 context = SSL_CTX_new(SSLv23_client_method());
2117 conn = SSL_new(context);
2118
2119 SSL_set_fd(conn, http->fd);
2120 if (SSL_connect(conn) != 1)
2121 {
2122 SSL_CTX_free(context);
2123 SSL_free(conn);
2124
2125 # ifdef WIN32
2126 http->error = WSAGetLastError();
2127 # else
2128 http->error = errno;
2129 # endif /* WIN32 */
2130 http->status = HTTP_ERROR;
2131
2132 return (HTTP_ERROR);
2133 }
2134
2135 # elif defined(HAVE_GNUTLS)
2136 conn = (http_tls_t *)malloc(sizeof(http_tls_t));
2137
2138 if (conn == NULL)
2139 {
2140 http->error = errno;
2141 http->status = HTTP_ERROR;
2142
2143 return (-1);
2144 }
2145
2146 credentials = (gnutls_certificate_client_credentials *)
2147 malloc(sizeof(gnutls_certificate_client_credentials));
2148 if (credentials == NULL)
2149 {
2150 free(conn);
2151
2152 http->error = errno;
2153 http->status = HTTP_ERROR;
2154
2155 return (-1);
2156 }
2157
2158 gnutls_certificate_allocate_credentials(credentials);
2159
2160 gnutls_init(&(conn->session), GNUTLS_CLIENT);
2161 gnutls_set_default_priority(conn->session);
2162 gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
2163 gnutls_transport_set_ptr(conn->session, http->fd);
2164
2165 if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
2166 {
2167 http->error = errno;
2168 http->status = HTTP_ERROR;
2169
2170 return (-1);
2171 }
2172
2173 conn->credentials = credentials;
2174
2175 # elif defined(HAVE_CDSASSL)
2176 error = SSLNewContext(false, &conn);
2177
2178 if (!error)
2179 error = SSLSetIOFuncs(conn, CDSAReadFunc, CDSAWriteFunc);
2180
2181 if (!error)
2182 error = SSLSetConnection(conn, (SSLConnectionRef)http->fd);
2183
2184 if (!error)
2185 error = SSLSetAllowsExpiredCerts(conn, true);
2186
2187 if (!error)
2188 error = SSLSetAllowsAnyRoot(conn, true);
2189
2190 if (!error)
2191 error = SSLHandshake(conn);
2192
2193 if (error != 0)
2194 {
2195 http->error = error;
2196 http->status = HTTP_ERROR;
2197
2198 SSLDisposeContext(conn);
2199
2200 close(http->fd);
2201
2202 return (-1);
2203 }
2204 # endif /* HAVE_CDSASSL */
2205
2206 http->tls = conn;
2207 return (0);
2208 }
2209
2210
2211 /*
2212 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
2213 */
2214
2215 static void
2216 http_shutdown_ssl(http_t *http) /* I - HTTP data */
2217 {
2218 # ifdef HAVE_LIBSSL
2219 SSL_CTX *context; /* Context for encryption */
2220 SSL *conn; /* Connection for encryption */
2221
2222
2223 conn = (SSL *)(http->tls);
2224 context = SSL_get_SSL_CTX(conn);
2225
2226 SSL_shutdown(conn);
2227 SSL_CTX_free(context);
2228 SSL_free(conn);
2229
2230 # elif defined(HAVE_GNUTLS)
2231 http_tls_t *conn; /* Encryption session */
2232 gnutls_certificate_client_credentials *credentials;
2233 /* TLS credentials */
2234
2235
2236 conn = (http_tls_t *)(http->tls);
2237 credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
2238
2239 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
2240 gnutls_deinit(conn->session);
2241 gnutls_certificate_free_credentials(*credentials);
2242 free(credentials);
2243 free(conn);
2244
2245 # elif defined(HAVE_CDSASSL)
2246 SSLClose((SSLContextRef)http->tls);
2247 SSLDisposeContext((SSLContextRef)http->tls);
2248 # endif /* HAVE_LIBSSL */
2249
2250 http->tls = NULL;
2251 }
2252
2253
2254 /*
2255 * 'http_read_ssl()' - Read from a SSL/TLS connection.
2256 */
2257
2258 static int /* O - Bytes read */
2259 http_read_ssl(http_t *http, /* I - HTTP data */
2260 char *buf, /* I - Buffer to store data */
2261 int len) /* I - Length of buffer */
2262 {
2263 # if defined(HAVE_LIBSSL)
2264 return (SSL_read((SSL *)(http->tls), buf, len));
2265
2266 # elif defined(HAVE_GNUTLS)
2267 return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len));
2268
2269 # elif defined(HAVE_CDSASSL)
2270 OSStatus error; /* Error info */
2271 size_t processed; /* Number of bytes processed */
2272
2273
2274 error = SSLRead((SSLContextRef)http->tls, buf, len, &processed);
2275
2276 if (error == 0)
2277 return (processed);
2278 else
2279 {
2280 http->error = error;
2281
2282 return (-1);
2283 }
2284 # endif /* HAVE_LIBSSL */
2285 }
2286
2287
2288 /*
2289 * 'http_write_ssl()' - Write to a SSL/TLS connection.
2290 */
2291
2292 static int /* O - Bytes written */
2293 http_write_ssl(http_t *http, /* I - HTTP data */
2294 const char *buf, /* I - Buffer holding data */
2295 int len) /* I - Length of buffer */
2296 {
2297 # if defined(HAVE_LIBSSL)
2298 return (SSL_write((SSL *)(http->tls), buf, len));
2299
2300 # elif defined(HAVE_GNUTLS)
2301 return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len));
2302 # elif defined(HAVE_CDSASSL)
2303 OSStatus error; /* Error info */
2304 size_t processed; /* Number of bytes processed */
2305
2306
2307 error = SSLWrite((SSLContextRef)http->tls, buf, len, &processed);
2308
2309 if (error == 0)
2310 return (processed);
2311 else
2312 {
2313 http->error = error;
2314 return (-1);
2315 }
2316 # endif /* HAVE_LIBSSL */
2317 }
2318
2319
2320 # if defined(HAVE_CDSASSL)
2321 /*
2322 * 'CDSAReadFunc()' - Read function for CDSA decryption code.
2323 */
2324
2325 static OSStatus /* O - -1 on error, 0 on success */
2326 CDSAReadFunc(SSLConnectionRef connection, /* I - SSL/TLS connection */
2327 void *data, /* I - Data buffer */
2328 size_t *dataLength) /* IO - Number of bytes */
2329 {
2330 ssize_t bytes; /* Number of bytes read */
2331
2332
2333 bytes = recv((int)connection, data, *dataLength, 0);
2334 if (bytes >= 0)
2335 {
2336 *dataLength = bytes;
2337 return (0);
2338 }
2339 else
2340 return (-1);
2341 }
2342
2343
2344 /*
2345 * 'CDSAWriteFunc()' - Write function for CDSA encryption code.
2346 */
2347
2348 static OSStatus /* O - -1 on error, 0 on success */
2349 CDSAWriteFunc(SSLConnectionRef connection, /* I - SSL/TLS connection */
2350 const void *data, /* I - Data buffer */
2351 size_t *dataLength) /* IO - Number of bytes */
2352 {
2353 ssize_t bytes;
2354
2355
2356 bytes = write((int)connection, data, *dataLength);
2357 if (bytes >= 0)
2358 {
2359 *dataLength = bytes;
2360 return (0);
2361 }
2362 else
2363 return (-1);
2364 }
2365 # endif /* HAVE_CDSASSL */
2366 #endif /* HAVE_SSL */
2367
2368
2369 /*
2370 * End of "$Id: http.c,v 1.117 2003/05/09 16:05:27 mike Exp $".
2371 */