[AAF-21] Initial code import
[aaf/cadi.git] / cass / src / main / java / com / att / cadi / aaf / cass / AAFAuthenticator.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aai\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * Copyright © 2017 Amdocs\r
7  * * ===========================================================================\r
8  * * Licensed under the Apache License, Version 2.0 (the "License");\r
9  * * you may not use this file except in compliance with the License.\r
10  * * You may obtain a copy of the License at\r
11  * * \r
12  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
13  * * \r
14  *  * Unless required by applicable law or agreed to in writing, software\r
15  * * distributed under the License is distributed on an "AS IS" BASIS,\r
16  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17  * * See the License for the specific language governing permissions and\r
18  * * limitations under the License.\r
19  * * ============LICENSE_END====================================================\r
20  * *\r
21  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
22  * *\r
23  ******************************************************************************/\r
24 package com.att.cadi.aaf.cass;\r
25 \r
26 import java.io.IOException;\r
27 import java.io.UnsupportedEncodingException;\r
28 import java.util.Arrays;\r
29 import java.util.HashMap;\r
30 import java.util.Map;\r
31 \r
32 import org.apache.cassandra.auth.AuthenticatedUser;\r
33 import org.apache.cassandra.auth.IAuthenticator;\r
34 import org.apache.cassandra.auth.ISaslAwareAuthenticator;\r
35 import org.apache.cassandra.exceptions.AuthenticationException;\r
36 import org.apache.cassandra.exceptions.InvalidRequestException;\r
37 import org.apache.cassandra.exceptions.RequestExecutionException;\r
38 \r
39 import com.att.cadi.Access.Level;\r
40 import com.att.cadi.CredVal.Type;\r
41 import com.att.cadi.Symm;\r
42 import com.att.cadi.config.Config;\r
43 \r
44 public class AAFAuthenticator extends AAFBase implements ISaslAwareAuthenticator  {\r
45 \r
46         public boolean requireAuthentication() {\r
47                  return true;\r
48          }\r
49           \r
50           /**\r
51            * Invoked to authenticate an user\r
52            */\r
53           public AuthenticatedUser authenticate(Map<String, String> credentials) throws AuthenticationException {\r
54                     String username = (String)credentials.get("username");\r
55                     if (username == null) {\r
56                       throw new AuthenticationException("'username' is missing");\r
57                     }\r
58                     \r
59                     AAFAuthenticatedUser aau = new AAFAuthenticatedUser(access,username);\r
60                     String fullName=aau.getFullName();\r
61                     access.log(Level.DEBUG, "Authenticating", aau.getName(),"(", fullName,")");\r
62                     \r
63                     String password = (String)credentials.get("password");\r
64                     if (password == null) {\r
65                       throw new AuthenticationException("'password' is missing");\r
66                     } else if(password.startsWith("bsf:")) {\r
67                         try {\r
68                                         password = Symm.base64noSplit.depass(password);\r
69                                 } catch (IOException e) {\r
70                                         throw new AuthenticationException("AAF bnf: Password cannot be decoded");\r
71                                 }\r
72                         } else if(password.startsWith("enc:???")) {\r
73                                 try {\r
74                                         password = access.decrypt(password, true);\r
75                                 } catch (IOException e) {\r
76                                         throw new AuthenticationException("AAF Encrypted Password cannot be decrypted");\r
77                                 }\r
78                     }\r
79                     \r
80                     if(localLur!=null) {\r
81                         access.log(Level.DEBUG, "Validating",fullName, "with LocalTaf", password); \r
82                         if(localLur.validate(fullName, Type.PASSWORD, password.getBytes())) {\r
83                                     aau.setAnonymous(true);\r
84                                     aau.setLocal(true);\r
85                                     access.log(Level.DEBUG, fullName, "is authenticated locally"); \r
86                                 return aau;\r
87                         }\r
88                     }\r
89                     \r
90                     String aafResponse;\r
91                     try {\r
92                         access.log(Level.DEBUG, "Validating",fullName, "with AAF");//, password); \r
93                         aafResponse = aafAuthn.validate(fullName, password);\r
94                             if(aafResponse != null) { // Reason for failing.\r
95                                 access.log(Level.AUDIT, "AAF reports ",fullName,":",aafResponse);\r
96                                 throw new AuthenticationException(aafResponse);\r
97                             }\r
98                             access.log(Level.AUDIT, fullName, "is authenticated"); //,password);\r
99                             // This tells Cassandra to skip checking it's own tables for User Entries.\r
100                             aau.setAnonymous(true);\r
101                     } catch (AuthenticationException ex) {\r
102                         throw ex;\r
103                     } catch(Exception ex) {\r
104                         access.log(ex,"Exception validating user");                             \r
105                         throw new AuthenticationException("Exception validating user");\r
106                     }\r
107                     \r
108                     return aau; \r
109           }\r
110           \r
111           public void create(String username, Map<IAuthenticator.Option, Object> options) throws InvalidRequestException, RequestExecutionException {\r
112                   access.log(Level.INFO,"Use AAF CLI to create user");\r
113           }\r
114           \r
115           public void alter(String username, Map<IAuthenticator.Option, Object> options) throws RequestExecutionException {\r
116                   access.log(Level.INFO,"Use AAF CLI to alter user");\r
117           }\r
118           \r
119           public void drop(String username) throws RequestExecutionException {\r
120                   access.log(Level.INFO,"Use AAF CLI to delete user");\r
121           }\r
122           \r
123           public SaslAuthenticator newAuthenticator() {\r
124                   return new ISaslAwareAuthenticator.SaslAuthenticator() {\r
125                     private boolean complete = false;\r
126                     private Map<String, String> credentials;\r
127 \r
128                     public byte[] evaluateResponse(byte[] clientResponse) throws AuthenticationException {\r
129                       this.credentials = decodeCredentials(clientResponse);\r
130                       this.complete = true;\r
131                       return null;\r
132                     }\r
133 \r
134                     public boolean isComplete() {\r
135                       return this.complete;\r
136                     }\r
137 \r
138                     public AuthenticatedUser getAuthenticatedUser() throws AuthenticationException {\r
139                       return AAFAuthenticator.this.authenticate(this.credentials);\r
140                     }\r
141 \r
142                     private Map<String, String> decodeCredentials(byte[] bytes) throws AuthenticationException {\r
143                         access.log(Level.DEBUG,"Decoding credentials from client token");\r
144                       byte[] user = null;\r
145                       byte[] pass = null;\r
146                       int end = bytes.length;\r
147                       for (int i = bytes.length - 1; i >= 0; i--)\r
148                       {\r
149                         if (bytes[i] != 0)\r
150                           continue;\r
151                         if (pass == null)\r
152                           pass = Arrays.copyOfRange(bytes, i + 1, end);\r
153                         else if (user == null)\r
154                           user = Arrays.copyOfRange(bytes, i + 1, end);\r
155                         end = i;\r
156                       }\r
157 \r
158                       if (user == null)\r
159                         throw new AuthenticationException("Authentication ID must not be null");\r
160                       if (pass == null) {\r
161                         throw new AuthenticationException("Password must not be null");\r
162                       }\r
163                       Map<String,String> credentials = new HashMap<String,String>();\r
164                       try {\r
165                           credentials.put(IAuthenticator.USERNAME_KEY, new String(user, Config.UTF_8));\r
166                           credentials.put(IAuthenticator.PASSWORD_KEY, new String(pass, Config.UTF_8));\r
167                                 } catch (UnsupportedEncodingException e) {\r
168                                         throw new AuthenticationException(e.getMessage());\r
169                                 }\r
170                       return credentials;\r
171                     }\r
172                   };      \r
173           }\r
174 \r
175 }\r
176 \r