[Server-devel] [PATCH] xs-activation: Support creating rtcreset signatures with master key

Daniel Drake dsd at laptop.org
Fri Dec 30 16:48:59 EST 2011


If the master keypair is available as lease.public/lease.private,
use it to create rtc reset signatures (rather than relying on
delegations).

The UUID of the client must be known to the server, stored in
the moodle database.
---
 oat.py                  |   51 ++++++++++++++++++++++++++++++++++++++++++++++-
 xs-activation-signer.py |   48 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+), 1 deletions(-)

For the moment this patch is just for review as "sample code" - it relies
on the addition of UUIDs into the moodle database, which will happen at
a later date.

diff --git a/oat.py b/oat.py
index bb22a23..7ad78c9 100644
--- a/oat.py
+++ b/oat.py
@@ -63,6 +63,23 @@ class oat:
 
         return False
 
+    def get_uuid(self, sn):
+        if not self.mdb_available():
+            return False
+
+        mdbh = self.get_mdb_handle()
+        mdbc  = mdbh.cursor()
+        sql = """SELECT uuid
+                 FROM   mdl_oat_laptops
+                 WHERE serialnum=%s
+               """
+        mdbc.execute(sql, [sn])
+        if mdbc.rowcount == 1:
+            rows = mdbc.fetchall()
+            return rows[0][0]
+
+        return False
+
     def mark_served_stolen(self, sn):
         """Returns False or the string 'STOLEN'"""
     
@@ -256,11 +273,19 @@ class oat:
         return response
 
     def get_rtcreset(self, sn, currentrtc, nonce):
+        newrtc = datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")
+
+        # use the master key to generate the rtcreset, if it is available
+        kpath = self.get_master_lease_key_path()
+        if kpath:
+            uuid = self.get_uuid(sn)
+            if uuid:
+                return self.generate_rtcreset(sn, uuid, currentrtc, nonce, newrtc)
+
         # attempt to build a sig02 delegated rtcreset
         kpath        = self.get_key_path()
         ldpath = self.get_lease_delegation_path(sn)
         if kpath and ldpath:
-            newrtc = datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")
             return self.generate_delegated_rtcreset(sn, currentrtc, nonce, newrtc)
 
     def mdb_available(self):
@@ -286,6 +311,14 @@ class oat:
         else:
             return False
 
+    def get_master_lease_key_path(self):
+        path = os.path.join(self.BASEDIR, 'keys', 'lease.private')
+        if os.path.exists(path):
+            # strip ".private" suffix
+            return path[:-8]
+        else:
+            return False
+
     def get_lease_delegation_path(self, sn):
         path = os.path.join(self.BASEDIR, 'lease-delegations',
                             sn[-2:], sn)
@@ -324,6 +357,22 @@ class oat:
 
         return lease;
 
+    def generate_rtcreset(self, sn, uuid, currentrtc, nonce, newrtc):
+        (fh, tmpfpath) = tempfile.mkstemp(dir='/var/lib/xs-activation/tmp')
+        os.write(fh, uuid)
+        os.close(fh)
+
+        fname = "rtc01_%s_%s_%s_%s_%s" % (sn, currentrtc, nonce, newrtc, hexlify(os.urandom(8)))
+        reqpath = '/var/lib/xs-activation/req/' + fname
+        os.rename(tmpfpath, reqpath)
+
+        rtcreset = self.get_signed_output(fname)
+        if rtcreset == None:
+            self.log_error("Timed out waiting for signed response")
+            raise RuntimeError("Timed out waiting for signed response")
+
+        return rtcreset
+
     def generate_delegated_rtcreset(self, sn, currentrtc, nonce, newrtc):
         fname = "rtc01delegated_%s_%s_%s_%s_%s" % (sn, currentrtc, nonce, newrtc, hexlify(os.urandom(8)))
         reqpath = '/var/lib/xs-activation/req/' + fname
diff --git a/xs-activation-signer.py b/xs-activation-signer.py
index 46ccec2..5383b1a 100755
--- a/xs-activation-signer.py
+++ b/xs-activation-signer.py
@@ -225,6 +225,52 @@ def generate_multiple_delegated_leases(dirpath, fname, fpath, params):
     destpath = '/var/lib/xs-activation/done/' + fname
     save_atomically(destpath, cjson.write([1,leases]))
 
+def serve_rtcreset(dirpath, fname, fpath, params):
+    # read UUID
+    fd = open(fpath, 'r')
+    uuid = fd.read()
+    fd.close()
+    os.unlink(fpath)
+
+    if not uuid:
+        raise RuntimeError('Missing UUID')
+
+    randid = params.pop()
+    newrtc = params.pop()
+    nonce = params.pop()
+    currentrtc = params.pop()
+
+    sn = params.pop()
+    if not validate_sn(sn):
+        raise RuntimeError('Invalid SN')
+
+    if len(currentrtc) != 16 or currentrtc[15] != 'Z' or currentrtc[8] != 'T':
+        log_error("Unrecognised rtcreset timestamp")
+        exit(1)
+
+    if not nonce.isdigit():
+        log_error("Unrecognised rtcreset nonce")
+        exit(1)
+
+    # find uuid and signing key
+    myoat = oat.oat()
+
+    kpath = myoat.get_master_lease_key_path()
+    if not kpath:
+        log_error("No master signing key available")
+        exit(1)
+
+    # prep params
+    cmd = ['/usr/bin/obc-make-rtcreset',
+           '--signingkey', kpath,
+           sn, uuid, currentrtc, nonce, newrtc]
+    log_error(cmd)
+    rtcreset = subprocess.Popen(cmd,
+                                stdout=subprocess.PIPE).communicate()[0]
+
+    destpath = '/var/lib/xs-activation/done/' + fname
+    save_atomically(destpath, rtcreset)
+
 def serve_delegated_rtcreset(dirpath, fname, fpath, params):
     # remove empty/unused file
     os.unlink(fpath)
@@ -323,6 +369,8 @@ try:
         serve_delegated_lease(dirpath, fname, fpath, params)
     elif cmd == 'multiact01':
         generate_multiple_delegated_leases(dirpath, fname, fpath, params)
+    elif cmd == 'rtc01':
+        serve_rtcreset(dirpath, fname, fpath, params)
     elif cmd == 'rtc01delegated':
         serve_delegated_rtcreset(dirpath, fname, fpath, params)
     else:
-- 
1.7.7.4



More information about the Server-devel mailing list