VariablePool.java
/*
** Module : VariablePool.java
** Abstract : implements variables for access rights expressions
**
** Copyright (c) 2005-2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- -T- --JPRM-- ----------------Description-----------------
** 001 NVS 20050323 NEW @20461 Created the initial version. This class
** implements SecurityManager variables that may
** be used in access rights expressions.
** 002 NVS 20050411 CHG @20677 Fixed few javadoc issues
** 003 NVS 20050414 CHG @20732 Added handling for the RestrictedUseException
** 004 NVS 20050418 CHG @20769 New Notifiable required dummy initEIR().
** 005 GES 20060305 CHG @24896 Logging level changes.
** 006 GES 20070111 CHG @31802 Removed use of notifiable (it was an over-
** complicated approach).
** 007 EVL 20070609 CHG @34005 Adding explicit import of the class
** com.goldencode.p2j.net.Queue to eliminate
** conflict with the same class from java.util
** package to be able to compile for Java 6.
** 008 ECF 20071106 CHG @35903 Eliminated references to network Queue class.
** Replaced with SessionManager API calls.
** 009 GES 20081027 CHG @40344 Some cleanups to eliminate direct socket use.
** Added isSecureConnection() variable.
** 010 GBB 20230512 Logging methods replaced by CentralLogger/ConversionStatus.
** 011 GBB 20230825 SecurityManager session method call updated.
** 012 GBB 20240313 Session renamed to SecuritySession to resolve ambigious imports.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.security;
import java.util.*;
import java.text.*;
import java.net.*;
import com.goldencode.p2j.net.*;
import com.goldencode.p2j.directory.*;
/* TODO:
* 1. there is a great deal of cut and paste duplication throughout this file
* (which is unnecessary), most likely there should be some new helpers in
* the security manager for the common stuff, but if this class is really
* the ONLY place the helpers would be used, then some private methods can
* be added to centralize an implementation
* 2. the expression engine's data type limits no longer exist so the API can
* be simplified a bit (e.g. get rid of use of long where possible and use
* an int instead)
*/
/**
* Implements Security Manager variables that may be used in access rights
* expressions.
*/
public class VariablePool
{
/**
* Constructor.
*/
public VariablePool()
{
}
/**
* Gets the current application ID.
*
* @return current application ID
*/
public String getAppId()
{
SecurityCache sc = SecurityManager.getInstance().getCache();
SecurityContextStack ctx = SecurityContextStack.getContext();
if (ctx == null)
return "";
int id = ctx.getIdList()[0];
if (id == -1)
return "";
else
return sc.getAccountByOrd(id).getSubjectId();
}
/**
* Gets the current user ID.
*
* @return current user ID
*/
public String getUserId()
{
SecurityCache sc = SecurityManager.getInstance().getCache();
SecurityContextStack ctx = SecurityContextStack.getContext();
if (ctx == null)
return "";
int id = ctx.getIdList()[1];
if (id == -1)
return "";
else
return sc.getAccountByOrd(id).getSubjectId();
}
/**
* Gets the number of groups.
*
* @return number of groups
*/
public long getGroups()
{
SecurityContextStack ctx = getContext();
if (ctx == null)
return 0;
int[] idList = ctx.getIdList();
return idList.length - 2;
}
/**
* Gets the first defined group ID.
*
* @return the first defined group ID
*/
public String getGroupId()
{
SecurityCache sc = SecurityManager.getInstance().getCache();
SecurityContextStack ctx = SecurityContextStack.getContext();
if (ctx == null)
return "";
int[] idList = ctx.getIdList();
if (idList.length == 2)
return "";
else
return sc.getAccountByOrd(idList[2]).getSubjectId();
}
/**
* Gets a group name by index.
*
* @param i
* index of the group name to get
* @return indexed group name
*/
public String getGroup(long i)
{
SecurityCache sc = SecurityManager.getInstance().getCache();
SecurityContextStack ctx = SecurityContextStack.getContext();
if (ctx == null)
return "";
int[] idList = ctx.getIdList();
if (2 + i >= idList.length)
return "";
else
return sc.getAccountByOrd(idList[2 + (int)i]).getSubjectId();
}
/**
* Gets the TLS peer name.
*
* @return TLS peer name
*/
public String getPeerName()
{
SecurityContextStack ctx = getContext();
if (ctx == null)
return "";
NetSocket nsock = getSocket(ctx);
InetAddress peer = nsock.getRemoteAddr();
return peer.getHostName();
}
/**
* Gets the TLS server name.
*
* @return TLS server name
*/
public String getServerName()
{
SecurityContextStack ctx = getContext();
if (ctx == null)
return "";
NetSocket nsock = getSocket(ctx);
InetAddress serv = nsock.getLocalAddr();
return serv.getHostName();
}
/**
* Gets the TLS peer IP address.
*
* @return TLS peer IP address
*/
public String getPeerIp()
{
SecurityContextStack ctx = getContext();
if (ctx == null)
return "";
NetSocket nsock = getSocket(ctx);
InetAddress peer = nsock.getRemoteAddr();
return peer.getHostAddress();
}
/**
* Gets the TLS server IP address.
*
* @return TLS server IP address
*/
public String getServerIp()
{
SecurityContextStack ctx = getContext();
if (ctx == null)
return "";
NetSocket nsock = getSocket(ctx);
InetAddress serv = nsock.getLocalAddr();
return serv.getHostAddress();
}
/**
* Gets the secure status of the socket in use for this session.
*
* @return <code>true</code> if the socket is based on SSL/TLS and
* <code>false</code> if the socket is insecure.
*/
public boolean isSecureConnection()
{
SecurityContextStack ctx = getContext();
if (ctx == null)
return false;
NetSocket nsock = getSocket(ctx);
return (nsock.getSession() != null);
}
/**
* Gets the TLS P2J peer node address.
*
* @return TLS P2J peer node address, or 0 if there is no network session
* for the current context.
*/
public long getPeerNode()
{
return SessionManager.get().getNodeAddress();
}
/**
* Gets the TLS P2J server node address.
*
* @return TLS P2J server node address, or 0 if there is no network
* session for the current context.
*/
public long getServerNode()
{
return SessionManager.get().getRemoteAddress();
}
/**
* Gets the current date as "YYYY/MM/DD".
*
* @return current date
*/
public String getDate()
{
Date date = new Date();
DateFormat df = new SimpleDateFormat("yyyy/MM/dd");
StringBuffer b = new StringBuffer();
df.format(date, b, new FieldPosition(DateFormat.YEAR_FIELD));
return new String(b);
}
/**
* Gets the current year.
*
* @return current year
*/
public long getYear()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.YEAR);
}
/**
* Gets the current month.
*
* @return current month
*/
public long getMonth()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.MONTH) + 1;
}
/**
* Gets the current day of the month.
*
* @return current day of the month
*/
public long getDayOfMonth()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.DATE);
}
/**
* Gets the current day of the year.
*
* @return current day of the year
*/
public long getDayOfYear()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.DAY_OF_YEAR);
}
/**
* Gets the current day of the epoch.
*
* @return current day of the epoch
*/
public long getDayOfEpoch()
{
Date date = new Date();
return date.getTime() / 1000 / 86400;
}
/**
* Gets the current day of the week.
*
* @return current day of the week
*/
public long getWeekDay()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.DAY_OF_WEEK);
}
/**
* Gets the current week number.
*
* @return current week number
*/
public long getWeekNum()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.WEEK_OF_YEAR);
}
/**
* Checks whether today is a holiday.
*
* @return <code>true</code> if today is a public holiday
*/
public boolean isHoliday()
{
// Safely query cached data
SecurityCache sc = SecurityManager.getInstance().getCache();
DateValue today = new DateValue();
return sc.getHolidays().contains(today.toString());
}
/**
* Gets the current time of day.
*
* @return current time of day
*/
public String getTime()
{
Date date = new Date();
DateFormat df = new SimpleDateFormat("HH/mm/ss");
StringBuffer b = new StringBuffer();
df.format(date, b, new FieldPosition(DateFormat.HOUR_OF_DAY0_FIELD));
return new String(b);
}
/**
* Gets the current hour for 12 hour clock.
*
* @return current hour for 12 hour clock
*/
public long getHourAmPm()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.HOUR);
}
/**
* Gets the current hour for 24 hour clock.
*
* @return current hour for 24 hour clock
*/
public long getHour()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.HOUR_OF_DAY);
}
/**
* Gets the current minute.
*
* @return current minute
*/
public long getMinute()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.MINUTE);
}
/**
* Gets the current second.
*
* @return current second
*/
public long getSecond()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.SECOND);
}
/**
* Gets the current minute since midnight.
*
* @return current minute since midnight
*/
public long getMinSinceMidnight()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.MINUTE) + cal.get(Calendar.HOUR_OF_DAY) * 60;
}
/**
* Gets the current second since midnight.
*
* @return current second since midnight
*/
public long getSecSinceMidnight()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.SECOND) +
(cal.get(Calendar.MINUTE) + cal.get(Calendar.HOUR_OF_DAY) * 60) * 60;
}
/**
* Checks whether it is AM time.
*
* @return <code>true</code> if it is AM time.
*/
public boolean isAm()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.AM_PM) == Calendar.AM;
}
/**
* Checks whether it is PM time.
*
* @return <code>true</code> if it is PM time.
*/
public boolean isPm()
{
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.AM_PM) == Calendar.PM;
}
/**
* Reads a single (the first) string value from a P2J directory attribute.
*
* @param oid
* directory object id to query
* @param attrName
* attribute name to read
* @return attribute value
*/
public String dirS(String oid, String attrName)
{
return dirS(oid, attrName, 0);
}
/**
* Reads a single indexed string value from a P2J directory attribute.
*
* @param oid
* directory object id to query
* @param attrName
* attribute name to read
* @param i
* index of the particular value to read
* @return attribute value
*/
public String dirS(String oid, String attrName, long i)
{
// accessing directory
DirectoryService ds = DirectoryService.getInstance();
ds.bind();
String value = ds.getNodeString(oid, attrName, (int)i);
ds.unbind();
return value;
}
/**
* Reads a single (the first) integer value from a P2J directory attribute.
*
* @param oid
* directory object id to query
* @param attrName
* attribute name to read
* @return attribute value
*/
public long dirL(String oid, String attrName)
{
return dirL(oid, attrName, 0);
}
/**
* Reads a single indexed integer value from a P2J directory attribute.
*
* @param oid
* directory object id to query
* @param attrName
* attribute name to read
* @param i
* index of the particular value to read
* @return attribute value
*/
public long dirL(String oid, String attrName, long i)
{
// accessing directory
DirectoryService ds = DirectoryService.getInstance();
ds.bind();
Integer value = ds.getNodeInteger(oid, attrName, (int)i);
ds.unbind();
return value == null ? 0 : value.intValue();
}
/**
* Reads a single (the first) boolean value from a P2J directory attribute.
*
* @param oid
* directory object id to query
* @param attrName
* attribute name to read
* @return attribute value
*/
public boolean dirB(String oid, String attrName)
{
return dirB(oid, attrName, 0);
}
/**
* Reads a single indexed boolean value from a P2J directory attribute.
*
* @param oid
* directory object id to query
* @param attrName
* attribute name to read
* @param i
* index of the particular value to read
* @return attribute value
*/
public boolean dirB(String oid, String attrName, long i)
{
// accessing directory
DirectoryService ds = DirectoryService.getInstance();
ds.bind();
Boolean value = ds.getNodeBoolean(oid, attrName, (int)i);
ds.unbind();
return value == null ? false : value.booleanValue();
}
/**
* Safely query the cached security context.
*
* @return The security context or <code>null</code> if there is no
* context available.
*/
private SecurityContextStack getContext()
{
SecurityCache sc = SecurityManager.getInstance().getCache();
return SecurityContextStack.getContext();
}
/**
* Access the network state associated with the current security context.
*
* @param ctx
* The current session's security context.
*
* @return The socket associated with the remote connection.
*/
private NetSocket getSocket(SecurityContextStack ctx)
{
SecurityContext key = ctx.getSessionKey();
SecuritySession sess = SecurityManager.getInstance().sessionSm.locateSession(key);
Object sessid = sess.getSessionId();
return (NetSocket) sessid;
}
}