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