XRootD
XrdCryptoX509Chain.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d C r y p t o X 5 0 9 C h a i n . c c */
4 /* */
5 /* (c) 2005 G. Ganis, CERN */
6 /* */
7 /* This file is part of the XRootD software suite. */
8 /* */
9 /* XRootD is free software: you can redistribute it and/or modify it under */
10 /* the terms of the GNU Lesser General Public License as published by the */
11 /* Free Software Foundation, either version 3 of the License, or (at your */
12 /* option) any later version. */
13 /* */
14 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
15 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
16 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
17 /* License for more details. */
18 /* */
19 /* You should have received a copy of the GNU Lesser General Public License */
20 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
21 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
22 /* */
23 /* The copyright holder's institutional names and contributor's names may not */
24 /* be used to endorse or promote products derived from this software without */
25 /* specific prior written permission of the institution or contributor. */
26 /* */
27 /******************************************************************************/
28 #include <ctime>
29 #include <cstring>
30 
33 
34 // ---------------------------------------------------------------------------//
35 // //
36 // XrdCryptoX509Chain //
37 // //
38 // Light single-linked list for managing stacks of XrdCryptoX509* objects //
39 // //
40 // ---------------------------------------------------------------------------//
41 
42 // For test dumps, to avoid interfering with the trace mutex
43 #define LOCDUMP(y) { std::cerr << epname << ":" << y << std::endl; }
44 
45 // Description of errors
46 static const char *X509ChainErrStr[] = {
47  "no error condition occurred", // 0
48  "chain is inconsistent", // 1
49  "size exceeds max allowed depth", // 2
50  "invalid or missing CA", // 3
51  "certificate missing", // 4
52  "unexpected certificate type", // 5
53  "names invalid or missing", // 6
54  "certificate has been revoked", // 7
55  "certificate expired", // 8
56  "extension not found", // 9
57  "signature verification failed", // 10
58  "issuer had no signing rights", // 11
59  "CA issued by another CA", // 12
60  "invalid or missing EEC", // 13
61  "too many EEC", // 14
62  "invalid proxy" // 15
63 };
64 
65 //___________________________________________________________________________
67 {
68  // Constructor
69 
70  previous = 0;
71  current = 0;
72  begin = 0;
73  end = 0;
74  effca = 0;
75  size = 0;
76  lastError = "";
77  caname = "";
78  eecname = "";
79  cahash = "";
80  eechash = "";
82 
83  if (c) {
85  current = begin = end = f;
86  size++;
87  //
88  // If CA verify it and save result
89  if (c->type == XrdCryptoX509::kCA) {
90  caname = c->Subject();
91  cahash = c->SubjectHash();
92  EX509ChainErr ecode = kNone;
93  if (!Verify(ecode, "CA: ",XrdCryptoX509::kCA, 0, c, c))
95  else
96  statusCA = kValid;
97  }
98  // Search for the effective CA
100  }
101 }
102 
103 //___________________________________________________________________________
105 {
106  // Copy constructor
107 
108  previous = 0;
109  current = 0;
110  begin = 0;
111  end = 0;
112  effca = 0;
113  size = 0;
114  lastError = ch->LastError();
115  caname = ch->CAname();
116  eecname = ch->EECname();
117  cahash = ch->CAhash();
118  eechash = ch->EEChash();
119  statusCA = ch->StatusCA();
120 
121  XrdCryptoX509 *c = ch->Begin();
122  while (c) {
124  if (!begin)
125  begin = nc;
126  if (end)
127  end->SetNext(nc);
128  end = nc;
129  if (c == ch->EffCA()) effca = nc;
130  size++;
131  // Go to Next
132  c = ch->Next();
133  }
134 }
135 
136 //___________________________________________________________________________
138 {
139  // Destructor
140 
141  XrdCryptoX509ChainNode *n = 0;
143  while (c) {
144  n = c->Next();
145  delete (c);
146  c = n;
147  }
148 }
149 
150 //___________________________________________________________________________
152 {
153  // Destructs content of nodes AND their content
154  // If keepCA is true, the top CA is kept
155 
156  XrdCryptoX509ChainNode *n = 0;
158  while (c) {
159  n = c->Next();
160  if (c->Cert() &&
161  (!keepCA || (c->Cert()->type != XrdCryptoX509::kCA)))
162  delete (c->Cert());
163  delete (c);
164  c = n;
165  }
166 
167  // Reset
168  previous = 0;
169  current = 0;
170  begin = 0;
171  end = 0;
172  effca = 0;
173  size = 0;
174  lastError = "";
175  caname = "";
176  eecname = "";
177  cahash = "";
178  eechash = "";
179  statusCA = kUnknown;
180 }
181 
182 //___________________________________________________________________________
183 bool XrdCryptoX509Chain::CheckCA(bool checkselfsigned)
184 {
185  // Search the list for a valid CA and set it at top.
186  // Search stops when a valid CA is found; an invalid CA is flagged.
187  // A second CA is always ignored.
188  // Signature check failures are accepted if 'checkselfsigned' is false.
189  // Return 1 if found, 0 otherwise; lastError is filled with the reason of
190  // failure, if any.
191 
192  XrdCryptoX509 *xc = 0;
193  XrdCryptoX509ChainNode *n = 0;
195  XrdCryptoX509ChainNode *p = 0;
196  lastError = "";
197  while (c) {
198  n = c->Next();
199  xc = c->Cert();
200  if (xc && xc->type == XrdCryptoX509::kCA) {
201  caname = xc->Subject();
202  cahash = xc->SubjectHash();
203  EX509ChainErr ecode = kNone;
204  bool CAok = Verify(ecode, "CA: ",XrdCryptoX509::kCA, 0, xc, xc);
205  if (!CAok && (ecode != kVerifyFail || checkselfsigned)) {
206  statusCA = kInvalid;
207  lastError += X509ChainError(ecode);
208  } else {
209  statusCA = kValid;
210  if (p) {
211  // Move at top
212  p->SetNext(c->Next());
213  c->SetNext(begin);
214  if (end == c) end = p;
215  begin = c;
216  }
217  return 1;
218  }
219  }
220  p = c; // Previous node
221  c = n;
222  }
223 
224  // Found nothing
225  return 0;
226 }
227 
228 //___________________________________________________________________________
230 {
231  // Return error string
232 
233  return X509ChainErrStr[e];
234 }
235 
236 //___________________________________________________________________________
238 {
239  // Find node containing bucket b
240 
242  for (; nd; nd = nd->Next()) {
243  if (nd->Cert() == c)
244  return nd;
245  }
246  return (XrdCryptoX509ChainNode *)0;
247 }
248 
249 //___________________________________________________________________________
251 {
252  // Add at the beginning of the list
253  // Check to avoid duplicates
254 
255  if (!Find(c)) {
257  begin = nc;
258  if (!end)
259  end = nc;
260  size++;
261  }
262 
263  // Search for the effective CA (the last one, in case of subCAs)
264  SetEffectiveCA();
265 }
266 
267 //___________________________________________________________________________
269 {
270  // Add or move certificate 'c' after certificate 'cp'; if 'cp' is not
271  // in the list, push-back
272 
273  XrdCryptoX509ChainNode *nc = Find(c);
274  XrdCryptoX509ChainNode *ncp = Find(cp);
275  if (ncp) {
276  // Create a new node, if not there
277  if (!nc) {
278  nc = new XrdCryptoX509ChainNode(c,ncp->Next());
279  size++;
280  }
281  // Update pointers
282  ncp->SetNext(nc);
283  if (end == ncp)
284  end = nc;
285 
286  } else {
287  // Reference certificate not in the list
288  // If new, add in last position; otherwise leave it where it is
289  if (!nc)
290  PushBack(c);
291  }
292 
293  // Search for the effective CA (the last one, in case of subCAs)
294  SetEffectiveCA();
295 }
296 
297 //___________________________________________________________________________
299 {
300  // Add at the end of the list
301  // Check to avoid duplicates
302 
303  if (!Find(c)) {
305  if (!begin)
306  begin = nc;
307  if (end)
308  end->SetNext(nc);
309  end = nc;
310  size++;
311  } else if (c) {
312  delete c;
313  }
314 
315  // Search for the effective CA (the last one, in case of subCAs)
316  SetEffectiveCA();
317 }
318 
319 //___________________________________________________________________________
321 {
322  // Remove node containing bucket b
323 
326 
327  if (!curr || curr->Cert() != c || (prev && curr != prev->Next())) {
328  // We need first to find the address
329  curr = begin;
330  prev = 0;
331  for (; curr; curr = curr->Next()) {
332  if (curr->Cert() == c)
333  break;
334  prev = curr;
335  }
336  }
337 
338  // The certificate is not in the list
339  if (!curr)
340  return;
341 
342  //
343  // If this was the top CA update the related information
344  if (c->type == XrdCryptoX509::kCA && curr == begin) {
345  // There may be other CAs in the chain, but we will
346  // check when needed
347  statusCA = kUnknown;
348  caname = "";
349  cahash = "";
350  }
351 
352  // Now we have all the information to remove
353  if (prev) {
354  if (curr != end) {
355  current = curr->Next();
356  prev->SetNext(current);
357  previous = prev;
358  } else {
359  end = prev;
360  previous = end;
361  current = 0;
362  prev->SetNext(current);
363  }
364  } else if (curr == begin) {
365  // First buffer
366  current = curr->Next();
367  begin = current;
368  previous = 0;
369  }
370 
371  // Cleanup and update size
372  delete curr;
373  size--;
374 
375  // Search for the effective CA (the last one, in case of subCAs)
376  SetEffectiveCA();
377 }
378 
379 //___________________________________________________________________________
381 {
382  // Iterator functionality: init
383 
384  previous = 0;
385  current = begin;
386  if (current)
387  return current->Cert();
388  return (XrdCryptoX509 *)0;
389 }
390 
391 //___________________________________________________________________________
393 {
394  // Iterator functionality: get next
395 
396  previous = current;
397  if (current) {
398  current = current->Next();
399  if (current)
400  return current->Cert();
401  }
402  return (XrdCryptoX509 *)0;
403 }
404 
405 //___________________________________________________________________________
407  ESearchMode mode)
408 {
409  // Return first certificate in the chain with issuer
410  // Match according to mode.
411 
412  XrdCryptoX509ChainNode *cn = FindIssuer(issuer, mode);
413 
414  // We are done
415  return ((cn) ? cn->Cert() : (XrdCryptoX509 *)0);
416 }
417 
418 //___________________________________________________________________________
420  ESearchMode mode)
421 {
422  // Return first certificate in the chain with subject
423  // Match according to mode.
424 
425  XrdCryptoX509ChainNode *cn = FindSubject(subject, mode);
426 
427  // We are done
428  return ((cn) ? cn->Cert() : (XrdCryptoX509 *)0);
429 
430 }
431 
432 //___________________________________________________________________________
434  ESearchMode mode, XrdCryptoX509ChainNode **prev)
435 {
436  // Return first chain node with certificate having issuer
437  // Match according to mode.
438 
439  // Make sure we got something to compare
440  if (!issuer)
441  return (XrdCryptoX509ChainNode *)0;
442 
443  XrdCryptoX509ChainNode *cp = 0;
444  XrdCryptoX509ChainNode *n = 0;
446  XrdCryptoX509 *c = 0;
447  while (cn) {
448  n = cn->Next();
449  c = cn->Cert();
450  if(c) {
451  const char *pi = c->Issuer();
452  if (pi) {
453  if (mode == kExact) {
454  if (!strcmp(pi, issuer))
455  break;
456  } else if (mode == kBegin) {
457  if (strstr(pi, issuer) == c->Issuer())
458  break;
459  } else if (mode == kEnd) {
460  int ibeg = strlen(pi) - strlen(issuer);
461  if (!strcmp(pi + ibeg, issuer))
462  break;
463  }
464  }
465  }
466  c = 0;
467  cp = cn; // previous
468  cn = n;
469  }
470  // return previous, if requested
471  if (prev)
472  *prev = (cn) ? cp : 0;
473 
474  // We are done
475  return ((cn) ? cn : (XrdCryptoX509ChainNode *)0);
476 }
477 
478 //___________________________________________________________________________
480  ESearchMode mode, XrdCryptoX509ChainNode **prev)
481 {
482  // Return first chain node with certificate having subject
483  // Match according to mode.
484 
485  // Make sure we got something to compare
486  if (!subject)
487  return (XrdCryptoX509ChainNode *)0;
488 
489  XrdCryptoX509ChainNode *cp = 0;
490  XrdCryptoX509ChainNode *n = 0;
492  XrdCryptoX509 *c = 0;
493  while (cn) {
494  n = cn->Next();
495  c = cn->Cert();
496  const char *ps = c ? c->Subject() : 0;
497  if (c && ps) {
498  if (mode == kExact) {
499  if (!strcmp(ps, subject))
500  break;
501  } else if (mode == kBegin) {
502  if (strstr(ps, subject) == ps)
503  break;
504  } else if (mode == kEnd) {
505  int sbeg = strlen(ps) - strlen(subject);
506  if (!strcmp(ps + sbeg, subject))
507  break;
508  }
509  }
510  c = 0;
511  cp = cn; // previous
512  cn = n;
513  }
514  // return previous, if requested
515  if (prev)
516  *prev = (cn) ? cp : 0;
517 
518  // We are done
519  return ((cn) ? cn : (XrdCryptoX509ChainNode *)0);
520 }
521 
522 //___________________________________________________________________________
524 {
525  // Dump content
526  EPNAME("X509Chain::Dump");
527 
528  LOCDUMP("//------------------Dumping X509 chain content ------------------//");
529  LOCDUMP("//");
530  LOCDUMP("// Chain instance: "<<this);
531  LOCDUMP("//");
532  LOCDUMP("// Number of certificates: "<<Size());
533  LOCDUMP("//");
534  if (CAname()) {
535  LOCDUMP("// CA: "<<CAname());
536  } else {
537  LOCDUMP("// CA: absent");
538  }
539  if (EECname()) {
540  LOCDUMP("// EEC: "<<EECname());
541  } else {
542  LOCDUMP("// EEC: absent");
543  }
544  LOCDUMP("//");
545  XrdCryptoX509ChainNode *n = 0;
547  while (c) {
548  n = c->Next();
549  if (c->Cert()) {
550  LOCDUMP("// Issuer: "<<c->Cert()->IssuerHash()<<
551  " Subject: "<<c->Cert()->SubjectHash()<<
552  " Type: "<<c->Cert()->Type());
553  }
554  c = n;
555  }
556  LOCDUMP("//");
557  LOCDUMP("//---------------------------- END ------------------------------//")
558 }
559 
560 //___________________________________________________________________________
562 {
563  // Reorder certificates in such a way that certificate n is the
564  // issuer of certificate n+1 .
565  // Return -1 if inconsistencies are found.
566  EPNAME("X509Chain::Reorder");
567 
568  if (size < 2) {
569  DEBUG("Nothing to reorder (size: "<<size<<")");
570  // Search for the effective CA (the last one, in case of subCAs)
571  SetEffectiveCA();
572  return 0;
573  }
574 
575  // Loop over the certificates
576  XrdCryptoX509ChainNode *nc = 0, *np = 0, *nn = 0, *nr = 0, *npp = 0;
577 
578  // Look for the first one, if needed
579  nr = begin;
580  np = nr;
581  while (nr) {
582  //
583  if (!(nn = FindSubject(nr->Cert()->Issuer(),kExact,&npp)) ||
584  nn == nr)
585  break;
586  np = nr;
587  nr = nr->Next();
588  }
589 
590  // Move it in first position if not yet there
591  if (nr && nr != begin) {
592  np->SetNext(nr->Next()); // short cut old position
593  nr->SetNext(begin); // set our next to present begin
594  if (end == nr) // Update end
595  end = np;
596  begin = nr; // set us as begin
597  // Flag if not CA: we do not check validity here
598  if (nr->Cert()->type != XrdCryptoX509::kCA) {
599  statusCA = kAbsent;
600  } else if (caname.length() <= 0) {
601  // Set the CA properties only if not done already to avoid overwriting
602  // the result of previous analysis
603  caname = nr->Cert()->Subject();
604  cahash = nr->Cert()->SubjectHash();
605  statusCA = kUnknown;
606  }
607  }
608 
609  int left = size-1;
610  np = begin;
611  while (np) {
612  if (np->Cert()) {
613  const char *pi = np->Cert()->Subject();
614  // Set the EEC name, if not yet done
615  if (np->Cert()->type == XrdCryptoX509::kEEC && eecname.length() <= 0) {
616  eecname = pi;
617  eechash = np->Cert()->SubjectHash();
618  }
619  npp = np;
620  nc = np->Next();
621  while (nc) {
622  if (nc->Cert() && !strcmp(pi, nc->Cert()->Issuer())) {
623  left--;
624  if (npp != np) {
625  npp->SetNext(nc->Next()); // drop child from previous pos
626  nc->SetNext(np->Next()); // set child next as our present
627  np->SetNext(nc); // set our next as child
628  if (nc == end)
629  end = npp;
630  }
631  break;
632  }
633  npp = nc;
634  nc = nc->Next();
635  }
636  }
637  np = np->Next();
638  }
639 
640  // Search for the effective CA (the last one, in case of subCAs)
641  SetEffectiveCA();
642 
643  // Check consistency
644  if (left > 0) {
645  DEBUG("Inconsistency found: "<<left<<
646  " certificates could not be correctly enchained!");
647  return -1;
648  }
649 
650  // We are done
651  return 0;
652 }
653 
654 //___________________________________________________________________________
656 {
657  // Search for the effective CA (the last one, in case of subCAs)
658  effca = 0; caname = ""; cahash = "";
659 
661  while (np) {
662  if (np->Cert()) {
663  if (np->Cert()->type == XrdCryptoX509::kCA) {
664  if (!effca || (effca &&
665  !(strcmp(effca->Cert()->SubjectHash(),
666  np->Cert()->IssuerHash())))) effca = np;
667  }
668  }
669  np = np->Next();
670  }
671  if (effca && effca->Cert()) {
672  caname = effca->Cert()->Subject();
673  cahash = effca->Cert()->SubjectHash();
674  }
675 }
676 
677 //___________________________________________________________________________
679 {
680  // Verify cross signatures of the chain
681  EPNAME("X509Chain::Verify");
682  errcode = kNone;
683 
684  // Do nothing if empty
685  if (size < 1) {
686  DEBUG("Nothing to verify (size: "<<size<<")");
687  return 0;
688  }
689 
690  //
691  // Reorder if needed
692  if (Reorder() != 0) {
693  errcode = kInconsistent;
694  lastError = ":";
695  lastError += X509ChainError(errcode);
696  return 0;
697  }
698 
699  //
700  // Verification options
701  int when = (vopt) ? vopt->when : (int)time(0);
702  int plen = (vopt) ? vopt->pathlen : -1;
703  bool chkss = (vopt) ? (vopt->opt & kOptsCheckSelfSigned) : 1;
704 
705  //
706  // Global path depth length consistency check
707  if (plen > -1 && plen < size) {
708  errcode = kTooMany;
709  lastError = "checking path depth: ";
710  lastError += X509ChainError(errcode);
711  }
712 
713  //
714  // Check the first certificate: it MUST be of CA type, valid,
715  // self-signed
716  if (!CheckCA(chkss)) {
717  errcode = kNoCA;
718  lastError = X509ChainError(errcode);
719  return 0;
720  }
721 
722  //
723  // Analyse the rest
725  XrdCryptoX509 *xsig = node->Cert(); // Signing certificate
726  XrdCryptoX509 *xcer = 0; // Certificate under exam
727  node = node->Next();
728  while (node) {
729 
730  // Attache to certificate
731  xcer = node->Cert();
732 
733  // Standard verification
734  if (!Verify(errcode, "cert: ", XrdCryptoX509::kUnknown, when, xcer, xsig))
735  return 0;
736 
737  // Get next
738  xsig = xcer;
739  node = node->Next();
740  }
741 
742  // We are done (successfully!)
743  return 1;
744 }
745 
746 //___________________________________________________________________________
747 int XrdCryptoX509Chain::CheckValidity(bool outatfirst, int when)
748 {
749  // Check validity at 'when' of certificates in the chain and return
750  // the number of invalid certificates.
751  // If 'outatfirst' return after the first invalid has been
752  // found.
753  EPNAME("X509Chain::CheckValidity");
754  int ninv = 0;
755 
756  // Do nothing if empty
757  if (size < 1) {
758  DEBUG("Nothing to verify (size: "<<size<<")");
759  return ninv;
760  }
761 
762  // Loop over the certificates
764  while (nc) {
765  //
766  XrdCryptoX509 *c = nc->Cert();
767  if (c) {
768  if (!(c->IsValid(when))) {
769  ninv++;
770  DEBUG("invalid certificate found");
771  if (outatfirst)
772  return ninv;
773  }
774  } else {
775  ninv++;
776  DEBUG("found node without certificate");
777  if (outatfirst)
778  return ninv;
779  }
780  // Get next
781  nc = nc->Next();
782  }
783 
784  // We are done
785  return ninv;
786 }
787 
788 //___________________________________________________________________________
789 bool XrdCryptoX509Chain::Verify(EX509ChainErr &errcode, const char *msg,
790  XrdCryptoX509::EX509Type type, int when,
791  XrdCryptoX509 *xcer, XrdCryptoX509 *xsig,
792  XrdCryptoX509Crl *crl)
793 {
794  // Internal verification method
795 
796  // Certificate must be defined
797  if (!xcer) {
798  errcode = kNoCertificate;
799  lastError = msg;
800  lastError += X509ChainError(errcode);
801  return 0;
802  }
803 
804  // Type should be the one expected
805  if (type != XrdCryptoX509::kUnknown && xcer->type != type) {
806  errcode = kInvalidType;
807  lastError = msg;
808  lastError += X509ChainError(errcode);
809  return 0;
810  }
811 
812  // Must not be revoked (check only if required)
813  if (crl) {
814  // Get certificate serial number
815  XrdOucString sn = xcer->SerialNumberString();
816  if (crl->IsRevoked(sn.c_str(), when)) {
817  errcode = kRevoked;
818  lastError = msg;
819  lastError += X509ChainError(errcode);
820  return 0;
821  }
822  }
823 
824  // Check validity in time
825  if (when >= 0 && !(xcer->IsValid(when))) {
826  errcode = kExpired;
827  lastError = msg;
828  lastError += X509ChainError(errcode);
829  return 0;
830  }
831 
832  // Check signature
833  if (!xsig || !(xcer->Verify(xsig))) {
834  errcode = kVerifyFail;
835  lastError = msg;
836  lastError += X509ChainError(errcode);
837  return 0;
838  }
839 
840  // We are done
841  return 1;
842 }
843 
844 //_____________________________________________________________________________
846 {
847  // Return subject name of the CA in the chain
848  EPNAME("X509Chain::CAname");
849 
850  // If we do not have it already, try extraction
851  if (caname.length() <= 0 && statusCA == kUnknown) {
852 
853  if (!CheckCA()) {
854  DEBUG("CA not found in chain");
855  return (const char *)0;
856  }
857  }
858 
859  // return what we have
860  return (caname.length() > 0) ? caname.c_str() : (const char *)0;
861 }
862 
863 //_____________________________________________________________________________
865 {
866  // Return subject name of the EEC in the chain
867  EPNAME("X509Chain::EECname");
868 
869  // If we do not have it already, try extraction
870  if (eecname.length() <= 0) {
871 
873  while (c) {
874  if (c->Cert()->type == XrdCryptoX509::kEEC) {
875  eecname = c->Cert()->Subject();
876  break;
877  }
878  c = c->Next();
879  }
880  if (eecname.length() <= 0) {
881  DEBUG("EEC not found in chain");
882  return (const char *)0;
883  }
884  }
885 
886  // return what we have
887  return (eecname.length() > 0) ? eecname.c_str() : (const char *)0;
888 }
889 
890 //_____________________________________________________________________________
892 {
893  // Return the subject name hash of the CA in the chain
894  EPNAME("X509Chain::CAhash");
895 
896  // If we do not have it already, try extraction
897  if (cahash.length() <= 0 && statusCA == kUnknown) {
898 
899  if (!CheckCA()) {
900  DEBUG("CA not found in chain");
901  return (const char *)0;
902  }
903  }
904 
905  // return what we have
906  return (cahash.length() > 0) ? cahash.c_str() : (const char *)0;
907 }
908 
909 //_____________________________________________________________________________
911 {
912  // Return the subject name hash of the EEC in the chain
913  EPNAME("X509Chain::EEChash");
914 
915  // If we do not have it already, try extraction
916  if (eechash.length() <= 0) {
917 
919  while (c) {
920  if (c->Cert()->type == XrdCryptoX509::kEEC) {
921  eechash = c->Cert()->SubjectHash();
922  break;
923  }
924  c = c->Next();
925  }
926  if (eechash.length() <= 0) {
927  DEBUG("EEC not found in chain");
928  return (const char *)0;
929  }
930  }
931 
932  // return what we have
933  return (eechash.length() > 0) ? eechash.c_str() : (const char *)0;
934 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define LOCDUMP(y)
static const char * X509ChainErrStr[]
const int kOptsCheckSelfSigned
XrdCryptoX509 * Cert() const
void SetNext(XrdCryptoX509ChainNode *n)
XrdCryptoX509ChainNode * Next() const
virtual bool Verify(EX509ChainErr &e, x509ChainVerifyOpt_t *vopt=0)
void InsertAfter(XrdCryptoX509 *c, XrdCryptoX509 *cp)
bool CheckCA(bool checkselfsigned=1)
XrdCryptoX509 * Next()
virtual int CheckValidity(bool outatfirst=1, int when=0)
XrdCryptoX509ChainNode * end
XrdCryptoX509 * Begin()
XrdCryptoX509ChainNode * FindIssuer(const char *issuer, ESearchMode mode=kExact, XrdCryptoX509ChainNode **p=0)
XrdCryptoX509ChainNode * FindSubject(const char *subject, ESearchMode mode=kExact, XrdCryptoX509ChainNode **p=0)
XrdCryptoX509ChainNode * begin
void Cleanup(bool keepCA=0)
void Remove(XrdCryptoX509 *c)
XrdCryptoX509 * SearchByIssuer(const char *issuer, ESearchMode mode=kExact)
ECAStatus StatusCA() const
XrdCryptoX509ChainNode * previous
XrdCryptoX509ChainNode * current
void PushBack(XrdCryptoX509 *c)
const char * X509ChainError(EX509ChainErr e)
XrdCryptoX509 * EffCA() const
const char * LastError() const
XrdCryptoX509 * SearchBySubject(const char *subject, ESearchMode mode=kExact)
void PutInFront(XrdCryptoX509 *c)
XrdCryptoX509ChainNode * effca
XrdCryptoX509ChainNode * Find(XrdCryptoX509 *c)
XrdCryptoX509Chain(XrdCryptoX509 *c=0)
virtual bool IsRevoked(int serialnumber, int when)
virtual bool Verify(XrdCryptoX509 *ref)
virtual const char * Subject()
const char * Type(EX509Type t=kUnknown) const
virtual const char * SubjectHash(int)
virtual const char * IssuerHash(int)
virtual const char * Issuer()
virtual bool IsValid(int when=0)
virtual XrdOucString SerialNumberString()
EX509Type type
const char * c_str() const
int length() const