As a security measure Windows forwards local smartcard readers to the remote machine. The problem is that
readers you already have handles for become unusable
it's not possible to get new readers
If you try to use a terminal or CardTerminals object, you get a PCSCException: SCARD_E_SERVICE_STOPPED.
I have code to demonstrate the issue:
import javax.smartcardio.*;
public class ScRdp {
public static void main( final String[] args ) throws Exception
{
TerminalFactory factory = TerminalFactory.getDefault();
System.out.println( "Factory: " + factory.hashCode() );
final CardTerminals terminals = factory.terminals();
List<CardTerminal> termNames = terminals.list();
BufferedReader in = new BufferedReader( new InputStreamReader( System.in ) );
in.readLine();
main( args );
}
}
Launch the code on machine A, RDP in using machine B and hit enter. You can even RDP in, immediately disconnect and hit enter on machine A.
In C, I would use SCardReleaseContext and SCardEstablishContext (ref). Is there any way to do this through the Java API?
Followup
AFAICT this is not possible. However see link, link. It should be possible to disable smartcard redirection on the server, circumventing the problem.
On Win7 Pro I found the setting in gpedit.msc: "Computer Configuration/Administrative Templates/Windows Components/Remote Desktop Services/Remote Desktop Session Host/Device and Resource Redirection/Do not allow smart card device redirection". That said I do not have this working yet. Even unchecking the "forward smartcards" checkbox in the RDP client before connection doesn't help.
This is only an issue if you RDP in as the same user as the one using the readers. We circumvented it by running the server using JavaService.exe from ObjectWeb to run as "Local System" user.
Related
I want to be able to open Mozilla Firefox in a Remote Desktop and be able to "play" inside Mozilla (accessing URLs, import from the "Desktop" of the Remote Desktop Connection). All these, I want them to be automatically executed. That is why I have created a java code in eclipse. So far, I am able to automatically access the Remote Desktop Connection. Please find the code that I am using for this:
public static void main(String[] args) throws IOException, InterruptedException {
String ip = "xxx.xxx.xx.xx"; //check if this is the desired IP
String userName = "XXX"; //check if this is the correct username
String password = "XXXxxx"; //check if the password has changed
String jacobDllVersionToUse;
jacobDllVersionToUse = "jacob-1.18-x64.dll";
File file = new File("lib", jacobDllVersionToUse);
System.setProperty(LibraryLoader.JACOB_DLL_PATH, file.getAbsolutePath());
// creating credentials
Process p = Runtime.getRuntime().exec("cmdkey /generic:"+ip+" /user:"+userName+" /pass:"+password );
p.destroy();
Process p2 = Runtime.getRuntime().exec("mstsc /v: "+ip+" /f /console");
AutoItX x = new AutoItX();
x.winWaitActive("Remote Desktop Connection");
x.controlClick("Remote Desktop Connection", "Co&nnect", "1");
x.winWaitActive("Remote Desktop Connection");
x.controlClick("Remote Desktop Connection", "Co&nnect", "1");
}
Could you assist me on how I will be able to open Mozilla in Remote Desktop through eclispse?
Thank you in advance!
I assume the code successfully activates the RDP Window.
Once it is active AutoIt can't identify elements controls inside the window, but you can still send keyboard commands using Java Robot or even AutoIt.
To launch Firefox send a Window+R and then pass the path of firefox.exe ("C:\Program Files\Mozilla Firefox\firefox.exe") and send ENTER.
I have an eclipse RCP product that is run by multiple people at our company. All PCs are running some version of Windows. We have access to a shared PC which different people have mapped to different drive letters. That means the same file may be referred to in many different ways depending on the PC on which program is run. E.g.
\communalPC\Shared\foo.txt
Y:\Shared\foo.txt
Z:\Shared\foo.txt
I want to programmatically check if an arbitrary file is on the communnal PC. Is there a robust way to do this in java?
Our current solution below is a bit of a hack It is not robust due to people mapping to different drive letters, changing drive letters, not-portable etc.
private static boolean isOnCommunalPc(File file) {
if(file.getAbsolutePath().toLowerCase().startsWith("\\\\communalPC")) {
return true;
}
if(file.getAbsolutePath().toLowerCase().startsWith("y:")){
return true;
}
if(file.getAbsolutePath().toLowerCase().startsWith("z:")){
return true;
}
return false;
}
Java cannot tell the difference of which machine the file is on, as Windows abstracts that layer away from the JVM. You can, however be explicit with your connection.
Is there a reason why you couldn't have an ftp or http server (or even a custom java server!) on the communal pc, and to access it via a hostname or an ip? That way, it doesn't matter where the user has mapped the network drive, you connected via a static address.
Accessing a remote file in Java is as easy as:
URL remoteUrl = new URL(String.format("%s/%s", hostName, fileName));
InputStream remoteInputStream remoteUrl.openConnection().getInputStream();
//copyStreamToFile(remoteInputStream, new File(destinationPath), false);
If you need the file to be local for a library or code you would prefer not to change, you could:
void copyStreamToFile(InputStream in, File outputFile, boolean doDeleteOnExit) {
//Clean up file after VM exit, if needed.
if(doDeleteOnExit)
outputFile.deleteOnExit();
FileOutputStream outputStream = new FileOutputStream(outputFile);
ReadableByteChannel inputChannel = Channels.newChannel(in);
WritableByteChannel outputChannel = Channels.newChannel(outputStream);
ChannelTools.fastChannelCopy(inputChannel, outputChannel);
inputChannel.close();
outputChannel.close()
}
EDIT Accessing a remote file via Samba with JCIFS is as easy as:
domain = ""; //Your domain, only set if needed.
NtlmPasswordAuthentication npa = new NtlmPasswordAuthentication(domain, userName, password);
SmbFile remoteFile = new SmbFile(String.format("smb://%s/%s", hostName, fileName), npa);
//copyStreamToFile(new SmbFileInputStream(remoteFile), new File(destinationPath), false)
This will probably be the most pragmatic solution, as it requires the least amount of work on the Windows server. This plugs into the existing server framework in Windows, instead of installing more.
I am need to spawn a SSH connection from a JAVA program using ProcessBuilder and a USERID/PASSWORD combination.
I have already successfully implemented SSH connections using Ganymed, JSch, a combination of JAVA Processbuilder and Expect scripting (Expect4J also), JAVA ProcessBuilder and SSHPASS script and SSH Shared Key.
Security is NOT a concern at this point in time and all I am after is to be able to support programmatically all kinds of combinations for SSH connection.
My problem is the Password prompt that SSH throws somewhere that is not on STDIN/STDOUT (on a tty I believe). This is my last hurdle to overcome.
My question is there a way to intercept SSH password request and provide it from my JAVA code?
Please, note this is a very narrow question (and all the above information was to guarantee the answer would not be too broad).
Here is a sample code of what I am trying:
import java.io.*;
import java.util.*;
public class ProcessBuilderTest {
public static void main(String[] args) throws IOException, Exception {
ProcessBuilder pb = new ProcessBuilder(
"/usr/bin/ssh",
"nyuser#myserver.com",
"export NOME='Jennifer Lawrence'; echo $NOME"
);
pb.redirectErrorStream(); //redirect stderr to stdout
Process process = pb.start();
InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
while((line = reader.readLine())!= null) {
System.out.println(line);
}
process.waitFor();
}
}
But, when I run it I got this:
[memphis BuilderTest]# java ProcessBuilderTest
myuser#myserver's password:
and after I type the password, I got the rest of the output:
Jennifer Lawrence
[memphis BuilderTest]#
Again, the specific question is:
Is there a way to spawn an external ssh client (OpenSSH, Tectia SSH, SecureCRT, etc) using PasswordAuthentication method (no other method can be used) process using JAVA ProcessBuilder interface (no other language can be used), intercept/capture the password prompt and respond/interact providing that password from my JAVA code (so the user does not need to type it)?
You need to learn about pseudo-ttys, assuming that you are operating on Linux. The password prompt is on the tty device. You will need to build a separate process running against a pseudo-tty instead of just inheriting your tty device, and then you can intercept the password prompt.
This is a moderately complex process.
There is a library that supports some of this: http://www.ganymed.ethz.ch/ssh2/FAQ.html. You might find reading its source illuminating if it is available.
While it has been suggested that a pseudo-tty (pty) is required to simulate a terminal, the accepted answer doesn't provide a working solution - there are also lots of similar questions with no working answers.
Here are two solutions that allow you to capture the "Password:" prompt in SSH and enter the password in an automated way without using SSH_ASKPASS or Expect.
Why use one programming language when you can use two - the first option isn't ideal, but it demonstrates the solution:
ProcessBuilder pb = new ProcessBuilder("/usr/bin/python", "-c", "import pty; pty.spawn(['/usr/bin/ssh', '<hostname>'])");
The above example makes use of the Python pty module to wrap SSH into a PTY. Although it is simple, it doesn't provide any flexibility to allow you to modify any terminal properties like the passed window size.
The other more lightweight option is to use a PTY wrapper in C - the pty tool from the "Advanced Programming in the UNIX® Environment" book is just this - the source can be found at https://github.com/abligh/pty.
You will then use it in a similar way, but referencing the pty tool instead of Python:
ProcessBuilder pb = new ProcessBuilder("/usr/local/bin/pty", "/usr/bin/ssh", "<hostname>");
This is the same approach that Expect uses to simulate a PTY, which is why you are able to intercept it using Expect. It goes without saying that tunneled clear text passwords are insecure and public key authentication should always be the preferred way of doing this.
I have Gui Application written which running on windows,and i want to connect to remote unix machine and perform actions there such like API's ,go over the log file in the machines and send back to the application the last log file or others API that i want to perform on the remote machine.
In the remote machine i don;t have application server i just have Java which installed there.
I want to use Java in order to perform remote API over the remote machine;
what is the advice ,can i use web services ,can any one please advise.
Thanks in advance.
If Java can perform the actions you're talking about, I would use Sockets to communicate with the UNIX-Machine (over TCP/IP).
Your Windows-PC would be the client sending commands to the Unix-PC.
Web services would be a bit heavy handed option, esp if you opt for the SOAP ones. If you don't have a problem with the client and server always being Java, RMI seems to be the simplest solution to this problem since it's communication between two different JVM's using the normal method calling mechanism (with some additional interfaces and rules to be followed to please the RMI specification).
The Spring Framework ships with a number of remoting options that are all very easy to setup. You can use their classes for simpler configuration of something standard like RMI or JMS, or use a lightweight web services protocol such as Spring's HTTP invoker or Hessian.
For analyzing log files of remote machines you can always use Apache Commons sftp programmatically to FTP a copy of the remote log file to your PC.
If you configure the log files to be rotatable or to rotate each time they reach a specific size, you can avoid reloading the same information over and over.
You can use Ganymed SSH-2 for Java to ssh to the remote host from Client Java App and run the commands. No need to run any additional components on remote server. You can do password based authentication or key based authentication to login to remote host. We had successfully used it to administer (start/stop/grep log files, etc.) applications running on remote UNIX hosts. You can capture output of the remote command using the StreamGobbler class provided in the package. You can pass multiple commands separated by semi-colon in one remote call.
Basic Example included in the package:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
public class Basic
{
public static void main(String[] args)
{
String hostname = "127.0.0.1";
String username = "joe";
String password = "joespass";
try
{
/* Create a connection instance */
Connection conn = new Connection(hostname);
/* Now connect */
conn.connect();
/* Authenticate.
* If you get an IOException saying something like
* "Authentication method password not supported by the server at this stage."
* then please check the FAQ.
*/
boolean isAuthenticated = conn.authenticateWithPassword(username, password);
if (isAuthenticated == false)
throw new IOException("Authentication failed.");
/* Create a session */
Session sess = conn.openSession();
sess.execCommand("uname -a && date && uptime && who");
System.out.println("Here is some information about the remote host:");
/*
* This basic example does not handle stderr, which is sometimes dangerous
* (please read the FAQ).
*/
InputStream stdout = new StreamGobbler(sess.getStdout());
BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
while (true)
{
String line = br.readLine();
if (line == null)
break;
System.out.println(line);
}
/* Show exit status, if available (otherwise "null") */
System.out.println("ExitCode: " + sess.getExitStatus());
/* Close this session */
sess.close();
/* Close the connection */
conn.close();
}
catch (IOException e)
{
e.printStackTrace(System.err);
System.exit(2);
}
}
}
I'm looking form way how to get system proxy information in Java under Windows, but I've found just one way. But it does not work for me.
public static void main(String[] args) throws Throwable {
System.setProperty("java.net.useSystemProxies", "true");
System.out.println("detecting proxies");
List<Proxy> pl = ProxySelector.getDefault().select(new URI("http://ihned.cz/"));
for (Proxy p : pl)
System.out.println(p);
Proxy p = null;
if (pl.size() > 0) //uses first one
p = pl.get(0);
System.out.println(p.address());
System.out.println("Done");
}
When I run the program, I get:
detecting proxies
DIRECT
null
Done
Java means, that I'm situated directly on internet. But it's wrong. I'm behind proxy. I'm unable to get the solution for my computer.
As we discussed in the comments the proxy settings is just applied for some of browsers you use.
If you want Java to use the same settings you need to manually put it into the java network settings (check this web page for details).
Thanks to Dacwe. The problem is, that browser does not use any system proxy, but it sets proxy self using a script. Thus there are not any proxies in the system and Java cannot reach them.