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