js: Making objects inmutable
-- * An Object.freeze should stop any malicious third party from changing objects' methods once the objects are instantiated (see unittest for an approach that would have worked before) - An initialized gpgmejs- object doesn't have a '_Keyring' property anymore (it still has its 'Keyring') - The internal expect='base64' needed to be turned into a method.
This commit is contained in:
parent
522121ea7e
commit
e16a87e839
@ -37,7 +37,6 @@ describe('GPGME context', function(){
|
|||||||
context.Keyring = input;
|
context.Keyring = input;
|
||||||
expect(context.Keyring).to.be.an('object');
|
expect(context.Keyring).to.be.an('object');
|
||||||
expect(context.Keyring).to.not.equal(input);
|
expect(context.Keyring).to.not.equal(input);
|
||||||
expect(context._Keyring).to.equal(context.Keyring);
|
|
||||||
expect(context.Keyring.getKeys).to.be.a('function');
|
expect(context.Keyring.getKeys).to.be.a('function');
|
||||||
expect(context.Keyring.getDefaultKey).to.be.a('function');
|
expect(context.Keyring.getDefaultKey).to.be.a('function');
|
||||||
expect(context.Keyring.importKey).to.be.a('function');
|
expect(context.Keyring.importKey).to.be.a('function');
|
||||||
|
@ -118,7 +118,7 @@ export class Connection{
|
|||||||
}
|
}
|
||||||
let chunksize = message.chunksize;
|
let chunksize = message.chunksize;
|
||||||
return new Promise(function(resolve, reject){
|
return new Promise(function(resolve, reject){
|
||||||
let answer = new Answer(message);
|
let answer = Object.freeze(new Answer(message));
|
||||||
let listener = function(msg) {
|
let listener = function(msg) {
|
||||||
if (!msg){
|
if (!msg){
|
||||||
_connection.onMessage.removeListener(listener);
|
_connection.onMessage.removeListener(listener);
|
||||||
@ -188,14 +188,15 @@ class Answer{
|
|||||||
*/
|
*/
|
||||||
constructor(message){
|
constructor(message){
|
||||||
const operation = message.operation;
|
const operation = message.operation;
|
||||||
const expect = message.expect;
|
const expected = message.getExpect();
|
||||||
let response_b64 = null;
|
let response_b64 = null;
|
||||||
|
|
||||||
this.getOperation = function(){
|
this.getOperation = function(){
|
||||||
return operation;
|
return operation;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getExpect = function(){
|
this.getExpect = function(){
|
||||||
return expect;
|
return expected;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -260,7 +261,7 @@ class Answer{
|
|||||||
}
|
}
|
||||||
if (_decodedResponse.base64 === true
|
if (_decodedResponse.base64 === true
|
||||||
&& poa.data[key] === 'string'
|
&& poa.data[key] === 'string'
|
||||||
&& this.getExpect() === undefined
|
&& this.getExpect() !== 'base64'
|
||||||
){
|
){
|
||||||
_response[key] = decodeURIComponent(
|
_response[key] = decodeURIComponent(
|
||||||
atob(_decodedResponse[key]).split('').map(
|
atob(_decodedResponse[key]).split('').map(
|
||||||
|
@ -119,7 +119,7 @@ const err_list = {
|
|||||||
export function gpgme_error(code = 'GENERIC_ERROR', info){
|
export function gpgme_error(code = 'GENERIC_ERROR', info){
|
||||||
if (err_list.hasOwnProperty(code)){
|
if (err_list.hasOwnProperty(code)){
|
||||||
if (err_list[code].type === 'error'){
|
if (err_list[code].type === 'error'){
|
||||||
return new GPGME_Error(code);
|
return Object.freeze(new GPGME_Error(code));
|
||||||
}
|
}
|
||||||
if (err_list[code].type === 'warning'){
|
if (err_list[code].type === 'warning'){
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
@ -127,10 +127,10 @@ export function gpgme_error(code = 'GENERIC_ERROR', info){
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} else if (code === 'GNUPG_ERROR'){
|
} else if (code === 'GNUPG_ERROR'){
|
||||||
return new GPGME_Error(code, info);
|
return Object.freeze(new GPGME_Error(code, info));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new GPGME_Error('GENERIC_ERROR');
|
return Object.freeze(new GPGME_Error('GENERIC_ERROR'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ export function createKey(fingerprint, async = false){
|
|||||||
if (!isFingerprint(fingerprint) || typeof(async) !== 'boolean'){
|
if (!isFingerprint(fingerprint) || typeof(async) !== 'boolean'){
|
||||||
return gpgme_error('PARAM_WRONG');
|
return gpgme_error('PARAM_WRONG');
|
||||||
}
|
}
|
||||||
else return new GPGME_Key(fingerprint, async);
|
else return Object.freeze(new GPGME_Key(fingerprint, async));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,15 +104,15 @@ export class GPGME_Key {
|
|||||||
case 'subkeys':
|
case 'subkeys':
|
||||||
_data.subkeys = [];
|
_data.subkeys = [];
|
||||||
for (let i=0; i< data.subkeys.length; i++) {
|
for (let i=0; i< data.subkeys.length; i++) {
|
||||||
_data.subkeys.push(
|
_data.subkeys.push(Object.freeze(
|
||||||
new GPGME_Subkey(data.subkeys[i]));
|
new GPGME_Subkey(data.subkeys[i])));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'userids':
|
case 'userids':
|
||||||
_data.userids = [];
|
_data.userids = [];
|
||||||
for (let i=0; i< data.userids.length; i++) {
|
for (let i=0; i< data.userids.length; i++) {
|
||||||
_data.userids.push(
|
_data.userids.push(Object.freeze(
|
||||||
new GPGME_UserId(data.userids[i]));
|
new GPGME_UserId(data.userids[i])));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'last_update':
|
case 'last_update':
|
||||||
|
@ -36,7 +36,7 @@ export function createMessage(operation){
|
|||||||
return gpgme_error('PARAM_WRONG');
|
return gpgme_error('PARAM_WRONG');
|
||||||
}
|
}
|
||||||
if (permittedOperations.hasOwnProperty(operation)){
|
if (permittedOperations.hasOwnProperty(operation)){
|
||||||
return new GPGME_Message(operation);
|
return Object.freeze(new GPGME_Message(operation));
|
||||||
} else {
|
} else {
|
||||||
return gpgme_error('MSG_WRONG_OP');
|
return gpgme_error('MSG_WRONG_OP');
|
||||||
}
|
}
|
||||||
@ -56,11 +56,21 @@ export class GPGME_Message {
|
|||||||
op: operation,
|
op: operation,
|
||||||
chunksize: 1023* 1024
|
chunksize: 1023* 1024
|
||||||
};
|
};
|
||||||
|
let expected = null;
|
||||||
|
|
||||||
this.getOperation = function(){
|
this.getOperation = function(){
|
||||||
return _msg.op;
|
return _msg.op;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.setExpect = function(value){
|
||||||
|
if (value === 'base64'){
|
||||||
|
expected = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.getExpect = function(){
|
||||||
|
return expected;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum size of responses from gpgme in bytes. As of July 2018,
|
* The maximum size of responses from gpgme in bytes. As of July 2018,
|
||||||
* most browsers will only accept answers up to 1 MB of size.
|
* most browsers will only accept answers up to 1 MB of size.
|
||||||
@ -204,7 +214,7 @@ export class GPGME_Message {
|
|||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
if (me.isComplete() === true) {
|
if (me.isComplete() === true) {
|
||||||
|
|
||||||
let conn = new Connection;
|
let conn = Object.freeze(new Connection);
|
||||||
conn.post(me).then(function(response) {
|
conn.post(me).then(function(response) {
|
||||||
resolve(response);
|
resolve(response);
|
||||||
}, function(reason) {
|
}, function(reason) {
|
||||||
|
@ -66,7 +66,7 @@ export function createSignature(sigObject){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new GPGME_Signature(sigObject);
|
return Object.freeze(new GPGME_Signature(sigObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ export class GpgME {
|
|||||||
*/
|
*/
|
||||||
this.getKeyring = function(){
|
this.getKeyring = function(){
|
||||||
if (!_Keyring){
|
if (!_Keyring){
|
||||||
_Keyring = new GPGME_Keyring;
|
_Keyring = Object.freeze(new GPGME_Keyring);
|
||||||
}
|
}
|
||||||
return _Keyring;
|
return _Keyring;
|
||||||
};
|
};
|
||||||
@ -241,7 +241,7 @@ export class GpgME {
|
|||||||
putData(msg, data);
|
putData(msg, data);
|
||||||
return new Promise(function(resolve,reject) {
|
return new Promise(function(resolve,reject) {
|
||||||
if (mode ==='detached'){
|
if (mode ==='detached'){
|
||||||
msg.expect= 'base64';
|
msg.setExpect('base64');
|
||||||
}
|
}
|
||||||
msg.post().then( function(message) {
|
msg.post().then( function(message) {
|
||||||
if (mode === 'clearsign'){
|
if (mode === 'clearsign'){
|
||||||
@ -319,10 +319,7 @@ export class GpgME {
|
|||||||
* Accesses the {@link GPGME_Keyring}.
|
* Accesses the {@link GPGME_Keyring}.
|
||||||
*/
|
*/
|
||||||
get Keyring(){
|
get Keyring(){
|
||||||
if (!this._Keyring){
|
return this.getKeyring();
|
||||||
this._Keyring = new GPGME_Keyring;
|
|
||||||
}
|
|
||||||
return this._Keyring;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,11 +34,11 @@ import { Connection } from './Connection';
|
|||||||
*/
|
*/
|
||||||
function init(){
|
function init(){
|
||||||
return new Promise(function(resolve, reject){
|
return new Promise(function(resolve, reject){
|
||||||
let connection = new Connection;
|
let connection = Object.freeze(new Connection);
|
||||||
connection.checkConnection(false).then(
|
connection.checkConnection(false).then(
|
||||||
function(result){
|
function(result){
|
||||||
if (result === true) {
|
if (result === true) {
|
||||||
resolve(new GpgME());
|
resolve(Object.freeze(new GpgME()));
|
||||||
} else {
|
} else {
|
||||||
reject(gpgme_error('CONN_NO_CONNECT'));
|
reject(gpgme_error('CONN_NO_CONNECT'));
|
||||||
}
|
}
|
||||||
|
@ -253,6 +253,22 @@ function unittests (){
|
|||||||
expect(key.fingerprint.code).to.equal('KEY_INVALID');
|
expect(key.fingerprint.code).to.equal('KEY_INVALID');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Overwriting getFingerprint does not work', function(){
|
||||||
|
const evilFunction = function(){
|
||||||
|
return 'bad Data';
|
||||||
|
};
|
||||||
|
let key = createKey(kp.validKeyFingerprint, true);
|
||||||
|
expect(key.fingerprint).to.equal(kp.validKeyFingerprint);
|
||||||
|
try {
|
||||||
|
key.getFingerprint = evilFunction;
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
expect(e).to.be.an.instanceof(TypeError);
|
||||||
|
}
|
||||||
|
expect(key.fingerprint).to.equal(kp.validKeyFingerprint);
|
||||||
|
expect(key.getFingerprint).to.not.equal(evilFunction);
|
||||||
|
});
|
||||||
// TODO: tests for subkeys
|
// TODO: tests for subkeys
|
||||||
// TODO: tests for userids
|
// TODO: tests for userids
|
||||||
// TODO: some invalid tests for key/keyring
|
// TODO: some invalid tests for key/keyring
|
||||||
|
Loading…
Reference in New Issue
Block a user