6bb9252c95b59df57edbedab42890961d0b76bbc
[aaf/cadi.git] / core / src / main / java / com / att / cadi / taf / dos / DenialOfServiceTaf.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aaf\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * ===========================================================================\r
7  * * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * * you may not use this file except in compliance with the License.\r
9  * * You may obtain a copy of the License at\r
10  * * \r
11  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * * \r
13  *  * Unless required by applicable law or agreed to in writing, software\r
14  * * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * * See the License for the specific language governing permissions and\r
17  * * limitations under the License.\r
18  * * ============LICENSE_END====================================================\r
19  * *\r
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
21  * *\r
22  ******************************************************************************/\r
23 package com.att.cadi.taf.dos;\r
24 \r
25 import java.io.BufferedReader;\r
26 import java.io.File;\r
27 import java.io.FileOutputStream;\r
28 import java.io.FileReader;\r
29 import java.io.IOException;\r
30 import java.io.PrintStream;\r
31 import java.util.ArrayList;\r
32 import java.util.Date;\r
33 import java.util.HashMap;\r
34 import java.util.List;\r
35 import java.util.Map;\r
36 \r
37 import javax.servlet.http.HttpServletRequest;\r
38 import javax.servlet.http.HttpServletResponse;\r
39 \r
40 import com.att.cadi.Access;\r
41 import com.att.cadi.CachedPrincipal;\r
42 import com.att.cadi.CachedPrincipal.Resp;\r
43 import com.att.cadi.CadiException;\r
44 import com.att.cadi.Taf.LifeForm;\r
45 import com.att.cadi.taf.HttpTaf;\r
46 import com.att.cadi.taf.PuntTafResp;\r
47 import com.att.cadi.taf.TafResp;\r
48 import com.att.cadi.taf.TafResp.RESP;\r
49 \r
50 public class DenialOfServiceTaf implements HttpTaf {\r
51         private static Map<String, Counter> deniedIP=null, deniedID=null;\r
52         private Access access;\r
53         private static File dosIP, dosID;\r
54         \r
55         /**\r
56          * \r
57          * @param hostname\r
58          * @param prod\r
59          * @throws CadiException\r
60          */\r
61         public DenialOfServiceTaf(Access access) throws CadiException {\r
62                 this.access = access;\r
63                 if(dosIP==null || dosID == null) {\r
64                         String dirStr;\r
65                         if((dirStr = access.getProperty("aaf_data_dir", null))!=null) {\r
66                                 dosIP = new File(dirStr+"/dosIP");\r
67                                 readIP();\r
68                                 dosID = new File(dirStr+"/dosID");\r
69                                 readID();\r
70                         }\r
71                 }\r
72         }\r
73 \r
74         public TafResp validate(LifeForm reading, HttpServletRequest req, final HttpServletResponse resp) {\r
75                 // Performance, when not needed\r
76                 if(deniedIP != null) {\r
77                         String ip;\r
78                         Counter c = deniedIP.get(ip=req.getRemoteAddr());\r
79                         if(c!=null) {\r
80                                 c.inc();\r
81                                 return respDenyIP(access,ip);\r
82                         }\r
83                 }\r
84                 \r
85                 // Note:  Can't process Principal, because this is the first TAF, and no Principal is created.\r
86                 // Other TAFs use "isDenied()" on this Object to validate.\r
87                 return PuntTafResp.singleton();\r
88         }\r
89 \r
90         public Resp revalidate(CachedPrincipal prin) {\r
91                 // We always return NOT MINE, because DOS Taf does not ever validate\r
92                 return Resp.NOT_MINE;\r
93         }\r
94 \r
95         /*\r
96          *  for use in Other TAFs, before they attempt backend validation of \r
97          */\r
98         public static Counter isDeniedID(String identity) {\r
99                 if(deniedID!=null) {\r
100                         return deniedID.get(identity);\r
101                 }\r
102                 return null;\r
103         }\r
104         \r
105         /**\r
106          *  \r
107          */\r
108         public static Counter isDeniedIP(String ipvX) {\r
109                 if(deniedID!=null) {\r
110                         return deniedID.get(ipvX);\r
111                 }\r
112                 return null;\r
113         }\r
114 \r
115         /**\r
116          * Return of "True" means IP has been added.\r
117          * Return of "False" means IP already added.\r
118          * \r
119          * @param ip\r
120          * @return\r
121          */\r
122         public static synchronized boolean denyIP(String ip) {\r
123                 boolean rv = false;\r
124                 if(deniedIP==null) {\r
125                         deniedIP = new HashMap<String,Counter>();\r
126                         deniedIP.put(ip, new Counter(ip)); // Noted duplicated for minimum time spent\r
127                         rv= true;\r
128                 } else if(deniedIP.get(ip)==null) {\r
129                         deniedIP.put(ip, new Counter(ip));\r
130                         rv = true;\r
131                 }\r
132                 if(rv) {\r
133                         writeIP();\r
134                 }\r
135                 return rv;\r
136         }\r
137         \r
138         private static void writeIP() {\r
139                 if(dosIP!=null && deniedIP!=null) {\r
140                         if(deniedIP.isEmpty()) {\r
141                                 if(dosIP.exists()) {\r
142                                         dosIP.delete();\r
143                                 }\r
144                         } else {\r
145                                 PrintStream fos;\r
146                                 try {\r
147                                         fos = new PrintStream(new FileOutputStream(dosIP,false));\r
148                                         try {\r
149                                                 for(String ip: deniedIP.keySet()) {\r
150                                                         fos.println(ip);\r
151                                                 }\r
152                                         } finally {\r
153                                                 fos.close();\r
154                                         }\r
155                                 } catch (IOException e) {\r
156                                         e.printStackTrace(System.err);\r
157                                 }\r
158                         }\r
159                 }\r
160         }\r
161         \r
162         private static void readIP() {\r
163                 if(dosIP!=null && dosIP.exists()) {\r
164                         BufferedReader br;\r
165                         try {\r
166                                 br = new BufferedReader(new FileReader(dosIP));\r
167                                 if(deniedIP==null) {\r
168                                         deniedIP=new HashMap<String,Counter>();\r
169                                 }\r
170 \r
171                                 try {\r
172                                         String line;\r
173                                         while((line=br.readLine())!=null) {\r
174                                                 deniedIP.put(line, new Counter(line));\r
175                                         }\r
176                                 } finally {\r
177                                         br.close();\r
178                                 }\r
179                         } catch (IOException e) {\r
180                                 e.printStackTrace(System.err);\r
181                         }\r
182                 }\r
183         }\r
184 \r
185 \r
186         /**\r
187          * Return of "True" means IP has was removed.\r
188          * Return of "False" means IP wasn't being denied.\r
189          * \r
190          * @param ip\r
191          * @return\r
192          */\r
193         public static synchronized boolean removeDenyIP(String ip) {\r
194                 if(deniedIP!=null && deniedIP.remove(ip)!=null) {\r
195                         writeIP();\r
196                         if(deniedIP.isEmpty()) {\r
197                                 deniedIP=null;\r
198                         }\r
199                         return true;\r
200                 }\r
201                 return false;\r
202         }\r
203 \r
204         /**\r
205          * Return of "True" means ID has been added.\r
206          * Return of "False" means ID already added.\r
207          * \r
208          * @param ip\r
209          * @return\r
210          */\r
211         public static synchronized boolean denyID(String id) {\r
212                 boolean rv = false;\r
213                 if(deniedID==null) {\r
214                         deniedID = new HashMap<String,Counter>();\r
215                         deniedID.put(id, new Counter(id)); // Noted duplicated for minimum time spent\r
216                         rv = true;\r
217                 } else if(deniedID.get(id)==null) {\r
218                         deniedID.put(id, new Counter(id));\r
219                         rv = true;\r
220                 }\r
221                 if(rv) {\r
222                         writeID();\r
223                 }\r
224                 return rv;\r
225 \r
226         }\r
227 \r
228         private static void writeID() {\r
229                 if(dosID!=null && deniedID!=null) {\r
230                         if(deniedID.isEmpty()) {\r
231                                 if(dosID.exists()) {\r
232                                         dosID.delete();\r
233                                 }\r
234                         } else {\r
235                                 PrintStream fos;\r
236                                 try {\r
237                                         fos = new PrintStream(new FileOutputStream(dosID,false));\r
238                                         try {\r
239                                                 for(String ip: deniedID.keySet()) {\r
240                                                         fos.println(ip);\r
241                                                 }\r
242                                         } finally {\r
243                                                 fos.close();\r
244                                         }\r
245                                 } catch (IOException e) {\r
246                                         e.printStackTrace(System.err);\r
247                                 }\r
248                         }\r
249                 }\r
250         }\r
251 \r
252         private static void readID() {\r
253                 if(dosID!=null && dosID.exists()) {\r
254                         BufferedReader br;\r
255                         try {\r
256                                 br = new BufferedReader(new FileReader(dosID));\r
257                                 if(deniedID==null) {\r
258                                         deniedID=new HashMap<String,Counter>();\r
259                                 }\r
260                                 try {\r
261                                         String line;\r
262                                         while((line=br.readLine())!=null) {\r
263                                                 deniedID.put(line, new Counter(line));\r
264                                         }\r
265                                 } finally {\r
266                                         br.close();\r
267                                 }\r
268                         } catch (IOException e) {\r
269                                 e.printStackTrace(System.err);\r
270                         }\r
271                 }\r
272         }\r
273 \r
274         /**\r
275          * Return of "True" means ID has was removed.\r
276          * Return of "False" means ID wasn't being denied.\r
277          * \r
278          * @param ip\r
279          * @return\r
280          */\r
281         public static synchronized boolean removeDenyID(String id) {\r
282                 if(deniedID!=null && deniedID.remove(id)!=null) { \r
283                         writeID();\r
284                         if(deniedID.isEmpty()) {\r
285                                 deniedID=null;\r
286                         }\r
287 \r
288                         return true;\r
289                 }\r
290                 return false;\r
291         }\r
292         \r
293         public List<String> report() {\r
294                 int initSize = 0;\r
295                 if(deniedIP!=null)initSize+=deniedIP.size();\r
296                 if(deniedID!=null)initSize+=deniedID.size();\r
297                 ArrayList<String> al = new ArrayList<String>(initSize);\r
298                 if(deniedID!=null) {\r
299                         for(Counter c : deniedID.values()) {\r
300                                 al.add(c.toString());\r
301                         }\r
302                 }\r
303                 if(deniedIP!=null) {\r
304                         for(Counter c : deniedIP.values()) {\r
305                                 al.add(c.toString());\r
306                         }\r
307                 }\r
308                 return al;\r
309         }\r
310         \r
311         public static class Counter {\r
312                 private final String name; \r
313                 private int count = 0;\r
314                 private Date first;\r
315                 private long last; // note, we use "last" as long, to avoid popping useless dates on Heap.\r
316                 \r
317                 public Counter(String name) {\r
318                         this.name = name;\r
319                         first = null;\r
320                         last = 0L;\r
321                         count = 0;\r
322                 }\r
323                 \r
324                 public String getName() {\r
325                         return name;\r
326                 }\r
327                 \r
328                 public int getCount() {\r
329                         return count;\r
330                 }\r
331 \r
332                 public long getLast() {\r
333                         return last;\r
334                 }\r
335                 \r
336                 /*\r
337                  * Only allow Denial of ServiceTaf to increment\r
338                  */\r
339                 private synchronized void inc() {\r
340                         ++count;\r
341                         last = System.currentTimeMillis();\r
342                         if(first==null) {\r
343                                 first = new Date(last);\r
344                         }\r
345                 }\r
346                 \r
347                 public String toString() {\r
348                         if(count==0) \r
349                                 return name + " is on the denied list, but has not attempted Access"; \r
350                         else \r
351                                 return \r
352                                         name +\r
353                                         " has been denied " +\r
354                                         count +\r
355                                         " times since " +\r
356                                         first +\r
357                                         ".  Last denial was " +\r
358                                         new Date(last);\r
359                 }\r
360         }\r
361 \r
362         public static TafResp respDenyID(Access access, String identity) {\r
363                 return new DenialOfServiceTafResp(access, RESP.NO_FURTHER_PROCESSING, identity + " is on the Identity Denial list");\r
364         }\r
365         \r
366         public static TafResp respDenyIP(Access access, String ip) {\r
367                 return new DenialOfServiceTafResp(access, RESP.NO_FURTHER_PROCESSING, ip + " is on the IP Denial list");\r
368         }\r
369 \r
370 }\r