1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.openr66.protocol.http.rest;
21
22 import io.netty.bootstrap.ServerBootstrap;
23 import io.netty.channel.ChannelFuture;
24 import io.netty.channel.ChannelHandlerContext;
25 import io.netty.handler.codec.http.HttpResponseStatus;
26 import org.waarp.common.command.exception.Reply421Exception;
27 import org.waarp.common.command.exception.Reply530Exception;
28 import org.waarp.common.database.DbSession;
29 import org.waarp.common.database.exception.WaarpDatabaseException;
30 import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
31 import org.waarp.common.digest.FilesystemBasedDigest;
32 import org.waarp.common.logging.SysErrLogger;
33 import org.waarp.common.logging.WaarpLogger;
34 import org.waarp.common.logging.WaarpLoggerFactory;
35 import org.waarp.common.utility.ParametersChecker;
36 import org.waarp.common.utility.WaarpNettyUtil;
37 import org.waarp.common.utility.WaarpStringUtils;
38 import org.waarp.gateway.kernel.exception.HttpInvalidAuthenticationException;
39 import org.waarp.gateway.kernel.rest.HttpRestHandler;
40 import org.waarp.gateway.kernel.rest.RestConfiguration;
41 import org.waarp.openr66.context.R66Session;
42 import org.waarp.openr66.database.DbConstantR66;
43 import org.waarp.openr66.database.data.DbHostAuth;
44 import org.waarp.openr66.protocol.configuration.Configuration;
45 import org.waarp.openr66.protocol.http.rest.handler.DbConfigurationR66RestMethodHandler;
46 import org.waarp.openr66.protocol.http.rest.handler.DbHostAuthR66RestMethodHandler;
47 import org.waarp.openr66.protocol.http.rest.handler.DbHostConfigurationR66RestMethodHandler;
48 import org.waarp.openr66.protocol.http.rest.handler.DbRuleR66RestMethodHandler;
49 import org.waarp.openr66.protocol.http.rest.handler.DbTaskRunnerR66RestMethodHandler;
50 import org.waarp.openr66.protocol.http.rest.handler.HttpRestBandwidthR66Handler;
51 import org.waarp.openr66.protocol.http.rest.handler.HttpRestBusinessR66Handler;
52 import org.waarp.openr66.protocol.http.rest.handler.HttpRestConfigR66Handler;
53 import org.waarp.openr66.protocol.http.rest.handler.HttpRestControlR66Handler;
54 import org.waarp.openr66.protocol.http.rest.handler.HttpRestInformationR66Handler;
55 import org.waarp.openr66.protocol.http.rest.handler.HttpRestLogR66Handler;
56 import org.waarp.openr66.protocol.http.rest.handler.HttpRestServerR66Handler;
57 import org.waarp.openr66.protocol.localhandler.ServerActions;
58
59 import java.net.InetSocketAddress;
60 import java.util.ArrayList;
61 import java.util.Arrays;
62 import java.util.HashMap;
63 import java.util.List;
64
65
66
67
68 public class HttpRestR66Handler extends HttpRestHandler {
69
70
71
72
73 private static final WaarpLogger logger =
74 WaarpLoggerFactory.getLogger(HttpRestR66Handler.class);
75 private static final METHOD[] METHOD_0_LENGTH = new METHOD[0];
76
77 private static final HashMap<String, DbSession> dbSessionFromUser =
78 new HashMap<String, DbSession>();
79
80 public enum RESTHANDLERS {
81 DbHostAuth(DbHostAuthR66RestMethodHandler.BASEURI,
82 org.waarp.openr66.database.data.DbHostAuth.class),
83 DbRule(DbRuleR66RestMethodHandler.BASEURI,
84 org.waarp.openr66.database.data.DbRule.class),
85 DbTaskRunner(DbTaskRunnerR66RestMethodHandler.BASEURI,
86 org.waarp.openr66.database.data.DbTaskRunner.class),
87 DbHostConfiguration(DbHostConfigurationR66RestMethodHandler.BASEURI,
88 org.waarp.openr66.database.data.DbHostConfiguration.class),
89 DbConfiguration(DbConfigurationR66RestMethodHandler.BASEURI,
90 org.waarp.openr66.database.data.DbConfiguration.class),
91 Bandwidth(HttpRestBandwidthR66Handler.BASEURI, null),
92 Business(HttpRestBusinessR66Handler.BASEURI, null),
93 Config(HttpRestConfigR66Handler.BASEURI, null),
94 Information(HttpRestInformationR66Handler.BASEURI, null),
95 Log(HttpRestLogR66Handler.BASEURI, null),
96 Server(HttpRestServerR66Handler.BASEURI, null),
97 Control(HttpRestControlR66Handler.BASEURI, null);
98
99 public final String uri;
100 @SuppressWarnings("rawtypes")
101 public final Class clasz;
102
103 @SuppressWarnings("rawtypes")
104 RESTHANDLERS(final String uri, final Class clasz) {
105 this.uri = uri;
106 this.clasz = clasz;
107 }
108
109 public static RESTHANDLERS getRESTHANDLER(final String baseUri) {
110 for (final RESTHANDLERS resthandler : RESTHANDLERS.values()) {
111 if (resthandler.uri.equals(baseUri)) {
112 return resthandler;
113 }
114 }
115 return null;
116 }
117 }
118
119
120
121
122 public static void defaultHandlers() {
123 synchronized (defaultConfiguration) {
124 if (defaultConfiguration.restHashMap.isEmpty()) {
125 defaultConfiguration.setRestAuthenticated(true);
126 defaultConfiguration.setResthandlersCrud(
127 new byte[RESTHANDLERS.values().length]);
128 Arrays.fill(defaultConfiguration.getResthandlersCrud(), (byte) 0x0F);
129 final METHOD[] methods = METHOD.values();
130 defaultConfiguration.restHashMap.put(RESTHANDLERS.DbTaskRunner.uri,
131 new DbTaskRunnerR66RestMethodHandler(
132 defaultConfiguration,
133 methods));
134 defaultConfiguration.restHashMap.put(RESTHANDLERS.DbHostAuth.uri,
135 new DbHostAuthR66RestMethodHandler(
136 defaultConfiguration,
137 methods));
138 defaultConfiguration.restHashMap.put(RESTHANDLERS.DbRule.uri,
139 new DbRuleR66RestMethodHandler(
140 defaultConfiguration,
141 methods));
142 defaultConfiguration.restHashMap.put(
143 RESTHANDLERS.DbHostConfiguration.uri,
144 new DbHostConfigurationR66RestMethodHandler(defaultConfiguration,
145 methods));
146 defaultConfiguration.restHashMap.put(RESTHANDLERS.DbConfiguration.uri,
147 new DbConfigurationR66RestMethodHandler(
148 defaultConfiguration,
149 methods));
150 defaultConfiguration.restHashMap.put(RESTHANDLERS.Bandwidth.uri,
151 new HttpRestBandwidthR66Handler(
152 defaultConfiguration,
153 methods));
154 defaultConfiguration.restHashMap.put(RESTHANDLERS.Business.uri,
155 new HttpRestBusinessR66Handler(
156 defaultConfiguration,
157 methods));
158 defaultConfiguration.restHashMap.put(RESTHANDLERS.Config.uri,
159 new HttpRestConfigR66Handler(
160 defaultConfiguration,
161 methods));
162 defaultConfiguration.restHashMap.put(RESTHANDLERS.Information.uri,
163 new HttpRestInformationR66Handler(
164 defaultConfiguration,
165 methods));
166 defaultConfiguration.restHashMap.put(RESTHANDLERS.Log.uri,
167 new HttpRestLogR66Handler(
168 defaultConfiguration,
169 methods));
170 defaultConfiguration.restHashMap.put(RESTHANDLERS.Server.uri,
171 new HttpRestServerR66Handler(
172 defaultConfiguration,
173 methods));
174 defaultConfiguration.restHashMap.put(RESTHANDLERS.Control.uri,
175 new HttpRestControlR66Handler(
176 defaultConfiguration,
177 methods));
178 }
179 }
180 }
181
182 public HttpRestR66Handler(final RestConfiguration config) {
183 super(config);
184 restHashMap = config.restHashMap;
185 }
186
187 protected static METHOD[] getMethods(final byte check) {
188 final List<METHOD> methods = new ArrayList<METHOD>();
189 if (RestConfiguration.CRUD.CREATE.isValid(check)) {
190 methods.add(METHOD.POST);
191 }
192 if (RestConfiguration.CRUD.READ.isValid(check)) {
193 methods.add(METHOD.GET);
194 }
195 if (RestConfiguration.CRUD.UPDATE.isValid(check)) {
196 methods.add(METHOD.PUT);
197 }
198 if (RestConfiguration.CRUD.DELETE.isValid(check)) {
199 methods.add(METHOD.DELETE);
200 }
201 return methods.toArray(METHOD_0_LENGTH);
202 }
203
204 public static void instantiateHandlers(
205 final RestConfiguration restConfiguration) {
206 defaultHandlers();
207 if (restConfiguration == null) {
208 return;
209 }
210 byte check =
211 restConfiguration.getResthandlersCrud()[RESTHANDLERS.DbTaskRunner.ordinal()];
212 if (check != 0) {
213 final METHOD[] methods = getMethods(check);
214 restConfiguration.restHashMap.put(RESTHANDLERS.DbTaskRunner.uri,
215 new DbTaskRunnerR66RestMethodHandler(
216 restConfiguration, methods));
217 }
218 check =
219 restConfiguration.getResthandlersCrud()[RESTHANDLERS.DbHostAuth.ordinal()];
220 if (check != 0) {
221 final METHOD[] methods = getMethods(check);
222 restConfiguration.restHashMap.put(RESTHANDLERS.DbHostAuth.uri,
223 new DbHostAuthR66RestMethodHandler(
224 restConfiguration, methods));
225 }
226 check =
227 restConfiguration.getResthandlersCrud()[RESTHANDLERS.DbRule.ordinal()];
228 if (check != 0) {
229 final METHOD[] methods = getMethods(check);
230 restConfiguration.restHashMap.put(RESTHANDLERS.DbRule.uri,
231 new DbRuleR66RestMethodHandler(
232 restConfiguration, methods));
233 }
234 check =
235 restConfiguration.getResthandlersCrud()[RESTHANDLERS.DbHostConfiguration.ordinal()];
236 if (check != 0) {
237 final METHOD[] methods = getMethods(check);
238 restConfiguration.restHashMap.put(RESTHANDLERS.DbHostConfiguration.uri,
239 new DbHostConfigurationR66RestMethodHandler(
240 restConfiguration, methods));
241 }
242 check =
243 restConfiguration.getResthandlersCrud()[RESTHANDLERS.DbConfiguration.ordinal()];
244 if (check != 0) {
245 final METHOD[] methods = getMethods(check);
246 restConfiguration.restHashMap.put(RESTHANDLERS.DbConfiguration.uri,
247 new DbConfigurationR66RestMethodHandler(
248 restConfiguration, methods));
249 }
250 check =
251 restConfiguration.getResthandlersCrud()[RESTHANDLERS.Bandwidth.ordinal()];
252 if (check != 0) {
253 final METHOD[] methods = getMethods(check);
254 restConfiguration.restHashMap.put(RESTHANDLERS.Bandwidth.uri,
255 new HttpRestBandwidthR66Handler(
256 restConfiguration, methods));
257 }
258 check =
259 restConfiguration.getResthandlersCrud()[RESTHANDLERS.Business.ordinal()];
260 if (check != 0) {
261 final METHOD[] methods = getMethods(check);
262 restConfiguration.restHashMap.put(RESTHANDLERS.Business.uri,
263 new HttpRestBusinessR66Handler(
264 restConfiguration, methods));
265 }
266 check =
267 restConfiguration.getResthandlersCrud()[RESTHANDLERS.Config.ordinal()];
268 if (check != 0) {
269 final METHOD[] methods = getMethods(check);
270 restConfiguration.restHashMap.put(RESTHANDLERS.Config.uri,
271 new HttpRestConfigR66Handler(
272 restConfiguration, methods));
273 }
274 check =
275 restConfiguration.getResthandlersCrud()[RESTHANDLERS.Information.ordinal()];
276 if (check != 0) {
277 final METHOD[] methods = getMethods(check);
278 restConfiguration.restHashMap.put(RESTHANDLERS.Information.uri,
279 new HttpRestInformationR66Handler(
280 restConfiguration, methods));
281 }
282 check = restConfiguration.getResthandlersCrud()[RESTHANDLERS.Log.ordinal()];
283 if (check != 0) {
284 final METHOD[] methods = getMethods(check);
285 restConfiguration.restHashMap.put(RESTHANDLERS.Log.uri,
286 new HttpRestLogR66Handler(
287 restConfiguration, methods));
288 }
289 check =
290 restConfiguration.getResthandlersCrud()[RESTHANDLERS.Server.ordinal()];
291 if (check != 0) {
292 final METHOD[] methods = getMethods(check);
293 restConfiguration.restHashMap.put(RESTHANDLERS.Server.uri,
294 new HttpRestServerR66Handler(
295 restConfiguration, methods));
296 }
297 check =
298 restConfiguration.getResthandlersCrud()[RESTHANDLERS.Control.ordinal()];
299 if (check != 0) {
300 final METHOD[] methods = getMethods(check);
301 restConfiguration.restHashMap.put(RESTHANDLERS.Control.uri,
302 new HttpRestControlR66Handler(
303 restConfiguration, methods));
304 }
305 logger.debug("Initialized handler: {}", RESTHANDLERS.values().length);
306 }
307
308
309
310
311 private final ServerActions serverHandler = new ServerActions();
312
313 @Override
314 protected final void checkConnection(final ChannelHandlerContext ctx)
315 throws HttpInvalidAuthenticationException {
316 logger.debug("Request: {} ### {}", arguments, response);
317 final String user;
318 String key = null;
319 if (restConfiguration.isRestAuthenticated()) {
320 user = arguments.getXAuthUser();
321 if (ParametersChecker.isEmpty(user)) {
322 status = HttpResponseStatus.UNAUTHORIZED;
323 throw new HttpInvalidAuthenticationException("Empty Authentication");
324 }
325 final DbHostAuth host;
326 try {
327 host = new DbHostAuth(user);
328 key = new String(host.getHostkey(), WaarpStringUtils.UTF8);
329 } catch (final WaarpDatabaseException e) {
330
331 if (user.equals(Configuration.configuration.getAdminName())) {
332 key = new String(Configuration.configuration.getServerAdminKey(),
333 WaarpStringUtils.UTF8);
334 }
335 }
336 if (ParametersChecker.isEmpty(key)) {
337 status = HttpResponseStatus.UNAUTHORIZED;
338 throw new HttpInvalidAuthenticationException("Wrong Authentication");
339 }
340 if (restConfiguration.isRestSignature()) {
341 arguments.checkBaseAuthent(restConfiguration.getHmacSha256(), key,
342 restConfiguration.getRestTimeLimit());
343 } else {
344 arguments.checkTime(restConfiguration.getRestTimeLimit());
345 }
346 } else {
347
348 user = Configuration.configuration.getAdminName();
349 if (restConfiguration.isRestSignature()) {
350 arguments.checkBaseAuthent(restConfiguration.getHmacSha256(), null,
351 restConfiguration.getRestTimeLimit());
352 } else {
353 arguments.checkTime(restConfiguration.getRestTimeLimit());
354 }
355 }
356 getServerHandler().newSession();
357 final R66Session session = getServerHandler().getSession();
358 if (!restConfiguration.isRestAuthenticated()) {
359
360 session.getAuth().specialNoSessionAuth(true,
361 Configuration.configuration.getHostSslId());
362 } else {
363
364 DbSession temp = getDbSessionFromUser().get(user);
365 if (temp == null) {
366 try {
367 temp = new DbSession(DbConstantR66.admin, false);
368 getDbSessionFromUser().put(user, temp);
369 } catch (final WaarpDatabaseNoConnectionException ignored) {
370
371 }
372 }
373 if (temp != null) {
374 temp.useConnection();
375 dbSession = temp;
376 }
377 if (key == null) {
378 status = HttpResponseStatus.UNAUTHORIZED;
379 throw new HttpInvalidAuthenticationException("Wrong Authentication");
380 }
381 try {
382 session.getAuth().connectionHttps(user,
383 FilesystemBasedDigest.passwdCrypt(
384 key.getBytes(
385 WaarpStringUtils.UTF8)));
386 } catch (final Reply530Exception e) {
387 status = HttpResponseStatus.UNAUTHORIZED;
388 throw new HttpInvalidAuthenticationException("Wrong Authentication", e);
389 } catch (final Reply421Exception e) {
390 status = HttpResponseStatus.SERVICE_UNAVAILABLE;
391 throw new HttpInvalidAuthenticationException("Service unavailable", e);
392 }
393 }
394 arguments.setXAuthRole(session.getAuth().getRole());
395 arguments.methodFromUri();
396 arguments.methodFromHeader();
397 }
398
399 @Override
400 public void channelInactive(final ChannelHandlerContext ctx)
401 throws Exception {
402 super.channelInactive(ctx);
403 getServerHandler().channelClosed();
404 }
405
406
407
408
409
410
411 public static void initializeService(
412 final RestConfiguration restConfiguration) {
413 instantiateHandlers(restConfiguration);
414 if (group == null) {
415 group = Configuration.configuration.getHttpChannelGroup();
416 }
417
418 final ServerBootstrap httpBootstrap = new ServerBootstrap();
419 WaarpNettyUtil.setServerBootstrap(httpBootstrap,
420 Configuration.configuration.getHttpWorkerGroup(),
421 Configuration.configuration.getHttpWorkerGroup(),
422 (int) Configuration.configuration.getTimeoutCon());
423
424 if (restConfiguration.isRestSsl()) {
425 httpBootstrap.childHandler(new HttpRestR66Initializer(false,
426 Configuration.getWaarpSslContextFactory(),
427 restConfiguration));
428 } else {
429 httpBootstrap.childHandler(
430 new HttpRestR66Initializer(false, null, restConfiguration));
431 }
432
433 final ChannelFuture future;
434 if (restConfiguration != null &&
435 restConfiguration.getRestAddress() != null &&
436 !restConfiguration.getRestAddress().isEmpty()) {
437 future = httpBootstrap.bind(
438 new InetSocketAddress(restConfiguration.getRestAddress(),
439 restConfiguration.getRestPort()));
440 } else {
441 future = httpBootstrap.bind(
442 new InetSocketAddress(restConfiguration.getRestPort()));
443 }
444 try {
445 future.await();
446 } catch (final InterruptedException e) {
447 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
448 }
449 if (future.isSuccess()) {
450 group.add(future.channel());
451 }
452 }
453
454
455
456
457 public static HashMap<String, DbSession> getDbSessionFromUser() {
458 return dbSessionFromUser;
459 }
460
461
462
463
464 public ServerActions getServerHandler() {
465 return serverHandler;
466 }
467 }