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