1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 22 * Portions Copyright (c) 2020, Chris Fraire <cfraire@me.com>. 23 */ 24 package opengrok.auth.plugin.decoders; 25 26 import java.util.Collections; 27 import java.util.Date; 28 import java.util.logging.Level; 29 import java.util.logging.Logger; 30 31 import jakarta.servlet.http.HttpServletRequest; 32 import opengrok.auth.plugin.entity.User; 33 import opengrok.auth.plugin.util.Timestamp; 34 import org.opengrok.indexer.web.Laundromat; 35 36 /** 37 * Decode Oracle SSO specific headers. 38 * 39 * @author Krystof Tulinger 40 */ 41 public class OSSOHeaderDecoder implements IUserDecoder { 42 43 private static final Logger LOGGER = Logger.getLogger(OSSOHeaderDecoder.class.getName()); 44 45 protected static String OSSO_COOKIE_TIMESTAMP_HEADER = "osso-cookie-timestamp"; 46 protected static String OSSO_TIMEOUT_EXCEEDED_HEADER = "osso-idle-timeout-exceeded"; 47 protected static String OSSO_SUBSCRIBER_DN_HEADER = "osso-subscriber-dn"; 48 protected static String OSSO_SUBSCRIBER_HEADER = "osso-subscriber"; 49 protected static String OSSO_USER_DN_HEADER = "osso-user-dn"; 50 protected static String OSSO_USER_GUID_HEADER = "osso-user-guid"; 51 52 @Override fromRequest(HttpServletRequest request)53 public User fromRequest(HttpServletRequest request) { 54 String username, userguid, timeouted, timestamp; 55 Date cookieTimestamp = null; 56 57 // Avoid classification as a taint bug. 58 username = Laundromat.launderInput(request.getHeader(OSSO_USER_DN_HEADER)); 59 timeouted = Laundromat.launderInput(request.getHeader(OSSO_TIMEOUT_EXCEEDED_HEADER)); 60 timestamp = Laundromat.launderInput(request.getHeader(OSSO_COOKIE_TIMESTAMP_HEADER)); 61 userguid = Laundromat.launderInput(request.getHeader(OSSO_USER_GUID_HEADER)); 62 63 if (username == null || username.isEmpty()) { 64 LOGGER.log(Level.WARNING, 65 "Can not construct an user: username could not be extracted from headers: {0}", 66 String.join(",", Collections.list(request.getHeaderNames()))); 67 return null; 68 } 69 70 if (userguid == null || userguid.isEmpty()) { 71 LOGGER.log(Level.WARNING, 72 "Can not construct an user: userguid could not be extracted from headers: {0}", 73 String.join(",", Collections.list(request.getHeaderNames()))); 74 return null; 75 } 76 77 /** 78 * The timestamp cookie can be corrupted. 79 */ 80 try { 81 cookieTimestamp = Timestamp.decodeTimeCookie(timestamp); 82 } catch (NumberFormatException ex) { 83 LOGGER.log(Level.WARNING, 84 String.format("Unparseable timestamp cookie \"%s\" for user \"%s\"", 85 timestamp, username), ex); 86 } 87 88 /** 89 * Creating new user entity with provided information. The entity can be 90 * checked if the timeout expired via {@link User#isTimeouted()}. 91 */ 92 User user = new User(username, userguid, cookieTimestamp, 93 "true".equalsIgnoreCase(timeouted)); 94 95 user.setAttribute("subscriber-dn", request.getHeader(OSSO_SUBSCRIBER_DN_HEADER)); 96 user.setAttribute("subscriber", request.getHeader(OSSO_SUBSCRIBER_HEADER)); 97 98 if (user.isTimeouted()) { 99 LOGGER.log(Level.WARNING, "Can not construct an user \"{0}\": header is timeouted", 100 username); 101 return null; 102 } 103 104 return user; 105 } 106 } 107