f083e5aadb499e07603c50526e35f0cbcb2be210
[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 (deniedIP!=null) {
114             return deniedIP.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<>();
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                 try {
172                     if (deniedIP==null) {
173                         deniedIP=new HashMap<>();
174                     }
175
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<>();
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                 try {
262                     if (deniedID==null) {
263                         deniedID=new HashMap<>();
264                     }
265                     
266                     String line;
267                     while ((line=br.readLine())!=null) {
268                         deniedID.put(line, new Counter(line));
269                     }
270                 } finally {
271                     br.close();
272                 }
273             } catch (IOException e) {
274                 e.printStackTrace(System.err);
275             }
276         }
277     }
278
279     /**
280      * Return of "True" means ID has was removed.
281      * Return of "False" means ID wasn't being denied.
282      * 
283      * @param ip
284      * @return
285      */
286     public static synchronized boolean removeDenyID(String id) {
287         if (deniedID!=null && deniedID.remove(id)!=null) { 
288             writeID();
289             if (deniedID.isEmpty()) {
290                 deniedID=null;
291             }
292
293             return true;
294         }
295         return false;
296     }
297     
298     public List<String> report() {
299         int initSize = 0;
300         if (deniedIP!=null)initSize+=deniedIP.size();
301         if (deniedID!=null)initSize+=deniedID.size();
302         ArrayList<String> al = new ArrayList<>(initSize);
303         if (deniedID!=null) {
304             for (Counter c : deniedID.values()) {
305                 al.add(c.toString());
306             }
307         }
308         if (deniedIP!=null) {
309             for (Counter c : deniedIP.values()) {
310                 al.add(c.toString());
311             }
312         }
313         return al;
314     }
315     
316     public static class Counter {
317         private final String name; 
318         private int count = 0;
319         private Date first;
320         private long last; // note, we use "last" as long, to avoid popping useless dates on Heap.
321         
322         public Counter(String name) {
323             this.name = name;
324             first = null;
325             last = 0L;
326             count = 0;
327         }
328         
329         public String getName() {
330             return name;
331         }
332         
333         public int getCount() {
334             return count;
335         }
336
337         public long getLast() {
338             return last;
339         }
340         
341         /*
342          * Only allow Denial of ServiceTaf to increment
343          */
344         private synchronized void inc() {
345             ++count;
346             last = System.currentTimeMillis();
347             if (first==null) {
348                 first = new Date(last);
349             }
350         }
351         
352         public String toString() {
353             if (count==0) 
354                 return name + " is on the denied list, but has not attempted Access"; 
355             else 
356                 return 
357                     name +
358                     " has been denied " +
359                     count +
360                     " times since " +
361                     first +
362                     ".  Last denial was " +
363                     new Date(last);
364         }
365     }
366
367     public static TafResp respDenyID(Access access, String identity) {
368         return new DenialOfServiceTafResp(access, RESP.NO_FURTHER_PROCESSING, identity + " is on the Identity Denial list");
369     }
370     
371     public static TafResp respDenyIP(Access access, String ip) {
372         return new DenialOfServiceTafResp(access, RESP.NO_FURTHER_PROCESSING, ip + " is on the IP Denial list");
373     }
374
375 }