Tuesday, February 24, 2009

Java, Telnet and AIX

I've decided to use the UnixLoginHanlder class. Here's my sample code s, and below is the history of my struggles.

Socket s = new Socket(host, port);
UnixLoginHandler handler = new UnixLoginHandler(s);
TelnetInputStreamConsumer is = handler.doLogin(user, pass);

String command="echo hello > deleteme.tres\r\n";

pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()), true);

pw.print(command);
// Don't forget to flush

pw.flush();

// Executing these immediately may precede the commands.
// Do logout/disconnects on a seperate event
//handler.doLogout();

//handler.disconnect();

Good luck!

____________________________________________________________
____________________________________________________________

This article will illustrate my struggles with automating some Telnet functions through Java. The application that's being designed could provide as an interface or relay server, and is intended eventually to get some information out of some flat files on an IBM AIX Unix server.

Disclaimer: Yes I'm aware of the security issues around the Telnet protocol. No, SSH is not available currently on this server.

In short, I'm trying to get a simple telnet session working through a Java Socket connection. Some examples, like this one make it seem as simple as making a new Socket and sending some text through. Naturally, I wouldn't be writing this article if it were that simple. Methods like "readline()" return arbitrary characters like "ÿþ%ÿý", and there's not much documentation around what this all means, so instead of spending more time re-inventing the wheel, I've begun evaluating 3rd party APIs.

A quick Google search shows some APIs with tutorials, but costs money. I'm skipping those for now, since I'm just in the design phase of this interface, so I'm sticking to free ones for now. The closer to GPL the better, right?

Forums allude that the Apache project has a great implementation of the Telnet protocol. My experience with the Apache libraries are they are often interdependent on each other, and I'd like to make this interface as small and vanilla as possible. I've found three potential candidates: JTA Telnet for Java, sadun-utils UnixLoginHandler and Dieter Wimberger's telnetd2. Telnetd2 does not come pre-compiled to drop-in as an API and also doesn't provide any code-snippets or documentation with its download, so going to skip that for now as well.

My unsuccessful code snippets are below attached exactly as they appeared in outgoing emails. As authors respond, I'll post their messages as well. If I have success, I'll certainly post that too.

Hi.

My name's Tres and I've been trying to use JTA as an API in an
application for implementing a simple Telnet connection.

I tried the sample code in /jta26/de/mud/telnet/
TelnetWrapper's
javadoc, and it connects and does a log-in first try, however I'm
having a hard time getting any further, such as executing commands on
the remote host.

I'm in Windows XP JDK 1.6 connecting to AIX 5.2. If I run the JAR as
an application it works just like PuTTY and acts as expected, so I'm
sure its something that I'm doing wrong in the code.

Is there a mailing list or perhaps a person to contact with this?
Also, are there any special considerations when connecting to Korn
shell or AIX? Thanks!

-Tres

p.s. I've attached the sample TelnetWrapper code below which has been
copied from the javadoc.

/**
* TelnetWrapper telnet = new TelnetWrapper();
* try {
* telnet.connect(args[0], 23);
* telnet.login("user", "password");
* telnet.setPrompt("user@host");
* telnet.waitfor("Terminal type?");
* telnet.send("dumb");
* System.out.println(telnet.
send("ls -l"));
* } catch(java.io.IOException e) {
* e.printStackTrace();
* }
*/
I quickly received a response from Matt Jugel:
Check that there actually is a "Terminal type?" prompt coming from your AIX host.
It will wait forever if this is not prompted. Remove the Terminal type waitfor and the send lin thereafter and try again.

Leo.
And here's my response to him:
Matt,

Thanks for the quick response. I simply attached that for a
refresher. A snippet of my usage is attached below. My "output" from
the command is always "null" and the file "deleteme.tres" never gets
created.

> TelnetWrapper telnet = new TelnetWrapper();
> String output;
> try {
> telnet.setLocalEcho(true);
> System.out.println("
Connecting...");
> telnet.connect(host, port);
> System.out.println("Logging in...");
> telnet.login(user, pass);
> System.out.println("Waiting...
");
> telnet.waitfor("/usr/local/
gnu/bin");
> System.out.println("Sending command...");
> output = telnet.send("echo hello > deleteme.tres");
> System.out.println("Output: " + output);
> telnet.disconnect();
> System.out.println("Done.");
> }
> catch(java.io.IOException e) {
> e.printStackTrace();
> }


-Tres

I've since emailed sadun through the SourceForge website on the UnixLoginHandler API:

Hi,

My name's Tres and I'm trying to set up a simple Telent session to an AIX machine. Client is Windows XP JDK 1.5 server is AIX 5.2.

I've tried your API for establishing this connection, and it seems to log in just fine, but when I try sending commands to the server, it does not appear to be working. Here's a snippet of my code:

> Socket s = new Socket(host, port);
> UnixLoginHandler handler = new UnixLoginHandler(s);
> TelnetInputStreamConsumer is = handler.doLogin(user, pass);
> String command="echo hello > deleteme.tres";
> pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()), true);
> pw.print(command+"\r\n");
> handler.doLogout();

When I do a "who" on the server, I can see the specified user logging in as a TTY session, however, the command does not appear to be executing, as the file "deleteme.tres" never gets created.

Any help would be appreciated. Sorry to email you through SourceForge, but I couldn't find a forum for this project.

-Tres
Sadun replied quickly with the following:
Hei,

no problem. Unfortunately I dont have an AIX machine to test right now. The original code's been running over HP and Solaris insofar I know.
How does the login prompt looks like at your target host? The handler uses "ogin:" by default, but it may be need to be configured differently.

Of course a bug is always possible. Like most of the utility classes, the group of telnet-related classes are relatively self contained - it should be easy to download the source and check directly at least where the output ends up stopping with a step-by-step editor..

-cs
And here's my response to him:
cs,

Thanks for the quick response.

The login sequence is working great. The server I am connecting to
uses "login:", and
"Password:". It appears to be logging in correctly as I can see the
connection come through (see screenshot "telnet.png" attached).

I am using the org.sadun.util.jar on my class path, so I cannot
step-by-step into the source code at this moment.

Could the issue be the CRLF characters sent through the terminal? Can
these change? I'm confused because the login works as expected.

To add to the confusion, I am having identical issues with JTA -
Telnet/SSH libraries where the connection establishes but I cannot go
any further.

Any help is greatly appreciated!!

-Tres
Here's his most useful response:
Hm. Have you tried removing the wrapping PrintWriter and flushing the outputstream directly?
Flush being the keyword. Since I had not worked with OutputStreams, I had forgotten to flush(), and the code snippet didn't have this line in there. Kudos to the UnixLoginHandler. This will the the one I'll use.

-Tres

2 comments:

Dieter said...

Hey there,

I am the author of telnetd; actually there is quite a bunch of code snippets within the documentation, which is represented also at:
http://telnetd.sourceforge.net/

You probably want to check out the documentation section, with the API and some how-to's. I also commonly help out people that write ;)

Regards,
Dieter

FatButtLarry said...

Dieter,

You are correct, my above post is incorrect, upon revisit, there's plenty of documentation.

Although the IDE I use calls ant behind the scenes, I was opting for the quickest class to get a proof of concept ready so I avoided compiling for that very reason. (I'm not too fluent with ant).

You said the following in your documentation:
> "Most IDE's nowadays provide ant integration or at least support anyway."

And the IDE I use, NetBeans didn't seem to have an easy way to bring the project in and compile. I didn't spend more than 20 minutes trying to figure it out though so I'm open to suggestions.

The UnixLoginHandler class that I'm currently using is having some sporatic connection issues. I was hoping the setTimeOut() would fix this but it doesn't seem to be helping.

If the project gets approved as being developed in-house, I may turn to telnetd, so any information is great, and I truly appreciate the gesture.

My main concern early on was getting a quick java telnet session to prove that our development group could in fact develop the solution in-house. What threw me for a loop with telnetd was trying to find a quick API implementation.

The shell tutorial:
http://telnetd.sourceforge.net/deployment/shell_tutorial.html

Looks like it might have whats needed, but it looks more of an interactive shell-in-gui implementation. I had a hard time figuring out what "shell implementation was". The description says:

> "This document describes how to write a Shell implementation and points out important issues with the implementation."

Which didn't mean a bunch to me... I'm a bit confused what the difference between terminal shell and daemon are.

Thanks again for the message. I'll likely be in contact regarding telnetd if this project takes off. Feel free to post back. Cheers.

-Tres