XRootD
XrdSecProtector.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S e c P r o t e c t o r . c c */
4 /* */
5 /* (c) 2016 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include <cerrno>
31 #include <cinttypes>
32 #include <cstring>
33 #include <sys/types.h>
34 
35 #include "XrdVersion.hh"
36 
37 #include "XrdNet/XrdNetIF.hh"
39 #include "XrdSec/XrdSecProtect.hh"
41 #include "XrdSys/XrdSysError.hh"
42 
43 /******************************************************************************/
44 /* L i b r a r y L i n k a g e */
45 /******************************************************************************/
46 
47 namespace
48 {
49 class protoProtector : public XrdSecProtector
50 {
51 public:
52  protoProtector() {}
53  ~protoProtector() {}
54 };
55 
56 protoProtector baseProtector;
57 }
58 
60 
62 
63 /******************************************************************************/
64 /* S e r v e r - S i d e C o n f i g u r a t i o n */
65 /******************************************************************************/
66 
67 namespace
68 {
69 struct ProtInfo {XrdSecProtect *theProt;
71  bool relaxed;
72  bool force;
73  ProtInfo() : theProt(0), relaxed(false), force(false)
74  {reqs.theTag = 'S';
75  reqs.rsvd = 0;
76  reqs.secver = kXR_secver_0;
77  reqs.secopt = 0;
78  reqs.seclvl = kXR_secNone;
79  reqs.secvsz = 0;
80  }
81  } lrTab[XrdSecProtector::isLR];
82 
83 bool lrSame = true;
84 bool noProt = true;
85 }
86 
87 /******************************************************************************/
88 /* S e r v e r - S i d e E r r o r M e s s a g e R o u t i n g */
89 /******************************************************************************/
90 
91 namespace
92 {
93 XrdSysError Say(0, "sec_");
94 }
95 
96 /******************************************************************************/
97 /* C o n f i g */
98 /******************************************************************************/
99 
101  const XrdSecProtectParms &rmtParms,
102  XrdSysLogger &logr)
103 {
104 
105 // Set the logger right off
106 //
107  Say.logger(&logr);
108 
109 // Setup local protection
110 //
111  if (lclParms.level != XrdSecProtectParms::secNone)
112  {Config(lclParms, lrTab[isLcl].reqs);
113  lrTab[isLcl].theProt = new XrdSecProtect;
114  lrTab[isLcl].theProt->SetProtection(lrTab[isLcl].reqs);
115  }
116 
117 // Setup remote protection (check for reuse of local protection)
118 //
119  if (rmtParms.level == lclParms.level)
120  {lrTab[isRmt] = lrTab[isLcl];
121  lrSame = true;
122  } else {
123  lrSame = false;
124  if (rmtParms.level != XrdSecProtectParms::secNone)
125  {Config(rmtParms, lrTab[isRmt].reqs);
126  lrTab[isRmt].theProt = new XrdSecProtect;
127  lrTab[isRmt].theProt->SetProtection(lrTab[isRmt].reqs);
128  }
129  }
130 
131 // Record relax flags
132 //
133  lrTab[isLcl].relaxed = (lclParms.opts & XrdSecProtectParms::relax) != 0;
134  lrTab[isLcl].force = (lclParms.opts & XrdSecProtectParms::force) != 0;
135  lrTab[isRmt].relaxed = (rmtParms.opts & XrdSecProtectParms::relax) != 0;
136  lrTab[isRmt].force = (rmtParms.opts & XrdSecProtectParms::force) != 0;
137 
138 // Setup shortcut flag
139 //
140  noProt = (lrTab[isLcl].theProt == 0) && (lrTab[isRmt].theProt == 0);
141 
142 // All done
143 //
144  return true;
145 }
146 
147 /******************************************************************************/
148 
151 {
152  unsigned int lvl;
153 
154 // Setup options
155 //
156  if ((parms.opts & XrdSecProtectParms::doData) != 0)
157  reqs.secopt |= kXR_secOData;
158  if ((parms.opts & XrdSecProtectParms::force) != 0)
159  reqs.secopt |= kXR_secOFrce;
160 
161 // Setup level
162 //
163  switch(parms.level)
165  break;
167  break;
169  break;
171  break;
172  default: lvl = kXR_secNone;
173  break;
174  }
175  reqs.seclvl = lvl;
176 }
177 
178 /******************************************************************************/
179 /* L N a m e */
180 /******************************************************************************/
181 
183 {
184  static const char *lvlVec[] = {"none", "compatible", "standard",
185  "intense", "pedantic"};
186 
187 // Validate the level
188 //
190  else if (level > XrdSecProtectParms::secPedantic)
192 
193 // Return the level name
194 //
195  return lvlVec[level];
196 }
197 
198 /******************************************************************************/
199 /* N e w 4 C l i e n t */
200 /******************************************************************************/
201 
203  const ServerResponseReqs_Protocol &inReqs,
204  unsigned int reqLen)
205 {
206  static const unsigned int hdrLen = sizeof(ServerResponseBody_Protocol)
207  - sizeof(ServerResponseSVec_Protocol);
208  XrdSecProtect *secP;
209  unsigned int vLen = static_cast<unsigned int>(inReqs.secvsz)
210  * sizeof(ServerResponseSVec_Protocol);
211  bool okED;
212 
213 // Validate the incoming struct (if it's bad skip the security) and that any
214 // security is actually wanted.
215 //
216  if (vLen+hdrLen > reqLen
217  || (inReqs.secvsz == 0 && inReqs.seclvl == kXR_secNone)) return 0;
218 
219 // If the auth protocol doesn't support encryption, see if we still need to
220 // send off signed requests (mostly for testng)
221 //
222  okED = aprot.getKey() > 0;
223  if (!okED && (inReqs.secopt & kXR_secOFrce) == 0) return 0;
224 
225 // Get a new security object and set its security level
226 //
227  secP = new XrdSecProtect(&aprot, okED);
228  secP->SetProtection(inReqs);
229 
230 // All done
231 //
232  return secP;
233 }
234 
235 /******************************************************************************/
236 /* N e w 4 S e r v e r */
237 /******************************************************************************/
238 
240 {
241  static const char *wFrc = "authentication can't encrypt; "
242  "continuing without it!";
243  static const char *wIgn = "authentication can't encrypt; "
244  "allowing unsigned requests!";
245  XrdSecProtect *secP;
246  lrType theLR;
247  bool okED;
248 
249 // Check if we need any security at all
250 //
251  if (noProt) return 0;
252 
253 // Now we need to see whether this is local or remote of if it matters
254 //
255  if (lrSame) theLR = isLcl;
256  else theLR = (XrdNetIF::InDomain(aprot.Entity.addrInfo) ? isLcl : isRmt);
257 
258 // Now check again, as may not need any protection for the domain
259 //
260  if (lrTab[theLR].theProt == 0) return 0;
261 
262 // Check for relaxed processing
263 //
264  if (plvl < kXR_PROTSIGNVERSION && lrTab[theLR].relaxed) return 0;
265 
266 // Check if protocol supports encryption
267 //
268  okED = aprot.getKey() > 0;
269  if (!okED)
270  {char pName[XrdSecPROTOIDSIZE+1];
271  const char *action;
272  strncpy(pName, aprot.Entity.prot, XrdSecPROTOIDSIZE);
273  pName[XrdSecPROTOIDSIZE] = 0;
274  action = (lrTab[theLR].force ? wFrc : wIgn);
275  Say.Emsg("Protect", aprot.Entity.tident, pName, action);
276  if (!lrTab[theLR].force) return 0;
277  }
278 
279 // Get a new security object and make it a clone of this right one
280 //
281  secP = new XrdSecProtect(&aprot, *lrTab[theLR].theProt, okED);
282 
283 // All done
284 //
285  return secP;
286 }
287 
288 /******************************************************************************/
289 /* P r o t R e s p */
290 /******************************************************************************/
291 
293  XrdNetAddrInfo &nai, int pver)
294 {
295  static const int rsplen = sizeof(ServerResponseReqs_Protocol)
296  - sizeof(ServerResponseSVec_Protocol);
298 
299 // Check if we need any response at all
300 //
301  if (noProt) return 0;
302 
303 // Get the right response
304 //
305  if (lrSame || XrdNetIF::InDomain(&nai)) myResp = &lrTab[isLcl].reqs;
306  else myResp = &lrTab[isRmt].reqs;
307 
308 // Return result
309 //
310  memcpy(&resp, myResp, rsplen);
311  return rsplen;
312 }
#define kXR_secStandard
Definition: XProtocol.hh:1133
#define kXR_PROTSIGNVERSION
Definition: XProtocol.hh:74
#define kXR_secOFrce
Definition: XProtocol.hh:1127
#define kXR_secNone
Definition: XProtocol.hh:1131
#define kXR_secOData
Definition: XProtocol.hh:1126
#define kXR_secPedantic
Definition: XProtocol.hh:1135
#define kXR_secver_0
Definition: XProtocol.hh:1146
#define kXR_secCompatible
Definition: XProtocol.hh:1132
#define kXR_secIntense
Definition: XProtocol.hh:1134
#define XrdSecPROTOIDSIZE
Definition: XrdSecEntity.hh:47
XrdVERSIONINFO(XrdSecProtObjectP,"secProt")
XrdSecProtector * XrdSecProtObjectP
static bool InDomain(XrdNetAddrInfo *epaddr)
Definition: XrdNetIF.cc:622
XrdNetAddrInfo * addrInfo
Entity's connection details.
Definition: XrdSecEntity.hh:80
const char * tident
Trace identifier always preset.
Definition: XrdSecEntity.hh:81
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5)
Definition: XrdSecEntity.hh:67
static const int doData
Secure data.
static const int relax
relax old clients
secLevel level
In: The desired level.
static const int force
Allow unencryted hash.
int opts
In: Options:
void SetProtection(const ServerResponseReqs_Protocol &inReqs)
virtual XrdSecProtect * New4Client(XrdSecProtocol &aprot, const ServerResponseReqs_Protocol &inReqs, unsigned int reqLen)
virtual XrdSecProtect * New4Server(XrdSecProtocol &aprot, int plvl)
virtual int ProtResp(ServerResponseReqs_Protocol &resp, XrdNetAddrInfo &nai, int pver)
virtual bool Config(const XrdSecProtectParms &lclParms, const XrdSecProtectParms &rmtParms, XrdSysLogger &logr)
virtual const char * LName(XrdSecProtectParms::secLevel level)
XrdSecEntity Entity
virtual int getKey(char *buff=0, int size=0)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:141
XrdSysError Say