Remove Tabs, per Jococo
[aaf/authz.git] / cadi / aaf / src / main / java / org / onap / aaf / cadi / aaf / PermEval.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * ===========================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END====================================================
19  *
20  */
21
22 package org.onap.aaf.cadi.aaf;
23
24 import org.onap.aaf.misc.env.util.Split;
25
26
27 public class PermEval {
28     public static final char START_REGEX_CHAR = '!';
29     public static final char START_INST_KEY_CHAR=':';
30     public static final char ALT_START_INST_KEY_CHAR='/';
31
32     public static final char LIST_SEP = ',';
33     public static final String INST_KEY_REGEX = new StringBuilder().append(START_INST_KEY_CHAR).toString();
34     public static final String ASTERIX = "*";
35
36     /**
37      * Evaluate Instance
38      *
39      * Instance can be more complex.  It can be a string, a Regular Expression, or a ":" separated Key
40      * who's parts can also be a String, Regular Expression.
41      *
42      * sInst = Server's Instance
43      * In order to prevent false matches, keys must be the same length to count as equal
44      * Changing this will break existing users, like Cassandra.  Jonathan 9-4-2015
45      */
46     public static boolean evalInstance(String sInst, String pInst) {
47         if (sInst == null || pInst == null) {
48             return false;
49         }
50         if (sInst == "" || pInst == "") {
51             return false;
52         }
53         if (ASTERIX.equals(sInst)) {
54             return true;            // If Server's String is "*", then it accepts every Instance
55         }
56         char firstChar = pInst.charAt(0);
57         char startChar = firstChar==ALT_START_INST_KEY_CHAR?ALT_START_INST_KEY_CHAR:START_INST_KEY_CHAR;
58         switch(pInst.charAt(0)) {                          // First char
59             case START_REGEX_CHAR:                            // Evaluate as Regular Expression
60                 String pItem = pInst.substring(1);
61                 String first = Split.split(LIST_SEP,sInst)[0];         // allow for "," definition in Action
62                 return first.matches(pItem);
63
64             case START_INST_KEY_CHAR:                        // Evaluate a special Key field, i.e.:xyz:*:!df.*
65             case ALT_START_INST_KEY_CHAR:                    // Also allow '/' as special Key Field, i.e. /xyz/*/!.*
66                 if (sInst.charAt(0)==startChar) {  // To compare key-to-key, both strings must be keys
67                     String[] skeys=Split.split(startChar,sInst);
68                     String[] pkeys=Split.split(startChar,pInst);
69                     if (pkeys.length<skeys.length) {
70                         return false;
71                     } else if(pkeys.length > skeys.length && 
72                              (skeys.length==0 || !ASTERIX.equals(skeys[skeys.length-1]))) {
73                            return false;
74                     }
75
76                     boolean pass = true;
77                     for (int i=1;pass && i<skeys.length;++i) {                  // We start at 1, because the first one, being ":" is always ""
78                         if (ASTERIX.equals(skeys[i])) {
79                             if(i==skeys.length-1) {
80                                 // accept all after
81                                 return true;
82                             }
83                             continue;               // Server data accepts all for this key spot
84                         }
85                         pass = false;
86                         for (String sItem : Split.split(LIST_SEP,skeys[i])) {        // allow for "," definition in Action
87                             if (pkeys[i].length()==0) {
88                                 if (pass=sItem.length()==0) {
89                                     break;                                  // Both Empty, keep checking
90                                 }
91                             } else if (sItem.length()>0 && sItem.charAt(0)==START_REGEX_CHAR) { // Check Server side when wildcarding like *
92                                 if (pass=pkeys[i].matches(sItem.substring(1))) {
93                                     break;                                  // Matches, keep checking
94                                 }
95                             } else if (skeys[i].endsWith(ASTERIX)) {
96                                 if (pass=endAsterixCompare(skeys[i],pkeys[i])) {
97                                     break;
98                                 }
99                             } else if (pass=sItem.equals(pkeys[i])) {
100                                 break;                                   // Equal, keep checking
101                             }
102                         }
103                     }
104                     return pass;                                             // return whether passed all key checks
105                 }
106                 return false;                                 // if first chars aren't the same, further String compare not necessary
107             default:                                        // Evaluate as String Compare
108                 for (String sItem : Split.split(LIST_SEP,sInst)) {    // allow for "," separator //TODO is this only for actions?
109                     if ((sItem.endsWith(ASTERIX)) && (endAsterixCompare(sInst, pInst))) {
110                         return true;
111                     } else if (sItem.equals(pInst)) {
112                         return true;
113                     }
114                 }
115                 return false;
116         }
117     }
118
119      private static boolean endAsterixCompare(String sInst, String pInst) {
120         final int len = sInst.length()-1;
121         if (pInst.length()<len) {
122             return false;
123         }
124         for (int j=0;j<len;++j) {
125             if (pInst.charAt(j)!=sInst.charAt(j)) {
126                 return false;
127             }
128         }
129         return true;
130     }
131
132     /**
133      * Evaluate Action
134      *
135      * sAction = Stored Action...
136      * pAction = Present Action... the Permission to validate against.
137      * Action is not quite as complex.  But we write it in this function so it can be consistent
138      */
139     public static boolean evalAction(String sAction,String pAction) {
140         if (ASTERIX.equals(sAction))return true;               // If Server's String is "*", then it accepts every Action
141         if (pAction == "") return false;
142         for (String sItem : Split.split(LIST_SEP,sAction)) {         // allow for "," definition in Action
143             if (pAction.charAt(0)==START_REGEX_CHAR?       // First char
144                     sItem.matches(pAction.substring(1)):   // Evaluate as Regular Expression
145                     sItem.equals(pAction))                 // Evaluate as String Compare
146                 return true;
147         }
148         return false;
149     }
150
151 }