| /** |
| * 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; |
| } |
| } |