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