From e0c6e7a4c72a9494004ecb6aeffb718e7472cd48 Mon Sep 17 00:00:00 2001
From: Ben Adida <ben@adida.net>
Date: Mon, 2 Jul 2012 12:17:22 -0700
Subject: [PATCH] disable cert chaining for now as the spec is changing.

---
 lib/primary.js                    |  4 +++
 lib/verifier/certassertion.js     |  4 +++
 tests/auth-with-assertion-test.js | 60 +++++++++++++++++++++++++++++--
 tests/verifier-test.js            | 53 +++++++++++++++++++++++++++
 4 files changed, 119 insertions(+), 2 deletions(-)

diff --git a/lib/primary.js b/lib/primary.js
index ad422cbf1..37c3fc809 100644
--- a/lib/primary.js
+++ b/lib/primary.js
@@ -275,6 +275,10 @@ exports.verifyAssertion = function(assertion, cb) {
   jwcrypto.cert.verifyBundle(assertion, now, getRoot, function(err, certParamsArray, payload, assertionParams) {
     if (err) return cb(err);
 
+    // for now, to be extra safe, we don't allow cert chains
+    if (certParamsArray.length > 1)
+      return cb("certificate chaining is not yet allowed");
+    
     // audience must be browserid itself
     var want = urlparse(config.get('public_url')).originOnly();
     var got = urlparse(assertionParams.audience).originOnly();
diff --git a/lib/verifier/certassertion.js b/lib/verifier/certassertion.js
index a8342f316..1222df636 100644
--- a/lib/verifier/certassertion.js
+++ b/lib/verifier/certassertion.js
@@ -119,6 +119,10 @@ function verify(assertion, audience, successCB, errorCB) {
     }, function(err, certParamsArray, payload, assertionParams) {
       if (err) return errorCB(err);
 
+      // for now, to be extra safe, we don't allow cert chains
+      if (certParamsArray.length > 1)
+        return errorCB("certificate chaining is not yet allowed");
+      
       // audience must match!
       var err = compareAudiences(assertionParams.audience, audience)
       if (err) {
diff --git a/tests/auth-with-assertion-test.js b/tests/auth-with-assertion-test.js
index 94a0e9ff1..d82156e74 100755
--- a/tests/auth-with-assertion-test.js
+++ b/tests/auth-with-assertion-test.js
@@ -15,7 +15,8 @@ db = require('../lib/db.js'),
 config = require('../lib/configuration.js'),
 http = require('http'),
 querystring = require('querystring'),
-primary = require('./lib/primary.js');
+primary = require('./lib/primary.js'),
+jwcrypto = require('jwcrypto');
 
 var suite = vows.describe('auth-with-assertion');
 
@@ -26,7 +27,9 @@ start_stop.addStartupBatches(suite);
 
 const TEST_DOMAIN = 'example.domain',
       TEST_EMAIL = 'testuser@' + TEST_DOMAIN,
-      TEST_ORIGIN = 'http://127.0.0.1:10002';
+      TEST_ORIGIN = 'http://127.0.0.1:10002',
+      OTHER_EMAIL = 'otheruser@' + TEST_DOMAIN;
+
 
 // here we go!  let's authenticate with an assertion from
 // a primary.
@@ -72,6 +75,59 @@ suite.addBatch({
   }
 });
 
+// now let's generate an assertion using this user
+suite.addBatch({
+  "generating a new intermediate keypair and then an assertion": {
+    topic: function() {
+      var expirationDate = new Date(new Date().getTime() + (2 * 60 * 1000));
+      var self = this;
+
+      jwcrypto.generateKeypair(
+        {algorithm: "DS", keysize: 256},
+        function(err, innerKeypair) {
+          
+          // sign this innerkeypair with the key from g_cert (g_keypair)
+          jwcrypto.cert.sign(
+            innerKeypair.publicKey, {email: OTHER_EMAIL},
+            {issuedAt: new Date(), expiresAt: expirationDate},
+            {}, primaryUser._keyPair.secretKey,
+            function(err, innerCert) {
+
+              jwcrypto.assertion.sign(
+                {},
+                {audience: TEST_ORIGIN, expiresAt: expirationDate},
+                innerKeypair.secretKey, function(err, signedObject) {
+                  if (err) return cb(err);
+
+                  var fullAssertion = jwcrypto.cert.bundle(
+                    [primaryUser._cert, innerCert], signedObject);
+
+                  self.callback(null, fullAssertion);
+                });
+              
+            });
+        });
+    },
+    "succeeds": function(err, assertion) {
+      assert.isString(assertion);
+    },
+    "and logging in with the assertion fails": {
+      topic: function(err, assertion)  {
+        wsapi.post('/wsapi/auth_with_assertion', {
+          assertion: assertion,
+          ephemeral: true
+        }).call(this);
+      },
+      "fails": function(err, r) {
+        var resp = JSON.parse(r.body);
+        assert.isObject(resp);
+        assert.isFalse(resp.success);
+        assert.equal(resp.reason, "certificate chaining is not yet allowed");
+      }
+    }
+  }
+});
+
 start_stop.addShutdownBatches(suite);
 
 // run or export the suite.
diff --git a/tests/verifier-test.js b/tests/verifier-test.js
index c3f708acc..f6225c048 100755
--- a/tests/verifier-test.js
+++ b/tests/verifier-test.js
@@ -966,6 +966,59 @@ suite.addBatch({
   }
 });
 
+const OTHER_EMAIL = 'otheremail@example.com';
+
+// check that chained certs do not work
+suite.addBatch({
+  "generating an assertion with chained certs": {
+    topic: function() {
+      // primaryCert generated
+      // newClientKeypair generated
+      var expirationDate = new Date(new Date().getTime() + (2 * 60 * 1000));
+      var self = this;
+
+      jwcrypto.generateKeypair(
+        {algorithm: "DS", keysize: 256},
+        function(err, innerKeypair) {
+
+          // sign this innerkeypair with the key from g_cert (g_keypair)
+          jwcrypto.cert.sign(
+            innerKeypair.publicKey, {email: OTHER_EMAIL},
+            {issuedAt: new Date(), expiresAt: expirationDate},
+            {}, g_keypair.secretKey,
+            function(err, innerCert) {
+              jwcrypto.assertion.sign({}, {audience: TEST_ORIGIN, expiresAt: expirationDate},
+                                      innerKeypair.secretKey, function(err, assertion) {
+                                        if (err) return self.callback(err);
+                                        
+                                        var b = jwcrypto.cert.bundle([g_cert, innerCert],
+                                                                     assertion);
+                                        self.callback(null, b);
+                                      });
+            });
+          
+        });
+    },
+    "yields a good looking assertion": function (err, assertion) {
+      assert.isString(assertion);
+      assert.equal(assertion.length > 0, true);
+    },
+    "will cause the verifier": {
+      topic: function(err, assertion) {
+        wsapi.post('/verify', {
+          audience: TEST_ORIGIN,
+          assertion: assertion
+        }).call(this);
+      },
+      "to fail": function (err, r) {
+        var resp = JSON.parse(r.body);
+        assert.strictEqual(resp.status, 'failure');
+        assert.strictEqual(resp.reason, "certificate chaining is not yet allowed");
+      }
+    }
+  }
+});
+
 start_stop.addShutdownBatches(suite);
 
 // run or export the suite.
-- 
GitLab