631a3fa816209611747462788c33276558d86328
[aaf/cadi.git] / cass / src / main / java / com / att / cadi / aaf / cass / AAFAuthenticator.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.cass;\r
24 \r
25 import java.io.IOException;\r
26 import java.io.UnsupportedEncodingException;\r
27 import java.util.Arrays;\r
28 import java.util.HashMap;\r
29 import java.util.Map;\r
30 \r
31 import org.apache.cassandra.auth.AuthenticatedUser;\r
32 import org.apache.cassandra.auth.IAuthenticator;\r
33 import org.apache.cassandra.auth.ISaslAwareAuthenticator;\r
34 import org.apache.cassandra.exceptions.AuthenticationException;\r
35 import org.apache.cassandra.exceptions.InvalidRequestException;\r
36 import org.apache.cassandra.exceptions.RequestExecutionException;\r
37 \r
38 import com.att.cadi.Access.Level;\r
39 import com.att.cadi.CredVal.Type;\r
40 import com.att.cadi.Symm;\r
41 import com.att.cadi.config.Config;\r
42 \r
43 public class AAFAuthenticator extends AAFBase implements ISaslAwareAuthenticator  {\r
44 \r
45         public boolean requireAuthentication() {\r
46                  return true;\r
47          }\r
48           \r
49           /**\r
50            * Invoked to authenticate an user\r
51            */\r
52           public AuthenticatedUser authenticate(Map<String, String> credentials) throws AuthenticationException {\r
53                     String username = (String)credentials.get("username");\r
54                     if (username == null) {\r
55                       throw new AuthenticationException("'username' is missing");\r
56                     }\r
57                     \r
58                     AAFAuthenticatedUser aau = new AAFAuthenticatedUser(access,username);\r
59                     String fullName=aau.getFullName();\r
60                     access.log(Level.DEBUG, "Authenticating", aau.getName(),"(", fullName,")");\r
61                     \r
62                     String password = (String)credentials.get("password");\r
63                     if (password == null) {\r
64                       throw new AuthenticationException("'password' is missing");\r
65                     } else if(password.startsWith("bsf:")) {\r
66                         try {\r
67                                         password = Symm.base64noSplit.depass(password);\r
68                                 } catch (IOException e) {\r
69                                         throw new AuthenticationException("AAF bnf: Password cannot be decoded");\r
70                                 }\r
71                         } else if(password.startsWith("enc:???")) {\r
72                                 try {\r
73                                         password = access.decrypt(password, true);\r
74                                 } catch (IOException e) {\r
75                                         throw new AuthenticationException("AAF Encrypted Password cannot be decrypted");\r
76                                 }\r
77                     }\r
78                     \r
79                     if(localLur!=null) {\r
80                         access.log(Level.DEBUG, "Validating",fullName, "with LocalTaf", password); \r
81                         if(localLur.validate(fullName, Type.PASSWORD, password.getBytes())) {\r
82                                     aau.setAnonymous(true);\r
83                                     aau.setLocal(true);\r
84                                     access.log(Level.DEBUG, fullName, "is authenticated locally"); \r
85                                 return aau;\r
86                         }\r
87                     }\r
88                     \r
89                     String aafResponse;\r
90                     try {\r
91                         access.log(Level.DEBUG, "Validating",fullName, "with AAF");//, password); \r
92                         aafResponse = aafAuthn.validate(fullName, password);\r
93                             if(aafResponse != null) { // Reason for failing.\r
94                                 access.log(Level.AUDIT, "AAF reports ",fullName,":",aafResponse);\r
95                                 throw new AuthenticationException(aafResponse);\r
96                             }\r
97                             access.log(Level.AUDIT, fullName, "is authenticated"); //,password);\r
98                             // This tells Cassandra to skip checking it's own tables for User Entries.\r
99                             aau.setAnonymous(true);\r
100                     } catch (AuthenticationException ex) {\r
101                         throw ex;\r
102                     } catch(Exception ex) {\r
103                         access.log(ex,"Exception validating user");                             \r
104                         throw new AuthenticationException("Exception validating user");\r
105                     }\r
106                     \r
107                     return aau; \r
108           }\r
109           \r
110           public void create(String username, Map<IAuthenticator.Option, Object> options) throws InvalidRequestException, RequestExecutionException {\r
111                   access.log(Level.INFO,"Use AAF CLI to create user");\r
112           }\r
113           \r
114           public void alter(String username, Map<IAuthenticator.Option, Object> options) throws RequestExecutionException {\r
115                   access.log(Level.INFO,"Use AAF CLI to alter user");\r
116           }\r
117           \r
118           public void drop(String username) throws RequestExecutionException {\r
119                   access.log(Level.INFO,"Use AAF CLI to delete user");\r
120           }\r
121           \r
122           public SaslAuthenticator newAuthenticator() {\r
123                   return new ISaslAwareAuthenticator.SaslAuthenticator() {\r
124                     private boolean complete = false;\r
125                     private Map<String, String> credentials;\r
126 \r
127                     public byte[] evaluateResponse(byte[] clientResponse) throws AuthenticationException {\r
128                       this.credentials = decodeCredentials(clientResponse);\r
129                       this.complete = true;\r
130                       return null;\r
131                     }\r
132 \r
133                     public boolean isComplete() {\r
134                       return this.complete;\r
135                     }\r
136 \r
137                     public AuthenticatedUser getAuthenticatedUser() throws AuthenticationException {\r
138                       return AAFAuthenticator.this.authenticate(this.credentials);\r
139                     }\r
140 \r
141                     private Map<String, String> decodeCredentials(byte[] bytes) throws AuthenticationException {\r
142                         access.log(Level.DEBUG,"Decoding credentials from client token");\r
143                       byte[] user = null;\r
144                       byte[] pass = null;\r
145                       int end = bytes.length;\r
146                       for (int i = bytes.length - 1; i >= 0; i--)\r
147                       {\r
148                         if (bytes[i] != 0)\r
149                           continue;\r
150                         if (pass == null)\r
151                           pass = Arrays.copyOfRange(bytes, i + 1, end);\r
152                         else if (user == null)\r
153                           user = Arrays.copyOfRange(bytes, i + 1, end);\r
154                         end = i;\r
155                       }\r
156 \r
157                       if (user == null)\r
158                         throw new AuthenticationException("Authentication ID must not be null");\r
159                       if (pass == null) {\r
160                         throw new AuthenticationException("Password must not be null");\r
161                       }\r
162                       Map<String,String> credentials = new HashMap<String,String>();\r
163                       try {\r
164                           credentials.put(IAuthenticator.USERNAME_KEY, new String(user, Config.UTF_8));\r
165                           credentials.put(IAuthenticator.PASSWORD_KEY, new String(pass, Config.UTF_8));\r
166                                 } catch (UnsupportedEncodingException e) {\r
167                                         throw new AuthenticationException(e.getMessage());\r
168                                 }\r
169                       return credentials;\r
170                     }\r
171                   };      \r
172           }\r
173 \r
174 }\r
175 \r