def floodout(registrar): r_addr = registrar.locator r_port = registrar.port r_proto = registrar.protocol grasp.tprint("Chose registrar", r_addr, r_proto, r_port) ################################### # Finalise the locator ################################### proxy_locator.protocol = registrar.protocol if registrar.protocol == socket.IPPROTO_TCP: proxy_locator.port = t_port elif registrar.protocol == socket.IPPROTO_UDP: proxy_locator.port = u_port elif registrar.protocol == socket.IPPROTO_IPV6: proxy_locator.port = 0 else: return # unknown method ################################### # Flood it out for the pledges ################################### grasp.tprint("Flooding", proxy_obj.name, proxy_locator.locator, proxy_locator.protocol, proxy_locator.port) grasp.flood(_asa_nonce, proxy_ttl, grasp.tagged_objective(proxy_obj, proxy_locator)) return
def insert_pool(plen, prefix): """inserts IPv6 prefix in pool in canonical order""" pool_lock.acquire() if len(ppool) > 0: #Are there prefixes of this length? for i in range(len(ppool)): if ppool[i][0] < plen: #We are in shorter prefixes, keep searching continue elif (ppool[i][0] == plen): #We found the right length while (i < len(ppool)): if prefix == ppool[i][1]: grasp.tprint("Blocked insertion of duplicate prefix", prefstr(plen, prefix)) pool_lock.release() return if (prefix<ppool[i][1]) and (ppool[i][0] == plen) \ or (ppool[i][0] > plen): #it belongs right here ppool.insert(i, [plen, prefix]) pool_lock.release() return i += 1 else: #We found a greater length ppool.insert(i, [plen, prefix]) pool_lock.release() return #We didn't insert, so append ppool.append([plen, prefix]) pool_lock.release() return
def endit(snonce, r): """Support function for negotiator""" grasp.tprint("Failed", r) err = grasp.end_negotiate(asa_nonce, snonce, False, reason=r) if err: grasp.tprint("end_negotiate error:", grasp.etext[err]) return
def split_prefix(plen, prefix): """-> plen+1, prefix1, plen+1, prefix2""" #Find last non-zero bit lb = 127 for i in range(15, -1, -1): if prefix[i] == 0: lb -= 8 else: for j in bitvals: if not j & prefix[i]: lb -= 1 else: break break #grasp.ttprint("Last non-zero bit is",lb) #Check for valid split point if plen > 127 or plen <= lb: grasp.tprint("Cannot split prefix", prefstr(plen, prefix)) raise RuntimeError("Unsplittable prefix") new_plen = plen + 1 new_pref = bytes.fromhex('') j = plen // 8 for i in range(0, j): new_pref += bytes([prefix[i]]) new_pref += bytes([prefix[j] | bitmasks[new_plen % 8]]) while len(new_pref) < 16: new_pref += bytes.fromhex('00') return new_plen, prefix, new_plen, new_pref
def run(self): while self.running: self.reg_obj.value = "EST-TLS" grasp.tprint("FLOODING IDENTIFIER: ", self.locator.locator, " | IS IPv6: ", self.locator.is_ipaddress) #grasp.flood(asa_nonce, 120000, # grasp.tagged_objective(reg_obj,tcp_locator)) grasp.flood(self.asa_nonce, 120000, grasp.tagged_objective(self.reg_obj, self.locator)) time.sleep(10)
def run(self): while True: time.sleep(60) obj1.value = datetime.datetime.utcnow().strftime( "%Y-%m-%d %H:%M UTC from Briggs") err = grasp.flood(asa_nonce, 59000, [grasp.tagged_objective(obj1, None)]) if err: grasp.tprint("Flood failure:", grasp.etext[err]) time.sleep(5) if grasp.test_mode: dump_some()
def main(args): """ - initialize the queues to communicate with the threads - start the modules as individual threads """ tprint("starting main Thread") #start_new_thread(TLS_Server.main,()) threads = [] connectCandidates = [] graspDiscoverQueue = Queue() tlsConnectionQueue = Queue() threads.append(grasp_device.GRASP_device_Thread(graspDiscoverQueue, )) #threads.append(TLS_client.TLS_device_Thread(tlsConnectionQueue, )) threads.append(NETCONF_server.NETCONF_device_Thread()) threads.append(REST_client.REST_device_Thread(tlsConnectionQueue)) for t in threads: t.start() #tlsConnectionQueue.put('172.20.0.3') while (True): """ - read data from the graspDiscoverQueue und check if it is already known - if its already know, check when it was last tried - if the last connection attempt is longer than 30sek ago, try again (might change the value later) """ tmpValues = [graspDiscoverQueue.get(), datetime.datetime.now()] deviceKnown = False for candidate in connectCandidates: if tmpValues[0] == candidate[0]: deviceKnown = True timeNow = datetime.datetime.now() elapsedTime = (timeNow - candidate[1]).seconds #print('#####################last connected: ', elapsedTime) if elapsedTime > 30: candidate[1] = timeNow tlsConnectionQueue.put(candidate[0]) if not deviceKnown: connectCandidates.append(tmpValues) tlsConnectionQueue.put(tmpValues[0]) tprint("\n#################\n", connectCandidates, "\n#################\n") #tprint('##############\n##############') pass
def run(self): if quickly: grasp.tprint("Prefix delegator running quickly") else: grasp.tprint("Prefix delegator running slowly") while True: if quickly: time.sleep(1) else: time.sleep(grasp._prng.randint(10, 60)) p = get_from_pool(subnet_length) if p == None: nudge_pool(subnet_length) else: delegated.append([subnet_length, p]) p = get4_from_pool(26) if p: delegated.append([122, p]) _l = len(delegated) if _l == 1: grasp.tprint("1 prefix was delegated") if _l > 1: if (not quickly) or (not _l % 10): grasp.tprint(_l, "prefixes were delegated") if (not quickly) and grasp.test_mode: dump_delegates()
def initASAs(self, registrar, proxy): ################################### # Main thread starts here ################################### grasp.tprint("==========================") grasp.tprint("GRASP Service is starting up.") grasp.tprint("==========================") #grasp.test_mode = True # tell everybody it's a test, will print extra diagnostics #time.sleep(1) # time to read the text #################################### # Register this ASA #################################### # The ASA name is arbitrary - it just needs to be # unique in the GRASP instance. grasp.skip_dialogue(False, False, True) _err, self._asa_nonce = grasp.register_asa("Pledge") if not _err: grasp.tprint("ASA Pledge registered OK") else: grasp.tprint("ASA registration failure:", grasp.etext[_err]) exit() #################################### # Construct a GRASP objective #################################### # This is an empty GRASP objective to find the proxy # It's only used for get_flood so doesn't need to be filled in if proxy: proxy_obj = grasp.objective("AN_proxy") proxy_obj.synch = True else: proxy_obj = None if registrar: reg_obj = grasp.objective("AN_join_registrar") reg_obj.synch = True else: reg_obj = None return proxy_obj, reg_obj
def run(self): grasp.tprint("Ready to negotiate", obj1.name, "as listener, unless pool is empty") while True: if len(ppool) > 0: #attempt to listen for negotiation err, snonce, answer = grasp.listen_negotiate(asa_nonce, obj1) if err: grasp.tprint("listen_negotiate error:", grasp.etext[err]) time.sleep(5) #to calm things if there's a looping error else: #got a new negotiation request; kick off a separate negotiator #so that multiple requests can be handled in parallel negotiator(snonce, answer).start() else: time.sleep(5) #hoping the pool will refill
def dump_some(): grasp.tprint("Objective registry contents:") for x in grasp._obj_registry: o= x.objective grasp.tprint(o.name,"ASA:",x.asa_id,"Listen:",x.listening,"Neg:",o.neg, "Synch:",o.synch,"Count:",o.loop_count,"Value:",o.value) grasp.tprint("Flood cache contents:") for x in grasp._flood_cache: grasp.tprint(x.objective.name,"count:",x.objective.loop_count,"value:", x.objective.value,"source",x.source.locator, x.source.protocol, x.source.port,"expiry",x.source.expire)
def dump_some(): """Dumps some GRASP internals for debugging.""" grasp.tprint("Objective registry contents:") for x in grasp._obj_registry: o= x.objective grasp.tprint(o.name,"ASA:",x.asa_id,"Listen:",x.listening,"Neg:",o.neg, "Synch:",o.synch,"Count:",o.loop_count,"Value:",o.value) grasp.tprint("Flood cache contents:") for x in grasp._flood_cache: grasp.tprint(x.objective.name,"count:",x.objective.loop_count,"value:", x.objective.value,"source",x.source) time.sleep(5)
def run(self): answer=self.nobj snonce=self.snonce grasp.ttprint("listened, answer",answer.name, answer.value) grasp.tprint("Got MUD URL", answer.value, "from", ipaddress.IPv6Address(snonce.id_source)) if grasp.tname(answer.value)!="str": endit(snonce, "Not a string") elif answer.value[0:8]!="https://": endit(snonce, "Not https: scheme") #could do other sanity checks else: #sanity checks passed #Now the MUD manager can process the URL process_MUD_URL(answer.value) #close the session normally (with no feedback to peer) err = grasp.end_negotiate(asa_nonce, snonce, True) if err: grasp.tprint("end_negotiate error:",grasp.etext[err])
def run(self): while True: stopt = time.monotonic() + 1 #Don't hold lock for >1s pool_lock.acquire() if len(ppool) > 1: #at least 2 entries l1 = ppool[0][0] p1 = ppool[0][1] for i in range(1, len(ppool)): if time.monotonic() > stopt: break l2 = ppool[i][0] p2 = ppool[i][1] if l1 == l2: #same length, are p1 and p2 combinable? #grasp.tprint(l1,ipaddress.IPv6Address(p1),l2,ipaddress.IPv6Address(p2)) if p1 == p2: #this should never happen, but if it does # we'll log it and delete the duplicate grasp.tprint("Deleting duplicate prefix", prefstr(l2, p2)) del ppool[i] break nl = l1 - 1 np = mask_prefix(nl, p1) if np == mask_prefix(nl, p2): #yes del ppool[i] del ppool[i - 1] pool_lock.release() insert_pool(nl, np) pool_lock.acquire() break #different length or no match, move on l1 = l2 p1 = p2 pool_lock.release() time.sleep(5)
def run(self): answer = self.nobj shandle = self.shandle grasp.ttprint("listened, answer", answer.name, answer.value) grasp.tprint("Got message:", answer.value) err = False while not err: err, stuff = grasp.grecv(asa_handle, shandle, 60000) if not err: grasp.tprint("Peer said", stuff) tweet = input("Your message:") err = grasp.gsend(asa_handle, shandle, tweet) grasp.tprint("Send/recv error:", grasp.etext[err]) #all errors are fatal, the session is dead grasp.tprint("End of session")
def dump_delegates(): """Print delegated prefixes""" grasp.tprint("Delegated prefixes:") if len(delegated) == 0: grasp.tprint("(none)") else: for x in delegated: grasp.tprint(prefstr(x[0], x[1])) return
def check_sig(j,sig): """ j is the MUD file (JSON) to be validated, sig is the URL of the signature file, return True if verified, else False.""" mfile = cwd+"/mud.mud" file = open(mfile, "wb") file.write(j) file.close() try: pfile = cwd+"/p7s.p7s" p7s = requests.get(sig).content file = open(pfile, "wb") file.write(p7s) file.close() except: grasp.tprint("Couldn't fetch signature file") return False cmd = ['openssl', 'cms', '-verify', '-in', pfile, '-inform', 'DER', '-content', mfile, '-binary'] if 'CAfile' in globals(): cmd.append('-CAfile') cmd.append(CAfile) elif 'CApath' in globals(): cmd.append('-CApath') cmd.append(CApath) x = run(cmd) grasp.ttprint(x) try: os.remove(mfile) os.remove(pfile) except: pass if x.returncode != 0: return False else: return True
def run(self): received_obj=self.nobj snonce=self.snonce grasp.tprint("Got request for QUADS keys") if received_obj.dry: endit(snonce,"Dry run not supported") else: #unwrap pledge's request pledge_password = private_key.decrypt( received_obj.value[0], padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)) if pledge_password != password: endit(snonce,"Incorrect password") else: #prepare pledge's public key pub_key = serialization.load_pem_public_key( received_obj.value[1], backend=default_backend() ) #prepare the QUADS keys chunk = cbor.dumps([key, iv]) grasp.tprint("Sending keys") #encrypt chunk received_obj.value = pub_key.encrypt( chunk, padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)) grasp.ttprint("Sending",len(chunk),"bytes") #send keys as negotiation step err,temp,received_obj = grasp.negotiate_step(asa_nonce, snonce, received_obj, 1000) grasp.ttprint("Negotiation step gave:", err, temp, received_obj) if not err: # the other end signalled End/Accept grasp.tprint("Ended transfer") else: #other end rejected or loop count exhausted if err==grasp.errors.loopExhausted: # we need to signal the end endit(snonce, grasp.etext[err]) else: grasp.tprint("Failed:",grasp.etext[err])
def dump_pool(): """Print prefix pool""" grasp.tprint("Prefix pool contents:") pool_lock.acquire() if len(ppool) == 0: grasp.tprint("(empty)") else: for x in ppool: grasp.tprint(prefstr(x[0], x[1])) pool_lock.release() return
grasp.tprint(o.name, "ASA:", x.asa_id, "Listen:", x.listening, "Neg:", o.neg, "Synch:", o.synch, "Count:", o.loop_count, "Value:", o.value) grasp.tprint("Flood cache contents:") for x in grasp._flood_cache: grasp.tprint(x.objective.name, "count:", x.objective.loop_count, "value:", x.objective.value, "source", x.source.locator, x.source.protocol, x.source.port, "expiry", x.source.expire) ################################### # Main thread starts here ################################### grasp.tprint("================================") grasp.tprint("ASA ACPcontainer is starting up.") grasp.tprint("================================") grasp.tprint("This is a demonstration Autonomic Service Agent.") grasp.tprint("It mimics an established ACP node by") grasp.tprint("announcing itself to potential on-link") grasp.tprint("peers by a flooded GRASP objective.") grasp.tprint("It also announce itself as an EST server.") grasp.tprint("On Windows or Linux, there should soon be") grasp.tprint("a nice window that displays the process.") grasp.tprint("==========================") #grasp.test_mode = True # tell everybody it's a test, will print extra diagnostics time.sleep(8) # time to read the text ####################################
def run(self): nobj = self.nobj snonce = self.snonce try: nobj.value = cbor.loads(nobj.value) grasp.tprint("CBOR value decoded") _cbor = True except: _cbor = False req_ipv = nobj.value[ipv] #req_PD = nobj.value[PD] req_plen = nobj.value[lgth] if len(nobj.value) == lgth + 1: nobj.value.append(None) #grasp.tprint("Got request for IPv"+str(req_ipv)+"; PD=", req_PD, "length=", req_plen) grasp.tprint("Got request for IPv" + str(req_ipv) + "; length=", req_plen) if nobj.dry: grasp.tprint("Dry run (not handled by this implementation)") result = True reason = None if len(ppool) == 0: endit(snonce, "Prefix pool empty") elif req_ipv == 6: if req_plen < 32 or req_plen > subnet_max: endit(snonce, "Prefix length out of range") else: pref = get_from_pool(req_plen) if not pref: #other end wants too much, we try to make an offer while (not pref) and (req_plen < subnet_max): req_plen += 1 pref = get_from_pool(req_plen) if pref: nobj.value = [6, req_plen, pref] #nobj.value = [6, False, req_plen, pref] grasp.tprint("Starting negotiation") #we are offering the shortest prefix we can, so no #negotiation loop can happen grasp.tprint("Offering", prefstr(req_plen, pref)) if _cbor: nobj.value = cbor.dumps(nobj.value) err, temp, nobj = grasp.negotiate_step( asa_nonce, snonce, nobj, 1000) grasp.ttprint("Step gave:", err, temp, nobj) if (not err) and temp == None: grasp.tprint("Negotiation succeeded") elif not err: #we don't have enough resource, we will reject insert_pool(req_plen, pref) endit(snonce, "Insufficient resource") else: #other end rejected or loop count exhausted insert_pool(req_plen, pref) if err == grasp.errors.loopExhausted: # we need to signal the end endit(snonce, "Loop count exhausted") else: grasp.tprint("Failed:", grasp.etext[err]) #end of negotiation else: #got nothing suitable from pool endit(snonce, "No prefix available") elif req_ipv == 4: if req_plen < 16 or req_plen > 32: endit(snonce, "Prefix length out of range") else: pref = get4_from_pool(req_plen) if pref: nobj.value = [4, req_plen, pref[12:]] #nobj.value = [4, False, req_plen, pref[12:]] grasp.tprint("Starting negotiation") #we are offering the shortest prefix we can, so no #negotiation loop can happen grasp.tprint("Offering", pref4str(req_plen, pref[12:])) if _cbor: nobj.value = cbor.dumps(nobj.value) err, temp, nobj = grasp.negotiate_step( asa_nonce, snonce, nobj, 1000) grasp.ttprint("Step gave:", err, temp, nobj) if (not err) and temp == None: grasp.tprint("Negotiation succeeded") elif not err: #we don't have enough resource, we will reject insert_pool(req_plen, pref) endit(snonce, "Insufficient resource") else: #other end rejected or loop count exhausted insert_pool(req_plen, pref) if err == grasp.errors.loopExhausted: # we need to signal the end endit(snonce, "Loop count exhausted") else: grasp.tprint("Failed:", grasp.etext[err]) #end of negotiation else: #got nothing suitable from pool endit(snonce, "No prefix available")
for x in grasp._obj_registry: o= x.objective grasp.tprint(o.name,"ASA:",x.asa_id,"Listen:",x.listening,"Neg:",o.neg, "Synch:",o.synch,"Count:",o.loop_count,"Value:",o.value) grasp.tprint("Flood cache contents:") for x in grasp._flood_cache: grasp.tprint(x.objective.name,"count:",x.objective.loop_count,"value:", x.objective.value,"source",x.source.locator, x.source.protocol, x.source.port,"expiry",x.source.expire) ################################### # Main thread starts here ################################### grasp.tprint("==========================") grasp.tprint("ASA Newby is starting up.") grasp.tprint("==========================") grasp.tprint("Newby is a demonstration Autonomic Service Agent.") grasp.tprint("It shows how a new ACP peer will find its") grasp.tprint("ACP neighbors and EST servers.") grasp.tprint("On Windows or Linux, there should soon be") grasp.tprint("a nice window that displays the process.") grasp.tprint("==========================") #grasp.test_mode = True # tell everybody it's a test, will print extra diagnostics time.sleep(8) # time to read the text #################################### # Register this ASA
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import grasp import time grasp.tprint("==========================") grasp.tprint("ASA TestClient is starting up.") grasp.tprint("==========================") grasp.tprint("TestClient is a demonstration Autonomic Service Agent.") grasp.tprint("It just tests out gsend() and grecv() by talking to its peer") grasp.tprint("On Windows or Linux, there should be a nice window") grasp.tprint("that displays the talking process.") grasp.tprint("==========================") time.sleep(8) # so the user can read the text #################################### # Register ASA/objectives #################################### name = "TestClient" err,asa_handle = grasp.register_asa(name) if err: exit() grasp.tprint("ASA", name, "registered OK") obj3 = grasp.objective("EX3") obj3.neg = True err = grasp.register_obj(asa_handle,obj3)
def run(self): answer = self.nobj snonce = self.snonce try: answer.value = cbor.loads(answer.value) grasp.tprint("CBOR value decoded") _cbor = True except: _cbor = False grasp.ttprint("listened, answer", answer.name, answer.value) grasp.tprint("Got request for", answer.value[0], answer.value[1]) if answer.dry: grasp.tprint("Dry run") result = True reason = None if answer.value[0] != "NZD": endit(snonce, "Invalid currency") elif answer.value[1] > reserves / 2: #other end wants too much, we need to negotiate proffer = int(reserves / 2) step = 1 concluded = False grasp.tprint("Starting negotiation") while not concluded: #proffer some resource grasp.tprint("Offering NZD", proffer) answer.value[1] = proffer if _cbor: answer.value = cbor.dumps(answer.value) err, temp, answer = grasp.negotiate_step( asa_nonce, snonce, answer, 1000) grasp.ttprint("Step", step, "gave:", err, temp, answer) step += 1 if (not err) and temp == None: concluded = True grasp.tprint("Negotiation succeeded") elif not err: try: answer.value = cbor.loads(answer.value) grasp.tprint("CBOR value decoded") except: pass grasp.tprint("Loop count", answer.loop_count, "request", answer.value[1]) #maybe wait (for no particular reason) if grasp._prng.randint(1, 10) % 2: err1 = grasp.negotiate_wait(asa_nonce, snonce, wt) grasp.tprint("Tried wait:", grasp.etext[err1]) time.sleep( 10 ) # if wt<10000 this tests anomaly handling by the peer grasp.tprint("Woke up") if proffer < 0.6 * reserves: proffer += 10 if proffer > answer.value[1]: proffer = answer.value[ 1] - 1 #always be a little mean else: #we don't have enough resource, we will reject result = False #randomly choose English or Russian error message if reserves % 2: reason = "Insufficient funds" else: reason = u"Недостаточно средств" endit(snonce, reason) concluded = True else: #other end rejected or loop count exhausted concluded = True result = False if err == grasp.errors.loopExhausted: # we need to signal the end endit(snonce, grasp.etext[err]) elif err == grasp.errors.declined and answer != "": grasp.tprint("Declined:", answer) else: grasp.tprint("Failed:", grasp.etext[err]) #end of negotiation loop pass #out of negotiation loop else: #we can accept the initially requested value grasp.tprint("Request accepted") err = grasp.end_negotiate(asa_nonce, snonce, True) if err: grasp.tprint("end_negotiate error:", grasp.etext[err])
def endit(snonce, r): grasp.tprint("Failed", r) err = grasp.end_negotiate(asa_nonce, snonce, False, reason=r) if err: grasp.tprint("end_negotiate error:", grasp.etext[err])
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import grasp import threading import time import datetime import cbor ## import ipaddress grasp.tprint("==========================") grasp.tprint("ASA Briggs is starting up.") grasp.tprint("==========================") grasp.tprint("Briggs is a demonstration Autonomic Service Agent.") grasp.tprint("It tests out several basic features of GRASP, and") grasp.tprint("then runs indefinitely as one side of a negotiation.") grasp.tprint("It acts as the banker, giving out money, and can") grasp.tprint("handle multiple overlapping negotiations.") grasp.tprint("The sum available is random for each negotiation,") grasp.tprint("and the negotiation timeout is changed at random.") grasp.tprint("On Windows or Linux, there should be a nice window") grasp.tprint("that displays the negotiation process.") grasp.tprint("==========================") #grasp.test_mode = True # set if you want detailed diagnostics time.sleep(8) # so the user can read the text #################################### # Register ASA/objectives ####################################
def get_dns_info(dom): """Obtain and return all DNS-SD records for a domain""" global obj3 global failct #start of a negotiating session obj3.value = dom obj3.loop_count = 10 #allows for some fragmentation # As a random test, use CBOR (Tag 24) format for value (should work) if not grasp._prng.randint(0, 3): _cbor = True else: _cbor = False # As a random test, request dry run (should fail) if not grasp._prng.randint(0, 7): obj3.dry = True # random error for testing purposes else: obj3.dry = False grasp.tprint("Asking for", obj3.value, "; dry run", obj3.dry, "; Tag 24", _cbor) #discover a peer if failct > 3: failct = 0 grasp.tprint("Flushing", obj3.name, "discovery") _, ll = grasp.discover(asa_nonce, obj3, 1000, flush=True) else: _, ll = grasp.discover(asa_nonce, obj3, 1000) if ll == []: grasp.tprint("Discovery failed") failct += 1 return grasp.ttprint("Discovered locator", ll[0].locator) #attempt to negotiate if _cbor: #CBORise the value obj3.value = cbor.dumps(obj3.value) reply = [] err, snonce, answer = grasp.req_negotiate(asa_nonce, obj3, ll[0], None) if err: if err == grasp.errors.declined and answer != "": _e = answer else: _e = grasp.etext[err] grasp.tprint("req_negotiate error:", _e) failct += 1 grasp.tprint("Fail count", failct) time.sleep(5) #to calm things if there's a looping error elif (not err) and snonce: grasp.ttprint("requested, session_nonce:", snonce, "answer", answer) _found_cbor = False if _cbor: answer.value, _found_cbor = detag(answer.value) grasp.ttprint("Received reply", answer.value) if _cbor != _found_cbor: #Anomaly, get me out of here grasp.tprint("CBOR anomaly 1 - missing segment?") grasp.end_negotiate(asa_nonce, snonce, False, reason="CBOR anomaly 1 - missing segment?") elif not grasp._prng.randint(0, 7): ####################################################### # As a random test of robustness, send a bogus response answer.value = "rubbish" grasp.tprint("Sending rubbish") if _cbor: #CBORise the value answer.value = cbor.dumps(answer.value) err, temp, answer = grasp.negotiate_step(asa_nonce, snonce, answer, 1000) grasp.ttprint("Reply to rubbish:", err, temp, answer) _found_cbor = False if _cbor and (not err): answer.value, _found_cbor = detag(answer.value) if (not err) and temp == None: grasp.tprint("Unexpected answer:", answer.value) elif (not err) and _cbor != _found_cbor: grasp.tprint("CBOR anomaly 2 - missing segment?") elif not err: grasp.tprint("Loop count", answer.loop_count, "unexpected answer", answer.value) err = grasp.end_negotiate(asa_nonce, snonce, False, reason="Unexpected answer") if err: grasp.tprint("end_negotiate error:", grasp.etext[err]) else: #other end rejected if err == grasp.errors.declined and answer != "": _e = answer else: _e = grasp.etext[err] grasp.tprint("Peer reject:", _e) # End of random test of robustness ####################################################### else: #Received answer looping = True while looping: grasp.ttprint("Answer is", answer.value) if 'MORE' in answer.value: #need to go again reply += answer.value[:answer.value.index('MORE')] answer.value = "ACK" grasp.tprint("Sending ACK for more") if _cbor: #CBORise the value answer.value = cbor.dumps(answer.value) err, temp, answer = grasp.negotiate_step( asa_nonce, snonce, answer, 1000) if err: grasp.tprint("negotiate_step error:", grasp.etext[err]) looping = False elif _cbor: answer.value, _found_cbor = detag(answer.value) if _cbor != _found_cbor: #anomaly, get me out of here looping = False grasp.end_negotiate( asa_nonce, snonce, False, reason="CBOR anomaly - missing segment?") grasp.tprint("CBOR anomaly 3 - missing segment?") grasp.ttprint("Reply to ACK:", err, temp, answer) else: looping = False reply += answer.value err = grasp.end_negotiate(asa_nonce, snonce, True) if not err: if len(reply): grasp.tprint("Query succeeded", reply) else: grasp.tprint("Empty result") else: grasp.tprint("end_negotiate error:", grasp.etext[err]) else: #immediate end, strange grasp.tprint("Unexpected reply", answer.value) #end of a negotiating session time.sleep(5) #to keep things calm... return
if len(reply): grasp.tprint("Query succeeded", reply) else: grasp.tprint("Empty result") else: grasp.tprint("end_negotiate error:", grasp.etext[err]) else: #immediate end, strange grasp.tprint("Unexpected reply", answer.value) #end of a negotiating session time.sleep(5) #to keep things calm... return grasp.tprint("========================") grasp.tprint("ASA AskDNSSD is starting up.") grasp.tprint("========================") grasp.tprint("AskDNSSD is a demonstration Autonomic Service Agent.") grasp.tprint("It acts as a client, asking for DNS-SD information.") grasp.tprint("On Windows or Linux, there should be a nice window") grasp.tprint("that displays the process.") grasp.tprint("========================") #################################### # General initialisation #################################### #grasp.test_mode = True # tell everybody it's a test time.sleep(8) # so the user can read the text failct = 0 # fail counter to control discovery retries
def run(self): answer=self.nobj snonce=self.snonce answer.value, _cbor = detag(answer.value) if _cbor: grasp.tprint("CBOR value decoded") grasp.tprint("Got request") if answer.dry: endit(snonce,"Dry run not supported") return # Check format of request & extract fields try: req = answer.value.get("@rfcXXXX") except: req = None if not req: endit(snonce,"Not RFCXXXX format") return grasp.tprint(req) sel = req.get(cp.srv_element) if not sel: endit(snonce,"No service element") return msg_type = sel.get(cp.msg_type) if msg_type != cp.describe_request: endit(snonce,"Not describe_request") return srv_name = sel.get(cp.service) if not srv_name: endit(snonce,"No service name") return dom_name = sel.get(cp.domain) if not dom_name: endit(snonce,"No domain name") return # Construct DNS name dns_name = "_"+srv_name+"."+dom_name if dns_name[-1] != ".": dns_name += "." #Look for PTR record first found_something = False broken = False a = resolve(dns_name,'PTR') for r in a: found_something = True #extract the instance name raw_name = str(r) #decode Unicode escapes fixed_name = fix_string(raw_name) #remove bogus escapes name = fixed_name.replace("\\","") grasp.tprint("Got PTR name:",name) grasp.ttprint("Raw name:",raw_name) if name[-len(dns_name):] == dns_name: inst_name = name[0:-len(dns_name)-1] else: inst_name = name grasp.tprint("Instance name", inst_name) #start new reply element relement = new_relement() grasp.ttprint("Answer is", answer) relement[cp.outer][cp.sender_loop_count] = answer.loop_count relement[cp.outer][cp.srv_element][cp.instance] = inst_name relement[cp.outer][cp.srv_element][cp.service] = srv_name relement[cp.outer][cp.srv_element][cp.domain] = dom_name #look for other records a = resolve(fixed_name,'SRV') for r in a: grasp.ttprint("Got SRV", str(r)) #parse SRV record to extract the fields priority,weight,srv_port,srv_dom = str(r).split(' ') grasp.ttprint("Got SRV domain", srv_dom) relement[cp.outer][cp.srv_element][cp.priority] = int(priority) relement[cp.outer][cp.srv_element][cp.weight] = int(weight) srv_port = int(srv_port) #look for address records & build locators loc_l = [] a = resolve(srv_dom,'AAAA') for r in a: grasp.ttprint("Got AAAA", str(r)) srv_addr = ipaddress.IPv6Address(r) loc = [grasp.O_IPv6_LOCATOR,srv_addr.packed,17,srv_port] loc_l.append(["Internet", loc]) a = resolve(srv_dom,'A') for r in a: grasp.ttprint("Got A", str(r)) srv_addr = ipaddress.IPv4Address(r) loc = [grasp.O_IPv4_LOCATOR,srv_addr.packed,17,srv_port] loc_l.append(["Internet", loc]) loc_l.append(["Internet",[grasp.O_FQDN_LOCATOR,srv_dom,17,srv_port]]) #add locators to reply relement[cp.outer][cp.srv_element][cp.clocator] = loc_l a = resolve(name,'TXT') for r in a: grasp.tprint("Got TXT", r) #Note that TXT records may include quotes try: k,v = str(r).split(' ') if k[0]=='"': k=k[1:-1] if v[0]=='"': v=v[1:-1] grasp.ttprint("kv",k,v) relement[cp.outer][cp.srv_element][cp.kvps] = {k:v} except: grasp.ttprint("Couldn't split", str(r)) pass # The relement is now complete, send it as next negotiation step grasp.tprint("Reply step", relement) answer.value = relement if _cbor: answer.value=cbor.dumps(answer.value) #send reply as negotiation step err,temp,answer = grasp.negotiate_step(asa_nonce, snonce, answer, 1000) grasp.ttprint("Negotiation step gave:", err, temp, answer) if (not err) and temp==None: grasp.tprint("Reply step succeeded") elif not err: answer.value, _ = detag(answer.value) if _: grasp.tprint("CBOR value decoded") if answer.value !="ACK": grasp.tprint("Unexpected reply: loop count", answer.loop_count, "value",answer.value) endit(snonce, "Unexpected reply") broken = True break else: #other end rejected or loop count exhausted if err==grasp.errors.loopExhausted: # we need to signal the end endit(snonce, grasp.etext[err]) else: grasp.tprint("Failed:",grasp.etext[err]) broken = True break #Sent all relements if broken: return if not found_something: #NXDOMAIN endit(snonce, "Service not found") else: err = grasp.end_negotiate(asa_nonce, snonce, True) if err: grasp.tprint("end_negotiate error:",grasp.etext[err])
break #Sent all relements if broken: return if not found_something: #NXDOMAIN endit(snonce, "Service not found") else: err = grasp.end_negotiate(asa_nonce, snonce, True) if err: grasp.tprint("end_negotiate error:",grasp.etext[err]) #end of negotiation grasp.tprint("==========================") grasp.tprint("ASA GetDNSSD2 is starting up.") grasp.tprint("==========================") grasp.tprint("GetDNSSD2 is a demonstration Autonomic Service Agent.") grasp.tprint("It runs indefinitely as a gateway to DNS,") grasp.tprint("to fetch and parse SRV and related records,") grasp.tprint("to proxy DNS-SD for GRASP nodes.") grasp.tprint("It is implemented using a negotiation objective") grasp.tprint("that can handle overlapping requests.") grasp.tprint("On Windows or Linux, there should be a nice") grasp.tprint("window that displays the process.") grasp.tprint("==========================") #################################### # General initialisation ####################################