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