Esempio n. 1
0
def process_API_call(fullrequest):

    callname = fullrequest.split('|')[0]

    if DEBUG_MODE:
        servicelogger.log("Now handling call: " + callname)

    if callname not in API_dict:
        raise nmAPI.BadRequest("Unknown Call")

    # find the entry that describes this call...
    numberofargs, permissiontype, APIfunction = API_dict[callname]

    # we'll do the signature checks first... (the signature needs to be stripped
    # off to get the args anyways)...

    if permissiontype == 'Public':
        # There should be no signature, so this is the raw request...
        if len(fullrequest.split('|')) < numberofargs - 1:
            raise nmAPI.BadRequest("Not Enough Arguments")

        # If there are 3 args, we want to split at most 3 times (the first item is
        # the callname)
        callargs = fullrequest.split('|', numberofargs)
        # return any output for the user...
        return APIfunction(*callargs[1:])

    else:
        # strip off the signature and get the requestdata
        requestdata, requestsignature = fastsigneddata.signeddata_split_signature(
            fullrequest)

        # NOTE: the first argument *must* be the vessel name!!!!!!!!!!!
        vesselname = requestdata.split('|', 2)[1]

        if vesselname not in nmAPI.vesseldict:
            raise nmAPI.BadRequest('Unknown Vessel')

        # I must have something to check...
        if permissiontype == 'Owner':
            # only the owner is allowed, so the list of keys is merely that key
            allowedkeys = [nmAPI.vesseldict[vesselname]['ownerkey']]
        else:
            # the user keys are also allowed
            allowedkeys = [nmAPI.vesseldict[vesselname]['ownerkey']
                           ] + nmAPI.vesseldict[vesselname]['userkeys']

        # I need to pass the fullrequest in here...
        ensure_is_correctly_signed(fullrequest, allowedkeys,
                                   nmAPI.vesseldict[vesselname]['oldmetadata'])

        # If there are 3 args, we want to split at most 3 times (the first item is
        # the callname)
        callargs = requestdata.split('|', numberofargs)

        #store the request signature as old metadata
        nmAPI.vesseldict[vesselname]['oldmetadata'] = requestsignature

        # return any output for the user...
        return APIfunction(*callargs[1:])
def ensure_is_correctly_signed(fullrequest, allowedkeys, oldmetadata):

  # check if time_updatetime has been called, if not, call it
  try:
    time.time_gettime()
  except time.TimeError:
    time.time_updatetime(34612)
    

  # check if request is still valid and has not expired
  # this code has been added to resolve an issue where we are not checking of the request is expired in the case that there is no old metadata
  thesigneddata, signature = fullrequest.rsplit('!',1)
  junk, rawpublickey, junktimestamp, expiration, sequencedata, junkdestination = thesigneddata.rsplit('!',5)
  if not fastsigneddata.signeddata_iscurrent(float(expiration)):
    raise nmAPI.BadRequest,"Bad Signature on '"+fullrequest+"'"
    
  
  # check if sequence id is equal to zero in the case that there is no data. 
  # This is intended to fix a previous issue where any value could be used as a sequence id when there was no old metadata (only 0 is valid in this case)
  if (sequencedata!="None"):
    junksequecename,sequenceno = sequencedata.rsplit(':',1)
    if not oldmetadata:
      if int(sequenceno) != 0:
        raise nmAPI.BadRequest, "Illegal sequence id on '"+fullrequest+"'"
    
  # ensure it's correctly signed, if not report this and exit
  if not fastsigneddata.signeddata_issignedcorrectly(fullrequest):
    raise nmAPI.BadRequest,"Bad Signature on '"+fullrequest+"'"

  request, requestsignature = fastsigneddata.signeddata_split_signature(fullrequest)

  signingpublickey = fastsigneddata.signeddata_split(fullrequest)[1]

  # If they care about the key, do they have a valid key?
  if allowedkeys and signingpublickey not in allowedkeys:
    raise nmAPI.BadRequest('Insufficient Permissions')

  #bug fix: old metadata may be storing full requests, so we are using a crude way to check if the full request is stored, or if just the signature is
  metadata_is_fullrequest = False
  if not(oldmetadata==None):
    oldrawpublickey, oldrawtimestamp, oldrawexpiration, oldrawsequenceno, oldrawdestination, oldjunksignature = oldmetadata.rsplit('!',5)
    try:
      conversion_try = rsa.rsa_string_to_publickey(oldrawpublickey[1:])
    except ValueError:
      #we catch any exception here that occurs when trying to convert, and assume it is because we are dealing with a full request
      #catching the general exception is ok here since we will do this same conversion in shouldtrust
      metadata_is_fullrequest = True
  
  #BUG FIX: only signature should be passed in for oldmetadata since full request may take extensive space
  if metadata_is_fullrequest:
    (shouldtrust, reasons) = fastsigneddata.signeddata_shouldtrust(oldmetadata, fullrequest)
  else:
    (shouldtrust, reasons) = fastsigneddata.signeddata_shouldtrustmeta(oldmetadata, fullrequest)
    
  if not shouldtrust:
    # let's tell them what is wrong.
    raise nmAPI.BadRequest,"Signature problem: "+' '.join(reasons)
  else:
    # We should trust...  All is well!
    return