diff --git a/gql.go b/gql.go index 3cb51dc..21831d4 100644 --- a/gql.go +++ b/gql.go @@ -550,6 +550,26 @@ func ParseAuthB64(auth_base64 string, server_id ed25519.PrivateKey) (*ClientAuth }, nil } +func ValidateAuthorization(auth Authorization, valid time.Duration) error { + // Check that the time + valid < now + // Check that Signature is public_key + start signed with client_id + if auth.Start.Add(valid).Compare(time.Now()) != 1 { + return fmt.Errorf("authorization expired") + } + + time_bytes, err := auth.Start.MarshalBinary() + if err != nil { + return err + } + + digest := append(auth.Key, time_bytes...) + if ed25519.Verify(auth.Identity, digest, auth.Signature) != true { + return fmt.Errorf("verification failed") + } + + return nil +} + func NewResolveContext(ctx *Context, server *Node, gql_ext *GQLExt) (*ResolveContext, error) { return &ResolveContext{ ID: uuid.New(), diff --git a/gql_test.go b/gql_test.go index a137d7c..51bc2ee 100644 --- a/gql_test.go +++ b/gql_test.go @@ -35,6 +35,12 @@ func TestGQLAuth(t *testing.T) { auth, err := ParseAuthB64(auth_header, node_2.Key) fatalErr(t, err) + err = ValidateAuthorization(Authorization{ + AuthInfo: auth.AuthInfo, + Key: auth.Key.Public().(ed25519.PublicKey), + }, time.Second) + fatalErr(t, err) + ctx.Log.Logf("test", "AUTH: %+v", auth) } diff --git a/node.go b/node.go index d20edca..0244fc5 100644 --- a/node.go +++ b/node.go @@ -295,7 +295,17 @@ func nodeLoop(ctx *Context, node *Node) error { continue } - princ_id := KeyID(msg.Source) + var princ_id NodeID + if msg.Authorization == nil { + princ_id = KeyID(msg.Source) + } else { + err := ValidateAuthorization(*msg.Authorization, time.Hour) + if err != nil { + ctx.Log.Logf("node", "Authorization validation failed: %s", err) + continue + } + princ_id = KeyID(msg.Authorization.Identity) + } if princ_id != node.ID { pends, resp := node.Allows(ctx, princ_id, msg.Signal.Permission()) if resp == Deny {