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