glooxd  0.3-svn
featuresasl.cpp
1 /*
2  Copyright (c) 2009 by Jakob Schroeter <js@camaya.net>
3  This file is part of the glooxd library. http://camaya.net/glooxd
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 #include "authenticationhandler.h"
14 #include "featuresasl.h"
15 #include "streambase.h"
16 
17 #include <gloox/adhoc.h>
18 #include <gloox/base64.h>
19 #include <gloox/dataform.h>
20 #include <gloox/gloox.h>
21 #include <gloox/iq.h>
22 
23 namespace glooxd
24 {
25 
27  : m_state( SASLCanceled ), m_authHandler( authHandler )
28  {
29  }
30 
31  const std::string& FeatureSASL::filterString() const
32  {
33  static const std::string filter = "/auth[@xmlns='" + gloox::XMLNS_STREAM_SASL + "']";
34  return filter;
35  }
36 
37  gloox::Tag* FeatureSASL::tag( int state, const std::string& /*domain*/ )
38  {
39  gloox::Tag* t = 0;
40 
41  if( ( state & StateAuthentication ) != StateAuthentication
42  // NOTE: If the following line is uncommented, SASL PLAIN will only
43  // be available if TLS encryption is on.
44  /*&& ( state & StateTLS ) == StateTLS*/ )
45  {
46  t = new gloox::Tag( "mechanisms" );
47  t->setXmlns( gloox::XMLNS_STREAM_SASL );
48  new gloox::Tag( t, "mechanism", "PLAIN" );
49 
50  m_state = SASLOffered;
51  }
52 
53  return t;
54  }
55 
56  void FeatureSASL::handleTag( gloox::Tag* _tag )
57  {
58  if( !_tag )
59  return;
60 
61  const gloox::Tag* auth = _tag->findTag( "/auth/[@xmlns='" + gloox::XMLNS_STREAM_SASL + "'][@mechanism='PLAIN']" );
62  if( m_state == SASLOffered && auth )
63  {
64  decodeSASLPLAIN( auth->cdata() );
65  return;
66  }
67 
68  m_state = SASLCanceled;
69  m_parent->disconnect( gloox::ConnAuthenticationFailed );
70  }
71 
72  void FeatureSASL::decodeSASLPLAIN( const std::string& cdata )
73  {
74  const std::string decoded = gloox::Base64::decode64( cdata );
75 
76  std::string::size_type pos = decoded.find( '\0', 0 );
77  if( pos == std::string::npos )
78  {
79  m_parent->disconnect( gloox::ConnAuthenticationFailed );
80  return;
81  }
82 
83  const gloox::JID authzid( decoded.substr( 0, pos ) );
84 
85  std::string::size_type pos2 = decoded.find( '\0', pos + 1 );
86  if( pos2 == std::string::npos )
87  {
88  m_parent->disconnect( gloox::ConnAuthenticationFailed );
89  return;
90  }
91 
92  const std::string& authcid = decoded.substr( pos + 1, pos2 - 1 );
93  const std::string& password = decoded.substr( pos2 + 1 );
94 
95  m_state = SASLChecking;
96  bool success = false;
97  if( m_authHandler )
98  success = m_authHandler->handleSASLPlain( authzid.bare(),
99  authcid, password );
100 
101  gloox::Tag* s = new gloox::Tag( success ? "success" : "failure" );
102  s->setXmlns( gloox::XMLNS_STREAM_SASL );
103  m_parent->send( s );
104 
105  if( success )
106  {
108  m_parent->finishStreamFeature( StateReset );
109  if( authzid )
110  {
111  const gloox::JID a( authzid );
112  m_parent->setUsername( a.username() );
113  m_parent->setServer( a.server() );
114  }
115  else
116  {
117  std::string::size_type pos3 = authcid.find( '@', 0 );
118  if( pos3 == std::string::npos )
119  {
120  m_parent->setUsername( authcid );
121  }
122  else
123  {
124  const gloox::JID a( authcid );
125  m_parent->setUsername( a.username() );
126  m_parent->setServer( a.server() );
127  }
128  }
129 
130  m_state = SASLEnabled;
131  }
132  else
133  {
134  m_state = SASLCanceled;
135  m_parent->disconnect( gloox::ConnAuthenticationFailed );
136  }
137  }
138 
139 }