commit a10b5f1a4532202f7ec786d854079c01e32a9f88 Author: Gregor Reitzenstein Date: Thu Apr 23 12:52:32 2020 +0200 Move schema to git diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6e92f57 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +tags diff --git a/api.capnp b/api.capnp new file mode 100644 index 0000000..d771276 --- /dev/null +++ b/api.capnp @@ -0,0 +1,137 @@ +# Copyright © 2020 Gregor Reitzenstein +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +@0xfd92ce9be2369b8e; + +interface Diflouroborane { + # Upon initial connection this is the interface a program is presented with, serving as the + # common point to access specific subsystems. Keep in mind that one can use pipelining to make this + # just as efficient as direct calls — e.g. access the authentication system and call + # `initializeAuthentication` on it in one roundtrip, provided one gets granted access to the + # Authentication subsystem (which in all fairness is a reasonable assumption) + + authentication @0 () -> ( auth :Authentication ); + # Then authentication subsystem handles authentication of clients and servers. Multiple + # authentication is possible, see the `Authentication` interface for details. + + permissions @1 () -> ( perm :Permissions ); + # Permission subsystem to manage permissions and systems underlying the authorization process + + machines @2 () -> ( mach :Machines ); + # Diflouroborane stores machine¹ information in an opaque internal database. This interface is + # the only stable process of modifying that information + + # TODO Capability transfer system, required for machine takeover, session resumption. +} + +struct UUID { + # UUID type used to identify machines. + # Since the exact value has no meaning the encoding rules are not too relevant, but it is + # paramount that you are consistent when encoding and decoding this type. + # + # Consider using this algorithm for assembling the 128-bit integer: + # (assuming ISO9899:2018 shifting & casting rules) + # uint128_t num = (uuid1 << 64) + uuid0; + # And then respectively this code for deconstructing it: + # uint64_t uuid0 = (uint64_t) num; + # uint64_t uuid1 = (uint64_t) (num >> 64); + + uuid0 @0 :UInt64; + uuid1 @1 :UInt64; +} + +interface Machines { + interface Manage { + setBlocked @0 ( blocked :Bool ) -> (); + # Block or Unblock the machine. A blocked machine can not be used. + + forceReturn @1 () -> (); + # Forcefully marking a machine as `returned` — i.e. not used. + } + + interface GiveBack { + # The only way of getting a `return` interface is by successfully calling `use`. This means + # only the user that marked a machine as `used` can return it again. (Baring force override) + giveback @0 () -> (); + } + + manage @0 ( uuid :UUID ) -> ( manage :Manage ); + + use @1 ( uuid :UUID ) -> ( giveback :GiveBack ); + # Use a machine, identified by its UUID. If the caller is allowed to and the machine is + # available to being used a `return` Capability will be returned — the person using a machine is + # after all the only person that can return the machine after use. +} + +interface Permissions { + # The permission system of FabAccess is a role-based access control (RBAC). + # This means that a principal is assigned to 0…N roles, and each role has 1…M permissions + # attached. A role can inherit from up to one other role meaning that roles are a set of + # cycle-free hierarchies. + getAllSubjects @0 () -> ( subjects :List(Text) ); + getAllObjects @1 () -> ( objects :List(Text) ); + getAllAction @2 () -> ( actions :List(Text) ); + getAllRoles @3 () -> ( roles :List(Text) ); + + removePolicy @4 ( p :List(Text) ) -> (); + addPolicy @5 ( p :List(Text) ) -> (); +} + +interface Authentication { + # List all SASL mechs the server is willing to use + availableMechanisms @0 () -> ( mechanisms :List(Text) ); + + # Start authentication using the given mechanism and optional initial data + initializeAuthentication @1 ( mechanism :Text, initialData :MaybeData ) + -> (response :StepResult ); + + getAuthzid @2 () -> ( authzid :Text ); + + struct StepResult { + union { + challenge @0 :Challenge; + outcome @1 :Outcome; + } + } + + struct MaybeData { + union { + some @0 :Data; + none @1 :Void; + } + } + + interface Challenge { + # Access the challenge data + read @0 () -> ( data :MaybeData ); + + respond @1 ( data :MaybeData ) + -> ( response :StepResult ); + } + + interface Outcome { + # Outcomes may contain additional data + read @0 () -> ( data :MaybeData ); + # The actual outcome. + value @1 () -> ( granted :Bool ); + } +} diff --git a/auth.capnp b/auth.capnp new file mode 100644 index 0000000..73ed978 --- /dev/null +++ b/auth.capnp @@ -0,0 +1,148 @@ +# Copyright © 2020 Gregor Reitzenstein +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +@0x81ac94a588025602; + +# ============================================================================== +# SASL Notes: +# +# - TLS and SASL security layers may not be both installed +# - A SASL security layer takes effect on the first octet following the outcome +# message in data being sent by the server and on the first octet sent after +# receipt of the outcome message in data being sent by the client. +# - Multiple authentication is currently NOT supported. +# ============================================================================== + +struct Message { + union { + discover @0 :Void; + # Message sent by a client to discover the list of available mechanisms. + # MUST NOT be sent during an ongoing authentication exchange. + + mechanisms @1 :List(Text); + # Message sent by a server as reply to a `Discover` message supplying + # the list of available mechanisms in the current context. + + request @2 :Request; # Authentication initiation sent by the client. + challenge @3 :Data; # Challenge sent by the server to the client + response @4 :Data; # Response sent by the client to the server + outcome @5 :Outcome; # Final outcome sent by the server + + abort @6 :Void; + # Abort the current exchange. This may be sent by both client and server + # at any point during the exchange. It MUST not be sent by a server + # after sending an outcome or by a client after receiving an outcome. + # A server receiving an abort after sending an outcome but before + # receiving any non-authentication message MUST respect the abort. + } +} + +struct Request { + mechanism @0 :Text; # The SASL mechanism name. + + initialResponse :union { + # A client may send some intial data when requesting an auth exchange. + # According to RFC4422 section 4.3a an implementation MUST to be able to + # distinguish between an empty initial reponse and no initial response. + + none @1 :Void; + # No initial reponse is being sent. + # The lowest numbered field in an union is the default value in Cap'n + # Proto. + + initial @2 :Data; + # A response may be any sequence of octets, including zero-length + # sequences and zero-valued octets. + } +} + +struct Outcome { + enum Result { + # Result code of the outcome + successful @0; + + unwilling @1; + # Generic "I'm sorry dave, I can't do that" response. MAY be set for any + # reason, all reasons or no reason at all. + # A server SHOULD set the `action` and `helpText` fields as appropiate. + # This code SHOULD only be sent if no other value is more fitting. + + invalidCredentials @2; + # The exchange was valid, but the provided credentials are invalid. This + # may mean that the authcid is not known to the server or that the + # password/certificate/key/etc. is not correct. + + unauthorized @3; + # The given authcid is not authorized to act as the requested authzid. + # This MAY also be returned for the cases `authzid == NULL` or + # `authzid == authcid`, for example because login is disabled for that + # authcid. + + malformedAuthZid @4; + # The provided authzid is malformed in some way. + + failed @5; + # A generic failed result. A server sending this result MUST set the + # `action` field to indicate whether this is a temporary or permanent + # failure and SHOULD set `helpText` to a human-readable error message. + } + enum Action { + # In case of a unsuccessful outcome, how should a client proceed? + + unset @0; + # Not a unsuccessful outcome, or the server doesn't know either. + # Also, the default value + + tryAgain @1; + # A client should just try again, potentially after prompting the user + # to enter their credentials again. + + wait @2; + # The client should wait and try again later. This MAY mean that + # whatever failure happened was temporary or the server is applying + # rate-limiting to the connection. + + permanent @3; + # The issue appears to the server as being permanent. Another try is + # very likely to return the exact same result. In most cases the user + # should notify the responsible system administrator. + } + + result @0 :Result; # Result code + + action @1 :Action; # Hints for the client how to proceed in case of an error + + helpText @2 :Text; # Human-readable further information in case of an error + + additionalData :union { + # Additional data that may be sent by the server to the client after a + # successful authentication exchange. + + none @3 :Void; + # No additional data is being sent. This MUST be set on unsuccessful + # outcomes. + + additional @4 :Data; + # Additional data may be any sequence of octets, including zero-length + # sequences and zero-value octets. + } +} diff --git a/connection.capnp b/connection.capnp new file mode 100644 index 0000000..8767836 --- /dev/null +++ b/connection.capnp @@ -0,0 +1,55 @@ +# Copyright © 2020 Gregor Reitzenstein +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +@0x9e1c146a27dcc635; + +using Auth = import "auth.capnp"; + +struct Message { + union { + hello @0 :Hello; + bye @1 :Bye; + starttls @2 :Void; + auth @3 :Auth.Message; + } +} + +struct Hello { + # Be nice and say hello to each other first + # A client sends this message to a server first thing + + major @0 :UInt32; # The major part of the API version + minor @1 :UInt32; # The minor part of the API version +} + +struct Bye { + # Tear down a connection nicely. + + enum Reason { + unset @0; # Just cause + + versionMismatch @1; + # The server doesn't implement a compatible version of the protocol + } + + reason @0 :Reason; +}