Пример #1
0
bool ZoneAdminRpcMethod::validCaller(const HttpRequestContext& requestContext,
                                const UtlString&          peerName,
                                XmlRpcResponse&           response,
                                const SipxRpc&            sipxRpcImpl,
                                const char*               callingMethod
                                )
{
   bool result = false;

   if (!peerName.isNull() && requestContext.isTrustedPeer(peerName))
   {
      // ssl says the connection is from the named host
      if (sipxRpcImpl.isAllowedPeer(peerName))
      {
         // sipXsupervisor says it is one of the allowed peers.
         result = true;
         OsSysLog::add(FAC_SUPERVISOR, PRI_DEBUG,
                       "ZoneAdminRpcMethod::validCaller '%s' peer authenticated for %s",
                       peerName.data(), callingMethod
                       );
      }
      else
      {
         // this peer is authenticated, but not configured, so provide a good error response
         UtlString faultMsg;
         faultMsg.append("Unconfigured calling host '");
         faultMsg.append(peerName);
         faultMsg.append("'");
         response.setFault(ZoneAdminRpcMethod::UnconfiguredPeer, faultMsg.data());

         OsSysLog::add(FAC_SUPERVISOR, PRI_ERR,
                       "%s failed - '%s' not a configured peer",
                       callingMethod, peerName.data()
                       );
      }
   }
   else
   {
      // ssl says not authenticated - provide only a generic error
      response.setFault(XmlRpcResponse::AuthenticationRequired, "TLS Peer Authentication Failure");

      OsSysLog::add(FAC_SUPERVISOR, PRI_ERR,
                    "%s failed: '%s' failed SSL authentication",
                    callingMethod, peerName.data()
                    );
   }

   return result;
}
Пример #2
0
/// Whether or not an HTTP request is from some allowed peer, and if so which one.
bool SipxRpc::isAllowedPeer(const HttpRequestContext& context, ///< the request to be checked
                            UtlString& peer                    ///< if allowed, the name of the peer
                            ) const
{
   bool isAllowed = false;
   peer.remove(0);

   UtlSListIterator allowedPeers(mAllowedPeers);
   UtlString* tryPeer;
   while (!isAllowed && (tryPeer = dynamic_cast<UtlString*>(allowedPeers())))
   {
      isAllowed = context.isTrustedPeer(*tryPeer);
   }
   if (isAllowed)
   {
      peer = *tryPeer;
   }
   return isAllowed;
}
Пример #3
0
/// Access check function
XmlRpcMethod::ExecutionStatus ConfigRPC_InDomainCallback::accessAllowed(
   const HttpRequestContext&  requestContext,
   ConfigRPC_Callback::Method method
                                                                        ) const
{
   XmlRpcMethod::ExecutionStatus isAllowed = (  requestContext.isTrustedPeer(mAllowedDomain)
                                              ? XmlRpcMethod::OK
                                              : XmlRpcMethod::FAILED
                                              );
   /*
    * - XmlRpcMethod::OK if allowed
    * - XmlRpcMethod::FAILED if not allowed,
    * - XmlRpcMethod::REQUIRE_AUTHENTICATION if authentication is missing or invalid.
    */
   if (XmlRpcMethod::FAILED == isAllowed)
   {
      Os::Logger::instance().log(FAC_KERNEL, PRI_WARNING,
                    "ConfigRPC_InDomainCallback disallowed configuration from untrusted peer"
                    );
   }
   return isAllowed;
}
Пример #4
0
/// Provide access to files as allowed by process definitions.
void HttpFileAccess::processRequest(const HttpRequestContext& requestContext,
                                    const HttpMessage& request,
                                    HttpMessage*& response
                                    )
{
   UtlString message;
   response = new HttpMessage();

   UtlString peerName;
   if (mSipxRpc->isAllowedPeer(requestContext, peerName))
   {
      if (requestContext.methodIs(HTTP_GET_METHOD))
      {
         UtlString path;
         requestContext.getMappedPath(path);

         FileResource* resource = FileResourceManager::getInstance()->find(path);
         if (resource)
         {
            if (resource->isReadable())
            {
               sendFile(path, peerName, requestContext, request, response);
            }
            else
            {
               message.append("resource ");
               resource->appendDescription(message);
               message.append(" does not allow write access to '");
               message.append(path);
               message.append("'");
               OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest from %s %s",
                             peerName.data(), message.data());

               response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                                    HTTP_FORBIDDEN_CODE,
                                                    "Access denied by process definition");
               response->setBody(new HttpBody(message.data(),message.length()));
               response->setContentType(CONTENT_TYPE_TEXT_PLAIN);
               response->setContentLength(message.length());
            }
         }
         else
         {
            message.append("File resource '");
            message.append(path);
            message.append("' not known to sipXsupervisor.");
            OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest from %s %s",
                          peerName.data(), message.data());

            response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                                 HTTP_FILE_NOT_FOUND_CODE,
                                                 HTTP_FILE_NOT_FOUND_TEXT);
            response->setBody(new HttpBody(message.data(),message.length()));
            response->setContentType(CONTENT_TYPE_TEXT_PLAIN);
            response->setContentLength(message.length());
         }
      }
      else if (requestContext.methodIs(HTTP_DELETE_METHOD))
      {
         UtlString path;
         requestContext.getMappedPath(path);

         FileResource* resource = FileResourceManager::getInstance()->find(path);
         if (resource)
         {
            if (resource->isWriteable())
            {
               OsPath filePath(path);
               if (OsFileSystem::exists(filePath))
               {
                  if (OS_SUCCESS
                      == OsFileSystem::remove(filePath, TRUE /* recursive */, TRUE /* force */))
                  {
                     message.append("File '");
                     message.append(path);
                     message.append("' deleted");
                     OsSysLog::add(FAC_SUPERVISOR, PRI_INFO, "HttpFileAccess::processRequest from %s %s",
                                   peerName.data(), message.data());
                  
                     response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION_1_1,
                                                          HTTP_OK_CODE, "Deleted");
                     response->setContentLength(0);

                     // tell anyone who cares that this has changed
                     resource->modified();
                  }
                  else
                  {
                     int       httpStatusCode;
                     UtlString httpStatusText;

                     switch (errno)
                     {
                     case EACCES:
                        httpStatusCode = HTTP_FORBIDDEN_CODE;
                        httpStatusText = "File Access Denied";
                        break;

                     default:
                        httpStatusCode = HTTP_SERVER_ERROR_CODE;
                        httpStatusText.append("Unknown error ");
                        httpStatusText.appendNumber(errno);
                        break;
                     }

                     message.append("File '");
                     message.append(path);
                     message.append("' errno ");
                     message.appendNumber(errno);
                     message.append(" ");

                     char errnoMsg[1024];
                     strerror_r(errno, errnoMsg, sizeof(errnoMsg));
                     message.append(errnoMsg);

                     OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest from %s %s",
                                   peerName.data(), message.data());

                     response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                                          httpStatusCode,
                                                          httpStatusText);
                     response->setBody(new HttpBody(message.data(),message.length()));
                     response->setContentType(CONTENT_TYPE_TEXT_PLAIN);
                     response->setContentLength(message.length());
                  }                  
               }
               else
               {
                  message.append("File to be deleted '");
                  message.append(path);
                  message.append("' does not exist");
                  OsSysLog::add(FAC_SUPERVISOR, PRI_INFO, "HttpFileAccess::processRequest from %s %s",
                                peerName.data(), message.data());
                  
                  response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION_1_1,
                                                       HTTP_OK_CODE, "File does not exist");
                  response->setContentLength(0);
               }
            }
            else
            {
               message.append("resource ");
               resource->appendDescription(message);
               message.append(" does not allow write access to '");
               message.append(path);
               message.append("'");
               OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest from %s %s",
                             peerName.data(), message.data());

               response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                                    HTTP_FORBIDDEN_CODE,
                                                    "Access denied by process definition");
               response->setBody(new HttpBody(message.data(),message.length()));
               response->setContentType(CONTENT_TYPE_TEXT_PLAIN);
               response->setContentLength(message.length());
            }
         }
         else
         {
            message.append("File resource '");
            message.append(path);
            message.append("' not known to sipXsupervisor.");
            OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest from %s %s",
                          peerName.data(), message.data());

            response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                                 HTTP_FILE_NOT_FOUND_CODE,
                                                 HTTP_FILE_NOT_FOUND_TEXT);
            response->setBody(new HttpBody(message.data(),message.length()));
            response->setContentType(CONTENT_TYPE_TEXT_PLAIN);
            response->setContentLength(message.length());
         }
      }
      else
      {
         OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest %s from %s",
                       HTTP_UNSUPPORTED_METHOD_TEXT, peerName.data());

         response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                              HTTP_UNSUPPORTED_METHOD_CODE,
                                              HTTP_UNSUPPORTED_METHOD_TEXT);
      }
   }
   else
   {
      message.append("Request not supported from untrusted peer.");
      OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest %s",
                    message.data());

      response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                           HTTP_FORBIDDEN_CODE, HTTP_FORBIDDEN_TEXT);

      response->setBody(new HttpBody(message.data(),message.length()));
      response->setContentType(CONTENT_TYPE_TEXT_PLAIN);
      response->setContentLength(message.length());
   }
}
Пример #5
0
void HttpFileAccess::sendFile(const UtlString& path,
                              const UtlString& peerName,
                              const HttpRequestContext& requestContext,
                              const HttpMessage& request,
                              HttpMessage*& response
                              )
{
   UtlString message;
   
   int file = open(path.data(), O_RDONLY);
   if (0 <= file)
   {
      UtlString fileBuffer;
      if (fileBuffer.capacity(MAX_FILE_CHUNK_SIZE + 1) >= MAX_FILE_CHUNK_SIZE + 1)
      {
         response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION_1_1,
                                              HTTP_OK_CODE, HTTP_OK_TEXT);
         response->useChunkedBody(true);

         // @TODO Annotate file resources with a mime type?

         // add a Content-Disposition header to suggest saving as the basename of the file
         response->setContentType("application/octet-stream");
         UtlString dispositionValue;
         UtlString basename;
         ssize_t finalSlash = path.last('/');
         if (UTL_NOT_FOUND != finalSlash)
         {
            basename.append(path, finalSlash+1, path.length()-finalSlash);
         }
         else
         {
            basename.append(path); // don't think this should ever be true....
         }
         dispositionValue.append("attachment; filename=\"");
         dispositionValue.append(basename);
         dispositionValue.append("\"");
         response->setHeaderValue(HTTP_CONTENT_DISPOSITION_FIELD,dispositionValue.data());

         bool    writtenOk = response->writeHeaders(requestContext.socket());
         ssize_t bytes;
         Int64   totalBytes = 0;
         Int64   chunks = 0;
         while (   writtenOk
                && (bytes = read(file, (void*)fileBuffer.data(),
                                 MAX_FILE_CHUNK_SIZE)))
         {
            fileBuffer.setLength(bytes);
            writtenOk = response->writeChunk(requestContext.socket(), fileBuffer);
            if (writtenOk)
            {
               totalBytes += bytes;
               chunks++;
            }
            OsSysLog::add(FAC_SUPERVISOR, PRI_DEBUG,
                          "file block %"FORMAT_INTLL"d %zd %s", chunks, bytes,
                          writtenOk ? "ok" : "failed");
         }
         if (writtenOk)
         {
            response->writeEndOfChunks(requestContext.socket());

            message.append(" sent file '");
            message.append(path);
            message.append("' (");
            message.appendNumber(totalBytes,"%"FORMAT_INTLL"d");
            message.append(" bytes in ");
            message.appendNumber(chunks,"%"FORMAT_INTLL"d");
            message.append(" chunks) to peer ");
            message.append(peerName);
            OsSysLog::add(FAC_SUPERVISOR, PRI_INFO, "HttpFileAccess::processRequest %s",
                          message.data());
         }
         else
         {
            message.append("error writing response after ");
            message.appendNumber(totalBytes,"%"FORMAT_INTLL"d");
            message.append(" body bytes in ");
            message.appendNumber(chunks,"%"FORMAT_INTLL"d");
            message.append(" chunks) to peer ");
            message.append(peerName);
            OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest %s",
                          message.data());
         }

         /*
          * We've already written the response, so prevent HttpServer from sending it by
          * not passing it back.
          */
         delete response;
         response = NULL;
      }
      else
      {
         // Send out-of-resources message
         message.append("Supervisor Buffer Exhausted");
         response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                              HTTP_OUT_OF_RESOURCES_CODE,
                                              message.data());
         response->setContentType(CONTENT_TYPE_TEXT_PLAIN);
         response->setBody(new HttpBody(message.data(),message.length()));
         response->setContentLength(message.length());

         OsSysLog::add(FAC_SUPERVISOR, PRI_ERR,
                       "HttpFileAccess::processRequest from %s %s",
                       peerName.data(), message.data());
      }
   }
   else
   {
      int       httpStatusCode;
      UtlString httpStatusText;

      switch (errno)
      {
      case EACCES:
         httpStatusCode = HTTP_FORBIDDEN_CODE;
         httpStatusText = "File Access Denied";
         break;

      case ENOENT:
         httpStatusCode = HTTP_FILE_NOT_FOUND_CODE;
         httpStatusText = HTTP_FILE_NOT_FOUND_TEXT;
         break;

      default:
         httpStatusCode = HTTP_SERVER_ERROR_CODE;
         httpStatusText = HTTP_SERVER_ERROR_TEXT;
         break;
      }

      message.append("File '");
      message.append(path);
      message.append("' errno ");
      message.appendNumber(errno);
      message.append(" ");

      char errnoMsg[1024];
      strerror_r(errno, errnoMsg, sizeof(errnoMsg));
      message.append(errnoMsg);

      OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest from %s %s",
                    peerName.data(), message.data());

      response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                           httpStatusCode,
                                           httpStatusText);
      response->setBody(new HttpBody(message.data(),message.length()));
      response->setContentType(CONTENT_TYPE_TEXT_PLAIN);
      response->setContentLength(message.length());
   }
}
Пример #6
0
void HttpServer::testCgiRequest(const HttpRequestContext& requestContext,
                                const HttpMessage& request,
                                HttpMessage*& response)
{
    UtlString url;
    UtlString value;
    requestContext.getEnvironmentVariable(HttpRequestContext::HTTP_ENV_RAW_URL,
        url);
    UtlString cgiDump("<HTML>\n<TITLE>\n");
    cgiDump.append(url);
    cgiDump.append(" dump\n</TITLE>\n<BODY>\n<H3>Environment Variables\n</H3>\n");
    cgiDump.append("<TABLE BORDER=1>\n<TR>\n<TH ALIGN=LEFT>Name</TH>\n<TH ALIGN=LEFT>Value</TH>\n</TR>\n");

    requestContext.getEnvironmentVariable(HttpRequestContext::HTTP_ENV_RAW_URL,
        value);
    cgiDump.append("<TR>\n<TD ALIGN=LEFT>HTTP_ENV_RAW_URL</TD>\n<TD ALIGN=LEFT>");
    cgiDump.append(value);
    cgiDump.append("</TD>\n</TR>\n");

    requestContext.getEnvironmentVariable(HttpRequestContext::HTTP_ENV_UNMAPPED_FILE,
        value);
    cgiDump.append("<TR>\n<TD ALIGN=LEFT>HTTP_ENV_UNMAPPED_FILE</TD>\n<TD ALIGN=LEFT>");
    cgiDump.append(value);
    cgiDump.append("</TD>\n</TR>\n");

    requestContext.getEnvironmentVariable(HttpRequestContext::HTTP_ENV_MAPPED_FILE,
        value);
    cgiDump.append("<TR>\n<TD ALIGN=LEFT>HTTP_ENV_MAPPED_FILE</TD>\n<TD ALIGN=LEFT>");
    cgiDump.append(value);
    cgiDump.append("</TD>\n</TR>\n");

    requestContext.getEnvironmentVariable(HttpRequestContext::HTTP_ENV_QUERY_STRING,
        value);
    cgiDump.append("<TR>\n<TD ALIGN=LEFT>HTTP_ENV_QUERY_STRING</TD>\n<TD ALIGN=LEFT>");
    cgiDump.append(value);
    cgiDump.append("</TD>\n</TR>\n");

    requestContext.getEnvironmentVariable(HttpRequestContext::HTTP_ENV_SERVER_NAME,
        value);
    cgiDump.append("<TR>\n<TD ALIGN=LEFT>HTTP_ENV_SERVER_NAME</TD>\n<TD ALIGN=LEFT>");
    cgiDump.append(value);
    cgiDump.append("</TD>\n</TR>\n");

    requestContext.getEnvironmentVariable(HttpRequestContext::HTTP_ENV_REQUEST_METHOD,
        value);
    cgiDump.append("<TR>\n<TD ALIGN=LEFT>HTTP_ENV_REQUEST_METHOD</TD>\n<TD ALIGN=LEFT>");
    cgiDump.append(value);
    cgiDump.append("</TD>\n</TR>\n");

    requestContext.getEnvironmentVariable(HttpRequestContext::HTTP_ENV_USER,
        value);
    cgiDump.append("<TR>\n<TD ALIGN=LEFT>HTTP_ENV_USER</TD>\n<TD ALIGN=LEFT>");
    cgiDump.append(value);
    cgiDump.append("</TD>\n</TR>\n</TABLE>\n");


    cgiDump.append("<H3>CGI/Form Variables\n</H3>\n");
    cgiDump.append("<TABLE BORDER=1>\n<TR>\n<TH>Name</TH>\n<TH>Value</TH>\n</TR>\n");

    int index = 0;
    UtlString name;
    while(requestContext.getCgiVariable(index, name, value))
    {
      cgiDump.append("<TR>\n<TD  ALIGN=LEFT>");
        cgiDump.append(name);
        cgiDump.append("</TD>\n<TD ALIGN=LEFT>");
        cgiDump.append(value);
        cgiDump.append("</TD>\n</TR>\n");
        index++;
    }
    cgiDump.append("</TABLE>\n");

    createHtmlResponse(HTTP_OK_CODE, HTTP_OK_TEXT, cgiDump.data(), response);

    url.remove(0);
    value.remove(0);
    cgiDump.remove(0);
    name.remove(0);
}
Пример #7
0
/* ============================ ACCESSORS ================================= */
void
WebServer::ProcessEvent(
    const HttpRequestContext& requestContext,
    const HttpMessage& request,
    HttpMessage*& response )
{
    // get the action type (used to be the event)
    UtlString event;
    response = new HttpMessage();

    ssize_t len;
    UtlString httpString;
    SubscribeServerPluginBase* plugin = NULL;

    request.getBytes(&httpString , &len);
    Os::Logger::instance().log(FAC_SIP, PRI_INFO,
                  "WebServer::ProcessEvent HttpEvent \n%s",
                  httpString.data());

    // get the ACTION CGI variable
    requestContext.getCgiVariable( EVENTTYPE, event );

    if( !event.isNull())
    {
        //according to event type , get the correct plugin from spPluginTable
        StatusPluginReference* pluginContainer = spPluginTable->getPlugin(event);
        if(pluginContainer)
        {
            plugin = pluginContainer->getPlugin();
            if(plugin)
            {
                // send 200 ok reply.
                response->setResponseFirstHeaderLine (
                    HTTP_PROTOCOL_VERSION,
                    HTTP_OK_CODE,
                    HTTP_OK_TEXT );

                //call the event handler for the plugin
                plugin->handleEvent(requestContext, request, *response);
            }
            else
            {
               Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                             "WebServer::ProcessEvent no plugin in container for event type '%s'",
                             event.data()
                             );
            }
        }
        else
        {
           Os::Logger::instance().log(FAC_SIP, PRI_WARNING,
                         "WebServer::ProcessEvent no plugin found for event type '%s'",
                         event.data()
                         );
        }
    }
    else
    {
       Os::Logger::instance().log(FAC_SIP, PRI_WARNING,
                     "WebServer::ProcessEvent no '" EVENTTYPE "' variable found"
                     );
    }


    // We did not find a plugin so nobody handled this request.
    if(plugin == NULL)
    {
        response->setResponseFirstHeaderLine (
            HTTP_PROTOCOL_VERSION,
            HTTP_FILE_NOT_FOUND_CODE,
            HTTP_FILE_NOT_FOUND_TEXT );
    }
    Os::Logger::instance().flush();

}