@@ -92,13 +92,14 @@ RuleSet.prototype = {
9292 wouldMatch : function ( hypothetical_uri , alist ) {
9393 // return true if this ruleset would match the uri, assuming it were http
9494 // used for judging moot / inactive rulesets
95+ // alist is optional
9596
9697 // if the ruleset is already somewhere in this applicable list, we don't
97- // care about hypothetical wouldMatch questios
98- if ( this . name in alist . all ) return false ;
98+ // care about hypothetical wouldMatch questions
99+ if ( alist && ( this . name in alist . all ) ) return false ;
99100
100101 this . log ( DBUG , "Would " + this . name + " match " + hypothetical_uri . spec +
101- "? serial " + alist . serial ) ;
102+ "? serial " + ( alist && alist . serial ) ) ;
102103
103104 var uri = hypothetical_uri . clone ( ) ;
104105 if ( uri . scheme == "https" ) uri . scheme = "http" ;
@@ -587,19 +588,25 @@ const HTTPSRules = {
587588 return results ;
588589 } ,
589590
590- shouldSecureCookie : function ( applicable_list , c ) {
591+ shouldSecureCookie : function ( applicable_list , c , known_https ) {
591592 // Check to see if the Cookie object c meets any of our cookierule citeria
592- // for being marked as secure
593+ // for being marked as secure.
594+ // @applicable_list : an ApplicableList or record keeping
595+ // @c : an nsICookie2
596+ // @known_https : true if we know the page setting the cookie is https
593597 //this.log(DBUG, "Testing cookie:");
594598 //this.log(DBUG, " name: " + c.name);
595599 //this.log(DBUG, " host: " + c.host);
596600 //this.log(DBUG, " domain: " + c.domain);
597- // this.log(DBUG, " rawhost: " + c.rawHost);
601+ this . log ( DBUG , " rawhost: " + c . rawHost ) ;
598602 var i , j ;
599603 var rs = this . potentiallyApplicableRulesets ( c . host ) ;
600604 for ( i = 0 ; i < rs . length ; ++ i ) {
601605 var ruleset = rs [ i ] ;
602606 if ( ruleset . active ) {
607+ // Never secure a cookie if this page might be HTTP
608+ if ( ! known_https && ! this . safeToSecureCookie ( c . rawhost ) )
609+ continue ;
603610 for ( j = 0 ; j < ruleset . cookierules . length ; j ++ ) {
604611 var cr = ruleset . cookierules [ j ] ;
605612 if ( cr . host_c . test ( c . host ) && cr . name_c . test ( c . name ) ) {
@@ -616,6 +623,36 @@ const HTTPSRules = {
616623 }
617624 }
618625 return false ;
626+ } ,
627+
628+ safeToSecureCookie ( domain ) {
629+ // Check if the domain might be being served over HTTP. If so, it isn't
630+ // safe to secure a cookie! We can't always know this for sure because
631+ // observing cookie-changed doesn't give us enough context to know the
632+ // full origin URI.
633+
634+ // If there are any redirect loops on this domain, don't secure cookies.
635+ // XXX This is not a very satisfactory heuristic. Sometimes we would want
636+ // to secure the cookie anyway, because the URLs that loop are not
637+ // authenticated or not important. Also by the time
638+
639+ if ( domain in https_blacklist_domains ) return false ;
640+
641+ // If we passed that test, make up a random URL on the domain, and see if
642+ // we would HTTPSify that.
643+
644+ var ios = CC [ '@mozilla.org/network/io-service;1' ]
645+ . getService ( CI . nsIIOService ) ;
646+ try {
647+ var nonce_path = Math . random ( ) . toString ( ) + "/" + Math . random ( ) . toString ( ) ;
648+ var test_uri = ios . newURI ( "http://" + nonce_path , "UTF-8" , null ) ;
649+ } catch ( e ) {
650+ this . log ( WARN , "explosion in safeToSecureCookie for " + domain + "\n"
651+ + "(" + e + ")" ) ;
652+ return false ;
653+ }
654+ return wouldMatch ( test_uri , null ) ;
619655 }
620656
657+
621658} ;
0 commit comments