Access Control
== Description ==
This page presents the facilities offered by HOP for programming
users authentications and accesses restrictions.
~~ Access restriction relies on some global parameters (as described
above) that enable or disable control. It also relies on user
declarations.
== Synopsis ==
=== server parameters ===
(hop-enable-proxying)
(hop-enable-proxying-set! arg)
(hop-proxy-authentication)
(hop-proxy-authentication-set! arg)
(hop-proxy-remote-authentication)
(hop-proxy-remote-authentication-set! arg)
(hop-proxy-allow-remote-client)
(hop-proxy-allow-remote-client-set! arg)
(hop-proxy-ip-mask)
(hop-proxy-ip-mask-set! mark)
(hop-path-access-control)
(hop-path-access-control-set! proc)
(hop-service-access-control)
(hop-service-access-control-set! proc)
(hop-http-authentication)
(hop-http-authentication-set! schema)
=== server functions ===
(add-user! arg ...)
(user-exists? string)
(find-user string string)
(find-user/encrypt string string procedure)
(find-authenticated-user string)
(user-authorized-request? obj request)
(user-authorized-path? obj string)
(authorized-path? obj string)
(user-authorized-service? obj symbol)
(authorized-service? request symbol)
(find-hopaccess string)
(user-access-denied request [message])
=== server and client functions ===
(authentication-encrypt :schema :algo :session :name :password :path :ip)
(basic-password-encrypt name password)
(digest-password-encrypt name password realm)
(password-encrypt name password method)
(h0password password path)
(h1password password path session)
(h2password password path session ip)
== Server Definitions ==
=== ++hop-enable-proxying++ ===
hop-enable-proxying
hop-enable-proxying-set!
^ access ^ type ^ current value ^ short description ^
| r/w | bool | ++,(hop-enable-proxying)++ | Enables/disables proxy requests. |
This parameter controls whether HOP can be used as a Web proxy. When this
parameter is set to ++#t++, HOP can be used as a proxy. Several other
parameters can be used to control which clients are allowed to emit
proxy requests (see, ++hop-proxy-authentication++,
++hop-proxy-remote-authentication++,
++hop-proxy-allow-remote-client++, ++hop-proxy-ip-mask++).
=== ++hop-proxy-authentication++ ===
hop-proxy-authentication
hop-proxy-authentication-set!
^ access ^ type ^ current value ^ short description ^
| r/w | bool | ++,(hop-proxy-authentication)++ | Is authentication requested for proxy responses. |
This parameter controls responses to proxy requests (::http-request). That is, when
a request hits HOP, the server find out if it can locally answers it.
If it cannot, it adopts a //proxy// behavior by transmitted this request
to the target host. If the parameter ++hop-proxy-authentication++ is
set to ++#t++, HOP will request user authentication in order
to server the request.
=== ++hop-proxy-remote-authentication++ ===
hop-proxy-remote-authentication
hop-proxy-remote-authentication-set!
^ access ^ type ^ current value ^ short description ^
| r/w | bool | ++,(hop-proxy-authentication)++ | Is authentication requested for proxy responses. |
This parameter controls responses to proxy requests emitted from
**remote clients**. That is, when a request from a remote client hits
HOP, the server find out if it can locally answers it. If it cannot,
it adopts a //proxy// behavior by transmitted this request to the
target host. If the parameter ++hop-proxy-remote-authentication++ is set to
++#t++, HOP will request user authentication in order to server the
request.
=== ++hop-proxy-allow-remote-client++ ===
hop-proxy-allow-remote-client
hop-proxy-allow-remote-client-set!
^ access ^ type ^ current value ^ short description ^
| r/w | bool | ++,(hop-proxy-allow-remote-client)++ | Are remote clients allowed for proxy responses. |
This parameter controls whenever remote clients can use the running
HOP as proxy.
=== ++hop-proxy-ip-mask++ ===
hop-proxy-ip-mask
hop-proxy-ip-mask-set!
^ access ^ type ^ current value ^ short description ^
| r/w | bool | ++,(hop-proxy-ip-mask)++ | The IP mask of allowed proxy clients. |
This parameter restricts the set of clients that are allowed to use
HOP as proxy to the set of clients whose IP address matches
++hop-proxy-ip-mask++ (see ++hop-enable-proxying++).
=== ++hop-ip-blacklist++ ===
hop-ip-blacklist
hop-ip-blacklist-set!
A list containing a list of blacklisted IP addresses. All attempts of
connection by these machines will be refused.
=== ++hop-path-access-control++ ===
hop-path-access-control
hop-path-access-control-set!
^ access ^ type ^ short description ^
| r/w | procedure | A procedure that returns ++#t++ for allowed paths. |
~~ Note: this parameter can only be changed while the HOP runtime command
file (++hop-rc-file++) file is loaded.
~~ The parameter ++hop-path-access-control++ enables global control over
access path restriction. It is bound to procedure of two
arguments. The first one is a ::http-request and the second a path.
When applied to an actual request and an actual path, if this
procedure returns ++#t++ the file denoted by the path is allowed to be
served. Otherwise it is allowed if and only if the authenticated user
is granted the permission to read that file.
~~ The parameter ++hop-path-access-control++ defaults to:
(lambda (req path)
(any (lambda (p)
(substring-at? path p 0))
(hop-path)))
=== ++hop-service-access-control++ ===
hop-service-access-control
hop-service-access-control-set!
^ access ^ type ^ short description ^
| r/w | procedure | A procedure that returns ++#t++ for allowed services. |
~~ Note: this parameter can only be changed while the HOP runtime command
file (++hop-rc-file++) file is loaded.
~~ The parameter ++hop-service-access-control++ enables global control
over service path restriction. it is bound to procedure of
two arguments. The first one is a ::http-request. The second one is a
service identifier. When applied to an actual request and an actual
service identifier, if this procedure returns ++#t++ the service
denoted by the identifier is allowed to be executed. Otherwise the
execution is allowed if and only if the authenticated user is granted
the permission to execute such a service.
~~ The parameter ++hop-service-access-control++ defaults to:
(lambda (req service)
#f)
=== ++hop-http-authentication++ ===
hop-http-authentication
hop-http-authentication-set!
^ access ^ type ^ short description ^
| r/w | symbol | either ++basic++ or ++digest++ |
~~ This parameter controls the type of HTTP authentication Hop asks to client.
The ++digest++ authentication is more robust than ++basic++ because passwords
are not sent as plain text but it consumes more server resource because
hashing operations have to be executed for each received requests.
=== ++(add-user! name option ...)++ ===
add-user!
^ argument ^ type ^ default ^ short description ^
| name | string | | the user name. |
| :password | string | | the encrypted user password. |
| :groups | list of symbols | ++()++ | the list of groups the user belongs to. |
| :directories | obj | ++#f++ | the authorized directories. |
| :services | obj | ++#f++ | the authorized services. |
The function ++add-user!++ returns an opaque structure denoting a
unique user. For security reasons, users can only be defined in the
,( "RC file" "07-hoprc.wiki").
In other words, the function ++add-user!++ can only be used in the
,( "RC file" "07-hoprc.wiki").
Users cannot be added as soon as the first Hop request has been
intercepted. Here are the meaning of its optional arguments:
* :password - The user encrypted password. This encryption should
be computed using the
,( :href (format "http://localhost:~a/hop/epassword" (hop-port))
( :style "font-variant: small-caps" "EPassword")) weblet. Hop
proposes two encryption methods. The first one called //basic// is computed
with ++(md5sum (string-append name ":" password))++. The second, that should
be preferred as much as possible is called //digest// and is computed by
++(string-append "+" (md5sum (string-append name ":" (hop-realm) ":" password)))++.
* :directories - The value of this option should either be:
* ++#f++, no directory can be visited by this user.
* ++'*++ (the symbol ++*++), all directories can be visited.
* a list of strings, each directory in the list can be visited.
* :services - The value of this option should either be:
* ++#f++, no ,( "service" "service.wiki") can be executed for
this user.
* ++'*++ (the symbol ++*++), all ,( "services" "service.wiki")
can be executed.
* a list of service names (a list of symbols), each
,( "service" "service.wiki") in the list can be executed. The
special name "?" stands for the anonymous services. That is only users whose
authorized services list contains the symbol ? is allowed to execute
anonymous services.
* :groups - The list of groups the user belongs to.
~~ Examples:
;; an administrator that can go everywhere and execute everthing and that
;; uses a basic pre-hashed password
(add-user! "admin"
:groups '(admin exec bbdb)
:password "75874d556834ccb5361316184780089c"
:directories '*
:services '*)
;; a guest that can only visit the /tmp/guest directory and that uses
;; a digest pre-hashed password
(add-user! "guest"
:password "+f874d556834ccb53613161847800897c"
:directories '("/tmp/guest"))
=== ++(user-exists? name)++ ===
user-exists?
^ argument ^ type ^ short description ^
| name | string | the user name. |
This predicate return ++#t++ if and only if the user named ++name++ exists.
(i.e., a call to ++add-user!++ with ++name++ as value of the first parameter
has already been executed). Otherwise, it returns ++#f++.
=== ++(find-user name password)++ ===
find-user
^ argument ^ type ^ short description ^
| name | string | the user name. |
| password | string | the encrypted user password. |
This function returns a user named ++name++ whose encrypted password
is ++password++. If such user is not found, the function returns ++#f++.
~~ Example:
(find-user "admin" "75874d556834ccb5361316184780089c")
=== ++(find-user/encrypt name password proc)++ ===
find-user/encrypt
^ argument ^ type ^ short description ^
| name | string | the user name. |
| password | string | the encrypted user password. |
| proc | procedure | the encryption procedure. |
This function behaves similarly to ++find-user++ except that encryption
is applied. That is, this function returns a user named ++name++ whose
password ++p++ for which ++(string=? (proc p) (proc password))++ is
true.
~~ The function ++find-user/encrypt++ can be used by application that
needs temporary authentications. For instance, let's assume an application
that needs to grant accesses that last until the next day is arrived. One
may used an encryption function such as:
(define (encrypt old-password)
(format "~a-~a" (date-day (current-date)) old-password))
~~ This function is used by the
,( :href (format "http://localhost:~a/hop/hz" (hop-port))
( :style "font-variant: small-caps" "Hz")) weblet to handle
user connections.
=== ++(find-authenticated-user uinfo path method ip)++ ===
find-authenticated-user
^ argument ^ type ^ short description ^
| uinfo | string | a user information. |
| path | string | a path. |
| method | symbol | either ++basic++ or ++digest++. |
| ip | string | an IP address. |
This functions search authenticated users from the ++userinfo++ field
found in ::http-request objects. If method is ++digest++ the
++method++ and ++ip++ are used to hash the user password. Otherwise,
they are ignored.
=== ++(user-authorized-request? user request)++ ===
user-authorized-request?
^ argument ^ type ^ short description ^
| user | obj | the user. |
| request | ::http-request | the request. |
This predicate returns ++#t++ if and only if the ++request++ can be satisfied
(i.e, the directory can be read and the service executed) for the ++user++.
Otherwise, it returns ++#f++.
=== ++(user-authorized-path? user request)++ ===
user-authorized-path?
^ argument ^ type ^ short description ^
| user | obj | the user. |
| path | string | the path. |
~~ A user can read the directory, if two condition are meet:
- the optional argument :directory that has been used when declaring
the user is compatible with ++path++.
- if it exists a file named ++,(hop-hopaccess)++ that goes from the directory
containing the file ++path++ to the root of the file system, this file
must either contain the symbol ++*++ or a list of names containing
the name of the user.
=== ++(authorized-path? request request)++ ===
authorized-path?
^ argument ^ type ^ short description ^
| request | ::http-request | the request. |
| path | string | the path. |
This predicate returns ++#t++ if and only if the ++path++ can be read
by the user authenticated in the ++request++ or if the procedure bound
to the parameter ++hop-path-access-control++ applied to the current
request and current path returns ++#t++. Otherwise, it returns ++#f++.
~~ See the ++user-authorized-path?++.
=== ++(user-authorized-service? user request)++ ===
user-authorized-service?
^ argument ^ type ^ short description ^
| user | obj | the user. |
| service | symbol | the service name. |
This predicate returns ++#t++ if and only if the ++service++ can be executed
by the ++user++. Otherwise, it returns ++#f++.
=== ++(authorized-service? request request)++ ===
authorized-service?
^ argument ^ type ^ short description ^
| request | ::http-request | the request. |
| service | symbol | the service name. |
This predicate returns ++#t++ if and only if the ++service++ can be
executed by the user authenticated in the ++request++ or if the
procedure bound to the parameter ++hop-service-access-control++
applied to the current request and current path returns ++#t++.
Otherwise, it returns ++#f++.
=== ++(find-hopaccess path)++ ===
find-hopaccess
^ argument ^ type ^ short description ^
| path | string | the path. |
This function scans the file system in order to find a file named
++,(hop-hopaccess)++ from the root of the file system to the directory
containing the file ++path++.
=== ++(user-access-denied request [message])++ ===
user-access-denied
^ argument ^ type ^ short description ^
| request | ::http-request | the request. |
| message | string | an optional error message. |
This function builds an answer of type ::http-response-authentication in order
to notify the client that an authentication is needed in order to fulfill
the request.
== Server and Client Definitions ==
=== ++(authentication-encrypt ...)++ ===
authentication-encrypt
authentication-encrypt
^ argument ^ type ^ short description ^
| schema | symbol | either ++url++, ++basic++, or ++digest++. |
| algo | symbol | either ++none++, ++ho0++, ++ho1++, or ++ho2++. |
| session | integer | Hop session. |
| name | string | user name. |
| password | string | user password. |
| path | string | resource path. |
| ip | string | IP address. |
The procedure ++authentication-encrypt++ encrypts a user authentication. One may
use this encryption to construct plains URLs. For instance, one may build an URL with
an expression such as:
(define (authenticated-url p)
(multiple-value-bind (proto login host port abspath)
(url-parse p)
(if (string? login)
p
(let* ((user (find-user "foo"))
(path (url-path-encode abspath))
(auth (authentication-encrypt :name "foo"
:password (user-password user)
:path path
:algo 'ho1)))
(format "~a://~a@~a:~a~a" proto auth host port path)))))
* ++schema++: specifies the method used to encrypt the user password
(see ++password-encrypt++ below).
* ++algo++: specifies the algorithm used to build the user authentication. The possible
values are as follows:
* ++none++: the authentication is the concatenation of the user name and
the plain password. Example ,( "http://foo:password@localhost:8080/tmp/file1").
* ++ho0++: the authentication is the MD5 sum of the user name, the password,
and the Hop session id.
Example: ,( "http://HO0foo:cfe3aa676834ccb5361316184780089c@localhost:8080/hop/file1").
* ++ho1++: the authentication is the MD5 sum of the user name, the password,
the requested path, and the Hop session id.
Example: ,( "http://HO1foo:ae3aa676834ccb5361316184780a089c@localhost:8080/hop/file1").
* ++ho2++: the authentication is the MD5 sum of the user name, the password,
the requested path, the Hop session id, and the client IP number.
Example: ,( "http://HO2foo:f1cba676830ccb5f31316184400a0809c@localhost:8080/hop/file1").
* ++session++: is the session id (an identifier) used by the authentication
encryption algorithm. It is recommended to use ++(hop-session)++ as session identifier.
* ++name++: the user name.
* ++password++: the user password.
* ++path++: the resource path.
* ++ip++: the client IP which is granted the access authorization.
=== ++(basic-password-encrypt name password)++ ===
basic-password-encrypt
basic-password-encrypt
^ argument ^ type ^ short description ^
| name | string | the user name. |
| password | string | the user password. |
~~ Encrypts a user identification as follows:
(md5sum (string-append name ":" password))
=== ++(digest-password-encrypt name password realm)++ ===
digest-password-encrypt
digest-password-encrypt
^ argument ^ type ^ short description ^
| name | string | the user name. |
| password | string | the user password. |
| realm | string | the Hop realm. |
~~ Encrypts a user identification as follows:
(md5sum (string-append name ":" realm ":" password))
=== ++(password-encrypt name password method)++ ===
digest-password-encrypt
digest-password-encrypt
^ argument ^ type ^ short description ^
| name | string | the user name. |
| password | string | the user password. |
| method | symbol | either ++basic++ or ++digest++. |
~~ Encrypts a user identification. If ++method++ is ++basic++ then
the ++basic-password-encrypt++ is used. Otherwise, the
++digest-password-encrypt++ is used and ++hop-realm++ is used as
++realm++.
=== ++(h0password password path)++ ===
h0password
h0password
^ argument ^ type ^ short description ^
| password | string | an encrypted password. |
| path | string | a resource path. |
~~ Encrypts a user password as follows:
(md5sum (string-append password ":" path))
=== ++(h1password password path session)++ ===
h0password
h0password
^ argument ^ type ^ short description ^
| password | string | an encrypted password. |
| path | string | a resource path. |
| session | integer | a session identifier. |
~~ Encrypts a user password as follows:
(md5sum (string-append (integer->string session) ":" password ":" path))
=== ++(h2password password path session ip)++ ===
h0password
h0password
^ argument ^ type ^ short description ^
| password | string | an encrypted password. |
| path | string | a resource path. |
| session | integer | a session identifier. |
| ip | string | client IP number. |
~~ Encrypts a user password as follows:
(md5sum (string-append (integer->string session) ":" ip ":" password ":" path))
== See also ==
authentication, -user, user-