Logo ROOT  
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 <cstdio>
22#include "strlcpy.h"
23#include "TSSLSocket.h"
24#include "TSystem.h"
25
26// Static properties
27char TSSLSocket::fgSSLCAFile[FILENAME_MAX] = "";
28char TSSLSocket::fgSSLCAPath[FILENAME_MAX] = "";
29char TSSLSocket::fgSSLUCert[FILENAME_MAX] = "";
30char 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
80wrapFailed:
81 Close();
82 return;
83}
84
85////////////////////////////////////////////////////////////////////////////////
86
88
89////////////////////////////////////////////////////////////////////////////////
90
91TSSLSocket::TSSLSocket(TInetAddress addr, const char *service, Int_t tcpwindowsize)
92 : TSocket(addr, service, tcpwindowsize)
93{
95}
96
97////////////////////////////////////////////////////////////////////////////////
98
100 : TSocket(addr, port, tcpwindowsize)
101{
102 WrapWithSSL();
103}
104
105////////////////////////////////////////////////////////////////////////////////
106
107TSSLSocket::TSSLSocket(const char *host, const char *service, Int_t tcpwindowsize)
108 : TSocket(host, service, tcpwindowsize)
109{
110 WrapWithSSL();
111}
112
113////////////////////////////////////////////////////////////////////////////////
114
115TSSLSocket::TSSLSocket(const char *url, Int_t port, Int_t tcpwindowsize)
116 : TSocket(url, port, tcpwindowsize)
117{
118 WrapWithSSL();
119}
120
121////////////////////////////////////////////////////////////////////////////////
122
123TSSLSocket::TSSLSocket(const char *sockpath) : TSocket(sockpath)
124{
125 WrapWithSSL();
126}
127
128////////////////////////////////////////////////////////////////////////////////
129
131{
132 WrapWithSSL();
133}
134
135////////////////////////////////////////////////////////////////////////////////
136
137TSSLSocket::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
174void 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
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
254Int_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
263Int_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) {
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}
int Int_t
Definition: RtypesCore.h:45
const char Option_t
Definition: RtypesCore.h:66
#define ClassImp(name)
Definition: Rtypes.h:364
Int_t gDebug
Definition: TROOT.cxx:592
ESendRecvOptions
Definition: TSystem.h:228
@ kPeek
Definition: TSystem.h:231
#define SSL_new
Definition: civetweb.c:2007
#define SSL_shutdown
Definition: civetweb.c:2028
#define SSL_library_init
Definition: civetweb.c:2010
#define SSL_ERROR_SYSCALL
Definition: civetweb.c:1803
#define SSL_CTX_load_verify_locations
Definition: civetweb.c:2029
#define SSL_CTX_new
Definition: civetweb.c:2008
#define SSL_free
Definition: civetweb.c:2000
#define SSL_CTX_use_PrivateKey_file
Definition: civetweb.c:2011
#define SSL_write
Definition: civetweb.c:2004
#define SSL_CTX_free
Definition: civetweb.c:2017
#define SSL_set_fd
Definition: civetweb.c:2006
#define SSL_read
Definition: civetweb.c:2003
#define SSL_CTX_use_certificate_chain_file
Definition: civetweb.c:2019
#define SSL_ERROR_ZERO_RETURN
Definition: civetweb.c:1804
#define SSL_get_error
Definition: civetweb.c:2005
#define SSL_connect
Definition: civetweb.c:2002
This class represents an Internet Protocol (IP) address.
Definition: TInetAddress.h:36
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:696
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:893
void ResetBit(UInt_t f)
Definition: TObject.h:186
Int_t Recv(TMessage *&mess)
Receive a TMessage object.
Definition: TSSLSocket.cxx:189
SSL * fSSL
Definition: TSSLSocket.h:41
SSL_CTX * fSSLCtx
Definition: TSSLSocket.h:40
static char fgSSLUKey[]
Definition: TSSLSocket.h:37
static char fgSSLCAPath[]
Definition: TSSLSocket.h:35
void WrapWithSSL()
Wraps the socket with OpenSSL.
Definition: TSSLSocket.cxx:35
static char fgSSLCAFile[]
Definition: TSSLSocket.h:34
Int_t Send(const TMessage &mess)
Send a TMessage object.
Definition: TSSLSocket.cxx:254
static char fgSSLUCert[]
Definition: TSSLSocket.h:36
Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Send a raw buffer of specified length.
Definition: TSSLSocket.cxx:263
void Close(Option_t *option="")
Close the SSL connection.
Definition: TSSLSocket.cxx:164
virtual ~TSSLSocket()
Close gracefully the connection, and free SSL structures.
Definition: TSSLSocket.cxx:152
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
Int_t RecvRaw(void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Receive a raw buffer of specified length bytes.
Definition: TSSLSocket.cxx:198
Int_t fSocket
Definition: TSocket.h:69
static ULong64_t fgBytesRecv
Definition: TSocket.h:78
@ kBrokenConn
Definition: TSocket.h:49
virtual void Close(Option_t *opt="")
Close the socket.
Definition: TSocket.cxx:389
void Touch()
Definition: TSocket.h:157
static ULong64_t fgBytesSent
Definition: TSocket.h:79
UInt_t fBytesSent
Definition: TSocket.h:61
UInt_t fBytesRecv
Definition: TSocket.h:60
static void ResetErrno()
Static function resetting system error number.
Definition: TSystem.cxx:279
const Int_t n
Definition: legend1.C:16
static constexpr double s