From 9fd77f53bd6238ee94b1ed5fe55dcfbfb475a93d Mon Sep 17 00:00:00 2001 From: Endi Sukma Dewata Date: Wed, 30 Jan 2013 13:26:55 -0500 Subject: Session support on CLI. The CLI has been modified to support executing multiple commands through the same session. A new 'connect' command has been added to establish the session. A new 'disconnect' command has been added to destroy the session. This way it's no longer necessary to specify the authentication info in each commands: pki connect pki user-find pki user-show caadmin pki disconnect The old way of specifying the authentication info in each command will continue to work, but the commands will be executed in separate sessions: pki user-find pki user-show caadmin Ticket #474 --- .../com/netscape/certsrv/client/PKIConnection.java | 48 ++++++++++++++- .../cms/tomcat/SSLAuthenticatorWithFallback.java | 8 +++ .../src/com/netscape/cmstools/cli/ConnectCLI.java | 40 +++++++++++++ .../com/netscape/cmstools/cli/DisconnectCLI.java | 40 +++++++++++++ .../src/com/netscape/cmstools/cli/MainCLI.java | 68 ++++++++++++++++++---- 5 files changed, 192 insertions(+), 12 deletions(-) create mode 100644 base/java-tools/src/com/netscape/cmstools/cli/ConnectCLI.java create mode 100644 base/java-tools/src/com/netscape/cmstools/cli/DisconnectCLI.java diff --git a/base/common/src/com/netscape/certsrv/client/PKIConnection.java b/base/common/src/com/netscape/certsrv/client/PKIConnection.java index 4556f1c6a..2a29db207 100644 --- a/base/common/src/com/netscape/certsrv/client/PKIConnection.java +++ b/base/common/src/com/netscape/certsrv/client/PKIConnection.java @@ -1,7 +1,11 @@ package com.netscape.certsrv.client; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.InetAddress; @@ -28,12 +32,15 @@ import org.apache.http.ProtocolException; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.auth.params.AuthPNames; +import org.apache.http.client.CookieStore; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.params.AuthPolicy; import org.apache.http.client.params.HttpClientParams; import org.apache.http.conn.scheme.LayeredSchemeSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeSocketFactory; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.ClientParamsStack; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultRedirectStrategy; @@ -62,7 +69,8 @@ public class PKIConnection { ClientConfig config; - DefaultHttpClient httpClient = new DefaultHttpClient(); + DefaultHttpClient httpClient; + CookieStore cookieStore; ResteasyProviderFactory providerFactory; ClientErrorHandler errorHandler; @@ -71,6 +79,9 @@ public class PKIConnection { public PKIConnection(ClientConfig config) { this.config = config; + httpClient = new DefaultHttpClient(); + cookieStore = httpClient.getCookieStore(); + // Register https scheme. Scheme scheme = new Scheme("https", 443, new JSSProtocolSocketFactory()); httpClient.getConnectionManager().getSchemeRegistry().register(scheme); @@ -345,6 +356,41 @@ public class PKIConnection { } + public void loadCookies(File file) throws IOException, ClassNotFoundException { + + if (verbose) System.out.println("Loading cookies from "+file+":"); + + FileInputStream fis = new FileInputStream(file); + ObjectInputStream ois = new ObjectInputStream(fis); + + BasicCookieStore bcs = (BasicCookieStore)ois.readObject(); + + cookieStore.clear(); + for (Cookie cookie : bcs.getCookies()) { + if (verbose) System.out.println(" "+cookie.getName()+": "+cookie.getValue()); + cookieStore.addCookie(cookie); + } + + ois.close(); + } + + public void saveCookies(File file) throws IOException { + + if (verbose) System.out.println("Storing cookies into "+file+":"); + + BasicCookieStore bcs = new BasicCookieStore(); + + for (Cookie cookie : cookieStore.getCookies()) { + if (verbose) System.out.println(" "+cookie.getName()+": "+cookie.getValue()); + bcs.addCookie(cookie); + } + + FileOutputStream fos = new FileOutputStream(file); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(bcs); + oos.close(); + } + public T createProxy(Class clazz) throws URISyntaxException { URI uri = new URI(config.getServerURI()+"/rest"); return ProxyFactory.create(clazz, uri, executor, providerFactory); diff --git a/base/common/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java b/base/common/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java index d1b3dc3f2..2e4d2002a 100644 --- a/base/common/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java +++ b/base/common/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java @@ -19,6 +19,7 @@ package com.netscape.cms.tomcat; import java.io.IOException; +import java.security.Principal; import java.security.cert.X509Certificate; import javax.servlet.http.HttpServletRequest; @@ -77,6 +78,13 @@ public class SSLAuthenticatorWithFallback extends AuthenticatorBase { @Override public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException { + log("Session: "+request.getSession().getId()); + Principal principal = request.getPrincipal(); + if (principal != null) { + log("Already authenticated as "+principal.getName()); + return true; + } + X509Certificate certs[] = (X509Certificate[]) request.getAttribute(Globals.CERTIFICATES_ATTR); boolean result; diff --git a/base/java-tools/src/com/netscape/cmstools/cli/ConnectCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/ConnectCLI.java new file mode 100644 index 000000000..60e15bf9e --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/cli/ConnectCLI.java @@ -0,0 +1,40 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cmstools.cli; + + +/** + * @author Endi S. Dewata + */ +public class ConnectCLI extends CLI { + + public MainCLI parent; + + public ConnectCLI(MainCLI parent) { + super("connect", "Connect to PKI server"); + this.parent = parent; + } + + public void printHelp() { + } + + public void execute(String[] args) throws Exception { + parent.accountClient.login(); + } +} diff --git a/base/java-tools/src/com/netscape/cmstools/cli/DisconnectCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/DisconnectCLI.java new file mode 100644 index 000000000..6d57d7f33 --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/cli/DisconnectCLI.java @@ -0,0 +1,40 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cmstools.cli; + + +/** + * @author Endi S. Dewata + */ +public class DisconnectCLI extends CLI { + + public MainCLI parent; + + public DisconnectCLI(MainCLI parent) { + super("disconnect", "Disconnect from PKI server"); + this.parent = parent; + } + + public void printHelp() { + } + + public void execute(String[] args) throws Exception { + parent.accountClient.logout(); + } +} diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java index 191a6326d..a43a3fbd1 100644 --- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java @@ -19,6 +19,7 @@ package com.netscape.cmstools.cli; import java.io.File; +import java.net.URI; import java.net.URISyntaxException; import org.apache.commons.cli.CommandLine; @@ -47,12 +48,25 @@ public class MainCLI extends CLI { public ClientConfig config = new ClientConfig(); + public File clientDir; + public File cookiesDir; + public PKIConnection connection; public AccountClient accountClient; + public ConnectCLI connectModule; + public DisconnectCLI disconnectModule; + public MainCLI() throws Exception { super("pki", "PKI command-line interface"); + clientDir = new File(System.getProperty("user.home"), ".pki"+File.separator+"client"); + cookiesDir = new File(clientDir, "cookies"); + cookiesDir.mkdirs(); + + addModule(connectModule = new ConnectCLI(this)); + addModule(disconnectModule = new DisconnectCLI(this)); + addModule(new CertCLI(this)); addModule(new GroupCLI(this)); addModule(new KeyCLI(this)); @@ -292,19 +306,54 @@ public class MainCLI extends CLI { } } - // execute command + URI uri = config.getServerURI(); + String path = uri.getPath().replace("/", "-"); + String filename = uri.getScheme()+"-"+uri.getHost()+"-"+uri.getPort()+path; + File cookies = new File(cookiesDir, filename); + boolean loggedIn = false; + try { connect(); - // login - if (config.getCertDatabase() != null || config.getUsername() != null) { - accountClient.login(); - loggedIn = true; - } + if (module == connectModule) { + // create session for multi-command mode + connectModule.execute(moduleArgs); + // store cookies + connection.saveCookies(cookies); + + } else if (module == disconnectModule) { + // load cookies for the current session + connection.loadCookies(cookies); + // destroy session for multi-command mode + disconnectModule.execute(moduleArgs); + // destroy cookies + cookies.delete(); + + } else { + + if (cookies.exists()) { + // load cookies for multi-command mode + connection.loadCookies(cookies); + + } else if (config.getCertDatabase() != null || config.getUsername() != null) { + // create session for single-command mode + connectModule.execute(moduleArgs); + loggedIn = true; + } + + // execute module command + module.execute(moduleArgs); - // execute module command - module.execute(moduleArgs); + if (cookies.exists()) { + // store cookies for multi-command mode + connection.saveCookies(cookies); + + } else if (loggedIn) { + // destroy session for single-command mode + disconnectModule.execute(moduleArgs); + } + } } catch (Throwable t) { if (verbose) { @@ -313,9 +362,6 @@ public class MainCLI extends CLI { System.err.println(t.getClass().getSimpleName()+": "+t.getMessage()); } System.exit(1); - - } finally { - if (loggedIn) accountClient.logout(); } } -- cgit