module Netmech_scram:sig
..end
SCRAM mechanism for authentication (RFC 5802)
This implements SCRAM for SASL and GSSAPI.
This module needs the SHA-1 hash function. In order to use it,
initialize crypto support, e.g. by including the nettls-gnutls
packages and calling Nettls_gnutls.init
.
As for all SASL mechanisms in OCamlnet, SASLprep is not automatically
called. Users of SCRAM should pass user names and passwords through
Netsaslprep.saslprep
.
typeptype =
[ `GSSAPI | `SASL ]
Profile types:
`GSSAPI
: as defined in RFC 5802, the gs2-header is omitted`SASL
: as defined in RFC 5802type
profile = {
|
ptype : |
|||
|
hash_function : |
(* | Which hash function | *) |
|
return_unknown_user : |
(* | Whether servers exhibit the fact that the user is unknown | *) |
|
iteration_count_limit : |
(* | Largest supported iteration number | *) |
Profile
typecb =
Netsys_sasl_types.cb
Using the same channel binding type as for SASL
typeserver_error =
[ `Channel_binding_not_supported
| `Channel_bindings_dont_match
| `Extension of string
| `Extensions_not_supported
| `Invalid_encoding
| `Invalid_proof
| `Invalid_username_encoding
| `No_resources
| `Other_error
| `Server_does_support_channel_binding
| `Unknown_user
| `Unsupported_channel_binding_type ]
Error codes of this protocol
type
client_session
Session context for clients
type
server_session
Session context for servers
Client exceptions: The exceptions are returned by client_error_flag
,
but never raised.
exception Invalid_encoding of string * string
Returned by clients when something cannot be decoded. First string is an error message, the second string the raw message that cannot be decoded
exception Invalid_username_encoding of string * string
Returned by clients when the username does not match the requirements.
Arguments as for Invalid_encoding
.
exception Extensions_not_supported of string * string
Returned by clients when the server enables an unsupported extension.
Arguments as for Invalid_encoding
.
exception Protocol_error of string
Returned by clients when the server violates the protocol. The argument is a message.
exception Invalid_server_signature
Returned by clients when the signature sent by the server is invalid (i.e. the server does not know the client password)
exception Server_error of server_error
Returned by clients when the server sent an error code
val error_of_exn : exn -> string
Converts one of the above exceptions to a human-readable string
val profile : ?return_unknown_user:bool ->
?iteration_count_limit:int ->
ptype -> Netsys_digests.iana_hash_fn -> profile
Creates a profile
val string_of_server_error : server_error -> string
val server_error_of_string : string -> server_error
Conversion
val mechanism_name : profile -> string
The official name of the mechanism
The idea is to create a client session s
first. The functions
client_emit_flag
and client_recv_flag
indicate now whether
the client needs to emit a new message, or whether it needs to
receive a message, respectively. Emission is done by client_emit_message
,
reception by client_recv_message
. If everything goes well, the
protocol state advances, and finally client_finish_flag
is true.
This indicates that the client is authenticated and that the server
knows the client's password. If an error occurs, an exception is
raised (see above for possibilities), and client_error_flag
signals
true
.
val create_client_session : ?nonce:string ->
profile -> string -> string -> client_session
create_client_session p username password
: Creates a new client
session for profile p
so that the client authenticates as user
username
, and proves its identity with the given password
.
val create_client_session2 : ?nonce:string ->
profile ->
string -> string -> string -> client_session
create_client_session p username authzname password
: Like
create_client_session
, but also sets the authorization name
(only processed for the SASL profile).
val client_configure_channel_binding : client_session ->
cb -> client_session
Sets whether to request channel binding.
val client_restart : client_session -> string -> client_session
Restart a client session (draft-ietf-httpauth-scram-auth-15). The string is the sr attribute.
val client_restart_stale : client_session -> string -> client_session
Restart a client session after the server indicated that the session is stale. The string arg is the new "sr" attribute (draft-ietf-httpauth-scram-auth-15).
val client_emit_flag : client_session -> bool
Whether client_emit_message
can now be called
val client_recv_flag : client_session -> bool
Whether client_recv_message
can now be called
val client_finish_flag : client_session -> bool
Whether the client is authenticated and the server verified
val client_semifinish_flag : client_session -> bool
Whether the client is authentication
val client_error_flag : client_session -> exn option
Whether an error occurred, and the protocol cannot advance anymore
val client_channel_binding : client_session -> cb
Returns the channel binding
val client_emit_message : client_session -> client_session * string
Emits the next message to be sent to the server
val client_emit_message_kv : client_session ->
client_session * string option * (string * string) list
Emits the next message to be sent to the server. The message is not
encoded as a single string, but as (gs2_opt, kv)
where
gs2_opt
is the optional GS2 header (the production gs2-header
from
the RFC), and kv
contains the parameters as key/value pairs.
val client_recv_message : client_session -> string -> client_session
Receives the next message from the server
val client_protocol_key : client_session -> string option
The 128-bit protocol key for encrypting messages. This is available as soon as the second client message is emitted.
val client_user_name : client_session -> string
The user name
val client_authz_name : client_session -> string
The authorization name
val client_password : client_session -> string
The password
val client_export : client_session -> string
val client_import : string -> client_session
Exports a client session as string, and imports the string again.
The export format is just a marshalled Ocaml value.
val client_prop : client_session -> string -> string
Returns a property of the client (or Not_found):
The idea is to create a server session s
first. The functions
server_emit_flag
and server_recv_flag
indicate now whether
the server needs to emit a new message, or whether it needs to
receive a message, respectively. Emission is done by server_emit_message
,
reception by server_recv_message
. If everything goes well, the
protocol state advances, and finally server_finish_flag
is true.
This indicates that the client could be authenticated.
If an error occurs, no exception is raised, and the protocol
advances nevertheless, and finally the server sends an error token
to the client. After this, server_error_flag
returns true.
typecredentials =
[ `Salted_password of string * string * int
| `Stored_creds of string * string * string * int ]
Two forms of providing credentials:
`Salted_password(spw,salt,iteration_count)
: get the
salted password with
spw = salt_password h password salt iteration_count
`Stored(stkey, srvkey, salt, iteration_count)
: get the
pair (stkey, srvkey) with
stored_key h password salt iteration_count
val create_server_session : ?nonce:string ->
profile ->
(string -> credentials) -> server_session
create_server_session p auth
: Creates a new server session with
profile p
and authenticator function auth
.
The function is auth
is called when the credentials of the
client have been received to check whether the client can be
authenticated. It is called as
let credentials = auth username
where username
is the user name. The function can now raise
Not_found
if the user is unknown, or it can return the
credentials. Note that the cleartext password needs not to
be known. The credentials contain a salt and an iteration count:
salt
is a random string, and iteration_count
a
security parameter that should be at least 4096. Whereas salt
should be different for each user, the iteration_count
can be
chosen as a constant (e.g. 4096). Now salted_password
can be
computed from the cleartext password and these two extra parameters.
See salt_password
below.
val create_server_session2 : ?nonce:string ->
profile ->
(string -> string -> credentials) ->
server_session
Same as create_server_session
, but the authentication callback
gets two arguments:
let credentials = auth username authzname
where authzname
is the passed authorization name (or "" if na).
val create_salt : unit -> string
Creates a random string suited as salt
val salt_password : Netsys_digests.iana_hash_fn -> string -> string -> int -> string
let salted_password = salt_password h password salt iteration_count
Use this now as credentials
`Salted_password(salted_password,salt,iteration_count)
.
As we do not implement SASLprep
only passwords consisting of
US-ASCII characters are accepted (Invalid_encoding
otherwise).
val stored_key : Netsys_digests.iana_hash_fn -> string -> string -> int -> string * string
let stkey,srvkey = stored_key h password salt iteration_count
Use this now as credentials
`Stored_creds(stkey,srvkey,salt,iteration_count)
.
val server_emit_flag : server_session -> bool
Whether server_emit_message
can now be called
val server_recv_flag : server_session -> bool
Whether server_recv_message
can now be called
val server_finish_flag : server_session -> bool
Whether the client is authenticated
val server_error_flag : server_session -> bool
Whether an error occurred, and the protocol cannot advance anymore
val server_emit_message : server_session -> server_session * string
Emits the next message to be sent to the client
val server_emit_message_kv : server_session ->
server_session * (string * string) list
Emits the next message to be sent to the client. The message is returned as a list of key/value pairs.
val server_recv_message : server_session -> string -> server_session
Receives the next message from the client
val server_protocol_key : server_session -> string option
The 128-bit protocol key for encrypting messages. This is available as soon as the second client message has been received.
val server_channel_binding : server_session -> cb
Returns the channel binding requirement. It is up to the application to enforce the binding. This information is available as soon as the second client message has been received
val server_user_name : server_session -> string option
The user name as transmitted from the client. This is returned here even before the authentication is completed!
val server_authz_name : server_session -> string option
The authorization name as transmitted from the client. This is returned here even before the authentication is completed!
val server_export : server_session -> string
val server_import : string -> server_session
val server_import_any : string ->
(string -> credentials) -> server_session
val server_import_any2 : string ->
(string -> string -> credentials) ->
server_session
Exports a server session as string, and imports the string again.
server_import
can only import established sessions.
server_import_any
can also import unfinished sessions, but one needs
to pass the authentication function as for server_create_session
.
server_import_any2
uses the modified auth function as in
server_create_session2
.
val server_prop : server_session -> string -> string
Returns a property of the server (or Not_found) - see also client_prop
above:
type
specific_keys = {
|
kc : |
|
ke : |
|
ki : |
The specific keys to use
module AES_CTS:sig
..end
This module implements AES in Ciphertext Stealing mode (see RFC 3962)
module Cryptosystem:sig
..end
This is the cryptosystem as defined in RFC 3961, so far needed here.
module Debug:sig
..end