Re: [Dovecot] calling dovecot exported auth from Java

2011-04-30 Thread WJCarpenter

On 4/15/2011 5:36 PM, WJCarpenter wrote:
As far as I have been able to figure out, dovecot auth always works 
over a Unix domain socket.  I believe it is not currently possible to 
operate dovecot auth over an Internet domain (TCP) socket.  Am I correct?


I want to call dovecot's exported authentication from a Java 
application.  Java doesn't natively know how to talk to a Unix domain 
socket, so there are inconveniences.  There are 3rd party JNI 
libraries to allow Java to do it, but I'm not too wild about the idea 
of using JNI.  My current thinking is to rig up some kind of 
proxy/shuttle arrangement between a localhost TCP port and the dovecot 
auth Unix domain socket in the filesystem.  I'm looking at using the 
more or less standard tool "socat" to do that.  (I'm on a mainstream 
Linux distribution.)


Here is the solution we came up with.  All of this is, uh, lightly 
tested at this point.  Bug reports welcome (directly or via this mailing 
list if you want.)


First, the "socat" command to connect a localhost TCP socket to the Unix 
domain socket.  This is suitable for somehow running just once since it 
makes its own children for handling each connection instance.


/usr/bin/socat -ly \
  TCP4-LISTEN:1649,bind=localhost,reuseaddr,fork \
  UNIX-CONNECT:/var/run/dovecot/auth-client

We chose port 1649 because it's allocated to the ancient kermit 
protocol, and we're confident we'll never use that here.


Here is the Java class that we use for speaking to the dovecot auth 
process.  It's basically a rework of the C++ code in the exim sources.  
Because we have a Tomcat environment for this, we used a Catalina 
utility for base64 encoding.  If you don't have that, you'll have to 
find one elsewhere (there is no standard base64 encoder thing in Java; 
grrr).  There are some things in here that I don't completely 
understand, but they are in the exim code and (apparently) do no harm.  
You can instantiate one of these objects and then call the doLogin() 
method arbitrarily many times.  As noted, the class is not threadsafe.



package aio.util;
import java.io.*;
import java.net.Socket;

import org.apache.catalina.util.Base64;

/**
 * This class is not threadsafe.
 */
public class DovecotLogin
{
private boolean TRACE = true;
private String host;
private int port;
private String service;
private LineNumberReader lineReader;
private OutputStream outputStream;

public DovecotLogin()
{
this(null, 0, null);
}

public DovecotLogin(String host, int port, String service)
{
this.host = host != null ? host : "localhost";
this.port = port > 0 ? port : 1649;
this.service = service != null ? service : "aiologin";
if (TRACE)
{
System.out.println("CONNECT " + this.host + ":" + this.port 
+ ", service=" + this.service);

}
initDovecotConnection();
}

private void initDovecotConnection()
{
try
{
socket = new Socket(host, port);
int localport = socket.getLocalPort();
InputStream inputStream = socket.getInputStream();
lineReader = new LineNumberReader(new 
InputStreamReader(inputStream, "utf-8"));

outputStream = socket.getOutputStream();
initialDovecotListenTo();
initialDovecotSpeakTo(localport);
}
catch (Exception e)
{
// TODO logme
e.printStackTrace();
}
}

public void close()
{
if (socket != null &&  socket.isConnected())
{
try
{
socket.close();
socket = null;
}
catch (IOException e)
{
// TODO logme
e.printStackTrace();
}
}
}

public boolean doLogin(String userid, String password)
{
try
{
sayThisLogin(userid, password);
return readLoginResponse();
}
catch (Exception e)
{
// TODO logme
e.printStackTrace();
return false;
}
}

private boolean readLoginResponse() throws IOException
{
String line = lineReader.readLine();
if (TRACE)
{
System.out.println("S< " + line);
}
String[] splits = line.split("\t");
String token1 = splits[0];
if ("FAIL".equalsIgnoreCase(token1))
{
return false;
}
if ("OK".equalsIgnoreCase(token1))
{
return true;
}
throw new IOException("unexpected response received from 
dovecot auth: " + line);

}

private void initialDovecotListenTo() throws IOException
{
boolean done = false;
while (!done)
{
String line = lineReader.readLine();
if (TRACE)
{
System.out.println("S< " + line);
}
 

Re: [Dovecot] calling dovecot exported auth from Java

2011-04-20 Thread Timo Sirainen
On Fri, 2011-04-15 at 17:36 -0700, WJCarpenter wrote:
> As far as I have been able to figure out, dovecot auth always works over 
> a Unix domain socket.  I believe it is not currently possible to operate 
> dovecot auth over an Internet domain (TCP) socket.  Am I correct?

v2.0 supports TCP auth sockets.




Re: [Dovecot] calling dovecot exported auth from Java

2011-04-16 Thread WJCarpenter

On 4/15/2011 5:36 PM, WJCarpenter wrote:
I want to call dovecot's exported authentication from a Java 
application.  Java doesn't natively know how to talk to a Unix domain 
socket, so there are inconveniences.  There are 3rd party JNI 
libraries to allow Java to do it, but I'm not too wild about the idea 
of using JNI.  My current thinking is to rig up some kind of 
proxy/shuttle arrangement between a localhost TCP port and the dovecot 
auth Unix domain socket in the filesystem.  I'm looking at using the 
more or less standard tool "socat" to do that.  ('m on a mainstream 
Linux distribution.)


BTW, one workaround I thought of this situation was to connect to the 
POP3 port and do a normal POP3 login there.  That would be pretty easy, 
but it doesn't happen to work out for me.  My SQL-based login config 
factors in the service name provided by dovecot, and some of the Java 
app users might not be authorized for POP3 and/or IMAP4.  If I could 
figure out a way to run a second POP3 daemon with a different service 
name, that would probably work for me (but I don't see a way to do it 
... at least with dovecot 1.1.11 ... some some later dovecot version 
allow that?)