diff options
Diffstat (limited to 'doc/wiki/AuthDatabase.Lua.txt')
-rw-r--r-- | doc/wiki/AuthDatabase.Lua.txt | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/doc/wiki/AuthDatabase.Lua.txt b/doc/wiki/AuthDatabase.Lua.txt new file mode 100644 index 0000000..41caf61 --- /dev/null +++ b/doc/wiki/AuthDatabase.Lua.txt @@ -0,0 +1,293 @@ +Lua based authentication +======================== + +Since v2.3.0 you can implement passdb and userdb using Lua +[https://www.lua.org/] script. + +Contents + + + 1. Lua based authentication + + 1. Known bugs + + 2. Lua interface + + 3. Auth request methods + + 4. Password database + + 5. User database + + 6. Examples + +Known bugs +---------- + + * Before 2.3.4 when returning a table with values, the table values are + mistakenly converted into a number if they seem like a number. So if you are + using values like '012345', this would get converted into '12345' + * Before 2.3.4 returning password without scheme would cause a crash. + +Lua interface +------------- + +For details about Dovecot Lua, see <Design.Lua.txt>. + +When used in authentication, additional module *dovecot.auth* is added, which +contains constants for passdb and userdb. + +List of constants +----------------- + + * dovecot.auth.PASSDB_RESULT_INTERNAL_FAILURE + * dovecot.auth.PASSDB_RESULT_SCHEME_NOT_AVAILABLE - indicates password scheme + that cannot be understood + * dovecot.auth.PASSDB_RESULT_USER_UNKNOWN + * dovecot.auth.PASSDB_RESULT_USER_DISABLED + * dovecot.auth.PASSDB_RESULT_PASS_EXPIRED + * dovecot.auth.PASSDB_RESULT_NEXT - indicates that this passdb did not + authenticate user, next passdb should do it + * dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH + * dovecot.auth.PASSDB_RESULT_OK + * dovecot.auth.USERDB_RESULT_INTERNAL_FAILURE + * dovecot.auth.USERDB_RESULT_USER_UNKNOWN + * dovecot.auth.USERDB_RESULT_OK + +Also, it registers object *struct auth_request** which lets access various +parts of the auth request. You should use the loggers associated with +auth_request when possible. + +Auth request methods +-------------------- + +Functions: + + * auth_request#log_debug(text) - logs debug message (if debug is enabled, noop + otherwise) + * auth_request#log_error(text) - logs error message + * auth_request#log_info(text) - logs informational message + * auth_request#log_warning(text) - logs warning message + * auth_request#response_from_template(template) - takes in key=value template + and expands it using var_expand and produces table suitable for passdb + result + * auth_request#var_expand(template) - performs var expansion on the template + using <Variables.txt> + * auth_request#password_verify(crypted_password, plain_password) - checks if + the plain password matches the crypted or hashed password + * auth_request#event() - Returns child event for the auth request, can be used + for logging and other events. Comes with a prefix. (Since v2.3.6+) + +Subtables: + + * auth_request#passdb + * auth_request#userdb + +Members: + +See <Variables.txt> for details + + * auth_request#auth_domain + * auth_request#auth_user + * auth_request#auth_username + * auth_request#cert + * auth_request#client_id + * auth_request#domain + * auth_request#domain_first + * auth_request#domain_last + * auth_request#home + * auth_request#lip + * auth_request#local_name + * auth_request#login_domain + * auth_request#login_user + * auth_request#login_username + * auth_request#lport + * auth_request#master_user + * auth_request#mech + * auth_request#orig_domain + * auth_request#orig_user + * auth_request#orig_username + * auth_request#password + * auth_request#pid + * auth_request#real_lip + * auth_request#real_lport + * auth_request#real_rip + * auth_request#real_rport + * auth_request#rip + * auth_request#rport + * auth_request#secured + * auth_request#service + * auth_request#session + * auth_request#session_pid + * auth_request#user + * auth_request#username + +Additionally you can access + + * skip_password_check - Set if the password has already been validated by + another passdb + * passdbs_seen_user_unknown - If some previous passdb has not found this user + * passdbs_seen_internal_failure - If some previous passdb has had internal + failure + * userdbs_seen_internal_failure - If some previous userdb has had internal + failure + +Password database +----------------- + +Lua passdb supports two modes of function. It can behave as lookup database, or +password verification database. + +Lookup function signature is *auth_passdb_lookup(request)* and the password +verification signature is *auth_password_verify(request, password)* + +Both functions must return a tuple, which contains a return code, and also +additionally string or table. Table must be in key-value format, it will be +imported into auth request. The string must be in key=value format, except if +return code indicates internal error, the second parameter can be used as error +string. + +If *auth_verify_password* is found, it's always used. + +To configure passdb in dovecot, use + +---%<------------------------------------------------------------------------- +passdb { + driver = lua + args = file=/path/to/lua blocking=yes # default is yes +} +---%<------------------------------------------------------------------------- + +By default, dovecot runs Lua scripts in auth-worker processes. If you do not +want this, you can disable blocking, and Lua script will be ran in auth +process. This can degrade performance if your script is slow or makes external +lookups. + +User database +------------- + +Lua userdb supports both single user lookup and iteration. Note that iteration +will hold the whole user database in memory during iteration. + +User lookup function signature is *auth_userdb_lookup(request)*. The function +must return a tuple, which contains a return code, and also additionally string +or table. Table must be in key-value format, it will be imported into auth +request. The string must be in key=value format, except if return code +indicates internal error, the second parameter can be used as error string. + +User iteration function signature is *auth_userdb_iterate*, which is expected +to return table of usernames. Key names are ignored. + +To configure userdb in dovecot, use + +---%<------------------------------------------------------------------------- +userdb { + driver = lua + args = file=/path/to/lua blocking=yes # default is yes +} +---%<------------------------------------------------------------------------- + +Examples +-------- + +Skeleton +-------- + +---%<------------------------------------------------------------------------- +function auth_passdb_lookup(req) + if req.user == "testuser1" then + return dovecot.auth.PASSDB_RESULT_OK, "password=pass" + end + return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "no such user" +end + +function auth_userdb_lookup(req) + if req.user == "testuser1" then + return dovecot.auth.USERDB_RESULT_OK, "uid=vmail gid=vmail" + end + return dovecot.auth.USERDB_RESULT_USER_UNKNOWN, "no such user" +end + +function script_init() + return 0 +end + +function script_deinit() +end + +function auth_userdb_iterate() + return {"testuser1"} +end +---%<------------------------------------------------------------------------- + +Simple username password database (such as opensmtpd) +----------------------------------------------------- + +The example uses whitespace separated username and password. As a special +caution, the way Lua is used here means you can have multiple user password per +line, instead of just one.This can be extended to more complicated separators +or multiple fields per user. + +If you only want to autenticate users, and don't care about user listing, you +can use + +---%<------------------------------------------------------------------------- +function auth_passdb_lookup(req) + for line in io.lines("/path/to/file") do + for user, pass in string.gmatch(line, "(%w+)%s(.+)") do + if (user == req.username) then + -- you can add additional information here, like userdb_uid + return dovecot.auth.PASSDB_RESULT_OK, "password=" .. pass + end + end + end + return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "" +end +---%<------------------------------------------------------------------------- + +If you also want to be able to list users, so that you could use doveadm cmd -A + +---%<------------------------------------------------------------------------- +local database = "/path/to/file" + +function db_lookup(username) + for line in io.lines(database) do + for user, pass in string.gmatch(line, "(%w+)%s(.+)") do + if (user == username) then + return {result=0, password=pass} + end + end + end + return {result=-1} +end + +function auth_passdb_lookup(req) + res = db_lookup(req.username) + if res.result == 0 then + -- you can add additional information here for passdb + return dovecot.auth.PASSDB_RESULT_OK, "password=" .. res.password + end + return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "" +end + +function auth_userdb_lookup(req) + res = db_lookup(req.username) + if res.result == 0 then + -- you can add additional information here for userdb, like uid or home + return dovecot.auth.USERDB_RESULT_OK, "uid=vmail gid=vmail" + end + return dovecot.auth.USERDB_RESULT_USER_UNKNOWN, "" +end + +function auth_userdb_iterate() + users = {} + for line in io.lines(database) do + for user in string.gmatch(line, "(%w+)%s.+") do + table.insert(users, user) + end + end + return users +end +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) |