Browse Source

removed serialization, was a security risk

master
nitowa 1 year ago
parent
commit
c138a2b9af
5 changed files with 7 additions and 205 deletions
  1. 1
    2
      Index.ts
  2. 0
    67
      src/Decorator.ts
  3. 3
    7
      src/Frontend.ts
  4. 1
    5
      src/Utils.ts
  5. 2
    124
      test/Test.ts

+ 1
- 2
Index.ts View File

2
 export * from './src/Frontend';
2
 export * from './src/Frontend';
3
 export * from './src/Interfaces'
3
 export * from './src/Interfaces'
4
 export * from './src/Types';
4
 export * from './src/Types';
5
-export * from './src/Utils'
6
-export * from './src/Decorator'
5
+export * from './src/Utils'

+ 0
- 67
src/Decorator.ts View File

1
-import { CLASSNAME_ATTRIBUTE } from "./Strings"
2
-
3
-export abstract class DeserializerFactory {
4
-    static entityClasses = {}
5
-
6
-    static from(object: any) {
7
-        if(!object){
8
-            return
9
-        }
10
-
11
-        if(typeof object !== 'object'){ //definitely not a class object
12
-            return object
13
-        }
14
-        
15
-        if(Array.isArray(object)){
16
-            return object.map(DeserializerFactory.from)
17
-        }
18
-
19
-        const clazz = DeserializerFactory.entityClasses[object[CLASSNAME_ATTRIBUTE]]
20
-        delete object[CLASSNAME_ATTRIBUTE]
21
-
22
-        if(!clazz){ //anonymous object or class not registered as @Serializable
23
-            Object.keys(object).forEach(key => {
24
-                object[key] = DeserializerFactory.from(object[key])
25
-            })
26
-            return object
27
-        }
28
-
29
-        const obj = new clazz()
30
-        Object.keys(object).forEach(key => {
31
-            obj[key] = DeserializerFactory.from(object[key])
32
-        })
33
-        return obj
34
-    }
35
-
36
-    
37
-
38
-    static makeDeserializable(object: any){
39
-        if(!object)
40
-            return
41
-        
42
-        if(typeof object !== 'object')
43
-            return object
44
-        
45
-        if(object.constructor.name === 'Object'){
46
-            Object.keys(object).forEach(key => {
47
-                object[key] = DeserializerFactory.makeDeserializable(object[key])
48
-            })
49
-            return object
50
-        }
51
-
52
-        object[CLASSNAME_ATTRIBUTE] = object.constructor.name
53
-        Object.keys(object).forEach(key => {
54
-            object[key] = DeserializerFactory.makeDeserializable(object[key])
55
-        })
56
-
57
-        return object
58
-    }
59
-}
60
-
61
-export function Serializable(attr?: any) {
62
-    return function _Serializable<T extends { new(...args: any[]): {} }>(clazz: T) {
63
-        DeserializerFactory.entityClasses[clazz.name] = clazz
64
-        
65
-        return clazz
66
-    }
67
-}

+ 3
- 7
src/Frontend.ts View File

5
 import * as I from './Interfaces';
5
 import * as I from './Interfaces';
6
 import { stripAfterEquals, appendComma } from './Utils';
6
 import { stripAfterEquals, appendComma } from './Utils';
7
 import { CALLBACK_NAME, DESTROY_PREFIX, SOCKET_NOT_CONNECTED, UNKNOWN_RPC_IDENTIFIER, USER_DEFINED_TIMEOUT } from './Strings';
7
 import { CALLBACK_NAME, DESTROY_PREFIX, SOCKET_NOT_CONNECTED, UNKNOWN_RPC_IDENTIFIER, USER_DEFINED_TIMEOUT } from './Strings';
8
-import { DeserializerFactory } from './Decorator';
9
-DeserializerFactory
10
 
8
 
11
 
9
 
12
 /**
10
 /**
209
         const headerArgs = fnArgs.join(",")
207
         const headerArgs = fnArgs.join(",")
210
         const argParams = fnArgs.map(stripAfterEquals).join(",")
208
         const argParams = fnArgs.map(stripAfterEquals).join(",")
211
         sesame = appendComma(sesame)
209
         sesame = appendComma(sesame)
212
-        const deserializer = DeserializerFactory
213
         return eval(`async (${headerArgs}) => { 
210
         return eval(`async (${headerArgs}) => { 
214
             const returnvalue = await this.call("${fnName}", ${sesame} ${argParams})
211
             const returnvalue = await this.call("${fnName}", ${sesame} ${argParams})
215
-            return deserializer.from(returnvalue)
212
+            return returnvalue
216
         }`)
213
         }`)
217
     }
214
     }
218
 
215
 
230
         const argParams = fnArgs.map(stripAfterEquals).join(",")
227
         const argParams = fnArgs.map(stripAfterEquals).join(",")
231
         sesame = appendComma(sesame, true)
228
         sesame = appendComma(sesame, true)
232
         headerArgs = fnArgs.length > 0 ? headerArgs + "," : headerArgs
229
         headerArgs = fnArgs.length > 0 ? headerArgs + "," : headerArgs
233
-        const deserializer = DeserializerFactory
234
         const destroy_prefix = DESTROY_PREFIX
230
         const destroy_prefix = DESTROY_PREFIX
235
 
231
 
236
         const frontendHookStr = `
232
         const frontendHookStr = `
248
                         })
244
                         })
249
 
245
 
250
                         this.socket.hook(r.uuid, (...args) => {
246
                         this.socket.hook(r.uuid, (...args) => {
251
-                            ${CALLBACK_NAME}.apply(${CALLBACK_NAME}, args.map(deserializer.from))
247
+                            ${CALLBACK_NAME}.apply(${CALLBACK_NAME}, args)
252
                         })
248
                         })
253
                     }
249
                     }
254
-                    return deserializer.from(r.return)
250
+                    return r.return
255
                 }else{
251
                 }else{
256
                     throw new Error("Empty response")
252
                     throw new Error("Empty response")
257
                 }
253
                 }

+ 1
- 5
src/Utils.ts View File

4
 import * as I from "./Interfaces";
4
 import * as I from "./Interfaces";
5
 import { Socket } from "socket.io"
5
 import { Socket } from "socket.io"
6
 import { CALL_NOT_FOUND, DESTROY_PREFIX, RPC_BAD_TYPE, RPC_NO_NAME } from "./Strings";
6
 import { CALL_NOT_FOUND, DESTROY_PREFIX, RPC_BAD_TYPE, RPC_NO_NAME } from "./Strings";
7
-import { DeserializerFactory } from "./Decorator";
8
 
7
 
9
 /**
8
 /**
10
  * Translate an RPC to RPCInfo for serialization.
9
  * Translate an RPC to RPCInfo for serialization.
80
     const argsArr = extractArgs(rpcFunction)
79
     const argsArr = extractArgs(rpcFunction)
81
     const args = argsArr.join(',')
80
     const args = argsArr.join(',')
82
     const argsStr = argsArr.map(stripAfterEquals).join(',')
81
     const argsStr = argsArr.map(stripAfterEquals).join(',')
83
-    const deserializer = DeserializerFactory 
84
 
82
 
85
     const callStr = `async (${args}) => {
83
     const callStr = `async (${args}) => {
86
         try{
84
         try{
87
             const res = await rpcFunction(${argsStr})
85
             const res = await rpcFunction(${argsStr})
88
-            return deserializer.makeDeserializable(res)
86
+            return res
89
         }catch(e){
87
         }catch(e){
90
             errorHandler($__socket__$, e, rpcName, [${args}])
88
             errorHandler($__socket__$, e, rpcName, [${args}])
91
         }
89
         }
108
  * @returns A {@link HookFunction}
106
  * @returns A {@link HookFunction}
109
  */
107
  */
110
 const hookGenerator = (rpc: T.HookRPC<any, any>, errorHandler: T.ErrorHandler, sesameFn?: T.SesameFunction, injectSocket?: boolean): T.HookInfo['generator'] => {
108
 const hookGenerator = (rpc: T.HookRPC<any, any>, errorHandler: T.ErrorHandler, sesameFn?: T.SesameFunction, injectSocket?: boolean): T.HookInfo['generator'] => {
111
-    const deserializer = DeserializerFactory 
112
     let argsArr = extractArgs(rpc.hook)
109
     let argsArr = extractArgs(rpc.hook)
113
     argsArr.shift()//remove callback param
110
     argsArr.shift()//remove callback param
114
 
111
 
125
             const uuid = uuidv4()
122
             const uuid = uuidv4()
126
             const res = await rpc.hook((...cbargs) => {
123
             const res = await rpc.hook((...cbargs) => {
127
                 ${rpc.onCallback ? `rpc.onCallback.apply({}, cbargs)` : ``}
124
                 ${rpc.onCallback ? `rpc.onCallback.apply({}, cbargs)` : ``}
128
-                cbargs = cbargs.map(deserializer.makeDeserializable)
129
                 $__socket__$.call.apply($__socket__$, [uuid, ...cbargs])
125
                 $__socket__$.call.apply($__socket__$, [uuid, ...cbargs])
130
             },${callArgs})
126
             },${callArgs})
131
             ${rpc.onDestroy ? `$__socket__$.bind(destroy_prefix+uuid, () => {
127
             ${rpc.onDestroy ? `$__socket__$.bind(destroy_prefix+uuid, () => {

+ 2
- 124
test/Test.ts View File

1
 import { describe, it } from "mocha";
1
 import { describe, it } from "mocha";
2
-import { RPCServer, RPCSocket, Serializable } from '../Index'
3
 import { RPCExporter, Socket } from "../src/Interfaces";
2
 import { RPCExporter, Socket } from "../src/Interfaces";
4
 import { ConnectedSocket, Callback, GenericFunction } from "../src/Types";
3
 import { ConnectedSocket, Callback, GenericFunction } from "../src/Types";
5
 import * as log from 'why-is-node-running';
4
 import * as log from 'why-is-node-running';
10
 import { PromiseIOClient } from "../src/PromiseIO/Client";
9
 import { PromiseIOClient } from "../src/PromiseIO/Client";
11
 import { assert, expect } from 'chai';
10
 import { assert, expect } from 'chai';
12
 import { CLASSNAME_ATTRIBUTE, USER_DEFINED_TIMEOUT } from "../src/Strings";
11
 import { CLASSNAME_ATTRIBUTE, USER_DEFINED_TIMEOUT } from "../src/Strings";
12
+import { RPCServer, RPCSocket } from "../Index";
13
 var should = require('chai').should();
13
 var should = require('chai').should();
14
 var chai = require("chai");
14
 var chai = require("chai");
15
 var chaiAsPromised = require("chai-as-promised");
15
 var chaiAsPromised = require("chai-as-promised");
1010
             done(e)
1010
             done(e)
1011
         })
1011
         })
1012
     })
1012
     })
1013
-})
1014
-
1015
-describe("class (de-)serialization", () => {
1016
-
1017
-    @Serializable()
1018
-    class SubClass {
1019
-        fString = "F"
1020
-    }
1021
-
1022
-    @Serializable()
1023
-    class TestClass {
1024
-        aString = "A"
1025
-        aNumber = 46
1026
-        aObject = {
1027
-            x: "x",
1028
-            y: undefined,
1029
-            sub: new SubClass()
1030
-        }
1031
-        aClassObject = new SubClass()
1032
-
1033
-        public returnOK() {
1034
-            return "OK"
1035
-        }
1036
-    }
1037
-
1038
-    const verifyObject = (obj: any) => {
1039
-        expect(obj).to.be.an.instanceOf(TestClass)
1040
-        expect(obj.aString).to.be.a('string')
1041
-        expect(obj.aNumber).to.be.a('number')
1042
-        expect(obj.aObject).to.be.a('object')
1043
-        expect(obj.aObject.x).to.be.a('string')
1044
-        expect(obj.aObject.y).to.be.undefined
1045
-        expect(obj.aObject.sub).to.be.an.instanceOf(SubClass)
1046
-        expect(obj.aClassObject).to.be.an.instanceOf(SubClass)
1047
-        expect(obj).to.not.have.key(CLASSNAME_ATTRIBUTE)
1048
-        expect(obj.aObject.sub).to.not.have.key(CLASSNAME_ATTRIBUTE)
1049
-        expect(obj.aClassObject).to.not.have.key(CLASSNAME_ATTRIBUTE)
1050
-        expect(obj.returnOK()).to.be.equal('OK')
1051
-    }
1052
-
1053
-    describe("Responses", () => {
1054
-        type TestIfc = {
1055
-            Test: {
1056
-                returnClass: () => Promise<TestClass>
1057
-                classCallback: (callback: Callback<[TestClass]>) => Promise<TestClass>
1058
-            }
1059
-        }
1060
-
1061
-        let myServer: RPCServer<TestIfc>;
1062
-        let mySocket: ConnectedSocket<TestIfc>;
1063
-
1064
-        before(function (done) {
1065
-            myServer = new RPCServer<TestIfc>([{
1066
-                name: "Test",
1067
-                RPCs: [
1068
-                    async function returnClass() {
1069
-                        return new TestClass()
1070
-                    }, {
1071
-                        name: "classCallback",
1072
-                        hook: async function (callback) {
1073
-                            setTimeout(_ => callback(new TestClass()), 250)
1074
-                            return new TestClass()
1075
-                        }
1076
-                    }
1077
-                ]
1078
-            }])
1079
-            myServer.listen(8084)
1080
-
1081
-            new RPCSocket<TestIfc>(8084, 'localhost').connect().then(connsock => {
1082
-                mySocket = connsock
1083
-                done()
1084
-            })
1085
-        })
1086
-
1087
-        after(function (done) {
1088
-            mySocket.close()
1089
-            myServer.close()
1090
-            done()
1091
-        })
1092
-
1093
-
1094
-        it("receives class object in call response", async () => {
1095
-            const obj: TestClass = await mySocket['Test'].returnClass()
1096
-            verifyObject(obj)
1097
-        })
1098
-
1099
-        it("receives class object in hook response", async function () {
1100
-            const obj: TestClass = await mySocket.Test.classCallback(function(x){
1101
-                x
1102
-            })
1103
-            verifyObject(obj)
1104
-        })
1105
-
1106
-        it("receives class object in callback", function (done) {
1107
-            mySocket.Test.classCallback(function (cbValue) {
1108
-                verifyObject(cbValue)
1109
-                done()
1110
-            }).then(verifyObject)
1111
-        })
1112
-    })
1113
-    describe("Parameters", () => {
1114
-        it("Class object in call", function(done){
1115
-            const server = new RPCServer([
1116
-                {
1117
-                    name: "Test",
1118
-                    RPCs: [
1119
-                        function callWithClass(testObj: TestClass){
1120
-                            verifyObject(testObj)
1121
-                            done()
1122
-                        }
1123
-                    ]
1124
-                }
1125
-            ]).listen(8086)
1126
-
1127
-            new RPCSocket(8086, 'localhost').connect().then(sock => {
1128
-                sock['Test'].callWithClass(new TestClass()).then(_ => {
1129
-                    sock.close()
1130
-                    server.close()
1131
-                })
1132
-            })
1133
-        })
1134
-    })
1135
-})
1013
+})

Loading…
Cancel
Save