reSIProcate/repro  9694
AmIResponsible.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #include "resip/stack/SipMessage.hxx"
00006 #include "resip/stack/Helper.hxx"
00007 #include "repro/monkeys/AmIResponsible.hxx"
00008 #include "repro/monkeys/IsTrustedNode.hxx"
00009 #include "repro/RequestContext.hxx"
00010 #include "repro/Proxy.hxx"
00011 #include <ostream>
00012 
00013 #include "rutil/Logger.hxx"
00014 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO
00015 
00016 using namespace resip;
00017 using namespace repro;
00018 using namespace std;
00019 
00020 AmIResponsible::AmIResponsible() : 
00021    Processor("AmIResponsible")
00022 {}
00023 
00024 AmIResponsible::~AmIResponsible()
00025 {}
00026 
00027 Processor::processor_action_t
00028 AmIResponsible::process(RequestContext& context)
00029 {
00030    DebugLog(<< "Monkey handling request: " << *this 
00031             << "; reqcontext = " << context);
00032 
00033    resip::SipMessage& request = context.getOriginalRequest();
00034 
00035    // There should be no Routes on the request at this point, if there was a route, then
00036    // the StrictRouteFixup monkey would have routed to it already
00037    assert (!request.exists(h_Routes) || 
00038            request.header(h_Routes).empty());
00039   
00040    // Topmost route had a flow-token; this is our problem
00041    if(!context.getTopRoute().uri().user().empty())
00042    {
00043       resip::Tuple dest(Tuple::makeTupleFromBinaryToken(context.getTopRoute().uri().user().base64decode(), Proxy::FlowTokenSalt));
00044       if(!(dest==resip::Tuple()))
00045       {
00046          // .bwc. Valid flow token
00047          std::auto_ptr<Target> target(new Target(request.header(h_RequestLine).uri()));
00048          target->rec().mReceivedFrom = dest;
00049          target->rec().mUseFlowRouting = true;
00050          context.getResponseContext().addTarget(target);
00051          return SkipThisChain;
00052       }
00053    }
00054 
00055    // this if is just to be safe
00056    if (!request.exists(h_Routes) || 
00057        request.header(h_Routes).empty())
00058    {
00059       // !RjS! - Jason - check the RURI to see if the domain is
00060       // something this request is responsible for. If yes, then
00061       // just return Continue. If no make this call below.
00062       const Uri& uri = request.header(h_RequestLine).uri();
00063       if (!context.getProxy().isMyUri(uri))
00064       {
00065          // if this is not for a domain for which the proxy is responsible,
00066          // check that this sender is in our domain and send to the Request URI
00067 
00068          // Ensure To header is well formed
00069          if(!request.header(h_To).isWellFormed())
00070          {
00071             resip::SipMessage response;
00072             InfoLog(<<"Garbage in To header: needed for relay check.");
00073             Helper::makeResponse(response,context.getOriginalRequest(), 400, "Malformed To: header");
00074             context.sendResponse(response);
00075             return Processor::SkipThisChain;
00076          }
00077 
00078          // only perform relay check for out-of-dialog requests
00079          // !bwc! Um, then all anyone has to do to get us to be their relay
00080          //       is throw in a spurious to-tag...
00081          //       This smells funny. I am commenting it out.
00082          // .slg. Putting the ood check back in and clarifying the funny smell...
00083          //       We only want to do this check for out of dialog requests, since 
00084          //       mid-dialog requests could be 403'd otherwise.  Consider
00085          //       an INVITE request from a repro domain user to a user in 
00086          //       another domain.  The resulting ACK/200, BYE or any other
00087          //       mid-dialog request coming from the remote domain, will contain
00088          //       the repro users contact address in the RequestUri and a 
00089          //       foreign domain in the from header.  We want to ensure these
00090          //       requests are not 403'd.  Byron's comment about an endpoint getting
00091          //       us to relay by placing a spurious to tag in the request still 
00092          //       stands. Perhaps we ought to be checking the To header domain in 
00093          //       this case - however that is also weak, since the To header is not
00094          //       used in routing and can easily be set to a URI in our domain to
00095          //       trick repro into forwarding.  Note:  From header domain checking is
00096          //       stronger than To header domain checking, since if the domain is 
00097          //       ours, then it must pass Digest Authentication (at least for non 
00098          //       ACK and BYE requests).
00099          // .bwc. I think that the only real way to solve the 
00100          //       I-don't-want-to-be-used-as-a-relay problem is crypto; specifically 
00101          //       Record-Route with crypto that states "Yeah, I set up this dialog, 
00102          //       let it through".
00103          if (!request.header(h_To).exists(p_tag))
00104          {
00105             // Ensure From header is well formed
00106             if(!request.header(h_From).isWellFormed())
00107             {
00108                resip::SipMessage response;
00109                InfoLog(<<"Garbage in From header: needed for relay check.");
00110                Helper::makeResponse(response,context.getOriginalRequest(), 400, "Malformed From: header");
00111                context.sendResponse(response);
00112                return Processor::SkipThisChain;
00113             }
00114 
00115             // !rwm! verify the AuthenticatioInfo object here.
00116             
00117             // !rwm! TODO check some kind of relay list here
00118             // for now, just see if the sender claims to be from one of our domains
00119             // send a 403 if not on the list
00120 
00121             // .slg. Allow trusted nodes to relay
00122             if (!context.getKeyValueStore().getBoolValue(IsTrustedNode::mFromTrustedNodeKey) && 
00123                 !context.getProxy().isMyUri(request.header(h_From).uri()))
00124             {
00125                // make 403, send, dispose of memory
00126                resip::SipMessage response;
00127                InfoLog (<< *this << ": will not relay to " << uri << " from " 
00128                         << request.header(h_From).uri() << ", send 403");
00129                Helper::makeResponse(response, context.getOriginalRequest(), 403, "Relaying Forbidden"); 
00130                context.sendResponse(response);
00131                return Processor::SkipThisChain;
00132             }
00133          }
00134          
00135          std::auto_ptr<Target> target(new Target(request.header(h_RequestLine).uri()));
00136          context.getResponseContext().addTarget(target);
00137 
00138          InfoLog (<< "Sending to requri: " << request.header(h_RequestLine).uri());
00139          // skip the rest of the monkeys
00140          return Processor::SkipThisChain;       
00141       }
00142    }
00143    return Processor::Continue;
00144 }
00145 
00146 
00147 /* ====================================================================
00148  * The Vovida Software License, Version 1.0 
00149  * 
00150  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00151  * 
00152  * Redistribution and use in source and binary forms, with or without
00153  * modification, are permitted provided that the following conditions
00154  * are met:
00155  * 
00156  * 1. Redistributions of source code must retain the above copyright
00157  *    notice, this list of conditions and the following disclaimer.
00158  * 
00159  * 2. Redistributions in binary form must reproduce the above copyright
00160  *    notice, this list of conditions and the following disclaimer in
00161  *    the documentation and/or other materials provided with the
00162  *    distribution.
00163  * 
00164  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00165  *    and "Vovida Open Communication Application Library (VOCAL)" must
00166  *    not be used to endorse or promote products derived from this
00167  *    software without prior written permission. For written
00168  *    permission, please contact vocal@vovida.org.
00169  *
00170  * 4. Products derived from this software may not be called "VOCAL", nor
00171  *    may "VOCAL" appear in their name, without prior written
00172  *    permission of Vovida Networks, Inc.
00173  * 
00174  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00175  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00176  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00177  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00178  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00179  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00180  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00181  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00182  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00183  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00184  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00185  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00186  * DAMAGE.
00187  * 
00188  * ====================================================================
00189  * 
00190  * This software consists of voluntary contributions made by Vovida
00191  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00192  * Inc.  For more information on Vovida Networks, Inc., please see
00193  * <http://www.vovida.org/>.
00194  *
00195  */