blob: 9415589ef8aeb6bb8ac6bd261e92d16821e4574d [file] [log] [blame]
/**
* 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;
import org.apache.kerby.kerberos.kerb.KrbCodec;
import org.apache.kerby.kerberos.kerb.KrbErrorCode;
import org.apache.kerby.kerberos.kerb.KrbErrorException;
import org.apache.kerby.kerberos.kerb.KrbException;
import org.apache.kerby.kerberos.kerb.server.request.AsRequest;
import org.apache.kerby.kerberos.kerb.server.request.KdcRequest;
import org.apache.kerby.kerberos.kerb.server.request.TgsRequest;
import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
import org.apache.kerby.kerberos.kerb.spec.base.KrbError;
import org.apache.kerby.kerberos.kerb.spec.base.KrbMessage;
import org.apache.kerby.kerberos.kerb.spec.base.KrbMessageType;
import org.apache.kerby.kerberos.kerb.spec.base.PrincipalName;
import org.apache.kerby.kerberos.kerb.spec.kdc.AsReq;
import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReq;
import org.apache.kerby.kerberos.kerb.spec.kdc.TgsReq;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
/**
* KDC handler to process client requests. Currently only one realm is supported.
*/
public class KdcHandler {
private final KdcContext kdcContext;
public KdcHandler(KdcContext kdcContext) {
this.kdcContext = kdcContext;
}
public ByteBuffer handleMessage(ByteBuffer receivedMessage, boolean isTcp,
InetAddress remoteAddress) throws KrbException {
KrbMessage krbRequest = null;
KdcRequest kdcRequest = null;
KrbMessage krbResponse;
try {
try {
krbRequest = KrbCodec.decodeMessage(receivedMessage);
} catch (IOException e) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_MSG_TYPE, "Krb decoding message failed");
}
KrbMessageType messageType = krbRequest.getMsgType();
if (messageType == KrbMessageType.TGS_REQ || messageType
== KrbMessageType.AS_REQ) {
KdcReq kdcReq = (KdcReq) krbRequest;
String realm = getRequestRealm(kdcReq);
if (realm == null || !kdcContext.getKdcRealm().equals(realm)) {
throw new KrbException("Invalid realm from kdc request: " + realm);
}
if (messageType == KrbMessageType.TGS_REQ) {
kdcRequest = new TgsRequest((TgsReq) kdcReq, kdcContext);
} else if (messageType == KrbMessageType.AS_REQ) {
kdcRequest = new AsRequest((AsReq) kdcReq, kdcContext);
} else {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_MSG_TYPE);
}
}
kdcRequest.setClientAddress(remoteAddress);
kdcRequest.isTcp(isTcp);
kdcRequest.process();
krbResponse = kdcRequest.getReply();
} catch (KrbException e) {
krbResponse = krbExceptionHandler(e, kdcRequest);
}
int bodyLen = krbResponse.encodingLength();
ByteBuffer responseMessage;
if (isTcp) {
responseMessage = ByteBuffer.allocate(bodyLen + 4);
responseMessage.putInt(bodyLen);
} else {
responseMessage = ByteBuffer.allocate(bodyLen);
}
krbResponse.encode(responseMessage);
responseMessage.flip();
return responseMessage;
}
private KrbMessage krbExceptionHandler(KrbException e, KdcRequest kdcRequest)
throws KrbException {
System.out.println("KRB error occured while processing request:"
+ e.getMessage());
KrbError error;
if(e instanceof KrbErrorException) {
error = ((KrbErrorException) e).getKrbError();
} else {
error = new KrbError();
}
error.setStime(KerberosTime.now());
error.setSusec(100);
error.setErrorCode(((KrbErrorException) e).getKrbError().getErrorCode());
error.setRealm(kdcContext.getKdcRealm());
if(kdcRequest != null) {
error.setSname(kdcRequest.getKdcReq().getReqBody().getCname());
} else {
error.setSname(new PrincipalName("NONE"));
}
error.setEtext(e.getMessage());
return error;
}
private String getRequestRealm(KdcReq kdcReq) {
String realm = kdcReq.getReqBody().getRealm();
if (realm == null && kdcReq.getReqBody().getCname() != null) {
realm = kdcReq.getReqBody().getCname().getRealm();
}
return realm;
}
}