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