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.messages;
021
022
023import java.nio.ByteBuffer;
024
025import org.apache.directory.api.asn1.Asn1Object;
026import org.apache.directory.api.asn1.EncoderException;
027import org.apache.directory.api.asn1.ber.tlv.BerValue;
028import org.apache.directory.api.asn1.ber.tlv.TLV;
029import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
030import org.apache.directory.api.util.Strings;
031import org.apache.directory.shared.kerberos.KerberosConstants;
032import org.apache.directory.shared.kerberos.components.PrincipalName;
033
034
035/**
036 * Change password data structure
037 * 
038 * ChangePasswdData ::=  SEQUENCE {
039 *       newpasswd[0]   OCTET STRING,
040 *       targname[1]    PrincipalName OPTIONAL,
041 *       targrealm[2]   Realm OPTIONAL
042 *     }
043 *     
044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045 */
046public class ChangePasswdData implements Asn1Object
047{
048
049    /** the new password */
050    private byte[] newPasswd;
051
052    /** principal name of the client */
053    private PrincipalName targName;
054
055    /** name of client's realm */
056    private String targRealm;
057
058    private int newPasswdLen;
059    private int targNameLen;
060    private int targRealmLen;
061    private int seqLen;
062
063
064    public ChangePasswdData()
065    {
066    }
067
068
069    /**
070     * Compute the ChangePasswdData length
071     * <pre>
072     * ChangePasswdData :
073     *
074     * 0x30 L1 ChangePasswdData sequence
075     *  |
076     *  +--&gt; 0xA0 L2 newPasswd tag
077     *  |     |
078     *  |     +--&gt; 0x04 L2-1 newPasswd (Octet string)
079     *  |
080     *  +--&gt; 0xA1 L3 targName tag
081     *  |     |
082     *  |     +--&gt; 0x30 L3-1 targName (PrincipalName)
083     *  |
084     *  +--&gt; 0xA2 L4 targRealm tag
085     *        |
086     *        +--&gt; 0x1B L4-1 targRealm (KerberosString)
087     * </pre>
088     */
089    @Override
090    public int computeLength()
091    {
092        newPasswdLen = 1 + TLV.getNbBytes( newPasswd.length ) + newPasswd.length;
093
094        seqLen = 1 + TLV.getNbBytes( newPasswdLen ) + newPasswdLen;
095
096        if ( targName != null )
097        {
098            targNameLen = targName.computeLength();
099            seqLen += 1 + TLV.getNbBytes( targNameLen ) + targNameLen;
100        }
101
102        if ( targRealm != null )
103        {
104            targRealmLen = Strings.getBytesUtf8( targRealm ).length;
105            targRealmLen = 1 + TLV.getNbBytes( targRealmLen ) + targRealmLen;
106            seqLen += 1 + TLV.getNbBytes( targRealmLen ) + targRealmLen;
107        }
108
109        return 1 + TLV.getNbBytes( seqLen ) + seqLen;
110    }
111
112
113    @Override
114    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
115    {
116        if ( buffer == null )
117        {
118            buffer = ByteBuffer.allocate( computeLength() );
119        }
120
121        // ChangePasswdData
122        buffer.put( UniversalTag.SEQUENCE.getValue() );
123        buffer.put( BerValue.getBytes( seqLen ) );
124
125        // newpasswd
126        buffer.put( ( byte ) KerberosConstants.CHNGPWD_NEWPWD_TAG );
127        buffer.put( BerValue.getBytes( newPasswdLen ) );
128        BerValue.encode( buffer, newPasswd );
129
130        if ( targName != null )
131        {
132            buffer.put( ( byte ) KerberosConstants.CHNGPWD_TARGNAME_TAG );
133            buffer.put( BerValue.getBytes( targNameLen ) );
134
135            targName.encode( buffer );
136        }
137
138        if ( targRealm != null )
139        {
140            buffer.put( ( byte ) KerberosConstants.CHNGPWD_TARGREALM_TAG );
141            buffer.put( BerValue.getBytes( targRealmLen ) );
142            buffer.put( UniversalTag.GENERAL_STRING.getValue() );
143            buffer.put( BerValue.getBytes( targRealmLen - 2 ) );
144            buffer.put( Strings.getBytesUtf8( targRealm ) );
145        }
146
147        return buffer;
148    }
149
150
151    public byte[] getNewPasswd()
152    {
153        return newPasswd;
154    }
155
156
157    public void setNewPasswd( byte[] newPasswd )
158    {
159        this.newPasswd = newPasswd;
160    }
161
162
163    public PrincipalName getTargName()
164    {
165        return targName;
166    }
167
168
169    public void setTargName( PrincipalName targName )
170    {
171        this.targName = targName;
172    }
173
174
175    public String getTargRealm()
176    {
177        return targRealm;
178    }
179
180
181    public void setTargRealm( String targRealm )
182    {
183        this.targRealm = targRealm;
184    }
185
186
187    /**
188     * @see Object#toString()
189     */
190    public String toString()
191    {
192        StringBuilder sb = new StringBuilder();
193
194        sb.append( "ChangePasswdData : \n" );
195
196        sb.append( "    newPasswd : " ).append( Strings.utf8ToString( newPasswd ) ).append( '\n' );
197        sb.append( "    targName : " ).append( targName ).append( '\n' );
198        sb.append( "    targRealm : " ).append( targRealm ).append( '\n' );
199
200        return sb.toString();
201    }
202}