123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- 'use strict';
- const assert = require('assert');
- const debug = false;
- const {
- fixtureKey,
- mustCall,
- setup,
- } = require('./common.js');
- const {
- AgentProtocol,
- BaseAgent,
- utils: { parseKey },
- } = require('../lib/index.js');
- const serverCfg = { hostKeys: [ fixtureKey('ssh_host_rsa_key').raw ] };
- const clientKey = fixtureKey('openssh_new_rsa');
- {
- let getIdentitiesCount = 0;
- let signCount = 0;
- class MyAgent extends BaseAgent {
- getIdentities(cb) {
- assert.strictEqual(++getIdentitiesCount, 1);
- // Ensure that no private portion of the key is used by re-parsing the
- // public version of the key
- cb(null, [ parseKey(clientKey.key.getPublicSSH()) ]);
- }
- sign(pubKey, data, options, cb) {
- assert.strictEqual(++signCount, 1);
- assert.strictEqual(pubKey.getPublicPEM(), clientKey.key.getPublicPEM());
- const sig = clientKey.key.sign(data, options.hash);
- cb(null, sig);
- }
- }
- const username = 'Agent User';
- const { server } = setup(
- 'Custom agent authentication',
- {
- client: { username, agent: new MyAgent() },
- server: serverCfg,
- debug,
- }
- );
- server.on('connection', mustCall((conn) => {
- let authAttempt = 0;
- conn.on('authentication', mustCall((ctx) => {
- assert(ctx.username === username,
- `Wrong username: ${ctx.username}`);
- switch (++authAttempt) {
- case 1:
- assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`);
- return ctx.reject();
- case 3:
- assert(ctx.signature, 'Missing publickey signature');
- // FALLTHROUGH
- case 2:
- assert(ctx.method === 'publickey',
- `Wrong auth method: ${ctx.method}`);
- assert(ctx.key.algo === clientKey.key.type,
- `Wrong key algo: ${ctx.key.algo}`);
- assert.deepStrictEqual(clientKey.key.getPublicSSH(),
- ctx.key.data,
- 'Public key mismatch');
- break;
- }
- if (ctx.signature) {
- assert(clientKey.key.verify(ctx.blob, ctx.signature) === true,
- 'Could not verify publickey signature');
- }
- ctx.accept();
- }, 3)).on('ready', mustCall(() => {
- assert.strictEqual(getIdentitiesCount, 1);
- assert.strictEqual(signCount, 1);
- conn.end();
- }));
- }));
- }
- {
- const client = new AgentProtocol(true);
- const server = new AgentProtocol(false);
- server.on('identities', mustCall((req) => {
- setImmediate(() => server.failureReply(req));
- }));
- client.getIdentities(mustCall((err, keys) => {
- assert(err, 'Missing expected error');
- }));
- client.pipe(server).pipe(client);
- }
- {
- const client = new AgentProtocol(true);
- const server = new AgentProtocol(false);
- server.on('identities', mustCall((req) => {
- const keys = [ clientKey.key ];
- server.getIdentitiesReply(req, keys);
- }));
- client.getIdentities(mustCall((err, keys) => {
- assert(!err, 'Unexpected error');
- assert.strictEqual(keys.length, 1);
- assert.strictEqual(keys[0].isPrivateKey(), false);
- assert.strictEqual(keys[0].getPublicPEM(), clientKey.key.getPublicPEM());
- }));
- client.pipe(server).pipe(client);
- }
- {
- const client = new AgentProtocol(true);
- const server = new AgentProtocol(false);
- const buf = Buffer.from('data to sign');
- server.on('sign', mustCall((req, pubKey, data, options) => {
- assert.strictEqual(pubKey.getPublicPEM(), clientKey.key.getPublicPEM());
- assert.deepStrictEqual(data, buf);
- assert.strictEqual(options.hash, undefined);
- server.failureReply(req);
- }));
- client.sign(clientKey.key.getPublicSSH(),
- buf,
- mustCall((err, signature) => {
- assert(err, 'Missing expected error');
- }));
- client.pipe(server).pipe(client);
- }
- {
- const client = new AgentProtocol(true);
- const server = new AgentProtocol(false);
- const buf = Buffer.from('data to sign');
- server.on('sign', mustCall((req, pubKey, data, options) => {
- assert.strictEqual(pubKey.getPublicPEM(), clientKey.key.getPublicPEM());
- assert.deepStrictEqual(data, buf);
- assert.strictEqual(options.hash, undefined);
- server.signReply(req, clientKey.key.sign(data));
- }));
- client.sign(clientKey.key.getPublicSSH(),
- buf,
- mustCall((err, signature) => {
- assert(!err, 'Unexpected error');
- const pubKey = parseKey(clientKey.key.getPublicSSH());
- assert.strictEqual(pubKey.verify(buf, signature), true);
- }));
- client.pipe(server).pipe(client);
- }
- {
- // Test that outstanding requests are handled upon unexpected closure of the
- // protocol stream
- const client = new AgentProtocol(true);
- const server = new AgentProtocol(false);
- server.on('identities', mustCall((req) => {
- server.destroy();
- }));
- client.getIdentities(mustCall((err) => {
- assert(err, 'Missing expected error');
- }));
- client.pipe(server).pipe(client);
- }
|