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.messages.value; 021 022 023 import java.nio.BufferOverflowException; 024 import java.nio.ByteBuffer; 025 026 import org.apache.directory.server.i18n.I18n; 027 import org.apache.directory.server.kerberos.shared.messages.value.types.TransitedEncodingType; 028 import org.apache.directory.shared.asn1.AbstractAsn1Object; 029 import org.apache.directory.shared.asn1.ber.tlv.TLV; 030 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag; 031 import org.apache.directory.shared.asn1.ber.tlv.Value; 032 import org.apache.directory.shared.asn1.codec.EncoderException; 033 import org.apache.directory.shared.ldap.util.StringTools; 034 import org.slf4j.Logger; 035 import org.slf4j.LoggerFactory; 036 037 038 /** 039 * The TransitedEncoding structure. 040 * 041 * The ASN.1 grammar is : 042 * 043 * -- encoded Transited field 044 * TransitedEncoding ::= SEQUENCE { 045 * tr-type [0] Int32 -- must be registered --, 046 * contents [1] OCTET STRING 047 * } 048 * 049 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 050 * @version $Rev: 902575 $, $Date: 2010-01-24 15:38:06 +0100 (Sun, 24 Jan 2010) $ 051 */ 052 public class TransitedEncoding extends AbstractAsn1Object 053 { 054 /** The logger */ 055 private static final Logger log = LoggerFactory.getLogger( TransitedEncoding.class ); 056 057 /** Speedup for logs */ 058 private static final boolean IS_DEBUG = log.isDebugEnabled(); 059 060 /** The transited type. One of : 061 * NULL 062 * DOMAIN_X500_COMPRESS 063 */ 064 private TransitedEncodingType trType; 065 066 /** The transited data */ 067 private byte[] contents; 068 069 // Storage for computed lengths 070 private transient int trTypeLength; 071 private transient int contentsLength; 072 private transient int transitedEncodingLength; 073 074 075 /** 076 * Creates a new instance of TransitedEncoding. 077 */ 078 public TransitedEncoding() 079 { 080 trType = TransitedEncodingType.NULL; 081 contents = new byte[0]; 082 } 083 084 085 /** 086 * Creates a new instance of TransitedEncoding. 087 * 088 * @param trType 089 * @param contents 090 */ 091 public TransitedEncoding( TransitedEncodingType trType, byte[] contents ) 092 { 093 this.trType = trType; 094 this.contents = contents; 095 } 096 097 098 /** 099 * Returns the contents. 100 * 101 * @return The contents. 102 */ 103 public byte[] getContents() 104 { 105 return contents; 106 } 107 108 109 /** 110 * Set the contents 111 * @param contents The contents 112 */ 113 public void setContents( byte[] contents ) 114 { 115 this.contents = contents; 116 } 117 118 119 /** 120 * Returns the {@link TransitedEncodingType}. 121 * 122 * @return The {@link TransitedEncodingType}. 123 */ 124 public TransitedEncodingType getTrType() 125 { 126 return trType; 127 } 128 129 130 /** 131 * Set the transited encoding type 132 * @param trType The transited encoding type 133 */ 134 public void setTrType( TransitedEncodingType trType ) 135 { 136 this.trType = trType; 137 } 138 139 140 /** 141 * Compute the TransitedEncoding length 142 * 143 * TransitedEncoding : 144 * 145 * 0x30 L1 TransitedEncoding 146 * | 147 * +--> 0xA0 L2 trType tag 148 * | | 149 * | +--> 0x02 L2-1 trType (int) 150 * | 151 * +--> 0xA1 L3 contents tag 152 * | 153 * +--> 0x04 L3-1 contents (OCTET STRING) 154 * 155 * where L1 = L2 + lenght(0xA0) + length(L2) + 156 * L3 + lenght(0xA1) + length(L3) 157 * and 158 * L2 = L2-1 + length(0x02) + length( L2-1) 159 * L3 = L3-1 + length(0x04) + length( L3-1) 160 */ 161 public int computeLength() 162 { 163 // Compute the trType. The Length will always be contained in 1 byte 164 trTypeLength = 1 + 1 + Value.getNbBytes( trType.getOrdinal() ); 165 transitedEncodingLength = 1 + TLV.getNbBytes( trTypeLength ) + trTypeLength; 166 167 // Compute the keyValue 168 if ( contents == null ) 169 { 170 contentsLength = 1 + 1; 171 } 172 else 173 { 174 contentsLength = 1 + TLV.getNbBytes( contents.length ) + contents.length; 175 } 176 177 transitedEncodingLength += 1 + TLV.getNbBytes( contentsLength ) + contentsLength; 178 179 // Compute the whole sequence length 180 int transitedEncodingSeqLength = 1 + Value.getNbBytes( transitedEncodingLength ) + transitedEncodingLength; 181 182 return transitedEncodingSeqLength; 183 184 } 185 186 187 /** 188 * Encode the TransitedEncoding message to a PDU. 189 * 190 * TransitedEncoding : 191 * 192 * 0x30 LL 193 * 0xA0 LL 194 * 0x02 0x01 trType 195 * 0xA1 LL 196 * 0x04 LL adData 197 * 198 * @param buffer The buffer where to put the PDU. It should have been allocated 199 * before, with the right size. 200 * @return The constructed PDU. 201 */ 202 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 203 { 204 if ( buffer == null ) 205 { 206 throw new EncoderException( I18n.err( I18n.ERR_148 ) ); 207 } 208 209 try 210 { 211 // The AuthorizationDataEntry SEQ Tag 212 buffer.put( UniversalTag.SEQUENCE_TAG ); 213 buffer.put( TLV.getBytes( transitedEncodingLength ) ); 214 215 // The tr-type, first the tag, then the value 216 buffer.put( ( byte ) 0xA0 ); 217 buffer.put( TLV.getBytes( trTypeLength ) ); 218 Value.encode( buffer, trType.getOrdinal() ); 219 220 // The contents, first the tag, then the value 221 buffer.put( ( byte ) 0xA1 ); 222 buffer.put( TLV.getBytes( contentsLength ) ); 223 Value.encode( buffer, contents ); 224 } 225 catch ( BufferOverflowException boe ) 226 { 227 log.error( I18n.err( I18n.ERR_147, 1 + TLV.getNbBytes( transitedEncodingLength ) 228 + transitedEncodingLength, buffer.capacity() ) ); 229 throw new EncoderException( I18n.err( I18n.ERR_138 ) ); 230 } 231 232 if ( IS_DEBUG ) 233 { 234 log.debug( "TransitedEncoding encoding : {}", StringTools.dumpBytes( buffer.array() ) ); 235 log.debug( "TransitedEncoding initial value : {}", toString() ); 236 } 237 238 return buffer; 239 } 240 241 242 /** 243 * @see Object#toString() 244 */ 245 public String toString() 246 { 247 StringBuilder sb = new StringBuilder(); 248 249 sb.append( "TransitedEncoding : {\n" ); 250 sb.append( " tr-type: " ).append( trType ).append( '\n' ); 251 252 sb.append( " contents: " ).append( StringTools.dumpBytes( contents ) ).append( "\n}\n" ); 253 254 return sb.toString(); 255 } 256 }