XRootD
XrdSecLoadSecurity.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S e c L o a d S e c u r i t y . c c */
4 /* */
5 /* (c) 2014 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 <iostream>
31 
32 #include "XrdVersion.hh"
33 
34 #include "XProtocol/XProtocol.hh"
35 
39 #include "XrdSys/XrdSysError.hh"
40 #include "XrdSys/XrdSysPlatform.hh"
41 #include "XrdSys/XrdSysPthread.hh"
42 
43 /******************************************************************************/
44 /* G l o b a l s */
45 /******************************************************************************/
46 
47 namespace
48 {
49 static XrdVERSIONINFODEF(myVersion, XrdSecLoader, XrdVNUMBER, XrdVERSION);
50 
51 XrdSysMutex protMutex;
52 }
53 
55 {
57 int protRC = 0;
58 }
59 
60 /******************************************************************************/
61 /* P l u g */
62 /******************************************************************************/
63 
64 namespace
65 {
66 int Plug(XrdOucPinLoader *piP, XrdSecGetProt_t *getP, XrdSecGetServ_t *ep)
67 {
68 // If we need to load the protocol factory do so now
69 //
70  if (getP && !(*getP=(XrdSecGetProt_t)piP->Resolve("XrdSecGetProtocol")))
71  return 1;
72 
73 // If we do not need to load the security service we are done
74 //
75  if (!ep) return 0;
76 
77 // Load the security service creator
78 //
79  if ((*ep = (XrdSecGetServ_t)piP->Resolve("XrdSecgetService"))) return 0;
80 
81 // We failed this is eiter soft or hard depending on what else we loaded
82 //
83  return (getP ? -1 : 1);
84 }
85 }
86 
87 /******************************************************************************/
88 /* Private: L o a d */
89 /******************************************************************************/
90 
91 namespace
92 {
93 int Load( char *eBuff, int eBlen,
94  const char *cfn, const char *seclib,
95  XrdSecGetProt_t *getP, XrdSecService **secP=0,
96  XrdSysError *eDest=0)
97 {
98  XrdSecGetServ_t ep;
99  XrdOucPinLoader *piP;
100  const char *mySecLib = "libXrdSec.so";
101  int rc;
102 
103 // Check for default path
104 //
105  if (!seclib) seclib = mySecLib;
106 
107 // Get a plugin loader object
108 //
109  if (eDest) piP = new XrdOucPinLoader(eDest,
110  &myVersion, "seclib", seclib);
111  else piP = new XrdOucPinLoader(eBuff, eBlen,
112  &myVersion, "seclib", seclib);
113 
114 // Load the appropriate pointers and get required objects.
115 //
116  rc = Plug(piP, getP, &ep);
117  if (rc == 0)
118  {if (secP && !(*secP = (*ep)(eDest->logger(), cfn))) rc = 1;
119  if (!rc) {delete piP; return 0;}
120  }
121 
122 // We failed, so bail out
123 //
124  if (eDest)
125  eDest->Say("Config ","Unable to create security framework via ", seclib);
126  piP->Unload(true);
127  return 1;
128 }
129 }
130 
131 /******************************************************************************/
132 
133 namespace
134 {
135 int Load( char *eBuff, int eBlen,
136  const char *protlib, XrdSysError *eDest=0)
137 {
138  XrdSecProtector **protPP;
139  XrdOucPinLoader *piP;
140  const char *myProtLib = "libXrdSecProt.so";
141 
142 // Check for default path
143 //
144  if (!protlib) protlib = myProtLib;
145 
146 // Get a plugin loader object
147 //
148  if (eDest) piP = new XrdOucPinLoader(eDest,
149  &myVersion, "protlib", protlib);
150  else piP = new XrdOucPinLoader(eBuff, eBlen,
151  &myVersion, "protlib", protlib);
152 
153 // Get the protection object which also is a factory object.
154 //
155  protPP = (XrdSecProtector **)piP->Resolve("XrdSecProtObjectP");
156  if (protPP)
158  delete piP;
159  return 0;
160  }
161  return 1;
162 
163 // We failed, so bail out
164 //
165  if (eDest)
166  eDest->Say("Config ","Unable to create protection framework via ",protlib);
167  piP->Unload(true);
168  return ENOENT;
169 }
170 }
171 
172 /******************************************************************************/
173 /* X r d S e c L o a d F a c t o r y */
174 /******************************************************************************/
175 
176 XrdSecGetProt_t XrdSecLoadSecFactory(char *eBuff, int eBlen, const char *seclib)
177 {
178  XrdSecGetProt_t getP;
179  int rc;
180 
181 // Load required plugin nd obtain pointers
182 //
183  rc = Load(eBuff, eBlen, 0, seclib, &getP);
184  if (!rc) return getP;
185 
186 // Issue correct error message, if any
187 //
188  if (!seclib) seclib = "default";
189 
190  if (rc < 0)
191  snprintf(eBuff, eBlen,
192  "Unable to create security framework via %s; invalid path.",
193  seclib);
194  else if (!(*eBuff))
195  snprintf(eBuff, eBlen,
196  "Unable to create security framework via %s", seclib);
197  return 0;
198 }
199 
200 /******************************************************************************/
201 /* X r d S e c G e t P r o t e c t i o n */
202 /******************************************************************************/
203 
204 // This is used client-side only
205 
207  XrdSecProtocol &aprot,
209  unsigned int resplen)
210 {
211  static const unsigned int hdrLen = sizeof(ServerResponseReqs_Protocol) - 2;
212  static const unsigned int minLen = kXR_ShortProtRespLen + hdrLen;
213  XrdSecProtector *pObj;
214  unsigned int vLen;
215  int rc;
216 
217 // First validate the response before passing it to anyone
218 //
219  protP = 0;
220  if (resplen <= kXR_ShortProtRespLen) return 0;
221  if (resplen < minLen) return -EINVAL;
222  vLen = static_cast<unsigned int>(resp.secreq.secvsz)
223  * sizeof(ServerResponseSVec_Protocol);
224  if (vLen + minLen > resplen) return -EINVAL;
225 
226 // Our first step is to see if any protection is required
227 //
228  if (vLen == 0 && resp.secreq.seclvl == kXR_secNone) return 0;
229 
230 // The next step is to see if we have a protector object. If we do not then
231 // we need to load the library that provides such objects. This needs to be
232 // MT-safe as it may be called at any time by any thread.
233 //
234  protMutex.Lock();
235  if (!(pObj = XrdSecProtection::theProtector))
237  {char eBuff[2048];
238  if ((XrdSecProtection::protRC = Load(eBuff, sizeof(eBuff), 0)))
239  std::cerr <<"SecLoad: " <<eBuff <<'\n' <<std::flush;
240  else
242  }
243  if ((rc = XrdSecProtection::protRC))
244  {protMutex.UnLock();
245  return -rc;
246  }
247  }
248  protMutex.UnLock();
249 
250 // Return new protection object
251 //
252  protP = pObj->New4Client(aprot, resp.secreq, resplen-kXR_ShortProtRespLen);
253  return (protP ? 1 : 0);
254 }
255 
256 /******************************************************************************/
257 /* X r d S e c L o a d P r o t e c t i o n */
258 /******************************************************************************/
259 
260 // This is a one-time server-side call
261 
263 {
264 
265 // Load the protection object. This is done in the main thread do no mutex
266 //
267  XrdSecProtection::protRC = Load(0, 0, 0, &erP);
268 
269 // All done, return result
270 //
272 }
273 
274 /******************************************************************************/
275 /* X r d S e c L o a d S e c S e r v i c e */
276 /******************************************************************************/
277 
279  const char *cfn,
280  const char *seclib,
281  XrdSecGetProt_t *getP,
282  XrdSecProtector**proP)
283 {
284  XrdSecService *CIA;
285 
286 // Load required plugin nd obtain pointers
287 //
288  if (Load(0, 0, cfn, seclib, getP, &CIA, eDest)) return 0;
289 
290 // Set the protectorobject. Note that the securityservice will load it if
291 // is needed and we will havecaptured its pointer. This sort of a hack but
292 // we can't change the SecService object as it is a public interface.
293 //
294  if (proP) *proP = XrdSecProtection::theProtector;
295  return CIA;
296 }
#define kXR_ShortProtRespLen
Definition: XProtocol.hh:1200
#define kXR_secNone
Definition: XProtocol.hh:1131
ServerResponseReqs_Protocol secreq
Definition: XProtocol.hh:1194
static XrdSysError eDest(0,"crypto_")
XrdSecService *(* XrdSecGetServ_t)(XrdSysLogger *, const char *)
XrdSecProtocol *(* XrdSecGetProt_t)(const char *hostname, XrdNetAddrInfo &endPoint, XrdSecParameters &sectoken, XrdOucErrInfo *einfo)
Typedef to simplify the encoding of methods returning XrdSecProtocol.
XrdSecGetProt_t XrdSecLoadSecFactory(char *eBuff, int eBlen, const char *seclib)
XrdSecProtector * XrdSecLoadProtection(XrdSysError &erP)
int XrdSecGetProtection(XrdSecProtect *&protP, XrdSecProtocol &aprot, ServerResponseBody_Protocol &resp, unsigned int resplen)
XrdSecService * XrdSecLoadSecService(XrdSysError *eDest, const char *cfn, const char *seclib, XrdSecGetProt_t *getP, XrdSecProtector **proP)
void * Resolve(const char *symbl, int mcnt=1)
void Unload(bool dodel=false)
virtual XrdSecProtect * New4Client(XrdSecProtocol &aprot, const ServerResponseReqs_Protocol &inReqs, unsigned int reqLen)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
Definition: XrdSysError.cc:141
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:141
XrdVersionInfo myVersion
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)
XrdSecProtector * theProtector