[AAF-21] Updated Copyright Headers for AAF
[aaf/cadi.git] / aaf / src / src / main / java / com / att / cadi / aaf / v2_0 / AAFAuthn.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.aaf.v2_0;\r
24 \r
25 import com.att.aft.dme2.api.DME2Exception;\r
26 import com.att.cadi.AbsUserCache;\r
27 import com.att.cadi.CachedPrincipal;\r
28 import com.att.cadi.GetCred;\r
29 import com.att.cadi.Hash;\r
30 import com.att.cadi.User;\r
31 import com.att.cadi.aaf.AAFPermission;\r
32 import com.att.cadi.client.Future;\r
33 import com.att.cadi.client.Rcli;\r
34 import com.att.cadi.config.Config;\r
35 import com.att.cadi.lur.ConfigPrincipal;\r
36 import com.att.inno.env.APIException;\r
37 \r
38 public class AAFAuthn<CLIENT> extends AbsUserCache<AAFPermission> {\r
39         private AAFCon<CLIENT> con;\r
40         private String realm;\r
41         \r
42         /**\r
43          * Configure with Standard AAF properties, Stand alone\r
44          * @param con\r
45          * @throws Exception \r
46          */\r
47         // Package on purpose\r
48         AAFAuthn(AAFCon<CLIENT> con) throws Exception {\r
49                 super(con.access,con.cleanInterval,con.highCount,con.usageRefreshTriggerCount);\r
50                 this.con = con;\r
51 \r
52                 try {\r
53                         setRealm();\r
54                 } catch (APIException e) {\r
55                         if(e.getCause() instanceof DME2Exception) {\r
56                                 // Can't contact AAF, assume default\r
57                                 realm=con.access.getProperty(Config.AAF_DEFAULT_REALM, Config.getDefaultRealm());\r
58                         }\r
59                 }\r
60                 }\r
61 \r
62         /**\r
63          * Configure with Standard AAF properties, but share the Cache (with AAF Lur)\r
64          * @param con\r
65          * @throws Exception \r
66          */\r
67         // Package on purpose\r
68         AAFAuthn(AAFCon<CLIENT> con, AbsUserCache<AAFPermission> cache) throws Exception {\r
69                 super(cache);\r
70                 this.con = con;\r
71                 try {\r
72                         setRealm();\r
73                 } catch (Exception e) {\r
74                         if(e.getCause() instanceof DME2Exception) {\r
75                                 access.log(e);\r
76                                 // Can't contact AAF, assume default            \r
77                                 realm=con.access.getProperty(Config.AAF_DEFAULT_REALM, Config.getDefaultRealm());\r
78                         }\r
79                 }\r
80         }\r
81 \r
82         private void setRealm() throws Exception {\r
83                 // Make a call without security set to get the 401 response, which\r
84                 // includes the Realm of the server\r
85                 // This also checks on Connectivity early on.\r
86                 Future<String> fp = con.client(AAFCon.AAF_VERSION).read("/authn/basicAuth", "text/plain");\r
87                 if(fp.get(con.timeout)) {\r
88                         throw new Exception("Do not preset Basic Auth Information for AAFAuthn");\r
89                 } else {\r
90                         if(fp.code()==401) {\r
91                                 realm = fp.header("WWW-Authenticate");\r
92                                 if(realm!=null && realm.startsWith("Basic realm=\"")) {\r
93                                         realm = realm.substring(13, realm.length()-1);\r
94                                 } else {\r
95                                         realm = "unknown.com";\r
96                                 }\r
97                         }\r
98                 }\r
99         }\r
100         \r
101         /**\r
102          * Return Native Realm of AAF Instance.\r
103          * \r
104          * @return\r
105          */\r
106         public String getRealm() {\r
107                 return realm;\r
108         }\r
109 \r
110         /**\r
111          * Returns null if ok, or an Error String;\r
112          * \r
113          * @param user\r
114          * @param password\r
115          * @return\r
116          * @throws Exception\r
117          */\r
118         public String validate(String user, String password) throws Exception {\r
119                 User<AAFPermission> usr = getUser(user);\r
120                 if(password.startsWith("enc:???")) {\r
121                         password = access.decrypt(password, true);\r
122                 }\r
123 \r
124                 byte[] bytes = password.getBytes();\r
125                 if(usr != null && usr.principal != null && usr.principal.getName().equals(user) \r
126                                 && usr.principal instanceof GetCred) {\r
127                         \r
128                         if(Hash.isEqual(((GetCred)usr.principal).getCred(),bytes)) {\r
129                                 return null;\r
130                         } else {\r
131                                 remove(usr);\r
132                                 usr = null;\r
133                         }\r
134                 }\r
135                 \r
136                 AAFCachedPrincipal cp = new AAFCachedPrincipal(this,con.app, user, bytes, con.cleanInterval);\r
137                 // Since I've relocated the Validation piece in the Principal, just revalidate, then do Switch\r
138                 // Statement\r
139                 switch(cp.revalidate()) {\r
140                         case REVALIDATED:\r
141                                 if(usr!=null) {\r
142                                         usr.principal = cp;\r
143                                 } else {\r
144                                         addUser(new User<AAFPermission>(cp,con.timeout));\r
145                                 }\r
146                                 return null;\r
147                         case INACCESSIBLE:\r
148                                 return "AAF Inaccessible";\r
149                         case UNVALIDATED:\r
150                                 return "User/Pass combo invalid";\r
151                         default: \r
152                                 return "AAFAuthn doesn't handle this Principal";\r
153                 }\r
154         }\r
155         \r
156         private class AAFCachedPrincipal extends ConfigPrincipal implements CachedPrincipal {\r
157                 private long expires,timeToLive;\r
158 \r
159                 public AAFCachedPrincipal(AAFAuthn<?> aaf, String app, String name, byte[] pass, int timeToLive) {\r
160                         super(name,pass);\r
161                         this.timeToLive = timeToLive;\r
162                         expires = timeToLive + System.currentTimeMillis();\r
163                 }\r
164 \r
165                 public Resp revalidate() {\r
166                         try {\r
167                                 Miss missed = missed(getName());\r
168                                 if(missed==null || missed.mayContinue(getCred())) {\r
169                                         Rcli<CLIENT> client = con.client(AAFCon.AAF_VERSION).forUser(con.basicAuth(getName(), new String(getCred())));\r
170                                         Future<String> fp = client.read(\r
171                                                         "/authn/basicAuth",\r
172                                                         "text/plain"\r
173                                                         );\r
174                                         if(fp.get(con.timeout)) {\r
175                                                 expires = System.currentTimeMillis() + timeToLive;\r
176                                                 addUser(new User<AAFPermission>(this, expires));\r
177                                                 return Resp.REVALIDATED;\r
178                                         } else {\r
179                                                 addMiss(getName(), getCred());\r
180                                                 return Resp.UNVALIDATED;\r
181                                         }\r
182                                 } else {\r
183                                         return Resp.UNVALIDATED;\r
184                                 }\r
185                         } catch (Exception e) {\r
186                                 con.access.log(e);\r
187                                 return Resp.INACCESSIBLE;\r
188                         }\r
189                 }\r
190 \r
191                 public long expires() {\r
192                         return expires;\r
193                 }\r
194         };\r
195 \r
196 }\r