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