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