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.shared.ldap.codec.extended.operations.certGeneration;
021    
022    
023    import org.apache.directory.shared.asn1.ber.IAsn1Container;
024    import org.apache.directory.shared.asn1.ber.grammar.AbstractGrammar;
025    import org.apache.directory.shared.asn1.ber.grammar.GrammarAction;
026    import org.apache.directory.shared.asn1.ber.grammar.GrammarTransition;
027    import org.apache.directory.shared.asn1.ber.grammar.IGrammar;
028    import org.apache.directory.shared.asn1.ber.grammar.IStates;
029    import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
030    import org.apache.directory.shared.asn1.ber.tlv.Value;
031    import org.apache.directory.shared.asn1.codec.DecoderException;
032    import org.apache.directory.shared.ldap.name.LdapDN;
033    import org.apache.directory.shared.ldap.util.StringTools;
034    import org.slf4j.Logger;
035    import org.slf4j.LoggerFactory;
036    
037    
038    /**
039     * This class implements the Certificate generation extended operation's ASN.1 grammer. 
040     * All the actions are declared in this class. As it is a singleton, 
041     * these declaration are only done once. The grammar is :
042     * 
043     * <pre>
044     *   CertGenerateObject ::= SEQUENCE 
045     *   {
046     *      targetDN        IA5String,
047     *      issuerDN        IA5String,
048     *      subjectDN       IA5String,
049     *      keyAlgorithm    IA5String
050     *   }
051     * </pre>
052     * 
053     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
054     * @version $Rev: 664290 $, $Date: 2008-06-07 11:58:06 +0530 (Sat, 07 Jun 2008) $, 
055     */
056    
057    public class CertGenerationGrammar extends AbstractGrammar
058    {
059    
060        /** logger */
061        private static final Logger LOG = LoggerFactory.getLogger( CertGenerationGrammar.class );
062    
063        /** Speedup for logs */
064        static final boolean IS_DEBUG = LOG.isDebugEnabled();
065    
066        /** The instance of grammar. CertGenerationObjectGrammar is a singleton */
067        private static IGrammar instance = new CertGenerationGrammar();
068    
069    
070        public CertGenerationGrammar()
071        {
072            name = CertGenerationGrammar.class.getName();
073            statesEnum = CertGenerationStatesEnum.getInstance();
074    
075            // Create the transitions table
076            super.transitions = new GrammarTransition[CertGenerationStatesEnum.LAST_CERT_GENERATION_STATE][256];
077    
078            /**
079             * Transition from init state to certificate generation
080             * 
081             * CertGenerationObject ::= SEQUENCE {
082             *     ...
083             *     
084             * Creates the CertGenerationObject object
085             */
086            super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
087                IStates.INIT_GRAMMAR_STATE, CertGenerationStatesEnum.CERT_GENERATION_REQUEST_SEQUENCE_STATE,
088                UniversalTag.SEQUENCE_TAG, new GrammarAction( "Init CertGenerationObject" )
089                {
090                    public void action( IAsn1Container container )
091                    {
092                        CertGenerationContainer certGenContainer = ( CertGenerationContainer ) container;
093                        CertGenerationObject certGenerationObject = new CertGenerationObject();
094                        certGenContainer.setCertGenerationObject( certGenerationObject );
095                    }
096                } );
097    
098            /**
099             * Transition from certificate generation request to targetDN
100             *
101             * CertGenerationObject ::= SEQUENCE { 
102             *     targetDN IA5String,
103             *     ...
104             *     
105             * Set the targetDN value into the CertGenerationObject instance.
106             */
107            super.transitions[CertGenerationStatesEnum.CERT_GENERATION_REQUEST_SEQUENCE_STATE][UniversalTag.OCTET_STRING] = new GrammarTransition(
108                CertGenerationStatesEnum.CERT_GENERATION_REQUEST_SEQUENCE_STATE, CertGenerationStatesEnum.TARGETDN_STATE,
109                UniversalTag.OCTET_STRING, new GrammarAction( "Set Cert Generation target DN value" )
110                {
111                    public void action( IAsn1Container container ) throws DecoderException
112                    {
113                        CertGenerationContainer CertGenContainer = ( CertGenerationContainer ) container;
114                        Value value = CertGenContainer.getCurrentTLV().getValue();
115    
116                        String targetDN = StringTools.utf8ToString( value.getData() );
117    
118                        if ( IS_DEBUG )
119                        {
120                            LOG.debug( "Target DN = " + targetDN );
121                        }
122    
123                        if ( ( targetDN != null ) && ( targetDN.trim().length() > 0 ) )
124                        {
125                            if( !LdapDN.isValid( targetDN ) )
126                            {
127                                String msg = "invalid target DN " +  targetDN;
128                                LOG.error( msg );
129                                throw new DecoderException( msg );
130                            }
131                            
132                            CertGenContainer.getCertGenerationObject().setTargetDN( targetDN );
133                        }
134                        else
135                        {
136                            String msg = "failed to decode the target DN, it cannot be null or empty it is '"
137                                + StringTools.dumpBytes( value.getData() );
138                            LOG.error( msg );
139                            throw new DecoderException( msg );
140                        }
141                    }
142                } );
143    
144            /**
145             * Transition from targetDN state to issuerDN
146             *
147             * CertGenerationObject ::= SEQUENCE { 
148             *     ...
149             *     issuerDN IA5String,
150             *     ...
151             *     
152             * Set the issuerDN value into the CertGenerationObject instance.
153             */
154            super.transitions[CertGenerationStatesEnum.TARGETDN_STATE][UniversalTag.OCTET_STRING] = new GrammarTransition(
155                CertGenerationStatesEnum.TARGETDN_STATE, CertGenerationStatesEnum.ISSUER_STATE, UniversalTag.OCTET_STRING,
156                new GrammarAction( "Set Cert Generation issuer DN value" )
157                {
158                    public void action( IAsn1Container container ) throws DecoderException
159                    {
160                        CertGenerationContainer CertGenContainer = ( CertGenerationContainer ) container;
161                        Value value = CertGenContainer.getCurrentTLV().getValue();
162    
163                        String issuerDN = StringTools.utf8ToString( value.getData() );
164    
165                        if ( IS_DEBUG )
166                        {
167                            LOG.debug( "Issuer DN = " + issuerDN );
168                        }
169    
170                        if ( ( issuerDN != null ) && ( issuerDN.trim().length() > 0 ) )
171                        {
172                            if( !LdapDN.isValid( issuerDN ) )
173                            {
174                                String msg = "invalid issuer DN " +  issuerDN;
175                                LOG.error( msg );
176                                throw new DecoderException( msg );
177                            }
178                            
179                            CertGenContainer.getCertGenerationObject().setIssuerDN( issuerDN );
180                        }
181                    }
182                } );
183    
184            /**
185             * Transition from issuerDN state to subjectDN
186             *
187             * CertGenerationObject ::= SEQUENCE {
188             *     ... 
189             *     subjectDN IA5String,
190             *     ...
191             *     
192             * Set the subjectDN value into the CertGenerationObject instance.
193             */
194            super.transitions[CertGenerationStatesEnum.ISSUER_STATE][UniversalTag.OCTET_STRING] = new GrammarTransition(
195                CertGenerationStatesEnum.ISSUER_STATE, CertGenerationStatesEnum.SUBJECT_STATE, UniversalTag.OCTET_STRING,
196                new GrammarAction( "Set Cert Generation subject DN value" )
197                {
198                    public void action( IAsn1Container container ) throws DecoderException
199                    {
200                        CertGenerationContainer CertGenContainer = ( CertGenerationContainer ) container;
201                        Value value = CertGenContainer.getCurrentTLV().getValue();
202    
203                        String subjectDN = StringTools.utf8ToString( value.getData() );
204    
205                        if ( IS_DEBUG )
206                        {
207                            LOG.debug( "subject DN = " + subjectDN );
208                        }
209    
210                        if ( ( subjectDN != null ) && ( subjectDN.trim().length() > 0 ) )
211                        {
212                            if( !LdapDN.isValid( subjectDN ) )
213                            {
214                                String msg = "invalid subject DN " +  subjectDN;
215                                LOG.error( msg );
216                                throw new DecoderException( msg );
217                            }
218    
219                            CertGenContainer.getCertGenerationObject().setSubjectDN( subjectDN );
220                        }
221                        else
222                        {
223                            String msg = "failed to decode the subject DN, it cannot be null or empty it is '"
224                                + StringTools.dumpBytes( value.getData() );
225                            LOG.error( msg );
226                            throw new DecoderException( msg );
227                        }
228                    }
229                } );
230    
231            /**
232             * Transition from subjectDN state to keyAlgo
233             *
234             * CertGenerationObject ::= SEQUENCE { 
235             *     ...
236             *     keyAlgorithm IA5String
237             *     
238             * Set the key algorithm value into the CertGenerationObject instance.
239             */
240            super.transitions[CertGenerationStatesEnum.SUBJECT_STATE][UniversalTag.OCTET_STRING] = new GrammarTransition(
241                CertGenerationStatesEnum.SUBJECT_STATE, CertGenerationStatesEnum.KEY_ALGORITHM_STATE,
242                UniversalTag.OCTET_STRING, new GrammarAction( "Set Cert Generation key algorithm value" )
243                {
244                    public void action( IAsn1Container container ) throws DecoderException
245                    {
246                        CertGenerationContainer CertGenContainer = ( CertGenerationContainer ) container;
247                        Value value = CertGenContainer.getCurrentTLV().getValue();
248    
249                        String keyAlgorithm = StringTools.utf8ToString( value.getData() );
250    
251                        if ( IS_DEBUG )
252                        {
253                            LOG.debug( "key algorithm = " + keyAlgorithm );
254                        }
255    
256                        if ( keyAlgorithm != null && ( keyAlgorithm.trim().length() > 0 ) )
257                        {
258                            CertGenContainer.getCertGenerationObject().setKeyAlgorithm( keyAlgorithm );
259                        }
260    
261                        CertGenContainer.grammarEndAllowed( true );
262                    }
263                } );
264    
265        }
266    
267    
268        /**
269         * This class is a singleton.
270         * 
271         * @return An instance on this grammar
272         */
273        public static IGrammar getInstance()
274        {
275            return instance;
276        }
277    }