@@ -73,24 +73,42 @@ def set_blacklist_location(location):
7373 global blacklist_location
7474 blacklist_location = location
7575
76+ def canonicalize_commitment_str (commitment ):
77+ # Worthy of note: an actually valid commitment
78+ # has a specific length, but that's not at issue here:
79+ # if the commitment isn't valid, it can't be reused.
80+ # This makes sure of a 1-1 mapping between a valid commitment
81+ # byte string and its hex representation.
82+ try :
83+ commitment = bytes .fromhex (commitment ).hex ()
84+ except ValueError :
85+ return False
86+ return commitment
87+
7688def check_utxo_blacklist (commitment , persist = False ):
7789 """Compare a given commitment with the persisted blacklist log file,
7890 which is hardcoded to this directory and name 'commitmentlist' (no
7991 security or privacy issue here).
80- If the commitment has been used before, return False (disallowed),
92+ If the commitment is not of a valid format, return "invalid_format"; if
93+ it has been used before, return False (disallowed),
8194 else return True.
8295 If flagged, persist the usage of this commitment to the above file.
8396 """
84- #TODO format error checking?
97+ # Fix DOS potential: should check what is given as a value, not as a string;
98+ # but since it's passed as a string, the format must be canonical:
99+ commitment = canonicalize_commitment_str (commitment )
100+ if not commitment :
101+ return "invalid_format"
85102 fname = blacklist_location
86103 if os .path .isfile (fname ):
87104 with open (fname , "rb" ) as f :
88- blacklisted_commitments = [x .decode ('ascii' ).strip () for x in f .readlines ()]
105+ blacklisted_commitments = [x .decode ('ascii' ).strip (). lower () for x in f .readlines ()]
89106 else :
90107 blacklisted_commitments = []
91108 if commitment in blacklisted_commitments :
92109 return False
93110 elif persist :
111+ # persisted commitments guaranteed to be canonical format
94112 blacklisted_commitments += [commitment ]
95113 with open (fname , "wb" ) as f :
96114 f .write ('\n ' .join (blacklisted_commitments ).encode ('ascii' ))
@@ -712,6 +730,7 @@ def on_JM_IOAUTH(self, nick, utxolist, pubkey, cjaddr, changeaddr, pubkeysig):
712730 #we broadcast them here, and not early - to avoid accidentally
713731 #blacklisting commitments that are broadcast between makers in real time
714732 #for the same transaction.
733+ #We don't need validity check here; we already did it.
715734 self .transfer_commitment (self .active_orders [nick ]["commit" ])
716735 #now persist the fact that the commitment is actually used.
717736 check_utxo_blacklist (self .active_orders [nick ]["commit" ], persist = True )
@@ -773,7 +792,11 @@ def on_order_fill(self, nick, oid, amount, taker_pk, commit):
773792 "Unsupported commitment type: " + str (commit [0 ]))
774793 return
775794 scommit = commit [1 :]
776- if not check_utxo_blacklist (scommit ):
795+ blacklist_check = check_utxo_blacklist (scommit )
796+ if blacklist_check == "invalid_format" :
797+ # Bad behaviour; ignore; don't forward it.
798+ return
799+ if not blacklist_check :
777800 log .msg ("Taker utxo commitment is blacklisted, rejecting." )
778801 self .mcc .send_error (nick , "Commitment is blacklisted: " + str (scommit ))
779802 #Note that broadcast is happening here to reflect an already
@@ -832,7 +855,7 @@ def on_commitment_seen(self, nick, commitment):
832855 """Triggered when we see a commitment for blacklisting
833856 appear in the public pit channel.
834857 """
835- #just add if necessary, ignore return value.
858+ #just add if necessary and valid , ignore return value.
836859 check_utxo_blacklist (commitment , persist = True )
837860 log .msg ("Received commitment broadcast by other maker: " + str (
838861 commitment ) + ", now blacklisted." )
@@ -842,8 +865,17 @@ def on_commitment_transferred(self, nick, commitment):
842865 """Triggered when a privmsg is received from another maker
843866 with a commitment to announce in public (obfuscation of source).
844867 We simply post it in public (not affected by whether we ourselves
845- are *accepting* commitment broadcasts.
868+ are *accepting* commitment broadcasts).
869+ There is no issue of malicious format in transfer: the only purpose
870+ of transfer is to give more possibility of blocking, not accepting.
871+ DOS risk would not be addressed by restricting format.
872+ However, as a kind of 'politeness', we are not going to pubmsg
873+ invalid-format commitments, in case other participants have old code
874+ that is not checking format (in short, why not).
846875 """
876+ commitment = canonicalize_commitment_str (commitment )
877+ if not commitment :
878+ return
847879 self .mcc .pubmsg ("!hp2 " + commitment )
848880
849881 @maker_only
0 commit comments