For SASL credentials are specified as a list
(string * string * (string * string) list) list
which looks complicated and needs some explanations. Basically, this list presents the authentication mechanism a number of encodings for the same secret. The mechanism can then pick the encoding it can process best. Every encoding of the secret is a tuple
(type, data, params)
where type
and data
are strings, and params
is a
(string * string) list) list
with (name,value)
pairs.
Why supporting several encodings? First, there may be huge differences in
the speed of the authentication mechanism, in particular when you compare
a cleartext password pw
with the version of pw
that is really used in
the mechanism, which is often a function of the password kdf(pw)
(kdf =
key derivation function). These functions are designed to be slow.
Second, there may be a security benefit when a password database needs not
to store pw
, but can store kdf(pw)
, in particular on the server side.
All mechanisms support:
type = "password"
: The data
string is the raw, unprocessed password.
Note that many mechanisms require that the password is a UTF-8 string,
and some even request a certain UTF-8 form (the so-called string preparation
of the password). The password type does not take any parameters.
type = "authpassword-SCRAM-SHA-1"
: The data
string is the "stored
password" for the mechanism SCRAM-SHA-1. There is one parameter "info"
containing the iteration count and the salt. These two strings are defined
in RFC-5803. OCamlnet uses here intentionally the same format as is
commonly used in LDAP servers for storing SCRAM credentials. See
Netmech_scram_sasl.SCRAM
for sample code how to generate this encoding.
OCamlnet tries to support types conforming either to the pattern defined
in RFC 3112 or RFC 2307. See
Netsys_sasl_types.SASL_MECHANISM.init_credentials
for details.
All user names and passwords for SASL mechanisms must be given in UTF-8.
Moreover, there is a special algorithm normalizing characters where
Unicode permits several ways of encoding them: SASLprep. In OCamlnet,
SASLprep is implemented by Netsaslprep
.
Newer SASL mechanisms require that user names and passwords go through SASLprep. Although older mechansims do not strictly require this yet, it is often also a good idea to apply SASLprep nevertheless, as all mechanisms access the same password database.
OCamlnet does not automatically call SASLprep. Callers of the SASL mechanisms should do that before the user names and passwords reach the mechanism implementations, e.g.
let creds =
[ "password", Netsaslprep.saslprep pw, [] ]
The reason is that SASLprep is fairly expensive, and should best only called once when several mechanisms have been enabled.
The (X.509) credentials exist here in two "flavors", namely certificates and private keys.
Representations in RAM
`DER
. Netx509.x509_certificate
objects.
The parser function is Netx509.x509_certificate_from_DER
.`DER
is also used for these lists. There is,
however, no parser callable from OCaml. (Inside GnuTLS there is a parser.)`RSA
, `DSA
, `EC
, `PKCS8
and
`PKCS8_encrypted
are attached to strings with the respective formats.
As of now, no parsers for any of these formats are callable from
OCaml. Important note: Encrypted keys are only supported via PKCS-8.
If you have a PEM file with a "DEK-Info" header, this file cannot be
read in. Convert it to PKCS-8 first with an external tool.As mentioned, there is always a container format:
Netascii_armor
. These are the objects (per header string):
Note that OCamlnet does not contain any utility for generating these
files. You can use the GnuTLS utility certtool
or the openssl
command.
Besides X.509 credentials, there are also other types (e.g. SRP or OpenPGP credentials) that be used with TLS. This is quite uncommon, though, and should only be used in special situations. At present, such alternate authentication methods are not supported in these TLS bindings.
You can usually pass credentials as pairs string * oid
where the
string contain the data formatted according to the rules for the OID.
At present, there are no helper functions to support any type of OID better that is possible here.
To be written