75df4eab58af901d426bc9dfbef3deb25884bc24
[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(skeys.length!=pkeys.length) return false;
70
71                                         boolean pass = true;
72                                         for(int i=1;pass && i<skeys.length;++i) {                               // We start at 1, because the first one, being ":" is always ""
73                                                 if(ASTERIX.equals(skeys[i]))continue;                           // Server data accepts all for this key spot
74                                                 pass = false;
75                                                 for(String sItem : Split.split(LIST_SEP,skeys[i])) {            // allow for "," definition in Action
76                                                         if(pkeys[i].length()==0) {
77                                                                 if(pass=sItem.length()==0) {
78                                                                         break;                                                                  // Both Empty, keep checking
79                                                                 }
80                                                         } else if(sItem.charAt(0)==START_REGEX_CHAR) { // Check Server side when wildcarding like *
81                                                                 if(pass=pkeys[i].matches(sItem.substring(1))) {
82                                                                         break;                                                                  // Matches, keep checking
83                                                                 }
84                                                         } else if(skeys[i].endsWith(ASTERIX)) {
85                                                                 if(pass=endAsterixCompare(skeys[i],pkeys[i])) {
86                                                                         break;
87                                                                 }
88                                                         } else if(pass=sItem.equals(pkeys[i])) {
89                                                                 break;                                                                  // Equal, keep checking
90                                                         }
91                                                 }
92                                         }
93                                         return pass;                                                                                    // return whether passed all key checks
94                                 }
95                                 return false;                                                           // if first chars aren't the same, further String compare not necessary
96                         default:                                                                                // Evaluate as String Compare
97                                 for(String sItem : Split.split(LIST_SEP,sInst)) {       // allow for "," separator //TODO is this only for actions?
98                                         if((sItem.endsWith(ASTERIX)) && (endAsterixCompare(sInst, pInst))) {
99                                                 return true;
100                                         } else if(sItem.equals(pInst)) {
101                                                 return true;
102                                         }
103                                 }
104                                 return false;
105                 }
106         }
107
108          private static boolean endAsterixCompare(String sInst, String pInst) {
109                 final int len = sInst.length()-1;
110                 if(pInst.length()<len) {
111                         return false;
112                 }
113                 for(int j=0;j<len;++j) {
114                         if(pInst.charAt(j)!=sInst.charAt(j)) {
115                                 return false;
116                         }
117                 }
118                 return true;
119         }
120
121         /**
122          * Evaluate Action
123          *
124          * sAction = Stored Action...
125          * pAction = Present Action... the Permission to validate against.
126          * Action is not quite as complex.  But we write it in this function so it can be consistent
127          */
128         public static boolean evalAction(String sAction,String pAction) {
129                 if(ASTERIX.equals(sAction))return true;                      // If Server's String is "*", then it accepts every Action
130                 if(pAction == "") return false;
131                 for(String sItem : Split.split(LIST_SEP,sAction)) {              // allow for "," definition in Action
132                         if (pAction.charAt(0)==START_REGEX_CHAR?       // First char
133                                         sItem.matches(pAction.substring(1)):   // Evaluate as Regular Expression
134                                         sItem.equals(pAction))                 // Evaluate as String Compare
135                                 return true;
136                 }
137                 return false;
138         }
139
140 }