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.i18n.I18n;
033    import org.apache.directory.shared.ldap.name.DN;
034    import org.apache.directory.shared.ldap.util.StringTools;
035    import org.slf4j.Logger;
036    import org.slf4j.LoggerFactory;
037    
038    
039    /**
040     * This class implements the Certificate generation extended operation's ASN.1 grammer. 
041     * All the actions are declared in this class. As it is a singleton, 
042     * these declaration are only done once. The grammar is :
043     * 
044     * <pre>
045     *   CertGenerateObject ::= SEQUENCE 
046     *   {
047     *      targetDN        IA5String,
048     *      issuerDN        IA5String,
049     *      subjectDN       IA5String,
050     *      keyAlgorithm    IA5String
051     *   }
052     * </pre>
053     * 
054     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
055     * @version $Rev: 664290 $, $Date: 2008-06-07 11:58:06 +0530 (Sat, 07 Jun 2008) $, 
056     */
057    
058    public class CertGenerationGrammar extends AbstractGrammar
059    {
060    
061        /** logger */
062        private static final Logger LOG = LoggerFactory.getLogger( CertGenerationGrammar.class );
063    
064        /** Speedup for logs */
065        static final boolean IS_DEBUG = LOG.isDebugEnabled();
066    
067        /** The instance of grammar. CertGenerationObjectGrammar is a singleton */
068        private static IGrammar instance = new CertGenerationGrammar();
069    
070    
071        public CertGenerationGrammar()
072        {
073            name = CertGenerationGrammar.class.getName();
074            statesEnum = CertGenerationStatesEnum.getInstance();
075    
076            // Create the transitions table
077            super.transitions = new GrammarTransition[CertGenerationStatesEnum.LAST_CERT_GENERATION_STATE][256];
078    
079            /**
080             * Transition from init state to certificate generation
081             * 
082             * CertGenerationObject ::= SEQUENCE {
083             *     ...
084             *     
085             * Creates the CertGenerationObject object
086             */
087            super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
088                IStates.INIT_GRAMMAR_STATE, CertGenerationStatesEnum.CERT_GENERATION_REQUEST_SEQUENCE_STATE,
089                UniversalTag.SEQUENCE_TAG, new GrammarAction( "Init CertGenerationObject" )
090                {
091                    public void action( IAsn1Container container )
092                    {
093                        CertGenerationContainer certGenContainer = ( CertGenerationContainer ) container;
094                        CertGenerationObject certGenerationObject = new CertGenerationObject();
095                        certGenContainer.setCertGenerationObject( certGenerationObject );
096                    }
097                } );
098    
099            /**
100             * Transition from certificate generation request to targetDN
101             *
102             * CertGenerationObject ::= SEQUENCE { 
103             *     targetDN IA5String,
104             *     ...
105             *     
106             * Set the targetDN value into the CertGenerationObject instance.
107             */
108            super.transitions[CertGenerationStatesEnum.CERT_GENERATION_REQUEST_SEQUENCE_STATE][UniversalTag.OCTET_STRING] = new GrammarTransition(
109                CertGenerationStatesEnum.CERT_GENERATION_REQUEST_SEQUENCE_STATE, CertGenerationStatesEnum.TARGETDN_STATE,
110                UniversalTag.OCTET_STRING, new GrammarAction( "Set Cert Generation target DN value" )
111                {
112                    public void action( IAsn1Container container ) throws DecoderException
113                    {
114                        CertGenerationContainer CertGenContainer = ( CertGenerationContainer ) container;
115                        Value value = CertGenContainer.getCurrentTLV().getValue();
116    
117                        String targetDN = StringTools.utf8ToString( value.getData() );
118    
119                        if ( IS_DEBUG )
120                        {
121                            LOG.debug( "Target DN = " + targetDN );
122                        }
123    
124                        if ( ( targetDN != null ) && ( targetDN.trim().length() > 0 ) )
125                        {
126                            if( !DN.isValid( targetDN ) )
127                            {
128                                String msg = I18n.err( I18n.ERR_04032, targetDN );
129                                LOG.error( msg );
130                                throw new DecoderException( msg );
131                            }
132                            
133                            CertGenContainer.getCertGenerationObject().setTargetDN( targetDN );
134                        }
135                        else
136                        {
137                            String msg = I18n.err( I18n.ERR_04033, 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( !DN.isValid( issuerDN ) )
173                            {
174                                String msg = I18n.err( I18n.ERR_04034, 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( !DN.isValid( subjectDN ) )
213                            {
214                                String msg = I18n.err( I18n.ERR_04035, subjectDN );
215                                LOG.error( msg );
216                                throw new DecoderException( msg );
217                            }
218    
219                            CertGenContainer.getCertGenerationObject().setSubjectDN( subjectDN );
220                        }
221                        else
222                        {
223                            String msg = I18n.err( I18n.ERR_04033, StringTools.dumpBytes( value.getData() ) );
224                            LOG.error( msg );
225                            throw new DecoderException( msg );
226                        }
227                    }
228                } );
229    
230            /**
231             * Transition from subjectDN state to keyAlgo
232             *
233             * CertGenerationObject ::= SEQUENCE { 
234             *     ...
235             *     keyAlgorithm IA5String
236             *     
237             * Set the key algorithm value into the CertGenerationObject instance.
238             */
239            super.transitions[CertGenerationStatesEnum.SUBJECT_STATE][UniversalTag.OCTET_STRING] = new GrammarTransition(
240                CertGenerationStatesEnum.SUBJECT_STATE, CertGenerationStatesEnum.KEY_ALGORITHM_STATE,
241                UniversalTag.OCTET_STRING, new GrammarAction( "Set Cert Generation key algorithm value" )
242                {
243                    public void action( IAsn1Container container ) throws DecoderException
244                    {
245                        CertGenerationContainer CertGenContainer = ( CertGenerationContainer ) container;
246                        Value value = CertGenContainer.getCurrentTLV().getValue();
247    
248                        String keyAlgorithm = StringTools.utf8ToString( value.getData() );
249    
250                        if ( IS_DEBUG )
251                        {
252                            LOG.debug( "key algorithm = " + keyAlgorithm );
253                        }
254    
255                        if ( keyAlgorithm != null && ( keyAlgorithm.trim().length() > 0 ) )
256                        {
257                            CertGenContainer.getCertGenerationObject().setKeyAlgorithm( keyAlgorithm );
258                        }
259    
260                        CertGenContainer.grammarEndAllowed( true );
261                    }
262                } );
263    
264        }
265    
266    
267        /**
268         * This class is a singleton.
269         * 
270         * @return An instance on this grammar
271         */
272        public static IGrammar getInstance()
273        {
274            return instance;
275        }
276    }