added tickets
[sfa.git] / util / hierarchy.py
index 738171f..e83b4d4 100644 (file)
 #      *.DBINFO - database info
 
 import os
+import report
 from cert import *
+from credential import *
 from gid import *
 from misc import *
 from config import *
+from geniticket import *
 
 class AuthInfo():
     hrn = None
+    gid_object = None
     gid_filename = None
     privkey_filename = None
     dbinfo_filename = None
 
     def __init__(self, hrn, gid_filename, privkey_filename, dbinfo_filename):
         self.hrn = hrn
-        self.gid_filename = gid_filename
+        self.set_gid_filename(gid_filename)
         self.privkey_filename = privkey_filename
         self.dbinfo_filename = dbinfo_filename
 
+    def set_gid_filename(self, fn):
+        self.gid_filename = fn
+        self.gid_object = None
+
     def get_gid_object(self):
-        return GID(filename = self.gid_filename)
+        if not self.gid_object:
+            self.gid_object = GID(filename = self.gid_filename)
+        return self.gid_object
 
     def get_pkey_object(self):
         return Keypair(filename = self.privkey_filename)
@@ -38,10 +48,14 @@ class AuthInfo():
         dict = eval(f.read())\r
         f.close()\r
         return dict\r
+\r
+    def update_gid_object(self, gid):\r
+        gid.save_to_file(self.gid_filename)\r
+        self.gid_object = gid\r
 
 class Hierarchy():
     def __init__(self, basedir="."):
-        self.basedir = basedir
+        self.basedir = os.path.join(basedir, "authorities")
 
     def get_auth_filenames(self, hrn):
         leaf = get_leaf(hrn)
@@ -62,7 +76,14 @@ class Hierarchy():
                os.path.exists(privkey_filename) and \
                os.path.exists(dbinfo_filename)
 
-    def create_auth(self, hrn):
+    def create_auth(self, hrn, create_parents=False):
+        report.trace("Hierarchy: creating authority: " + hrn)
+
+        # create the parent authority if necessary
+        parent_hrn = get_authority(hrn)
+        if (parent_hrn) and (not self.auth_exists(parent_hrn)) and (create_parents):
+            self.create_auth(parent_hrn, create_parents)
+
         (directory, gid_filename, privkey_filename, dbinfo_filename) = \
             self.get_auth_filenames(hrn)
 
@@ -78,7 +99,7 @@ class Hierarchy():
         pkey.save_to_file(privkey_filename)
 
         gid = self.create_gid(hrn, create_uuid(), pkey)
-        gid.save_to_file(gid_filename)
+        gid.save_to_file(gid_filename, save_parents=True)
 
         # XXX TODO: think up a better way for the dbinfo to work
 
@@ -87,25 +108,29 @@ class Hierarchy():
         dbinfo_file.write(str(dbinfo))\r
         dbinfo_file.close()
 
-    def get_auth_info(self, hrn, can_create=True):
-        if not self.auth_exists(hrn):
-            if not can_create:
-                return MissingAuthority(hrn)
+    def get_auth_info(self, hrn):
+        #report.trace("Hierarchy: getting authority: " + hrn)
 
-            self.create_auth(hrn)
+        if not self.auth_exists(hrn):
+            raise MissingAuthority(hrn)
 
         (directory, gid_filename, privkey_filename, dbinfo_filename) = \
             self.get_auth_filenames(hrn)
 
         auth_info = AuthInfo(hrn, gid_filename, privkey_filename, dbinfo_filename)
 
+        # check the GID and see if it needs to be refreshed
+        gid = auth_info.get_gid_object()
+        gid_refreshed = self.refresh_gid(gid)
+        if gid != gid_refreshed:
+            auth_info.update_gid_object(gid_refreshed)
+
         return auth_info
 
     def create_gid(self, hrn, uuid, pkey):
-        parent_hrn = get_authority(hrn)
-
-        gid = GID(subject=hrn, uuid=uuid)
+        gid = GID(subject=hrn, uuid=uuid, hrn=hrn)
 
+        parent_hrn = get_authority(hrn)
         if not parent_hrn:
             # if there is no parent hrn, then it must be self-signed. this
             # is where we terminate the recursion
@@ -117,6 +142,7 @@ class Hierarchy():
             gid.set_parent(parent_auth_info.get_gid_object())
 
         gid.set_pubkey(pkey)
+        gid.encode()
         gid.sign()
 
         return gid
@@ -138,3 +164,58 @@ class Hierarchy():
 
         return gid
 
+    def get_auth_cred(self, hrn):
+        auth_info = self.get_auth_info(hrn)
+        gid = auth_info.get_gid_object()
+
+        cred = Credential(subject=hrn)
+        cred.set_gid_caller(gid)
+        cred.set_gid_object(gid)
+        cred.set_privileges("authority")
+        cred.set_delegate(True)
+        cred.set_pubkey(auth_info.get_gid_object().get_pubkey())
+
+        parent_hrn = get_authority(hrn)
+        if not parent_hrn:
+            # if there is no parent hrn, then it must be self-signed. this
+            # is where we terminate the recursion
+            cred.set_issuer(auth_info.get_pkey_object(), hrn)
+        else:
+            # we need the parent's private key in order to sign this GID
+            parent_auth_info = self.get_auth_info(parent_hrn)
+            cred.set_issuer(parent_auth_info.get_pkey_object(), parent_auth_info.hrn)
+            cred.set_parent(self.get_auth_cred(parent_hrn))
+
+        cred.encode()
+        cred.sign()
+
+        return cred
+
+    # this looks almost the same as get_auth_cred, but works for tickets
+    # XXX does similarity imply there should be more code re-use?
+    def get_auth_ticket(self, hrn):
+        auth_info = self.get_auth_info(hrn)
+        gid = auth_info.get_gid_object()
+
+        ticket = Ticket(subject=hrn)
+        ticket.set_gid_caller(gid)
+        ticket.set_gid_object(gid)
+        ticket.set_delegate(True)
+        ticket.set_pubkey(auth_info.get_gid_object().get_pubkey())
+
+        parent_hrn = get_authority(hrn)
+        if not parent_hrn:
+            # if there is no parent hrn, then it must be self-signed. this
+            # is where we terminate the recursion
+            ticket.set_issuer(auth_info.get_pkey_object(), hrn)
+        else:
+            # we need the parent's private key in order to sign this GID
+            parent_auth_info = self.get_auth_info(parent_hrn)
+            ticket.set_issuer(parent_auth_info.get_pkey_object(), parent_auth_info.hrn)
+            ticket.set_parent(self.get_auth_cred(parent_hrn))
+
+        ticket.encode()
+        ticket.sign()
+
+        return ticket
+