]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Merge changes from CUPS 1.5svn-r9352.
[thirdparty/cups.git] / cups / http.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: http.c 7850 2008-08-20 00:07:25Z mike $"
ef416fc2 3 *
71e16022 4 * HTTP routines for CUPS.
ef416fc2 5 *
71e16022 6 * Copyright 2007-2010 by Apple Inc.
b86bc4cf 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 8 *
f7deaa1a 9 * This file contains Kerberos support code, copyright 2006 by
10 * Jelmer Vernooij.
11 *
ef416fc2 12 * These coded instructions, statements, and computer programs are the
bc44d920 13 * property of Apple Inc. and are protected by Federal copyright
14 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
15 * which should have been included with this file. If this file is
16 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 17 *
18 * This file is subject to the Apple OS-Developed Software exception.
19 *
20 * Contents:
21 *
7cf5915e
MS
22 * httpAddCredential() - Allocates and adds a single credential to an
23 * array.
24 * _httpBIOMethods() - Get the OpenSSL BIO methods for HTTP
25 * connections.
26 * httpBlocking() - Set blocking/non-blocking behavior on a
27 * connection.
28 * httpCheck() - Check to see if there is a pending response
29 * from the server.
30 * httpClearCookie() - Clear the cookie value(s).
31 * httpClearFields() - Clear HTTP request fields.
32 * httpClose() - Close an HTTP connection.
33 * httpConnect() - Connect to a HTTP server.
34 * httpConnectEncrypt() - Connect to a HTTP server using encryption.
35 * httpCopyCredentials() - Copy the credentials associated with an
36 * encrypted connection.
37 * _httpConvertCredentials() - Convert credentials to the internal format.
38 * _httpCreate() - Create an unconnected HTTP connection.
39 * httpDelete() - Send a DELETE request to the server.
40 * _httpDisconnect() - Disconnect a HTTP connection.
41 * httpEncryption() - Set the required encryption on the link.
42 * httpError() - Get the last error on a connection.
43 * httpFlush() - Flush data from a HTTP connection.
44 * httpFlushWrite() - Flush data in write buffer.
45 * _httpFreeCredentials() - Free internal credentials.
46 * httpFreeCredentials() - Free an array of credentials.
47 * httpGet() - Send a GET request to the server.
48 * httpGetAuthString() - Get the current authorization string.
49 * httpGetBlocking() - Get the blocking/non-block state of a
50 * connection.
51 * httpGetCookie() - Get any cookie data from the response.
52 * httpGetFd() - Get the file descriptor associated with a
53 * connection.
54 * httpGetField() - Get a field value from a request/response.
55 * httpGetLength() - Get the amount of data remaining from the
56 * content-length or transfer-encoding fields.
57 * httpGetLength2() - Get the amount of data remaining from the
58 * content-length or transfer-encoding fields.
59 * httpGetStatus() - Get the status of the last HTTP request.
60 * httpGetSubField() - Get a sub-field value.
61 * httpGetSubField2() - Get a sub-field value.
62 * httpGets() - Get a line of text from a HTTP connection.
63 * httpHead() - Send a HEAD request to the server.
64 * httpInitialize() - Initialize the HTTP interface library and set
65 * the default HTTP proxy (if any).
66 * httpOptions() - Send an OPTIONS request to the server.
67 * _httpPeek() - Peek at data from a HTTP connection.
68 * httpPost() - Send a POST request to the server.
69 * httpPrintf() - Print a formatted string to a HTTP connection.
70 * httpPut() - Send a PUT request to the server.
71 * httpRead() - Read data from a HTTP connection.
72 * httpRead2() - Read data from a HTTP connection.
73 * _httpReadCDSA() - Read function for the CDSA library.
74 * _httpReadGNUTLS() - Read function for the GNU TLS library.
75 * httpReconnect() - Reconnect to a HTTP server.
76 * httpSetAuthString() - Set the current authorization string.
77 * httpSetCredentials() - Set the credentials associated with an
78 * encrypted connection.
79 * httpSetCookie() - Set the cookie value(s).
80 * httpSetExpect() - Set the Expect: header in a request.
81 * httpSetField() - Set the value of an HTTP header.
82 * httpSetLength() - Set the content-length and content-encoding.
10d09e33
MS
83 * _httpSetTimeout() - Set read/write timeouts and an optional
84 * callback.
7cf5915e
MS
85 * httpTrace() - Send an TRACE request to the server.
86 * httpUpdate() - Update the current HTTP state for incoming
87 * data.
88 * _httpWait() - Wait for data available on a connection (no
89 * flush).
90 * httpWait() - Wait for data available on a connection.
91 * httpWrite() - Write data to a HTTP connection.
92 * httpWrite2() - Write data to a HTTP connection.
93 * _httpWriteCDSA() - Write function for the CDSA library.
94 * _httpWriteGNUTLS() - Write function for the GNU TLS library.
95 * http_bio_ctrl() - Control the HTTP connection.
96 * http_bio_free() - Free OpenSSL data.
97 * http_bio_new() - Initialize an OpenSSL BIO structure.
98 * http_bio_puts() - Send a string for OpenSSL.
99 * http_bio_read() - Read data for OpenSSL.
100 * http_bio_write() - Write data for OpenSSL.
101 * http_debug_hex() - Do a hex dump of a buffer.
102 * http_field() - Return the field index for a field name.
103 * http_read_ssl() - Read from a SSL/TLS connection.
104 * http_locking_cb() - Lock/unlock a thread's mutex.
105 * http_send() - Send a request with all fields and the trailing
106 * blank line.
107 * http_set_credentials() - Set the SSL/TLS credentials.
108 * http_setup_ssl() - Set up SSL/TLS support on a connection.
109 * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
110 * http_threadid_cb() - Return the current thread ID.
111 * http_upgrade() - Force upgrade to TLS encryption.
112 * http_write() - Write a buffer to a HTTP connection.
113 * http_write_chunk() - Write a chunked buffer.
114 * http_write_ssl() - Write to a SSL/TLS connection.
ef416fc2 115 */
116
117/*
118 * Include necessary headers...
119 */
120
71e16022 121#include "cups-private.h"
ef416fc2 122#include <fcntl.h>
cc754834
MS
123#ifdef WIN32
124# include <tchar.h>
125#else
ef416fc2 126# include <signal.h>
127# include <sys/time.h>
128# include <sys/resource.h>
cc754834 129#endif /* WIN32 */
f7deaa1a 130#ifdef HAVE_POLL
131# include <sys/poll.h>
132#endif /* HAVE_POLL */
ef416fc2 133
134
135/*
136 * Some operating systems have done away with the Fxxxx constants for
137 * the fcntl() call; this works around that "feature"...
138 */
139
140#ifndef FNONBLK
141# define FNONBLK O_NONBLOCK
142#endif /* !FNONBLK */
143
144
145/*
146 * Local functions...
147 */
148
ae71f5de
MS
149#ifdef DEBUG
150static void http_debug_hex(const char *prefix, const char *buffer,
151 int bytes);
152#endif /* DEBUG */
ef416fc2 153static http_field_t http_field(const char *name);
154static int http_send(http_t *http, http_state_t request,
155 const char *uri);
ef416fc2 156static int http_write(http_t *http, const char *buffer,
157 int length);
158static int http_write_chunk(http_t *http, const char *buffer,
159 int length);
160#ifdef HAVE_SSL
161static int http_read_ssl(http_t *http, char *buf, int len);
7cf5915e 162static int http_set_credentials(http_t *http);
ef416fc2 163static int http_setup_ssl(http_t *http);
164static void http_shutdown_ssl(http_t *http);
165static int http_upgrade(http_t *http);
166static int http_write_ssl(http_t *http, const char *buf, int len);
6d2f911b
MS
167
168# ifdef HAVE_GNUTLS
169# ifdef HAVE_PTHREAD_H
170GCRY_THREAD_OPTION_PTHREAD_IMPL;
171# endif /* HAVE_PTHREAD_H */
172
173# elif defined(HAVE_LIBSSL)
174static _cups_mutex_t *http_locks; /* OpenSSL lock mutexes */
175
176static void http_locking_cb(int mode, int type, const char *file,
177 int line);
178static unsigned long http_threadid_cb(void);
179# endif /* HAVE_GNUTLS */
ef416fc2 180#endif /* HAVE_SSL */
181
182
183/*
184 * Local globals...
185 */
186
187static const char * const http_fields[] =
188 {
189 "Accept-Language",
190 "Accept-Ranges",
191 "Authorization",
192 "Connection",
193 "Content-Encoding",
194 "Content-Language",
195 "Content-Length",
196 "Content-Location",
197 "Content-MD5",
198 "Content-Range",
199 "Content-Type",
200 "Content-Version",
201 "Date",
202 "Host",
203 "If-Modified-Since",
204 "If-Unmodified-since",
205 "Keep-Alive",
206 "Last-Modified",
207 "Link",
208 "Location",
209 "Range",
210 "Referer",
211 "Retry-After",
212 "Transfer-Encoding",
213 "Upgrade",
214 "User-Agent",
215 "WWW-Authenticate"
216 };
f11a948a
MS
217#ifdef DEBUG
218static const char * const http_states[] =
219 {
220 "HTTP_WAITING",
221 "HTTP_OPTIONS",
222 "HTTP_GET",
223 "HTTP_GET_SEND",
224 "HTTP_HEAD",
225 "HTTP_POST",
226 "HTTP_POST_RECV",
227 "HTTP_POST_SEND",
228 "HTTP_PUT",
229 "HTTP_PUT_RECV",
230 "HTTP_DELETE",
231 "HTTP_TRACE",
232 "HTTP_CLOSE",
233 "HTTP_STATUS"
234 };
235#endif /* DEBUG */
ef416fc2 236
237
411affcf 238#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
239/*
240 * BIO methods for OpenSSL...
241 */
242
243static int http_bio_write(BIO *h, const char *buf, int num);
244static int http_bio_read(BIO *h, char *buf, int size);
245static int http_bio_puts(BIO *h, const char *str);
246static long http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
247static int http_bio_new(BIO *h);
248static int http_bio_free(BIO *data);
249
250static BIO_METHOD http_bio_methods =
251 {
252 BIO_TYPE_SOCKET,
253 "http",
254 http_bio_write,
255 http_bio_read,
256 http_bio_puts,
257 NULL, /* http_bio_gets, */
258 http_bio_ctrl,
259 http_bio_new,
260 http_bio_free,
261 NULL,
262 };
7cf5915e 263#endif /* HAVE_SSL && HAVE_LIBSSL */
411affcf 264
265
7cf5915e
MS
266/*
267 * 'httpAddCredential()' - Allocates and adds a single credential to an array.
268 *
269 * Use @code cupsArrayNew(NULL, NULL)@ to create a credentials array.
270 *
271 * @since CUPS 1.5@
272 */
273
274int /* O - 0 on success, -1 on error */
275httpAddCredential(
276 cups_array_t *credentials, /* I - Credentials array */
277 const void *data, /* I - PEM-encoded X.509 data */
278 size_t datalen) /* I - Length of data */
279{
280 http_credential_t *credential; /* Credential data */
281
282
283 if ((credential = malloc(sizeof(http_credential_t))) != NULL)
284 {
285 credential->datalen = datalen;
286
287 if ((credential->data = malloc(datalen)) != NULL)
288 {
289 memcpy(credential->data, data, datalen);
290 cupsArrayAdd(credentials, credential);
291 return (0);
292 }
293
294 free(credential);
295 }
296
297 return (-1);
298}
299
300
301#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
411affcf 302/*
303 * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections.
304 */
305
306BIO_METHOD * /* O - BIO methods for OpenSSL */
307_httpBIOMethods(void)
308{
309 return (&http_bio_methods);
310}
311#endif /* HAVE_SSL && HAVE_LIBSSL */
312
313
ecdc0628 314/*
315 * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
316 */
317
318void
568fa3fa 319httpBlocking(http_t *http, /* I - Connection to server */
ecdc0628 320 int b) /* I - 1 = blocking, 0 = non-blocking */
321{
322 if (http)
323 http->blocking = b;
324}
325
326
ef416fc2 327/*
328 * 'httpCheck()' - Check to see if there is a pending response from the server.
329 */
330
ecdc0628 331int /* O - 0 = no data, 1 = data available */
568fa3fa 332httpCheck(http_t *http) /* I - Connection to server */
ef416fc2 333{
334 return (httpWait(http, 0));
335}
336
337
338/*
339 * 'httpClearCookie()' - Clear the cookie value(s).
340 *
426c6a59 341 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 342 */
343
344void
568fa3fa 345httpClearCookie(http_t *http) /* I - Connection to server */
ef416fc2 346{
347 if (!http)
348 return;
349
350 if (http->cookie)
351 {
352 free(http->cookie);
353 http->cookie = NULL;
354 }
355}
356
357
ecdc0628 358/*
359 * 'httpClearFields()' - Clear HTTP request fields.
360 */
361
362void
568fa3fa 363httpClearFields(http_t *http) /* I - Connection to server */
ecdc0628 364{
365 if (http)
366 {
367 memset(http->fields, 0, sizeof(http->fields));
07725fee 368 if (http->hostname[0] == '/')
369 httpSetField(http, HTTP_FIELD_HOST, "localhost");
370 else
371 httpSetField(http, HTTP_FIELD_HOST, http->hostname);
b423cd4c 372
f7deaa1a 373 if (http->field_authorization)
374 {
375 free(http->field_authorization);
376 http->field_authorization = NULL;
377 }
378
b423cd4c 379 http->expect = (http_status_t)0;
ecdc0628 380 }
381}
382
383
ef416fc2 384/*
6d2f911b 385 * 'httpClose()' - Close an HTTP connection.
ef416fc2 386 */
387
388void
568fa3fa 389httpClose(http_t *http) /* I - Connection to server */
ef416fc2 390{
f7deaa1a 391#ifdef HAVE_GSSAPI
1f0275e3 392 OM_uint32 minor_status; /* Minor status code */
f7deaa1a 393#endif /* HAVE_GSSAPI */
394
395
e07d4801 396 DEBUG_printf(("httpClose(http=%p)", http));
ef416fc2 397
6d2f911b
MS
398 /*
399 * Range check input...
400 */
401
ef416fc2 402 if (!http)
403 return;
404
6d2f911b
MS
405 /*
406 * Close any open connection...
407 */
408
409 _httpDisconnect(http);
410
411 /*
412 * Free memory used...
413 */
414
ef416fc2 415 httpAddrFreeList(http->addrlist);
416
ef416fc2 417 if (http->cookie)
418 free(http->cookie);
419
f7deaa1a 420#ifdef HAVE_GSSAPI
421 if (http->gssctx != GSS_C_NO_CONTEXT)
1f0275e3 422 gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
f7deaa1a 423
424 if (http->gssname != GSS_C_NO_NAME)
1f0275e3 425 gss_release_name(&minor_status, &http->gssname);
f7deaa1a 426#endif /* HAVE_GSSAPI */
427
b94498cf 428#ifdef HAVE_AUTHORIZATION_H
429 if (http->auth_ref)
430 AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
431#endif /* HAVE_AUTHORIZATION_H */
432
f7deaa1a 433 httpClearFields(http);
434
435 if (http->authstring && http->authstring != http->_authstring)
436 free(http->authstring);
437
ef416fc2 438 free(http);
439}
440
441
442/*
443 * 'httpConnect()' - Connect to a HTTP server.
1ff0402e
MS
444 *
445 * This function is deprecated - use @link httpConnectEncrypt@ instead.
446 *
447 * @deprecated@
ef416fc2 448 */
449
450http_t * /* O - New HTTP connection */
451httpConnect(const char *host, /* I - Host to connect to */
452 int port) /* I - Port number */
453{
1ff0402e
MS
454 return (httpConnectEncrypt(host, port, HTTP_ENCRYPT_IF_REQUESTED));
455}
456
457
458/*
459 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
460 */
461
462http_t * /* O - New HTTP connection */
463httpConnectEncrypt(
464 const char *host, /* I - Host to connect to */
465 int port, /* I - Port number */
466 http_encryption_t encryption) /* I - Type of encryption to use */
467{
468 http_t *http; /* New HTTP connection */
ef416fc2 469
470
e07d4801 471 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)",
1ff0402e
MS
472 host, port, encryption));
473
ef416fc2 474 /*
1ff0402e 475 * Create the HTTP structure...
ef416fc2 476 */
477
1ff0402e
MS
478 if ((http = _httpCreate(host, port, encryption)) == NULL)
479 return (NULL);
ef416fc2 480
1ff0402e
MS
481 /*
482 * Connect to the remote system...
483 */
484
485 if (!httpReconnect(http))
486 return (http);
487
488 /*
489 * Could not connect to any known address - bail out!
490 */
491
492 httpAddrFreeList(http->addrlist);
493
494 free(http);
495
496 return (NULL);
ef416fc2 497}
498
499
7cf5915e
MS
500/*
501 * 'httpCopyCredentials()' - Copy the credentials associated with an encrypted
502 * connection.
503 *
504 * @since CUPS 1.5@
505 */
506
507int /* O - Status of call (0 = success) */
508httpCopyCredentials(
509 http_t *http, /* I - Connection to server */
510 cups_array_t **credentials) /* O - Array of credentials */
511{
512# ifdef HAVE_LIBSSL
513# elif defined(HAVE_GNUTLS)
514# elif defined(HAVE_CDSASSL)
515 OSStatus error; /* Error code */
516 CFIndex count; /* Number of credentials */
517 CFArrayRef peerCerts; /* Peer certificates */
518 SecCertificateRef secCert; /* Certificate reference */
519 CFDataRef data; /* Certificate data */
520 int i; /* Looping var */
521# elif defined(HAVE_SSPISSL)
522# endif /* HAVE_LIBSSL */
523
524
525 if (credentials)
526 *credentials = NULL;
527
528 if (!http || !http->tls || !credentials)
529 return (-1);
530
531# ifdef HAVE_LIBSSL
532 return (-1);
533
534# elif defined(HAVE_GNUTLS)
535 return (-1);
536
537# elif defined(HAVE_CDSASSL)
538 if (!(error = SSLCopyPeerCertificates(http->tls, &peerCerts)) && peerCerts)
539 {
540 if ((*credentials = cupsArrayNew(NULL, NULL)) != NULL)
541 {
542 for (i = 0, count = CFArrayGetCount(peerCerts); i < count; i++)
543 {
544 secCert = (SecCertificateRef)CFArrayGetValueAtIndex(peerCerts, i);
545 if ((data = SecCertificateCopyData(secCert)))
546 {
547 httpAddCredential(*credentials, CFDataGetBytePtr(data),
548 CFDataGetLength(data));
549 CFRelease(data);
550 }
551 }
552 }
553
554 CFRelease(peerCerts);
555 }
556
557 return (error);
558
559# elif defined(HAVE_SSPISSL)
560 return (-1);
561# endif /* HAVE_LIBSSL */
562}
563
564
565/*
566 * '_httpConvertCredentials()' - Convert credentials to the internal format.
567 */
568
569http_tls_credentials_t /* O - Internal credentials */
570_httpConvertCredentials(
571 cups_array_t *credentials) /* I - Array of credentials */
572{
573 if (!credentials)
574 return (NULL);
575
576# ifdef HAVE_LIBSSL
577 return (NULL);
578
579# elif defined(HAVE_GNUTLS)
580 return (NULL);
581
582# elif defined(HAVE_CDSASSL)
583 CFMutableArrayRef peerCerts; /* Peer credentials reference */
584 SecCertificateRef secCert; /* Certificate reference */
585 CFDataRef data; /* Credential data reference */
586 http_credential_t *credential; /* Credential data */
587
588
589 if ((peerCerts = CFArrayCreateMutable(kCFAllocatorDefault,
590 cupsArrayCount(credentials),
591 &kCFTypeArrayCallBacks)) == NULL)
592 return (NULL);
593
594 for (credential = (http_credential_t *)cupsArrayFirst(credentials);
595 credential;
596 credential = (http_credential_t *)cupsArrayNext(credentials))
597 {
598 if ((data = CFDataCreate(kCFAllocatorDefault, credential->data,
599 credential->datalen)))
600 {
601 if ((secCert = SecCertificateCreateWithData(kCFAllocatorDefault, data))
602 != NULL)
603 {
604 CFArrayAppendValue(peerCerts, secCert);
605 CFRelease(secCert);
606 }
607
608 CFRelease(data);
609 }
610 }
611
612 return (peerCerts);
613
614# elif defined(HAVE_SSPISSL)
615 return (NULL);
616
617# else
618 return (NULL);
619# endif /* HAVE_LIBSSL */
620}
621
622
ef416fc2 623/*
1ff0402e 624 * '_httpCreate()' - Create an unconnected HTTP connection.
ef416fc2 625 */
626
1ff0402e
MS
627http_t * /* O - HTTP connection */
628_httpCreate(
629 const char *host, /* I - Hostname */
ef416fc2 630 int port, /* I - Port number */
1ff0402e 631 http_encryption_t encryption) /* I - Encryption to use */
ef416fc2 632{
633 http_t *http; /* New HTTP connection */
634 http_addrlist_t *addrlist; /* Host address data */
635 char service[255]; /* Service name */
636
637
e07d4801 638 DEBUG_printf(("4_httpCreate(host=\"%s\", port=%d, encryption=%d)",
1ff0402e 639 host, port, encryption));
ef416fc2 640
641 if (!host)
642 return (NULL);
643
644 httpInitialize();
645
646 /*
647 * Lookup the host...
648 */
649
650 sprintf(service, "%d", port);
651
652 if ((addrlist = httpAddrGetList(host, AF_UNSPEC, service)) == NULL)
653 return (NULL);
654
655 /*
656 * Allocate memory for the structure...
657 */
658
91c84a35
MS
659 if ((http = calloc(sizeof(http_t), 1)) == NULL)
660 {
661 httpAddrFreeList(addrlist);
ef416fc2 662 return (NULL);
91c84a35 663 }
ef416fc2 664
1ff0402e
MS
665 /*
666 * Initialize the HTTP data...
667 */
668
ef416fc2 669 http->activity = time(NULL);
1ff0402e
MS
670 http->addrlist = addrlist;
671 http->blocking = 1;
ef416fc2 672 http->fd = -1;
f7deaa1a 673#ifdef HAVE_GSSAPI
1ff0402e
MS
674 http->gssctx = GSS_C_NO_CONTEXT;
675 http->gssname = GSS_C_NO_NAME;
f7deaa1a 676#endif /* HAVE_GSSAPI */
1ff0402e 677 http->version = HTTP_1_1;
f7deaa1a 678
1ff0402e 679 strlcpy(http->hostname, host, sizeof(http->hostname));
ef416fc2 680
681 if (port == 443) /* Always use encryption for https */
682 http->encryption = HTTP_ENCRYPT_ALWAYS;
683 else
684 http->encryption = encryption;
685
686 /*
1ff0402e 687 * Return the new structure...
ef416fc2 688 */
689
1ff0402e 690 return (http);
ef416fc2 691}
692
693
694/*
695 * 'httpDelete()' - Send a DELETE request to the server.
696 */
697
698int /* O - Status of call (0 = success) */
568fa3fa 699httpDelete(http_t *http, /* I - Connection to server */
ef416fc2 700 const char *uri) /* I - URI to delete */
701{
702 return (http_send(http, HTTP_DELETE, uri));
703}
704
705
6d2f911b
MS
706/*
707 * '_httpDisconnect()' - Disconnect a HTTP connection.
708 */
709
710void
711_httpDisconnect(http_t *http) /* I - Connection to server */
712{
713#ifdef HAVE_SSL
714 if (http->tls)
715 http_shutdown_ssl(http);
716#endif /* HAVE_SSL */
717
718#ifdef WIN32
719 closesocket(http->fd);
720#else
721 close(http->fd);
722#endif /* WIN32 */
723
724 http->fd = -1;
725}
726
727
ef416fc2 728/*
729 * 'httpEncryption()' - Set the required encryption on the link.
730 */
731
732int /* O - -1 on error, 0 on success */
568fa3fa 733httpEncryption(http_t *http, /* I - Connection to server */
ef416fc2 734 http_encryption_t e) /* I - New encryption preference */
735{
e07d4801 736 DEBUG_printf(("httpEncryption(http=%p, e=%d)", http, e));
ef416fc2 737
738#ifdef HAVE_SSL
739 if (!http)
740 return (0);
741
742 http->encryption = e;
743
744 if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
745 (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
746 return (httpReconnect(http));
747 else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
748 return (http_upgrade(http));
749 else
750 return (0);
751#else
752 if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
753 return (-1);
754 else
755 return (0);
756#endif /* HAVE_SSL */
757}
758
759
ecdc0628 760/*
761 * 'httpError()' - Get the last error on a connection.
762 */
763
764int /* O - Error code (errno) value */
568fa3fa 765httpError(http_t *http) /* I - Connection to server */
ecdc0628 766{
767 if (http)
768 return (http->error);
769 else
770 return (EINVAL);
771}
772
773
ef416fc2 774/*
775 * 'httpFlush()' - Flush data from a HTTP connection.
776 */
777
778void
568fa3fa 779httpFlush(http_t *http) /* I - Connection to server */
ef416fc2 780{
f8b3a85b
MS
781 char buffer[8192]; /* Junk buffer */
782 int blocking; /* To block or not to block */
783 http_state_t oldstate; /* Old state */
ef416fc2 784
785
f11a948a
MS
786 DEBUG_printf(("httpFlush(http=%p), state=%s", http,
787 http_states[http->state]));
ef416fc2 788
fa73b229 789 /*
790 * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
791 */
792
793 blocking = http->blocking;
794 http->blocking = 0;
795
796 /*
797 * Read any data we can...
798 */
799
f8b3a85b 800 oldstate = http->state;
a4d04587 801 while (httpRead2(http, buffer, sizeof(buffer)) > 0);
fa73b229 802
803 /*
804 * Restore blocking and reset the connection if we didn't get all of
805 * the remaining data...
806 */
807
808 http->blocking = blocking;
809
aaf19ab0 810 if (http->state == oldstate && http->state != HTTP_WAITING && http->fd >= 0)
fa73b229 811 {
812 /*
813 * Didn't get the data back, so close the current connection.
814 */
815
816 http->state = HTTP_WAITING;
817
818#ifdef HAVE_SSL
819 if (http->tls)
820 http_shutdown_ssl(http);
821#endif /* HAVE_SSL */
822
823#ifdef WIN32
824 closesocket(http->fd);
825#else
826 close(http->fd);
827#endif /* WIN32 */
828
829 http->fd = -1;
830 }
ef416fc2 831}
832
833
834/*
835 * 'httpFlushWrite()' - Flush data in write buffer.
836 *
426c6a59 837 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 838 */
839
840int /* O - Bytes written or -1 on error */
568fa3fa 841httpFlushWrite(http_t *http) /* I - Connection to server */
ef416fc2 842{
843 int bytes; /* Bytes written */
844
845
e07d4801 846 DEBUG_printf(("httpFlushWrite(http=%p)", http));
ef416fc2 847
848 if (!http || !http->wused)
f8b3a85b
MS
849 {
850 DEBUG_puts(http ? "1httpFlushWrite: Write buffer is empty." :
851 "1httpFlushWrite: No connection.");
ef416fc2 852 return (0);
f8b3a85b 853 }
ef416fc2 854
855 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
856 bytes = http_write_chunk(http, http->wbuffer, http->wused);
857 else
858 bytes = http_write(http, http->wbuffer, http->wused);
859
860 http->wused = 0;
861
f8b3a85b
MS
862 DEBUG_printf(("1httpFlushWrite: Returning %d.", bytes));
863
ef416fc2 864 return (bytes);
865}
866
867
7cf5915e
MS
868/*
869 * '_httpFreeCredentials()' - Free internal credentials.
870 */
871
872void
873_httpFreeCredentials(
874 http_tls_credentials_t credentials) /* I - Internal credentials */
875{
876 if (!credentials)
877 return;
878
879#ifdef HAVE_LIBSSL
880 (void)credentials;
881
882#elif defined(HAVE_GNUTLS)
883 (void)credentials;
884
885#elif defined(HAVE_CDSASSL)
886 CFRelease(credentials);
887
888#elif defined(HAVE_SSPISSL)
889 (void)credentials;
890
891#endif /* HAVE_LIBSSL */
892}
893
894
895/*
896 * 'httpFreeCredentials()' - Free an array of credentials.
897 */
898
899void
900httpFreeCredentials(
901 cups_array_t *credentials) /* I - Array of credentials */
902{
903 http_credential_t *credential; /* Credential */
904
905
906 for (credential = (http_credential_t *)cupsArrayFirst(credentials);
907 credential;
908 credential = (http_credential_t *)cupsArrayNext(credentials))
909 {
910 cupsArrayRemove(credentials, credential);
911 free((void *)credential->data);
912 free(credential);
913 }
914
915 cupsArrayDelete(credentials);
916}
917
918
ef416fc2 919/*
920 * 'httpGet()' - Send a GET request to the server.
921 */
922
923int /* O - Status of call (0 = success) */
568fa3fa 924httpGet(http_t *http, /* I - Connection to server */
ef416fc2 925 const char *uri) /* I - URI to get */
926{
927 return (http_send(http, HTTP_GET, uri));
928}
929
930
355e94dc
MS
931/*
932 * 'httpGetAuthString()' - Get the current authorization string.
933 *
934 * The authorization string is set by cupsDoAuthentication() and
935 * httpSetAuthString(). Use httpGetAuthString() to retrieve the
936 * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION
937 * value.
938 *
426c6a59 939 * @since CUPS 1.3/Mac OS X 10.5@
355e94dc
MS
940 */
941
942char * /* O - Authorization string */
568fa3fa 943httpGetAuthString(http_t *http) /* I - Connection to server */
355e94dc
MS
944{
945 if (http)
946 return (http->authstring);
947 else
948 return (NULL);
949}
950
951
ecdc0628 952/*
953 * 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
954 *
426c6a59 955 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 956 */
957
958int /* O - 1 if blocking, 0 if non-blocking */
568fa3fa 959httpGetBlocking(http_t *http) /* I - Connection to server */
ecdc0628 960{
961 return (http ? http->blocking : 0);
962}
963
964
965/*
966 * 'httpGetCookie()' - Get any cookie data from the response.
757d2cad 967 *
426c6a59 968 * @since CUPS 1.1.19/Mac OS X 10.3@
ecdc0628 969 */
970
971const char * /* O - Cookie data or NULL */
972httpGetCookie(http_t *http) /* I - HTTP connecion */
973{
974 return (http ? http->cookie : NULL);
975}
976
977
978/*
979 * 'httpGetFd()' - Get the file descriptor associated with a connection.
980 *
426c6a59 981 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 982 */
983
984int /* O - File descriptor or -1 if none */
568fa3fa 985httpGetFd(http_t *http) /* I - Connection to server */
ecdc0628 986{
987 return (http ? http->fd : -1);
988}
989
990
991/*
992 * 'httpGetField()' - Get a field value from a request/response.
993 */
994
995const char * /* O - Field value */
568fa3fa 996httpGetField(http_t *http, /* I - Connection to server */
ecdc0628 997 http_field_t field) /* I - Field to get */
998{
999 if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
1000 return (NULL);
ef55b745 1001 else if (field == HTTP_FIELD_AUTHORIZATION &&
f7deaa1a 1002 http->field_authorization)
1003 {
1004 /*
1005 * Special case for WWW-Authenticate: as its contents can be
1006 * longer than HTTP_MAX_VALUE...
1007 */
1008
1009 return (http->field_authorization);
1010 }
ecdc0628 1011 else
1012 return (http->fields[field]);
1013}
1014
1015
1016/*
1017 * 'httpGetLength()' - Get the amount of data remaining from the
1018 * content-length or transfer-encoding fields.
1019 *
1020 * This function is deprecated and will not return lengths larger than
1021 * 2^31 - 1; use httpGetLength2() instead.
1022 *
1023 * @deprecated@
1024 */
1025
1026int /* O - Content length */
568fa3fa 1027httpGetLength(http_t *http) /* I - Connection to server */
ecdc0628 1028{
1029 /*
1030 * Get the read content length and return the 32-bit value.
1031 */
1032
1033 if (http)
1034 {
1035 httpGetLength2(http);
1036
1037 return (http->_data_remaining);
1038 }
1039 else
1040 return (-1);
1041}
1042
1043
1044/*
1045 * 'httpGetLength2()' - Get the amount of data remaining from the
1046 * content-length or transfer-encoding fields.
1047 *
1048 * This function returns the complete content length, even for
1049 * content larger than 2^31 - 1.
1050 *
426c6a59 1051 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 1052 */
1053
1054off_t /* O - Content length */
568fa3fa 1055httpGetLength2(http_t *http) /* I - Connection to server */
ecdc0628 1056{
f11a948a
MS
1057 DEBUG_printf(("2httpGetLength2(http=%p), state=%s", http,
1058 http_states[http->state]));
ecdc0628 1059
1060 if (!http)
1061 return (-1);
1062
1063 if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
1064 {
e07d4801 1065 DEBUG_puts("4httpGetLength2: chunked request!");
ecdc0628 1066
1067 http->data_encoding = HTTP_ENCODE_CHUNKED;
1068 http->data_remaining = 0;
1069 }
1070 else
1071 {
1072 http->data_encoding = HTTP_ENCODE_LENGTH;
1073
1074 /*
1075 * The following is a hack for HTTP servers that don't send a
1076 * content-length or transfer-encoding field...
1077 *
1078 * If there is no content-length then the connection must close
1079 * after the transfer is complete...
1080 */
1081
b86bc4cf 1082 if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
1083 {
1084 /*
1085 * Default content length is 0 for errors and 2^31-1 for other
1086 * successful requests...
1087 */
1088
1089 if (http->status >= HTTP_MULTIPLE_CHOICES)
1090 http->data_remaining = 0;
1091 else
1092 http->data_remaining = 2147483647;
1093 }
ecdc0628 1094 else
1095 http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
1096 NULL, 10);
1097
e07d4801 1098 DEBUG_printf(("4httpGetLength2: content_length=" CUPS_LLFMT,
ecdc0628 1099 CUPS_LLCAST http->data_remaining));
1100 }
1101
1102 if (http->data_remaining <= INT_MAX)
1103 http->_data_remaining = (int)http->data_remaining;
1104 else
1105 http->_data_remaining = INT_MAX;
1106
1107 return (http->data_remaining);
1108}
1109
1110
1111/*
1112 * 'httpGetStatus()' - Get the status of the last HTTP request.
1113 *
426c6a59 1114 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 1115 */
1116
1117http_status_t /* O - HTTP status */
568fa3fa 1118httpGetStatus(http_t *http) /* I - Connection to server */
ecdc0628 1119{
1120 return (http ? http->status : HTTP_ERROR);
1121}
1122
1123
ef416fc2 1124/*
1125 * 'httpGetSubField()' - Get a sub-field value.
1126 *
1127 * @deprecated@
1128 */
1129
1130char * /* O - Value or NULL */
568fa3fa 1131httpGetSubField(http_t *http, /* I - Connection to server */
ef416fc2 1132 http_field_t field, /* I - Field index */
1133 const char *name, /* I - Name of sub-field */
1134 char *value) /* O - Value string */
1135{
1136 return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
1137}
1138
1139
1140/*
1141 * 'httpGetSubField2()' - Get a sub-field value.
1142 *
426c6a59 1143 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 1144 */
1145
1146char * /* O - Value or NULL */
568fa3fa 1147httpGetSubField2(http_t *http, /* I - Connection to server */
ef416fc2 1148 http_field_t field, /* I - Field index */
1149 const char *name, /* I - Name of sub-field */
1150 char *value, /* O - Value string */
1151 int valuelen) /* I - Size of value buffer */
1152{
1153 const char *fptr; /* Pointer into field */
1154 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
1155 *ptr, /* Pointer into string buffer */
1156 *end; /* End of value buffer */
1157
e07d4801
MS
1158 DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, "
1159 "valuelen=%d)", http, field, name, value, valuelen));
ef416fc2 1160
1161 if (!http || !name || !value || valuelen < 2 ||
ecdc0628 1162 field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
ef416fc2 1163 return (NULL);
1164
1165 end = value + valuelen - 1;
1166
1167 for (fptr = http->fields[field]; *fptr;)
1168 {
1169 /*
1170 * Skip leading whitespace...
1171 */
1172
7cf5915e 1173 while (_cups_isspace(*fptr))
ef416fc2 1174 fptr ++;
1175
1176 if (*fptr == ',')
1177 {
1178 fptr ++;
1179 continue;
1180 }
1181
1182 /*
1183 * Get the sub-field name...
1184 */
1185
1186 for (ptr = temp;
7cf5915e 1187 *fptr && *fptr != '=' && !_cups_isspace(*fptr) &&
ef416fc2 1188 ptr < (temp + sizeof(temp) - 1);
1189 *ptr++ = *fptr++);
1190
1191 *ptr = '\0';
1192
e07d4801 1193 DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp));
ef416fc2 1194
1195 /*
1196 * Skip trailing chars up to the '='...
1197 */
1198
7cf5915e 1199 while (_cups_isspace(*fptr))
ef416fc2 1200 fptr ++;
1201
1202 if (!*fptr)
1203 break;
1204
1205 if (*fptr != '=')
1206 continue;
1207
1208 /*
1209 * Skip = and leading whitespace...
1210 */
1211
1212 fptr ++;
1213
7cf5915e 1214 while (_cups_isspace(*fptr))
ef416fc2 1215 fptr ++;
1216
1217 if (*fptr == '\"')
1218 {
1219 /*
1220 * Read quoted string...
1221 */
1222
1223 for (ptr = value, fptr ++;
1224 *fptr && *fptr != '\"' && ptr < end;
1225 *ptr++ = *fptr++);
1226
1227 *ptr = '\0';
1228
1229 while (*fptr && *fptr != '\"')
1230 fptr ++;
1231
1232 if (*fptr)
1233 fptr ++;
1234 }
1235 else
1236 {
1237 /*
1238 * Read unquoted string...
1239 */
1240
1241 for (ptr = value;
7cf5915e 1242 *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end;
ef416fc2 1243 *ptr++ = *fptr++);
1244
1245 *ptr = '\0';
1246
7cf5915e 1247 while (*fptr && !_cups_isspace(*fptr) && *fptr != ',')
ef416fc2 1248 fptr ++;
1249 }
1250
e07d4801 1251 DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value));
ef416fc2 1252
1253 /*
1254 * See if this is the one...
1255 */
1256
1257 if (!strcmp(name, temp))
e07d4801
MS
1258 {
1259 DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value));
ef416fc2 1260 return (value);
e07d4801 1261 }
ef416fc2 1262 }
1263
1264 value[0] = '\0';
1265
e07d4801
MS
1266 DEBUG_puts("3httpGetSubField2: Returning NULL");
1267
ef416fc2 1268 return (NULL);
1269}
1270
1271
ef416fc2 1272/*
1273 * 'httpGets()' - Get a line of text from a HTTP connection.
1274 */
1275
1276char * /* O - Line or NULL */
1277httpGets(char *line, /* I - Line to read into */
1278 int length, /* I - Max length of buffer */
568fa3fa 1279 http_t *http) /* I - Connection to server */
ef416fc2 1280{
1281 char *lineptr, /* Pointer into line */
1282 *lineend, /* End of line */
1283 *bufptr, /* Pointer into input buffer */
1284 *bufend; /* Pointer to end of buffer */
1285 int bytes, /* Number of bytes read */
1286 eol; /* End-of-line? */
1287
1288
e07d4801 1289 DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", line, length, http));
ef416fc2 1290
1291 if (http == NULL || line == NULL)
1292 return (NULL);
1293
1294 /*
1295 * Read a line from the buffer...
1296 */
f11a948a
MS
1297
1298 http->error = 0;
1299 lineptr = line;
1300 lineend = line + length - 1;
1301 eol = 0;
ef416fc2 1302
1303 while (lineptr < lineend)
1304 {
1305 /*
1306 * Pre-load the buffer as needed...
1307 */
1308
1309#ifdef WIN32
1310 WSASetLastError(0);
1311#else
1312 errno = 0;
1313#endif /* WIN32 */
1314
1315 while (http->used == 0)
1316 {
1317 /*
1318 * No newline; see if there is more data to be read...
1319 */
1320
38e73f87 1321 if (!http->blocking && !_httpWait(http, 10000, 1))
89d46774 1322 {
e07d4801 1323 DEBUG_puts("3httpGets: Timed out!");
b86bc4cf 1324#ifdef WIN32
1325 http->error = WSAETIMEDOUT;
1326#else
89d46774 1327 http->error = ETIMEDOUT;
b86bc4cf 1328#endif /* WIN32 */
ef416fc2 1329 return (NULL);
89d46774 1330 }
ef416fc2 1331
1332#ifdef HAVE_SSL
1333 if (http->tls)
1334 bytes = http_read_ssl(http, http->buffer + http->used,
1335 HTTP_MAX_BUFFER - http->used);
1336 else
1337#endif /* HAVE_SSL */
1338 bytes = recv(http->fd, http->buffer + http->used,
1339 HTTP_MAX_BUFFER - http->used, 0);
1340
e07d4801 1341 DEBUG_printf(("4httpGets: read %d bytes...", bytes));
ef416fc2 1342
1343 if (bytes < 0)
1344 {
1345 /*
1346 * Nope, can't get a line this time...
1347 */
1348
1349#ifdef WIN32
cc754834
MS
1350 DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError()));
1351
10d09e33 1352 if (WSAGetLastError() == WSAEINTR)
cc754834 1353 continue;
10d09e33
MS
1354 else if (WSAGetLastError() == WSAEWOULDBLOCK)
1355 {
1356 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1357 continue;
1358
1359 http->error = WSAGetLastError();
1360 }
cc754834 1361 else if (WSAGetLastError() != http->error)
ef416fc2 1362 {
1363 http->error = WSAGetLastError();
1364 continue;
1365 }
1366
ef416fc2 1367#else
e07d4801 1368 DEBUG_printf(("3httpGets: recv() error %d!", errno));
ef416fc2 1369
10d09e33 1370 if (errno == EINTR)
ef416fc2 1371 continue;
10d09e33
MS
1372 else if (errno == EWOULDBLOCK || errno == EAGAIN)
1373 {
1374 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1375 continue;
1376 else if (!http->timeout_cb && errno == EAGAIN)
1377 continue;
1378
1379 http->error = errno;
1380 }
ef416fc2 1381 else if (errno != http->error)
1382 {
1383 http->error = errno;
1384 continue;
1385 }
1386#endif /* WIN32 */
1387
1388 return (NULL);
1389 }
1390 else if (bytes == 0)
1391 {
1392 http->error = EPIPE;
1393
1394 return (NULL);
1395 }
1396
1397 /*
1398 * Yup, update the amount used...
1399 */
1400
1401 http->used += bytes;
1402 }
1403
1404 /*
1405 * Now copy as much of the current line as possible...
1406 */
1407
1408 for (bufptr = http->buffer, bufend = http->buffer + http->used;
1409 lineptr < lineend && bufptr < bufend;)
1410 {
1411 if (*bufptr == 0x0a)
1412 {
1413 eol = 1;
1414 bufptr ++;
1415 break;
1416 }
1417 else if (*bufptr == 0x0d)
1418 bufptr ++;
1419 else
1420 *lineptr++ = *bufptr++;
1421 }
1422
b86bc4cf 1423 http->used -= (int)(bufptr - http->buffer);
ef416fc2 1424 if (http->used > 0)
1425 memmove(http->buffer, bufptr, http->used);
1426
1427 if (eol)
1428 {
1429 /*
1430 * End of line...
1431 */
1432
1433 http->activity = time(NULL);
1434
1435 *lineptr = '\0';
ef55b745 1436
e07d4801 1437 DEBUG_printf(("3httpGets: Returning \"%s\"", line));
ef416fc2 1438
1439 return (line);
1440 }
1441 }
1442
e07d4801 1443 DEBUG_puts("3httpGets: No new line available!");
ef416fc2 1444
1445 return (NULL);
1446}
1447
1448
1449/*
1450 * 'httpHead()' - Send a HEAD request to the server.
1451 */
1452
1453int /* O - Status of call (0 = success) */
568fa3fa 1454httpHead(http_t *http, /* I - Connection to server */
ef416fc2 1455 const char *uri) /* I - URI for head */
1456{
e07d4801 1457 DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", http, uri));
ef416fc2 1458 return (http_send(http, HTTP_HEAD, uri));
1459}
1460
1461
1462/*
1463 * 'httpInitialize()' - Initialize the HTTP interface library and set the
1464 * default HTTP proxy (if any).
1465 */
1466
1467void
1468httpInitialize(void)
1469{
6d2f911b
MS
1470 static int initialized = 0; /* Have we been called before? */
1471#ifdef WIN32
1472 WSADATA winsockdata; /* WinSock data */
1473#endif /* WIN32 */
ef416fc2 1474#ifdef HAVE_LIBSSL
6d2f911b
MS
1475 int i; /* Looping var */
1476 unsigned char data[1024]; /* Seed data */
ef416fc2 1477#endif /* HAVE_LIBSSL */
1478
ef416fc2 1479
6d2f911b
MS
1480 _cupsGlobalLock();
1481 if (initialized)
1482 {
1483 _cupsGlobalUnlock();
1484 return;
1485 }
1486
1487#ifdef WIN32
c7017ecc 1488 WSAStartup(MAKEWORD(2,2), &winsockdata);
ef416fc2 1489
fa73b229 1490#elif !defined(SO_NOSIGPIPE)
ef416fc2 1491 /*
1492 * Ignore SIGPIPE signals...
1493 */
1494
fa73b229 1495# ifdef HAVE_SIGSET
1496 sigset(SIGPIPE, SIG_IGN);
6d2f911b 1497
fa73b229 1498# elif defined(HAVE_SIGACTION)
1499 struct sigaction action; /* POSIX sigaction data */
1500
1501
ef416fc2 1502 memset(&action, 0, sizeof(action));
1503 action.sa_handler = SIG_IGN;
1504 sigaction(SIGPIPE, &action, NULL);
6d2f911b 1505
fa73b229 1506# else
ef416fc2 1507 signal(SIGPIPE, SIG_IGN);
fa73b229 1508# endif /* !SO_NOSIGPIPE */
ef416fc2 1509#endif /* WIN32 */
1510
1511#ifdef HAVE_GNUTLS
6d2f911b
MS
1512 /*
1513 * Make sure we handle threading properly...
1514 */
1515
1516# ifdef HAVE_PTHREAD_H
1517 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
1518# endif /* HAVE_PTHREAD_H */
1519
1520 /*
1521 * Initialize GNU TLS...
1522 */
1523
ef416fc2 1524 gnutls_global_init();
ef416fc2 1525
6d2f911b
MS
1526#elif defined(HAVE_LIBSSL)
1527 /*
1528 * Initialize OpenSSL...
1529 */
1530
ef416fc2 1531 SSL_load_error_strings();
1532 SSL_library_init();
1533
6d2f911b
MS
1534 /*
1535 * Set the threading callbacks...
1536 */
1537
1538 http_locks = calloc(CRYPTO_num_locks(), sizeof(_cups_mutex_t));
1539# ifdef HAVE_PTHREAD_H
1540 for (i = 0; i < CRYPTO_num_locks(); i ++)
1541 pthread_mutex_init(http_locks + i, NULL);
1542# endif /* HAVE_PTHREAD_H */
1543
1544 CRYPTO_set_id_callback(http_threadid_cb);
1545 CRYPTO_set_locking_callback(http_locking_cb);
1546
ef416fc2 1547 /*
1548 * Using the current time is a dubious random seed, but on some systems
1549 * it is the best we can do (on others, this seed isn't even used...)
1550 */
1551
6d2f911b 1552 CUPS_SRAND(time(NULL));
ef416fc2 1553
1554 for (i = 0; i < sizeof(data); i ++)
6d2f911b 1555 data[i] = CUPS_RAND();
ef416fc2 1556
dfd5680b 1557 RAND_seed(data, sizeof(data));
6d2f911b
MS
1558#endif /* HAVE_GNUTLS */
1559
1560 initialized = 1;
1561 _cupsGlobalUnlock();
ef416fc2 1562}
1563
1564
1565/*
1566 * 'httpOptions()' - Send an OPTIONS request to the server.
1567 */
1568
1569int /* O - Status of call (0 = success) */
568fa3fa 1570httpOptions(http_t *http, /* I - Connection to server */
ef416fc2 1571 const char *uri) /* I - URI for options */
1572{
1573 return (http_send(http, HTTP_OPTIONS, uri));
1574}
1575
1576
6d2f911b
MS
1577/*
1578 * '_httpPeek()' - Peek at data from a HTTP connection.
1579 *
1580 * This function copies available data from the given HTTP connection, reading
1581 * a buffer as needed. The data is still available for reading using
1582 * @link httpRead@ or @link httpRead2@.
1583 *
1584 * For non-blocking connections the usual timeouts apply.
1585 */
1586
1587ssize_t /* O - Number of bytes copied */
1588_httpPeek(http_t *http, /* I - Connection to server */
1589 char *buffer, /* I - Buffer for data */
1590 size_t length) /* I - Maximum number of bytes */
1591{
1592 ssize_t bytes; /* Bytes read */
1593 char len[32]; /* Length string */
1594
1595
1596 DEBUG_printf(("_httpPeek(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
1597 http, buffer, CUPS_LLCAST length));
1598
1599 if (http == NULL || buffer == NULL)
1600 return (-1);
1601
1602 http->activity = time(NULL);
1603 http->error = 0;
1604
1605 if (length <= 0)
1606 return (0);
1607
1608 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1609 http->data_remaining <= 0)
1610 {
1611 DEBUG_puts("2_httpPeek: Getting chunk length...");
1612
1613 if (httpGets(len, sizeof(len), http) == NULL)
1614 {
1615 DEBUG_puts("1_httpPeek: Could not get length!");
1616 return (0);
1617 }
1618
1619 http->data_remaining = strtoll(len, NULL, 16);
1620 if (http->data_remaining < 0)
1621 {
1622 DEBUG_puts("1_httpPeek: Negative chunk length!");
1623 return (0);
1624 }
1625 }
1626
1627 DEBUG_printf(("2_httpPeek: data_remaining=" CUPS_LLFMT,
1628 CUPS_LLCAST http->data_remaining));
1629
1630 if (http->data_remaining <= 0)
1631 {
1632 /*
1633 * A zero-length chunk ends a transfer; unless we are reading POST
1634 * data, go idle...
1635 */
1636
1637 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1638 httpGets(len, sizeof(len), http);
1639
1640 if (http->state == HTTP_POST_RECV)
1641 http->state ++;
1642 else
1643 http->state = HTTP_WAITING;
1644
1645 /*
1646 * Prevent future reads for this request...
1647 */
1648
1649 http->data_encoding = HTTP_ENCODE_LENGTH;
1650
1651 return (0);
1652 }
1653 else if (length > (size_t)http->data_remaining)
1654 length = (size_t)http->data_remaining;
1655
1656 if (http->used == 0)
1657 {
1658 /*
1659 * Buffer small reads for better performance...
1660 */
1661
1662 if (!http->blocking && !httpWait(http, 10000))
1663 return (0);
1664
1665 if (http->data_remaining > sizeof(http->buffer))
1666 bytes = sizeof(http->buffer);
1667 else
1668 bytes = http->data_remaining;
1669
1670#ifdef HAVE_SSL
1671 if (http->tls)
1672 bytes = http_read_ssl(http, http->buffer, bytes);
1673 else
1674#endif /* HAVE_SSL */
1675 {
1676 DEBUG_printf(("2_httpPeek: reading %d bytes from socket into buffer...",
1677 (int)bytes));
1678
1679 bytes = recv(http->fd, http->buffer, bytes, 0);
1680
1681 DEBUG_printf(("2_httpPeek: read %d bytes from socket into buffer...",
1682 (int)bytes));
1683 }
1684
1685 if (bytes > 0)
1686 http->used = bytes;
1687 else if (bytes < 0)
1688 {
1689#ifdef WIN32
cc754834
MS
1690 if (WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK)
1691 {
1692 http->error = WSAGetLastError();
1693 return (-1);
1694 }
6d2f911b
MS
1695#else
1696 if (errno != EINTR && errno != EAGAIN)
1697 {
1698 http->error = errno;
1699 return (-1);
1700 }
1701#endif /* WIN32 */
1702 }
1703 else
1704 {
1705 http->error = EPIPE;
1706 return (0);
1707 }
1708 }
1709
1710 if (http->used > 0)
1711 {
1712 if (length > (size_t)http->used)
1713 length = (size_t)http->used;
1714
1715 bytes = (ssize_t)length;
1716
1717 DEBUG_printf(("2_httpPeek: grabbing %d bytes from input buffer...",
1718 (int)bytes));
1719
1720 memcpy(buffer, http->buffer, length);
1721 }
1722 else
1723 bytes = 0;
1724
1725 if (bytes < 0)
1726 {
1727#ifdef WIN32
cc754834
MS
1728 if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)
1729 bytes = 0;
1730 else
1731 http->error = WSAGetLastError();
6d2f911b
MS
1732#else
1733 if (errno == EINTR || errno == EAGAIN)
1734 bytes = 0;
1735 else
1736 http->error = errno;
1737#endif /* WIN32 */
1738 }
1739 else if (bytes == 0)
1740 {
1741 http->error = EPIPE;
1742 return (0);
1743 }
1744
1745#ifdef DEBUG
1746 http_debug_hex("_httpPeek", buffer, (int)bytes);
1747#endif /* DEBUG */
1748
1749 return (bytes);
1750}
1751
1752
ef416fc2 1753/*
1754 * 'httpPost()' - Send a POST request to the server.
1755 */
1756
1757int /* O - Status of call (0 = success) */
568fa3fa 1758httpPost(http_t *http, /* I - Connection to server */
ef416fc2 1759 const char *uri) /* I - URI for post */
1760{
1761 return (http_send(http, HTTP_POST, uri));
1762}
1763
1764
1765/*
1766 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
ecdc0628 1767 *
1768 * @private@
ef416fc2 1769 */
1770
1771int /* O - Number of bytes written */
568fa3fa 1772httpPrintf(http_t *http, /* I - Connection to server */
ef416fc2 1773 const char *format, /* I - printf-style format string */
1774 ...) /* I - Additional args as needed */
1775{
1776 int bytes; /* Number of bytes to write */
1777 char buf[16384]; /* Buffer for formatted string */
1778 va_list ap; /* Variable argument pointer */
1779
1780
e07d4801 1781 DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", http, format));
ef416fc2 1782
1783 va_start(ap, format);
1784 bytes = vsnprintf(buf, sizeof(buf), format, ap);
1785 va_end(ap);
1786
e07d4801 1787 DEBUG_printf(("3httpPrintf: %s", buf));
ef416fc2 1788
d09495fa 1789 if (http->data_encoding == HTTP_ENCODE_FIELDS)
1790 return (httpWrite2(http, buf, bytes));
1791 else
ef416fc2 1792 {
d09495fa 1793 if (http->wused)
1794 {
e07d4801 1795 DEBUG_puts("4httpPrintf: flushing existing data...");
ef416fc2 1796
d09495fa 1797 if (httpFlushWrite(http) < 0)
1798 return (-1);
1799 }
ef416fc2 1800
d09495fa 1801 return (http_write(http, buf, bytes));
1802 }
ef416fc2 1803}
1804
1805
1806/*
1807 * 'httpPut()' - Send a PUT request to the server.
1808 */
1809
1810int /* O - Status of call (0 = success) */
568fa3fa 1811httpPut(http_t *http, /* I - Connection to server */
ef416fc2 1812 const char *uri) /* I - URI to put */
1813{
e07d4801 1814 DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", http, uri));
ef416fc2 1815 return (http_send(http, HTTP_PUT, uri));
1816}
1817
1818
1819/*
1820 * 'httpRead()' - Read data from a HTTP connection.
a4d04587 1821 *
1822 * This function is deprecated. Use the httpRead2() function which can
1823 * read more than 2GB of data.
1824 *
1825 * @deprecated@
ef416fc2 1826 */
1827
1828int /* O - Number of bytes read */
568fa3fa 1829httpRead(http_t *http, /* I - Connection to server */
ef416fc2 1830 char *buffer, /* I - Buffer for data */
1831 int length) /* I - Maximum number of bytes */
1832{
a4d04587 1833 return ((int)httpRead2(http, buffer, length));
1834}
1835
1836
1837/*
1838 * 'httpRead2()' - Read data from a HTTP connection.
ecdc0628 1839 *
426c6a59 1840 * @since CUPS 1.2/Mac OS X 10.5@
a4d04587 1841 */
1842
1843ssize_t /* O - Number of bytes read */
568fa3fa 1844httpRead2(http_t *http, /* I - Connection to server */
a4d04587 1845 char *buffer, /* I - Buffer for data */
1846 size_t length) /* I - Maximum number of bytes */
1847{
1848 ssize_t bytes; /* Bytes read */
ef416fc2 1849 char len[32]; /* Length string */
1850
1851
e07d4801 1852 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
a603edef 1853 http, buffer, CUPS_LLCAST length));
ef416fc2 1854
1855 if (http == NULL || buffer == NULL)
1856 return (-1);
1857
1858 http->activity = time(NULL);
f11a948a 1859 http->error = 0;
ef416fc2 1860
1861 if (length <= 0)
1862 return (0);
1863
1864 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1865 http->data_remaining <= 0)
1866 {
e07d4801 1867 DEBUG_puts("2httpRead2: Getting chunk length...");
ef416fc2 1868
1869 if (httpGets(len, sizeof(len), http) == NULL)
1870 {
e07d4801 1871 DEBUG_puts("1httpRead2: Could not get length!");
ef416fc2 1872 return (0);
1873 }
1874
1875 http->data_remaining = strtoll(len, NULL, 16);
1876 if (http->data_remaining < 0)
1877 {
e07d4801 1878 DEBUG_puts("1httpRead2: Negative chunk length!");
ef416fc2 1879 return (0);
1880 }
1881 }
1882
e07d4801 1883 DEBUG_printf(("2httpRead2: data_remaining=" CUPS_LLFMT,
ef416fc2 1884 CUPS_LLCAST http->data_remaining));
1885
1886 if (http->data_remaining <= 0)
1887 {
1888 /*
1889 * A zero-length chunk ends a transfer; unless we are reading POST
1890 * data, go idle...
1891 */
1892
1893 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1894 httpGets(len, sizeof(len), http);
1895
1896 if (http->state == HTTP_POST_RECV)
1897 http->state ++;
1898 else
1899 http->state = HTTP_WAITING;
1900
1901 /*
1902 * Prevent future reads for this request...
1903 */
1904
1905 http->data_encoding = HTTP_ENCODE_LENGTH;
1906
1907 return (0);
1908 }
b86bc4cf 1909 else if (length > (size_t)http->data_remaining)
1910 length = (size_t)http->data_remaining;
ef416fc2 1911
1912 if (http->used == 0 && length <= 256)
1913 {
1914 /*
1915 * Buffer small reads for better performance...
1916 */
1917
ed486911 1918 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 1919 return (0);
1920
1921 if (http->data_remaining > sizeof(http->buffer))
1922 bytes = sizeof(http->buffer);
1923 else
1924 bytes = http->data_remaining;
1925
1926#ifdef HAVE_SSL
1927 if (http->tls)
1928 bytes = http_read_ssl(http, http->buffer, bytes);
1929 else
1930#endif /* HAVE_SSL */
1931 {
e07d4801 1932 DEBUG_printf(("2httpRead2: reading %d bytes from socket into buffer...",
a603edef 1933 (int)bytes));
ef416fc2 1934
1935 bytes = recv(http->fd, http->buffer, bytes, 0);
1936
e07d4801 1937 DEBUG_printf(("2httpRead2: read %d bytes from socket into buffer...",
a603edef 1938 (int)bytes));
ef416fc2 1939 }
1940
1941 if (bytes > 0)
1942 http->used = bytes;
1943 else if (bytes < 0)
1944 {
1945#ifdef WIN32
10d09e33 1946 if (WSAGetLastError() != WSAEINTR)
cc754834
MS
1947 {
1948 http->error = WSAGetLastError();
1949 return (-1);
1950 }
10d09e33
MS
1951 else if (WSAGetLastError() == WSAEWOULDBLOCK)
1952 {
1953 if (!http->timeout_cb || !(*http->timeout_cb)(http, http->timeout_data))
1954 {
1955 http->error = WSAEWOULDBLOCK;
1956 return (-1);
1957 }
1958 }
ef416fc2 1959#else
10d09e33
MS
1960 if (errno == EWOULDBLOCK || errno == EAGAIN)
1961 {
1962 if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
1963 {
1964 http->error = errno;
1965 return (-1);
1966 }
1967 else if (!http->timeout_cb && errno != EAGAIN)
1968 {
1969 http->error = errno;
1970 return (-1);
1971 }
1972 }
1973 else if (errno != EINTR)
ef416fc2 1974 {
1975 http->error = errno;
1976 return (-1);
1977 }
1978#endif /* WIN32 */
1979 }
1980 else
1981 {
1982 http->error = EPIPE;
1983 return (0);
1984 }
1985 }
1986
1987 if (http->used > 0)
1988 {
b86bc4cf 1989 if (length > (size_t)http->used)
1990 length = (size_t)http->used;
ef416fc2 1991
b86bc4cf 1992 bytes = (ssize_t)length;
ef416fc2 1993
e07d4801 1994 DEBUG_printf(("2httpRead2: grabbing %d bytes from input buffer...",
a603edef 1995 (int)bytes));
ef416fc2 1996
1997 memcpy(buffer, http->buffer, length);
b86bc4cf 1998 http->used -= (int)length;
ef416fc2 1999
2000 if (http->used > 0)
2001 memmove(http->buffer, http->buffer + length, http->used);
2002 }
2003#ifdef HAVE_SSL
2004 else if (http->tls)
2005 {
ed486911 2006 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 2007 return (0);
2008
b86bc4cf 2009 bytes = (ssize_t)http_read_ssl(http, buffer, (int)length);
ef416fc2 2010 }
2011#endif /* HAVE_SSL */
2012 else
2013 {
ed486911 2014 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 2015 return (0);
2016
e07d4801 2017 DEBUG_printf(("2httpRead2: reading " CUPS_LLFMT " bytes from socket...",
a603edef 2018 CUPS_LLCAST length));
ef416fc2 2019
b86bc4cf 2020#ifdef WIN32
10d09e33
MS
2021 while ((bytes = (ssize_t)recv(http->fd, buffer, (int)length, 0)) < 0)
2022 {
2023 if (WSAGetLastError() == WSAEWOULDBLOCK)
2024 {
2025 if (!http->timeout_cb || !(*http->timeout_cb)(http, http->timeout_data))
2026 break;
2027 }
2028 else if (WSAGetLastError() != WSAEINTR)
cc754834 2029 break;
10d09e33 2030 }
b86bc4cf 2031#else
ef416fc2 2032 while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
10d09e33
MS
2033 {
2034 if (errno == EWOULDBLOCK || errno == EAGAIN)
2035 {
2036 if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
2037 break;
2038 else if (!http->timeout_cb && errno != EAGAIN)
2039 break;
2040 }
2041 else if (errno != EINTR)
ef416fc2 2042 break;
10d09e33 2043 }
b86bc4cf 2044#endif /* WIN32 */
ef416fc2 2045
e07d4801 2046 DEBUG_printf(("2httpRead2: read " CUPS_LLFMT " bytes from socket...",
a603edef 2047 CUPS_LLCAST bytes));
ef416fc2 2048 }
2049
2050 if (bytes > 0)
2051 {
2052 http->data_remaining -= bytes;
2053
2054 if (http->data_remaining <= INT_MAX)
2055 http->_data_remaining = (int)http->data_remaining;
2056 else
2057 http->_data_remaining = INT_MAX;
2058 }
2059 else if (bytes < 0)
2060 {
2061#ifdef WIN32
10d09e33 2062 if (WSAGetLastError() == WSAEINTR)
cc754834
MS
2063 bytes = 0;
2064 else
2065 http->error = WSAGetLastError();
ef416fc2 2066#else
10d09e33 2067 if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb))
ef416fc2 2068 bytes = 0;
2069 else
2070 http->error = errno;
2071#endif /* WIN32 */
2072 }
2073 else
2074 {
2075 http->error = EPIPE;
2076 return (0);
2077 }
2078
2079 if (http->data_remaining == 0)
2080 {
2081 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
2082 httpGets(len, sizeof(len), http);
2083
2084 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
2085 {
2086 if (http->state == HTTP_POST_RECV)
2087 http->state ++;
2088 else
2089 http->state = HTTP_WAITING;
2090 }
2091 }
2092
2093#ifdef DEBUG
ae71f5de 2094 http_debug_hex("httpRead2", buffer, (int)bytes);
ef416fc2 2095#endif /* DEBUG */
2096
2097 return (bytes);
2098}
2099
2100
2101#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
2102/*
411affcf 2103 * '_httpReadCDSA()' - Read function for the CDSA library.
ef416fc2 2104 */
2105
2106OSStatus /* O - -1 on error, 0 on success */
2107_httpReadCDSA(
2108 SSLConnectionRef connection, /* I - SSL/TLS connection */
2109 void *data, /* I - Data buffer */
2110 size_t *dataLength) /* IO - Number of bytes */
2111{
411affcf 2112 OSStatus result; /* Return value */
2113 ssize_t bytes; /* Number of bytes read */
2114 http_t *http; /* HTTP connection */
2115
2116
2117 http = (http_t *)connection;
e53920b9 2118
411affcf 2119 if (!http->blocking)
2120 {
2121 /*
2122 * Make sure we have data before we read...
2123 */
e53920b9 2124
38e73f87 2125 if (!_httpWait(http, 10000, 0))
411affcf 2126 {
2127 http->error = ETIMEDOUT;
2128 return (-1);
2129 }
2130 }
ef416fc2 2131
b423cd4c 2132 do
411affcf 2133 {
2134 bytes = recv(http->fd, data, *dataLength, 0);
2135 }
e07d4801 2136 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 2137
b423cd4c 2138 if (bytes == *dataLength)
411affcf 2139 {
b423cd4c 2140 result = 0;
411affcf 2141 }
b423cd4c 2142 else if (bytes > 0)
2143 {
2144 *dataLength = bytes;
2145 result = errSSLWouldBlock;
2146 }
2147 else
2148 {
2149 *dataLength = 0;
fa73b229 2150
2151 if (bytes == 0)
ed486911 2152 result = errSSLClosedGraceful;
b423cd4c 2153 else if (errno == EAGAIN)
2154 result = errSSLWouldBlock;
b423cd4c 2155 else
ed486911 2156 result = errSSLClosedAbort;
ef416fc2 2157 }
b423cd4c 2158
411affcf 2159 return (result);
ef416fc2 2160}
2161#endif /* HAVE_SSL && HAVE_CDSASSL */
2162
2163
411affcf 2164#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
2165/*
2166 * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
2167 */
2168
2169ssize_t /* O - Number of bytes read or -1 on error */
2170_httpReadGNUTLS(
568fa3fa 2171 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 2172 void *data, /* I - Buffer */
2173 size_t length) /* I - Number of bytes to read */
2174{
2175 http_t *http; /* HTTP connection */
2176
2177
2178 http = (http_t *)ptr;
2179
2180 if (!http->blocking)
2181 {
2182 /*
2183 * Make sure we have data before we read...
2184 */
2185
38e73f87 2186 if (!_httpWait(http, 10000, 0))
411affcf 2187 {
2188 http->error = ETIMEDOUT;
2189 return (-1);
2190 }
2191 }
2192
2193 return (recv(http->fd, data, length, 0));
2194}
2195#endif /* HAVE_SSL && HAVE_GNUTLS */
2196
2197
ef416fc2 2198/*
ecdc0628 2199 * 'httpReconnect()' - Reconnect to a HTTP server.
ef416fc2 2200 */
2201
2202int /* O - 0 on success, non-zero on failure */
568fa3fa 2203httpReconnect(http_t *http) /* I - Connection to server */
ef416fc2 2204{
2205 http_addrlist_t *addr; /* Connected address */
1ff0402e
MS
2206#ifdef DEBUG
2207 http_addrlist_t *current; /* Current address */
2208 char temp[256]; /* Temporary address string */
2209#endif /* DEBUG */
ef416fc2 2210
2211
e07d4801 2212 DEBUG_printf(("httpReconnect(http=%p)", http));
ef416fc2 2213
2214 if (!http)
2215 return (-1);
2216
2217#ifdef HAVE_SSL
2218 if (http->tls)
1ff0402e 2219 {
e07d4801 2220 DEBUG_puts("2httpReconnect: Shutting down SSL/TLS...");
ef416fc2 2221 http_shutdown_ssl(http);
1ff0402e 2222 }
ef416fc2 2223#endif /* HAVE_SSL */
2224
2225 /*
2226 * Close any previously open socket...
2227 */
2228
2229 if (http->fd >= 0)
bd7854cb 2230 {
e07d4801 2231 DEBUG_printf(("2httpReconnect: Closing socket %d...", http->fd));
1ff0402e 2232
ef416fc2 2233#ifdef WIN32
2234 closesocket(http->fd);
2235#else
2236 close(http->fd);
2237#endif /* WIN32 */
2238
bd7854cb 2239 http->fd = -1;
2240 }
2241
ef416fc2 2242 /*
2243 * Connect to the server...
2244 */
2245
1ff0402e
MS
2246#ifdef DEBUG
2247 for (current = http->addrlist; current; current = current->next)
e07d4801 2248 DEBUG_printf(("2httpReconnect: Address %s:%d",
1ff0402e
MS
2249 httpAddrString(&(current->addr), temp, sizeof(temp)),
2250 _httpAddrPort(&(current->addr))));
2251#endif /* DEBUG */
2252
ef416fc2 2253 if ((addr = httpAddrConnect(http->addrlist, &(http->fd))) == NULL)
2254 {
2255 /*
2256 * Unable to connect...
2257 */
2258
2259#ifdef WIN32
2260 http->error = WSAGetLastError();
2261#else
2262 http->error = errno;
2263#endif /* WIN32 */
2264 http->status = HTTP_ERROR;
2265
e07d4801 2266 DEBUG_printf(("1httpReconnect: httpAddrConnect failed: %s",
1ff0402e
MS
2267 strerror(http->error)));
2268
ef416fc2 2269 return (-1);
2270 }
2271
e07d4801 2272 DEBUG_printf(("2httpReconnect: New socket=%d", http->fd));
1ff0402e 2273
10d09e33
MS
2274 if (http->timeout_value.tv_sec > 0)
2275 {
2276 setsockopt(http->fd, SOL_SOCKET, SO_RCVTIMEO, &(http->timeout_value),
2277 sizeof(http->timeout_value));
2278 setsockopt(http->fd, SOL_SOCKET, SO_SNDTIMEO, &(http->timeout_value),
2279 sizeof(http->timeout_value));
2280 }
2281
ef416fc2 2282 http->hostaddr = &(addr->addr);
2283 http->error = 0;
2284 http->status = HTTP_CONTINUE;
2285
2286#ifdef HAVE_SSL
2287 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
2288 {
2289 /*
2290 * Always do encryption via SSL.
2291 */
2292
2293 if (http_setup_ssl(http) != 0)
2294 {
f7deaa1a 2295# ifdef WIN32
ef416fc2 2296 closesocket(http->fd);
f7deaa1a 2297# else
ef416fc2 2298 close(http->fd);
f7deaa1a 2299# endif /* WIN32 */
ef416fc2 2300
2301 return (-1);
2302 }
2303 }
2304 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
2305 return (http_upgrade(http));
2306#endif /* HAVE_SSL */
2307
e07d4801 2308 DEBUG_printf(("1httpReconnect: Connected to %s:%d...",
1ff0402e
MS
2309 httpAddrString(http->hostaddr, temp, sizeof(temp)),
2310 _httpAddrPort(http->hostaddr)));
2311
ef416fc2 2312 return (0);
2313}
2314
2315
355e94dc
MS
2316/*
2317 * 'httpSetAuthString()' - Set the current authorization string.
2318 *
2319 * This function just stores a copy of the current authorization string in
2320 * the HTTP connection object. You must still call httpSetField() to set
2321 * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
2322 * httpHead(), httpOptions(), httpPost, or httpPut().
2323 *
426c6a59 2324 * @since CUPS 1.3/Mac OS X 10.5@
355e94dc
MS
2325 */
2326
2327void
568fa3fa 2328httpSetAuthString(http_t *http, /* I - Connection to server */
355e94dc
MS
2329 const char *scheme, /* I - Auth scheme (NULL to clear it) */
2330 const char *data) /* I - Auth data (NULL for none) */
2331{
2332 /*
2333 * Range check input...
2334 */
2335
2336 if (!http)
2337 return;
2338
2339 if (http->authstring && http->authstring != http->_authstring)
2340 free(http->authstring);
2341
2342 http->authstring = http->_authstring;
2343
2344 if (scheme)
2345 {
2346 /*
2347 * Set the current authorization string...
2348 */
2349
2350 int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1;
91c84a35 2351 char *temp;
355e94dc
MS
2352
2353 if (len > (int)sizeof(http->_authstring))
91c84a35
MS
2354 {
2355 if ((temp = malloc(len)) == NULL)
2356 len = sizeof(http->_authstring);
2357 else
2358 http->authstring = temp;
2359 }
355e94dc
MS
2360
2361 if (data)
2362 snprintf(http->authstring, len, "%s %s", scheme, data);
2363 else
2364 strlcpy(http->authstring, scheme, len);
2365 }
2366 else
2367 {
2368 /*
2369 * Clear the current authorization string...
2370 */
2371
2372 http->_authstring[0] = '\0';
2373 }
2374}
2375
2376
7cf5915e
MS
2377/*
2378 * 'httpSetCredentials()' - Set the credentials associated with an encrypted
2379 * connection.
2380 *
2381 * @since CUPS 1.5@
2382 */
2383
2384int /* O - Status of call (0 = success) */
2385httpSetCredentials(http_t *http, /* I - Connection to server */
2386 cups_array_t *credentials) /* I - Array of credentials */
2387{
2388 if (!http || cupsArrayCount(credentials) < 1)
2389 return (-1);
2390
2391 _httpFreeCredentials(http->tls_credentials);
2392
2393 http->tls_credentials = _httpConvertCredentials(credentials);
2394
2395 return (http->tls_credentials ? 0 : -1);
2396}
2397
2398
ef416fc2 2399/*
6d2f911b 2400 * 'httpSetCookie()' - Set the cookie value(s).
ef416fc2 2401 *
426c6a59 2402 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 2403 */
2404
2405void
2406httpSetCookie(http_t *http, /* I - Connection */
2407 const char *cookie) /* I - Cookie string */
2408{
2409 if (!http)
2410 return;
2411
2412 if (http->cookie)
2413 free(http->cookie);
2414
2415 if (cookie)
2416 http->cookie = strdup(cookie);
2417 else
2418 http->cookie = NULL;
2419}
2420
2421
b423cd4c 2422/*
2423 * 'httpSetExpect()' - Set the Expect: header in a request.
2424 *
2425 * Currently only HTTP_CONTINUE is supported for the "expect" argument.
2426 *
426c6a59 2427 * @since CUPS 1.2/Mac OS X 10.5@
b423cd4c 2428 */
2429
2430void
568fa3fa 2431httpSetExpect(http_t *http, /* I - Connection to server */
b423cd4c 2432 http_status_t expect) /* I - HTTP status to expect (HTTP_CONTINUE) */
2433{
2434 if (http)
2435 http->expect = expect;
2436}
2437
2438
ef416fc2 2439/*
2440 * 'httpSetField()' - Set the value of an HTTP header.
2441 */
2442
2443void
568fa3fa 2444httpSetField(http_t *http, /* I - Connection to server */
ef416fc2 2445 http_field_t field, /* I - Field index */
2446 const char *value) /* I - Value */
2447{
2448 if (http == NULL ||
2449 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
2450 field > HTTP_FIELD_WWW_AUTHENTICATE ||
2451 value == NULL)
2452 return;
2453
2454 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
f7deaa1a 2455
f7deaa1a 2456 if (field == HTTP_FIELD_AUTHORIZATION)
2457 {
e07d4801
MS
2458 /*
2459 * Special case for Authorization: as its contents can be
2460 * longer than HTTP_MAX_VALUE
2461 */
2462
f7deaa1a 2463 if (http->field_authorization)
2464 free(http->field_authorization);
2465
2466 http->field_authorization = strdup(value);
2467 }
e07d4801
MS
2468 else if (field == HTTP_FIELD_HOST)
2469 {
2470 /*
f11a948a
MS
2471 * Special-case for Host: as we don't want a trailing "." on the hostname and
2472 * need to bracket IPv6 numeric addresses.
e07d4801
MS
2473 */
2474
178cb736
MS
2475 char *ptr = strchr(value, ':');
2476
2477 if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
f11a948a
MS
2478 {
2479 /*
2480 * Bracket IPv6 numeric addresses...
2481 *
2482 * This is slightly inefficient (basically copying twice), but is an edge
2483 * case and not worth optimizing...
2484 */
e07d4801 2485
f11a948a
MS
2486 snprintf(http->fields[HTTP_FIELD_HOST],
2487 sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
2488 }
2489 else
e07d4801 2490 {
f11a948a
MS
2491 /*
2492 * Check for a trailing dot on the hostname...
2493 */
2494
178cb736 2495 ptr = http->fields[HTTP_FIELD_HOST];
f11a948a
MS
2496
2497 if (*ptr)
2498 {
2499 ptr += strlen(ptr) - 1;
e07d4801 2500
f11a948a
MS
2501 if (*ptr == '.')
2502 *ptr = '\0';
2503 }
e07d4801
MS
2504 }
2505 }
ef416fc2 2506}
2507
2508
2509/*
2510 * 'httpSetLength()' - Set the content-length and content-encoding.
2511 *
426c6a59 2512 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 2513 */
2514
2515void
568fa3fa 2516httpSetLength(http_t *http, /* I - Connection to server */
ef416fc2 2517 size_t length) /* I - Length (0 for chunked) */
2518{
2519 if (!http)
2520 return;
2521
2522 if (!length)
2523 {
2524 strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked");
2525 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
2526 }
2527 else
2528 {
2529 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
2530 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
2531 CUPS_LLFMT, CUPS_LLCAST length);
2532 }
2533}
2534
2535
10d09e33
MS
2536/*
2537 * '_httpSetTimeout()' - Set read/write timeouts and an optional callback.
2538 *
2539 * The optional timeout callback receives both the HTTP connection and a user
2540 * data pointer and must return 1 to continue or 0 to error out.
2541 */
2542
2543void
2544_httpSetTimeout(
2545 http_t *http, /* I - Connection to server */
2546 double timeout, /* I - Number of seconds for timeout,
2547 must be greater than 0 */
2548 _http_timeout_cb_t cb, /* I - Callback function or NULL */
2549 void *user_data) /* I - User data pointer */
2550{
2551 if (!http || timeout <= 0.0)
2552 return;
2553
2554 http->timeout_cb = cb;
2555 http->timeout_data = user_data;
2556 http->timeout_value.tv_sec = (int)timeout;
2557 http->timeout_value.tv_usec = (int)(timeout * 1000000) % 1000000;
2558
2559 if (http->fd >= 0)
2560 {
2561 setsockopt(http->fd, SOL_SOCKET, SO_RCVTIMEO, &(http->timeout_value),
2562 sizeof(http->timeout_value));
2563 setsockopt(http->fd, SOL_SOCKET, SO_SNDTIMEO, &(http->timeout_value),
2564 sizeof(http->timeout_value));
2565 }
2566}
2567
2568
ef416fc2 2569/*
2570 * 'httpTrace()' - Send an TRACE request to the server.
2571 */
2572
2573int /* O - Status of call (0 = success) */
568fa3fa 2574httpTrace(http_t *http, /* I - Connection to server */
ef416fc2 2575 const char *uri) /* I - URI for trace */
2576{
2577 return (http_send(http, HTTP_TRACE, uri));
2578}
2579
2580
2581/*
2582 * 'httpUpdate()' - Update the current HTTP state for incoming data.
2583 */
2584
2585http_status_t /* O - HTTP status */
568fa3fa 2586httpUpdate(http_t *http) /* I - Connection to server */
ef416fc2 2587{
2588 char line[32768], /* Line from connection... */
2589 *value; /* Pointer to value on line */
2590 http_field_t field; /* Field index */
2591 int major, minor, /* HTTP version numbers */
2592 status; /* Request status */
2593
2594
f11a948a
MS
2595 DEBUG_printf(("httpUpdate(http=%p), state=%s", http,
2596 http_states[http->state]));
ef416fc2 2597
2598 /*
2599 * Flush pending data, if any...
2600 */
2601
2602 if (http->wused)
2603 {
e07d4801 2604 DEBUG_puts("2httpUpdate: flushing buffer...");
ef416fc2 2605
2606 if (httpFlushWrite(http) < 0)
2607 return (HTTP_ERROR);
2608 }
2609
2610 /*
2611 * If we haven't issued any commands, then there is nothing to "update"...
2612 */
2613
2614 if (http->state == HTTP_WAITING)
2615 return (HTTP_CONTINUE);
2616
2617 /*
2618 * Grab all of the lines we can from the connection...
2619 */
2620
2621 while (httpGets(line, sizeof(line), http) != NULL)
2622 {
e07d4801 2623 DEBUG_printf(("2httpUpdate: Got \"%s\"", line));
ef416fc2 2624
2625 if (line[0] == '\0')
2626 {
2627 /*
2628 * Blank line means the start of the data section (if any). Return
2629 * the result code, too...
2630 *
2631 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
2632 * Instead, we just return HTTP_CONTINUE to the caller and keep on
2633 * tryin'...
2634 */
2635
2636 if (http->status == HTTP_CONTINUE)
2637 return (http->status);
2638
2639 if (http->status < HTTP_BAD_REQUEST)
2640 http->digest_tries = 0;
2641
2642#ifdef HAVE_SSL
2643 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
2644 {
2645 if (http_setup_ssl(http) != 0)
2646 {
2647# ifdef WIN32
2648 closesocket(http->fd);
2649# else
2650 close(http->fd);
2651# endif /* WIN32 */
2652
2653 return (HTTP_ERROR);
2654 }
2655
2656 return (HTTP_CONTINUE);
2657 }
2658#endif /* HAVE_SSL */
2659
2660 httpGetLength2(http);
2661
2662 switch (http->state)
2663 {
2664 case HTTP_GET :
2665 case HTTP_POST :
2666 case HTTP_POST_RECV :
2667 case HTTP_PUT :
2668 http->state ++;
2669 case HTTP_POST_SEND :
e1d6a774 2670 case HTTP_HEAD :
ef416fc2 2671 break;
2672
2673 default :
2674 http->state = HTTP_WAITING;
2675 break;
2676 }
2677
2678 return (http->status);
2679 }
e07d4801 2680 else if (!strncmp(line, "HTTP/", 5))
ef416fc2 2681 {
2682 /*
2683 * Got the beginning of a response...
2684 */
2685
2686 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
2687 return (HTTP_ERROR);
2688
2689 http->version = (http_version_t)(major * 100 + minor);
2690 http->status = (http_status_t)status;
2691 }
2692 else if ((value = strchr(line, ':')) != NULL)
2693 {
2694 /*
2695 * Got a value...
2696 */
2697
2698 *value++ = '\0';
7cf5915e 2699 while (_cups_isspace(*value))
ef416fc2 2700 value ++;
2701
2702 /*
2703 * Be tolerants of servers that send unknown attribute fields...
2704 */
2705
2706 if (!strcasecmp(line, "expect"))
2707 {
2708 /*
2709 * "Expect: 100-continue" or similar...
2710 */
2711
2712 http->expect = (http_status_t)atoi(value);
2713 }
2714 else if (!strcasecmp(line, "cookie"))
2715 {
2716 /*
2717 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
2718 */
2719
2720 httpSetCookie(http, value);
2721 }
2722 else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
2723 {
e07d4801 2724 DEBUG_printf(("1httpUpdate: unknown field %s seen!", line));
ef416fc2 2725 continue;
2726 }
2727 else
2728 httpSetField(http, field, value);
2729 }
2730 else
2731 {
e07d4801 2732 DEBUG_printf(("1httpUpdate: Bad response line \"%s\"!", line));
ef416fc2 2733 http->status = HTTP_ERROR;
2734 return (HTTP_ERROR);
2735 }
2736 }
2737
2738 /*
2739 * See if there was an error...
2740 */
2741
2742 if (http->error == EPIPE && http->status > HTTP_CONTINUE)
e07d4801
MS
2743 {
2744 DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
ef416fc2 2745 return (http->status);
e07d4801 2746 }
ef416fc2 2747
2748 if (http->error)
2749 {
e07d4801 2750 DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
ef416fc2 2751 strerror(http->error)));
2752 http->status = HTTP_ERROR;
2753 return (HTTP_ERROR);
2754 }
2755
2756 /*
2757 * If we haven't already returned, then there is nothing new...
2758 */
2759
2760 return (HTTP_CONTINUE);
2761}
2762
2763
38e73f87
MS
2764/*
2765 * '_httpWait()' - Wait for data available on a connection (no flush).
2766 */
2767
2768int /* O - 1 if data is available, 0 otherwise */
2769_httpWait(http_t *http, /* I - Connection to server */
2770 int msec, /* I - Milliseconds to wait */
2771 int usessl) /* I - Use SSL context? */
2772{
2773#ifdef HAVE_POLL
2774 struct pollfd pfd; /* Polled file descriptor */
2775#else
2776 fd_set input_set; /* select() input set */
2777 struct timeval timeout; /* Timeout */
2778#endif /* HAVE_POLL */
2779 int nfds; /* Result from select()/poll() */
2780
2781
e07d4801 2782 DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
38e73f87
MS
2783
2784 if (http->fd < 0)
f8b3a85b
MS
2785 {
2786 DEBUG_printf(("5_httpWait: Returning 0 since fd=%d", http->fd));
38e73f87 2787 return (0);
f8b3a85b 2788 }
38e73f87
MS
2789
2790 /*
2791 * Check the SSL/TLS buffers for data first...
2792 */
2793
2794#ifdef HAVE_SSL
2795 if (http->tls && usessl)
2796 {
2797# ifdef HAVE_LIBSSL
7cf5915e 2798 if (SSL_pending(http->tls))
f8b3a85b
MS
2799 {
2800 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 2801 return (1);
f8b3a85b
MS
2802 }
2803
38e73f87 2804# elif defined(HAVE_GNUTLS)
7cf5915e 2805 if (gnutls_record_check_pending(http->tls))
f8b3a85b
MS
2806 {
2807 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 2808 return (1);
f8b3a85b
MS
2809 }
2810
38e73f87
MS
2811# elif defined(HAVE_CDSASSL)
2812 size_t bytes; /* Bytes that are available */
2813
7cf5915e 2814 if (!SSLGetBufferedReadSize(http->tls, &bytes) &&
38e73f87 2815 bytes > 0)
f8b3a85b
MS
2816 {
2817 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 2818 return (1);
f8b3a85b 2819 }
38e73f87
MS
2820# endif /* HAVE_LIBSSL */
2821 }
2822#endif /* HAVE_SSL */
2823
2824 /*
2825 * Then try doing a select() or poll() to poll the socket...
2826 */
2827
2828#ifdef HAVE_POLL
2829 pfd.fd = http->fd;
2830 pfd.events = POLLIN;
2831
e07d4801
MS
2832 while ((nfds = poll(&pfd, 1, msec)) < 0 &&
2833 (errno == EINTR || errno == EAGAIN));
38e73f87
MS
2834
2835#else
2836 do
2837 {
2838 FD_ZERO(&input_set);
2839 FD_SET(http->fd, &input_set);
2840
e07d4801 2841 DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
38e73f87
MS
2842
2843 if (msec >= 0)
2844 {
2845 timeout.tv_sec = msec / 1000;
2846 timeout.tv_usec = (msec % 1000) * 1000;
2847
2848 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
2849 }
2850 else
2851 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
2852
e07d4801 2853 DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
38e73f87
MS
2854 }
2855# ifdef WIN32
cc754834
MS
2856 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
2857 WSAGetLastError() == WSAEWOULDBLOCK));
38e73f87 2858# else
e07d4801 2859 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
38e73f87
MS
2860# endif /* WIN32 */
2861#endif /* HAVE_POLL */
2862
f8b3a85b
MS
2863 DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds,
2864 errno));
38e73f87
MS
2865
2866 return (nfds > 0);
2867}
2868
2869
ef416fc2 2870/*
2871 * 'httpWait()' - Wait for data available on a connection.
2872 *
426c6a59 2873 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 2874 */
2875
2876int /* O - 1 if data is available, 0 otherwise */
568fa3fa 2877httpWait(http_t *http, /* I - Connection to server */
ef416fc2 2878 int msec) /* I - Milliseconds to wait */
2879{
2880 /*
2881 * First see if there is data in the buffer...
2882 */
2883
2884 if (http == NULL)
2885 return (0);
2886
2887 if (http->used)
2888 return (1);
2889
8ca02f3c 2890 /*
2891 * Flush pending data, if any...
2892 */
2893
2894 if (http->wused)
2895 {
2896 if (httpFlushWrite(http) < 0)
2897 return (0);
2898 }
2899
ef416fc2 2900 /*
2901 * If not, check the SSL/TLS buffers and do a select() on the connection...
2902 */
2903
38e73f87 2904 return (_httpWait(http, msec, 1));
ef416fc2 2905}
2906
2907
2908/*
2909 * 'httpWrite()' - Write data to a HTTP connection.
a4d04587 2910 *
2911 * This function is deprecated. Use the httpWrite2() function which can
2912 * write more than 2GB of data.
2913 *
2914 * @deprecated@
ef416fc2 2915 */
ef55b745 2916
ef416fc2 2917int /* O - Number of bytes written */
568fa3fa 2918httpWrite(http_t *http, /* I - Connection to server */
ef416fc2 2919 const char *buffer, /* I - Buffer for data */
2920 int length) /* I - Number of bytes to write */
2921{
a4d04587 2922 return ((int)httpWrite2(http, buffer, length));
2923}
2924
2925
2926/*
2927 * 'httpWrite2()' - Write data to a HTTP connection.
ecdc0628 2928 *
426c6a59 2929 * @since CUPS 1.2/Mac OS X 10.5@
a4d04587 2930 */
ef55b745 2931
a4d04587 2932ssize_t /* O - Number of bytes written */
568fa3fa 2933httpWrite2(http_t *http, /* I - Connection to server */
a4d04587 2934 const char *buffer, /* I - Buffer for data */
2935 size_t length) /* I - Number of bytes to write */
2936{
2937 ssize_t bytes; /* Bytes written */
ef416fc2 2938
2939
e07d4801 2940 DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
a603edef 2941 buffer, CUPS_LLCAST length));
ef416fc2 2942
2943 /*
2944 * Range check input...
2945 */
2946
2947 if (http == NULL || buffer == NULL)
2948 return (-1);
2949
2950 /*
2951 * Mark activity on the connection...
2952 */
2953
2954 http->activity = time(NULL);
2955
2956 /*
2957 * Buffer small writes for better performance...
2958 */
2959
2960 if (length > 0)
2961 {
2962 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
2963 {
e07d4801
MS
2964 DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
2965 CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
ef416fc2 2966
2967 httpFlushWrite(http);
2968 }
2969
38e73f87
MS
2970 if ((length + http->wused) <= sizeof(http->wbuffer) &&
2971 length < sizeof(http->wbuffer))
ef416fc2 2972 {
2973 /*
2974 * Write to buffer...
2975 */
2976
e07d4801 2977 DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
a603edef 2978 CUPS_LLCAST length));
ef416fc2 2979
2980 memcpy(http->wbuffer + http->wused, buffer, length);
b86bc4cf 2981 http->wused += (int)length;
2982 bytes = (ssize_t)length;
ef416fc2 2983 }
2984 else
2985 {
2986 /*
2987 * Otherwise write the data directly...
2988 */
2989
e07d4801 2990 DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
a603edef 2991 CUPS_LLCAST length));
ef416fc2 2992
2993 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
b86bc4cf 2994 bytes = (ssize_t)http_write_chunk(http, buffer, (int)length);
ef416fc2 2995 else
b86bc4cf 2996 bytes = (ssize_t)http_write(http, buffer, (int)length);
ef416fc2 2997
e07d4801 2998 DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
ae71f5de 2999 CUPS_LLCAST bytes));
ef416fc2 3000 }
3001
3002 if (http->data_encoding == HTTP_ENCODE_LENGTH)
3003 http->data_remaining -= bytes;
3004 }
3005 else
3006 bytes = 0;
3007
3008 /*
3009 * Handle end-of-request processing...
3010 */
3011
3012 if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
3013 (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
3014 {
3015 /*
3016 * Finished with the transfer; unless we are sending POST or PUT
3017 * data, go idle...
3018 */
3019
e07d4801 3020 DEBUG_puts("2httpWrite: changing states...");
ef416fc2 3021
3022 if (http->wused)
3023 httpFlushWrite(http);
3024
3025 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
3026 {
3027 /*
3028 * Send a 0-length chunk at the end of the request...
3029 */
3030
3031 http_write(http, "0\r\n\r\n", 5);
3032
3033 /*
3034 * Reset the data state...
3035 */
3036
3037 http->data_encoding = HTTP_ENCODE_LENGTH;
3038 http->data_remaining = 0;
3039 }
3040
3041 if (http->state == HTTP_POST_RECV)
3042 http->state ++;
3043 else if (http->state == HTTP_PUT_RECV)
3044 http->state = HTTP_STATUS;
3045 else
3046 http->state = HTTP_WAITING;
3047 }
3048
3049 return (bytes);
3050}
3051
3052
3053#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
3054/*
411affcf 3055 * '_httpWriteCDSA()' - Write function for the CDSA library.
ef416fc2 3056 */
3057
3058OSStatus /* O - -1 on error, 0 on success */
3059_httpWriteCDSA(
3060 SSLConnectionRef connection, /* I - SSL/TLS connection */
3061 const void *data, /* I - Data buffer */
3062 size_t *dataLength) /* IO - Number of bytes */
3063{
411affcf 3064 OSStatus result; /* Return value */
3065 ssize_t bytes; /* Number of bytes read */
3066 http_t *http; /* HTTP connection */
e53920b9 3067
3068
411affcf 3069 http = (http_t *)connection;
ef416fc2 3070
b423cd4c 3071 do
411affcf 3072 {
3073 bytes = write(http->fd, data, *dataLength);
3074 }
e07d4801 3075 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 3076
b423cd4c 3077 if (bytes == *dataLength)
411affcf 3078 {
b423cd4c 3079 result = 0;
411affcf 3080 }
b423cd4c 3081 else if (bytes >= 0)
3082 {
3083 *dataLength = bytes;
3084 result = errSSLWouldBlock;
3085 }
3086 else
3087 {
3088 *dataLength = 0;
ef55b745 3089
fa73b229 3090 if (errno == EAGAIN)
b423cd4c 3091 result = errSSLWouldBlock;
b423cd4c 3092 else
ed486911 3093 result = errSSLClosedAbort;
ef416fc2 3094 }
b423cd4c 3095
411affcf 3096 return (result);
ef416fc2 3097}
3098#endif /* HAVE_SSL && HAVE_CDSASSL */
3099
3100
411affcf 3101#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
3102/*
3103 * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
3104 */
3105
3106ssize_t /* O - Number of bytes written or -1 on error */
3107_httpWriteGNUTLS(
568fa3fa 3108 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 3109 const void *data, /* I - Data buffer */
3110 size_t length) /* I - Number of bytes to write */
3111{
3112 return (send(((http_t *)ptr)->fd, data, length, 0));
3113}
3114#endif /* HAVE_SSL && HAVE_GNUTLS */
3115
3116
3117#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
3118/*
3119 * 'http_bio_ctrl()' - Control the HTTP connection.
3120 */
3121
3122static long /* O - Result/data */
3123http_bio_ctrl(BIO *h, /* I - BIO data */
3124 int cmd, /* I - Control command */
3125 long arg1, /* I - First argument */
3126 void *arg2) /* I - Second argument */
3127{
3128 switch (cmd)
3129 {
3130 default :
3131 return (0);
3132
3133 case BIO_CTRL_RESET :
3134 h->ptr = NULL;
3135 return (0);
3136
3137 case BIO_C_SET_FILE_PTR :
3138 h->ptr = arg2;
3139 h->init = 1;
3140 return (1);
3141
3142 case BIO_C_GET_FILE_PTR :
3143 if (arg2)
3144 {
3145 *((void **)arg2) = h->ptr;
3146 return (1);
3147 }
3148 else
3149 return (0);
ef55b745 3150
411affcf 3151 case BIO_CTRL_DUP :
3152 case BIO_CTRL_FLUSH :
3153 return (1);
3154 }
3155}
3156
3157
3158/*
3159 * 'http_bio_free()' - Free OpenSSL data.
3160 */
3161
3162static int /* O - 1 on success, 0 on failure */
3163http_bio_free(BIO *h) /* I - BIO data */
3164{
3165 if (!h)
3166 return (0);
3167
3168 if (h->shutdown)
3169 {
3170 h->init = 0;
3171 h->flags = 0;
3172 }
3173
3174 return (1);
3175}
3176
3177
3178/*
3179 * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
3180 */
3181
3182static int /* O - 1 on success, 0 on failure */
3183http_bio_new(BIO *h) /* I - BIO data */
3184{
3185 if (!h)
3186 return (0);
3187
3188 h->init = 0;
3189 h->num = 0;
3190 h->ptr = NULL;
3191 h->flags = 0;
3192
3193 return (1);
3194}
3195
3196
3197/*
3198 * 'http_bio_puts()' - Send a string for OpenSSL.
3199 */
3200
3201static int /* O - Bytes written */
3202http_bio_puts(BIO *h, /* I - BIO data */
3203 const char *str) /* I - String to write */
3204{
b86bc4cf 3205#ifdef WIN32
3206 return (send(((http_t *)h->ptr)->fd, str, (int)strlen(str), 0));
3207#else
411affcf 3208 return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
b86bc4cf 3209#endif /* WIN32 */
411affcf 3210}
3211
3212
3213/*
3214 * 'http_bio_read()' - Read data for OpenSSL.
3215 */
3216
3217static int /* O - Bytes read */
3218http_bio_read(BIO *h, /* I - BIO data */
3219 char *buf, /* I - Buffer */
3220 int size) /* I - Number of bytes to read */
3221{
3222 http_t *http; /* HTTP connection */
3223
3224
3225 http = (http_t *)h->ptr;
3226
3227 if (!http->blocking)
3228 {
3229 /*
3230 * Make sure we have data before we read...
3231 */
3232
38e73f87 3233 if (!_httpWait(http, 10000, 0))
411affcf 3234 {
b86bc4cf 3235#ifdef WIN32
3236 http->error = WSAETIMEDOUT;
3237#else
411affcf 3238 http->error = ETIMEDOUT;
b86bc4cf 3239#endif /* WIN32 */
3240
411affcf 3241 return (-1);
3242 }
3243 }
3244
3245 return (recv(http->fd, buf, size, 0));
3246}
3247
3248
3249/*
3250 * 'http_bio_write()' - Write data for OpenSSL.
3251 */
3252
3253static int /* O - Bytes written */
3254http_bio_write(BIO *h, /* I - BIO data */
3255 const char *buf, /* I - Buffer to write */
3256 int num) /* I - Number of bytes to write */
3257{
3258 return (send(((http_t *)h->ptr)->fd, buf, num, 0));
3259}
3260#endif /* HAVE_SSL && HAVE_LIBSSL */
3261
3262
ae71f5de
MS
3263#ifdef DEBUG
3264/*
3265 * 'http_debug_hex()' - Do a hex dump of a buffer.
3266 */
3267
3268static void
3269http_debug_hex(const char *prefix, /* I - Prefix for line */
3270 const char *buffer, /* I - Buffer to dump */
3271 int bytes) /* I - Bytes to dump */
3272{
3273 int i, j, /* Looping vars */
3274 ch; /* Current character */
3275 char line[255], /* Line buffer */
3276 *start, /* Start of line after prefix */
3277 *ptr; /* Pointer into line */
3278
3279
f11a948a 3280 if (_cups_debug_fd < 0 || _cups_debug_level < 6)
dd1abb6b
MS
3281 return;
3282
e07d4801 3283 DEBUG_printf(("6%s: %d bytes:\n", prefix, bytes));
ae71f5de 3284
f11a948a 3285 snprintf(line, sizeof(line), "6%s: ", prefix);
ae71f5de
MS
3286 start = line + strlen(line);
3287
3288 for (i = 0; i < bytes; i += 16)
3289 {
3290 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
3291 sprintf(ptr, "%02X", buffer[i + j] & 255);
3292
3293 while (j < 16)
3294 {
3295 strcpy(ptr, " ");
3296 ptr += 2;
3297 j ++;
3298 }
3299
3300 strcpy(ptr, " ");
3301 ptr += 2;
3302
3303 for (j = 0; j < 16 && (i + j) < bytes; j ++)
3304 {
3305 ch = buffer[i + j] & 255;
3306
3307 if (ch < ' ' || ch >= 127)
3308 ch = '.';
3309
3310 *ptr++ = ch;
3311 }
3312
3313 *ptr = '\0';
3314 DEBUG_puts(line);
3315 }
3316}
3317#endif /* DEBUG */
3318
3319
ef416fc2 3320/*
3321 * 'http_field()' - Return the field index for a field name.
3322 */
3323
ae71f5de
MS
3324static http_field_t /* O - Field index */
3325http_field(const char *name) /* I - String name */
ef416fc2 3326{
ae71f5de 3327 int i; /* Looping var */
ef416fc2 3328
3329
3330 for (i = 0; i < HTTP_FIELD_MAX; i ++)
3331 if (strcasecmp(name, http_fields[i]) == 0)
3332 return ((http_field_t)i);
3333
3334 return (HTTP_FIELD_UNKNOWN);
3335}
3336
3337
3338#ifdef HAVE_SSL
3339/*
3340 * 'http_read_ssl()' - Read from a SSL/TLS connection.
3341 */
3342
3343static int /* O - Bytes read */
568fa3fa 3344http_read_ssl(http_t *http, /* I - Connection to server */
ef416fc2 3345 char *buf, /* I - Buffer to store data */
3346 int len) /* I - Length of buffer */
3347{
3348# if defined(HAVE_LIBSSL)
3349 return (SSL_read((SSL *)(http->tls), buf, len));
3350
3351# elif defined(HAVE_GNUTLS)
ef55b745
MS
3352 ssize_t result; /* Return value */
3353
3354
7cf5915e 3355 result = gnutls_record_recv(http->tls, buf, len);
ef55b745
MS
3356
3357 if (result < 0 && !errno)
3358 {
3359 /*
3360 * Convert GNU TLS error to errno value...
3361 */
3362
3363 switch (result)
3364 {
3365 case GNUTLS_E_INTERRUPTED :
3366 errno = EINTR;
3367 break;
3368
3369 case GNUTLS_E_AGAIN :
3370 errno = EAGAIN;
3371 break;
3372
3373 default :
3374 errno = EPIPE;
3375 break;
3376 }
3377
3378 result = -1;
3379 }
3380
3381 return ((int)result);
ef416fc2 3382
3383# elif defined(HAVE_CDSASSL)
fa73b229 3384 int result; /* Return value */
ef416fc2 3385 OSStatus error; /* Error info */
3386 size_t processed; /* Number of bytes processed */
3387
3388
7cf5915e 3389 error = SSLRead(http->tls, buf, len, &processed);
ef416fc2 3390
fa73b229 3391 switch (error)
ef416fc2 3392 {
fa73b229 3393 case 0 :
3394 result = (int)processed;
3395 break;
3396 case errSSLClosedGraceful :
3397 result = 0;
3398 break;
3399 case errSSLWouldBlock :
b423cd4c 3400 if (processed)
3401 result = (int)processed;
3402 else
3403 {
3404 result = -1;
3405 errno = EINTR;
3406 }
fa73b229 3407 break;
3408 default :
3409 errno = EPIPE;
3410 result = -1;
3411 break;
ef416fc2 3412 }
fa73b229 3413
3414 return (result);
cc754834
MS
3415# elif defined(HAVE_SSPISSL)
3416 return _sspiRead((_sspi_struct_t*) http->tls, buf, len);
ef416fc2 3417# endif /* HAVE_LIBSSL */
3418}
3419#endif /* HAVE_SSL */
3420
3421
6d2f911b
MS
3422#ifdef HAVE_LIBSSL
3423/*
3424 * 'http_locking_cb()' - Lock/unlock a thread's mutex.
3425 */
3426
3427static void
3428http_locking_cb(int mode, /* I - Lock mode */
3429 int type, /* I - Lock type */
3430 const char *file, /* I - Source file */
3431 int line) /* I - Line number */
3432{
3433 if (mode & CRYPTO_LOCK)
3434 _cupsMutexLock(http_locks + type);
3435 else
3436 _cupsMutexUnlock(http_locks + type);
3437}
3438#endif /* HAVE_LIBSSL */
3439
3440
ef416fc2 3441/*
3442 * 'http_send()' - Send a request with all fields and the trailing blank line.
3443 */
3444
3445static int /* O - 0 on success, non-zero on error */
568fa3fa 3446http_send(http_t *http, /* I - Connection to server */
ef416fc2 3447 http_state_t request, /* I - Request code */
3448 const char *uri) /* I - URI */
3449{
3450 int i; /* Looping var */
839a51c8 3451 char buf[1024]; /* Encoded URI buffer */
ef416fc2 3452 static const char * const codes[] =
3453 { /* Request code strings */
3454 NULL,
3455 "OPTIONS",
3456 "GET",
3457 NULL,
3458 "HEAD",
3459 "POST",
3460 NULL,
3461 NULL,
3462 "PUT",
3463 NULL,
3464 "DELETE",
3465 "TRACE",
3466 "CLOSE"
3467 };
ef416fc2 3468
3469
e07d4801 3470 DEBUG_printf(("7http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
ef416fc2 3471 http, codes[request], uri));
3472
3473 if (http == NULL || uri == NULL)
3474 return (-1);
3475
3476 /*
3477 * Set the User-Agent field if it isn't already...
3478 */
3479
3480 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
3481 httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
3482
3483 /*
3484 * Encode the URI as needed...
3485 */
3486
839a51c8 3487 _httpEncodeURI(buf, uri, sizeof(buf));
ef416fc2 3488
3489 /*
3490 * See if we had an error the last time around; if so, reconnect...
3491 */
3492
3493 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
fa73b229 3494 if (httpReconnect(http))
3495 return (-1);
ef416fc2 3496
d09495fa 3497 /*
3498 * Flush any written data that is pending...
3499 */
3500
3501 if (http->wused)
536bc2c6
MS
3502 {
3503 if (httpFlushWrite(http) < 0)
3504 if (httpReconnect(http))
3505 return (-1);
3506 }
d09495fa 3507
ef416fc2 3508 /*
3509 * Send the request header...
3510 */
3511
d09495fa 3512 http->state = request;
3513 http->data_encoding = HTTP_ENCODE_FIELDS;
3514
ef416fc2 3515 if (request == HTTP_POST || request == HTTP_PUT)
3516 http->state ++;
3517
3518 http->status = HTTP_CONTINUE;
3519
3520#ifdef HAVE_SSL
3521 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
3522 {
3523 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
3524 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
3525 }
3526#endif /* HAVE_SSL */
3527
3528 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
3529 {
3530 http->status = HTTP_ERROR;
3531 return (-1);
3532 }
3533
3534 for (i = 0; i < HTTP_FIELD_MAX; i ++)
3535 if (http->fields[i][0] != '\0')
3536 {
e07d4801 3537 DEBUG_printf(("9http_send: %s: %s", http_fields[i],
ae71f5de 3538 httpGetField(http, i)));
ef416fc2 3539
ef55b745 3540 if (httpPrintf(http, "%s: %s\r\n", http_fields[i],
f7deaa1a 3541 httpGetField(http, i)) < 1)
ef416fc2 3542 {
3543 http->status = HTTP_ERROR;
3544 return (-1);
3545 }
3546 }
3547
3548 if (http->cookie)
3549 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
3550 {
3551 http->status = HTTP_ERROR;
3552 return (-1);
3553 }
3554
b423cd4c 3555 if (http->expect == HTTP_CONTINUE &&
3556 (http->state == HTTP_POST_RECV || http->state == HTTP_PUT_RECV))
3557 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
3558 {
3559 http->status = HTTP_ERROR;
3560 return (-1);
3561 }
3562
ef416fc2 3563 if (httpPrintf(http, "\r\n") < 1)
3564 {
3565 http->status = HTTP_ERROR;
3566 return (-1);
3567 }
3568
536bc2c6
MS
3569 if (httpFlushWrite(http) < 0)
3570 return (-1);
3571
ef416fc2 3572 httpGetLength2(http);
3573 httpClearFields(http);
3574
f7deaa1a 3575 /*
b94498cf 3576 * The Kerberos and AuthRef authentication strings can only be used once...
f7deaa1a 3577 */
3578
ef55b745
MS
3579 if (http->field_authorization && http->authstring &&
3580 (!strncmp(http->authstring, "Negotiate", 9) ||
b94498cf 3581 !strncmp(http->authstring, "AuthRef", 7)))
f7deaa1a 3582 {
3583 http->_authstring[0] = '\0';
3584
3585 if (http->authstring != http->_authstring)
3586 free(http->authstring);
ef55b745 3587
f7deaa1a 3588 http->authstring = http->_authstring;
3589 }
3590
ef416fc2 3591 return (0);
3592}
3593
3594
3595#ifdef HAVE_SSL
7cf5915e
MS
3596/*
3597 * 'http_set_credentials()' - Set the SSL/TLS credentials.
3598 */
3599
3600static int /* O - Status of connection */
3601http_set_credentials(http_t *http) /* I - Connection to server */
3602{
3603 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
3604# ifdef HAVE_CDSASSL
3605 OSStatus error = 0; /* Error code */
3606 http_tls_credentials_t credentials = NULL;
3607 /* TLS credentials */
3608# endif /* HAVE_CDSASSL */
3609
3610
3611 DEBUG_printf(("7http_set_credentials(%p)", http));
3612
3613# ifdef HAVE_LIBSSL
3614 return (-1);
3615
3616# elif defined(HAVE_GNUTLS)
3617 return (-1);
3618
3619# elif defined(HAVE_CDSASSL)
3620 /*
3621 * Prefer connection specific credentials...
3622 */
3623
3624 if ((credentials = http->tls_credentials) == NULL)
3625 credentials = cg->tls_credentials;
3626
3627# if HAVE_SECPOLICYCREATESSL
3628 /*
3629 * Otherwise root around in the user's keychain to see if one can be found...
3630 */
3631
3632 if (!credentials)
3633 {
3634 CFDictionaryRef query; /* Query dictionary */
3635 CFTypeRef matches = NULL; /* Matching credentials */
3636 CFArrayRef dn_array = NULL;/* Distinguished names array */
3637 CFTypeRef keys[] = { kSecClass,
3638 kSecMatchLimit,
3639 kSecReturnRef };
3640 /* Keys for dictionary */
3641 CFTypeRef values[] = { kSecClassCertificate,
3642 kSecMatchLimitOne,
3643 kCFBooleanTrue };
3644 /* Values for dictionary */
3645
3646 /*
3647 * Get the names associated with the server.
3648 */
3649
3650 if ((error = SSLCopyDistinguishedNames(http->tls, &dn_array)) != noErr)
3651 {
3652 DEBUG_printf(("4http_set_credentials: SSLCopyDistinguishedNames, error=%d",
3653 (int)error));
3654 return (error);
3655 }
3656
3657 /*
3658 * Create a query which will return all identities that can sign and match
3659 * the passed in policy.
3660 */
3661
3662 query = CFDictionaryCreate(NULL,
3663 (const void**)(&keys[0]),
3664 (const void**)(&values[0]),
3665 sizeof(keys) / sizeof(keys[0]),
3666 &kCFTypeDictionaryKeyCallBacks,
3667 &kCFTypeDictionaryValueCallBacks);
3668 if (query)
3669 {
3670 error = SecItemCopyMatching(query, &matches);
3671 DEBUG_printf(("4http_set_credentials: SecItemCopyMatching, error=%d",
3672 (int)error));
3673 CFRelease(query);
3674 }
3675
3676 if (matches)
3677 CFRelease(matches);
3678
3679 if (dn_array)
3680 CFRelease(dn_array);
3681 }
3682# endif /* HAVE_SECPOLICYCREATESSL */
3683
3684 if (credentials)
3685 {
3686 error = SSLSetCertificate(http->tls, credentials);
3687 DEBUG_printf(("4http_set_credentials: SSLSetCertificate, error=%d",
3688 (int)error));
3689 }
3690 else
3691 DEBUG_puts("4http_set_credentials: No credentials to set.");
3692
3693 return (error);
3694
3695# elif defined(HAVE_SSPISSL)
3696 return (-1);
3697# endif /* HAVE_LIBSSL */
3698}
3699
3700
ef416fc2 3701/*
3702 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
3703 */
3704
3705static int /* O - Status of connection */
568fa3fa 3706http_setup_ssl(http_t *http) /* I - Connection to server */
ef416fc2 3707{
7cf5915e
MS
3708 _cups_globals_t *cg = _cupsGlobals();
3709 /* Pointer to library globals */
3710 int any_root; /* Allow any root */
3711
ef416fc2 3712# ifdef HAVE_LIBSSL
89d46774 3713 SSL_CTX *context; /* Context for encryption */
411affcf 3714 BIO *bio; /* BIO data */
ef416fc2 3715# elif defined(HAVE_GNUTLS)
ef416fc2 3716 gnutls_certificate_client_credentials *credentials;
89d46774 3717 /* TLS credentials */
ef416fc2 3718# elif defined(HAVE_CDSASSL)
89d46774 3719 OSStatus error; /* Error code */
7cf5915e
MS
3720 const char *message = NULL; /* Error message */
3721 cups_array_t *credentials; /* Credentials array */
3722 char *hostname; /* Hostname */
3723 cups_array_t *names; /* CUPS distinguished names */
3724 CFArrayRef dn_array; /* CF distinguished names array */
3725 CFIndex count; /* Number of credentials */
3726 CFDataRef data; /* Certificate data */
3727 int i; /* Looping var */
3728 http_credential_t
3729 *credential; /* Credential data */
cc754834
MS
3730# elif defined(HAVE_SSPISSL)
3731 TCHAR username[256]; /* Username returned from GetUserName() */
3732 TCHAR commonName[256]; /* Common name for certificate */
3733 DWORD dwSize; /* 32 bit size */
ef416fc2 3734# endif /* HAVE_LIBSSL */
3735
3736
e07d4801 3737 DEBUG_printf(("7http_setup_ssl(http=%p)", http));
ef416fc2 3738
7cf5915e
MS
3739 /*
3740 * Always allow self-signed certificates for the local loopback address...
3741 */
3742
3743 if (httpAddrLocalhost(http->hostaddr))
3744 any_root = 1;
3745 else
3746 any_root = cg->any_root;
3747
ef416fc2 3748# ifdef HAVE_LIBSSL
3749 context = SSL_CTX_new(SSLv23_client_method());
3750
3751 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
3752
411affcf 3753 bio = BIO_new(_httpBIOMethods());
3754 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
3755
7cf5915e
MS
3756 http->tls = SSL_new(context);
3757 SSL_set_bio(http->tls_credentials, bio, bio);
ef416fc2 3758
7cf5915e 3759 if (SSL_connect(http->tls) != 1)
ef416fc2 3760 {
3761# ifdef DEBUG
3762 unsigned long error; /* Error code */
3763
3764 while ((error = ERR_get_error()) != 0)
e07d4801 3765 DEBUG_printf(("8http_setup_ssl: %s", ERR_error_string(error, NULL)));
ef416fc2 3766# endif /* DEBUG */
3767
3768 SSL_CTX_free(context);
7cf5915e
MS
3769 SSL_free(http->tls);
3770 http->tls = NULL;
ef416fc2 3771
3772# ifdef WIN32
3773 http->error = WSAGetLastError();
3774# else
3775 http->error = errno;
3776# endif /* WIN32 */
3777 http->status = HTTP_ERROR;
3778
3779 return (HTTP_ERROR);
3780 }
3781
3782# elif defined(HAVE_GNUTLS)
ef416fc2 3783 credentials = (gnutls_certificate_client_credentials *)
3784 malloc(sizeof(gnutls_certificate_client_credentials));
3785 if (credentials == NULL)
3786 {
ef416fc2 3787 http->error = errno;
3788 http->status = HTTP_ERROR;
3789
3790 return (-1);
3791 }
3792
3793 gnutls_certificate_allocate_credentials(credentials);
3794
7cf5915e
MS
3795 gnutls_init(&http->tls, GNUTLS_CLIENT);
3796 gnutls_set_default_priority(http->tls);
3797 gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials);
3798 gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr)http);
3799 gnutls_transport_set_pull_function(http->tls, _httpReadGNUTLS);
3800 gnutls_transport_set_push_function(http->tls, _httpWriteGNUTLS);
ef416fc2 3801
7cf5915e 3802 if ((gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS)
ef416fc2 3803 {
3804 http->error = errno;
3805 http->status = HTTP_ERROR;
3806
7cf5915e 3807 gnutls_deinit(http->tls);
85b5d1df
MS
3808 gnutls_certificate_free_credentials(*credentials);
3809 free(credentials);
7cf5915e 3810 http->tls = NULL;
85b5d1df 3811
ef416fc2 3812 return (-1);
3813 }
3814
7cf5915e 3815 http->tls_credentials = credentials;
ef416fc2 3816
3817# elif defined(HAVE_CDSASSL)
7cf5915e 3818 if ((error = SSLNewContext(false, &http->tls)))
e53920b9 3819 {
89d46774 3820 http->error = error;
3821 http->status = HTTP_ERROR;
e53920b9 3822
89d46774 3823 return (-1);
e53920b9 3824 }
ef416fc2 3825
7cf5915e
MS
3826 error = SSLSetConnection(http->tls, http);
3827 DEBUG_printf(("4http_setup_ssl: SSLSetConnection, error=%d", (int)error));
3828
3829 if (!error)
3830 {
3831 error = SSLSetIOFuncs(http->tls, _httpReadCDSA, _httpWriteCDSA);
3832 DEBUG_printf(("4http_setup_ssl: SSLSetIOFuncs, error=%d", (int)error));
3833 }
3834
3835 if (!error)
3836 {
3837 error = SSLSetProtocolVersionEnabled(http->tls, kSSLProtocol2, false);
3838 DEBUG_printf(("4http_setup_ssl: SSLSetProtocolVersionEnabled, error=%d",
3839 (int)error));
3840 }
89d46774 3841
7cf5915e
MS
3842 if (!error)
3843 {
3844 error = SSLSetAllowsAnyRoot(http->tls, any_root);
3845 DEBUG_printf(("4http_setup_ssl: SSLSetAllowsAnyRoot(%d), error=%d",
3846 any_root, (int)error));
3847 }
89d46774 3848
3849 if (!error)
7cf5915e
MS
3850 {
3851 error = SSLSetAllowsExpiredCerts(http->tls, cg->expired_certs);
3852 DEBUG_printf(("4http_setup_ssl: SSLSetAllowsExpiredCerts(%d), error=%d",
3853 cg->expired_certs, (int)error));
3854 }
89d46774 3855
ef416fc2 3856 if (!error)
7cf5915e
MS
3857 {
3858 error = SSLSetAllowsExpiredRoots(http->tls, cg->expired_root);
3859 DEBUG_printf(("4http_setup_ssl: SSLSetAllowsExpiredRoots(%d), error=%d",
3860 cg->expired_root, (int)error));
3861 }
ef416fc2 3862
3863 if (!error)
7cf5915e
MS
3864 {
3865 if (cg->client_cert_cb)
3866 {
3867 error = SSLSetSessionOption(http->tls,
3868 kSSLSessionOptionBreakOnCertRequested, true);
3869 DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnCertRequested, "
3870 "error=%d", (int)error));
3871 }
3872 else
3873 {
3874 error = http_set_credentials(http);
3875 DEBUG_printf(("4http_setup_ssl: http_set_credentials, error=%d",
3876 (int)error));
3877 }
3878 }
3879
3880 /*
3881 * If there's a server certificate callback installed let it evaluate the
3882 * certificate(s) during the handshake...
3883 */
3884
3885 if (!error && cg->server_cert_cb != NULL)
3886 {
3887 error = SSLSetEnableCertVerify(http->tls, false);
3888 DEBUG_printf(("4http_setup_ssl: SSLSetEnableCertVerify, error=%d",
3889 (int)error));
3890
3891 if (!error)
3892 {
3893 error = SSLSetSessionOption(http->tls,
3894 kSSLSessionOptionBreakOnServerAuth, true);
3895 DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnServerAuth, "
3896 "error=%d", (int)error));
3897 }
3898 }
ef416fc2 3899
ed486911 3900 if (!error)
7cf5915e
MS
3901 {
3902 hostname = httpAddrLocalhost(http->hostaddr) ? "localhost" : http->hostname;
3903 error = SSLSetPeerDomainName(http->tls, hostname, strlen(hostname));
3904
3905 DEBUG_printf(("4http_setup_ssl: SSLSetPeerDomainName, error=%d",
3906 (int)error));
3907 }
ed486911 3908
ef416fc2 3909 if (!error)
b423cd4c 3910 {
7cf5915e
MS
3911 int done = 0; /* Are we done yet? */
3912
3913 while (!error && !done)
3914 {
3915 error = SSLHandshake(http->tls);
3916
3917 DEBUG_printf(("4_httpWait: SSLHandshake returned %d.", (int)error));
3918
3919 switch (error)
3920 {
3921 case noErr :
3922 done = 1;
3923 break;
3924
3925 case errSSLWouldBlock :
3926 usleep(1000);
3927 break;
3928
3929 case errSSLServerAuthCompleted :
3930 error = 0;
3931 if (cg->server_cert_cb)
3932 {
3933 error = httpCopyCredentials(http, &credentials);
3934 if (!error)
3935 {
3936 error = (cg->server_cert_cb)(http, http->tls, credentials,
3937 cg->server_cert_data);
3938 httpFreeCredentials(credentials);
3939 }
3940
3941 DEBUG_printf(("4_httpWait: Server certificate callback returned "
3942 "%d.", (int)error));
3943 }
3944 break;
3945
3946 case errSSLClientCertRequested :
3947 error = 0;
3948
3949 if (cg->client_cert_cb)
3950 {
3951 names = NULL;
3952 if (!(error = SSLCopyDistinguishedNames(http->tls, &dn_array)) &&
3953 dn_array)
3954 {
3955 if ((names = cupsArrayNew(NULL, NULL)) != NULL)
3956 {
3957 for (i = 0, count = CFArrayGetCount(dn_array); i < count; i++)
3958 {
3959 data = (CFDataRef)CFArrayGetValueAtIndex(dn_array, i);
3960
3961 if ((credential = malloc(sizeof(*credential))))
3962 {
3963 credential->datalen = CFDataGetLength(data);
3964 if ((credential->data = malloc(credential->datalen)))
3965 {
3966 memcpy((void *)credential->data, CFDataGetBytePtr(data),
3967 credential->datalen);
3968 cupsArrayAdd(names, credential);
3969 }
3970 }
3971 }
3972 }
3973
3974 CFRelease(dn_array);
3975 }
3976
3977 if (!error)
3978 {
3979 error = (cg->client_cert_cb)(http, http->tls, names,
3980 cg->client_cert_data);
3981
3982 DEBUG_printf(("4_httpWait: Client certificate callback "
3983 "returned %d.", (int)error));
3984 }
3985
3986 httpFreeCredentials(names);
3987 }
3988 break;
3989
3990 case errSSLUnknownRootCert :
3991 message = _("Unable to establish a secure connection to host "
3992 "(untrusted certificate).");
3993 break;
3994
3995 case errSSLNoRootCert :
3996 message = _("Unable to establish a secure connection to host "
3997 "(self-signed certificate).");
3998 break;
3999
4000 case errSSLCertExpired :
4001 message = _("Unable to establish a secure connection to host "
4002 "(expired certificate).");
4003 break;
4004
4005 case errSSLCertNotYetValid :
4006 message = _("Unable to establish a secure connection to host "
4007 "(certificate not yet valid).");
4008 break;
4009
4010 case errSSLHostNameMismatch :
4011 message = _("Unable to establish a secure connection to host "
4012 "(host name mismatch).");
4013 break;
4014
4015 case errSSLXCertChainInvalid :
4016 message = _("Unable to establish a secure connection to host "
4017 "(certificate chain invalid).");
4018 break;
4019
4020 case errSSLConnectionRefused :
4021 message = _("Unable to establish a secure connection to host "
4022 "(peer dropped connection before responding).");
4023 break;
4024
4025 default :
4026 break;
4027 }
4028 }
b423cd4c 4029 }
ef416fc2 4030
89d46774 4031 if (error)
ef416fc2 4032 {
4033 http->error = error;
4034 http->status = HTTP_ERROR;
7cf5915e
MS
4035 errno = ECONNREFUSED;
4036
4037 SSLDisposeContext(http->tls);
4038 http->tls = NULL;
ef416fc2 4039
7cf5915e
MS
4040 /*
4041 * If an error string wasn't set by the callbacks use a generic one...
4042 */
4043
4044 if (!message)
4045#ifdef HAVE_CSSMERRORSTRING
4046 message = cssmErrorString(error);
4047#else
4048 message = _("Unable to establish a secure connection to host.");
4049#endif /* HAVE_CSSMERRORSTRING */
ef416fc2 4050
7cf5915e 4051 _cupsSetError(IPP_PKI_ERROR, message, 1);
ef416fc2 4052
cc754834
MS
4053 return (-1);
4054 }
7cf5915e 4055
cc754834 4056# elif defined(HAVE_SSPISSL)
7cf5915e 4057 http->tls = _sspiAlloc();
cc754834 4058
7cf5915e 4059 if (!http->tls)
cc754834
MS
4060 return (-1);
4061
7cf5915e
MS
4062 http->tls->sock = http->fd;
4063 dwSize = sizeof(username) / sizeof(TCHAR);
cc754834
MS
4064 GetUserName(username, &dwSize);
4065 _sntprintf_s(commonName, sizeof(commonName) / sizeof(TCHAR),
4066 sizeof(commonName) / sizeof(TCHAR), TEXT("CN=%s"), username);
4067
7cf5915e
MS
4068 if (!_sspiGetCredentials(http->tls_credentials, L"ClientContainer",
4069 commonName, FALSE))
cc754834 4070 {
7cf5915e
MS
4071 _sspiFree(http->tls_credentials);
4072 http->tls_credentials = NULL;
cc754834
MS
4073 return (-1);
4074 }
4075
7cf5915e
MS
4076 _sspiSetAllowsAnyRoot(http->tls_credentials, TRUE);
4077 _sspiSetAllowsExpiredCerts(http->tls_credentials, TRUE);
cc754834 4078
7cf5915e 4079 if (!_sspiConnect(http->tls_credentials, http->hostname))
cc754834 4080 {
7cf5915e
MS
4081 _sspiFree(http->tls_credentials);
4082 http->tls_credentials = NULL;
ef416fc2 4083 return (-1);
4084 }
4085# endif /* HAVE_CDSASSL */
4086
ef416fc2 4087 return (0);
4088}
4089#endif /* HAVE_SSL */
4090
4091
4092#ifdef HAVE_SSL
4093/*
4094 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
4095 */
4096
4097static void
568fa3fa 4098http_shutdown_ssl(http_t *http) /* I - Connection to server */
ef416fc2 4099{
4100# ifdef HAVE_LIBSSL
89d46774 4101 SSL_CTX *context; /* Context for encryption */
ef416fc2 4102
7cf5915e 4103 context = SSL_get_SSL_CTX(http->tls_credentials);
ef416fc2 4104
7cf5915e 4105 SSL_shutdown(http->tls_credentials);
ef416fc2 4106 SSL_CTX_free(context);
7cf5915e 4107 SSL_free(http->tls_credentials);
ef416fc2 4108
4109# elif defined(HAVE_GNUTLS)
ef416fc2 4110 gnutls_certificate_client_credentials *credentials;
89d46774 4111 /* TLS credentials */
ef416fc2 4112
7cf5915e 4113 credentials = (gnutls_certificate_client_credentials *)(http->tls_credentials);
ef416fc2 4114
7cf5915e
MS
4115 gnutls_bye(http->tls, GNUTLS_SHUT_RDWR);
4116 gnutls_deinit(http->tls);
ef416fc2 4117 gnutls_certificate_free_credentials(*credentials);
4118 free(credentials);
ef416fc2 4119
4120# elif defined(HAVE_CDSASSL)
7cf5915e 4121 while (SSLClose(http->tls) == errSSLWouldBlock)
b423cd4c 4122 usleep(1000);
4123
7cf5915e 4124 SSLDisposeContext(http->tls);
89d46774 4125
7cf5915e
MS
4126 if (http->tls_credentials)
4127 CFRelease(http->tls_credentials);
89d46774 4128
cc754834 4129# elif defined(HAVE_SSPISSL)
7cf5915e 4130 _sspiFree(http->tls_credentials);
ef416fc2 4131# endif /* HAVE_LIBSSL */
4132
7cf5915e
MS
4133 http->tls = NULL;
4134 http->tls_credentials = NULL;
ef416fc2 4135}
4136#endif /* HAVE_SSL */
4137
4138
6d2f911b
MS
4139#ifdef HAVE_LIBSSL
4140/*
4141 * 'http_threadid_cb()' - Return the current thread ID.
4142 */
4143
4144static unsigned long /* O - Thread ID */
4145http_threadid_cb(void)
4146{
4147# ifdef HAVE_PTHREAD_H
4148 return ((unsigned long)pthread_self());
4149# else
4150 return (0);
4151# endif /* HAVE_PTHREAD_H */
4152}
4153#endif /* HAVE_LIBSSL */
4154
4155
ef416fc2 4156#ifdef HAVE_SSL
4157/*
4158 * 'http_upgrade()' - Force upgrade to TLS encryption.
4159 */
4160
89d46774 4161static int /* O - Status of connection */
568fa3fa 4162http_upgrade(http_t *http) /* I - Connection to server */
ef416fc2 4163{
89d46774 4164 int ret; /* Return value */
4165 http_t myhttp; /* Local copy of HTTP data */
ef416fc2 4166
4167
e07d4801 4168 DEBUG_printf(("7http_upgrade(%p)", http));
ef416fc2 4169
85b5d1df
MS
4170 /*
4171 * Flush the connection to make sure any previous "Upgrade" message
4172 * has been read.
4173 */
4174
4175 httpFlush(http);
4176
ef416fc2 4177 /*
4178 * Copy the HTTP data to a local variable so we can do the OPTIONS
4179 * request without interfering with the existing request data...
4180 */
4181
4182 memcpy(&myhttp, http, sizeof(myhttp));
4183
4184 /*
4185 * Send an OPTIONS request to the server, requiring SSL or TLS
4186 * encryption on the link...
4187 */
4188
f7deaa1a 4189 http->field_authorization = NULL; /* Don't free the auth string */
4190
b86bc4cf 4191 httpClearFields(http);
4192 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
7cf5915e 4193 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2, TLS/1.1, TLS/1.0, SSL/3.0");
ef416fc2 4194
b86bc4cf 4195 if ((ret = httpOptions(http, "*")) == 0)
ef416fc2 4196 {
4197 /*
4198 * Wait for the secure connection...
4199 */
4200
b86bc4cf 4201 while (httpUpdate(http) == HTTP_CONTINUE);
ef416fc2 4202 }
4203
ef416fc2 4204 /*
b86bc4cf 4205 * Restore the HTTP request data...
ef416fc2 4206 */
4207
b86bc4cf 4208 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
f7deaa1a 4209 http->data_encoding = myhttp.data_encoding;
4210 http->data_remaining = myhttp.data_remaining;
4211 http->_data_remaining = myhttp._data_remaining;
4212 http->expect = myhttp.expect;
4213 http->field_authorization = myhttp.field_authorization;
bc44d920 4214 http->digest_tries = myhttp.digest_tries;
ef416fc2 4215
4216 /*
4217 * See if we actually went secure...
4218 */
4219
4220 if (!http->tls)
4221 {
4222 /*
4223 * Server does not support HTTP upgrade...
4224 */
4225
e07d4801 4226 DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!");
ef416fc2 4227
4228# ifdef WIN32
4229 closesocket(http->fd);
4230# else
4231 close(http->fd);
4232# endif
4233
4234 http->fd = -1;
4235
4236 return (-1);
4237 }
4238 else
4239 return (ret);
4240}
4241#endif /* HAVE_SSL */
4242
4243
ef416fc2 4244/*
4245 * 'http_write()' - Write a buffer to a HTTP connection.
4246 */
ef55b745 4247
ef416fc2 4248static int /* O - Number of bytes written */
568fa3fa 4249http_write(http_t *http, /* I - Connection to server */
f11a948a
MS
4250 const char *buffer, /* I - Buffer for data */
4251 int length) /* I - Number of bytes to write */
ef416fc2 4252{
4253 int tbytes, /* Total bytes sent */
4254 bytes; /* Bytes sent */
4255
4256
f8b3a85b
MS
4257 DEBUG_printf(("2http_write(http=%p, buffer=%p, length=%d)", http, buffer,
4258 length));
f11a948a
MS
4259 http->error = 0;
4260 tbytes = 0;
ef416fc2 4261
4262 while (length > 0)
4263 {
4264#ifdef HAVE_SSL
4265 if (http->tls)
4266 bytes = http_write_ssl(http, buffer, length);
4267 else
4268#endif /* HAVE_SSL */
4269 bytes = send(http->fd, buffer, length, 0);
4270
4271 if (bytes < 0)
4272 {
4273#ifdef WIN32
10d09e33 4274 if (WSAGetLastError() == WSAEINTR)
cc754834 4275 continue;
10d09e33
MS
4276 else if (WSAGetLastError() == WSAEWOULDBLOCK)
4277 {
4278 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4279 continue;
4280
4281 http->error = WSAGetLastError();
4282 }
4283 else if (WSAGetLastError() != http->error &&
4284 WSAGetLastError() != WSAECONNRESET)
ef416fc2 4285 {
4286 http->error = WSAGetLastError();
4287 continue;
4288 }
10d09e33 4289
ef416fc2 4290#else
10d09e33 4291 if (errno == EINTR)
ef416fc2 4292 continue;
10d09e33
MS
4293 else if (errno == EWOULDBLOCK || errno == EAGAIN)
4294 {
4295 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4296 continue;
4297 else if (!http->timeout_cb && errno == EAGAIN)
4298 continue;
4299
4300 http->error = errno;
4301 }
ef416fc2 4302 else if (errno != http->error && errno != ECONNRESET)
4303 {
4304 http->error = errno;
4305 continue;
4306 }
4307#endif /* WIN32 */
4308
f8b3a85b
MS
4309 DEBUG_printf(("3http_write: error writing data (%s).",
4310 strerror(http->error)));
ef416fc2 4311
4312 return (-1);
4313 }
4314
4315 buffer += bytes;
4316 tbytes += bytes;
4317 length -= bytes;
4318 }
4319
4320#ifdef DEBUG
ae71f5de 4321 http_debug_hex("http_write", buffer - tbytes, tbytes);
ef416fc2 4322#endif /* DEBUG */
4323
f8b3a85b
MS
4324 DEBUG_printf(("3http_write: Returning %d.", tbytes));
4325
ef416fc2 4326 return (tbytes);
4327}
4328
4329
4330/*
4331 * 'http_write_chunk()' - Write a chunked buffer.
4332 */
4333
4334static int /* O - Number bytes written */
568fa3fa 4335http_write_chunk(http_t *http, /* I - Connection to server */
ef416fc2 4336 const char *buffer, /* I - Buffer to write */
4337 int length) /* I - Length of buffer */
4338{
4339 char header[255]; /* Chunk header */
4340 int bytes; /* Bytes written */
4341
f11a948a 4342
e07d4801 4343 DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=%d)",
ef416fc2 4344 http, buffer, length));
4345
4346 /*
4347 * Write the chunk header, data, and trailer.
4348 */
4349
4350 sprintf(header, "%x\r\n", length);
b86bc4cf 4351 if (http_write(http, header, (int)strlen(header)) < 0)
ef416fc2 4352 {
e07d4801 4353 DEBUG_puts("8http_write_chunk: http_write of length failed!");
ef416fc2 4354 return (-1);
4355 }
4356
4357 if ((bytes = http_write(http, buffer, length)) < 0)
4358 {
e07d4801 4359 DEBUG_puts("8http_write_chunk: http_write of buffer failed!");
ef416fc2 4360 return (-1);
4361 }
4362
4363 if (http_write(http, "\r\n", 2) < 0)
4364 {
e07d4801 4365 DEBUG_puts("8http_write_chunk: http_write of CR LF failed!");
ef416fc2 4366 return (-1);
4367 }
4368
4369 return (bytes);
4370}
4371
4372
4373#ifdef HAVE_SSL
4374/*
4375 * 'http_write_ssl()' - Write to a SSL/TLS connection.
4376 */
4377
4378static int /* O - Bytes written */
568fa3fa 4379http_write_ssl(http_t *http, /* I - Connection to server */
ef416fc2 4380 const char *buf, /* I - Buffer holding data */
4381 int len) /* I - Length of buffer */
4382{
f8b3a85b
MS
4383 ssize_t result; /* Return value */
4384
4385
4386 DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len));
4387
ef416fc2 4388# if defined(HAVE_LIBSSL)
f8b3a85b 4389 result = SSL_write((SSL *)(http->tls), buf, len);
ef416fc2 4390
4391# elif defined(HAVE_GNUTLS)
7cf5915e 4392 result = gnutls_record_send(http->tls, buf, len);
ef55b745
MS
4393
4394 if (result < 0 && !errno)
4395 {
4396 /*
4397 * Convert GNU TLS error to errno value...
4398 */
4399
4400 switch (result)
4401 {
4402 case GNUTLS_E_INTERRUPTED :
4403 errno = EINTR;
4404 break;
4405
4406 case GNUTLS_E_AGAIN :
4407 errno = EAGAIN;
4408 break;
4409
4410 default :
4411 errno = EPIPE;
4412 break;
4413 }
4414
4415 result = -1;
4416 }
4417
ef416fc2 4418# elif defined(HAVE_CDSASSL)
4419 OSStatus error; /* Error info */
4420 size_t processed; /* Number of bytes processed */
4421
4422
7cf5915e 4423 error = SSLWrite(http->tls, buf, len, &processed);
ef416fc2 4424
fa73b229 4425 switch (error)
ef416fc2 4426 {
fa73b229 4427 case 0 :
4428 result = (int)processed;
4429 break;
4430 case errSSLClosedGraceful :
4431 result = 0;
4432 break;
4433 case errSSLWouldBlock :
b423cd4c 4434 if (processed)
4435 result = (int)processed;
4436 else
4437 {
4438 result = -1;
ef55b745 4439 errno = EINTR;
b423cd4c 4440 }
fa73b229 4441 break;
4442 default :
ef55b745 4443 errno = EPIPE;
fa73b229 4444 result = -1;
4445 break;
ef416fc2 4446 }
cc754834
MS
4447# elif defined(HAVE_SSPISSL)
4448 return _sspiWrite((_sspi_struct_t*) http->tls, (void*) buf, len);
ef416fc2 4449# endif /* HAVE_LIBSSL */
f8b3a85b
MS
4450
4451 DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result));
4452
4453 return ((int)result);
ef416fc2 4454}
4455#endif /* HAVE_SSL */
4456
4457
4458/*
b19ccc9e 4459 * End of "$Id: http.c 7850 2008-08-20 00:07:25Z mike $".
ef416fc2 4460 */