1 /*
2  * "$Id: http.c 9233 2010-08-10 06:15:55Z mike $"
3  *
4  *   HTTP routines for CUPS.
5  *
6  *   Copyright 2007-2010 by Apple Inc.
7  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
8  *
9  *   This file contains Kerberos support code, copyright 2006 by
10  *   Jelmer Vernooij.
11  *
12  *   These coded instructions, statements, and computer programs are the
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/".
17  *
18  *   This file is subject to the Apple OS-Developed Software exception.
19  *
20  * Contents:
21  *
22  *   _httpBIOMethods()    - Get the OpenSSL BIO methods for HTTP connections.
23  *   httpBlocking()       - Set blocking/non-blocking behavior on a connection.
24  *   httpCheck()          - Check to see if there is a pending response from the
25  *                          server.
26  *   httpClearCookie()    - Clear the cookie value(s).
27  *   httpClearFields()    - Clear HTTP request fields.
28  *   httpClose()          - Close an HTTP connection.
29  *   httpConnect()        - Connect to a HTTP server.
30  *   httpConnectEncrypt() - Connect to a HTTP server using encryption.
31  *   _httpCreate()        - Create an unconnected HTTP connection.
32  *   httpDelete()         - Send a DELETE request to the server.
33  *   httpEncryption()     - Set the required encryption on the link.
34  *   httpError()          - Get the last error on a connection.
35  *   httpFlush()          - Flush data from a HTTP connection.
36  *   httpFlushWrite()     - Flush data in write buffer.
37  *   httpGet()            - Send a GET request to the server.
38  *   httpGetAuthString()  - Get the current authorization string.
39  *   httpGetBlocking()    - Get the blocking/non-block state of a connection.
40  *   httpGetCookie()      - Get any cookie data from the response.
41  *   httpGetFd()          - Get the file descriptor associated with a
42  *                          connection.
43  *   httpGetField()       - Get a field value from a request/response.
44  *   httpGetLength()      - Get the amount of data remaining from the
45  *                          content-length or transfer-encoding fields.
46  *   httpGetLength2()     - Get the amount of data remaining from the
47  *                          content-length or transfer-encoding fields.
48  *   httpGetStatus()      - Get the status of the last HTTP request.
49  *   httpGetSubField()    - Get a sub-field value.
50  *   httpGetSubField2()   - Get a sub-field value.
51  *   httpGets()           - Get a line of text from a HTTP connection.
52  *   httpHead()           - Send a HEAD request to the server.
53  *   httpInitialize()     - Initialize the HTTP interface library and set the
54  *                          default HTTP proxy (if any).
55  *   httpOptions()        - Send an OPTIONS request to the server.
56  *   httpPost()           - Send a POST request to the server.
57  *   httpPrintf()         - Print a formatted string to a HTTP connection.
58  *   httpPut()            - Send a PUT request to the server.
59  *   httpRead()           - Read data from a HTTP connection.
60  *   httpRead2()          - Read data from a HTTP connection.
61  *   _httpReadCDSA()      - Read function for the CDSA library.
62  *   _httpReadGNUTLS()    - Read function for the GNU TLS library.
63  *   httpReconnect()      - Reconnect to a HTTP server.
64  *   httpSetAuthString()  - Set the current authorization string.
65  *   httpSetCookie()      - Set the cookie value(s).
66  *   httpSetExpect()      - Set the Expect: header in a request.
67  *   httpSetField()       - Set the value of an HTTP header.
68  *   httpSetLength()      - Set the content-length and content-encoding.
69  *   httpTrace()          - Send an TRACE request to the server.
70  *   httpUpdate()         - Update the current HTTP state for incoming data.
71  *   _httpWait()          - Wait for data available on a connection (no flush).
72  *   httpWait()           - Wait for data available on a connection.
73  *   httpWrite()          - Write data to a HTTP connection.
74  *   httpWrite2()         - Write data to a HTTP connection.
75  *   _httpWriteCDSA()     - Write function for the CDSA library.
76  *   _httpWriteGNUTLS()   - Write function for the GNU TLS library.
77  *   http_bio_ctrl()      - Control the HTTP connection.
78  *   http_bio_free()      - Free OpenSSL data.
79  *   http_bio_new()       - Initialize an OpenSSL BIO structure.
80  *   http_bio_puts()      - Send a string for OpenSSL.
81  *   http_bio_read()      - Read data for OpenSSL.
82  *   http_bio_write()     - Write data for OpenSSL.
83  *   http_debug_hex()     - Do a hex dump of a buffer.
84  *   http_field()         - Return the field index for a field name.
85  *   http_read_ssl()      - Read from a SSL/TLS connection.
86  *   http_locking_cb()    - Lock/unlock a thread's mutex.
87  *   http_send()          - Send a request with all fields and the trailing
88  *                          blank line.
89  *   http_setup_ssl()     - Set up SSL/TLS support on a connection.
90  *   http_shutdown_ssl()  - Shut down SSL/TLS on a connection.
91  *   http_threadid_cb()   - Return the current thread ID.
92  *   http_upgrade()       - Force upgrade to TLS encryption.
93  *   http_write()         - Write a buffer to a HTTP connection.
94  *   http_write_chunk()   - Write a chunked buffer.
95  *   http_write_ssl()     - Write to a SSL/TLS connection.
96  */
97 
98 /*
99  * Include necessary headers...
100  */
101 
102 #include "http-private.h"
103 #include "globals.h"
104 #include "debug.h"
105 #include <stdlib.h>
106 #include <fcntl.h>
107 #include <errno.h>
108 #ifndef WIN32
109 #  include <signal.h>
110 #  include <sys/time.h>
111 #  include <sys/resource.h>
112 #endif /* !WIN32 */
113 #ifdef HAVE_POLL
114 #  include <sys/poll.h>
115 #endif /* HAVE_POLL */
116 
117 
118 /*
119  * Some operating systems have done away with the Fxxxx constants for
120  * the fcntl() call; this works around that "feature"...
121  */
122 
123 #ifndef FNONBLK
124 #  define FNONBLK O_NONBLOCK
125 #endif /* !FNONBLK */
126 
127 
128 /*
129  * Local functions...
130  */
131 
132 #ifdef DEBUG
133 static void		http_debug_hex(const char *prefix, const char *buffer,
134 			               int bytes);
135 #endif /* DEBUG */
136 static http_field_t	http_field(const char *name);
137 static int		http_send(http_t *http, http_state_t request,
138 			          const char *uri);
139 static int		http_write(http_t *http, const char *buffer,
140 			           int length);
141 static int		http_write_chunk(http_t *http, const char *buffer,
142 			                 int length);
143 #ifdef HAVE_SSL
144 static int		http_read_ssl(http_t *http, char *buf, int len);
145 static int		http_setup_ssl(http_t *http);
146 static void		http_shutdown_ssl(http_t *http);
147 static int		http_upgrade(http_t *http);
148 static int		http_write_ssl(http_t *http, const char *buf, int len);
149 
150 #  ifdef HAVE_GNUTLS
151 #    ifdef HAVE_PTHREAD_H
152 GCRY_THREAD_OPTION_PTHREAD_IMPL;
153 #    endif /* HAVE_PTHREAD_H */
154 
155 #  elif defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD_H)
156 static pthread_mutex_t	*http_locks;	/* OpenSSL lock mutexes */
157 
158 static void		http_locking_cb(int mode, int type, const char *file,
159 					int line);
160 static unsigned long	http_threadid_cb(void);
161 #  endif /* HAVE_GNUTLS */
162 #endif /* HAVE_SSL */
163 
164 
165 /*
166  * Local globals...
167  */
168 
169 static const char * const http_fields[] =
170 			{
171 			  "Accept-Language",
172 			  "Accept-Ranges",
173 			  "Authorization",
174 			  "Connection",
175 			  "Content-Encoding",
176 			  "Content-Language",
177 			  "Content-Length",
178 			  "Content-Location",
179 			  "Content-MD5",
180 			  "Content-Range",
181 			  "Content-Type",
182 			  "Content-Version",
183 			  "Date",
184 			  "Host",
185 			  "If-Modified-Since",
186 			  "If-Unmodified-since",
187 			  "Keep-Alive",
188 			  "Last-Modified",
189 			  "Link",
190 			  "Location",
191 			  "Range",
192 			  "Referer",
193 			  "Retry-After",
194 			  "Transfer-Encoding",
195 			  "Upgrade",
196 			  "User-Agent",
197 			  "WWW-Authenticate"
198 			};
199 #ifdef DEBUG
200 static const char * const http_states[] =
201 			{
202 			  "HTTP_WAITING",
203 			  "HTTP_OPTIONS",
204 			  "HTTP_GET",
205 			  "HTTP_GET_SEND",
206 			  "HTTP_HEAD",
207 			  "HTTP_POST",
208 			  "HTTP_POST_RECV",
209 			  "HTTP_POST_SEND",
210 			  "HTTP_PUT",
211 			  "HTTP_PUT_RECV",
212 			  "HTTP_DELETE",
213 			  "HTTP_TRACE",
214 			  "HTTP_CLOSE",
215 			  "HTTP_STATUS"
216 			};
217 #endif /* DEBUG */
218 
219 
220 #if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
221 /*
222  * BIO methods for OpenSSL...
223  */
224 
225 static int		http_bio_write(BIO *h, const char *buf, int num);
226 static int		http_bio_read(BIO *h, char *buf, int size);
227 static int		http_bio_puts(BIO *h, const char *str);
228 static long		http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
229 static int		http_bio_new(BIO *h);
230 static int		http_bio_free(BIO *data);
231 
232 static BIO_METHOD	http_bio_methods =
233 			{
234 			  BIO_TYPE_SOCKET,
235 			  "http",
236 			  http_bio_write,
237 			  http_bio_read,
238 			  http_bio_puts,
239 			  NULL, /* http_bio_gets, */
240 			  http_bio_ctrl,
241 			  http_bio_new,
242 			  http_bio_free,
243 			  NULL,
244 			};
245 
246 
247 /*
248  * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections.
249  */
250 
251 BIO_METHOD *				/* O - BIO methods for OpenSSL */
_httpBIOMethods(void)252 _httpBIOMethods(void)
253 {
254   return (&http_bio_methods);
255 }
256 #endif /* HAVE_SSL && HAVE_LIBSSL */
257 
258 
259 /*
260  * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
261  */
262 
263 void
httpBlocking(http_t * http,int b)264 httpBlocking(http_t *http,		/* I - Connection to server */
265              int    b)			/* I - 1 = blocking, 0 = non-blocking */
266 {
267   if (http)
268     http->blocking = b;
269 }
270 
271 
272 /*
273  * 'httpCheck()' - Check to see if there is a pending response from the server.
274  */
275 
276 int					/* O - 0 = no data, 1 = data available */
httpCheck(http_t * http)277 httpCheck(http_t *http)			/* I - Connection to server */
278 {
279   return (httpWait(http, 0));
280 }
281 
282 
283 /*
284  * 'httpClearCookie()' - Clear the cookie value(s).
285  *
286  * @since CUPS 1.1.19/Mac OS X 10.3@
287  */
288 
289 void
httpClearCookie(http_t * http)290 httpClearCookie(http_t *http)		/* I - Connection to server */
291 {
292   if (!http)
293     return;
294 
295   if (http->cookie)
296   {
297     free(http->cookie);
298     http->cookie = NULL;
299   }
300 }
301 
302 
303 /*
304  * 'httpClearFields()' - Clear HTTP request fields.
305  */
306 
307 void
httpClearFields(http_t * http)308 httpClearFields(http_t *http)		/* I - Connection to server */
309 {
310   if (http)
311   {
312     memset(http->fields, 0, sizeof(http->fields));
313     if (http->hostname[0] == '/')
314       httpSetField(http, HTTP_FIELD_HOST, "localhost");
315     else
316       httpSetField(http, HTTP_FIELD_HOST, http->hostname);
317 
318     if (http->field_authorization)
319     {
320       free(http->field_authorization);
321       http->field_authorization = NULL;
322     }
323 
324     http->expect = (http_status_t)0;
325   }
326 }
327 
328 
329 /*
330  * 'httpClose()' - Close an HTTP connection.
331  */
332 
333 void
httpClose(http_t * http)334 httpClose(http_t *http)			/* I - Connection to server */
335 {
336 #ifdef HAVE_GSSAPI
337   OM_uint32	minor_status;		/* Minor status code */
338 #endif /* HAVE_GSSAPI */
339 
340 
341   DEBUG_printf(("httpClose(http=%p)", http));
342 
343   if (!http)
344     return;
345 
346   httpAddrFreeList(http->addrlist);
347 
348   if (http->cookie)
349     free(http->cookie);
350 
351 #ifdef HAVE_SSL
352   if (http->tls)
353     http_shutdown_ssl(http);
354 #endif /* HAVE_SSL */
355 
356 #ifdef WIN32
357   closesocket(http->fd);
358 #else
359   close(http->fd);
360 #endif /* WIN32 */
361 
362 #ifdef HAVE_GSSAPI
363   if (http->gssctx != GSS_C_NO_CONTEXT)
364     gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
365 
366   if (http->gssname != GSS_C_NO_NAME)
367     gss_release_name(&minor_status, &http->gssname);
368 #endif /* HAVE_GSSAPI */
369 
370 #ifdef HAVE_AUTHORIZATION_H
371   if (http->auth_ref)
372     AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
373 #endif /* HAVE_AUTHORIZATION_H */
374 
375   httpClearFields(http);
376 
377   if (http->authstring && http->authstring != http->_authstring)
378     free(http->authstring);
379 
380   free(http);
381 }
382 
383 
384 /*
385  * 'httpConnect()' - Connect to a HTTP server.
386  *
387  * This function is deprecated - use @link httpConnectEncrypt@ instead.
388  *
389  * @deprecated@
390  */
391 
392 http_t *				/* O - New HTTP connection */
httpConnect(const char * host,int port)393 httpConnect(const char *host,		/* I - Host to connect to */
394             int        port)		/* I - Port number */
395 {
396   return (httpConnectEncrypt(host, port, HTTP_ENCRYPT_IF_REQUESTED));
397 }
398 
399 
400 /*
401  * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
402  */
403 
404 http_t *				/* O - New HTTP connection */
httpConnectEncrypt(const char * host,int port,http_encryption_t encryption)405 httpConnectEncrypt(
406     const char        *host,		/* I - Host to connect to */
407     int               port,		/* I - Port number */
408     http_encryption_t encryption)	/* I - Type of encryption to use */
409 {
410   http_t	*http;			/* New HTTP connection */
411 
412 
413   DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)",
414                 host, port, encryption));
415 
416  /*
417   * Create the HTTP structure...
418   */
419 
420   if ((http = _httpCreate(host, port, encryption)) == NULL)
421     return (NULL);
422 
423  /*
424   * Connect to the remote system...
425   */
426 
427   if (!httpReconnect(http))
428     return (http);
429 
430  /*
431   * Could not connect to any known address - bail out!
432   */
433 
434   httpAddrFreeList(http->addrlist);
435 
436   free(http);
437 
438   return (NULL);
439 }
440 
441 
442 /*
443  * '_httpCreate()' - Create an unconnected HTTP connection.
444  */
445 
446 http_t *				/* O - HTTP connection */
_httpCreate(const char * host,int port,http_encryption_t encryption)447 _httpCreate(
448     const char        *host,		/* I - Hostname */
449     int               port,		/* I - Port number */
450     http_encryption_t encryption)	/* I - Encryption to use */
451 {
452   http_t		*http;		/* New HTTP connection */
453   http_addrlist_t	*addrlist;	/* Host address data */
454   char			service[255];	/* Service name */
455 
456 
457   DEBUG_printf(("4_httpCreate(host=\"%s\", port=%d, encryption=%d)",
458                 host, port, encryption));
459 
460   if (!host)
461     return (NULL);
462 
463   httpInitialize();
464 
465  /*
466   * Lookup the host...
467   */
468 
469   sprintf(service, "%d", port);
470 
471   if ((addrlist = httpAddrGetList(host, AF_UNSPEC, service)) == NULL)
472     return (NULL);
473 
474  /*
475   * Allocate memory for the structure...
476   */
477 
478   if ((http = calloc(sizeof(http_t), 1)) == NULL)
479   {
480     httpAddrFreeList(addrlist);
481     return (NULL);
482   }
483 
484  /*
485   * Initialize the HTTP data...
486   */
487 
488   http->activity = time(NULL);
489   http->addrlist = addrlist;
490   http->blocking = 1;
491   http->fd       = -1;
492 #ifdef HAVE_GSSAPI
493   http->gssctx   = GSS_C_NO_CONTEXT;
494   http->gssname  = GSS_C_NO_NAME;
495 #endif /* HAVE_GSSAPI */
496   http->version  = HTTP_1_1;
497 
498   strlcpy(http->hostname, host, sizeof(http->hostname));
499 
500   if (port == 443)			/* Always use encryption for https */
501     http->encryption = HTTP_ENCRYPT_ALWAYS;
502   else
503     http->encryption = encryption;
504 
505  /*
506   * Return the new structure...
507   */
508 
509   return (http);
510 }
511 
512 
513 /*
514  * 'httpDelete()' - Send a DELETE request to the server.
515  */
516 
517 int					/* O - Status of call (0 = success) */
httpDelete(http_t * http,const char * uri)518 httpDelete(http_t     *http,		/* I - Connection to server */
519            const char *uri)		/* I - URI to delete */
520 {
521   return (http_send(http, HTTP_DELETE, uri));
522 }
523 
524 
525 /*
526  * 'httpEncryption()' - Set the required encryption on the link.
527  */
528 
529 int					/* O - -1 on error, 0 on success */
httpEncryption(http_t * http,http_encryption_t e)530 httpEncryption(http_t            *http,	/* I - Connection to server */
531                http_encryption_t e)	/* I - New encryption preference */
532 {
533   DEBUG_printf(("httpEncryption(http=%p, e=%d)", http, e));
534 
535 #ifdef HAVE_SSL
536   if (!http)
537     return (0);
538 
539   http->encryption = e;
540 
541   if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
542       (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
543     return (httpReconnect(http));
544   else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
545     return (http_upgrade(http));
546   else
547     return (0);
548 #else
549   if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
550     return (-1);
551   else
552     return (0);
553 #endif /* HAVE_SSL */
554 }
555 
556 
557 /*
558  * 'httpError()' - Get the last error on a connection.
559  */
560 
561 int					/* O - Error code (errno) value */
httpError(http_t * http)562 httpError(http_t *http)			/* I - Connection to server */
563 {
564   if (http)
565     return (http->error);
566   else
567     return (EINVAL);
568 }
569 
570 
571 /*
572  * 'httpFlush()' - Flush data from a HTTP connection.
573  */
574 
575 void
httpFlush(http_t * http)576 httpFlush(http_t *http)			/* I - Connection to server */
577 {
578   char		buffer[8192];		/* Junk buffer */
579   int		blocking;		/* To block or not to block */
580   http_state_t	oldstate;		/* Old state */
581 
582 
583   DEBUG_printf(("httpFlush(http=%p), state=%s", http,
584                 http_states[http->state]));
585 
586  /*
587   * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
588   */
589 
590   blocking = http->blocking;
591   http->blocking = 0;
592 
593  /*
594   * Read any data we can...
595   */
596 
597   oldstate = http->state;
598   while (httpRead2(http, buffer, sizeof(buffer)) > 0);
599 
600  /*
601   * Restore blocking and reset the connection if we didn't get all of
602   * the remaining data...
603   */
604 
605   http->blocking = blocking;
606 
607   if (http->state == oldstate && http->state != HTTP_WAITING && http->fd >= 0)
608   {
609    /*
610     * Didn't get the data back, so close the current connection.
611     */
612 
613     http->state = HTTP_WAITING;
614 
615 #ifdef HAVE_SSL
616     if (http->tls)
617       http_shutdown_ssl(http);
618 #endif /* HAVE_SSL */
619 
620 #ifdef WIN32
621     closesocket(http->fd);
622 #else
623     close(http->fd);
624 #endif /* WIN32 */
625 
626     http->fd = -1;
627   }
628 }
629 
630 
631 /*
632  * 'httpFlushWrite()' - Flush data in write buffer.
633  *
634  * @since CUPS 1.2/Mac OS X 10.5@
635  */
636 
637 int					/* O - Bytes written or -1 on error */
httpFlushWrite(http_t * http)638 httpFlushWrite(http_t *http)		/* I - Connection to server */
639 {
640   int	bytes;				/* Bytes written */
641 
642 
643   DEBUG_printf(("httpFlushWrite(http=%p)", http));
644 
645   if (!http || !http->wused)
646     return (0);
647 
648   if (http->data_encoding == HTTP_ENCODE_CHUNKED)
649     bytes = http_write_chunk(http, http->wbuffer, http->wused);
650   else
651     bytes = http_write(http, http->wbuffer, http->wused);
652 
653   http->wused = 0;
654 
655   return (bytes);
656 }
657 
658 
659 /*
660  * 'httpGet()' - Send a GET request to the server.
661  */
662 
663 int					/* O - Status of call (0 = success) */
httpGet(http_t * http,const char * uri)664 httpGet(http_t     *http,		/* I - Connection to server */
665         const char *uri)		/* I - URI to get */
666 {
667   return (http_send(http, HTTP_GET, uri));
668 }
669 
670 
671 /*
672  * 'httpGetAuthString()' - Get the current authorization string.
673  *
674  * The authorization string is set by cupsDoAuthentication() and
675  * httpSetAuthString().  Use httpGetAuthString() to retrieve the
676  * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION
677  * value.
678  *
679  * @since CUPS 1.3/Mac OS X 10.5@
680  */
681 
682 char *					/* O - Authorization string */
httpGetAuthString(http_t * http)683 httpGetAuthString(http_t *http)		/* I - Connection to server */
684 {
685   if (http)
686     return (http->authstring);
687   else
688     return (NULL);
689 }
690 
691 
692 /*
693  * 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
694  *
695  * @since CUPS 1.2/Mac OS X 10.5@
696  */
697 
698 int					/* O - 1 if blocking, 0 if non-blocking */
httpGetBlocking(http_t * http)699 httpGetBlocking(http_t *http)		/* I - Connection to server */
700 {
701   return (http ? http->blocking : 0);
702 }
703 
704 
705 /*
706  * 'httpGetCookie()' - Get any cookie data from the response.
707  *
708  * @since CUPS 1.1.19/Mac OS X 10.3@
709  */
710 
711 const char *				/* O - Cookie data or NULL */
httpGetCookie(http_t * http)712 httpGetCookie(http_t *http)		/* I - HTTP connecion */
713 {
714   return (http ? http->cookie : NULL);
715 }
716 
717 
718 /*
719  * 'httpGetFd()' - Get the file descriptor associated with a connection.
720  *
721  * @since CUPS 1.2/Mac OS X 10.5@
722  */
723 
724 int					/* O - File descriptor or -1 if none */
httpGetFd(http_t * http)725 httpGetFd(http_t *http)			/* I - Connection to server */
726 {
727   return (http ? http->fd : -1);
728 }
729 
730 
731 /*
732  * 'httpGetField()' - Get a field value from a request/response.
733  */
734 
735 const char *				/* O - Field value */
httpGetField(http_t * http,http_field_t field)736 httpGetField(http_t       *http,	/* I - Connection to server */
737              http_field_t field)	/* I - Field to get */
738 {
739   if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
740     return (NULL);
741   else if (field == HTTP_FIELD_AUTHORIZATION &&
742 	   http->field_authorization)
743   {
744    /*
745     * Special case for WWW-Authenticate: as its contents can be
746     * longer than HTTP_MAX_VALUE...
747     */
748 
749     return (http->field_authorization);
750   }
751   else
752     return (http->fields[field]);
753 }
754 
755 
756 /*
757  * 'httpGetLength()' - Get the amount of data remaining from the
758  *                     content-length or transfer-encoding fields.
759  *
760  * This function is deprecated and will not return lengths larger than
761  * 2^31 - 1; use httpGetLength2() instead.
762  *
763  * @deprecated@
764  */
765 
766 int					/* O - Content length */
httpGetLength(http_t * http)767 httpGetLength(http_t *http)		/* I - Connection to server */
768 {
769  /*
770   * Get the read content length and return the 32-bit value.
771   */
772 
773   if (http)
774   {
775     httpGetLength2(http);
776 
777     return (http->_data_remaining);
778   }
779   else
780     return (-1);
781 }
782 
783 
784 /*
785  * 'httpGetLength2()' - Get the amount of data remaining from the
786  *                      content-length or transfer-encoding fields.
787  *
788  * This function returns the complete content length, even for
789  * content larger than 2^31 - 1.
790  *
791  * @since CUPS 1.2/Mac OS X 10.5@
792  */
793 
794 off_t					/* O - Content length */
httpGetLength2(http_t * http)795 httpGetLength2(http_t *http)		/* I - Connection to server */
796 {
797   DEBUG_printf(("2httpGetLength2(http=%p), state=%s", http,
798                 http_states[http->state]));
799 
800   if (!http)
801     return (-1);
802 
803   if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
804   {
805     DEBUG_puts("4httpGetLength2: chunked request!");
806 
807     http->data_encoding  = HTTP_ENCODE_CHUNKED;
808     http->data_remaining = 0;
809   }
810   else
811   {
812     http->data_encoding = HTTP_ENCODE_LENGTH;
813 
814    /*
815     * The following is a hack for HTTP servers that don't send a
816     * content-length or transfer-encoding field...
817     *
818     * If there is no content-length then the connection must close
819     * after the transfer is complete...
820     */
821 
822     if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
823     {
824      /*
825       * Default content length is 0 for errors and 2^31-1 for other
826       * successful requests...
827       */
828 
829       if (http->status >= HTTP_MULTIPLE_CHOICES)
830         http->data_remaining = 0;
831       else
832         http->data_remaining = 2147483647;
833     }
834     else
835       http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
836                                      NULL, 10);
837 
838     DEBUG_printf(("4httpGetLength2: content_length=" CUPS_LLFMT,
839                   CUPS_LLCAST http->data_remaining));
840   }
841 
842   if (http->data_remaining <= INT_MAX)
843     http->_data_remaining = (int)http->data_remaining;
844   else
845     http->_data_remaining = INT_MAX;
846 
847   return (http->data_remaining);
848 }
849 
850 
851 /*
852  * 'httpGetStatus()' - Get the status of the last HTTP request.
853  *
854  * @since CUPS 1.2/Mac OS X 10.5@
855  */
856 
857 http_status_t				/* O - HTTP status */
httpGetStatus(http_t * http)858 httpGetStatus(http_t *http)		/* I - Connection to server */
859 {
860   return (http ? http->status : HTTP_ERROR);
861 }
862 
863 
864 /*
865  * 'httpGetSubField()' - Get a sub-field value.
866  *
867  * @deprecated@
868  */
869 
870 char *					/* O - Value or NULL */
httpGetSubField(http_t * http,http_field_t field,const char * name,char * value)871 httpGetSubField(http_t       *http,	/* I - Connection to server */
872                 http_field_t field,	/* I - Field index */
873                 const char   *name,	/* I - Name of sub-field */
874 		char         *value)	/* O - Value string */
875 {
876   return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
877 }
878 
879 
880 /*
881  * 'httpGetSubField2()' - Get a sub-field value.
882  *
883  * @since CUPS 1.2/Mac OS X 10.5@
884  */
885 
886 char *					/* O - Value or NULL */
httpGetSubField2(http_t * http,http_field_t field,const char * name,char * value,int valuelen)887 httpGetSubField2(http_t       *http,	/* I - Connection to server */
888                  http_field_t field,	/* I - Field index */
889                  const char   *name,	/* I - Name of sub-field */
890 		 char         *value,	/* O - Value string */
891 		 int          valuelen)	/* I - Size of value buffer */
892 {
893   const char	*fptr;			/* Pointer into field */
894   char		temp[HTTP_MAX_VALUE],	/* Temporary buffer for name */
895 		*ptr,			/* Pointer into string buffer */
896 		*end;			/* End of value buffer */
897 
898   DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, "
899                 "valuelen=%d)", http, field, name, value, valuelen));
900 
901   if (!http || !name || !value || valuelen < 2 ||
902       field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
903     return (NULL);
904 
905   end = value + valuelen - 1;
906 
907   for (fptr = http->fields[field]; *fptr;)
908   {
909    /*
910     * Skip leading whitespace...
911     */
912 
913     while (_cups_isspace(*fptr))
914       fptr ++;
915 
916     if (*fptr == ',')
917     {
918       fptr ++;
919       continue;
920     }
921 
922    /*
923     * Get the sub-field name...
924     */
925 
926     for (ptr = temp;
927          *fptr && *fptr != '=' && !_cups_isspace(*fptr) &&
928 	     ptr < (temp + sizeof(temp) - 1);
929          *ptr++ = *fptr++);
930 
931     *ptr = '\0';
932 
933     DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp));
934 
935    /*
936     * Skip trailing chars up to the '='...
937     */
938 
939     while (_cups_isspace(*fptr))
940       fptr ++;
941 
942     if (!*fptr)
943       break;
944 
945     if (*fptr != '=')
946       continue;
947 
948    /*
949     * Skip = and leading whitespace...
950     */
951 
952     fptr ++;
953 
954     while (_cups_isspace(*fptr))
955       fptr ++;
956 
957     if (*fptr == '\"')
958     {
959      /*
960       * Read quoted string...
961       */
962 
963       for (ptr = value, fptr ++;
964            *fptr && *fptr != '\"' && ptr < end;
965 	   *ptr++ = *fptr++);
966 
967       *ptr = '\0';
968 
969       while (*fptr && *fptr != '\"')
970         fptr ++;
971 
972       if (*fptr)
973         fptr ++;
974     }
975     else
976     {
977      /*
978       * Read unquoted string...
979       */
980 
981       for (ptr = value;
982            *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end;
983 	   *ptr++ = *fptr++);
984 
985       *ptr = '\0';
986 
987       while (*fptr && !_cups_isspace(*fptr) && *fptr != ',')
988         fptr ++;
989     }
990 
991     DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value));
992 
993    /*
994     * See if this is the one...
995     */
996 
997     if (!strcmp(name, temp))
998     {
999       DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value));
1000       return (value);
1001     }
1002   }
1003 
1004   value[0] = '\0';
1005 
1006   DEBUG_puts("3httpGetSubField2: Returning NULL");
1007 
1008   return (NULL);
1009 }
1010 
1011 
1012 /*
1013  * 'httpGets()' - Get a line of text from a HTTP connection.
1014  */
1015 
1016 char *					/* O - Line or NULL */
httpGets(char * line,int length,http_t * http)1017 httpGets(char   *line,			/* I - Line to read into */
1018          int    length,			/* I - Max length of buffer */
1019 	 http_t *http)			/* I - Connection to server */
1020 {
1021   char	*lineptr,			/* Pointer into line */
1022 	*lineend,			/* End of line */
1023 	*bufptr,			/* Pointer into input buffer */
1024 	*bufend;			/* Pointer to end of buffer */
1025   int	bytes,				/* Number of bytes read */
1026 	eol;				/* End-of-line? */
1027 
1028 
1029   DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", line, length, http));
1030 
1031   if (http == NULL || line == NULL)
1032     return (NULL);
1033 
1034  /*
1035   * Read a line from the buffer...
1036   */
1037 
1038   http->error = 0;
1039   lineptr     = line;
1040   lineend     = line + length - 1;
1041   eol         = 0;
1042 
1043   while (lineptr < lineend)
1044   {
1045    /*
1046     * Pre-load the buffer as needed...
1047     */
1048 
1049 #ifdef WIN32
1050     WSASetLastError(0);
1051 #else
1052     errno = 0;
1053 #endif /* WIN32 */
1054 
1055     while (http->used == 0)
1056     {
1057      /*
1058       * No newline; see if there is more data to be read...
1059       */
1060 
1061       if (!http->blocking && !_httpWait(http, 10000, 1))
1062       {
1063         DEBUG_puts("3httpGets: Timed out!");
1064 #ifdef WIN32
1065         http->error = WSAETIMEDOUT;
1066 #else
1067         http->error = ETIMEDOUT;
1068 #endif /* WIN32 */
1069         return (NULL);
1070       }
1071 
1072 #ifdef HAVE_SSL
1073       if (http->tls)
1074 	bytes = http_read_ssl(http, http->buffer + http->used,
1075 	                      HTTP_MAX_BUFFER - http->used);
1076       else
1077 #endif /* HAVE_SSL */
1078         bytes = recv(http->fd, http->buffer + http->used,
1079 	             HTTP_MAX_BUFFER - http->used, 0);
1080 
1081       DEBUG_printf(("4httpGets: read %d bytes...", bytes));
1082 
1083       if (bytes < 0)
1084       {
1085        /*
1086 	* Nope, can't get a line this time...
1087 	*/
1088 
1089 #ifdef WIN32
1090         if (WSAGetLastError() != http->error)
1091 	{
1092 	  http->error = WSAGetLastError();
1093 	  continue;
1094 	}
1095 
1096         DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError()));
1097 #else
1098         DEBUG_printf(("3httpGets: recv() error %d!", errno));
1099 
1100         if (errno == EINTR || errno == EAGAIN)
1101 	  continue;
1102 	else if (errno != http->error)
1103 	{
1104 	  http->error = errno;
1105 	  continue;
1106 	}
1107 #endif /* WIN32 */
1108 
1109         return (NULL);
1110       }
1111       else if (bytes == 0)
1112       {
1113 	http->error = EPIPE;
1114 
1115         return (NULL);
1116       }
1117 
1118      /*
1119       * Yup, update the amount used...
1120       */
1121 
1122       http->used += bytes;
1123     }
1124 
1125    /*
1126     * Now copy as much of the current line as possible...
1127     */
1128 
1129     for (bufptr = http->buffer, bufend = http->buffer + http->used;
1130          lineptr < lineend && bufptr < bufend;)
1131     {
1132       if (*bufptr == 0x0a)
1133       {
1134         eol = 1;
1135 	bufptr ++;
1136 	break;
1137       }
1138       else if (*bufptr == 0x0d)
1139 	bufptr ++;
1140       else
1141 	*lineptr++ = *bufptr++;
1142     }
1143 
1144     http->used -= (int)(bufptr - http->buffer);
1145     if (http->used > 0)
1146       memmove(http->buffer, bufptr, http->used);
1147 
1148     if (eol)
1149     {
1150      /*
1151       * End of line...
1152       */
1153 
1154       http->activity = time(NULL);
1155 
1156       *lineptr = '\0';
1157 
1158       DEBUG_printf(("3httpGets: Returning \"%s\"", line));
1159 
1160       return (line);
1161     }
1162   }
1163 
1164   DEBUG_puts("3httpGets: No new line available!");
1165 
1166   return (NULL);
1167 }
1168 
1169 
1170 /*
1171  * 'httpHead()' - Send a HEAD request to the server.
1172  */
1173 
1174 int					/* O - Status of call (0 = success) */
httpHead(http_t * http,const char * uri)1175 httpHead(http_t     *http,		/* I - Connection to server */
1176          const char *uri)		/* I - URI for head */
1177 {
1178   DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", http, uri));
1179   return (http_send(http, HTTP_HEAD, uri));
1180 }
1181 
1182 
1183 /*
1184  * 'httpInitialize()' - Initialize the HTTP interface library and set the
1185  *                      default HTTP proxy (if any).
1186  */
1187 
1188 void
httpInitialize(void)1189 httpInitialize(void)
1190 {
1191   static int	initialized = 0;	/* Have we been called before? */
1192 #ifdef WIN32
1193   WSADATA	winsockdata;		/* WinSock data */
1194 #endif /* WIN32 */
1195 #ifdef HAVE_LIBSSL
1196   int		i;			/* Looping var */
1197   unsigned char	data[1024];		/* Seed data */
1198 #endif /* HAVE_LIBSSL */
1199 
1200 
1201   if (initialized)
1202     return;
1203 
1204 #ifdef WIN32
1205   WSAStartup(MAKEWORD(2,2), &winsockdata);
1206 
1207 #elif !defined(SO_NOSIGPIPE)
1208  /*
1209   * Ignore SIGPIPE signals...
1210   */
1211 
1212 #  ifdef HAVE_SIGSET
1213   sigset(SIGPIPE, SIG_IGN);
1214 
1215 #  elif defined(HAVE_SIGACTION)
1216   struct sigaction	action;		/* POSIX sigaction data */
1217 
1218 
1219   memset(&action, 0, sizeof(action));
1220   action.sa_handler = SIG_IGN;
1221   sigaction(SIGPIPE, &action, NULL);
1222 
1223 #  else
1224   signal(SIGPIPE, SIG_IGN);
1225 #  endif /* !SO_NOSIGPIPE */
1226 #endif /* WIN32 */
1227 
1228 #ifdef HAVE_GNUTLS
1229  /*
1230   * Make sure we handle threading properly...
1231   */
1232 
1233 #  ifdef HAVE_PTHREAD_H
1234   gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
1235 #  endif /* HAVE_PTHREAD_H */
1236 
1237  /*
1238   * Initialize GNU TLS...
1239   */
1240 
1241   gnutls_global_init();
1242 
1243 #elif defined(HAVE_LIBSSL)
1244  /*
1245   * Initialize OpenSSL...
1246   */
1247 
1248   SSL_load_error_strings();
1249   SSL_library_init();
1250 
1251  /*
1252   * Set the threading callbacks...
1253   */
1254 
1255 #  ifdef HAVE_PTHREAD_H
1256   http_locks = calloc(CRYPTO_num_locks(), sizeof(pthread_mutex_t));
1257 
1258   for (i = 0; i < CRYPTO_num_locks(); i ++)
1259     pthread_mutex_init(http_locks + i, NULL);
1260 
1261   CRYPTO_set_id_callback(http_threadid_cb);
1262   CRYPTO_set_locking_callback(http_locking_cb);
1263 #  endif /* HAVE_PTHREAD_H */
1264 
1265  /*
1266   * Using the current time is a dubious random seed, but on some systems
1267   * it is the best we can do (on others, this seed isn't even used...)
1268   */
1269 
1270   CUPS_SRAND(time(NULL));
1271 
1272   for (i = 0; i < sizeof(data); i ++)
1273     data[i] = CUPS_RAND();
1274 
1275   RAND_seed(data, sizeof(data));
1276 #endif /* HAVE_GNUTLS */
1277 
1278   initialized = 1;
1279 }
1280 
1281 
1282 /*
1283  * 'httpOptions()' - Send an OPTIONS request to the server.
1284  */
1285 
1286 int					/* O - Status of call (0 = success) */
httpOptions(http_t * http,const char * uri)1287 httpOptions(http_t     *http,		/* I - Connection to server */
1288             const char *uri)		/* I - URI for options */
1289 {
1290   return (http_send(http, HTTP_OPTIONS, uri));
1291 }
1292 
1293 
1294 /*
1295  * 'httpPost()' - Send a POST request to the server.
1296  */
1297 
1298 int					/* O - Status of call (0 = success) */
httpPost(http_t * http,const char * uri)1299 httpPost(http_t     *http,		/* I - Connection to server */
1300          const char *uri)		/* I - URI for post */
1301 {
1302   return (http_send(http, HTTP_POST, uri));
1303 }
1304 
1305 
1306 /*
1307  * 'httpPrintf()' - Print a formatted string to a HTTP connection.
1308  *
1309  * @private@
1310  */
1311 
1312 int					/* O - Number of bytes written */
httpPrintf(http_t * http,const char * format,...)1313 httpPrintf(http_t     *http,		/* I - Connection to server */
1314            const char *format,		/* I - printf-style format string */
1315 	   ...)				/* I - Additional args as needed */
1316 {
1317   int		bytes;			/* Number of bytes to write */
1318   char		buf[16384];		/* Buffer for formatted string */
1319   va_list	ap;			/* Variable argument pointer */
1320 
1321 
1322   DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", http, format));
1323 
1324   va_start(ap, format);
1325   bytes = vsnprintf(buf, sizeof(buf), format, ap);
1326   va_end(ap);
1327 
1328   DEBUG_printf(("3httpPrintf: %s", buf));
1329 
1330   if (http->data_encoding == HTTP_ENCODE_FIELDS)
1331     return (httpWrite2(http, buf, bytes));
1332   else
1333   {
1334     if (http->wused)
1335     {
1336       DEBUG_puts("4httpPrintf: flushing existing data...");
1337 
1338       if (httpFlushWrite(http) < 0)
1339 	return (-1);
1340     }
1341 
1342     return (http_write(http, buf, bytes));
1343   }
1344 }
1345 
1346 
1347 /*
1348  * 'httpPut()' - Send a PUT request to the server.
1349  */
1350 
1351 int					/* O - Status of call (0 = success) */
httpPut(http_t * http,const char * uri)1352 httpPut(http_t     *http,		/* I - Connection to server */
1353         const char *uri)		/* I - URI to put */
1354 {
1355   DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", http, uri));
1356   return (http_send(http, HTTP_PUT, uri));
1357 }
1358 
1359 
1360 /*
1361  * 'httpRead()' - Read data from a HTTP connection.
1362  *
1363  * This function is deprecated. Use the httpRead2() function which can
1364  * read more than 2GB of data.
1365  *
1366  * @deprecated@
1367  */
1368 
1369 int					/* O - Number of bytes read */
httpRead(http_t * http,char * buffer,int length)1370 httpRead(http_t *http,			/* I - Connection to server */
1371          char   *buffer,		/* I - Buffer for data */
1372 	 int    length)			/* I - Maximum number of bytes */
1373 {
1374   return ((int)httpRead2(http, buffer, length));
1375 }
1376 
1377 
1378 /*
1379  * 'httpRead2()' - Read data from a HTTP connection.
1380  *
1381  * @since CUPS 1.2/Mac OS X 10.5@
1382  */
1383 
1384 ssize_t					/* O - Number of bytes read */
httpRead2(http_t * http,char * buffer,size_t length)1385 httpRead2(http_t *http,			/* I - Connection to server */
1386           char   *buffer,		/* I - Buffer for data */
1387 	  size_t length)		/* I - Maximum number of bytes */
1388 {
1389   ssize_t	bytes;			/* Bytes read */
1390   char		len[32];		/* Length string */
1391 
1392 
1393   DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
1394                 http, buffer, CUPS_LLCAST length));
1395 
1396   if (http == NULL || buffer == NULL)
1397     return (-1);
1398 
1399   http->activity = time(NULL);
1400   http->error    = 0;
1401 
1402   if (length <= 0)
1403     return (0);
1404 
1405   if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1406       http->data_remaining <= 0)
1407   {
1408     DEBUG_puts("2httpRead2: Getting chunk length...");
1409 
1410     if (httpGets(len, sizeof(len), http) == NULL)
1411     {
1412       DEBUG_puts("1httpRead2: Could not get length!");
1413       return (0);
1414     }
1415 
1416     http->data_remaining = strtoll(len, NULL, 16);
1417     if (http->data_remaining < 0)
1418     {
1419       DEBUG_puts("1httpRead2: Negative chunk length!");
1420       return (0);
1421     }
1422   }
1423 
1424   DEBUG_printf(("2httpRead2: data_remaining=" CUPS_LLFMT,
1425                 CUPS_LLCAST http->data_remaining));
1426 
1427   if (http->data_remaining <= 0)
1428   {
1429    /*
1430     * A zero-length chunk ends a transfer; unless we are reading POST
1431     * data, go idle...
1432     */
1433 
1434     if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1435       httpGets(len, sizeof(len), http);
1436 
1437     if (http->state == HTTP_POST_RECV)
1438       http->state ++;
1439     else
1440       http->state = HTTP_WAITING;
1441 
1442    /*
1443     * Prevent future reads for this request...
1444     */
1445 
1446     http->data_encoding = HTTP_ENCODE_LENGTH;
1447 
1448     return (0);
1449   }
1450   else if (length > (size_t)http->data_remaining)
1451     length = (size_t)http->data_remaining;
1452 
1453   if (http->used == 0 && length <= 256)
1454   {
1455    /*
1456     * Buffer small reads for better performance...
1457     */
1458 
1459     if (!http->blocking && !httpWait(http, 10000))
1460       return (0);
1461 
1462     if (http->data_remaining > sizeof(http->buffer))
1463       bytes = sizeof(http->buffer);
1464     else
1465       bytes = http->data_remaining;
1466 
1467 #ifdef HAVE_SSL
1468     if (http->tls)
1469       bytes = http_read_ssl(http, http->buffer, bytes);
1470     else
1471 #endif /* HAVE_SSL */
1472     {
1473       DEBUG_printf(("2httpRead2: reading %d bytes from socket into buffer...",
1474                     (int)bytes));
1475 
1476       bytes = recv(http->fd, http->buffer, bytes, 0);
1477 
1478       DEBUG_printf(("2httpRead2: read %d bytes from socket into buffer...",
1479                     (int)bytes));
1480     }
1481 
1482     if (bytes > 0)
1483       http->used = bytes;
1484     else if (bytes < 0)
1485     {
1486 #ifdef WIN32
1487       http->error = WSAGetLastError();
1488       return (-1);
1489 #else
1490       if (errno != EINTR && errno != EAGAIN)
1491       {
1492         http->error = errno;
1493         return (-1);
1494       }
1495 #endif /* WIN32 */
1496     }
1497     else
1498     {
1499       http->error = EPIPE;
1500       return (0);
1501     }
1502   }
1503 
1504   if (http->used > 0)
1505   {
1506     if (length > (size_t)http->used)
1507       length = (size_t)http->used;
1508 
1509     bytes = (ssize_t)length;
1510 
1511     DEBUG_printf(("2httpRead2: grabbing %d bytes from input buffer...",
1512                   (int)bytes));
1513 
1514     memcpy(buffer, http->buffer, length);
1515     http->used -= (int)length;
1516 
1517     if (http->used > 0)
1518       memmove(http->buffer, http->buffer + length, http->used);
1519   }
1520 #ifdef HAVE_SSL
1521   else if (http->tls)
1522   {
1523     if (!http->blocking && !httpWait(http, 10000))
1524       return (0);
1525 
1526     bytes = (ssize_t)http_read_ssl(http, buffer, (int)length);
1527   }
1528 #endif /* HAVE_SSL */
1529   else
1530   {
1531     if (!http->blocking && !httpWait(http, 10000))
1532       return (0);
1533 
1534     DEBUG_printf(("2httpRead2: reading " CUPS_LLFMT " bytes from socket...",
1535                   CUPS_LLCAST length));
1536 
1537 #ifdef WIN32
1538     bytes = (ssize_t)recv(http->fd, buffer, (int)length, 0);
1539 #else
1540     while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
1541       if (errno != EINTR && errno != EAGAIN)
1542         break;
1543 #endif /* WIN32 */
1544 
1545     DEBUG_printf(("2httpRead2: read " CUPS_LLFMT " bytes from socket...",
1546                   CUPS_LLCAST bytes));
1547   }
1548 
1549   if (bytes > 0)
1550   {
1551     http->data_remaining -= bytes;
1552 
1553     if (http->data_remaining <= INT_MAX)
1554       http->_data_remaining = (int)http->data_remaining;
1555     else
1556       http->_data_remaining = INT_MAX;
1557   }
1558   else if (bytes < 0)
1559   {
1560 #ifdef WIN32
1561     http->error = WSAGetLastError();
1562 #else
1563     if (errno == EINTR || errno == EAGAIN)
1564       bytes = 0;
1565     else
1566       http->error = errno;
1567 #endif /* WIN32 */
1568   }
1569   else
1570   {
1571     http->error = EPIPE;
1572     return (0);
1573   }
1574 
1575   if (http->data_remaining == 0)
1576   {
1577     if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1578       httpGets(len, sizeof(len), http);
1579 
1580     if (http->data_encoding != HTTP_ENCODE_CHUNKED)
1581     {
1582       if (http->state == HTTP_POST_RECV)
1583 	http->state ++;
1584       else
1585 	http->state = HTTP_WAITING;
1586     }
1587   }
1588 
1589 #ifdef DEBUG
1590   http_debug_hex("httpRead2", buffer, (int)bytes);
1591 #endif /* DEBUG */
1592 
1593   return (bytes);
1594 }
1595 
1596 
1597 #if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
1598 /*
1599  * '_httpReadCDSA()' - Read function for the CDSA library.
1600  */
1601 
1602 OSStatus				/* O  - -1 on error, 0 on success */
_httpReadCDSA(SSLConnectionRef connection,void * data,size_t * dataLength)1603 _httpReadCDSA(
1604     SSLConnectionRef connection,	/* I  - SSL/TLS connection */
1605     void             *data,		/* I  - Data buffer */
1606     size_t           *dataLength)	/* IO - Number of bytes */
1607 {
1608   OSStatus	result;			/* Return value */
1609   ssize_t	bytes;			/* Number of bytes read */
1610   http_t	*http;			/* HTTP connection */
1611 
1612 
1613   http = (http_t *)connection;
1614 
1615   if (!http->blocking)
1616   {
1617    /*
1618     * Make sure we have data before we read...
1619     */
1620 
1621     if (!_httpWait(http, 10000, 0))
1622     {
1623       http->error = ETIMEDOUT;
1624       return (-1);
1625     }
1626   }
1627 
1628   do
1629   {
1630     bytes = recv(http->fd, data, *dataLength, 0);
1631   }
1632   while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
1633 
1634   if (bytes == *dataLength)
1635   {
1636     result = 0;
1637   }
1638   else if (bytes > 0)
1639   {
1640     *dataLength = bytes;
1641     result = errSSLWouldBlock;
1642   }
1643   else
1644   {
1645     *dataLength = 0;
1646 
1647     if (bytes == 0)
1648       result = errSSLClosedGraceful;
1649     else if (errno == EAGAIN)
1650       result = errSSLWouldBlock;
1651     else
1652       result = errSSLClosedAbort;
1653   }
1654 
1655   return (result);
1656 }
1657 #endif /* HAVE_SSL && HAVE_CDSASSL */
1658 
1659 
1660 #if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
1661 /*
1662  * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
1663  */
1664 
1665 ssize_t					/* O - Number of bytes read or -1 on error */
_httpReadGNUTLS(gnutls_transport_ptr ptr,void * data,size_t length)1666 _httpReadGNUTLS(
1667     gnutls_transport_ptr ptr,		/* I - Connection to server */
1668     void                 *data,		/* I - Buffer */
1669     size_t               length)	/* I - Number of bytes to read */
1670 {
1671   http_t	*http;			/* HTTP connection */
1672 
1673 
1674   http = (http_t *)ptr;
1675 
1676   if (!http->blocking)
1677   {
1678    /*
1679     * Make sure we have data before we read...
1680     */
1681 
1682     if (!_httpWait(http, 10000, 0))
1683     {
1684       http->error = ETIMEDOUT;
1685       return (-1);
1686     }
1687   }
1688 
1689   return (recv(http->fd, data, length, 0));
1690 }
1691 #endif /* HAVE_SSL && HAVE_GNUTLS */
1692 
1693 
1694 /*
1695  * 'httpReconnect()' - Reconnect to a HTTP server.
1696  */
1697 
1698 int					/* O - 0 on success, non-zero on failure */
httpReconnect(http_t * http)1699 httpReconnect(http_t *http)		/* I - Connection to server */
1700 {
1701   http_addrlist_t	*addr;		/* Connected address */
1702 #ifdef DEBUG
1703   http_addrlist_t	*current;	/* Current address */
1704   char			temp[256];	/* Temporary address string */
1705 #endif /* DEBUG */
1706 
1707 
1708   DEBUG_printf(("httpReconnect(http=%p)", http));
1709 
1710   if (!http)
1711     return (-1);
1712 
1713 #ifdef HAVE_SSL
1714   if (http->tls)
1715   {
1716     DEBUG_puts("2httpReconnect: Shutting down SSL/TLS...");
1717     http_shutdown_ssl(http);
1718   }
1719 #endif /* HAVE_SSL */
1720 
1721  /*
1722   * Close any previously open socket...
1723   */
1724 
1725   if (http->fd >= 0)
1726   {
1727     DEBUG_printf(("2httpReconnect: Closing socket %d...", http->fd));
1728 
1729 #ifdef WIN32
1730     closesocket(http->fd);
1731 #else
1732     close(http->fd);
1733 #endif /* WIN32 */
1734 
1735     http->fd = -1;
1736   }
1737 
1738  /*
1739   * Connect to the server...
1740   */
1741 
1742 #ifdef DEBUG
1743   for (current = http->addrlist; current; current = current->next)
1744     DEBUG_printf(("2httpReconnect: Address %s:%d",
1745                   httpAddrString(&(current->addr), temp, sizeof(temp)),
1746                   _httpAddrPort(&(current->addr))));
1747 #endif /* DEBUG */
1748 
1749   if ((addr = httpAddrConnect(http->addrlist, &(http->fd))) == NULL)
1750   {
1751    /*
1752     * Unable to connect...
1753     */
1754 
1755 #ifdef WIN32
1756     http->error  = WSAGetLastError();
1757 #else
1758     http->error  = errno;
1759 #endif /* WIN32 */
1760     http->status = HTTP_ERROR;
1761 
1762     DEBUG_printf(("1httpReconnect: httpAddrConnect failed: %s",
1763                   strerror(http->error)));
1764 
1765     return (-1);
1766   }
1767 
1768   DEBUG_printf(("2httpReconnect: New socket=%d", http->fd));
1769 
1770   http->hostaddr = &(addr->addr);
1771   http->error    = 0;
1772   http->status   = HTTP_CONTINUE;
1773 
1774 #ifdef HAVE_SSL
1775   if (http->encryption == HTTP_ENCRYPT_ALWAYS)
1776   {
1777    /*
1778     * Always do encryption via SSL.
1779     */
1780 
1781     if (http_setup_ssl(http) != 0)
1782     {
1783 #  ifdef WIN32
1784       closesocket(http->fd);
1785 #  else
1786       close(http->fd);
1787 #  endif /* WIN32 */
1788 
1789       return (-1);
1790     }
1791   }
1792   else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
1793     return (http_upgrade(http));
1794 #endif /* HAVE_SSL */
1795 
1796   DEBUG_printf(("1httpReconnect: Connected to %s:%d...",
1797 		httpAddrString(http->hostaddr, temp, sizeof(temp)),
1798 		_httpAddrPort(http->hostaddr)));
1799 
1800   return (0);
1801 }
1802 
1803 
1804 /*
1805  * 'httpSetAuthString()' - Set the current authorization string.
1806  *
1807  * This function just stores a copy of the current authorization string in
1808  * the HTTP connection object.  You must still call httpSetField() to set
1809  * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
1810  * httpHead(), httpOptions(), httpPost, or httpPut().
1811  *
1812  * @since CUPS 1.3/Mac OS X 10.5@
1813  */
1814 
1815 void
httpSetAuthString(http_t * http,const char * scheme,const char * data)1816 httpSetAuthString(http_t     *http,	/* I - Connection to server */
1817                   const char *scheme,	/* I - Auth scheme (NULL to clear it) */
1818 		  const char *data)	/* I - Auth data (NULL for none) */
1819 {
1820  /*
1821   * Range check input...
1822   */
1823 
1824   if (!http)
1825     return;
1826 
1827   if (http->authstring && http->authstring != http->_authstring)
1828     free(http->authstring);
1829 
1830   http->authstring = http->_authstring;
1831 
1832   if (scheme)
1833   {
1834    /*
1835     * Set the current authorization string...
1836     */
1837 
1838     int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1;
1839     char *temp;
1840 
1841     if (len > (int)sizeof(http->_authstring))
1842     {
1843       if ((temp = malloc(len)) == NULL)
1844         len = sizeof(http->_authstring);
1845       else
1846         http->authstring = temp;
1847     }
1848 
1849     if (data)
1850       snprintf(http->authstring, len, "%s %s", scheme, data);
1851     else
1852       strlcpy(http->authstring, scheme, len);
1853   }
1854   else
1855   {
1856    /*
1857     * Clear the current authorization string...
1858     */
1859 
1860     http->_authstring[0] = '\0';
1861   }
1862 }
1863 
1864 
1865 /*
1866  * 'httpSetCookie()' - Set the cookie value(s).
1867  *
1868  * @since CUPS 1.1.19/Mac OS X 10.3@
1869  */
1870 
1871 void
httpSetCookie(http_t * http,const char * cookie)1872 httpSetCookie(http_t     *http,		/* I - Connection */
1873               const char *cookie)	/* I - Cookie string */
1874 {
1875   if (!http)
1876     return;
1877 
1878   if (http->cookie)
1879     free(http->cookie);
1880 
1881   if (cookie)
1882     http->cookie = strdup(cookie);
1883   else
1884     http->cookie = NULL;
1885 }
1886 
1887 
1888 /*
1889  * 'httpSetExpect()' - Set the Expect: header in a request.
1890  *
1891  * Currently only HTTP_CONTINUE is supported for the "expect" argument.
1892  *
1893  * @since CUPS 1.2/Mac OS X 10.5@
1894  */
1895 
1896 void
httpSetExpect(http_t * http,http_status_t expect)1897 httpSetExpect(http_t        *http,	/* I - Connection to server */
1898               http_status_t expect)	/* I - HTTP status to expect (HTTP_CONTINUE) */
1899 {
1900   if (http)
1901     http->expect = expect;
1902 }
1903 
1904 
1905 /*
1906  * 'httpSetField()' - Set the value of an HTTP header.
1907  */
1908 
1909 void
httpSetField(http_t * http,http_field_t field,const char * value)1910 httpSetField(http_t       *http,	/* I - Connection to server */
1911              http_field_t field,	/* I - Field index */
1912 	     const char   *value)	/* I - Value */
1913 {
1914   if (http == NULL ||
1915       field < HTTP_FIELD_ACCEPT_LANGUAGE ||
1916       field > HTTP_FIELD_WWW_AUTHENTICATE ||
1917       value == NULL)
1918     return;
1919 
1920   strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
1921 
1922   if (field == HTTP_FIELD_AUTHORIZATION)
1923   {
1924    /*
1925     * Special case for Authorization: as its contents can be
1926     * longer than HTTP_MAX_VALUE
1927     */
1928 
1929     if (http->field_authorization)
1930       free(http->field_authorization);
1931 
1932     http->field_authorization = strdup(value);
1933   }
1934   else if (field == HTTP_FIELD_HOST)
1935   {
1936    /*
1937     * Special-case for Host: as we don't want a trailing "." on the hostname and
1938     * need to bracket IPv6 numeric addresses.
1939     */
1940 
1941     char *ptr = strchr(value, ':');
1942 
1943     if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
1944     {
1945      /*
1946       * Bracket IPv6 numeric addresses...
1947       *
1948       * This is slightly inefficient (basically copying twice), but is an edge
1949       * case and not worth optimizing...
1950       */
1951 
1952       snprintf(http->fields[HTTP_FIELD_HOST],
1953                sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
1954     }
1955     else
1956     {
1957      /*
1958       * Check for a trailing dot on the hostname...
1959       */
1960 
1961       ptr = http->fields[HTTP_FIELD_HOST];
1962 
1963       if (*ptr)
1964       {
1965 	ptr += strlen(ptr) - 1;
1966 
1967 	if (*ptr == '.')
1968 	  *ptr = '\0';
1969       }
1970     }
1971   }
1972 }
1973 
1974 
1975 /*
1976  * 'httpSetLength()' - Set the content-length and content-encoding.
1977  *
1978  * @since CUPS 1.2/Mac OS X 10.5@
1979  */
1980 
1981 void
httpSetLength(http_t * http,size_t length)1982 httpSetLength(http_t *http,		/* I - Connection to server */
1983               size_t length)		/* I - Length (0 for chunked) */
1984 {
1985   if (!http)
1986     return;
1987 
1988   if (!length)
1989   {
1990     strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked");
1991     http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
1992   }
1993   else
1994   {
1995     http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
1996     snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
1997              CUPS_LLFMT, CUPS_LLCAST length);
1998   }
1999 }
2000 
2001 
2002 /*
2003  * 'httpTrace()' - Send an TRACE request to the server.
2004  */
2005 
2006 int					/* O - Status of call (0 = success) */
httpTrace(http_t * http,const char * uri)2007 httpTrace(http_t     *http,		/* I - Connection to server */
2008           const char *uri)		/* I - URI for trace */
2009 {
2010   return (http_send(http, HTTP_TRACE, uri));
2011 }
2012 
2013 
2014 /*
2015  * 'httpUpdate()' - Update the current HTTP state for incoming data.
2016  */
2017 
2018 http_status_t				/* O - HTTP status */
httpUpdate(http_t * http)2019 httpUpdate(http_t *http)		/* I - Connection to server */
2020 {
2021   char		line[32768],		/* Line from connection... */
2022 		*value;			/* Pointer to value on line */
2023   http_field_t	field;			/* Field index */
2024   int		major, minor,		/* HTTP version numbers */
2025 		status;			/* Request status */
2026 
2027 
2028   DEBUG_printf(("httpUpdate(http=%p), state=%s", http,
2029                 http_states[http->state]));
2030 
2031  /*
2032   * Flush pending data, if any...
2033   */
2034 
2035   if (http->wused)
2036   {
2037     DEBUG_puts("2httpUpdate: flushing buffer...");
2038 
2039     if (httpFlushWrite(http) < 0)
2040       return (HTTP_ERROR);
2041   }
2042 
2043  /*
2044   * If we haven't issued any commands, then there is nothing to "update"...
2045   */
2046 
2047   if (http->state == HTTP_WAITING)
2048     return (HTTP_CONTINUE);
2049 
2050  /*
2051   * Grab all of the lines we can from the connection...
2052   */
2053 
2054   while (httpGets(line, sizeof(line), http) != NULL)
2055   {
2056     DEBUG_printf(("2httpUpdate: Got \"%s\"", line));
2057 
2058     if (line[0] == '\0')
2059     {
2060      /*
2061       * Blank line means the start of the data section (if any).  Return
2062       * the result code, too...
2063       *
2064       * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
2065       * Instead, we just return HTTP_CONTINUE to the caller and keep on
2066       * tryin'...
2067       */
2068 
2069       if (http->status == HTTP_CONTINUE)
2070         return (http->status);
2071 
2072       if (http->status < HTTP_BAD_REQUEST)
2073         http->digest_tries = 0;
2074 
2075 #ifdef HAVE_SSL
2076       if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
2077       {
2078 	if (http_setup_ssl(http) != 0)
2079 	{
2080 #  ifdef WIN32
2081 	  closesocket(http->fd);
2082 #  else
2083 	  close(http->fd);
2084 #  endif /* WIN32 */
2085 
2086 	  return (HTTP_ERROR);
2087 	}
2088 
2089         return (HTTP_CONTINUE);
2090       }
2091 #endif /* HAVE_SSL */
2092 
2093       httpGetLength2(http);
2094 
2095       switch (http->state)
2096       {
2097         case HTTP_GET :
2098 	case HTTP_POST :
2099 	case HTTP_POST_RECV :
2100 	case HTTP_PUT :
2101 	    http->state ++;
2102 	case HTTP_POST_SEND :
2103 	case HTTP_HEAD :
2104 	    break;
2105 
2106 	default :
2107 	    http->state = HTTP_WAITING;
2108 	    break;
2109       }
2110 
2111       return (http->status);
2112     }
2113     else if (!strncmp(line, "HTTP/", 5))
2114     {
2115      /*
2116       * Got the beginning of a response...
2117       */
2118 
2119       if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
2120         return (HTTP_ERROR);
2121 
2122       http->version = (http_version_t)(major * 100 + minor);
2123       http->status  = (http_status_t)status;
2124     }
2125     else if ((value = strchr(line, ':')) != NULL)
2126     {
2127      /*
2128       * Got a value...
2129       */
2130 
2131       *value++ = '\0';
2132       while (_cups_isspace(*value))
2133         value ++;
2134 
2135      /*
2136       * Be tolerants of servers that send unknown attribute fields...
2137       */
2138 
2139       if (!strcasecmp(line, "expect"))
2140       {
2141        /*
2142         * "Expect: 100-continue" or similar...
2143 	*/
2144 
2145         http->expect = (http_status_t)atoi(value);
2146       }
2147       else if (!strcasecmp(line, "cookie"))
2148       {
2149        /*
2150         * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
2151 	*/
2152 
2153         httpSetCookie(http, value);
2154       }
2155       else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
2156       {
2157         DEBUG_printf(("1httpUpdate: unknown field %s seen!", line));
2158         continue;
2159       }
2160       else
2161         httpSetField(http, field, value);
2162     }
2163     else
2164     {
2165       DEBUG_printf(("1httpUpdate: Bad response line \"%s\"!", line));
2166       http->status = HTTP_ERROR;
2167       return (HTTP_ERROR);
2168     }
2169   }
2170 
2171  /*
2172   * See if there was an error...
2173   */
2174 
2175   if (http->error == EPIPE && http->status > HTTP_CONTINUE)
2176   {
2177     DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
2178     return (http->status);
2179   }
2180 
2181   if (http->error)
2182   {
2183     DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
2184                   strerror(http->error)));
2185     http->status = HTTP_ERROR;
2186     return (HTTP_ERROR);
2187   }
2188 
2189  /*
2190   * If we haven't already returned, then there is nothing new...
2191   */
2192 
2193   return (HTTP_CONTINUE);
2194 }
2195 
2196 
2197 /*
2198  * '_httpWait()' - Wait for data available on a connection (no flush).
2199  */
2200 
2201 int					/* O - 1 if data is available, 0 otherwise */
_httpWait(http_t * http,int msec,int usessl)2202 _httpWait(http_t *http,			/* I - Connection to server */
2203           int    msec,			/* I - Milliseconds to wait */
2204 	  int    usessl)		/* I - Use SSL context? */
2205 {
2206 #ifdef HAVE_POLL
2207   struct pollfd		pfd;		/* Polled file descriptor */
2208 #else
2209   fd_set		input_set;	/* select() input set */
2210   struct timeval	timeout;	/* Timeout */
2211 #endif /* HAVE_POLL */
2212   int			nfds;		/* Result from select()/poll() */
2213 
2214 
2215   DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
2216 
2217   if (http->fd < 0)
2218     return (0);
2219 
2220  /*
2221   * Check the SSL/TLS buffers for data first...
2222   */
2223 
2224 #ifdef HAVE_SSL
2225   if (http->tls && usessl)
2226   {
2227 #  ifdef HAVE_LIBSSL
2228     if (SSL_pending((SSL *)(http->tls)))
2229       return (1);
2230 #  elif defined(HAVE_GNUTLS)
2231     if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
2232       return (1);
2233 #  elif defined(HAVE_CDSASSL)
2234     size_t bytes;			/* Bytes that are available */
2235 
2236     if (!SSLGetBufferedReadSize(((http_tls_t *)(http->tls))->session, &bytes) &&
2237         bytes > 0)
2238       return (1);
2239 #  endif /* HAVE_LIBSSL */
2240   }
2241 #endif /* HAVE_SSL */
2242 
2243  /*
2244   * Then try doing a select() or poll() to poll the socket...
2245   */
2246 
2247 #ifdef HAVE_POLL
2248   pfd.fd     = http->fd;
2249   pfd.events = POLLIN;
2250 
2251   while ((nfds = poll(&pfd, 1, msec)) < 0 &&
2252          (errno == EINTR || errno == EAGAIN));
2253 
2254 #else
2255   do
2256   {
2257     FD_ZERO(&input_set);
2258     FD_SET(http->fd, &input_set);
2259 
2260     DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
2261 
2262     if (msec >= 0)
2263     {
2264       timeout.tv_sec  = msec / 1000;
2265       timeout.tv_usec = (msec % 1000) * 1000;
2266 
2267       nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
2268     }
2269     else
2270       nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
2271 
2272     DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
2273   }
2274 #  ifdef WIN32
2275   while (nfds < 0 && WSAGetLastError() == WSAEINTR);
2276 #  else
2277   while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
2278 #  endif /* WIN32 */
2279 #endif /* HAVE_POLL */
2280 
2281   DEBUG_printf(("5_httpWait: returning with nfds=%d...", nfds));
2282 
2283   return (nfds > 0);
2284 }
2285 
2286 
2287 /*
2288  * 'httpWait()' - Wait for data available on a connection.
2289  *
2290  * @since CUPS 1.1.19/Mac OS X 10.3@
2291  */
2292 
2293 int					/* O - 1 if data is available, 0 otherwise */
httpWait(http_t * http,int msec)2294 httpWait(http_t *http,			/* I - Connection to server */
2295          int    msec)			/* I - Milliseconds to wait */
2296 {
2297  /*
2298   * First see if there is data in the buffer...
2299   */
2300 
2301   if (http == NULL)
2302     return (0);
2303 
2304   if (http->used)
2305     return (1);
2306 
2307  /*
2308   * Flush pending data, if any...
2309   */
2310 
2311   if (http->wused)
2312   {
2313     if (httpFlushWrite(http) < 0)
2314       return (0);
2315   }
2316 
2317  /*
2318   * If not, check the SSL/TLS buffers and do a select() on the connection...
2319   */
2320 
2321   return (_httpWait(http, msec, 1));
2322 }
2323 
2324 
2325 /*
2326  * 'httpWrite()' - Write data to a HTTP connection.
2327  *
2328  * This function is deprecated. Use the httpWrite2() function which can
2329  * write more than 2GB of data.
2330  *
2331  * @deprecated@
2332  */
2333 
2334 int					/* O - Number of bytes written */
httpWrite(http_t * http,const char * buffer,int length)2335 httpWrite(http_t     *http,		/* I - Connection to server */
2336           const char *buffer,		/* I - Buffer for data */
2337 	  int        length)		/* I - Number of bytes to write */
2338 {
2339   return ((int)httpWrite2(http, buffer, length));
2340 }
2341 
2342 
2343 /*
2344  * 'httpWrite2()' - Write data to a HTTP connection.
2345  *
2346  * @since CUPS 1.2/Mac OS X 10.5@
2347  */
2348 
2349 ssize_t					/* O - Number of bytes written */
httpWrite2(http_t * http,const char * buffer,size_t length)2350 httpWrite2(http_t     *http,		/* I - Connection to server */
2351            const char *buffer,		/* I - Buffer for data */
2352 	   size_t     length)		/* I - Number of bytes to write */
2353 {
2354   ssize_t	bytes;			/* Bytes written */
2355 
2356 
2357   DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
2358                 buffer, CUPS_LLCAST length));
2359 
2360  /*
2361   * Range check input...
2362   */
2363 
2364   if (http == NULL || buffer == NULL)
2365     return (-1);
2366 
2367  /*
2368   * Mark activity on the connection...
2369   */
2370 
2371   http->activity = time(NULL);
2372 
2373  /*
2374   * Buffer small writes for better performance...
2375   */
2376 
2377   if (length > 0)
2378   {
2379     if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
2380     {
2381       DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
2382                     CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
2383 
2384       httpFlushWrite(http);
2385     }
2386 
2387     if ((length + http->wused) <= sizeof(http->wbuffer) &&
2388         length < sizeof(http->wbuffer))
2389     {
2390      /*
2391       * Write to buffer...
2392       */
2393 
2394       DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
2395                     CUPS_LLCAST length));
2396 
2397       memcpy(http->wbuffer + http->wused, buffer, length);
2398       http->wused += (int)length;
2399       bytes = (ssize_t)length;
2400     }
2401     else
2402     {
2403      /*
2404       * Otherwise write the data directly...
2405       */
2406 
2407       DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
2408                     CUPS_LLCAST length));
2409 
2410       if (http->data_encoding == HTTP_ENCODE_CHUNKED)
2411 	bytes = (ssize_t)http_write_chunk(http, buffer, (int)length);
2412       else
2413 	bytes = (ssize_t)http_write(http, buffer, (int)length);
2414 
2415       DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
2416                     CUPS_LLCAST bytes));
2417     }
2418 
2419     if (http->data_encoding == HTTP_ENCODE_LENGTH)
2420       http->data_remaining -= bytes;
2421   }
2422   else
2423     bytes = 0;
2424 
2425  /*
2426   * Handle end-of-request processing...
2427   */
2428 
2429   if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
2430       (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
2431   {
2432    /*
2433     * Finished with the transfer; unless we are sending POST or PUT
2434     * data, go idle...
2435     */
2436 
2437     DEBUG_puts("2httpWrite: changing states...");
2438 
2439     if (http->wused)
2440       httpFlushWrite(http);
2441 
2442     if (http->data_encoding == HTTP_ENCODE_CHUNKED)
2443     {
2444      /*
2445       * Send a 0-length chunk at the end of the request...
2446       */
2447 
2448       http_write(http, "0\r\n\r\n", 5);
2449 
2450      /*
2451       * Reset the data state...
2452       */
2453 
2454       http->data_encoding  = HTTP_ENCODE_LENGTH;
2455       http->data_remaining = 0;
2456     }
2457 
2458     if (http->state == HTTP_POST_RECV)
2459       http->state ++;
2460     else if (http->state == HTTP_PUT_RECV)
2461       http->state = HTTP_STATUS;
2462     else
2463       http->state = HTTP_WAITING;
2464   }
2465 
2466   return (bytes);
2467 }
2468 
2469 
2470 #if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
2471 /*
2472  * '_httpWriteCDSA()' - Write function for the CDSA library.
2473  */
2474 
2475 OSStatus				/* O  - -1 on error, 0 on success */
_httpWriteCDSA(SSLConnectionRef connection,const void * data,size_t * dataLength)2476 _httpWriteCDSA(
2477     SSLConnectionRef connection,	/* I  - SSL/TLS connection */
2478     const void       *data,		/* I  - Data buffer */
2479     size_t           *dataLength)	/* IO - Number of bytes */
2480 {
2481   OSStatus	result;			/* Return value */
2482   ssize_t	bytes;			/* Number of bytes read */
2483   http_t	*http;			/* HTTP connection */
2484 
2485 
2486   http = (http_t *)connection;
2487 
2488   do
2489   {
2490     bytes = write(http->fd, data, *dataLength);
2491   }
2492   while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
2493 
2494   if (bytes == *dataLength)
2495   {
2496     result = 0;
2497   }
2498   else if (bytes >= 0)
2499   {
2500     *dataLength = bytes;
2501     result = errSSLWouldBlock;
2502   }
2503   else
2504   {
2505     *dataLength = 0;
2506 
2507     if (errno == EAGAIN)
2508       result = errSSLWouldBlock;
2509     else
2510       result = errSSLClosedAbort;
2511   }
2512 
2513   return (result);
2514 }
2515 #endif /* HAVE_SSL && HAVE_CDSASSL */
2516 
2517 
2518 #if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
2519 /*
2520  * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
2521  */
2522 
2523 ssize_t					/* O - Number of bytes written or -1 on error */
_httpWriteGNUTLS(gnutls_transport_ptr ptr,const void * data,size_t length)2524 _httpWriteGNUTLS(
2525     gnutls_transport_ptr ptr,		/* I - Connection to server */
2526     const void           *data,		/* I - Data buffer */
2527     size_t               length)	/* I - Number of bytes to write */
2528 {
2529   return (send(((http_t *)ptr)->fd, data, length, 0));
2530 }
2531 #endif /* HAVE_SSL && HAVE_GNUTLS */
2532 
2533 
2534 #if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
2535 /*
2536  * 'http_bio_ctrl()' - Control the HTTP connection.
2537  */
2538 
2539 static long				/* O - Result/data */
http_bio_ctrl(BIO * h,int cmd,long arg1,void * arg2)2540 http_bio_ctrl(BIO  *h,			/* I - BIO data */
2541               int  cmd,			/* I - Control command */
2542 	      long arg1,		/* I - First argument */
2543 	      void *arg2)		/* I - Second argument */
2544 {
2545   switch (cmd)
2546   {
2547     default :
2548         return (0);
2549 
2550     case BIO_CTRL_RESET :
2551         h->ptr = NULL;
2552 	return (0);
2553 
2554     case BIO_C_SET_FILE_PTR :
2555         h->ptr  = arg2;
2556 	h->init = 1;
2557 	return (1);
2558 
2559     case BIO_C_GET_FILE_PTR :
2560         if (arg2)
2561 	{
2562 	  *((void **)arg2) = h->ptr;
2563 	  return (1);
2564 	}
2565 	else
2566 	  return (0);
2567 
2568     case BIO_CTRL_DUP :
2569     case BIO_CTRL_FLUSH :
2570         return (1);
2571   }
2572 }
2573 
2574 
2575 /*
2576  * 'http_bio_free()' - Free OpenSSL data.
2577  */
2578 
2579 static int				/* O - 1 on success, 0 on failure */
http_bio_free(BIO * h)2580 http_bio_free(BIO *h)			/* I - BIO data */
2581 {
2582   if (!h)
2583     return (0);
2584 
2585   if (h->shutdown)
2586   {
2587     h->init  = 0;
2588     h->flags = 0;
2589   }
2590 
2591   return (1);
2592 }
2593 
2594 
2595 /*
2596  * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
2597  */
2598 
2599 static int				/* O - 1 on success, 0 on failure */
http_bio_new(BIO * h)2600 http_bio_new(BIO *h)			/* I - BIO data */
2601 {
2602   if (!h)
2603     return (0);
2604 
2605   h->init  = 0;
2606   h->num   = 0;
2607   h->ptr   = NULL;
2608   h->flags = 0;
2609 
2610   return (1);
2611 }
2612 
2613 
2614 /*
2615  * 'http_bio_puts()' - Send a string for OpenSSL.
2616  */
2617 
2618 static int				/* O - Bytes written */
http_bio_puts(BIO * h,const char * str)2619 http_bio_puts(BIO        *h,		/* I - BIO data */
2620               const char *str)		/* I - String to write */
2621 {
2622 #ifdef WIN32
2623   return (send(((http_t *)h->ptr)->fd, str, (int)strlen(str), 0));
2624 #else
2625   return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
2626 #endif /* WIN32 */
2627 }
2628 
2629 
2630 /*
2631  * 'http_bio_read()' - Read data for OpenSSL.
2632  */
2633 
2634 static int				/* O - Bytes read */
http_bio_read(BIO * h,char * buf,int size)2635 http_bio_read(BIO  *h,			/* I - BIO data */
2636               char *buf,		/* I - Buffer */
2637 	      int  size)		/* I - Number of bytes to read */
2638 {
2639   http_t	*http;			/* HTTP connection */
2640 
2641 
2642   http = (http_t *)h->ptr;
2643 
2644   if (!http->blocking)
2645   {
2646    /*
2647     * Make sure we have data before we read...
2648     */
2649 
2650     if (!_httpWait(http, 10000, 0))
2651     {
2652 #ifdef WIN32
2653       http->error = WSAETIMEDOUT;
2654 #else
2655       http->error = ETIMEDOUT;
2656 #endif /* WIN32 */
2657 
2658       return (-1);
2659     }
2660   }
2661 
2662   return (recv(http->fd, buf, size, 0));
2663 }
2664 
2665 
2666 /*
2667  * 'http_bio_write()' - Write data for OpenSSL.
2668  */
2669 
2670 static int				/* O - Bytes written */
http_bio_write(BIO * h,const char * buf,int num)2671 http_bio_write(BIO        *h,		/* I - BIO data */
2672                const char *buf,		/* I - Buffer to write */
2673 	       int        num)		/* I - Number of bytes to write */
2674 {
2675   return (send(((http_t *)h->ptr)->fd, buf, num, 0));
2676 }
2677 #endif /* HAVE_SSL && HAVE_LIBSSL */
2678 
2679 
2680 #ifdef DEBUG
2681 /*
2682  * 'http_debug_hex()' - Do a hex dump of a buffer.
2683  */
2684 
2685 static void
http_debug_hex(const char * prefix,const char * buffer,int bytes)2686 http_debug_hex(const char *prefix,	/* I - Prefix for line */
2687                const char *buffer,	/* I - Buffer to dump */
2688                int        bytes)	/* I - Bytes to dump */
2689 {
2690   int	i, j,				/* Looping vars */
2691 	ch;				/* Current character */
2692   char	line[255],			/* Line buffer */
2693 	*start,				/* Start of line after prefix */
2694 	*ptr;				/* Pointer into line */
2695 
2696 
2697   if (_cups_debug_fd < 0 || _cups_debug_level < 6)
2698     return;
2699 
2700   DEBUG_printf(("6%s: %d bytes:\n", prefix, bytes));
2701 
2702   snprintf(line, sizeof(line), "6%s: ", prefix);
2703   start = line + strlen(line);
2704 
2705   for (i = 0; i < bytes; i += 16)
2706   {
2707     for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
2708       sprintf(ptr, "%02X", buffer[i + j] & 255);
2709 
2710     while (j < 16)
2711     {
2712       strcpy(ptr, "  ");
2713       ptr += 2;
2714       j ++;
2715     }
2716 
2717     strcpy(ptr, "  ");
2718     ptr += 2;
2719 
2720     for (j = 0; j < 16 && (i + j) < bytes; j ++)
2721     {
2722       ch = buffer[i + j] & 255;
2723 
2724       if (ch < ' ' || ch >= 127)
2725 	ch = '.';
2726 
2727       *ptr++ = ch;
2728     }
2729 
2730     *ptr = '\0';
2731     DEBUG_puts(line);
2732   }
2733 }
2734 #endif /* DEBUG */
2735 
2736 
2737 /*
2738  * 'http_field()' - Return the field index for a field name.
2739  */
2740 
2741 static http_field_t			/* O - Field index */
http_field(const char * name)2742 http_field(const char *name)		/* I - String name */
2743 {
2744   int	i;				/* Looping var */
2745 
2746 
2747   for (i = 0; i < HTTP_FIELD_MAX; i ++)
2748     if (strcasecmp(name, http_fields[i]) == 0)
2749       return ((http_field_t)i);
2750 
2751   return (HTTP_FIELD_UNKNOWN);
2752 }
2753 
2754 
2755 #ifdef HAVE_SSL
2756 /*
2757  * 'http_read_ssl()' - Read from a SSL/TLS connection.
2758  */
2759 
2760 static int				/* O - Bytes read */
http_read_ssl(http_t * http,char * buf,int len)2761 http_read_ssl(http_t *http,		/* I - Connection to server */
2762 	      char   *buf,		/* I - Buffer to store data */
2763 	      int    len)		/* I - Length of buffer */
2764 {
2765 #  if defined(HAVE_LIBSSL)
2766   return (SSL_read((SSL *)(http->tls), buf, len));
2767 
2768 #  elif defined(HAVE_GNUTLS)
2769   ssize_t	result;			/* Return value */
2770 
2771 
2772   result = gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len);
2773 
2774   if (result < 0 && !errno)
2775   {
2776    /*
2777     * Convert GNU TLS error to errno value...
2778     */
2779 
2780     switch (result)
2781     {
2782       case GNUTLS_E_INTERRUPTED :
2783 	  errno = EINTR;
2784 	  break;
2785 
2786       case GNUTLS_E_AGAIN :
2787           errno = EAGAIN;
2788           break;
2789 
2790       default :
2791           errno = EPIPE;
2792           break;
2793     }
2794 
2795     result = -1;
2796   }
2797 
2798   return ((int)result);
2799 
2800 #  elif defined(HAVE_CDSASSL)
2801   int		result;			/* Return value */
2802   OSStatus	error;			/* Error info */
2803   size_t	processed;		/* Number of bytes processed */
2804 
2805 
2806   error = SSLRead(((http_tls_t *)http->tls)->session, buf, len, &processed);
2807 
2808   switch (error)
2809   {
2810     case 0 :
2811 	result = (int)processed;
2812 	break;
2813     case errSSLClosedGraceful :
2814 	result = 0;
2815 	break;
2816     case errSSLWouldBlock :
2817 	if (processed)
2818 	  result = (int)processed;
2819 	else
2820 	{
2821 	  result = -1;
2822 	  errno = EINTR;
2823 	}
2824 	break;
2825     default :
2826 	errno = EPIPE;
2827 	result = -1;
2828 	break;
2829   }
2830 
2831   return (result);
2832 #  endif /* HAVE_LIBSSL */
2833 }
2834 #endif /* HAVE_SSL */
2835 
2836 
2837 #if defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD_H)
2838 /*
2839  * 'http_locking_cb()' - Lock/unlock a thread's mutex.
2840  */
2841 
2842 static void
http_locking_cb(int mode,int type,const char * file,int line)2843 http_locking_cb(int        mode,	/* I - Lock mode */
2844 		int        type,	/* I - Lock type */
2845 		const char *file,	/* I - Source file */
2846 		int        line)	/* I - Line number */
2847 {
2848   if (mode & CRYPTO_LOCK)
2849     pthread_mutex_lock(http_locks + type);
2850   else
2851     pthread_mutex_unlock(http_locks + type);
2852 }
2853 #endif /* HAVE_LIBSSL && HAVE_PTHREAD_H */
2854 
2855 
2856 /*
2857  * 'http_send()' - Send a request with all fields and the trailing blank line.
2858  */
2859 
2860 static int			/* O - 0 on success, non-zero on error */
http_send(http_t * http,http_state_t request,const char * uri)2861 http_send(http_t       *http,	/* I - Connection to server */
2862           http_state_t request,	/* I - Request code */
2863 	  const char   *uri)	/* I - URI */
2864 {
2865   int		i;		/* Looping var */
2866   char		buf[1024];	/* Encoded URI buffer */
2867   static const char * const codes[] =
2868 		{		/* Request code strings */
2869 		  NULL,
2870 		  "OPTIONS",
2871 		  "GET",
2872 		  NULL,
2873 		  "HEAD",
2874 		  "POST",
2875 		  NULL,
2876 		  NULL,
2877 		  "PUT",
2878 		  NULL,
2879 		  "DELETE",
2880 		  "TRACE",
2881 		  "CLOSE"
2882 		};
2883 
2884 
2885   DEBUG_printf(("7http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
2886                 http, codes[request], uri));
2887 
2888   if (http == NULL || uri == NULL)
2889     return (-1);
2890 
2891  /*
2892   * Set the User-Agent field if it isn't already...
2893   */
2894 
2895   if (!http->fields[HTTP_FIELD_USER_AGENT][0])
2896     httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
2897 
2898  /*
2899   * Encode the URI as needed...
2900   */
2901 
2902   _httpEncodeURI(buf, uri, sizeof(buf));
2903 
2904  /*
2905   * See if we had an error the last time around; if so, reconnect...
2906   */
2907 
2908   if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
2909     if (httpReconnect(http))
2910       return (-1);
2911 
2912  /*
2913   * Flush any written data that is pending...
2914   */
2915 
2916   if (http->wused)
2917   {
2918     if (httpFlushWrite(http) < 0)
2919       if (httpReconnect(http))
2920         return (-1);
2921   }
2922 
2923  /*
2924   * Send the request header...
2925   */
2926 
2927   http->state         = request;
2928   http->data_encoding = HTTP_ENCODE_FIELDS;
2929 
2930   if (request == HTTP_POST || request == HTTP_PUT)
2931     http->state ++;
2932 
2933   http->status = HTTP_CONTINUE;
2934 
2935 #ifdef HAVE_SSL
2936   if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
2937   {
2938     httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
2939     httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
2940   }
2941 #endif /* HAVE_SSL */
2942 
2943   if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
2944   {
2945     http->status = HTTP_ERROR;
2946     return (-1);
2947   }
2948 
2949   for (i = 0; i < HTTP_FIELD_MAX; i ++)
2950     if (http->fields[i][0] != '\0')
2951     {
2952       DEBUG_printf(("9http_send: %s: %s", http_fields[i],
2953                     httpGetField(http, i)));
2954 
2955       if (httpPrintf(http, "%s: %s\r\n", http_fields[i],
2956 		     httpGetField(http, i)) < 1)
2957       {
2958 	http->status = HTTP_ERROR;
2959 	return (-1);
2960       }
2961     }
2962 
2963   if (http->cookie)
2964     if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
2965     {
2966       http->status = HTTP_ERROR;
2967       return (-1);
2968     }
2969 
2970   if (http->expect == HTTP_CONTINUE &&
2971       (http->state == HTTP_POST_RECV || http->state == HTTP_PUT_RECV))
2972     if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
2973     {
2974       http->status = HTTP_ERROR;
2975       return (-1);
2976     }
2977 
2978   if (httpPrintf(http, "\r\n") < 1)
2979   {
2980     http->status = HTTP_ERROR;
2981     return (-1);
2982   }
2983 
2984   if (httpFlushWrite(http) < 0)
2985     return (-1);
2986 
2987   httpGetLength2(http);
2988   httpClearFields(http);
2989 
2990  /*
2991   * The Kerberos and AuthRef authentication strings can only be used once...
2992   */
2993 
2994   if (http->field_authorization && http->authstring &&
2995       (!strncmp(http->authstring, "Negotiate", 9) ||
2996        !strncmp(http->authstring, "AuthRef", 7)))
2997   {
2998     http->_authstring[0] = '\0';
2999 
3000     if (http->authstring != http->_authstring)
3001       free(http->authstring);
3002 
3003     http->authstring = http->_authstring;
3004   }
3005 
3006   return (0);
3007 }
3008 
3009 
3010 #ifdef HAVE_SSL
3011 /*
3012  * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
3013  */
3014 
3015 static int				/* O - Status of connection */
http_setup_ssl(http_t * http)3016 http_setup_ssl(http_t *http)		/* I - Connection to server */
3017 {
3018 #  ifdef HAVE_LIBSSL
3019   SSL_CTX	*context;		/* Context for encryption */
3020   SSL		*conn;			/* Connection for encryption */
3021   BIO		*bio;			/* BIO data */
3022 #  elif defined(HAVE_GNUTLS)
3023   http_tls_t	*conn;			/* TLS session object */
3024   gnutls_certificate_client_credentials *credentials;
3025 					/* TLS credentials */
3026 #  elif defined(HAVE_CDSASSL)
3027   OSStatus	error;			/* Error code */
3028   http_tls_t	*conn;			/* CDSA connection information */
3029 #  endif /* HAVE_LIBSSL */
3030 
3031 
3032   DEBUG_printf(("7http_setup_ssl(http=%p)", http));
3033 
3034 #  ifdef HAVE_LIBSSL
3035   context = SSL_CTX_new(SSLv23_client_method());
3036 
3037   SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
3038 
3039   bio = BIO_new(_httpBIOMethods());
3040   BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
3041 
3042   conn = SSL_new(context);
3043   SSL_set_bio(conn, bio, bio);
3044 
3045   if (SSL_connect(conn) != 1)
3046   {
3047 #    ifdef DEBUG
3048     unsigned long	error;	/* Error code */
3049 
3050     while ((error = ERR_get_error()) != 0)
3051       DEBUG_printf(("8http_setup_ssl: %s", ERR_error_string(error, NULL)));
3052 #    endif /* DEBUG */
3053 
3054     SSL_CTX_free(context);
3055     SSL_free(conn);
3056 
3057 #    ifdef WIN32
3058     http->error  = WSAGetLastError();
3059 #    else
3060     http->error  = errno;
3061 #    endif /* WIN32 */
3062     http->status = HTTP_ERROR;
3063 
3064     return (HTTP_ERROR);
3065   }
3066 
3067 #  elif defined(HAVE_GNUTLS)
3068   if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
3069   {
3070     http->error  = errno;
3071     http->status = HTTP_ERROR;
3072 
3073     return (-1);
3074   }
3075 
3076   credentials = (gnutls_certificate_client_credentials *)
3077                     malloc(sizeof(gnutls_certificate_client_credentials));
3078   if (credentials == NULL)
3079   {
3080     free(conn);
3081 
3082     http->error = errno;
3083     http->status = HTTP_ERROR;
3084 
3085     return (-1);
3086   }
3087 
3088   gnutls_certificate_allocate_credentials(credentials);
3089 
3090   gnutls_init(&(conn->session), GNUTLS_CLIENT);
3091   gnutls_set_default_priority(conn->session);
3092   gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
3093   gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr)http);
3094   gnutls_transport_set_pull_function(conn->session, _httpReadGNUTLS);
3095   gnutls_transport_set_push_function(conn->session, _httpWriteGNUTLS);
3096 
3097   if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
3098   {
3099     http->error  = errno;
3100     http->status = HTTP_ERROR;
3101 
3102     gnutls_deinit(conn->session);
3103     gnutls_certificate_free_credentials(*credentials);
3104     free(credentials);
3105     free(conn);
3106 
3107     return (-1);
3108   }
3109 
3110   conn->credentials = credentials;
3111 
3112 #  elif defined(HAVE_CDSASSL)
3113   conn = (http_tls_t *)calloc(1, sizeof(http_tls_t));
3114 
3115   if (conn == NULL)
3116     return (-1);
3117 
3118   if ((error = SSLNewContext(false, &conn->session)))
3119   {
3120     http->error  = error;
3121     http->status = HTTP_ERROR;
3122 
3123     free(conn);
3124     return (-1);
3125   }
3126 
3127  /*
3128   * Use a union to resolve warnings about int/pointer size mismatches...
3129   */
3130 
3131   error = SSLSetConnection(conn->session, http);
3132 
3133   if (!error)
3134     error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
3135 
3136   if (!error)
3137     error = SSLSetAllowsExpiredCerts(conn->session, true);
3138 
3139   if (!error)
3140     error = SSLSetAllowsAnyRoot(conn->session, true);
3141 
3142   if (!error)
3143     error = SSLSetProtocolVersionEnabled(conn->session, kSSLProtocol2, false);
3144 
3145   if (!error)
3146   {
3147     while ((error = SSLHandshake(conn->session)) == errSSLWouldBlock)
3148       usleep(1000);
3149   }
3150 
3151   if (error)
3152   {
3153     http->error  = error;
3154     http->status = HTTP_ERROR;
3155 
3156     SSLDisposeContext(conn->session);
3157 
3158     free(conn);
3159 
3160     return (-1);
3161   }
3162 #  endif /* HAVE_CDSASSL */
3163 
3164   http->tls = conn;
3165   return (0);
3166 }
3167 #endif /* HAVE_SSL */
3168 
3169 
3170 #ifdef HAVE_SSL
3171 /*
3172  * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
3173  */
3174 
3175 static void
http_shutdown_ssl(http_t * http)3176 http_shutdown_ssl(http_t *http)		/* I - Connection to server */
3177 {
3178 #  ifdef HAVE_LIBSSL
3179   SSL_CTX	*context;		/* Context for encryption */
3180   SSL		*conn;			/* Connection for encryption */
3181 
3182 
3183   conn    = (SSL *)(http->tls);
3184   context = SSL_get_SSL_CTX(conn);
3185 
3186   SSL_shutdown(conn);
3187   SSL_CTX_free(context);
3188   SSL_free(conn);
3189 
3190 #  elif defined(HAVE_GNUTLS)
3191   http_tls_t      *conn;		/* Encryption session */
3192   gnutls_certificate_client_credentials *credentials;
3193 					/* TLS credentials */
3194 
3195 
3196   conn = (http_tls_t *)(http->tls);
3197   credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
3198 
3199   gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
3200   gnutls_deinit(conn->session);
3201   gnutls_certificate_free_credentials(*credentials);
3202   free(credentials);
3203   free(conn);
3204 
3205 #  elif defined(HAVE_CDSASSL)
3206   http_tls_t      *conn;		/* CDSA connection information */
3207 
3208 
3209   conn = (http_tls_t *)(http->tls);
3210 
3211   while (SSLClose(conn->session) == errSSLWouldBlock)
3212     usleep(1000);
3213 
3214   SSLDisposeContext(conn->session);
3215 
3216   if (conn->certsArray)
3217     CFRelease(conn->certsArray);
3218 
3219   free(conn);
3220 #  endif /* HAVE_LIBSSL */
3221 
3222   http->tls = NULL;
3223 }
3224 #endif /* HAVE_SSL */
3225 
3226 
3227 #if defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD_H)
3228 /*
3229  * 'http_threadid_cb()' - Return the current thread ID.
3230  */
3231 
3232 static unsigned long			/* O - Thread ID */
http_threadid_cb(void)3233 http_threadid_cb(void)
3234 {
3235   return ((unsigned long)pthread_self());
3236 }
3237 #endif /* HAVE_LIBSSL && HAVE_PTHREAD_H */
3238 
3239 
3240 #ifdef HAVE_SSL
3241 /*
3242  * 'http_upgrade()' - Force upgrade to TLS encryption.
3243  */
3244 
3245 static int				/* O - Status of connection */
http_upgrade(http_t * http)3246 http_upgrade(http_t *http)		/* I - Connection to server */
3247 {
3248   int		ret;			/* Return value */
3249   http_t	myhttp;			/* Local copy of HTTP data */
3250 
3251 
3252   DEBUG_printf(("7http_upgrade(%p)", http));
3253 
3254  /*
3255   * Flush the connection to make sure any previous "Upgrade" message
3256   * has been read.
3257   */
3258 
3259   httpFlush(http);
3260 
3261  /*
3262   * Copy the HTTP data to a local variable so we can do the OPTIONS
3263   * request without interfering with the existing request data...
3264   */
3265 
3266   memcpy(&myhttp, http, sizeof(myhttp));
3267 
3268  /*
3269   * Send an OPTIONS request to the server, requiring SSL or TLS
3270   * encryption on the link...
3271   */
3272 
3273   http->field_authorization = NULL;	/* Don't free the auth string */
3274 
3275   httpClearFields(http);
3276   httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
3277   httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
3278 
3279   if ((ret = httpOptions(http, "*")) == 0)
3280   {
3281    /*
3282     * Wait for the secure connection...
3283     */
3284 
3285     while (httpUpdate(http) == HTTP_CONTINUE);
3286   }
3287 
3288  /*
3289   * Restore the HTTP request data...
3290   */
3291 
3292   memcpy(http->fields, myhttp.fields, sizeof(http->fields));
3293   http->data_encoding       = myhttp.data_encoding;
3294   http->data_remaining      = myhttp.data_remaining;
3295   http->_data_remaining     = myhttp._data_remaining;
3296   http->expect              = myhttp.expect;
3297   http->field_authorization = myhttp.field_authorization;
3298   http->digest_tries        = myhttp.digest_tries;
3299 
3300  /*
3301   * See if we actually went secure...
3302   */
3303 
3304   if (!http->tls)
3305   {
3306    /*
3307     * Server does not support HTTP upgrade...
3308     */
3309 
3310     DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!");
3311 
3312 #  ifdef WIN32
3313     closesocket(http->fd);
3314 #  else
3315     close(http->fd);
3316 #  endif
3317 
3318     http->fd = -1;
3319 
3320     return (-1);
3321   }
3322   else
3323     return (ret);
3324 }
3325 #endif /* HAVE_SSL */
3326 
3327 
3328 /*
3329  * 'http_write()' - Write a buffer to a HTTP connection.
3330  */
3331 
3332 static int				/* O - Number of bytes written */
http_write(http_t * http,const char * buffer,int length)3333 http_write(http_t     *http,		/* I - Connection to server */
3334            const char *buffer,		/* I - Buffer for data */
3335 	   int        length)		/* I - Number of bytes to write */
3336 {
3337   int	tbytes,				/* Total bytes sent */
3338 	bytes;				/* Bytes sent */
3339 
3340 
3341   http->error = 0;
3342   tbytes      = 0;
3343 
3344   while (length > 0)
3345   {
3346 #ifdef HAVE_SSL
3347     if (http->tls)
3348       bytes = http_write_ssl(http, buffer, length);
3349     else
3350 #endif /* HAVE_SSL */
3351     bytes = send(http->fd, buffer, length, 0);
3352 
3353     if (bytes < 0)
3354     {
3355 #ifdef WIN32
3356       if (WSAGetLastError() != http->error)
3357       {
3358         http->error = WSAGetLastError();
3359 	continue;
3360       }
3361 #else
3362       if (errno == EINTR || errno == EAGAIN)
3363         continue;
3364       else if (errno != http->error && errno != ECONNRESET)
3365       {
3366         http->error = errno;
3367 	continue;
3368       }
3369 #endif /* WIN32 */
3370 
3371       DEBUG_puts("8http_write: error writing data...");
3372 
3373       return (-1);
3374     }
3375 
3376     buffer += bytes;
3377     tbytes += bytes;
3378     length -= bytes;
3379   }
3380 
3381 #ifdef DEBUG
3382   http_debug_hex("http_write", buffer - tbytes, tbytes);
3383 #endif /* DEBUG */
3384 
3385   return (tbytes);
3386 }
3387 
3388 
3389 /*
3390  * 'http_write_chunk()' - Write a chunked buffer.
3391  */
3392 
3393 static int				/* O - Number bytes written */
http_write_chunk(http_t * http,const char * buffer,int length)3394 http_write_chunk(http_t     *http,	/* I - Connection to server */
3395                  const char *buffer,	/* I - Buffer to write */
3396 		 int        length)	/* I - Length of buffer */
3397 {
3398   char	header[255];			/* Chunk header */
3399   int	bytes;				/* Bytes written */
3400 
3401 
3402   DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=%d)",
3403                 http, buffer, length));
3404 
3405  /*
3406   * Write the chunk header, data, and trailer.
3407   */
3408 
3409   sprintf(header, "%x\r\n", length);
3410   if (http_write(http, header, (int)strlen(header)) < 0)
3411   {
3412     DEBUG_puts("8http_write_chunk: http_write of length failed!");
3413     return (-1);
3414   }
3415 
3416   if ((bytes = http_write(http, buffer, length)) < 0)
3417   {
3418     DEBUG_puts("8http_write_chunk: http_write of buffer failed!");
3419     return (-1);
3420   }
3421 
3422   if (http_write(http, "\r\n", 2) < 0)
3423   {
3424     DEBUG_puts("8http_write_chunk: http_write of CR LF failed!");
3425     return (-1);
3426   }
3427 
3428   return (bytes);
3429 }
3430 
3431 
3432 #ifdef HAVE_SSL
3433 /*
3434  * 'http_write_ssl()' - Write to a SSL/TLS connection.
3435  */
3436 
3437 static int				/* O - Bytes written */
http_write_ssl(http_t * http,const char * buf,int len)3438 http_write_ssl(http_t     *http,	/* I - Connection to server */
3439 	       const char *buf,		/* I - Buffer holding data */
3440 	       int        len)		/* I - Length of buffer */
3441 {
3442 #  if defined(HAVE_LIBSSL)
3443   return (SSL_write((SSL *)(http->tls), buf, len));
3444 
3445 #  elif defined(HAVE_GNUTLS)
3446   ssize_t	result;			/* Return value */
3447 
3448   result = gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len);
3449 
3450   if (result < 0 && !errno)
3451   {
3452    /*
3453     * Convert GNU TLS error to errno value...
3454     */
3455 
3456     switch (result)
3457     {
3458       case GNUTLS_E_INTERRUPTED :
3459 	  errno = EINTR;
3460 	  break;
3461 
3462       case GNUTLS_E_AGAIN :
3463           errno = EAGAIN;
3464           break;
3465 
3466       default :
3467           errno = EPIPE;
3468           break;
3469     }
3470 
3471     result = -1;
3472   }
3473 
3474   return ((int)result);
3475 
3476 #  elif defined(HAVE_CDSASSL)
3477   int		result;			/* Return value */
3478   OSStatus	error;			/* Error info */
3479   size_t	processed;		/* Number of bytes processed */
3480 
3481 
3482   error = SSLWrite(((http_tls_t *)http->tls)->session, buf, len, &processed);
3483 
3484   switch (error)
3485   {
3486     case 0 :
3487 	result = (int)processed;
3488 	break;
3489     case errSSLClosedGraceful :
3490 	result = 0;
3491 	break;
3492     case errSSLWouldBlock :
3493 	if (processed)
3494 	  result = (int)processed;
3495 	else
3496 	{
3497 	  result = -1;
3498 	  errno  = EINTR;
3499 	}
3500 	break;
3501     default :
3502 	errno  = EPIPE;
3503 	result = -1;
3504 	break;
3505   }
3506 
3507   return (result);
3508 #  endif /* HAVE_LIBSSL */
3509 }
3510 #endif /* HAVE_SSL */
3511 
3512 
3513 /*
3514  * End of "$Id: http.c 9233 2010-08-10 06:15:55Z mike $".
3515  */
3516