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