[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [stem/master] Generalizing PGP style block parsing



commit 54c3e6b7c6ea41ff29230c4e6a476f6f7fbac19a
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date:   Mon Mar 19 08:35:12 2012 -0700

    Generalizing PGP style block parsing
    
    Descriptors include blocks for both "RSA PUBLIC KEY" and "SIGNATURE" so
    generalizing that parser (the spec around how to handle these blocks is wrong
    and I'll fix that later). I'm also including the block type since callers will
    want that to be prepared for encryption migrations.
---
 stem/descriptor/server_descriptor.py |   59 +++++++++++++++++++---------------
 1 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 73c7f27..9512fa3 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -19,11 +19,11 @@ from stem.descriptor.descriptor import Descriptor
 ENTRY_START = "router"
 ENTRY_END   = "router-signature"
 
-KEYWORD_CHAR    = "[a-zA-Z0-9-]"
-WHITESPACE      = "[ \t]"
-KEYWORD_LINE    = re.compile("^(%s+)%s*(%s*)$" % (KEYWORD_CHAR, WHITESPACE, KEYWORD_CHAR))
-PUBLIC_KEY_START = re.compile("^-----BEGIN (%s+) PUBLIC KEY-----$" % KEYWORD_CHAR)
-PUBLIC_KEY_END   = "-----END %s PUBLIC KEY-----"
+KEYWORD_CHAR    = "a-zA-Z0-9-"
+WHITESPACE      = " \t"
+KEYWORD_LINE    = re.compile("^([%s]+)[%s]*([%s]*)$" % (KEYWORD_CHAR, WHITESPACE, KEYWORD_CHAR))
+PGP_BLOCK_START = re.compile("^-----BEGIN ([%s%s]+)-----$" % (KEYWORD_CHAR, WHITESPACE))
+PGP_BLOCK_END   = "-----END %s-----"
 
 # entries must have exactly one of the following
 REQUIRED_FIELDS = (
@@ -53,16 +53,17 @@ def parse_server_descriptors_v2(path, descriptor_file):
   
   pass
 
-def _get_key_block(remaining_contents):
+def _get_psudo_pgp_block(remaining_contents):
   """
-  Checks if given contents begins with a public key block and, if so, pops it
-  off and provides it back to the caller.
+  Checks if given contents begins with a pseudo-Open-PGP-style block and, if
+  so, pops it off and provides it back to the caller.
   
   Arguments:
     remaining_contents (list) - lines to be checked for a public key block
   
   Returns:
-    String with the public key block, or None if it doesn't exist
+    (str, str) tuple with the block type and the armor wrapped contents, this
+    returns (None, None) instead if it doesn't exist
   
   Raises:
     ValueError if the contents starts with a key block but it's malformed (for
@@ -70,25 +71,25 @@ def _get_key_block(remaining_contents):
   """
   
   if not remaining_contents:
-    return None # nothing left
+    return (None, None) # nothing left
   
-  key_match = PUBLIC_KEY_START.match(remaining_contents[0])
+  block_match = PGP_BLOCK_START.match(remaining_contents[0])
   
-  if key_match:
-    key_type = key_match.groups()[0]
-    key_lines = []
+  if block_match:
+    block_type = block_match.groups()[0]
+    block_lines = []
     
     while True:
       if not remaining_contents:
         raise ValueError("Unterminated public key block")
       
       line = remaining_contents.pop(0)
-      key_lines.append(line)
+      block_lines.append(line)
       
-      if line == PUBLIC_KEY_END $ key_type:
-        return "\n".join(key_lines)
+      if line == PGP_BLOCK_END $ block_type:
+        return block_type, "\n".join(block_lines)
   else:
-    return None
+    return (None, None)
 
 class ServerDescriptorV2(Descriptor):
   """
@@ -111,7 +112,9 @@ class ServerDescriptorV2(Descriptor):
     hibernating (bool)       - flag to indicate if the relay was hibernating when published (*)
     uptime (int)             - relay's uptime when published in seconds
     onion_key (str)          - key used to encrypt EXTEND cells (*)
+    onion_key_type (str)     - block type of the onion_key, probably "RSA PUBLIC KEY" (*)
     signing_key (str)        - relay's long-term identity key (*)
+    signing_key_type (str)   - block type of the signing_key, probably "RSA PUBLIC KEY" (*)
     
     * required fields, others are left as None if undefined
   """
@@ -153,14 +156,14 @@ class ServerDescriptorV2(Descriptor):
         raise ValueError("Line contains invalid characters: %s" % line)
       
       keyword, value = line_match.groups()
-      key_block = _get_key_block(remaining_contents)
+      block_type, block_contents = _get_psudo_pgp_block(remaining_contents)
       
       if keyword in ("accept", "reject"):
         exit_policy_lines.append("%s %s" % (keyword, value))
       elif keyword in entries:
-        entries[keyword].append((value, key_block))
+        entries[keyword].append((value, block_type, block_contents))
       else:
-        entries[keyword] = [(value, key_block)]
+        entries[keyword] = [(value, block_type, block_contents)]
     
     # validates restrictions about the entries
     
@@ -175,7 +178,9 @@ class ServerDescriptorV2(Descriptor):
     # parse all the entries into our attributes
     
     for keyword, values in entres.items():
-      value, key_block = values[0] # most just work with the first (and only) value
+      # most just work with the first (and only) value
+      value, block_type, block_contents = values[0]
+      
       line = "%s %s" % (keyword, value) # original line
       
       if keyword == "router":
@@ -267,15 +272,17 @@ class ServerDescriptorV2(Descriptor):
         
         self.uptime = int(value)
       elif keyword == "onion-key":
-        if not key_block:
+        if not block_type or not block_contents:
           raise TypeError("Onion key line must be followed by a public key: %s" % value)
           
-        self.onion_key = key_block
+        self.onion_key_type = block_type
+        self.onion_key = block_contents
       elif keyword == "signing-key":
-        if not key_block:
+        if not block_type or not block_contents:
           raise TypeError("Signing key line must be followed by a public key: %s" % value)
           
-        self.signing_key = key_block
+        self.signing_key_type = block_type
+        self.signing_key = block_contents
       else:
         unrecognized_entries.append(line)
 



_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits