You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by dr...@apache.org on 2015/04/24 01:56:20 UTC
directory-kerby git commit: Refactored KDC request handling related
to ticket issuing
Repository: directory-kerby
Updated Branches:
refs/heads/master 0bb77a111 -> 6de5ada93
Refactored KDC request handling related to ticket issuing
Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/6de5ada9
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/6de5ada9
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/6de5ada9
Branch: refs/heads/master
Commit: 6de5ada9389fbe7919a5af36dec91d50a058d7f4
Parents: 0bb77a1
Author: Drankye <dr...@gmail.com>
Authored: Fri Apr 24 07:55:58 2015 +0800
Committer: Drankye <dr...@gmail.com>
Committed: Fri Apr 24 07:55:58 2015 +0800
----------------------------------------------------------------------
.../kerb/server/impl/DefaultKdcHandler.java | 3 +-
.../kerberos/kerb/server/request/AsRequest.java | 11 +-
.../kerb/server/request/KdcRequest.java | 171 +-------------
.../server/request/ServiceTickertIssuer.java | 50 ++++
.../kerb/server/request/TgsRequest.java | 21 +-
.../kerb/server/request/TgtTickertIssuer.java | 43 ++++
.../kerb/server/request/TickertIssuer.java | 231 +++++++++++++++++++
7 files changed, 356 insertions(+), 174 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/6de5ada9/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/DefaultKdcHandler.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/DefaultKdcHandler.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/DefaultKdcHandler.java
index 96809ee..3ff9a10 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/DefaultKdcHandler.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/DefaultKdcHandler.java
@@ -67,7 +67,8 @@ public class DefaultKdcHandler extends KdcHandler implements Runnable {
ByteBuffer krbResponse = handleMessage(message, isTcp, clientAddress);
transport.sendMessage(krbResponse);
} catch (Exception e) {
- logger.debug("Error occured while processing request:", e);
+ e.printStackTrace();
+ logger.error("Error occured while processing request:", e);
}
}
}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/6de5ada9/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
index 097a630..c402926 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
@@ -42,7 +42,7 @@ public class AsRequest extends KdcRequest {
PrincipalName clientPrincipal = request.getReqBody().getCname();
String clientRealm = request.getReqBody().getRealm();
if (clientRealm == null || clientRealm.isEmpty()) {
- clientRealm = kdcContext.getKdcRealm();
+ clientRealm = getKdcContext().getKdcRealm();
}
clientPrincipal.setRealm(clientRealm);
@@ -59,13 +59,20 @@ public class AsRequest extends KdcRequest {
}
@Override
+ protected void issueTicket() throws KrbException {
+ TickertIssuer issuer = new TgtTickertIssuer(this);
+ Ticket newTicket = issuer.issueTicket();
+ setTicket(newTicket);
+ }
+
+ @Override
protected void makeReply() throws KrbException {
Ticket ticket = getTicket();
AsRep reply = new AsRep();
reply.setCname(getClientEntry().getPrincipal());
- reply.setCrealm(kdcContext.getKdcRealm());
+ reply.setCrealm(getKdcContext().getKdcRealm());
reply.setTicket(ticket);
EncKdcRepPart encKdcRepPart = makeEncKdcRepPart();
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/6de5ada9/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
index 6430d3d..8ceaf6a 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
@@ -19,32 +19,20 @@
*/
package org.apache.kerby.kerberos.kerb.server.request;
-import org.apache.kerby.kerberos.kerb.KrbErrorCode;
-import org.apache.kerby.kerberos.kerb.KrbCodec;
+import org.apache.kerby.kerberos.kerb.*;
import org.apache.kerby.kerberos.kerb.common.EncryptionUtil;
-import org.apache.kerby.kerberos.kerb.crypto.EncryptionHandler;
import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
-import org.apache.kerby.kerberos.kerb.server.KdcConfig;
import org.apache.kerby.kerberos.kerb.server.KdcContext;
import org.apache.kerby.kerberos.kerb.server.preauth.KdcFastContext;
import org.apache.kerby.kerberos.kerb.server.preauth.PreauthContext;
import org.apache.kerby.kerberos.kerb.server.preauth.PreauthHandler;
-import org.apache.kerby.kerberos.kerb.KrbConstant;
-import org.apache.kerby.kerberos.kerb.KrbErrorException;
-import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
import org.apache.kerby.kerberos.kerb.spec.base.*;
-import org.apache.kerby.kerberos.kerb.spec.kdc.KdcOption;
-import org.apache.kerby.kerberos.kerb.spec.kdc.KdcOptions;
import org.apache.kerby.kerberos.kerb.spec.kdc.KdcRep;
import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReq;
import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
-import org.apache.kerby.kerberos.kerb.spec.ticket.EncTicketPart;
import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
-import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlag;
-import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlags;
import java.net.InetAddress;
import java.nio.ByteBuffer;
@@ -53,11 +41,11 @@ import java.util.List;
public abstract class KdcRequest {
- protected KdcContext kdcContext;
+ private final KdcReq kdcReq;
+ private final KdcContext kdcContext;
private Ticket ticket;
private boolean isPreAuthenticated;
- private KdcReq kdcReq;
private KdcRep reply;
private InetAddress clientAddress;
private boolean isTcp = true;
@@ -74,6 +62,7 @@ public abstract class KdcRequest {
public KdcRequest(KdcReq kdcReq, KdcContext kdcContext) {
this.kdcReq = kdcReq;
this.kdcContext = kdcContext;
+
this.preauthContext = kdcContext.getPreauthHandler()
.preparePreauthContext(this);
this.fastContext = new KdcFastContext();
@@ -83,6 +72,10 @@ public abstract class KdcRequest {
return kdcContext;
}
+ public KdcReq getKdcReq() {
+ return kdcReq;
+ }
+
public PreauthContext getPreauthContext() {
return preauthContext;
}
@@ -97,10 +90,6 @@ public abstract class KdcRequest {
makeReply();
}
- public KdcReq getKdcReq() {
- return kdcReq;
- }
-
public KrbIdentity getTgsEntry() {
return tgsEntry;
}
@@ -275,149 +264,7 @@ public abstract class KdcRequest {
checkPolicy();
}
- protected void issueTicket() throws KrbException {
- KdcReq request = getKdcReq();
-
- EncryptionType encryptionType = getEncryptionType();
- EncryptionKey serverKey = getServerEntry().getKeys().get(encryptionType);
-
- PrincipalName ticketPrincipal = getIssueTicketServerPrincipal();
-
- EncTicketPart encTicketPart = new EncTicketPart();
- KdcConfig config = kdcContext.getConfig();
-
- TicketFlags ticketFlags = new TicketFlags();
- encTicketPart.setFlags(ticketFlags);
- ticketFlags.setFlag(TicketFlag.INITIAL);
-
- if (isPreAuthenticated()) {
- ticketFlags.setFlag(TicketFlag.PRE_AUTH);
- }
-
- if (request.getReqBody().getKdcOptions().isFlagSet(KdcOption.FORWARDABLE)) {
- if (!config.isForwardableAllowed()) {
- throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
- }
-
- ticketFlags.setFlag(TicketFlag.FORWARDABLE);
- }
-
- if (request.getReqBody().getKdcOptions().isFlagSet(KdcOption.PROXIABLE)) {
- if (!config.isProxiableAllowed()) {
- throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
- }
-
- ticketFlags.setFlag(TicketFlag.PROXIABLE);
- }
-
- if (request.getReqBody().getKdcOptions().isFlagSet(KdcOption.ALLOW_POSTDATE)) {
- if (!config.isPostdatedAllowed()) {
- throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
- }
-
- ticketFlags.setFlag(TicketFlag.MAY_POSTDATE);
- }
-
- KdcOptions kdcOptions = request.getReqBody().getKdcOptions();
-
- EncryptionKey sessionKey = EncryptionHandler.random2Key(getEncryptionType());
- encTicketPart.setKey(sessionKey);
-
- encTicketPart.setCname(getIssueTicketClientPrincipal());
- encTicketPart.setCrealm(request.getReqBody().getRealm());
-
- TransitedEncoding transEnc = new TransitedEncoding();
- encTicketPart.setTransited(transEnc);
- String serverRealm = request.getReqBody().getRealm();
-
- KerberosTime now = KerberosTime.now();
- encTicketPart.setAuthTime(now);
-
- KerberosTime krbStartTime = request.getReqBody().getFrom();
- if (krbStartTime == null || krbStartTime.lessThan(now) ||
- krbStartTime.isInClockSkew(config.getAllowableClockSkew())) {
- krbStartTime = now;
- }
- if (krbStartTime.greaterThan(now)
- && !krbStartTime.isInClockSkew(config.getAllowableClockSkew())
- && !kdcOptions.isFlagSet(KdcOption.POSTDATED)) {
- throw new KrbException(KrbErrorCode.KDC_ERR_CANNOT_POSTDATE);
- }
-
- if (kdcOptions.isFlagSet(KdcOption.POSTDATED)) {
- if (!config.isPostdatedAllowed()) {
- throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
- }
-
- ticketFlags.setFlag(TicketFlag.POSTDATED);
- encTicketPart.setStartTime(krbStartTime);
- }
-
- KerberosTime krbEndTime = request.getReqBody().getTill();
- if (krbEndTime == null || krbEndTime.getTime() == 0) {
- krbEndTime = krbStartTime.extend(config.getMaximumTicketLifetime() * 1000);
- } else if (krbStartTime.greaterThan(krbEndTime)) {
- throw new KrbException(KrbErrorCode.KDC_ERR_NEVER_VALID);
- }
- encTicketPart.setEndTime(krbEndTime);
-
- long ticketLifeTime = Math.abs(krbEndTime.diff(krbStartTime));
- if (ticketLifeTime < config.getMinimumTicketLifetime()) {
- throw new KrbException(KrbErrorCode.KDC_ERR_NEVER_VALID);
- }
-
- KerberosTime krbRtime = request.getReqBody().getRtime();
- if (kdcOptions.isFlagSet(KdcOption.RENEWABLE_OK)) {
- kdcOptions.setFlag(KdcOption.RENEWABLE);
- }
- if (kdcOptions.isFlagSet(KdcOption.RENEWABLE)) {
- if (!config.isRenewableAllowed()) {
- throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
- }
-
- ticketFlags.setFlag(TicketFlag.RENEWABLE);
-
- if (krbRtime == null || krbRtime.getTime() == 0) {
- krbRtime = KerberosTime.NEVER;
- }
- KerberosTime allowedMaximumRenewableTime = krbStartTime;
- allowedMaximumRenewableTime.extend(config.getMaximumRenewableLifetime() * 1000);
- if (krbRtime.greaterThan(allowedMaximumRenewableTime)) {
- krbRtime = allowedMaximumRenewableTime;
- }
- encTicketPart.setRenewtill(krbRtime);
- }
-
- HostAddresses hostAddresses = request.getReqBody().getAddresses();
- if (hostAddresses == null || hostAddresses.isEmpty()) {
- if (!config.isEmptyAddressesAllowed()) {
- throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
- }
- } else {
- encTicketPart.setClientAddresses(hostAddresses);
- }
-
- EncryptedData encryptedData = EncryptionUtil.seal(encTicketPart,
- serverKey, KeyUsage.KDC_REP_TICKET);
-
- Ticket newTicket = new Ticket();
- newTicket.setSname(ticketPrincipal);
- newTicket.setEncryptedEncPart(encryptedData);
- newTicket.setRealm(serverRealm);
- newTicket.setEncPart(encTicketPart);
-
- setTicket(newTicket);
- }
-
- protected PrincipalName getIssueTicketServerPrincipal() {
- KdcReq request = getKdcReq();
- return request.getReqBody().getSname();
- }
-
- protected PrincipalName getIssueTicketClientPrincipal() {
- KdcReq request = getKdcReq();
- return request.getReqBody().getCname();
- }
+ protected abstract void issueTicket() throws KrbException;
private void checkServer() throws KrbException {
KdcReq request = getKdcReq();
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/6de5ada9/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/ServiceTickertIssuer.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/ServiceTickertIssuer.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/ServiceTickertIssuer.java
new file mode 100644
index 0000000..ee30ee9
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/ServiceTickertIssuer.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.kerby.kerberos.kerb.server.request;
+
+import org.apache.kerby.kerberos.kerb.spec.base.PrincipalName;
+import org.apache.kerby.kerberos.kerb.spec.base.TransitedEncoding;
+import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
+
+/**
+ * Issuing service ticket.
+ */
+public class ServiceTickertIssuer extends TickertIssuer {
+ private final Ticket tgtTicket;
+
+ public ServiceTickertIssuer(TgsRequest kdcRequest) {
+ super(kdcRequest);
+ tgtTicket = kdcRequest.getTgtTicket();
+ }
+
+ protected KdcRequest getTgsRequest() {
+ return getKdcRequest();
+ }
+
+ @Override
+ protected PrincipalName getclientPrincipal() {
+ return tgtTicket.getEncPart().getCname();
+ }
+
+ @Override
+ protected TransitedEncoding getTransitedEncoding() {
+ return tgtTicket.getEncPart().getTransited();
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/6de5ada9/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgsRequest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgsRequest.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgsRequest.java
index 9088bd6..34e21c2 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgsRequest.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgsRequest.java
@@ -58,17 +58,20 @@ public class TgsRequest extends KdcRequest {
this.tgtSessionKey = tgtSessionKey;
}
- protected PrincipalName getIssueTicketServerPrincipal() {
- return tgtTicket.getSname();
+ @Override
+ protected void checkClient() throws KrbException {
+ // Nothing to do at this phase because client couldn't be checked out yet.
}
- protected PrincipalName getIssueTicketClientPrincipal() {
- return tgtTicket.getEncPart().getCname();
+ protected Ticket getTgtTicket() {
+ return tgtTicket;
}
@Override
- protected void checkClient() throws KrbException {
- // Nothing to do at this phase because client couldn't be checked out yet.
+ protected void issueTicket() throws KrbException {
+ TickertIssuer issuer = new ServiceTickertIssuer(this);
+ Ticket newTicket = issuer.issueTicket();
+ setTicket(newTicket);
}
public void verifyAuthenticator(PaDataEntry paDataEntry) throws KrbException {
@@ -109,7 +112,7 @@ public class TgsRequest extends KdcRequest {
HostAddresses hostAddresses = tgtTicket.getEncPart().getClientAddresses();
if (hostAddresses == null || hostAddresses.isEmpty()) {
- if (!kdcContext.getConfig().isEmptyAddressesAllowed()) {
+ if (!getKdcContext().getConfig().isEmptyAddressesAllowed()) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADADDR);
}
} else if (!hostAddresses.contains(getClientAddress())) {
@@ -124,7 +127,7 @@ public class TgsRequest extends KdcRequest {
setClientEntry(clientEntry);
if (!authenticator.getCtime().isInClockSkew(
- kdcContext.getConfig().getAllowableClockSkew() * 1000)) {
+ getKdcContext().getConfig().getAllowableClockSkew() * 1000)) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_SKEW);
}
@@ -154,7 +157,7 @@ public class TgsRequest extends KdcRequest {
TgsRep reply = new TgsRep();
reply.setCname(getClientEntry().getPrincipal());
- reply.setCrealm(kdcContext.getKdcRealm());
+ reply.setCrealm(getKdcContext().getKdcRealm());
reply.setTicket(ticket);
EncKdcRepPart encKdcRepPart = makeEncKdcRepPart();
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/6de5ada9/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgtTickertIssuer.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgtTickertIssuer.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgtTickertIssuer.java
new file mode 100644
index 0000000..4003f95
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgtTickertIssuer.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.kerby.kerberos.kerb.server.request;
+
+import org.apache.kerby.kerberos.kerb.spec.base.TransitedEncoding;
+import org.apache.kerby.kerberos.kerb.spec.base.TransitedEncodingType;
+
+/**
+ * Issuing TGT ticket.
+ */
+public class TgtTickertIssuer extends TickertIssuer {
+
+ public TgtTickertIssuer(AsRequest kdcRequest) {
+ super(kdcRequest);
+ }
+
+ @Override
+ protected TransitedEncoding getTransitedEncoding() {
+ TransitedEncoding transEnc = new TransitedEncoding();
+ transEnc.setTrType(TransitedEncodingType.DOMAIN_X500_COMPRESS);
+ byte[] empty = new byte[0];
+ transEnc.setContents(empty);
+
+ return transEnc;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/6de5ada9/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TickertIssuer.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TickertIssuer.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TickertIssuer.java
new file mode 100644
index 0000000..372bd02
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TickertIssuer.java
@@ -0,0 +1,231 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.kerby.kerberos.kerb.server.request;
+
+import org.apache.kerby.kerberos.kerb.KrbErrorCode;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.common.EncryptionUtil;
+import org.apache.kerby.kerberos.kerb.crypto.EncryptionHandler;
+import org.apache.kerby.kerberos.kerb.server.KdcConfig;
+import org.apache.kerby.kerberos.kerb.server.KdcContext;
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.base.*;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcOption;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcOptions;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReq;
+import org.apache.kerby.kerberos.kerb.spec.ticket.EncTicketPart;
+import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlag;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlags;
+
+/**
+ * Handling ticket constructing, filling, and issuing.
+ */
+public abstract class TickertIssuer {
+ private final KdcRequest kdcRequest;
+
+ public TickertIssuer(KdcRequest kdcRequest) {
+ this.kdcRequest = kdcRequest;
+ }
+
+ protected KdcRequest getKdcRequest() {
+ return kdcRequest;
+ }
+
+ public Ticket issueTicket() throws KrbException {
+ KdcReq request = kdcRequest.getKdcReq();
+
+ Ticket issuedTicket = new Ticket();
+
+ PrincipalName serverPrincipal = getServerPrincipal();
+ issuedTicket.setSname(serverPrincipal);
+
+ String serverRealm = request.getReqBody().getRealm();
+ issuedTicket.setRealm(serverRealm);
+
+ EncTicketPart encTicketPart = makeEncTicketPart();
+
+ EncryptionKey encryptionKey = getTicketEncryptionKey();
+
+ EncryptedData encryptedData = EncryptionUtil.seal(encTicketPart,
+ encryptionKey, KeyUsage.KDC_REP_TICKET);
+ issuedTicket.setEncryptedEncPart(encryptedData);
+ issuedTicket.setEncPart(encTicketPart);
+
+ return issuedTicket;
+ }
+
+ public EncTicketPart makeEncTicketPart() throws KrbException {
+ KdcReq request = kdcRequest.getKdcReq();
+
+ EncTicketPart encTicketPart = new EncTicketPart();
+ KdcConfig config = kdcRequest.getKdcContext().getConfig();
+
+ TicketFlags ticketFlags = new TicketFlags();
+ encTicketPart.setFlags(ticketFlags);
+ ticketFlags.setFlag(TicketFlag.INITIAL);
+
+ if (kdcRequest.isPreAuthenticated()) {
+ ticketFlags.setFlag(TicketFlag.PRE_AUTH);
+ }
+
+ if (request.getReqBody().getKdcOptions().isFlagSet(KdcOption.FORWARDABLE)) {
+ if (!config.isForwardableAllowed()) {
+ throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+ }
+
+ ticketFlags.setFlag(TicketFlag.FORWARDABLE);
+ }
+
+ if (request.getReqBody().getKdcOptions().isFlagSet(KdcOption.PROXIABLE)) {
+ if (!config.isProxiableAllowed()) {
+ throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+ }
+
+ ticketFlags.setFlag(TicketFlag.PROXIABLE);
+ }
+
+ if (request.getReqBody().getKdcOptions().isFlagSet(KdcOption.ALLOW_POSTDATE)) {
+ if (!config.isPostdatedAllowed()) {
+ throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+ }
+
+ ticketFlags.setFlag(TicketFlag.MAY_POSTDATE);
+ }
+
+ EncryptionKey sessionKey = EncryptionHandler.random2Key(
+ kdcRequest.getEncryptionType());
+ encTicketPart.setKey(sessionKey);
+
+ encTicketPart.setCname(getclientPrincipal());
+ encTicketPart.setCrealm(request.getReqBody().getRealm());
+
+ TransitedEncoding transEnc = getTransitedEncoding();
+ encTicketPart.setTransited(transEnc);
+
+ KdcOptions kdcOptions = request.getReqBody().getKdcOptions();
+
+ KerberosTime now = KerberosTime.now();
+ encTicketPart.setAuthTime(now);
+
+ KerberosTime krbStartTime = request.getReqBody().getFrom();
+ if (krbStartTime == null || krbStartTime.lessThan(now) ||
+ krbStartTime.isInClockSkew(config.getAllowableClockSkew())) {
+ krbStartTime = now;
+ }
+ if (krbStartTime.greaterThan(now)
+ && !krbStartTime.isInClockSkew(config.getAllowableClockSkew())
+ && !kdcOptions.isFlagSet(KdcOption.POSTDATED)) {
+ throw new KrbException(KrbErrorCode.KDC_ERR_CANNOT_POSTDATE);
+ }
+
+ if (kdcOptions.isFlagSet(KdcOption.POSTDATED)) {
+ if (!config.isPostdatedAllowed()) {
+ throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+ }
+
+ ticketFlags.setFlag(TicketFlag.POSTDATED);
+ encTicketPart.setStartTime(krbStartTime);
+ }
+
+ KerberosTime krbEndTime = request.getReqBody().getTill();
+ if (krbEndTime == null || krbEndTime.getTime() == 0) {
+ krbEndTime = krbStartTime.extend(config.getMaximumTicketLifetime() * 1000);
+ } else if (krbStartTime.greaterThan(krbEndTime)) {
+ throw new KrbException(KrbErrorCode.KDC_ERR_NEVER_VALID);
+ }
+ encTicketPart.setEndTime(krbEndTime);
+
+ long ticketLifeTime = Math.abs(krbEndTime.diff(krbStartTime));
+ if (ticketLifeTime < config.getMinimumTicketLifetime()) {
+ throw new KrbException(KrbErrorCode.KDC_ERR_NEVER_VALID);
+ }
+
+ KerberosTime krbRtime = request.getReqBody().getRtime();
+ if (kdcOptions.isFlagSet(KdcOption.RENEWABLE_OK)) {
+ kdcOptions.setFlag(KdcOption.RENEWABLE);
+ }
+ if (kdcOptions.isFlagSet(KdcOption.RENEWABLE)) {
+ if (!config.isRenewableAllowed()) {
+ throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+ }
+
+ ticketFlags.setFlag(TicketFlag.RENEWABLE);
+
+ if (krbRtime == null || krbRtime.getTime() == 0) {
+ krbRtime = KerberosTime.NEVER;
+ }
+ KerberosTime allowedMaximumRenewableTime = krbStartTime;
+ allowedMaximumRenewableTime.extend(config.getMaximumRenewableLifetime() * 1000);
+ if (krbRtime.greaterThan(allowedMaximumRenewableTime)) {
+ krbRtime = allowedMaximumRenewableTime;
+ }
+ encTicketPart.setRenewtill(krbRtime);
+ }
+
+ HostAddresses hostAddresses = request.getReqBody().getAddresses();
+ if (hostAddresses == null || hostAddresses.isEmpty()) {
+ if (!config.isEmptyAddressesAllowed()) {
+ throw new KrbException(KrbErrorCode.KDC_ERR_POLICY);
+ }
+ } else {
+ encTicketPart.setClientAddresses(hostAddresses);
+ }
+
+ return encTicketPart;
+ }
+
+ protected KdcContext getKdcContext() {
+ return kdcRequest.getKdcContext();
+ }
+
+ protected KdcReq getKdcReq() {
+ return kdcRequest.getKdcReq();
+ }
+
+ protected PrincipalName getclientPrincipal() {
+ return getKdcReq().getReqBody().getCname();
+ }
+
+ protected PrincipalName getServerPrincipal() {
+ return getKdcReq().getReqBody().getSname();
+ }
+
+ protected EncryptionType getTicketEncryptionType() throws KrbException {
+ EncryptionType encryptionType = kdcRequest.getEncryptionType();
+ return encryptionType;
+ }
+
+ protected EncryptionKey getTicketEncryptionKey() throws KrbException {
+ EncryptionType encryptionType = getTicketEncryptionType();
+ EncryptionKey serverKey =
+ kdcRequest.getServerEntry().getKeys().get(encryptionType);
+ return serverKey;
+ }
+
+ protected TransitedEncoding getTransitedEncoding() {
+ TransitedEncoding transEnc = new TransitedEncoding();
+ transEnc.setTrType(TransitedEncodingType.DOMAIN_X500_COMPRESS);
+ byte[] empty = new byte[0];
+ transEnc.setContents(empty);
+
+ return transEnc;
+ }
+}