~ubuntu-branches/ubuntu/feisty/elinks/feisty-updates

« back to all changes in this revision

Viewing changes to src/protocol/http/http.c

  • Committer: Bazaar Package Importer
  • Author(s): Jamie Strandboge
  • Date: 2007-09-24 13:55:54 UTC
  • Revision ID: james.westby@ubuntu.com-20070924135554-mvubd94gk626d5ld
Tags: 0.11.1-1.2ubuntu2.2
* SECURITY UPDATE: possible information disclosure when using an HTTPS proxy
  server and sending a POST request
* added patch to src/protocol/http/http.c for proper handling of POST DATA
* References
  CVE-2007-5034
  Fixes LP: #141018

Show diffs side-by-side

added added

removed removed

Lines of Context:
551
551
        int trace = get_opt_bool("protocol.http.trace");
552
552
        struct string header;
553
553
        unsigned char *post_data = NULL;
554
 
        struct auth_entry *entry;
 
554
        struct auth_entry *entry = NULL;
555
555
        struct uri *uri = conn->proxied_uri; /* Set to the real uri */
556
556
        unsigned char *optstr;
557
557
        int use_connect, talking_to_proxy;
577
577
                add_to_string(&header, "TRACE ");
578
578
        } else if (use_connect) {
579
579
                add_to_string(&header, "CONNECT ");
 
580
                /* In CONNECT requests, we send only a subset of the
 
581
                 * headers to the proxy.  See the "CONNECT:" comments
 
582
                 * below.  After the CONNECT request succeeds, we
 
583
                 * negotiate TLS with the real server and make a new
 
584
                 * HTTP request that includes all the headers.  */
580
585
        } else if (uri->post) {
581
586
                add_to_string(&header, "POST ");
582
587
                conn->unrestartable = 1;
609
614
        add_long_to_string(&header, http->sent_version.minor);
610
615
        add_crlf_to_string(&header);
611
616
 
 
617
        /* CONNECT: Sending a Host header seems pointless as the same
 
618
         * information is already in the CONNECT line.  It's harmless
 
619
         * though and Mozilla does it too.  */
612
620
        add_to_string(&header, "Host: ");
613
621
        add_uri_to_string(&header, uri, URI_HTTP_HOST);
614
622
        add_crlf_to_string(&header);
615
623
 
 
624
        /* CONNECT: Proxy-Authorization is intended to be seen by the proxy.  */
616
625
        if (talking_to_proxy) {
617
626
                unsigned char *user = get_opt_str("protocol.http.proxy.user");
618
627
                unsigned char *passwd = get_opt_str("protocol.http.proxy.passwd");
660
669
                }
661
670
        }
662
671
 
 
672
        /* CONNECT: User-Agent does not reveal anything about the
 
673
         * resource we're fetching, and it may help the proxy return
 
674
         * better error messages.  */
663
675
        optstr = get_opt_str("protocol.http.user_agent");
664
676
        if (*optstr && strcmp(optstr, " ")) {
665
677
                unsigned char *ustr, ts[64] = "";
685
697
                add_crlf_to_string(&header);
686
698
        }
687
699
 
688
 
        switch (get_opt_int("protocol.http.referer.policy")) {
689
 
                case REFERER_NONE:
690
 
                        /* oh well */
691
 
                        break;
692
 
 
693
 
                case REFERER_FAKE:
694
 
                        optstr = get_opt_str("protocol.http.referer.fake");
695
 
                        if (!optstr[0]) break;
696
 
                        add_to_string(&header, "Referer: ");
697
 
                        add_to_string(&header, optstr);
698
 
                        add_crlf_to_string(&header);
699
 
                        break;
700
 
 
701
 
                case REFERER_TRUE:
702
 
                        if (!conn->referrer) break;
703
 
                        add_to_string(&header, "Referer: ");
704
 
                        add_url_to_http_string(&header, conn->referrer, URI_HTTP_REFERRER);
705
 
                        add_crlf_to_string(&header);
706
 
                        break;
707
 
 
708
 
                case REFERER_SAME_URL:
709
 
                        add_to_string(&header, "Referer: ");
710
 
                        add_url_to_http_string(&header, uri, URI_HTTP_REFERRER);
711
 
                        add_crlf_to_string(&header);
712
 
                        break;
 
700
        /* CONNECT: Referer probably is a secret page in the HTTPS
 
701
         * server, so don't reveal it to the proxy.  */ 
 
702
        if (!use_connect) {
 
703
                switch (get_opt_int("protocol.http.referer.policy")) {
 
704
                        case REFERER_NONE:
 
705
                                /* oh well */
 
706
                                break;
 
707
 
 
708
                        case REFERER_FAKE:
 
709
                                optstr = get_opt_str("protocol.http.referer.fake");
 
710
                                if (!optstr[0]) break;
 
711
                                add_to_string(&header, "Referer: ");
 
712
                                add_to_string(&header, optstr);
 
713
                                add_crlf_to_string(&header);
 
714
                                break;
 
715
 
 
716
                        case REFERER_TRUE:
 
717
                                if (!conn->referrer) break;
 
718
                                add_to_string(&header, "Referer: ");
 
719
                                add_url_to_http_string(&header, conn->referrer, URI_HTTP_REFERRER);
 
720
                                add_crlf_to_string(&header);
 
721
                                break;
 
722
 
 
723
                        case REFERER_SAME_URL:
 
724
                                add_to_string(&header, "Referer: ");
 
725
                                add_url_to_http_string(&header, uri, URI_HTTP_REFERRER);
 
726
                                add_crlf_to_string(&header);
 
727
                                break;
 
728
                }
713
729
        }
714
730
 
 
731
        /* CONNECT: Do send all Accept* headers to the CONNECT proxy,
 
732
         * because they do not reveal anything about the resource
 
733
         * we're going to request via TLS, and they may affect the
 
734
         * error message if the CONNECT request fails.
 
735
         *
 
736
         * If ELinks is ever changed to vary its Accept headers based
 
737
         * on what it intends to do with the returned resource, e.g.
 
738
         * sending "Accept: text/css" when it wants an external
 
739
         * stylesheet, then it should do that only in the inner GET
 
740
         * and not in the outer CONNECT.  */
715
741
        add_to_string(&header, "Accept: */*");
716
742
        add_crlf_to_string(&header);
717
743
 
766
792
        }
767
793
#endif
768
794
 
 
795
        /* CONNECT: Proxy-Connection is intended to be seen by the
 
796
         * proxy.  If the CONNECT request succeeds, then the proxy
 
797
         * will forward the remainder of the TCP connection to the
 
798
         * origin server, and Proxy-Connection does not matter; but
 
799
         * if the request fails, then Proxy-Connection may matter.  */
769
800
        /* FIXME: What about post-HTTP/1.1?? --Zas */
770
801
        if (HTTP_1_1(http->sent_version)) {
771
802
                if (!IS_PROXY_URI(conn->uri)) {
782
813
                add_crlf_to_string(&header);
783
814
        }
784
815
 
785
 
        if (conn->cached) {
 
816
        /* CONNECT: Do not tell the proxy anything we have cached
 
817
         * about the resource.  */
 
818
        if (!use_connect && conn->cached) {
786
819
                if (!conn->cached->incomplete && conn->cached->head && conn->cached->last_modified
787
820
                    && conn->cache_mode <= CACHE_MODE_CHECK_IF_MODIFIED) {
788
821
                        add_to_string(&header, "If-Modified-Since: ");
791
824
                }
792
825
        }
793
826
 
 
827
        /* CONNECT: Let's send cache control headers to the proxy too;
 
828
         * they may affect DNS caching.  */
794
829
        if (conn->cache_mode >= CACHE_MODE_FORCE_RELOAD) {
795
830
                add_to_string(&header, "Pragma: no-cache");
796
831
                add_crlf_to_string(&header);
798
833
                add_crlf_to_string(&header);
799
834
        }
800
835
 
801
 
        if (conn->from || conn->progress->start > 0) {
 
836
        /* CONNECT: Do not reveal byte ranges to the proxy.  It can't
 
837
         * do anything good with that information anyway.  */
 
838
        if (!use_connect && (conn->from || conn->progress->start > 0)) {
802
839
                /* conn->from takes precedence. conn->progress.start is set only the first
803
840
                 * time, then conn->from gets updated and in case of any retries
804
841
                 * etc we have everything interesting in conn->from already. */
808
845
                add_crlf_to_string(&header);
809
846
        }
810
847
 
811
 
        entry = find_auth(uri);
 
848
        /* CONNECT: The Authorization header is for the origin server only.  */
 
849
        if (!use_connect) {
 
850
                entry = find_auth(uri);
 
851
        }
812
852
        if (entry) {
813
853
                if (entry->digest) {
814
854
                        unsigned char *response;
848
888
                }
849
889
        }
850
890
 
851
 
        if (uri->post) {
 
891
        /* CONNECT: Any POST data is for the origin server only.  */
 
892
        if (!use_connect && uri->post) {
852
893
                /* We search for first '\n' in uri->post to get content type
853
894
                 * as set by get_form_uri(). This '\n' is dropped if any
854
895
                 * and replaced by correct '\r\n' termination here. */
867
908
        }
868
909
 
869
910
#ifdef CONFIG_COOKIES
870
 
        {
 
911
        /* CONNECT: Cookies are for the origin server only.  */
 
912
        if (!use_connect) {
871
913
                struct string *cookies = send_cookies(uri);
872
914
 
873
915
                if (cookies) {
881
923
 
882
924
        add_crlf_to_string(&header);
883
925
 
 
926
        /* CONNECT: Any POST data is for the origin server only.
 
927
         * This was already checked above and post_data is NULL
 
928
         * in that case.  Verified with an assertion below.  */
884
929
        if (post_data) {
885
930
#define POST_BUFFER_SIZE 4096
886
931
                unsigned char *post = post_data;
887
932
                unsigned char buffer[POST_BUFFER_SIZE];
888
933
                int n = 0;
889
934
 
 
935
                assert(!use_connect); /* see comment above */
 
936
 
890
937
                while (post[0] && post[1]) {
891
938
                        int h1, h2;
892
939