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