-- Limristem eMail Dovecot 2.4 passdb (replaces removed checkpassword driver). -- Verifies primary mailbox password and active app passwords via the Python helper. -- -- Helper path is injected at install time (__AUTH_VERIFY_HELPER__). local VERIFY_HELPER = "__AUTH_VERIFY_HELPER__" function script_init() return 0 end function script_deinit() end function auth_password_verify(req, password) if type(password) ~= "string" or password == "" then return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "" end local user = req.user if type(user) ~= "string" or user == "" then return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "" end -- Username on argv only (safe); password exclusively on stdin (not visible in ps). local cmd = string.format("%s %s", shell_quote(VERIFY_HELPER), shell_quote(user)) local pipe, err = io.popen(cmd, "w") if not pipe then req:log_error("auth-verify open failed: " .. tostring(err)) return dovecot.auth.PASSDB_RESULT_INTERNAL_FAILURE, "auth helper unavailable" end local ok_write = pipe:write(password) -- Ensure trailing newline is not required; helper reads raw stdin. if not ok_write then pipe:close() req:log_error("auth-verify write failed for user " .. user) return dovecot.auth.PASSDB_RESULT_INTERNAL_FAILURE, "auth helper write failed" end local ok_close, reason, code = pipe:close() -- Lua 5.4: close returns true on success exit 0; else false, "exit", code if ok_close then return dovecot.auth.PASSDB_RESULT_OK, {} end if reason == "exit" and tonumber(code) == 1 then return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "" end if reason == "exit" and tonumber(code) == 111 then req:log_error("auth-verify temporary failure (exit 111) for " .. user) return dovecot.auth.PASSDB_RESULT_INTERNAL_FAILURE, "auth helper temporary failure" end req:log_error(string.format( "auth-verify unexpected status user=%s reason=%s code=%s", user, tostring(reason), tostring(code) )) return dovecot.auth.PASSDB_RESULT_INTERNAL_FAILURE, "auth helper failed" end function shell_quote(value) -- Single-quote for POSIX shells; escape embedded single quotes. return "'" .. string.gsub(value, "'", "'\\''") .. "'" end