XRootD
Loading...
Searching...
No Matches
XrdSecsssKT Class Reference

#include <XrdSecsssKT.hh>

+ Collaboration diagram for XrdSecsssKT:

Classes

class  ktEnt
 

Public Types

enum  xMode {
  isAdmin = 0 ,
  isClient ,
  isServer
}
 

Public Member Functions

 XrdSecsssKT (XrdOucErrInfo *, const char *, xMode, int refr=60 *60)
 
 ~XrdSecsssKT ()
 
void addKey (ktEnt &ktNew)
 
int delKey (ktEnt &ktDel)
 
int getKey (ktEnt &ktEql, bool andKeyID=false)
 
ktEntkeyList ()
 
void Refresh ()
 
time_t RefrTime ()
 
int Rewrite (int Keep, int &numKeys, int &numTot, int &numExp)
 
int Same (const char *path)
 
void setPath (const char *Path)
 

Static Public Member Functions

static char * genFN ()
 
static void genKey (char *Buff, int blen)
 

Detailed Description

Definition at line 40 of file XrdSecsssKT.hh.

Member Enumeration Documentation

◆ xMode

Enumerator
isAdmin 
isClient 
isServer 

Definition at line 114 of file XrdSecsssKT.hh.

Constructor & Destructor Documentation

◆ XrdSecsssKT()

XrdSecsssKT::XrdSecsssKT ( XrdOucErrInfo * eInfo,
const char * kPath,
xMode oMode,
int refr = 60*60 )

Definition at line 78 of file XrdSecsssKT.cc.

80{
81 static const char *eText = "Unable to start keytab refresh thread";
82 const char *devRand = "/dev/urandom";
83 struct stat sbuf;
84 int retc;
85
86// Do some common initialization
87//
88 ktRefID= 0;
89 ktPath = (kPath ? strdup(kPath) : 0);
90 ktList = 0; kthiID = 0; ktMode = oMode; ktRefT = (time_t)refrInt;
91 if (eInfo) eInfo->setErrCode(0);
92
93// Prepare /dev/random if we have it
94//
95 if (stat(devRand, &sbuf)) devRand = "/dev/random";
96 if ((randFD = open(devRand, O_RDONLY)) < 0
97 && oMode != isClient && errno != ENOENT)
98 eMsg("sssKT",errno,"Unable to generate random key"," opening ",devRand);
99
100// First get the stat information for the file
101//
102 if (!kPath)
103 {if (oMode != isAdmin)
104 {eMsg("sssKT", -1, "Keytable path not specified.");
105 if (eInfo) eInfo->setErrInfo(EINVAL, "Keytable path missing.");
106 return;
107 }
108 sbuf.st_mtime = 0; sbuf.st_mode = S_IRWXU;
109 } else if (stat(kPath, &sbuf))
110 {if (eInfo) eInfo->setErrInfo(errno, "Keytable not found");
111 if (errno != ENOENT || oMode != isAdmin)
112 eMsg("sssKT",errno,"Unable process keytable ",kPath);
113 return;
114 }
115
116// Now read in the whole key table and start possible refresh thread
117//
118 if ((ktList = getKeyTab(eInfo, sbuf.st_mtime, sbuf.st_mode))
119 && (oMode != isAdmin) && (!eInfo || eInfo->getErrInfo() == 0))
120 {if ((retc = XrdSysThread::Run(&ktRefID,XrdSecsssKTRefresh, (void *)this,
121 XRDSYSTHREAD_HOLD)))
122 {eMsg("sssKT", errno, eText); eInfo->setErrInfo(-1, eText);}
123 }
124}
#define open
Definition XrdPosix.hh:76
#define stat(a, b)
Definition XrdPosix.hh:101
#define eMsg(x)
if(ec< 0) ec
int setErrInfo(int code, const char *emsg)
int setErrCode(int code)

References eMsg, XrdOucErrInfo::getErrInfo(), isAdmin, isClient, open, XrdSysThread::Run(), XrdOucErrInfo::setErrCode(), XrdOucErrInfo::setErrInfo(), stat, XrdSecsssKTRefresh(), and XRDSYSTHREAD_HOLD.

+ Here is the call graph for this function:

◆ ~XrdSecsssKT()

XrdSecsssKT::~XrdSecsssKT ( )

Definition at line 130 of file XrdSecsssKT.cc.

131{
132 ktEnt *ktP;
133 void *Dummy;
134
135// Lock against others
136//
137 myMutex.Lock();
138
139// Kill the refresh thread first
140//
141 if (ktRefID && !XrdSysThread::Kill(ktRefID))
142 XrdSysThread::Join(ktRefID, &Dummy);
143 ktRefID= 0;
144
145// Now we can safely clean up
146//
147 if (ktPath) {free(ktPath); ktPath = 0;}
148
149 while((ktP = ktList)) {ktList = ktList->Next; delete ktP;}
150
151 myMutex.UnLock();
152}
static int Join(pthread_t tid, void **ret)
static int Kill(pthread_t tid)

References XrdSysThread::Join(), XrdSysThread::Kill(), XrdSysMutex::Lock(), XrdSecsssKT::ktEnt::Next, and XrdSysMutex::UnLock().

+ Here is the call graph for this function:

Member Function Documentation

◆ addKey()

void XrdSecsssKT::addKey ( ktEnt & ktNew)

Definition at line 158 of file XrdSecsssKT.cc.

159{
160 ktEnt *ktPP = 0, *ktP;
161
162// Generate a key for this entry
163//
164 genKey(ktNew.Data.Val, ktNew.Data.Len);
165 ktNew.Data.Crt = time(0);
166 ktNew.Data.ID = static_cast<long long>(ktNew.Data.Crt & 0x7fffffff) << 32L
167 | static_cast<long long>(++kthiID);
168
169// Locate place to insert this key
170//
171 ktP = ktList;
172 while(ktP && !isKey(*ktP, &ktNew, 0)) {ktPP = ktP; ktP = ktP->Next;}
173
174// Now chain in the entry
175//
176 if (ktPP) ktPP->Next = &ktNew;
177 else ktList = &ktNew;
178 ktNew.Next = ktP;
179}
static void genKey(char *Buff, int blen)

References XrdSecsssKT::ktEnt::ktData::Crt, XrdSecsssKT::ktEnt::Data, genKey(), XrdSecsssKT::ktEnt::ktData::ID, XrdSecsssKT::ktEnt::ktData::Len, XrdSecsssKT::ktEnt::Next, and XrdSecsssKT::ktEnt::ktData::Val.

Referenced by XrdSecsssAdmin_addKey().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ delKey()

int XrdSecsssKT::delKey ( ktEnt & ktDel)

Definition at line 185 of file XrdSecsssKT.cc.

186{
187 ktEnt *ktN, *ktPP = 0, *ktP = ktList;
188 int nDel = 0;
189
190// Remove all matching keys
191//
192 while(ktP)
193 {if (isKey(ktDel, ktP))
194 {if (ktPP) ktPP->Next = ktP->Next;
195 else ktList = ktP->Next;
196 ktN = ktP; ktP = ktP->Next; delete ktN; nDel++;
197 } else {ktPP = ktP; ktP = ktP->Next;}
198 }
199
200 return nDel;
201}

References XrdSecsssKT::ktEnt::Next.

Referenced by XrdSecsssAdmin_delKey().

+ Here is the caller graph for this function:

◆ genFN()

char * XrdSecsssKT::genFN ( )
static

Definition at line 249 of file XrdSecsssKT.cc.

250{
251 static char fnbuff[1040];
252 const char *pfx;
253
254// Get the path prefix
255//
256 if (!(pfx = getenv("HOME")) || !*pfx) pfx = "";
257
258// Format the name
259//
260 snprintf(fnbuff, sizeof(fnbuff), "%s/.xrd/sss.keytab", pfx);
261 return fnbuff;
262}

Referenced by XrdSecProtocolsss::Load_Client(), XrdSecProtocolsss::Load_Server(), and main().

+ Here is the caller graph for this function:

◆ genKey()

void XrdSecsssKT::genKey ( char * Buff,
int blen )
static

Definition at line 268 of file XrdSecsssKT.cc.

269{
270 struct timeval tval;
271 int kTemp;
272
273// See if we can directly service the key. Make sure that we get some entropy
274// because some /dev/random devices start out really cold.
275//
276 if (randFD >= 0)
277 {char *buffP = kBP;
278 int i, Got, Want = kLen, zcnt = 0, maxZ = kLen*25/100;
279 while(Want)
280 do { {do {Got = read(randFD, buffP, Want);}
281 while(Got < 0 && errno == EINTR);
282 if (Got > 0) {buffP += Got; Want -= Got;}
283 }
284 } while(Got > 0 && Want);
285 if (!Want)
286 {for (i = 0; i < kLen; i++) if (!kBP[i]) zcnt++;
287 if (zcnt <= maxZ) return;
288 }
289 }
290
291// Generate a seed
292//
293 gettimeofday(&tval, 0);
294 if (tval.tv_usec == 0) tval.tv_usec = tval.tv_sec;
295 tval.tv_usec = tval.tv_usec ^ getpid();
296 srand48(static_cast<long>(tval.tv_usec));
297
298// Now generate the key (we ignore he fact that longs may be 4 or 8 bytes)
299//
300 while(kLen > 0)
301 {kTemp = mrand48();
302 memcpy(kBP, &kTemp, (4 > kLen ? kLen : 4));
303 kBP += 4; kLen -= 4;
304 }
305}
#define read(a, b, c)
Definition XrdPosix.hh:82

References read.

Referenced by addKey().

+ Here is the caller graph for this function:

◆ getKey()

int XrdSecsssKT::getKey ( ktEnt & ktEql,
bool andKeyID = false )

Definition at line 207 of file XrdSecsssKT.cc.

208{
209 ktEnt *ktP, *ktN;
210
211// Lock the keytab to prevent modification
212//
213 myMutex.Lock();
214 ktP = ktList;
215
216// Find first key by key name (used normally by clients), by keyID, or both
217//
218 if (!*theEnt.Data.Name)
219 {if (theEnt.Data.ID >= 0)
220 while(ktP && ktP->Data.ID != theEnt.Data.ID) ktP = ktP->Next;
221 }
222 else if (andKeyID)
223 {while((ktP && ktP->Data.ID != theEnt.Data.ID)
224 || strcmp(ktP->Data.Name,theEnt.Data.Name)) ktP=ktP->Next;
225 }
226 else {while(ktP && strcmp(ktP->Data.Name,theEnt.Data.Name)) ktP=ktP->Next;
227 while(ktP && ktP->Data.Exp <= time(0))
228 {if (!(ktN=ktP->Next)
229 || strcmp(ktN->Data.Name,theEnt.Data.Name)) break;
230 ktP = ktN;
231 }
232 }
233
234// If we found a match, export it
235//
236 if (ktP) theEnt = *ktP;
237 myMutex.UnLock();
238
239// Indicate if key expired
240//
241 if (!ktP) return ENOENT;
242 return (theEnt.Data.Exp && theEnt.Data.Exp <= time(0) ? -1 : 0);
243}

References XrdSecsssKT::ktEnt::Data, XrdSecsssKT::ktEnt::ktData::Exp, XrdSecsssKT::ktEnt::ktData::ID, XrdSysMutex::Lock(), XrdSecsssKT::ktEnt::ktData::Name, XrdSecsssKT::ktEnt::Next, and XrdSysMutex::UnLock().

Referenced by XrdSecProtocolsss::getCredentials().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ keyList()

ktEnt * XrdSecsssKT::keyList ( )
inline

Definition at line 101 of file XrdSecsssKT.hh.

101{return ktList;}

Referenced by XrdSecsssAdmin_delKey(), XrdSecsssAdmin_insKey(), and XrdSecsssAdmin_lstKey().

+ Here is the caller graph for this function:

◆ Refresh()

void XrdSecsssKT::Refresh ( )

Definition at line 311 of file XrdSecsssKT.cc.

312{
313 XrdOucErrInfo eInfo;
314 ktEnt *ktNew, *ktOld, *ktNext;
315 struct stat sbuf;
316 int retc = 0;
317
318// Get change time of keytable and if changed, update it
319//
320 if (stat(ktPath, &sbuf) == 0)
321 {if (sbuf.st_mtime == ktMtime) return;
322 if ((ktNew = getKeyTab(&eInfo, sbuf.st_mtime, sbuf.st_mode))
323 && eInfo.getErrInfo() == 0)
324 {myMutex.Lock(); ktOld = ktList; ktList = ktNew; myMutex.UnLock();
325 } else ktOld = ktNew;
326 while(ktOld) {ktNext = ktOld->Next; delete ktOld; ktOld = ktNext;}
327 if ((retc == eInfo.getErrInfo()) == 0) return;
328 } else retc = errno;
329
330// Refresh failed
331//
332 eMsg("Refresh",retc,"Unable to refresh keytable",ktPath);
333}

References eMsg, XrdOucErrInfo::getErrInfo(), XrdSysMutex::Lock(), XrdSecsssKT::ktEnt::Next, stat, and XrdSysMutex::UnLock().

Referenced by XrdSecsssKTRefresh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ RefrTime()

time_t XrdSecsssKT::RefrTime ( )
inline

Definition at line 105 of file XrdSecsssKT.hh.

105{return ktRefT;}

Referenced by XrdSecsssKTRefresh().

+ Here is the caller graph for this function:

◆ Rewrite()

int XrdSecsssKT::Rewrite ( int Keep,
int & numKeys,
int & numTot,
int & numExp )

Definition at line 339 of file XrdSecsssKT.cc.

340{
341 char tmpFN[2048], buff[2048], kbuff[4096], *Slash;
342 int ktFD, numID = 0, n, retc = 0;
343 ktEnt ktCurr, *ktP, *ktN;
344 mode_t theMode = fileMode(ktPath);
345
346// Invoke mkpath in case the path is missing
347//
348 strcpy(tmpFN, ktPath);
349 if ((Slash = rindex(tmpFN, '/'))) *Slash = '\0';
350 retc = XrdOucUtils::makePath(tmpFN,S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
351 if (retc) return (retc < 0 ? -retc : retc);
352 if (Slash) *Slash = '/';
353
354// Construct temporary filename
355//
356 sprintf(buff, ".%d", static_cast<int>(getpid()));
357 strcat(tmpFN, buff);
358
359// Open the file for output
360//
361 if ((ktFD = open(tmpFN, O_WRONLY|O_CREAT|O_TRUNC, theMode)) < 0)
362 return errno;
363
364// Write all of the keytable
365//
366 ktCurr.Data.Name[0] = ktCurr.Data.User[0] = ktCurr.Data.Grup[0] = 3;
367 ktN = ktList; numKeys = numTot = numExp = 0;
368 while((ktP = ktN))
369 {ktN = ktN->Next; numTot++;
370 if (ktP->Data.Name[0] == '\0') continue;
371 if (ktP->Data.Exp && ktP->Data.Exp <= time(0)) {numExp++; continue;}
372 if (!isKey(ktCurr, ktP, 0)) {ktCurr.NUG(ktP); numID = 0;}
373 else if (Keep && numID >= Keep) continue;
374 n = sprintf(buff, "%s0 u:%s g:%s n:%s N:%lld c:%lld e:%lld f:%lld k:",
375 (numKeys ? "\n" : ""),
376 ktP->Data.User,ktP->Data.Grup,ktP->Data.Name,ktP->Data.ID,
377 (long long) ktP->Data.Crt, (long long) ktP->Data.Exp,
378 ktP->Data.Flags);
379 numID++; numKeys++; keyB2X(ktP, kbuff);
380 if (write(ktFD, buff, n) < 0
381 || write(ktFD, kbuff, ktP->Data.Len*2) < 0) break;
382 }
383
384// Check for errors
385//
386 if (ktP) retc = errno;
387 else if (!numKeys) retc = ENODATA;
388
389// Atomically trounce the original file if we can
390//
391 close(ktFD);
392 if (!retc && rename(tmpFN, ktPath) < 0) retc = errno;
393
394// All done
395//
396 unlink(tmpFN);
397 return retc;
398}
#define ENODATA
#define close(a)
Definition XrdPosix.hh:48
#define write(a, b, c)
Definition XrdPosix.hh:115
#define unlink(a)
Definition XrdPosix.hh:113
#define rename(a, b)
Definition XrdPosix.hh:92
static int makePath(char *path, mode_t mode, bool reset=false)

References close, XrdSecsssKT::ktEnt::ktData::Crt, XrdSecsssKT::ktEnt::Data, ENODATA, XrdSecsssKT::ktEnt::ktData::Exp, XrdSecsssKT::ktEnt::ktData::Flags, XrdSecsssKT::ktEnt::ktData::Grup, XrdSecsssKT::ktEnt::ktData::ID, XrdSecsssKT::ktEnt::ktData::Len, XrdOucUtils::makePath(), XrdSecsssKT::ktEnt::ktData::Name, XrdSecsssKT::ktEnt::Next, XrdSecsssKT::ktEnt::NUG(), open, rename, unlink, XrdSecsssKT::ktEnt::ktData::User, and write.

Referenced by XrdSecsssAdmin_addKey(), XrdSecsssAdmin_delKey(), and XrdSecsssAdmin_insKey().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Same()

int XrdSecsssKT::Same ( const char * path)
inline

Definition at line 109 of file XrdSecsssKT.hh.

109{return (ktPath && !strcmp(ktPath, path));}

Referenced by XrdSecProtocolsss::Init_Client().

+ Here is the caller graph for this function:

◆ setPath()

void XrdSecsssKT::setPath ( const char * Path)
inline

Definition at line 111 of file XrdSecsssKT.hh.

112 {if (ktPath) free(ktPath); ktPath = strdup(Path);}
XrdOucString Path

References Path.

Referenced by XrdSecsssAdmin_insKey().

+ Here is the caller graph for this function:

The documentation for this class was generated from the following files: