summaryrefslogtreecommitdiffstats
path: root/remoting/signaling/xmpp_login_handler.h
blob: 33d87e6b70d88536250f9b1f471d16033e97539a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef REMOTING_SIGNALING_XMPP_LOGIN_HANDLER_H_
#define REMOTING_SIGNALING_XMPP_LOGIN_HANDLER_H_

#include <string>

#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "remoting/signaling/signal_strategy.h"

// Undefine SendMessage and ERROR defined in Windows headers.
#ifdef SendMessage
#undef SendMessage
#endif

#ifdef ERROR
#undef ERROR
#endif

namespace remoting {

class XmppStreamParser;

// XmppLoginHandler handles authentication handshake for XmppSignalStrategy. It
// receives incoming data using onDataReceived(), calls Delegate::SendMessage()
// to send outgoing messages and calls Delegate::OnHandshakeDone() after
// authentication is finished successfully or Delegate::OnError() on error.
//
// See RFC3920 for description of XMPP and authentication handshake.
class XmppLoginHandler {
 public:
  class Delegate {
   public:
    Delegate() {}

    // All Delegate methods are allowed to destroy XmppLoginHandler.
    virtual void SendMessage(const std::string& message) = 0;
    virtual void StartTls() = 0;
    virtual void OnHandshakeDone(const std::string& jid,
                                 scoped_ptr<XmppStreamParser> parser) = 0;
    virtual void OnLoginHandlerError(SignalStrategy::Error error) = 0;

   protected:
    virtual ~Delegate() {}
  };

  enum class TlsMode {
    NO_TLS,
    WITH_HANDSHAKE,
    WITHOUT_HANDSHAKE,
  };

  XmppLoginHandler(const std::string& server,
                   const std::string& username,
                   const std::string& auth_token,
                   TlsMode tls_mode,
                   Delegate* delegate);
  ~XmppLoginHandler();

  void Start();
  void OnDataReceived(const std::string& data);
  void OnTlsStarted();

 private:
  // States the handshake goes through. States are iterated from INIT to DONE
  // sequentially, except for ERROR state which may be accepted at any point.
  //
  // Following messages are sent/received in each state:
  //    INIT
  //      client -> server: Stream header
  //      client -> server: <starttls>
  //    WAIT_STREAM_HEADER
  //      client <- server: Stream header with list of supported features which
  //          should include starttls.
  //    WAIT_STARTTLS_RESPONSE
  //      client <- server: <proceed>
  //    STARTING_TLS
  //      TLS handshake
  //      client -> server: Stream header
  //      client -> server: <auth> message with the OAuth2 token.
  //    WAIT_STREAM_HEADER_AFTER_TLS
  //      client <- server: Stream header with list of supported authentication
  //          methods which is expected to include X-OAUTH2
  //    WAIT_AUTH_RESULT
  //      client <- server: <success> or <failure>
  //      client -> server: Stream header
  //      client -> server: <bind>
  //      client -> server: <iq><session/></iq> to start the session
  //    WAIT_STREAM_HEADER_AFTER_AUTH
  //      client <- server: Stream header with list of features that should
  //         include <bind>.
  //    WAIT_BIND_RESULT
  //      client <- server: <bind> result with JID.
  //    WAIT_SESSION_IQ_RESULT
  //      client <- server: result for <iq><session/></iq>
  //    DONE
  enum class State {
    INIT,
    WAIT_STREAM_HEADER,
    WAIT_STARTTLS_RESPONSE,
    STARTING_TLS,
    WAIT_STREAM_HEADER_AFTER_TLS,
    WAIT_AUTH_RESULT,
    WAIT_STREAM_HEADER_AFTER_AUTH,
    WAIT_BIND_RESULT,
    WAIT_SESSION_IQ_RESULT,
    DONE,
    ERROR,
  };

  // Callbacks for XmppStreamParser.
  void OnStanza(scoped_ptr<buzz::XmlElement> stanza);
  void OnParserError();

  // Starts authentication handshake in WAIT_STREAM_HEADER_AFTER_TLS state.
  void StartAuthHandshake();

  // Helper used to send stream header.
  void StartStream(const std::string& first_message);

  // Report the |error| to the delegate and changes |state_| to ERROR,
  void OnError(SignalStrategy::Error error);

  std::string server_;
  std::string username_;
  std::string auth_token_;
  TlsMode tls_mode_;
  Delegate* delegate_;

  State state_;

  std::string jid_;

  scoped_ptr<XmppStreamParser> stream_parser_;

  DISALLOW_COPY_AND_ASSIGN(XmppLoginHandler);
};

}  // namespace remoting

#endif  // REMOTING_SIGNALING_XMPP_LOGIN_HANDLER_H_