Open DavidRobb opened 3 years ago
Hi, I apologize for the delay.
Can you share a compilable code pinpointing your problem?
When I recycle the ZAuthTest#testCurveSuccessful, by binding a REQ and connecting a REP, it works.
public void testBindREQConnectREP() throws IOException
{
try (ZContext ctx = new ZContext();
ZAuth auth = new ZAuth(ctx, new ZCertStore.Hasher());
ZMQ.Socket server = ctx.createSocket(SocketType.REQ);
ZMQ.Socket client = ctx.createSocket(SocketType.REP)) {
// Start an authentication engine for this context. This engine
// allows or denies incoming connections (talking to the libzmq
// core over a protocol called ZAP).
// Get some indication of what the authenticator is deciding
auth.setVerbose(VERBOSE_MODE);
// auth send the replies
auth.replies(true);
// Tell authenticator to use the certificate store in .curve
auth.configureCurve(certificateFolder);
// We'll generate a new client certificate and save the public part
// in the certificate store (in practice this would be done by hand
// or some out-of-band process).
ZCert clientCert = new ZCert();
clientCert.setMeta("name", "Client test certificate");
clientCert.setMeta("meta1/meta2/meta3", "Third level of meta");
// wait a second before overwriting a cert, otherwise the certstore won't see that the file actually changed and will deny
// if creating new files, this is not needed
// ZMQ.sleep(1);
clientCert.savePublic(certificateFolder + "/testcert.pub");
ZCert serverCert = new ZCert();
// Create and bind server socket
server.setZapDomain("global".getBytes());
server.setCurveServer(true);
server.setCurvePublicKey(serverCert.getPublicKey());
server.setCurveSecretKey(serverCert.getSecretKey());
boolean rc = server.bind("tcp://localhost:*");
assertThat(rc, is(true));
// Create and connect client socket
client.setCurvePublicKey(clientCert.getPublicKey());
client.setCurveSecretKey(clientCert.getSecretKey());
client.setCurveServerKey(serverCert.getPublicKey());
rc = client.connect(server.getLastEndpoint());
assertThat(rc, is(true));
// By default PUSH sockets block if there's no peer
rc = server.setSendTimeOut(200);
assertThat(rc, is(true));
// Send a single message from server to client
server.send("Hello");
ZAuth.ZapReply reply = auth.nextReply(true);
assertThat(reply.statusCode, is(200));
assertThat(reply.userId, is(clientCert.getPublicKeyAsZ85()));
String message = client.recvStr();
assertThat(message, is("Hello"));
}
}
Hi, Thanks for looking into this. Maybe you can see if I have done anything stupid:
I have the keys hard coded into the source but also present in the Appdata .curve directory. Doesn't appear to be a directory problem as ZAuth reports allowed:
> Task :run
ZAuth: Enabled replies
ZAuth: Using C:\Users\David\AppData\Roaming\ZMQTest\.curve as certificates directory
Bind...
Send Hello...
Recv world...
ZAuth: Allowed (CURVE) client_key=2c*Um{$$YK7Tbd2)W5nq/{o=bXLM6DkS=!H0/%C=
ZAuth: Allowed (CURVE) client_key=2c*Um{$$YK7Tbd2)W5nq/{o=bXLM6DkS=!H0/%C=
But Server does not report 'Done' unless I set CURVE_ALLOW_ANY
Server Main is
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package ReqServer;
import java.io.IOException;
import org.zeromq.SocketType;
import org.zeromq.ZAuth;
import org.zeromq.ZCertStore;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
/**
*
* @author David
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
String server_secret = "?y$]][$s+e:GHh#z!CN9ZJKvu)4sZw.y^>tDRLwD";
String client_secret = "Rg1UHpL(qiw<lh7b{(Im-{1v9w#3m){mM]+hNXYA";
String client_public = "2c*Um{$$YK7Tbd2)W5nq/{o=bXLM6DkS=!H0/%C=";
String server_public = "0pITW):T^ip-7ZT+*9ZqL6mY42IF.}wUSKC%nH5R";
var ctx = new ZContext(1);
ZAuth auth = new ZAuth(ctx, new ZCertStore.Hasher());
auth.setVerbose(true);
auth.replies(true);
// auth.configureCurve(ZAuth.CURVE_ALLOW_ANY);
auth.configureCurve("C:\\Users\\David\\AppData\\Roaming\\ZMQTest\\.curve");
ZMQ.Socket reqSocket = ctx.createSocket(SocketType.REQ);
reqSocket.setLinger(0);
reqSocket.setZapDomain("global".getBytes());
reqSocket.setCurveSecretKey(ZMQ.Curve.z85Decode(server_secret));
reqSocket.setCurveServer(true);
System.out.println("Bind...");
reqSocket.bind("tcp://*:5432");
System.out.println("Send Hello...");
reqSocket.send("HELLO");
System.out.println("Recv world...");
byte[] ba = reqSocket.recv(); // Curve server hangs here
System.out.println("Done...");
}
}
Client main is
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package RepClient;
import java.io.IOException;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
/**
*
* @author David
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException, InterruptedException {
String client_secret = "Rg1UHpL(qiw<lh7b{(Im-{1v9w#3m){mM]+hNXYA";
String client_public = "2c*Um{$$YK7Tbd2)W5nq/{o=bXLM6DkS=!H0/%C=";
String server_public = "0pITW):T^ip-7ZT+*9ZqL6mY42IF.}wUSKC%nH5R";
var context = new ZContext(1);
ZMQ.Socket repSocket = context.createSocket(SocketType.REP);
repSocket.setCurveServerKey(ZMQ.Curve.z85Decode(server_public));
repSocket.setCurvePublicKey(ZMQ.Curve.z85Decode(client_public));
repSocket.setCurveSecretKey(ZMQ.Curve.z85Decode(client_secret));
System.out.println("Connect...");
repSocket.connect("tcp://localhost:5432");
System.out.println("Recv...");
byte[] ba = repSocket.recv();
System.out.println("Send World...");
repSocket.send("WORLD");
System.out.println("Done...");
Thread.sleep(5000);
}
}
Zipped gradle project files are:
I'm trying to use ZAuth to authorise a request reply socket pair where the curveServer is on the REQ socket that 'binds' and waits for the REP socket to connect.
It half works in that the REP socket is authorised and receives a request, then sends a reply. However, the REQ socket never sees this reply.
Setup
REQ CurveServer Config
REP CurveClient Config
Even with client2Sec key correctly set in my key store location, the CurveServer hangs waiting at the line indicated. Rep Client appears to go through the motions of receiving the message and sending the reply.
However, if I have auth configured as ALLOW_ANY it works fine.
Is there something a bit odd about this setup? Usually the CurveServer would be the 'Server' and reply to Client requests with a REP socket. But for this dynamically setup connection I want the CurveClient to be the 'Server' and respond to CurveServer requests.
If I swap the REP and REQ socket types over and send the initial Request from the CurveClient then it also works fine. Hence, I think I have my keys and ZAuth all configured correctly.