/[mwsec]/trunk/lcmaps-plugins-verify-proxy/src/verify-proxy/verify-lib/src_internal/_verify_x509.c
ViewVC logotype

Contents of /trunk/lcmaps-plugins-verify-proxy/src/verify-proxy/verify-lib/src_internal/_verify_x509.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 18905 - (show annotations) (download) (as text)
Mon Sep 20 11:47:11 2021 UTC (9 months ago) by msalle
File MIME type: text/x-chdr
File size: 62685 byte(s)
OpenSSL 3.0 no longer uses function in error

"function" is no longer used in packed errors, see e.g.
https://github.com/openssl/openssl/pull/9058
We need to make sure that we do not still set them using ERR_PACK(), since that
would overwrite the library name instead.

1 /**
2 * Copyright (c) Members of the EGEE Collaboration. 2004-2010.
3 * See http://www.eu-egee.org/partners/ for details on the copyright
4 * holders.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 *
19 * Authors:
20 * 2004-
21 * Oscar Koeroo <okoeroo@nikhef.nl>
22 * NIKHEF Amsterdam, the Netherlands
23 * <grid-mw-security@nikhef.nl>
24 *
25 */
26
27 /* Needed for snprintf */
28 #define _XOPEN_SOURCE 500
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <time.h>
34 #include <errno.h>
35
36 #include <openssl/x509.h>
37 #include <openssl/x509v3.h>
38 #include <openssl/x509_vfy.h>
39 #include <openssl/err.h>
40 #include <openssl/pem.h>
41 #include <openssl/bio.h>
42 #include <openssl/asn1.h>
43 #include <openssl/evp.h>
44 #include <openssl/objects.h>
45
46 #include <openssl/rsa.h>
47 #include <openssl/des.h>
48
49 #include "_verify_log.h"
50 #include "_verify_proxy_certinfo.h"
51 #include "_verify_x509.h"
52 #include "verify_x509.h"
53
54 #include "verify_x509_datatypes.h"
55
56
57 /* OpenSSL uses a default depth of 9.
58 * To cope with Subordinate CAs we have to extend the verification depth to be
59 * able to hold the certificate chain (could contain a lot of delegations) and
60 * all the CA certificate, which might not be added to the certificate chain
61 * itself but would still be lingering in the X509 CA directory lookup functions
62 */
63 #define VERIFICATION_CHAIN_DEPTH_EXTENSION 9
64
65 #define USE_STRICT_PATH_VALIDATION
66
67 #define OBJ_TEXT_LEN 80
68
69 #define MY_ERR_MAX 13
70 #if OPENSSL_VERSION_NUMBER < 0x030000000L
71 # define MY_FUNC_MAX 5 /* function part only for OpenSSL < 3.0 */
72 #endif
73 #define MY_LIB (ERR_LIB_USER+64)
74
75 #define CA_TEXT "CA"
76 #define EEC_TEXT "EEC"
77 #define GT2_TEXT "GT2/old-style"
78 #define GT3_TEXT "GT3/pre-RFC"
79 #define RFC_TEXT "RFC3820"
80 #define ANY_PROXY_TEXT "any type of"
81
82 #define IMPERSONATION_TEXT " Proxy"
83 #define LIMITED_TEXT " Limited Proxy"
84 #define INDEPENDENT_TEXT " Independent Proxy"
85 #define ANYLANG_TEXT " AnyLanguage Proxy"
86 #define RESTRICTED_TEXT " Restricted Proxy"
87 #define ALL_LANGUAGE_TEXT " proxy of any language"
88
89
90 /*****************************************************************************/
91 /* Internal variables */
92 /*****************************************************************************/
93
94 /**
95 * library number to be set by ERR_get_next_error_library(). Can be initialized
96 * using verify_init_library() and read out by verify_get_library().
97 */
98 static int initialized=0;
99 static int library=-1;
100
101 static int chain_verify=0;
102
103 /**
104 * Input array containing the library name and errors.
105 * Use only the reason as first argument, we'll do the proper ERR_PACK(library,
106 * 0, reason) in verify_init_library() when using them to fill the actual
107 * errstr[]
108 */
109 static ERR_STRING_DATA my_errstr[MY_ERR_MAX] = {
110 { 0, "Proxy Verification library"},
111 { VER_R_NO_CACERT, "No CA certificate directory specified"},
112 { VER_R_CERTSTACK_EMPTY, "No certificate chain presented"},
113 { VER_R_PARAMETER_EMPTY, "Mandatory parameter is empty"},
114 { VER_R_LIMITED_DISABLED, "Limited proxies are disallowed by configuration"},
115 { VER_R_NOPRIVATEKEY_DISABLED, "Absence of private key disallowed by configuration"},
116 { VER_R_X509_VERIFY_CERT_FAILURE, "Certificate verification failed"},
117 { VER_R_X509_PARAMS_CONTAINER_FAILURE, "Parameter object is unset or empty"},
118 { VER_R_X509_PARAMS_ALREADY_SET, "Parameter is set multiple times"},
119 { VER_R_X509_PARAMS_DATA_EMPTY, "Parameter is set but value is empty"},
120 { VER_R_X509_PARAMS_ACCESS_FAILURE, "Parameter value cannot be accessed (I/O error)"},
121 { VER_R_X509_PARAMS_UNSUPPORTED_DATATYPE, "Unknown parameter type specified"},
122 { 0, NULL },
123 };
124
125 #if OPENSSL_VERSION_NUMBER < 0x030000000L
126 /* Function part is deprecated in OpenSSL 3.0: therefore should not try to set
127 * it via ERR_PACK() or we'll overwrite our library part */
128
129 /**
130 * Input array containing the functions.
131 * Use only the reason as first argument, we'll do the proper ERR_PACK(library,
132 * 0, reason) in verify_init_library() when using them to fill the actual
133 * errstr[]
134 */
135 static ERR_STRING_DATA my_funcstr[MY_FUNC_MAX] = {
136 { VER_F_VERIFY_X509_VERIFY, "verify_x509_verify()"},
137 { VER_F_PROCESS_INTERNAL, "process_internal_verify_data()"},
138 { VER_F_GRID_VERIFYCERT, "verify_verifyCert()"},
139 { VER_F_SET_PARAM, "verify_X509_setParameter()"},
140 { 0, NULL }
141 };
142 #endif
143
144 /*****************************************************************************/
145 /* Internal prototypes */
146 /*****************************************************************************/
147
148 /**
149 * Callback function for PEM_read_bio_PrivateKey() and friends. See
150 * PEM_read_bio_PrivateKey(3ssl)
151 */
152 static int grid_X509_empty_password_callback(char *buf, int buf_size, int verify, void *cb_tmp);
153
154 /**
155 * Callback function for OpenSSL to put the errors
156 * Parameters: ok, X509_STORE_CTX
157 * Returns: 1 on success, 0 on error
158 */
159 static int grid_X509_verify_callback(int ok, X509_STORE_CTX *ctx);
160
161 /**
162 * Checks the certificate chain on CA based (RFC5280) and RFC3820 Proxy based
163 * Path Length Constraints. In addition it does a number of other proxy tests.
164 * Returns X509_V_OK on successful verification or X509_V_ERR_CERT_REJECTED on
165 * any error.
166 */
167 static int grid_verifyChain(STACK_OF(X509) * chain);
168
169 /**
170 * Returns proxy pathlength constraint for GT3 and RFC type proxies or -1 when
171 * none.
172 */
173 static long get_proxy_pathlength(X509 *cert, proxy_type_t proxy_type);
174
175 /**
176 * Checks to see if one of the unsupported critical extensions is a valid proxy
177 * type.
178 * Returns X509_V_OK on success or X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION on
179 * error
180 */
181 static int grid_X509_knownCriticalExts(X509 *cert);
182
183 /**
184 * Check if we can safely discards errors about the issuer
185 * Returns 1 when issuer is fine, 0 when no.
186 */
187 static int grid_X509_check_issued_wrapper(X509_STORE_CTX *ctx,X509 *x,X509 *issuer);
188
189 /**
190 * Print and verify the key strength for given certificate, on L_WARN for
191 * smaller than given mininum keylength. For length == 0, use default 1024
192 * Returns -1 on error (cannot retrieve pubkey or keylength)
193 */
194 static int grid_check_keylength(X509 *cert, int minlength);
195
196 /**
197 * Print the signature algorithm for given certificate, on L_WARN for deprecated
198 * algorithms
199 * Returns 0 when still acceptable, -1 when too old (currently not used) or
200 * unknown
201 */
202 static int grid_check_sigalg(X509 *cert);
203
204 /**
205 * Converts the ASN1_INTEGER serial into a string
206 * Returns a pointer to a buffer-to-be-freed or NULL on error
207 */
208 static char *grid_get_serialStr(ASN1_INTEGER *);
209
210 /**
211 * Constructs string printing the expected types of certificates in human
212 * readable form.
213 * Parameters:
214 * int expected_proxy_type : bitfield of types of certificates that we expected.
215 * Returns:
216 * char *message, MUST be free'd, NULL on error
217 */
218 static char *grid_get_expected_proxy_string(int expected_proxy_type);
219
220 /*****************************************************************************/
221 /* Function definitions */
222 /*****************************************************************************/
223
224 /**
225 * Converts an internal library 'reason' to an ERR_get_error() compatible code
226 * and pushes the corresponding error on the stack.
227 * Returns the error code
228 * */
229 unsigned long verify_errval(int func, verify_x509_error_t reason,
230 const char *file, int line) {
231 /* Make sure the library is initialized */
232 if (!initialized)
233 verify_init_library();
234
235 ERR_put_error(library, func, (int)reason, file, line);
236 /* Although manpage says arguments are int, there are combined as unsigned.
237 * Better convert them now */
238 return ERR_PACK((unsigned int)library,
239 (unsigned int)func,
240 (unsigned int)reason);
241 }
242
243 /**
244 * Converts an internal library 'reason' to an ERR_get_error() compatible code
245 * and pushes the corresponding error on the stack.
246 * Returns the reason code
247 * */
248 verify_x509_error_t verify_reasonval(int func, verify_x509_error_t reason,
249 const char *file, int line) {
250 /* Make sure the library is initialized */
251 if (!initialized)
252 verify_init_library();
253
254 ERR_put_error(library, func, (int)reason, file, line);
255 return reason;
256 }
257
258 /**
259 * Initializes the library, by creating a new library ID and loading the error
260 * and function strings.
261 * Returns library number
262 */
263 int verify_init_library(void) {
264 const char *oper = "verify_init_library";
265 const char *buf=NULL;
266 int i;
267 ERR_STRING_DATA *errstr=NULL;
268 #if OPENSSL_VERSION_NUMBER < 0x030000000L
269 ERR_STRING_DATA *funcstr=NULL; /* function part only for OpenSSL < 3.0 */
270 #endif
271 ASN1_OBJECT *obj=NULL;
272 int nid;
273
274 /* Although in an ideal world we should use ERR_get_next_error_library(),
275 * since VOMS is not using it, better set it by hand to a hopefully unused
276 * value. */
277 /* library=ERR_get_next_error_library();*/
278 library=MY_LIB;
279
280 /* Check whether we already have loaded the error and function strings */
281 buf=ERR_lib_error_string(ERR_PACK(library,0,0));
282 if (buf!=NULL) {
283 verify_log( L_DEBUG,
284 "Strings have already been loaded for lib %d: name: %s\n",
285 library, buf);
286 } else {
287 verify_log( L_DEBUG, "Loading strings for lib %d\n", library);
288
289 /* We need to either strdup the strings or guarantee that they are
290 * unloaded using (undocumented) ERR_unload_strings() explicitly before
291 * the plugin is dlclosed since they are used by OpenSSL as is (i.e. not
292 * strdupped). We prefer to strdup them here and never unload them, to
293 * prevent any potential problem when they would still be referenced
294 * after the dlclose, e.g. when one of the errors would still be on the
295 * error stack (current OpenSSL implementation seems to protect against
296 * that, but we prefer not to rely on that).
297 * Result is in a small but fixed amount of 'still reachable' memory. */
298
299 /* Allocate dynamically the library and error array itself */
300 errstr = (ERR_STRING_DATA*)calloc(sizeof(ERR_STRING_DATA), MY_ERR_MAX);
301 if (errstr == NULL) {
302 verify_error(oper, "out of memory while allocating errstr[]\n");
303 } else {
304 /* Now copy in the data from the input array to the array that will be
305 * passed to ERR_load_strings(). The first element is the name of the
306 * library itself */
307 for (i=0; i<MY_ERR_MAX-1; i++) {
308 /* Protect against too large value of MY_ERR_MAX, since that would
309 * result in a strdup of NULL */
310 if ( my_errstr[i].string == NULL ) {
311 verify_log(L_WARN,
312 "Internal error: MY_ERR_MAX=%d, should have been %d\n",
313 MY_ERR_MAX, i+1);
314 break;
315 }
316 /* Copy in actual library (i==0) or error (i>0) string */
317 if ( (errstr[i].string=strdup(my_errstr[i].string)) == NULL ) {
318 verify_error(oper,
319 "out of memory while duplicating errorstring %s\n",
320 my_errstr[i].string);
321 /* can safely break out of for-loop: we effectively truncate
322 * the list of errors earlier */
323 break;
324 }
325 /* Function code ==0 and reason !=0 sets the reasons */
326 errstr[i].error=ERR_PACK(library, 0, my_errstr[i].error);
327 }
328 /* Store the library and error strings */
329 ERR_load_strings(library,errstr);
330 }
331
332 #if OPENSSL_VERSION_NUMBER < 0x030000000L
333 /* Function part is deprecated in OpenSSL 3.0: therefore should not try
334 * to set it via ERR_PACK() or we'll overwrite our library part */
335
336 /* Allocate dynamically the array itself */
337 funcstr = (ERR_STRING_DATA*)calloc(sizeof(ERR_STRING_DATA), MY_FUNC_MAX);
338 if (funcstr == NULL) {
339 verify_error(oper, "out of memory while allocating funcstr[]\n");
340 } else {
341 /* Now copy in the data from the input array to the array that will be
342 * passed to ERR_load_strings() */
343 for (i=0; i<MY_FUNC_MAX-1; i++) {
344 /* Protect against too large value of MY_FUNC_MAX, since that would
345 * result in a strdup of NULL */
346 if ( my_funcstr[i].string == NULL) {
347 verify_log(L_WARN,
348 "Internal error: MY_FUNC_MAX=%d, should have been %d\n",
349 MY_FUNC_MAX, i+1);
350 break;
351 }
352 /* Copy in actual function string */
353 if ( (funcstr[i].string=strdup(my_funcstr[i].string)) == NULL) {
354 verify_error(oper,
355 "out of memory while duplicating functionstring %s\n",
356 my_funcstr[i].string);
357 /* can safely break out of for-loop: we effectively truncate
358 * the list of functions earlier */
359 break;
360 }
361 /* Function code !=0 and reason ==0 sets the reasons */
362 funcstr[i].error=ERR_PACK(library, my_funcstr[i].error, 0);
363 }
364 /* Store the function strings */
365 ERR_load_strings(library,funcstr);
366 }
367 #endif
368 }
369
370 /* Add our own OID entries
371 * NOTE: We inherit the proxy cert info extension
372 * fields from either OpenSSL or VOMS_Init via InitProxyCertInfoExtension()
373 * in proxycertinfo.c, unless we're running in standalone mode */
374
375 /* GT3 proxyCertInfo */
376 obj=OBJ_txt2obj(GLOBUS_PROXY_V3_OID,0);
377 nid=OBJ_obj2nid(obj); ASN1_OBJECT_free(obj);
378 if ( nid==NID_undef) {
379 verify_log(L_DEBUG, "Creating proxyCertInfo OID %s (%s)",
380 GLOBUS_PROXY_V3_OID, GLOBUS_PROXY_V3_LN);
381 if (init_GT3_proxy_extension())
382 verify_error(oper, "initialization of GT3 proxyCertInfo failed");
383 } else
384 verify_log(L_DEBUG, "Proxy Cert Info OID %s (%s) already exists",
385 GLOBUS_PROXY_V3_OID, OBJ_nid2ln(nid));
386
387 /* RFC proxyCertInfo */
388 obj=OBJ_txt2obj(RFC_PROXY_OID,0);
389 nid=OBJ_obj2nid(obj); ASN1_OBJECT_free(obj);
390 if ( nid==NID_undef) {
391 verify_log(L_DEBUG, "Creating proxyCertInfo OID %s (%s)",
392 RFC_PROXY_OID, RFC_PROXY_LN);
393 if (init_RFC_proxy_extension())
394 verify_error(oper, "initialization of RFC proxyCertInfo failed");
395 } else
396 verify_log(L_DEBUG, "Proxy Cert Info OID %s (%s) already exists",
397 RFC_PROXY_OID, OBJ_nid2ln(nid));
398
399 /* policy languages, first two are typically defined by OpenSSL or VOMS */
400 /* Standard proxy */
401 obj=OBJ_txt2obj(IMPERSONATION_PROXY_OID,0);
402 nid=OBJ_obj2nid(obj); ASN1_OBJECT_free(obj);
403 if ( nid==NID_undef) {
404 verify_log(L_DEBUG, "Creating language OID %s (%s)",
405 IMPERSONATION_PROXY_OID, IMPERSONATION_PROXY_LN);
406 OBJ_create(IMPERSONATION_PROXY_OID,
407 IMPERSONATION_PROXY_SN, IMPERSONATION_PROXY_LN);
408 } else
409 verify_log(L_DEBUG, "Language OID %s (%s) already exists",
410 IMPERSONATION_PROXY_OID, OBJ_nid2ln(nid));
411 /* Independent proxy */
412 obj=OBJ_txt2obj(INDEPENDENT_PROXY_OID,0);
413 nid=OBJ_obj2nid(obj); ASN1_OBJECT_free(obj);
414 if ( nid==NID_undef) {
415 verify_log(L_DEBUG, "Creating language OID %s (%s)",
416 INDEPENDENT_PROXY_OID, INDEPENDENT_PROXY_LN);
417 OBJ_create(INDEPENDENT_PROXY_OID,
418 INDEPENDENT_PROXY_SN, INDEPENDENT_PROXY_LN);
419 } else
420 verify_log(L_DEBUG, "Language OID %s (%s) already exists",
421 INDEPENDENT_PROXY_OID, OBJ_nid2ln(nid));
422 /* Any Language proxy */
423 obj=OBJ_txt2obj(ANY_LANGUAGE_OID,0);
424 nid=OBJ_obj2nid(obj); ASN1_OBJECT_free(obj);
425 if ( nid==NID_undef) {
426 verify_log(L_DEBUG, "Creating language OID %s (%s)",
427 ANY_LANGUAGE_OID, ANY_LANGUAGE_LN);
428 OBJ_create(ANY_LANGUAGE_OID,
429 ANY_LANGUAGE_SN, ANY_LANGUAGE_LN);
430 } else
431 verify_log(L_DEBUG, "Language OID %s (%s) already exists",
432 ANY_LANGUAGE_OID, OBJ_nid2ln(nid));
433 /* Limited proxy */
434 obj=OBJ_txt2obj(LIMITED_PROXY_OID,0);
435 nid=OBJ_obj2nid(obj); ASN1_OBJECT_free(obj);
436 if ( nid==NID_undef) {
437 verify_log(L_DEBUG, "Creating language OID %s (%s)",
438 LIMITED_PROXY_OID, LIMITED_PROXY_LN);
439 OBJ_create(LIMITED_PROXY_OID,
440 LIMITED_PROXY_SN, LIMITED_PROXY_LN);
441 } else
442 verify_log(L_DEBUG, "Language OID %s (%s) already exists",
443 LIMITED_PROXY_OID, OBJ_nid2ln(nid));
444
445 initialized=1;
446
447 return library;
448 }
449
450 /**
451 * Reads the private key from filename and stores the result in pkey
452 * Returns value of ERR_peek_error() on error or 0 on success.
453 */
454 unsigned long verify_x509_readPrivateKeyFromFile(char *filename, EVP_PKEY **pkey)
455 {
456 BIO *certbio = NULL;
457 verify_log( L_DEBUG, "--- Reading the Private Key From File ---");
458
459 if ( (certbio = BIO_new(BIO_s_file())) == NULL ) return ERR_peek_error();
460
461 verify_log( L_DEBUG, "Reading file %s", filename );
462 if ( BIO_read_filename(certbio, filename) <= 0 ) return ERR_peek_error();
463
464 verify_log( L_DEBUG, "Reading Private key" );
465 *pkey = PEM_read_bio_PrivateKey( certbio, NULL, grid_X509_empty_password_callback, NULL );
466
467 if ( *pkey == NULL ) verify_log( L_WARN, "No private key found." );
468
469 BIO_free_all(certbio);
470 return 0;
471 }
472
473
474 /**
475 * Reads the private key from PEM string and stores the result in pkey
476 * Returns value of ERR_get_error() on error or 0 on success.
477 */
478 unsigned long verify_x509_readPrivateKeyFromPEM (char * pem, EVP_PKEY **pkey)
479 {
480 BIO *certbio = NULL;
481 verify_log( L_DEBUG, "--- Reading the Private Key From PEM ---");
482
483 /* if ( (certbio = BIO_new(BIO_s_mem())) == NULL ) return ERR_get_error(); */
484
485 verify_log( L_DEBUG, "Reading PEM string");
486 if ( (certbio = BIO_new_mem_buf (pem, -1)) == NULL ) return ERR_peek_error();
487
488 verify_log( L_DEBUG, "Reading Private key" );
489 *pkey = PEM_read_bio_PrivateKey( certbio, NULL, grid_X509_empty_password_callback, NULL );
490
491 if ( *pkey == NULL ) verify_log( L_WARN, "No private key found." );
492
493 BIO_free_all(certbio);
494 return 0;
495 }
496
497
498 /**
499 * Reads the certificate chain from filename and stores the result in certstack
500 * Returns value of ERR_get_error() on error or 0 on success.
501 */
502 unsigned long verify_x509_readPublicCertChain(char *filename, STACK_OF(X509) **certstack)
503 {
504 const char *oper = "Reading proxy";
505
506 STACK_OF(X509_INFO) *sk = NULL;
507 BIO *certbio = NULL;
508 X509_INFO *xi;
509 unsigned long err;
510
511 verify_log( L_DEBUG, "--- Welcome to the %s function ---", oper);
512
513 *certstack = sk_X509_new_null();
514 if (*certstack == NULL) return ERR_peek_error();
515
516 if ( (certbio = BIO_new(BIO_s_file())) == NULL ) return ERR_peek_error();
517
518 verify_log( L_DEBUG, "Reading file %s", filename );
519 if ( BIO_read_filename(certbio, filename) <= 0 ) return ERR_peek_error();
520
521 verify_log( L_DEBUG, "Reading X509_INFO records" );
522 if ( !(sk=PEM_X509_INFO_read_bio(certbio, NULL, NULL, NULL)) )
523 {
524 err = ERR_peek_error();
525 verify_error( oper, "No X509 records found" );
526 BIO_free_all(certbio);
527 sk_X509_INFO_free(sk);
528 sk_X509_free(*certstack);
529 *certstack=NULL;
530 return err;
531 }
532
533 while (sk_X509_INFO_num(sk))
534 {
535 xi=sk_X509_INFO_shift(sk);
536 if (xi->x509 != NULL)
537 {
538 sk_X509_push(*certstack, xi->x509);
539 xi->x509=NULL;
540 }
541 X509_INFO_free(xi);
542 }
543
544 if (!sk_X509_num(*certstack))
545 {
546 err = ERR_peek_error();
547 verify_error( oper, "No certificates found" );
548 BIO_free_all(certbio);
549 sk_X509_INFO_free(sk);
550 sk_X509_free(*certstack);
551 *certstack=NULL;
552 return err;
553 }
554
555 BIO_free_all(certbio);
556 sk_X509_INFO_free(sk);
557
558 return 0;
559 }
560
561
562 /**
563 * Verifies a privatekey with the first cert in the certstack
564 * returns 0 on success, or appropriate value from ERR_peek_error().
565 */
566 unsigned long verify_verifyPrivateKey( STACK_OF(X509) *certstack, EVP_PKEY *pkey )
567 {
568 const char *oper="verify_verifyPrivateKey";
569 X509 *cert = NULL;
570
571 verify_log( L_DEBUG, "--- Welcome to the %s function ---", oper);
572
573 if ( pkey == NULL )
574 {
575 verify_log( L_WARN, "No private key available." );
576 return 0;
577 }
578
579 /* Check for X509 certificate and point to it with 'cert' */
580 if ((cert = sk_X509_value(certstack, 0)) != NULL)
581 {
582 verify_log( L_DEBUG, "X509_check_private_key" );
583 if ( X509_check_private_key( cert, pkey ) != 1 )
584 {
585 return ERR_peek_error();
586 }
587 }
588
589 return 0;
590 }
591
592
593 /**
594 * Validates a certificate with the CRL list and the signing CA
595 * Return 0 on success or result of ERR_peek_error() on error (to be fixed)
596 */
597 unsigned long verify_verifyCert( char * CA_DIR, STACK_OF(X509) *certstack, unsigned int verifyatnotbefore)
598 {
599 const char *oper = "Verifying certificate chain";
600
601 X509_STORE *store = NULL;
602 X509_LOOKUP *lookup = NULL;
603 X509_STORE_CTX *verify_ctx = NULL;
604 X509 *cert = NULL;
605 char * cert_DN = NULL;
606 char * issuer_DN = NULL;
607 int i = 0;
608 int depth = 0;
609 int fail_err;
610 int fail_depth;
611 X509 * fail_cert = NULL;
612 char * fail_dn = NULL;
613 unsigned long rc = 0;
614 time_t verificationtime;
615 char timebuf[30];
616 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
617 proxy_type_t cert_type = NONE;
618 #endif
619
620 verify_log( L_DEBUG, "--- Welcome to the %s function ---", __func__);
621
622 /* This is very important! We need to initialize at each invocation of
623 * verify_verifyCert() or we get problems in a service such as the SCAS */
624 chain_verify=0;
625
626 /* Initials must be good */
627 if ( CA_DIR == NULL )
628 {
629 verify_error( oper, "No CA certificate directory specified." );
630 return VERIFY_errval(VER_F_GRID_VERIFYCERT, VER_R_NO_CACERT);
631 }
632 if ( certstack == NULL )
633 {
634 verify_error( oper, "Certificate stack is empty." );
635 return VERIFY_errval(VER_F_GRID_VERIFYCERT, VER_R_CERTSTACK_EMPTY);
636 }
637
638 verify_log( L_DEBUG, "Using CA Directory: %s", CA_DIR);
639
640 verify_log( L_DEBUG, "X509_STORE_new");
641 if (!(store = X509_STORE_new()))
642 {
643 verify_error( oper, "Could not create a X509 STORE." );
644 return ERR_peek_error();
645 }
646
647 verify_log( L_DEBUG, "X509_STORE_set_verify_cb_func");
648 #if OPENSSL_VERSION_NUMBER < 0x010000000L
649 X509_STORE_set_verify_cb_func (store, grid_X509_verify_callback);
650 #else
651 X509_STORE_set_verify_cb (store, grid_X509_verify_callback);
652 #endif
653 #if 0
654 /* NOTE: the following two calls are defined in openssl ./crypto/x509/x509_d2.c
655 * (at least for openssl-1.0.0f)
656 * Also note that the X509_STORE_set_default_paths adds X509_LOOKUP_file (among
657 * others) which is effectively the file pointed at by the env variable
658 * SSL_CERT_FILE */
659 /* Executing the lookups to the CA and CRL files */
660 verify_log( L_DEBUG, "X509_STORE_load_locations");
661 if (X509_STORE_load_locations (store, NULL, CA_DIR) != 1)
662 {
663 verify_error( oper, "Could not load the CA directory.");
664 return ERR_get_error();
665 }
666
667 verify_log( L_DEBUG, "X509_STORE_set_default_paths");
668 if (X509_STORE_set_default_paths(store) != 1)
669 {
670 verify_error( oper, "Could not load the system wide CA certificates.");
671 return ERR_get_error();
672 }
673 #endif
674
675 /* Add CA_DIR, note: the next lines will effectively call dir_ctrl() from
676 * ./crypto/x509/by_dir.c with type X509_FILETYPE_PEM */
677 verify_log( L_DEBUG, "X509_STORE_add_lookup");
678 if (!(lookup = X509_STORE_add_lookup (store, X509_LOOKUP_hash_dir())))
679 {
680 verify_error( oper, "Could not create X509_LOOKUP object.");
681 rc=ERR_peek_error();
682 goto cleanup;
683 }
684
685 verify_log( L_DEBUG, "X509_LOOKUP_add_dir");
686 i=X509_LOOKUP_add_dir (lookup, CA_DIR, X509_FILETYPE_PEM);
687 if (!i)
688 {
689 verify_error( oper, "Could not add CA_DIR.");
690 rc=ERR_peek_error();
691 goto cleanup;
692 }
693
694 verify_log( L_DEBUG, "X509_STORE_set_flags");
695
696 #if OPENSSL_VERSION_NUMBER < 0x010100000L
697 store->check_issued = grid_X509_check_issued_wrapper;
698 #else
699 X509_STORE_set_check_issued(store, grid_X509_check_issued_wrapper);
700 #endif
701 #if OPENSSL_VERSION_NUMBER < 0x00908000L
702 X509_STORE_set_flags( store, X509_V_FLAG_CRL_CHECK |
703 X509_V_FLAG_CRL_CHECK_ALL );
704 #else
705 X509_STORE_set_flags( store, X509_V_FLAG_CRL_CHECK |
706 X509_V_FLAG_CRL_CHECK_ALL |
707 X509_V_FLAG_ALLOW_PROXY_CERTS );
708 #endif
709
710 /* Use last (proxy) certificate in chain */
711 cert = sk_X509_value( certstack, 0 );
712
713 /* Log the certificate subject and issuer DN. The X509_NAME_oneline() result
714 * without a provided buffer must be free'd */
715 cert_DN = X509_NAME_oneline( X509_get_subject_name( cert ) , NULL, 0 );
716 issuer_DN = X509_NAME_oneline( X509_get_issuer_name( cert ) , NULL, 0 );
717 verify_log( L_DEBUG, "Certificate to verify:" );
718 verify_log( L_DEBUG, " DN: \"%s\"", cert_DN ? cert_DN : "(NULL)");
719 verify_log( L_DEBUG, " Issuer DN: \"%s\"", issuer_DN ? issuer_DN : "(NULL)");
720 free(cert_DN);
721 free(issuer_DN);
722
723 /* Creating a verification context and init it */
724 verify_log( L_DEBUG, "X509_STORE_CTX_new");
725 if (!(verify_ctx = X509_STORE_CTX_new()))
726 {
727 verify_error( oper, "Could not create a X509 STORE CTX (context).");
728 rc=ERR_peek_error();
729 goto cleanup;
730 }
731
732 verify_log( L_DEBUG, "X509_STORE_CTX_init" );
733 if ( X509_STORE_CTX_init( verify_ctx, store, cert, certstack) != 1 )
734 {
735 verify_error( oper, "Could not initialize verification context.");
736 rc=ERR_peek_error();
737 goto cleanup;
738 }
739
740 if ( verifyatnotbefore ) {
741 verificationtime=verify_asn1TimeToTimeT(X509_get_notBefore(cert));
742 /* Add 5 minutes to verificationtime since many but not all tools
743 * backdate proxy certificates. Note that POSIX specifies that time_t is
744 * an integer or real representing seconds. */
745 verificationtime+=5*60;
746 if (strftime(timebuf, 30, "%F %T %Z", localtime(&verificationtime))==0){
747 verify_error(oper, "timebuf too small for verificationtime.");
748 verify_log( L_INFO, "Verifying at 'notBefore' time");
749 } else
750 verify_log( L_INFO, "Verifying at 'notBefore' time: %s", timebuf);
751 X509_VERIFY_PARAM_set_time(X509_STORE_CTX_get0_param(verify_ctx),
752 verificationtime);
753 } else
754 verify_log( L_DEBUG, "Verifying at current time");
755
756
757 X509_STORE_CTX_set_purpose( verify_ctx, X509_PURPOSE_SSL_CLIENT );
758 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
759 cert_type=verify_type_of_proxy(cert);
760 if ( CERTISTYPE(cert_type, EEC) || CERTISTYPE(cert_type, CA) ) {
761 verify_log( L_DEBUG, "Cert is not a proxy, NOT setting proxy flag");
762 } else {
763 verify_log( L_DEBUG, "Setting proxy flag");
764 #if OPENSSL_VERSION_NUMBER < 0x010100000L
765 cert->ex_flags |= EXFLAG_PROXY;
766 #else
767 X509_set_proxy_flag(cert);
768 #endif
769 }
770 #endif
771
772 /* Alter verification depth to fit the certificate chain, sub-CAs and root
773 * CA */
774 depth = sk_X509_num (certstack);
775 verify_log( L_DEBUG, "The certificate chain has a depth of %d. "
776 "For verification the depth is extended to fit the chain and "
777 "(subordinate) CAs to %d",
778 depth, depth + VERIFICATION_CHAIN_DEPTH_EXTENSION);
779 X509_STORE_CTX_set_depth (verify_ctx, depth + VERIFICATION_CHAIN_DEPTH_EXTENSION);
780
781 verify_log( L_DEBUG, "X509_verify_cert");
782
783 if ( X509_verify_cert(verify_ctx) != 1) {
784 /* Note: can also use verify_ctx->error, ->error_depth and
785 * ->current_cert, but is cleaner to use API */
786 fail_err=X509_STORE_CTX_get_error(verify_ctx);
787 fail_depth=X509_STORE_CTX_get_error_depth(verify_ctx);
788 if ( (fail_cert=X509_STORE_CTX_get_current_cert(verify_ctx)) )
789 fail_dn=X509_NAME_oneline(X509_get_subject_name(fail_cert),NULL,0);
790
791 verify_error("Verifying certificate chain", "error %d: %s",
792 fail_err, X509_verify_cert_error_string(fail_err));
793 verify_error("Failed at depth", "%d, DN: %s",
794 fail_depth, fail_dn ? fail_dn : "Not applicable");
795
796 free(fail_dn);
797
798 /* Note: X509_verify_cert() already pushes a error on the error stack
799 * using X509err() (wrapper around ERR_PUT_error() defined in
800 * openssl/err.h), and we have just printed the X509_V_* error code, so
801 * we can suffice with returning that the verification failed */
802 rc=VERIFY_errval(VER_F_GRID_VERIFYCERT, VER_R_X509_VERIFY_CERT_FAILURE);
803
804 } else {
805 verify_log( L_INFO, "The verification of the certificate has succeeded.");
806
807 rc=0;
808 }
809
810 cleanup:
811 if ( verify_ctx ) X509_STORE_CTX_free( verify_ctx );
812 if ( store ) X509_STORE_free( store );
813
814 return rc;
815 }
816
817 /**
818 * converts proxy_type_t certificate to human readable string
819 */
820 const char *verify_certificate_type_str(proxy_type_t cert_type) {
821 /* CA cert? */
822 if (CERTISTYPE(cert_type, CA))
823 return CA_TEXT;
824
825 /* EEC cert? */
826 if (CERTISTYPE(cert_type, EEC))
827 return EEC_TEXT;
828
829 /* Different proxy types? */
830 if (CERTISTYPE(cert_type, GT2_TYPE)) {
831 if (CERTISTYPE(cert_type, IMPERSONATION))
832 return GT2_TEXT IMPERSONATION_TEXT;
833 if (CERTISTYPE(cert_type, LIMITED))
834 return GT2_TEXT LIMITED_TEXT;
835 } else if (CERTISTYPE(cert_type, GT3_TYPE)) {
836 if (CERTISTYPE(cert_type, IMPERSONATION))
837 return GT3_TEXT IMPERSONATION_TEXT;
838 if (CERTISTYPE(cert_type, LIMITED))
839 return GT3_TEXT LIMITED_TEXT;
840 if (CERTISTYPE(cert_type, INDEPENDENT))
841 return GT3_TEXT INDEPENDENT_TEXT;
842 if (CERTISTYPE(cert_type, ANYLANG))
843 return GT3_TEXT ANYLANG_TEXT;
844 if (CERTISTYPE(cert_type, RESTRICTED))
845 return GT3_TEXT RESTRICTED_TEXT;
846 } else if (CERTISTYPE(cert_type, RFC_TYPE)) {
847 if (CERTISTYPE(cert_type, IMPERSONATION))
848 return RFC_TEXT IMPERSONATION_TEXT;
849 if (CERTISTYPE(cert_type, LIMITED))
850 return RFC_TEXT LIMITED_TEXT;
851 if (CERTISTYPE(cert_type, INDEPENDENT))
852 return RFC_TEXT INDEPENDENT_TEXT;
853 if (CERTISTYPE(cert_type, ANYLANG))
854 return RFC_TEXT ANYLANG_TEXT;
855 if (CERTISTYPE(cert_type, RESTRICTED))
856 return RFC_TEXT RESTRICTED_TEXT;
857 }
858
859 /* No known certificate type */
860 return "Unknown";
861 }
862
863
864 /******************************************************************************
865 * Internal functions
866 *****************************************************************************/
867
868 /**
869 * Callback function for PEM_read_bio_PrivateKey() and friends. See
870 * PEM_read_bio_PrivateKey(3ssl)
871 */
872 static int grid_X509_empty_password_callback(char *buf, int buf_size, int verify, void *cb_tmp)
873 {
874 if ( buf_size > 0 )
875 *buf = '\0';
876 return 0;
877 }
878
879
880 /**
881 * Callback function for OpenSSL to put the errors
882 * Parameters: ok, X509_STORE_CTX
883 * Returns: 1 on success, 0 on error
884 */
885 static int grid_X509_verify_callback(int ok, X509_STORE_CTX *ctx)
886 {
887 int errnum = X509_STORE_CTX_get_error(ctx);
888 int errdepth = X509_STORE_CTX_get_error_depth(ctx);
889
890 verify_log( L_DEBUG, "--- Welcome to the %s function ---", __func__);
891
892 /* When not ok... */
893 if (ok != 1)
894 {
895 verify_log( L_DEBUG,
896 "verification callback indicated \'ok = %d\', error number = %d (depth %d):",
897 ok, errnum, errdepth);
898
899 if (errnum == X509_V_ERR_INVALID_CA) {
900 verify_log( L_INFO, "Invalid CA at depth %d.", errdepth);
901 ok=1;
902 }
903 if (errnum == X509_V_ERR_UNABLE_TO_GET_CRL)
904 {
905 verify_log( L_INFO, "Unable to get CRL at depth %d.", errdepth);
906 ok=1;
907 }
908 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
909 /* I don't want to do this, really, but I have yet to figure out
910 how to get openssl 0.9.8 to accept old-style proxy certificates...
911 */
912 if (errnum == X509_V_ERR_INVALID_PURPOSE) {
913 verify_log( L_INFO, "Invalid purpose at depth %d.", errdepth);
914 ok=1;
915 }
916 #endif
917 if (errnum == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)
918 {
919 verify_log( L_DEBUG, "Unhandled critical extension at depth %d, running grid_X509_knownCriticalExts() to check if we know it.", errdepth);
920 errnum = grid_X509_knownCriticalExts(X509_STORE_CTX_get_current_cert(ctx));
921 X509_STORE_CTX_set_error(ctx, errnum);
922 if (errnum == X509_V_OK) ok=1;
923 }
924
925 /* Path length exceeded for the CA (should never happen in OpenSSL - famous last words) */
926 if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_PATH_LENGTH_EXCEEDED)
927 {
928 verify_log( L_DEBUG, "Shallow Error X509_V_ERR_PATH_LENGTH_EXCEEDED: Running alternative RFC5280 and RFC3820 compliance tests.");
929 #if OPENSSL_VERSION_NUMBER < 0x010100000L
930 errnum = grid_verifyChain(X509_STORE_CTX_get_chain(ctx));
931 #else
932 errnum = grid_verifyChain(X509_STORE_CTX_get0_chain(ctx));
933 #endif
934 X509_STORE_CTX_set_error(ctx, errnum);
935 if (errnum != X509_V_OK)
936 goto failure;
937 /* It's ok */
938 ok=1;
939 }
940
941 /* Path length exceeded for the Proxy! -> Override and continue */
942 /* This is NOT about X509_V_ERR_PATH_LENGTH_EXCEEDED */
943 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
944 if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED)
945 {
946 verify_log( L_DEBUG, "Shallow Error X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: Running alternative RFC5280 and RFC3820 compliance tests.");
947 #if OPENSSL_VERSION_NUMBER < 0x010100000L
948 errnum = grid_verifyChain(X509_STORE_CTX_get_chain(ctx));
949 #else
950 errnum = grid_verifyChain(X509_STORE_CTX_get0_chain(ctx));
951 #endif
952 X509_STORE_CTX_set_error(ctx, errnum);
953 if (errnum != X509_V_OK)
954 goto failure;
955 /* It's ok */
956 ok=1;
957 }
958 #endif
959 }
960
961 /*
962 * We've now got the last certificate - the identity being used for
963 * this connection. At this point we check the whole chain for valid
964 * CAs or, failing that, GSI-proxy validity using grid_verifyProxy
965 */
966 if ((errdepth == 0) && (ok == 1)) {
967 /* I'm in the OK state - Let's see if the chain is really well
968 * formed:\ */
969 #if OPENSSL_VERSION_NUMBER < 0x010100000L
970 errnum = grid_verifyChain(X509_STORE_CTX_get_chain(ctx));
971 #else
972 errnum = grid_verifyChain(X509_STORE_CTX_get0_chain(ctx));
973 #endif
974 X509_STORE_CTX_set_error(ctx, errnum);
975 if (errnum != X509_V_OK)
976 goto failure;
977 }
978
979 /* Ready and probably ok */
980 return ok;
981
982 failure:
983 /* Indicate failure */
984 ok = 0;
985 errnum = X509_STORE_CTX_get_error(ctx);
986 verify_log( L_INFO, "grid_verify_callback: error code: %d, message: \"%s\"",
987 errnum, X509_verify_cert_error_string(errnum));
988
989 return ok;
990 }
991
992 /**
993 * Checks the certificate chain on CA based (RFC5280) and RFC3820 Proxy based
994 * Path Length Constraints.
995 * Returns X509_V_OK on successful verification or a suitable error code on
996 * any error (default X509_V_ERR_CERT_REJECTED).
997 */
998 static int grid_verifyChain(STACK_OF(X509) * chain)
999 {
1000 const char *oper = "grid_verifyChain";
1001 X509 *cert = NULL;
1002 int i, depth, proxylevel=-1;
1003 proxy_type_t curr_cert_type = NONE;
1004 /* Note: cannot define expe_cert_type as proxy_type_t since it's a
1005 * combination of them */
1006 int expe_cert_type = CA|EEC|ANY_PROXY_VERSION|ALL_LANGUAGE;
1007 int found_EEC = 0;
1008 char *cert_subjectdn = NULL, *cert_issuerdn = NULL;
1009 size_t len_subject, len_issuer;
1010 char *expected_sub_msg = NULL;
1011
1012 EVP_PKEY *ca_key=NULL;
1013 int result;
1014 ASN1_OBJECT *vomsobj=NULL;
1015 int voms_proxy_pos = -1;
1016
1017 long cert_ex_pathlen = -1;
1018 long ca_path_len_countdown = -1;
1019 long proxy_path_len_countdown = -1;
1020 long ex_pcpathlen = -1;
1021
1022 char *serialstr;
1023 unsigned long hash;
1024 GENERAL_NAMES *sANs;
1025 GENERAL_NAME *sAN;
1026 CERTIFICATEPOLICIES *pols;
1027 POLICYINFO *pol;
1028 unsigned char *utext;
1029 char buffer[OBJ_TEXT_LEN];
1030 int j, num;
1031
1032 time_t now = time((time_t *)NULL);
1033 ASN1_INTEGER *cert_Serial=NULL, *issuer_Serial=NULL;
1034
1035 int rc=X509_V_ERR_CERT_REJECTED;
1036
1037 verify_log( L_DEBUG, "--- Welcome to the %s function, run %d ---", oper, chain_verify);
1038
1039 /* Note: the callback is called once for each error, so if we have multiple
1040 * errors at level 0, we would be called here multiple times with the same
1041 * chain: if we have already verified succesfully, just reuse the result */
1042 if (chain_verify) {
1043 chain_verify++;
1044 return X509_V_OK;
1045 }
1046
1047 /* No chain, no game */
1048 if (!chain) {
1049 verify_error( oper, "No certificate chain detected.");
1050 goto failure;
1051 }
1052
1053 /* Go through the list, from the CA(s) down through the EEC to the final
1054 * delegation */
1055 depth = sk_X509_num (chain);
1056 for (i=depth-1; i >= 0; --i) {
1057 if ((cert = sk_X509_value(chain, i))) {
1058 /* Init to None, indicating not to have identified it yet */
1059 curr_cert_type = NONE;
1060
1061 /* Extract Subject DN - Needs free */
1062 if (!(cert_subjectdn = X509_NAME_oneline (X509_get_subject_name (cert), NULL, 0))) {
1063 verify_error (oper, "Couldn't get the subject DN from the certificate at depth %d", depth);
1064 goto failure;
1065 }
1066
1067 /* verify_log (L_DEBUG, "\tCert here is: %s", cert_subjectdn); */
1068 curr_cert_type = verify_type_of_proxy(cert);
1069 if (curr_cert_type == NONE) {
1070 verify_error (oper, "Couldn't classify certificate at depth %d with subject DN \"%s\"",
1071 depth, cert_subjectdn);
1072 goto failure;
1073 }
1074
1075 /* Mark that we've found an EEC - When we see it again, it's a
1076 * failure, this would otherwise also be caught by the 'expectation
1077 * management tests' below */
1078 if (CERTISTYPE(curr_cert_type, EEC) && found_EEC == 0) {
1079 found_EEC = 1;
1080 } else if (CERTISTYPE(curr_cert_type, EEC) && found_EEC == 1) {
1081 verify_error (oper, "Found another EEC certificate in the same chain at depth %d of %d with subject DN \"%s\"",
1082 i, depth, cert_subjectdn);
1083 goto failure;
1084 }
1085
1086 /* Expectation management */
1087 if ( !CERTISTYPE(expe_cert_type, (int)curr_cert_type) ) {
1088 /* Failed to comply with the expectations! */
1089 expected_sub_msg=grid_get_expected_proxy_string(expe_cert_type);
1090 #ifdef USE_STRICT_PATH_VALIDATION
1091 verify_error(oper, "Certificate chain not build in the right order: Got %s certificate, but expected %s. Cert at depth %d of %d with Subject DN: %s",
1092 verify_certificate_type_str(curr_cert_type), expected_sub_msg,
1093 i,
1094 depth,
1095 cert_subjectdn);
1096 free(expected_sub_msg);
1097 goto failure;
1098 #else
1099 verify_log(L_WARN, "%s: Certificate chain not build in the right order: Got %s certificate, but expected %s. Cert at depth %d of %d with Subject DN: %s. Cert at depth %d of %d with Subject DN: %s",
1100 oper,
1101 verify_certificate_type_str(curr_cert_type), expected_sub_msg,
1102 i,
1103 depth,
1104 cert_subjectdn);
1105 free(expected_sub_msg);
1106 #endif
1107 }
1108
1109
1110 if (CERTISTYPE(curr_cert_type, CA)) {
1111 /* Expected next certificate type is: CA or EEC certificate */
1112 expe_cert_type = CA|EEC;
1113
1114 /* Are we a root CA? Check whether we are self-signed: first get
1115 * public key */
1116 if ( (ca_key = X509_get_pubkey(cert)) ==NULL ) {
1117 verify_error(oper, "cannot get public key from CA cert");
1118 goto failure;
1119 }
1120 /* Check that certificate is self-signed:
1121 * returns 1 on success, <= 0 for error */
1122 result = X509_verify(cert, ca_key);
1123
1124 /* Free memory */
1125 EVP_PKEY_free(ca_key);
1126
1127 if (result == 1) { /* signature check succeeded */
1128 /* root CA, log, don't check sig alg (no point) */
1129 verify_log (L_INFO, "Cert at depth %d is a root CA: \"%s\"", i, cert_subjectdn);
1130 } else if (result == 0) { /* signature check failed */
1131 /* Clear error stack (the signature failed) */
1132 while(ERR_get_error());
1133 verify_log (L_INFO, "Cert at depth %d is a CA: \"%s\"", i, cert_subjectdn);
1134 /* Check signature algorithm */
1135 if (grid_check_sigalg(cert)<0) {
1136 rc=X509_V_ERR_CERT_SIGNATURE_FAILURE;
1137 goto failure;
1138 }
1139 } else { /* signature couldn't be checked because it was invalid or some other error occurred */
1140 verify_error(oper, "Error while trying to verify CA cert with CA key");
1141 rc=X509_V_ERR_CERT_SIGNATURE_FAILURE;
1142 goto failure;
1143 }
1144
1145 /* Now check the public key strength */
1146 grid_check_keylength(cert, 2048);
1147
1148 /* Exceeded CA Path Length ? */
1149 if (ca_path_len_countdown == 0) {
1150 verify_error(oper, "CA Path Length Constraint exceeded on depth %d for certificate \"%s\". No CA certificates were expected at this stage.", i, cert_subjectdn);
1151 rc=X509_V_ERR_PATH_LENGTH_EXCEEDED;
1152 goto failure;
1153 }
1154
1155 /* Store pathlen, override when small, otherwise keep the
1156 * smallest */
1157 #if OPENSSL_VERSION_NUMBER < 0x010100000L
1158 cert_ex_pathlen = cert->ex_pathlen;
1159 #else
1160 cert_ex_pathlen = X509_get_pathlen(cert);
1161 #endif
1162 if (cert_ex_pathlen != -1) {
1163 /* Update when ca_path_len_countdown is the initial value
1164 * or when the PathLenConstraint is smaller then the
1165 * remembered ca_path_len_countdown */
1166 if ((ca_path_len_countdown == -1) || (cert_ex_pathlen < ca_path_len_countdown)) {
1167 ca_path_len_countdown = cert_ex_pathlen;
1168 } else {
1169 /* If a path length was already issued, lower
1170 * ca_path_len_countdown */
1171 if (ca_path_len_countdown != -1)
1172 ca_path_len_countdown--;
1173 }
1174 } else {
1175 /* If a path length was already issued, lower
1176 * ca_path_len_countdown */
1177 if (ca_path_len_countdown != -1)
1178 ca_path_len_countdown--;
1179 }
1180
1181 /* continue to next cert in chain */
1182 free(cert_subjectdn);
1183 cert_subjectdn = NULL;
1184 continue;
1185
1186 } else if (CERTISTYPE(curr_cert_type, EEC)) {
1187 /* Expected next certificate type is any type of proxy */
1188 expe_cert_type = ANY_PROXY_VERSION | ALL_LANGUAGE;
1189
1190 /* Log certificate DN */
1191 verify_log (L_INFO,
1192 "Cert at depth %d is an EEC: \"%s\"", i, cert_subjectdn);
1193
1194 /* Check signature algorithm */
1195 if (grid_check_sigalg(cert)<0) {
1196 rc=X509_V_ERR_CERT_SIGNATURE_FAILURE;
1197 goto failure;
1198 }
1199
1200 /* Now check the public key strength */
1201 grid_check_keylength(cert, 2048);
1202
1203 /* Get the serial string and hash */
1204 serialstr=grid_get_serialStr(X509_get_serialNumber(cert));
1205 hash=X509_NAME_hash(X509_get_issuer_name(cert));
1206
1207 /* Log certificate CA hash and serial number */
1208 verify_log (L_INFO,
1209 " CA hash: %lx, serial: %s", hash, serialstr);
1210
1211 free(serialstr);
1212
1213 /* Get Subject Alternative Names */
1214 sANs = X509_get_ext_d2i( cert, NID_subject_alt_name, 0, 0 );
1215
1216 if (sANs) {
1217 num = sk_GENERAL_NAME_num( sANs );
1218 for (j=0; j<num; j++) {
1219 /* Get number of altnames */
1220 sAN=sk_GENERAL_NAME_value( sANs, j );
1221 if( GEN_DNS == sAN->type ) { /* dNSName */
1222 ASN1_STRING_to_UTF8( &utext, sAN->d.dNSName );
1223 verify_log(L_INFO,
1224 " subjAltName dNSName: %s", utext);
1225 OPENSSL_free(utext);
1226 } else if (GEN_EMAIL == sAN->type ) { /* email */
1227 ASN1_STRING_to_UTF8( &utext, sAN->d.rfc822Name );
1228 verify_log(L_INFO,
1229 " subjAltName rfc822Name: %s", utext);
1230 OPENSSL_free(utext);
1231 }
1232 }
1233 GENERAL_NAMES_free(sANs);
1234 }
1235
1236 /* Get Certificate Policies */
1237 pols = X509_get_ext_d2i( cert, NID_certificate_policies, 0, 0);
1238 if (pols) {
1239 /* Get number of policy OIDs */
1240 num = sk_POLICYINFO_num( pols );
1241 for (j=0; j<num; j++) {
1242 pol = sk_POLICYINFO_value( pols, j);
1243 /* OBJ_obj2txt(3ssl) says that 80 should be more than
1244 * enough */
1245 OBJ_obj2txt(buffer, OBJ_TEXT_LEN, pol->policyid, 0);
1246 verify_log(L_INFO, " policy OID: %s", buffer);
1247 }
1248 CERTIFICATEPOLICIES_free(pols);
1249 }
1250
1251 /* continue to next cert in chain */
1252 free(cert_subjectdn);
1253 cert_subjectdn=NULL;
1254 continue;
1255
1256 }
1257 /* Remainder are proxies */
1258
1259 /* Set expected type of next proxy */
1260
1261 /* First map onto the basic type: expected type must be same as the
1262 * current one */
1263 expe_cert_type = (curr_cert_type & ANY_PROXY_VERSION);
1264
1265 /* For a limited proxy, the next one must be limited, otherwise, any
1266 * proxy language is fine */
1267 if ( CERTISTYPE(curr_cert_type, LIMITED) )
1268 expe_cert_type |= LIMITED;
1269 else
1270 expe_cert_type |= ALL_LANGUAGE;
1271
1272 /* Check whether we see a VOMS extension */
1273 vomsobj=OBJ_txt2obj(VOMS_AC_OID,0);
1274 voms_proxy_pos=X509_get_ext_by_OBJ(cert, vomsobj, -1);
1275 ASN1_OBJECT_free(vomsobj);
1276
1277 verify_log (L_INFO, "Cert at depth %d (proxylevel %d) is a %s%s: \"%s\"",
1278 i, ++proxylevel,
1279 (voms_proxy_pos==-1 ? "" : "VOMS "),
1280 verify_certificate_type_str(curr_cert_type),
1281 cert_subjectdn);
1282
1283 /* Check signature algorithm */
1284 if (grid_check_sigalg(cert)<0) {
1285 rc=X509_V_ERR_CERT_SIGNATURE_FAILURE;
1286 goto failure;
1287 }
1288
1289 /* Now check the public key strength */
1290 grid_check_keylength(cert, 0);
1291
1292 /* Check expire time */
1293 time(&now);
1294
1295 if (now < verify_asn1TimeToTimeT(X509_get_notBefore(cert)))
1296 {
1297 verify_error( oper, "Proxy certificate at proxy-level %d is not yet valid.", proxylevel);
1298 /* error will be caught later by x509_verify: don't do yet to get also more
1299 * serious errors.*/
1300 /* rc=X509_V_ERR_CERT_NOT_YET_VALID;
1301 goto failure;*/
1302 }
1303
1304 if (now > verify_asn1TimeToTimeT(X509_get_notAfter(cert)))
1305 {
1306 verify_error( oper, "Proxy certificate at proxy-level %d expired.", proxylevel);
1307 /* error will be caught later by x509_verify: don't do yet to get also more
1308 * serious errors.*/
1309 /* return X509_V_ERR_CERT_HAS_EXPIRED;
1310 * goto failure;*/
1311 }
1312
1313 /* Get issuer to check subject matches it */
1314 if (!(cert_issuerdn = X509_NAME_oneline( X509_get_issuer_name( cert ), NULL, 0))) {
1315 verify_error( oper, "Couldn't get the issuer DN at proxy-level %d.", proxylevel);
1316 rc=X509_V_ERR_OUT_OF_MEM;
1317 goto failure;
1318 }
1319
1320 len_subject = strlen( cert_subjectdn );
1321 len_issuer = strlen( cert_issuerdn );
1322 if (len_issuer>=len_subject || strncmp(cert_subjectdn, cert_issuerdn, len_issuer) != 0) {
1323 verify_error( oper,
1324 "Proxy subject must begin with the issuer, DN \"%s\", Issuer \"%s\"",
1325 cert_subjectdn, cert_issuerdn);
1326 rc=X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
1327 goto failure;
1328 }
1329
1330 /* Do all proxy Path Length checks */
1331 if ( CERTISTYPE(curr_cert_type, RFC_TYPE) || CERTISTYPE(curr_cert_type, GT3_TYPE) ) {
1332 /* Exceeded CA Path Length ? */
1333 if (proxy_path_len_countdown == 0) {
1334 verify_error(oper, "Proxy Path Length Constraint exceeded on depth %d of %d for certificate \"%s\". No Proxy certificates were expected at this stage.", i, depth, cert_subjectdn);
1335 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
1336 rc=X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
1337 #endif
1338 goto failure;
1339 }
1340
1341 /* Store pathlen, override when small, otherwise keep the smallest */
1342 ex_pcpathlen=get_proxy_pathlength(cert, curr_cert_type);
1343 if (ex_pcpathlen != -1) {
1344 /* Update when proxy_path_len_countdown is the initial value
1345 * or when the PathLenConstraint is smaller then the
1346 * remembered proxy_path_len_countdown */
1347
1348 if ((proxy_path_len_countdown == -1) || (ex_pcpathlen < proxy_path_len_countdown)) {
1349 proxy_path_len_countdown = ex_pcpathlen;
1350 verify_log (L_DEBUG, "Cert here is: %s -> Setting proxy path len constraint to: %ld", cert_subjectdn, ex_pcpathlen);
1351 } else {
1352 /* If a path length was already issuesd, lower ca_path_len_countdown */
1353 if (proxy_path_len_countdown != -1)
1354 proxy_path_len_countdown--;
1355
1356 verify_log (L_DEBUG, "Cert here is: %s -> Countdown is at %ld", cert_subjectdn, proxy_path_len_countdown);
1357 }
1358 } else {
1359 /* If a path length was already issued, lower ca_path_len_countdown */
1360 if (proxy_path_len_countdown != -1) {
1361 proxy_path_len_countdown--;
1362 verify_log (L_DEBUG, "Cert here is: %s -> Countdown is at %ld", cert_subjectdn, proxy_path_len_countdown);
1363 }
1364 }
1365 } else { /* i.e. legacy proxy */
1366 /* Check serial numbers match for old style proxy */
1367 cert_Serial =X509_get_serialNumber(cert);
1368 issuer_Serial=X509_get_serialNumber(sk_X509_value(chain, i+1));
1369 if ( (serialstr=grid_get_serialStr(cert_Serial)) ) {
1370 verify_log( L_DEBUG, "Serial number: %s", serialstr);
1371 free(serialstr);
1372 }
1373 if ( (serialstr=grid_get_serialStr(issuer_Serial)) ) {
1374 verify_log( L_DEBUG, "Issuer serial number: %s", serialstr);
1375 free(serialstr);
1376 }
1377
1378 if ( ASN1_INTEGER_cmp( cert_Serial, issuer_Serial ) )
1379 verify_log( L_WARN, "Serial numbers do not match." );
1380 }
1381
1382 /* Free memory during each cycle */
1383 free(cert_subjectdn);
1384 free(cert_issuerdn);
1385 cert_subjectdn = cert_issuerdn = NULL;
1386 }
1387 }
1388
1389 /* When we're here we should have ended with either a proxy or an EEC */
1390
1391 /* If we're now a CA there's something wrong */
1392 if (CERTISTYPE(curr_cert_type, CA)) {
1393 verify_error( oper, "No personal certificate (neither proxy or user certificate) found in the certficiate stack." );
1394 goto failure;
1395 }
1396
1397 /* If we're now an EEC we don't have any proxies */
1398 if (CERTISTYPE(curr_cert_type, EEC))
1399 verify_log( L_WARN, "No proxy certificate in certificate stack to check." );
1400
1401 /*success:*/
1402 /* Return an OK (thumbs up) in the grid_X509_verify_callback() */
1403 /* keep track of successful verifications */
1404 ++chain_verify;
1405
1406 return X509_V_OK;
1407
1408 failure:
1409 free(cert_subjectdn);
1410 free(cert_issuerdn);
1411 return rc;
1412 }
1413
1414 /**
1415 * Obtains proxy pathlength constraint for GT3 and RFC type proxies
1416 */
1417 static long get_proxy_pathlength(X509 *cert, proxy_type_t proxy_type) {
1418 #if OPENSSL_VERSION_NUMBER < 0x00908000L
1419 PROXYCERTINFO *info_rfc=NULL;
1420 #endif
1421 PROXYCERTINFO_GT3 *info_gt3=NULL;
1422 long ex_pcpathlen=-1;
1423
1424 if ( CERTISTYPE(proxy_type, GT3_TYPE) ) {
1425 info_gt3=X509_get_ext_d2i( cert, OBJ_txt2nid(GLOBUS_PROXY_V3_OID), NULL, NULL);
1426 if (info_gt3 && info_gt3->path_length)
1427 ex_pcpathlen=ASN1_INTEGER_get(info_gt3->path_length);
1428 PROXYCERTINFO_GT3_free(info_gt3);
1429 } else if ( CERTISTYPE(proxy_type, RFC_TYPE) ) {
1430 /* OpenSSL pre-0.9.8 has no proxy support and hence no ex_pcpathlen in X509,
1431 * then we use our own */
1432 #if OPENSSL_VERSION_NUMBER < 0x00908000L
1433 info_rfc=X509_get_ext_d2i( cert, OBJ_txt2nid(RFC_PROXY_OID), NULL, NULL);
1434 if (info_rfc && info_rfc->path_length)
1435 ex_pcpathlen=ASN1_INTEGER_get(info_rfc->path_length);
1436 PROXYCERTINFO_free(info_rfc);
1437 #elif OPENSSL_VERSION_NUMBER < 0x010100000L
1438 ex_pcpathlen=cert->ex_pcpathlen;
1439 #else
1440 ex_pcpathlen=X509_get_proxy_pathlen(cert);
1441 #endif
1442 }
1443
1444 /* Other types do not have proxy pathlength */
1445 return ex_pcpathlen;
1446 }
1447
1448
1449 /**
1450 * Checks to see if one of the unsupported critical extensions is a valid proxy
1451 * type.
1452 * Returns X509_V_OK on success or X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION on
1453 * error
1454 */
1455 static int grid_X509_knownCriticalExts(X509 *cert)
1456 {
1457 int i;
1458 char s[OBJ_TEXT_LEN];
1459 X509_EXTENSION *ex;
1460
1461 for (i = 0; i < X509_get_ext_count(cert); ++i) {
1462 ex = X509_get_ext(cert, i);
1463
1464 if (X509_EXTENSION_get_critical(ex) &&
1465 !X509_supported_extension(ex))
1466 {
1467 OBJ_obj2txt(s, OBJ_TEXT_LEN, X509_EXTENSION_get_object(ex), 1);
1468
1469 verify_log( L_DEBUG, "Critical extension found: %s", s );
1470
1471 if (strcmp(s, RFC_PROXY_OID) == 0 ||
1472 strcmp(s, GLOBUS_PROXY_V3_OID) == 0)
1473 return X509_V_OK;
1474
1475 return X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
1476 }
1477 }
1478
1479 return X509_V_OK;
1480 }
1481
1482 /**
1483 * Check if we can safely discards errors about the issuer
1484 * Returns 1 when issuer is fine, 0 when no.
1485 */
1486 static int grid_X509_check_issued_wrapper(X509_STORE_CTX *ctx,X509 *x,X509 *issuer)
1487 /* We change the default callback to use our wrapper and discard errors
1488 due to GSI proxy chains (ie where users certs act as CAs) */
1489 {
1490 int ret;
1491 unsigned long flags;
1492 #if OPENSSL_VERSION_NUMBER >= 0x010100000L
1493 X509_STORE_CTX_verify_cb callback;
1494 #endif
1495
1496 ret = X509_check_issued(issuer, x);
1497 if (ret == X509_V_OK) return 1;
1498
1499 /* Non self-signed certs without signing are ok if they passed
1500 the other checks inside X509_check_issued. Is this enough? */
1501 if ((ret == X509_V_ERR_KEYUSAGE_NO_CERTSIGN) &&
1502 (X509_NAME_cmp(X509_get_subject_name(issuer),
1503 X509_get_subject_name(x)) != 0)) return 1;
1504
1505 #if OPENSSL_VERSION_NUMBER < 0x00908000L
1506 /* If we haven't asked for issuer errors don't set ctx */
1507 flags = ctx->flags;
1508 #else
1509 flags = X509_VERIFY_PARAM_get_flags(X509_STORE_CTX_get0_param(ctx));
1510 #endif
1511
1512 if (!(flags & X509_V_FLAG_CB_ISSUER_CHECK))
1513 return 0;
1514
1515 X509_STORE_CTX_set_error(ctx, ret);
1516 #if OPENSSL_VERSION_NUMBER < 0x010100000L
1517 ctx->current_cert = x;
1518 /* Not clear if next one is necessary... */
1519 ctx->current_issuer = issuer;
1520
1521 /* verify_cb() returns 1 on ok. */
1522 return ctx->verify_cb(0, ctx);
1523 #else
1524 X509_STORE_CTX_set_current_cert(ctx, x);
1525
1526 /* verify_cb() returns 1 on ok. */
1527 callback = X509_STORE_CTX_get_verify_cb(ctx);
1528 return callback(0, ctx);
1529 #endif
1530 }
1531
1532 /**
1533 * Print and verify the key strength for given certificate, on L_WARN for
1534 * smaller than given mininum keylength. For length == 0, use default 1024
1535 * Returns -1 on error (cannot retrieve pubkey or keylength)
1536 */
1537 static int grid_check_keylength(X509 *cert, int minlength) {
1538 const char *oper = "grid_check_keylength";
1539 EVP_PKEY *pkey = NULL;
1540 int key_strength;
1541 int min_strength=(minlength ? minlength : 1024);
1542 int rc=-1;
1543
1544 if ( (pkey=X509_get_pubkey(cert)) == NULL ) {
1545 verify_error( oper, "Cannot retrieve public key.");
1546 rc=-1;
1547 } else {
1548 #if OPENSSL_VERSION_NUMBER < 0x010100000L
1549 /* EVP_PKEY_id already exists since 0.9.9 but this makes it easier */
1550 if (pkey->type == EVP_PKEY_RSA) {
1551 key_strength = BN_num_bits(pkey->pkey.rsa->n);
1552 #else
1553 if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
1554 key_strength = RSA_bits(EVP_PKEY_get0_RSA(pkey));
1555 #endif
1556 if (key_strength < min_strength)
1557 verify_log(L_WARN, " Key strength too low: %d (<%d)",
1558 key_strength, min_strength);
1559 else
1560 verify_log( L_INFO, " Key strength: %d", key_strength );
1561 rc=0;
1562 } else {
1563 verify_log( L_DEBUG, "No RSA public key found?!?" );
1564 rc=-1;
1565 }
1566 /* Cleanup memory */
1567 EVP_PKEY_free(pkey);
1568 }
1569 return rc;
1570 }
1571
1572 /**
1573 * Print the signature algorithm for given certificate, on L_WARN for deprecated
1574 * algorithms
1575 * Returns 0 when still acceptable, -1 when too old or unknown
1576 */
1577 static int grid_check_sigalg(X509 *cert) {
1578 const char *oper = "grid_check_sigalg";
1579 const ASN1_OBJECT *algorithm;
1580 char buffer[OBJ_TEXT_LEN];
1581 int nid;
1582 const char *sigalg_text="";
1583
1584 #if OPENSSL_VERSION_NUMBER < 0x010100000L
1585 algorithm = cert -> sig_alg -> algorithm;
1586 #else
1587 /* Try to get the OID */
1588 const X509_ALGOR *x509_sig_alg;
1589 X509_get0_signature(NULL, &x509_sig_alg, cert);
1590 X509_ALGOR_get0(&algorithm, NULL, NULL, x509_sig_alg);
1591 #endif
1592
1593 /* Get the OID for the algorithm */
1594 OBJ_obj2txt(buffer, OBJ_TEXT_LEN, algorithm, 1);
1595
1596 /* Try to get signature algorithm and convert to long name,
1597 * for > 1.1 can use X509_get_signature_nid(cert) */
1598 if ( (nid = OBJ_obj2nid(algorithm)) != NID_undef )
1599 sigalg_text=OBJ_nid2ln(nid);
1600
1601 switch (nid) {
1602 case NID_undef:
1603 verify_error(oper, " Unknown signature algorithm %s", buffer);
1604 return -1;
1605 case NID_md2WithRSAEncryption:
1606 case NID_md4WithRSAEncryption:
1607 case NID_shaWithRSAEncryption:
1608 verify_error(oper, " Ancient signature algorithm: %s (=%s)",
1609 sigalg_text, buffer);
1610 return -1;
1611 case NID_md5WithRSAEncryption:
1612 case NID_sha1WithRSAEncryption:
1613 verify_log(L_WARN, " Deprecated signature algorithm: %s (=%s)",
1614 sigalg_text, buffer);
1615 break;
1616 default:
1617 verify_log(L_INFO, " signature algorithm: %s (=%s)",
1618 sigalg_text, buffer);
1619 break;
1620 }
1621 return 0;
1622 }
1623
1624
1625
1626 /**
1627 * Converts the ASN1_INTEGER serial into a string
1628 * Returns a pointer to a buffer-to-be-freed or NULL on error
1629 */
1630 static char *grid_get_serialStr(ASN1_INTEGER *serial) {
1631 const char *oper = "grid_get_serialStr";
1632 BIGNUM *bn_serial;
1633 char *serialStr;
1634
1635 if ( serial == NULL ||
1636 (bn_serial = ASN1_INTEGER_to_BN(serial, NULL)) == NULL ||
1637 (serialStr=BN_bn2hex(bn_serial)) == NULL ) {
1638 verify_error( oper,
1639 "Cannot convert ASN1_INTEGER serial to char *");
1640 return NULL;
1641 }
1642
1643 BN_clear_free(bn_serial);
1644 return serialStr;
1645 }
1646
1647 /**
1648 * Constructs string printing the expected types of certificates in human
1649 * readable form.
1650 * Parameters:
1651 * int expected_proxy_type : bitfield of types of certificates that we
1652 * expected.
1653 * Returns:
1654 * char *message, MUST be free'd, NULL on error
1655 */
1656 static char *grid_get_expected_proxy_string(int expected_proxy_type) {
1657 const char *oper = __func__;
1658 int prev=0, proxy=0, type=0;
1659 int len;
1660 size_t buflen=0;
1661 char *buf=NULL, *pos=NULL;
1662
1663 if ( CERTISTYPE(expected_proxy_type, CA) ) {
1664 buflen+=strlen(CA_TEXT);
1665 prev=1;
1666 }
1667 if ( CERTISTYPE(expected_proxy_type, EEC) ) {
1668 buflen+=(prev ? 4+strlen(EEC_TEXT) : strlen(EEC_TEXT));
1669 prev=1;
1670 }
1671 /* Handle all proxy version specially */
1672 if ( CERTISTYPE(expected_proxy_type, ANY_PROXY_VERSION) ) {
1673 buflen+=(prev ? 4+strlen(ANY_PROXY_TEXT) : strlen(ANY_PROXY_TEXT));
1674 prev=proxy=1;
1675 } else { /* Now check individual proxy versions */
1676 if ( CERTISTYPE(expected_proxy_type, GT2_TYPE) ) {
1677 buflen+=(prev ? 4+strlen(GT2_TEXT) : strlen(GT2_TEXT));
1678 prev=proxy=1;
1679 }
1680 if ( CERTISTYPE(expected_proxy_type, GT3_TYPE) ) {
1681 buflen+=(prev ? 4+strlen(GT3_TEXT) : strlen(GT3_TEXT));
1682 prev=proxy=1;
1683 }
1684 if ( CERTISTYPE(expected_proxy_type, RFC_TYPE) ) {
1685 buflen+=(prev ? 4+strlen(RFC_TEXT) : strlen(RFC_TEXT));
1686 prev=proxy=1;
1687 }
1688 /* Check whether we matched any type of cert */
1689 if (prev==0) {
1690 verify_error(oper, "Cannot determine basic certificate type");
1691 return NULL;
1692 }
1693 }
1694
1695 if (proxy==1) {
1696 /* First handle all proxy languages combined */
1697 if ( CERTISTYPE(expected_proxy_type, ALL_LANGUAGE) ) {
1698 buflen+=strlen(ALL_LANGUAGE_TEXT);
1699 type=1;
1700 } else { /* Now check individual proxy languages */
1701 if ( CERTISTYPE(expected_proxy_type, IMPERSONATION) ) {
1702 buflen+=strlen(IMPERSONATION_TEXT);
1703 type=1;
1704 }
1705 if ( CERTISTYPE(expected_proxy_type, LIMITED) ) {
1706 buflen+=strlen(LIMITED_TEXT) + (type ? 3 : 0);
1707 type=1;
1708 }
1709 if ( CERTISTYPE(expected_proxy_type, INDEPENDENT) ) {
1710 buflen+=strlen(INDEPENDENT_TEXT) + (type ? 3 : 0);
1711 type=1;
1712 }
1713 if ( CERTISTYPE(expected_proxy_type, ANYLANG) ) {
1714 buflen+=strlen(ANYLANG_TEXT) + (type ? 3 : 0);
1715 type=1;
1716 }
1717 if ( CERTISTYPE(expected_proxy_type, RESTRICTED) ) {
1718 buflen+=strlen(RESTRICTED_TEXT) + (type ? 3 : 0);
1719 type=1;
1720 }
1721 /* Check whether we matched any type of language */
1722 if (type==0) {
1723 verify_error(oper, "Cannot determine proxy language for proxy");
1724 return NULL;
1725 }
1726 }
1727 }
1728
1729 /* Add one for the \0 byte */
1730 buflen++;
1731
1732 if ( (buf=malloc(buflen)) == NULL ) {
1733 verify_error(oper, "Out of memory");
1734 return NULL;
1735 }
1736 pos=buf;
1737
1738 /* reset prev, proxy and type */
1739 prev=proxy=type=0;
1740
1741 if ( CERTISTYPE(expected_proxy_type, CA) ) {
1742 len=snprintf(pos, buflen, "%s", CA_TEXT);
1743 buflen-=(size_t)len; pos+=(size_t)len; prev=1;
1744 }
1745 if ( CERTISTYPE(expected_proxy_type, EEC) ) {
1746 len=snprintf(pos, buflen, prev ? " or %s" : "%s", EEC_TEXT);
1747 buflen-=(size_t)len; pos+=(size_t)len; prev=1;
1748 }
1749 /* Handle all proxy version specially */
1750 if ( CERTISTYPE(expected_proxy_type, ANY_PROXY_VERSION) ) {
1751 len=snprintf(pos, buflen, prev ? " or %s" : "%s",ANY_PROXY_TEXT);
1752 buflen-=(size_t)len; pos+=(size_t)len; prev=proxy=1;
1753 } else { /* Now check individual proxy versions */
1754 if ( CERTISTYPE(expected_proxy_type, GT2_TYPE) ) {
1755 len=snprintf(pos, buflen, prev ? " or %s" : "%s", GT2_TEXT);
1756 buflen-=(size_t)len; pos+=(size_t)len; prev=proxy=1;
1757 }
1758 if ( CERTISTYPE(expected_proxy_type, GT3_TYPE) ) {
1759 len=snprintf(pos, buflen, prev ? " or %s" : "%s", GT3_TEXT);
1760 buflen-=(size_t)len; pos+=(size_t)len; prev=proxy=1;
1761 }
1762 if ( CERTISTYPE(expected_proxy_type, RFC_TYPE) ) {
1763 len=snprintf(pos, buflen, prev ? " or %s" : "%s", RFC_TEXT);
1764 buflen-=(size_t)len; pos+=(size_t)len; prev=proxy=1;
1765 }
1766 }
1767
1768 if (proxy==1) {
1769 /* First handle all proxy languages combined */
1770 if ( CERTISTYPE(expected_proxy_type, ALL_LANGUAGE) ) {
1771 len=snprintf(pos, buflen, "%s", ALL_LANGUAGE_TEXT);
1772 buflen-=(size_t)len; pos+=(size_t)len; type=1;
1773 } else {
1774 /* Now check individual proxy languages */
1775 if ( CERTISTYPE(expected_proxy_type, IMPERSONATION) ) {
1776 len=snprintf(pos, buflen, "%s", IMPERSONATION_TEXT);
1777 buflen-=(size_t)len; pos+=(size_t)len; type=1;
1778 }
1779 if ( CERTISTYPE(expected_proxy_type, LIMITED) ) {
1780 len=snprintf(pos, buflen, type ? " or%s" : "%s", LIMITED_TEXT);
1781 buflen-=(size_t)len; pos+=(size_t)len; type=1;
1782 }
1783 if ( CERTISTYPE(expected_proxy_type, INDEPENDENT) ) {
1784 len=snprintf(pos, buflen,
1785 type ? " or%s" : "%s", INDEPENDENT_TEXT);
1786 buflen-=(size_t)len; pos+=(size_t)len; type=1;
1787 }
1788 if ( CERTISTYPE(expected_proxy_type, ANYLANG) ) {
1789 len=snprintf(pos, buflen, type ? " or%s" : "%s", ANYLANG_TEXT);
1790 buflen-=(size_t)len; pos+=(size_t)len; type=1;
1791 }
1792 if ( CERTISTYPE(expected_proxy_type, RESTRICTED) ) {
1793 len=snprintf(pos, buflen,
1794 type ? " or%s" : "%s", RESTRICTED_TEXT);
1795 buflen-=(size_t)len; pos+=(size_t)len; type=1;
1796 }
1797 }
1798 }
1799
1800 return buf;
1801 }
1802
1803

Properties

Name Value
svn:keywords URL,HeadURL,Author,LastChangedBy,Date,LastChangedDate,Rev,Revision,LastChangedRevision,Id,Header

grid.support@nikhef.nl
ViewVC Help
Powered by ViewVC 1.1.28