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