blob: 8a096c21bc9066627d7ee5b453aa40da2b875414 [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
/**
* @fileoverview Code for dealing with the specific message types used in
* the SSH agent protocol.
*/
nassh.agent.messages = {};
/**
* Types of requests/responses exchanged between client application and SSH
* agent. All types are represented as 8-bit unsigned integers.
* @see https://tools.ietf.org/id/draft-miller-ssh-agent-00.html#rfc.section.5.1
*
* @readonly
* @enum {!number}
*/
nassh.agent.messages.Numbers = {
AGENT_FAILURE: 5,
AGENT_SUCCESS: 6,
AGENTC_REQUEST_IDENTITIES: 11,
AGENT_IDENTITIES_ANSWER: 12,
AGENTC_SIGN_REQUEST: 13,
AGENT_SIGN_RESPONSE: 14,
};
/**
* Generic agent responses.
* @see https://tools.ietf.org/id/draft-miller-ssh-agent-00.html#rfc.section.4.1
*
* @readonly
* @const {!nassh.agent.Message}
*/
nassh.agent.messages.SUCCESS =
new nassh.agent.Message(nassh.agent.messages.Numbers.AGENT_SUCCESS);
nassh.agent.messages.FAILURE =
new nassh.agent.Message(nassh.agent.messages.Numbers.AGENT_FAILURE);
/**
* Map message types to reader function.
*
* @type {Object<!nassh.agent.messages.Numbers, function(!nassh.agent.Message):
* void>}
* @private
*/
nassh.agent.messages.readers_ = {};
/**
* Read the contents of a message into fields according to the format specified
* by its type.
*
* @param {nassh.agent.Message} message
*/
nassh.agent.messages.read = function(message) {
if (nassh.agent.messages.readers_.hasOwnProperty(message.type)) {
try {
return nassh.agent.messages.readers_[message.type](message);
} catch (e) {
console.error(e);
return null;
}
} else {
console.warn(`messages.read: message number ${message.type} not supported`);
return null;
}
};
/**
* Read an AGENTC_REQUEST_IDENTITIES request.
* @see https://tools.ietf.org/id/draft-miller-ssh-agent-00.html#rfc.section.4.4
*
* @param {!nassh.agent.Message} message A message of type
* AGENTC_REQUEST_IDENTITIES.
*/
nassh.agent.messages
.readers_[nassh.agent.messages.Numbers.AGENTC_REQUEST_IDENTITIES] =
function(message) {
if (!message.eom()) {
throw new Error(
'AGENTC_REQUEST_IDENTITIES: message body longer than expected');
}
return message;
};
/**
* Read an AGENTC_SIGN_REQUEST request.
* @see https://tools.ietf.org/id/draft-miller-ssh-agent-00.html#rfc.section.4.5
*
* @param {!nassh.agent.Message} message A message of type AGENTC_SIGN_REQUEST.
*/
nassh.agent.messages
.readers_[nassh.agent.messages.Numbers.AGENTC_SIGN_REQUEST] = function(
message) {
message.fields.keyBlob = message.readString();
message.fields.data = message.readString();
message.fields.flags = message.readUint32();
if (!message.eom()) {
throw new Error('AGENTC_SIGN_REQUEST: message body longer than expected');
}
return message;
};
/**
* Map message types to writer function.
*
* @type {Object<!nassh.agent.messages.Numbers, function(...[*]):
* !nassh.agent.Message>}
* @private
*/
nassh.agent.messages.writers_ = {};
/**
* Write a message of a given type.
*
* @param {!nassh.agent.messages.Numbers} type
* @param {...*} args Any number of arguments dictated by the type.
* @returns {!nassh.agent.Message} A message of the given type encoding the
* supplied arguments.
*/
nassh.agent.messages.write = function(type, ...args) {
if (nassh.agent.messages.writers_.hasOwnProperty(type)) {
try {
return nassh.agent.messages.writers_[type](...args);
} catch (e) {
console.error(e);
return nassh.agent.messages.FAILURE;
}
} else {
console.warn(`messages.write: message number ${type} not supported`);
return nassh.agent.messages.FAILURE;
}
};
/**
* An SSH identity (public key), containing the wire encoding of the public key
* and a UTF-8 encoded human-readable comment.
* @see https://tools.ietf.org/id/draft-miller-ssh-agent-00.html#rfc.section.4.4
*
* @typedef {{keyBlob: !Uint8Array, comment: !Uint8Array}} Identity
*/
/**
* Write an AGENT_IDENTITIES_ANSWER response.
* @see https://tools.ietf.org/id/draft-miller-ssh-agent-00.html#rfc.section.4.4
*
* @param {!Array<!Identity>} identities An array of SSH identities.
* @returns {!nassh.agent.Message}
*/
nassh.agent.messages
.writers_[nassh.agent.messages.Numbers.AGENT_IDENTITIES_ANSWER] = function(
identities) {
const message = new nassh.agent.Message(
nassh.agent.messages.Numbers.AGENT_IDENTITIES_ANSWER);
message.writeUint32(identities.length);
for (const identity of identities) {
message.writeString(identity.keyBlob);
message.writeString(identity.comment);
}
return message;
};
/**
* Write an AGENT_SIGN_RESPONSE response.
* @see https://tools.ietf.org/id/draft-miller-ssh-agent-00.html#rfc.section.4.5
*
* @param {!Uint8Array} signature The computed signature.
* @returns {!nassh.agent.Message}
*/
nassh.agent.messages
.writers_[nassh.agent.messages.Numbers.AGENT_SIGN_RESPONSE] = function(
signature) {
const message =
new nassh.agent.Message(nassh.agent.messages.Numbers.AGENT_SIGN_RESPONSE);
message.writeString(signature);
return message;
};