瀏覽代碼

[http] Split construction of Authorization header out of http_step()

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 年之前
父節點
當前提交
8f5d44b5c6
共有 1 個檔案被更改,包括 96 行新增57 行删除
  1. 96
    57
      src/net/tcp/httpcore.c

+ 96
- 57
src/net/tcp/httpcore.c 查看文件

@@ -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
 }

Loading…
取消
儲存