use of org.xipki.ca.api.mgmt.RequestorInfo.CmpRequestorInfo in project xipki by xipki.
the class BaseCmpResponder method processPkiMessage0.
// method getX500Sender
/**
* Processes the request and returns the response.
* @param request
* Original request. Will only be used for the storage. Could be{@code null}.
* @param requestor
* Requestor. Must not be {@code null}.
* @param tid
* Transaction id. Must not be {@code null}.
* @param message
* PKI message. Must not be {@code null}.
* @param msgId
* Message id. Must not be {@code null}.
* @param parameters
* Additional parameters.
* @param event
* Audit event. Must not be {@code null}.
* @return the response
*/
private PKIMessage processPkiMessage0(PKIMessage request, RequestorInfo requestor, ASN1OctetString tid, GeneralPKIMessage message, String msgId, Map<String, String> parameters, AuditEvent event) {
if (!(requestor instanceof CmpRequestorInfo)) {
throw new IllegalArgumentException("unknown requestor type " + requestor.getClass().getName());
}
CmpRequestorInfo cmpRequestor = (CmpRequestorInfo) requestor;
event.addEventData(NAME_requestor, cmpRequestor.getIdent().getName());
PKIHeader reqHeader = message.getHeader();
PKIHeaderBuilder respHeader = new PKIHeaderBuilder(reqHeader.getPvno().getValue().intValue(), getSender(), reqHeader.getSender());
respHeader.setTransactionID(tid);
ASN1OctetString senderNonce = reqHeader.getSenderNonce();
if (senderNonce != null) {
respHeader.setRecipNonce(senderNonce);
}
PKIBody respBody;
PKIBody reqBody = message.getBody();
final int type = reqBody.getType();
CmpControl cmpControl = getCmpControl();
try {
if (type == PKIBody.TYPE_INIT_REQ || type == PKIBody.TYPE_CERT_REQ || type == PKIBody.TYPE_KEY_UPDATE_REQ || type == PKIBody.TYPE_P10_CERT_REQ || type == PKIBody.TYPE_CROSS_CERT_REQ) {
String eventType;
if (PKIBody.TYPE_CERT_REQ == type) {
eventType = Cmp.TYPE_cr;
} else if (PKIBody.TYPE_INIT_REQ == type) {
eventType = Cmp.TYPE_ir;
} else if (PKIBody.TYPE_KEY_UPDATE_REQ == type) {
eventType = Cmp.TYPE_kur;
} else if (PKIBody.TYPE_P10_CERT_REQ == type) {
eventType = Cmp.TYPE_p10cr;
} else {
// if (PKIBody.TYPE_CROSS_CERT_REQ == type) {
eventType = Cmp.TYPE_ccr;
}
event.addEventType(eventType);
String dfltCertprofileName = null;
if (parameters != null) {
dfltCertprofileName = parameters.get("certprofile");
}
respBody = cmpEnrollCert(dfltCertprofileName, request, respHeader, cmpControl, reqHeader, reqBody, cmpRequestor, tid, msgId, event);
} else if (type == PKIBody.TYPE_CERT_CONFIRM) {
event.addEventType(Cmp.TYPE_certConf);
CertConfirmContent certConf = (CertConfirmContent) reqBody.getContent();
respBody = confirmCertificates(tid, certConf, msgId);
} else if (type == PKIBody.TYPE_REVOCATION_REQ) {
respBody = cmpUnRevokeRemoveCertificates(request, respHeader, cmpControl, reqHeader, reqBody, cmpRequestor, msgId, event);
} else if (type == PKIBody.TYPE_CONFIRM) {
event.addEventType(Cmp.TYPE_pkiconf);
respBody = new PKIBody(PKIBody.TYPE_CONFIRM, DERNull.INSTANCE);
} else if (type == PKIBody.TYPE_GEN_MSG) {
respBody = cmpGeneralMsg(respHeader, cmpControl, reqHeader, reqBody, cmpRequestor, tid, msgId, event);
} else if (type == PKIBody.TYPE_ERROR) {
event.addEventType(Cmp.TYPE_error);
revokePendingCertificates(tid, msgId);
respBody = new PKIBody(PKIBody.TYPE_CONFIRM, DERNull.INSTANCE);
} else {
event.addEventType("PKIBody." + type);
respBody = buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badRequest, "unsupported type " + type);
}
} catch (InsufficientPermissionException ex) {
ErrorMsgContent emc = new ErrorMsgContent(new PKIStatusInfo(PKIStatus.rejection, new PKIFreeText(ex.getMessage()), new PKIFailureInfo(PKIFailureInfo.notAuthorized)));
respBody = new PKIBody(PKIBody.TYPE_ERROR, emc);
}
if (respBody.getType() == PKIBody.TYPE_ERROR) {
ErrorMsgContent errorMsgContent = (ErrorMsgContent) respBody.getContent();
org.xipki.security.cmp.PkiStatusInfo pkiStatus = new org.xipki.security.cmp.PkiStatusInfo(errorMsgContent.getPKIStatusInfo());
event.setStatus(AuditStatus.FAILED);
String statusString = pkiStatus.statusMessage();
if (statusString != null) {
event.addEventData(NAME_message, statusString);
}
} else if (event.getStatus() == null) {
event.setStatus(AuditStatus.SUCCESSFUL);
}
return new PKIMessage(respHeader.build(), respBody);
}
use of org.xipki.ca.api.mgmt.RequestorInfo.CmpRequestorInfo in project xipki by xipki.
the class BaseCmpResponder method processPkiMessage.
// method processPKIMessage0
public PKIMessage processPkiMessage(PKIMessage pkiMessage, X509Cert tlsClientCert, Map<String, String> parameters, AuditEvent event) {
notNull(pkiMessage, "pkiMessage");
notNull(event, "event");
GeneralPKIMessage message = new GeneralPKIMessage(pkiMessage);
PKIHeader reqHeader = message.getHeader();
ASN1OctetString tid = reqHeader.getTransactionID();
String msgId = RandomUtil.nextHexLong();
event.addEventData(NAME_mid, msgId);
if (tid == null) {
byte[] randomBytes = randomTransactionId();
tid = new DEROctetString(randomBytes);
}
String tidStr = Base64.encodeToString(tid.getOctets());
event.addEventData(NAME_tid, tidStr);
int reqPvno = reqHeader.getPvno().getValue().intValue();
if (reqPvno < PVNO_CMP2000) {
event.update(AuditLevel.INFO, AuditStatus.FAILED);
event.addEventData(NAME_message, "unsupported version " + reqPvno);
return buildErrorPkiMessage(tid, reqHeader, PKIFailureInfo.unsupportedVersion, null);
}
CmpControl cmpControl = getCmpControl();
Integer failureCode = null;
String statusText = null;
Date messageTime = null;
if (reqHeader.getMessageTime() != null) {
try {
messageTime = reqHeader.getMessageTime().getDate();
} catch (ParseException ex) {
LogUtil.error(LOG, ex, "tid=" + tidStr + ": could not parse messageTime");
}
}
GeneralName recipient = reqHeader.getRecipient();
boolean intentMe = recipient == null || intendsMe(recipient);
if (!intentMe) {
LOG.warn("tid={}: I am not the intended recipient, but '{}'", tid, reqHeader.getRecipient());
failureCode = PKIFailureInfo.badRequest;
statusText = "I am not the intended recipient";
} else if (messageTime == null) {
if (cmpControl.isMessageTimeRequired()) {
failureCode = PKIFailureInfo.missingTimeStamp;
statusText = "missing time-stamp";
}
} else {
long messageTimeBias = cmpControl.getMessageTimeBias();
if (messageTimeBias < 0) {
messageTimeBias *= -1;
}
long msgTimeMs = messageTime.getTime();
long currentTimeMs = System.currentTimeMillis();
long bias = (msgTimeMs - currentTimeMs) / 1000L;
if (bias > messageTimeBias) {
failureCode = PKIFailureInfo.badTime;
statusText = "message time is in the future";
} else if (bias * -1 > messageTimeBias) {
failureCode = PKIFailureInfo.badTime;
statusText = "message too old";
}
}
if (failureCode != null) {
event.update(AuditLevel.INFO, AuditStatus.FAILED);
event.addEventData(NAME_message, statusText);
return buildErrorPkiMessage(tid, reqHeader, failureCode, statusText);
}
boolean isProtected = message.hasProtection();
CmpRequestorInfo requestor;
String errorStatus;
if (isProtected) {
try {
ProtectionVerificationResult verificationResult = verifyProtection(tidStr, message, cmpControl);
ProtectionResult pr = verificationResult.getProtectionResult();
if (pr == ProtectionResult.SIGNATURE_VALID || pr == ProtectionResult.MAC_VALID) {
errorStatus = null;
} else if (pr == ProtectionResult.SIGNATURE_INVALID) {
errorStatus = "request is protected by signature but invalid";
} else if (pr == ProtectionResult.MAC_INVALID) {
errorStatus = "request is protected by MAC but invalid";
} else if (pr == ProtectionResult.SENDER_NOT_AUTHORIZED) {
errorStatus = "request is protected but the requestor is not authorized";
} else if (pr == ProtectionResult.SIGNATURE_ALGO_FORBIDDEN) {
errorStatus = "request is protected by signature but the algorithm is forbidden";
} else if (pr == ProtectionResult.MAC_ALGO_FORBIDDEN) {
errorStatus = "request is protected by MAC but the algorithm is forbidden";
} else {
throw new IllegalStateException("should not reach here, unknown ProtectionResult " + pr);
}
requestor = (CmpRequestorInfo) verificationResult.getRequestor();
} catch (Exception ex) {
LogUtil.error(LOG, ex, "tid=" + tidStr + ": could not verify the signature");
errorStatus = "request has invalid signature based protection";
requestor = null;
}
} else if (tlsClientCert != null) {
boolean authorized = false;
X500Name x500Sender = getX500Sender(reqHeader);
requestor = (x500Sender == null) ? null : getRequestor(x500Sender);
if (requestor != null) {
if (tlsClientCert.equals(requestor.getCert().getCert())) {
authorized = true;
}
}
if (authorized) {
errorStatus = null;
} else {
LOG.warn("tid={}: not authorized requestor (TLS client '{}')", tid, tlsClientCert.getSubjectRfc4519Text());
errorStatus = "requestor (TLS client certificate) is not authorized";
}
} else {
errorStatus = "request has no protection";
requestor = null;
}
if (errorStatus != null) {
event.update(AuditLevel.INFO, AuditStatus.FAILED);
event.addEventData(NAME_message, errorStatus);
return buildErrorPkiMessage(tid, reqHeader, PKIFailureInfo.badMessageCheck, errorStatus);
}
PKIMessage resp = processPkiMessage0(pkiMessage, requestor, tid, message, msgId, parameters, event);
if (isProtected) {
resp = addProtection(resp, event, requestor);
}
return resp;
}
use of org.xipki.ca.api.mgmt.RequestorInfo.CmpRequestorInfo in project xipki by xipki.
the class BaseCmpResponder method verifyProtection.
// method randomBytes
private ProtectionVerificationResult verifyProtection(String tid, GeneralPKIMessage pkiMessage, CmpControl cmpControl) throws CMPException, InvalidKeyException {
ProtectedPKIMessage protectedMsg = new ProtectedPKIMessage(pkiMessage);
PKIHeader header = protectedMsg.getHeader();
X500Name sender = getX500Sender(header);
if (sender == null) {
LOG.warn("tid={}: not authorized requestor 'null'", tid);
return new ProtectionVerificationResult(null, ProtectionResult.SENDER_NOT_AUTHORIZED);
}
AlgorithmIdentifier protectionAlg = header.getProtectionAlg();
if (protectedMsg.hasPasswordBasedMacProtection()) {
PBMParameter parameter = PBMParameter.getInstance(pkiMessage.getHeader().getProtectionAlg().getParameters());
HashAlgo owfAlg;
try {
owfAlg = HashAlgo.getInstance(parameter.getOwf());
} catch (NoSuchAlgorithmException ex) {
LogUtil.warn(LOG, ex);
return new ProtectionVerificationResult(null, ProtectionResult.MAC_ALGO_FORBIDDEN);
}
if (!cmpControl.isRequestPbmOwfPermitted(owfAlg)) {
LOG.warn("MAC_ALGO_FORBIDDEN (PBMParameter.owf: {})", owfAlg.getJceName());
return new ProtectionVerificationResult(null, ProtectionResult.MAC_ALGO_FORBIDDEN);
}
SignAlgo macAlg;
try {
macAlg = SignAlgo.getInstance(parameter.getMac());
} catch (NoSuchAlgorithmException ex) {
LogUtil.warn(LOG, ex);
return new ProtectionVerificationResult(null, ProtectionResult.MAC_ALGO_FORBIDDEN);
}
if (!cmpControl.isRequestPbmMacPermitted(macAlg)) {
LOG.warn("MAC_ALGO_FORBIDDEN (PBMParameter.mac: {})", macAlg.getJceName());
return new ProtectionVerificationResult(null, ProtectionResult.MAC_ALGO_FORBIDDEN);
}
int iterationCount = parameter.getIterationCount().getValue().intValue();
if (iterationCount < 1000) {
LOG.warn("MAC_ALGO_FORBIDDEN (PBMParameter.iterationCount: {} < 1000)", iterationCount);
return new ProtectionVerificationResult(null, ProtectionResult.MAC_ALGO_FORBIDDEN);
}
ASN1OctetString asn1 = header.getSenderKID();
byte[] senderKID = (asn1 == null) ? null : asn1.getOctets();
PKMACBuilder pkMacBuilder = new PKMACBuilder(new JcePKMACValuesCalculator());
CmpRequestorInfo requestor = getMacRequestor(senderKID);
if (requestor == null) {
LOG.warn("tid={}: not authorized requestor with senderKID '{}", tid, (senderKID == null) ? "null" : Hex.toHexString(senderKID));
return new ProtectionVerificationResult(null, ProtectionResult.SENDER_NOT_AUTHORIZED);
}
boolean macValid = protectedMsg.verify(pkMacBuilder, requestor.getPassword());
return new ProtectionVerificationResult(requestor, macValid ? ProtectionResult.MAC_VALID : ProtectionResult.MAC_INVALID);
} else {
if (!cmpControl.getSigAlgoValidator().isAlgorithmPermitted(protectionAlg)) {
LOG.warn("SIG_ALGO_FORBIDDEN: {}", pkiMessage.getHeader().getProtectionAlg().getAlgorithm().getId());
return new ProtectionVerificationResult(null, ProtectionResult.SIGNATURE_ALGO_FORBIDDEN);
}
X500Name x500Sender = getX500Sender(header);
CmpRequestorInfo requestor = (x500Sender == null) ? null : getRequestor(x500Sender);
if (requestor == null) {
LOG.warn("tid={}: not authorized requestor '{}'", tid, header.getSender());
return new ProtectionVerificationResult(null, ProtectionResult.SENDER_NOT_AUTHORIZED);
}
ContentVerifierProvider verifierProvider = securityFactory.getContentVerifierProvider(requestor.getCert().getCert());
if (verifierProvider == null) {
LOG.warn("tid={}: not authorized requestor '{}'", tid, sender);
return new ProtectionVerificationResult(requestor, ProtectionResult.SENDER_NOT_AUTHORIZED);
}
boolean signatureValid = protectedMsg.verify(verifierProvider);
return new ProtectionVerificationResult(requestor, signatureValid ? ProtectionResult.SIGNATURE_VALID : ProtectionResult.SIGNATURE_INVALID);
}
}
Aggregations