changeset 12611:d9f75b73c5fd

PSARC/2010/177 KMF Certificate Name mapping extensions PSARC/2010/178 KMF Common Name Mapper 6942888 KMF should provide certificate to name mapping capabilities 6949176 KMF cert-to-name mapping framework needs a CN mapper
author Jan Pechanec <Jan.Pechanec@Sun.COM>
date Fri, 11 Jun 2010 01:25:07 -0700
parents 5daa5746f6ae
children 29da3d2c2ccb
files usr/src/cmd/cmd-crypto/kmfcfg/create.c usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd usr/src/cmd/cmd-crypto/kmfcfg/list.c usr/src/cmd/cmd-crypto/kmfcfg/modify.c usr/src/lib/libkmf/Makefile usr/src/lib/libkmf/include/kmfapi.h usr/src/lib/libkmf/include/kmfapiP.h usr/src/lib/libkmf/include/kmfmapper.h usr/src/lib/libkmf/include/kmfpolicy.h usr/src/lib/libkmf/include/kmftypes.h usr/src/lib/libkmf/libkmf/Makefile.com usr/src/lib/libkmf/libkmf/common/generalop.c usr/src/lib/libkmf/libkmf/common/mapfile-vers usr/src/lib/libkmf/libkmf/common/mapping.c usr/src/lib/libkmf/libkmf/common/policy.c usr/src/lib/libkmf/mappers/Makefile usr/src/lib/libkmf/mappers/kmf_mapper_cn/Makefile usr/src/lib/libkmf/mappers/kmf_mapper_cn/Makefile.com usr/src/lib/libkmf/mappers/kmf_mapper_cn/amd64/Makefile usr/src/lib/libkmf/mappers/kmf_mapper_cn/common/mapfile-vers usr/src/lib/libkmf/mappers/kmf_mapper_cn/common/mapper_cn.c usr/src/lib/libkmf/mappers/kmf_mapper_cn/i386/Makefile usr/src/lib/libkmf/mappers/kmf_mapper_cn/sparc/Makefile usr/src/lib/libkmf/mappers/kmf_mapper_cn/sparcv9/Makefile usr/src/pkg/manifests/system-library.mf
diffstat 26 files changed, 1375 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/cmd-crypto/kmfcfg/create.c	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/create.c	Fri Jun 11 01:25:07 2010 -0700
@@ -18,12 +18,9 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <stdio.h>
 #include <strings.h>
 #include <ctype.h>
@@ -71,6 +68,10 @@
 	    "X:(crl-proxy)"
 	    "S:(crl-ignore-crl-sign)"
 	    "D:(crl-ignore-crl-date)"
+	    "m:(mapper-name)"
+	    "M:(mapper-directory)"
+	    "Q:(mapper-pathname)"
+	    "q:(mapper-options)"
 	    "u:(keyusage)"
 	    "E:(ekunames)"
 	    "O:(ekuoids)")) != EOF) {
@@ -374,6 +375,39 @@
 					rv = KC_ERR_USAGE;
 				}
 				break;
+			case 'm':
+				plc.mapper.mapname = get_string(optarg_av, &rv);
+				if (plc.mapper.mapname == NULL) {
+					(void) fprintf(stderr,
+					    gettext("Error mapper-name "
+					    "input.\n"));
+				}
+				break;
+			case 'M':
+				plc.mapper.dir = get_string(optarg_av, &rv);
+				if (plc.mapper.dir == NULL) {
+					(void) fprintf(stderr,
+					    gettext("Error mapper-dir "
+					    "input.\n"));
+				}
+				break;
+			case 'Q':
+				plc.mapper.pathname = get_string(optarg_av,
+				    &rv);
+				if (plc.mapper.pathname == NULL) {
+					(void) fprintf(stderr,
+					    gettext("Error mapper-pathname "
+					    "input.\n"));
+				}
+				break;
+			case 'q':
+				plc.mapper.options = get_string(optarg_av, &rv);
+				if (plc.mapper.options == NULL) {
+					(void) fprintf(stderr,
+					    gettext("Error mapper-options "
+					    "input.\n"));
+				}
+				break;
 			default:
 				(void) fprintf(stderr,
 				    gettext("Error input option.\n"));
@@ -463,6 +497,23 @@
 	}
 
 	/*
+	 * Setting mapper-name (with optional mapper-dir) and mapper-pathname is
+	 * mutually exclusive. Also, you cannot set options only, you need the
+	 * name or pathname, and you can set the directory only with the name,
+	 * not the pathname.
+	 */
+	if ((plc.mapper.mapname != NULL && plc.mapper.pathname != NULL) ||
+	    (plc.mapper.dir != NULL && plc.mapper.pathname != NULL) ||
+	    (plc.mapper.dir != NULL && plc.mapper.mapname == NULL) ||
+	    (plc.mapper.options != NULL && plc.mapper.mapname == NULL &&
+	    plc.mapper.pathname == NULL)) {
+		(void) fprintf(stderr,
+		    gettext("Error in mapper input options\n"));
+		rv = KC_ERR_USAGE;
+		goto out;
+	}
+
+	/*
 	 * If any CRL attribute is set, turn on the CRL checking flag.
 	 */
 	if (crl_set_attr > 0)
--- a/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c	Fri Jun 11 01:25:07 2010 -0700
@@ -17,13 +17,9 @@
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
+ *
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
-/*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include <stdio.h>
 #include <strings.h>
@@ -94,7 +90,11 @@
 		"\t\tipsecEndSystem | ipsecTunnel |\n\t"
 		"\t\tipsecUser | timeStamping |\n\t"
 		"\t\tOCSPSigning],[...]\n"
-		"\t\t[ekuoids=OID,OID,OID...]\n" },
+		"\t\t[ekuoids=OID,OID,OID...]\n"
+		"\t\t[mapper-name=name of mapper library]\n"
+		"\t\t[mapper-directory=dir where mapper library resides]\n"
+		"\t\t[mapper-path=full pathname of mapper library]\n"
+		"\t\t[mapper-options=mapper options]\n"},
 	{ "modify",	kc_modify,
 		"modify [dbfile=dbfile] policy=policyname\n"
 		"\t\t[ignore-date=true|false]\n"
@@ -130,6 +130,10 @@
 		"\t\tOCSPSigning],[...]\n"
 		"\t\t[ekuoids=OID,OID,OID...]\n"
 		"\t\t[eku-none=true|false]\n\n"
+		"\t\t[mapper-name=name of mapper library]\n"
+		"\t\t[mapper-directory=dir where mapper library resides]\n"
+		"\t\t[mapper-path=full pathname of mapper library]\n"
+		"\t\t[mapper-options=mapper options]\n"
 		"\tmodify plugin keystore=keystorename option=optionstring\n"},
 
 	{ "import",	kc_import, "import [dbfile=dbfile] policy=policyname "
--- a/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd	Fri Jun 11 01:25:07 2010 -0700
@@ -1,8 +1,7 @@
 <?xml version='1.0' encoding='UTF-8' ?>
 
 <!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
+ Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
 
  CDDL HEADER START
 
@@ -22,8 +21,6 @@
  information: Portions Copyright [yyyy] [name of copyright owner]
 
  CDDL HEADER END
-
-	ident	"%Z%%M%	%I%	%E% SMI"
 -->
 
 <!--Element Definitions-->
@@ -31,7 +28,7 @@
 <!ELEMENT kmf-policy-db (kmf-policy*)>
 <!ATTLIST kmf-policy-db allow-local-files (TRUE|FALSE) #IMPLIED>
 
-<!ELEMENT kmf-policy (validation-methods, key-usage-set?,  ext-key-usage?)>
+<!ELEMENT kmf-policy (validation-methods, key-usage-set?,  ext-key-usage?, cert-to-name-mapping?)>
 <!ATTLIST kmf-policy name CDATA #REQUIRED>
 <!ATTLIST kmf-policy ignore-date (TRUE|FALSE) #IMPLIED>
 <!ATTLIST kmf-policy ignore-unknown-eku (TRUE|FALSE) #IMPLIED>
@@ -82,3 +79,9 @@
 		timeStamping | OCSPSigning) #IMPLIED >
 <!ELEMENT eku-oid EMPTY>
 <!ATTLIST eku-oid oid CDATA #IMPLIED>
+
+<!ELEMENT cert-to-name-mapping ANY>
+<!ATTLIST cert-to-name-mapping mapper-name CDATA #IMPLIED>
+<!ATTLIST cert-to-name-mapping mapper-directory CDATA #IMPLIED>
+<!ATTLIST cert-to-name-mapping mapper-pathname CDATA #IMPLIED>
+<!ATTLIST cert-to-name-mapping mapper-options CDATA #IMPLIED>
--- a/usr/src/cmd/cmd-crypto/kmfcfg/list.c	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/list.c	Fri Jun 11 01:25:07 2010 -0700
@@ -18,12 +18,9 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <stdio.h>
 #include <strings.h>
 #include <ctype.h>
@@ -161,6 +158,14 @@
 		    plc->validation_info.crl_info.ignore_crl_date ?
 		    gettext("true") : gettext("false"));
 	}
+	(void) printf(gettext("Mapper name: %s\n"),
+	    plc->mapper.mapname ? plc->mapper.mapname : "<null>");
+	(void) printf(gettext("Mapper pathname: %s\n"),
+	    plc->mapper.pathname ? plc->mapper.pathname : "<null>");
+	(void) printf(gettext("Mapper directory: %s\n"),
+	    plc->mapper.dir ? plc->mapper.dir : "<null>");
+	(void) printf(gettext("Mapper options: %s\n"),
+	    plc->mapper.options ? plc->mapper.options : "<null>");
 
 	(void) printf("\n");
 }
--- a/usr/src/cmd/cmd-crypto/kmfcfg/modify.c	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/modify.c	Fri Jun 11 01:25:07 2010 -0700
@@ -18,12 +18,9 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <stdio.h>
 #include <strings.h>
 #include <ctype.h>
@@ -61,9 +58,17 @@
 #define	KC_KEYUSAGE_NONE		0x0400000
 #define	KC_EKUS				0x0800000
 #define	KC_EKUS_NONE			0x1000000
+#define	KC_MAPPER_OPTIONS		0x2000000
 
 static int err; /* To store errno which may be overwritten by gettext() */
 
+#define	UPDATE_IF_DIFFERENT(old, new) \
+	if ((old != NULL && new != NULL && strcmp(old, new) != 0) || \
+	    (old == NULL && new != NULL)) { \
+		if (old != NULL) \
+			free(old); \
+		old = new; \
+	}
 
 int
 kc_modify_policy(int argc, char *argv[])
@@ -74,6 +79,9 @@
 	extern int	optind_av;
 	extern char	*optarg_av;
 	char		*filename = NULL;
+	char		*mapper_name = NULL;
+	char		*mapper_dir = NULL;
+	char		*mapper_pathname = NULL;
 	uint32_t	flags = 0;
 	boolean_t	ocsp_none_opt = B_FALSE;
 	boolean_t	crl_none_opt = B_FALSE;
@@ -114,6 +122,10 @@
 	    "Y:(keyusage-none)"
 	    "E:(ekunames)"
 	    "O:(ekuoids)"
+	    "m:(mapper-name)"
+	    "M:(mapper-directory)"
+	    "Q:(mapper-pathname)"
+	    "q:(mapper-options)"
 	    "Z:(eku-none)")) != EOF) {
 		switch (opt) {
 			case 'i':
@@ -485,6 +497,35 @@
 					flags |= KC_EKUS_NONE;
 				}
 				break;
+			case 'm':
+				mapper_name = get_string(optarg_av, &rv);
+				if (mapper_name == NULL) {
+					(void) fprintf(stderr,
+					    gettext("Error mapper-name "
+					    "input.\n"));
+				}
+				break;
+			case 'M':
+				mapper_dir = get_string(optarg_av, &rv);
+				if (mapper_dir == NULL) {
+					(void) fprintf(stderr,
+					    gettext("Error mapper-directory "
+					    "input.\n"));
+				}
+				break;
+			case 'Q':
+				mapper_pathname = get_string(optarg_av, &rv);
+				if (mapper_pathname == NULL) {
+					(void) fprintf(stderr,
+					    gettext("Error mapper-pathname "
+					    "input.\n"));
+				}
+				break;
+			case 'q':
+				plc.mapper.options = get_string(optarg_av, &rv);
+				rv = 0; /* its ok for this to be NULL */
+				flags |= KC_MAPPER_OPTIONS;
+				break;
 			default:
 				(void) fprintf(stderr,
 				    gettext("Error input option.\n"));
@@ -577,6 +618,55 @@
 		oplc.ta_serial = plc.ta_serial;
 	}
 
+	/*
+	 * There are some combinations of attributes that are not valid.
+	 *
+	 * First, setting mapper-name (with optional mapper-directory) and
+	 * mapper-pathname is mutually exclusive.
+	 */
+	if ((mapper_name != NULL && mapper_pathname != NULL) ||
+	    (mapper_name != NULL && oplc.mapper.pathname != NULL) ||
+	    (mapper_pathname != NULL && oplc.mapper.mapname != NULL) ||
+	    /* Mapper directory can be set only if mapper name is set. */
+	    (mapper_dir != NULL && mapper_pathname != NULL) ||
+	    (mapper_dir != NULL && mapper_name == NULL &&
+	    oplc.mapper.mapname == NULL) ||
+	    (mapper_dir != NULL && oplc.mapper.pathname != NULL) ||
+	    /* Options can be set only if mapper name or pathname is set. */
+	    ((plc.mapper.options != NULL || oplc.mapper.options != NULL) &&
+	    (mapper_name == NULL && oplc.mapper.mapname == NULL &&
+	    mapper_pathname == NULL && oplc.mapper.pathname == NULL))) {
+		(void) fprintf(stderr,
+		    gettext("Error in mapper input options\n"));
+		if (mapper_name != NULL)
+			free(mapper_name);
+		if (mapper_pathname != NULL)
+			free(mapper_pathname);
+		if (mapper_dir != NULL)
+			free(mapper_dir);
+		if (flags & KC_MAPPER_OPTIONS && plc.mapper.options != NULL)
+			free(plc.mapper.options);
+		rv = KC_ERR_USAGE;
+		goto out;
+	} else {
+		if (mapper_name != NULL)
+			plc.mapper.mapname = mapper_name;
+		if (mapper_pathname != NULL)
+			plc.mapper.pathname = mapper_pathname;
+		if (mapper_dir != NULL)
+			plc.mapper.dir = mapper_dir;
+	}
+
+	UPDATE_IF_DIFFERENT(oplc.mapper.mapname, plc.mapper.mapname);
+	UPDATE_IF_DIFFERENT(oplc.mapper.pathname, plc.mapper.pathname);
+	UPDATE_IF_DIFFERENT(oplc.mapper.dir, plc.mapper.dir);
+
+	if (flags & KC_MAPPER_OPTIONS) {
+		if (oplc.mapper.options != NULL)
+			free(oplc.mapper.options);
+		oplc.mapper.options = plc.mapper.options;
+	}
+
 	/* Update the OCSP policy */
 	if (ocsp_none_opt == B_TRUE) {
 		if (ocsp_set_attr > 0) {
@@ -849,7 +939,6 @@
 	return (rv);
 }
 
-
 static int
 kc_modify_plugin(int argc, char *argv[])
 {
--- a/usr/src/lib/libkmf/Makefile	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/lib/libkmf/Makefile	Fri Jun 11 01:25:07 2010 -0700
@@ -18,10 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
+# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 # KMF Prototype Makefile
 #
@@ -30,7 +27,7 @@
 LIBRARY=	libkmf.a
 VERS=		1
 
-SUBDIRS		=	ber_der libkmf plugins
+SUBDIRS	=	ber_der libkmf plugins mappers
 
 HDRS=	kmfapi.h kmftypes.h
 HDRDIR= include
--- a/usr/src/lib/libkmf/include/kmfapi.h	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/lib/libkmf/include/kmfapi.h	Fri Jun 11 01:25:07 2010 -0700
@@ -17,11 +17,8 @@
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
- */
-/*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
  *
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  *
  * Constant definitions and function prototypes for the KMF library.
  * Commonly used data types are defined in "kmftypes.h".
@@ -340,6 +337,25 @@
 void kmf_set_attr_at_index(KMF_ATTRIBUTE *, int, KMF_ATTR_TYPE,
 	void *, uint32_t);
 
+/*
+ * Certificate to name mapping functions.
+ */
+KMF_RETURN kmf_cert_to_name_mapping_initialize(KMF_HANDLE_T, int,
+	KMF_ATTRIBUTE *);
+KMF_RETURN kmf_cert_to_name_mapping_finalize(KMF_HANDLE_T);
+KMF_RETURN kmf_map_cert_to_name(KMF_HANDLE_T, KMF_DATA *, KMF_DATA *);
+KMF_RETURN kmf_match_cert_to_name(KMF_HANDLE_T, KMF_DATA *, KMF_DATA *,
+	KMF_DATA *);
+KMF_RETURN kmf_get_mapper_error_str(KMF_HANDLE_T, char **);
+/*
+ * Helper functions for handling the mapper internal state. They are part of the
+ * public interface, too.
+ */
+void kmf_set_mapper_lasterror(KMF_HANDLE_T, uint32_t);
+uint32_t kmf_get_mapper_lasterror(KMF_HANDLE_T);
+void kmf_set_mapper_options(KMF_HANDLE_T, void *);
+void *kmf_get_mapper_options(KMF_HANDLE_T);
+
 #ifdef __cplusplus
 }
 #endif
--- a/usr/src/lib/libkmf/include/kmfapiP.h	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/lib/libkmf/include/kmfapiP.h	Fri Jun 11 01:25:07 2010 -0700
@@ -17,10 +17,8 @@
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
- */
-/*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ *
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 #ifndef _KMFAPIP_H
 #define	_KMFAPIP_H
@@ -182,6 +180,7 @@
 	KMF_ERROR		lasterr;
 	KMF_POLICY_RECORD	*policy;
 	KMF_PLUGIN_LIST		*plugins;
+	KMF_MAPPER_STATE	*mapstate;
 } KMF_HANDLE;
 
 #define	CLEAR_ERROR(h, rv) { \
@@ -348,8 +347,9 @@
 extern boolean_t is_valid_keystore_type(KMF_KEYSTORE_TYPE);
 extern KMF_BOOL is_eku_present(KMF_X509EXT_EKU *, KMF_OID *);
 extern KMF_RETURN parse_eku_data(const KMF_DATA *, KMF_X509EXT_EKU *);
-extern KMF_RETURN
-copy_extension_data(KMF_X509_EXTENSION *, KMF_X509_EXTENSION *);
+extern KMF_RETURN copy_extension_data(KMF_X509_EXTENSION *,
+	KMF_X509_EXTENSION *);
+extern char *get_mapper_pathname(char *, char *);
 
 #ifdef __cplusplus
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/include/kmfmapper.h	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,81 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * This is a private header file for the KMF certificate to name mapping
+ * framework.
+ */
+#ifndef _KMFMAPPER_H
+#define	_KMFMAPPER_H
+
+#pragma ident	"@(#)kmfmapper.h	1.1	08/02/27 SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define	MAPPER_NAME_TEMPLATE "kmf_mapper_%s.so.1"
+
+#define	MAPPER_ERROR_STRING_FUNCTION "mapper_get_error_str"
+#define	MAP_CERT_TO_NAME_FUNCTION "mapper_map_cert_to_name"
+#define	MATCH_CERT_TO_NAME_FUNCTION "mapper_match_cert_to_name"
+#define	MAPPER_FINISH_FUNCTION "mapper_finalize"
+#define	MAPPER_INIT_FUNCTION "mapper_initialize"
+
+/* KMF mapper policy record. */
+typedef struct {
+	/*
+	 * Those four attributes are initialized from the policy database and
+	 * are not to be changed for the life of the KMF session.
+	 */
+	char *mapname;
+	char *options;
+	char *pathname;
+	char *dir;
+	/* Current mapper. */
+	void *dldesc;
+	/*
+	 * The presently open mapper pathname and options. Can be based on the
+	 * policy attributes or attributes provided directly to the
+	 * kmf_cert_to_name_mapping_init(), thus overriding the policy settings.
+	 */
+	char *curpathname;
+	char *curoptions;
+} KMF_MAPPER_RECORD;
+
+/* KMF mapper state record. */
+typedef struct {
+	/*
+	 * (Processed) options. Transparent to KMF. Each mapper can store its
+	 * data there since options can be unique to every KMF handle.
+	 */
+	void *options;
+	/*
+	 * If the mapper returns KMF_ERR_INTERNAL the application may ask for
+	 * the internal mapper error string. That error code is stored here.
+	 */
+	uint32_t lastmappererr;
+} KMF_MAPPER_STATE;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _KMFMAPPER_H */
--- a/usr/src/lib/libkmf/include/kmfpolicy.h	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/lib/libkmf/include/kmfpolicy.h	Fri Jun 11 01:25:07 2010 -0700
@@ -18,15 +18,13 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 #ifndef _KMFPOLICY_H
 #define	_KMFPOLICY_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <kmfapi.h>
+#include <kmfmapper.h>
 #include <libxml/tree.h>
 #include <libxml/parser.h>
 
@@ -72,15 +70,14 @@
 	KMF_OID		*ekulist;
 }KMF_EKU_POLICY;
 
-
 #define	KMF_REVOCATION_METHOD_CRL		0x1
 #define	KMF_REVOCATION_METHOD_OCSP		0x2
 
-
 typedef struct {
 	char			*name;
 	KMF_VALIDATION_POLICY	validation_info;
 	KMF_EKU_POLICY		eku_set;
+	KMF_MAPPER_RECORD	mapper; /* kmfmapper.h */
 	uint32_t		ku_bits;
 	boolean_t		ignore_date;
 	boolean_t		ignore_unknown_ekus;
@@ -173,6 +170,12 @@
 #define	KMF_EKU_OID_ELEMENT	"eku-oid"
 #define	KMF_EKU_OID_ATTR	"oid"
 
+#define	KMF_CERT_MAPPER_ELEMENT		"cert-to-name-mapping"
+#define	KMF_CERT_MAPPER_NAME_ATTR	"mapper-name"
+#define	KMF_CERT_MAPPER_DIR_ATTR	"mapper-directory"
+#define	KMF_CERT_MAPPER_PATH_ATTR	"mapper-pathname"
+#define	KMF_CERT_MAPPER_OPTIONS_ATTR	"mapper-options"
+
 #define	TMPFILE_TEMPLATE	"policyXXXXXX"
 
 extern int parsePolicyElement(xmlNodePtr, KMF_POLICY_RECORD *);
--- a/usr/src/lib/libkmf/include/kmftypes.h	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/lib/libkmf/include/kmftypes.h	Fri Jun 11 01:25:07 2010 -0700
@@ -2,8 +2,7 @@
  * Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _KMFTYPES_H
@@ -345,7 +344,11 @@
 	KMF_ERR_UNEXTRACTABLE_KEY	= 0x52,
 	KMF_ERR_KEY_MISMATCH		= 0x53,
 	KMF_ERR_ATTR_NOT_FOUND		= 0x54,
-	KMF_ERR_KMF_CONF		= 0x55
+	KMF_ERR_KMF_CONF		= 0x55,
+	KMF_ERR_NAME_NOT_MATCHED	= 0x56,
+	KMF_ERR_MAPPER_OPEN		= 0x57,
+	KMF_ERR_MAPPER_NOT_FOUND	= 0x58,
+	KMF_ERR_MAPPING_FAILED		= 0x59
 } KMF_RETURN;
 
 /* Data structures for OCSP support */
@@ -795,7 +798,10 @@
 	KMF_VALIDATE_RESULT_ATTR,
 	KMF_KEY_DATA_ATTR,
 	KMF_PK11_USER_TYPE_ATTR,
-	KMF_ECC_CURVE_OID_ATTR
+	KMF_ECC_CURVE_OID_ATTR,
+	KMF_MAPPER_NAME_ATTR,
+	KMF_MAPPER_PATH_ATTR,
+	KMF_MAPPER_OPTIONS_ATTR
 } KMF_ATTR_TYPE;
 
 typedef struct {
--- a/usr/src/lib/libkmf/libkmf/Makefile.com	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/lib/libkmf/libkmf/Makefile.com	Fri Jun 11 01:25:07 2010 -0700
@@ -18,8 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 LIBRARY= libkmf.a
@@ -34,6 +33,7 @@
 	generalop.o \
 	keyop.o \
 	kmfoids.o \
+	mapping.o \
 	pem_encode.o \
 	pk11tokens.o \
 	policy.o \
--- a/usr/src/lib/libkmf/libkmf/common/generalop.c	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/lib/libkmf/libkmf/common/generalop.c	Fri Jun 11 01:25:07 2010 -0700
@@ -18,9 +18,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- *
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <stdio.h>
@@ -136,7 +134,11 @@
 	{KMF_ERR_UNEXTRACTABLE_KEY,	"KMF_ERR_UNEXTRACTABLE_KEY"},
 	{KMF_ERR_KEY_MISMATCH,		"KMF_ERR_KEY_MISMATCH"},
 	{KMF_ERR_ATTR_NOT_FOUND,	"KMF_ERR_ATTR_NOT_FOUND"},
-	{KMF_ERR_KMF_CONF,		"KMF_ERR_KMF_CONF"}
+	{KMF_ERR_KMF_CONF,		"KMF_ERR_KMF_CONF"},
+	{KMF_ERR_NAME_NOT_MATCHED,	"KMF_ERR_NAME_NOT_MATCHED"},
+	{KMF_ERR_MAPPER_OPEN,		"KMF_ERR_MAPPER_OPEN"},
+	{KMF_ERR_MAPPER_NOT_FOUND,	"KMF_ERR_MAPPER_NOT_FOUND"},
+	{KMF_ERR_MAPPING_FAILED,	"KMF_ERR_MAPPING_FAILED"}
 };
 
 typedef struct {
@@ -491,6 +493,26 @@
 	if (ret != KMF_OK)
 		goto errout;
 
+	/*
+	 * Let's have the mapper status structure even if no cert-to-name
+	 * mapping is initialized. It's better not to coredump in the
+	 * kmf_get_mapper_lasterror function, for example, when there is no
+	 * mapping initialized.
+	 */
+	handle->mapstate = malloc(sizeof (KMF_MAPPER_STATE));
+	if (handle->mapstate == NULL) {
+		ret = KMF_ERR_MEMORY;
+		goto errout;
+	}
+	handle->mapstate->lastmappererr = KMF_OK;
+	handle->mapstate->options = NULL;
+
+	/*
+	 * Initialize the mapping scheme according to the policy. If no mapping
+	 * is set in the policy database we silently ignore the error.
+	 */
+	(void) kmf_cert_to_name_mapping_initialize(handle, 0, NULL);
+
 	CLEAR_ERROR(handle, ret);
 errout:
 	if (ret != KMF_OK) {
--- a/usr/src/lib/libkmf/libkmf/common/mapfile-vers	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/lib/libkmf/libkmf/common/mapfile-vers	Fri Jun 11 01:25:07 2010 -0700
@@ -18,8 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 #
 # MAPFILE HEADER START
@@ -237,6 +236,8 @@
 	kmf_add_csr_eku;
 	kmf_add_policy_to_db;
 	kmf_build_pk12;
+	kmf_cert_to_name_mapping_initialize;
+	kmf_cert_to_name_mapping_finalize;
 	kmf_check_cert_date;
 	kmf_check_crl_date;
 	kmf_compare_rdns;
@@ -314,6 +315,9 @@
 	kmf_get_encoded_ocsp_response;
 	kmf_get_file_format;
 	kmf_get_kmf_error_str;
+	kmf_get_mapper_error_str;
+	kmf_get_mapper_lasterror;
+	kmf_get_mapper_options;
 	kmf_get_ocsp_for_cert;
 	kmf_get_ocsp_status_for_cert;
 	kmf_get_pk11_handle;
@@ -332,6 +336,8 @@
 	kmf_is_crl_file;
 	kmf_ku_to_string;
 	kmf_list_crl;
+	kmf_map_cert_to_name;
+	kmf_match_cert_to_name;
 	kmf_oid_to_ekuname;
 	kmf_oid_to_string;
 	kmf_pem_to_der;
@@ -359,6 +365,8 @@
 	kmf_set_csr_subject;
 	kmf_set_csr_subject_altname;
 	kmf_set_csr_version;
+	kmf_set_mapper_lasterror;
+	kmf_set_mapper_options;
 	kmf_set_policy;
 	kmf_set_token_pin;
 	kmf_sign_cert;
@@ -381,20 +389,21 @@
 
 SUNWprivate_1.1 {
     global:
-	GetIDFromSPKI;
-	IsEqualOid;
 	copy_extension_data;
 	dup_entry;
 	free_entry;
 	free_entrylist;
 	get_entrylist;
-	kmf_select_token;
+	get_mapper_pathname;
+	get_pk11_data;
+	GetIDFromSPKI;
+	IsEqualOid;
 	kmf_create_pk11_session;
+	kmf_select_token;
 	parsePolicyElement;
-	PKCS_VerifyData;
 	PKCS_DigestData;
 	PKCS_EncryptData;
-	get_pk11_data;
+	PKCS_VerifyData;
 	x509_algid_to_algoid;
 	x509_algoid_to_algid;
     local:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/libkmf/common/mapping.c	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,405 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * This file implements the KMF certificate to name mapping framework.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <libgen.h>
+#include <kmftypes.h>
+#include <kmfapiP.h>
+
+/* Mappers go in the same dir as plugins. */
+#define	DEFAULT_MAPPER_DIR KMF_PLUGIN_PATH
+
+static void
+cleanup_mapper(KMF_HANDLE_T handle)
+{
+	KMF_MAPPER_RECORD *mapper = &handle->policy->mapper;
+	void (*finalize)(KMF_HANDLE_T);
+
+	if (mapper->curpathname != NULL) {
+		free(mapper->curpathname);
+		mapper->curpathname = NULL;
+	}
+	if (mapper->curoptions != NULL) {
+		free(mapper->curoptions);
+		mapper->curoptions = NULL;
+	}
+	if (mapper->dldesc != NULL) {
+		finalize = (void(*)())dlsym(mapper->dldesc,
+		    MAPPER_FINISH_FUNCTION);
+		/* Optional, not an error if it does not exist. */
+		if (finalize != NULL)
+			finalize(handle);
+
+		(void) dlclose(mapper->dldesc);
+		mapper->dldesc = NULL;
+	}
+}
+
+/* The caller is expected to free the returned string. */
+char *
+get_mapper_pathname(char *name, char *dir)
+{
+	char *pathname = NULL;
+	int len;
+
+	if (name == NULL)
+		return (NULL);
+
+	if (dir == NULL)
+		dir = DEFAULT_MAPPER_DIR;
+
+	/*
+	 * MAPPER_NAME_TEMPLATE has 2 extra characters (%s) which make up for
+	 * the "/" and the terminating NULL when computing the total length.
+	 */
+	len = strlen(name) + strlen(MAPPER_NAME_TEMPLATE) + strlen(dir);
+
+	pathname = malloc(len);
+	if (pathname == NULL)
+		return (NULL);
+	(void) memset(pathname, 0, len);
+	/* Avoid double forward slash if the dir's last character is "/". */
+	(void) snprintf(pathname, len, "%s%s" MAPPER_NAME_TEMPLATE,
+	    dir, dir[strlen(dir) - 1] == '/' ? "" : "/", name);
+
+	return (pathname);
+}
+
+static KMF_RETURN
+open_mapper_library(KMF_MAPPER_RECORD *map)
+{
+	KMF_RETURN ret = KMF_OK;
+
+	map->dldesc = dlopen(map->curpathname, RTLD_LAZY | RTLD_PARENT);
+	if (map->dldesc == NULL)
+		return (KMF_ERR_MAPPER_OPEN);
+
+	return (ret);
+}
+
+/*
+ * The mapping framework uses either attributes or the policy file. Those two
+ * sources are never mixed. We always need a mapper name or a mapper pathname
+ * but these two are mutually exclusive. Directory can be set only if name is
+ * set.
+ */
+KMF_RETURN
+kmf_cert_to_name_mapping_initialize(KMF_HANDLE_T handle, int numattr,
+	KMF_ATTRIBUTE *attrlist)
+{
+	KMF_RETURN ret = KMF_OK;
+	KMF_RETURN (*initialize)(KMF_HANDLE_T, char *);
+	KMF_MAPPER_RECORD *map = NULL;
+	char *dir = NULL;
+	char *name = NULL;
+	char *opts = NULL;
+	char *path = NULL;
+	char *tmppath = NULL;
+	char *old_curpathname = NULL;
+	char *old_curoptions = NULL;
+
+	if (handle == NULL)
+		return (KMF_ERR_BAD_PARAMETER);
+
+	map = &handle->policy->mapper;
+	old_curpathname = map->curpathname;
+	old_curoptions = map->curoptions;
+
+	name = kmf_get_attr_ptr(KMF_MAPPER_NAME_ATTR, attrlist, numattr);
+	dir = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
+	path = kmf_get_attr_ptr(KMF_MAPPER_PATH_ATTR, attrlist, numattr);
+	opts = kmf_get_attr_ptr(KMF_MAPPER_OPTIONS_ATTR, attrlist, numattr);
+
+	if (path != NULL) {
+		/* Mutually exclusive. */
+		if (name != NULL || dir != NULL)
+			return (KMF_ERR_BAD_PARAMETER);
+		tmppath = strdup(path);
+		if (tmppath == NULL)
+			return (KMF_ERR_MEMORY);
+	/* If we only have a name and possibly a dir, we can find the path. */
+	} else if (name != NULL) {
+		tmppath = get_mapper_pathname(name, dir);
+		/*
+		 * If we were given name but the returned path is still NULL,
+		 * return an error.
+		 */
+		if (tmppath == NULL)
+			return (KMF_ERR_MEMORY);
+	/* Can not exist standalone. */
+	} else if (dir != NULL || opts != NULL) {
+			return (KMF_ERR_BAD_PARAMETER);
+	/* No attributes define the mapper so let's use the policy database. */
+	} else if (map->pathname != NULL) {
+		tmppath = strdup(map->pathname);
+		if (tmppath == NULL)
+			return (KMF_ERR_MEMORY);
+		opts = map->options;
+	} else if (map->mapname != NULL) {
+		tmppath = get_mapper_pathname(map->mapname, map->dir);
+		/*
+		 * If we were given name but the returned path is still NULL,
+		 * return an error.
+		 */
+		if (tmppath == NULL)
+			return (KMF_ERR_MEMORY);
+		opts = map->options;
+	} else {
+		/*
+		 * Either a name or a full pathname must be provided whether
+		 * from attributes or the policy database.
+		 */
+		return (KMF_ERR_BAD_PARAMETER);
+	}
+
+	/*
+	 * Dlopen the mapper specified by the policy. If anything goes wrong
+	 * just return an error. We do not have to worry about resetting
+	 * curpathname and curoptions to the previous values since there was no
+	 * mapper initialized beforehand.
+	 *
+	 * No mapper was open so stored curoptions and curpathname are
+	 * already NULL and need not to be freed.
+	 */
+	if (map->dldesc == NULL) {
+		map->curpathname = tmppath;
+		if (opts != NULL) {
+			map->curoptions = strdup(opts);
+			if (map->curoptions == NULL) {
+				free(map->curpathname);
+				map->curpathname = NULL;
+				return (KMF_ERR_MEMORY);
+			}
+		} else
+			map->curoptions = NULL;
+
+		if ((ret = open_mapper_library(map)) != KMF_OK) {
+			free(map->curpathname);
+			map->curpathname = NULL;
+			if (map->curoptions != NULL) {
+				free(map->curoptions);
+				map->curoptions = NULL;
+			}
+			return (ret);
+		}
+
+		goto end;
+	}
+
+	/*
+	 * We already have an open mapper, let's see if this is a new mapper
+	 * library.
+	 */
+	if (map->curpathname != NULL &&
+	    /* No change in mapper pathname. */
+	    strcmp(map->curpathname, tmppath) == 0) {
+		/* New options are empty while we had some before. */
+		if (map->curoptions != NULL && opts == NULL) {
+			map->curoptions = NULL;
+		/* We have some options now while we had none before. */
+		} else if (map->curoptions == NULL && opts != NULL) {
+			if ((map->curoptions = strdup(opts)) == NULL)
+				goto err_mem;
+		/* We got different options. */
+		} else if (strcmp(map->curoptions, opts) != 0) {
+			if ((map->curoptions = strdup(opts)) == NULL)
+				goto err_mem;
+		} else {
+			/*
+			 * Same options, no free() of current options is
+			 * required.
+			 */
+			old_curoptions = NULL;
+		}
+
+		/* Free old options if applicable. */
+		if (old_curoptions != NULL)
+			free(old_curoptions);
+	} else {
+		/*
+		 * This is a new mapper path, clean up the old data and open the
+		 * new mapper.
+		 */
+		cleanup_mapper(handle);
+		/* These two are no longer valid. */
+		old_curoptions = NULL;
+		old_curpathname = NULL;
+		map->curpathname = tmppath;
+		if (opts != NULL) {
+			map->curoptions = strdup(opts);
+			if (map->curoptions == NULL)
+				goto err_mem;
+		}
+		if ((ret = open_mapper_library(map)) != KMF_OK) {
+			/*
+			 * This will cleanup curoptions and curpathname, and
+			 * ignores the dldesc since it is NULL. Do not free
+			 * tmppath, it will be freed through map->curpathname.
+			 */
+			cleanup_mapper(handle);
+			return (ret);
+		}
+	}
+
+end:
+	initialize = (KMF_RETURN(*)())dlsym(map->dldesc,
+	    MAPPER_INIT_FUNCTION);
+	/* Optional, not an error if it does not exist. */
+	ret = KMF_OK;
+	if (initialize != NULL)
+		ret = initialize(handle, map->curoptions);
+
+	if (ret != KMF_OK)
+		cleanup_mapper(handle);
+
+	return (ret);
+
+err_mem:
+	/*
+	 * Try to put the old curpathname and curoptions back there. In theory,
+	 * the application might be able to continue to use the old mapping
+	 * unless we already called cleanup_mapper(). However, it's neither
+	 * recommended nor officially supported. The app should initialize the
+	 * old mapping again.
+	 */
+	if (tmppath != NULL)
+		free(tmppath);
+	map->curoptions = old_curoptions;
+	map->curpathname = old_curpathname;
+	return (KMF_ERR_MEMORY);
+}
+
+KMF_RETURN
+kmf_cert_to_name_mapping_finalize(KMF_HANDLE_T handle)
+{
+	if (handle == NULL)
+		return (KMF_ERR_BAD_PARAMETER);
+
+	cleanup_mapper(handle);
+
+	return (KMF_OK);
+}
+
+KMF_RETURN
+kmf_map_cert_to_name(KMF_HANDLE_T handle, KMF_DATA *cert, KMF_DATA *name)
+{
+	KMF_MAPPER_RECORD *map = NULL;
+	KMF_RETURN (*cert2name)(KMF_HANDLE *, KMF_DATA *, KMF_DATA *);
+
+	if (handle == NULL)
+		return (KMF_ERR_BAD_PARAMETER);
+
+	map = &handle->policy->mapper;
+	if (map->dldesc == NULL)
+		return (KMF_ERR_MAPPER_NOT_FOUND);
+
+	cert2name = (KMF_RETURN(*)())dlsym(map->dldesc,
+	    MAP_CERT_TO_NAME_FUNCTION);
+	if (cert2name == NULL)
+		return (KMF_ERR_FUNCTION_NOT_FOUND);
+
+	return (cert2name(handle, cert, name));
+}
+
+/*
+ * If mapped_name is non-NULL the caller is later expected to free its Data
+ * after use.
+ */
+KMF_RETURN
+kmf_match_cert_to_name(KMF_HANDLE_T handle, KMF_DATA *cert,
+    KMF_DATA *name_to_match, KMF_DATA *mapped_name)
+{
+	KMF_MAPPER_RECORD *map = NULL;
+	KMF_RETURN (*cert2name)(KMF_HANDLE *, KMF_DATA *, KMF_DATA *,
+	    KMF_DATA *);
+
+	if (handle == NULL)
+		return (KMF_ERR_BAD_PARAMETER);
+
+	map = &handle->policy->mapper;
+
+	if (map->curpathname == NULL || map->dldesc == NULL)
+		return (KMF_ERR_MAPPER_NOT_FOUND);
+
+	cert2name = (KMF_RETURN(*)())dlsym(map->dldesc,
+	    MATCH_CERT_TO_NAME_FUNCTION);
+	if (cert2name == NULL)
+		return (KMF_ERR_FUNCTION_NOT_FOUND);
+
+	return (cert2name(handle, cert, name_to_match, mapped_name));
+}
+
+/*
+ * The caller is responsible for freeing the error string (ie., *errstr) when
+ * done with it.
+ */
+KMF_RETURN
+kmf_get_mapper_error_str(KMF_HANDLE_T handle, char **errstr)
+{
+	KMF_HANDLE *h = NULL;
+	KMF_MAPPER_RECORD *map = NULL;
+	KMF_RETURN (*err2string)(KMF_HANDLE *, char **);
+
+	if (handle == NULL || errstr == NULL)
+		return (KMF_ERR_BAD_PARAMETER);
+
+	h = (KMF_HANDLE *)handle;
+	map = &(h->policy->mapper);
+
+	if (map->curpathname == NULL || map->dldesc == NULL)
+		return (KMF_ERR_MAPPER_NOT_FOUND);
+
+	err2string = (KMF_RETURN(*)())dlsym(map->dldesc,
+	    MAPPER_ERROR_STRING_FUNCTION);
+	if (err2string == NULL)
+		return (KMF_ERR_FUNCTION_NOT_FOUND);
+
+	return (err2string(h, errstr));
+}
+
+void
+kmf_set_mapper_lasterror(KMF_HANDLE_T handle, uint32_t err)
+{
+	handle->mapstate->lastmappererr = err;
+}
+
+uint32_t
+kmf_get_mapper_lasterror(KMF_HANDLE_T handle)
+{
+	return (handle->mapstate->lastmappererr);
+}
+
+void
+kmf_set_mapper_options(KMF_HANDLE_T handle, void *opts)
+{
+	handle->mapstate->options = opts;
+}
+
+void *
+kmf_get_mapper_options(KMF_HANDLE_T handle)
+{
+	return (handle->mapstate->options);
+}
--- a/usr/src/lib/libkmf/libkmf/common/policy.c	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/lib/libkmf/libkmf/common/policy.c	Fri Jun 11 01:25:07 2010 -0700
@@ -17,11 +17,8 @@
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ *
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <stdlib.h>
@@ -29,6 +26,7 @@
 #include <strings.h>
 #include <unistd.h>
 #include <errno.h>
+#include <libgen.h>
 #include <sys/param.h>
 #include <sys/stat.h>
 
@@ -387,6 +385,31 @@
 	return (ret);
 }
 
+static KMF_RETURN
+parseMapper(xmlNodePtr node, KMF_MAPPER_RECORD *mapper)
+{
+	xmlNodePtr n;
+
+	n = node;
+	mapper->mapname = (char *)xmlGetProp(n,
+	    (const xmlChar *)KMF_CERT_MAPPER_NAME_ATTR);
+	mapper->dir = (char *)xmlGetProp(n,
+	    (const xmlChar *)KMF_CERT_MAPPER_DIR_ATTR);
+	mapper->pathname = (char *)xmlGetProp(n,
+	    (const xmlChar *)KMF_CERT_MAPPER_PATH_ATTR);
+	mapper->options = (char *)xmlGetProp(n,
+	    (const xmlChar *)KMF_CERT_MAPPER_OPTIONS_ATTR);
+
+	/*
+	 * These are set according to whether mapper setting is taken from the
+	 * database or init function attributes.
+	 */
+	mapper->curpathname = NULL;
+	mapper->curoptions = NULL;
+
+	return (KMF_OK);
+}
+
 int
 parsePolicyElement(xmlNodePtr node, KMF_POLICY_RECORD *policy)
 {
@@ -449,6 +472,11 @@
 				ret = parseExtKeyUsage(n, &policy->eku_set);
 				if (ret != KMF_OK)
 					return (ret);
+			} else if (!xmlStrcmp((const xmlChar *)n->name,
+			    (const xmlChar *)KMF_CERT_MAPPER_ELEMENT)) {
+				ret = parseMapper(n, &policy->mapper);
+				if (ret != KMF_OK)
+					return (ret);
 			}
 
 			n = n->next;
@@ -637,6 +665,57 @@
 }
 
 /*
+ * Add mapper policy info to the policy tree.
+ * Return non-zero on any failure, else 0 for success.
+ */
+static KMF_RETURN
+AddMapperPolicyNodes(xmlNodePtr parent, KMF_MAPPER_RECORD  *mapper)
+{
+	KMF_RETURN ret = KMF_OK;
+	xmlNodePtr mapper_node;
+
+	addFormatting(parent, "\n\t");
+	mapper_node = xmlNewChild(parent, NULL,
+	    (const xmlChar *)KMF_CERT_MAPPER_ELEMENT, NULL);
+	if (mapper_node == NULL)
+		return (KMF_ERR_POLICY_ENGINE);
+
+	if (mapper->mapname != NULL &&
+	    newprop(mapper_node, KMF_CERT_MAPPER_NAME_ATTR, mapper->mapname)) {
+		ret = KMF_ERR_POLICY_ENGINE;
+		goto end;
+	}
+
+	if (mapper->pathname != NULL &&
+	    newprop(mapper_node, KMF_CERT_MAPPER_PATH_ATTR, mapper->pathname)) {
+		ret = KMF_ERR_POLICY_ENGINE;
+		goto end;
+	}
+
+	if (mapper->dir != NULL &&
+	    newprop(mapper_node, KMF_CERT_MAPPER_DIR_ATTR, mapper->dir)) {
+		ret = KMF_ERR_POLICY_ENGINE;
+		goto end;
+	}
+
+	if (mapper->options != NULL &&
+	    newprop(mapper_node, KMF_CERT_MAPPER_OPTIONS_ATTR, mapper->options))
+		ret = KMF_ERR_POLICY_ENGINE;
+
+	if (ret == KMF_OK) {
+		addFormatting(mapper_node, "\n\t");
+		addFormatting(parent, "\n");
+	}
+
+end:
+	if (ret != KMF_OK) {
+		xmlUnlinkNode(mapper_node);
+		xmlFreeNode(mapper_node);
+	}
+	return (ret);
+}
+
+/*
  * Add Key Usage information to the policy tree.
  * Return non-zero on any failure, else 0 for success.
  */
@@ -760,6 +839,10 @@
 	FREE_POLICY_STR(policy->validity_adjusttime)
 	FREE_POLICY_STR(policy->ta_name)
 	FREE_POLICY_STR(policy->ta_serial)
+	FREE_POLICY_STR(policy->mapper.mapname)
+	FREE_POLICY_STR(policy->mapper.pathname)
+	FREE_POLICY_STR(policy->mapper.options)
+	FREE_POLICY_STR(policy->mapper.dir)
 
 	kmf_free_eku_policy(&policy->eku_set);
 
@@ -1181,6 +1264,9 @@
 		if ((ret = AddExtKeyUsageNodes(pnode, &policy->eku_set))) {
 			goto out;
 		}
+		if ((ret = AddMapperPolicyNodes(pnode, &policy->mapper))) {
+			goto out;
+		}
 	} else {
 		ret = KMF_ERR_BAD_PARAMETER;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/mappers/Makefile	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,45 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+# Makefile for KMF mappers.
+#
+include	../../Makefile.lib
+
+SUBDIRS	=	kmf_mapper_cn
+
+HDRS =
+HDRDIR =	include
+
+all :=          TARGET= all
+clean :=        TARGET= clean
+clobber :=      TARGET= clobber
+install :=      TARGET= install
+lint :=         TARGET= lint
+
+all clean clobber install lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+	@cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/lib/Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/mappers/kmf_mapper_cn/Makefile	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,45 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+# The CN KMF mapper. Maps a certificate to its Common Name value.
+#
+include         $(SRC)/lib/Makefile.lib
+
+SUBDIRS =	$(MACH)
+
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all :=          TARGET= all
+check :=        TARGET= check
+clean :=        TARGET= clean
+clobber :=      TARGET= clobber
+install :=      TARGET= install
+lint :=         TARGET= lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+	@cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/mappers/kmf_mapper_cn/Makefile.com	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+# KMF CN mapper. Maps a certificate to its Common Name value.
+#
+
+LIBRARY =	kmf_mapper_cn.a
+VERS =		.1
+
+OBJECTS =	mapper_cn.o
+
+include	$(SRC)/lib/Makefile.lib
+
+LIBLINKS =	$(DYNLIB:.so.1=.so)
+KMFINC =	-I../../../include
+
+SRCDIR =	../common
+INCDIR =	../../include
+
+SRCS =		$(OBJECTS:%.o=$(SRCDIR)/%.c)
+
+CFLAGS +=	$(CCVERBOSE)
+CPPFLAGS +=	-I../../../include -I$(INCDIR)
+LINTFLAGS64 +=	-errchk=longptr64
+
+PICS =		$(OBJECTS:%=pics/%)
+
+LDLIBS +=	-lkmf -lc
+
+ROOTLIBDIR =	$(ROOTFS_LIBDIR)/crypto
+ROOTLIBDIR64 =	$(ROOTFS_LIBDIR)/crypto/$(MACH64)
+
+.KEEP_STATE:
+
+LIBS =		$(DYNLIB)
+
+all:		$(LIBS) $(LINTLIB)
+
+lint:		lintcheck
+
+FRC:
+
+include $(SRC)/lib/Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/mappers/kmf_mapper_cn/amd64/Makefile	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,27 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+install: $(ROOTLIBS64)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/mappers/kmf_mapper_cn/common/mapfile-vers	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,48 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING:  STOP NOW.  DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+#	usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+SUNWprivate {
+    global:
+	mapper_finalize;
+	mapper_get_error_str;
+	mapper_initialize;
+	mapper_map_cert_to_name;
+	mapper_match_cert_to_name;
+    local:
+	*;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/mappers/kmf_mapper_cn/common/mapper_cn.c	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,222 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * KMF CN certificate-to-name mapper.
+ */
+
+#include <kmftypes.h>
+#include <kmfapi.h>
+#include <fcntl.h>
+
+/*
+ * KMF uses long identifiers for RDN processing which makes it hard to keep
+ * cstyle cleanliness without using some auxiliary macros. Parameter 'x' is of
+ * the KMF_X509_NAME type.
+ */
+#define	RDN_VALUE(x, i) \
+	(&x.RelativeDistinguishedName[i].AttributeTypeAndValue->value)
+
+#define	RDN_OID(x, i) \
+	(&x.RelativeDistinguishedName[i].AttributeTypeAndValue->type)
+
+#define	RDN_NPAIRS(x, i) (x.RelativeDistinguishedName[i].numberOfPairs)
+
+/* Error codes specific to this mapper. */
+#define	CN_MAPPER_CN_RDN_NOT_PRESENT	1
+
+typedef struct cooked_opts {
+	int casesensitive;
+} cooked_opts;
+
+KMF_RETURN
+mapper_initialize(KMF_HANDLE_T h, char *options)
+{
+	cooked_opts *opts;
+
+	if ((opts = malloc(sizeof (cooked_opts))) == NULL)
+		return (KMF_ERR_MEMORY);
+
+	/* This is the default. */
+	opts->casesensitive = B_FALSE;
+
+	if (options != NULL) {
+		if (strcmp(options, "casesensitive") == 0)
+			opts->casesensitive = B_TRUE;
+	}
+
+	kmf_set_mapper_options(h, opts);
+
+	return (KMF_OK);
+}
+
+void
+mapper_finalize(KMF_HANDLE_T h)
+{
+	void *opts;
+
+	if ((opts = kmf_get_mapper_options(h)) != NULL)
+		free(opts);
+	kmf_set_mapper_options(h, NULL);
+}
+
+/*
+ * The CN string returned in name.Data will be NULL-terminated. The caller is
+ * expected to free name->Data after use.
+ */
+KMF_RETURN
+mapper_map_cert_to_name(KMF_HANDLE_T h, KMF_DATA *cert, KMF_DATA *name)
+{
+	int i, j;
+	char *dn;
+	KMF_RETURN rv;
+	uchar_t *cn = NULL;
+	KMF_X509_NAME x509name;
+
+	kmf_set_mapper_lasterror(h, KMF_OK);
+
+	if ((rv = kmf_get_cert_subject_str(h, cert, &dn)) != KMF_OK)
+		return (rv);
+
+	if ((rv = kmf_dn_parser(dn, &x509name)) != KMF_OK)
+		return (rv);
+
+	/* Go through the list of RDNs and look for the CN. */
+	for (i = 0; i < x509name.numberOfRDNs; ++i) {
+		for (j = 0; j < RDN_NPAIRS(x509name, i); ++j) {
+			KMF_OID *oid = RDN_OID(x509name, i);
+			KMF_DATA *data = RDN_VALUE(x509name, i);
+
+			if (oid == NULL)
+				continue;
+
+			/* Is this RDN a Common Name? */
+			if (oid->Length == KMFOID_CommonName.Length &&
+			    memcmp(oid->Data, KMFOID_CommonName.Data,
+			    oid->Length) == 0) {
+				if ((cn = malloc(data->Length + 1)) == NULL) {
+					kmf_free_dn(&x509name);
+					return (KMF_ERR_MEMORY);
+				}
+				(void) memcpy(cn, data->Data, data->Length);
+				/* Terminate the string. */
+				cn[data->Length] = '\0';
+				name->Length = data->Length + 1;
+				name->Data = cn;
+				goto finished;
+			}
+		}
+	}
+
+finished:
+	kmf_free_dn(&x509name);
+	if (cn != NULL)
+		return (KMF_OK);
+	else {
+		kmf_set_mapper_lasterror(h, CN_MAPPER_CN_RDN_NOT_PRESENT);
+		return (KMF_ERR_INTERNAL);
+	}
+}
+
+/*
+ * Note that name_to_match->Data might or might not be NULL terminated. If
+ * mapped_name->Length returned is greater than zero the caller is expected to
+ * free mapped_name->Data after use.
+ */
+KMF_RETURN
+mapper_match_cert_to_name(KMF_HANDLE_T h, KMF_DATA *cert,
+    KMF_DATA *name_to_match, KMF_DATA *mapped_name)
+{
+	int ret;
+	KMF_RETURN rv;
+	KMF_DATA get_name;
+	cooked_opts *opts = NULL;
+
+	opts = (cooked_opts *)kmf_get_mapper_options(h);
+
+	/* Initialize the output parameter. */
+	if (mapped_name != NULL) {
+		mapped_name->Length = 0;
+		mapped_name->Data = NULL;
+	}
+
+	if ((rv = mapper_map_cert_to_name(h, cert, &get_name)) != KMF_OK)
+		return (rv);
+
+	/*
+	 * If name_to_match->Data is not NULL terminated, check that we have the
+	 * same number of characters.
+	 */
+	if (name_to_match->Data[name_to_match->Length - 1] != '\0')
+		/* We know that get_name.Data is NULL terminated. */
+		if (name_to_match->Length != get_name.Length - 1)
+			return (KMF_ERR_NAME_NOT_MATCHED);
+
+	/*
+	 * Compare the strings. We must use name_to_match->Length in case
+	 * name_to_match->Data was not NULL terminated. If we used
+	 * get_name.Length we could overrun name_to_match->Data by one byte.
+	 */
+	if (opts->casesensitive == B_TRUE)
+		ret = strncmp((char *)name_to_match->Data,
+		    (char *)get_name.Data, name_to_match->Length);
+	else
+		ret = strncasecmp((char *)name_to_match->Data,
+		    (char *)get_name.Data, name_to_match->Length);
+
+	if (mapped_name != NULL) {
+		mapped_name->Length = get_name.Length;
+		mapped_name->Data = get_name.Data;
+	} else
+		kmf_free_data(&get_name);
+
+	if (ret == 0)
+		return (KMF_OK);
+	else
+		return (KMF_ERR_NAME_NOT_MATCHED);
+}
+
+/* The caller is responsible for freeing the error string when done with it. */
+KMF_RETURN
+mapper_get_error_str(KMF_HANDLE_T h, char **errstr)
+{
+	uint32_t lasterr;
+
+	lasterr = kmf_get_mapper_lasterror(h);
+	*errstr = NULL;
+	if (lasterr == 0)
+		return (KMF_ERR_MISSING_ERRCODE);
+
+	switch (lasterr) {
+	case CN_MAPPER_CN_RDN_NOT_PRESENT:
+		*errstr = (char *)strdup("CN_MAPPER_CN_RDN_NOT_PRESENT");
+		break;
+	default:
+		*errstr = (char *)strdup("KMF_ERR_MISSING_MAPPER_ERRCODE");
+	}
+
+	if (*errstr == NULL)
+		return (KMF_ERR_MEMORY);
+
+	return (KMF_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/mappers/kmf_mapper_cn/i386/Makefile	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,26 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.com
+
+install: $(ROOTLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/mappers/kmf_mapper_cn/sparc/Makefile	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,26 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.com
+
+install: $(ROOTLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libkmf/mappers/kmf_mapper_cn/sparcv9/Makefile	Fri Jun 11 01:25:07 2010 -0700
@@ -0,0 +1,27 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.com
+include ../../../../Makefile.lib.64
+
+install: $(ROOTLIBS64)
--- a/usr/src/pkg/manifests/system-library.mf	Fri Jun 11 11:54:13 2010 +0800
+++ b/usr/src/pkg/manifests/system-library.mf	Fri Jun 11 01:25:07 2010 -0700
@@ -156,6 +156,8 @@
 file path=lib/crypto/kmf_nss.so.1
 file path=lib/crypto/kmf_openssl.so.1
 file path=lib/crypto/kmf_pkcs11.so.1
+file path=lib/crypto/$(ARCH64)/kmf_mapper_cn.so.1
+file path=lib/crypto/kmf_mapper_cn.so.1
 file path=lib/ld.so.1
 file path=lib/libadm.so.1
 file path=lib/libaio.so.1