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