* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeMap;
import java.util.TreeSet;
import org.onap.aaf.auth.common.Define;
/**
* Question HL DAO
- *
+ *
* A Data Access Combination Object which asks Security and other Questions
- *
+ *
* @author Jonathan
*
*/
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;
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()));
}
-
+
/**
* Note: This Constructor created for JUNIT Purposes. Do not use otherwise.
*/
CachedDAO.startCleansing(env, credDAO, userRoleDAO);
CachedDAO.startRefresh(env, cacheInfoDAO);
}
-
+
public void close(AuthzTrans trans) {
historyDAO.close(trans);
cacheInfoDAO.close(trans);
pdd.type = type.substring(colon+1);
pdd.instance = instance;
pdd.action = action;
-
+
return Result.ok(pdd);
} else {
return Result.err(Result.ERR_BadData,"Could not extract ns and type from " + type);
/**
* 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
+ // 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()) {
trans.error().log(pn,", derived from a Role, is invalid. Run Data Cleanup:",rpdd.errorString());
}
}
- return Result.ok(rlpUser);
+ return Result.ok(rlpUser);
}
public Result<List<PermDAO.Data>> getPermsByType(AuthzTrans trans, String type) {
if (nss.notOK()) {
return Result.err(nss);
}
-
+
return permDAO.read(trans, nss.value.ns, nss.value.name, instance,action);
}
}
/**
* 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 {
return Result.ok(nsd);
} else {
int dot = str.lastIndexOf('.');
-
+
if (dot < 0) {
return Result.err(Status.ERR_NsNotFound, "No Namespace for [%s]", str);
} else {
}
} else {
int dot = str.lastIndexOf('.');
-
+
if (dot < 0) {
return Result.err(Status.ERR_NsNotFound,"There is no valid Company Namespace for %s",str);
} else {
/**
* Translate an ID into it's domain
- *
+ *
* i.e. myid1234@aaf.att.com results in domain of com.att.aaf
- *
+ *
* @param id
* @return
*/
/**
* Validate Namespace of ID@Domain
- *
+ *
* Namespace is reverse order of Domain.
- *
+ *
* @param trans
* @param id
* @return
ns = domain2ns(id);
}
if (ns.length() > 0) {
- if (!trans.org().getDomain().equals(ns)) {
+ 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));
ns = ns.substring(0, last);
}
} while (last >= 0);
-
+
// SAFETY - Do not allow these when NS is Root
if(!isRoot) {
// com.att.aaf.ns|:<client ns>:ns|<access>
// 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,
+ Result<org.onap.aaf.auth.dao.cass.NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd,
":" + rdd.ns + ":ns", access.name());
if (rv.isOK()) {
return rv;
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;
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,
+ if (!isUser) {
+ String supportedDomain = org.supportedDomain(dd.user);
+ if(supportedDomain==null) {
+ return Result.err(Status.ERR_Denied,
+ "[%s] may not create a delegate for the domain for [%s]",
+ trans.user(), dd.user);
+ } else if(!isGranted(trans, trans.user(), ROOT_NS,DELG,supportedDomain,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 &&
+ 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(),
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);
ns_and_type);
}
-
+
/**
* isGranted
- *
+ *
* Important function - Check internal Permission Schemes for Permission to
* do things
- *
+ *
* @param trans
* @param type
* @param instance
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
+ if (PermEval.evalAction(pd.action, action)) { // don't return action here, might miss other action
return true;
}
}
}
} else {
Date now = new Date();
- // Bug noticed 6/22. Sorting on the result can cause Concurrency Issues.
- List<CredDAO.Data> cddl;
+ // Bug noticed 6/22. Sorting on the result can cause Concurrency Issues.
+ // 9/14/2019. Use TreeSet for sorting, and using only the LAST of a Tagged entry
+ Collection<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);
+ Map<String,CredDAO.Data> mcdd = new TreeMap<>();
+ CredDAO.Data cdd;
+ String tag;
+ int pseudoTag = 0;
+ for (CredDAO.Data rcdd : result.value) {
+ if (rcdd.type==CredDAO.BASIC_AUTH || rcdd.type==CredDAO.BASIC_AUTH_SHA256) {
+ if(rcdd.tag==null) {
+ mcdd.put(Integer.toString(++pseudoTag),rcdd);
+ } else {
+ tag = rcdd.tag;
+ cdd = mcdd.get(tag);
+ if(cdd==null || cdd.expires.before(rcdd.expires)) {
+ mcdd.put(tag,rcdd);
+ }
+ }
}
}
- if (cddl.size()>1) {
- Collections.sort(cddl, (a, b) -> b.expires.compareTo(a.expires));
- }
+ cddl = mcdd.values();
} else {
cddl = result.value;
}
-
+
Date expired = null;
StringBuilder debug = willSpecialLog(trans,user)?new StringBuilder():null;
for (CredDAO.Data cdd : cddl) {
}
if (cdd.expires.after(now)) {
byte[] dbcred = cdd.cred.array();
-
+
try {
switch(cdd.type) {
case CredDAO.BASIC_AUTH:
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);
}
}
} // end for each
-
+
if (expired!=null) {
// Note: this is only returned if there are no good Credentials
rv = Result.err(Status.ERR_Security,
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,
+ cdd.id,trans.ip(),Chrono.dateOnlyStamp(cdd.expires),daysLeft, cdd.tag,
daysLeft,daysLeft==1?"":"s");
}
}
} 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) {
Result<Boolean> rv;
TimeTaken tt = trans.start("CheckCred Cred", Env.SUB);
}
return b;
}
-
+
public static void logEncryptTrace(AuthzTrans trans, String data) {
long ti;
trans.put(transIDSlot, ti=nextTraceID());
}
boolean rc = specialLog.add(id);
if (rc) {
- trans.trace().printf("Trace on for %s requested by %s",id,trans.user());
+ trans.trace().printf("Trace on for %s requested by %s",id,trans.user());
}
return rc;
}
specialLog = null;
}
if (rv) {
- trans.trace().printf("Trace off for %s requested by %s",id,trans.user());
+ trans.trace().printf("Trace off for %s requested by %s",id,trans.user());
}
return rv;
}
- /**
+ /**
* canMove
* Which Types can be moved
* @param nsType
};
return false;
}
-
+
public boolean isOwner(AuthzTrans trans, String user, String ns) {
Result<List<UserRoleDAO.Data>> rur = userRoleDAO().read(trans, user,ns+DOT_OWNER);
if (rur.isOKhasData()) {for (UserRoleDAO.Data urdd : rur.value){
}};
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
+ * @throws IOException
*/
public static String toUnique(String name) throws IOException {
byte[] from = name.getBytes();
}
return sb.toString();
}
-
+
public static String fromUnique(String name) throws IOException {
byte[] from = name.getBytes();
StringBuilder sb = new StringBuilder();