8948bc3c28c3dc0fb71b62553ad9f5078fbae5bb
[aaf/authz.git] / cadi / aaf / src / main / java / org / onap / aaf / cadi / sso / AAFSSO.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.sso;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.PrintStream;
29 import java.lang.reflect.InvocationTargetException;
30 import java.lang.reflect.Method;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Properties;
34
35 import org.onap.aaf.cadi.CadiException;
36 import org.onap.aaf.cadi.PropAccess;
37 import org.onap.aaf.cadi.Symm;
38 import org.onap.aaf.cadi.Access.Level;
39 import org.onap.aaf.cadi.config.Config;
40 import org.onap.aaf.cadi.util.MyConsole;
41 import org.onap.aaf.cadi.util.SubStandardConsole;
42 import org.onap.aaf.cadi.util.TheConsole;
43
44 public class AAFSSO {
45         public static final MyConsole  cons = TheConsole.implemented() ? new TheConsole() : new SubStandardConsole();
46         private static final int EIGHT_HOURS = 8 * 60 * 60 * 1000;
47
48         private Properties diskprops = null; // use for temp storing User/Password on disk
49         private File dot_aaf = null;
50         private File sso = null; // instantiated, if ever, with diskprops
51
52         boolean removeSSO = false;
53         boolean loginOnly = false;
54         boolean doExit = true;
55         private PropAccess access;
56         private StringBuilder err;
57         private String user;
58         private String encrypted_pass;
59         private boolean use_X509;
60
61         private PrintStream os;
62
63         private Method close;
64
65         public AAFSSO(String[] args) throws IOException, CadiException {
66                 String[] nargs = parseArgs(args);
67
68                 dot_aaf = new File(System.getProperty("user.home") + "/.aaf");
69                 if (!dot_aaf.exists()) {
70                         dot_aaf.mkdirs();
71                 }
72                 File f = new File(dot_aaf, "sso.out");
73                 os = new PrintStream(new FileOutputStream(f, true));
74                 System.setOut(os);
75                 System.setErr(os);
76
77                 access = new PropAccess(os, nargs);
78                 Config.setDefaultRealm(access);
79
80                 user = access.getProperty(Config.AAF_APPID);
81                 encrypted_pass = access.getProperty(Config.AAF_APPPASS);
82
83                 File dot_aaf_kf = new File(dot_aaf, "keyfile");
84
85                 sso = new File(dot_aaf, "sso.props");
86                 if (removeSSO) {
87                         if (dot_aaf_kf.exists()) {
88                                 dot_aaf_kf.setWritable(true, true);
89                                 dot_aaf_kf.delete();
90                         }
91                         if (sso.exists()) {
92                                 sso.delete();
93                         }
94                         System.out.println("AAF SSO information removed");
95                         if (doExit) {
96                                 System.exit(0);
97                         }
98                 }
99
100                 if (!dot_aaf_kf.exists()) {
101                         FileOutputStream fos = new FileOutputStream(dot_aaf_kf);
102                         try {
103                                 fos.write(Symm.keygen());
104                                 setReadonly(dot_aaf_kf);
105                         } finally {
106                                 fos.close();
107                         }
108                 }
109
110                 String keyfile = access.getProperty(Config.CADI_KEYFILE); // in case it's CertificateMan props
111                 if (keyfile == null) {
112                         access.setProperty(Config.CADI_KEYFILE, dot_aaf_kf.getAbsolutePath());
113                 }
114
115                 String alias = access.getProperty(Config.CADI_ALIAS);
116                 if ((user == null) && (alias != null) && (access.getProperty(Config.CADI_KEYSTORE_PASSWORD) != null)) {
117                         user = alias;
118                         access.setProperty(Config.AAF_APPID, user);
119                         use_X509 = true;
120                 } else {
121                         use_X509 = false;
122                         Symm decryptor = Symm.obtain(dot_aaf_kf);
123                         if (user == null) {
124                                 if (sso.exists() && (sso.lastModified() > (System.currentTimeMillis() - EIGHT_HOURS))) {
125                                         String cm_url = access.getProperty(Config.CM_URL); // SSO might overwrite...
126                                         FileInputStream fos = new FileInputStream(sso);
127                                         try {
128                                                 access.load(fos);
129                                                 user = access.getProperty(Config.AAF_APPID);
130                                                 encrypted_pass = access.getProperty(Config.AAF_APPPASS);
131                                                 // decrypt with .aaf, and re-encrypt with regular Keyfile
132                                                 access.setProperty(Config.AAF_APPPASS,
133                                                                 access.encrypt(decryptor.depass(encrypted_pass)));
134                                                 if (cm_url != null) { //Command line CM_URL Overwrites ssofile.
135                                                         access.setProperty(Config.CM_URL, cm_url);
136                                                 }
137                                         } finally {
138                                                 fos.close();
139                                         }
140                                 } else {
141                                         diskprops = new Properties();
142                                         String realm = Config.getDefaultRealm();
143                                         // Turn on Console Sysout
144                                         System.setOut(System.out);
145                                         user = cons.readLine("aaf_id(%s@%s): ", System.getProperty("user.name"), realm);
146                                         if (user == null) {
147                                                 user = System.getProperty("user.name") + '@' + realm;
148                                         } else if (user.length() == 0) { //
149                                                 user = System.getProperty("user.name") + '@' + realm;
150                                         } else if ((user.indexOf('@') < 0) && (realm != null)) {
151                                                 user = user + '@' + realm;
152                                         }
153                                         access.setProperty(Config.AAF_APPID, user);
154                                         diskprops.setProperty(Config.AAF_APPID, user);
155                                         encrypted_pass = new String(cons.readPassword("aaf_password: "));
156                                         System.setOut(os);
157                                         encrypted_pass = Symm.ENC + decryptor.enpass(encrypted_pass);
158                                         access.setProperty(Config.AAF_APPPASS, encrypted_pass);
159                                         diskprops.setProperty(Config.AAF_APPPASS, encrypted_pass);
160                                         diskprops.setProperty(Config.CADI_KEYFILE, access.getProperty(Config.CADI_KEYFILE));
161                                 }
162                         }
163                 }
164                 if (user == null) {
165                         err = new StringBuilder("Add -D" + Config.AAF_APPID + "=<id> ");
166                 }
167
168                 if (encrypted_pass == null && alias == null) {
169                         if (err == null) {
170                                 err = new StringBuilder();
171                         } else {
172                                 err.append("and ");
173                         }
174                         err.append("-D" + Config.AAF_APPPASS + "=<passwd> ");
175                 }
176         }
177
178         public void setLogDefault() {
179                 this.setLogDefault(PropAccess.DEFAULT);
180         }
181
182         public void setStdErrDefault() {
183                 access.setLogLevel(PropAccess.DEFAULT);
184                 System.setErr(System.err);
185         }
186
187         public void setLogDefault(Level level) {
188                 access.setLogLevel(level);
189                 System.setOut(System.out);
190         }
191
192         public boolean loginOnly() {
193                 return loginOnly;
194         }
195
196         public void addProp(String key, String value) {
197                 if (diskprops != null) {
198                         diskprops.setProperty(key, value);
199                 }
200         }
201
202         public void writeFiles() throws IOException {
203                 // Store Creds, if they work
204                 if (diskprops != null) {
205                         if (!dot_aaf.exists()) {
206                                 dot_aaf.mkdirs();
207                         }
208                         FileOutputStream fos = new FileOutputStream(sso);
209                         try {
210                                 diskprops.store(fos, "AAF Single Signon");
211                         } finally {
212                                 fos.close();
213                                 setReadonly(sso);
214                         }
215                 }
216                 if (sso != null) {
217                         setReadonly(sso);
218                         sso.setWritable(true, true);
219                 }
220         }
221
222         public PropAccess access() {
223                 return access;
224         }
225
226         public StringBuilder err() {
227                 return err;
228         }
229
230         public String user() {
231                 return user;
232         }
233
234         public String enc_pass() {
235                 return encrypted_pass;
236         }
237
238         public boolean useX509() {
239                 return use_X509;
240         }
241
242         public void close() {
243                 if (close != null) {
244                         try {
245                                 close.invoke(null);
246                         } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
247                                 // nothing to do here.
248                         }
249                         close = null;
250                 }
251         }
252
253         private String[] parseArgs(String[] args)
254         {
255                 List<String> larg = new ArrayList<String>(args.length);
256
257                 // Cover for bash's need to escape *.. (\\*)
258                 // also, remove SSO if required
259                 for (int i = 0; i < args.length; ++i) {
260                         if ("\\*".equals(args[i])) {
261                                 args[i] = "*";
262                         }
263
264                         if ("-logout".equalsIgnoreCase(args[i])) {
265                                 removeSSO = true;
266                         } else if ("-login".equalsIgnoreCase(args[i])) {
267                                 loginOnly = true;
268                         } else if ("-noexit".equalsIgnoreCase(args[i])) {
269                                 doExit = false;
270                         } else {
271                                 larg.add(args[i]);
272                         }
273                 }
274                 String[] nargs = new String[larg.size()];
275                 larg.toArray(nargs);
276                 return nargs;
277         }
278         
279         private void setReadonly(File file) {
280                 file.setExecutable(false, false);
281                 file.setWritable(false, false);
282                 file.setReadable(false, false);
283                 file.setReadable(true, true);
284         }
285 }