Skip to content
This repository
Browse code

Test client renegotiation attacks on HTTPS

This test should output roughly the same results as the tls ci-reneg attack
pummel test.  However, it does not.
  • Loading branch information...
commit dec16aa5c2e21de1d0db737f2a08872993c1b2dd 1 parent 0ef1e5b
Isaac Z. Schlueter authored August 29, 2012

Showing 1 changed file with 106 additions and 0 deletions. Show diff stats Hide diff stats

  1. 106  test/pummel/test-https-ci-reneg-attack.js
106  test/pummel/test-https-ci-reneg-attack.js
... ...
@@ -0,0 +1,106 @@
  1
+// Copyright Joyent, Inc. and other Node contributors.
  2
+//
  3
+// Permission is hereby granted, free of charge, to any person obtaining a
  4
+// copy of this software and associated documentation files (the
  5
+// "Software"), to deal in the Software without restriction, including
  6
+// without limitation the rights to use, copy, modify, merge, publish,
  7
+// distribute, sublicense, and/or sell copies of the Software, and to permit
  8
+// persons to whom the Software is furnished to do so, subject to the
  9
+// following conditions:
  10
+//
  11
+// The above copyright notice and this permission notice shall be included
  12
+// in all copies or substantial portions of the Software.
  13
+//
  14
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  17
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  18
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  19
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  20
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
  21
+
  22
+var common = require('../common');
  23
+var assert = require('assert');
  24
+var spawn = require('child_process').spawn;
  25
+var tls = require('tls');
  26
+var https = require('https');
  27
+var fs = require('fs');
  28
+
  29
+// renegotiation limits to test
  30
+var LIMITS = [0, 1, 2, 3, 5, 10, 16];
  31
+
  32
+if (process.platform === 'win32') {
  33
+  console.log('Skipping test, you probably don\'t have openssl installed.');
  34
+  process.exit();
  35
+}
  36
+
  37
+(function() {
  38
+  var n = 0;
  39
+  function next() {
  40
+    if (n >= LIMITS.length) return;
  41
+    tls.CLIENT_RENEG_LIMIT = LIMITS[n++];
  42
+    test(next);
  43
+  }
  44
+  next();
  45
+})();
  46
+
  47
+function test(next) {
  48
+  var options = {
  49
+    cert: fs.readFileSync(common.fixturesDir + '/test_cert.pem'),
  50
+    key: fs.readFileSync(common.fixturesDir + '/test_key.pem')
  51
+  };
  52
+
  53
+  var seenError = false;
  54
+
  55
+  var server = https.createServer(options, function(req, res) {
  56
+    var conn = req.connection;
  57
+    conn.on('error', function(err) {
  58
+      console.error('Caught exception: ' + err);
  59
+      assert(/TLS session renegotiation attack/.test(err));
  60
+      conn.destroy();
  61
+      seenError = true;
  62
+    });
  63
+    res.end('ok');
  64
+  });
  65
+
  66
+  server.listen(common.PORT, function() {
  67
+    var args = ('s_client -connect 127.0.0.1:' + common.PORT).split(' ');
  68
+    var child = spawn('openssl', args);
  69
+
  70
+    child.stdout.pipe(process.stdout);
  71
+    child.stderr.pipe(process.stderr);
  72
+
  73
+    // count handshakes, start the attack after the initial handshake is done
  74
+    var handshakes = 0;
  75
+    var renegs = 0;
  76
+
  77
+    child.stderr.on('data', function(data) {
  78
+      if (seenError) return;
  79
+      handshakes += (('' + data).match(/verify return:1/g) || []).length;
  80
+      if (handshakes === 2) spam();
  81
+      renegs += (('' + data).match(/RENEGOTIATING/g) || []).length;
  82
+    });
  83
+
  84
+    child.on('exit', function() {
  85
+      assert.equal(renegs, tls.CLIENT_RENEG_LIMIT + 1);
  86
+      server.close();
  87
+      process.nextTick(next);
  88
+    });
  89
+
  90
+    var closed = false;
  91
+    child.stdin.on('error', function(err) {
  92
+      assert.equal(err.code, 'EPIPE');
  93
+      closed = true;
  94
+    });
  95
+    child.stdin.on('close', function() {
  96
+      closed = true;
  97
+    });
  98
+
  99
+    // simulate renegotiation attack
  100
+    function spam() {
  101
+      if (closed) return;
  102
+      child.stdin.write('R\n');
  103
+      setTimeout(spam, 50);
  104
+    }
  105
+  });
  106
+}

0 notes on commit dec16aa

Please sign in to comment.
Something went wrong with that request. Please try again.