1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.directory.server.integration.http;
22
23
24 import java.io.ByteArrayInputStream;
25 import java.io.File;
26 import java.io.FilenameFilter;
27 import java.io.InputStream;
28 import java.io.OutputStream;
29 import java.nio.file.Files;
30 import java.nio.file.Paths;
31 import java.security.KeyPair;
32 import java.security.KeyStore;
33 import java.security.cert.Certificate;
34 import java.security.cert.X509Certificate;
35 import java.util.Set;
36 import java.util.UUID;
37
38 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
39 import org.apache.directory.api.ldap.model.entry.Entry;
40 import org.apache.directory.api.ldap.model.name.Dn;
41 import org.apache.directory.server.bridge.http.HttpDirectoryService;
42 import org.apache.directory.server.constants.ServerDNConstants;
43 import org.apache.directory.server.core.api.DirectoryService;
44 import org.apache.directory.server.core.security.TlsKeyGenerator;
45 import org.apache.directory.server.i18n.I18n;
46 import org.apache.directory.server.protocol.shared.transport.TcpTransport;
47 import org.bouncycastle.jce.provider.X509CertParser;
48 import org.eclipse.jetty.server.Handler;
49 import org.eclipse.jetty.server.HttpConfiguration;
50 import org.eclipse.jetty.server.HttpConnectionFactory;
51 import org.eclipse.jetty.server.SecureRequestCustomizer;
52 import org.eclipse.jetty.server.Server;
53 import org.eclipse.jetty.server.ServerConnector;
54 import org.eclipse.jetty.server.SslConnectionFactory;
55 import org.eclipse.jetty.server.handler.ContextHandler;
56 import org.eclipse.jetty.server.handler.HandlerList;
57 import org.eclipse.jetty.util.ssl.SslContextFactory;
58 import org.eclipse.jetty.webapp.WebAppContext;
59 import org.eclipse.jetty.xml.XmlConfiguration;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63
64
65
66
67
68
69 public class HttpServer
70 {
71
72
73 private Server jetty;
74
75
76 private String confFile;
77
78
79 private Set<WebApp> webApps;
80
81
82 private TcpTransport httpTransport = null;
83
84
85 private TcpTransport httpsTransport = null;
86
87
88 public static final String HTTP_TRANSPORT_ID = "http";
89
90
91 public static final String HTTPS_TRANSPORT_ID = "https";
92
93
94 private boolean configured = false;
95
96 private static final Logger LOG = LoggerFactory.getLogger( HttpServer.class );
97
98 private DirectoryService dirService;
99
100
101 public HttpServer()
102 {
103 }
104
105
106
107
108
109
110
111
112 public void start( DirectoryService dirService ) throws Exception
113 {
114 this.dirService = dirService;
115
116 XmlConfiguration jettyConf = null;
117
118 if ( confFile != null )
119 {
120 InputStream input = Files.newInputStream( Paths.get( confFile ) );
121 jettyConf = new XmlConfiguration( input );
122
123 LOG.info( "configuring jetty http server from the configuration file {}", confFile );
124
125 try
126 {
127 jetty = new Server();
128 jettyConf.configure( jetty );
129 configured = true;
130 }
131 catch ( Exception e )
132 {
133 LOG.error( I18n.err( I18n.ERR_120 ) );
134 throw e;
135 }
136 }
137 else
138 {
139 LOG.info( "No configuration file set, looking for web apps" );
140 configureServerThroughCode();
141 }
142
143 if ( configured )
144 {
145 Handler[] handlers = jetty.getHandlers();
146
147 for ( Handler h : handlers )
148 {
149 if ( h instanceof ContextHandler )
150 {
151 ContextHandler ch = ( ContextHandler ) h;
152 ch.setAttribute( HttpDirectoryService.KEY, new HttpDirectoryService( dirService ) );
153 }
154 }
155
156 LOG.info( "starting jetty http server" );
157 jetty.start();
158 }
159 else
160 {
161 jetty = null;
162 LOG.warn( "Error while configuring the http server, skipping the http server startup" );
163 }
164 }
165
166
167
168
169
170 private void configureServerThroughCode()
171 {
172 try
173 {
174 jetty = new Server();
175
176 if ( httpTransport != null )
177 {
178 ServerConnector httpConnector = new ServerConnector( jetty );
179 httpConnector.setPort( httpTransport.getPort() );
180 httpConnector.setHost( httpTransport.getAddress() );
181 jetty.addConnector( httpConnector );
182 }
183
184 if ( httpsTransport != null )
185 {
186
187 Dn adminDn = dirService.getDnFactory().create( ServerDNConstants.ADMIN_SYSTEM_DN );
188 Entry adminEntry = dirService.getAdminSession().lookup( adminDn, SchemaConstants.ALL_USER_ATTRIBUTES,
189 SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES );
190
191 File confDir = dirService.getInstanceLayout().getConfDirectory();
192 File ksFile = new File( confDir, "httpserver.generated.ks" );
193
194 String password = UUID.randomUUID().toString();
195
196 KeyStore ks = KeyStore.getInstance( KeyStore.getDefaultType() );
197 ks.load( null, null );
198
199 X509CertParser parser = new X509CertParser();
200
201 parser.engineInit( new ByteArrayInputStream( adminEntry.get( TlsKeyGenerator.USER_CERTIFICATE_AT )
202 .getBytes() ) );
203
204 X509Certificate cert = ( X509Certificate ) parser.engineRead();
205
206 ks.setCertificateEntry( "cert", cert );
207
208 KeyPair keyPair = TlsKeyGenerator.getKeyPair( adminEntry );
209 ks.setKeyEntry( "privatekey", keyPair.getPrivate(), password.toCharArray(), new Certificate[]
210 { cert } );
211
212 try ( OutputStream stream = Files.newOutputStream( ksFile.toPath() ) )
213 {
214 ks.store( stream, password.toCharArray() );
215 }
216
217 SslContextFactory sslContextFactory = new SslContextFactory();
218 sslContextFactory.setKeyStoreType( KeyStore.getDefaultType() );
219 sslContextFactory.setKeyStorePath( ksFile.getAbsolutePath() );
220 sslContextFactory.setKeyStorePassword( password );
221 sslContextFactory.setKeyManagerPassword( password );
222
223 HttpConfiguration httpsConfiguration = new HttpConfiguration();
224 httpsConfiguration.setSecureScheme( HTTPS_TRANSPORT_ID );
225 httpsConfiguration.setSecurePort( httpsTransport.getPort() );
226 httpsConfiguration.addCustomizer( new SecureRequestCustomizer() );
227
228 ServerConnector httpsConnector = new ServerConnector( jetty, new SslConnectionFactory( sslContextFactory, "http/1.1" ), new HttpConnectionFactory( httpsConfiguration ) );
229 httpsConnector.setPort( httpsTransport.getPort() );
230 httpsConnector.setHost( httpsTransport.getAddress() );
231
232 jetty.addConnector( httpsConnector );
233 }
234
235 HandlerList handlers = new HandlerList();
236 for ( WebApp w : webApps )
237 {
238 WebAppContext webapp = new WebAppContext();
239 webapp.setWar( w.getWarFile() );
240 webapp.setContextPath( w.getContextPath() );
241 handlers.addHandler( webapp );
242
243 webapp.setParentLoaderPriority( true );
244 }
245
246
247
248 File webAppDir = new File( dirService.getInstanceLayout().getInstanceDirectory(), "webapps" );
249
250 FilenameFilter webAppFilter = new FilenameFilter()
251 {
252
253 public boolean accept( File dir, String name )
254 {
255 return name.endsWith( ".war" );
256 }
257 };
258
259 if ( webAppDir.exists() )
260 {
261 File[] appList = webAppDir.listFiles( webAppFilter );
262 for ( File app : appList )
263 {
264 WebAppContext webapp = new WebAppContext();
265 webapp.setWar( app.getAbsolutePath() );
266 String ctxName = app.getName();
267 int pos = ctxName.indexOf( '.' );
268 if ( pos > 0 )
269 {
270 ctxName = ctxName.substring( 0, pos );
271 }
272
273 webapp.setContextPath( "/" + ctxName );
274 handlers.addHandler( webapp );
275
276 webapp.setParentLoaderPriority( true );
277 }
278 }
279
280 jetty.setHandler( handlers );
281
282 configured = true;
283 }
284 catch ( Exception e )
285 {
286 LOG.error( I18n.err( I18n.ERR_121 ), e );
287 }
288
289 }
290
291
292
293
294
295
296
297 public void stop() throws Exception
298 {
299 if ( jetty != null && jetty.isStarted() )
300 {
301 LOG.info( "stopping jetty http server" );
302 jetty.stop();
303 }
304 }
305
306
307 public void setConfFile( String confFile )
308 {
309 this.confFile = confFile;
310 }
311
312
313 public Set<WebApp> getWebApps()
314 {
315 return webApps;
316 }
317
318
319 public void setWebApps( Set<WebApp> webapps )
320 {
321 this.webApps = webapps;
322 }
323
324
325 public TcpTransport getHttpTransport()
326 {
327 return httpTransport;
328 }
329
330
331 public void setHttpTransport( TcpTransport httpTransport )
332 {
333 this.httpTransport = httpTransport;
334 }
335
336
337 public TcpTransport getHttpsTransport()
338 {
339 return httpsTransport;
340 }
341
342
343 public void setHttpsTransport( TcpTransport httpsTransport )
344 {
345 this.httpsTransport = httpsTransport;
346 }
347
348 }