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