001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.server.kerberos.shared.io.encoder; 021 022 023 import java.io.ByteArrayOutputStream; 024 import java.io.IOException; 025 import java.nio.ByteBuffer; 026 027 import org.apache.directory.server.kerberos.shared.messages.KdcRequest; 028 import org.apache.directory.server.kerberos.shared.messages.value.PaData; 029 import org.apache.directory.server.kerberos.shared.messages.value.RequestBody; 030 import org.apache.directory.shared.asn1.der.ASN1OutputStream; 031 import org.apache.directory.shared.asn1.der.DERApplicationSpecific; 032 import org.apache.directory.shared.asn1.der.DERBitString; 033 import org.apache.directory.shared.asn1.der.DERGeneralString; 034 import org.apache.directory.shared.asn1.der.DERInteger; 035 import org.apache.directory.shared.asn1.der.DEROctetString; 036 import org.apache.directory.shared.asn1.der.DERSequence; 037 import org.apache.directory.shared.asn1.der.DERTaggedObject; 038 039 040 /** 041 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 042 * @version $Rev: 587624 $, $Date: 2007-10-23 21:22:08 +0200 (Tue, 23 Oct 2007) $ 043 */ 044 public class KdcRequestEncoder 045 { 046 /** 047 * Encodes a {@link KdcRequest} into a {@link ByteBuffer}. 048 * 049 * AS-REQ ::= [APPLICATION 10] KDC-REQ 050 * TGS-REQ ::= [APPLICATION 12] KDC-REQ 051 * 052 * @param request 053 * @param out 054 * @throws IOException 055 */ 056 public void encode( KdcRequest request, ByteBuffer out ) throws IOException 057 { 058 ASN1OutputStream aos = new ASN1OutputStream( out ); 059 060 DERSequence kdcRequest = encodeInitialSequence( request ); 061 aos.writeObject( DERApplicationSpecific.valueOf( request.getMessageType().getOrdinal(), kdcRequest ) ); 062 aos.close(); 063 } 064 065 066 /* 067 KDC-REQ ::= SEQUENCE { 068 pvno[1] INTEGER, 069 msg-type[2] INTEGER, 070 padata[3] SEQUENCE OF PA-DATA OPTIONAL, 071 req-body[4] KDC-REQ-BODY 072 }*/ 073 private DERSequence encodeInitialSequence( KdcRequest app ) 074 { 075 DERSequence sequence = new DERSequence(); 076 077 sequence.add( new DERTaggedObject( 1, DERInteger.valueOf( app.getProtocolVersionNumber() ) ) ); 078 079 sequence.add( new DERTaggedObject( 2, DERInteger.valueOf( app.getMessageType().getOrdinal() ) ) ); 080 081 if ( app.getPreAuthData() != null ) 082 { 083 sequence.add( new DERTaggedObject( 3, encodePreAuthData( app.getPreAuthData() ) ) ); 084 } 085 086 sequence.add( new DERTaggedObject( 4, encodeKdcRequestBody( app.getRequestBody() ) ) ); 087 088 return sequence; 089 } 090 091 092 /** 093 * Encodes a {@link KdcRequest} into a byte[]. 094 * 095 * @param requestBody 096 * @return The encoded {@link KdcRequest}. 097 * @throws IOException 098 */ 099 public byte[] encodeRequestBody( RequestBody requestBody ) throws IOException 100 { 101 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 102 ASN1OutputStream aos = new ASN1OutputStream( baos ); 103 104 aos.writeObject( encodeKdcRequestBody( requestBody ) ); 105 aos.close(); 106 107 return baos.toByteArray(); 108 } 109 110 111 /** 112 * KDC-REQ-BODY ::= SEQUENCE { 113 * kdc-options[0] KDCOptions, 114 * cname[1] PrincipalName OPTIONAL, 115 * -- Used only in AS-REQ 116 * realm[2] Realm, -- Server's realm 117 * -- Also client's in AS-REQ 118 * sname[3] PrincipalName OPTIONAL, 119 * from[4] KerberosTime OPTIONAL, 120 * till[5] KerberosTime, 121 * rtime[6] KerberosTime OPTIONAL, 122 * nonce[7] INTEGER, 123 * 124 * etype[8] SEQUENCE OF INTEGER, -- EncryptionEngine, 125 * -- in preference order 126 * addresses[9] HostAddresses OPTIONAL, 127 * enc-authorization-data[10] EncryptedData OPTIONAL, 128 * -- Encrypted AuthorizationData encoding 129 * additional-tickets[11] SEQUENCE OF Ticket OPTIONAL 130 * } 131 */ 132 private DERSequence encodeKdcRequestBody( RequestBody requestBody ) 133 { 134 DERSequence sequence = new DERSequence(); 135 136 sequence.add( new DERTaggedObject( 0, new DERBitString( requestBody.getKdcOptions().getBytes() ) ) ); 137 138 // OPTIONAL 139 if ( requestBody.getClientPrincipal() != null ) 140 { 141 sequence.add( new DERTaggedObject( 1, PrincipalNameEncoder.encode( requestBody.getClientPrincipal() ) ) ); 142 } 143 144 sequence.add( new DERTaggedObject( 2, DERGeneralString.valueOf( requestBody.getServerPrincipal().getRealm() 145 .toString() ) ) ); 146 147 // OPTIONAL 148 if ( requestBody.getServerPrincipal() != null ) 149 { 150 sequence.add( new DERTaggedObject( 3, PrincipalNameEncoder.encode( requestBody.getServerPrincipal() ) ) ); 151 } 152 153 // OPTIONAL 154 if ( requestBody.getFrom() != null ) 155 { 156 sequence.add( new DERTaggedObject( 4, KerberosTimeEncoder.encode( requestBody.getFrom() ) ) ); 157 } 158 159 sequence.add( new DERTaggedObject( 5, KerberosTimeEncoder.encode( requestBody.getTill() ) ) ); 160 161 // OPTIONAL 162 if ( requestBody.getRtime() != null ) 163 { 164 sequence.add( new DERTaggedObject( 6, KerberosTimeEncoder.encode( requestBody.getRtime() ) ) ); 165 } 166 167 sequence.add( new DERTaggedObject( 7, DERInteger.valueOf( requestBody.getNonce() ) ) ); 168 169 sequence.add( new DERTaggedObject( 8, EncryptionTypeEncoder.encode( requestBody.getEType() ) ) ); 170 171 // OPTIONAL 172 if ( requestBody.getAddresses() != null ) 173 { 174 sequence.add( new DERTaggedObject( 9, HostAddressesEncoder.encodeSequence( requestBody.getAddresses() ) ) ); 175 } 176 177 // OPTIONAL 178 if ( requestBody.getEncAuthorizationData() != null ) 179 { 180 sequence.add( new DERTaggedObject( 10, EncryptedDataEncoder.encodeSequence( requestBody 181 .getEncAuthorizationData() ) ) ); 182 } 183 184 // OPTIONAL 185 if ( requestBody.getAdditionalTickets() != null ) 186 { 187 sequence 188 .add( new DERTaggedObject( 11, TicketEncoder.encodeSequence( requestBody.getAdditionalTickets() ) ) ); 189 } 190 191 return sequence; 192 } 193 194 195 /* 196 PA-DATA ::= SEQUENCE { 197 padata-type[1] INTEGER, 198 padata-value[2] OCTET STRING, 199 -- might be encoded AP-REQ 200 }*/ 201 private DERSequence encodePreAuthData( PaData[] preAuthData ) 202 { 203 DERSequence preAuth = new DERSequence(); 204 205 for ( int ii = 0; ii < preAuthData.length; ii++ ) 206 { 207 DERSequence sequence = new DERSequence(); 208 209 sequence.add( new DERTaggedObject( 1, DERInteger.valueOf( preAuthData[ii].getPaDataType().getOrdinal() ) ) ); 210 sequence.add( new DERTaggedObject( 2, new DEROctetString( preAuthData[ii].getPaDataValue() ) ) ); 211 preAuth.add( sequence ); 212 } 213 214 return preAuth; 215 } 216 }