summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjmagne <jmagne@c9f7a03b-bd48-0410-a16d-cbbf54688b0b>2010-08-19 20:49:24 +0000
committerjmagne <jmagne@c9f7a03b-bd48-0410-a16d-cbbf54688b0b>2010-08-19 20:49:24 +0000
commitc4fd85af7a6f72f273f3f284f3f14b7cc90bc0fe (patch)
tree78807d047008b4815bd68ff809d0e80333250bb7
parent646cf3f0d7b3d39713f60b493fd76ed5b4e66574 (diff)
downloadpki-c4fd85af7a6f72f273f3f284f3f14b7cc90bc0fe.tar.gz
pki-c4fd85af7a6f72f273f3f284f3f14b7cc90bc0fe.tar.xz
pki-c4fd85af7a6f72f273f3f284f3f14b7cc90bc0fe.zip
Fix Bug 547507 - Token renewal: certs on the token is deleted when one of the certs on the token is outside renewal grace period.
git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/trunk@1225 c9f7a03b-bd48-0410-a16d-cbbf54688b0b
-rw-r--r--pki/base/tps/doc/CS.cfg16
-rw-r--r--pki/base/tps/src/engine/RA.cpp1
-rw-r--r--pki/base/tps/src/include/processor/RA_Enroll_Processor.h1
-rw-r--r--pki/base/tps/src/processor/RA_Enroll_Processor.cpp211
4 files changed, 211 insertions, 18 deletions
diff --git a/pki/base/tps/doc/CS.cfg b/pki/base/tps/doc/CS.cfg
index 00482a2ba..033f14ab7 100644
--- a/pki/base/tps/doc/CS.cfg
+++ b/pki/base/tps/doc/CS.cfg
@@ -921,17 +921,31 @@ op.enroll.userKeyTemporary.tks.conn=tks1
op.enroll.userKeyTemporary.cardmgr_instance=A0000000030000
op.enroll.userKeyTemporary.auth.id=ldap1
op.enroll.userKeyTemporary.auth.enable=true
+# Token Renewal.
+# For each token in TPS UI set the following:
+# RENEW=YES
+# To trigger renewal operations.
op.enroll.userKey.renewal.keyType.num=2
op.enroll.userKey.renewal.keyType.value.0=signing
op.enroll.userKey.renewal.keyType.value.1=encryption
op.enroll.userKey.renewal.signing.enable=true
+#optional grace period enforcement
+#must coincide exactly with what the CA enforces
+op.enroll.userKey.renewal.signing.gracePeriod.enable=false
+op.enroll.userKey.renewal.signing.gracePeriod.before=30
+op.enroll.userKey.renewal.signing.gracePeriod.after=30
op.enroll.userKey.renewal.signing.certId=C1
-#encryption certId values for completeness only
+#in case of renewal, encryption certId values for completeness only
#server code calculates actual values used.
op.enroll.userKey.renewal.encryption.certId=C2
op.enroll.userKey.renewal.signing.certAttrId=c1
op.enroll.userKey.renewal.encryption.certAttrId=c2
op.enroll.userKey.renewal.encryption.enable=true
+#optional grace period enforcement
+#must coincide exactly with what the CA enforces
+op.enroll.userKey.renewal.encryption.gracePeriod.enable=false
+op.enroll.userKey.renewal.encryption.gracePeriod.before=30
+op.enroll.userKey.renewal.encryption.gracePeriod.after=30
op.enroll.userKey.renewal.signing.ca.conn=ca1
op.enroll.userKey.renewal.encryption.ca.conn=ca1
op.enroll.userKey.renewal.signing.ca.profileId=caTokenUserSigningKeyRenewal
diff --git a/pki/base/tps/src/engine/RA.cpp b/pki/base/tps/src/engine/RA.cpp
index 69ca1ec09..1ff81d57b 100644
--- a/pki/base/tps/src/engine/RA.cpp
+++ b/pki/base/tps/src/engine/RA.cpp
@@ -2839,6 +2839,7 @@ int RA::tdb_update_certificates(char* cuid, char **tokentypes, char *userid, CER
goto loser;
}
+ RA::Debug(LL_PER_PDU, "RA::tdb_update_certificates","numOfCerts %d", numOfCerts);
/* update certificates */
for (i = 0; i < numOfCerts; i++) {
if (certificates[i] == NULL) {
diff --git a/pki/base/tps/src/include/processor/RA_Enroll_Processor.h b/pki/base/tps/src/include/processor/RA_Enroll_Processor.h
index 17c56302d..1b91f6d6c 100644
--- a/pki/base/tps/src/include/processor/RA_Enroll_Processor.h
+++ b/pki/base/tps/src/include/processor/RA_Enroll_Processor.h
@@ -293,6 +293,7 @@ class RA_Enroll_Processor : public RA_Processor
private:
int GetNextFreeCertIdNumber(PKCS11Obj *pkcs11objx);
+ bool isCertRenewable(CERTCertificate *cert, int graceBefore, int graceAfter);
};
#endif /* RA_ENROLL_PROCESSOR_H */
diff --git a/pki/base/tps/src/processor/RA_Enroll_Processor.cpp b/pki/base/tps/src/processor/RA_Enroll_Processor.cpp
index aa8fb4481..32fd7599b 100644
--- a/pki/base/tps/src/processor/RA_Enroll_Processor.cpp
+++ b/pki/base/tps/src/processor/RA_Enroll_Processor.cpp
@@ -31,6 +31,7 @@
#include <string.h>
+#include <time.h>
#include "pkcs11.h"
// for public key processing
@@ -71,6 +72,7 @@
#endif /* !XP_WIN32 */
SECStatus PK11_GenerateRandom(unsigned char *,int);
+void PrintPRTime(PRTime,char *);
// This parameter is read from the config file. It is the
@@ -1037,6 +1039,8 @@ bool RA_Enroll_Processor::GetAppletInfo(
BYTE &o_app_major_version,
BYTE &o_app_minor_version)
{
+ int total_mem = 0;
+ int free_mem = 0;
Buffer *token_status = NULL;
SelectApplet(a_session, 0x04, 0x00, a_aid);
token_status = GetStatus(a_session, 0x00, 0x00);
@@ -1050,11 +1054,22 @@ bool RA_Enroll_Processor::GetAppletInfo(
o_minor_version = ((BYTE*)*token_status)[1];
o_app_major_version = ((BYTE*)*token_status)[2]; // and this applet version?
o_app_minor_version = ((BYTE*)*token_status)[3];
+
+ BYTE tot_high = ((BYTE*)*token_status)[6];
+ BYTE tot_low = ((BYTE*)*token_status)[7];
+
+ BYTE free_high = ((BYTE*)*token_status)[10];
+ BYTE free_low = ((BYTE*)*token_status)[11];
+
+ total_mem = (tot_high << 8) + tot_low;
+ free_mem = (free_high << 8) + free_low;
+
+ RA::DebugBuffer("RA_Enroll_Processor::Process AppletInfo Data", "Data=", token_status);
delete token_status;
}
RA::Debug(LL_PER_PDU, "RA_Enroll_Processor::Process",
- "Major=%d Minor=%d Applet Major=%d Applet Minor=%d",
- o_major_version, o_minor_version, o_app_major_version, o_app_minor_version);
+ "Major=%d Minor=%d Applet Major=%d Applet Minor=%d Total Mem %d Free Mem %d",
+ o_major_version, o_minor_version, o_app_major_version, o_app_minor_version,total_mem,free_mem);
return true;
}
@@ -3156,24 +3171,51 @@ RA::Debug("RA_Enroll_Processor::GenerateCertsAfterRecoveryPolicy", "returning bo
/*
* cfu - check if a cert is within the renewal grace period
- * for now, just check if it expired
+ * utilize passed in grace period values.
*/
-bool isCertRenewable(CERTCertificate *cert){
+bool RA_Enroll_Processor::isCertRenewable(CERTCertificate *cert, int graceBefore, int graceAfter){
PRTime timeBefore, timeAfter, now;
- PRExplodedTime beforePrintable, afterPrintable;
- char *beforestr, *afterstr;
+ //Grace period input in days
+ RA::Debug("RA_Enroll_Processor::isCertRenewable","graceBefore %d graceAfter %d",graceBefore,graceAfter);
+ PRTime graceBefore64, graceAfter64,microSecondsPerSecond;
+ PRInt64 graceBeforeSeconds,graceAfterSeconds;
+
+ LL_I2L(microSecondsPerSecond, PR_USEC_PER_SEC);
+
+ //Get number of microseconds in each grace period value.
+ LL_I2L(graceBeforeSeconds, graceBefore * 60 * 60 * 24);
+ LL_I2L(graceAfterSeconds,graceAfter * 60 * 60 * 24);
+
+ LL_MUL(graceBefore64, microSecondsPerSecond,graceBeforeSeconds);
+ LL_MUL(graceAfter64, microSecondsPerSecond,graceAfterSeconds);
+
+ PRTime lowerBound, upperBound;
+
DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore);
DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter);
+
+ PrintPRTime(timeBefore,"timeBefore");
+ PrintPRTime(timeAfter,"timeAfter");
+
now = PR_Now();
- if (timeAfter <= now) {
+
+ //Calculate lower and upper legal bounds for time
+ LL_SUB(lowerBound,timeAfter, graceBefore64);
+ LL_ADD(upperBound,timeAfter,graceAfter64);
+
+ PrintPRTime(lowerBound,"lowerBound");
+ PrintPRTime(now,"now");
+ PrintPRTime(upperBound,"upperBound");
+
+ if(LL_CMP(now,>=, lowerBound) && LL_CMP(now,<=,upperBound)) {
+ RA::Debug("RA_Enroll_Processor::isCertRenewable","returning true!");
return true;
}
+
+ RA::Debug("RA_Enroll_Processor::isCertRenewable","returning false!");
+
return false;
-/*
- PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable);
- PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable);
-*/
}
/*
@@ -3233,8 +3275,26 @@ loser:
return r;
}
+#define RENEWAL_FAILURE 1
+#define RENEWAL_FAILURE_GRACE 2
-// cfu
+/*
+* Renewal logic
+* 1. Create Optional local TPS grace period per token profile,
+* per token type, such as signing or encryption.
+* This grace period must match how the CA is configured. Ex:
+* op.enroll.userKey.renewal.encryption.enable=true
+* op.enroll.userKey.renewal.encryption.gracePeriod.enable=true
+* op.enroll.userKey.renewal.encryption.gracePeriod.before=30
+* op.enroll.userKey.renewal.encryption.gracePeriod.after=30
+* 2. In case of a grace period failure the code will go on
+* and attempt to renew the next certificate in the list.
+* 3. In case of any other code failure, the code will abort
+* and leave the token untouched, while informing the user
+* with an error message.
+*
+*
+*/
bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session, char **&ktypes,
char **&origins,
char *tokenType, PKCS11Obj *pkcs11objx, int pkcs11obj_enable,
@@ -3253,6 +3313,11 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
const char *pretty_cuid = NULL;
char audit_msg[512] = "";
char *keyVersion = NULL;
+ int renewal_failure_found = 0;
+
+ int maxCertUpdate = 25;
+ char *renewedCertUpdateList[25];
+ int renewedCertUpdateCount = 0;
int i = 0;
const char *FN="RA_Enroll_Processor::ProcessRenewal";
@@ -3284,13 +3349,18 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
RA::Debug("RA_Enroll_Processor::ProcessRenewal", "keyType.num=%d", keyTypeNum);
- o_certNums = 0 /*keyTypeNum*/;
+ o_certNums = keyTypeNum;
certificates = (CERTCertificate **) malloc (sizeof(CERTCertificate *) * keyTypeNum);
ktypes = (char **) malloc (sizeof(char *) * keyTypeNum);
origins = (char **) malloc (sizeof(char *) * keyTypeNum);
tokenTypes = (char **) malloc (sizeof(char *) * keyTypeNum);
for (i=0; i<keyTypeNum; i++) {
+ certificates[i] = NULL;
+ ktypes[i] = NULL;
+ origins[i] = NULL;
+ tokenTypes[i] = NULL;
+
bool renewable = true;
// e.g. op.enroll.userKey.renewal.keyType.value.0=signing
// e.g. op.enroll.userKey.renewal.keyType.value.1=encryption
@@ -3419,6 +3489,10 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
Buffer *exponent=NULL;
CERTSubjectPublicKeyInfo* spkix = NULL;
+ bool graceEnabled = false;
+ int graceBefore = 0;
+ int graceAfter = 0;
+
if (certs[0] != NULL) {
RA::Debug("RA_Enroll_Processor::ProcessRenewal",
@@ -3464,19 +3538,56 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
RA::Debug("RA_Enroll_Processor::ProcessRenewal","got profileId=%s",profileId);
RA::Debug("RA_Enroll_Processor::ProcessRenewal", "begin renewal");
+
+
+ PR_snprintf(configname,256,
+ "op.enroll.%s.renewal.%s.gracePeriod.enable",tokenType,keyTypeValue);
+
+ graceEnabled = RA::GetConfigStore()->GetConfigAsBool(configname,0);
+
+ if(graceEnabled) {
+
+ PR_snprintf(configname,256,
+ "op.enroll.%s.renewal.%s.gracePeriod.before",tokenType,keyTypeValue);
+
+ graceBefore = RA::GetConfigStore()->GetConfigAsInt(configname,0);
+
+ PR_snprintf(configname,256,
+ "op.enroll.%s.renewal.%s.gracePeriod.after",tokenType,keyTypeValue);
+
+ graceAfter = RA::GetConfigStore()->GetConfigAsInt(configname,0);
+ // check if renewable (note: CA makes the final decision)
+ if (!isCertRenewable(certs[0],graceBefore,graceAfter)) {
+ RA::Debug("RA_Enroll_Processor::ProcessRenewal",
+ "Cert outside of renewal period");
+ renewal_failure_found = RENEWAL_FAILURE_GRACE;
+ //Since this is merely a grace period failure for one cert
+ //let's keep going.
+ r = true;
+ goto rloser;
+ }
+
+ }
+
// send renewal request to CA
// o_cert is the cert gotten back
r = DoRenewal(caconnid, profileId, certs[0], &o_cert, audit_msg);
if (r == false) {
- RA::Debug("RA_Enroll_Processor::ProcessRenewal", "after DoRenewal");
+ RA::Debug("RA_Enroll_Processor::ProcessRenewal", "after DoRenewal failure. o_cert %p",o_cert);
o_status = STATUS_ERROR_MAC_ENROLL_PDU;
-
+ //Assume a renewal grace failure here since we can't obtain the reason.
+ //This is the most likely error and there is a chance the next renewal may succeed.
+ renewal_failure_found = RENEWAL_FAILURE_GRACE;
char snum[2048];
RA::ra_tus_print_integer(snum, &(certs[0])->serialNumber);
RA::Audit(EV_RENEWAL, AUDIT_MSG_PROC_CERT_REQ,
userid, cuid, msn, "failure", "renewal", final_applet_version,
keyVersion != NULL ? keyVersion : "",
snum, caconnid, audit_msg);
+ //Since this is merely a grace period or renewal failure for one cert
+ //let's keep it going
+
+ r = true;
goto rloser;
}
@@ -3492,6 +3603,7 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
if(pattern == NULL)
{
RA::Debug("RA_Enroll_Processor::ProcessRenewal", "no configured cert label!");
+ renewal_failure_found = RENEWAL_FAILURE;
PR_snprintf(audit_msg,512, "No cert label configured for cert!");
goto rloser;
}
@@ -3524,7 +3636,7 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
ktypes[i] = PL_strdup(keyTypeValue);
origins[i] = PL_strdup(cuid);
certificates[i] = o_cert;
- o_certNums++;
+ //o_certNums++;
// For the encrytion cert we actually need to calculate the proper certId and certAttrId
// since we now leave previous encryption certs on the token to allow dencryption of old
@@ -3543,6 +3655,7 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
RA::Debug(LL_PER_CONNECTION,FN,
"RA_Enroll_Processor::ProcessRenewal","Possible misconfiguration or out of sync token!");
PR_snprintf(audit_msg, 512, "Renewal of cert failed, misconfiguration or out of sync token!");
+ renewal_failure_found = RENEWAL_FAILURE;
goto rloser;
}
@@ -3570,6 +3683,7 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
} else {
RA::Debug(LL_PER_CONNECTION,FN,
"Not implemented");
+ renewal_failure_found = RENEWAL_FAILURE;
PR_snprintf(audit_msg, 512, "Write cert to token failed: pkcs11obj_enable = false not implemented");
goto rloser;
/*
@@ -3605,6 +3719,7 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
key_type , finalCertAttrId, label, keyid);
if (b == NULL) {
PR_snprintf(audit_msg, 512, "Write cert to token failed: CreatePKCS11CertAttrsBuffer returns null");
+ renewal_failure_found = RENEWAL_FAILURE;
goto rloser;
}
ObjectSpec *objSpec =
@@ -3614,6 +3729,7 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
&b);
if (objSpec == NULL) {
PR_snprintf(audit_msg, 512, "Write cert to token failed: ParseFromTokenData returns null");
+ renewal_failure_found = RENEWAL_FAILURE;
goto rloser;
}
@@ -3646,6 +3762,7 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
RA::Debug(LL_PER_CONNECTION,FN,
"Not implemented");
PR_snprintf(audit_msg, 512, "Write cert to token failed: pkcs11obj_enable = false not implemented");
+ renewal_failure_found = RENEWAL_FAILURE;
goto rloser;
/*
RA::Debug(LL_PER_CONNECTION,FN,
@@ -3678,11 +3795,13 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
modulus = new Buffer((BYTE*) si_mod.data, si_mod.len);
if (modulus == NULL) {
PR_snprintf(audit_msg, 512, "Write cert to token failed: modulus is null");
+ renewal_failure_found = RENEWAL_FAILURE;
goto rloser;
}
spkix = SECKEY_CreateSubjectPublicKeyInfo(pk_p);
if (spkix == NULL) {
PR_snprintf(audit_msg, 512, "Write cert to token failed: CreateSubjectPublicKeyInfo returns null");
+ renewal_failure_found = RENEWAL_FAILURE;
goto rloser;
}
@@ -3696,6 +3815,7 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
si_kid = PK11_MakeIDFromPubKey(&spkix->subjectPublicKey);
if (si_kid == NULL) {
PR_snprintf(audit_msg, 512, "Write cert to token failed: si_kid is null");
+ renewal_failure_found = RENEWAL_FAILURE;
goto rloser;
}
spkix->subjectPublicKey.len <<= 3;
@@ -3705,12 +3825,14 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
keyid = new Buffer((BYTE*) si_kid->data, si_kid->len);
if (keyid == NULL) {
PR_snprintf(audit_msg, 512, "Write cert to token failed: keyid is null");
+ renewal_failure_found = RENEWAL_FAILURE;
goto rloser;
}
si_exp = pk_p->u.rsa.publicExponent;
exponent = new Buffer((BYTE*) si_exp.data, si_exp.len);
if (exponent == NULL) {
PR_snprintf(audit_msg, 512, "Write cert to token failed: exponent is null");
+ renewal_failure_found = RENEWAL_FAILURE;
goto rloser;
}
RA::Debug(LL_PER_PDU, "RA_Enroll_Processor::Process",
@@ -3739,13 +3861,20 @@ bool RA_Enroll_Processor::ProcessRenewal(AuthParams *login, RA_Session *session,
PL_strfree( (char *) label );
label = NULL;
}
+ if(renewal_failure_found == RENEWAL_FAILURE) {
+ RA::Debug("RA_Enroll_Processor_ProcessRenewal", "A renewal in list failed other than grace period error, aborting.");
+ goto loser;
+ }
}
break;
} //for
if((strcmp( attr_status, "active" ) == 0) &&
renewed) {
char *cn = RA::ra_get_cert_cn(e);
- RA::ra_update_cert_status(cn, "renewed");
+ if(renewedCertUpdateCount < ( maxCertUpdate -1)) //unlikely scenario this fails
+ renewedCertUpdateList[renewedCertUpdateCount++] = PL_strdup(cn);
+ // Let's hold off on the celebration until the end.
+ // RA::ra_update_cert_status(cn, "renewed");
if (cn != NULL) {
PL_strfree(cn);
cn = NULL;
@@ -3777,6 +3906,27 @@ loser:
audit_msg);
}
+ //Let's wait until all the certs are processed to actually update the renewal status
+ RA::Debug("RA_Enroll_Process::ProcessRenewal","renewedCertUpdateCount %d", renewedCertUpdateCount);
+ if(renewedCertUpdateCount > 0) {
+ for(int rr = 0; rr < renewedCertUpdateCount; rr++) {
+ if(renewedCertUpdateList[rr]) {
+ if(renewal_failure_found != RENEWAL_FAILURE) {
+ RA::Debug("RA_Enroll_Process::ProcessRenewal","updating to renewed status of cn= %s", renewedCertUpdateList[rr]);
+ RA::ra_update_cert_status(renewedCertUpdateList[rr],"renewed");
+ }
+ PL_strfree(renewedCertUpdateList[rr]);
+ renewedCertUpdateList[rr] = NULL;
+ }
+ }
+ } else {
+ // All certs failed to renew
+ RA::Debug("RA_Enroll_Process::ProcessRenewal","All certs failed to renew, bailing with error");
+ o_status = STATUS_ERROR_MAC_ENROLL_PDU;
+ r = false;
+
+ }
+
if( pretty_cuid != NULL ) {
PR_Free( (char *) pretty_cuid );
pretty_cuid = NULL;
@@ -4532,6 +4682,7 @@ bool RA_Enroll_Processor::ProcessRecovery(AuthParams *login, char *reason, RA_Se
ldap_msgfree( result );
}
+
RA::Debug("RA_Enroll_Processor::ProcessRecovery","leaving whole function...");
return r;
}
@@ -4697,3 +4848,29 @@ int RA_Enroll_Processor::GetNextFreeCertIdNumber(PKCS11Obj *pkcs11objx)
"returning id number: %d", highest_cert_id + 1);
return highest_cert_id + 1;
}
+
+void PrintPRTime(PRTime theTime,char *theName)
+{
+ struct tm t;
+ PRExplodedTime explode;
+ char buffer[256];
+
+ if(!theName)
+ return;
+
+ PR_ExplodeTime (theTime, PR_LocalTimeParameters, &explode);
+
+ t.tm_sec = explode.tm_sec;
+ t.tm_min = explode.tm_min;
+ t.tm_hour = explode.tm_hour;
+ t.tm_mday = explode.tm_mday;
+ t.tm_mon = explode.tm_month;
+ t.tm_year = explode.tm_year - 1900;
+ t.tm_wday = explode.tm_wday;
+ t.tm_yday = explode.tm_yday;
+
+ PL_strncpy(buffer, asctime (&t), 256);
+ buffer[256 - 1] = 0;
+
+ RA::Debug("PrintPRTime","Date/Time: %s %s",theName,buffer);
+}