1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef REMOTING_PROTOCOL_AUTHENTICATOR_H_
6 #define REMOTING_PROTOCOL_AUTHENTICATOR_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/callback_forward.h"
12 
13 namespace jingle_xmpp {
14 class XmlElement;
15 }  // namespace jingle_xmpp
16 
17 namespace remoting {
18 namespace protocol {
19 
20 class Authenticator;
21 class ChannelAuthenticator;
22 
23 // Authenticator is an abstract interface for authentication protocol
24 // implementations. Different implementations of this interface may be used on
25 // each side of the connection depending of type of the auth protocol. Client
26 // and host will repeatedly call their Authenticators and deliver the messages
27 // they generate, until successful authentication is reported.
28 //
29 // Authenticator may exchange multiple messages before session is authenticated.
30 // Each message sent/received by an Authenticator is delivered either in a
31 // session description inside session-initiate and session-accept messages or in
32 // a session-info message. Session-info messages are used only if authenticators
33 // need to exchange more than one message.
34 class Authenticator {
35  public:
36   // Allowed state transitions:
37   // When ProcessMessage() is called:
38   //    WAITING_MESSAGE -> MESSAGE_READY
39   //    WAITING_MESSAGE -> ACCEPTED
40   //    WAITING_MESSAGE -> REJECTED
41   //    WAITING_MESSAGE -> PROCESSING_MESSAGE
42   // After asynchronous message processing finishes:
43   //    PROCESSING_MESSAGE -> MESSAGE_READY
44   //    PROCESSING_MESSAGE -> ACCEPTED
45   //    PROCESSING_MESSAGE -> REJECTED
46   // When GetNextMessage() is called:
47   //    MESSAGE_READY -> WAITING_MESSAGE
48   //    MESSAGE_READY -> ACCEPTED
49   enum State {
50     // Waiting for the next message from the peer.
51     WAITING_MESSAGE,
52 
53     // Next message is ready to be sent to the peer.
54     MESSAGE_READY,
55 
56     // Session is authenticated successfully.
57     ACCEPTED,
58 
59     // Session is rejected.
60     REJECTED,
61 
62     // Asynchronously processing the last message from the peer.
63     PROCESSING_MESSAGE,
64   };
65 
66   enum RejectionReason {
67     // The account credentials were not valid (i.e. incorrect PIN).
68     INVALID_CREDENTIALS,
69 
70     // The client JID was not valid (i.e. violated a policy or was malformed).
71     INVALID_ACCOUNT,
72 
73     // Generic error used when something goes wrong establishing a session.
74     PROTOCOL_ERROR,
75 
76     // Session was rejected by the user (i.e. via the confirmation dialog).
77     REJECTED_BY_USER,
78 
79     // Multiple, valid connection requests were received for the same session.
80     TOO_MANY_CONNECTIONS,
81   };
82 
83   // Callback used for layered Authenticator implementations, particularly
84   // third-party and pairing authenticators. They use this callback to create
85   // base SPAKE2 authenticators.
86   typedef base::RepeatingCallback<std::unique_ptr<Authenticator>(
87       const std::string& shared_secret,
88       Authenticator::State initial_state)>
89       CreateBaseAuthenticatorCallback;
90 
91   // Returns true if |message| is an Authenticator message.
92   static bool IsAuthenticatorMessage(const jingle_xmpp::XmlElement* message);
93 
94   // Creates an empty Authenticator message, owned by the caller.
95   static std::unique_ptr<jingle_xmpp::XmlElement> CreateEmptyAuthenticatorMessage();
96 
97   // Finds Authenticator message among child elements of |message|, or
98   // returns nullptr otherwise.
99   static const jingle_xmpp::XmlElement* FindAuthenticatorMessage(
100       const jingle_xmpp::XmlElement* message);
101 
Authenticator()102   Authenticator() {}
~Authenticator()103   virtual ~Authenticator() {}
104 
105   // Returns current state of the authenticator.
106   virtual State state() const = 0;
107 
108   // Returns whether authentication has started. The chromoting host uses this
109   // method to start the back off process to prevent malicious clients from
110   // guessing the PIN by spamming the host with auth requests.
111   virtual bool started() const = 0;
112 
113   // Returns rejection reason. Can be called only when in REJECTED state.
114   virtual RejectionReason rejection_reason() const = 0;
115 
116   // Called in response to incoming message received from the peer.
117   // Should only be called when in WAITING_MESSAGE state. Caller retains
118   // ownership of |message|. |resume_callback| will be called when processing is
119   // finished. The implementation must guarantee that |resume_callback| is not
120   // called after the Authenticator is destroyed.
121   virtual void ProcessMessage(const jingle_xmpp::XmlElement* message,
122                               base::OnceClosure resume_callback) = 0;
123 
124   // Must be called when in MESSAGE_READY state. Returns next
125   // authentication message that needs to be sent to the peer.
126   virtual std::unique_ptr<jingle_xmpp::XmlElement> GetNextMessage() = 0;
127 
128   // Returns the auth key received as result of the authentication handshake.
129   virtual const std::string& GetAuthKey() const = 0;
130 
131   // Creates new authenticator for a channel. Can be called only in
132   // the ACCEPTED state.
133   virtual std::unique_ptr<ChannelAuthenticator> CreateChannelAuthenticator()
134       const = 0;
135 };
136 
137 // Factory for Authenticator instances.
138 class AuthenticatorFactory {
139  public:
AuthenticatorFactory()140   AuthenticatorFactory() {}
~AuthenticatorFactory()141   virtual ~AuthenticatorFactory() {}
142 
143   // Called when session-initiate stanza is received to create
144   // authenticator for the new session. |first_message| specifies
145   // authentication part of the session-initiate stanza so that
146   // appropriate type of Authenticator can be chosen for the session
147   // (useful when multiple authenticators are supported). Returns nullptr
148   // if the |first_message| is invalid and the session should be
149   // rejected. ProcessMessage() should be called with |first_message|
150   // for the result of this method.
151   virtual std::unique_ptr<Authenticator> CreateAuthenticator(
152       const std::string& local_jid,
153       const std::string& remote_jid) = 0;
154 };
155 
156 }  // namespace protocol
157 }  // namespace remoting
158 
159 #endif  // REMOTING_PROTOCOL_AUTHENTICATOR_H_
160