diff --git a/lib/src/Core/ExceptionCode.dart b/lib/src/Core/ExceptionCode.dart index 76a03dd..507f1e3 100644 --- a/lib/src/Core/ExceptionCode.dart +++ b/lib/src/Core/ExceptionCode.dart @@ -36,5 +36,7 @@ enum ExceptionCode { AlreadyUnlistened, NotListenable, ParseError, - Timeout + Timeout, + NotSupported, + NotImplemented } diff --git a/lib/src/Data/Codec.dart b/lib/src/Data/Codec.dart index c3bb75f..22d2775 100644 --- a/lib/src/Data/Codec.dart +++ b/lib/src/Data/Codec.dart @@ -214,6 +214,7 @@ class Codec { UInt8: DataSerializer.uInt8Composer, Int16: DataSerializer.int16Composer, UInt16: DataSerializer.uInt16Composer, + Float32: DataSerializer.float128Composer, int: DataSerializer.int64Composer, //[typeof(long?)] = DataSerializer.Int64Composer, //[typeof(ulong)] = DataSerializer.UIn64Composer, diff --git a/lib/src/Data/DataDeserializer.dart b/lib/src/Data/DataDeserializer.dart index 6ae1045..0adb6a2 100644 --- a/lib/src/Data/DataDeserializer.dart +++ b/lib/src/Data/DataDeserializer.dart @@ -45,13 +45,13 @@ class DataDeserializer { static AsyncReply byteParser(DC data, int offset, int length, DistributedConnection? connection, List? requestSequence) { - return new AsyncReply.ready(data[offset]); + return new AsyncReply.ready(data[offset].cast()); } static AsyncReply sByteParser(DC data, int offset, int length, DistributedConnection? connection, List? requestSequence) { - return new AsyncReply.ready( - data[offset] > 127 ? data[offset] - 256 : data[offset]); + return new AsyncReply.ready( + data[offset] > 127 ? (data[offset] - 256).cast() : data[offset].cast()); } static AsyncReply char16Parser(DC data, int offset, int length, @@ -66,27 +66,27 @@ class DataDeserializer { static AsyncReply int16Parser(DC data, int offset, int length, DistributedConnection? connection, List? requestSequence) { - return AsyncReply.ready(data.getInt16(offset)); + return AsyncReply.ready(data.getInt16(offset).cast()); } static AsyncReply uInt16Parser(DC data, int offset, int length, DistributedConnection? connection, List? requestSequence) { - return AsyncReply.ready(data.getUint16(offset)); + return AsyncReply.ready(data.getUint16(offset).cast()); } static AsyncReply int32Parser(DC data, int offset, int length, DistributedConnection? connection, List? requestSequence) { - return AsyncReply.ready(data.getInt32(offset)); + return AsyncReply.ready(data.getInt32(offset).cast()); } static AsyncReply uInt32Parser(DC data, int offset, int length, DistributedConnection? connection, List? requestSequence) { - return AsyncReply.ready(data.getUint32(offset)); + return AsyncReply.ready(data.getUint32(offset).cast()); } static AsyncReply float32Parser(DC data, int offset, int length, DistributedConnection? connection, List? requestSequence) { - return AsyncReply.ready(data.getFloat32(offset)); + return AsyncReply.ready(data.getFloat32(offset).cast()); } static AsyncReply float64Parser(DC data, int offset, int length, @@ -322,7 +322,10 @@ class DataDeserializer { offset += valueRep.size; length -= valueRep.size; - var map = Map(); + + var keyRuntimeType = keyRep.type.getRuntimeType(); + + var map = keyRuntimeType == null ? Map() : Warehouse.createMap(keyRuntimeType); var rt = new AsyncReply(); var results = new AsyncBag(); diff --git a/lib/src/Data/DataSerializer.dart b/lib/src/Data/DataSerializer.dart index f1e9331..13a1b65 100644 --- a/lib/src/Data/DataSerializer.dart +++ b/lib/src/Data/DataSerializer.dart @@ -35,35 +35,35 @@ class DataSerializer { static DataSerializerComposeResults int32Composer( value, DistributedConnection? connection) { var rt = new DC(4); - rt.setInt32(0, (value as Int32).toInt()); + rt.setInt32(0, (value as Int32).toNum()); return DataSerializerComposeResults(TransmissionTypeIdentifier.Int32, rt); } static DataSerializerComposeResults uInt32Composer( value, DistributedConnection? connection) { var rt = new DC(4); - rt.setUint32(0, (value as UInt32).toInt()); + rt.setUint32(0, (value as UInt32).toNum()); return DataSerializerComposeResults(TransmissionTypeIdentifier.UInt32, rt); } static DataSerializerComposeResults int16Composer( value, DistributedConnection? connection) { var rt = new DC(2); - rt.setInt16(0, (value as Int16).toInt()); + rt.setInt16(0, (value as Int16).toNum()); return DataSerializerComposeResults(TransmissionTypeIdentifier.Int16, rt); } static DataSerializerComposeResults uInt16Composer( value, DistributedConnection? connection) { var rt = new DC(2); - rt.setUint16(0, (value as UInt16).toInt()); + rt.setUint16(0, (value as UInt16).toNum()); return DataSerializerComposeResults(TransmissionTypeIdentifier.UInt16, rt); } static DataSerializerComposeResults float32Composer( value, DistributedConnection? connection) { var rt = new DC(4); - rt.setFloat32(0, value as double); + rt.setFloat32(0, (value as Float32).toNum()); return DataSerializerComposeResults(TransmissionTypeIdentifier.Float32, rt); } @@ -140,14 +140,14 @@ class DataSerializer { static DataSerializerComposeResults uInt8Composer( value, DistributedConnection? connection) { var rt = new DC(1); - rt[0] = (value as UInt8).toInt(); + rt[0] = (value as UInt8).toNum(); return DataSerializerComposeResults(TransmissionTypeIdentifier.UInt8, rt); } static DataSerializerComposeResults int8Composer( value, DistributedConnection? connection) { var rt = new DC(1); - rt[0] = (value as Int8).toInt(); + rt[0] = (value as Int8).toNum(); return DataSerializerComposeResults(TransmissionTypeIdentifier.Int8, rt); } diff --git a/lib/src/Data/IntType.dart b/lib/src/Data/IntType.dart index 6211c99..c8c77f9 100644 --- a/lib/src/Data/IntType.dart +++ b/lib/src/Data/IntType.dart @@ -1,5 +1,5 @@ -class IntType { - int _value = 0; +class IntType { + T _value; bool operator ==(Object other) { if (other is IntType) @@ -27,15 +27,44 @@ class IntType { return this._value <= other._value; } - operator +(IntType other) { - this._value += other._value; + + IntType operator +(IntType other) { + if (this is Int8) + return new Int8(this._value + other._value as int) as IntType; + else if (this is UInt8) + return new UInt8(this._value + other._value as int) as IntType; + else if (this is Int16) + return new Int16(this._value + other._value as int) as IntType; + else if (this is UInt16) + return new UInt16(this._value + other._value as int) as IntType; + else if (this is Int32) + return new Int32(this._value + other._value as int) as IntType; + else if (this is UInt32) + return new UInt32(this._value + other._value as int) as IntType; + + return new IntType(this._value + other._value as int) as IntType; } - operator -(IntType other) { - this._value -= other._value; + + + IntType operator -(IntType other) { + if (this is Int8) + return new Int8(this._value - other._value as int) as IntType; + else if (this is UInt8) + return new UInt8(this._value - other._value as int) as IntType; + else if (this is Int16) + return new Int16(this._value - other._value as int) as IntType; + else if (this is UInt16) + return new UInt16(this._value - other._value as int) as IntType; + else if (this is Int32) + return new Int32(this._value - other._value as int) as IntType; + else if (this is UInt32) + return new UInt32(this._value - other._value as int) as IntType; + + return new IntType(this._value - other._value as int) as IntType; } - int toInt() => _value; + T toNum() => _value; @override String toString() => _value.toString(); @@ -44,26 +73,55 @@ class IntType { int get hashCode => _value.hashCode; } -class Int32 extends IntType { +class Int32 extends IntType { Int32(int value) : super(value); } -class Int16 extends IntType { +class Int16 extends IntType { Int16(int value) : super(value); } -class Int8 extends IntType { +class Int8 extends IntType { Int8(int value) : super(value); } -class UInt32 extends IntType { +class UInt32 extends IntType { UInt32(int value) : super(value); } -class UInt16 extends IntType { +class UInt16 extends IntType { UInt16(int value) : super(value); } -class UInt8 extends IntType { +class UInt8 extends IntType { UInt8(int value) : super(value); } + +class Float32 extends IntType { + Float32(double value) : super(value); +} + + +extension IntTypeCasting on int { + T cast() { + switch(T){ + case Int8: return Int8(this) as T; + case UInt8: return UInt8(this) as T; + case Int16: return Int16(this) as T; + case UInt16: return UInt16(this) as T; + case Int32: return Int32(this) as T; + case UInt32: return UInt32(this) as T; + } + + return IntType(this) as T; + } +} + +extension Float32Casting on double { + T cast() { + + if (T == Float32) + return Float32(this) as T; + return IntType(this) as T; + } +} diff --git a/lib/src/Data/RepresentationType.dart b/lib/src/Data/RepresentationType.dart index 204cfcf..7b412b3 100644 --- a/lib/src/Data/RepresentationType.dart +++ b/lib/src/Data/RepresentationType.dart @@ -1,3 +1,5 @@ +import 'package:esiur/src/Data/IntType.dart'; + import 'IEnum.dart'; import '../Resource/Template/TemplateType.dart'; import 'IRecord.dart'; @@ -135,15 +137,15 @@ class RepresentationType { RepresentationTypeIdentifier.Dynamic: [dynamic, dynamic], RepresentationTypeIdentifier.Bool: [bool, getNullableType()], RepresentationTypeIdentifier.Char: [String, getNullableType()], - RepresentationTypeIdentifier.UInt8: [int, getNullableType()], - RepresentationTypeIdentifier.Int8: [int, getNullableType()], - RepresentationTypeIdentifier.Int16: [int, getNullableType()], - RepresentationTypeIdentifier.UInt16: [int, getNullableType()], - RepresentationTypeIdentifier.Int32: [int, getNullableType()], - RepresentationTypeIdentifier.UInt32: [int, getNullableType()], + RepresentationTypeIdentifier.UInt8: [UInt8, getNullableType()], + RepresentationTypeIdentifier.Int8: [Int8, getNullableType()], + RepresentationTypeIdentifier.Int16: [Int16, getNullableType()], + RepresentationTypeIdentifier.UInt16: [UInt16, getNullableType()], + RepresentationTypeIdentifier.Int32: [Int32, getNullableType()], + RepresentationTypeIdentifier.UInt32: [UInt32, getNullableType()], RepresentationTypeIdentifier.Int64: [int, getNullableType()], RepresentationTypeIdentifier.UInt64: [int, getNullableType()], - RepresentationTypeIdentifier.Float32: [double, getNullableType()], + RepresentationTypeIdentifier.Float32: [Float32, getNullableType()], RepresentationTypeIdentifier.Float64: [double, getNullableType()], RepresentationTypeIdentifier.Decimal: [double, getNullableType()], RepresentationTypeIdentifier.String: [String, getNullableType()], diff --git a/lib/src/Net/IIP/DistributedConnection.dart b/lib/src/Net/IIP/DistributedConnection.dart index 7c5109b..8c203ee 100644 --- a/lib/src/Net/IIP/DistributedConnection.dart +++ b/lib/src/Net/IIP/DistributedConnection.dart @@ -25,6 +25,16 @@ SOFTWARE. import 'dart:async'; import 'package:collection/collection.dart'; +import 'package:web_socket_channel/status.dart'; +import '../../Misc/Global.dart'; +import '../../Security/Membership/AuthorizationResults.dart'; +import '../../Security/Membership/AuthorizationResultsResponse.dart'; +import '../Packets/IIPAuthPacketAcknowledge.dart'; +import '../Packets/IIPAuthPacketEvent.dart'; +import '../Packets/IIPAuthPacketHeader.dart'; +import '../Packets/IIPAuthPacketIAuthHeader.dart'; +import '../Packets/IIPAuthPacketInitialize.dart'; +import '../Sockets/SocketState.dart'; import 'ConnectionStatus.dart'; import '../../Data/IntType.dart'; @@ -92,36 +102,51 @@ import '../../Security/Integrity/SHA256.dart'; import '../../Resource/ResourceTrigger.dart'; import './DistributedServer.dart'; +import '../Packets/IIPAuthPacketHashAlgorithm.dart'; + class DistributedConnection extends NetworkConnection with IStore { - //public delegate void ReadyEvent(DistributedConnection sender); - //public delegate void ErrorEvent(DistributedConnection sender, byte errorCode, string errorMessage); - /// - /// Ready event is raised when the connection is fully established. - /// - //public event ReadyEvent OnReady; + // fields + bool _invalidCredentials = false; - /// - /// Error event - /// - //public event ErrorEvent OnError; - - AsyncReply? _openReply; - - DistributedServer? _server; + Timer? _keepAliveTimer; + DateTime? _lastKeepAliveSent; + DateTime? _lastKeepAliveReceived; IIPPacket _packet = new IIPPacket(); IIPAuthPacket _authPacket = new IIPAuthPacket(); - Session? _session; + Session _session = new Session(); + AsyncReply? _openReply; DC? _localPasswordOrToken; - DC? _localNonce, _remoteNonce; + bool _ready = false, _readyToEstablish = false; String? _hostname; int _port = 10518; - bool _ready = false, _readyToEstablish = false; + DistributedServer? _server; + DateTime? _loginDate; + + // Properties + DateTime? get loginDate => _loginDate; + + int jitter = 0; + ConnectionStatus _status = ConnectionStatus.Closed; + ConnectionStatus get status => _status; + + + //Attributes + int keepAliveTime = 10; + int keepAliveInterval = 30; + AsyncReply Function (Map)? authenticator; + bool autoReconnect = false; + int reconnectInterval = 5; + + DistributedServer? get server => _server; + + + KeyList> _attachedResources = new KeyList>(); @@ -149,34 +174,13 @@ class DistributedConnection extends NetworkConnection with IStore { Map> _subscriptions = new Map>(); - DateTime? _lastKeepAliveSent; - DateTime? _lastKeepAliveReceived; - int jitter = 0; - int keepAliveTime = 10; - int reconnectInterval = 5; - DistributedServer? server; - - /// - /// Local username to authenticate ourselves. - /// - String get localUsername => _session?.localAuthentication.username ?? ""; - - /// - /// Peer's username. - /// - String get remoteUsername => - _session?.remoteAuthentication.username ?? ""; // { get; set; } - - /// - /// Working domain. - /// - //public string Domain { get { return domain; } } + /// /// The session related to this connection. /// - Session? get session => _session; + Session get session => _session; /// /// Distributed server responsible for this connection, usually for incoming connections. @@ -292,26 +296,41 @@ class DistributedConnection extends NetworkConnection with IStore { if (_openReply != null) throw AsyncException(ErrorType.Exception, 0, "Connection in progress"); - status = ConnectionStatus.Connecting; + _status = ConnectionStatus.Connecting; _openReply = new AsyncReply(); - //print("_openReply hash ${_openReply.hashCode}"); if (hostname != null) { - _session = - new Session(new ClientAuthentication(), new HostAuthentication()); + _session = new Session(); + + _session.authenticationType = AuthenticationType.Client; + _session.localMethod = method; + _session.remoteMethod = AuthenticationMethod.None; + + _session.localHeaders[IIPAuthPacketHeader.Domain] = domain; + _session.localHeaders[IIPAuthPacketHeader.Nonce] = Global.generateCode(32); + + if (method == AuthenticationMethod.Credentials) + { + _session.localHeaders[IIPAuthPacketHeader.Username] = username; + } + else if (method == AuthenticationMethod.Token) + { + _session.localHeaders[IIPAuthPacketHeader.TokenIndex] = tokenIndex; + } + else if (method == AuthenticationMethod.Certificate) + { + throw Exception("Unsupported authentication method."); + } - _session?.localAuthentication.method = method; - _session?.localAuthentication.tokenIndex = tokenIndex; - _session?.localAuthentication.domain = domain; - _session?.localAuthentication.username = username; _localPasswordOrToken = passwordOrToken; _invalidCredentials = false; + } - if (_session == null) - throw AsyncException(ErrorType.Exception, 0, "Session not initialized"); + //if (_session == null) + // throw AsyncException(ErrorType.Exception, 0, "Session not initialized"); if (socket == null) { if (useWebsocket || kIsWeb) { @@ -323,7 +342,8 @@ class DistributedConnection extends NetworkConnection with IStore { _port = port ?? _port; _hostname = hostname ?? _hostname; - if (_hostname == null) throw Exception("Host not specified."); + if (_hostname == null) + throw Exception("Host not specified."); _connectSocket(socket); @@ -347,15 +367,13 @@ class DistributedConnection extends NetworkConnection with IStore { }); } - bool autoReconnect = false; - bool _invalidCredentials = false; @override void disconnected() { // clean up _ready = false; _readyToEstablish = false; - status = ConnectionStatus.Closed; + _status = ConnectionStatus.Closed; //print("Disconnected .."); @@ -489,40 +507,55 @@ class DistributedConnection extends NetworkConnection with IStore { Instance? instance; _declare() { - var dmn = DC.stringToBytes(_session?.localAuthentication.domain ?? ""); - if (_session?.localAuthentication.method == - AuthenticationMethod.Credentials) { - // declare (Credentials -> No Auth, No Enctypt) + // if (session.KeyExchanger != null) + // { + // // create key + // var key = session.keyExchanger.GetPublicKey(); + // session.localHeaders[IIPAuthPacketHeader.CipherKey] = key; + // } - var un = DC.stringToBytes(_session?.localAuthentication.username ?? ""); - _sendParams() - ..addUint8(0x60) - ..addUint8(dmn.length) - ..addDC(dmn) - ..addDC(_localNonce as DC) - ..addUint8(un.length) - ..addDC(un) - ..done(); //, dmn, localNonce, (byte)un.Length, un); - } else if (_session?.localAuthentication.method == - AuthenticationMethod.Token) { - _sendParams() - ..addUint8(0x70) - ..addUint8(dmn.length) - ..addDC(dmn) - ..addDC(_localNonce as DC) - ..addUint64(_session?.localAuthentication.tokenIndex ?? 0) - ..done(); //, dmn, localNonce, token + if (session.localMethod == AuthenticationMethod.Credentials + && session.remoteMethod == AuthenticationMethod.None) + { + // change to Map for compatibility + var headers = Codec.compose(session.localHeaders, this); - } else if (_session?.localAuthentication.method == - AuthenticationMethod.None) { - _sendParams() - ..addUint8(0x40) - ..addUint8(dmn.length) - ..addDC(dmn) - ..done(); //, dmn, localNonce, token - } + // declare (Credentials -> No Auth, No Enctypt) + _sendParams() + ..addUint8(IIPAuthPacketInitialize.CredentialsNoAuth) + ..addDC(headers) + ..done(); + + } + else if (session.localMethod == AuthenticationMethod.Token + && session.remoteMethod == AuthenticationMethod.None) + { + // change to Map for compatibility + var headers = Codec.compose(session.localHeaders, this); + + _sendParams() + ..addUint8(IIPAuthPacketInitialize.TokenNoAuth) + ..addDC(headers) + ..done(); + } + else if (session.localMethod == AuthenticationMethod.None + && session.remoteMethod == AuthenticationMethod.None) + { + // change to Map for compatibility + var headers = Codec.compose(session.localHeaders, this); + + // @REVIEW: MITM Attack can still occure + _sendParams() + ..addUint8(IIPAuthPacketInitialize.NoAuthNoAuth) + ..addDC(headers) + ..done(); + } + else + { + throw new Exception("Authentication method is not implemented."); + } } /// @@ -530,21 +563,16 @@ class DistributedConnection extends NetworkConnection with IStore { /// /// Any socket that implements ISocket. assign(ISocket socket) { - super.assign(socket); - _session?.remoteAuthentication.source - ?.attributes[SourceAttributeType.IPv4] = socket.remoteEndPoint?.address; - _session?.remoteAuthentication.source - ?.attributes[SourceAttributeType.Port] = socket.remoteEndPoint?.port; - _session?.localAuthentication.source?.attributes[SourceAttributeType.IPv4] = - socket.localEndPoint?.address; - _session?.localAuthentication.source?.attributes[SourceAttributeType.Port] = - socket.localEndPoint?.port; + super.assign(socket); - if (_session?.localAuthentication.type == AuthenticationType.Client) { - // declare (Credentials -> No Auth, No Enctypt) - _declare(); - } + + session.localHeaders[IIPAuthPacketHeader.IPv4] = socket.remoteEndPoint?.address; + if (socket.state == SocketState.Established && + session.authenticationType == AuthenticationType.Client) + { + _declare(); + } } /// @@ -592,11 +620,9 @@ class DistributedConnection extends NetworkConnection with IStore { /// Create a new instance of a distributed connection /// DistributedConnection() { - //myId = Global.GenerateCode(12); - // localParams.Host = DistributedParameters.HostType.Host; - _session = - new Session(new HostAuthentication(), new ClientAuthentication()); - init(); + session.authenticationType = AuthenticationType.Host; + session.localMethod = AuthenticationMethod.None; + init(); } String? link(IResource resource) { @@ -610,9 +636,6 @@ class DistributedConnection extends NetworkConnection with IStore { return null; } - Timer? _keepAliveTimer; - - int keepAliveInterval = 30; void init() { _queue.then((x) { @@ -624,11 +647,14 @@ class DistributedConnection extends NetworkConnection with IStore { var r = new Random(); var n = new DC(32); - for (var i = 0; i < 32; i++) n[i] = r.nextInt(255); - _localNonce = n; + for (var i = 0; i < 32; i++) + n[i] = r.nextInt(255); + + session.localHeaders[IIPAuthPacketHeader.Nonce] = n; - // _keepAliveTimer = - // Timer(Duration(seconds: KeepAliveInterval), _keepAliveTimer_Elapsed); + // removed because dart timers start at initialization + // _keepAliveTimer = + // Timer(Duration(seconds: keepAliveInterval), _keepAliveTimerElapsed); } void _keepAliveTimerElapsed() { @@ -682,69 +708,64 @@ class DistributedConnection extends NetworkConnection with IStore { int processPacket( DC msg, int offset, int ends, NetworkBuffer data, int chunkId) { - var packet = new IIPPacket(); if (_ready) { - //print("Inc " + msg.length.toString()); - var rt = packet.parse(msg, offset, ends); + var rt = _packet.parse(msg, offset, ends); - //print("Packet " + packet.toString()); if (rt <= 0) { - // print("hold"); var size = ends - offset; data.holdFor(msg, offset, size, size - rt); return ends; } else { - //print("CMD ${packet.command} ${offset} ${ends}"); offset += rt; - if (packet.command == IIPPacketCommand.Event) { - switch (packet.event) { + if (_packet.command == IIPPacketCommand.Event) { + switch (_packet.event) { case IIPPacketEvent.ResourceReassigned: iipEventResourceReassigned( - packet.resourceId, packet.newResourceId); + _packet.resourceId, _packet.newResourceId); break; case IIPPacketEvent.ResourceDestroyed: - iipEventResourceDestroyed(packet.resourceId); + iipEventResourceDestroyed(_packet.resourceId); break; case IIPPacketEvent.PropertyUpdated: - iipEventPropertyUpdated(packet.resourceId, packet.methodIndex, - packet.dataType ?? TransmissionType.Null, msg); + iipEventPropertyUpdated(_packet.resourceId, _packet.methodIndex, + _packet.dataType ?? TransmissionType.Null, msg); break; case IIPPacketEvent.EventOccurred: - iipEventEventOccurred(packet.resourceId, packet.methodIndex, - packet.dataType ?? TransmissionType.Null, msg); + iipEventEventOccurred(_packet.resourceId, _packet.methodIndex, + _packet.dataType ?? TransmissionType.Null, msg); break; case IIPPacketEvent.ChildAdded: - iipEventChildAdded(packet.resourceId, packet.childId); + iipEventChildAdded(_packet.resourceId, _packet.childId); break; case IIPPacketEvent.ChildRemoved: - iipEventChildRemoved(packet.resourceId, packet.childId); + iipEventChildRemoved(_packet.resourceId, _packet.childId); break; case IIPPacketEvent.Renamed: - iipEventRenamed(packet.resourceId, packet.resourceName); + iipEventRenamed(_packet.resourceId, _packet.resourceName); break; case IIPPacketEvent.AttributesUpdated: // @TODO: fix this //iipEventAttributesUpdated(packet.resourceId, packet.dataType. ?? TransmissionType.Null); break; } - } else if (packet.command == IIPPacketCommand.Request) { - switch (packet.action) { + } else if (_packet.command == IIPPacketCommand.Request) { + switch (_packet.action) { // Manage case IIPPacketAction.AttachResource: - iipRequestAttachResource(packet.callbackId, packet.resourceId); + iipRequestAttachResource(_packet.callbackId, _packet.resourceId); break; case IIPPacketAction.ReattachResource: iipRequestReattachResource( - packet.callbackId, packet.resourceId, packet.resourceAge); + _packet.callbackId, _packet.resourceId, _packet.resourceAge); break; case IIPPacketAction.DetachResource: - iipRequestDetachResource(packet.callbackId, packet.resourceId); + iipRequestDetachResource(_packet.callbackId, _packet.resourceId); break; case IIPPacketAction.CreateResource: @@ -753,70 +774,70 @@ class DistributedConnection extends NetworkConnection with IStore { // packet.resourceId, packet.content); break; case IIPPacketAction.DeleteResource: - iipRequestDeleteResource(packet.callbackId, packet.resourceId); + iipRequestDeleteResource(_packet.callbackId, _packet.resourceId); break; case IIPPacketAction.AddChild: iipRequestAddChild( - packet.callbackId, packet.resourceId, packet.childId); + _packet.callbackId, _packet.resourceId, _packet.childId); break; case IIPPacketAction.RemoveChild: iipRequestRemoveChild( - packet.callbackId, packet.resourceId, packet.childId); + _packet.callbackId, _packet.resourceId, _packet.childId); break; case IIPPacketAction.RenameResource: iipRequestRenameResource( - packet.callbackId, packet.resourceId, packet.resourceName); + _packet.callbackId, _packet.resourceId, _packet.resourceName); break; // Inquire case IIPPacketAction.TemplateFromClassName: iipRequestTemplateFromClassName( - packet.callbackId, packet.className); + _packet.callbackId, _packet.className); break; case IIPPacketAction.TemplateFromClassId: - iipRequestTemplateFromClassId(packet.callbackId, packet.classId); + iipRequestTemplateFromClassId(_packet.callbackId, _packet.classId); break; case IIPPacketAction.TemplateFromResourceId: iipRequestTemplateFromResourceId( - packet.callbackId, packet.resourceId); + _packet.callbackId, _packet.resourceId); break; case IIPPacketAction.QueryLink: - iipRequestQueryResources(packet.callbackId, packet.resourceLink); + iipRequestQueryResources(_packet.callbackId, _packet.resourceLink); break; case IIPPacketAction.ResourceChildren: - iipRequestResourceChildren(packet.callbackId, packet.resourceId); + iipRequestResourceChildren(_packet.callbackId, _packet.resourceId); break; case IIPPacketAction.ResourceParents: - iipRequestResourceParents(packet.callbackId, packet.resourceId); + iipRequestResourceParents(_packet.callbackId, _packet.resourceId); break; case IIPPacketAction.ResourceHistory: - iipRequestInquireResourceHistory(packet.callbackId, - packet.resourceId, packet.fromDate, packet.toDate); + iipRequestInquireResourceHistory(_packet.callbackId, + _packet.resourceId, _packet.fromDate, _packet.toDate); break; case IIPPacketAction.LinkTemplates: - iipRequestLinkTemplates(packet.callbackId, packet.resourceLink); + iipRequestLinkTemplates(_packet.callbackId, _packet.resourceLink); break; // Invoke case IIPPacketAction.InvokeFunction: iipRequestInvokeFunction( - packet.callbackId, - packet.resourceId, - packet.methodIndex, - packet.dataType ?? TransmissionType.Null, + _packet.callbackId, + _packet.resourceId, + _packet.methodIndex, + _packet.dataType ?? TransmissionType.Null, msg); break; case IIPPacketAction.Listen: iipRequestListen( - packet.callbackId, packet.resourceId, packet.methodIndex); + _packet.callbackId, _packet.resourceId, _packet.methodIndex); break; case IIPPacketAction.Unlisten: iipRequestUnlisten( - packet.callbackId, packet.resourceId, packet.methodIndex); + _packet.callbackId, _packet.resourceId, _packet.methodIndex); break; /* case IIPPacketAction.GetProperty: @@ -829,10 +850,10 @@ class DistributedConnection extends NetworkConnection with IStore { */ case IIPPacketAction.SetProperty: iipRequestSetProperty( - packet.callbackId, - packet.resourceId, - packet.methodIndex, - packet.dataType ?? TransmissionType.Null, + _packet.callbackId, + _packet.resourceId, + _packet.methodIndex, + _packet.dataType ?? TransmissionType.Null, msg); break; @@ -865,53 +886,53 @@ class DistributedConnection extends NetworkConnection with IStore { case IIPPacketAction.KeepAlive: iipRequestKeepAlive( - packet.callbackId, packet.currentTime, packet.interval); + _packet.callbackId, _packet.currentTime, _packet.interval); break; case IIPPacketAction.ProcedureCall: - iipRequestProcedureCall(packet.callbackId, packet.procedure, - packet.dataType as TransmissionType, msg); + iipRequestProcedureCall(_packet.callbackId, _packet.procedure, + _packet.dataType as TransmissionType, msg); break; case IIPPacketAction.StaticCall: - iipRequestStaticCall(packet.callbackId, packet.classId, - packet.methodIndex, packet.dataType as TransmissionType, msg); + iipRequestStaticCall(_packet.callbackId, _packet.classId, + _packet.methodIndex, _packet.dataType as TransmissionType, msg); break; } - } else if (packet.command == IIPPacketCommand.Reply) { - switch (packet.action) { + } else if (_packet.command == IIPPacketCommand.Reply) { + switch (_packet.action) { // Manage case IIPPacketAction.AttachResource: - iipReply(packet.callbackId, [ - packet.classId, - packet.resourceAge, - packet.resourceLink, - packet.dataType ?? TransmissionType.Null, + iipReply(_packet.callbackId, [ + _packet.classId, + _packet.resourceAge, + _packet.resourceLink, + _packet.dataType ?? TransmissionType.Null, msg ]); break; case IIPPacketAction.ReattachResource: - iipReply(packet.callbackId, [ - packet.resourceAge, - packet.dataType ?? TransmissionType.Null, + iipReply(_packet.callbackId, [ + _packet.resourceAge, + _packet.dataType ?? TransmissionType.Null, msg ]); break; case IIPPacketAction.DetachResource: - iipReply(packet.callbackId); + iipReply(_packet.callbackId); break; case IIPPacketAction.CreateResource: - iipReply(packet.callbackId, [packet.resourceId]); + iipReply(_packet.callbackId, [_packet.resourceId]); break; case IIPPacketAction.DeleteResource: case IIPPacketAction.AddChild: case IIPPacketAction.RemoveChild: case IIPPacketAction.RenameResource: - iipReply(packet.callbackId); + iipReply(_packet.callbackId); break; // Inquire @@ -919,12 +940,12 @@ class DistributedConnection extends NetworkConnection with IStore { case IIPPacketAction.TemplateFromClassName: case IIPPacketAction.TemplateFromClassId: case IIPPacketAction.TemplateFromResourceId: - if (packet.dataType != null) { - var content = msg.clip(packet.dataType?.offset ?? 0, - packet.dataType?.contentLength ?? 0); - iipReply(packet.callbackId, [TypeTemplate.parse(content)]); + if (_packet.dataType != null) { + var content = msg.clip(_packet.dataType?.offset ?? 0, + _packet.dataType?.contentLength ?? 0); + iipReply(_packet.callbackId, [TypeTemplate.parse(content)]); } else { - iipReportError(packet.callbackId, ErrorType.Management, + iipReportError(_packet.callbackId, ErrorType.Management, ExceptionCode.TemplateNotFound.index, "Template not found"); } @@ -935,16 +956,16 @@ class DistributedConnection extends NetworkConnection with IStore { case IIPPacketAction.ResourceParents: case IIPPacketAction.ResourceHistory: case IIPPacketAction.LinkTemplates: - iipReply(packet.callbackId, - [packet.dataType ?? TransmissionType.Null, msg]); + iipReply(_packet.callbackId, + [_packet.dataType ?? TransmissionType.Null, msg]); break; // Invoke case IIPPacketAction.InvokeFunction: case IIPPacketAction.StaticCall: case IIPPacketAction.ProcedureCall: - iipReplyInvoke(packet.callbackId, - packet.dataType ?? TransmissionType.Null, msg); + iipReplyInvoke(_packet.callbackId, + _packet.dataType ?? TransmissionType.Null, msg); break; // case IIPPacketAction.GetProperty: @@ -958,44 +979,44 @@ class DistributedConnection extends NetworkConnection with IStore { case IIPPacketAction.Listen: case IIPPacketAction.Unlisten: case IIPPacketAction.SetProperty: - iipReply(packet.callbackId); + iipReply(_packet.callbackId); break; // Attribute case IIPPacketAction.GetAllAttributes: case IIPPacketAction.GetAttributes: - iipReply(packet.callbackId, - [packet.dataType ?? TransmissionType.Null, msg]); + iipReply(_packet.callbackId, + [_packet.dataType ?? TransmissionType.Null, msg]); break; case IIPPacketAction.UpdateAllAttributes: case IIPPacketAction.UpdateAttributes: case IIPPacketAction.ClearAllAttributes: case IIPPacketAction.ClearAttributes: - iipReply(packet.callbackId); + iipReply(_packet.callbackId); break; case IIPPacketAction.KeepAlive: - iipReply(packet.callbackId, [packet.currentTime, packet.jitter]); + iipReply(_packet.callbackId, [_packet.currentTime, _packet.jitter]); break; } - } else if (packet.command == IIPPacketCommand.Report) { - switch (packet.report) { + } else if (_packet.command == IIPPacketCommand.Report) { + switch (_packet.report) { case IIPPacketReport.ManagementError: - iipReportError(packet.callbackId, ErrorType.Management, - packet.errorCode, null); + iipReportError(_packet.callbackId, ErrorType.Management, + _packet.errorCode, null); break; case IIPPacketReport.ExecutionError: - iipReportError(packet.callbackId, ErrorType.Exception, - packet.errorCode, packet.errorMessage); + iipReportError(_packet.callbackId, ErrorType.Exception, + _packet.errorCode, _packet.errorMessage); break; case IIPPacketReport.ProgressReport: - iipReportProgress(packet.callbackId, ProgressType.Execution, - packet.progressValue, packet.progressMax); + iipReportProgress(_packet.callbackId, ProgressType.Execution, + _packet.progressValue, _packet.progressMax); break; case IIPPacketReport.ChunkStream: - iipReportChunk(packet.callbackId, - packet.dataType ?? TransmissionType.Null, msg); + iipReportChunk(_packet.callbackId, + _packet.dataType ?? TransmissionType.Null, msg); break; } } @@ -1003,176 +1024,22 @@ class DistributedConnection extends NetworkConnection with IStore { } else { var rt = _authPacket.parse(msg, offset, ends); + if (rt <= 0) { data.holdForNeeded(msg, ends - rt); return ends; } else { offset += rt; - if (_session?.localAuthentication.type == AuthenticationType.Host) { - if (_authPacket.command == IIPAuthPacketCommand.Declare) { - if (_authPacket.remoteMethod == AuthenticationMethod.Credentials && - _authPacket.localMethod == AuthenticationMethod.None) { - /* - server.membership.userExists(_authPacket.remoteUsername, _authPacket.domain).then((x) - { - if (x) - { - _session.remoteAuthentication.username = _authPacket.remoteUsername; - _remoteNonce = _authPacket.remoteNonce; - _session.remoteAuthentication.domain = _authPacket.domain; - sendParams() - .addUint8(0xa0) - .addDC(_localNonce) - .done(); - } - else - { - sendParams().addUint8(0xc0).addUint8(1).addUint16(14).addString("User not found").done(); - } - }); - */ - - } - } else if (_authPacket.command == IIPAuthPacketCommand.Action) { - if (_authPacket.action == IIPAuthPacketAction.AuthenticateHash) { - var remoteHash = _authPacket.hash; - - /* - server.membership.getPassword(_session.remoteAuthentication.username, - _session.remoteAuthentication.domain).then((pw) - { - if (pw != null) - { - //var hash = hashFunc.ComputeHash(BinaryList.ToBytes(pw, remoteNonce, localNonce)); - var hash = SHA256.compute((new BinaryList()) - .addDC(pw) - .addDC(_remoteNonce) - .addDC(_localNonce) - .toDC()); - if (hash.sequenceEqual(remoteHash)) - { - // send our hash - //var localHash = hashFunc.ComputeHash(BinaryList.ToBytes(localNonce, remoteNonce, pw)); - //SendParams((byte)0, localHash); - - var localHash = SHA256.compute - ((new BinaryList()).addDC(_localNonce).addDC(_remoteNonce).addDC(pw).toDC()); - sendParams().addUint8(0).addDC(localHash).done(); - - _readyToEstablish = true; - } - else - { - sendParams().addUint8(0xc0).addUint8(1).addUint16(5).addString("Error").done(); - } - } - }); - */ - } else if (_authPacket.action == - IIPAuthPacketAction.NewConnection) { - if (_readyToEstablish) { - var r = new Random(); - - var sid = DC(32); - - for (var i = 0; i < 32; i++) sid[i] = r.nextInt(255); - _session?.id = sid; - - _sendParams() - ..addUint8(0x28) - ..addDC(sid) - ..done(); - - _ready = true; - status = ConnectionStatus.Connected; - - _openReply?.trigger(true); - _openReply = null; - emitArgs("ready", []); - //OnReady?.Invoke(this); - // server.membership.login(session); - - } - } - } - } else if (_session?.localAuthentication.type == - AuthenticationType.Client) { - if (_authPacket.command == IIPAuthPacketCommand.Acknowledge) { - if (_authPacket.remoteMethod == AuthenticationMethod.None) { - _sendParams() - ..addUint8(0x20) - ..addUint16(0) - ..done(); - } else if (_authPacket.remoteMethod == - AuthenticationMethod.Credentials || - _authPacket.remoteMethod == AuthenticationMethod.Token) { - _remoteNonce = _authPacket.remoteNonce; - - // send our hash - var localHash = SHA256.compute((BinaryList() - ..addDC(_localPasswordOrToken as DC) - ..addDC(_localNonce as DC) - ..addDC(_remoteNonce as DC)) - .toDC()); - - _sendParams() - ..addUint8(0) - ..addDC(localHash) - ..done(); - } - //SendParams((byte)0, localHash); - } else if (_authPacket.command == IIPAuthPacketCommand.Action) { - if (_authPacket.action == IIPAuthPacketAction.AuthenticateHash) { - // check if the server knows my password - var remoteHash = SHA256.compute((BinaryList() - ..addDC(_remoteNonce as DC) - ..addDC(_localNonce as DC) - ..addDC(_localPasswordOrToken as DC)) - .toDC()); - - if (remoteHash.sequenceEqual(_authPacket.hash)) { - // send establish request - _sendParams() - ..addUint8(0x20) - ..addUint16(0) - ..done(); - } else { - _sendParams() - ..addUint8(0xc0) - ..addUint8(ExceptionCode.ChallengeFailed.index) - ..addUint16(16) - ..addString("Challenge Failed") - ..done(); - - //SendParams((byte)0xc0, 1, 5, DC.ToBytes("Error")); - } - } else if (_authPacket.action == - IIPAuthPacketAction.ConnectionEstablished) { - _session?.id = _authPacket.sessionId; - - _ready = true; - status = ConnectionStatus.Connected; - - _openReply?.trigger(true); - _openReply = null; - emitArgs("ready", []); - - // start perodic keep alive timer - _keepAliveTimer = Timer( - Duration(seconds: keepAliveInterval), _keepAliveTimerElapsed); - } - } else if (_authPacket.command == IIPAuthPacketCommand.Error) { - _invalidCredentials = true; - var ex = AsyncException(ErrorType.Management, _authPacket.errorCode, - _authPacket.errorMessage); - _openReply?.triggerError(ex); - _openReply = null; - emitArgs("error", [ex]); - //OnError?.Invoke(this, authPacket.ErrorCode, authPacket.ErrorMessage); - close(); - } + if (session.authenticationType == AuthenticationType.Host) + { + _processHostAuth(msg); } + else if (session.authenticationType == AuthenticationType.Client) + { + _processClientAuth(msg); + } + } } @@ -1182,6 +1049,701 @@ class DistributedConnection extends NetworkConnection with IStore { // processPacket(msg, offset, ends, data, chunkId); } + + void _processClientAuth(DC data) + { + if (_authPacket.command == IIPAuthPacketCommand.Acknowledge) + { + // if there is a mismatch in authentication + if (session.localMethod != _authPacket.remoteMethod + || session.remoteMethod != _authPacket.localMethod) + { + _openReply?.triggerError(new Exception("Peer refused authentication method.")); + _openReply = null; + } + + // Parse remote headers + + var dataType = _authPacket.dataType!; + + var pr = Codec.parse(data, dataType.offset, this, null, dataType); + + var rt= pr.reply.result as Map; + + session.remoteHeaders = rt; + + if (session.localMethod == AuthenticationMethod.None) + { + // send establish + _sendParams() + ..addUint8(IIPAuthPacketAction.EstablishNewSession) + ..done(); + } + else if (session.localMethod == AuthenticationMethod.Credentials + || session.localMethod == AuthenticationMethod.Token) + { + var remoteNonce = session.remoteHeaders[IIPAuthPacketHeader.Nonce]; + var localNonce = session.localHeaders[IIPAuthPacketHeader.Nonce]; + + // send our hash + // local nonce + password or token + remote nonce + var challenge = SHA256.compute((new BinaryList() + ..addDC(localNonce) + ..addDC(_localPasswordOrToken!) + ..addDC(remoteNonce)) + .toDC()); + + + _sendParams() + ..addUint8(IIPAuthPacketAction.AuthenticateHash) + ..addUint8(IIPAuthPacketHashAlgorithm.SHA256) + ..addUint16(challenge.length) + ..addDC(challenge) + ..done(); + } + + } + else if (_authPacket.command == IIPAuthPacketCommand.Action) + { + if (_authPacket.action == IIPAuthPacketAction.AuthenticateHash) + { + var remoteNonce = session.remoteHeaders[IIPAuthPacketHeader.Nonce]; + var localNonce = session.localHeaders[IIPAuthPacketHeader.Nonce]; + + // check if the server knows my password + + var challenge = SHA256.compute((new BinaryList() + ..addDC(remoteNonce) + ..addDC(_localPasswordOrToken!) + ..addDC(localNonce) + ).toDC()); + + + if (challenge.sequenceEqual(_authPacket.challenge)) + { + // send establish request + _sendParams() + ..addUint8(IIPAuthPacketAction.EstablishNewSession) + ..done(); + } + else + { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.ChallengeFailed.index) + ..addUint16(16) + ..addString("Challenge Failed") + ..done(); + + } + } + } + else if (_authPacket.command == IIPAuthPacketCommand.Event) + { + if (_authPacket.event == IIPAuthPacketEvent.ErrorTerminate + || _authPacket.event == IIPAuthPacketEvent.ErrorMustEncrypt + || _authPacket.event == IIPAuthPacketEvent.ErrorRetry) + { + _invalidCredentials = true; + _openReply?.triggerError(new AsyncException(ErrorType.Management, _authPacket.errorCode, _authPacket.message)); + _openReply = null; + + var ex = AsyncException(ErrorType.Management, _authPacket.errorCode, + _authPacket.message); + + emitArgs("error", [ex]); + + close(); + } + else if (_authPacket.event == IIPAuthPacketEvent.IndicationEstablished) + { + session.id = _authPacket.sessionId; + + _ready = true; + _status = ConnectionStatus.Connected; + + // put it in the warehouse + + if (this.instance == null) + { + Warehouse.put(this.hashCode.toString().replaceAll("/", "_"), this, null, server).then((x) + { + _openReply?.trigger(true); + + emitArgs("ready", []); + _openReply = null; + + }).error((x) + { + _openReply?.triggerError(x); + _openReply = null; + }); + } + else + { + _openReply?.trigger(true); + _openReply = null; + emitArgs("ready", []); + } + + // start perodic keep alive timer + _keepAliveTimer = + Timer(Duration(seconds: keepAliveInterval), _keepAliveTimerElapsed); + + + } + else if (_authPacket.event == IIPAuthPacketEvent.IAuthPlain) + { + var dataType = _authPacket.dataType!; + var pr = Codec.parse(data, dataType.offset, this, null, dataType); + var rt = pr.reply.result; + + Map headers = rt; + //headers[IIPAuthPacketIAuthHeader.Reference] = rt; + + if (authenticator == null) + { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.NotSupported.index) + ..addUint16(13) + ..addString("Not supported") + ..done(); + } + else + { + authenticator!(headers).then((response) + { + _sendParams() + ..addUint8(IIPAuthPacketAction.IAuthPlain) + ..addUint32(headers[IIPAuthPacketIAuthHeader.Reference]) + ..addDC(Codec.compose(response, this)) + ..done(); + }) + .timeout(headers.containsKey(IIPAuthPacketIAuthHeader.Timeout) ? + headers[IIPAuthPacketIAuthHeader.Timeout] * 1000 : 30000, + onTimeout: () { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.Timeout.index) + ..addUint16(7) + ..addString("Timeout") + ..done(); + } + ); + } + } + else if (_authPacket.event == IIPAuthPacketEvent.IAuthHashed) + { + var dataType = _authPacket.dataType!; + var parsed = Codec.parse(data, dataType.offset, this, null, dataType); + Map headers = parsed.reply.result; + + + if (authenticator == null) + { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.NotSupported.index) + ..addUint16(13) + ..addString("Not supported") + ..done(); + } + else + { + + authenticator!(headers).then((response) + { + + var hash = SHA256.compute((new BinaryList() + ..addDC(session.localHeaders[IIPAuthPacketHeader.Nonce]) + ..addDC(Codec.compose(response, this)) + ..addDC(session.remoteHeaders[IIPAuthPacketHeader.Nonce]) + ).toDC()); + + _sendParams() + ..addUint8(IIPAuthPacketAction.IAuthHashed) + ..addUint32(headers[IIPAuthPacketIAuthHeader.Reference]) + ..addUint8(IIPAuthPacketHashAlgorithm.SHA256) + ..addUint16(hash.length) + ..addDC(hash) + ..done(); + }) + .timeout(headers.containsKey(IIPAuthPacketIAuthHeader.Timeout) ? + headers[IIPAuthPacketIAuthHeader.Timeout] * 1000 : 30000, + onTimeout: () { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.Timeout.index) + ..addUint16(7) + ..addString("Timeout") + ..done(); + }); + } + } + else if (_authPacket.event == IIPAuthPacketEvent.IAuthEncrypted) + { + throw new Exception("IAuthEncrypted not implemented."); + } + } + } + + void _processHostAuth(DC data) + { + if (_authPacket.command == IIPAuthPacketCommand.Initialize) + { + // Parse headers + + var dataType = _authPacket.dataType!; + + var parsed = Codec.parse(data, dataType.offset, this, null, dataType); + + Map rt = parsed.reply.result; + + + session.remoteHeaders = rt; + session.remoteMethod = _authPacket.localMethod; + + + if (_authPacket.initialization == IIPAuthPacketInitialize.CredentialsNoAuth) + { + try + { + + var username = session.remoteHeaders[IIPAuthPacketHeader.Username]; + var domain = session.remoteHeaders[IIPAuthPacketHeader.Domain]; + + if (_server?.membership == null) + { + var errMsg = DC.stringToBytes("Membership not set."); + + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.GeneralFailure.index) + ..addUint16(errMsg.length) + ..addDC(errMsg) + ..done(); + } + else { + _server!.membership!.userExists(username, domain).then((x) + { + if (x != null) + { + session.authorizedAccount = x; + + var localHeaders = session.localHeaders; + + _sendParams() + ..addUint8(IIPAuthPacketAcknowledge.NoAuthCredentials) + ..addDC(Codec.compose(localHeaders, this)) + ..done(); + } + else + { + // Send user not found error + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.UserOrTokenNotFound.index) + ..addUint16(14) + ..addString("User not found") + ..done(); + } + }); + } + } + catch (ex) + { + // Send the server side error + var errMsg = DC.stringToBytes(ex.toString()); + + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.GeneralFailure.index) + ..addUint16(errMsg.length) + ..addDC(errMsg) + ..done(); + } + } + else if (_authPacket.initialization == IIPAuthPacketInitialize.TokenNoAuth) + { + try + { + if (_server?.membership == null) + { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.UserOrTokenNotFound.index) + ..addUint16(15) + ..addString("Token not found") + ..done(); + } + // Check if user and token exists + else + { + int tokenIndex = session.remoteHeaders[IIPAuthPacketHeader.TokenIndex]; + String domain = session.remoteHeaders[IIPAuthPacketHeader.Domain]; + + + _server!.membership!.tokenExists(tokenIndex, domain).then((x) + { + if (x != null) + { + session.authorizedAccount = x; + + var localHeaders = session.localHeaders; + + _sendParams() + ..addUint8(IIPAuthPacketAcknowledge.NoAuthToken) + ..addDC(Codec.compose(localHeaders, this)) + ..done(); + + } + else + { + // Send token not found error. + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.UserOrTokenNotFound.index) + ..addUint16(15) + ..addString("Token not found") + ..done(); + } + }); + } + } + catch (ex) + { + // Sender server side error. + + var errMsg = DC.stringToBytes(ex.toString()); + + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.GeneralFailure.index) + ..addUint16(errMsg.length) + ..addDC(errMsg) + ..done(); + } + } + else if (_authPacket.initialization == IIPAuthPacketInitialize.NoAuthNoAuth) + { + try + { + // Check if guests are allowed + if (_server?.membership?.guestsAllowed ?? true) + { + var localHeaders = session.localHeaders; + + session.authorizedAccount = "g-" + Global.generateCode(); + + _readyToEstablish = true; + + _sendParams() + ..addUint8(IIPAuthPacketAcknowledge.NoAuthNoAuth) + ..addDC(Codec.compose(localHeaders, this)) + ..done(); + } + else + { + // Send access denied error because the server does not allow guests. + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.AccessDenied.index) + ..addUint16(18) + ..addString("Guests not allowed") + ..done(); + } + } + catch (ex) + { + // Send the server side error. + var errMsg = DC.stringToBytes(ex.toString()); + + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.GeneralFailure.index) + ..addUint16(errMsg.length) + ..addDC(errMsg) + ..done(); + } + } + + } + else if (_authPacket.command == IIPAuthPacketCommand.Action) + { + if (_authPacket.action == IIPAuthPacketAction.AuthenticateHash) + { + var remoteHash = _authPacket.challenge; + AsyncReply reply; + + try + { + if (session.remoteMethod == AuthenticationMethod.Credentials) + { + reply = server!.membership!.getPassword(session.remoteHeaders[IIPAuthPacketHeader.Username], + session.remoteHeaders[IIPAuthPacketHeader.Domain]); + } + else if (session.remoteMethod == AuthenticationMethod.Token) + { + reply = _server!.membership!.getToken(session.remoteHeaders[IIPAuthPacketHeader.TokenIndex], + session.remoteHeaders[IIPAuthPacketHeader.Domain]); + } + else + { + // Error + throw Exception("Unsupported authentication method"); + } + + reply.then((pw) + { + if (pw != null) + { + var localNonce = session.localHeaders[IIPAuthPacketHeader.Nonce]; + var remoteNonce = session.remoteHeaders[IIPAuthPacketHeader.Nonce]; + + + var hash = SHA256.compute((new BinaryList() + ..addDC(remoteNonce) + ..addDC(pw) + ..addDC(localNonce) + ).toDC()); + + if (hash.sequenceEqual(remoteHash)) + { + // send our hash + var localHash = SHA256.compute((new BinaryList() + ..addDC(localNonce) + ..addDC(pw) + ..addDC(remoteNonce) + ).toDC()); + + _sendParams() + ..addUint8(IIPAuthPacketAction.AuthenticateHash) + ..addUint8(IIPAuthPacketHashAlgorithm.SHA256) + ..addUint16(localHash.length) + ..addDC(localHash) + ..done(); + + _readyToEstablish = true; + } + else + { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.AccessDenied.index) + ..addUint16(13) + ..addString("Access Denied") + ..done(); + } + } + }); + } + catch (ex) + { + var errMsg = DC.stringToBytes(ex.toString()); + + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.GeneralFailure.index) + ..addUint16(errMsg.length) + ..addDC(errMsg) + ..done(); + } + } + else if (_authPacket.action == IIPAuthPacketAction.IAuthPlain) + { + var reference = _authPacket.reference; + var dataType = _authPacket.dataType!; + + var parsed = Codec.parse(data, dataType.offset, this, null, dataType); + + var value = parsed.reply.result; + + _server?.membership?.authorizePlain(session, reference, value) + .then((x) => _processAuthorization(x)); + + + } + else if (_authPacket.action == IIPAuthPacketAction.IAuthHashed) + { + var reference = _authPacket.reference; + var value = _authPacket.challenge!; + var algorithm = _authPacket.hashAlgorithm; + + _server?.membership?.authorizeHashed(session, reference, algorithm, value) + .then((x) => _processAuthorization(x)); + + } + else if (_authPacket.action == IIPAuthPacketAction.IAuthEncrypted) + { + var reference = _authPacket.reference; + var value = _authPacket.challenge!; + var algorithm = _authPacket.publicKeyAlgorithm; + + _server?.membership?.authorizeEncrypted(session, reference, algorithm, value) + .then((x) => _processAuthorization(x)); + } + else if (_authPacket.action == IIPAuthPacketAction.EstablishNewSession) + { + if (_readyToEstablish) + { + + if (_server?.membership == null) + { + _processAuthorization(null); + } + else + { + server?.membership?.authorize(session).then((x) + { + _processAuthorization(x); + }); + } + + } + else + { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.GeneralFailure.index) + ..addUint16(9) + ..addString("Not ready") + ..done(); + } + } + } + } + + _processAuthorization(AuthorizationResults? results) + { + if (results == null || results.response == AuthorizationResultsResponse.Success) + { + + var r = new Random(); + var n = new DC(32); + for (var i = 0; i < 32; i++) + n[i] = r.nextInt(255); + + session.id = n; + + _sendParams() + ..addUint8(IIPAuthPacketEvent.IndicationEstablished) + ..addUint8(n.length) + ..addDC(n) + ..done(); + + if (this.instance == null) + { + Warehouse.put(this.hashCode.toString().replaceAll("/", "_"), this, null, _server).then((x) + { + _ready = true; + _status = ConnectionStatus.Connected; + _openReply?.trigger(true); + _openReply = null; + emitArgs("ready", []); + + _server?.membership?.login(session); + _loginDate = DateTime.now(); + + }).error((x) + { + _openReply?.triggerError(x); + _openReply = null; + + }); + } + else + { + _ready = true; + _status = ConnectionStatus.Connected; + + _openReply?.trigger(true); + _openReply = null; + + emitArgs("ready", []); + + server?.membership?.login(session); + } + } + else if (results.response == AuthorizationResultsResponse.Failed) + { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.ChallengeFailed.index) + ..addUint16(21) + ..addString("Authentication failed") + ..done(); + } + else if (results.response == AuthorizationResultsResponse.Expired) + { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.Timeout.index) + ..addUint16(22) + ..addString("Authentication expired") + ..done(); + } + else if (results.response == AuthorizationResultsResponse.ServiceUnavailable) + { + _sendParams() + ..addUint8(IIPAuthPacketEvent.ErrorTerminate) + ..addUint8(ExceptionCode.GeneralFailure.index) + ..addUint16(19) + ..addString("Service unavailable") + ..done(); + } + else if (results.response == AuthorizationResultsResponse.IAuthPlain) + { + var args = + { + IIPAuthPacketIAuthHeader.Reference: results.reference, + IIPAuthPacketIAuthHeader.Destination: results.destination, + IIPAuthPacketIAuthHeader.Timeout: results.timeout, + IIPAuthPacketIAuthHeader.Clue: results.clue, + IIPAuthPacketIAuthHeader.RequiredFormat: results.requiredFormat, + }; + + _sendParams() + ..addUint8(IIPAuthPacketEvent.IAuthPlain) + ..addDC(Codec.compose(args, this)) + ..done(); + + } + else if (results.response == AuthorizationResultsResponse.IAuthHashed) + { + var args = + { + IIPAuthPacketIAuthHeader.Reference: results.reference, + IIPAuthPacketIAuthHeader.Destination: results.destination, + IIPAuthPacketIAuthHeader.Timeout: results.timeout, + IIPAuthPacketIAuthHeader.Clue: results.clue, + IIPAuthPacketIAuthHeader.RequiredFormat: results.requiredFormat, + }; + + _sendParams() + ..addUint8(IIPAuthPacketEvent.IAuthHashed) + ..addDC(Codec.compose(args, this)) + ..done(); + + } + else if (results.response == AuthorizationResultsResponse.IAuthEncrypted) + { + var args = + { + IIPAuthPacketIAuthHeader.Destination: results.destination, + IIPAuthPacketIAuthHeader.Timeout: results.timeout, + IIPAuthPacketIAuthHeader.Clue: results.clue, + IIPAuthPacketIAuthHeader.RequiredFormat: results.requiredFormat, + }; + + _sendParams() + ..addUint8(IIPAuthPacketEvent.IAuthEncrypted) + ..addDC(Codec.compose(args, this)) + ..done(); + } + } + + @override void dataReceived(NetworkBuffer data) { // print("dataReceived"); @@ -3160,8 +3722,9 @@ class DistributedConnection extends NetworkConnection with IStore { return; } - if (info.receivers != null && - this._session != null) if (!info.receivers!(this._session!)) return; + if (info.receivers != null) + if (!info.receivers!(this._session)) + return; if (info.resource.instance?.applicable(_session as Session, ActionType.ReceiveEvent, info.eventTemplate, info.issuer) == @@ -3175,7 +3738,6 @@ class DistributedConnection extends NetworkConnection with IStore { ..done(); } - ConnectionStatus status = ConnectionStatus.Closed; @override getProperty(String name) => null; diff --git a/lib/src/Net/IIP/DistributedServer.dart b/lib/src/Net/IIP/DistributedServer.dart index d72385f..573a882 100644 --- a/lib/src/Net/IIP/DistributedServer.dart +++ b/lib/src/Net/IIP/DistributedServer.dart @@ -1,3 +1,5 @@ +import 'package:esiur/src/Security/Membership/IMembership.dart'; + import '../../Resource/Template/TemplateDescriber.dart'; import '../../Resource/IResource.dart'; @@ -31,4 +33,6 @@ class DistributedServer extends IResource { @override TemplateDescriber get template => TemplateDescriber("Esiur.Net.IIP.DistributedServer"); + + IMembership? membership; } diff --git a/lib/src/Net/INetworkReceiver.dart b/lib/src/Net/INetworkReceiver.dart index a51b5e7..057f898 100644 --- a/lib/src/Net/INetworkReceiver.dart +++ b/lib/src/Net/INetworkReceiver.dart @@ -1,6 +1,6 @@ import 'NetworkBuffer.dart'; -abstract mixin class INetworkReceiver + abstract class INetworkReceiver { void networkClose(T sender); void networkReceive(T sender, NetworkBuffer buffer); diff --git a/lib/src/Net/Packets/IIPAuthPacket.dart b/lib/src/Net/Packets/IIPAuthPacket.dart index 39817ae..49cdbed 100644 --- a/lib/src/Net/Packets/IIPAuthPacket.dart +++ b/lib/src/Net/Packets/IIPAuthPacket.dart @@ -21,51 +21,38 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +import 'package:esiur/esiur.dart'; + import '../../Data/DC.dart'; import 'IIPAuthPacketAction.dart'; import 'IIPAuthPacketCommand.dart'; import '../../Security/Authority/AuthenticationMethod.dart'; +import 'IIPAuthPacketEvent.dart'; class IIPAuthPacket { int command = 0; + int initialization = 0; + int acknowledgement = 0; int action = 0; - - int errorCode = 0; - String errorMessage = ""; + int event = 0; AuthenticationMethod localMethod = AuthenticationMethod.None; - - DC? sourceInfo; - - DC? hash; - - DC? sessionId; - AuthenticationMethod remoteMethod = AuthenticationMethod.None; - String? domain; + int errorCode = 0; + String message = ""; - int certificateId = 0; - - String? localUsername; - - String? remoteUsername; - - DC? localPassword; - - DC? remotePassword; - - DC? localToken; - - DC? remoteToken; + int publicKeyAlgorithm = 0; + int hashAlgorithm = 0; + DC? certificate; + DC? challenge; DC? asymetricEncryptionKey; + DC? sessionId; - DC? localNonce; + TransmissionType? dataType; - DC? remoteNonce; - - int remoteTokenIndex = 0; + int reference = 0; int _dataLengthNeeded = 0; @@ -82,157 +69,262 @@ class IIPAuthPacket { } int parse(DC data, int offset, int ends) { + var oOffset = offset; - if (_notEnough(offset, ends, 1)) return -_dataLengthNeeded; + if (_notEnough(offset, ends, 1)) + return -_dataLengthNeeded; command = (data[offset] >> 6); - if (command == IIPAuthPacketCommand.Action) { - action = (data[offset++] & 0x3f); + if (command == IIPAuthPacketCommand.Initialize) { - if (action == IIPAuthPacketAction.AuthenticateHash) { - if (_notEnough(offset, ends, 32)) return -_dataLengthNeeded; + localMethod = AuthenticationMethod.values[((data[offset] >> 4) & 0x3)]; + remoteMethod = AuthenticationMethod.values[((data[offset] >> 2) & 0x3)]; - hash = data.clip(offset, 32); + initialization = (data[offset++] & 0xFC); // remove last two reserved LSBs - //var hash = new byte[32]; - //Buffer.BlockCopy(data, (int)offset, hash, 0, 32); - //Hash = hash; + if (_notEnough(offset, ends, 1)) + return -_dataLengthNeeded; - offset += 32; - } else if (action == IIPAuthPacketAction.NewConnection) { - if (_notEnough(offset, ends, 2)) return -_dataLengthNeeded; + var parsed = TransmissionType.parse(data, offset, ends); - var length = data.getUint16(offset); + if (parsed.type == null) + return -parsed.size; - offset += 2; + dataType = parsed.type; + offset += parsed.size; - if (_notEnough(offset, ends, length)) return -_dataLengthNeeded; - - sourceInfo = data.clip(offset, length); - - //var sourceInfo = new byte[length]; - //Buffer.BlockCopy(data, (int)offset, sourceInfo, 0, length); - //SourceInfo = sourceInfo; - - offset += 32; - } else if (action == IIPAuthPacketAction.ResumeConnection || - action == IIPAuthPacketAction.ConnectionEstablished) { - //var sessionId = new byte[32]; - - if (_notEnough(offset, ends, 32)) return -_dataLengthNeeded; - - sessionId = data.clip(offset, 32); - - //Buffer.BlockCopy(data, (int)offset, sessionId, 0, 32); - //SessionId = sessionId; - - offset += 32; - } - } else if (command == IIPAuthPacketCommand.Declare) { - remoteMethod = AuthenticationMethod.values[((data[offset] >> 4) & 0x3)]; - localMethod = AuthenticationMethod.values[((data[offset] >> 2) & 0x3)]; - var encrypt = ((data[offset++] & 0x2) == 0x2); - - if (_notEnough(offset, ends, 1)) return -_dataLengthNeeded; - - var domainLength = data[offset++]; - if (_notEnough(offset, ends, domainLength)) return -_dataLengthNeeded; - - var domain = data.getString(offset, domainLength); - - this.domain = domain; - - offset += domainLength; - - if (remoteMethod == AuthenticationMethod.Credentials) { - if (localMethod == AuthenticationMethod.None) { - if (_notEnough(offset, ends, 33)) return -_dataLengthNeeded; - - remoteNonce = data.clip(offset, 32); - - offset += 32; - - var length = data[offset++]; - - if (_notEnough(offset, ends, length)) return -_dataLengthNeeded; - - remoteUsername = data.getString(offset, length); - - offset += length; - } - } else if (remoteMethod == AuthenticationMethod.Token) { - if (localMethod == AuthenticationMethod.None) { - if (_notEnough(offset, ends, 40)) return -_dataLengthNeeded; - - remoteNonce = data.clip(offset, 32); - - offset += 32; - - remoteTokenIndex = data.getUint64(offset); - offset += 8; - } - } - - if (encrypt) { - if (_notEnough(offset, ends, 2)) return -_dataLengthNeeded; - - var keyLength = data.getUint16(offset); - - offset += 2; - - if (_notEnough(offset, ends, keyLength)) return -_dataLengthNeeded; - - asymetricEncryptionKey = data.clip(offset, keyLength); - - offset += keyLength; - } } else if (command == IIPAuthPacketCommand.Acknowledge) { - remoteMethod = AuthenticationMethod.values[((data[offset] >> 4) & 0x3)]; - localMethod = AuthenticationMethod.values[((data[offset] >> 2) & 0x3)]; - var encrypt = ((data[offset++] & 0x2) == 0x2); - if (remoteMethod == AuthenticationMethod.None) { - if (localMethod == AuthenticationMethod.None) { - // do nothing - } - } else if (remoteMethod == AuthenticationMethod.Credentials || - remoteMethod == AuthenticationMethod.Token) { - if (localMethod == AuthenticationMethod.None) { - if (_notEnough(offset, ends, 32)) return -_dataLengthNeeded; + localMethod = AuthenticationMethod.values[((data[offset] >> 4) & 0x3)]; + remoteMethod = AuthenticationMethod.values[((data[offset] >> 2) & 0x3)]; - remoteNonce = data.clip(offset, 32); - offset += 32; - } - } + acknowledgement = + (data[offset++] & 0xFC); // remove last two reserved LSBs - if (encrypt) { - if (_notEnough(offset, ends, 2)) return -_dataLengthNeeded; + if (_notEnough(offset, ends, 1)) + return -_dataLengthNeeded; + + var parsed = TransmissionType.parse(data, offset, ends); + + if (parsed.type == null) + return -parsed.size; + + dataType = parsed.type; + offset += parsed.size; + + } else if (command == IIPAuthPacketCommand.Action) { + + action = (data[offset++]); + if (action == IIPAuthPacketAction.AuthenticateHash || + action == IIPAuthPacketAction.AuthenticatePublicHash || + action == IIPAuthPacketAction.AuthenticatePrivateHash || + action == IIPAuthPacketAction.AuthenticatePublicPrivateHash) { + + if (_notEnough(offset, ends, 3)) + return -_dataLengthNeeded; + + hashAlgorithm = data[offset++]; + + var hashLength = data.getUint16(offset); + offset += 2; + + if (_notEnough(offset, ends, hashLength)) + return -_dataLengthNeeded; + + challenge = data.clip(offset, hashLength); + offset += hashLength; + + } else if (action == IIPAuthPacketAction.AuthenticatePrivateHashCert || + action == IIPAuthPacketAction.AuthenticatePublicPrivateHashCert) { + + if (_notEnough(offset, ends, 3)) + return -_dataLengthNeeded; + + hashAlgorithm = data[offset++]; + + var hashLength = data.getUint16(offset); + offset += 2; + + if (_notEnough(offset, ends, hashLength)) + return -_dataLengthNeeded; + + challenge = data.clip(offset, hashLength); + offset += hashLength; + + if (_notEnough(offset, ends, 2)) + return -_dataLengthNeeded; + + var certLength = data.getUint16(offset); + offset += 2; + + if (_notEnough(offset, ends, certLength)) + return -_dataLengthNeeded; + + certificate = data.clip(offset, certLength); + + offset += certLength; + + } else if (action == IIPAuthPacketAction.IAuthPlain) { + + if (_notEnough(offset, ends, 5)) + return -_dataLengthNeeded; + + reference = data.getUint32(offset); + offset += 4; + + var parsed = TransmissionType.parse(data, offset, ends); + + if (parsed.type == null) + return -parsed.size; + + dataType = parsed.type; + offset += parsed.size; + + } else if (action == IIPAuthPacketAction.IAuthHashed) { + + if (_notEnough(offset, ends, 7)) + return -_dataLengthNeeded; + + reference = data.getUint32(offset); + offset += 4; + + hashAlgorithm = data[offset++]; + + var cl = data.getUint16(offset); + offset += 2; + + if (_notEnough(offset, ends, cl)) + return -_dataLengthNeeded; + + challenge = data.clip(offset, cl); + + offset += cl; + + } else if (action == IIPAuthPacketAction.IAuthEncrypted) { + + if (_notEnough(offset, ends, 7)) + return -_dataLengthNeeded; + + reference = data.getUint32(offset); + offset += 4; + + publicKeyAlgorithm = data[offset++]; + + var cl = data.getUint16(offset); + offset += 2; + + if (_notEnough(offset, ends, cl)) + return -_dataLengthNeeded; + + challenge = data.clip(offset, cl); + + offset += cl; + + } else if (action == IIPAuthPacketAction.EstablishNewSession) { + // Nothing here + } else if (action == IIPAuthPacketAction.EstablishResumeSession) { + + if (_notEnough(offset, ends, 1)) + return -_dataLengthNeeded; + + var sessionLength = data[offset++]; + + if (_notEnough(offset, ends, sessionLength)) + return -_dataLengthNeeded; + + sessionId = data.clip(offset, sessionLength); + + offset += sessionLength; + + } else if (action == IIPAuthPacketAction.EncryptKeyExchange) { + + if (_notEnough(offset, ends, 2)) + return -_dataLengthNeeded; var keyLength = data.getUint16(offset); offset += 2; - if (_notEnough(offset, ends, keyLength)) return -_dataLengthNeeded; + if (_notEnough(offset, ends, keyLength)) + return -_dataLengthNeeded; asymetricEncryptionKey = data.clip(offset, keyLength); offset += keyLength; + + } else if (action == IIPAuthPacketAction.RegisterEndToEndKey || + action == IIPAuthPacketAction.RegisterHomomorphic) { + + if (_notEnough(offset, ends, 3)) + return -_dataLengthNeeded; + + publicKeyAlgorithm = data[offset++]; + + var keyLength = data.getUint16(offset); + + offset += 2; + + if (_notEnough(offset, ends, keyLength)) + return -_dataLengthNeeded; + + asymetricEncryptionKey = data.clip(offset, keyLength); + + offset += keyLength; + } - } else if (command == IIPAuthPacketCommand.Error) { - if (_notEnough(offset, ends, 4)) return -_dataLengthNeeded; + } else if (command == IIPAuthPacketCommand.Event) { - offset++; - errorCode = data[offset++]; + event = data[offset++]; - var cl = data.getUint16(offset); - offset += 2; + if (event == IIPAuthPacketEvent.ErrorTerminate || + event == IIPAuthPacketEvent.ErrorMustEncrypt || + event == IIPAuthPacketEvent.ErrorRetry) { - if (_notEnough(offset, ends, cl)) return -_dataLengthNeeded; + if (_notEnough(offset, ends, 3)) + return -_dataLengthNeeded; - errorMessage = data.getString(offset, cl); - offset += cl; + errorCode = data[offset++]; + var msgLength = data.getUint16(offset); + offset += 2; + + if (_notEnough(offset, ends, msgLength)) + return -_dataLengthNeeded; + + message = data.getString(offset, msgLength); + + offset += msgLength; + + } else if (event == IIPAuthPacketEvent.IndicationEstablished) { + + if (_notEnough(offset, ends, 1)) + return -_dataLengthNeeded; + + var sessionLength = data[offset++]; + + if (_notEnough(offset, ends, sessionLength)) + return -_dataLengthNeeded; + + sessionId = data.clip(offset, sessionLength); + + offset += sessionLength; + + } else if (event == IIPAuthPacketEvent.IAuthPlain || + event == IIPAuthPacketEvent.IAuthHashed || + event == IIPAuthPacketEvent.IAuthEncrypted) { + + if (_notEnough(offset, ends, 1)) + return -_dataLengthNeeded; + + var parsed = TransmissionType.parse(data, offset, ends); + + if (parsed.type == null) + return -parsed.size; + + dataType = parsed.type; + offset += parsed.size; + } } return offset - oOffset; diff --git a/lib/src/Net/Packets/IIPAuthPacketAcknowledge.dart b/lib/src/Net/Packets/IIPAuthPacketAcknowledge.dart new file mode 100644 index 0000000..505f44b --- /dev/null +++ b/lib/src/Net/Packets/IIPAuthPacketAcknowledge.dart @@ -0,0 +1,19 @@ +class IIPAuthPacketAcknowledge +{ + static const int NoAuthNoAuth = 0x40; // 0b01000000, + static const int NoAuthCredentials = 0x44; // 0b01000100, + static const int NoAuthToken = 0x48; //0b01001000, + static const int NoAuthCertificate = 0x4c; //0b01001100, + static const int CredentialsNoAuth = 0x50; //0b01010000, + static const int CredentialsCredentials = 0x54; //0b01010100, + static const int CredentialsToken = 0x58; //0b01011000, + static const int CredentialsCertificate = 0x5c; //0b01011100, + static const int TokenNoAuth = 0x60; //0b01100000, + static const int TokenCredentials = 0x64; //0b01100100, + static const int TokenToken = 0x68; //0b01101000, + static const int TokenCertificate = 0x6c; //0b01101100, + static const int CertificateNoAuth = 0x70; //0b01110000, + static const int CertificateCredentials = 0x74; //0b01110100, + static const int CertificateToken = 0x78; //0b01111000, + static const int CertificateCertificate = 0x7c; // 0b01111100, +} \ No newline at end of file diff --git a/lib/src/Net/Packets/IIPAuthPacketAction.dart b/lib/src/Net/Packets/IIPAuthPacketAction.dart index 182df4e..2d6806b 100644 --- a/lib/src/Net/Packets/IIPAuthPacketAction.dart +++ b/lib/src/Net/Packets/IIPAuthPacketAction.dart @@ -1,16 +1,27 @@ class IIPAuthPacketAction { - // Authenticate - static const int AuthenticateHash = 0; - - - //Challenge, - //CertificateRequest, - //CertificateReply, - //EstablishRequest, - //EstablishReply - static const int NewConnection = 0x20; static const int ResumeConnection = 0x21; static const int ConnectionEstablished = 0x28; + + static const int AuthenticateHash = 0x80; + static const int AuthenticatePublicHash = 0x81; + static const int AuthenticatePrivateHash = 0x82; + static const int AuthenticatePublicPrivateHash = 0x83; + + static const int AuthenticatePrivateHashCert = 0x88; + static const int AuthenticatePublicPrivateHashCert = 0x89; + + static const int IAuthPlain = 0x90; + static const int IAuthHashed = 0x91; + static const int IAuthEncrypted = 0x92; + + + static const int EstablishNewSession = 0x98; + static const int EstablishResumeSession = 0x99; + + static const int EncryptKeyExchange = 0xA0; + + static const int RegisterEndToEndKey = 0xA8; + static const int RegisterHomomorphic = 0xA9; } \ No newline at end of file diff --git a/lib/src/Net/Packets/IIPAuthPacketCommand.dart b/lib/src/Net/Packets/IIPAuthPacketCommand.dart index f8dde7b..9f27e4c 100644 --- a/lib/src/Net/Packets/IIPAuthPacketCommand.dart +++ b/lib/src/Net/Packets/IIPAuthPacketCommand.dart @@ -1,7 +1,7 @@ class IIPAuthPacketCommand { - static const int Action = 0; - static const int Declare = 1; - static const int Acknowledge = 2; - static const int Error = 3; + static const int Initialize = 0x0; + static const int Acknowledge = 0x1; + static const int Action = 0x2; + static const int Event = 0x3; } \ No newline at end of file diff --git a/lib/src/Net/Packets/IIPAuthPacketEvent.dart b/lib/src/Net/Packets/IIPAuthPacketEvent.dart new file mode 100644 index 0000000..bb95871 --- /dev/null +++ b/lib/src/Net/Packets/IIPAuthPacketEvent.dart @@ -0,0 +1,12 @@ +class IIPAuthPacketEvent +{ + static const int ErrorTerminate = 0xC0; + static const int ErrorMustEncrypt = 0xC1; + static const int ErrorRetry = 0xC2; + + static const int IndicationEstablished = 0xC8; + + static const int IAuthPlain = 0xD0; + static const int IAuthHashed = 0xD1; + static const int IAuthEncrypted = 0xD2; +} \ No newline at end of file diff --git a/lib/src/Net/Packets/IIPAuthPacketHashAlgorithm.dart b/lib/src/Net/Packets/IIPAuthPacketHashAlgorithm.dart new file mode 100644 index 0000000..c8ecbc3 --- /dev/null +++ b/lib/src/Net/Packets/IIPAuthPacketHashAlgorithm.dart @@ -0,0 +1,6 @@ + +class IIPAuthPacketHashAlgorithm +{ + static int SHA256 = 0x0; + static int SHA3 = 0x1; +} \ No newline at end of file diff --git a/lib/src/Net/Packets/IIPAuthPacketHeader.dart b/lib/src/Net/Packets/IIPAuthPacketHeader.dart new file mode 100644 index 0000000..5897a55 --- /dev/null +++ b/lib/src/Net/Packets/IIPAuthPacketHeader.dart @@ -0,0 +1,25 @@ + +import '../../Data/IntType.dart'; + +class IIPAuthPacketHeader +{ + static UInt8 Version = UInt8(0); + static UInt8 Domain = UInt8(1); + static UInt8 SupportedAuthentications = UInt8(2); + static UInt8 SupportedHashAlgorithms = UInt8(3); + static UInt8 SupportedCiphers = UInt8(4); + static UInt8 SupportedCompression = UInt8(5); + static UInt8 SupportedPersonalAuth = UInt8(6); + static UInt8 Nonce = UInt8(7); + static UInt8 Username = UInt8(8); + static UInt8 TokenIndex = UInt8(9); + static UInt8 CertificateId = UInt8(10); + static UInt8 CachedCertificates = UInt8(11); + static UInt8 CipherType = UInt8(12); + static UInt8 CipherKey = UInt8(13); + static UInt8 SoftwareIdentity = UInt8(14); + static UInt8 Referrer = UInt8(15); + static UInt8 Time = UInt8(16); + static UInt8 Certificate = UInt8(17); + static UInt8 IPv4 = UInt8(18); +} \ No newline at end of file diff --git a/lib/src/Net/Packets/IIPAuthPacketIAuthDestination.dart b/lib/src/Net/Packets/IIPAuthPacketIAuthDestination.dart new file mode 100644 index 0000000..42d1a21 --- /dev/null +++ b/lib/src/Net/Packets/IIPAuthPacketIAuthDestination.dart @@ -0,0 +1,9 @@ +class IIPAuthPacketIAuthDestination +{ + static int Self = 0; + static int Device = 1; // logged in device + static int Email = 2; + static int SMS = 3; + static int App = 4; // Authenticator app + static int ThirdParty = 5; // usualy a second person +} \ No newline at end of file diff --git a/lib/src/Net/Packets/IIPAuthPacketIAuthFormat.dart b/lib/src/Net/Packets/IIPAuthPacketIAuthFormat.dart new file mode 100644 index 0000000..648716f --- /dev/null +++ b/lib/src/Net/Packets/IIPAuthPacketIAuthFormat.dart @@ -0,0 +1,12 @@ + +class IIPAuthPacketIAuthFormat +{ + static int None = 0; + static int Number = 1; + static int Text = 2; + static int LowercaseText = 3; + static int Choice = 4; + static int Photo = 5; + static int Signature = 6; + static int Fingerprint = 7; +} \ No newline at end of file diff --git a/lib/src/Net/Packets/IIPAuthPacketIAuthHeader.dart b/lib/src/Net/Packets/IIPAuthPacketIAuthHeader.dart new file mode 100644 index 0000000..d87cd1b --- /dev/null +++ b/lib/src/Net/Packets/IIPAuthPacketIAuthHeader.dart @@ -0,0 +1,11 @@ + +class IIPAuthPacketIAuthHeader +{ + static int Reference = 0; + static int Destination = 1; + static int Clue = 2; + static int RequiredFormat = 3; + static int ContentFormat = 4; + static int Content = 5; + static int Timeout = 6; +} \ No newline at end of file diff --git a/lib/src/Net/Packets/IIPAuthPacketInitialize.dart b/lib/src/Net/Packets/IIPAuthPacketInitialize.dart new file mode 100644 index 0000000..fc4469e --- /dev/null +++ b/lib/src/Net/Packets/IIPAuthPacketInitialize.dart @@ -0,0 +1,19 @@ +class IIPAuthPacketInitialize +{ + static int NoAuthNoAuth = 0x0; //0b00000000, + static int NoAuthCredentials = 0x4; //0b00000100, + static int NoAuthToken = 0x8; //0b00001000, + static int NoAuthCertificate = 0xC; //0b00001100, + static int CredentialsNoAuth = 0x10; //0b00010000, + static int CredentialsCredentials = 0x14; //0b00010100, + static int CredentialsToken = 0x18; //0b00011000, + static int CredentialsCertificate = 0x1c; //0b00011100, + static int TokenNoAuth = 0x20; //0b00100000, + static int TokenCredentials = 0x24; //0b00100100, + static int TokenToken = 0x28; //0b00101000, + static int TokenCertificate = 0x2c; //0b00101100, + static int CertificateNoAuth = 0x30; //0b00110000, + static int CertificateCredentials = 0x34; // 0b00110100, + static int CertificateToken = 0x38; //0b00111000, + static int CertificateCertificate = 0x3c; //0b00111100, +} \ No newline at end of file diff --git a/lib/src/Net/Packets/IIPAuthPacketPublicKeyAlgorithm.dart b/lib/src/Net/Packets/IIPAuthPacketPublicKeyAlgorithm.dart new file mode 100644 index 0000000..755ff1c --- /dev/null +++ b/lib/src/Net/Packets/IIPAuthPacketPublicKeyAlgorithm.dart @@ -0,0 +1,6 @@ + +class IIPAuthPacketPublicKeyAlgorithm +{ + static int RSA = 0; + static int CKKS = 1; +} \ No newline at end of file diff --git a/lib/src/Proxy/TemplateGenerator.dart b/lib/src/Proxy/TemplateGenerator.dart index 24f9a1b..d5ff68c 100644 --- a/lib/src/Proxy/TemplateGenerator.dart +++ b/lib/src/Proxy/TemplateGenerator.dart @@ -209,22 +209,22 @@ class TemplateGenerator { name = "double"; break; case RepresentationTypeIdentifier.Float32: - name = "double"; + name = "Float32"; break; case RepresentationTypeIdentifier.Float64: name = "double"; break; case RepresentationTypeIdentifier.Int16: - name = "int"; + name = "Int16"; break; case RepresentationTypeIdentifier.Int32: - name = "int"; + name = "Int32"; break; case RepresentationTypeIdentifier.Int64: name = "int"; break; case RepresentationTypeIdentifier.Int8: - name = "int"; + name = "Int8"; break; case RepresentationTypeIdentifier.String: name = "String"; @@ -233,16 +233,16 @@ class TemplateGenerator { name = "Map"; break; case RepresentationTypeIdentifier.UInt16: - name = "int"; + name = "UInt16"; break; case RepresentationTypeIdentifier.UInt32: - name = "int"; + name = "UInt32"; break; case RepresentationTypeIdentifier.UInt64: name = "int"; break; case RepresentationTypeIdentifier.UInt8: - name = "int"; + name = "UInt8"; break; case RepresentationTypeIdentifier.List: name = "List"; diff --git a/lib/src/Resource/FactoryEntry.dart b/lib/src/Resource/FactoryEntry.dart index 9dc801f..9220547 100644 --- a/lib/src/Resource/FactoryEntry.dart +++ b/lib/src/Resource/FactoryEntry.dart @@ -14,6 +14,7 @@ class FactoryEntry { final Function instanceCreator; final Function arrayCreator = () => []; final RepresentationType representationType; + final Function mapCreator = () => Map(); bool isMapKeySubType(Map map) { return map is Map; diff --git a/lib/src/Resource/IStore.dart b/lib/src/Resource/IStore.dart index 1a03f46..0690cb1 100644 --- a/lib/src/Resource/IStore.dart +++ b/lib/src/Resource/IStore.dart @@ -31,7 +31,7 @@ import '../Data/PropertyValue.dart'; // old // abstract class IStore extends IResource // new -abstract mixin class IStore implements IResource { +abstract class IStore implements IResource { AsyncReply get(String path); // AsyncReply retrieve(int iid); AsyncReply put(IResource resource); diff --git a/lib/src/Resource/Instance.dart b/lib/src/Resource/Instance.dart index 6ef5f32..9f1860c 100644 --- a/lib/src/Resource/Instance.dart +++ b/lib/src/Resource/Instance.dart @@ -482,7 +482,8 @@ class Instance extends IEventHandler { if (pi.parents.count == 0) break; - p = pi.parents.firstOrNull!; + p = pi.parents.first; + } return l.join("/"); diff --git a/lib/src/Resource/Warehouse.dart b/lib/src/Resource/Warehouse.dart index cfadfdc..dcd2ad3 100644 --- a/lib/src/Resource/Warehouse.dart +++ b/lib/src/Resource/Warehouse.dart @@ -510,6 +510,11 @@ class Warehouse { return _factory[type]?.arrayCreator.call() as List; } + static Map createMap(Type keyType) { + return _factory[keyType]?.mapCreator.call() as Map; + } + + static AsyncReply newResource(String name, [IStore? store = null, IResource? parent = null, @@ -759,6 +764,8 @@ class Warehouse { RepresentationType(RepresentationTypeIdentifier.Int64, false))) ..addAll(_getTypeEntries(() => false, RepresentationType(RepresentationTypeIdentifier.Bool, false))) + ..addAll(_getTypeEntries(() => 0.0, + RepresentationType(RepresentationTypeIdentifier.Float64, false))) ..addAll(_getTypeEntries(() => 0.0, RepresentationType(RepresentationTypeIdentifier.Float64, false))) ..addAll(_getTypeEntries(() => "", diff --git a/lib/src/Security/Authority/AuthenticationMethod.dart b/lib/src/Security/Authority/AuthenticationMethod.dart index 6e6010f..91c6ef0 100644 --- a/lib/src/Security/Authority/AuthenticationMethod.dart +++ b/lib/src/Security/Authority/AuthenticationMethod.dart @@ -9,8 +9,8 @@ enum AuthenticationMethod { - None, - Certificate, - Credentials, - Token, + None, + Credentials, + Token, + Certificate } \ No newline at end of file diff --git a/lib/src/Security/Authority/Session.dart b/lib/src/Security/Authority/Session.dart index f1aa183..487334b 100644 --- a/lib/src/Security/Authority/Session.dart +++ b/lib/src/Security/Authority/Session.dart @@ -21,32 +21,28 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + import '../../Data/DC.dart'; -import 'Authentication.dart'; +import '../../Data/IntType.dart'; import '../../Data/KeyList.dart'; +import 'AuthenticationMethod.dart'; +import 'AuthenticationType.dart'; class Session { - Authentication get localAuthentication => _localAuth; - Authentication get remoteAuthentication => _remoteAuth; - - // public Source Source { get; } DC? id; - - //DateTime get creation => _creation; - - //public DateTime Modification { get; } + DateTime creation = DateTime.now(); + DateTime modification = DateTime.now(); + final KeyList variables = new KeyList(); - //KeyList Variables { get; } - //IStore Store { get; } + Map localHeaders = Map(); + Map remoteHeaders = Map(); - //string id; - Authentication _localAuth, _remoteAuth; - + AuthenticationMethod localMethod = AuthenticationMethod.None; + AuthenticationMethod remoteMethod = AuthenticationMethod.None; - Session(this._localAuth, this._remoteAuth) - { - - } + AuthenticationType authenticationType = AuthenticationType.Host ; + + String? authorizedAccount; } diff --git a/lib/src/Security/Membership/AuthorizationResults.dart b/lib/src/Security/Membership/AuthorizationResults.dart new file mode 100644 index 0000000..2fc4cbc --- /dev/null +++ b/lib/src/Security/Membership/AuthorizationResults.dart @@ -0,0 +1,18 @@ +import '../../Net/Packets/IIPAuthPacketIAuthDestination.dart'; +import '../../Net/Packets/IIPAuthPacketIAuthFormat.dart'; +import 'AuthorizationResultsResponse.dart'; + +class AuthorizationResults + { + AuthorizationResultsResponse response = AuthorizationResultsResponse.Failed; + int destination = IIPAuthPacketIAuthDestination.Self; + int requiredFormat = IIPAuthPacketIAuthFormat.None ; + String clue = ""; + + int timeout = 0; // 0 means no timeout + int reference = 0; + + DateTime issue = DateTime.now(); + + //bool expired => timeout == 0 ? false : (DateTime.UtcNow - Issue).TotalSeconds > Timeout; + } diff --git a/lib/src/Security/Membership/AuthorizationResultsResponse.dart b/lib/src/Security/Membership/AuthorizationResultsResponse.dart new file mode 100644 index 0000000..2285e49 --- /dev/null +++ b/lib/src/Security/Membership/AuthorizationResultsResponse.dart @@ -0,0 +1,10 @@ + enum AuthorizationResultsResponse + { + Success, + Failed, + Expired, + ServiceUnavailable, + IAuthPlain, + IAuthHashed, + IAuthEncrypted + } \ No newline at end of file diff --git a/lib/src/Security/Membership/IMembership.dart b/lib/src/Security/Membership/IMembership.dart new file mode 100644 index 0000000..a9384a9 --- /dev/null +++ b/lib/src/Security/Membership/IMembership.dart @@ -0,0 +1,26 @@ +import '../../Core/AsyncReply.dart'; +import '../../Data/DC.dart'; +import '../../Net/Packets/IIPAuthPacketHashAlgorithm.dart'; +import '../Authority/Session.dart'; +import 'AuthorizationResults.dart'; + +abstract class IMembership +{ + //public event ResourceEventHandler Authorization; + + AsyncReply userExists(String username, String domain); + AsyncReply tokenExists(int tokenIndex, String domain); + + AsyncReply getPassword(String username, String domain); + AsyncReply getToken(String tokenIndex, String domain); + AsyncReply authorize(Session session); + AsyncReply authorizePlain(Session session, int reference, value); + AsyncReply authorizeHashed(Session session, int reference, int algorithm, DC value); + AsyncReply authorizeEncrypted(Session session, int reference, int algorithm, DC value); + + AsyncReply login(Session session); + AsyncReply logout(Session session); + bool get guestsAllowed; + + +} diff --git a/pubspec.yaml b/pubspec.yaml index 95e2275..f7ac319 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: esiur description: Distributed Object Framework. -version: 2.1.6 +version: 2.2.0 #author: Ahmed Zamil homepage: https://github.com/esiur/esiur-dart