glooxd  0.3-svn
featurestarttls.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 
14 #include "certificateprovider.h"
15 #include "featurestarttls.h"
16 #include "streambase.h"
17 
18 #include <gloox/connectiontlsserver.h>
19 #include <gloox/gloox.h>
20 #include <gloox/tag.h>
21 
22 #include <cstdio>
23 
24 namespace glooxd
25 {
26 
28  CertificateProvider* cp )
29  : m_state( TLSCanceled ), m_cp( cp ),
30  m_encryption( 0 ), m_required( required )
31  {
32  }
33 
35  {
36  delete m_encryption;
37  }
38 
39  const std::string& FeatureSTARTTLS::filterString() const
40  {
41  static const std::string filter = "/starttls[@xmlns='" + gloox::XMLNS_STREAM_TLS + "']";
42  return filter;
43  }
44 
45  gloox::Tag* FeatureSTARTTLS::tag( int state, const std::string& /*domain*/ )
46  {
47  gloox::Tag* t = 0;
48 
49  if( m_state == TLSCanceled
50  && !( state & ( StateTLS | StateAuthentication ) ) )
51  {
52  bool haveCert = false;
53  if( m_cp )
54  {
55  m_key = m_cp->handleKeyRequest( m_parent->jid().server() );
56  m_cert = m_cp->handleCertificateRequest( m_parent->jid().server() );
57  haveCert = ( !m_key.empty() && !m_cert.empty() );
58  }
59 
60  if( haveCert )
61  {
62  t = new gloox::Tag( "starttls" );
63  t->setXmlns( gloox::XMLNS_STREAM_TLS );
64  if( m_required )
65  new gloox::Tag( t, "required" );
66  else
67  new gloox::Tag( t, "optional" );
68 
69  m_state = TLSOffered;
70  }
71  else if( m_required )
72  m_parent->disconnect( gloox::ConnStreamError,
73  gloox::StreamErrorInternalServerError );
74  else if( !m_required )
75  m_parent->finishStreamFeature( StateTLS );
76  }
77 
78  return t;
79  }
80 
81  void FeatureSTARTTLS::handleTag( gloox::Tag* _tag )
82  {
83  if( !_tag || _tag->xmlns() != gloox::XMLNS_STREAM_TLS )
84  return;
85 
86  const std::string& name = _tag->name();
87 
88  if( name == "starttls" && m_state == TLSOffered )
89  {
90  gloox::Tag* p = new gloox::Tag( "proceed" );
91  p->setXmlns( gloox::XMLNS_STREAM_TLS );
92  m_parent->send( p );
93 
94  m_encryption = new gloox::ConnectionTLSServer( m_parent, m_parent->connection(),
95  m_parent->logInstance() );
96  m_encryption->registerTLSHandler( this );
97 // m_encryption->setCACerts( m_cacerts );
98  m_encryption->setClientCert( m_key, m_cert );
99  m_encryption->connect();
100  m_parent->finishStreamFeature( StateTLS, m_encryption );
101  m_state = TLSHandshake;
102  }
103  else if( name == "failure" )
104  {
105  m_state = TLSCanceled;
106  m_parent->disconnect( gloox::ConnTlsFailed );
107  }
108  }
109 
110  void FeatureSTARTTLS::handleHandshakeResult( const gloox::TLSBase* /*base*/,
111  bool success, gloox::CertInfo& certinfo )
112  {
113  printf( "handshake result: %d\n", success );
114 
115  m_encryption->registerTLSHandler( 0 );
116  m_encryption = 0;
117 
118  if( success )
119  {
120  m_state = TLSEnabled;
121  if( !certinfo.compression.empty() )
122  {
123 #ifdef DEBUG
124  printf( "TLS compression enabled, disabling stream compression (XEP-138)\n" );
125 #endif
127  }
128  m_parent->finishStreamFeature( StateReset );
129  }
130  else
131  {
132  m_state = TLSCanceled;
133  gloox::Tag* f = new gloox::Tag( "failure" );
134  f->setXmlns( gloox::XMLNS_STREAM_TLS );
135  m_parent->send( f );
136  m_parent->disconnect( gloox::ConnTlsFailed );
137  }
138  }
139 
140 }