LCOV - code coverage report
Current view: top level - acl - logic_check.h (source / functions) Hit Total Coverage
Test: report.info Lines: 40 44 90.9 %
Date: 2012-05-15 Functions: 43 54 79.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 68 115 59.1 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : #ifndef ACL_LOGIC_CHECK_H
      16                 :            : #define ACL_LOGIC_CHECK_H
      17                 :            : 
      18                 :            : #include "check.h"
      19                 :            : #include "loader.h"
      20                 :            : 
      21                 :            : namespace isc {
      22                 :            : namespace acl {
      23                 :            : 
      24                 :            : /// \brief Constants for the AnyOf implementation
      25                 :            : class AnyOfSpec {
      26                 :            : public:
      27                 :            :     static bool start() { return (false); }
      28                 :            :     static bool terminate(const bool another) {
      29                 :            :         return (another);
      30                 :            :     }
      31                 :            : };
      32                 :            : 
      33                 :            : /// \brief Constants for the AllOf implementation
      34                 :            : class AllOfSpec {
      35                 :            : public:
      36                 :            :     static bool start() { return (true); }
      37                 :            :     static bool terminate(const bool another) {
      38                 :            :         return (!another);
      39                 :            :     }
      40                 :            : };
      41                 :            : 
      42                 :            : /**
      43                 :            :  * \brief Logic operators
      44                 :            :  *
      45                 :            :  * This class implements the AllOf and AnyOf compound checks. As their
      46                 :            :  * behaviour is almost the same, the same template class is used. Which
      47                 :            :  * one it is depends on the Mode template parameter. The Mode should be
      48                 :            :  * one of AnyOfSpec or AllOfSpec, which provide some commands for the
      49                 :            :  * internal implementation. It would be nice to provide typedefs for
      50                 :            :  * them, but it is impossible to do so, as we have the Context template
      51                 :            :  * parameter as well and C++ doesn't like templated typedefs.
      52                 :            :  *
      53                 :            :  * The object holds several subexpressions and returns true if all
      54                 :            :  * of the subexpressions return true (in case of AllOfSpec Mode) or
      55                 :            :  * at last one of them return true (in case of AnyOfSpec Mode). If
      56                 :            :  * some subexpression guarantees the result (eg. some returns false
      57                 :            :  * in case of AllOfSpec), the rest is not tried for performance
      58                 :            :  * reasons.
      59                 :            :  */
      60                 :            : template<typename Mode, typename Context>
      61 [ +  - ][ +  - ]:         61 : class LogicOperator : public CompoundCheck<Context> {
      62                 :            : public:
      63                 :            :     /**
      64                 :            :      * \brief Add another subexpression.
      65                 :            :      *
      66                 :            :      * This adds another subexpression to the list of checked expressions.
      67                 :            :      * This is usually done shortly after the creation, before using the
      68                 :            :      * check for matches.
      69                 :            :      *
      70                 :            :      * Currently there's no way to place the expression into arbitrary place
      71                 :            :      * or to remove it. It might turn out it would be needed in future to
      72                 :            :      * optimise or it might even turn out we need shared pointers for it.
      73                 :            :      *
      74                 :            :      * \param expr The new expression to put inside.
      75                 :            :      */
      76                 :            :     void addSubexpression(const boost::shared_ptr<Check<Context> >& expr) {
      77   [ +  -  +  - ]:         40 :         checks_.push_back(expr);
         [ #  # ][ +  -  
          +  -  #  #  #  
              # ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
      78                 :            :     }
      79                 :            :     /**
      80                 :            :      * \brief The current list of subexpressions.
      81                 :            :      */
      82                 :         35 :     virtual typename CompoundCheck<Context>::Checks getSubexpressions() const {
      83                 :          0 :         typename CompoundCheck<Context>::Checks result;
      84 [ +  + ][ +  + ]:        105 :         for (typename Checks::const_iterator i(checks_.begin());
      85                 :            :              i != checks_.end(); ++i) {
      86 [ +  - ][ +  - ]:         70 :             result.push_back(i->get());
      87                 :            :         }
      88                 :         35 :         return (result);
      89                 :            :     }
      90                 :            :     /**
      91                 :            :      * \brief The match of the check.
      92                 :            :      *
      93                 :            :      * Runs the subexpressions, one by one, and then decides based on that
      94                 :            :      * what to return.
      95                 :            :      */
      96                 :         24 :     virtual bool matches(const Context& context) const {
      97                 :            :         /*
      98                 :            :          * This might look slightly complicated. However, this is just
      99                 :            :          * generalized version of multi-and or multi-or. The usual
     100                 :            :          * implementation of multi-and starts with true and if one with
     101                 :            :          * false is found, it turns to be false forever and false is
     102                 :            :          * returned. It is exactly the other way around with or.
     103                 :            :          *
     104                 :            :          * So, if we ever find one that makes it the other one than start
     105                 :            :          * (false in case of and, true in case of or), we can just stop and
     106                 :            :          * return that one right away. If it meets no such expression, we
     107                 :            :          * get to the end and return the default.
     108                 :            :          */
     109 [ +  + ][ +  + ]:         65 :         for (typename Checks::const_iterator i(checks_.begin());
     110                 :            :              i != checks_.end(); ++i) {
     111 [ +  + ][ +  + ]:         41 :             if (Mode::terminate((*i)->matches(context))) {
            [ + ][ +  + ]
     112                 :            :                 return (!Mode::start());
     113                 :            :             }
     114                 :            :         }
     115                 :            :         return (Mode::start());
     116                 :            :     }
     117                 :            : private:
     118                 :            :     /// \brief List of subexpressions
     119                 :            :     typedef typename std::vector<boost::shared_ptr<Check<Context> > > Checks;
     120                 :            :     Checks checks_;
     121                 :            : };
     122                 :            : 
     123                 :            : /**
     124                 :            :  * \brief Creator for the LogicOperator compound check.
     125                 :            :  *
     126                 :            :  * This class can load the ANY and ALL operators from JSON. They expect
     127                 :            :  * a list of subexpressions as a parameter, eg. like this:
     128                 :            :  *
     129                 :            :  * \verbatim
     130                 :            :  * {"ANY": [
     131                 :            :  *    {"ip": "1.2.3.4"},
     132                 :            :  *    {"ip": "5.6.7.8"}
     133                 :            :  * ]}
     134                 :            :  * \endverbatim
     135                 :            :  *
     136                 :            :  * It uses the loader to load the subexpressions, therefore whatever is
     137                 :            :  * supported there is supported here as well.
     138                 :            :  *
     139                 :            :  * The Mode template parameter has the same meaning as with LogicOperator,
     140                 :            :  * it is used to know which operators to create.
     141                 :            :  */
     142                 :            : template<typename Mode, typename Context, typename Action = BasicAction>
     143                 :         60 : class LogicCreator : public Loader<Context, Action>::CheckCreator {
     144                 :            : public:
     145                 :            :     /**
     146                 :            :      * \brief Constructor.
     147                 :            :      *
     148                 :            :      * \param name The name for which the loader will work. In practice,
     149                 :            :      *     it will usually be ANY or ALL (depending on the mode), but
     150                 :            :      *     anything else can be used as well.
     151                 :            :      */
     152                 :            :     LogicCreator(const std::string& name) :
     153 [ -  + ][ -  + ]:         28 :         name_(name)
     154                 :            :     {}
     155                 :            :     /// \brief Returns vector containing the name.
     156                 :         28 :     virtual std::vector<std::string> names() const {
     157                 :          0 :         std::vector<std::string> result;
     158 [ +  - ][ +  - ]:         28 :         result.push_back(name_);
     159                 :         28 :         return (result);
     160                 :            :     }
     161                 :            :     /**
     162                 :            :      * \brief Converts a JSON description into the logic operator.
     163                 :            :      *
     164                 :            :      * This is the place where the actual loading happens. It creates
     165                 :            :      * the logic operator and calls the loader on each of the list
     166                 :            :      * elements, placing the result into the logic operator.
     167                 :            :      *
     168                 :            :      * The first parameter is ignored and is there only to match interface.
     169                 :            :      *
     170                 :            :      * \param definition The JSON definition of the subexpressions. This must
     171                 :            :      *     be a list (if it isn't, the LoaderError is thrown) and the elements
     172                 :            :      *     must be loadable by the loader (the exceptions from it are not
     173                 :            :      *     caught).
     174                 :            :      * \param loader The loader to use for loading of subexpressions.
     175                 :            :      */
     176                 :         25 :     virtual boost::shared_ptr<Check<Context> > create(const std::string&,
     177                 :            :                                                       data::ConstElementPtr
     178                 :            :                                                       definition,
     179                 :            :                                                       const Loader<Context,
     180                 :            :                                                       Action>& loader)
     181                 :            :     {
     182                 :         25 :         std::vector<data::ConstElementPtr> subexprs;
     183                 :            :         try {
     184 [ +  + ][ +  - ]:         25 :             subexprs = definition->listValue();
         [ +  + ][ +  - ]
     185                 :            :         }
     186 [ -  + ][ -  + ]:         20 :         catch (const data::TypeError&) {
     187 [ -  + ][ -  + ]:         30 :             isc_throw_1(LoaderError, "Logic operator takes list", definition);
         [ -  + ][ -  + ]
         [ -  + ][ -  + ]
     188                 :            :         }
     189                 :            :         boost::shared_ptr<LogicOperator<Mode, Context> >
     190 [ +  - ][ +  - ]:         15 :             result(new LogicOperator<Mode, Context>);
         [ +  - ][ +  - ]
     191 [ +  + ][ +  + ]:         39 :         for (std::vector<data::ConstElementPtr>::const_iterator
     192                 :         54 :                  i(subexprs.begin());
     193                 :            :              i != subexprs.end(); ++i) {
     194 [ +  + ][ +  + ]:         26 :             result->addSubexpression(loader.loadCheck(*i));
                 [ +  - ]
     195                 :            :         }
     196                 :         13 :         return (result);
     197                 :            :     }
     198                 :         25 :     virtual bool allowListAbbreviation() const { return (false); }
     199                 :            : private:
     200                 :            :     const std::string name_;
     201                 :            : };
     202                 :            : 
     203                 :            : /**
     204                 :            :  * \brief The NOT operator for ACLs.
     205                 :            :  *
     206                 :            :  * This simply returns the negation of whatever returns the subexpression.
     207                 :            :  */
     208                 :            : template<typename Context>
     209                 :          6 : class NotOperator : public CompoundCheck<Context> {
     210                 :            : public:
     211                 :            :     /**
     212                 :            :      * \brief Constructor
     213                 :            :      *
     214                 :            :      * \param expr The subexpression to be negated by this NOT.
     215                 :            :      */
     216                 :            :     NotOperator(const boost::shared_ptr<Check<Context> >& expr) :
     217                 :          8 :         expr_(expr)
     218                 :            :     { }
     219                 :            :     /**
     220                 :            :      * \brief The list of subexpressions
     221                 :            :      *
     222                 :            :      * \return The vector will contain single value and it is the expression
     223                 :            :      *     passed by constructor.
     224                 :            :      */
     225                 :          4 :     virtual typename CompoundCheck<Context>::Checks getSubexpressions() const {
     226                 :          0 :         typename CompoundCheck<Context>::Checks result;
     227         [ +  - ]:          4 :         result.push_back(expr_.get());
     228                 :          4 :         return (result);
     229                 :            :     }
     230                 :            :     /// \brief The matching function
     231                 :          3 :     virtual bool matches(const Context& context) const {
     232                 :          3 :         return (!expr_->matches(context));
     233                 :            :     }
     234                 :            : private:
     235                 :            :     /// \brief The subexpression
     236                 :            :     const boost::shared_ptr<Check<Context> > expr_;
     237                 :            : };
     238                 :            : 
     239                 :            : template<typename Context, typename Action = BasicAction>
     240                 :         30 : class NotCreator : public Loader<Context, Action>::CheckCreator {
     241                 :            : public:
     242                 :            :     /**
     243                 :            :      * \brief Constructor
     244                 :            :      *
     245                 :            :      * \param name The name of the NOT operator to be loaded as.
     246                 :            :      */
     247                 :            :     NotCreator(const std::string& name) :
     248         [ -  + ]:         14 :         name_(name)
     249                 :            :     { }
     250                 :            :     /**
     251                 :            :      * \brief List of the names this loads
     252                 :            :      *
     253                 :            :      * \return Single-value vector containing the name passed to the
     254                 :            :      *     constructor.
     255                 :            :      */
     256                 :         14 :     virtual std::vector<std::string> names() const {
     257                 :          0 :         std::vector<std::string> result;
     258         [ +  - ]:         14 :         result.push_back(name_);
     259                 :         14 :         return (result);
     260                 :            :     }
     261                 :            :     /// \brief Create the check.
     262                 :          8 :     virtual boost::shared_ptr<Check<Context> > create(const std::string&,
     263                 :            :                                                       data::ConstElementPtr
     264                 :            :                                                       definition,
     265                 :            :                                                       const Loader<Context,
     266                 :            :                                                       Action>& loader)
     267                 :            :     {
     268                 :            :         return (boost::shared_ptr<Check<Context> >(new NotOperator<Context>(
     269         [ +  - ]:         10 :                     loader.loadCheck(definition))));
     270                 :            :     }
     271                 :            :     /**
     272                 :            :      * \brief Or-abbreviated form.
     273                 :            :      *
     274                 :            :      * This returns false. In theory, the NOT operator could be used with
     275                 :            :      * the abbreviated form, but it would be confusing. Such syntax is
     276                 :            :      * therefore explicitly forbidden.
     277                 :            :      */
     278                 :          8 :     virtual bool allowListAbbreviation() const { return (false); }
     279                 :            : public:
     280                 :            :     const std::string name_;
     281                 :            : };
     282                 :            : 
     283                 :            : }
     284                 :            : }
     285                 :            : 
     286                 :            : #endif

Generated by: LCOV version 1.9