import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import org.onap.aaf.auth.dao.cass.RoleDAO;
import org.onap.aaf.auth.dao.cass.Status;
import org.onap.aaf.auth.dao.cass.UserRoleDAO;
+import org.onap.aaf.auth.env.AuthzEnv;
import org.onap.aaf.auth.env.AuthzTrans;
import org.onap.aaf.auth.env.AuthzTrans.REQD_TYPE;
import org.onap.aaf.auth.env.AuthzTransFilter;
*/
public class Question {
- // DON'T CHANGE FROM lower Case!!!
- public static enum Type {
- ns, role, perm, cred
- };
-
- public static final String OWNER="owner";
- public static final String ADMIN="admin";
- public static final String DOT_OWNER=".owner";
- public static final String DOT_ADMIN=".admin";
- public static final String ACCESS = "access";
-
- static final String ASTERIX = "*";
-
- public static enum Access {
- read, write, create
- };
-
- public static final String READ = Access.read.name();
- public static final String WRITE = Access.write.name();
- public static final String CREATE = Access.create.name();
-
- public static final String ROLE = Type.role.name();
- public static final String PERM = Type.perm.name();
- public static final String NS = Type.ns.name();
- public static final String CRED = Type.cred.name();
- private static final String DELG = "delg";
- public static final String ROOT_NS = Define.ROOT_NS();
- public static final String ATTRIB = "attrib";
-
-
- public static final int MAX_SCOPE = 10;
- public static final int APP_SCOPE = 3;
- public static final int COMPANY_SCOPE = 2;
- static Slot PERMS;
-
- private static Set<String> specialLog = null;
- public static final Random random = new SecureRandom();
- private static long traceID = random.nextLong();
- private static Slot specialLogSlot = null;
- private static Slot transIDSlot = null;
-
-
- public final HistoryDAO historyDAO;
- public final CachedNSDAO nsDAO;
- public final CachedRoleDAO roleDAO;
- public final CachedPermDAO permDAO;
- public final CachedUserRoleDAO userRoleDAO;
- public final CachedCredDAO credDAO;
- public final CachedCertDAO certDAO;
- public final DelegateDAO delegateDAO;
- public final FutureDAO futureDAO;
- public final ApprovalDAO approvalDAO;
- private final CacheInfoDAO cacheInfoDAO;
- public final LocateDAO locateDAO;
-
- public Question(AuthzTrans trans, Cluster cluster, String keyspace, boolean startClean) throws APIException, IOException {
- PERMS = trans.slot("USER_PERMS");
- trans.init().log("Instantiating DAOs");
- long expiresIn = Long.parseLong(trans.getProperty(Config.AAF_USER_EXPIRES, Config.AAF_USER_EXPIRES_DEF));
- historyDAO = new HistoryDAO(trans, cluster, keyspace);
-
- // Deal with Cached Entries
- cacheInfoDAO = new CacheInfoDAO(trans, historyDAO);
-
- nsDAO = new CachedNSDAO(new NsDAO(trans, historyDAO, cacheInfoDAO),cacheInfoDAO, expiresIn);
- permDAO = new CachedPermDAO(new PermDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
- roleDAO = new CachedRoleDAO(new RoleDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
- userRoleDAO = new CachedUserRoleDAO(new UserRoleDAO(trans, historyDAO,cacheInfoDAO), cacheInfoDAO, expiresIn);
- credDAO = new CachedCredDAO(new CredDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
- certDAO = new CachedCertDAO(new CertDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
-
- locateDAO = new LocateDAO(trans,historyDAO);
- futureDAO = new FutureDAO(trans, historyDAO);
- delegateDAO = new DelegateDAO(trans, historyDAO);
- approvalDAO = new ApprovalDAO(trans, historyDAO);
-
- // Only want to aggressively cleanse User related Caches... The others,
- // just normal refresh
- if(startClean) {
- CachedDAO.startCleansing(trans.env(), credDAO, userRoleDAO);
- CachedDAO.startRefresh(trans.env(), cacheInfoDAO);
- }
- // Set a Timer to Check Caches to send messages for Caching changes
-
- if(specialLogSlot==null) {
- specialLogSlot = trans.slot(AuthzTransFilter.SPECIAL_LOG_SLOT);
- }
-
- if(transIDSlot==null) {
- transIDSlot = trans.slot(AuthzTransFilter.TRANS_ID_SLOT);
- }
-
- AbsCassDAO.primePSIs(trans);
- }
-
-
- public void close(AuthzTrans trans) {
- historyDAO.close(trans);
- cacheInfoDAO.close(trans);
- nsDAO.close(trans);
- permDAO.close(trans);
- roleDAO.close(trans);
- userRoleDAO.close(trans);
- credDAO.close(trans);
- certDAO.close(trans);
- delegateDAO.close(trans);
- futureDAO.close(trans);
- approvalDAO.close(trans);
- }
-
- public Result<PermDAO.Data> permFrom(AuthzTrans trans, String type,
- String instance, String action) {
- Result<NsDAO.Data> rnd = deriveNs(trans, type);
- if (rnd.isOK()) {
- return Result.ok(new PermDAO.Data(new NsSplit(rnd.value, type),
- instance, action));
- } else {
- return Result.err(rnd);
- }
- }
-
- /**
- * getPermsByUser
- *
- * Because this call is frequently called internally, AND because we already
- * look for it in the initial Call, we cache within the Transaction
- *
- * @param trans
- * @param user
- * @return
- */
- public Result<List<PermDAO.Data>> getPermsByUser(AuthzTrans trans, String user, boolean lookup) {
- return PermLookup.get(trans, this, user).getPerms(lookup);
- }
-
- public Result<List<PermDAO.Data>> getPermsByUserFromRolesFilter(AuthzTrans trans, String user, String forUser) {
- PermLookup plUser = PermLookup.get(trans, this, user);
- Result<Set<String>> plPermNames = plUser.getPermNames();
- if(plPermNames.notOK()) {
- return Result.err(plPermNames);
- }
-
- Set<String> nss;
- if(forUser.equals(user)) {
- nss = null;
- } else {
- // Setup a TreeSet to check on Namespaces to
- nss = new TreeSet<String>();
- PermLookup fUser = PermLookup.get(trans, this, forUser);
- Result<Set<String>> forUpn = fUser.getPermNames();
- if(forUpn.notOK()) {
- return Result.err(forUpn);
- }
-
- for(String pn : forUpn.value) {
- Result<String[]> decoded = PermDAO.Data.decodeToArray(trans, this, pn);
- if(decoded.isOKhasData()) {
- nss.add(decoded.value[0]);
- } else {
- trans.error().log(pn,", derived from a Role, is invalid:",decoded.errorString());
- }
- }
- }
-
- List<PermDAO.Data> rlpUser = new ArrayList<PermDAO.Data>();
- Result<PermDAO.Data> rpdd;
- PermDAO.Data pdd;
- for(String pn : plPermNames.value) {
- rpdd = PermDAO.Data.decode(trans, this, pn);
- if(rpdd.isOKhasData()) {
- pdd=rpdd.value;
- if(nss==null || nss.contains(pdd.ns)) {
- rlpUser.add(pdd);
- }
- } else {
- trans.error().log(pn,", derived from a Role, is invalid. Run Data Cleanup:",rpdd.errorString());
- }
- }
- return Result.ok(rlpUser);
- }
-
- public Result<List<PermDAO.Data>> getPermsByType(AuthzTrans trans, String perm) {
- Result<NsSplit> nss = deriveNsSplit(trans, perm);
- if (nss.notOK()) {
- return Result.err(nss);
- }
- return permDAO.readByType(trans, nss.value.ns, nss.value.name);
- }
-
- public Result<List<PermDAO.Data>> getPermsByName(AuthzTrans trans,
- String type, String instance, String action) {
- Result<NsSplit> nss = deriveNsSplit(trans, type);
- if (nss.notOK()) {
- return Result.err(nss);
- }
- return permDAO.read(trans, nss.value.ns, nss.value.name, instance,action);
- }
-
- public Result<List<PermDAO.Data>> getPermsByRole(AuthzTrans trans, String role, boolean lookup) {
- Result<NsSplit> nss = deriveNsSplit(trans, role);
- if (nss.notOK()) {
- return Result.err(nss);
- }
-
- Result<List<RoleDAO.Data>> rlrd = roleDAO.read(trans, nss.value.ns,
- nss.value.name);
- if (rlrd.notOKorIsEmpty()) {
- return Result.err(rlrd);
- }
- // Using Set to avoid duplicates
- Set<String> permNames = new HashSet<String>();
- if (rlrd.isOKhasData()) {
- for (RoleDAO.Data drr : rlrd.value) {
- permNames.addAll(drr.perms(false));
- }
- }
-
- // Note: It should be ok for a Valid user to have no permissions -
- // Jonathan 8/12/2013
- List<PermDAO.Data> perms = new ArrayList<PermDAO.Data>();
- for (String perm : permNames) {
- Result<PermDAO.Data> pr = PermDAO.Data.decode(trans, this, perm);
- if (pr.notOK()) {
- return Result.err(pr);
- }
-
- if(lookup) {
- Result<List<PermDAO.Data>> rlpd = permDAO.read(trans, pr.value);
- if (rlpd.isOKhasData()) {
- for (PermDAO.Data pData : rlpd.value) {
- perms.add(pData);
- }
- }
- } else {
- perms.add(pr.value);
- }
- }
-
- return Result.ok(perms);
- }
-
- public Result<List<RoleDAO.Data>> getRolesByName(AuthzTrans trans,
- String role) {
- Result<NsSplit> nss = deriveNsSplit(trans, role);
- if (nss.notOK()) {
- return Result.err(nss);
- }
- String r = nss.value.name;
- if (r.endsWith(".*")) { // do children Search
- return roleDAO.readChildren(trans, nss.value.ns,
- r.substring(0, r.length() - 2));
- } else if (ASTERIX.equals(r)) {
- return roleDAO.readChildren(trans, nss.value.ns, ASTERIX);
- } else {
- return roleDAO.read(trans, nss.value.ns, r);
- }
- }
-
- /**
- * Derive NS
- *
- * Given a Child Namespace, figure out what the best Namespace parent is.
- *
- * For instance, if in the NS table, the parent "com.att" exists, but not
- * "org.osaaf.child" or "org.osaaf.a.b.c", then passing in either
- * "org.osaaf.child" or "org.osaaf.a.b.c" will return "com.att"
- *
- * Uses recursive search on Cached DAO data
- *
- * @param trans
- * @param child
- * @return
- */
- public Result<NsDAO.Data> deriveNs(AuthzTrans trans, String child) {
- Result<List<NsDAO.Data>> r = nsDAO.read(trans, child);
-
- if (r.isOKhasData()) {
- return Result.ok(r.value.get(0));
- } else {
- int dot;
- if(child==null) {
- return Result.err(Status.ERR_NsNotFound, "No Namespace");
- } else {
- dot = child.lastIndexOf('.');
- }
- if (dot < 0) {
- return Result.err(Status.ERR_NsNotFound, "No Namespace for [%s]", child);
- } else {
- return deriveNs(trans, child.substring(0, dot));
- }
- }
- }
-
- public Result<NsDAO.Data> deriveFirstNsForType(AuthzTrans trans, String str, NsType type) {
- NsDAO.Data nsd;
-
- for(String lookup = str;!".".equals(lookup) && lookup!=null;) {
- Result<List<NsDAO.Data>> rld = nsDAO.read(trans, lookup);
- if(rld.isOKhasData()) {
- nsd=rld.value.get(0);
- lookup = nsd.parent;
- if(type.type == nsd.type) {
- return Result.ok(nsd);
- }
- } else {
- return Result.err(Status.ERR_NsNotFound,"There is no valid Company Namespace for %s",str);
- }
- }
- return Result.err(Status.ERR_NotFound, str + " does not contain type " + type.name());
- }
-
- public Result<NsSplit> deriveNsSplit(AuthzTrans trans, String child) {
- Result<NsDAO.Data> ndd = deriveNs(trans, child);
- if (ndd.isOK()) {
- NsSplit nss = new NsSplit(ndd.value, child);
- if (nss.isOK()) {
- return Result.ok(nss);
- } else {
- return Result.err(Status.ERR_NsNotFound,
- "Cannot split [%s] into valid namespace elements",
- child);
- }
- }
- return Result.err(ndd);
- }
-
- /**
- * Translate an ID into it's domain
- *
- * i.e. myid1234@aaf.att.com results in domain of com.att.aaf
- *
- * @param id
- * @return
- */
- public static String domain2ns(String id) {
- int at = id.indexOf('@');
- if (at >= 0) {
- String[] domain = id.substring(at + 1).split("\\.");
- StringBuilder ns = new StringBuilder(id.length());
- boolean first = true;
- for (int i = domain.length - 1; i >= 0; --i) {
- if (first) {
- first = false;
- } else {
- ns.append('.');
- }
- ns.append(domain[i]);
- }
- return ns.toString();
- } else {
- return "";
- }
-
- }
-
- /**
- * Validate Namespace of ID@Domain
- *
- * Namespace is reverse order of Domain.
- *
- * @param trans
- * @param id
- * @return
- */
- public Result<NsDAO.Data> validNSOfDomain(AuthzTrans trans, String id) {
- // Take domain, reverse order, and check on NS
- String ns;
- if(id.indexOf('@')<0) { // it's already an ns, not an ID
- ns = id;
- } else {
- ns = domain2ns(id);
- }
- if (ns.length() > 0) {
- if(!trans.org().getDomain().equals(ns)) {
- Result<List<NsDAO.Data>> rlnsd = nsDAO.read(trans, ns);
- if (rlnsd.isOKhasData()) {
- return Result.ok(rlnsd.value.get(0));
- }
- }
- }
- return Result.err(Status.ERR_NsNotFound,
- "A Namespace is not available for %s", id);
- }
-
- public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,NsDAO.Data ndd, Access access) {
- // <ns>.access|:role:<role name>|<read|write>
- String ns = ndd.name;
- int last;
- do {
- if (isGranted(trans, user, ns, ACCESS, ":ns", access.name())) {
- return Result.ok(ndd);
- }
- if ((last = ns.lastIndexOf('.')) >= 0) {
- ns = ns.substring(0, last);
- }
- } while (last >= 0);
- // com.att.aaf.ns|:<client ns>:ns|<access>
- // AAF-724 - Make consistent response for May User", and not take the
- // last check... too confusing.
- Result<NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, ":" + ndd.name + ":ns", access.name());
- if (rv.isOK()) {
- return rv;
- } else if(rv.status==Result.ERR_Backend) {
- return Result.err(rv);
- } else {
- return Result.err(Status.ERR_Denied, "[%s] may not %s in NS [%s]",
- user, access.name(), ndd.name);
- }
- }
-
- public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user, RoleDAO.Data rdd, Access access) {
- Result<NsDAO.Data> rnsd = deriveNs(trans, rdd.ns);
- if (rnsd.isOK()) {
- return mayUser(trans, user, rnsd.value, rdd, access);
- }
- return rnsd;
- }
-
- public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user, NsDAO.Data ndd, RoleDAO.Data rdd, Access access) {
- // 1) Is User in the Role?
- Result<List<UserRoleDAO.Data>> rurd = userRoleDAO.readUserInRole(trans, user, rdd.fullName());
- if (rurd.isOKhasData()) {
- return Result.ok(ndd);
- }
-
- String roleInst = ":role:" + rdd.name;
- // <ns>.access|:role:<role name>|<read|write>
- String ns = rdd.ns;
- int last;
- do {
- if (isGranted(trans, user, ns,ACCESS, roleInst, access.name())) {
- return Result.ok(ndd);
- }
- if ((last = ns.lastIndexOf('.')) >= 0) {
- ns = ns.substring(0, last);
- }
- } while (last >= 0);
-
- // Check if Access by Global Role perm
- // com.att.aaf.ns|:<client ns>:role:name|<access>
- Result<NsDAO.Data> rnsd = mayUserVirtueOfNS(trans, user, ndd, ":"
- + rdd.ns + roleInst, access.name());
- if (rnsd.isOK()) {
- return rnsd;
- } else if(rnsd.status==Result.ERR_Backend) {
- return Result.err(rnsd);
- }
-
- // Check if Access to Whole NS
- // AAF-724 - Make consistent response for May User", and not take the
- // last check... too confusing.
- Result<org.onap.aaf.auth.dao.cass.NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd,
- ":" + rdd.ns + ":ns", access.name());
- if (rv.isOK()) {
- return rv;
- } else if(rnsd.status==Result.ERR_Backend) {
- return Result.err(rnsd);
- } else {
- return Result.err(Status.ERR_Denied, "[%s] may not %s Role [%s]",
- user, access.name(), rdd.fullName());
- }
-
- }
-
- public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,PermDAO.Data pdd, Access access) {
- Result<NsDAO.Data> rnsd = deriveNs(trans, pdd.ns);
- if (rnsd.isOK()) {
- return mayUser(trans, user, rnsd.value, pdd, access);
- }
- return rnsd;
- }
-
- public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,NsDAO.Data ndd, PermDAO.Data pdd, Access access) {
- if (isGranted(trans, user, pdd.ns, pdd.type, pdd.instance, pdd.action)) {
- return Result.ok(ndd);
- }
- String permInst = ":perm:" + pdd.type + ':' + pdd.instance + ':' + pdd.action;
- // <ns>.access|:role:<role name>|<read|write>
- String ns = ndd.name;
- int last;
- do {
- if (isGranted(trans, user, ns, ACCESS, permInst, access.name())) {
- return Result.ok(ndd);
- }
- if ((last = ns.lastIndexOf('.')) >= 0) {
- ns = ns.substring(0, last);
- }
- } while (last >= 0);
-
- // Check if Access by NS perm
- // com.att.aaf.ns|:<client ns>:role:name|<access>
- Result<NsDAO.Data> rnsd = mayUserVirtueOfNS(trans, user, ndd, ":" + pdd.ns + permInst, access.name());
- if (rnsd.isOK()) {
- return rnsd;
- } else if(rnsd.status==Result.ERR_Backend) {
- return Result.err(rnsd);
- }
-
- // Check if Access to Whole NS
- // AAF-724 - Make consistent response for May User", and not take the
- // last check... too confusing.
- Result<NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, ":" + pdd.ns + ":ns", access.name());
- if (rv.isOK()) {
- return rv;
- } else {
- return Result.err(Status.ERR_Denied,
- "[%s] may not %s Perm [%s|%s|%s]", user, access.name(),
- pdd.fullType(), pdd.instance, pdd.action);
- }
-
- }
-
- public Result<Void> mayUser(AuthzTrans trans, DelegateDAO.Data dd, Access access) {
- try {
- Result<NsDAO.Data> rnsd = deriveNs(trans, domain2ns(trans.user()));
- if(rnsd.isOKhasData() && mayUserVirtueOfNS(trans,trans.user(),rnsd.value, ":" + rnsd.value.name + ":ns", access.name()).isOK()) {
- return Result.ok();
- }
- boolean isUser = trans.user().equals(dd.user);
- boolean isDelegate = dd.delegate != null
- && (dd.user.equals(dd.delegate) || trans.user().equals(
- dd.delegate));
- Organization org = trans.org();
- switch (access) {
- case create:
- if (org.getIdentity(trans, dd.user) == null) {
- return Result.err(Status.ERR_UserNotFound,
- "[%s] is not a user in the company database.",
- dd.user);
- }
- if (!dd.user.equals(dd.delegate) && org.getIdentity(trans, dd.delegate) == null) {
- return Result.err(Status.ERR_UserNotFound,
- "[%s] is not a user in the company database.",
- dd.delegate);
- }
- if (!trans.requested(REQD_TYPE.force) && dd.user != null && dd.user.equals(dd.delegate)) {
- return Result.err(Status.ERR_BadData,
- "[%s] cannot be a delegate for self", dd.user);
- }
- if (!isUser && !isGranted(trans, trans.user(), ROOT_NS,DELG,
- org.getDomain(), Question.CREATE)) {
- return Result.err(Status.ERR_Denied,
- "[%s] may not create a delegate for [%s]",
- trans.user(), dd.user);
- }
- break;
- case read:
- case write:
- if (!isUser && !isDelegate &&
- !isGranted(trans, trans.user(), ROOT_NS,DELG,org.getDomain(), access.name())) {
- return Result.err(Status.ERR_Denied,
- "[%s] may not %s delegates for [%s]", trans.user(),
- access.name(), dd.user);
- }
- break;
- default:
- return Result.err(Status.ERR_BadData,"Unknown Access type [%s]", access.name());
- }
- } catch (Exception e) {
- return Result.err(e);
- }
- return Result.ok();
- }
-
- /*
- * Check (recursively, if necessary), if able to do something based on NS
- */
- private Result<NsDAO.Data> mayUserVirtueOfNS(AuthzTrans trans, String user, NsDAO.Data nsd, String ns_and_type, String access) {
- String ns = nsd.name;
-
- // If an ADMIN of the Namespace, then allow
-
- Result<List<UserRoleDAO.Data>> rurd;
- if ((rurd = userRoleDAO.readUserInRole(trans, user, ns+DOT_ADMIN)).isOKhasData()) {
- return Result.ok(nsd);
- } else if(rurd.status==Result.ERR_Backend) {
- return Result.err(rurd);
- }
-
- // If Specially granted Global Permission
- if (isGranted(trans, user, ROOT_NS,NS, ns_and_type, access)) {
- return Result.ok(nsd);
- }
-
- // Check recur
-
- int dot = ns.length();
- if ((dot = ns.lastIndexOf('.', dot - 1)) >= 0) {
- Result<NsDAO.Data> rnsd = deriveNs(trans, ns.substring(0, dot));
- if (rnsd.isOK()) {
- rnsd = mayUserVirtueOfNS(trans, user, rnsd.value, ns_and_type,access);
- } else if(rnsd.status==Result.ERR_Backend) {
- return Result.err(rnsd);
- }
- if (rnsd.isOK()) {
- return Result.ok(nsd);
- } else if(rnsd.status==Result.ERR_Backend) {
- return Result.err(rnsd);
- }
- }
- return Result.err(Status.ERR_Denied, "%s may not %s %s", user, access,
- ns_and_type);
- }
-
-
- /**
- * isGranted
- *
- * Important function - Check internal Permission Schemes for Permission to
- * do things
- *
- * @param trans
- * @param type
- * @param instance
- * @param action
- * @return
- */
- public boolean isGranted(AuthzTrans trans, String user, String ns, String type,String instance, String action) {
- Result<List<PermDAO.Data>> perms = getPermsByUser(trans, user, false);
- if (perms.isOK()) {
- for (PermDAO.Data pd : perms.value) {
- if (ns.equals(pd.ns)) {
- if (type.equals(pd.type)) {
- if (PermEval.evalInstance(pd.instance, instance)) {
- if(PermEval.evalAction(pd.action, action)) { // don't return action here, might miss other action
- return true;
- }
- }
- }
- }
- }
- }
- return false;
- }
-
- public Result<Date> doesUserCredMatch(AuthzTrans trans, String user, byte[] cred) throws DAOException {
- Result<List<CredDAO.Data>> result;
- TimeTaken tt = trans.start("Read DB Cred", Env.REMOTE);
- try {
- result = credDAO.readID(trans, user);
- } finally {
- tt.done();
- }
-
- Result<Date> rv = null;
- if(result.isOK()) {
- if (result.isEmpty()) {
- rv = Result.err(Status.ERR_UserNotFound, user);
- if (willSpecialLog(trans,user)) {
- trans.audit().log("Special DEBUG:", user, " does not exist in DB");
- }
- } else {
- Date now = new Date();//long now = System.currentTimeMillis();
- // Bug noticed 6/22. Sorting on the result can cause Concurrency Issues.
- List<CredDAO.Data> cddl;
- if(result.value.size() > 1) {
- cddl = new ArrayList<CredDAO.Data>(result.value.size());
- for(CredDAO.Data old : result.value) {
- if(old.type==CredDAO.BASIC_AUTH || old.type==CredDAO.BASIC_AUTH_SHA256) {
- cddl.add(old);
- }
- }
- if(cddl.size()>1) {
- Collections.sort(cddl,new Comparator<CredDAO.Data>() {
- @Override
- public int compare(org.onap.aaf.auth.dao.cass.CredDAO.Data a,
- org.onap.aaf.auth.dao.cass.CredDAO.Data b) {
- return b.expires.compareTo(a.expires);
- }
- });
- }
- } else {
- cddl = result.value;
- }
-
- Date expired = null;
- StringBuilder debug = willSpecialLog(trans,user)?new StringBuilder():null;
- for (CredDAO.Data cdd : cddl) {
- if(!cdd.id.equals(user)) {
- trans.error().log("doesUserCredMatch DB call does not match for user: " + user);
- }
- if (cdd.expires.after(now)) {
- byte[] dbcred = cdd.cred.array();
-
- try {
- switch(cdd.type) {
- case CredDAO.BASIC_AUTH:
- byte[] md5=Hash.hashMD5(cred);
- if(Hash.compareTo(md5,dbcred)==0) {
- checkLessThanDays(trans,7,now,cdd);
- return Result.ok(cdd.expires);
- } else if (debug!=null) {
- load(debug, cdd);
- }
- break;
- case CredDAO.BASIC_AUTH_SHA256:
- ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + cred.length);
- bb.putInt(cdd.other);
- bb.put(cred);
- byte[] hash = Hash.hashSHA256(bb.array());
-
- if(Hash.compareTo(hash,dbcred)==0) {
- checkLessThanDays(trans,7,now,cdd);
- return Result.ok(cdd.expires);
- } else if (debug!=null) {
- load(debug, cdd);
- }
- break;
- default:
- trans.error().log("Unknown Credential Type %s for %s, %s",Integer.toString(cdd.type),cdd.id, Chrono.dateTime(cdd.expires));
- }
- } catch (NoSuchAlgorithmException e) {
- trans.error().log(e);
- }
- } else {
- if(expired==null || expired.before(cdd.expires)) {
- expired = cdd.expires;
- }
- }
- } // end for each
- if(debug==null) {
- trans.audit().printf("No cred matches ip=%s, user=%s\n",trans.ip(),user);
- } else {
- trans.audit().printf("No cred matches ip=%s, user=%s %s\n",trans.ip(),user,debug.toString());
- }
- if(expired!=null) {
- // Note: this is only returned if there are no good Credentials
- rv = Result.err(Status.ERR_Security,
- "Credentials %s from %s expired %s",trans.user(), trans.ip(), Chrono.dateTime(expired));
- }
- }
- } else {
- return Result.err(result);
- }
- return rv == null ? Result.create((Date) null, Status.ERR_Security, "Wrong credential") : rv;
- }
-
-
- private void load(StringBuilder debug, Data cdd) {
- debug.append("DB Entry: user=");
- debug.append(cdd.id);
- debug.append(",type=");
- debug.append(cdd.type);
- debug.append(",expires=");
- debug.append(Chrono.dateTime(cdd.expires));
- debug.append('\n');
- }
-
-
- private void checkLessThanDays(AuthzTrans trans, int days, Date now, Data cdd) {
- long close = now.getTime() + (days * 86400000);
- long cexp=cdd.expires.getTime();
- if(cexp<close) {
- int daysLeft = days-(int)((close-cexp)/86400000);
- trans.audit().printf("user=%s,ip=%s,expires=%s,days=%d,msg=\"Password expires in less than %d day%s\"",
- cdd.id,trans.ip(),Chrono.dateOnlyStamp(cdd.expires),daysLeft, daysLeft,daysLeft==1?"":"s");
- }
- }
-
-
- public Result<CredDAO.Data> userCredSetup(AuthzTrans trans, CredDAO.Data cred) {
- if(cred.type==CredDAO.RAW) {
- TimeTaken tt = trans.start("Hash Cred", Env.SUB);
- try {
- cred.type = CredDAO.BASIC_AUTH_SHA256;
- cred.other = random.nextInt();
- ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + cred.cred.capacity());
- bb.putInt(cred.other);
- bb.put(cred.cred);
- byte[] hash = Hash.hashSHA256(bb.array());
- cred.cred = ByteBuffer.wrap(hash);
- return Result.ok(cred);
- } catch (NoSuchAlgorithmException e) {
- return Result.err(Status.ERR_General,e.getLocalizedMessage());
- } finally {
- tt.done();
- }
-
- }
- return Result.err(Status.ERR_Security,"invalid/unreadable credential");
- }
-
- public Result<Boolean> userCredCheck(AuthzTrans trans, CredDAO.Data orig, final byte[] raw) {
- TimeTaken tt = trans.start("CheckCred Cred", Env.SUB);
- try {
- switch(orig.type) {
- case CredDAO.BASIC_AUTH_SHA256:
- ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + raw.length);
- bb.putInt(orig.other);
- bb.put(raw);
- return Result.ok(Hash.compareTo(orig.cred.array(),Hash.hashSHA256(bb.array()))==0);
- case CredDAO.BASIC_AUTH:
- return Result.ok( Hash.compareTo(orig.cred.array(), Hash.hashMD5(raw))==0);
- default:
- return Result.ok(false);
- }
- } catch (NoSuchAlgorithmException e) {
- return Result.err(Status.ERR_General,e.getLocalizedMessage());
- } finally {
- tt.done();
- }
- }
-
- public static final String APPROVED = "APPROVE";
- public static final String REJECT = "REJECT";
- public static final String PENDING = "PENDING";
-
- public Result<Void> canAddUser(AuthzTrans trans, UserRoleDAO.Data data,
- List<ApprovalDAO.Data> approvals) {
- // get the approval policy for the organization
-
- // get the list of approvals with an accept status
-
- // validate the approvals against the policy
-
- // for now check if all approvals are received and return
- // SUCCESS/FAILURE/SKIP
- boolean bReject = false;
- boolean bPending = false;
-
- for (ApprovalDAO.Data approval : approvals) {
- if (approval.status.equals(REJECT)) {
- bReject = true;
- } else if (approval.status.equals(PENDING)) {
- bPending = true;
- }
- }
- if (bReject) {
- return Result.err(Status.ERR_Policy,
- "Approval Polocy not conformed");
- }
- if (bPending) {
- return Result.err(Status.ERR_ActionNotCompleted,
- "Required Approvals not received");
- }
-
- return Result.ok();
- }
-
- private static final String NO_CACHE_NAME = "No Cache Data named %s";
-
- public Result<Void> clearCache(AuthzTrans trans, String cname) {
- boolean all = "all".equals(cname);
- Result<Void> rv = null;
-
- if (all || NsDAO.TABLE.equals(cname)) {
- int seg[] = series(NsDAO.CACHE_SEG);
- for(int i: seg) {cacheClear(trans, NsDAO.TABLE,i);}
- rv = cacheInfoDAO.touch(trans, NsDAO.TABLE, seg);
- }
- if (all || PermDAO.TABLE.equals(cname)) {
- int seg[] = series(NsDAO.CACHE_SEG);
- for(int i: seg) {cacheClear(trans, PermDAO.TABLE,i);}
- rv = cacheInfoDAO.touch(trans, PermDAO.TABLE,seg);
- }
- if (all || RoleDAO.TABLE.equals(cname)) {
- int seg[] = series(NsDAO.CACHE_SEG);
- for(int i: seg) {cacheClear(trans, RoleDAO.TABLE,i);}
- rv = cacheInfoDAO.touch(trans, RoleDAO.TABLE,seg);
- }
- if (all || UserRoleDAO.TABLE.equals(cname)) {
- int seg[] = series(NsDAO.CACHE_SEG);
- for(int i: seg) {cacheClear(trans, UserRoleDAO.TABLE,i);}
- rv = cacheInfoDAO.touch(trans, UserRoleDAO.TABLE,seg);
- }
- if (all || CredDAO.TABLE.equals(cname)) {
- int seg[] = series(NsDAO.CACHE_SEG);
- for(int i: seg) {cacheClear(trans, CredDAO.TABLE,i);}
- rv = cacheInfoDAO.touch(trans, CredDAO.TABLE,seg);
- }
- if (all || CertDAO.TABLE.equals(cname)) {
- int seg[] = series(NsDAO.CACHE_SEG);
- for(int i: seg) {cacheClear(trans, CertDAO.TABLE,i);}
- rv = cacheInfoDAO.touch(trans, CertDAO.TABLE,seg);
- }
-
- if (rv == null) {
- rv = Result.err(Status.ERR_BadData, NO_CACHE_NAME, cname);
- }
- return rv;
- }
-
- public Result<Void> cacheClear(AuthzTrans trans, String cname,Integer segment) {
- Result<Void> rv;
- if (NsDAO.TABLE.equals(cname)) {
- rv = nsDAO.invalidate(segment);
- } else if (PermDAO.TABLE.equals(cname)) {
- rv = permDAO.invalidate(segment);
- } else if (RoleDAO.TABLE.equals(cname)) {
- rv = roleDAO.invalidate(segment);
- } else if (UserRoleDAO.TABLE.equals(cname)) {
- rv = userRoleDAO.invalidate(segment);
- } else if (CredDAO.TABLE.equals(cname)) {
- rv = credDAO.invalidate(segment);
- } else if (CertDAO.TABLE.equals(cname)) {
- rv = certDAO.invalidate(segment);
- } else {
- rv = Result.err(Status.ERR_BadData, NO_CACHE_NAME, cname);
- }
- return rv;
- }
-
- private int[] series(int max) {
- int[] series = new int[max];
- for (int i = 0; i < max; ++i)
- series[i] = i;
- return series;
- }
-
- public boolean isDelegated(AuthzTrans trans, String user, String approver, Map<String,Result<List<DelegateDAO.Data>>> rldd ) {
- Result<List<DelegateDAO.Data>> userDelegatedFor = rldd.get(user);
- if(userDelegatedFor==null) {
- userDelegatedFor=delegateDAO.readByDelegate(trans, user);
- rldd.put(user, userDelegatedFor);
- }
- if(userDelegatedFor.isOKhasData()) {
- for (DelegateDAO.Data curr : userDelegatedFor.value) {
- if (curr.user.equals(approver) && curr.delegate.equals(user)
- && curr.expires.after(new Date())) {
- return true;
- }
- }
- }
- return false;
- }
-
- public static boolean willSpecialLog(AuthzTrans trans, String user) {
- Boolean b = trans.get(specialLogSlot, null);
- if(b==null) { // we haven't evaluated in this trans for Special Log yet
- if(specialLog==null) {
- return false;
- } else {
- b = specialLog.contains(user);
- trans.put(specialLogSlot, b);
- }
- }
- return b;
- }
-
- public static void logEncryptTrace(AuthzTrans trans, String data) {
- long ti;
- trans.put(transIDSlot, ti=nextTraceID());
- trans.trace().log("id="+Long.toHexString(ti)+",data=\""+trans.env().encryptor().encrypt(data)+'"');
- }
-
- private synchronized static long nextTraceID() {
- return ++traceID;
- }
-
- public static synchronized boolean specialLogOn(AuthzTrans trans, String id) {
- if (specialLog == null) {
- specialLog = new HashSet<String>();
- }
- boolean rc = specialLog.add(id);
- if(rc) {
- trans.trace().printf("Trace on for %s requested by %s",id,trans.user());
- }
- return rc;
- }
-
- public static synchronized boolean specialLogOff(AuthzTrans trans, String id) {
- if(specialLog==null) {
- return false;
- }
- boolean rv = specialLog.remove(id);
- if (specialLog.isEmpty()) {
- specialLog = null;
- }
- if(rv) {
- trans.trace().printf("Trace off for %s requested by %s",id,trans.user());
- }
- return rv;
- }
-
- /**
- * canMove
- * Which Types can be moved
- * @param nsType
- * @return
- */
- public boolean canMove(NsType nsType) {
- boolean rv;
- switch(nsType) {
- case DOT:
- case ROOT:
- case COMPANY:
- case UNKNOWN:
- rv = false;
- break;
- default:
- rv = true;
- }
- return rv;
- }
-
- public boolean isAdmin(AuthzTrans trans, String user, String ns) {
- Date now = new Date();
- Result<List<UserRoleDAO.Data>> rur = userRoleDAO.read(trans, user,ns+DOT_ADMIN);
- if(rur.isOKhasData()) {for(UserRoleDAO.Data urdd : rur.value){
- if(urdd.expires.after(now)) {
- return true;
- }
- }};
- return false;
- }
-
- public boolean isOwner(AuthzTrans trans, String user, String ns) {
- Result<List<UserRoleDAO.Data>> rur = userRoleDAO.read(trans, user,ns+DOT_OWNER);
- Date now = new Date();
- if(rur.isOKhasData()) {for(UserRoleDAO.Data urdd : rur.value){
- if(urdd.expires.after(now)) {
- return true;
- }
- }};
- return false;
- }
-
- public int countOwner(AuthzTrans trans, String ns) {
- Result<List<UserRoleDAO.Data>> rur = userRoleDAO.readByRole(trans,ns+DOT_OWNER);
- Date now = new Date();
- int count = 0;
- if(rur.isOKhasData()) {for(UserRoleDAO.Data urdd : rur.value){
- if(urdd.expires.after(now)) {
- ++count;
- }
- }};
- return count;
- }
-
- /**
- * Return a Unique String, (same string, if it is already unique), with only
- * lowercase letters, digits and the '.' character.
- *
- * @param name
- * @return
- * @throws IOException
- */
- public static String toUnique(String name) throws IOException {
- byte[] from = name.getBytes();
- StringBuilder sb = new StringBuilder();
- byte f;
- for(int i=0;i<from.length;++i) {
- f=(byte)(from[i]); // printables;
- sb.append((char)((f>>4)+0x61));
- sb.append((char)((f&0x0F)+0x61));
- }
- return sb.toString();
- }
-
- public static String fromUnique(String name) throws IOException {
- byte[] from = name.getBytes();
- StringBuilder sb = new StringBuilder();
- char c;
- for(int i=0;i<from.length;++i) {
- c = (char)((from[i]-0x61)<<4);
- c |= (from[++i]-0x61);
- sb.append(c);
- }
- return sb.toString();
- }
+ // DON'T CHANGE FROM lower Case!!!
+ public enum Type {
+ ns, role, perm, cred
+ };
+
+ public static final String OWNER="owner";
+ public static final String ADMIN="admin";
+ public static final String DOT_OWNER=".owner";
+ public static final String DOT_ADMIN=".admin";
+ public static final String ACCESS = "access";
+
+ static final String ASTERIX = "*";
+
+ public enum Access {
+ read, write, create
+ };
+
+ public static final String READ = Access.read.name();
+ public static final String WRITE = Access.write.name();
+ public static final String CREATE = Access.create.name();
+
+ public static final String ROLE = Type.role.name();
+ public static final String PERM = Type.perm.name();
+ public static final String NS = Type.ns.name();
+ public static final String CRED = Type.cred.name();
+ private static final String DELG = "delg";
+ public static final String ROOT_NS = Define.isInitialized() ? Define.ROOT_NS() : "undefined";
+ public static final String ATTRIB = "attrib";
+
+
+ public static final int MAX_SCOPE = 10;
+ public static final int APP_SCOPE = 3;
+ public static final int COMPANY_SCOPE = 2;
+ static Slot PERMS;
+
+ private static Set<String> specialLog = null;
+ public static final Random random = new SecureRandom();
+ private static long traceID = random.nextLong();
+ private static Slot specialLogSlot = null;
+ private static Slot transIDSlot = null;
+
+
+ private final HistoryDAO historyDAO;
+ public HistoryDAO historyDAO() {
+ return historyDAO;
+ }
+
+ private final CachedNSDAO nsDAO;
+ public CachedNSDAO nsDAO() {
+ return nsDAO;
+ }
+
+ private final CachedRoleDAO roleDAO;
+ public CachedRoleDAO roleDAO() {
+ return roleDAO;
+ }
+
+ private final CachedPermDAO permDAO;
+ public CachedPermDAO permDAO() {
+ return permDAO;
+ }
+
+ private final CachedUserRoleDAO userRoleDAO;
+ public CachedUserRoleDAO userRoleDAO() {
+ return userRoleDAO;
+ }
+
+ private final CachedCredDAO credDAO;
+ public CachedCredDAO credDAO() {
+ return credDAO;
+ }
+
+ private final CachedCertDAO certDAO;
+ public CachedCertDAO certDAO() {
+ return certDAO;
+ }
+
+ private final DelegateDAO delegateDAO;
+ public DelegateDAO delegateDAO() {
+ return delegateDAO;
+ }
+
+ private final FutureDAO futureDAO;
+ public FutureDAO futureDAO() {
+ return futureDAO;
+ }
+
+ private final ApprovalDAO approvalDAO;
+ public ApprovalDAO approvalDAO() {
+ return approvalDAO;
+ }
+
+ public final LocateDAO locateDAO;
+ public LocateDAO locateDAO() {
+ return locateDAO;
+ }
+
+ private final CacheInfoDAO cacheInfoDAO;
+ private final int cldays;
+ private final boolean alwaysSpecial;
+
+ public Question(AuthzTrans trans, Cluster cluster, String keyspace) throws APIException, IOException {
+ PERMS = trans.slot("USER_PERMS");
+ trans.init().log("Instantiating DAOs");
+ long expiresIn = Long.parseLong(trans.getProperty(Config.AAF_USER_EXPIRES, Config.AAF_USER_EXPIRES_DEF));
+ historyDAO = new HistoryDAO(trans, cluster, keyspace);
+
+ // Deal with Cached Entries
+ cacheInfoDAO = new CacheInfoDAO(trans, historyDAO);
+
+ nsDAO = new CachedNSDAO(new NsDAO(trans, historyDAO, cacheInfoDAO),cacheInfoDAO, expiresIn);
+ permDAO = new CachedPermDAO(new PermDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
+ roleDAO = new CachedRoleDAO(new RoleDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
+ userRoleDAO = new CachedUserRoleDAO(new UserRoleDAO(trans, historyDAO,cacheInfoDAO), cacheInfoDAO, expiresIn);
+ credDAO = new CachedCredDAO(new CredDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
+ certDAO = new CachedCertDAO(new CertDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
+
+ locateDAO = new LocateDAO(trans,historyDAO);
+ futureDAO = new FutureDAO(trans, historyDAO);
+ delegateDAO = new DelegateDAO(trans, historyDAO);
+ approvalDAO = new ApprovalDAO(trans, historyDAO);
+
+ if (specialLogSlot==null) {
+ specialLogSlot = trans.slot(AuthzTransFilter.SPECIAL_LOG_SLOT);
+ }
+
+ if (transIDSlot==null) {
+ transIDSlot = trans.slot(AuthzTransFilter.TRANS_ID_SLOT);
+ }
+
+ AbsCassDAO.primePSIs(trans);
+
+ cldays = Integer.parseInt(trans.getProperty(Config.AAF_CRED_WARN_DAYS, Config.AAF_CRED_WARN_DAYS_DFT));
+
+ alwaysSpecial = Boolean.parseBoolean(trans.getProperty("aaf_always_special", Boolean.FALSE.toString()));
+ }
+
+ public void startTimers(AuthzEnv env) {
+ // Only want to aggressively cleanse User related Caches... The others,
+ // just normal refresh
+ CachedDAO.startCleansing(env, credDAO, userRoleDAO);
+ CachedDAO.startRefresh(env, cacheInfoDAO);
+ }
+
+ public void close(AuthzTrans trans) {
+ historyDAO.close(trans);
+ cacheInfoDAO.close(trans);
+ nsDAO.close(trans);
+ permDAO.close(trans);
+ roleDAO.close(trans);
+ userRoleDAO.close(trans);
+ credDAO.close(trans);
+ certDAO.close(trans);
+ delegateDAO.close(trans);
+ futureDAO.close(trans);
+ approvalDAO.close(trans);
+ }
+
+ public Result<PermDAO.Data> permFrom(AuthzTrans trans, String type,
+ String instance, String action) {
+ Result<NsDAO.Data> rnd = deriveNs(trans, type);
+ if (rnd.isOK()) {
+ return Result.ok(new PermDAO.Data(new NsSplit(rnd.value, type),
+ instance, action));
+ } else {
+ return Result.err(rnd);
+ }
+ }
+
+ /**
+ * getPermsByUser
+ *
+ * Because this call is frequently called internally, AND because we already
+ * look for it in the initial Call, we cache within the Transaction
+ *
+ * @param trans
+ * @param user
+ * @return
+ */
+ public Result<List<PermDAO.Data>> getPermsByUser(AuthzTrans trans, String user, boolean lookup) {
+ return PermLookup.get(trans, this, user).getPerms(lookup);
+ }
+
+ public Result<List<PermDAO.Data>> getPermsByUserFromRolesFilter(AuthzTrans trans, String user, String forUser) {
+ PermLookup plUser = PermLookup.get(trans, this, user);
+ Result<Set<String>> plPermNames = plUser.getPermNames();
+ if (plPermNames.notOK()) {
+ return Result.err(plPermNames);
+ }
+
+ Set<String> nss;
+ if (forUser.equals(user)) {
+ nss = null;
+ } else {
+ // Setup a TreeSet to check on Namespaces to
+ nss = new TreeSet<>();
+ PermLookup fUser = PermLookup.get(trans, this, forUser);
+ Result<Set<String>> forUpn = fUser.getPermNames();
+ if (forUpn.notOK()) {
+ return Result.err(forUpn);
+ }
+
+ for (String pn : forUpn.value) {
+ Result<String[]> decoded = PermDAO.Data.decodeToArray(trans, this, pn);
+ if (decoded.isOKhasData()) {
+ nss.add(decoded.value[0]);
+ } else {
+ trans.error().log(pn,", derived from a Role, is invalid:",decoded.errorString());
+ }
+ }
+ }
+
+ List<PermDAO.Data> rlpUser = new ArrayList<>();
+ Result<PermDAO.Data> rpdd;
+ PermDAO.Data pdd;
+ for (String pn : plPermNames.value) {
+ rpdd = PermDAO.Data.decode(trans, this, pn);
+ if (rpdd.isOKhasData()) {
+ pdd=rpdd.value;
+ if (nss==null || nss.contains(pdd.ns)) {
+ rlpUser.add(pdd);
+ }
+ } else {
+ trans.error().log(pn,", derived from a Role, is invalid. Run Data Cleanup:",rpdd.errorString());
+ }
+ }
+ return Result.ok(rlpUser);
+ }
+
+ public Result<List<PermDAO.Data>> getPermsByType(AuthzTrans trans, String perm) {
+ Result<NsSplit> nss = deriveNsSplit(trans, perm);
+ if (nss.notOK()) {
+ return Result.err(nss);
+ }
+ return permDAO.readByType(trans, nss.value.ns, nss.value.name);
+ }
+
+ public Result<List<PermDAO.Data>> getPermsByName(AuthzTrans trans,
+ String type, String instance, String action) {
+ Result<NsSplit> nss = deriveNsSplit(trans, type);
+ if (nss.notOK()) {
+ return Result.err(nss);
+ }
+ return permDAO.read(trans, nss.value.ns, nss.value.name, instance,action);
+ }
+
+ public Result<List<PermDAO.Data>> getPermsByRole(AuthzTrans trans, String role, boolean lookup) {
+ Result<NsSplit> nss = deriveNsSplit(trans, role);
+ if (nss.notOK()) {
+ return Result.err(nss);
+ }
+
+ Result<List<RoleDAO.Data>> rlrd = roleDAO.read(trans, nss.value.ns,
+ nss.value.name);
+ if (rlrd.notOKorIsEmpty()) {
+ return Result.err(rlrd);
+ }
+ // Using Set to avoid duplicates
+ Set<String> permNames = new HashSet<>();
+ if (rlrd.isOKhasData()) {
+ for (RoleDAO.Data drr : rlrd.value) {
+ permNames.addAll(drr.perms(false));
+ }
+ }
+
+ // Note: It should be ok for a Valid user to have no permissions -
+ // Jonathan 8/12/2013
+ List<PermDAO.Data> perms = new ArrayList<>();
+ for (String perm : permNames) {
+ Result<PermDAO.Data> pr = PermDAO.Data.decode(trans, this, perm);
+ if (pr.notOK()) {
+ return Result.err(pr);
+ }
+
+ if (lookup) {
+ Result<List<PermDAO.Data>> rlpd = permDAO.read(trans, pr.value);
+ if (rlpd.isOKhasData()) {
+ for (PermDAO.Data pData : rlpd.value) {
+ perms.add(pData);
+ }
+ }
+ } else {
+ perms.add(pr.value);
+ }
+ }
+
+ return Result.ok(perms);
+ }
+
+ public Result<List<RoleDAO.Data>> getRolesByName(AuthzTrans trans,
+ String role) {
+ Result<NsSplit> nss = deriveNsSplit(trans, role);
+ if (nss.notOK()) {
+ return Result.err(nss);
+ }
+ String r = nss.value.name;
+ if (r.endsWith(".*")) { // do children Search
+ return roleDAO.readChildren(trans, nss.value.ns,
+ r.substring(0, r.length() - 2));
+ } else if (ASTERIX.equals(r)) {
+ return roleDAO.readChildren(trans, nss.value.ns, ASTERIX);
+ } else {
+ return roleDAO.read(trans, nss.value.ns, r);
+ }
+ }
+
+ /**
+ * Derive NS
+ *
+ * Given a Child Namespace, figure out what the best Namespace parent is.
+ *
+ * For instance, if in the NS table, the parent "org.osaaf" exists, but not
+ * "org.osaaf.child" or "org.osaaf.a.b.c", then passing in either
+ * "org.osaaf.child" or "org.osaaf.a.b.c" will return "org.osaaf"
+ *
+ * Uses recursive search on Cached DAO data
+ *
+ * @param trans
+ * @param child
+ * @return
+ */
+ public Result<NsDAO.Data> deriveNs(AuthzTrans trans, String child) {
+ Result<List<NsDAO.Data>> r = nsDAO.read(trans, child);
+
+ if (r.isOKhasData()) {
+ return Result.ok(r.value.get(0));
+ } else {
+ int dot;
+ if (child==null) {
+ return Result.err(Status.ERR_NsNotFound, "No Namespace");
+ } else {
+ dot = child.lastIndexOf('.');
+ }
+ if (dot < 0) {
+ return Result.err(Status.ERR_NsNotFound, "No Namespace for [%s]", child);
+ } else {
+ return deriveNs(trans, child.substring(0, dot));
+ }
+ }
+ }
+
+ public Result<NsDAO.Data> deriveFirstNsForType(AuthzTrans trans, String str, NsType type) {
+ NsDAO.Data nsd;
+
+ for (String lookup = str;!".".equals(lookup) && lookup!=null;) {
+ Result<List<NsDAO.Data>> rld = nsDAO.read(trans, lookup);
+ if (rld.isOKhasData()) {
+ nsd=rld.value.get(0);
+ lookup = nsd.parent;
+ if (type.type == nsd.type) {
+ return Result.ok(nsd);
+ } else {
+ int dot = str.lastIndexOf('.');
+
+ if (dot < 0) {
+ return Result.err(Status.ERR_NsNotFound, "No Namespace for [%s]", str);
+ } else {
+ return deriveFirstNsForType(trans, str.substring(0, dot),type);
+ }
+ }
+ } else {
+ int dot = str.lastIndexOf('.');
+
+ if (dot < 0) {
+ return Result.err(Status.ERR_NsNotFound,"There is no valid Company Namespace for %s",str);
+ } else {
+ return deriveFirstNsForType(trans, str.substring(0, dot),type);
+ }
+ }
+ }
+ return Result.err(Status.ERR_NotFound, str + " does not contain type " + type.name());
+ }
+
+ public Result<NsSplit> deriveNsSplit(AuthzTrans trans, String child) {
+ Result<NsDAO.Data> ndd = deriveNs(trans, child);
+ if (ndd.isOK()) {
+ NsSplit nss = new NsSplit(ndd.value, child);
+ if (nss.isOK()) {
+ return Result.ok(nss);
+ } else {
+ return Result.err(Status.ERR_NsNotFound,
+ "Cannot split [%s] into valid namespace elements",
+ child);
+ }
+ }
+ return Result.err(ndd);
+ }
+
+ /**
+ * Translate an ID into it's domain
+ *
+ * i.e. myid1234@aaf.att.com results in domain of com.att.aaf
+ *
+ * @param id
+ * @return
+ */
+ public static String domain2ns(String id) {
+ int at = id.indexOf('@');
+ if (at >= 0) {
+ String[] domain = id.substring(at + 1).split("\\.");
+ StringBuilder ns = new StringBuilder(id.length());
+ boolean first = true;
+ for (int i = domain.length - 1; i >= 0; --i) {
+ if (first) {
+ first = false;
+ } else {
+ ns.append('.');
+ }
+ ns.append(domain[i]);
+ }
+ return ns.toString();
+ } else {
+ return "";
+ }
+
+ }
+
+ /**
+ * Validate Namespace of ID@Domain
+ *
+ * Namespace is reverse order of Domain.
+ *
+ * @param trans
+ * @param id
+ * @return
+ */
+ public Result<NsDAO.Data> validNSOfDomain(AuthzTrans trans, String id) {
+ // Take domain, reverse order, and check on NS
+ String ns;
+ if (id.indexOf('@')<0) { // it's already an ns, not an ID
+ ns = id;
+ } else {
+ ns = domain2ns(id);
+ }
+ if (ns.length() > 0) {
+ if (!trans.org().getDomain().equals(ns)) {
+ Result<List<NsDAO.Data>> rlnsd = nsDAO.read(trans, ns);
+ if (rlnsd.isOKhasData()) {
+ return Result.ok(rlnsd.value.get(0));
+ }
+ }
+ }
+ return Result.err(Status.ERR_NsNotFound,
+ "A Namespace is not available for %s", id);
+ }
+
+ public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,NsDAO.Data ndd, Access access) {
+ // <ns>.access|:role:<role name>|<read|write>
+ String ns = ndd.name;
+ int last;
+ do {
+ if (isGranted(trans, user, ns, ACCESS, ":ns", access.name())) {
+ return Result.ok(ndd);
+ }
+ if ((last = ns.lastIndexOf('.')) >= 0) {
+ ns = ns.substring(0, last);
+ }
+ } while (last >= 0);
+ // com.att.aaf.ns|:<client ns>:ns|<access>
+ // AAF-724 - Make consistent response for May User", and not take the
+ // last check... too confusing.
+ Result<NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, ":" + ndd.name + ":ns", access.name());
+ if (rv.isOK()) {
+ return rv;
+ } else if (rv.status==Result.ERR_Backend) {
+ return Result.err(rv);
+ } else {
+ return Result.err(Status.ERR_Denied, "[%s] may not %s in NS [%s]",
+ user, access.name(), ndd.name);
+ }
+ }
+
+ public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user, RoleDAO.Data rdd, Access access) {
+ Result<NsDAO.Data> rnsd = deriveNs(trans, rdd.ns);
+ if (rnsd.isOK()) {
+ return mayUser(trans, user, rnsd.value, rdd, access);
+ }
+ return rnsd;
+ }
+
+ public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user, NsDAO.Data ndd, RoleDAO.Data rdd, Access access) {
+ // 1) Is User in the Role?
+ Result<List<UserRoleDAO.Data>> rurd = userRoleDAO.readUserInRole(trans, user, rdd.fullName());
+ if (rurd.isOKhasData()) {
+ return Result.ok(ndd);
+ }
+
+ String roleInst = ":role:" + rdd.name;
+ // <ns>.access|:role:<role name>|<read|write>
+ String ns = rdd.ns;
+ int last;
+ do {
+ if (isGranted(trans, user, ns,ACCESS, roleInst, access.name())) {
+ return Result.ok(ndd);
+ }
+ if ((last = ns.lastIndexOf('.')) >= 0) {
+ ns = ns.substring(0, last);
+ }
+ } while (last >= 0);
+
+ // Check if Access by Global Role perm
+ // com.att.aaf.ns|:<client ns>:role:name|<access>
+ Result<NsDAO.Data> rnsd = mayUserVirtueOfNS(trans, user, ndd, ":"
+ + rdd.ns + roleInst, access.name());
+ if (rnsd.isOK()) {
+ return rnsd;
+ } else if (rnsd.status==Result.ERR_Backend) {
+ return Result.err(rnsd);
+ }
+
+ // Check if Access to Whole NS
+ // AAF-724 - Make consistent response for May User", and not take the
+ // last check... too confusing.
+ Result<org.onap.aaf.auth.dao.cass.NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd,
+ ":" + rdd.ns + ":ns", access.name());
+ if (rv.isOK()) {
+ return rv;
+ } else if (rnsd.status==Result.ERR_Backend) {
+ return Result.err(rnsd);
+ } else {
+ return Result.err(Status.ERR_Denied, "[%s] may not %s Role [%s]",
+ user, access.name(), rdd.fullName());
+ }
+
+ }
+
+ public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,PermDAO.Data pdd, Access access) {
+ if(pdd.ns.indexOf('@')>-1) {
+ if(user.equals(pdd.ns) || isGranted(trans,user,Define.ROOT_NS(),"access",pdd.instance,READ)) {
+ NsDAO.Data ndd = new NsDAO.Data();
+ ndd.name = user;
+ ndd.type = NsDAO.USER;
+ ndd.parent = "";
+ return Result.ok(ndd);
+ } else {
+ return Result.err(Result.ERR_Security,"Only a User may modify User");
+ }
+ }
+ Result<NsDAO.Data> rnsd = deriveNs(trans, pdd.ns);
+ if (rnsd.isOK()) {
+ return mayUser(trans, user, rnsd.value, pdd, access);
+ }
+ return rnsd;
+ }
+
+ public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,NsDAO.Data ndd, PermDAO.Data pdd, Access access) {
+ if (isGranted(trans, user, pdd.ns, pdd.type, pdd.instance, pdd.action)) {
+ return Result.ok(ndd);
+ }
+ String permInst = ":perm:" + pdd.type + ':' + pdd.instance + ':' + pdd.action;
+ // <ns>.access|:role:<role name>|<read|write>
+ String ns = ndd.name;
+ int last;
+ do {
+ if (isGranted(trans, user, ns, ACCESS, permInst, access.name())) {
+ return Result.ok(ndd);
+ }
+ if ((last = ns.lastIndexOf('.')) >= 0) {
+ ns = ns.substring(0, last);
+ }
+ } while (last >= 0);
+
+ // Check if Access by NS perm
+ // com.att.aaf.ns|:<client ns>:role:name|<access>
+ Result<NsDAO.Data> rnsd = mayUserVirtueOfNS(trans, user, ndd, ":" + pdd.ns + permInst, access.name());
+ if (rnsd.isOK()) {
+ return rnsd;
+ } else if (rnsd.status==Result.ERR_Backend) {
+ return Result.err(rnsd);
+ }
+
+ // Check if Access to Whole NS
+ // AAF-724 - Make consistent response for May User", and not take the
+ // last check... too confusing.
+ Result<NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, ":" + pdd.ns + ":ns", access.name());
+ if (rv.isOK()) {
+ return rv;
+ } else {
+ return Result.err(Status.ERR_Denied,
+ "[%s] may not %s Perm [%s|%s|%s]", user, access.name(),
+ pdd.fullType(), pdd.instance, pdd.action);
+ }
+
+ }
+
+ public Result<Void> mayUser(AuthzTrans trans, DelegateDAO.Data dd, Access access) {
+ try {
+ Result<NsDAO.Data> rnsd = deriveNs(trans, domain2ns(trans.user()));
+ if (rnsd.isOKhasData() && mayUserVirtueOfNS(trans,trans.user(),rnsd.value, ":" + rnsd.value.name + ":ns", access.name()).isOK()) {
+ return Result.ok();
+ }
+ boolean isUser = trans.user().equals(dd.user);
+ boolean isDelegate = dd.delegate != null
+ && (dd.user.equals(dd.delegate) || trans.user().equals(
+ dd.delegate));
+ Organization org = trans.org();
+ switch (access) {
+ case create:
+ if (org.getIdentity(trans, dd.user) == null) {
+ return Result.err(Status.ERR_UserNotFound,
+ "[%s] is not a user in the company database.",
+ dd.user);
+ }
+ if (!dd.user.equals(dd.delegate) && org.getIdentity(trans, dd.delegate) == null) {
+ return Result.err(Status.ERR_UserNotFound,
+ "[%s] is not a user in the company database.",
+ dd.delegate);
+ }
+ if (!trans.requested(REQD_TYPE.force) && dd.user != null && dd.user.equals(dd.delegate)) {
+ return Result.err(Status.ERR_BadData,
+ "[%s] cannot be a delegate for self", dd.user);
+ }
+ if (!isUser && !isGranted(trans, trans.user(), ROOT_NS,DELG,
+ org.getDomain(), Question.CREATE)) {
+ return Result.err(Status.ERR_Denied,
+ "[%s] may not create a delegate for [%s]",
+ trans.user(), dd.user);
+ }
+ break;
+ case read:
+ case write:
+ if (!isUser && !isDelegate &&
+ !isGranted(trans, trans.user(), ROOT_NS,DELG,org.getDomain(), access.name())) {
+ return Result.err(Status.ERR_Denied,
+ "[%s] may not %s delegates for [%s]", trans.user(),
+ access.name(), dd.user);
+ }
+ break;
+ default:
+ return Result.err(Status.ERR_BadData,"Unknown Access type [%s]", access.name());
+ }
+ } catch (Exception e) {
+ return Result.err(e);
+ }
+ return Result.ok();
+ }
+
+ /*
+ * Check (recursively, if necessary), if able to do something based on NS
+ */
+ private Result<NsDAO.Data> mayUserVirtueOfNS(AuthzTrans trans, String user, NsDAO.Data nsd, String ns_and_type, String access) {
+ String ns = nsd.name;
+
+ // If an ADMIN of the Namespace, then allow
+
+ Result<List<UserRoleDAO.Data>> rurd;
+ if ((rurd = userRoleDAO.readUserInRole(trans, user, ns+DOT_ADMIN)).isOKhasData()) {
+ return Result.ok(nsd);
+ } else if (rurd.status==Result.ERR_Backend) {
+ return Result.err(rurd);
+ }
+
+ // If Specially granted Global Permission
+ if (isGranted(trans, user, ROOT_NS,NS, ns_and_type, access)) {
+ return Result.ok(nsd);
+ }
+
+ // Check recur
+
+ int dot = ns.length();
+ if ((dot = ns.lastIndexOf('.', dot - 1)) >= 0) {
+ Result<NsDAO.Data> rnsd = deriveNs(trans, ns.substring(0, dot));
+ if (rnsd.isOK()) {
+ rnsd = mayUserVirtueOfNS(trans, user, rnsd.value, ns_and_type,access);
+ } else if (rnsd.status==Result.ERR_Backend) {
+ return Result.err(rnsd);
+ }
+ if (rnsd.isOK()) {
+ return Result.ok(nsd);
+ } else if (rnsd.status==Result.ERR_Backend) {
+ return Result.err(rnsd);
+ }
+ }
+ return Result.err(Status.ERR_Denied, "%s may not %s %s", user, access,
+ ns_and_type);
+ }
+
+
+ /**
+ * isGranted
+ *
+ * Important function - Check internal Permission Schemes for Permission to
+ * do things
+ *
+ * @param trans
+ * @param type
+ * @param instance
+ * @param action
+ * @return
+ */
+ public boolean isGranted(AuthzTrans trans, String user, String ns, String type,String instance, String action) {
+ Result<List<PermDAO.Data>> perms = getPermsByUser(trans, user, false);
+ if (perms.isOK()) {
+ for (PermDAO.Data pd : perms.value) {
+ if (ns.equals(pd.ns)) {
+ if (type.equals(pd.type)) {
+ if (PermEval.evalInstance(pd.instance, instance)) {
+ if (PermEval.evalAction(pd.action, action)) { // don't return action here, might miss other action
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public Result<Date> doesUserCredMatch(AuthzTrans trans, String user, byte[] cred) throws DAOException {
+ Result<List<CredDAO.Data>> result;
+ TimeTaken tt = trans.start("Read DB Cred", Env.REMOTE);
+ try {
+ result = credDAO.readID(trans, user);
+ } finally {
+ tt.done();
+ }
+
+ Result<Date> rv = null;
+ if (result.isOK()) {
+ if (result.isEmpty()) {
+ rv = Result.err(Status.ERR_UserNotFound, user);
+ if (willSpecialLog(trans,user)) {
+ trans.audit().log("Special DEBUG:", user, " does not exist in DB");
+ }
+ } else {
+ Date now = new Date();
+ // Bug noticed 6/22. Sorting on the result can cause Concurrency Issues.
+ List<CredDAO.Data> cddl;
+ if (result.value.size() > 1) {
+ cddl = new ArrayList<>(result.value.size());
+ for (CredDAO.Data old : result.value) {
+ if (old.type==CredDAO.BASIC_AUTH || old.type==CredDAO.BASIC_AUTH_SHA256) {
+ cddl.add(old);
+ }
+ }
+ if (cddl.size()>1) {
+ Collections.sort(cddl, (a, b) -> b.expires.compareTo(a.expires));
+ }
+ } else {
+ cddl = result.value;
+ }
+
+ Date expired = null;
+ StringBuilder debug = willSpecialLog(trans,user)?new StringBuilder():null;
+ for (CredDAO.Data cdd : cddl) {
+ if (!cdd.id.equals(user)) {
+ trans.error().log("doesUserCredMatch DB call does not match for user: " + user);
+ }
+ if (cdd.expires.after(now)) {
+ byte[] dbcred = cdd.cred.array();
+
+ try {
+ switch(cdd.type) {
+ case CredDAO.BASIC_AUTH:
+ byte[] md5=Hash.hashMD5(cred);
+ if (Hash.compareTo(md5,dbcred)==0) {
+ checkLessThanDays(trans,cldays,now,cdd);
+ trans.setTag(cdd.tag);
+ return Result.ok(cdd.expires);
+ } else if (debug!=null) {
+ load(debug, cdd);
+ }
+ break;
+ case CredDAO.BASIC_AUTH_SHA256:
+ ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + cred.length);
+ bb.putInt(cdd.other);
+ bb.put(cred);
+ byte[] hash = Hash.hashSHA256(bb.array());
+
+ if (Hash.compareTo(hash,dbcred)==0) {
+ checkLessThanDays(trans,cldays,now,cdd);
+ trans.setTag(cdd.tag);
+ return Result.ok(cdd.expires);
+ } else if (debug!=null) {
+ load(debug, cdd);
+ }
+ break;
+ default:
+ trans.error().log("Unknown Credential Type %s for %s, %s",Integer.toString(cdd.type),cdd.id, Chrono.dateTime(cdd.expires));
+ }
+ } catch (NoSuchAlgorithmException e) {
+ trans.error().log(e);
+ }
+ } else {
+ if (expired==null || expired.before(cdd.expires)) {
+ expired = cdd.expires;
+ trans.setTag(cdd.tag);
+ }
+ }
+ } // end for each
+
+ if (expired!=null) {
+ // Note: this is only returned if there are no good Credentials
+ rv = Result.err(Status.ERR_Security,
+ "Credentials expired %s",Chrono.utcStamp(expired));
+ } else {
+ if (debug==null && alwaysSpecial) {
+ debug = new StringBuilder();
+ }
+ if (debug!=null) {
+ debug.append(trans.env().encryptor().encrypt(new String(cred)));
+ rv = Result.err(Status.ERR_Security,String.format("invalid password - %s",debug.toString()));
+ }
+ }
+ }
+ } else {
+ return Result.err(result);
+ }
+ return rv == null ? Result.err(Status.ERR_Security, "Wrong credential") : rv;
+ }
+
+
+ private void load(StringBuilder debug, Data cdd) {
+ debug.append("\nDB Entry: user=");
+ debug.append(cdd.id);
+ debug.append(",type=");
+ debug.append(cdd.type);
+ debug.append(",expires=");
+ debug.append(Chrono.dateTime(cdd.expires));
+ debug.append(",tag=");
+ debug.append(cdd.tag);
+ debug.append('\n');
+ }
+
+
+ private void checkLessThanDays(AuthzTrans trans, int days, Date now, Data cdd) {
+ long close = now.getTime() + (days * 86400000);
+ long cexp=cdd.expires.getTime();
+ if (cexp<close) {
+ int daysLeft = days-(int)((close-cexp)/86400000);
+ trans.audit().printf("user=%s,ip=%s,expires=%s,days=%d,tag=%s,msg=\"Password expires in less than %d day%s\"",
+ cdd.id,trans.ip(),Chrono.dateOnlyStamp(cdd.expires),daysLeft, cdd.tag,
+ daysLeft,daysLeft==1?"":"s");
+ }
+ }
+
+
+ public Result<CredDAO.Data> userCredSetup(AuthzTrans trans, CredDAO.Data cred) {
+ if (cred.type==CredDAO.RAW) {
+ TimeTaken tt = trans.start("Hash Cred", Env.SUB);
+ try {
+ cred.type = CredDAO.BASIC_AUTH_SHA256;
+ cred.other = random.nextInt();
+ ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + cred.cred.capacity());
+ bb.putInt(cred.other);
+ bb.put(cred.cred);
+ byte[] hash = Hash.hashSHA256(bb.array());
+ cred.cred = ByteBuffer.wrap(hash);
+ return Result.ok(cred);
+ } catch (NoSuchAlgorithmException e) {
+ return Result.err(Status.ERR_General,e.getLocalizedMessage());
+ } finally {
+ tt.done();
+ }
+
+ } else if (cred.type==CredDAO.FQI) {
+ cred.cred = null;
+ return Result.ok(cred);
+ }
+ return Result.err(Status.ERR_Security,"invalid/unreadable credential");
+ }
+
+ public Result<Boolean> userCredCheck(AuthzTrans trans, CredDAO.Data orig, final byte[] raw) {
+ TimeTaken tt = trans.start("CheckCred Cred", Env.SUB);
+ try {
+ switch(orig.type) {
+ case CredDAO.BASIC_AUTH_SHA256:
+ ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + raw.length);
+ bb.putInt(orig.other);
+ bb.put(raw);
+ return Result.ok(Hash.compareTo(orig.cred.array(),Hash.hashSHA256(bb.array()))==0);
+ case CredDAO.BASIC_AUTH:
+ return Result.ok( Hash.compareTo(orig.cred.array(), Hash.hashMD5(raw))==0);
+ default:
+ return Result.ok(false);
+ }
+ } catch (NoSuchAlgorithmException e) {
+ return Result.err(Status.ERR_General,e.getLocalizedMessage());
+ } finally {
+ tt.done();
+ }
+ }
+
+ public static final String APPROVED = "APPROVE";
+ public static final String REJECT = "REJECT";
+ public static final String PENDING = "PENDING";
+
+ public Result<Void> canAddUser(AuthzTrans trans, UserRoleDAO.Data data,
+ List<ApprovalDAO.Data> approvals) {
+ // get the approval policy for the organization
+
+ // get the list of approvals with an accept status
+
+ // validate the approvals against the policy
+
+ // for now check if all approvals are received and return
+ // SUCCESS/FAILURE/SKIP
+ boolean bReject = false;
+ boolean bPending = false;
+
+ for (ApprovalDAO.Data approval : approvals) {
+ if (approval.status.equals(REJECT)) {
+ bReject = true;
+ } else if (approval.status.equals(PENDING)) {
+ bPending = true;
+ }
+ }
+ if (bReject) {
+ return Result.err(Status.ERR_Policy,
+ "Approval Polocy not conformed");
+ }
+ if (bPending) {
+ return Result.err(Status.ERR_ActionNotCompleted,
+ "Required Approvals not received");
+ }
+
+ return Result.ok();
+ }
+
+ private static final String NO_CACHE_NAME = "No Cache Data named %s";
+
+ public Result<Void> clearCache(AuthzTrans trans, String cname) {
+ boolean all = "all".equals(cname);
+ Result<Void> rv = null;
+
+ if (all || NsDAO.TABLE.equals(cname)) {
+ int[] seg = series(NsDAO.CACHE_SEG);
+ for (int i: seg) {cacheClear(trans, NsDAO.TABLE,i);}
+ rv = cacheInfoDAO.touch(trans, NsDAO.TABLE, seg);
+ }
+ if (all || PermDAO.TABLE.equals(cname)) {
+ int[] seg = series(PermDAO.CACHE_SEG);
+ for (int i: seg) {cacheClear(trans, PermDAO.TABLE,i);}
+ rv = cacheInfoDAO.touch(trans, PermDAO.TABLE,seg);
+ }
+ if (all || RoleDAO.TABLE.equals(cname)) {
+ int[] seg = series(RoleDAO.CACHE_SEG);
+ for (int i: seg) {cacheClear(trans, RoleDAO.TABLE,i);}
+ rv = cacheInfoDAO.touch(trans, RoleDAO.TABLE,seg);
+ }
+ if (all || UserRoleDAO.TABLE.equals(cname)) {
+ int[] seg = series(UserRoleDAO.CACHE_SEG);
+ for (int i: seg) {cacheClear(trans, UserRoleDAO.TABLE,i);}
+ rv = cacheInfoDAO.touch(trans, UserRoleDAO.TABLE,seg);
+ }
+ if (all || CredDAO.TABLE.equals(cname)) {
+ int[] seg = series(CredDAO.CACHE_SEG);
+ for (int i: seg) {cacheClear(trans, CredDAO.TABLE,i);}
+ rv = cacheInfoDAO.touch(trans, CredDAO.TABLE,seg);
+ }
+ if (all || CertDAO.TABLE.equals(cname)) {
+ int[] seg = series(CertDAO.CACHE_SEG);
+ for (int i: seg) {cacheClear(trans, CertDAO.TABLE,i);}
+ rv = cacheInfoDAO.touch(trans, CertDAO.TABLE,seg);
+ }
+
+ if (rv == null) {
+ rv = Result.err(Status.ERR_BadData, NO_CACHE_NAME, cname);
+ }
+ return rv;
+ }
+
+ public Result<Void> cacheClear(AuthzTrans trans, String cname,Integer segment) {
+ Result<Void> rv;
+ if (NsDAO.TABLE.equals(cname)) {
+ rv = nsDAO.invalidate(segment);
+ } else if (PermDAO.TABLE.equals(cname)) {
+ rv = permDAO.invalidate(segment);
+ } else if (RoleDAO.TABLE.equals(cname)) {
+ rv = roleDAO.invalidate(segment);
+ } else if (UserRoleDAO.TABLE.equals(cname)) {
+ rv = userRoleDAO.invalidate(segment);
+ } else if (CredDAO.TABLE.equals(cname)) {
+ rv = credDAO.invalidate(segment);
+ } else if (CertDAO.TABLE.equals(cname)) {
+ rv = certDAO.invalidate(segment);
+ } else {
+ rv = Result.err(Status.ERR_BadData, NO_CACHE_NAME, cname);
+ }
+ return rv;
+ }
+
+ private int[] series(int max) {
+ int[] series = new int[max];
+ for (int i = 0; i < max; ++i)
+ series[i] = i;
+ return series;
+ }
+
+ public boolean isDelegated(AuthzTrans trans, String user, String approver, Map<String,Result<List<DelegateDAO.Data>>> rldd ) {
+ Result<List<DelegateDAO.Data>> userDelegatedFor = rldd.get(user);
+ if (userDelegatedFor==null) {
+ userDelegatedFor=delegateDAO.readByDelegate(trans, user);
+ rldd.put(user, userDelegatedFor);
+ }
+ if (userDelegatedFor.isOKhasData()) {
+ for (DelegateDAO.Data curr : userDelegatedFor.value) {
+ if (curr.user.equals(approver) && curr.delegate.equals(user)
+ && curr.expires.after(new Date())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static boolean willSpecialLog(AuthzTrans trans, String user) {
+ Boolean b = trans.get(specialLogSlot, null);
+ if (b==null) { // we haven't evaluated in this trans for Special Log yet
+ if (specialLog==null) {
+ return false;
+ } else {
+ b = specialLog.contains(user);
+ trans.put(specialLogSlot, b);
+ }
+ }
+ return b;
+ }
+
+ public static void logEncryptTrace(AuthzTrans trans, String data) {
+ long ti;
+ trans.put(transIDSlot, ti=nextTraceID());
+ trans.trace().log("id="+Long.toHexString(ti)+",data=\""+trans.env().encryptor().encrypt(data)+'"');
+ }
+
+ private synchronized static long nextTraceID() {
+ return ++traceID;
+ }
+
+ public static synchronized boolean specialLogOn(AuthzTrans trans, String id) {
+ if (specialLog == null) {
+ specialLog = new HashSet<>();
+ }
+ boolean rc = specialLog.add(id);
+ if (rc) {
+ trans.trace().printf("Trace on for %s requested by %s",id,trans.user());
+ }
+ return rc;
+ }
+
+ public static synchronized boolean specialLogOff(AuthzTrans trans, String id) {
+ if (specialLog==null) {
+ return false;
+ }
+ boolean rv = specialLog.remove(id);
+ if (specialLog.isEmpty()) {
+ specialLog = null;
+ }
+ if (rv) {
+ trans.trace().printf("Trace off for %s requested by %s",id,trans.user());
+ }
+ return rv;
+ }
+
+ /**
+ * canMove
+ * Which Types can be moved
+ * @param nsType
+ * @return
+ */
+ public boolean canMove(NsType nsType) {
+ boolean rv;
+ switch(nsType) {
+ case DOT:
+ case ROOT:
+ case COMPANY:
+ case UNKNOWN:
+ rv = false;
+ break;
+ default:
+ rv = true;
+ }
+ return rv;
+ }
+
+ public boolean isAdmin(AuthzTrans trans, String user, String ns) {
+ Date now = new Date();
+ Result<List<UserRoleDAO.Data>> rur = userRoleDAO.read(trans, user,ns+DOT_ADMIN);
+ if (rur.isOKhasData()) {
+ for (UserRoleDAO.Data urdd : rur.value){
+ if (urdd.expires.after(now)) {
+ return true;
+ }
+ }
+ };
+ return false;
+ }
+
+ public boolean isOwner(AuthzTrans trans, String user, String ns) {
+ Result<List<UserRoleDAO.Data>> rur = userRoleDAO.read(trans, user,ns+DOT_OWNER);
+ Date now = new Date();
+ if (rur.isOKhasData()) {for (UserRoleDAO.Data urdd : rur.value){
+ if (urdd.expires.after(now)) {
+ return true;
+ }
+ }};
+ return false;
+ }
+
+ public int countOwner(AuthzTrans trans, String ns) {
+ Result<List<UserRoleDAO.Data>> rur = userRoleDAO.readByRole(trans,ns+DOT_OWNER);
+ Date now = new Date();
+ int count = 0;
+ if (rur.isOKhasData()) {for (UserRoleDAO.Data urdd : rur.value){
+ if (urdd.expires.after(now)) {
+ ++count;
+ }
+ }};
+ return count;
+ }
+
+ /**
+ * Return a Unique String, (same string, if it is already unique), with only
+ * lowercase letters, digits and the '.' character.
+ *
+ * @param name
+ * @return
+ * @throws IOException
+ */
+ public static String toUnique(String name) throws IOException {
+ byte[] from = name.getBytes();
+ StringBuilder sb = new StringBuilder();
+ byte f;
+ for (int i=0;i<from.length;++i) {
+ f=(byte)(from[i]); // printables;
+ sb.append((char)((f>>4)+0x61));
+ sb.append((char)((f&0x0F)+0x61));
+ }
+ return sb.toString();
+ }
+
+ public static String fromUnique(String name) throws IOException {
+ byte[] from = name.getBytes();
+ StringBuilder sb = new StringBuilder();
+ char c;
+ for (int i=0;i<from.length;++i) {
+ c = (char)((from[i]-0x61)<<4);
+ c |= (from[++i]-0x61);
+ sb.append(c);
+ }
+ return sb.toString();
+ }
}