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