[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Google
  Web www.spinics.net

Re: [GNU Crypto] exception on multiple SaslConnection.send() calls



>From my testing, I believe the fix for this problem is to remove the
call to reset() in gnu.crypto.assembly.Assembly.lastUpdate(byte[], int,
int), to push the wrap operation through the Assembly, flushing internal
buffers so the message is completely wrapped, without resetting the
Assembly, so additional messages can be pushed through subsequently.

When the call to reset() is removed, I can make multiple
SaslClient.wrap() calls using the same SASL context (as it should be).
I used the attached program for testing.

Could this fix be included in the next gnu-crypto release?

import gnu.crypto.Registry;
import gnu.crypto.sasl.ClientFactory;
import gnu.crypto.sasl.ServerFactory;
import gnu.crypto.sasl.srp.PasswordFile;
import gnu.crypto.sasl.srp.SRPRegistry;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Random;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslServer;

public class SaslTest {
    private static String username = "test";
    private static String password = "test";
    private static String pFile = "./test";

    public static void main(String[] args) throws Exception {
	String mechanisms[] = { "SRP" };

	createPasswordFile();

	HashMap clientprops = new HashMap();
	clientprops.put(Registry.SASL_AUTHORISATION_ID, username);
	clientprops.put(Registry.SASL_USERNAME, username);
	clientprops.put(Registry.SASL_PASSWORD, password);
	clientprops.put(SRPRegistry.SRP_REPLAY_DETECTION, "true");
	clientprops.put(SRPRegistry.SRP_INTEGRITY_PROTECTION, "true");
	clientprops.put(SRPRegistry.SRP_CONFIDENTIALITY, "true");
	ClientFactory cf = new ClientFactory();
	SaslClient sc = cf.createSaslClient(mechanisms,
					    "test",
					    "http",
					    "localhost",
					    clientprops,
					    null);
	if (sc == null) {
	    System.err.println("createSaslClient failed.");
	    System.exit(1);
	}

	HashMap serverprops = new HashMap();
	serverprops.put(SRPRegistry.SRP_REPLAY_DETECTION, "true");
	serverprops.put(SRPRegistry.SRP_INTEGRITY_PROTECTION, "true");
	serverprops.put(SRPRegistry.SRP_CONFIDENTIALITY, "true");
	serverprops.put(SRPRegistry.PASSWORD_FILE, pFile);
	ServerFactory sf = new ServerFactory();
	SaslServer ss = sf.createSaslServer(mechanisms[0],
					    "http",
					    "localhost",
					    serverprops,
					    null);
	if (ss == null) {
	    System.err.println("createSaslServer failed.");
	    System.exit(1);
	}

	byte[] response = sc.hasInitialResponse() ?
	    sc.evaluateChallenge(new byte[0]) : new byte[0];

	while (!ss.isComplete()) {
	    byte[] challenge = ss.evaluateResponse(response);

	    if (!sc.isComplete()) {
		response = sc.evaluateChallenge(challenge);
	    }
	}

	int i = 100;
	byte[] send = "hello, world".getBytes();
	while (i-- > 0) {
	    byte[] recv, wrap;
	    wrap = sc.wrap(send, 0, send.length);
	    recv = ss.unwrap(wrap, 0, wrap.length);
	    System.out.println("Sent "+(new String().valueOf(send.length))+" bytes: "+(new String(send)));
	    System.out.println("Wrap "+(new String().valueOf(wrap.length))+" bytes");
	    System.out.println("Received "+(new String().valueOf(recv.length))+"bytes: "+(new String(recv)));
	    if (!Arrays.equals(send, recv)) {
		System.err.println("transmission failure.");
		System.exit(1);
	    }
	    wrap = ss.wrap(send, 0, send.length);
	    recv = sc.unwrap(wrap, 0, wrap.length);
	    System.out.println("Sent "+(new String().valueOf(send.length))+" bytes: "+(new String(send)));
	    System.out.println("Wrap "+(new String().valueOf(wrap.length))+" bytes");
	    System.out.println("Received "+(new String().valueOf(recv.length))+"bytes: "+(new String(recv)));
	    if (!Arrays.equals(send, recv)) {
		System.err.println("transmission failure.");
		System.exit(1);
	    }
	}
	System.out.println("done");
    }

    private static void createPasswordFile() throws Exception {
	File f = new File(pFile);
	if (!f.exists()) {
	    if (f.createNewFile()) {
		f.deleteOnExit();
	    }
	} else if (!f.isFile()) {
	    throw new RuntimeException("File object ("+pFile+") exists but is not a file");
	} else if (!f.canRead() || !f.canWrite()) {
	    throw new RuntimeException("File ("+pFile+") exists but is not accessible");
	}
	f = null;

	PasswordFile tpasswd = new PasswordFile(pFile);
	if (!tpasswd.contains(username)) {
	    byte[] testSalt = new byte[10];
	    new Random().nextBytes(testSalt);
	    tpasswd.add(username, password, testSalt, "1");
	} else {
	    tpasswd.changePasswd(username, password);
	}
	tpasswd.savePasswd();
	tpasswd = null;
    }
}
Bryan Hoover <bhoover@xxxxxxxx> wrote:
> Jim Basney wrote:
> 
> > Bryan Hoover <bhoover@xxxxxxxx> wrote:
> > > Jim Basney wrote:
> > >
> > > > Bryan Hoover <bhoover@xxxxxxxx> wrote:
> > > > > Jim Basney wrote:
> > > > > > Am I doing something wrong?
> > > > >
> > > > > Don't comment the reconnect call :).  If possible, the existing connection will be reused,
> > > > > so "reconnect" is in a sense, a bit of a misnomer.
> > > >
> > > > Hmmm.  SaslConnection.reconnect() calls disconnect() then connect(),
> > > > which creates a new Socket().  Watching the network with ngrep, I see a
> > > > new TCP socket connection after the SaslConnection.reconnect() call.
> > >
> > > Well, statelessness protocals, and all that you know.
> > >
> > > But the security session -- that's the time consuming thing you want to reuse if possible, and
> > > that what the lib does, unless, for instance, it's been to long, and session timed out.  Then
> > > you have to renogotiate the security layer -- basically start all over like a first time
> > > connection.
> >
> > You're saying that I can only call SaslClient.wrap() once, after which I
> > have to go through the SaslClient.evaluateChallenge() loop again?
> 
> I don't know.
> 
> My experience with the routines, and the protocol really, is limited. I helped in making passwords
> immutible, and have used the routines for stateless authentication -- connect, and subsequent
> connection with a new socket, with the subsequent connection(s) resulting in security session reuse.
> 
> BTW, if you go back through evaluateChallenge, the call should not result in renegotiation, but
> rather, reuse of the preexisting security context.
> 
> Assuming you haven't already done it, you might want to google on 'sasl srp protocol', and read up
> on the ins, and outs of that.
> 
> Bryan
> 
> > -Jim
_______________________________________________
gnu-crypto-discuss mailing list
gnu-crypto-discuss@xxxxxxx
http://lists.gnu.org/mailman/listinfo/gnu-crypto-discuss

[Home]     [Gnu Classpath]     [Linux Kernel]     [Linux Cryptography]     [Fedora]     [Fedora Directory]     [Red Hat Development]     [Red Hat 9 Bible]     [Fedora Bible]     [Red Hat 9]     [Network Security Reading]

RSS
Powered by Linux