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