XRootD
XrdOfsTPCAuth.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O f s T P C A u t h . c c */
4 /* */
5 /* (c) 2012 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <cstdio>
32 #include <cstdlib>
33 #include <strings.h>
34 
35 #include "XrdOfs/XrdOfsStats.hh"
36 #include "XrdOfs/XrdOfsTPCAuth.hh"
38 #include "XrdOuc/XrdOucCallBack.hh"
40 #include "XrdSys/XrdSysError.hh"
41 #include "XrdSys/XrdSysTimer.hh"
42 
43 /******************************************************************************/
44 /* G l o b a l O b j e c t s */
45 /******************************************************************************/
46 
47 extern XrdSysError OfsEroute;
48 extern XrdOfsStats OfsStats;
49 
50 namespace XrdOfsTPCParms
51 {
52 extern XrdOfsTPCConfig Cfg;
53 }
54 using namespace XrdOfsTPCParms;
55 
56 /******************************************************************************/
57 /* S t a t i c V a r i a b l e s */
58 /******************************************************************************/
59 
60 XrdSysMutex XrdOfsTPCAuth::authMutex;
61 XrdOfsTPCAuth *XrdOfsTPCAuth::authQ = 0;
62 
63 /******************************************************************************/
64 /* E x t e r n a l L i n k a g e s */
65 /******************************************************************************/
66 
67 void *XrdOfsTPCAuthttl(void *pp)
68 {
70  return (void *)0;
71 }
72 
73 /******************************************************************************/
74 /* A d d */
75 /******************************************************************************/
76 
78 {
79  XrdOfsTPCAuth *aP;
80  const char *eMsg;
81  char Buff[512];
82 
83 // Generate the origin information
84 //
85  if (!genOrg(Args.Usr, Buff, sizeof(Buff))) return Fatal(Args, Buff, EINVAL);
86  Args.Org = Buff;
87 
88 // Check if there is a matching authorization in the queue. If this is for a
89 // pending authorization, indicated that we now have one. Otherwise, consider
90 // this a potential security breach and cancel both autorizations.
91 //
92  authMutex.Lock();
93  if ((aP = Find(Args)))
94  {if (aP->Info.cbP)
95  {aP->expT = expT;
96  aP->Next = authQ; authQ = aP;
97  aP->Info.Reply(SFS_OK, 0, "", &authMutex);
98  return 1;
99  } else {
100  authMutex.UnLock();
101  return Fatal(Args, "duplicate athorization", EPROTO);
102  }
103  }
104 
105 // Set the copy authorization information
106 //
107  if ((eMsg = Info.Set(Args.Key, Buff, Args.Lfn, Args.Dst)))
108  {
109  authMutex.UnLock();
110  return Fatal(Args, eMsg, EINVAL);
111  }
112 
113 // Add this to queue
114 //
115  Next = authQ; authQ = this; inQ = 1;
116 
117 // All done
118 //
119  authMutex.UnLock();
120  return 1;
121 }
122 
123 /******************************************************************************/
124 /* D e l */
125 /******************************************************************************/
126 
128 {
129  XrdOfsTPCAuth *pP;
130 
131 // Remove from queue if we are still in the queue
132 //
133  authMutex.Lock();
134  if (inQ)
135  {if (this == authQ) authQ = Next;
136  else {pP = authQ;
137  while(pP && pP->Next != this) pP = pP->Next;
138  if (pP) pP->Next = Next;
139  }
140  inQ = 0;
141  }
142 
143 // Delete the element if possible
144 //
145  if (Refs <= 1) delete this;
146  else Refs--;
147  authMutex.UnLock();
148 }
149 
150 /******************************************************************************/
151 /* E x p i r e d */
152 /******************************************************************************/
153 
154 int XrdOfsTPCAuth::Expired(const char *Dst, int cnt)
155 {
156  char Buff[1024];
157 
158 // If there is a callback, tell the client they are no longer wanted
159 //
160  if (Info.cbP) Info.Reply(SFS_ERROR, EACCES, "tpc authorization expired");
161 
162 // Log this event
163 //
164  snprintf(Buff, sizeof(Buff), "tpc grant by %s expired for", Info.Org);
165  Buff[sizeof(Buff)-1] = 0;
166  OfsEroute.Emsg("TPC", Dst, Buff, Info.Lfn);
167 
168 // Count stats and return
169 //
170  if (cnt) OfsStats.Add(OfsStats.Data.numTPCexpr);
171  return 0;
172 }
173 
174 /******************************************************************************/
175 /* Private: F i n d */
176 /******************************************************************************/
177 
178 XrdOfsTPCAuth *XrdOfsTPCAuth::Find(XrdOfsTPC::Facts &Args)
179 {
180  XrdOfsTPCAuth *cP, *pP = 0;
181 
182 // Find matching entry
183 //
184  cP = authQ;
185  while(cP && !(cP->Info.Match(Args.Key, Args.Org, Args.Lfn, Args.Dst)))
186  {pP = cP; cP = cP->Next;}
187 
188 // Remove from queue if found
189 //
190  if (cP) {if (pP) pP->Next = cP->Next;
191  else authQ = cP->Next;
192  cP->inQ = 0;
193  }
194 
195 // Return result
196 //
197  return cP;
198 }
199 
200 /******************************************************************************/
201 /* G e t */
202 /******************************************************************************/
203 
205 {
206  XrdSysMutexHelper authMon(&authMutex);
207  XrdOfsTPCAuth *aP;
208  const char *eMsg;
209 
210 // Check if there is a matching authorization in the queue. If this is for a
211 // pending authorization, then consider this a potential security breach and
212 // cancel both requests. Otherwise, indicate that authorization is present.
213 //
214  if ((aP = Find(Args)))
215  {if (aP->Info.cbP)
216  {aP->Info.Reply(SFS_ERROR, EPROTO, "duplicate tpc auth request");
217  return Fatal(Args, "duplicate tpc auth request", EPROTO);
218  } else {
219  aP->Refs++;
220  *theTPC = aP;
221  return SFS_OK;
222  }
223  }
224 
225 // Add this request as a pending authorization to the queue
226 //
227  if (!(aP = new XrdOfsTPCAuth(Cfg.maxTTL)))
228  return Fatal(Args, "insufficient memory", ENOMEM);
229 
230 // Set the copy authorization information
231 //
232  if ((eMsg = aP->Info.Set(Args.Key, Args.Org, Args.Lfn, Args.Dst)))
233  {delete aP;
234  return Fatal(Args, eMsg, EINVAL);
235  }
236 
237 // Create a callback
238 //
239  if (aP->Info.SetCB(Args.eRR)) {delete aP; return SFS_ERROR;}
240 
241 // Add it to the queue
242 //
243  aP->Next = authQ; authQ = aP;
244 
245 // Return result
246 //
247  *theTPC = aP;
248  aP->Refs = 0;
249  aP->Info.Engage();
250  return SFS_STARTED;
251 }
252 
253 /******************************************************************************/
254 /* R u n T T L */
255 /******************************************************************************/
256 
258 {
259  XrdOfsTPCAuth *cP, *pP, *nP;
260  time_t eNow;
261  int eWait, eDiff, numExp;
262 
263 // Start the expiration thread
264 //
265  if (Init)
266  {pthread_t tid;
267  int rc;
268  if ((rc = XrdSysThread::Run(&tid,XrdOfsTPCAuthttl,0,0,"TPC ttl runner")))
269  OfsEroute.Emsg("TPC", rc, "create tpc ttl runner thread");
270  return (rc ? 0 : 1);
271  }
272 
273 // Find all expired entries and remove them
274 //
275 do{authMutex.Lock();
276  cP = authQ; pP = 0;
277  eNow = time(0); eWait = Cfg.maxTTL; numExp = 0;
278  while(cP)
279  {if (eNow < cP->expT)
280  {eDiff = cP->expT - eNow;
281  if (eDiff < eWait) eWait = eDiff;
282  pP = cP; cP = cP->Next;
283  }
284  else {if (pP) pP->Next = cP->Next;
285  else authQ = cP->Next;
286  cP->Expired("localhost", 0); numExp++;
287  nP = cP->Next;
288  if (cP->Refs < 1) delete cP;
289  cP = nP;
290  }
291  }
292  authMutex.UnLock();
293 
294 // Add number of expirations to statistics
295 //
296  if (numExp)
297  {OfsStats.sdMutex.Lock();
298  OfsStats.Data.numTPCexpr += numExp;
300  }
301 
302 // Wait as long as possible for a recan
303 //
304  XrdSysTimer::Snooze(eWait);
305  } while(1);
306 }
void Fatal(const char *op, const char *target)
Definition: XrdCrc32c.cc:58
void * XrdOfsTPCAuthttl(void *pp)
XrdOfsStats OfsStats
Definition: XrdOfs.cc:113
XrdSysError OfsEroute
@ Info
#define eMsg(x)
#define SFS_ERROR
#define SFS_STARTED
#define SFS_OK
struct XrdOfsStats::StatsData Data
void Add(int &Cntr)
Definition: XrdOfsStats.hh:62
XrdSysMutex sdMutex
Definition: XrdOfsStats.hh:60
static int Get(Facts &Args, XrdOfsTPCAuth **theTPC)
int Add(Facts &Args)
static int RunTTL(int Init)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
static void Snooze(int seconds)
Definition: XrdSysTimer.cc:168
XrdOfsTPCConfig Cfg
Definition: XrdOfsTPC.cc:85
const XrdSecEntity * Usr
Definition: XrdOfsTPC.hh:57
const char * Key
Definition: XrdOfsTPC.hh:52
const char * Org
Definition: XrdOfsTPC.hh:55
const char * Lfn
Definition: XrdOfsTPC.hh:53
XrdOucErrInfo * eRR
Definition: XrdOfsTPC.hh:58
const char * Dst
Definition: XrdOfsTPC.hh:56