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