Replaced "==" with equals for string comparisons
[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 ASTERIX = "*";
34
35     /**
36      * Evaluate Instance
37      *
38      * Instance can be more complex.  It can be a string, a Regular Expression, or a ":" separated Key
39      * who's parts can also be a String, Regular Expression.
40      *
41      * sInst = Server's Instance
42      * In order to prevent false matches, keys must be the same length to count as equal
43      * Changing this will break existing users, like Cassandra.  Jonathan 9-4-2015
44      */
45     public static boolean evalInstance(String sInst, String pInst) {
46         if (sInst == null || pInst == null) {
47             return false;
48         }
49         if (sInst.equals("") || pInst.equals("")) {
50             return false;
51         }
52         if (ASTERIX.equals(sInst)) {
53             return true;            // If Server's String is "*", then it accepts every Instance
54         }
55         char firstChar = pInst.charAt(0);
56         char startChar = firstChar==ALT_START_INST_KEY_CHAR?ALT_START_INST_KEY_CHAR:START_INST_KEY_CHAR;
57         switch(pInst.charAt(0)) {                          // First char
58             case START_REGEX_CHAR:                            // Evaluate as Regular Expression
59                 String pItem = pInst.substring(1);
60                 String first = Split.split(LIST_SEP,sInst)[0];         // allow for "," definition in Action
61                 return first.matches(pItem);
62
63             case START_INST_KEY_CHAR:                        // Evaluate a special Key field, i.e.:xyz:*:!df.*
64             case ALT_START_INST_KEY_CHAR:                    // Also allow '/' as special Key Field, i.e. /xyz/*/!.*
65                 if (sInst.charAt(0)==startChar) {  // To compare key-to-key, both strings must be keys
66                     String[] skeys=Split.split(startChar,sInst);
67                     String[] pkeys=Split.split(startChar,pInst);
68                     if (pkeys.length<skeys.length) {
69                         return false;
70                     } else if(pkeys.length > skeys.length &&
71                              (skeys.length==0 || !ASTERIX.equals(skeys[skeys.length-1]))) {
72                            return false;
73                     }
74
75                     boolean pass = true;
76                     for (int i=1;pass && i<skeys.length;++i) {                  // We start at 1, because the first one, being ":" is always ""
77                         if (ASTERIX.equals(skeys[i])) {
78                             if(i==skeys.length-1) {
79                                 // accept all after
80                                 return true;
81                             }
82                             continue;               // Server data accepts all for this key spot
83                         }
84                         pass = false;
85                         for (String sItem : Split.split(LIST_SEP,skeys[i])) {        // allow for "," definition in Action
86                             if (pkeys[i].length()==0) {
87                                 if (pass=sItem.length()==0) {
88                                     break;                                  // Both Empty, keep checking
89                                 }
90                             } else if (sItem.length()>0 && sItem.charAt(0)==START_REGEX_CHAR) { // Check Server side when wildcarding like *
91                                 if (pass=pkeys[i].matches(sItem.substring(1))) {
92                                     break;                                  // Matches, keep checking
93                                 }
94                             } else if (skeys[i].endsWith(ASTERIX)) {
95                                 if (pass=endAsterixCompare(skeys[i],pkeys[i])) {
96                                     break;
97                                 }
98                             } else if (pass=sItem.equals(pkeys[i])) {
99                                 break;                                   // Equal, keep checking
100                             }
101                         }
102                     }
103                     return pass;                                             // return whether passed all key checks
104                 }
105                 return false;                                 // if first chars aren't the same, further String compare not necessary
106             default:                                        // Evaluate as String Compare
107                 for (String sItem : Split.split(LIST_SEP,sInst)) {    // allow for "," separator //TODO is this only for actions?
108                     if ((sItem.endsWith(ASTERIX)) && (endAsterixCompare(sInst, pInst))) {
109                         return true;
110                     } else if (sItem.equals(pInst)) {
111                         return true;
112                     }
113                 }
114                 return false;
115         }
116     }
117
118      private static boolean endAsterixCompare(String sInst, String pInst) {
119         final int len = sInst.length()-1;
120         if (pInst.length()<len) {
121             return false;
122         }
123         for (int j=0;j<len;++j) {
124             if (pInst.charAt(j)!=sInst.charAt(j)) {
125                 return false;
126             }
127         }
128         return true;
129     }
130
131     /**
132      * Evaluate Action
133      *
134      * sAction = Stored Action...
135      * pAction = Present Action... the Permission to validate against.
136      * Action is not quite as complex.  But we write it in this function so it can be consistent
137      */
138     public static boolean evalAction(String sAction,String pAction) {
139         if (ASTERIX.equals(sAction)) return true;               // If Server's String is "*", then it accepts every Action
140         if (pAction.equals("")) return false;
141         for (String sItem : Split.split(LIST_SEP,sAction)) {         // allow for "," definition in Action
142             if (pAction.charAt(0)==START_REGEX_CHAR?       // First char
143                     sItem.matches(pAction.substring(1)):   // Evaluate as Regular Expression
144                     sItem.equals(pAction))                 // Evaluate as String Compare
145                 return true;
146         }
147         return false;
148     }
149
150 }