Dialing into TINI from a PC (With Authentication)

11 May

Example: Dialing into TINI from a PC (With Authentication): The previous example involved making a TINI act as a PPP server that can be called and logged into remotely from a PC. For simplicity, we omitted user authentication. Anybody can call into TINI and start up a PPP connection. That’s a great big weakness. So, we’re going to redo the example adding user authentication. There are really only two changes to the program. We have to add some code that takes a user name and a password from the client requesting a connection and compare them against the data stored in the TINI  password file. We need to then execute this code when the AUTHENTICATION_REQUEST event occurs (that is, during the AUTH state). Last, we need to add the setAuthenticate(true) method to main(). We’re going to present the whole  program below, then look at the portions that differ from the previous example.

Listing 13-7: PPPServerWA.java

import java.io.*;

import javax.comm.*;

import com.dalsemi.tininet.ppp.*;

public class PPPServerWA implements PPPEventListener {

static SerialPort serialPort = null;

static PPP ppp;

public void pppEvent (PPPEvent e) {

switch(e.getEventType()) {

case PPPEvent.STARTING:

System.out.println(“PPP sent the STARTING event!”);

ppp.up(serialPort);

break;

case PPPEvent.UP:

System.out.println(“PPP sent the UP event!”);

ppp.addInterface(“ppp0”);

break;

case PPPEvent.AUTHENTICATION_REQUEST:

System.out.println(“PPP sent the AUTHENTICATION_REQUEST event!”); String userName = ppp.getPeerID();

String password = ppp.getPeerPassword();

if (validateLogin(userName, password)) {

ppp.authenticate(true);

System.out.println(“Login Validation has succeeded”);

} else {

ppp.authenticate(false);

System.out.println(“Login Validation has failed”);

}

break;

case PPPEvent.STOPPED:

System.out.println(“PPP sent the STOPPED event!”);

ppp.close();

break;

case PPPEvent.CLOSED:

System.out.println(“PPP sent the CLOSED event!”);

ppp.down();

ppp.removeEventListener(this); serialPort.close(); System.exit(0);

break;

default:

break;

}

}

public boolean validateLogin(String user, String passwd) { String inputLine;

boolean flag=true;

byte[] hashFromFile = new byte[20]; ParsePasswdLine pwl = new ParsePasswdLine(); try {

BufferedReader passwdFileLines = new BufferedReader(

new FileReader(“/etc/passwd”));

while ((inputLine = passwdFileLines.readLine()) != null) {

pwl.parse(inputLine);

if ( (pwl.userName).equals(user) ) {

hashFromFile = pwl.passwdHash;

byte[] testHash = com.dalsemi.system.Security

.hashMessage((user + “:” + passwd).getBytes());

for (int i=0; i<20;i++) {

if (testHash[i]!=hashFromFile[i]) {

return false;

}

}

return true;

}

}

}

catch (Exception e) { System.out.println(e); return false;

}

return false;

}

public static void main(String[] args) { Modem external = new Modem(); external.openSerialPort(“serial0”); serialPort = external.serialPort;

PPPServerWA ourListener = new PPPServerWA();

ppp = new PPP();

byte[] localAddress = new byte[] {(byte)192,(byte)168,(byte)10,(byte)9}; byte[] remoteAddress = new byte[]{(byte)192,(byte)168,(byte)10,(byte)12}; try {

ppp.close(); ppp.addEventListener(ourListener); ppp.setLocalAddress(localAddress); ppp.setRemoteAddress(remoteAddress); ppp.setACCM(0×00000000); ppp.setAuthenticate(true); ppp.setDefaultInterface(true); ppp.setPassive(true);

} catch(Exception e) { System.out.println(e);

System.out.println(“The ppp methods failed”);

serialPort.close(); System.exit(0);

}

if (external.answer()) {

ppp.open();

} else {

System.out.println(“The answer has failed!”);

serialPort.close(); System.exit(0);

}

while(true) {

//run forever…

}

}

}

The first change we see is in the AUTHENTICATION_REQUEST case. We use the getPeerID() and the getPeerPassword() methods to grab the username and password entered by the client requesting a PPP connection. Then we pass those to a method called validateLogin(). If that method returns true, we use the authenticate(true) method to move us into the UP state. Else, we use authenticate(false) to move to the STOPPED state.

case PPPEvent.AUTHENTICATION_REQUEST:

System.out.println(“PPP sent the AUTHENTICATION_REQUEST event!”); String userName = ppp.getPeerID();

String password = ppp.getPeerPassword();

if (validateLogin(userName, password)) {

ppp.authenticate(true);

System.out.println(“Login Validation has succeeded”);

} else {

ppp.authenticate(false);

System.out.println(“Login Validation has failed”);

}

break;

The validateLogin() method takes the username/password and compares it to what is found in the TINI password file. We make use of a utility class, ParsePasswordLine, which is stored in a separate file in the same directory. The ParsePasswordLine class has two member variables, the user name and the 20 bit hash associated with that user name. We read in the contents of the password file, line by line, and as we do, we parse the line and separate out the username and 20 bit hash (via the ParsePasswordLine class). If the client’s user name matches a name in the file, we create a string consisting of the username, a colon, and the password the client entered. We compute the SHA-1 hash of that string. We compare that hash, with the hash retrieved from the password file, byte for byte. If they match, the client gets logged.

public boolean validateLogin(String user, String passwd) { String inputLine;

boolean flag=true;

byte[] hashFromFile = new byte[20]; ParsePasswdLine pwl = new ParsePasswdLine(); try {

BufferedReader passwdFileLines = new BufferedReader(

new FileReader(“/etc/passwd”));

while ((inputLine = passwdFileLines.readLine()) != null) {

pwl.parse(inputLine);

if ( (pwl.userName).equals(user) ) {

hashFromFile = pwl.passwdHash;

byte[] testHash = com.dalsemi.system.Security

.hashMessage((user + “:” + passwd).getBytes());

for (int i=0; i<20;i++) {

if (testHash[i]!=hashFromFile[i]) {

return false;

}

}

return true;

}

}

}

catch (Exception e) { System.out.println(e); return false;

}

return false;

}

The ParsePasswordLine class has one method, parse(), which takes a string and grabs the first two colon separated fields. The second field is treated as hex bytes, and put into a byte array.

import java.io.*;

import com.dalsemi.system.*;

public class ParsePasswdLine   { String userName;

byte[] passwdHash = new byte[20];

public void parse(String passwdLine) {

int firstField = passwdLine.indexOf(‘:’, 0);

int secondField = passwdLine.indexOf(‘:’, firstField+1);

userName = passwdLine.substring(0, firstField);

String passwdHashStr = passwdLine.substring(firstField+1, secondField);

int n=0;

int i=0;

String str = “”;

while (n<39) {

str = passwdHashStr.substring(n,n+2); passwdHash[i] = (byte)Short.parseShort(str, 16); i++;

n=n+2;

}

}

}

Like the previous example, use a TINI connected to a PC via Ethernet. Connect the TINI to a modem (a cell phone in our case) via the specially made crossover cable and the cell phone’s data connectivity cable. To compile the program, create a separate folder and place PPPserverWA.java in it, as well as Modem.java, and ParsePasswordLine.java. Make a bin folder in the same directory. Then type the following:

C:\> cd src

C:\> javac -bootclasspath %TINI_HOME%\bin\tiniclasses.jar

-d ..\bin PPPServerWA.java

C:\> cd ..

C:\> java -classpath %TINI_HOME%\bin\tini.jar;. BuildDependency

-p %TINI_HOME%\bin\owapi_dependencies_TINI.jar

-f bin

-x %TINI_HOME%\bin\owapi_dep.txt

-o bin\PPPServerWA.tini

-d %TINI_HOME%\bin\tini.db

As we’ve done in previous examples, some of the command line arguments for the java command have been shown on a separate line. Everything after java should be entered on the same line. Transfer the .tini file to your TINI stick via FTP, and via telnet attempt the following as the root user:

TINI /> downserver -s

Warning:  This will disconnect users on specified servers.

OK to proceed? (Y/N): y

[ Wed Feb 13 08:52:58 GMT 2002 ]   Message from System: Serial server stopped.

TINI /> java PPPServerWA.tini

Sending: AT Receiving:

AT OK

Wait for 3 rings

RING RING RING

Sending: ATA Receiving: ATA

Wait for CONNECT CONNECT

PPP sent the STARTING event!

PPP sent the AUTHENTICATION_REQUEST event! Login Validation has succeeded

PPP sent the UP event!

Then, log into the same TINI via Telnet either right on top of the current process, or in a different window. Run ipconfig –x:

TINI /> ipconfig -x Interface 0 is active. Name       : eth0

Type         : Ethernet

IP Address   : 192.168.0.5

Subnet Mask  : 255.255.255.0

Gateway      : 0.0.0.0

Interface 1 is active. Name      : lo

Type         : Local Loopback

IP Address   : 127.0.0.1

Subnet Mask  : 255.0.0.0

Gateway      : 0.0.0.0

Interface 2 is active.

Name         : ppp0 (default)

Type          : Point-to-Point Protocol

IP Address   : 192.168.10.9

Subnet Mask  : 255.255.255.0

Gateway      : 0.0.0.0

Interface 3 is not active.

Success!  As in the previous example, we now have a PPP connection between the TINI stick and a PC, with the stick acting as a server. This time, the PPP process checked to see if we entered a valid user name and password when dialing in form the PC. If this didn’t work for you, refer to comments at the end of the previous example.

Random Posts

Comments are closed.