@@ -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" ;
@@ -544,19 +545,25 @@ const HTTPSRules = {
544545 return results ;
545546 } ,
546547
547- shouldSecureCookie : function ( applicable_list , c ) {
548+ shouldSecureCookie : function ( applicable_list , c , known_https ) {
548549 // Check to see if the Cookie object c meets any of our cookierule citeria
549- // for being marked as secure
550+ // for being marked as secure.
551+ // @applicable_list : an ApplicableList or record keeping
552+ // @c : an nsICookie2
553+ // @known_https : true if we know the page setting the cookie is https
550554 //this.log(DBUG, "Testing cookie:");
551555 //this.log(DBUG, " name: " + c.name);
552556 //this.log(DBUG, " host: " + c.host);
553557 //this.log(DBUG, " domain: " + c.domain);
554- // this.log(DBUG, " rawhost: " + c.rawHost);
558+ this . log ( DBUG , " rawhost: " + c . rawHost ) ;
555559 var i , j ;
556560 var rs = this . potentiallyApplicableRulesets ( c . host ) ;
557561 for ( i = 0 ; i < rs . length ; ++ i ) {
558562 var ruleset = rs [ i ] ;
559563 if ( ruleset . active ) {
564+ // Never secure a cookie if this page might be HTTP
565+ if ( ! known_https && ! this . safeToSecureCookie ( c . rawhost ) )
566+ continue ;
560567 for ( j = 0 ; j < ruleset . cookierules . length ; j ++ ) {
561568 var cr = ruleset . cookierules [ j ] ;
562569 if ( cr . host_c . test ( c . host ) && cr . name_c . test ( c . name ) ) {
@@ -573,6 +580,36 @@ const HTTPSRules = {
573580 }
574581 }
575582 return false ;
583+ } ,
584+
585+ safeToSecureCookie ( domain ) {
586+ // Check if the domain might be being served over HTTP. If so, it isn't
587+ // safe to secure a cookie! We can't always know this for sure because
588+ // observing cookie-changed doesn't give us enough context to know the
589+ // full origin URI.
590+
591+ // If there are any redirect loops on this domain, don't secure cookies.
592+ // XXX This is not a very satisfactory heuristic. Sometimes we would want
593+ // to secure the cookie anyway, because the URLs that loop are not
594+ // authenticated or not important. Also by the time
595+
596+ if ( domain in https_blacklist_domains ) return false ;
597+
598+ // If we passed that test, make up a random URL on the domain, and see if
599+ // we would HTTPSify that.
600+
601+ var ios = CC [ '@mozilla.org/network/io-service;1' ]
602+ . getService ( CI . nsIIOService ) ;
603+ try {
604+ var nonce_path = Math . random ( ) . toString ( ) + "/" + Math . random ( ) . toString ( ) ;
605+ var test_uri = ios . newURI ( "http://" + nonce_path , "UTF-8" , null ) ;
606+ } catch ( e ) {
607+ this . log ( WARN , "explosion in safeToSecureCookie for " + domain + "\n"
608+ + "(" + e + ")" ) ;
609+ return false ;
610+ }
611+ return wouldMatch ( test_uri , null ) ;
576612 }
577613
614+
578615} ;
0 commit comments