From 4feb3be475ee4f15cb2478f132fef1e1c862cbb9 Mon Sep 17 00:00:00 2001 From: ale <ale@incal.net> Date: Sun, 17 Dec 2017 09:19:25 +0000 Subject: [PATCH] Update id/auth --- .../ai3/go-common/serverutil/tls.go | 7 +- vendor/git.autistici.org/id/auth/README.md | 100 ++++++++++++++++-- vendor/git.autistici.org/id/auth/protocol.go | 12 ++- vendor/vendor.json | 32 +++--- 4 files changed, 121 insertions(+), 30 deletions(-) diff --git a/vendor/git.autistici.org/ai3/go-common/serverutil/tls.go b/vendor/git.autistici.org/ai3/go-common/serverutil/tls.go index 926488f..7e5adff 100644 --- a/vendor/git.autistici.org/ai3/go-common/serverutil/tls.go +++ b/vendor/git.autistici.org/ai3/go-common/serverutil/tls.go @@ -60,6 +60,11 @@ func (c *TLSAuthConfig) match(req *http.Request) bool { return false } +var serverCiphers = []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, +} + // TLSServerConfig configures a TLS server with client authentication // and authorization based on the client X509 certificate. type TLSServerConfig struct { @@ -87,7 +92,7 @@ func (c *TLSServerConfig) TLSConfig() (*tls.Config, error) { Certificates: []tls.Certificate{cert}, ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: cas, - CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, + CipherSuites: serverCiphers, MinVersion: tls.VersionTLS12, PreferServerCipherSuites: true, } diff --git a/vendor/git.autistici.org/id/auth/README.md b/vendor/git.autistici.org/id/auth/README.md index 3bd5752..6130625 100644 --- a/vendor/git.autistici.org/id/auth/README.md +++ b/vendor/git.autistici.org/id/auth/README.md @@ -40,10 +40,8 @@ The authentication server data model is based on the concept of a in LDAP, but it has to be told the specific details of how to find them and how to map the information there to what it needs. - # Configuration - The behavior of auth-server can be configured with a YAML file. The YAML file should contain a dictionary with the following attributes: @@ -121,6 +119,15 @@ method, U2F support is currently missing. ## LDAP Backend The *ldap* backend will look up user information in a LDAP database. +It needs some parameters to be passed in the top-level *ldap_config* +dictionary: + +* `uri` of the LDAP server (like *ldapi:///var/run/ldap/ldapi*) +* `bind_dn` is the DN to bind with +* `bind_pw_file` points at a file containing the bind password + +The *ldap* backend will currently always attempt to bind on every +connection. ### Query definition @@ -173,14 +180,85 @@ App-specific passwords should be encoded as colon-separated strings: The password should be encrypted. The comment is a free-form string set by the user to tell the various credentials apart. -## OTP implementation - -The authentication server uses a very simple implementation of -time-based OTP (TOTP), supporting a single secret per user and without -any fancy features such as emergency tokens etc. The reason for this -is that TOTP authentication requires just plain read-only access to -the user database, while counter-based authentication with proper -token revocation is a read-write, locked operation which is more -difficult to perform on a LDAP backend. +# Usage + +The *auth-server* runs on a local UNIX socket. You can use UNIX +permissions to control who has access to this socket. The Debian +package makes it group-readable to the *auth-server* group, so you can +add specific users to it easily. + +The daemon can run either standalone or be socket-activated by +systemd, which is what the Debian package does. + +## Wire protocol + +The rationale behind the wire protocol ("why not http?") is twofold: +first, we wanted strict access control, and that's more easily done +with UNIX permissions, so UNIX sockets were chosen. Then, the protocol +should be able to transfer data maps, and it must be trivial to +implement (and verify) in C, Go and Python. Furthermore, it should +minimize external dependencies. + +The protocol is line-based: multiple authentication requests can be +sent over the same connection, but every request must wait for a +response (i.e. no pipelining). Commands are single words, and can be +followed by a space and an attribute/value map. The responses are +simply attribute/value maps. + +Attribute maps should have the following characteristics: + +* maps can't be nested, they are simple key/value sets where both keys + and values are strings +* keys can't contain '=' characters + +They are encoded using the following algorithm: + +* if this is not the first attribute/value pair, add a space character +* add the key string +* add the '=' character +* if the value contains a non-printable character or a double quote: + * add the base64-encoded value +* if it does not: + * add a '"' character, then the value, then another '"' character. + +## API + +There is only one command: `auth`, which must be followed by the +authentication request. Parameters for an authentication request are: + +* `service`: the service requesting the authentication +* `username`: name of the user to authenticate +* `password`: password (cleartext) provided by the user +* `otp` (optional): TOTP-based 2FA token +* `u2f_app_id` (optional): U2F AppID +* `u2f_response` (optional): U2F response object + * `key_handle` + * `signature_data` + * `client_data` +* `device` (optional): information about the client device + * `id`: a unique ID, specific to this device + * `remote_addr`: remote IP address (will be minimized) + * `remote_zone`: remote zone (country-level IP aggregation) + * `browser`: browser name + * `os`: client OS + * `user_agent`: client User-Agent string + * `mobile`: boolean variable indicating a mobile device + +Responses will contain the following attributes: + +* `status`: status of the request, one of *ok*, + *insufficient_credentials* or *error* +* `2fa_method`: if *status* is *insufficient_credentials*, one of + *otp* or *u2f* indicating which 2FA method should be used for the + next request +* `u2f_req`: when *2fa_method* is *u2f*, this field will contain a U2F + SignResponse object: + * `version` + * `challenge` + * `registered_keys`: a list of registered keys +* `user`: when *status* is *ok* (the authentication has been + successful), this dictionary will contain user information: + * `email`: email of this user + * `groups`: groups the user is a member of. diff --git a/vendor/git.autistici.org/id/auth/protocol.go b/vendor/git.autistici.org/id/auth/protocol.go index ff7585e..ea41d3b 100644 --- a/vendor/git.autistici.org/id/auth/protocol.go +++ b/vendor/git.autistici.org/id/auth/protocol.go @@ -90,9 +90,11 @@ func (r *Request) DecodeFromMap(m map[string]string, prefix string) { r.DeviceInfo = decodeDeviceInfoFromMap(m, prefix+"device.") } -// UserInfo contains optional user information. +// UserInfo contains optional user information that may be useful to +// authentication endpoints. type UserInfo struct { Email string + Shard string Groups []string } @@ -100,13 +102,19 @@ func (u *UserInfo) EncodeToMap(m map[string]string, prefix string) { if u.Email != "" { m[prefix+"email"] = u.Email } + if u.Shard != "" { + m[prefix+"shard"] = u.Shard + } for i, g := range u.Groups { m[fmt.Sprintf("%sgroup.%d.", prefix, i)] = g } } func decodeUserInfoFromMap(m map[string]string, prefix string) *UserInfo { - u := UserInfo{Email: m[prefix+"email"]} + u := UserInfo{ + Email: m[prefix+"email"], + Shard: m[prefix+"shard"], + } i := 0 for { s, ok := m[fmt.Sprintf("%sgroup.%d.", prefix, i)] diff --git a/vendor/vendor.json b/vendor/vendor.json index 62f9486..87be133 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -5,44 +5,44 @@ { "checksumSHA1": "raJx5BjBbVQG0ylGSjPpi+JvqjU=", "path": "git.autistici.org/ai3/go-common", - "revision": "cd9ee1e6cc35b08a350d3dcb1b331750b363a82d", - "revisionTime": "2017-12-14T07:42:45Z" + "revision": "8cedcb1d73128f5566216cb3e39ad1ccea318213", + "revisionTime": "2017-12-16T15:39:23Z" }, { "checksumSHA1": "2X2UMundICtpGTb8pTdBk7PCKss=", "path": "git.autistici.org/ai3/go-common/clientutil", - "revision": "cd9ee1e6cc35b08a350d3dcb1b331750b363a82d", - "revisionTime": "2017-12-14T07:42:45Z" + "revision": "8cedcb1d73128f5566216cb3e39ad1ccea318213", + "revisionTime": "2017-12-16T15:39:23Z" }, { - "checksumSHA1": "g6I5506EXkjQetiXSYbVTypDnDM=", + "checksumSHA1": "wY0SM35qAhX3P2IZzDnYa068cPw=", "path": "git.autistici.org/ai3/go-common/serverutil", - "revision": "cd9ee1e6cc35b08a350d3dcb1b331750b363a82d", - "revisionTime": "2017-12-14T07:42:45Z" + "revision": "8cedcb1d73128f5566216cb3e39ad1ccea318213", + "revisionTime": "2017-12-16T15:39:23Z" }, { - "checksumSHA1": "Br4iXxLFs+Yp7doAZQUccQA/su4=", + "checksumSHA1": "C1BVHHj8iBgBN5EWr3ucsGoEzew=", "path": "git.autistici.org/id/auth", - "revision": "ddba7d73598682b17e4683f5a3873f12e158c679", - "revisionTime": "2017-12-13T22:22:39Z" + "revision": "1ac213f96bd3ab25b3ad98729831ca28eb8e1784", + "revisionTime": "2017-12-17T09:15:51Z" }, { "checksumSHA1": "48njEQBB73cV6tTPBEOnzSVRjeA=", "path": "git.autistici.org/id/auth/client", - "revision": "ddba7d73598682b17e4683f5a3873f12e158c679", - "revisionTime": "2017-12-13T22:22:39Z" + "revision": "1ac213f96bd3ab25b3ad98729831ca28eb8e1784", + "revisionTime": "2017-12-17T09:15:51Z" }, { "checksumSHA1": "3alRLG3a43ORlVZyfQc/JsT0KtI=", "path": "git.autistici.org/id/keystore", - "revision": "e7fb4821845b47ce2e372e384b49f4b5216bba93", - "revisionTime": "2017-12-09T17:36:20Z" + "revision": "b09f1210471f6a60402e8ced4783be3889a4074f", + "revisionTime": "2017-12-15T13:50:57Z" }, { "checksumSHA1": "HGK52MX+2CEKVzb9I5y1BfgDkWQ=", "path": "git.autistici.org/id/keystore/client", - "revision": "e7fb4821845b47ce2e372e384b49f4b5216bba93", - "revisionTime": "2017-12-09T17:36:20Z" + "revision": "b09f1210471f6a60402e8ced4783be3889a4074f", + "revisionTime": "2017-12-15T13:50:57Z" }, { "checksumSHA1": "usT4LCSQItkFvFOQT7cBlkCuGaE=", -- GitLab