00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef _GNU_SOURCE
00037 #define _GNU_SOURCE
00038 #endif
00039
00040 #include <stdio.h>
00041 #include <unistd.h>
00042 #include <stdlib.h>
00043 #include <stdarg.h>
00044 #include <time.h>
00045 #include <stdarg.h>
00046 #include <dirent.h>
00047 #include <string.h>
00048 #include <strings.h>
00049 #include <pwd.h>
00050 #include <errno.h>
00051 #include <getopt.h>
00052 #include <pthread.h>
00053
00054 #include <sys/types.h>
00055 #include <sys/stat.h>
00056
00057 #ifndef GRST_NO_OPENSSL
00058 #include <openssl/x509.h>
00059 #include <openssl/x509v3.h>
00060 #include <openssl/err.h>
00061 #include <openssl/pem.h>
00062
00063 #include <openssl/rsa.h>
00064 #include <openssl/pem.h>
00065 #include <openssl/err.h>
00066 #include <openssl/evp.h>
00067 #include <openssl/bio.h>
00068 #include <openssl/des.h>
00069 #include <openssl/rand.h>
00070 #endif
00071
00072 #include "gridsite.h"
00073
00074 #define GRST_KEYSIZE 512
00075 #define GRST_PROXYCACHE "/../proxycache/"
00076 #define GRST_MAX_CHAIN_LEN 9
00077 #define GRST_BACKDATE_SECONDS 300
00078
00079 pthread_mutex_t vomsmutex;
00080
00081
00082 int GRSTx509NameCmp(char *a, char *b)
00083
00084
00085
00086
00087
00088
00089
00090 {
00091 int ret;
00092 char *aa, *bb, *p;
00093
00094 if ((a == NULL) || (b == NULL)) return 1;
00095
00096 aa = strdup(a);
00097 while ((p = strstr(aa, "/emailAddress=")) != NULL)
00098 {
00099 memmove(&p[6], &p[13], strlen(&p[13]) + 1);
00100 p[1] = 'E';
00101 }
00102
00103 bb = strdup(b);
00104 while ((p = strstr(bb, "/emailAddress=")) != NULL)
00105 {
00106 memmove(&p[6], &p[13], strlen(&p[13]) + 1);
00107 p[1] = 'E';
00108 }
00109
00110 ret = strcasecmp(aa, bb);
00111
00112 free(aa);
00113 free(bb);
00114
00115 return ret;
00116 }
00117
00118
00119
00120 int GRSTx509KnownCriticalExts(X509 *cert)
00121
00122
00123
00124
00125
00126
00127
00128
00129 {
00130 int i;
00131 char s[80];
00132 X509_EXTENSION *ex;
00133
00134 #ifdef X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
00135 for (i = 0; i < X509_get_ext_count(cert); ++i)
00136 {
00137 ex = X509_get_ext(cert, i);
00138
00139 if (X509_EXTENSION_get_critical(ex) &&
00140 !X509_supported_extension(ex))
00141 {
00142 OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(ex), 1);
00143 if ( (strcmp(s, GRST_PROXYCERTINFO_OID) != 0) &&
00144 (strcmp(s, GRST_PROXYCERTNEWINFO_OID) != 0) )
00145 return GRST_RET_FAILED;
00146 }
00147 }
00148
00149 return GRST_RET_OK;
00150 #else
00151 return GRST_RET_FAILED;
00152 #endif
00153 }
00154
00155
00156 int GRSTx509IsCA(X509 *cert)
00157
00158
00159 {
00160 int purpose_id;
00161
00162 purpose_id = X509_PURPOSE_get_by_sname("sslclient");
00163
00164
00165 if (X509_check_purpose(cert, purpose_id + X509_PURPOSE_MIN, 1))
00166 return GRST_RET_OK;
00167 else return GRST_RET_FAILED;
00168 }
00169
00170 int GRSTx509ChainFree(GRSTx509Chain *chain)
00171 {
00172 GRSTx509Cert *grst_cert, *next_grst_cert;
00173
00174 if (chain == NULL) return GRST_RET_OK;
00175
00176 next_grst_cert = chain->firstcert;
00177
00178 while (next_grst_cert != NULL)
00179 {
00180 grst_cert = next_grst_cert;
00181
00182 if (grst_cert->issuer != NULL) free(grst_cert->issuer);
00183 if (grst_cert->dn != NULL) free(grst_cert->dn);
00184 if (grst_cert->ocsp != NULL) free(grst_cert->ocsp);
00185
00186 next_grst_cert = grst_cert->next;
00187 free(grst_cert);
00188 }
00189
00190 free(chain);
00191
00192 return GRST_RET_OK;
00193 }
00194
00195
00196 static int GRSTx509VerifySig(time_t *time1_time, time_t *time2_time,
00197 unsigned char *txt, int txt_len,
00198 unsigned char *sig, int sig_len,
00199 X509 *cert)
00200
00201
00202 {
00203 int ret;
00204 EVP_PKEY *prvkey;
00205 EVP_MD_CTX ctx;
00206 time_t voms_service_time1, voms_service_time2;
00207
00208 prvkey = X509_extract_key(cert);
00209 if (prvkey == NULL) {
00210 return GRST_RET_FAILED;
00211 }
00212
00213 OpenSSL_add_all_digests();
00214 #if OPENSSL_VERSION_NUMBER >= 0x0090701fL
00215 EVP_MD_CTX_init(&ctx);
00216 EVP_VerifyInit_ex(&ctx, EVP_md5(), NULL);
00217 #else
00218 EVP_VerifyInit(&ctx, EVP_md5());
00219 #endif
00220
00221 EVP_VerifyUpdate(&ctx, txt, txt_len);
00222
00223 ret = EVP_VerifyFinal(&ctx, sig, sig_len, prvkey);
00224
00225 #if OPENSSL_VERSION_NUMBER >= 0x0090701fL
00226 EVP_MD_CTX_cleanup(&ctx);
00227 #endif
00228 EVP_PKEY_free(prvkey);
00229
00230 if (ret != 1) {
00231 return GRST_RET_FAILED;
00232 }
00233
00234 voms_service_time1 =
00235 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(cert)),0);
00236 if (voms_service_time1 > *time1_time)
00237 *time1_time = voms_service_time1;
00238
00239 voms_service_time2 =
00240 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(cert)),0);
00241 if (voms_service_time2 < *time1_time)
00242 *time2_time = voms_service_time2;
00243
00244 return GRST_RET_OK ;
00245 }
00246
00247
00248 static int GRSTx509VerifyVomsSig(time_t *time1_time, time_t *time2_time,
00249 unsigned char *asn1string,
00250 struct GRSTasn1TagList taglist[],
00251 int lasttag,
00252 char *vomsdir, int acnumber)
00253
00254
00255 {
00256 #define GRST_ASN1_COORDS_VOMS_DN "-1-1-%d-1-3-1-1-1-%%d-1-%%d"
00257 #define GRST_ASN1_COORDS_VOMS_INFO "-1-1-%d-1"
00258 #define GRST_ASN1_COORDS_VOMS_SIG "-1-1-%d-3"
00259 int isig, iinfo;
00260 char certpath[16384], certpath2[16384], acvomsdn[200], dn_coords[200],
00261 info_coords[200], sig_coords[200];
00262
00263 DIR *vomsDIR, *vomsDIR2;
00264 struct dirent *vomsdirent, *vomsdirent2;
00265 X509 *cert;
00266
00267 FILE *fp;
00268 struct stat statbuf;
00269 static int voms_mutex_init=0;
00270
00271 if (!voms_mutex_init) {
00272
00273 voms_mutex_init = 1;
00274 pthread_mutex_init(&vomsmutex,NULL);
00275 }
00276
00277 pthread_mutex_lock(&vomsmutex);
00278
00279 if ((vomsdir == NULL) || (vomsdir[0] == '\0')) {
00280 pthread_mutex_unlock(&vomsmutex);
00281 return GRST_RET_FAILED;
00282 }
00283
00284 snprintf(dn_coords, sizeof(dn_coords),
00285 GRST_ASN1_COORDS_VOMS_DN, acnumber);
00286
00287 if (GRSTasn1GetX509Name(acvomsdn, sizeof(acvomsdn), dn_coords,
00288 (char*)asn1string, taglist, lasttag) != GRST_RET_OK) {
00289 pthread_mutex_unlock(&vomsmutex);
00290 return GRST_RET_FAILED;
00291 }
00292
00293 snprintf(info_coords, sizeof(info_coords),
00294 GRST_ASN1_COORDS_VOMS_INFO, acnumber);
00295 iinfo = GRSTasn1SearchTaglist(taglist, lasttag, info_coords);
00296
00297 snprintf(sig_coords, sizeof(sig_coords),
00298 GRST_ASN1_COORDS_VOMS_SIG, acnumber);
00299 isig = GRSTasn1SearchTaglist(taglist, lasttag, sig_coords);
00300
00301 if ((iinfo < 0) || (isig < 0)) {
00302 pthread_mutex_unlock(&vomsmutex);
00303 return GRST_RET_FAILED;
00304 }
00305
00306 vomsDIR = opendir(vomsdir);
00307 if (vomsDIR == NULL) {
00308 pthread_mutex_unlock(&vomsmutex);
00309 return GRST_RET_FAILED;
00310 }
00311
00312 while ((vomsdirent = readdir(vomsDIR)) != NULL)
00313 {
00314 if (vomsdirent->d_name[0] == '.') continue;
00315
00316 sprintf(certpath, "%s/%s", vomsdir, vomsdirent->d_name);
00317 stat(certpath, &statbuf);
00318
00319 if (S_ISDIR(statbuf.st_mode))
00320 {
00321 vomsDIR2 = opendir(certpath);
00322 GRSTerrorLog(GRST_LOG_DEBUG,
00323 "Descend VOMS subdirectory %s", certpath);
00324
00325 if (vomsDIR2 == NULL) continue;
00326
00327
00328 while ((vomsdirent2 = readdir(vomsDIR2)) != NULL)
00329 {
00330 if (vomsdirent2->d_name[0] == '.') continue;
00331
00332 sprintf(certpath2, "%s/%s/%s",
00333 vomsdir, vomsdirent->d_name, vomsdirent2->d_name);
00334
00335 fp = fopen(certpath2, "r");
00336 GRSTerrorLog(GRST_LOG_DEBUG,
00337 "Examine VOMS cert %s", certpath2);
00338 if (fp == NULL) continue;
00339
00340 cert = PEM_read_X509(fp, NULL, NULL, NULL);
00341 fclose(fp);
00342 if (cert == NULL) continue;
00343
00344 if (GRSTx509VerifySig(time1_time, time2_time,
00345 &asn1string[taglist[iinfo].start],
00346 taglist[iinfo].length+taglist[iinfo].headerlength,
00347 &asn1string[taglist[isig].start+
00348 taglist[isig].headerlength+1],
00349 taglist[isig].length - 1,
00350 cert) == GRST_RET_OK)
00351 {
00352 GRSTerrorLog(GRST_LOG_DEBUG, " VOMS cert signature match");
00353 X509_free(cert);
00354 closedir(vomsDIR2);
00355 closedir(vomsDIR);
00356 pthread_mutex_unlock(&vomsmutex);
00357 return GRST_RET_OK ;
00358 }
00359
00360 X509_free(cert);
00361 }
00362
00363 closedir(vomsDIR2);
00364 }
00365 else
00366 {
00367 fp = fopen(certpath, "r");
00368 GRSTerrorLog(GRST_LOG_DEBUG, "Examine VOMS cert %s", certpath);
00369 if (fp == NULL) continue;
00370
00371 cert = PEM_read_X509(fp, NULL, NULL, NULL);
00372 fclose(fp);
00373 if (cert == NULL) continue;
00374
00375 if (GRSTx509VerifySig(time1_time, time2_time,
00376 &asn1string[taglist[iinfo].start],
00377 taglist[iinfo].length+taglist[iinfo].headerlength,
00378 &asn1string[taglist[isig].start+
00379 taglist[isig].headerlength+1],
00380 taglist[isig].length - 1,
00381 cert) == GRST_RET_OK)
00382 {
00383 X509_free(cert);
00384 closedir(vomsDIR);
00385 pthread_mutex_unlock(&vomsmutex);
00386 return GRST_RET_OK ;
00387 }
00388
00389 X509_free(cert);
00390 }
00391 }
00392
00393 closedir(vomsDIR);
00394 pthread_mutex_unlock(&vomsmutex);
00395 return GRST_RET_FAILED;
00396 }
00397
00398
00399 static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert,
00400 time_t time1_time, time_t time2_time,
00401 X509_EXTENSION *ex,
00402 char *ucuserdn, char *vomsdir)
00403
00404
00405
00406 {
00407 #define MAXTAG 500
00408 #define GRST_ASN1_COORDS_FQAN "-1-1-%d-1-7-1-2-1-2-%d"
00409 #define GRST_ASN1_COORDS_USER_DN "-1-1-%d-1-2-1-1-1-1-%%d-1-%%d"
00410 #define GRST_ASN1_COORDS_VOMS_DN "-1-1-%d-1-3-1-1-1-%%d-1-%%d"
00411 #define GRST_ASN1_COORDS_TIME1 "-1-1-%d-1-6-1"
00412 #define GRST_ASN1_COORDS_TIME2 "-1-1-%d-1-6-2"
00413 ASN1_OCTET_STRING *asn1data;
00414 char *asn1string, acuserdn[200], acvomsdn[200],
00415 dn_coords[200], fqan_coords[200], time1_coords[200],
00416 time2_coords[200];
00417 long asn1length;
00418 int lasttag=-1, itag, i, acnumber = 1, chain_errors = 0;
00419 struct GRSTasn1TagList taglist[MAXTAG+1];
00420 time_t actime1 = 0, actime2 = 0, time_now;
00421
00422 asn1data = X509_EXTENSION_get_data(ex);
00423 asn1string = (char*)ASN1_STRING_data(asn1data);
00424 asn1length = ASN1_STRING_length(asn1data);
00425
00426 GRSTasn1ParseDump(NULL, (unsigned char*) asn1string, asn1length, taglist, MAXTAG, &lasttag);
00427
00428 for (acnumber = 1; ; ++acnumber)
00429 {
00430 chain_errors = 0;
00431
00432 snprintf(dn_coords, sizeof(dn_coords), GRST_ASN1_COORDS_USER_DN, acnumber);
00433 if (GRSTasn1GetX509Name(acuserdn, sizeof(acuserdn), dn_coords,
00434 asn1string, taglist, lasttag) != GRST_RET_OK)
00435 break;
00436
00437 snprintf(dn_coords, sizeof(dn_coords), GRST_ASN1_COORDS_VOMS_DN, acnumber);
00438 if (GRSTasn1GetX509Name(acvomsdn, sizeof(acvomsdn), dn_coords,
00439 asn1string, taglist, lasttag) != GRST_RET_OK)
00440 break;
00441
00442 if (GRSTx509NameCmp(ucuserdn, acuserdn) != 0)
00443 chain_errors |= GRST_CERT_BAD_CHAIN;
00444
00445 if (GRSTx509VerifyVomsSig(&time1_time, &time2_time,
00446 (unsigned char*)asn1string, taglist, lasttag, vomsdir, acnumber)
00447 != GRST_RET_OK)
00448 chain_errors |= GRST_CERT_BAD_SIG;
00449
00450 snprintf(time1_coords, sizeof(time1_coords), GRST_ASN1_COORDS_TIME1, acnumber);
00451 itag = GRSTasn1SearchTaglist(taglist, lasttag, time1_coords);
00452
00453 if (itag > -1) actime1 = GRSTasn1TimeToTimeT((unsigned char*)
00454 &asn1string[taglist[itag].start+
00455 taglist[itag].headerlength],
00456 taglist[itag].length);
00457 else actime1 = 0;
00458
00459 snprintf(time2_coords, sizeof(time2_coords), GRST_ASN1_COORDS_TIME2, acnumber);
00460 itag = GRSTasn1SearchTaglist(taglist, lasttag, time2_coords);
00461
00462 if (itag > -1) actime2 = GRSTasn1TimeToTimeT((unsigned char*)
00463 &asn1string[taglist[itag].start+
00464 taglist[itag].headerlength],
00465 taglist[itag].length);
00466 else actime2 = 0;
00467
00468 if (actime1 > time1_time) time1_time = actime1;
00469 if (actime2 < time2_time) time2_time = actime2;
00470
00471 time(&time_now);
00472 if ((time1_time > time_now + 300) || (time2_time < time_now))
00473 chain_errors |= GRST_CERT_BAD_TIME;
00474
00475 for (i=1; ; ++i)
00476 {
00477 snprintf(fqan_coords, sizeof(fqan_coords), GRST_ASN1_COORDS_FQAN, acnumber, i);
00478 itag = GRSTasn1SearchTaglist(taglist, lasttag, fqan_coords);
00479
00480 if (itag > -1)
00481 {
00482 (*grst_cert)->next = malloc(sizeof(GRSTx509Cert));
00483 *grst_cert = (*grst_cert)->next;
00484 bzero(*grst_cert, sizeof(GRSTx509Cert));
00485
00486 (*grst_cert)->notbefore = time1_time;
00487 (*grst_cert)->notafter = time2_time;
00488 sprintf(((*grst_cert)->value), "%.*s",
00489 taglist[itag].length,
00490 &asn1string[taglist[itag].start+
00491 taglist[itag].headerlength]);
00492
00493 (*grst_cert)->errors = chain_errors;
00494 (*grst_cert)->type = GRST_CERT_TYPE_VOMS;
00495 (*grst_cert)->issuer = strdup(acvomsdn);
00496 (*grst_cert)->dn = strdup(acuserdn);
00497 }
00498 else break;
00499 }
00500 }
00501
00502 return GRST_RET_OK;
00503 }
00504
00505
00506 int GRSTx509ChainLoadCheck(GRSTx509Chain **chain,
00507 STACK_OF(X509) *certstack, X509 *lastcert,
00508 char *capath, char *vomsdir)
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 {
00519 X509 *cert;
00520 X509 *cacert = NULL;
00521 int depth = 0;
00522 int chain_errors = 0;
00523 int first_non_ca;
00524 char *ucuserdn = NULL;
00525 size_t len,len2;
00526 int IsCA;
00527 int prevIsCA;
00528
00529 int prevIsLimited;
00530 int i,j,ret;
00531 char *proxy_part_DN;
00532
00533 char s[80];
00534 char cacertpath[16384];
00535 unsigned long subjecthash = 0;
00536 unsigned long issuerhash = 0;
00537 FILE *fp;
00538 X509_EXTENSION *ex;
00539 time_t now;
00540 GRSTx509Cert *grst_cert, *new_grst_cert;
00541 grst_cert = NULL;
00542 new_grst_cert = NULL;
00543 GRSTerrorLog(GRST_LOG_DEBUG, "GRSTx509ChainLoadCheck() starts");
00544
00545 time(&now);
00546
00547 first_non_ca = 0;
00548
00549
00550 IsCA = TRUE;
00551 prevIsLimited = 0;
00552
00553
00554 if (certstack != NULL)
00555 depth = sk_X509_num(certstack);
00556
00557 if ((depth == 0) && (lastcert == NULL))
00558 {
00559 *chain = NULL;
00560 return GRST_RET_FAILED;
00561 }
00562
00563 cert = sk_X509_value(certstack, depth - 1);
00564 subjecthash = X509_NAME_hash(X509_get_subject_name(cert));
00565 issuerhash = X509_NAME_hash(X509_get_issuer_name(cert));
00566 sprintf(cacertpath, "%s/%.8x.0", capath, (int)issuerhash);
00567
00568 GRSTerrorLog(GRST_LOG_DEBUG, "Look for CA root file %s", cacertpath);
00569
00570 fp = fopen(cacertpath, "r");
00571
00572 if (fp == NULL) chain_errors |= GRST_CERT_BAD_CHAIN;
00573 else
00574 {
00575 cacert = PEM_read_X509(fp, NULL, NULL, NULL);
00576 fclose(fp);
00577 if (cacert != NULL) {
00578 GRSTerrorLog(GRST_LOG_DEBUG, "Loaded CA root cert from file");
00579 } else {
00580 GRSTerrorLog(GRST_LOG_DEBUG, "Failed to load CA root cert file");
00581 }
00582 }
00583
00584
00585 *chain = malloc(sizeof(GRSTx509Chain));
00586 bzero(*chain, sizeof(GRSTx509Chain));
00587
00588
00589 for (i = depth - ((subjecthash == issuerhash) ? 1 : 0);
00590 i >= ((lastcert == NULL) ? 0 : -1);
00591 --i)
00592
00593 {
00594 GRSTerrorLog(GRST_LOG_DEBUG, "Process cert at depth %d in chain", i);
00595
00596 prevIsCA=IsCA;
00597
00598 new_grst_cert = malloc(sizeof(GRSTx509Cert));
00599 bzero(new_grst_cert, sizeof(GRSTx509Cert));
00600 new_grst_cert->errors = chain_errors;
00601
00602 if ((*chain)->firstcert == NULL)
00603 {
00604 GRSTerrorLog(GRST_LOG_DEBUG, "Initialise chain");
00605 (*chain)->firstcert = new_grst_cert;
00606 }
00607 else grst_cert->next = new_grst_cert;
00608
00609 grst_cert = new_grst_cert;
00610
00611
00612 if (i < 0) cert = lastcert;
00613 else if (i == depth)
00614 cert = cacert;
00615 else if ((i == depth - 1) && (subjecthash == issuerhash))
00616 cert = cacert;
00617 else cert = sk_X509_value(certstack, i);
00618
00619 if (cert != NULL)
00620 {
00621 if ((i == depth - 1) && (subjecthash != issuerhash))
00622 {
00623
00624
00625
00626 if (cacert == NULL)
00627 {
00628 chain_errors |= GRST_CERT_BAD_CHAIN;
00629 ret = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
00630 }
00631 else
00632 {
00633 ret = X509_check_issued(cacert, cert);
00634
00635 GRSTerrorLog(GRST_LOG_DEBUG,
00636 "Cert sig check %d returns %d", i, ret);
00637
00638 if (ret != X509_V_OK)
00639 new_grst_cert->errors |= GRST_CERT_BAD_SIG;
00640 }
00641 }
00642 else if ((i == depth - 2) && (subjecthash == issuerhash))
00643 {
00644
00645
00646
00647
00648 if (cacert == NULL)
00649 {
00650 chain_errors |= GRST_CERT_BAD_CHAIN;
00651 ret = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
00652 }
00653 else
00654 {
00655 ret = X509_check_issued(cacert, cert);
00656
00657 GRSTerrorLog(GRST_LOG_DEBUG,
00658 "Cert sig check %d returns %d", i, ret);
00659
00660 if (ret != X509_V_OK)
00661 new_grst_cert->errors |= GRST_CERT_BAD_SIG;
00662 }
00663 }
00664 else if (i < depth - 1)
00665 {
00666
00667
00668
00669
00670 ret = X509_check_issued(sk_X509_value(certstack, i + 1), cert);
00671
00672 GRSTerrorLog(GRST_LOG_DEBUG,
00673 "Cert sig check %d returns %d", i, ret);
00674
00675 if ((ret != X509_V_OK) &&
00676 (ret != X509_V_ERR_KEYUSAGE_NO_CERTSIGN))
00677 new_grst_cert->errors |= GRST_CERT_BAD_SIG;
00678
00679
00680 }
00681
00682 new_grst_cert->serial = (int) ASN1_INTEGER_get(
00683 X509_get_serialNumber(cert));
00684 new_grst_cert->notbefore = GRSTasn1TimeToTimeT(
00685 ASN1_STRING_data(X509_get_notBefore(cert)), 0);
00686 new_grst_cert->notafter = GRSTasn1TimeToTimeT(
00687 ASN1_STRING_data(X509_get_notAfter(cert)), 0);
00688
00689
00690
00691 if (now < new_grst_cert->notbefore)
00692 new_grst_cert->errors |= GRST_CERT_BAD_TIME;
00693
00694 if (now > new_grst_cert->notafter)
00695 new_grst_cert->errors |= GRST_CERT_BAD_TIME;
00696
00697 new_grst_cert->dn = X509_NAME_oneline(X509_get_subject_name(cert),NULL,0);
00698 new_grst_cert->issuer = X509_NAME_oneline(X509_get_issuer_name(cert),NULL,0);
00699 len = strlen(new_grst_cert->dn);
00700 len2 = strlen(new_grst_cert->issuer);
00701
00702
00703
00704
00705
00706 if (i == depth)
00707 IsCA = TRUE;
00708 else
00709 IsCA = (GRSTx509IsCA(cert) == GRST_RET_OK);
00710
00711
00712
00713 if (prevIsCA)
00714 {
00715 if (IsCA)
00716 {
00717 new_grst_cert->type = GRST_CERT_TYPE_CA;
00718 }
00719 else
00720 {
00721 new_grst_cert->type = GRST_CERT_TYPE_EEC;
00722 first_non_ca = i;
00723 ucuserdn = new_grst_cert->dn;
00724 new_grst_cert->delegation
00725 = (lastcert == NULL) ? i : i + 1;
00726 }
00727 }
00728 else
00729 {
00730 new_grst_cert->type = GRST_CERT_TYPE_PROXY;
00731
00732 IsCA = FALSE;
00733
00734
00735
00736 new_grst_cert->delegation = (lastcert == NULL) ? i : i + 1;
00737 }
00738
00739 if (!prevIsCA)
00740 {
00741
00742
00743
00744 if (prevIsLimited)
00745 {
00746 new_grst_cert->errors |= GRST_CERT_BAD_CHAIN;
00747 chain_errors |= GRST_CERT_BAD_CHAIN;
00748 }
00749
00750
00751 if (len2 > len)
00752 {
00753 new_grst_cert->errors |= GRST_CERT_BAD_CHAIN;
00754 chain_errors |= GRST_CERT_BAD_CHAIN;
00755 }
00756
00757
00758 if (strncmp((const char*)new_grst_cert->dn, new_grst_cert->issuer, len2) != 0)
00759 {
00760 new_grst_cert->errors |= GRST_CERT_BAD_CHAIN;
00761 chain_errors |= GRST_CERT_BAD_CHAIN;
00762 }
00763
00764
00765 proxy_part_DN = &(new_grst_cert->dn[len2]);
00766
00767
00768
00769 if (strncmp((const char*)proxy_part_DN, "/CN=", 4) != 0)
00770 {
00771 new_grst_cert->errors |= GRST_CERT_BAD_CHAIN;
00772 chain_errors |= GRST_CERT_BAD_CHAIN;
00773 }
00774
00775 if (strncmp((const char*)proxy_part_DN, "/CN=limited proxy", 17) == 0)
00776 prevIsLimited = 1;
00777
00778 for (j=0; j < X509_get_ext_count(cert); ++j)
00779 {
00780 ex = X509_get_ext(cert, j);
00781 OBJ_obj2txt(s,sizeof(s),X509_EXTENSION_get_object(ex),1);
00782
00783 if (strcmp(s, GRST_VOMS_OID) == 0)
00784 {
00785 GRSTx509ChainVomsAdd(&grst_cert,
00786 new_grst_cert->notbefore,
00787 new_grst_cert->notafter,
00788 ex,
00789 ucuserdn,
00790 vomsdir);
00791 grst_cert->delegation = (lastcert == NULL) ? i : i+1;
00792 }
00793 }
00794
00795 }
00796 }
00797
00798
00799 }
00800
00801 if (cacert != NULL) X509_free(cacert);
00802
00803 return GRST_RET_OK;
00804 }
00805
00806
00807 int GRSTx509CheckChain(int *first_non_ca, X509_STORE_CTX *ctx)
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 {
00824 STACK_OF(X509) *certstack;
00825 X509 *cert;
00826 int depth;
00827 size_t len,len2;
00828 int IsCA;
00829 int prevIsCA=TRUE;
00830
00831 int prevIsLimited;
00832 int i;
00833 char *cert_DN;
00834
00835 char *issuer_DN;
00836
00837 char *proxy_part_DN;
00838
00839 time_t now;
00840
00841 time(&now);
00842
00843 *first_non_ca = 0;
00844
00845
00846 if (!ctx) return X509_V_ERR_INVALID_CA;
00847
00848
00849
00850
00851 IsCA = TRUE;
00852 prevIsLimited = 0;
00853
00854
00855 certstack = X509_STORE_CTX_get_chain(ctx);
00856 depth = sk_X509_num(certstack);
00857
00858
00859 for (i=depth-1; i >= 0; --i)
00860
00861 {
00862 prevIsCA=IsCA;
00863
00864
00865 if ( (cert = sk_X509_value(certstack, i)) )
00866 {
00867
00868
00869 if (now <
00870 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(cert)),0))
00871 return X509_V_ERR_INVALID_CA;
00872
00873 if (now >
00874 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(cert)),0))
00875 return X509_V_ERR_INVALID_CA;
00876
00877
00878
00879 if (prevIsCA)
00880 {
00881
00882 if (i == depth-1) IsCA = TRUE;
00883
00884 else IsCA = (GRSTx509IsCA(cert) == GRST_RET_OK);
00885
00886 if (!IsCA) *first_non_ca = i;
00887 }
00888 else
00889 {
00890 IsCA = FALSE;
00891
00892
00893 }
00894
00895 cert_DN = X509_NAME_oneline(X509_get_subject_name(cert),NULL,0);
00896 issuer_DN = X509_NAME_oneline(X509_get_issuer_name(cert),NULL,0);
00897 len = strlen(cert_DN);
00898 len2 = strlen(issuer_DN);
00899
00900
00901
00902
00903 if (!prevIsCA)
00904 {
00905 if (prevIsLimited)
00906 return X509_V_ERR_INVALID_CA;
00907
00908
00909 if (len2 > len) return X509_V_ERR_INVALID_CA;
00910
00911
00912 if (strncmp((const char*)cert_DN, issuer_DN, len2) != 0)
00913 return X509_V_ERR_INVALID_CA;
00914
00915
00916 proxy_part_DN = &cert_DN[len2];
00917
00918
00919
00920 if (strncmp((const char*)proxy_part_DN, "/CN=", 4) != 0)
00921 return X509_V_ERR_INVALID_CA;
00922
00923 if ((strncmp((const char*)proxy_part_DN, "/CN=limited proxy", 17) == 0) &&
00924 (i > 0)) prevIsLimited = 1;
00925 }
00926 }
00927 }
00928
00929
00930
00931
00932 if (!prevIsCA)
00933 {
00934 if (prevIsLimited) return X509_V_ERR_INVALID_CA;
00935
00936
00937 if ( (cert = sk_X509_value(certstack, 0)) )
00938 {
00939
00940
00941 cert_DN = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
00942 issuer_DN = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
00943 len = strlen(cert_DN);
00944 len2 = strlen(issuer_DN);
00945
00946
00947
00948 if (len2 > len) return X509_V_ERR_INVALID_CA;
00949
00950
00951 if (strncmp((const char*)cert_DN, issuer_DN, len2) != 0)
00952 return X509_V_ERR_INVALID_CA;
00953
00954
00955 proxy_part_DN = &cert_DN[len2];
00956
00957
00958
00959
00960
00961
00962
00963 if (strncmp((const char*)proxy_part_DN, "/CN=", 4) != 0)
00964 return X509_V_ERR_INVALID_CA;
00965 }
00966 }
00967
00968 return X509_V_OK;
00969 }
00970
00971
00972 int GRSTx509VerifyCallback (int ok, X509_STORE_CTX *ctx)
00973 {
00974 int errnum = X509_STORE_CTX_get_error(ctx);
00975 int errdepth = X509_STORE_CTX_get_error_depth(ctx);
00976 int first_non_ca;
00977
00978 #ifndef X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
00979 #define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
00980 #endif
00981
00982 if (errnum == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)
00983 {
00984 if (GRSTx509KnownCriticalExts(X509_STORE_CTX_get_current_cert(ctx))
00985 == GRST_RET_OK)
00986 {
00987 ok = TRUE;
00988 errnum = X509_V_OK;
00989 X509_STORE_CTX_set_error(ctx, errnum);
00990 }
00991 }
00992 else if ((errdepth == 0) &&
00993 (errnum == X509_V_OK) &&
00994 (GRSTx509CheckChain(&first_non_ca, ctx) != X509_V_OK)) ok = FALSE;
00995
00996
00997 return ok;
00998
00999
01000
01001
01002
01003 }
01004
01005
01006 int GRSTx509ParseVomsExt(int *lastcred, int maxcreds, size_t credlen,
01007 char *creds, time_t time1_time, time_t time2_time,
01008 X509_EXTENSION *ex, char *ucuserdn, char *vomsdir)
01009
01010
01011
01012
01013 {
01014 #define MAXTAG 500
01015 #define GRST_ASN1_COORDS_FQAN "-1-1-%d-1-7-1-2-1-2-%d"
01016 #define GRST_ASN1_COORDS_USER_DN "-1-1-%d-1-2-1-1-1-1-%%d-1-%%d"
01017 #define GRST_ASN1_COORDS_TIME1 "-1-1-%d-1-6-1"
01018 #define GRST_ASN1_COORDS_TIME2 "-1-1-%d-1-6-2"
01019 ASN1_OCTET_STRING *asn1data;
01020 unsigned char *asn1string;
01021 char acuserdn[200],
01022 dn_coords[200], fqan_coords[200], time1_coords[200],
01023 time2_coords[200];
01024 long asn1length;
01025 int lasttag=-1, itag, i, acnumber = 1;
01026 struct GRSTasn1TagList taglist[MAXTAG+1];
01027 time_t actime1, actime2, time_now;
01028
01029 asn1data = X509_EXTENSION_get_data(ex);
01030 asn1string = (unsigned char*) (ASN1_STRING_data((asn1data)));
01031 asn1length = (long)ASN1_STRING_length(asn1data);
01032
01033 GRSTasn1ParseDump(NULL, asn1string, asn1length, taglist, MAXTAG, &lasttag);
01034
01035 for (acnumber = 1; ; ++acnumber)
01036 {
01037 snprintf(dn_coords, sizeof(dn_coords), GRST_ASN1_COORDS_USER_DN, acnumber);
01038 if (GRSTasn1GetX509Name(acuserdn, sizeof(acuserdn), dn_coords,
01039 (char*)asn1string, taglist, lasttag) != GRST_RET_OK) break;
01040
01041 if (GRSTx509NameCmp(ucuserdn, acuserdn) != 0) continue;
01042
01043 if (GRSTx509VerifyVomsSig(&time1_time, &time2_time,
01044 asn1string, taglist, lasttag, vomsdir, acnumber)
01045 != GRST_RET_OK) continue;
01046
01047 snprintf(time1_coords, sizeof(time1_coords), GRST_ASN1_COORDS_TIME1, acnumber);
01048 itag = GRSTasn1SearchTaglist(taglist, lasttag, time1_coords);
01049 actime1 = GRSTasn1TimeToTimeT(&asn1string[taglist[itag].start+
01050 taglist[itag].headerlength],
01051 taglist[itag].length);
01052 if (actime1 > time1_time) time1_time = actime1;
01053
01054 snprintf(time2_coords, sizeof(time2_coords), GRST_ASN1_COORDS_TIME2, acnumber);
01055 itag = GRSTasn1SearchTaglist(taglist, lasttag, time2_coords);
01056 actime2 = GRSTasn1TimeToTimeT(&asn1string[taglist[itag].start+
01057 taglist[itag].headerlength],
01058 taglist[itag].length);
01059 if (actime2 < time2_time) time2_time = actime2;
01060
01061 time(&time_now);
01062 if ((time1_time > time_now + 300) || (time2_time < time_now))
01063 continue;
01064
01065 for (i=1; ; ++i)
01066 {
01067 snprintf(fqan_coords, sizeof(fqan_coords), GRST_ASN1_COORDS_FQAN, acnumber, i);
01068 itag = GRSTasn1SearchTaglist(taglist, lasttag, fqan_coords);
01069
01070 if (itag > -1)
01071 {
01072 if (*lastcred < maxcreds - 1)
01073 {
01074 ++(*lastcred);
01075 snprintf(&creds[*lastcred * (credlen + 1)], credlen+1,
01076 "VOMS %010lu %010lu 0 %.*s",
01077 time1_time, time2_time,
01078 taglist[itag].length,
01079 &asn1string[taglist[itag].start+
01080 taglist[itag].headerlength]);
01081 }
01082 }
01083 else break;
01084 }
01085 }
01086
01087 return GRST_RET_OK;
01088 }
01089
01090
01091 int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen,
01092 char *creds, X509 *usercert, STACK_OF(X509) *certstack,
01093 char *vomsdir)
01094
01095
01096
01097 {
01098 int i, j;
01099 char s[80];
01100 unsigned char *ucuser;
01101 X509_EXTENSION *ex;
01102 X509 *cert;
01103 time_t time1_time = 0, time2_time = 0, uctime1_time, uctime2_time;
01104
01105 uctime1_time =
01106 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(usercert)),0);
01107 uctime2_time =
01108 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(usercert)),0);
01109 ucuser = (unsigned char*)
01110 X509_NAME_oneline(X509_get_subject_name(usercert), NULL, 0);
01111
01112 for (j=sk_X509_num(certstack)-1; j >= 0; --j)
01113 {
01114 cert = sk_X509_value(certstack, j);
01115
01116 time1_time =
01117 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(cert)),0);
01118 uctime1_time = (time1_time > uctime1_time) ? time1_time:uctime1_time;
01119
01120 time2_time =
01121 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(cert)),0);
01122 uctime2_time = (time2_time < uctime2_time) ? time2_time:uctime2_time;
01123
01124 for (i=0; i < X509_get_ext_count(cert); ++i)
01125 {
01126 ex = X509_get_ext(cert, i);
01127 OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(ex), 1);
01128
01129 if (strcmp(s, GRST_VOMS_OID) == 0)
01130 {
01131 GRSTx509ParseVomsExt(lastcred, maxcreds, credlen, creds,
01132 uctime1_time, uctime2_time,
01133 ex, (char*)ucuser, vomsdir);
01134 }
01135 }
01136 }
01137
01138 return GRST_RET_OK;
01139 }
01140
01141
01142 GRSTgaclCred *GRSTx509CompactToCred(char *grst_cred)
01143
01144
01145 {
01146 int delegation;
01147 char *p, *encoded;
01148 time_t now, notbefore, notafter;
01149 GRSTgaclCred *cred = NULL;
01150
01151 time(&now);
01152
01153 if (grst_cred == NULL) return NULL;
01154
01155 if (strncmp((const char*)grst_cred, "X509USER ", 9) == 0)
01156 {
01157 if ((sscanf(grst_cred, "X509USER %lu %lu %d",
01158 ¬before, ¬after, &delegation) == 3)
01159 && (now >= notbefore)
01160 && (now <= notafter)
01161 && (p = index(grst_cred, ' '))
01162 && (p = index(++p, ' '))
01163 && (p = index(++p, ' '))
01164 && (p = index(++p, ' ')))
01165 {
01166 encoded = GRSThttpUrlMildencode(&p[1]);
01167 cred = GRSTgaclCredCreate("dn:", encoded);
01168 free(encoded);
01169 GRSTgaclCredSetDelegation(cred, delegation);
01170 }
01171
01172 return cred;
01173 }
01174
01175 if (strncmp((const char*)grst_cred, "VOMS ", 5) == 0)
01176 {
01177 if ((sscanf(grst_cred, "VOMS %lu %lu %d",
01178 ¬before, ¬after, &delegation) == 3)
01179 && (now >= notbefore)
01180 && (now <= notafter)
01181 && (p = index(grst_cred, ' '))
01182 && (p = index(++p, ' '))
01183 && (p = index(++p, ' '))
01184 && (p = index(++p, ' ')))
01185 {
01186
01187
01188 if (p[1] != '/') return NULL;
01189
01190 encoded = GRSThttpUrlMildencode(&p[1]);
01191 cred = GRSTgaclCredCreate("fqan:", encoded);
01192 free(encoded);
01193 GRSTgaclCredSetDelegation(cred, delegation);
01194 }
01195
01196 return cred;
01197 }
01198
01199 return NULL;
01200 }
01201
01202
01203 int GRSTx509CompactCreds(int *lastcred, int maxcreds, size_t credlen,
01204 char *creds, STACK_OF(X509) *certstack, char *vomsdir,
01205 X509 *peercert)
01206
01207
01208
01209
01210
01211 {
01212 int i, delegation = 0;
01213 char credtemp[credlen+1];
01214 X509 *cert, *usercert = NULL, *gsiproxycert = NULL;
01215
01216 *lastcred = -1;
01217
01218 for (i = sk_X509_num(certstack) - 1; i >= 0; --i)
01219 {
01220 cert = sk_X509_value(certstack, i);
01221
01222 if (usercert != NULL)
01223 {
01224 gsiproxycert = cert;
01225 ++delegation;
01226 }
01227
01228 if ((usercert == NULL) &&
01229 (i < sk_X509_num(certstack) - 1) &&
01230 (GRSTx509IsCA(cert) != GRST_RET_OK)) usercert = cert;
01231
01232 }
01233
01234 if (peercert != NULL)
01235 {
01236 if (usercert != NULL)
01237 {
01238 gsiproxycert = peercert;
01239 ++delegation;
01240 }
01241
01242 if ((usercert == NULL) &&
01243 (GRSTx509IsCA(peercert) != GRST_RET_OK)) usercert = peercert;
01244
01245 }
01246
01247 if ((usercert == NULL)
01248 ||
01249 (snprintf(credtemp, credlen+1, "X509USER %010lu %010lu %d %s",
01250 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(usercert)),0),
01251 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(usercert)),0),
01252 delegation,
01253 X509_NAME_oneline(X509_get_subject_name(usercert), NULL, 0)) >= credlen+1)
01254 ||
01255 (*lastcred >= maxcreds-1))
01256 {
01257 *lastcred = -1;
01258 return GRST_RET_FAILED;
01259 }
01260
01261 ++(*lastcred);
01262 strcpy(&creds[*lastcred * (credlen + 1)], credtemp);
01263
01264 if ((gsiproxycert != NULL)
01265 &&
01266 (snprintf(credtemp, credlen+1, "GSIPROXY %010lu %010lu %d %s",
01267 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(gsiproxycert)),0),
01268 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(gsiproxycert)),0),
01269 delegation,
01270 X509_NAME_oneline(X509_get_subject_name(gsiproxycert), NULL, 0)) < credlen+1)
01271 &&
01272 (*lastcred < maxcreds-1))
01273 {
01274 ++(*lastcred);
01275 strcpy(&creds[*lastcred * (credlen + 1)], credtemp);
01276 GRSTx509GetVomsCreds(lastcred, maxcreds, credlen, creds,
01277 usercert, certstack, vomsdir);
01278 }
01279
01280 return GRST_RET_OK;
01281 }
01282
01283
01284 char *GRSTx509FindProxyFileName(void)
01285
01286
01287
01288 {
01289 char *p;
01290
01291 p = getenv("X509_USER_PROXY");
01292
01293 if (p != NULL) return strdup(p);
01294
01295 p = malloc(sizeof("/tmp/x509up_uXYYYXXXYYY"));
01296
01297 sprintf(p, "/tmp/x509up_u%d", getuid());
01298
01299 return p;
01300 }
01301
01302 static void mpcerror(FILE *debugfp, char *msg)
01303 {
01304 if (debugfp != NULL)
01305 {
01306 fputs(msg, debugfp);
01307 ERR_print_errors_fp(debugfp);
01308 }
01309 }
01310
01311
01312 int GRSTx509MakeProxyCert(char **proxychain, FILE *debugfp,
01313 char *reqtxt, char *cert, char *key, int minutes)
01314
01315
01316
01317
01318 {
01319 char *ptr, *certchain;
01320 int i, ncerts;
01321 long serial = 1234, ptrlen;
01322 EVP_PKEY *pkey, *CApkey;
01323 const EVP_MD *digest;
01324 X509 *certs[GRST_MAX_CHAIN_LEN];
01325 X509_REQ *req;
01326 X509_NAME *name, *CAsubject, *newsubject;
01327 X509_NAME_ENTRY *ent;
01328 FILE *fp;
01329 BIO *reqmem, *certmem;
01330 time_t notAfter;
01331
01332
01333 reqmem = BIO_new(BIO_s_mem());
01334 BIO_puts(reqmem, reqtxt);
01335
01336 if (!(req = PEM_read_bio_X509_REQ(reqmem, NULL, NULL, NULL)))
01337 {
01338 mpcerror(debugfp,
01339 "GRSTx509MakeProxyCert(): error reading request from BIO memory\n");
01340 BIO_free(reqmem);
01341 return GRST_RET_FAILED;
01342 }
01343
01344 BIO_free(reqmem);
01345
01346
01347 if (!(pkey = X509_REQ_get_pubkey(req)))
01348 {
01349 mpcerror(debugfp,
01350 "GRSTx509MakeProxyCert(): error getting public key from request\n");
01351
01352 X509_REQ_free(req);
01353 return GRST_RET_FAILED;
01354 }
01355
01356 if (X509_REQ_verify(req, pkey) != 1)
01357 {
01358 mpcerror(debugfp,
01359 "GRSTx509MakeProxyCert(): error verifying signature on certificate\n");
01360
01361 X509_REQ_free(req);
01362 return GRST_RET_FAILED;
01363 }
01364
01365
01366 if (!(fp = fopen(cert, "r")))
01367 {
01368 mpcerror(debugfp,
01369 "GRSTx509MakeProxyCert(): error opening signing certificate file\n");
01370
01371 X509_REQ_free(req);
01372 return GRST_RET_FAILED;
01373 }
01374
01375 for (ncerts = 1; ncerts < GRST_MAX_CHAIN_LEN; ++ncerts)
01376 if ((certs[ncerts] = PEM_read_X509(fp, NULL, NULL, NULL)) == NULL) break;
01377
01378 if (ncerts == 1)
01379 {
01380 mpcerror(debugfp,
01381 "GRSTx509MakeProxyCert(): error reading signing certificate file\n");
01382
01383 X509_REQ_free(req);
01384 return GRST_RET_FAILED;
01385 }
01386
01387 fclose(fp);
01388
01389 CAsubject = X509_get_subject_name(certs[1]);
01390
01391
01392 if (!(fp = fopen(key, "r")))
01393 {
01394 mpcerror(debugfp,
01395 "GRSTx509MakeProxyCert(): error reading signing private key file\n");
01396
01397 X509_REQ_free(req);
01398 return GRST_RET_FAILED;
01399 }
01400
01401 if (!(CApkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)))
01402 {
01403 mpcerror(debugfp,
01404 "GRSTx509MakeProxyCert(): error reading signing private key in file\n");
01405
01406 X509_REQ_free(req);
01407 return GRST_RET_FAILED;
01408 }
01409
01410 fclose(fp);
01411
01412
01413 if (!(name = X509_REQ_get_subject_name(req)))
01414 {
01415 mpcerror(debugfp,
01416 "GRSTx509MakeProxyCert(): error getting subject name from request\n");
01417
01418 X509_REQ_free(req);
01419 return GRST_RET_FAILED;
01420 }
01421
01422
01423 if (!(certs[0] = X509_new()))
01424 {
01425 mpcerror(debugfp,
01426 "GRSTx509MakeProxyCert(): error creating X509 object\n");
01427
01428 X509_REQ_free(req);
01429 return GRST_RET_FAILED;
01430 }
01431
01432
01433
01434 if (X509_set_version(certs[0], 3L) != 1)
01435 {
01436 mpcerror(debugfp,
01437 "GRSTx509MakeProxyCert(): error setting certificate version\n");
01438
01439 X509_REQ_free(req);
01440 return GRST_RET_FAILED;
01441 }
01442
01443 ASN1_INTEGER_set(X509_get_serialNumber(certs[0]), serial++);
01444
01445 if (!(name = X509_get_subject_name(certs[1])))
01446 {
01447 mpcerror(debugfp,
01448 "GRSTx509MakeProxyCert(): error getting subject name from CA certificate\n");
01449
01450 X509_REQ_free(req);
01451 return GRST_RET_FAILED;
01452 }
01453
01454 if (X509_set_issuer_name(certs[0], name) != 1)
01455 {
01456 mpcerror(debugfp,
01457 "GRSTx509MakeProxyCert(): error setting issuer name of certificate\n");
01458
01459 X509_REQ_free(req);
01460 return GRST_RET_FAILED;
01461 }
01462
01463
01464 ent = X509_NAME_ENTRY_create_by_NID(NULL, OBJ_txt2nid("commonName"),
01465 MBSTRING_ASC, (unsigned char*)"proxy", -1);
01466
01467 newsubject = X509_NAME_dup(CAsubject);
01468
01469 X509_NAME_add_entry(newsubject, ent, -1, 0);
01470
01471 if (X509_set_subject_name(certs[0], newsubject) != 1)
01472 {
01473 mpcerror(debugfp,
01474 "GRSTx509MakeProxyCert(): error setting subject name of certificate\n");
01475
01476 X509_REQ_free(req);
01477 return GRST_RET_FAILED;
01478 }
01479
01480 X509_NAME_free(newsubject);
01481 X509_NAME_ENTRY_free(ent);
01482
01483
01484 if (X509_set_pubkey(certs[0], pkey) != 1)
01485 {
01486 mpcerror(debugfp,
01487 "GRSTx509MakeProxyCert(): error setting public key of the certificate\n");
01488
01489 X509_REQ_free(req);
01490 return GRST_RET_FAILED;
01491 }
01492
01493
01494 if (!(X509_gmtime_adj(X509_get_notBefore(certs[0]), -GRST_BACKDATE_SECONDS)))
01495 {
01496 mpcerror(debugfp,
01497 "GRSTx509MakeProxyCert(): error setting beginning time of the certificate\n");
01498
01499 X509_REQ_free(req);
01500 return GRST_RET_FAILED;
01501 }
01502
01503 if (!(X509_gmtime_adj(X509_get_notAfter(certs[0]), 60 * minutes)))
01504 {
01505 mpcerror(debugfp,
01506 "GRSTx509MakeProxyCert(): error setting ending time of the certificate\n");
01507
01508 X509_REQ_free(req);
01509 return GRST_RET_FAILED;
01510 }
01511
01512
01513
01514 notAfter =
01515 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(certs[0])), 0);
01516
01517 for (i=1; i < ncerts; ++i)
01518 if (notAfter >
01519 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(certs[i])),
01520 0))
01521 {
01522 notAfter =
01523 GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(certs[i])),
01524 0);
01525
01526 ASN1_UTCTIME_set(X509_get_notAfter(certs[0]), notAfter);
01527 }
01528
01529
01530 if (EVP_PKEY_type(CApkey->type) == EVP_PKEY_RSA)
01531 digest = EVP_md5();
01532 else
01533 {
01534 mpcerror(debugfp,
01535 "GRSTx509MakeProxyCert(): error checking signing private key for a valid digest\n");
01536
01537 X509_REQ_free(req);
01538 return GRST_RET_FAILED;
01539 }
01540
01541 if (!(X509_sign(certs[0], CApkey, digest)))
01542 {
01543 mpcerror(debugfp,
01544 "GRSTx509MakeProxyCert(): error signing certificate\n");
01545
01546 X509_REQ_free(req);
01547 return GRST_RET_FAILED;
01548 }
01549
01550
01551
01552 certchain = strdup("");
01553
01554 for (i=0; i < ncerts; ++i)
01555 {
01556 certmem = BIO_new(BIO_s_mem());
01557
01558 if (PEM_write_bio_X509(certmem, certs[i]) != 1)
01559 {
01560 mpcerror(debugfp,
01561 "GRSTx509MakeProxyCert(): error writing certificate to memory BIO\n");
01562
01563 X509_REQ_free(req);
01564 return GRST_RET_FAILED;
01565 }
01566
01567 ptrlen = BIO_get_mem_data(certmem, &ptr);
01568
01569 certchain = realloc(certchain, strlen(certchain) + ptrlen + 1);
01570
01571 strncat(certchain, ptr, ptrlen);
01572
01573 BIO_free(certmem);
01574 X509_free(certs[i]);
01575 }
01576
01577 EVP_PKEY_free(pkey);
01578 EVP_PKEY_free(CApkey);
01579 X509_REQ_free(req);
01580
01581 *proxychain = certchain;
01582 return GRST_RET_OK;
01583 }
01584
01585
01586 char *GRSTx509CachedProxyFind(char *proxydir, char *delegation_id,
01587 char *user_dn)
01588
01589
01590
01591
01592
01593
01594
01595 {
01596 char *user_dn_enc;
01597 char* proxyfile = (char*)malloc(16384);
01598 struct stat statbuf;
01599
01600 user_dn_enc = GRSThttpUrlEncode(user_dn);
01601
01602 sprintf(proxyfile, "%s/%s/%s/userproxy.pem",
01603 proxydir, user_dn_enc, delegation_id);
01604
01605 free(user_dn_enc);
01606
01607 if ((stat(proxyfile, &statbuf) != 0) || !S_ISREG(statbuf.st_mode))
01608 {
01609 free(proxyfile);
01610 return NULL;
01611 }
01612
01613 return proxyfile;
01614 }
01615
01616
01617 char *GRSTx509CachedProxyKeyFind(char *proxydir, char *delegation_id,
01618 char *user_dn)
01619
01620
01621
01622
01623
01624
01625
01626 {
01627 char *user_dn_enc;
01628 char* prvkeyfile = (char*) malloc(16384);
01629 struct stat statbuf;
01630
01631 user_dn_enc = GRSThttpUrlEncode(user_dn);
01632
01633 sprintf(prvkeyfile, "%s/cache/%s/%s/userkey.pem",
01634 proxydir, user_dn_enc, delegation_id);
01635
01636 free(user_dn_enc);
01637
01638 if ((stat(prvkeyfile, &statbuf) != 0) || !S_ISREG(statbuf.st_mode))
01639 {
01640 free(prvkeyfile);
01641 return NULL;
01642 }
01643
01644 return prvkeyfile;
01645 }
01646
01647 static void mkdir_printf(mode_t mode, char *fmt, ...)
01648 {
01649 int ret;
01650 char path[16384];
01651 va_list ap;
01652
01653 va_start(ap, fmt);
01654 vsprintf(path, fmt, ap);
01655 va_end(ap);
01656
01657 ret = mkdir(path, mode);
01658 }
01659
01660
01661 int GRSTx509CreateProxyRequest(char **reqtxt, char **keytxt, char *ocspurl)
01662
01663
01664
01665 {
01666 char *ptr;
01667 size_t ptrlen;
01668 RSA *keypair;
01669 X509_NAME *subject;
01670 X509_NAME_ENTRY *ent;
01671 EVP_PKEY *pkey;
01672 X509_REQ *certreq;
01673 BIO *reqmem, *keymem;
01674 const EVP_MD *digest;
01675
01676
01677
01678 if ((keypair = RSA_generate_key(GRST_KEYSIZE, 65537, NULL, NULL)) == NULL)
01679 return 1;
01680
01681 keymem = BIO_new(BIO_s_mem());
01682 if (!PEM_write_bio_RSAPrivateKey(keymem, keypair, NULL, NULL, 0, NULL, NULL))
01683 {
01684 BIO_free(keymem);
01685 return 3;
01686 }
01687
01688 ptrlen = BIO_get_mem_data(keymem, &ptr);
01689
01690 *keytxt = malloc(ptrlen + 1);
01691 memcpy(*keytxt, ptr, ptrlen);
01692 (*keytxt)[ptrlen] = '\0';
01693
01694 BIO_free(keymem);
01695
01696
01697
01698 certreq = X509_REQ_new();
01699
01700 OpenSSL_add_all_algorithms();
01701
01702 pkey = EVP_PKEY_new();
01703 EVP_PKEY_assign_RSA(pkey, keypair);
01704
01705 X509_REQ_set_pubkey(certreq, pkey);
01706
01707 subject = X509_NAME_new();
01708 ent = X509_NAME_ENTRY_create_by_NID(NULL, OBJ_txt2nid("organizationName"),
01709 MBSTRING_ASC, (unsigned char*)"Dummy", -1);
01710 X509_NAME_add_entry (subject, ent, -1, 0);
01711 X509_REQ_set_subject_name (certreq, subject);
01712
01713 digest = EVP_md5();
01714 X509_REQ_sign(certreq, pkey, digest);
01715
01716 reqmem = BIO_new(BIO_s_mem());
01717 PEM_write_bio_X509_REQ(reqmem, certreq);
01718 ptrlen = BIO_get_mem_data(reqmem, &ptr);
01719
01720 *reqtxt = malloc(ptrlen + 1);
01721 memcpy(*reqtxt, ptr, ptrlen);
01722 (*reqtxt)[ptrlen] = '\0';
01723
01724 BIO_free(reqmem);
01725
01726 X509_REQ_free(certreq);
01727
01728 return 0;
01729 }
01730
01731
01732 int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir,
01733 char *delegation_id, char *user_dn)
01734
01735
01736
01737
01738 {
01739 char prvkeyfile[16384], *ptr, *user_dn_enc;
01740 size_t ptrlen;
01741 FILE *fp;
01742 RSA *keypair;
01743 X509_NAME *subject;
01744 X509_NAME_ENTRY *ent;
01745 EVP_PKEY *pkey;
01746 X509_REQ *certreq;
01747 BIO *reqmem;
01748 const EVP_MD *digest;
01749
01750 if (strcmp(user_dn, "cache") == 0) return GRST_RET_FAILED;
01751
01752 user_dn_enc = GRSThttpUrlEncode(user_dn);
01753
01754
01755
01756 mkdir_printf(S_IRUSR | S_IWUSR | S_IXUSR,
01757 "%s/cache", proxydir);
01758 mkdir_printf(S_IRUSR | S_IWUSR | S_IXUSR,
01759 "%s/cache/%s", proxydir, user_dn_enc);
01760 mkdir_printf(S_IRUSR | S_IWUSR | S_IXUSR,
01761 "%s/cache/%s/%s", proxydir, user_dn_enc, delegation_id);
01762
01763
01764
01765 sprintf(prvkeyfile, "%s/cache/%s/%s/userkey.pem",
01766 proxydir, user_dn_enc, delegation_id);
01767
01768 if (prvkeyfile == NULL)
01769 {
01770 free(user_dn_enc);
01771 return GRST_RET_FAILED;
01772 }
01773
01774 if ((keypair = RSA_generate_key(GRST_KEYSIZE, 65537, NULL, NULL)) == NULL)
01775 return 1;
01776
01777 if ((fp = fopen(prvkeyfile, "w")) == NULL) return 2;
01778
01779 chmod(prvkeyfile, S_IRUSR | S_IWUSR);
01780 free(user_dn_enc);
01781
01782 if (!PEM_write_RSAPrivateKey(fp, keypair, NULL, NULL, 0, NULL, NULL))
01783 return 3;
01784
01785 if (fclose(fp) != 0) return 4;
01786
01787
01788
01789 certreq = X509_REQ_new();
01790 if (certreq == NULL) return 5;
01791
01792 OpenSSL_add_all_algorithms();
01793
01794 pkey = EVP_PKEY_new();
01795 EVP_PKEY_assign_RSA(pkey, keypair);
01796
01797 X509_REQ_set_pubkey(certreq, pkey);
01798
01799 subject = X509_NAME_new();
01800 ent = X509_NAME_ENTRY_create_by_NID(NULL, OBJ_txt2nid("organizationName"),
01801 MBSTRING_ASC, (unsigned char*)"Dummy", -1);
01802 X509_NAME_add_entry (subject, ent, -1, 0);
01803 X509_REQ_set_subject_name (certreq, subject);
01804
01805 digest = EVP_md5();
01806 X509_REQ_sign(certreq, pkey, digest);
01807
01808 reqmem = BIO_new(BIO_s_mem());
01809 PEM_write_bio_X509_REQ(reqmem, certreq);
01810 ptrlen = BIO_get_mem_data(reqmem, &ptr);
01811
01812 *reqtxt = malloc(ptrlen + 1);
01813 memcpy(*reqtxt, ptr, ptrlen);
01814 (*reqtxt)[ptrlen] = '\0';
01815
01816 BIO_free(reqmem);
01817
01818 X509_REQ_free(certreq);
01819
01820 return 0;
01821 }
01822
01823
01824 int GRSTx509ProxyDestroy(char *proxydir, char *delegation_id, char *user_dn)
01825
01826
01827
01828
01829 {
01830 int ret = GRST_RET_OK;
01831 char filename[16384], *user_dn_enc;
01832
01833 if (strcmp(user_dn, "cache") == 0) return GRST_RET_FAILED;
01834
01835 user_dn_enc = GRSThttpUrlEncode(user_dn);
01836
01837
01838
01839 sprintf(filename, "%s/%s/%s/userproxy.pem",
01840 proxydir, user_dn_enc, delegation_id);
01841
01842 if (unlink(filename) != 0) ret = GRST_RET_NO_SUCH_FILE;
01843
01844
01845
01846 sprintf(filename, "%s/%s/%s/voms.attributes",
01847 proxydir, user_dn_enc, delegation_id);
01848
01849 unlink(filename);
01850
01851 return ret;
01852 }
01853
01854
01855 int GRSTx509ProxyGetTimes(char *proxydir, char *delegation_id, char *user_dn,
01856 time_t *start, time_t *finish)
01857
01858
01859
01860 {
01861 char filename[16384], *user_dn_enc;
01862 FILE *fp;
01863 X509 *cert;
01864
01865 if (strcmp(user_dn, "cache") == 0) return GRST_RET_FAILED;
01866
01867 user_dn_enc = GRSThttpUrlEncode(user_dn);
01868
01869 sprintf(filename, "%s/%s/%s/userproxy.pem",
01870 proxydir, user_dn_enc, delegation_id);
01871
01872 free(user_dn_enc);
01873
01874 if (filename == NULL) return GRST_RET_FAILED;
01875
01876 fp = fopen(filename, "r");
01877
01878 if (fp == NULL) return GRST_RET_NO_SUCH_FILE;
01879
01880 cert = PEM_read_X509(fp, NULL, NULL, NULL);
01881
01882 fclose(fp);
01883
01884 *start = GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(cert)),0);
01885 *finish = GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(cert)),0);
01886
01887 X509_free(cert);
01888
01889 return GRST_RET_OK;
01890 }
01891
01892
01893 int GRSTx509StringToChain(STACK_OF(X509) **certstack, char *certstring)
01894
01895
01896
01897
01898
01899 {
01900 STACK_OF(X509_INFO) *sk=NULL;
01901 BIO *certbio;
01902 X509_INFO *xi;
01903
01904 *certstack = sk_X509_new_null();
01905 if (*certstack == NULL) return GRST_RET_FAILED;
01906
01907 certbio = BIO_new_mem_buf(certstring, -1);
01908
01909 if (!(sk=PEM_X509_INFO_read_bio(certbio, NULL, NULL, NULL)))
01910 {
01911 BIO_free(certbio);
01912 sk_X509_INFO_free(sk);
01913 sk_X509_free(*certstack);
01914 return GRST_RET_FAILED;
01915 }
01916
01917 while (sk_X509_INFO_num(sk))
01918 {
01919 xi=sk_X509_INFO_shift(sk);
01920 if (xi->x509 != NULL)
01921 {
01922 sk_X509_push(*certstack, xi->x509);
01923 xi->x509=NULL;
01924 }
01925 X509_INFO_free(xi);
01926 }
01927
01928 if (!sk_X509_num(*certstack))
01929 {
01930 BIO_free(certbio);
01931 sk_X509_INFO_free(sk);
01932 sk_X509_free(*certstack);
01933 return GRST_RET_FAILED;
01934 }
01935
01936 BIO_free(certbio);
01937 sk_X509_INFO_free(sk);
01938
01939 return GRST_RET_OK;
01940 }
01941
01942
01943 char *GRSTx509MakeDelegationID(void)
01944
01945
01946
01947 {
01948 unsigned char hash_delegation_id[EVP_MAX_MD_SIZE];
01949 int i;
01950 unsigned int delegation_id_len;
01951 char cred_name[14], *cred_value, *delegation_id;
01952 const EVP_MD *m;
01953 EVP_MD_CTX ctx;
01954
01955 OpenSSL_add_all_digests();
01956
01957 m = EVP_sha1();
01958 if (m == NULL) return NULL;
01959
01960 EVP_DigestInit(&ctx, m);
01961
01962 for (i=0; i <= 999; ++i)
01963 {
01964 snprintf(cred_name, sizeof(cred_name), "GRST_CRED_%d", i);
01965 if ((cred_value = getenv(cred_name)) == NULL) break;
01966
01967 EVP_DigestUpdate(&ctx, cred_value, strlen(cred_value));
01968 }
01969
01970 EVP_DigestFinal(&ctx, hash_delegation_id, &delegation_id_len);
01971
01972 delegation_id = malloc(17);
01973
01974 for (i=0; i <=7; ++i)
01975 sprintf(&delegation_id[i*2], "%02x", hash_delegation_id[i]);
01976
01977 delegation_id[16] = '\0';
01978
01979 return delegation_id;
01980 }
01981
01982 #if 0
01983
01984 char *GRSTx509MakeProxyFileName(char *delegation_id,
01985 STACK_OF(X509) *certstack)
01986
01987
01988
01989
01990
01991
01992
01993 {
01994 int i, depth, prevIsCA = 1, IsCA, hash_name_len, delegation_id_len,
01995 der_name_len;
01996 unsigned char *der_name, *buf, hash_name[EVP_MAX_MD_SIZE],
01997 hash_delegation_id[EVP_MAX_MD_SIZE],
01998 filename[34];
01999 X509_NAME *subject_name;
02000 X509 *cert;
02001 const EVP_MD *m;
02002 EVP_MD_CTX ctx;
02003
02004 depth = sk_X509_num(certstack);
02005
02006 for (i=depth-1; i >= 0; --i)
02007
02008 {
02009 if (cert = sk_X509_value(certstack, i))
02010 {
02011 IsCA = (GRSTx509IsCA(cert) == GRST_RET_OK);
02012
02013 if (prevIsCA && !IsCA)
02014 {
02015 break;
02016 }
02017 }
02018 }
02019
02020 if (i < 0) return NULL;
02021
02022 if ((subject_name = X509_get_subject_name(cert)) == NULL) return NULL;
02023
02024 der_name_len = i2d_X509_NAME(X509_get_subject_name(cert), NULL);
02025 if (der_name_len == 0) return NULL;
02026
02027 buf = OPENSSL_malloc(der_name_len);
02028 der_name = buf;
02029
02030
02031 if (!i2d_X509_NAME(X509_get_subject_name(cert), &der_name))
02032 {
02033 OPENSSL_free(der_name);
02034 return NULL;
02035 }
02036
02037 OpenSSL_add_all_digests();
02038
02039 m = EVP_sha1();
02040 if (m == NULL)
02041 {
02042 OPENSSL_free(der_name);
02043 return NULL;
02044 }
02045
02046
02047 EVP_DigestInit(&ctx, m);
02048 EVP_DigestUpdate(&ctx, delegation_id, strlen(delegation_id));
02049 EVP_DigestFinal(&ctx, hash_delegation_id, &delegation_id_len);
02050
02051
02052
02053
02054 for (i=0; i <=7; ++i)
02055 sprintf(&filename[i*2], "%02x", hash_delegation_id[i]);
02056
02057 filename[16] = '-';
02058
02059 EVP_DigestInit(&ctx, m);
02060 EVP_DigestUpdate(&ctx, buf, der_name_len);
02061 EVP_DigestFinal(&ctx, hash_name, &hash_name_len);
02062
02063 for (i=0; i <=7; ++i)
02064 sprintf(&filename[17 + i*2], "%02x", hash_name[i]);
02065
02066 return strdup(filename);
02067 }
02068 #endif
02069
02070
02071 int GRSTx509CacheProxy(char *proxydir, char *delegation_id,
02072 char *user_dn, char *proxychain)
02073
02074
02075
02076
02077 {
02078 int c, i;
02079 char *user_dn_enc, *ptr, *prvkeyfile, proxyfile[16384];
02080 STACK_OF(X509) *certstack;
02081 BIO *certmem;
02082 X509 *cert;
02083 long ptrlen;
02084 FILE *ifp, *ofp;
02085
02086 if (strcmp(user_dn, "cache") == 0) return GRST_RET_FAILED;
02087
02088
02089
02090 prvkeyfile = GRSTx509CachedProxyKeyFind(proxydir, delegation_id, user_dn);
02091
02092 if (prvkeyfile == NULL)
02093 {
02094 return GRST_RET_FAILED;
02095 }
02096
02097
02098
02099 if ((ifp = fopen(prvkeyfile, "r")) == NULL)
02100 {
02101 free(prvkeyfile);
02102 return GRST_RET_FAILED;
02103 }
02104
02105
02106
02107 if (GRSTx509StringToChain(&certstack, proxychain) != GRST_RET_OK)
02108 {
02109 fclose(ifp);
02110 free(prvkeyfile);
02111 return GRST_RET_FAILED;
02112 }
02113
02114
02115
02116 user_dn_enc = GRSThttpUrlEncode(user_dn);
02117
02118 mkdir_printf(S_IRUSR | S_IWUSR | S_IXUSR,
02119 "%s/%s", proxydir, user_dn_enc);
02120 mkdir_printf(S_IRUSR | S_IWUSR | S_IXUSR,
02121 "%s/%s/%s", proxydir, user_dn_enc, delegation_id);
02122
02123 sprintf(proxyfile, "%s/%s/%s/userproxy.pem",
02124 proxydir, user_dn_enc, delegation_id);
02125
02126 free(user_dn_enc);
02127
02128
02129
02130 ofp = fopen(proxyfile, "w");
02131 chmod(proxyfile, S_IRUSR | S_IWUSR);
02132
02133 if (ofp == NULL)
02134 {
02135 fclose(ifp);
02136 free(prvkeyfile);
02137 return GRST_RET_FAILED;
02138 }
02139
02140
02141
02142 if ( (cert = sk_X509_value(certstack, 0)) )
02143 {
02144 certmem = BIO_new(BIO_s_mem());
02145 if (PEM_write_bio_X509(certmem, cert) == 1)
02146 {
02147 ptrlen = BIO_get_mem_data(certmem, &ptr);
02148 fwrite(ptr, 1, ptrlen, ofp);
02149 }
02150
02151 BIO_free(certmem);
02152 }
02153
02154
02155
02156 while ((c = fgetc(ifp)) != EOF) fputc(c, ofp);
02157 unlink(prvkeyfile);
02158 free(prvkeyfile);
02159
02160 for (i=1; i <= sk_X509_num(certstack) - 1; ++i)
02161
02162 {
02163 if ( (cert = sk_X509_value(certstack, i)))
02164 {
02165 certmem = BIO_new(BIO_s_mem());
02166 if (PEM_write_bio_X509(certmem, cert) == 1)
02167 {
02168 ptrlen = BIO_get_mem_data(certmem, &ptr);
02169 fwrite(ptr, 1, ptrlen, ofp);
02170 }
02171
02172 BIO_free(certmem);
02173 }
02174 }
02175
02176 sk_X509_free(certstack);
02177
02178 if (fclose(ifp) != 0) return GRST_RET_FAILED;
02179 if (fclose(ofp) != 0) return GRST_RET_FAILED;
02180
02181 return GRST_RET_OK;
02182 }