Mass removal of all Tabs (Style Warnings)
[aaf/authz.git] / cadi / aaf / src / main / java / org / onap / aaf / cadi / aaf / v2_0 / AAFTaf.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.v2_0;
23
24 import java.io.IOException;
25 import java.security.Principal;
26 import javax.servlet.http.HttpServletRequest;
27 import javax.servlet.http.HttpServletResponse;
28 import org.onap.aaf.cadi.AbsUserCache;
29 import org.onap.aaf.cadi.Access.Level;
30 import org.onap.aaf.cadi.CachedPrincipal;
31 import org.onap.aaf.cadi.CachedPrincipal.Resp;
32 import org.onap.aaf.cadi.CadiException;
33 import org.onap.aaf.cadi.Connector;
34 import org.onap.aaf.cadi.GetCred;
35 import org.onap.aaf.cadi.Hash;
36 import org.onap.aaf.cadi.SecuritySetter;
37 import org.onap.aaf.cadi.Taf.LifeForm;
38 import org.onap.aaf.cadi.User;
39 import org.onap.aaf.cadi.aaf.AAFPermission;
40 import org.onap.aaf.cadi.aaf.v2_0.AAFCon.GetSetter;
41 import org.onap.aaf.cadi.client.Future;
42 import org.onap.aaf.cadi.client.Rcli;
43 import org.onap.aaf.cadi.client.Retryable;
44 import org.onap.aaf.cadi.config.Config;
45 import org.onap.aaf.cadi.principal.BasicPrincipal;
46 import org.onap.aaf.cadi.principal.CachedBasicPrincipal;
47 import org.onap.aaf.cadi.taf.HttpTaf;
48 import org.onap.aaf.cadi.taf.TafResp;
49 import org.onap.aaf.cadi.taf.TafResp.RESP;
50 import org.onap.aaf.cadi.taf.basic.BasicHttpTafResp;
51 import org.onap.aaf.misc.env.APIException;
52
53 public class AAFTaf<CLIENT> extends AbsUserCache<AAFPermission> implements HttpTaf {
54     private AAFCon<CLIENT> aaf;
55     private boolean warn;
56
57     public AAFTaf(AAFCon<CLIENT> con, boolean turnOnWarning) {
58         super(con.access,con.cleanInterval,con.highCount, con.usageRefreshTriggerCount);
59         aaf = con;
60         warn = turnOnWarning;
61     }
62
63     public AAFTaf(AAFCon<CLIENT> con, boolean turnOnWarning, AbsUserCache<AAFPermission> other) {
64         super(other);
65         aaf = con;
66         warn = turnOnWarning;
67     }
68     
69     // Note: Needed for Creation of this Object with Generics
70     @SuppressWarnings("unchecked")
71     public AAFTaf(Connector mustBeAAFCon, boolean turnOnWarning, AbsUserCache<AAFPermission> other) {
72         this((AAFCon<CLIENT>)mustBeAAFCon,turnOnWarning,other);
73     }
74
75     // Note: Needed for Creation of this Object with Generics
76     @SuppressWarnings("unchecked")
77     public AAFTaf(Connector mustBeAAFCon, boolean turnOnWarning) {
78         this((AAFCon<CLIENT>)mustBeAAFCon,turnOnWarning);
79     }
80
81
82     public TafResp validate(final LifeForm reading, final HttpServletRequest req, final HttpServletResponse resp) {
83         //TODO Do we allow just anybody to validate?
84
85         // Note: Either Carbon or Silicon based LifeForms ok
86         String authz = req.getHeader("Authorization");
87         if(authz != null && authz.startsWith("Basic ")) {
88             if(warn&&!req.isSecure()) {
89                 aaf.access.log(Level.WARN,"WARNING! BasicAuth has been used over an insecure channel");
90             }
91             try {
92                 final CachedBasicPrincipal bp;
93                 if(req.getUserPrincipal() instanceof CachedBasicPrincipal) {
94                     bp = (CachedBasicPrincipal)req.getUserPrincipal();
95                 } else {
96                     bp = new CachedBasicPrincipal(this,authz,aaf.getRealm(),aaf.userExpires);
97                 }
98                 // First try Cache
99                 final User<AAFPermission> usr = getUser(bp);
100                 if(usr != null
101                     && usr.principal instanceof GetCred
102                     && Hash.isEqual(bp.getCred(),((GetCred)usr.principal).getCred())) {
103                     return new BasicHttpTafResp(aaf.access,bp,bp.getName()+" authenticated by cached AAF password",RESP.IS_AUTHENTICATED,resp,aaf.getRealm(),false);
104                 }
105
106                 Miss miss = missed(bp.getName(), bp.getCred());
107                 if(miss!=null && !miss.mayContinue()) {
108                     return new BasicHttpTafResp(aaf.access,null,buildMsg(bp,req,
109                             "User/Pass Retry limit exceeded"), 
110                             RESP.TRY_AUTHENTICATING,resp,aaf.getRealm(),true);
111                 }
112                 
113                 return aaf.bestForUser(
114                     new GetSetter() {
115                         @Override
116                         public <CL> SecuritySetter<CL> get(AAFCon<CL> con) throws CadiException {
117                             return con.basicAuthSS(bp);
118                         }
119                     },new Retryable<BasicHttpTafResp>() {
120                         @Override
121                         public BasicHttpTafResp code(Rcli<?> client) throws CadiException, APIException {
122                             Future<String> fp = client.read("/authn/basicAuth", "text/plain");
123                             if(fp.get(aaf.timeout)) {
124                                 if(usr!=null) {
125                                     usr.principal = bp;
126                                 } else {
127                                     addUser(new User<AAFPermission>(bp,aaf.userExpires));
128                                 }
129                                 return new BasicHttpTafResp(aaf.access,bp,bp.getName()+" authenticated by AAF password",RESP.IS_AUTHENTICATED,resp,aaf.getRealm(),false);
130                             } else {
131                                 // Note: AddMiss checks for miss==null, and is part of logic
132                                 boolean rv= addMiss(bp.getName(),bp.getCred());
133                                 if(rv) {
134                                     return new BasicHttpTafResp(aaf.access,null,buildMsg(bp,req,
135                                             "user/pass combo invalid via AAF from " + req.getRemoteAddr()), 
136                                             RESP.TRY_AUTHENTICATING,resp,aaf.getRealm(),true);
137                                 } else {
138                                     return new BasicHttpTafResp(aaf.access,null,buildMsg(bp,req,
139                                             "user/pass combo invalid via AAF from " + req.getRemoteAddr() + " - Retry limit exceeded"), 
140                                             RESP.FAIL,resp,aaf.getRealm(),true);
141                                 }
142                             }
143                         }
144                     }
145                 );
146             } catch (IOException e) {
147                 String msg = buildMsg(null,req,"Invalid Auth Token");
148                 aaf.access.log(Level.WARN,msg,'(', e.getMessage(), ')');
149                 return new BasicHttpTafResp(aaf.access,null,msg, RESP.TRY_AUTHENTICATING, resp, aaf.getRealm(),true);
150             } catch (Exception e) {
151                 String msg = buildMsg(null,req,"Authenticating Service unavailable");
152                 try {
153                     aaf.invalidate();
154                 } catch (CadiException e1) {
155                     aaf.access.log(e1, "Error Invalidating Client");
156                 }
157                 aaf.access.log(Level.WARN,msg,'(', e.getMessage(), ')');
158                 return new BasicHttpTafResp(aaf.access,null,msg, RESP.FAIL, resp, aaf.getRealm(),false);
159             }
160         }
161         return new BasicHttpTafResp(aaf.access,null,"Requesting HTTP Basic Authorization",RESP.TRY_AUTHENTICATING,resp,aaf.getRealm(),false);
162     }
163     
164     private String buildMsg(Principal pr, HttpServletRequest req, Object... msg) {
165         StringBuilder sb = new StringBuilder();
166         for(Object s : msg) {
167             sb.append(s.toString());
168         }
169         if(pr!=null) {
170             sb.append(" for ");
171             sb.append(pr.getName());
172         }
173         sb.append(" from ");
174         sb.append(req.getRemoteAddr());
175         sb.append(':');
176         sb.append(req.getRemotePort());
177         return sb.toString();
178     }
179
180
181     
182     public Resp revalidate(CachedPrincipal prin, Object state) {
183         //  !!!! TEST THIS.. Things may not be revalidated, if not BasicPrincipal
184         if(prin instanceof BasicPrincipal) {
185             Future<String> fp;
186             try {
187                 Rcli<CLIENT> userAAF = aaf.client(Config.AAF_DEFAULT_VERSION).forUser(aaf.transferSS((BasicPrincipal)prin));
188                 fp = userAAF.read("/authn/basicAuth", "text/plain");
189                 return fp.get(aaf.timeout)?Resp.REVALIDATED:Resp.UNVALIDATED;
190             } catch (Exception e) {
191                 aaf.access.log(e, "Cannot Revalidate",prin.getName());
192                 return Resp.INACCESSIBLE;
193             }
194         }
195         return Resp.NOT_MINE;
196     }
197
198 }