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 */ 020package org.apache.directory.shared.kerberos.components; 021 022 023import java.nio.BufferOverflowException; 024import java.nio.ByteBuffer; 025 026import org.apache.directory.api.asn1.Asn1Object; 027import org.apache.directory.api.asn1.EncoderException; 028import org.apache.directory.api.asn1.ber.tlv.BerValue; 029import org.apache.directory.api.asn1.ber.tlv.TLV; 030import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 031import org.apache.directory.api.util.Strings; 032import org.apache.directory.server.i18n.I18n; 033import org.apache.directory.shared.kerberos.KerberosConstants; 034import org.apache.directory.shared.kerberos.codec.types.PaDataType; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038 039/** 040 * The Pre-Authentication data. The ASN.1 GRAMMAR IS : 041 * <pre> 042 * PA-DATA ::= SEQUENCE { 043 * -- NOTE: first tag is [1], not [0] 044 * padata-type [1] Int32, 045 * padata-value [2] OCTET STRING -- might be encoded AP-REQ 046 * } 047 * </pre> 048 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 049 */ 050public class PaData implements Asn1Object 051{ 052 /** The logger */ 053 private static final Logger log = LoggerFactory.getLogger( PaData.class ); 054 055 /** Speedup for logs */ 056 private static final boolean IS_DEBUG = log.isDebugEnabled(); 057 058 /** The Pre-authentication type */ 059 private PaDataType paDataType; 060 061 /** The authentication data */ 062 private byte[] paDataValue; 063 064 // Storage for computed lengths 065 private int paDataTypeTagLength; 066 private int paDataValueTagLength; 067 private int preAuthenticationDataSeqLength; 068 069 070 /** 071 * Creates a new instance of PreAuthenticationData. 072 */ 073 public PaData() 074 { 075 } 076 077 078 /** 079 * Creates a new instance of PreAuthenticationData. 080 * 081 * @param paDataType 082 * @param paDataValue 083 */ 084 public PaData( PaDataType paDataType, byte[] paDataValue ) 085 { 086 this.paDataType = paDataType; 087 this.paDataValue = paDataValue; 088 } 089 090 091 /** 092 * Returns the {@link PaDataType}. 093 * 094 * @return The {@link PaDataType}. 095 */ 096 public PaDataType getPaDataType() 097 { 098 return paDataType; 099 } 100 101 102 /** 103 * Set the PA-DATA type 104 * 105 * @param paDataType The PA-DATA type 106 */ 107 public void setPaDataType( int paDataType ) 108 { 109 this.paDataType = PaDataType.getTypeByValue( paDataType ); 110 } 111 112 113 /** 114 * Set the PA-DATA type 115 * 116 * @param paDataType The PA-DATA type 117 */ 118 public void setPaDataType( PaDataType paDataType ) 119 { 120 this.paDataType = paDataType; 121 } 122 123 124 /** 125 * Returns the raw bytes of the {@link PaData}. 126 * 127 * @return The raw bytes of the {@link PaData}. 128 */ 129 public byte[] getPaDataValue() 130 { 131 return paDataValue; 132 } 133 134 135 /** 136 * Set the PA-DATA value 137 * 138 * @param paDataValue The PA-DATA value 139 */ 140 public void setPaDataValue( byte[] paDataValue ) 141 { 142 this.paDataValue = paDataValue; 143 } 144 145 146 /** 147 * Compute the PreAuthenticationData length 148 * <pre> 149 * PreAuthenticationData : 150 * 151 * 0x30 L1 PreAuthenticationData sequence 152 * | 153 * +--> 0xA0 L2 padata-type tag 154 * | | 155 * | +--> 0x02 L2-1 padata-type (int) 156 * | 157 * +--> 0xA1 L3 padata-value tag 158 * | 159 * +--> 0x04 L3-1 padata-value (OCTET STRING) 160 * 161 * where L1 = L2 + lenght(0xA0) + length(L2) + 162 * L3 + lenght(0xA1) + length(L3) 163 * and 164 * L2 = L2-1 + length(0x02) + length( L2-1) 165 * L3 = L3-1 + length(0x04) + length( L3-1) 166 * </pre> 167 */ 168 public int computeLength() 169 { 170 // Compute the paDataType. The Length will always be contained in 1 byte 171 int paDataTypeLength = BerValue.getNbBytes( paDataType.getValue() ); 172 paDataTypeTagLength = 1 + TLV.getNbBytes( paDataTypeLength ) + paDataTypeLength; 173 preAuthenticationDataSeqLength = 1 + TLV.getNbBytes( paDataTypeTagLength ) + paDataTypeTagLength; 174 175 // Compute the paDataValue 176 if ( paDataValue == null ) 177 { 178 paDataValueTagLength = 1 + 1; 179 } 180 else 181 { 182 paDataValueTagLength = 1 + TLV.getNbBytes( paDataValue.length ) + paDataValue.length; 183 } 184 185 // Compute the whole sequence length 186 preAuthenticationDataSeqLength += 1 + TLV.getNbBytes( paDataValueTagLength ) + paDataValueTagLength; 187 188 return 1 + TLV.getNbBytes( preAuthenticationDataSeqLength ) + preAuthenticationDataSeqLength; 189 190 } 191 192 193 /** 194 * Encode the PreAuthenticationData message to a PDU. 195 * <pre> 196 * PreAuthenticationData : 197 * 198 * 0x30 LL 199 * 0xA1 LL 200 * 0x02 0x01 padata-type 201 * 0xA2 LL 202 * 0x04 LL padata-value 203 * </pre> 204 * @param buffer The buffer where to put the PDU. It should have been allocated 205 * before, with the right size. 206 * @return The constructed PDU. 207 */ 208 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 209 { 210 if ( buffer == null ) 211 { 212 throw new EncoderException( I18n.err( I18n.ERR_148 ) ); 213 } 214 215 try 216 { 217 // The PreAuthenticationData SEQ Tag 218 buffer.put( UniversalTag.SEQUENCE.getValue() ); 219 buffer.put( TLV.getBytes( preAuthenticationDataSeqLength ) ); 220 221 // The PaDataType, first the tag, then the value 222 buffer.put( ( byte ) KerberosConstants.PADATA_TYPE_TAG ); 223 buffer.put( TLV.getBytes( paDataTypeTagLength ) ); 224 BerValue.encode( buffer, paDataType.getValue() ); 225 226 // The PaDataValue, first the tag, then the value 227 buffer.put( ( byte ) KerberosConstants.PADATA_VALUE_TAG ); 228 buffer.put( TLV.getBytes( paDataValueTagLength ) ); 229 BerValue.encode( buffer, paDataValue ); 230 } 231 catch ( BufferOverflowException boe ) 232 { 233 log.error( I18n.err( I18n.ERR_145, 1 + TLV.getNbBytes( preAuthenticationDataSeqLength ) 234 + preAuthenticationDataSeqLength, buffer.capacity() ) ); 235 throw new EncoderException( I18n.err( I18n.ERR_138 ), boe ); 236 } 237 238 if ( IS_DEBUG ) 239 { 240 log.debug( "PreAuthenticationData encoding : {}", Strings.dumpBytes( buffer.array() ) ); 241 log.debug( "PreAuthenticationData initial value : {}", this ); 242 } 243 244 return buffer; 245 } 246 247 248 /** 249 * @see Object#toString() 250 */ 251 public String toString() 252 { 253 return toString( "" ); 254 } 255 256 257 /** 258 * @see Object#toString() 259 */ 260 public String toString( String tabs ) 261 { 262 StringBuilder sb = new StringBuilder(); 263 264 sb.append( tabs ).append( "PreAuthenticationData : \n" ); 265 sb.append( tabs ).append( " padata-type: " ).append( paDataType ).append( '\n' ); 266 267 if ( paDataValue != null ) 268 { 269 sb.append( tabs + " padata-value:" ).append( Strings.dumpBytes( paDataValue ) ).append( '\n' ); 270 } 271 272 return sb.toString(); 273 } 274}