Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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\file TSSLSocket.cxx
14\class TSSLSocket
15\brief A TSocket wrapped in by SSL.
16\note This class deals with sockets: the user is entirely responsible for the security of their usage, for example, but
17not limited to, the management of the connections to said sockets.
18**/
19
20
21#include <openssl/ssl.h>
22#include <cstdio>
23#include "strlcpy.h"
24#include "TSSLSocket.h"
25#include "TSystem.h"
26
27// Static properties
28char TSSLSocket::fgSSLCAFile[FILENAME_MAX] = "";
29char TSSLSocket::fgSSLCAPath[FILENAME_MAX] = "";
30char TSSLSocket::fgSSLUCert[FILENAME_MAX] = "";
31char TSSLSocket::fgSSLUKey[FILENAME_MAX] = "";
32
33////////////////////////////////////////////////////////////////////////////////
34/// Wraps the socket with OpenSSL.
35
37{
38 SSL_library_init();
39
40 // New context
41 if (!(fSSLCtx = SSL_CTX_new(SSLv23_method()))) {
42 Error("WrapWithSSL", "the context could not be created");
43 goto wrapFailed;
44 }
45
46 if ((fgSSLCAFile[0] || fgSSLCAPath[0]) && SSL_CTX_load_verify_locations(fSSLCtx, fgSSLCAFile, fgSSLCAPath) == 0) {
47 Error("WrapWithSSL", "could not set the CA file and/or the CA path");
48 goto wrapFailed;
49 }
50
51 if (fgSSLUCert[0] && SSL_CTX_use_certificate_chain_file(fSSLCtx, fgSSLUCert) == 0) {
52 Error("WrapWithSSL", "could not set the client certificate");
53 goto wrapFailed;
54 }
55
56 if (fgSSLUKey[0] && SSL_CTX_use_PrivateKey_file(fSSLCtx, fgSSLUKey, SSL_FILETYPE_PEM) == 0) {
57 Error("WrapWithSSL", "could not set the client private key");
58 goto wrapFailed;
59 }
60
61 // New SSL structure
62 if (!(fSSL = SSL_new(fSSLCtx))) {
63 Error("WrapWithSSL", "cannot create the ssl struct");
64 goto wrapFailed;
65 }
66
67 // Bind to the socket
68 if (SSL_set_fd(fSSL, fSocket) != 1) {
69 Error("WrapWithSSL", "cannot bind to the socket %d", fSocket);
70 goto wrapFailed;
71 }
72
73 // Open connection
74 if (SSL_connect(fSSL) != 1) {
75 Error("WrapWithSSL", "cannot connect");
76 goto wrapFailed;
77 }
78
79 return;
80
81wrapFailed:
82 Close();
83 return;
84}
85
86////////////////////////////////////////////////////////////////////////////////
87
89
90////////////////////////////////////////////////////////////////////////////////
91
92TSSLSocket::TSSLSocket(TInetAddress addr, const char *service, Int_t tcpwindowsize)
93 : TSocket(addr, service, tcpwindowsize)
94{
96}
97
98////////////////////////////////////////////////////////////////////////////////
99
101 : TSocket(addr, port, tcpwindowsize)
102{
103 WrapWithSSL();
104}
105
106////////////////////////////////////////////////////////////////////////////////
107
108TSSLSocket::TSSLSocket(const char *host, const char *service, Int_t tcpwindowsize)
109 : TSocket(host, service, tcpwindowsize)
110{
111 WrapWithSSL();
112}
113
114////////////////////////////////////////////////////////////////////////////////
115
116TSSLSocket::TSSLSocket(const char *url, Int_t port, Int_t tcpwindowsize)
117 : TSocket(url, port, tcpwindowsize)
118{
119 WrapWithSSL();
120}
121
122////////////////////////////////////////////////////////////////////////////////
123
124TSSLSocket::TSSLSocket(const char *sockpath) : TSocket(sockpath)
125{
126 WrapWithSSL();
127}
128
129////////////////////////////////////////////////////////////////////////////////
130
132{
133 WrapWithSSL();
134}
135
136////////////////////////////////////////////////////////////////////////////////
137
138TSSLSocket::TSSLSocket(Int_t desc, const char *sockpath) : TSocket(desc, sockpath)
139{
140 WrapWithSSL();
141}
142
143////////////////////////////////////////////////////////////////////////////////
144
146{
147 WrapWithSSL();
148}
149
150////////////////////////////////////////////////////////////////////////////////
151/// Close gracefully the connection, and free SSL structures.
152
154{
155 Close();
156 if (fSSL)
157 SSL_free(fSSL);
158 if (fSSLCtx)
159 SSL_CTX_free(fSSLCtx);
160}
161
162////////////////////////////////////////////////////////////////////////////////
163/// Close the SSL connection.
164
166{
167 if (fSSL)
168 SSL_shutdown(fSSL);
170}
171
172////////////////////////////////////////////////////////////////////////////////
173/// Set up the static configuration variables.
174
175void TSSLSocket::SetUpSSL(const char *cafile, const char *capath,
176 const char *ucert, const char *ukey)
177{
178 if (cafile)
179 strlcpy(fgSSLCAFile, cafile, FILENAME_MAX);
180 if (capath)
181 strlcpy(fgSSLCAPath, capath, FILENAME_MAX);
182 if (ucert)
183 strlcpy(fgSSLUCert, ucert, FILENAME_MAX);
184 if (ukey)
185 strlcpy(fgSSLUKey, ukey, FILENAME_MAX);
186}
187
188////////////////////////////////////////////////////////////////////////////////
189
191{
192 Error("Recv", "not implemented");
193 return -1;
194}
195
196////////////////////////////////////////////////////////////////////////////////
197/// Receive a raw buffer of specified length bytes.
198
200{
202
203 if (fSocket == -1) return -1;
204 if (length == 0) return 0;
205
207
208 Int_t n;
209 Int_t offset = 0;
210 Int_t remain = length;
211
212 // SSL_read/SSL_peek may not return the total length at once
213 while (remain > 0) {
214 if (opt == kPeek)
215 n = SSL_peek(fSSL, (char*)buffer + offset, (int)remain);
216 else
217 n = SSL_read(fSSL, (char*)buffer + offset, (int)remain);
218
219 if (n <= 0) {
220 if (gDebug > 0)
221 Error("RecvRaw", "failed to read from the socket");
222
223 if (SSL_get_error(fSSL, n) == SSL_ERROR_ZERO_RETURN || SSL_get_error(fSSL, n) == SSL_ERROR_SYSCALL) {
224 // Connection closed, reset or broken
226 SSL_set_quiet_shutdown(fSSL, 1); // Socket is gone, sending "close notify" will fail
227 Close();
228 }
229 return n;
230 }
231
232 // When peeking, just return the available data, don't loop. Otherwise,
233 // we may copy the same chunk of data multiple times into the
234 // output buffer, for instance when there is no more recent data
235 // in the socket's internal reception buffers.
236 // Note that in this case we don't update the counters of data received
237 // through this socket. They will be updated when the data is actually
238 // read. This avoids double counting.
239 if (opt == kPeek) return n;
240
241 offset += n;
242 remain -= n;
243 }
244
247
248 Touch(); // update usage timestamp
249
250 return offset;
251}
252
253////////////////////////////////////////////////////////////////////////////////
254
255Int_t TSSLSocket::Send(const TMessage & /* mess */)
256{
257 Error("Send", "not implemented");
258 return -1;
259}
260
261////////////////////////////////////////////////////////////////////////////////
262/// Send a raw buffer of specified length.
263
265{
267
268 if (fSocket == -1) return -1;
269
271
272 Int_t nsent;
273 if ((nsent = SSL_write(fSSL, buffer, (int)length)) <= 0) {
274 if (SSL_get_error(fSSL, nsent) == SSL_ERROR_ZERO_RETURN) {
275 // Connection reset or broken: close
277 Close();
278 }
279 return nsent;
280 }
281
282 fBytesSent += nsent;
283 fgBytesSent += nsent;
284
285 Touch(); // update usage timestamp
286
287 return nsent;
288}
int Int_t
Definition RtypesCore.h:45
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Int_t gDebug
Definition TROOT.cxx:622
ESendRecvOptions
Definition TSystem.h:236
@ kPeek
Definition TSystem.h:239
This class represents an Internet Protocol (IP) address.
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
void ResetBit(UInt_t f)
Definition TObject.h:195
A TSocket wrapped in by SSL.
Definition TSSLSocket.h:28
Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault) override
Send a raw buffer of specified length.
Int_t RecvRaw(void *buffer, Int_t length, ESendRecvOptions opt=kDefault) override
Receive a raw buffer of specified length bytes.
SSL * fSSL
Definition TSSLSocket.h:41
SSL_CTX * fSSLCtx
Definition TSSLSocket.h:40
static char fgSSLUKey[]
Definition TSSLSocket.h:37
void Close(Option_t *option="") override
Close the SSL connection.
static char fgSSLCAPath[]
Definition TSSLSocket.h:35
Int_t Recv(TMessage *&mess) override
Receive a TMessage object.
void WrapWithSSL()
Wraps the socket with OpenSSL.
static char fgSSLCAFile[]
Definition TSSLSocket.h:34
static char fgSSLUCert[]
Definition TSSLSocket.h:36
virtual ~TSSLSocket()
Close gracefully the connection, and free SSL structures.
Int_t Send(const TMessage &mess) override
Send a TMessage object.
static void SetUpSSL(const char *cafile, const char *capath, const char *ucert, const char *ukey)
Set up the static configuration variables.
Int_t fSocket
Definition TSocket.h:69
TSocket()
Definition TSocket.h:83
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:391
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:284
const Int_t n
Definition legend1.C:16
#define SSL_ERROR_SYSCALL
#define SSL_ERROR_ZERO_RETURN