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