-
Notifications
You must be signed in to change notification settings - Fork 149
/
XrdSecProtocolgsi.hh
546 lines (491 loc) · 24.2 KB
/
XrdSecProtocolgsi.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
/******************************************************************************/
/* */
/* X r d S e c P r o t o c o l g s i . h h */
/* */
/* (c) 2005 G. Ganis / CERN */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/* */
/******************************************************************************/
#include <ctime>
#include <memory>
#include "XrdNet/XrdNetAddrInfo.hh"
#include "XrdOuc/XrdOucErrInfo.hh"
#include "XrdOuc/XrdOucGMap.hh"
#include "XrdOuc/XrdOucHash.hh"
#include "XrdOuc/XrdOucString.hh"
#include "XrdOuc/XrdOucTokenizer.hh"
#include "XrdSys/XrdSysPthread.hh"
#include "XrdSec/XrdSecInterface.hh"
#include "XrdSecgsi/XrdSecgsiTrace.hh"
#include "XrdSut/XrdSutCache.hh"
#include "XrdSut/XrdSutPFEntry.hh"
#include "XrdSut/XrdSutPFile.hh"
#include "XrdSut/XrdSutBuffer.hh"
#include "XrdSut/XrdSutRndm.hh"
#include "XrdCrypto/XrdCryptoAux.hh"
#include "XrdCrypto/XrdCryptoCipher.hh"
#include "XrdCrypto/XrdCryptoFactory.hh"
#include "XrdCrypto/XrdCryptoX509Crl.hh"
#include "XrdCrypto/XrdCryptogsiX509Chain.hh"
/******************************************************************************/
/* D e f i n e s */
/******************************************************************************/
typedef XrdOucString String;
typedef XrdCryptogsiX509Chain X509Chain;
#define XrdSecPROTOIDENT "gsi"
#define XrdSecPROTOIDLEN sizeof(XrdSecPROTOIDENT)
#define XrdSecgsiVERSION 10600
#define XrdSecNOIPCHK 0x0001
#define XrdSecDEBUG 0x1000
#define XrdCryptoMax 10
#define kMAXBUFLEN 1024
#define XrdSecgsiVersDHsigned 10400 // Version at which started signing
// of server DH parameters
#define XrdSecgsiVersCertKey 10600 // Version at which started supporting
// authentication with cert/key only
//
// Message codes either returned by server or included in buffers
enum kgsiStatus {
kgST_error = -1, // error occurred
kgST_ok = 0, // ok
kgST_more = 1 // need more info
};
// Client steps
enum kgsiClientSteps {
kXGC_none = 0,
kXGC_certreq = 1000, // 1000: request server certificate
kXGC_cert, // 1001: packet with (proxy) certificate
kXGC_sigpxy, // 1002: packet with signed proxy certificate
kXGC_reserved //
};
// Server steps
enum kgsiServerSteps {
kXGS_none = 0,
kXGS_init = 2000, // 2000: fake code used the first time
kXGS_cert, // 2001: packet with certificate
kXGS_pxyreq, // 2002: packet with proxy req to be signed
kXGS_reserved //
};
// Handshake options
enum kgsiHandshakeOpts {
kOptsDlgPxy = 1, // 0x0001: Ask for a delegated proxy
kOptsFwdPxy = 2, // 0x0002: Forward local proxy
kOptsSigReq = 4, // 0x0004: Accept to sign delegated proxy
kOptsSrvReq = 8, // 0x0008: Server request for delegated proxy
kOptsPxFile = 16, // 0x0010: Save delegated proxies in file
kOptsDelChn = 32, // 0x0020: Delete chain
kOptsPxCred = 64, // 0x0040: Save delegated proxies as credentials
kOptsCreatePxy = 128 // 0x0080: Request a client proxy
};
// Error codes
enum kgsiErrors {
kGSErrParseBuffer = 10000, // 10000
kGSErrDecodeBuffer, // 10001
kGSErrLoadCrypto, // 10002
kGSErrBadProtocol, // 10003
kGSErrCreateBucket, // 10004
kGSErrDuplicateBucket, // 10005
kGSErrCreateBuffer, // 10006
kGSErrSerialBuffer, // 10007
kGSErrGenCipher, // 10008
kGSErrExportPuK, // 10009
kGSErrEncRndmTag, // 10010
kGSErrBadRndmTag, // 10011
kGSErrNoRndmTag, // 10012
kGSErrNoCipher, // 10013
kGSErrNoCreds, // 10014
kGSErrBadOpt, // 10015
kGSErrMarshal, // 10016
kGSErrUnmarshal, // 10017
kGSErrSaveCreds, // 10018
kGSErrNoBuffer, // 10019
kGSErrRefCipher, // 10020
kGSErrNoPublic, // 10021
kGSErrAddBucket, // 10022
kGSErrFinCipher, // 10023
kGSErrInit, // 10024
kGSErrBadCreds, // 10025
kGSErrError // 10026
};
#define REL1(x) { if (x) delete x; }
#define REL2(x,y) { if (x) delete x; if (y) delete y; }
#define REL3(x,y,z) { if (x) delete x; if (y) delete y; if (z) delete z; }
#define SafeDelete(x) { if (x) {delete x ; x = 0;} }
#define SafeDelArray(x) { if (x) {delete [] x ; x = 0;} }
#define SafeFree(x) { if (x) {free(x) ; x = 0;} }
// External functions for generic mapping
typedef char *(*XrdSecgsiGMAP_t)(const char *, int);
typedef int (*XrdSecgsiAuthz_t)(XrdSecEntity &);
typedef int (*XrdSecgsiAuthzInit_t)(const char *);
typedef int (*XrdSecgsiAuthzKey_t)(XrdSecEntity &, char **);
// VOMS extraction
typedef XrdSecgsiAuthz_t XrdSecgsiVOMS_t;
typedef XrdSecgsiAuthzInit_t XrdSecgsiVOMSInit_t;
//
// This a small class to set the relevant options in one go
//
class XrdOucGMap;
class XrdOucTrace;
class gsiOptions {
public:
short debug; // [cs] debug flag
char mode; // [cs] 'c' or 's'
char *clist; // [s] list of crypto modules ["ssl" ]
char *certdir;// [cs] dir with CA info [/etc/grid-security/certificates]
char *crldir; // [cs] dir with CRL info [/etc/grid-security/certificates]
char *crlext; // [cs] extension of CRL files [.r0]
char *cert; // [s] server certificate [/etc/grid-security/root/rootcert.pem]
// [c] user certificate [$HOME/.globus/usercert.pem]
char *key; // [s] server private key [/etc/grid-security/root/rootkey.pem]
// [c] user private key [$HOME/.globus/userkey.pem]
char *cipher; // [s] list of ciphers [aes-128-cbc:bf-cbc:des-ede3-cbc]
char *md; // [s] list of MDs [sha256:md5]
int crl; // [cs] check level of CRL's [1]
int ca; // [cs] verification level of CA's [1]
int crlrefresh; // [cs] CRL refresh or expiration period in secs [1 day]
char *proxy; // [c] user proxy [/tmp/x509up_u<uid>]
char *valid; // [c] proxy validity [12:00]
int deplen; // [c] depth of signature path for proxies [0]
int bits; // [c] bits in PKI for proxies [512]
char *gridmap;// [s] gridmap file [/etc/grid-security/gridmap]
int gmapto; // [s] validity in secs of grid-map cache entries [600 s]
char *gmapfun;// [s] file with the function to map DN to usernames [0]
char *gmapfunparms;// [s] parameters for the function to map DN to usernames [0]
char *authzfun;// [s] file with the function to fill entities [0]
char *authzfunparms;// [s] parameters for the function to fill entities [0]
int authzcall; // [s] when to call authz function [1 -> always]
int authzto; // [s] validity in secs of authz cache entries [-1 => unlimited]
int ogmap; // [s] gridmap file checking option
int dlgpxy; // [c] explicitely ask the creation of a delegated proxy; default 0
// [s] ask client for proxies; default: do not accept delegated proxies
int sigpxy; // [c] accept delegated proxy requests
int createpxy; // [c] force client proxy authentications
char *srvnames;// [c] '|' separated list of allowed server names
char *exppxy; // [s] template for the exported file with proxies
int authzpxy; // [s] if 1 make proxy available in exported form in the 'endorsement'
// field of the XrdSecEntity object for use in XrdAcc
int vomsat; // [s] 0 do not look for; 1 extract if any
char *vomsfun;// [s] file with the function to fill VOMS [0]
char *vomsfunparms;// [s] parameters for the function to fill VOMS [0]
int moninfo; // [s] 0 do not look for; 1 use DN as default
int hashcomp; // [cs] 1 send hash names with both algorithms; 0 send only the default [1]
bool trustdns; // [cs] 'true' if DNS is trusted [true]
gsiOptions() { debug = -1; mode = 's'; clist = 0;
certdir = 0; crldir = 0; crlext = 0; cert = 0; key = 0;
cipher = 0; md = 0; ca = 1 ; crl = 1; crlrefresh = 86400;
proxy = 0; valid = 0; deplen = 0; bits = 512;
gridmap = 0; gmapto = 600;
gmapfun = 0; gmapfunparms = 0; authzfun = 0; authzfunparms = 0;
authzto = -1; authzcall = 1;
ogmap = 1; dlgpxy = 0; sigpxy = 1; srvnames = 0;
exppxy = 0; authzpxy = 0;
vomsat = 1; vomsfun = 0; vomsfunparms = 0; moninfo = 0;
hashcomp = 1; trustdns = true; createpxy = 1;}
virtual ~gsiOptions() { } // Cleanup inside XrdSecProtocolgsiInit
void Print(XrdOucTrace *t); // Print summary of gsi option status
};
class XrdSecProtocolgsi;
class gsiHSVars;
// From a proxy query
typedef struct {
X509Chain *chain;
XrdCryptoRSA *ksig;
XrdSutBucket *cbck;
} ProxyOut_t;
// To query proxies
typedef struct {
const char *cert;
const char *key;
const char *certdir;
const char *out;
const char *valid;
int deplen;
int bits;
bool createpxy;
} ProxyIn_t;
template<class T>
class GSIStack {
public:
void Add(T *t) {
char k[40]; snprintf(k, 40, "%p", t);
mtx.Lock();
if (!stack.Find(k)) stack.Add(k, t, 0, Hash_count); // We need an additional count
stack.Add(k, t, 0, Hash_count);
mtx.UnLock();
}
void Del(T *t) {
char k[40]; snprintf(k, 40, "%p", t);
mtx.Lock();
if (stack.Find(k)) stack.Del(k, Hash_count);
mtx.UnLock();
}
private:
XrdSysMutex mtx;
XrdOucHash<T> stack;
};
/******************************************************************************/
/* X r d S e c P r o t o c o l g s i C l a s s */
/******************************************************************************/
class XrdSecProtocolgsi : public XrdSecProtocol
{
friend class gsiOptions;
friend class gsiHSVars;
public:
int Authenticate (XrdSecCredentials *cred,
XrdSecParameters **parms,
XrdOucErrInfo *einfo=0);
XrdSecCredentials *getCredentials(XrdSecParameters *parm=0,
XrdOucErrInfo *einfo=0);
XrdSecProtocolgsi(int opts, const char *hname, XrdNetAddrInfo &endPoint,
const char *parms = 0);
virtual ~XrdSecProtocolgsi() {} // Delete() does it all
// Initialization methods
static char *Init(gsiOptions o, XrdOucErrInfo *erp);
void Delete();
// Encrypt / Decrypt methods
int Encrypt(const char *inbuf, int inlen,
XrdSecBuffer **outbuf);
int Decrypt(const char *inbuf, int inlen,
XrdSecBuffer **outbuf);
// Sign / Verify methods
int Sign(const char *inbuf, int inlen,
XrdSecBuffer **outbuf);
int Verify(const char *inbuf, int inlen,
const char *sigbuf, int siglen);
// Export session key
int getKey(char *kbuf=0, int klen=0);
// Import a key
int setKey(char *kbuf, int klen);
// Enable tracing
static XrdOucTrace *EnableTracing();
private:
XrdNetAddrInfo epAddr;
// Static members initialized at startup
static XrdSysMutex gsiContext;
static String CAdir;
static String CRLdir;
static String DefCRLext;
static String SrvCert;
static String SrvKey;
static String UsrProxy;
static String UsrCert;
static String UsrKey;
static String PxyValid;
static int DepLength;
static int DefBits;
static int CACheck;
static int CRLCheck;
static int CRLDownload;
static int CRLRefresh;
static String DefCrypto;
static String DefCipher;
static String DefMD;
static String DefError;
static String GMAPFile;
static int GMAPOpt;
static bool GMAPuseDNname;
static int GMAPCacheTimeOut;
static XrdSecgsiGMAP_t GMAPFun;
static XrdSecgsiAuthz_t AuthzFun;
static XrdSecgsiAuthzKey_t AuthzKey;
static int AuthzCertFmt;
static int AuthzCacheTimeOut;
static int PxyReqOpts;
static int AuthzPxyWhat;
static int AuthzPxyWhere;
static int AuthzAlways;
static String SrvAllowedNames;
static int VOMSAttrOpt;
static XrdSecgsiVOMS_t VOMSFun;
static int VOMSCertFmt;
static int MonInfoOpt;
static bool HashCompatibility;
static bool TrustDNS;
//
// Crypto related info
static int ncrypt; // Number of factories
static XrdCryptoFactory *cryptF[XrdCryptoMax]; // their hooks
static int cryptID[XrdCryptoMax]; // their IDs
static String cryptName[XrdCryptoMax]; // their names
static XrdCryptoCipher *refcip[XrdCryptoMax]; // ref for session ciphers
//
// Caches
static XrdSutCache cacheCA; // Info about trusted CA's
static XrdSutCache cacheCert; // Server certificates info cache
static XrdSutCache cachePxy; // Client proxies cache;
static XrdSutCache cacheGMAPFun; // Cache for entries mapped by GMAPFun
static XrdSutCache cacheAuthzFun; // Cache for entities filled by AuthzFun
//
// Services
static XrdOucGMap *servGMap; // Grid mapping service
//
// CA and CRL stacks
static GSIStack<XrdCryptoX509Chain> stackCA; // Stack of CA in use
static std::unique_ptr<GSIStack<XrdCryptoX509Crl>> stackCRL; // Stack of CRL in use
//
// GMAP control vars
static time_t lastGMAPCheck; // time of last check on GMAP
static XrdSysMutex mutexGMAP; // mutex to control GMAP reloads
//
// Running options / settings
static int Debug; // [CS] Debug level
static bool Server; // [CS] If server mode
static int TimeSkew; // [CS] Allowed skew in secs for time stamps
//
// for error logging and tracing
static XrdSysLogger Logger;
static XrdSysError eDest;
static XrdOucTrace *GSITrace;
// Information local to this instance
int options;
XrdCryptoFactory *sessionCF; // Chosen crypto factory
XrdCryptoCipher *sessionKey; // Session Key (result of the handshake)
XrdSutBucket *bucketKey; // Bucket with the key in export form
XrdCryptoMsgDigest *sessionMD; // Message Digest instance
XrdCryptoRSA *sessionKsig; // RSA key to sign
XrdCryptoRSA *sessionKver; // RSA key to verify
X509Chain *proxyChain; // Chain with the delegated proxy on servers
bool srvMode; // TRUE if server mode
char *expectedHost; // Expected hostname if TrustDNS is enabled.
bool useIV; // Use a non-zeroed unique IV in cipher enc/dec operations
// Temporary Handshake local info
gsiHSVars *hs;
// Parsing received buffers: client
int ParseClientInput(XrdSutBuffer *br, XrdSutBuffer **bm,
String &emsg);
int ClientDoInit(XrdSutBuffer *br, XrdSutBuffer **bm,
String &cmsg);
int ClientDoCert(XrdSutBuffer *br, XrdSutBuffer **bm,
String &cmsg);
int ClientDoPxyreq(XrdSutBuffer *br, XrdSutBuffer **bm,
String &cmsg);
// Parsing received buffers: server
int ParseServerInput(XrdSutBuffer *br, XrdSutBuffer **bm,
String &cmsg);
int ServerDoCertreq(XrdSutBuffer *br, XrdSutBuffer **bm,
String &cmsg);
int ServerDoCert(XrdSutBuffer *br, XrdSutBuffer **bm,
String &cmsg);
int ServerDoSigpxy(XrdSutBuffer *br, XrdSutBuffer **bm,
String &cmsg);
// Auxilliary functions
int ParseCrypto(String cryptlist);
int ParseCAlist(String calist);
// Load CA certificates
static int GetCA(const char *cahash,
XrdCryptoFactory *cryptof, gsiHSVars *hs = 0);
static String GetCApath(const char *cahash);
static bool VerifyCA(int opt, X509Chain *cca, XrdCryptoFactory *cf);
static int VerifyCRL(XrdCryptoX509Crl *crl, XrdCryptoX509 *xca, XrdOucString crldir,
XrdCryptoFactory *CF, int hashalg);
bool ServerCertNameOK(const char *subject, const char *hname, String &e);
static XrdSutCacheEntry *GetSrvCertEnt(XrdSutCERef &gcref,
XrdCryptoFactory *cf,
time_t timestamp, String &cal);
// Load CRLs
static XrdCryptoX509Crl *LoadCRL(XrdCryptoX509 *xca, const char *sjhash,
XrdCryptoFactory *CF, int dwld, int &err);
// Updating proxies
static int QueryProxy(bool checkcache, XrdSutCache *cache, const char *tag,
XrdCryptoFactory *cf, time_t timestamp,
ProxyIn_t *pi, ProxyOut_t *po);
static int InitProxy(ProxyIn_t *pi, XrdCryptoFactory *cf,
X509Chain *ch = 0, XrdCryptoRSA **key = 0);
// Error functions
static void ErrF(XrdOucErrInfo *einfo, kXR_int32 ecode,
const char *msg1, const char *msg2 = 0,
const char *msg3 = 0);
XrdSecCredentials *ErrC(XrdOucErrInfo *einfo, XrdSutBuffer *b1,
XrdSutBuffer *b2,XrdSutBuffer *b3,
kXR_int32 ecode, const char *msg1 = 0,
const char *msg2 = 0, const char *msg3 = 0);
int ErrS(String ID, XrdOucErrInfo *einfo, XrdSutBuffer *b1,
XrdSutBuffer *b2, XrdSutBuffer *b3,
kXR_int32 ecode, const char *msg1 = 0,
const char *msg2 = 0, const char *msg3 = 0);
// Check Time stamp
bool CheckTimeStamp(XrdSutBuffer *b, int skew, String &emsg);
// Check random challenge
bool CheckRtag(XrdSutBuffer *bm, String &emsg);
// Auxilliary methods
int AddSerialized(char opt, kXR_int32 step, String ID,
XrdSutBuffer *bls, XrdSutBuffer *buf,
kXR_int32 type, XrdCryptoCipher *cip);
// Grid map cache handling
static XrdSecgsiGMAP_t // Load alternative function for mapping
LoadGMAPFun(const char *plugin, const char *parms);
static XrdSecgsiAuthz_t // Load alternative function to fill XrdSecEntity
LoadAuthzFun(const char *plugin, const char *parms, int &fmt);
static XrdSecgsiVOMS_t // Load alternative function to extract VOMS
LoadVOMSFun(const char *plugin, const char *parms, int &fmt);
static void QueryGMAP(XrdCryptoX509Chain* chain, int now, String &name); //Lookup info for DN
// Entity handling
void CopyEntity(XrdSecEntity *in, XrdSecEntity *out, int *lout = 0);
void FreeEntity(XrdSecEntity *in);
};
class gsiHSVars {
public:
int Iter; // Iteration number
time_t TimeStamp; // Time of last call
String CryptoMod; // Crypto module in use
int RemVers; // Version run by remote counterpart
XrdCryptoCipher *Rcip; // Reference cipher
bool HasPad; // Whether padding is supported
XrdSutBucket *Cbck; // Bucket with the certificate in export form
String ID; // Handshake ID (dummy for clients)
XrdSutPFEntry *Cref; // Cache reference
XrdSutPFEntry *Pent; // Pointer to relevant file entry
X509Chain *Chain; // Chain to be eventually verified
XrdCryptoX509Crl *Crl; // Pointer to CRL, if required
X509Chain *PxyChain; // Proxy Chain on clients
bool RtagOK; // Rndm tag checked / not checked
bool Tty; // Terminal attached / not attached
int LastStep; // Step required at previous iteration
int Options; // Handshake options;
int HashAlg; // Hash algorithm of peer hash name;
XrdSutBuffer *Parms; // Buffer with server parms on first iteration
gsiHSVars() { Iter = 0; TimeStamp = -1; CryptoMod = "";
RemVers = -1; Rcip = 0; HasPad = 0;
Cbck = 0;
ID = ""; Cref = 0; Pent = 0; Chain = 0; Crl = 0; PxyChain = 0;
RtagOK = 0; Tty = 0; LastStep = 0; Options = 0; HashAlg = 0; Parms = 0;}
~gsiHSVars() { SafeDelete(Cref);
if (Options & kOptsDelChn) {
// Do not delete the CA certificate in the cached reference
if (Chain) Chain->Cleanup(1);
SafeDelete(Chain);
}
// Make sure XrdSecProtocolgsi::stackCRL exists, it could happen
// that it has been deallocated due to static deinitialization
// order fiasco
if (Crl && bool( XrdSecProtocolgsi::stackCRL ) ) {
// This decreases the counter and actually deletes the object only
// when no instance is using it
XrdSecProtocolgsi::stackCRL->Del(Crl);
Crl = 0;
}
// The proxy chain is owned by the proxy cache; invalid proxies are
// detected (and eventually removed) by QueryProxy
PxyChain = 0;
SafeDelete(Parms); }
void Dump(XrdSecProtocolgsi *p = 0);
};