LCOV - code coverage report
Current view: top level - security/manager/ssl - nsSecurityHeaderParser.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 116 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "nsSecurityHeaderParser.h"
       6             : #include "mozilla/Logging.h"
       7             : 
       8             : // The character classes in this file are informed by [RFC2616], Section 2.2.
       9             : // signed char is a signed data type one byte (8 bits) wide, so its value can
      10             : // never be greater than 127. The following implicitly makes use of this.
      11             : 
      12             : // A token is one or more CHAR except CTLs or separators.
      13             : // A CHAR is any US-ASCII character (octets 0 - 127).
      14             : // A CTL is any US-ASCII control character (octets 0 - 31) and DEL (127).
      15             : // A separator is one of ()<>@,;:\"/[]?={} as well as space and
      16             : // horizontal-tab (32 and 9, respectively).
      17             : // So, this returns true if chr is any octet 33-126 except ()<>@,;:\"/[]?={}
      18             : bool
      19           0 : IsTokenSymbol(signed char chr) {
      20           0 :   if (chr < 33 || chr == 127 ||
      21           0 :       chr == '(' || chr == ')' || chr == '<' || chr == '>' ||
      22           0 :       chr == '@' || chr == ',' || chr == ';' || chr == ':' ||
      23           0 :       chr == '"' || chr == '/' || chr == '[' || chr == ']' ||
      24           0 :       chr == '?' || chr == '=' || chr == '{' || chr == '}' || chr == '\\') {
      25           0 :     return false;
      26             :   }
      27           0 :   return true;
      28             : }
      29             : 
      30             : // A quoted-string consists of a quote (") followed by any amount of
      31             : // qdtext or quoted-pair, followed by a quote.
      32             : // qdtext is any TEXT except a quote.
      33             : // TEXT is any 8-bit octet except CTLs, but including LWS.
      34             : // quoted-pair is a backslash (\) followed by a CHAR.
      35             : // So, it turns out, \ can't really be a qdtext symbol for our purposes.
      36             : // This returns true if chr is any octet 9,10,13,32-126 except <"> or "\"
      37             : bool
      38           0 : IsQuotedTextSymbol(signed char chr) {
      39           0 :   return ((chr >= 32 && chr != '"' && chr != '\\' && chr != 127) ||
      40           0 :           chr == 0x9 || chr == 0xa || chr == 0xd);
      41             : }
      42             : 
      43             : // The octet following the "\" in a quoted pair can be anything 0-127.
      44             : bool
      45           0 : IsQuotedPairSymbol(signed char chr) {
      46           0 :   return (chr >= 0);
      47             : }
      48             : 
      49             : static mozilla::LazyLogModule sSHParserLog("nsSecurityHeaderParser");
      50             : 
      51             : #define SHPARSERLOG(args) MOZ_LOG(sSHParserLog, mozilla::LogLevel::Debug, args)
      52             : 
      53           0 : nsSecurityHeaderParser::nsSecurityHeaderParser(const nsCString& aHeader)
      54           0 :   : mCursor(aHeader.get())
      55           0 :   , mError(false)
      56             : {
      57           0 : }
      58             : 
      59           0 : nsSecurityHeaderParser::~nsSecurityHeaderParser() {
      60             :   nsSecurityHeaderDirective *directive;
      61           0 :   while ((directive = mDirectives.popFirst())) {
      62           0 :     delete directive;
      63             :   }
      64           0 : }
      65             : 
      66             : mozilla::LinkedList<nsSecurityHeaderDirective> *
      67           0 : nsSecurityHeaderParser::GetDirectives() {
      68           0 :   return &mDirectives;
      69             : }
      70             : 
      71             : nsresult
      72           0 : nsSecurityHeaderParser::Parse() {
      73           0 :   MOZ_ASSERT(mDirectives.isEmpty());
      74           0 :   SHPARSERLOG(("trying to parse '%s'", mCursor));
      75             : 
      76           0 :   Header();
      77             : 
      78             :   // if we didn't consume the entire input, we were unable to parse it => error
      79           0 :   if (mError || *mCursor) {
      80           0 :     return NS_ERROR_FAILURE;
      81             :   } else {
      82           0 :     return NS_OK;
      83             :   }
      84             : }
      85             : 
      86             : bool
      87           0 : nsSecurityHeaderParser::Accept(char aChr)
      88             : {
      89           0 :   if (*mCursor == aChr) {
      90           0 :     Advance();
      91           0 :     return true;
      92             :   }
      93             : 
      94           0 :   return false;
      95             : }
      96             : 
      97             : bool
      98           0 : nsSecurityHeaderParser::Accept(bool (*aClassifier) (signed char))
      99             : {
     100           0 :   if (aClassifier(*mCursor)) {
     101           0 :     Advance();
     102           0 :     return true;
     103             :   }
     104             : 
     105           0 :   return false;
     106             : }
     107             : 
     108             : void
     109           0 : nsSecurityHeaderParser::Expect(char aChr)
     110             : {
     111           0 :   if (*mCursor != aChr) {
     112           0 :     mError = true;
     113             :   } else {
     114           0 :     Advance();
     115             :   }
     116           0 : }
     117             : 
     118             : void
     119           0 : nsSecurityHeaderParser::Advance()
     120             : {
     121             :   // Technically, 0 is valid in quoted-pair, but we were handed a
     122             :   // null-terminated const char *, so this doesn't handle that.
     123           0 :   if (*mCursor) {
     124           0 :     mOutput.Append(*mCursor);
     125           0 :     mCursor++;
     126             :   } else {
     127           0 :     mError = true;
     128             :   }
     129           0 : }
     130             : 
     131             : void
     132           0 : nsSecurityHeaderParser::Header()
     133             : {
     134           0 :   Directive();
     135           0 :   while (Accept(';')) {
     136           0 :     Directive();
     137             :   }
     138           0 : }
     139             : 
     140             : void
     141           0 : nsSecurityHeaderParser::Directive()
     142             : {
     143           0 :   mDirective = new nsSecurityHeaderDirective();
     144           0 :   LWSMultiple();
     145           0 :   DirectiveName();
     146           0 :   LWSMultiple();
     147           0 :   if (Accept('=')) {
     148           0 :     LWSMultiple();
     149           0 :     DirectiveValue();
     150           0 :     LWSMultiple();
     151             :   }
     152           0 :   mDirectives.insertBack(mDirective);
     153           0 :   SHPARSERLOG(("read directive name '%s', value '%s'",
     154             :                mDirective->mName.Data(), mDirective->mValue.Data()));
     155           0 : }
     156             : 
     157             : void
     158           0 : nsSecurityHeaderParser::DirectiveName()
     159             : {
     160           0 :   mOutput.Truncate(0);
     161           0 :   Token();
     162           0 :   mDirective->mName.Assign(mOutput);
     163           0 : }
     164             : 
     165             : void
     166           0 : nsSecurityHeaderParser::DirectiveValue()
     167             : {
     168           0 :   mOutput.Truncate(0);
     169           0 :   if (Accept(IsTokenSymbol)) {
     170           0 :     Token();
     171           0 :     mDirective->mValue.Assign(mOutput);
     172           0 :   } else if (Accept('"')) {
     173             :     // Accept advances the cursor if successful, which appends a character to
     174             :     // mOutput. The " is not part of what we want to capture, so truncate
     175             :     // mOutput again.
     176           0 :     mOutput.Truncate(0);
     177           0 :     QuotedString();
     178           0 :     mDirective->mValue.Assign(mOutput);
     179           0 :     Expect('"');
     180             :   }
     181           0 : }
     182             : 
     183             : void
     184           0 : nsSecurityHeaderParser::Token()
     185             : {
     186           0 :   while (Accept(IsTokenSymbol));
     187           0 : }
     188             : 
     189             : void
     190           0 : nsSecurityHeaderParser::QuotedString()
     191             : {
     192             :   while (true) {
     193           0 :     if (Accept(IsQuotedTextSymbol)) {
     194           0 :       QuotedText();
     195           0 :     } else if (Accept('\\')) {
     196           0 :       QuotedPair();
     197             :     } else {
     198           0 :       break;
     199             :     }
     200             :   }
     201           0 : }
     202             : 
     203             : void
     204           0 : nsSecurityHeaderParser::QuotedText()
     205             : {
     206           0 :   while (Accept(IsQuotedTextSymbol));
     207           0 : }
     208             : 
     209             : void
     210           0 : nsSecurityHeaderParser::QuotedPair()
     211             : {
     212           0 :   Accept(IsQuotedPairSymbol);
     213           0 : }
     214             : 
     215             : void
     216           0 : nsSecurityHeaderParser::LWSMultiple()
     217             : {
     218             :   while (true) {
     219           0 :     if (Accept('\r')) {
     220           0 :       LWSCRLF();
     221           0 :     } else if (Accept(' ') || Accept('\t')) {
     222           0 :       LWS();
     223             :     } else {
     224           0 :       break;
     225             :     }
     226             :   }
     227           0 : }
     228             : 
     229             : void
     230           0 : nsSecurityHeaderParser::LWSCRLF() {
     231           0 :   Expect('\n');
     232           0 :   if (!(Accept(' ') || Accept('\t'))) {
     233           0 :     mError = true;
     234             :   }
     235           0 :   LWS();
     236           0 : }
     237             : 
     238             : void
     239           0 : nsSecurityHeaderParser::LWS()
     240             : {
     241             :   // Note that becaue of how we're called, we don't have to check for
     242             :   // the mandatory presense of at least one of SP or HT.
     243           0 :   while (Accept(' ') || Accept('\t'));
     244           0 : }

Generated by: LCOV version 1.13