diff options
author | cfu <cfu@c9f7a03b-bd48-0410-a16d-cbbf54688b0b> | 2008-11-18 23:39:12 +0000 |
---|---|---|
committer | cfu <cfu@c9f7a03b-bd48-0410-a16d-cbbf54688b0b> | 2008-11-18 23:39:12 +0000 |
commit | ab68b8dc0a485e2b4bf505cbdea8da786a13ce41 (patch) | |
tree | b665054fd8b4749578137f3e72998f701bef0a7a /pki | |
parent | 0e913677fe84263495a20c1fe4f47508f762a1ad (diff) | |
download | pki-ab68b8dc0a485e2b4bf505cbdea8da786a13ce41.tar.gz pki-ab68b8dc0a485e2b4bf505cbdea8da786a13ce41.tar.xz pki-ab68b8dc0a485e2b4bf505cbdea8da786a13ce41.zip |
Bugzilla Bug #471622 - Need Renewal feature via enrollment profile Framework (Phase 1)
git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/trunk@141 c9f7a03b-bd48-0410-a16d-cbbf54688b0b
Diffstat (limited to 'pki')
27 files changed, 1446 insertions, 22 deletions
diff --git a/pki/base/ca/shared/conf/CS.cfg b/pki/base/ca/shared/conf/CS.cfg index b552a6b29..7d8fd4140 100644 --- a/pki/base/ca/shared/conf/CS.cfg +++ b/pki/base/ca/shared/conf/CS.cfg @@ -106,6 +106,7 @@ CrossCertPair.ldap=internaldb accessEvaluator.impl.group.class=com.netscape.cms.evaluators.GroupAccessEvaluator accessEvaluator.impl.ipaddress.class=com.netscape.cms.evaluators.IPAddressAccessEvaluator accessEvaluator.impl.user.class=com.netscape.cms.evaluators.UserAccessEvaluator +accessEvaluator.impl.user_origreq.class=com.netscape.cms.evaluators.UserOrigReqAccessEvaluator auths._000=## auths._001=## new authentication auths._002=## @@ -116,6 +117,7 @@ auths.impl.AgentCertAuth.class=com.netscape.cms.authentication.AgentCertAuthenti auths.impl.CMCAuth.class=com.netscape.cms.authentication.CMCAuth auths.impl.NISAuth.class=com.netscape.cms.authentication.NISAuth auths.impl.PortalEnroll.class=com.netscape.cms.authentication.PortalEnroll +auths.impl.SSLclientCertAuth.class=com.netscape.cms.authentication.SSLclientCertAuthentication auths.impl.UdnPwdDirAuth.class=com.netscape.cms.authentication.UdnPwdDirAuthentication auths.impl.UidPwdDirAuth.class=com.netscape.cms.authentication.UidPwdDirAuthentication auths.impl.UidPwdPinDirAuth.class=com.netscape.cms.authentication.UidPwdPinDirAuthentication @@ -129,6 +131,7 @@ auths.instance.raCertAuth.agentGroup=Registration Manager Agents auths.instance.raCertAuth.pluginName=AgentCertAuth auths.instance.flatFileAuth.pluginName=FlatFileAuth auths.instance.flatFileAuth.fileName=[PKI_INSTANCE_PATH]/conf/flatfile.txt +auths.instance.SSLclientCertAuth.pluginName=SSLclientCertAuth auths.revocationChecking.bufferSize=50 auths.revocationChecking.ca=ca auths.revocationChecking.enabled=true @@ -796,9 +799,15 @@ oidmap.pse.oid=2.16.840.1.113730.1.18 oidmap.subject_info_access.class=netscape.security.extensions.SubjectInfoAccessExtension oidmap.subject_info_access.oid=1.3.6.1.5.5.7.1.11 os.userid=nobody -profile.list=caUserCert,caDualCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caOtherCert,caCACert,caInstallCACert,caRACert,caOCSPCert,caTransportCert,caDirUserCert,caAgentServerCert,caAgentFileSigning,caCMCUserCert,caFullCMCUserCert,caSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caInternalAuthOCSPCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert +profile.list=caUserCert,caDualCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caOtherCert,caCACert,caInstallCACert,caRACert,caOCSPCert,caTransportCert,caDirUserCert,caAgentServerCert,caAgentFileSigning,caCMCUserCert,caFullCMCUserCert,caSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caInternalAuthOCSPCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal profile.caUUIDdeviceCert.class_id=caEnrollImpl profile.caUUIDdeviceCert.config=[PKI_INSTANCE_PATH]/profiles/ca/caUUIDdeviceCert.cfg +profile.caManualRenewal.class_id=caEnrollImpl +profile.caManualRenewal.config=[PKI_INSTANCE_PATH]/profiles/ca/caManualRenewal.cfg +profile.caDirUserRenewal.class_id=caEnrollImpl +profile.caDirUserRenewal.config=[PKI_INSTANCE_PATH]/profiles/ca/caDirUserRenewal.cfg +profile.caSSLClientSelfRenewal.class_id=caEnrollImpl +profile.caSSLClientSelfRenewal.config=[PKI_INSTANCE_PATH]/profiles/ca/caSSLClientSelfRenewal.cfg profile.DomainController.class_id=caEnrollImpl profile.DomainController.config=[PKI_INSTANCE_PATH]/profiles/ca/DomainController.cfg profile.caAgentFileSigning.class_id=caEnrollImpl diff --git a/pki/base/ca/shared/conf/registry.cfg b/pki/base/ca/shared/conf/registry.cfg index 807ebdd4d..5cb40faba 100644 --- a/pki/base/ca/shared/conf/registry.cfg +++ b/pki/base/ca/shared/conf/registry.cfg @@ -1,5 +1,5 @@ types=profile,defaultPolicy,constraintPolicy,profileInput,profileOutput,profileUpdater -constraintPolicy.ids=noConstraintImpl,subjectNameConstraintImpl,uniqueSubjectNameConstraintImpl,validityConstraintImpl,keyUsageExtConstraintImpl,nsCertTypeExtConstraintImpl,extendedKeyUsageExtConstraintImpl,keyConstraintImpl,basicConstraintsExtConstraintImpl,extensionConstraintImpl,signingAlgConstraintImpl,uniqueKeyConstraintImpl +constraintPolicy.ids=noConstraintImpl,subjectNameConstraintImpl,uniqueSubjectNameConstraintImpl,validityConstraintImpl,keyUsageExtConstraintImpl,nsCertTypeExtConstraintImpl,extendedKeyUsageExtConstraintImpl,keyConstraintImpl,basicConstraintsExtConstraintImpl,extensionConstraintImpl,signingAlgConstraintImpl,uniqueKeyConstraintImpl,renewGracePeriodConstraintImpl constraintPolicy.signingAlgConstraintImpl.class=com.netscape.cms.profile.constraint.SigningAlgConstraint constraintPolicy.signingAlgConstraintImpl.desc=Signing Algorithm Constraint constraintPolicy.signingAlgConstraintImpl.name=Signing Algorithm Constraint @@ -33,6 +33,9 @@ constraintPolicy.uniqueSubjectNameConstraintImpl.name=Unique Subject Name Constr constraintPolicy.validityConstraintImpl.class=com.netscape.cms.profile.constraint.ValidityConstraint constraintPolicy.validityConstraintImpl.desc=Validity Constraint constraintPolicy.validityConstraintImpl.name=Validity Constraint +constraintPolicy.renewGracePeriodConstraintImpl.class=com.netscape.cms.profile.constraint.RenewGracePeriodConstraint +constraintPolicy.renewGracePeriodConstraintImpl.desc=Renewal Grace Period Constraint +constraintPolicy.renewGracePeriodConstraintImpl.name=Renewal Grace Period Constraint constraintPolicy.uniqueKeyConstraintImpl.class=com.netscape.cms.profile.constraint.UniqueKeyConstraint constraintPolicy.uniqueKeyConstraintImpl.desc=Unique Public Key Constraint constraintPolicy.uniqueKeyConstraintImpl.name=Unique Public Key Constraint @@ -161,7 +164,7 @@ profile.caServerCertEnrollImpl.name=Server Certificate Enrollment Profile profile.caUserCertEnrollImpl.class=com.netscape.cms.profile.common.UserCertCAEnrollProfile profile.caUserCertEnrollImpl.desc=Certificate Authority User Certificate Enrollment Profile profile.caUserCertEnrollImpl.name=User Certificate Enrollment Profile -profileInput.ids=cmcCertReqInputImpl,certReqInputImpl,keyGenInputImpl,dualKeyGenInputImpl,subjectNameInputImpl,submitterInfoInputImpl,genericInputImpl,fileSigningInputImpl,imageInputImpl,subjectDNInputImpl,nsNKeyCertReqInputImpl,nsHKeyCertReqInputImpl +profileInput.ids=cmcCertReqInputImpl,certReqInputImpl,keyGenInputImpl,dualKeyGenInputImpl,subjectNameInputImpl,submitterInfoInputImpl,genericInputImpl,fileSigningInputImpl,imageInputImpl,subjectDNInputImpl,nsNKeyCertReqInputImpl,nsHKeyCertReqInputImpl,serialNumRenewInputImpl profileInput.fileSigningInputImpl.class=com.netscape.cms.profile.input.FileSigningInput profileInput.fileSigningInputImpl.desc=File Signing Input profileInput.fileSigningInputImpl.name=File Signing Input @@ -192,6 +195,9 @@ profileInput.nsNKeyCertReqInputImpl.name=nsNKeyCertReqInputImpl profileInput.nsHKeyCertReqInputImpl.class=com.netscape.cms.profile.input.nsHKeyCertReqInput profileInput.nsHKeyCertReqInputImpl.desc=nsHKeyCertReqInputImpl profileInput.nsHKeyCertReqInputImpl.name=nsHKeyCertReqInputImpl +profileInput.serialNumRenewInputImpl.class=com.netscape.cms.profile.input.SerialNumRenewInput +profileInput.serialNumRenewInputImpl.desc=Certificate Renewal Request Serial Number Input +profileInput.serialNumRenewInputImpl.name=Certificate Renewal Request Serial Number Input profileInput.subjectDNInputImpl.class=com.netscape.cms.profile.input.SubjectDNInput profileInput.subjectDNInputImpl.desc=Subject DN Input profileInput.subjectDNInputImpl.name=Subject DN Input diff --git a/pki/base/ca/shared/profiles/ca/caDirUserCert.cfg b/pki/base/ca/shared/profiles/ca/caDirUserCert.cfg index 3806d0b21..693f3dc9e 100644 --- a/pki/base/ca/shared/profiles/ca/caDirUserCert.cfg +++ b/pki/base/ca/shared/profiles/ca/caDirUserCert.cfg @@ -9,7 +9,7 @@ input.i1.class_id=keyGenInputImpl output.list=o1 output.o1.class_id=certOutputImpl policyset.list=userCertSet -policyset.userCertSet.list=1,2,3,4,5,6,7,8,9 +policyset.userCertSet.list=1,10,2,3,4,5,6,7,8,9 policyset.userCertSet.1.constraint.class_id=subjectNameConstraintImpl policyset.userCertSet.1.constraint.name=Subject Name Constraint policyset.userCertSet.1.constraint.params.pattern=UID=.* @@ -17,6 +17,12 @@ policyset.userCertSet.1.constraint.params.accept=true policyset.userCertSet.1.default.class_id=authTokenSubjectNameDefaultImpl policyset.userCertSet.1.default.name=Subject Name Default policyset.userCertSet.1.default.params.name= +policyset.userCertSet.10.constraint.class_id=renewGracePeriodConstraintImpl +policyset.userCertSet.10.constraint.name=Renewal Grace Period Constraint +policyset.userCertSet.10.constraint.params.renewal.graceBefore=30 +policyset.userCertSet.10.constraint.params.renewal.graceAfter=30 +policyset.userCertSet.10.default.class_id=noDefaultImpl +policyset.userCertSet.10.default.name=No Default policyset.userCertSet.2.constraint.class_id=validityConstraintImpl policyset.userCertSet.2.constraint.name=Validity Constraint policyset.userCertSet.2.constraint.params.range=365 diff --git a/pki/base/ca/shared/profiles/ca/caDirUserRenewal.cfg b/pki/base/ca/shared/profiles/ca/caDirUserRenewal.cfg new file mode 100755 index 000000000..f0ec21388 --- /dev/null +++ b/pki/base/ca/shared/profiles/ca/caDirUserRenewal.cfg @@ -0,0 +1,12 @@ +desc=This certificate profile is for renewing a certificate by serial number by using directory based authentication. +visible=true +enable=true +enableBy=admin +renewal=true +auth.instance_id=UserDirEnrollment +authz.acl=user_origreq="auth_token.uid" +name=Directory-Authenticated User Certificate Self-Renew profile +input.list=i1 +input.i1.class_id=serialNumRenewInputImpl +output.list=o1 +output.o1.class_id=certOutputImpl diff --git a/pki/base/ca/shared/profiles/ca/caManualRenewal.cfg b/pki/base/ca/shared/profiles/ca/caManualRenewal.cfg new file mode 100755 index 000000000..b691b4d10 --- /dev/null +++ b/pki/base/ca/shared/profiles/ca/caManualRenewal.cfg @@ -0,0 +1,11 @@ +desc=This certificate profile is for renewing certificates to be approved manually by agents. +visible=true +enable=true +enableBy=admin +renewal=true +auth.instance_id= +name=Renew certificate to be manually approved by agents +input.list=i1 +input.i1.class_id=serialNumRenewInputImpl +output.list=o1 +output.o1.class_id=certOutputImpl diff --git a/pki/base/ca/shared/profiles/ca/caSSLClientSelfRenewal.cfg b/pki/base/ca/shared/profiles/ca/caSSLClientSelfRenewal.cfg new file mode 100755 index 000000000..f89c1b143 --- /dev/null +++ b/pki/base/ca/shared/profiles/ca/caSSLClientSelfRenewal.cfg @@ -0,0 +1,9 @@ +desc=This certificate profile is for renewing SSL client certificates. +visible=true +enable=true +enableBy=admin +renewal=true +auth.instance_id=SSLclientCertAuth +name=Self-renew user SSL client certificates +output.list=o1 +output.o1.class_id=certOutputImpl diff --git a/pki/base/ca/shared/profiles/ca/caUserCert.cfg b/pki/base/ca/shared/profiles/ca/caUserCert.cfg index bd5932a76..56780ac62 100644 --- a/pki/base/ca/shared/profiles/ca/caUserCert.cfg +++ b/pki/base/ca/shared/profiles/ca/caUserCert.cfg @@ -11,7 +11,7 @@ input.i3.class_id=submitterInfoInputImpl output.list=o1 output.o1.class_id=certOutputImpl policyset.list=userCertSet -policyset.userCertSet.list=1,2,3,4,5,6,7,8,9 +policyset.userCertSet.list=1,10,2,3,4,5,6,7,8,9 policyset.userCertSet.1.constraint.class_id=subjectNameConstraintImpl policyset.userCertSet.1.constraint.name=Subject Name Constraint policyset.userCertSet.1.constraint.params.pattern=UID=.* @@ -19,6 +19,12 @@ policyset.userCertSet.1.constraint.params.accept=true policyset.userCertSet.1.default.class_id=userSubjectNameDefaultImpl policyset.userCertSet.1.default.name=Subject Name Default policyset.userCertSet.1.default.params.name= +policyset.userCertSet.10.constraint.class_id=renewGracePeriodConstraintImpl +policyset.userCertSet.10.constraint.name=Renewal Grace Period Constraint +policyset.userCertSet.10.constraint.params.renewal.graceBefore=30 +policyset.userCertSet.10.constraint.params.renewal.graceAfter=30 +policyset.userCertSet.10.default.class_id=noDefaultImpl +policyset.userCertSet.10.default.name=No Default policyset.userCertSet.2.constraint.class_id=validityConstraintImpl policyset.userCertSet.2.constraint.name=Validity Constraint policyset.userCertSet.2.constraint.params.range=365 diff --git a/pki/base/common/src/UserMessages_en.properties b/pki/base/common/src/UserMessages_en.properties index 1ea7ebd88..e0081fb06 100644 --- a/pki/base/common/src/UserMessages_en.properties +++ b/pki/base/common/src/UserMessages_en.properties @@ -305,6 +305,8 @@ CMS_AUTHENTICATION_NIS_NAME=NIS Authentication CMS_AUTHENTICATION_NIS_TEXT=This plugin authenticates a user using NIS. CMS_AUTHENTICATION_AGENT_NAME=Agent Authentication CMS_AUTHENTICATION_AGENT_TEXT=This plugin authenticates agents using a certificate. +CMS_AUTHENTICATION_SSL_CLIENT_NAME=SSL Client Authentication +CMS_AUTHENTICATION_SSL_CLIENT_TEXT=This plugin authenticates users using a certificate. CMS_AUTHENTICATION_CMC_SIGN_NAME=CMC Agent Signature Authentication CMS_AUTHENTICATION_CMC_SIGN_TEXT=This plugin authenticates the signature in the CMC request against the CS internal database. CMS_AUTHENTICATION_LDAP_UID_PIN_NAME=LDAP UID & Password & Pin Authentication @@ -819,6 +821,10 @@ CMS_PROFILE_VALIDITY_CHECK_NOT_AFTER=Check Not After against Not Before CMS_PROFILE_VALIDITY_RANGE=Validity Range (in days) CMS_PROFILE_VALIDITY_START_TIME=Relative Start Time (in seconds) CMS_PROFILE_VALIDITY_OUT_OF_RANGE=Validity Out of Range {0} days +CMS_PROFILE_RENEW_GRACE_BEFORE=Renewal Grace Period Before +CMS_PROFILE_RENEW_GRACE_AFTER=Renewal Grace Period After +CMS_PROFILE_RENEW_OUTSIDE_GRACE_PERIOD=Outside of Renewal Grace Period: {0} +CMS_PROFILE_RENEW_ORIG_EXP_NOT_FOUND=Renewal: Original Cert Expiration Date Not Found. Cannot validate. CMS_PROFILE_INVALID_VALIDITY=Invalid Validity CMS_PROFILE_NOT_BEFORE_BEFORE_CURRENT=Not Before is earlier than current time CMS_PROFILE_NOT_AFTER_BEFORE_NOT_BEFORE=Not After is earlier than Not Before @@ -915,7 +921,9 @@ CMS_PROFILE_CONSTRAINT_NO_CONSTRAINT_TEXT=No Constraint CMS_PROFILE_CONSTRAINT_SIGNING_ALG_TEXT=This constraint accepts only the Signing Algorithms of {0} CMS_PROFILE_CONSTRAINT_SUBJECT_NAME_TEXT=This constraint accepts the subject name that matches {0} CMS_PROFILE_CONSTRAINT_UNIQUE_SUBJECT_NAME_TEXT=This constraint accepts unique subject name only -CMS_PROFILE_CONSTRAINT_VALIDITY_TEXT=This constraint rejects the validity that is not between {0} days +CMS_PROFILE_CONSTRAINT_VALIDITY_TEXT=This constraint rejects the validity that is not between {0} days. +CMS_PROFILE_CONSTRAINT_RENEWAL_GRACE_PERIOD_TEXT=This constraint rejects the renewal requests that are outside of the grace period {0} +CMS_PROFILE_CONSTRAINT_VALIDITY_RENEWAL_TEXT=This constraint rejects the validity that is not between {0} days. If renewal, grace period is {1} days before and {2} days after the expiration date of the original certificate. CMS_PROFILE_DEF_SIA_TEXT=This default populates a Subject Info Access Extension (1.3.6.1.5.5.7.1.11) to the request. The default values are Criticality={0}, {1} CMS_PROFILE_DEF_AIA_TEXT=This default populates a Authority Info Access Extension (1.3.6.1.5.5.7.1.1) to the request. The default values are Criticality={0}, {1} CMS_PROFILE_DEF_IMAGE=This default populates the image from the user. @@ -999,6 +1007,8 @@ CMS_PROFILE_IMAGE=Image CMS_PROFILE_INPUT_IMAGE_NAME=Image CMS_PROFILE_INPUT_IMAGE_TEXT=Image CMS_PROFILE_INPUT_IMAGE_URL=Image URL +CMS_PROFILE_INPUT_SERIAL_NUM_NAME=Serial Number of Certificate to Renew +CMS_PROFILE_INPUT_SERIAL_NUM_TEXT=Serial Number of Certificate to Renew CMS_PROFILE_INPUT_SUBMITTER_NAME=Requestor Information CMS_PROFILE_INPUT_SUBMITTER_TEXT=Requestor Information CMS_PROFILE_INPUT_GENERIC_NAME_NAME=Generic Input diff --git a/pki/base/common/src/com/netscape/certsrv/profile/IProfile.java b/pki/base/common/src/com/netscape/certsrv/profile/IProfile.java index 1c643a3df..c8ca1472f 100644 --- a/pki/base/common/src/com/netscape/certsrv/profile/IProfile.java +++ b/pki/base/common/src/com/netscape/certsrv/profile/IProfile.java @@ -184,6 +184,11 @@ public interface IProfile { */ public String getApprovedBy(); + /* + * Is this a renewal profile + */ + public String isRenewal(); + /** * Returns the profile name. * diff --git a/pki/base/common/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java b/pki/base/common/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java new file mode 100644 index 000000000..7a3993cde --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java @@ -0,0 +1,353 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2008 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.authentication; + + +import netscape.ldap.*; +import java.util.*; +import java.lang.Class; +import java.security.cert.*; +import java.security.Principal; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.policy.*; + +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.kra.*; + +import javax.servlet.http.HttpServletRequest; + + +/** + * Certificate server SSL client authentication. + * + * @author Christina Fu + * <P> + * + */ +public class SSLclientCertAuthentication implements IAuthManager, + IProfileAuthenticator { + + /* result auth token attributes */ + public static final String TOKEN_USERDN = "user"; + public static final String TOKEN_USER_DN = "userdn"; + public static final String TOKEN_USERID = "userid"; + public static final String TOKEN_UID = "uid"; + + /* required credentials */ + public static final String CRED_CERT = IAuthManager.CRED_SSL_CLIENT_CERT; + protected String[] mRequiredCreds = { CRED_CERT }; + + /* config parameters to pass to console (none) */ + protected static String[] mConfigParams = null; + + private String mName = null; + private String mImplName = null; + private IConfigStore mConfig = null; + + private ILogger mLogger = CMS.getLogger(); + + private IConfigStore mRevocationChecking = null; + private String mRequestor = null; + + public SSLclientCertAuthentication() { + } + + /** + * initializes the SSLClientCertAuthentication auth manager + * <p> + * called by AuthSubsystem init() method, when initializing + * all available authentication managers. + * @param name The name of this authentication manager instance. + * @param implName The name of the authentication manager plugin. + * @param config The configuration store for this authentication manager. + */ + public void init(String name, String implName, IConfigStore config) + throws EBaseException { + mName = name; + mImplName = implName; + mConfig = config; + } + + /** + * Gets the name of this authentication manager. + */ + public String getName() { + return mName; + } + + /** + * Gets the plugin name of authentication manager. + */ + public String getImplName() { + return mImplName; + } + + public boolean isSSLClientRequired() { + return true; + } + + /** + * authenticates user by certificate + * <p> + * called by other subsystems or their servlets to authenticate + * users + * @param authCred - authentication credential that contains + * an usrgrp.Certificates of the user (agent) + * @return the authentication token that contains the following + * + * @exception EMissingCredential If a required credential for this + * authentication manager is missing. + * @exception EInvalidCredentials If credentials cannot be authenticated. + * @exception EBaseException If an internal error occurred. + * @see com.netscape.certsrv.authentication.AuthToken + * @see com.netscape.certsrv.usrgrp.Certificates + */ + public IAuthToken authenticate(IAuthCredentials authCred) + throws EMissingCredential, EInvalidCredentials, EBaseException { + + CMS.debug("SSLclientCertAuthentication: start"); + CMS.debug("authenticator instance name is "+getName()); + + // force SSL handshake + SessionContext context = SessionContext.getExistingContext(); + ISSLClientCertProvider provider = (ISSLClientCertProvider) + context.get("sslClientCertProvider"); + + if (provider == null) { + CMS.debug("SSLclientCertAuthentication: No SSL Client Cert Provider Found"); + throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL")); + } + CMS.debug("SSLclientCertAuthentication: got provider"); + CMS.debug("SSLclientCertAuthentication: retrieving client certificate"); + X509Certificate[] allCerts = provider.getClientCertificateChain(); + + if (allCerts == null) { + CMS.debug("SSLclientCertAuthentication: No SSL Client Certs Found"); + throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL")); + } + CMS.debug("SSLclientCertAuthentication: got certificates"); + + // retreive certificate from socket + AuthToken authToken = new AuthToken(this); + X509Certificate[] x509Certs = allCerts; + + // default certificate default has bugs in version + // version(3) is returned as 3, which should be 2 + X509CertImpl ci[] = new X509CertImpl[x509Certs.length]; + + X509Certificate clientCert = null; + try { + for (int i = 0; i < x509Certs.length; i++) { + ci[i] = new X509CertImpl(x509Certs[i].getEncoded()); + // find out which one is the leaf cert + clientCert = ci[i]; + + byte [] extBytes = clientCert.getExtensionValue("2.5.29.19"); + // try to see if this is a leaf cert + // look for BasicConstraint extension + if (extBytes == null) { + // found leaf cert + CMS.debug("SSLclientCertAuthentication: authenticate: found leaf cert"); + break; + } else { + CMS.debug("SSLclientCertAuthentication: authenticate: found cert having BasicConstraints ext"); + // it's got BasicConstraints extension + // so it's not likely to be a leaf cert, + // however, check the isCA field regardless + try { + BasicConstraintsExtension bce = + new BasicConstraintsExtension(true, extBytes); + if (bce != null) { + if (!(Boolean)bce.get("is_ca")) { + CMS.debug("SSLclientCertAuthentication: authenticate: found CA cert in chain"); + break; + } // else found a ca cert, continue + } + } catch (Exception e) { + CMS.debug("SSLclientCertAuthentication: authenticate: exception:"+ + e.toString()); + throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL")); + } + } + } + if (clientCert == null) { + CMS.debug("SSLclientCertAuthentication: authenticate: client cert not found"); + throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL")); + } + } catch (CertificateException e) { + CMS.debug(e.toString()); + throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL")); + } + + // check if certificate(s) is revoked + boolean checkRevocation = true; + try { + checkRevocation = mConfig.getBoolean("checkRevocation", true); + } catch (EBaseException e) { + // do nothing; default to true + } + if (checkRevocation) { + if (CMS.isRevoked(ci)) { + CMS.debug("SSLclientCertAuthentication: certificate revoked"); + throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL")); + } + } + Certificates certs = new Certificates(ci); + Principal p_dn = clientCert.getSubjectDN(); + authToken.set(TOKEN_USERDN, p_dn.getName()); + authToken.set("userdn", p_dn.getName()); + String uid = getUidFromDN(p_dn.getName()); + if (uid != null) { + authToken.set(TOKEN_UID, uid); + authToken.set(TOKEN_USERID, uid); + } +/* + authToken.set(TOKEN_USER_DN, user.getUserDN()); + authToken.set(TOKEN_USERID, user.getUserID()); + authToken.set(TOKEN_UID, user.getUserID()); + authToken.set(TOKEN_GROUP, groupname); +*/ + authToken.set(CRED_CERT, certs); + + CMS.debug("SSLclientCertAuthentication: authenticated "); + + return authToken; + } + + String getUidFromDN(String userdn) { + StringTokenizer st = new StringTokenizer(userdn, ","); + while (st.hasMoreTokens()) { + String t = st.nextToken(); + int i = t.indexOf("="); + + if (i == -1) { + continue; + } + String n = t.substring(0, i); + if (n.equalsIgnoreCase("uid")) { + String v = t.substring(i + 1); + CMS.debug("SSLclientCertAuthentication: getUidFromDN(): uid found:"+v); + return v; + } else { + continue; + } + } + return null; + } + + /** + * get the list of authentication credential attribute names + * required by this authentication manager. Generally used by + * the servlets that handle agent operations to authenticate its + * users. It calls this method to know which are the + * required credentials from the user (e.g. Javascript form data) + * @return attribute names in Vector + */ + public String[] getRequiredCreds() { + return (mRequiredCreds); + } + + /** + * get the list of configuration parameter names + * required by this authentication manager. Generally used by + * the Certificate Server Console to display the table for + * configuration purposes. CertUserDBAuthentication is currently not + * exposed in this case, so this method is not to be used. + * @return configuration parameter names in Hashtable of Vectors + * where each hashtable entry's key is the substore name, value is a + * Vector of parameter names. If no substore, the parameter name + * is the Hashtable key itself, with value same as key. + */ + public String[] getConfigParams() { + return (mConfigParams); + } + + /** + * prepare this authentication manager for shutdown. + */ + public void shutdown() { + } + + /** + * gets the configuretion substore used by this authentication + * manager + * @return configuration store + */ + public IConfigStore getConfigStore() { + return mConfig; + } + + // Profile-related methods + + public void init(IProfile profile, IConfigStore config) + throws EProfileException { + } + + /** + * Retrieves the localizable name of this policy. + */ + public String getName(Locale locale) { + return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_SSL_CLIENT_NAME"); + } + + /** + * Retrieves the localizable description of this policy. + */ + public String getText(Locale locale) { + return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_SSL_CLIENT_TEXT"); + } + + /** + * Retrieves a list of names of the value parameter. + */ + public Enumeration getValueNames() { + return null; + } + + public boolean isValueWriteable(String name) { + return false; + } + + /** + * Retrieves the descriptor of the given value + * parameter by name. + */ + public IDescriptor getValueDescriptor(Locale locale, String name) { + return null; + } + + public void populate(IAuthToken token, IRequest request) + throws EProfileException { + request.setExtData(IProfileAuthenticator.AUTHENTICATED_NAME, + token.getInString(TOKEN_USERDN)); + request.setExtData(IProfileAuthenticator.AUTHENTICATED_NAME, + token.getInString("userDN")); + } +} diff --git a/pki/base/common/src/com/netscape/cms/evaluators/GroupAccessEvaluator.java b/pki/base/common/src/com/netscape/cms/evaluators/GroupAccessEvaluator.java index d153dd88f..dc42b6fb1 100644 --- a/pki/base/common/src/com/netscape/cms/evaluators/GroupAccessEvaluator.java +++ b/pki/base/common/src/com/netscape/cms/evaluators/GroupAccessEvaluator.java @@ -58,6 +58,7 @@ public class GroupAccessEvaluator implements IAccessEvaluator { * initialization. nothing for now. */ public void init() { + CMS.debug("GroupAccessEvaluator: init"); } /** diff --git a/pki/base/common/src/com/netscape/cms/evaluators/UserAccessEvaluator.java b/pki/base/common/src/com/netscape/cms/evaluators/UserAccessEvaluator.java index 0885f66b6..37be1e624 100644 --- a/pki/base/common/src/com/netscape/cms/evaluators/UserAccessEvaluator.java +++ b/pki/base/common/src/com/netscape/cms/evaluators/UserAccessEvaluator.java @@ -53,6 +53,7 @@ public class UserAccessEvaluator implements IAccessEvaluator { * initialization. nothing for now. */ public void init() { + CMS.debug("UserAccessEvaluator: init"); } /** diff --git a/pki/base/common/src/com/netscape/cms/evaluators/UserOrigReqAccessEvaluator.java b/pki/base/common/src/com/netscape/cms/evaluators/UserOrigReqAccessEvaluator.java new file mode 100644 index 000000000..16b59b59b --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/evaluators/UserOrigReqAccessEvaluator.java @@ -0,0 +1,171 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2008 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.evaluators; + + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.evaluators.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.acls.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.cmsutil.util.*; + + +/** + * A class represents a user-origreq uid mapping acls evaluator. + * This is primarily used for renewal. During renewal, the orig_req + * uid is placed in the SessionContext of the renewal session context + * to be evaluated by this evaluator + * <P> + * + * @author Christina Fu + * @version $Revision: $, $Date: + */ +public class UserOrigReqAccessEvaluator implements IAccessEvaluator { + private String mType = "user_origreq"; + private String mDescription = "user origreq matching evaluator"; + private ILogger mLogger = CMS.getLogger(); + + private final static String ANYBODY = "anybody"; + private final static String EVERYBODY = "everybody"; + + /** + * Class constructor. + */ + public UserOrigReqAccessEvaluator() { + } + + /** + * initialization. nothing for now. + */ + public void init() { + CMS.debug("UserOrigReqAccessEvaluator: init"); + } + + /** + * gets the type name for this acl evaluator + * @return type for this acl evaluator: "user_origreq" or "at_user_origreq" + */ + public String getType() { + return mType; + } + + /** + * gets the description for this acl evaluator + * @return description for this acl evaluator + */ + public String getDescription() { + return mDescription; + } + + public String[] getSupportedOperators() { + String[] s = new String[2]; + + s[0] = "="; + s[1] = "!="; + return s; + } + + /** + * Evaluates the user in AuthToken to see if it's equal to value + * @param authToken AuthToken from authentication + * @param type must be "at_userreq" + * @param op must be "=" + * @param value the request param name + * @return true if AuthToken uid is same as value, false otherwise + */ + public boolean evaluate(IAuthToken authToken, String type, String op, String value) { + CMS.debug("UserOrigReqAccessEvaluator: evaluate() begins"); + if (type.equals(mType)) { + String s = Utils.stripQuotes(value); + + if ((s.equals(ANYBODY) || s.equals(EVERYBODY)) && op.equals("=")) + return true; + + // should define "uid" at a common place + String uid = null; + + uid = authToken.getInString("uid"); + + if (uid == null) { + CMS.debug("UserOrigReqAccessEvaluator: evaluate() uid in authtoken null"); + return false; + } else + CMS.debug("UserOrigReqAccessEvaluator: evaluate() uid in authtoken ="+ uid); + + // find value of param in request + SessionContext mSC = SessionContext.getContext(); + CMS.debug("UserOrigReqAccessEvaluator: evaluate() getting "+"orig_req."+s+ " in SessionContext"); + // "orig_req.auth_token.uid" + String orig_id = (String) mSC.get("orig_req."+s); + + if (orig_id == null) { + CMS.debug("UserOrigReqAccessEvaluator: evaluate() orig_id null"); + return false; + } + CMS.debug("UserOrigReqAccessEvaluator: evaluate() orig_id ="+ orig_id); + if (op.equals("=")) + return uid.equalsIgnoreCase(orig_id); + else if (op.equals("!=")) + return !(uid.equalsIgnoreCase(orig_id)); + } + + return false; + } + + /** + * Evaluates the user in session context to see if it's equal to value + * @param type must be "user_origreq" + * @param op must be "=" + * @param value the user id + * @return true if SessionContext uid is same as value, false otherwise + */ + public boolean evaluate(String type, String op, String value) { + + SessionContext mSC = SessionContext.getContext(); + + if (type.equals(mType)) { +// what do I do with s here? + String s = Utils.stripQuotes(value); + + if (s.equals(ANYBODY) && op.equals("=")) + return true; + + IUser id = (IUser) mSC.get(SessionContext.USER); + // "orig_req.auth_token.uid" + String orig_id = (String) mSC.get("orig_req"+s); + + if (op.equals("=")) + return id.getName().equalsIgnoreCase(orig_id); + else if (op.equals("!=")) + return !(id.getName().equalsIgnoreCase(orig_id)); + } + + return false; + } + private void log(int level, String msg) { + if (mLogger == null) + return; + mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_ACLS, + level, "UserOrigReqAccessEvaluator: " + msg); + } + +} diff --git a/pki/base/common/src/com/netscape/cms/profile/common/BasicProfile.java b/pki/base/common/src/com/netscape/cms/profile/common/BasicProfile.java index fb03725a0..d96bec0b9 100644 --- a/pki/base/common/src/com/netscape/cms/profile/common/BasicProfile.java +++ b/pki/base/common/src/com/netscape/cms/profile/common/BasicProfile.java @@ -40,6 +40,7 @@ public abstract class BasicProfile implements IProfile { public static final String PROP_ENABLE = "enable"; public static final String PROP_ENABLE_BY = "enableBy"; + public static final String PROP_IS_RENEWAL = "renewal"; public static final String PROP_VISIBLE = "visible"; public static final String PROP_INPUT_LIST = "list"; public static final String PROP_OUTPUT_LIST = "list"; @@ -86,6 +87,14 @@ public abstract class BasicProfile implements IProfile { } } + public String isRenewal() { + try { + return mConfig.getString(PROP_IS_RENEWAL, "false"); + } catch (EBaseException e) { + return "false"; + } + } + public String getApprovedBy() { try { return mConfig.getString(PROP_ENABLE_BY, ""); @@ -953,6 +962,7 @@ public abstract class BasicProfile implements IProfile { throws EProfileException { String setId = getPolicySetId(request); Vector policies = getPolicies(setId); + CMS.debug("BasicProfile: populate() policy setid ="+ setId); for (int i = 0; i < policies.size(); i++) { ProfilePolicy policy = (ProfilePolicy) @@ -968,8 +978,8 @@ public abstract class BasicProfile implements IProfile { */ public void validate(IRequest request) throws ERejectException { - CMS.debug("BasicProfile: validate start"); String setId = getPolicySetId(request); + CMS.debug("BasicProfile: validate start on setId="+ setId); Vector policies = getPolicies(setId); for (int i = 0; i < policies.size(); i++) { diff --git a/pki/base/common/src/com/netscape/cms/profile/common/EnrollProfile.java b/pki/base/common/src/com/netscape/cms/profile/common/EnrollProfile.java index 9a8183a5e..e889904a0 100644 --- a/pki/base/common/src/com/netscape/cms/profile/common/EnrollProfile.java +++ b/pki/base/common/src/com/netscape/cms/profile/common/EnrollProfile.java @@ -268,6 +268,7 @@ public abstract class EnrollProfile extends BasicProfile } if (token == null) { + CMS.debug("EnrollProfile: auth token is null"); CMS.debug("EnrollProfile: validating request"); validate(request); try { @@ -280,6 +281,7 @@ public abstract class EnrollProfile extends BasicProfile } else { // this profile executes request that is authenticated // by non NoAuth + CMS.debug("EnrollProfile: auth token is not null"); validate(request); execute(request); } diff --git a/pki/base/common/src/com/netscape/cms/profile/constraint/RenewGracePeriodConstraint.java b/pki/base/common/src/com/netscape/cms/profile/constraint/RenewGracePeriodConstraint.java new file mode 100644 index 000000000..29a5c232c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/profile/constraint/RenewGracePeriodConstraint.java @@ -0,0 +1,158 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.profile.constraint; + + +import java.util.*; +import java.io.*; +import java.math.BigInteger; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.apps.*; + +import com.netscape.cms.profile.def.*; +import netscape.security.x509.*; + + +/** + * This class supports renewal grace period, which has two + * parameters: graceBefore and graceAfter + * + * @author Christina Fu + * @version $Revision: $, $Date: $ + */ +public class RenewGracePeriodConstraint extends EnrollConstraint { + + // for renewal: # of days before the orig cert expiration date + public static final String CONFIG_RENEW_GRACE_BEFORE = "renewal.graceBefore"; + // for renewal: # of days after the orig cert expiration date + public static final String CONFIG_RENEW_GRACE_AFTER = "renewal.graceAfter"; + + public RenewGracePeriodConstraint() { + super(); + addConfigName(CONFIG_RENEW_GRACE_BEFORE); + addConfigName(CONFIG_RENEW_GRACE_AFTER); + } + + public void init(IProfile profile, IConfigStore config) + throws EProfileException { + super.init(profile, config); + } + + public void setConfig(String name, String value) + throws EPropertyException { + if ( name.equals(CONFIG_RENEW_GRACE_BEFORE) || + name.equals(CONFIG_RENEW_GRACE_AFTER)) { + try { + Integer.parseInt(value); + } catch (Exception e) { + throw new EPropertyException(CMS.getUserMessage( + "CMS_INVALID_PROPERTY", CONFIG_RENEW_GRACE_BEFORE +" or "+ CONFIG_RENEW_GRACE_AFTER)); + } + } + super.setConfig(name, value); + } + + public IDescriptor getConfigDescriptor(Locale locale, String name) { + if (name.equals(CONFIG_RENEW_GRACE_BEFORE)) { + return new Descriptor(IDescriptor.INTEGER, null, "30", + CMS.getUserMessage(locale, "CMS_PROFILE_RENEW_GRACE_BEFORE")); + } else if (name.equals(CONFIG_RENEW_GRACE_AFTER)) { + return new Descriptor(IDescriptor.INTEGER, null, "30", + CMS.getUserMessage(locale, "CMS_PROFILE_RENEW_GRACE_AFTER")); + } + return null; + } + + public void validate(IRequest req, X509CertInfo info) + throws ERejectException { + String origExpDate_s = req.getExtDataInString("origNotAfter"); + // probably not for renewal + if (origExpDate_s == null) { + return; + } else { + CMS.debug("validate RenewGracePeriod: original cert expiration date found... renewing"); + } + CMS.debug("ValidilityConstraint: validateRenewGraceperiod begins"); + BigInteger origExpDate_BI = new BigInteger(origExpDate_s); + Date origExpDate = new Date(origExpDate_BI.longValue()); + String renew_grace_before_s = getConfig(CONFIG_RENEW_GRACE_BEFORE); + String renew_grace_after_s = getConfig(CONFIG_RENEW_GRACE_AFTER); + int renew_grace_before = 0; + int renew_grace_after = 0; + // -1 means no limit + if (renew_grace_before_s == "") + renew_grace_before = -1; + else + renew_grace_before = Integer.parseInt(renew_grace_before_s); + + if (renew_grace_after_s == "") + renew_grace_after = -1; + else + renew_grace_after = Integer.parseInt(renew_grace_after_s); + + Date current = CMS.getCurrentDate(); + long millisDiff = origExpDate.getTime() - current.getTime(); + CMS.debug("validateRenewGracePeriod: millisDiff=" + millisDiff + " origExpDate=" + origExpDate.getTime() + " current=" + current.getTime()); + long long_days = (millisDiff / 1000 ) / 86400; + CMS.debug("validateRenewGracePeriod: long_days: "+long_days); + int days = (int)long_days; + CMS.debug("validateRenewGracePeriod: days: "+days); + + /* + * "days", if positive, has to be less than renew_grace_before + * "days", if negative, means already past expiration date, + * (abs value) has to be less than renew_grace_after + * if renew_grace_before or renew_grace_after are negative + * the one with negative value is ignored + */ + if (days >= 0) { + if ((renew_grace_before>0) && (days > renew_grace_before)) { + throw new ERejectException(CMS.getUserMessage(getLocale(req), + "CMS_PROFILE_RENEW_OUTSIDE_GRACE_PERIOD", + renew_grace_before+" days before and "+ + renew_grace_after+" days after original cert expiration date")); + } + } else { + if ((renew_grace_after > 0) && ((0-days) > renew_grace_after)) { + throw new ERejectException(CMS.getUserMessage(getLocale(req), + "CMS_PROFILE_RENEW_OUTSIDE_GRACE_PERIOD", + renew_grace_before+" days before and "+ + renew_grace_after+" days after original cert expiration date")); + } + } + } + + + public String getText(Locale locale) { + String renew_grace_before_s = getConfig(CONFIG_RENEW_GRACE_BEFORE); + String renew_grace_after_s= getConfig(CONFIG_RENEW_GRACE_AFTER); + return CMS.getUserMessage(locale, "CMS_PROFILE_CONSTRAINT_VALIDITY_TEXT", + renew_grace_before_s+" days before and "+ + renew_grace_after_s+" days after original cert expiration date"); + } + + public boolean isApplicable(IPolicyDefault def) { + if (def instanceof NoDefault) + return true; + return false; + } +} diff --git a/pki/base/common/src/com/netscape/cms/profile/constraint/SubjectNameConstraint.java b/pki/base/common/src/com/netscape/cms/profile/constraint/SubjectNameConstraint.java index d15710481..a37687021 100644 --- a/pki/base/common/src/com/netscape/cms/profile/constraint/SubjectNameConstraint.java +++ b/pki/base/common/src/com/netscape/cms/profile/constraint/SubjectNameConstraint.java @@ -77,6 +77,8 @@ public class SubjectNameConstraint extends EnrollConstraint { try { sn = (CertificateSubjectName) info.get(X509CertInfo.SUBJECT); + CMS.debug("SubjectNameConstraint: validate cert subject ="+ + sn.toString()); } catch (Exception e) { throw new ERejectException( CMS.getUserMessage(getLocale(request), @@ -92,11 +94,17 @@ public class SubjectNameConstraint extends EnrollConstraint { "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND")); } if (sn500 == null) { + CMS.debug("SubjectNameConstraint: validate() - sn500 is null"); throw new ERejectException( CMS.getUserMessage(getLocale(request), "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND")); + } else { + CMS.debug("SubjectNameConstraint: validate() - sn500 "+ + CertificateSubjectName.DN_NAME + " = "+ + sn500.toString()); } if (!sn500.toString().matches(getConfig(CONFIG_PATTERN))) { + CMS.debug("SubjectNameConstraint: validate() - sn500 not matching pattern "+ getConfig(CONFIG_PATTERN)); throw new ERejectException( CMS.getUserMessage(getLocale(request), "CMS_PROFILE_SUBJECT_NAME_NOT_MATCHED", diff --git a/pki/base/common/src/com/netscape/cms/profile/def/AuthTokenSubjectNameDefault.java b/pki/base/common/src/com/netscape/cms/profile/def/AuthTokenSubjectNameDefault.java index 35a7507d3..4d15a0db0 100644 --- a/pki/base/common/src/com/netscape/cms/profile/def/AuthTokenSubjectNameDefault.java +++ b/pki/base/common/src/com/netscape/cms/profile/def/AuthTokenSubjectNameDefault.java @@ -63,6 +63,7 @@ public class AuthTokenSubjectNameDefault extends EnrollDefault { public void setValue(String name, Locale locale, X509CertInfo info, String value) throws EPropertyException { + CMS.debug("AuthTokenSubjectNameDefault: begins"); if (name == null) { throw new EPropertyException(CMS.getUserMessage(locale, "CMS_INVALID_PROPERTY", name)); @@ -72,11 +73,17 @@ public class AuthTokenSubjectNameDefault extends EnrollDefault { try { x500name = new X500Name(value); + if (x500name != null) { + CMS.debug("AuthTokenSubjectNameDefault: setValue x500name=" + x500name.toString()); + } else { + CMS.debug("AuthTokenSubjectNameDefault: setValue x500name=null"); + } } catch (IOException e) { CMS.debug("AuthTokenSubjectNameDefault: setValue " + e.toString()); // failed to build x500 name } + CMS.debug("AuthTokenSubjectNameDefault: setValue name=" + x500name.toString()); try { info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(x500name)); @@ -133,6 +140,7 @@ public class AuthTokenSubjectNameDefault extends EnrollDefault { X500Name name = new X500Name( request.getExtDataInString(IProfileAuthenticator.AUTHENTICATED_NAME)); + CMS.debug("AuthTokenSubjectNameDefault: X500Name=" + name.toString()); info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(name)); } catch (Exception e) { // failed to insert subject name diff --git a/pki/base/common/src/com/netscape/cms/profile/def/SubjectNameDefault.java b/pki/base/common/src/com/netscape/cms/profile/def/SubjectNameDefault.java index 2c3123fb1..c78509931 100644 --- a/pki/base/common/src/com/netscape/cms/profile/def/SubjectNameDefault.java +++ b/pki/base/common/src/com/netscape/cms/profile/def/SubjectNameDefault.java @@ -86,11 +86,14 @@ public class SubjectNameDefault extends EnrollDefault { try { x500name = new X500Name(value); + if (x500name != null) { + CMS.debug("SubjectNameDefault: setValue x500name=" + x500name.toString()); + } } catch (IOException e) { CMS.debug("SubjectNameDefault: setValue " + e.toString()); // failed to build x500 name } - CMS.debug("SubjectNameDefault: setValue name=" + x500name); + CMS.debug("SubjectNameDefault: setValue name=" + x500name.toString()); try { info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(x500name)); diff --git a/pki/base/common/src/com/netscape/cms/profile/input/SerialNumRenewInput.java b/pki/base/common/src/com/netscape/cms/profile/input/SerialNumRenewInput.java new file mode 100644 index 000000000..2eeaac114 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/profile/input/SerialNumRenewInput.java @@ -0,0 +1,94 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.profile.input; + + +import java.security.cert.*; +import java.io.*; +import java.util.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.apps.*; + +import netscape.security.x509.*; +import netscape.security.util.*; +import netscape.security.pkcs.*; + +import com.netscape.cms.profile.common.*; + + +/** + * This class implements the serial number input + * for renewal + * <p> + * + * @author Christina Fu + */ +public class SerialNumRenewInput extends EnrollInput implements IProfileInput { + + public static final String SERIAL_NUM = "serial_num"; + + public SerialNumRenewInput() { + addValueName(SERIAL_NUM); + } + + /** + * Initializes this default policy. + */ + public void init(IProfile profile, IConfigStore config) + throws EProfileException { + super.init(profile, config); + } + + /** + * Retrieves the localizable name of this policy. + */ + public String getName(Locale locale) { + return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SERIAL_NUM_NAME"); + } + + /** + * Retrieves the localizable description of this policy. + */ + public String getText(Locale locale) { + return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SERIAL_NUM_TEXT"); + } + + /** + * Populates the request with this policy default. + */ + public void populate(IProfileContext ctx, IRequest request) + throws EProfileException { + // + } + + /** + * Retrieves the descriptor of the given value + * parameter by name. + */ + public IDescriptor getValueDescriptor(Locale locale, String name) { + if (name.equals(SERIAL_NUM)) { + return new Descriptor(IDescriptor.STRING, null, + null, + CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SERIAL_NUM_NAME")); + } + return null; + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java index 83904279c..dd1860ee4 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java @@ -333,6 +333,7 @@ public class ProfileSelectServlet extends ProfileServlet { } args.set(ARG_INPUT_LIST, inputlist); args.set(ARG_INPUT_PLUGIN_LIST, inputPluginlist); + args.set(ARG_IS_RENEWAL, profile.isRenewal()); // (5) return info as template outputTemplate(request, response, args); diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java index 0aa6155a6..9ce0d55bc 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java @@ -75,6 +75,7 @@ public class ProfileServlet extends CMSServlet { public final static String ARG_PROFILE = "profile"; public final static String ARG_REQUEST_NOTES = "requestNotes"; public final static String ARG_PROFILE_ID = "profileId"; + public final static String ARG_RENEWAL_PROFILE_ID = "rprofileId"; public final static String ARG_PROFILE_IS_ENABLED = "profileIsEnable"; public final static String ARG_PROFILE_IS_VISIBLE = "profileIsVisible"; public final static String ARG_PROFILE_ENABLED_BY = "profileEnableBy"; @@ -106,6 +107,7 @@ public class ProfileServlet extends CMSServlet { public final static String ARG_INPUT_CONSTRAINT = "inputConstraint"; public final static String ARG_INPUT_NAME = "inputName"; public final static String ARG_INPUT_VAL = "inputVal"; + public final static String ARG_IS_RENEWAL = "renewal"; public final static String ARG_OUTPUT_LIST = "outputList"; public final static String ARG_OUTPUT_ID = "outputId"; public final static String ARG_OUTPUT_SYNTAX = "outputSyntax"; diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java index 79c63be92..3e270a036 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java @@ -19,12 +19,15 @@ package com.netscape.cms.servlet.profile; import java.util.*; +import java.math.BigInteger; import java.security.cert.*; import javax.servlet.*; import javax.servlet.http.*; import com.netscape.certsrv.apps.*; import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; import com.netscape.certsrv.util.*; import com.netscape.certsrv.template.*; import com.netscape.certsrv.property.*; @@ -32,6 +35,7 @@ import com.netscape.certsrv.profile.*; import com.netscape.certsrv.request.*; import com.netscape.certsrv.authentication.*; import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.authority.*; import com.netscape.certsrv.logging.*; import com.netscape.cms.servlet.common.*; import com.netscape.cms.servlet.common.AuthCredentials; @@ -44,6 +48,7 @@ import netscape.security.x509.*; /** * This servlet submits end-user request into the profile framework. * + * @author Christina Fu (renewal support) * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ */ public class ProfileSubmitServlet extends ProfileServlet { @@ -112,18 +117,149 @@ public class ProfileSubmitServlet extends ProfileServlet { } + /* + * fill input info from "request" to context. + * This is expected to be used by renewal where the request + * is retrieved from request record + */ + private void setInputsIntoContext(IRequest request, IProfile profile, IProfileContext ctx, Locale locale) { + // passing inputs into context + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + String inputValue = ""; + CMS.debug("ProfileSubmitServlet: setInputsIntoContext() getting input name= " + inputName); + try { + inputValue = profileInput.getValue(inputName, locale, request); + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet: setInputsIntoContext() getvalue() failed: " + e.toString()); + } + + if (inputValue != null) { + CMS.debug("ProfileSubmitServlet: setInputsIntoContext() setting value in ctx:"+ inputValue); + ctx.set(inputName, inputValue); + } else { + CMS.debug("ProfileSubmitServlet: setInputsIntoContext() value null"); + } + } + } + } + + } + + + private void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator, IProfileContext ctx) { Enumeration authIds = authenticator.getValueNames(); if (authIds != null) { + CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authNames not null"); while (authIds.hasMoreElements()) { String authName = (String) authIds.nextElement(); + CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authName:"+ + authName); if (request.getParameter(authName) != null) { + CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authName found in request"); ctx.set(authName, request.getParameter(authName)); + } else { + CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authName not found in request"); } } + } else { + CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authIds` null"); + } + } + + String getUidFromDN(String userdn) { + StringTokenizer st = new StringTokenizer(userdn, ","); + while (st.hasMoreTokens()) { + String t = st.nextToken(); + int i = t.indexOf("="); + + if (i == -1) { + continue; + } + String n = t.substring(0, i); + if (n.equalsIgnoreCase("uid")) { + String v = t.substring(i + 1); + CMS.debug("ProfileSubmitServlet:: getUidFromDN(): uid found:"+v); + return v; + } else { + continue; + } } + return null; + } + + /* + * authenticate for renewal - more to add necessary params/values + * to the session context + */ + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request, IRequest origReq, SessionContext context) + throws EBaseException { + IAuthToken authToken = authenticate(authenticator, request); + // For renewal, fill in necessary params + if (authToken!= null) { + String ouid = origReq.getExtDataInString("auth_token.uid"); + // if the orig cert was manually approved, then there was + // no auth token uid. Try to get the uid from the cert dn + // itself, if possible + if (ouid == null) { + String sdn = (String) context.get("origSubjectDN"); + if (sdn != null) { + ouid = getUidFromDN(sdn); + if (ouid != null) + CMS.debug("ProfileSubmitServlet: renewal: authToken original uid not found"); + } + } else { + CMS.debug("ProfileSubmitServlet: renewal: authToken original uid found in orig request auth_token"); + } + String auid = authToken.getInString("uid"); + if (auid != null) { // not through ssl client auth + CMS.debug("ProfileSubmitServlet: renewal: authToken uid found:"+auid); + // authenticated with uid + // put "orig_req.auth_token.uid" so that authz with + // UserOrigReqAccessEvaluator will work + if (ouid != null) { + context.put("orig_req.auth_token.uid", ouid); + CMS.debug("ProfileSubmitServlet: renewal: authToken original uid found:"+ouid); + } else { + CMS.debug("ProfileSubmitServlet: renewal: authToken original uid not found"); + } + } else { // through ssl client auth? + CMS.debug("ProfileSubmitServlet: renewal: authToken uid not found:"); + // put in orig_req's uid + if (ouid != null) { + CMS.debug("ProfileSubmitServlet: renewal: origReq uid not null:" +ouid+". Setting authtoken"); + authToken.set("uid", ouid); + context.put(SessionContext.USER_ID, ouid); + } else { + CMS.debug("ProfileSubmitServlet: renewal: origReq uid not found"); +// throw new EBaseException("origReq uid not found"); + } + } + + String userdn = origReq.getExtDataInString("auth_token.userdn"); + if (userdn != null) { + CMS.debug("ProfileSubmitServlet: renewal: origReq userdn not null:"+userdn+". Setting authtoken"); + authToken.set("userdn", userdn); + } else { + CMS.debug("ProfileSubmitServlet: renewal: origReq userdn not found"); +// throw new EBaseException("origReq userdn not found"); + } + } else { + CMS.debug("ProfileSubmitServlet: renewal: authToken null"); + } + return authToken; } public IAuthToken authenticate(IProfileAuthenticator authenticator, @@ -178,6 +314,44 @@ public class ProfileSubmitServlet extends ProfileServlet { } } + /* + * fill input info from orig request to the renew request. + * This is expected to be used by renewal where the request + * is retrieved from request record + */ + private void setInputsIntoRequest(IRequest request, IProfile profile, IRequest req, Locale locale) { + // passing inputs into request + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + String inputValue = ""; + CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() getting input name= " + inputName); + try { + inputValue = profileInput.getValue(inputName, locale, request); + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() getvalue() failed: " + e.toString()); + } + + if (inputValue != null) { + CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() setting value in ctx:"+ inputValue); + req.setExtData(inputName, inputValue); + } else { + CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() value null"); + } + } + } + } + + } + + private void setOutputIntoArgs(IProfile profile, ArgList outputlist, Locale locale, IRequest req) { Enumeration outputIds = profile.getProfileOutputIds(); @@ -255,6 +429,8 @@ public class ProfileSubmitServlet extends ProfileServlet { Locale locale = getLocale(request); ArgSet args = new ArgSet(); +//xxx this ought to be removed. pwds are logged +/* if (CMS.debugOn()) { CMS.debug("Start of Input Parameters"); Enumeration paramNames = request.getParameterNames(); @@ -267,6 +443,7 @@ public class ProfileSubmitServlet extends ProfileServlet { } CMS.debug("End of Input Parameters"); } +*/ CMS.debug("ProfileSubmitServlet: start serving"); @@ -294,6 +471,31 @@ public class ProfileSubmitServlet extends ProfileServlet { return; } + /* + * Renewal - Renewal is retrofitted into the Profile Enrollment + * Framework. The authentication and authorization are taken from + * the renewal profile, while the input (with requests) and grace + * period constraint are taken from the original cert's request record. + * + * Things to note: + * * the renew request will contain the original profile instead + * of the new + * * there is no request for system and admin certs generated at + * time of installation configuration. + */ + String renewal = request.getParameter("renewal"); + boolean isRenewal = false; + if ((renewal!= null) && (renewal.equalsIgnoreCase("true"))) { + CMS.debug("ProfileSubmitServlet: isRenewal true"); + isRenewal = true; + request.setAttribute("reqType", (Object)"renewal"); + } else { + CMS.debug("ProfileSubmitServlet: isRenewal false"); + } + + String renewProfileId = null; + IRequest origReq = null; + // if we did not configure profileId in xml file, // then accept the user-provided one String profileId = null; @@ -304,14 +506,258 @@ public class ProfileSubmitServlet extends ProfileServlet { profileId = mProfileId; } + CMS.debug("ProfileSubmitServlet: profileId " + profileId); + // This is the expiration date of the orig. cert that will + // be used in the RenewGracePeriodConstraint + Date origNotAfter = null; + String origSubjectDN = null; + + if (isRenewal) { + // dig up the original request to "clone" + renewProfileId = profileId; + CMS.debug("ProfileSubmitServlet: renewProfileId ="+renewProfileId); + IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId); + if (authority == null) { + CMS.debug("ProfileSubmitServlet: renewal: Authority " + mAuthorityId + + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + IRequestQueue queue = authority.getRequestQueue(); + + if (queue == null) { + CMS.debug("ProfileSubmitServlet: renewal: Request Queue of " + + mAuthorityId + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + + String serial = request.getParameter("serial_num"); + BigInteger certSerial = null; + // if serial number is sent with request, then the authentication + // method is not ssl client auth. In this case, an alternative + // authentication method is used (default: ldap based) + if (serial != null) { + CMS.debug("ProfileSubmitServlet: renewal: found serial_num"); + certSerial = new BigInteger(serial); + // usr_origreq evaluator should be used to authorize ownership + // of the cert + } else { + CMS.debug("ProfileSubmitServlet: renewal: serial_num not found, must do ssl client auth"); + // ssl client auth is to be used + // this is not authentication. Just use the cert to search + // for orig request and find the right profile + SSLClientCertProvider sslCCP = new SSLClientCertProvider(request); + X509Certificate[] certs = sslCCP.getClientCertificateChain(); + certSerial = null; + if (certs == null || certs.length == 0) { + CMS.debug("ProfileSubmitServlet: renewal: no ssl client cert chain"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } else { // has ssl client cert + CMS.debug("ProfileSubmitServlet: renewal: has ssl client cert chain"); + // shouldn't expect leaf cert to be always at the + // same location + X509Certificate clientCert = null; + for (int i = 0; i< certs.length; i++) { + clientCert = certs[i]; + byte [] extBytes = clientCert.getExtensionValue("2.5.29.19"); + // try to see if this is a leaf cert + // look for BasicConstraint extension + if (extBytes == null) { + // found leaf cert + CMS.debug("ProfileSubmitServlet: renewal: found leaf cert"); + break; + } else { + CMS.debug("ProfileSubmitServlet: renewal: found cert having BasicConstraints ext"); + // it's got BasicConstraints extension + // so it's not likely to be a leaf cert, + // however, check the isCA field regardless + try { + BasicConstraintsExtension bce = + new BasicConstraintsExtension(true, extBytes); + if (bce != null) { + if (!(Boolean)bce.get("is_ca")) { + CMS.debug("ProfileSubmitServlet: renewal: found CA cert in chain"); + break; + } // else found a ca cert, continue + } + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet: renewal: exception:"+ + e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + } + } + if (clientCert == null) { + CMS.debug("ProfileSubmitServlet: renewal: no client cert in chain"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + // convert to java X509 cert interface + try { + byte[] certEncoded = clientCert.getEncoded(); + + clientCert = new X509CertImpl(certEncoded); + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet: renewal: exception:"+e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + + certSerial = clientCert.getSerialNumber(); + } + } + + CMS.debug("ProfileSubmitServlet: renewal: serial number of cert to renew:"+ certSerial.toString()); + + try { + ICertificateRepository certDB = null; + if (authority instanceof ICertificateAuthority) { + certDB = ((ICertificateAuthority) authority).getCertificateRepository(); + } + if (certDB == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + ICertRecord rec = (ICertRecord) certDB.readCertificateRecord(certSerial); + if (rec == null) { + CMS.debug("ProfileSubmitServlet: renewal cert record not found for serial number "+ certSerial.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } else { + CMS.debug("ProfileSubmitServlet: renewal cert record found for serial number:"+ certSerial.toString()); + // check to see if the cert is revoked + if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) { + CMS.debug("ProfileSubmitServlet: renewal cert found to be revoked. Serial number = "+ certSerial.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_CA_CANNOT_RENEW_REVOKED_CERT", certSerial.toString())); + outputTemplate(request, response, args); + return; + } + MetaInfo metaInfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO); + // note: CA's internal certs don't have request ids + // so some other way needs to be done + if (metaInfo != null) { + String rid = (String) metaInfo.get(ICertRecord.META_REQUEST_ID); + + if (rid != null) { + origReq = queue.findRequest(new RequestId(rid)); + if (origReq != null) { + CMS.debug("ProfileSubmitServlet: renewal: found original enrollment request id:"+ rid); + // debug: print the extData keys + Enumeration en = origReq.getExtDataKeys(); +/* + CMS.debug("ProfileSubmitServlet: renewal: origRequest extdata key print BEGINS"); + while (en.hasMoreElements()) { + String next = (String) en.nextElement(); + CMS.debug("ProfileSubmitServlet: renewal: origRequest extdata key:"+ next); + } + CMS.debug("ProfileSubmitServlet: renewal: origRequest extdata key print ENDS"); +*/ + String requestorE = origReq.getExtDataInString("requestor_email"); + CMS.debug("ProfileSubmitServlet: renewal original requestor email="+requestorE); + profileId = origReq.getExtDataInString("profileId"); + if (profileId != null) + CMS.debug("ProfileSubmitServlet: renewal original profileId="+profileId); + else { + CMS.debug("ProfileSubmitServlet: renewal original profileId not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + } else { //if origReq + CMS.debug("ProfileSubmitServlet: renewal original request not found for request id "+ rid); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + } else { + CMS.debug("ProfileSubmitServlet: renewal: cert record locating request id in MetaInfo failed for serial number "+ certSerial.toString()); + CMS.debug("ProfileSubmitServlet: renewal: cert may be bootstrapped system cert during installation/configuration - no request record exists"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR"+": original request not found")); + outputTemplate(request, response, args); + return; + } + } else { + CMS.debug("ProfileSubmitServlet: renewal: cert record locating MetaInfo failed for serial number "+ certSerial.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + // get orig cert expiration date + CMS.debug("ProfileSubmitServlet: renewal: before getting origNotAfter"); + X509CertImpl origCert = rec.getCertificate(); + origNotAfter = origCert.getNotAfter(); + CMS.debug("ProfileSubmitServlet: renewal: origNotAfter ="+ + origNotAfter.toString()); + origSubjectDN = origCert.getSubjectDN().getName(); + CMS.debug("ProfileSubmitServlet: renewal: orig subj dn ="+ + origSubjectDN); + } + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet: renewal: exception:"+e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + } // end isRenewal + IProfile profile = null; + IProfile renewProfile = null; try { - CMS.debug("ProfileSubmitServlet: profileId " + profileId); profile = ps.getProfile(profileId); + if (isRenewal) { + // in case of renew, "profile" is the orig profile + // while "renewProfile" is the current profile used for renewal + renewProfile = ps.getProfile(renewProfileId); + } } catch (EProfileException e) { - CMS.debug("ProfileSubmitServlet: profile not found profileId " + - profileId + " " + e.toString()); + if(profile == null) { + CMS.debug("ProfileSubmitServlet: profile not found profileId " + + profileId + " " + e.toString()); + } + if (renewProfile == null) { + CMS.debug("ProfileSubmitServlet: profile not found renewProfileId " + + renewProfileId + " " + e.toString()); + } } if (profile == null) { if (xmlOutput) { @@ -324,6 +770,17 @@ public class ProfileSubmitServlet extends ProfileServlet { } return; } + if (isRenewal && (renewProfile == null)) { + if (xmlOutput) { + outputError(response, CMS.getUserMessage(locale,"CMS_PROFILE_NOT_FOUND", renewProfileId)); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", renewProfileId)); + outputTemplate(request, response, args); + } + return; + } if (!ps.isProfileEnable(profileId)) { CMS.debug("ProfileSubmitServlet: Profile " + profileId + @@ -342,14 +799,42 @@ public class ProfileSubmitServlet extends ProfileServlet { return; } + if (isRenewal) { + if (!ps.isProfileEnable(renewProfileId)) { + CMS.debug("ProfileSubmitServlet: renewal Profile " + renewProfileId + + " not enabled"); + if (xmlOutput) { + outputError(response, CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", renewProfileId)); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", renewProfileId)); + outputTemplate(request, response, args); + } + return; + } + } + IProfileContext ctx = profile.createContext(); // passing auths into context IProfileAuthenticator authenticator = null; + IProfileAuthenticator origAuthenticator = null; try { - authenticator = profile.getAuthenticator(); + if (isRenewal) { + authenticator = renewProfile.getAuthenticator(); + origAuthenticator = profile.getAuthenticator(); + } else { + authenticator = profile.getAuthenticator(); + } } catch (EProfileException e) { // authenticator not installed correctly + CMS.debug("ProfileSubmitServlet: renewal: exception:"+e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; } if (authenticator == null) { CMS.debug("ProfileSubmitServlet: authenticator not found"); @@ -359,8 +844,27 @@ public class ProfileSubmitServlet extends ProfileServlet { setCredentialsIntoContext(request, authenticator, ctx); } - setInputsIntoContext(request, profile, ctx); - CMS.debug("ProfileSubmistServlet: set Inputs into Context"); + // for renewal, this will override or add auth info to the profile context + if (isRenewal) { + if (origAuthenticator!= null) { + CMS.debug("ProfileSubmitServlet: for renewal, original authenticator " + + origAuthenticator.getName() + " found"); + setCredentialsIntoContext(request, origAuthenticator, ctx); + } else { + CMS.debug("ProfileSubmitServlet: for renewal, original authenticator not found"); + } + } + + CMS.debug("ProfileSubmistServlet: set Inputs into profile Context"); + if (isRenewal) { + // for renewal, input needs to be retrieved from the orig req record + CMS.debug("ProfileSubmitServlet: set original Inputs into profile Context"); + setInputsIntoContext(origReq, profile, ctx, locale); + ctx.set("renewal", "true"); + ctx.set("renewProfileId", renewProfileId); + } else { + setInputsIntoContext(request, profile, ctx); + } // before creating the request, authenticate the request @@ -375,13 +879,20 @@ public class ProfileSubmitServlet extends ProfileServlet { context.put("sslClientCertProvider", new SSLClientCertProvider(request)); CMS.debug("ProfileSubmitServlet: set sslClientCertProvider"); + if ((isRenewal == true) && (origSubjectDN != null)) + context.put("origSubjectDN", origSubjectDN); if (statsSub != null) { statsSub.startTiming("profile_authentication"); } if (authenticator != null) { try { - authToken = authenticate(authenticator, request); - // authentication success + if (isRenewal) { + CMS.debug("ProfileSubmitServlet: renewal authenticate begins"); + authToken = authenticate(authenticator, request, origReq, context); + CMS.debug("ProfileSubmitServlet: renewal authenticate ends"); + } else { + authToken = authenticate(authenticator, request); + } } catch (EBaseException e) { CMS.debug("ProfileSubmitServlet: authentication error " + e.toString()); @@ -407,9 +918,16 @@ public class ProfileSubmitServlet extends ProfileServlet { statsSub.endTiming("profile_authentication"); } + // authentication success if (authToken != null) { + CMS.debug("ProfileSubmitServlet authToken not null"); // do profile authorization - String acl = profile.getAuthzAcl(); + String acl = null; + if (isRenewal) + acl = renewProfile.getAuthzAcl(); + else + acl = profile.getAuthzAcl(); + CMS.debug("ProfileSubmitServlet: authz using acl: "+acl); if (acl != null && acl.length() > 0) { try { AuthzToken authzToken = authorize(mAclMethod, authToken, acl); @@ -482,9 +1000,19 @@ public class ProfileSubmitServlet extends ProfileServlet { for (int k = 0; k < reqs.length; k++) { boolean fromRA = false; String uid = ""; - + // adding parameters to request - setInputsIntoRequest(request, profile, reqs[k]); + if (isRenewal) { + setInputsIntoRequest(origReq, profile, reqs[k], locale); + // set orig expiration date to be used in Validity constraint + reqs[k].setExtData("origNotAfter", + BigInteger.valueOf(origNotAfter.getTime())); + // set subjectDN to be used in subject name default + reqs[k].setExtData(IProfileAuthenticator.AUTHENTICATED_NAME, origSubjectDN); + // set request type + reqs[k].setExtData("requestType", "renewal"); + } else + setInputsIntoRequest(request, profile, reqs[k]); // serial auth token into request if (authToken != null) { @@ -522,6 +1050,8 @@ public class ProfileSubmitServlet extends ProfileServlet { // put profile framework parameters into the request reqs[k].setExtData(ARG_PROFILE, "true"); reqs[k].setExtData(ARG_PROFILE_ID, profileId); + if (isRenewal) + reqs[k].setExtData(ARG_RENEWAL_PROFILE_ID, request.getParameter("profileId")); reqs[k].setExtData(ARG_PROFILE_APPROVED_BY, profile.getApprovedBy()); String setId = profile.getPolicySetId(reqs[k]); diff --git a/pki/linux/ca-ui/pki-ca-ui.spec b/pki/linux/ca-ui/pki-ca-ui.spec index 19ab74249..1daee1fc2 100644 --- a/pki/linux/ca-ui/pki-ca-ui.spec +++ b/pki/linux/ca-ui/pki-ca-ui.spec @@ -34,7 +34,7 @@ ## Package Header Definitions %define base_name %{base_prefix}-%{base_component} %define base_version 1.0.0 -%define base_release 4 +%define base_release 5 %define base_group System Environment/Base %define base_vendor Red Hat, Inc. %define base_license GPLv2 with exceptions @@ -221,6 +221,8 @@ rm -rf ${RPM_BUILD_ROOT} ############################################################################### %changelog +* Tue Nov 18 2008 Christina Fu <cfu@redhat.com> 1.0.0-5 +- Bugzilla Bug #471622 - Need Renewal feature via enrollment profile Framework (phase 1) * Wed Oct 15 2008 Andrew Wnuk <awnuk@redhat.com> 1.0.0-4 - Fix for Bug 466064: Search filters built by CA servlets are not always correct * Wed Oct 8 2008 Jack Magne <jmagne@redhat.com> 1.0.0-3 diff --git a/pki/linux/ca-ui/shared/webapps/ca/ee/ca/ProfileSelect.template b/pki/linux/ca-ui/shared/webapps/ca/ee/ca/ProfileSelect.template index 95a978e91..a3557fcd6 100644 --- a/pki/linux/ca-ui/shared/webapps/ca/ee/ca/ProfileSelect.template +++ b/pki/linux/ca-ui/shared/webapps/ca/ee/ca/ProfileSelect.template @@ -439,6 +439,8 @@ document.writeln('</table>'); document.writeln('<p>'); document.writeln('<input type=hidden name=profileId value="' + profileId + '">'); +document.writeln('<input type=hidden name=renewal value="' + + renewal + '">'); } else { document.write('Sorry, your request is not submitted. The error code is "' + errorReason + '".'); } diff --git a/pki/linux/ca/pki-ca.spec b/pki/linux/ca/pki-ca.spec index b6349228c..2f1149751 100644 --- a/pki/linux/ca/pki-ca.spec +++ b/pki/linux/ca/pki-ca.spec @@ -34,7 +34,7 @@ ## Package Header Definitions %define base_name %{base_prefix}-%{base_component} %define base_version 1.0.0 -%define base_release 13 +%define base_release 14 %define base_group System Environment/Daemons %define base_vendor Red Hat, Inc. %define base_license GPLv2 with exceptions @@ -282,6 +282,8 @@ fi ############################################################################### %changelog +* Tue Nov 18 2008 Christina Fu <cfu@redhat.com> 1.0.0-14 +- Bugzilla Bug #471622 - Need Renewal feature via enrollment profile Framework (phase 1) * Fri Oct 10 2008 Jack Magne <jmagne@redhat.com> 1.0.0-13 - Fix for port separation bug #466188. * Fri Oct 9 2008 Ade Lee <alee@redhat.com> 1.0.0-12 diff --git a/pki/linux/common/pki-common.spec b/pki/linux/common/pki-common.spec index 016fe171d..cdb2afd7b 100644 --- a/pki/linux/common/pki-common.spec +++ b/pki/linux/common/pki-common.spec @@ -33,7 +33,7 @@ ## Package Header Definitions %define base_name %{base_prefix}-%{base_component} %define base_version 1.0.0 -%define base_release 25 +%define base_release 26 %define base_group System Environment/Base %define base_vendor Red Hat, Inc. %define base_license GPLv2 with exceptions @@ -298,6 +298,8 @@ chmod 00755 %{_datadir}/%{base_prefix}/setup/postinstall ############################################################################### %changelog +* Tue Nov 18 2008 Christina Fu <cfu@redhat.com> 1.0.0-26 +- Bugzilla Bug #471622 - Need Renewal feature via enrollment profile Framework (Phase 1) * Mon Oct 27 2008 Ade Lee <alee@redhat.com> 1.0.0-25 - Fix for Bugs: 223324, 430745, 224765, 223309 * Fri Oct 17 2008 Andrew Wnuk <awnuk@redhat.com> 1.0.0-24 |