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.api.ldap.extras.extended.ads_impl.certGeneration;
021
022
023import org.apache.directory.api.asn1.DecoderException;
024import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
025import org.apache.directory.api.asn1.ber.grammar.Grammar;
026import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
027import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
028import org.apache.directory.api.asn1.ber.tlv.BerValue;
029import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
030import org.apache.directory.api.i18n.I18n;
031import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
032import org.apache.directory.api.ldap.extras.extended.certGeneration.CertGenerationRequestImpl;
033import org.apache.directory.api.ldap.model.name.Dn;
034import org.apache.directory.api.util.Strings;
035import org.slf4j.Logger;
036import 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 */
056
057public class CertGenerationGrammar extends AbstractGrammar<CertGenerationContainer>
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 Grammar<CertGenerationContainer> instance = new CertGenerationGrammar();
068
069
070    @SuppressWarnings("unchecked")
071    public CertGenerationGrammar()
072    {
073        setName( CertGenerationGrammar.class.getName() );
074
075        // Create the transitions table
076        super.transitions = new GrammarTransition[CertGenerationStatesEnum.LAST_CERT_GENERATION_STATE.ordinal()][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[CertGenerationStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
087            new GrammarTransition<CertGenerationContainer>(
088                CertGenerationStatesEnum.START_STATE, CertGenerationStatesEnum.CERT_GENERATION_REQUEST_SEQUENCE_STATE,
089                UniversalTag.SEQUENCE.getValue(), new GrammarAction<CertGenerationContainer>(
090                    "Init CertGenerationObject" )
091                {
092                    public void action( CertGenerationContainer container )
093                    {
094                        CertGenerationRequestDecorator certGenerationRequest = new CertGenerationRequestDecorator(
095                            LdapApiServiceFactory.getSingleton(), new CertGenerationRequestImpl() );
096                        container.setCertGenerationRequest( certGenerationRequest );
097                    }
098                } );
099
100        /**
101         * Transition from certificate generation request to targetDN
102         *
103         * CertGenerationObject ::= SEQUENCE { 
104         *     targetDN IA5String,
105         *     ...
106         *     
107         * Set the targetDN value into the CertGenerationObject instance.
108         */
109        super.transitions[CertGenerationStatesEnum.CERT_GENERATION_REQUEST_SEQUENCE_STATE.ordinal()][UniversalTag.OCTET_STRING
110            .getValue()] =
111            new GrammarTransition<CertGenerationContainer>(
112                CertGenerationStatesEnum.CERT_GENERATION_REQUEST_SEQUENCE_STATE,
113                CertGenerationStatesEnum.TARGETDN_STATE, UniversalTag.OCTET_STRING.getValue(),
114                new GrammarAction<CertGenerationContainer>( "Set Cert Generation target Dn value" )
115                {
116                    public void action( CertGenerationContainer container ) throws DecoderException
117                    {
118                        BerValue value = container.getCurrentTLV().getValue();
119
120                        String targetDN = Strings.utf8ToString( value.getData() );
121
122                        if ( IS_DEBUG )
123                        {
124                            LOG.debug( "Target Dn = " + targetDN );
125                        }
126
127                        if ( ( targetDN != null ) && ( targetDN.trim().length() > 0 ) )
128                        {
129                            if ( !Dn.isValid( targetDN ) )
130                            {
131                                String msg = I18n.err( I18n.ERR_04032, targetDN );
132                                LOG.error( msg );
133                                throw new DecoderException( msg );
134                            }
135
136                            container.getCertGenerationRequest().setTargetDN( targetDN );
137                        }
138                        else
139                        {
140                            String msg = I18n.err( I18n.ERR_04033, Strings.dumpBytes( value.getData() ) );
141                            LOG.error( msg );
142                            throw new DecoderException( msg );
143                        }
144                    }
145                } );
146
147        /**
148         * Transition from targetDN state to issuerDN
149         *
150         * CertGenerationObject ::= SEQUENCE { 
151         *     ...
152         *     issuerDN IA5String,
153         *     ...
154         *     
155         * Set the issuerDN value into the CertGenerationObject instance.
156         */
157        super.transitions[CertGenerationStatesEnum.TARGETDN_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
158            new GrammarTransition<CertGenerationContainer>( CertGenerationStatesEnum.TARGETDN_STATE,
159                CertGenerationStatesEnum.ISSUER_STATE, UniversalTag.OCTET_STRING.getValue(),
160                new GrammarAction<CertGenerationContainer>( "Set Cert Generation issuer Dn value" )
161                {
162                    public void action( CertGenerationContainer container ) throws DecoderException
163                    {
164                        BerValue value = container.getCurrentTLV().getValue();
165
166                        String issuerDN = Strings.utf8ToString( value.getData() );
167
168                        if ( IS_DEBUG )
169                        {
170                            LOG.debug( "Issuer Dn = " + issuerDN );
171                        }
172
173                        if ( ( issuerDN != null ) && ( issuerDN.trim().length() > 0 ) )
174                        {
175                            if ( !Dn.isValid( issuerDN ) )
176                            {
177                                String msg = I18n.err( I18n.ERR_04034, issuerDN );
178                                LOG.error( msg );
179                                throw new DecoderException( msg );
180                            }
181
182                            container.getCertGenerationRequest().setIssuerDN( issuerDN );
183                        }
184                    }
185                } );
186
187        /**
188         * Transition from issuerDN state to subjectDN
189         *
190         * CertGenerationObject ::= SEQUENCE {
191         *     ... 
192         *     subjectDN IA5String,
193         *     ...
194         *     
195         * Set the subjectDN value into the CertGenerationObject instance.
196         */
197        super.transitions[CertGenerationStatesEnum.ISSUER_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
198            new GrammarTransition<CertGenerationContainer>( CertGenerationStatesEnum.ISSUER_STATE,
199                CertGenerationStatesEnum.SUBJECT_STATE, UniversalTag.OCTET_STRING.getValue(),
200                new GrammarAction<CertGenerationContainer>( "Set Cert Generation subject Dn value" )
201                {
202                    public void action( CertGenerationContainer container ) throws DecoderException
203                    {
204                        BerValue value = container.getCurrentTLV().getValue();
205
206                        String subjectDN = Strings.utf8ToString( value.getData() );
207
208                        if ( IS_DEBUG )
209                        {
210                            LOG.debug( "subject Dn = " + subjectDN );
211                        }
212
213                        if ( ( subjectDN != null ) && ( subjectDN.trim().length() > 0 ) )
214                        {
215                            if ( !Dn.isValid( subjectDN ) )
216                            {
217                                String msg = I18n.err( I18n.ERR_04035, subjectDN );
218                                LOG.error( msg );
219                                throw new DecoderException( msg );
220                            }
221
222                            container.getCertGenerationRequest().setSubjectDN( subjectDN );
223                        }
224                        else
225                        {
226                            String msg = I18n.err( I18n.ERR_04033, Strings.dumpBytes( value.getData() ) );
227                            LOG.error( msg );
228                            throw new DecoderException( msg );
229                        }
230                    }
231                } );
232
233        /**
234         * Transition from subjectDN state to keyAlgo
235         *
236         * CertGenerationObject ::= SEQUENCE { 
237         *     ...
238         *     keyAlgorithm IA5String
239         *     
240         * Set the key algorithm value into the CertGenerationObject instance.
241         */
242        super.transitions[CertGenerationStatesEnum.SUBJECT_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
243            new GrammarTransition<CertGenerationContainer>( CertGenerationStatesEnum.SUBJECT_STATE,
244                CertGenerationStatesEnum.KEY_ALGORITHM_STATE,
245                UniversalTag.OCTET_STRING.getValue(),
246                new GrammarAction<CertGenerationContainer>( "Set Cert Generation key algorithm value" )
247                {
248                    public void action( CertGenerationContainer container ) throws DecoderException
249                    {
250                        BerValue value = container.getCurrentTLV().getValue();
251
252                        String keyAlgorithm = Strings.utf8ToString( value.getData() );
253
254                        if ( IS_DEBUG )
255                        {
256                            LOG.debug( "key algorithm = " + keyAlgorithm );
257                        }
258
259                        if ( keyAlgorithm != null && ( keyAlgorithm.trim().length() > 0 ) )
260                        {
261                            container.getCertGenerationRequest().setKeyAlgorithm( keyAlgorithm );
262                        }
263
264                        container.setGrammarEndAllowed( true );
265                    }
266                } );
267
268    }
269
270
271    /**
272     * This class is a singleton.
273     * 
274     * @return An instance on this grammar
275     */
276    public static Grammar<CertGenerationContainer> getInstance()
277    {
278        return instance;
279    }
280}