Logo ROOT   6.08/07
Reference Guide
TSSLSocket.cxx
Go to the documentation of this file.
1 // @(#)root/net:$Id: TSSLSocket.cxx
2 // Author: Alejandro Alvarez 16/09/2011
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // TSSLSocket //
15 // //
16 // A TSocket wrapped in by SSL. //
17 // //
18 //////////////////////////////////////////////////////////////////////////
19 
20 #include <openssl/ssl.h>
21 #include <stdio.h>
22 #include "TROOT.h"
23 #include "TSSLSocket.h"
24 #include "TSystem.h"
25 
26 // Static properties
27 char TSSLSocket::fgSSLCAFile[FILENAME_MAX] = "";
28 char TSSLSocket::fgSSLCAPath[FILENAME_MAX] = "";
29 char TSSLSocket::fgSSLUCert[FILENAME_MAX] = "";
30 char TSSLSocket::fgSSLUKey[FILENAME_MAX] = "";
31 
32 ////////////////////////////////////////////////////////////////////////////////
33 /// Wraps the socket with OpenSSL.
34 
36 {
38 
39  // New context
40  if (!(fSSLCtx = SSL_CTX_new(SSLv23_method()))) {
41  Error("WrapWithSSL", "the context could not be created");
42  goto wrapFailed;
43  }
44 
46  Error("WrapWithSSL", "could not set the CA file and/or the CA path");
47  goto wrapFailed;
48  }
49 
51  Error("WrapWithSSL", "could not set the client certificate");
52  goto wrapFailed;
53  }
54 
55  if (fgSSLUKey[0] && SSL_CTX_use_PrivateKey_file(fSSLCtx, fgSSLUKey, SSL_FILETYPE_PEM) == 0) {
56  Error("WrapWithSSL", "could not set the client private key");
57  goto wrapFailed;
58  }
59 
60  // New SSL structure
61  if (!(fSSL = SSL_new(fSSLCtx))) {
62  Error("WrapWithSSL", "cannot create the ssl struct");
63  goto wrapFailed;
64  }
65 
66  // Bind to the socket
67  if (SSL_set_fd(fSSL, fSocket) != 1) {
68  Error("WrapWithSSL", "cannot bind to the socket %d", fSocket);
69  goto wrapFailed;
70  }
71 
72  // Open connection
73  if (SSL_connect(fSSL) != 1) {
74  Error("WrapWithSSL", "cannot connect");
75  goto wrapFailed;
76  }
77 
78  return;
79 
80 wrapFailed:
81  Close();
82  return;
83 }
84 
85 ////////////////////////////////////////////////////////////////////////////////
86 
88 
89 ////////////////////////////////////////////////////////////////////////////////
90 
91 TSSLSocket::TSSLSocket(TInetAddress addr, const char *service, Int_t tcpwindowsize)
92  : TSocket(addr, service, tcpwindowsize)
93 {
94  WrapWithSSL();
95 }
96 
97 ////////////////////////////////////////////////////////////////////////////////
98 
99 TSSLSocket::TSSLSocket(TInetAddress addr, Int_t port, Int_t tcpwindowsize)
100  : TSocket(addr, port, tcpwindowsize)
101 {
102  WrapWithSSL();
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 
107 TSSLSocket::TSSLSocket(const char *host, const char *service, Int_t tcpwindowsize)
108  : TSocket(host, service, tcpwindowsize)
109 {
110  WrapWithSSL();
111 }
112 
113 ////////////////////////////////////////////////////////////////////////////////
114 
115 TSSLSocket::TSSLSocket(const char *url, Int_t port, Int_t tcpwindowsize)
116  : TSocket(url, port, tcpwindowsize)
117 {
118  WrapWithSSL();
119 }
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 
123 TSSLSocket::TSSLSocket(const char *sockpath) : TSocket(sockpath)
124 {
125  WrapWithSSL();
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 
131 {
132  WrapWithSSL();
133 }
134 
135 ////////////////////////////////////////////////////////////////////////////////
136 
137 TSSLSocket::TSSLSocket(Int_t desc, const char *sockpath) : TSocket(desc, sockpath)
138 {
139  WrapWithSSL();
140 }
141 
142 ////////////////////////////////////////////////////////////////////////////////
143 
145 {
146  WrapWithSSL();
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Close gracefully the connection, and free SSL structures.
151 
153 {
154  Close();
155  if (fSSL)
156  SSL_free(fSSL);
157  if (fSSLCtx)
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 /// Close the SSL connection.
163 
165 {
166  if (fSSL)
168  TSocket::Close(option);
169 }
170 
171 ////////////////////////////////////////////////////////////////////////////////
172 /// Set up the static configuration variables.
173 
174 void TSSLSocket::SetUpSSL(const char *cafile, const char *capath,
175  const char *ucert, const char *ukey)
176 {
177  if (cafile)
178  strlcpy(fgSSLCAFile, cafile, FILENAME_MAX);
179  if (capath)
180  strlcpy(fgSSLCAPath, capath, FILENAME_MAX);
181  if (ucert)
182  strlcpy(fgSSLUCert, ucert, FILENAME_MAX);
183  if (ukey)
184  strlcpy(fgSSLUKey, ukey, FILENAME_MAX);
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 
190 {
191  Error("Recv", "not implemented");
192  return -1;
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// Receive a raw buffer of specified length bytes.
197 
199 {
201 
202  if (fSocket == -1) return -1;
203  if (length == 0) return 0;
204 
206 
207  Int_t n;
208  Int_t offset = 0;
209  Int_t remain = length;
210 
211  // SSL_read/SSL_peek may not return the total length at once
212  while (remain > 0) {
213  if (opt == kPeek)
214  n = SSL_peek(fSSL, (char*)buffer + offset, (int)remain);
215  else
216  n = SSL_read(fSSL, (char*)buffer + offset, (int)remain);
217 
218  if (n <= 0) {
219  if (gDebug > 0)
220  Error("RecvRaw", "failed to read from the socket");
221 
222  if (SSL_get_error(fSSL, n) == SSL_ERROR_ZERO_RETURN || SSL_get_error(fSSL, n) == SSL_ERROR_SYSCALL) {
223  // Connection closed, reset or broken
225  SSL_set_quiet_shutdown(fSSL, 1); // Socket is gone, sending "close notify" will fail
226  Close();
227  }
228  return n;
229  }
230 
231  // When peeking, just return the available data, don't loop. Otherwise,
232  // we may copy the same chunk of data multiple times into the
233  // output buffer, for instance when there is no more recent data
234  // in the socket's internal reception buffers.
235  // Note that in this case we don't update the counters of data received
236  // through this socket. They will be updated when the data is actually
237  // read. This avoids double counting.
238  if (opt == kPeek) return n;
239 
240  offset += n;
241  remain -= n;
242  }
243 
244  fBytesRecv += length;
245  fgBytesRecv += length;
246 
247  Touch(); // update usage timestamp
248 
249  return offset;
250 }
251 
252 ////////////////////////////////////////////////////////////////////////////////
253 
254 Int_t TSSLSocket::Send(const TMessage & /* mess */)
255 {
256  Error("Send", "not implemented");
257  return -1;
258 }
259 
260 ////////////////////////////////////////////////////////////////////////////////
261 /// Send a raw buffer of specified length.
262 
263 Int_t TSSLSocket::SendRaw(const void *buffer, Int_t length, ESendRecvOptions /* opt */)
264 {
266 
267  if (fSocket == -1) return -1;
268 
270 
271  Int_t nsent;
272  if ((nsent = SSL_write(fSSL, buffer, (int)length)) <= 0) {
273  if (SSL_get_error(fSSL, nsent) == SSL_ERROR_ZERO_RETURN) {
274  // Connection reset or broken: close
276  Close();
277  }
278  return nsent;
279  }
280 
281  fBytesSent += nsent;
282  fgBytesSent += nsent;
283 
284  Touch(); // update usage timestamp
285 
286  return nsent;
287 }
SSL * fSSL
Definition: TSSLSocket.h:43
static char fgSSLUCert[]
Definition: TSSLSocket.h:38
Int_t fSocket
Definition: TSocket.h:100
Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Send a raw buffer of specified length.
Definition: TSSLSocket.cxx:263
#define SSL_CTX_use_certificate_chain_file
Definition: civetweb.c:908
static char fgSSLCAPath[]
Definition: TSSLSocket.h:37
const char Option_t
Definition: RtypesCore.h:62
#define SSL_library_init
Definition: civetweb.c:899
#define SSL_set_fd
Definition: civetweb.c:895
This class represents an Internet Protocol (IP) address.
Definition: TInetAddress.h:40
#define SSL_write
Definition: civetweb.c:893
int Int_t
Definition: RtypesCore.h:41
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
ESendRecvOptions
Definition: TSocket.h:65
#define SSL_CTX_free
Definition: civetweb.c:906
Int_t Recv(TMessage *&mess)
Receive a TMessage object.
Definition: TSSLSocket.cxx:189
Int_t Send(const TMessage &mess)
Send a TMessage object.
Definition: TSSLSocket.cxx:254
static char fgSSLUKey[]
Definition: TSSLSocket.h:39
#define SSL_CTX_use_PrivateKey_file
Definition: civetweb.c:900
#define SSL_get_error
Definition: civetweb.c:894
#define SSL_shutdown
Definition: civetweb.c:916
SSL_CTX * fSSLCtx
Definition: TSSLSocket.h:42
virtual void Close(Option_t *opt="")
Close the socket.
Definition: TSocket.cxx:388
#define SSL_new
Definition: civetweb.c:896
UInt_t fBytesSent
Definition: TSocket.h:92
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
Definition: TSocket.h:68
#define SSL_CTX_new
Definition: civetweb.c:897
void Touch()
Definition: TSocket.h:187
#define ClassImp(name)
Definition: Rtypes.h:279
static void SetUpSSL(const char *cafile, const char *capath, const char *ucert, const char *ukey)
Set up the static configuration variables.
Definition: TSSLSocket.cxx:174
void Close(Option_t *option="")
Close the SSL connection.
Definition: TSSLSocket.cxx:164
void WrapWithSSL()
Wraps the socket with OpenSSL.
Definition: TSSLSocket.cxx:35
#define SSL_free
Definition: civetweb.c:889
static ULong64_t fgBytesSent
Definition: TSocket.h:110
#define SSL_connect
Definition: civetweb.c:891
static ULong64_t fgBytesRecv
Definition: TSocket.h:109
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
#define SSL_CTX_load_verify_locations
Definition: civetweb.c:917
static void ResetErrno()
Static function resetting system error number.
Definition: TSystem.cxx:281
void ResetBit(UInt_t f)
Definition: TObject.h:156
Int_t RecvRaw(void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Receive a raw buffer of specified length bytes.
Definition: TSSLSocket.cxx:198
static char fgSSLCAFile[]
Definition: TSSLSocket.h:36
const Int_t n
Definition: legend1.C:16
virtual ~TSSLSocket()
Close gracefully the connection, and free SSL structures.
Definition: TSSLSocket.cxx:152
UInt_t fBytesRecv
Definition: TSocket.h:91
#define SSL_read
Definition: civetweb.c:892