001    package org.apache.geronimo.tomcat;
002    
003    import java.util.Map;
004    import javax.net.ssl.KeyManagerFactory;
005    
006    import org.apache.geronimo.management.geronimo.SecureConnector;
007    import org.apache.geronimo.management.geronimo.WebManager;
008    import org.apache.geronimo.system.serverinfo.ServerInfo;
009    import org.apache.geronimo.gbean.GBeanInfo;
010    import org.apache.geronimo.gbean.GBeanInfoBuilder;
011    
012    /**
013     * A wrapper around a connector for the HTTPS protocol for Tomcat.  The
014     * functionality is not different than the standard ConnectorGBean, but
015     * there's an additional set of HTTPS attributes exposed.
016     *
017     * @version $Revision: 1.0$
018     */
019    public class HttpsConnectorGBean extends ConnectorGBean implements TomcatSecureConnector {
020        private final ServerInfo serverInfo;
021        private String keystoreFileName;
022        private String truststoreFileName;
023        private String algorithm;
024    
025        public HttpsConnectorGBean(String name, String protocol, String host, int port, TomcatContainer container, ServerInfo serverInfo) throws Exception {
026            super(name, protocol, host, port, container);
027    
028            if (serverInfo == null){
029                throw new IllegalArgumentException("serverInfo cannot be null.");
030            }
031    
032            this.serverInfo = serverInfo;
033        }
034    
035        /**
036         * Adds any special parameters before constructing the connector.
037         *
038         * @param protocol Should be one of the constants from WebContainer.
039         * @param params   The map of parameters that will be used to initialize the connector.
040         */
041        protected void initializeParams(String protocol, Map params) {
042            super.initializeParams(protocol, params);
043            params.put("scheme", "https");
044            params.put("secure", "true");
045        }
046    
047        /**
048         * Ensures that this implementation can handle the requested protocol.
049         *
050         * @param protocol
051         */
052        protected void validateProtocol(String protocol) {
053            if(protocol != null && !protocol.equals(WebManager.PROTOCOL_HTTPS)) {
054                throw new IllegalStateException("HttpsConnectorGBean only supports "+WebManager.PROTOCOL_HTTPS);
055            }
056        }
057    
058        /**
059         * Gets the name of the keystore file that holds the server certificate
060         * (and by default, the trusted CA certificates used for client certificate
061         * authentication).  This is relative to the Geronimo home directory.
062         */
063        public String getKeystoreFileName() {
064            return keystoreFileName; // don't look it up as we need it to be relative
065        }
066    
067        /**
068         * Sets the name of the keystore file that holds the server certificate
069         * (and by default, the trusted CA certificates used for client certificate
070         * authentication).  This is relative to the Geronimo home directory.
071         */
072        public void setKeystoreFileName(String name) {
073            keystoreFileName = name;
074            connector.setAttribute("keystoreFile", serverInfo.resolveServerPath(keystoreFileName));
075        }
076    
077        public String getTruststoreFileName() {
078            return truststoreFileName; // don't look it up as we need it to be relative
079        }
080    
081        public void setTruststoreFileName(String name) {
082            truststoreFileName = name;
083            connector.setAttribute("truststoreFile", serverInfo.resolveServerPath(truststoreFileName));
084        }
085    
086        /**
087         * Sets the password used to access the keystore, and by default, used to
088         * access the server private key inside the keystore.  Not all connectors
089         * support configuring different passwords for those two features; if so,
090         * a separate PrivateKeyPassword should be defined in an
091         * implementation-specific connector interface.
092         */
093        public void setKeystorePassword(String password) {
094            connector.setAttribute("keystorePass", password);
095        }
096    
097        public void setTruststorePassword(String password) {
098            connector.setAttribute("truststorePass", password);
099        }
100    
101        /**
102         * Gets the format of the entries in the keystore.  The default format for
103         * Java keystores is JKS, though some connector implementations support
104         * PCKS12 (and possibly other formats).
105         */
106        public String getKeystoreType() {
107            return (String)connector.getAttribute("keystoreType");
108        }
109    
110        /**
111         * Sets the format of the entries in the keystore.  The default format for
112         * Java keystores is JKS, though some connector implementations support
113         * PCKS12 (and possibly other formats).
114         */
115        public void setKeystoreType(String type) {
116            connector.setAttribute("keystoreType", type);
117        }
118    
119        public String getTruststoreType() {
120            return (String)connector.getAttribute("truststoreType");
121        }
122    
123        public void setTruststoreType(String type) {
124            connector.setAttribute("truststoreType", type);
125        }
126    
127        /**
128         * Gets the certificate algorithm used to access the keystore.  This may
129         * be different for different JVM vendors, but should not usually be
130         * changed otherwise.
131         */
132        public String getAlgorithm() {
133            return algorithm;
134        }
135    
136        /**
137         * Sets the certificate algorithm used to access the keystore.  This may
138         * be different for different JVM vendors, but should not usually be
139         * changed otherwise.
140         */
141        public void setAlgorithm(String algorithm) {
142            this.algorithm = algorithm;
143            if ("default".equalsIgnoreCase(algorithm)) {
144                algorithm = KeyManagerFactory.getDefaultAlgorithm();
145            }
146            connector.setAttribute("algorithm", algorithm);
147        }
148    
149        /**
150         * Gets the protocol used for secure communication.  This should usually
151         * be TLS, though some JVM implementations (particularly some of IBM's)
152         * may not be compatible with popular browsers unless this is changed to
153         * SSL.
154         */
155        public String getSecureProtocol() {
156            return (String)connector.getAttribute("sslProtocol");
157        }
158    
159        /**
160         * Gets the protocol used for secure communication.  This should usually
161         * be TLS, though some JVM implementations (particularly some of IBM's)
162         * may not be compatible with popular browsers unless this is changed to
163         * SSL.  Don't change it if you're not having problems.
164         */
165        public void setSecureProtocol(String protocol) {
166            connector.setAttribute("sslProtocol", protocol);
167        }
168    
169        /**
170         * Checks whether clients are required to authenticate using client
171         * certificates in order to connect using this connector.  If enabled,
172         * client certificates are validated using the trust store, which defaults
173         * to the same keystore file, keystore type, and keystore password as the
174         * regular keystore.  Some connector implementations may allow you to
175         * configure those 3 values separately to use a different trust store.
176         */
177        public boolean isClientAuthRequired() {
178            Object value = connector.getAttribute("clientAuth");
179            return value == null ? false : new Boolean(value.toString()).booleanValue();
180        }
181    
182        /**
183         * Checks whether clients are required to authenticate using client
184         * certificates in order to connect using this connector.  If enabled,
185         * client certificates are validated using the trust store, which defaults
186         * to the same keystore file, keystore type, and keystore password as the
187         * regular keystore.  Some connector implementations may allow you to
188         * configure those 3 values separately to use a different trust store.
189         */
190        public void setClientAuthRequired(boolean clientCert) {
191            connector.setAttribute("clientAuth", new Boolean(clientCert));
192        }
193    
194        /**
195         * Gets a comma seperated list of the encryption ciphers that may be used. If not
196         * specified, then any available cipher may be used.
197         */
198         public String getCiphers() {
199            return (String)connector.getAttribute("ciphers");
200        }
201    
202        /**
203         * Sets a comma seperated list of the encryption ciphers that may be used. If not
204         * specified, then any available cipher may be used.
205         */
206         public void setCiphers(String ciphers) {
207            connector.setAttribute("ciphers", ciphers);
208        }
209    
210        public static final GBeanInfo GBEAN_INFO;
211    
212        static {
213            GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic("Tomcat Connector", HttpsConnectorGBean.class, ConnectorGBean.GBEAN_INFO);
214            infoFactory.addAttribute("keystoreFileName", String.class, true, true);
215            infoFactory.addAttribute("truststoreFileName", String.class, true, true);
216            infoFactory.addAttribute("algorithm", String.class, true, true);
217            infoFactory.addAttribute("keystorePassword", String.class, true, true);
218            infoFactory.addAttribute("truststorePassword", String.class, true, true);
219    // todo should we support this?
220    //        infoFactory.addAttribute("keyPassword", String.class, true, true);
221            infoFactory.addAttribute("secureProtocol", String.class, true, true);
222            infoFactory.addAttribute("keystoreType", String.class, true, true);
223            infoFactory.addAttribute("truststoreType", String.class, true, true);
224            infoFactory.addAttribute("clientAuthRequired", boolean.class, true, true);
225            infoFactory.addAttribute("ciphers", String.class, true, true);
226            infoFactory.addInterface(TomcatSecureConnector.class);
227    
228            infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean");
229            infoFactory.setConstructor(new String[] { "name", "protocol", "host", "port", "TomcatContainer", "ServerInfo"});
230            GBEAN_INFO = infoFactory.getBeanInfo();
231        }
232    
233        public static GBeanInfo getGBeanInfo() {
234            return GBEAN_INFO;
235        }
236    }