|
@@ -731,27 +731,56 @@ static void http_socket_close ( struct http_request *http, int rc ) {
|
731
|
731
|
}
|
732
|
732
|
|
733
|
733
|
/**
|
734
|
|
- * HTTP process
|
|
734
|
+ * Generate HTTP Basic authorisation string
|
735
|
735
|
*
|
736
|
736
|
* @v http HTTP request
|
|
737
|
+ * @ret auth Authorisation string, or NULL on error
|
|
738
|
+ *
|
|
739
|
+ * The authorisation string is dynamically allocated, and must be
|
|
740
|
+ * freed by the caller.
|
737
|
741
|
*/
|
738
|
|
-static void http_step ( struct http_request *http ) {
|
739
|
|
- const char *host = http->uri->host;
|
|
742
|
+static char * http_basic_auth ( struct http_request *http ) {
|
740
|
743
|
const char *user = http->uri->user;
|
741
|
744
|
const char *password =
|
742
|
745
|
( http->uri->password ? http->uri->password : "" );
|
743
|
|
- size_t user_pw_len = ( user ? ( strlen ( user ) + 1 /* ":" */ +
|
744
|
|
- strlen ( password ) ) : 0 );
|
|
746
|
+ size_t user_pw_len =
|
|
747
|
+ ( strlen ( user ) + 1 /* ":" */ + strlen ( password ) );
|
|
748
|
+ char user_pw[ user_pw_len + 1 /* NUL */ ];
|
745
|
749
|
size_t user_pw_base64_len = base64_encoded_len ( user_pw_len );
|
746
|
|
- int request_len = unparse_uri ( NULL, 0, http->uri,
|
747
|
|
- URI_PATH_BIT | URI_QUERY_BIT );
|
748
|
|
- struct {
|
749
|
|
- uint8_t user_pw[ user_pw_len + 1 /* NUL */ ];
|
750
|
|
- char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
|
751
|
|
- char request[ request_len + 1 /* NUL */ ];
|
752
|
|
- char range[48]; /* Enough for two 64-bit integers in decimal */
|
753
|
|
- } *dynamic;
|
754
|
|
- int partial;
|
|
750
|
+ char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
|
|
751
|
+ char *auth;
|
|
752
|
+ int len;
|
|
753
|
+
|
|
754
|
+ /* Sanity check */
|
|
755
|
+ assert ( user != NULL );
|
|
756
|
+
|
|
757
|
+ /* Make "user:password" string from decoded fields */
|
|
758
|
+ snprintf ( user_pw, sizeof ( user_pw ), "%s:%s", user, password );
|
|
759
|
+
|
|
760
|
+ /* Base64-encode the "user:password" string */
|
|
761
|
+ base64_encode ( ( void * ) user_pw, user_pw_len, user_pw_base64 );
|
|
762
|
+
|
|
763
|
+ /* Generate the authorisation string */
|
|
764
|
+ len = asprintf ( &auth, "Authorization: Basic %s\r\n",
|
|
765
|
+ user_pw_base64 );
|
|
766
|
+ if ( len < 0 )
|
|
767
|
+ return NULL;
|
|
768
|
+
|
|
769
|
+ return auth;
|
|
770
|
+}
|
|
771
|
+
|
|
772
|
+/**
|
|
773
|
+ * HTTP process
|
|
774
|
+ *
|
|
775
|
+ * @v http HTTP request
|
|
776
|
+ */
|
|
777
|
+static void http_step ( struct http_request *http ) {
|
|
778
|
+ size_t uri_len;
|
|
779
|
+ char *method;
|
|
780
|
+ char *uri;
|
|
781
|
+ char *range;
|
|
782
|
+ char *auth;
|
|
783
|
+ int len;
|
755
|
784
|
int rc;
|
756
|
785
|
|
757
|
786
|
/* Do nothing if we have already transmitted the request */
|
|
@@ -762,74 +791,84 @@ static void http_step ( struct http_request *http ) {
|
762
|
791
|
if ( ! xfer_window ( &http->socket ) )
|
763
|
792
|
return;
|
764
|
793
|
|
765
|
|
- /* Allocate dynamic storage */
|
766
|
|
- dynamic = malloc ( sizeof ( *dynamic ) );
|
767
|
|
- if ( ! dynamic ) {
|
768
|
|
- rc = -ENOMEM;
|
769
|
|
- goto err_alloc;
|
|
794
|
+ /* Force a HEAD request if we have nowhere to send any received data */
|
|
795
|
+ if ( ( xfer_window ( &http->xfer ) == 0 ) &&
|
|
796
|
+ ( http->rx_buffer == UNULL ) ) {
|
|
797
|
+ http->flags |= ( HTTP_HEAD_ONLY | HTTP_CLIENT_KEEPALIVE );
|
770
|
798
|
}
|
771
|
799
|
|
772
|
|
- /* Construct path?query request */
|
773
|
|
- unparse_uri ( dynamic->request, sizeof ( dynamic->request ), http->uri,
|
774
|
|
- URI_PATH_BIT | URI_QUERY_BIT );
|
|
800
|
+ /* Determine method */
|
|
801
|
+ method = ( ( http->flags & HTTP_HEAD_ONLY ) ? "HEAD" : "GET" );
|
775
|
802
|
|
776
|
|
- /* Construct authorisation, if applicable */
|
777
|
|
- if ( user ) {
|
778
|
|
- /* Make "user:password" string from decoded fields */
|
779
|
|
- snprintf ( ( ( char * ) dynamic->user_pw ),
|
780
|
|
- sizeof ( dynamic->user_pw ), "%s:%s",
|
781
|
|
- user, password );
|
782
|
|
-
|
783
|
|
- /* Base64-encode the "user:password" string */
|
784
|
|
- base64_encode ( dynamic->user_pw, user_pw_len,
|
785
|
|
- dynamic->user_pw_base64 );
|
|
803
|
+ /* Construct path?query request */
|
|
804
|
+ uri_len = ( unparse_uri ( NULL, 0, http->uri,
|
|
805
|
+ URI_PATH_BIT | URI_QUERY_BIT )
|
|
806
|
+ + 1 /* possible "/" */ + 1 /* NUL */ );
|
|
807
|
+ uri = malloc ( uri_len );
|
|
808
|
+ if ( ! uri ) {
|
|
809
|
+ rc = -ENOMEM;
|
|
810
|
+ goto err_uri;
|
|
811
|
+ }
|
|
812
|
+ unparse_uri ( uri, uri_len, http->uri, URI_PATH_BIT | URI_QUERY_BIT );
|
|
813
|
+ if ( ! uri[0] ) {
|
|
814
|
+ uri[0] = '/';
|
|
815
|
+ uri[1] = '\0';
|
786
|
816
|
}
|
787
|
817
|
|
788
|
|
- /* Force a HEAD request if we have nowhere to send any received data */
|
789
|
|
- if ( ( xfer_window ( &http->xfer ) == 0 ) &&
|
790
|
|
- ( http->rx_buffer == UNULL ) ) {
|
791
|
|
- http->flags |= ( HTTP_HEAD_ONLY | HTTP_CLIENT_KEEPALIVE );
|
|
818
|
+ /* Calculate range request parameters if applicable */
|
|
819
|
+ if ( http->partial_len ) {
|
|
820
|
+ len = asprintf ( &range, "Range: bytes=%zd-%zd\r\n",
|
|
821
|
+ http->partial_start,
|
|
822
|
+ ( http->partial_start + http->partial_len
|
|
823
|
+ - 1 ) );
|
|
824
|
+ if ( len < 0 ) {
|
|
825
|
+ rc = len;
|
|
826
|
+ goto err_range;
|
|
827
|
+ }
|
|
828
|
+ } else {
|
|
829
|
+ range = NULL;
|
792
|
830
|
}
|
793
|
831
|
|
794
|
|
- /* Determine type of request */
|
795
|
|
- partial = ( http->partial_len != 0 );
|
796
|
|
- snprintf ( dynamic->range, sizeof ( dynamic->range ),
|
797
|
|
- "%zd-%zd", http->partial_start,
|
798
|
|
- ( http->partial_start + http->partial_len - 1 ) );
|
|
832
|
+ /* Construct authorisation, if applicable */
|
|
833
|
+ if ( http->uri->user ) {
|
|
834
|
+ auth = http_basic_auth ( http );
|
|
835
|
+ if ( ! auth ) {
|
|
836
|
+ rc = -ENOMEM;
|
|
837
|
+ goto err_auth;
|
|
838
|
+ }
|
|
839
|
+ } else {
|
|
840
|
+ auth = NULL;
|
|
841
|
+ }
|
799
|
842
|
|
800
|
843
|
/* Mark request as transmitted */
|
801
|
844
|
http->flags &= ~HTTP_TX_PENDING;
|
802
|
845
|
|
803
|
|
- /* Send GET request */
|
|
846
|
+ /* Send request */
|
804
|
847
|
if ( ( rc = xfer_printf ( &http->socket,
|
805
|
|
- "%s %s%s HTTP/1.1\r\n"
|
|
848
|
+ "%s %s HTTP/1.1\r\n"
|
806
|
849
|
"User-Agent: iPXE/" VERSION "\r\n"
|
807
|
850
|
"Host: %s%s%s\r\n"
|
808
|
|
- "%s%s%s%s%s%s%s"
|
|
851
|
+ "%s%s%s"
|
809
|
852
|
"\r\n",
|
810
|
|
- ( ( http->flags & HTTP_HEAD_ONLY ) ?
|
811
|
|
- "HEAD" : "GET" ),
|
812
|
|
- ( http->uri->path ? "" : "/" ),
|
813
|
|
- dynamic->request, host,
|
|
853
|
+ method, uri, http->uri->host,
|
814
|
854
|
( http->uri->port ?
|
815
|
855
|
":" : "" ),
|
816
|
856
|
( http->uri->port ?
|
817
|
857
|
http->uri->port : "" ),
|
818
|
858
|
( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ?
|
819
|
859
|
"Connection: keep-alive\r\n" : "" ),
|
820
|
|
- ( partial ? "Range: bytes=" : "" ),
|
821
|
|
- ( partial ? dynamic->range : "" ),
|
822
|
|
- ( partial ? "\r\n" : "" ),
|
823
|
|
- ( user ?
|
824
|
|
- "Authorization: Basic " : "" ),
|
825
|
|
- ( user ? dynamic->user_pw_base64 : "" ),
|
826
|
|
- ( user ? "\r\n" : "" ) ) ) != 0 ) {
|
|
860
|
+ ( range ? range : "" ),
|
|
861
|
+ ( auth ? auth : "" ) ) ) != 0 ) {
|
827
|
862
|
goto err_xfer;
|
828
|
863
|
}
|
829
|
864
|
|
830
|
865
|
err_xfer:
|
831
|
|
- free ( dynamic );
|
832
|
|
- err_alloc:
|
|
866
|
+ free ( auth );
|
|
867
|
+ err_auth:
|
|
868
|
+ free ( range );
|
|
869
|
+ err_range:
|
|
870
|
+ free ( uri );
|
|
871
|
+ err_uri:
|
833
|
872
|
if ( rc != 0 )
|
834
|
873
|
http_close ( http, rc );
|
835
|
874
|
}
|