Esempio n. 1
0
static OCStackApplicationResult AmsMgrAclReqCallback(void *ctx, OCDoHandle handle,
    OCClientResponse * clientResponse)
{
    OC_LOG_V(INFO, TAG, "%s Begin", __func__ );

    (void)handle;
    PEContext_t *context = (PEContext_t *) ctx;
    SRMAccessResponse_t rsps;

    if (!ctx ||
        !clientResponse ||
        !clientResponse->payload||
        (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type) ||
        (clientResponse->result != OC_STACK_OK))
    {
        SRMSendResponse(ACCESS_DENIED_AMS_SERVICE_ERROR);
        goto exit;
    }

    if (context->state != AWAITING_AMS_RESPONSE)
    {
        OC_LOG_V(ERROR, TAG, "%s Invalid State ", __func__);
        context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
        SRMSendResponse(context->retVal);
        return OC_STACK_DELETE_TRANSACTION;
    }

    // Verify before installing ACL if the ID of the sender of this ACL is an AMS
    //service that this device trusts.
    rsps = ACCESS_DENIED;
    if((UUID_LENGTH == clientResponse->identity.id_length) &&
        memcmp(context->amsMgrContext->amsDeviceId.id, clientResponse->identity.id,
                       sizeof(context->amsMgrContext->amsDeviceId.id)) == 0)
    {
        OCStackResult ret =
                InstallNewACL(((OCSecurityPayload*)clientResponse->payload)->securityData);
        VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);

        OC_LOG_V(INFO, TAG, "%s : Calling checkPermission", __func__);
        rsps = CheckPermission(context, &context->subject, context->resource, context->permission);
        VERIFY_SUCCESS(TAG, (true == IsAccessGranted(rsps)), ERROR);

        OC_LOG_V(INFO, TAG, "%sAccess granted, Calling SRMCallCARequestHandler", __func__);
        context->retVal = ACCESS_GRANTED;
        SRMSendResponse(context->retVal);
        return OC_STACK_DELETE_TRANSACTION;
    }

exit:
    context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
    SRMSendResponse(context->retVal);
    FreeCARequestInfo(context->amsMgrContext->requestInfo);
    OICFree(context->amsMgrContext->endpoint);
    return OC_STACK_DELETE_TRANSACTION;
}
  static void InternalCallback(struct mg_connection *connection,
                               const struct mg_request_info *request)
  {
    MongooseServer* that = reinterpret_cast<MongooseServer*>(request->user_data);

    MongooseOutputStream stream(connection);
    HttpOutput output(stream, that->IsKeepAliveEnabled());

    // Check remote calls
    if (!that->IsRemoteAccessAllowed() &&
        request->remote_ip != LOCALHOST)
    {
      output.SendUnauthorized(ORTHANC_REALM);
      return;
    }


    // Extract the HTTP headers
    IHttpHandler::Arguments headers;
    for (int i = 0; i < request->num_headers; i++)
    {
      std::string name = request->http_headers[i].name;
      std::transform(name.begin(), name.end(), name.begin(), ::tolower);
      headers.insert(std::make_pair(name, request->http_headers[i].value));
    }


    // Extract the GET arguments
    IHttpHandler::GetArguments argumentsGET;
    if (!strcmp(request->request_method, "GET"))
    {
      HttpToolbox::ParseGetArguments(argumentsGET, request->query_string);
    }


    // Compute the HTTP method, taking method faking into consideration
    HttpMethod method = HttpMethod_Get;
    if (!ExtractMethod(method, request, headers, argumentsGET))
    {
      output.SendStatus(HttpStatus_400_BadRequest);
      return;
    }


    // Authenticate this connection
    if (that->IsAuthenticationEnabled() && !IsAccessGranted(*that, headers))
    {
      output.SendUnauthorized(ORTHANC_REALM);
      return;
    }


    // Apply the filter, if it is installed
    const IIncomingHttpRequestFilter *filter = that->GetIncomingHttpRequestFilter();
    if (filter != NULL)
    {
      std::string username = GetAuthenticatedUsername(headers);

      char remoteIp[24];
      sprintf(remoteIp, "%d.%d.%d.%d", 
              reinterpret_cast<const uint8_t*>(&request->remote_ip) [3], 
              reinterpret_cast<const uint8_t*>(&request->remote_ip) [2], 
              reinterpret_cast<const uint8_t*>(&request->remote_ip) [1], 
              reinterpret_cast<const uint8_t*>(&request->remote_ip) [0]);

      if (!filter->IsAllowed(method, request->uri, remoteIp, username.c_str()))
      {
        output.SendUnauthorized(ORTHANC_REALM);
        return;
      }
    }


    // Extract the body of the request for PUT and POST

    // TODO Avoid unneccessary memcopy of the body

    std::string body;
    if (method == HttpMethod_Post ||
        method == HttpMethod_Put)
    {
      PostDataStatus status;

      IHttpHandler::Arguments::const_iterator ct = headers.find("content-type");
      if (ct == headers.end())
      {
        // No content-type specified. Assume no multi-part content occurs at this point.
        status = ReadBody(body, connection, headers);          
      }
      else
      {
        std::string contentType = ct->second;
        if (contentType.size() >= multipartLength &&
            !memcmp(contentType.c_str(), multipart, multipartLength))
        {
          status = ParseMultipartPost(body, connection, headers, contentType, that->GetChunkStore());
        }
        else
        {
          status = ReadBody(body, connection, headers);
        }
      }

      switch (status)
      {
        case PostDataStatus_NoLength:
          output.SendStatus(HttpStatus_411_LengthRequired);
          return;

        case PostDataStatus_Failure:
          output.SendStatus(HttpStatus_400_BadRequest);
          return;

        case PostDataStatus_Pending:
          output.SendBody();
          return;

        default:
          break;
      }
    }


    // Decompose the URI into its components
    UriComponents uri;
    try
    {
      Toolbox::SplitUriComponents(uri, request->uri);
    }
    catch (OrthancException)
    {
      output.SendStatus(HttpStatus_400_BadRequest);
      return;
    }


    LOG(INFO) << EnumerationToString(method) << " " << Toolbox::FlattenUri(uri);

    bool found = false;

    try
    {
      if (that->HasHandler())
      {
        found = that->GetHandler().Handle(output, method, uri, headers, argumentsGET, body.c_str(), body.size());
      }
    }
    catch (OrthancException& e)
    {
      // Using this candidate handler results in an exception
      LOG(ERROR) << "Exception in the HTTP handler: " << e.What();

      try
      {
        switch (e.GetErrorCode())
        {
          case ErrorCode_InexistentFile:
          case ErrorCode_InexistentItem:
          case ErrorCode_UnknownResource:
            output.SendStatus(HttpStatus_404_NotFound);
            break;

          case ErrorCode_BadRequest:
          case ErrorCode_UriSyntax:
            output.SendStatus(HttpStatus_400_BadRequest);
            break;

          default:
            output.SendStatus(HttpStatus_500_InternalServerError);
        }
      }
      catch (OrthancException&)
      {
        // An exception here reflects the fact that an exception was
        // triggered after the status code was sent by the HTTP handler.
      }

      return;
    }
    catch (boost::bad_lexical_cast&)
    {
      LOG(ERROR) << "Exception in the HTTP handler: Bad lexical cast";
      output.SendStatus(HttpStatus_400_BadRequest);
      return;
    }
    catch (std::runtime_error&)
    {
      LOG(ERROR) << "Exception in the HTTP handler: Presumably a bad JSON request";
      output.SendStatus(HttpStatus_400_BadRequest);
      return;
    }

    if (!found)
    {
      output.SendStatus(HttpStatus_404_NotFound);
    }
  }