4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
38 #include <openssl/ssl.h>
39 #include <openssl/err.h>
40 #include <openssl/rand.h>
41 #include <openssl/pkcs12.h>
43 /* this must be included after ssl.h to avoid re-defining 'offsetof' */
44 #include <sys/sysmacros.h>
46 #include <boot_http.h>
47 #include <socket_inet.h>
48 #include <p12access.h>
52 #define BOOT_HTTP_MAJOR_VERSION 1
53 #define BOOT_HTTP_MINOR_VERSION 0
54 #define BOOT_HTTP_MICRO_VERSION 0
56 static boot_http_ver_t boot_http_ver
= {
57 BOOT_HTTP_MAJOR_VERSION
,
58 BOOT_HTTP_MINOR_VERSION
,
59 BOOT_HTTP_MICRO_VERSION
62 static int early_err
; /* Error from before error occurred */
64 static boolean_t verbosemode
= B_FALSE
;
65 static char *cipher_list
= NULL
; /* Ciphers supported (if not default) */
68 int i
; /* current position in buffer */
69 int n
; /* number of bytes in buffer */
70 char buf
[512]; /* buffer */
74 uint_t errsrc
; /* Source of this error */
75 ulong_t error
; /* Which error? */
80 HTTP_REQ_TYPE_HEAD
= 1,
84 #define FAILSAFE 20 /* Max # empty lines to accept */
85 #define DEFAULT_TIMEOUT 10 /* Default socket read timeout value */
86 #define HTTP_CONN_INFO 0x90919293 /* Identifies a http_conn_t struct */
87 #define ESTACK_SIZE 20 /* Size of the stack */
89 typedef struct http_conn_t
{
90 uint_t signature
; /* Cookie indicating this is a handle */
91 int fd
; /* Connection's fd... */
93 void *ssl
; /* Handle to ssl data structure */
94 int read_timeout
; /* Timeout to use on read requests in sec */
95 char *basic_auth_userid
; /* Basic authentication user ID */
96 char *basic_auth_password
; /* and password */
97 char is_multipart
; /* B_TRUE if doing multipart/mixed download */
98 char is_firstpart
; /* B_TRUE if first part in a multipart xfer */
99 char is_firstchunk
; /* B_TRUE if first chunk in chunked xfer */
100 char is_chunked
; /* B_TRUE if message body is chunked */
102 struct sockaddr_in host_addr
; /* Address of host */
103 url_t uri
; /* The current URI */
104 url_hport_t proxy
; /* The proxy info */
105 boolean_t proxied
; /* Connection is proxied */
106 char *random_file
; /* File with seed info for pseudo random */
107 /* number generator */
108 char *client_cert_file
; /* File holding client's certificate */
109 char *private_key_file
; /* File with the private key */
110 char *file_password
; /* file with password to key or pkcs12 file. */
111 http_respinfo_t resp
; /* Response summary info */
112 char **resphdr
; /* Array of header response lines */
114 char *boundary
; /* Boundary text (multipart downloads only) */
115 uint_t boundary_len
; /* Length of boundary string */
117 uint_t nexterr
; /* Next error to return */
118 ssize_t body_size
; /* Size of message body or chunk */
119 ssize_t body_read
; /* # of bytes of body_size processed */
120 ssize_t body_size_tot
; /* Total message body size */
121 ssize_t body_read_tot
; /* # of bytes of body_size_tot processed */
122 errent_t errs
[ESTACK_SIZE
]; /* stack of errors on the last request */
123 /* (libssl can return multiple errors on one */
128 * Convenient macros for accessing fields in connection structure.
130 #define CONN_HOSTNAME c_id->uri.hport.hostname
131 #define CONN_PORT c_id->uri.hport.port
132 #define CONN_ABSPATH c_id->uri.abspath
133 #define CONN_HTTPS c_id->uri.https
134 #define CONN_PROXY_HOSTNAME c_id->proxy.hostname
135 #define CONN_PROXY_PORT c_id->proxy.port
137 #define RESET_ERR(c_id) (c_id)->numerrs = 0, (c_id)->nexterr = 0
138 #define SET_ERR(c_id, src, err) if ((c_id)->numerrs < ESTACK_SIZE) \
139 (c_id)->errs[(c_id)->numerrs].errsrc = (src), \
140 (c_id)->errs[(c_id)->numerrs ++].error = (err)
142 #define GET_ERR(c_id, e_src, e_code) \
143 if ((c_id)->nexterr < (c_id)->numerrs) \
144 (e_src) = (c_id)->errs[((c_id)->nexterr)].errsrc, \
145 (e_code) = (c_id)->errs[((c_id)->nexterr)++].error; \
147 (e_src) = 0, (e_code) = 0
150 * Macro used to increment message body read counters
152 #define INC_BREAD_CNT(bool, bcnt) \
156 c_id->body_read_tot++; \
159 static int ssl_init
= 0; /* 1 when ssl has been initialized */
160 static char *ca_verify_file
; /* List of trusted CA's */
161 static int verify_depth
= 16; /* Certificate chain depth to verify */
162 static int p12_format
= 0; /* Default to PEM format */
165 /* prototypes for local functions */
166 static int http_req(http_handle_t
, const char *, http_req_t
, offset_t
,
168 static boolean_t
http_check_conn(http_conn_t
*);
169 static SSL_CTX
*initialize_ctx(http_conn_t
*);
170 static int tcp_connect(http_conn_t
*, const char *, uint16_t);
171 static int readline(http_conn_t
*, int, char *, int);
172 static int proxy_connect(http_conn_t
*);
173 static int check_cert_chain(http_conn_t
*, char *);
174 static void print_ciphers(SSL
*);
175 static int read_headerlines(http_conn_t
*, boolean_t
);
176 static void free_response(http_conn_t
*, int);
177 static int free_ctx_ssl(http_conn_t
*);
178 static int get_chunk_header(http_conn_t
*);
179 static int init_bread(http_conn_t
*);
180 static int get_msgcnt(http_conn_t
*, ssize_t
*);
181 static int getaline(http_conn_t
*, char *, int, boolean_t
);
182 static int getbytes(http_conn_t
*, char *, int);
183 static int http_srv_send(http_conn_t
*, const void *, size_t);
184 static int http_srv_recv(http_conn_t
*, void *, size_t);
185 static void handle_ssl_error(http_conn_t
*, int);
186 static int count_digits(int);
187 static int hexdigit(char);
188 static char *eat_ws(const char *);
189 static boolean_t
startswith(const char **strp
, const char *starts
);
191 /* ---------------------- public functions ----------------------- */
194 * http_set_p12_format - Set flag indicating that certs & keys will be in
197 * Default is PEM certs. When this is called, the default can be changed to
201 http_set_p12_format(int on_off
)
207 * http_get_version - Get current boot http support version
209 * pVer = http_get_version();
215 * Pointer to struct with version information.
217 * Returns the version of the http support in the current library. This
218 * is a struct with unsigned integsrs for <major>, <minor> and
219 * <micro> version numbers. <major> changes when an incompatible change
220 * is made. <minor> changes when an upwardly-compatible API change is
221 * made. <micro> consists of bug fixes, etc.
223 boot_http_ver_t
const *
224 http_get_version(void)
226 return (&boot_http_ver
);
230 * http_set_verbose - Turn verbose on/off
232 * http_set_verbose(on_off);
235 * on_off - When TRUE, turn verbose mode one. When FALSE, turn
241 * When enabled, information is logged to bootlog (or the Solaris equivalent).
244 http_set_verbose(boolean_t on_off
)
246 verbosemode
= on_off
;
250 * http_set_cipher_list - Change the list of ciphers that can be used.
252 * ret = http_set_cipher_list(handle, list);
255 * list - List of ciphers that can be used.
259 * -1 - An error occurred. Check http_get_lasterr().
262 http_set_cipher_list(const char *list
)
269 early_err
= EHTTP_NOMEM
;
275 cipher_list
= (char *)list
;
280 * http_srv_init - Set up a structure for a connection.
282 * handle = http_srv_init(url);
285 * url - the structure that contains the URI.
288 * != NULL - A handle for referring to this connection.
289 * == NULL - An error occurred. Get the exact error from
290 * http_get_lasterr().
293 http_srv_init(const url_t
*url
)
299 early_err
= EHTTP_BADARG
;
303 if ((c_id
= malloc(sizeof (*c_id
))) == NULL
) {
304 early_err
= EHTTP_NOMEM
;
308 bzero(c_id
, sizeof (*c_id
));
310 c_id
->proxied
= B_FALSE
;
311 c_id
->read_timeout
= DEFAULT_TIMEOUT
;
312 c_id
->keepalive
= B_TRUE
;
315 /* Do this at the end, just in case.... */
316 c_id
->signature
= HTTP_CONN_INFO
;
322 * http_conn_is_https - Determine whether the scheme is http or https.
324 * B_TRUE - Connection is an SSL connection.
325 * B_FALSE - Connection isn't SSL.
327 * ret = http_conn_is_https(handle, boolean_t *bool);
330 * handle - Handle associated with the desired connection
331 * bool - Ptr to boolean in which to place result
335 * -1 - Some error occurred.
338 http_conn_is_https(http_handle_t handle
, boolean_t
*bool)
340 http_conn_t
*c_id
= handle
;
342 if (!http_check_conn(c_id
))
350 * http_set_proxy - Establish the proxy name/port.
352 * ret = http_set_proxy(handle, proxy);
355 * handle - Handle associated with the desired connection
356 * proxy - The hostport definition for the proxy. If NULL,
357 * The next connect will not use a proxy.
361 * -1 - An error occurred. Check http_get_lasterr().
364 http_set_proxy(http_handle_t handle
, const url_hport_t
*proxy
)
366 http_conn_t
*c_id
= handle
;
368 if (!http_check_conn(c_id
))
372 c_id
->proxy
= *proxy
;
373 c_id
->proxied
= B_TRUE
;
375 CONN_PROXY_HOSTNAME
[0] = '\0';
376 c_id
->proxied
= B_FALSE
;
383 * http_set_keepalive - Set keepalive for this connection.
385 * http_set_keepalive(handle, on_off);
388 * handle - Handle associated with the desired connection
389 * on_off - Boolean turning keepalive on (TRUE) or off (FALSE)
393 * -1 - An error occurred. Check http_get_lasterr().
395 * This setting takes effect next time a connection is opened using this
399 http_set_keepalive(http_handle_t handle
, boolean_t on_off
)
401 http_conn_t
*c_id
= handle
;
403 if (!http_check_conn(c_id
))
406 c_id
->keepalive
= on_off
;
411 * http_set_socket_read_timeout - Set the timeout reads
413 * http_set_socket_read_timeout(handle, timeout);
416 * handle - Handle associated with the desired connection
417 * timeout - Timeout, in seconds. Zero will default to 10 second
422 * -1 - An error occurred. Check http_get_lasterr().
424 * This setting takes effect beginning with the next read operation on this
428 http_set_socket_read_timeout(http_handle_t handle
, uint_t timout
)
430 http_conn_t
*c_id
= handle
;
432 if (!http_check_conn(c_id
))
435 c_id
->read_timeout
= (timout
) ? timout
: DEFAULT_TIMEOUT
;
440 * http_set_basic_auth - Set the basic authorization user ID and password
442 * ret = http_set_basic_auth(handle, userid, password);
445 * handle - Handle associated with the desired connection
446 * userid - ID to pass as part of http/https request
447 * password- Password which goes with the user ID
451 * -1 - An error occurred. Check http_get_lasterr().
453 * This must be set before a https connection is made.
456 http_set_basic_auth(http_handle_t handle
, const char *userid
,
457 const char *password
)
459 http_conn_t
*c_id
= handle
;
461 if (!http_check_conn(c_id
))
464 if (password
== NULL
|| userid
== NULL
|| userid
[0] == '\0') {
465 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADARG
);
469 userid
= strdup(userid
);
470 password
= strdup(password
);
471 if (userid
== NULL
|| password
== NULL
) {
472 free((void *)userid
);
473 free((void *)password
);
474 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
478 free(c_id
->basic_auth_userid
);
479 c_id
->basic_auth_userid
= (char *)userid
;
480 free(c_id
->basic_auth_password
);
481 c_id
->basic_auth_password
= (char *)password
;
486 * http_set_random_file - See the pseudo random number generator with file data
488 * ret = http_set_random_file(handle, filename);
491 * handle - Handle associated with the desired connection
493 * - filename (including path) with random number seed.
497 * -1 - An error occurred. Check http_get_lasterr().
499 * This must be set before a https connection is made.
502 http_set_random_file(http_handle_t handle
, const char *fname
)
504 http_conn_t
*c_id
= handle
;
506 if (!http_check_conn(c_id
))
510 fname
= strdup(fname
);
512 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
517 free(c_id
->random_file
);
518 c_id
->random_file
= (char *)fname
;
523 * http_set_certificate_authority_file - Set the CA file.
525 * ret = http_set_certificate_authority_file(filename);
528 * filename- File with the certificate authority certs
532 * -1 - An error occurred. Check http_get_lasterr().
534 * This must be set before https connections to the servers is done.
537 http_set_certificate_authority_file(const char *fname
)
542 fname
= strdup(fname
);
544 early_err
= EHTTP_NOMEM
;
549 free(ca_verify_file
);
550 ca_verify_file
= (char *)fname
;
555 * http_set_client_certificate_file - Set the file containing the PKCS#12
556 * client certificate and optionally its certificate chain.
558 * ret = http_set_client_certificate_file(handle, filename);
561 * handle - Handle associated with the desired connection
562 * filename- File (including path) containing certificate, etc.
566 * -1 - An error occurred. Check http_get_lasterr().
568 * This must be set before the handle is used to make a https connection
569 * which will require a client certificate.
572 http_set_client_certificate_file(http_handle_t handle
, const char *fname
)
574 http_conn_t
*c_id
= handle
;
576 if (!http_check_conn(c_id
))
580 fname
= strdup(fname
);
582 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
587 free(c_id
->client_cert_file
);
588 c_id
->client_cert_file
= (char *)fname
;
593 * http_set_password - Set the password for the private key or pkcs12 file.
595 * ret = http_set_password(handle, password);
598 * handle - Handle associated with the desired connection
599 * password- Password for the client's private key file or pkcs12 file.
603 * -1 - An error occurred. Check http_get_lasterr().
605 * This must be set before the handle is used to make a https connection.
608 http_set_password(http_handle_t handle
, const char *password
)
610 http_conn_t
*c_id
= handle
;
612 if (!http_check_conn(c_id
))
615 if (password
!= NULL
) {
616 password
= strdup(password
);
617 if (password
== NULL
) {
618 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
623 free(c_id
->file_password
);
624 c_id
->file_password
= (char *)password
;
629 * http_set_key_file_password - Set the password for the private key
632 * ret = http_set_key_file_password(handle, password);
635 * handle - Handle associated with the desired connection
636 * password- Password for the client's private key file.
640 * -1 - An error occurred. Check http_get_lasterr().
642 * This must be set before the handle is used to make a https connection.
645 http_set_key_file_password(http_handle_t handle
, const char *password
)
647 return (http_set_password(handle
, password
));
651 * http_set_private_key_file - Set the file containing the PKCS#12
652 * private key for this client.
654 * ret = http_set_private_key_file(handle, filename);
657 * handle - Handle associated with the desired connection
658 * filename- File (including path) containing the private key.
662 * -1 - An error occurred. Check http_get_lasterr().
664 * This must be set before the handle is used to make a https connection.
667 http_set_private_key_file(http_handle_t handle
, const char *fname
)
669 http_conn_t
*c_id
= handle
;
671 if (!http_check_conn(c_id
))
675 fname
= strdup(fname
);
677 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
682 free(c_id
->private_key_file
);
683 c_id
->private_key_file
= (char *)fname
;
688 * http_srv_connect - Establish a connection to the server
690 * ret = http_srv_connect(handle);
693 * handle - Handle associated with the desired connection
697 * -1 - An error occurred. Check http_get_lasterr() for specifics.
700 http_srv_connect(http_handle_t handle
)
702 http_conn_t
*c_id
= handle
;
707 if (!http_check_conn(c_id
))
711 /* Build our SSL context (this function sets any errors) */
712 ctx
= initialize_ctx(c_id
);
714 libbootlog(BOOTLOG_CRIT
,
715 "http_srv_connect: initialize_ctx returned NULL");
720 /* Connect the TCP socket */
722 c_id
->fd
= proxy_connect(c_id
);
724 c_id
->fd
= tcp_connect(c_id
, CONN_HOSTNAME
, CONN_PORT
);
730 libbootlog(BOOTLOG_CRIT
, "http_srv_connect: %s returned %d",
731 (c_id
->proxied
) ? "proxy_connect" : "tcp_connect",
737 /* Connect the SSL socket */
738 if ((c_id
->ssl
= SSL_new(ctx
)) == NULL
) {
740 while ((err
= ERR_get_error()) != 0)
741 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
742 libbootlog(BOOTLOG_CRIT
,
743 "http_srv_connect: SSL_new returned "
745 (void) free_ctx_ssl(c_id
);
749 print_ciphers(c_id
->ssl
);
751 /* Ensure automatic negotiations will do things right */
752 SSL_set_connect_state(c_id
->ssl
);
754 if (SSL_set_fd(c_id
->ssl
, c_id
->fd
) == 0) {
756 while ((err
= ERR_get_error()) != 0)
757 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
758 libbootlog(BOOTLOG_CRIT
,
759 "http_srv_connect: SSL_set_fd returned 0");
760 (void) free_ctx_ssl(c_id
);
764 if ((retval
= SSL_connect(c_id
->ssl
)) <= 0) {
765 handle_ssl_error(c_id
, retval
);
766 libbootlog(BOOTLOG_CRIT
,
767 "http_srv_connect: SSL_connect");
768 (void) free_ctx_ssl(c_id
);
772 if (check_cert_chain(c_id
, CONN_HOSTNAME
) != 0) {
773 (void) free_ctx_ssl(c_id
);
778 print_ciphers(c_id
->ssl
);
785 * http_head_request - Issue http HEAD request
787 * ret = http_head_request(handle, abs_path);
790 * handle - Handle associated with the desired connection
791 * abs_path- File name portion of the URI, beginning with a /. Query,
792 * segment, etc are allowed.
796 * -1 - An error occurred. Check http_get_lasterr().
799 http_head_request(http_handle_t handle
, const char *abs_path
)
801 return (http_req(handle
, abs_path
, HTTP_REQ_TYPE_HEAD
, 0, 0));
805 * http_get_request - Issue http GET request without a range.
807 * ret = http_get_request(handle, abs_path);
810 * handle - Handle associated with the desired connection
811 * abs_path- File name portion of the URI, beginning with a /. Query,
812 * segment, etc are allowed.
816 * -1 - An error occurred. Check http_get_lasterr().
819 http_get_request(http_handle_t handle
, const char *abs_path
)
821 return (http_req(handle
, abs_path
, HTTP_REQ_TYPE_GET
, -1, 0));
825 * http_get_range_request - Issue http GET request using a range.
827 * ret = http_get_range_request(handle, abs_path, curpos, len);
830 * handle - Handle associated with the desired connection
831 * abs_path- File name portion of the URI, beginning with a /. Query,
832 * segment, etc are allowed.
833 * curpos - >=0 - Beginning of range
834 * len - = 0 - Range ends at the end of the file
835 * > 0 - Length of range.
839 * -1 - An error occurred. Check http_get_lasterr().
842 http_get_range_request(http_handle_t handle
, const char *abs_path
,
843 offset_t curpos
, offset_t len
)
845 http_conn_t
*c_id
= handle
;
847 if (!http_check_conn(c_id
))
851 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADARG
);
855 return (http_req(handle
, abs_path
, HTTP_REQ_TYPE_GET
, curpos
, len
));
859 * http_free_respinfo - Free a respinfo structure
861 * ret = http_free_respinfo(resp);
864 * resp - respinfo structure presumably allocated by
865 * http_process_headers() or http_process_part_headers()
867 * Note that if resp is NULL, then this results in a NOOP.
871 http_free_respinfo(http_respinfo_t
*resp
)
877 if (resp
->statusmsg
!= NULL
) {
878 free(resp
->statusmsg
);
884 * http_process_headers - Read in the header lines from the response
886 * ret = http_process_headers(handle, resp);
889 * handle - Handle associated with the connection where the request
891 * resp - Summary information about the response.
895 * < 0 - An error occurred. Specifics of the error can
896 * be gotten using http_get_lasterr().
898 * Process the HTTP headers in the response. Check for a valid response
899 * status line. Allocate and return response information via the 'resp'
900 * argument. Header lines are stored locally, are are returned using calls
901 * to http_get_response_header() and http_get_header_value().
903 * Note that the errors will be set in the http_conn_t struct before the
904 * function which detected the error returns.
906 * Note that if resp is non-NULL, then upon a successful return, information
907 * about the status line, the code in the status line and the number of
908 * header lines are returned in the http_respinfo_t structure. The caller is
909 * responsible for freeing the resources allocated to this structure via
910 * http_free_respinfo().
912 * Note that the counters used to read message bodies are initialized here.
914 * Calling this function replaces the header information which is
915 * queried using http_get_response_header() and http_get_header_value().
916 * Once this function is called, headers read by the previous call
917 * to http_process_headers() or http_process_part_headers() is lost.
920 http_process_headers(http_handle_t handle
, http_respinfo_t
**resp
)
922 http_conn_t
*c_id
= handle
;
923 http_respinfo_t
*lresp
;
924 char line
[MAXHOSTNAMELEN
];
929 if (!http_check_conn(c_id
))
933 if ((lresp
= malloc(sizeof (http_respinfo_t
))) == NULL
) {
934 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
938 bzero(lresp
, sizeof (http_respinfo_t
));
942 * check the response status line, expecting
945 i
= getaline(c_id
, line
, sizeof (line
), B_FALSE
);
955 * Cause of I/O error was already put into
956 * error stack. This is an additional error.
958 http_free_respinfo(lresp
);
959 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NODATA
);
963 free_response(c_id
, B_TRUE
);
966 libbootlog(BOOTLOG_VERBOSE
, "http_process_headers: %s", line
);
969 if (strncmp(ptr
, "HTTP/1.1", 8) != 0) {
970 http_free_respinfo(lresp
);
971 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOT_1_1
);
975 /* skip to the code */
977 while (isspace(*ptr
))
980 /* make sure it's three digits */
982 while (isdigit(ptr
[i
]))
985 http_free_respinfo(lresp
);
986 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADHDR
);
989 c_id
->resp
.code
= strtol(ptr
, NULL
, 10);
991 /* skip to the message */
993 while (isspace(*ptr
))
996 /* save the message */
997 c_id
->resp
.statusmsg
= malloc(strlen(ptr
) + 1);
998 if (c_id
->resp
.statusmsg
== NULL
) {
999 http_free_respinfo(lresp
);
1000 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1003 (void) strcpy(c_id
->resp
.statusmsg
, ptr
);
1005 if ((i
= read_headerlines(c_id
, B_FALSE
)) < 0) {
1007 * Error stack was already set at a lower level.
1008 * 'statusmsg' will be cleaned up next time
1011 http_free_respinfo(lresp
);
1016 * See if there is a 'content-type: multipart/mixed' line in the
1017 * headers. If so, get the boundary string.
1019 ptr
= http_get_header_value(handle
, "Content-Type");
1024 while (isspace(*ptr2
))
1026 if (startswith((const char **)&ptr2
, "Multipart/Mixed;")) {
1027 while (isspace(*ptr2
))
1029 if (startswith((const char **)&ptr2
, "Boundary=")) {
1030 if (ptr2
[0] == '"') {
1032 if (ptr2
[strlen(ptr2
) - 1] == '"')
1033 ptr2
[strlen(ptr2
) - 1] = '\0';
1035 c_id
->boundary
= strdup(ptr2
);
1036 if (c_id
->boundary
== NULL
) {
1038 http_free_respinfo(lresp
);
1039 SET_ERR(c_id
, ERRSRC_LIBHTTP
,
1043 c_id
->boundary_len
= strlen(c_id
->boundary
);
1044 c_id
->is_multipart
= B_TRUE
;
1045 c_id
->is_firstpart
= B_TRUE
;
1052 * Initialize the counters used to process message bodies.
1054 if (init_bread(c_id
) != 0) {
1056 * Error stack was already set at a lower level.
1058 http_free_respinfo(lresp
);
1062 /* Copy fields to the caller's structure */
1064 lresp
->code
= c_id
->resp
.code
;
1065 lresp
->nresphdrs
= c_id
->resp
.nresphdrs
;
1066 lresp
->statusmsg
= strdup(c_id
->resp
.statusmsg
);
1067 if (lresp
->statusmsg
== NULL
) {
1068 http_free_respinfo(lresp
);
1069 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1079 * http_process_part_headers - Read in part boundary and header lines for the
1080 * next part of a multipart message.
1082 * ret = http_process_part_headers(handle, resp);
1085 * handle - Handle associated with the connection where the request
1087 * resp - Return address for summary information about the
1091 * = 1 - The end part was found.
1092 * = 0 - Success, with header info returned in 'resp'
1093 * = -1 - An error occurred. Specifics of the error can
1094 * be gotten using http_get_lasterr().
1096 * This function reads any \r\n sequences (empty lines) and expects to get
1097 * a boundary line as the next non-empty line. It then reads header lines
1098 * (content-length, etc) until it gets another empty lines, which ends the
1101 * Note that if resp is non-NULL, then upon a successful return, information
1102 * about the the number of header lines is returned in the http_respinfo_t
1103 * structure. The caller is responsible for freeing the resources allocated
1104 * to this structure via http_free_respinfo().
1106 * Headers values can be returned using http_get_response_header() and
1107 * http_get_header_value().
1109 * Calling this function replaces the header information which is
1110 * queried using http_get_response_header() and http_get_header_value().
1111 * Once this function is called, information returned by the previous call
1112 * to http_process_headers() or http_process_part_headers() is gone.
1115 http_process_part_headers(http_handle_t handle
, http_respinfo_t
**resp
)
1117 http_conn_t
*c_id
= handle
;
1118 char line
[MAXHOSTNAMELEN
];
1124 if (!http_check_conn(c_id
))
1127 if (c_id
->is_multipart
== 0) {
1128 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOTMULTI
);
1133 * Figure out how many empty lines to allow. Before the first
1134 * boundary of the transmission, there can be any number of
1135 * empty lines (from 0 up). Limit these to some reasonable
1138 * For the 2nd and later boundaries, there is supposed to be
1139 * one crlf pair. However, many implementations don't require
1140 * it. So don't require it.
1142 if (c_id
->is_firstpart
) {
1144 c_id
->is_firstpart
= B_FALSE
;
1148 /* Look for the boundary line. */
1150 while ((i
= getaline(c_id
, line
, sizeof (line
), B_TRUE
)) == 0 &&
1153 if (i
< 0 || count
> limit
) {
1155 * If I/O error, cause was already put into
1156 * error stack. This is an additional error.
1158 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOBOUNDARY
);
1162 free_response(c_id
, B_FALSE
);
1165 libbootlog(BOOTLOG_VERBOSE
,
1166 "http_process_part_headers: %s", line
);
1168 /* Look for boundary line - '--<boundary text> */
1169 if (line
[0] != '-' || line
[1] != '-' ||
1170 strncmp(&line
[2], c_id
->boundary
, c_id
->boundary_len
) != 0) {
1171 /* No boundary line.... */
1172 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOBOUNDARY
);
1176 /* Is this the end-of-parts boundary (ends with a trailing '--') */
1177 if (strcmp(&line
[c_id
->boundary_len
+ 2], "--") == 0) {
1181 free_response(c_id
, B_FALSE
);
1182 if (read_headerlines(c_id
, B_TRUE
) < 0) {
1183 /* Error stack was already set at a lower level. */
1187 /* Copy fields to the caller's structure */
1189 if ((*resp
= malloc(sizeof (http_respinfo_t
))) == NULL
) {
1190 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1193 bzero(*resp
, sizeof (http_respinfo_t
));
1194 (*resp
)->code
= ' ';
1195 (*resp
)->nresphdrs
= c_id
->resp
.nresphdrs
;
1202 * http_get_response_header - Get a line from the response header
1204 * ret = http_get_response_header(handle, whichline);
1207 * handle - Handle associated with the desired connection
1208 * whichline - Which line of the header to return. This must be between
1209 * zero and resp.nresphdrs which was returned by the call to
1210 * http_process_headers().
1213 * ptr - Points to a copy of the header line.
1214 * NULL - An error occurred. Check http_get_lasterr().
1217 http_get_response_header(http_handle_t handle
, uint_t which
)
1219 http_conn_t
*c_id
= handle
;
1222 if (!http_check_conn(c_id
))
1225 if (which
>= c_id
->resp
.nresphdrs
) {
1226 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_OORANGE
);
1230 res
= strdup(c_id
->resphdr
[which
]);
1232 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1239 * http_get_header_value - Get the value of a header line.
1241 * ret = http_get_header_value(handle, what);
1244 * handle - Handle associated with the desired connection
1245 * what - The field name to look up.
1248 * ptr - Points to a copy of the header value.
1249 * NULL - An error occurred. Check http_get_lasterr().
1252 http_get_header_value(http_handle_t handle
, const char *field_name
)
1254 http_conn_t
*c_id
= handle
;
1260 if (!http_check_conn(c_id
))
1263 if (field_name
== NULL
|| field_name
[0] == '\0') {
1264 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADARG
);
1268 for (i
= 0; i
< c_id
->resp
.nresphdrs
; i
++) {
1269 ptr
= c_id
->resphdr
[i
];
1270 n
= strlen(field_name
);
1271 if (strncasecmp(field_name
, ptr
, n
) == 0 && ptr
[n
] == ':') {
1274 while (isspace(*ptr
))
1279 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1285 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMATCH
);
1290 * http_read_body - Read the HTTP response body.
1292 * ret = http_read_body(handle, recv_buf_ptr, recv_buf_size);
1295 * handle - Handle associated with the relevant connection
1296 * recv_buf_ptr - Points to buffer to receive buffer
1297 * recv_buf_size - Length in bytes of buffer.
1300 * n - Number of bytes read..
1301 * < 0 - An error occurred. This is (the number of bytes gotten + 1),
1302 * negated. In other words, if 'n' bytes were read and then an
1303 * error occurred, this will return (-(n+1)). So zero bytes
1304 * were read and then an error occurs, this will return -1. If
1305 * 1 byte was read, it will return -2, etc. Specifics of the
1306 * error can be gotten using http_get_lasterr().
1308 * Note that the errors will be set in the http_conn_t struct before the
1309 * function which detected the error returns.
1312 http_read_body(http_handle_t handle
, char *recv_buf_ptr
, size_t recv_buf_size
)
1314 http_conn_t
*c_id
= handle
;
1317 if (!http_check_conn(c_id
))
1320 if (recv_buf_ptr
== NULL
|| recv_buf_size
== 0) {
1321 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADARG
);
1325 return (getbytes(c_id
, recv_buf_ptr
, recv_buf_size
));
1329 * http_srv_disconnect - Get rid of the connection to the server without
1330 * freeing the http_conn_t structure.
1332 * ret = http_srv_disconnect(handle);
1335 * handle - Handle associated with the connection
1339 * -1 - An error occurred. Specifics of the error can
1340 * be gotten using http_get_lasterr().
1343 http_srv_disconnect(http_handle_t handle
)
1345 http_conn_t
*c_id
= handle
;
1349 if (!http_check_conn(c_id
))
1352 err_ret
= free_ctx_ssl(c_id
);
1353 bzero(&c_id
->inbuf
, sizeof (c_id
->inbuf
));
1354 free_response(c_id
, B_TRUE
);
1360 * http_srv_close - Close the connection and clean up the http_conn_t
1363 * http_srv_close(handle);
1366 * handle - Handle associated with the desired connection
1370 * -1 - An error occurred. Specifics of the error can
1371 * be gotten using http_get_lasterr().
1374 http_srv_close(http_handle_t handle
)
1376 http_conn_t
*c_id
= handle
;
1379 if (!http_check_conn(c_id
))
1382 if (c_id
->ctx
!= NULL
|| c_id
->ssl
!= NULL
|| c_id
->fd
!= -1)
1383 err_ret
= http_srv_disconnect(handle
);
1385 free(c_id
->basic_auth_userid
);
1386 free(c_id
->basic_auth_password
);
1387 free(c_id
->resp
.statusmsg
);
1388 free(c_id
->client_cert_file
);
1389 free(c_id
->private_key_file
);
1390 free(c_id
->random_file
);
1391 free(c_id
->file_password
);
1392 c_id
->signature
= 0;
1399 * http_get_conn_info - Return current information about the connection
1401 * err = http_get_conn_info(handle);
1404 * handle - Handle associated with the connection in question
1407 * non_NULL- Points to structure
1408 * NULL - An error exists. Check http_get_lasterr().
1411 http_get_conn_info(http_handle_t handle
)
1413 http_conn_t
*c_id
= handle
;
1414 http_conninfo_t
*info
;
1416 if (!http_check_conn(c_id
))
1419 info
= malloc(sizeof (*info
));
1421 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1425 bzero(info
, sizeof (*info
));
1427 info
->uri
= c_id
->uri
;
1428 info
->proxy
= c_id
->proxy
;
1429 info
->keepalive
= c_id
->keepalive
;
1430 info
->read_timeout
= c_id
->read_timeout
;
1436 * http_get_lasterr - Return the next error on the last operation
1438 * err = http_get_lasterr(handle, errsrc);
1441 * handle - Handle associated with the connection in question
1442 * If no valid handle exists yet, this can be NULL.
1443 * However, it must be checked with the very next call.
1444 * errsrc - Returns the Sources of errors (ERRSRC_* values).
1447 * 0 - No error exists
1451 http_get_lasterr(http_handle_t handle
, uint_t
*errsrc
)
1453 http_conn_t
*c_id
= handle
;
1457 if (c_id
== NULL
|| c_id
->signature
!= HTTP_CONN_INFO
) {
1459 *errsrc
= ERRSRC_LIBHTTP
;
1465 GET_ERR(c_id
, src
, err
);
1466 if (src
== 0 && err
== 0) {
1468 *errsrc
= ERRSRC_LIBHTTP
;
1479 * http_decode_err - Decode a libssl error
1481 * err = http_decode_err(err, errlib, errfunc, errcode);
1484 * err - libssl/libcrypto error returned.
1485 * errlib - returns libssl/libcrypto sublibrary that caused the error
1486 * errfunc - returns function in that library
1487 * errcode - returns error code
1490 * None other than the above.
1493 http_decode_err(ulong_t err
, int *errlib
, int *errfunc
, int *errcode
)
1496 *errlib
= ERR_GET_LIB(err
);
1498 *errfunc
= ERR_GET_FUNC(err
);
1500 *errcode
= ERR_GET_REASON(err
);
1503 /* ---------------------- private functions ----------------------- */
1506 * http_req - Issue http request (either HEAD or GET)
1508 * ret = http_req(handle, abs_path, reqtype, curpos, len);
1511 * handle - Handle associated with the desired connection
1512 * abs_path- File name portion of the URI, beginning with a /. Query,
1513 * segment, etc are allowed.
1514 * type - HTTP_REQ_TYPE_HEAD or HTTP_REQ_TYPE_GET
1516 * In the case of GET requests,
1517 * curpos- -1 - Range not used
1518 * >=0 - Beginning of range
1519 * len - 0 - Range ends at the end of the file
1520 * >0 - Length of range.
1524 * -1 - An error occurred. Check http_get_lasterr().
1527 http_req(http_handle_t handle
, const char *abs_path
, http_req_t type
,
1528 offset_t curpos
, offset_t len
)
1530 http_conn_t
*c_id
= handle
;
1539 if (!http_check_conn(c_id
))
1542 if (abs_path
== NULL
|| abs_path
[0] == '\0') {
1543 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADARG
);
1547 /* Determine the name for the request type */
1549 case HTTP_REQ_TYPE_GET
:
1550 reqtypename
= "GET";
1551 if (curpos
< 0 && curpos
!= -1) {
1552 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADARG
);
1557 case HTTP_REQ_TYPE_HEAD
:
1558 reqtypename
= "HEAD";
1562 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADARG
);
1566 /* Do rudimentary checks on the absolute path */
1567 if (abs_path
== NULL
|| *abs_path
!= '/') {
1568 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADARG
);
1569 libbootlog(BOOTLOG_CRIT
, "http_req: invalid file path");
1570 if (abs_path
!= NULL
)
1571 libbootlog(BOOTLOG_CRIT
, " %s", abs_path
);
1574 (void) strlcpy(CONN_ABSPATH
, abs_path
, MAXHOSTNAMELEN
);
1580 * reqtypename + " http://" + host + ":" + port + path +
1583 * reqtypename + " " + path + " HTTP/1.1\r\n" +
1585 requestlen
= strlen(reqtypename
) + 8 + strlen(CONN_HOSTNAME
) + 1 +
1586 count_digits(CONN_PORT
) + strlen(CONN_ABSPATH
) + 11;
1590 * "Host: " + targethost + ":" + count_digits(port) + "\r\n" +
1591 * "Connection: Keep-Alive\r\n" plus trailing "\r\n\0"
1593 requestlen
+= 6 + strlen(CONN_HOSTNAME
) + 1 +
1594 count_digits(CONN_PORT
) + 2 + 24 + 3;
1595 if ((request
= malloc(requestlen
)) == NULL
) {
1596 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1600 /* The request line */
1601 if (c_id
->proxied
&& c_id
->ssl
== NULL
) {
1602 j
= snprintf(request
, requestlen
,
1603 "%s http://%s:%d%s HTTP/1.1\r\n",
1604 reqtypename
, CONN_HOSTNAME
, CONN_PORT
,
1607 j
= snprintf(request
, requestlen
, "%s %s HTTP/1.1\r\n",
1608 reqtypename
, CONN_ABSPATH
);
1611 /* Ancillary headers */
1612 j
+= snprintf(&request
[j
], requestlen
- j
, "Host: %s:%d\r\n",
1613 CONN_HOSTNAME
, CONN_PORT
);
1614 if (!c_id
->keepalive
)
1615 j
+= snprintf(&request
[j
], requestlen
- j
,
1616 "Connection: close\r\n");
1618 j
+= snprintf(&request
[j
], requestlen
- j
,
1619 "Connection: Keep-Alive\r\n");
1621 * We only send the range header on GET requests
1623 * "Range: bytes=" + from + "-" + end + "\r\n" or
1624 * "Range: bytes=" + from + "-" "\r\n"
1626 if (type
== HTTP_REQ_TYPE_GET
&& curpos
>= 0) {
1629 requestlen
+= 13 + count_digits(curpos
) + 1 + 2;
1631 endpos
= curpos
+ len
- 1;
1632 requestlen
+= count_digits(endpos
);
1635 if ((newreq
= realloc(request
, requestlen
)) == NULL
) {
1637 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1642 j
+= sprintf(&request
[j
], "Range: bytes=%lld-", curpos
);
1644 j
+= sprintf(&request
[j
], "%lld", endpos
);
1645 j
+= sprintf(&request
[j
], "\r\n");
1649 * Authorization is added only if provided (RFC 2617, Section 2)
1651 * "Authorization: Basic " + authencstr + "\r\n"
1653 if (c_id
->basic_auth_userid
&& c_id
->basic_auth_password
) {
1659 * Allow for concat(basic_auth_userid ":" basic_auth_password)
1661 authlen
= strlen(c_id
->basic_auth_userid
) + 2 +
1662 strlen(c_id
->basic_auth_password
);
1663 if ((authstr
= malloc(authlen
+ 1)) == NULL
) {
1665 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1668 (void) snprintf(authstr
, authlen
+ 1, "%s:%s",
1669 c_id
->basic_auth_userid
, c_id
->basic_auth_password
);
1671 /* 3 bytes encoded as 4 (round up) with null termination */
1672 if ((authencstr
= malloc((authlen
+ 2) / 3 * 4 + 1)) == NULL
) {
1675 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1679 (void) EVP_EncodeBlock((unsigned char *)authencstr
,
1680 (unsigned char *)authstr
, authlen
);
1683 * Finally do concat(Authorization: Basic " authencstr "\r\n")
1685 requestlen
+= 21 + strlen(authencstr
) + 2;
1686 if ((newreq
= realloc(request
, requestlen
)) == NULL
) {
1690 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
1695 j
+= snprintf(&request
[j
], requestlen
- j
,
1696 "Authorization: Basic %s\r\n", authencstr
);
1702 j
+= sprintf(&request
[j
], "\r\n");
1705 libbootlog(BOOTLOG_VERBOSE
, "%s", request
);
1707 /* send the HTTP request */
1708 retval
= http_srv_send(c_id
, request
, j
);
1712 /* Assume error in was set by send request. */
1720 * password_cb - Callback to get private key password and return it
1721 * to SSL. (Used for PEM certificates only.)
1723 * len = passwd_cb(buf, buflen, rwflag, userdata);
1726 * buf - Buffer for the password
1727 * buflen - Length of 'buf'
1728 * rwflag - password will be used for reading/decryption (== 0)
1729 * or writing/encryption (== 1).
1730 * userdata - Points to connection-specific information.
1733 * > 0 - Length of password that was put into 'buf'.
1734 * 0 - No password was returned (usually error occurred)
1736 * NOTE: The password code is not thread safe
1740 password_cb(char *buf
, int buflen
, int rwflag
, void *userdata
)
1742 http_conn_t
*c_id
= userdata
;
1744 if (c_id
== NULL
|| c_id
->signature
!= HTTP_CONN_INFO
)
1747 if (c_id
->file_password
== NULL
||
1748 buflen
< strlen(c_id
->file_password
) + 1)
1751 return (strlcpy(buf
, c_id
->file_password
, buflen
));
1755 * initialize_ctx - Initialize the context for a connection.
1757 * ctx = initialize_ctx(c_id);
1763 * non-NULL - Points to ctx structure.
1764 * NULL - An error occurred. Any cleanup is done and error
1765 * information is in the error stack.
1768 initialize_ctx(http_conn_t
*c_id
)
1770 #if OPENSSL_VERSION_NUMBER < 0x10000000L
1773 const SSL_METHOD
*meth
;
1779 /* Global system initialization */
1780 if (ssl_init
== 0) {
1782 SSL_load_error_strings();
1786 /* Create our context */
1787 meth
= SSLv3_client_method();
1788 if ((ctx
= SSL_CTX_new(meth
)) == NULL
) {
1790 while ((err
= ERR_get_error()) != 0)
1791 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1792 libbootlog(BOOTLOG_CRIT
,
1793 "initialize_ctx: SSL_CTX_new returned NULL");
1798 * Ensure that any renegotiations for blocking connections will
1799 * be done automatically. (The alternative is to return partial
1800 * reads to the caller and let it oversee the renegotiations.)
1802 if (SSL_CTX_set_mode(ctx
, SSL_MODE_AUTO_RETRY
) == 0) {
1804 while ((err
= ERR_get_error()) != 0)
1805 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1806 libbootlog(BOOTLOG_CRIT
,
1807 "initialize_ctx: SSL_CTX_set_mode returned 0");
1808 (void) SSL_CTX_free(ctx
);
1812 /* set cipher list if provided */
1813 if (cipher_list
!= NULL
) {
1814 if (!SSL_CTX_set_cipher_list(ctx
, cipher_list
)) {
1816 while ((err
= ERR_get_error()) != 0)
1817 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1818 libbootlog(BOOTLOG_CRIT
,
1819 "initialize_ctx: Error in cipher list");
1826 * We attempt to use the client_certificate_file for the private
1827 * key input scheme *only* in the absence of private_key_file. In
1828 * this instance the scheme will be the same as that used for the
1829 * certificate input.
1832 /* Load our certificates */
1833 if (c_id
->client_cert_file
!= NULL
) {
1835 /* Load pkcs12-formated files */
1836 if (sunw_p12_use_certfile(ctx
, c_id
->client_cert_file
,
1837 c_id
->file_password
)
1840 while ((err
= ERR_get_error()) != 0)
1841 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1842 libbootlog(BOOTLOG_CRIT
,
1843 "initialize_ctx: Couldn't read "
1844 "PKCS12 certificate file");
1849 /* Load PEM-formated files */
1850 if (SSL_CTX_use_certificate_file(ctx
,
1851 c_id
->client_cert_file
, SSL_FILETYPE_PEM
) <= 0) {
1853 while ((err
= ERR_get_error()) != 0)
1854 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1855 libbootlog(BOOTLOG_CRIT
,
1856 "initialize_ctx: Couldn't read "
1857 "PEM certificate file");
1862 if (c_id
->private_key_file
== NULL
)
1863 c_id
->private_key_file
= c_id
->client_cert_file
;
1868 /* Load pkcs12-formated files */
1869 if (c_id
->private_key_file
!= NULL
) {
1870 if (sunw_p12_use_keyfile(ctx
, c_id
->private_key_file
,
1871 c_id
->file_password
)
1874 while ((err
= ERR_get_error()) != 0)
1875 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1876 libbootlog(BOOTLOG_CRIT
,
1877 "initialize_ctx: Couldn't read "
1884 /* Load PEM-formated files */
1885 SSL_CTX_set_default_passwd_cb(ctx
, password_cb
);
1886 SSL_CTX_set_default_passwd_cb_userdata(ctx
, c_id
);
1887 if (c_id
->private_key_file
!= NULL
) {
1888 if (SSL_CTX_use_PrivateKey_file(ctx
,
1889 c_id
->private_key_file
, SSL_FILETYPE_PEM
) <= 0) {
1891 while ((err
= ERR_get_error()) != 0)
1892 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1893 libbootlog(BOOTLOG_CRIT
,
1894 "initialize_ctx: Couldn't read "
1902 /* Load the CAs we trust */
1903 if (ca_verify_file
!= NULL
) {
1905 if (sunw_p12_use_trustfile(ctx
, ca_verify_file
,
1906 c_id
->file_password
)
1909 while ((err
= ERR_get_error()) != 0)
1910 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1911 libbootlog(BOOTLOG_CRIT
,
1912 "initialize_ctx: Couldn't read "
1913 "PKCS12 CA list file");
1918 if (SSL_CTX_load_verify_locations(ctx
, ca_verify_file
,
1921 while ((err
= ERR_get_error()) != 0)
1922 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1923 libbootlog(BOOTLOG_CRIT
,
1924 "initialize_ctx: Couldn't read PEM"
1932 SSL_CTX_set_verify_depth(ctx
, verify_depth
);
1934 /* Load randomness */
1935 if (c_id
->random_file
!= NULL
&&
1936 RAND_load_file(c_id
->random_file
, 1024 * 1024) <= 0) {
1938 while ((err
= ERR_get_error()) != 0)
1939 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1940 libbootlog(BOOTLOG_CRIT
,
1941 "initialize_ctx: Couldn't load random file");
1945 if (RAND_status() <= 0) {
1947 while ((err
= ERR_get_error()) != 0)
1948 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
1949 libbootlog(BOOTLOG_CRIT
,
1950 "initialize_ctx: PRNG not seeded");
1959 * tcp_connect - Set up a TCP connection.
1961 * sock = tcp_connect(c_id, hostname, port);
1964 * c_id - Structure associated with the desired connection
1965 * hostname - the host to connect to
1966 * port - the port to connect to
1969 * >= 0 - Socket number.
1970 * -1 - Error occurred. Error information is set in the
1971 * error stack. Any cleanup is done.
1973 * This function established a connection to the target host. When
1974 * it returns, the connection is ready for a HEAD or GET request.
1977 tcp_connect(http_conn_t
*c_id
, const char *hostname
, uint16_t port
)
1980 struct sockaddr_in addr
;
1984 if ((hp
= gethostbyname(hostname
)) == NULL
) {
1985 SET_ERR(c_id
, ERRSRC_RESOLVE
, h_errno
);
1989 bzero(&addr
, sizeof (addr
));
1991 addr
.sin_addr
= *(struct in_addr
*)hp
->h_addr
;
1992 addr
.sin_family
= AF_INET
;
1993 addr
.sin_port
= htons(port
);
1995 if ((sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0) {
1996 SET_ERR(c_id
, ERRSRC_SYSTEM
, errno
);
2000 status
= connect(sock
, (struct sockaddr
*)&addr
, sizeof (addr
));
2002 SET_ERR(c_id
, ERRSRC_SYSTEM
, errno
);
2003 (void) socket_close(sock
);
2007 c_id
->host_addr
= addr
; /* save for future sendto calls */
2014 * readline - Get a line from the socket. Discard the end-of-line
2015 * (CR or CR/LF or LF).
2017 * ret = readline(c_id, sock, buf, len);
2020 * c_id - Structure associated with the desired connection
2021 * sock - Socket to read
2022 * buf - Buffer for the line
2023 * len - Length of the buffer
2026 * 0 - Success. 'buf' contains the line.
2027 * -1 - Error occurred. Error information is set in the
2031 readline(http_conn_t
*c_id
, int sock
, char *buf
, int len
)
2036 for (n
= 0; n
< len
; n
++) {
2037 r
= socket_read(sock
, ptr
, 1, c_id
->read_timeout
);
2040 SET_ERR(c_id
, ERRSRC_SYSTEM
, errno
);
2042 } else if (r
== 0) {
2043 libbootlog(BOOTLOG_WARNING
, "Readline: no data");
2050 /* Strip off the CR if it's there */
2051 if (buf
[n
-1] == '\r') {
2062 libbootlog(BOOTLOG_WARNING
, "readline: Buffer too short\n");
2067 * proxy_connect - Set up a proxied TCP connection to the target host.
2069 * sock = proxy_connect(c_id);
2072 * c_id - Structure associated with the desired connection
2075 * >= 0 - Socket number.
2076 * -1 - Error occurred. Error information is set in the
2077 * error stack. Any cleanup is done.
2079 * This function established a connection to the proxy and then sends
2080 * the request to connect to the target host. It reads the response
2081 * (the status line and any headers). When it returns, the connection
2082 * is ready for a HEAD or GET request.
2085 proxy_connect(http_conn_t
*c_id
)
2087 struct sockaddr_in addr
;
2093 if ((sock
= tcp_connect(c_id
, CONN_PROXY_HOSTNAME
,
2094 CONN_PROXY_PORT
)) < 0) {
2102 /* Now that we're connected, do the proxy request */
2103 (void) snprintf(buf
, sizeof (buf
),
2104 "CONNECT %s:%d HTTP/1.0\r\n\r\n", CONN_HOSTNAME
, CONN_PORT
);
2106 /* socket_write sets the errors */
2107 if (socket_write(sock
, buf
, strlen(buf
), &addr
) <= 0) {
2108 SET_ERR(c_id
, ERRSRC_SYSTEM
, errno
);
2109 (void) socket_close(sock
);
2113 /* And read the response */
2114 i
= readline(c_id
, sock
, buf
, sizeof (buf
));
2117 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NORESP
);
2118 libbootlog(BOOTLOG_CRIT
,
2119 "proxy_connect: Empty response from proxy");
2120 (void) socket_close(sock
);
2125 if (strncmp(ptr
, "HTTP", 4) != 0) {
2126 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOT_1_1
);
2127 libbootlog(BOOTLOG_CRIT
,
2128 "proxy_connect: Unrecognized protocol");
2129 (void) socket_close(sock
);
2133 /* skip to the code */
2135 while (*ptr
!= ' ' && *ptr
!= '\0')
2137 while (*ptr
== ' ' && *ptr
!= '\0')
2140 /* make sure it's three digits */
2141 if (strncmp(ptr
, "200", 3) != 0) {
2142 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADRESP
);
2143 libbootlog(BOOTLOG_CRIT
,
2144 "proxy_connect: Received error from proxy server");
2145 (void) socket_close(sock
);
2149 if (isdigit(*ptr
)) {
2150 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADRESP
);
2151 (void) socket_close(sock
);
2155 /* Look for the blank line that signals end of proxy header */
2156 while ((i
= readline(c_id
, sock
, buf
, sizeof (buf
))) > 0)
2160 (void) socket_close(sock
);
2168 * check_cert_chain - Check if we have a valid certificate chain.
2170 * ret = check_cert_chain(c_id, host);
2173 * c_id - Connection info.
2174 * host - Name to compare with the common name in the certificate.
2177 * 0 - Certificate chain and common name are both OK.
2178 * -1 - Certificate chain and/or common name is not valid.
2181 check_cert_chain(http_conn_t
*c_id
, char *host
)
2187 if ((verify_err
= SSL_get_verify_result(c_id
->ssl
)) != X509_V_OK
) {
2188 SET_ERR(c_id
, ERRSRC_VERIFERR
, verify_err
);
2189 libbootlog(BOOTLOG_CRIT
,
2190 "check_cert_chain: Certificate doesn't verify");
2195 * Check the cert chain. The chain length
2196 * is automatically checked by OpenSSL when we
2197 * set the verify depth in the ctx
2199 * All we need to do here is check that the CN
2203 /* Check the common name */
2204 if ((peer
= SSL_get_peer_certificate(c_id
->ssl
)) == NULL
) {
2205 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOCERT
);
2206 libbootlog(BOOTLOG_CRIT
,
2207 "check_cert_chain: Peer did not present a certificate");
2210 (void) X509_NAME_get_text_by_NID(X509_get_subject_name(peer
),
2211 NID_commonName
, peer_CN
, 256);
2214 libbootlog(BOOTLOG_VERBOSE
,
2215 "server cert's peer_CN is %s, host is %s", peer_CN
, host
);
2217 if (strcasecmp(peer_CN
, host
)) {
2218 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMATCH
);
2219 libbootlog(BOOTLOG_CRIT
,
2220 "check_cert_chain: Common name doesn't match host name");
2221 libbootlog(BOOTLOG_CRIT
,
2222 "peer_CN = %s, host = %s", peer_CN
, host
);
2230 * print_ciphers - Print the list of ciphers for debugging.
2232 * print_ciphers(ssl);
2235 * ssl - SSL connection.
2241 print_ciphers(SSL
*ssl
)
2244 STACK_OF(SSL_CIPHER
) *sk
;
2251 sk
= SSL_get_ciphers(ssl
);
2255 for (i
= 0; i
< sk_SSL_CIPHER_num(sk
); i
++) {
2257 c
= sk_SSL_CIPHER_value(sk
, i
);
2258 libbootlog(BOOTLOG_VERBOSE
, "%08lx %s", c
->id
, c
->name
);
2260 name
= SSL_get_cipher_name(ssl
);
2263 libbootlog(BOOTLOG_VERBOSE
, "Current cipher = %s", name
);
2267 * read_headerlines - Get the header lines from the server. This reads
2268 * lines until it gets a empty line indicating end of headers.
2270 * ret = read_headerlines(c_id);
2273 * c_id - Info about the connection being read.
2274 * bread - TRUE if the headerlines are part of the message body.
2277 * 0 - Header lines were read.
2278 * -1 - Error occurred. The errors information is already in
2281 * Read the lines. If the current line begins with a space or tab, it is
2282 * a continuation. Take the new line and append it to the end of the
2283 * previous line rather than making an entry for another line in
2286 * Note that I/O errors are put into the error stack by http_srv_recv(),
2287 * which is called by getaline().
2290 read_headerlines(http_conn_t
*c_id
, boolean_t bread
)
2292 char line
[MAXHOSTNAMELEN
];
2299 /* process headers, stop when we get to an empty line */
2302 while ((n
= getaline(c_id
, line
, sizeof (line
), bread
)) > 0) {
2305 libbootlog(BOOTLOG_VERBOSE
,
2306 "read_headerlines: %s", line
);
2308 * See if this is a continuation line (first col is a
2311 if (line
[0] != ' ' && line
[0] != ' ') {
2315 realloc(c_id
->resphdr
, (cur
+ 1) * sizeof (void *));
2316 if (new_buf
== NULL
) {
2317 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
2320 c_id
->resphdr
= new_buf
;
2322 c_id
->resphdr
[cur
] = strdup(line
);
2323 if (c_id
->resphdr
[cur
] == NULL
) {
2324 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
2329 while (isspace(*ptr
))
2331 c_id
->resphdr
[cur
] = realloc(c_id
->resphdr
[cur
],
2332 strlen(c_id
->resphdr
[cur
]) + strlen(ptr
) + 1);
2333 if (c_id
->resphdr
[cur
] == NULL
) {
2334 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOMEM
);
2337 (void) strcat(c_id
->resphdr
[cur
], ptr
);
2339 ptr
= &(c_id
->resphdr
[cur
][strlen(c_id
->resphdr
[cur
]) - 1]);
2340 while (ptr
> c_id
->resphdr
[cur
] && isspace(*ptr
))
2343 c_id
->resp
.nresphdrs
= next
;
2345 /* Cause of any I/O error was already put into error stack. */
2346 return (n
>= 0 ? 0 : -1);
2350 free_response(http_conn_t
*c_id
, int free_boundary
)
2354 /* free memory from previous calls */
2355 if (c_id
->resp
.statusmsg
!= NULL
) {
2356 free(c_id
->resp
.statusmsg
);
2357 c_id
->resp
.statusmsg
= NULL
;
2359 for (i
= 0; i
< c_id
->resp
.nresphdrs
; i
++) {
2360 free(c_id
->resphdr
[i
]);
2361 c_id
->resphdr
[i
] = NULL
;
2363 c_id
->resp
.nresphdrs
= 0;
2364 if (c_id
->resphdr
!= NULL
) {
2365 free(c_id
->resphdr
);
2366 c_id
->resphdr
= NULL
;
2369 if (free_boundary
&& c_id
->boundary
) {
2370 free(c_id
->boundary
);
2371 c_id
->boundary
= NULL
;
2372 c_id
->is_multipart
= B_FALSE
;
2377 free_ctx_ssl(http_conn_t
*c_id
)
2381 if (c_id
->ssl
!= NULL
) {
2382 if (SSL_shutdown(c_id
->ssl
) <= 0) {
2384 while ((err
= ERR_get_error()) != 0)
2385 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
2388 SSL_free(c_id
->ssl
);
2392 if (c_id
->fd
!= -1 && socket_close(c_id
->fd
) < 0) {
2393 SET_ERR(c_id
, ERRSRC_SYSTEM
, errno
);
2398 if (c_id
->ctx
!= NULL
) {
2399 SSL_CTX_free(c_id
->ctx
);
2407 * get_chunk_header - Get a chunk header line
2410 * c_id - Structure describing the connection in question.
2413 * >=0 - Length of next chunk
2414 * -1 - Error occurred. The error information is in the error stack.
2417 get_chunk_header(http_conn_t
*c_id
)
2419 char line
[MAXHOSTNAMELEN
];
2426 * Determine whether an extra crlf pair will precede the
2427 * chunk header. For the first one, there is no preceding
2428 * crlf. For later chunks, there is one crlf.
2430 if (c_id
->is_firstchunk
) {
2432 c_id
->is_firstchunk
= B_FALSE
;
2434 ok
= ((i
= getaline(c_id
, line
, sizeof (line
), B_FALSE
)) == 0);
2438 i
= getaline(c_id
, line
, sizeof (line
), B_FALSE
);
2441 * If I/O error, the Cause was already put into
2442 * error stack. This is an additional error.
2444 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_NOHEADER
);
2449 libbootlog(BOOTLOG_VERBOSE
, "get_chunk_header: <%s>", line
);
2453 * The first (and probably only) field in the line is the hex
2454 * length of the chunk.
2458 while (*ptr
!= '\0' && (i
= hexdigit(*ptr
)) >= 0) {
2459 value
= (value
<< 4) + i
;
2467 * init_bread - Initialize the counters used to read message bodies.
2470 * c_id - Structure describing the connection in question.
2474 * -1 - Error occurred. The error information is in the error stack.
2476 * This routine will determine whether the message body being received is
2477 * chunked or non-chunked. Once determined, the counters used to read
2478 * message bodies will be initialized.
2481 init_bread(http_conn_t
*c_id
)
2485 boolean_t sized
= B_FALSE
;
2488 * Assume non-chunked reads until proven otherwise.
2490 c_id
->is_chunked
= B_FALSE
;
2491 c_id
->is_firstchunk
= B_FALSE
;
2492 hdr
= http_get_header_value(c_id
, "Content-Length");
2494 c_id
->body_size
= strtol(hdr
, NULL
, 10);
2495 if (c_id
->body_size
== 0 && errno
!= 0) {
2497 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADSIZE
);
2505 * If size was not determined above, then see if this is a
2506 * chunked message. Keep in mind that the first chunk size is
2510 hdr
= http_get_header_value(c_id
, "Transfer-Encoding");
2513 if (startswith((const char **)&ptr
, "chunked;") ||
2514 strcasecmp(ptr
, "chunked") == 0) {
2515 c_id
->is_firstchunk
= B_TRUE
;
2516 c_id
->is_chunked
= B_TRUE
;
2519 if (c_id
->is_chunked
) {
2520 c_id
->body_size
= get_chunk_header(c_id
);
2521 if (c_id
->body_size
== -1) {
2523 * Error stack was already set at a
2534 * Well, isn't this a fine predicament? It wasn't chunked or
2535 * non-chunked as far as we can tell.
2538 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_BADSIZE
);
2542 c_id
->body_read
= 0;
2543 c_id
->body_size_tot
= c_id
->body_size
;
2544 c_id
->body_read_tot
= 0;
2550 * get_msgcnt - Get the number of bytes left in the message body or chunk.
2553 * c_id - Structure describing the connection in question.
2554 * msgcnt - Where to store the message count.
2558 * -1 - Error occurred. The error information is in the error stack.
2560 * Note that if the message being read is not chunked, then the byte count
2561 * is simply the message size minus the bytes read thus far. In the case of
2562 * chunked messages, the byte count returned will be the number of bytes
2563 * left in the chunk. If the current chunk has been exhausted, then this
2564 * routine will determine the size of the next chunk. When the next chunk
2565 * size is zero, the message has been read in its entirety.
2568 get_msgcnt(http_conn_t
*c_id
, ssize_t
*msgcnt
)
2571 * If there are more bytes in the message, then return.
2573 *msgcnt
= c_id
->body_size
- c_id
->body_read
;
2578 * If this is not a chunked message and the body has been
2579 * read, then we're done.
2581 if (!c_id
->is_chunked
) {
2586 * We're looking at a chunked message whose immediate
2587 * chunk has been totally processed. See if there is
2590 c_id
->body_size
= get_chunk_header(c_id
);
2591 if (c_id
->body_size
== -1) {
2593 * Error stack was already set at a
2600 * No bytes of this chunk have been processed yet.
2602 c_id
->body_read
= 0;
2605 * A zero length chunk signals the end of the
2606 * message body and chunking.
2608 if (c_id
->body_size
== 0) {
2609 c_id
->is_chunked
= B_FALSE
;
2614 * There is another chunk.
2616 c_id
->body_size_tot
+= c_id
->body_size
;
2617 *msgcnt
= c_id
->body_size
- c_id
->body_read
;
2623 * getaline - Get lines of data from the HTTP response, up to 'len' bytes.
2624 * NOTE: the line will not end with a NULL if all 'len' bytes
2628 * c_id - Structure describing the connection in question.
2629 * line - Where to store the data.
2630 * len - Maximum number of bytes in the line.
2631 * bread - TRUE if the lines are part of the message body.
2634 * >=0 - The number of bytes successfully read.
2635 * <0 - An error occurred. This is (the number of bytes gotten + 1),
2636 * negated. In other words, if 'n' bytes were read and then an
2637 * error occurred, this will return (-(n+1)). So zero bytes read
2638 * and then an error occurs, this will return -1. If 1 bytes
2639 * was read, it will return -2, etc.
2641 * Specifics of the error can be gotten using http_get_lasterr();
2643 * Note that I/O errors are put into the error stack by http_srv_recv().1
2646 getaline(http_conn_t
*c_id
, char *line
, int len
, boolean_t bread
)
2654 * Special processing required for message body reads.
2658 * See if there is another chunk. Obviously, in the
2659 * case of non-chunked messages, there won't be.
2660 * But in either case, chunked or not, if msgcnt
2661 * is still zero after the call to get_msgcnt(),
2665 if (get_msgcnt(c_id
, &msgcnt
) == -1) {
2672 cnt
= MIN(msgcnt
, sizeof (c_id
->inbuf
.buf
));
2674 cnt
= sizeof (c_id
->inbuf
.buf
);
2677 /* read more data if buffer empty */
2678 if (c_id
->inbuf
.i
== c_id
->inbuf
.n
) {
2680 c_id
->inbuf
.n
= http_srv_recv(c_id
, c_id
->inbuf
.buf
,
2682 if (c_id
->inbuf
.n
== 0) {
2685 if (c_id
->inbuf
.n
< 0) {
2690 if (c_id
->inbuf
.buf
[c_id
->inbuf
.i
] == '\r') {
2691 INC_BREAD_CNT(bread
, msgcnt
);
2695 if (c_id
->inbuf
.buf
[c_id
->inbuf
.i
] == '\n') {
2696 INC_BREAD_CNT(bread
, msgcnt
);
2701 /* copy buf from internal buffer */
2702 INC_BREAD_CNT(bread
, msgcnt
);
2703 line
[i
++] = c_id
->inbuf
.buf
[c_id
->inbuf
.i
++];
2709 * getbytes - Get a block from the HTTP response. Used for the HTTP body.
2712 * c_id - Structure describing the connection in question.
2713 * line - Where to store the data.
2714 * len - Maximum number of bytes in the block.
2717 * >=0 - The number of bytes successfully read.
2718 * <0 - An error occurred. This is (the number of bytes gotten + 1),
2719 * negated. In other words, if 'n' bytes were read and then an
2720 * error occurred, this will return (-(n+1)). So zero bytes read
2721 * and then an error occurs, this will return -1. If 1 bytes
2722 * was read, it will return -2, etc.
2724 * Specifics of the error can be gotten using http_get_lasterr();
2726 * Note that all reads performed here assume that a message body is being
2727 * read. If this changes in the future, then the logic should more closely
2728 * resemble getaline().
2730 * Note that I/O errors are put into the error stack by http_srv_recv().
2733 getbytes(http_conn_t
*c_id
, char *line
, int len
)
2742 * See if there is another chunk. Obviously, in the
2743 * case of non-chunked messages, there won't be.
2744 * But in either case, chunked or not, if msgcnt
2745 * is still zero after the call to get_msgcnt(), then
2749 if (get_msgcnt(c_id
, &msgcnt
) == -1) {
2757 cnt
= MIN(msgcnt
, len
- i
);
2759 if (c_id
->inbuf
.n
!= c_id
->inbuf
.i
) {
2760 nbytes
= (int)MIN(cnt
, c_id
->inbuf
.n
- c_id
->inbuf
.i
);
2761 (void) memcpy(line
, &c_id
->inbuf
.buf
[c_id
->inbuf
.i
],
2763 c_id
->inbuf
.i
+= nbytes
;
2765 nbytes
= http_srv_recv(c_id
, line
, cnt
);
2777 c_id
->body_read
+= nbytes
;
2778 c_id
->body_read_tot
+= nbytes
;
2785 http_srv_send(http_conn_t
*c_id
, const void *buf
, size_t nbyte
)
2789 if (c_id
->ssl
!= NULL
) {
2790 if ((retval
= SSL_write(c_id
->ssl
, buf
, nbyte
)) <= 0) {
2791 handle_ssl_error(c_id
, retval
);
2795 retval
= socket_write(c_id
->fd
, buf
, nbyte
, &c_id
->host_addr
);
2797 SET_ERR(c_id
, ERRSRC_SYSTEM
, errno
);
2805 http_srv_recv(http_conn_t
*c_id
, void *buf
, size_t nbyte
)
2809 if (c_id
->ssl
!= NULL
) {
2810 if ((retval
= SSL_read(c_id
->ssl
, buf
, nbyte
)) <= 0) {
2811 handle_ssl_error(c_id
, retval
);
2815 retval
= socket_read(c_id
->fd
, buf
, nbyte
, c_id
->read_timeout
);
2817 SET_ERR(c_id
, ERRSRC_SYSTEM
, errno
);
2825 http_check_conn(http_conn_t
*c_id
)
2828 if (c_id
== NULL
|| c_id
->signature
!= HTTP_CONN_INFO
) {
2829 early_err
= EHTTP_BADARG
;
2837 handle_ssl_error(http_conn_t
*c_id
, int retval
)
2841 err
= SSL_get_error(c_id
->ssl
, retval
);
2844 case SSL_ERROR_NONE
:
2847 case SSL_ERROR_ZERO_RETURN
:
2848 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_CONCLOSED
);
2851 case SSL_ERROR_WANT_READ
:
2852 case SSL_ERROR_WANT_WRITE
:
2853 case SSL_ERROR_WANT_CONNECT
:
2854 case SSL_ERROR_WANT_X509_LOOKUP
:
2855 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_UNEXPECTED
);
2858 case SSL_ERROR_SYSCALL
:
2859 err
= ERR_get_error();
2861 SET_ERR(c_id
, ERRSRC_LIBHTTP
, EHTTP_EOFERR
);
2862 else if (err
== (ulong_t
)-1)
2863 SET_ERR(c_id
, ERRSRC_SYSTEM
, errno
);
2865 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
2866 while ((err
= ERR_get_error()) != 0)
2867 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
2872 while ((err
= ERR_get_error()) != 0) {
2873 SET_ERR(c_id
, ERRSRC_LIBSSL
, err
);
2880 count_digits(int value
)
2899 if (ch
>= '0' && ch
<= '9')
2901 if (ch
>= 'A' && ch
<= 'F')
2902 return (ch
- 'A' + 10);
2903 if (ch
>= 'a' && ch
<= 'f')
2904 return (ch
- 'a' + 10);
2909 eat_ws(const char *buf
)
2911 char *ptr
= (char *)buf
;
2913 while (isspace(*ptr
))
2920 startswith(const char **strp
, const char *starts
)
2922 int len
= strlen(starts
);
2924 if (strncasecmp(*strp
, starts
, len
) == 0) {