Compare commits
10 commits
0ee755f4e9
...
a6add70310
| Author | SHA1 | Date | |
|---|---|---|---|
| a6add70310 | |||
| ecdc3bdc68 | |||
| 43673222df | |||
| 2bfddd1d57 | |||
| 8abe49672b | |||
| 070d49833c | |||
| d325b43c04 | |||
| df2b3f7638 | |||
| 4cd40ef8a6 | |||
| c1304add81 |
28 changed files with 389 additions and 67 deletions
15
apparmor.d/boilerplate
Normal file
15
apparmor.d/boilerplate
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
# This file is related to the `Baguette` project (authd, dnsmanagerd…).
|
||||||
|
# It is a way to avoid the long and complex default configuration files provided
|
||||||
|
# by the system. Allowed operations can be known in a matter of seconds.
|
||||||
|
|
||||||
|
# Accept basically all available libraries.
|
||||||
|
@{BASE_LIBS}=/{,usr/,usr/local/}lib{,32,64}/*.so* /usr/lib/x86_64*/*.so* /etc/ld*
|
||||||
|
|
||||||
|
# Enable reading files from different places required by the libraries I use,
|
||||||
|
# which may be the Crystal standard library itself.
|
||||||
|
@{BASE_RO}=/dev/{,u}random /dev/pts/* /proc/** /etc/localtime /usr/share/zoneinfo/**
|
||||||
|
@{BASE_RW}=/dev/{null,zero,full}
|
||||||
|
|
||||||
|
# Found in other profiles:
|
||||||
|
# Recent glibc uses /dev/full in preference to /dev/null for programs
|
||||||
|
# that don't have open fds at exec().
|
||||||
27
apparmor.d/dnsmanager
Normal file
27
apparmor.d/dnsmanager
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Main configuration directory.
|
||||||
|
@{MAIN_CONF_DIR}=@{HOME}/.config/baguette
|
||||||
|
|
||||||
|
# Main configuration files.
|
||||||
|
@{AUTHD_CONFIG}=@{MAIN_CONF_DIR}/auth.yml
|
||||||
|
@{DNSMANAGERD_CONFIG}=@{MAIN_CONF_DIR}/dnsmanager.yml
|
||||||
|
|
||||||
|
# Databases.
|
||||||
|
@{AUTHD_DB_PATH}=@{HOME}/tmp/db-authd
|
||||||
|
@{DNSMANAGERD_DB_PATH}=@{HOME}/tmp/db-dnsmanagerd
|
||||||
|
|
||||||
|
# Key to encrypt passwords.
|
||||||
|
@{AUTHD_DB_KEY}=@{MAIN_CONF_DIR}/authd-db-key
|
||||||
|
|
||||||
|
# DNS templates (read-only entries).
|
||||||
|
@{DNSMANAGERD_TEMPLATES}=@{MAIN_CONF_DIR}/templates/*.json
|
||||||
|
|
||||||
|
# Logs.
|
||||||
|
@{LOGS_DIR}=@{HOME}/tmp/logs
|
||||||
|
@{AUTHD_LOGS}=@{LOGS_DIR}/auth
|
||||||
|
@{DNSMANAGERD_LOGS}=@{LOGS_DIR}/dnsmanager
|
||||||
|
|
||||||
|
# Mailer for authd.
|
||||||
|
@{MAILER}=/{usr,usr/local}/bin/mailer
|
||||||
|
|
||||||
|
# IPC-related directory (see libipc(7)).
|
||||||
|
@{LIBIPC_DIR}=/tmp/.libipc-run/
|
||||||
33
apparmor.d/usr.local.bin.authd
Normal file
33
apparmor.d/usr.local.bin.authd
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
abi <abi/3.0>,
|
||||||
|
|
||||||
|
include <tunables/global>
|
||||||
|
include <dnsmanager>
|
||||||
|
include <boilerplate>
|
||||||
|
|
||||||
|
/usr/local/bin/authd flags=(enforce) {
|
||||||
|
# See the file `boilerplate`.
|
||||||
|
@{BASE_LIBS} mr,
|
||||||
|
@{BASE_RO} r,
|
||||||
|
@{BASE_RW} rw,
|
||||||
|
|
||||||
|
# Allow IPC-related unix sockets.
|
||||||
|
owner @{LIBIPC_DIR}/* rwk,
|
||||||
|
|
||||||
|
# Enable all unix socket operations. TODO: restrict this even further?
|
||||||
|
unix,
|
||||||
|
|
||||||
|
# Deny networking (udp and tcp).
|
||||||
|
deny network tcp,
|
||||||
|
deny network udp,
|
||||||
|
|
||||||
|
# Enable to read the configuration (and the database key).
|
||||||
|
owner @{AUTHD_CONFIG} r,
|
||||||
|
owner @{AUTHD_DB_KEY} r,
|
||||||
|
|
||||||
|
# Database and logs.
|
||||||
|
owner @{AUTHD_DB_PATH}/** rwkl,
|
||||||
|
owner @{AUTHD_LOGS} w,
|
||||||
|
|
||||||
|
# Enable authd to send mails.
|
||||||
|
@{MAILER} ux,
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
login: admin
|
login: admin
|
||||||
pass: secret
|
pass: secret
|
||||||
|
|
||||||
|
# Path to the log file. By default, everything is just printed on screen.
|
||||||
|
log_file: /var/log/baguette/auth.log
|
||||||
|
|
||||||
# In case you have a special `mailer` application.
|
# In case you have a special `mailer` application.
|
||||||
# Read the manual to understand how it is invoked.
|
# Read the manual to understand how it is invoked.
|
||||||
mailer_exe: /usr/local/bin/my-special-mailer
|
mailer_exe: /usr/local/bin/my-special-mailer
|
||||||
|
|
@ -40,16 +43,10 @@ recovery_template: netlibre-email-recovery
|
||||||
|
|
||||||
#verbosity: 4
|
#verbosity: 4
|
||||||
|
|
||||||
|
# By default, print everything except KEEPALIVE messages.
|
||||||
|
#messages_to_mask: [KEEPALIVE]
|
||||||
|
|
||||||
#print_password_recovery_parameters: false
|
#print_password_recovery_parameters: false
|
||||||
|
|
||||||
# IPC-related variables. By default, only print errors and exceptions.
|
# IPC-related messages. By default, only print errors and exceptions.
|
||||||
#print_ipc_timer: false
|
#ipc_messages_to_show: [ERROR, EXCEPTION]
|
||||||
#print_ipc_connection: false
|
|
||||||
#print_ipc_disconnection: false
|
|
||||||
#print_ipc_extra_socket: false
|
|
||||||
#print_ipc_message_received: false
|
|
||||||
#print_ipc_message_sent: false
|
|
||||||
#print_ipc_switch: false
|
|
||||||
#print_ipc_error: true
|
|
||||||
#print_ipc_exception: true
|
|
||||||
#print_keepalive: false
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ can be:
|
||||||
.Bl -tag -width " print functions" -compact
|
.Bl -tag -width " print functions" -compact
|
||||||
.It Li bootstrap
|
.It Li bootstrap
|
||||||
Add the first user (an admin).
|
Add the first user (an admin).
|
||||||
|
.It Li exit
|
||||||
|
Kill the service.
|
||||||
.It Li migration-script
|
.It Li migration-script
|
||||||
Adding a batch of users from old code base.
|
Adding a batch of users from old code base.
|
||||||
.It Li user
|
.It Li user
|
||||||
|
|
@ -113,7 +115,13 @@ Add the first user (will automatically be an admin).
|
||||||
.br
|
.br
|
||||||
.Nm authctl
|
.Nm authctl
|
||||||
.Ar migration-script No
|
.Ar migration-script No
|
||||||
|
.br
|
||||||
|
|
||||||
|
Kill the service.
|
||||||
|
.br
|
||||||
|
.Nm authctl
|
||||||
|
.Ar exit No
|
||||||
|
.br
|
||||||
|
|
||||||
Operations on users.
|
Operations on users.
|
||||||
.br
|
.br
|
||||||
|
|
@ -259,13 +267,13 @@ to handle users (authentication, authorization, preferences and profile)
|
||||||
.It
|
.It
|
||||||
.Xr mailer 1
|
.Xr mailer 1
|
||||||
a simple executable to send mails based on templates
|
a simple executable to send mails based on templates
|
||||||
.
|
|
||||||
.It
|
|
||||||
.Xr dodb 7
|
|
||||||
a document database library used in
|
|
||||||
.Xr authd .
|
|
||||||
.El
|
.El
|
||||||
|
|
||||||
|
The Document-oriented DataBase (DoDB) library used in
|
||||||
|
.Xr authd .
|
||||||
|
.br
|
||||||
|
.Lk https://git.baguette.netlib.re/Baguette/dodb.cr dodb
|
||||||
|
|
||||||
.Sh Limitations
|
.Sh Limitations
|
||||||
WARNING:
|
WARNING:
|
||||||
.Xr authctl
|
.Xr authctl
|
||||||
|
|
|
||||||
116
man/authd.1
116
man/authd.1
|
|
@ -58,8 +58,8 @@ to encrypt users's password is read from the file
|
||||||
.Pa /var/authd/secret-password .
|
.Pa /var/authd/secret-password .
|
||||||
.br
|
.br
|
||||||
Finally, indexes are recreated, which is related to the
|
Finally, indexes are recreated, which is related to the
|
||||||
.Xr dodb 7
|
.Xr DoDB
|
||||||
document database, see the related manual page to learn more.
|
document database, see the related documentation to learn more.
|
||||||
|
|
||||||
.Sh Configuration file variables
|
.Sh Configuration file variables
|
||||||
The following presents the complete list of configuration file variables.
|
The following presents the complete list of configuration file variables.
|
||||||
|
|
@ -70,50 +70,72 @@ related variables:
|
||||||
.
|
.
|
||||||
.Bl -tag -width " print functions" -compact
|
.Bl -tag -width " print functions" -compact
|
||||||
.It Li ipc_timer
|
.It Li ipc_timer
|
||||||
Int32, 30_000 (30 seconds)
|
Int32, 30_000
|
||||||
.
|
.br
|
||||||
|
The IPC timer wakes the process by default every 30 seconds.
|
||||||
|
There is no much point changing this value since nothing is executed periodically anyway, at least for now.
|
||||||
|
|
||||||
.It Li verbosity
|
.It Li verbosity
|
||||||
Int32, 4 ([0-4],
|
Int32, 4
|
||||||
|
.br
|
||||||
|
[0-4],
|
||||||
.Dq 0
|
.Dq 0
|
||||||
being quiet and
|
being quiet and
|
||||||
.Dq 4
|
.Dq 4
|
||||||
meaning printing debug values)
|
meaning printing debug values.
|
||||||
.
|
|
||||||
.It Li print functions
|
|
||||||
Print functions enable to select messages to print, for example by printing a message each time a message is received while ignoring keepalive messages.
|
|
||||||
|
|
||||||
.Bl -tag -width " print_ipc_message_received" -compact
|
.It Li ipc_messages_to_show
|
||||||
.It Li print_ipc_timer
|
Array of
|
||||||
Bool, false
|
.Vt Baguette::Configuration::IPC::MESSAGE ,
|
||||||
.It Li print_ipc_connection
|
[ERROR, EXCEPTION]
|
||||||
Bool, false
|
|
||||||
.It Li print_ipc_disconnection
|
Types of IPC messages to print, for example all connections.
|
||||||
Bool, false
|
This is mainly for debug since it is very low-level.
|
||||||
.It Li print_ipc_extra_socket
|
High-level messages are more relevant to log.
|
||||||
Bool, false
|
By default, errors and exceptions are logged.
|
||||||
.It Li print_ipc_message_received
|
|
||||||
Bool, false
|
See
|
||||||
.It Li print_ipc_message_sent
|
.Xr Baguette-crystal-base ,
|
||||||
Bool, false
|
which includes the
|
||||||
.It Li print_ipc_switch
|
.Vt Baguette::Configuration::IPC::MESSAGE
|
||||||
Bool, false
|
definition.
|
||||||
.It Li print_ipc_error
|
This type has an alias in
|
||||||
Bool, true
|
.Xr authd :
|
||||||
.It Li print_ipc_exception
|
.Vt IPCMESSAGE .
|
||||||
Bool, true
|
|
||||||
.It Li print_keepalive
|
.It Li service_name
|
||||||
Bool, false
|
String,
|
||||||
|
.Dq auth
|
||||||
|
.br
|
||||||
|
.Xr libipc 7
|
||||||
|
unix socket name.
|
||||||
.El
|
.El
|
||||||
.
|
|
||||||
.El
|
.El
|
||||||
|
|
||||||
Specific
|
Specific
|
||||||
.Xr authd
|
.Xr authd
|
||||||
variables:
|
variables:
|
||||||
.Bl -tag -width " print_password_recovery_parameters" -compact
|
.Bl -tag -width " print_password_recovery" -compact
|
||||||
.It Li service_name
|
.It Li log_file
|
||||||
String,
|
String?,
|
||||||
.Dq auth
|
.Em none
|
||||||
|
.br
|
||||||
|
Path to the log file.
|
||||||
|
|
||||||
|
.It Li messages_to_mask
|
||||||
|
Array of
|
||||||
|
.Vt AuthD::MESSAGE ,
|
||||||
|
.Em [ KEEPALIVE ]
|
||||||
|
.br
|
||||||
|
List of high-level
|
||||||
|
.Em authd
|
||||||
|
messages to mask in the logs.
|
||||||
|
.br
|
||||||
|
The type
|
||||||
|
.Vt AuthD::MESSAGE
|
||||||
|
has an alias:
|
||||||
|
.Vt AUTHMESSAGE .
|
||||||
|
|
||||||
.It Li recreate_indexes
|
.It Li recreate_indexes
|
||||||
Bool, false
|
Bool, false
|
||||||
.It Li storage_directory
|
.It Li storage_directory
|
||||||
|
|
@ -250,13 +272,27 @@ to handle users (authentication, authorization, preferences and profile)
|
||||||
.It
|
.It
|
||||||
.Xr mailer 1
|
.Xr mailer 1
|
||||||
a simple executable to send mails based on templates
|
a simple executable to send mails based on templates
|
||||||
.
|
|
||||||
.It
|
|
||||||
.Xr dodb 7
|
|
||||||
a document database library used in
|
|
||||||
.Xr authd .
|
|
||||||
.El
|
.El
|
||||||
|
|
||||||
|
The Document-oriented DataBase (DoDB) library used in
|
||||||
|
.Xr authd .
|
||||||
|
.br
|
||||||
|
.Lk https://git.baguette.netlib.re/Baguette/dodb.cr dodb
|
||||||
|
|
||||||
|
The online service
|
||||||
|
.Dq netlib.re
|
||||||
|
is the first one to use the
|
||||||
|
.Xr authd
|
||||||
|
daemon.
|
||||||
|
.br
|
||||||
|
.Lk https://www.netlib.re netlib.re
|
||||||
|
|
||||||
|
The logging and configuration library for the whole
|
||||||
|
.Dq baguette
|
||||||
|
project.
|
||||||
|
.br
|
||||||
|
.Lk https://git.baguette.netlib.re/Baguette/baguette-crystal-base baguette-crystal-base
|
||||||
|
|
||||||
.Sh Limitations
|
.Sh Limitations
|
||||||
WARNING:
|
WARNING:
|
||||||
.Xr authd
|
.Xr authd
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,10 @@ module AuthD
|
||||||
], read
|
], read
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def exit
|
||||||
|
send_now Request::Exit.new
|
||||||
|
end
|
||||||
|
|
||||||
def validate_user(login : String, activation_key : String)
|
def validate_user(login : String, activation_key : String)
|
||||||
send_now Request::ValidateUser.new login, activation_key
|
send_now Request::ValidateUser.new login, activation_key
|
||||||
parse_message [
|
parse_message [
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,15 @@ parser = OptionParser.new do |parser|
|
||||||
unrecognized_args_to_context_args.call parser, 2
|
unrecognized_args_to_context_args.call parser, 2
|
||||||
end
|
end
|
||||||
|
|
||||||
|
parser.on "exit", "Kill the service." do
|
||||||
|
parser.banner = "Usage: exit"
|
||||||
|
Baguette::Log.info "Kill the service."
|
||||||
|
Context.command = "exit"
|
||||||
|
opt_authd_login.call parser
|
||||||
|
opt_help.call parser
|
||||||
|
unrecognized_args_to_context_args.call parser, 0
|
||||||
|
end
|
||||||
|
|
||||||
parser.on "migration-script", "Add a batch of users from old code base." do
|
parser.on "migration-script", "Add a batch of users from old code base." do
|
||||||
parser.banner = "usage: migration-script user-db.txt"
|
parser.banner = "usage: migration-script user-db.txt"
|
||||||
Baguette::Log.info "Add a batch of users."
|
Baguette::Log.info "Add a batch of users."
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ class Actions
|
||||||
@the_call["user-migrate"] = ->user_migrate
|
@the_call["user-migrate"] = ->user_migrate
|
||||||
@the_call["migration-script"] = ->migration_script
|
@the_call["migration-script"] = ->migration_script
|
||||||
@the_call["user-mod"] = ->user_mod
|
@the_call["user-mod"] = ->user_mod
|
||||||
|
@the_call["exit"] = ->kill_service
|
||||||
|
|
||||||
@the_call["permission-set"] = ->permission_set
|
@the_call["permission-set"] = ->permission_set
|
||||||
@the_call["permission-check"] = ->permission_check
|
@the_call["permission-check"] = ->permission_check
|
||||||
|
|
@ -192,6 +193,14 @@ class Actions
|
||||||
puts "error: #{e.message}"
|
puts "error: #{e.message}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def kill_service
|
||||||
|
puts "Kill the service."
|
||||||
|
authd.exit
|
||||||
|
rescue e : AuthD::Exception
|
||||||
|
puts "error: #{e.message}"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def user_change_password
|
def user_change_password
|
||||||
args = Context.args.not_nil!
|
args = Context.args.not_nil!
|
||||||
login = args[0]
|
login = args[0]
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ class IPC::JSON
|
||||||
def handle(service : AuthD::Service, fd : Int32)
|
def handle(service : AuthD::Service, fd : Int32)
|
||||||
raise "unimplemented"
|
raise "unimplemented"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
io << self.class.name.sub /[^:]+::[^:]+::/, ""
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module AuthD
|
module AuthD
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ class AuthD::Request
|
||||||
def initialize(@login, @password, @admin, @email, @profile)
|
def initialize(@login, @password, @admin, @email, @profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (login: #{@login}, email: #{@email})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user_full? fd
|
logged_user = authd.get_logged_user_full? fd
|
||||||
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
|
@ -56,6 +61,11 @@ class AuthD::Request
|
||||||
def initialize(@login, @password, @email, @profile = nil)
|
def initialize(@login, @password, @email, @profile = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (login: #{@login}, email: #{email})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
# Check if there already is a registered user.
|
# Check if there already is a registered user.
|
||||||
if authd.users.to_a.size > 0
|
if authd.users.to_a.size > 0
|
||||||
|
|
@ -90,6 +100,11 @@ class AuthD::Request
|
||||||
def initialize(@token)
|
def initialize(@token)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (token size: #{@token.size})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user_full? fd
|
logged_user = authd.get_logged_user_full? fd
|
||||||
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
|
@ -105,4 +120,23 @@ class AuthD::Request
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
AuthD.requests << DecodeToken
|
AuthD.requests << DecodeToken
|
||||||
|
|
||||||
|
IPC::JSON.message Exit, 248 do
|
||||||
|
def initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
|
logged_user = authd.get_logged_user_full? fd
|
||||||
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
logged_user.assert_permission("authd", "*", User::PermissionLevel::Admin)
|
||||||
|
|
||||||
|
Baguette::Log.warning "exit requested, bye"
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
AuthD.requests << Exit
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,11 @@ class AuthD::Request
|
||||||
def initialize(@user = nil)
|
def initialize(@user = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user_full? fd
|
logged_user = authd.get_logged_user_full? fd
|
||||||
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,11 @@ class AuthD::Request
|
||||||
def initialize(@login, @password)
|
def initialize(@login, @password)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (login: #{@login})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
begin
|
begin
|
||||||
user = authd.users_per_login.get @login
|
user = authd.users_per_login.get @login
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,11 @@ class AuthD::Request
|
||||||
def initialize(@login, @password_hash_brkn, @admin = false, @email = nil, @profile = nil)
|
def initialize(@login, @password_hash_brkn, @admin = false, @email = nil, @profile = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (login: #{@login}, admin: #{@admin})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user_full? fd
|
logged_user = authd.get_logged_user_full? fd
|
||||||
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@ class AuthD::Request
|
||||||
def initialize(@user, @admin, @password, @email)
|
def initialize(@user, @admin, @password, @email)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user}, admin: #{@admin})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user_full? fd
|
logged_user = authd.get_logged_user_full? fd
|
||||||
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,11 @@ class AuthD::Request
|
||||||
def initialize(@login = nil, @email = nil)
|
def initialize(@login = nil, @email = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (login: #{@login})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
if @login.nil? && @email.nil?
|
if @login.nil? && @email.nil?
|
||||||
return Response::ErrorUserNotFound.new
|
return Response::ErrorUserNotFound.new
|
||||||
|
|
@ -54,6 +59,11 @@ class AuthD::Request
|
||||||
def initialize(@user, @password_renew_key, @new_password)
|
def initialize(@user, @password_renew_key, @new_password)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user}, password_renew_key: #{@password_renew_key})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
user = authd.user? @user
|
user = authd.user? @user
|
||||||
# This is a way for an attacker to know what are the valid logins.
|
# This is a way for an attacker to know what are the valid logins.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,11 @@ class AuthD::Request
|
||||||
def initialize(@user, @service, @resource)
|
def initialize(@user, @service, @resource)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user}, service: #{@service}, resource: #{@resource})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user_full? fd
|
logged_user = authd.get_logged_user_full? fd
|
||||||
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
|
@ -42,6 +47,11 @@ class AuthD::Request
|
||||||
def initialize(@user, @service, @resource, @permission)
|
def initialize(@user, @service, @resource, @permission)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user}, service: #{@service}, resource: #{@resource}, permission: #{@permission})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user_full? fd
|
logged_user = authd.get_logged_user_full? fd
|
||||||
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@ class AuthD::Request
|
||||||
def initialize(@new_profile_entries, @user = nil)
|
def initialize(@new_profile_entries, @user = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user_full? fd
|
logged_user = authd.get_logged_user_full? fd
|
||||||
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@ class AuthD::Request
|
||||||
def initialize(@login, @password, @email, @profile)
|
def initialize(@login, @password, @email, @profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (login: #{@login})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
unless authd.configuration.registrations
|
unless authd.configuration.registrations
|
||||||
return Response::ErrorRegistrationsClosed.new
|
return Response::ErrorRegistrationsClosed.new
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ class AuthD::Request
|
||||||
def initialize(@regex = nil, @offset = 0)
|
def initialize(@regex = nil, @offset = 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (regex: #{@regex}, offset: #{@offset})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user_full? fd
|
logged_user = authd.get_logged_user_full? fd
|
||||||
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,11 @@ class AuthD::Request
|
||||||
def initialize(@user, @activation_key)
|
def initialize(@user, @activation_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user}, activation_key: #{@activation_key})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
user = authd.user? @user
|
user = authd.user? @user
|
||||||
# This is a way for an attacker to know what are the valid logins.
|
# This is a way for an attacker to know what are the valid logins.
|
||||||
|
|
@ -40,6 +45,11 @@ class AuthD::Request
|
||||||
def initialize(@user)
|
def initialize(@user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user})"
|
||||||
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user? fd
|
logged_user = authd.get_logged_user? fd
|
||||||
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,12 @@ class AuthD::Response
|
||||||
property email : String? = nil
|
property email : String? = nil
|
||||||
def initialize(@user, @email)
|
def initialize(@user, @email)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user}, email: #{@email})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
AuthD.responses << Contacts
|
AuthD.responses << Contacts
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ class AuthD::Response
|
||||||
property email : String
|
property email : String
|
||||||
def initialize(@email)
|
def initialize(@email)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (email: #{@email})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << NewEmailAddressValidated
|
AuthD.responses << NewEmailAddressValidated
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,11 @@ class AuthD::Response
|
||||||
property reason : String? = nil
|
property reason : String? = nil
|
||||||
def initialize(@reason)
|
def initialize(@reason)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (reason: #{@reason})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << Error
|
AuthD.responses << Error
|
||||||
|
|
||||||
|
|
@ -70,6 +75,11 @@ class AuthD::Response
|
||||||
property read_only_keys : Array(String)
|
property read_only_keys : Array(String)
|
||||||
def initialize(@read_only_keys)
|
def initialize(@read_only_keys)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (read_only_keys: #{@read_only_keys.join(",")})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << ErrorReadOnlyProfileKeys
|
AuthD.responses << ErrorReadOnlyProfileKeys
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,11 @@ class AuthD::Response
|
||||||
property pending_email : String? = nil
|
property pending_email : String? = nil
|
||||||
def initialize(@token, @uid, @current_email, @pending_email)
|
def initialize(@token, @uid, @current_email, @pending_email)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (uid: #{@uid})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << Login
|
AuthD.responses << Login
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,11 @@ class AuthD::Response
|
||||||
property permission : ::AuthD::User::PermissionLevel
|
property permission : ::AuthD::User::PermissionLevel
|
||||||
def initialize(@service, @resource, @user, @permission)
|
def initialize(@service, @resource, @user, @permission)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user}, service: #{@service}, resource: #{@resource}, permission: #{@permission})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << PermissionCheck
|
AuthD.responses << PermissionCheck
|
||||||
|
|
||||||
|
|
@ -16,6 +21,11 @@ class AuthD::Response
|
||||||
property permission : ::AuthD::User::PermissionLevel
|
property permission : ::AuthD::User::PermissionLevel
|
||||||
def initialize(@user, @service, @resource, @permission)
|
def initialize(@user, @service, @resource, @permission)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user: #{@user}, service: #{@service}, resource: #{@resource}, permission: #{@permission})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << PermissionSet
|
AuthD.responses << PermissionSet
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,11 @@ class AuthD::Response
|
||||||
property user : ::AuthD::User::Public
|
property user : ::AuthD::User::Public
|
||||||
def initialize(@user)
|
def initialize(@user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user public data: #{@user})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << User
|
AuthD.responses << User
|
||||||
|
|
||||||
|
|
@ -10,6 +15,11 @@ class AuthD::Response
|
||||||
property user : ::AuthD::User::Public
|
property user : ::AuthD::User::Public
|
||||||
def initialize(@user)
|
def initialize(@user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user public data: #{@user})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << UserAdded
|
AuthD.responses << UserAdded
|
||||||
|
|
||||||
|
|
@ -17,6 +27,11 @@ class AuthD::Response
|
||||||
property uid : UInt32
|
property uid : UInt32
|
||||||
def initialize(@uid)
|
def initialize(@uid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (uid: #{@uid})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << UserEdited
|
AuthD.responses << UserEdited
|
||||||
|
|
||||||
|
|
@ -24,6 +39,11 @@ class AuthD::Response
|
||||||
property user : ::AuthD::User::Public
|
property user : ::AuthD::User::Public
|
||||||
def initialize(@user)
|
def initialize(@user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (user public data: #{@user})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << UserValidated
|
AuthD.responses << UserValidated
|
||||||
|
|
||||||
|
|
@ -31,6 +51,11 @@ class AuthD::Response
|
||||||
property users : Array(::AuthD::User::Public)
|
property users : Array(::AuthD::User::Public)
|
||||||
def initialize(@users)
|
def initialize(@users)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (users public data: #{(@users.map &.uid).join ","})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << UsersList
|
AuthD.responses << UsersList
|
||||||
|
|
||||||
|
|
@ -38,6 +63,11 @@ class AuthD::Response
|
||||||
property users : Array(::AuthD::User::Public)
|
property users : Array(::AuthD::User::Public)
|
||||||
def initialize(@users)
|
def initialize(@users)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (users public data: #{(@users.map &.uid).join ","})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << MatchingUsers
|
AuthD.responses << MatchingUsers
|
||||||
|
|
||||||
|
|
@ -45,6 +75,11 @@ class AuthD::Response
|
||||||
property uid : UInt32
|
property uid : UInt32
|
||||||
def initialize(@uid)
|
def initialize(@uid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s(io : IO)
|
||||||
|
super io
|
||||||
|
io << " (uid: #{@uid})"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AuthD.responses << UserDeleted
|
AuthD.responses << UserDeleted
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class AuthD::Service < IPC
|
||||||
property configuration : Baguette::Configuration::Auth
|
property configuration : Baguette::Configuration::Auth
|
||||||
|
|
||||||
# DB and its indexes.
|
# DB and its indexes.
|
||||||
property users : DODB::Storage::Cached(User)
|
property users : DODB::Storage::Common(User)
|
||||||
property users_per_uid : DODB::Trigger::IndexCached(User)
|
property users_per_uid : DODB::Trigger::IndexCached(User)
|
||||||
property users_per_login : DODB::Trigger::IndexCached(User)
|
property users_per_login : DODB::Trigger::IndexCached(User)
|
||||||
property users_per_email : DODB::Trigger::IndexCached(User)
|
property users_per_email : DODB::Trigger::IndexCached(User)
|
||||||
|
|
@ -42,7 +42,7 @@ class AuthD::Service < IPC
|
||||||
def initialize(@configuration)
|
def initialize(@configuration)
|
||||||
super()
|
super()
|
||||||
|
|
||||||
@users = DODB::Storage::Cached(User).new @configuration.storage_directory
|
@users = DODB::Storage::Common(User).new @configuration.storage_directory, 5000
|
||||||
@users_per_uid = @users.new_index "uid", &.uid.to_s
|
@users_per_uid = @users.new_index "uid", &.uid.to_s
|
||||||
@users_per_login = @users.new_index "login", &.login
|
@users_per_login = @users.new_index "login", &.login
|
||||||
@users_per_email = @users.new_index "email" do |user|
|
@users_per_email = @users.new_index "email" do |user|
|
||||||
|
|
@ -111,7 +111,7 @@ class AuthD::Service < IPC
|
||||||
File.write @last_uid_file, uid.to_s
|
File.write @last_uid_file, uid.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_logged_user?(fd : Int32)
|
def get_logged_user?(fd : Int32) : AuthD::User::Public?
|
||||||
@logged_users[fd]?
|
@logged_users[fd]?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -123,6 +123,17 @@ class AuthD::Service < IPC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# `log_user_info` provides a string composed from either the user
|
||||||
|
# id in case the user was authenticated or the file descriptor of
|
||||||
|
# the connection.
|
||||||
|
def log_user_info(fd : Int32) : String
|
||||||
|
if user = get_logged_user? fd
|
||||||
|
"userid #{user.uid}"
|
||||||
|
else
|
||||||
|
"fd #{"%4d" % fd}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def user?(uid_or_login : UserID)
|
def user?(uid_or_login : UserID)
|
||||||
if uid_or_login.is_a? UInt32
|
if uid_or_login.is_a? UInt32
|
||||||
@users_per_uid.get? uid_or_login.to_s
|
@users_per_uid.get? uid_or_login.to_s
|
||||||
|
|
@ -144,20 +155,21 @@ class AuthD::Service < IPC
|
||||||
end
|
end
|
||||||
|
|
||||||
request_name = request.class.name.sub /^AuthD::Request::/, ""
|
request_name = request.class.name.sub /^AuthD::Request::/, ""
|
||||||
|
connection_info_str = log_user_info event.fd
|
||||||
|
|
||||||
response = begin
|
response = begin
|
||||||
request.handle self, event.fd
|
request.handle self, event.fd
|
||||||
rescue e : UserNotFound
|
rescue e : UserNotFound
|
||||||
Baguette::Log.error "(fd #{ "%4d" % event.fd}) #{request_name} user not found"
|
Baguette::Log.error "(#{connection_info_str}) #{request} user not found"
|
||||||
AuthD::Response::Error.new "authorization error"
|
AuthD::Response::Error.new "authorization error"
|
||||||
rescue e : AuthenticationInfoLacking
|
rescue e : AuthenticationInfoLacking
|
||||||
Baguette::Log.error "(fd #{ "%4d" % event.fd}) #{request_name} lacking authentication info"
|
Baguette::Log.error "(#{connection_info_str}) #{request} lacking authentication info"
|
||||||
AuthD::Response::Error.new "authorization error"
|
AuthD::Response::Error.new "authorization error"
|
||||||
rescue e : AdminAuthorizationException
|
rescue e : AdminAuthorizationException
|
||||||
Baguette::Log.error "(fd #{ "%4d" % event.fd}) #{request_name} admin authentication failed"
|
Baguette::Log.error "(#{connection_info_str}) #{request} admin authentication failed"
|
||||||
AuthD::Response::Error.new "authorization error"
|
AuthD::Response::Error.new "authorization error"
|
||||||
rescue e
|
rescue e
|
||||||
Baguette::Log.error "(fd #{ "%4d" % event.fd}) #{request_name} generic error #{e}"
|
Baguette::Log.error "(#{connection_info_str}) #{request} generic error #{e}"
|
||||||
AuthD::Response::Error.new "unknown error"
|
AuthD::Response::Error.new "unknown error"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -169,13 +181,11 @@ class AuthD::Service < IPC
|
||||||
|
|
||||||
duration = Time.utc - request_start
|
duration = Time.utc - request_start
|
||||||
|
|
||||||
response_name = response.class.name.sub /^AuthD::Response::/, ""
|
|
||||||
|
|
||||||
if response.is_a? AuthD::Response::Error
|
if response.is_a? AuthD::Response::Error
|
||||||
Baguette::Log.warning "fd #{ "%4d" % event.fd} (#{duration}) #{request_name} >> #{response_name} (#{response.reason})"
|
Baguette::Log.warning "(#{connection_info_str}) (#{duration}) #{request} >> #{response}"
|
||||||
else
|
else
|
||||||
if request_name != "KeepAlive" || should_display? AUTHMESSAGE::KEEPALIVE
|
if request_name != "KeepAlive" || should_display? AUTHMESSAGE::KEEPALIVE
|
||||||
Baguette::Log.debug "fd #{ "%4d" % event.fd} (#{duration}) #{request_name} >> #{response_name}"
|
Baguette::Log.debug "(#{connection_info_str}) (#{duration}) #{request} >> #{response}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue