Subject: KMF Certificate Name mapping extensions [PSARC/2010/177 FastTrack timeout 05/25/2010] To: PSARC-ext@Sun.Com Cc: jan.pechanec@sun.com Bcc: one-pager-list@sac.sfbay one-pager-log@sac.sfbay sac-bar@sac.sfbay Template Version: @(#)sac_nextcase 1.70 03/30/10 SMI This information is Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 1. Introduction 1.1. Project/Component Working Name: KMF Certificate Name mapping extensions 1.2. Name of Document Author/Supplier: Author: Jan Pechanec 1.3 Date of This Document: 18 May, 2010 4. Technical Description Certificate to name mapping extension to the Key Management Framework ===================================================================== Motivation ---------- When applications work with user or host certificates the validating side needs to find out which user or which host was the certificate issued for. The most commonly used way may be to put the name into the Common Name (CN) attribute. However, there are other ways of supplying the information, be it rfc822Name, iPAddress, or dNSName from the subjectAltName extension. We can also hash the certificate and find the mapped name in an external database. We might use the whole DN string to map the certificate to a name using an external database again. Another use might be also to strip the domain name from rfc822Name to get a user name, or we might want to ignore case sensitiveness. We might also somehow translate information harvested from the certificate to something else following a merge of two administrative domains, thus solving name space conflicts between them. The list of possible uses could continue. All of this is quite independent of the application and to avoid a situation where every application does its own certficate to name mapping, we think that KMF would be the best place to put this functionality. What's more, we think that this feature should be extensible and Solaris itself should provide a few basic mapping schemes. Who needs that now ------------------ SSH/X.509 project (6357779 SSHv2 x.509 support desired) needs a way to map a certificate to a hostname for the server authentication, and to map a certificate to a user name for the user authentication. Overview -------- The mapping scheme in effect would be tied to the KMF session. If a different mapping should be used for the session, the mapping must be reinitialized. It's enough to initialize a new mapping, KMF will automatically finalize the current one if mapper supports the finalize function. The mapping itself corresponds to an object called a "mapper". It is a shared object that KMF would dlopen() upon mapping initialization. The mapper object would provide 5 functions. The set would contain a function to initialize the mapping, map a certificate to a name, a convenience function that would provide an answer if the certificate matches a name provided, a finalization function, and a function to provide more information should other functions result in an error internal to the specific mapper. Mapper internals must be designed so that the same mapper can be used from multiple KMF sessions from the same process. The set of these 5 functions would be an interface between the KMF and the mappers. The programmer using the libkmf(3lib) library would use 5 functions correspending to the mapper fuctions described above. The mapper programmer can also use 4 more KMF functions that work with the mapper state as part of the libkmf(3lib). Relevant CRs ------------ 6942888 KMF should provide certificate to name mapping capabilities 6950204 STC-2 KMF test suite need to test certificate to name mapping Delivering mappers ------------------ Listing mappers is not part of this ARC case and will not be part of the initial push. While all the functionality has been already tested against the CN mapper prototype (mapping a certificate to the contents of the Common Name attribute), we will deliver mappers in separate pushes. New tests for kmfcfg(1) will be part of the 1st phase of the project, tests for cert-to-name mapping functions will be part of the 2nd phase which will deliver the CN mapper. KMF API extension ----------------- There are 9 new functions representing the public interface an application or mapper programmer could use. Note that the existing KMF_DATA structure is defined like this: typedef struct kmf_data { size_t Length; /* in bytes */ uchar_t *Data; } KMF_DATA; KMF_RETURN kmf_cert_to_name_mapping_initialize( KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) supported attributes are all (char *) pointers to ASCII strings: KMF_MAPPER_NAME_ATTR - mapper name (kmf_mapper_.so) KMF_DIRPATH_ATTR - default is /lib/crypto where all existing KMF plugins already reside KMF_MAPPER_FILENAME_ATTR - full path to the mapper shared object, overrides the name and directory KMF_MAPPER_OPTIONS_ATTR - mapper specific options in a string. KMF does not know the inner structure of the string. However, we expect a comma separated list of option names will be used. The function is called once internally when the policy is processed in the "kmf_initialize" function. If the policy has no mapping set the call has no effect on KMF. If the consumer needs to use a different mapping later, this function can be called with the proper attributes and the old one mapper will be closed and the new one opened. The name, mapper path, and options in the policy database can be always overridden using the attributes. Also, the directory attribute is always tied to the specific mapper name. If only a mapper name is set in the function attributes, the default KMF mapper directory will be used no matter how the mapper directory is set in the policy file. Re-initializing an already initialized mapper is allowed and the mapper can get new options by that, for example. The init function from the mapper is always called again if it does exist. If initialization of a mapper fails while there was already an initialized mapper, the state of the current mapping is undefined. The application is expected to initialize the mapping again before proceeding. return values: KMF_OK - OK KMF_ERR_BAD_PARAMETER - handle is NULL or some attributes are missing, either in the attrlist or in the policy file KMF_ERR_MEMORY - out of memory during memory allocation KMF_ERR_MAPPER_OPEN - dlopen() failed KMF_ERR_MAPPER_NOT_FOUND - mapper not found or set KMF_ERR_INTERNAL - an error occured in the mapper module; a missing mapper config file or badly formatted config settings string, for example - in this case, user can call kmf_get_mapper_error_str() to get a more specific error message KMF_RETURN kmf_cert_to_name_mapping_finalize(KMF_HANDLE_T handle) Frees up any local memory in the KMF policy handle associated with the mapper and calls "dlclose()" on the mappers descriptor. If the mapper has a finalize function called "mapper_finalize", this function will look it up and call it prior to calling "dlclose()". return values: KMF_OK - OK KMF_RETURN kmf_get_mapper_error_str(KMF_HANDLE_T handle, char **errstr) If the mapper returns KMF_ERR_INTERNAL the application may ask for the internal mapper error string. The caller is expected to free the returned string later with kmf_free_str(). KMF_RETURN kmf_map_cert_to_name( KMF_HANDLE_T handle, KMF_DATA *cert, KMF_DATA *name); Maps the certificate to a name. We intentionally use KMF_DATA for the output "name" parameter so that the certificate can be mapped to any data, possibly even binary. The mapper fills out its Data and Length fields. The caller is responsible for freeing the Data buffer when done using it. The "name" output parameter will be zeroized in case of any error, effectively returning a NULL string. return values: KMF_OK - OK KMF_ERR_BAD_PARAMETER - handle is NULL KMF_ERR_MAPPER_NOT_FOUND - same as in the init function KMF_ERR_FUNCTION_NOT_FOUND - the mapping function not found in the mapper KMF_ERR_INTERNAL - same as in the init function KMF_ERR_MEMORY - memory shortage in the KMF or the mapper function KMF_ERR_MAPPING_FAILED - generic error when the module doesn't want to provide more information through the KMF_ERR_INTERNAL error KMF_ERR_BAD_CERT_FORMAT - is not cert in ASN.1 format KMF_RETURN kmf_match_cert_to_name( KMF_HANDLE_T handle, KMF_DATA *cert, KMF_DATA *name_to_match, KMF_DATA *mapped_name) The function returns KMF_OK if the certificate matches the name in "name_to_match". It also provides the mapped name if "mapped_name" is not NULL. This should make the user's life easier - if the match failure is not expected, the "mapped_name" can be immediatelly used in the debug, warning, or error message. Technically, we could have just used the map function. For mapping, we would ignore the KMF_ERR_CERT_TO_NAME_NO_MATCH error code. However, it's cleaner to separate those. We expect that internally in the mappers the match function will be implemented mostly using the mapping function anyway. return values: KMF_OK - the certificate matches the provided name KMF_ERR_NAME_NOT_MATCHED - mapper must return this return code when the certificate does not match the provided name Other error codes same as in kmf_map_cert_to_name(). The next four functions are helper functions that work with the mapper state related to the KMF handle. We expect that users can write their own mappers but since the KMF session handle is an opaque structure, we must provide a way to access the last mapper internal error code and the options. Both are tied to the KMF session so it's logical to store them together with the KMF session handle. void kmf_set_mapper_lasterror(KMF_HANDLE_T handle, uint32_t err); uint32_t kmf_get_mapper_lasterror(KMF_HANDLE_T handle); Note that the next 2 functions are not about handling the option string from the policy database or from the attribute to the kmf_cert_to_name_mapping_initialize function. It is solely about keeping the pointer to the mapper-specific option info with the KMF session handle. void kmf_set_mapper_options(KMF_HANDLE_T h, void *options) void *kmf_get_mapper_options(KMF_HANDLE_T h); KMF-Mapper API interface ------------------------ The naming convention for mappers is "kmf_mapper_%s.so". For example, the CN mapper will use kmf_mapper_cn.so. By default, the mapper libraries will be installed in the same directory as other KMF plugins (/lib/crypto and /lib/crypto/$ISA). However, the policy definition (mapper-directory) or the KMF_DIRPATH_ATTR attribute to the kmf_cert_to_name_mapping_initialize function may specify an alternate location. Every mapper can provide up to 5 functions to be used from KMF. From those 5, 3 are mandatory. Since the mappers are more or less part of KMF they should make use of KMF as much as possible. The mapper interface to KMF is through the following functions: KMF_RETURN mapper_initialize(KMF_HANDLE_T h, int num_attr, char *options) - mapper library initialization function. The attribute "options" delivers the current options whether those came from the attribute to the kmf_cert_to_name_mapping_initialize() function or from the policy database. - this function is NOT mandatory void mapper_finalize(KMF_HANDLE_T h) - mapper library cleanup function - this function is NOT mandatory KMF_RETURN mapper_map_cert_to_name(KMF_HANDLE *handle, KMF_DATA *cert, KMF_DATA *name); - maps the certificate to a name KMF_RETURN mapper_match_cert_to_name(KMF_HANDLE_T h, KMF_DATA *cert, KMF_DATA *name_to_match, KMF_DATA *mapped_name) - tries to match the provided name to a certificate - if mapped_name name is not NULL, the function allocates memory for Data, copies the mapped name there, and updates the Lenght. The name should be NULL terminated if it is a string. mapper_get_error_string(KMF_HANDLE *handle, char **errstr) - translate local mapper-specific error codes into human readable text for logging and error messages. - the local mapper function should allocate the string and return its pointer to the caller. The caller is responsible for freeing it using kmf_free_str(). See respective KMF functions for the list of expected return values. kmfcfg(1) --------- "create" and "modify" subcommands will be extended with: mapper-name mapper-directory mapper-path mapper-options "mapper-options" is opaque to KMF, its limit is 255 characters and its contents restricted to US ASCII (0-127). "mapper-options" is expected to contain comma separated list of attributes that affect the mapping operation, for example: mapper-options="ignorecase,ignoredomain" For some mappers, the "mapper-options" may be expected to contain attr/value pairs such as: config=/usr/local/kmf/mappers/xxx-mapping.conf The exact structure of mapper-options attribute is enforced by the mapper library, not KMF or the KMF Policy engine. kmfpolicy.dtd ------------- Will be extended the way that the policy file can contain something like this: or, Attributes "mapper-path" and "mapper-name" (possibly with mapper-directory) are mutually exclusive, kmfcfg(1) will not allow users to set both. The "mapper-name" contains the name that is to replace the %s substring in "(/lib/crypto/)kmf_mapper_%s.so". "mapper-options" %attribute can be present only if "mapper-path" or "mapper-name" is present. "mapper-directory" can be present only if "mapper-name" is present. The mappers provided by Solaris ------------------------------- Such mappers are not part of this case. If an ARC case (or cases) for those are needed they will be filed separatedly. We plan to deliver the CN mapper as the 1st one. Man page changes ---------------- 6951981 libkmf(3lib) will need an update after the delivery of 6942888 libkmf(3lib) only contains a list of public functions. We will add all 9 functions there. kmf_cert_to_name_mapping_finalize kmf_cert_to_name_mapping_initialize kmf_get_mapper_error_str kmf_get_mapper_lasterror kmf_get_mapper_options kmf_map_cert_to_name kmf_match_cert_to_name kmf_set_mapper_lasterror kmf_set_mapper_options 6951979 kmfcfg(1) will need an update after the delivery of 6942888 --- kmfcfg.1 Thu May 13 14:47:43 2010 +++ kmfcfg.1.new Thu May 13 14:47:43 2010 @@ -66,6 +66,10 @@ ipsecUser | timeStamping | OCSPSigning],[...] [ekuoids=OID,OID,OID...] + [mapper-name=name of the mapper] + [mapper-dir=dir where mapper library resides] + [mapper-path=full pathname of mapper library] + [mapper-options=mapper options] The create subcommand supports the following options: @@ -283,6 +287,30 @@ attributes need to be set, if the value of ignore- trust-anchor attribute is false. + mapper-name=name + mapper-dir=directory + mapper-path=path + mapper-options=options + + These four options support the certificate to + name mapping. mapper-name provides the name of + the mapper. For example, the "cn" name + represents the mapper object kmf_mapper_cn.so. + mapper-dir overrides the default mapper directory + /lib/crypto. mapper-path specifies the full path + to the mapper object. mapper-options is an ASCII + only string of maximum of 255 bytes long. Its + format is mapper specific but mappers are + expected to accept a comma separated list of + options, for example "ignorecase,ignoredomain". + mapper-path and mapper-name are mutually + exclusive. mapper-dir can be set only if + mapper-name is set. mapper-options can be set + only if mapper-name or mapper-path is set. Trying + to use any of the above mentioned incorrect + settings will result in an error and the policy + database will not be modified. + delete Deletes any policy matching the indicated policy name. @@ -430,6 +458,10 @@ OCSPSigning],[...] [ekuoids=OID,OID,OID] [eku-none=true|false] + [mapper-name=name of the mapper] + [mapper-dir=dir where mapper library resides] + [mapper-path=full pathname of mapper library] + [mapper-options=mapper options] The modify subcommand supports many of the same options as the create subcommand. For descriptions of shared @@ -488,6 +520,12 @@ database cannot be modi- fied. + mapper-name=name, mapper-dir=directory, mapper-path=path + mapper-options=options + See the "create" + subcommand for more + information. + Plugin Subcommands install keystore=keystore_name modulepath=pathname\ [option=option_str] The mappers will have their own manual page. We will deliver documentation together with the mappers. Interface stability ------------------- Private Release Binding --------------- Patch 6. Resources and Schedule 6.4. Steering Committee requested information 6.4.1. Consolidation C-team Name: ON 6.5. ARC review type: FastTrack 6.6. ARC Exposure: open