Monthly Archives: March 2021

Dovecot with vpopmail and lua authentication

I'm running the Dovecot imap server with users and mailboxes managed by vpopmail and for various reasons I want to gradually move away from vpopmail but without losing the maildir++ storage structure for messages.

The first issue is that vpopmail authentication in dovecot is not compiled in by default on the Debian packages so every time I upgrade I have to recompile the packages to support the vpopmail driver.

This post explains how to use the lua authentication with the vpopmail vpasswd files so we continue to use the same users and passwords without relying on the special dovecot vpopmail driver. If assumes your vpopmail installation is in /home/vpopmail , if it's somewhere else just change the location in the auth.lua file.

Disable the vpopmail authentication module in conf.d/10-auth.conf

Add /etc/dovecot/conf.d/auth-lua.conf.ext with this content:

passdb {
 driver = lua
 args = file=/etc/dovecot/auth.lua blocking=yes # default is yes
}
userdb {
 driver = lua
 args = file=/etc/dovecot/auth.lua blocking=yes # default is yes
}

Create /etc/dovecot/auth.lua with the following content:

local function isempty(s)
  return s == nil or s == ''
end

function auth_password_verify(req, pass)
 local str=req.user
 local lastAt = str:find("[^%@]+$")
 local localPart = str:sub(1, (lastAt - 2)) 
 local domainPart = str:sub(lastAt, #str)
 local file = "/home/vpopmail/domains/"..domainPart.."/vpasswd"

 for line in io.lines(file) do
  local u,epass=string.match(line,"([^%:]+):([^%:]+)");
  if not isempty(epass) and localPart==u and req:password_verify("{MD5-CRYPT}"..epass,pass)>0 then
   return dovecot.auth.PASSDB_RESULT_OK, {}
  end
 end
end

function auth_userdb_lookup(req)
 local str=req.user
 local lastAt = str:find("[^%@]+$")
 local localPart = str:sub(1, (lastAt - 2)) 
 local domainPart = str:sub(lastAt, #str)
 local file = "/home/vpopmail/domains/"..domainPart.."/vpasswd"
 for line in io.lines(file) do
  local u,epass=string.match(line,"([^%:]+):([^%:]*):");
  if localPart==u then
   return dovecot.auth.USERDB_RESULT_OK, "uid=vpopmail gid=vchkpw"
  end
 end
 return dovecot.auth.USERDB_RESULT_USER_UNKNOWN, "no such user"
end