package org.apache.kerberos.kerb.client.preauth.pkinit; import org.apache.kerberos.kerb.client.KrbContext; import org.apache.kerberos.kerb.client.KrbOption; import org.apache.kerberos.kerb.client.KrbOptions; import org.apache.kerberos.kerb.client.preauth.AbstractPreauthPlugin; import org.apache.kerberos.kerb.preauth.PluginRequestContext; import org.apache.kerberos.kerb.client.request.KdcRequest; import org.apache.kerberos.kerb.preauth.PaFlag; import org.apache.kerberos.kerb.preauth.PaFlags; import org.apache.kerberos.kerb.preauth.pkinit.PkinitIdenity; import org.apache.kerberos.kerb.preauth.pkinit.PkinitPreauthMeta; import org.apache.kerberos.kerb.KrbException; import org.apache.kerberos.kerb.spec.KerberosTime; import org.apache.kerberos.kerb.spec.common.EncryptionKey; import org.apache.kerberos.kerb.spec.common.EncryptionType; import org.apache.kerberos.kerb.spec.common.PrincipalName; import org.apache.kerberos.kerb.spec.pa.PaData; import org.apache.kerberos.kerb.spec.pa.PaDataEntry; import org.apache.kerberos.kerb.spec.pa.PaDataType; import org.apache.kerberos.kerb.spec.pa.pkinit.*; import org.apache.kerberos.kerb.spec.x509.SubjectPublicKeyInfo; public class PkinitPreauth extends AbstractPreauthPlugin { private PkinitContext pkinitContext; public PkinitPreauth() { super(new PkinitPreauthMeta()); } @Override public void init(KrbContext context) { super.init(context); this.pkinitContext = new PkinitContext(); } @Override public PluginRequestContext initRequestContext(KdcRequest kdcRequest) { PkinitRequestContext reqCtx = new PkinitRequestContext(); reqCtx.updateRequestOpts(pkinitContext.pluginOpts); return reqCtx; } @Override public void setPreauthOptions(KdcRequest kdcRequest, PluginRequestContext requestContext, KrbOptions options) { if (options.contains(KrbOption.PKINIT_X509_IDENTITY)) { pkinitContext.identityOpts.identity = options.getStringOption(KrbOption.PKINIT_X509_IDENTITY); } if (options.contains(KrbOption.PKINIT_X509_ANCHORS)) { pkinitContext.identityOpts.anchors.add( options.getStringOption(KrbOption.PKINIT_X509_ANCHORS)); } if (options.contains(KrbOption.PKINIT_USING_RSA)) { pkinitContext.pluginOpts.usingRsa = options.getBooleanOption(KrbOption.PKINIT_USING_RSA); } } @Override public void prepareQuestions(KdcRequest kdcRequest, PluginRequestContext requestContext) { PkinitRequestContext reqCtx = (PkinitRequestContext) requestContext; if (!reqCtx.identityInitialized) { PkinitIdenity.initialize(reqCtx.identityOpts, kdcRequest.getClientPrincipal()); reqCtx.identityInitialized = true; } // Might have questions asking for password to access the private key } public void tryFirst(KdcRequest kdcRequest, PluginRequestContext requestContext, PaData outPadata) throws KrbException { } @Override public boolean process(KdcRequest kdcRequest, PluginRequestContext requestContext, PaDataEntry inPadata, PaData outPadata) throws KrbException { PkinitRequestContext reqCtx = (PkinitRequestContext) requestContext; if (inPadata == null) return false; boolean processingRequest = false; switch (inPadata.getPaDataType()) { case PK_AS_REQ: processingRequest = true; break; case PK_AS_REP: break; } if (processingRequest) { generateRequest(reqCtx, kdcRequest, outPadata); } else { EncryptionType encType = kdcRequest.getEncType(); processReply(kdcRequest, reqCtx, inPadata, encType); } return false; } private void generateRequest(PkinitRequestContext reqCtx, KdcRequest kdcRequest, PaData outPadata) { } private PaPkAsReq makePaPkAsReq(PkinitContext pkinitContext, PkinitRequestContext reqCtx, KerberosTime ctime, int cusec, int nonce, byte[] checksum, PrincipalName client, PrincipalName server) { PaPkAsReq paPkAsReq = new PaPkAsReq(); AuthPack authPack = new AuthPack(); SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(); PkAuthenticator pkAuthen = new PkAuthenticator(); boolean usingRsa = reqCtx.requestOpts.usingRsa; PaDataType paType = reqCtx.paType = PaDataType.PK_AS_REQ; pkAuthen.setCtime(ctime); pkAuthen.setCusec(cusec); pkAuthen.setNonce(nonce); pkAuthen.setPaChecksum(checksum); authPack.setPkAuthenticator(pkAuthen); DHNonce dhNonce = new DHNonce(); authPack.setClientDhNonce(dhNonce); authPack.setClientPublicValue(pubInfo); authPack.setsupportedCmsTypes(pkinitContext.pluginOpts.createSupportedCMSTypes()); if (usingRsa) { // DH case } else { authPack.setClientPublicValue(null); } byte[] signedAuthPack = signAuthPack(pkinitContext, reqCtx, authPack); paPkAsReq.setSignedAuthPack(signedAuthPack); TrustedCertifiers trustedCertifiers = pkinitContext.pluginOpts.createTrustedCertifiers(); paPkAsReq.setTrustedCertifiers(trustedCertifiers); byte[] kdcPkId = pkinitContext.pluginOpts.createIssuerAndSerial(); paPkAsReq.setKdcPkId(kdcPkId); return paPkAsReq; } private byte[] signAuthPack(PkinitContext pkinitContext, PkinitRequestContext reqCtx, AuthPack authPack) { return null; } private void processReply(KdcRequest kdcRequest, PkinitRequestContext reqCtx, PaDataEntry inPadata, EncryptionType encType) { EncryptionKey asKey = null; // TODO kdcRequest.setAsKey(asKey); } @Override public boolean tryAgain(KdcRequest kdcRequest, PluginRequestContext requestContext, PaDataType preauthType, PaData errPadata, PaData outPadata) { PkinitRequestContext reqCtx = (PkinitRequestContext) requestContext; if (reqCtx.paType != preauthType && errPadata == null) { return false; } boolean doAgain = false; for (PaDataEntry pde : errPadata.getElements()) { switch (pde.getPaDataType()) { // TODO } } if (doAgain) { generateRequest(reqCtx, kdcRequest, outPadata); } return false; } @Override public PaFlags getFlags(PaDataType paType) { PaFlags paFlags = new PaFlags(0); paFlags.setFlag(PaFlag.PA_REAL); return paFlags; } }