diff options
283 files changed, 40103 insertions, 3433 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 0ce24fb60fe..52f30555720 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,4 +1,4 @@ -What's new in Samba 4 alpha2 +What's new in Samba 4 alpha3 ============================ Samba 4 is the ambitious next version of the Samba suite that is being @@ -10,14 +10,14 @@ Samba 4 is currently not yet in a state where it is usable in production environments. Note the WARNINGS below, and the STATUS file, which aims to document what should and should not work. -Samba4 alpha2 follows on from our first alpha release, made in +Samba4 alpha3 follows on from our first alpha release, made in September, and the Technology Preview series we have offered for some time now. WARNINGS ======== -Samba4 alpha2 is not a final Samba release. That is more a reference +Samba4 alpha3 is not a final Samba release. That is more a reference to Samba4's lack of the features we expect you will need than a statement of code quality, but clearly it hasn't seen a broad deployment yet. If you were to upgrade Samba3 (or indeed Windows) to @@ -64,29 +64,27 @@ working on modules to map between AD-like behaviours and this backend. We are aiming for Samba 4 to be powerful frontend to large directories. -CHANGES SINCE Alpha 1 +CHANGES SINCE Alpha2 ===================== -In the time since Samba4 Alpha1 was released in September 2007, Samba has +In the time since Samba4 Alpha2 was released in December 2007, Samba has continued to evolve, but you may particularly notice these areas: - MMC Support: The Active Directory Users and Computers console now - handles group membership correctly. + Python Bindings: Bindings for Python are now in place, and used for + Samba's provision script, slowly displacing EJS as the embedded + scripting language - member/memberOf: These and other linked attributes are now kept in - sync + SWAT Disabled: Due to a lack of developer time and without a + long-term web developer to maintain it, the SWAT web UI has been + disabled. - subtree renames: Renaming a subtree of LDAP objects is now possible, - with all linked attributes being kept consistant. + Oplock support: Samba4's file server now supports oplocks - Python Bindings: Bindings for a future move to Python as the - internal scripting language have been created. - - Shared library use: In support of projects such as OpenChange, - which depend on Samba4, more of Samba4 is built as shared libraries. + GNU Make: To try and simplfy our build system, we rely on GNU Make + to avoid autogenerating a massive single makefile. These are just some of the highlights of the work done in the past few -months. More details can be found in our SVN history. +months. More details can be found in our GIT history. CHANGES @@ -109,6 +107,7 @@ KNOWN ISSUES actually due to Kerberos objecting to a clock skew between client and server. + RUNNING Samba4 ============== diff --git a/source4/auth/credentials/credentials.h b/source4/auth/credentials/credentials.h index a3da5c60546..1b205c61ce6 100644 --- a/source4/auth/credentials/credentials.h +++ b/source4/auth/credentials/credentials.h @@ -128,7 +128,10 @@ struct cli_credentials { struct ldb_context; struct loadparm_context; -#include "auth/credentials/credentials_krb5.h" +struct ccache_container; + +struct gssapi_creds_container; + #include "auth/credentials/credentials_proto.h" #endif /* __CREDENTIALS_H__ */ diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c index 90b196e99e3..52bf9f124fe 100644 --- a/source4/auth/credentials/credentials_krb5.c +++ b/source4/auth/credentials/credentials_krb5.c @@ -400,10 +400,10 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, to the credentials system. */ -int cli_credentials_set_client_gss_creds(struct cli_credentials *cred, - struct loadparm_context *lp_ctx, - gss_cred_id_t gssapi_cred, - enum credentials_obtained obtained) + int cli_credentials_set_client_gss_creds(struct cli_credentials *cred, + struct loadparm_context *lp_ctx, + gss_cred_id_t gssapi_cred, + enum credentials_obtained obtained) { int ret; OM_uint32 maj_stat, min_stat; diff --git a/source4/auth/credentials/credentials_krb5.h b/source4/auth/credentials/credentials_krb5.h index b963fbdca44..aaa7d7f0da1 100644 --- a/source4/auth/credentials/credentials_krb5.h +++ b/source4/auth/credentials/credentials_krb5.h @@ -26,10 +26,20 @@ #include <gssapi/gssapi.h> #include <krb5.h> -struct ccache_container; - struct gssapi_creds_container { gss_cred_id_t creds; }; +/* Manually prototyped here to avoid needing gss headers in most callers */ +int cli_credentials_set_client_gss_creds(struct cli_credentials *cred, + struct loadparm_context *lp_ctx, + gss_cred_id_t gssapi_cred, + enum credentials_obtained obtained); + +/* Manually prototyped here to avoid needing krb5 headers in most callers */ +krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx, + struct cli_credentials *credentials, + struct smb_krb5_context *smb_krb5_context, + krb5_principal *princ); + #endif /* __CREDENTIALS_KRB5_H__ */ diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c index 70e2961d552..e905e3e704a 100644 --- a/source4/auth/kerberos/kerberos_util.c +++ b/source4/auth/kerberos/kerberos_util.c @@ -101,10 +101,10 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx, * the library routines. The returned princ is placed in the talloc * system by means of a destructor (do *not* free). */ -krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx, - struct cli_credentials *credentials, - struct smb_krb5_context *smb_krb5_context, - krb5_principal *princ) + krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx, + struct cli_credentials *credentials, + struct smb_krb5_context *smb_krb5_context, + krb5_principal *princ) { krb5_error_code ret; const char *princ_string; diff --git a/source4/auth/sam.c b/source4/auth/sam.c index 882196343c7..b171fc57b9a 100644 --- a/source4/auth/sam.c +++ b/source4/auth/sam.c @@ -157,7 +157,7 @@ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, msg, domain_dn); - acct_expiry = samdb_result_account_expires(msg, 0); + acct_expiry = samdb_result_account_expires(msg); /* Check for when we must change this password, taking the * userAccountControl flags into account */ @@ -351,7 +351,7 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte server_info->last_logon = samdb_result_nttime(msg, "lastLogon", 0); server_info->last_logoff = samdb_result_nttime(msg, "lastLogoff", 0); - server_info->acct_expiry = samdb_result_account_expires(msg, 0); + server_info->acct_expiry = samdb_result_account_expires(msg); server_info->last_password_change = samdb_result_nttime(msg, "pwdLastSet", 0); ncname = samdb_result_dn(sam_ctx, mem_ctx, msg_domain_ref, "nCName", NULL); diff --git a/source4/build/m4/public.m4 b/source4/build/m4/public.m4 index 604092c8d72..0058afe2b51 100644 --- a/source4/build/m4/public.m4 +++ b/source4/build/m4/public.m4 @@ -39,13 +39,13 @@ ENABLE = YES " ]) -dnl SMB_LIBRARY(name,obj_files,required_subsystems,version,so_version,cflags,ldflags) +dnl SMB_LIBRARY(name,obj_files,required_subsystems,cflags,ldflags) AC_DEFUN([SMB_LIBRARY], [ MAKE_SETTINGS="$MAKE_SETTINGS $1_OBJ_FILES = $2 -$1_CFLAGS = $6 -$1_LDFLAGS = $7 +$1_CFLAGS = $4 +$1_LDFLAGS = $5 $1_ENABLE = YES " @@ -54,8 +54,6 @@ SMB_INFO_LIBRARIES="$SMB_INFO_LIBRARIES # Start Library $1 @<:@LIBRARY::$1@:>@ PRIVATE_DEPENDENCIES = $3 -VERSION = $4 -SO_VERSION = $5 CFLAGS = \$($1_CFLAGS) LDFLAGS = \$($1_LDFLAGS) ENABLE = YES diff --git a/source4/cluster/ctdb/opendb_ctdb.c b/source4/cluster/ctdb/opendb_ctdb.c index a7b8ddf7606..402f3a2a1af 100644 --- a/source4/cluster/ctdb/opendb_ctdb.c +++ b/source4/cluster/ctdb/opendb_ctdb.c @@ -283,7 +283,7 @@ static NTSTATUS odb_oplock_break_send(struct odb_context *odb, struct opendb_ent */ static NTSTATUS odb_ctdb_open_file(struct odb_lock *lck, void *file_handle, const char *path, - bool allow_level_II_oplock, + int *fd, bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted) { diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 88c8afd6cca..1220a5c8553 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -445,13 +445,12 @@ NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, NTTIME def * Consolidate that logic here to allow clearer logic for account expiry in * the rest of the code. */ -NTTIME samdb_result_account_expires(struct ldb_message *msg, - NTTIME default_value) +NTTIME samdb_result_account_expires(struct ldb_message *msg) { NTTIME ret = ldb_msg_find_attr_as_uint64(msg, "accountExpires", - default_value); + 0); - if (ret == (NTTIME)0) + if (ret == 0) ret = 0x7FFFFFFFFFFFFFFFULL; return ret; @@ -1004,7 +1003,13 @@ struct ldb_dn *samdb_sites_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx) const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb) { TALLOC_CTX *tmp_ctx; - struct dom_sid *domain_sid; + const struct dom_sid *domain_sid; + const char *attrs[] = { + "objectSid", + NULL + }; + struct ldb_result *res; + int ret; /* see if we have a cached copy */ domain_sid = (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid"); @@ -1017,9 +1022,17 @@ const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb) goto failed; } - /* find the domain_sid */ - domain_sid = samdb_search_dom_sid(ldb, tmp_ctx, ldb_get_default_basedn(ldb), - "objectSid", "objectClass=domainDNS"); + ret = ldb_search_exp_fmt(ldb, tmp_ctx, &res, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, attrs, "objectSid=*"); + + if (ret != LDB_SUCCESS) { + goto failed; + } + + if (res->count != 1) { + goto failed; + } + + domain_sid = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSid"); if (domain_sid == NULL) { goto failed; } @@ -1464,7 +1477,7 @@ int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) { ret = ldb_search(ldb, sdn, LDB_SCOPE_BASE, - "(|(objectClass=domain)(objectClass=builtinDomain))", attrs, &res); + "(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain))", attrs, &res); if (ret == LDB_SUCCESS) { talloc_steal(local_ctx, res); if (res->count == 1) { diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c index 93da46d5bdd..b9333e451ba 100644 --- a/source4/dsdb/samdb/cracknames.c +++ b/source4/dsdb/samdb/cracknames.c @@ -329,7 +329,7 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(samAccountName=%s))", ldb_binary_encode_string(mem_ctx, unparsed_name_short)); - domain_filter = talloc_asprintf(mem_ctx, "(dn=%s)", ldb_dn_get_linearized(domain_res->msgs[0]->dn)); + domain_filter = talloc_asprintf(mem_ctx, "(distinguishedName=%s)", ldb_dn_get_linearized(domain_res->msgs[0]->dn)); if (!result_filter || !domain_filter) { free(unparsed_name_short); diff --git a/source4/dsdb/samdb/ldb_modules/kludge_acl.c b/source4/dsdb/samdb/ldb_modules/kludge_acl.c index e3e1f7ac88b..e418031271c 100644 --- a/source4/dsdb/samdb/ldb_modules/kludge_acl.c +++ b/source4/dsdb/samdb/ldb_modules/kludge_acl.c @@ -46,42 +46,15 @@ * */ -enum user_is { - ANONYMOUS, - USER, - ADMINISTRATOR, - SYSTEM -}; - struct kludge_private_data { const char **password_attrs; }; -static enum user_is what_is_user(struct ldb_module *module) +static enum security_user_level what_is_user(struct ldb_module *module) { struct auth_session_info *session_info = (struct auth_session_info *)ldb_get_opaque(module->ldb, "sessionInfo"); - if (!session_info) { - return ANONYMOUS; - } - - if (security_token_is_system(session_info->security_token)) { - return SYSTEM; - } - - if (security_token_is_anonymous(session_info->security_token)) { - return ANONYMOUS; - } - - if (security_token_has_builtin_administrators(session_info->security_token)) { - return ADMINISTRATOR; - } - - if (security_token_has_nt_authenticated_users(session_info->security_token)) { - return USER; - } - - return ANONYMOUS; + return security_session_user_level(session_info); } static const char *user_name(TALLOC_CTX *mem_ctx, struct ldb_module *module) @@ -104,7 +77,7 @@ struct kludge_acl_context { void *up_context; int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *); - enum user_is user_type; + enum security_user_level user_type; bool allowedAttributes; bool allowedAttributesEffective; bool allowedChildClasses; @@ -272,8 +245,8 @@ static int kludge_acl_callback(struct ldb_context *ldb, void *context, struct ld if (data && data->password_attrs) /* if we are not initialized just get through */ { switch (ac->user_type) { - case SYSTEM: - case ADMINISTRATOR: + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: if (ac->allowedAttributesEffective) { ret = kludge_acl_allowedAttributes(ldb, ares->message, "allowedAttributesEffective"); if (ret != LDB_SUCCESS) { @@ -359,7 +332,7 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req) so we don't allow a search for 'sambaPassword=penguin', just as we would not allow that attribute to be returned */ switch (ac->user_type) { - case SYSTEM: + case SECURITY_SYSTEM: break; default: /* remove password attributes */ @@ -391,10 +364,10 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req) /* ANY change type */ static int kludge_acl_change(struct ldb_module *module, struct ldb_request *req) { - enum user_is user_type = what_is_user(module); + enum security_user_level user_type = what_is_user(module); switch (user_type) { - case SYSTEM: - case ADMINISTRATOR: + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: return ldb_next_request(module, req); default: ldb_asprintf_errstring(module->ldb, diff --git a/source4/dsdb/samdb/ldb_modules/normalise.c b/source4/dsdb/samdb/ldb_modules/normalise.c index a0eff43534d..8de9e33002b 100644 --- a/source4/dsdb/samdb/ldb_modules/normalise.c +++ b/source4/dsdb/samdb/ldb_modules/normalise.c @@ -117,7 +117,7 @@ static int normalise_search_callback(struct ldb_context *ldb, void *context, str talloc_free(mem_ctx); return LDB_ERR_OPERATIONS_ERROR; } - ret = fix_dn(ares->message->dn); + ret = fix_dn(dn); if (ret != LDB_SUCCESS) { talloc_free(mem_ctx); return ret; diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index e63ad4de56b..4d4ef585cbb 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -257,12 +257,18 @@ static DATA_BLOB *get_sd(struct ldb_module *module, TALLOC_CTX *mem_ctx, DATA_BLOB *linear_sd; struct auth_session_info *session_info = ldb_get_opaque(module->ldb, "sessionInfo"); - struct security_descriptor *sd - = sddl_decode(mem_ctx, - objectclass->defaultSecurityDescriptor, - samdb_domain_sid(module->ldb)); + struct security_descriptor *sd; + struct dom_sid *domain_sid = samdb_domain_sid(module->ldb); - if (!session_info || !session_info->security_token) { + if (!objectclass->defaultSecurityDescriptor || !domain_sid) { + return NULL; + } + + sd = sddl_decode(mem_ctx, + objectclass->defaultSecurityDescriptor, + domain_sid); + + if (!sd || !session_info || !session_info->security_token) { return NULL; } @@ -538,7 +544,9 @@ static int objectclass_do_add(struct ldb_handle *h) } if (!ldb_msg_find_element(msg, "nTSecurityDescriptor")) { DATA_BLOB *sd = get_sd(ac->module, mem_ctx, current->objectclass); - ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd); + if (sd) { + ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd); + } } } } diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index aa64700f2f8..1d2bdd988e6 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1220,7 +1220,8 @@ static int build_domain_data_request(struct ph_context *ac) ac->dom_req->op.search.base = ldb_get_default_basedn(ac->module->ldb); ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE; - filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(|(objectClass=domain)(objectClass=builtinDomain)))", + filter = talloc_asprintf(ac->dom_req, + "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", ldap_encode_ndr_dom_sid(ac->dom_req, ac->domain_sid)); if (filter == NULL) { ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n"); diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 905cd4a995d..5407db99565 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -293,7 +293,7 @@ int samldb_notice_sid(struct ldb_module *module, /* find the domain DN */ ret = ldb_search_exp_fmt(module->ldb, mem_ctx, &dom_res, NULL, LDB_SCOPE_SUBTREE, attrs, - "(&(objectSid=%s)(objectclass=domain))", + "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", ldap_encode_ndr_dom_sid(mem_ctx, dom_sid)); if (ret == LDB_SUCCESS) { if (dom_res->count == 0) { @@ -369,7 +369,7 @@ static int samldb_generate_samAccountName(struct ldb_module *module, TALLOC_CTX /* Format: $000000-000000000000 */ do { - *name = talloc_asprintf(mem_ctx, "$%.6X-%.6X%.6X", (unsigned int)random(), (unsigned int)random(), (unsigned int)random()); + *name = talloc_asprintf(mem_ctx, "$%.6X-%.6X%.6X", (unsigned int)generate_random(), (unsigned int)generate_random(), (unsigned int)generate_random()); /* TODO: Figure out exactly what this is meant to conflict with */ ret = ldb_search_exp_fmt(module->ldb, mem_ctx, &res, dom_dn, LDB_SCOPE_SUBTREE, attrs, diff --git a/source4/heimdal/kdc/digest.c b/source4/heimdal/kdc/digest.c index 358ca5ad56d..b845b0f9a89 100644 --- a/source4/heimdal/kdc/digest.c +++ b/source4/heimdal/kdc/digest.c @@ -34,7 +34,7 @@ #include "kdc_locl.h" #include <hex.h> -RCSID("$Id: digest.c 21606 2007-07-17 07:03:25Z lha $"); +RCSID("$Id: digest.c 22374 2007-12-28 18:36:52Z lha $"); #define MS_CHAP_V2 0x20 #define CHAP_MD5 0x10 @@ -1003,7 +1003,8 @@ _kdc_do_digest(krb5_context context, } r.u.ntlmInitReply.flags |= - NTLM_NEG_TARGET_DOMAIN | + NTLM_NEG_TARGET | + NTLM_TARGET_DOMAIN | NTLM_ENC_128; #define ALL \ @@ -1331,6 +1332,27 @@ _kdc_do_digest(krb5_context context, version, ireq.u.ntlmRequest.username); break; } + case choice_DigestReqInner_supportedMechs: + + kdc_log(context, config, 0, "digest supportedMechs from %s", from); + + r.element = choice_DigestRepInner_supportedMechs; + memset(&r.u.supportedMechs, 0, sizeof(r.u.supportedMechs)); + + if (config->digests_allowed & NTLM_V1) + r.u.supportedMechs.ntlm_v1 = 1; + if (config->digests_allowed & NTLM_V1_SESSION) + r.u.supportedMechs.ntlm_v1_session = 1; + if (config->digests_allowed & NTLM_V2) + r.u.supportedMechs.ntlm_v2 = 1; + if (config->digests_allowed & DIGEST_MD5) + r.u.supportedMechs.digest_md5 = 1; + if (config->digests_allowed & CHAP_MD5) + r.u.supportedMechs.chap_md5 = 1; + if (config->digests_allowed & MS_CHAP_V2) + r.u.supportedMechs.ms_chap_v2 = 1; + break; + default: { char *s; krb5_set_error_string(context, "unknown operation to digest"); diff --git a/source4/heimdal/kdc/kaserver.c b/source4/heimdal/kdc/kaserver.c index 15624e8e763..27f497ea664 100644 --- a/source4/heimdal/kdc/kaserver.c +++ b/source4/heimdal/kdc/kaserver.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: kaserver.c 21661 2007-07-22 01:57:17Z lha $"); +RCSID("$Id: kaserver.c 21654 2007-07-21 17:30:18Z lha $"); #include <krb5-v4compat.h> #include <rx.h> diff --git a/source4/heimdal/kdc/kdc-private.h b/source4/heimdal/kdc/kdc-private.h index 030be9ae58b..4052e9b5090 100644 --- a/source4/heimdal/kdc/kdc-private.h +++ b/source4/heimdal/kdc/kdc-private.h @@ -281,6 +281,7 @@ krb5_error_code _kdc_windc_client_access ( krb5_context /*context*/, struct hdb_entry_ex */*client*/, - KDC_REQ */*req*/); + KDC_REQ */*req*/, + krb5_data */*e_data*/); #endif /* __kdc_private_h__ */ diff --git a/source4/heimdal/kdc/kdc_locl.h b/source4/heimdal/kdc/kdc_locl.h index fdbdf271def..fe0523665a4 100644 --- a/source4/heimdal/kdc/kdc_locl.h +++ b/source4/heimdal/kdc/kdc_locl.h @@ -32,7 +32,7 @@ */ /* - * $Id: kdc_locl.h 20954 2007-06-07 03:30:15Z lha $ + * $Id: kdc_locl.h 22247 2007-12-08 23:49:41Z lha $ */ #ifndef __KDC_LOCL_H__ @@ -58,8 +58,7 @@ extern int detach_from_console; extern const struct units _kdc_digestunits[]; -#define _PATH_KDC_CONF HDB_DB_DIR "/kdc.conf" -#define DEFAULT_LOG_DEST "0-1/FILE:" HDB_DB_DIR "/kdc.log" +#define KDC_LOG_FILE "kdc.log" extern struct timeval _kdc_now; #define kdc_time (_kdc_now.tv_sec) diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 40a9c9c972f..f1dea6499df 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: kerberos5.c 21529 2007-07-13 12:37:14Z lha $"); +RCSID("$Id: kerberos5.c 22071 2007-11-14 20:04:50Z lha $"); #define MAX_TIME ((time_t)((1U << 31) - 1)) @@ -362,6 +362,13 @@ older_enctype(krb5_enctype enctype) case ETYPE_DES3_CBC_SHA1: case ETYPE_ARCFOUR_HMAC_MD5: case ETYPE_ARCFOUR_HMAC_MD5_56: + /* + * The following three is "old" windows enctypes and is needed for + * windows 2000 hosts. + */ + case ETYPE_ARCFOUR_MD4: + case ETYPE_ARCFOUR_HMAC_OLD: + case ETYPE_ARCFOUR_HMAC_OLD_EXP: return 1; default: return 0; @@ -411,8 +418,8 @@ make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key) *ent->salttype = key->salt->type; #else /* - * We shouldn't sent salttype since its incompatible with the - * specification and its break windows clients. The afs + * We shouldn't sent salttype since it is incompatible with the + * specification and it breaks windows clients. The afs * salting problem is solved by using KRB5-PADATA-AFS3-SALT * implemented in Heimdal 0.7 and later. */ @@ -472,11 +479,13 @@ get_pa_etype_info(krb5_context context, free_ETYPE_INFO(&pa); return ret; } + break; } } skip1:; } for(i = 0; i < client->keys.len; i++) { + /* already added? */ for(j = 0; j < etypes_len; j++) { if(client->keys.val[i].key.keytype == etypes[j]) goto skip2; @@ -497,7 +506,7 @@ get_pa_etype_info(krb5_context context, } if(n < pa.len) { - /* stripped out newer enctypes */ + /* stripped out dups, newer enctypes, and not valid enctypes */ pa.len = n; } @@ -621,23 +630,29 @@ get_pa_etype_info2(krb5_context context, if(client->keys.val[i].key.keytype == etypes[j]) { if (krb5_enctype_valid(context, etypes[j]) != 0) continue; + if (n >= pa.len) + krb5_abortx(context, "internal error: n >= p.len"); if((ret = make_etype_info2_entry(&pa.val[n++], &client->keys.val[i])) != 0) { free_ETYPE_INFO2(&pa); return ret; } + break; } } skip1:; } - /* send enctypes that the cliene doesn't know about too */ + /* send enctypes that the client doesn't know about too */ for(i = 0; i < client->keys.len; i++) { + /* already added? */ for(j = 0; j < etypes_len; j++) { if(client->keys.val[i].key.keytype == etypes[j]) goto skip2; } if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0) continue; + if (n >= pa.len) + krb5_abortx(context, "internal error: n >= p.len"); if((ret = make_etype_info2_entry(&pa.val[n++], &client->keys.val[i])) != 0) { free_ETYPE_INFO2(&pa); @@ -646,16 +661,8 @@ get_pa_etype_info2(krb5_context context, skip2:; } - if(n != pa.len) { - char *name; - ret = krb5_unparse_name(context, client->principal, &name); - if (ret) - name = rk_UNCONST("<unparse_name failed>"); - kdc_log(context, config, 0, - "internal error in get_pa_etype_info2(%s): %d != %d", - name, n, pa.len); - if (ret == 0) - free(name); + if(n < pa.len) { + /* stripped out dups, and not valid enctypes */ pa.len = n; } @@ -1043,7 +1050,7 @@ _kdc_as_rep(krb5_context context, goto out; } - ret = _kdc_windc_client_access(context, client, req); + ret = _kdc_windc_client_access(context, client, req, &e_data); if(ret) goto out; @@ -1554,6 +1561,10 @@ _kdc_as_rep(krb5_context context, * otherwise just a dummy lr. */ ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val)); + if (ek.last_req.val == NULL) { + ret = ENOMEM; + goto out; + } ek.last_req.len = 0; if (client->entry.pw_end && (config->kdc_warn_pwexpire == 0 diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 4d6be60f68f..32bdee9799c 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: krb5tgs.c 21262 2007-06-21 15:18:37Z lha $"); +RCSID("$Id: krb5tgs.c 22071 2007-11-14 20:04:50Z lha $"); /* * return the realm of a krbtgt-ticket or NULL @@ -822,7 +822,7 @@ tgs_make_reply(krb5_context context, if(rspac->length) { /* * No not need to filter out the any PAC from the - * auth_data since its signed by the KDC. + * auth_data since it's signed by the KDC. */ ret = _kdc_tkt_add_if_relevant_ad(context, &et, KRB5_AUTHDATA_WIN2K_PAC, @@ -1099,11 +1099,14 @@ tgs_parse_request(krb5_context context, ret = hdb_enctype2key(context, &(*krbtgt)->entry, ap_req.ticket.enc_part.etype, &tkey); if(ret){ - char *str, *p; + char *str = NULL, *p = NULL; + krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str); krb5_unparse_name(context, princ, &p); - kdc_log(context, config, 0, - "No server key with enctype %s found for %s", str, p); + kdc_log(context, config, 0, + "No server key with enctype %s found for %s", + str ? str : "<unknown enctype>", + p ? p : "<unparse_name failed>"); free(str); free(p); ret = KRB5KRB_AP_ERR_BADKEYVER; @@ -1163,8 +1166,10 @@ tgs_parse_request(krb5_context context, } if (b->enc_authorization_data) { + unsigned usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY; krb5_keyblock *subkey; krb5_data ad; + ret = krb5_auth_con_getremotesubkey(context, ac, &subkey); @@ -1175,6 +1180,7 @@ tgs_parse_request(krb5_context context, goto out; } if(subkey == NULL){ + usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION; ret = krb5_auth_con_getkey(context, ac, &subkey); if(ret) { krb5_auth_con_free(context, ac); @@ -1199,7 +1205,7 @@ tgs_parse_request(krb5_context context, } ret = krb5_decrypt_EncryptedData (context, crypto, - KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, + usage, b->enc_authorization_data, &ad); krb5_crypto_destroy(context, crypto); @@ -1373,6 +1379,7 @@ server_lookup: ret = krb5_unparse_name(context, sp, &spn); if (ret) goto out; + auth_data = NULL; /* ms don't handle AD in referals */ goto server_lookup; } } @@ -1390,6 +1397,7 @@ server_lookup: if (ret) goto out; krb5_free_host_realm(context, realms); + auth_data = NULL; /* ms don't handle AD in referals */ goto server_lookup; } krb5_free_host_realm(context, realms); @@ -1431,8 +1439,8 @@ server_lookup: } /* - * Check that service is in the same realm as the krbtgt. If its - * not the same, its someone that is using a uni-directional trust + * Check that service is in the same realm as the krbtgt. If it's + * not the same, it's someone that is using a uni-directional trust * backward. */ diff --git a/source4/heimdal/kdc/log.c b/source4/heimdal/kdc/log.c index 977b1c94760..8cf967fbfb8 100644 --- a/source4/heimdal/kdc/log.c +++ b/source4/heimdal/kdc/log.c @@ -32,7 +32,7 @@ */ #include "kdc_locl.h" -RCSID("$Id: log.c 15532 2005-06-30 01:54:49Z lha $"); +RCSID("$Id: log.c 22254 2007-12-09 06:01:05Z lha $"); void kdc_openlog(krb5_context context, @@ -47,8 +47,12 @@ kdc_openlog(krb5_context context, for(p = s; *p; p++) krb5_addlog_dest(context, config->logf, *p); krb5_config_free_strings(s); - }else - krb5_addlog_dest(context, config->logf, DEFAULT_LOG_DEST); + }else { + char *s; + asprintf(&s, "0-1/FILE:%s/%s", hdb_db_dir(context), KDC_LOG_FILE); + krb5_addlog_dest(context, config->logf, s); + free(s); + } krb5_set_warn_dest(context, config->logf); } diff --git a/source4/heimdal/kdc/pkinit.c b/source4/heimdal/kdc/pkinit.c index ead961022d1..bf248af588f 100755 --- a/source4/heimdal/kdc/pkinit.c +++ b/source4/heimdal/kdc/pkinit.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: pkinit.c 21290 2007-06-25 14:13:23Z lha $"); +RCSID("$Id: pkinit.c 22243 2007-12-08 23:39:30Z lha $"); #ifdef PKINIT @@ -1248,6 +1248,7 @@ out: static int match_rfc_san(krb5_context context, krb5_kdc_configuration *config, + hx509_context hx509ctx, hx509_cert client_cert, krb5_const_principal match) { @@ -1256,7 +1257,8 @@ match_rfc_san(krb5_context context, memset(&list, 0 , sizeof(list)); - ret = hx509_cert_find_subjectAltName_otherName(client_cert, + ret = hx509_cert_find_subjectAltName_otherName(hx509ctx, + client_cert, oid_id_pkinit_san(), &list); if (ret) @@ -1304,6 +1306,7 @@ out: static int match_ms_upn_san(krb5_context context, krb5_kdc_configuration *config, + hx509_context hx509ctx, hx509_cert client_cert, krb5_const_principal match) { @@ -1315,7 +1318,8 @@ match_ms_upn_san(krb5_context context, memset(&list, 0 , sizeof(list)); - ret = hx509_cert_find_subjectAltName_otherName(client_cert, + ret = hx509_cert_find_subjectAltName_otherName(hx509ctx, + client_cert, oid_id_pkinit_ms_san(), &list); if (ret) @@ -1376,7 +1380,7 @@ _kdc_pk_check_client(krb5_context context, hx509_name name; int i; - ret = hx509_cert_get_base_subject(kdc_identity->hx509ctx, + ret = hx509_cert_get_base_subject(kdc_identity->hx509ctx, client_params->cert, &name); if (ret) @@ -1393,6 +1397,7 @@ _kdc_pk_check_client(krb5_context context, if (config->pkinit_princ_in_cert) { ret = match_rfc_san(context, config, + kdc_identity->hx509ctx, client_params->cert, client->entry.principal); if (ret == 0) { @@ -1401,6 +1406,7 @@ _kdc_pk_check_client(krb5_context context, return 0; } ret = match_ms_upn_san(context, config, + kdc_identity->hx509ctx, client_params->cert, client->entry.principal); if (ret == 0) { @@ -1580,7 +1586,8 @@ _kdc_pk_initialize(krb5_context context, char **pool, char **revoke_list) { - const char *file; + const char *file; + char *fn = NULL; krb5_error_code ret; file = krb5_config_get_string(context, NULL, @@ -1646,14 +1653,19 @@ _kdc_pk_initialize(krb5_context context, NULL); _krb5_pk_allow_proxy_certificate(kdc_identity, ret); - file = krb5_config_get_string_default(context, - NULL, - HDB_DB_DIR "/pki-mapping", - "kdc", - "pkinit_mappings_file", - NULL); + file = krb5_config_get_string(context, + NULL, + "kdc", + "pkinit_mappings_file", + NULL); + if (file == NULL) { + asprintf(&fn, "%s/pki-mapping", hdb_db_dir(context)); + file = fn; + } load_mappings(context, file); + if (fn) + free(fn); return 0; } diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c index 395ab734328..85e4d7f725c 100644 --- a/source4/heimdal/kdc/windc.c +++ b/source4/heimdal/kdc/windc.c @@ -101,9 +101,10 @@ _kdc_pac_verify(krb5_context context, krb5_error_code _kdc_windc_client_access(krb5_context context, struct hdb_entry_ex *client, - KDC_REQ *req) + KDC_REQ *req, + krb5_data *e_data) { if (windcft == NULL) return 0; - return (windcft->client_access)(windcctx, context, client, req); + return (windcft->client_access)(windcctx, context, client, req, e_data); } diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h index ec480cf950c..3ae0c94681e 100644 --- a/source4/heimdal/kdc/windc_plugin.h +++ b/source4/heimdal/kdc/windc_plugin.h @@ -64,7 +64,7 @@ typedef krb5_error_code typedef krb5_error_code (*krb5plugin_windc_client_access)( - void *, krb5_context, struct hdb_entry_ex *, KDC_REQ *); + void *, krb5_context, struct hdb_entry_ex *, KDC_REQ *, krb5_data *); #define KRB5_WINDC_PLUGING_MINOR 2 diff --git a/source4/heimdal/kuser/kinit.c b/source4/heimdal/kuser/kinit.c index 23fa7a5bafb..26763098590 100644 --- a/source4/heimdal/kuser/kinit.c +++ b/source4/heimdal/kuser/kinit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -32,7 +32,7 @@ */ #include "kuser_locl.h" -RCSID("$Id: kinit.c 21483 2007-07-10 16:40:46Z lha $"); +RCSID("$Id: kinit.c 22116 2007-12-03 21:22:58Z lha $"); #include "krb5-v4compat.h" @@ -260,7 +260,7 @@ renew_validate(krb5_context context, if (renew) { /* - * no need to check the error here, its only to be + * no need to check the error here, it's only to be * friendly to the user */ krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out); @@ -377,6 +377,7 @@ get_new_tickets(krb5_context context, char *renewstr = NULL; krb5_enctype *enctype = NULL; struct ntlm_buf ntlmkey; + krb5_ccache tempccache; memset(&ntlmkey, 0, sizeof(ntlmkey)); passwd[0] = '\0'; @@ -577,16 +578,25 @@ get_new_tickets(krb5_context context, } } - ret = krb5_cc_initialize (context, ccache, cred.client); + ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache), + NULL, &tempccache); + if (ret) + krb5_err (context, 1, ret, "krb5_cc_new_unique"); + + ret = krb5_cc_initialize (context, tempccache, cred.client); if (ret) krb5_err (context, 1, ret, "krb5_cc_initialize"); - ret = krb5_cc_store_cred (context, ccache, &cred); + ret = krb5_cc_store_cred (context, tempccache, &cred); if (ret) krb5_err (context, 1, ret, "krb5_cc_store_cred"); krb5_free_cred_contents (context, &cred); + ret = krb5_cc_move(context, tempccache, ccache); + if (ret) + krb5_err (context, 1, ret, "krb5_cc_move"); + if (ntlm_domain && ntlmkey.data) store_ntlmkey(context, ccache, ntlm_domain, principal, &ntlmkey); @@ -757,8 +767,11 @@ main (int argc, char **argv) krb4_cc_name = NULL; } } - } else - ret = krb5_cc_default (context, &ccache); + } else { + ret = krb5_cc_cache_match(context, principal, NULL, &ccache); + if (ret) + ret = krb5_cc_default (context, &ccache); + } } if (ret) krb5_err (context, 1, ret, "resolving credentials cache"); diff --git a/source4/heimdal/lib/asn1/asn1-common.h b/source4/heimdal/lib/asn1/asn1-common.h index 15c4a09cd0d..5789e0f22df 100644 --- a/source4/heimdal/lib/asn1/asn1-common.h +++ b/source4/heimdal/lib/asn1/asn1-common.h @@ -1,4 +1,4 @@ -/* $Id: asn1-common.h 19539 2006-12-28 17:15:05Z lha $ */ +/* $Id: asn1-common.h 22429 2008-01-13 10:25:50Z lha $ */ #include <stddef.h> #include <time.h> diff --git a/source4/heimdal/lib/asn1/canthandle.asn1 b/source4/heimdal/lib/asn1/canthandle.asn1 index edb8375ee35..5ba3e3880c2 100644 --- a/source4/heimdal/lib/asn1/canthandle.asn1 +++ b/source4/heimdal/lib/asn1/canthandle.asn1 @@ -1,4 +1,4 @@ --- $Id: canthandle.asn1 16593 2006-01-18 19:12:33Z lha $ -- +-- $Id: canthandle.asn1 22071 2007-11-14 20:04:50Z lha $ -- CANTHANDLE DEFINITIONS ::= BEGIN @@ -19,7 +19,7 @@ Foo ::= SEQUENCE { kaka3 [2] IMPLICIT Kaka3 OPTIONAL } --- Don't code kaka if its 1 +-- Don't code kaka if it's 1 -- Workaround is to use OPTIONAL and check for in the encoder stubs Bar ::= SEQUENCE { diff --git a/source4/heimdal/lib/asn1/der.c b/source4/heimdal/lib/asn1/der.c index c7b911b8d6c..120dc086afc 100644 --- a/source4/heimdal/lib/asn1/der.c +++ b/source4/heimdal/lib/asn1/der.c @@ -38,7 +38,7 @@ #include <getarg.h> #include <err.h> -RCSID("$Id: der.c 15617 2005-07-12 06:27:42Z lha $"); +RCSID("$Id: der.c 22429 2008-01-13 10:25:50Z lha $"); static const char *class_names[] = { diff --git a/source4/heimdal/lib/asn1/digest.asn1 b/source4/heimdal/lib/asn1/digest.asn1 index 17341863c66..eafe48ea5ae 100644 --- a/source4/heimdal/lib/asn1/digest.asn1 +++ b/source4/heimdal/lib/asn1/digest.asn1 @@ -1,10 +1,19 @@ --- $Id: digest.asn1 20138 2007-02-02 21:08:24Z lha $ +-- $Id: digest.asn1 22152 2007-12-04 19:59:18Z lha $ DIGEST DEFINITIONS ::= BEGIN IMPORTS EncryptedData, Principal FROM krb5; +DigestTypes ::= BIT STRING { + ntlm-v1(0), + ntlm-v1-session(1), + ntlm-v2(2), + digest-md5(3), + chap-md5(4), + ms-chap-v2(5) +} + DigestInit ::= SEQUENCE { type UTF8String, -- http, sasl, chap, cram-md5 -- channel [0] SEQUENCE { @@ -95,7 +104,8 @@ DigestReqInner ::= CHOICE { init [0] DigestInit, digestRequest [1] DigestRequest, ntlmInit [2] NTLMInit, - ntlmRequest [3] NTLMRequest + ntlmRequest [3] NTLMRequest, + supportedMechs [4] NULL } DigestREQ ::= [APPLICATION 128] SEQUENCE { @@ -108,7 +118,9 @@ DigestRepInner ::= CHOICE { initReply [1] DigestInitReply, response [2] DigestResponse, ntlmInitReply [3] NTLMInitReply, - ntlmResponse [4] NTLMResponse + ntlmResponse [4] NTLMResponse, + supportedMechs [5] DigestTypes, + ... } DigestREP ::= [APPLICATION 129] SEQUENCE { diff --git a/source4/heimdal/lib/asn1/gen.c b/source4/heimdal/lib/asn1/gen.c index 26890212ae6..499f8eab363 100644 --- a/source4/heimdal/lib/asn1/gen.c +++ b/source4/heimdal/lib/asn1/gen.c @@ -33,7 +33,7 @@ #include "gen_locl.h" -RCSID("$Id: gen.c 21364 2007-06-27 08:51:06Z lha $"); +RCSID("$Id: gen.c 22429 2008-01-13 10:25:50Z lha $"); FILE *headerfile, *codefile, *logfile; diff --git a/source4/heimdal/lib/asn1/gen_encode.c b/source4/heimdal/lib/asn1/gen_encode.c index 9544514212f..08f1a9449f8 100644 --- a/source4/heimdal/lib/asn1/gen_encode.c +++ b/source4/heimdal/lib/asn1/gen_encode.c @@ -33,7 +33,7 @@ #include "gen_locl.h" -RCSID("$Id: gen_encode.c 21503 2007-07-12 11:57:19Z lha $"); +RCSID("$Id: gen_encode.c 22429 2008-01-13 10:25:50Z lha $"); static void encode_primitive (const char *typename, const char *name) diff --git a/source4/heimdal/lib/asn1/k5.asn1 b/source4/heimdal/lib/asn1/k5.asn1 index e3fe2b11e9a..18f1e1541b5 100644 --- a/source4/heimdal/lib/asn1/k5.asn1 +++ b/source4/heimdal/lib/asn1/k5.asn1 @@ -1,4 +1,4 @@ --- $Id: k5.asn1 21400 2007-07-02 19:57:31Z lha $ +-- $Id: k5.asn1 21965 2007-10-18 18:24:36Z lha $ KERBEROS5 DEFINITIONS ::= BEGIN @@ -137,6 +137,10 @@ ENCTYPE ::= INTEGER { ETYPE_ARCFOUR_HMAC_MD5(23), ETYPE_ARCFOUR_HMAC_MD5_56(24), ETYPE_ENCTYPE_PK_CROSS(48), +-- some "old" windows types + ETYPE_ARCFOUR_MD4(-128), + ETYPE_ARCFOUR_HMAC_OLD(-133), + ETYPE_ARCFOUR_HMAC_OLD_EXP(-135), -- these are for Heimdal internal use ETYPE_DES_CBC_NONE(-0x1000), ETYPE_DES3_CBC_NONE(-0x1001), diff --git a/source4/heimdal/lib/asn1/lex.c b/source4/heimdal/lib/asn1/lex.c index 86c4359f1a0..da4f729c3d6 100644 --- a/source4/heimdal/lib/asn1/lex.c +++ b/source4/heimdal/lib/asn1/lex.c @@ -1,6 +1,5 @@ -#include "config.h" -#line 3 "heimdal/lib/asn1/lex.c" +#line 3 "lex.c" #define YY_INT_ALIGNED short int @@ -827,7 +826,7 @@ char *yytext; * SUCH DAMAGE. */ -/* $Id: lex.l,v 1.31 2006/10/21 11:57:22 lha Exp $ */ +/* $Id: lex.l 18738 2006-10-21 11:57:22Z lha $ */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -852,7 +851,7 @@ static unsigned lineno = 1; static void unterminated(const char *, unsigned); /* This is for broken old lexes (solaris 10 and hpux) */ -#line 855 "heimdal/lib/asn1/lex.c" +#line 855 "lex.c" #define INITIAL 0 @@ -870,6 +869,35 @@ static void unterminated(const char *, unsigned); static int yy_init_globals (void ); +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * out_str ); + +int yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int line_number ); + /* Macros after this point can all be overridden by user definitions in * section 1. */ @@ -1007,7 +1035,7 @@ YY_DECL #line 68 "lex.l" -#line 1010 "heimdal/lib/asn1/lex.c" +#line 1039 "lex.c" if ( !(yy_init) ) { @@ -1676,7 +1704,7 @@ YY_RULE_SETUP #line 274 "lex.l" ECHO; YY_BREAK -#line 1679 "heimdal/lib/asn1/lex.c" +#line 1708 "lex.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1907,7 +1935,7 @@ static int yy_get_next_buffer (void) /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); + (yy_n_chars), num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } @@ -2408,7 +2436,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan + * @param str a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use diff --git a/source4/heimdal/lib/asn1/parse.c b/source4/heimdal/lib/asn1/parse.c index edcb313bd02..6a3e524e93a 100644 --- a/source4/heimdal/lib/asn1/parse.c +++ b/source4/heimdal/lib/asn1/parse.c @@ -248,7 +248,7 @@ /* Copy the first part of user declarations. */ -#line 36 "heimdal/lib/asn1/parse.y" +#line 36 "parse.y" #ifdef HAVE_CONFIG_H #include <config.h> @@ -280,7 +280,7 @@ struct string_list { /* Enabling traces. */ #ifndef YYDEBUG -# define YYDEBUG 0 +# define YYDEBUG 1 #endif /* Enabling verbose error messages. */ @@ -298,7 +298,7 @@ struct string_list { #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -#line 65 "heimdal/lib/asn1/parse.y" +#line 65 "parse.y" { int constant; struct value *value; @@ -314,7 +314,7 @@ typedef union YYSTYPE struct constraint_spec *constraint_spec; } /* Line 187 of yacc.c. */ -#line 318 "heimdal/lib/asn1/parse.y" +#line 318 "parse.c" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -327,7 +327,7 @@ typedef union YYSTYPE /* Line 216 of yacc.c. */ -#line 331 "heimdal/lib/asn1/parse.y" +#line 331 "parse.c" #ifdef short # undef short @@ -1762,29 +1762,29 @@ yyreduce: switch (yyn) { case 2: -#line 235 "heimdal/lib/asn1/parse.y" +#line 235 "parse.y" { checkundefined(); } break; case 4: -#line 242 "heimdal/lib/asn1/parse.y" +#line 242 "parse.y" { error_message("implicit tagging is not supported"); } break; case 5: -#line 244 "heimdal/lib/asn1/parse.y" +#line 244 "parse.y" { error_message("automatic tagging is not supported"); } break; case 7: -#line 249 "heimdal/lib/asn1/parse.y" +#line 249 "parse.y" { error_message("no extensibility options supported"); } break; case 17: -#line 270 "heimdal/lib/asn1/parse.y" +#line 270 "parse.y" { struct string_list *sl; for(sl = (yyvsp[(1) - (4)].sl); sl != NULL; sl = sl->next) { @@ -1796,7 +1796,7 @@ yyreduce: break; case 22: -#line 289 "heimdal/lib/asn1/parse.y" +#line 289 "parse.y" { (yyval.sl) = emalloc(sizeof(*(yyval.sl))); (yyval.sl)->string = (yyvsp[(1) - (3)].name); @@ -1805,7 +1805,7 @@ yyreduce: break; case 23: -#line 295 "heimdal/lib/asn1/parse.y" +#line 295 "parse.y" { (yyval.sl) = emalloc(sizeof(*(yyval.sl))); (yyval.sl)->string = (yyvsp[(1) - (1)].name); @@ -1814,7 +1814,7 @@ yyreduce: break; case 24: -#line 303 "heimdal/lib/asn1/parse.y" +#line 303 "parse.y" { Symbol *s = addsym ((yyvsp[(1) - (3)].name)); s->stype = Stype; @@ -1825,7 +1825,7 @@ yyreduce: break; case 42: -#line 334 "heimdal/lib/asn1/parse.y" +#line 334 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_Boolean, TE_EXPLICIT, new_type(TBoolean)); @@ -1833,7 +1833,7 @@ yyreduce: break; case 43: -#line 341 "heimdal/lib/asn1/parse.y" +#line 341 "parse.y" { if((yyvsp[(2) - (5)].value)->type != integervalue) error_message("Non-integer used in first part of range"); @@ -1846,7 +1846,7 @@ yyreduce: break; case 44: -#line 351 "heimdal/lib/asn1/parse.y" +#line 351 "parse.y" { if((yyvsp[(2) - (5)].value)->type != integervalue) error_message("Non-integer in first part of range"); @@ -1857,7 +1857,7 @@ yyreduce: break; case 45: -#line 359 "heimdal/lib/asn1/parse.y" +#line 359 "parse.y" { if((yyvsp[(4) - (5)].value)->type != integervalue) error_message("Non-integer in second part of range"); @@ -1868,7 +1868,7 @@ yyreduce: break; case 46: -#line 367 "heimdal/lib/asn1/parse.y" +#line 367 "parse.y" { if((yyvsp[(2) - (3)].value)->type != integervalue) error_message("Non-integer used in limit"); @@ -1879,7 +1879,7 @@ yyreduce: break; case 47: -#line 378 "heimdal/lib/asn1/parse.y" +#line 378 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, new_type(TInteger)); @@ -1887,7 +1887,7 @@ yyreduce: break; case 48: -#line 383 "heimdal/lib/asn1/parse.y" +#line 383 "parse.y" { (yyval.type) = new_type(TInteger); (yyval.type)->range = (yyvsp[(2) - (2)].range); @@ -1896,7 +1896,7 @@ yyreduce: break; case 49: -#line 389 "heimdal/lib/asn1/parse.y" +#line 389 "parse.y" { (yyval.type) = new_type(TInteger); (yyval.type)->members = (yyvsp[(3) - (4)].members); @@ -1905,7 +1905,7 @@ yyreduce: break; case 50: -#line 397 "heimdal/lib/asn1/parse.y" +#line 397 "parse.y" { (yyval.members) = emalloc(sizeof(*(yyval.members))); ASN1_TAILQ_INIT((yyval.members)); @@ -1914,7 +1914,7 @@ yyreduce: break; case 51: -#line 403 "heimdal/lib/asn1/parse.y" +#line 403 "parse.y" { ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), (yyvsp[(3) - (3)].member), members); (yyval.members) = (yyvsp[(1) - (3)].members); @@ -1922,12 +1922,12 @@ yyreduce: break; case 52: -#line 408 "heimdal/lib/asn1/parse.y" +#line 408 "parse.y" { (yyval.members) = (yyvsp[(1) - (3)].members); } break; case 53: -#line 412 "heimdal/lib/asn1/parse.y" +#line 412 "parse.y" { (yyval.member) = emalloc(sizeof(*(yyval.member))); (yyval.member)->name = (yyvsp[(1) - (4)].name); @@ -1941,7 +1941,7 @@ yyreduce: break; case 54: -#line 425 "heimdal/lib/asn1/parse.y" +#line 425 "parse.y" { (yyval.type) = new_type(TInteger); (yyval.type)->members = (yyvsp[(3) - (4)].members); @@ -1950,7 +1950,7 @@ yyreduce: break; case 56: -#line 436 "heimdal/lib/asn1/parse.y" +#line 436 "parse.y" { (yyval.type) = new_type(TBitString); (yyval.type)->members = emalloc(sizeof(*(yyval.type)->members)); @@ -1960,7 +1960,7 @@ yyreduce: break; case 57: -#line 443 "heimdal/lib/asn1/parse.y" +#line 443 "parse.y" { (yyval.type) = new_type(TBitString); (yyval.type)->members = (yyvsp[(4) - (5)].members); @@ -1969,7 +1969,7 @@ yyreduce: break; case 58: -#line 451 "heimdal/lib/asn1/parse.y" +#line 451 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_OID, TE_EXPLICIT, new_type(TOID)); @@ -1977,7 +1977,7 @@ yyreduce: break; case 59: -#line 457 "heimdal/lib/asn1/parse.y" +#line 457 "parse.y" { Type *t = new_type(TOctetString); t->range = (yyvsp[(3) - (3)].range); @@ -1987,7 +1987,7 @@ yyreduce: break; case 60: -#line 466 "heimdal/lib/asn1/parse.y" +#line 466 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_Null, TE_EXPLICIT, new_type(TNull)); @@ -1995,17 +1995,17 @@ yyreduce: break; case 61: -#line 473 "heimdal/lib/asn1/parse.y" +#line 473 "parse.y" { (yyval.range) = NULL; } break; case 62: -#line 475 "heimdal/lib/asn1/parse.y" +#line 475 "parse.y" { (yyval.range) = (yyvsp[(2) - (2)].range); } break; case 63: -#line 480 "heimdal/lib/asn1/parse.y" +#line 480 "parse.y" { (yyval.type) = new_type(TSequence); (yyval.type)->members = (yyvsp[(3) - (4)].members); @@ -2014,7 +2014,7 @@ yyreduce: break; case 64: -#line 486 "heimdal/lib/asn1/parse.y" +#line 486 "parse.y" { (yyval.type) = new_type(TSequence); (yyval.type)->members = NULL; @@ -2023,7 +2023,7 @@ yyreduce: break; case 65: -#line 494 "heimdal/lib/asn1/parse.y" +#line 494 "parse.y" { (yyval.type) = new_type(TSequenceOf); (yyval.type)->range = (yyvsp[(2) - (4)].range); @@ -2033,7 +2033,7 @@ yyreduce: break; case 66: -#line 503 "heimdal/lib/asn1/parse.y" +#line 503 "parse.y" { (yyval.type) = new_type(TSet); (yyval.type)->members = (yyvsp[(3) - (4)].members); @@ -2042,7 +2042,7 @@ yyreduce: break; case 67: -#line 509 "heimdal/lib/asn1/parse.y" +#line 509 "parse.y" { (yyval.type) = new_type(TSet); (yyval.type)->members = NULL; @@ -2051,7 +2051,7 @@ yyreduce: break; case 68: -#line 517 "heimdal/lib/asn1/parse.y" +#line 517 "parse.y" { (yyval.type) = new_type(TSetOf); (yyval.type)->subtype = (yyvsp[(3) - (3)].type); @@ -2060,7 +2060,7 @@ yyreduce: break; case 69: -#line 525 "heimdal/lib/asn1/parse.y" +#line 525 "parse.y" { (yyval.type) = new_type(TChoice); (yyval.type)->members = (yyvsp[(3) - (4)].members); @@ -2068,7 +2068,7 @@ yyreduce: break; case 72: -#line 536 "heimdal/lib/asn1/parse.y" +#line 536 "parse.y" { Symbol *s = addsym((yyvsp[(1) - (1)].name)); (yyval.type) = new_type(TType); @@ -2080,7 +2080,7 @@ yyreduce: break; case 73: -#line 547 "heimdal/lib/asn1/parse.y" +#line 547 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_GeneralizedTime, TE_EXPLICIT, new_type(TGeneralizedTime)); @@ -2088,7 +2088,7 @@ yyreduce: break; case 74: -#line 552 "heimdal/lib/asn1/parse.y" +#line 552 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_UTCTime, TE_EXPLICIT, new_type(TUTCTime)); @@ -2096,7 +2096,7 @@ yyreduce: break; case 75: -#line 559 "heimdal/lib/asn1/parse.y" +#line 559 "parse.y" { /* if (Constraint.type == contentConstrant) { assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too @@ -2112,14 +2112,14 @@ yyreduce: break; case 76: -#line 575 "heimdal/lib/asn1/parse.y" +#line 575 "parse.y" { (yyval.constraint_spec) = (yyvsp[(2) - (3)].constraint_spec); } break; case 80: -#line 588 "heimdal/lib/asn1/parse.y" +#line 588 "parse.y" { (yyval.constraint_spec) = new_constraint_spec(CT_CONTENTS); (yyval.constraint_spec)->u.content.type = (yyvsp[(2) - (2)].type); @@ -2128,7 +2128,7 @@ yyreduce: break; case 81: -#line 594 "heimdal/lib/asn1/parse.y" +#line 594 "parse.y" { if ((yyvsp[(3) - (3)].value)->type != objectidentifiervalue) error_message("Non-OID used in ENCODED BY constraint"); @@ -2139,7 +2139,7 @@ yyreduce: break; case 82: -#line 602 "heimdal/lib/asn1/parse.y" +#line 602 "parse.y" { if ((yyvsp[(5) - (5)].value)->type != objectidentifiervalue) error_message("Non-OID used in ENCODED BY constraint"); @@ -2150,14 +2150,14 @@ yyreduce: break; case 83: -#line 612 "heimdal/lib/asn1/parse.y" +#line 612 "parse.y" { (yyval.constraint_spec) = new_constraint_spec(CT_USER); } break; case 84: -#line 618 "heimdal/lib/asn1/parse.y" +#line 618 "parse.y" { (yyval.type) = new_type(TTag); (yyval.type)->tag = (yyvsp[(1) - (3)].tag); @@ -2171,7 +2171,7 @@ yyreduce: break; case 85: -#line 631 "heimdal/lib/asn1/parse.y" +#line 631 "parse.y" { (yyval.tag).tagclass = (yyvsp[(2) - (4)].constant); (yyval.tag).tagvalue = (yyvsp[(3) - (4)].constant); @@ -2180,56 +2180,56 @@ yyreduce: break; case 86: -#line 639 "heimdal/lib/asn1/parse.y" +#line 639 "parse.y" { (yyval.constant) = ASN1_C_CONTEXT; } break; case 87: -#line 643 "heimdal/lib/asn1/parse.y" +#line 643 "parse.y" { (yyval.constant) = ASN1_C_UNIV; } break; case 88: -#line 647 "heimdal/lib/asn1/parse.y" +#line 647 "parse.y" { (yyval.constant) = ASN1_C_APPL; } break; case 89: -#line 651 "heimdal/lib/asn1/parse.y" +#line 651 "parse.y" { (yyval.constant) = ASN1_C_PRIVATE; } break; case 90: -#line 657 "heimdal/lib/asn1/parse.y" +#line 657 "parse.y" { (yyval.constant) = TE_EXPLICIT; } break; case 91: -#line 661 "heimdal/lib/asn1/parse.y" +#line 661 "parse.y" { (yyval.constant) = TE_EXPLICIT; } break; case 92: -#line 665 "heimdal/lib/asn1/parse.y" +#line 665 "parse.y" { (yyval.constant) = TE_IMPLICIT; } break; case 93: -#line 672 "heimdal/lib/asn1/parse.y" +#line 672 "parse.y" { Symbol *s; s = addsym ((yyvsp[(1) - (4)].name)); @@ -2241,7 +2241,7 @@ yyreduce: break; case 95: -#line 686 "heimdal/lib/asn1/parse.y" +#line 686 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_GeneralString, TE_EXPLICIT, new_type(TGeneralString)); @@ -2249,7 +2249,7 @@ yyreduce: break; case 96: -#line 691 "heimdal/lib/asn1/parse.y" +#line 691 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_UTF8String, TE_EXPLICIT, new_type(TUTF8String)); @@ -2257,7 +2257,7 @@ yyreduce: break; case 97: -#line 696 "heimdal/lib/asn1/parse.y" +#line 696 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_PrintableString, TE_EXPLICIT, new_type(TPrintableString)); @@ -2265,7 +2265,7 @@ yyreduce: break; case 98: -#line 701 "heimdal/lib/asn1/parse.y" +#line 701 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_VisibleString, TE_EXPLICIT, new_type(TVisibleString)); @@ -2273,7 +2273,7 @@ yyreduce: break; case 99: -#line 706 "heimdal/lib/asn1/parse.y" +#line 706 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_IA5String, TE_EXPLICIT, new_type(TIA5String)); @@ -2281,7 +2281,7 @@ yyreduce: break; case 100: -#line 711 "heimdal/lib/asn1/parse.y" +#line 711 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_BMPString, TE_EXPLICIT, new_type(TBMPString)); @@ -2289,7 +2289,7 @@ yyreduce: break; case 101: -#line 716 "heimdal/lib/asn1/parse.y" +#line 716 "parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_UniversalString, TE_EXPLICIT, new_type(TUniversalString)); @@ -2297,7 +2297,7 @@ yyreduce: break; case 102: -#line 724 "heimdal/lib/asn1/parse.y" +#line 724 "parse.y" { (yyval.members) = emalloc(sizeof(*(yyval.members))); ASN1_TAILQ_INIT((yyval.members)); @@ -2306,7 +2306,7 @@ yyreduce: break; case 103: -#line 730 "heimdal/lib/asn1/parse.y" +#line 730 "parse.y" { ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), (yyvsp[(3) - (3)].member), members); (yyval.members) = (yyvsp[(1) - (3)].members); @@ -2314,7 +2314,7 @@ yyreduce: break; case 104: -#line 735 "heimdal/lib/asn1/parse.y" +#line 735 "parse.y" { struct member *m = ecalloc(1, sizeof(*m)); m->name = estrdup("..."); @@ -2326,7 +2326,7 @@ yyreduce: break; case 105: -#line 746 "heimdal/lib/asn1/parse.y" +#line 746 "parse.y" { (yyval.member) = emalloc(sizeof(*(yyval.member))); (yyval.member)->name = (yyvsp[(1) - (2)].name); @@ -2338,7 +2338,7 @@ yyreduce: break; case 106: -#line 757 "heimdal/lib/asn1/parse.y" +#line 757 "parse.y" { (yyval.member) = (yyvsp[(1) - (1)].member); (yyval.member)->optional = 0; @@ -2347,7 +2347,7 @@ yyreduce: break; case 107: -#line 763 "heimdal/lib/asn1/parse.y" +#line 763 "parse.y" { (yyval.member) = (yyvsp[(1) - (2)].member); (yyval.member)->optional = 1; @@ -2356,7 +2356,7 @@ yyreduce: break; case 108: -#line 769 "heimdal/lib/asn1/parse.y" +#line 769 "parse.y" { (yyval.member) = (yyvsp[(1) - (3)].member); (yyval.member)->optional = 0; @@ -2365,7 +2365,7 @@ yyreduce: break; case 109: -#line 777 "heimdal/lib/asn1/parse.y" +#line 777 "parse.y" { (yyval.members) = emalloc(sizeof(*(yyval.members))); ASN1_TAILQ_INIT((yyval.members)); @@ -2374,7 +2374,7 @@ yyreduce: break; case 110: -#line 783 "heimdal/lib/asn1/parse.y" +#line 783 "parse.y" { ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), (yyvsp[(3) - (3)].member), members); (yyval.members) = (yyvsp[(1) - (3)].members); @@ -2382,7 +2382,7 @@ yyreduce: break; case 111: -#line 790 "heimdal/lib/asn1/parse.y" +#line 790 "parse.y" { (yyval.member) = emalloc(sizeof(*(yyval.member))); (yyval.member)->name = (yyvsp[(1) - (4)].name); @@ -2396,26 +2396,26 @@ yyreduce: break; case 113: -#line 803 "heimdal/lib/asn1/parse.y" +#line 803 "parse.y" { (yyval.objid) = NULL; } break; case 114: -#line 807 "heimdal/lib/asn1/parse.y" +#line 807 "parse.y" { (yyval.objid) = (yyvsp[(2) - (3)].objid); } break; case 115: -#line 813 "heimdal/lib/asn1/parse.y" +#line 813 "parse.y" { (yyval.objid) = NULL; } break; case 116: -#line 817 "heimdal/lib/asn1/parse.y" +#line 817 "parse.y" { if ((yyvsp[(2) - (2)].objid)) { (yyval.objid) = (yyvsp[(2) - (2)].objid); @@ -2427,14 +2427,14 @@ yyreduce: break; case 117: -#line 828 "heimdal/lib/asn1/parse.y" +#line 828 "parse.y" { (yyval.objid) = new_objid((yyvsp[(1) - (4)].name), (yyvsp[(3) - (4)].constant)); } break; case 118: -#line 832 "heimdal/lib/asn1/parse.y" +#line 832 "parse.y" { Symbol *s = addsym((yyvsp[(1) - (1)].name)); if(s->stype != SValue || @@ -2448,14 +2448,14 @@ yyreduce: break; case 119: -#line 843 "heimdal/lib/asn1/parse.y" +#line 843 "parse.y" { (yyval.objid) = new_objid(NULL, (yyvsp[(1) - (1)].constant)); } break; case 129: -#line 866 "heimdal/lib/asn1/parse.y" +#line 866 "parse.y" { Symbol *s = addsym((yyvsp[(1) - (1)].name)); if(s->stype != SValue) @@ -2467,7 +2467,7 @@ yyreduce: break; case 130: -#line 877 "heimdal/lib/asn1/parse.y" +#line 877 "parse.y" { (yyval.value) = emalloc(sizeof(*(yyval.value))); (yyval.value)->type = stringvalue; @@ -2476,7 +2476,7 @@ yyreduce: break; case 131: -#line 885 "heimdal/lib/asn1/parse.y" +#line 885 "parse.y" { (yyval.value) = emalloc(sizeof(*(yyval.value))); (yyval.value)->type = booleanvalue; @@ -2485,7 +2485,7 @@ yyreduce: break; case 132: -#line 891 "heimdal/lib/asn1/parse.y" +#line 891 "parse.y" { (yyval.value) = emalloc(sizeof(*(yyval.value))); (yyval.value)->type = booleanvalue; @@ -2494,7 +2494,7 @@ yyreduce: break; case 133: -#line 899 "heimdal/lib/asn1/parse.y" +#line 899 "parse.y" { (yyval.value) = emalloc(sizeof(*(yyval.value))); (yyval.value)->type = integervalue; @@ -2503,13 +2503,13 @@ yyreduce: break; case 135: -#line 910 "heimdal/lib/asn1/parse.y" +#line 910 "parse.y" { } break; case 136: -#line 915 "heimdal/lib/asn1/parse.y" +#line 915 "parse.y" { (yyval.value) = emalloc(sizeof(*(yyval.value))); (yyval.value)->type = objectidentifiervalue; @@ -2519,7 +2519,7 @@ yyreduce: /* Line 1267 of yacc.c. */ -#line 2523 "heimdal/lib/asn1/parse.y" +#line 2523 "parse.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -2733,7 +2733,7 @@ yyreturn: } -#line 922 "heimdal/lib/asn1/parse.y" +#line 922 "parse.y" void diff --git a/source4/heimdal/lib/asn1/parse.h b/source4/heimdal/lib/asn1/parse.h index bea506ca7b9..5e73094f9e6 100644 --- a/source4/heimdal/lib/asn1/parse.h +++ b/source4/heimdal/lib/asn1/parse.h @@ -222,7 +222,7 @@ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -#line 65 "heimdal/lib/asn1/parse.y" +#line 65 "parse.y" { int constant; struct value *value; @@ -238,7 +238,7 @@ typedef union YYSTYPE struct constraint_spec *constraint_spec; } /* Line 1489 of yacc.c. */ -#line 242 "heimdal/lib/asn1/parse.y" +#line 242 "parse.h" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 diff --git a/source4/heimdal/lib/asn1/pkinit.asn1 b/source4/heimdal/lib/asn1/pkinit.asn1 index 1bfc11ad740..989b26581b3 100644 --- a/source4/heimdal/lib/asn1/pkinit.asn1 +++ b/source4/heimdal/lib/asn1/pkinit.asn1 @@ -2,7 +2,7 @@ PKINIT DEFINITIONS ::= BEGIN -IMPORTS EncryptionKey, PrincipalName, Realm, KerberosTime, Checksum FROM krb5 +IMPORTS EncryptionKey, PrincipalName, Realm, KerberosTime, Checksum, Ticket FROM krb5 IssuerAndSerialNumber, ContentInfo FROM cms SubjectPublicKeyInfo, AlgorithmIdentifier FROM rfc2459 heim_any FROM heim; @@ -40,6 +40,11 @@ td-dh-parameters INTEGER ::= 109 DHNonce ::= OCTET STRING +KDFAlgorithmId ::= SEQUENCE { + kdf-id [0] OBJECT IDENTIFIER, + ... +} + TrustedCA ::= SEQUENCE { caName [0] IMPLICIT OCTET STRING, certificateSerialNumber [1] INTEGER OPTIONAL, @@ -76,6 +81,8 @@ AuthPack ::= SEQUENCE { clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL, supportedCMSTypes [2] SEQUENCE OF AlgorithmIdentifier OPTIONAL, clientDHNonce [3] DHNonce OPTIONAL, + ..., + supportedKDFs [4] SEQUENCE OF KDFAlgorithmId OPTIONAL, ... } @@ -89,10 +96,12 @@ KRB5PrincipalName ::= SEQUENCE { AD-INITIAL-VERIFIED-CAS ::= SEQUENCE OF ExternalPrincipalIdentifier - DHRepInfo ::= SEQUENCE { dhSignedData [0] IMPLICIT OCTET STRING, - serverDHNonce [1] DHNonce OPTIONAL + serverDHNonce [1] DHNonce OPTIONAL, + ..., + kdf [2] KDFAlgorithmId OPTIONAL, + ... } PA-PK-AS-REP ::= CHOICE { @@ -162,4 +171,12 @@ ReplyKeyPack-Win2k ::= SEQUENCE { ... } +PkinitSuppPubInfo ::= SEQUENCE { + enctype [0] INTEGER (-2147483648..2147483647), + as-REQ [1] OCTET STRING, + pk-as-rep [2] OCTET STRING, + ticket [3] Ticket, + ... +} + END diff --git a/source4/heimdal/lib/asn1/rfc2459.asn1 b/source4/heimdal/lib/asn1/rfc2459.asn1 index 0ec3b695ebe..8e24f0740b8 100644 --- a/source4/heimdal/lib/asn1/rfc2459.asn1 +++ b/source4/heimdal/lib/asn1/rfc2459.asn1 @@ -21,6 +21,8 @@ id-pkcs1-sha256WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 11 } id-pkcs1-sha384WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 12 } id-pkcs1-sha512WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 13 } +id-heim-rsa-pkcs1-x509 OBJECT IDENTIFIER ::= { 1 2 752 43 16 1 } + id-pkcs-2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 2 } id-pkcs2-md2 OBJECT IDENTIFIER ::= { id-pkcs-2 2 } diff --git a/source4/heimdal/lib/com_err/lex.c b/source4/heimdal/lib/com_err/lex.c index 7a85b302a11..3c6ea3beb71 100644 --- a/source4/heimdal/lib/com_err/lex.c +++ b/source4/heimdal/lib/com_err/lex.c @@ -1,6 +1,5 @@ -#include "config.h" -#line 3 "heimdal/lib/com_err/lex.c" +#line 3 "lex.c" #define YY_INT_ALIGNED short int @@ -524,7 +523,7 @@ char *yytext; #include "parse.h" #include "lex.h" -RCSID("$Id: lex.l,v 1.8 2005/05/16 08:52:54 lha Exp $"); +RCSID("$Id: lex.l 15143 2005-05-16 08:52:54Z lha $"); static unsigned lineno = 1; static int getstring(void); @@ -533,7 +532,7 @@ static int getstring(void); #undef ECHO -#line 536 "heimdal/lib/com_err/lex.c" +#line 536 "lex.c" #define INITIAL 0 @@ -551,6 +550,35 @@ static int getstring(void); static int yy_init_globals (void ); +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * out_str ); + +int yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int line_number ); + /* Macros after this point can all be overridden by user definitions in * section 1. */ @@ -688,7 +716,7 @@ YY_DECL #line 59 "lex.l" -#line 691 "heimdal/lib/com_err/lex.c" +#line 720 "lex.c" if ( !(yy_init) ) { @@ -852,7 +880,7 @@ YY_RULE_SETUP #line 75 "lex.l" ECHO; YY_BREAK -#line 855 "heimdal/lib/com_err/lex.c" +#line 884 "lex.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1083,7 +1111,7 @@ static int yy_get_next_buffer (void) /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); + (yy_n_chars), num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } @@ -1584,7 +1612,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan + * @param str a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use diff --git a/source4/heimdal/lib/com_err/parse.c b/source4/heimdal/lib/com_err/parse.c index 95fe18f16e4..4bacb721ca1 100644 --- a/source4/heimdal/lib/com_err/parse.c +++ b/source4/heimdal/lib/com_err/parse.c @@ -90,7 +90,7 @@ /* Copy the first part of user declarations. */ -#line 1 "heimdal/lib/com_err/parse.y" +#line 1 "parse.y" /* * Copyright (c) 1998 - 2000 Kungliga Tekniska Högskolan @@ -163,13 +163,13 @@ extern char *yytext; #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -#line 53 "heimdal/lib/com_err/parse.y" +#line 53 "parse.y" { char *string; int number; } /* Line 187 of yacc.c. */ -#line 173 "heimdal/lib/com_err/parse.y" +#line 173 "parse.c" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -182,7 +182,7 @@ typedef union YYSTYPE /* Line 216 of yacc.c. */ -#line 186 "heimdal/lib/com_err/parse.y" +#line 186 "parse.c" #ifdef short # undef short @@ -1381,14 +1381,14 @@ yyreduce: switch (yyn) { case 6: -#line 73 "heimdal/lib/com_err/parse.y" +#line 73 "parse.y" { id_str = (yyvsp[(2) - (2)].string); } break; case 7: -#line 79 "heimdal/lib/com_err/parse.y" +#line 79 "parse.y" { base_id = name2number((yyvsp[(2) - (2)].string)); strlcpy(name, (yyvsp[(2) - (2)].string), sizeof(name)); @@ -1397,7 +1397,7 @@ yyreduce: break; case 8: -#line 85 "heimdal/lib/com_err/parse.y" +#line 85 "parse.y" { base_id = name2number((yyvsp[(2) - (3)].string)); strlcpy(name, (yyvsp[(3) - (3)].string), sizeof(name)); @@ -1407,14 +1407,14 @@ yyreduce: break; case 11: -#line 98 "heimdal/lib/com_err/parse.y" +#line 98 "parse.y" { number = (yyvsp[(2) - (2)].number); } break; case 12: -#line 102 "heimdal/lib/com_err/parse.y" +#line 102 "parse.y" { free(prefix); asprintf (&prefix, "%s_", (yyvsp[(2) - (2)].string)); @@ -1425,7 +1425,7 @@ yyreduce: break; case 13: -#line 110 "heimdal/lib/com_err/parse.y" +#line 110 "parse.y" { prefix = realloc(prefix, 1); if (prefix == NULL) @@ -1435,7 +1435,7 @@ yyreduce: break; case 14: -#line 117 "heimdal/lib/com_err/parse.y" +#line 117 "parse.y" { struct error_code *ec = malloc(sizeof(*ec)); @@ -1458,7 +1458,7 @@ yyreduce: break; case 15: -#line 137 "heimdal/lib/com_err/parse.y" +#line 137 "parse.y" { YYACCEPT; } @@ -1466,7 +1466,7 @@ yyreduce: /* Line 1267 of yacc.c. */ -#line 1470 "heimdal/lib/com_err/parse.y" +#line 1470 "parse.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -1680,7 +1680,7 @@ yyreturn: } -#line 142 "heimdal/lib/com_err/parse.y" +#line 142 "parse.y" static long diff --git a/source4/heimdal/lib/com_err/parse.h b/source4/heimdal/lib/com_err/parse.h index 9aabca90236..4c9681ff34f 100644 --- a/source4/heimdal/lib/com_err/parse.h +++ b/source4/heimdal/lib/com_err/parse.h @@ -64,13 +64,13 @@ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -#line 53 "heimdal/lib/com_err/parse.y" +#line 53 "parse.y" { char *string; int number; } /* Line 1489 of yacc.c. */ -#line 74 "heimdal/lib/com_err/parse.y" +#line 74 "parse.h" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h index cca529fe26f..2223f4f22f7 100644 --- a/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: gssapi_krb5.h 20385 2007-04-18 08:51:32Z lha $ */ +/* $Id: gssapi_krb5.h 22655 2008-02-26 12:40:35Z lha $ */ #ifndef GSSAPI_KRB5_H_ #define GSSAPI_KRB5_H_ @@ -80,6 +80,7 @@ extern gss_OID GSS_KRB5_GET_SERVICE_KEYBLOCK_X; /* Extensions creds */ extern gss_OID GSS_KRB5_IMPORT_CRED_X; extern gss_OID GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X; +extern gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X; /* * kerberos mechanism specific functions diff --git a/source4/heimdal/lib/gssapi/gssapi_mech.h b/source4/heimdal/lib/gssapi/gssapi_mech.h index 403990ad47a..b360de13fca 100644 --- a/source4/heimdal/lib/gssapi/gssapi_mech.h +++ b/source4/heimdal/lib/gssapi/gssapi_mech.h @@ -356,4 +356,6 @@ gssapi_mech_interface __gss_spnego_initialize(void); gssapi_mech_interface __gss_krb5_initialize(void); gssapi_mech_interface __gss_ntlm_initialize(void); +void gss_mg_collect_error(gss_OID, OM_uint32, OM_uint32); + #endif /* GSSAPI_MECH_H */ diff --git a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c index d5c70636bc5..051446c19b4 100644 --- a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c +++ b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c @@ -33,7 +33,7 @@ #include "krb5/gsskrb5_locl.h" -RCSID("$Id: acquire_cred.c 21221 2007-06-20 08:42:10Z lha $"); +RCSID("$Id: acquire_cred.c 22596 2008-02-18 18:05:55Z lha $"); OM_uint32 __gsskrb5_ccache_lifetime(OM_uint32 *minor_status, @@ -128,9 +128,12 @@ static OM_uint32 acquire_initiator_cred ret = GSS_S_FAILURE; memset(&cred, 0, sizeof(cred)); - /* If we have a preferred principal, lets try to find it in all - * caches, otherwise, fall back to default cache. Ignore - * errors. */ + /* + * If we have a preferred principal, lets try to find it in all + * caches, otherwise, fall back to default cache, ignore all + * errors while searching. + */ + if (handle->principal) kret = krb5_cc_cache_match (context, handle->principal, @@ -142,32 +145,30 @@ static OM_uint32 acquire_initiator_cred if (kret) goto end; } - kret = krb5_cc_get_principal(context, ccache, - &def_princ); + kret = krb5_cc_get_principal(context, ccache, &def_princ); if (kret != 0) { /* we'll try to use a keytab below */ - krb5_cc_destroy(context, ccache); - ccache = NULL; + krb5_cc_close(context, ccache); + def_princ = NULL; kret = 0; } else if (handle->principal == NULL) { - kret = krb5_copy_principal(context, def_princ, - &handle->principal); + kret = krb5_copy_principal(context, def_princ, &handle->principal); if (kret) goto end; } else if (handle->principal != NULL && - krb5_principal_compare(context, handle->principal, - def_princ) == FALSE) { - /* Before failing, lets check the keytab */ + krb5_principal_compare(context, handle->principal, + def_princ) == FALSE) { krb5_free_principal(context, def_princ); def_princ = NULL; + krb5_cc_close(context, ccache); + ccache = NULL; } if (def_princ == NULL) { /* We have no existing credentials cache, * so attempt to get a TGT using a keytab. */ if (handle->principal == NULL) { - kret = krb5_get_default_principal(context, - &handle->principal); + kret = krb5_get_default_principal(context, &handle->principal); if (kret) goto end; } @@ -182,16 +183,19 @@ static OM_uint32 acquire_initiator_cred krb5_get_init_creds_opt_free(context, opt); if (kret) goto end; - kret = krb5_cc_gen_new(context, &krb5_mcc_ops, - &ccache); + kret = krb5_cc_gen_new(context, &krb5_mcc_ops, &ccache); if (kret) goto end; kret = krb5_cc_initialize(context, ccache, cred.client); - if (kret) + if (kret) { + krb5_cc_destroy(context, ccache); goto end; + } kret = krb5_cc_store_cred(context, ccache, &cred); - if (kret) + if (kret) { + krb5_cc_destroy(context, ccache); goto end; + } handle->lifetime = cred.times.endtime; handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; } else { @@ -201,8 +205,10 @@ static OM_uint32 acquire_initiator_cred ccache, handle->principal, &handle->lifetime); - if (ret != GSS_S_COMPLETE) + if (ret != GSS_S_COMPLETE) { + krb5_cc_close(context, ccache); goto end; + } kret = 0; } @@ -216,13 +222,8 @@ end: krb5_free_principal(context, def_princ); if (keytab != NULL) krb5_kt_close(context, keytab); - if (ret != GSS_S_COMPLETE) { - if (ccache != NULL) - krb5_cc_close(context, ccache); - if (kret != 0) { - *minor_status = kret; - } - } + if (ret != GSS_S_COMPLETE && kret != 0) + *minor_status = kret; return (ret); } @@ -257,8 +258,23 @@ static OM_uint32 acquire_acceptor_cred goto end; krb5_kt_free_entry(context, &entry); ret = GSS_S_COMPLETE; - } - + } else { + /* + * Check if there is at least one entry in the keytab before + * declaring it as an useful keytab. + */ + krb5_keytab_entry tmp; + krb5_kt_cursor c; + + kret = krb5_kt_start_seq_get (context, handle->keytab, &c); + if (kret) + goto end; + if (krb5_kt_next_entry(context, handle->keytab, &tmp, &c) == 0) { + krb5_kt_free_entry(context, &tmp); + ret = GSS_S_COMPLETE; /* ok found one entry */ + } + krb5_kt_end_seq_get (context, handle->keytab, &c); + } end: if (ret != GSS_S_COMPLETE) { if (handle->keytab != NULL) diff --git a/source4/heimdal/lib/gssapi/krb5/external.c b/source4/heimdal/lib/gssapi/krb5/external.c index d4c1bc4db29..03fe61dc574 100644 --- a/source4/heimdal/lib/gssapi/krb5/external.c +++ b/source4/heimdal/lib/gssapi/krb5/external.c @@ -34,7 +34,7 @@ #include "krb5/gsskrb5_locl.h" #include <gssapi_mech.h> -RCSID("$Id: external.c 20386 2007-04-18 08:52:08Z lha $"); +RCSID("$Id: external.c 22128 2007-12-04 00:56:55Z lha $"); /* * The implementation must reserve static storage for a @@ -374,8 +374,6 @@ gss_OID GSS_SASL_DIGEST_MD5_MECHANISM = &gss_sasl_digest_md5_mechanism_desc; * Context for krb5 calls. */ -krb5_context context; - /* * */ diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h index c2239f13462..64a0dd36b19 100644 --- a/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h +++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h @@ -413,7 +413,7 @@ _gsskrb5_init (krb5_context */*context*/); OM_uint32 _gsskrb5_init_sec_context ( OM_uint32 * /*minor_status*/, - const gss_cred_id_t /*initiator_cred_handle*/, + const gss_cred_id_t /*cred_handle*/, gss_ctx_id_t * /*context_handle*/, const gss_name_t /*target_name*/, const gss_OID /*mech_type*/, diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h index 6ffb6070352..3e8c1b8fa65 100644 --- a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h +++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: gsskrb5_locl.h 20324 2007-04-12 16:46:01Z lha $ */ +/* $Id: gsskrb5_locl.h 22655 2008-02-26 12:40:35Z lha $ */ #ifndef GSSKRB5_LOCL_H #define GSSKRB5_LOCL_H @@ -86,6 +86,7 @@ typedef struct { krb5_principal principal; int cred_flags; #define GSS_CF_DESTROY_CRED_ON_RELEASE 1 +#define GSS_CF_NO_CI_FLAGS 2 struct krb5_keytab_data *keytab; OM_uint32 lifetime; gss_cred_usage_t usage; diff --git a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c index 4d1ae0daa9f..d4482a54b27 100644 --- a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5/gsskrb5_locl.h" -RCSID("$Id: init_sec_context.c 20326 2007-04-12 16:49:57Z lha $"); +RCSID("$Id: init_sec_context.c 22671 2008-03-09 23:57:54Z lha $"); /* * copy the addresses from `input_chan_bindings' (if any) to @@ -326,7 +326,7 @@ do_delegation (krb5_context context, static OM_uint32 init_auth (OM_uint32 * minor_status, - gsskrb5_cred initiator_cred_handle, + gsskrb5_cred cred, gsskrb5_ctx ctx, krb5_context context, krb5_const_principal name, @@ -344,7 +344,7 @@ init_auth OM_uint32 ret = GSS_S_FAILURE; krb5_error_code kret; krb5_flags ap_options; - krb5_creds *cred = NULL; + krb5_creds *kcred = NULL; krb5_data outbuf; krb5_ccache ccache = NULL; uint32_t flags; @@ -362,7 +362,7 @@ init_auth if (actual_mech_type) *actual_mech_type = GSS_KRB5_MECHANISM; - if (initiator_cred_handle == NULL) { + if (cred == NULL) { kret = krb5_cc_default (context, &ccache); if (kret) { *minor_status = kret; @@ -370,7 +370,7 @@ init_auth goto failure; } } else - ccache = initiator_cred_handle->ccache; + ccache = cred->ccache; kret = krb5_cc_get_principal (context, ccache, &ctx->source); if (kret) { @@ -400,8 +400,8 @@ init_auth { krb5_enctype *enctypes = NULL; - if (initiator_cred_handle && initiator_cred_handle->enctypes) - enctypes = initiator_cred_handle->enctypes; + if (cred && cred->enctypes) + enctypes = cred->enctypes; krb5_set_default_in_tkt_etypes(context, enctypes); } @@ -412,11 +412,11 @@ init_auth ctx->target, time_req, time_rec, - &cred); + &kcred); if (ret) goto failure; - ctx->lifetime = cred->times.endtime; + ctx->lifetime = kcred->times.endtime; ret = _gsskrb5_lifetime_left(minor_status, context, @@ -434,11 +434,11 @@ init_auth krb5_auth_con_setkey(context, ctx->auth_context, - &cred->session); + &kcred->session); kret = krb5_auth_con_generatelocalsubkey(context, ctx->auth_context, - &cred->session); + &kcred->session); if(kret) { *minor_status = kret; ret = GSS_S_FAILURE; @@ -449,10 +449,10 @@ init_auth * If the credential doesn't have ok-as-delegate, check what local * policy say about ok-as-delegate, default is FALSE that makes * code ignore the KDC setting and follow what the application - * requested. If its TRUE, strip of the GSS_C_DELEG_FLAG if the + * requested. If it is TRUE, strip of the GSS_C_DELEG_FLAG if the * KDC doesn't set ok-as-delegate. */ - if (!cred->flags.b.ok_as_delegate) { + if (!kcred->flags.b.ok_as_delegate) { krb5_boolean delegate; krb5_appdefault_boolean(context, @@ -467,7 +467,7 @@ init_auth if (req_flags & GSS_C_DELEG_FLAG) do_delegation (context, ctx->auth_context, - ccache, cred, name, &fwd_data, &flags); + ccache, kcred, name, &fwd_data, &flags); if (req_flags & GSS_C_MUTUAL_FLAG) { flags |= GSS_C_MUTUAL_FLAG; @@ -490,8 +490,10 @@ init_auth if (req_flags & GSS_C_EXTENDED_ERROR_FLAG) flags |= GSS_C_EXTENDED_ERROR_FLAG; - flags |= GSS_C_CONF_FLAG; - flags |= GSS_C_INTEG_FLAG; + if (cred == NULL || !(cred->cred_flags & GSS_CF_NO_CI_FLAGS)) { + flags |= GSS_C_CONF_FLAG; + flags |= GSS_C_INTEG_FLAG; + } flags |= GSS_C_TRANS_FLAG; if (ret_flags) @@ -513,7 +515,7 @@ init_auth kret = krb5_build_authenticator (context, ctx->auth_context, enctype, - cred, + kcred, &cksum, NULL, &authenticator, @@ -527,7 +529,7 @@ init_auth kret = krb5_build_ap_req (context, enctype, - cred, + kcred, ap_options, authenticator, &outbuf); @@ -544,9 +546,9 @@ init_auth goto failure; krb5_data_free (&outbuf); - krb5_free_creds(context, cred); + krb5_free_creds(context, kcred); free_Checksum(&cksum); - if (initiator_cred_handle == NULL) + if (cred == NULL) krb5_cc_close(context, ccache); if (flags & GSS_C_MUTUAL_FLAG) { @@ -556,9 +558,9 @@ init_auth return gsskrb5_initiator_ready(minor_status, ctx, context); failure: - if(cred) - krb5_free_creds(context, cred); - if (ccache && initiator_cred_handle == NULL) + if(kcred) + krb5_free_creds(context, kcred); + if (ccache && cred == NULL) krb5_cc_close(context, ccache); return ret; @@ -682,7 +684,7 @@ repl_mutual OM_uint32 _gsskrb5_init_sec_context (OM_uint32 * minor_status, - const gss_cred_id_t initiator_cred_handle, + const gss_cred_id_t cred_handle, gss_ctx_id_t * context_handle, const gss_name_t target_name, const gss_OID mech_type, @@ -697,7 +699,7 @@ OM_uint32 _gsskrb5_init_sec_context ) { krb5_context context; - gsskrb5_cred cred = (gsskrb5_cred)initiator_cred_handle; + gsskrb5_cred cred = (gsskrb5_cred)cred_handle; krb5_const_principal name = (krb5_const_principal)target_name; gsskrb5_ctx ctx; OM_uint32 ret; diff --git a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c index d0ca1c4d95d..242dfa87b47 100644 --- a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c +++ b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c @@ -32,13 +32,22 @@ #include "krb5/gsskrb5_locl.h" -RCSID("$Id: set_cred_option.c 20325 2007-04-12 16:49:17Z lha $"); +RCSID("$Id: set_cred_option.c 22655 2008-02-26 12:40:35Z lha $"); +/* 1.2.752.43.13.17 */ +static gss_OID_desc gss_krb5_ccache_name_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x11")}; + +gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X = &gss_krb5_ccache_name_x_oid_desc; + +/* 1.2.752.43.13.18 */ static gss_OID_desc gss_krb5_import_cred_x_oid_desc = -{9, (void *)"\x2b\x06\x01\x04\x01\xa9\x4a\x13\x04"}; /* XXX */ +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x12")}; gss_OID GSS_KRB5_IMPORT_CRED_X = &gss_krb5_import_cred_x_oid_desc; + + static OM_uint32 import_cred(OM_uint32 *minor_status, krb5_context context, @@ -201,6 +210,27 @@ out: return major_stat; } +static OM_uint32 +no_ci_flags(OM_uint32 *minor_status, + krb5_context context, + gss_cred_id_t *cred_handle, + const gss_buffer_t value) +{ + gsskrb5_cred cred; + + if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + + cred = (gsskrb5_cred)*cred_handle; + cred->cred_flags |= GSS_CF_NO_CI_FLAGS; + + *minor_status = 0; + return GSS_S_COMPLETE; + +} + OM_uint32 _gsskrb5_set_cred_option @@ -224,6 +254,11 @@ _gsskrb5_set_cred_option if (gss_oid_equal(desired_object, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X)) return allowed_enctypes(minor_status, context, cred_handle, value); + if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_CI_FLAGS_X)) { + return no_ci_flags(minor_status, context, cred_handle, value); + } + + *minor_status = EINVAL; return GSS_S_FAILURE; } diff --git a/source4/heimdal/lib/gssapi/mech/context.c b/source4/heimdal/lib/gssapi/mech/context.c index e4517bee449..926630c42dc 100644 --- a/source4/heimdal/lib/gssapi/mech/context.c +++ b/source4/heimdal/lib/gssapi/mech/context.c @@ -1,7 +1,7 @@ #include "mech/mech_locl.h" #include "heim_threads.h" -RCSID("$Id: context.c 21248 2007-06-21 00:45:13Z lha $"); +RCSID("$Id: context.c 22600 2008-02-21 12:46:24Z lha $"); struct mg_thread_ctx { gss_OID mech; @@ -107,6 +107,13 @@ _gss_mg_error(gssapi_mech_interface m, OM_uint32 maj, OM_uint32 min) OM_uint32 message_content; struct mg_thread_ctx *mg; + /* + * Mechs without gss_display_status() does + * gss_mg_collect_error() by themself. + */ + if (m->gm_display_status == NULL) + return ; + mg = _gss_mechglue_thread(); if (mg == NULL) return; @@ -139,3 +146,12 @@ _gss_mg_error(gssapi_mech_interface m, OM_uint32 maj, OM_uint32 min) mg->min_error.length = 0; } } + +void +gss_mg_collect_error(gss_OID mech, OM_uint32 maj, OM_uint32 min) +{ + gssapi_mech_interface m = __gss_get_mechanism(mech); + if (m == NULL) + return; + _gss_mg_error(m, maj, min); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c index d1e243d8b85..a6b1ded5cad 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c @@ -27,7 +27,7 @@ */ #include "mech_locl.h" -RCSID("$Id: gss_accept_sec_context.c 21237 2007-06-20 11:21:09Z lha $"); +RCSID("$Id: gss_accept_sec_context.c 22071 2007-11-14 20:04:50Z lha $"); static OM_uint32 parse_header(const gss_buffer_t input_token, gss_OID mech_oid) @@ -38,7 +38,7 @@ parse_header(const gss_buffer_t input_token, gss_OID mech_oid) /* * Token must start with [APPLICATION 0] SEQUENCE. - * But if it doesn't assume its DCE-STYLE Kerberos! + * But if it doesn't assume it is DCE-STYLE Kerberos! */ if (len == 0) return (GSS_S_DEFECTIVE_TOKEN); @@ -102,7 +102,7 @@ choose_mech(const gss_buffer_t input, gss_OID mech_oid) OM_uint32 status; /* - * First try to parse the gssapi token header and see if its a + * First try to parse the gssapi token header and see if it's a * correct header, use that in the first hand. */ diff --git a/source4/heimdal/lib/gssapi/mech/gss_krb5.c b/source4/heimdal/lib/gssapi/mech/gss_krb5.c index 9e77f429828..03081cb70ff 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_krb5.c +++ b/source4/heimdal/lib/gssapi/mech/gss_krb5.c @@ -27,7 +27,7 @@ */ #include "mech_locl.h" -RCSID("$Id: gss_krb5.c 21123 2007-06-18 20:05:26Z lha $"); +RCSID("$Id: gss_krb5.c 21889 2007-08-09 07:43:24Z lha $"); #include <krb5.h> #include <roken.h> @@ -253,7 +253,6 @@ free_key(gss_krb5_lucid_key_t *key) memset(key, 0, sizeof(*key)); } - OM_uint32 gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, @@ -824,3 +823,43 @@ gsskrb5_set_default_realm(const char *realm) return (GSS_S_COMPLETE); } + +OM_uint32 +gss_krb5_get_tkt_flags(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + OM_uint32 *tkt_flags) +{ + + OM_uint32 major_status; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + + if (context_handle == GSS_C_NO_CONTEXT) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + major_status = + gss_inquire_sec_context_by_oid (minor_status, + context_handle, + GSS_KRB5_GET_TKT_FLAGS_X, + &data_set); + if (major_status) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || + data_set->count != 1 || + data_set->elements[0].length < 4) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + { + const u_char *p = data_set->elements[0].value; + *tkt_flags = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + } + + gss_release_buffer_set(minor_status, &data_set); + return GSS_S_COMPLETE; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c b/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c index f1a18afb13a..fe65ad1ae15 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c +++ b/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c @@ -28,7 +28,7 @@ #include "mech_locl.h" #include <heim_threads.h> -RCSID("$Id: gss_mech_switch.c 21700 2007-07-26 19:08:34Z lha $"); +RCSID("$Id: gss_mech_switch.c 21698 2007-07-26 19:07:11Z lha $"); #ifndef _PATH_GSS_MECH #define _PATH_GSS_MECH "/etc/gss/mech" diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c b/source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c index 4372e622948..388cfdbf4cf 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c +++ b/source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c @@ -27,7 +27,7 @@ */ #include "mech_locl.h" -RCSID("$Id: gss_release_oid_set.c 19963 2007-01-17 16:01:22Z lha $"); +RCSID("$Id: gss_release_oid_set.c 22144 2007-12-04 17:31:55Z lha $"); OM_uint32 gss_release_oid_set(OM_uint32 *minor_status, @@ -35,7 +35,7 @@ gss_release_oid_set(OM_uint32 *minor_status, { *minor_status = 0; - if (*set) { + if (set && *set) { if ((*set)->elements) free((*set)->elements); free(*set); diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c index 1afe26f1e39..df25b0f4bf6 100644 --- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: accept_sec_context.c 21461 2007-07-10 14:01:13Z lha $"); +RCSID("$Id: accept_sec_context.c 22600 2008-02-21 12:46:24Z lha $"); static OM_uint32 send_reject (OM_uint32 *minor_status, @@ -540,7 +540,7 @@ acceptor_start gss_cred_id_t *delegated_cred_handle ) { - OM_uint32 ret, junk, minor; + OM_uint32 ret, junk; NegotiationToken nt; size_t nt_len; NegTokenInit *ni; @@ -609,7 +609,7 @@ acceptor_start /* * First we try the opportunistic token if we have support for it, * don't try to verify we have credential for the token, - * gss_accept_sec_context will (hopefully) tell us that. + * gss_accept_sec_context() will (hopefully) tell us that. * If that failes, */ @@ -633,12 +633,12 @@ acceptor_start mech_cred = GSS_C_NO_CREDENTIAL; if (ctx->mech_src_name != GSS_C_NO_NAME) - gss_release_name(&minor, &ctx->mech_src_name); + gss_release_name(&junk, &ctx->mech_src_name); if (ctx->delegated_cred_id != GSS_C_NO_CREDENTIAL) - _gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); + _gss_spnego_release_cred(&junk, &ctx->delegated_cred_id); - ret = gss_accept_sec_context(&minor, + ret = gss_accept_sec_context(minor_status, &ctx->negotiated_ctx_id, mech_cred, mech_input_token, @@ -656,7 +656,7 @@ acceptor_start ctx->open = 1; if (mech_delegated_cred && delegated_cred_handle) - ret = _gss_spnego_alloc_cred(minor_status, + ret = _gss_spnego_alloc_cred(&junk, mech_delegated_cred, delegated_cred_handle); else @@ -674,6 +674,8 @@ acceptor_start goto out; first_ok = 1; + } else { + gss_mg_collect_error(preferred_mech_type, ret, *minor_status); } } @@ -681,7 +683,9 @@ acceptor_start * If opportunistic token failed, lets try the other mechs. */ - if (!first_ok) { + if (!first_ok && ni->mechToken != NULL) { + + preferred_mech_type = GSS_C_NO_OID; /* Call glue layer to find first mech we support */ for (i = 1; i < ni->mechTypes.len; ++i) { @@ -695,7 +699,7 @@ acceptor_start if (preferred_mech_type == GSS_C_NO_OID) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); free_NegotiationToken(&nt); - return GSS_S_BAD_MECH; + return ret; } ctx->preferred_mech_type = preferred_mech_type; @@ -717,7 +721,7 @@ acceptor_start out: if (mech_output_token.value != NULL) - gss_release_buffer(&minor, &mech_output_token); + gss_release_buffer(&junk, &mech_output_token); if (mech_buf.value != NULL) { free(mech_buf.value); mech_buf.value = NULL; @@ -754,7 +758,7 @@ out: return ret; } - _gss_spnego_internal_delete_sec_context(&minor, context_handle, + _gss_spnego_internal_delete_sec_context(&junk, context_handle, GSS_C_NO_BUFFER); return ret; @@ -877,6 +881,7 @@ acceptor_continue } if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { free_NegotiationToken(&nt); + gss_mg_collect_error(ctx->negotiated_mech_type, ret, minor); send_reject (minor_status, output_token); HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); return ret; diff --git a/source4/heimdal/lib/gssapi/spnego/compat.c b/source4/heimdal/lib/gssapi/spnego/compat.c index bc7da9410e6..287f4f760ed 100644 --- a/source4/heimdal/lib/gssapi/spnego/compat.c +++ b/source4/heimdal/lib/gssapi/spnego/compat.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: compat.c 19415 2006-12-18 17:52:26Z lha $"); +RCSID("$Id: compat.c 21866 2007-08-08 11:31:29Z lha $"); /* * Apparently Microsoft got the OID wrong, and used @@ -129,6 +129,7 @@ OM_uint32 _gss_spnego_internal_delete_sec_context gss_release_oid(&minor, &ctx->preferred_mech_type); ctx->negotiated_mech_type = GSS_C_NO_OID; + gss_release_name(&minor, &ctx->target_name); gss_release_name(&minor, &ctx->mech_src_name); if (ctx->negotiated_ctx_id != GSS_C_NO_CONTEXT) { diff --git a/source4/heimdal/lib/gssapi/spnego/context_stubs.c b/source4/heimdal/lib/gssapi/spnego/context_stubs.c index 3535c7bb359..0169017ee5a 100644 --- a/source4/heimdal/lib/gssapi/spnego/context_stubs.c +++ b/source4/heimdal/lib/gssapi/spnego/context_stubs.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: context_stubs.c 21035 2007-06-09 15:32:47Z lha $"); +RCSID("$Id: context_stubs.c 22604 2008-02-21 21:12:48Z lha $"); static OM_uint32 spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs) @@ -263,18 +263,6 @@ OM_uint32 _gss_spnego_unwrap qop_state); } -OM_uint32 _gss_spnego_display_status - (OM_uint32 * minor_status, - OM_uint32 status_value, - int status_type, - const gss_OID mech_type, - OM_uint32 * message_context, - gss_buffer_t status_string - ) -{ - return GSS_S_FAILURE; -} - OM_uint32 _gss_spnego_compare_name (OM_uint32 *minor_status, const gss_name_t name1, @@ -406,28 +394,58 @@ OM_uint32 _gss_spnego_inquire_context ( ) { gssspnego_ctx ctx; + OM_uint32 maj_stat, junk; + gss_name_t src_mn, targ_mn; *minor_status = 0; - if (context_handle == GSS_C_NO_CONTEXT) { + if (context_handle == GSS_C_NO_CONTEXT) return GSS_S_NO_CONTEXT; - } ctx = (gssspnego_ctx)context_handle; - if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) return GSS_S_NO_CONTEXT; - } - return gss_inquire_context(minor_status, - ctx->negotiated_ctx_id, - src_name, - targ_name, - lifetime_rec, - mech_type, - ctx_flags, - locally_initiated, - open_context); + maj_stat = gss_inquire_context(minor_status, + ctx->negotiated_ctx_id, + &src_mn, + &targ_mn, + lifetime_rec, + mech_type, + ctx_flags, + locally_initiated, + open_context); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + if (src_name) { + spnego_name name = calloc(1, sizeof(*name)); + if (name == NULL) + goto enomem; + name->mech = src_mn; + *src_name = (gss_name_t)name; + } else + gss_release_name(&junk, &src_mn); + + if (targ_name) { + spnego_name name = calloc(1, sizeof(*name)); + if (name == NULL) { + gss_release_name(minor_status, src_name); + goto enomem; + } + name->mech = targ_mn; + *targ_name = (gss_name_t)name; + } else + gss_release_name(&junk, &targ_mn); + + return GSS_S_COMPLETE; + +enomem: + gss_release_name(&junk, &targ_mn); + gss_release_name(&junk, &src_mn); + *minor_status = ENOMEM; + return GSS_S_FAILURE; } OM_uint32 _gss_spnego_wrap_size_limit ( diff --git a/source4/heimdal/lib/gssapi/spnego/external.c b/source4/heimdal/lib/gssapi/spnego/external.c index fbc231f3aeb..6c9a03a3b00 100644 --- a/source4/heimdal/lib/gssapi/spnego/external.c +++ b/source4/heimdal/lib/gssapi/spnego/external.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" #include <gssapi_mech.h> -RCSID("$Id: external.c 18336 2006-10-07 22:27:13Z lha $"); +RCSID("$Id: external.c 22600 2008-02-21 12:46:24Z lha $"); /* * RFC2478, SPNEGO: @@ -57,7 +57,7 @@ static gssapi_mech_interface_desc spnego_mech = { _gss_spnego_verify_mic, _gss_spnego_wrap, _gss_spnego_unwrap, - _gss_spnego_display_status, + NULL, NULL, _gss_spnego_compare_name, _gss_spnego_display_name, diff --git a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c index 7c74981e664..bee48958981 100644 --- a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: init_sec_context.c 19411 2006-12-18 15:42:03Z lha $"); +RCSID("$Id: init_sec_context.c 22600 2008-02-21 12:46:24Z lha $"); /* * Is target_name an sane target for `mech´. @@ -59,8 +59,10 @@ initiator_approved(gss_name_t target_name, gss_OID mech) &out, NULL, NULL); - if (GSS_ERROR(maj_stat)) + if (GSS_ERROR(maj_stat)) { + gss_mg_collect_error(mech, maj_stat, min_stat); return GSS_S_BAD_MECH; + } gss_release_buffer(&min_stat, &out); gss_delete_sec_context(&min_stat, &ctx, NULL); @@ -268,6 +270,7 @@ spnego_initial if (GSS_ERROR(sub)) { free_NegTokenInit(&ni); *minor_status = minor; + gss_mg_collect_error(ctx->preferred_mech_type, sub, minor); _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); return sub; } @@ -480,7 +483,8 @@ spnego_reply return GSS_S_BAD_MECH; } - if (resp.responseToken != NULL || + /* if a token (of non zero length), or no context, pass to underlaying mech */ + if ((resp.responseToken != NULL && resp.responseToken->length) || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { gss_buffer_desc mech_input_token; @@ -515,6 +519,7 @@ spnego_reply if (GSS_ERROR(ret)) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); free_NegTokenResp(&resp); + gss_mg_collect_error(&mech, ret, minor); *minor_status = minor; return ret; } diff --git a/source4/heimdal/lib/gssapi/spnego/spnego-private.h b/source4/heimdal/lib/gssapi/spnego/spnego-private.h index d80db0018ad..69f4d8423d2 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego-private.h +++ b/source4/heimdal/lib/gssapi/spnego/spnego-private.h @@ -91,15 +91,6 @@ _gss_spnego_display_name ( gss_OID * output_name_type ); OM_uint32 -_gss_spnego_display_status ( - OM_uint32 * /*minor_status*/, - OM_uint32 /*status_value*/, - int /*status_type*/, - const gss_OID /*mech_type*/, - OM_uint32 * /*message_context*/, - gss_buffer_t status_string ); - -OM_uint32 _gss_spnego_duplicate_name ( OM_uint32 * /*minor_status*/, const gss_name_t /*src_name*/, diff --git a/source4/heimdal/lib/hcrypto/bn.c b/source4/heimdal/lib/hcrypto/bn.c index 698da2fe0b1..6076478bbb0 100644 --- a/source4/heimdal/lib/hcrypto/bn.c +++ b/source4/heimdal/lib/hcrypto/bn.c @@ -35,7 +35,7 @@ #include <config.h> #endif -RCSID("$Id: bn.c 18449 2006-10-14 09:21:09Z lha $"); +RCSID("$Id: bn.c 22261 2007-12-09 06:24:18Z lha $"); #include <stdio.h> #include <stdlib.h> @@ -232,9 +232,9 @@ BN_set_negative(BIGNUM *bn, int flag) } int -BN_is_negative(BIGNUM *bn) +BN_is_negative(const BIGNUM *bn) { - return ((heim_integer *)bn)->negative ? 1 : 0; + return ((const heim_integer *)bn)->negative ? 1 : 0; } static const unsigned char is_set[8] = { 1, 2, 4, 8, 16, 32, 64, 128 }; diff --git a/source4/heimdal/lib/hcrypto/bn.h b/source4/heimdal/lib/hcrypto/bn.h index 82c9991c2cb..92cacec2a66 100644 --- a/source4/heimdal/lib/hcrypto/bn.h +++ b/source4/heimdal/lib/hcrypto/bn.h @@ -32,7 +32,7 @@ */ /* - * $Id: bn.h 16536 2006-01-13 08:27:50Z lha $ + * $Id: bn.h 22260 2007-12-09 06:23:47Z lha $ */ #ifndef _HEIM_BN_H @@ -97,7 +97,7 @@ int BN_num_bytes(const BIGNUM *); int BN_cmp(const BIGNUM *, const BIGNUM *); void BN_set_negative(BIGNUM *, int); -int BN_is_negative(BIGNUM *); +int BN_is_negative(const BIGNUM *); int BN_is_bit_set(const BIGNUM *, int); int BN_set_bit(BIGNUM *, int); diff --git a/source4/heimdal/lib/hcrypto/camellia-ntt.c b/source4/heimdal/lib/hcrypto/camellia-ntt.c new file mode 100644 index 00000000000..c32c406baaa --- /dev/null +++ b/source4/heimdal/lib/hcrypto/camellia-ntt.c @@ -0,0 +1,1461 @@ +/* camellia.h ver 1.2.0 + * + * Copyright (C) 2006,2007 + * NTT (Nippon Telegraph and Telephone Corporation). + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Algorithm Specification + * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html + */ + +#include <string.h> +#include <stdlib.h> + +#include "camellia.h" + +/* u32 must be 32bit word */ +typedef unsigned int u32; +typedef unsigned char u8; + +/* key constants */ + +#define CAMELLIA_SIGMA1L (0xA09E667FL) +#define CAMELLIA_SIGMA1R (0x3BCC908BL) +#define CAMELLIA_SIGMA2L (0xB67AE858L) +#define CAMELLIA_SIGMA2R (0x4CAA73B2L) +#define CAMELLIA_SIGMA3L (0xC6EF372FL) +#define CAMELLIA_SIGMA3R (0xE94F82BEL) +#define CAMELLIA_SIGMA4L (0x54FF53A5L) +#define CAMELLIA_SIGMA4R (0xF1D36F1CL) +#define CAMELLIA_SIGMA5L (0x10E527FAL) +#define CAMELLIA_SIGMA5R (0xDE682D1DL) +#define CAMELLIA_SIGMA6L (0xB05688C2L) +#define CAMELLIA_SIGMA6R (0xB3E6C1FDL) + +/* + * macros + */ + + +#if defined(_MSC_VER) + +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));} + +#else /* not MS-VC */ + +# define GETU32(pt) \ + (((u32)(pt)[0] << 24) \ + ^ ((u32)(pt)[1] << 16) \ + ^ ((u32)(pt)[2] << 8) \ + ^ ((u32)(pt)[3])) + +# define PUTU32(ct, st) { \ + (ct)[0] = (u8)((st) >> 24); \ + (ct)[1] = (u8)((st) >> 16); \ + (ct)[2] = (u8)((st) >> 8); \ + (ct)[3] = (u8)(st); } + +#endif + +#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2]) +#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1]) + +/* rotation right shift 1byte */ +#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24)) +/* rotation left shift 1bit */ +#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31)) +/* rotation left shift 1byte */ +#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24)) + +#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + ll = (ll << bits) + (lr >> (32 - bits)); \ + lr = (lr << bits) + (rl >> (32 - bits)); \ + rl = (rl << bits) + (rr >> (32 - bits)); \ + rr = (rr << bits) + (w0 >> (32 - bits)); \ + } while(0) + +#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + w1 = lr; \ + ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \ + lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \ + rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \ + rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \ + } while(0) + +#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)]) +#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)]) +#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)]) +#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)]) + +#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + il = xl ^ kl; \ + ir = xr ^ kr; \ + t0 = il >> 16; \ + t1 = ir >> 16; \ + yl = CAMELLIA_SP1110(ir & 0xff) \ + ^ CAMELLIA_SP0222((t1 >> 8) & 0xff) \ + ^ CAMELLIA_SP3033(t1 & 0xff) \ + ^ CAMELLIA_SP4404((ir >> 8) & 0xff); \ + yr = CAMELLIA_SP1110((t0 >> 8) & 0xff) \ + ^ CAMELLIA_SP0222(t0 & 0xff) \ + ^ CAMELLIA_SP3033((il >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(il & 0xff); \ + yl ^= yr; \ + yr = CAMELLIA_RR8(yr); \ + yr ^= yl; \ + } while(0) + + +/* + * for speed up + * + */ +#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \ + do { \ + t0 = kll; \ + t0 &= ll; \ + lr ^= CAMELLIA_RL1(t0); \ + t1 = klr; \ + t1 |= lr; \ + ll ^= t1; \ + \ + t2 = krr; \ + t2 |= rr; \ + rl ^= t2; \ + t3 = krl; \ + t3 &= rl; \ + rr ^= CAMELLIA_RL1(t3); \ + } while(0) + +#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + ir = CAMELLIA_SP1110(xr & 0xff) \ + ^ CAMELLIA_SP0222((xr >> 24) & 0xff) \ + ^ CAMELLIA_SP3033((xr >> 16) & 0xff) \ + ^ CAMELLIA_SP4404((xr >> 8) & 0xff); \ + il = CAMELLIA_SP1110((xl >> 24) & 0xff) \ + ^ CAMELLIA_SP0222((xl >> 16) & 0xff) \ + ^ CAMELLIA_SP3033((xl >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(xl & 0xff); \ + il ^= kl; \ + ir ^= kr; \ + ir ^= il; \ + il = CAMELLIA_RR8(il); \ + il ^= ir; \ + yl ^= ir; \ + yr ^= il; \ + } while(0) + + +static const u32 camellia_sp1110[256] = { + 0x70707000,0x82828200,0x2c2c2c00,0xececec00, + 0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500, + 0xe4e4e400,0x85858500,0x57575700,0x35353500, + 0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100, + 0x23232300,0xefefef00,0x6b6b6b00,0x93939300, + 0x45454500,0x19191900,0xa5a5a500,0x21212100, + 0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00, + 0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00, + 0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00, + 0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00, + 0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00, + 0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00, + 0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00, + 0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00, + 0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600, + 0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00, + 0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600, + 0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00, + 0x74747400,0x12121200,0x2b2b2b00,0x20202000, + 0xf0f0f000,0xb1b1b100,0x84848400,0x99999900, + 0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200, + 0x34343400,0x7e7e7e00,0x76767600,0x05050500, + 0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100, + 0xd1d1d100,0x17171700,0x04040400,0xd7d7d700, + 0x14141400,0x58585800,0x3a3a3a00,0x61616100, + 0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00, + 0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600, + 0x53535300,0x18181800,0xf2f2f200,0x22222200, + 0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200, + 0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100, + 0x24242400,0x08080800,0xe8e8e800,0xa8a8a800, + 0x60606000,0xfcfcfc00,0x69696900,0x50505000, + 0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00, + 0xa1a1a100,0x89898900,0x62626200,0x97979700, + 0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500, + 0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200, + 0x10101000,0xc4c4c400,0x00000000,0x48484800, + 0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00, + 0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00, + 0x09090900,0x3f3f3f00,0xdddddd00,0x94949400, + 0x87878700,0x5c5c5c00,0x83838300,0x02020200, + 0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300, + 0x73737300,0x67676700,0xf6f6f600,0xf3f3f300, + 0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200, + 0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600, + 0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00, + 0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00, + 0x13131300,0xbebebe00,0x63636300,0x2e2e2e00, + 0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00, + 0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00, + 0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600, + 0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900, + 0x78787800,0x98989800,0x06060600,0x6a6a6a00, + 0xe7e7e700,0x46464600,0x71717100,0xbababa00, + 0xd4d4d400,0x25252500,0xababab00,0x42424200, + 0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00, + 0x72727200,0x07070700,0xb9b9b900,0x55555500, + 0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00, + 0x36363600,0x49494900,0x2a2a2a00,0x68686800, + 0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400, + 0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00, + 0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100, + 0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400, + 0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00, +}; + +static const u32 camellia_sp0222[256] = { + 0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9, + 0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb, + 0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a, + 0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282, + 0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727, + 0x008a8a8a,0x00323232,0x004b4b4b,0x00424242, + 0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c, + 0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b, + 0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f, + 0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d, + 0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe, + 0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434, + 0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595, + 0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a, + 0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad, + 0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a, + 0x00171717,0x001a1a1a,0x00353535,0x00cccccc, + 0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a, + 0x00e8e8e8,0x00242424,0x00565656,0x00404040, + 0x00e1e1e1,0x00636363,0x00090909,0x00333333, + 0x00bfbfbf,0x00989898,0x00979797,0x00858585, + 0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a, + 0x00dadada,0x006f6f6f,0x00535353,0x00626262, + 0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf, + 0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2, + 0x00bdbdbd,0x00363636,0x00222222,0x00383838, + 0x00646464,0x001e1e1e,0x00393939,0x002c2c2c, + 0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444, + 0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565, + 0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323, + 0x00484848,0x00101010,0x00d1d1d1,0x00515151, + 0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0, + 0x00555555,0x00a1a1a1,0x00414141,0x00fafafa, + 0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f, + 0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b, + 0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5, + 0x00202020,0x00898989,0x00000000,0x00909090, + 0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7, + 0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5, + 0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929, + 0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404, + 0x009b9b9b,0x00949494,0x00212121,0x00666666, + 0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7, + 0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5, + 0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c, + 0x00919191,0x006e6e6e,0x008d8d8d,0x00767676, + 0x00030303,0x002d2d2d,0x00dedede,0x00969696, + 0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c, + 0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919, + 0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d, + 0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d, + 0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2, + 0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4, + 0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575, + 0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484, + 0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5, + 0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa, + 0x00f1f1f1,0x00dddddd,0x00595959,0x00141414, + 0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0, + 0x00787878,0x00707070,0x00e3e3e3,0x00494949, + 0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6, + 0x00777777,0x00939393,0x00868686,0x00838383, + 0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9, + 0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d, +}; + +static const u32 camellia_sp3033[256] = { + 0x38003838,0x41004141,0x16001616,0x76007676, + 0xd900d9d9,0x93009393,0x60006060,0xf200f2f2, + 0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a, + 0x75007575,0x06000606,0x57005757,0xa000a0a0, + 0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9, + 0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090, + 0xf600f6f6,0x07000707,0xa700a7a7,0x27002727, + 0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede, + 0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7, + 0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767, + 0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf, + 0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d, + 0x53005353,0xf000f0f0,0x9c009c9c,0x65006565, + 0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e, + 0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b, + 0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6, + 0xc500c5c5,0x86008686,0x4d004d4d,0x33003333, + 0xfd00fdfd,0x66006666,0x58005858,0x96009696, + 0x3a003a3a,0x09000909,0x95009595,0x10001010, + 0x78007878,0xd800d8d8,0x42004242,0xcc00cccc, + 0xef00efef,0x26002626,0xe500e5e5,0x61006161, + 0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282, + 0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898, + 0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb, + 0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0, + 0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e, + 0x19001919,0x87008787,0x4e004e4e,0x0b000b0b, + 0xa900a9a9,0x0c000c0c,0x79007979,0x11001111, + 0x7f007f7f,0x22002222,0xe700e7e7,0x59005959, + 0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8, + 0x12001212,0x04000404,0x74007474,0x54005454, + 0x30003030,0x7e007e7e,0xb400b4b4,0x28002828, + 0x55005555,0x68006868,0x50005050,0xbe00bebe, + 0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb, + 0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca, + 0x70007070,0xff00ffff,0x32003232,0x69006969, + 0x08000808,0x62006262,0x00000000,0x24002424, + 0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded, + 0x45004545,0x81008181,0x73007373,0x6d006d6d, + 0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a, + 0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101, + 0xe600e6e6,0x25002525,0x48004848,0x99009999, + 0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9, + 0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171, + 0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313, + 0x64006464,0x9b009b9b,0x63006363,0x9d009d9d, + 0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5, + 0x89008989,0x5f005f5f,0xb100b1b1,0x17001717, + 0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646, + 0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747, + 0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b, + 0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac, + 0x3c003c3c,0x4c004c4c,0x03000303,0x35003535, + 0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d, + 0x6a006a6a,0x92009292,0xd500d5d5,0x21002121, + 0x44004444,0x51005151,0xc600c6c6,0x7d007d7d, + 0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa, + 0x7c007c7c,0x77007777,0x56005656,0x05000505, + 0x1b001b1b,0xa400a4a4,0x15001515,0x34003434, + 0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252, + 0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd, + 0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0, + 0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a, + 0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f, +}; + +static const u32 camellia_sp4404[256] = { + 0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0, + 0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae, + 0x23230023,0x6b6b006b,0x45450045,0xa5a500a5, + 0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092, + 0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f, + 0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b, + 0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d, + 0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c, + 0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0, + 0x74740074,0x2b2b002b,0xf0f000f0,0x84840084, + 0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076, + 0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004, + 0x14140014,0x3a3a003a,0xdede00de,0x11110011, + 0x32320032,0x9c9c009c,0x53530053,0xf2f200f2, + 0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a, + 0x24240024,0xe8e800e8,0x60600060,0x69690069, + 0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062, + 0x54540054,0x1e1e001e,0xe0e000e0,0x64640064, + 0x10100010,0x00000000,0xa3a300a3,0x75750075, + 0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd, + 0x87870087,0x83830083,0xcdcd00cd,0x90900090, + 0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf, + 0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6, + 0x81810081,0x6f6f006f,0x13130013,0x63630063, + 0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc, + 0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4, + 0x78780078,0x06060006,0xe7e700e7,0x71710071, + 0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d, + 0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac, + 0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1, + 0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043, + 0x15150015,0xadad00ad,0x77770077,0x80800080, + 0x82820082,0xecec00ec,0x27270027,0xe5e500e5, + 0x85850085,0x35350035,0x0c0c000c,0x41410041, + 0xefef00ef,0x93930093,0x19190019,0x21210021, + 0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd, + 0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce, + 0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a, + 0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d, + 0x01010001,0xd6d600d6,0x56560056,0x4d4d004d, + 0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d, + 0x12120012,0x20200020,0xb1b100b1,0x99990099, + 0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005, + 0xb7b700b7,0x31310031,0x17170017,0xd7d700d7, + 0x58580058,0x61610061,0x1b1b001b,0x1c1c001c, + 0x0f0f000f,0x16160016,0x18180018,0x22220022, + 0x44440044,0xb2b200b2,0xb5b500b5,0x91910091, + 0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050, + 0xd0d000d0,0x7d7d007d,0x89890089,0x97970097, + 0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2, + 0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db, + 0x03030003,0xdada00da,0x3f3f003f,0x94940094, + 0x5c5c005c,0x02020002,0x4a4a004a,0x33330033, + 0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2, + 0x9b9b009b,0x26260026,0x37370037,0x3b3b003b, + 0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e, + 0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e, + 0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059, + 0x98980098,0x6a6a006a,0x46460046,0xbaba00ba, + 0x25250025,0x42420042,0xa2a200a2,0xfafa00fa, + 0x07070007,0x55550055,0xeeee00ee,0x0a0a000a, + 0x49490049,0x68680068,0x38380038,0xa4a400a4, + 0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1, + 0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e, +}; + + +/** + * Stuff related to the Camellia key schedule + */ +#define subl(x) subL[(x)] +#define subr(x) subR[(x)] + +void camellia_setup128(const unsigned char *key, u32 *subkey) +{ + u32 kll, klr, krl, krr; + u32 il, ir, t0, t1, w0, w1; + u32 kw4l, kw4r, dw, tl, tr; + u32 subL[26]; + u32 subR[26]; + + /** + * k == kll || klr || krl || krr (|| is concatination) + */ + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + /** + * generate KL dependent subkeys + */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(4) = kll; subr(4) = klr; + subl(5) = krl; subr(5) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(10) = kll; subr(10) = klr; + subl(11) = krl; subr(11) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(18) = kll; subr(18) = klr; + subl(19) = krl; subr(19) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + + /* generate KA */ + kll = subl(0); klr = subr(0); + krl = subl(1); krr = subr(1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KA dependent subkeys */ + subl(2) = kll; subr(2) = klr; + subl(3) = krl; subr(3) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(8) = kll; subr(8) = klr; + subl(9) = krl; subr(9) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(12) = kll; subr(12) = klr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(20) = kll; subr(20) = klr; + subl(21) = krl; subr(21) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(24) = kll; subr(24) = klr; + subl(25) = krl; subr(25) = krr; + + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(24) ^= subl(1); subr(24) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(25); kw4r = subr(25); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + CamelliaSubkeyL(23) = subl(22); + CamelliaSubkeyR(23) = subr(22); + CamelliaSubkeyL(24) = subl(24) ^ subl(23); + CamelliaSubkeyR(24) = subr(24) ^ subr(23); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + + return; +} + +void camellia_setup256(const unsigned char *key, u32 *subkey) +{ + u32 kll,klr,krl,krr; /* left half of key */ + u32 krll,krlr,krrl,krrr; /* right half of key */ + u32 il, ir, t0, t1, w0, w1; /* temporary variables */ + u32 kw4l, kw4r, dw, tl, tr; + u32 subL[34]; + u32 subR[34]; + + /** + * key = (kll || klr || krl || krr || krll || krlr || krrl || krrr) + * (|| is concatination) + */ + + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + krll = GETU32(key + 16); + krlr = GETU32(key + 20); + krrl = GETU32(key + 24); + krrr = GETU32(key + 28); + + /* generate KL dependent subkeys */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45); + subl(12) = kll; subr(12) = klr; + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(30) = kll; subr(30) = klr; + subl(31) = krl; subr(31) = krr; + + /* generate KR dependent subkeys */ + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(4) = krll; subr(4) = krlr; + subl(5) = krrl; subr(5) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(8) = krll; subr(8) = krlr; + subl(9) = krrl; subr(9) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(18) = krll; subr(18) = krlr; + subl(19) = krrl; subr(19) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + subl(26) = krll; subr(26) = krlr; + subl(27) = krrl; subr(27) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + + /* generate KA */ + kll = subl(0) ^ krll; klr = subr(0) ^ krlr; + krl = subl(1) ^ krrl; krr = subr(1) ^ krrr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + kll ^= krll; klr ^= krlr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0 ^ krrl; krr ^= w1 ^ krrr; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KB */ + krll ^= kll; krlr ^= klr; + krrl ^= krl; krrr ^= krr; + CAMELLIA_F(krll, krlr, + CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R, + w0, w1, il, ir, t0, t1); + krrl ^= w0; krrr ^= w1; + CAMELLIA_F(krrl, krrr, + CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R, + w0, w1, il, ir, t0, t1); + krll ^= w0; krlr ^= w1; + + /* generate KA dependent subkeys */ + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + subl(24) = klr; subr(24) = krl; + subl(25) = krr; subr(25) = kll; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49); + subl(28) = kll; subr(28) = klr; + subl(29) = krl; subr(29) = krr; + + /* generate KB dependent subkeys */ + subl(2) = krll; subr(2) = krlr; + subl(3) = krrl; subr(3) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(10) = krll; subr(10) = krlr; + subl(11) = krrl; subr(11) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(20) = krll; subr(20) = krlr; + subl(21) = krrl; subr(21) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51); + subl(32) = krll; subr(32) = krlr; + subl(33) = krrl; subr(33) = krrr; + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(1) ^= subr(1) & ~subr(25); + dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw); + subl(27) ^= subl(1); subr(27) ^= subr(1); + subl(29) ^= subl(1); subr(29) ^= subr(1); + subl(31) ^= subl(1); subr(31) ^= subr(1); + subl(32) ^= subl(1); subr(32) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(33); kw4r = subr(33); + subl(30) ^= kw4l; subr(30) ^= kw4r; + subl(28) ^= kw4l; subr(28) ^= kw4r; + subl(26) ^= kw4l; subr(26) ^= kw4r; + kw4l ^= kw4r & ~subr(24); + dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + tl = subl(26) ^ (subr(26) & ~subr(24)); + dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(23) = subl(22) ^ tl; + CamelliaSubkeyR(23) = subr(22) ^ tr; + CamelliaSubkeyL(24) = subl(24); + CamelliaSubkeyR(24) = subr(24); + CamelliaSubkeyL(25) = subl(25); + CamelliaSubkeyR(25) = subr(25); + tl = subl(23) ^ (subr(23) & ~subr(25)); + dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(26) = tl ^ subl(27); + CamelliaSubkeyR(26) = tr ^ subr(27); + CamelliaSubkeyL(27) = subl(26) ^ subl(28); + CamelliaSubkeyR(27) = subr(26) ^ subr(28); + CamelliaSubkeyL(28) = subl(27) ^ subl(29); + CamelliaSubkeyR(28) = subr(27) ^ subr(29); + CamelliaSubkeyL(29) = subl(28) ^ subl(30); + CamelliaSubkeyR(29) = subr(28) ^ subr(30); + CamelliaSubkeyL(30) = subl(29) ^ subl(31); + CamelliaSubkeyR(30) = subr(29) ^ subr(31); + CamelliaSubkeyL(31) = subl(30); + CamelliaSubkeyR(31) = subr(30); + CamelliaSubkeyL(32) = subl(32) ^ subl(31); + CamelliaSubkeyR(32) = subr(32) ^ subr(31); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + dw = CamelliaSubkeyL(26) ^ CamelliaSubkeyR(26), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(26) = CamelliaSubkeyL(26) ^ dw, CamelliaSubkeyL(26) = dw; + dw = CamelliaSubkeyL(27) ^ CamelliaSubkeyR(27), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(27) = CamelliaSubkeyL(27) ^ dw, CamelliaSubkeyL(27) = dw; + dw = CamelliaSubkeyL(28) ^ CamelliaSubkeyR(28), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(28) = CamelliaSubkeyL(28) ^ dw, CamelliaSubkeyL(28) = dw; + dw = CamelliaSubkeyL(29) ^ CamelliaSubkeyR(29), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(29) = CamelliaSubkeyL(29) ^ dw, CamelliaSubkeyL(29) = dw; + dw = CamelliaSubkeyL(30) ^ CamelliaSubkeyR(30), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw; + dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw; + + return; +} + +void camellia_setup192(const unsigned char *key, u32 *subkey) +{ + unsigned char kk[32]; + u32 krll, krlr, krrl,krrr; + + memcpy(kk, key, 24); + memcpy((unsigned char *)&krll, key+16,4); + memcpy((unsigned char *)&krlr, key+20,4); + krrl = ~krll; + krrr = ~krlr; + memcpy(kk+24, (unsigned char *)&krrl, 4); + memcpy(kk+28, (unsigned char *)&krrr, 4); + camellia_setup256(kk, subkey); + return; +} + + +/** + * Stuff related to camellia encryption/decryption + * + * "io" must be 4byte aligned and big-endian data. + */ +void camellia_encrypt128(const u32 *subkey, u32 *io) +{ + u32 il, ir, t0, t1; + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + /* main iteration */ + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(24); + io[3] ^= CamelliaSubkeyR(24); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +void camellia_decrypt128(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(24); + io[1] ^= CamelliaSubkeyR(24); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/** + * stuff for 192 and 256bit encryption/decryption + */ +void camellia_encrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(32); + io[3] ^= CamelliaSubkeyR(32); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +void camellia_decrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(32); + io[1] ^= CamelliaSubkeyR(32); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/*** + * + * API for compatibility + */ + +void Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, + KEY_TABLE_TYPE keyTable) +{ + switch(keyBitLength) { + case 128: + camellia_setup128(rawKey, keyTable); + break; + case 192: + camellia_setup192(rawKey, keyTable); + break; + case 256: + camellia_setup256(rawKey, keyTable); + break; + default: + break; + } +} + + +void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *ciphertext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(plaintext); + tmp[1] = GETU32(plaintext + 4); + tmp[2] = GETU32(plaintext + 8); + tmp[3] = GETU32(plaintext + 12); + + switch (keyBitLength) { + case 128: + camellia_encrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_encrypt256(keyTable, tmp); + break; + default: + break; + } + + PUTU32(ciphertext, tmp[0]); + PUTU32(ciphertext + 4, tmp[1]); + PUTU32(ciphertext + 8, tmp[2]); + PUTU32(ciphertext + 12, tmp[3]); +} + +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *ciphertext, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(ciphertext); + tmp[1] = GETU32(ciphertext + 4); + tmp[2] = GETU32(ciphertext + 8); + tmp[3] = GETU32(ciphertext + 12); + + switch (keyBitLength) { + case 128: + camellia_decrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_decrypt256(keyTable, tmp); + break; + default: + break; + } + PUTU32(plaintext, tmp[0]); + PUTU32(plaintext + 4, tmp[1]); + PUTU32(plaintext + 8, tmp[2]); + PUTU32(plaintext + 12, tmp[3]); +} diff --git a/source4/heimdal/lib/hcrypto/camellia-ntt.h b/source4/heimdal/lib/hcrypto/camellia-ntt.h new file mode 100644 index 00000000000..740ed8bfd9f --- /dev/null +++ b/source4/heimdal/lib/hcrypto/camellia-ntt.h @@ -0,0 +1,54 @@ +/* camellia.h ver 1.2.0 + * + * Copyright (C) 2006,2007 + * NTT (Nippon Telegraph and Telephone Corporation). + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef HEADER_CAMELLIA_H +#define HEADER_CAMELLIA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define CAMELLIA_BLOCK_SIZE 16 +#define CAMELLIA_TABLE_BYTE_LEN 272 +#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4) + +typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; + + +void Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, + KEY_TABLE_TYPE keyTable); + +void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *cipherText); + +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *cipherText, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext); + + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_CAMELLIA_H */ diff --git a/source4/heimdal/lib/hcrypto/camellia.c b/source4/heimdal/lib/hcrypto/camellia.c new file mode 100644 index 00000000000..2047b75ead8 --- /dev/null +++ b/source4/heimdal/lib/hcrypto/camellia.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" + +RCSID("$Id: aes.c 20466 2007-04-20 08:29:05Z lha $"); +#endif + +#ifdef KRB5 +#include <krb5-types.h> +#endif + +#include <string.h> + +#include "camellia-ntt.h" +#include "camellia.h" + +int +CAMELLIA_set_key(const unsigned char *userkey, + const int bits, CAMELLIA_KEY *key) +{ + key->bits = bits; + Camellia_Ekeygen(bits, userkey, key->key); + return 1; +} + +void +CAMELLIA_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key) +{ + Camellia_EncryptBlock(key->bits, in, key->key, out); + +} + +void +CAMELLIA_decrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key) +{ + Camellia_DecryptBlock(key->bits, in, key->key, out); +} + +void +CAMELLIA_cbc_encrypt(const unsigned char *in, unsigned char *out, + unsigned long size, const CAMELLIA_KEY *key, + unsigned char *iv, int mode_encrypt) +{ + unsigned char tmp[CAMELLIA_BLOCK_SIZE]; + int i; + + if (mode_encrypt) { + while (size >= CAMELLIA_BLOCK_SIZE) { + for (i = 0; i < CAMELLIA_BLOCK_SIZE; i++) + tmp[i] = in[i] ^ iv[i]; + CAMELLIA_encrypt(tmp, out, key); + memcpy(iv, out, CAMELLIA_BLOCK_SIZE); + size -= CAMELLIA_BLOCK_SIZE; + in += CAMELLIA_BLOCK_SIZE; + out += CAMELLIA_BLOCK_SIZE; + } + if (size) { + for (i = 0; i < size; i++) + tmp[i] = in[i] ^ iv[i]; + for (i = size; i < CAMELLIA_BLOCK_SIZE; i++) + tmp[i] = iv[i]; + CAMELLIA_encrypt(tmp, out, key); + memcpy(iv, out, CAMELLIA_BLOCK_SIZE); + } + } else { + while (size >= CAMELLIA_BLOCK_SIZE) { + memcpy(tmp, in, CAMELLIA_BLOCK_SIZE); + CAMELLIA_decrypt(tmp, out, key); + for (i = 0; i < CAMELLIA_BLOCK_SIZE; i++) + out[i] ^= iv[i]; + memcpy(iv, tmp, CAMELLIA_BLOCK_SIZE); + size -= CAMELLIA_BLOCK_SIZE; + in += CAMELLIA_BLOCK_SIZE; + out += CAMELLIA_BLOCK_SIZE; + } + if (size) { + memcpy(tmp, in, CAMELLIA_BLOCK_SIZE); + CAMELLIA_decrypt(tmp, out, key); + for (i = 0; i < size; i++) + out[i] ^= iv[i]; + memcpy(iv, tmp, CAMELLIA_BLOCK_SIZE); + } + } +} diff --git a/source4/heimdal/lib/hcrypto/camellia.h b/source4/heimdal/lib/hcrypto/camellia.h new file mode 100644 index 00000000000..3b21934b660 --- /dev/null +++ b/source4/heimdal/lib/hcrypto/camellia.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef HEIM_CAMELLIA_H +#define HEIM_CAMELLIA_H 1 + +#include <krb5-types.h> +#include "camellia-ntt.h" + +/* symbol renaming */ +#define CAMELLIA_set_key hc_CAMELLIA_set_encrypt_key +#define CAMELLIA_encrypt hc_CAMELLIA_encrypt +#define CAMELLIA_decrypt hc_CAMELLIA_decrypt +#define CAMELLIA_cbc_encrypt hc_CAMELLIA_cbc_encrypt + +/* + * + */ + +#define CAMELLIA_BLOCK_SIZE 16 +#define CAMELLIA_MAXNR 14 + +#define CAMELLIA_ENCRYPT 1 +#define CAMELLIA_DECRYPT 0 + +typedef struct camellia_key { + unsigned int bits; + KEY_TABLE_TYPE key; +} CAMELLIA_KEY; + +int CAMELLIA_set_key(const unsigned char *, const int, CAMELLIA_KEY *); + +void CAMELLIA_encrypt(const unsigned char *, unsigned char *, + const CAMELLIA_KEY *); +void CAMELLIA_decrypt(const unsigned char *, unsigned char *, + const CAMELLIA_KEY *); + +void CAMELLIA_cbc_encrypt(const unsigned char *, unsigned char *, + const unsigned long, const CAMELLIA_KEY *, + unsigned char *, int); + +#endif /* HEIM_CAMELLIA_H */ diff --git a/source4/heimdal/lib/hcrypto/dh-imath.c b/source4/heimdal/lib/hcrypto/dh-imath.c index 17592bbdf69..494d436d131 100644 --- a/source4/heimdal/lib/hcrypto/dh-imath.c +++ b/source4/heimdal/lib/hcrypto/dh-imath.c @@ -43,7 +43,7 @@ #include "imath/imath.h" -RCSID("$Id: dh-imath.c 18645 2006-10-20 06:56:57Z lha $"); +RCSID("$Id: dh-imath.c 22368 2007-12-28 15:27:52Z lha $"); static void BN2mpz(mpz_t *s, const BIGNUM *bn) @@ -224,7 +224,7 @@ dh_finish(DH *dh) * */ -const DH_METHOD hc_dh_imath_method = { +const DH_METHOD _hc_dh_imath_method = { "hcrypto imath DH", dh_generate_key, dh_compute_key, @@ -236,8 +236,16 @@ const DH_METHOD hc_dh_imath_method = { dh_generate_params }; +/** + * DH implementation using libimath. + * + * @return the DH_METHOD for the DH implementation using libimath. + * + * @ingroup hcrypto_dh + */ + const DH_METHOD * DH_imath_method(void) { - return &hc_dh_imath_method; + return &_hc_dh_imath_method; } diff --git a/source4/heimdal/lib/hcrypto/dh.c b/source4/heimdal/lib/hcrypto/dh.c index b558eb901cc..9f1af0b3b11 100644 --- a/source4/heimdal/lib/hcrypto/dh.c +++ b/source4/heimdal/lib/hcrypto/dh.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Kungliga Tekniska Högskolan + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -35,7 +35,7 @@ #include <config.h> #endif -RCSID("$Id: dh.c 18618 2006-10-19 17:31:51Z lha $"); +RCSID("$Id: dh.c 22397 2008-01-01 20:20:31Z lha $"); #include <stdio.h> #include <stdlib.h> @@ -43,8 +43,23 @@ RCSID("$Id: dh.c 18618 2006-10-19 17:31:51Z lha $"); #include <roken.h> -/* +/** + * @page page_dh DH - Diffie-Hellman key exchange + * + * Diffie-Hellman key exchange is a protocol that allows two parties + * to establish a shared secret key. + * + * Include and example how to use DH_new() and friends here. * + * See the library functions here: @ref hcrypto_dh + */ + +/** + * Create a new DH object using DH_new_method(NULL), see DH_new_method(). + * + * @return a newly allocated DH object. + * + * @ingroup hcrypto_dh */ DH * @@ -53,6 +68,17 @@ DH_new(void) return DH_new_method(NULL); } +/** + * Create a new DH object from the given engine, if the NULL is used, + * the default engine is used. Free the DH object with DH_free(). + * + * @param engine The engine to use to allocate the DH object. + * + * @return a newly allocated DH object. + * + * @ingroup hcrypto_dh + */ + DH * DH_new_method(ENGINE *engine) { @@ -88,6 +114,15 @@ DH_new_method(ENGINE *engine) return dh; } +/** + * Free a DH object and release related resources, like ENGINE, that + * the object was using. + * + * @param dh object to be freed. + * + * @ingroup hcrypto_dh + */ + void DH_free(DH *dh) { @@ -116,18 +151,52 @@ DH_free(DH *dh) free(dh); } +/** + * Add a reference to the DH object. The object should be free with + * DH_free() to drop the reference. + * + * @param dh the object to increase the reference count too. + * + * @return the updated reference count, can't safely be used except + * for debug printing. + * + * @ingroup hcrypto_dh + */ + int DH_up_ref(DH *dh) { return ++dh->references; } +/** + * The maximum output size of the DH_compute_key() function. + * + * @param dh The DH object to get the size from. + * + * @return the maximum size in bytes of the out data. + * + * @ingroup hcrypto_dh + */ + int DH_size(const DH *dh) { return BN_num_bytes(dh->p); } +/** + * Set the data index idx in the DH object to data. + * + * @param dh DH object. + * @param idx index to set the data for. + * @param data data to store for the index idx. + * + * @return 1 on success. + * + * @ingroup hcrypto_dh + */ + int DH_set_ex_data(DH *dh, int idx, void *data) { @@ -135,12 +204,36 @@ DH_set_ex_data(DH *dh, int idx, void *data) return 1; } +/** + * Get the data for index idx in the DH object. + * + * @param dh DH object. + * @param idx index to get the data for. + * + * @return the object store in index idx + * + * @ingroup hcrypto_dh + */ + void * DH_get_ex_data(DH *dh, int idx) { return dh->ex_data.sk; } +/** + * Generate DH parameters for the DH object give parameters. + * + * @param dh The DH object to generate parameters for. + * @param prime_len length of the prime + * @param generator generator, g + * @param cb Callback parameters to show progress, can be NULL. + * + * @return the maximum size in bytes of the out data. + * + * @ingroup hcrypto_dh + */ + int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, BN_GENCB *cb) { @@ -149,12 +242,17 @@ DH_generate_parameters_ex(DH *dh, int prime_len, int generator, BN_GENCB *cb) return 0; } -/* - * Check that +/** + * Check that the public key is sane. * - * pub_key > 1 and pub_key < p - 1 + * @param dh the local peer DH parameters. + * @param pub_key the remote peer public key parameters. + * @param codes return that the failures of the pub_key are. * - * to avoid small subgroups attack. + * @return 1 on success, 0 on failure and *codes is set the the + * combined fail check for the public key + * + * @ingroup hcrypto_dh */ int @@ -165,6 +263,19 @@ DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes) *codes = 0; + /** + * Checks that the function performs are: + * - pub_key is not negative + */ + + if (BN_is_negative(pub_key)) + goto out; + + /** + * - pub_key > 1 and pub_key < p - 1, + * to avoid small subgroups attack. + */ + bn = BN_new(); if (bn == NULL) goto out; @@ -184,6 +295,28 @@ DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes) if (BN_cmp(sum, dh->p) >= 0) *codes |= DH_CHECK_PUBKEY_TOO_LARGE; + /** + * - if g == 2, pub_key have more then one bit set, + * if bits set is 1, log_2(pub_key) is trival + */ + + if (!BN_set_word(bn, 2)) + goto out; + + if (BN_cmp(bn, pub_key) == 0) { + unsigned i, n = BN_num_bits(pub_key); + unsigned bits = 0; + + for (i = 0; i <= n; i++) + if (BN_is_bit_set(pub_key, i)) + bits++; + + if (bits > 1) { + *codes |= DH_CHECK_PUBKEY_TOO_SMALL; + goto out; + } + } + ret = 1; out: if (bn) @@ -194,24 +327,64 @@ out: return ret; } +/** + * Generate a new DH private-public key pair. The dh parameter must be + * allocted first with DH_new(). dh->p and dp->g must be set. + * + * @param dh dh parameter. + * + * @return 1 on success. + * + * @ingroup hcrypto_dh + */ + int DH_generate_key(DH *dh) { return dh->meth->generate_key(dh); } +/** + * Complute the shared secret key. + * + * @param shared_key the resulting shared key, need to be at least + * DH_size() large. + * @param peer_pub_key the peer's public key. + * @param dh the dh key pair. + * + * @return 1 on success. + * + * @ingroup hcrypto_dh + */ + int DH_compute_key(unsigned char *shared_key, const BIGNUM *peer_pub_key, DH *dh) { int codes; + /** + * Checks that the pubkey passed in is valid using + * DH_check_pubkey(). + */ + if (!DH_check_pubkey(dh, peer_pub_key, &codes) || codes != 0) return -1; return dh->meth->compute_key(shared_key, peer_pub_key, dh); } +/** + * Set a new method for the DH keypair. + * + * @param dh dh parameter. + * @param method the new method for the DH parameter. + * + * @return 1 on success. + * + * @ingroup hcrypto_dh + */ + int DH_set_method(DH *dh, const DH_METHOD *method) { @@ -271,8 +444,16 @@ static const DH_METHOD dh_null_method = { dh_null_generate_params }; -extern const DH_METHOD hc_dh_imath_method; -static const DH_METHOD *dh_default_method = &hc_dh_imath_method; +extern const DH_METHOD _hc_dh_imath_method; +static const DH_METHOD *dh_default_method = &_hc_dh_imath_method; + +/** + * Return the dummy DH implementation. + * + * @return pointer to a DH_METHOD. + * + * @ingroup hcrypto_dh + */ const DH_METHOD * DH_null_method(void) @@ -280,12 +461,28 @@ DH_null_method(void) return &dh_null_method; } +/** + * Set the default DH implementation. + * + * @param meth pointer to a DH_METHOD. + * + * @ingroup hcrypto_dh + */ + void DH_set_default_method(const DH_METHOD *meth) { dh_default_method = meth; } +/** + * Return the default DH implementation. + * + * @return pointer to a DH_METHOD. + * + * @ingroup hcrypto_dh + */ + const DH_METHOD * DH_get_default_method(void) { diff --git a/source4/heimdal/lib/hcrypto/evp.c b/source4/heimdal/lib/hcrypto/evp.c index 19b0ac85e7a..788000b0548 100644 --- a/source4/heimdal/lib/hcrypto/evp.c +++ b/source4/heimdal/lib/hcrypto/evp.c @@ -1,7 +1,42 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #ifdef HAVE_CONFIG_H -#include "config.h" +#include <config.h> #endif +RCSID("$Id: evp.c 22379 2007-12-29 11:13:26Z lha $"); + #include <sys/types.h> #include <stdio.h> #include <stdlib.h> @@ -13,6 +48,7 @@ #include <krb5-types.h> #include <aes.h> +#include "camellia.h" #include <des.h> #include <sha.h> #include <rc2.h> @@ -21,6 +57,13 @@ #include <md4.h> #include <md5.h> +/** + * @page page_evp EVP - generic crypto interface + * + * See the library functions here: @ref hcrypto_evp + */ + + typedef int (*evp_md_init)(EVP_MD_CTX *); typedef int (*evp_md_update)(EVP_MD_CTX *,const void *, size_t); typedef int (*evp_md_final)(void *, EVP_MD_CTX *); @@ -36,8 +79,14 @@ struct hc_evp_md { evp_md_cleanup cleanup; }; -/* +/** + * Return the output size of the message digest function. + * + * @param md the evp message * + * @return size output size of the message digest function. + * + * @ingroup hcrypto_evp */ size_t @@ -46,24 +95,60 @@ EVP_MD_size(const EVP_MD *md) return md->hash_size; } +/** + * Return the blocksize of the message digest function. + * + * @param md the evp message + * + * @return size size of the message digest block size + * + * @ingroup hcrypto_evp + */ + size_t EVP_MD_block_size(const EVP_MD *md) { return md->block_size; } +/** + * Allocate a messsage digest context object. Free with + * EVP_MD_CTX_destroy(). + * + * @return a newly allocated message digest context object. + * + * @ingroup hcrypto_evp + */ + EVP_MD_CTX * EVP_MD_CTX_create(void) { return calloc(1, sizeof(EVP_MD_CTX)); } +/** + * Initiate a messsage digest context object. Deallocate with + * EVP_MD_CTX_cleanup(). Please use EVP_MD_CTX_create() instead. + * + * @param ctx variable to initiate. + * + * @ingroup hcrypto_evp + */ + void EVP_MD_CTX_init(EVP_MD_CTX *ctx) { memset(ctx, 0, sizeof(*ctx)); } +/** + * Free a messsage digest context object. + * + * @param ctx context to free. + * + * @ingroup hcrypto_evp + */ + void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) { @@ -71,6 +156,16 @@ EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) free(ctx); } +/** + * Free the resources used by the EVP_MD context. + * + * @param ctx the context to free the resources from. + * + * @return 1 on success. + * + * @ingroup hcrypto_evp + */ + int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) { @@ -79,9 +174,19 @@ EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) ctx->md = NULL; ctx->engine = NULL; free(ctx->ptr); + memset(ctx, 0, sizeof(*ctx)); return 1; } +/** + * Get the EVP_MD use for a specified context. + * + * @param ctx the EVP_MD context to get the EVP_MD for. + * + * @return the EVP_MD used for the context. + * + * @ingroup hcrypto_evp + */ const EVP_MD * EVP_MD_CTX_md(EVP_MD_CTX *ctx) @@ -89,18 +194,50 @@ EVP_MD_CTX_md(EVP_MD_CTX *ctx) return ctx->md; } +/** + * Return the output size of the message digest function. + * + * @param ctx the evp message digest context + * + * @return size output size of the message digest function. + * + * @ingroup hcrypto_evp + */ + size_t EVP_MD_CTX_size(EVP_MD_CTX *ctx) { return EVP_MD_size(ctx->md); } +/** + * Return the blocksize of the message digest function. + * + * @param ctx the evp message digest context + * + * @return size size of the message digest block size + * + * @ingroup hcrypto_evp + */ + size_t EVP_MD_CTX_block_size(EVP_MD_CTX *ctx) { return EVP_MD_block_size(ctx->md); } +/** + * Init a EVP_MD_CTX for use a specific message digest and engine. + * + * @param ctx the message digest context to init. + * @param md the message digest to use. + * @param engine the engine to use, NULL to use the default engine. + * + * @return 1 on success. + * + * @ingroup hcrypto_evp + */ + int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *md, ENGINE *engine) { @@ -117,6 +254,18 @@ EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *md, ENGINE *engine) return 1; } +/** + * Update the digest with some data. + * + * @param ctx the context to update + * @param data the data to update the context with + * @param size length of data + * + * @return 1 on success. + * + * @ingroup hcrypto_evp + */ + int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t size) { @@ -124,6 +273,19 @@ EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t size) return 1; } +/** + * Complete the message digest. + * + * @param ctx the context to complete. + * @param hash the output of the message digest function. At least + * EVP_MD_size(). + * @param size the output size of hash. + * + * @return 1 on success. + * + * @ingroup hcrypto_evp + */ + int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, void *hash, unsigned int *size) { @@ -133,6 +295,23 @@ EVP_DigestFinal_ex(EVP_MD_CTX *ctx, void *hash, unsigned int *size) return 1; } +/** + * Do the whole EVP_MD_CTX_create(), EVP_DigestInit_ex(), + * EVP_DigestUpdate(), EVP_DigestFinal_ex(), EVP_MD_CTX_destroy() + * dance in one call. + * + * @param data the data to update the context with + * @param dsize length of data + * @param hash output data of at least EVP_MD_size() length. + * @param hsize output length of hash. + * @param md message digest to use + * @param engine engine to use, NULL for default engine. + * + * @return 1 on success. + * + * @ingroup hcrypto_evp + */ + int EVP_Digest(const void *data, size_t dsize, void *hash, unsigned int *hsize, const EVP_MD *md, ENGINE *engine) @@ -144,20 +323,26 @@ EVP_Digest(const void *data, size_t dsize, void *hash, unsigned int *hsize, if (ctx == NULL) return 0; ret = EVP_DigestInit_ex(ctx, md, engine); - if (ret != 1) + if (ret != 1) { + EVP_MD_CTX_destroy(ctx); return ret; + } ret = EVP_DigestUpdate(ctx, data, dsize); - if (ret != 1) + if (ret != 1) { + EVP_MD_CTX_destroy(ctx); return ret; + } ret = EVP_DigestFinal_ex(ctx, hash, hsize); - if (ret != 1) - return ret; EVP_MD_CTX_destroy(ctx); - return 1; + return ret; } -/* +/** + * The message digest SHA256 + * + * @return the message digest type. * + * @ingroup hcrypto_evp */ const EVP_MD * @@ -185,18 +370,42 @@ static const struct hc_evp_md sha1 = { NULL }; +/** + * The message digest SHA1 + * + * @return the message digest type. + * + * @ingroup hcrypto_evp + */ + const EVP_MD * EVP_sha1(void) { return &sha1; } +/** + * The message digest SHA1 + * + * @return the message digest type. + * + * @ingroup hcrypto_evp + */ + const EVP_MD * EVP_sha(void) { return &sha1; } +/** + * The message digest MD5 + * + * @return the message digest type. + * + * @ingroup hcrypto_evp + */ + const EVP_MD * EVP_md5(void) { @@ -212,6 +421,14 @@ EVP_md5(void) return &md5; } +/** + * The message digest MD4 + * + * @return the message digest type. + * + * @ingroup hcrypto_evp + */ + const EVP_MD * EVP_md4(void) { @@ -227,6 +444,14 @@ EVP_md4(void) return &md4; } +/** + * The message digest MD2 + * + * @return the message digest type. + * + * @ingroup hcrypto_evp + */ + const EVP_MD * EVP_md2(void) { @@ -255,10 +480,18 @@ null_Update (void *m, const void * data, size_t size) { } static void -null_Final(void *res, struct md5 *m) +null_Final(void *res, void *m) { } +/** + * The null message digest + * + * @return the message digest type. + * + * @ingroup hcrypto_evp + */ + const EVP_MD * EVP_md_null(void) { @@ -282,8 +515,14 @@ int EVP_SignFinal(EVP_MD_CTX *, void *, size_t *, EVP_PKEY *); int EVP_VerifyFinal(EVP_MD_CTX *, const void *, size_t, EVP_PKEY *); #endif -/* +/** + * Return the block size of the cipher. + * + * @param c cipher to get the block size from. * + * @return the block size of the cipher. + * + * @ingroup hcrypto_evp */ size_t @@ -292,24 +531,63 @@ EVP_CIPHER_block_size(const EVP_CIPHER *c) return c->block_size; } +/** + * Return the key size of the cipher. + * + * @param c cipher to get the key size from. + * + * @return the key size of the cipher. + * + * @ingroup hcrypto_evp + */ + size_t EVP_CIPHER_key_length(const EVP_CIPHER *c) { return c->key_len; } +/** + * Return the IV size of the cipher. + * + * @param c cipher to get the IV size from. + * + * @return the IV size of the cipher. + * + * @ingroup hcrypto_evp + */ + size_t EVP_CIPHER_iv_length(const EVP_CIPHER *c) { return c->iv_len; } +/** + * Initiate a EVP_CIPHER_CTX context. Clean up with + * EVP_CIPHER_CTX_cleanup(). + * + * @param c the cipher initiate. + * + * @ingroup hcrypto_evp + */ + void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *c) { memset(c, 0, sizeof(*c)); } +/** + * Clean up the EVP_CIPHER_CTX context. + * + * @param c the cipher to clean up. + * + * @return 1 on success. + * + * @ingroup hcrypto_evp + */ + int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c) { @@ -336,54 +614,149 @@ EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad) } #endif +/** + * Return the EVP_CIPHER for a EVP_CIPHER_CTX context. + * + * @param ctx the context to get the cipher type from. + * + * @return the EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + const EVP_CIPHER * EVP_CIPHER_CTX_cipher(EVP_CIPHER_CTX *ctx) { return ctx->cipher; } +/** + * Return the block size of the cipher context. + * + * @param ctx cipher context to get the block size from. + * + * @return the block size of the cipher context. + * + * @ingroup hcrypto_evp + */ + size_t EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx) { return EVP_CIPHER_block_size(ctx->cipher); } +/** + * Return the key size of the cipher context. + * + * @param ctx cipher context to get the key size from. + * + * @return the key size of the cipher context. + * + * @ingroup hcrypto_evp + */ + size_t EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) { return EVP_CIPHER_key_length(ctx->cipher); } +/** + * Return the IV size of the cipher context. + * + * @param ctx cipher context to get the IV size from. + * + * @return the IV size of the cipher context. + * + * @ingroup hcrypto_evp + */ + size_t EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) { return EVP_CIPHER_iv_length(ctx->cipher); } +/** + * Get the flags for an EVP_CIPHER_CTX context. + * + * @param ctx the EVP_CIPHER_CTX to get the flags from + * + * @return the flags for an EVP_CIPHER_CTX. + * + * @ingroup hcrypto_evp + */ + unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx) { return ctx->cipher->flags; } +/** + * Get the mode for an EVP_CIPHER_CTX context. + * + * @param ctx the EVP_CIPHER_CTX to get the mode from + * + * @return the mode for an EVP_CIPHER_CTX. + * + * @ingroup hcrypto_evp + */ + int EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx) { return EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_MODE; } +/** + * Get the app data for an EVP_CIPHER_CTX context. + * + * @param ctx the EVP_CIPHER_CTX to get the app data from + * + * @return the app data for an EVP_CIPHER_CTX. + * + * @ingroup hcrypto_evp + */ + void * EVP_CIPHER_CTX_get_app_data(EVP_CIPHER_CTX *ctx) { return ctx->app_data; } +/** + * Set the app data for an EVP_CIPHER_CTX context. + * + * @param ctx the EVP_CIPHER_CTX to set the app data for + * @param data the app data to set for an EVP_CIPHER_CTX. + * + * @ingroup hcrypto_evp + */ + void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data) { ctx->app_data = data; } +/** + * Initiate the EVP_CIPHER_CTX context to encrypt or decrypt data. + * Clean up with EVP_CIPHER_CTX_cleanup(). + * + * @param ctx context to initiate + * @param c cipher to use. + * @param engine crypto engine to use, NULL to select default. + * @param key the crypto key to use, NULL will use the previous value. + * @param iv the IV to use, NULL will use the previous value. + * @param encp non zero will encrypt, -1 use the previous value. + * + * @return 1 on success. + * + * @ingroup hcrypto_evp + */ + int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *c, ENGINE *engine, const void *key, const void *iv, int encp) @@ -426,6 +799,17 @@ EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *c, ENGINE *engine, return 1; } +/** + * Encypher/decypher data + * + * @param ctx the cipher context. + * @param out out data from the operation. + * @param in in data to the operation. + * @param size length of data. + * + * @return 1 on success. + */ + int EVP_Cipher(EVP_CIPHER_CTX *ctx, void *out, const void *in,size_t size) { @@ -461,6 +845,14 @@ enc_null_cleanup(EVP_CIPHER_CTX *ctx) return 1; } +/** + * The NULL cipher type, does no encryption/decryption. + * + * @return the null EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + const EVP_CIPHER * EVP_enc_null(void) { @@ -524,6 +916,13 @@ rc2_cleanup(EVP_CIPHER_CTX *ctx) return 1; } +/** + * The RC2 cipher type + * + * @return the RC2 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ const EVP_CIPHER * EVP_rc2_cbc(void) @@ -546,6 +945,14 @@ EVP_rc2_cbc(void) return &rc2_cbc; } +/** + * The RC2-40 cipher type + * + * @return the RC2-40 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + const EVP_CIPHER * EVP_rc2_40_cbc(void) { @@ -567,6 +974,14 @@ EVP_rc2_40_cbc(void) return &rc2_40_cbc; } +/** + * The RC2-64 cipher type + * + * @return the RC2-64 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + const EVP_CIPHER * EVP_rc2_64_cbc(void) { @@ -588,8 +1003,12 @@ EVP_rc2_64_cbc(void) return &rc2_64_cbc; } -/* +/** + * The RC4 cipher type * + * @return the RC4 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp */ const EVP_CIPHER * @@ -600,6 +1019,14 @@ EVP_rc4(void) return NULL; } +/** + * The RC4-40 cipher type + * + * @return the RC4-40 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + const EVP_CIPHER * EVP_rc4_40(void) { @@ -651,6 +1078,14 @@ des_ede3_cbc_cleanup(EVP_CIPHER_CTX *ctx) return 1; } +/** + * The tripple DES cipher type + * + * @return the DES-EDE3-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + const EVP_CIPHER * EVP_des_ede3_cbc(void) { @@ -708,6 +1143,14 @@ aes_cleanup(EVP_CIPHER_CTX *ctx) return 1; } +/** + * The AES-128 cipher type + * + * @return the AES-128 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + const EVP_CIPHER * EVP_aes_128_cbc(void) { @@ -729,6 +1172,14 @@ EVP_aes_128_cbc(void) return &aes_128_cbc; } +/** + * The AES-192 cipher type + * + * @return the AES-192 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + const EVP_CIPHER * EVP_aes_192_cbc(void) { @@ -750,6 +1201,13 @@ EVP_aes_192_cbc(void) return &aes_192_cbc; } +/** + * The AES-256 cipher type + * + * @return the AES-256 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ const EVP_CIPHER * EVP_aes_256_cbc(void) @@ -772,6 +1230,123 @@ EVP_aes_256_cbc(void) return &aes_256_cbc; } +static int +camellia_init(EVP_CIPHER_CTX *ctx, + const unsigned char * key, + const unsigned char * iv, + int encp) +{ + CAMELLIA_KEY *k = ctx->cipher_data; + k->bits = ctx->cipher->key_len * 8; + CAMELLIA_set_key(key, ctx->cipher->key_len * 8, k); + return 1; +} + +static int +camellia_do_cipher(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + unsigned int size) +{ + CAMELLIA_KEY *k = ctx->cipher_data; + CAMELLIA_cbc_encrypt(in, out, size, k, ctx->iv, ctx->encrypt); + return 1; +} + +static int +camellia_cleanup(EVP_CIPHER_CTX *ctx) +{ + memset(ctx->cipher_data, 0, sizeof(CAMELLIA_KEY)); + return 1; +} + +/** + * The Camellia-128 cipher type + * + * @return the Camellia-128 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +const EVP_CIPHER * +EVP_camellia_128_cbc(void) +{ + static const EVP_CIPHER cipher = { + 0, + 16, + 16, + 16, + EVP_CIPH_CBC_MODE, + camellia_init, + camellia_do_cipher, + camellia_cleanup, + sizeof(CAMELLIA_KEY), + NULL, + NULL, + NULL, + NULL + }; + return &cipher; +} + +/** + * The Camellia-198 cipher type + * + * @return the Camellia-198 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +const EVP_CIPHER * +EVP_camellia_192_cbc(void) +{ + static const EVP_CIPHER cipher = { + 0, + 16, + 24, + 16, + EVP_CIPH_CBC_MODE, + camellia_init, + camellia_do_cipher, + camellia_cleanup, + sizeof(CAMELLIA_KEY), + NULL, + NULL, + NULL, + NULL + }; + return &cipher; +} + +/** + * The Camellia-256 cipher type + * + * @return the Camellia-256 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +const EVP_CIPHER * +EVP_camellia_256_cbc(void) +{ + static const EVP_CIPHER cipher = { + 0, + 16, + 32, + 16, + EVP_CIPH_CBC_MODE, + camellia_init, + camellia_do_cipher, + camellia_cleanup, + sizeof(CAMELLIA_KEY), + NULL, + NULL, + NULL, + NULL + }; + return &cipher; +} + /* * */ @@ -783,9 +1358,21 @@ static const struct cipher_name { { "des-ede3-cbc", EVP_des_ede3_cbc }, { "aes-128-cbc", EVP_aes_128_cbc }, { "aes-192-cbc", EVP_aes_192_cbc }, - { "aes-256-cbc", EVP_aes_256_cbc } + { "aes-256-cbc", EVP_aes_256_cbc }, + { "camellia-128-cbc", EVP_camellia_128_cbc }, + { "camellia-192-cbc", EVP_camellia_192_cbc }, + { "camellia-256-cbc", EVP_camellia_256_cbc } }; +/** + * Get the cipher type using their name. + * + * @param name the name of the cipher. + * + * @return the selected EVP_CIPHER pointer or NULL if not found. + * + * @ingroup hcrypto_evp + */ const EVP_CIPHER * EVP_get_cipherbyname(const char *name) @@ -807,6 +1394,26 @@ EVP_get_cipherbyname(const char *name) #define min(a,b) (((a)>(b))?(b):(a)) #endif +/** + * Provides a legancy string to key function, used in PEM files. + * + * New protocols should use new string to key functions like NIST + * SP56-800A or PKCS#5 v2.0 (see PKCS5_PBKDF2_HMAC_SHA1()). + * + * @param type type of cipher to use + * @param md message digest to use + * @param salt salt salt string, should be an binary 8 byte buffer. + * @param data the password/input key string. + * @param datalen length of data parameter. + * @param count iteration counter. + * @param keydata output keydata, needs to of the size EVP_CIPHER_key_length(). + * @param ivdata output ivdata, needs to of the size EVP_CIPHER_block_size(). + * + * @return the size of derived key. + * + * @ingroup hcrypto_evp + */ + int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, @@ -886,8 +1493,10 @@ EVP_BytesToKey(const EVP_CIPHER *type, return EVP_CIPHER_key_length(type); } -/* +/** + * Add all algorithms to the crypto core. * + * @ingroup hcrypto_core */ void @@ -896,12 +1505,25 @@ OpenSSL_add_all_algorithms(void) return; } +/** + * Add all algorithms to the crypto core using configuration file. + * + * @ingroup hcrypto_core + */ + void OpenSSL_add_all_algorithms_conf(void) { return; } +/** + * Add all algorithms to the crypto core, but don't use the + * configuration file. + * + * @ingroup hcrypto_core + */ + void OpenSSL_add_all_algorithms_noconf(void) { diff --git a/source4/heimdal/lib/hcrypto/evp.h b/source4/heimdal/lib/hcrypto/evp.h index a3fbc4c9cad..4910ca01b8d 100644 --- a/source4/heimdal/lib/hcrypto/evp.h +++ b/source4/heimdal/lib/hcrypto/evp.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: evp.h 18312 2006-10-07 17:21:48Z lha $ */ +/* $Id: evp.h 21687 2007-07-24 16:29:05Z lha $ */ #ifndef HEIM_EVP_H #define HEIM_EVP_H 1 @@ -83,6 +83,9 @@ #define EVP_rc2_cbc hc_EVP_rc2_cbc #define EVP_rc4 hc_EVP_rc4 #define EVP_rc4_40 hc_EVP_rc4_40 +#define EVP_camellia_128_cbc hc_EVP_camellia_128_cbc +#define EVP_camellia_192_cbc hc_EVP_camellia_192_cbc +#define EVP_camellia_256_cbc hc_EVP_camellia_256_cbc #define EVP_sha hc_EVP_sha #define EVP_sha1 hc_EVP_sha1 #define EVP_sha256 hc_EVP_sha256 @@ -180,6 +183,9 @@ const EVP_CIPHER * EVP_rc2_64_cbc(void); const EVP_CIPHER * EVP_rc2_cbc(void); const EVP_CIPHER * EVP_rc4(void); const EVP_CIPHER * EVP_rc4_40(void); +const EVP_CIPHER * EVP_camellia_128_cbc(void); +const EVP_CIPHER * EVP_camellia_192_cbc(void); +const EVP_CIPHER * EVP_camellia_256_cbc(void); /* * diff --git a/source4/heimdal/lib/hcrypto/hmac.c b/source4/heimdal/lib/hcrypto/hmac.c index 6c59758b11c..d0433edef6d 100644 --- a/source4/heimdal/lib/hcrypto/hmac.c +++ b/source4/heimdal/lib/hcrypto/hmac.c @@ -1,6 +1,35 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ #include <sys/types.h> #include <stdio.h> diff --git a/source4/heimdal/lib/hcrypto/imath/imath.c b/source4/heimdal/lib/hcrypto/imath/imath.c index 376425788b0..4487029f78f 100755 --- a/source4/heimdal/lib/hcrypto/imath/imath.c +++ b/source4/heimdal/lib/hcrypto/imath/imath.c @@ -2,7 +2,7 @@ Name: imath.c Purpose: Arbitrary precision integer arithmetic routines. Author: M. J. Fromberger <http://www.dartmouth.edu/~sting/> - Info: $Id: imath.c 20854 2007-06-03 18:04:10Z lha $ + Info: $Id: imath.c 22648 2008-02-25 07:37:57Z lha $ Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved. @@ -1769,7 +1769,7 @@ mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **e return MP_RANGE; /* Skip leading whitespace */ - while(isspace((int)*str)) + while(isspace((unsigned char)*str)) ++str; /* Handle leading sign tag (+/-, positive default) */ @@ -3135,7 +3135,7 @@ static int s_ch2val(char c, int r) if(isdigit((unsigned char) c)) out = c - '0'; else if(r > 10 && isalpha((unsigned char) c)) - out = toupper(c) - 'A' + 10; + out = toupper((unsigned char)c) - 'A' + 10; else return -1; diff --git a/source4/heimdal/lib/hcrypto/rand.c b/source4/heimdal/lib/hcrypto/rand.c index 248fdde6208..79dd39eb766 100644 --- a/source4/heimdal/lib/hcrypto/rand.c +++ b/source4/heimdal/lib/hcrypto/rand.c @@ -35,7 +35,7 @@ #include <config.h> #endif -RCSID("$Id: rand.c 21198 2007-06-20 05:10:41Z lha $"); +RCSID("$Id: rand.c 22199 2007-12-07 13:43:25Z lha $"); #include <stdio.h> #include <stdlib.h> @@ -189,13 +189,12 @@ RAND_file_name(char *filename, size_t size) pathp = 1; } } - if (e == NULL) { - struct passwd *pw = getpwuid(getuid()); - if (pw) { - e = pw->pw_dir; - pathp = 1; - } - } + /* + * Here we really want to call getpwuid(getuid()) but this will + * cause recursive lookups if the nss library uses + * gssapi/krb5/hcrypto to authenticate to the ldap servers. + */ + if (e == NULL) return NULL; diff --git a/source4/heimdal/lib/hcrypto/rsa.c b/source4/heimdal/lib/hcrypto/rsa.c index a7b4371e4d4..270857d1759 100644 --- a/source4/heimdal/lib/hcrypto/rsa.c +++ b/source4/heimdal/lib/hcrypto/rsa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -35,7 +35,7 @@ #include <config.h> #endif -RCSID("$Id: rsa.c 20466 2007-04-20 08:29:05Z lha $"); +RCSID("$Id: rsa.c 22422 2008-01-13 09:43:59Z lha $"); #include <stdio.h> #include <stdlib.h> @@ -46,12 +46,41 @@ RCSID("$Id: rsa.c 20466 2007-04-20 08:29:05Z lha $"); #include <roken.h> +/** + * @page page_rsa RSA - public-key cryptography + * + * RSA is named by its inventors (Ron Rivest, Adi Shamir, and Leonard + * Adleman) (published in 1977), patented expired in 21 September 2000. + * + * See the library functions here: @ref hcrypto_rsa + */ + +/** + * Same as RSA_new_method() using NULL as engine. + * + * @return a newly allocated RSA object. Free with RSA_free(). + * + * @ingroup hcrypto_rsa + */ + RSA * RSA_new(void) { return RSA_new_method(NULL); } +/** + * Allocate a new RSA object using the engine, if NULL is specified as + * the engine, use the default RSA engine as returned by + * ENGINE_get_default_RSA(). + * + * @param engine Specific what ENGINE RSA provider should be used. + * + * @return a newly allocated RSA object. Free with RSA_free(). + * + * @ingroup hcrypto_rsa + */ + RSA * RSA_new_method(ENGINE *engine) { @@ -87,6 +116,12 @@ RSA_new_method(ENGINE *engine) return rsa; } +/** + * Free an allocation RSA object. + * + * @param rsa the RSA object to free. + * @ingroup hcrypto_rsa + */ void RSA_free(RSA *rsa) @@ -117,18 +152,51 @@ RSA_free(RSA *rsa) free(rsa); } +/** + * Add an extra reference to the RSA object. The object should be free + * with RSA_free() to drop the reference. + * + * @param rsa the object to add reference counting too. + * + * @return the current reference count, can't safely be used except + * for debug printing. + * + * @ingroup hcrypto_rsa + */ + int RSA_up_ref(RSA *rsa) { return ++rsa->references; } +/** + * Return the RSA_METHOD used for this RSA object. + * + * @param rsa the object to get the method from. + * + * @return the method used for this RSA object. + * + * @ingroup hcrypto_rsa + */ + const RSA_METHOD * RSA_get_method(const RSA *rsa) { return rsa->meth; } +/** + * Set a new method for the RSA keypair. + * + * @param rsa rsa parameter. + * @param method the new method for the RSA parameter. + * + * @return 1 on success. + * + * @ingroup hcrypto_rsa + */ + int RSA_set_method(RSA *rsa, const RSA_METHOD *method) { @@ -144,6 +212,17 @@ RSA_set_method(RSA *rsa, const RSA_METHOD *method) return 1; } +/** + * Set the application data for the RSA object. + * + * @param rsa the rsa object to set the parameter for + * @param arg the data object to store + * + * @return 1 on success. + * + * @ingroup hcrypto_rsa + */ + int RSA_set_app_data(RSA *rsa, void *arg) { @@ -151,6 +230,16 @@ RSA_set_app_data(RSA *rsa, void *arg) return 1; } +/** + * Get the application data for the RSA object. + * + * @param rsa the rsa object to get the parameter for + * + * @return the data object + * + * @ingroup hcrypto_rsa + */ + void * RSA_get_app_data(RSA *rsa) { @@ -296,7 +385,11 @@ RSA_null_method(void) } extern const RSA_METHOD hc_rsa_imath_method; +#ifdef HAVE_GMP +static const RSA_METHOD *default_rsa_method = &hc_rsa_gmp_method; +#else static const RSA_METHOD *default_rsa_method = &hc_rsa_imath_method; +#endif const RSA_METHOD * RSA_get_default_method(void) diff --git a/source4/heimdal/lib/hcrypto/rsa.h b/source4/heimdal/lib/hcrypto/rsa.h index 575774dbde8..0f54ca0a4dd 100644 --- a/source4/heimdal/lib/hcrypto/rsa.h +++ b/source4/heimdal/lib/hcrypto/rsa.h @@ -32,7 +32,7 @@ */ /* - * $Id: rsa.h 19734 2007-01-05 20:26:23Z lha $ + * $Id: rsa.h 22269 2007-12-11 10:59:22Z lha $ */ #ifndef _HEIM_RSA_H @@ -41,6 +41,7 @@ /* symbol renaming */ #define RSA_null_method hc_RSA_null_method #define RSA_imath_method hc_RSA_imath_method +#define RSA_gmp_method hc_RSA_gmp_method #define RSA_new hc_RSA_new #define RSA_new_method hc_RSA_new_method #define RSA_free hc_RSA_free @@ -133,6 +134,7 @@ struct RSA { const RSA_METHOD *RSA_null_method(void); const RSA_METHOD *RSA_imath_method(void); +const RSA_METHOD *RSA_gmp_method(void); /* * diff --git a/source4/heimdal/lib/hdb/dbinfo.c b/source4/heimdal/lib/hdb/dbinfo.c new file mode 100644 index 00000000000..d43e31b39ad --- /dev/null +++ b/source4/heimdal/lib/hdb/dbinfo.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hdb_locl.h" + +RCSID("$Id: dbinfo.c 22306 2007-12-14 12:22:38Z lha $"); + +struct hdb_dbinfo { + char *label; + char *realm; + char *dbname; + char *mkey_file; + char *acl_file; + char *log_file; + const krb5_config_binding *binding; + struct hdb_dbinfo *next; +}; + +static int +get_dbinfo(krb5_context context, + const krb5_config_binding *db_binding, + const char *label, + struct hdb_dbinfo **db) +{ + struct hdb_dbinfo *di; + const char *p; + + *db = NULL; + + p = krb5_config_get_string(context, db_binding, "dbname", NULL); + if(p == NULL) + return 0; + + di = calloc(1, sizeof(*di)); + if (di == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + di->label = strdup(label); + di->dbname = strdup(p); + + p = krb5_config_get_string(context, db_binding, "realm", NULL); + if(p) + di->realm = strdup(p); + p = krb5_config_get_string(context, db_binding, "mkey_file", NULL); + if(p) + di->mkey_file = strdup(p); + p = krb5_config_get_string(context, db_binding, "acl_file", NULL); + if(p) + di->acl_file = strdup(p); + p = krb5_config_get_string(context, db_binding, "log_file", NULL); + if(p) + di->log_file = strdup(p); + + di->binding = db_binding; + + *db = di; + return 0; +} + + +int +hdb_get_dbinfo(krb5_context context, struct hdb_dbinfo **dbp) +{ + const krb5_config_binding *db_binding; + struct hdb_dbinfo *di, **dt, *databases; + const char *default_dbname = HDB_DEFAULT_DB; + const char *default_mkey = HDB_DB_DIR "/m-key"; + const char *default_acl = HDB_DB_DIR "/kadmind.acl"; + const char *p; + int ret; + + *dbp = NULL; + dt = NULL; + databases = NULL; + + db_binding = krb5_config_get(context, NULL, krb5_config_list, + "kdc", + "database", + NULL); + if (db_binding) { + + ret = get_dbinfo(context, db_binding, "default", &di); + if (ret == 0 && di) { + databases = di; + dt = &di->next; + } + + for ( ; db_binding != NULL; db_binding = db_binding->next) { + + if (db_binding->type != krb5_config_list) + continue; + + ret = get_dbinfo(context, db_binding->u.list, + db_binding->name, &di); + if (ret) + krb5_err(context, 1, ret, "failed getting realm"); + + if (di == NULL) + continue; + + if (dt) + *dt = di; + else + databases = di; + dt = &di->next; + + } + } + + if(databases == NULL) { + /* if there are none specified, create one and use defaults */ + di = calloc(1, sizeof(*di)); + databases = di; + di->label = strdup("default"); + } + + for(di = databases; di; di = di->next) { + if(di->dbname == NULL) { + di->dbname = strdup(default_dbname); + if (di->mkey_file == NULL) + di->mkey_file = strdup(default_mkey); + } + if(di->mkey_file == NULL) { + p = strrchr(di->dbname, '.'); + if(p == NULL || strchr(p, '/') != NULL) + /* final pathname component does not contain a . */ + asprintf(&di->mkey_file, "%s.mkey", di->dbname); + else + /* the filename is something.else, replace .else with + .mkey */ + asprintf(&di->mkey_file, "%.*s.mkey", + (int)(p - di->dbname), di->dbname); + } + if(di->acl_file == NULL) + di->acl_file = strdup(default_acl); + } + *dbp = databases; + return 0; +} + + +struct hdb_dbinfo * +hdb_dbinfo_get_next(struct hdb_dbinfo *dbp, struct hdb_dbinfo *dbprevp) +{ + if (dbprevp == NULL) + return dbp; + else + return dbprevp->next; +} + +const char * +hdb_dbinfo_get_label(krb5_context context, struct hdb_dbinfo *dbp) +{ + return dbp->label; +} + +const char * +hdb_dbinfo_get_realm(krb5_context context, struct hdb_dbinfo *dbp) +{ + return dbp->realm; +} + +const char * +hdb_dbinfo_get_dbname(krb5_context context, struct hdb_dbinfo *dbp) +{ + return dbp->dbname; +} + +const char * +hdb_dbinfo_get_mkey_file(krb5_context context, struct hdb_dbinfo *dbp) +{ + return dbp->mkey_file; +} + +const char * +hdb_dbinfo_get_acl_file(krb5_context context, struct hdb_dbinfo *dbp) +{ + return dbp->acl_file; +} + +const char * +hdb_dbinfo_get_log_file(krb5_context context, struct hdb_dbinfo *dbp) +{ + return dbp->log_file; +} + +const krb5_config_binding * +hdb_dbinfo_get_binding(krb5_context context, struct hdb_dbinfo *dbp) +{ + return dbp->binding; +} + +void +hdb_free_dbinfo(krb5_context context, struct hdb_dbinfo **dbp) +{ + struct hdb_dbinfo *di, *ndi; + + for(di = *dbp; di != NULL; di = ndi) { + ndi = di->next; + free (di->realm); + free (di->dbname); + if (di->mkey_file) + free (di->mkey_file); + free(di); + } + *dbp = NULL; +} + +/** + * Return the directory where the hdb database resides. + * + * @param context Kerberos 5 context. + * + * @return string pointing to directory. + */ + +const char * +hdb_db_dir(krb5_context context) +{ + return HDB_DB_DIR; +} + +/** + * Return the default hdb database resides. + * + * @param context Kerberos 5 context. + * + * @return string pointing to directory. + */ + +const char * +hdb_default_db(krb5_context context) +{ + return HDB_DEFAULT_DB; +} diff --git a/source4/heimdal/lib/hdb/hdb-protos.h b/source4/heimdal/lib/hdb/hdb-protos.h index 6d679fd48f7..4c3d3eb1ab1 100644 --- a/source4/heimdal/lib/hdb/hdb-protos.h +++ b/source4/heimdal/lib/hdb/hdb-protos.h @@ -43,6 +43,9 @@ hdb_db_create ( const char */*filename*/); const char * +hdb_db_dir (krb5_context /*context*/); + +const char * hdb_dbinfo_get_acl_file ( krb5_context /*context*/, struct hdb_dbinfo */*dbp*/); @@ -63,6 +66,11 @@ hdb_dbinfo_get_label ( struct hdb_dbinfo */*dbp*/); const char * +hdb_dbinfo_get_log_file ( + krb5_context /*context*/, + struct hdb_dbinfo */*dbp*/); + +const char * hdb_dbinfo_get_mkey_file ( krb5_context /*context*/, struct hdb_dbinfo */*dbp*/); @@ -77,6 +85,9 @@ hdb_dbinfo_get_realm ( krb5_context /*context*/, struct hdb_dbinfo */*dbp*/); +const char * +hdb_default_db (krb5_context /*context*/); + krb5_error_code hdb_enctype2key ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h index 830589388f8..742b92405d4 100644 --- a/source4/heimdal/lib/hdb/hdb.h +++ b/source4/heimdal/lib/hdb/hdb.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: hdb.h 20535 2007-04-23 07:49:16Z lha $ */ +/* $Id: hdb.h 22198 2007-12-07 13:09:25Z lha $ */ #ifndef __HDB_H__ #define __HDB_H__ @@ -135,10 +135,6 @@ struct hdb_so_method { krb5_error_code (*create)(krb5_context, HDB **, const char *filename); }; -#define HDB_DB_DIR "/var/heimdal" -#define HDB_DEFAULT_DB HDB_DB_DIR "/heimdal" -#define HDB_DB_FORMAT_ENTRY "hdb/db-format" - typedef krb5_error_code (*hdb_foreach_func_t)(krb5_context, HDB*, hdb_entry_ex*, void*); extern krb5_kt_ops hdb_kt_ops; diff --git a/source4/heimdal/lib/hdb/hdb_locl.h b/source4/heimdal/lib/hdb/hdb_locl.h index ad16075b247..8f9d6fc4c2b 100644 --- a/source4/heimdal/lib/hdb/hdb_locl.h +++ b/source4/heimdal/lib/hdb/hdb_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: hdb_locl.h 12820 2003-09-10 21:54:58Z lha $ */ +/* $Id: hdb_locl.h 22209 2007-12-07 19:03:41Z lha $ */ #ifndef __HDB_LOCL_H__ #define __HDB_LOCL_H__ @@ -64,6 +64,9 @@ #include <hdb.h> #include <hdb-private.h> +#define HDB_DEFAULT_DB HDB_DB_DIR "/heimdal" +#define HDB_DB_FORMAT_ENTRY "hdb/db-format" + krb5_error_code hdb_ldb_create ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/hdb/keys.c b/source4/heimdal/lib/hdb/keys.c index 9b870501201..60a58677fef 100644 --- a/source4/heimdal/lib/hdb/keys.c +++ b/source4/heimdal/lib/hdb/keys.c @@ -33,7 +33,7 @@ #include "hdb_locl.h" -RCSID("$Id: keys.c 18819 2006-10-22 09:40:12Z lha $"); +RCSID("$Id: keys.c 22071 2007-11-14 20:04:50Z lha $"); /* * free all the memory used by (len, keys) @@ -105,7 +105,7 @@ parse_key_set(krb5_context context, const char *key, salt->saltvalue.length = 0; for(i = 0; i < num_buf; i++) { - if(enctypes == NULL) { + if(enctypes == NULL && num_buf > 1) { /* this might be a etype specifier */ /* XXX there should be a string_to_etypes handling special cases like `des' and `all' */ @@ -124,7 +124,9 @@ parse_key_set(krb5_context context, const char *key, } else return ret; } - } else if(salt->salttype == 0) { + continue; + } + if(salt->salttype == 0) { /* interpret string as a salt specifier, if no etype is set, this sets default values */ /* XXX should perhaps use string_to_salttype, but that @@ -142,7 +144,10 @@ parse_key_set(krb5_context context, const char *key, } salt->salttype = KRB5_AFS3_SALT; } - } else { + continue; + } + + { /* if there is a final string, use it as the string to salt with, this is mostly useful with null salt for v4 compat, and a cell name for afs compat */ @@ -239,7 +244,7 @@ add_enctype_to_key_set(Key **key_set, size_t *nkeyset, /* * Generate the `key_set' from the [kadmin]default_keys statement. If * `no_salt' is set, salt is not important (and will not be set) since - * its random keys that is going to be created. + * it's random keys that is going to be created. */ krb5_error_code diff --git a/source4/heimdal/lib/hdb/mkey.c b/source4/heimdal/lib/hdb/mkey.c index 02d87b6cf3e..05cf71c5931 100644 --- a/source4/heimdal/lib/hdb/mkey.c +++ b/source4/heimdal/lib/hdb/mkey.c @@ -36,7 +36,7 @@ #define O_BINARY 0 #endif -RCSID("$Id: mkey.c 17445 2006-05-05 10:37:46Z lha $"); +RCSID("$Id: mkey.c 21745 2007-07-31 16:11:25Z lha $"); struct hdb_master_key_data { krb5_keytab_entry keytab; @@ -129,6 +129,11 @@ read_master_keytab(krb5_context context, const char *filename, *mkey = NULL; while(krb5_kt_next_entry(context, id, &entry, &cursor) == 0) { p = calloc(1, sizeof(*p)); + if(p == NULL) { + krb5_kt_end_seq_get(context, id, &cursor); + ret = ENOMEM; + goto out; + } p->keytab = entry; ret = krb5_crypto_init(context, &p->keytab.keyblock, 0, &p->crypto); p->next = *mkey; diff --git a/source4/heimdal/lib/hx509/ca.c b/source4/heimdal/lib/hx509/ca.c index bf8fe1be1a4..40260700b3f 100644 --- a/source4/heimdal/lib/hx509/ca.c +++ b/source4/heimdal/lib/hx509/ca.c @@ -33,7 +33,13 @@ #include "hx_locl.h" #include <pkinit_asn1.h> -RCSID("$Id: ca.c 21379 2007-06-28 07:38:17Z lha $"); +RCSID("$Id: ca.c 22456 2008-01-15 20:22:53Z lha $"); + +/** + * @page page_ca Hx509 CA functions + * + * See the library functions here: @ref hx509_ca + */ struct hx509_ca_tbs { hx509_name subject; @@ -55,6 +61,19 @@ struct hx509_ca_tbs { CRLDistributionPoints crldp; }; +/** + * Allocate an to-be-signed certificate object that will be converted + * into an certificate. + * + * @param context A hx509 context. + * @param tbs returned to-be-signed certicate object, free with + * hx509_ca_tbs_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs) { @@ -74,6 +93,14 @@ hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs) return 0; } +/** + * Free an To Be Signed object. + * + * @param tbs object to free. + * + * @ingroup hx509_ca + */ + void hx509_ca_tbs_free(hx509_ca_tbs *tbs) { @@ -93,6 +120,19 @@ hx509_ca_tbs_free(hx509_ca_tbs *tbs) *tbs = NULL; } +/** + * Set the absolute time when the certificate is valid from. If not + * set the current time will be used. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param t time the certificated will start to be valid + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_set_notBefore(hx509_context context, hx509_ca_tbs tbs, @@ -102,6 +142,18 @@ hx509_ca_tbs_set_notBefore(hx509_context context, return 0; } +/** + * Set the absolute time when the certificate is valid to. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param t time when the certificate will expire + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_set_notAfter(hx509_context context, hx509_ca_tbs tbs, @@ -111,6 +163,18 @@ hx509_ca_tbs_set_notAfter(hx509_context context, return 0; } +/** + * Set the relative time when the certificiate is going to expire. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param delta seconds to the certificate is going to expire. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_set_notAfter_lifetime(hx509_context context, hx509_ca_tbs tbs, @@ -130,12 +194,35 @@ static const struct units templatebits[] = { { NULL, 0 } }; +/** + * Make of template units, use to build flags argument to + * hx509_ca_tbs_set_template() with parse_units(). + * + * @return an units structure. + * + * @ingroup hx509_ca + */ + const struct units * hx509_ca_tbs_template_units(void) { return templatebits; } +/** + * Initialize the to-be-signed certificate object from a template certifiate. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param flags bit field selecting what to copy from the template + * certifiate. + * @param cert template certificate. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_set_template(hx509_context context, hx509_ca_tbs tbs, @@ -170,12 +257,10 @@ hx509_ca_tbs_set_template(hx509_context context, tbs->notAfter = hx509_cert_get_notAfter(cert); if (flags & HX509_CA_TEMPLATE_SPKI) { free_SubjectPublicKeyInfo(&tbs->spki); - ret = hx509_cert_get_SPKI(cert, &tbs->spki); + ret = hx509_cert_get_SPKI(context, cert, &tbs->spki); tbs->flags.key = !ret; - if (ret) { - hx509_set_error_string(context, 0, ret, "Failed to copy SPKI"); + if (ret) return ret; - } } if (flags & HX509_CA_TEMPLATE_KU) { KeyUsage ku; @@ -202,6 +287,20 @@ hx509_ca_tbs_set_template(hx509_context context, return 0; } +/** + * Make the to-be-signed certificate object a CA certificate. If the + * pathLenConstraint is negative path length constraint is used. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param pathLenConstraint path length constraint, negative, no + * constraint. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_set_ca(hx509_context context, hx509_ca_tbs tbs, @@ -212,6 +311,20 @@ hx509_ca_tbs_set_ca(hx509_context context, return 0; } +/** + * Make the to-be-signed certificate object a proxy certificate. If the + * pathLenConstraint is negative path length constraint is used. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param pathLenConstraint path length constraint, negative, no + * constraint. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_set_proxy(hx509_context context, hx509_ca_tbs tbs, @@ -223,6 +336,17 @@ hx509_ca_tbs_set_proxy(hx509_context context, } +/** + * Make the to-be-signed certificate object a windows domain controller certificate. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_set_domaincontroller(hx509_context context, hx509_ca_tbs tbs) @@ -231,6 +355,20 @@ hx509_ca_tbs_set_domaincontroller(hx509_context context, return 0; } +/** + * Set the subject public key info (SPKI) in the to-be-signed certificate + * object. SPKI is the public key and key related parameters in the + * certificate. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param spki subject public key info to use for the to-be-signed certificate object. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_set_spki(hx509_context context, hx509_ca_tbs tbs, @@ -243,6 +381,19 @@ hx509_ca_tbs_set_spki(hx509_context context, return ret; } +/** + * Set the serial number to use for to-be-signed certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param serialNumber serial number to use for the to-be-signed + * certificate object. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_set_serialnumber(hx509_context context, hx509_ca_tbs tbs, @@ -255,6 +406,19 @@ hx509_ca_tbs_set_serialnumber(hx509_context context, return ret; } +/** + * An an extended key usage to the to-be-signed certificate object. + * Duplicates will detected and not added. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param oid extended key usage to add. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_add_eku(hx509_context context, hx509_ca_tbs tbs, @@ -285,6 +449,20 @@ hx509_ca_tbs_add_eku(hx509_context context, return 0; } +/** + * Add CRL distribution point URI to the to-be-signed certificate + * object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param uri uri to the CRL. + * @param issuername name of the issuer. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_add_crl_dp_uri(hx509_context context, hx509_ca_tbs tbs, @@ -325,6 +503,9 @@ hx509_ca_tbs_add_crl_dp_uri(hx509_context context, if (issuername) { #if 1 + /** + * issuername not supported + */ hx509_set_error_string(context, 0, EINVAL, "CRLDistributionPoints.name.issuername not yet supported"); return EINVAL; @@ -372,6 +553,20 @@ out: return ret; } +/** + * Add Subject Alternative Name otherName to the to-be-signed + * certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param oid the oid of the OtherName. + * @param os data in the other name. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_add_san_otherName(hx509_context context, hx509_ca_tbs tbs, @@ -388,6 +583,18 @@ hx509_ca_tbs_add_san_otherName(hx509_context context, return add_GeneralNames(&tbs->san, &gn); } +/** + * Add Kerberos Subject Alternative Name to the to-be-signed + * certificate object. The principal string is a UTF8 string. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param principal Kerberos principal to add to the certificate. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ int hx509_ca_tbs_add_san_pkinit(hx509_context context, @@ -511,6 +718,19 @@ out: return ret; } +/** + * Add Microsoft UPN Subject Alternative Name to the to-be-signed + * certificate object. The principal string is a UTF8 string. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param principal Microsoft UPN string. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_add_san_ms_upn(hx509_context context, hx509_ca_tbs tbs, @@ -519,6 +739,19 @@ hx509_ca_tbs_add_san_ms_upn(hx509_context context, return add_utf8_san(context, tbs, oid_id_pkinit_ms_san(), principal); } +/** + * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed + * certificate object. The jid is an UTF8 string. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param jid string of an a jabber id in UTF8. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_add_san_jid(hx509_context context, hx509_ca_tbs tbs, @@ -528,6 +761,22 @@ hx509_ca_tbs_add_san_jid(hx509_context context, } +/** + * Add a Subject Alternative Name hostname to to-be-signed certificate + * object. A domain match starts with ., an exact match does not. + * + * Example of a an domain match: .domain.se matches the hostname + * host.domain.se. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param dnsname a hostame. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_add_san_hostname(hx509_context context, hx509_ca_tbs tbs, @@ -542,6 +791,19 @@ hx509_ca_tbs_add_san_hostname(hx509_context context, return add_GeneralNames(&tbs->san, &gn); } +/** + * Add a Subject Alternative Name rfc822 (email address) to + * to-be-signed certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param rfc822Name a string to a email address. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_add_san_rfc822name(hx509_context context, hx509_ca_tbs tbs, @@ -556,6 +818,17 @@ hx509_ca_tbs_add_san_rfc822name(hx509_context context, return add_GeneralNames(&tbs->san, &gn); } +/** + * Set the subject name of a to-be-signed certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param subject the name to set a subject. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ int hx509_ca_tbs_set_subject(hx509_context context, @@ -567,6 +840,20 @@ hx509_ca_tbs_set_subject(hx509_context context, return hx509_name_copy(context, subject, &tbs->subject); } +/** + * Expand the the subject name in the to-be-signed certificate object + * using hx509_name_expand(). + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param env enviroment variable to expand variables in the subject + * name, see hx509_env_init(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_tbs_subject_expand(hx509_context context, hx509_ca_tbs tbs, @@ -1148,6 +1435,30 @@ out: } +/** + * Sign a to-be-signed certificate object with a issuer certificate. + * + * The caller needs to at least have called the following functions on the + * to-be-signed certificate object: + * - hx509_ca_tbs_init() + * - hx509_ca_tbs_set_subject() + * - hx509_ca_tbs_set_spki() + * + * When done the to-be-signed certificate object should be freed with + * hx509_ca_tbs_free(). + * + * When creating self-signed certificate use hx509_ca_sign_self() instead. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param signer the CA certificate object to sign with (need private key). + * @param certificate return cerificate, free with hx509_cert_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_sign(hx509_context context, hx509_ca_tbs tbs, @@ -1179,6 +1490,19 @@ out: return ret; } +/** + * Work just like hx509_ca_sign() but signs it-self. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param signer private key to sign with. + * @param certificate return cerificate, free with hx509_cert_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + int hx509_ca_sign_self(hx509_context context, hx509_ca_tbs tbs, diff --git a/source4/heimdal/lib/hx509/cert.c b/source4/heimdal/lib/hx509/cert.c index b7f19d152a9..09c85bc0841 100644 --- a/source4/heimdal/lib/hx509/cert.c +++ b/source4/heimdal/lib/hx509/cert.c @@ -32,10 +32,25 @@ */ #include "hx_locl.h" -RCSID("$Id: cert.c 21380 2007-06-28 07:38:38Z lha $"); +RCSID("$Id: cert.c 22583 2008-02-11 20:46:21Z lha $"); #include "crypto-headers.h" #include <rtbl.h> +/** + * @page page_cert The basic certificate + * + * The basic hx509 cerificate object in hx509 is hx509_cert. The + * hx509_cert object is representing one X509/PKIX certificate and + * associated attributes; like private key, friendly name, etc. + * + * A hx509_cert object is usully found via the keyset interfaces (@ref + * page_keyset), but its also possible to create a certificate + * directly from a parsed object with hx509_cert_init() and + * hx509_cert_init_data(). + * + * See the library functions here: @ref hx509_cert + */ + struct hx509_verify_ctx_data { hx509_certs trust_anchors; int flags; @@ -78,8 +93,16 @@ typedef struct hx509_name_constraints { #define GeneralSubtrees_SET(g,var) \ (g)->len = (var)->len, (g)->val = (var)->val; -/* +/** + * Creates a hx509 context that most functions in the library + * uses. The context is only allowed to be used by one thread at each + * moment. Free the context with hx509_context_free(). * + * @param context Returns a pointer to new hx509 context. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509 */ int @@ -113,6 +136,19 @@ hx509_context_init(hx509_context *context) return 0; } +/** + * Selects if the hx509_revoke_verify() function is going to require + * the existans of a revokation method (OSCP, CRL) or not. Note that + * hx509_verify_path(), hx509_cms_verify_signed(), and other function + * call hx509_revoke_verify(). + * + * @param context hx509 context to change the flag for. + * @param flag zero, revokation method required, non zero missing + * revokation method ok + * + * @ingroup hx509_verify + */ + void hx509_context_set_missing_revoke(hx509_context context, int flag) { @@ -122,6 +158,14 @@ hx509_context_set_missing_revoke(hx509_context context, int flag) context->flags &= ~HX509_CTX_VERIFY_MISSING_OK; } +/** + * Free the context allocated by hx509_context_init(). + * + * @param context context to be freed. + * + * @ingroup hx509 + */ + void hx509_context_free(hx509_context *context) { @@ -139,7 +183,6 @@ hx509_context_free(hx509_context *context) *context = NULL; } - /* * */ @@ -154,39 +197,25 @@ _hx509_get_cert(hx509_cert cert) * */ -#if 0 -void -_hx509_print_cert_subject(hx509_cert cert) -{ - char *subject_name; - hx509_name name; - int ret; - - ret = hx509_cert_get_subject(cert, &name); - if (ret) - abort(); - - ret = hx509_name_to_string(name, &subject_name); - hx509_name_free(&name); - if (ret) - abort(); - - printf("name: %s\n", subject_name); - - free(subject_name); -} -#endif - -/* - * - */ - int _hx509_cert_get_version(const Certificate *t) { return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1; } +/** + * Allocate and init an hx509 certificate object from the decoded + * certificate `c´. + * + * @param context A hx509 context. + * @param c + * @param cert + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_cert + */ + int hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert) { @@ -218,9 +247,29 @@ hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert) return ret; } +/** + * Just like hx509_cert_init(), but instead of a decode certificate + * takes an pointer and length to a memory region that contains a + * DER/BER encoded certificate. + * + * If the memory region doesn't contain just the certificate and + * nothing more the function will fail with + * HX509_EXTRA_DATA_AFTER_STRUCTURE. + * + * @param context A hx509 context. + * @param ptr pointer to memory region containing encoded certificate. + * @param len length of memory region. + * @param cert a return pointer to a hx509 certificate object, will + * contain NULL on error. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_cert_init_data(hx509_context context, - const void *ptr, + const void *ptr, size_t len, hx509_cert *cert) { @@ -265,6 +314,15 @@ _hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key) return 0; } +/** + * Free reference to the hx509 certificate object, if the refcounter + * reaches 0, the object if freed. Its allowed to pass in NULL. + * + * @param cert the cert to free. + * + * @ingroup hx509_cert + */ + void hx509_cert_free(hx509_cert cert) { @@ -274,7 +332,7 @@ hx509_cert_free(hx509_cert cert) return; if (cert->ref <= 0) - _hx509_abort("refcount <= 0"); + _hx509_abort("cert refcount <= 0 on free"); if (--cert->ref > 0) return; @@ -300,9 +358,21 @@ hx509_cert_free(hx509_cert cert) free(cert); } +/** + * Add a reference to a hx509 certificate object. + * + * @param cert a pointer to an hx509 certificate object. + * + * @return the same object as is passed in. + * + * @ingroup hx509_cert + */ + hx509_cert hx509_cert_ref(hx509_cert cert) { + if (cert == NULL) + return NULL; if (cert->ref <= 0) _hx509_abort("cert refcount <= 0"); cert->ref++; @@ -311,6 +381,18 @@ hx509_cert_ref(hx509_cert cert) return cert; } +/** + * Allocate an verification context that is used fo control the + * verification process. + * + * @param context A hx509 context. + * @param ctx returns a pointer to a hx509_verify_ctx object. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + int hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx) { @@ -327,26 +409,75 @@ hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx) return 0; } +/** + * Free an hx509 verification context. + * + * @param ctx the context to be freed. + * + * @ingroup hx509_verify + */ + void hx509_verify_destroy_ctx(hx509_verify_ctx ctx) { - if (ctx) + if (ctx) { + hx509_certs_free(&ctx->trust_anchors); + hx509_revoke_free(&ctx->revoke_ctx); memset(ctx, 0, sizeof(*ctx)); + } free(ctx); } +/** + * Set the trust anchors in the verification context, makes an + * reference to the keyset, so the consumer can free the keyset + * independent of the destruction of the verification context (ctx). + * + * @param ctx a verification context + * @param set a keyset containing the trust anchors. + * + * @ingroup hx509_verify + */ + void hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set) { - ctx->trust_anchors = set; + ctx->trust_anchors = _hx509_certs_ref(set); } +/** + * Attach an revocation context to the verfication context, , makes an + * reference to the revoke context, so the consumer can free the + * revoke context independent of the destruction of the verification + * context. If there is no revoke context, the verification process is + * NOT going to check any verification status. + * + * @param ctx a verification context. + * @param revoke_ctx a revoke context. + * + * @ingroup hx509_verify + */ + void hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx) { - ctx->revoke_ctx = revoke_ctx; + if (ctx->revoke_ctx) + hx509_revoke_free(&ctx->revoke_ctx); + ctx->revoke_ctx = _hx509_revoke_ref(revoke_ctx); } +/** + * Set the clock time the the verification process is going to + * use. Used to check certificate in the past and future time. If not + * set the current time will be used. + * + * @param ctx a verification context. + * @param t the time the verifiation is using. + * + * + * @ingroup hx509_verify + */ + void hx509_verify_set_time(hx509_verify_ctx ctx, time_t t) { @@ -354,12 +485,32 @@ hx509_verify_set_time(hx509_verify_ctx ctx, time_t t) ctx->time_now = t; } +/** + * Set the maximum depth of the certificate chain that the path + * builder is going to try. + * + * @param ctx a verification context + * @param max_depth maxium depth of the certificate chain, include + * trust anchor. + * + * @ingroup hx509_verify + */ + void hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth) { ctx->max_depth = max_depth; } +/** + * Allow or deny the use of proxy certificates + * + * @param ctx a verification context + * @param boolean if non zero, allow proxy certificates. + * + * @ingroup hx509_verify + */ + void hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean) { @@ -369,6 +520,17 @@ hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean) ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE; } +/** + * Select strict RFC3280 verification of certificiates. This means + * checking key usage on CA certificates, this will make version 1 + * certificiates unuseable. + * + * @param ctx a verification context + * @param boolean if non zero, use strict verification. + * + * @ingroup hx509_verify + */ + void hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean) { @@ -378,6 +540,20 @@ hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean) ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280; } +/** + * Allow using the operating system builtin trust anchors if no other + * trust anchors are configured. + * + * @param ctx a verification context + * @param boolean if non zero, useing the operating systems builtin + * trust anchors. + * + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + void hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean) { @@ -512,6 +688,15 @@ add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry) return 0; } +/** + * Free a list of octet strings returned by another hx509 library + * function. + * + * @param list list to be freed. + * + * @ingroup hx509_misc + */ + void hx509_free_octet_string_list(hx509_octet_string_list *list) { @@ -523,8 +708,26 @@ hx509_free_octet_string_list(hx509_octet_string_list *list) list->len = 0; } +/** + * Return a list of subjectAltNames specified by oid in the + * certificate. On error the + * + * The returned list of octet string should be freed with + * hx509_free_octet_string_list(). + * + * @param context A hx509 context. + * @param cert a hx509 certificate object. + * @param oid an oid to for SubjectAltName. + * @param list list of matching SubjectAltName. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int -hx509_cert_find_subjectAltName_otherName(hx509_cert cert, +hx509_cert_find_subjectAltName_otherName(hx509_context context, + hx509_cert cert, const heim_oid *oid, hx509_octet_string_list *list) { @@ -541,9 +744,11 @@ hx509_cert_find_subjectAltName_otherName(hx509_cert cert, if (ret == HX509_EXTENSION_NOT_FOUND) { ret = 0; break; - } else if (ret != 0) - break; - + } else if (ret != 0) { + hx509_set_error_string(context, 0, ret, "Error searching for SAN"); + hx509_free_octet_string_list(list); + return ret; + } for (j = 0; j < sa.len; j++) { if (sa.val[j].element == choice_GeneralName_otherName && @@ -551,6 +756,10 @@ hx509_cert_find_subjectAltName_otherName(hx509_cert cert, { ret = add_to_list(list, &sa.val[j].u.otherName.value); if (ret) { + hx509_set_error_string(context, 0, ret, + "Error adding an exra SAN to " + "return list"); + hx509_free_octet_string_list(list); free_GeneralNames(&sa); return ret; } @@ -558,7 +767,7 @@ hx509_cert_find_subjectAltName_otherName(hx509_cert cert, } free_GeneralNames(&sa); } - return ret; + return 0; } @@ -605,6 +814,12 @@ check_key_usage(hx509_context context, const Certificate *cert, return 0; } +/* + * Return 0 on matching key usage 'flags' for 'cert', otherwise return + * an error code. If 'req_present' the existance is required of the + * KeyUsage extension. + */ + int _hx509_check_key_usage(hx509_context context, hx509_cert cert, unsigned flags, int req_present) @@ -678,10 +893,13 @@ _hx509_cert_is_parent_cmp(const Certificate *subject, int diff; AuthorityKeyIdentifier ai; SubjectKeyIdentifier si; - int ret_ai, ret_si; + int ret_ai, ret_si, ret; - diff = _hx509_name_cmp(&issuer->tbsCertificate.subject, - &subject->tbsCertificate.issuer); + ret = _hx509_name_cmp(&issuer->tbsCertificate.subject, + &subject->tbsCertificate.issuer, + &diff); + if (ret) + return ret; if (diff) return diff; @@ -689,7 +907,7 @@ _hx509_cert_is_parent_cmp(const Certificate *subject, memset(&si, 0, sizeof(si)); /* - * Try to find AuthorityKeyIdentifier, if its not present in the + * Try to find AuthorityKeyIdentifier, if it's not present in the * subject certificate nor the parent. */ @@ -736,8 +954,11 @@ _hx509_cert_is_parent_cmp(const Certificate *subject, name.u.rdnSequence = ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence; - diff = _hx509_name_cmp(&issuer->tbsCertificate.subject, - &name); + ret = _hx509_name_cmp(&issuer->tbsCertificate.subject, + &name, + &diff); + if (ret) + return ret; if (diff) return diff; diff = 0; @@ -776,13 +997,22 @@ certificate_is_anchor(hx509_context context, } static int -certificate_is_self_signed(const Certificate *cert) -{ - return _hx509_cert_is_parent_cmp(cert, cert, 1) == 0; +certificate_is_self_signed(hx509_context context, + const Certificate *cert, + int *self_signed) +{ + int ret, diff; + ret = _hx509_name_cmp(&cert->tbsCertificate.subject, + &cert->tbsCertificate.issuer, &diff); + *self_signed = (diff == 0); + if (ret) + hx509_set_error_string(context, 0, ret, + "Failed to check if self signed"); + return ret; } /* - * The subjectName is "null" when its empty set of relative DBs. + * The subjectName is "null" when it's empty set of relative DBs. */ static int @@ -1032,9 +1262,9 @@ _hx509_calculate_path(hx509_context context, return 0; } -static int -AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p, - const AlgorithmIdentifier *q) +int +_hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p, + const AlgorithmIdentifier *q) { int diff; diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm); @@ -1061,8 +1291,8 @@ _hx509_Certificate_cmp(const Certificate *p, const Certificate *q) diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue); if (diff) return diff; - diff = AlgorithmIdentifier_cmp(&p->signatureAlgorithm, - &q->signatureAlgorithm); + diff = _hx509_AlgorithmIdentifier_cmp(&p->signatureAlgorithm, + &q->signatureAlgorithm); if (diff) return diff; diff = der_heim_octet_string_cmp(&p->tbsCertificate._save, @@ -1070,24 +1300,77 @@ _hx509_Certificate_cmp(const Certificate *p, const Certificate *q) return diff; } +/** + * Compare to hx509 certificate object, useful for sorting. + * + * @param p a hx509 certificate object. + * @param q a hx509 certificate object. + * + * @return 0 the objects are the same, returns > 0 is p is "larger" + * then q, < 0 if p is "smaller" then q. + * + * @ingroup hx509_cert + */ + int hx509_cert_cmp(hx509_cert p, hx509_cert q) { return _hx509_Certificate_cmp(p->data, q->data); } +/** + * Return the name of the issuer of the hx509 certificate. + * + * @param p a hx509 certificate object. + * @param name a pointer to a hx509 name, should be freed by + * hx509_name_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_cert_get_issuer(hx509_cert p, hx509_name *name) { return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name); } +/** + * Return the name of the subject of the hx509 certificate. + * + * @param p a hx509 certificate object. + * @param name a pointer to a hx509 name, should be freed by + * hx509_name_free(). See also hx509_cert_get_base_subject(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_cert_get_subject(hx509_cert p, hx509_name *name) { return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name); } +/** + * Return the name of the base subject of the hx509 certificate. If + * the certiicate is a verified proxy certificate, the this function + * return the base certificate (root of the proxy chain). If the proxy + * certificate is not verified with the base certificate + * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned. + * + * @param context a hx509 context. + * @param c a hx509 certificate object. + * @param name a pointer to a hx509 name, should be freed by + * hx509_name_free(). See also hx509_cert_get_subject(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_cert_get_base_subject(hx509_context context, hx509_cert c, hx509_name *name) @@ -1104,31 +1387,107 @@ hx509_cert_get_base_subject(hx509_context context, hx509_cert c, return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name); } +/** + * Get serial number of the certificate. + * + * @param p a hx509 certificate object. + * @param i serial number, should be freed ith der_free_heim_integer(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i) { return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i); } +/** + * Get notBefore time of the certificate. + * + * @param p a hx509 certificate object. + * + * @return return not before time + * + * @ingroup hx509_cert + */ + time_t hx509_cert_get_notBefore(hx509_cert p) { return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore); } +/** + * Get notAfter time of the certificate. + * + * @param p a hx509 certificate object. + * + * @return return not after time. + * + * @ingroup hx509_cert + */ + time_t hx509_cert_get_notAfter(hx509_cert p) { return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter); } +/** + * Get the SubjectPublicKeyInfo structure from the hx509 certificate. + * + * @param context a hx509 context. + * @param p a hx509 certificate object. + * @param spki SubjectPublicKeyInfo, should be freed with + * free_SubjectPublicKeyInfo(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +int +hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *spki) +{ + int ret; + + ret = copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, spki); + if (ret) + hx509_set_error_string(context, 0, ret, "Failed to copy SPKI"); + return ret; +} + +/** + * Get the AlgorithmIdentifier from the hx509 certificate. + * + * @param context a hx509 context. + * @param p a hx509 certificate object. + * @param alg AlgorithmIdentifier, should be freed with + * free_AlgorithmIdentifier(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int -hx509_cert_get_SPKI(hx509_cert p, SubjectPublicKeyInfo *spki) +hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context, + hx509_cert p, + AlgorithmIdentifier *alg) { - return copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, - spki); + int ret; + + ret = copy_AlgorithmIdentifier(&p->data->tbsCertificate.subjectPublicKeyInfo.algorithm, alg); + if (ret) + hx509_set_error_string(context, 0, ret, + "Failed to copy SPKI AlgorithmIdentifier"); + return ret; } + hx509_private_key _hx509_cert_private_key(hx509_cert p) { @@ -1136,6 +1495,13 @@ _hx509_cert_private_key(hx509_cert p) } int +hx509_cert_have_private_key(hx509_cert p) +{ + return p->private_key ? 1 : 0; +} + + +int _hx509_cert_private_key_exportable(hx509_cert p) { if (p->private_key == NULL) @@ -1253,9 +1619,14 @@ match_RDN(const RelativeDistinguishedName *c, return HX509_NAME_CONSTRAINT_ERROR; for (i = 0; i < n->len; i++) { + int diff, ret; + if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0) return HX509_NAME_CONSTRAINT_ERROR; - if (_hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value) != 0) + ret = _hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value, &diff); + if (ret) + return ret; + if (diff != 0) return HX509_NAME_CONSTRAINT_ERROR; } return 0; @@ -1316,7 +1687,7 @@ match_general_name(const GeneralName *c, const GeneralName *n, int *match) return HX509_NAME_CONSTRAINT_ERROR; if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 0) return HX509_NAME_CONSTRAINT_ERROR; - if (len1 < len2 && s[len2 - len1] != '.') + if (len1 < len2 && s[len2 - len1 + 1] != '.') return HX509_NAME_CONSTRAINT_ERROR; } *match = 1; @@ -1387,7 +1758,6 @@ match_alt_name(const GeneralName *n, const Certificate *c, } free_GeneralNames(&sa); } while (1); - return ret; } @@ -1457,7 +1827,10 @@ check_name_constraints(hx509_context context, } /* allow null subjectNames, they wont matches anything */ if (match == 0 && !subject_null_p(c)) { - hx509_clear_error_string(context); + hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS, + "Error verify constraints, " + "certificate didn't match any " + "permitted subtree"); return HX509_VERIFY_CONSTRAINTS; } } @@ -1469,7 +1842,10 @@ check_name_constraints(hx509_context context, return ret; } if (match) { - hx509_clear_error_string(context); + hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS, + "Error verify constraints, " + "certificate included in excluded " + "subtree"); return HX509_VERIFY_CONSTRAINTS; } } @@ -1487,6 +1863,21 @@ free_name_constraints(hx509_name_constraints *nc) free(nc->val); } +/** + * Build and verify the path for the certificate to the trust anchor + * specified in the verify context. The path is constructed from the + * certificate, the pool and the trust anchors. + * + * @param context A hx509 context. + * @param ctx A hx509 verification context. + * @param cert the certificate to build the path from. + * @param pool A keyset of certificates to build the chain from. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + int hx509_verify_path(hx509_context context, hx509_verify_ctx ctx, @@ -1495,10 +1886,7 @@ hx509_verify_path(hx509_context context, { hx509_name_constraints nc; hx509_path path; -#if 0 - const AlgorithmIdentifier *alg_id; -#endif - int ret, i, proxy_cert_depth; + int ret, i, proxy_cert_depth, selfsigned_depth, diff; enum certtype type; Name proxy_issuer; hx509_certs anchors = NULL; @@ -1538,10 +1926,6 @@ hx509_verify_path(hx509_context context, if (ret) goto out; -#if 0 - alg_id = path.val[path->len - 1]->data->tbsCertificate.signature; -#endif - /* * Check CA and proxy certificate chain from the top of the * certificate chain. Also check certificate is valid with respect @@ -1550,6 +1934,7 @@ hx509_verify_path(hx509_context context, */ proxy_cert_depth = 0; + selfsigned_depth = 0; if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE) type = PROXY_CERT; @@ -1570,6 +1955,7 @@ hx509_verify_path(hx509_context context, switch (type) { case CA_CERT: + /* XXX make constants for keyusage */ ret = check_key_usage(context, c, 1 << 5, REQUIRE_RFC3280(ctx) ? TRUE : FALSE); @@ -1578,6 +1964,18 @@ hx509_verify_path(hx509_context context, "Key usage missing from CA certificate"); goto out; } + + /* self signed cert doesn't add to path length */ + if (i + 1 != path.len) { + int selfsigned; + + ret = certificate_is_self_signed(context, c, &selfsigned); + if (ret) + goto out; + if (selfsigned) + selfsigned_depth++; + } + break; case PROXY_CERT: { ProxyCertInfo info; @@ -1624,8 +2022,12 @@ hx509_verify_path(hx509_context context, */ if (proxy_cert_depth) { - ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject); + ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject, &diff); if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (diff) { ret = HX509_PROXY_CERT_NAME_WRONG; hx509_set_error_string(context, 0, ret, "Base proxy name not right"); @@ -1658,8 +2060,12 @@ hx509_verify_path(hx509_context context, free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]); proxy_issuer.u.rdnSequence.len -= 1; - ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer); - if (ret != 0) { + ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer, &diff); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (diff != 0) { ret = HX509_PROXY_CERT_NAME_WRONG; hx509_set_error_string(context, 0, ret, "Proxy issuer name not as expected"); @@ -1685,9 +2091,13 @@ hx509_verify_path(hx509_context context, */ if (proxy_cert_depth) { - ret = _hx509_name_cmp(&proxy_issuer, - &c->tbsCertificate.subject); + ret = _hx509_name_cmp(&proxy_issuer, + &c->tbsCertificate.subject, &diff); if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + if (diff) { ret = HX509_PROXY_CERT_NAME_WRONG; hx509_clear_error_string(context); goto out; @@ -1705,7 +2115,8 @@ hx509_verify_path(hx509_context context, break; } - ret = check_basic_constraints(context, c, type, i - proxy_cert_depth); + ret = check_basic_constraints(context, c, type, + i - proxy_cert_depth - selfsigned_depth); if (ret) goto out; @@ -1742,22 +2153,16 @@ hx509_verify_path(hx509_context context, for (ret = 0, i = path.len - 1; i >= 0; i--) { Certificate *c; + int selfsigned; c = _hx509_get_cert(path.val[i]); -#if 0 - /* check that algorithm and parameters is the same */ - /* XXX this is wrong */ - ret = alg_cmp(&c->tbsCertificate.signature, alg_id); - if (ret) { - hx509_clear_error_string(context); - ret = HX509_PATH_ALGORITHM_CHANGED; + ret = certificate_is_self_signed(context, c, &selfsigned); + if (ret) goto out; - } -#endif /* verify name constraints, not for selfsigned and anchor */ - if (!certificate_is_self_signed(c) || i == path.len - 1) { + if (!selfsigned || i + 1 != path.len) { ret = check_name_constraints(context, &nc, c); if (ret) { goto out; @@ -1813,12 +2218,6 @@ hx509_verify_path(hx509_context context, hx509_certs_free(&certs); } -#if 0 - for (i = path.len - 1; i >= 0; i--) { - _hx509_print_cert_subject(path.val[i]); - } -#endif - /* * Verify signatures, do this backward so public key working * parameter is passed up from the anchor up though the chain. @@ -1830,11 +2229,17 @@ hx509_verify_path(hx509_context context, c = _hx509_get_cert(path.val[i]); /* is last in chain (trust anchor) */ - if (i == path.len - 1) { + if (i + 1 == path.len) { + int selfsigned; + signer = path.val[i]->data; + ret = certificate_is_self_signed(context, signer, &selfsigned); + if (ret) + goto out; + /* if trust anchor is not self signed, don't check sig */ - if (!certificate_is_self_signed(signer)) + if (!selfsigned) continue; } else { /* take next certificate in chain */ @@ -1863,6 +2268,20 @@ out: return ret; } +/** + * Verify a signature made using the private key of an certificate. + * + * @param context A hx509 context. + * @param signer the certificate that made the signature. + * @param alg algorthm that was used to sign the data. + * @param data the data that was signed. + * @param sig the sigature to verify. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_crypto + */ + int hx509_verify_signature(hx509_context context, const hx509_cert signer, @@ -1873,7 +2292,26 @@ hx509_verify_signature(hx509_context context, return _hx509_verify_signature(context, signer->data, alg, data, sig); } -#define HX509_VHN_F_ALLOW_NO_MATCH 1 + +/** + * Verify that the certificate is allowed to be used for the hostname + * and address. + * + * @param context A hx509 context. + * @param cert the certificate to match with + * @param flags Flags to modify the behavior: + * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok + * @param type type of hostname: + * - HX509_HN_HOSTNAME for plain hostname. + * - HX509_HN_DNSSRV for DNS SRV names. + * @param hostname the hostname to check + * @param sa address of the host + * @param sa_size length of address + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ int hx509_verify_hostname(hx509_context context, @@ -1984,6 +2422,19 @@ _hx509_set_cert_attribute(hx509_context context, return 0; } +/** + * Get an external attribute for the certificate, examples are + * friendly name and id. + * + * @param cert hx509 certificate object to search + * @param oid an oid to search for. + * + * @return an hx509_cert_attribute, only valid as long as the + * certificate is referenced. + * + * @ingroup hx509_cert + */ + hx509_cert_attribute hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid) { @@ -1994,6 +2445,17 @@ hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid) return NULL; } +/** + * Set the friendly name on the certificate. + * + * @param cert The certificate to set the friendly name on + * @param name Friendly name. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_cert_set_friendly_name(hx509_cert cert, const char *name) { @@ -2005,6 +2467,16 @@ hx509_cert_set_friendly_name(hx509_cert cert, const char *name) return 0; } +/** + * Get friendly name of the certificate. + * + * @param cert cert to get the friendly name from. + * + * @return an friendly name or NULL if there is. The friendly name is + * only valid as long as the certificate is referenced. + * + * @ingroup hx509_cert + */ const char * hx509_cert_get_friendly_name(hx509_cert cert) @@ -2056,6 +2528,17 @@ _hx509_query_clear(hx509_query *q) memset(q, 0, sizeof(*q)); } +/** + * Allocate an query controller. Free using hx509_query_free(). + * + * @param context A hx509 context. + * @param q return pointer to a hx509_query. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_query_alloc(hx509_context context, hx509_query **q) { @@ -2065,6 +2548,17 @@ hx509_query_alloc(hx509_context context, hx509_query **q) return 0; } +/** + * Set match options for the hx509 query controller. + * + * @param q query controller. + * @param option options to control the query controller. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + void hx509_query_match_option(hx509_query *q, hx509_query_option option) { @@ -2087,6 +2581,19 @@ hx509_query_match_option(hx509_query *q, hx509_query_option option) } } +/** + * Set the issuer and serial number of match in the query + * controller. The function make copies of the isser and serial number. + * + * @param q a hx509 query controller + * @param issuer issuer to search for + * @param serialNumber the serialNumber of the issuer. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_query_match_issuer_serial(hx509_query *q, const Name *issuer, @@ -2123,6 +2630,16 @@ hx509_query_match_issuer_serial(hx509_query *q, return 0; } +/** + * Set the query controller to match on a friendly name + * + * @param q a hx509 query controller. + * @param name a friendly name to match on + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ int hx509_query_match_friendly_name(hx509_query *q, const char *name) @@ -2136,6 +2653,63 @@ hx509_query_match_friendly_name(hx509_query *q, const char *name) return 0; } +/** + * Set the query controller to require an one specific EKU (extended + * key usage). Any previous EKU matching is overwitten. If NULL is + * passed in as the eku, the EKU requirement is reset. + * + * @param q a hx509 query controller. + * @param eku an EKU to match on. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +int +hx509_query_match_eku(hx509_query *q, const heim_oid *eku) +{ + int ret; + + if (eku == NULL) { + if (q->eku) { + der_free_oid(q->eku); + free(q->eku); + q->eku = NULL; + } + q->match &= ~HX509_QUERY_MATCH_EKU; + } else { + if (q->eku) { + der_free_oid(q->eku); + } else { + q->eku = calloc(1, sizeof(*q->eku)); + if (q->eku == NULL) + return ENOMEM; + } + ret = der_copy_oid(eku, q->eku); + if (ret) { + free(q->eku); + q->eku = NULL; + return ret; + } + q->match |= HX509_QUERY_MATCH_EKU; + } + return 0; +} + +/** + * Set the query controller to match using a specific match function. + * + * @param q a hx509 query controller. + * @param func function to use for matching, if the argument is NULL, + * the match function is removed. + * @param ctx context passed to the function. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_query_match_cmp_func(hx509_query *q, int (*func)(void *, hx509_cert), @@ -2150,24 +2724,36 @@ hx509_query_match_cmp_func(hx509_query *q, return 0; } +/** + * Free the query controller. + * + * @param context A hx509 context. + * @param q a pointer to the query controller. + * + * @ingroup hx509_cert + */ void hx509_query_free(hx509_context context, hx509_query *q) { + if (q == NULL) + return; + if (q->serial) { der_free_heim_integer(q->serial); free(q->serial); - q->serial = NULL; } if (q->issuer_name) { free_Name(q->issuer_name); free(q->issuer_name); - q->issuer_name = NULL; } - if (q) { - free(q->friendlyname); - memset(q, 0, sizeof(*q)); + if (q->eku) { + der_free_oid(q->eku); + free(q->eku); } + if (q->friendlyname) + free(q->friendlyname); + memset(q, 0, sizeof(*q)); free(q); } @@ -2175,6 +2761,7 @@ int _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert) { Certificate *c = _hx509_get_cert(cert); + int ret, diff; _hx509_query_statistic(context, 1, q); @@ -2190,17 +2777,20 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0) return 0; - if ((q->match & HX509_QUERY_MATCH_ISSUER_NAME) - && _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name) != 0) - return 0; + if (q->match & HX509_QUERY_MATCH_ISSUER_NAME) { + ret = _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name, &diff); + if (ret || diff) + return 0; + } - if ((q->match & HX509_QUERY_MATCH_SUBJECT_NAME) - && _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name) != 0) - return 0; + if (q->match & HX509_QUERY_MATCH_SUBJECT_NAME) { + ret = _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name, &diff); + if (ret || diff) + return 0; + } if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) { SubjectKeyIdentifier si; - int ret; ret = _hx509_find_extension_subject_key_id(c, &si); if (ret == 0) { @@ -2264,14 +2854,13 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert return 0; } if (q->match & HX509_QUERY_MATCH_FUNCTION) { - int ret = (*q->cmp_func)(q->cmp_func_ctx, cert); + ret = (*q->cmp_func)(q->cmp_func_ctx, cert); if (ret != 0) return 0; } if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) { heim_octet_string os; - int ret; os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; os.length = @@ -2296,12 +2885,26 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert return 0; } + /* If an EKU is required, check the cert for it. */ + if ((q->match & HX509_QUERY_MATCH_EKU) && + hx509_cert_check_eku(context, cert, q->eku, 0)) + return 0; + if (q->match & ~HX509_QUERY_MASK) return 0; return 1; } +/** + * Set a statistic file for the query statistics. + * + * @param context A hx509 context. + * @param fn statistics file name + * + * @ingroup hx509_cert + */ + void hx509_query_statistic_file(hx509_context context, const char *fn) { @@ -2362,6 +2965,16 @@ stat_sort(const void *a, const void *b) return be->stats - ae->stats; } +/** + * Unparse the statistics file and print the result on a FILE descriptor. + * + * @param context A hx509 context. + * @param printtype tyep to print + * @param out the FILE to write the data on. + * + * @ingroup hx509_cert + */ + void hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out) { @@ -2435,6 +3048,20 @@ hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out) multiqueries, totalqueries); } +/** + * Check the extended key usage on the hx509 certificate. + * + * @param context A hx509 context. + * @param cert A hx509 context. + * @param eku the EKU to check for + * @param allow_any_eku if the any EKU is set, allow that to be a + * substitute. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_cert_check_eku(hx509_context context, hx509_cert cert, const heim_oid *eku, int allow_any_eku) @@ -2511,6 +3138,19 @@ _hx509_cert_get_eku(hx509_context context, return 0; } +/** + * Encodes the hx509 certificate as a DER encode binary. + * + * @param context A hx509 context. + * @param c the certificate to encode. + * @param os the encode certificate, set to NULL, 0 on case of + * error. Free the returned structure with hx509_xfree(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + int hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os) { @@ -2522,8 +3162,11 @@ hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os) ASN1_MALLOC_ENCODE(Certificate, os->data, os->length, _hx509_get_cert(c), &size, ret); - if (ret) + if (ret) { + os->data = NULL; + os->length = 0; return ret; + } if (os->length != size) _hx509_abort("internal ASN.1 encoder error"); @@ -2550,3 +3193,16 @@ _hx509_abort(const char *fmt, ...) abort(); } +/** + * Free a data element allocated in the library. + * + * @param ptr data to be freed. + * + * @ingroup hx509_misc + */ + +void +hx509_xfree(void *ptr) +{ + free(ptr); +} diff --git a/source4/heimdal/lib/hx509/cms.c b/source4/heimdal/lib/hx509/cms.c index 30f364060d0..80bcaac6c98 100644 --- a/source4/heimdal/lib/hx509/cms.c +++ b/source4/heimdal/lib/hx509/cms.c @@ -32,11 +32,46 @@ */ #include "hx_locl.h" -RCSID("$Id: cms.c 21319 2007-06-25 19:46:52Z lha $"); +RCSID("$Id: cms.c 22327 2007-12-15 04:49:37Z lha $"); + +/** + * @page page_cms CMS/PKCS7 message functions. + * + * CMS is defined in RFC 3369 and is an continuation of the RSA Labs + * standard PKCS7. The basic messages in CMS is + * + * - SignedData + * Data signed with private key (RSA, DSA, ECDSA) or secret + * (symmetric) key + * - EnvelopedData + * Data encrypted with private key (RSA) + * - EncryptedData + * Data encrypted with secret (symmetric) key. + * - ContentInfo + * Wrapper structure including type and data. + * + * + * See the library functions here: @ref hx509_cms + */ #define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) #define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0) +/** + * Wrap data and oid in a ContentInfo and encode it. + * + * @param oid type of the content. + * @param buf data to be wrapped. If a NULL pointer is passed in, the + * optional content field in the ContentInfo is not going be filled + * in. + * @param res the encoded buffer, the result should be freed with + * der_free_octet_string(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_cms + */ + int hx509_cms_wrap_ContentInfo(const heim_oid *oid, const heim_octet_string *buf, @@ -52,18 +87,20 @@ hx509_cms_wrap_ContentInfo(const heim_oid *oid, ret = der_copy_oid(oid, &ci.contentType); if (ret) return ret; - ALLOC(ci.content, 1); - if (ci.content == NULL) { - free_ContentInfo(&ci); - return ENOMEM; - } - ci.content->data = malloc(buf->length); - if (ci.content->data == NULL) { - free_ContentInfo(&ci); - return ENOMEM; + if (buf) { + ALLOC(ci.content, 1); + if (ci.content == NULL) { + free_ContentInfo(&ci); + return ENOMEM; + } + ci.content->data = malloc(buf->length); + if (ci.content->data == NULL) { + free_ContentInfo(&ci); + return ENOMEM; + } + memcpy(ci.content->data, buf->data, buf->length); + ci.content->length = buf->length; } - memcpy(ci.content->data, buf->data, buf->length); - ci.content->length = buf->length; ASN1_MALLOC_ENCODE(ContentInfo, res->data, res->length, &ci, &size, ret); free_ContentInfo(&ci); @@ -75,6 +112,20 @@ hx509_cms_wrap_ContentInfo(const heim_oid *oid, return 0; } +/** + * Decode an ContentInfo and unwrap data and oid it. + * + * @param in the encoded buffer. + * @param oid type of the content. + * @param out data to be wrapped. + * @param have_data since the data is optional, this flags show dthe + * diffrence between no data and the zero length data. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_cms + */ + int hx509_cms_unwrap_ContentInfo(const heim_octet_string *in, heim_oid *oid, @@ -267,6 +318,27 @@ find_CMSIdentifier(hx509_context context, return 0; } +/** + * Decode and unencrypt EnvelopedData. + * + * Extract data and parameteres from from the EnvelopedData. Also + * supports using detached EnvelopedData. + * + * @param context A hx509 context. + * @param certs Certificate that can decrypt the EnvelopedData + * encryption key. + * @param flags HX509_CMS_UE flags to control the behavior. + * @param data pointer the structure the contains the DER/BER encoded + * EnvelopedData stucture. + * @param length length of the data that data point to. + * @param encryptedContent in case of detached signature, this + * contains the actual encrypted data, othersize its should be NULL. + * @param contentType output type oid, should be freed with der_free_oid(). + * @param content the data, free with der_free_octet_string(). + * + * @ingroup hx509_cms + */ + int hx509_cms_unenvelope(hx509_context context, hx509_certs certs, @@ -335,11 +407,6 @@ hx509_cms_unenvelope(hx509_context context, ri = &ed.recipientInfos.val[i]; - /* ret = search_keyset(ri, - * PRIVATE_KEY, - * ki->keyEncryptionAlgorithm.algorithm); - */ - ret = find_CMSIdentifier(context, &ri->rid, certs, &cert, HX509_QUERY_PRIVATE_KEY|findflags); if (ret) @@ -444,6 +511,29 @@ out: return ret; } +/** + * Encrypt end encode EnvelopedData. + * + * Encrypt and encode EnvelopedData. The data is encrypted with a + * random key and the the random key is encrypted with the + * certificates private key. This limits what private key type can be + * used to RSA. + * + * @param context A hx509 context. + * @param flags flags to control the behavior, no flags today + * @param cert Certificate to encrypt the EnvelopedData encryption key + * with. + * @param data pointer the data to encrypt. + * @param length length of the data that data point to. + * @param encryption_type Encryption cipher to use for the bulk data, + * use NULL to get default. + * @param contentType type of the data that is encrypted + * @param content the output of the function, + * free with der_free_octet_string(). + * + * @ingroup hx509_cms + */ + int hx509_cms_envelope_1(hx509_context context, int flags, @@ -637,13 +727,31 @@ find_attribute(const CMSAttributes *attr, const heim_oid *oid) return NULL; } +/** + * Decode SignedData and verify that the signature is correct. + * + * @param context A hx509 context. + * @param ctx a hx509 version context + * @param data + * @param length length of the data that data point to. + * @param signedContent + * @param pool certificate pool to build certificates paths. + * @param contentType free with der_free_oid() + * @param content the output of the function, free with + * der_free_octet_string(). + * @param signer_certs list of the cerficates used to sign this + * request, free with hx509_certs_free(). + * + * @ingroup hx509_cms + */ + int hx509_cms_verify_signed(hx509_context context, hx509_verify_ctx ctx, const void *data, size_t length, const heim_octet_string *signedContent, - hx509_certs store, + hx509_certs pool, heim_oid *contentType, heim_octet_string *content, hx509_certs *signer_certs) @@ -701,8 +809,8 @@ hx509_cms_verify_signed(hx509_context context, if (ret) goto out; - if (store) { - ret = hx509_certs_merge(context, certs, store); + if (pool) { + ret = hx509_certs_merge(context, certs, pool); if (ret) goto out; } @@ -946,6 +1054,29 @@ add_one_attribute(Attribute **attr, return 0; } +/** + * Decode SignedData and verify that the signature is correct. + * + * @param context A hx509 context. + * @param flags + * @param eContentType the type of the data. + * @param data data to sign + * @param length length of the data that data point to. + * @param digest_alg digest algorithm to use, use NULL to get the + * default or the peer determined algorithm. + * @param cert certificate to use for sign the data. + * @param peer info about the peer the message to send the message to, + * like what digest algorithm to use. + * @param anchors trust anchors that the client will use, used to + * polulate the certificates included in the message + * @param pool certificates to use in try to build the path to the + * trust anchors. + * @param signed_data the output of the function, free with + * der_free_octet_string(). + * + * @ingroup hx509_cms + */ + int hx509_cms_create_signed_1(hx509_context context, int flags, @@ -1050,7 +1181,7 @@ hx509_cms_create_signed_1(hx509_context context, } /* - * If its not pkcs7-data send signedAttributes + * If it isn't pkcs7-data send signedAttributes */ if (der_heim_oid_cmp(eContentType, oid_id_pkcs7_data()) != 0) { diff --git a/source4/heimdal/lib/hx509/crypto.c b/source4/heimdal/lib/hx509/crypto.c index d86300bd586..e0f00ad7b45 100644 --- a/source4/heimdal/lib/hx509/crypto.c +++ b/source4/heimdal/lib/hx509/crypto.c @@ -32,7 +32,7 @@ */ #include "hx_locl.h" -RCSID("$Id: crypto.c 21318 2007-06-25 19:46:32Z lha $"); +RCSID("$Id: crypto.c 22435 2008-01-14 20:53:56Z lha $"); struct hx509_crypto; @@ -64,6 +64,7 @@ struct hx509_private_key_ops { int (*generate_private_key)(hx509_context, struct hx509_generate_private_context *, hx509_private_key); + BIGNUM *(*get_internal)(hx509_context, hx509_private_key, const char *); int (*handle_alg)(const hx509_private_key, const AlgorithmIdentifier *, enum crypto_op_type); @@ -115,6 +116,9 @@ struct signature_alg { #define SIG_PUBLIC_SIG 0x200 #define SIG_SECRET 0x400 +#define RA_RSA_USES_DIGEST_INFO 0x1000000 + + int (*verify_signature)(hx509_context context, const struct signature_alg *, const Certificate *, @@ -248,43 +252,57 @@ rsa_verify_signature(hx509_context context, } if (retsize > tosize) _hx509_abort("internal rsa decryption failure: ret > tosize"); - ret = decode_DigestInfo(to, retsize, &di, &size); - free(to); - if (ret) { - goto out; - } - /* Check for extra data inside the sigature */ - if (size != retsize) { - ret = HX509_CRYPTO_SIG_INVALID_FORMAT; - hx509_set_error_string(context, 0, ret, "size from decryption mismatch"); - goto out; - } + if (sig_alg->flags & RA_RSA_USES_DIGEST_INFO) { - if (sig_alg->digest_oid && - der_heim_oid_cmp(&di.digestAlgorithm.algorithm, - (*sig_alg->digest_oid)()) != 0) - { - ret = HX509_CRYPTO_OID_MISMATCH; - hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch"); - goto out; - } + ret = decode_DigestInfo(to, retsize, &di, &size); + free(to); + if (ret) { + goto out; + } + + /* Check for extra data inside the sigature */ + if (size != retsize) { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "size from decryption mismatch"); + goto out; + } + + if (sig_alg->digest_oid && + der_heim_oid_cmp(&di.digestAlgorithm.algorithm, + (*sig_alg->digest_oid)()) != 0) + { + ret = HX509_CRYPTO_OID_MISMATCH; + hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch"); + goto out; + } + + /* verify that the parameters are NULL or the NULL-type */ + if (di.digestAlgorithm.parameters != NULL && + (di.digestAlgorithm.parameters->length != 2 || + memcmp(di.digestAlgorithm.parameters->data, "\x05\x00", 2) != 0)) + { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "Extra parameters inside RSA signature"); + goto out; + } - /* verify that the parameters are NULL or the NULL-type */ - if (di.digestAlgorithm.parameters != NULL && - (di.digestAlgorithm.parameters->length != 2 || - memcmp(di.digestAlgorithm.parameters->data, "\x05\x00", 2) != 0)) - { - ret = HX509_CRYPTO_SIG_INVALID_FORMAT; - hx509_set_error_string(context, 0, ret, "Extra parameters inside RSA signature"); - goto out; + ret = _hx509_verify_signature(context, + NULL, + &di.digestAlgorithm, + data, + &di.digest); + } else { + if (retsize != data->length || + memcmp(to, data->data, retsize) != 0) + { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "RSA Signature incorrect"); + goto out; + } + free(to); } - ret = _hx509_verify_signature(context, - NULL, - &di.digestAlgorithm, - data, - &di.digest); out: free_DigestInfo(&di); RSA_free(rsa); @@ -303,7 +321,6 @@ rsa_create_signature(hx509_context context, const AlgorithmIdentifier *digest_alg; heim_octet_string indata; const heim_oid *sig_oid; - DigestInfo di; size_t size; int ret; @@ -324,6 +341,8 @@ rsa_create_signature(hx509_context context, digest_alg = hx509_signature_sha1(); } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_rsaEncryption()) == 0) { digest_alg = hx509_signature_sha1(); + } else if (der_heim_oid_cmp(sig_oid, oid_id_heim_rsa_pkcs1_x509()) == 0) { + digest_alg = NULL; } else return HX509_ALG_NOT_SUPP; @@ -335,29 +354,34 @@ rsa_create_signature(hx509_context context, } } - memset(&di, 0, sizeof(di)); + if (digest_alg) { + DigestInfo di; + memset(&di, 0, sizeof(di)); - ret = _hx509_create_signature(context, - NULL, - digest_alg, - data, - &di.digestAlgorithm, - &di.digest); - if (ret) - return ret; - ASN1_MALLOC_ENCODE(DigestInfo, - indata.data, - indata.length, - &di, - &size, - ret); - free_DigestInfo(&di); - if (ret) { - hx509_set_error_string(context, 0, ret, "out of memory"); - return ret; + ret = _hx509_create_signature(context, + NULL, + digest_alg, + data, + &di.digestAlgorithm, + &di.digest); + if (ret) + return ret; + ASN1_MALLOC_ENCODE(DigestInfo, + indata.data, + indata.length, + &di, + &size, + ret); + free_DigestInfo(&di); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + return ret; + } + if (indata.length != size) + _hx509_abort("internal ASN.1 encoder error"); + } else { + indata = *data; } - if (indata.length != size) - _hx509_abort("internal ASN.1 encoder error"); sig->length = RSA_size(signer->private_key.rsa); sig->data = malloc(sig->length); @@ -371,7 +395,8 @@ rsa_create_signature(hx509_context context, sig->data, signer->private_key.rsa, RSA_PKCS1_PADDING); - der_free_octet_string(&indata); + if (indata.data != data->data) + der_free_octet_string(&indata); if (ret <= 0) { ret = HX509_CMS_FAILED_CREATE_SIGATURE; hx509_set_error_string(context, 0, ret, @@ -517,6 +542,18 @@ rsa_private_key_export(hx509_context context, return 0; } +static BIGNUM * +rsa_get_internal(hx509_context context, hx509_private_key key, const char *type) +{ + if (strcasecmp(type, "rsa-modulus") == 0) { + return BN_dup(key->private_key.rsa->n); + } else if (strcasecmp(type, "rsa-exponent") == 0) { + return BN_dup(key->private_key.rsa->e); + } else + return NULL; +} + + static hx509_private_key_ops rsa_private_key_ops = { "RSA PRIVATE KEY", @@ -524,7 +561,8 @@ static hx509_private_key_ops rsa_private_key_ops = { rsa_private_key2SPKI, rsa_private_key_export, rsa_private_key_import, - rsa_generate_private_key + rsa_generate_private_key, + rsa_get_internal }; @@ -833,13 +871,24 @@ md2_verify_signature(hx509_context context, return 0; } +static const struct signature_alg heim_rsa_pkcs1_x509 = { + "rsa-pkcs1-x509", + oid_id_heim_rsa_pkcs1_x509, + hx509_signature_rsa_pkcs1_x509, + oid_id_pkcs1_rsaEncryption, + NULL, + PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, + rsa_verify_signature, + rsa_create_signature +}; + static const struct signature_alg pkcs1_rsa_sha1_alg = { "rsa", oid_id_pkcs1_rsaEncryption, hx509_signature_rsa_with_sha1, oid_id_pkcs1_rsaEncryption, NULL, - PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, rsa_verify_signature, rsa_create_signature }; @@ -850,7 +899,7 @@ static const struct signature_alg rsa_with_sha256_alg = { hx509_signature_rsa_with_sha256, oid_id_pkcs1_rsaEncryption, oid_id_sha256, - PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, rsa_verify_signature, rsa_create_signature }; @@ -861,7 +910,7 @@ static const struct signature_alg rsa_with_sha1_alg = { hx509_signature_rsa_with_sha1, oid_id_pkcs1_rsaEncryption, oid_id_secsig_sha_1, - PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, rsa_verify_signature, rsa_create_signature }; @@ -872,7 +921,7 @@ static const struct signature_alg rsa_with_md5_alg = { hx509_signature_rsa_with_md5, oid_id_pkcs1_rsaEncryption, oid_id_rsa_digest_md5, - PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, rsa_verify_signature, rsa_create_signature }; @@ -883,7 +932,7 @@ static const struct signature_alg rsa_with_md2_alg = { hx509_signature_rsa_with_md2, oid_id_pkcs1_rsaEncryption, oid_id_rsa_digest_md2, - PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, rsa_verify_signature, rsa_create_signature }; @@ -952,7 +1001,7 @@ static const struct signature_alg *sig_algs[] = { &pkcs1_rsa_sha1_alg, &rsa_with_md5_alg, &rsa_with_md2_alg, - &pkcs1_rsa_sha1_alg, + &heim_rsa_pkcs1_x509, &dsa_sha1_alg, &sha256_alg, &sha1_alg, @@ -1423,6 +1472,11 @@ const AlgorithmIdentifier _hx509_signature_rsa_data = { { 7, rk_UNCONST(rsa_oid) }, NULL }; +static const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 }; +const AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = { + { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL +}; + static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 }; const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = { { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL @@ -1491,6 +1545,10 @@ hx509_signature_rsa(void) { return &_hx509_signature_rsa_data; } const AlgorithmIdentifier * +hx509_signature_rsa_pkcs1_x509(void) +{ return &_hx509_signature_rsa_pkcs1_x509_data; } + +const AlgorithmIdentifier * hx509_crypto_des_rsdi_ede3_cbc(void) { return &_hx509_des_rsdi_ede3_cbc_oid; } @@ -1597,6 +1655,16 @@ _hx509_private_key_exportable(hx509_private_key key) return 1; } +BIGNUM * +_hx509_private_key_get_internal(hx509_context context, + hx509_private_key key, + const char *type) +{ + if (key->ops->get_internal == NULL) + return NULL; + return (*key->ops->get_internal)(context, key, type); +} + int _hx509_private_key_export(hx509_context context, const hx509_private_key key, diff --git a/source4/heimdal/lib/hx509/env.c b/source4/heimdal/lib/hx509/env.c index 4cb2f9f4b17..f868c22488c 100644 --- a/source4/heimdal/lib/hx509/env.c +++ b/source4/heimdal/lib/hx509/env.c @@ -32,7 +32,13 @@ */ #include "hx_locl.h" -RCSID("$Id: env.c 19878 2007-01-13 00:58:39Z lha $"); +RCSID("$Id: env.c 22349 2007-12-26 19:32:49Z lha $"); + +/** + * @page page_env Hx509 enviroment functions + * + * See the library functions here: @ref hx509_env + */ struct hx509_env { struct { @@ -42,6 +48,17 @@ struct hx509_env { size_t len; }; +/** + * Allocate a new hx509_env container object. + * + * @param context A hx509 context. + * @param env return a hx509_env structure, free with hx509_env_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_env + */ + int hx509_env_init(hx509_context context, hx509_env *env) { @@ -53,6 +70,19 @@ hx509_env_init(hx509_context context, hx509_env *env) return 0; } +/** + * Add a new key/value pair to the hx509_env. + * + * @param context A hx509 context. + * @param env enviroment to add the enviroment variable too. + * @param key key to add + * @param value value to add + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_env + */ + int hx509_env_add(hx509_context context, hx509_env env, const char *key, const char *value) @@ -80,6 +110,19 @@ hx509_env_add(hx509_context context, hx509_env env, return 0; } +/** + * Search the hx509_env for a key. + * + * @param context A hx509 context. + * @param env enviroment to add the enviroment variable too. + * @param key key to search for. + * @param len length of key. + * + * @return the value if the key is found, NULL otherwise. + * + * @ingroup hx509_env + */ + const char * hx509_env_lfind(hx509_context context, hx509_env env, const char *key, size_t len) @@ -94,6 +137,13 @@ hx509_env_lfind(hx509_context context, hx509_env env, return NULL; } +/** + * Free an hx509_env enviroment context. + * + * @param env the enviroment to free. + * + * @ingroup hx509_env + */ void hx509_env_free(hx509_env *env) diff --git a/source4/heimdal/lib/hx509/error.c b/source4/heimdal/lib/hx509/error.c index 9f3a0148732..25119ed2883 100644 --- a/source4/heimdal/lib/hx509/error.c +++ b/source4/heimdal/lib/hx509/error.c @@ -32,7 +32,13 @@ */ #include "hx_locl.h" -RCSID("$Id: error.c 20912 2007-06-05 03:53:52Z lha $"); +RCSID("$Id: error.c 22332 2007-12-17 01:03:22Z lha $"); + +/** + * @page page_error Hx509 error reporting functions + * + * See the library functions here: @ref hx509_error + */ struct hx509_error_data { hx509_error next; @@ -51,6 +57,14 @@ free_error_string(hx509_error msg) } } +/** + * Resets the error strings the hx509 context. + * + * @param context A hx509 context. + * + * @ingroup hx509_error + */ + void hx509_clear_error_string(hx509_context context) { @@ -58,6 +72,20 @@ hx509_clear_error_string(hx509_context context) context->error = NULL; } +/** + * Add an error message to the hx509 context. + * + * @param context A hx509 context. + * @param flags + * - HX509_ERROR_APPEND appends the error string to the old messages + (code is updated). + * @param code error code related to error message + * @param fmt error message format + * @param ap arguments to error message format + * + * @ingroup hx509_error + */ + void hx509_set_error_stringv(hx509_context context, int flags, int code, const char *fmt, va_list ap) @@ -86,6 +114,20 @@ hx509_set_error_stringv(hx509_context context, int flags, int code, } } +/** + * See hx509_set_error_stringv(). + * + * @param context A hx509 context. + * @param flags + * - HX509_ERROR_APPEND appends the error string to the old messages + (code is updated). + * @param code error code related to error message + * @param fmt error message format + * @param ... arguments to error message format + * + * @ingroup hx509_error + */ + void hx509_set_error_string(hx509_context context, int flags, int code, const char *fmt, ...) @@ -97,6 +139,17 @@ hx509_set_error_string(hx509_context context, int flags, int code, va_end(ap); } +/** + * Get an error string from context associated with error_code. + * + * @param context A hx509 context. + * @param error_code Get error message for this error code. + * + * @return error string, free with hx509_free_error_string(). + * + * @ingroup hx509_error + */ + char * hx509_get_error_string(hx509_context context, int error_code) { @@ -125,6 +178,32 @@ hx509_get_error_string(hx509_context context, int error_code) return rk_strpoolcollect(p); } +/** + * Free error string returned by hx509_get_error_string(). + * + * @param str error string to free. + * + * @ingroup hx509_error + */ + +void +hx509_free_error_string(char *str) +{ + free(str); +} + +/** + * Print error message and fatally exit from error code + * + * @param context A hx509 context. + * @param exit_code exit() code from process. + * @param error_code Error code for the reason to exit. + * @param fmt format string with the exit message. + * @param ... argument to format string. + * + * @ingroup hx509_error + */ + void hx509_err(hx509_context context, int exit_code, int error_code, const char *fmt, ...) diff --git a/source4/heimdal/lib/hx509/hx509-private.h b/source4/heimdal/lib/hx509/hx509-private.h index acbc3218c64..be36c07421e 100644 --- a/source4/heimdal/lib/hx509/hx509-private.h +++ b/source4/heimdal/lib/hx509/hx509-private.h @@ -9,6 +9,11 @@ #endif int +_hx509_AlgorithmIdentifier_cmp ( + const AlgorithmIdentifier */*p*/, + const AlgorithmIdentifier */*q*/); + +int _hx509_Certificate_cmp ( const Certificate */*p*/, const Certificate */*q*/); @@ -269,12 +274,14 @@ _hx509_match_keys ( int _hx509_name_cmp ( const Name */*n1*/, - const Name */*n2*/); + const Name */*n2*/, + int */*c*/); int _hx509_name_ds_cmp ( const DirectoryString */*ds1*/, - const DirectoryString */*ds2*/); + const DirectoryString */*ds2*/, + int */*diff*/); int _hx509_name_from_Name ( @@ -314,6 +321,14 @@ _hx509_pbe_decrypt ( const heim_octet_string */*econtent*/, heim_octet_string */*content*/); +int +_hx509_pbe_encrypt ( + hx509_context /*context*/, + hx509_lock /*lock*/, + const AlgorithmIdentifier */*ai*/, + const heim_octet_string */*content*/, + heim_octet_string */*econtent*/); + void _hx509_pi_printf ( int (*/*func*/)(void *, const char *), @@ -344,6 +359,12 @@ _hx509_private_key_exportable (hx509_private_key /*key*/); int _hx509_private_key_free (hx509_private_key */*key*/); +BIGNUM * +_hx509_private_key_get_internal ( + hx509_context /*context*/, + hx509_private_key /*key*/, + const char */*type*/); + int _hx509_private_key_init ( hx509_private_key */*key*/, @@ -415,11 +436,35 @@ void _hx509_request_free (hx509_request */*req*/); int +_hx509_request_get_SubjectPublicKeyInfo ( + hx509_context /*context*/, + hx509_request /*req*/, + SubjectPublicKeyInfo */*key*/); + +int +_hx509_request_get_name ( + hx509_context /*context*/, + hx509_request /*req*/, + hx509_name */*name*/); + +int _hx509_request_init ( hx509_context /*context*/, hx509_request */*req*/); int +_hx509_request_parse ( + hx509_context /*context*/, + const char */*path*/, + hx509_request */*req*/); + +int +_hx509_request_print ( + hx509_context /*context*/, + hx509_request /*req*/, + FILE */*f*/); + +int _hx509_request_set_SubjectPublicKeyInfo ( hx509_context /*context*/, hx509_request /*req*/, @@ -438,6 +483,9 @@ _hx509_request_to_pkcs10 ( const hx509_private_key /*signer*/, heim_octet_string */*request*/); +hx509_revoke_ctx +_hx509_revoke_ref (hx509_revoke_ctx /*ctx*/); + int _hx509_set_cert_attribute ( hx509_context /*context*/, diff --git a/source4/heimdal/lib/hx509/hx509-protos.h b/source4/heimdal/lib/hx509/hx509-protos.h index 71fb29d59dd..3e297424cc9 100644 --- a/source4/heimdal/lib/hx509/hx509-protos.h +++ b/source4/heimdal/lib/hx509/hx509-protos.h @@ -183,6 +183,7 @@ hx509_cert_cmp ( int hx509_cert_find_subjectAltName_otherName ( + hx509_context /*context*/, hx509_cert /*cert*/, const heim_oid */*oid*/, hx509_octet_string_list */*list*/); @@ -192,9 +193,16 @@ hx509_cert_free (hx509_cert /*cert*/); int hx509_cert_get_SPKI ( + hx509_context /*context*/, hx509_cert /*p*/, SubjectPublicKeyInfo */*spki*/); +int +hx509_cert_get_SPKI_AlgorithmIdentifier ( + hx509_context /*context*/, + hx509_cert /*p*/, + AlgorithmIdentifier */*alg*/); + hx509_cert_attribute hx509_cert_get_attribute ( hx509_cert /*cert*/, @@ -231,6 +239,9 @@ hx509_cert_get_subject ( hx509_name */*name*/); int +hx509_cert_have_private_key (hx509_cert /*p*/); + +int hx509_cert_init ( hx509_context /*context*/, const Certificate */*c*/, @@ -305,7 +316,7 @@ int hx509_certs_iter ( hx509_context /*context*/, hx509_certs /*certs*/, - int (*/*fn*/)(hx509_context, void *, hx509_cert), + int (*/*func*/)(hx509_context, void *, hx509_cert), void */*ctx*/); int @@ -402,7 +413,7 @@ hx509_cms_verify_signed ( const void */*data*/, size_t /*length*/, const heim_octet_string */*signedContent*/, - hx509_certs /*store*/, + hx509_certs /*pool*/, heim_oid */*contentType*/, heim_octet_string */*content*/, hx509_certs */*signer_certs*/); @@ -581,6 +592,9 @@ hx509_err ( ...); void +hx509_free_error_string (char */*str*/); + +void hx509_free_octet_string_list (hx509_octet_string_list */*list*/); int @@ -652,6 +666,11 @@ hx509_lock_set_prompter ( void */*data*/); int +hx509_name_binary ( + const hx509_name /*name*/, + heim_octet_string */*os*/); + +int hx509_name_cmp ( hx509_name /*n1*/, hx509_name /*n2*/); @@ -685,12 +704,6 @@ hx509_name_to_Name ( Name */*to*/); int -hx509_name_to_der_name ( - const hx509_name /*name*/, - void **/*data*/, - size_t */*length*/); - -int hx509_name_to_string ( const hx509_name /*name*/, char **/*str*/); @@ -783,13 +796,6 @@ hx509_pem_write ( size_t /*size*/); void -hx509_print_func ( - hx509_vprint_func /*func*/, - void */*ctx*/, - const char */*fmt*/, - ...); - -void hx509_print_stdout ( void */*ctx*/, const char */*fmt*/, @@ -815,6 +821,11 @@ hx509_query_match_cmp_func ( void */*ctx*/); int +hx509_query_match_eku ( + hx509_query */*q*/, + const heim_oid */*eku*/); + +int hx509_query_match_friendly_name ( hx509_query */*q*/, const char */*name*/); @@ -902,6 +913,9 @@ const AlgorithmIdentifier * hx509_signature_rsa (void); const AlgorithmIdentifier * +hx509_signature_rsa_pkcs1_x509 (void); + +const AlgorithmIdentifier * hx509_signature_rsa_with_md2 (void); const AlgorithmIdentifier * @@ -1030,6 +1044,9 @@ hx509_verify_signature ( const heim_octet_string */*data*/, const heim_octet_string */*sig*/); +void +hx509_xfree (void */*ptr*/); + #ifdef __cplusplus } #endif diff --git a/source4/heimdal/lib/hx509/hx509.h b/source4/heimdal/lib/hx509/hx509.h index 2f22cedfbc8..be02f634749 100644 --- a/source4/heimdal/lib/hx509/hx509.h +++ b/source4/heimdal/lib/hx509/hx509.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: hx509.h 21310 2007-06-25 18:26:06Z lha $ */ +/* $Id: hx509.h 22464 2008-01-16 14:24:50Z lha $ */ typedef struct hx509_cert_attribute_data *hx509_cert_attribute; typedef struct hx509_cert_data *hx509_cert; @@ -56,6 +56,10 @@ typedef struct hx509_crl *hx509_crl; typedef void (*hx509_vprint_func)(void *, const char *, va_list); enum { + HX509_VHN_F_ALLOW_NO_MATCH = 1 +}; + +enum { HX509_VALIDATE_F_VALIDATE = 1, HX509_VALIDATE_F_VERBOSE = 2 }; @@ -107,6 +111,7 @@ typedef enum { /* flags to hx509_certs_init */ #define HX509_CERTS_CREATE 0x01 +#define HX509_CERTS_UNPROTECT_ALL 0x02 /* flags to hx509_set_error_string */ #define HX509_ERROR_APPEND 0x01 diff --git a/source4/heimdal/lib/hx509/hx509_err.et b/source4/heimdal/lib/hx509/hx509_err.et index 90f3b3d907d..8fc5cb8f2f7 100644 --- a/source4/heimdal/lib/hx509/hx509_err.et +++ b/source4/heimdal/lib/hx509/hx509_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: hx509_err.et 20807 2007-06-03 03:11:20Z lha $" +id "$Id: hx509_err.et 22329 2007-12-15 05:13:14Z lha $" error_table hx prefix HX509 @@ -72,7 +72,7 @@ prefix HX509 error_code CRL_USED_BEFORE_TIME, "CRL used before it became valid" error_code CRL_USED_AFTER_TIME, "CRL used after it became invalid" error_code CRL_INVALID_FORMAT, "CRL have invalid format" -error_code CRL_CERT_REVOKED, "Certificate is included in CRL" +error_code CERT_REVOKED, "Certificate is revoked" error_code REVOKE_STATUS_MISSING, "No revoke status found for certificates" error_code CRL_UNKNOWN_EXTENSION, "Unknown extension" error_code REVOKE_WRONG_DATA, "Got wrong CRL/OCSP data from server" diff --git a/source4/heimdal/lib/hx509/hx_locl.h b/source4/heimdal/lib/hx509/hx_locl.h index 145bfcc006d..6d89167bfcb 100644 --- a/source4/heimdal/lib/hx509/hx_locl.h +++ b/source4/heimdal/lib/hx509/hx_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: hx_locl.h 21083 2007-06-13 02:11:19Z lha $ */ +/* $Id: hx_locl.h 22538 2008-01-27 13:05:47Z lha $ */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -128,7 +128,8 @@ struct hx509_query_data { #define HX509_QUERY_MATCH_FUNCTION 0x080000 #define HX509_QUERY_MATCH_KEY_HASH_SHA1 0x100000 #define HX509_QUERY_MATCH_TIME 0x200000 -#define HX509_QUERY_MASK 0x3fffff +#define HX509_QUERY_MATCH_EKU 0x400000 +#define HX509_QUERY_MASK 0x7fffff Certificate *subject; Certificate *certificate; heim_integer *serial; @@ -142,6 +143,7 @@ struct hx509_query_data { void *cmp_func_ctx; heim_octet_string *keyhash_sha1; time_t timenow; + heim_oid *eku; }; struct hx509_keyset_ops { diff --git a/source4/heimdal/lib/hx509/keyset.c b/source4/heimdal/lib/hx509/keyset.c index 7da5705a802..2fcff7b03b3 100644 --- a/source4/heimdal/lib/hx509/keyset.c +++ b/source4/heimdal/lib/hx509/keyset.c @@ -32,7 +32,31 @@ */ #include "hx_locl.h" -RCSID("$Id: keyset.c 21140 2007-06-18 21:24:19Z lha $"); +RCSID("$Id: keyset.c 22466 2008-01-16 14:26:35Z lha $"); + +/** + * @page page_keyset Certificate store operations + * + * Type of certificates store: + * - MEMORY + * In memory based format. Doesnt support storing. + * - FILE + * FILE supports raw DER certicates and PEM certicates. When PEM is + * used the file can contain may certificates and match private + * keys. Support storing the certificates. DER format only supports + * on certificate and no private key. + * - PEM-FILE + * Same as FILE, defaulting to PEM encoded certificates. + * - PEM-FILE + * Same as FILE, defaulting to DER encoded certificates. + * - PKCS11 + * - PKCS12 + * - DIR + * - KEYCHAIN + * Apple Mac OS X KeyChain backed keychain object. + * + * See the library functions here: @ref hx509_keyset + */ struct hx509_certs_data { int ref; @@ -69,6 +93,22 @@ _hx509_ks_register(hx509_context context, struct hx509_keyset_ops *ops) context->ks_num_ops++; } +/** + * Open or creates a new hx509 certificate store. + * + * @param context A hx509 context + * @param name name of the store, format is TYPE:type-specific-string, + * if NULL is used the MEMORY store is used. + * @param flags list of flags: + * - HX509_CERTS_CREATE create a new keystore of the specific TYPE. + * - HX509_CERTS_UNPROTECT_ALL fails if any private key failed to be extracted. + * @param lock a lock that unlocks the certificates store, use NULL to + * select no password/certifictes/prompt lock (see @ref page_lock). + * @param certs return pointer, free with hx509_certs_free(). + * + * @ingroup hx509_keyset + */ + int hx509_certs_init(hx509_context context, const char *name, int flags, @@ -125,6 +165,21 @@ hx509_certs_init(hx509_context context, return 0; } +/** + * Write the certificate store to stable storage. + * + * @param context A hx509 context. + * @param certs a certificate store to store. + * @param flags currently unused, use 0. + * @param lock a lock that unlocks the certificates store, use NULL to + * select no password/certifictes/prompt lock (see @ref page_lock). + * + * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION if + * the certificate store doesn't support the store operation. + * + * @ingroup hx509_keyset + */ + int hx509_certs_store(hx509_context context, hx509_certs certs, @@ -132,11 +187,11 @@ hx509_certs_store(hx509_context context, hx509_lock lock) { if (certs->ops->store == NULL) { - hx509_set_error_string(context, 0, EINVAL, + hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, "keystore if type %s doesn't support " "store operation", certs->ops->name); - return EINVAL; + return HX509_UNSUPPORTED_OPERATION; } return (*certs->ops->store)(context, certs, certs->ops_data, flags, lock); @@ -146,6 +201,8 @@ hx509_certs_store(hx509_context context, hx509_certs _hx509_certs_ref(hx509_certs certs) { + if (certs == NULL) + return NULL; if (certs->ref <= 0) _hx509_abort("certs refcount <= 0"); certs->ref++; @@ -154,6 +211,14 @@ _hx509_certs_ref(hx509_certs certs) return certs; } +/** + * Free a certificate store. + * + * @param certs certificate store to free. + * + * @ingroup hx509_keyset + */ + void hx509_certs_free(hx509_certs *certs) { @@ -169,6 +234,21 @@ hx509_certs_free(hx509_certs *certs) } } +/** + * Start the integration + * + * @param context a hx509 context. + * @param certs certificate store to iterate over + * @param cursor cursor that will keep track of progress, free with + * hx509_certs_end_seq(). + * + * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION is + * returned if the certificate store doesn't support the iteration + * operation. + * + * @ingroup hx509_keyset + */ + int hx509_certs_start_seq(hx509_context context, hx509_certs certs, @@ -177,10 +257,10 @@ hx509_certs_start_seq(hx509_context context, int ret; if (certs->ops->iter_start == NULL) { - hx509_set_error_string(context, 0, ENOENT, + hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, "Keyset type %s doesn't support iteration", certs->ops->name); - return ENOENT; + return HX509_UNSUPPORTED_OPERATION; } ret = (*certs->ops->iter_start)(context, certs, certs->ops_data, cursor); @@ -190,6 +270,21 @@ hx509_certs_start_seq(hx509_context context, return 0; } +/** + * Get next ceritificate from the certificate keystore pointed out by + * cursor. + * + * @param context a hx509 context. + * @param certs certificate store to iterate over. + * @param cursor cursor that keeps track of progress. + * @param cert return certificate next in store, NULL if the store + * contains no more certificates. Free with hx509_cert_free(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + int hx509_certs_next_cert(hx509_context context, hx509_certs certs, @@ -200,6 +295,18 @@ hx509_certs_next_cert(hx509_context context, return (*certs->ops->iter)(context, certs, certs->ops_data, cursor, cert); } +/** + * End the iteration over certificates. + * + * @param context a hx509 context. + * @param certs certificate store to iterate over. + * @param cursor cursor that will keep track of progress, freed. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + int hx509_certs_end_seq(hx509_context context, hx509_certs certs, @@ -209,11 +316,26 @@ hx509_certs_end_seq(hx509_context context, return 0; } +/** + * Iterate over all certificates in a keystore and call an function + * for each fo them. + * + * @param context a hx509 context. + * @param certs certificate store to iterate over. + * @param func function to call for each certificate. The function + * should return non-zero to abort the iteration, that value is passed + * back to te caller of hx509_certs_iter(). + * @param ctx context variable that will passed to the function. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ int hx509_certs_iter(hx509_context context, hx509_certs certs, - int (*fn)(hx509_context, void *, hx509_cert), + int (*func)(hx509_context, void *, hx509_cert), void *ctx) { hx509_cursor cursor; @@ -232,7 +354,7 @@ hx509_certs_iter(hx509_context context, ret = 0; break; } - ret = (*fn)(context, ctx, c); + ret = (*func)(context, ctx, c); hx509_cert_free(c); if (ret) break; @@ -243,6 +365,20 @@ hx509_certs_iter(hx509_context context, return ret; } + +/** + * Function to use to hx509_certs_iter() as a function argument, the + * ctx variable to hx509_certs_iter() should be a FILE file descriptor. + * + * @param context a hx509 context. + * @param ctx used by hx509_certs_iter(). + * @param c a certificate + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + int hx509_ci_print_names(hx509_context context, void *ctx, hx509_cert c) { @@ -264,10 +400,20 @@ hx509_ci_print_names(hx509_context context, void *ctx, hx509_cert c) return 0; } -/* - * The receiving keyset `certs´ will either increase reference counter - * of the `cert´ or make a deep copy, either way, the caller needs to - * free the `cert´ itself. +/** + * Add a certificate to the certificiate store. + * + * The receiving keyset certs will either increase reference counter + * of the cert or make a deep copy, either way, the caller needs to + * free the cert itself. + * + * @param context a hx509 context. + * @param certs certificate store to add the certificate to. + * @param cert certificate to add. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset */ int @@ -283,6 +429,20 @@ hx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert) return (*certs->ops->add)(context, certs, certs->ops_data, cert); } +/** + * Find a certificate matching the query. + * + * @param context a hx509 context. + * @param certs certificate store to search. + * @param q query allocated with @ref hx509_query functions. + * @param r return certificate (or NULL on error), should be freed + * with hx509_cert_free(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + int hx509_certs_find(hx509_context context, hx509_certs certs, @@ -335,6 +495,19 @@ certs_merge_func(hx509_context context, void *ctx, hx509_cert c) return hx509_certs_add(context, (hx509_certs)ctx, c); } +/** + * Merge a certificate store into another. The from store is keep + * intact. + * + * @param context a hx509 context. + * @param to the store to merge into. + * @param from the store to copy the object from. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + int hx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from) { @@ -343,6 +516,21 @@ hx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from) return hx509_certs_iter(context, from, certs_merge_func, to); } +/** + * Same a hx509_certs_merge() but use a lock and name to describe the + * from source. + * + * @param context a hx509 context. + * @param to the store to merge into. + * @param lock a lock that unlocks the certificates store, use NULL to + * select no password/certifictes/prompt lock (see @ref page_lock). + * @param name name of the source store + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + int hx509_certs_append(hx509_context context, hx509_certs to, @@ -360,6 +548,18 @@ hx509_certs_append(hx509_context context, return ret; } +/** + * Get one random certificate from the certificate store. + * + * @param context a hx509 context. + * @param certs a certificate store to get the certificate from. + * @param c return certificate, should be freed with hx509_cert_free(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + int hx509_get_one_cert(hx509_context context, hx509_certs certs, hx509_cert *c) { @@ -388,6 +588,21 @@ certs_info_stdio(void *ctx, const char *str) return 0; } +/** + * Print some info about the certificate store. + * + * @param context a hx509 context. + * @param certs certificate store to print information about. + * @param func function that will get each line of the information, if + * NULL is used the data is printed on a FILE descriptor that should + * be passed in ctx, if ctx also is NULL, stdout is used. + * @param ctx parameter to func. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + int hx509_certs_info(hx509_context context, hx509_certs certs, diff --git a/source4/heimdal/lib/hx509/ks_file.c b/source4/heimdal/lib/hx509/ks_file.c index 269afd03b10..87b97af401c 100644 --- a/source4/heimdal/lib/hx509/ks_file.c +++ b/source4/heimdal/lib/hx509/ks_file.c @@ -32,7 +32,7 @@ */ #include "hx_locl.h" -RCSID("$Id: ks_file.c 21314 2007-06-25 18:45:07Z lha $"); +RCSID("$Id: ks_file.c 22465 2008-01-16 14:25:24Z lha $"); typedef enum { USE_PEM, USE_DER } outformat; @@ -289,19 +289,25 @@ struct pem_formats { }; +struct pem_ctx { + int flags; + struct hx509_collector *c; +}; + static int pem_func(hx509_context context, const char *type, const hx509_pem_header *header, const void *data, size_t len, void *ctx) { - struct hx509_collector *c = ctx; - int ret, j; + struct pem_ctx *pem_ctx = (struct pem_ctx*)ctx; + int ret = 0, j; for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) { const char *q = formats[j].name; if (strcasecmp(type, q) == 0) { - ret = (*formats[j].func)(context, NULL, c, header, data, len); - break; + ret = (*formats[j].func)(context, NULL, pem_ctx->c, header, data, len); + if (ret == 0) + break; } } if (j == sizeof(formats)/sizeof(formats[0])) { @@ -310,6 +316,8 @@ pem_func(hx509_context context, const char *type, "Found no matching PEM format for %s", type); return ret; } + if (ret && (pem_ctx->flags & HX509_CERTS_UNPROTECT_ALL)) + return ret; return 0; } @@ -324,9 +332,12 @@ file_init_common(hx509_context context, { char *p, *pnext; struct ks_file *f = NULL; - struct hx509_collector *c = NULL; hx509_private_key *keys = NULL; int ret; + struct pem_ctx pem_ctx; + + pem_ctx.flags = flags; + pem_ctx.c = NULL; *data = NULL; @@ -361,7 +372,7 @@ file_init_common(hx509_context context, return 0; } - ret = _hx509_collector_alloc(context, lock, &c); + ret = _hx509_collector_alloc(context, lock, &pem_ctx.c); if (ret) goto out; @@ -381,7 +392,7 @@ file_init_common(hx509_context context, goto out; } - ret = hx509_pem_read(context, f, pem_func, c); + ret = hx509_pem_read(context, f, pem_func, &pem_ctx); fclose(f); if (ret != 0 && ret != HX509_PARSING_KEY_FAILED) goto out; @@ -397,7 +408,7 @@ file_init_common(hx509_context context, } for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { - ret = (*formats[i].func)(context, p, c, NULL, ptr, length); + ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length); if (ret == 0) break; } @@ -407,11 +418,11 @@ file_init_common(hx509_context context, } } - ret = _hx509_collector_collect_certs(context, c, &f->certs); + ret = _hx509_collector_collect_certs(context, pem_ctx.c, &f->certs); if (ret) goto out; - ret = _hx509_collector_collect_private_keys(context, c, &keys); + ret = _hx509_collector_collect_private_keys(context, pem_ctx.c, &keys); if (ret == 0) { int i; @@ -428,8 +439,9 @@ out: free(f->fn); free(f); } - if (c) - _hx509_collector_free(c); + if (pem_ctx.c) + _hx509_collector_free(pem_ctx.c); + return ret; } diff --git a/source4/heimdal/lib/hx509/ks_keychain.c b/source4/heimdal/lib/hx509/ks_keychain.c index 33c4d6774b3..f8181975d9d 100644 --- a/source4/heimdal/lib/hx509/ks_keychain.c +++ b/source4/heimdal/lib/hx509/ks_keychain.c @@ -32,17 +32,19 @@ */ #include "hx_locl.h" -RCSID("$Id: ks_keychain.c 21097 2007-06-16 07:00:49Z lha $"); +RCSID("$Id: ks_keychain.c 22084 2007-11-16 20:12:30Z lha $"); #ifdef HAVE_FRAMEWORK_SECURITY #include <Security/Security.h> -/* Missing function decls */ +/* Missing function decls in pre Leopard */ +#ifdef NEED_SECKEYGETCSPHANDLE_PROTO OSStatus SecKeyGetCSPHandle(SecKeyRef, CSSM_CSP_HANDLE *); OSStatus SecKeyGetCredentials(SecKeyRef, CSSM_ACL_AUTHORIZATION_TAG, int, const CSSM_ACCESS_CREDENTIALS **); #define kSecCredentialTypeDefault 0 +#endif static int @@ -50,7 +52,7 @@ getAttribute(SecKeychainItemRef itemRef, SecItemAttr item, SecKeychainAttributeList **attrs) { SecKeychainAttributeInfo attrInfo; - uint32 attrFormat = 0; + UInt32 attrFormat = 0; OSStatus ret; *attrs = NULL; @@ -408,7 +410,7 @@ keychain_iter(hx509_context context, { SecKeychainAttributeList *attrs = NULL; SecKeychainAttributeInfo attrInfo; - uint32 attrFormat[1] = { 0 }; + UInt32 attrFormat[1] = { 0 }; SecKeychainItemRef itemRef; SecItemAttr item[1]; struct iter *iter = cursor; diff --git a/source4/heimdal/lib/hx509/ks_p11.c b/source4/heimdal/lib/hx509/ks_p11.c index e3066bbcfac..0d7c312c724 100644 --- a/source4/heimdal/lib/hx509/ks_p11.c +++ b/source4/heimdal/lib/hx509/ks_p11.c @@ -32,7 +32,7 @@ */ #include "hx_locl.h" -RCSID("$Id: ks_p11.c 21387 2007-06-28 08:53:45Z lha $"); +RCSID("$Id: ks_p11.c 22071 2007-11-14 20:04:50Z lha $"); #ifdef HAVE_DLFCN_H #include <dlfcn.h> #endif @@ -403,7 +403,7 @@ p11_get_session(hx509_context context, * prompter or known to work pin code. * * This code is very conversative and only uses the prompter in - * the hx509_lock, the reason is that its bad to try many + * the hx509_lock, the reason is that it's bad to try many * passwords on a pkcs11 token, it might lock up and have to be * unlocked by a administrator. * diff --git a/source4/heimdal/lib/hx509/lock.c b/source4/heimdal/lib/hx509/lock.c index de326f2e2de..e835aee35af 100644 --- a/source4/heimdal/lib/hx509/lock.c +++ b/source4/heimdal/lib/hx509/lock.c @@ -32,7 +32,13 @@ */ #include "hx_locl.h" -RCSID("$Id: lock.c 18452 2006-10-14 09:41:05Z lha $"); +RCSID("$Id: lock.c 22327 2007-12-15 04:49:37Z lha $"); + +/** + * @page page_lock Locking and unlocking certificates and encrypted data. + * + * See the library functions here: @ref hx509_lock + */ struct hx509_lock_data { struct _hx509_password password; diff --git a/source4/heimdal/lib/hx509/name.c b/source4/heimdal/lib/hx509/name.c index 5198633b1e5..3f0806ddc01 100644 --- a/source4/heimdal/lib/hx509/name.c +++ b/source4/heimdal/lib/hx509/name.c @@ -32,17 +32,39 @@ */ #include "hx_locl.h" -RCSID("$Id: name.c 20891 2007-06-04 22:51:41Z lha $"); +#include <wind.h> +RCSID("$Id: name.c 22583 2008-02-11 20:46:21Z lha $"); -/* - * name parsing from rfc2253 - * fix so parsing rfc1779 works too - * rfc3280 +/** + * @page page_name PKIX/X.509 Names + * + * There are several names in PKIX/X.509, GeneralName and Name. + * + * A Name consists of an ordered list of Relative Distinguished Names + * (RDN). Each RDN consists of an unordered list of typed strings. The + * types are defined by OID and have long and short description. For + * example id-at-commonName (2.5.4.3) have the long name CommonName + * and short name CN. The string itself can be of serveral encoding, + * UTF8, UTF16, Teltex string, etc. The type limit what encoding + * should be used. + * + * GeneralName is a broader nametype that can contains al kind of + * stuff like Name, IP addresses, partial Name, etc. + * + * Name is mapped into a hx509_name object. + * + * Parse and string name into a hx509_name object with hx509_parse_name(), + * make it back into string representation with hx509_name_to_string(). + * + * Name string are defined rfc2253, rfc1779 and X.501. + * + * See the library functions here: @ref hx509_name */ static const struct { const char *n; const heim_oid *(*o)(void); + wind_profile_flags flags; } no[] = { { "C", oid_id_at_countryName }, { "CN", oid_id_at_commonName }, @@ -153,6 +175,18 @@ stringtooid(const char *name, size_t len, heim_oid *oid) return ret; } +/** + * Convert the hx509 name object into a printable string. + * The resulting string should be freed with free(). + * + * @param name name to print + * @param str the string to return + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + int hx509_name_to_string(const hx509_name name, char **str) { @@ -247,82 +281,185 @@ _hx509_Name_to_string(const Name *n, char **str) return 0; } -/* - * XXX this function is broken, it needs to compare code points, not - * bytes. - */ +#define COPYCHARARRAY(_ds,_el,_l,_n) \ + (_l) = strlen(_ds->u._el); \ + (_n) = malloc((_l) * sizeof((_n)[0])); \ + if ((_n) == NULL) \ + return ENOMEM; \ + for (i = 0; i < (_l); i++) \ + (_n)[i] = _ds->u._el[i] -int -_hx509_name_ds_cmp(const DirectoryString *ds1, const DirectoryString *ds2) + +#define COPYVALARRAY(_ds,_el,_l,_n) \ + (_l) = _ds->u._el.length; \ + (_n) = malloc((_l) * sizeof((_n)[0])); \ + if ((_n) == NULL) \ + return ENOMEM; \ + for (i = 0; i < (_l); i++) \ + (_n)[i] = _ds->u._el.data[i] + +#define COPYVOIDARRAY(_ds,_el,_l,_n) \ + (_l) = _ds->u._el.length; \ + (_n) = malloc((_l) * sizeof((_n)[0])); \ + if ((_n) == NULL) \ + return ENOMEM; \ + for (i = 0; i < (_l); i++) \ + (_n)[i] = ((unsigned char *)_ds->u._el.data)[i] + + + +static int +dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen) { - int c; + wind_profile_flags flags = 0; + size_t i, len; + int ret; + uint32_t *name; - c = ds1->element - ds2->element; - if (c) - return c; + *rname = NULL; + *rlen = 0; - switch(ds1->element) { + switch(ds->element) { case choice_DirectoryString_ia5String: - c = strcmp(ds1->u.ia5String, ds2->u.ia5String); - break; - case choice_DirectoryString_teletexString: - c = der_heim_octet_string_cmp(&ds1->u.teletexString, - &ds2->u.teletexString); + COPYCHARARRAY(ds, ia5String, len, name); break; case choice_DirectoryString_printableString: - c = strcasecmp(ds1->u.printableString, ds2->u.printableString); + flags = WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE; + COPYCHARARRAY(ds, printableString, len, name); break; - case choice_DirectoryString_utf8String: - c = strcmp(ds1->u.utf8String, ds2->u.utf8String); + case choice_DirectoryString_teletexString: + COPYVOIDARRAY(ds, teletexString, len, name); + break; + case choice_DirectoryString_bmpString: + COPYVALARRAY(ds, bmpString, len, name); break; case choice_DirectoryString_universalString: - c = der_heim_universal_string_cmp(&ds1->u.universalString, - &ds2->u.universalString); + COPYVALARRAY(ds, universalString, len, name); break; - case choice_DirectoryString_bmpString: - c = der_heim_bmp_string_cmp(&ds1->u.bmpString, - &ds2->u.bmpString); + case choice_DirectoryString_utf8String: + ret = wind_utf8ucs4_length(ds->u.utf8String, &len); + if (ret) + return ret; + name = malloc(len * sizeof(name[0])); + if (name == NULL) + return ENOMEM; + ret = wind_utf8ucs4(ds->u.utf8String, name, &len); + if (ret) + return ret; break; default: - c = 1; - break; + _hx509_abort("unknown directory type: %d", ds->element); + } + + *rlen = len; + /* try a couple of times to get the length right, XXX gross */ + for (i = 0; i < 4; i++) { + *rlen = *rlen * 2; + *rname = malloc(*rlen * sizeof((*rname)[0])); + + ret = wind_stringprep(name, len, *rname, rlen, + WIND_PROFILE_LDAP|flags); + if (ret == WIND_ERR_OVERRUN) { + free(*rname); + *rname = NULL; + continue; + } else + break; + } + free(name); + if (ret) { + if (*rname) + free(*rname); + *rname = NULL; + *rlen = 0; + return ret; + } + + return 0; +} + +int +_hx509_name_ds_cmp(const DirectoryString *ds1, + const DirectoryString *ds2, + int *diff) +{ + uint32_t *ds1lp, *ds2lp; + size_t ds1len, ds2len; + int ret; + + ret = dsstringprep(ds1, &ds1lp, &ds1len); + if (ret) + return ret; + ret = dsstringprep(ds2, &ds2lp, &ds2len); + if (ret) { + free(ds1lp); + return ret; } - return c; + + if (ds1len != ds2len) + *diff = ds1len - ds2len; + else + *diff = memcmp(ds1lp, ds2lp, ds1len * sizeof(ds1lp[0])); + + free(ds1lp); + free(ds2lp); + + return 0; } int -_hx509_name_cmp(const Name *n1, const Name *n2) +_hx509_name_cmp(const Name *n1, const Name *n2, int *c) { - int i, j, c; + int ret, i, j; - c = n1->u.rdnSequence.len - n2->u.rdnSequence.len; - if (c) - return c; + *c = n1->u.rdnSequence.len - n2->u.rdnSequence.len; + if (*c) + return 0; for (i = 0 ; i < n1->u.rdnSequence.len; i++) { - c = n1->u.rdnSequence.val[i].len - n2->u.rdnSequence.val[i].len; - if (c) - return c; + *c = n1->u.rdnSequence.val[i].len - n2->u.rdnSequence.val[i].len; + if (*c) + return 0; for (j = 0; j < n1->u.rdnSequence.val[i].len; j++) { - c = der_heim_oid_cmp(&n1->u.rdnSequence.val[i].val[j].type, - &n1->u.rdnSequence.val[i].val[j].type); - if (c) - return c; + *c = der_heim_oid_cmp(&n1->u.rdnSequence.val[i].val[j].type, + &n1->u.rdnSequence.val[i].val[j].type); + if (*c) + return 0; - c = _hx509_name_ds_cmp(&n1->u.rdnSequence.val[i].val[j].value, - &n2->u.rdnSequence.val[i].val[j].value); - if (c) - return c; + ret = _hx509_name_ds_cmp(&n1->u.rdnSequence.val[i].val[j].value, + &n2->u.rdnSequence.val[i].val[j].value, + c); + if (ret) + return ret; + if (*c) + return 0; } } + *c = 0; return 0; } +/** + * Compare to hx509 name object, useful for sorting. + * + * @param n1 a hx509 name object. + * @param n2 a hx509 name object. + * + * @return 0 the objects are the same, returns > 0 is n2 is "larger" + * then n2, < 0 if n1 is "smaller" then n2. + * + * @ingroup hx509_name + */ + int hx509_name_cmp(hx509_name n1, hx509_name n2) { - return _hx509_name_cmp(&n1->der_name, &n2->der_name); + int ret, diff; + ret = _hx509_name_cmp(&n1->der_name, &n2->der_name, &diff); + if (ret) + return ret; + return diff; } @@ -341,19 +478,6 @@ _hx509_name_from_Name(const Name *n, hx509_name *name) return ret; } -static int -hx509_der_parse_name(const void *data, size_t length, hx509_name *name) -{ - int ret; - Name n; - - *name = NULL; - ret = decode_Name(data, length, &n, NULL); - if (ret) - return ret; - return _hx509_name_from_Name(&n, name); -} - int _hx509_name_modify(hx509_context context, Name *name, @@ -400,6 +524,18 @@ _hx509_name_modify(hx509_context context, return 0; } +/** + * Parse a string into a hx509 name object. + * + * @param context A hx509 context. + * @param str a string to parse. + * @param name the resulting object, NULL in case of error. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + int hx509_parse_name(hx509_context context, const char *str, hx509_name *name) { @@ -492,6 +628,18 @@ out: return HX509_NAME_MALFORMED; } +/** + * Copy a hx509 name object. + * + * @param context A hx509 cotext. + * @param from the name to copy from + * @param to the name to copy to + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + int hx509_name_copy(hx509_context context, const hx509_name from, hx509_name *to) { @@ -509,6 +657,17 @@ hx509_name_copy(hx509_context context, const hx509_name from, hx509_name *to) return 0; } +/** + * Convert a hx509_name into a Name. + * + * @param from the name to copy from + * @param to the name to copy to + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + int hx509_name_to_Name(const hx509_name from, Name *to) { @@ -521,6 +680,19 @@ hx509_name_normalize(hx509_context context, hx509_name name) return 0; } +/** + * Expands variables in the name using env. Variables are on the form + * ${name}. Useful when dealing with certificate templates. + * + * @param context A hx509 cotext. + * @param name the name to expand. + * @param env environment variable to expand. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + int hx509_name_expand(hx509_context context, hx509_name name, @@ -539,6 +711,7 @@ hx509_name_expand(hx509_context context, for (i = 0 ; i < n->u.rdnSequence.len; i++) { for (j = 0; j < n->u.rdnSequence.val[i].len; j++) { + /** Only UTF8String rdnSequence names are allowed */ /* THIS SHOULD REALLY BE: COMP = n->u.rdnSequence.val[i].val[j]; @@ -615,6 +788,13 @@ hx509_name_expand(hx509_context context, return 0; } +/** + * Free a hx509 name object, upond return *name will be NULL. + * + * @param name a hx509 name object to be freed. + * + * @ingroup hx509_name + */ void hx509_name_free(hx509_name *name) @@ -625,37 +805,61 @@ hx509_name_free(hx509_name *name) *name = NULL; } +/** + * Convert a DER encoded name info a string. + * + * @param data data to a DER/BER encoded name + * @param length length of data + * @param str the resulting string, is NULL on failure. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + int hx509_unparse_der_name(const void *data, size_t length, char **str) { - hx509_name name; + Name name; int ret; - ret = hx509_der_parse_name(data, length, &name); + *str = NULL; + + ret = decode_Name(data, length, &name, NULL); if (ret) return ret; - - ret = hx509_name_to_string(name, str); - hx509_name_free(&name); + ret = _hx509_Name_to_string(&name, str); + free_Name(&name); return ret; } +/** + * Convert a hx509_name object to DER encoded name. + * + * @param name name to concert + * @param os data to a DER encoded name, free the resulting octet + * string with hx509_xfree(os->data). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + int -hx509_name_to_der_name(const hx509_name name, void **data, size_t *length) +hx509_name_binary(const hx509_name name, heim_octet_string *os) { size_t size; int ret; - ASN1_MALLOC_ENCODE(Name, *data, *length, &name->der_name, &size, ret); + ASN1_MALLOC_ENCODE(Name, os->data, os->length, &name->der_name, &size, ret); if (ret) return ret; - if (*length != size) + if (os->length != size) _hx509_abort("internal ASN.1 encoder error"); return 0; } - int _hx509_unparse_Name(const Name *aname, char **str) { @@ -671,12 +875,33 @@ _hx509_unparse_Name(const Name *aname, char **str) return ret; } +/** + * Unparse the hx509 name in name into a string. + * + * @param name the name to check if its empty/null. + * + * @return non zero if the name is empty/null. + * + * @ingroup hx509_name + */ + int hx509_name_is_null_p(const hx509_name name) { return name->der_name.u.rdnSequence.len == 0; } +/** + * Unparse the hx509 name in name into a string. + * + * @param name the name to print + * @param str an allocated string returns the name in string form + * + * @return An hx509 error code, see krb5_get_error_string(). + * + * @ingroup hx509_name + */ + int hx509_general_name_unparse(GeneralName *name, char **str) { diff --git a/source4/heimdal/lib/hx509/peer.c b/source4/heimdal/lib/hx509/peer.c index e90f8f34b06..eb0ecd2bdef 100644 --- a/source4/heimdal/lib/hx509/peer.c +++ b/source4/heimdal/lib/hx509/peer.c @@ -32,7 +32,27 @@ */ #include "hx_locl.h" -RCSID("$Id: peer.c 21481 2007-07-10 16:33:23Z lha $"); +RCSID("$Id: peer.c 22345 2007-12-26 19:03:51Z lha $"); + +/** + * @page page_peer Hx509 crypto selecting functions + * + * Peer info structures are used togeter with hx509_crypto_select() to + * select the best avaible crypto algorithm to use. + * + * See the library functions here: @ref hx509_peer + */ + +/** + * Allocate a new peer info structure an init it to default values. + * + * @param context A hx509 context. + * @param peer return an allocated peer, free with hx509_peer_info_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_peer + */ int hx509_peer_info_alloc(hx509_context context, hx509_peer_info *peer) @@ -59,6 +79,14 @@ free_cms_alg(hx509_peer_info peer) } } +/** + * Free a peer info structure. + * + * @param peer peer info to be freed. + * + * @ingroup hx509_peer + */ + void hx509_peer_info_free(hx509_peer_info peer) { @@ -71,6 +99,17 @@ hx509_peer_info_free(hx509_peer_info peer) free(peer); } +/** + * Set the certificate that remote peer is using. + * + * @param peer peer info to update + * @param cert cerificate of the remote peer. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_peer + */ + int hx509_peer_info_set_cert(hx509_peer_info peer, hx509_cert cert) @@ -81,6 +120,19 @@ hx509_peer_info_set_cert(hx509_peer_info peer, return 0; } +/** + * Set the algorithms that the peer supports. + * + * @param context A hx509 context. + * @param peer the peer to set the new algorithms for + * @param val array of supported AlgorithmsIdentiers + * @param len length of array val. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_peer + */ + int hx509_peer_info_set_cms_algs(hx509_context context, hx509_peer_info peer, diff --git a/source4/heimdal/lib/hx509/print.c b/source4/heimdal/lib/hx509/print.c index e6f71ea2ceb..c1594ff0476 100644 --- a/source4/heimdal/lib/hx509/print.c +++ b/source4/heimdal/lib/hx509/print.c @@ -32,8 +32,13 @@ */ #include "hx_locl.h" -RCSID("$Id: print.c 21381 2007-06-28 08:29:22Z lha $"); +RCSID("$Id: print.c 22538 2008-01-27 13:05:47Z lha $"); +/** + * @page page_print Hx509 printing functions + * + * See the library functions here: @ref hx509_print + */ struct hx509_validate_ctx_data { int flags; @@ -75,15 +80,31 @@ Time2string(const Time *T, char **str) return 0; } +/** + * Helper function to print on stdout for: + * - hx509_oid_print(), + * - hx509_bitstring_print(), + * - hx509_validate_ctx_set_print(). + * + * @param ctx the context to the print function. If the ctx is NULL, + * stdout is used. + * @param fmt the printing format. + * @param va the argumet list. + * + * @ingroup hx509_print + */ + void hx509_print_stdout(void *ctx, const char *fmt, va_list va) { FILE *f = ctx; + if (f == NULL) + f = stdout; vfprintf(f, fmt, va); } -void -hx509_print_func(hx509_vprint_func func, void *ctx, const char *fmt, ...) +static void +print_func(hx509_vprint_func func, void *ctx, const char *fmt, ...) { va_list va; va_start(va, fmt); @@ -91,36 +112,82 @@ hx509_print_func(hx509_vprint_func func, void *ctx, const char *fmt, ...) va_end(va); } +/** + * Print a oid to a string. + * + * @param oid oid to print + * @param str allocated string, free with hx509_xfree(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + int hx509_oid_sprint(const heim_oid *oid, char **str) { return der_print_heim_oid(oid, '.', str); } +/** + * Print a oid using a hx509_vprint_func function. To print to stdout + * use hx509_print_stdout(). + * + * @param oid oid to print + * @param func hx509_vprint_func to print with. + * @param ctx context variable to hx509_vprint_func function. + * + * @ingroup hx509_print + */ + void hx509_oid_print(const heim_oid *oid, hx509_vprint_func func, void *ctx) { char *str; hx509_oid_sprint(oid, &str); - hx509_print_func(func, ctx, "%s", str); + print_func(func, ctx, "%s", str); free(str); } +/** + * Print a bitstring using a hx509_vprint_func function. To print to + * stdout use hx509_print_stdout(). + * + * @param b bit string to print. + * @param func hx509_vprint_func to print with. + * @param ctx context variable to hx509_vprint_func function. + * + * @ingroup hx509_print + */ + void hx509_bitstring_print(const heim_bit_string *b, hx509_vprint_func func, void *ctx) { int i; - hx509_print_func(func, ctx, "\tlength: %d\n\t", b->length); + print_func(func, ctx, "\tlength: %d\n\t", b->length); for (i = 0; i < (b->length + 7) / 8; i++) - hx509_print_func(func, ctx, "%02x%s%s", - ((unsigned char *)b->data)[i], - i < (b->length - 7) / 8 - && (i == 0 || (i % 16) != 15) ? ":" : "", - i != 0 && (i % 16) == 15 ? - (i <= ((b->length + 7) / 8 - 2) ? "\n\t" : "\n"):""); + print_func(func, ctx, "%02x%s%s", + ((unsigned char *)b->data)[i], + i < (b->length - 7) / 8 + && (i == 0 || (i % 16) != 15) ? ":" : "", + i != 0 && (i % 16) == 15 ? + (i <= ((b->length + 7) / 8 - 2) ? "\n\t" : "\n"):""); } +/** + * Print certificate usage for a certificate to a string. + * + * @param context A hx509 context. + * @param c a certificate print the keyusage for. + * @param s the return string with the keysage printed in to, free + * with hx509_xfree(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + int hx509_cert_keyusage_print(hx509_context context, hx509_cert c, char **s) { @@ -268,9 +335,6 @@ check_authorityKeyIdentifier(hx509_validate_ctx ctx, status->haveAKI = 1; check_Null(ctx, status, cf, e); - status->haveSKI = 1; - check_Null(ctx, status, cf, e); - ret = decode_AuthorityKeyIdentifier(e->extnValue.data, e->extnValue.length, &ai, &size); @@ -298,6 +362,56 @@ check_authorityKeyIdentifier(hx509_validate_ctx ctx, return 0; } +static int +check_extKeyUsage(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + ExtKeyUsage eku; + size_t size, i; + int ret; + + check_Null(ctx, status, cf, e); + + ret = decode_ExtKeyUsage(e->extnValue.data, + e->extnValue.length, + &eku, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding ExtKeyUsage failed: %d", ret); + return 1; + } + if (size != e->extnValue.length) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Padding data in EKU"); + free_ExtKeyUsage(&eku); + return 1; + } + if (eku.len == 0) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "ExtKeyUsage length is 0"); + return 1; + } + + for (i = 0; i < eku.len; i++) { + char *str; + ret = der_print_heim_oid (&eku.val[i], '.', &str); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\tEKU: failed to print oid %d", i); + free_ExtKeyUsage(&eku); + return 1; + } + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\teku-%d: %s\n", i, str);; + free(str); + } + + free_ExtKeyUsage(&eku); + + return 0; +} static int check_pkinit_san(hx509_validate_ctx ctx, heim_any *a) @@ -664,7 +778,7 @@ struct { { ext(policyMappings, Null), M_N_C }, { ext(authorityKeyIdentifier, authorityKeyIdentifier), M_N_C }, { ext(policyConstraints, Null), D_C }, - { ext(extKeyUsage, Null), D_C }, + { ext(extKeyUsage, extKeyUsage), D_C }, { ext(freshestCRL, Null), M_N_C }, { ext(inhibitAnyPolicy, Null), M_C }, #undef ext @@ -679,6 +793,18 @@ struct { { NULL } }; +/** + * Allocate a hx509 validation/printing context. + * + * @param context A hx509 context. + * @param ctx a new allocated hx509 validation context, free with + * hx509_validate_ctx_free(). + + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + int hx509_validate_ctx_init(hx509_context context, hx509_validate_ctx *ctx) { @@ -689,6 +815,18 @@ hx509_validate_ctx_init(hx509_context context, hx509_validate_ctx *ctx) return 0; } +/** + * Set the printing functions for the validation context. + * + * @param ctx a hx509 valication context. + * @param func the printing function to usea. + * @param c the context variable to the printing function. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + void hx509_validate_ctx_set_print(hx509_validate_ctx ctx, hx509_vprint_func func, @@ -698,18 +836,50 @@ hx509_validate_ctx_set_print(hx509_validate_ctx ctx, ctx->ctx = c; } +/** + * Add flags to control the behaivor of the hx509_validate_cert() + * function. + * + * @param ctx A hx509 validation context. + * @param flags flags to add to the validation context. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + void hx509_validate_ctx_add_flags(hx509_validate_ctx ctx, int flags) { ctx->flags |= flags; } +/** + * Free an hx509 validate context. + * + * @param ctx the hx509 validate context to free. + * + * @ingroup hx509_print + */ + void hx509_validate_ctx_free(hx509_validate_ctx ctx) { free(ctx); } +/** + * Validate/Print the status of the certificate. + * + * @param context A hx509 context. + * @param ctx A hx509 validation context. + * @param cert the cerificate to validate/print. + + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + int hx509_validate_cert(hx509_context context, hx509_validate_ctx ctx, diff --git a/source4/heimdal/lib/hx509/revoke.c b/source4/heimdal/lib/hx509/revoke.c index ddcb17ee38d..2010f945f0e 100644 --- a/source4/heimdal/lib/hx509/revoke.c +++ b/source4/heimdal/lib/hx509/revoke.c @@ -31,14 +31,33 @@ * SUCH DAMAGE. */ +/** + * @page page_revoke Revocation methods + * + * There are two revocation method for PKIX/X.509: CRL and OCSP. + * Revocation is needed if the private key is lost and + * stolen. Depending on how picky you are, you might want to make + * revocation for destroyed private keys too (smartcard broken), but + * that should not be a problem. + * + * CRL is a list of certifiates that have expired. + * + * OCSP is an online checking method where the requestor sends a list + * of certificates to the OCSP server to return a signed reply if they + * are valid or not. Some services sends a OCSP reply as part of the + * hand-shake to make the revoktion decision simpler/faster for the + * client. + */ + #include "hx_locl.h" -RCSID("$Id: revoke.c 21153 2007-06-18 21:55:46Z lha $"); +RCSID("$Id: revoke.c 22583 2008-02-11 20:46:21Z lha $"); struct revoke_crl { char *path; time_t last_modfied; CRLCertificateList crl; int verified; + int failed_verify; }; struct revoke_ocsp { @@ -51,6 +70,7 @@ struct revoke_ocsp { struct hx509_revoke_ctx_data { + unsigned ref; struct { struct revoke_crl *val; size_t len; @@ -61,6 +81,17 @@ struct hx509_revoke_ctx_data { } ocsps; }; +/** + * Allocate a revokation context. Free with hx509_revoke_free(). + * + * @param context A hx509 context. + * @param ctx returns a newly allocated revokation context. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + int hx509_revoke_init(hx509_context context, hx509_revoke_ctx *ctx) { @@ -68,6 +99,7 @@ hx509_revoke_init(hx509_context context, hx509_revoke_ctx *ctx) if (*ctx == NULL) return ENOMEM; + (*ctx)->ref = 1; (*ctx)->crls.len = 0; (*ctx)->crls.val = NULL; (*ctx)->ocsps.len = 0; @@ -76,6 +108,19 @@ hx509_revoke_init(hx509_context context, hx509_revoke_ctx *ctx) return 0; } +hx509_revoke_ctx +_hx509_revoke_ref(hx509_revoke_ctx ctx) +{ + if (ctx == NULL) + return NULL; + if (ctx->ref <= 0) + _hx509_abort("revoke ctx refcount <= 0"); + ctx->ref++; + if (ctx->ref == 0) + _hx509_abort("revoke ctx refcount == 0"); + return ctx; +} + static void free_ocsp(struct revoke_ocsp *ocsp) { @@ -85,6 +130,14 @@ free_ocsp(struct revoke_ocsp *ocsp) hx509_cert_free(ocsp->signer); } +/** + * Free a hx509 revokation context. + * + * @param ctx context to be freed + * + * @ingroup hx509_revoke + */ + void hx509_revoke_free(hx509_revoke_ctx *ctx) { @@ -93,6 +146,11 @@ hx509_revoke_free(hx509_revoke_ctx *ctx) if (ctx == NULL || *ctx == NULL) return; + if ((*ctx)->ref <= 0) + _hx509_abort("revoke ctx refcount <= 0 on free"); + if (--(*ctx)->ref > 0) + return; + for (i = 0; i < (*ctx)->crls.len; i++) { free((*ctx)->crls.val[i].path); free_CRLCertificateList(&(*ctx)->crls.val[i].crl); @@ -150,7 +208,7 @@ verify_ocsp(hx509_context context, /* * If signer certificate isn't the CA certificate, lets check the - * its the CA that signed the signer certificate and the OCSP EKU + * it is the CA that signed the signer certificate and the OCSP EKU * is set. */ if (hx509_cert_cmp(signer, parent) != 0) { @@ -324,6 +382,18 @@ load_ocsp(hx509_context context, struct revoke_ocsp *ocsp) return 0; } +/** + * Add a OCSP file to the revokation context. + * + * @param context hx509 context + * @param ctx hx509 revokation context + * @param path path to file that is going to be added to the context. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + int hx509_revoke_add_ocsp(hx509_context context, hx509_revoke_ctx ctx, @@ -380,6 +450,7 @@ hx509_revoke_add_ocsp(hx509_context context, static int verify_crl(hx509_context context, + hx509_revoke_ctx ctx, CRLCertificateList *crl, time_t time_now, hx509_certs certs, @@ -391,52 +462,44 @@ verify_crl(hx509_context context, int ret; t = _hx509_Time2time_t(&crl->tbsCertList.thisUpdate); - if (t > time_now) + if (t > time_now) { + hx509_set_error_string(context, 0, HX509_CRL_USED_BEFORE_TIME, + "CRL used before time"); return HX509_CRL_USED_BEFORE_TIME; + } - if (crl->tbsCertList.nextUpdate == NULL) + if (crl->tbsCertList.nextUpdate == NULL) { + hx509_set_error_string(context, 0, HX509_CRL_INVALID_FORMAT, + "CRL missing nextUpdate"); return HX509_CRL_INVALID_FORMAT; + } t = _hx509_Time2time_t(crl->tbsCertList.nextUpdate); - if (t < time_now) + if (t < time_now) { + hx509_set_error_string(context, 0, HX509_CRL_USED_AFTER_TIME, + "CRL used after time"); return HX509_CRL_USED_AFTER_TIME; + } _hx509_query_clear(&q); - q.match = HX509_QUERY_MATCH_SUBJECT_NAME; - q.subject_name = &crl->tbsCertList.issuer; + /* + * If it's the signer have CRLSIGN bit set, use that as the signer + * cert for the certificate, otherwise, search for a certificate. + */ + if (_hx509_check_key_usage(context, parent, 1 << 6, FALSE) == 0) { + signer = hx509_cert_ref(parent); + } else { + q.match = HX509_QUERY_MATCH_SUBJECT_NAME; + q.match |= HX509_QUERY_KU_CRLSIGN; + q.subject_name = &crl->tbsCertList.issuer; - ret = hx509_certs_find(context, certs, &q, &signer); - if (ret) - return ret; - - /* verify is parent or CRLsigner */ - if (hx509_cert_cmp(signer, parent) != 0) { - Certificate *p = _hx509_get_cert(parent); - Certificate *s = _hx509_get_cert(signer); - - ret = _hx509_cert_is_parent_cmp(s, p, 0); - if (ret != 0) { - ret = HX509_PARENT_NOT_CA; - hx509_set_error_string(context, 0, ret, "Revoke CRL signer is " - "doesn't have CA as signer certificate"); - goto out; - } - - ret = _hx509_verify_signature_bitstring(context, - p, - &s->signatureAlgorithm, - &s->tbsCertificate._save, - &s->signatureValue); + ret = hx509_certs_find(context, certs, &q, &signer); if (ret) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, - "CRL signer signature invalid"); - goto out; + "Failed to find certificate for CRL"); + return ret; } - - ret = _hx509_check_key_usage(context, signer, 1 << 6, TRUE); /* crl */ - if (ret != 0) - goto out; } ret = _hx509_verify_signature_bitstring(context, @@ -450,6 +513,44 @@ verify_crl(hx509_context context, goto out; } + /* + * If signer is not CA cert, need to check revoke status of this + * CRL signing cert too, this include all parent CRL signer cert + * up to the root *sigh*, assume root at least hve CERTSIGN flag + * set. + */ + while (_hx509_check_key_usage(context, signer, 1 << 5, TRUE)) { + hx509_cert crl_parent; + + _hx509_query_clear(&q); + + q.match = HX509_QUERY_MATCH_SUBJECT_NAME; + q.match |= HX509_QUERY_KU_CRLSIGN; + q.subject_name = &_hx509_get_cert(signer)->tbsCertificate.issuer; + + ret = hx509_certs_find(context, certs, &q, &crl_parent); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to find parent of CRL signer"); + goto out; + } + + ret = hx509_revoke_verify(context, + ctx, + certs, + time_now, + signer, + crl_parent); + hx509_cert_free(signer); + signer = crl_parent; + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to verify revoke " + "status of CRL signer"); + goto out; + } + } + out: hx509_cert_free(signer); @@ -485,6 +586,18 @@ load_crl(const char *path, time_t *t, CRLCertificateList *crl) return 0; } +/** + * Add a CRL file to the revokation context. + * + * @param context hx509 context + * @param ctx hx509 revokation context + * @param path path to file that is going to be added to the context. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + int hx509_revoke_add_crl(hx509_context context, hx509_revoke_ctx ctx, @@ -537,6 +650,23 @@ hx509_revoke_add_crl(hx509_context context, return ret; } +/** + * Check that a certificate is not expired according to a revokation + * context. Also need the parent certificte to the check OCSP + * parent identifier. + * + * @param context hx509 context + * @param ctx hx509 revokation context + * @param certs + * @param now + * @param cert + * @param parent_cert + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + int hx509_revoke_verify(hx509_context context, @@ -551,6 +681,8 @@ hx509_revoke_verify(hx509_context context, unsigned long i, j, k; int ret; + hx509_clear_error_string(context); + for (i = 0; i < ctx->ocsps.len; i++) { struct revoke_ocsp *ocsp = &ctx->ocsps.val[i]; struct stat sb; @@ -604,6 +736,10 @@ hx509_revoke_verify(hx509_context context, case choice_OCSPCertStatus_good: break; case choice_OCSPCertStatus_revoked: + hx509_set_error_string(context, 0, + HX509_CERT_REVOKED, + "Certificate revoked by issuer in OCSP"); + return HX509_CERT_REVOKED; case choice_OCSPCertStatus_unknown: continue; } @@ -613,7 +749,7 @@ hx509_revoke_verify(hx509_context context, now + context->ocsp_time_diff) continue; - /* don't allow the next updte to be in the past */ + /* don't allow the next update to be in the past */ if (ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate) { if (*ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate < now) continue; @@ -627,11 +763,12 @@ hx509_revoke_verify(hx509_context context, for (i = 0; i < ctx->crls.len; i++) { struct revoke_crl *crl = &ctx->crls.val[i]; struct stat sb; + int diff; /* check if cert.issuer == crls.val[i].crl.issuer */ ret = _hx509_name_cmp(&c->tbsCertificate.issuer, - &crl->crl.tbsCertList.issuer); - if (ret) + &crl->crl.tbsCertList.issuer, &diff); + if (ret || diff) continue; ret = stat(crl->path, &sb); @@ -643,21 +780,32 @@ hx509_revoke_verify(hx509_context context, free_CRLCertificateList(&crl->crl); crl->crl = cl; crl->verified = 0; + crl->failed_verify = 0; } } + if (crl->failed_verify) + continue; /* verify signature in crl if not already done */ if (crl->verified == 0) { - ret = verify_crl(context, &crl->crl, now, certs, parent_cert); - if (ret) - return ret; + ret = verify_crl(context, ctx, &crl->crl, now, certs, parent_cert); + if (ret) { + crl->failed_verify = 1; + continue; + } crl->verified = 1; } - - if (crl->crl.tbsCertList.crlExtensions) - for (j = 0; j < crl->crl.tbsCertList.crlExtensions->len; j++) - if (crl->crl.tbsCertList.crlExtensions->val[j].critical) + + if (crl->crl.tbsCertList.crlExtensions) { + for (j = 0; j < crl->crl.tbsCertList.crlExtensions->len; j++) { + if (crl->crl.tbsCertList.crlExtensions->val[j].critical) { + hx509_set_error_string(context, 0, + HX509_CRL_UNKNOWN_EXTENSION, + "Unknown CRL extension"); return HX509_CRL_UNKNOWN_EXTENSION; + } + } + } if (crl->crl.tbsCertList.revokedCertificates == NULL) return 0; @@ -667,7 +815,7 @@ hx509_revoke_verify(hx509_context context, time_t t; ret = der_heim_integer_cmp(&crl->crl.tbsCertList.revokedCertificates->val[j].userCertificate, - &c->tbsCertificate.serialNumber); + &c->tbsCertificate.serialNumber); if (ret != 0) continue; @@ -680,7 +828,10 @@ hx509_revoke_verify(hx509_context context, if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->val[k].critical) return HX509_CRL_UNKNOWN_EXTENSION; - return HX509_CRL_CERT_REVOKED; + hx509_set_error_string(context, 0, + HX509_CERT_REVOKED, + "Certificate revoked by issuer in CRL"); + return HX509_CERT_REVOKED; } return 0; @@ -689,6 +840,10 @@ hx509_revoke_verify(hx509_context context, if (context->flags & HX509_CTX_VERIFY_MISSING_OK) return 0; + hx509_set_error_string(context, HX509_ERROR_APPEND, + HX509_REVOKE_STATUS_MISSING, + "No revoke status found for " + "certificates"); return HX509_REVOKE_STATUS_MISSING; } @@ -785,6 +940,22 @@ out: return ret; } +/** + * Create an OCSP request for a set of certificates. + * + * @param context a hx509 context + * @param reqcerts list of certificates to request ocsp data for + * @param pool certificate pool to use when signing + * @param signer certificate to use to sign the request + * @param digest the signing algorithm in the request, if NULL use the + * default signature algorithm, + * @param request the encoded request, free with free_heim_octet_string(). + * @param nonce nonce in the request, free with free_heim_octet_string(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ int hx509_ocsp_request(hx509_context context, @@ -813,41 +984,49 @@ hx509_ocsp_request(hx509_context context, ret = hx509_certs_iter(context, reqcerts, add_to_req, &ctx); hx509_cert_free(ctx.parent); - if (ret) { - free_OCSPRequest(&req); - return ret; - } + if (ret) + goto out; if (nonce) { - req.tbsRequest.requestExtensions = calloc(1, sizeof(*req.tbsRequest.requestExtensions)); if (req.tbsRequest.requestExtensions == NULL) { - free_OCSPRequest(&req); - return ENOMEM; + ret = ENOMEM; + goto out; } es = req.tbsRequest.requestExtensions; - es->len = 1; es->val = calloc(es->len, sizeof(es->val[0])); + if (es->val == NULL) { + ret = ENOMEM; + goto out; + } + es->len = 1; ret = der_copy_oid(oid_id_pkix_ocsp_nonce(), &es->val[0].extnID); - if (ret) - abort(); - + if (ret) { + free_OCSPRequest(&req); + return ret; + } + es->val[0].extnValue.data = malloc(10); if (es->val[0].extnValue.data == NULL) { - free_OCSPRequest(&req); - return ENOMEM; + ret = ENOMEM; + goto out; } es->val[0].extnValue.length = 10; ret = RAND_bytes(es->val[0].extnValue.data, es->val[0].extnValue.length); if (ret != 1) { - free_OCSPRequest(&req); - return HX509_CRYPTO_INTERNAL_ERROR; + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; + } + ret = der_copy_octet_string(nonce, &es->val[0].extnValue); + if (ret) { + ret = ENOMEM; + goto out; } } @@ -855,12 +1034,15 @@ hx509_ocsp_request(hx509_context context, &req, &size, ret); free_OCSPRequest(&req); if (ret) - return ret; + goto out; if (size != request->length) _hx509_abort("internal ASN.1 encoder error"); - return 0; + +out: + free_OCSPRequest(&req); + return ret; } static char * @@ -872,6 +1054,18 @@ printable_time(time_t t) return s; } +/** + * Print the OCSP reply stored in a file. + * + * @param context a hx509 context + * @param path path to a file with a OCSP reply + * @param out the out FILE descriptor to print the reply on + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + int hx509_revoke_ocsp_print(hx509_context context, const char *path, FILE *out) { @@ -959,10 +1153,23 @@ hx509_revoke_ocsp_print(hx509_context context, const char *path, FILE *out) return ret; } -/* - * Verify that the `cert' is part of the OCSP reply and its not - * expired. Doesn't verify signature the OCSP reply or its done by a +/** + * Verify that the certificate is part of the OCSP reply and it's not + * expired. Doesn't verify signature the OCSP reply or it's done by a * authorized sender, that is assumed to be already done. + * + * @param context a hx509 context + * @param now the time right now, if 0, use the current time. + * @param cert the certificate to verify + * @param flags flags control the behavior + * @param data pointer to the encode ocsp reply + * @param length the length of the encode ocsp reply + * @param expiration return the time the OCSP will expire and need to + * be rechecked. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify */ int @@ -1062,6 +1269,17 @@ struct hx509_crl { time_t expire; }; +/** + * Create a CRL context. Use hx509_crl_free() to free the CRL context. + * + * @param context a hx509 context. + * @param crl return pointer to a newly allocated CRL context. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + int hx509_crl_alloc(hx509_context context, hx509_crl *crl) { @@ -1083,6 +1301,18 @@ hx509_crl_alloc(hx509_context context, hx509_crl *crl) return ret; } +/** + * Add revoked certificate to an CRL context. + * + * @param context a hx509 context. + * @param crl the CRL to add the revoked certificate to. + * @param certs keyset of certificate to revoke. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + int hx509_crl_add_revoked_certs(hx509_context context, hx509_crl crl, @@ -1091,6 +1321,19 @@ hx509_crl_add_revoked_certs(hx509_context context, return hx509_certs_merge(context, crl->revoked, certs); } +/** + * Set the lifetime of a CRL context. + * + * @param context a hx509 context. + * @param crl a CRL context + * @param delta delta time the certificate is valid, library adds the + * current time to this. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + int hx509_crl_lifetime(hx509_context context, hx509_crl crl, int delta) { @@ -1098,6 +1341,14 @@ hx509_crl_lifetime(hx509_context context, hx509_crl crl, int delta) return 0; } +/** + * Free a CRL context. + * + * @param context a hx509 context. + * @param crl a CRL context to free. + * + * @ingroup hx509_verify + */ void hx509_crl_free(hx509_context context, hx509_crl *crl) @@ -1144,6 +1395,19 @@ add_revoked(hx509_context context, void *ctx, hx509_cert cert) return 0; } +/** + * Sign a CRL and return an encode certificate. + * + * @param context a hx509 context. + * @param signer certificate to sign the CRL with + * @param crl the CRL to sign + * @param os return the signed and encoded CRL, free with + * free_heim_octet_string() + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ int hx509_crl_sign(hx509_context context, diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index 999ce7f1204..775239cf6df 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -37,7 +37,7 @@ #include <dlfcn.h> #endif -RCSID("$Id: acache.c 19764 2007-01-08 15:31:01Z lha $"); +RCSID("$Id: acache.c 22669 2008-03-09 23:39:25Z lha $"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; @@ -188,11 +188,10 @@ make_cred_from_ccred(krb5_context context, ; if (i) { - cred->authdata.val = malloc(sizeof(cred->authdata.val[0]) * i); + cred->authdata.val = calloc(i, sizeof(cred->authdata.val[0])); if (cred->authdata.val == NULL) goto nomem; cred->authdata.len = i; - memset(cred->authdata.val, 0, sizeof(cred->authdata.val[0]) * i); for (i = 0; i < cred->authdata.len; i++) { cred->authdata.val[i].ad_type = incred->authdata[i]->type; ret = krb5_data_copy(&cred->authdata.val[i].ad_data, @@ -207,11 +206,10 @@ make_cred_from_ccred(krb5_context context, ; if (i) { - cred->addresses.val = malloc(sizeof(cred->addresses.val[0]) * i); + cred->addresses.val = calloc(i, sizeof(cred->addresses.val[0])); if (cred->addresses.val == NULL) goto nomem; cred->addresses.len = i; - memset(cred->addresses.val, 0, sizeof(cred->addresses.val[0]) * i); for (i = 0; i < cred->addresses.len; i++) { cred->addresses.val[i].addr_type = incred->addresses[i]->type; @@ -260,7 +258,7 @@ nomem: krb5_set_error_string(context, "malloc - out of memory"); fail: - krb5_free_creds_contents(context, cred); + krb5_free_cred_contents(context, cred); return ret; } @@ -331,6 +329,10 @@ make_ccred_from_cred(krb5_context context, for (i = 0; i < incred->addresses.len; i++) { cc_data *addr; addr = malloc(sizeof(*addr)); + if (addr == NULL) { + ret = ENOMEM; + goto fail; + } addr->type = incred->addresses.val[i].addr_type; addr->length = incred->addresses.val[i].address.length; addr->data = malloc(addr->length); @@ -383,20 +385,21 @@ fail: return ret; } -static char * -get_cc_name(cc_ccache_t cache) +static cc_int32 +get_cc_name(krb5_acc *a) { cc_string_t name; cc_int32 error; - char *str; - error = (*cache->func->get_name)(cache, &name); + error = (*a->ccache->func->get_name)(a->ccache, &name); if (error) - return NULL; + return error; - str = strdup(name->data); + a->cache_name = strdup(name->data); (*name->func->release)(name); - return str; + if (a->cache_name == NULL) + return ccErrNoMem; + return ccNoError; } @@ -405,17 +408,36 @@ acc_get_name(krb5_context context, krb5_ccache id) { krb5_acc *a = ACACHE(id); - static char n[255]; - char *name; + int32_t error; - name = get_cc_name(a->ccache); - if (name == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return NULL; - } - strlcpy(n, name, sizeof(n)); - free(name); - return n; + if (a->cache_name == NULL) { + krb5_error_code ret; + krb5_principal principal; + char *name; + + ret = _krb5_get_default_principal_local(context, &principal); + if (ret) + return NULL; + + ret = krb5_unparse_name(context, principal, &name); + krb5_free_principal(context, principal); + if (ret) + return NULL; + + error = (*a->context->func->create_new_ccache)(a->context, + cc_credentials_v5, + name, + &a->ccache); + krb5_xfree(name); + if (error) + return NULL; + + error = get_cc_name(a); + if (error) + return NULL; + } + + return a->cache_name; } static krb5_error_code @@ -449,23 +471,6 @@ acc_alloc(krb5_context context, krb5_ccache *id) } static krb5_error_code -get_default_principal(krb5_context context, char **p) -{ - krb5_error_code ret; - krb5_principal principal; - - *p = NULL; - - ret = _krb5_get_default_principal_local(context, &principal); - if (ret) - return ret; - - ret = krb5_unparse_name(context, principal, p); - krb5_free_principal(context, principal); - return ret; -} - -static krb5_error_code acc_resolve(krb5_context context, krb5_ccache *id, const char *res) { krb5_error_code ret; @@ -478,38 +483,22 @@ acc_resolve(krb5_context context, krb5_ccache *id, const char *res) a = ACACHE(*id); - if (res == NULL || res[0] == '\0') { - error = (*a->context->func->open_default_ccache)(a->context, - &a->ccache); - if (error == ccErrCCacheNotFound) { - char *p; - - ret = get_default_principal(context, &p); - if (ret == 0) { - error = (*a->context->func->create_default_ccache)(a->context, - cc_credentials_v5, - p, - &a->ccache); - free(p); - } + error = (*a->context->func->open_ccache)(a->context, res, &a->ccache); + if (error == ccNoError) { + error = get_cc_name(a); + if (error != ccNoError) { + acc_close(context, *id); + *id = NULL; + return translate_cc_error(context, error); } - if (error == 0) - a->cache_name = get_cc_name(a->ccache); + } else if (error == ccErrCCacheNotFound) { + a->ccache = NULL; + a->cache_name = NULL; + error = 0; } else { - error = (*a->context->func->open_ccache)(a->context, res, &a->ccache); - if (error == 0) - a->cache_name = strdup(res); - } - if (error != 0) { *id = NULL; return translate_cc_error(context, error); } - if (a->cache_name == NULL) { - acc_close(context, *id); - *id = NULL; - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } return 0; } @@ -518,35 +507,17 @@ static krb5_error_code acc_gen_new(krb5_context context, krb5_ccache *id) { krb5_error_code ret; - cc_int32 error; krb5_acc *a; - char *p; - - ret = get_default_principal(context, &p); ret = acc_alloc(context, id); - if (ret) { - free(p); + if (ret) return ret; - } a = ACACHE(*id); - error = (*a->context->func->create_new_ccache)(a->context, - cc_credentials_v5, - p, &a->ccache); - free(p); - if (error) { - *id = NULL; - return translate_cc_error(context, error); - } - a->cache_name = get_cc_name(a->ccache); - if (a->cache_name == NULL) { - acc_close(context, *id); - *id = NULL; - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } + a->ccache = NULL; + a->cache_name = NULL; + return 0; } @@ -555,9 +526,7 @@ acc_initialize(krb5_context context, krb5_ccache id, krb5_principal primary_principal) { - cc_credentials_iterator_t iter; krb5_acc *a = ACACHE(id); - cc_credentials_t ccred; krb5_error_code ret; int32_t error; char *name; @@ -566,12 +535,17 @@ acc_initialize(krb5_context context, if (ret) return ret; - if (a->ccache == NULL) { + if (a->cache_name == NULL) { error = (*a->context->func->create_new_ccache)(a->context, cc_credentials_v5, name, &a->ccache); - } else { + free(name); + if (error == ccNoError) + error = get_cc_name(a); + } else { + cc_credentials_iterator_t iter; + cc_credentials_t ccred; error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); if (error) { @@ -593,8 +567,6 @@ acc_initialize(krb5_context context, name); } - free(name); - return translate_cc_error(context, error); } @@ -629,6 +601,10 @@ acc_destroy(krb5_context context, error = (*a->ccache->func->destroy)(a->ccache); a->ccache = NULL; } + if (a->context) { + error = (a->context->func->release)(a->context); + a->context = NULL; + } return translate_cc_error(context, error); } @@ -643,6 +619,11 @@ acc_store_cred(krb5_context context, krb5_error_code ret; cc_int32 error; + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } + cred.version = cc_credentials_v5; cred.credentials.credentials_v5 = &v5cred; @@ -671,8 +652,10 @@ acc_get_principal(krb5_context context, int32_t error; cc_string_t name; - if (a->ccache == NULL) - return ENOENT; + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } error = (*a->ccache->func->get_principal)(a->ccache, cc_credentials_v5, @@ -695,6 +678,11 @@ acc_get_first (krb5_context context, krb5_acc *a = ACACHE(id); int32_t error; + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } + error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); if (error) { krb5_clear_error_string(context); @@ -755,6 +743,11 @@ acc_remove_cred(krb5_context context, cc_int32 error; char *client, *server; + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } + if (cred->client) { ret = krb5_unparse_name(context, cred->client, &client); if (ret) @@ -894,12 +887,11 @@ acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) a = ACACHE(*id); a->ccache = cache; - a->cache_name = get_cc_name(a->ccache); - if (a->cache_name == NULL) { + error = get_cc_name(a); + if (error) { acc_close(context, *id); *id = NULL; - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; + return translate_cc_error(context, error); } return 0; } @@ -917,6 +909,76 @@ acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) return 0; } +static krb5_error_code +acc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_acc *afrom = ACACHE(from); + krb5_acc *ato = ACACHE(to); + int32_t error; + + if (ato->ccache == NULL) { + cc_string_t name; + + error = (*afrom->ccache->func->get_principal)(afrom->ccache, + cc_credentials_v5, + &name); + if (error) + return translate_cc_error(context, error); + + error = (*ato->context->func->create_new_ccache)(ato->context, + cc_credentials_v5, + name->data, + &ato->ccache); + (*name->func->release)(name); + if (error) + return translate_cc_error(context, error); + } + + + error = (*ato->ccache->func->move)(afrom->ccache, ato->ccache); + return translate_cc_error(context, error); +} + +static krb5_error_code +acc_default_name(krb5_context context, char **str) +{ + krb5_error_code ret; + cc_context_t cc; + cc_string_t name; + int32_t error; + + ret = init_ccapi(context); + if (ret) + return ret; + + error = (*init_func)(&cc, ccapi_version_3, NULL, NULL); + if (error) + return translate_cc_error(context, error); + + error = (*cc->func->get_default_ccache_name)(cc, &name); + if (error) { + (*cc->func->release)(cc); + return translate_cc_error(context, error); + } + + asprintf(str, "API:%s", name->data); + (*name->func->release)(name); + (*cc->func->release)(cc); + + if (*str == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + + +/** + * Variable containing the API based credential cache implemention. + * + * @ingroup krb5_ccache + */ + const krb5_cc_ops krb5_acc_ops = { "API", acc_get_name, @@ -936,5 +998,7 @@ const krb5_cc_ops krb5_acc_ops = { acc_get_version, acc_get_cache_first, acc_get_cache_next, - acc_end_cache_get + acc_end_cache_get, + acc_move, + acc_default_name }; diff --git a/source4/heimdal/lib/krb5/add_et_list.c b/source4/heimdal/lib/krb5/add_et_list.c index a6005c68590..5455d8ac994 100644 --- a/source4/heimdal/lib/krb5/add_et_list.c +++ b/source4/heimdal/lib/krb5/add_et_list.c @@ -33,12 +33,20 @@ #include "krb5_locl.h" -RCSID("$Id: add_et_list.c 13713 2004-04-13 14:33:45Z lha $"); +RCSID("$Id: add_et_list.c 22603 2008-02-21 18:44:57Z lha $"); -/* +/** * Add a specified list of error messages to the et list in context. * Call func (probably a comerr-generated function) with a pointer to * the current et_list. + * + * @param context A kerberos context. + * @param func The generated com_err et function. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 */ krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index 8c318430581..f364f5974d4 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c 18805 2006-10-22 06:54:00Z lha $"); +RCSID("$Id: addr_families.c 22039 2007-11-10 11:47:35Z lha $"); struct addr_operations { int af; @@ -767,6 +767,19 @@ find_atype(int atype) return NULL; } +/** + * krb5_sockaddr2address stores a address a "struct sockaddr" sa in + * the krb5_address addr. + * + * @param context a Keberos context + * @param sa a struct sockaddr to extract the address from + * @param addr an Kerberos 5 address to store the address in. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_sockaddr2address (krb5_context context, const struct sockaddr *sa, krb5_address *addr) @@ -780,6 +793,20 @@ krb5_sockaddr2address (krb5_context context, return (*a->sockaddr2addr)(sa, addr); } +/** + * krb5_sockaddr2port extracts a port (if possible) from a "struct + * sockaddr. + * + * @param context a Keberos context + * @param sa a struct sockaddr to extract the port from + * @param port a pointer to an int16_t store the port in. + * + * @return Return an error code or 0. Will return + * KRB5_PROG_ATYPE_NOSUPP in case address type is not supported. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_sockaddr2port (krb5_context context, const struct sockaddr *sa, int16_t *port) @@ -793,6 +820,27 @@ krb5_sockaddr2port (krb5_context context, return (*a->sockaddr2port)(sa, port); } +/** + * krb5_addr2sockaddr sets the "struct sockaddr sockaddr" from addr + * and port. The argument sa_size should initially contain the size of + * the sa and after the call, it will contain the actual length of the + * address. In case of the sa is too small to fit the whole address, + * the up to *sa_size will be stored, and then *sa_size will be set to + * the required length. + * + * @param context a Keberos context + * @param addr the address to copy the from + * @param sa the struct sockaddr that will be filled in + * @param sa_size pointer to length of sa, and after the call, it will + * contain the actual length of the address. + * @param port set port in sa. + * + * @return Return an error code or 0. Will return + * KRB5_PROG_ATYPE_NOSUPP in case address type is not supported. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_addr2sockaddr (krb5_context context, const krb5_address *addr, @@ -808,7 +856,8 @@ krb5_addr2sockaddr (krb5_context context, return KRB5_PROG_ATYPE_NOSUPP; } if (a->addr2sockaddr == NULL) { - krb5_set_error_string (context, "Can't convert address type %d to sockaddr", + krb5_set_error_string (context, + "Can't convert address type %d to sockaddr", addr->addr_type); return KRB5_PROG_ATYPE_NOSUPP; } @@ -816,6 +865,15 @@ krb5_addr2sockaddr (krb5_context context, return 0; } +/** + * krb5_max_sockaddr_size returns the max size of the .Li struct + * sockaddr that the Kerberos library will return. + * + * @return Return an size_t of the maximum struct sockaddr. + * + * @ingroup krb5_address + */ + size_t KRB5_LIB_FUNCTION krb5_max_sockaddr_size (void) { @@ -828,6 +886,18 @@ krb5_max_sockaddr_size (void) return max_sockaddr_size; } +/** + * krb5_sockaddr_uninteresting returns TRUE for all .Fa sa that the + * kerberos library thinks are uninteresting. One example are link + * local addresses. + * + * @param sa pointer to struct sockaddr that might be interesting. + * + * @return Return a non zero for uninteresting addresses. + * + * @ingroup krb5_address + */ + krb5_boolean KRB5_LIB_FUNCTION krb5_sockaddr_uninteresting(const struct sockaddr *sa) { @@ -837,6 +907,25 @@ krb5_sockaddr_uninteresting(const struct sockaddr *sa) return (*a->uninteresting)(sa); } +/** + * krb5_h_addr2sockaddr initializes a "struct sockaddr sa" from af and + * the "struct hostent" (see gethostbyname(3) ) h_addr_list + * component. The argument sa_size should initially contain the size + * of the sa, and after the call, it will contain the actual length of + * the address. + * + * @param context a Keberos context + * @param af addresses + * @param addr address + * @param sa returned struct sockaddr + * @param sa_size size of sa + * @param port port to set in sa. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_h_addr2sockaddr (krb5_context context, int af, @@ -853,6 +942,20 @@ krb5_h_addr2sockaddr (krb5_context context, return 0; } +/** + * krb5_h_addr2addr works like krb5_h_addr2sockaddr with the exception + * that it operates on a krb5_address instead of a struct sockaddr. + * + * @param context a Keberos context + * @param af address family + * @param haddr host address from struct hostent. + * @param addr returned krb5_address. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_h_addr2addr (krb5_context context, int af, @@ -866,6 +969,23 @@ krb5_h_addr2addr (krb5_context context, return (*a->h_addr2addr)(haddr, addr); } +/** + * krb5_anyaddr fills in a "struct sockaddr sa" that can be used to + * bind(2) to. The argument sa_size should initially contain the size + * of the sa, and after the call, it will contain the actual length + * of the address. + * + * @param context a Keberos context + * @param af address family + * @param sa sockaddr + * @param sa_size lenght of sa. + * @param port for to fill into sa. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_anyaddr (krb5_context context, int af, @@ -884,6 +1004,22 @@ krb5_anyaddr (krb5_context context, return 0; } +/** + * krb5_print_address prints the address in addr to the string string + * that have the length len. If ret_len is not NULL, it will be filled + * with the length of the string if size were unlimited (not including + * the final NUL) . + * + * @param addr address to be printed + * @param str pointer string to print the address into + * @param len length that will fit into area pointed to by "str". + * @param ret_len return length the str. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_print_address (const krb5_address *addr, char *str, size_t len, size_t *ret_len) @@ -921,6 +1057,19 @@ krb5_print_address (const krb5_address *addr, return 0; } +/** + * krb5_parse_address returns the resolved hostname in string to the + * krb5_addresses addresses . + * + * @param context a Keberos context + * @param string + * @param addresses + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_parse_address(krb5_context context, const char *string, @@ -980,6 +1129,21 @@ krb5_parse_address(krb5_context context, return 0; } +/** + * krb5_address_order compares the addresses addr1 and addr2 so that + * it can be used for sorting addresses. If the addresses are the same + * address krb5_address_order will return 0. Behavies like memcmp(2). + * + * @param context a Keberos context + * @param addr1 krb5_address to compare + * @param addr2 krb5_address to compare + * + * @return < 0 if address addr1 in "less" then addr2. 0 if addr1 and + * addr2 is the same address, > 0 if addr2 is "less" then addr1. + * + * @ingroup krb5_address + */ + int KRB5_LIB_FUNCTION krb5_address_order(krb5_context context, const krb5_address *addr1, @@ -1014,6 +1178,19 @@ krb5_address_order(krb5_context context, addr1->address.length); } +/** + * krb5_address_compare compares the addresses addr1 and addr2. + * Returns TRUE if the two addresses are the same. + * + * @param context a Keberos context + * @param addr1 address to compare + * @param addr2 address to compare + * + * @return Return an TRUE is the address are the same FALSE if not + * + * @ingroup krb5_address + */ + krb5_boolean KRB5_LIB_FUNCTION krb5_address_compare(krb5_context context, const krb5_address *addr1, @@ -1022,6 +1199,19 @@ krb5_address_compare(krb5_context context, return krb5_address_order (context, addr1, addr2) == 0; } +/** + * krb5_address_search checks if the address addr is a member of the + * address set list addrlist . + * + * @param context a Keberos context. + * @param addr address to search for. + * @param addrlist list of addresses to look in for addr. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_boolean KRB5_LIB_FUNCTION krb5_address_search(krb5_context context, const krb5_address *addr, @@ -1035,6 +1225,18 @@ krb5_address_search(krb5_context context, return FALSE; } +/** + * krb5_free_address frees the data stored in the address that is + * alloced with any of the krb5_address functions. + * + * @param context a Keberos context + * @param address addresss to be freed. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_free_address(krb5_context context, krb5_address *address) @@ -1047,6 +1249,18 @@ krb5_free_address(krb5_context context, return 0; } +/** + * krb5_free_addresses frees the data stored in the address that is + * alloced with any of the krb5_address functions. + * + * @param context a Keberos context + * @param addresses addressses to be freed. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_free_addresses(krb5_context context, krb5_addresses *addresses) @@ -1060,6 +1274,19 @@ krb5_free_addresses(krb5_context context, return 0; } +/** + * krb5_copy_address copies the content of address + * inaddr to outaddr. + * + * @param context a Keberos context + * @param inaddr pointer to source address + * @param outaddr pointer to destination address + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_copy_address(krb5_context context, const krb5_address *inaddr, @@ -1071,6 +1298,19 @@ krb5_copy_address(krb5_context context, return copy_HostAddress(inaddr, outaddr); } +/** + * krb5_copy_addresses copies the content of addresses + * inaddr to outaddr. + * + * @param context a Keberos context + * @param inaddr pointer to source addresses + * @param outaddr pointer to destination addresses + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_copy_addresses(krb5_context context, const krb5_addresses *inaddr, @@ -1085,6 +1325,19 @@ krb5_copy_addresses(krb5_context context, return 0; } +/** + * krb5_append_addresses adds the set of addresses in source to + * dest. While copying the addresses, duplicates are also sorted out. + * + * @param context a Keberos context + * @param dest destination of copy operation + * @param source adresses that are going to be added to dest + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_append_addresses(krb5_context context, krb5_addresses *dest, @@ -1115,8 +1368,17 @@ krb5_append_addresses(krb5_context context, return 0; } -/* +/** * Create an address of type KRB5_ADDRESS_ADDRPORT from (addr, port) + * + * @param context a Keberos context + * @param res built address from addr/port + * @param addr address to use + * @param port port to use + * + * @return Return an error code or 0. + * + * @ingroup krb5_address */ krb5_error_code KRB5_LIB_FUNCTION @@ -1170,9 +1432,19 @@ krb5_make_addrport (krb5_context context, return 0; } -/* +/** * Calculate the boundary addresses of `inaddr'/`prefixlen' and store * them in `low' and `high'. + * + * @param context a Keberos context + * @param inaddr address in prefixlen that the bondery searched + * @param prefixlen width of boundery + * @param low lowest address + * @param high highest address + * + * @return Return an error code or 0. + * + * @ingroup krb5_address */ krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/asn1_glue.c b/source4/heimdal/lib/krb5/asn1_glue.c index 6b7d40d4537..b3f775b4bea 100644 --- a/source4/heimdal/lib/krb5/asn1_glue.c +++ b/source4/heimdal/lib/krb5/asn1_glue.c @@ -37,7 +37,7 @@ #include "krb5_locl.h" -RCSID("$Id: asn1_glue.c 18269 2006-10-06 17:02:48Z lha $"); +RCSID("$Id: asn1_glue.c 21745 2007-07-31 16:11:25Z lha $"); krb5_error_code KRB5_LIB_FUNCTION _krb5_principal2principalname (PrincipalName *p, @@ -53,8 +53,12 @@ _krb5_principalname2krb5_principal (krb5_context context, const Realm realm) { krb5_principal p = malloc(sizeof(*p)); + if (p == NULL) + return ENOMEM; copy_PrincipalName(&from, &p->name); p->realm = strdup(realm); + if (p->realm == NULL) + return ENOMEM; *principal = p; return 0; } diff --git a/source4/heimdal/lib/krb5/auth_context.c b/source4/heimdal/lib/krb5/auth_context.c index 5e08f15ad46..323f17a2453 100644 --- a/source4/heimdal/lib/krb5/auth_context.c +++ b/source4/heimdal/lib/krb5/auth_context.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: auth_context.c 14452 2005-01-05 02:34:08Z lukeh $"); +RCSID("$Id: auth_context.c 21745 2007-07-31 16:11:25Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_auth_con_init(krb5_context context, @@ -141,14 +141,16 @@ krb5_auth_con_setaddrs(krb5_context context, if (auth_context->local_address) krb5_free_address (context, auth_context->local_address); else - auth_context->local_address = malloc(sizeof(krb5_address)); + if ((auth_context->local_address = malloc(sizeof(krb5_address))) == NULL) + return ENOMEM; krb5_copy_address(context, local_addr, auth_context->local_address); } if (remote_addr) { if (auth_context->remote_address) krb5_free_address (context, auth_context->remote_address); else - auth_context->remote_address = malloc(sizeof(krb5_address)); + if ((auth_context->remote_address = malloc(sizeof(krb5_address))) == NULL) + return ENOMEM; krb5_copy_address(context, remote_addr, auth_context->remote_address); } return 0; diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index 59aae40d289..5db6d2b2cf8 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,12 +33,20 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c 21498 2007-07-11 09:41:43Z lha $"); +RCSID("$Id: cache.c 22127 2007-12-04 00:54:37Z lha $"); -/* +/** * Add a new ccache type with operations `ops', overwriting any * existing one if `override'. - * Return an error code or 0. + * + * @param context a Keberos context + * @param ops type of plugin symbol + * @param override flag to select if the registration is to overide + * an existing ops with the same name. + * + * @return Return an error code or 0. + * + * @ingroup krb5_ccache */ krb5_error_code KRB5_LIB_FUNCTION @@ -101,8 +109,7 @@ _krb5_cc_allocate(krb5_context context, /* * Allocate memory for a new ccache in `id' with operations `ops' - * and name `residual'. - * Return 0 or an error code. + * and name `residual'. Return 0 or an error code. */ static krb5_error_code @@ -122,12 +129,21 @@ allocate_ccache (krb5_context context, return ret; } -/* +/** * Find and allocate a ccache in `id' from the specification in `residual'. * If the ccache name doesn't contain any colon, interpret it as a file name. - * Return 0 or an error code. + * + * @param context a Keberos context. + * @param name string name of a credential cache. + * @param id return pointer to a found credential cache. + * + * @return Return 0 or an error code. In case of an error, id is set + * to NULL. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_resolve(krb5_context context, const char *name, @@ -135,6 +151,8 @@ krb5_cc_resolve(krb5_context context, { int i; + *id = NULL; + for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { size_t prefix_len = strlen(context->cc_ops[i].prefix); @@ -153,57 +171,64 @@ krb5_cc_resolve(krb5_context context, } } -/* +/** * Generate a new ccache of type `ops' in `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_gen_new(krb5_context context, const krb5_cc_ops *ops, krb5_ccache *id) { - krb5_error_code ret; - - ret = _krb5_cc_allocate(context, ops, id); - if (ret) - return ret; - return (*id)->ops->gen_new(context, id); + return krb5_cc_new_unique(context, ops->prefix, NULL, id); } -/* +/** * Generates a new unique ccache of `type` in `id'. If `type' is NULL, * the library chooses the default credential cache type. The supplied * `hint' (that can be NULL) is a string that the credential cache * type can use to base the name of the credential on, this is to make - * its easier for the user to differentiate the credentials. + * it easier for the user to differentiate the credentials. + * + * @return Returns 0 or an error code. * - * Returns 0 or an error code. + * @ingroup krb5_ccache */ krb5_error_code KRB5_LIB_FUNCTION krb5_cc_new_unique(krb5_context context, const char *type, const char *hint, krb5_ccache *id) { - const krb5_cc_ops *ops; - - if (type == NULL) - type = KRB5_DEFAULT_CCNAME; + const krb5_cc_ops *ops = KRB5_DEFAULT_CCTYPE; + krb5_error_code ret; - ops = krb5_cc_get_prefix_ops(context, type); - if (ops == NULL) { - krb5_set_error_string(context, "Credential cache type %s is unknown", - type); - return KRB5_CC_UNKNOWN_TYPE; + if (type) { + ops = krb5_cc_get_prefix_ops(context, type); + if (ops == NULL) { + krb5_set_error_string(context, + "Credential cache type %s is unknown", type); + return KRB5_CC_UNKNOWN_TYPE; + } } - return krb5_cc_gen_new(context, ops, id); + ret = _krb5_cc_allocate(context, ops, id); + if (ret) + return ret; + return (*id)->ops->gen_new(context, id); } -/* +/** * Return the name of the ccache `id' + * + * @ingroup krb5_ccache */ + const char* KRB5_LIB_FUNCTION krb5_cc_get_name(krb5_context context, krb5_ccache id) @@ -211,10 +236,13 @@ krb5_cc_get_name(krb5_context context, return id->ops->get_name(context, id); } -/* +/** * Return the type of the ccache `id'. + * + * @ingroup krb5_ccache */ + const char* KRB5_LIB_FUNCTION krb5_cc_get_type(krb5_context context, krb5_ccache id) @@ -222,12 +250,15 @@ krb5_cc_get_type(krb5_context context, return id->ops->prefix; } -/* +/** * Return the complete resolvable name the ccache `id' in `str´. * `str` should be freed with free(3). * Returns 0 or an error (and then *str is set to NULL). + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_get_full_name(krb5_context context, krb5_ccache id, @@ -257,10 +288,13 @@ krb5_cc_get_full_name(krb5_context context, return 0; } -/* +/** * Return krb5_cc_ops of a the ccache `id'. + * + * @ingroup krb5_ccache */ + const krb5_cc_ops * krb5_cc_get_ops(krb5_context context, krb5_ccache id) { @@ -348,6 +382,10 @@ environment_changed(krb5_context context) { const char *e; + /* if the cc name was set, don't change it */ + if (context->default_cc_name_set) + return 0; + if(issuid()) return 0; @@ -367,10 +405,13 @@ environment_changed(krb5_context context) return 0; } -/* +/** * Set the default cc name for `context' to `name'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_set_default_name(krb5_context context, const char *name) { @@ -392,14 +433,23 @@ krb5_cc_set_default_name(krb5_context context, const char *name) if (e == NULL) { e = krb5_config_get_string(context, NULL, "libdefaults", "default_cc_name", NULL); - if (e == NULL) - e = KRB5_DEFAULT_CCNAME; - ret = _krb5_expand_default_cc_name(context, e, &p); - if (ret) - return ret; + if (e) { + ret = _krb5_expand_default_cc_name(context, e, &p); + if (ret) + return ret; + } + if (e == NULL) { + const krb5_cc_ops *ops = KRB5_DEFAULT_CCTYPE; + ret = (*ops->default_name)(context, &p); + if (ret) + return ret; + } } - } else + context->default_cc_name_set = 0; + } else { p = strdup(name); + context->default_cc_name_set = 1; + } if (p == NULL) { krb5_set_error_string(context, "malloc - out of memory"); @@ -414,11 +464,16 @@ krb5_cc_set_default_name(krb5_context context, const char *name) return ret; } -/* +/** * Return a pointer to a context static string containing the default * ccache name. + * + * @return String to the default credential cache name. + * + * @ingroup krb5_ccache */ + const char* KRB5_LIB_FUNCTION krb5_cc_default_name(krb5_context context) { @@ -428,11 +483,15 @@ krb5_cc_default_name(krb5_context context) return context->default_cc_name; } -/* +/** * Open the default ccache in `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_default(krb5_context context, krb5_ccache *id) @@ -446,11 +505,15 @@ krb5_cc_default(krb5_context context, return krb5_cc_resolve(context, p, id); } -/* +/** * Create a new ccache in `id' for `primary_principal'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_initialize(krb5_context context, krb5_ccache id, @@ -460,11 +523,15 @@ krb5_cc_initialize(krb5_context context, } -/* +/** * Remove the ccache `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_destroy(krb5_context context, krb5_ccache id) @@ -476,11 +543,15 @@ krb5_cc_destroy(krb5_context context, return ret; } -/* +/** * Stop using the ccache `id' and free the related resources. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_close(krb5_context context, krb5_ccache id) @@ -491,11 +562,15 @@ krb5_cc_close(krb5_context context, return ret; } -/* +/** * Store `creds' in the ccache `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_store_cred(krb5_context context, krb5_ccache id, @@ -504,13 +579,17 @@ krb5_cc_store_cred(krb5_context context, return (*id->ops->store)(context, id, creds); } -/* +/** * Retrieve the credential identified by `mcreds' (and `whichfields') * from `id' in `creds'. 'creds' must be free by the caller using * krb5_free_cred_contents. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_retrieve_cred(krb5_context context, krb5_ccache id, @@ -526,7 +605,9 @@ krb5_cc_retrieve_cred(krb5_context context, mcreds, creds); } - krb5_cc_start_seq_get(context, id, &cursor); + ret = krb5_cc_start_seq_get(context, id, &cursor); + if (ret) + return ret; while((ret = krb5_cc_next_cred(context, id, &cursor, creds)) == 0){ if(krb5_compare_creds(context, whichfields, mcreds, creds)){ ret = 0; @@ -538,11 +619,15 @@ krb5_cc_retrieve_cred(krb5_context context, return ret; } -/* +/** * Return the principal of `id' in `principal'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_get_principal(krb5_context context, krb5_ccache id, @@ -551,12 +636,16 @@ krb5_cc_get_principal(krb5_context context, return (*id->ops->get_princ)(context, id, principal); } -/* +/** * Start iterating over `id', `cursor' is initialized to the * beginning. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_start_seq_get (krb5_context context, const krb5_ccache id, @@ -565,12 +654,16 @@ krb5_cc_start_seq_get (krb5_context context, return (*id->ops->get_first)(context, id, cursor); } -/* +/** * Retrieve the next cred pointed to by (`id', `cursor') in `creds' * and advance `cursor'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_next_cred (krb5_context context, const krb5_ccache id, @@ -580,7 +673,12 @@ krb5_cc_next_cred (krb5_context context, return (*id->ops->get_next)(context, id, cursor, creds); } -/* like krb5_cc_next_cred, but allow for selective retrieval */ +/** + * Like krb5_cc_next_cred, but allow for selective retrieval + * + * @ingroup krb5_ccache + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_next_cred_match(krb5_context context, @@ -601,10 +699,13 @@ krb5_cc_next_cred_match(krb5_context context, } } -/* +/** * Destroy the cursor `cursor'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_end_seq_get (krb5_context context, const krb5_ccache id, @@ -613,10 +714,13 @@ krb5_cc_end_seq_get (krb5_context context, return (*id->ops->end_get)(context, id, cursor); } -/* +/** * Remove the credential identified by `cred', `which' from `id'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_remove_cred(krb5_context context, krb5_ccache id, @@ -632,10 +736,13 @@ krb5_cc_remove_cred(krb5_context context, return (*id->ops->remove_cred)(context, id, which, cred); } -/* +/** * Set the flags of `id' to `flags'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_set_flags(krb5_context context, krb5_ccache id, @@ -644,10 +751,13 @@ krb5_cc_set_flags(krb5_context context, return (*id->ops->set_flags)(context, id, flags); } -/* +/** * Copy the contents of `from' to `to'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_copy_cache_match(krb5_context context, const krb5_ccache from, @@ -689,6 +799,13 @@ krb5_cc_copy_cache_match(krb5_context context, return ret; } +/** + * Just like krb5_cc_copy_cache_match, but copy everything. + * + * @ingroup krb5_ccache + */ + + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_copy_cache(krb5_context context, const krb5_ccache from, @@ -697,10 +814,13 @@ krb5_cc_copy_cache(krb5_context context, return krb5_cc_copy_cache_match(context, from, to, 0, NULL, NULL); } -/* +/** * Return the version of `id'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_get_version(krb5_context context, const krb5_ccache id) @@ -711,23 +831,30 @@ krb5_cc_get_version(krb5_context context, return 0; } -/* +/** * Clear `mcreds' so it can be used with krb5_cc_retrieve_cred + * + * @ingroup krb5_ccache */ + void KRB5_LIB_FUNCTION krb5_cc_clear_mcred(krb5_creds *mcred) { memset(mcred, 0, sizeof(*mcred)); } -/* +/** * Get the cc ops that is registered in `context' to handle the * `prefix'. `prefix' can be a complete credential cache name or a * prefix, the function will only use part up to the first colon (:) - * if there is one. Returns NULL if ops not found. + * if there is one. + * Returns NULL if ops not found. + * + * @ingroup krb5_ccache */ + const krb5_cc_ops * krb5_cc_get_prefix_ops(krb5_context context, const char *prefix) { @@ -761,12 +888,16 @@ struct krb5_cc_cache_cursor_data { krb5_cc_cursor cursor; }; -/* +/** * Start iterating over all caches of `type'. If `type' is NULL, the * default type is * used. `cursor' is initialized to the beginning. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_get_first (krb5_context context, const char *type, @@ -807,12 +938,16 @@ krb5_cc_cache_get_first (krb5_context context, return ret; } -/* +/** * Retrieve the next cache pointed to by (`cursor') in `id' * and advance `cursor'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_next (krb5_context context, krb5_cc_cache_cursor cursor, @@ -821,10 +956,15 @@ krb5_cc_cache_next (krb5_context context, return cursor->ops->get_cache_next(context, cursor->cursor, id); } -/* +/** * Destroy the cursor `cursor'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_end_seq_get (krb5_context context, krb5_cc_cache_cursor cursor) @@ -836,14 +976,18 @@ krb5_cc_cache_end_seq_get (krb5_context context, return ret; } -/* +/** * Search for a matching credential cache of type `type' that have the * `principal' as the default principal. If NULL is used for `type', * the default type is used. On success, `id' needs to be freed with - * krb5_cc_close or krb5_cc_destroy. On failure, error code is - * returned and `id' is set to NULL. + * krb5_cc_close or krb5_cc_destroy. + * + * @return On failure, error code is returned and `id' is set to NULL. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_match (krb5_context context, krb5_principal client, @@ -895,3 +1039,35 @@ krb5_cc_cache_match (krb5_context context, return 0; } +/** + * Move the content from one credential cache to another. The + * operation is an atomic switch. + * + * @param context a Keberos context + * @param from the credential cache to move the content from + * @param to the credential cache to move the content to + + * @return On sucess, from is freed. On failure, error code is + * returned and from and to are both still allocated. + * + * @ingroup krb5_ccache + */ + +krb5_error_code +krb5_cc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_error_code ret; + + if (strcmp(from->ops->prefix, to->ops->prefix) != 0) { + krb5_set_error_string(context, "Moving credentials between diffrent " + "types not yet supported"); + return KRB5_CC_NOSUPP; + } + + ret = (*to->ops->move)(context, from, to); + if (ret == 0) { + memset(from, 0, sizeof(*from)); + free(from); + } + return ret; +} diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index b54e293a602..256783310e9 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -34,12 +34,19 @@ #include "krb5_locl.h" #include <com_err.h> -RCSID("$Id: context.c 19107 2006-11-24 14:24:33Z lha $"); +RCSID("$Id: context.c 22293 2007-12-14 05:25:59Z lha $"); #define INIT_FIELD(C, T, E, D, F) \ (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ "libdefaults", F, NULL) +#define INIT_FLAG(C, O, V, D, F) \ + do { \ + if (krb5_config_get_bool_default((C), NULL, (D),"libdefaults", F, NULL)) { \ + (C)->O |= V; \ + } \ + } while(0) + /* * Set the list of etypes `ret_etypes' from the configuration variable * `name' @@ -181,11 +188,28 @@ init_context_from_config_file(krb5_context context) INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size"); - INIT_FIELD(context, bool, dns_canonicalize_hostname, TRUE, "dns_canonicalize_hostname"); + INIT_FLAG(context, flags, KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME, TRUE, "dns_canonicalize_hostname"); + INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac"); context->default_cc_name = NULL; + context->default_cc_name_set = 0; return 0; } +/** + * Initializes the context structure and reads the configuration file + * /etc/krb5.conf. The structure should be freed by calling + * krb5_free_context() when it is no longer being used. + * + * @param context pointer to returned context + * + * @return Returns 0 to indicate success. Otherwise an errno code is + * returned. Failure means either that something bad happened during + * initialization (typically ENOMEM) or that Kerberos should not be + * used ENXIO. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_init_context(krb5_context *context) { @@ -246,11 +270,21 @@ out: return ret; } +/** + * Frees the krb5_context allocated by krb5_init_context(). + * + * @param context context to be freed. + * + * @ingroup krb5 +*/ + void KRB5_LIB_FUNCTION krb5_free_context(krb5_context context) { if (context->default_cc_name) free(context->default_cc_name); + if (context->default_cc_name_env) + free(context->default_cc_name_env); free(context->etypes); free(context->etypes_des); krb5_free_host_realm (context, context->default_realms); @@ -272,6 +306,18 @@ krb5_free_context(krb5_context context) free(context); } +/** + * Reinit the context from a new set of filenames. + * + * @param context context to add configuration too. + * @param filenames array of filenames, end of list is indicated with a NULL filename. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_config_files(krb5_context context, char **filenames) { @@ -324,7 +370,7 @@ add_file(char ***pfilenames, int *len, char *file) } /* - * `pq' isn't free, its up the the caller + * `pq' isn't free, it's up the the caller */ krb5_error_code KRB5_LIB_FUNCTION @@ -380,6 +426,18 @@ krb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp) return 0; } +/** + * Prepend the filename to the global configuration list. + * + * @param filelist a filename to add to the default list of filename + * @param pfilenames return array of filenames, should be freed with krb5_free_config_files(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_prepend_config_files_default(const char *filelist, char ***pfilenames) { @@ -399,6 +457,17 @@ krb5_prepend_config_files_default(const char *filelist, char ***pfilenames) return 0; } +/** + * Get the global configuration list. + * + * @param pfilenames return array of filenames, should be freed with krb5_free_config_files(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_get_default_config_files(char ***pfilenames) { @@ -414,6 +483,17 @@ krb5_get_default_config_files(char ***pfilenames) return krb5_prepend_config_files(files, NULL, pfilenames); } +/** + * Free a list of configuration files. + * + * @param filenames list to be freed. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_free_config_files(char **filenames) { @@ -423,12 +503,17 @@ krb5_free_config_files(char **filenames) free(filenames); } -/* +/** * Returns the list of Kerberos encryption types sorted in order of - * most preferred to least preferred encryption type. The array ends - * with ETYPE_NULL. Note that some encryption types might be - * disabled, so you need to check with krb5_enctype_valid() before - * using the encryption type. + * most preferred to least preferred encryption type. Note that some + * encryption types might be disabled, so you need to check with + * krb5_enctype_valid() before using the encryption type. + * + * @return list of enctypes, terminated with ETYPE_NULL. Its a static + * array completed into the Kerberos library so the content doesn't + * need to be freed. + * + * @ingroup krb5 */ const krb5_enctype * KRB5_LIB_FUNCTION @@ -479,6 +564,19 @@ default_etypes(krb5_context context, krb5_enctype **etype) return 0; } +/** + * Set the default encryption types that will be use in communcation + * with the KDC, clients and servers. + * + * @param context Kerberos 5 context. + * @param etypes Encryption types, array terminated with ETYPE_NULL (0). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_default_in_tkt_etypes(krb5_context context, const krb5_enctype *etypes) @@ -507,6 +605,19 @@ krb5_set_default_in_tkt_etypes(krb5_context context, return 0; } +/** + * Get the default encryption types that will be use in communcation + * with the KDC, clients and servers. + * + * @param context Kerberos 5 context. + * @param etypes Encryption types, array terminated with + * ETYPE_NULL(0), caller should free array with krb5_xfree(): + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ krb5_error_code KRB5_LIB_FUNCTION krb5_get_default_in_tkt_etypes(krb5_context context, @@ -534,6 +645,18 @@ krb5_get_default_in_tkt_etypes(krb5_context context, return 0; } +/** + * Return the error string for the error code. The caller must not + * free the string. + * + * @param context Kerberos 5 context. + * @param code Kerberos error code. + * + * @return the error message matching code + * + * @ingroup krb5 + */ + const char* KRB5_LIB_FUNCTION krb5_get_err_text(krb5_context context, krb5_error_code code) { @@ -547,6 +670,14 @@ krb5_get_err_text(krb5_context context, krb5_error_code code) return p; } +/** + * Init the built-in ets in the Kerberos library. + * + * @param context kerberos context to add the ets too + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_init_ets(krb5_context context) { @@ -561,18 +692,50 @@ krb5_init_ets(krb5_context context) } } +/** + * Make the kerberos library default to the admin KDC. + * + * @param context Kerberos 5 context. + * @param flag boolean flag to select if the use the admin KDC or not. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag) { context->use_admin_kdc = flag; } +/** + * Make the kerberos library default to the admin KDC. + * + * @param context Kerberos 5 context. + * + * @return boolean flag to telling the context will use admin KDC as the default KDC. + * + * @ingroup krb5 + */ + krb5_boolean KRB5_LIB_FUNCTION krb5_get_use_admin_kdc (krb5_context context) { return context->use_admin_kdc; } +/** + * Add extra address to the address list that the library will add to + * the client's address list when communicating with the KDC. + * + * @param context Kerberos 5 context. + * @param addresses addreses to add + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses) { @@ -584,6 +747,19 @@ krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses) return krb5_set_extra_addresses(context, addresses); } +/** + * Set extra address to the address list that the library will add to + * the client's address list when communicating with the KDC. + * + * @param context Kerberos 5 context. + * @param addresses addreses to set + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses) { @@ -607,6 +783,19 @@ krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses) return krb5_copy_addresses(context, addresses, context->extra_addresses); } +/** + * Get extra address to the address list that the library will add to + * the client's address list when communicating with the KDC. + * + * @param context Kerberos 5 context. + * @param addresses addreses to set + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses) { @@ -617,6 +806,19 @@ krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses) return krb5_copy_addresses(context,context->extra_addresses, addresses); } +/** + * Add extra addresses to ignore when fetching addresses from the + * underlaying operating system. + * + * @param context Kerberos 5 context. + * @param addresses addreses to ignore + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses) { @@ -628,6 +830,19 @@ krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses) return krb5_set_ignore_addresses(context, addresses); } +/** + * Set extra addresses to ignore when fetching addresses from the + * underlaying operating system. + * + * @param context Kerberos 5 context. + * @param addresses addreses to ignore + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses) { @@ -650,6 +865,19 @@ krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses) return krb5_copy_addresses(context, addresses, context->ignore_addresses); } +/** + * Get extra addresses to ignore when fetching addresses from the + * underlaying operating system. + * + * @param context Kerberos 5 context. + * @param addresses list addreses ignored + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses) { @@ -660,6 +888,18 @@ krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses) return krb5_copy_addresses(context, context->ignore_addresses, addresses); } +/** + * Set version of fcache that the library should use. + * + * @param context Kerberos 5 context. + * @param version version number. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_fcache_version(krb5_context context, int version) { @@ -667,6 +907,18 @@ krb5_set_fcache_version(krb5_context context, int version) return 0; } +/** + * Get version of fcache that the library should use. + * + * @param context Kerberos 5 context. + * @param version version number. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_get_fcache_version(krb5_context context, int *version) { @@ -674,6 +926,15 @@ krb5_get_fcache_version(krb5_context context, int *version) return 0; } +/** + * Runtime check if the Kerberos library was complied with thread support. + * + * @return TRUE if the library was compiled with thread support, FALSE if not. + * + * @ingroup krb5 + */ + + krb5_boolean KRB5_LIB_FUNCTION krb5_is_thread_safe(void) { @@ -684,18 +945,52 @@ krb5_is_thread_safe(void) #endif } +/** + * Set if the library should use DNS to canonicalize hostnames. + * + * @param context Kerberos 5 context. + * @param flag if its dns canonicalizion is used or not. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_set_dns_canonicalize_hostname (krb5_context context, krb5_boolean flag) { - context->dns_canonicalize_hostname = flag; + if (flag) + context->flags |= KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME; + else + context->flags &= ~KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME; } +/** + * Get if the library uses DNS to canonicalize hostnames. + * + * @param context Kerberos 5 context. + * + * @return return non zero if the library uses DNS to canonicalize hostnames. + * + * @ingroup krb5 + */ + krb5_boolean KRB5_LIB_FUNCTION krb5_get_dns_canonicalize_hostname (krb5_context context) { - return context->dns_canonicalize_hostname; + return (context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) ? 1 : 0; } +/** + * Get current offset in time to the KDC. + * + * @param context Kerberos 5 context. + * @param sec seconds part of offset. + * @param usec micro seconds part of offset. + * + * @return return non zero if the library uses DNS to canonicalize hostnames. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) { @@ -706,12 +1001,31 @@ krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) return 0; } +/** + * Get max time skew allowed. + * + * @param context Kerberos 5 context. + * + * @return timeskew in seconds. + * + * @ingroup krb5 + */ + time_t KRB5_LIB_FUNCTION krb5_get_max_time_skew (krb5_context context) { return context->max_skew; } +/** + * Set max time skew allowed. + * + * @param context Kerberos 5 context. + * @param t timeskew in seconds. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_set_max_time_skew (krb5_context context, time_t t) { diff --git a/source4/heimdal/lib/krb5/convert_creds.c b/source4/heimdal/lib/krb5/convert_creds.c index 1d1b4d70706..b2af0187eac 100644 --- a/source4/heimdal/lib/krb5/convert_creds.c +++ b/source4/heimdal/lib/krb5/convert_creds.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: convert_creds.c 14897 2005-04-23 19:40:57Z lha $"); +RCSID("$Id: convert_creds.c 22050 2007-11-11 11:20:46Z lha $"); #include "krb5-v4compat.h" @@ -42,10 +42,20 @@ check_ticket_flags(TicketFlags f) return 0; /* maybe add some more tests here? */ } -/* Convert the v5 credentials in `in_cred' to v4-dito in `v4creds'. - * This is done by sending them to the 524 function in the KDC. If +/** + * Convert the v5 credentials in in_cred to v4-dito in v4creds. This + * is done by sending them to the 524 function in the KDC. If * `in_cred' doesn't contain a DES session key, then a new one is * gotten from the KDC and stored in the cred cache `ccache'. + * + * @param context Kerberos 5 context. + * @param in_cred the credential to convert + * @param v4creds the converted credential + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5_v4compat */ krb5_error_code KRB5_LIB_FUNCTION @@ -134,6 +144,21 @@ out2: return ret; } +/** + * Convert the v5 credentials in in_cred to v4-dito in v4creds, + * check the credential cache ccache before checking with the KDC. + * + * @param context Kerberos 5 context. + * @param ccache credential cache used to check for des-ticket. + * @param in_cred the credential to convert + * @param v4creds the converted credential + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5_v4compat + */ + krb5_error_code KRB5_LIB_FUNCTION krb524_convert_creds_kdc_ccache(krb5_context context, krb5_ccache ccache, diff --git a/source4/heimdal/lib/krb5/copy_host_realm.c b/source4/heimdal/lib/krb5/copy_host_realm.c index 4e668c2a14f..8c4f39b4ac4 100644 --- a/source4/heimdal/lib/krb5/copy_host_realm.c +++ b/source4/heimdal/lib/krb5/copy_host_realm.c @@ -33,10 +33,19 @@ #include "krb5_locl.h" -RCSID("$Id: copy_host_realm.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: copy_host_realm.c 22057 2007-11-11 15:13:13Z lha $"); -/* +/** * Copy the list of realms from `from' to `to'. + * + * @param context Kerberos 5 context. + * @param from list of realms to copy from. + * @param to list of realms to copy to, free list of krb5_free_host_realm(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 */ krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/creds.c b/source4/heimdal/lib/krb5/creds.c index d4d83162f1e..17ef46dfa3b 100644 --- a/source4/heimdal/lib/krb5/creds.c +++ b/source4/heimdal/lib/krb5/creds.c @@ -33,15 +33,30 @@ #include "krb5_locl.h" -RCSID("$Id: creds.c 15167 2005-05-18 04:21:57Z lha $"); +RCSID("$Id: creds.c 22062 2007-11-11 15:41:50Z lha $"); + +#undef __attribute__ +#define __attribute__(X) /* keep this for compatibility with older code */ -krb5_error_code KRB5_LIB_FUNCTION +krb5_error_code KRB5_LIB_FUNCTION __attribute__((deprecated)) krb5_free_creds_contents (krb5_context context, krb5_creds *c) { return krb5_free_cred_contents (context, c); } +/** + * Free content of krb5_creds. + * + * @param context Kerberos 5 context. + * @param c krb5_creds to free. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_free_cred_contents (krb5_context context, krb5_creds *c) { @@ -58,6 +73,19 @@ krb5_free_cred_contents (krb5_context context, krb5_creds *c) return 0; } +/** + * Copy content of krb5_creds. + * + * @param context Kerberos 5 context. + * @param incred source credential + * @param c destination credential, free with krb5_free_cred_contents(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_copy_creds_contents (krb5_context context, const krb5_creds *incred, @@ -102,6 +130,19 @@ fail: return ret; } +/** + * Copy krb5_creds. + * + * @param context Kerberos 5 context. + * @param incred source credential + * @param outcred destination credential, free with krb5_free_creds(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_copy_creds (krb5_context context, const krb5_creds *incred, @@ -119,6 +160,18 @@ krb5_copy_creds (krb5_context context, return krb5_copy_creds_contents (context, incred, c); } +/** + * Free krb5_creds. + * + * @param context Kerberos 5 context. + * @param c krb5_creds to free. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_free_creds (krb5_context context, krb5_creds *c) { @@ -127,15 +180,7 @@ krb5_free_creds (krb5_context context, krb5_creds *c) return 0; } -/* XXX these do not belong here */ -static krb5_boolean -krb5_data_equal(const krb5_data *a, const krb5_data *b) -{ - if(a->length != b->length) - return FALSE; - return memcmp(a->data, b->data, a->length) == 0; -} - +/* XXX this do not belong here */ static krb5_boolean krb5_times_equal(const krb5_times *a, const krb5_times *b) { @@ -145,9 +190,18 @@ krb5_times_equal(const krb5_times *a, const krb5_times *b) a->renew_till == b->renew_till; } -/* +/** * Return TRUE if `mcreds' and `creds' are equal (`whichfields' * determines what equal means). + * + * @param context Kerberos 5 context. + * @param whichfields which fields to compare. + * @param mcreds cred to compare with. + * @param creds cred to compare with. + * + * @return return TRUE if mcred and creds are equal, FALSE if not. + * + * @ingroup krb5 */ krb5_boolean KRB5_LIB_FUNCTION @@ -201,11 +255,11 @@ krb5_compare_creds(krb5_context context, krb5_flags whichfields, for(i = 0; match && i < mcreds->authdata.len; i++) match = (mcreds->authdata.val[i].ad_type == creds->authdata.val[i].ad_type) && - krb5_data_equal(&mcreds->authdata.val[i].ad_data, - &creds->authdata.val[i].ad_data); + (krb5_data_cmp(&mcreds->authdata.val[i].ad_data, + &creds->authdata.val[i].ad_data) == 0); } if (match && (whichfields & KRB5_TC_MATCH_2ND_TKT)) - match = krb5_data_equal(&mcreds->second_ticket, &creds->second_ticket); + match = (krb5_data_cmp(&mcreds->second_ticket, &creds->second_ticket) == 0); if (match && (whichfields & KRB5_TC_MATCH_IS_SKEY)) match = ((mcreds->second_ticket.length == 0) == diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 12f75d0bcde..2e634909468 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c 21130 2007-06-18 20:45:21Z lha $"); +RCSID("$Id: crypto.c 22200 2007-12-07 13:48:01Z lha $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -184,7 +184,7 @@ krb5_DES_schedule(krb5_context context, #ifdef ENABLE_AFS_STRING_TO_KEY /* This defines the Andrew string_to_key function. It accepts a password - * string as input and converts its via a one-way encryption algorithm to a DES + * string as input and converts it via a one-way encryption algorithm to a DES * encryption key. It is compatible with the original Andrew authentication * service password database. */ @@ -425,6 +425,7 @@ DES3_string_to_key(krb5_context context, size_t len; unsigned char tmp[24]; DES_cblock keys[3]; + krb5_error_code ret; len = password.length + salt.saltvalue.length; str = malloc(len); @@ -439,7 +440,13 @@ DES3_string_to_key(krb5_context context, DES_key_schedule s[3]; int i; - _krb5_n_fold(str, len, tmp, 24); + ret = _krb5_n_fold(str, len, tmp, 24); + if (ret) { + memset(str, 0, len); + free(str); + krb5_set_error_string(context, "out of memory"); + return ret; + } for(i = 0; i < 3; i++){ memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); @@ -557,12 +564,14 @@ ARCFOUR_string_to_key(krb5_context context, size_t len; int i; MD4_CTX m; + krb5_error_code ret; len = 2 * password.length; s = malloc (len); if (len != 0 && s == NULL) { krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; + ret = ENOMEM; + goto out; } for (p = s, i = 0; i < password.length; ++i) { *p++ = ((char *)password.data)[i]; @@ -571,11 +580,17 @@ ARCFOUR_string_to_key(krb5_context context, MD4_Init (&m); MD4_Update (&m, s, len); key->keytype = enctype; - krb5_data_alloc (&key->keyvalue, 16); + ret = krb5_data_alloc (&key->keyvalue, 16); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + goto out; + } MD4_Final (key->keyvalue.data, &m); memset (s, 0, len); + ret = 0; +out: free (s); - return 0; + return ret; } /* @@ -1829,7 +1844,9 @@ create_checksum (krb5_context context, } else dkey = NULL; result->cksumtype = ct->type; - krb5_data_alloc(&result->checksum, ct->checksumsize); + ret = krb5_data_alloc(&result->checksum, ct->checksumsize); + if (ret) + return (ret); (*ct->checksum)(context, dkey, data, len, usage, result); return 0; } @@ -2751,6 +2768,7 @@ krb5_enctype_to_string(krb5_context context, if(e == NULL) { krb5_set_error_string (context, "encryption type %d not supported", etype); + *string = NULL; return KRB5_PROG_ETYPE_NOSUPP; } *string = strdup(e->name); @@ -3525,15 +3543,19 @@ derive_key(krb5_context context, ret = _key_schedule(context, key); if(ret) return ret; - if(et->blocksize * 8 < kt->bits || - len != et->blocksize) { + if(et->blocksize * 8 < kt->bits || len != et->blocksize) { nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8); k = malloc(nblocks * et->blocksize); if(k == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - _krb5_n_fold(constant, len, k, et->blocksize); + ret = _krb5_n_fold(constant, len, k, et->blocksize); + if (ret) { + free(k); + krb5_set_error_string(context, "out of memory"); + return ret; + } for(i = 0; i < nblocks; i++) { if(i > 0) memcpy(k + i * et->blocksize, @@ -3559,7 +3581,12 @@ derive_key(krb5_context context, krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - _krb5_n_fold(c, len, k, res_len); + ret = _krb5_n_fold(c, len, k, res_len); + if (ret) { + free(k); + krb5_set_error_string(context, "out of memory"); + return ret; + } free(c); } @@ -3821,7 +3848,12 @@ krb5_string_to_key_derived(krb5_context context, krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } - _krb5_n_fold(str, len, tmp, keylen); + ret = _krb5_n_fold(str, len, tmp, keylen); + if (ret) { + free(tmp); + krb5_set_error_string(context, "out of memory"); + return ret; + } kd.schedule = NULL; DES3_postproc (context, tmp, keylen, &kd); /* XXX */ memset(tmp, 0, keylen); @@ -4122,7 +4154,7 @@ main() d = _new_derived_key(crypto, usage); if(d == NULL) - return ENOMEM; + krb5_errx(context, 1, "_new_derived_key failed"); krb5_copy_keyblock(context, crypto->key.key, &d->key); _krb5_put_int(constant, usage, 4); derive_key(context, crypto->et, d, constant, sizeof(constant)); @@ -4148,11 +4180,10 @@ main() "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */ key.keyvalue.length = 4; - d = calloc(1, sizeof(*d)); - + d = ecalloc(1, sizeof(*d)); d->key = &key; res.checksum.length = 20; - res.checksum.data = malloc(res.checksum.length); + res.checksum.data = emalloc(res.checksum.length); SP_HMAC_SHA1_checksum(context, d, data, 28, &res); return 0; diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c index 2ece85bdb32..eda1a8b2598 100644 --- a/source4/heimdal/lib/krb5/data.c +++ b/source4/heimdal/lib/krb5/data.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,15 @@ #include "krb5_locl.h" -RCSID("$Id: data.c 20039 2007-01-23 20:34:01Z lha $"); +RCSID("$Id: data.c 22064 2007-11-11 16:28:14Z lha $"); + +/** + * Reset the (potentially uninitalized) krb5_data structure. + * + * @param p krb5_data to reset. + * + * @ingroup krb5 + */ void KRB5_LIB_FUNCTION krb5_data_zero(krb5_data *p) @@ -42,6 +50,15 @@ krb5_data_zero(krb5_data *p) p->data = NULL; } +/** + * Free the content of krb5_data structure, its ok to free a zeroed + * structure. When done, the structure will be zeroed. + * + * @param p krb5_data to free. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_data_free(krb5_data *p) { @@ -50,12 +67,30 @@ krb5_data_free(krb5_data *p) krb5_data_zero(p); } +/** + * Same as krb5_data_free(). + * + * @param context Kerberos 5 context. + * @param data krb5_data to free. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_free_data_contents(krb5_context context, krb5_data *data) { krb5_data_free(data); } +/** + * Free krb5_data (and its content). + * + * @param context Kerberos 5 context. + * @param p krb5_data to free. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_free_data(krb5_context context, krb5_data *p) @@ -64,6 +99,18 @@ krb5_free_data(krb5_context context, free(p); } +/** + * Allocate data of and krb5_data. + * + * @param p krb5_data to free. + * @param len size to allocate. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_data_alloc(krb5_data *p, int len) { @@ -74,6 +121,18 @@ krb5_data_alloc(krb5_data *p, int len) return 0; } +/** + * Grow (or shrink) the content of krb5_data to a new size. + * + * @param p krb5_data to free. + * @param len new size. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_data_realloc(krb5_data *p, int len) { @@ -86,6 +145,19 @@ krb5_data_realloc(krb5_data *p, int len) return 0; } +/** + * Copy the data of len into the krb5_data. + * + * @param p krb5_data to copy into. + * @param data data to copy.. + * @param len new size. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_data_copy(krb5_data *p, const void *data, size_t len) { @@ -99,6 +171,19 @@ krb5_data_copy(krb5_data *p, const void *data, size_t len) return 0; } +/** + * Copy the data into a newly allocated krb5_data. + * + * @param context Kerberos 5 context. + * @param indata the krb5_data data to copy + * @param outdata new krb5_date to copy too. Free with krb5_free_data(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_copy_data(krb5_context context, const krb5_data *indata, @@ -119,6 +204,17 @@ krb5_copy_data(krb5_context context, return ret; } +/** + * Compare to data. + * + * @param data1 krb5_data to compare + * @param data2 krb5_data to compare + * + * @return return the same way as memcmp(), useful when sorting. + * + * @ingroup krb5 + */ + int KRB5_LIB_FUNCTION krb5_data_cmp(const krb5_data *data1, const krb5_data *data2) { diff --git a/source4/heimdal/lib/krb5/eai_to_heim_errno.c b/source4/heimdal/lib/krb5/eai_to_heim_errno.c index c6b5cfb18bb..19315cea867 100644 --- a/source4/heimdal/lib/krb5/eai_to_heim_errno.c +++ b/source4/heimdal/lib/krb5/eai_to_heim_errno.c @@ -33,12 +33,17 @@ #include <krb5_locl.h> -RCSID("$Id: eai_to_heim_errno.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: eai_to_heim_errno.c 22065 2007-11-11 16:41:06Z lha $"); -/* - * convert the getaddrinfo error code in `eai_errno' into a - * krb5_error_code. `system_error' should have the value of the errno - * after the failed call. +/** + * Convert the getaddrinfo() error code to a Kerberos et error code. + * + * @param eai_errno contains the error code from getaddrinfo(). + * @param system_error should have the value of errno after the failed getaddrinfo(). + * + * @return Kerberos error code representing the EAI errors. + * + * @ingroup krb5_error */ krb5_error_code KRB5_LIB_FUNCTION @@ -78,6 +83,17 @@ krb5_eai_to_heim_errno(int eai_errno, int system_error) } } +/** + * Convert the gethostname() error code (h_error) to a Kerberos et + * error code. + * + * @param eai_errno contains the error code from gethostname(). + * + * @return Kerberos error code representing the gethostname errors. + * + * @ingroup krb5_error + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_h_errno_to_heim_errno(int eai_errno) { diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c index 1ba64944872..ff6e98a3dca 100644 --- a/source4/heimdal/lib/krb5/error_string.c +++ b/source4/heimdal/lib/krb5/error_string.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: error_string.c 16746 2006-02-16 07:49:23Z lha $"); +RCSID("$Id: error_string.c 22142 2007-12-04 16:56:02Z lha $"); #undef __attribute__ #define __attribute__(X) @@ -86,14 +86,26 @@ krb5_vset_error_string(krb5_context context, const char *fmt, va_list args) return 0; } +/** + * Return the error message in context. On error or no error string, + * the function returns NULL. + * + * @param context Kerberos 5 context + * + * @return an error string, needs to be freed with + * krb5_free_error_string(). The functions return NULL on error. + * + * @ingroup krb5_error + */ + char * KRB5_LIB_FUNCTION krb5_get_error_string(krb5_context context) { - char *ret; + char *ret = NULL; HEIMDAL_MUTEX_lock(context->mutex); - ret = context->error_string; - context->error_string = NULL; + if (context->error_string) + ret = strdup(context->error_string); HEIMDAL_MUTEX_unlock(context->mutex); return ret; } @@ -108,6 +120,19 @@ krb5_have_error_string(krb5_context context) return str != NULL; } +/** + * Return the error message for `code' in context. On error the + * function returns NULL. + * + * @param context Kerberos 5 context + * @param code Error code related to the error + * + * @return an error string, needs to be freed with + * krb5_free_error_string(). The functions return NULL on error. + * + * @ingroup krb5_error + */ + char * KRB5_LIB_FUNCTION krb5_get_error_message(krb5_context context, krb5_error_code code) { diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c index b2b410269ed..28e39afb42f 100644 --- a/source4/heimdal/lib/krb5/expand_hostname.c +++ b/source4/heimdal/lib/krb5/expand_hostname.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: expand_hostname.c 18906 2006-11-04 03:34:57Z lha $"); +RCSID("$Id: expand_hostname.c 22229 2007-12-08 21:40:59Z lha $"); static krb5_error_code copy_hostname(krb5_context context, @@ -62,7 +62,7 @@ krb5_expand_hostname (krb5_context context, struct addrinfo *ai, *a, hints; int error; - if (!context->dns_canonicalize_hostname) + if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0) return copy_hostname (context, orig_hostname, new_hostname); memset (&hints, 0, sizeof(hints)); @@ -127,7 +127,7 @@ krb5_expand_hostname_realms (krb5_context context, int error; krb5_error_code ret = 0; - if (!context->dns_canonicalize_hostname) + if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0) return vanilla_hostname (context, orig_hostname, new_hostname, realms); diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c index 864efa8d7d1..484df059abd 100644 --- a/source4/heimdal/lib/krb5/fcache.c +++ b/source4/heimdal/lib/krb5/fcache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: fcache.c 19379 2006-12-15 21:35:52Z lha $"); +RCSID("$Id: fcache.c 22517 2008-01-24 11:45:51Z lha $"); typedef struct krb5_fcache{ char *filename; @@ -108,7 +108,7 @@ int _krb5_xunlock(krb5_context context, int fd) { int ret; -#ifdef HAVE_FCNTL_LOCK +#ifdef HAVE_FCNTL struct flock l; l.l_start = 0; l.l_len = 0; @@ -463,9 +463,13 @@ init_fcc (krb5_context context, krb5_storage_set_eof_code(sp, KRB5_CC_END); ret = krb5_ret_int8(sp, &pvno); if(ret != 0) { - if(ret == KRB5_CC_END) - ret = ENOENT; /* empty file */ - krb5_clear_error_string(context); + if(ret == KRB5_CC_END) { + krb5_set_error_string(context, "Empty credential cache file: %s", + FILENAME(id)); + ret = ENOENT; + } else + krb5_set_error_string(context, "Error reading pvno in " + "cache file: %s", FILENAME(id)); goto out; } if(pvno != 5) { @@ -476,7 +480,8 @@ init_fcc (krb5_context context, } ret = krb5_ret_int8(sp, &tag); /* should not be host byte order */ if(ret != 0) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading tag in " + "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } @@ -489,7 +494,8 @@ init_fcc (krb5_context context, ret = krb5_ret_int16 (sp, &length); if(ret) { ret = KRB5_CC_FORMAT; - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading tag length in " + "cache file: %s", FILENAME(id)); goto out; } while(length > 0) { @@ -499,13 +505,15 @@ init_fcc (krb5_context context, ret = krb5_ret_int16 (sp, &dtag); if(ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading dtag in " + "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } ret = krb5_ret_int16 (sp, &data_len); if(ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading dlength in " + "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } @@ -513,13 +521,15 @@ init_fcc (krb5_context context, case FCC_TAG_DELTATIME : ret = krb5_ret_int32 (sp, &context->kdc_sec_offset); if(ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading kdc_sec in " + "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } ret = krb5_ret_int32 (sp, &context->kdc_usec_offset); if(ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading kdc_usec in " + "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } @@ -528,7 +538,9 @@ init_fcc (krb5_context context, for (i = 0; i < data_len; ++i) { ret = krb5_ret_int8 (sp, &dummy); if(ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading unknown " + "tag in cache file: %s", + FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } @@ -755,6 +767,95 @@ fcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) return 0; } +static krb5_error_code +fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_error_code ret = 0; + + ret = rename(FILENAME(from), FILENAME(to)); + if (ret && errno != EXDEV) { + ret = errno; + krb5_set_error_string(context, + "Rename of file from %s to %s failed: %s", + FILENAME(from), FILENAME(to), + strerror(ret)); + return ret; + } else if (ret && errno == EXDEV) { + /* make a copy and delete the orignal */ + krb5_ssize_t sz1, sz2; + int fd1, fd2; + char buf[BUFSIZ]; + + ret = fcc_open(context, from, &fd1, O_RDONLY | O_BINARY, 0); + if(ret) + return ret; + + unlink(FILENAME(to)); + + ret = fcc_open(context, to, &fd2, + O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600); + if(ret) + goto out1; + + while((sz1 = read(fd1, buf, sizeof(buf))) > 0) { + sz2 = write(fd2, buf, sz1); + if (sz1 != sz2) { + ret = EIO; + krb5_set_error_string(context, + "Failed to write data from one file " + "credential cache to the other"); + goto out2; + } + } + if (sz1 < 0) { + ret = EIO; + krb5_set_error_string(context, + "Failed to read data from one file " + "credential cache to the other"); + goto out2; + } + erase_file(FILENAME(from)); + + out2: + fcc_unlock(context, fd2); + close(fd2); + + out1: + fcc_unlock(context, fd1); + close(fd1); + + if (ret) { + erase_file(FILENAME(to)); + return ret; + } + } + + /* make sure ->version is uptodate */ + { + krb5_storage *sp; + int fd; + ret = init_fcc (context, to, &sp, &fd); + krb5_storage_free(sp); + fcc_unlock(context, fd); + close(fd); + } + return ret; +} + +static krb5_error_code +fcc_default_name(krb5_context context, char **str) +{ + return _krb5_expand_default_cc_name(context, + KRB5_DEFAULT_CCNAME_FILE, + str); +} + +/** + * Variable containing the FILE based credential cache implemention. + * + * @ingroup krb5_ccache + */ + const krb5_cc_ops krb5_fcc_ops = { "FILE", fcc_get_name, @@ -774,5 +875,7 @@ const krb5_cc_ops krb5_fcc_ops = { fcc_get_version, fcc_get_cache_first, fcc_get_cache_next, - fcc_end_cache_get + fcc_end_cache_get, + fcc_move, + fcc_default_name }; diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 7c3f128ae59..fc78945c63a 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include <krb5_locl.h> -RCSID("$Id: get_cred.c 21669 2007-07-22 11:29:13Z lha $"); +RCSID("$Id: get_cred.c 22530 2008-01-27 11:48:16Z lha $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -761,14 +761,6 @@ get_cred_from_kdc_flags(krb5_context context, try_realm = krb5_config_get_string(context, NULL, "capaths", client_realm, server_realm, NULL); - -#if 1 - /* XXX remove in future release */ - if(try_realm == NULL) - try_realm = krb5_config_get_string(context, NULL, "libdefaults", - "capath", server_realm, NULL); -#endif - if (try_realm == NULL) try_realm = client_realm; diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index 1bb98737d1a..cb8b7c8641a 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -33,7 +33,7 @@ #include <krb5_locl.h> -RCSID("$Id: get_for_creds.c 17036 2006-04-10 09:28:15Z lha $"); +RCSID("$Id: get_for_creds.c 22504 2008-01-21 15:49:58Z lha $"); static krb5_error_code add_addrs(krb5_context context, @@ -83,11 +83,23 @@ fail: return ret; } -/* - * Forward credentials for `client' to host `hostname`, - * making them forwardable if `forwardable', and returning the - * blob of data to sent in `out_data'. - * If hostname == NULL, pick it from `server' +/** + * Forward credentials for client to host hostname , making them + * forwardable if forwardable, and returning the blob of data to sent + * in out_data. If hostname == NULL, pick it from server. + * + * @param context A kerberos 5 context. + * @param auth_context the auth context with the key to encrypt the out_data. + * @param hostname the host to forward the tickets too. + * @param client the client to delegate from. + * @param server the server to delegate the credential too. + * @param ccache credential cache to use. + * @param forwardable make the forwarded ticket forwabledable. + * @param out_data the resulting credential. + * + * @return Return an error code or 0. + * + * @ingroup krb5_credential */ krb5_error_code KRB5_LIB_FUNCTION @@ -147,8 +159,31 @@ krb5_fwd_tgt_creds (krb5_context context, return ret; } -/* +/** + * Gets tickets forwarded to hostname. If the tickets that are + * forwarded are address-less, the forwarded tickets will also be + * address-less. + * + * If the ticket have any address, hostname will be used for figure + * out the address to forward the ticket too. This since this might + * use DNS, its insecure and also doesn't represent configured all + * addresses of the host. For example, the host might have two + * adresses, one IPv4 and one IPv6 address where the later is not + * published in DNS. This IPv6 address might be used communications + * and thus the resulting ticket useless. * + * @param context A kerberos 5 context. + * @param auth_context the auth context with the key to encrypt the out_data. + * @param ccache credential cache to use + * @param flags the flags to control the resulting ticket flags + * @param hostname the host to forward the tickets too. + * @param in_creds the in client and server ticket names. The client + * and server components forwarded to the remote host. + * @param out_data the resulting credential. + * + * @return Return an error code or 0. + * + * @ingroup krb5_credential */ krb5_error_code KRB5_LIB_FUNCTION @@ -174,39 +209,31 @@ krb5_get_forwarded_creds (krb5_context context, struct addrinfo *ai; int save_errno; krb5_creds *ticket; - char *realm; - - realm = in_creds->client->realm; + paddrs = NULL; addrs.len = 0; addrs.val = NULL; - paddrs = &addrs; - { + ret = krb5_get_credentials(context, 0, ccache, in_creds, &ticket); + if(ret == 0) { + if (ticket->addresses.len) + paddrs = &addrs; + krb5_free_creds (context, ticket); + } else { krb5_boolean noaddr; - krb5_appdefault_boolean(context, NULL, realm, + krb5_appdefault_boolean(context, NULL, + krb5_principal_get_realm(context, + in_creds->client), "no-addresses", KRB5_ADDRESSLESS_DEFAULT, &noaddr); - if (noaddr) - paddrs = NULL; + if (!noaddr) + paddrs = &addrs; } /* - * If tickets are address-less, forward address-less tickets. + * If tickets have addresses, get the address of the remote host. */ - if (paddrs) { - ret = _krb5_get_krbtgt (context, - ccache, - realm, - &ticket); - if(ret == 0) { - if (ticket->addresses.len == 0) - paddrs = NULL; - krb5_free_creds (context, ticket); - } - } - if (paddrs != NULL) { ret = getaddrinfo (hostname, NULL, NULL, &ai); @@ -233,9 +260,8 @@ krb5_get_forwarded_creds (krb5_context context, in_creds, &out_creds); krb5_free_addresses (context, &addrs); - if (ret) { + if (ret) return ret; - } memset (&cred, 0, sizeof(cred)); cred.pvno = 5; @@ -373,6 +399,14 @@ krb5_get_forwarded_creds (krb5_context context, if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); + /** + * Some older of the MIT gssapi library used clear-text tickets + * (warped inside AP-REQ encryption), use the krb5_auth_context + * flag KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED to support those + * tickets. The session key is used otherwise to encrypt the + * forwarded ticket. + */ + if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) { cred.enc_part.etype = ENCTYPE_NULL; cred.enc_part.kvno = NULL; diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c index ec106bb7ecc..a9ed3857d03 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt.c +++ b/source4/heimdal/lib/krb5/get_in_tkt.c @@ -145,7 +145,7 @@ _krb5_extract_ticket(krb5_context context, flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; flags |=EXTRACT_TICKET_ALLOW_CNAME_MISMATCH ; - ret = _krb5_principalname2krb5_principal (context, + ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.cname, rep->kdc_rep.crealm); diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index bd250cef2bd..a59c903bd9e 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c 21712 2007-07-27 14:23:41Z lha $"); +RCSID("$Id: init_creds.c 21711 2007-07-27 14:22:02Z lha $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 0043b5ef3c1..441adff8fdf 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c 21428 2007-07-10 12:31:58Z lha $"); +RCSID("$Id: init_creds_pw.c 21931 2007-08-27 14:11:55Z lha $"); typedef struct krb5_get_init_creds_ctx { KDCOptions flags; @@ -1547,9 +1547,15 @@ krb5_get_init_creds_password(krb5_context context, char buf[BUFSIZ]; krb5_error_code ret; - if (in_options == NULL) + if (in_options == NULL) { + const char *realm = krb5_principal_get_realm(context, client); ret = krb5_get_init_creds_opt_alloc(context, &options); - else + if (ret == 0) + krb5_get_init_creds_opt_set_default_flags(context, + NULL, + realm, + options); + } else ret = _krb5_get_init_creds_opt_copy(context, in_options, &options); if (ret) return ret; diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c index c945a9ce135..8afaa6ea80a 100644 --- a/source4/heimdal/lib/krb5/kcm.c +++ b/source4/heimdal/lib/krb5/kcm.c @@ -43,7 +43,7 @@ #include "kcm.h" -RCSID("$Id: kcm.c 17442 2006-05-05 09:31:15Z lha $"); +RCSID("$Id: kcm.c 22108 2007-12-03 17:23:53Z lha $"); typedef struct krb5_kcmcache { char *name; @@ -829,6 +829,27 @@ kcm_get_version(krb5_context context, return 0; } +static krb5_error_code +kcm_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_set_error_string(context, "kcm_move not implemented"); + return EINVAL; +} + +static krb5_error_code +kcm_default_name(krb5_context context, char **str) +{ + return _krb5_expand_default_cc_name(context, + KRB5_DEFAULT_CCNAME_KCM, + str); +} + +/** + * Variable containing the KCM based credential cache implemention. + * + * @ingroup krb5_ccache + */ + const krb5_cc_ops krb5_kcm_ops = { "KCM", kcm_get_name, @@ -845,7 +866,12 @@ const krb5_cc_ops krb5_kcm_ops = { kcm_end_get, kcm_remove_cred, kcm_set_flags, - kcm_get_version + kcm_get_version, + NULL, + NULL, + NULL, + kcm_move, + kcm_default_name }; krb5_boolean diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c index f6c7858c12e..79a3f20e79d 100644 --- a/source4/heimdal/lib/krb5/keytab.c +++ b/source4/heimdal/lib/krb5/keytab.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab.c 20211 2007-02-09 07:11:03Z lha $"); +RCSID("$Id: keytab.c 22532 2008-01-27 11:59:18Z lha $"); /* * Register a new keytab in `ops' @@ -337,8 +337,9 @@ krb5_kt_get_entry(krb5_context context, ret = krb5_kt_start_seq_get (context, id, &cursor); if (ret) { - krb5_clear_error_string(context); - return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */ + /* This is needed for krb5_verify_init_creds, but keep error + * string from previous error for the human. */ + return KRB5_KT_NOTFOUND; } entry->vno = 0; diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c index 4ada3a463ea..be195d96c26 100644 --- a/source4/heimdal/lib/krb5/keytab_file.c +++ b/source4/heimdal/lib/krb5/keytab_file.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_file.c 17457 2006-05-05 12:36:57Z lha $"); +RCSID("$Id: keytab_file.c 22532 2008-01-27 11:59:18Z lha $"); #define KRB5_KT_VNO_1 1 #define KRB5_KT_VNO_2 2 @@ -334,8 +334,8 @@ fkt_start_seq_get_int(krb5_context context, c->fd = open (d->filename, flags); if (c->fd < 0) { ret = errno; - krb5_set_error_string(context, "%s: %s", d->filename, - strerror(ret)); + krb5_set_error_string(context, "keytab %s open failed: %s", + d->filename, strerror(ret)); return ret; } ret = _krb5_xlock(context, c->fd, exclusive, d->filename); diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c index 77455ba5f7c..aa612add097 100644 --- a/source4/heimdal/lib/krb5/keytab_keyfile.c +++ b/source4/heimdal/lib/krb5/keytab_keyfile.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_keyfile.c 20695 2007-05-30 14:09:09Z lha $"); +RCSID("$Id: keytab_keyfile.c 22532 2008-01-27 11:59:18Z lha $"); /* afs keyfile operations --------------------------------------- */ @@ -197,8 +197,8 @@ akf_start_seq_get(krb5_context context, c->fd = open (d->filename, O_RDONLY|O_BINARY, 0600); if (c->fd < 0) { ret = errno; - krb5_set_error_string(context, "open(%s): %s", d->filename, - strerror(ret)); + krb5_set_error_string(context, "keytab afs keyfil open %s failed: %s", + d->filename, strerror(ret)); return ret; } diff --git a/source4/heimdal/lib/krb5/keytab_krb4.c b/source4/heimdal/lib/krb5/keytab_krb4.c index 907836c144f..32bb00141ab 100644 --- a/source4/heimdal/lib/krb5/keytab_krb4.c +++ b/source4/heimdal/lib/krb5/keytab_krb4.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_krb4.c 17046 2006-04-10 17:10:53Z lha $"); +RCSID("$Id: keytab_krb4.c 22532 2008-01-27 11:59:18Z lha $"); struct krb4_kt_data { char *filename; @@ -134,14 +134,15 @@ krb4_kt_start_seq_get_int (krb5_context context, if (c->fd < 0) { ret = errno; free (ed); - krb5_set_error_string(context, "open(%s): %s", d->filename, - strerror(ret)); + krb5_set_error_string(context, "keytab krb5 open %s failed: %s", + d->filename, strerror(ret)); return ret; } c->sp = krb5_storage_from_fd(c->fd); if(c->sp == NULL) { close(c->fd); free(ed); + krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_eof_code(c->sp, KRB5_KT_END); @@ -369,8 +370,11 @@ krb4_kt_remove_entry(krb5_context context, if(fd < 0) { memset(data.data, 0, data.length); krb5_data_free(&data); - if(errno == EACCES || errno == EROFS) + if(errno == EACCES || errno == EROFS) { + krb5_set_error_string(context, "failed to open %s for writing", + d->filename); return KRB5_KT_NOWRITE; + } return errno; } @@ -378,14 +382,16 @@ krb4_kt_remove_entry(krb5_context context, memset(data.data, 0, data.length); krb5_data_free(&data); close(fd); - krb5_set_error_string(context, "failed writing to \"%s\"", d->filename); + krb5_set_error_string(context, "failed writing to file %s", + d->filename); return errno; } memset(data.data, 0, data.length); if(fstat(fd, &st) < 0) { krb5_data_free(&data); close(fd); - krb5_set_error_string(context, "failed getting size of \"%s\"", d->filename); + krb5_set_error_string(context, "failed getting size of file %s", + d->filename); return errno; } st.st_size -= data.length; @@ -396,7 +402,8 @@ krb4_kt_remove_entry(krb5_context context, if(n <= 0) { krb5_data_free(&data); close(fd); - krb5_set_error_string(context, "failed writing to \"%s\"", d->filename); + krb5_set_error_string(context, "failed writing to file %s", + d->filename); return errno; } @@ -405,17 +412,20 @@ krb4_kt_remove_entry(krb5_context context, if(ftruncate(fd, data.length) < 0) { krb5_data_free(&data); close(fd); - krb5_set_error_string(context, "failed truncating \"%s\"", d->filename); + krb5_set_error_string(context, "failed truncating file %s", + d->filename); return errno; } krb5_data_free(&data); if(close(fd) < 0) { - krb5_set_error_string(context, "error closing \"%s\"", d->filename); + krb5_set_error_string(context, "error closing %s", + d->filename); return errno; } return 0; } else { krb5_storage_free(sp); + krb5_set_error_string(context, "Keytab entry not found"); return KRB5_KT_NOTFOUND; } } diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 9a84dde61a7..7e04446fe07 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -276,7 +276,7 @@ _krb5_mk_req_internal ( krb5_key_usage /*checksum_usage*/, krb5_key_usage /*encrypt_usage*/); -void KRB5_LIB_FUNCTION +krb5_error_code KRB5_LIB_FUNCTION _krb5_n_fold ( const void */*str*/, size_t /*len*/, @@ -292,7 +292,7 @@ _krb5_oid_to_enctype ( krb5_error_code _krb5_pac_sign ( krb5_context /*context*/, - struct krb5_pac */*p*/, + krb5_pac /*p*/, time_t /*authtime*/, krb5_principal /*principal*/, const krb5_keyblock */*server_key*/, @@ -396,13 +396,6 @@ _krb5_plugin_get_next (struct krb5_plugin */*p*/); void * _krb5_plugin_get_symbol (struct krb5_plugin */*p*/); -krb5_error_code -_krb5_plugin_register ( - krb5_context /*context*/, - enum krb5_plugin_type /*type*/, - const char */*name*/, - void */*symbol*/); - krb5_error_code KRB5_LIB_FUNCTION _krb5_principal2principalname ( PrincipalName */*p*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 740b394be8a..647d8886b7c 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -670,6 +670,12 @@ krb5_cc_initialize ( krb5_ccache /*id*/, krb5_principal /*primary_principal*/); +krb5_error_code +krb5_cc_move ( + krb5_context /*context*/, + krb5_ccache /*from*/, + krb5_ccache /*to*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_new_unique ( krb5_context /*context*/, @@ -1329,6 +1335,13 @@ krb5_digest_init_request ( krb5_realm /*realm*/, krb5_ccache /*ccache*/); +krb5_error_code +krb5_digest_probe ( + krb5_context /*context*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/, + unsigned */*flags*/); + krb5_boolean krb5_digest_rep_get_status ( krb5_context /*context*/, @@ -1606,6 +1619,9 @@ krb5_err ( ...) __attribute__ ((noreturn, format (printf, 4, 5))); +krb5_error_code KRB5_LIB_FUNCTION + __attribute__((deprecated)) krb5_free_creds_contents (krb5_context context, krb5_creds *c); + krb5_error_code KRB5_LIB_FUNCTION krb5_error_from_rd_error ( krb5_context /*context*/, @@ -1694,11 +1710,6 @@ krb5_free_creds ( krb5_context /*context*/, krb5_creds */*c*/); -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_creds_contents ( - krb5_context /*context*/, - krb5_creds */*c*/); - void KRB5_LIB_FUNCTION krb5_free_data ( krb5_context /*context*/, @@ -2244,6 +2255,14 @@ krb5_get_pw_salt ( krb5_salt */*salt*/); krb5_error_code KRB5_LIB_FUNCTION +krb5_get_renewed_creds ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_const_principal /*client*/, + krb5_ccache /*ccache*/, + const char */*in_tkt_service*/); + +krb5_error_code KRB5_LIB_FUNCTION krb5_get_server_rcache ( krb5_context /*context*/, const krb5_data */*piece*/, @@ -2797,45 +2816,45 @@ krb5_openlog ( krb5_error_code krb5_pac_add_buffer ( krb5_context /*context*/, - struct krb5_pac */*p*/, + krb5_pac /*p*/, uint32_t /*type*/, const krb5_data */*data*/); void krb5_pac_free ( krb5_context /*context*/, - struct krb5_pac */*pac*/); + krb5_pac /*pac*/); krb5_error_code krb5_pac_get_buffer ( krb5_context /*context*/, - struct krb5_pac */*p*/, + krb5_pac /*p*/, uint32_t /*type*/, krb5_data */*data*/); krb5_error_code krb5_pac_get_types ( krb5_context /*context*/, - struct krb5_pac */*p*/, + krb5_pac /*p*/, size_t */*len*/, uint32_t **/*types*/); krb5_error_code krb5_pac_init ( krb5_context /*context*/, - struct krb5_pac **/*pac*/); + krb5_pac */*pac*/); krb5_error_code krb5_pac_parse ( krb5_context /*context*/, const void */*ptr*/, size_t /*len*/, - struct krb5_pac **/*pac*/); + krb5_pac */*pac*/); krb5_error_code krb5_pac_verify ( krb5_context /*context*/, - const struct krb5_pac */*pac*/, + const krb5_pac /*pac*/, time_t /*authtime*/, krb5_const_principal /*principal*/, const krb5_keyblock */*server*/, @@ -2887,6 +2906,13 @@ krb5_password_key_proc ( krb5_const_pointer /*keyseed*/, krb5_keyblock **/*key*/); +krb5_error_code +krb5_plugin_register ( + krb5_context /*context*/, + enum krb5_plugin_type /*type*/, + const char */*name*/, + void */*symbol*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_prepend_config_files ( const char */*filelist*/, diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 4f9a63bf054..571eb6192ae 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h 21551 2007-07-15 09:03:39Z lha $ */ +/* $Id: krb5.h 22100 2007-12-03 17:15:00Z lha $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -75,15 +75,16 @@ typedef struct krb5_crypto_data *krb5_crypto; struct krb5_get_creds_opt_data; typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt; -struct krb5_digest; -typedef struct krb5_digest *krb5_digest; -struct krb5_ntlm; -typedef struct krb5_ntlm *krb5_ntlm; +struct krb5_digest_data; +typedef struct krb5_digest_data *krb5_digest; +struct krb5_ntlm_data; +typedef struct krb5_ntlm_data *krb5_ntlm; -typedef struct krb5_pac *krb5_pac; +struct krb5_pac_data; +typedef struct krb5_pac_data *krb5_pac; -typedef struct krb5_rd_req_in_ctx *krb5_rd_req_in_ctx; -typedef struct krb5_rd_req_out_ctx *krb5_rd_req_out_ctx; +typedef struct krb5_rd_req_in_ctx_data *krb5_rd_req_in_ctx; +typedef struct krb5_rd_req_out_ctx_data *krb5_rd_req_out_ctx; typedef CKSUMTYPE krb5_cksumtype; @@ -417,6 +418,8 @@ typedef struct krb5_cc_ops { krb5_error_code (*get_cache_first)(krb5_context, krb5_cc_cursor *); krb5_error_code (*get_cache_next)(krb5_context, krb5_cc_cursor, krb5_ccache *); krb5_error_code (*end_cache_get)(krb5_context, krb5_cc_cursor); + krb5_error_code (*move)(krb5_context, krb5_ccache, krb5_ccache); + krb5_error_code (*default_name)(krb5_context, char **); } krb5_cc_ops; struct krb5_log_facility; @@ -753,7 +756,7 @@ enum { KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4 }; -typedef struct krb5_sendto_ctx *krb5_sendto_ctx; +typedef struct krb5_sendto_ctx_data *krb5_sendto_ctx; #define KRB5_SENDTO_DONE 0 #define KRB5_SENDTO_RESTART 1 diff --git a/source4/heimdal/lib/krb5/krb5_ccapi.h b/source4/heimdal/lib/krb5/krb5_ccapi.h index b53d77ef188..59a38425c25 100644 --- a/source4/heimdal/lib/krb5/krb5_ccapi.h +++ b/source4/heimdal/lib/krb5/krb5_ccapi.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_ccapi.h 17442 2006-05-05 09:31:15Z lha $ */ +/* $Id: krb5_ccapi.h 22090 2007-12-02 23:23:43Z lha $ */ #ifndef KRB5_CCAPI_H #define KRB5_CCAPI_H 1 @@ -180,18 +180,18 @@ typedef struct cc_ccache_functions { cc_int32 (*destroy)(cc_ccache_t); cc_int32 (*set_default)(cc_ccache_t); cc_int32 (*get_credentials_version)(cc_ccache_t, cc_uint32*); - cc_int32 (*get_name)(cc_ccache_t ccache,cc_string_t*); + cc_int32 (*get_name)(cc_ccache_t, cc_string_t*); cc_int32 (*get_principal)(cc_ccache_t, cc_uint32, cc_string_t*); cc_int32 (*set_principal)(cc_ccache_t, cc_uint32, const char*); cc_int32 (*store_credentials)(cc_ccache_t, const cc_credentials_union*); cc_int32 (*remove_credentials)(cc_ccache_t, cc_credentials_t); cc_int32 (*new_credentials_iterator)(cc_ccache_t, cc_credentials_iterator_t*); - cc_int32 (*move)(cc_ccache_t source, cc_ccache_t); + cc_int32 (*move)(cc_ccache_t, cc_ccache_t); cc_int32 (*lock)(cc_ccache_t, cc_uint32, cc_uint32); cc_int32 (*unlock)(cc_ccache_t); cc_int32 (*get_last_default_time)(cc_ccache_t, cc_time_t*); - cc_int32 (*get_change_time)(cc_ccache_t ccache, cc_time_t*); + cc_int32 (*get_change_time)(cc_ccache_t, cc_time_t*); cc_int32 (*compare)(cc_ccache_t, cc_ccache_t, cc_uint32*); cc_int32 (*get_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t *); cc_int32 (*set_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t); diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index b41e6e1182e..8b7c41cc80d 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h 21552 2007-07-15 09:04:00Z lha $ */ +/* $Id: krb5_locl.h 22226 2007-12-08 21:31:53Z lha $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -231,14 +231,18 @@ typedef struct krb5_context_data { krb5_addresses *ignore_addresses; char *default_cc_name; char *default_cc_name_env; + int default_cc_name_set; void *mutex; /* protects error_string/error_buf */ int large_msg_size; - int dns_canonicalize_hostname; + int flags; +#define KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME 1 +#define KRB5_CTX_F_CHECK_PAC 2 struct send_to_kdc *send_to_kdc; } krb5_context_data; #define KRB5_DEFAULT_CCNAME_FILE "FILE:/tmp/krb5cc_%{uid}" #define KRB5_DEFAULT_CCNAME_API "API:" +#define KRB5_DEFAULT_CCNAME_KCM "KCM:%{uid}" #define EXTRACT_TICKET_ALLOW_CNAME_MISMATCH 1 #define EXTRACT_TICKET_ALLOW_SERVER_MISMATCH 2 @@ -248,11 +252,11 @@ typedef struct krb5_context_data { * Configurable options */ -#ifndef KRB5_DEFAULT_CCNAME +#ifndef KRB5_DEFAULT_CCTYPE #ifdef __APPLE__ -#define KRB5_DEFAULT_CCNAME KRB5_DEFAULT_CCNAME_API +#define KRB5_DEFAULT_CCTYPE (&krb5_acc_ops) #else -#define KRB5_DEFAULT_CCNAME KRB5_DEFAULT_CCNAME_FILE +#define KRB5_DEFAULT_CCTYPE (&krb5_fcc_ops) #endif #endif diff --git a/source4/heimdal/lib/krb5/mcache.c b/source4/heimdal/lib/krb5/mcache.c index ff9261a7db7..01bcb09d3be 100644 --- a/source4/heimdal/lib/krb5/mcache.c +++ b/source4/heimdal/lib/krb5/mcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: mcache.c 19834 2007-01-11 09:26:21Z lha $"); +RCSID("$Id: mcache.c 22107 2007-12-03 17:22:51Z lha $"); typedef struct krb5_mcache { char *name; @@ -401,6 +401,57 @@ mcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) return 0; } +static krb5_error_code +mcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_mcache *mfrom = MCACHE(from), *mto = MCACHE(to); + struct link *creds; + krb5_principal principal; + krb5_mcache **n; + + HEIMDAL_MUTEX_lock(&mcc_mutex); + + /* drop the from cache from the linked list to avoid lookups */ + for(n = &mcc_head; n && *n; n = &(*n)->next) { + if(mfrom == *n) { + *n = mfrom->next; + break; + } + } + + /* swap creds */ + creds = mto->creds; + mto->creds = mfrom->creds; + mfrom->creds = creds; + /* swap principal */ + principal = mto->primary_principal; + mto->primary_principal = mfrom->primary_principal; + mfrom->primary_principal = principal; + + HEIMDAL_MUTEX_unlock(&mcc_mutex); + mcc_destroy(context, from); + + return 0; +} + +static krb5_error_code +mcc_default_name(krb5_context context, char **str) +{ + *str = strdup("MEMORY:"); + if (*str == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + + +/** + * Variable containing the MEMORY based credential cache implemention. + * + * @ingroup krb5_ccache + */ + const krb5_cc_ops krb5_mcc_ops = { "MEMORY", mcc_get_name, @@ -420,5 +471,7 @@ const krb5_cc_ops krb5_mcc_ops = { NULL, mcc_get_cache_first, mcc_get_cache_next, - mcc_end_cache_get + mcc_end_cache_get, + mcc_move, + mcc_default_name }; diff --git a/source4/heimdal/lib/krb5/n-fold.c b/source4/heimdal/lib/krb5/n-fold.c index 1474a76b775..53528cfd1f7 100644 --- a/source4/heimdal/lib/krb5/n-fold.c +++ b/source4/heimdal/lib/krb5/n-fold.c @@ -32,21 +32,23 @@ #include "krb5_locl.h" -RCSID("$Id: n-fold.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: n-fold.c 22190 2007-12-06 16:24:22Z lha $"); -static void +static krb5_error_code rr13(unsigned char *buf, size_t len) { unsigned char *tmp; int bytes = (len + 7) / 8; int i; if(len == 0) - return; + return 0; { const int bits = 13 % len; const int lbit = len % 8; tmp = malloc(bytes); + if (tmp == NULL) + return ENOMEM; memcpy(tmp, buf, bytes); if(lbit) { /* pad final byte with inital bits */ @@ -75,9 +77,10 @@ rr13(unsigned char *buf, size_t len) } free(tmp); } + return 0; } -/* Add `b' to `a', both beeing one's complement numbers. */ +/* Add `b' to `a', both being one's complement numbers. */ static void add1(unsigned char *a, unsigned char *b, size_t len) { @@ -95,22 +98,28 @@ add1(unsigned char *a, unsigned char *b, size_t len) } } -void KRB5_LIB_FUNCTION +krb5_error_code KRB5_LIB_FUNCTION _krb5_n_fold(const void *str, size_t len, void *key, size_t size) { /* if len < size we need at most N * len bytes, ie < 2 * size; if len > size we need at most 2 * len */ + krb5_error_code ret = 0; size_t maxlen = 2 * max(size, len); size_t l = 0; unsigned char *tmp = malloc(maxlen); unsigned char *buf = malloc(len); + if (tmp == NULL || buf == NULL) + return ENOMEM; + memcpy(buf, str, len); memset(key, 0, size); do { memcpy(tmp + l, buf, len); l += len; - rr13(buf, len * 8); + ret = rr13(buf, len * 8); + if (ret) + goto out; while(l >= size) { add1(key, tmp, size); l -= size; @@ -119,8 +128,10 @@ _krb5_n_fold(const void *str, size_t len, void *key, size_t size) memmove(tmp, tmp + size, l); } } while(l != 0); +out: memset(buf, 0, len); free(buf); memset(tmp, 0, maxlen); free(tmp); + return ret; } diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index f7a5e83ea34..0b44ca1da38 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -32,8 +32,9 @@ */ #include "krb5_locl.h" +#include <wind.h> -RCSID("$Id: pac.c 21149 2007-06-18 21:50:22Z lha $"); +RCSID("$Id: pac.c 22562 2008-02-03 17:38:35Z lha $"); struct PAC_INFO_BUFFER { uint32_t type; @@ -48,7 +49,7 @@ struct PACTYPE { struct PAC_INFO_BUFFER buffers[1]; }; -struct krb5_pac { +struct krb5_pac_data { struct PACTYPE *pac; krb5_data data; struct PAC_INFO_BUFFER *server_checksum; @@ -82,10 +83,10 @@ static const char zeros[PAC_ALIGNMENT] = { 0 }; krb5_error_code krb5_pac_parse(krb5_context context, const void *ptr, size_t len, - struct krb5_pac **pac) + krb5_pac *pac) { krb5_error_code ret; - struct krb5_pac *p; + krb5_pac p; krb5_storage *sp = NULL; uint32_t i, tmp, tmp2, header_end; @@ -216,10 +217,10 @@ out: } krb5_error_code -krb5_pac_init(krb5_context context, struct krb5_pac **pac) +krb5_pac_init(krb5_context context, krb5_pac *pac) { krb5_error_code ret; - struct krb5_pac *p; + krb5_pac p; p = calloc(1, sizeof(*p)); if (p == NULL) { @@ -248,7 +249,7 @@ krb5_pac_init(krb5_context context, struct krb5_pac **pac) } krb5_error_code -krb5_pac_add_buffer(krb5_context context, struct krb5_pac *p, +krb5_pac_add_buffer(krb5_context context, krb5_pac p, uint32_t type, const krb5_data *data) { krb5_error_code ret; @@ -316,7 +317,7 @@ krb5_pac_add_buffer(krb5_context context, struct krb5_pac *p, } krb5_error_code -krb5_pac_get_buffer(krb5_context context, struct krb5_pac *p, +krb5_pac_get_buffer(krb5_context context, krb5_pac p, uint32_t type, krb5_data *data) { krb5_error_code ret; @@ -361,7 +362,7 @@ krb5_pac_get_buffer(krb5_context context, struct krb5_pac *p, krb5_error_code krb5_pac_get_types(krb5_context context, - struct krb5_pac *p, + krb5_pac p, size_t *len, uint32_t **types) { @@ -385,7 +386,7 @@ krb5_pac_get_types(krb5_context context, */ void -krb5_pac_free(krb5_context context, struct krb5_pac *pac) +krb5_pac_free(krb5_context context, krb5_pac pac) { krb5_data_free(&pac->data); free(pac->pac); @@ -564,51 +565,48 @@ verify_logonname(krb5_context context, ret = krb5_storage_read(sp, s, len); if (ret != len) { krb5_storage_free(sp); - krb5_set_error_string(context, "Failed to read pac logon name"); + krb5_set_error_string(context, "Failed to read PAC logon name"); return EINVAL; } krb5_storage_free(sp); -#if 1 /* cheat for now */ - { - size_t i; - - if (len & 1) { - krb5_set_error_string(context, "PAC logon name malformed"); - return EINVAL; - } - - for (i = 0; i < len / 2; i++) { - if (s[(i * 2) + 1]) { - krb5_set_error_string(context, "PAC logon name not ASCII"); - return EINVAL; - } - s[i] = s[i * 2]; - } - s[i] = '\0'; - } -#else { + size_t ucs2len = len / 2; uint16_t *ucs2; - ssize_t ucs2len; size_t u8len; + unsigned int flags = WIND_RW_LE; - ucs2 = malloc(sizeof(ucs2[0]) * len / 2); - if (ucs2) - abort(); - ucs2len = wind_ucs2read(s, len / 2, ucs2); + ucs2 = malloc(sizeof(ucs2[0]) * ucs2len); + if (ucs2 == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len); free(s); - if (len < 0) - return -1; - ret = wind_ucs2toutf8(ucs2, ucs2len, NULL, &u8len); - if (ret < 0) - abort(); - s = malloc(u8len + 1); - if (s == NULL) - abort(); - wind_ucs2toutf8(ucs2, ucs2len, s, &u8len); + if (ret) { + free(ucs2); + krb5_set_error_string(context, "Failed to convert string to UCS-2"); + return ret; + } + ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len); + if (ret) { + free(ucs2); + krb5_set_error_string(context, "Failed to count length of UCS-2 string"); + return ret; + } + u8len += 1; /* Add space for NUL */ + s = malloc(u8len); + if (s == NULL) { + free(ucs2); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = wind_ucs2utf8(ucs2, ucs2len, s, &u8len); free(ucs2); + if (ret) { + krb5_set_error_string(context, "Failed to convert to UTF-8"); + return ret; + } } -#endif ret = krb5_parse_name_flags(context, s, KRB5_PRINCIPAL_PARSE_NO_REALM, &p2); free(s); if (ret) @@ -703,7 +701,7 @@ out: krb5_error_code krb5_pac_verify(krb5_context context, - const struct krb5_pac *pac, + const krb5_pac pac, time_t authtime, krb5_const_principal principal, const krb5_keyblock *server, @@ -840,7 +838,7 @@ pac_checksum(krb5_context context, krb5_error_code _krb5_pac_sign(krb5_context context, - struct krb5_pac *p, + krb5_pac p, time_t authtime, krb5_principal principal, const krb5_keyblock *server_key, diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index c8587770f4c..4a585bff070 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c 21684 2007-07-23 23:09:10Z lha $"); +RCSID("$Id: pkinit.c 22673 2008-03-10 15:00:05Z lha $"); struct krb5_dh_moduli { char *name; @@ -139,17 +139,59 @@ integer_to_BN(krb5_context context, const char *field, const heim_integer *f) return bn; } +struct certfind { + const char *type; + const heim_oid *oid; +}; + +/* + * Try searchin the key by to use by first looking for for PK-INIT + * EKU, then the Microsoft smart card EKU and last, no special EKU at all. + */ static krb5_error_code -_krb5_pk_create_sign(krb5_context context, - const heim_oid *eContentType, - krb5_data *eContent, - struct krb5_pk_identity *id, - hx509_peer_info peer, - krb5_data *sd_data) +find_cert(krb5_context context, struct krb5_pk_identity *id, + hx509_query *q, hx509_cert *cert) { - hx509_cert cert; - hx509_query *q; + struct certfind cf[3] = { + { "PKINIT EKU" }, + { "MS EKU" }, + { "no" } + }; + int i, ret; + + cf[0].oid = oid_id_pkekuoid(); + cf[1].oid = oid_id_pkinit_ms_eku(); + cf[2].oid = NULL; + + for (i = 0; i < sizeof(cf)/sizeof(cf[0]); i++) { + ret = hx509_query_match_eku(q, cf[i].oid); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed setting %s OID", cf[i].type); + return ret; + } + + ret = hx509_certs_find(id->hx509ctx, id->certs, q, cert); + if (ret == 0) + break; + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed cert for finding %s OID", cf[i].type); + } + return ret; +} + + +static krb5_error_code +create_signature(krb5_context context, + const heim_oid *eContentType, + krb5_data *eContent, + struct krb5_pk_identity *id, + hx509_peer_info peer, + krb5_data *sd_data) +{ + hx509_cert cert = NULL; + hx509_query *q = NULL; int ret; ret = hx509_query_alloc(id->hx509ctx, &q); @@ -162,13 +204,10 @@ _krb5_pk_create_sign(krb5_context context, hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); - ret = hx509_certs_find(id->hx509ctx, id->certs, q, &cert); + ret = find_cert(context, id, q, &cert); hx509_query_free(id->hx509ctx, q); - if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Find certificate to signed CMS data"); + if (ret) return ret; - } ret = hx509_cms_create_signed_1(id->hx509ctx, 0, @@ -181,11 +220,14 @@ _krb5_pk_create_sign(krb5_context context, NULL, id->certs, sd_data); - if (ret) - _krb5_pk_copy_error(context, id->hx509ctx, ret, "create CMS signedData"); hx509_cert_free(cert); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Create CMS signedData"); + return ret; + } - return ret; + return 0; } static int @@ -212,8 +254,7 @@ cert2epi(hx509_context context, void *ctx, hx509_cert c) return ENOMEM; } - ret = hx509_name_to_der_name(subject, &id.subjectName->data, - &id.subjectName->length); + ret = hx509_name_binary(subject, id.subjectName); if (ret) { hx509_name_free(&subject); free_ExternalPrincipalIdentifier(&id); @@ -544,12 +585,8 @@ pk_mk_padata(krb5_context context, } else krb5_abortx(context, "internal pkinit error"); - ret = _krb5_pk_create_sign(context, - oid, - &buf, - ctx->id, - ctx->peer, - &sd_buf); + ret = create_signature(context, oid, &buf, ctx->id, + ctx->peer, &sd_buf); krb5_data_free(&buf); if (ret) goto out; @@ -878,7 +915,8 @@ pk_verify_host(krb5_context context, hx509_octet_string_list list; int i; - ret = hx509_cert_find_subjectAltName_otherName(host->cert, + ret = hx509_cert_find_subjectAltName_otherName(ctx->id->hx509ctx, + host->cert, oid_id_pkinit_san(), &list); if (ret) { diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index 43fa3f5b45a..bae28496aaf 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: plugin.c 21702 2007-07-26 19:13:53Z lha $"); +RCSID("$Id: plugin.c 22033 2007-11-10 10:39:47Z lha $"); #ifdef HAVE_DLFCN_H #include <dlfcn.h> #endif @@ -117,11 +117,23 @@ loadlib(krb5_context context, } #endif /* HAVE_DLOPEN */ +/** + * Register a plugin symbol name of specific type. + * @param context a Keberos context + * @param type type of plugin symbol + * @param name name of plugin symbol + * @param symbol a pointer to the named symbol + * @return In case of error a non zero error com_err error is returned + * and the Kerberos error string is set. + * + * @ingroup krb5_support + */ + krb5_error_code -_krb5_plugin_register(krb5_context context, - enum krb5_plugin_type type, - const char *name, - void *symbol) +krb5_plugin_register(krb5_context context, + enum krb5_plugin_type type, + const char *name, + void *symbol) { struct plugin *e; @@ -250,4 +262,3 @@ _krb5_plugin_free(struct krb5_plugin *list) list = next; } } - diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index c1a29d266b6..cdad4771153 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,6 +31,22 @@ * SUCH DAMAGE. */ +/** + * @page page_principal The principal handing functions. + * + * A Kerberos principal is a email address looking string that + * contains to parts separeted by a @. The later part is the kerbero + * realm the principal belongs to and the former is a list of 0 or + * more components. For example + * @verbatim +lha@SU.SE +host/hummel.it.su.se@SU.SE +host/admin@H5L.ORG +@endverbatim + * + * See the library functions here: @ref krb5_principal + */ + #include "krb5_locl.h" #ifdef HAVE_RES_SEARCH #define USE_RESOLVER @@ -41,7 +57,7 @@ #include <fnmatch.h> #include "resolve.h" -RCSID("$Id: principal.c 21285 2007-06-25 12:30:55Z lha $"); +RCSID("$Id: principal.c 22549 2008-01-29 09:37:25Z lha $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -49,6 +65,21 @@ RCSID("$Id: principal.c 21285 2007-06-25 12:30:55Z lha $"); #define princ_ncomp(P, N) ((P)->name.name_string.val[(N)]) #define princ_realm(P) ((P)->realm) +/** + * Frees a Kerberos principal allocated by the library with + * krb5_parse_name(), krb5_make_principal() or any other related + * principal functions. + * + * @param context A Kerberos context. + * @param p a principal to free. + * + * @return An krb5 error code, see krb5_get_error_message(). + * + * @ingroup krb5_principal + */ + + + void KRB5_LIB_FUNCTION krb5_free_principal(krb5_context context, krb5_principal p) @@ -804,7 +835,7 @@ krb5_425_conv_principal_ext2(krb5_context context, char local_hostname[MAXHOSTNAMELEN]; /* do the following: if the name is found in the - `v4_name_convert:host' part, is is assumed to be a `host' type + `v4_name_convert:host' part, is assumed to be a `host' type principal, and the instance is looked up in the `v4_instance_convert' part. if not found there the name is (optionally) looked up as a hostname, and if that doesn't yield diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c index 47b5df85b23..ed7a2ccc527 100644 --- a/source4/heimdal/lib/krb5/rd_priv.c +++ b/source4/heimdal/lib/krb5/rd_priv.c @@ -33,7 +33,7 @@ #include <krb5_locl.h> -RCSID("$Id: rd_priv.c 21770 2007-08-01 04:04:33Z lha $"); +RCSID("$Id: rd_priv.c 21751 2007-07-31 20:42:20Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_priv(krb5_context context, diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 001b47f094d..0f33b971645 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -33,7 +33,7 @@ #include <krb5_locl.h> -RCSID("$Id: rd_req.c 21004 2007-06-08 01:53:10Z lha $"); +RCSID("$Id: rd_req.c 22235 2007-12-08 21:52:07Z lha $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -137,7 +137,7 @@ check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc) krb5_error_code ret; /* - * Windows 2000 and 2003 uses this inside their TGT so its normaly + * Windows 2000 and 2003 uses this inside their TGT so it's normaly * not seen by others, however, samba4 joined with a Windows AD as * a Domain Controller gets exposed to this. */ @@ -512,13 +512,13 @@ krb5_verify_ap_req2(krb5_context context, * */ -struct krb5_rd_req_in_ctx { +struct krb5_rd_req_in_ctx_data { krb5_keytab keytab; krb5_keyblock *keyblock; - krb5_boolean no_pac_check; + krb5_boolean check_pac; }; -struct krb5_rd_req_out_ctx { +struct krb5_rd_req_out_ctx_data { krb5_keyblock *keyblock; krb5_flags ap_req_options; krb5_ticket *ticket; @@ -536,6 +536,7 @@ krb5_rd_req_in_ctx_alloc(krb5_context context, krb5_rd_req_in_ctx *ctx) krb5_set_error_string(context, "out of memory"); return ENOMEM; } + (*ctx)->check_pac = (context->flags & KRB5_CTX_F_CHECK_PAC) ? 1 : 0; return 0; } @@ -548,12 +549,24 @@ krb5_rd_req_in_set_keytab(krb5_context context, return 0; } +/** + * Set if krb5_rq_red() is going to check the Windows PAC or not + * + * @param context Keberos 5 context. + * @param in krb5_rd_req_in_ctx to check the option on. + * @param flag flag to select if to check the pac (TRUE) or not (FALSE). + * + * @return Kerberos 5 error code, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_rd_req_in_set_pac_check(krb5_context context, krb5_rd_req_in_ctx in, krb5_boolean flag) { - in->no_pac_check = !flag; + in->check_pac = flag; return 0; } @@ -826,20 +839,21 @@ krb5_rd_req_ctx(krb5_context context, goto out; } - ret = krb5_verify_ap_req(context, - auth_context, - &ap_req, - server, - o->keyblock, - 0, - &o->ap_req_options, - &o->ticket); + ret = krb5_verify_ap_req2(context, + auth_context, + &ap_req, + server, + o->keyblock, + 0, + &o->ap_req_options, + &o->ticket, + KRB5_KU_AP_REQ_AUTH); if (ret) goto out; /* If there is a PAC, verify its server signature */ - if (inctx->no_pac_check == FALSE) { + if (inctx->check_pac) { krb5_pac pac; krb5_data data; diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index c1a4df2b01c..2582a615c05 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: send_to_kdc.c 21062 2007-06-12 17:58:57Z lha $"); +RCSID("$Id: send_to_kdc.c 21934 2007-08-27 14:21:04Z lha $"); struct send_to_kdc { krb5_send_to_kdc_func func; @@ -448,7 +448,7 @@ krb5_set_send_to_kdc_func(krb5_context context, return 0; } -struct krb5_sendto_ctx { +struct krb5_sendto_ctx_data { int flags; int type; krb5_sendto_ctx_func func; diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index 4abcf44a43a..c9cbbb5cef3 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store.c 20529 2007-04-22 14:28:19Z lha $"); +RCSID("$Id: store.c 22071 2007-11-14 20:04:50Z lha $"); #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) @@ -838,8 +838,8 @@ krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) if(ret) goto cleanup; /* * Runtime detect the what is the higher bits of the bitfield. If - * any of the higher bits are set in the input data, its either a - * new ticket flag (and this code need to be removed), or its a + * any of the higher bits are set in the input data, it's either a + * new ticket flag (and this code need to be removed), or it's a * MIT cache (or new Heimdal cache), lets change it to our current * format. */ @@ -993,8 +993,8 @@ krb5_ret_creds_tag(krb5_storage *sp, if(ret) goto cleanup; /* * Runtime detect the what is the higher bits of the bitfield. If - * any of the higher bits are set in the input data, its either a - * new ticket flag (and this code need to be removed), or its a + * any of the higher bits are set in the input data, it's either a + * new ticket flag (and this code need to be removed), or it's a * MIT cache (or new Heimdal cache), lets change it to our current * format. */ diff --git a/source4/heimdal/lib/krb5/store_emem.c b/source4/heimdal/lib/krb5/store_emem.c index 07acdd1a00b..c38c1b53c3a 100644 --- a/source4/heimdal/lib/krb5/store_emem.c +++ b/source4/heimdal/lib/krb5/store_emem.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_emem.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: store_emem.c 22574 2008-02-05 20:31:55Z lha $"); typedef struct emem_storage{ unsigned char *base; @@ -115,13 +115,28 @@ emem_free(krb5_storage *sp) krb5_storage * KRB5_LIB_FUNCTION krb5_storage_emem(void) { - krb5_storage *sp = malloc(sizeof(krb5_storage)); - emem_storage *s = malloc(sizeof(*s)); + krb5_storage *sp; + emem_storage *s; + + sp = malloc(sizeof(krb5_storage)); + if (sp == NULL) + return NULL; + + s = malloc(sizeof(*s)); + if (s == NULL) { + free(sp); + return NULL; + } sp->data = s; sp->flags = 0; sp->eof_code = HEIM_ERR_EOF; s->size = 1024; s->base = malloc(s->size); + if (s->base == NULL) { + free(sp); + free(s); + return NULL; + } s->len = 0; s->ptr = s->base; sp->fetch = emem_fetch; diff --git a/source4/heimdal/lib/krb5/transited.c b/source4/heimdal/lib/krb5/transited.c index 7f5498f5921..9b67ecc04f2 100644 --- a/source4/heimdal/lib/krb5/transited.c +++ b/source4/heimdal/lib/krb5/transited.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: transited.c 17043 2006-04-10 10:26:35Z lha $"); +RCSID("$Id: transited.c 21745 2007-07-31 16:11:25Z lha $"); /* this is an attempt at one of the most horrible `compression' schemes that has ever been invented; it's so amazingly brain-dead @@ -87,6 +87,10 @@ make_path(krb5_context context, struct tr_realm *r, if(strcmp(p, to) == 0) break; tmp = calloc(1, sizeof(*tmp)); + if(tmp == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } tmp->next = path; path = tmp; path->realm = strdup(p); @@ -107,6 +111,10 @@ make_path(krb5_context context, struct tr_realm *r, if(strncmp(to, from, p - from) == 0) break; tmp = calloc(1, sizeof(*tmp)); + if(tmp == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } tmp->next = path; path = tmp; path->realm = malloc(p - from + 1); @@ -277,6 +285,10 @@ decode_realms(krb5_context context, } if(tr[i] == ','){ tmp = malloc(tr + i - start + 1); + if(tmp == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } memcpy(tmp, start, tr + i - start); tmp[tr + i - start] = '\0'; r = make_realm(tmp); @@ -290,6 +302,11 @@ decode_realms(krb5_context context, } } tmp = malloc(tr + i - start + 1); + if(tmp == NULL){ + free(*realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } memcpy(tmp, start, tr + i - start); tmp[tr + i - start] = '\0'; r = make_realm(tmp); diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c index 3f99df6391c..37b1e35dd18 100644 --- a/source4/heimdal/lib/krb5/v4_glue.c +++ b/source4/heimdal/lib/krb5/v4_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: v4_glue.c 21572 2007-07-16 05:13:08Z lha $"); +RCSID("$Id: v4_glue.c 22071 2007-11-14 20:04:50Z lha $"); #include "krb5-v4compat.h" @@ -599,7 +599,7 @@ _krb5_krb_cr_err_reply(krb5_context context, RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_ERR_REPLY), error); RCHECK(ret, put_nir(sp, name, inst, realm), error); RCHECK(ret, krb5_store_int32(sp, time_ws), error); - /* If its a Kerberos 4 error-code, remove the et BASE */ + /* If it is a Kerberos 4 error-code, remove the et BASE */ if (e >= ERROR_TABLE_BASE_krb && e <= ERROR_TABLE_BASE_krb + 255) e -= ERROR_TABLE_BASE_krb; RCHECK(ret, krb5_store_int32(sp, e), error); diff --git a/source4/heimdal/lib/ntlm/heimntlm-protos.h b/source4/heimdal/lib/ntlm/heimntlm-protos.h index 438ba2b94d1..bc64791b439 100644 --- a/source4/heimdal/lib/ntlm/heimntlm-protos.h +++ b/source4/heimdal/lib/ntlm/heimntlm-protos.h @@ -43,7 +43,7 @@ heim_ntlm_calculate_ntlm2_sess ( int heim_ntlm_decode_targetinfo ( - struct ntlm_buf */*data*/, + const struct ntlm_buf */*data*/, int /*ucs2*/, struct ntlm_targetinfo */*ti*/); @@ -65,7 +65,7 @@ heim_ntlm_decode_type3 ( int heim_ntlm_encode_targetinfo ( - struct ntlm_targetinfo */*ti*/, + const struct ntlm_targetinfo */*ti*/, int /*ucs2*/, struct ntlm_buf */*data*/); @@ -76,15 +76,18 @@ heim_ntlm_encode_type1 ( int heim_ntlm_encode_type2 ( - struct ntlm_type2 */*type2*/, + const struct ntlm_type2 */*type2*/, struct ntlm_buf */*data*/); int heim_ntlm_encode_type3 ( - struct ntlm_type3 */*type3*/, + const struct ntlm_type3 */*type3*/, struct ntlm_buf */*data*/); void +heim_ntlm_free_buf (struct ntlm_buf */*p*/); + +void heim_ntlm_free_targetinfo (struct ntlm_targetinfo */*ti*/); void diff --git a/source4/heimdal/lib/ntlm/heimntlm.h b/source4/heimdal/lib/ntlm/heimntlm.h index 1c1afe1eb1f..09d2205fd21 100644 --- a/source4/heimdal/lib/ntlm/heimntlm.h +++ b/source4/heimdal/lib/ntlm/heimntlm.h @@ -31,17 +31,22 @@ * SUCH DAMAGE. */ -/* $Id: heimntlm.h 19469 2006-12-20 07:28:37Z lha $ */ +/* $Id: heimntlm.h 22376 2007-12-28 18:38:23Z lha $ */ #ifndef HEIM_NTLM_H #define HEIM_NTLM_H +/** + * Buffer for storing data in the NTLM library. When filled in by the + * library it should be freed with heim_ntlm_free_buf(). + */ struct ntlm_buf { - size_t length; - void *data; + size_t length; /**< length buffer data */ + void *data; /**< pointer to the data itself */ }; #define NTLM_NEG_UNICODE 0x00000001 +#define NTLM_NEG_TARGET 0x00000004 #define NTLM_NEG_SIGN 0x00000010 #define NTLM_NEG_SEAL 0x00000020 #define NTLM_NEG_NTLM 0x00000200 @@ -52,42 +57,66 @@ struct ntlm_buf { #define NTLM_NEG_ALWAYS_SIGN 0x00008000 #define NTLM_NEG_NTLM2_SESSION 0x00080000 -#define NTLM_NEG_TARGET_DOMAIN 0x00010000 +#define NTLM_TARGET_DOMAIN 0x00010000 +#define NTLM_TARGET_SERVER 0x00020000 #define NTLM_ENC_128 0x20000000 #define NTLM_NEG_KEYEX 0x40000000 +/** + * Struct for the NTLM target info, the strings is assumed to be in + * UTF8. When filled in by the library it should be freed with + * heim_ntlm_free_targetinfo(). + */ struct ntlm_targetinfo { - char *servername; - char *domainname; - char *dnsdomainname; - char *dnsservername; + char *servername; /**< */ + char *domainname; /**< */ + char *dnsdomainname; /**< */ + char *dnsservername; /**< */ }; +/** + * Struct for the NTLM type1 message info, the strings is assumed to + * be in UTF8. When filled in by the library it should be freed with + * heim_ntlm_free_type1(). + */ + struct ntlm_type1 { - uint32_t flags; - char *domain; - char *hostname; - uint32_t os[2]; + uint32_t flags; /**< */ + char *domain; /**< */ + char *hostname; /**< */ + uint32_t os[2]; /**< */ }; +/** + * Struct for the NTLM type2 message info, the strings is assumed to + * be in UTF8. When filled in by the library it should be freed with + * heim_ntlm_free_type2(). + */ + struct ntlm_type2 { - uint32_t flags; - char *targetname; - struct ntlm_buf targetinfo; - unsigned char challange[8]; - uint32_t context[2]; - uint32_t os[2]; + uint32_t flags; /**< */ + char *targetname; /**< */ + struct ntlm_buf targetinfo; /**< */ + unsigned char challange[8]; /**< */ + uint32_t context[2]; /**< */ + uint32_t os[2]; /**< */ }; +/** + * Struct for the NTLM type3 message info, the strings is assumed to + * be in UTF8. When filled in by the library it should be freed with + * heim_ntlm_free_type3(). + */ + struct ntlm_type3 { - uint32_t flags; - char *username; - char *targetname; - struct ntlm_buf lm; - struct ntlm_buf ntlm; - struct ntlm_buf sessionkey; - char *ws; - uint32_t os[2]; + uint32_t flags; /**< */ + char *username; /**< */ + char *targetname; /**< */ + struct ntlm_buf lm; /**< */ + struct ntlm_buf ntlm; /**< */ + struct ntlm_buf sessionkey; /**< */ + char *ws; /**< */ + uint32_t os[2]; /**< */ }; #include <heimntlm-protos.h> diff --git a/source4/heimdal/lib/ntlm/ntlm.c b/source4/heimdal/lib/ntlm/ntlm.c index 671bf329e86..f3dccfaca16 100644 --- a/source4/heimdal/lib/ntlm/ntlm.c +++ b/source4/heimdal/lib/ntlm/ntlm.c @@ -33,7 +33,7 @@ #include <config.h> -RCSID("$Id: ntlm.c 21604 2007-07-17 06:48:55Z lha $"); +RCSID("$Id: ntlm.c 22370 2007-12-28 16:12:01Z lha $"); #include <stdio.h> #include <stdlib.h> @@ -51,12 +51,37 @@ RCSID("$Id: ntlm.c 21604 2007-07-17 06:48:55Z lha $"); #include <heimntlm.h> - -/* - * Source of NTLM information: - * http://davenport.sourceforge.net/ntlm.html +/*! \mainpage Heimdal NTLM library + * + * \section intro Introduction + * + * Heimdal libheimntlm library is a implementation of the NTLM + * protocol, both version 1 and 2. The GSS-API mech that uses this + * library adds support for transport encryption and integrity + * checking. + * + * NTLM is a protocol for mutual authentication, its still used in + * many protocol where Kerberos is not support, one example is + * EAP/X802.1x mechanism LEAP from Microsoft and Cisco. + * + * This is a support library for the core protocol, its used in + * Heimdal to implement and GSS-API mechanism. There is also support + * in the KDC to do remote digest authenticiation, this to allow + * services to authenticate users w/o direct access to the users ntlm + * hashes (same as Kerberos arcfour enctype hashes). + * + * More information about the NTLM protocol can found here + * http://davenport.sourceforge.net/ntlm.html . + * + * The Heimdal projects web page: http://www.h5l.org/ */ +/** @defgroup ntlm_core Heimdal NTLM library + * + * The NTLM core functions implement the string2key generation + * function, message encode and decode function, and the hash function + * functions. + */ struct sec_buffer { uint16_t length; @@ -73,8 +98,16 @@ static const unsigned char ntlmsigature[8] = "NTLMSSP\x00"; #define CHECK(f, e) \ do { ret = f ; if (ret != (e)) { ret = EINVAL; goto out; } } while(0) -static void -_ntlm_free_buf(struct ntlm_buf *p) +/** + * heim_ntlm_free_buf frees the ntlm buffer + * + * @param p buffer to be freed + * + * @ingroup ntlm_core + */ + +void +heim_ntlm_free_buf(struct ntlm_buf *p) { if (p->data) free(p->data); @@ -96,7 +129,7 @@ ascii2ucs2le(const char *string, int up, struct ntlm_buf *buf) buf->length = len * 2; buf->data = malloc(buf->length); if (buf->data == NULL && len != 0) { - _ntlm_free_buf(buf); + heim_ntlm_free_buf(buf); return ENOMEM; } @@ -104,7 +137,7 @@ ascii2ucs2le(const char *string, int up, struct ntlm_buf *buf) for (i = 0; i < len; i++) { unsigned char t = (unsigned char)string[i]; if (t & 0x80) { - _ntlm_free_buf(buf); + heim_ntlm_free_buf(buf); return EINVAL; } if (up) @@ -201,7 +234,7 @@ put_string(krb5_storage *sp, int ucs2, const char *s) CHECK(krb5_storage_write(sp, buf.data, buf.length), buf.length); if (ucs2) - _ntlm_free_buf(&buf); + heim_ntlm_free_buf(&buf); ret = 0; out: return ret; @@ -226,7 +259,7 @@ out: } static krb5_error_code -put_buf(krb5_storage *sp, struct ntlm_buf *buf) +put_buf(krb5_storage *sp, const struct ntlm_buf *buf) { krb5_error_code ret; CHECK(krb5_storage_write(sp, buf->data, buf->length), buf->length); @@ -235,8 +268,12 @@ out: return ret; } -/* +/** + * Frees the ntlm_targetinfo message + * + * @param ti targetinfo to be freed * + * @ingroup ntlm_core */ void @@ -260,8 +297,22 @@ out: return ret; } +/** + * Encodes a ntlm_targetinfo message. + * + * @param ti the ntlm_targetinfo message to encode. + * @param ucs2 if the strings should be encoded with ucs2 (selected by flag in message). + * @param data is the return buffer with the encoded message, should be + * freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core + */ + int -heim_ntlm_encode_targetinfo(struct ntlm_targetinfo *ti, +heim_ntlm_encode_targetinfo(const struct ntlm_targetinfo *ti, int ucs2, struct ntlm_buf *data) { @@ -299,16 +350,34 @@ out: return ret; } +/** + * Decodes an NTLM targetinfo message + * + * @param data input data buffer with the encode NTLM targetinfo message + * @param ucs2 if the strings should be encoded with ucs2 (selected by flag in message). + * @param ti the decoded target info, should be freed with heim_ntlm_free_targetinfo(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core + */ + int -heim_ntlm_decode_targetinfo(struct ntlm_buf *data, int ucs2, +heim_ntlm_decode_targetinfo(const struct ntlm_buf *data, + int ucs2, struct ntlm_targetinfo *ti) { memset(ti, 0, sizeof(*ti)); return 0; } -/* - * encoder/decoder type1 messages +/** + * Frees the ntlm_type1 message + * + * @param data message to be freed + * + * @ingroup ntlm_core */ void @@ -367,6 +436,19 @@ out: return ret; } +/** + * Encodes an ntlm_type1 message. + * + * @param type1 the ntlm_type1 message to encode. + * @param data is the return buffer with the encoded message, should be + * freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core + */ + int heim_ntlm_encode_type1(const struct ntlm_type1 *type1, struct ntlm_buf *data) { @@ -435,8 +517,12 @@ out: return ret; } -/* - * encoder/decoder type 2 messages +/** + * Frees the ntlm_type2 message + * + * @param data message to be freed + * + * @ingroup ntlm_core */ void @@ -444,7 +530,7 @@ heim_ntlm_free_type2(struct ntlm_type2 *data) { if (data->targetname) free(data->targetname); - _ntlm_free_buf(&data->targetinfo); + heim_ntlm_free_buf(&data->targetinfo); memset(data, 0, sizeof(*data)); } @@ -499,8 +585,21 @@ out: return ret; } +/** + * Encodes an ntlm_type2 message. + * + * @param type2 the ntlm_type2 message to encode. + * @param data is the return buffer with the encoded message, should be + * freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core + */ + int -heim_ntlm_encode_type2(struct ntlm_type2 *type2, struct ntlm_buf *data) +heim_ntlm_encode_type2(const struct ntlm_type2 *type2, struct ntlm_buf *data) { struct sec_buffer targetname, targetinfo; krb5_error_code ret; @@ -562,22 +661,26 @@ out: return ret; } -/* - * encoder/decoder type 2 messages +/** + * Frees the ntlm_type3 message + * + * @param data message to be freed + * + * @ingroup ntlm_core */ void heim_ntlm_free_type3(struct ntlm_type3 *data) { - _ntlm_free_buf(&data->lm); - _ntlm_free_buf(&data->ntlm); + heim_ntlm_free_buf(&data->lm); + heim_ntlm_free_buf(&data->ntlm); if (data->targetname) free(data->targetname); if (data->username) free(data->username); if (data->ws) free(data->ws); - _ntlm_free_buf(&data->sessionkey); + heim_ntlm_free_buf(&data->sessionkey); memset(data, 0, sizeof(*data)); } @@ -629,7 +732,7 @@ heim_ntlm_decode_type3(const struct ntlm_buf *buf, CHECK(ret_buf(in, &ntlm, &type3->ntlm), 0); CHECK(ret_string(in, ucs2, &target, &type3->targetname), 0); CHECK(ret_string(in, ucs2, &username, &type3->username), 0); - CHECK(ret_string(in, ucs2, &username, &type3->ws), 0); + CHECK(ret_string(in, ucs2, &ws, &type3->ws), 0); if (sessionkey.offset) CHECK(ret_buf(in, &sessionkey, &type3->sessionkey), 0); @@ -641,8 +744,21 @@ out: return ret; } +/** + * Encodes an ntlm_type3 message. + * + * @param type3 the ntlm_type3 message to encode. + * @param data is the return buffer with the encoded message, should be + * freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core + */ + int -heim_ntlm_encode_type3(struct ntlm_type3 *type3, struct ntlm_buf *data) +heim_ntlm_encode_type3(const struct ntlm_type3 *type3, struct ntlm_buf *data) { struct sec_buffer lm, ntlm, target, username, sessionkey, ws; krb5_error_code ret; @@ -766,8 +882,16 @@ splitandenc(unsigned char *hash, memset(key, 0, sizeof(key)); } -/* - * String-to-key function for NTLM +/** + * Calculate the NTLM key, the password is assumed to be in UTF8. + * + * @param password password to calcute the key for. + * @param key calcuted key, should be freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core */ int @@ -784,18 +908,28 @@ heim_ntlm_nt_key(const char *password, struct ntlm_buf *key) ret = ascii2ucs2le(password, 0, &buf); if (ret) { - _ntlm_free_buf(key); + heim_ntlm_free_buf(key); return ret; } MD4_Init(&ctx); MD4_Update(&ctx, buf.data, buf.length); MD4_Final(key->data, &ctx); - _ntlm_free_buf(&buf); + heim_ntlm_free_buf(&buf); return 0; } -/* +/** * Calculate NTLMv1 response hash + * + * @param key the ntlm v1 key + * @param len length of key + * @param challange sent by the server + * @param answer calculated answer, should be freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core */ int @@ -823,8 +957,18 @@ heim_ntlm_calculate_ntlm1(void *key, size_t len, return 0; } -/* - * Calculate NTLMv1 master key +/** + * Generates an NTLMv1 session random with assosited session master key. + * + * @param key the ntlm v1 key + * @param len length of key + * @param session generated session nonce, should be freed with heim_ntlm_free_buf(). + * @param master calculated session master key, should be freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core */ int @@ -849,8 +993,8 @@ heim_ntlm_build_ntlm1_master(void *key, size_t len, master->length = MD4_DIGEST_LENGTH; master->data = malloc(master->length); if (master->data == NULL) { - _ntlm_free_buf(master); - _ntlm_free_buf(session); + heim_ntlm_free_buf(master); + heim_ntlm_free_buf(session); return EINVAL; } @@ -866,8 +1010,8 @@ heim_ntlm_build_ntlm1_master(void *key, size_t len, } if (RAND_bytes(session->data, session->length) != 1) { - _ntlm_free_buf(master); - _ntlm_free_buf(session); + heim_ntlm_free_buf(master); + heim_ntlm_free_buf(session); return EINVAL; } @@ -877,8 +1021,16 @@ heim_ntlm_build_ntlm1_master(void *key, size_t len, return 0; } -/* +/** + * Generates an NTLMv2 session key. + * + * @param key the ntlm key + * @param len length of key + * @param username name of the user, as sent in the message, assumed to be in UTF8. + * @param target the name of the target, assumed to be in UTF8. + * @param ntlmv2 the ntlmv2 session key * + * @ingroup ntlm_core */ void @@ -932,8 +1084,22 @@ nt2unixtime(uint64_t t) } -/* +/** * Calculate NTLMv2 response + * + * @param key the ntlm key + * @param len length of key + * @param username name of the user, as sent in the message, assumed to be in UTF8. + * @param target the name of the target, assumed to be in UTF8. + * @param serverchallange challange as sent by the server in the type2 message. + * @param infotarget infotarget as sent by the server in the type2 message. + * @param ntlmv2 calculated session key + * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core */ int @@ -1020,8 +1186,23 @@ out: static const int authtimediff = 3600 * 2; /* 2 hours */ -/* +/** * Verify NTLMv2 response. + * + * @param key the ntlm key + * @param len length of key + * @param username name of the user, as sent in the message, assumed to be in UTF8. + * @param target the name of the target, assumed to be in UTF8. + * @param now the time now (0 if the library should pick it up itself) + * @param serverchallange challange as sent by the server in the type2 message. + * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf(). + * @param infotarget infotarget as sent by the server in the type2 message. + * @param ntlmv2 calculated session key + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core */ int @@ -1110,13 +1291,13 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len, HMAC_CTX_cleanup(&c); if (memcmp(serveranswer, clientanswer, 16) != 0) { - _ntlm_free_buf(infotarget); + heim_ntlm_free_buf(infotarget); return EINVAL; } return 0; out: - _ntlm_free_buf(infotarget); + heim_ntlm_free_buf(infotarget); if (sp) krb5_storage_free(sp); return ret; @@ -1125,6 +1306,17 @@ out: /* * Calculate the NTLM2 Session Response + * + * @param clnt_nonce client nonce + * @param svr_chal server challage + * @param ntlm2_hash ntlm hash + * @param lm The LM response, should be freed with heim_ntlm_free_buf(). + * @param ntlm The NTLM response, should be freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core */ int diff --git a/source4/heimdal/lib/vers/print_version.c b/source4/heimdal/lib/vers/print_version.c index 4337d591c42..325f3fa046f 100644 --- a/source4/heimdal/lib/vers/print_version.c +++ b/source4/heimdal/lib/vers/print_version.c @@ -33,7 +33,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> -RCSID("$Id: print_version.c 19566 2006-12-29 16:00:16Z lha $"); +RCSID("$Id: print_version.c 22428 2008-01-13 09:58:05Z lha $"); #endif #include "roken.h" @@ -50,6 +50,6 @@ print_version(const char *progname) if(*package_list == '\0') package_list = "no version information"; fprintf(stderr, "%s (%s)\n", progname, package_list); - fprintf(stderr, "Copyright 1995-2007 Kungliga Tekniska Högskolan\n"); + fprintf(stderr, "Copyright 1995-2008 Kungliga Tekniska Högskolan\n"); fprintf(stderr, "Send bug-reports to %s\n", PACKAGE_BUGREPORT); } diff --git a/source4/heimdal/lib/wind/bidi.c b/source4/heimdal/lib/wind/bidi.c new file mode 100644 index 00000000000..fa62989eac3 --- /dev/null +++ b/source4/heimdal/lib/wind/bidi.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "windlocl.h" + +#include <stdlib.h> + +#include "bidi_table.h" + +static int +range_entry_cmp(const void *a, const void *b) +{ + const struct range_entry *ea = (const struct range_entry*)a; + const struct range_entry *eb = (const struct range_entry*)b; + + if (ea->start >= eb->start && ea->start < eb->start + eb->len) + return 0; + return ea->start - eb->start; +} + +static int +is_ral(uint32_t cp) +{ + struct range_entry ee = {cp}; + void *s = bsearch(&ee, _wind_ral_table, _wind_ral_table_size, + sizeof(_wind_ral_table[0]), + range_entry_cmp); + return s != NULL; +} + +static int +is_l(uint32_t cp) +{ + struct range_entry ee = {cp}; + void *s = bsearch(&ee, _wind_l_table, _wind_l_table_size, + sizeof(_wind_l_table[0]), + range_entry_cmp); + return s != NULL; +} + +int +_wind_stringprep_testbidi(const uint32_t *in, size_t in_len, wind_profile_flags flags) +{ + size_t i; + unsigned ral = 0; + unsigned l = 0; + + if ((flags & (WIND_PROFILE_NAME|WIND_PROFILE_SASL)) == 0) + return 0; + + for (i = 0; i < in_len; ++i) { + ral |= is_ral(in[i]); + l |= is_l(in[i]); + } + if (ral) { + if (l) + return 1; + if (!is_ral(in[0]) || !is_ral(in[in_len - 1])) + return 1; + } + return 0; +} diff --git a/source4/heimdal/lib/wind/bidi_table.c b/source4/heimdal/lib/wind/bidi_table.c new file mode 100644 index 00000000000..34530b933d4 --- /dev/null +++ b/source4/heimdal/lib/wind/bidi_table.c @@ -0,0 +1,410 @@ +/* bidi_table.c */ +/* Automatically generated at 2008-03-18T11:38:07.839291 */ + + +#include "bidi_table.h" + +const struct range_entry _wind_ral_table[] = { + {0x5be, 1}, + {0x5c0, 1}, + {0x5c3, 1}, + {0x5d0, 0x1b}, + {0x5f0, 0x5}, + {0x61b, 1}, + {0x61f, 1}, + {0x621, 0x1a}, + {0x640, 0xb}, + {0x66d, 0x3}, + {0x671, 0x65}, + {0x6dd, 1}, + {0x6e5, 0x2}, + {0x6fa, 0x5}, + {0x700, 0xe}, + {0x710, 1}, + {0x712, 0x1b}, + {0x780, 0x26}, + {0x7b1, 1}, + {0x200f, 1}, + {0xfb1d, 1}, + {0xfb1f, 0xa}, + {0xfb2a, 0xd}, + {0xfb38, 0x5}, + {0xfb3e, 1}, + {0xfb40, 0x2}, + {0xfb43, 0x2}, + {0xfb46, 0x6c}, + {0xfbd3, 0x16b}, + {0xfd50, 0x40}, + {0xfd92, 0x36}, + {0xfdf0, 0xd}, + {0xfe70, 0x5}, + {0xfe76, 0x87}, +}; + +const size_t _wind_ral_table_size = 34; + +const struct range_entry _wind_l_table[] = { + {0x41, 0x1a}, + {0x61, 0x1a}, + {0xaa, 1}, + {0xb5, 1}, + {0xba, 1}, + {0xc0, 0x17}, + {0xd8, 0x1f}, + {0xf8, 0x129}, + {0x222, 0x12}, + {0x250, 0x5e}, + {0x2b0, 0x9}, + {0x2bb, 0x7}, + {0x2d0, 0x2}, + {0x2e0, 0x5}, + {0x2ee, 1}, + {0x37a, 1}, + {0x386, 1}, + {0x388, 0x3}, + {0x38c, 1}, + {0x38e, 0x14}, + {0x3a3, 0x2c}, + {0x3d0, 0x26}, + {0x400, 0x83}, + {0x48a, 0x45}, + {0x4d0, 0x26}, + {0x4f8, 0x2}, + {0x500, 0x10}, + {0x531, 0x26}, + {0x559, 0x7}, + {0x561, 0x27}, + {0x589, 1}, + {0x903, 1}, + {0x905, 0x35}, + {0x93d, 0x4}, + {0x949, 0x4}, + {0x950, 1}, + {0x958, 0xa}, + {0x964, 0xd}, + {0x982, 0x2}, + {0x985, 0x8}, + {0x98f, 0x2}, + {0x993, 0x16}, + {0x9aa, 0x7}, + {0x9b2, 1}, + {0x9b6, 0x4}, + {0x9be, 0x3}, + {0x9c7, 0x2}, + {0x9cb, 0x2}, + {0x9d7, 1}, + {0x9dc, 0x2}, + {0x9df, 0x3}, + {0x9e6, 0xc}, + {0x9f4, 0x7}, + {0xa05, 0x6}, + {0xa0f, 0x2}, + {0xa13, 0x16}, + {0xa2a, 0x7}, + {0xa32, 0x2}, + {0xa35, 0x2}, + {0xa38, 0x2}, + {0xa3e, 0x3}, + {0xa59, 0x4}, + {0xa5e, 1}, + {0xa66, 0xa}, + {0xa72, 0x3}, + {0xa83, 1}, + {0xa85, 0x7}, + {0xa8d, 1}, + {0xa8f, 0x3}, + {0xa93, 0x16}, + {0xaaa, 0x7}, + {0xab2, 0x2}, + {0xab5, 0x5}, + {0xabd, 0x4}, + {0xac9, 1}, + {0xacb, 0x2}, + {0xad0, 1}, + {0xae0, 1}, + {0xae6, 0xa}, + {0xb02, 0x2}, + {0xb05, 0x8}, + {0xb0f, 0x2}, + {0xb13, 0x16}, + {0xb2a, 0x7}, + {0xb32, 0x2}, + {0xb36, 0x4}, + {0xb3d, 0x2}, + {0xb40, 1}, + {0xb47, 0x2}, + {0xb4b, 0x2}, + {0xb57, 1}, + {0xb5c, 0x2}, + {0xb5f, 0x3}, + {0xb66, 0xb}, + {0xb83, 1}, + {0xb85, 0x6}, + {0xb8e, 0x3}, + {0xb92, 0x4}, + {0xb99, 0x2}, + {0xb9c, 1}, + {0xb9e, 0x2}, + {0xba3, 0x2}, + {0xba8, 0x3}, + {0xbae, 0x8}, + {0xbb7, 0x3}, + {0xbbe, 0x2}, + {0xbc1, 0x2}, + {0xbc6, 0x3}, + {0xbca, 0x3}, + {0xbd7, 1}, + {0xbe7, 0xc}, + {0xc01, 0x3}, + {0xc05, 0x8}, + {0xc0e, 0x3}, + {0xc12, 0x17}, + {0xc2a, 0xa}, + {0xc35, 0x5}, + {0xc41, 0x4}, + {0xc60, 0x2}, + {0xc66, 0xa}, + {0xc82, 0x2}, + {0xc85, 0x8}, + {0xc8e, 0x3}, + {0xc92, 0x17}, + {0xcaa, 0xa}, + {0xcb5, 0x5}, + {0xcbe, 1}, + {0xcc0, 0x5}, + {0xcc7, 0x2}, + {0xcca, 0x2}, + {0xcd5, 0x2}, + {0xcde, 1}, + {0xce0, 0x2}, + {0xce6, 0xa}, + {0xd02, 0x2}, + {0xd05, 0x8}, + {0xd0e, 0x3}, + {0xd12, 0x17}, + {0xd2a, 0x10}, + {0xd3e, 0x3}, + {0xd46, 0x3}, + {0xd4a, 0x3}, + {0xd57, 1}, + {0xd60, 0x2}, + {0xd66, 0xa}, + {0xd82, 0x2}, + {0xd85, 0x12}, + {0xd9a, 0x18}, + {0xdb3, 0x9}, + {0xdbd, 1}, + {0xdc0, 0x7}, + {0xdcf, 0x3}, + {0xdd8, 0x8}, + {0xdf2, 0x3}, + {0xe01, 0x30}, + {0xe32, 0x2}, + {0xe40, 0x7}, + {0xe4f, 0xd}, + {0xe81, 0x2}, + {0xe84, 1}, + {0xe87, 0x2}, + {0xe8a, 1}, + {0xe8d, 1}, + {0xe94, 0x4}, + {0xe99, 0x7}, + {0xea1, 0x3}, + {0xea5, 1}, + {0xea7, 1}, + {0xeaa, 0x2}, + {0xead, 0x4}, + {0xeb2, 0x2}, + {0xebd, 1}, + {0xec0, 0x5}, + {0xec6, 1}, + {0xed0, 0xa}, + {0xedc, 0x2}, + {0xf00, 0x18}, + {0xf1a, 0x1b}, + {0xf36, 1}, + {0xf38, 1}, + {0xf3e, 0xa}, + {0xf49, 0x22}, + {0xf7f, 1}, + {0xf85, 1}, + {0xf88, 0x4}, + {0xfbe, 0x8}, + {0xfc7, 0x6}, + {0xfcf, 1}, + {0x1000, 0x22}, + {0x1023, 0x5}, + {0x1029, 0x2}, + {0x102c, 1}, + {0x1031, 1}, + {0x1038, 1}, + {0x1040, 0x18}, + {0x10a0, 0x26}, + {0x10d0, 0x29}, + {0x10fb, 1}, + {0x1100, 0x5a}, + {0x115f, 0x44}, + {0x11a8, 0x52}, + {0x1200, 0x7}, + {0x1208, 0x3f}, + {0x1248, 1}, + {0x124a, 0x4}, + {0x1250, 0x7}, + {0x1258, 1}, + {0x125a, 0x4}, + {0x1260, 0x27}, + {0x1288, 1}, + {0x128a, 0x4}, + {0x1290, 0x1f}, + {0x12b0, 1}, + {0x12b2, 0x4}, + {0x12b8, 0x7}, + {0x12c0, 1}, + {0x12c2, 0x4}, + {0x12c8, 0x7}, + {0x12d0, 0x7}, + {0x12d8, 0x17}, + {0x12f0, 0x1f}, + {0x1310, 1}, + {0x1312, 0x4}, + {0x1318, 0x7}, + {0x1320, 0x27}, + {0x1348, 0x13}, + {0x1361, 0x1c}, + {0x13a0, 0x55}, + {0x1401, 0x276}, + {0x1681, 0x1a}, + {0x16a0, 0x51}, + {0x1700, 0xd}, + {0x170e, 0x4}, + {0x1720, 0x12}, + {0x1735, 0x2}, + {0x1740, 0x12}, + {0x1760, 0xd}, + {0x176e, 0x3}, + {0x1780, 0x37}, + {0x17be, 0x8}, + {0x17c7, 0x2}, + {0x17d4, 0x7}, + {0x17dc, 1}, + {0x17e0, 0xa}, + {0x1810, 0xa}, + {0x1820, 0x58}, + {0x1880, 0x29}, + {0x1e00, 0x9c}, + {0x1ea0, 0x5a}, + {0x1f00, 0x16}, + {0x1f18, 0x6}, + {0x1f20, 0x26}, + {0x1f48, 0x6}, + {0x1f50, 0x8}, + {0x1f59, 1}, + {0x1f5b, 1}, + {0x1f5d, 1}, + {0x1f5f, 0x1f}, + {0x1f80, 0x35}, + {0x1fb6, 0x7}, + {0x1fbe, 1}, + {0x1fc2, 0x3}, + {0x1fc6, 0x7}, + {0x1fd0, 0x4}, + {0x1fd6, 0x6}, + {0x1fe0, 0xd}, + {0x1ff2, 0x3}, + {0x1ff6, 0x7}, + {0x200e, 1}, + {0x2071, 1}, + {0x207f, 1}, + {0x2102, 1}, + {0x2107, 1}, + {0x210a, 0xa}, + {0x2115, 1}, + {0x2119, 0x5}, + {0x2124, 1}, + {0x2126, 1}, + {0x2128, 1}, + {0x212a, 0x4}, + {0x212f, 0x3}, + {0x2133, 0x7}, + {0x213d, 0x3}, + {0x2145, 0x5}, + {0x2160, 0x24}, + {0x2336, 0x45}, + {0x2395, 1}, + {0x249c, 0x4e}, + {0x3005, 0x3}, + {0x3021, 0x9}, + {0x3031, 0x5}, + {0x3038, 0x5}, + {0x3041, 0x56}, + {0x309d, 0x3}, + {0x30a1, 0x5a}, + {0x30fc, 0x4}, + {0x3105, 0x28}, + {0x3131, 0x5e}, + {0x3190, 0x28}, + {0x31f0, 0x2d}, + {0x3220, 0x24}, + {0x3260, 0x1c}, + {0x327f, 0x32}, + {0x32c0, 0xc}, + {0x32d0, 0x2f}, + {0x3300, 0x77}, + {0x337b, 0x63}, + {0x33e0, 0x1f}, + {0x3400, 0x19b6}, + {0x4e00, 0x51a6}, + {0xa000, 0x48d}, + {0xac00, 0x2ba4}, + {0xd800, 0x222e}, + {0xfa30, 0x3b}, + {0xfb00, 0x7}, + {0xfb13, 0x5}, + {0xff21, 0x1a}, + {0xff41, 0x1a}, + {0xff66, 0x59}, + {0xffc2, 0x6}, + {0xffca, 0x6}, + {0xffd2, 0x6}, + {0xffda, 0x3}, + {0x10300, 0x1f}, + {0x10320, 0x4}, + {0x10330, 0x1b}, + {0x10400, 0x26}, + {0x10428, 0x26}, + {0x1d000, 0xf6}, + {0x1d100, 0x27}, + {0x1d12a, 0x3d}, + {0x1d16a, 0x9}, + {0x1d183, 0x2}, + {0x1d18c, 0x1e}, + {0x1d1ae, 0x30}, + {0x1d400, 0x55}, + {0x1d456, 0x47}, + {0x1d49e, 0x2}, + {0x1d4a2, 1}, + {0x1d4a5, 0x2}, + {0x1d4a9, 0x4}, + {0x1d4ae, 0xc}, + {0x1d4bb, 1}, + {0x1d4bd, 0x4}, + {0x1d4c2, 0x2}, + {0x1d4c5, 0x41}, + {0x1d507, 0x4}, + {0x1d50d, 0x8}, + {0x1d516, 0x7}, + {0x1d51e, 0x1c}, + {0x1d53b, 0x4}, + {0x1d540, 0x5}, + {0x1d546, 1}, + {0x1d54a, 0x7}, + {0x1d552, 0x152}, + {0x1d6a8, 0x122}, + {0x20000, 0xa6d7}, + {0x2f800, 0x21e}, + {0xf0000, 0xfffe}, + {0x100000, 0xfffe}, +}; + +const size_t _wind_l_table_size = 360; + diff --git a/source4/heimdal/lib/wind/bidi_table.h b/source4/heimdal/lib/wind/bidi_table.h new file mode 100644 index 00000000000..2e369f2d9a5 --- /dev/null +++ b/source4/heimdal/lib/wind/bidi_table.h @@ -0,0 +1,21 @@ +/* bidi_table.h */ +/* Automatically generated at 2008-03-18T11:38:07.839121 */ + +#ifndef BIDI_TABLE_H +#define BIDI_TABLE_H 1 + +#include <stdint.h> +#include <stddef.h> + +struct range_entry { + uint32_t start; + unsigned len; +}; + +extern const struct range_entry _wind_ral_table[]; +extern const struct range_entry _wind_l_table[]; + +extern const size_t _wind_ral_table_size; +extern const size_t _wind_l_table_size; + +#endif /* BIDI_TABLE_H */ diff --git a/source4/heimdal/lib/wind/combining.c b/source4/heimdal/lib/wind/combining.c new file mode 100644 index 00000000000..8481cab8591 --- /dev/null +++ b/source4/heimdal/lib/wind/combining.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "windlocl.h" + +#include <stdlib.h> + +#include "combining_table.h" + +static int +translation_cmp(const void *key, const void *data) +{ + const struct translation *t1 = (const struct translation *)key; + const struct translation *t2 = (const struct translation *)data; + + return t1->key - t2->key; +} + +int +_wind_combining_class(uint32_t code_point) +{ + struct translation ts = {code_point}; + void *s = bsearch(&ts, _wind_combining_table, _wind_combining_table_size, + sizeof(_wind_combining_table[0]), + translation_cmp); + if (s != NULL) { + const struct translation *t = (const struct translation *)s; + return t->combining_class; + } else { + return 0; + } +} diff --git a/source4/heimdal/lib/wind/combining_table.c b/source4/heimdal/lib/wind/combining_table.c new file mode 100644 index 00000000000..7abd1cf76d0 --- /dev/null +++ b/source4/heimdal/lib/wind/combining_table.c @@ -0,0 +1,362 @@ +/* combining_table.c */ +/* Automatically generated at 2008-03-18T11:38:08.166082 */ + + +#include "combining_table.h" + +const struct translation _wind_combining_table[] = { +{0x300, 230}, /* Mn */ +{0x301, 230}, /* Mn */ +{0x302, 230}, /* Mn */ +{0x303, 230}, /* Mn */ +{0x304, 230}, /* Mn */ +{0x305, 230}, /* Mn */ +{0x306, 230}, /* Mn */ +{0x307, 230}, /* Mn */ +{0x308, 230}, /* Mn */ +{0x309, 230}, /* Mn */ +{0x30a, 230}, /* Mn */ +{0x30b, 230}, /* Mn */ +{0x30c, 230}, /* Mn */ +{0x30d, 230}, /* Mn */ +{0x30e, 230}, /* Mn */ +{0x30f, 230}, /* Mn */ +{0x310, 230}, /* Mn */ +{0x311, 230}, /* Mn */ +{0x312, 230}, /* Mn */ +{0x313, 230}, /* Mn */ +{0x314, 230}, /* Mn */ +{0x315, 232}, /* Mn */ +{0x316, 220}, /* Mn */ +{0x317, 220}, /* Mn */ +{0x318, 220}, /* Mn */ +{0x319, 220}, /* Mn */ +{0x31a, 232}, /* Mn */ +{0x31b, 216}, /* Mn */ +{0x31c, 220}, /* Mn */ +{0x31d, 220}, /* Mn */ +{0x31e, 220}, /* Mn */ +{0x31f, 220}, /* Mn */ +{0x320, 220}, /* Mn */ +{0x321, 202}, /* Mn */ +{0x322, 202}, /* Mn */ +{0x323, 220}, /* Mn */ +{0x324, 220}, /* Mn */ +{0x325, 220}, /* Mn */ +{0x326, 220}, /* Mn */ +{0x327, 202}, /* Mn */ +{0x328, 202}, /* Mn */ +{0x329, 220}, /* Mn */ +{0x32a, 220}, /* Mn */ +{0x32b, 220}, /* Mn */ +{0x32c, 220}, /* Mn */ +{0x32d, 220}, /* Mn */ +{0x32e, 220}, /* Mn */ +{0x32f, 220}, /* Mn */ +{0x330, 220}, /* Mn */ +{0x331, 220}, /* Mn */ +{0x332, 220}, /* Mn */ +{0x333, 220}, /* Mn */ +{0x334, 1}, /* Mn */ +{0x335, 1}, /* Mn */ +{0x336, 1}, /* Mn */ +{0x337, 1}, /* Mn */ +{0x338, 1}, /* Mn */ +{0x339, 220}, /* Mn */ +{0x33a, 220}, /* Mn */ +{0x33b, 220}, /* Mn */ +{0x33c, 220}, /* Mn */ +{0x33d, 230}, /* Mn */ +{0x33e, 230}, /* Mn */ +{0x33f, 230}, /* Mn */ +{0x340, 230}, /* Mn */ +{0x341, 230}, /* Mn */ +{0x342, 230}, /* Mn */ +{0x343, 230}, /* Mn */ +{0x344, 230}, /* Mn */ +{0x345, 240}, /* Mn */ +{0x346, 230}, /* Mn */ +{0x347, 220}, /* Mn */ +{0x348, 220}, /* Mn */ +{0x349, 220}, /* Mn */ +{0x34a, 230}, /* Mn */ +{0x34b, 230}, /* Mn */ +{0x34c, 230}, /* Mn */ +{0x34d, 220}, /* Mn */ +{0x34e, 220}, /* Mn */ +{0x350, 230}, /* Mn */ +{0x351, 230}, /* Mn */ +{0x352, 230}, /* Mn */ +{0x353, 220}, /* Mn */ +{0x354, 220}, /* Mn */ +{0x355, 220}, /* Mn */ +{0x356, 220}, /* Mn */ +{0x357, 230}, /* Mn */ +{0x35d, 234}, /* Mn */ +{0x35e, 234}, /* Mn */ +{0x35f, 233}, /* Mn */ +{0x360, 234}, /* Mn */ +{0x361, 234}, /* Mn */ +{0x362, 233}, /* Mn */ +{0x363, 230}, /* Mn */ +{0x364, 230}, /* Mn */ +{0x365, 230}, /* Mn */ +{0x366, 230}, /* Mn */ +{0x367, 230}, /* Mn */ +{0x368, 230}, /* Mn */ +{0x369, 230}, /* Mn */ +{0x36a, 230}, /* Mn */ +{0x36b, 230}, /* Mn */ +{0x36c, 230}, /* Mn */ +{0x36d, 230}, /* Mn */ +{0x36e, 230}, /* Mn */ +{0x36f, 230}, /* Mn */ +{0x483, 230}, /* Mn */ +{0x484, 230}, /* Mn */ +{0x485, 230}, /* Mn */ +{0x486, 230}, /* Mn */ +{0x591, 220}, /* Mn */ +{0x592, 230}, /* Mn */ +{0x593, 230}, /* Mn */ +{0x594, 230}, /* Mn */ +{0x595, 230}, /* Mn */ +{0x596, 220}, /* Mn */ +{0x597, 230}, /* Mn */ +{0x598, 230}, /* Mn */ +{0x599, 230}, /* Mn */ +{0x59a, 222}, /* Mn */ +{0x59b, 220}, /* Mn */ +{0x59c, 230}, /* Mn */ +{0x59d, 230}, /* Mn */ +{0x59e, 230}, /* Mn */ +{0x59f, 230}, /* Mn */ +{0x5a0, 230}, /* Mn */ +{0x5a1, 230}, /* Mn */ +{0x5a3, 220}, /* Mn */ +{0x5a4, 220}, /* Mn */ +{0x5a5, 220}, /* Mn */ +{0x5a6, 220}, /* Mn */ +{0x5a7, 220}, /* Mn */ +{0x5a8, 230}, /* Mn */ +{0x5a9, 230}, /* Mn */ +{0x5aa, 220}, /* Mn */ +{0x5ab, 230}, /* Mn */ +{0x5ac, 230}, /* Mn */ +{0x5ad, 222}, /* Mn */ +{0x5ae, 228}, /* Mn */ +{0x5af, 230}, /* Mn */ +{0x5b0, 10}, /* Mn */ +{0x5b1, 11}, /* Mn */ +{0x5b2, 12}, /* Mn */ +{0x5b3, 13}, /* Mn */ +{0x5b4, 14}, /* Mn */ +{0x5b5, 15}, /* Mn */ +{0x5b6, 16}, /* Mn */ +{0x5b7, 17}, /* Mn */ +{0x5b8, 18}, /* Mn */ +{0x5b9, 19}, /* Mn */ +{0x5bb, 20}, /* Mn */ +{0x5bc, 21}, /* Mn */ +{0x5bd, 22}, /* Mn */ +{0x5bf, 23}, /* Mn */ +{0x5c1, 24}, /* Mn */ +{0x5c2, 25}, /* Mn */ +{0x5c4, 230}, /* Mn */ +{0x610, 230}, /* Mn */ +{0x611, 230}, /* Mn */ +{0x612, 230}, /* Mn */ +{0x613, 230}, /* Mn */ +{0x614, 230}, /* Mn */ +{0x615, 230}, /* Mn */ +{0x64b, 27}, /* Mn */ +{0x64c, 28}, /* Mn */ +{0x64d, 29}, /* Mn */ +{0x64e, 30}, /* Mn */ +{0x64f, 31}, /* Mn */ +{0x650, 32}, /* Mn */ +{0x651, 33}, /* Mn */ +{0x652, 34}, /* Mn */ +{0x653, 230}, /* Mn */ +{0x654, 230}, /* Mn */ +{0x655, 220}, /* Mn */ +{0x656, 220}, /* Mn */ +{0x657, 230}, /* Mn */ +{0x658, 230}, /* Mn */ +{0x670, 35}, /* Mn */ +{0x6d6, 230}, /* Mn */ +{0x6d7, 230}, /* Mn */ +{0x6d8, 230}, /* Mn */ +{0x6d9, 230}, /* Mn */ +{0x6da, 230}, /* Mn */ +{0x6db, 230}, /* Mn */ +{0x6dc, 230}, /* Mn */ +{0x6df, 230}, /* Mn */ +{0x6e0, 230}, /* Mn */ +{0x6e1, 230}, /* Mn */ +{0x6e2, 230}, /* Mn */ +{0x6e3, 220}, /* Mn */ +{0x6e4, 230}, /* Mn */ +{0x6e7, 230}, /* Mn */ +{0x6e8, 230}, /* Mn */ +{0x6ea, 220}, /* Mn */ +{0x6eb, 230}, /* Mn */ +{0x6ec, 230}, /* Mn */ +{0x6ed, 220}, /* Mn */ +{0x711, 36}, /* Mn */ +{0x730, 230}, /* Mn */ +{0x731, 220}, /* Mn */ +{0x732, 230}, /* Mn */ +{0x733, 230}, /* Mn */ +{0x734, 220}, /* Mn */ +{0x735, 230}, /* Mn */ +{0x736, 230}, /* Mn */ +{0x737, 220}, /* Mn */ +{0x738, 220}, /* Mn */ +{0x739, 220}, /* Mn */ +{0x73a, 230}, /* Mn */ +{0x73b, 220}, /* Mn */ +{0x73c, 220}, /* Mn */ +{0x73d, 230}, /* Mn */ +{0x73e, 220}, /* Mn */ +{0x73f, 230}, /* Mn */ +{0x740, 230}, /* Mn */ +{0x741, 230}, /* Mn */ +{0x742, 220}, /* Mn */ +{0x743, 230}, /* Mn */ +{0x744, 220}, /* Mn */ +{0x745, 230}, /* Mn */ +{0x746, 220}, /* Mn */ +{0x747, 230}, /* Mn */ +{0x748, 220}, /* Mn */ +{0x749, 230}, /* Mn */ +{0x74a, 230}, /* Mn */ +{0x93c, 7}, /* Mn */ +{0x94d, 9}, /* Mn */ +{0x951, 230}, /* Mn */ +{0x952, 220}, /* Mn */ +{0x953, 230}, /* Mn */ +{0x954, 230}, /* Mn */ +{0x9bc, 7}, /* Mn */ +{0x9cd, 9}, /* Mn */ +{0xa3c, 7}, /* Mn */ +{0xa4d, 9}, /* Mn */ +{0xabc, 7}, /* Mn */ +{0xacd, 9}, /* Mn */ +{0xb3c, 7}, /* Mn */ +{0xb4d, 9}, /* Mn */ +{0xbcd, 9}, /* Mn */ +{0xc4d, 9}, /* Mn */ +{0xc55, 84}, /* Mn */ +{0xc56, 91}, /* Mn */ +{0xcbc, 7}, /* Mn */ +{0xccd, 9}, /* Mn */ +{0xd4d, 9}, /* Mn */ +{0xdca, 9}, /* Mn */ +{0xe38, 103}, /* Mn */ +{0xe39, 103}, /* Mn */ +{0xe3a, 9}, /* Mn */ +{0xe48, 107}, /* Mn */ +{0xe49, 107}, /* Mn */ +{0xe4a, 107}, /* Mn */ +{0xe4b, 107}, /* Mn */ +{0xeb8, 118}, /* Mn */ +{0xeb9, 118}, /* Mn */ +{0xec8, 122}, /* Mn */ +{0xec9, 122}, /* Mn */ +{0xeca, 122}, /* Mn */ +{0xecb, 122}, /* Mn */ +{0xf18, 220}, /* Mn */ +{0xf19, 220}, /* Mn */ +{0xf35, 220}, /* Mn */ +{0xf37, 220}, /* Mn */ +{0xf39, 216}, /* Mn */ +{0xf71, 129}, /* Mn */ +{0xf72, 130}, /* Mn */ +{0xf74, 132}, /* Mn */ +{0xf7a, 130}, /* Mn */ +{0xf7b, 130}, /* Mn */ +{0xf7c, 130}, /* Mn */ +{0xf7d, 130}, /* Mn */ +{0xf80, 130}, /* Mn */ +{0xf82, 230}, /* Mn */ +{0xf83, 230}, /* Mn */ +{0xf84, 9}, /* Mn */ +{0xf86, 230}, /* Mn */ +{0xf87, 230}, /* Mn */ +{0xfc6, 220}, /* Mn */ +{0x1037, 7}, /* Mn */ +{0x1039, 9}, /* Mn */ +{0x1714, 9}, /* Mn */ +{0x1734, 9}, /* Mn */ +{0x17d2, 9}, /* Mn */ +{0x17dd, 230}, /* Mn */ +{0x18a9, 228}, /* Mn */ +{0x1939, 222}, /* Mn */ +{0x193a, 230}, /* Mn */ +{0x193b, 220}, /* Mn */ +{0x20d0, 230}, /* Mn */ +{0x20d1, 230}, /* Mn */ +{0x20d2, 1}, /* Mn */ +{0x20d3, 1}, /* Mn */ +{0x20d4, 230}, /* Mn */ +{0x20d5, 230}, /* Mn */ +{0x20d6, 230}, /* Mn */ +{0x20d7, 230}, /* Mn */ +{0x20d8, 1}, /* Mn */ +{0x20d9, 1}, /* Mn */ +{0x20da, 1}, /* Mn */ +{0x20db, 230}, /* Mn */ +{0x20dc, 230}, /* Mn */ +{0x20e1, 230}, /* Mn */ +{0x20e5, 1}, /* Mn */ +{0x20e6, 1}, /* Mn */ +{0x20e7, 230}, /* Mn */ +{0x20e8, 220}, /* Mn */ +{0x20e9, 230}, /* Mn */ +{0x20ea, 1}, /* Mn */ +{0x302a, 218}, /* Mn */ +{0x302b, 228}, /* Mn */ +{0x302c, 232}, /* Mn */ +{0x302d, 222}, /* Mn */ +{0x302e, 224}, /* Mn */ +{0x302f, 224}, /* Mn */ +{0x3099, 8}, /* Mn */ +{0x309a, 8}, /* Mn */ +{0xfb1e, 26}, /* Mn */ +{0xfe20, 230}, /* Mn */ +{0xfe21, 230}, /* Mn */ +{0xfe22, 230}, /* Mn */ +{0xfe23, 230}, /* Mn */ +{0x1d165, 216}, /* Mc */ +{0x1d166, 216}, /* Mc */ +{0x1d167, 1}, /* Mn */ +{0x1d168, 1}, /* Mn */ +{0x1d169, 1}, /* Mn */ +{0x1d16d, 226}, /* Mc */ +{0x1d16e, 216}, /* Mc */ +{0x1d16f, 216}, /* Mc */ +{0x1d170, 216}, /* Mc */ +{0x1d171, 216}, /* Mc */ +{0x1d172, 216}, /* Mc */ +{0x1d17b, 220}, /* Mn */ +{0x1d17c, 220}, /* Mn */ +{0x1d17d, 220}, /* Mn */ +{0x1d17e, 220}, /* Mn */ +{0x1d17f, 220}, /* Mn */ +{0x1d180, 220}, /* Mn */ +{0x1d181, 220}, /* Mn */ +{0x1d182, 220}, /* Mn */ +{0x1d185, 230}, /* Mn */ +{0x1d186, 230}, /* Mn */ +{0x1d187, 230}, /* Mn */ +{0x1d188, 230}, /* Mn */ +{0x1d189, 230}, /* Mn */ +{0x1d18a, 220}, /* Mn */ +{0x1d18b, 220}, /* Mn */ +{0x1d1aa, 230}, /* Mn */ +{0x1d1ab, 230}, /* Mn */ +{0x1d1ac, 230}, /* Mn */ +{0x1d1ad, 230}, /* Mn */ + +}; +const size_t _wind_combining_table_size = 352; diff --git a/source4/heimdal/lib/wind/combining_table.h b/source4/heimdal/lib/wind/combining_table.h new file mode 100644 index 00000000000..000af13ea88 --- /dev/null +++ b/source4/heimdal/lib/wind/combining_table.h @@ -0,0 +1,18 @@ +/* combining_table.h */ +/* Automatically generated at 2008-03-18T11:38:08.165877 */ + +#ifndef COMBINING_TABLE_H +#define COMBINING_TABLE_H 1 + +#include <stddef.h> +#include <stdint.h> + +struct translation { + uint32_t key; + unsigned combining_class; +}; + +extern const struct translation _wind_combining_table[]; + +extern const size_t _wind_combining_table_size; +#endif /* COMBINING_TABLE_H */ diff --git a/source4/heimdal/lib/wind/errorlist.c b/source4/heimdal/lib/wind/errorlist.c new file mode 100644 index 00000000000..9a65338cd24 --- /dev/null +++ b/source4/heimdal/lib/wind/errorlist.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "windlocl.h" + +#include <stdlib.h> + +#include "errorlist_table.h" + +static int +error_entry_cmp(const void *a, const void *b) +{ + const struct error_entry *ea = (const struct error_entry*)a; + const struct error_entry *eb = (const struct error_entry*)b; + + if (ea->start >= eb->start && ea->start < eb->start + eb->len) + return 0; + return ea->start - eb->start; +} + +int +_wind_stringprep_error(uint32_t cp, wind_profile_flags flags) +{ + struct error_entry ee = {cp}; + const struct error_entry *s; + + s = (const struct error_entry *) + bsearch(&ee, _wind_errorlist_table, + _wind_errorlist_table_size, + sizeof(_wind_errorlist_table[0]), + error_entry_cmp); + if (s == NULL) + return 0; + return (s->flags & flags); +} + +int +_wind_stringprep_prohibited(const uint32_t *in, size_t in_len, + wind_profile_flags flags) +{ + unsigned i; + + for (i = 0; i < in_len; ++i) + if (_wind_stringprep_error(in[i], flags)) + return 1; + return 0; +} diff --git a/source4/heimdal/lib/wind/errorlist_table.c b/source4/heimdal/lib/wind/errorlist_table.c new file mode 100644 index 00000000000..5d5d8caaf27 --- /dev/null +++ b/source4/heimdal/lib/wind/errorlist_table.c @@ -0,0 +1,88 @@ +/* errorlist_table.c */ +/* Automatically generated at 2008-03-18T11:38:08.266475 */ + + +#include "errorlist_table.h" + +const struct error_entry _wind_errorlist_table[] = { + {0x0, 0x20, WIND_PROFILE_SASL}, /* C.2.1: [CONTROL CHARACTERS] */ + {0x7f, 0x1, WIND_PROFILE_SASL}, /* C.2.1: DELETE */ + {0x80, 0x20, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: [CONTROL CHARACTERS] */ + {0xa0, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: NO-BREAK SPACE */ + {0x340, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: COMBINING GRAVE TONE MARK */ + {0x341, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: COMBINING ACUTE TONE MARK */ + {0x6dd, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: ARABIC END OF AYAH */ + {0x70f, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: SYRIAC ABBREVIATION MARK */ + {0x1680, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: OGHAM SPACE MARK */ + {0x180e, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: MONGOLIAN VOWEL SEPARATOR */ + {0x2000, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: EN QUAD */ + {0x2001, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: EM QUAD */ + {0x2002, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: EN SPACE */ + {0x2003, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: EM SPACE */ + {0x2004, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: THREE-PER-EM SPACE */ + {0x2005, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: FOUR-PER-EM SPACE */ + {0x2006, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: SIX-PER-EM SPACE */ + {0x2007, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: FIGURE SPACE */ + {0x2008, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: PUNCTUATION SPACE */ + {0x2009, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: THIN SPACE */ + {0x200a, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: HAIR SPACE */ + {0x200b, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: ZERO WIDTH SPACE */ + {0x200c, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: ZERO WIDTH NON-JOINER */ + {0x200d, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: ZERO WIDTH JOINER */ + {0x200e, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: LEFT-TO-RIGHT MARK */ + {0x200f, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: RIGHT-TO-LEFT MARK */ + {0x2028, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: LINE SEPARATOR */ + {0x2029, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: PARAGRAPH SEPARATOR */ + {0x202a, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: LEFT-TO-RIGHT EMBEDDING */ + {0x202b, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: RIGHT-TO-LEFT EMBEDDING */ + {0x202c, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: POP DIRECTIONAL FORMATTING */ + {0x202d, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: LEFT-TO-RIGHT OVERRIDE */ + {0x202e, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: RIGHT-TO-LEFT OVERRIDE */ + {0x202f, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: NARROW NO-BREAK SPACE */ + {0x205f, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: MEDIUM MATHEMATICAL SPACE */ + {0x2060, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: WORD JOINER */ + {0x2061, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: FUNCTION APPLICATION */ + {0x2062, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: INVISIBLE TIMES */ + {0x2063, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: INVISIBLE SEPARATOR */ + {0x206a, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL|WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.8,C.2.2: INHIBIT SYMMETRIC SWAPPING */ + {0x206b, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: ACTIVATE SYMMETRIC SWAPPING */ + {0x206c, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: INHIBIT ARABIC FORM SHAPING */ + {0x206d, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: ACTIVATE ARABIC FORM SHAPING */ + {0x206e, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: NATIONAL DIGIT SHAPES */ + {0x206f, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.8: NOMINAL DIGIT SHAPES */ + {0x2ff0, 0xc, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.7: [IDEOGRAPHIC DESCRIPTION CHARACTERS] */ + {0x3000, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.1.2: IDEOGRAPHIC SPACE */ + {0xd800, 0x800, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.5: [SURROGATE CODES] */ + {0xe000, 0x1900, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.3: [PRIVATE USE, PLANE 0] */ + {0xfdd0, 0x20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0xfeff, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: ZERO WIDTH NO-BREAK SPACE */ + {0xfff9, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.6,C.2.2: INTERLINEAR ANNOTATION ANCHOR */ + {0xfffa, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.6: INTERLINEAR ANNOTATION SEPARATOR */ + {0xfffb, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.6: INTERLINEAR ANNOTATION TERMINATOR */ + {0xfffc, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.6: OBJECT REPLACEMENT CHARACTER */ + {0xfffd, 0x1, WIND_PROFILE_LDAP|WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* rfc4518-error,C.6: */ + {0xfffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0x1d173, 0x8, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.2.2: [MUSICAL CONTROL CHARACTERS] */ + {0x1fffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0x2fffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0x3fffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0x4fffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0x5fffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0x6fffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0x7fffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0x8fffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0x9fffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0xafffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0xbfffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0xcfffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0xdfffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0xe0001, 0x1, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.9: LANGUAGE TAG */ + {0xe0020, 0x60, WIND_PROFILE_NAME|WIND_PROFILE_SASL}, /* C.9: [TAGGING CHARACTERS] */ + {0xefffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0xf0000, 0xfffe, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.3: [PRIVATE USE, PLANE 15] */ + {0xffffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ + {0x100000, 0xfffe, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.3: [PRIVATE USE, PLANE 16] */ + {0x10fffe, 0x2, WIND_PROFILE_NAME|WIND_PROFILE_LDAP|WIND_PROFILE_SASL}, /* C.4: [NONCHARACTER CODE POINTS] */ +}; + +const size_t _wind_errorlist_table_size = 78; diff --git a/source4/heimdal/lib/wind/errorlist_table.h b/source4/heimdal/lib/wind/errorlist_table.h new file mode 100644 index 00000000000..5fc9ddbf044 --- /dev/null +++ b/source4/heimdal/lib/wind/errorlist_table.h @@ -0,0 +1,19 @@ +/* errorlist_table.h */ +/* Automatically generated at 2008-03-18T11:38:08.266305 */ + +#ifndef ERRORLIST_TABLE_H +#define ERRORLIST_TABLE_H 1 + +#include "windlocl.h" + +struct error_entry { + uint32_t start; + unsigned len; + wind_profile_flags flags; +}; + +extern const struct error_entry _wind_errorlist_table[]; + +extern const size_t _wind_errorlist_table_size; + +#endif /* ERRORLIST_TABLE_H */ diff --git a/source4/heimdal/lib/wind/ldap.c b/source4/heimdal/lib/wind/ldap.c new file mode 100644 index 00000000000..1ff681fc31e --- /dev/null +++ b/source4/heimdal/lib/wind/ldap.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "windlocl.h" +#include <assert.h> + +static int +put_char(uint32_t *out, size_t *o, uint32_t c, size_t out_len) +{ + if (*o >= out_len) + return 1; + out[*o] = c; + (*o)++; + return 0; +} + +int +_wind_ldap_case_exact_attribute(const uint32_t *tmp, + size_t olen, + uint32_t *out, + size_t *out_len) +{ + size_t o = 0, i = 0; + + if (olen == 0) { + *out_len = 0; + return 0; + } + + if (put_char(out, &o, 0x20, *out_len)) + return WIND_ERR_OVERRUN; + while(i < olen && tmp[i] == 0x20) /* skip initial spaces */ + i++; + + while (i < olen) { + if (tmp[i] == 0x20) { + if (put_char(out, &o, 0x20, *out_len) || + put_char(out, &o, 0x20, *out_len)) + return WIND_ERR_OVERRUN; + while(i < olen && tmp[i] == 0x20) /* skip middle spaces */ + i++; + } else { + if (put_char(out, &o, tmp[i++], *out_len)) + return WIND_ERR_OVERRUN; + } + } + assert(o > 0); + + /* only one spaces at the end */ + if (o == 1 && out[0] == 0x20) + o = 0; + else if (out[o - 1] == 0x20) { + if (out[o - 2] == 0x20) + o--; + } else + put_char(out, &o, 0x20, *out_len); + + *out_len = o; + + return 0; +} diff --git a/source4/heimdal/lib/wind/map.c b/source4/heimdal/lib/wind/map.c new file mode 100644 index 00000000000..ae6d10e5126 --- /dev/null +++ b/source4/heimdal/lib/wind/map.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "windlocl.h" + +#include <stdlib.h> + +#include "map_table.h" + +RCSID("$Id: map.c 22556 2008-02-01 16:38:46Z lha $"); + +static int +translation_cmp(const void *key, const void *data) +{ + const struct translation *t1 = (const struct translation *)key; + const struct translation *t2 = (const struct translation *)data; + + return t1->key - t2->key; +} + +int +_wind_stringprep_map(const uint32_t *in, size_t in_len, + uint32_t *out, size_t *out_len, + wind_profile_flags flags) +{ + unsigned i; + unsigned o = 0; + + for (i = 0; i < in_len; ++i) { + struct translation ts = {in[i]}; + const struct translation *s; + + s = (const struct translation *) + bsearch(&ts, _wind_map_table, _wind_map_table_size, + sizeof(_wind_map_table[0]), + translation_cmp); + if (s != NULL && (s->flags & flags)) { + unsigned j; + + for (j = 0; j < s->val_len; ++j) { + if (o >= *out_len) + return WIND_ERR_OVERRUN; + out[o++] = _wind_map_table_val[s->val_offset + j]; + } + } else { + if (o >= *out_len) + return WIND_ERR_OVERRUN; + out[o++] = in[i]; + + } + } + *out_len = o; + return 0; +} diff --git a/source4/heimdal/lib/wind/map_table.c b/source4/heimdal/lib/wind/map_table.c new file mode 100644 index 00000000000..e4dba94ea68 --- /dev/null +++ b/source4/heimdal/lib/wind/map_table.c @@ -0,0 +1,2613 @@ +/* map_table.c */ +/* Automatically generated at 2008-03-18T11:38:08.353797 */ + + +#include "map_table.h" + +const struct translation _wind_map_table[] = { + {0x0, 0, 0, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1, 0, 0, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x2, 0, 0, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x3, 0, 0, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x4, 0, 0, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x5, 0, 0, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x6, 0, 0, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x7, 0, 0, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x9, 1, 0, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0xa, 1, 1, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0xb, 1, 2, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0xc, 1, 3, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0xd, 1, 4, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0xe, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xf, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x10, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x11, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x12, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x13, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x14, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x15, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x16, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x17, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x18, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x19, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1a, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1b, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1c, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1d, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1e, 0, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x20, 1, 5, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x41, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x42, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x43, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x44, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x45, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x46, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x47, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x48, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x49, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4a, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4b, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4c, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4d, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4e, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4f, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x50, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x51, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x52, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x53, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x54, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x55, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x56, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x57, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x58, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x59, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x5a, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x7f, 0, 32, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x80, 0, 32, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x81, 0, 32, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x82, 0, 32, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x83, 0, 32, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x85, 1, 32, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x86, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x87, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x88, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x89, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x8a, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x8b, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x8c, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x8d, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x8e, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x8f, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x90, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x91, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x92, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x93, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x94, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x95, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x96, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x97, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x98, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x99, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x9a, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x9b, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x9c, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x9d, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x9e, 0, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xa0, 1, 33, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0xad, 0, 34, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xb5, 1, 34, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xc0, 1, 35, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xc1, 1, 36, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xc2, 1, 37, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xc3, 1, 38, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xc4, 1, 39, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xc5, 1, 40, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xc6, 1, 41, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xc7, 1, 42, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xc8, 1, 43, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xc9, 1, 44, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xca, 1, 45, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xcb, 1, 46, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xcc, 1, 47, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xcd, 1, 48, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xce, 1, 49, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xcf, 1, 50, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xd0, 1, 51, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xd1, 1, 52, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xd2, 1, 53, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xd3, 1, 54, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xd4, 1, 55, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xd5, 1, 56, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xd6, 1, 57, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xd8, 1, 58, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xd9, 1, 59, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xda, 1, 60, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xdb, 1, 61, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xdc, 1, 62, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xdd, 1, 63, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xde, 1, 64, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xdf, 2, 65, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x100, 1, 67, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x102, 1, 68, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x104, 1, 69, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x106, 1, 70, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x108, 1, 71, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10a, 1, 72, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10c, 1, 73, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10e, 1, 74, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x110, 1, 75, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x112, 1, 76, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x114, 1, 77, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x116, 1, 78, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x118, 1, 79, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x11a, 1, 80, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x11c, 1, 81, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x11e, 1, 82, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x120, 1, 83, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x122, 1, 84, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x124, 1, 85, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x126, 1, 86, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x128, 1, 87, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x12a, 1, 88, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x12c, 1, 89, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x12e, 1, 90, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x130, 2, 91, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x132, 1, 93, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x134, 1, 94, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x136, 1, 95, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x139, 1, 96, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x13b, 1, 97, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x13d, 1, 98, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x13f, 1, 99, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x141, 1, 100, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x143, 1, 101, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x145, 1, 102, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x147, 1, 103, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x149, 2, 104, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x14a, 1, 106, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x14c, 1, 107, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x14e, 1, 108, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x150, 1, 109, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x152, 1, 110, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x154, 1, 111, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x156, 1, 112, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x158, 1, 113, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x15a, 1, 114, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x15c, 1, 115, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x15e, 1, 116, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x160, 1, 117, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x162, 1, 118, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x164, 1, 119, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x166, 1, 120, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x168, 1, 121, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x16a, 1, 122, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x16c, 1, 123, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x16e, 1, 124, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x170, 1, 125, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x172, 1, 126, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x174, 1, 127, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x176, 1, 128, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x178, 1, 129, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x179, 1, 130, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x17b, 1, 131, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x17d, 1, 132, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x17f, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x181, 1, 133, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x182, 1, 134, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x184, 1, 135, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x186, 1, 136, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x187, 1, 137, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x189, 1, 138, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x18a, 1, 139, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x18b, 1, 140, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x18e, 1, 141, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x18f, 1, 142, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x190, 1, 143, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x191, 1, 144, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x193, 1, 145, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x194, 1, 146, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x196, 1, 147, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x197, 1, 148, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x198, 1, 149, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x19c, 1, 150, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x19d, 1, 151, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x19f, 1, 152, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1a0, 1, 153, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1a2, 1, 154, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1a4, 1, 155, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1a6, 1, 156, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1a7, 1, 157, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1a9, 1, 158, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ac, 1, 159, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ae, 1, 160, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1af, 1, 161, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1b1, 1, 162, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1b2, 1, 163, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1b3, 1, 164, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1b5, 1, 165, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1b7, 1, 166, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1b8, 1, 167, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1bc, 1, 168, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1c4, 1, 169, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1c5, 1, 169, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1c7, 1, 170, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1c8, 1, 170, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ca, 1, 171, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1cb, 1, 171, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1cd, 1, 172, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1cf, 1, 173, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1d1, 1, 174, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1d3, 1, 175, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1d5, 1, 176, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1d7, 1, 177, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1d9, 1, 178, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1db, 1, 179, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1de, 1, 180, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e0, 1, 181, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e2, 1, 182, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e4, 1, 183, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e6, 1, 184, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e8, 1, 185, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ea, 1, 186, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ec, 1, 187, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ee, 1, 188, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f0, 2, 189, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f1, 1, 191, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f2, 1, 191, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f4, 1, 192, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f6, 1, 193, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f7, 1, 194, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f8, 1, 195, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa, 1, 196, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fc, 1, 197, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fe, 1, 198, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x200, 1, 199, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x202, 1, 200, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x204, 1, 201, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x206, 1, 202, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x208, 1, 203, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x20a, 1, 204, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x20c, 1, 205, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x20e, 1, 206, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x210, 1, 207, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x212, 1, 208, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x214, 1, 209, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x216, 1, 210, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x218, 1, 211, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x21a, 1, 212, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x21c, 1, 213, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x21e, 1, 214, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x220, 1, 215, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x222, 1, 216, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x224, 1, 217, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x226, 1, 218, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x228, 1, 219, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x22a, 1, 220, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x22c, 1, 221, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x22e, 1, 222, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x230, 1, 223, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x232, 1, 224, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x345, 1, 225, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x34f, 0, 226, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0x37a, 2, 226, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x386, 1, 228, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x388, 1, 229, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x389, 1, 230, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x38a, 1, 231, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x38c, 1, 232, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x38e, 1, 233, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x38f, 1, 234, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x390, 3, 235, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x391, 1, 238, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x392, 1, 239, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x393, 1, 240, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x394, 1, 241, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x395, 1, 242, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x396, 1, 243, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x397, 1, 244, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x398, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x399, 1, 225, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x39a, 1, 246, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x39b, 1, 247, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x39c, 1, 34, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x39d, 1, 248, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x39e, 1, 249, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x39f, 1, 250, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3a0, 1, 251, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3a1, 1, 252, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3a3, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3a4, 1, 254, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3a5, 1, 255, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3a6, 1, 256, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3a7, 1, 257, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3a8, 1, 258, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3a9, 1, 259, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3aa, 1, 260, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3ab, 1, 261, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3b0, 3, 262, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3c2, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3d0, 1, 239, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3d1, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3d2, 1, 255, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3d3, 1, 233, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3d4, 1, 261, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3d5, 1, 256, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3d6, 1, 251, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3d8, 1, 265, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3da, 1, 266, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3dc, 1, 267, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3de, 1, 268, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3e0, 1, 269, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3e2, 1, 270, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3e4, 1, 271, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3e6, 1, 272, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3e8, 1, 273, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3ea, 1, 274, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3ec, 1, 275, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3ee, 1, 276, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3f0, 1, 246, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3f1, 1, 252, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3f2, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3f4, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3f5, 1, 242, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x400, 1, 277, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x401, 1, 278, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x402, 1, 279, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x403, 1, 280, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x404, 1, 281, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x405, 1, 282, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x406, 1, 283, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x407, 1, 284, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x408, 1, 285, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x409, 1, 286, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x40a, 1, 287, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x40b, 1, 288, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x40c, 1, 289, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x40d, 1, 290, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x40e, 1, 291, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x40f, 1, 292, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x410, 1, 293, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x411, 1, 294, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x412, 1, 295, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x413, 1, 296, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x414, 1, 297, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x415, 1, 298, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x416, 1, 299, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x417, 1, 300, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x418, 1, 301, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x419, 1, 302, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x41a, 1, 303, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x41b, 1, 304, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x41c, 1, 305, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x41d, 1, 306, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x41e, 1, 307, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x41f, 1, 308, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x420, 1, 309, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x421, 1, 310, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x422, 1, 311, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x423, 1, 312, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x424, 1, 313, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x425, 1, 314, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x426, 1, 315, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x427, 1, 316, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x428, 1, 317, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x429, 1, 318, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x42a, 1, 319, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x42b, 1, 320, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x42c, 1, 321, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x42d, 1, 322, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x42e, 1, 323, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x42f, 1, 324, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x460, 1, 325, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x462, 1, 326, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x464, 1, 327, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x466, 1, 328, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x468, 1, 329, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x46a, 1, 330, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x46c, 1, 331, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x46e, 1, 332, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x470, 1, 333, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x472, 1, 334, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x474, 1, 335, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x476, 1, 336, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x478, 1, 337, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x47a, 1, 338, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x47c, 1, 339, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x47e, 1, 340, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x480, 1, 341, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x48a, 1, 342, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x48c, 1, 343, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x48e, 1, 344, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x490, 1, 345, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x492, 1, 346, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x494, 1, 347, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x496, 1, 348, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x498, 1, 349, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x49a, 1, 350, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x49c, 1, 351, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x49e, 1, 352, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4a0, 1, 353, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4a2, 1, 354, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4a4, 1, 355, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4a6, 1, 356, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4a8, 1, 357, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4aa, 1, 358, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4ac, 1, 359, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4ae, 1, 360, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4b0, 1, 361, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4b2, 1, 362, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4b4, 1, 363, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4b6, 1, 364, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4b8, 1, 365, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4ba, 1, 366, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4bc, 1, 367, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4be, 1, 368, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4c1, 1, 369, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4c3, 1, 370, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4c5, 1, 371, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4c7, 1, 372, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4c9, 1, 373, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4cb, 1, 374, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4cd, 1, 375, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4d0, 1, 376, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4d2, 1, 377, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4d4, 1, 378, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4d6, 1, 379, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4d8, 1, 380, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4da, 1, 381, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4dc, 1, 382, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4de, 1, 383, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4e0, 1, 384, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4e2, 1, 385, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4e4, 1, 386, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4e6, 1, 387, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4e8, 1, 388, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4ea, 1, 389, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4ec, 1, 390, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4ee, 1, 391, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4f0, 1, 392, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4f2, 1, 393, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4f4, 1, 394, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x4f8, 1, 395, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x500, 1, 396, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x502, 1, 397, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x504, 1, 398, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x506, 1, 399, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x508, 1, 400, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x50a, 1, 401, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x50c, 1, 402, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x50e, 1, 403, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x531, 1, 404, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x532, 1, 405, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x533, 1, 406, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x534, 1, 407, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x535, 1, 408, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x536, 1, 409, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x537, 1, 410, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x538, 1, 411, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x539, 1, 412, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x53a, 1, 413, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x53b, 1, 414, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x53c, 1, 415, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x53d, 1, 416, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x53e, 1, 417, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x53f, 1, 418, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x540, 1, 419, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x541, 1, 420, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x542, 1, 421, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x543, 1, 422, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x544, 1, 423, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x545, 1, 424, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x546, 1, 425, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x547, 1, 426, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x548, 1, 427, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x549, 1, 428, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x54a, 1, 429, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x54b, 1, 430, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x54c, 1, 431, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x54d, 1, 432, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x54e, 1, 433, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x54f, 1, 434, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x550, 1, 435, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x551, 1, 436, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x552, 1, 437, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x553, 1, 438, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x554, 1, 439, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x555, 1, 440, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x556, 1, 441, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x587, 2, 442, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x6dd, 0, 444, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x70f, 0, 444, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1680, 1, 444, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x1806, 0, 445, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0x180b, 0, 445, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0x180c, 0, 445, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0x180d, 0, 445, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0x180e, 0, 445, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1e00, 1, 445, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e02, 1, 446, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e04, 1, 447, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e06, 1, 448, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e08, 1, 449, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e0a, 1, 450, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e0c, 1, 451, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e0e, 1, 452, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e10, 1, 453, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e12, 1, 454, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e14, 1, 455, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e16, 1, 456, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e18, 1, 457, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e1a, 1, 458, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e1c, 1, 459, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e1e, 1, 460, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e20, 1, 461, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e22, 1, 462, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e24, 1, 463, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e26, 1, 464, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e28, 1, 465, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e2a, 1, 466, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e2c, 1, 467, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e2e, 1, 468, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e30, 1, 469, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e32, 1, 470, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e34, 1, 471, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e36, 1, 472, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e38, 1, 473, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e3a, 1, 474, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e3c, 1, 475, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e3e, 1, 476, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e40, 1, 477, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e42, 1, 478, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e44, 1, 479, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e46, 1, 480, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e48, 1, 481, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e4a, 1, 482, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e4c, 1, 483, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e4e, 1, 484, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e50, 1, 485, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e52, 1, 486, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e54, 1, 487, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e56, 1, 488, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e58, 1, 489, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e5a, 1, 490, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e5c, 1, 491, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e5e, 1, 492, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e60, 1, 493, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e62, 1, 494, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e64, 1, 495, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e66, 1, 496, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e68, 1, 497, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e6a, 1, 498, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e6c, 1, 499, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e6e, 1, 500, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e70, 1, 501, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e72, 1, 502, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e74, 1, 503, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e76, 1, 504, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e78, 1, 505, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e7a, 1, 506, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e7c, 1, 507, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e7e, 1, 508, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e80, 1, 509, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e82, 1, 510, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e84, 1, 511, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e86, 1, 512, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e88, 1, 513, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e8a, 1, 514, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e8c, 1, 515, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e8e, 1, 516, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e90, 1, 517, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e92, 1, 518, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e94, 1, 519, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e96, 2, 520, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e97, 2, 522, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e98, 2, 524, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e99, 2, 526, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e9a, 2, 528, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1e9b, 1, 493, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ea0, 1, 530, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ea2, 1, 531, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ea4, 1, 532, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ea6, 1, 533, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ea8, 1, 534, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eaa, 1, 535, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eac, 1, 536, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eae, 1, 537, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eb0, 1, 538, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eb2, 1, 539, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eb4, 1, 540, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eb6, 1, 541, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eb8, 1, 542, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eba, 1, 543, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ebc, 1, 544, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ebe, 1, 545, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ec0, 1, 546, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ec2, 1, 547, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ec4, 1, 548, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ec6, 1, 549, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ec8, 1, 550, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eca, 1, 551, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ecc, 1, 552, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ece, 1, 553, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ed0, 1, 554, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ed2, 1, 555, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ed4, 1, 556, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ed6, 1, 557, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ed8, 1, 558, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eda, 1, 559, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1edc, 1, 560, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ede, 1, 561, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ee0, 1, 562, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ee2, 1, 563, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ee4, 1, 564, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ee6, 1, 565, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ee8, 1, 566, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eea, 1, 567, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eec, 1, 568, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1eee, 1, 569, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ef0, 1, 570, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ef2, 1, 571, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ef4, 1, 572, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ef6, 1, 573, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ef8, 1, 574, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f08, 1, 575, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f09, 1, 576, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f0a, 1, 577, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f0b, 1, 578, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f0c, 1, 579, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f0d, 1, 580, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f0e, 1, 581, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f0f, 1, 582, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f18, 1, 583, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f19, 1, 584, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f1a, 1, 585, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f1b, 1, 586, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f1c, 1, 587, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f1d, 1, 588, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f28, 1, 589, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f29, 1, 590, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f2a, 1, 591, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f2b, 1, 592, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f2c, 1, 593, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f2d, 1, 594, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f2e, 1, 595, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f2f, 1, 596, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f38, 1, 597, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f39, 1, 598, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f3a, 1, 599, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f3b, 1, 600, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f3c, 1, 601, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f3d, 1, 602, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f3e, 1, 603, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f3f, 1, 604, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f48, 1, 605, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f49, 1, 606, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f4a, 1, 607, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f4b, 1, 608, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f4c, 1, 609, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f4d, 1, 610, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f50, 2, 611, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f52, 3, 613, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f54, 3, 616, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f56, 3, 619, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f59, 1, 622, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f5b, 1, 623, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f5d, 1, 624, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f5f, 1, 625, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f68, 1, 626, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f69, 1, 627, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f6a, 1, 628, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f6b, 1, 629, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f6c, 1, 630, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f6d, 1, 631, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f6e, 1, 632, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f6f, 1, 633, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f80, 2, 634, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f81, 2, 636, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f82, 2, 638, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f83, 2, 640, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f84, 2, 642, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f85, 2, 644, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f86, 2, 646, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f87, 2, 648, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f88, 2, 634, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f89, 2, 636, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f8a, 2, 638, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f8b, 2, 640, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f8c, 2, 642, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f8d, 2, 644, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f8e, 2, 646, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f8f, 2, 648, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f90, 2, 650, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f91, 2, 652, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f92, 2, 654, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f93, 2, 656, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f94, 2, 658, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f95, 2, 660, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f96, 2, 662, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f97, 2, 664, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f98, 2, 650, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f99, 2, 652, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f9a, 2, 654, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f9b, 2, 656, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f9c, 2, 658, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f9d, 2, 660, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f9e, 2, 662, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1f9f, 2, 664, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa0, 2, 666, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa1, 2, 668, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa2, 2, 670, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa3, 2, 672, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa4, 2, 674, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa5, 2, 676, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa6, 2, 678, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa7, 2, 680, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa8, 2, 666, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fa9, 2, 668, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1faa, 2, 670, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fab, 2, 672, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fac, 2, 674, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fad, 2, 676, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fae, 2, 678, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1faf, 2, 680, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fb2, 2, 682, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fb3, 2, 684, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fb4, 2, 686, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fb6, 2, 688, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fb7, 3, 690, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fb8, 1, 693, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fb9, 1, 694, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fba, 1, 682, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fbb, 1, 695, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fbc, 2, 684, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fbe, 1, 225, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fc2, 2, 696, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fc3, 2, 698, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fc4, 2, 700, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fc6, 2, 702, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fc7, 3, 704, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fc8, 1, 707, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fc9, 1, 708, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fca, 1, 696, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fcb, 1, 709, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fcc, 2, 698, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fd2, 3, 710, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fd3, 3, 235, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fd6, 2, 713, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fd7, 3, 715, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fd8, 1, 718, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fd9, 1, 719, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fda, 1, 720, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fdb, 1, 721, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fe2, 3, 722, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fe3, 3, 262, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fe4, 2, 725, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fe6, 2, 727, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fe7, 3, 729, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fe8, 1, 732, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fe9, 1, 733, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fea, 1, 734, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1feb, 1, 735, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1fec, 1, 736, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ff2, 2, 737, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ff3, 2, 739, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ff4, 2, 234, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ff6, 2, 741, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ff7, 3, 743, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ff8, 1, 746, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ff9, 1, 747, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ffa, 1, 737, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ffb, 1, 748, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1ffc, 2, 739, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2000, 1, 749, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x2001, 1, 750, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x2002, 1, 751, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x2003, 1, 752, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x2004, 1, 753, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x2005, 1, 754, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x2006, 1, 755, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x2007, 1, 756, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x2008, 1, 757, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x2009, 1, 758, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x200b, 0, 759, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0x200c, 0, 759, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0x200d, 0, 759, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0x200e, 0, 759, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x2028, 1, 759, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x202a, 0, 760, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x202b, 0, 760, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x202c, 0, 760, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x202d, 0, 760, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x202f, 1, 760, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x205f, 1, 761, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x2060, 0, 762, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0x2061, 0, 762, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x2062, 0, 762, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x206a, 0, 762, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x206b, 0, 762, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x206c, 0, 762, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x206d, 0, 762, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x206e, 0, 762, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x20a8, 2, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2102, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2103, 2, 762, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2107, 1, 143, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2109, 2, 764, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x210b, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x210c, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x210d, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2110, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2111, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2112, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2115, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2116, 2, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2119, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x211a, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x211b, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x211c, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x211d, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2120, 2, 766, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2121, 3, 768, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2122, 2, 771, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2124, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2126, 1, 259, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2128, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x212a, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x212b, 1, 40, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x212c, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x212d, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2130, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2131, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2133, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x213e, 1, 240, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x213f, 1, 251, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2145, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x2160, 1, 773, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2161, 1, 774, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2162, 1, 775, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2163, 1, 776, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2164, 1, 777, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2165, 1, 778, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2166, 1, 779, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2167, 1, 780, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2168, 1, 781, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x2169, 1, 782, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x216a, 1, 783, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x216b, 1, 784, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x216c, 1, 785, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x216d, 1, 786, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x216e, 1, 787, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x216f, 1, 788, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24b6, 1, 789, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24b7, 1, 790, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24b8, 1, 791, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24b9, 1, 792, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24ba, 1, 793, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24bb, 1, 794, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24bc, 1, 795, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24bd, 1, 796, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24be, 1, 797, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24bf, 1, 798, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24c0, 1, 799, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24c1, 1, 800, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24c2, 1, 801, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24c3, 1, 802, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24c4, 1, 803, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24c5, 1, 804, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24c6, 1, 805, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24c7, 1, 806, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24c8, 1, 807, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24c9, 1, 808, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24ca, 1, 809, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24cb, 1, 810, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24cc, 1, 811, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24cd, 1, 812, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24ce, 1, 813, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x24cf, 1, 814, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x3000, 1, 815, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to SPACE */ + {0x3371, 3, 816, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3373, 2, 819, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3375, 2, 821, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3380, 2, 817, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3381, 2, 823, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3382, 2, 825, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3383, 2, 827, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3384, 2, 829, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3385, 2, 831, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3386, 2, 833, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3387, 2, 835, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x338a, 2, 837, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x338b, 2, 839, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x338c, 2, 841, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3390, 2, 843, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3391, 3, 845, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3392, 3, 848, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3393, 3, 851, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x3394, 3, 854, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33a9, 2, 817, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33aa, 3, 857, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33ab, 3, 860, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33ac, 3, 863, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33b4, 2, 866, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33b5, 2, 868, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33b6, 2, 870, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33b7, 2, 872, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33b8, 2, 874, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33b9, 2, 872, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33ba, 2, 876, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33bb, 2, 878, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33bc, 2, 880, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33bd, 2, 882, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33be, 2, 884, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33bf, 2, 882, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33c0, 2, 886, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33c1, 2, 888, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33c3, 2, 890, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33c6, 4, 892, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33c7, 3, 896, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33c8, 2, 899, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33c9, 2, 901, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33cb, 2, 816, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33cd, 2, 903, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33ce, 2, 905, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33d7, 2, 907, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33d9, 3, 909, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33da, 2, 912, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33dc, 2, 914, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x33dd, 2, 916, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0xfb00, 2, 918, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb01, 2, 920, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb02, 2, 922, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb03, 3, 919, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb04, 3, 924, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb05, 2, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb06, 2, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb13, 2, 927, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb14, 2, 929, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb15, 2, 931, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb16, 2, 933, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfb17, 2, 935, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfe00, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe01, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe02, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe03, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe04, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe05, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe06, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe07, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe08, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe09, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe0a, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe0b, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe0c, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe0d, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe0e, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfe0f, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xfeff, 0, 937, WIND_PROFILE_NAME|WIND_PROFILE_SASL|WIND_PROFILE_LDAP}, /* B.1,rfc4518-map: Map to nothing */ + {0xff21, 1, 937, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff22, 1, 938, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff23, 1, 939, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff24, 1, 940, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff25, 1, 941, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff26, 1, 942, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff27, 1, 943, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff28, 1, 944, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff29, 1, 945, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff2a, 1, 946, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff2b, 1, 947, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff2c, 1, 948, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff2d, 1, 949, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff2e, 1, 950, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff2f, 1, 951, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff30, 1, 952, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff31, 1, 953, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff32, 1, 954, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff33, 1, 955, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff34, 1, 956, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff35, 1, 957, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff36, 1, 958, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff37, 1, 959, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff38, 1, 960, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff39, 1, 961, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xff3a, 1, 962, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0xfff9, 0, 963, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xfffa, 0, 963, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xfffc, 0, 963, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x10400, 1, 963, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10401, 1, 964, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10402, 1, 965, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10403, 1, 966, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10404, 1, 967, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10405, 1, 968, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10406, 1, 969, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10407, 1, 970, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10408, 1, 971, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10409, 1, 972, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1040a, 1, 973, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1040b, 1, 974, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1040c, 1, 975, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1040d, 1, 976, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1040e, 1, 977, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1040f, 1, 978, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10410, 1, 979, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10411, 1, 980, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10412, 1, 981, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10413, 1, 982, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10414, 1, 983, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10415, 1, 984, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10416, 1, 985, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10417, 1, 986, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10418, 1, 987, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10419, 1, 988, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1041a, 1, 989, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1041b, 1, 990, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1041c, 1, 991, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1041d, 1, 992, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1041e, 1, 993, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1041f, 1, 994, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10420, 1, 995, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10421, 1, 996, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10422, 1, 997, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10423, 1, 998, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10424, 1, 999, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x10425, 1, 1000, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Case map */ + {0x1d173, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1d174, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1d175, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1d176, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1d177, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1d178, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1d179, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0x1d400, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d401, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d402, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d403, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d404, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d405, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d406, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d407, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d408, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d409, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d40a, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d40b, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d40c, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d40d, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d40e, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d40f, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d410, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d411, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d412, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d413, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d414, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d415, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d416, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d417, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d418, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d419, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d434, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d435, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d436, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d437, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d438, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d439, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d43a, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d43b, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d43c, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d43d, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d43e, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d43f, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d440, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d441, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d442, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d443, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d444, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d445, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d446, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d447, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d448, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d449, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d44a, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d44b, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d44c, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d44d, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d468, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d469, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d46a, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d46b, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d46c, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d46d, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d46e, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d46f, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d470, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d471, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d472, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d473, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d474, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d475, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d476, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d477, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d478, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d479, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d47a, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d47b, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d47c, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d47d, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d47e, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d47f, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d480, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d481, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d49c, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d49e, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d49f, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4a2, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4a5, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4a6, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4a9, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4aa, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4ab, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4ac, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4ae, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4af, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4b0, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4b1, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4b2, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4b3, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4b4, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4b5, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4d0, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4d1, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4d2, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4d3, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4d4, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4d5, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4d6, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4d7, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4d8, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4d9, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4da, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4db, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4dc, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4dd, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4de, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4df, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4e0, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4e1, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4e2, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4e3, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4e4, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4e5, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4e6, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4e7, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4e8, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d4e9, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d504, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d505, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d507, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d508, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d509, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d50a, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d50d, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d50e, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d50f, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d510, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d511, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d512, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d513, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d514, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d516, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d517, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d518, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d519, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d51a, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d51b, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d51c, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d538, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d539, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d53b, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d53c, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d53d, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d53e, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d540, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d541, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d542, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d543, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d544, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d546, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d54a, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d54b, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d54c, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d54d, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d54e, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d54f, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d550, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d56c, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d56d, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d56e, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d56f, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d570, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d571, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d572, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d573, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d574, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d575, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d576, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d577, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d578, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d579, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d57a, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d57b, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d57c, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d57d, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d57e, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d57f, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d580, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d581, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d582, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d583, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d584, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d585, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5a0, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5a1, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5a2, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5a3, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5a4, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5a5, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5a6, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5a7, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5a8, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5a9, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5aa, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5ab, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5ac, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5ad, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5ae, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5af, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5b0, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5b1, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5b2, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5b3, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5b4, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5b5, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5b6, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5b7, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5b8, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5b9, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5d4, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5d5, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5d6, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5d7, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5d8, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5d9, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5da, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5db, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5dc, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5dd, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5de, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5df, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5e0, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5e1, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5e2, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5e3, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5e4, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5e5, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5e6, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5e7, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5e8, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5e9, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5ea, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5eb, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5ec, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d5ed, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d608, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d609, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d60a, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d60b, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d60c, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d60d, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d60e, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d60f, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d610, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d611, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d612, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d613, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d614, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d615, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d616, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d617, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d618, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d619, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d61a, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d61b, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d61c, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d61d, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d61e, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d61f, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d620, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d621, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d63c, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d63d, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d63e, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d63f, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d640, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d641, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d642, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d643, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d644, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d645, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d646, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d647, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d648, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d649, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d64a, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d64b, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d64c, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d64d, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d64e, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d64f, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d650, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d651, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d652, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d653, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d654, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d655, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d670, 1, 6, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d671, 1, 7, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d672, 1, 8, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d673, 1, 9, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d674, 1, 10, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d675, 1, 11, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d676, 1, 12, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d677, 1, 13, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d678, 1, 14, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d679, 1, 15, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d67a, 1, 16, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d67b, 1, 17, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d67c, 1, 18, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d67d, 1, 19, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d67e, 1, 20, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d67f, 1, 21, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d680, 1, 22, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d681, 1, 23, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d682, 1, 24, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d683, 1, 25, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d684, 1, 26, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d685, 1, 27, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d686, 1, 28, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d687, 1, 29, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d688, 1, 30, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d689, 1, 31, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6a8, 1, 238, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6a9, 1, 239, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6aa, 1, 240, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6ab, 1, 241, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6ac, 1, 242, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6ad, 1, 243, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6ae, 1, 244, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6af, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6b0, 1, 225, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6b1, 1, 246, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6b2, 1, 247, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6b3, 1, 34, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6b4, 1, 248, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6b5, 1, 249, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6b6, 1, 250, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6b7, 1, 251, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6b8, 1, 252, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6b9, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6ba, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6bb, 1, 254, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6bc, 1, 255, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6bd, 1, 256, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6be, 1, 257, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6bf, 1, 258, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6c0, 1, 259, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6d3, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6e2, 1, 238, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6e3, 1, 239, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6e4, 1, 240, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6e5, 1, 241, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6e6, 1, 242, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6e7, 1, 243, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6e8, 1, 244, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6e9, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6ea, 1, 225, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6eb, 1, 246, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6ec, 1, 247, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6ed, 1, 34, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6ee, 1, 248, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6ef, 1, 249, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6f0, 1, 250, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6f1, 1, 251, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6f2, 1, 252, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6f3, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6f4, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6f5, 1, 254, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6f6, 1, 255, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6f7, 1, 256, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6f8, 1, 257, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6f9, 1, 258, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d6fa, 1, 259, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d70d, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d71c, 1, 238, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d71d, 1, 239, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d71e, 1, 240, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d71f, 1, 241, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d720, 1, 242, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d721, 1, 243, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d722, 1, 244, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d723, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d724, 1, 225, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d725, 1, 246, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d726, 1, 247, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d727, 1, 34, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d728, 1, 248, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d729, 1, 249, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d72a, 1, 250, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d72b, 1, 251, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d72c, 1, 252, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d72d, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d72e, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d72f, 1, 254, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d730, 1, 255, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d731, 1, 256, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d732, 1, 257, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d733, 1, 258, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d734, 1, 259, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d747, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d756, 1, 238, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d757, 1, 239, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d758, 1, 240, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d759, 1, 241, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d75a, 1, 242, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d75b, 1, 243, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d75c, 1, 244, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d75d, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d75e, 1, 225, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d75f, 1, 246, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d760, 1, 247, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d761, 1, 34, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d762, 1, 248, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d763, 1, 249, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d764, 1, 250, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d765, 1, 251, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d766, 1, 252, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d767, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d768, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d769, 1, 254, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d76a, 1, 255, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d76b, 1, 256, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d76c, 1, 257, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d76d, 1, 258, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d76e, 1, 259, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d781, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d790, 1, 238, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d791, 1, 239, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d792, 1, 240, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d793, 1, 241, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d794, 1, 242, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d795, 1, 243, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d796, 1, 244, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d797, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d798, 1, 225, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d799, 1, 246, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d79a, 1, 247, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d79b, 1, 34, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d79c, 1, 248, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d79d, 1, 249, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d79e, 1, 250, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d79f, 1, 251, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d7a0, 1, 252, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d7a1, 1, 245, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d7a2, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d7a3, 1, 254, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d7a4, 1, 255, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d7a5, 1, 256, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d7a6, 1, 257, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d7a7, 1, 258, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d7a8, 1, 259, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0x1d7bb, 1, 253, WIND_PROFILE_NAME|WIND_PROFILE_LDAP}, /* B.2: Additional folding */ + {0xe0001, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0020, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0021, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0022, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0023, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0024, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0025, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0026, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0027, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0028, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0029, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe002a, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe002b, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe002c, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe002d, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe002e, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe002f, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0030, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0031, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0032, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0033, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0034, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0035, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0036, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0037, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0038, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0039, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe003a, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe003b, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe003c, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe003d, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe003e, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe003f, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0040, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0041, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0042, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0043, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0044, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0045, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0046, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0047, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0048, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0049, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe004a, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe004b, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe004c, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe004d, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe004e, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe004f, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0050, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0051, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0052, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0053, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0054, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0055, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0056, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0057, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0058, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0059, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe005a, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe005b, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe005c, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe005d, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe005e, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe005f, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0060, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0061, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0062, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0063, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0064, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0065, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0066, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0067, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0068, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0069, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe006a, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe006b, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe006c, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe006d, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe006e, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe006f, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0070, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0071, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0072, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0073, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0074, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0075, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0076, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0077, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0078, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe0079, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe007a, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe007b, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe007c, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe007d, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + {0xe007e, 0, 1001, WIND_PROFILE_LDAP}, /* rfc4518-map: Map to nothing */ + +}; + +const size_t _wind_map_table_size = 1597; + +const uint32_t _wind_map_table_val[] = { + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0061, + 0x0062, + 0x0063, + 0x0064, + 0x0065, + 0x0066, + 0x0067, + 0x0068, + 0x0069, + 0x006A, + 0x006B, + 0x006C, + 0x006D, + 0x006E, + 0x006F, + 0x0070, + 0x0071, + 0x0072, + 0x0073, + 0x0074, + 0x0075, + 0x0076, + 0x0077, + 0x0078, + 0x0079, + 0x007A, + 0x0020, + 0x0020, + 0x03BC, + 0x00E0, + 0x00E1, + 0x00E2, + 0x00E3, + 0x00E4, + 0x00E5, + 0x00E6, + 0x00E7, + 0x00E8, + 0x00E9, + 0x00EA, + 0x00EB, + 0x00EC, + 0x00ED, + 0x00EE, + 0x00EF, + 0x00F0, + 0x00F1, + 0x00F2, + 0x00F3, + 0x00F4, + 0x00F5, + 0x00F6, + 0x00F8, + 0x00F9, + 0x00FA, + 0x00FB, + 0x00FC, + 0x00FD, + 0x00FE, + 0x0073, + 0x0073, + 0x0101, + 0x0103, + 0x0105, + 0x0107, + 0x0109, + 0x010B, + 0x010D, + 0x010F, + 0x0111, + 0x0113, + 0x0115, + 0x0117, + 0x0119, + 0x011B, + 0x011D, + 0x011F, + 0x0121, + 0x0123, + 0x0125, + 0x0127, + 0x0129, + 0x012B, + 0x012D, + 0x012F, + 0x0069, + 0x0307, + 0x0133, + 0x0135, + 0x0137, + 0x013A, + 0x013C, + 0x013E, + 0x0140, + 0x0142, + 0x0144, + 0x0146, + 0x0148, + 0x02BC, + 0x006E, + 0x014B, + 0x014D, + 0x014F, + 0x0151, + 0x0153, + 0x0155, + 0x0157, + 0x0159, + 0x015B, + 0x015D, + 0x015F, + 0x0161, + 0x0163, + 0x0165, + 0x0167, + 0x0169, + 0x016B, + 0x016D, + 0x016F, + 0x0171, + 0x0173, + 0x0175, + 0x0177, + 0x00FF, + 0x017A, + 0x017C, + 0x017E, + 0x0253, + 0x0183, + 0x0185, + 0x0254, + 0x0188, + 0x0256, + 0x0257, + 0x018C, + 0x01DD, + 0x0259, + 0x025B, + 0x0192, + 0x0260, + 0x0263, + 0x0269, + 0x0268, + 0x0199, + 0x026F, + 0x0272, + 0x0275, + 0x01A1, + 0x01A3, + 0x01A5, + 0x0280, + 0x01A8, + 0x0283, + 0x01AD, + 0x0288, + 0x01B0, + 0x028A, + 0x028B, + 0x01B4, + 0x01B6, + 0x0292, + 0x01B9, + 0x01BD, + 0x01C6, + 0x01C9, + 0x01CC, + 0x01CE, + 0x01D0, + 0x01D2, + 0x01D4, + 0x01D6, + 0x01D8, + 0x01DA, + 0x01DC, + 0x01DF, + 0x01E1, + 0x01E3, + 0x01E5, + 0x01E7, + 0x01E9, + 0x01EB, + 0x01ED, + 0x01EF, + 0x006A, + 0x030C, + 0x01F3, + 0x01F5, + 0x0195, + 0x01BF, + 0x01F9, + 0x01FB, + 0x01FD, + 0x01FF, + 0x0201, + 0x0203, + 0x0205, + 0x0207, + 0x0209, + 0x020B, + 0x020D, + 0x020F, + 0x0211, + 0x0213, + 0x0215, + 0x0217, + 0x0219, + 0x021B, + 0x021D, + 0x021F, + 0x019E, + 0x0223, + 0x0225, + 0x0227, + 0x0229, + 0x022B, + 0x022D, + 0x022F, + 0x0231, + 0x0233, + 0x03B9, + 0x0020, + 0x03B9, + 0x03AC, + 0x03AD, + 0x03AE, + 0x03AF, + 0x03CC, + 0x03CD, + 0x03CE, + 0x03B9, + 0x0308, + 0x0301, + 0x03B1, + 0x03B2, + 0x03B3, + 0x03B4, + 0x03B5, + 0x03B6, + 0x03B7, + 0x03B8, + 0x03BA, + 0x03BB, + 0x03BD, + 0x03BE, + 0x03BF, + 0x03C0, + 0x03C1, + 0x03C3, + 0x03C4, + 0x03C5, + 0x03C6, + 0x03C7, + 0x03C8, + 0x03C9, + 0x03CA, + 0x03CB, + 0x03C5, + 0x0308, + 0x0301, + 0x03D9, + 0x03DB, + 0x03DD, + 0x03DF, + 0x03E1, + 0x03E3, + 0x03E5, + 0x03E7, + 0x03E9, + 0x03EB, + 0x03ED, + 0x03EF, + 0x0450, + 0x0451, + 0x0452, + 0x0453, + 0x0454, + 0x0455, + 0x0456, + 0x0457, + 0x0458, + 0x0459, + 0x045A, + 0x045B, + 0x045C, + 0x045D, + 0x045E, + 0x045F, + 0x0430, + 0x0431, + 0x0432, + 0x0433, + 0x0434, + 0x0435, + 0x0436, + 0x0437, + 0x0438, + 0x0439, + 0x043A, + 0x043B, + 0x043C, + 0x043D, + 0x043E, + 0x043F, + 0x0440, + 0x0441, + 0x0442, + 0x0443, + 0x0444, + 0x0445, + 0x0446, + 0x0447, + 0x0448, + 0x0449, + 0x044A, + 0x044B, + 0x044C, + 0x044D, + 0x044E, + 0x044F, + 0x0461, + 0x0463, + 0x0465, + 0x0467, + 0x0469, + 0x046B, + 0x046D, + 0x046F, + 0x0471, + 0x0473, + 0x0475, + 0x0477, + 0x0479, + 0x047B, + 0x047D, + 0x047F, + 0x0481, + 0x048B, + 0x048D, + 0x048F, + 0x0491, + 0x0493, + 0x0495, + 0x0497, + 0x0499, + 0x049B, + 0x049D, + 0x049F, + 0x04A1, + 0x04A3, + 0x04A5, + 0x04A7, + 0x04A9, + 0x04AB, + 0x04AD, + 0x04AF, + 0x04B1, + 0x04B3, + 0x04B5, + 0x04B7, + 0x04B9, + 0x04BB, + 0x04BD, + 0x04BF, + 0x04C2, + 0x04C4, + 0x04C6, + 0x04C8, + 0x04CA, + 0x04CC, + 0x04CE, + 0x04D1, + 0x04D3, + 0x04D5, + 0x04D7, + 0x04D9, + 0x04DB, + 0x04DD, + 0x04DF, + 0x04E1, + 0x04E3, + 0x04E5, + 0x04E7, + 0x04E9, + 0x04EB, + 0x04ED, + 0x04EF, + 0x04F1, + 0x04F3, + 0x04F5, + 0x04F9, + 0x0501, + 0x0503, + 0x0505, + 0x0507, + 0x0509, + 0x050B, + 0x050D, + 0x050F, + 0x0561, + 0x0562, + 0x0563, + 0x0564, + 0x0565, + 0x0566, + 0x0567, + 0x0568, + 0x0569, + 0x056A, + 0x056B, + 0x056C, + 0x056D, + 0x056E, + 0x056F, + 0x0570, + 0x0571, + 0x0572, + 0x0573, + 0x0574, + 0x0575, + 0x0576, + 0x0577, + 0x0578, + 0x0579, + 0x057A, + 0x057B, + 0x057C, + 0x057D, + 0x057E, + 0x057F, + 0x0580, + 0x0581, + 0x0582, + 0x0583, + 0x0584, + 0x0585, + 0x0586, + 0x0565, + 0x0582, + 0x0020, + 0x1E01, + 0x1E03, + 0x1E05, + 0x1E07, + 0x1E09, + 0x1E0B, + 0x1E0D, + 0x1E0F, + 0x1E11, + 0x1E13, + 0x1E15, + 0x1E17, + 0x1E19, + 0x1E1B, + 0x1E1D, + 0x1E1F, + 0x1E21, + 0x1E23, + 0x1E25, + 0x1E27, + 0x1E29, + 0x1E2B, + 0x1E2D, + 0x1E2F, + 0x1E31, + 0x1E33, + 0x1E35, + 0x1E37, + 0x1E39, + 0x1E3B, + 0x1E3D, + 0x1E3F, + 0x1E41, + 0x1E43, + 0x1E45, + 0x1E47, + 0x1E49, + 0x1E4B, + 0x1E4D, + 0x1E4F, + 0x1E51, + 0x1E53, + 0x1E55, + 0x1E57, + 0x1E59, + 0x1E5B, + 0x1E5D, + 0x1E5F, + 0x1E61, + 0x1E63, + 0x1E65, + 0x1E67, + 0x1E69, + 0x1E6B, + 0x1E6D, + 0x1E6F, + 0x1E71, + 0x1E73, + 0x1E75, + 0x1E77, + 0x1E79, + 0x1E7B, + 0x1E7D, + 0x1E7F, + 0x1E81, + 0x1E83, + 0x1E85, + 0x1E87, + 0x1E89, + 0x1E8B, + 0x1E8D, + 0x1E8F, + 0x1E91, + 0x1E93, + 0x1E95, + 0x0068, + 0x0331, + 0x0074, + 0x0308, + 0x0077, + 0x030A, + 0x0079, + 0x030A, + 0x0061, + 0x02BE, + 0x1EA1, + 0x1EA3, + 0x1EA5, + 0x1EA7, + 0x1EA9, + 0x1EAB, + 0x1EAD, + 0x1EAF, + 0x1EB1, + 0x1EB3, + 0x1EB5, + 0x1EB7, + 0x1EB9, + 0x1EBB, + 0x1EBD, + 0x1EBF, + 0x1EC1, + 0x1EC3, + 0x1EC5, + 0x1EC7, + 0x1EC9, + 0x1ECB, + 0x1ECD, + 0x1ECF, + 0x1ED1, + 0x1ED3, + 0x1ED5, + 0x1ED7, + 0x1ED9, + 0x1EDB, + 0x1EDD, + 0x1EDF, + 0x1EE1, + 0x1EE3, + 0x1EE5, + 0x1EE7, + 0x1EE9, + 0x1EEB, + 0x1EED, + 0x1EEF, + 0x1EF1, + 0x1EF3, + 0x1EF5, + 0x1EF7, + 0x1EF9, + 0x1F00, + 0x1F01, + 0x1F02, + 0x1F03, + 0x1F04, + 0x1F05, + 0x1F06, + 0x1F07, + 0x1F10, + 0x1F11, + 0x1F12, + 0x1F13, + 0x1F14, + 0x1F15, + 0x1F20, + 0x1F21, + 0x1F22, + 0x1F23, + 0x1F24, + 0x1F25, + 0x1F26, + 0x1F27, + 0x1F30, + 0x1F31, + 0x1F32, + 0x1F33, + 0x1F34, + 0x1F35, + 0x1F36, + 0x1F37, + 0x1F40, + 0x1F41, + 0x1F42, + 0x1F43, + 0x1F44, + 0x1F45, + 0x03C5, + 0x0313, + 0x03C5, + 0x0313, + 0x0300, + 0x03C5, + 0x0313, + 0x0301, + 0x03C5, + 0x0313, + 0x0342, + 0x1F51, + 0x1F53, + 0x1F55, + 0x1F57, + 0x1F60, + 0x1F61, + 0x1F62, + 0x1F63, + 0x1F64, + 0x1F65, + 0x1F66, + 0x1F67, + 0x1F00, + 0x03B9, + 0x1F01, + 0x03B9, + 0x1F02, + 0x03B9, + 0x1F03, + 0x03B9, + 0x1F04, + 0x03B9, + 0x1F05, + 0x03B9, + 0x1F06, + 0x03B9, + 0x1F07, + 0x03B9, + 0x1F20, + 0x03B9, + 0x1F21, + 0x03B9, + 0x1F22, + 0x03B9, + 0x1F23, + 0x03B9, + 0x1F24, + 0x03B9, + 0x1F25, + 0x03B9, + 0x1F26, + 0x03B9, + 0x1F27, + 0x03B9, + 0x1F60, + 0x03B9, + 0x1F61, + 0x03B9, + 0x1F62, + 0x03B9, + 0x1F63, + 0x03B9, + 0x1F64, + 0x03B9, + 0x1F65, + 0x03B9, + 0x1F66, + 0x03B9, + 0x1F67, + 0x03B9, + 0x1F70, + 0x03B9, + 0x03B1, + 0x03B9, + 0x03AC, + 0x03B9, + 0x03B1, + 0x0342, + 0x03B1, + 0x0342, + 0x03B9, + 0x1FB0, + 0x1FB1, + 0x1F71, + 0x1F74, + 0x03B9, + 0x03B7, + 0x03B9, + 0x03AE, + 0x03B9, + 0x03B7, + 0x0342, + 0x03B7, + 0x0342, + 0x03B9, + 0x1F72, + 0x1F73, + 0x1F75, + 0x03B9, + 0x0308, + 0x0300, + 0x03B9, + 0x0342, + 0x03B9, + 0x0308, + 0x0342, + 0x1FD0, + 0x1FD1, + 0x1F76, + 0x1F77, + 0x03C5, + 0x0308, + 0x0300, + 0x03C1, + 0x0313, + 0x03C5, + 0x0342, + 0x03C5, + 0x0308, + 0x0342, + 0x1FE0, + 0x1FE1, + 0x1F7A, + 0x1F7B, + 0x1FE5, + 0x1F7C, + 0x03B9, + 0x03C9, + 0x03B9, + 0x03C9, + 0x0342, + 0x03C9, + 0x0342, + 0x03B9, + 0x1F78, + 0x1F79, + 0x1F7D, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x0020, + 0x00B0, + 0x0063, + 0x00B0, + 0x0066, + 0x0073, + 0x006D, + 0x0074, + 0x0065, + 0x006C, + 0x0074, + 0x006D, + 0x2170, + 0x2171, + 0x2172, + 0x2173, + 0x2174, + 0x2175, + 0x2176, + 0x2177, + 0x2178, + 0x2179, + 0x217A, + 0x217B, + 0x217C, + 0x217D, + 0x217E, + 0x217F, + 0x24D0, + 0x24D1, + 0x24D2, + 0x24D3, + 0x24D4, + 0x24D5, + 0x24D6, + 0x24D7, + 0x24D8, + 0x24D9, + 0x24DA, + 0x24DB, + 0x24DC, + 0x24DD, + 0x24DE, + 0x24DF, + 0x24E0, + 0x24E1, + 0x24E2, + 0x24E3, + 0x24E4, + 0x24E5, + 0x24E6, + 0x24E7, + 0x24E8, + 0x24E9, + 0x0020, + 0x0068, + 0x0070, + 0x0061, + 0x0061, + 0x0075, + 0x006F, + 0x0076, + 0x006E, + 0x0061, + 0x03BC, + 0x0061, + 0x006D, + 0x0061, + 0x006B, + 0x0061, + 0x006B, + 0x0062, + 0x006D, + 0x0062, + 0x0067, + 0x0062, + 0x0070, + 0x0066, + 0x006E, + 0x0066, + 0x03BC, + 0x0066, + 0x0068, + 0x007A, + 0x006B, + 0x0068, + 0x007A, + 0x006D, + 0x0068, + 0x007A, + 0x0067, + 0x0068, + 0x007A, + 0x0074, + 0x0068, + 0x007A, + 0x006B, + 0x0070, + 0x0061, + 0x006D, + 0x0070, + 0x0061, + 0x0067, + 0x0070, + 0x0061, + 0x0070, + 0x0076, + 0x006E, + 0x0076, + 0x03BC, + 0x0076, + 0x006D, + 0x0076, + 0x006B, + 0x0076, + 0x0070, + 0x0077, + 0x006E, + 0x0077, + 0x03BC, + 0x0077, + 0x006D, + 0x0077, + 0x006B, + 0x0077, + 0x006B, + 0x03C9, + 0x006D, + 0x03C9, + 0x0062, + 0x0071, + 0x0063, + 0x2215, + 0x006B, + 0x0067, + 0x0063, + 0x006F, + 0x002E, + 0x0064, + 0x0062, + 0x0067, + 0x0079, + 0x006B, + 0x006B, + 0x006B, + 0x006D, + 0x0070, + 0x0068, + 0x0070, + 0x0070, + 0x006D, + 0x0070, + 0x0072, + 0x0073, + 0x0076, + 0x0077, + 0x0062, + 0x0066, + 0x0066, + 0x0066, + 0x0069, + 0x0066, + 0x006C, + 0x0066, + 0x0066, + 0x006C, + 0x0574, + 0x0576, + 0x0574, + 0x0565, + 0x0574, + 0x056B, + 0x057E, + 0x0576, + 0x0574, + 0x056D, + 0xFF41, + 0xFF42, + 0xFF43, + 0xFF44, + 0xFF45, + 0xFF46, + 0xFF47, + 0xFF48, + 0xFF49, + 0xFF4A, + 0xFF4B, + 0xFF4C, + 0xFF4D, + 0xFF4E, + 0xFF4F, + 0xFF50, + 0xFF51, + 0xFF52, + 0xFF53, + 0xFF54, + 0xFF55, + 0xFF56, + 0xFF57, + 0xFF58, + 0xFF59, + 0xFF5A, + 0x10428, + 0x10429, + 0x1042A, + 0x1042B, + 0x1042C, + 0x1042D, + 0x1042E, + 0x1042F, + 0x10430, + 0x10431, + 0x10432, + 0x10433, + 0x10434, + 0x10435, + 0x10436, + 0x10437, + 0x10438, + 0x10439, + 0x1043A, + 0x1043B, + 0x1043C, + 0x1043D, + 0x1043E, + 0x1043F, + 0x10440, + 0x10441, + 0x10442, + 0x10443, + 0x10444, + 0x10445, + 0x10446, + 0x10447, + 0x10448, + 0x10449, + 0x1044A, + 0x1044B, + 0x1044C, + 0x1044D, +}; + diff --git a/source4/heimdal/lib/wind/map_table.h b/source4/heimdal/lib/wind/map_table.h new file mode 100644 index 00000000000..4b4565472d7 --- /dev/null +++ b/source4/heimdal/lib/wind/map_table.h @@ -0,0 +1,22 @@ +/* map_table.h */ +/* Automatically generated at 2008-03-18T11:38:08.353625 */ + +#ifndef MAP_TABLE_H +#define MAP_TABLE_H 1 + +#include "windlocl.h" + +struct translation { + uint32_t key; + unsigned short val_len; + unsigned short val_offset; + wind_profile_flags flags; +}; + +extern const struct translation _wind_map_table[]; + +extern const size_t _wind_map_table_size; + +extern const uint32_t _wind_map_table_val[]; + +#endif /* MAP_TABLE_H */ diff --git a/source4/heimdal/lib/wind/normalize.c b/source4/heimdal/lib/wind/normalize.c new file mode 100644 index 00000000000..d1b440513a3 --- /dev/null +++ b/source4/heimdal/lib/wind/normalize.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "windlocl.h" + +#include <assert.h> +#include <stdlib.h> +#include <errno.h> + +#include "normalize_table.h" + +RCSID("$Id: normalize.c 22581 2008-02-11 20:42:25Z lha $"); + +static int +translation_cmp(const void *key, const void *data) +{ + const struct translation *t1 = (const struct translation *)key; + const struct translation *t2 = (const struct translation *)data; + + return t1->key - t2->key; +} + +enum { s_base = 0xAC00}; +enum { s_count = 11172}; +enum { l_base = 0x1100}; +enum { l_count = 19}; +enum { v_base = 0x1161}; +enum { v_count = 21}; +enum { t_base = 0x11A7}; +enum { t_count = 28}; +enum { n_count = v_count * t_count}; + +static int +hangul_decomp(const uint32_t *in, size_t in_len, + uint32_t *out, size_t *out_len) +{ + uint32_t u = *in; + unsigned s_index; + unsigned l, v, t; + unsigned o; + + if (u < s_base || u >= s_base + s_count) + return 0; + s_index = u - s_base; + l = l_base + s_index / n_count; + v = v_base + (s_index % n_count) / t_count; + t = t_base + s_index % t_count; + o = 2; + if (t != t_base) + ++o; + if (*out_len < o) + return WIND_ERR_OVERRUN; + out[0] = l; + out[1] = v; + if (t != t_base) + out[2] = t; + *out_len = o; + return 1; +} + +static uint32_t +hangul_composition(const uint32_t *in, size_t in_len) +{ + if (in_len < 2) + return 0; + if (in[0] >= l_base && in[0] < l_base + l_count) { + unsigned l_index = in[0] - l_base; + unsigned v_index; + + if (in[1] < v_base || in[1] >= v_base + v_count) + return 0; + v_index = in[1] - v_base; + return (l_index * v_count + v_index) * t_count + s_base; + } else if (in[0] >= s_base && in[0] < s_base + s_count) { + unsigned s_index = in[0] - s_base; + unsigned t_index; + + if (s_index % t_count != 0) + return 0; + if (in[1] < t_base || in[1] >= t_base + t_count) + return 0; + t_index = in[1] - t_base; + return in[0] + t_index; + } + return 0; +} + +static int +compat_decomp(const uint32_t *in, size_t in_len, + uint32_t *out, size_t *out_len) +{ + unsigned i; + unsigned o = 0; + + for (i = 0; i < in_len; ++i) { + struct translation ts = {in[i]}; + size_t sub_len = *out_len - o; + int ret; + + ret = hangul_decomp(in + i, in_len - i, + out + o, &sub_len); + if (ret) { + if (ret == WIND_ERR_OVERRUN) + return ret; + o += sub_len; + } else { + void *s = bsearch(&ts, + _wind_normalize_table, + _wind_normalize_table_size, + sizeof(_wind_normalize_table[0]), + translation_cmp); + if (s != NULL) { + const struct translation *t = (const struct translation *)s; + + ret = compat_decomp(_wind_normalize_val_table + t->val_offset, + t->val_len, + out + o, &sub_len); + if (ret) + return ret; + o += sub_len; + } else { + if (o >= *out_len) + return WIND_ERR_OVERRUN; + out[o++] = in[i]; + + } + } + } + *out_len = o; + return 0; +} + +static int +cc_cmp(const void *a, const void *b) +{ + const uint32_t *ua = (const uint32_t *)a; + const uint32_t *ub = (const uint32_t *)b; + + return _wind_combining_class(*ua) - _wind_combining_class(*ub); +} + +static void +canonical_reorder(uint32_t *tmp, size_t tmp_len) +{ + unsigned i; + + for (i = 0; i < tmp_len; ++i) { + int cc = _wind_combining_class(tmp[i]); + if (cc) { + size_t j; + for (j = i + 1; + j < tmp_len && _wind_combining_class(tmp[j]); + ++j) + ; + qsort(&tmp[i], j - i, sizeof(unsigned), + cc_cmp); + i = j; + } + } +} + +static uint32_t +find_composition(const uint32_t *in, unsigned in_len) +{ + unsigned short canon_index = 0; + uint32_t cur; + unsigned n = 0; + + cur = hangul_composition(in, in_len); + if (cur) + return cur; + + do { + const struct canon_node *c = &_wind_canon_table[canon_index]; + unsigned i; + + if (n % 5 == 0) { + cur = *in++; + if (in_len-- == 0) + return c->val; + } + + i = cur >> 16; + if (i < c->next_start || i >= c->next_end) + canon_index = 0; + else + canon_index = + _wind_canon_next_table[c->next_offset + i - c->next_start]; + if (canon_index != 0) { + cur = (cur << 4) & 0xFFFFF; + ++n; + } + } while (canon_index != 0); + return 0; +} + +static int +combine(const uint32_t *in, size_t in_len, + uint32_t *out, size_t *out_len) +{ + unsigned i; + int ostarter; + unsigned o = 0; + int old_cc; + int cc; + + for (i = 0; i < in_len;) { + while (i < in_len && (cc = _wind_combining_class(in[i])) != 0) { + out[o++] = in[i++]; + } + if (i < in_len) { + if (o >= *out_len) + return WIND_ERR_OVERRUN; + ostarter = o; + out[o++] = in[i++]; + old_cc = -1; + + while (i < in_len) { + uint32_t comb; + uint32_t v[2]; + + v[0] = out[ostarter]; + v[1] = in[i]; + + cc = _wind_combining_class(in[i]); + if (old_cc != cc && (comb = find_composition(v, 2))) { + out[ostarter] = comb; + } else if (cc == 0) { + break; + } else { + if (o >= *out_len) + return WIND_ERR_OVERRUN; + out[o++] = in[i]; + old_cc = cc; + } + ++i; + } + } + } + *out_len = o; + return 0; +} + +int +_wind_stringprep_normalize(const uint32_t *in, size_t in_len, + uint32_t *out, size_t *out_len) +{ + size_t tmp_len; + uint32_t *tmp; + int ret; + + tmp_len = in_len * 4; + if (tmp_len < MAX_LENGTH_CANON) + tmp_len = MAX_LENGTH_CANON; + tmp = malloc(tmp_len * sizeof(uint32_t)); + if (tmp == NULL) + return ENOMEM; + + ret = compat_decomp(in, in_len, tmp, &tmp_len); + if (ret) { + free(tmp); + return ret; + } + canonical_reorder(tmp, tmp_len); + ret = combine(tmp, tmp_len, out, out_len); + free(tmp); + return ret; +} diff --git a/source4/heimdal/lib/wind/normalize_table.c b/source4/heimdal/lib/wind/normalize_table.c new file mode 100644 index 00000000000..c8893193a74 --- /dev/null +++ b/source4/heimdal/lib/wind/normalize_table.c @@ -0,0 +1,22976 @@ +/* normalize_table.c */ +/* Automatically generated at 2008-03-18T11:38:08.923861 */ + + +#include "normalize_table.h" + +const struct translation _wind_normalize_table[] = { + {0xa0, 1, 0}, /* NO-BREAK SPACE */ + {0xa8, 2, 1}, /* DIAERESIS */ + {0xaa, 1, 3}, /* FEMININE ORDINAL INDICATOR */ + {0xaf, 2, 4}, /* MACRON */ + {0xb2, 1, 6}, /* SUPERSCRIPT TWO */ + {0xb3, 1, 7}, /* SUPERSCRIPT THREE */ + {0xb4, 2, 8}, /* ACUTE ACCENT */ + {0xb5, 1, 10}, /* MICRO SIGN */ + {0xb8, 2, 11}, /* CEDILLA */ + {0xb9, 1, 13}, /* SUPERSCRIPT ONE */ + {0xba, 1, 14}, /* MASCULINE ORDINAL INDICATOR */ + {0xbc, 3, 15}, /* VULGAR FRACTION ONE QUARTER */ + {0xbd, 3, 18}, /* VULGAR FRACTION ONE HALF */ + {0xbe, 3, 21}, /* VULGAR FRACTION THREE QUARTERS */ + {0xc0, 2, 24}, /* LATIN CAPITAL LETTER A WITH GRAVE */ + {0xc1, 2, 26}, /* LATIN CAPITAL LETTER A WITH ACUTE */ + {0xc2, 2, 28}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ + {0xc3, 2, 30}, /* LATIN CAPITAL LETTER A WITH TILDE */ + {0xc4, 2, 32}, /* LATIN CAPITAL LETTER A WITH DIAERESIS */ + {0xc5, 2, 34}, /* LATIN CAPITAL LETTER A WITH RING ABOVE */ + {0xc7, 2, 36}, /* LATIN CAPITAL LETTER C WITH CEDILLA */ + {0xc8, 2, 38}, /* LATIN CAPITAL LETTER E WITH GRAVE */ + {0xc9, 2, 40}, /* LATIN CAPITAL LETTER E WITH ACUTE */ + {0xca, 2, 42}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ + {0xcb, 2, 44}, /* LATIN CAPITAL LETTER E WITH DIAERESIS */ + {0xcc, 2, 46}, /* LATIN CAPITAL LETTER I WITH GRAVE */ + {0xcd, 2, 48}, /* LATIN CAPITAL LETTER I WITH ACUTE */ + {0xce, 2, 50}, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ + {0xcf, 2, 52}, /* LATIN CAPITAL LETTER I WITH DIAERESIS */ + {0xd1, 2, 54}, /* LATIN CAPITAL LETTER N WITH TILDE */ + {0xd2, 2, 56}, /* LATIN CAPITAL LETTER O WITH GRAVE */ + {0xd3, 2, 58}, /* LATIN CAPITAL LETTER O WITH ACUTE */ + {0xd4, 2, 60}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ + {0xd5, 2, 62}, /* LATIN CAPITAL LETTER O WITH TILDE */ + {0xd6, 2, 64}, /* LATIN CAPITAL LETTER O WITH DIAERESIS */ + {0xd9, 2, 66}, /* LATIN CAPITAL LETTER U WITH GRAVE */ + {0xda, 2, 68}, /* LATIN CAPITAL LETTER U WITH ACUTE */ + {0xdb, 2, 70}, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ + {0xdc, 2, 72}, /* LATIN CAPITAL LETTER U WITH DIAERESIS */ + {0xdd, 2, 74}, /* LATIN CAPITAL LETTER Y WITH ACUTE */ + {0xe0, 2, 76}, /* LATIN SMALL LETTER A WITH GRAVE */ + {0xe1, 2, 78}, /* LATIN SMALL LETTER A WITH ACUTE */ + {0xe2, 2, 80}, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */ + {0xe3, 2, 82}, /* LATIN SMALL LETTER A WITH TILDE */ + {0xe4, 2, 84}, /* LATIN SMALL LETTER A WITH DIAERESIS */ + {0xe5, 2, 86}, /* LATIN SMALL LETTER A WITH RING ABOVE */ + {0xe7, 2, 88}, /* LATIN SMALL LETTER C WITH CEDILLA */ + {0xe8, 2, 90}, /* LATIN SMALL LETTER E WITH GRAVE */ + {0xe9, 2, 92}, /* LATIN SMALL LETTER E WITH ACUTE */ + {0xea, 2, 94}, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */ + {0xeb, 2, 96}, /* LATIN SMALL LETTER E WITH DIAERESIS */ + {0xec, 2, 98}, /* LATIN SMALL LETTER I WITH GRAVE */ + {0xed, 2, 100}, /* LATIN SMALL LETTER I WITH ACUTE */ + {0xee, 2, 102}, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */ + {0xef, 2, 104}, /* LATIN SMALL LETTER I WITH DIAERESIS */ + {0xf1, 2, 106}, /* LATIN SMALL LETTER N WITH TILDE */ + {0xf2, 2, 108}, /* LATIN SMALL LETTER O WITH GRAVE */ + {0xf3, 2, 110}, /* LATIN SMALL LETTER O WITH ACUTE */ + {0xf4, 2, 112}, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */ + {0xf5, 2, 114}, /* LATIN SMALL LETTER O WITH TILDE */ + {0xf6, 2, 116}, /* LATIN SMALL LETTER O WITH DIAERESIS */ + {0xf9, 2, 118}, /* LATIN SMALL LETTER U WITH GRAVE */ + {0xfa, 2, 120}, /* LATIN SMALL LETTER U WITH ACUTE */ + {0xfb, 2, 122}, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */ + {0xfc, 2, 124}, /* LATIN SMALL LETTER U WITH DIAERESIS */ + {0xfd, 2, 126}, /* LATIN SMALL LETTER Y WITH ACUTE */ + {0xff, 2, 128}, /* LATIN SMALL LETTER Y WITH DIAERESIS */ + {0x100, 2, 130}, /* LATIN CAPITAL LETTER A WITH MACRON */ + {0x101, 2, 132}, /* LATIN SMALL LETTER A WITH MACRON */ + {0x102, 2, 134}, /* LATIN CAPITAL LETTER A WITH BREVE */ + {0x103, 2, 136}, /* LATIN SMALL LETTER A WITH BREVE */ + {0x104, 2, 138}, /* LATIN CAPITAL LETTER A WITH OGONEK */ + {0x105, 2, 140}, /* LATIN SMALL LETTER A WITH OGONEK */ + {0x106, 2, 142}, /* LATIN CAPITAL LETTER C WITH ACUTE */ + {0x107, 2, 144}, /* LATIN SMALL LETTER C WITH ACUTE */ + {0x108, 2, 146}, /* LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ + {0x109, 2, 148}, /* LATIN SMALL LETTER C WITH CIRCUMFLEX */ + {0x10a, 2, 150}, /* LATIN CAPITAL LETTER C WITH DOT ABOVE */ + {0x10b, 2, 152}, /* LATIN SMALL LETTER C WITH DOT ABOVE */ + {0x10c, 2, 154}, /* LATIN CAPITAL LETTER C WITH CARON */ + {0x10d, 2, 156}, /* LATIN SMALL LETTER C WITH CARON */ + {0x10e, 2, 158}, /* LATIN CAPITAL LETTER D WITH CARON */ + {0x10f, 2, 160}, /* LATIN SMALL LETTER D WITH CARON */ + {0x112, 2, 162}, /* LATIN CAPITAL LETTER E WITH MACRON */ + {0x113, 2, 164}, /* LATIN SMALL LETTER E WITH MACRON */ + {0x114, 2, 166}, /* LATIN CAPITAL LETTER E WITH BREVE */ + {0x115, 2, 168}, /* LATIN SMALL LETTER E WITH BREVE */ + {0x116, 2, 170}, /* LATIN CAPITAL LETTER E WITH DOT ABOVE */ + {0x117, 2, 172}, /* LATIN SMALL LETTER E WITH DOT ABOVE */ + {0x118, 2, 174}, /* LATIN CAPITAL LETTER E WITH OGONEK */ + {0x119, 2, 176}, /* LATIN SMALL LETTER E WITH OGONEK */ + {0x11a, 2, 178}, /* LATIN CAPITAL LETTER E WITH CARON */ + {0x11b, 2, 180}, /* LATIN SMALL LETTER E WITH CARON */ + {0x11c, 2, 182}, /* LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ + {0x11d, 2, 184}, /* LATIN SMALL LETTER G WITH CIRCUMFLEX */ + {0x11e, 2, 186}, /* LATIN CAPITAL LETTER G WITH BREVE */ + {0x11f, 2, 188}, /* LATIN SMALL LETTER G WITH BREVE */ + {0x120, 2, 190}, /* LATIN CAPITAL LETTER G WITH DOT ABOVE */ + {0x121, 2, 192}, /* LATIN SMALL LETTER G WITH DOT ABOVE */ + {0x122, 2, 194}, /* LATIN CAPITAL LETTER G WITH CEDILLA */ + {0x123, 2, 196}, /* LATIN SMALL LETTER G WITH CEDILLA */ + {0x124, 2, 198}, /* LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ + {0x125, 2, 200}, /* LATIN SMALL LETTER H WITH CIRCUMFLEX */ + {0x128, 2, 202}, /* LATIN CAPITAL LETTER I WITH TILDE */ + {0x129, 2, 204}, /* LATIN SMALL LETTER I WITH TILDE */ + {0x12a, 2, 206}, /* LATIN CAPITAL LETTER I WITH MACRON */ + {0x12b, 2, 208}, /* LATIN SMALL LETTER I WITH MACRON */ + {0x12c, 2, 210}, /* LATIN CAPITAL LETTER I WITH BREVE */ + {0x12d, 2, 212}, /* LATIN SMALL LETTER I WITH BREVE */ + {0x12e, 2, 214}, /* LATIN CAPITAL LETTER I WITH OGONEK */ + {0x12f, 2, 216}, /* LATIN SMALL LETTER I WITH OGONEK */ + {0x130, 2, 218}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */ + {0x132, 2, 220}, /* LATIN CAPITAL LIGATURE IJ */ + {0x133, 2, 222}, /* LATIN SMALL LIGATURE IJ */ + {0x134, 2, 224}, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ + {0x135, 2, 226}, /* LATIN SMALL LETTER J WITH CIRCUMFLEX */ + {0x136, 2, 228}, /* LATIN CAPITAL LETTER K WITH CEDILLA */ + {0x137, 2, 230}, /* LATIN SMALL LETTER K WITH CEDILLA */ + {0x139, 2, 232}, /* LATIN CAPITAL LETTER L WITH ACUTE */ + {0x13a, 2, 234}, /* LATIN SMALL LETTER L WITH ACUTE */ + {0x13b, 2, 236}, /* LATIN CAPITAL LETTER L WITH CEDILLA */ + {0x13c, 2, 238}, /* LATIN SMALL LETTER L WITH CEDILLA */ + {0x13d, 2, 240}, /* LATIN CAPITAL LETTER L WITH CARON */ + {0x13e, 2, 242}, /* LATIN SMALL LETTER L WITH CARON */ + {0x13f, 2, 244}, /* LATIN CAPITAL LETTER L WITH MIDDLE DOT */ + {0x140, 2, 246}, /* LATIN SMALL LETTER L WITH MIDDLE DOT */ + {0x143, 2, 248}, /* LATIN CAPITAL LETTER N WITH ACUTE */ + {0x144, 2, 250}, /* LATIN SMALL LETTER N WITH ACUTE */ + {0x145, 2, 252}, /* LATIN CAPITAL LETTER N WITH CEDILLA */ + {0x146, 2, 254}, /* LATIN SMALL LETTER N WITH CEDILLA */ + {0x147, 2, 256}, /* LATIN CAPITAL LETTER N WITH CARON */ + {0x148, 2, 258}, /* LATIN SMALL LETTER N WITH CARON */ + {0x149, 2, 260}, /* LATIN SMALL LETTER N PRECEDED BY APOSTROPHE */ + {0x14c, 2, 262}, /* LATIN CAPITAL LETTER O WITH MACRON */ + {0x14d, 2, 264}, /* LATIN SMALL LETTER O WITH MACRON */ + {0x14e, 2, 266}, /* LATIN CAPITAL LETTER O WITH BREVE */ + {0x14f, 2, 268}, /* LATIN SMALL LETTER O WITH BREVE */ + {0x150, 2, 270}, /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ + {0x151, 2, 272}, /* LATIN SMALL LETTER O WITH DOUBLE ACUTE */ + {0x154, 2, 274}, /* LATIN CAPITAL LETTER R WITH ACUTE */ + {0x155, 2, 276}, /* LATIN SMALL LETTER R WITH ACUTE */ + {0x156, 2, 278}, /* LATIN CAPITAL LETTER R WITH CEDILLA */ + {0x157, 2, 280}, /* LATIN SMALL LETTER R WITH CEDILLA */ + {0x158, 2, 282}, /* LATIN CAPITAL LETTER R WITH CARON */ + {0x159, 2, 284}, /* LATIN SMALL LETTER R WITH CARON */ + {0x15a, 2, 286}, /* LATIN CAPITAL LETTER S WITH ACUTE */ + {0x15b, 2, 288}, /* LATIN SMALL LETTER S WITH ACUTE */ + {0x15c, 2, 290}, /* LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ + {0x15d, 2, 292}, /* LATIN SMALL LETTER S WITH CIRCUMFLEX */ + {0x15e, 2, 294}, /* LATIN CAPITAL LETTER S WITH CEDILLA */ + {0x15f, 2, 296}, /* LATIN SMALL LETTER S WITH CEDILLA */ + {0x160, 2, 298}, /* LATIN CAPITAL LETTER S WITH CARON */ + {0x161, 2, 300}, /* LATIN SMALL LETTER S WITH CARON */ + {0x162, 2, 302}, /* LATIN CAPITAL LETTER T WITH CEDILLA */ + {0x163, 2, 304}, /* LATIN SMALL LETTER T WITH CEDILLA */ + {0x164, 2, 306}, /* LATIN CAPITAL LETTER T WITH CARON */ + {0x165, 2, 308}, /* LATIN SMALL LETTER T WITH CARON */ + {0x168, 2, 310}, /* LATIN CAPITAL LETTER U WITH TILDE */ + {0x169, 2, 312}, /* LATIN SMALL LETTER U WITH TILDE */ + {0x16a, 2, 314}, /* LATIN CAPITAL LETTER U WITH MACRON */ + {0x16b, 2, 316}, /* LATIN SMALL LETTER U WITH MACRON */ + {0x16c, 2, 318}, /* LATIN CAPITAL LETTER U WITH BREVE */ + {0x16d, 2, 320}, /* LATIN SMALL LETTER U WITH BREVE */ + {0x16e, 2, 322}, /* LATIN CAPITAL LETTER U WITH RING ABOVE */ + {0x16f, 2, 324}, /* LATIN SMALL LETTER U WITH RING ABOVE */ + {0x170, 2, 326}, /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ + {0x171, 2, 328}, /* LATIN SMALL LETTER U WITH DOUBLE ACUTE */ + {0x172, 2, 330}, /* LATIN CAPITAL LETTER U WITH OGONEK */ + {0x173, 2, 332}, /* LATIN SMALL LETTER U WITH OGONEK */ + {0x174, 2, 334}, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */ + {0x175, 2, 336}, /* LATIN SMALL LETTER W WITH CIRCUMFLEX */ + {0x176, 2, 338}, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */ + {0x177, 2, 340}, /* LATIN SMALL LETTER Y WITH CIRCUMFLEX */ + {0x178, 2, 342}, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ + {0x179, 2, 344}, /* LATIN CAPITAL LETTER Z WITH ACUTE */ + {0x17a, 2, 346}, /* LATIN SMALL LETTER Z WITH ACUTE */ + {0x17b, 2, 348}, /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */ + {0x17c, 2, 350}, /* LATIN SMALL LETTER Z WITH DOT ABOVE */ + {0x17d, 2, 352}, /* LATIN CAPITAL LETTER Z WITH CARON */ + {0x17e, 2, 354}, /* LATIN SMALL LETTER Z WITH CARON */ + {0x17f, 1, 288}, /* LATIN SMALL LETTER LONG S */ + {0x1a0, 2, 356}, /* LATIN CAPITAL LETTER O WITH HORN */ + {0x1a1, 2, 358}, /* LATIN SMALL LETTER O WITH HORN */ + {0x1af, 2, 360}, /* LATIN CAPITAL LETTER U WITH HORN */ + {0x1b0, 2, 362}, /* LATIN SMALL LETTER U WITH HORN */ + {0x1c4, 2, 364}, /* LATIN CAPITAL LETTER DZ WITH CARON */ + {0x1c5, 2, 366}, /* LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON */ + {0x1c6, 2, 368}, /* LATIN SMALL LETTER DZ WITH CARON */ + {0x1c7, 2, 370}, /* LATIN CAPITAL LETTER LJ */ + {0x1c8, 2, 372}, /* LATIN CAPITAL LETTER L WITH SMALL LETTER J */ + {0x1c9, 2, 374}, /* LATIN SMALL LETTER LJ */ + {0x1ca, 2, 376}, /* LATIN CAPITAL LETTER NJ */ + {0x1cb, 2, 378}, /* LATIN CAPITAL LETTER N WITH SMALL LETTER J */ + {0x1cc, 2, 380}, /* LATIN SMALL LETTER NJ */ + {0x1cd, 2, 382}, /* LATIN CAPITAL LETTER A WITH CARON */ + {0x1ce, 2, 384}, /* LATIN SMALL LETTER A WITH CARON */ + {0x1cf, 2, 386}, /* LATIN CAPITAL LETTER I WITH CARON */ + {0x1d0, 2, 388}, /* LATIN SMALL LETTER I WITH CARON */ + {0x1d1, 2, 390}, /* LATIN CAPITAL LETTER O WITH CARON */ + {0x1d2, 2, 392}, /* LATIN SMALL LETTER O WITH CARON */ + {0x1d3, 2, 394}, /* LATIN CAPITAL LETTER U WITH CARON */ + {0x1d4, 2, 396}, /* LATIN SMALL LETTER U WITH CARON */ + {0x1d5, 2, 398}, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON */ + {0x1d6, 2, 400}, /* LATIN SMALL LETTER U WITH DIAERESIS AND MACRON */ + {0x1d7, 2, 402}, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE */ + {0x1d8, 2, 404}, /* LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE */ + {0x1d9, 2, 406}, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON */ + {0x1da, 2, 408}, /* LATIN SMALL LETTER U WITH DIAERESIS AND CARON */ + {0x1db, 2, 410}, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE */ + {0x1dc, 2, 412}, /* LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE */ + {0x1de, 2, 414}, /* LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON */ + {0x1df, 2, 416}, /* LATIN SMALL LETTER A WITH DIAERESIS AND MACRON */ + {0x1e0, 2, 418}, /* LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON */ + {0x1e1, 2, 420}, /* LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON */ + {0x1e2, 2, 422}, /* LATIN CAPITAL LETTER AE WITH MACRON */ + {0x1e3, 2, 424}, /* LATIN SMALL LETTER AE WITH MACRON */ + {0x1e6, 2, 426}, /* LATIN CAPITAL LETTER G WITH CARON */ + {0x1e7, 2, 428}, /* LATIN SMALL LETTER G WITH CARON */ + {0x1e8, 2, 430}, /* LATIN CAPITAL LETTER K WITH CARON */ + {0x1e9, 2, 432}, /* LATIN SMALL LETTER K WITH CARON */ + {0x1ea, 2, 434}, /* LATIN CAPITAL LETTER O WITH OGONEK */ + {0x1eb, 2, 436}, /* LATIN SMALL LETTER O WITH OGONEK */ + {0x1ec, 2, 438}, /* LATIN CAPITAL LETTER O WITH OGONEK AND MACRON */ + {0x1ed, 2, 440}, /* LATIN SMALL LETTER O WITH OGONEK AND MACRON */ + {0x1ee, 2, 442}, /* LATIN CAPITAL LETTER EZH WITH CARON */ + {0x1ef, 2, 444}, /* LATIN SMALL LETTER EZH WITH CARON */ + {0x1f0, 2, 446}, /* LATIN SMALL LETTER J WITH CARON */ + {0x1f1, 2, 448}, /* LATIN CAPITAL LETTER DZ */ + {0x1f2, 2, 450}, /* LATIN CAPITAL LETTER D WITH SMALL LETTER Z */ + {0x1f3, 2, 452}, /* LATIN SMALL LETTER DZ */ + {0x1f4, 2, 454}, /* LATIN CAPITAL LETTER G WITH ACUTE */ + {0x1f5, 2, 456}, /* LATIN SMALL LETTER G WITH ACUTE */ + {0x1f8, 2, 458}, /* LATIN CAPITAL LETTER N WITH GRAVE */ + {0x1f9, 2, 460}, /* LATIN SMALL LETTER N WITH GRAVE */ + {0x1fa, 2, 462}, /* LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE */ + {0x1fb, 2, 464}, /* LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE */ + {0x1fc, 2, 466}, /* LATIN CAPITAL LETTER AE WITH ACUTE */ + {0x1fd, 2, 468}, /* LATIN SMALL LETTER AE WITH ACUTE */ + {0x1fe, 2, 470}, /* LATIN CAPITAL LETTER O WITH STROKE AND ACUTE */ + {0x1ff, 2, 472}, /* LATIN SMALL LETTER O WITH STROKE AND ACUTE */ + {0x200, 2, 474}, /* LATIN CAPITAL LETTER A WITH DOUBLE GRAVE */ + {0x201, 2, 476}, /* LATIN SMALL LETTER A WITH DOUBLE GRAVE */ + {0x202, 2, 478}, /* LATIN CAPITAL LETTER A WITH INVERTED BREVE */ + {0x203, 2, 480}, /* LATIN SMALL LETTER A WITH INVERTED BREVE */ + {0x204, 2, 482}, /* LATIN CAPITAL LETTER E WITH DOUBLE GRAVE */ + {0x205, 2, 484}, /* LATIN SMALL LETTER E WITH DOUBLE GRAVE */ + {0x206, 2, 486}, /* LATIN CAPITAL LETTER E WITH INVERTED BREVE */ + {0x207, 2, 488}, /* LATIN SMALL LETTER E WITH INVERTED BREVE */ + {0x208, 2, 490}, /* LATIN CAPITAL LETTER I WITH DOUBLE GRAVE */ + {0x209, 2, 492}, /* LATIN SMALL LETTER I WITH DOUBLE GRAVE */ + {0x20a, 2, 494}, /* LATIN CAPITAL LETTER I WITH INVERTED BREVE */ + {0x20b, 2, 496}, /* LATIN SMALL LETTER I WITH INVERTED BREVE */ + {0x20c, 2, 498}, /* LATIN CAPITAL LETTER O WITH DOUBLE GRAVE */ + {0x20d, 2, 500}, /* LATIN SMALL LETTER O WITH DOUBLE GRAVE */ + {0x20e, 2, 502}, /* LATIN CAPITAL LETTER O WITH INVERTED BREVE */ + {0x20f, 2, 504}, /* LATIN SMALL LETTER O WITH INVERTED BREVE */ + {0x210, 2, 506}, /* LATIN CAPITAL LETTER R WITH DOUBLE GRAVE */ + {0x211, 2, 508}, /* LATIN SMALL LETTER R WITH DOUBLE GRAVE */ + {0x212, 2, 510}, /* LATIN CAPITAL LETTER R WITH INVERTED BREVE */ + {0x213, 2, 512}, /* LATIN SMALL LETTER R WITH INVERTED BREVE */ + {0x214, 2, 514}, /* LATIN CAPITAL LETTER U WITH DOUBLE GRAVE */ + {0x215, 2, 516}, /* LATIN SMALL LETTER U WITH DOUBLE GRAVE */ + {0x216, 2, 518}, /* LATIN CAPITAL LETTER U WITH INVERTED BREVE */ + {0x217, 2, 520}, /* LATIN SMALL LETTER U WITH INVERTED BREVE */ + {0x218, 2, 522}, /* LATIN CAPITAL LETTER S WITH COMMA BELOW */ + {0x219, 2, 524}, /* LATIN SMALL LETTER S WITH COMMA BELOW */ + {0x21a, 2, 526}, /* LATIN CAPITAL LETTER T WITH COMMA BELOW */ + {0x21b, 2, 528}, /* LATIN SMALL LETTER T WITH COMMA BELOW */ + {0x21e, 2, 530}, /* LATIN CAPITAL LETTER H WITH CARON */ + {0x21f, 2, 532}, /* LATIN SMALL LETTER H WITH CARON */ + {0x226, 2, 534}, /* LATIN CAPITAL LETTER A WITH DOT ABOVE */ + {0x227, 2, 536}, /* LATIN SMALL LETTER A WITH DOT ABOVE */ + {0x228, 2, 538}, /* LATIN CAPITAL LETTER E WITH CEDILLA */ + {0x229, 2, 540}, /* LATIN SMALL LETTER E WITH CEDILLA */ + {0x22a, 2, 542}, /* LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON */ + {0x22b, 2, 544}, /* LATIN SMALL LETTER O WITH DIAERESIS AND MACRON */ + {0x22c, 2, 546}, /* LATIN CAPITAL LETTER O WITH TILDE AND MACRON */ + {0x22d, 2, 548}, /* LATIN SMALL LETTER O WITH TILDE AND MACRON */ + {0x22e, 2, 550}, /* LATIN CAPITAL LETTER O WITH DOT ABOVE */ + {0x22f, 2, 552}, /* LATIN SMALL LETTER O WITH DOT ABOVE */ + {0x230, 2, 554}, /* LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON */ + {0x231, 2, 556}, /* LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON */ + {0x232, 2, 558}, /* LATIN CAPITAL LETTER Y WITH MACRON */ + {0x233, 2, 560}, /* LATIN SMALL LETTER Y WITH MACRON */ + {0x2b0, 1, 200}, /* MODIFIER LETTER SMALL H */ + {0x2b1, 1, 562}, /* MODIFIER LETTER SMALL H WITH HOOK */ + {0x2b2, 1, 223}, /* MODIFIER LETTER SMALL J */ + {0x2b3, 1, 276}, /* MODIFIER LETTER SMALL R */ + {0x2b4, 1, 563}, /* MODIFIER LETTER SMALL TURNED R */ + {0x2b5, 1, 564}, /* MODIFIER LETTER SMALL TURNED R WITH HOOK */ + {0x2b6, 1, 565}, /* MODIFIER LETTER SMALL CAPITAL INVERTED R */ + {0x2b7, 1, 336}, /* MODIFIER LETTER SMALL W */ + {0x2b8, 1, 126}, /* MODIFIER LETTER SMALL Y */ + {0x2d8, 2, 566}, /* BREVE */ + {0x2d9, 2, 568}, /* DOT ABOVE */ + {0x2da, 2, 570}, /* RING ABOVE */ + {0x2db, 2, 572}, /* OGONEK */ + {0x2dc, 2, 574}, /* SMALL TILDE */ + {0x2dd, 2, 576}, /* DOUBLE ACUTE ACCENT */ + {0x2e0, 1, 578}, /* MODIFIER LETTER SMALL GAMMA */ + {0x2e1, 1, 234}, /* MODIFIER LETTER SMALL L */ + {0x2e2, 1, 288}, /* MODIFIER LETTER SMALL S */ + {0x2e3, 1, 579}, /* MODIFIER LETTER SMALL X */ + {0x2e4, 1, 580}, /* MODIFIER LETTER SMALL REVERSED GLOTTAL STOP */ + {0x340, 1, 25}, /* COMBINING GRAVE TONE MARK */ + {0x341, 1, 9}, /* COMBINING ACUTE TONE MARK */ + {0x343, 1, 581}, /* COMBINING GREEK KORONIS */ + {0x344, 2, 582}, /* COMBINING GREEK DIALYTIKA TONOS */ + {0x374, 1, 584}, /* GREEK NUMERAL SIGN */ + {0x37a, 2, 585}, /* GREEK YPOGEGRAMMENI */ + {0x37e, 1, 587}, /* GREEK QUESTION MARK */ + {0x384, 2, 8}, /* GREEK TONOS */ + {0x385, 2, 588}, /* GREEK DIALYTIKA TONOS */ + {0x386, 2, 590}, /* GREEK CAPITAL LETTER ALPHA WITH TONOS */ + {0x387, 1, 245}, /* GREEK ANO TELEIA */ + {0x388, 2, 592}, /* GREEK CAPITAL LETTER EPSILON WITH TONOS */ + {0x389, 2, 594}, /* GREEK CAPITAL LETTER ETA WITH TONOS */ + {0x38a, 2, 596}, /* GREEK CAPITAL LETTER IOTA WITH TONOS */ + {0x38c, 2, 598}, /* GREEK CAPITAL LETTER OMICRON WITH TONOS */ + {0x38e, 2, 600}, /* GREEK CAPITAL LETTER UPSILON WITH TONOS */ + {0x38f, 2, 602}, /* GREEK CAPITAL LETTER OMEGA WITH TONOS */ + {0x390, 2, 604}, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ + {0x3aa, 2, 606}, /* GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ + {0x3ab, 2, 608}, /* GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ + {0x3ac, 2, 610}, /* GREEK SMALL LETTER ALPHA WITH TONOS */ + {0x3ad, 2, 612}, /* GREEK SMALL LETTER EPSILON WITH TONOS */ + {0x3ae, 2, 614}, /* GREEK SMALL LETTER ETA WITH TONOS */ + {0x3af, 2, 616}, /* GREEK SMALL LETTER IOTA WITH TONOS */ + {0x3b0, 2, 618}, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ + {0x3ca, 2, 620}, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA */ + {0x3cb, 2, 622}, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ + {0x3cc, 2, 624}, /* GREEK SMALL LETTER OMICRON WITH TONOS */ + {0x3cd, 2, 626}, /* GREEK SMALL LETTER UPSILON WITH TONOS */ + {0x3ce, 2, 628}, /* GREEK SMALL LETTER OMEGA WITH TONOS */ + {0x3d0, 1, 630}, /* GREEK BETA SYMBOL */ + {0x3d1, 1, 631}, /* GREEK THETA SYMBOL */ + {0x3d2, 1, 600}, /* GREEK UPSILON WITH HOOK SYMBOL */ + {0x3d3, 2, 632}, /* GREEK UPSILON WITH ACUTE AND HOOK SYMBOL */ + {0x3d4, 2, 634}, /* GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL */ + {0x3d5, 1, 636}, /* GREEK PHI SYMBOL */ + {0x3d6, 1, 637}, /* GREEK PI SYMBOL */ + {0x3f0, 1, 638}, /* GREEK KAPPA SYMBOL */ + {0x3f1, 1, 639}, /* GREEK RHO SYMBOL */ + {0x3f2, 1, 640}, /* GREEK LUNATE SIGMA SYMBOL */ + {0x3f4, 1, 641}, /* GREEK CAPITAL THETA SYMBOL */ + {0x3f5, 1, 612}, /* GREEK LUNATE EPSILON SYMBOL */ + {0x3f9, 1, 642}, /* GREEK CAPITAL LUNATE SIGMA SYMBOL */ + {0x400, 2, 643}, /* CYRILLIC CAPITAL LETTER IE WITH GRAVE */ + {0x401, 2, 645}, /* CYRILLIC CAPITAL LETTER IO */ + {0x403, 2, 647}, /* CYRILLIC CAPITAL LETTER GJE */ + {0x407, 2, 649}, /* CYRILLIC CAPITAL LETTER YI */ + {0x40c, 2, 651}, /* CYRILLIC CAPITAL LETTER KJE */ + {0x40d, 2, 653}, /* CYRILLIC CAPITAL LETTER I WITH GRAVE */ + {0x40e, 2, 655}, /* CYRILLIC CAPITAL LETTER SHORT U */ + {0x419, 2, 657}, /* CYRILLIC CAPITAL LETTER SHORT I */ + {0x439, 2, 659}, /* CYRILLIC SMALL LETTER SHORT I */ + {0x450, 2, 661}, /* CYRILLIC SMALL LETTER IE WITH GRAVE */ + {0x451, 2, 663}, /* CYRILLIC SMALL LETTER IO */ + {0x453, 2, 665}, /* CYRILLIC SMALL LETTER GJE */ + {0x457, 2, 667}, /* CYRILLIC SMALL LETTER YI */ + {0x45c, 2, 669}, /* CYRILLIC SMALL LETTER KJE */ + {0x45d, 2, 671}, /* CYRILLIC SMALL LETTER I WITH GRAVE */ + {0x45e, 2, 673}, /* CYRILLIC SMALL LETTER SHORT U */ + {0x476, 2, 675}, /* CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT */ + {0x477, 2, 677}, /* CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT */ + {0x4c1, 2, 679}, /* CYRILLIC CAPITAL LETTER ZHE WITH BREVE */ + {0x4c2, 2, 681}, /* CYRILLIC SMALL LETTER ZHE WITH BREVE */ + {0x4d0, 2, 683}, /* CYRILLIC CAPITAL LETTER A WITH BREVE */ + {0x4d1, 2, 685}, /* CYRILLIC SMALL LETTER A WITH BREVE */ + {0x4d2, 2, 687}, /* CYRILLIC CAPITAL LETTER A WITH DIAERESIS */ + {0x4d3, 2, 689}, /* CYRILLIC SMALL LETTER A WITH DIAERESIS */ + {0x4d6, 2, 691}, /* CYRILLIC CAPITAL LETTER IE WITH BREVE */ + {0x4d7, 2, 693}, /* CYRILLIC SMALL LETTER IE WITH BREVE */ + {0x4da, 2, 695}, /* CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS */ + {0x4db, 2, 697}, /* CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS */ + {0x4dc, 2, 699}, /* CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS */ + {0x4dd, 2, 701}, /* CYRILLIC SMALL LETTER ZHE WITH DIAERESIS */ + {0x4de, 2, 703}, /* CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS */ + {0x4df, 2, 705}, /* CYRILLIC SMALL LETTER ZE WITH DIAERESIS */ + {0x4e2, 2, 707}, /* CYRILLIC CAPITAL LETTER I WITH MACRON */ + {0x4e3, 2, 709}, /* CYRILLIC SMALL LETTER I WITH MACRON */ + {0x4e4, 2, 711}, /* CYRILLIC CAPITAL LETTER I WITH DIAERESIS */ + {0x4e5, 2, 713}, /* CYRILLIC SMALL LETTER I WITH DIAERESIS */ + {0x4e6, 2, 715}, /* CYRILLIC CAPITAL LETTER O WITH DIAERESIS */ + {0x4e7, 2, 717}, /* CYRILLIC SMALL LETTER O WITH DIAERESIS */ + {0x4ea, 2, 719}, /* CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS */ + {0x4eb, 2, 721}, /* CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS */ + {0x4ec, 2, 723}, /* CYRILLIC CAPITAL LETTER E WITH DIAERESIS */ + {0x4ed, 2, 725}, /* CYRILLIC SMALL LETTER E WITH DIAERESIS */ + {0x4ee, 2, 727}, /* CYRILLIC CAPITAL LETTER U WITH MACRON */ + {0x4ef, 2, 729}, /* CYRILLIC SMALL LETTER U WITH MACRON */ + {0x4f0, 2, 731}, /* CYRILLIC CAPITAL LETTER U WITH DIAERESIS */ + {0x4f1, 2, 733}, /* CYRILLIC SMALL LETTER U WITH DIAERESIS */ + {0x4f2, 2, 735}, /* CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE */ + {0x4f3, 2, 737}, /* CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE */ + {0x4f4, 2, 739}, /* CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS */ + {0x4f5, 2, 741}, /* CYRILLIC SMALL LETTER CHE WITH DIAERESIS */ + {0x4f8, 2, 743}, /* CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS */ + {0x4f9, 2, 745}, /* CYRILLIC SMALL LETTER YERU WITH DIAERESIS */ + {0x587, 2, 747}, /* ARMENIAN SMALL LIGATURE ECH YIWN */ + {0x622, 2, 749}, /* ARABIC LETTER ALEF WITH MADDA ABOVE */ + {0x623, 2, 751}, /* ARABIC LETTER ALEF WITH HAMZA ABOVE */ + {0x624, 2, 753}, /* ARABIC LETTER WAW WITH HAMZA ABOVE */ + {0x625, 2, 755}, /* ARABIC LETTER ALEF WITH HAMZA BELOW */ + {0x626, 2, 757}, /* ARABIC LETTER YEH WITH HAMZA ABOVE */ + {0x675, 2, 759}, /* ARABIC LETTER HIGH HAMZA ALEF */ + {0x676, 2, 761}, /* ARABIC LETTER HIGH HAMZA WAW */ + {0x677, 2, 763}, /* ARABIC LETTER U WITH HAMZA ABOVE */ + {0x678, 2, 765}, /* ARABIC LETTER HIGH HAMZA YEH */ + {0x6c0, 2, 767}, /* ARABIC LETTER HEH WITH YEH ABOVE */ + {0x6c2, 2, 769}, /* ARABIC LETTER HEH GOAL WITH HAMZA ABOVE */ + {0x6d3, 2, 771}, /* ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */ + {0x929, 2, 773}, /* DEVANAGARI LETTER NNNA */ + {0x931, 2, 775}, /* DEVANAGARI LETTER RRA */ + {0x934, 2, 777}, /* DEVANAGARI LETTER LLLA */ + {0x958, 2, 779}, /* DEVANAGARI LETTER QA */ + {0x959, 2, 781}, /* DEVANAGARI LETTER KHHA */ + {0x95a, 2, 783}, /* DEVANAGARI LETTER GHHA */ + {0x95b, 2, 785}, /* DEVANAGARI LETTER ZA */ + {0x95c, 2, 787}, /* DEVANAGARI LETTER DDDHA */ + {0x95d, 2, 789}, /* DEVANAGARI LETTER RHA */ + {0x95e, 2, 791}, /* DEVANAGARI LETTER FA */ + {0x95f, 2, 793}, /* DEVANAGARI LETTER YYA */ + {0x9cb, 2, 795}, /* BENGALI VOWEL SIGN O */ + {0x9cc, 2, 797}, /* BENGALI VOWEL SIGN AU */ + {0x9dc, 2, 799}, /* BENGALI LETTER RRA */ + {0x9dd, 2, 801}, /* BENGALI LETTER RHA */ + {0x9df, 2, 803}, /* BENGALI LETTER YYA */ + {0xa33, 2, 805}, /* GURMUKHI LETTER LLA */ + {0xa36, 2, 807}, /* GURMUKHI LETTER SHA */ + {0xa59, 2, 809}, /* GURMUKHI LETTER KHHA */ + {0xa5a, 2, 811}, /* GURMUKHI LETTER GHHA */ + {0xa5b, 2, 813}, /* GURMUKHI LETTER ZA */ + {0xa5e, 2, 815}, /* GURMUKHI LETTER FA */ + {0xb48, 2, 817}, /* ORIYA VOWEL SIGN AI */ + {0xb4b, 2, 819}, /* ORIYA VOWEL SIGN O */ + {0xb4c, 2, 821}, /* ORIYA VOWEL SIGN AU */ + {0xb5c, 2, 823}, /* ORIYA LETTER RRA */ + {0xb5d, 2, 825}, /* ORIYA LETTER RHA */ + {0xb94, 2, 827}, /* TAMIL LETTER AU */ + {0xbca, 2, 829}, /* TAMIL VOWEL SIGN O */ + {0xbcb, 2, 831}, /* TAMIL VOWEL SIGN OO */ + {0xbcc, 2, 833}, /* TAMIL VOWEL SIGN AU */ + {0xc48, 2, 835}, /* TELUGU VOWEL SIGN AI */ + {0xcc0, 2, 837}, /* KANNADA VOWEL SIGN II */ + {0xcc7, 2, 839}, /* KANNADA VOWEL SIGN EE */ + {0xcc8, 2, 841}, /* KANNADA VOWEL SIGN AI */ + {0xcca, 2, 843}, /* KANNADA VOWEL SIGN O */ + {0xccb, 2, 845}, /* KANNADA VOWEL SIGN OO */ + {0xd4a, 2, 847}, /* MALAYALAM VOWEL SIGN O */ + {0xd4b, 2, 849}, /* MALAYALAM VOWEL SIGN OO */ + {0xd4c, 2, 851}, /* MALAYALAM VOWEL SIGN AU */ + {0xdda, 2, 853}, /* SINHALA VOWEL SIGN DIGA KOMBUVA */ + {0xddc, 2, 855}, /* SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA */ + {0xddd, 2, 857}, /* SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA */ + {0xdde, 2, 859}, /* SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA */ + {0xe33, 2, 861}, /* THAI CHARACTER SARA AM */ + {0xeb3, 2, 863}, /* LAO VOWEL SIGN AM */ + {0xedc, 2, 865}, /* LAO HO NO */ + {0xedd, 2, 867}, /* LAO HO MO */ + {0xf0c, 1, 869}, /* TIBETAN MARK DELIMITER TSHEG BSTAR */ + {0xf43, 2, 870}, /* TIBETAN LETTER GHA */ + {0xf4d, 2, 872}, /* TIBETAN LETTER DDHA */ + {0xf52, 2, 874}, /* TIBETAN LETTER DHA */ + {0xf57, 2, 876}, /* TIBETAN LETTER BHA */ + {0xf5c, 2, 878}, /* TIBETAN LETTER DZHA */ + {0xf69, 2, 880}, /* TIBETAN LETTER KSSA */ + {0xf73, 2, 882}, /* TIBETAN VOWEL SIGN II */ + {0xf75, 2, 884}, /* TIBETAN VOWEL SIGN UU */ + {0xf76, 2, 886}, /* TIBETAN VOWEL SIGN VOCALIC R */ + {0xf77, 2, 888}, /* TIBETAN VOWEL SIGN VOCALIC RR */ + {0xf78, 2, 890}, /* TIBETAN VOWEL SIGN VOCALIC L */ + {0xf79, 2, 892}, /* TIBETAN VOWEL SIGN VOCALIC LL */ + {0xf81, 2, 894}, /* TIBETAN VOWEL SIGN REVERSED II */ + {0xf93, 2, 896}, /* TIBETAN SUBJOINED LETTER GHA */ + {0xf9d, 2, 898}, /* TIBETAN SUBJOINED LETTER DDHA */ + {0xfa2, 2, 900}, /* TIBETAN SUBJOINED LETTER DHA */ + {0xfa7, 2, 902}, /* TIBETAN SUBJOINED LETTER BHA */ + {0xfac, 2, 904}, /* TIBETAN SUBJOINED LETTER DZHA */ + {0xfb9, 2, 906}, /* TIBETAN SUBJOINED LETTER KSSA */ + {0x1026, 2, 908}, /* MYANMAR LETTER UU */ + {0x1d2c, 1, 24}, /* MODIFIER LETTER CAPITAL A */ + {0x1d2d, 1, 422}, /* MODIFIER LETTER CAPITAL AE */ + {0x1d2e, 1, 910}, /* MODIFIER LETTER CAPITAL B */ + {0x1d30, 1, 158}, /* MODIFIER LETTER CAPITAL D */ + {0x1d31, 1, 38}, /* MODIFIER LETTER CAPITAL E */ + {0x1d32, 1, 911}, /* MODIFIER LETTER CAPITAL REVERSED E */ + {0x1d33, 1, 182}, /* MODIFIER LETTER CAPITAL G */ + {0x1d34, 1, 198}, /* MODIFIER LETTER CAPITAL H */ + {0x1d35, 1, 46}, /* MODIFIER LETTER CAPITAL I */ + {0x1d36, 1, 221}, /* MODIFIER LETTER CAPITAL J */ + {0x1d37, 1, 228}, /* MODIFIER LETTER CAPITAL K */ + {0x1d38, 1, 232}, /* MODIFIER LETTER CAPITAL L */ + {0x1d39, 1, 912}, /* MODIFIER LETTER CAPITAL M */ + {0x1d3a, 1, 54}, /* MODIFIER LETTER CAPITAL N */ + {0x1d3c, 1, 56}, /* MODIFIER LETTER CAPITAL O */ + {0x1d3d, 1, 913}, /* MODIFIER LETTER CAPITAL OU */ + {0x1d3e, 1, 914}, /* MODIFIER LETTER CAPITAL P */ + {0x1d3f, 1, 274}, /* MODIFIER LETTER CAPITAL R */ + {0x1d40, 1, 302}, /* MODIFIER LETTER CAPITAL T */ + {0x1d41, 1, 66}, /* MODIFIER LETTER CAPITAL U */ + {0x1d42, 1, 334}, /* MODIFIER LETTER CAPITAL W */ + {0x1d43, 1, 3}, /* MODIFIER LETTER SMALL A */ + {0x1d44, 1, 915}, /* MODIFIER LETTER SMALL TURNED A */ + {0x1d45, 1, 916}, /* MODIFIER LETTER SMALL ALPHA */ + {0x1d46, 1, 917}, /* MODIFIER LETTER SMALL TURNED AE */ + {0x1d47, 1, 918}, /* MODIFIER LETTER SMALL B */ + {0x1d48, 1, 160}, /* MODIFIER LETTER SMALL D */ + {0x1d49, 1, 90}, /* MODIFIER LETTER SMALL E */ + {0x1d4a, 1, 919}, /* MODIFIER LETTER SMALL SCHWA */ + {0x1d4b, 1, 920}, /* MODIFIER LETTER SMALL OPEN E */ + {0x1d4c, 1, 921}, /* MODIFIER LETTER SMALL TURNED OPEN E */ + {0x1d4d, 1, 184}, /* MODIFIER LETTER SMALL G */ + {0x1d4f, 1, 230}, /* MODIFIER LETTER SMALL K */ + {0x1d50, 1, 922}, /* MODIFIER LETTER SMALL M */ + {0x1d51, 1, 923}, /* MODIFIER LETTER SMALL ENG */ + {0x1d52, 1, 14}, /* MODIFIER LETTER SMALL O */ + {0x1d53, 1, 924}, /* MODIFIER LETTER SMALL OPEN O */ + {0x1d54, 1, 925}, /* MODIFIER LETTER SMALL TOP HALF O */ + {0x1d55, 1, 926}, /* MODIFIER LETTER SMALL BOTTOM HALF O */ + {0x1d56, 1, 927}, /* MODIFIER LETTER SMALL P */ + {0x1d57, 1, 304}, /* MODIFIER LETTER SMALL T */ + {0x1d58, 1, 118}, /* MODIFIER LETTER SMALL U */ + {0x1d59, 1, 928}, /* MODIFIER LETTER SMALL SIDEWAYS U */ + {0x1d5a, 1, 929}, /* MODIFIER LETTER SMALL TURNED M */ + {0x1d5b, 1, 930}, /* MODIFIER LETTER SMALL V */ + {0x1d5c, 1, 931}, /* MODIFIER LETTER SMALL AIN */ + {0x1d5d, 1, 630}, /* MODIFIER LETTER SMALL BETA */ + {0x1d5e, 1, 932}, /* MODIFIER LETTER SMALL GREEK GAMMA */ + {0x1d5f, 1, 933}, /* MODIFIER LETTER SMALL DELTA */ + {0x1d60, 1, 636}, /* MODIFIER LETTER SMALL GREEK PHI */ + {0x1d61, 1, 934}, /* MODIFIER LETTER SMALL CHI */ + {0x1d62, 1, 98}, /* LATIN SUBSCRIPT SMALL LETTER I */ + {0x1d63, 1, 276}, /* LATIN SUBSCRIPT SMALL LETTER R */ + {0x1d64, 1, 118}, /* LATIN SUBSCRIPT SMALL LETTER U */ + {0x1d65, 1, 930}, /* LATIN SUBSCRIPT SMALL LETTER V */ + {0x1d66, 1, 630}, /* GREEK SUBSCRIPT SMALL LETTER BETA */ + {0x1d67, 1, 932}, /* GREEK SUBSCRIPT SMALL LETTER GAMMA */ + {0x1d68, 1, 639}, /* GREEK SUBSCRIPT SMALL LETTER RHO */ + {0x1d69, 1, 636}, /* GREEK SUBSCRIPT SMALL LETTER PHI */ + {0x1d6a, 1, 934}, /* GREEK SUBSCRIPT SMALL LETTER CHI */ + {0x1e00, 2, 935}, /* LATIN CAPITAL LETTER A WITH RING BELOW */ + {0x1e01, 2, 937}, /* LATIN SMALL LETTER A WITH RING BELOW */ + {0x1e02, 2, 939}, /* LATIN CAPITAL LETTER B WITH DOT ABOVE */ + {0x1e03, 2, 941}, /* LATIN SMALL LETTER B WITH DOT ABOVE */ + {0x1e04, 2, 943}, /* LATIN CAPITAL LETTER B WITH DOT BELOW */ + {0x1e05, 2, 945}, /* LATIN SMALL LETTER B WITH DOT BELOW */ + {0x1e06, 2, 947}, /* LATIN CAPITAL LETTER B WITH LINE BELOW */ + {0x1e07, 2, 949}, /* LATIN SMALL LETTER B WITH LINE BELOW */ + {0x1e08, 2, 951}, /* LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE */ + {0x1e09, 2, 953}, /* LATIN SMALL LETTER C WITH CEDILLA AND ACUTE */ + {0x1e0a, 2, 955}, /* LATIN CAPITAL LETTER D WITH DOT ABOVE */ + {0x1e0b, 2, 957}, /* LATIN SMALL LETTER D WITH DOT ABOVE */ + {0x1e0c, 2, 959}, /* LATIN CAPITAL LETTER D WITH DOT BELOW */ + {0x1e0d, 2, 961}, /* LATIN SMALL LETTER D WITH DOT BELOW */ + {0x1e0e, 2, 963}, /* LATIN CAPITAL LETTER D WITH LINE BELOW */ + {0x1e0f, 2, 965}, /* LATIN SMALL LETTER D WITH LINE BELOW */ + {0x1e10, 2, 967}, /* LATIN CAPITAL LETTER D WITH CEDILLA */ + {0x1e11, 2, 969}, /* LATIN SMALL LETTER D WITH CEDILLA */ + {0x1e12, 2, 971}, /* LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW */ + {0x1e13, 2, 973}, /* LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW */ + {0x1e14, 2, 975}, /* LATIN CAPITAL LETTER E WITH MACRON AND GRAVE */ + {0x1e15, 2, 977}, /* LATIN SMALL LETTER E WITH MACRON AND GRAVE */ + {0x1e16, 2, 979}, /* LATIN CAPITAL LETTER E WITH MACRON AND ACUTE */ + {0x1e17, 2, 981}, /* LATIN SMALL LETTER E WITH MACRON AND ACUTE */ + {0x1e18, 2, 983}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW */ + {0x1e19, 2, 985}, /* LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW */ + {0x1e1a, 2, 987}, /* LATIN CAPITAL LETTER E WITH TILDE BELOW */ + {0x1e1b, 2, 989}, /* LATIN SMALL LETTER E WITH TILDE BELOW */ + {0x1e1c, 2, 991}, /* LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE */ + {0x1e1d, 2, 993}, /* LATIN SMALL LETTER E WITH CEDILLA AND BREVE */ + {0x1e1e, 2, 995}, /* LATIN CAPITAL LETTER F WITH DOT ABOVE */ + {0x1e1f, 2, 997}, /* LATIN SMALL LETTER F WITH DOT ABOVE */ + {0x1e20, 2, 999}, /* LATIN CAPITAL LETTER G WITH MACRON */ + {0x1e21, 2, 1001}, /* LATIN SMALL LETTER G WITH MACRON */ + {0x1e22, 2, 1003}, /* LATIN CAPITAL LETTER H WITH DOT ABOVE */ + {0x1e23, 2, 1005}, /* LATIN SMALL LETTER H WITH DOT ABOVE */ + {0x1e24, 2, 1007}, /* LATIN CAPITAL LETTER H WITH DOT BELOW */ + {0x1e25, 2, 1009}, /* LATIN SMALL LETTER H WITH DOT BELOW */ + {0x1e26, 2, 1011}, /* LATIN CAPITAL LETTER H WITH DIAERESIS */ + {0x1e27, 2, 1013}, /* LATIN SMALL LETTER H WITH DIAERESIS */ + {0x1e28, 2, 1015}, /* LATIN CAPITAL LETTER H WITH CEDILLA */ + {0x1e29, 2, 1017}, /* LATIN SMALL LETTER H WITH CEDILLA */ + {0x1e2a, 2, 1019}, /* LATIN CAPITAL LETTER H WITH BREVE BELOW */ + {0x1e2b, 2, 1021}, /* LATIN SMALL LETTER H WITH BREVE BELOW */ + {0x1e2c, 2, 1023}, /* LATIN CAPITAL LETTER I WITH TILDE BELOW */ + {0x1e2d, 2, 1025}, /* LATIN SMALL LETTER I WITH TILDE BELOW */ + {0x1e2e, 2, 1027}, /* LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE */ + {0x1e2f, 2, 1029}, /* LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE */ + {0x1e30, 2, 1031}, /* LATIN CAPITAL LETTER K WITH ACUTE */ + {0x1e31, 2, 1033}, /* LATIN SMALL LETTER K WITH ACUTE */ + {0x1e32, 2, 1035}, /* LATIN CAPITAL LETTER K WITH DOT BELOW */ + {0x1e33, 2, 1037}, /* LATIN SMALL LETTER K WITH DOT BELOW */ + {0x1e34, 2, 1039}, /* LATIN CAPITAL LETTER K WITH LINE BELOW */ + {0x1e35, 2, 1041}, /* LATIN SMALL LETTER K WITH LINE BELOW */ + {0x1e36, 2, 1043}, /* LATIN CAPITAL LETTER L WITH DOT BELOW */ + {0x1e37, 2, 1045}, /* LATIN SMALL LETTER L WITH DOT BELOW */ + {0x1e38, 2, 1047}, /* LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON */ + {0x1e39, 2, 1049}, /* LATIN SMALL LETTER L WITH DOT BELOW AND MACRON */ + {0x1e3a, 2, 1051}, /* LATIN CAPITAL LETTER L WITH LINE BELOW */ + {0x1e3b, 2, 1053}, /* LATIN SMALL LETTER L WITH LINE BELOW */ + {0x1e3c, 2, 1055}, /* LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW */ + {0x1e3d, 2, 1057}, /* LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW */ + {0x1e3e, 2, 1059}, /* LATIN CAPITAL LETTER M WITH ACUTE */ + {0x1e3f, 2, 1061}, /* LATIN SMALL LETTER M WITH ACUTE */ + {0x1e40, 2, 1063}, /* LATIN CAPITAL LETTER M WITH DOT ABOVE */ + {0x1e41, 2, 1065}, /* LATIN SMALL LETTER M WITH DOT ABOVE */ + {0x1e42, 2, 1067}, /* LATIN CAPITAL LETTER M WITH DOT BELOW */ + {0x1e43, 2, 1069}, /* LATIN SMALL LETTER M WITH DOT BELOW */ + {0x1e44, 2, 1071}, /* LATIN CAPITAL LETTER N WITH DOT ABOVE */ + {0x1e45, 2, 1073}, /* LATIN SMALL LETTER N WITH DOT ABOVE */ + {0x1e46, 2, 1075}, /* LATIN CAPITAL LETTER N WITH DOT BELOW */ + {0x1e47, 2, 1077}, /* LATIN SMALL LETTER N WITH DOT BELOW */ + {0x1e48, 2, 1079}, /* LATIN CAPITAL LETTER N WITH LINE BELOW */ + {0x1e49, 2, 1081}, /* LATIN SMALL LETTER N WITH LINE BELOW */ + {0x1e4a, 2, 1083}, /* LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW */ + {0x1e4b, 2, 1085}, /* LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW */ + {0x1e4c, 2, 1087}, /* LATIN CAPITAL LETTER O WITH TILDE AND ACUTE */ + {0x1e4d, 2, 1089}, /* LATIN SMALL LETTER O WITH TILDE AND ACUTE */ + {0x1e4e, 2, 1091}, /* LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS */ + {0x1e4f, 2, 1093}, /* LATIN SMALL LETTER O WITH TILDE AND DIAERESIS */ + {0x1e50, 2, 1095}, /* LATIN CAPITAL LETTER O WITH MACRON AND GRAVE */ + {0x1e51, 2, 1097}, /* LATIN SMALL LETTER O WITH MACRON AND GRAVE */ + {0x1e52, 2, 1099}, /* LATIN CAPITAL LETTER O WITH MACRON AND ACUTE */ + {0x1e53, 2, 1101}, /* LATIN SMALL LETTER O WITH MACRON AND ACUTE */ + {0x1e54, 2, 1103}, /* LATIN CAPITAL LETTER P WITH ACUTE */ + {0x1e55, 2, 1105}, /* LATIN SMALL LETTER P WITH ACUTE */ + {0x1e56, 2, 1107}, /* LATIN CAPITAL LETTER P WITH DOT ABOVE */ + {0x1e57, 2, 1109}, /* LATIN SMALL LETTER P WITH DOT ABOVE */ + {0x1e58, 2, 1111}, /* LATIN CAPITAL LETTER R WITH DOT ABOVE */ + {0x1e59, 2, 1113}, /* LATIN SMALL LETTER R WITH DOT ABOVE */ + {0x1e5a, 2, 1115}, /* LATIN CAPITAL LETTER R WITH DOT BELOW */ + {0x1e5b, 2, 1117}, /* LATIN SMALL LETTER R WITH DOT BELOW */ + {0x1e5c, 2, 1119}, /* LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON */ + {0x1e5d, 2, 1121}, /* LATIN SMALL LETTER R WITH DOT BELOW AND MACRON */ + {0x1e5e, 2, 1123}, /* LATIN CAPITAL LETTER R WITH LINE BELOW */ + {0x1e5f, 2, 1125}, /* LATIN SMALL LETTER R WITH LINE BELOW */ + {0x1e60, 2, 1127}, /* LATIN CAPITAL LETTER S WITH DOT ABOVE */ + {0x1e61, 2, 1129}, /* LATIN SMALL LETTER S WITH DOT ABOVE */ + {0x1e62, 2, 1131}, /* LATIN CAPITAL LETTER S WITH DOT BELOW */ + {0x1e63, 2, 1133}, /* LATIN SMALL LETTER S WITH DOT BELOW */ + {0x1e64, 2, 1135}, /* LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE */ + {0x1e65, 2, 1137}, /* LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE */ + {0x1e66, 2, 1139}, /* LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE */ + {0x1e67, 2, 1141}, /* LATIN SMALL LETTER S WITH CARON AND DOT ABOVE */ + {0x1e68, 2, 1143}, /* LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE */ + {0x1e69, 2, 1145}, /* LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE */ + {0x1e6a, 2, 1147}, /* LATIN CAPITAL LETTER T WITH DOT ABOVE */ + {0x1e6b, 2, 1149}, /* LATIN SMALL LETTER T WITH DOT ABOVE */ + {0x1e6c, 2, 1151}, /* LATIN CAPITAL LETTER T WITH DOT BELOW */ + {0x1e6d, 2, 1153}, /* LATIN SMALL LETTER T WITH DOT BELOW */ + {0x1e6e, 2, 1155}, /* LATIN CAPITAL LETTER T WITH LINE BELOW */ + {0x1e6f, 2, 1157}, /* LATIN SMALL LETTER T WITH LINE BELOW */ + {0x1e70, 2, 1159}, /* LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW */ + {0x1e71, 2, 1161}, /* LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW */ + {0x1e72, 2, 1163}, /* LATIN CAPITAL LETTER U WITH DIAERESIS BELOW */ + {0x1e73, 2, 1165}, /* LATIN SMALL LETTER U WITH DIAERESIS BELOW */ + {0x1e74, 2, 1167}, /* LATIN CAPITAL LETTER U WITH TILDE BELOW */ + {0x1e75, 2, 1169}, /* LATIN SMALL LETTER U WITH TILDE BELOW */ + {0x1e76, 2, 1171}, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW */ + {0x1e77, 2, 1173}, /* LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW */ + {0x1e78, 2, 1175}, /* LATIN CAPITAL LETTER U WITH TILDE AND ACUTE */ + {0x1e79, 2, 1177}, /* LATIN SMALL LETTER U WITH TILDE AND ACUTE */ + {0x1e7a, 2, 1179}, /* LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS */ + {0x1e7b, 2, 1181}, /* LATIN SMALL LETTER U WITH MACRON AND DIAERESIS */ + {0x1e7c, 2, 1183}, /* LATIN CAPITAL LETTER V WITH TILDE */ + {0x1e7d, 2, 1185}, /* LATIN SMALL LETTER V WITH TILDE */ + {0x1e7e, 2, 1187}, /* LATIN CAPITAL LETTER V WITH DOT BELOW */ + {0x1e7f, 2, 1189}, /* LATIN SMALL LETTER V WITH DOT BELOW */ + {0x1e80, 2, 1191}, /* LATIN CAPITAL LETTER W WITH GRAVE */ + {0x1e81, 2, 1193}, /* LATIN SMALL LETTER W WITH GRAVE */ + {0x1e82, 2, 1195}, /* LATIN CAPITAL LETTER W WITH ACUTE */ + {0x1e83, 2, 1197}, /* LATIN SMALL LETTER W WITH ACUTE */ + {0x1e84, 2, 1199}, /* LATIN CAPITAL LETTER W WITH DIAERESIS */ + {0x1e85, 2, 1201}, /* LATIN SMALL LETTER W WITH DIAERESIS */ + {0x1e86, 2, 1203}, /* LATIN CAPITAL LETTER W WITH DOT ABOVE */ + {0x1e87, 2, 1205}, /* LATIN SMALL LETTER W WITH DOT ABOVE */ + {0x1e88, 2, 1207}, /* LATIN CAPITAL LETTER W WITH DOT BELOW */ + {0x1e89, 2, 1209}, /* LATIN SMALL LETTER W WITH DOT BELOW */ + {0x1e8a, 2, 1211}, /* LATIN CAPITAL LETTER X WITH DOT ABOVE */ + {0x1e8b, 2, 1213}, /* LATIN SMALL LETTER X WITH DOT ABOVE */ + {0x1e8c, 2, 1215}, /* LATIN CAPITAL LETTER X WITH DIAERESIS */ + {0x1e8d, 2, 1217}, /* LATIN SMALL LETTER X WITH DIAERESIS */ + {0x1e8e, 2, 1219}, /* LATIN CAPITAL LETTER Y WITH DOT ABOVE */ + {0x1e8f, 2, 1221}, /* LATIN SMALL LETTER Y WITH DOT ABOVE */ + {0x1e90, 2, 1223}, /* LATIN CAPITAL LETTER Z WITH CIRCUMFLEX */ + {0x1e91, 2, 1225}, /* LATIN SMALL LETTER Z WITH CIRCUMFLEX */ + {0x1e92, 2, 1227}, /* LATIN CAPITAL LETTER Z WITH DOT BELOW */ + {0x1e93, 2, 1229}, /* LATIN SMALL LETTER Z WITH DOT BELOW */ + {0x1e94, 2, 1231}, /* LATIN CAPITAL LETTER Z WITH LINE BELOW */ + {0x1e95, 2, 1233}, /* LATIN SMALL LETTER Z WITH LINE BELOW */ + {0x1e96, 2, 1235}, /* LATIN SMALL LETTER H WITH LINE BELOW */ + {0x1e97, 2, 1237}, /* LATIN SMALL LETTER T WITH DIAERESIS */ + {0x1e98, 2, 1239}, /* LATIN SMALL LETTER W WITH RING ABOVE */ + {0x1e99, 2, 1241}, /* LATIN SMALL LETTER Y WITH RING ABOVE */ + {0x1e9a, 2, 1243}, /* LATIN SMALL LETTER A WITH RIGHT HALF RING */ + {0x1e9b, 2, 1245}, /* LATIN SMALL LETTER LONG S WITH DOT ABOVE */ + {0x1ea0, 2, 1247}, /* LATIN CAPITAL LETTER A WITH DOT BELOW */ + {0x1ea1, 2, 1249}, /* LATIN SMALL LETTER A WITH DOT BELOW */ + {0x1ea2, 2, 1251}, /* LATIN CAPITAL LETTER A WITH HOOK ABOVE */ + {0x1ea3, 2, 1253}, /* LATIN SMALL LETTER A WITH HOOK ABOVE */ + {0x1ea4, 2, 1255}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */ + {0x1ea5, 2, 1257}, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */ + {0x1ea6, 2, 1259}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */ + {0x1ea7, 2, 1261}, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */ + {0x1ea8, 2, 1263}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ + {0x1ea9, 2, 1265}, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ + {0x1eaa, 2, 1267}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */ + {0x1eab, 2, 1269}, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */ + {0x1eac, 2, 1271}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ + {0x1ead, 2, 1273}, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ + {0x1eae, 2, 1275}, /* LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */ + {0x1eaf, 2, 1277}, /* LATIN SMALL LETTER A WITH BREVE AND ACUTE */ + {0x1eb0, 2, 1279}, /* LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */ + {0x1eb1, 2, 1281}, /* LATIN SMALL LETTER A WITH BREVE AND GRAVE */ + {0x1eb2, 2, 1283}, /* LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */ + {0x1eb3, 2, 1285}, /* LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */ + {0x1eb4, 2, 1287}, /* LATIN CAPITAL LETTER A WITH BREVE AND TILDE */ + {0x1eb5, 2, 1289}, /* LATIN SMALL LETTER A WITH BREVE AND TILDE */ + {0x1eb6, 2, 1291}, /* LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */ + {0x1eb7, 2, 1293}, /* LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */ + {0x1eb8, 2, 1295}, /* LATIN CAPITAL LETTER E WITH DOT BELOW */ + {0x1eb9, 2, 1297}, /* LATIN SMALL LETTER E WITH DOT BELOW */ + {0x1eba, 2, 1299}, /* LATIN CAPITAL LETTER E WITH HOOK ABOVE */ + {0x1ebb, 2, 1301}, /* LATIN SMALL LETTER E WITH HOOK ABOVE */ + {0x1ebc, 2, 1303}, /* LATIN CAPITAL LETTER E WITH TILDE */ + {0x1ebd, 2, 1305}, /* LATIN SMALL LETTER E WITH TILDE */ + {0x1ebe, 2, 1307}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */ + {0x1ebf, 2, 1309}, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */ + {0x1ec0, 2, 1311}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */ + {0x1ec1, 2, 1313}, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */ + {0x1ec2, 2, 1315}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ + {0x1ec3, 2, 1317}, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ + {0x1ec4, 2, 1319}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */ + {0x1ec5, 2, 1321}, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */ + {0x1ec6, 2, 1323}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ + {0x1ec7, 2, 1325}, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ + {0x1ec8, 2, 1327}, /* LATIN CAPITAL LETTER I WITH HOOK ABOVE */ + {0x1ec9, 2, 1329}, /* LATIN SMALL LETTER I WITH HOOK ABOVE */ + {0x1eca, 2, 1331}, /* LATIN CAPITAL LETTER I WITH DOT BELOW */ + {0x1ecb, 2, 1333}, /* LATIN SMALL LETTER I WITH DOT BELOW */ + {0x1ecc, 2, 1335}, /* LATIN CAPITAL LETTER O WITH DOT BELOW */ + {0x1ecd, 2, 1337}, /* LATIN SMALL LETTER O WITH DOT BELOW */ + {0x1ece, 2, 1339}, /* LATIN CAPITAL LETTER O WITH HOOK ABOVE */ + {0x1ecf, 2, 1341}, /* LATIN SMALL LETTER O WITH HOOK ABOVE */ + {0x1ed0, 2, 1343}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */ + {0x1ed1, 2, 1345}, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */ + {0x1ed2, 2, 1347}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */ + {0x1ed3, 2, 1349}, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */ + {0x1ed4, 2, 1351}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ + {0x1ed5, 2, 1353}, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ + {0x1ed6, 2, 1355}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */ + {0x1ed7, 2, 1357}, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */ + {0x1ed8, 2, 1359}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ + {0x1ed9, 2, 1361}, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ + {0x1eda, 2, 1363}, /* LATIN CAPITAL LETTER O WITH HORN AND ACUTE */ + {0x1edb, 2, 1365}, /* LATIN SMALL LETTER O WITH HORN AND ACUTE */ + {0x1edc, 2, 1367}, /* LATIN CAPITAL LETTER O WITH HORN AND GRAVE */ + {0x1edd, 2, 1369}, /* LATIN SMALL LETTER O WITH HORN AND GRAVE */ + {0x1ede, 2, 1371}, /* LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */ + {0x1edf, 2, 1373}, /* LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */ + {0x1ee0, 2, 1375}, /* LATIN CAPITAL LETTER O WITH HORN AND TILDE */ + {0x1ee1, 2, 1377}, /* LATIN SMALL LETTER O WITH HORN AND TILDE */ + {0x1ee2, 2, 1379}, /* LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */ + {0x1ee3, 2, 1381}, /* LATIN SMALL LETTER O WITH HORN AND DOT BELOW */ + {0x1ee4, 2, 1383}, /* LATIN CAPITAL LETTER U WITH DOT BELOW */ + {0x1ee5, 2, 1385}, /* LATIN SMALL LETTER U WITH DOT BELOW */ + {0x1ee6, 2, 1387}, /* LATIN CAPITAL LETTER U WITH HOOK ABOVE */ + {0x1ee7, 2, 1389}, /* LATIN SMALL LETTER U WITH HOOK ABOVE */ + {0x1ee8, 2, 1391}, /* LATIN CAPITAL LETTER U WITH HORN AND ACUTE */ + {0x1ee9, 2, 1393}, /* LATIN SMALL LETTER U WITH HORN AND ACUTE */ + {0x1eea, 2, 1395}, /* LATIN CAPITAL LETTER U WITH HORN AND GRAVE */ + {0x1eeb, 2, 1397}, /* LATIN SMALL LETTER U WITH HORN AND GRAVE */ + {0x1eec, 2, 1399}, /* LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */ + {0x1eed, 2, 1401}, /* LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */ + {0x1eee, 2, 1403}, /* LATIN CAPITAL LETTER U WITH HORN AND TILDE */ + {0x1eef, 2, 1405}, /* LATIN SMALL LETTER U WITH HORN AND TILDE */ + {0x1ef0, 2, 1407}, /* LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */ + {0x1ef1, 2, 1409}, /* LATIN SMALL LETTER U WITH HORN AND DOT BELOW */ + {0x1ef2, 2, 1411}, /* LATIN CAPITAL LETTER Y WITH GRAVE */ + {0x1ef3, 2, 1413}, /* LATIN SMALL LETTER Y WITH GRAVE */ + {0x1ef4, 2, 1415}, /* LATIN CAPITAL LETTER Y WITH DOT BELOW */ + {0x1ef5, 2, 1417}, /* LATIN SMALL LETTER Y WITH DOT BELOW */ + {0x1ef6, 2, 1419}, /* LATIN CAPITAL LETTER Y WITH HOOK ABOVE */ + {0x1ef7, 2, 1421}, /* LATIN SMALL LETTER Y WITH HOOK ABOVE */ + {0x1ef8, 2, 1423}, /* LATIN CAPITAL LETTER Y WITH TILDE */ + {0x1ef9, 2, 1425}, /* LATIN SMALL LETTER Y WITH TILDE */ + {0x1f00, 2, 1427}, /* GREEK SMALL LETTER ALPHA WITH PSILI */ + {0x1f01, 2, 1429}, /* GREEK SMALL LETTER ALPHA WITH DASIA */ + {0x1f02, 2, 1431}, /* GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA */ + {0x1f03, 2, 1433}, /* GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA */ + {0x1f04, 2, 1435}, /* GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA */ + {0x1f05, 2, 1437}, /* GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA */ + {0x1f06, 2, 1439}, /* GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI */ + {0x1f07, 2, 1441}, /* GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI */ + {0x1f08, 2, 1443}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI */ + {0x1f09, 2, 1445}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA */ + {0x1f0a, 2, 1447}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA */ + {0x1f0b, 2, 1449}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA */ + {0x1f0c, 2, 1451}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA */ + {0x1f0d, 2, 1453}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA */ + {0x1f0e, 2, 1455}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI */ + {0x1f0f, 2, 1457}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI */ + {0x1f10, 2, 1459}, /* GREEK SMALL LETTER EPSILON WITH PSILI */ + {0x1f11, 2, 1461}, /* GREEK SMALL LETTER EPSILON WITH DASIA */ + {0x1f12, 2, 1463}, /* GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA */ + {0x1f13, 2, 1465}, /* GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA */ + {0x1f14, 2, 1467}, /* GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA */ + {0x1f15, 2, 1469}, /* GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA */ + {0x1f18, 2, 1471}, /* GREEK CAPITAL LETTER EPSILON WITH PSILI */ + {0x1f19, 2, 1473}, /* GREEK CAPITAL LETTER EPSILON WITH DASIA */ + {0x1f1a, 2, 1475}, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA */ + {0x1f1b, 2, 1477}, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA */ + {0x1f1c, 2, 1479}, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA */ + {0x1f1d, 2, 1481}, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA */ + {0x1f20, 2, 1483}, /* GREEK SMALL LETTER ETA WITH PSILI */ + {0x1f21, 2, 1485}, /* GREEK SMALL LETTER ETA WITH DASIA */ + {0x1f22, 2, 1487}, /* GREEK SMALL LETTER ETA WITH PSILI AND VARIA */ + {0x1f23, 2, 1489}, /* GREEK SMALL LETTER ETA WITH DASIA AND VARIA */ + {0x1f24, 2, 1491}, /* GREEK SMALL LETTER ETA WITH PSILI AND OXIA */ + {0x1f25, 2, 1493}, /* GREEK SMALL LETTER ETA WITH DASIA AND OXIA */ + {0x1f26, 2, 1495}, /* GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI */ + {0x1f27, 2, 1497}, /* GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI */ + {0x1f28, 2, 1499}, /* GREEK CAPITAL LETTER ETA WITH PSILI */ + {0x1f29, 2, 1501}, /* GREEK CAPITAL LETTER ETA WITH DASIA */ + {0x1f2a, 2, 1503}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA */ + {0x1f2b, 2, 1505}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA */ + {0x1f2c, 2, 1507}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA */ + {0x1f2d, 2, 1509}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA */ + {0x1f2e, 2, 1511}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI */ + {0x1f2f, 2, 1513}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI */ + {0x1f30, 2, 1515}, /* GREEK SMALL LETTER IOTA WITH PSILI */ + {0x1f31, 2, 1517}, /* GREEK SMALL LETTER IOTA WITH DASIA */ + {0x1f32, 2, 1519}, /* GREEK SMALL LETTER IOTA WITH PSILI AND VARIA */ + {0x1f33, 2, 1521}, /* GREEK SMALL LETTER IOTA WITH DASIA AND VARIA */ + {0x1f34, 2, 1523}, /* GREEK SMALL LETTER IOTA WITH PSILI AND OXIA */ + {0x1f35, 2, 1525}, /* GREEK SMALL LETTER IOTA WITH DASIA AND OXIA */ + {0x1f36, 2, 1527}, /* GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI */ + {0x1f37, 2, 1529}, /* GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI */ + {0x1f38, 2, 1531}, /* GREEK CAPITAL LETTER IOTA WITH PSILI */ + {0x1f39, 2, 1533}, /* GREEK CAPITAL LETTER IOTA WITH DASIA */ + {0x1f3a, 2, 1535}, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA */ + {0x1f3b, 2, 1537}, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA */ + {0x1f3c, 2, 1539}, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA */ + {0x1f3d, 2, 1541}, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA */ + {0x1f3e, 2, 1543}, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI */ + {0x1f3f, 2, 1545}, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI */ + {0x1f40, 2, 1547}, /* GREEK SMALL LETTER OMICRON WITH PSILI */ + {0x1f41, 2, 1549}, /* GREEK SMALL LETTER OMICRON WITH DASIA */ + {0x1f42, 2, 1551}, /* GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA */ + {0x1f43, 2, 1553}, /* GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA */ + {0x1f44, 2, 1555}, /* GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA */ + {0x1f45, 2, 1557}, /* GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA */ + {0x1f48, 2, 1559}, /* GREEK CAPITAL LETTER OMICRON WITH PSILI */ + {0x1f49, 2, 1561}, /* GREEK CAPITAL LETTER OMICRON WITH DASIA */ + {0x1f4a, 2, 1563}, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA */ + {0x1f4b, 2, 1565}, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA */ + {0x1f4c, 2, 1567}, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA */ + {0x1f4d, 2, 1569}, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA */ + {0x1f50, 2, 1571}, /* GREEK SMALL LETTER UPSILON WITH PSILI */ + {0x1f51, 2, 1573}, /* GREEK SMALL LETTER UPSILON WITH DASIA */ + {0x1f52, 2, 1575}, /* GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA */ + {0x1f53, 2, 1577}, /* GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA */ + {0x1f54, 2, 1579}, /* GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA */ + {0x1f55, 2, 1581}, /* GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA */ + {0x1f56, 2, 1583}, /* GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI */ + {0x1f57, 2, 1585}, /* GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI */ + {0x1f59, 2, 1587}, /* GREEK CAPITAL LETTER UPSILON WITH DASIA */ + {0x1f5b, 2, 1589}, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA */ + {0x1f5d, 2, 1591}, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA */ + {0x1f5f, 2, 1593}, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI */ + {0x1f60, 2, 1595}, /* GREEK SMALL LETTER OMEGA WITH PSILI */ + {0x1f61, 2, 1597}, /* GREEK SMALL LETTER OMEGA WITH DASIA */ + {0x1f62, 2, 1599}, /* GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA */ + {0x1f63, 2, 1601}, /* GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA */ + {0x1f64, 2, 1603}, /* GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA */ + {0x1f65, 2, 1605}, /* GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA */ + {0x1f66, 2, 1607}, /* GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI */ + {0x1f67, 2, 1609}, /* GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI */ + {0x1f68, 2, 1611}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI */ + {0x1f69, 2, 1613}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA */ + {0x1f6a, 2, 1615}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA */ + {0x1f6b, 2, 1617}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA */ + {0x1f6c, 2, 1619}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA */ + {0x1f6d, 2, 1621}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA */ + {0x1f6e, 2, 1623}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI */ + {0x1f6f, 2, 1625}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI */ + {0x1f70, 2, 1627}, /* GREEK SMALL LETTER ALPHA WITH VARIA */ + {0x1f71, 1, 1629}, /* GREEK SMALL LETTER ALPHA WITH OXIA */ + {0x1f72, 2, 1630}, /* GREEK SMALL LETTER EPSILON WITH VARIA */ + {0x1f73, 1, 1632}, /* GREEK SMALL LETTER EPSILON WITH OXIA */ + {0x1f74, 2, 1633}, /* GREEK SMALL LETTER ETA WITH VARIA */ + {0x1f75, 1, 1635}, /* GREEK SMALL LETTER ETA WITH OXIA */ + {0x1f76, 2, 1636}, /* GREEK SMALL LETTER IOTA WITH VARIA */ + {0x1f77, 1, 1638}, /* GREEK SMALL LETTER IOTA WITH OXIA */ + {0x1f78, 2, 1639}, /* GREEK SMALL LETTER OMICRON WITH VARIA */ + {0x1f79, 1, 1641}, /* GREEK SMALL LETTER OMICRON WITH OXIA */ + {0x1f7a, 2, 1642}, /* GREEK SMALL LETTER UPSILON WITH VARIA */ + {0x1f7b, 1, 1644}, /* GREEK SMALL LETTER UPSILON WITH OXIA */ + {0x1f7c, 2, 1645}, /* GREEK SMALL LETTER OMEGA WITH VARIA */ + {0x1f7d, 1, 1647}, /* GREEK SMALL LETTER OMEGA WITH OXIA */ + {0x1f80, 2, 1648}, /* GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI */ + {0x1f81, 2, 1650}, /* GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI */ + {0x1f82, 2, 1652}, /* GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ + {0x1f83, 2, 1654}, /* GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ + {0x1f84, 2, 1656}, /* GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ + {0x1f85, 2, 1658}, /* GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ + {0x1f86, 2, 1660}, /* GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ + {0x1f87, 2, 1662}, /* GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ + {0x1f88, 2, 1664}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI */ + {0x1f89, 2, 1666}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI */ + {0x1f8a, 2, 1668}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + {0x1f8b, 2, 1670}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + {0x1f8c, 2, 1672}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + {0x1f8d, 2, 1674}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + {0x1f8e, 2, 1676}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1f8f, 2, 1678}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1f90, 2, 1680}, /* GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI */ + {0x1f91, 2, 1682}, /* GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI */ + {0x1f92, 2, 1684}, /* GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ + {0x1f93, 2, 1686}, /* GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ + {0x1f94, 2, 1688}, /* GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ + {0x1f95, 2, 1690}, /* GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ + {0x1f96, 2, 1692}, /* GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ + {0x1f97, 2, 1694}, /* GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ + {0x1f98, 2, 1696}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI */ + {0x1f99, 2, 1698}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI */ + {0x1f9a, 2, 1700}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + {0x1f9b, 2, 1702}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + {0x1f9c, 2, 1704}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + {0x1f9d, 2, 1706}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + {0x1f9e, 2, 1708}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1f9f, 2, 1710}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1fa0, 2, 1712}, /* GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI */ + {0x1fa1, 2, 1714}, /* GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI */ + {0x1fa2, 2, 1716}, /* GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ + {0x1fa3, 2, 1718}, /* GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ + {0x1fa4, 2, 1720}, /* GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ + {0x1fa5, 2, 1722}, /* GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ + {0x1fa6, 2, 1724}, /* GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ + {0x1fa7, 2, 1726}, /* GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ + {0x1fa8, 2, 1728}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI */ + {0x1fa9, 2, 1730}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI */ + {0x1faa, 2, 1732}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + {0x1fab, 2, 1734}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + {0x1fac, 2, 1736}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + {0x1fad, 2, 1738}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + {0x1fae, 2, 1740}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1faf, 2, 1742}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1fb0, 2, 1744}, /* GREEK SMALL LETTER ALPHA WITH VRACHY */ + {0x1fb1, 2, 1746}, /* GREEK SMALL LETTER ALPHA WITH MACRON */ + {0x1fb2, 2, 1748}, /* GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI */ + {0x1fb3, 2, 1750}, /* GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI */ + {0x1fb4, 2, 1752}, /* GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI */ + {0x1fb6, 2, 1754}, /* GREEK SMALL LETTER ALPHA WITH PERISPOMENI */ + {0x1fb7, 2, 1756}, /* GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI */ + {0x1fb8, 2, 1758}, /* GREEK CAPITAL LETTER ALPHA WITH VRACHY */ + {0x1fb9, 2, 1760}, /* GREEK CAPITAL LETTER ALPHA WITH MACRON */ + {0x1fba, 2, 1762}, /* GREEK CAPITAL LETTER ALPHA WITH VARIA */ + {0x1fbb, 1, 1764}, /* GREEK CAPITAL LETTER ALPHA WITH OXIA */ + {0x1fbc, 2, 1765}, /* GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI */ + {0x1fbd, 2, 1767}, /* GREEK KORONIS */ + {0x1fbe, 1, 616}, /* GREEK PROSGEGRAMMENI */ + {0x1fbf, 2, 1767}, /* GREEK PSILI */ + {0x1fc0, 2, 1769}, /* GREEK PERISPOMENI */ + {0x1fc1, 2, 1771}, /* GREEK DIALYTIKA AND PERISPOMENI */ + {0x1fc2, 2, 1773}, /* GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI */ + {0x1fc3, 2, 1775}, /* GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI */ + {0x1fc4, 2, 1777}, /* GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI */ + {0x1fc6, 2, 1779}, /* GREEK SMALL LETTER ETA WITH PERISPOMENI */ + {0x1fc7, 2, 1781}, /* GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI */ + {0x1fc8, 2, 1783}, /* GREEK CAPITAL LETTER EPSILON WITH VARIA */ + {0x1fc9, 1, 1785}, /* GREEK CAPITAL LETTER EPSILON WITH OXIA */ + {0x1fca, 2, 1786}, /* GREEK CAPITAL LETTER ETA WITH VARIA */ + {0x1fcb, 1, 1788}, /* GREEK CAPITAL LETTER ETA WITH OXIA */ + {0x1fcc, 2, 1789}, /* GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI */ + {0x1fcd, 2, 1791}, /* GREEK PSILI AND VARIA */ + {0x1fce, 2, 1793}, /* GREEK PSILI AND OXIA */ + {0x1fcf, 2, 1795}, /* GREEK PSILI AND PERISPOMENI */ + {0x1fd0, 2, 1797}, /* GREEK SMALL LETTER IOTA WITH VRACHY */ + {0x1fd1, 2, 1799}, /* GREEK SMALL LETTER IOTA WITH MACRON */ + {0x1fd2, 2, 1801}, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA */ + {0x1fd3, 1, 1803}, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA */ + {0x1fd6, 2, 1804}, /* GREEK SMALL LETTER IOTA WITH PERISPOMENI */ + {0x1fd7, 2, 1806}, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI */ + {0x1fd8, 2, 1808}, /* GREEK CAPITAL LETTER IOTA WITH VRACHY */ + {0x1fd9, 2, 1810}, /* GREEK CAPITAL LETTER IOTA WITH MACRON */ + {0x1fda, 2, 1812}, /* GREEK CAPITAL LETTER IOTA WITH VARIA */ + {0x1fdb, 1, 1814}, /* GREEK CAPITAL LETTER IOTA WITH OXIA */ + {0x1fdd, 2, 1815}, /* GREEK DASIA AND VARIA */ + {0x1fde, 2, 1817}, /* GREEK DASIA AND OXIA */ + {0x1fdf, 2, 1819}, /* GREEK DASIA AND PERISPOMENI */ + {0x1fe0, 2, 1821}, /* GREEK SMALL LETTER UPSILON WITH VRACHY */ + {0x1fe1, 2, 1823}, /* GREEK SMALL LETTER UPSILON WITH MACRON */ + {0x1fe2, 2, 1825}, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA */ + {0x1fe3, 1, 1827}, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA */ + {0x1fe4, 2, 1828}, /* GREEK SMALL LETTER RHO WITH PSILI */ + {0x1fe5, 2, 1830}, /* GREEK SMALL LETTER RHO WITH DASIA */ + {0x1fe6, 2, 1832}, /* GREEK SMALL LETTER UPSILON WITH PERISPOMENI */ + {0x1fe7, 2, 1834}, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI */ + {0x1fe8, 2, 1836}, /* GREEK CAPITAL LETTER UPSILON WITH VRACHY */ + {0x1fe9, 2, 1838}, /* GREEK CAPITAL LETTER UPSILON WITH MACRON */ + {0x1fea, 2, 1840}, /* GREEK CAPITAL LETTER UPSILON WITH VARIA */ + {0x1feb, 1, 1842}, /* GREEK CAPITAL LETTER UPSILON WITH OXIA */ + {0x1fec, 2, 1843}, /* GREEK CAPITAL LETTER RHO WITH DASIA */ + {0x1fed, 2, 1845}, /* GREEK DIALYTIKA AND VARIA */ + {0x1fee, 1, 1847}, /* GREEK DIALYTIKA AND OXIA */ + {0x1fef, 1, 1848}, /* GREEK VARIA */ + {0x1ff2, 2, 1849}, /* GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI */ + {0x1ff3, 2, 1851}, /* GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI */ + {0x1ff4, 2, 1853}, /* GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI */ + {0x1ff6, 2, 1855}, /* GREEK SMALL LETTER OMEGA WITH PERISPOMENI */ + {0x1ff7, 2, 1857}, /* GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI */ + {0x1ff8, 2, 1859}, /* GREEK CAPITAL LETTER OMICRON WITH VARIA */ + {0x1ff9, 1, 1861}, /* GREEK CAPITAL LETTER OMICRON WITH OXIA */ + {0x1ffa, 2, 1862}, /* GREEK CAPITAL LETTER OMEGA WITH VARIA */ + {0x1ffb, 1, 1864}, /* GREEK CAPITAL LETTER OMEGA WITH OXIA */ + {0x1ffc, 2, 1865}, /* GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI */ + {0x1ffd, 1, 1867}, /* GREEK OXIA */ + {0x1ffe, 2, 1868}, /* GREEK DASIA */ + {0x2000, 1, 1870}, /* EN QUAD */ + {0x2001, 1, 1871}, /* EM QUAD */ + {0x2002, 1, 1872}, /* EN SPACE */ + {0x2003, 1, 1873}, /* EM SPACE */ + {0x2004, 1, 1874}, /* THREE-PER-EM SPACE */ + {0x2005, 1, 1875}, /* FOUR-PER-EM SPACE */ + {0x2006, 1, 1876}, /* SIX-PER-EM SPACE */ + {0x2007, 1, 1877}, /* FIGURE SPACE */ + {0x2008, 1, 1878}, /* PUNCTUATION SPACE */ + {0x2009, 1, 1879}, /* THIN SPACE */ + {0x200a, 1, 1880}, /* HAIR SPACE */ + {0x2011, 1, 1881}, /* NON-BREAKING HYPHEN */ + {0x2017, 2, 1882}, /* DOUBLE LOW LINE */ + {0x2024, 1, 1884}, /* ONE DOT LEADER */ + {0x2025, 2, 1885}, /* TWO DOT LEADER */ + {0x2026, 3, 1884}, /* HORIZONTAL ELLIPSIS */ + {0x202f, 1, 1887}, /* NARROW NO-BREAK SPACE */ + {0x2033, 2, 1888}, /* DOUBLE PRIME */ + {0x2034, 3, 1890}, /* TRIPLE PRIME */ + {0x2036, 2, 1893}, /* REVERSED DOUBLE PRIME */ + {0x2037, 3, 1895}, /* REVERSED TRIPLE PRIME */ + {0x203c, 2, 1898}, /* DOUBLE EXCLAMATION MARK */ + {0x203e, 2, 1900}, /* OVERLINE */ + {0x2047, 2, 1902}, /* DOUBLE QUESTION MARK */ + {0x2048, 2, 1904}, /* QUESTION EXCLAMATION MARK */ + {0x2049, 2, 1906}, /* EXCLAMATION QUESTION MARK */ + {0x2057, 4, 1888}, /* QUADRUPLE PRIME */ + {0x205f, 1, 1908}, /* MEDIUM MATHEMATICAL SPACE */ + {0x2070, 1, 1909}, /* SUPERSCRIPT ZERO */ + {0x2071, 1, 98}, /* SUPERSCRIPT LATIN SMALL LETTER I */ + {0x2074, 1, 17}, /* SUPERSCRIPT FOUR */ + {0x2075, 1, 1910}, /* SUPERSCRIPT FIVE */ + {0x2076, 1, 1911}, /* SUPERSCRIPT SIX */ + {0x2077, 1, 1912}, /* SUPERSCRIPT SEVEN */ + {0x2078, 1, 1913}, /* SUPERSCRIPT EIGHT */ + {0x2079, 1, 1914}, /* SUPERSCRIPT NINE */ + {0x207a, 1, 1915}, /* SUPERSCRIPT PLUS SIGN */ + {0x207b, 1, 1916}, /* SUPERSCRIPT MINUS */ + {0x207c, 1, 1917}, /* SUPERSCRIPT EQUALS SIGN */ + {0x207d, 1, 1918}, /* SUPERSCRIPT LEFT PARENTHESIS */ + {0x207e, 1, 1919}, /* SUPERSCRIPT RIGHT PARENTHESIS */ + {0x207f, 1, 106}, /* SUPERSCRIPT LATIN SMALL LETTER N */ + {0x2080, 1, 1909}, /* SUBSCRIPT ZERO */ + {0x2081, 1, 13}, /* SUBSCRIPT ONE */ + {0x2082, 1, 6}, /* SUBSCRIPT TWO */ + {0x2083, 1, 7}, /* SUBSCRIPT THREE */ + {0x2084, 1, 17}, /* SUBSCRIPT FOUR */ + {0x2085, 1, 1910}, /* SUBSCRIPT FIVE */ + {0x2086, 1, 1911}, /* SUBSCRIPT SIX */ + {0x2087, 1, 1912}, /* SUBSCRIPT SEVEN */ + {0x2088, 1, 1913}, /* SUBSCRIPT EIGHT */ + {0x2089, 1, 1914}, /* SUBSCRIPT NINE */ + {0x208a, 1, 1915}, /* SUBSCRIPT PLUS SIGN */ + {0x208b, 1, 1916}, /* SUBSCRIPT MINUS */ + {0x208c, 1, 1917}, /* SUBSCRIPT EQUALS SIGN */ + {0x208d, 1, 1918}, /* SUBSCRIPT LEFT PARENTHESIS */ + {0x208e, 1, 1919}, /* SUBSCRIPT RIGHT PARENTHESIS */ + {0x20a8, 2, 1920}, /* RUPEE SIGN */ + {0x2100, 3, 1922}, /* ACCOUNT OF */ + {0x2101, 3, 1925}, /* ADDRESSED TO THE SUBJECT */ + {0x2102, 1, 36}, /* DOUBLE-STRUCK CAPITAL C */ + {0x2103, 2, 1928}, /* DEGREE CELSIUS */ + {0x2105, 3, 1930}, /* CARE OF */ + {0x2106, 3, 1933}, /* CADA UNA */ + {0x2107, 1, 1936}, /* EULER CONSTANT */ + {0x2109, 2, 1937}, /* DEGREE FAHRENHEIT */ + {0x210a, 1, 184}, /* SCRIPT SMALL G */ + {0x210b, 1, 198}, /* SCRIPT CAPITAL H */ + {0x210c, 1, 198}, /* BLACK-LETTER CAPITAL H */ + {0x210d, 1, 198}, /* DOUBLE-STRUCK CAPITAL H */ + {0x210e, 1, 200}, /* PLANCK CONSTANT */ + {0x210f, 1, 1939}, /* PLANCK CONSTANT OVER TWO PI */ + {0x2110, 1, 46}, /* SCRIPT CAPITAL I */ + {0x2111, 1, 46}, /* BLACK-LETTER CAPITAL I */ + {0x2112, 1, 232}, /* SCRIPT CAPITAL L */ + {0x2113, 1, 234}, /* SCRIPT SMALL L */ + {0x2115, 1, 54}, /* DOUBLE-STRUCK CAPITAL N */ + {0x2116, 2, 1940}, /* NUMERO SIGN */ + {0x2119, 1, 914}, /* DOUBLE-STRUCK CAPITAL P */ + {0x211a, 1, 1942}, /* DOUBLE-STRUCK CAPITAL Q */ + {0x211b, 1, 274}, /* SCRIPT CAPITAL R */ + {0x211c, 1, 274}, /* BLACK-LETTER CAPITAL R */ + {0x211d, 1, 274}, /* DOUBLE-STRUCK CAPITAL R */ + {0x2120, 2, 1943}, /* SERVICE MARK */ + {0x2121, 3, 1945}, /* TELEPHONE SIGN */ + {0x2122, 2, 1948}, /* TRADE MARK SIGN */ + {0x2124, 1, 344}, /* DOUBLE-STRUCK CAPITAL Z */ + {0x2126, 1, 602}, /* OHM SIGN */ + {0x2128, 1, 344}, /* BLACK-LETTER CAPITAL Z */ + {0x212a, 1, 228}, /* KELVIN SIGN */ + {0x212b, 1, 462}, /* ANGSTROM SIGN */ + {0x212c, 1, 910}, /* SCRIPT CAPITAL B */ + {0x212d, 1, 36}, /* BLACK-LETTER CAPITAL C */ + {0x212f, 1, 90}, /* SCRIPT SMALL E */ + {0x2130, 1, 38}, /* SCRIPT CAPITAL E */ + {0x2131, 1, 995}, /* SCRIPT CAPITAL F */ + {0x2133, 1, 912}, /* SCRIPT CAPITAL M */ + {0x2134, 1, 14}, /* SCRIPT SMALL O */ + {0x2135, 1, 1950}, /* ALEF SYMBOL */ + {0x2136, 1, 1951}, /* BET SYMBOL */ + {0x2137, 1, 1952}, /* GIMEL SYMBOL */ + {0x2138, 1, 1953}, /* DALET SYMBOL */ + {0x2139, 1, 98}, /* INFORMATION SOURCE */ + {0x213b, 3, 1954}, /* FACSIMILE SIGN */ + {0x213d, 1, 932}, /* DOUBLE-STRUCK SMALL GAMMA */ + {0x213e, 1, 1957}, /* DOUBLE-STRUCK CAPITAL GAMMA */ + {0x213f, 1, 1958}, /* DOUBLE-STRUCK CAPITAL PI */ + {0x2140, 1, 1959}, /* DOUBLE-STRUCK N-ARY SUMMATION */ + {0x2145, 1, 158}, /* DOUBLE-STRUCK ITALIC CAPITAL D */ + {0x2146, 1, 160}, /* DOUBLE-STRUCK ITALIC SMALL D */ + {0x2147, 1, 90}, /* DOUBLE-STRUCK ITALIC SMALL E */ + {0x2148, 1, 98}, /* DOUBLE-STRUCK ITALIC SMALL I */ + {0x2149, 1, 223}, /* DOUBLE-STRUCK ITALIC SMALL J */ + {0x2153, 3, 1960}, /* VULGAR FRACTION ONE THIRD */ + {0x2154, 3, 1963}, /* VULGAR FRACTION TWO THIRDS */ + {0x2155, 3, 1966}, /* VULGAR FRACTION ONE FIFTH */ + {0x2156, 3, 1969}, /* VULGAR FRACTION TWO FIFTHS */ + {0x2157, 3, 1972}, /* VULGAR FRACTION THREE FIFTHS */ + {0x2158, 3, 1975}, /* VULGAR FRACTION FOUR FIFTHS */ + {0x2159, 3, 1978}, /* VULGAR FRACTION ONE SIXTH */ + {0x215a, 3, 1981}, /* VULGAR FRACTION FIVE SIXTHS */ + {0x215b, 3, 1984}, /* VULGAR FRACTION ONE EIGHTH */ + {0x215c, 3, 1987}, /* VULGAR FRACTION THREE EIGHTHS */ + {0x215d, 3, 1990}, /* VULGAR FRACTION FIVE EIGHTHS */ + {0x215e, 3, 1993}, /* VULGAR FRACTION SEVEN EIGHTHS */ + {0x215f, 2, 15}, /* FRACTION NUMERATOR ONE */ + {0x2160, 1, 46}, /* ROMAN NUMERAL ONE */ + {0x2161, 2, 1996}, /* ROMAN NUMERAL TWO */ + {0x2162, 3, 1998}, /* ROMAN NUMERAL THREE */ + {0x2163, 2, 2001}, /* ROMAN NUMERAL FOUR */ + {0x2164, 1, 1183}, /* ROMAN NUMERAL FIVE */ + {0x2165, 2, 2003}, /* ROMAN NUMERAL SIX */ + {0x2166, 3, 2005}, /* ROMAN NUMERAL SEVEN */ + {0x2167, 4, 2008}, /* ROMAN NUMERAL EIGHT */ + {0x2168, 2, 2012}, /* ROMAN NUMERAL NINE */ + {0x2169, 1, 1211}, /* ROMAN NUMERAL TEN */ + {0x216a, 2, 2014}, /* ROMAN NUMERAL ELEVEN */ + {0x216b, 3, 2016}, /* ROMAN NUMERAL TWELVE */ + {0x216c, 1, 232}, /* ROMAN NUMERAL FIFTY */ + {0x216d, 1, 36}, /* ROMAN NUMERAL ONE HUNDRED */ + {0x216e, 1, 158}, /* ROMAN NUMERAL FIVE HUNDRED */ + {0x216f, 1, 912}, /* ROMAN NUMERAL ONE THOUSAND */ + {0x2170, 1, 98}, /* SMALL ROMAN NUMERAL ONE */ + {0x2171, 2, 2019}, /* SMALL ROMAN NUMERAL TWO */ + {0x2172, 3, 2021}, /* SMALL ROMAN NUMERAL THREE */ + {0x2173, 2, 2024}, /* SMALL ROMAN NUMERAL FOUR */ + {0x2174, 1, 930}, /* SMALL ROMAN NUMERAL FIVE */ + {0x2175, 2, 2026}, /* SMALL ROMAN NUMERAL SIX */ + {0x2176, 3, 2028}, /* SMALL ROMAN NUMERAL SEVEN */ + {0x2177, 4, 2031}, /* SMALL ROMAN NUMERAL EIGHT */ + {0x2178, 2, 2035}, /* SMALL ROMAN NUMERAL NINE */ + {0x2179, 1, 579}, /* SMALL ROMAN NUMERAL TEN */ + {0x217a, 2, 2037}, /* SMALL ROMAN NUMERAL ELEVEN */ + {0x217b, 3, 2039}, /* SMALL ROMAN NUMERAL TWELVE */ + {0x217c, 1, 234}, /* SMALL ROMAN NUMERAL FIFTY */ + {0x217d, 1, 88}, /* SMALL ROMAN NUMERAL ONE HUNDRED */ + {0x217e, 1, 160}, /* SMALL ROMAN NUMERAL FIVE HUNDRED */ + {0x217f, 1, 922}, /* SMALL ROMAN NUMERAL ONE THOUSAND */ + {0x219a, 2, 2042}, /* LEFTWARDS ARROW WITH STROKE */ + {0x219b, 2, 2044}, /* RIGHTWARDS ARROW WITH STROKE */ + {0x21ae, 2, 2046}, /* LEFT RIGHT ARROW WITH STROKE */ + {0x21cd, 2, 2048}, /* LEFTWARDS DOUBLE ARROW WITH STROKE */ + {0x21ce, 2, 2050}, /* LEFT RIGHT DOUBLE ARROW WITH STROKE */ + {0x21cf, 2, 2052}, /* RIGHTWARDS DOUBLE ARROW WITH STROKE */ + {0x2204, 2, 2054}, /* THERE DOES NOT EXIST */ + {0x2209, 2, 2056}, /* NOT AN ELEMENT OF */ + {0x220c, 2, 2058}, /* DOES NOT CONTAIN AS MEMBER */ + {0x2224, 2, 2060}, /* DOES NOT DIVIDE */ + {0x2226, 2, 2062}, /* NOT PARALLEL TO */ + {0x222c, 2, 2064}, /* DOUBLE INTEGRAL */ + {0x222d, 3, 2066}, /* TRIPLE INTEGRAL */ + {0x222f, 2, 2069}, /* SURFACE INTEGRAL */ + {0x2230, 3, 2071}, /* VOLUME INTEGRAL */ + {0x2241, 2, 2074}, /* NOT TILDE */ + {0x2244, 2, 2076}, /* NOT ASYMPTOTICALLY EQUAL TO */ + {0x2247, 2, 2078}, /* NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO */ + {0x2249, 2, 2080}, /* NOT ALMOST EQUAL TO */ + {0x2260, 2, 2082}, /* NOT EQUAL TO */ + {0x2262, 2, 2084}, /* NOT IDENTICAL TO */ + {0x226d, 2, 2086}, /* NOT EQUIVALENT TO */ + {0x226e, 2, 2088}, /* NOT LESS-THAN */ + {0x226f, 2, 2090}, /* NOT GREATER-THAN */ + {0x2270, 2, 2092}, /* NEITHER LESS-THAN NOR EQUAL TO */ + {0x2271, 2, 2094}, /* NEITHER GREATER-THAN NOR EQUAL TO */ + {0x2274, 2, 2096}, /* NEITHER LESS-THAN NOR EQUIVALENT TO */ + {0x2275, 2, 2098}, /* NEITHER GREATER-THAN NOR EQUIVALENT TO */ + {0x2278, 2, 2100}, /* NEITHER LESS-THAN NOR GREATER-THAN */ + {0x2279, 2, 2102}, /* NEITHER GREATER-THAN NOR LESS-THAN */ + {0x2280, 2, 2104}, /* DOES NOT PRECEDE */ + {0x2281, 2, 2106}, /* DOES NOT SUCCEED */ + {0x2284, 2, 2108}, /* NOT A SUBSET OF */ + {0x2285, 2, 2110}, /* NOT A SUPERSET OF */ + {0x2288, 2, 2112}, /* NEITHER A SUBSET OF NOR EQUAL TO */ + {0x2289, 2, 2114}, /* NEITHER A SUPERSET OF NOR EQUAL TO */ + {0x22ac, 2, 2116}, /* DOES NOT PROVE */ + {0x22ad, 2, 2118}, /* NOT TRUE */ + {0x22ae, 2, 2120}, /* DOES NOT FORCE */ + {0x22af, 2, 2122}, /* NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE */ + {0x22e0, 2, 2124}, /* DOES NOT PRECEDE OR EQUAL */ + {0x22e1, 2, 2126}, /* DOES NOT SUCCEED OR EQUAL */ + {0x22e2, 2, 2128}, /* NOT SQUARE IMAGE OF OR EQUAL TO */ + {0x22e3, 2, 2130}, /* NOT SQUARE ORIGINAL OF OR EQUAL TO */ + {0x22ea, 2, 2132}, /* NOT NORMAL SUBGROUP OF */ + {0x22eb, 2, 2134}, /* DOES NOT CONTAIN AS NORMAL SUBGROUP */ + {0x22ec, 2, 2136}, /* NOT NORMAL SUBGROUP OF OR EQUAL TO */ + {0x22ed, 2, 2138}, /* DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL */ + {0x2329, 1, 2140}, /* LEFT-POINTING ANGLE BRACKET */ + {0x232a, 1, 2141}, /* RIGHT-POINTING ANGLE BRACKET */ + {0x2460, 1, 13}, /* CIRCLED DIGIT ONE */ + {0x2461, 1, 6}, /* CIRCLED DIGIT TWO */ + {0x2462, 1, 7}, /* CIRCLED DIGIT THREE */ + {0x2463, 1, 17}, /* CIRCLED DIGIT FOUR */ + {0x2464, 1, 1910}, /* CIRCLED DIGIT FIVE */ + {0x2465, 1, 1911}, /* CIRCLED DIGIT SIX */ + {0x2466, 1, 1912}, /* CIRCLED DIGIT SEVEN */ + {0x2467, 1, 1913}, /* CIRCLED DIGIT EIGHT */ + {0x2468, 1, 1914}, /* CIRCLED DIGIT NINE */ + {0x2469, 2, 2142}, /* CIRCLED NUMBER TEN */ + {0x246a, 2, 2144}, /* CIRCLED NUMBER ELEVEN */ + {0x246b, 2, 2146}, /* CIRCLED NUMBER TWELVE */ + {0x246c, 2, 2148}, /* CIRCLED NUMBER THIRTEEN */ + {0x246d, 2, 2150}, /* CIRCLED NUMBER FOURTEEN */ + {0x246e, 2, 2152}, /* CIRCLED NUMBER FIFTEEN */ + {0x246f, 2, 2154}, /* CIRCLED NUMBER SIXTEEN */ + {0x2470, 2, 2156}, /* CIRCLED NUMBER SEVENTEEN */ + {0x2471, 2, 2158}, /* CIRCLED NUMBER EIGHTEEN */ + {0x2472, 2, 2160}, /* CIRCLED NUMBER NINETEEN */ + {0x2473, 2, 2162}, /* CIRCLED NUMBER TWENTY */ + {0x2474, 3, 2164}, /* PARENTHESIZED DIGIT ONE */ + {0x2475, 3, 2167}, /* PARENTHESIZED DIGIT TWO */ + {0x2476, 3, 2170}, /* PARENTHESIZED DIGIT THREE */ + {0x2477, 3, 2173}, /* PARENTHESIZED DIGIT FOUR */ + {0x2478, 3, 2176}, /* PARENTHESIZED DIGIT FIVE */ + {0x2479, 3, 2179}, /* PARENTHESIZED DIGIT SIX */ + {0x247a, 3, 2182}, /* PARENTHESIZED DIGIT SEVEN */ + {0x247b, 3, 2185}, /* PARENTHESIZED DIGIT EIGHT */ + {0x247c, 3, 2188}, /* PARENTHESIZED DIGIT NINE */ + {0x247d, 4, 2191}, /* PARENTHESIZED NUMBER TEN */ + {0x247e, 4, 2195}, /* PARENTHESIZED NUMBER ELEVEN */ + {0x247f, 4, 2199}, /* PARENTHESIZED NUMBER TWELVE */ + {0x2480, 4, 2203}, /* PARENTHESIZED NUMBER THIRTEEN */ + {0x2481, 4, 2207}, /* PARENTHESIZED NUMBER FOURTEEN */ + {0x2482, 4, 2211}, /* PARENTHESIZED NUMBER FIFTEEN */ + {0x2483, 4, 2215}, /* PARENTHESIZED NUMBER SIXTEEN */ + {0x2484, 4, 2219}, /* PARENTHESIZED NUMBER SEVENTEEN */ + {0x2485, 4, 2223}, /* PARENTHESIZED NUMBER EIGHTEEN */ + {0x2486, 4, 2227}, /* PARENTHESIZED NUMBER NINETEEN */ + {0x2487, 4, 2231}, /* PARENTHESIZED NUMBER TWENTY */ + {0x2488, 2, 2235}, /* DIGIT ONE FULL STOP */ + {0x2489, 2, 2237}, /* DIGIT TWO FULL STOP */ + {0x248a, 2, 2239}, /* DIGIT THREE FULL STOP */ + {0x248b, 2, 2241}, /* DIGIT FOUR FULL STOP */ + {0x248c, 2, 2243}, /* DIGIT FIVE FULL STOP */ + {0x248d, 2, 2245}, /* DIGIT SIX FULL STOP */ + {0x248e, 2, 2247}, /* DIGIT SEVEN FULL STOP */ + {0x248f, 2, 2249}, /* DIGIT EIGHT FULL STOP */ + {0x2490, 2, 2251}, /* DIGIT NINE FULL STOP */ + {0x2491, 3, 2253}, /* NUMBER TEN FULL STOP */ + {0x2492, 3, 2256}, /* NUMBER ELEVEN FULL STOP */ + {0x2493, 3, 2259}, /* NUMBER TWELVE FULL STOP */ + {0x2494, 3, 2262}, /* NUMBER THIRTEEN FULL STOP */ + {0x2495, 3, 2265}, /* NUMBER FOURTEEN FULL STOP */ + {0x2496, 3, 2268}, /* NUMBER FIFTEEN FULL STOP */ + {0x2497, 3, 2271}, /* NUMBER SIXTEEN FULL STOP */ + {0x2498, 3, 2274}, /* NUMBER SEVENTEEN FULL STOP */ + {0x2499, 3, 2277}, /* NUMBER EIGHTEEN FULL STOP */ + {0x249a, 3, 2280}, /* NUMBER NINETEEN FULL STOP */ + {0x249b, 3, 2283}, /* NUMBER TWENTY FULL STOP */ + {0x249c, 3, 2286}, /* PARENTHESIZED LATIN SMALL LETTER A */ + {0x249d, 3, 2289}, /* PARENTHESIZED LATIN SMALL LETTER B */ + {0x249e, 3, 2292}, /* PARENTHESIZED LATIN SMALL LETTER C */ + {0x249f, 3, 2295}, /* PARENTHESIZED LATIN SMALL LETTER D */ + {0x24a0, 3, 2298}, /* PARENTHESIZED LATIN SMALL LETTER E */ + {0x24a1, 3, 2301}, /* PARENTHESIZED LATIN SMALL LETTER F */ + {0x24a2, 3, 2304}, /* PARENTHESIZED LATIN SMALL LETTER G */ + {0x24a3, 3, 2307}, /* PARENTHESIZED LATIN SMALL LETTER H */ + {0x24a4, 3, 2310}, /* PARENTHESIZED LATIN SMALL LETTER I */ + {0x24a5, 3, 2313}, /* PARENTHESIZED LATIN SMALL LETTER J */ + {0x24a6, 3, 2316}, /* PARENTHESIZED LATIN SMALL LETTER K */ + {0x24a7, 3, 2319}, /* PARENTHESIZED LATIN SMALL LETTER L */ + {0x24a8, 3, 2322}, /* PARENTHESIZED LATIN SMALL LETTER M */ + {0x24a9, 3, 2325}, /* PARENTHESIZED LATIN SMALL LETTER N */ + {0x24aa, 3, 2328}, /* PARENTHESIZED LATIN SMALL LETTER O */ + {0x24ab, 3, 2331}, /* PARENTHESIZED LATIN SMALL LETTER P */ + {0x24ac, 3, 2334}, /* PARENTHESIZED LATIN SMALL LETTER Q */ + {0x24ad, 3, 2337}, /* PARENTHESIZED LATIN SMALL LETTER R */ + {0x24ae, 3, 2340}, /* PARENTHESIZED LATIN SMALL LETTER S */ + {0x24af, 3, 2343}, /* PARENTHESIZED LATIN SMALL LETTER T */ + {0x24b0, 3, 2346}, /* PARENTHESIZED LATIN SMALL LETTER U */ + {0x24b1, 3, 2349}, /* PARENTHESIZED LATIN SMALL LETTER V */ + {0x24b2, 3, 2352}, /* PARENTHESIZED LATIN SMALL LETTER W */ + {0x24b3, 3, 2355}, /* PARENTHESIZED LATIN SMALL LETTER X */ + {0x24b4, 3, 2358}, /* PARENTHESIZED LATIN SMALL LETTER Y */ + {0x24b5, 3, 2361}, /* PARENTHESIZED LATIN SMALL LETTER Z */ + {0x24b6, 1, 24}, /* CIRCLED LATIN CAPITAL LETTER A */ + {0x24b7, 1, 910}, /* CIRCLED LATIN CAPITAL LETTER B */ + {0x24b8, 1, 36}, /* CIRCLED LATIN CAPITAL LETTER C */ + {0x24b9, 1, 158}, /* CIRCLED LATIN CAPITAL LETTER D */ + {0x24ba, 1, 38}, /* CIRCLED LATIN CAPITAL LETTER E */ + {0x24bb, 1, 995}, /* CIRCLED LATIN CAPITAL LETTER F */ + {0x24bc, 1, 182}, /* CIRCLED LATIN CAPITAL LETTER G */ + {0x24bd, 1, 198}, /* CIRCLED LATIN CAPITAL LETTER H */ + {0x24be, 1, 46}, /* CIRCLED LATIN CAPITAL LETTER I */ + {0x24bf, 1, 221}, /* CIRCLED LATIN CAPITAL LETTER J */ + {0x24c0, 1, 228}, /* CIRCLED LATIN CAPITAL LETTER K */ + {0x24c1, 1, 232}, /* CIRCLED LATIN CAPITAL LETTER L */ + {0x24c2, 1, 912}, /* CIRCLED LATIN CAPITAL LETTER M */ + {0x24c3, 1, 54}, /* CIRCLED LATIN CAPITAL LETTER N */ + {0x24c4, 1, 56}, /* CIRCLED LATIN CAPITAL LETTER O */ + {0x24c5, 1, 914}, /* CIRCLED LATIN CAPITAL LETTER P */ + {0x24c6, 1, 1942}, /* CIRCLED LATIN CAPITAL LETTER Q */ + {0x24c7, 1, 274}, /* CIRCLED LATIN CAPITAL LETTER R */ + {0x24c8, 1, 286}, /* CIRCLED LATIN CAPITAL LETTER S */ + {0x24c9, 1, 302}, /* CIRCLED LATIN CAPITAL LETTER T */ + {0x24ca, 1, 66}, /* CIRCLED LATIN CAPITAL LETTER U */ + {0x24cb, 1, 1183}, /* CIRCLED LATIN CAPITAL LETTER V */ + {0x24cc, 1, 334}, /* CIRCLED LATIN CAPITAL LETTER W */ + {0x24cd, 1, 1211}, /* CIRCLED LATIN CAPITAL LETTER X */ + {0x24ce, 1, 74}, /* CIRCLED LATIN CAPITAL LETTER Y */ + {0x24cf, 1, 344}, /* CIRCLED LATIN CAPITAL LETTER Z */ + {0x24d0, 1, 3}, /* CIRCLED LATIN SMALL LETTER A */ + {0x24d1, 1, 918}, /* CIRCLED LATIN SMALL LETTER B */ + {0x24d2, 1, 88}, /* CIRCLED LATIN SMALL LETTER C */ + {0x24d3, 1, 160}, /* CIRCLED LATIN SMALL LETTER D */ + {0x24d4, 1, 90}, /* CIRCLED LATIN SMALL LETTER E */ + {0x24d5, 1, 997}, /* CIRCLED LATIN SMALL LETTER F */ + {0x24d6, 1, 184}, /* CIRCLED LATIN SMALL LETTER G */ + {0x24d7, 1, 200}, /* CIRCLED LATIN SMALL LETTER H */ + {0x24d8, 1, 98}, /* CIRCLED LATIN SMALL LETTER I */ + {0x24d9, 1, 223}, /* CIRCLED LATIN SMALL LETTER J */ + {0x24da, 1, 230}, /* CIRCLED LATIN SMALL LETTER K */ + {0x24db, 1, 234}, /* CIRCLED LATIN SMALL LETTER L */ + {0x24dc, 1, 922}, /* CIRCLED LATIN SMALL LETTER M */ + {0x24dd, 1, 106}, /* CIRCLED LATIN SMALL LETTER N */ + {0x24de, 1, 14}, /* CIRCLED LATIN SMALL LETTER O */ + {0x24df, 1, 927}, /* CIRCLED LATIN SMALL LETTER P */ + {0x24e0, 1, 2335}, /* CIRCLED LATIN SMALL LETTER Q */ + {0x24e1, 1, 276}, /* CIRCLED LATIN SMALL LETTER R */ + {0x24e2, 1, 288}, /* CIRCLED LATIN SMALL LETTER S */ + {0x24e3, 1, 304}, /* CIRCLED LATIN SMALL LETTER T */ + {0x24e4, 1, 118}, /* CIRCLED LATIN SMALL LETTER U */ + {0x24e5, 1, 930}, /* CIRCLED LATIN SMALL LETTER V */ + {0x24e6, 1, 336}, /* CIRCLED LATIN SMALL LETTER W */ + {0x24e7, 1, 579}, /* CIRCLED LATIN SMALL LETTER X */ + {0x24e8, 1, 126}, /* CIRCLED LATIN SMALL LETTER Y */ + {0x24e9, 1, 346}, /* CIRCLED LATIN SMALL LETTER Z */ + {0x24ea, 1, 1909}, /* CIRCLED DIGIT ZERO */ + {0x2a0c, 4, 2064}, /* QUADRUPLE INTEGRAL OPERATOR */ + {0x2a74, 3, 2364}, /* DOUBLE COLON EQUAL */ + {0x2a75, 2, 2367}, /* TWO CONSECUTIVE EQUALS SIGNS */ + {0x2a76, 3, 2366}, /* THREE CONSECUTIVE EQUALS SIGNS */ + {0x2adc, 2, 2369}, /* FORKING */ + {0x2e9f, 1, 2371}, /* CJK RADICAL MOTHER */ + {0x2ef3, 1, 2372}, /* CJK RADICAL C-SIMPLIFIED TURTLE */ + {0x2f00, 1, 2373}, /* KANGXI RADICAL ONE */ + {0x2f01, 1, 2374}, /* KANGXI RADICAL LINE */ + {0x2f02, 1, 2375}, /* KANGXI RADICAL DOT */ + {0x2f03, 1, 2376}, /* KANGXI RADICAL SLASH */ + {0x2f04, 1, 2377}, /* KANGXI RADICAL SECOND */ + {0x2f05, 1, 2378}, /* KANGXI RADICAL HOOK */ + {0x2f06, 1, 2379}, /* KANGXI RADICAL TWO */ + {0x2f07, 1, 2380}, /* KANGXI RADICAL LID */ + {0x2f08, 1, 2381}, /* KANGXI RADICAL MAN */ + {0x2f09, 1, 2382}, /* KANGXI RADICAL LEGS */ + {0x2f0a, 1, 2383}, /* KANGXI RADICAL ENTER */ + {0x2f0b, 1, 2384}, /* KANGXI RADICAL EIGHT */ + {0x2f0c, 1, 2385}, /* KANGXI RADICAL DOWN BOX */ + {0x2f0d, 1, 2386}, /* KANGXI RADICAL COVER */ + {0x2f0e, 1, 2387}, /* KANGXI RADICAL ICE */ + {0x2f0f, 1, 2388}, /* KANGXI RADICAL TABLE */ + {0x2f10, 1, 2389}, /* KANGXI RADICAL OPEN BOX */ + {0x2f11, 1, 2390}, /* KANGXI RADICAL KNIFE */ + {0x2f12, 1, 2391}, /* KANGXI RADICAL POWER */ + {0x2f13, 1, 2392}, /* KANGXI RADICAL WRAP */ + {0x2f14, 1, 2393}, /* KANGXI RADICAL SPOON */ + {0x2f15, 1, 2394}, /* KANGXI RADICAL RIGHT OPEN BOX */ + {0x2f16, 1, 2395}, /* KANGXI RADICAL HIDING ENCLOSURE */ + {0x2f17, 1, 2396}, /* KANGXI RADICAL TEN */ + {0x2f18, 1, 2397}, /* KANGXI RADICAL DIVINATION */ + {0x2f19, 1, 2398}, /* KANGXI RADICAL SEAL */ + {0x2f1a, 1, 2399}, /* KANGXI RADICAL CLIFF */ + {0x2f1b, 1, 2400}, /* KANGXI RADICAL PRIVATE */ + {0x2f1c, 1, 2401}, /* KANGXI RADICAL AGAIN */ + {0x2f1d, 1, 2402}, /* KANGXI RADICAL MOUTH */ + {0x2f1e, 1, 2403}, /* KANGXI RADICAL ENCLOSURE */ + {0x2f1f, 1, 2404}, /* KANGXI RADICAL EARTH */ + {0x2f20, 1, 2405}, /* KANGXI RADICAL SCHOLAR */ + {0x2f21, 1, 2406}, /* KANGXI RADICAL GO */ + {0x2f22, 1, 2407}, /* KANGXI RADICAL GO SLOWLY */ + {0x2f23, 1, 2408}, /* KANGXI RADICAL EVENING */ + {0x2f24, 1, 2409}, /* KANGXI RADICAL BIG */ + {0x2f25, 1, 2410}, /* KANGXI RADICAL WOMAN */ + {0x2f26, 1, 2411}, /* KANGXI RADICAL CHILD */ + {0x2f27, 1, 2412}, /* KANGXI RADICAL ROOF */ + {0x2f28, 1, 2413}, /* KANGXI RADICAL INCH */ + {0x2f29, 1, 2414}, /* KANGXI RADICAL SMALL */ + {0x2f2a, 1, 2415}, /* KANGXI RADICAL LAME */ + {0x2f2b, 1, 2416}, /* KANGXI RADICAL CORPSE */ + {0x2f2c, 1, 2417}, /* KANGXI RADICAL SPROUT */ + {0x2f2d, 1, 2418}, /* KANGXI RADICAL MOUNTAIN */ + {0x2f2e, 1, 2419}, /* KANGXI RADICAL RIVER */ + {0x2f2f, 1, 2420}, /* KANGXI RADICAL WORK */ + {0x2f30, 1, 2421}, /* KANGXI RADICAL ONESELF */ + {0x2f31, 1, 2422}, /* KANGXI RADICAL TURBAN */ + {0x2f32, 1, 2423}, /* KANGXI RADICAL DRY */ + {0x2f33, 1, 2424}, /* KANGXI RADICAL SHORT THREAD */ + {0x2f34, 1, 2425}, /* KANGXI RADICAL DOTTED CLIFF */ + {0x2f35, 1, 2426}, /* KANGXI RADICAL LONG STRIDE */ + {0x2f36, 1, 2427}, /* KANGXI RADICAL TWO HANDS */ + {0x2f37, 1, 2428}, /* KANGXI RADICAL SHOOT */ + {0x2f38, 1, 2429}, /* KANGXI RADICAL BOW */ + {0x2f39, 1, 2430}, /* KANGXI RADICAL SNOUT */ + {0x2f3a, 1, 2431}, /* KANGXI RADICAL BRISTLE */ + {0x2f3b, 1, 2432}, /* KANGXI RADICAL STEP */ + {0x2f3c, 1, 2433}, /* KANGXI RADICAL HEART */ + {0x2f3d, 1, 2434}, /* KANGXI RADICAL HALBERD */ + {0x2f3e, 1, 2435}, /* KANGXI RADICAL DOOR */ + {0x2f3f, 1, 2436}, /* KANGXI RADICAL HAND */ + {0x2f40, 1, 2437}, /* KANGXI RADICAL BRANCH */ + {0x2f41, 1, 2438}, /* KANGXI RADICAL RAP */ + {0x2f42, 1, 2439}, /* KANGXI RADICAL SCRIPT */ + {0x2f43, 1, 2440}, /* KANGXI RADICAL DIPPER */ + {0x2f44, 1, 2441}, /* KANGXI RADICAL AXE */ + {0x2f45, 1, 2442}, /* KANGXI RADICAL SQUARE */ + {0x2f46, 1, 2443}, /* KANGXI RADICAL NOT */ + {0x2f47, 1, 2444}, /* KANGXI RADICAL SUN */ + {0x2f48, 1, 2445}, /* KANGXI RADICAL SAY */ + {0x2f49, 1, 2446}, /* KANGXI RADICAL MOON */ + {0x2f4a, 1, 2447}, /* KANGXI RADICAL TREE */ + {0x2f4b, 1, 2448}, /* KANGXI RADICAL LACK */ + {0x2f4c, 1, 2449}, /* KANGXI RADICAL STOP */ + {0x2f4d, 1, 2450}, /* KANGXI RADICAL DEATH */ + {0x2f4e, 1, 2451}, /* KANGXI RADICAL WEAPON */ + {0x2f4f, 1, 2452}, /* KANGXI RADICAL DO NOT */ + {0x2f50, 1, 2453}, /* KANGXI RADICAL COMPARE */ + {0x2f51, 1, 2454}, /* KANGXI RADICAL FUR */ + {0x2f52, 1, 2455}, /* KANGXI RADICAL CLAN */ + {0x2f53, 1, 2456}, /* KANGXI RADICAL STEAM */ + {0x2f54, 1, 2457}, /* KANGXI RADICAL WATER */ + {0x2f55, 1, 2458}, /* KANGXI RADICAL FIRE */ + {0x2f56, 1, 2459}, /* KANGXI RADICAL CLAW */ + {0x2f57, 1, 2460}, /* KANGXI RADICAL FATHER */ + {0x2f58, 1, 2461}, /* KANGXI RADICAL DOUBLE X */ + {0x2f59, 1, 2462}, /* KANGXI RADICAL HALF TREE TRUNK */ + {0x2f5a, 1, 2463}, /* KANGXI RADICAL SLICE */ + {0x2f5b, 1, 2464}, /* KANGXI RADICAL FANG */ + {0x2f5c, 1, 2465}, /* KANGXI RADICAL COW */ + {0x2f5d, 1, 2466}, /* KANGXI RADICAL DOG */ + {0x2f5e, 1, 2467}, /* KANGXI RADICAL PROFOUND */ + {0x2f5f, 1, 2468}, /* KANGXI RADICAL JADE */ + {0x2f60, 1, 2469}, /* KANGXI RADICAL MELON */ + {0x2f61, 1, 2470}, /* KANGXI RADICAL TILE */ + {0x2f62, 1, 2471}, /* KANGXI RADICAL SWEET */ + {0x2f63, 1, 2472}, /* KANGXI RADICAL LIFE */ + {0x2f64, 1, 2473}, /* KANGXI RADICAL USE */ + {0x2f65, 1, 2474}, /* KANGXI RADICAL FIELD */ + {0x2f66, 1, 2475}, /* KANGXI RADICAL BOLT OF CLOTH */ + {0x2f67, 1, 2476}, /* KANGXI RADICAL SICKNESS */ + {0x2f68, 1, 2477}, /* KANGXI RADICAL DOTTED TENT */ + {0x2f69, 1, 2478}, /* KANGXI RADICAL WHITE */ + {0x2f6a, 1, 2479}, /* KANGXI RADICAL SKIN */ + {0x2f6b, 1, 2480}, /* KANGXI RADICAL DISH */ + {0x2f6c, 1, 2481}, /* KANGXI RADICAL EYE */ + {0x2f6d, 1, 2482}, /* KANGXI RADICAL SPEAR */ + {0x2f6e, 1, 2483}, /* KANGXI RADICAL ARROW */ + {0x2f6f, 1, 2484}, /* KANGXI RADICAL STONE */ + {0x2f70, 1, 2485}, /* KANGXI RADICAL SPIRIT */ + {0x2f71, 1, 2486}, /* KANGXI RADICAL TRACK */ + {0x2f72, 1, 2487}, /* KANGXI RADICAL GRAIN */ + {0x2f73, 1, 2488}, /* KANGXI RADICAL CAVE */ + {0x2f74, 1, 2489}, /* KANGXI RADICAL STAND */ + {0x2f75, 1, 2490}, /* KANGXI RADICAL BAMBOO */ + {0x2f76, 1, 2491}, /* KANGXI RADICAL RICE */ + {0x2f77, 1, 2492}, /* KANGXI RADICAL SILK */ + {0x2f78, 1, 2493}, /* KANGXI RADICAL JAR */ + {0x2f79, 1, 2494}, /* KANGXI RADICAL NET */ + {0x2f7a, 1, 2495}, /* KANGXI RADICAL SHEEP */ + {0x2f7b, 1, 2496}, /* KANGXI RADICAL FEATHER */ + {0x2f7c, 1, 2497}, /* KANGXI RADICAL OLD */ + {0x2f7d, 1, 2498}, /* KANGXI RADICAL AND */ + {0x2f7e, 1, 2499}, /* KANGXI RADICAL PLOW */ + {0x2f7f, 1, 2500}, /* KANGXI RADICAL EAR */ + {0x2f80, 1, 2501}, /* KANGXI RADICAL BRUSH */ + {0x2f81, 1, 2502}, /* KANGXI RADICAL MEAT */ + {0x2f82, 1, 2503}, /* KANGXI RADICAL MINISTER */ + {0x2f83, 1, 2504}, /* KANGXI RADICAL SELF */ + {0x2f84, 1, 2505}, /* KANGXI RADICAL ARRIVE */ + {0x2f85, 1, 2506}, /* KANGXI RADICAL MORTAR */ + {0x2f86, 1, 2507}, /* KANGXI RADICAL TONGUE */ + {0x2f87, 1, 2508}, /* KANGXI RADICAL OPPOSE */ + {0x2f88, 1, 2509}, /* KANGXI RADICAL BOAT */ + {0x2f89, 1, 2510}, /* KANGXI RADICAL STOPPING */ + {0x2f8a, 1, 2511}, /* KANGXI RADICAL COLOR */ + {0x2f8b, 1, 2512}, /* KANGXI RADICAL GRASS */ + {0x2f8c, 1, 2513}, /* KANGXI RADICAL TIGER */ + {0x2f8d, 1, 2514}, /* KANGXI RADICAL INSECT */ + {0x2f8e, 1, 2515}, /* KANGXI RADICAL BLOOD */ + {0x2f8f, 1, 2516}, /* KANGXI RADICAL WALK ENCLOSURE */ + {0x2f90, 1, 2517}, /* KANGXI RADICAL CLOTHES */ + {0x2f91, 1, 2518}, /* KANGXI RADICAL WEST */ + {0x2f92, 1, 2519}, /* KANGXI RADICAL SEE */ + {0x2f93, 1, 2520}, /* KANGXI RADICAL HORN */ + {0x2f94, 1, 2521}, /* KANGXI RADICAL SPEECH */ + {0x2f95, 1, 2522}, /* KANGXI RADICAL VALLEY */ + {0x2f96, 1, 2523}, /* KANGXI RADICAL BEAN */ + {0x2f97, 1, 2524}, /* KANGXI RADICAL PIG */ + {0x2f98, 1, 2525}, /* KANGXI RADICAL BADGER */ + {0x2f99, 1, 2526}, /* KANGXI RADICAL SHELL */ + {0x2f9a, 1, 2527}, /* KANGXI RADICAL RED */ + {0x2f9b, 1, 2528}, /* KANGXI RADICAL RUN */ + {0x2f9c, 1, 2529}, /* KANGXI RADICAL FOOT */ + {0x2f9d, 1, 2530}, /* KANGXI RADICAL BODY */ + {0x2f9e, 1, 2531}, /* KANGXI RADICAL CART */ + {0x2f9f, 1, 2532}, /* KANGXI RADICAL BITTER */ + {0x2fa0, 1, 2533}, /* KANGXI RADICAL MORNING */ + {0x2fa1, 1, 2534}, /* KANGXI RADICAL WALK */ + {0x2fa2, 1, 2535}, /* KANGXI RADICAL CITY */ + {0x2fa3, 1, 2536}, /* KANGXI RADICAL WINE */ + {0x2fa4, 1, 2537}, /* KANGXI RADICAL DISTINGUISH */ + {0x2fa5, 1, 2538}, /* KANGXI RADICAL VILLAGE */ + {0x2fa6, 1, 2539}, /* KANGXI RADICAL GOLD */ + {0x2fa7, 1, 2540}, /* KANGXI RADICAL LONG */ + {0x2fa8, 1, 2541}, /* KANGXI RADICAL GATE */ + {0x2fa9, 1, 2542}, /* KANGXI RADICAL MOUND */ + {0x2faa, 1, 2543}, /* KANGXI RADICAL SLAVE */ + {0x2fab, 1, 2544}, /* KANGXI RADICAL SHORT TAILED BIRD */ + {0x2fac, 1, 2545}, /* KANGXI RADICAL RAIN */ + {0x2fad, 1, 2546}, /* KANGXI RADICAL BLUE */ + {0x2fae, 1, 2547}, /* KANGXI RADICAL WRONG */ + {0x2faf, 1, 2548}, /* KANGXI RADICAL FACE */ + {0x2fb0, 1, 2549}, /* KANGXI RADICAL LEATHER */ + {0x2fb1, 1, 2550}, /* KANGXI RADICAL TANNED LEATHER */ + {0x2fb2, 1, 2551}, /* KANGXI RADICAL LEEK */ + {0x2fb3, 1, 2552}, /* KANGXI RADICAL SOUND */ + {0x2fb4, 1, 2553}, /* KANGXI RADICAL LEAF */ + {0x2fb5, 1, 2554}, /* KANGXI RADICAL WIND */ + {0x2fb6, 1, 2555}, /* KANGXI RADICAL FLY */ + {0x2fb7, 1, 2556}, /* KANGXI RADICAL EAT */ + {0x2fb8, 1, 2557}, /* KANGXI RADICAL HEAD */ + {0x2fb9, 1, 2558}, /* KANGXI RADICAL FRAGRANT */ + {0x2fba, 1, 2559}, /* KANGXI RADICAL HORSE */ + {0x2fbb, 1, 2560}, /* KANGXI RADICAL BONE */ + {0x2fbc, 1, 2561}, /* KANGXI RADICAL TALL */ + {0x2fbd, 1, 2562}, /* KANGXI RADICAL HAIR */ + {0x2fbe, 1, 2563}, /* KANGXI RADICAL FIGHT */ + {0x2fbf, 1, 2564}, /* KANGXI RADICAL SACRIFICIAL WINE */ + {0x2fc0, 1, 2565}, /* KANGXI RADICAL CAULDRON */ + {0x2fc1, 1, 2566}, /* KANGXI RADICAL GHOST */ + {0x2fc2, 1, 2567}, /* KANGXI RADICAL FISH */ + {0x2fc3, 1, 2568}, /* KANGXI RADICAL BIRD */ + {0x2fc4, 1, 2569}, /* KANGXI RADICAL SALT */ + {0x2fc5, 1, 2570}, /* KANGXI RADICAL DEER */ + {0x2fc6, 1, 2571}, /* KANGXI RADICAL WHEAT */ + {0x2fc7, 1, 2572}, /* KANGXI RADICAL HEMP */ + {0x2fc8, 1, 2573}, /* KANGXI RADICAL YELLOW */ + {0x2fc9, 1, 2574}, /* KANGXI RADICAL MILLET */ + {0x2fca, 1, 2575}, /* KANGXI RADICAL BLACK */ + {0x2fcb, 1, 2576}, /* KANGXI RADICAL EMBROIDERY */ + {0x2fcc, 1, 2577}, /* KANGXI RADICAL FROG */ + {0x2fcd, 1, 2578}, /* KANGXI RADICAL TRIPOD */ + {0x2fce, 1, 2579}, /* KANGXI RADICAL DRUM */ + {0x2fcf, 1, 2580}, /* KANGXI RADICAL RAT */ + {0x2fd0, 1, 2581}, /* KANGXI RADICAL NOSE */ + {0x2fd1, 1, 2582}, /* KANGXI RADICAL EVEN */ + {0x2fd2, 1, 2583}, /* KANGXI RADICAL TOOTH */ + {0x2fd3, 1, 2584}, /* KANGXI RADICAL DRAGON */ + {0x2fd4, 1, 2585}, /* KANGXI RADICAL TURTLE */ + {0x2fd5, 1, 2586}, /* KANGXI RADICAL FLUTE */ + {0x3000, 1, 2587}, /* IDEOGRAPHIC SPACE */ + {0x3036, 1, 2588}, /* CIRCLED POSTAL MARK */ + {0x3038, 1, 2396}, /* HANGZHOU NUMERAL TEN */ + {0x3039, 1, 2589}, /* HANGZHOU NUMERAL TWENTY */ + {0x303a, 1, 2590}, /* HANGZHOU NUMERAL THIRTY */ + {0x304c, 2, 2591}, /* HIRAGANA LETTER GA */ + {0x304e, 2, 2593}, /* HIRAGANA LETTER GI */ + {0x3050, 2, 2595}, /* HIRAGANA LETTER GU */ + {0x3052, 2, 2597}, /* HIRAGANA LETTER GE */ + {0x3054, 2, 2599}, /* HIRAGANA LETTER GO */ + {0x3056, 2, 2601}, /* HIRAGANA LETTER ZA */ + {0x3058, 2, 2603}, /* HIRAGANA LETTER ZI */ + {0x305a, 2, 2605}, /* HIRAGANA LETTER ZU */ + {0x305c, 2, 2607}, /* HIRAGANA LETTER ZE */ + {0x305e, 2, 2609}, /* HIRAGANA LETTER ZO */ + {0x3060, 2, 2611}, /* HIRAGANA LETTER DA */ + {0x3062, 2, 2613}, /* HIRAGANA LETTER DI */ + {0x3065, 2, 2615}, /* HIRAGANA LETTER DU */ + {0x3067, 2, 2617}, /* HIRAGANA LETTER DE */ + {0x3069, 2, 2619}, /* HIRAGANA LETTER DO */ + {0x3070, 2, 2621}, /* HIRAGANA LETTER BA */ + {0x3071, 2, 2623}, /* HIRAGANA LETTER PA */ + {0x3073, 2, 2625}, /* HIRAGANA LETTER BI */ + {0x3074, 2, 2627}, /* HIRAGANA LETTER PI */ + {0x3076, 2, 2629}, /* HIRAGANA LETTER BU */ + {0x3077, 2, 2631}, /* HIRAGANA LETTER PU */ + {0x3079, 2, 2633}, /* HIRAGANA LETTER BE */ + {0x307a, 2, 2635}, /* HIRAGANA LETTER PE */ + {0x307c, 2, 2637}, /* HIRAGANA LETTER BO */ + {0x307d, 2, 2639}, /* HIRAGANA LETTER PO */ + {0x3094, 2, 2641}, /* HIRAGANA LETTER VU */ + {0x309b, 2, 2643}, /* KATAKANA-HIRAGANA VOICED SOUND MARK */ + {0x309c, 2, 2645}, /* KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ + {0x309e, 2, 2647}, /* HIRAGANA VOICED ITERATION MARK */ + {0x309f, 2, 2649}, /* HIRAGANA DIGRAPH YORI */ + {0x30ac, 2, 2651}, /* KATAKANA LETTER GA */ + {0x30ae, 2, 2653}, /* KATAKANA LETTER GI */ + {0x30b0, 2, 2655}, /* KATAKANA LETTER GU */ + {0x30b2, 2, 2657}, /* KATAKANA LETTER GE */ + {0x30b4, 2, 2659}, /* KATAKANA LETTER GO */ + {0x30b6, 2, 2661}, /* KATAKANA LETTER ZA */ + {0x30b8, 2, 2663}, /* KATAKANA LETTER ZI */ + {0x30ba, 2, 2665}, /* KATAKANA LETTER ZU */ + {0x30bc, 2, 2667}, /* KATAKANA LETTER ZE */ + {0x30be, 2, 2669}, /* KATAKANA LETTER ZO */ + {0x30c0, 2, 2671}, /* KATAKANA LETTER DA */ + {0x30c2, 2, 2673}, /* KATAKANA LETTER DI */ + {0x30c5, 2, 2675}, /* KATAKANA LETTER DU */ + {0x30c7, 2, 2677}, /* KATAKANA LETTER DE */ + {0x30c9, 2, 2679}, /* KATAKANA LETTER DO */ + {0x30d0, 2, 2681}, /* KATAKANA LETTER BA */ + {0x30d1, 2, 2683}, /* KATAKANA LETTER PA */ + {0x30d3, 2, 2685}, /* KATAKANA LETTER BI */ + {0x30d4, 2, 2687}, /* KATAKANA LETTER PI */ + {0x30d6, 2, 2689}, /* KATAKANA LETTER BU */ + {0x30d7, 2, 2691}, /* KATAKANA LETTER PU */ + {0x30d9, 2, 2693}, /* KATAKANA LETTER BE */ + {0x30da, 2, 2695}, /* KATAKANA LETTER PE */ + {0x30dc, 2, 2697}, /* KATAKANA LETTER BO */ + {0x30dd, 2, 2699}, /* KATAKANA LETTER PO */ + {0x30f4, 2, 2701}, /* KATAKANA LETTER VU */ + {0x30f7, 2, 2703}, /* KATAKANA LETTER VA */ + {0x30f8, 2, 2705}, /* KATAKANA LETTER VI */ + {0x30f9, 2, 2707}, /* KATAKANA LETTER VE */ + {0x30fa, 2, 2709}, /* KATAKANA LETTER VO */ + {0x30fe, 2, 2711}, /* KATAKANA VOICED ITERATION MARK */ + {0x30ff, 2, 2713}, /* KATAKANA DIGRAPH KOTO */ + {0x3131, 1, 2715}, /* HANGUL LETTER KIYEOK */ + {0x3132, 1, 2716}, /* HANGUL LETTER SSANGKIYEOK */ + {0x3133, 1, 2717}, /* HANGUL LETTER KIYEOK-SIOS */ + {0x3134, 1, 2718}, /* HANGUL LETTER NIEUN */ + {0x3135, 1, 2719}, /* HANGUL LETTER NIEUN-CIEUC */ + {0x3136, 1, 2720}, /* HANGUL LETTER NIEUN-HIEUH */ + {0x3137, 1, 2721}, /* HANGUL LETTER TIKEUT */ + {0x3138, 1, 2722}, /* HANGUL LETTER SSANGTIKEUT */ + {0x3139, 1, 2723}, /* HANGUL LETTER RIEUL */ + {0x313a, 1, 2724}, /* HANGUL LETTER RIEUL-KIYEOK */ + {0x313b, 1, 2725}, /* HANGUL LETTER RIEUL-MIEUM */ + {0x313c, 1, 2726}, /* HANGUL LETTER RIEUL-PIEUP */ + {0x313d, 1, 2727}, /* HANGUL LETTER RIEUL-SIOS */ + {0x313e, 1, 2728}, /* HANGUL LETTER RIEUL-THIEUTH */ + {0x313f, 1, 2729}, /* HANGUL LETTER RIEUL-PHIEUPH */ + {0x3140, 1, 2730}, /* HANGUL LETTER RIEUL-HIEUH */ + {0x3141, 1, 2731}, /* HANGUL LETTER MIEUM */ + {0x3142, 1, 2732}, /* HANGUL LETTER PIEUP */ + {0x3143, 1, 2733}, /* HANGUL LETTER SSANGPIEUP */ + {0x3144, 1, 2734}, /* HANGUL LETTER PIEUP-SIOS */ + {0x3145, 1, 2735}, /* HANGUL LETTER SIOS */ + {0x3146, 1, 2736}, /* HANGUL LETTER SSANGSIOS */ + {0x3147, 1, 2737}, /* HANGUL LETTER IEUNG */ + {0x3148, 1, 2738}, /* HANGUL LETTER CIEUC */ + {0x3149, 1, 2739}, /* HANGUL LETTER SSANGCIEUC */ + {0x314a, 1, 2740}, /* HANGUL LETTER CHIEUCH */ + {0x314b, 1, 2741}, /* HANGUL LETTER KHIEUKH */ + {0x314c, 1, 2742}, /* HANGUL LETTER THIEUTH */ + {0x314d, 1, 2743}, /* HANGUL LETTER PHIEUPH */ + {0x314e, 1, 2744}, /* HANGUL LETTER HIEUH */ + {0x314f, 1, 2745}, /* HANGUL LETTER A */ + {0x3150, 1, 2746}, /* HANGUL LETTER AE */ + {0x3151, 1, 2747}, /* HANGUL LETTER YA */ + {0x3152, 1, 2748}, /* HANGUL LETTER YAE */ + {0x3153, 1, 2749}, /* HANGUL LETTER EO */ + {0x3154, 1, 2750}, /* HANGUL LETTER E */ + {0x3155, 1, 2751}, /* HANGUL LETTER YEO */ + {0x3156, 1, 2752}, /* HANGUL LETTER YE */ + {0x3157, 1, 2753}, /* HANGUL LETTER O */ + {0x3158, 1, 2754}, /* HANGUL LETTER WA */ + {0x3159, 1, 2755}, /* HANGUL LETTER WAE */ + {0x315a, 1, 2756}, /* HANGUL LETTER OE */ + {0x315b, 1, 2757}, /* HANGUL LETTER YO */ + {0x315c, 1, 2758}, /* HANGUL LETTER U */ + {0x315d, 1, 2759}, /* HANGUL LETTER WEO */ + {0x315e, 1, 2760}, /* HANGUL LETTER WE */ + {0x315f, 1, 2761}, /* HANGUL LETTER WI */ + {0x3160, 1, 2762}, /* HANGUL LETTER YU */ + {0x3161, 1, 2763}, /* HANGUL LETTER EU */ + {0x3162, 1, 2764}, /* HANGUL LETTER YI */ + {0x3163, 1, 2765}, /* HANGUL LETTER I */ + {0x3164, 1, 2766}, /* HANGUL FILLER */ + {0x3165, 1, 2767}, /* HANGUL LETTER SSANGNIEUN */ + {0x3166, 1, 2768}, /* HANGUL LETTER NIEUN-TIKEUT */ + {0x3167, 1, 2769}, /* HANGUL LETTER NIEUN-SIOS */ + {0x3168, 1, 2770}, /* HANGUL LETTER NIEUN-PANSIOS */ + {0x3169, 1, 2771}, /* HANGUL LETTER RIEUL-KIYEOK-SIOS */ + {0x316a, 1, 2772}, /* HANGUL LETTER RIEUL-TIKEUT */ + {0x316b, 1, 2773}, /* HANGUL LETTER RIEUL-PIEUP-SIOS */ + {0x316c, 1, 2774}, /* HANGUL LETTER RIEUL-PANSIOS */ + {0x316d, 1, 2775}, /* HANGUL LETTER RIEUL-YEORINHIEUH */ + {0x316e, 1, 2776}, /* HANGUL LETTER MIEUM-PIEUP */ + {0x316f, 1, 2777}, /* HANGUL LETTER MIEUM-SIOS */ + {0x3170, 1, 2778}, /* HANGUL LETTER MIEUM-PANSIOS */ + {0x3171, 1, 2779}, /* HANGUL LETTER KAPYEOUNMIEUM */ + {0x3172, 1, 2780}, /* HANGUL LETTER PIEUP-KIYEOK */ + {0x3173, 1, 2781}, /* HANGUL LETTER PIEUP-TIKEUT */ + {0x3174, 1, 2782}, /* HANGUL LETTER PIEUP-SIOS-KIYEOK */ + {0x3175, 1, 2783}, /* HANGUL LETTER PIEUP-SIOS-TIKEUT */ + {0x3176, 1, 2784}, /* HANGUL LETTER PIEUP-CIEUC */ + {0x3177, 1, 2785}, /* HANGUL LETTER PIEUP-THIEUTH */ + {0x3178, 1, 2786}, /* HANGUL LETTER KAPYEOUNPIEUP */ + {0x3179, 1, 2787}, /* HANGUL LETTER KAPYEOUNSSANGPIEUP */ + {0x317a, 1, 2788}, /* HANGUL LETTER SIOS-KIYEOK */ + {0x317b, 1, 2789}, /* HANGUL LETTER SIOS-NIEUN */ + {0x317c, 1, 2790}, /* HANGUL LETTER SIOS-TIKEUT */ + {0x317d, 1, 2791}, /* HANGUL LETTER SIOS-PIEUP */ + {0x317e, 1, 2792}, /* HANGUL LETTER SIOS-CIEUC */ + {0x317f, 1, 2793}, /* HANGUL LETTER PANSIOS */ + {0x3180, 1, 2794}, /* HANGUL LETTER SSANGIEUNG */ + {0x3181, 1, 2795}, /* HANGUL LETTER YESIEUNG */ + {0x3182, 1, 2796}, /* HANGUL LETTER YESIEUNG-SIOS */ + {0x3183, 1, 2797}, /* HANGUL LETTER YESIEUNG-PANSIOS */ + {0x3184, 1, 2798}, /* HANGUL LETTER KAPYEOUNPHIEUPH */ + {0x3185, 1, 2799}, /* HANGUL LETTER SSANGHIEUH */ + {0x3186, 1, 2800}, /* HANGUL LETTER YEORINHIEUH */ + {0x3187, 1, 2801}, /* HANGUL LETTER YO-YA */ + {0x3188, 1, 2802}, /* HANGUL LETTER YO-YAE */ + {0x3189, 1, 2803}, /* HANGUL LETTER YO-I */ + {0x318a, 1, 2804}, /* HANGUL LETTER YU-YEO */ + {0x318b, 1, 2805}, /* HANGUL LETTER YU-YE */ + {0x318c, 1, 2806}, /* HANGUL LETTER YU-I */ + {0x318d, 1, 2807}, /* HANGUL LETTER ARAEA */ + {0x318e, 1, 2808}, /* HANGUL LETTER ARAEAE */ + {0x3192, 1, 2373}, /* IDEOGRAPHIC ANNOTATION ONE MARK */ + {0x3193, 1, 2379}, /* IDEOGRAPHIC ANNOTATION TWO MARK */ + {0x3194, 1, 2809}, /* IDEOGRAPHIC ANNOTATION THREE MARK */ + {0x3195, 1, 2810}, /* IDEOGRAPHIC ANNOTATION FOUR MARK */ + {0x3196, 1, 2811}, /* IDEOGRAPHIC ANNOTATION TOP MARK */ + {0x3197, 1, 2812}, /* IDEOGRAPHIC ANNOTATION MIDDLE MARK */ + {0x3198, 1, 2813}, /* IDEOGRAPHIC ANNOTATION BOTTOM MARK */ + {0x3199, 1, 2814}, /* IDEOGRAPHIC ANNOTATION FIRST MARK */ + {0x319a, 1, 2377}, /* IDEOGRAPHIC ANNOTATION SECOND MARK */ + {0x319b, 1, 2815}, /* IDEOGRAPHIC ANNOTATION THIRD MARK */ + {0x319c, 1, 2816}, /* IDEOGRAPHIC ANNOTATION FOURTH MARK */ + {0x319d, 1, 2817}, /* IDEOGRAPHIC ANNOTATION HEAVEN MARK */ + {0x319e, 1, 2818}, /* IDEOGRAPHIC ANNOTATION EARTH MARK */ + {0x319f, 1, 2381}, /* IDEOGRAPHIC ANNOTATION MAN MARK */ + {0x3200, 3, 2819}, /* PARENTHESIZED HANGUL KIYEOK */ + {0x3201, 3, 2822}, /* PARENTHESIZED HANGUL NIEUN */ + {0x3202, 3, 2825}, /* PARENTHESIZED HANGUL TIKEUT */ + {0x3203, 3, 2828}, /* PARENTHESIZED HANGUL RIEUL */ + {0x3204, 3, 2831}, /* PARENTHESIZED HANGUL MIEUM */ + {0x3205, 3, 2834}, /* PARENTHESIZED HANGUL PIEUP */ + {0x3206, 3, 2837}, /* PARENTHESIZED HANGUL SIOS */ + {0x3207, 3, 2840}, /* PARENTHESIZED HANGUL IEUNG */ + {0x3208, 3, 2843}, /* PARENTHESIZED HANGUL CIEUC */ + {0x3209, 3, 2846}, /* PARENTHESIZED HANGUL CHIEUCH */ + {0x320a, 3, 2849}, /* PARENTHESIZED HANGUL KHIEUKH */ + {0x320b, 3, 2852}, /* PARENTHESIZED HANGUL THIEUTH */ + {0x320c, 3, 2855}, /* PARENTHESIZED HANGUL PHIEUPH */ + {0x320d, 3, 2858}, /* PARENTHESIZED HANGUL HIEUH */ + {0x320e, 4, 2861}, /* PARENTHESIZED HANGUL KIYEOK A */ + {0x320f, 4, 2865}, /* PARENTHESIZED HANGUL NIEUN A */ + {0x3210, 4, 2869}, /* PARENTHESIZED HANGUL TIKEUT A */ + {0x3211, 4, 2873}, /* PARENTHESIZED HANGUL RIEUL A */ + {0x3212, 4, 2877}, /* PARENTHESIZED HANGUL MIEUM A */ + {0x3213, 4, 2881}, /* PARENTHESIZED HANGUL PIEUP A */ + {0x3214, 4, 2885}, /* PARENTHESIZED HANGUL SIOS A */ + {0x3215, 4, 2889}, /* PARENTHESIZED HANGUL IEUNG A */ + {0x3216, 4, 2893}, /* PARENTHESIZED HANGUL CIEUC A */ + {0x3217, 4, 2897}, /* PARENTHESIZED HANGUL CHIEUCH A */ + {0x3218, 4, 2901}, /* PARENTHESIZED HANGUL KHIEUKH A */ + {0x3219, 4, 2905}, /* PARENTHESIZED HANGUL THIEUTH A */ + {0x321a, 4, 2909}, /* PARENTHESIZED HANGUL PHIEUPH A */ + {0x321b, 4, 2913}, /* PARENTHESIZED HANGUL HIEUH A */ + {0x321c, 4, 2917}, /* PARENTHESIZED HANGUL CIEUC U */ + {0x321d, 7, 2921}, /* PARENTHESIZED KOREAN CHARACTER OJEON */ + {0x321e, 6, 2928}, /* PARENTHESIZED KOREAN CHARACTER O HU */ + {0x3220, 3, 2934}, /* PARENTHESIZED IDEOGRAPH ONE */ + {0x3221, 3, 2937}, /* PARENTHESIZED IDEOGRAPH TWO */ + {0x3222, 3, 2940}, /* PARENTHESIZED IDEOGRAPH THREE */ + {0x3223, 3, 2943}, /* PARENTHESIZED IDEOGRAPH FOUR */ + {0x3224, 3, 2946}, /* PARENTHESIZED IDEOGRAPH FIVE */ + {0x3225, 3, 2949}, /* PARENTHESIZED IDEOGRAPH SIX */ + {0x3226, 3, 2952}, /* PARENTHESIZED IDEOGRAPH SEVEN */ + {0x3227, 3, 2955}, /* PARENTHESIZED IDEOGRAPH EIGHT */ + {0x3228, 3, 2958}, /* PARENTHESIZED IDEOGRAPH NINE */ + {0x3229, 3, 2961}, /* PARENTHESIZED IDEOGRAPH TEN */ + {0x322a, 3, 2964}, /* PARENTHESIZED IDEOGRAPH MOON */ + {0x322b, 3, 2967}, /* PARENTHESIZED IDEOGRAPH FIRE */ + {0x322c, 3, 2970}, /* PARENTHESIZED IDEOGRAPH WATER */ + {0x322d, 3, 2973}, /* PARENTHESIZED IDEOGRAPH WOOD */ + {0x322e, 3, 2976}, /* PARENTHESIZED IDEOGRAPH METAL */ + {0x322f, 3, 2979}, /* PARENTHESIZED IDEOGRAPH EARTH */ + {0x3230, 3, 2982}, /* PARENTHESIZED IDEOGRAPH SUN */ + {0x3231, 3, 2985}, /* PARENTHESIZED IDEOGRAPH STOCK */ + {0x3232, 3, 2988}, /* PARENTHESIZED IDEOGRAPH HAVE */ + {0x3233, 3, 2991}, /* PARENTHESIZED IDEOGRAPH SOCIETY */ + {0x3234, 3, 2994}, /* PARENTHESIZED IDEOGRAPH NAME */ + {0x3235, 3, 2997}, /* PARENTHESIZED IDEOGRAPH SPECIAL */ + {0x3236, 3, 3000}, /* PARENTHESIZED IDEOGRAPH FINANCIAL */ + {0x3237, 3, 3003}, /* PARENTHESIZED IDEOGRAPH CONGRATULATION */ + {0x3238, 3, 3006}, /* PARENTHESIZED IDEOGRAPH LABOR */ + {0x3239, 3, 3009}, /* PARENTHESIZED IDEOGRAPH REPRESENT */ + {0x323a, 3, 3012}, /* PARENTHESIZED IDEOGRAPH CALL */ + {0x323b, 3, 3015}, /* PARENTHESIZED IDEOGRAPH STUDY */ + {0x323c, 3, 3018}, /* PARENTHESIZED IDEOGRAPH SUPERVISE */ + {0x323d, 3, 3021}, /* PARENTHESIZED IDEOGRAPH ENTERPRISE */ + {0x323e, 3, 3024}, /* PARENTHESIZED IDEOGRAPH RESOURCE */ + {0x323f, 3, 3027}, /* PARENTHESIZED IDEOGRAPH ALLIANCE */ + {0x3240, 3, 3030}, /* PARENTHESIZED IDEOGRAPH FESTIVAL */ + {0x3241, 3, 3033}, /* PARENTHESIZED IDEOGRAPH REST */ + {0x3242, 3, 3036}, /* PARENTHESIZED IDEOGRAPH SELF */ + {0x3243, 3, 3039}, /* PARENTHESIZED IDEOGRAPH REACH */ + {0x3250, 3, 3042}, /* PARTNERSHIP SIGN */ + {0x3251, 2, 2147}, /* CIRCLED NUMBER TWENTY ONE */ + {0x3252, 2, 3045}, /* CIRCLED NUMBER TWENTY TWO */ + {0x3253, 2, 6}, /* CIRCLED NUMBER TWENTY THREE */ + {0x3254, 2, 3047}, /* CIRCLED NUMBER TWENTY FOUR */ + {0x3255, 2, 3049}, /* CIRCLED NUMBER TWENTY FIVE */ + {0x3256, 2, 3051}, /* CIRCLED NUMBER TWENTY SIX */ + {0x3257, 2, 3053}, /* CIRCLED NUMBER TWENTY SEVEN */ + {0x3258, 2, 3055}, /* CIRCLED NUMBER TWENTY EIGHT */ + {0x3259, 2, 3057}, /* CIRCLED NUMBER TWENTY NINE */ + {0x325a, 2, 3059}, /* CIRCLED NUMBER THIRTY */ + {0x325b, 2, 1965}, /* CIRCLED NUMBER THIRTY ONE */ + {0x325c, 2, 1962}, /* CIRCLED NUMBER THIRTY TWO */ + {0x325d, 2, 3061}, /* CIRCLED NUMBER THIRTY THREE */ + {0x325e, 2, 3063}, /* CIRCLED NUMBER THIRTY FOUR */ + {0x325f, 2, 3065}, /* CIRCLED NUMBER THIRTY FIVE */ + {0x3260, 1, 2715}, /* CIRCLED HANGUL KIYEOK */ + {0x3261, 1, 2718}, /* CIRCLED HANGUL NIEUN */ + {0x3262, 1, 2721}, /* CIRCLED HANGUL TIKEUT */ + {0x3263, 1, 2723}, /* CIRCLED HANGUL RIEUL */ + {0x3264, 1, 2731}, /* CIRCLED HANGUL MIEUM */ + {0x3265, 1, 2732}, /* CIRCLED HANGUL PIEUP */ + {0x3266, 1, 2735}, /* CIRCLED HANGUL SIOS */ + {0x3267, 1, 2737}, /* CIRCLED HANGUL IEUNG */ + {0x3268, 1, 2738}, /* CIRCLED HANGUL CIEUC */ + {0x3269, 1, 2740}, /* CIRCLED HANGUL CHIEUCH */ + {0x326a, 1, 2741}, /* CIRCLED HANGUL KHIEUKH */ + {0x326b, 1, 2742}, /* CIRCLED HANGUL THIEUTH */ + {0x326c, 1, 2743}, /* CIRCLED HANGUL PHIEUPH */ + {0x326d, 1, 2744}, /* CIRCLED HANGUL HIEUH */ + {0x326e, 2, 2862}, /* CIRCLED HANGUL KIYEOK A */ + {0x326f, 2, 2866}, /* CIRCLED HANGUL NIEUN A */ + {0x3270, 2, 2870}, /* CIRCLED HANGUL TIKEUT A */ + {0x3271, 2, 2874}, /* CIRCLED HANGUL RIEUL A */ + {0x3272, 2, 2878}, /* CIRCLED HANGUL MIEUM A */ + {0x3273, 2, 2882}, /* CIRCLED HANGUL PIEUP A */ + {0x3274, 2, 2886}, /* CIRCLED HANGUL SIOS A */ + {0x3275, 2, 2890}, /* CIRCLED HANGUL IEUNG A */ + {0x3276, 2, 2894}, /* CIRCLED HANGUL CIEUC A */ + {0x3277, 2, 2898}, /* CIRCLED HANGUL CHIEUCH A */ + {0x3278, 2, 2902}, /* CIRCLED HANGUL KHIEUKH A */ + {0x3279, 2, 2906}, /* CIRCLED HANGUL THIEUTH A */ + {0x327a, 2, 2910}, /* CIRCLED HANGUL PHIEUPH A */ + {0x327b, 2, 2744}, /* CIRCLED HANGUL HIEUH A */ + {0x327c, 5, 3067}, /* CIRCLED KOREAN CHARACTER CHAMKO */ + {0x327d, 4, 3072}, /* CIRCLED KOREAN CHARACTER JUEUI */ + {0x3280, 1, 2373}, /* CIRCLED IDEOGRAPH ONE */ + {0x3281, 1, 2379}, /* CIRCLED IDEOGRAPH TWO */ + {0x3282, 1, 2809}, /* CIRCLED IDEOGRAPH THREE */ + {0x3283, 1, 2810}, /* CIRCLED IDEOGRAPH FOUR */ + {0x3284, 1, 2947}, /* CIRCLED IDEOGRAPH FIVE */ + {0x3285, 1, 2950}, /* CIRCLED IDEOGRAPH SIX */ + {0x3286, 1, 2953}, /* CIRCLED IDEOGRAPH SEVEN */ + {0x3287, 1, 2384}, /* CIRCLED IDEOGRAPH EIGHT */ + {0x3288, 1, 2959}, /* CIRCLED IDEOGRAPH NINE */ + {0x3289, 1, 2396}, /* CIRCLED IDEOGRAPH TEN */ + {0x328a, 1, 2446}, /* CIRCLED IDEOGRAPH MOON */ + {0x328b, 1, 2458}, /* CIRCLED IDEOGRAPH FIRE */ + {0x328c, 1, 2457}, /* CIRCLED IDEOGRAPH WATER */ + {0x328d, 1, 2447}, /* CIRCLED IDEOGRAPH WOOD */ + {0x328e, 1, 2539}, /* CIRCLED IDEOGRAPH METAL */ + {0x328f, 1, 2404}, /* CIRCLED IDEOGRAPH EARTH */ + {0x3290, 1, 2444}, /* CIRCLED IDEOGRAPH SUN */ + {0x3291, 1, 2986}, /* CIRCLED IDEOGRAPH STOCK */ + {0x3292, 1, 2989}, /* CIRCLED IDEOGRAPH HAVE */ + {0x3293, 1, 2992}, /* CIRCLED IDEOGRAPH SOCIETY */ + {0x3294, 1, 2995}, /* CIRCLED IDEOGRAPH NAME */ + {0x3295, 1, 2998}, /* CIRCLED IDEOGRAPH SPECIAL */ + {0x3296, 1, 3001}, /* CIRCLED IDEOGRAPH FINANCIAL */ + {0x3297, 1, 3004}, /* CIRCLED IDEOGRAPH CONGRATULATION */ + {0x3298, 1, 3007}, /* CIRCLED IDEOGRAPH LABOR */ + {0x3299, 1, 3076}, /* CIRCLED IDEOGRAPH SECRET */ + {0x329a, 1, 3077}, /* CIRCLED IDEOGRAPH MALE */ + {0x329b, 1, 2410}, /* CIRCLED IDEOGRAPH FEMALE */ + {0x329c, 1, 3078}, /* CIRCLED IDEOGRAPH SUITABLE */ + {0x329d, 1, 3079}, /* CIRCLED IDEOGRAPH EXCELLENT */ + {0x329e, 1, 3080}, /* CIRCLED IDEOGRAPH PRINT */ + {0x329f, 1, 3081}, /* CIRCLED IDEOGRAPH ATTENTION */ + {0x32a0, 1, 3082}, /* CIRCLED IDEOGRAPH ITEM */ + {0x32a1, 1, 3034}, /* CIRCLED IDEOGRAPH REST */ + {0x32a2, 1, 3083}, /* CIRCLED IDEOGRAPH COPY */ + {0x32a3, 1, 3084}, /* CIRCLED IDEOGRAPH CORRECT */ + {0x32a4, 1, 2811}, /* CIRCLED IDEOGRAPH HIGH */ + {0x32a5, 1, 2812}, /* CIRCLED IDEOGRAPH CENTRE */ + {0x32a6, 1, 2813}, /* CIRCLED IDEOGRAPH LOW */ + {0x32a7, 1, 3085}, /* CIRCLED IDEOGRAPH LEFT */ + {0x32a8, 1, 3086}, /* CIRCLED IDEOGRAPH RIGHT */ + {0x32a9, 1, 3087}, /* CIRCLED IDEOGRAPH MEDICINE */ + {0x32aa, 1, 3088}, /* CIRCLED IDEOGRAPH RELIGION */ + {0x32ab, 1, 3016}, /* CIRCLED IDEOGRAPH STUDY */ + {0x32ac, 1, 3019}, /* CIRCLED IDEOGRAPH SUPERVISE */ + {0x32ad, 1, 3022}, /* CIRCLED IDEOGRAPH ENTERPRISE */ + {0x32ae, 1, 3025}, /* CIRCLED IDEOGRAPH RESOURCE */ + {0x32af, 1, 3028}, /* CIRCLED IDEOGRAPH ALLIANCE */ + {0x32b0, 1, 3089}, /* CIRCLED IDEOGRAPH NIGHT */ + {0x32b1, 2, 3090}, /* CIRCLED NUMBER THIRTY SIX */ + {0x32b2, 2, 3092}, /* CIRCLED NUMBER THIRTY SEVEN */ + {0x32b3, 2, 3094}, /* CIRCLED NUMBER THIRTY EIGHT */ + {0x32b4, 2, 3096}, /* CIRCLED NUMBER THIRTY NINE */ + {0x32b5, 2, 3098}, /* CIRCLED NUMBER FORTY */ + {0x32b6, 2, 17}, /* CIRCLED NUMBER FORTY ONE */ + {0x32b7, 2, 3048}, /* CIRCLED NUMBER FORTY TWO */ + {0x32b8, 2, 3064}, /* CIRCLED NUMBER FORTY THREE */ + {0x32b9, 2, 3100}, /* CIRCLED NUMBER FORTY FOUR */ + {0x32ba, 2, 3102}, /* CIRCLED NUMBER FORTY FIVE */ + {0x32bb, 2, 3104}, /* CIRCLED NUMBER FORTY SIX */ + {0x32bc, 2, 3106}, /* CIRCLED NUMBER FORTY SEVEN */ + {0x32bd, 2, 3108}, /* CIRCLED NUMBER FORTY EIGHT */ + {0x32be, 2, 3110}, /* CIRCLED NUMBER FORTY NINE */ + {0x32bf, 2, 3112}, /* CIRCLED NUMBER FIFTY */ + {0x32c0, 2, 3114}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY */ + {0x32c1, 2, 3116}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY */ + {0x32c2, 2, 3118}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH */ + {0x32c3, 2, 3120}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL */ + {0x32c4, 2, 3122}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY */ + {0x32c5, 2, 3124}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE */ + {0x32c6, 2, 3126}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY */ + {0x32c7, 2, 3128}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST */ + {0x32c8, 2, 3130}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER */ + {0x32c9, 3, 3132}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER */ + {0x32ca, 3, 3135}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER */ + {0x32cb, 3, 3138}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER */ + {0x32cc, 2, 3141}, /* SQUARE HG */ + {0x32cd, 3, 3143}, /* SQUARE ERG */ + {0x32ce, 2, 3146}, /* SQUARE EV */ + {0x32cf, 3, 3148}, /* LIMITED LIABILITY SIGN */ + {0x32d0, 1, 3151}, /* CIRCLED KATAKANA A */ + {0x32d1, 1, 3152}, /* CIRCLED KATAKANA I */ + {0x32d2, 1, 2701}, /* CIRCLED KATAKANA U */ + {0x32d3, 1, 3153}, /* CIRCLED KATAKANA E */ + {0x32d4, 1, 3154}, /* CIRCLED KATAKANA O */ + {0x32d5, 1, 2651}, /* CIRCLED KATAKANA KA */ + {0x32d6, 1, 2653}, /* CIRCLED KATAKANA KI */ + {0x32d7, 1, 2655}, /* CIRCLED KATAKANA KU */ + {0x32d8, 1, 2657}, /* CIRCLED KATAKANA KE */ + {0x32d9, 1, 2659}, /* CIRCLED KATAKANA KO */ + {0x32da, 1, 2661}, /* CIRCLED KATAKANA SA */ + {0x32db, 1, 2663}, /* CIRCLED KATAKANA SI */ + {0x32dc, 1, 2665}, /* CIRCLED KATAKANA SU */ + {0x32dd, 1, 2667}, /* CIRCLED KATAKANA SE */ + {0x32de, 1, 2669}, /* CIRCLED KATAKANA SO */ + {0x32df, 1, 2671}, /* CIRCLED KATAKANA TA */ + {0x32e0, 1, 2673}, /* CIRCLED KATAKANA TI */ + {0x32e1, 1, 2675}, /* CIRCLED KATAKANA TU */ + {0x32e2, 1, 2677}, /* CIRCLED KATAKANA TE */ + {0x32e3, 1, 2679}, /* CIRCLED KATAKANA TO */ + {0x32e4, 1, 3155}, /* CIRCLED KATAKANA NA */ + {0x32e5, 1, 3156}, /* CIRCLED KATAKANA NI */ + {0x32e6, 1, 3157}, /* CIRCLED KATAKANA NU */ + {0x32e7, 1, 3158}, /* CIRCLED KATAKANA NE */ + {0x32e8, 1, 3159}, /* CIRCLED KATAKANA NO */ + {0x32e9, 1, 2681}, /* CIRCLED KATAKANA HA */ + {0x32ea, 1, 2685}, /* CIRCLED KATAKANA HI */ + {0x32eb, 1, 2689}, /* CIRCLED KATAKANA HU */ + {0x32ec, 1, 2693}, /* CIRCLED KATAKANA HE */ + {0x32ed, 1, 2697}, /* CIRCLED KATAKANA HO */ + {0x32ee, 1, 3160}, /* CIRCLED KATAKANA MA */ + {0x32ef, 1, 3161}, /* CIRCLED KATAKANA MI */ + {0x32f0, 1, 3162}, /* CIRCLED KATAKANA MU */ + {0x32f1, 1, 3163}, /* CIRCLED KATAKANA ME */ + {0x32f2, 1, 3164}, /* CIRCLED KATAKANA MO */ + {0x32f3, 1, 3165}, /* CIRCLED KATAKANA YA */ + {0x32f4, 1, 3166}, /* CIRCLED KATAKANA YU */ + {0x32f5, 1, 3167}, /* CIRCLED KATAKANA YO */ + {0x32f6, 1, 3168}, /* CIRCLED KATAKANA RA */ + {0x32f7, 1, 3169}, /* CIRCLED KATAKANA RI */ + {0x32f8, 1, 3170}, /* CIRCLED KATAKANA RU */ + {0x32f9, 1, 3171}, /* CIRCLED KATAKANA RE */ + {0x32fa, 1, 3172}, /* CIRCLED KATAKANA RO */ + {0x32fb, 1, 2703}, /* CIRCLED KATAKANA WA */ + {0x32fc, 1, 2705}, /* CIRCLED KATAKANA WI */ + {0x32fd, 1, 2707}, /* CIRCLED KATAKANA WE */ + {0x32fe, 1, 2709}, /* CIRCLED KATAKANA WO */ + {0x3300, 4, 3173}, /* SQUARE APAATO */ + {0x3301, 4, 3177}, /* SQUARE ARUHUA */ + {0x3302, 4, 3181}, /* SQUARE ANPEA */ + {0x3303, 3, 3185}, /* SQUARE AARU */ + {0x3304, 4, 3188}, /* SQUARE ININGU */ + {0x3305, 3, 3192}, /* SQUARE INTI */ + {0x3306, 3, 3195}, /* SQUARE UON */ + {0x3307, 5, 3198}, /* SQUARE ESUKUUDO */ + {0x3308, 4, 3203}, /* SQUARE EEKAA */ + {0x3309, 3, 3207}, /* SQUARE ONSU */ + {0x330a, 3, 3210}, /* SQUARE OOMU */ + {0x330b, 3, 3213}, /* SQUARE KAIRI */ + {0x330c, 4, 3216}, /* SQUARE KARATTO */ + {0x330d, 4, 3220}, /* SQUARE KARORII */ + {0x330e, 3, 3224}, /* SQUARE GARON */ + {0x330f, 3, 3227}, /* SQUARE GANMA */ + {0x3310, 2, 3230}, /* SQUARE GIGA */ + {0x3311, 3, 3232}, /* SQUARE GINII */ + {0x3312, 4, 3235}, /* SQUARE KYURII */ + {0x3313, 4, 3239}, /* SQUARE GIRUDAA */ + {0x3314, 2, 3243}, /* SQUARE KIRO */ + {0x3315, 5, 3245}, /* SQUARE KIROGURAMU */ + {0x3316, 6, 3250}, /* SQUARE KIROMEETORU */ + {0x3317, 5, 3256}, /* SQUARE KIROWATTO */ + {0x3318, 3, 3247}, /* SQUARE GURAMU */ + {0x3319, 5, 3261}, /* SQUARE GURAMUTON */ + {0x331a, 5, 3266}, /* SQUARE KURUZEIRO */ + {0x331b, 4, 3271}, /* SQUARE KUROONE */ + {0x331c, 3, 3275}, /* SQUARE KEESU */ + {0x331d, 3, 3278}, /* SQUARE KORUNA */ + {0x331e, 3, 3281}, /* SQUARE KOOPO */ + {0x331f, 4, 3284}, /* SQUARE SAIKURU */ + {0x3320, 5, 3288}, /* SQUARE SANTIIMU */ + {0x3321, 4, 3293}, /* SQUARE SIRINGU */ + {0x3322, 3, 3297}, /* SQUARE SENTI */ + {0x3323, 3, 3300}, /* SQUARE SENTO */ + {0x3324, 3, 3303}, /* SQUARE DAASU */ + {0x3325, 2, 3306}, /* SQUARE DESI */ + {0x3326, 2, 3308}, /* SQUARE DORU */ + {0x3327, 2, 3264}, /* SQUARE TON */ + {0x3328, 2, 3310}, /* SQUARE NANO */ + {0x3329, 3, 3312}, /* SQUARE NOTTO */ + {0x332a, 3, 3315}, /* SQUARE HAITU */ + {0x332b, 5, 3318}, /* SQUARE PAASENTO */ + {0x332c, 3, 3323}, /* SQUARE PAATU */ + {0x332d, 4, 3326}, /* SQUARE BAARERU */ + {0x332e, 5, 3330}, /* SQUARE PIASUTORU */ + {0x332f, 3, 3335}, /* SQUARE PIKURU */ + {0x3330, 2, 3338}, /* SQUARE PIKO */ + {0x3331, 2, 3340}, /* SQUARE BIRU */ + {0x3332, 5, 3342}, /* SQUARE HUARADDO */ + {0x3333, 4, 3347}, /* SQUARE HUIITO */ + {0x3334, 5, 3351}, /* SQUARE BUSSYERU */ + {0x3335, 3, 3356}, /* SQUARE HURAN */ + {0x3336, 5, 3359}, /* SQUARE HEKUTAARU */ + {0x3337, 2, 3364}, /* SQUARE PESO */ + {0x3338, 3, 3366}, /* SQUARE PENIHI */ + {0x3339, 3, 3369}, /* SQUARE HERUTU */ + {0x333a, 3, 3372}, /* SQUARE PENSU */ + {0x333b, 3, 3375}, /* SQUARE PEEZI */ + {0x333c, 3, 3378}, /* SQUARE BEETA */ + {0x333d, 4, 3381}, /* SQUARE POINTO */ + {0x333e, 3, 3385}, /* SQUARE BORUTO */ + {0x333f, 2, 3388}, /* SQUARE HON */ + {0x3340, 3, 3390}, /* SQUARE PONDO */ + {0x3341, 3, 3393}, /* SQUARE HOORU */ + {0x3342, 3, 3396}, /* SQUARE HOON */ + {0x3343, 4, 3399}, /* SQUARE MAIKURO */ + {0x3344, 3, 3403}, /* SQUARE MAIRU */ + {0x3345, 3, 3406}, /* SQUARE MAHHA */ + {0x3346, 3, 3409}, /* SQUARE MARUKU */ + {0x3347, 5, 3412}, /* SQUARE MANSYON */ + {0x3348, 4, 3417}, /* SQUARE MIKURON */ + {0x3349, 2, 3421}, /* SQUARE MIRI */ + {0x334a, 5, 3423}, /* SQUARE MIRIBAARU */ + {0x334b, 2, 3428}, /* SQUARE MEGA */ + {0x334c, 4, 3430}, /* SQUARE MEGATON */ + {0x334d, 4, 3252}, /* SQUARE MEETORU */ + {0x334e, 3, 3434}, /* SQUARE YAADO */ + {0x334f, 3, 3437}, /* SQUARE YAARU */ + {0x3350, 3, 3440}, /* SQUARE YUAN */ + {0x3351, 4, 3443}, /* SQUARE RITTORU */ + {0x3352, 2, 3447}, /* SQUARE RIRA */ + {0x3353, 3, 3449}, /* SQUARE RUPII */ + {0x3354, 4, 3452}, /* SQUARE RUUBURU */ + {0x3355, 2, 3456}, /* SQUARE REMU */ + {0x3356, 5, 3458}, /* SQUARE RENTOGEN */ + {0x3357, 3, 3258}, /* SQUARE WATTO */ + {0x3358, 2, 3463}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO */ + {0x3359, 2, 3465}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE */ + {0x335a, 2, 3467}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO */ + {0x335b, 2, 3469}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE */ + {0x335c, 2, 3471}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR */ + {0x335d, 2, 3473}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE */ + {0x335e, 2, 3475}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX */ + {0x335f, 2, 3477}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN */ + {0x3360, 2, 3479}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT */ + {0x3361, 2, 3481}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE */ + {0x3362, 3, 3483}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN */ + {0x3363, 3, 3486}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN */ + {0x3364, 3, 3489}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE */ + {0x3365, 3, 3492}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN */ + {0x3366, 3, 3495}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN */ + {0x3367, 3, 3498}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN */ + {0x3368, 3, 3501}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN */ + {0x3369, 3, 3504}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN */ + {0x336a, 3, 3507}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN */ + {0x336b, 3, 3510}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN */ + {0x336c, 3, 3513}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY */ + {0x336d, 3, 3516}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE */ + {0x336e, 3, 3519}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO */ + {0x336f, 3, 3522}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE */ + {0x3370, 3, 3525}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR */ + {0x3371, 3, 3528}, /* SQUARE HPA */ + {0x3372, 2, 3531}, /* SQUARE DA */ + {0x3373, 2, 3533}, /* SQUARE AU */ + {0x3374, 3, 3535}, /* SQUARE BAR */ + {0x3375, 2, 3538}, /* SQUARE OV */ + {0x3376, 2, 3540}, /* SQUARE PC */ + {0x3377, 2, 3542}, /* SQUARE DM */ + {0x3378, 3, 3544}, /* SQUARE DM SQUARED */ + {0x3379, 3, 3547}, /* SQUARE DM CUBED */ + {0x337a, 2, 3550}, /* SQUARE IU */ + {0x337b, 2, 3552}, /* SQUARE ERA NAME HEISEI */ + {0x337c, 2, 3554}, /* SQUARE ERA NAME SYOUWA */ + {0x337d, 2, 3556}, /* SQUARE ERA NAME TAISYOU */ + {0x337e, 2, 3558}, /* SQUARE ERA NAME MEIZI */ + {0x337f, 4, 3560}, /* SQUARE CORPORATION */ + {0x3380, 2, 3564}, /* SQUARE PA AMPS */ + {0x3381, 2, 3566}, /* SQUARE NA */ + {0x3382, 2, 3568}, /* SQUARE MU A */ + {0x3383, 2, 3570}, /* SQUARE MA */ + {0x3384, 2, 3572}, /* SQUARE KA */ + {0x3385, 2, 3574}, /* SQUARE KB */ + {0x3386, 2, 3576}, /* SQUARE MB */ + {0x3387, 2, 3578}, /* SQUARE GB */ + {0x3388, 3, 3580}, /* SQUARE CAL */ + {0x3389, 4, 3583}, /* SQUARE KCAL */ + {0x338a, 2, 3587}, /* SQUARE PF */ + {0x338b, 2, 3589}, /* SQUARE NF */ + {0x338c, 2, 3591}, /* SQUARE MU F */ + {0x338d, 2, 3593}, /* SQUARE MU G */ + {0x338e, 2, 3595}, /* SQUARE MG */ + {0x338f, 2, 3597}, /* SQUARE KG */ + {0x3390, 2, 3599}, /* SQUARE HZ */ + {0x3391, 3, 3601}, /* SQUARE KHZ */ + {0x3392, 3, 3604}, /* SQUARE MHZ */ + {0x3393, 3, 3607}, /* SQUARE GHZ */ + {0x3394, 3, 3610}, /* SQUARE THZ */ + {0x3395, 2, 3613}, /* SQUARE MU L */ + {0x3396, 2, 3615}, /* SQUARE ML */ + {0x3397, 2, 3617}, /* SQUARE DL */ + {0x3398, 2, 3619}, /* SQUARE KL */ + {0x3399, 2, 3621}, /* SQUARE FM */ + {0x339a, 2, 3623}, /* SQUARE NM */ + {0x339b, 2, 3625}, /* SQUARE MU M */ + {0x339c, 2, 3627}, /* SQUARE MM */ + {0x339d, 2, 3629}, /* SQUARE CM */ + {0x339e, 2, 3631}, /* SQUARE KM */ + {0x339f, 3, 3633}, /* SQUARE MM SQUARED */ + {0x33a0, 3, 3636}, /* SQUARE CM SQUARED */ + {0x33a1, 2, 3545}, /* SQUARE M SQUARED */ + {0x33a2, 3, 3639}, /* SQUARE KM SQUARED */ + {0x33a3, 3, 3642}, /* SQUARE MM CUBED */ + {0x33a4, 3, 3645}, /* SQUARE CM CUBED */ + {0x33a5, 2, 3548}, /* SQUARE M CUBED */ + {0x33a6, 3, 3648}, /* SQUARE KM CUBED */ + {0x33a7, 3, 3651}, /* SQUARE M OVER S */ + {0x33a8, 4, 3654}, /* SQUARE M OVER S SQUARED */ + {0x33a9, 2, 3529}, /* SQUARE PA */ + {0x33aa, 3, 3658}, /* SQUARE KPA */ + {0x33ab, 3, 3661}, /* SQUARE MPA */ + {0x33ac, 3, 3664}, /* SQUARE GPA */ + {0x33ad, 3, 3667}, /* SQUARE RAD */ + {0x33ae, 5, 3670}, /* SQUARE RAD OVER S */ + {0x33af, 6, 3675}, /* SQUARE RAD OVER S SQUARED */ + {0x33b0, 2, 3681}, /* SQUARE PS */ + {0x33b1, 2, 3683}, /* SQUARE NS */ + {0x33b2, 2, 3685}, /* SQUARE MU S */ + {0x33b3, 2, 3687}, /* SQUARE MS */ + {0x33b4, 2, 3689}, /* SQUARE PV */ + {0x33b5, 2, 3691}, /* SQUARE NV */ + {0x33b6, 2, 3693}, /* SQUARE MU V */ + {0x33b7, 2, 3695}, /* SQUARE MV */ + {0x33b8, 2, 3697}, /* SQUARE KV */ + {0x33b9, 2, 3699}, /* SQUARE MV MEGA */ + {0x33ba, 2, 3701}, /* SQUARE PW */ + {0x33bb, 2, 3703}, /* SQUARE NW */ + {0x33bc, 2, 3705}, /* SQUARE MU W */ + {0x33bd, 2, 3707}, /* SQUARE MW */ + {0x33be, 2, 3709}, /* SQUARE KW */ + {0x33bf, 2, 3711}, /* SQUARE MW MEGA */ + {0x33c0, 2, 3713}, /* SQUARE K OHM */ + {0x33c1, 2, 3715}, /* SQUARE M OHM */ + {0x33c2, 4, 3717}, /* SQUARE AM */ + {0x33c3, 2, 3721}, /* SQUARE BQ */ + {0x33c4, 2, 3723}, /* SQUARE CC */ + {0x33c5, 2, 3541}, /* SQUARE CD */ + {0x33c6, 4, 3725}, /* SQUARE C OVER KG */ + {0x33c7, 3, 3729}, /* SQUARE CO */ + {0x33c8, 2, 3732}, /* SQUARE DB */ + {0x33c9, 2, 3734}, /* SQUARE GY */ + {0x33ca, 2, 3736}, /* SQUARE HA */ + {0x33cb, 2, 3738}, /* SQUARE HP */ + {0x33cc, 2, 3740}, /* SQUARE IN */ + {0x33cd, 2, 3742}, /* SQUARE KK */ + {0x33ce, 2, 3744}, /* SQUARE KM CAPITAL */ + {0x33cf, 2, 3746}, /* SQUARE KT */ + {0x33d0, 2, 3748}, /* SQUARE LM */ + {0x33d1, 2, 3750}, /* SQUARE LN */ + {0x33d2, 3, 3752}, /* SQUARE LOG */ + {0x33d3, 2, 3755}, /* SQUARE LX */ + {0x33d4, 2, 3757}, /* SQUARE MB SMALL */ + {0x33d5, 3, 3759}, /* SQUARE MIL */ + {0x33d6, 3, 3762}, /* SQUARE MOL */ + {0x33d7, 2, 3765}, /* SQUARE PH */ + {0x33d8, 4, 3767}, /* SQUARE PM */ + {0x33d9, 3, 3771}, /* SQUARE PPM */ + {0x33da, 2, 3774}, /* SQUARE PR */ + {0x33db, 2, 3674}, /* SQUARE SR */ + {0x33dc, 2, 3776}, /* SQUARE SV */ + {0x33dd, 2, 3778}, /* SQUARE WB */ + {0x33de, 3, 3780}, /* SQUARE V OVER M */ + {0x33df, 3, 3783}, /* SQUARE A OVER M */ + {0x33e0, 2, 3786}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE */ + {0x33e1, 2, 3788}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO */ + {0x33e2, 2, 3790}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE */ + {0x33e3, 2, 3792}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR */ + {0x33e4, 2, 3794}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE */ + {0x33e5, 2, 3796}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX */ + {0x33e6, 2, 3798}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN */ + {0x33e7, 2, 3800}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT */ + {0x33e8, 2, 3802}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE */ + {0x33e9, 3, 3804}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN */ + {0x33ea, 3, 3807}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN */ + {0x33eb, 3, 3810}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE */ + {0x33ec, 3, 3813}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN */ + {0x33ed, 3, 3816}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN */ + {0x33ee, 3, 3819}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN */ + {0x33ef, 3, 3822}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN */ + {0x33f0, 3, 3825}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN */ + {0x33f1, 3, 3828}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN */ + {0x33f2, 3, 3831}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN */ + {0x33f3, 3, 3834}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY */ + {0x33f4, 3, 3837}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE */ + {0x33f5, 3, 3840}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO */ + {0x33f6, 3, 3843}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE */ + {0x33f7, 3, 3846}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR */ + {0x33f8, 3, 3849}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE */ + {0x33f9, 3, 3852}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX */ + {0x33fa, 3, 3855}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN */ + {0x33fb, 3, 3858}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT */ + {0x33fc, 3, 3861}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE */ + {0x33fd, 3, 3864}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY */ + {0x33fe, 3, 3867}, /* IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE */ + {0x33ff, 3, 3870}, /* SQUARE GAL */ + {0xf900, 1, 3873}, /* CJK COMPATIBILITY IDEOGRAPH-F900 */ + {0xf901, 1, 3874}, /* CJK COMPATIBILITY IDEOGRAPH-F901 */ + {0xf902, 1, 2531}, /* CJK COMPATIBILITY IDEOGRAPH-F902 */ + {0xf903, 1, 3875}, /* CJK COMPATIBILITY IDEOGRAPH-F903 */ + {0xf904, 1, 3876}, /* CJK COMPATIBILITY IDEOGRAPH-F904 */ + {0xf905, 1, 3877}, /* CJK COMPATIBILITY IDEOGRAPH-F905 */ + {0xf906, 1, 3878}, /* CJK COMPATIBILITY IDEOGRAPH-F906 */ + {0xf907, 1, 2585}, /* CJK COMPATIBILITY IDEOGRAPH-F907 */ + {0xf908, 1, 2585}, /* CJK COMPATIBILITY IDEOGRAPH-F908 */ + {0xf909, 1, 3879}, /* CJK COMPATIBILITY IDEOGRAPH-F909 */ + {0xf90a, 1, 2539}, /* CJK COMPATIBILITY IDEOGRAPH-F90A */ + {0xf90b, 1, 3880}, /* CJK COMPATIBILITY IDEOGRAPH-F90B */ + {0xf90c, 1, 3881}, /* CJK COMPATIBILITY IDEOGRAPH-F90C */ + {0xf90d, 1, 3882}, /* CJK COMPATIBILITY IDEOGRAPH-F90D */ + {0xf90e, 1, 3883}, /* CJK COMPATIBILITY IDEOGRAPH-F90E */ + {0xf90f, 1, 3884}, /* CJK COMPATIBILITY IDEOGRAPH-F90F */ + {0xf910, 1, 3885}, /* CJK COMPATIBILITY IDEOGRAPH-F910 */ + {0xf911, 1, 3886}, /* CJK COMPATIBILITY IDEOGRAPH-F911 */ + {0xf912, 1, 3887}, /* CJK COMPATIBILITY IDEOGRAPH-F912 */ + {0xf913, 1, 3888}, /* CJK COMPATIBILITY IDEOGRAPH-F913 */ + {0xf914, 1, 3889}, /* CJK COMPATIBILITY IDEOGRAPH-F914 */ + {0xf915, 1, 3890}, /* CJK COMPATIBILITY IDEOGRAPH-F915 */ + {0xf916, 1, 3891}, /* CJK COMPATIBILITY IDEOGRAPH-F916 */ + {0xf917, 1, 3892}, /* CJK COMPATIBILITY IDEOGRAPH-F917 */ + {0xf918, 1, 3893}, /* CJK COMPATIBILITY IDEOGRAPH-F918 */ + {0xf919, 1, 3894}, /* CJK COMPATIBILITY IDEOGRAPH-F919 */ + {0xf91a, 1, 3895}, /* CJK COMPATIBILITY IDEOGRAPH-F91A */ + {0xf91b, 1, 3896}, /* CJK COMPATIBILITY IDEOGRAPH-F91B */ + {0xf91c, 1, 3897}, /* CJK COMPATIBILITY IDEOGRAPH-F91C */ + {0xf91d, 1, 3898}, /* CJK COMPATIBILITY IDEOGRAPH-F91D */ + {0xf91e, 1, 3899}, /* CJK COMPATIBILITY IDEOGRAPH-F91E */ + {0xf91f, 1, 3900}, /* CJK COMPATIBILITY IDEOGRAPH-F91F */ + {0xf920, 1, 3901}, /* CJK COMPATIBILITY IDEOGRAPH-F920 */ + {0xf921, 1, 3902}, /* CJK COMPATIBILITY IDEOGRAPH-F921 */ + {0xf922, 1, 3903}, /* CJK COMPATIBILITY IDEOGRAPH-F922 */ + {0xf923, 1, 3904}, /* CJK COMPATIBILITY IDEOGRAPH-F923 */ + {0xf924, 1, 3905}, /* CJK COMPATIBILITY IDEOGRAPH-F924 */ + {0xf925, 1, 3906}, /* CJK COMPATIBILITY IDEOGRAPH-F925 */ + {0xf926, 1, 3907}, /* CJK COMPATIBILITY IDEOGRAPH-F926 */ + {0xf927, 1, 3908}, /* CJK COMPATIBILITY IDEOGRAPH-F927 */ + {0xf928, 1, 3909}, /* CJK COMPATIBILITY IDEOGRAPH-F928 */ + {0xf929, 1, 3910}, /* CJK COMPATIBILITY IDEOGRAPH-F929 */ + {0xf92a, 1, 3911}, /* CJK COMPATIBILITY IDEOGRAPH-F92A */ + {0xf92b, 1, 3912}, /* CJK COMPATIBILITY IDEOGRAPH-F92B */ + {0xf92c, 1, 3913}, /* CJK COMPATIBILITY IDEOGRAPH-F92C */ + {0xf92d, 1, 3914}, /* CJK COMPATIBILITY IDEOGRAPH-F92D */ + {0xf92e, 1, 3915}, /* CJK COMPATIBILITY IDEOGRAPH-F92E */ + {0xf92f, 1, 3916}, /* CJK COMPATIBILITY IDEOGRAPH-F92F */ + {0xf930, 1, 3917}, /* CJK COMPATIBILITY IDEOGRAPH-F930 */ + {0xf931, 1, 3918}, /* CJK COMPATIBILITY IDEOGRAPH-F931 */ + {0xf932, 1, 3919}, /* CJK COMPATIBILITY IDEOGRAPH-F932 */ + {0xf933, 1, 3920}, /* CJK COMPATIBILITY IDEOGRAPH-F933 */ + {0xf934, 1, 2497}, /* CJK COMPATIBILITY IDEOGRAPH-F934 */ + {0xf935, 1, 3921}, /* CJK COMPATIBILITY IDEOGRAPH-F935 */ + {0xf936, 1, 3922}, /* CJK COMPATIBILITY IDEOGRAPH-F936 */ + {0xf937, 1, 3923}, /* CJK COMPATIBILITY IDEOGRAPH-F937 */ + {0xf938, 1, 3924}, /* CJK COMPATIBILITY IDEOGRAPH-F938 */ + {0xf939, 1, 3925}, /* CJK COMPATIBILITY IDEOGRAPH-F939 */ + {0xf93a, 1, 3926}, /* CJK COMPATIBILITY IDEOGRAPH-F93A */ + {0xf93b, 1, 3927}, /* CJK COMPATIBILITY IDEOGRAPH-F93B */ + {0xf93c, 1, 3928}, /* CJK COMPATIBILITY IDEOGRAPH-F93C */ + {0xf93d, 1, 3929}, /* CJK COMPATIBILITY IDEOGRAPH-F93D */ + {0xf93e, 1, 3930}, /* CJK COMPATIBILITY IDEOGRAPH-F93E */ + {0xf93f, 1, 3931}, /* CJK COMPATIBILITY IDEOGRAPH-F93F */ + {0xf940, 1, 2570}, /* CJK COMPATIBILITY IDEOGRAPH-F940 */ + {0xf941, 1, 3932}, /* CJK COMPATIBILITY IDEOGRAPH-F941 */ + {0xf942, 1, 3933}, /* CJK COMPATIBILITY IDEOGRAPH-F942 */ + {0xf943, 1, 3934}, /* CJK COMPATIBILITY IDEOGRAPH-F943 */ + {0xf944, 1, 3935}, /* CJK COMPATIBILITY IDEOGRAPH-F944 */ + {0xf945, 1, 3936}, /* CJK COMPATIBILITY IDEOGRAPH-F945 */ + {0xf946, 1, 3937}, /* CJK COMPATIBILITY IDEOGRAPH-F946 */ + {0xf947, 1, 3938}, /* CJK COMPATIBILITY IDEOGRAPH-F947 */ + {0xf948, 1, 3939}, /* CJK COMPATIBILITY IDEOGRAPH-F948 */ + {0xf949, 1, 3940}, /* CJK COMPATIBILITY IDEOGRAPH-F949 */ + {0xf94a, 1, 3941}, /* CJK COMPATIBILITY IDEOGRAPH-F94A */ + {0xf94b, 1, 3942}, /* CJK COMPATIBILITY IDEOGRAPH-F94B */ + {0xf94c, 1, 3943}, /* CJK COMPATIBILITY IDEOGRAPH-F94C */ + {0xf94d, 1, 3944}, /* CJK COMPATIBILITY IDEOGRAPH-F94D */ + {0xf94e, 1, 3945}, /* CJK COMPATIBILITY IDEOGRAPH-F94E */ + {0xf94f, 1, 3946}, /* CJK COMPATIBILITY IDEOGRAPH-F94F */ + {0xf950, 1, 3947}, /* CJK COMPATIBILITY IDEOGRAPH-F950 */ + {0xf951, 1, 3948}, /* CJK COMPATIBILITY IDEOGRAPH-F951 */ + {0xf952, 1, 3949}, /* CJK COMPATIBILITY IDEOGRAPH-F952 */ + {0xf953, 1, 3950}, /* CJK COMPATIBILITY IDEOGRAPH-F953 */ + {0xf954, 1, 3951}, /* CJK COMPATIBILITY IDEOGRAPH-F954 */ + {0xf955, 1, 3952}, /* CJK COMPATIBILITY IDEOGRAPH-F955 */ + {0xf956, 1, 3953}, /* CJK COMPATIBILITY IDEOGRAPH-F956 */ + {0xf957, 1, 3954}, /* CJK COMPATIBILITY IDEOGRAPH-F957 */ + {0xf958, 1, 3955}, /* CJK COMPATIBILITY IDEOGRAPH-F958 */ + {0xf959, 1, 3956}, /* CJK COMPATIBILITY IDEOGRAPH-F959 */ + {0xf95a, 1, 3957}, /* CJK COMPATIBILITY IDEOGRAPH-F95A */ + {0xf95b, 1, 3958}, /* CJK COMPATIBILITY IDEOGRAPH-F95B */ + {0xf95c, 1, 3889}, /* CJK COMPATIBILITY IDEOGRAPH-F95C */ + {0xf95d, 1, 3959}, /* CJK COMPATIBILITY IDEOGRAPH-F95D */ + {0xf95e, 1, 3960}, /* CJK COMPATIBILITY IDEOGRAPH-F95E */ + {0xf95f, 1, 3961}, /* CJK COMPATIBILITY IDEOGRAPH-F95F */ + {0xf960, 1, 3962}, /* CJK COMPATIBILITY IDEOGRAPH-F960 */ + {0xf961, 1, 3963}, /* CJK COMPATIBILITY IDEOGRAPH-F961 */ + {0xf962, 1, 3964}, /* CJK COMPATIBILITY IDEOGRAPH-F962 */ + {0xf963, 1, 3965}, /* CJK COMPATIBILITY IDEOGRAPH-F963 */ + {0xf964, 1, 3966}, /* CJK COMPATIBILITY IDEOGRAPH-F964 */ + {0xf965, 1, 3967}, /* CJK COMPATIBILITY IDEOGRAPH-F965 */ + {0xf966, 1, 3968}, /* CJK COMPATIBILITY IDEOGRAPH-F966 */ + {0xf967, 1, 3969}, /* CJK COMPATIBILITY IDEOGRAPH-F967 */ + {0xf968, 1, 3970}, /* CJK COMPATIBILITY IDEOGRAPH-F968 */ + {0xf969, 1, 3971}, /* CJK COMPATIBILITY IDEOGRAPH-F969 */ + {0xf96a, 1, 3972}, /* CJK COMPATIBILITY IDEOGRAPH-F96A */ + {0xf96b, 1, 3973}, /* CJK COMPATIBILITY IDEOGRAPH-F96B */ + {0xf96c, 1, 3974}, /* CJK COMPATIBILITY IDEOGRAPH-F96C */ + {0xf96d, 1, 3975}, /* CJK COMPATIBILITY IDEOGRAPH-F96D */ + {0xf96e, 1, 3976}, /* CJK COMPATIBILITY IDEOGRAPH-F96E */ + {0xf96f, 1, 3977}, /* CJK COMPATIBILITY IDEOGRAPH-F96F */ + {0xf970, 1, 3978}, /* CJK COMPATIBILITY IDEOGRAPH-F970 */ + {0xf971, 1, 2533}, /* CJK COMPATIBILITY IDEOGRAPH-F971 */ + {0xf972, 1, 3979}, /* CJK COMPATIBILITY IDEOGRAPH-F972 */ + {0xf973, 1, 3980}, /* CJK COMPATIBILITY IDEOGRAPH-F973 */ + {0xf974, 1, 3981}, /* CJK COMPATIBILITY IDEOGRAPH-F974 */ + {0xf975, 1, 3982}, /* CJK COMPATIBILITY IDEOGRAPH-F975 */ + {0xf976, 1, 3983}, /* CJK COMPATIBILITY IDEOGRAPH-F976 */ + {0xf977, 1, 3984}, /* CJK COMPATIBILITY IDEOGRAPH-F977 */ + {0xf978, 1, 3985}, /* CJK COMPATIBILITY IDEOGRAPH-F978 */ + {0xf979, 1, 3986}, /* CJK COMPATIBILITY IDEOGRAPH-F979 */ + {0xf97a, 1, 3987}, /* CJK COMPATIBILITY IDEOGRAPH-F97A */ + {0xf97b, 1, 3988}, /* CJK COMPATIBILITY IDEOGRAPH-F97B */ + {0xf97c, 1, 3989}, /* CJK COMPATIBILITY IDEOGRAPH-F97C */ + {0xf97d, 1, 3990}, /* CJK COMPATIBILITY IDEOGRAPH-F97D */ + {0xf97e, 1, 3991}, /* CJK COMPATIBILITY IDEOGRAPH-F97E */ + {0xf97f, 1, 3992}, /* CJK COMPATIBILITY IDEOGRAPH-F97F */ + {0xf980, 1, 3993}, /* CJK COMPATIBILITY IDEOGRAPH-F980 */ + {0xf981, 1, 2410}, /* CJK COMPATIBILITY IDEOGRAPH-F981 */ + {0xf982, 1, 3994}, /* CJK COMPATIBILITY IDEOGRAPH-F982 */ + {0xf983, 1, 3995}, /* CJK COMPATIBILITY IDEOGRAPH-F983 */ + {0xf984, 1, 3996}, /* CJK COMPATIBILITY IDEOGRAPH-F984 */ + {0xf985, 1, 3997}, /* CJK COMPATIBILITY IDEOGRAPH-F985 */ + {0xf986, 1, 3998}, /* CJK COMPATIBILITY IDEOGRAPH-F986 */ + {0xf987, 1, 3999}, /* CJK COMPATIBILITY IDEOGRAPH-F987 */ + {0xf988, 1, 4000}, /* CJK COMPATIBILITY IDEOGRAPH-F988 */ + {0xf989, 1, 4001}, /* CJK COMPATIBILITY IDEOGRAPH-F989 */ + {0xf98a, 1, 2391}, /* CJK COMPATIBILITY IDEOGRAPH-F98A */ + {0xf98b, 1, 4002}, /* CJK COMPATIBILITY IDEOGRAPH-F98B */ + {0xf98c, 1, 4003}, /* CJK COMPATIBILITY IDEOGRAPH-F98C */ + {0xf98d, 1, 4004}, /* CJK COMPATIBILITY IDEOGRAPH-F98D */ + {0xf98e, 1, 4005}, /* CJK COMPATIBILITY IDEOGRAPH-F98E */ + {0xf98f, 1, 4006}, /* CJK COMPATIBILITY IDEOGRAPH-F98F */ + {0xf990, 1, 4007}, /* CJK COMPATIBILITY IDEOGRAPH-F990 */ + {0xf991, 1, 4008}, /* CJK COMPATIBILITY IDEOGRAPH-F991 */ + {0xf992, 1, 4009}, /* CJK COMPATIBILITY IDEOGRAPH-F992 */ + {0xf993, 1, 4010}, /* CJK COMPATIBILITY IDEOGRAPH-F993 */ + {0xf994, 1, 4011}, /* CJK COMPATIBILITY IDEOGRAPH-F994 */ + {0xf995, 1, 4012}, /* CJK COMPATIBILITY IDEOGRAPH-F995 */ + {0xf996, 1, 4013}, /* CJK COMPATIBILITY IDEOGRAPH-F996 */ + {0xf997, 1, 4014}, /* CJK COMPATIBILITY IDEOGRAPH-F997 */ + {0xf998, 1, 4015}, /* CJK COMPATIBILITY IDEOGRAPH-F998 */ + {0xf999, 1, 4016}, /* CJK COMPATIBILITY IDEOGRAPH-F999 */ + {0xf99a, 1, 4017}, /* CJK COMPATIBILITY IDEOGRAPH-F99A */ + {0xf99b, 1, 4018}, /* CJK COMPATIBILITY IDEOGRAPH-F99B */ + {0xf99c, 1, 4019}, /* CJK COMPATIBILITY IDEOGRAPH-F99C */ + {0xf99d, 1, 4020}, /* CJK COMPATIBILITY IDEOGRAPH-F99D */ + {0xf99e, 1, 4021}, /* CJK COMPATIBILITY IDEOGRAPH-F99E */ + {0xf99f, 1, 4022}, /* CJK COMPATIBILITY IDEOGRAPH-F99F */ + {0xf9a0, 1, 4023}, /* CJK COMPATIBILITY IDEOGRAPH-F9A0 */ + {0xf9a1, 1, 3977}, /* CJK COMPATIBILITY IDEOGRAPH-F9A1 */ + {0xf9a2, 1, 4024}, /* CJK COMPATIBILITY IDEOGRAPH-F9A2 */ + {0xf9a3, 1, 4025}, /* CJK COMPATIBILITY IDEOGRAPH-F9A3 */ + {0xf9a4, 1, 4026}, /* CJK COMPATIBILITY IDEOGRAPH-F9A4 */ + {0xf9a5, 1, 4027}, /* CJK COMPATIBILITY IDEOGRAPH-F9A5 */ + {0xf9a6, 1, 4028}, /* CJK COMPATIBILITY IDEOGRAPH-F9A6 */ + {0xf9a7, 1, 4029}, /* CJK COMPATIBILITY IDEOGRAPH-F9A7 */ + {0xf9a8, 1, 4030}, /* CJK COMPATIBILITY IDEOGRAPH-F9A8 */ + {0xf9a9, 1, 4031}, /* CJK COMPATIBILITY IDEOGRAPH-F9A9 */ + {0xf9aa, 1, 3961}, /* CJK COMPATIBILITY IDEOGRAPH-F9AA */ + {0xf9ab, 1, 4032}, /* CJK COMPATIBILITY IDEOGRAPH-F9AB */ + {0xf9ac, 1, 4033}, /* CJK COMPATIBILITY IDEOGRAPH-F9AC */ + {0xf9ad, 1, 4034}, /* CJK COMPATIBILITY IDEOGRAPH-F9AD */ + {0xf9ae, 1, 4035}, /* CJK COMPATIBILITY IDEOGRAPH-F9AE */ + {0xf9af, 1, 4036}, /* CJK COMPATIBILITY IDEOGRAPH-F9AF */ + {0xf9b0, 1, 4037}, /* CJK COMPATIBILITY IDEOGRAPH-F9B0 */ + {0xf9b1, 1, 4038}, /* CJK COMPATIBILITY IDEOGRAPH-F9B1 */ + {0xf9b2, 1, 4039}, /* CJK COMPATIBILITY IDEOGRAPH-F9B2 */ + {0xf9b3, 1, 4040}, /* CJK COMPATIBILITY IDEOGRAPH-F9B3 */ + {0xf9b4, 1, 4041}, /* CJK COMPATIBILITY IDEOGRAPH-F9B4 */ + {0xf9b5, 1, 4042}, /* CJK COMPATIBILITY IDEOGRAPH-F9B5 */ + {0xf9b6, 1, 4043}, /* CJK COMPATIBILITY IDEOGRAPH-F9B6 */ + {0xf9b7, 1, 4044}, /* CJK COMPATIBILITY IDEOGRAPH-F9B7 */ + {0xf9b8, 1, 4045}, /* CJK COMPATIBILITY IDEOGRAPH-F9B8 */ + {0xf9b9, 1, 4046}, /* CJK COMPATIBILITY IDEOGRAPH-F9B9 */ + {0xf9ba, 1, 4047}, /* CJK COMPATIBILITY IDEOGRAPH-F9BA */ + {0xf9bb, 1, 4048}, /* CJK COMPATIBILITY IDEOGRAPH-F9BB */ + {0xf9bc, 1, 4049}, /* CJK COMPATIBILITY IDEOGRAPH-F9BC */ + {0xf9bd, 1, 4050}, /* CJK COMPATIBILITY IDEOGRAPH-F9BD */ + {0xf9be, 1, 4051}, /* CJK COMPATIBILITY IDEOGRAPH-F9BE */ + {0xf9bf, 1, 3889}, /* CJK COMPATIBILITY IDEOGRAPH-F9BF */ + {0xf9c0, 1, 4052}, /* CJK COMPATIBILITY IDEOGRAPH-F9C0 */ + {0xf9c1, 1, 4053}, /* CJK COMPATIBILITY IDEOGRAPH-F9C1 */ + {0xf9c2, 1, 4054}, /* CJK COMPATIBILITY IDEOGRAPH-F9C2 */ + {0xf9c3, 1, 4055}, /* CJK COMPATIBILITY IDEOGRAPH-F9C3 */ + {0xf9c4, 1, 2584}, /* CJK COMPATIBILITY IDEOGRAPH-F9C4 */ + {0xf9c5, 1, 4056}, /* CJK COMPATIBILITY IDEOGRAPH-F9C5 */ + {0xf9c6, 1, 4057}, /* CJK COMPATIBILITY IDEOGRAPH-F9C6 */ + {0xf9c7, 1, 4058}, /* CJK COMPATIBILITY IDEOGRAPH-F9C7 */ + {0xf9c8, 1, 4059}, /* CJK COMPATIBILITY IDEOGRAPH-F9C8 */ + {0xf9c9, 1, 4060}, /* CJK COMPATIBILITY IDEOGRAPH-F9C9 */ + {0xf9ca, 1, 4061}, /* CJK COMPATIBILITY IDEOGRAPH-F9CA */ + {0xf9cb, 1, 4062}, /* CJK COMPATIBILITY IDEOGRAPH-F9CB */ + {0xf9cc, 1, 4063}, /* CJK COMPATIBILITY IDEOGRAPH-F9CC */ + {0xf9cd, 1, 4064}, /* CJK COMPATIBILITY IDEOGRAPH-F9CD */ + {0xf9ce, 1, 4065}, /* CJK COMPATIBILITY IDEOGRAPH-F9CE */ + {0xf9cf, 1, 4066}, /* CJK COMPATIBILITY IDEOGRAPH-F9CF */ + {0xf9d0, 1, 4067}, /* CJK COMPATIBILITY IDEOGRAPH-F9D0 */ + {0xf9d1, 1, 2950}, /* CJK COMPATIBILITY IDEOGRAPH-F9D1 */ + {0xf9d2, 1, 4068}, /* CJK COMPATIBILITY IDEOGRAPH-F9D2 */ + {0xf9d3, 1, 4069}, /* CJK COMPATIBILITY IDEOGRAPH-F9D3 */ + {0xf9d4, 1, 4070}, /* CJK COMPATIBILITY IDEOGRAPH-F9D4 */ + {0xf9d5, 1, 4071}, /* CJK COMPATIBILITY IDEOGRAPH-F9D5 */ + {0xf9d6, 1, 4072}, /* CJK COMPATIBILITY IDEOGRAPH-F9D6 */ + {0xf9d7, 1, 4073}, /* CJK COMPATIBILITY IDEOGRAPH-F9D7 */ + {0xf9d8, 1, 4074}, /* CJK COMPATIBILITY IDEOGRAPH-F9D8 */ + {0xf9d9, 1, 4075}, /* CJK COMPATIBILITY IDEOGRAPH-F9D9 */ + {0xf9da, 1, 4076}, /* CJK COMPATIBILITY IDEOGRAPH-F9DA */ + {0xf9db, 1, 3963}, /* CJK COMPATIBILITY IDEOGRAPH-F9DB */ + {0xf9dc, 1, 4077}, /* CJK COMPATIBILITY IDEOGRAPH-F9DC */ + {0xf9dd, 1, 4078}, /* CJK COMPATIBILITY IDEOGRAPH-F9DD */ + {0xf9de, 1, 4079}, /* CJK COMPATIBILITY IDEOGRAPH-F9DE */ + {0xf9df, 1, 4080}, /* CJK COMPATIBILITY IDEOGRAPH-F9DF */ + {0xf9e0, 1, 4081}, /* CJK COMPATIBILITY IDEOGRAPH-F9E0 */ + {0xf9e1, 1, 4082}, /* CJK COMPATIBILITY IDEOGRAPH-F9E1 */ + {0xf9e2, 1, 4083}, /* CJK COMPATIBILITY IDEOGRAPH-F9E2 */ + {0xf9e3, 1, 4084}, /* CJK COMPATIBILITY IDEOGRAPH-F9E3 */ + {0xf9e4, 1, 4085}, /* CJK COMPATIBILITY IDEOGRAPH-F9E4 */ + {0xf9e5, 1, 4086}, /* CJK COMPATIBILITY IDEOGRAPH-F9E5 */ + {0xf9e6, 1, 4087}, /* CJK COMPATIBILITY IDEOGRAPH-F9E6 */ + {0xf9e7, 1, 4088}, /* CJK COMPATIBILITY IDEOGRAPH-F9E7 */ + {0xf9e8, 1, 4089}, /* CJK COMPATIBILITY IDEOGRAPH-F9E8 */ + {0xf9e9, 1, 2538}, /* CJK COMPATIBILITY IDEOGRAPH-F9E9 */ + {0xf9ea, 1, 4090}, /* CJK COMPATIBILITY IDEOGRAPH-F9EA */ + {0xf9eb, 1, 4091}, /* CJK COMPATIBILITY IDEOGRAPH-F9EB */ + {0xf9ec, 1, 4092}, /* CJK COMPATIBILITY IDEOGRAPH-F9EC */ + {0xf9ed, 1, 4093}, /* CJK COMPATIBILITY IDEOGRAPH-F9ED */ + {0xf9ee, 1, 4094}, /* CJK COMPATIBILITY IDEOGRAPH-F9EE */ + {0xf9ef, 1, 4095}, /* CJK COMPATIBILITY IDEOGRAPH-F9EF */ + {0xf9f0, 1, 4096}, /* CJK COMPATIBILITY IDEOGRAPH-F9F0 */ + {0xf9f1, 1, 4097}, /* CJK COMPATIBILITY IDEOGRAPH-F9F1 */ + {0xf9f2, 1, 4098}, /* CJK COMPATIBILITY IDEOGRAPH-F9F2 */ + {0xf9f3, 1, 4099}, /* CJK COMPATIBILITY IDEOGRAPH-F9F3 */ + {0xf9f4, 1, 4100}, /* CJK COMPATIBILITY IDEOGRAPH-F9F4 */ + {0xf9f5, 1, 4101}, /* CJK COMPATIBILITY IDEOGRAPH-F9F5 */ + {0xf9f6, 1, 4102}, /* CJK COMPATIBILITY IDEOGRAPH-F9F6 */ + {0xf9f7, 1, 2489}, /* CJK COMPATIBILITY IDEOGRAPH-F9F7 */ + {0xf9f8, 1, 4103}, /* CJK COMPATIBILITY IDEOGRAPH-F9F8 */ + {0xf9f9, 1, 4104}, /* CJK COMPATIBILITY IDEOGRAPH-F9F9 */ + {0xf9fa, 1, 4105}, /* CJK COMPATIBILITY IDEOGRAPH-F9FA */ + {0xf9fb, 1, 4106}, /* CJK COMPATIBILITY IDEOGRAPH-F9FB */ + {0xf9fc, 1, 4107}, /* CJK COMPATIBILITY IDEOGRAPH-F9FC */ + {0xf9fd, 1, 4108}, /* CJK COMPATIBILITY IDEOGRAPH-F9FD */ + {0xf9fe, 1, 4109}, /* CJK COMPATIBILITY IDEOGRAPH-F9FE */ + {0xf9ff, 1, 4110}, /* CJK COMPATIBILITY IDEOGRAPH-F9FF */ + {0xfa00, 1, 4111}, /* CJK COMPATIBILITY IDEOGRAPH-FA00 */ + {0xfa01, 1, 4112}, /* CJK COMPATIBILITY IDEOGRAPH-FA01 */ + {0xfa02, 1, 4113}, /* CJK COMPATIBILITY IDEOGRAPH-FA02 */ + {0xfa03, 1, 4114}, /* CJK COMPATIBILITY IDEOGRAPH-FA03 */ + {0xfa04, 1, 4115}, /* CJK COMPATIBILITY IDEOGRAPH-FA04 */ + {0xfa05, 1, 4116}, /* CJK COMPATIBILITY IDEOGRAPH-FA05 */ + {0xfa06, 1, 4117}, /* CJK COMPATIBILITY IDEOGRAPH-FA06 */ + {0xfa07, 1, 4118}, /* CJK COMPATIBILITY IDEOGRAPH-FA07 */ + {0xfa08, 1, 2516}, /* CJK COMPATIBILITY IDEOGRAPH-FA08 */ + {0xfa09, 1, 4119}, /* CJK COMPATIBILITY IDEOGRAPH-FA09 */ + {0xfa0a, 1, 2519}, /* CJK COMPATIBILITY IDEOGRAPH-FA0A */ + {0xfa0b, 1, 4120}, /* CJK COMPATIBILITY IDEOGRAPH-FA0B */ + {0xfa0c, 1, 4121}, /* CJK COMPATIBILITY IDEOGRAPH-FA0C */ + {0xfa0d, 1, 4122}, /* CJK COMPATIBILITY IDEOGRAPH-FA0D */ + {0xfa10, 1, 4123}, /* CJK COMPATIBILITY IDEOGRAPH-FA10 */ + {0xfa12, 1, 4124}, /* CJK COMPATIBILITY IDEOGRAPH-FA12 */ + {0xfa15, 1, 4125}, /* CJK COMPATIBILITY IDEOGRAPH-FA15 */ + {0xfa16, 1, 4126}, /* CJK COMPATIBILITY IDEOGRAPH-FA16 */ + {0xfa17, 1, 4127}, /* CJK COMPATIBILITY IDEOGRAPH-FA17 */ + {0xfa18, 1, 4128}, /* CJK COMPATIBILITY IDEOGRAPH-FA18 */ + {0xfa19, 1, 4129}, /* CJK COMPATIBILITY IDEOGRAPH-FA19 */ + {0xfa1a, 1, 4130}, /* CJK COMPATIBILITY IDEOGRAPH-FA1A */ + {0xfa1b, 1, 4131}, /* CJK COMPATIBILITY IDEOGRAPH-FA1B */ + {0xfa1c, 1, 4132}, /* CJK COMPATIBILITY IDEOGRAPH-FA1C */ + {0xfa1d, 1, 4133}, /* CJK COMPATIBILITY IDEOGRAPH-FA1D */ + {0xfa1e, 1, 2496}, /* CJK COMPATIBILITY IDEOGRAPH-FA1E */ + {0xfa20, 1, 4134}, /* CJK COMPATIBILITY IDEOGRAPH-FA20 */ + {0xfa22, 1, 4135}, /* CJK COMPATIBILITY IDEOGRAPH-FA22 */ + {0xfa25, 1, 4136}, /* CJK COMPATIBILITY IDEOGRAPH-FA25 */ + {0xfa26, 1, 4137}, /* CJK COMPATIBILITY IDEOGRAPH-FA26 */ + {0xfa2a, 1, 4138}, /* CJK COMPATIBILITY IDEOGRAPH-FA2A */ + {0xfa2b, 1, 4139}, /* CJK COMPATIBILITY IDEOGRAPH-FA2B */ + {0xfa2c, 1, 4140}, /* CJK COMPATIBILITY IDEOGRAPH-FA2C */ + {0xfa2d, 1, 4141}, /* CJK COMPATIBILITY IDEOGRAPH-FA2D */ + {0xfa30, 1, 4142}, /* CJK COMPATIBILITY IDEOGRAPH-FA30 */ + {0xfa31, 1, 4143}, /* CJK COMPATIBILITY IDEOGRAPH-FA31 */ + {0xfa32, 1, 4144}, /* CJK COMPATIBILITY IDEOGRAPH-FA32 */ + {0xfa33, 1, 4145}, /* CJK COMPATIBILITY IDEOGRAPH-FA33 */ + {0xfa34, 1, 4146}, /* CJK COMPATIBILITY IDEOGRAPH-FA34 */ + {0xfa35, 1, 4147}, /* CJK COMPATIBILITY IDEOGRAPH-FA35 */ + {0xfa36, 1, 4148}, /* CJK COMPATIBILITY IDEOGRAPH-FA36 */ + {0xfa37, 1, 4149}, /* CJK COMPATIBILITY IDEOGRAPH-FA37 */ + {0xfa38, 1, 4150}, /* CJK COMPATIBILITY IDEOGRAPH-FA38 */ + {0xfa39, 1, 4151}, /* CJK COMPATIBILITY IDEOGRAPH-FA39 */ + {0xfa3a, 1, 4152}, /* CJK COMPATIBILITY IDEOGRAPH-FA3A */ + {0xfa3b, 1, 4153}, /* CJK COMPATIBILITY IDEOGRAPH-FA3B */ + {0xfa3c, 1, 2417}, /* CJK COMPATIBILITY IDEOGRAPH-FA3C */ + {0xfa3d, 1, 4154}, /* CJK COMPATIBILITY IDEOGRAPH-FA3D */ + {0xfa3e, 1, 4155}, /* CJK COMPATIBILITY IDEOGRAPH-FA3E */ + {0xfa3f, 1, 4156}, /* CJK COMPATIBILITY IDEOGRAPH-FA3F */ + {0xfa40, 1, 4157}, /* CJK COMPATIBILITY IDEOGRAPH-FA40 */ + {0xfa41, 1, 4158}, /* CJK COMPATIBILITY IDEOGRAPH-FA41 */ + {0xfa42, 1, 4159}, /* CJK COMPATIBILITY IDEOGRAPH-FA42 */ + {0xfa43, 1, 4160}, /* CJK COMPATIBILITY IDEOGRAPH-FA43 */ + {0xfa44, 1, 4161}, /* CJK COMPATIBILITY IDEOGRAPH-FA44 */ + {0xfa45, 1, 4162}, /* CJK COMPATIBILITY IDEOGRAPH-FA45 */ + {0xfa46, 1, 4163}, /* CJK COMPATIBILITY IDEOGRAPH-FA46 */ + {0xfa47, 1, 4164}, /* CJK COMPATIBILITY IDEOGRAPH-FA47 */ + {0xfa48, 1, 4165}, /* CJK COMPATIBILITY IDEOGRAPH-FA48 */ + {0xfa49, 1, 4166}, /* CJK COMPATIBILITY IDEOGRAPH-FA49 */ + {0xfa4a, 1, 4167}, /* CJK COMPATIBILITY IDEOGRAPH-FA4A */ + {0xfa4b, 1, 4168}, /* CJK COMPATIBILITY IDEOGRAPH-FA4B */ + {0xfa4c, 1, 2992}, /* CJK COMPATIBILITY IDEOGRAPH-FA4C */ + {0xfa4d, 1, 4169}, /* CJK COMPATIBILITY IDEOGRAPH-FA4D */ + {0xfa4e, 1, 4170}, /* CJK COMPATIBILITY IDEOGRAPH-FA4E */ + {0xfa4f, 1, 4171}, /* CJK COMPATIBILITY IDEOGRAPH-FA4F */ + {0xfa50, 1, 4172}, /* CJK COMPATIBILITY IDEOGRAPH-FA50 */ + {0xfa51, 1, 3004}, /* CJK COMPATIBILITY IDEOGRAPH-FA51 */ + {0xfa52, 1, 4173}, /* CJK COMPATIBILITY IDEOGRAPH-FA52 */ + {0xfa53, 1, 4174}, /* CJK COMPATIBILITY IDEOGRAPH-FA53 */ + {0xfa54, 1, 4175}, /* CJK COMPATIBILITY IDEOGRAPH-FA54 */ + {0xfa55, 1, 4176}, /* CJK COMPATIBILITY IDEOGRAPH-FA55 */ + {0xfa56, 1, 4177}, /* CJK COMPATIBILITY IDEOGRAPH-FA56 */ + {0xfa57, 1, 4013}, /* CJK COMPATIBILITY IDEOGRAPH-FA57 */ + {0xfa58, 1, 4178}, /* CJK COMPATIBILITY IDEOGRAPH-FA58 */ + {0xfa59, 1, 4179}, /* CJK COMPATIBILITY IDEOGRAPH-FA59 */ + {0xfa5a, 1, 4180}, /* CJK COMPATIBILITY IDEOGRAPH-FA5A */ + {0xfa5b, 1, 4181}, /* CJK COMPATIBILITY IDEOGRAPH-FA5B */ + {0xfa5c, 1, 4182}, /* CJK COMPATIBILITY IDEOGRAPH-FA5C */ + {0xfa5d, 1, 4183}, /* CJK COMPATIBILITY IDEOGRAPH-FA5D */ + {0xfa5e, 1, 4183}, /* CJK COMPATIBILITY IDEOGRAPH-FA5E */ + {0xfa5f, 1, 4184}, /* CJK COMPATIBILITY IDEOGRAPH-FA5F */ + {0xfa60, 1, 4185}, /* CJK COMPATIBILITY IDEOGRAPH-FA60 */ + {0xfa61, 1, 4186}, /* CJK COMPATIBILITY IDEOGRAPH-FA61 */ + {0xfa62, 1, 4187}, /* CJK COMPATIBILITY IDEOGRAPH-FA62 */ + {0xfa63, 1, 4188}, /* CJK COMPATIBILITY IDEOGRAPH-FA63 */ + {0xfa64, 1, 4189}, /* CJK COMPATIBILITY IDEOGRAPH-FA64 */ + {0xfa65, 1, 4190}, /* CJK COMPATIBILITY IDEOGRAPH-FA65 */ + {0xfa66, 1, 4191}, /* CJK COMPATIBILITY IDEOGRAPH-FA66 */ + {0xfa67, 1, 4136}, /* CJK COMPATIBILITY IDEOGRAPH-FA67 */ + {0xfa68, 1, 4192}, /* CJK COMPATIBILITY IDEOGRAPH-FA68 */ + {0xfa69, 1, 4193}, /* CJK COMPATIBILITY IDEOGRAPH-FA69 */ + {0xfa6a, 1, 4194}, /* CJK COMPATIBILITY IDEOGRAPH-FA6A */ + {0xfb00, 2, 4195}, /* LATIN SMALL LIGATURE FF */ + {0xfb01, 2, 4197}, /* LATIN SMALL LIGATURE FI */ + {0xfb02, 2, 4199}, /* LATIN SMALL LIGATURE FL */ + {0xfb03, 3, 4196}, /* LATIN SMALL LIGATURE FFI */ + {0xfb04, 3, 4201}, /* LATIN SMALL LIGATURE FFL */ + {0xfb05, 2, 4204}, /* LATIN SMALL LIGATURE LONG S T */ + {0xfb06, 2, 4206}, /* LATIN SMALL LIGATURE ST */ + {0xfb13, 2, 4208}, /* ARMENIAN SMALL LIGATURE MEN NOW */ + {0xfb14, 2, 4210}, /* ARMENIAN SMALL LIGATURE MEN ECH */ + {0xfb15, 2, 4212}, /* ARMENIAN SMALL LIGATURE MEN INI */ + {0xfb16, 2, 4214}, /* ARMENIAN SMALL LIGATURE VEW NOW */ + {0xfb17, 2, 4216}, /* ARMENIAN SMALL LIGATURE MEN XEH */ + {0xfb1d, 2, 4218}, /* HEBREW LETTER YOD WITH HIRIQ */ + {0xfb1f, 2, 4220}, /* HEBREW LIGATURE YIDDISH YOD YOD PATAH */ + {0xfb20, 1, 4222}, /* HEBREW LETTER ALTERNATIVE AYIN */ + {0xfb21, 1, 1950}, /* HEBREW LETTER WIDE ALEF */ + {0xfb22, 1, 1953}, /* HEBREW LETTER WIDE DALET */ + {0xfb23, 1, 4223}, /* HEBREW LETTER WIDE HE */ + {0xfb24, 1, 4224}, /* HEBREW LETTER WIDE KAF */ + {0xfb25, 1, 4225}, /* HEBREW LETTER WIDE LAMED */ + {0xfb26, 1, 4226}, /* HEBREW LETTER WIDE FINAL MEM */ + {0xfb27, 1, 4227}, /* HEBREW LETTER WIDE RESH */ + {0xfb28, 1, 4228}, /* HEBREW LETTER WIDE TAV */ + {0xfb29, 1, 1915}, /* HEBREW LETTER ALTERNATIVE PLUS SIGN */ + {0xfb2a, 2, 4229}, /* HEBREW LETTER SHIN WITH SHIN DOT */ + {0xfb2b, 2, 4231}, /* HEBREW LETTER SHIN WITH SIN DOT */ + {0xfb2c, 2, 4233}, /* HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT */ + {0xfb2d, 2, 4235}, /* HEBREW LETTER SHIN WITH DAGESH AND SIN DOT */ + {0xfb2e, 2, 4237}, /* HEBREW LETTER ALEF WITH PATAH */ + {0xfb2f, 2, 4239}, /* HEBREW LETTER ALEF WITH QAMATS */ + {0xfb30, 2, 4241}, /* HEBREW LETTER ALEF WITH MAPIQ */ + {0xfb31, 2, 4243}, /* HEBREW LETTER BET WITH DAGESH */ + {0xfb32, 2, 4245}, /* HEBREW LETTER GIMEL WITH DAGESH */ + {0xfb33, 2, 4247}, /* HEBREW LETTER DALET WITH DAGESH */ + {0xfb34, 2, 4249}, /* HEBREW LETTER HE WITH MAPIQ */ + {0xfb35, 2, 4251}, /* HEBREW LETTER VAV WITH DAGESH */ + {0xfb36, 2, 4253}, /* HEBREW LETTER ZAYIN WITH DAGESH */ + {0xfb38, 2, 4255}, /* HEBREW LETTER TET WITH DAGESH */ + {0xfb39, 2, 4257}, /* HEBREW LETTER YOD WITH DAGESH */ + {0xfb3a, 2, 4259}, /* HEBREW LETTER FINAL KAF WITH DAGESH */ + {0xfb3b, 2, 4261}, /* HEBREW LETTER KAF WITH DAGESH */ + {0xfb3c, 2, 4263}, /* HEBREW LETTER LAMED WITH DAGESH */ + {0xfb3e, 2, 4265}, /* HEBREW LETTER MEM WITH DAGESH */ + {0xfb40, 2, 4267}, /* HEBREW LETTER NUN WITH DAGESH */ + {0xfb41, 2, 4269}, /* HEBREW LETTER SAMEKH WITH DAGESH */ + {0xfb43, 2, 4271}, /* HEBREW LETTER FINAL PE WITH DAGESH */ + {0xfb44, 2, 4273}, /* HEBREW LETTER PE WITH DAGESH */ + {0xfb46, 2, 4275}, /* HEBREW LETTER TSADI WITH DAGESH */ + {0xfb47, 2, 4277}, /* HEBREW LETTER QOF WITH DAGESH */ + {0xfb48, 2, 4279}, /* HEBREW LETTER RESH WITH DAGESH */ + {0xfb49, 2, 4281}, /* HEBREW LETTER SHIN WITH DAGESH */ + {0xfb4a, 2, 4283}, /* HEBREW LETTER TAV WITH DAGESH */ + {0xfb4b, 2, 4285}, /* HEBREW LETTER VAV WITH HOLAM */ + {0xfb4c, 2, 4287}, /* HEBREW LETTER BET WITH RAFE */ + {0xfb4d, 2, 4289}, /* HEBREW LETTER KAF WITH RAFE */ + {0xfb4e, 2, 4291}, /* HEBREW LETTER PE WITH RAFE */ + {0xfb4f, 2, 4293}, /* HEBREW LIGATURE ALEF LAMED */ + {0xfb50, 1, 4295}, /* ARABIC LETTER ALEF WASLA ISOLATED FORM */ + {0xfb51, 1, 4295}, /* ARABIC LETTER ALEF WASLA FINAL FORM */ + {0xfb52, 1, 4296}, /* ARABIC LETTER BEEH ISOLATED FORM */ + {0xfb53, 1, 4296}, /* ARABIC LETTER BEEH FINAL FORM */ + {0xfb54, 1, 4296}, /* ARABIC LETTER BEEH INITIAL FORM */ + {0xfb55, 1, 4296}, /* ARABIC LETTER BEEH MEDIAL FORM */ + {0xfb56, 1, 4297}, /* ARABIC LETTER PEH ISOLATED FORM */ + {0xfb57, 1, 4297}, /* ARABIC LETTER PEH FINAL FORM */ + {0xfb58, 1, 4297}, /* ARABIC LETTER PEH INITIAL FORM */ + {0xfb59, 1, 4297}, /* ARABIC LETTER PEH MEDIAL FORM */ + {0xfb5a, 1, 4298}, /* ARABIC LETTER BEHEH ISOLATED FORM */ + {0xfb5b, 1, 4298}, /* ARABIC LETTER BEHEH FINAL FORM */ + {0xfb5c, 1, 4298}, /* ARABIC LETTER BEHEH INITIAL FORM */ + {0xfb5d, 1, 4298}, /* ARABIC LETTER BEHEH MEDIAL FORM */ + {0xfb5e, 1, 4299}, /* ARABIC LETTER TTEHEH ISOLATED FORM */ + {0xfb5f, 1, 4299}, /* ARABIC LETTER TTEHEH FINAL FORM */ + {0xfb60, 1, 4299}, /* ARABIC LETTER TTEHEH INITIAL FORM */ + {0xfb61, 1, 4299}, /* ARABIC LETTER TTEHEH MEDIAL FORM */ + {0xfb62, 1, 4300}, /* ARABIC LETTER TEHEH ISOLATED FORM */ + {0xfb63, 1, 4300}, /* ARABIC LETTER TEHEH FINAL FORM */ + {0xfb64, 1, 4300}, /* ARABIC LETTER TEHEH INITIAL FORM */ + {0xfb65, 1, 4300}, /* ARABIC LETTER TEHEH MEDIAL FORM */ + {0xfb66, 1, 4301}, /* ARABIC LETTER TTEH ISOLATED FORM */ + {0xfb67, 1, 4301}, /* ARABIC LETTER TTEH FINAL FORM */ + {0xfb68, 1, 4301}, /* ARABIC LETTER TTEH INITIAL FORM */ + {0xfb69, 1, 4301}, /* ARABIC LETTER TTEH MEDIAL FORM */ + {0xfb6a, 1, 4302}, /* ARABIC LETTER VEH ISOLATED FORM */ + {0xfb6b, 1, 4302}, /* ARABIC LETTER VEH FINAL FORM */ + {0xfb6c, 1, 4302}, /* ARABIC LETTER VEH INITIAL FORM */ + {0xfb6d, 1, 4302}, /* ARABIC LETTER VEH MEDIAL FORM */ + {0xfb6e, 1, 4303}, /* ARABIC LETTER PEHEH ISOLATED FORM */ + {0xfb6f, 1, 4303}, /* ARABIC LETTER PEHEH FINAL FORM */ + {0xfb70, 1, 4303}, /* ARABIC LETTER PEHEH INITIAL FORM */ + {0xfb71, 1, 4303}, /* ARABIC LETTER PEHEH MEDIAL FORM */ + {0xfb72, 1, 4304}, /* ARABIC LETTER DYEH ISOLATED FORM */ + {0xfb73, 1, 4304}, /* ARABIC LETTER DYEH FINAL FORM */ + {0xfb74, 1, 4304}, /* ARABIC LETTER DYEH INITIAL FORM */ + {0xfb75, 1, 4304}, /* ARABIC LETTER DYEH MEDIAL FORM */ + {0xfb76, 1, 4305}, /* ARABIC LETTER NYEH ISOLATED FORM */ + {0xfb77, 1, 4305}, /* ARABIC LETTER NYEH FINAL FORM */ + {0xfb78, 1, 4305}, /* ARABIC LETTER NYEH INITIAL FORM */ + {0xfb79, 1, 4305}, /* ARABIC LETTER NYEH MEDIAL FORM */ + {0xfb7a, 1, 4306}, /* ARABIC LETTER TCHEH ISOLATED FORM */ + {0xfb7b, 1, 4306}, /* ARABIC LETTER TCHEH FINAL FORM */ + {0xfb7c, 1, 4306}, /* ARABIC LETTER TCHEH INITIAL FORM */ + {0xfb7d, 1, 4306}, /* ARABIC LETTER TCHEH MEDIAL FORM */ + {0xfb7e, 1, 4307}, /* ARABIC LETTER TCHEHEH ISOLATED FORM */ + {0xfb7f, 1, 4307}, /* ARABIC LETTER TCHEHEH FINAL FORM */ + {0xfb80, 1, 4307}, /* ARABIC LETTER TCHEHEH INITIAL FORM */ + {0xfb81, 1, 4307}, /* ARABIC LETTER TCHEHEH MEDIAL FORM */ + {0xfb82, 1, 4308}, /* ARABIC LETTER DDAHAL ISOLATED FORM */ + {0xfb83, 1, 4308}, /* ARABIC LETTER DDAHAL FINAL FORM */ + {0xfb84, 1, 4309}, /* ARABIC LETTER DAHAL ISOLATED FORM */ + {0xfb85, 1, 4309}, /* ARABIC LETTER DAHAL FINAL FORM */ + {0xfb86, 1, 4310}, /* ARABIC LETTER DUL ISOLATED FORM */ + {0xfb87, 1, 4310}, /* ARABIC LETTER DUL FINAL FORM */ + {0xfb88, 1, 4311}, /* ARABIC LETTER DDAL ISOLATED FORM */ + {0xfb89, 1, 4311}, /* ARABIC LETTER DDAL FINAL FORM */ + {0xfb8a, 1, 4312}, /* ARABIC LETTER JEH ISOLATED FORM */ + {0xfb8b, 1, 4312}, /* ARABIC LETTER JEH FINAL FORM */ + {0xfb8c, 1, 4313}, /* ARABIC LETTER RREH ISOLATED FORM */ + {0xfb8d, 1, 4313}, /* ARABIC LETTER RREH FINAL FORM */ + {0xfb8e, 1, 4314}, /* ARABIC LETTER KEHEH ISOLATED FORM */ + {0xfb8f, 1, 4314}, /* ARABIC LETTER KEHEH FINAL FORM */ + {0xfb90, 1, 4314}, /* ARABIC LETTER KEHEH INITIAL FORM */ + {0xfb91, 1, 4314}, /* ARABIC LETTER KEHEH MEDIAL FORM */ + {0xfb92, 1, 4315}, /* ARABIC LETTER GAF ISOLATED FORM */ + {0xfb93, 1, 4315}, /* ARABIC LETTER GAF FINAL FORM */ + {0xfb94, 1, 4315}, /* ARABIC LETTER GAF INITIAL FORM */ + {0xfb95, 1, 4315}, /* ARABIC LETTER GAF MEDIAL FORM */ + {0xfb96, 1, 4316}, /* ARABIC LETTER GUEH ISOLATED FORM */ + {0xfb97, 1, 4316}, /* ARABIC LETTER GUEH FINAL FORM */ + {0xfb98, 1, 4316}, /* ARABIC LETTER GUEH INITIAL FORM */ + {0xfb99, 1, 4316}, /* ARABIC LETTER GUEH MEDIAL FORM */ + {0xfb9a, 1, 4317}, /* ARABIC LETTER NGOEH ISOLATED FORM */ + {0xfb9b, 1, 4317}, /* ARABIC LETTER NGOEH FINAL FORM */ + {0xfb9c, 1, 4317}, /* ARABIC LETTER NGOEH INITIAL FORM */ + {0xfb9d, 1, 4317}, /* ARABIC LETTER NGOEH MEDIAL FORM */ + {0xfb9e, 1, 4318}, /* ARABIC LETTER NOON GHUNNA ISOLATED FORM */ + {0xfb9f, 1, 4318}, /* ARABIC LETTER NOON GHUNNA FINAL FORM */ + {0xfba0, 1, 4319}, /* ARABIC LETTER RNOON ISOLATED FORM */ + {0xfba1, 1, 4319}, /* ARABIC LETTER RNOON FINAL FORM */ + {0xfba2, 1, 4319}, /* ARABIC LETTER RNOON INITIAL FORM */ + {0xfba3, 1, 4319}, /* ARABIC LETTER RNOON MEDIAL FORM */ + {0xfba4, 1, 4320}, /* ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM */ + {0xfba5, 1, 4320}, /* ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM */ + {0xfba6, 1, 769}, /* ARABIC LETTER HEH GOAL ISOLATED FORM */ + {0xfba7, 1, 769}, /* ARABIC LETTER HEH GOAL FINAL FORM */ + {0xfba8, 1, 769}, /* ARABIC LETTER HEH GOAL INITIAL FORM */ + {0xfba9, 1, 769}, /* ARABIC LETTER HEH GOAL MEDIAL FORM */ + {0xfbaa, 1, 4321}, /* ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM */ + {0xfbab, 1, 4321}, /* ARABIC LETTER HEH DOACHASHMEE FINAL FORM */ + {0xfbac, 1, 4321}, /* ARABIC LETTER HEH DOACHASHMEE INITIAL FORM */ + {0xfbad, 1, 4321}, /* ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM */ + {0xfbae, 1, 771}, /* ARABIC LETTER YEH BARREE ISOLATED FORM */ + {0xfbaf, 1, 771}, /* ARABIC LETTER YEH BARREE FINAL FORM */ + {0xfbb0, 1, 4322}, /* ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM */ + {0xfbb1, 1, 4322}, /* ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM */ + {0xfbd3, 1, 4323}, /* ARABIC LETTER NG ISOLATED FORM */ + {0xfbd4, 1, 4323}, /* ARABIC LETTER NG FINAL FORM */ + {0xfbd5, 1, 4323}, /* ARABIC LETTER NG INITIAL FORM */ + {0xfbd6, 1, 4323}, /* ARABIC LETTER NG MEDIAL FORM */ + {0xfbd7, 1, 763}, /* ARABIC LETTER U ISOLATED FORM */ + {0xfbd8, 1, 763}, /* ARABIC LETTER U FINAL FORM */ + {0xfbd9, 1, 4324}, /* ARABIC LETTER OE ISOLATED FORM */ + {0xfbda, 1, 4324}, /* ARABIC LETTER OE FINAL FORM */ + {0xfbdb, 1, 4325}, /* ARABIC LETTER YU ISOLATED FORM */ + {0xfbdc, 1, 4325}, /* ARABIC LETTER YU FINAL FORM */ + {0xfbdd, 1, 4326}, /* ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */ + {0xfbde, 1, 4327}, /* ARABIC LETTER VE ISOLATED FORM */ + {0xfbdf, 1, 4327}, /* ARABIC LETTER VE FINAL FORM */ + {0xfbe0, 1, 4328}, /* ARABIC LETTER KIRGHIZ OE ISOLATED FORM */ + {0xfbe1, 1, 4328}, /* ARABIC LETTER KIRGHIZ OE FINAL FORM */ + {0xfbe2, 1, 4329}, /* ARABIC LETTER KIRGHIZ YU ISOLATED FORM */ + {0xfbe3, 1, 4329}, /* ARABIC LETTER KIRGHIZ YU FINAL FORM */ + {0xfbe4, 1, 4330}, /* ARABIC LETTER E ISOLATED FORM */ + {0xfbe5, 1, 4330}, /* ARABIC LETTER E FINAL FORM */ + {0xfbe6, 1, 4330}, /* ARABIC LETTER E INITIAL FORM */ + {0xfbe7, 1, 4330}, /* ARABIC LETTER E MEDIAL FORM */ + {0xfbe8, 1, 4331}, /* ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM */ + {0xfbe9, 1, 4331}, /* ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM */ + {0xfbea, 2, 4332}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM */ + {0xfbeb, 2, 4332}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM */ + {0xfbec, 2, 4334}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM */ + {0xfbed, 2, 4334}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM */ + {0xfbee, 2, 4336}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM */ + {0xfbef, 2, 4336}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM */ + {0xfbf0, 2, 4338}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM */ + {0xfbf1, 2, 4338}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM */ + {0xfbf2, 2, 4340}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM */ + {0xfbf3, 2, 4340}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM */ + {0xfbf4, 2, 4342}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM */ + {0xfbf5, 2, 4342}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM */ + {0xfbf6, 2, 4344}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM */ + {0xfbf7, 2, 4344}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM */ + {0xfbf8, 2, 4344}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM */ + {0xfbf9, 2, 4346}, /* ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM */ + {0xfbfa, 2, 4346}, /* ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM */ + {0xfbfb, 2, 4346}, /* ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM */ + {0xfbfc, 1, 4348}, /* ARABIC LETTER FARSI YEH ISOLATED FORM */ + {0xfbfd, 1, 4348}, /* ARABIC LETTER FARSI YEH FINAL FORM */ + {0xfbfe, 1, 4348}, /* ARABIC LETTER FARSI YEH INITIAL FORM */ + {0xfbff, 1, 4348}, /* ARABIC LETTER FARSI YEH MEDIAL FORM */ + {0xfc00, 2, 4349}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM */ + {0xfc01, 2, 4351}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM */ + {0xfc02, 2, 4353}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM */ + {0xfc03, 2, 4346}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc04, 2, 4355}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM */ + {0xfc05, 2, 4357}, /* ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM */ + {0xfc06, 2, 4359}, /* ARABIC LIGATURE BEH WITH HAH ISOLATED FORM */ + {0xfc07, 2, 4361}, /* ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM */ + {0xfc08, 2, 4363}, /* ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM */ + {0xfc09, 2, 4365}, /* ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc0a, 2, 4367}, /* ARABIC LIGATURE BEH WITH YEH ISOLATED FORM */ + {0xfc0b, 2, 4369}, /* ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM */ + {0xfc0c, 2, 4371}, /* ARABIC LIGATURE TEH WITH HAH ISOLATED FORM */ + {0xfc0d, 2, 4373}, /* ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM */ + {0xfc0e, 2, 4375}, /* ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM */ + {0xfc0f, 2, 4377}, /* ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc10, 2, 4379}, /* ARABIC LIGATURE TEH WITH YEH ISOLATED FORM */ + {0xfc11, 2, 4381}, /* ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM */ + {0xfc12, 2, 4383}, /* ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM */ + {0xfc13, 2, 4385}, /* ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc14, 2, 4387}, /* ARABIC LIGATURE THEH WITH YEH ISOLATED FORM */ + {0xfc15, 2, 4389}, /* ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM */ + {0xfc16, 2, 4391}, /* ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM */ + {0xfc17, 2, 4390}, /* ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM */ + {0xfc18, 2, 4393}, /* ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM */ + {0xfc19, 2, 4395}, /* ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM */ + {0xfc1a, 2, 4397}, /* ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM */ + {0xfc1b, 2, 4399}, /* ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM */ + {0xfc1c, 2, 4401}, /* ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM */ + {0xfc1d, 2, 4403}, /* ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM */ + {0xfc1e, 2, 4405}, /* ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM */ + {0xfc1f, 2, 4407}, /* ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM */ + {0xfc20, 2, 4409}, /* ARABIC LIGATURE SAD WITH HAH ISOLATED FORM */ + {0xfc21, 2, 4411}, /* ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM */ + {0xfc22, 2, 4413}, /* ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM */ + {0xfc23, 2, 4415}, /* ARABIC LIGATURE DAD WITH HAH ISOLATED FORM */ + {0xfc24, 2, 4417}, /* ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM */ + {0xfc25, 2, 4419}, /* ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM */ + {0xfc26, 2, 4421}, /* ARABIC LIGATURE TAH WITH HAH ISOLATED FORM */ + {0xfc27, 2, 4423}, /* ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM */ + {0xfc28, 2, 4425}, /* ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM */ + {0xfc29, 2, 4427}, /* ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM */ + {0xfc2a, 2, 4429}, /* ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM */ + {0xfc2b, 2, 4431}, /* ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM */ + {0xfc2c, 2, 4433}, /* ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM */ + {0xfc2d, 2, 4435}, /* ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM */ + {0xfc2e, 2, 4437}, /* ARABIC LIGATURE FEH WITH HAH ISOLATED FORM */ + {0xfc2f, 2, 4439}, /* ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM */ + {0xfc30, 2, 4441}, /* ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM */ + {0xfc31, 2, 4443}, /* ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc32, 2, 4445}, /* ARABIC LIGATURE FEH WITH YEH ISOLATED FORM */ + {0xfc33, 2, 4447}, /* ARABIC LIGATURE QAF WITH HAH ISOLATED FORM */ + {0xfc34, 2, 4449}, /* ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM */ + {0xfc35, 2, 4451}, /* ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc36, 2, 4453}, /* ARABIC LIGATURE QAF WITH YEH ISOLATED FORM */ + {0xfc37, 2, 4455}, /* ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM */ + {0xfc38, 2, 4457}, /* ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM */ + {0xfc39, 2, 4459}, /* ARABIC LIGATURE KAF WITH HAH ISOLATED FORM */ + {0xfc3a, 2, 4461}, /* ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM */ + {0xfc3b, 2, 4463}, /* ARABIC LIGATURE KAF WITH LAM ISOLATED FORM */ + {0xfc3c, 2, 4465}, /* ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM */ + {0xfc3d, 2, 4467}, /* ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc3e, 2, 4469}, /* ARABIC LIGATURE KAF WITH YEH ISOLATED FORM */ + {0xfc3f, 2, 4471}, /* ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM */ + {0xfc40, 2, 4473}, /* ARABIC LIGATURE LAM WITH HAH ISOLATED FORM */ + {0xfc41, 2, 4475}, /* ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM */ + {0xfc42, 2, 4477}, /* ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM */ + {0xfc43, 2, 4479}, /* ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc44, 2, 4481}, /* ARABIC LIGATURE LAM WITH YEH ISOLATED FORM */ + {0xfc45, 2, 4483}, /* ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM */ + {0xfc46, 2, 4392}, /* ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM */ + {0xfc47, 2, 4394}, /* ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM */ + {0xfc48, 2, 4485}, /* ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM */ + {0xfc49, 2, 4487}, /* ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc4a, 2, 4489}, /* ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM */ + {0xfc4b, 2, 4491}, /* ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM */ + {0xfc4c, 2, 4493}, /* ARABIC LIGATURE NOON WITH HAH ISOLATED FORM */ + {0xfc4d, 2, 4495}, /* ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM */ + {0xfc4e, 2, 4497}, /* ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM */ + {0xfc4f, 2, 4499}, /* ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc50, 2, 4501}, /* ARABIC LIGATURE NOON WITH YEH ISOLATED FORM */ + {0xfc51, 2, 4503}, /* ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM */ + {0xfc52, 2, 4505}, /* ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM */ + {0xfc53, 2, 4507}, /* ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc54, 2, 4509}, /* ARABIC LIGATURE HEH WITH YEH ISOLATED FORM */ + {0xfc55, 2, 4388}, /* ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM */ + {0xfc56, 2, 4511}, /* ARABIC LIGATURE YEH WITH HAH ISOLATED FORM */ + {0xfc57, 2, 4513}, /* ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM */ + {0xfc58, 2, 4482}, /* ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM */ + {0xfc59, 2, 4515}, /* ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM */ + {0xfc5a, 2, 4510}, /* ARABIC LIGATURE YEH WITH YEH ISOLATED FORM */ + {0xfc5b, 2, 4517}, /* ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM */ + {0xfc5c, 2, 4519}, /* ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM */ + {0xfc5d, 2, 4521}, /* ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM */ + {0xfc5e, 3, 4523}, /* ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM */ + {0xfc5f, 3, 4526}, /* ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM */ + {0xfc60, 3, 4529}, /* ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM */ + {0xfc61, 3, 4532}, /* ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM */ + {0xfc62, 3, 4535}, /* ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM */ + {0xfc63, 3, 4538}, /* ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM */ + {0xfc64, 2, 4541}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM */ + {0xfc65, 2, 4543}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM */ + {0xfc66, 2, 4353}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM */ + {0xfc67, 2, 4545}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM */ + {0xfc68, 2, 4346}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM */ + {0xfc69, 2, 4355}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM */ + {0xfc6a, 2, 4547}, /* ARABIC LIGATURE BEH WITH REH FINAL FORM */ + {0xfc6b, 2, 4549}, /* ARABIC LIGATURE BEH WITH ZAIN FINAL FORM */ + {0xfc6c, 2, 4363}, /* ARABIC LIGATURE BEH WITH MEEM FINAL FORM */ + {0xfc6d, 2, 4551}, /* ARABIC LIGATURE BEH WITH NOON FINAL FORM */ + {0xfc6e, 2, 4365}, /* ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM */ + {0xfc6f, 2, 4367}, /* ARABIC LIGATURE BEH WITH YEH FINAL FORM */ + {0xfc70, 2, 4553}, /* ARABIC LIGATURE TEH WITH REH FINAL FORM */ + {0xfc71, 2, 4555}, /* ARABIC LIGATURE TEH WITH ZAIN FINAL FORM */ + {0xfc72, 2, 4375}, /* ARABIC LIGATURE TEH WITH MEEM FINAL FORM */ + {0xfc73, 2, 4557}, /* ARABIC LIGATURE TEH WITH NOON FINAL FORM */ + {0xfc74, 2, 4377}, /* ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM */ + {0xfc75, 2, 4379}, /* ARABIC LIGATURE TEH WITH YEH FINAL FORM */ + {0xfc76, 2, 4559}, /* ARABIC LIGATURE THEH WITH REH FINAL FORM */ + {0xfc77, 2, 4561}, /* ARABIC LIGATURE THEH WITH ZAIN FINAL FORM */ + {0xfc78, 2, 4383}, /* ARABIC LIGATURE THEH WITH MEEM FINAL FORM */ + {0xfc79, 2, 4563}, /* ARABIC LIGATURE THEH WITH NOON FINAL FORM */ + {0xfc7a, 2, 4385}, /* ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM */ + {0xfc7b, 2, 4387}, /* ARABIC LIGATURE THEH WITH YEH FINAL FORM */ + {0xfc7c, 2, 4443}, /* ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM */ + {0xfc7d, 2, 4445}, /* ARABIC LIGATURE FEH WITH YEH FINAL FORM */ + {0xfc7e, 2, 4451}, /* ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM */ + {0xfc7f, 2, 4453}, /* ARABIC LIGATURE QAF WITH YEH FINAL FORM */ + {0xfc80, 2, 4455}, /* ARABIC LIGATURE KAF WITH ALEF FINAL FORM */ + {0xfc81, 2, 4463}, /* ARABIC LIGATURE KAF WITH LAM FINAL FORM */ + {0xfc82, 2, 4465}, /* ARABIC LIGATURE KAF WITH MEEM FINAL FORM */ + {0xfc83, 2, 4467}, /* ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM */ + {0xfc84, 2, 4469}, /* ARABIC LIGATURE KAF WITH YEH FINAL FORM */ + {0xfc85, 2, 4477}, /* ARABIC LIGATURE LAM WITH MEEM FINAL FORM */ + {0xfc86, 2, 4479}, /* ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM */ + {0xfc87, 2, 4481}, /* ARABIC LIGATURE LAM WITH YEH FINAL FORM */ + {0xfc88, 2, 4565}, /* ARABIC LIGATURE MEEM WITH ALEF FINAL FORM */ + {0xfc89, 2, 4485}, /* ARABIC LIGATURE MEEM WITH MEEM FINAL FORM */ + {0xfc8a, 2, 4567}, /* ARABIC LIGATURE NOON WITH REH FINAL FORM */ + {0xfc8b, 2, 4569}, /* ARABIC LIGATURE NOON WITH ZAIN FINAL FORM */ + {0xfc8c, 2, 4497}, /* ARABIC LIGATURE NOON WITH MEEM FINAL FORM */ + {0xfc8d, 2, 4571}, /* ARABIC LIGATURE NOON WITH NOON FINAL FORM */ + {0xfc8e, 2, 4499}, /* ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM */ + {0xfc8f, 2, 4501}, /* ARABIC LIGATURE NOON WITH YEH FINAL FORM */ + {0xfc90, 2, 4521}, /* ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM */ + {0xfc91, 2, 4573}, /* ARABIC LIGATURE YEH WITH REH FINAL FORM */ + {0xfc92, 2, 4575}, /* ARABIC LIGATURE YEH WITH ZAIN FINAL FORM */ + {0xfc93, 2, 4482}, /* ARABIC LIGATURE YEH WITH MEEM FINAL FORM */ + {0xfc94, 2, 4490}, /* ARABIC LIGATURE YEH WITH NOON FINAL FORM */ + {0xfc95, 2, 4515}, /* ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM */ + {0xfc96, 2, 4510}, /* ARABIC LIGATURE YEH WITH YEH FINAL FORM */ + {0xfc97, 2, 4349}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM */ + {0xfc98, 2, 4351}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM */ + {0xfc99, 2, 4577}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM */ + {0xfc9a, 2, 4353}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM */ + {0xfc9b, 2, 4579}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM */ + {0xfc9c, 2, 4357}, /* ARABIC LIGATURE BEH WITH JEEM INITIAL FORM */ + {0xfc9d, 2, 4359}, /* ARABIC LIGATURE BEH WITH HAH INITIAL FORM */ + {0xfc9e, 2, 4361}, /* ARABIC LIGATURE BEH WITH KHAH INITIAL FORM */ + {0xfc9f, 2, 4363}, /* ARABIC LIGATURE BEH WITH MEEM INITIAL FORM */ + {0xfca0, 2, 4581}, /* ARABIC LIGATURE BEH WITH HEH INITIAL FORM */ + {0xfca1, 2, 4369}, /* ARABIC LIGATURE TEH WITH JEEM INITIAL FORM */ + {0xfca2, 2, 4371}, /* ARABIC LIGATURE TEH WITH HAH INITIAL FORM */ + {0xfca3, 2, 4373}, /* ARABIC LIGATURE TEH WITH KHAH INITIAL FORM */ + {0xfca4, 2, 4375}, /* ARABIC LIGATURE TEH WITH MEEM INITIAL FORM */ + {0xfca5, 2, 4583}, /* ARABIC LIGATURE TEH WITH HEH INITIAL FORM */ + {0xfca6, 2, 4383}, /* ARABIC LIGATURE THEH WITH MEEM INITIAL FORM */ + {0xfca7, 2, 4389}, /* ARABIC LIGATURE JEEM WITH HAH INITIAL FORM */ + {0xfca8, 2, 4391}, /* ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM */ + {0xfca9, 2, 4390}, /* ARABIC LIGATURE HAH WITH JEEM INITIAL FORM */ + {0xfcaa, 2, 4393}, /* ARABIC LIGATURE HAH WITH MEEM INITIAL FORM */ + {0xfcab, 2, 4395}, /* ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM */ + {0xfcac, 2, 4399}, /* ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM */ + {0xfcad, 2, 4401}, /* ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM */ + {0xfcae, 2, 4403}, /* ARABIC LIGATURE SEEN WITH HAH INITIAL FORM */ + {0xfcaf, 2, 4405}, /* ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM */ + {0xfcb0, 2, 4407}, /* ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM */ + {0xfcb1, 2, 4409}, /* ARABIC LIGATURE SAD WITH HAH INITIAL FORM */ + {0xfcb2, 2, 4585}, /* ARABIC LIGATURE SAD WITH KHAH INITIAL FORM */ + {0xfcb3, 2, 4411}, /* ARABIC LIGATURE SAD WITH MEEM INITIAL FORM */ + {0xfcb4, 2, 4413}, /* ARABIC LIGATURE DAD WITH JEEM INITIAL FORM */ + {0xfcb5, 2, 4415}, /* ARABIC LIGATURE DAD WITH HAH INITIAL FORM */ + {0xfcb6, 2, 4417}, /* ARABIC LIGATURE DAD WITH KHAH INITIAL FORM */ + {0xfcb7, 2, 4419}, /* ARABIC LIGATURE DAD WITH MEEM INITIAL FORM */ + {0xfcb8, 2, 4421}, /* ARABIC LIGATURE TAH WITH HAH INITIAL FORM */ + {0xfcb9, 2, 4425}, /* ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM */ + {0xfcba, 2, 4427}, /* ARABIC LIGATURE AIN WITH JEEM INITIAL FORM */ + {0xfcbb, 2, 4429}, /* ARABIC LIGATURE AIN WITH MEEM INITIAL FORM */ + {0xfcbc, 2, 4431}, /* ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM */ + {0xfcbd, 2, 4433}, /* ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM */ + {0xfcbe, 2, 4435}, /* ARABIC LIGATURE FEH WITH JEEM INITIAL FORM */ + {0xfcbf, 2, 4437}, /* ARABIC LIGATURE FEH WITH HAH INITIAL FORM */ + {0xfcc0, 2, 4439}, /* ARABIC LIGATURE FEH WITH KHAH INITIAL FORM */ + {0xfcc1, 2, 4441}, /* ARABIC LIGATURE FEH WITH MEEM INITIAL FORM */ + {0xfcc2, 2, 4447}, /* ARABIC LIGATURE QAF WITH HAH INITIAL FORM */ + {0xfcc3, 2, 4449}, /* ARABIC LIGATURE QAF WITH MEEM INITIAL FORM */ + {0xfcc4, 2, 4457}, /* ARABIC LIGATURE KAF WITH JEEM INITIAL FORM */ + {0xfcc5, 2, 4459}, /* ARABIC LIGATURE KAF WITH HAH INITIAL FORM */ + {0xfcc6, 2, 4461}, /* ARABIC LIGATURE KAF WITH KHAH INITIAL FORM */ + {0xfcc7, 2, 4463}, /* ARABIC LIGATURE KAF WITH LAM INITIAL FORM */ + {0xfcc8, 2, 4465}, /* ARABIC LIGATURE KAF WITH MEEM INITIAL FORM */ + {0xfcc9, 2, 4471}, /* ARABIC LIGATURE LAM WITH JEEM INITIAL FORM */ + {0xfcca, 2, 4473}, /* ARABIC LIGATURE LAM WITH HAH INITIAL FORM */ + {0xfccb, 2, 4475}, /* ARABIC LIGATURE LAM WITH KHAH INITIAL FORM */ + {0xfccc, 2, 4477}, /* ARABIC LIGATURE LAM WITH MEEM INITIAL FORM */ + {0xfccd, 2, 4587}, /* ARABIC LIGATURE LAM WITH HEH INITIAL FORM */ + {0xfcce, 2, 4483}, /* ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM */ + {0xfccf, 2, 4392}, /* ARABIC LIGATURE MEEM WITH HAH INITIAL FORM */ + {0xfcd0, 2, 4394}, /* ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM */ + {0xfcd1, 2, 4485}, /* ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM */ + {0xfcd2, 2, 4491}, /* ARABIC LIGATURE NOON WITH JEEM INITIAL FORM */ + {0xfcd3, 2, 4493}, /* ARABIC LIGATURE NOON WITH HAH INITIAL FORM */ + {0xfcd4, 2, 4495}, /* ARABIC LIGATURE NOON WITH KHAH INITIAL FORM */ + {0xfcd5, 2, 4497}, /* ARABIC LIGATURE NOON WITH MEEM INITIAL FORM */ + {0xfcd6, 2, 4589}, /* ARABIC LIGATURE NOON WITH HEH INITIAL FORM */ + {0xfcd7, 2, 4503}, /* ARABIC LIGATURE HEH WITH JEEM INITIAL FORM */ + {0xfcd8, 2, 4505}, /* ARABIC LIGATURE HEH WITH MEEM INITIAL FORM */ + {0xfcd9, 2, 4591}, /* ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM */ + {0xfcda, 2, 4388}, /* ARABIC LIGATURE YEH WITH JEEM INITIAL FORM */ + {0xfcdb, 2, 4511}, /* ARABIC LIGATURE YEH WITH HAH INITIAL FORM */ + {0xfcdc, 2, 4513}, /* ARABIC LIGATURE YEH WITH KHAH INITIAL FORM */ + {0xfcdd, 2, 4482}, /* ARABIC LIGATURE YEH WITH MEEM INITIAL FORM */ + {0xfcde, 2, 4502}, /* ARABIC LIGATURE YEH WITH HEH INITIAL FORM */ + {0xfcdf, 2, 4353}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM */ + {0xfce0, 2, 4579}, /* ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM */ + {0xfce1, 2, 4363}, /* ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM */ + {0xfce2, 2, 4581}, /* ARABIC LIGATURE BEH WITH HEH MEDIAL FORM */ + {0xfce3, 2, 4375}, /* ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM */ + {0xfce4, 2, 4583}, /* ARABIC LIGATURE TEH WITH HEH MEDIAL FORM */ + {0xfce5, 2, 4383}, /* ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM */ + {0xfce6, 2, 4593}, /* ARABIC LIGATURE THEH WITH HEH MEDIAL FORM */ + {0xfce7, 2, 4407}, /* ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM */ + {0xfce8, 2, 4595}, /* ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM */ + {0xfce9, 2, 4597}, /* ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM */ + {0xfcea, 2, 4599}, /* ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM */ + {0xfceb, 2, 4463}, /* ARABIC LIGATURE KAF WITH LAM MEDIAL FORM */ + {0xfcec, 2, 4465}, /* ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM */ + {0xfced, 2, 4477}, /* ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM */ + {0xfcee, 2, 4497}, /* ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM */ + {0xfcef, 2, 4589}, /* ARABIC LIGATURE NOON WITH HEH MEDIAL FORM */ + {0xfcf0, 2, 4482}, /* ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM */ + {0xfcf1, 2, 4502}, /* ARABIC LIGATURE YEH WITH HEH MEDIAL FORM */ + {0xfcf2, 3, 4601}, /* ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM */ + {0xfcf3, 3, 4604}, /* ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM */ + {0xfcf4, 3, 4607}, /* ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM */ + {0xfcf5, 2, 4610}, /* ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM */ + {0xfcf6, 2, 4612}, /* ARABIC LIGATURE TAH WITH YEH ISOLATED FORM */ + {0xfcf7, 2, 4614}, /* ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM */ + {0xfcf8, 2, 4616}, /* ARABIC LIGATURE AIN WITH YEH ISOLATED FORM */ + {0xfcf9, 2, 4618}, /* ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM */ + {0xfcfa, 2, 4620}, /* ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM */ + {0xfcfb, 2, 4622}, /* ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM */ + {0xfcfc, 2, 4624}, /* ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM */ + {0xfcfd, 2, 4626}, /* ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM */ + {0xfcfe, 2, 4628}, /* ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM */ + {0xfcff, 2, 4630}, /* ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM */ + {0xfd00, 2, 4512}, /* ARABIC LIGATURE HAH WITH YEH ISOLATED FORM */ + {0xfd01, 2, 4632}, /* ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM */ + {0xfd02, 2, 4634}, /* ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM */ + {0xfd03, 2, 4636}, /* ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM */ + {0xfd04, 2, 4514}, /* ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM */ + {0xfd05, 2, 4638}, /* ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM */ + {0xfd06, 2, 4640}, /* ARABIC LIGATURE SAD WITH YEH ISOLATED FORM */ + {0xfd07, 2, 4642}, /* ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM */ + {0xfd08, 2, 4644}, /* ARABIC LIGATURE DAD WITH YEH ISOLATED FORM */ + {0xfd09, 2, 4646}, /* ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM */ + {0xfd0a, 2, 4648}, /* ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM */ + {0xfd0b, 2, 4650}, /* ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM */ + {0xfd0c, 2, 4597}, /* ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM */ + {0xfd0d, 2, 4652}, /* ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM */ + {0xfd0e, 2, 4654}, /* ARABIC LIGATURE SEEN WITH REH ISOLATED FORM */ + {0xfd0f, 2, 4656}, /* ARABIC LIGATURE SAD WITH REH ISOLATED FORM */ + {0xfd10, 2, 4658}, /* ARABIC LIGATURE DAD WITH REH ISOLATED FORM */ + {0xfd11, 2, 4610}, /* ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM */ + {0xfd12, 2, 4612}, /* ARABIC LIGATURE TAH WITH YEH FINAL FORM */ + {0xfd13, 2, 4614}, /* ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM */ + {0xfd14, 2, 4616}, /* ARABIC LIGATURE AIN WITH YEH FINAL FORM */ + {0xfd15, 2, 4618}, /* ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM */ + {0xfd16, 2, 4620}, /* ARABIC LIGATURE GHAIN WITH YEH FINAL FORM */ + {0xfd17, 2, 4622}, /* ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM */ + {0xfd18, 2, 4624}, /* ARABIC LIGATURE SEEN WITH YEH FINAL FORM */ + {0xfd19, 2, 4626}, /* ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM */ + {0xfd1a, 2, 4628}, /* ARABIC LIGATURE SHEEN WITH YEH FINAL FORM */ + {0xfd1b, 2, 4630}, /* ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM */ + {0xfd1c, 2, 4512}, /* ARABIC LIGATURE HAH WITH YEH FINAL FORM */ + {0xfd1d, 2, 4632}, /* ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM */ + {0xfd1e, 2, 4634}, /* ARABIC LIGATURE JEEM WITH YEH FINAL FORM */ + {0xfd1f, 2, 4636}, /* ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM */ + {0xfd20, 2, 4514}, /* ARABIC LIGATURE KHAH WITH YEH FINAL FORM */ + {0xfd21, 2, 4638}, /* ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM */ + {0xfd22, 2, 4640}, /* ARABIC LIGATURE SAD WITH YEH FINAL FORM */ + {0xfd23, 2, 4642}, /* ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM */ + {0xfd24, 2, 4644}, /* ARABIC LIGATURE DAD WITH YEH FINAL FORM */ + {0xfd25, 2, 4646}, /* ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM */ + {0xfd26, 2, 4648}, /* ARABIC LIGATURE SHEEN WITH HAH FINAL FORM */ + {0xfd27, 2, 4650}, /* ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM */ + {0xfd28, 2, 4597}, /* ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM */ + {0xfd29, 2, 4652}, /* ARABIC LIGATURE SHEEN WITH REH FINAL FORM */ + {0xfd2a, 2, 4654}, /* ARABIC LIGATURE SEEN WITH REH FINAL FORM */ + {0xfd2b, 2, 4656}, /* ARABIC LIGATURE SAD WITH REH FINAL FORM */ + {0xfd2c, 2, 4658}, /* ARABIC LIGATURE DAD WITH REH FINAL FORM */ + {0xfd2d, 2, 4646}, /* ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM */ + {0xfd2e, 2, 4648}, /* ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM */ + {0xfd2f, 2, 4650}, /* ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM */ + {0xfd30, 2, 4597}, /* ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM */ + {0xfd31, 2, 4595}, /* ARABIC LIGATURE SEEN WITH HEH INITIAL FORM */ + {0xfd32, 2, 4599}, /* ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM */ + {0xfd33, 2, 4423}, /* ARABIC LIGATURE TAH WITH MEEM INITIAL FORM */ + {0xfd34, 2, 4401}, /* ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM */ + {0xfd35, 2, 4403}, /* ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM */ + {0xfd36, 2, 4405}, /* ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM */ + {0xfd37, 2, 4646}, /* ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM */ + {0xfd38, 2, 4648}, /* ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM */ + {0xfd39, 2, 4650}, /* ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM */ + {0xfd3a, 2, 4423}, /* ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM */ + {0xfd3b, 2, 4425}, /* ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM */ + {0xfd3c, 2, 4660}, /* ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM */ + {0xfd3d, 2, 4660}, /* ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM */ + {0xfd50, 3, 4662}, /* ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM */ + {0xfd51, 3, 4665}, /* ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM */ + {0xfd52, 3, 4665}, /* ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM */ + {0xfd53, 3, 4668}, /* ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM */ + {0xfd54, 3, 4671}, /* ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM */ + {0xfd55, 3, 4674}, /* ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM */ + {0xfd56, 3, 4677}, /* ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM */ + {0xfd57, 3, 4680}, /* ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM */ + {0xfd58, 3, 4391}, /* ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM */ + {0xfd59, 3, 4391}, /* ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM */ + {0xfd5a, 3, 4683}, /* ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM */ + {0xfd5b, 3, 4686}, /* ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM */ + {0xfd5c, 3, 4689}, /* ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM */ + {0xfd5d, 3, 4692}, /* ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM */ + {0xfd5e, 3, 4695}, /* ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM */ + {0xfd5f, 3, 4698}, /* ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM */ + {0xfd60, 3, 4698}, /* ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM */ + {0xfd61, 3, 4701}, /* ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM */ + {0xfd62, 3, 4704}, /* ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM */ + {0xfd63, 3, 4704}, /* ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM */ + {0xfd64, 3, 4707}, /* ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM */ + {0xfd65, 3, 4707}, /* ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM */ + {0xfd66, 3, 4710}, /* ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM */ + {0xfd67, 3, 4713}, /* ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM */ + {0xfd68, 3, 4713}, /* ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM */ + {0xfd69, 3, 4716}, /* ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM */ + {0xfd6a, 3, 4719}, /* ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM */ + {0xfd6b, 3, 4719}, /* ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM */ + {0xfd6c, 3, 4722}, /* ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM */ + {0xfd6d, 3, 4722}, /* ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM */ + {0xfd6e, 3, 4725}, /* ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM */ + {0xfd6f, 3, 4728}, /* ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM */ + {0xfd70, 3, 4728}, /* ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM */ + {0xfd71, 3, 4731}, /* ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM */ + {0xfd72, 3, 4731}, /* ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM */ + {0xfd73, 3, 4734}, /* ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM */ + {0xfd74, 3, 4737}, /* ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM */ + {0xfd75, 3, 4740}, /* ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM */ + {0xfd76, 3, 4743}, /* ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM */ + {0xfd77, 3, 4743}, /* ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM */ + {0xfd78, 3, 4746}, /* ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM */ + {0xfd79, 3, 4749}, /* ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM */ + {0xfd7a, 3, 4752}, /* ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM */ + {0xfd7b, 3, 4755}, /* ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM */ + {0xfd7c, 3, 4758}, /* ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM */ + {0xfd7d, 3, 4758}, /* ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM */ + {0xfd7e, 3, 4761}, /* ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM */ + {0xfd7f, 3, 4764}, /* ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM */ + {0xfd80, 3, 4767}, /* ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM */ + {0xfd81, 3, 4770}, /* ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM */ + {0xfd82, 3, 4773}, /* ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM */ + {0xfd83, 3, 4776}, /* ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM */ + {0xfd84, 3, 4776}, /* ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM */ + {0xfd85, 3, 4779}, /* ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM */ + {0xfd86, 3, 4779}, /* ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM */ + {0xfd87, 3, 4782}, /* ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM */ + {0xfd88, 3, 4782}, /* ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM */ + {0xfd89, 3, 4785}, /* ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM */ + {0xfd8a, 3, 4392}, /* ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM */ + {0xfd8b, 3, 4788}, /* ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM */ + {0xfd8c, 3, 4791}, /* ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM */ + {0xfd8d, 3, 4483}, /* ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM */ + {0xfd8e, 3, 4394}, /* ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM */ + {0xfd8f, 3, 4794}, /* ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM */ + {0xfd92, 3, 4797}, /* ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM */ + {0xfd93, 3, 4800}, /* ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM */ + {0xfd94, 3, 4803}, /* ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM */ + {0xfd95, 3, 4806}, /* ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM */ + {0xfd96, 3, 4809}, /* ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM */ + {0xfd97, 3, 4812}, /* ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM */ + {0xfd98, 3, 4812}, /* ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM */ + {0xfd99, 3, 4815}, /* ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM */ + {0xfd9a, 3, 4818}, /* ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM */ + {0xfd9b, 3, 4821}, /* ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM */ + {0xfd9c, 3, 4824}, /* ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM */ + {0xfd9d, 3, 4824}, /* ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM */ + {0xfd9e, 3, 4827}, /* ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM */ + {0xfd9f, 3, 4830}, /* ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM */ + {0xfda0, 3, 4833}, /* ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM */ + {0xfda1, 3, 4836}, /* ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM */ + {0xfda2, 3, 4839}, /* ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM */ + {0xfda3, 3, 4842}, /* ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM */ + {0xfda4, 3, 4845}, /* ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM */ + {0xfda5, 3, 4848}, /* ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM */ + {0xfda6, 3, 4851}, /* ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM */ + {0xfda7, 3, 4854}, /* ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM */ + {0xfda8, 3, 4857}, /* ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM */ + {0xfda9, 3, 4860}, /* ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM */ + {0xfdaa, 3, 4863}, /* ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM */ + {0xfdab, 3, 4866}, /* ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM */ + {0xfdac, 3, 4869}, /* ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM */ + {0xfdad, 3, 4872}, /* ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM */ + {0xfdae, 3, 4511}, /* ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM */ + {0xfdaf, 3, 4875}, /* ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM */ + {0xfdb0, 3, 4878}, /* ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM */ + {0xfdb1, 3, 4881}, /* ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM */ + {0xfdb2, 3, 4884}, /* ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM */ + {0xfdb3, 3, 4887}, /* ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM */ + {0xfdb4, 3, 4761}, /* ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM */ + {0xfdb5, 3, 4767}, /* ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM */ + {0xfdb6, 3, 4890}, /* ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM */ + {0xfdb7, 3, 4893}, /* ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM */ + {0xfdb8, 3, 4896}, /* ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM */ + {0xfdb9, 3, 4899}, /* ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM */ + {0xfdba, 3, 4902}, /* ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM */ + {0xfdbb, 3, 4905}, /* ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM */ + {0xfdbc, 3, 4902}, /* ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM */ + {0xfdbd, 3, 4896}, /* ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM */ + {0xfdbe, 3, 4908}, /* ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM */ + {0xfdbf, 3, 4911}, /* ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM */ + {0xfdc0, 3, 4914}, /* ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM */ + {0xfdc1, 3, 4917}, /* ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM */ + {0xfdc2, 3, 4920}, /* ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM */ + {0xfdc3, 3, 4905}, /* ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM */ + {0xfdc4, 3, 4740}, /* ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM */ + {0xfdc5, 3, 4710}, /* ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM */ + {0xfdc6, 3, 4923}, /* ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM */ + {0xfdc7, 3, 4926}, /* ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM */ + {0xfdf0, 3, 4929}, /* ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM */ + {0xfdf1, 3, 4932}, /* ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM */ + {0xfdf2, 4, 4935}, /* ARABIC LIGATURE ALLAH ISOLATED FORM */ + {0xfdf3, 4, 4939}, /* ARABIC LIGATURE AKBAR ISOLATED FORM */ + {0xfdf4, 4, 4943}, /* ARABIC LIGATURE MOHAMMAD ISOLATED FORM */ + {0xfdf5, 4, 4947}, /* ARABIC LIGATURE SALAM ISOLATED FORM */ + {0xfdf6, 4, 4951}, /* ARABIC LIGATURE RASOUL ISOLATED FORM */ + {0xfdf7, 4, 4955}, /* ARABIC LIGATURE ALAYHE ISOLATED FORM */ + {0xfdf8, 4, 4959}, /* ARABIC LIGATURE WASALLAM ISOLATED FORM */ + {0xfdf9, 3, 4963}, /* ARABIC LIGATURE SALLA ISOLATED FORM */ + {0xfdfa, 18, 4966}, /* ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM */ + {0xfdfb, 8, 4984}, /* ARABIC LIGATURE JALLAJALALOUHOU */ + {0xfdfc, 4, 4992}, /* RIAL SIGN */ + {0xfe30, 1, 4996}, /* PRESENTATION FORM FOR VERTICAL TWO DOT LEADER */ + {0xfe31, 1, 4997}, /* PRESENTATION FORM FOR VERTICAL EM DASH */ + {0xfe32, 1, 4998}, /* PRESENTATION FORM FOR VERTICAL EN DASH */ + {0xfe33, 1, 4999}, /* PRESENTATION FORM FOR VERTICAL LOW LINE */ + {0xfe34, 1, 4999}, /* PRESENTATION FORM FOR VERTICAL WAVY LOW LINE */ + {0xfe35, 1, 1918}, /* PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS */ + {0xfe36, 1, 1919}, /* PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS */ + {0xfe37, 1, 5000}, /* PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET */ + {0xfe38, 1, 5001}, /* PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET */ + {0xfe39, 1, 5002}, /* PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET */ + {0xfe3a, 1, 5003}, /* PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET */ + {0xfe3b, 1, 5004}, /* PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET */ + {0xfe3c, 1, 5005}, /* PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET */ + {0xfe3d, 1, 5006}, /* PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET */ + {0xfe3e, 1, 5007}, /* PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET */ + {0xfe3f, 1, 2140}, /* PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET */ + {0xfe40, 1, 2141}, /* PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET */ + {0xfe41, 1, 5008}, /* PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET */ + {0xfe42, 1, 5009}, /* PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET */ + {0xfe43, 1, 5010}, /* PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET */ + {0xfe44, 1, 5011}, /* PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET */ + {0xfe47, 1, 5012}, /* PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET */ + {0xfe48, 1, 5013}, /* PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET */ + {0xfe49, 1, 5014}, /* DASHED OVERLINE */ + {0xfe4a, 1, 5014}, /* CENTRELINE OVERLINE */ + {0xfe4b, 1, 5014}, /* WAVY OVERLINE */ + {0xfe4c, 1, 5014}, /* DOUBLE WAVY OVERLINE */ + {0xfe4d, 1, 4999}, /* DASHED LOW LINE */ + {0xfe4e, 1, 4999}, /* CENTRELINE LOW LINE */ + {0xfe4f, 1, 4999}, /* WAVY LOW LINE */ + {0xfe50, 1, 5015}, /* SMALL COMMA */ + {0xfe51, 1, 5016}, /* SMALL IDEOGRAPHIC COMMA */ + {0xfe52, 1, 1884}, /* SMALL FULL STOP */ + {0xfe54, 1, 587}, /* SMALL SEMICOLON */ + {0xfe55, 1, 2364}, /* SMALL COLON */ + {0xfe56, 1, 1902}, /* SMALL QUESTION MARK */ + {0xfe57, 1, 1898}, /* SMALL EXCLAMATION MARK */ + {0xfe58, 1, 4997}, /* SMALL EM DASH */ + {0xfe59, 1, 1918}, /* SMALL LEFT PARENTHESIS */ + {0xfe5a, 1, 1919}, /* SMALL RIGHT PARENTHESIS */ + {0xfe5b, 1, 5000}, /* SMALL LEFT CURLY BRACKET */ + {0xfe5c, 1, 5001}, /* SMALL RIGHT CURLY BRACKET */ + {0xfe5d, 1, 5002}, /* SMALL LEFT TORTOISE SHELL BRACKET */ + {0xfe5e, 1, 5003}, /* SMALL RIGHT TORTOISE SHELL BRACKET */ + {0xfe5f, 1, 5017}, /* SMALL NUMBER SIGN */ + {0xfe60, 1, 5018}, /* SMALL AMPERSAND */ + {0xfe61, 1, 5019}, /* SMALL ASTERISK */ + {0xfe62, 1, 1915}, /* SMALL PLUS SIGN */ + {0xfe63, 1, 5020}, /* SMALL HYPHEN-MINUS */ + {0xfe64, 1, 2088}, /* SMALL LESS-THAN SIGN */ + {0xfe65, 1, 2090}, /* SMALL GREATER-THAN SIGN */ + {0xfe66, 1, 1917}, /* SMALL EQUALS SIGN */ + {0xfe68, 1, 5021}, /* SMALL REVERSE SOLIDUS */ + {0xfe69, 1, 5022}, /* SMALL DOLLAR SIGN */ + {0xfe6a, 1, 5023}, /* SMALL PERCENT SIGN */ + {0xfe6b, 1, 5024}, /* SMALL COMMERCIAL AT */ + {0xfe70, 2, 5025}, /* ARABIC FATHATAN ISOLATED FORM */ + {0xfe71, 2, 5027}, /* ARABIC TATWEEL WITH FATHATAN ABOVE */ + {0xfe72, 2, 4523}, /* ARABIC DAMMATAN ISOLATED FORM */ + {0xfe74, 2, 4526}, /* ARABIC KASRATAN ISOLATED FORM */ + {0xfe76, 2, 4529}, /* ARABIC FATHA ISOLATED FORM */ + {0xfe77, 2, 4601}, /* ARABIC FATHA MEDIAL FORM */ + {0xfe78, 2, 4532}, /* ARABIC DAMMA ISOLATED FORM */ + {0xfe79, 2, 4604}, /* ARABIC DAMMA MEDIAL FORM */ + {0xfe7a, 2, 4535}, /* ARABIC KASRA ISOLATED FORM */ + {0xfe7b, 2, 4607}, /* ARABIC KASRA MEDIAL FORM */ + {0xfe7c, 2, 4538}, /* ARABIC SHADDA ISOLATED FORM */ + {0xfe7d, 2, 5029}, /* ARABIC SHADDA MEDIAL FORM */ + {0xfe7e, 2, 5031}, /* ARABIC SUKUN ISOLATED FORM */ + {0xfe7f, 2, 5033}, /* ARABIC SUKUN MEDIAL FORM */ + {0xfe80, 1, 5035}, /* ARABIC LETTER HAMZA ISOLATED FORM */ + {0xfe81, 1, 5036}, /* ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM */ + {0xfe82, 1, 5036}, /* ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM */ + {0xfe83, 1, 5037}, /* ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM */ + {0xfe84, 1, 5037}, /* ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM */ + {0xfe85, 1, 5038}, /* ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM */ + {0xfe86, 1, 5038}, /* ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM */ + {0xfe87, 1, 5039}, /* ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM */ + {0xfe88, 1, 5039}, /* ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM */ + {0xfe89, 1, 4332}, /* ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM */ + {0xfe8a, 1, 4332}, /* ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM */ + {0xfe8b, 1, 4332}, /* ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM */ + {0xfe8c, 1, 4332}, /* ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM */ + {0xfe8d, 1, 749}, /* ARABIC LETTER ALEF ISOLATED FORM */ + {0xfe8e, 1, 749}, /* ARABIC LETTER ALEF FINAL FORM */ + {0xfe8f, 1, 4357}, /* ARABIC LETTER BEH ISOLATED FORM */ + {0xfe90, 1, 4357}, /* ARABIC LETTER BEH FINAL FORM */ + {0xfe91, 1, 4357}, /* ARABIC LETTER BEH INITIAL FORM */ + {0xfe92, 1, 4357}, /* ARABIC LETTER BEH MEDIAL FORM */ + {0xfe93, 1, 5040}, /* ARABIC LETTER TEH MARBUTA ISOLATED FORM */ + {0xfe94, 1, 5040}, /* ARABIC LETTER TEH MARBUTA FINAL FORM */ + {0xfe95, 1, 4369}, /* ARABIC LETTER TEH ISOLATED FORM */ + {0xfe96, 1, 4369}, /* ARABIC LETTER TEH FINAL FORM */ + {0xfe97, 1, 4369}, /* ARABIC LETTER TEH INITIAL FORM */ + {0xfe98, 1, 4369}, /* ARABIC LETTER TEH MEDIAL FORM */ + {0xfe99, 1, 4381}, /* ARABIC LETTER THEH ISOLATED FORM */ + {0xfe9a, 1, 4381}, /* ARABIC LETTER THEH FINAL FORM */ + {0xfe9b, 1, 4381}, /* ARABIC LETTER THEH INITIAL FORM */ + {0xfe9c, 1, 4381}, /* ARABIC LETTER THEH MEDIAL FORM */ + {0xfe9d, 1, 4350}, /* ARABIC LETTER JEEM ISOLATED FORM */ + {0xfe9e, 1, 4350}, /* ARABIC LETTER JEEM FINAL FORM */ + {0xfe9f, 1, 4350}, /* ARABIC LETTER JEEM INITIAL FORM */ + {0xfea0, 1, 4350}, /* ARABIC LETTER JEEM MEDIAL FORM */ + {0xfea1, 1, 4352}, /* ARABIC LETTER HAH ISOLATED FORM */ + {0xfea2, 1, 4352}, /* ARABIC LETTER HAH FINAL FORM */ + {0xfea3, 1, 4352}, /* ARABIC LETTER HAH INITIAL FORM */ + {0xfea4, 1, 4352}, /* ARABIC LETTER HAH MEDIAL FORM */ + {0xfea5, 1, 4362}, /* ARABIC LETTER KHAH ISOLATED FORM */ + {0xfea6, 1, 4362}, /* ARABIC LETTER KHAH FINAL FORM */ + {0xfea7, 1, 4362}, /* ARABIC LETTER KHAH INITIAL FORM */ + {0xfea8, 1, 4362}, /* ARABIC LETTER KHAH MEDIAL FORM */ + {0xfea9, 1, 4946}, /* ARABIC LETTER DAL ISOLATED FORM */ + {0xfeaa, 1, 4946}, /* ARABIC LETTER DAL FINAL FORM */ + {0xfeab, 1, 4517}, /* ARABIC LETTER THAL ISOLATED FORM */ + {0xfeac, 1, 4517}, /* ARABIC LETTER THAL FINAL FORM */ + {0xfead, 1, 4519}, /* ARABIC LETTER REH ISOLATED FORM */ + {0xfeae, 1, 4519}, /* ARABIC LETTER REH FINAL FORM */ + {0xfeaf, 1, 4544}, /* ARABIC LETTER ZAIN ISOLATED FORM */ + {0xfeb0, 1, 4544}, /* ARABIC LETTER ZAIN FINAL FORM */ + {0xfeb1, 1, 4401}, /* ARABIC LETTER SEEN ISOLATED FORM */ + {0xfeb2, 1, 4401}, /* ARABIC LETTER SEEN FINAL FORM */ + {0xfeb3, 1, 4401}, /* ARABIC LETTER SEEN INITIAL FORM */ + {0xfeb4, 1, 4401}, /* ARABIC LETTER SEEN MEDIAL FORM */ + {0xfeb5, 1, 4597}, /* ARABIC LETTER SHEEN ISOLATED FORM */ + {0xfeb6, 1, 4597}, /* ARABIC LETTER SHEEN FINAL FORM */ + {0xfeb7, 1, 4597}, /* ARABIC LETTER SHEEN INITIAL FORM */ + {0xfeb8, 1, 4597}, /* ARABIC LETTER SHEEN MEDIAL FORM */ + {0xfeb9, 1, 4409}, /* ARABIC LETTER SAD ISOLATED FORM */ + {0xfeba, 1, 4409}, /* ARABIC LETTER SAD FINAL FORM */ + {0xfebb, 1, 4409}, /* ARABIC LETTER SAD INITIAL FORM */ + {0xfebc, 1, 4409}, /* ARABIC LETTER SAD MEDIAL FORM */ + {0xfebd, 1, 4413}, /* ARABIC LETTER DAD ISOLATED FORM */ + {0xfebe, 1, 4413}, /* ARABIC LETTER DAD FINAL FORM */ + {0xfebf, 1, 4413}, /* ARABIC LETTER DAD INITIAL FORM */ + {0xfec0, 1, 4413}, /* ARABIC LETTER DAD MEDIAL FORM */ + {0xfec1, 1, 4421}, /* ARABIC LETTER TAH ISOLATED FORM */ + {0xfec2, 1, 4421}, /* ARABIC LETTER TAH FINAL FORM */ + {0xfec3, 1, 4421}, /* ARABIC LETTER TAH INITIAL FORM */ + {0xfec4, 1, 4421}, /* ARABIC LETTER TAH MEDIAL FORM */ + {0xfec5, 1, 4425}, /* ARABIC LETTER ZAH ISOLATED FORM */ + {0xfec6, 1, 4425}, /* ARABIC LETTER ZAH FINAL FORM */ + {0xfec7, 1, 4425}, /* ARABIC LETTER ZAH INITIAL FORM */ + {0xfec8, 1, 4425}, /* ARABIC LETTER ZAH MEDIAL FORM */ + {0xfec9, 1, 4427}, /* ARABIC LETTER AIN ISOLATED FORM */ + {0xfeca, 1, 4427}, /* ARABIC LETTER AIN FINAL FORM */ + {0xfecb, 1, 4427}, /* ARABIC LETTER AIN INITIAL FORM */ + {0xfecc, 1, 4427}, /* ARABIC LETTER AIN MEDIAL FORM */ + {0xfecd, 1, 4431}, /* ARABIC LETTER GHAIN ISOLATED FORM */ + {0xfece, 1, 4431}, /* ARABIC LETTER GHAIN FINAL FORM */ + {0xfecf, 1, 4431}, /* ARABIC LETTER GHAIN INITIAL FORM */ + {0xfed0, 1, 4431}, /* ARABIC LETTER GHAIN MEDIAL FORM */ + {0xfed1, 1, 4435}, /* ARABIC LETTER FEH ISOLATED FORM */ + {0xfed2, 1, 4435}, /* ARABIC LETTER FEH FINAL FORM */ + {0xfed3, 1, 4435}, /* ARABIC LETTER FEH INITIAL FORM */ + {0xfed4, 1, 4435}, /* ARABIC LETTER FEH MEDIAL FORM */ + {0xfed5, 1, 4447}, /* ARABIC LETTER QAF ISOLATED FORM */ + {0xfed6, 1, 4447}, /* ARABIC LETTER QAF FINAL FORM */ + {0xfed7, 1, 4447}, /* ARABIC LETTER QAF INITIAL FORM */ + {0xfed8, 1, 4447}, /* ARABIC LETTER QAF MEDIAL FORM */ + {0xfed9, 1, 4455}, /* ARABIC LETTER KAF ISOLATED FORM */ + {0xfeda, 1, 4455}, /* ARABIC LETTER KAF FINAL FORM */ + {0xfedb, 1, 4455}, /* ARABIC LETTER KAF INITIAL FORM */ + {0xfedc, 1, 4455}, /* ARABIC LETTER KAF MEDIAL FORM */ + {0xfedd, 1, 4464}, /* ARABIC LETTER LAM ISOLATED FORM */ + {0xfede, 1, 4464}, /* ARABIC LETTER LAM FINAL FORM */ + {0xfedf, 1, 4464}, /* ARABIC LETTER LAM INITIAL FORM */ + {0xfee0, 1, 4464}, /* ARABIC LETTER LAM MEDIAL FORM */ + {0xfee1, 1, 4354}, /* ARABIC LETTER MEEM ISOLATED FORM */ + {0xfee2, 1, 4354}, /* ARABIC LETTER MEEM FINAL FORM */ + {0xfee3, 1, 4354}, /* ARABIC LETTER MEEM INITIAL FORM */ + {0xfee4, 1, 4354}, /* ARABIC LETTER MEEM MEDIAL FORM */ + {0xfee5, 1, 4491}, /* ARABIC LETTER NOON ISOLATED FORM */ + {0xfee6, 1, 4491}, /* ARABIC LETTER NOON FINAL FORM */ + {0xfee7, 1, 4491}, /* ARABIC LETTER NOON INITIAL FORM */ + {0xfee8, 1, 4491}, /* ARABIC LETTER NOON MEDIAL FORM */ + {0xfee9, 1, 4503}, /* ARABIC LETTER HEH ISOLATED FORM */ + {0xfeea, 1, 4503}, /* ARABIC LETTER HEH FINAL FORM */ + {0xfeeb, 1, 4503}, /* ARABIC LETTER HEH INITIAL FORM */ + {0xfeec, 1, 4503}, /* ARABIC LETTER HEH MEDIAL FORM */ + {0xfeed, 1, 753}, /* ARABIC LETTER WAW ISOLATED FORM */ + {0xfeee, 1, 753}, /* ARABIC LETTER WAW FINAL FORM */ + {0xfeef, 1, 4331}, /* ARABIC LETTER ALEF MAKSURA ISOLATED FORM */ + {0xfef0, 1, 4331}, /* ARABIC LETTER ALEF MAKSURA FINAL FORM */ + {0xfef1, 1, 757}, /* ARABIC LETTER YEH ISOLATED FORM */ + {0xfef2, 1, 757}, /* ARABIC LETTER YEH FINAL FORM */ + {0xfef3, 1, 757}, /* ARABIC LETTER YEH INITIAL FORM */ + {0xfef4, 1, 757}, /* ARABIC LETTER YEH MEDIAL FORM */ + {0xfef5, 2, 5041}, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */ + {0xfef6, 2, 5041}, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */ + {0xfef7, 2, 5043}, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */ + {0xfef8, 2, 5043}, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */ + {0xfef9, 2, 5045}, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */ + {0xfefa, 2, 5045}, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */ + {0xfefb, 2, 4988}, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */ + {0xfefc, 2, 4988}, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */ + {0xff01, 1, 1898}, /* FULLWIDTH EXCLAMATION MARK */ + {0xff02, 1, 5047}, /* FULLWIDTH QUOTATION MARK */ + {0xff03, 1, 5017}, /* FULLWIDTH NUMBER SIGN */ + {0xff04, 1, 5022}, /* FULLWIDTH DOLLAR SIGN */ + {0xff05, 1, 5023}, /* FULLWIDTH PERCENT SIGN */ + {0xff06, 1, 5018}, /* FULLWIDTH AMPERSAND */ + {0xff07, 1, 5048}, /* FULLWIDTH APOSTROPHE */ + {0xff08, 1, 1918}, /* FULLWIDTH LEFT PARENTHESIS */ + {0xff09, 1, 1919}, /* FULLWIDTH RIGHT PARENTHESIS */ + {0xff0a, 1, 5019}, /* FULLWIDTH ASTERISK */ + {0xff0b, 1, 1915}, /* FULLWIDTH PLUS SIGN */ + {0xff0c, 1, 5015}, /* FULLWIDTH COMMA */ + {0xff0d, 1, 5020}, /* FULLWIDTH HYPHEN-MINUS */ + {0xff0e, 1, 1884}, /* FULLWIDTH FULL STOP */ + {0xff0f, 1, 1923}, /* FULLWIDTH SOLIDUS */ + {0xff10, 1, 1909}, /* FULLWIDTH DIGIT ZERO */ + {0xff11, 1, 13}, /* FULLWIDTH DIGIT ONE */ + {0xff12, 1, 6}, /* FULLWIDTH DIGIT TWO */ + {0xff13, 1, 7}, /* FULLWIDTH DIGIT THREE */ + {0xff14, 1, 17}, /* FULLWIDTH DIGIT FOUR */ + {0xff15, 1, 1910}, /* FULLWIDTH DIGIT FIVE */ + {0xff16, 1, 1911}, /* FULLWIDTH DIGIT SIX */ + {0xff17, 1, 1912}, /* FULLWIDTH DIGIT SEVEN */ + {0xff18, 1, 1913}, /* FULLWIDTH DIGIT EIGHT */ + {0xff19, 1, 1914}, /* FULLWIDTH DIGIT NINE */ + {0xff1a, 1, 2364}, /* FULLWIDTH COLON */ + {0xff1b, 1, 587}, /* FULLWIDTH SEMICOLON */ + {0xff1c, 1, 2088}, /* FULLWIDTH LESS-THAN SIGN */ + {0xff1d, 1, 1917}, /* FULLWIDTH EQUALS SIGN */ + {0xff1e, 1, 2090}, /* FULLWIDTH GREATER-THAN SIGN */ + {0xff1f, 1, 1902}, /* FULLWIDTH QUESTION MARK */ + {0xff20, 1, 5024}, /* FULLWIDTH COMMERCIAL AT */ + {0xff21, 1, 24}, /* FULLWIDTH LATIN CAPITAL LETTER A */ + {0xff22, 1, 910}, /* FULLWIDTH LATIN CAPITAL LETTER B */ + {0xff23, 1, 36}, /* FULLWIDTH LATIN CAPITAL LETTER C */ + {0xff24, 1, 158}, /* FULLWIDTH LATIN CAPITAL LETTER D */ + {0xff25, 1, 38}, /* FULLWIDTH LATIN CAPITAL LETTER E */ + {0xff26, 1, 995}, /* FULLWIDTH LATIN CAPITAL LETTER F */ + {0xff27, 1, 182}, /* FULLWIDTH LATIN CAPITAL LETTER G */ + {0xff28, 1, 198}, /* FULLWIDTH LATIN CAPITAL LETTER H */ + {0xff29, 1, 46}, /* FULLWIDTH LATIN CAPITAL LETTER I */ + {0xff2a, 1, 221}, /* FULLWIDTH LATIN CAPITAL LETTER J */ + {0xff2b, 1, 228}, /* FULLWIDTH LATIN CAPITAL LETTER K */ + {0xff2c, 1, 232}, /* FULLWIDTH LATIN CAPITAL LETTER L */ + {0xff2d, 1, 912}, /* FULLWIDTH LATIN CAPITAL LETTER M */ + {0xff2e, 1, 54}, /* FULLWIDTH LATIN CAPITAL LETTER N */ + {0xff2f, 1, 56}, /* FULLWIDTH LATIN CAPITAL LETTER O */ + {0xff30, 1, 914}, /* FULLWIDTH LATIN CAPITAL LETTER P */ + {0xff31, 1, 1942}, /* FULLWIDTH LATIN CAPITAL LETTER Q */ + {0xff32, 1, 274}, /* FULLWIDTH LATIN CAPITAL LETTER R */ + {0xff33, 1, 286}, /* FULLWIDTH LATIN CAPITAL LETTER S */ + {0xff34, 1, 302}, /* FULLWIDTH LATIN CAPITAL LETTER T */ + {0xff35, 1, 66}, /* FULLWIDTH LATIN CAPITAL LETTER U */ + {0xff36, 1, 1183}, /* FULLWIDTH LATIN CAPITAL LETTER V */ + {0xff37, 1, 334}, /* FULLWIDTH LATIN CAPITAL LETTER W */ + {0xff38, 1, 1211}, /* FULLWIDTH LATIN CAPITAL LETTER X */ + {0xff39, 1, 74}, /* FULLWIDTH LATIN CAPITAL LETTER Y */ + {0xff3a, 1, 344}, /* FULLWIDTH LATIN CAPITAL LETTER Z */ + {0xff3b, 1, 5012}, /* FULLWIDTH LEFT SQUARE BRACKET */ + {0xff3c, 1, 5021}, /* FULLWIDTH REVERSE SOLIDUS */ + {0xff3d, 1, 5013}, /* FULLWIDTH RIGHT SQUARE BRACKET */ + {0xff3e, 1, 5049}, /* FULLWIDTH CIRCUMFLEX ACCENT */ + {0xff3f, 1, 4999}, /* FULLWIDTH LOW LINE */ + {0xff40, 1, 1848}, /* FULLWIDTH GRAVE ACCENT */ + {0xff41, 1, 3}, /* FULLWIDTH LATIN SMALL LETTER A */ + {0xff42, 1, 918}, /* FULLWIDTH LATIN SMALL LETTER B */ + {0xff43, 1, 88}, /* FULLWIDTH LATIN SMALL LETTER C */ + {0xff44, 1, 160}, /* FULLWIDTH LATIN SMALL LETTER D */ + {0xff45, 1, 90}, /* FULLWIDTH LATIN SMALL LETTER E */ + {0xff46, 1, 997}, /* FULLWIDTH LATIN SMALL LETTER F */ + {0xff47, 1, 184}, /* FULLWIDTH LATIN SMALL LETTER G */ + {0xff48, 1, 200}, /* FULLWIDTH LATIN SMALL LETTER H */ + {0xff49, 1, 98}, /* FULLWIDTH LATIN SMALL LETTER I */ + {0xff4a, 1, 223}, /* FULLWIDTH LATIN SMALL LETTER J */ + {0xff4b, 1, 230}, /* FULLWIDTH LATIN SMALL LETTER K */ + {0xff4c, 1, 234}, /* FULLWIDTH LATIN SMALL LETTER L */ + {0xff4d, 1, 922}, /* FULLWIDTH LATIN SMALL LETTER M */ + {0xff4e, 1, 106}, /* FULLWIDTH LATIN SMALL LETTER N */ + {0xff4f, 1, 14}, /* FULLWIDTH LATIN SMALL LETTER O */ + {0xff50, 1, 927}, /* FULLWIDTH LATIN SMALL LETTER P */ + {0xff51, 1, 2335}, /* FULLWIDTH LATIN SMALL LETTER Q */ + {0xff52, 1, 276}, /* FULLWIDTH LATIN SMALL LETTER R */ + {0xff53, 1, 288}, /* FULLWIDTH LATIN SMALL LETTER S */ + {0xff54, 1, 304}, /* FULLWIDTH LATIN SMALL LETTER T */ + {0xff55, 1, 118}, /* FULLWIDTH LATIN SMALL LETTER U */ + {0xff56, 1, 930}, /* FULLWIDTH LATIN SMALL LETTER V */ + {0xff57, 1, 336}, /* FULLWIDTH LATIN SMALL LETTER W */ + {0xff58, 1, 579}, /* FULLWIDTH LATIN SMALL LETTER X */ + {0xff59, 1, 126}, /* FULLWIDTH LATIN SMALL LETTER Y */ + {0xff5a, 1, 346}, /* FULLWIDTH LATIN SMALL LETTER Z */ + {0xff5b, 1, 5000}, /* FULLWIDTH LEFT CURLY BRACKET */ + {0xff5c, 1, 5050}, /* FULLWIDTH VERTICAL LINE */ + {0xff5d, 1, 5001}, /* FULLWIDTH RIGHT CURLY BRACKET */ + {0xff5e, 1, 5051}, /* FULLWIDTH TILDE */ + {0xff5f, 1, 5052}, /* FULLWIDTH LEFT WHITE PARENTHESIS */ + {0xff60, 1, 5053}, /* FULLWIDTH RIGHT WHITE PARENTHESIS */ + {0xff61, 1, 5054}, /* HALFWIDTH IDEOGRAPHIC FULL STOP */ + {0xff62, 1, 5008}, /* HALFWIDTH LEFT CORNER BRACKET */ + {0xff63, 1, 5009}, /* HALFWIDTH RIGHT CORNER BRACKET */ + {0xff64, 1, 5016}, /* HALFWIDTH IDEOGRAPHIC COMMA */ + {0xff65, 1, 5055}, /* HALFWIDTH KATAKANA MIDDLE DOT */ + {0xff66, 1, 2709}, /* HALFWIDTH KATAKANA LETTER WO */ + {0xff67, 1, 3180}, /* HALFWIDTH KATAKANA LETTER SMALL A */ + {0xff68, 1, 3348}, /* HALFWIDTH KATAKANA LETTER SMALL I */ + {0xff69, 1, 5056}, /* HALFWIDTH KATAKANA LETTER SMALL U */ + {0xff6a, 1, 3354}, /* HALFWIDTH KATAKANA LETTER SMALL E */ + {0xff6b, 1, 3196}, /* HALFWIDTH KATAKANA LETTER SMALL O */ + {0xff6c, 1, 5057}, /* HALFWIDTH KATAKANA LETTER SMALL YA */ + {0xff6d, 1, 3236}, /* HALFWIDTH KATAKANA LETTER SMALL YU */ + {0xff6e, 1, 3415}, /* HALFWIDTH KATAKANA LETTER SMALL YO */ + {0xff6f, 1, 3218}, /* HALFWIDTH KATAKANA LETTER SMALL TU */ + {0xff70, 1, 3175}, /* HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK */ + {0xff71, 1, 3151}, /* HALFWIDTH KATAKANA LETTER A */ + {0xff72, 1, 3152}, /* HALFWIDTH KATAKANA LETTER I */ + {0xff73, 1, 2701}, /* HALFWIDTH KATAKANA LETTER U */ + {0xff74, 1, 3153}, /* HALFWIDTH KATAKANA LETTER E */ + {0xff75, 1, 3154}, /* HALFWIDTH KATAKANA LETTER O */ + {0xff76, 1, 2651}, /* HALFWIDTH KATAKANA LETTER KA */ + {0xff77, 1, 2653}, /* HALFWIDTH KATAKANA LETTER KI */ + {0xff78, 1, 2655}, /* HALFWIDTH KATAKANA LETTER KU */ + {0xff79, 1, 2657}, /* HALFWIDTH KATAKANA LETTER KE */ + {0xff7a, 1, 2659}, /* HALFWIDTH KATAKANA LETTER KO */ + {0xff7b, 1, 2661}, /* HALFWIDTH KATAKANA LETTER SA */ + {0xff7c, 1, 2663}, /* HALFWIDTH KATAKANA LETTER SI */ + {0xff7d, 1, 2665}, /* HALFWIDTH KATAKANA LETTER SU */ + {0xff7e, 1, 2667}, /* HALFWIDTH KATAKANA LETTER SE */ + {0xff7f, 1, 2669}, /* HALFWIDTH KATAKANA LETTER SO */ + {0xff80, 1, 2671}, /* HALFWIDTH KATAKANA LETTER TA */ + {0xff81, 1, 2673}, /* HALFWIDTH KATAKANA LETTER TI */ + {0xff82, 1, 2675}, /* HALFWIDTH KATAKANA LETTER TU */ + {0xff83, 1, 2677}, /* HALFWIDTH KATAKANA LETTER TE */ + {0xff84, 1, 2679}, /* HALFWIDTH KATAKANA LETTER TO */ + {0xff85, 1, 3155}, /* HALFWIDTH KATAKANA LETTER NA */ + {0xff86, 1, 3156}, /* HALFWIDTH KATAKANA LETTER NI */ + {0xff87, 1, 3157}, /* HALFWIDTH KATAKANA LETTER NU */ + {0xff88, 1, 3158}, /* HALFWIDTH KATAKANA LETTER NE */ + {0xff89, 1, 3159}, /* HALFWIDTH KATAKANA LETTER NO */ + {0xff8a, 1, 2681}, /* HALFWIDTH KATAKANA LETTER HA */ + {0xff8b, 1, 2685}, /* HALFWIDTH KATAKANA LETTER HI */ + {0xff8c, 1, 2689}, /* HALFWIDTH KATAKANA LETTER HU */ + {0xff8d, 1, 2693}, /* HALFWIDTH KATAKANA LETTER HE */ + {0xff8e, 1, 2697}, /* HALFWIDTH KATAKANA LETTER HO */ + {0xff8f, 1, 3160}, /* HALFWIDTH KATAKANA LETTER MA */ + {0xff90, 1, 3161}, /* HALFWIDTH KATAKANA LETTER MI */ + {0xff91, 1, 3162}, /* HALFWIDTH KATAKANA LETTER MU */ + {0xff92, 1, 3163}, /* HALFWIDTH KATAKANA LETTER ME */ + {0xff93, 1, 3164}, /* HALFWIDTH KATAKANA LETTER MO */ + {0xff94, 1, 3165}, /* HALFWIDTH KATAKANA LETTER YA */ + {0xff95, 1, 3166}, /* HALFWIDTH KATAKANA LETTER YU */ + {0xff96, 1, 3167}, /* HALFWIDTH KATAKANA LETTER YO */ + {0xff97, 1, 3168}, /* HALFWIDTH KATAKANA LETTER RA */ + {0xff98, 1, 3169}, /* HALFWIDTH KATAKANA LETTER RI */ + {0xff99, 1, 3170}, /* HALFWIDTH KATAKANA LETTER RU */ + {0xff9a, 1, 3171}, /* HALFWIDTH KATAKANA LETTER RE */ + {0xff9b, 1, 3172}, /* HALFWIDTH KATAKANA LETTER RO */ + {0xff9c, 1, 2703}, /* HALFWIDTH KATAKANA LETTER WA */ + {0xff9d, 1, 3182}, /* HALFWIDTH KATAKANA LETTER N */ + {0xff9e, 1, 2592}, /* HALFWIDTH KATAKANA VOICED SOUND MARK */ + {0xff9f, 1, 2624}, /* HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK */ + {0xffa0, 1, 5058}, /* HALFWIDTH HANGUL FILLER */ + {0xffa1, 1, 5059}, /* HALFWIDTH HANGUL LETTER KIYEOK */ + {0xffa2, 1, 5060}, /* HALFWIDTH HANGUL LETTER SSANGKIYEOK */ + {0xffa3, 1, 5061}, /* HALFWIDTH HANGUL LETTER KIYEOK-SIOS */ + {0xffa4, 1, 5062}, /* HALFWIDTH HANGUL LETTER NIEUN */ + {0xffa5, 1, 5063}, /* HALFWIDTH HANGUL LETTER NIEUN-CIEUC */ + {0xffa6, 1, 5064}, /* HALFWIDTH HANGUL LETTER NIEUN-HIEUH */ + {0xffa7, 1, 5065}, /* HALFWIDTH HANGUL LETTER TIKEUT */ + {0xffa8, 1, 5066}, /* HALFWIDTH HANGUL LETTER SSANGTIKEUT */ + {0xffa9, 1, 5067}, /* HALFWIDTH HANGUL LETTER RIEUL */ + {0xffaa, 1, 5068}, /* HALFWIDTH HANGUL LETTER RIEUL-KIYEOK */ + {0xffab, 1, 5069}, /* HALFWIDTH HANGUL LETTER RIEUL-MIEUM */ + {0xffac, 1, 5070}, /* HALFWIDTH HANGUL LETTER RIEUL-PIEUP */ + {0xffad, 1, 5071}, /* HALFWIDTH HANGUL LETTER RIEUL-SIOS */ + {0xffae, 1, 5072}, /* HALFWIDTH HANGUL LETTER RIEUL-THIEUTH */ + {0xffaf, 1, 5073}, /* HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH */ + {0xffb0, 1, 5074}, /* HALFWIDTH HANGUL LETTER RIEUL-HIEUH */ + {0xffb1, 1, 5075}, /* HALFWIDTH HANGUL LETTER MIEUM */ + {0xffb2, 1, 5076}, /* HALFWIDTH HANGUL LETTER PIEUP */ + {0xffb3, 1, 5077}, /* HALFWIDTH HANGUL LETTER SSANGPIEUP */ + {0xffb4, 1, 5078}, /* HALFWIDTH HANGUL LETTER PIEUP-SIOS */ + {0xffb5, 1, 5079}, /* HALFWIDTH HANGUL LETTER SIOS */ + {0xffb6, 1, 5080}, /* HALFWIDTH HANGUL LETTER SSANGSIOS */ + {0xffb7, 1, 5081}, /* HALFWIDTH HANGUL LETTER IEUNG */ + {0xffb8, 1, 5082}, /* HALFWIDTH HANGUL LETTER CIEUC */ + {0xffb9, 1, 5083}, /* HALFWIDTH HANGUL LETTER SSANGCIEUC */ + {0xffba, 1, 5084}, /* HALFWIDTH HANGUL LETTER CHIEUCH */ + {0xffbb, 1, 5085}, /* HALFWIDTH HANGUL LETTER KHIEUKH */ + {0xffbc, 1, 5086}, /* HALFWIDTH HANGUL LETTER THIEUTH */ + {0xffbd, 1, 5087}, /* HALFWIDTH HANGUL LETTER PHIEUPH */ + {0xffbe, 1, 5088}, /* HALFWIDTH HANGUL LETTER HIEUH */ + {0xffc2, 1, 5089}, /* HALFWIDTH HANGUL LETTER A */ + {0xffc3, 1, 5090}, /* HALFWIDTH HANGUL LETTER AE */ + {0xffc4, 1, 5091}, /* HALFWIDTH HANGUL LETTER YA */ + {0xffc5, 1, 5092}, /* HALFWIDTH HANGUL LETTER YAE */ + {0xffc6, 1, 5093}, /* HALFWIDTH HANGUL LETTER EO */ + {0xffc7, 1, 5094}, /* HALFWIDTH HANGUL LETTER E */ + {0xffca, 1, 5095}, /* HALFWIDTH HANGUL LETTER YEO */ + {0xffcb, 1, 5096}, /* HALFWIDTH HANGUL LETTER YE */ + {0xffcc, 1, 5097}, /* HALFWIDTH HANGUL LETTER O */ + {0xffcd, 1, 5098}, /* HALFWIDTH HANGUL LETTER WA */ + {0xffce, 1, 5099}, /* HALFWIDTH HANGUL LETTER WAE */ + {0xffcf, 1, 5100}, /* HALFWIDTH HANGUL LETTER OE */ + {0xffd2, 1, 5101}, /* HALFWIDTH HANGUL LETTER YO */ + {0xffd3, 1, 5102}, /* HALFWIDTH HANGUL LETTER U */ + {0xffd4, 1, 5103}, /* HALFWIDTH HANGUL LETTER WEO */ + {0xffd5, 1, 5104}, /* HALFWIDTH HANGUL LETTER WE */ + {0xffd6, 1, 5105}, /* HALFWIDTH HANGUL LETTER WI */ + {0xffd7, 1, 5106}, /* HALFWIDTH HANGUL LETTER YU */ + {0xffda, 1, 5107}, /* HALFWIDTH HANGUL LETTER EU */ + {0xffdb, 1, 5108}, /* HALFWIDTH HANGUL LETTER YI */ + {0xffdc, 1, 5109}, /* HALFWIDTH HANGUL LETTER I */ + {0xffe0, 1, 5110}, /* FULLWIDTH CENT SIGN */ + {0xffe1, 1, 5111}, /* FULLWIDTH POUND SIGN */ + {0xffe2, 1, 5112}, /* FULLWIDTH NOT SIGN */ + {0xffe3, 1, 5113}, /* FULLWIDTH MACRON */ + {0xffe4, 1, 5114}, /* FULLWIDTH BROKEN BAR */ + {0xffe5, 1, 5115}, /* FULLWIDTH YEN SIGN */ + {0xffe6, 1, 5116}, /* FULLWIDTH WON SIGN */ + {0xffe8, 1, 5117}, /* HALFWIDTH FORMS LIGHT VERTICAL */ + {0xffe9, 1, 2042}, /* HALFWIDTH LEFTWARDS ARROW */ + {0xffea, 1, 5118}, /* HALFWIDTH UPWARDS ARROW */ + {0xffeb, 1, 2044}, /* HALFWIDTH RIGHTWARDS ARROW */ + {0xffec, 1, 5119}, /* HALFWIDTH DOWNWARDS ARROW */ + {0xffed, 1, 5120}, /* HALFWIDTH BLACK SQUARE */ + {0xffee, 1, 5121}, /* HALFWIDTH WHITE CIRCLE */ + {0x1d15e, 2, 5122}, /* MUSICAL SYMBOL HALF NOTE */ + {0x1d15f, 2, 5124}, /* MUSICAL SYMBOL QUARTER NOTE */ + {0x1d160, 2, 5126}, /* MUSICAL SYMBOL EIGHTH NOTE */ + {0x1d161, 2, 5128}, /* MUSICAL SYMBOL SIXTEENTH NOTE */ + {0x1d162, 2, 5130}, /* MUSICAL SYMBOL THIRTY-SECOND NOTE */ + {0x1d163, 2, 5132}, /* MUSICAL SYMBOL SIXTY-FOURTH NOTE */ + {0x1d164, 2, 5134}, /* MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE */ + {0x1d1bb, 2, 5136}, /* MUSICAL SYMBOL MINIMA */ + {0x1d1bc, 2, 5138}, /* MUSICAL SYMBOL MINIMA BLACK */ + {0x1d1bd, 2, 5140}, /* MUSICAL SYMBOL SEMIMINIMA WHITE */ + {0x1d1be, 2, 5142}, /* MUSICAL SYMBOL SEMIMINIMA BLACK */ + {0x1d1bf, 2, 5144}, /* MUSICAL SYMBOL FUSA WHITE */ + {0x1d1c0, 2, 5146}, /* MUSICAL SYMBOL FUSA BLACK */ + {0x1d400, 1, 24}, /* MATHEMATICAL BOLD CAPITAL A */ + {0x1d401, 1, 910}, /* MATHEMATICAL BOLD CAPITAL B */ + {0x1d402, 1, 36}, /* MATHEMATICAL BOLD CAPITAL C */ + {0x1d403, 1, 158}, /* MATHEMATICAL BOLD CAPITAL D */ + {0x1d404, 1, 38}, /* MATHEMATICAL BOLD CAPITAL E */ + {0x1d405, 1, 995}, /* MATHEMATICAL BOLD CAPITAL F */ + {0x1d406, 1, 182}, /* MATHEMATICAL BOLD CAPITAL G */ + {0x1d407, 1, 198}, /* MATHEMATICAL BOLD CAPITAL H */ + {0x1d408, 1, 46}, /* MATHEMATICAL BOLD CAPITAL I */ + {0x1d409, 1, 221}, /* MATHEMATICAL BOLD CAPITAL J */ + {0x1d40a, 1, 228}, /* MATHEMATICAL BOLD CAPITAL K */ + {0x1d40b, 1, 232}, /* MATHEMATICAL BOLD CAPITAL L */ + {0x1d40c, 1, 912}, /* MATHEMATICAL BOLD CAPITAL M */ + {0x1d40d, 1, 54}, /* MATHEMATICAL BOLD CAPITAL N */ + {0x1d40e, 1, 56}, /* MATHEMATICAL BOLD CAPITAL O */ + {0x1d40f, 1, 914}, /* MATHEMATICAL BOLD CAPITAL P */ + {0x1d410, 1, 1942}, /* MATHEMATICAL BOLD CAPITAL Q */ + {0x1d411, 1, 274}, /* MATHEMATICAL BOLD CAPITAL R */ + {0x1d412, 1, 286}, /* MATHEMATICAL BOLD CAPITAL S */ + {0x1d413, 1, 302}, /* MATHEMATICAL BOLD CAPITAL T */ + {0x1d414, 1, 66}, /* MATHEMATICAL BOLD CAPITAL U */ + {0x1d415, 1, 1183}, /* MATHEMATICAL BOLD CAPITAL V */ + {0x1d416, 1, 334}, /* MATHEMATICAL BOLD CAPITAL W */ + {0x1d417, 1, 1211}, /* MATHEMATICAL BOLD CAPITAL X */ + {0x1d418, 1, 74}, /* MATHEMATICAL BOLD CAPITAL Y */ + {0x1d419, 1, 344}, /* MATHEMATICAL BOLD CAPITAL Z */ + {0x1d41a, 1, 3}, /* MATHEMATICAL BOLD SMALL A */ + {0x1d41b, 1, 918}, /* MATHEMATICAL BOLD SMALL B */ + {0x1d41c, 1, 88}, /* MATHEMATICAL BOLD SMALL C */ + {0x1d41d, 1, 160}, /* MATHEMATICAL BOLD SMALL D */ + {0x1d41e, 1, 90}, /* MATHEMATICAL BOLD SMALL E */ + {0x1d41f, 1, 997}, /* MATHEMATICAL BOLD SMALL F */ + {0x1d420, 1, 184}, /* MATHEMATICAL BOLD SMALL G */ + {0x1d421, 1, 200}, /* MATHEMATICAL BOLD SMALL H */ + {0x1d422, 1, 98}, /* MATHEMATICAL BOLD SMALL I */ + {0x1d423, 1, 223}, /* MATHEMATICAL BOLD SMALL J */ + {0x1d424, 1, 230}, /* MATHEMATICAL BOLD SMALL K */ + {0x1d425, 1, 234}, /* MATHEMATICAL BOLD SMALL L */ + {0x1d426, 1, 922}, /* MATHEMATICAL BOLD SMALL M */ + {0x1d427, 1, 106}, /* MATHEMATICAL BOLD SMALL N */ + {0x1d428, 1, 14}, /* MATHEMATICAL BOLD SMALL O */ + {0x1d429, 1, 927}, /* MATHEMATICAL BOLD SMALL P */ + {0x1d42a, 1, 2335}, /* MATHEMATICAL BOLD SMALL Q */ + {0x1d42b, 1, 276}, /* MATHEMATICAL BOLD SMALL R */ + {0x1d42c, 1, 288}, /* MATHEMATICAL BOLD SMALL S */ + {0x1d42d, 1, 304}, /* MATHEMATICAL BOLD SMALL T */ + {0x1d42e, 1, 118}, /* MATHEMATICAL BOLD SMALL U */ + {0x1d42f, 1, 930}, /* MATHEMATICAL BOLD SMALL V */ + {0x1d430, 1, 336}, /* MATHEMATICAL BOLD SMALL W */ + {0x1d431, 1, 579}, /* MATHEMATICAL BOLD SMALL X */ + {0x1d432, 1, 126}, /* MATHEMATICAL BOLD SMALL Y */ + {0x1d433, 1, 346}, /* MATHEMATICAL BOLD SMALL Z */ + {0x1d434, 1, 24}, /* MATHEMATICAL ITALIC CAPITAL A */ + {0x1d435, 1, 910}, /* MATHEMATICAL ITALIC CAPITAL B */ + {0x1d436, 1, 36}, /* MATHEMATICAL ITALIC CAPITAL C */ + {0x1d437, 1, 158}, /* MATHEMATICAL ITALIC CAPITAL D */ + {0x1d438, 1, 38}, /* MATHEMATICAL ITALIC CAPITAL E */ + {0x1d439, 1, 995}, /* MATHEMATICAL ITALIC CAPITAL F */ + {0x1d43a, 1, 182}, /* MATHEMATICAL ITALIC CAPITAL G */ + {0x1d43b, 1, 198}, /* MATHEMATICAL ITALIC CAPITAL H */ + {0x1d43c, 1, 46}, /* MATHEMATICAL ITALIC CAPITAL I */ + {0x1d43d, 1, 221}, /* MATHEMATICAL ITALIC CAPITAL J */ + {0x1d43e, 1, 228}, /* MATHEMATICAL ITALIC CAPITAL K */ + {0x1d43f, 1, 232}, /* MATHEMATICAL ITALIC CAPITAL L */ + {0x1d440, 1, 912}, /* MATHEMATICAL ITALIC CAPITAL M */ + {0x1d441, 1, 54}, /* MATHEMATICAL ITALIC CAPITAL N */ + {0x1d442, 1, 56}, /* MATHEMATICAL ITALIC CAPITAL O */ + {0x1d443, 1, 914}, /* MATHEMATICAL ITALIC CAPITAL P */ + {0x1d444, 1, 1942}, /* MATHEMATICAL ITALIC CAPITAL Q */ + {0x1d445, 1, 274}, /* MATHEMATICAL ITALIC CAPITAL R */ + {0x1d446, 1, 286}, /* MATHEMATICAL ITALIC CAPITAL S */ + {0x1d447, 1, 302}, /* MATHEMATICAL ITALIC CAPITAL T */ + {0x1d448, 1, 66}, /* MATHEMATICAL ITALIC CAPITAL U */ + {0x1d449, 1, 1183}, /* MATHEMATICAL ITALIC CAPITAL V */ + {0x1d44a, 1, 334}, /* MATHEMATICAL ITALIC CAPITAL W */ + {0x1d44b, 1, 1211}, /* MATHEMATICAL ITALIC CAPITAL X */ + {0x1d44c, 1, 74}, /* MATHEMATICAL ITALIC CAPITAL Y */ + {0x1d44d, 1, 344}, /* MATHEMATICAL ITALIC CAPITAL Z */ + {0x1d44e, 1, 3}, /* MATHEMATICAL ITALIC SMALL A */ + {0x1d44f, 1, 918}, /* MATHEMATICAL ITALIC SMALL B */ + {0x1d450, 1, 88}, /* MATHEMATICAL ITALIC SMALL C */ + {0x1d451, 1, 160}, /* MATHEMATICAL ITALIC SMALL D */ + {0x1d452, 1, 90}, /* MATHEMATICAL ITALIC SMALL E */ + {0x1d453, 1, 997}, /* MATHEMATICAL ITALIC SMALL F */ + {0x1d454, 1, 184}, /* MATHEMATICAL ITALIC SMALL G */ + {0x1d456, 1, 98}, /* MATHEMATICAL ITALIC SMALL I */ + {0x1d457, 1, 223}, /* MATHEMATICAL ITALIC SMALL J */ + {0x1d458, 1, 230}, /* MATHEMATICAL ITALIC SMALL K */ + {0x1d459, 1, 234}, /* MATHEMATICAL ITALIC SMALL L */ + {0x1d45a, 1, 922}, /* MATHEMATICAL ITALIC SMALL M */ + {0x1d45b, 1, 106}, /* MATHEMATICAL ITALIC SMALL N */ + {0x1d45c, 1, 14}, /* MATHEMATICAL ITALIC SMALL O */ + {0x1d45d, 1, 927}, /* MATHEMATICAL ITALIC SMALL P */ + {0x1d45e, 1, 2335}, /* MATHEMATICAL ITALIC SMALL Q */ + {0x1d45f, 1, 276}, /* MATHEMATICAL ITALIC SMALL R */ + {0x1d460, 1, 288}, /* MATHEMATICAL ITALIC SMALL S */ + {0x1d461, 1, 304}, /* MATHEMATICAL ITALIC SMALL T */ + {0x1d462, 1, 118}, /* MATHEMATICAL ITALIC SMALL U */ + {0x1d463, 1, 930}, /* MATHEMATICAL ITALIC SMALL V */ + {0x1d464, 1, 336}, /* MATHEMATICAL ITALIC SMALL W */ + {0x1d465, 1, 579}, /* MATHEMATICAL ITALIC SMALL X */ + {0x1d466, 1, 126}, /* MATHEMATICAL ITALIC SMALL Y */ + {0x1d467, 1, 346}, /* MATHEMATICAL ITALIC SMALL Z */ + {0x1d468, 1, 24}, /* MATHEMATICAL BOLD ITALIC CAPITAL A */ + {0x1d469, 1, 910}, /* MATHEMATICAL BOLD ITALIC CAPITAL B */ + {0x1d46a, 1, 36}, /* MATHEMATICAL BOLD ITALIC CAPITAL C */ + {0x1d46b, 1, 158}, /* MATHEMATICAL BOLD ITALIC CAPITAL D */ + {0x1d46c, 1, 38}, /* MATHEMATICAL BOLD ITALIC CAPITAL E */ + {0x1d46d, 1, 995}, /* MATHEMATICAL BOLD ITALIC CAPITAL F */ + {0x1d46e, 1, 182}, /* MATHEMATICAL BOLD ITALIC CAPITAL G */ + {0x1d46f, 1, 198}, /* MATHEMATICAL BOLD ITALIC CAPITAL H */ + {0x1d470, 1, 46}, /* MATHEMATICAL BOLD ITALIC CAPITAL I */ + {0x1d471, 1, 221}, /* MATHEMATICAL BOLD ITALIC CAPITAL J */ + {0x1d472, 1, 228}, /* MATHEMATICAL BOLD ITALIC CAPITAL K */ + {0x1d473, 1, 232}, /* MATHEMATICAL BOLD ITALIC CAPITAL L */ + {0x1d474, 1, 912}, /* MATHEMATICAL BOLD ITALIC CAPITAL M */ + {0x1d475, 1, 54}, /* MATHEMATICAL BOLD ITALIC CAPITAL N */ + {0x1d476, 1, 56}, /* MATHEMATICAL BOLD ITALIC CAPITAL O */ + {0x1d477, 1, 914}, /* MATHEMATICAL BOLD ITALIC CAPITAL P */ + {0x1d478, 1, 1942}, /* MATHEMATICAL BOLD ITALIC CAPITAL Q */ + {0x1d479, 1, 274}, /* MATHEMATICAL BOLD ITALIC CAPITAL R */ + {0x1d47a, 1, 286}, /* MATHEMATICAL BOLD ITALIC CAPITAL S */ + {0x1d47b, 1, 302}, /* MATHEMATICAL BOLD ITALIC CAPITAL T */ + {0x1d47c, 1, 66}, /* MATHEMATICAL BOLD ITALIC CAPITAL U */ + {0x1d47d, 1, 1183}, /* MATHEMATICAL BOLD ITALIC CAPITAL V */ + {0x1d47e, 1, 334}, /* MATHEMATICAL BOLD ITALIC CAPITAL W */ + {0x1d47f, 1, 1211}, /* MATHEMATICAL BOLD ITALIC CAPITAL X */ + {0x1d480, 1, 74}, /* MATHEMATICAL BOLD ITALIC CAPITAL Y */ + {0x1d481, 1, 344}, /* MATHEMATICAL BOLD ITALIC CAPITAL Z */ + {0x1d482, 1, 3}, /* MATHEMATICAL BOLD ITALIC SMALL A */ + {0x1d483, 1, 918}, /* MATHEMATICAL BOLD ITALIC SMALL B */ + {0x1d484, 1, 88}, /* MATHEMATICAL BOLD ITALIC SMALL C */ + {0x1d485, 1, 160}, /* MATHEMATICAL BOLD ITALIC SMALL D */ + {0x1d486, 1, 90}, /* MATHEMATICAL BOLD ITALIC SMALL E */ + {0x1d487, 1, 997}, /* MATHEMATICAL BOLD ITALIC SMALL F */ + {0x1d488, 1, 184}, /* MATHEMATICAL BOLD ITALIC SMALL G */ + {0x1d489, 1, 200}, /* MATHEMATICAL BOLD ITALIC SMALL H */ + {0x1d48a, 1, 98}, /* MATHEMATICAL BOLD ITALIC SMALL I */ + {0x1d48b, 1, 223}, /* MATHEMATICAL BOLD ITALIC SMALL J */ + {0x1d48c, 1, 230}, /* MATHEMATICAL BOLD ITALIC SMALL K */ + {0x1d48d, 1, 234}, /* MATHEMATICAL BOLD ITALIC SMALL L */ + {0x1d48e, 1, 922}, /* MATHEMATICAL BOLD ITALIC SMALL M */ + {0x1d48f, 1, 106}, /* MATHEMATICAL BOLD ITALIC SMALL N */ + {0x1d490, 1, 14}, /* MATHEMATICAL BOLD ITALIC SMALL O */ + {0x1d491, 1, 927}, /* MATHEMATICAL BOLD ITALIC SMALL P */ + {0x1d492, 1, 2335}, /* MATHEMATICAL BOLD ITALIC SMALL Q */ + {0x1d493, 1, 276}, /* MATHEMATICAL BOLD ITALIC SMALL R */ + {0x1d494, 1, 288}, /* MATHEMATICAL BOLD ITALIC SMALL S */ + {0x1d495, 1, 304}, /* MATHEMATICAL BOLD ITALIC SMALL T */ + {0x1d496, 1, 118}, /* MATHEMATICAL BOLD ITALIC SMALL U */ + {0x1d497, 1, 930}, /* MATHEMATICAL BOLD ITALIC SMALL V */ + {0x1d498, 1, 336}, /* MATHEMATICAL BOLD ITALIC SMALL W */ + {0x1d499, 1, 579}, /* MATHEMATICAL BOLD ITALIC SMALL X */ + {0x1d49a, 1, 126}, /* MATHEMATICAL BOLD ITALIC SMALL Y */ + {0x1d49b, 1, 346}, /* MATHEMATICAL BOLD ITALIC SMALL Z */ + {0x1d49c, 1, 24}, /* MATHEMATICAL SCRIPT CAPITAL A */ + {0x1d49e, 1, 36}, /* MATHEMATICAL SCRIPT CAPITAL C */ + {0x1d49f, 1, 158}, /* MATHEMATICAL SCRIPT CAPITAL D */ + {0x1d4a2, 1, 182}, /* MATHEMATICAL SCRIPT CAPITAL G */ + {0x1d4a5, 1, 221}, /* MATHEMATICAL SCRIPT CAPITAL J */ + {0x1d4a6, 1, 228}, /* MATHEMATICAL SCRIPT CAPITAL K */ + {0x1d4a9, 1, 54}, /* MATHEMATICAL SCRIPT CAPITAL N */ + {0x1d4aa, 1, 56}, /* MATHEMATICAL SCRIPT CAPITAL O */ + {0x1d4ab, 1, 914}, /* MATHEMATICAL SCRIPT CAPITAL P */ + {0x1d4ac, 1, 1942}, /* MATHEMATICAL SCRIPT CAPITAL Q */ + {0x1d4ae, 1, 286}, /* MATHEMATICAL SCRIPT CAPITAL S */ + {0x1d4af, 1, 302}, /* MATHEMATICAL SCRIPT CAPITAL T */ + {0x1d4b0, 1, 66}, /* MATHEMATICAL SCRIPT CAPITAL U */ + {0x1d4b1, 1, 1183}, /* MATHEMATICAL SCRIPT CAPITAL V */ + {0x1d4b2, 1, 334}, /* MATHEMATICAL SCRIPT CAPITAL W */ + {0x1d4b3, 1, 1211}, /* MATHEMATICAL SCRIPT CAPITAL X */ + {0x1d4b4, 1, 74}, /* MATHEMATICAL SCRIPT CAPITAL Y */ + {0x1d4b5, 1, 344}, /* MATHEMATICAL SCRIPT CAPITAL Z */ + {0x1d4b6, 1, 3}, /* MATHEMATICAL SCRIPT SMALL A */ + {0x1d4b7, 1, 918}, /* MATHEMATICAL SCRIPT SMALL B */ + {0x1d4b8, 1, 88}, /* MATHEMATICAL SCRIPT SMALL C */ + {0x1d4b9, 1, 160}, /* MATHEMATICAL SCRIPT SMALL D */ + {0x1d4bb, 1, 997}, /* MATHEMATICAL SCRIPT SMALL F */ + {0x1d4bd, 1, 200}, /* MATHEMATICAL SCRIPT SMALL H */ + {0x1d4be, 1, 98}, /* MATHEMATICAL SCRIPT SMALL I */ + {0x1d4bf, 1, 223}, /* MATHEMATICAL SCRIPT SMALL J */ + {0x1d4c0, 1, 230}, /* MATHEMATICAL SCRIPT SMALL K */ + {0x1d4c1, 1, 234}, /* MATHEMATICAL SCRIPT SMALL L */ + {0x1d4c2, 1, 922}, /* MATHEMATICAL SCRIPT SMALL M */ + {0x1d4c3, 1, 106}, /* MATHEMATICAL SCRIPT SMALL N */ + {0x1d4c5, 1, 927}, /* MATHEMATICAL SCRIPT SMALL P */ + {0x1d4c6, 1, 2335}, /* MATHEMATICAL SCRIPT SMALL Q */ + {0x1d4c7, 1, 276}, /* MATHEMATICAL SCRIPT SMALL R */ + {0x1d4c8, 1, 288}, /* MATHEMATICAL SCRIPT SMALL S */ + {0x1d4c9, 1, 304}, /* MATHEMATICAL SCRIPT SMALL T */ + {0x1d4ca, 1, 118}, /* MATHEMATICAL SCRIPT SMALL U */ + {0x1d4cb, 1, 930}, /* MATHEMATICAL SCRIPT SMALL V */ + {0x1d4cc, 1, 336}, /* MATHEMATICAL SCRIPT SMALL W */ + {0x1d4cd, 1, 579}, /* MATHEMATICAL SCRIPT SMALL X */ + {0x1d4ce, 1, 126}, /* MATHEMATICAL SCRIPT SMALL Y */ + {0x1d4cf, 1, 346}, /* MATHEMATICAL SCRIPT SMALL Z */ + {0x1d4d0, 1, 24}, /* MATHEMATICAL BOLD SCRIPT CAPITAL A */ + {0x1d4d1, 1, 910}, /* MATHEMATICAL BOLD SCRIPT CAPITAL B */ + {0x1d4d2, 1, 36}, /* MATHEMATICAL BOLD SCRIPT CAPITAL C */ + {0x1d4d3, 1, 158}, /* MATHEMATICAL BOLD SCRIPT CAPITAL D */ + {0x1d4d4, 1, 38}, /* MATHEMATICAL BOLD SCRIPT CAPITAL E */ + {0x1d4d5, 1, 995}, /* MATHEMATICAL BOLD SCRIPT CAPITAL F */ + {0x1d4d6, 1, 182}, /* MATHEMATICAL BOLD SCRIPT CAPITAL G */ + {0x1d4d7, 1, 198}, /* MATHEMATICAL BOLD SCRIPT CAPITAL H */ + {0x1d4d8, 1, 46}, /* MATHEMATICAL BOLD SCRIPT CAPITAL I */ + {0x1d4d9, 1, 221}, /* MATHEMATICAL BOLD SCRIPT CAPITAL J */ + {0x1d4da, 1, 228}, /* MATHEMATICAL BOLD SCRIPT CAPITAL K */ + {0x1d4db, 1, 232}, /* MATHEMATICAL BOLD SCRIPT CAPITAL L */ + {0x1d4dc, 1, 912}, /* MATHEMATICAL BOLD SCRIPT CAPITAL M */ + {0x1d4dd, 1, 54}, /* MATHEMATICAL BOLD SCRIPT CAPITAL N */ + {0x1d4de, 1, 56}, /* MATHEMATICAL BOLD SCRIPT CAPITAL O */ + {0x1d4df, 1, 914}, /* MATHEMATICAL BOLD SCRIPT CAPITAL P */ + {0x1d4e0, 1, 1942}, /* MATHEMATICAL BOLD SCRIPT CAPITAL Q */ + {0x1d4e1, 1, 274}, /* MATHEMATICAL BOLD SCRIPT CAPITAL R */ + {0x1d4e2, 1, 286}, /* MATHEMATICAL BOLD SCRIPT CAPITAL S */ + {0x1d4e3, 1, 302}, /* MATHEMATICAL BOLD SCRIPT CAPITAL T */ + {0x1d4e4, 1, 66}, /* MATHEMATICAL BOLD SCRIPT CAPITAL U */ + {0x1d4e5, 1, 1183}, /* MATHEMATICAL BOLD SCRIPT CAPITAL V */ + {0x1d4e6, 1, 334}, /* MATHEMATICAL BOLD SCRIPT CAPITAL W */ + {0x1d4e7, 1, 1211}, /* MATHEMATICAL BOLD SCRIPT CAPITAL X */ + {0x1d4e8, 1, 74}, /* MATHEMATICAL BOLD SCRIPT CAPITAL Y */ + {0x1d4e9, 1, 344}, /* MATHEMATICAL BOLD SCRIPT CAPITAL Z */ + {0x1d4ea, 1, 3}, /* MATHEMATICAL BOLD SCRIPT SMALL A */ + {0x1d4eb, 1, 918}, /* MATHEMATICAL BOLD SCRIPT SMALL B */ + {0x1d4ec, 1, 88}, /* MATHEMATICAL BOLD SCRIPT SMALL C */ + {0x1d4ed, 1, 160}, /* MATHEMATICAL BOLD SCRIPT SMALL D */ + {0x1d4ee, 1, 90}, /* MATHEMATICAL BOLD SCRIPT SMALL E */ + {0x1d4ef, 1, 997}, /* MATHEMATICAL BOLD SCRIPT SMALL F */ + {0x1d4f0, 1, 184}, /* MATHEMATICAL BOLD SCRIPT SMALL G */ + {0x1d4f1, 1, 200}, /* MATHEMATICAL BOLD SCRIPT SMALL H */ + {0x1d4f2, 1, 98}, /* MATHEMATICAL BOLD SCRIPT SMALL I */ + {0x1d4f3, 1, 223}, /* MATHEMATICAL BOLD SCRIPT SMALL J */ + {0x1d4f4, 1, 230}, /* MATHEMATICAL BOLD SCRIPT SMALL K */ + {0x1d4f5, 1, 234}, /* MATHEMATICAL BOLD SCRIPT SMALL L */ + {0x1d4f6, 1, 922}, /* MATHEMATICAL BOLD SCRIPT SMALL M */ + {0x1d4f7, 1, 106}, /* MATHEMATICAL BOLD SCRIPT SMALL N */ + {0x1d4f8, 1, 14}, /* MATHEMATICAL BOLD SCRIPT SMALL O */ + {0x1d4f9, 1, 927}, /* MATHEMATICAL BOLD SCRIPT SMALL P */ + {0x1d4fa, 1, 2335}, /* MATHEMATICAL BOLD SCRIPT SMALL Q */ + {0x1d4fb, 1, 276}, /* MATHEMATICAL BOLD SCRIPT SMALL R */ + {0x1d4fc, 1, 288}, /* MATHEMATICAL BOLD SCRIPT SMALL S */ + {0x1d4fd, 1, 304}, /* MATHEMATICAL BOLD SCRIPT SMALL T */ + {0x1d4fe, 1, 118}, /* MATHEMATICAL BOLD SCRIPT SMALL U */ + {0x1d4ff, 1, 930}, /* MATHEMATICAL BOLD SCRIPT SMALL V */ + {0x1d500, 1, 336}, /* MATHEMATICAL BOLD SCRIPT SMALL W */ + {0x1d501, 1, 579}, /* MATHEMATICAL BOLD SCRIPT SMALL X */ + {0x1d502, 1, 126}, /* MATHEMATICAL BOLD SCRIPT SMALL Y */ + {0x1d503, 1, 346}, /* MATHEMATICAL BOLD SCRIPT SMALL Z */ + {0x1d504, 1, 24}, /* MATHEMATICAL FRAKTUR CAPITAL A */ + {0x1d505, 1, 910}, /* MATHEMATICAL FRAKTUR CAPITAL B */ + {0x1d507, 1, 158}, /* MATHEMATICAL FRAKTUR CAPITAL D */ + {0x1d508, 1, 38}, /* MATHEMATICAL FRAKTUR CAPITAL E */ + {0x1d509, 1, 995}, /* MATHEMATICAL FRAKTUR CAPITAL F */ + {0x1d50a, 1, 182}, /* MATHEMATICAL FRAKTUR CAPITAL G */ + {0x1d50d, 1, 221}, /* MATHEMATICAL FRAKTUR CAPITAL J */ + {0x1d50e, 1, 228}, /* MATHEMATICAL FRAKTUR CAPITAL K */ + {0x1d50f, 1, 232}, /* MATHEMATICAL FRAKTUR CAPITAL L */ + {0x1d510, 1, 912}, /* MATHEMATICAL FRAKTUR CAPITAL M */ + {0x1d511, 1, 54}, /* MATHEMATICAL FRAKTUR CAPITAL N */ + {0x1d512, 1, 56}, /* MATHEMATICAL FRAKTUR CAPITAL O */ + {0x1d513, 1, 914}, /* MATHEMATICAL FRAKTUR CAPITAL P */ + {0x1d514, 1, 1942}, /* MATHEMATICAL FRAKTUR CAPITAL Q */ + {0x1d516, 1, 286}, /* MATHEMATICAL FRAKTUR CAPITAL S */ + {0x1d517, 1, 302}, /* MATHEMATICAL FRAKTUR CAPITAL T */ + {0x1d518, 1, 66}, /* MATHEMATICAL FRAKTUR CAPITAL U */ + {0x1d519, 1, 1183}, /* MATHEMATICAL FRAKTUR CAPITAL V */ + {0x1d51a, 1, 334}, /* MATHEMATICAL FRAKTUR CAPITAL W */ + {0x1d51b, 1, 1211}, /* MATHEMATICAL FRAKTUR CAPITAL X */ + {0x1d51c, 1, 74}, /* MATHEMATICAL FRAKTUR CAPITAL Y */ + {0x1d51e, 1, 3}, /* MATHEMATICAL FRAKTUR SMALL A */ + {0x1d51f, 1, 918}, /* MATHEMATICAL FRAKTUR SMALL B */ + {0x1d520, 1, 88}, /* MATHEMATICAL FRAKTUR SMALL C */ + {0x1d521, 1, 160}, /* MATHEMATICAL FRAKTUR SMALL D */ + {0x1d522, 1, 90}, /* MATHEMATICAL FRAKTUR SMALL E */ + {0x1d523, 1, 997}, /* MATHEMATICAL FRAKTUR SMALL F */ + {0x1d524, 1, 184}, /* MATHEMATICAL FRAKTUR SMALL G */ + {0x1d525, 1, 200}, /* MATHEMATICAL FRAKTUR SMALL H */ + {0x1d526, 1, 98}, /* MATHEMATICAL FRAKTUR SMALL I */ + {0x1d527, 1, 223}, /* MATHEMATICAL FRAKTUR SMALL J */ + {0x1d528, 1, 230}, /* MATHEMATICAL FRAKTUR SMALL K */ + {0x1d529, 1, 234}, /* MATHEMATICAL FRAKTUR SMALL L */ + {0x1d52a, 1, 922}, /* MATHEMATICAL FRAKTUR SMALL M */ + {0x1d52b, 1, 106}, /* MATHEMATICAL FRAKTUR SMALL N */ + {0x1d52c, 1, 14}, /* MATHEMATICAL FRAKTUR SMALL O */ + {0x1d52d, 1, 927}, /* MATHEMATICAL FRAKTUR SMALL P */ + {0x1d52e, 1, 2335}, /* MATHEMATICAL FRAKTUR SMALL Q */ + {0x1d52f, 1, 276}, /* MATHEMATICAL FRAKTUR SMALL R */ + {0x1d530, 1, 288}, /* MATHEMATICAL FRAKTUR SMALL S */ + {0x1d531, 1, 304}, /* MATHEMATICAL FRAKTUR SMALL T */ + {0x1d532, 1, 118}, /* MATHEMATICAL FRAKTUR SMALL U */ + {0x1d533, 1, 930}, /* MATHEMATICAL FRAKTUR SMALL V */ + {0x1d534, 1, 336}, /* MATHEMATICAL FRAKTUR SMALL W */ + {0x1d535, 1, 579}, /* MATHEMATICAL FRAKTUR SMALL X */ + {0x1d536, 1, 126}, /* MATHEMATICAL FRAKTUR SMALL Y */ + {0x1d537, 1, 346}, /* MATHEMATICAL FRAKTUR SMALL Z */ + {0x1d538, 1, 24}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL A */ + {0x1d539, 1, 910}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL B */ + {0x1d53b, 1, 158}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL D */ + {0x1d53c, 1, 38}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL E */ + {0x1d53d, 1, 995}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL F */ + {0x1d53e, 1, 182}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL G */ + {0x1d540, 1, 46}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL I */ + {0x1d541, 1, 221}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL J */ + {0x1d542, 1, 228}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL K */ + {0x1d543, 1, 232}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL L */ + {0x1d544, 1, 912}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL M */ + {0x1d546, 1, 56}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL O */ + {0x1d54a, 1, 286}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL S */ + {0x1d54b, 1, 302}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL T */ + {0x1d54c, 1, 66}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL U */ + {0x1d54d, 1, 1183}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL V */ + {0x1d54e, 1, 334}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL W */ + {0x1d54f, 1, 1211}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL X */ + {0x1d550, 1, 74}, /* MATHEMATICAL DOUBLE-STRUCK CAPITAL Y */ + {0x1d552, 1, 3}, /* MATHEMATICAL DOUBLE-STRUCK SMALL A */ + {0x1d553, 1, 918}, /* MATHEMATICAL DOUBLE-STRUCK SMALL B */ + {0x1d554, 1, 88}, /* MATHEMATICAL DOUBLE-STRUCK SMALL C */ + {0x1d555, 1, 160}, /* MATHEMATICAL DOUBLE-STRUCK SMALL D */ + {0x1d556, 1, 90}, /* MATHEMATICAL DOUBLE-STRUCK SMALL E */ + {0x1d557, 1, 997}, /* MATHEMATICAL DOUBLE-STRUCK SMALL F */ + {0x1d558, 1, 184}, /* MATHEMATICAL DOUBLE-STRUCK SMALL G */ + {0x1d559, 1, 200}, /* MATHEMATICAL DOUBLE-STRUCK SMALL H */ + {0x1d55a, 1, 98}, /* MATHEMATICAL DOUBLE-STRUCK SMALL I */ + {0x1d55b, 1, 223}, /* MATHEMATICAL DOUBLE-STRUCK SMALL J */ + {0x1d55c, 1, 230}, /* MATHEMATICAL DOUBLE-STRUCK SMALL K */ + {0x1d55d, 1, 234}, /* MATHEMATICAL DOUBLE-STRUCK SMALL L */ + {0x1d55e, 1, 922}, /* MATHEMATICAL DOUBLE-STRUCK SMALL M */ + {0x1d55f, 1, 106}, /* MATHEMATICAL DOUBLE-STRUCK SMALL N */ + {0x1d560, 1, 14}, /* MATHEMATICAL DOUBLE-STRUCK SMALL O */ + {0x1d561, 1, 927}, /* MATHEMATICAL DOUBLE-STRUCK SMALL P */ + {0x1d562, 1, 2335}, /* MATHEMATICAL DOUBLE-STRUCK SMALL Q */ + {0x1d563, 1, 276}, /* MATHEMATICAL DOUBLE-STRUCK SMALL R */ + {0x1d564, 1, 288}, /* MATHEMATICAL DOUBLE-STRUCK SMALL S */ + {0x1d565, 1, 304}, /* MATHEMATICAL DOUBLE-STRUCK SMALL T */ + {0x1d566, 1, 118}, /* MATHEMATICAL DOUBLE-STRUCK SMALL U */ + {0x1d567, 1, 930}, /* MATHEMATICAL DOUBLE-STRUCK SMALL V */ + {0x1d568, 1, 336}, /* MATHEMATICAL DOUBLE-STRUCK SMALL W */ + {0x1d569, 1, 579}, /* MATHEMATICAL DOUBLE-STRUCK SMALL X */ + {0x1d56a, 1, 126}, /* MATHEMATICAL DOUBLE-STRUCK SMALL Y */ + {0x1d56b, 1, 346}, /* MATHEMATICAL DOUBLE-STRUCK SMALL Z */ + {0x1d56c, 1, 24}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL A */ + {0x1d56d, 1, 910}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL B */ + {0x1d56e, 1, 36}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL C */ + {0x1d56f, 1, 158}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL D */ + {0x1d570, 1, 38}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL E */ + {0x1d571, 1, 995}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL F */ + {0x1d572, 1, 182}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL G */ + {0x1d573, 1, 198}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL H */ + {0x1d574, 1, 46}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL I */ + {0x1d575, 1, 221}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL J */ + {0x1d576, 1, 228}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL K */ + {0x1d577, 1, 232}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL L */ + {0x1d578, 1, 912}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL M */ + {0x1d579, 1, 54}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL N */ + {0x1d57a, 1, 56}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL O */ + {0x1d57b, 1, 914}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL P */ + {0x1d57c, 1, 1942}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL Q */ + {0x1d57d, 1, 274}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL R */ + {0x1d57e, 1, 286}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL S */ + {0x1d57f, 1, 302}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL T */ + {0x1d580, 1, 66}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL U */ + {0x1d581, 1, 1183}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL V */ + {0x1d582, 1, 334}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL W */ + {0x1d583, 1, 1211}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL X */ + {0x1d584, 1, 74}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL Y */ + {0x1d585, 1, 344}, /* MATHEMATICAL BOLD FRAKTUR CAPITAL Z */ + {0x1d586, 1, 3}, /* MATHEMATICAL BOLD FRAKTUR SMALL A */ + {0x1d587, 1, 918}, /* MATHEMATICAL BOLD FRAKTUR SMALL B */ + {0x1d588, 1, 88}, /* MATHEMATICAL BOLD FRAKTUR SMALL C */ + {0x1d589, 1, 160}, /* MATHEMATICAL BOLD FRAKTUR SMALL D */ + {0x1d58a, 1, 90}, /* MATHEMATICAL BOLD FRAKTUR SMALL E */ + {0x1d58b, 1, 997}, /* MATHEMATICAL BOLD FRAKTUR SMALL F */ + {0x1d58c, 1, 184}, /* MATHEMATICAL BOLD FRAKTUR SMALL G */ + {0x1d58d, 1, 200}, /* MATHEMATICAL BOLD FRAKTUR SMALL H */ + {0x1d58e, 1, 98}, /* MATHEMATICAL BOLD FRAKTUR SMALL I */ + {0x1d58f, 1, 223}, /* MATHEMATICAL BOLD FRAKTUR SMALL J */ + {0x1d590, 1, 230}, /* MATHEMATICAL BOLD FRAKTUR SMALL K */ + {0x1d591, 1, 234}, /* MATHEMATICAL BOLD FRAKTUR SMALL L */ + {0x1d592, 1, 922}, /* MATHEMATICAL BOLD FRAKTUR SMALL M */ + {0x1d593, 1, 106}, /* MATHEMATICAL BOLD FRAKTUR SMALL N */ + {0x1d594, 1, 14}, /* MATHEMATICAL BOLD FRAKTUR SMALL O */ + {0x1d595, 1, 927}, /* MATHEMATICAL BOLD FRAKTUR SMALL P */ + {0x1d596, 1, 2335}, /* MATHEMATICAL BOLD FRAKTUR SMALL Q */ + {0x1d597, 1, 276}, /* MATHEMATICAL BOLD FRAKTUR SMALL R */ + {0x1d598, 1, 288}, /* MATHEMATICAL BOLD FRAKTUR SMALL S */ + {0x1d599, 1, 304}, /* MATHEMATICAL BOLD FRAKTUR SMALL T */ + {0x1d59a, 1, 118}, /* MATHEMATICAL BOLD FRAKTUR SMALL U */ + {0x1d59b, 1, 930}, /* MATHEMATICAL BOLD FRAKTUR SMALL V */ + {0x1d59c, 1, 336}, /* MATHEMATICAL BOLD FRAKTUR SMALL W */ + {0x1d59d, 1, 579}, /* MATHEMATICAL BOLD FRAKTUR SMALL X */ + {0x1d59e, 1, 126}, /* MATHEMATICAL BOLD FRAKTUR SMALL Y */ + {0x1d59f, 1, 346}, /* MATHEMATICAL BOLD FRAKTUR SMALL Z */ + {0x1d5a0, 1, 24}, /* MATHEMATICAL SANS-SERIF CAPITAL A */ + {0x1d5a1, 1, 910}, /* MATHEMATICAL SANS-SERIF CAPITAL B */ + {0x1d5a2, 1, 36}, /* MATHEMATICAL SANS-SERIF CAPITAL C */ + {0x1d5a3, 1, 158}, /* MATHEMATICAL SANS-SERIF CAPITAL D */ + {0x1d5a4, 1, 38}, /* MATHEMATICAL SANS-SERIF CAPITAL E */ + {0x1d5a5, 1, 995}, /* MATHEMATICAL SANS-SERIF CAPITAL F */ + {0x1d5a6, 1, 182}, /* MATHEMATICAL SANS-SERIF CAPITAL G */ + {0x1d5a7, 1, 198}, /* MATHEMATICAL SANS-SERIF CAPITAL H */ + {0x1d5a8, 1, 46}, /* MATHEMATICAL SANS-SERIF CAPITAL I */ + {0x1d5a9, 1, 221}, /* MATHEMATICAL SANS-SERIF CAPITAL J */ + {0x1d5aa, 1, 228}, /* MATHEMATICAL SANS-SERIF CAPITAL K */ + {0x1d5ab, 1, 232}, /* MATHEMATICAL SANS-SERIF CAPITAL L */ + {0x1d5ac, 1, 912}, /* MATHEMATICAL SANS-SERIF CAPITAL M */ + {0x1d5ad, 1, 54}, /* MATHEMATICAL SANS-SERIF CAPITAL N */ + {0x1d5ae, 1, 56}, /* MATHEMATICAL SANS-SERIF CAPITAL O */ + {0x1d5af, 1, 914}, /* MATHEMATICAL SANS-SERIF CAPITAL P */ + {0x1d5b0, 1, 1942}, /* MATHEMATICAL SANS-SERIF CAPITAL Q */ + {0x1d5b1, 1, 274}, /* MATHEMATICAL SANS-SERIF CAPITAL R */ + {0x1d5b2, 1, 286}, /* MATHEMATICAL SANS-SERIF CAPITAL S */ + {0x1d5b3, 1, 302}, /* MATHEMATICAL SANS-SERIF CAPITAL T */ + {0x1d5b4, 1, 66}, /* MATHEMATICAL SANS-SERIF CAPITAL U */ + {0x1d5b5, 1, 1183}, /* MATHEMATICAL SANS-SERIF CAPITAL V */ + {0x1d5b6, 1, 334}, /* MATHEMATICAL SANS-SERIF CAPITAL W */ + {0x1d5b7, 1, 1211}, /* MATHEMATICAL SANS-SERIF CAPITAL X */ + {0x1d5b8, 1, 74}, /* MATHEMATICAL SANS-SERIF CAPITAL Y */ + {0x1d5b9, 1, 344}, /* MATHEMATICAL SANS-SERIF CAPITAL Z */ + {0x1d5ba, 1, 3}, /* MATHEMATICAL SANS-SERIF SMALL A */ + {0x1d5bb, 1, 918}, /* MATHEMATICAL SANS-SERIF SMALL B */ + {0x1d5bc, 1, 88}, /* MATHEMATICAL SANS-SERIF SMALL C */ + {0x1d5bd, 1, 160}, /* MATHEMATICAL SANS-SERIF SMALL D */ + {0x1d5be, 1, 90}, /* MATHEMATICAL SANS-SERIF SMALL E */ + {0x1d5bf, 1, 997}, /* MATHEMATICAL SANS-SERIF SMALL F */ + {0x1d5c0, 1, 184}, /* MATHEMATICAL SANS-SERIF SMALL G */ + {0x1d5c1, 1, 200}, /* MATHEMATICAL SANS-SERIF SMALL H */ + {0x1d5c2, 1, 98}, /* MATHEMATICAL SANS-SERIF SMALL I */ + {0x1d5c3, 1, 223}, /* MATHEMATICAL SANS-SERIF SMALL J */ + {0x1d5c4, 1, 230}, /* MATHEMATICAL SANS-SERIF SMALL K */ + {0x1d5c5, 1, 234}, /* MATHEMATICAL SANS-SERIF SMALL L */ + {0x1d5c6, 1, 922}, /* MATHEMATICAL SANS-SERIF SMALL M */ + {0x1d5c7, 1, 106}, /* MATHEMATICAL SANS-SERIF SMALL N */ + {0x1d5c8, 1, 14}, /* MATHEMATICAL SANS-SERIF SMALL O */ + {0x1d5c9, 1, 927}, /* MATHEMATICAL SANS-SERIF SMALL P */ + {0x1d5ca, 1, 2335}, /* MATHEMATICAL SANS-SERIF SMALL Q */ + {0x1d5cb, 1, 276}, /* MATHEMATICAL SANS-SERIF SMALL R */ + {0x1d5cc, 1, 288}, /* MATHEMATICAL SANS-SERIF SMALL S */ + {0x1d5cd, 1, 304}, /* MATHEMATICAL SANS-SERIF SMALL T */ + {0x1d5ce, 1, 118}, /* MATHEMATICAL SANS-SERIF SMALL U */ + {0x1d5cf, 1, 930}, /* MATHEMATICAL SANS-SERIF SMALL V */ + {0x1d5d0, 1, 336}, /* MATHEMATICAL SANS-SERIF SMALL W */ + {0x1d5d1, 1, 579}, /* MATHEMATICAL SANS-SERIF SMALL X */ + {0x1d5d2, 1, 126}, /* MATHEMATICAL SANS-SERIF SMALL Y */ + {0x1d5d3, 1, 346}, /* MATHEMATICAL SANS-SERIF SMALL Z */ + {0x1d5d4, 1, 24}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL A */ + {0x1d5d5, 1, 910}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL B */ + {0x1d5d6, 1, 36}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL C */ + {0x1d5d7, 1, 158}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL D */ + {0x1d5d8, 1, 38}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL E */ + {0x1d5d9, 1, 995}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL F */ + {0x1d5da, 1, 182}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL G */ + {0x1d5db, 1, 198}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL H */ + {0x1d5dc, 1, 46}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL I */ + {0x1d5dd, 1, 221}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL J */ + {0x1d5de, 1, 228}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL K */ + {0x1d5df, 1, 232}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL L */ + {0x1d5e0, 1, 912}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL M */ + {0x1d5e1, 1, 54}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL N */ + {0x1d5e2, 1, 56}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL O */ + {0x1d5e3, 1, 914}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL P */ + {0x1d5e4, 1, 1942}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL Q */ + {0x1d5e5, 1, 274}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL R */ + {0x1d5e6, 1, 286}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL S */ + {0x1d5e7, 1, 302}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL T */ + {0x1d5e8, 1, 66}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL U */ + {0x1d5e9, 1, 1183}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL V */ + {0x1d5ea, 1, 334}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL W */ + {0x1d5eb, 1, 1211}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL X */ + {0x1d5ec, 1, 74}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL Y */ + {0x1d5ed, 1, 344}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL Z */ + {0x1d5ee, 1, 3}, /* MATHEMATICAL SANS-SERIF BOLD SMALL A */ + {0x1d5ef, 1, 918}, /* MATHEMATICAL SANS-SERIF BOLD SMALL B */ + {0x1d5f0, 1, 88}, /* MATHEMATICAL SANS-SERIF BOLD SMALL C */ + {0x1d5f1, 1, 160}, /* MATHEMATICAL SANS-SERIF BOLD SMALL D */ + {0x1d5f2, 1, 90}, /* MATHEMATICAL SANS-SERIF BOLD SMALL E */ + {0x1d5f3, 1, 997}, /* MATHEMATICAL SANS-SERIF BOLD SMALL F */ + {0x1d5f4, 1, 184}, /* MATHEMATICAL SANS-SERIF BOLD SMALL G */ + {0x1d5f5, 1, 200}, /* MATHEMATICAL SANS-SERIF BOLD SMALL H */ + {0x1d5f6, 1, 98}, /* MATHEMATICAL SANS-SERIF BOLD SMALL I */ + {0x1d5f7, 1, 223}, /* MATHEMATICAL SANS-SERIF BOLD SMALL J */ + {0x1d5f8, 1, 230}, /* MATHEMATICAL SANS-SERIF BOLD SMALL K */ + {0x1d5f9, 1, 234}, /* MATHEMATICAL SANS-SERIF BOLD SMALL L */ + {0x1d5fa, 1, 922}, /* MATHEMATICAL SANS-SERIF BOLD SMALL M */ + {0x1d5fb, 1, 106}, /* MATHEMATICAL SANS-SERIF BOLD SMALL N */ + {0x1d5fc, 1, 14}, /* MATHEMATICAL SANS-SERIF BOLD SMALL O */ + {0x1d5fd, 1, 927}, /* MATHEMATICAL SANS-SERIF BOLD SMALL P */ + {0x1d5fe, 1, 2335}, /* MATHEMATICAL SANS-SERIF BOLD SMALL Q */ + {0x1d5ff, 1, 276}, /* MATHEMATICAL SANS-SERIF BOLD SMALL R */ + {0x1d600, 1, 288}, /* MATHEMATICAL SANS-SERIF BOLD SMALL S */ + {0x1d601, 1, 304}, /* MATHEMATICAL SANS-SERIF BOLD SMALL T */ + {0x1d602, 1, 118}, /* MATHEMATICAL SANS-SERIF BOLD SMALL U */ + {0x1d603, 1, 930}, /* MATHEMATICAL SANS-SERIF BOLD SMALL V */ + {0x1d604, 1, 336}, /* MATHEMATICAL SANS-SERIF BOLD SMALL W */ + {0x1d605, 1, 579}, /* MATHEMATICAL SANS-SERIF BOLD SMALL X */ + {0x1d606, 1, 126}, /* MATHEMATICAL SANS-SERIF BOLD SMALL Y */ + {0x1d607, 1, 346}, /* MATHEMATICAL SANS-SERIF BOLD SMALL Z */ + {0x1d608, 1, 24}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL A */ + {0x1d609, 1, 910}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL B */ + {0x1d60a, 1, 36}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL C */ + {0x1d60b, 1, 158}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL D */ + {0x1d60c, 1, 38}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL E */ + {0x1d60d, 1, 995}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL F */ + {0x1d60e, 1, 182}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL G */ + {0x1d60f, 1, 198}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL H */ + {0x1d610, 1, 46}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL I */ + {0x1d611, 1, 221}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL J */ + {0x1d612, 1, 228}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL K */ + {0x1d613, 1, 232}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL L */ + {0x1d614, 1, 912}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL M */ + {0x1d615, 1, 54}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL N */ + {0x1d616, 1, 56}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL O */ + {0x1d617, 1, 914}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL P */ + {0x1d618, 1, 1942}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q */ + {0x1d619, 1, 274}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL R */ + {0x1d61a, 1, 286}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL S */ + {0x1d61b, 1, 302}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL T */ + {0x1d61c, 1, 66}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL U */ + {0x1d61d, 1, 1183}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL V */ + {0x1d61e, 1, 334}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL W */ + {0x1d61f, 1, 1211}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL X */ + {0x1d620, 1, 74}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y */ + {0x1d621, 1, 344}, /* MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z */ + {0x1d622, 1, 3}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL A */ + {0x1d623, 1, 918}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL B */ + {0x1d624, 1, 88}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL C */ + {0x1d625, 1, 160}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL D */ + {0x1d626, 1, 90}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL E */ + {0x1d627, 1, 997}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL F */ + {0x1d628, 1, 184}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL G */ + {0x1d629, 1, 200}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL H */ + {0x1d62a, 1, 98}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL I */ + {0x1d62b, 1, 223}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL J */ + {0x1d62c, 1, 230}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL K */ + {0x1d62d, 1, 234}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL L */ + {0x1d62e, 1, 922}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL M */ + {0x1d62f, 1, 106}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL N */ + {0x1d630, 1, 14}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL O */ + {0x1d631, 1, 927}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL P */ + {0x1d632, 1, 2335}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL Q */ + {0x1d633, 1, 276}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL R */ + {0x1d634, 1, 288}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL S */ + {0x1d635, 1, 304}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL T */ + {0x1d636, 1, 118}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL U */ + {0x1d637, 1, 930}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL V */ + {0x1d638, 1, 336}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL W */ + {0x1d639, 1, 579}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL X */ + {0x1d63a, 1, 126}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL Y */ + {0x1d63b, 1, 346}, /* MATHEMATICAL SANS-SERIF ITALIC SMALL Z */ + {0x1d63c, 1, 24}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A */ + {0x1d63d, 1, 910}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B */ + {0x1d63e, 1, 36}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C */ + {0x1d63f, 1, 158}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D */ + {0x1d640, 1, 38}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E */ + {0x1d641, 1, 995}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F */ + {0x1d642, 1, 182}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G */ + {0x1d643, 1, 198}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H */ + {0x1d644, 1, 46}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I */ + {0x1d645, 1, 221}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J */ + {0x1d646, 1, 228}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K */ + {0x1d647, 1, 232}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L */ + {0x1d648, 1, 912}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M */ + {0x1d649, 1, 54}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N */ + {0x1d64a, 1, 56}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O */ + {0x1d64b, 1, 914}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P */ + {0x1d64c, 1, 1942}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q */ + {0x1d64d, 1, 274}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R */ + {0x1d64e, 1, 286}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S */ + {0x1d64f, 1, 302}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T */ + {0x1d650, 1, 66}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U */ + {0x1d651, 1, 1183}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V */ + {0x1d652, 1, 334}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W */ + {0x1d653, 1, 1211}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X */ + {0x1d654, 1, 74}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y */ + {0x1d655, 1, 344}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z */ + {0x1d656, 1, 3}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A */ + {0x1d657, 1, 918}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B */ + {0x1d658, 1, 88}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C */ + {0x1d659, 1, 160}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D */ + {0x1d65a, 1, 90}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E */ + {0x1d65b, 1, 997}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F */ + {0x1d65c, 1, 184}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G */ + {0x1d65d, 1, 200}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H */ + {0x1d65e, 1, 98}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I */ + {0x1d65f, 1, 223}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J */ + {0x1d660, 1, 230}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K */ + {0x1d661, 1, 234}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L */ + {0x1d662, 1, 922}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M */ + {0x1d663, 1, 106}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N */ + {0x1d664, 1, 14}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O */ + {0x1d665, 1, 927}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P */ + {0x1d666, 1, 2335}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q */ + {0x1d667, 1, 276}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R */ + {0x1d668, 1, 288}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S */ + {0x1d669, 1, 304}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T */ + {0x1d66a, 1, 118}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U */ + {0x1d66b, 1, 930}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V */ + {0x1d66c, 1, 336}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W */ + {0x1d66d, 1, 579}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X */ + {0x1d66e, 1, 126}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y */ + {0x1d66f, 1, 346}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z */ + {0x1d670, 1, 24}, /* MATHEMATICAL MONOSPACE CAPITAL A */ + {0x1d671, 1, 910}, /* MATHEMATICAL MONOSPACE CAPITAL B */ + {0x1d672, 1, 36}, /* MATHEMATICAL MONOSPACE CAPITAL C */ + {0x1d673, 1, 158}, /* MATHEMATICAL MONOSPACE CAPITAL D */ + {0x1d674, 1, 38}, /* MATHEMATICAL MONOSPACE CAPITAL E */ + {0x1d675, 1, 995}, /* MATHEMATICAL MONOSPACE CAPITAL F */ + {0x1d676, 1, 182}, /* MATHEMATICAL MONOSPACE CAPITAL G */ + {0x1d677, 1, 198}, /* MATHEMATICAL MONOSPACE CAPITAL H */ + {0x1d678, 1, 46}, /* MATHEMATICAL MONOSPACE CAPITAL I */ + {0x1d679, 1, 221}, /* MATHEMATICAL MONOSPACE CAPITAL J */ + {0x1d67a, 1, 228}, /* MATHEMATICAL MONOSPACE CAPITAL K */ + {0x1d67b, 1, 232}, /* MATHEMATICAL MONOSPACE CAPITAL L */ + {0x1d67c, 1, 912}, /* MATHEMATICAL MONOSPACE CAPITAL M */ + {0x1d67d, 1, 54}, /* MATHEMATICAL MONOSPACE CAPITAL N */ + {0x1d67e, 1, 56}, /* MATHEMATICAL MONOSPACE CAPITAL O */ + {0x1d67f, 1, 914}, /* MATHEMATICAL MONOSPACE CAPITAL P */ + {0x1d680, 1, 1942}, /* MATHEMATICAL MONOSPACE CAPITAL Q */ + {0x1d681, 1, 274}, /* MATHEMATICAL MONOSPACE CAPITAL R */ + {0x1d682, 1, 286}, /* MATHEMATICAL MONOSPACE CAPITAL S */ + {0x1d683, 1, 302}, /* MATHEMATICAL MONOSPACE CAPITAL T */ + {0x1d684, 1, 66}, /* MATHEMATICAL MONOSPACE CAPITAL U */ + {0x1d685, 1, 1183}, /* MATHEMATICAL MONOSPACE CAPITAL V */ + {0x1d686, 1, 334}, /* MATHEMATICAL MONOSPACE CAPITAL W */ + {0x1d687, 1, 1211}, /* MATHEMATICAL MONOSPACE CAPITAL X */ + {0x1d688, 1, 74}, /* MATHEMATICAL MONOSPACE CAPITAL Y */ + {0x1d689, 1, 344}, /* MATHEMATICAL MONOSPACE CAPITAL Z */ + {0x1d68a, 1, 3}, /* MATHEMATICAL MONOSPACE SMALL A */ + {0x1d68b, 1, 918}, /* MATHEMATICAL MONOSPACE SMALL B */ + {0x1d68c, 1, 88}, /* MATHEMATICAL MONOSPACE SMALL C */ + {0x1d68d, 1, 160}, /* MATHEMATICAL MONOSPACE SMALL D */ + {0x1d68e, 1, 90}, /* MATHEMATICAL MONOSPACE SMALL E */ + {0x1d68f, 1, 997}, /* MATHEMATICAL MONOSPACE SMALL F */ + {0x1d690, 1, 184}, /* MATHEMATICAL MONOSPACE SMALL G */ + {0x1d691, 1, 200}, /* MATHEMATICAL MONOSPACE SMALL H */ + {0x1d692, 1, 98}, /* MATHEMATICAL MONOSPACE SMALL I */ + {0x1d693, 1, 223}, /* MATHEMATICAL MONOSPACE SMALL J */ + {0x1d694, 1, 230}, /* MATHEMATICAL MONOSPACE SMALL K */ + {0x1d695, 1, 234}, /* MATHEMATICAL MONOSPACE SMALL L */ + {0x1d696, 1, 922}, /* MATHEMATICAL MONOSPACE SMALL M */ + {0x1d697, 1, 106}, /* MATHEMATICAL MONOSPACE SMALL N */ + {0x1d698, 1, 14}, /* MATHEMATICAL MONOSPACE SMALL O */ + {0x1d699, 1, 927}, /* MATHEMATICAL MONOSPACE SMALL P */ + {0x1d69a, 1, 2335}, /* MATHEMATICAL MONOSPACE SMALL Q */ + {0x1d69b, 1, 276}, /* MATHEMATICAL MONOSPACE SMALL R */ + {0x1d69c, 1, 288}, /* MATHEMATICAL MONOSPACE SMALL S */ + {0x1d69d, 1, 304}, /* MATHEMATICAL MONOSPACE SMALL T */ + {0x1d69e, 1, 118}, /* MATHEMATICAL MONOSPACE SMALL U */ + {0x1d69f, 1, 930}, /* MATHEMATICAL MONOSPACE SMALL V */ + {0x1d6a0, 1, 336}, /* MATHEMATICAL MONOSPACE SMALL W */ + {0x1d6a1, 1, 579}, /* MATHEMATICAL MONOSPACE SMALL X */ + {0x1d6a2, 1, 126}, /* MATHEMATICAL MONOSPACE SMALL Y */ + {0x1d6a3, 1, 346}, /* MATHEMATICAL MONOSPACE SMALL Z */ + {0x1d6a8, 1, 590}, /* MATHEMATICAL BOLD CAPITAL ALPHA */ + {0x1d6a9, 1, 5148}, /* MATHEMATICAL BOLD CAPITAL BETA */ + {0x1d6aa, 1, 1957}, /* MATHEMATICAL BOLD CAPITAL GAMMA */ + {0x1d6ab, 1, 5149}, /* MATHEMATICAL BOLD CAPITAL DELTA */ + {0x1d6ac, 1, 592}, /* MATHEMATICAL BOLD CAPITAL EPSILON */ + {0x1d6ad, 1, 5150}, /* MATHEMATICAL BOLD CAPITAL ZETA */ + {0x1d6ae, 1, 594}, /* MATHEMATICAL BOLD CAPITAL ETA */ + {0x1d6af, 1, 641}, /* MATHEMATICAL BOLD CAPITAL THETA */ + {0x1d6b0, 1, 596}, /* MATHEMATICAL BOLD CAPITAL IOTA */ + {0x1d6b1, 1, 5151}, /* MATHEMATICAL BOLD CAPITAL KAPPA */ + {0x1d6b2, 1, 5152}, /* MATHEMATICAL BOLD CAPITAL LAMDA */ + {0x1d6b3, 1, 5153}, /* MATHEMATICAL BOLD CAPITAL MU */ + {0x1d6b4, 1, 5154}, /* MATHEMATICAL BOLD CAPITAL NU */ + {0x1d6b5, 1, 5155}, /* MATHEMATICAL BOLD CAPITAL XI */ + {0x1d6b6, 1, 598}, /* MATHEMATICAL BOLD CAPITAL OMICRON */ + {0x1d6b7, 1, 1958}, /* MATHEMATICAL BOLD CAPITAL PI */ + {0x1d6b8, 1, 1843}, /* MATHEMATICAL BOLD CAPITAL RHO */ + {0x1d6b9, 1, 5156}, /* MATHEMATICAL BOLD CAPITAL THETA SYMBOL */ + {0x1d6ba, 1, 642}, /* MATHEMATICAL BOLD CAPITAL SIGMA */ + {0x1d6bb, 1, 5157}, /* MATHEMATICAL BOLD CAPITAL TAU */ + {0x1d6bc, 1, 600}, /* MATHEMATICAL BOLD CAPITAL UPSILON */ + {0x1d6bd, 1, 5158}, /* MATHEMATICAL BOLD CAPITAL PHI */ + {0x1d6be, 1, 5159}, /* MATHEMATICAL BOLD CAPITAL CHI */ + {0x1d6bf, 1, 5160}, /* MATHEMATICAL BOLD CAPITAL PSI */ + {0x1d6c0, 1, 602}, /* MATHEMATICAL BOLD CAPITAL OMEGA */ + {0x1d6c1, 1, 5161}, /* MATHEMATICAL BOLD NABLA */ + {0x1d6c2, 1, 610}, /* MATHEMATICAL BOLD SMALL ALPHA */ + {0x1d6c3, 1, 630}, /* MATHEMATICAL BOLD SMALL BETA */ + {0x1d6c4, 1, 932}, /* MATHEMATICAL BOLD SMALL GAMMA */ + {0x1d6c5, 1, 933}, /* MATHEMATICAL BOLD SMALL DELTA */ + {0x1d6c6, 1, 612}, /* MATHEMATICAL BOLD SMALL EPSILON */ + {0x1d6c7, 1, 5162}, /* MATHEMATICAL BOLD SMALL ZETA */ + {0x1d6c8, 1, 614}, /* MATHEMATICAL BOLD SMALL ETA */ + {0x1d6c9, 1, 631}, /* MATHEMATICAL BOLD SMALL THETA */ + {0x1d6ca, 1, 616}, /* MATHEMATICAL BOLD SMALL IOTA */ + {0x1d6cb, 1, 638}, /* MATHEMATICAL BOLD SMALL KAPPA */ + {0x1d6cc, 1, 5163}, /* MATHEMATICAL BOLD SMALL LAMDA */ + {0x1d6cd, 1, 10}, /* MATHEMATICAL BOLD SMALL MU */ + {0x1d6ce, 1, 5164}, /* MATHEMATICAL BOLD SMALL NU */ + {0x1d6cf, 1, 5165}, /* MATHEMATICAL BOLD SMALL XI */ + {0x1d6d0, 1, 624}, /* MATHEMATICAL BOLD SMALL OMICRON */ + {0x1d6d1, 1, 637}, /* MATHEMATICAL BOLD SMALL PI */ + {0x1d6d2, 1, 639}, /* MATHEMATICAL BOLD SMALL RHO */ + {0x1d6d3, 1, 640}, /* MATHEMATICAL BOLD SMALL FINAL SIGMA */ + {0x1d6d4, 1, 5166}, /* MATHEMATICAL BOLD SMALL SIGMA */ + {0x1d6d5, 1, 5167}, /* MATHEMATICAL BOLD SMALL TAU */ + {0x1d6d6, 1, 622}, /* MATHEMATICAL BOLD SMALL UPSILON */ + {0x1d6d7, 1, 636}, /* MATHEMATICAL BOLD SMALL PHI */ + {0x1d6d8, 1, 934}, /* MATHEMATICAL BOLD SMALL CHI */ + {0x1d6d9, 1, 5168}, /* MATHEMATICAL BOLD SMALL PSI */ + {0x1d6da, 1, 628}, /* MATHEMATICAL BOLD SMALL OMEGA */ + {0x1d6db, 1, 5169}, /* MATHEMATICAL BOLD PARTIAL DIFFERENTIAL */ + {0x1d6dc, 1, 5170}, /* MATHEMATICAL BOLD EPSILON SYMBOL */ + {0x1d6dd, 1, 5171}, /* MATHEMATICAL BOLD THETA SYMBOL */ + {0x1d6de, 1, 5172}, /* MATHEMATICAL BOLD KAPPA SYMBOL */ + {0x1d6df, 1, 5173}, /* MATHEMATICAL BOLD PHI SYMBOL */ + {0x1d6e0, 1, 5174}, /* MATHEMATICAL BOLD RHO SYMBOL */ + {0x1d6e1, 1, 5175}, /* MATHEMATICAL BOLD PI SYMBOL */ + {0x1d6e2, 1, 590}, /* MATHEMATICAL ITALIC CAPITAL ALPHA */ + {0x1d6e3, 1, 5148}, /* MATHEMATICAL ITALIC CAPITAL BETA */ + {0x1d6e4, 1, 1957}, /* MATHEMATICAL ITALIC CAPITAL GAMMA */ + {0x1d6e5, 1, 5149}, /* MATHEMATICAL ITALIC CAPITAL DELTA */ + {0x1d6e6, 1, 592}, /* MATHEMATICAL ITALIC CAPITAL EPSILON */ + {0x1d6e7, 1, 5150}, /* MATHEMATICAL ITALIC CAPITAL ZETA */ + {0x1d6e8, 1, 594}, /* MATHEMATICAL ITALIC CAPITAL ETA */ + {0x1d6e9, 1, 641}, /* MATHEMATICAL ITALIC CAPITAL THETA */ + {0x1d6ea, 1, 596}, /* MATHEMATICAL ITALIC CAPITAL IOTA */ + {0x1d6eb, 1, 5151}, /* MATHEMATICAL ITALIC CAPITAL KAPPA */ + {0x1d6ec, 1, 5152}, /* MATHEMATICAL ITALIC CAPITAL LAMDA */ + {0x1d6ed, 1, 5153}, /* MATHEMATICAL ITALIC CAPITAL MU */ + {0x1d6ee, 1, 5154}, /* MATHEMATICAL ITALIC CAPITAL NU */ + {0x1d6ef, 1, 5155}, /* MATHEMATICAL ITALIC CAPITAL XI */ + {0x1d6f0, 1, 598}, /* MATHEMATICAL ITALIC CAPITAL OMICRON */ + {0x1d6f1, 1, 1958}, /* MATHEMATICAL ITALIC CAPITAL PI */ + {0x1d6f2, 1, 1843}, /* MATHEMATICAL ITALIC CAPITAL RHO */ + {0x1d6f3, 1, 5156}, /* MATHEMATICAL ITALIC CAPITAL THETA SYMBOL */ + {0x1d6f4, 1, 642}, /* MATHEMATICAL ITALIC CAPITAL SIGMA */ + {0x1d6f5, 1, 5157}, /* MATHEMATICAL ITALIC CAPITAL TAU */ + {0x1d6f6, 1, 600}, /* MATHEMATICAL ITALIC CAPITAL UPSILON */ + {0x1d6f7, 1, 5158}, /* MATHEMATICAL ITALIC CAPITAL PHI */ + {0x1d6f8, 1, 5159}, /* MATHEMATICAL ITALIC CAPITAL CHI */ + {0x1d6f9, 1, 5160}, /* MATHEMATICAL ITALIC CAPITAL PSI */ + {0x1d6fa, 1, 602}, /* MATHEMATICAL ITALIC CAPITAL OMEGA */ + {0x1d6fb, 1, 5161}, /* MATHEMATICAL ITALIC NABLA */ + {0x1d6fc, 1, 610}, /* MATHEMATICAL ITALIC SMALL ALPHA */ + {0x1d6fd, 1, 630}, /* MATHEMATICAL ITALIC SMALL BETA */ + {0x1d6fe, 1, 932}, /* MATHEMATICAL ITALIC SMALL GAMMA */ + {0x1d6ff, 1, 933}, /* MATHEMATICAL ITALIC SMALL DELTA */ + {0x1d700, 1, 612}, /* MATHEMATICAL ITALIC SMALL EPSILON */ + {0x1d701, 1, 5162}, /* MATHEMATICAL ITALIC SMALL ZETA */ + {0x1d702, 1, 614}, /* MATHEMATICAL ITALIC SMALL ETA */ + {0x1d703, 1, 631}, /* MATHEMATICAL ITALIC SMALL THETA */ + {0x1d704, 1, 616}, /* MATHEMATICAL ITALIC SMALL IOTA */ + {0x1d705, 1, 638}, /* MATHEMATICAL ITALIC SMALL KAPPA */ + {0x1d706, 1, 5163}, /* MATHEMATICAL ITALIC SMALL LAMDA */ + {0x1d707, 1, 10}, /* MATHEMATICAL ITALIC SMALL MU */ + {0x1d708, 1, 5164}, /* MATHEMATICAL ITALIC SMALL NU */ + {0x1d709, 1, 5165}, /* MATHEMATICAL ITALIC SMALL XI */ + {0x1d70a, 1, 624}, /* MATHEMATICAL ITALIC SMALL OMICRON */ + {0x1d70b, 1, 637}, /* MATHEMATICAL ITALIC SMALL PI */ + {0x1d70c, 1, 639}, /* MATHEMATICAL ITALIC SMALL RHO */ + {0x1d70d, 1, 640}, /* MATHEMATICAL ITALIC SMALL FINAL SIGMA */ + {0x1d70e, 1, 5166}, /* MATHEMATICAL ITALIC SMALL SIGMA */ + {0x1d70f, 1, 5167}, /* MATHEMATICAL ITALIC SMALL TAU */ + {0x1d710, 1, 622}, /* MATHEMATICAL ITALIC SMALL UPSILON */ + {0x1d711, 1, 636}, /* MATHEMATICAL ITALIC SMALL PHI */ + {0x1d712, 1, 934}, /* MATHEMATICAL ITALIC SMALL CHI */ + {0x1d713, 1, 5168}, /* MATHEMATICAL ITALIC SMALL PSI */ + {0x1d714, 1, 628}, /* MATHEMATICAL ITALIC SMALL OMEGA */ + {0x1d715, 1, 5169}, /* MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL */ + {0x1d716, 1, 5170}, /* MATHEMATICAL ITALIC EPSILON SYMBOL */ + {0x1d717, 1, 5171}, /* MATHEMATICAL ITALIC THETA SYMBOL */ + {0x1d718, 1, 5172}, /* MATHEMATICAL ITALIC KAPPA SYMBOL */ + {0x1d719, 1, 5173}, /* MATHEMATICAL ITALIC PHI SYMBOL */ + {0x1d71a, 1, 5174}, /* MATHEMATICAL ITALIC RHO SYMBOL */ + {0x1d71b, 1, 5175}, /* MATHEMATICAL ITALIC PI SYMBOL */ + {0x1d71c, 1, 590}, /* MATHEMATICAL BOLD ITALIC CAPITAL ALPHA */ + {0x1d71d, 1, 5148}, /* MATHEMATICAL BOLD ITALIC CAPITAL BETA */ + {0x1d71e, 1, 1957}, /* MATHEMATICAL BOLD ITALIC CAPITAL GAMMA */ + {0x1d71f, 1, 5149}, /* MATHEMATICAL BOLD ITALIC CAPITAL DELTA */ + {0x1d720, 1, 592}, /* MATHEMATICAL BOLD ITALIC CAPITAL EPSILON */ + {0x1d721, 1, 5150}, /* MATHEMATICAL BOLD ITALIC CAPITAL ZETA */ + {0x1d722, 1, 594}, /* MATHEMATICAL BOLD ITALIC CAPITAL ETA */ + {0x1d723, 1, 641}, /* MATHEMATICAL BOLD ITALIC CAPITAL THETA */ + {0x1d724, 1, 596}, /* MATHEMATICAL BOLD ITALIC CAPITAL IOTA */ + {0x1d725, 1, 5151}, /* MATHEMATICAL BOLD ITALIC CAPITAL KAPPA */ + {0x1d726, 1, 5152}, /* MATHEMATICAL BOLD ITALIC CAPITAL LAMDA */ + {0x1d727, 1, 5153}, /* MATHEMATICAL BOLD ITALIC CAPITAL MU */ + {0x1d728, 1, 5154}, /* MATHEMATICAL BOLD ITALIC CAPITAL NU */ + {0x1d729, 1, 5155}, /* MATHEMATICAL BOLD ITALIC CAPITAL XI */ + {0x1d72a, 1, 598}, /* MATHEMATICAL BOLD ITALIC CAPITAL OMICRON */ + {0x1d72b, 1, 1958}, /* MATHEMATICAL BOLD ITALIC CAPITAL PI */ + {0x1d72c, 1, 1843}, /* MATHEMATICAL BOLD ITALIC CAPITAL RHO */ + {0x1d72d, 1, 5156}, /* MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL */ + {0x1d72e, 1, 642}, /* MATHEMATICAL BOLD ITALIC CAPITAL SIGMA */ + {0x1d72f, 1, 5157}, /* MATHEMATICAL BOLD ITALIC CAPITAL TAU */ + {0x1d730, 1, 600}, /* MATHEMATICAL BOLD ITALIC CAPITAL UPSILON */ + {0x1d731, 1, 5158}, /* MATHEMATICAL BOLD ITALIC CAPITAL PHI */ + {0x1d732, 1, 5159}, /* MATHEMATICAL BOLD ITALIC CAPITAL CHI */ + {0x1d733, 1, 5160}, /* MATHEMATICAL BOLD ITALIC CAPITAL PSI */ + {0x1d734, 1, 602}, /* MATHEMATICAL BOLD ITALIC CAPITAL OMEGA */ + {0x1d735, 1, 5161}, /* MATHEMATICAL BOLD ITALIC NABLA */ + {0x1d736, 1, 610}, /* MATHEMATICAL BOLD ITALIC SMALL ALPHA */ + {0x1d737, 1, 630}, /* MATHEMATICAL BOLD ITALIC SMALL BETA */ + {0x1d738, 1, 932}, /* MATHEMATICAL BOLD ITALIC SMALL GAMMA */ + {0x1d739, 1, 933}, /* MATHEMATICAL BOLD ITALIC SMALL DELTA */ + {0x1d73a, 1, 612}, /* MATHEMATICAL BOLD ITALIC SMALL EPSILON */ + {0x1d73b, 1, 5162}, /* MATHEMATICAL BOLD ITALIC SMALL ZETA */ + {0x1d73c, 1, 614}, /* MATHEMATICAL BOLD ITALIC SMALL ETA */ + {0x1d73d, 1, 631}, /* MATHEMATICAL BOLD ITALIC SMALL THETA */ + {0x1d73e, 1, 616}, /* MATHEMATICAL BOLD ITALIC SMALL IOTA */ + {0x1d73f, 1, 638}, /* MATHEMATICAL BOLD ITALIC SMALL KAPPA */ + {0x1d740, 1, 5163}, /* MATHEMATICAL BOLD ITALIC SMALL LAMDA */ + {0x1d741, 1, 10}, /* MATHEMATICAL BOLD ITALIC SMALL MU */ + {0x1d742, 1, 5164}, /* MATHEMATICAL BOLD ITALIC SMALL NU */ + {0x1d743, 1, 5165}, /* MATHEMATICAL BOLD ITALIC SMALL XI */ + {0x1d744, 1, 624}, /* MATHEMATICAL BOLD ITALIC SMALL OMICRON */ + {0x1d745, 1, 637}, /* MATHEMATICAL BOLD ITALIC SMALL PI */ + {0x1d746, 1, 639}, /* MATHEMATICAL BOLD ITALIC SMALL RHO */ + {0x1d747, 1, 640}, /* MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA */ + {0x1d748, 1, 5166}, /* MATHEMATICAL BOLD ITALIC SMALL SIGMA */ + {0x1d749, 1, 5167}, /* MATHEMATICAL BOLD ITALIC SMALL TAU */ + {0x1d74a, 1, 622}, /* MATHEMATICAL BOLD ITALIC SMALL UPSILON */ + {0x1d74b, 1, 636}, /* MATHEMATICAL BOLD ITALIC SMALL PHI */ + {0x1d74c, 1, 934}, /* MATHEMATICAL BOLD ITALIC SMALL CHI */ + {0x1d74d, 1, 5168}, /* MATHEMATICAL BOLD ITALIC SMALL PSI */ + {0x1d74e, 1, 628}, /* MATHEMATICAL BOLD ITALIC SMALL OMEGA */ + {0x1d74f, 1, 5169}, /* MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL */ + {0x1d750, 1, 5170}, /* MATHEMATICAL BOLD ITALIC EPSILON SYMBOL */ + {0x1d751, 1, 5171}, /* MATHEMATICAL BOLD ITALIC THETA SYMBOL */ + {0x1d752, 1, 5172}, /* MATHEMATICAL BOLD ITALIC KAPPA SYMBOL */ + {0x1d753, 1, 5173}, /* MATHEMATICAL BOLD ITALIC PHI SYMBOL */ + {0x1d754, 1, 5174}, /* MATHEMATICAL BOLD ITALIC RHO SYMBOL */ + {0x1d755, 1, 5175}, /* MATHEMATICAL BOLD ITALIC PI SYMBOL */ + {0x1d756, 1, 590}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA */ + {0x1d757, 1, 5148}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA */ + {0x1d758, 1, 1957}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA */ + {0x1d759, 1, 5149}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA */ + {0x1d75a, 1, 592}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON */ + {0x1d75b, 1, 5150}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA */ + {0x1d75c, 1, 594}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA */ + {0x1d75d, 1, 641}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA */ + {0x1d75e, 1, 596}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA */ + {0x1d75f, 1, 5151}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA */ + {0x1d760, 1, 5152}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA */ + {0x1d761, 1, 5153}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL MU */ + {0x1d762, 1, 5154}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL NU */ + {0x1d763, 1, 5155}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL XI */ + {0x1d764, 1, 598}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON */ + {0x1d765, 1, 1958}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL PI */ + {0x1d766, 1, 1843}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO */ + {0x1d767, 1, 5156}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL */ + {0x1d768, 1, 642}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA */ + {0x1d769, 1, 5157}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU */ + {0x1d76a, 1, 600}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON */ + {0x1d76b, 1, 5158}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI */ + {0x1d76c, 1, 5159}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI */ + {0x1d76d, 1, 5160}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI */ + {0x1d76e, 1, 602}, /* MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA */ + {0x1d76f, 1, 5161}, /* MATHEMATICAL SANS-SERIF BOLD NABLA */ + {0x1d770, 1, 610}, /* MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA */ + {0x1d771, 1, 630}, /* MATHEMATICAL SANS-SERIF BOLD SMALL BETA */ + {0x1d772, 1, 932}, /* MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA */ + {0x1d773, 1, 933}, /* MATHEMATICAL SANS-SERIF BOLD SMALL DELTA */ + {0x1d774, 1, 612}, /* MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON */ + {0x1d775, 1, 5162}, /* MATHEMATICAL SANS-SERIF BOLD SMALL ZETA */ + {0x1d776, 1, 614}, /* MATHEMATICAL SANS-SERIF BOLD SMALL ETA */ + {0x1d777, 1, 631}, /* MATHEMATICAL SANS-SERIF BOLD SMALL THETA */ + {0x1d778, 1, 616}, /* MATHEMATICAL SANS-SERIF BOLD SMALL IOTA */ + {0x1d779, 1, 638}, /* MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA */ + {0x1d77a, 1, 5163}, /* MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA */ + {0x1d77b, 1, 10}, /* MATHEMATICAL SANS-SERIF BOLD SMALL MU */ + {0x1d77c, 1, 5164}, /* MATHEMATICAL SANS-SERIF BOLD SMALL NU */ + {0x1d77d, 1, 5165}, /* MATHEMATICAL SANS-SERIF BOLD SMALL XI */ + {0x1d77e, 1, 624}, /* MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON */ + {0x1d77f, 1, 637}, /* MATHEMATICAL SANS-SERIF BOLD SMALL PI */ + {0x1d780, 1, 639}, /* MATHEMATICAL SANS-SERIF BOLD SMALL RHO */ + {0x1d781, 1, 640}, /* MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA */ + {0x1d782, 1, 5166}, /* MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA */ + {0x1d783, 1, 5167}, /* MATHEMATICAL SANS-SERIF BOLD SMALL TAU */ + {0x1d784, 1, 622}, /* MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON */ + {0x1d785, 1, 636}, /* MATHEMATICAL SANS-SERIF BOLD SMALL PHI */ + {0x1d786, 1, 934}, /* MATHEMATICAL SANS-SERIF BOLD SMALL CHI */ + {0x1d787, 1, 5168}, /* MATHEMATICAL SANS-SERIF BOLD SMALL PSI */ + {0x1d788, 1, 628}, /* MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA */ + {0x1d789, 1, 5169}, /* MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL */ + {0x1d78a, 1, 5170}, /* MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL */ + {0x1d78b, 1, 5171}, /* MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL */ + {0x1d78c, 1, 5172}, /* MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL */ + {0x1d78d, 1, 5173}, /* MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL */ + {0x1d78e, 1, 5174}, /* MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL */ + {0x1d78f, 1, 5175}, /* MATHEMATICAL SANS-SERIF BOLD PI SYMBOL */ + {0x1d790, 1, 590}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA */ + {0x1d791, 1, 5148}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA */ + {0x1d792, 1, 1957}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA */ + {0x1d793, 1, 5149}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA */ + {0x1d794, 1, 592}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON */ + {0x1d795, 1, 5150}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA */ + {0x1d796, 1, 594}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA */ + {0x1d797, 1, 641}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA */ + {0x1d798, 1, 596}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA */ + {0x1d799, 1, 5151}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA */ + {0x1d79a, 1, 5152}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA */ + {0x1d79b, 1, 5153}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU */ + {0x1d79c, 1, 5154}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU */ + {0x1d79d, 1, 5155}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI */ + {0x1d79e, 1, 598}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON */ + {0x1d79f, 1, 1958}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI */ + {0x1d7a0, 1, 1843}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO */ + {0x1d7a1, 1, 5156}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL */ + {0x1d7a2, 1, 642}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA */ + {0x1d7a3, 1, 5157}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU */ + {0x1d7a4, 1, 600}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON */ + {0x1d7a5, 1, 5158}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI */ + {0x1d7a6, 1, 5159}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI */ + {0x1d7a7, 1, 5160}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI */ + {0x1d7a8, 1, 602}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA */ + {0x1d7a9, 1, 5161}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA */ + {0x1d7aa, 1, 610}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA */ + {0x1d7ab, 1, 630}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA */ + {0x1d7ac, 1, 932}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA */ + {0x1d7ad, 1, 933}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA */ + {0x1d7ae, 1, 612}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON */ + {0x1d7af, 1, 5162}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA */ + {0x1d7b0, 1, 614}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA */ + {0x1d7b1, 1, 631}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA */ + {0x1d7b2, 1, 616}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA */ + {0x1d7b3, 1, 638}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA */ + {0x1d7b4, 1, 5163}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA */ + {0x1d7b5, 1, 10}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU */ + {0x1d7b6, 1, 5164}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU */ + {0x1d7b7, 1, 5165}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI */ + {0x1d7b8, 1, 624}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON */ + {0x1d7b9, 1, 637}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI */ + {0x1d7ba, 1, 639}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO */ + {0x1d7bb, 1, 640}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA */ + {0x1d7bc, 1, 5166}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA */ + {0x1d7bd, 1, 5167}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU */ + {0x1d7be, 1, 622}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON */ + {0x1d7bf, 1, 636}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI */ + {0x1d7c0, 1, 934}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI */ + {0x1d7c1, 1, 5168}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI */ + {0x1d7c2, 1, 628}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA */ + {0x1d7c3, 1, 5169}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL */ + {0x1d7c4, 1, 5170}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL */ + {0x1d7c5, 1, 5171}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL */ + {0x1d7c6, 1, 5172}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL */ + {0x1d7c7, 1, 5173}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL */ + {0x1d7c8, 1, 5174}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL */ + {0x1d7c9, 1, 5175}, /* MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL */ + {0x1d7ce, 1, 1909}, /* MATHEMATICAL BOLD DIGIT ZERO */ + {0x1d7cf, 1, 13}, /* MATHEMATICAL BOLD DIGIT ONE */ + {0x1d7d0, 1, 6}, /* MATHEMATICAL BOLD DIGIT TWO */ + {0x1d7d1, 1, 7}, /* MATHEMATICAL BOLD DIGIT THREE */ + {0x1d7d2, 1, 17}, /* MATHEMATICAL BOLD DIGIT FOUR */ + {0x1d7d3, 1, 1910}, /* MATHEMATICAL BOLD DIGIT FIVE */ + {0x1d7d4, 1, 1911}, /* MATHEMATICAL BOLD DIGIT SIX */ + {0x1d7d5, 1, 1912}, /* MATHEMATICAL BOLD DIGIT SEVEN */ + {0x1d7d6, 1, 1913}, /* MATHEMATICAL BOLD DIGIT EIGHT */ + {0x1d7d7, 1, 1914}, /* MATHEMATICAL BOLD DIGIT NINE */ + {0x1d7d8, 1, 1909}, /* MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO */ + {0x1d7d9, 1, 13}, /* MATHEMATICAL DOUBLE-STRUCK DIGIT ONE */ + {0x1d7da, 1, 6}, /* MATHEMATICAL DOUBLE-STRUCK DIGIT TWO */ + {0x1d7db, 1, 7}, /* MATHEMATICAL DOUBLE-STRUCK DIGIT THREE */ + {0x1d7dc, 1, 17}, /* MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR */ + {0x1d7dd, 1, 1910}, /* MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE */ + {0x1d7de, 1, 1911}, /* MATHEMATICAL DOUBLE-STRUCK DIGIT SIX */ + {0x1d7df, 1, 1912}, /* MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN */ + {0x1d7e0, 1, 1913}, /* MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT */ + {0x1d7e1, 1, 1914}, /* MATHEMATICAL DOUBLE-STRUCK DIGIT NINE */ + {0x1d7e2, 1, 1909}, /* MATHEMATICAL SANS-SERIF DIGIT ZERO */ + {0x1d7e3, 1, 13}, /* MATHEMATICAL SANS-SERIF DIGIT ONE */ + {0x1d7e4, 1, 6}, /* MATHEMATICAL SANS-SERIF DIGIT TWO */ + {0x1d7e5, 1, 7}, /* MATHEMATICAL SANS-SERIF DIGIT THREE */ + {0x1d7e6, 1, 17}, /* MATHEMATICAL SANS-SERIF DIGIT FOUR */ + {0x1d7e7, 1, 1910}, /* MATHEMATICAL SANS-SERIF DIGIT FIVE */ + {0x1d7e8, 1, 1911}, /* MATHEMATICAL SANS-SERIF DIGIT SIX */ + {0x1d7e9, 1, 1912}, /* MATHEMATICAL SANS-SERIF DIGIT SEVEN */ + {0x1d7ea, 1, 1913}, /* MATHEMATICAL SANS-SERIF DIGIT EIGHT */ + {0x1d7eb, 1, 1914}, /* MATHEMATICAL SANS-SERIF DIGIT NINE */ + {0x1d7ec, 1, 1909}, /* MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO */ + {0x1d7ed, 1, 13}, /* MATHEMATICAL SANS-SERIF BOLD DIGIT ONE */ + {0x1d7ee, 1, 6}, /* MATHEMATICAL SANS-SERIF BOLD DIGIT TWO */ + {0x1d7ef, 1, 7}, /* MATHEMATICAL SANS-SERIF BOLD DIGIT THREE */ + {0x1d7f0, 1, 17}, /* MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR */ + {0x1d7f1, 1, 1910}, /* MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE */ + {0x1d7f2, 1, 1911}, /* MATHEMATICAL SANS-SERIF BOLD DIGIT SIX */ + {0x1d7f3, 1, 1912}, /* MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN */ + {0x1d7f4, 1, 1913}, /* MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT */ + {0x1d7f5, 1, 1914}, /* MATHEMATICAL SANS-SERIF BOLD DIGIT NINE */ + {0x1d7f6, 1, 1909}, /* MATHEMATICAL MONOSPACE DIGIT ZERO */ + {0x1d7f7, 1, 13}, /* MATHEMATICAL MONOSPACE DIGIT ONE */ + {0x1d7f8, 1, 6}, /* MATHEMATICAL MONOSPACE DIGIT TWO */ + {0x1d7f9, 1, 7}, /* MATHEMATICAL MONOSPACE DIGIT THREE */ + {0x1d7fa, 1, 17}, /* MATHEMATICAL MONOSPACE DIGIT FOUR */ + {0x1d7fb, 1, 1910}, /* MATHEMATICAL MONOSPACE DIGIT FIVE */ + {0x1d7fc, 1, 1911}, /* MATHEMATICAL MONOSPACE DIGIT SIX */ + {0x1d7fd, 1, 1912}, /* MATHEMATICAL MONOSPACE DIGIT SEVEN */ + {0x1d7fe, 1, 1913}, /* MATHEMATICAL MONOSPACE DIGIT EIGHT */ + {0x1d7ff, 1, 1914}, /* MATHEMATICAL MONOSPACE DIGIT NINE */ + {0x2f800, 1, 5176}, /* CJK COMPATIBILITY IDEOGRAPH-2F800 */ + {0x2f801, 1, 5177}, /* CJK COMPATIBILITY IDEOGRAPH-2F801 */ + {0x2f802, 1, 5178}, /* CJK COMPATIBILITY IDEOGRAPH-2F802 */ + {0x2f803, 1, 5179}, /* CJK COMPATIBILITY IDEOGRAPH-2F803 */ + {0x2f804, 1, 5180}, /* CJK COMPATIBILITY IDEOGRAPH-2F804 */ + {0x2f805, 1, 4142}, /* CJK COMPATIBILITY IDEOGRAPH-2F805 */ + {0x2f806, 1, 5181}, /* CJK COMPATIBILITY IDEOGRAPH-2F806 */ + {0x2f807, 1, 5182}, /* CJK COMPATIBILITY IDEOGRAPH-2F807 */ + {0x2f808, 1, 5183}, /* CJK COMPATIBILITY IDEOGRAPH-2F808 */ + {0x2f809, 1, 5184}, /* CJK COMPATIBILITY IDEOGRAPH-2F809 */ + {0x2f80a, 1, 4143}, /* CJK COMPATIBILITY IDEOGRAPH-2F80A */ + {0x2f80b, 1, 5185}, /* CJK COMPATIBILITY IDEOGRAPH-2F80B */ + {0x2f80c, 1, 5186}, /* CJK COMPATIBILITY IDEOGRAPH-2F80C */ + {0x2f80d, 1, 5187}, /* CJK COMPATIBILITY IDEOGRAPH-2F80D */ + {0x2f80e, 1, 4144}, /* CJK COMPATIBILITY IDEOGRAPH-2F80E */ + {0x2f80f, 1, 5188}, /* CJK COMPATIBILITY IDEOGRAPH-2F80F */ + {0x2f810, 1, 5189}, /* CJK COMPATIBILITY IDEOGRAPH-2F810 */ + {0x2f811, 1, 5190}, /* CJK COMPATIBILITY IDEOGRAPH-2F811 */ + {0x2f812, 1, 5191}, /* CJK COMPATIBILITY IDEOGRAPH-2F812 */ + {0x2f813, 1, 5192}, /* CJK COMPATIBILITY IDEOGRAPH-2F813 */ + {0x2f814, 1, 5193}, /* CJK COMPATIBILITY IDEOGRAPH-2F814 */ + {0x2f815, 1, 5194}, /* CJK COMPATIBILITY IDEOGRAPH-2F815 */ + {0x2f816, 1, 5195}, /* CJK COMPATIBILITY IDEOGRAPH-2F816 */ + {0x2f817, 1, 5196}, /* CJK COMPATIBILITY IDEOGRAPH-2F817 */ + {0x2f818, 1, 5197}, /* CJK COMPATIBILITY IDEOGRAPH-2F818 */ + {0x2f819, 1, 5198}, /* CJK COMPATIBILITY IDEOGRAPH-2F819 */ + {0x2f81a, 1, 5199}, /* CJK COMPATIBILITY IDEOGRAPH-2F81A */ + {0x2f81b, 1, 5200}, /* CJK COMPATIBILITY IDEOGRAPH-2F81B */ + {0x2f81c, 1, 5201}, /* CJK COMPATIBILITY IDEOGRAPH-2F81C */ + {0x2f81d, 1, 2389}, /* CJK COMPATIBILITY IDEOGRAPH-2F81D */ + {0x2f81e, 1, 5202}, /* CJK COMPATIBILITY IDEOGRAPH-2F81E */ + {0x2f81f, 1, 5203}, /* CJK COMPATIBILITY IDEOGRAPH-2F81F */ + {0x2f820, 1, 5204}, /* CJK COMPATIBILITY IDEOGRAPH-2F820 */ + {0x2f821, 1, 5205}, /* CJK COMPATIBILITY IDEOGRAPH-2F821 */ + {0x2f822, 1, 5206}, /* CJK COMPATIBILITY IDEOGRAPH-2F822 */ + {0x2f823, 1, 5207}, /* CJK COMPATIBILITY IDEOGRAPH-2F823 */ + {0x2f824, 1, 5208}, /* CJK COMPATIBILITY IDEOGRAPH-2F824 */ + {0x2f825, 1, 5209}, /* CJK COMPATIBILITY IDEOGRAPH-2F825 */ + {0x2f826, 1, 4145}, /* CJK COMPATIBILITY IDEOGRAPH-2F826 */ + {0x2f827, 1, 4146}, /* CJK COMPATIBILITY IDEOGRAPH-2F827 */ + {0x2f828, 1, 5210}, /* CJK COMPATIBILITY IDEOGRAPH-2F828 */ + {0x2f829, 1, 5211}, /* CJK COMPATIBILITY IDEOGRAPH-2F829 */ + {0x2f82a, 1, 5212}, /* CJK COMPATIBILITY IDEOGRAPH-2F82A */ + {0x2f82b, 1, 3965}, /* CJK COMPATIBILITY IDEOGRAPH-2F82B */ + {0x2f82c, 1, 5213}, /* CJK COMPATIBILITY IDEOGRAPH-2F82C */ + {0x2f82d, 1, 4147}, /* CJK COMPATIBILITY IDEOGRAPH-2F82D */ + {0x2f82e, 1, 5214}, /* CJK COMPATIBILITY IDEOGRAPH-2F82E */ + {0x2f82f, 1, 5215}, /* CJK COMPATIBILITY IDEOGRAPH-2F82F */ + {0x2f830, 1, 5216}, /* CJK COMPATIBILITY IDEOGRAPH-2F830 */ + {0x2f831, 1, 5217}, /* CJK COMPATIBILITY IDEOGRAPH-2F831 */ + {0x2f832, 1, 5217}, /* CJK COMPATIBILITY IDEOGRAPH-2F832 */ + {0x2f833, 1, 5217}, /* CJK COMPATIBILITY IDEOGRAPH-2F833 */ + {0x2f834, 1, 5218}, /* CJK COMPATIBILITY IDEOGRAPH-2F834 */ + {0x2f835, 1, 5219}, /* CJK COMPATIBILITY IDEOGRAPH-2F835 */ + {0x2f836, 1, 5220}, /* CJK COMPATIBILITY IDEOGRAPH-2F836 */ + {0x2f837, 1, 5221}, /* CJK COMPATIBILITY IDEOGRAPH-2F837 */ + {0x2f838, 1, 5222}, /* CJK COMPATIBILITY IDEOGRAPH-2F838 */ + {0x2f839, 1, 5223}, /* CJK COMPATIBILITY IDEOGRAPH-2F839 */ + {0x2f83a, 1, 5224}, /* CJK COMPATIBILITY IDEOGRAPH-2F83A */ + {0x2f83b, 1, 5225}, /* CJK COMPATIBILITY IDEOGRAPH-2F83B */ + {0x2f83c, 1, 5226}, /* CJK COMPATIBILITY IDEOGRAPH-2F83C */ + {0x2f83d, 1, 5227}, /* CJK COMPATIBILITY IDEOGRAPH-2F83D */ + {0x2f83e, 1, 5228}, /* CJK COMPATIBILITY IDEOGRAPH-2F83E */ + {0x2f83f, 1, 5229}, /* CJK COMPATIBILITY IDEOGRAPH-2F83F */ + {0x2f840, 1, 5230}, /* CJK COMPATIBILITY IDEOGRAPH-2F840 */ + {0x2f841, 1, 5231}, /* CJK COMPATIBILITY IDEOGRAPH-2F841 */ + {0x2f842, 1, 5232}, /* CJK COMPATIBILITY IDEOGRAPH-2F842 */ + {0x2f843, 1, 5233}, /* CJK COMPATIBILITY IDEOGRAPH-2F843 */ + {0x2f844, 1, 5234}, /* CJK COMPATIBILITY IDEOGRAPH-2F844 */ + {0x2f845, 1, 5235}, /* CJK COMPATIBILITY IDEOGRAPH-2F845 */ + {0x2f846, 1, 5235}, /* CJK COMPATIBILITY IDEOGRAPH-2F846 */ + {0x2f847, 1, 5236}, /* CJK COMPATIBILITY IDEOGRAPH-2F847 */ + {0x2f848, 1, 5237}, /* CJK COMPATIBILITY IDEOGRAPH-2F848 */ + {0x2f849, 1, 5238}, /* CJK COMPATIBILITY IDEOGRAPH-2F849 */ + {0x2f84a, 1, 5239}, /* CJK COMPATIBILITY IDEOGRAPH-2F84A */ + {0x2f84b, 1, 5240}, /* CJK COMPATIBILITY IDEOGRAPH-2F84B */ + {0x2f84c, 1, 4149}, /* CJK COMPATIBILITY IDEOGRAPH-2F84C */ + {0x2f84d, 1, 5241}, /* CJK COMPATIBILITY IDEOGRAPH-2F84D */ + {0x2f84e, 1, 5242}, /* CJK COMPATIBILITY IDEOGRAPH-2F84E */ + {0x2f84f, 1, 5243}, /* CJK COMPATIBILITY IDEOGRAPH-2F84F */ + {0x2f850, 1, 4111}, /* CJK COMPATIBILITY IDEOGRAPH-2F850 */ + {0x2f851, 1, 5244}, /* CJK COMPATIBILITY IDEOGRAPH-2F851 */ + {0x2f852, 1, 5245}, /* CJK COMPATIBILITY IDEOGRAPH-2F852 */ + {0x2f853, 1, 5246}, /* CJK COMPATIBILITY IDEOGRAPH-2F853 */ + {0x2f854, 1, 5247}, /* CJK COMPATIBILITY IDEOGRAPH-2F854 */ + {0x2f855, 1, 5248}, /* CJK COMPATIBILITY IDEOGRAPH-2F855 */ + {0x2f856, 1, 5249}, /* CJK COMPATIBILITY IDEOGRAPH-2F856 */ + {0x2f857, 1, 5250}, /* CJK COMPATIBILITY IDEOGRAPH-2F857 */ + {0x2f858, 1, 5251}, /* CJK COMPATIBILITY IDEOGRAPH-2F858 */ + {0x2f859, 1, 5252}, /* CJK COMPATIBILITY IDEOGRAPH-2F859 */ + {0x2f85a, 1, 5253}, /* CJK COMPATIBILITY IDEOGRAPH-2F85A */ + {0x2f85b, 1, 5254}, /* CJK COMPATIBILITY IDEOGRAPH-2F85B */ + {0x2f85c, 1, 5255}, /* CJK COMPATIBILITY IDEOGRAPH-2F85C */ + {0x2f85d, 1, 5256}, /* CJK COMPATIBILITY IDEOGRAPH-2F85D */ + {0x2f85e, 1, 5257}, /* CJK COMPATIBILITY IDEOGRAPH-2F85E */ + {0x2f85f, 1, 5258}, /* CJK COMPATIBILITY IDEOGRAPH-2F85F */ + {0x2f860, 1, 5259}, /* CJK COMPATIBILITY IDEOGRAPH-2F860 */ + {0x2f861, 1, 5260}, /* CJK COMPATIBILITY IDEOGRAPH-2F861 */ + {0x2f862, 1, 5261}, /* CJK COMPATIBILITY IDEOGRAPH-2F862 */ + {0x2f863, 1, 5262}, /* CJK COMPATIBILITY IDEOGRAPH-2F863 */ + {0x2f864, 1, 5263}, /* CJK COMPATIBILITY IDEOGRAPH-2F864 */ + {0x2f865, 1, 5264}, /* CJK COMPATIBILITY IDEOGRAPH-2F865 */ + {0x2f866, 1, 5265}, /* CJK COMPATIBILITY IDEOGRAPH-2F866 */ + {0x2f867, 1, 5266}, /* CJK COMPATIBILITY IDEOGRAPH-2F867 */ + {0x2f868, 1, 5267}, /* CJK COMPATIBILITY IDEOGRAPH-2F868 */ + {0x2f869, 1, 5268}, /* CJK COMPATIBILITY IDEOGRAPH-2F869 */ + {0x2f86a, 1, 5269}, /* CJK COMPATIBILITY IDEOGRAPH-2F86A */ + {0x2f86b, 1, 5269}, /* CJK COMPATIBILITY IDEOGRAPH-2F86B */ + {0x2f86c, 1, 5270}, /* CJK COMPATIBILITY IDEOGRAPH-2F86C */ + {0x2f86d, 1, 5271}, /* CJK COMPATIBILITY IDEOGRAPH-2F86D */ + {0x2f86e, 1, 5272}, /* CJK COMPATIBILITY IDEOGRAPH-2F86E */ + {0x2f86f, 1, 3961}, /* CJK COMPATIBILITY IDEOGRAPH-2F86F */ + {0x2f870, 1, 5273}, /* CJK COMPATIBILITY IDEOGRAPH-2F870 */ + {0x2f871, 1, 5274}, /* CJK COMPATIBILITY IDEOGRAPH-2F871 */ + {0x2f872, 1, 5275}, /* CJK COMPATIBILITY IDEOGRAPH-2F872 */ + {0x2f873, 1, 5276}, /* CJK COMPATIBILITY IDEOGRAPH-2F873 */ + {0x2f874, 1, 5277}, /* CJK COMPATIBILITY IDEOGRAPH-2F874 */ + {0x2f875, 1, 2415}, /* CJK COMPATIBILITY IDEOGRAPH-2F875 */ + {0x2f876, 1, 5278}, /* CJK COMPATIBILITY IDEOGRAPH-2F876 */ + {0x2f877, 1, 5279}, /* CJK COMPATIBILITY IDEOGRAPH-2F877 */ + {0x2f878, 1, 2417}, /* CJK COMPATIBILITY IDEOGRAPH-2F878 */ + {0x2f879, 1, 5280}, /* CJK COMPATIBILITY IDEOGRAPH-2F879 */ + {0x2f87a, 1, 5281}, /* CJK COMPATIBILITY IDEOGRAPH-2F87A */ + {0x2f87b, 1, 5282}, /* CJK COMPATIBILITY IDEOGRAPH-2F87B */ + {0x2f87c, 1, 5283}, /* CJK COMPATIBILITY IDEOGRAPH-2F87C */ + {0x2f87d, 1, 5284}, /* CJK COMPATIBILITY IDEOGRAPH-2F87D */ + {0x2f87e, 1, 5285}, /* CJK COMPATIBILITY IDEOGRAPH-2F87E */ + {0x2f87f, 1, 5286}, /* CJK COMPATIBILITY IDEOGRAPH-2F87F */ + {0x2f880, 1, 5287}, /* CJK COMPATIBILITY IDEOGRAPH-2F880 */ + {0x2f881, 1, 5288}, /* CJK COMPATIBILITY IDEOGRAPH-2F881 */ + {0x2f882, 1, 5289}, /* CJK COMPATIBILITY IDEOGRAPH-2F882 */ + {0x2f883, 1, 5290}, /* CJK COMPATIBILITY IDEOGRAPH-2F883 */ + {0x2f884, 1, 5291}, /* CJK COMPATIBILITY IDEOGRAPH-2F884 */ + {0x2f885, 1, 5292}, /* CJK COMPATIBILITY IDEOGRAPH-2F885 */ + {0x2f886, 1, 5293}, /* CJK COMPATIBILITY IDEOGRAPH-2F886 */ + {0x2f887, 1, 5294}, /* CJK COMPATIBILITY IDEOGRAPH-2F887 */ + {0x2f888, 1, 5295}, /* CJK COMPATIBILITY IDEOGRAPH-2F888 */ + {0x2f889, 1, 5296}, /* CJK COMPATIBILITY IDEOGRAPH-2F889 */ + {0x2f88a, 1, 5297}, /* CJK COMPATIBILITY IDEOGRAPH-2F88A */ + {0x2f88b, 1, 5298}, /* CJK COMPATIBILITY IDEOGRAPH-2F88B */ + {0x2f88c, 1, 5299}, /* CJK COMPATIBILITY IDEOGRAPH-2F88C */ + {0x2f88d, 1, 5300}, /* CJK COMPATIBILITY IDEOGRAPH-2F88D */ + {0x2f88e, 1, 3909}, /* CJK COMPATIBILITY IDEOGRAPH-2F88E */ + {0x2f88f, 1, 5301}, /* CJK COMPATIBILITY IDEOGRAPH-2F88F */ + {0x2f890, 1, 2427}, /* CJK COMPATIBILITY IDEOGRAPH-2F890 */ + {0x2f891, 1, 5302}, /* CJK COMPATIBILITY IDEOGRAPH-2F891 */ + {0x2f892, 1, 5302}, /* CJK COMPATIBILITY IDEOGRAPH-2F892 */ + {0x2f893, 1, 5303}, /* CJK COMPATIBILITY IDEOGRAPH-2F893 */ + {0x2f894, 1, 5304}, /* CJK COMPATIBILITY IDEOGRAPH-2F894 */ + {0x2f895, 1, 5304}, /* CJK COMPATIBILITY IDEOGRAPH-2F895 */ + {0x2f896, 1, 5305}, /* CJK COMPATIBILITY IDEOGRAPH-2F896 */ + {0x2f897, 1, 5306}, /* CJK COMPATIBILITY IDEOGRAPH-2F897 */ + {0x2f898, 1, 5307}, /* CJK COMPATIBILITY IDEOGRAPH-2F898 */ + {0x2f899, 1, 5308}, /* CJK COMPATIBILITY IDEOGRAPH-2F899 */ + {0x2f89a, 1, 5309}, /* CJK COMPATIBILITY IDEOGRAPH-2F89A */ + {0x2f89b, 1, 5310}, /* CJK COMPATIBILITY IDEOGRAPH-2F89B */ + {0x2f89c, 1, 5311}, /* CJK COMPATIBILITY IDEOGRAPH-2F89C */ + {0x2f89d, 1, 5312}, /* CJK COMPATIBILITY IDEOGRAPH-2F89D */ + {0x2f89e, 1, 5313}, /* CJK COMPATIBILITY IDEOGRAPH-2F89E */ + {0x2f89f, 1, 5314}, /* CJK COMPATIBILITY IDEOGRAPH-2F89F */ + {0x2f8a0, 1, 5315}, /* CJK COMPATIBILITY IDEOGRAPH-2F8A0 */ + {0x2f8a1, 1, 5316}, /* CJK COMPATIBILITY IDEOGRAPH-2F8A1 */ + {0x2f8a2, 1, 5317}, /* CJK COMPATIBILITY IDEOGRAPH-2F8A2 */ + {0x2f8a3, 1, 4154}, /* CJK COMPATIBILITY IDEOGRAPH-2F8A3 */ + {0x2f8a4, 1, 5318}, /* CJK COMPATIBILITY IDEOGRAPH-2F8A4 */ + {0x2f8a5, 1, 5319}, /* CJK COMPATIBILITY IDEOGRAPH-2F8A5 */ + {0x2f8a6, 1, 5320}, /* CJK COMPATIBILITY IDEOGRAPH-2F8A6 */ + {0x2f8a7, 1, 5321}, /* CJK COMPATIBILITY IDEOGRAPH-2F8A7 */ + {0x2f8a8, 1, 5322}, /* CJK COMPATIBILITY IDEOGRAPH-2F8A8 */ + {0x2f8a9, 1, 5321}, /* CJK COMPATIBILITY IDEOGRAPH-2F8A9 */ + {0x2f8aa, 1, 5323}, /* CJK COMPATIBILITY IDEOGRAPH-2F8AA */ + {0x2f8ab, 1, 4156}, /* CJK COMPATIBILITY IDEOGRAPH-2F8AB */ + {0x2f8ac, 1, 5324}, /* CJK COMPATIBILITY IDEOGRAPH-2F8AC */ + {0x2f8ad, 1, 5325}, /* CJK COMPATIBILITY IDEOGRAPH-2F8AD */ + {0x2f8ae, 1, 5326}, /* CJK COMPATIBILITY IDEOGRAPH-2F8AE */ + {0x2f8af, 1, 5327}, /* CJK COMPATIBILITY IDEOGRAPH-2F8AF */ + {0x2f8b0, 1, 4157}, /* CJK COMPATIBILITY IDEOGRAPH-2F8B0 */ + {0x2f8b1, 1, 3882}, /* CJK COMPATIBILITY IDEOGRAPH-2F8B1 */ + {0x2f8b2, 1, 3553}, /* CJK COMPATIBILITY IDEOGRAPH-2F8B2 */ + {0x2f8b3, 1, 5328}, /* CJK COMPATIBILITY IDEOGRAPH-2F8B3 */ + {0x2f8b4, 1, 5329}, /* CJK COMPATIBILITY IDEOGRAPH-2F8B4 */ + {0x2f8b5, 1, 5330}, /* CJK COMPATIBILITY IDEOGRAPH-2F8B5 */ + {0x2f8b6, 1, 5331}, /* CJK COMPATIBILITY IDEOGRAPH-2F8B6 */ + {0x2f8b7, 1, 5332}, /* CJK COMPATIBILITY IDEOGRAPH-2F8B7 */ + {0x2f8b8, 1, 5333}, /* CJK COMPATIBILITY IDEOGRAPH-2F8B8 */ + {0x2f8b9, 1, 5334}, /* CJK COMPATIBILITY IDEOGRAPH-2F8B9 */ + {0x2f8ba, 1, 5335}, /* CJK COMPATIBILITY IDEOGRAPH-2F8BA */ + {0x2f8bb, 1, 5336}, /* CJK COMPATIBILITY IDEOGRAPH-2F8BB */ + {0x2f8bc, 1, 5337}, /* CJK COMPATIBILITY IDEOGRAPH-2F8BC */ + {0x2f8bd, 1, 5338}, /* CJK COMPATIBILITY IDEOGRAPH-2F8BD */ + {0x2f8be, 1, 5339}, /* CJK COMPATIBILITY IDEOGRAPH-2F8BE */ + {0x2f8bf, 1, 5340}, /* CJK COMPATIBILITY IDEOGRAPH-2F8BF */ + {0x2f8c0, 1, 5341}, /* CJK COMPATIBILITY IDEOGRAPH-2F8C0 */ + {0x2f8c1, 1, 5342}, /* CJK COMPATIBILITY IDEOGRAPH-2F8C1 */ + {0x2f8c2, 1, 5343}, /* CJK COMPATIBILITY IDEOGRAPH-2F8C2 */ + {0x2f8c3, 1, 5344}, /* CJK COMPATIBILITY IDEOGRAPH-2F8C3 */ + {0x2f8c4, 1, 5345}, /* CJK COMPATIBILITY IDEOGRAPH-2F8C4 */ + {0x2f8c5, 1, 5346}, /* CJK COMPATIBILITY IDEOGRAPH-2F8C5 */ + {0x2f8c6, 1, 5347}, /* CJK COMPATIBILITY IDEOGRAPH-2F8C6 */ + {0x2f8c7, 1, 5348}, /* CJK COMPATIBILITY IDEOGRAPH-2F8C7 */ + {0x2f8c8, 1, 4158}, /* CJK COMPATIBILITY IDEOGRAPH-2F8C8 */ + {0x2f8c9, 1, 5349}, /* CJK COMPATIBILITY IDEOGRAPH-2F8C9 */ + {0x2f8ca, 1, 5350}, /* CJK COMPATIBILITY IDEOGRAPH-2F8CA */ + {0x2f8cb, 1, 5351}, /* CJK COMPATIBILITY IDEOGRAPH-2F8CB */ + {0x2f8cc, 1, 5352}, /* CJK COMPATIBILITY IDEOGRAPH-2F8CC */ + {0x2f8cd, 1, 5353}, /* CJK COMPATIBILITY IDEOGRAPH-2F8CD */ + {0x2f8ce, 1, 5354}, /* CJK COMPATIBILITY IDEOGRAPH-2F8CE */ + {0x2f8cf, 1, 4160}, /* CJK COMPATIBILITY IDEOGRAPH-2F8CF */ + {0x2f8d0, 1, 5355}, /* CJK COMPATIBILITY IDEOGRAPH-2F8D0 */ + {0x2f8d1, 1, 5356}, /* CJK COMPATIBILITY IDEOGRAPH-2F8D1 */ + {0x2f8d2, 1, 5357}, /* CJK COMPATIBILITY IDEOGRAPH-2F8D2 */ + {0x2f8d3, 1, 5358}, /* CJK COMPATIBILITY IDEOGRAPH-2F8D3 */ + {0x2f8d4, 1, 5359}, /* CJK COMPATIBILITY IDEOGRAPH-2F8D4 */ + {0x2f8d5, 1, 5360}, /* CJK COMPATIBILITY IDEOGRAPH-2F8D5 */ + {0x2f8d6, 1, 5361}, /* CJK COMPATIBILITY IDEOGRAPH-2F8D6 */ + {0x2f8d7, 1, 5362}, /* CJK COMPATIBILITY IDEOGRAPH-2F8D7 */ + {0x2f8d8, 1, 3910}, /* CJK COMPATIBILITY IDEOGRAPH-2F8D8 */ + {0x2f8d9, 1, 5363}, /* CJK COMPATIBILITY IDEOGRAPH-2F8D9 */ + {0x2f8da, 1, 5364}, /* CJK COMPATIBILITY IDEOGRAPH-2F8DA */ + {0x2f8db, 1, 5365}, /* CJK COMPATIBILITY IDEOGRAPH-2F8DB */ + {0x2f8dc, 1, 5366}, /* CJK COMPATIBILITY IDEOGRAPH-2F8DC */ + {0x2f8dd, 1, 5367}, /* CJK COMPATIBILITY IDEOGRAPH-2F8DD */ + {0x2f8de, 1, 5368}, /* CJK COMPATIBILITY IDEOGRAPH-2F8DE */ + {0x2f8df, 1, 5369}, /* CJK COMPATIBILITY IDEOGRAPH-2F8DF */ + {0x2f8e0, 1, 5370}, /* CJK COMPATIBILITY IDEOGRAPH-2F8E0 */ + {0x2f8e1, 1, 5371}, /* CJK COMPATIBILITY IDEOGRAPH-2F8E1 */ + {0x2f8e2, 1, 4161}, /* CJK COMPATIBILITY IDEOGRAPH-2F8E2 */ + {0x2f8e3, 1, 5372}, /* CJK COMPATIBILITY IDEOGRAPH-2F8E3 */ + {0x2f8e4, 1, 5373}, /* CJK COMPATIBILITY IDEOGRAPH-2F8E4 */ + {0x2f8e5, 1, 5374}, /* CJK COMPATIBILITY IDEOGRAPH-2F8E5 */ + {0x2f8e6, 1, 5375}, /* CJK COMPATIBILITY IDEOGRAPH-2F8E6 */ + {0x2f8e7, 1, 5376}, /* CJK COMPATIBILITY IDEOGRAPH-2F8E7 */ + {0x2f8e8, 1, 5377}, /* CJK COMPATIBILITY IDEOGRAPH-2F8E8 */ + {0x2f8e9, 1, 5378}, /* CJK COMPATIBILITY IDEOGRAPH-2F8E9 */ + {0x2f8ea, 1, 5379}, /* CJK COMPATIBILITY IDEOGRAPH-2F8EA */ + {0x2f8eb, 1, 5380}, /* CJK COMPATIBILITY IDEOGRAPH-2F8EB */ + {0x2f8ec, 1, 5381}, /* CJK COMPATIBILITY IDEOGRAPH-2F8EC */ + {0x2f8ed, 1, 5382}, /* CJK COMPATIBILITY IDEOGRAPH-2F8ED */ + {0x2f8ee, 1, 5383}, /* CJK COMPATIBILITY IDEOGRAPH-2F8EE */ + {0x2f8ef, 1, 5384}, /* CJK COMPATIBILITY IDEOGRAPH-2F8EF */ + {0x2f8f0, 1, 5385}, /* CJK COMPATIBILITY IDEOGRAPH-2F8F0 */ + {0x2f8f1, 1, 5386}, /* CJK COMPATIBILITY IDEOGRAPH-2F8F1 */ + {0x2f8f2, 1, 5387}, /* CJK COMPATIBILITY IDEOGRAPH-2F8F2 */ + {0x2f8f3, 1, 5388}, /* CJK COMPATIBILITY IDEOGRAPH-2F8F3 */ + {0x2f8f4, 1, 5389}, /* CJK COMPATIBILITY IDEOGRAPH-2F8F4 */ + {0x2f8f5, 1, 3978}, /* CJK COMPATIBILITY IDEOGRAPH-2F8F5 */ + {0x2f8f6, 1, 5390}, /* CJK COMPATIBILITY IDEOGRAPH-2F8F6 */ + {0x2f8f7, 1, 5391}, /* CJK COMPATIBILITY IDEOGRAPH-2F8F7 */ + {0x2f8f8, 1, 5392}, /* CJK COMPATIBILITY IDEOGRAPH-2F8F8 */ + {0x2f8f9, 1, 5393}, /* CJK COMPATIBILITY IDEOGRAPH-2F8F9 */ + {0x2f8fa, 1, 5394}, /* CJK COMPATIBILITY IDEOGRAPH-2F8FA */ + {0x2f8fb, 1, 5395}, /* CJK COMPATIBILITY IDEOGRAPH-2F8FB */ + {0x2f8fc, 1, 5396}, /* CJK COMPATIBILITY IDEOGRAPH-2F8FC */ + {0x2f8fd, 1, 5397}, /* CJK COMPATIBILITY IDEOGRAPH-2F8FD */ + {0x2f8fe, 1, 5398}, /* CJK COMPATIBILITY IDEOGRAPH-2F8FE */ + {0x2f8ff, 1, 5399}, /* CJK COMPATIBILITY IDEOGRAPH-2F8FF */ + {0x2f900, 1, 5400}, /* CJK COMPATIBILITY IDEOGRAPH-2F900 */ + {0x2f901, 1, 4162}, /* CJK COMPATIBILITY IDEOGRAPH-2F901 */ + {0x2f902, 1, 4061}, /* CJK COMPATIBILITY IDEOGRAPH-2F902 */ + {0x2f903, 1, 5401}, /* CJK COMPATIBILITY IDEOGRAPH-2F903 */ + {0x2f904, 1, 5402}, /* CJK COMPATIBILITY IDEOGRAPH-2F904 */ + {0x2f905, 1, 5403}, /* CJK COMPATIBILITY IDEOGRAPH-2F905 */ + {0x2f906, 1, 5404}, /* CJK COMPATIBILITY IDEOGRAPH-2F906 */ + {0x2f907, 1, 5405}, /* CJK COMPATIBILITY IDEOGRAPH-2F907 */ + {0x2f908, 1, 5406}, /* CJK COMPATIBILITY IDEOGRAPH-2F908 */ + {0x2f909, 1, 5407}, /* CJK COMPATIBILITY IDEOGRAPH-2F909 */ + {0x2f90a, 1, 5408}, /* CJK COMPATIBILITY IDEOGRAPH-2F90A */ + {0x2f90b, 1, 5409}, /* CJK COMPATIBILITY IDEOGRAPH-2F90B */ + {0x2f90c, 1, 5410}, /* CJK COMPATIBILITY IDEOGRAPH-2F90C */ + {0x2f90d, 1, 5411}, /* CJK COMPATIBILITY IDEOGRAPH-2F90D */ + {0x2f90e, 1, 5412}, /* CJK COMPATIBILITY IDEOGRAPH-2F90E */ + {0x2f90f, 1, 5413}, /* CJK COMPATIBILITY IDEOGRAPH-2F90F */ + {0x2f910, 1, 5414}, /* CJK COMPATIBILITY IDEOGRAPH-2F910 */ + {0x2f911, 1, 5415}, /* CJK COMPATIBILITY IDEOGRAPH-2F911 */ + {0x2f912, 1, 5416}, /* CJK COMPATIBILITY IDEOGRAPH-2F912 */ + {0x2f913, 1, 5417}, /* CJK COMPATIBILITY IDEOGRAPH-2F913 */ + {0x2f914, 1, 5418}, /* CJK COMPATIBILITY IDEOGRAPH-2F914 */ + {0x2f915, 1, 5419}, /* CJK COMPATIBILITY IDEOGRAPH-2F915 */ + {0x2f916, 1, 5420}, /* CJK COMPATIBILITY IDEOGRAPH-2F916 */ + {0x2f917, 1, 5421}, /* CJK COMPATIBILITY IDEOGRAPH-2F917 */ + {0x2f918, 1, 5422}, /* CJK COMPATIBILITY IDEOGRAPH-2F918 */ + {0x2f919, 1, 5423}, /* CJK COMPATIBILITY IDEOGRAPH-2F919 */ + {0x2f91a, 1, 5424}, /* CJK COMPATIBILITY IDEOGRAPH-2F91A */ + {0x2f91b, 1, 5425}, /* CJK COMPATIBILITY IDEOGRAPH-2F91B */ + {0x2f91c, 1, 5426}, /* CJK COMPATIBILITY IDEOGRAPH-2F91C */ + {0x2f91d, 1, 5427}, /* CJK COMPATIBILITY IDEOGRAPH-2F91D */ + {0x2f91e, 1, 5428}, /* CJK COMPATIBILITY IDEOGRAPH-2F91E */ + {0x2f91f, 1, 5429}, /* CJK COMPATIBILITY IDEOGRAPH-2F91F */ + {0x2f920, 1, 5430}, /* CJK COMPATIBILITY IDEOGRAPH-2F920 */ + {0x2f921, 1, 5431}, /* CJK COMPATIBILITY IDEOGRAPH-2F921 */ + {0x2f922, 1, 5432}, /* CJK COMPATIBILITY IDEOGRAPH-2F922 */ + {0x2f923, 1, 5433}, /* CJK COMPATIBILITY IDEOGRAPH-2F923 */ + {0x2f924, 1, 5434}, /* CJK COMPATIBILITY IDEOGRAPH-2F924 */ + {0x2f925, 1, 5435}, /* CJK COMPATIBILITY IDEOGRAPH-2F925 */ + {0x2f926, 1, 5436}, /* CJK COMPATIBILITY IDEOGRAPH-2F926 */ + {0x2f927, 1, 5437}, /* CJK COMPATIBILITY IDEOGRAPH-2F927 */ + {0x2f928, 1, 5438}, /* CJK COMPATIBILITY IDEOGRAPH-2F928 */ + {0x2f929, 1, 5439}, /* CJK COMPATIBILITY IDEOGRAPH-2F929 */ + {0x2f92a, 1, 5440}, /* CJK COMPATIBILITY IDEOGRAPH-2F92A */ + {0x2f92b, 1, 5441}, /* CJK COMPATIBILITY IDEOGRAPH-2F92B */ + {0x2f92c, 1, 5442}, /* CJK COMPATIBILITY IDEOGRAPH-2F92C */ + {0x2f92d, 1, 5442}, /* CJK COMPATIBILITY IDEOGRAPH-2F92D */ + {0x2f92e, 1, 5443}, /* CJK COMPATIBILITY IDEOGRAPH-2F92E */ + {0x2f92f, 1, 5444}, /* CJK COMPATIBILITY IDEOGRAPH-2F92F */ + {0x2f930, 1, 5445}, /* CJK COMPATIBILITY IDEOGRAPH-2F930 */ + {0x2f931, 1, 5446}, /* CJK COMPATIBILITY IDEOGRAPH-2F931 */ + {0x2f932, 1, 5447}, /* CJK COMPATIBILITY IDEOGRAPH-2F932 */ + {0x2f933, 1, 5448}, /* CJK COMPATIBILITY IDEOGRAPH-2F933 */ + {0x2f934, 1, 5449}, /* CJK COMPATIBILITY IDEOGRAPH-2F934 */ + {0x2f935, 1, 5450}, /* CJK COMPATIBILITY IDEOGRAPH-2F935 */ + {0x2f936, 1, 5451}, /* CJK COMPATIBILITY IDEOGRAPH-2F936 */ + {0x2f937, 1, 5452}, /* CJK COMPATIBILITY IDEOGRAPH-2F937 */ + {0x2f938, 1, 3964}, /* CJK COMPATIBILITY IDEOGRAPH-2F938 */ + {0x2f939, 1, 5453}, /* CJK COMPATIBILITY IDEOGRAPH-2F939 */ + {0x2f93a, 1, 5454}, /* CJK COMPATIBILITY IDEOGRAPH-2F93A */ + {0x2f93b, 1, 5455}, /* CJK COMPATIBILITY IDEOGRAPH-2F93B */ + {0x2f93c, 1, 5456}, /* CJK COMPATIBILITY IDEOGRAPH-2F93C */ + {0x2f93d, 1, 5457}, /* CJK COMPATIBILITY IDEOGRAPH-2F93D */ + {0x2f93e, 1, 5458}, /* CJK COMPATIBILITY IDEOGRAPH-2F93E */ + {0x2f93f, 1, 5459}, /* CJK COMPATIBILITY IDEOGRAPH-2F93F */ + {0x2f940, 1, 5460}, /* CJK COMPATIBILITY IDEOGRAPH-2F940 */ + {0x2f941, 1, 5461}, /* CJK COMPATIBILITY IDEOGRAPH-2F941 */ + {0x2f942, 1, 5462}, /* CJK COMPATIBILITY IDEOGRAPH-2F942 */ + {0x2f943, 1, 5463}, /* CJK COMPATIBILITY IDEOGRAPH-2F943 */ + {0x2f944, 1, 5464}, /* CJK COMPATIBILITY IDEOGRAPH-2F944 */ + {0x2f945, 1, 5465}, /* CJK COMPATIBILITY IDEOGRAPH-2F945 */ + {0x2f946, 1, 5466}, /* CJK COMPATIBILITY IDEOGRAPH-2F946 */ + {0x2f947, 1, 5466}, /* CJK COMPATIBILITY IDEOGRAPH-2F947 */ + {0x2f948, 1, 5467}, /* CJK COMPATIBILITY IDEOGRAPH-2F948 */ + {0x2f949, 1, 5468}, /* CJK COMPATIBILITY IDEOGRAPH-2F949 */ + {0x2f94a, 1, 5469}, /* CJK COMPATIBILITY IDEOGRAPH-2F94A */ + {0x2f94b, 1, 5470}, /* CJK COMPATIBILITY IDEOGRAPH-2F94B */ + {0x2f94c, 1, 5471}, /* CJK COMPATIBILITY IDEOGRAPH-2F94C */ + {0x2f94d, 1, 5472}, /* CJK COMPATIBILITY IDEOGRAPH-2F94D */ + {0x2f94e, 1, 5473}, /* CJK COMPATIBILITY IDEOGRAPH-2F94E */ + {0x2f94f, 1, 3927}, /* CJK COMPATIBILITY IDEOGRAPH-2F94F */ + {0x2f950, 1, 5474}, /* CJK COMPATIBILITY IDEOGRAPH-2F950 */ + {0x2f951, 1, 5475}, /* CJK COMPATIBILITY IDEOGRAPH-2F951 */ + {0x2f952, 1, 5476}, /* CJK COMPATIBILITY IDEOGRAPH-2F952 */ + {0x2f953, 1, 4172}, /* CJK COMPATIBILITY IDEOGRAPH-2F953 */ + {0x2f954, 1, 5477}, /* CJK COMPATIBILITY IDEOGRAPH-2F954 */ + {0x2f955, 1, 5478}, /* CJK COMPATIBILITY IDEOGRAPH-2F955 */ + {0x2f956, 1, 4131}, /* CJK COMPATIBILITY IDEOGRAPH-2F956 */ + {0x2f957, 1, 5479}, /* CJK COMPATIBILITY IDEOGRAPH-2F957 */ + {0x2f958, 1, 5480}, /* CJK COMPATIBILITY IDEOGRAPH-2F958 */ + {0x2f959, 1, 4175}, /* CJK COMPATIBILITY IDEOGRAPH-2F959 */ + {0x2f95a, 1, 5481}, /* CJK COMPATIBILITY IDEOGRAPH-2F95A */ + {0x2f95b, 1, 5482}, /* CJK COMPATIBILITY IDEOGRAPH-2F95B */ + {0x2f95c, 1, 5483}, /* CJK COMPATIBILITY IDEOGRAPH-2F95C */ + {0x2f95d, 1, 5484}, /* CJK COMPATIBILITY IDEOGRAPH-2F95D */ + {0x2f95e, 1, 5484}, /* CJK COMPATIBILITY IDEOGRAPH-2F95E */ + {0x2f95f, 1, 5485}, /* CJK COMPATIBILITY IDEOGRAPH-2F95F */ + {0x2f960, 1, 5486}, /* CJK COMPATIBILITY IDEOGRAPH-2F960 */ + {0x2f961, 1, 5487}, /* CJK COMPATIBILITY IDEOGRAPH-2F961 */ + {0x2f962, 1, 5488}, /* CJK COMPATIBILITY IDEOGRAPH-2F962 */ + {0x2f963, 1, 5489}, /* CJK COMPATIBILITY IDEOGRAPH-2F963 */ + {0x2f964, 1, 5490}, /* CJK COMPATIBILITY IDEOGRAPH-2F964 */ + {0x2f965, 1, 5491}, /* CJK COMPATIBILITY IDEOGRAPH-2F965 */ + {0x2f966, 1, 5492}, /* CJK COMPATIBILITY IDEOGRAPH-2F966 */ + {0x2f967, 1, 5493}, /* CJK COMPATIBILITY IDEOGRAPH-2F967 */ + {0x2f968, 1, 5494}, /* CJK COMPATIBILITY IDEOGRAPH-2F968 */ + {0x2f969, 1, 5495}, /* CJK COMPATIBILITY IDEOGRAPH-2F969 */ + {0x2f96a, 1, 5496}, /* CJK COMPATIBILITY IDEOGRAPH-2F96A */ + {0x2f96b, 1, 5497}, /* CJK COMPATIBILITY IDEOGRAPH-2F96B */ + {0x2f96c, 1, 5498}, /* CJK COMPATIBILITY IDEOGRAPH-2F96C */ + {0x2f96d, 1, 5499}, /* CJK COMPATIBILITY IDEOGRAPH-2F96D */ + {0x2f96e, 1, 5500}, /* CJK COMPATIBILITY IDEOGRAPH-2F96E */ + {0x2f96f, 1, 5501}, /* CJK COMPATIBILITY IDEOGRAPH-2F96F */ + {0x2f970, 1, 5502}, /* CJK COMPATIBILITY IDEOGRAPH-2F970 */ + {0x2f971, 1, 5503}, /* CJK COMPATIBILITY IDEOGRAPH-2F971 */ + {0x2f972, 1, 5504}, /* CJK COMPATIBILITY IDEOGRAPH-2F972 */ + {0x2f973, 1, 5505}, /* CJK COMPATIBILITY IDEOGRAPH-2F973 */ + {0x2f974, 1, 5506}, /* CJK COMPATIBILITY IDEOGRAPH-2F974 */ + {0x2f975, 1, 5507}, /* CJK COMPATIBILITY IDEOGRAPH-2F975 */ + {0x2f976, 1, 5508}, /* CJK COMPATIBILITY IDEOGRAPH-2F976 */ + {0x2f977, 1, 5509}, /* CJK COMPATIBILITY IDEOGRAPH-2F977 */ + {0x2f978, 1, 5510}, /* CJK COMPATIBILITY IDEOGRAPH-2F978 */ + {0x2f979, 1, 5511}, /* CJK COMPATIBILITY IDEOGRAPH-2F979 */ + {0x2f97a, 1, 4181}, /* CJK COMPATIBILITY IDEOGRAPH-2F97A */ + {0x2f97b, 1, 5512}, /* CJK COMPATIBILITY IDEOGRAPH-2F97B */ + {0x2f97c, 1, 5513}, /* CJK COMPATIBILITY IDEOGRAPH-2F97C */ + {0x2f97d, 1, 5514}, /* CJK COMPATIBILITY IDEOGRAPH-2F97D */ + {0x2f97e, 1, 5515}, /* CJK COMPATIBILITY IDEOGRAPH-2F97E */ + {0x2f97f, 1, 5516}, /* CJK COMPATIBILITY IDEOGRAPH-2F97F */ + {0x2f980, 1, 5517}, /* CJK COMPATIBILITY IDEOGRAPH-2F980 */ + {0x2f981, 1, 5518}, /* CJK COMPATIBILITY IDEOGRAPH-2F981 */ + {0x2f982, 1, 5519}, /* CJK COMPATIBILITY IDEOGRAPH-2F982 */ + {0x2f983, 1, 5520}, /* CJK COMPATIBILITY IDEOGRAPH-2F983 */ + {0x2f984, 1, 5521}, /* CJK COMPATIBILITY IDEOGRAPH-2F984 */ + {0x2f985, 1, 5522}, /* CJK COMPATIBILITY IDEOGRAPH-2F985 */ + {0x2f986, 1, 5523}, /* CJK COMPATIBILITY IDEOGRAPH-2F986 */ + {0x2f987, 1, 5524}, /* CJK COMPATIBILITY IDEOGRAPH-2F987 */ + {0x2f988, 1, 5525}, /* CJK COMPATIBILITY IDEOGRAPH-2F988 */ + {0x2f989, 1, 5526}, /* CJK COMPATIBILITY IDEOGRAPH-2F989 */ + {0x2f98a, 1, 5527}, /* CJK COMPATIBILITY IDEOGRAPH-2F98A */ + {0x2f98b, 1, 5303}, /* CJK COMPATIBILITY IDEOGRAPH-2F98B */ + {0x2f98c, 1, 5528}, /* CJK COMPATIBILITY IDEOGRAPH-2F98C */ + {0x2f98d, 1, 5529}, /* CJK COMPATIBILITY IDEOGRAPH-2F98D */ + {0x2f98e, 1, 5530}, /* CJK COMPATIBILITY IDEOGRAPH-2F98E */ + {0x2f98f, 1, 5531}, /* CJK COMPATIBILITY IDEOGRAPH-2F98F */ + {0x2f990, 1, 5532}, /* CJK COMPATIBILITY IDEOGRAPH-2F990 */ + {0x2f991, 1, 5533}, /* CJK COMPATIBILITY IDEOGRAPH-2F991 */ + {0x2f992, 1, 5534}, /* CJK COMPATIBILITY IDEOGRAPH-2F992 */ + {0x2f993, 1, 5535}, /* CJK COMPATIBILITY IDEOGRAPH-2F993 */ + {0x2f994, 1, 5536}, /* CJK COMPATIBILITY IDEOGRAPH-2F994 */ + {0x2f995, 1, 5537}, /* CJK COMPATIBILITY IDEOGRAPH-2F995 */ + {0x2f996, 1, 5538}, /* CJK COMPATIBILITY IDEOGRAPH-2F996 */ + {0x2f997, 1, 5539}, /* CJK COMPATIBILITY IDEOGRAPH-2F997 */ + {0x2f998, 1, 3981}, /* CJK COMPATIBILITY IDEOGRAPH-2F998 */ + {0x2f999, 1, 5540}, /* CJK COMPATIBILITY IDEOGRAPH-2F999 */ + {0x2f99a, 1, 5541}, /* CJK COMPATIBILITY IDEOGRAPH-2F99A */ + {0x2f99b, 1, 5542}, /* CJK COMPATIBILITY IDEOGRAPH-2F99B */ + {0x2f99c, 1, 5543}, /* CJK COMPATIBILITY IDEOGRAPH-2F99C */ + {0x2f99d, 1, 5544}, /* CJK COMPATIBILITY IDEOGRAPH-2F99D */ + {0x2f99e, 1, 5545}, /* CJK COMPATIBILITY IDEOGRAPH-2F99E */ + {0x2f99f, 1, 4184}, /* CJK COMPATIBILITY IDEOGRAPH-2F99F */ + {0x2f9a0, 1, 5546}, /* CJK COMPATIBILITY IDEOGRAPH-2F9A0 */ + {0x2f9a1, 1, 5547}, /* CJK COMPATIBILITY IDEOGRAPH-2F9A1 */ + {0x2f9a2, 1, 5548}, /* CJK COMPATIBILITY IDEOGRAPH-2F9A2 */ + {0x2f9a3, 1, 5549}, /* CJK COMPATIBILITY IDEOGRAPH-2F9A3 */ + {0x2f9a4, 1, 5550}, /* CJK COMPATIBILITY IDEOGRAPH-2F9A4 */ + {0x2f9a5, 1, 5551}, /* CJK COMPATIBILITY IDEOGRAPH-2F9A5 */ + {0x2f9a6, 1, 5552}, /* CJK COMPATIBILITY IDEOGRAPH-2F9A6 */ + {0x2f9a7, 1, 5553}, /* CJK COMPATIBILITY IDEOGRAPH-2F9A7 */ + {0x2f9a8, 1, 5554}, /* CJK COMPATIBILITY IDEOGRAPH-2F9A8 */ + {0x2f9a9, 1, 5555}, /* CJK COMPATIBILITY IDEOGRAPH-2F9A9 */ + {0x2f9aa, 1, 5556}, /* CJK COMPATIBILITY IDEOGRAPH-2F9AA */ + {0x2f9ab, 1, 5557}, /* CJK COMPATIBILITY IDEOGRAPH-2F9AB */ + {0x2f9ac, 1, 5558}, /* CJK COMPATIBILITY IDEOGRAPH-2F9AC */ + {0x2f9ad, 1, 5559}, /* CJK COMPATIBILITY IDEOGRAPH-2F9AD */ + {0x2f9ae, 1, 5560}, /* CJK COMPATIBILITY IDEOGRAPH-2F9AE */ + {0x2f9af, 1, 5561}, /* CJK COMPATIBILITY IDEOGRAPH-2F9AF */ + {0x2f9b0, 1, 5562}, /* CJK COMPATIBILITY IDEOGRAPH-2F9B0 */ + {0x2f9b1, 1, 5563}, /* CJK COMPATIBILITY IDEOGRAPH-2F9B1 */ + {0x2f9b2, 1, 5564}, /* CJK COMPATIBILITY IDEOGRAPH-2F9B2 */ + {0x2f9b3, 1, 5565}, /* CJK COMPATIBILITY IDEOGRAPH-2F9B3 */ + {0x2f9b4, 1, 3922}, /* CJK COMPATIBILITY IDEOGRAPH-2F9B4 */ + {0x2f9b5, 1, 5566}, /* CJK COMPATIBILITY IDEOGRAPH-2F9B5 */ + {0x2f9b6, 1, 5567}, /* CJK COMPATIBILITY IDEOGRAPH-2F9B6 */ + {0x2f9b7, 1, 5568}, /* CJK COMPATIBILITY IDEOGRAPH-2F9B7 */ + {0x2f9b8, 1, 5569}, /* CJK COMPATIBILITY IDEOGRAPH-2F9B8 */ + {0x2f9b9, 1, 5570}, /* CJK COMPATIBILITY IDEOGRAPH-2F9B9 */ + {0x2f9ba, 1, 5571}, /* CJK COMPATIBILITY IDEOGRAPH-2F9BA */ + {0x2f9bb, 1, 5572}, /* CJK COMPATIBILITY IDEOGRAPH-2F9BB */ + {0x2f9bc, 1, 5573}, /* CJK COMPATIBILITY IDEOGRAPH-2F9BC */ + {0x2f9bd, 1, 5574}, /* CJK COMPATIBILITY IDEOGRAPH-2F9BD */ + {0x2f9be, 1, 5575}, /* CJK COMPATIBILITY IDEOGRAPH-2F9BE */ + {0x2f9bf, 1, 5576}, /* CJK COMPATIBILITY IDEOGRAPH-2F9BF */ + {0x2f9c0, 1, 5577}, /* CJK COMPATIBILITY IDEOGRAPH-2F9C0 */ + {0x2f9c1, 1, 5578}, /* CJK COMPATIBILITY IDEOGRAPH-2F9C1 */ + {0x2f9c2, 1, 5579}, /* CJK COMPATIBILITY IDEOGRAPH-2F9C2 */ + {0x2f9c3, 1, 5580}, /* CJK COMPATIBILITY IDEOGRAPH-2F9C3 */ + {0x2f9c4, 1, 2517}, /* CJK COMPATIBILITY IDEOGRAPH-2F9C4 */ + {0x2f9c5, 1, 5581}, /* CJK COMPATIBILITY IDEOGRAPH-2F9C5 */ + {0x2f9c6, 1, 5582}, /* CJK COMPATIBILITY IDEOGRAPH-2F9C6 */ + {0x2f9c7, 1, 5583}, /* CJK COMPATIBILITY IDEOGRAPH-2F9C7 */ + {0x2f9c8, 1, 5584}, /* CJK COMPATIBILITY IDEOGRAPH-2F9C8 */ + {0x2f9c9, 1, 5585}, /* CJK COMPATIBILITY IDEOGRAPH-2F9C9 */ + {0x2f9ca, 1, 5586}, /* CJK COMPATIBILITY IDEOGRAPH-2F9CA */ + {0x2f9cb, 1, 5587}, /* CJK COMPATIBILITY IDEOGRAPH-2F9CB */ + {0x2f9cc, 1, 5588}, /* CJK COMPATIBILITY IDEOGRAPH-2F9CC */ + {0x2f9cd, 1, 5589}, /* CJK COMPATIBILITY IDEOGRAPH-2F9CD */ + {0x2f9ce, 1, 5590}, /* CJK COMPATIBILITY IDEOGRAPH-2F9CE */ + {0x2f9cf, 1, 5591}, /* CJK COMPATIBILITY IDEOGRAPH-2F9CF */ + {0x2f9d0, 1, 5592}, /* CJK COMPATIBILITY IDEOGRAPH-2F9D0 */ + {0x2f9d1, 1, 5593}, /* CJK COMPATIBILITY IDEOGRAPH-2F9D1 */ + {0x2f9d2, 1, 2524}, /* CJK COMPATIBILITY IDEOGRAPH-2F9D2 */ + {0x2f9d3, 1, 5594}, /* CJK COMPATIBILITY IDEOGRAPH-2F9D3 */ + {0x2f9d4, 1, 5595}, /* CJK COMPATIBILITY IDEOGRAPH-2F9D4 */ + {0x2f9d5, 1, 5596}, /* CJK COMPATIBILITY IDEOGRAPH-2F9D5 */ + {0x2f9d6, 1, 5597}, /* CJK COMPATIBILITY IDEOGRAPH-2F9D6 */ + {0x2f9d7, 1, 5598}, /* CJK COMPATIBILITY IDEOGRAPH-2F9D7 */ + {0x2f9d8, 1, 5599}, /* CJK COMPATIBILITY IDEOGRAPH-2F9D8 */ + {0x2f9d9, 1, 5600}, /* CJK COMPATIBILITY IDEOGRAPH-2F9D9 */ + {0x2f9da, 1, 5601}, /* CJK COMPATIBILITY IDEOGRAPH-2F9DA */ + {0x2f9db, 1, 5602}, /* CJK COMPATIBILITY IDEOGRAPH-2F9DB */ + {0x2f9dc, 1, 5603}, /* CJK COMPATIBILITY IDEOGRAPH-2F9DC */ + {0x2f9dd, 1, 5604}, /* CJK COMPATIBILITY IDEOGRAPH-2F9DD */ + {0x2f9de, 1, 5605}, /* CJK COMPATIBILITY IDEOGRAPH-2F9DE */ + {0x2f9df, 1, 5606}, /* CJK COMPATIBILITY IDEOGRAPH-2F9DF */ + {0x2f9e0, 1, 5607}, /* CJK COMPATIBILITY IDEOGRAPH-2F9E0 */ + {0x2f9e1, 1, 5608}, /* CJK COMPATIBILITY IDEOGRAPH-2F9E1 */ + {0x2f9e2, 1, 5609}, /* CJK COMPATIBILITY IDEOGRAPH-2F9E2 */ + {0x2f9e3, 1, 5610}, /* CJK COMPATIBILITY IDEOGRAPH-2F9E3 */ + {0x2f9e4, 1, 5611}, /* CJK COMPATIBILITY IDEOGRAPH-2F9E4 */ + {0x2f9e5, 1, 5612}, /* CJK COMPATIBILITY IDEOGRAPH-2F9E5 */ + {0x2f9e6, 1, 5613}, /* CJK COMPATIBILITY IDEOGRAPH-2F9E6 */ + {0x2f9e7, 1, 5614}, /* CJK COMPATIBILITY IDEOGRAPH-2F9E7 */ + {0x2f9e8, 1, 5615}, /* CJK COMPATIBILITY IDEOGRAPH-2F9E8 */ + {0x2f9e9, 1, 5616}, /* CJK COMPATIBILITY IDEOGRAPH-2F9E9 */ + {0x2f9ea, 1, 5617}, /* CJK COMPATIBILITY IDEOGRAPH-2F9EA */ + {0x2f9eb, 1, 5618}, /* CJK COMPATIBILITY IDEOGRAPH-2F9EB */ + {0x2f9ec, 1, 5619}, /* CJK COMPATIBILITY IDEOGRAPH-2F9EC */ + {0x2f9ed, 1, 5620}, /* CJK COMPATIBILITY IDEOGRAPH-2F9ED */ + {0x2f9ee, 1, 5621}, /* CJK COMPATIBILITY IDEOGRAPH-2F9EE */ + {0x2f9ef, 1, 5622}, /* CJK COMPATIBILITY IDEOGRAPH-2F9EF */ + {0x2f9f0, 1, 5623}, /* CJK COMPATIBILITY IDEOGRAPH-2F9F0 */ + {0x2f9f1, 1, 5624}, /* CJK COMPATIBILITY IDEOGRAPH-2F9F1 */ + {0x2f9f2, 1, 5625}, /* CJK COMPATIBILITY IDEOGRAPH-2F9F2 */ + {0x2f9f3, 1, 5626}, /* CJK COMPATIBILITY IDEOGRAPH-2F9F3 */ + {0x2f9f4, 1, 5627}, /* CJK COMPATIBILITY IDEOGRAPH-2F9F4 */ + {0x2f9f5, 1, 5628}, /* CJK COMPATIBILITY IDEOGRAPH-2F9F5 */ + {0x2f9f6, 1, 5629}, /* CJK COMPATIBILITY IDEOGRAPH-2F9F6 */ + {0x2f9f7, 1, 5630}, /* CJK COMPATIBILITY IDEOGRAPH-2F9F7 */ + {0x2f9f8, 1, 5631}, /* CJK COMPATIBILITY IDEOGRAPH-2F9F8 */ + {0x2f9f9, 1, 5632}, /* CJK COMPATIBILITY IDEOGRAPH-2F9F9 */ + {0x2f9fa, 1, 5633}, /* CJK COMPATIBILITY IDEOGRAPH-2F9FA */ + {0x2f9fb, 1, 5634}, /* CJK COMPATIBILITY IDEOGRAPH-2F9FB */ + {0x2f9fc, 1, 5635}, /* CJK COMPATIBILITY IDEOGRAPH-2F9FC */ + {0x2f9fd, 1, 5636}, /* CJK COMPATIBILITY IDEOGRAPH-2F9FD */ + {0x2f9fe, 1, 5637}, /* CJK COMPATIBILITY IDEOGRAPH-2F9FE */ + {0x2f9ff, 1, 5637}, /* CJK COMPATIBILITY IDEOGRAPH-2F9FF */ + {0x2fa00, 1, 5638}, /* CJK COMPATIBILITY IDEOGRAPH-2FA00 */ + {0x2fa01, 1, 5639}, /* CJK COMPATIBILITY IDEOGRAPH-2FA01 */ + {0x2fa02, 1, 5640}, /* CJK COMPATIBILITY IDEOGRAPH-2FA02 */ + {0x2fa03, 1, 5641}, /* CJK COMPATIBILITY IDEOGRAPH-2FA03 */ + {0x2fa04, 1, 5642}, /* CJK COMPATIBILITY IDEOGRAPH-2FA04 */ + {0x2fa05, 1, 5643}, /* CJK COMPATIBILITY IDEOGRAPH-2FA05 */ + {0x2fa06, 1, 5644}, /* CJK COMPATIBILITY IDEOGRAPH-2FA06 */ + {0x2fa07, 1, 5645}, /* CJK COMPATIBILITY IDEOGRAPH-2FA07 */ + {0x2fa08, 1, 5646}, /* CJK COMPATIBILITY IDEOGRAPH-2FA08 */ + {0x2fa09, 1, 5647}, /* CJK COMPATIBILITY IDEOGRAPH-2FA09 */ + {0x2fa0a, 1, 5648}, /* CJK COMPATIBILITY IDEOGRAPH-2FA0A */ + {0x2fa0b, 1, 5649}, /* CJK COMPATIBILITY IDEOGRAPH-2FA0B */ + {0x2fa0c, 1, 5650}, /* CJK COMPATIBILITY IDEOGRAPH-2FA0C */ + {0x2fa0d, 1, 5651}, /* CJK COMPATIBILITY IDEOGRAPH-2FA0D */ + {0x2fa0e, 1, 5652}, /* CJK COMPATIBILITY IDEOGRAPH-2FA0E */ + {0x2fa0f, 1, 5653}, /* CJK COMPATIBILITY IDEOGRAPH-2FA0F */ + {0x2fa10, 1, 5654}, /* CJK COMPATIBILITY IDEOGRAPH-2FA10 */ + {0x2fa11, 1, 5655}, /* CJK COMPATIBILITY IDEOGRAPH-2FA11 */ + {0x2fa12, 1, 5656}, /* CJK COMPATIBILITY IDEOGRAPH-2FA12 */ + {0x2fa13, 1, 5657}, /* CJK COMPATIBILITY IDEOGRAPH-2FA13 */ + {0x2fa14, 1, 5658}, /* CJK COMPATIBILITY IDEOGRAPH-2FA14 */ + {0x2fa15, 1, 2572}, /* CJK COMPATIBILITY IDEOGRAPH-2FA15 */ + {0x2fa16, 1, 5659}, /* CJK COMPATIBILITY IDEOGRAPH-2FA16 */ + {0x2fa17, 1, 2576}, /* CJK COMPATIBILITY IDEOGRAPH-2FA17 */ + {0x2fa18, 1, 5660}, /* CJK COMPATIBILITY IDEOGRAPH-2FA18 */ + {0x2fa19, 1, 5661}, /* CJK COMPATIBILITY IDEOGRAPH-2FA19 */ + {0x2fa1a, 1, 5662}, /* CJK COMPATIBILITY IDEOGRAPH-2FA1A */ + {0x2fa1b, 1, 5663}, /* CJK COMPATIBILITY IDEOGRAPH-2FA1B */ + {0x2fa1c, 1, 2581}, /* CJK COMPATIBILITY IDEOGRAPH-2FA1C */ + {0x2fa1d, 1, 5664}, /* CJK COMPATIBILITY IDEOGRAPH-2FA1D */ +}; + +const size_t _wind_normalize_table_size = 5224; + +const uint32_t _wind_normalize_val_table[] = { + 0x20, + 0x20, + 0x308, + 0x61, + 0x20, + 0x304, + 0x32, + 0x33, + 0x20, + 0x301, + 0x3bc, + 0x20, + 0x327, + 0x31, + 0x6f, + 0x31, + 0x2044, + 0x34, + 0x31, + 0x2044, + 0x32, + 0x33, + 0x2044, + 0x34, + 0x41, + 0x300, + 0x41, + 0x301, + 0x41, + 0x302, + 0x41, + 0x303, + 0x41, + 0x308, + 0x41, + 0x30a, + 0x43, + 0x327, + 0x45, + 0x300, + 0x45, + 0x301, + 0x45, + 0x302, + 0x45, + 0x308, + 0x49, + 0x300, + 0x49, + 0x301, + 0x49, + 0x302, + 0x49, + 0x308, + 0x4e, + 0x303, + 0x4f, + 0x300, + 0x4f, + 0x301, + 0x4f, + 0x302, + 0x4f, + 0x303, + 0x4f, + 0x308, + 0x55, + 0x300, + 0x55, + 0x301, + 0x55, + 0x302, + 0x55, + 0x308, + 0x59, + 0x301, + 0x61, + 0x300, + 0x61, + 0x301, + 0x61, + 0x302, + 0x61, + 0x303, + 0x61, + 0x308, + 0x61, + 0x30a, + 0x63, + 0x327, + 0x65, + 0x300, + 0x65, + 0x301, + 0x65, + 0x302, + 0x65, + 0x308, + 0x69, + 0x300, + 0x69, + 0x301, + 0x69, + 0x302, + 0x69, + 0x308, + 0x6e, + 0x303, + 0x6f, + 0x300, + 0x6f, + 0x301, + 0x6f, + 0x302, + 0x6f, + 0x303, + 0x6f, + 0x308, + 0x75, + 0x300, + 0x75, + 0x301, + 0x75, + 0x302, + 0x75, + 0x308, + 0x79, + 0x301, + 0x79, + 0x308, + 0x41, + 0x304, + 0x61, + 0x304, + 0x41, + 0x306, + 0x61, + 0x306, + 0x41, + 0x328, + 0x61, + 0x328, + 0x43, + 0x301, + 0x63, + 0x301, + 0x43, + 0x302, + 0x63, + 0x302, + 0x43, + 0x307, + 0x63, + 0x307, + 0x43, + 0x30c, + 0x63, + 0x30c, + 0x44, + 0x30c, + 0x64, + 0x30c, + 0x45, + 0x304, + 0x65, + 0x304, + 0x45, + 0x306, + 0x65, + 0x306, + 0x45, + 0x307, + 0x65, + 0x307, + 0x45, + 0x328, + 0x65, + 0x328, + 0x45, + 0x30c, + 0x65, + 0x30c, + 0x47, + 0x302, + 0x67, + 0x302, + 0x47, + 0x306, + 0x67, + 0x306, + 0x47, + 0x307, + 0x67, + 0x307, + 0x47, + 0x327, + 0x67, + 0x327, + 0x48, + 0x302, + 0x68, + 0x302, + 0x49, + 0x303, + 0x69, + 0x303, + 0x49, + 0x304, + 0x69, + 0x304, + 0x49, + 0x306, + 0x69, + 0x306, + 0x49, + 0x328, + 0x69, + 0x328, + 0x49, + 0x307, + 0x49, + 0x4a, + 0x69, + 0x6a, + 0x4a, + 0x302, + 0x6a, + 0x302, + 0x4b, + 0x327, + 0x6b, + 0x327, + 0x4c, + 0x301, + 0x6c, + 0x301, + 0x4c, + 0x327, + 0x6c, + 0x327, + 0x4c, + 0x30c, + 0x6c, + 0x30c, + 0x4c, + 0xb7, + 0x6c, + 0xb7, + 0x4e, + 0x301, + 0x6e, + 0x301, + 0x4e, + 0x327, + 0x6e, + 0x327, + 0x4e, + 0x30c, + 0x6e, + 0x30c, + 0x2bc, + 0x6e, + 0x4f, + 0x304, + 0x6f, + 0x304, + 0x4f, + 0x306, + 0x6f, + 0x306, + 0x4f, + 0x30b, + 0x6f, + 0x30b, + 0x52, + 0x301, + 0x72, + 0x301, + 0x52, + 0x327, + 0x72, + 0x327, + 0x52, + 0x30c, + 0x72, + 0x30c, + 0x53, + 0x301, + 0x73, + 0x301, + 0x53, + 0x302, + 0x73, + 0x302, + 0x53, + 0x327, + 0x73, + 0x327, + 0x53, + 0x30c, + 0x73, + 0x30c, + 0x54, + 0x327, + 0x74, + 0x327, + 0x54, + 0x30c, + 0x74, + 0x30c, + 0x55, + 0x303, + 0x75, + 0x303, + 0x55, + 0x304, + 0x75, + 0x304, + 0x55, + 0x306, + 0x75, + 0x306, + 0x55, + 0x30a, + 0x75, + 0x30a, + 0x55, + 0x30b, + 0x75, + 0x30b, + 0x55, + 0x328, + 0x75, + 0x328, + 0x57, + 0x302, + 0x77, + 0x302, + 0x59, + 0x302, + 0x79, + 0x302, + 0x59, + 0x308, + 0x5a, + 0x301, + 0x7a, + 0x301, + 0x5a, + 0x307, + 0x7a, + 0x307, + 0x5a, + 0x30c, + 0x7a, + 0x30c, + 0x4f, + 0x31b, + 0x6f, + 0x31b, + 0x55, + 0x31b, + 0x75, + 0x31b, + 0x44, + 0x17d, + 0x44, + 0x17e, + 0x64, + 0x17e, + 0x4c, + 0x4a, + 0x4c, + 0x6a, + 0x6c, + 0x6a, + 0x4e, + 0x4a, + 0x4e, + 0x6a, + 0x6e, + 0x6a, + 0x41, + 0x30c, + 0x61, + 0x30c, + 0x49, + 0x30c, + 0x69, + 0x30c, + 0x4f, + 0x30c, + 0x6f, + 0x30c, + 0x55, + 0x30c, + 0x75, + 0x30c, + 0xdc, + 0x304, + 0xfc, + 0x304, + 0xdc, + 0x301, + 0xfc, + 0x301, + 0xdc, + 0x30c, + 0xfc, + 0x30c, + 0xdc, + 0x300, + 0xfc, + 0x300, + 0xc4, + 0x304, + 0xe4, + 0x304, + 0x226, + 0x304, + 0x227, + 0x304, + 0xc6, + 0x304, + 0xe6, + 0x304, + 0x47, + 0x30c, + 0x67, + 0x30c, + 0x4b, + 0x30c, + 0x6b, + 0x30c, + 0x4f, + 0x328, + 0x6f, + 0x328, + 0x1ea, + 0x304, + 0x1eb, + 0x304, + 0x1b7, + 0x30c, + 0x292, + 0x30c, + 0x6a, + 0x30c, + 0x44, + 0x5a, + 0x44, + 0x7a, + 0x64, + 0x7a, + 0x47, + 0x301, + 0x67, + 0x301, + 0x4e, + 0x300, + 0x6e, + 0x300, + 0xc5, + 0x301, + 0xe5, + 0x301, + 0xc6, + 0x301, + 0xe6, + 0x301, + 0xd8, + 0x301, + 0xf8, + 0x301, + 0x41, + 0x30f, + 0x61, + 0x30f, + 0x41, + 0x311, + 0x61, + 0x311, + 0x45, + 0x30f, + 0x65, + 0x30f, + 0x45, + 0x311, + 0x65, + 0x311, + 0x49, + 0x30f, + 0x69, + 0x30f, + 0x49, + 0x311, + 0x69, + 0x311, + 0x4f, + 0x30f, + 0x6f, + 0x30f, + 0x4f, + 0x311, + 0x6f, + 0x311, + 0x52, + 0x30f, + 0x72, + 0x30f, + 0x52, + 0x311, + 0x72, + 0x311, + 0x55, + 0x30f, + 0x75, + 0x30f, + 0x55, + 0x311, + 0x75, + 0x311, + 0x53, + 0x326, + 0x73, + 0x326, + 0x54, + 0x326, + 0x74, + 0x326, + 0x48, + 0x30c, + 0x68, + 0x30c, + 0x41, + 0x307, + 0x61, + 0x307, + 0x45, + 0x327, + 0x65, + 0x327, + 0xd6, + 0x304, + 0xf6, + 0x304, + 0xd5, + 0x304, + 0xf5, + 0x304, + 0x4f, + 0x307, + 0x6f, + 0x307, + 0x22e, + 0x304, + 0x22f, + 0x304, + 0x59, + 0x304, + 0x79, + 0x304, + 0x266, + 0x279, + 0x27b, + 0x281, + 0x20, + 0x306, + 0x20, + 0x307, + 0x20, + 0x30a, + 0x20, + 0x328, + 0x20, + 0x303, + 0x20, + 0x30b, + 0x263, + 0x78, + 0x295, + 0x313, + 0x308, + 0x301, + 0x2b9, + 0x20, + 0x345, + 0x3b, + 0xa8, + 0x301, + 0x391, + 0x301, + 0x395, + 0x301, + 0x397, + 0x301, + 0x399, + 0x301, + 0x39f, + 0x301, + 0x3a5, + 0x301, + 0x3a9, + 0x301, + 0x3ca, + 0x301, + 0x399, + 0x308, + 0x3a5, + 0x308, + 0x3b1, + 0x301, + 0x3b5, + 0x301, + 0x3b7, + 0x301, + 0x3b9, + 0x301, + 0x3cb, + 0x301, + 0x3b9, + 0x308, + 0x3c5, + 0x308, + 0x3bf, + 0x301, + 0x3c5, + 0x301, + 0x3c9, + 0x301, + 0x3b2, + 0x3b8, + 0x3d2, + 0x301, + 0x3d2, + 0x308, + 0x3c6, + 0x3c0, + 0x3ba, + 0x3c1, + 0x3c2, + 0x398, + 0x3a3, + 0x415, + 0x300, + 0x415, + 0x308, + 0x413, + 0x301, + 0x406, + 0x308, + 0x41a, + 0x301, + 0x418, + 0x300, + 0x423, + 0x306, + 0x418, + 0x306, + 0x438, + 0x306, + 0x435, + 0x300, + 0x435, + 0x308, + 0x433, + 0x301, + 0x456, + 0x308, + 0x43a, + 0x301, + 0x438, + 0x300, + 0x443, + 0x306, + 0x474, + 0x30f, + 0x475, + 0x30f, + 0x416, + 0x306, + 0x436, + 0x306, + 0x410, + 0x306, + 0x430, + 0x306, + 0x410, + 0x308, + 0x430, + 0x308, + 0x415, + 0x306, + 0x435, + 0x306, + 0x4d8, + 0x308, + 0x4d9, + 0x308, + 0x416, + 0x308, + 0x436, + 0x308, + 0x417, + 0x308, + 0x437, + 0x308, + 0x418, + 0x304, + 0x438, + 0x304, + 0x418, + 0x308, + 0x438, + 0x308, + 0x41e, + 0x308, + 0x43e, + 0x308, + 0x4e8, + 0x308, + 0x4e9, + 0x308, + 0x42d, + 0x308, + 0x44d, + 0x308, + 0x423, + 0x304, + 0x443, + 0x304, + 0x423, + 0x308, + 0x443, + 0x308, + 0x423, + 0x30b, + 0x443, + 0x30b, + 0x427, + 0x308, + 0x447, + 0x308, + 0x42b, + 0x308, + 0x44b, + 0x308, + 0x565, + 0x582, + 0x627, + 0x653, + 0x627, + 0x654, + 0x648, + 0x654, + 0x627, + 0x655, + 0x64a, + 0x654, + 0x627, + 0x674, + 0x648, + 0x674, + 0x6c7, + 0x674, + 0x64a, + 0x674, + 0x6d5, + 0x654, + 0x6c1, + 0x654, + 0x6d2, + 0x654, + 0x928, + 0x93c, + 0x930, + 0x93c, + 0x933, + 0x93c, + 0x915, + 0x93c, + 0x916, + 0x93c, + 0x917, + 0x93c, + 0x91c, + 0x93c, + 0x921, + 0x93c, + 0x922, + 0x93c, + 0x92b, + 0x93c, + 0x92f, + 0x93c, + 0x9c7, + 0x9be, + 0x9c7, + 0x9d7, + 0x9a1, + 0x9bc, + 0x9a2, + 0x9bc, + 0x9af, + 0x9bc, + 0xa32, + 0xa3c, + 0xa38, + 0xa3c, + 0xa16, + 0xa3c, + 0xa17, + 0xa3c, + 0xa1c, + 0xa3c, + 0xa2b, + 0xa3c, + 0xb47, + 0xb56, + 0xb47, + 0xb3e, + 0xb47, + 0xb57, + 0xb21, + 0xb3c, + 0xb22, + 0xb3c, + 0xb92, + 0xbd7, + 0xbc6, + 0xbbe, + 0xbc7, + 0xbbe, + 0xbc6, + 0xbd7, + 0xc46, + 0xc56, + 0xcbf, + 0xcd5, + 0xcc6, + 0xcd5, + 0xcc6, + 0xcd6, + 0xcc6, + 0xcc2, + 0xcca, + 0xcd5, + 0xd46, + 0xd3e, + 0xd47, + 0xd3e, + 0xd46, + 0xd57, + 0xdd9, + 0xdca, + 0xdd9, + 0xdcf, + 0xddc, + 0xdca, + 0xdd9, + 0xddf, + 0xe4d, + 0xe32, + 0xecd, + 0xeb2, + 0xeab, + 0xe99, + 0xeab, + 0xea1, + 0xf0b, + 0xf42, + 0xfb7, + 0xf4c, + 0xfb7, + 0xf51, + 0xfb7, + 0xf56, + 0xfb7, + 0xf5b, + 0xfb7, + 0xf40, + 0xfb5, + 0xf71, + 0xf72, + 0xf71, + 0xf74, + 0xfb2, + 0xf80, + 0xfb2, + 0xf81, + 0xfb3, + 0xf80, + 0xfb3, + 0xf81, + 0xf71, + 0xf80, + 0xf92, + 0xfb7, + 0xf9c, + 0xfb7, + 0xfa1, + 0xfb7, + 0xfa6, + 0xfb7, + 0xfab, + 0xfb7, + 0xf90, + 0xfb5, + 0x1025, + 0x102e, + 0x42, + 0x18e, + 0x4d, + 0x222, + 0x50, + 0x250, + 0x251, + 0x1d02, + 0x62, + 0x259, + 0x25b, + 0x25c, + 0x6d, + 0x14b, + 0x254, + 0x1d16, + 0x1d17, + 0x70, + 0x1d1d, + 0x26f, + 0x76, + 0x1d25, + 0x3b3, + 0x3b4, + 0x3c7, + 0x41, + 0x325, + 0x61, + 0x325, + 0x42, + 0x307, + 0x62, + 0x307, + 0x42, + 0x323, + 0x62, + 0x323, + 0x42, + 0x331, + 0x62, + 0x331, + 0xc7, + 0x301, + 0xe7, + 0x301, + 0x44, + 0x307, + 0x64, + 0x307, + 0x44, + 0x323, + 0x64, + 0x323, + 0x44, + 0x331, + 0x64, + 0x331, + 0x44, + 0x327, + 0x64, + 0x327, + 0x44, + 0x32d, + 0x64, + 0x32d, + 0x112, + 0x300, + 0x113, + 0x300, + 0x112, + 0x301, + 0x113, + 0x301, + 0x45, + 0x32d, + 0x65, + 0x32d, + 0x45, + 0x330, + 0x65, + 0x330, + 0x228, + 0x306, + 0x229, + 0x306, + 0x46, + 0x307, + 0x66, + 0x307, + 0x47, + 0x304, + 0x67, + 0x304, + 0x48, + 0x307, + 0x68, + 0x307, + 0x48, + 0x323, + 0x68, + 0x323, + 0x48, + 0x308, + 0x68, + 0x308, + 0x48, + 0x327, + 0x68, + 0x327, + 0x48, + 0x32e, + 0x68, + 0x32e, + 0x49, + 0x330, + 0x69, + 0x330, + 0xcf, + 0x301, + 0xef, + 0x301, + 0x4b, + 0x301, + 0x6b, + 0x301, + 0x4b, + 0x323, + 0x6b, + 0x323, + 0x4b, + 0x331, + 0x6b, + 0x331, + 0x4c, + 0x323, + 0x6c, + 0x323, + 0x1e36, + 0x304, + 0x1e37, + 0x304, + 0x4c, + 0x331, + 0x6c, + 0x331, + 0x4c, + 0x32d, + 0x6c, + 0x32d, + 0x4d, + 0x301, + 0x6d, + 0x301, + 0x4d, + 0x307, + 0x6d, + 0x307, + 0x4d, + 0x323, + 0x6d, + 0x323, + 0x4e, + 0x307, + 0x6e, + 0x307, + 0x4e, + 0x323, + 0x6e, + 0x323, + 0x4e, + 0x331, + 0x6e, + 0x331, + 0x4e, + 0x32d, + 0x6e, + 0x32d, + 0xd5, + 0x301, + 0xf5, + 0x301, + 0xd5, + 0x308, + 0xf5, + 0x308, + 0x14c, + 0x300, + 0x14d, + 0x300, + 0x14c, + 0x301, + 0x14d, + 0x301, + 0x50, + 0x301, + 0x70, + 0x301, + 0x50, + 0x307, + 0x70, + 0x307, + 0x52, + 0x307, + 0x72, + 0x307, + 0x52, + 0x323, + 0x72, + 0x323, + 0x1e5a, + 0x304, + 0x1e5b, + 0x304, + 0x52, + 0x331, + 0x72, + 0x331, + 0x53, + 0x307, + 0x73, + 0x307, + 0x53, + 0x323, + 0x73, + 0x323, + 0x15a, + 0x307, + 0x15b, + 0x307, + 0x160, + 0x307, + 0x161, + 0x307, + 0x1e62, + 0x307, + 0x1e63, + 0x307, + 0x54, + 0x307, + 0x74, + 0x307, + 0x54, + 0x323, + 0x74, + 0x323, + 0x54, + 0x331, + 0x74, + 0x331, + 0x54, + 0x32d, + 0x74, + 0x32d, + 0x55, + 0x324, + 0x75, + 0x324, + 0x55, + 0x330, + 0x75, + 0x330, + 0x55, + 0x32d, + 0x75, + 0x32d, + 0x168, + 0x301, + 0x169, + 0x301, + 0x16a, + 0x308, + 0x16b, + 0x308, + 0x56, + 0x303, + 0x76, + 0x303, + 0x56, + 0x323, + 0x76, + 0x323, + 0x57, + 0x300, + 0x77, + 0x300, + 0x57, + 0x301, + 0x77, + 0x301, + 0x57, + 0x308, + 0x77, + 0x308, + 0x57, + 0x307, + 0x77, + 0x307, + 0x57, + 0x323, + 0x77, + 0x323, + 0x58, + 0x307, + 0x78, + 0x307, + 0x58, + 0x308, + 0x78, + 0x308, + 0x59, + 0x307, + 0x79, + 0x307, + 0x5a, + 0x302, + 0x7a, + 0x302, + 0x5a, + 0x323, + 0x7a, + 0x323, + 0x5a, + 0x331, + 0x7a, + 0x331, + 0x68, + 0x331, + 0x74, + 0x308, + 0x77, + 0x30a, + 0x79, + 0x30a, + 0x61, + 0x2be, + 0x17f, + 0x307, + 0x41, + 0x323, + 0x61, + 0x323, + 0x41, + 0x309, + 0x61, + 0x309, + 0xc2, + 0x301, + 0xe2, + 0x301, + 0xc2, + 0x300, + 0xe2, + 0x300, + 0xc2, + 0x309, + 0xe2, + 0x309, + 0xc2, + 0x303, + 0xe2, + 0x303, + 0x1ea0, + 0x302, + 0x1ea1, + 0x302, + 0x102, + 0x301, + 0x103, + 0x301, + 0x102, + 0x300, + 0x103, + 0x300, + 0x102, + 0x309, + 0x103, + 0x309, + 0x102, + 0x303, + 0x103, + 0x303, + 0x1ea0, + 0x306, + 0x1ea1, + 0x306, + 0x45, + 0x323, + 0x65, + 0x323, + 0x45, + 0x309, + 0x65, + 0x309, + 0x45, + 0x303, + 0x65, + 0x303, + 0xca, + 0x301, + 0xea, + 0x301, + 0xca, + 0x300, + 0xea, + 0x300, + 0xca, + 0x309, + 0xea, + 0x309, + 0xca, + 0x303, + 0xea, + 0x303, + 0x1eb8, + 0x302, + 0x1eb9, + 0x302, + 0x49, + 0x309, + 0x69, + 0x309, + 0x49, + 0x323, + 0x69, + 0x323, + 0x4f, + 0x323, + 0x6f, + 0x323, + 0x4f, + 0x309, + 0x6f, + 0x309, + 0xd4, + 0x301, + 0xf4, + 0x301, + 0xd4, + 0x300, + 0xf4, + 0x300, + 0xd4, + 0x309, + 0xf4, + 0x309, + 0xd4, + 0x303, + 0xf4, + 0x303, + 0x1ecc, + 0x302, + 0x1ecd, + 0x302, + 0x1a0, + 0x301, + 0x1a1, + 0x301, + 0x1a0, + 0x300, + 0x1a1, + 0x300, + 0x1a0, + 0x309, + 0x1a1, + 0x309, + 0x1a0, + 0x303, + 0x1a1, + 0x303, + 0x1a0, + 0x323, + 0x1a1, + 0x323, + 0x55, + 0x323, + 0x75, + 0x323, + 0x55, + 0x309, + 0x75, + 0x309, + 0x1af, + 0x301, + 0x1b0, + 0x301, + 0x1af, + 0x300, + 0x1b0, + 0x300, + 0x1af, + 0x309, + 0x1b0, + 0x309, + 0x1af, + 0x303, + 0x1b0, + 0x303, + 0x1af, + 0x323, + 0x1b0, + 0x323, + 0x59, + 0x300, + 0x79, + 0x300, + 0x59, + 0x323, + 0x79, + 0x323, + 0x59, + 0x309, + 0x79, + 0x309, + 0x59, + 0x303, + 0x79, + 0x303, + 0x3b1, + 0x313, + 0x3b1, + 0x314, + 0x1f00, + 0x300, + 0x1f01, + 0x300, + 0x1f00, + 0x301, + 0x1f01, + 0x301, + 0x1f00, + 0x342, + 0x1f01, + 0x342, + 0x391, + 0x313, + 0x391, + 0x314, + 0x1f08, + 0x300, + 0x1f09, + 0x300, + 0x1f08, + 0x301, + 0x1f09, + 0x301, + 0x1f08, + 0x342, + 0x1f09, + 0x342, + 0x3b5, + 0x313, + 0x3b5, + 0x314, + 0x1f10, + 0x300, + 0x1f11, + 0x300, + 0x1f10, + 0x301, + 0x1f11, + 0x301, + 0x395, + 0x313, + 0x395, + 0x314, + 0x1f18, + 0x300, + 0x1f19, + 0x300, + 0x1f18, + 0x301, + 0x1f19, + 0x301, + 0x3b7, + 0x313, + 0x3b7, + 0x314, + 0x1f20, + 0x300, + 0x1f21, + 0x300, + 0x1f20, + 0x301, + 0x1f21, + 0x301, + 0x1f20, + 0x342, + 0x1f21, + 0x342, + 0x397, + 0x313, + 0x397, + 0x314, + 0x1f28, + 0x300, + 0x1f29, + 0x300, + 0x1f28, + 0x301, + 0x1f29, + 0x301, + 0x1f28, + 0x342, + 0x1f29, + 0x342, + 0x3b9, + 0x313, + 0x3b9, + 0x314, + 0x1f30, + 0x300, + 0x1f31, + 0x300, + 0x1f30, + 0x301, + 0x1f31, + 0x301, + 0x1f30, + 0x342, + 0x1f31, + 0x342, + 0x399, + 0x313, + 0x399, + 0x314, + 0x1f38, + 0x300, + 0x1f39, + 0x300, + 0x1f38, + 0x301, + 0x1f39, + 0x301, + 0x1f38, + 0x342, + 0x1f39, + 0x342, + 0x3bf, + 0x313, + 0x3bf, + 0x314, + 0x1f40, + 0x300, + 0x1f41, + 0x300, + 0x1f40, + 0x301, + 0x1f41, + 0x301, + 0x39f, + 0x313, + 0x39f, + 0x314, + 0x1f48, + 0x300, + 0x1f49, + 0x300, + 0x1f48, + 0x301, + 0x1f49, + 0x301, + 0x3c5, + 0x313, + 0x3c5, + 0x314, + 0x1f50, + 0x300, + 0x1f51, + 0x300, + 0x1f50, + 0x301, + 0x1f51, + 0x301, + 0x1f50, + 0x342, + 0x1f51, + 0x342, + 0x3a5, + 0x314, + 0x1f59, + 0x300, + 0x1f59, + 0x301, + 0x1f59, + 0x342, + 0x3c9, + 0x313, + 0x3c9, + 0x314, + 0x1f60, + 0x300, + 0x1f61, + 0x300, + 0x1f60, + 0x301, + 0x1f61, + 0x301, + 0x1f60, + 0x342, + 0x1f61, + 0x342, + 0x3a9, + 0x313, + 0x3a9, + 0x314, + 0x1f68, + 0x300, + 0x1f69, + 0x300, + 0x1f68, + 0x301, + 0x1f69, + 0x301, + 0x1f68, + 0x342, + 0x1f69, + 0x342, + 0x3b1, + 0x300, + 0x3ac, + 0x3b5, + 0x300, + 0x3ad, + 0x3b7, + 0x300, + 0x3ae, + 0x3b9, + 0x300, + 0x3af, + 0x3bf, + 0x300, + 0x3cc, + 0x3c5, + 0x300, + 0x3cd, + 0x3c9, + 0x300, + 0x3ce, + 0x1f00, + 0x345, + 0x1f01, + 0x345, + 0x1f02, + 0x345, + 0x1f03, + 0x345, + 0x1f04, + 0x345, + 0x1f05, + 0x345, + 0x1f06, + 0x345, + 0x1f07, + 0x345, + 0x1f08, + 0x345, + 0x1f09, + 0x345, + 0x1f0a, + 0x345, + 0x1f0b, + 0x345, + 0x1f0c, + 0x345, + 0x1f0d, + 0x345, + 0x1f0e, + 0x345, + 0x1f0f, + 0x345, + 0x1f20, + 0x345, + 0x1f21, + 0x345, + 0x1f22, + 0x345, + 0x1f23, + 0x345, + 0x1f24, + 0x345, + 0x1f25, + 0x345, + 0x1f26, + 0x345, + 0x1f27, + 0x345, + 0x1f28, + 0x345, + 0x1f29, + 0x345, + 0x1f2a, + 0x345, + 0x1f2b, + 0x345, + 0x1f2c, + 0x345, + 0x1f2d, + 0x345, + 0x1f2e, + 0x345, + 0x1f2f, + 0x345, + 0x1f60, + 0x345, + 0x1f61, + 0x345, + 0x1f62, + 0x345, + 0x1f63, + 0x345, + 0x1f64, + 0x345, + 0x1f65, + 0x345, + 0x1f66, + 0x345, + 0x1f67, + 0x345, + 0x1f68, + 0x345, + 0x1f69, + 0x345, + 0x1f6a, + 0x345, + 0x1f6b, + 0x345, + 0x1f6c, + 0x345, + 0x1f6d, + 0x345, + 0x1f6e, + 0x345, + 0x1f6f, + 0x345, + 0x3b1, + 0x306, + 0x3b1, + 0x304, + 0x1f70, + 0x345, + 0x3b1, + 0x345, + 0x3ac, + 0x345, + 0x3b1, + 0x342, + 0x1fb6, + 0x345, + 0x391, + 0x306, + 0x391, + 0x304, + 0x391, + 0x300, + 0x386, + 0x391, + 0x345, + 0x20, + 0x313, + 0x20, + 0x342, + 0xa8, + 0x342, + 0x1f74, + 0x345, + 0x3b7, + 0x345, + 0x3ae, + 0x345, + 0x3b7, + 0x342, + 0x1fc6, + 0x345, + 0x395, + 0x300, + 0x388, + 0x397, + 0x300, + 0x389, + 0x397, + 0x345, + 0x1fbf, + 0x300, + 0x1fbf, + 0x301, + 0x1fbf, + 0x342, + 0x3b9, + 0x306, + 0x3b9, + 0x304, + 0x3ca, + 0x300, + 0x390, + 0x3b9, + 0x342, + 0x3ca, + 0x342, + 0x399, + 0x306, + 0x399, + 0x304, + 0x399, + 0x300, + 0x38a, + 0x1ffe, + 0x300, + 0x1ffe, + 0x301, + 0x1ffe, + 0x342, + 0x3c5, + 0x306, + 0x3c5, + 0x304, + 0x3cb, + 0x300, + 0x3b0, + 0x3c1, + 0x313, + 0x3c1, + 0x314, + 0x3c5, + 0x342, + 0x3cb, + 0x342, + 0x3a5, + 0x306, + 0x3a5, + 0x304, + 0x3a5, + 0x300, + 0x38e, + 0x3a1, + 0x314, + 0xa8, + 0x300, + 0x385, + 0x60, + 0x1f7c, + 0x345, + 0x3c9, + 0x345, + 0x3ce, + 0x345, + 0x3c9, + 0x342, + 0x1ff6, + 0x345, + 0x39f, + 0x300, + 0x38c, + 0x3a9, + 0x300, + 0x38f, + 0x3a9, + 0x345, + 0xb4, + 0x20, + 0x314, + 0x2002, + 0x2003, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x2010, + 0x20, + 0x333, + 0x2e, + 0x2e, + 0x2e, + 0x20, + 0x2032, + 0x2032, + 0x2032, + 0x2032, + 0x2032, + 0x2035, + 0x2035, + 0x2035, + 0x2035, + 0x2035, + 0x21, + 0x21, + 0x20, + 0x305, + 0x3f, + 0x3f, + 0x3f, + 0x21, + 0x21, + 0x3f, + 0x20, + 0x30, + 0x35, + 0x36, + 0x37, + 0x38, + 0x39, + 0x2b, + 0x2212, + 0x3d, + 0x28, + 0x29, + 0x52, + 0x73, + 0x61, + 0x2f, + 0x63, + 0x61, + 0x2f, + 0x73, + 0xb0, + 0x43, + 0x63, + 0x2f, + 0x6f, + 0x63, + 0x2f, + 0x75, + 0x190, + 0xb0, + 0x46, + 0x127, + 0x4e, + 0x6f, + 0x51, + 0x53, + 0x4d, + 0x54, + 0x45, + 0x4c, + 0x54, + 0x4d, + 0x5d0, + 0x5d1, + 0x5d2, + 0x5d3, + 0x46, + 0x41, + 0x58, + 0x393, + 0x3a0, + 0x2211, + 0x31, + 0x2044, + 0x33, + 0x32, + 0x2044, + 0x33, + 0x31, + 0x2044, + 0x35, + 0x32, + 0x2044, + 0x35, + 0x33, + 0x2044, + 0x35, + 0x34, + 0x2044, + 0x35, + 0x31, + 0x2044, + 0x36, + 0x35, + 0x2044, + 0x36, + 0x31, + 0x2044, + 0x38, + 0x33, + 0x2044, + 0x38, + 0x35, + 0x2044, + 0x38, + 0x37, + 0x2044, + 0x38, + 0x49, + 0x49, + 0x49, + 0x49, + 0x49, + 0x49, + 0x56, + 0x56, + 0x49, + 0x56, + 0x49, + 0x49, + 0x56, + 0x49, + 0x49, + 0x49, + 0x49, + 0x58, + 0x58, + 0x49, + 0x58, + 0x49, + 0x49, + 0x69, + 0x69, + 0x69, + 0x69, + 0x69, + 0x69, + 0x76, + 0x76, + 0x69, + 0x76, + 0x69, + 0x69, + 0x76, + 0x69, + 0x69, + 0x69, + 0x69, + 0x78, + 0x78, + 0x69, + 0x78, + 0x69, + 0x69, + 0x2190, + 0x338, + 0x2192, + 0x338, + 0x2194, + 0x338, + 0x21d0, + 0x338, + 0x21d4, + 0x338, + 0x21d2, + 0x338, + 0x2203, + 0x338, + 0x2208, + 0x338, + 0x220b, + 0x338, + 0x2223, + 0x338, + 0x2225, + 0x338, + 0x222b, + 0x222b, + 0x222b, + 0x222b, + 0x222b, + 0x222e, + 0x222e, + 0x222e, + 0x222e, + 0x222e, + 0x223c, + 0x338, + 0x2243, + 0x338, + 0x2245, + 0x338, + 0x2248, + 0x338, + 0x3d, + 0x338, + 0x2261, + 0x338, + 0x224d, + 0x338, + 0x3c, + 0x338, + 0x3e, + 0x338, + 0x2264, + 0x338, + 0x2265, + 0x338, + 0x2272, + 0x338, + 0x2273, + 0x338, + 0x2276, + 0x338, + 0x2277, + 0x338, + 0x227a, + 0x338, + 0x227b, + 0x338, + 0x2282, + 0x338, + 0x2283, + 0x338, + 0x2286, + 0x338, + 0x2287, + 0x338, + 0x22a2, + 0x338, + 0x22a8, + 0x338, + 0x22a9, + 0x338, + 0x22ab, + 0x338, + 0x227c, + 0x338, + 0x227d, + 0x338, + 0x2291, + 0x338, + 0x2292, + 0x338, + 0x22b2, + 0x338, + 0x22b3, + 0x338, + 0x22b4, + 0x338, + 0x22b5, + 0x338, + 0x3008, + 0x3009, + 0x31, + 0x30, + 0x31, + 0x31, + 0x31, + 0x32, + 0x31, + 0x33, + 0x31, + 0x34, + 0x31, + 0x35, + 0x31, + 0x36, + 0x31, + 0x37, + 0x31, + 0x38, + 0x31, + 0x39, + 0x32, + 0x30, + 0x28, + 0x31, + 0x29, + 0x28, + 0x32, + 0x29, + 0x28, + 0x33, + 0x29, + 0x28, + 0x34, + 0x29, + 0x28, + 0x35, + 0x29, + 0x28, + 0x36, + 0x29, + 0x28, + 0x37, + 0x29, + 0x28, + 0x38, + 0x29, + 0x28, + 0x39, + 0x29, + 0x28, + 0x31, + 0x30, + 0x29, + 0x28, + 0x31, + 0x31, + 0x29, + 0x28, + 0x31, + 0x32, + 0x29, + 0x28, + 0x31, + 0x33, + 0x29, + 0x28, + 0x31, + 0x34, + 0x29, + 0x28, + 0x31, + 0x35, + 0x29, + 0x28, + 0x31, + 0x36, + 0x29, + 0x28, + 0x31, + 0x37, + 0x29, + 0x28, + 0x31, + 0x38, + 0x29, + 0x28, + 0x31, + 0x39, + 0x29, + 0x28, + 0x32, + 0x30, + 0x29, + 0x31, + 0x2e, + 0x32, + 0x2e, + 0x33, + 0x2e, + 0x34, + 0x2e, + 0x35, + 0x2e, + 0x36, + 0x2e, + 0x37, + 0x2e, + 0x38, + 0x2e, + 0x39, + 0x2e, + 0x31, + 0x30, + 0x2e, + 0x31, + 0x31, + 0x2e, + 0x31, + 0x32, + 0x2e, + 0x31, + 0x33, + 0x2e, + 0x31, + 0x34, + 0x2e, + 0x31, + 0x35, + 0x2e, + 0x31, + 0x36, + 0x2e, + 0x31, + 0x37, + 0x2e, + 0x31, + 0x38, + 0x2e, + 0x31, + 0x39, + 0x2e, + 0x32, + 0x30, + 0x2e, + 0x28, + 0x61, + 0x29, + 0x28, + 0x62, + 0x29, + 0x28, + 0x63, + 0x29, + 0x28, + 0x64, + 0x29, + 0x28, + 0x65, + 0x29, + 0x28, + 0x66, + 0x29, + 0x28, + 0x67, + 0x29, + 0x28, + 0x68, + 0x29, + 0x28, + 0x69, + 0x29, + 0x28, + 0x6a, + 0x29, + 0x28, + 0x6b, + 0x29, + 0x28, + 0x6c, + 0x29, + 0x28, + 0x6d, + 0x29, + 0x28, + 0x6e, + 0x29, + 0x28, + 0x6f, + 0x29, + 0x28, + 0x70, + 0x29, + 0x28, + 0x71, + 0x29, + 0x28, + 0x72, + 0x29, + 0x28, + 0x73, + 0x29, + 0x28, + 0x74, + 0x29, + 0x28, + 0x75, + 0x29, + 0x28, + 0x76, + 0x29, + 0x28, + 0x77, + 0x29, + 0x28, + 0x78, + 0x29, + 0x28, + 0x79, + 0x29, + 0x28, + 0x7a, + 0x29, + 0x3a, + 0x3a, + 0x3d, + 0x3d, + 0x3d, + 0x2add, + 0x338, + 0x6bcd, + 0x9f9f, + 0x4e00, + 0x4e28, + 0x4e36, + 0x4e3f, + 0x4e59, + 0x4e85, + 0x4e8c, + 0x4ea0, + 0x4eba, + 0x513f, + 0x5165, + 0x516b, + 0x5182, + 0x5196, + 0x51ab, + 0x51e0, + 0x51f5, + 0x5200, + 0x529b, + 0x52f9, + 0x5315, + 0x531a, + 0x5338, + 0x5341, + 0x535c, + 0x5369, + 0x5382, + 0x53b6, + 0x53c8, + 0x53e3, + 0x56d7, + 0x571f, + 0x58eb, + 0x5902, + 0x590a, + 0x5915, + 0x5927, + 0x5973, + 0x5b50, + 0x5b80, + 0x5bf8, + 0x5c0f, + 0x5c22, + 0x5c38, + 0x5c6e, + 0x5c71, + 0x5ddb, + 0x5de5, + 0x5df1, + 0x5dfe, + 0x5e72, + 0x5e7a, + 0x5e7f, + 0x5ef4, + 0x5efe, + 0x5f0b, + 0x5f13, + 0x5f50, + 0x5f61, + 0x5f73, + 0x5fc3, + 0x6208, + 0x6236, + 0x624b, + 0x652f, + 0x6534, + 0x6587, + 0x6597, + 0x65a4, + 0x65b9, + 0x65e0, + 0x65e5, + 0x66f0, + 0x6708, + 0x6728, + 0x6b20, + 0x6b62, + 0x6b79, + 0x6bb3, + 0x6bcb, + 0x6bd4, + 0x6bdb, + 0x6c0f, + 0x6c14, + 0x6c34, + 0x706b, + 0x722a, + 0x7236, + 0x723b, + 0x723f, + 0x7247, + 0x7259, + 0x725b, + 0x72ac, + 0x7384, + 0x7389, + 0x74dc, + 0x74e6, + 0x7518, + 0x751f, + 0x7528, + 0x7530, + 0x758b, + 0x7592, + 0x7676, + 0x767d, + 0x76ae, + 0x76bf, + 0x76ee, + 0x77db, + 0x77e2, + 0x77f3, + 0x793a, + 0x79b8, + 0x79be, + 0x7a74, + 0x7acb, + 0x7af9, + 0x7c73, + 0x7cf8, + 0x7f36, + 0x7f51, + 0x7f8a, + 0x7fbd, + 0x8001, + 0x800c, + 0x8012, + 0x8033, + 0x807f, + 0x8089, + 0x81e3, + 0x81ea, + 0x81f3, + 0x81fc, + 0x820c, + 0x821b, + 0x821f, + 0x826e, + 0x8272, + 0x8278, + 0x864d, + 0x866b, + 0x8840, + 0x884c, + 0x8863, + 0x897e, + 0x898b, + 0x89d2, + 0x8a00, + 0x8c37, + 0x8c46, + 0x8c55, + 0x8c78, + 0x8c9d, + 0x8d64, + 0x8d70, + 0x8db3, + 0x8eab, + 0x8eca, + 0x8f9b, + 0x8fb0, + 0x8fb5, + 0x9091, + 0x9149, + 0x91c6, + 0x91cc, + 0x91d1, + 0x9577, + 0x9580, + 0x961c, + 0x96b6, + 0x96b9, + 0x96e8, + 0x9751, + 0x975e, + 0x9762, + 0x9769, + 0x97cb, + 0x97ed, + 0x97f3, + 0x9801, + 0x98a8, + 0x98db, + 0x98df, + 0x9996, + 0x9999, + 0x99ac, + 0x9aa8, + 0x9ad8, + 0x9adf, + 0x9b25, + 0x9b2f, + 0x9b32, + 0x9b3c, + 0x9b5a, + 0x9ce5, + 0x9e75, + 0x9e7f, + 0x9ea5, + 0x9ebb, + 0x9ec3, + 0x9ecd, + 0x9ed1, + 0x9ef9, + 0x9efd, + 0x9f0e, + 0x9f13, + 0x9f20, + 0x9f3b, + 0x9f4a, + 0x9f52, + 0x9f8d, + 0x9f9c, + 0x9fa0, + 0x20, + 0x3012, + 0x5344, + 0x5345, + 0x304b, + 0x3099, + 0x304d, + 0x3099, + 0x304f, + 0x3099, + 0x3051, + 0x3099, + 0x3053, + 0x3099, + 0x3055, + 0x3099, + 0x3057, + 0x3099, + 0x3059, + 0x3099, + 0x305b, + 0x3099, + 0x305d, + 0x3099, + 0x305f, + 0x3099, + 0x3061, + 0x3099, + 0x3064, + 0x3099, + 0x3066, + 0x3099, + 0x3068, + 0x3099, + 0x306f, + 0x3099, + 0x306f, + 0x309a, + 0x3072, + 0x3099, + 0x3072, + 0x309a, + 0x3075, + 0x3099, + 0x3075, + 0x309a, + 0x3078, + 0x3099, + 0x3078, + 0x309a, + 0x307b, + 0x3099, + 0x307b, + 0x309a, + 0x3046, + 0x3099, + 0x20, + 0x3099, + 0x20, + 0x309a, + 0x309d, + 0x3099, + 0x3088, + 0x308a, + 0x30ab, + 0x3099, + 0x30ad, + 0x3099, + 0x30af, + 0x3099, + 0x30b1, + 0x3099, + 0x30b3, + 0x3099, + 0x30b5, + 0x3099, + 0x30b7, + 0x3099, + 0x30b9, + 0x3099, + 0x30bb, + 0x3099, + 0x30bd, + 0x3099, + 0x30bf, + 0x3099, + 0x30c1, + 0x3099, + 0x30c4, + 0x3099, + 0x30c6, + 0x3099, + 0x30c8, + 0x3099, + 0x30cf, + 0x3099, + 0x30cf, + 0x309a, + 0x30d2, + 0x3099, + 0x30d2, + 0x309a, + 0x30d5, + 0x3099, + 0x30d5, + 0x309a, + 0x30d8, + 0x3099, + 0x30d8, + 0x309a, + 0x30db, + 0x3099, + 0x30db, + 0x309a, + 0x30a6, + 0x3099, + 0x30ef, + 0x3099, + 0x30f0, + 0x3099, + 0x30f1, + 0x3099, + 0x30f2, + 0x3099, + 0x30fd, + 0x3099, + 0x30b3, + 0x30c8, + 0x1100, + 0x1101, + 0x11aa, + 0x1102, + 0x11ac, + 0x11ad, + 0x1103, + 0x1104, + 0x1105, + 0x11b0, + 0x11b1, + 0x11b2, + 0x11b3, + 0x11b4, + 0x11b5, + 0x111a, + 0x1106, + 0x1107, + 0x1108, + 0x1121, + 0x1109, + 0x110a, + 0x110b, + 0x110c, + 0x110d, + 0x110e, + 0x110f, + 0x1110, + 0x1111, + 0x1112, + 0x1161, + 0x1162, + 0x1163, + 0x1164, + 0x1165, + 0x1166, + 0x1167, + 0x1168, + 0x1169, + 0x116a, + 0x116b, + 0x116c, + 0x116d, + 0x116e, + 0x116f, + 0x1170, + 0x1171, + 0x1172, + 0x1173, + 0x1174, + 0x1175, + 0x1160, + 0x1114, + 0x1115, + 0x11c7, + 0x11c8, + 0x11cc, + 0x11ce, + 0x11d3, + 0x11d7, + 0x11d9, + 0x111c, + 0x11dd, + 0x11df, + 0x111d, + 0x111e, + 0x1120, + 0x1122, + 0x1123, + 0x1127, + 0x1129, + 0x112b, + 0x112c, + 0x112d, + 0x112e, + 0x112f, + 0x1132, + 0x1136, + 0x1140, + 0x1147, + 0x114c, + 0x11f1, + 0x11f2, + 0x1157, + 0x1158, + 0x1159, + 0x1184, + 0x1185, + 0x1188, + 0x1191, + 0x1192, + 0x1194, + 0x119e, + 0x11a1, + 0x4e09, + 0x56db, + 0x4e0a, + 0x4e2d, + 0x4e0b, + 0x7532, + 0x4e19, + 0x4e01, + 0x5929, + 0x5730, + 0x28, + 0x1100, + 0x29, + 0x28, + 0x1102, + 0x29, + 0x28, + 0x1103, + 0x29, + 0x28, + 0x1105, + 0x29, + 0x28, + 0x1106, + 0x29, + 0x28, + 0x1107, + 0x29, + 0x28, + 0x1109, + 0x29, + 0x28, + 0x110b, + 0x29, + 0x28, + 0x110c, + 0x29, + 0x28, + 0x110e, + 0x29, + 0x28, + 0x110f, + 0x29, + 0x28, + 0x1110, + 0x29, + 0x28, + 0x1111, + 0x29, + 0x28, + 0x1112, + 0x29, + 0x28, + 0x1100, + 0x1161, + 0x29, + 0x28, + 0x1102, + 0x1161, + 0x29, + 0x28, + 0x1103, + 0x1161, + 0x29, + 0x28, + 0x1105, + 0x1161, + 0x29, + 0x28, + 0x1106, + 0x1161, + 0x29, + 0x28, + 0x1107, + 0x1161, + 0x29, + 0x28, + 0x1109, + 0x1161, + 0x29, + 0x28, + 0x110b, + 0x1161, + 0x29, + 0x28, + 0x110c, + 0x1161, + 0x29, + 0x28, + 0x110e, + 0x1161, + 0x29, + 0x28, + 0x110f, + 0x1161, + 0x29, + 0x28, + 0x1110, + 0x1161, + 0x29, + 0x28, + 0x1111, + 0x1161, + 0x29, + 0x28, + 0x1112, + 0x1161, + 0x29, + 0x28, + 0x110c, + 0x116e, + 0x29, + 0x28, + 0x110b, + 0x1169, + 0x110c, + 0x1165, + 0x11ab, + 0x29, + 0x28, + 0x110b, + 0x1169, + 0x1112, + 0x116e, + 0x29, + 0x28, + 0x4e00, + 0x29, + 0x28, + 0x4e8c, + 0x29, + 0x28, + 0x4e09, + 0x29, + 0x28, + 0x56db, + 0x29, + 0x28, + 0x4e94, + 0x29, + 0x28, + 0x516d, + 0x29, + 0x28, + 0x4e03, + 0x29, + 0x28, + 0x516b, + 0x29, + 0x28, + 0x4e5d, + 0x29, + 0x28, + 0x5341, + 0x29, + 0x28, + 0x6708, + 0x29, + 0x28, + 0x706b, + 0x29, + 0x28, + 0x6c34, + 0x29, + 0x28, + 0x6728, + 0x29, + 0x28, + 0x91d1, + 0x29, + 0x28, + 0x571f, + 0x29, + 0x28, + 0x65e5, + 0x29, + 0x28, + 0x682a, + 0x29, + 0x28, + 0x6709, + 0x29, + 0x28, + 0x793e, + 0x29, + 0x28, + 0x540d, + 0x29, + 0x28, + 0x7279, + 0x29, + 0x28, + 0x8ca1, + 0x29, + 0x28, + 0x795d, + 0x29, + 0x28, + 0x52b4, + 0x29, + 0x28, + 0x4ee3, + 0x29, + 0x28, + 0x547c, + 0x29, + 0x28, + 0x5b66, + 0x29, + 0x28, + 0x76e3, + 0x29, + 0x28, + 0x4f01, + 0x29, + 0x28, + 0x8cc7, + 0x29, + 0x28, + 0x5354, + 0x29, + 0x28, + 0x796d, + 0x29, + 0x28, + 0x4f11, + 0x29, + 0x28, + 0x81ea, + 0x29, + 0x28, + 0x81f3, + 0x29, + 0x50, + 0x54, + 0x45, + 0x32, + 0x32, + 0x32, + 0x34, + 0x32, + 0x35, + 0x32, + 0x36, + 0x32, + 0x37, + 0x32, + 0x38, + 0x32, + 0x39, + 0x33, + 0x30, + 0x33, + 0x33, + 0x33, + 0x34, + 0x33, + 0x35, + 0x110e, + 0x1161, + 0x11b7, + 0x1100, + 0x1169, + 0x110c, + 0x116e, + 0x110b, + 0x1174, + 0x79d8, + 0x7537, + 0x9069, + 0x512a, + 0x5370, + 0x6ce8, + 0x9805, + 0x5199, + 0x6b63, + 0x5de6, + 0x53f3, + 0x533b, + 0x5b97, + 0x591c, + 0x33, + 0x36, + 0x33, + 0x37, + 0x33, + 0x38, + 0x33, + 0x39, + 0x34, + 0x30, + 0x34, + 0x34, + 0x34, + 0x35, + 0x34, + 0x36, + 0x34, + 0x37, + 0x34, + 0x38, + 0x34, + 0x39, + 0x35, + 0x30, + 0x31, + 0x6708, + 0x32, + 0x6708, + 0x33, + 0x6708, + 0x34, + 0x6708, + 0x35, + 0x6708, + 0x36, + 0x6708, + 0x37, + 0x6708, + 0x38, + 0x6708, + 0x39, + 0x6708, + 0x31, + 0x30, + 0x6708, + 0x31, + 0x31, + 0x6708, + 0x31, + 0x32, + 0x6708, + 0x48, + 0x67, + 0x65, + 0x72, + 0x67, + 0x65, + 0x56, + 0x4c, + 0x54, + 0x44, + 0x30a2, + 0x30a4, + 0x30a8, + 0x30aa, + 0x30ca, + 0x30cb, + 0x30cc, + 0x30cd, + 0x30ce, + 0x30de, + 0x30df, + 0x30e0, + 0x30e1, + 0x30e2, + 0x30e4, + 0x30e6, + 0x30e8, + 0x30e9, + 0x30ea, + 0x30eb, + 0x30ec, + 0x30ed, + 0x30a2, + 0x30d1, + 0x30fc, + 0x30c8, + 0x30a2, + 0x30eb, + 0x30d5, + 0x30a1, + 0x30a2, + 0x30f3, + 0x30da, + 0x30a2, + 0x30a2, + 0x30fc, + 0x30eb, + 0x30a4, + 0x30cb, + 0x30f3, + 0x30b0, + 0x30a4, + 0x30f3, + 0x30c1, + 0x30a6, + 0x30a9, + 0x30f3, + 0x30a8, + 0x30b9, + 0x30af, + 0x30fc, + 0x30c9, + 0x30a8, + 0x30fc, + 0x30ab, + 0x30fc, + 0x30aa, + 0x30f3, + 0x30b9, + 0x30aa, + 0x30fc, + 0x30e0, + 0x30ab, + 0x30a4, + 0x30ea, + 0x30ab, + 0x30e9, + 0x30c3, + 0x30c8, + 0x30ab, + 0x30ed, + 0x30ea, + 0x30fc, + 0x30ac, + 0x30ed, + 0x30f3, + 0x30ac, + 0x30f3, + 0x30de, + 0x30ae, + 0x30ac, + 0x30ae, + 0x30cb, + 0x30fc, + 0x30ad, + 0x30e5, + 0x30ea, + 0x30fc, + 0x30ae, + 0x30eb, + 0x30c0, + 0x30fc, + 0x30ad, + 0x30ed, + 0x30ad, + 0x30ed, + 0x30b0, + 0x30e9, + 0x30e0, + 0x30ad, + 0x30ed, + 0x30e1, + 0x30fc, + 0x30c8, + 0x30eb, + 0x30ad, + 0x30ed, + 0x30ef, + 0x30c3, + 0x30c8, + 0x30b0, + 0x30e9, + 0x30e0, + 0x30c8, + 0x30f3, + 0x30af, + 0x30eb, + 0x30bc, + 0x30a4, + 0x30ed, + 0x30af, + 0x30ed, + 0x30fc, + 0x30cd, + 0x30b1, + 0x30fc, + 0x30b9, + 0x30b3, + 0x30eb, + 0x30ca, + 0x30b3, + 0x30fc, + 0x30dd, + 0x30b5, + 0x30a4, + 0x30af, + 0x30eb, + 0x30b5, + 0x30f3, + 0x30c1, + 0x30fc, + 0x30e0, + 0x30b7, + 0x30ea, + 0x30f3, + 0x30b0, + 0x30bb, + 0x30f3, + 0x30c1, + 0x30bb, + 0x30f3, + 0x30c8, + 0x30c0, + 0x30fc, + 0x30b9, + 0x30c7, + 0x30b7, + 0x30c9, + 0x30eb, + 0x30ca, + 0x30ce, + 0x30ce, + 0x30c3, + 0x30c8, + 0x30cf, + 0x30a4, + 0x30c4, + 0x30d1, + 0x30fc, + 0x30bb, + 0x30f3, + 0x30c8, + 0x30d1, + 0x30fc, + 0x30c4, + 0x30d0, + 0x30fc, + 0x30ec, + 0x30eb, + 0x30d4, + 0x30a2, + 0x30b9, + 0x30c8, + 0x30eb, + 0x30d4, + 0x30af, + 0x30eb, + 0x30d4, + 0x30b3, + 0x30d3, + 0x30eb, + 0x30d5, + 0x30a1, + 0x30e9, + 0x30c3, + 0x30c9, + 0x30d5, + 0x30a3, + 0x30fc, + 0x30c8, + 0x30d6, + 0x30c3, + 0x30b7, + 0x30a7, + 0x30eb, + 0x30d5, + 0x30e9, + 0x30f3, + 0x30d8, + 0x30af, + 0x30bf, + 0x30fc, + 0x30eb, + 0x30da, + 0x30bd, + 0x30da, + 0x30cb, + 0x30d2, + 0x30d8, + 0x30eb, + 0x30c4, + 0x30da, + 0x30f3, + 0x30b9, + 0x30da, + 0x30fc, + 0x30b8, + 0x30d9, + 0x30fc, + 0x30bf, + 0x30dd, + 0x30a4, + 0x30f3, + 0x30c8, + 0x30dc, + 0x30eb, + 0x30c8, + 0x30db, + 0x30f3, + 0x30dd, + 0x30f3, + 0x30c9, + 0x30db, + 0x30fc, + 0x30eb, + 0x30db, + 0x30fc, + 0x30f3, + 0x30de, + 0x30a4, + 0x30af, + 0x30ed, + 0x30de, + 0x30a4, + 0x30eb, + 0x30de, + 0x30c3, + 0x30cf, + 0x30de, + 0x30eb, + 0x30af, + 0x30de, + 0x30f3, + 0x30b7, + 0x30e7, + 0x30f3, + 0x30df, + 0x30af, + 0x30ed, + 0x30f3, + 0x30df, + 0x30ea, + 0x30df, + 0x30ea, + 0x30d0, + 0x30fc, + 0x30eb, + 0x30e1, + 0x30ac, + 0x30e1, + 0x30ac, + 0x30c8, + 0x30f3, + 0x30e4, + 0x30fc, + 0x30c9, + 0x30e4, + 0x30fc, + 0x30eb, + 0x30e6, + 0x30a2, + 0x30f3, + 0x30ea, + 0x30c3, + 0x30c8, + 0x30eb, + 0x30ea, + 0x30e9, + 0x30eb, + 0x30d4, + 0x30fc, + 0x30eb, + 0x30fc, + 0x30d6, + 0x30eb, + 0x30ec, + 0x30e0, + 0x30ec, + 0x30f3, + 0x30c8, + 0x30b2, + 0x30f3, + 0x30, + 0x70b9, + 0x31, + 0x70b9, + 0x32, + 0x70b9, + 0x33, + 0x70b9, + 0x34, + 0x70b9, + 0x35, + 0x70b9, + 0x36, + 0x70b9, + 0x37, + 0x70b9, + 0x38, + 0x70b9, + 0x39, + 0x70b9, + 0x31, + 0x30, + 0x70b9, + 0x31, + 0x31, + 0x70b9, + 0x31, + 0x32, + 0x70b9, + 0x31, + 0x33, + 0x70b9, + 0x31, + 0x34, + 0x70b9, + 0x31, + 0x35, + 0x70b9, + 0x31, + 0x36, + 0x70b9, + 0x31, + 0x37, + 0x70b9, + 0x31, + 0x38, + 0x70b9, + 0x31, + 0x39, + 0x70b9, + 0x32, + 0x30, + 0x70b9, + 0x32, + 0x31, + 0x70b9, + 0x32, + 0x32, + 0x70b9, + 0x32, + 0x33, + 0x70b9, + 0x32, + 0x34, + 0x70b9, + 0x68, + 0x50, + 0x61, + 0x64, + 0x61, + 0x41, + 0x55, + 0x62, + 0x61, + 0x72, + 0x6f, + 0x56, + 0x70, + 0x63, + 0x64, + 0x6d, + 0x64, + 0x6d, + 0xb2, + 0x64, + 0x6d, + 0xb3, + 0x49, + 0x55, + 0x5e73, + 0x6210, + 0x662d, + 0x548c, + 0x5927, + 0x6b63, + 0x660e, + 0x6cbb, + 0x682a, + 0x5f0f, + 0x4f1a, + 0x793e, + 0x70, + 0x41, + 0x6e, + 0x41, + 0x3bc, + 0x41, + 0x6d, + 0x41, + 0x6b, + 0x41, + 0x4b, + 0x42, + 0x4d, + 0x42, + 0x47, + 0x42, + 0x63, + 0x61, + 0x6c, + 0x6b, + 0x63, + 0x61, + 0x6c, + 0x70, + 0x46, + 0x6e, + 0x46, + 0x3bc, + 0x46, + 0x3bc, + 0x67, + 0x6d, + 0x67, + 0x6b, + 0x67, + 0x48, + 0x7a, + 0x6b, + 0x48, + 0x7a, + 0x4d, + 0x48, + 0x7a, + 0x47, + 0x48, + 0x7a, + 0x54, + 0x48, + 0x7a, + 0x3bc, + 0x2113, + 0x6d, + 0x2113, + 0x64, + 0x2113, + 0x6b, + 0x2113, + 0x66, + 0x6d, + 0x6e, + 0x6d, + 0x3bc, + 0x6d, + 0x6d, + 0x6d, + 0x63, + 0x6d, + 0x6b, + 0x6d, + 0x6d, + 0x6d, + 0xb2, + 0x63, + 0x6d, + 0xb2, + 0x6b, + 0x6d, + 0xb2, + 0x6d, + 0x6d, + 0xb3, + 0x63, + 0x6d, + 0xb3, + 0x6b, + 0x6d, + 0xb3, + 0x6d, + 0x2215, + 0x73, + 0x6d, + 0x2215, + 0x73, + 0xb2, + 0x6b, + 0x50, + 0x61, + 0x4d, + 0x50, + 0x61, + 0x47, + 0x50, + 0x61, + 0x72, + 0x61, + 0x64, + 0x72, + 0x61, + 0x64, + 0x2215, + 0x73, + 0x72, + 0x61, + 0x64, + 0x2215, + 0x73, + 0xb2, + 0x70, + 0x73, + 0x6e, + 0x73, + 0x3bc, + 0x73, + 0x6d, + 0x73, + 0x70, + 0x56, + 0x6e, + 0x56, + 0x3bc, + 0x56, + 0x6d, + 0x56, + 0x6b, + 0x56, + 0x4d, + 0x56, + 0x70, + 0x57, + 0x6e, + 0x57, + 0x3bc, + 0x57, + 0x6d, + 0x57, + 0x6b, + 0x57, + 0x4d, + 0x57, + 0x6b, + 0x3a9, + 0x4d, + 0x3a9, + 0x61, + 0x2e, + 0x6d, + 0x2e, + 0x42, + 0x71, + 0x63, + 0x63, + 0x43, + 0x2215, + 0x6b, + 0x67, + 0x43, + 0x6f, + 0x2e, + 0x64, + 0x42, + 0x47, + 0x79, + 0x68, + 0x61, + 0x48, + 0x50, + 0x69, + 0x6e, + 0x4b, + 0x4b, + 0x4b, + 0x4d, + 0x6b, + 0x74, + 0x6c, + 0x6d, + 0x6c, + 0x6e, + 0x6c, + 0x6f, + 0x67, + 0x6c, + 0x78, + 0x6d, + 0x62, + 0x6d, + 0x69, + 0x6c, + 0x6d, + 0x6f, + 0x6c, + 0x50, + 0x48, + 0x70, + 0x2e, + 0x6d, + 0x2e, + 0x50, + 0x50, + 0x4d, + 0x50, + 0x52, + 0x53, + 0x76, + 0x57, + 0x62, + 0x56, + 0x2215, + 0x6d, + 0x41, + 0x2215, + 0x6d, + 0x31, + 0x65e5, + 0x32, + 0x65e5, + 0x33, + 0x65e5, + 0x34, + 0x65e5, + 0x35, + 0x65e5, + 0x36, + 0x65e5, + 0x37, + 0x65e5, + 0x38, + 0x65e5, + 0x39, + 0x65e5, + 0x31, + 0x30, + 0x65e5, + 0x31, + 0x31, + 0x65e5, + 0x31, + 0x32, + 0x65e5, + 0x31, + 0x33, + 0x65e5, + 0x31, + 0x34, + 0x65e5, + 0x31, + 0x35, + 0x65e5, + 0x31, + 0x36, + 0x65e5, + 0x31, + 0x37, + 0x65e5, + 0x31, + 0x38, + 0x65e5, + 0x31, + 0x39, + 0x65e5, + 0x32, + 0x30, + 0x65e5, + 0x32, + 0x31, + 0x65e5, + 0x32, + 0x32, + 0x65e5, + 0x32, + 0x33, + 0x65e5, + 0x32, + 0x34, + 0x65e5, + 0x32, + 0x35, + 0x65e5, + 0x32, + 0x36, + 0x65e5, + 0x32, + 0x37, + 0x65e5, + 0x32, + 0x38, + 0x65e5, + 0x32, + 0x39, + 0x65e5, + 0x33, + 0x30, + 0x65e5, + 0x33, + 0x31, + 0x65e5, + 0x67, + 0x61, + 0x6c, + 0x8c48, + 0x66f4, + 0x8cc8, + 0x6ed1, + 0x4e32, + 0x53e5, + 0x5951, + 0x5587, + 0x5948, + 0x61f6, + 0x7669, + 0x7f85, + 0x863f, + 0x87ba, + 0x88f8, + 0x908f, + 0x6a02, + 0x6d1b, + 0x70d9, + 0x73de, + 0x843d, + 0x916a, + 0x99f1, + 0x4e82, + 0x5375, + 0x6b04, + 0x721b, + 0x862d, + 0x9e1e, + 0x5d50, + 0x6feb, + 0x85cd, + 0x8964, + 0x62c9, + 0x81d8, + 0x881f, + 0x5eca, + 0x6717, + 0x6d6a, + 0x72fc, + 0x90ce, + 0x4f86, + 0x51b7, + 0x52de, + 0x64c4, + 0x6ad3, + 0x7210, + 0x76e7, + 0x8606, + 0x865c, + 0x8def, + 0x9732, + 0x9b6f, + 0x9dfa, + 0x788c, + 0x797f, + 0x7da0, + 0x83c9, + 0x9304, + 0x8ad6, + 0x58df, + 0x5f04, + 0x7c60, + 0x807e, + 0x7262, + 0x78ca, + 0x8cc2, + 0x96f7, + 0x58d8, + 0x5c62, + 0x6a13, + 0x6dda, + 0x6f0f, + 0x7d2f, + 0x7e37, + 0x964b, + 0x52d2, + 0x808b, + 0x51dc, + 0x51cc, + 0x7a1c, + 0x7dbe, + 0x83f1, + 0x9675, + 0x8b80, + 0x62cf, + 0x8afe, + 0x4e39, + 0x5be7, + 0x6012, + 0x7387, + 0x7570, + 0x5317, + 0x78fb, + 0x4fbf, + 0x5fa9, + 0x4e0d, + 0x6ccc, + 0x6578, + 0x7d22, + 0x53c3, + 0x585e, + 0x7701, + 0x8449, + 0x8aaa, + 0x6bba, + 0x6c88, + 0x62fe, + 0x82e5, + 0x63a0, + 0x7565, + 0x4eae, + 0x5169, + 0x51c9, + 0x6881, + 0x7ce7, + 0x826f, + 0x8ad2, + 0x91cf, + 0x52f5, + 0x5442, + 0x5eec, + 0x65c5, + 0x6ffe, + 0x792a, + 0x95ad, + 0x9a6a, + 0x9e97, + 0x9ece, + 0x66c6, + 0x6b77, + 0x8f62, + 0x5e74, + 0x6190, + 0x6200, + 0x649a, + 0x6f23, + 0x7149, + 0x7489, + 0x79ca, + 0x7df4, + 0x806f, + 0x8f26, + 0x84ee, + 0x9023, + 0x934a, + 0x5217, + 0x52a3, + 0x54bd, + 0x70c8, + 0x88c2, + 0x5ec9, + 0x5ff5, + 0x637b, + 0x6bae, + 0x7c3e, + 0x7375, + 0x4ee4, + 0x56f9, + 0x5dba, + 0x601c, + 0x73b2, + 0x7469, + 0x7f9a, + 0x8046, + 0x9234, + 0x96f6, + 0x9748, + 0x9818, + 0x4f8b, + 0x79ae, + 0x91b4, + 0x96b8, + 0x60e1, + 0x4e86, + 0x50da, + 0x5bee, + 0x5c3f, + 0x6599, + 0x71ce, + 0x7642, + 0x84fc, + 0x907c, + 0x6688, + 0x962e, + 0x5289, + 0x677b, + 0x67f3, + 0x6d41, + 0x6e9c, + 0x7409, + 0x7559, + 0x786b, + 0x7d10, + 0x985e, + 0x622e, + 0x9678, + 0x502b, + 0x5d19, + 0x6dea, + 0x8f2a, + 0x5f8b, + 0x6144, + 0x6817, + 0x9686, + 0x5229, + 0x540f, + 0x5c65, + 0x6613, + 0x674e, + 0x68a8, + 0x6ce5, + 0x7406, + 0x75e2, + 0x7f79, + 0x88cf, + 0x88e1, + 0x96e2, + 0x533f, + 0x6eba, + 0x541d, + 0x71d0, + 0x7498, + 0x85fa, + 0x96a3, + 0x9c57, + 0x9e9f, + 0x6797, + 0x6dcb, + 0x81e8, + 0x7b20, + 0x7c92, + 0x72c0, + 0x7099, + 0x8b58, + 0x4ec0, + 0x8336, + 0x523a, + 0x5207, + 0x5ea6, + 0x62d3, + 0x7cd6, + 0x5b85, + 0x6d1e, + 0x66b4, + 0x8f3b, + 0x964d, + 0x5ed3, + 0x5140, + 0x55c0, + 0x585a, + 0x6674, + 0x51de, + 0x732a, + 0x76ca, + 0x793c, + 0x795e, + 0x7965, + 0x798f, + 0x9756, + 0x7cbe, + 0x8612, + 0x8af8, + 0x9038, + 0x90fd, + 0x98ef, + 0x98fc, + 0x9928, + 0x9db4, + 0x4fae, + 0x50e7, + 0x514d, + 0x52c9, + 0x52e4, + 0x5351, + 0x559d, + 0x5606, + 0x5668, + 0x5840, + 0x58a8, + 0x5c64, + 0x6094, + 0x6168, + 0x618e, + 0x61f2, + 0x654f, + 0x65e2, + 0x6691, + 0x6885, + 0x6d77, + 0x6e1a, + 0x6f22, + 0x716e, + 0x722b, + 0x7422, + 0x7891, + 0x7949, + 0x7948, + 0x7950, + 0x7956, + 0x798d, + 0x798e, + 0x7a40, + 0x7a81, + 0x7bc0, + 0x7e09, + 0x7e41, + 0x7f72, + 0x8005, + 0x81ed, + 0x8279, + 0x8457, + 0x8910, + 0x8996, + 0x8b01, + 0x8b39, + 0x8cd3, + 0x8d08, + 0x8fb6, + 0x96e3, + 0x97ff, + 0x983b, + 0x66, + 0x66, + 0x66, + 0x69, + 0x66, + 0x6c, + 0x66, + 0x66, + 0x6c, + 0x17f, + 0x74, + 0x73, + 0x74, + 0x574, + 0x576, + 0x574, + 0x565, + 0x574, + 0x56b, + 0x57e, + 0x576, + 0x574, + 0x56d, + 0x5d9, + 0x5b4, + 0x5f2, + 0x5b7, + 0x5e2, + 0x5d4, + 0x5db, + 0x5dc, + 0x5dd, + 0x5e8, + 0x5ea, + 0x5e9, + 0x5c1, + 0x5e9, + 0x5c2, + 0xfb49, + 0x5c1, + 0xfb49, + 0x5c2, + 0x5d0, + 0x5b7, + 0x5d0, + 0x5b8, + 0x5d0, + 0x5bc, + 0x5d1, + 0x5bc, + 0x5d2, + 0x5bc, + 0x5d3, + 0x5bc, + 0x5d4, + 0x5bc, + 0x5d5, + 0x5bc, + 0x5d6, + 0x5bc, + 0x5d8, + 0x5bc, + 0x5d9, + 0x5bc, + 0x5da, + 0x5bc, + 0x5db, + 0x5bc, + 0x5dc, + 0x5bc, + 0x5de, + 0x5bc, + 0x5e0, + 0x5bc, + 0x5e1, + 0x5bc, + 0x5e3, + 0x5bc, + 0x5e4, + 0x5bc, + 0x5e6, + 0x5bc, + 0x5e7, + 0x5bc, + 0x5e8, + 0x5bc, + 0x5e9, + 0x5bc, + 0x5ea, + 0x5bc, + 0x5d5, + 0x5b9, + 0x5d1, + 0x5bf, + 0x5db, + 0x5bf, + 0x5e4, + 0x5bf, + 0x5d0, + 0x5dc, + 0x671, + 0x67b, + 0x67e, + 0x680, + 0x67a, + 0x67f, + 0x679, + 0x6a4, + 0x6a6, + 0x684, + 0x683, + 0x686, + 0x687, + 0x68d, + 0x68c, + 0x68e, + 0x688, + 0x698, + 0x691, + 0x6a9, + 0x6af, + 0x6b3, + 0x6b1, + 0x6ba, + 0x6bb, + 0x6c0, + 0x6be, + 0x6d3, + 0x6ad, + 0x6c6, + 0x6c8, + 0x677, + 0x6cb, + 0x6c5, + 0x6c9, + 0x6d0, + 0x649, + 0x626, + 0x627, + 0x626, + 0x6d5, + 0x626, + 0x648, + 0x626, + 0x6c7, + 0x626, + 0x6c6, + 0x626, + 0x6c8, + 0x626, + 0x6d0, + 0x626, + 0x649, + 0x6cc, + 0x626, + 0x62c, + 0x626, + 0x62d, + 0x626, + 0x645, + 0x626, + 0x64a, + 0x628, + 0x62c, + 0x628, + 0x62d, + 0x628, + 0x62e, + 0x628, + 0x645, + 0x628, + 0x649, + 0x628, + 0x64a, + 0x62a, + 0x62c, + 0x62a, + 0x62d, + 0x62a, + 0x62e, + 0x62a, + 0x645, + 0x62a, + 0x649, + 0x62a, + 0x64a, + 0x62b, + 0x62c, + 0x62b, + 0x645, + 0x62b, + 0x649, + 0x62b, + 0x64a, + 0x62c, + 0x62d, + 0x62c, + 0x645, + 0x62d, + 0x645, + 0x62e, + 0x62c, + 0x62e, + 0x62d, + 0x62e, + 0x645, + 0x633, + 0x62c, + 0x633, + 0x62d, + 0x633, + 0x62e, + 0x633, + 0x645, + 0x635, + 0x62d, + 0x635, + 0x645, + 0x636, + 0x62c, + 0x636, + 0x62d, + 0x636, + 0x62e, + 0x636, + 0x645, + 0x637, + 0x62d, + 0x637, + 0x645, + 0x638, + 0x645, + 0x639, + 0x62c, + 0x639, + 0x645, + 0x63a, + 0x62c, + 0x63a, + 0x645, + 0x641, + 0x62c, + 0x641, + 0x62d, + 0x641, + 0x62e, + 0x641, + 0x645, + 0x641, + 0x649, + 0x641, + 0x64a, + 0x642, + 0x62d, + 0x642, + 0x645, + 0x642, + 0x649, + 0x642, + 0x64a, + 0x643, + 0x627, + 0x643, + 0x62c, + 0x643, + 0x62d, + 0x643, + 0x62e, + 0x643, + 0x644, + 0x643, + 0x645, + 0x643, + 0x649, + 0x643, + 0x64a, + 0x644, + 0x62c, + 0x644, + 0x62d, + 0x644, + 0x62e, + 0x644, + 0x645, + 0x644, + 0x649, + 0x644, + 0x64a, + 0x645, + 0x62c, + 0x645, + 0x645, + 0x645, + 0x649, + 0x645, + 0x64a, + 0x646, + 0x62c, + 0x646, + 0x62d, + 0x646, + 0x62e, + 0x646, + 0x645, + 0x646, + 0x649, + 0x646, + 0x64a, + 0x647, + 0x62c, + 0x647, + 0x645, + 0x647, + 0x649, + 0x647, + 0x64a, + 0x64a, + 0x62d, + 0x64a, + 0x62e, + 0x64a, + 0x649, + 0x630, + 0x670, + 0x631, + 0x670, + 0x649, + 0x670, + 0x20, + 0x64c, + 0x651, + 0x20, + 0x64d, + 0x651, + 0x20, + 0x64e, + 0x651, + 0x20, + 0x64f, + 0x651, + 0x20, + 0x650, + 0x651, + 0x20, + 0x651, + 0x670, + 0x626, + 0x631, + 0x626, + 0x632, + 0x626, + 0x646, + 0x628, + 0x631, + 0x628, + 0x632, + 0x628, + 0x646, + 0x62a, + 0x631, + 0x62a, + 0x632, + 0x62a, + 0x646, + 0x62b, + 0x631, + 0x62b, + 0x632, + 0x62b, + 0x646, + 0x645, + 0x627, + 0x646, + 0x631, + 0x646, + 0x632, + 0x646, + 0x646, + 0x64a, + 0x631, + 0x64a, + 0x632, + 0x626, + 0x62e, + 0x626, + 0x647, + 0x628, + 0x647, + 0x62a, + 0x647, + 0x635, + 0x62e, + 0x644, + 0x647, + 0x646, + 0x647, + 0x647, + 0x670, + 0x62b, + 0x647, + 0x633, + 0x647, + 0x634, + 0x645, + 0x634, + 0x647, + 0x640, + 0x64e, + 0x651, + 0x640, + 0x64f, + 0x651, + 0x640, + 0x650, + 0x651, + 0x637, + 0x649, + 0x637, + 0x64a, + 0x639, + 0x649, + 0x639, + 0x64a, + 0x63a, + 0x649, + 0x63a, + 0x64a, + 0x633, + 0x649, + 0x633, + 0x64a, + 0x634, + 0x649, + 0x634, + 0x64a, + 0x62d, + 0x649, + 0x62c, + 0x649, + 0x62c, + 0x64a, + 0x62e, + 0x649, + 0x635, + 0x649, + 0x635, + 0x64a, + 0x636, + 0x649, + 0x636, + 0x64a, + 0x634, + 0x62c, + 0x634, + 0x62d, + 0x634, + 0x62e, + 0x634, + 0x631, + 0x633, + 0x631, + 0x635, + 0x631, + 0x636, + 0x631, + 0x627, + 0x64b, + 0x62a, + 0x62c, + 0x645, + 0x62a, + 0x62d, + 0x62c, + 0x62a, + 0x62d, + 0x645, + 0x62a, + 0x62e, + 0x645, + 0x62a, + 0x645, + 0x62c, + 0x62a, + 0x645, + 0x62d, + 0x62a, + 0x645, + 0x62e, + 0x62d, + 0x645, + 0x64a, + 0x62d, + 0x645, + 0x649, + 0x633, + 0x62d, + 0x62c, + 0x633, + 0x62c, + 0x62d, + 0x633, + 0x62c, + 0x649, + 0x633, + 0x645, + 0x62d, + 0x633, + 0x645, + 0x62c, + 0x633, + 0x645, + 0x645, + 0x635, + 0x62d, + 0x62d, + 0x635, + 0x645, + 0x645, + 0x634, + 0x62d, + 0x645, + 0x634, + 0x62c, + 0x64a, + 0x634, + 0x645, + 0x62e, + 0x634, + 0x645, + 0x645, + 0x636, + 0x62d, + 0x649, + 0x636, + 0x62e, + 0x645, + 0x637, + 0x645, + 0x62d, + 0x637, + 0x645, + 0x645, + 0x637, + 0x645, + 0x64a, + 0x639, + 0x62c, + 0x645, + 0x639, + 0x645, + 0x645, + 0x639, + 0x645, + 0x649, + 0x63a, + 0x645, + 0x645, + 0x63a, + 0x645, + 0x64a, + 0x63a, + 0x645, + 0x649, + 0x641, + 0x62e, + 0x645, + 0x642, + 0x645, + 0x62d, + 0x642, + 0x645, + 0x645, + 0x644, + 0x62d, + 0x645, + 0x644, + 0x62d, + 0x64a, + 0x644, + 0x62d, + 0x649, + 0x644, + 0x62c, + 0x62c, + 0x644, + 0x62e, + 0x645, + 0x644, + 0x645, + 0x62d, + 0x645, + 0x62d, + 0x62c, + 0x645, + 0x62d, + 0x64a, + 0x645, + 0x62c, + 0x62d, + 0x645, + 0x62e, + 0x645, + 0x645, + 0x62c, + 0x62e, + 0x647, + 0x645, + 0x62c, + 0x647, + 0x645, + 0x645, + 0x646, + 0x62d, + 0x645, + 0x646, + 0x62d, + 0x649, + 0x646, + 0x62c, + 0x645, + 0x646, + 0x62c, + 0x649, + 0x646, + 0x645, + 0x64a, + 0x646, + 0x645, + 0x649, + 0x64a, + 0x645, + 0x645, + 0x628, + 0x62e, + 0x64a, + 0x62a, + 0x62c, + 0x64a, + 0x62a, + 0x62c, + 0x649, + 0x62a, + 0x62e, + 0x64a, + 0x62a, + 0x62e, + 0x649, + 0x62a, + 0x645, + 0x64a, + 0x62a, + 0x645, + 0x649, + 0x62c, + 0x645, + 0x64a, + 0x62c, + 0x62d, + 0x649, + 0x62c, + 0x645, + 0x649, + 0x633, + 0x62e, + 0x649, + 0x635, + 0x62d, + 0x64a, + 0x634, + 0x62d, + 0x64a, + 0x636, + 0x62d, + 0x64a, + 0x644, + 0x62c, + 0x64a, + 0x644, + 0x645, + 0x64a, + 0x64a, + 0x62c, + 0x64a, + 0x64a, + 0x645, + 0x64a, + 0x645, + 0x645, + 0x64a, + 0x642, + 0x645, + 0x64a, + 0x646, + 0x62d, + 0x64a, + 0x639, + 0x645, + 0x64a, + 0x643, + 0x645, + 0x64a, + 0x646, + 0x62c, + 0x62d, + 0x645, + 0x62e, + 0x64a, + 0x644, + 0x62c, + 0x645, + 0x643, + 0x645, + 0x645, + 0x62c, + 0x62d, + 0x64a, + 0x62d, + 0x62c, + 0x64a, + 0x645, + 0x62c, + 0x64a, + 0x641, + 0x645, + 0x64a, + 0x628, + 0x62d, + 0x64a, + 0x633, + 0x62e, + 0x64a, + 0x646, + 0x62c, + 0x64a, + 0x635, + 0x644, + 0x6d2, + 0x642, + 0x644, + 0x6d2, + 0x627, + 0x644, + 0x644, + 0x647, + 0x627, + 0x643, + 0x628, + 0x631, + 0x645, + 0x62d, + 0x645, + 0x62f, + 0x635, + 0x644, + 0x639, + 0x645, + 0x631, + 0x633, + 0x648, + 0x644, + 0x639, + 0x644, + 0x64a, + 0x647, + 0x648, + 0x633, + 0x644, + 0x645, + 0x635, + 0x644, + 0x649, + 0x635, + 0x644, + 0x649, + 0x20, + 0x627, + 0x644, + 0x644, + 0x647, + 0x20, + 0x639, + 0x644, + 0x64a, + 0x647, + 0x20, + 0x648, + 0x633, + 0x644, + 0x645, + 0x62c, + 0x644, + 0x20, + 0x62c, + 0x644, + 0x627, + 0x644, + 0x647, + 0x631, + 0x6cc, + 0x627, + 0x644, + 0x2025, + 0x2014, + 0x2013, + 0x5f, + 0x7b, + 0x7d, + 0x3014, + 0x3015, + 0x3010, + 0x3011, + 0x300a, + 0x300b, + 0x300c, + 0x300d, + 0x300e, + 0x300f, + 0x5b, + 0x5d, + 0x203e, + 0x2c, + 0x3001, + 0x23, + 0x26, + 0x2a, + 0x2d, + 0x5c, + 0x24, + 0x25, + 0x40, + 0x20, + 0x64b, + 0x640, + 0x64b, + 0x640, + 0x651, + 0x20, + 0x652, + 0x640, + 0x652, + 0x621, + 0x622, + 0x623, + 0x624, + 0x625, + 0x629, + 0x644, + 0x622, + 0x644, + 0x623, + 0x644, + 0x625, + 0x22, + 0x27, + 0x5e, + 0x7c, + 0x7e, + 0x2985, + 0x2986, + 0x3002, + 0x30fb, + 0x30a5, + 0x30e3, + 0x3164, + 0x3131, + 0x3132, + 0x3133, + 0x3134, + 0x3135, + 0x3136, + 0x3137, + 0x3138, + 0x3139, + 0x313a, + 0x313b, + 0x313c, + 0x313d, + 0x313e, + 0x313f, + 0x3140, + 0x3141, + 0x3142, + 0x3143, + 0x3144, + 0x3145, + 0x3146, + 0x3147, + 0x3148, + 0x3149, + 0x314a, + 0x314b, + 0x314c, + 0x314d, + 0x314e, + 0x314f, + 0x3150, + 0x3151, + 0x3152, + 0x3153, + 0x3154, + 0x3155, + 0x3156, + 0x3157, + 0x3158, + 0x3159, + 0x315a, + 0x315b, + 0x315c, + 0x315d, + 0x315e, + 0x315f, + 0x3160, + 0x3161, + 0x3162, + 0x3163, + 0xa2, + 0xa3, + 0xac, + 0xaf, + 0xa6, + 0xa5, + 0x20a9, + 0x2502, + 0x2191, + 0x2193, + 0x25a0, + 0x25cb, + 0x1d157, + 0x1d165, + 0x1d158, + 0x1d165, + 0x1d15f, + 0x1d16e, + 0x1d15f, + 0x1d16f, + 0x1d15f, + 0x1d170, + 0x1d15f, + 0x1d171, + 0x1d15f, + 0x1d172, + 0x1d1b9, + 0x1d165, + 0x1d1ba, + 0x1d165, + 0x1d1bb, + 0x1d16e, + 0x1d1bc, + 0x1d16e, + 0x1d1bb, + 0x1d16f, + 0x1d1bc, + 0x1d16f, + 0x392, + 0x394, + 0x396, + 0x39a, + 0x39b, + 0x39c, + 0x39d, + 0x39e, + 0x3f4, + 0x3a4, + 0x3a6, + 0x3a7, + 0x3a8, + 0x2207, + 0x3b6, + 0x3bb, + 0x3bd, + 0x3be, + 0x3c3, + 0x3c4, + 0x3c8, + 0x2202, + 0x3f5, + 0x3d1, + 0x3f0, + 0x3d5, + 0x3f1, + 0x3d6, + 0x4e3d, + 0x4e38, + 0x4e41, + 0x20122, + 0x4f60, + 0x4fbb, + 0x5002, + 0x507a, + 0x5099, + 0x50cf, + 0x349e, + 0x2063a, + 0x5154, + 0x5164, + 0x5177, + 0x2051c, + 0x34b9, + 0x5167, + 0x518d, + 0x2054b, + 0x5197, + 0x51a4, + 0x4ecc, + 0x51ac, + 0x51b5, + 0x291df, + 0x5203, + 0x34df, + 0x523b, + 0x5246, + 0x5272, + 0x5277, + 0x3515, + 0x52c7, + 0x52fa, + 0x5305, + 0x5306, + 0x5349, + 0x535a, + 0x5373, + 0x537d, + 0x537f, + 0x20a2c, + 0x7070, + 0x53ca, + 0x53df, + 0x20b63, + 0x53eb, + 0x53f1, + 0x5406, + 0x549e, + 0x5438, + 0x5448, + 0x5468, + 0x54a2, + 0x54f6, + 0x5510, + 0x5553, + 0x5563, + 0x5584, + 0x5599, + 0x55ab, + 0x55b3, + 0x55c2, + 0x5716, + 0x5717, + 0x5651, + 0x5674, + 0x58ee, + 0x57ce, + 0x57f4, + 0x580d, + 0x578b, + 0x5832, + 0x5831, + 0x58ac, + 0x214e4, + 0x58f2, + 0x58f7, + 0x5906, + 0x591a, + 0x5922, + 0x5962, + 0x216a8, + 0x216ea, + 0x59ec, + 0x5a1b, + 0x5a27, + 0x59d8, + 0x5a66, + 0x36ee, + 0x36fc, + 0x5b08, + 0x5b3e, + 0x219c8, + 0x5bc3, + 0x5bd8, + 0x5bf3, + 0x21b18, + 0x5bff, + 0x5c06, + 0x5f53, + 0x3781, + 0x5c60, + 0x5cc0, + 0x5c8d, + 0x21de4, + 0x5d43, + 0x21de6, + 0x5d6e, + 0x5d6b, + 0x5d7c, + 0x5de1, + 0x5de2, + 0x382f, + 0x5dfd, + 0x5e28, + 0x5e3d, + 0x5e69, + 0x3862, + 0x22183, + 0x387c, + 0x5eb0, + 0x5eb3, + 0x5eb6, + 0x2a392, + 0x22331, + 0x8201, + 0x5f22, + 0x38c7, + 0x232b8, + 0x261da, + 0x5f62, + 0x5f6b, + 0x38e3, + 0x5f9a, + 0x5fcd, + 0x5fd7, + 0x5ff9, + 0x6081, + 0x393a, + 0x391c, + 0x226d4, + 0x60c7, + 0x6148, + 0x614c, + 0x614e, + 0x617a, + 0x61b2, + 0x61a4, + 0x61af, + 0x61de, + 0x621b, + 0x625d, + 0x62b1, + 0x62d4, + 0x6350, + 0x22b0c, + 0x633d, + 0x62fc, + 0x6368, + 0x6383, + 0x63e4, + 0x22bf1, + 0x6422, + 0x63c5, + 0x63a9, + 0x3a2e, + 0x6469, + 0x647e, + 0x649d, + 0x6477, + 0x3a6c, + 0x656c, + 0x2300a, + 0x65e3, + 0x66f8, + 0x6649, + 0x3b19, + 0x3b08, + 0x3ae4, + 0x5192, + 0x5195, + 0x6700, + 0x669c, + 0x80ad, + 0x43d9, + 0x671b, + 0x6721, + 0x675e, + 0x6753, + 0x233c3, + 0x3b49, + 0x67fa, + 0x6785, + 0x6852, + 0x2346d, + 0x688e, + 0x681f, + 0x6914, + 0x3b9d, + 0x6942, + 0x69a3, + 0x69ea, + 0x6aa8, + 0x236a3, + 0x6adb, + 0x3c18, + 0x6b21, + 0x238a7, + 0x6b54, + 0x3c4e, + 0x6b72, + 0x6b9f, + 0x6bbb, + 0x23a8d, + 0x21d0b, + 0x23afa, + 0x6c4e, + 0x23cbc, + 0x6cbf, + 0x6ccd, + 0x6c67, + 0x6d16, + 0x6d3e, + 0x6d69, + 0x6d78, + 0x6d85, + 0x23d1e, + 0x6d34, + 0x6e2f, + 0x6e6e, + 0x3d33, + 0x6ecb, + 0x6ec7, + 0x23ed1, + 0x6df9, + 0x6f6e, + 0x23f5e, + 0x23f8e, + 0x6fc6, + 0x7039, + 0x701e, + 0x701b, + 0x3d96, + 0x704a, + 0x707d, + 0x7077, + 0x70ad, + 0x20525, + 0x7145, + 0x24263, + 0x719c, + 0x243ab, + 0x7228, + 0x7235, + 0x7250, + 0x24608, + 0x7280, + 0x7295, + 0x24735, + 0x24814, + 0x737a, + 0x738b, + 0x3eac, + 0x73a5, + 0x3eb8, + 0x7447, + 0x745c, + 0x7471, + 0x7485, + 0x74ca, + 0x3f1b, + 0x7524, + 0x24c36, + 0x753e, + 0x24c92, + 0x2219f, + 0x7610, + 0x24fa1, + 0x24fb8, + 0x25044, + 0x3ffc, + 0x4008, + 0x76f4, + 0x250f3, + 0x250f2, + 0x25119, + 0x25133, + 0x771e, + 0x771f, + 0x774a, + 0x4039, + 0x778b, + 0x4046, + 0x4096, + 0x2541d, + 0x784e, + 0x78cc, + 0x40e3, + 0x25626, + 0x2569a, + 0x256c5, + 0x79eb, + 0x412f, + 0x7a4a, + 0x7a4f, + 0x2597c, + 0x25aa7, + 0x7aee, + 0x4202, + 0x25bab, + 0x7bc6, + 0x7bc9, + 0x4227, + 0x25c80, + 0x7cd2, + 0x42a0, + 0x7ce8, + 0x7ce3, + 0x7d00, + 0x25f86, + 0x7d63, + 0x4301, + 0x7dc7, + 0x7e02, + 0x7e45, + 0x4334, + 0x26228, + 0x26247, + 0x4359, + 0x262d9, + 0x7f7a, + 0x2633e, + 0x7f95, + 0x7ffa, + 0x264da, + 0x26523, + 0x8060, + 0x265a8, + 0x8070, + 0x2335f, + 0x43d5, + 0x80b2, + 0x8103, + 0x440b, + 0x813e, + 0x5ab5, + 0x267a7, + 0x267b5, + 0x23393, + 0x2339c, + 0x8204, + 0x8f9e, + 0x446b, + 0x8291, + 0x828b, + 0x829d, + 0x52b3, + 0x82b1, + 0x82b3, + 0x82bd, + 0x82e6, + 0x26b3c, + 0x831d, + 0x8363, + 0x83ad, + 0x8323, + 0x83bd, + 0x83e7, + 0x8353, + 0x83ca, + 0x83cc, + 0x83dc, + 0x26c36, + 0x26d6b, + 0x26cd5, + 0x452b, + 0x84f1, + 0x84f3, + 0x8516, + 0x273ca, + 0x8564, + 0x26f2c, + 0x455d, + 0x4561, + 0x26fb1, + 0x270d2, + 0x456b, + 0x8650, + 0x8667, + 0x8669, + 0x86a9, + 0x8688, + 0x870e, + 0x86e2, + 0x8779, + 0x8728, + 0x876b, + 0x8786, + 0x45d7, + 0x87e1, + 0x8801, + 0x45f9, + 0x8860, + 0x27667, + 0x88d7, + 0x88de, + 0x4635, + 0x88fa, + 0x34bb, + 0x278ae, + 0x27966, + 0x46be, + 0x46c7, + 0x8aa0, + 0x8aed, + 0x8b8a, + 0x27ca8, + 0x8cab, + 0x8cc1, + 0x8d1b, + 0x8d77, + 0x27f2f, + 0x20804, + 0x8dcb, + 0x8dbc, + 0x8df0, + 0x208de, + 0x8ed4, + 0x8f38, + 0x285d2, + 0x285ed, + 0x9094, + 0x90f1, + 0x9111, + 0x2872e, + 0x911b, + 0x9238, + 0x92d7, + 0x92d8, + 0x927c, + 0x93f9, + 0x9415, + 0x28bfa, + 0x958b, + 0x4995, + 0x95b7, + 0x28d77, + 0x49e6, + 0x96c3, + 0x5db2, + 0x9723, + 0x29145, + 0x2921a, + 0x4a6e, + 0x4a76, + 0x97e0, + 0x2940a, + 0x4ab2, + 0x29496, + 0x980b, + 0x9829, + 0x295b6, + 0x98e2, + 0x4b33, + 0x9929, + 0x99a7, + 0x99c2, + 0x99fe, + 0x4bce, + 0x29b30, + 0x9b12, + 0x9c40, + 0x9cfd, + 0x4cce, + 0x4ced, + 0x9d67, + 0x2a0ce, + 0x4cf8, + 0x2a105, + 0x2a20e, + 0x2a291, + 0x4d56, + 0x9efe, + 0x9f05, + 0x9f0f, + 0x9f16, + 0x2a600, +}; + +const struct canon_node _wind_canon_table[] = { + {0x0, 0, 3, 0}, + {0x0, 0, 10, 3}, + {0x0, 0, 16, 13}, + {0x0, 0, 15, 29}, + {0x0, 1, 14, 44}, + {0x2f993, 16, 16, 57}, + {0x0, 0, 16, 57}, + {0x0, 0, 16, 73}, + {0x0, 8, 16, 89}, + {0xf942, 16, 16, 97}, + {0x2f994, 16, 16, 97}, + {0x0, 0, 16, 97}, + {0x0, 9, 15, 113}, + {0x0, 5, 6, 119}, + {0x2f9ef, 16, 16, 120}, + {0x0, 0, 16, 120}, + {0x0, 0, 16, 136}, + {0x0, 0, 16, 152}, + {0x0, 0, 1, 168}, + {0x0, 0, 1, 169}, + {0x0, 3, 4, 170}, + {0x0, 4, 5, 171}, + {0x0, 5, 6, 172}, + {0x1f94, 16, 16, 173}, + {0x0, 0, 16, 173}, + {0x0, 0, 12, 189}, + {0x0, 10, 12, 201}, + {0x2f8f6, 16, 16, 203}, + {0xf970, 16, 16, 203}, + {0x0, 0, 16, 203}, + {0x0, 2, 14, 219}, + {0x0, 2, 6, 231}, + {0x0, 0, 1, 235}, + {0x0, 0, 1, 236}, + {0x0, 6, 7, 237}, + {0x0, 5, 6, 238}, + {0x0, 4, 5, 239}, + {0x6c0, 16, 16, 240}, + {0x0, 0, 16, 240}, + {0x0, 0, 13, 256}, + {0x0, 9, 10, 269}, + {0xf9ae, 16, 16, 270}, + {0x0, 0, 16, 270}, + {0x0, 2, 16, 286}, + {0x0, 15, 16, 300}, + {0xfa69, 16, 16, 301}, + {0x0, 0, 11, 301}, + {0x0, 1, 16, 312}, + {0x0, 3, 14, 327}, + {0x0, 6, 7, 338}, + {0x2f9a4, 16, 16, 339}, + {0x0, 4, 15, 339}, + {0x0, 9, 10, 350}, + {0xf9be, 16, 16, 351}, + {0x0, 1, 12, 351}, + {0x0, 7, 8, 362}, + {0x2f864, 16, 16, 363}, + {0x0, 0, 13, 363}, + {0x0, 0, 1, 376}, + {0x0, 0, 1, 377}, + {0x0, 3, 4, 378}, + {0x0, 4, 5, 379}, + {0x0, 5, 6, 380}, + {0x1fc2, 16, 16, 381}, + {0x0, 0, 16, 381}, + {0x0, 0, 16, 397}, + {0x0, 1, 16, 413}, + {0x0, 0, 1, 428}, + {0x0, 3, 4, 429}, + {0x0, 0, 1, 430}, + {0x0, 9, 10, 431}, + {0x0, 9, 10, 432}, + {0x3065, 16, 16, 433}, + {0x0, 0, 3, 433}, + {0x0, 0, 12, 436}, + {0x0, 3, 14, 448}, + {0x0, 0, 1, 459}, + {0x0, 0, 1, 460}, + {0x0, 3, 4, 461}, + {0x0, 3, 4, 462}, + {0x0, 8, 9, 463}, + {0x2244, 16, 16, 464}, + {0x0, 0, 15, 464}, + {0x0, 0, 12, 479}, + {0x0, 0, 1, 491}, + {0x0, 0, 1, 492}, + {0x0, 3, 4, 493}, + {0x0, 0, 1, 494}, + {0x0, 8, 9, 495}, + {0x1e7b, 16, 16, 496}, + {0x0, 1, 16, 496}, + {0x0, 0, 1, 511}, + {0x0, 3, 4, 512}, + {0x0, 0, 1, 513}, + {0x0, 9, 10, 514}, + {0x0, 9, 10, 515}, + {0x30ba, 16, 16, 516}, + {0x2f995, 16, 16, 516}, + {0x0, 0, 15, 516}, + {0x0, 0, 15, 531}, + {0x0, 0, 1, 546}, + {0x0, 0, 1, 547}, + {0x0, 3, 4, 548}, + {0x0, 0, 1, 549}, + {0x0, 8, 9, 550}, + {0x4df, 16, 16, 551}, + {0x0, 0, 16, 551}, + {0x0, 7, 8, 567}, + {0x2f9d7, 16, 16, 568}, + {0x0, 0, 16, 568}, + {0x0, 14, 15, 584}, + {0x2f86b, 16, 16, 585}, + {0xf94a, 16, 16, 585}, + {0x0, 4, 14, 585}, + {0x0, 9, 13, 595}, + {0x0, 0, 1, 599}, + {0x0, 0, 1, 600}, + {0x0, 13, 14, 601}, + {0x0, 12, 13, 602}, + {0x0, 10, 11, 603}, + {0xddd, 16, 16, 604}, + {0x0, 2, 16, 604}, + {0x0, 1, 15, 618}, + {0xf91a, 16, 16, 632}, + {0x0, 0, 16, 632}, + {0x0, 1, 4, 648}, + {0x0, 9, 10, 651}, + {0x2f943, 16, 16, 652}, + {0x0, 0, 16, 652}, + {0x0, 10, 11, 668}, + {0x0, 8, 9, 669}, + {0x2f9d3, 16, 16, 670}, + {0x0, 3, 16, 670}, + {0x0, 1, 16, 683}, + {0x0, 0, 1, 698}, + {0x0, 0, 1, 699}, + {0x0, 3, 4, 700}, + {0x0, 0, 3, 701}, + {0x0, 1, 13, 704}, + {0x10c, 16, 16, 716}, + {0x0, 1, 16, 716}, + {0x0, 1, 2, 731}, + {0xf958, 16, 16, 732}, + {0x0, 0, 1, 732}, + {0x0, 0, 1, 733}, + {0x0, 3, 4, 734}, + {0x0, 0, 1, 735}, + {0x0, 0, 9, 736}, + {0x4e5, 16, 16, 745}, + {0x439, 16, 16, 745}, + {0x4e3, 16, 16, 745}, + {0x0, 2, 15, 745}, + {0x0, 12, 13, 758}, + {0x2f8c7, 16, 16, 759}, + {0x0, 0, 1, 759}, + {0x0, 3, 4, 760}, + {0x0, 0, 1, 761}, + {0x0, 9, 10, 762}, + {0x0, 9, 10, 763}, + {0x30b4, 16, 16, 764}, + {0x45d, 16, 16, 764}, + {0x0, 0, 16, 764}, + {0x0, 0, 1, 780}, + {0x0, 0, 1, 781}, + {0x0, 3, 4, 782}, + {0x0, 0, 3, 783}, + {0x0, 0, 10, 786}, + {0x1ee8, 16, 16, 796}, + {0x0, 0, 16, 796}, + {0x0, 0, 1, 812}, + {0x0, 0, 1, 813}, + {0x0, 3, 4, 814}, + {0x0, 0, 4, 815}, + {0x0, 3, 14, 819}, + {0x1eb9, 16, 16, 830}, + {0x1eee, 16, 16, 830}, + {0x229, 16, 16, 830}, + {0x1eec, 16, 16, 830}, + {0x119, 16, 16, 830}, + {0x2fa07, 16, 16, 830}, + {0x10a, 16, 16, 830}, + {0x106, 16, 16, 830}, + {0x108, 16, 16, 830}, + {0x0, 1, 16, 830}, + {0x0, 9, 10, 845}, + {0x2f90e, 16, 16, 846}, + {0x0, 0, 14, 846}, + {0x0, 1, 16, 860}, + {0x0, 0, 1, 875}, + {0x0, 0, 1, 876}, + {0x0, 3, 4, 877}, + {0x0, 0, 2, 878}, + {0x0, 4, 5, 880}, + {0x1f59, 16, 16, 881}, + {0x0, 6, 12, 881}, + {0x0, 14, 15, 887}, + {0x2f9f8, 16, 16, 888}, + {0x0, 0, 11, 888}, + {0x0, 0, 1, 899}, + {0x0, 0, 1, 900}, + {0x0, 3, 4, 901}, + {0x0, 0, 4, 902}, + {0x0, 1, 2, 906}, + {0x212, 16, 16, 907}, + {0x0, 0, 1, 907}, + {0x0, 0, 1, 908}, + {0x0, 3, 4, 909}, + {0x0, 0, 3, 910}, + {0x0, 1, 12, 913}, + {0x20f, 16, 16, 924}, + {0x0, 2, 14, 924}, + {0x0, 0, 1, 936}, + {0x0, 0, 1, 937}, + {0x0, 3, 4, 938}, + {0x0, 3, 4, 939}, + {0x0, 8, 9, 940}, + {0x22e1, 16, 16, 941}, + {0x0, 0, 15, 941}, + {0x0, 13, 14, 956}, + {0xf967, 16, 16, 957}, + {0x1e19, 16, 16, 957}, + {0x0, 1, 16, 957}, + {0x0, 10, 11, 972}, + {0xf9f0, 16, 16, 973}, + {0x0, 0, 15, 973}, + {0x0, 2, 3, 988}, + {0x2f807, 16, 16, 989}, + {0x0, 3, 15, 989}, + {0x0, 13, 14, 1001}, + {0x2f8b9, 16, 16, 1002}, + {0x0, 0, 1, 1002}, + {0x0, 0, 1, 1003}, + {0x0, 3, 4, 1004}, + {0x0, 0, 4, 1005}, + {0x0, 0, 16, 1009}, + {0x1d0, 16, 16, 1025}, + {0x0, 0, 14, 1025}, + {0x0, 9, 10, 1039}, + {0x2f974, 16, 16, 1040}, + {0x0, 1, 12, 1040}, + {0x0, 1, 5, 1051}, + {0x0, 5, 6, 1055}, + {0x2f91b, 16, 16, 1056}, + {0x0, 0, 1, 1056}, + {0x0, 0, 1, 1057}, + {0x0, 3, 4, 1058}, + {0x0, 3, 4, 1059}, + {0x0, 8, 9, 1060}, + {0x22e0, 16, 16, 1061}, + {0x0, 0, 16, 1061}, + {0x0, 1, 11, 1077}, + {0x2f82e, 16, 16, 1087}, + {0x0, 0, 16, 1087}, + {0x0, 0, 1, 1103}, + {0x0, 0, 1, 1104}, + {0x0, 3, 4, 1105}, + {0x0, 0, 2, 1106}, + {0x0, 3, 5, 1108}, + {0x1f19, 16, 16, 1110}, + {0x0, 0, 10, 1110}, + {0x0, 9, 10, 1120}, + {0x2f8ce, 16, 16, 1121}, + {0x1f18, 16, 16, 1121}, + {0x0, 1, 15, 1121}, + {0x1f7d, 0, 1, 1135}, + {0x0, 0, 1, 1136}, + {0x0, 3, 4, 1137}, + {0x0, 4, 5, 1138}, + {0x0, 5, 6, 1139}, + {0x1ff4, 16, 16, 1140}, + {0x0, 0, 16, 1140}, + {0x0, 9, 10, 1156}, + {0xf9dd, 16, 16, 1157}, + {0x0, 1, 14, 1157}, + {0x2f991, 16, 16, 1170}, + {0x0, 2, 16, 1170}, + {0x0, 3, 4, 1184}, + {0xfa0b, 16, 16, 1185}, + {0x0, 6, 16, 1185}, + {0x0, 0, 1, 1195}, + {0x0, 0, 1, 1196}, + {0x0, 3, 4, 1197}, + {0x0, 0, 5, 1198}, + {0x0, 2, 3, 1203}, + {0x1fcf, 16, 16, 1204}, + {0x0, 0, 15, 1204}, + {0x0, 8, 9, 1219}, + {0x2f9bc, 16, 16, 1220}, + {0x0, 6, 7, 1220}, + {0x0, 3, 4, 1221}, + {0x2f838, 16, 16, 1222}, + {0x0, 0, 7, 1222}, + {0x0, 9, 10, 1229}, + {0x0, 2, 3, 1230}, + {0x2f88f, 16, 16, 1231}, + {0x0, 2, 6, 1231}, + {0x0, 0, 1, 1235}, + {0x0, 0, 1, 1236}, + {0x0, 3, 4, 1237}, + {0x0, 3, 4, 1238}, + {0x0, 8, 9, 1239}, + {0x22ec, 16, 16, 1240}, + {0x0, 0, 7, 1240}, + {0x2f88d, 16, 16, 1247}, + {0x0, 4, 16, 1247}, + {0x0, 14, 15, 1259}, + {0xfa3f, 16, 16, 1260}, + {0x2f98f, 16, 16, 1260}, + {0x0, 8, 12, 1260}, + {0x0, 11, 12, 1264}, + {0x2f9ee, 16, 16, 1265}, + {0xfa35, 16, 16, 1265}, + {0x0, 0, 1, 1265}, + {0x0, 0, 1, 1266}, + {0x0, 3, 4, 1267}, + {0x0, 0, 3, 1268}, + {0x0, 1, 2, 1271}, + {0x203, 16, 16, 1272}, + {0x0, 6, 8, 1272}, + {0x0, 0, 1, 1274}, + {0x0, 0, 1, 1275}, + {0x0, 13, 14, 1276}, + {0x0, 3, 6, 1277}, + {0x0, 7, 8, 1280}, + {0xd4c, 16, 16, 1281}, + {0x0, 0, 15, 1281}, + {0x0, 2, 3, 1296}, + {0xfa20, 16, 16, 1297}, + {0x0, 3, 13, 1297}, + {0x0, 0, 2, 1307}, + {0x0, 0, 1, 1309}, + {0x0, 0, 1, 1310}, + {0x0, 3, 4, 1311}, + {0x0, 0, 1, 1312}, + {0x0, 2, 7, 1313}, + {0x1eac, 16, 16, 1318}, + {0x0, 0, 16, 1318}, + {0x0, 3, 4, 1334}, + {0x2f874, 16, 16, 1335}, + {0x1eb6, 16, 16, 1335}, + {0x0, 0, 1, 1335}, + {0x0, 0, 1, 1336}, + {0x0, 3, 4, 1337}, + {0x0, 4, 5, 1338}, + {0x0, 5, 6, 1339}, + {0x1f9c, 16, 16, 1340}, + {0x0, 2, 12, 1340}, + {0x0, 6, 16, 1350}, + {0x0, 0, 1, 1360}, + {0x0, 0, 1, 1361}, + {0x0, 3, 4, 1362}, + {0x0, 0, 1, 1363}, + {0x0, 6, 7, 1364}, + {0x1e1d, 16, 16, 1365}, + {0x0, 1, 14, 1365}, + {0x0, 0, 14, 1378}, + {0x2f918, 16, 16, 1392}, + {0x0, 2, 14, 1392}, + {0x0, 9, 10, 1404}, + {0x2f975, 16, 16, 1405}, + {0x0, 1, 10, 1405}, + {0x0, 11, 12, 1414}, + {0xfa0a, 16, 16, 1415}, + {0x0, 0, 16, 1415}, + {0x0, 2, 4, 1431}, + {0xf992, 16, 16, 1433}, + {0xfa47, 16, 16, 1433}, + {0x0, 2, 15, 1433}, + {0x0, 13, 16, 1446}, + {0xfa53, 16, 16, 1449}, + {0xfa52, 16, 16, 1449}, + {0xfa1b, 16, 16, 1449}, + {0x0, 0, 1, 1449}, + {0x0, 3, 4, 1450}, + {0x0, 0, 1, 1451}, + {0x0, 9, 10, 1452}, + {0x0, 9, 10, 1453}, + {0x30b2, 16, 16, 1454}, + {0x0, 0, 1, 1454}, + {0x0, 0, 1, 1455}, + {0x0, 3, 4, 1456}, + {0x0, 0, 5, 1457}, + {0x0, 0, 2, 1462}, + {0x1fca, 16, 16, 1464}, + {0x389, 16, 16, 1464}, + {0x0, 1, 16, 1464}, + {0x0, 12, 13, 1479}, + {0x2f93e, 16, 16, 1480}, + {0x0, 3, 15, 1480}, + {0x0, 3, 9, 1492}, + {0x2f968, 16, 16, 1498}, + {0x0, 0, 1, 1498}, + {0x0, 0, 1, 1499}, + {0x0, 3, 4, 1500}, + {0x0, 0, 5, 1501}, + {0x0, 2, 6, 1506}, + {0x1f2e, 16, 16, 1510}, + {0x1f98, 16, 16, 1510}, + {0x0, 6, 12, 1510}, + {0x0, 0, 1, 1516}, + {0x2f804, 16, 16, 1517}, + {0x2f919, 16, 16, 1517}, + {0x2f835, 16, 16, 1517}, + {0x0, 1, 2, 1517}, + {0x0, 5, 6, 1518}, + {0x2f824, 16, 16, 1519}, + {0x0, 0, 16, 1519}, + {0x1fe3, 16, 16, 1535}, + {0x0, 2, 4, 1535}, + {0x0, 0, 1, 1537}, + {0x0, 0, 1, 1538}, + {0x0, 3, 4, 1539}, + {0x0, 0, 1, 1540}, + {0x0, 7, 8, 1541}, + {0x1e69, 16, 16, 1542}, + {0x1fbe, 0, 1, 1542}, + {0x0, 0, 16, 1543}, + {0x0, 3, 4, 1559}, + {0x2f96c, 16, 16, 1560}, + {0x0, 0, 15, 1560}, + {0x0, 10, 11, 1575}, + {0x2f85d, 16, 16, 1576}, + {0x0, 3, 11, 1576}, + {0x2f836, 16, 16, 1584}, + {0x0, 12, 13, 1584}, + {0x2f92f, 16, 16, 1585}, + {0x0, 0, 10, 1585}, + {0x0, 0, 1, 1595}, + {0x0, 0, 1, 1596}, + {0x0, 3, 4, 1597}, + {0x0, 0, 5, 1598}, + {0x0, 2, 3, 1603}, + {0x1f5f, 16, 16, 1604}, + {0x0, 2, 3, 1604}, + {0x0, 15, 16, 1605}, + {0x2f9d8, 16, 16, 1606}, + {0x0, 1, 16, 1606}, + {0x0, 0, 12, 1621}, + {0xf932, 16, 16, 1633}, + {0x0, 0, 16, 1633}, + {0x0, 11, 12, 1649}, + {0xfa6a, 16, 16, 1650}, + {0x0, 2, 16, 1650}, + {0x0, 2, 4, 1664}, + {0xfa68, 16, 16, 1666}, + {0x0, 2, 16, 1666}, + {0x212b, 0, 1, 1680}, + {0x0, 0, 1, 1681}, + {0x0, 3, 4, 1682}, + {0x0, 0, 1, 1683}, + {0x0, 1, 2, 1684}, + {0x1fa, 16, 16, 1685}, + {0x0, 1, 16, 1685}, + {0x0, 0, 1, 1700}, + {0x0, 3, 4, 1701}, + {0x0, 0, 1, 1702}, + {0x0, 9, 10, 1703}, + {0x0, 9, 10, 1704}, + {0x30c9, 16, 16, 1705}, + {0xf9ea, 16, 16, 1705}, + {0x0, 2, 16, 1705}, + {0x0, 0, 1, 1719}, + {0x0, 0, 1, 1720}, + {0x0, 3, 4, 1721}, + {0x0, 0, 1, 1722}, + {0x0, 1, 2, 1723}, + {0x1e09, 16, 16, 1724}, + {0x0, 1, 11, 1724}, + {0x0, 2, 3, 1734}, + {0x2f8e1, 16, 16, 1735}, + {0x0, 0, 14, 1735}, + {0x0, 0, 1, 1749}, + {0x0, 3, 4, 1750}, + {0x0, 0, 1, 1751}, + {0x0, 9, 10, 1752}, + {0x0, 9, 10, 1753}, + {0x30f9, 16, 16, 1754}, + {0x0, 13, 14, 1754}, + {0xf986, 16, 16, 1755}, + {0x0, 0, 1, 1755}, + {0x0, 0, 1, 1756}, + {0x0, 3, 4, 1757}, + {0x0, 0, 4, 1758}, + {0x0, 7, 8, 1762}, + {0x1e03, 16, 16, 1763}, + {0x0, 0, 1, 1763}, + {0x0, 0, 1, 1764}, + {0x0, 3, 4, 1765}, + {0x0, 0, 1, 1766}, + {0x0, 1, 5, 1767}, + {0x1fd, 16, 16, 1771}, + {0x0, 0, 1, 1771}, + {0x0, 0, 1, 1772}, + {0x0, 3, 4, 1773}, + {0x0, 3, 4, 1774}, + {0x0, 8, 9, 1775}, + {0x2281, 16, 16, 1776}, + {0x1e3, 16, 16, 1776}, + {0x0, 2, 12, 1776}, + {0x0, 0, 1, 1786}, + {0x0, 0, 1, 1787}, + {0x0, 3, 4, 1788}, + {0x0, 3, 4, 1789}, + {0x0, 8, 9, 1790}, + {0x22af, 16, 16, 1791}, + {0xf96b, 16, 16, 1791}, + {0x0, 2, 16, 1791}, + {0x0, 3, 10, 1805}, + {0x0, 2, 3, 1812}, + {0x2f937, 16, 16, 1813}, + {0x0, 2, 12, 1813}, + {0x0, 2, 3, 1823}, + {0xf98d, 16, 16, 1824}, + {0x0, 6, 16, 1824}, + {0x0, 0, 1, 1834}, + {0x0, 3, 4, 1835}, + {0x0, 0, 1, 1836}, + {0x0, 9, 10, 1837}, + {0x0, 9, 10, 1838}, + {0x30b0, 16, 16, 1839}, + {0x0, 0, 1, 1839}, + {0x0, 0, 1, 1840}, + {0x0, 3, 4, 1841}, + {0x0, 0, 3, 1842}, + {0x0, 1, 8, 1845}, + {0x1e3e, 16, 16, 1852}, + {0x1e40, 16, 16, 1852}, + {0x0, 8, 9, 1852}, + {0xfa65, 16, 16, 1853}, + {0x0, 6, 16, 1853}, + {0x0, 10, 11, 1863}, + {0xf93a, 16, 16, 1864}, + {0x0, 0, 16, 1864}, + {0x0, 0, 1, 1880}, + {0x0, 0, 1, 1881}, + {0x0, 3, 4, 1882}, + {0x0, 4, 5, 1883}, + {0x0, 5, 6, 1884}, + {0x1faa, 16, 16, 1885}, + {0x0, 0, 1, 1885}, + {0x0, 2, 4, 1886}, + {0x2001, 16, 16, 1888}, + {0x2000, 16, 16, 1888}, + {0x0, 0, 16, 1888}, + {0x0, 11, 12, 1904}, + {0x0, 8, 9, 1905}, + {0x2f897, 16, 16, 1906}, + {0x0, 2, 15, 1906}, + {0x0, 4, 5, 1919}, + {0x2f934, 16, 16, 1920}, + {0x0, 1, 13, 1920}, + {0x0, 11, 12, 1932}, + {0x2f848, 16, 16, 1933}, + {0x0, 0, 16, 1933}, + {0x0, 0, 1, 1949}, + {0x0, 0, 1, 1950}, + {0x0, 3, 4, 1951}, + {0x0, 0, 5, 1952}, + {0x0, 2, 6, 1957}, + {0x1f07, 16, 16, 1961}, + {0x1f81, 16, 16, 1961}, + {0x0, 0, 1, 1961}, + {0x0, 0, 1, 1962}, + {0x0, 3, 4, 1963}, + {0x0, 0, 4, 1964}, + {0x0, 7, 13, 1968}, + {0x1e0b, 16, 16, 1974}, + {0x0, 0, 1, 1974}, + {0x0, 0, 1, 1975}, + {0x0, 3, 4, 1976}, + {0x0, 4, 5, 1977}, + {0x0, 5, 6, 1978}, + {0x1f9b, 16, 16, 1979}, + {0x0, 0, 1, 1979}, + {0x0, 0, 1, 1980}, + {0x0, 3, 4, 1981}, + {0x0, 0, 3, 1982}, + {0x0, 3, 4, 1985}, + {0x1e43, 16, 16, 1986}, + {0x0, 8, 9, 1986}, + {0x0, 0, 1, 1987}, + {0x0, 0, 1, 1988}, + {0x0, 3, 4, 1989}, + {0x0, 0, 5, 1990}, + {0x0, 0, 2, 1995}, + {0x1fed, 16, 16, 1997}, + {0x385, 16, 16, 1997}, + {0x0, 2, 4, 1997}, + {0x0, 0, 1, 1999}, + {0x0, 0, 1, 2000}, + {0x0, 3, 4, 2001}, + {0x0, 0, 1, 2002}, + {0x0, 0, 2, 2003}, + {0x1e17, 16, 16, 2005}, + {0x0, 1, 15, 2005}, + {0x0, 14, 15, 2019}, + {0x2f95f, 16, 16, 2020}, + {0x0, 0, 1, 2020}, + {0x0, 0, 1, 2021}, + {0x0, 3, 4, 2022}, + {0x0, 0, 5, 2023}, + {0x0, 0, 2, 2028}, + {0x1f53, 16, 16, 2030}, + {0x1f55, 16, 16, 2030}, + {0x0, 0, 1, 2030}, + {0x0, 0, 1, 2031}, + {0x0, 3, 4, 2032}, + {0x0, 3, 4, 2033}, + {0x0, 8, 9, 2034}, + {0x22ad, 16, 16, 2035}, + {0x0, 2, 12, 2035}, + {0x0, 0, 1, 2045}, + {0x0, 3, 4, 2046}, + {0x0, 0, 1, 2047}, + {0x0, 9, 10, 2048}, + {0x0, 9, 11, 2049}, + {0x3079, 16, 16, 2051}, + {0x0, 0, 1, 2051}, + {0x0, 3, 4, 2052}, + {0x0, 0, 1, 2053}, + {0x0, 9, 10, 2054}, + {0x0, 9, 11, 2055}, + {0x307d, 16, 16, 2057}, + {0x0, 3, 8, 2057}, + {0x1e5a, 16, 16, 2062}, + {0x156, 16, 16, 2062}, + {0x0, 12, 13, 2062}, + {0xf982, 16, 16, 2063}, + {0x0, 10, 12, 2063}, + {0x0, 0, 1, 2065}, + {0x0, 0, 1, 2066}, + {0x0, 3, 4, 2067}, + {0x0, 0, 1, 2068}, + {0x0, 4, 5, 2069}, + {0x1ec, 16, 16, 2070}, + {0x0, 4, 14, 2070}, + {0x0, 3, 4, 2080}, + {0xfa64, 16, 16, 2081}, + {0x0, 0, 1, 2081}, + {0x0, 0, 1, 2082}, + {0x0, 3, 4, 2083}, + {0x0, 4, 5, 2084}, + {0x0, 5, 6, 2085}, + {0x1f8e, 16, 16, 2086}, + {0x0, 7, 8, 2086}, + {0xf99c, 16, 16, 2087}, + {0x0, 0, 10, 2087}, + {0x0, 0, 1, 2097}, + {0x0, 0, 1, 2098}, + {0x0, 3, 4, 2099}, + {0x0, 0, 5, 2100}, + {0x0, 0, 2, 2105}, + {0x1f3d, 16, 16, 2107}, + {0x0, 0, 1, 2107}, + {0x0, 3, 4, 2108}, + {0x0, 0, 5, 2109}, + {0x0, 2, 3, 2114}, + {0x1fd6, 16, 16, 2115}, + {0x0, 6, 15, 2115}, + {0x0, 0, 1, 2124}, + {0x0, 0, 1, 2125}, + {0x0, 3, 4, 2126}, + {0x0, 0, 5, 2127}, + {0x0, 0, 2, 2132}, + {0x1fde, 16, 16, 2134}, + {0x1fdd, 16, 16, 2134}, + {0x0, 0, 1, 2134}, + {0x0, 0, 1, 2135}, + {0x0, 3, 4, 2136}, + {0x0, 4, 5, 2137}, + {0x0, 5, 6, 2138}, + {0x1f95, 16, 16, 2139}, + {0x0, 4, 8, 2139}, + {0xf90b, 16, 16, 2143}, + {0x2f846, 16, 16, 2143}, + {0x0, 3, 6, 2143}, + {0x0, 0, 1, 2146}, + {0x0, 0, 1, 2147}, + {0x0, 3, 4, 2148}, + {0x0, 3, 4, 2149}, + {0x0, 8, 9, 2150}, + {0x2224, 16, 16, 2151}, + {0x0, 0, 16, 2151}, + {0x0, 12, 13, 2167}, + {0xfa08, 16, 16, 2168}, + {0x0, 5, 6, 2168}, + {0x2f905, 16, 16, 2169}, + {0x0, 10, 11, 2169}, + {0xf995, 16, 16, 2170}, + {0x0, 0, 1, 2170}, + {0x0, 3, 4, 2171}, + {0x0, 0, 1, 2172}, + {0x0, 9, 10, 2173}, + {0x0, 9, 10, 2174}, + {0x30c7, 16, 16, 2175}, + {0x0, 0, 1, 2175}, + {0x0, 0, 1, 2176}, + {0x0, 3, 4, 2177}, + {0x0, 0, 5, 2178}, + {0x0, 0, 2, 2183}, + {0x1f22, 16, 16, 2185}, + {0x0, 5, 11, 2185}, + {0xf97f, 16, 16, 2191}, + {0x0, 9, 10, 2191}, + {0x2fa00, 16, 16, 2192}, + {0x0, 7, 16, 2192}, + {0x0, 2, 11, 2201}, + {0xf9e6, 16, 16, 2210}, + {0x0, 1, 16, 2210}, + {0x0, 10, 11, 2225}, + {0xfa17, 16, 16, 2226}, + {0xfa5a, 16, 16, 2226}, + {0x0, 10, 12, 2226}, + {0x0, 0, 1, 2228}, + {0x0, 0, 1, 2229}, + {0x0, 3, 4, 2230}, + {0x0, 0, 1, 2231}, + {0x0, 4, 5, 2232}, + {0x1e5d, 16, 16, 2233}, + {0x0, 7, 10, 2233}, + {0x2f9b5, 16, 16, 2236}, + {0x2f9b6, 16, 16, 2236}, + {0x0, 0, 12, 2236}, + {0x0, 0, 16, 2248}, + {0xf997, 16, 16, 2264}, + {0x0, 1, 12, 2264}, + {0x0, 11, 12, 2275}, + {0x0, 6, 7, 2276}, + {0x2fa01, 16, 16, 2277}, + {0x0, 10, 16, 2277}, + {0x0, 8, 15, 2283}, + {0xfa22, 16, 16, 2290}, + {0x0, 0, 10, 2290}, + {0x0, 0, 1, 2300}, + {0x0, 0, 1, 2301}, + {0x0, 3, 4, 2302}, + {0x0, 0, 1, 2303}, + {0x0, 0, 2, 2304}, + {0x1f4a, 16, 16, 2306}, + {0x0, 4, 13, 2306}, + {0x0, 6, 7, 2315}, + {0x0, 0, 1, 2316}, + {0x0, 0, 1, 2317}, + {0x0, 12, 13, 2318}, + {0x0, 5, 6, 2319}, + {0x0, 6, 7, 2320}, + {0xc48, 16, 16, 2321}, + {0x2f976, 16, 16, 2321}, + {0x0, 15, 16, 2321}, + {0xf97c, 16, 16, 2322}, + {0x0, 2, 13, 2322}, + {0x0, 4, 5, 2333}, + {0xf930, 16, 16, 2334}, + {0x212a, 0, 1, 2334}, + {0x0, 0, 1, 2335}, + {0x0, 3, 4, 2336}, + {0x0, 0, 4, 2337}, + {0x0, 1, 2, 2341}, + {0x1e34, 16, 16, 2342}, + {0x0, 2, 11, 2342}, + {0x0, 3, 4, 2351}, + {0x2f97c, 16, 16, 2352}, + {0x0, 2, 3, 2352}, + {0x2f85f, 16, 16, 2353}, + {0x0, 0, 1, 2353}, + {0x0, 0, 1, 2354}, + {0x0, 3, 4, 2355}, + {0x0, 0, 1, 2356}, + {0x0, 6, 9, 2357}, + {0x4d1, 16, 16, 2360}, + {0x0, 1, 2, 2360}, + {0xfa55, 16, 16, 2361}, + {0x0, 5, 14, 2361}, + {0x0, 15, 16, 2370}, + {0x0, 10, 11, 2371}, + {0x2f9ed, 16, 16, 2372}, + {0x2f97d, 16, 16, 2372}, + {0x0, 9, 10, 2372}, + {0xf90e, 16, 16, 2373}, + {0x0, 0, 1, 2373}, + {0x0, 0, 1, 2374}, + {0x0, 3, 4, 2375}, + {0x0, 0, 5, 2376}, + {0x0, 0, 2, 2381}, + {0x1f0a, 16, 16, 2383}, + {0x1f0c, 16, 16, 2383}, + {0x0, 0, 1, 2383}, + {0x0, 0, 1, 2384}, + {0x0, 3, 4, 2385}, + {0x0, 0, 5, 2386}, + {0x0, 2, 6, 2391}, + {0x1f67, 16, 16, 2395}, + {0x0, 0, 1, 2395}, + {0x0, 0, 1, 2396}, + {0x0, 3, 4, 2397}, + {0x0, 0, 3, 2398}, + {0x0, 7, 8, 2401}, + {0xe7, 16, 16, 2402}, + {0x1fa1, 16, 16, 2402}, + {0x1eea, 16, 16, 2402}, + {0x0, 5, 11, 2402}, + {0x2f978, 16, 16, 2408}, + {0x0, 2, 3, 2408}, + {0x0, 0, 1, 2409}, + {0x0, 0, 1, 2410}, + {0x0, 3, 4, 2411}, + {0x0, 0, 1, 2412}, + {0x0, 1, 9, 2413}, + {0x3d4, 16, 16, 2421}, + {0x0, 4, 14, 2421}, + {0x0, 12, 13, 2431}, + {0x2f91e, 16, 16, 2432}, + {0x3d3, 16, 16, 2432}, + {0x0, 3, 14, 2432}, + {0x0, 7, 9, 2443}, + {0x2f9e9, 16, 16, 2445}, + {0x0, 0, 1, 2445}, + {0x0, 0, 1, 2446}, + {0x0, 3, 4, 2447}, + {0x0, 0, 3, 2448}, + {0x0, 0, 10, 2451}, + {0x176, 16, 16, 2461}, + {0xdd, 16, 16, 2461}, + {0x1ef2, 16, 16, 2461}, + {0x1e8e, 16, 16, 2461}, + {0x232, 16, 16, 2461}, + {0x0, 6, 16, 2461}, + {0x0, 0, 1, 2471}, + {0x0, 3, 4, 2472}, + {0x0, 0, 1, 2473}, + {0x0, 9, 10, 2474}, + {0x0, 9, 10, 2475}, + {0x3094, 16, 16, 2476}, + {0x1ef6, 16, 16, 2476}, + {0x178, 16, 16, 2476}, + {0x0, 0, 1, 2476}, + {0x0, 0, 1, 2477}, + {0x0, 3, 4, 2478}, + {0x0, 0, 1, 2479}, + {0x0, 7, 8, 2480}, + {0x1e68, 16, 16, 2481}, + {0x2f9e8, 16, 16, 2481}, + {0x0, 13, 14, 2481}, + {0x2f999, 16, 16, 2482}, + {0x0, 0, 1, 2482}, + {0x0, 0, 1, 2483}, + {0x0, 3, 4, 2484}, + {0x0, 0, 3, 2485}, + {0x0, 0, 9, 2488}, + {0x1e82, 16, 16, 2497}, + {0x0, 4, 16, 2497}, + {0x0, 14, 15, 2509}, + {0x2f94e, 16, 16, 2510}, + {0x174, 16, 16, 2510}, + {0x1e86, 16, 16, 2510}, + {0x0, 0, 1, 2510}, + {0x0, 0, 1, 2511}, + {0x0, 3, 4, 2512}, + {0x0, 0, 1, 2513}, + {0x0, 4, 5, 2514}, + {0x1de, 16, 16, 2515}, + {0xf9af, 16, 16, 2515}, + {0x0, 2, 15, 2515}, + {0x0, 3, 4, 2528}, + {0x2f89b, 16, 16, 2529}, + {0x0, 3, 5, 2529}, + {0x1f28, 16, 16, 2531}, + {0x1f29, 16, 16, 2531}, + {0x0, 8, 16, 2531}, + {0x0, 10, 11, 2539}, + {0x2f8f9, 16, 16, 2540}, + {0x0, 10, 11, 2540}, + {0x2f89c, 16, 16, 2541}, + {0x0, 1, 2, 2541}, + {0x1e07, 16, 16, 2542}, + {0x0, 0, 1, 2542}, + {0x0, 3, 4, 2543}, + {0x0, 0, 1, 2544}, + {0x0, 9, 10, 2545}, + {0x0, 9, 11, 2546}, + {0x30d0, 16, 16, 2548}, + {0x0, 11, 12, 2548}, + {0x2f9d6, 16, 16, 2549}, + {0x0, 0, 13, 2549}, + {0x0, 0, 15, 2562}, + {0xfa3c, 16, 16, 2577}, + {0x0, 7, 8, 2577}, + {0x2f92e, 16, 16, 2578}, + {0x0, 0, 1, 2578}, + {0x0, 3, 4, 2579}, + {0x0, 0, 1, 2580}, + {0x0, 9, 10, 2581}, + {0x0, 9, 10, 2582}, + {0x30ae, 16, 16, 2583}, + {0x0, 1, 16, 2583}, + {0x0, 0, 1, 2598}, + {0x0, 3, 4, 2599}, + {0x0, 0, 1, 2600}, + {0x0, 9, 10, 2601}, + {0x0, 9, 10, 2602}, + {0x3058, 16, 16, 2603}, + {0x0, 0, 1, 2603}, + {0x0, 0, 1, 2604}, + {0x0, 3, 4, 2605}, + {0x0, 0, 4, 2606}, + {0x0, 0, 16, 2610}, + {0xcb, 16, 16, 2626}, + {0x1eba, 16, 16, 2626}, + {0xca, 16, 16, 2626}, + {0x1ebc, 16, 16, 2626}, + {0xc8, 16, 16, 2626}, + {0xc9, 16, 16, 2626}, + {0x114, 16, 16, 2626}, + {0x116, 16, 16, 2626}, + {0x112, 16, 16, 2626}, + {0xf94b, 16, 16, 2626}, + {0x2f877, 16, 16, 2626}, + {0xf9df, 16, 16, 2626}, + {0xfa3b, 16, 16, 2626}, + {0x0, 0, 1, 2626}, + {0x0, 0, 1, 2627}, + {0x0, 3, 4, 2628}, + {0x0, 0, 1, 2629}, + {0x0, 6, 7, 2630}, + {0x1e1c, 16, 16, 2631}, + {0x0, 4, 16, 2631}, + {0x0, 4, 5, 2643}, + {0x2f93d, 16, 16, 2644}, + {0x0, 0, 1, 2644}, + {0x0, 0, 1, 2645}, + {0x0, 3, 4, 2646}, + {0x0, 0, 1, 2647}, + {0x0, 1, 2, 2648}, + {0x1fb, 16, 16, 2649}, + {0x0, 6, 7, 2649}, + {0x0, 13, 14, 2650}, + {0x2f8e3, 16, 16, 2651}, + {0x0, 2, 8, 2651}, + {0x2f85b, 16, 16, 2657}, + {0x2f85a, 16, 16, 2657}, + {0x307c, 16, 16, 2657}, + {0x0, 0, 1, 2657}, + {0x0, 0, 1, 2658}, + {0x0, 3, 4, 2659}, + {0x0, 0, 5, 2660}, + {0x0, 2, 6, 2665}, + {0x1f06, 16, 16, 2669}, + {0x11a, 16, 16, 2669}, + {0x204, 16, 16, 2669}, + {0x1f80, 16, 16, 2669}, + {0x307a, 16, 16, 2669}, + {0x0, 0, 1, 2669}, + {0x0, 8, 9, 2670}, + {0x2f923, 16, 16, 2671}, + {0x0, 3, 4, 2671}, + {0x2f944, 16, 16, 2672}, + {0x0, 10, 11, 2672}, + {0xf94d, 16, 16, 2673}, + {0x0, 3, 4, 2673}, + {0x1ef0, 16, 16, 2674}, + {0x0, 11, 12, 2674}, + {0xf9d4, 16, 16, 2675}, + {0x0, 0, 16, 2675}, + {0x113, 16, 16, 2691}, + {0x115, 16, 16, 2691}, + {0x117, 16, 16, 2691}, + {0xe8, 16, 16, 2691}, + {0xe9, 16, 16, 2691}, + {0xea, 16, 16, 2691}, + {0x1ebd, 16, 16, 2691}, + {0x0, 0, 1, 2691}, + {0x0, 0, 1, 2692}, + {0x0, 3, 4, 2693}, + {0x0, 0, 1, 2694}, + {0x0, 1, 2, 2695}, + {0x1e08, 16, 16, 2696}, + {0xeb, 16, 16, 2696}, + {0x1ebb, 16, 16, 2696}, + {0x0, 12, 14, 2696}, + {0x0, 0, 1, 2698}, + {0x0, 0, 1, 2699}, + {0x0, 3, 4, 2700}, + {0x0, 0, 1, 2701}, + {0x0, 0, 2, 2702}, + {0x1e52, 16, 16, 2704}, + {0x0, 9, 14, 2704}, + {0x0, 0, 5, 2709}, + {0x0, 0, 1, 2714}, + {0x0, 0, 1, 2715}, + {0x0, 3, 4, 2716}, + {0x0, 3, 4, 2717}, + {0x0, 8, 9, 2718}, + {0x21cf, 16, 16, 2719}, + {0x0, 0, 1, 2719}, + {0x0, 0, 1, 2720}, + {0x0, 3, 4, 2721}, + {0x0, 0, 1, 2722}, + {0x0, 2, 3, 2723}, + {0x134, 16, 16, 2724}, + {0x0, 0, 1, 2724}, + {0x0, 0, 1, 2725}, + {0x0, 3, 4, 2726}, + {0x0, 0, 5, 2727}, + {0x0, 0, 2, 2732}, + {0x1f54, 16, 16, 2734}, + {0x1f52, 16, 16, 2734}, + {0x0, 1, 2, 2734}, + {0x1e5e, 16, 16, 2735}, + {0x0, 8, 9, 2735}, + {0xf99f, 16, 16, 2736}, + {0x0, 1, 5, 2736}, + {0x0, 14, 15, 2740}, + {0x2f8f2, 16, 16, 2741}, + {0x205, 16, 16, 2741}, + {0x11b, 16, 16, 2741}, + {0x2f88b, 16, 16, 2741}, + {0x2f88c, 16, 16, 2741}, + {0x0, 3, 8, 2741}, + {0x2f81e, 16, 16, 2746}, + {0x0, 0, 1, 2746}, + {0x0, 0, 1, 2747}, + {0x0, 3, 4, 2748}, + {0x0, 0, 5, 2749}, + {0x0, 3, 5, 2754}, + {0x1f01, 16, 16, 2756}, + {0xfa00, 16, 16, 2756}, + {0x0, 3, 16, 2756}, + {0x2f830, 16, 16, 2769}, + {0x0, 2, 13, 2769}, + {0x0, 0, 4, 2780}, + {0x0, 0, 1, 2784}, + {0x0, 0, 1, 2785}, + {0x0, 9, 10, 2786}, + {0x0, 3, 4, 2787}, + {0x0, 12, 13, 2788}, + {0x931, 16, 16, 2789}, + {0x2f833, 16, 16, 2789}, + {0x0, 0, 1, 2789}, + {0x0, 0, 1, 2790}, + {0x0, 3, 4, 2791}, + {0x0, 0, 1, 2792}, + {0x0, 8, 9, 2793}, + {0x1e7a, 16, 16, 2794}, + {0x0, 14, 15, 2794}, + {0xf9d0, 16, 16, 2795}, + {0x0, 9, 14, 2795}, + {0x2f847, 16, 16, 2800}, + {0x0, 13, 14, 2800}, + {0x0, 2, 3, 2801}, + {0x2f9b1, 16, 16, 2802}, + {0x0, 4, 13, 2802}, + {0x0, 7, 8, 2811}, + {0x0, 0, 1, 2812}, + {0x0, 0, 1, 2813}, + {0x0, 11, 12, 2814}, + {0x0, 3, 6, 2815}, + {0x0, 14, 15, 2818}, + {0xb4b, 16, 16, 2819}, + {0x0, 6, 8, 2819}, + {0x0, 0, 1, 2821}, + {0x0, 0, 1, 2822}, + {0x0, 3, 4, 2823}, + {0x0, 0, 1, 2824}, + {0x0, 4, 5, 2825}, + {0x1e39, 16, 16, 2826}, + {0x0, 0, 1, 2826}, + {0x0, 0, 1, 2827}, + {0x0, 3, 4, 2828}, + {0x0, 0, 1, 2829}, + {0x0, 2, 13, 2830}, + {0x135, 16, 16, 2841}, + {0x0, 13, 14, 2841}, + {0x2f9d0, 16, 16, 2842}, + {0x0, 4, 14, 2842}, + {0x0, 0, 15, 2852}, + {0x0, 4, 7, 2867}, + {0x2f87d, 16, 16, 2870}, + {0x2f87b, 16, 16, 2870}, + {0x0, 7, 8, 2870}, + {0x0, 0, 1, 2871}, + {0x0, 0, 1, 2872}, + {0x0, 9, 10, 2873}, + {0x0, 11, 14, 2874}, + {0x0, 14, 15, 2877}, + {0x9cb, 16, 16, 2878}, + {0x0, 1, 6, 2878}, + {0x0, 0, 1, 2883}, + {0x0, 0, 1, 2884}, + {0x0, 3, 4, 2885}, + {0x0, 3, 4, 2886}, + {0x0, 8, 9, 2887}, + {0x2270, 16, 16, 2888}, + {0x0, 5, 9, 2888}, + {0xf959, 16, 16, 2892}, + {0xfa36, 16, 16, 2892}, + {0x0, 0, 1, 2892}, + {0x0, 0, 1, 2893}, + {0x0, 3, 4, 2894}, + {0x0, 3, 4, 2895}, + {0x0, 8, 9, 2896}, + {0x2271, 16, 16, 2897}, + {0x0, 9, 10, 2897}, + {0xfa5e, 16, 16, 2898}, + {0x0, 0, 1, 2898}, + {0x0, 0, 1, 2899}, + {0x0, 3, 4, 2900}, + {0x0, 0, 1, 2901}, + {0x0, 1, 2, 2902}, + {0x453, 16, 16, 2903}, + {0xf9d3, 16, 16, 2903}, + {0x0, 12, 14, 2903}, + {0x0, 0, 1, 2905}, + {0x0, 0, 1, 2906}, + {0x0, 3, 4, 2907}, + {0x0, 0, 1, 2908}, + {0x0, 2, 3, 2909}, + {0x1ed8, 16, 16, 2910}, + {0x0, 2, 16, 2910}, + {0xf9e7, 16, 16, 2924}, + {0xf91c, 16, 16, 2924}, + {0x0, 1, 16, 2924}, + {0x0, 4, 9, 2939}, + {0xf901, 16, 16, 2944}, + {0x2f82f, 16, 16, 2944}, + {0x0, 15, 16, 2944}, + {0x2f883, 16, 16, 2945}, + {0x0, 0, 5, 2945}, + {0x0, 0, 1, 2950}, + {0x0, 0, 1, 2951}, + {0x0, 3, 4, 2952}, + {0x0, 3, 4, 2953}, + {0x0, 8, 9, 2954}, + {0x21ae, 16, 16, 2955}, + {0x0, 11, 12, 2955}, + {0x0, 12, 13, 2956}, + {0x2f8fb, 16, 16, 2957}, + {0x0, 0, 1, 2957}, + {0x0, 0, 1, 2958}, + {0x0, 3, 4, 2959}, + {0x0, 0, 5, 2960}, + {0x0, 3, 5, 2965}, + {0x1f21, 16, 16, 2967}, + {0x1f0, 16, 16, 2967}, + {0x1f20, 16, 16, 2967}, + {0x0, 0, 11, 2967}, + {0x0, 0, 1, 2978}, + {0x2f967, 16, 16, 2979}, + {0x0, 3, 9, 2979}, + {0x12f, 16, 16, 2985}, + {0x0, 7, 15, 2985}, + {0x2f9c7, 16, 16, 2993}, + {0x1ecb, 16, 16, 2993}, + {0x0, 2, 12, 2993}, + {0x0, 0, 1, 3003}, + {0x0, 3, 4, 3004}, + {0x0, 0, 1, 3005}, + {0x0, 9, 10, 3006}, + {0x0, 9, 11, 3007}, + {0x30dc, 16, 16, 3009}, + {0x0, 6, 11, 3009}, + {0x0, 0, 1, 3014}, + {0x0, 0, 1, 3015}, + {0x0, 12, 13, 3016}, + {0x0, 13, 14, 3017}, + {0x0, 5, 6, 3018}, + {0xccb, 16, 16, 3019}, + {0x0, 4, 9, 3019}, + {0x2f9e7, 16, 16, 3024}, + {0x0, 3, 8, 3024}, + {0x1e32, 16, 16, 3029}, + {0x0, 0, 1, 3029}, + {0x0, 0, 1, 3030}, + {0x0, 3, 4, 3031}, + {0x0, 0, 5, 3032}, + {0x0, 2, 3, 3037}, + {0x1f36, 16, 16, 3038}, + {0x0, 3, 14, 3038}, + {0x0, 0, 1, 3049}, + {0x0, 0, 1, 3050}, + {0x0, 3, 4, 3051}, + {0x0, 0, 1, 3052}, + {0x0, 4, 12, 3053}, + {0x45e, 16, 16, 3061}, + {0x136, 16, 16, 3061}, + {0x0, 6, 8, 3061}, + {0x0, 0, 1, 3063}, + {0x0, 0, 1, 3064}, + {0x0, 11, 12, 3065}, + {0x0, 11, 14, 3066}, + {0x0, 7, 8, 3069}, + {0xbcc, 16, 16, 3070}, + {0x0, 3, 4, 3070}, + {0xf981, 16, 16, 3071}, + {0x0, 0, 1, 3071}, + {0x0, 0, 1, 3072}, + {0x0, 3, 4, 3073}, + {0x0, 0, 4, 3074}, + {0x0, 0, 16, 3078}, + {0x1ec8, 16, 16, 3094}, + {0x0, 3, 4, 3094}, + {0x343, 16, 16, 3095}, + {0x12c, 16, 16, 3095}, + {0x0, 3, 16, 3095}, + {0x2f870, 16, 16, 3108}, + {0xf9b1, 16, 16, 3108}, + {0x0, 0, 15, 3108}, + {0x2f97f, 16, 16, 3123}, + {0x2f8cc, 16, 16, 3123}, + {0x0, 0, 1, 3123}, + {0x0, 0, 1, 3124}, + {0x0, 3, 4, 3125}, + {0x0, 0, 1, 3126}, + {0x0, 4, 5, 3127}, + {0x1ed, 16, 16, 3128}, + {0x30dd, 16, 16, 3128}, + {0x0, 0, 7, 3128}, + {0x0, 11, 12, 3135}, + {0x2f984, 16, 16, 3136}, + {0x0, 1, 12, 3136}, + {0x0, 13, 14, 3147}, + {0x0, 4, 5, 3148}, + {0x2f8a4, 16, 16, 3149}, + {0x2f9c6, 16, 16, 3149}, + {0x2f872, 16, 16, 3149}, + {0x0, 2, 16, 3149}, + {0x0, 12, 13, 3163}, + {0xf9c3, 16, 16, 3164}, + {0xf945, 16, 16, 3164}, + {0x0, 5, 6, 3164}, + {0xf90f, 16, 16, 3165}, + {0x0, 1, 16, 3165}, + {0x0, 13, 14, 3180}, + {0x2f884, 16, 16, 3181}, + {0x0, 0, 1, 3181}, + {0x0, 0, 1, 3182}, + {0x0, 3, 4, 3183}, + {0x0, 0, 1, 3184}, + {0x0, 8, 9, 3185}, + {0x4f9, 16, 16, 3186}, + {0x0, 5, 6, 3186}, + {0x2f921, 16, 16, 3187}, + {0x0, 8, 10, 3187}, + {0xfa4d, 16, 16, 3189}, + {0xfa4e, 16, 16, 3189}, + {0x0, 1, 16, 3189}, + {0x0, 11, 12, 3204}, + {0x2fa15, 16, 16, 3205}, + {0x0, 7, 16, 3205}, + {0xf988, 16, 16, 3214}, + {0x0, 11, 12, 3214}, + {0x2f863, 16, 16, 3215}, + {0x0, 0, 5, 3215}, + {0x0, 7, 8, 3220}, + {0xf950, 16, 16, 3221}, + {0x0, 0, 16, 3221}, + {0x0, 9, 16, 3237}, + {0xf95b, 16, 16, 3244}, + {0x0, 0, 1, 3244}, + {0x0, 0, 1, 3245}, + {0x0, 3, 4, 3246}, + {0x0, 0, 1, 3247}, + {0x0, 7, 9, 3248}, + {0x1e8a, 16, 16, 3250}, + {0x0, 0, 1, 3250}, + {0x0, 0, 1, 3251}, + {0x0, 3, 4, 3252}, + {0x0, 0, 5, 3253}, + {0x0, 0, 2, 3258}, + {0x3b0, 16, 16, 3260}, + {0x1fe2, 16, 16, 3260}, + {0x0, 1, 15, 3260}, + {0x0, 2, 3, 3274}, + {0x2f8e8, 16, 16, 3275}, + {0xf9f3, 16, 16, 3275}, + {0x1e8c, 16, 16, 3275}, + {0x0, 0, 1, 3275}, + {0x0, 3, 4, 3276}, + {0x0, 0, 1, 3277}, + {0x0, 9, 10, 3278}, + {0x0, 9, 10, 3279}, + {0x30bc, 16, 16, 3280}, + {0x0, 0, 1, 3280}, + {0x0, 0, 1, 3281}, + {0x0, 3, 4, 3282}, + {0x0, 0, 1, 3283}, + {0x0, 4, 5, 3284}, + {0x1e38, 16, 16, 3285}, + {0x0, 9, 10, 3285}, + {0xf966, 16, 16, 3286}, + {0x0, 2, 3, 3286}, + {0x0, 14, 15, 3287}, + {0x2f9e5, 16, 16, 3288}, + {0x0, 1, 2, 3288}, + {0x206, 16, 16, 3289}, + {0x0, 5, 16, 3289}, + {0x1fcb, 16, 16, 3300}, + {0x0, 3, 4, 3300}, + {0x1e42, 16, 16, 3301}, + {0x0, 4, 16, 3301}, + {0x0, 0, 1, 3313}, + {0x2fa0b, 16, 16, 3314}, + {0x0, 13, 14, 3314}, + {0x2f89d, 16, 16, 3315}, + {0x0, 1, 15, 3315}, + {0xfa44, 16, 16, 3329}, + {0x0, 8, 13, 3329}, + {0xfa3a, 16, 16, 3334}, + {0x0, 1, 15, 3334}, + {0x0, 2, 13, 3348}, + {0xf960, 16, 16, 3359}, + {0x0, 1, 2, 3359}, + {0x0, 13, 14, 3360}, + {0x2f94d, 16, 16, 3361}, + {0x0, 13, 14, 3361}, + {0xf923, 16, 16, 3362}, + {0x0, 4, 5, 3362}, + {0xf91d, 16, 16, 3363}, + {0x0, 12, 13, 3363}, + {0x0, 14, 15, 3364}, + {0x2fa10, 16, 16, 3365}, + {0x0, 0, 1, 3365}, + {0x0, 0, 1, 3366}, + {0x0, 3, 4, 3367}, + {0x0, 0, 5, 3368}, + {0x0, 0, 2, 3373}, + {0x1f33, 16, 16, 3375}, + {0x0, 0, 1, 3375}, + {0x0, 0, 1, 3376}, + {0x0, 3, 4, 3377}, + {0x0, 0, 1, 3378}, + {0x0, 7, 8, 3379}, + {0x1e1e, 16, 16, 3380}, + {0x1f35, 16, 16, 3380}, + {0x0, 15, 16, 3380}, + {0xfa41, 16, 16, 3381}, + {0xf9ac, 16, 16, 3381}, + {0x2f858, 16, 16, 3381}, + {0x0, 0, 1, 3381}, + {0x0, 0, 1, 3382}, + {0x0, 3, 4, 3383}, + {0x0, 4, 5, 3384}, + {0x0, 5, 6, 3385}, + {0x1f82, 16, 16, 3386}, + {0x0, 11, 12, 3386}, + {0xf9d8, 16, 16, 3387}, + {0x0, 0, 15, 3387}, + {0x0, 0, 1, 3402}, + {0x0, 0, 1, 3403}, + {0x0, 3, 4, 3404}, + {0x0, 0, 1, 3405}, + {0x0, 0, 9, 3406}, + {0x4d6, 16, 16, 3415}, + {0x0, 5, 6, 3415}, + {0xf983, 16, 16, 3416}, + {0x400, 16, 16, 3416}, + {0x0, 0, 1, 3416}, + {0x0, 0, 1, 3417}, + {0x0, 3, 4, 3418}, + {0x0, 0, 5, 3419}, + {0x0, 0, 2, 3424}, + {0x1f0d, 16, 16, 3426}, + {0x1f0b, 16, 16, 3426}, + {0x401, 16, 16, 3426}, + {0x0, 10, 14, 3426}, + {0x2f8c5, 16, 16, 3430}, + {0xf991, 16, 16, 3430}, + {0x0, 1, 2, 3430}, + {0x207, 16, 16, 3431}, + {0x0, 10, 12, 3431}, + {0x0, 0, 1, 3433}, + {0x0, 0, 1, 3434}, + {0x0, 3, 4, 3435}, + {0x0, 0, 1, 3436}, + {0x0, 7, 8, 3437}, + {0x1e64, 16, 16, 3438}, + {0x0, 5, 6, 3438}, + {0x2f9a6, 16, 16, 3439}, + {0x0, 4, 8, 3439}, + {0x387, 16, 16, 3443}, + {0x1ffd, 16, 16, 3443}, + {0x0, 9, 11, 3443}, + {0xf928, 16, 16, 3445}, + {0x0, 0, 1, 3445}, + {0x0, 0, 1, 3446}, + {0x0, 3, 4, 3447}, + {0x0, 0, 3, 3448}, + {0x0, 3, 4, 3451}, + {0x1ee2, 16, 16, 3452}, + {0x0, 4, 16, 3452}, + {0x0, 4, 14, 3464}, + {0xf9d1, 16, 16, 3474}, + {0x0, 1, 14, 3474}, + {0x0, 1, 12, 3487}, + {0x2f9e6, 16, 16, 3498}, + {0x0, 13, 14, 3498}, + {0x2fa0c, 16, 16, 3499}, + {0x0, 0, 1, 3499}, + {0x0, 0, 1, 3500}, + {0x0, 3, 4, 3501}, + {0x0, 0, 1, 3502}, + {0x0, 4, 5, 3503}, + {0x230, 16, 16, 3504}, + {0x0, 0, 1, 3504}, + {0x0, 0, 1, 3505}, + {0x0, 3, 4, 3506}, + {0x0, 4, 5, 3507}, + {0x0, 5, 6, 3508}, + {0x1faf, 16, 16, 3509}, + {0x0, 14, 15, 3509}, + {0xf9a6, 16, 16, 3510}, + {0x0, 13, 14, 3510}, + {0x2f87a, 16, 16, 3511}, + {0x0, 0, 7, 3511}, + {0x3ac, 16, 16, 3518}, + {0x1f70, 16, 16, 3518}, + {0x0, 7, 8, 3518}, + {0x0, 0, 1, 3519}, + {0x0, 0, 1, 3520}, + {0x0, 6, 7, 3521}, + {0x0, 5, 6, 3522}, + {0x0, 3, 6, 3523}, + {0x623, 16, 16, 3526}, + {0x625, 16, 16, 3526}, + {0x1fb1, 16, 16, 3526}, + {0x1fb0, 16, 16, 3526}, + {0xf9a2, 16, 16, 3526}, + {0x0, 10, 11, 3526}, + {0xf9d6, 16, 16, 3527}, + {0x0, 3, 4, 3527}, + {0x2f844, 16, 16, 3528}, + {0x0, 1, 2, 3528}, + {0x1e0f, 16, 16, 3529}, + {0x0, 14, 15, 3529}, + {0xf9c0, 16, 16, 3530}, + {0x0, 6, 7, 3530}, + {0xf9dc, 16, 16, 3531}, + {0x2f810, 16, 16, 3531}, + {0x2f814, 16, 16, 3531}, + {0xf978, 16, 16, 3531}, + {0x2f9e4, 16, 16, 3531}, + {0x0, 0, 16, 3531}, + {0x0, 13, 14, 3547}, + {0xf9ed, 16, 16, 3548}, + {0x0, 0, 1, 3548}, + {0x0, 3, 4, 3549}, + {0x0, 0, 1, 3550}, + {0x0, 9, 10, 3551}, + {0x0, 9, 11, 3552}, + {0x3071, 16, 16, 3554}, + {0x0, 2, 16, 3554}, + {0x0, 1, 12, 3568}, + {0x2f9af, 16, 16, 3579}, + {0x0, 0, 1, 3579}, + {0x0, 0, 1, 3580}, + {0x0, 3, 4, 3581}, + {0x0, 0, 4, 3582}, + {0x0, 3, 14, 3586}, + {0x1e4b, 16, 16, 3597}, + {0x0, 0, 1, 3597}, + {0x0, 0, 1, 3598}, + {0x0, 3, 4, 3599}, + {0x0, 4, 5, 3600}, + {0x0, 5, 6, 3601}, + {0x1f9a, 16, 16, 3602}, + {0x0, 5, 7, 3602}, + {0x2f829, 16, 16, 3604}, + {0x2f82a, 16, 16, 3604}, + {0x0, 3, 16, 3604}, + {0x0, 14, 15, 3617}, + {0xf999, 16, 16, 3618}, + {0x0, 7, 15, 3618}, + {0xf9bc, 16, 16, 3626}, + {0x0, 0, 1, 3626}, + {0x0, 0, 1, 3627}, + {0x0, 3, 4, 3628}, + {0x0, 3, 4, 3629}, + {0x0, 8, 9, 3630}, + {0x21cd, 16, 16, 3631}, + {0x0, 0, 1, 3631}, + {0x0, 0, 1, 3632}, + {0x0, 3, 4, 3633}, + {0x0, 3, 4, 3634}, + {0x0, 8, 9, 3635}, + {0x2262, 16, 16, 3636}, + {0x0, 0, 2, 3636}, + {0x3ae, 16, 16, 3638}, + {0x1f74, 16, 16, 3638}, + {0x0, 0, 1, 3638}, + {0x0, 0, 1, 3639}, + {0x0, 3, 4, 3640}, + {0x0, 0, 4, 3641}, + {0x0, 1, 2, 3645}, + {0x1e96, 16, 16, 3646}, + {0x0, 0, 1, 3646}, + {0x0, 3, 4, 3647}, + {0x0, 0, 1, 3648}, + {0x0, 9, 10, 3649}, + {0x0, 9, 10, 3650}, + {0x30b8, 16, 16, 3651}, + {0x0, 2, 7, 3651}, + {0xf97d, 16, 16, 3656}, + {0xf941, 16, 16, 3656}, + {0x1e47, 16, 16, 3656}, + {0x146, 16, 16, 3656}, + {0x0, 0, 1, 3656}, + {0x1e2d, 16, 16, 3657}, + {0x2f9b2, 16, 16, 3657}, + {0x0, 0, 1, 3657}, + {0xf9fa, 16, 16, 3658}, + {0x3070, 16, 16, 3658}, + {0x0, 8, 9, 3658}, + {0xf90c, 16, 16, 3659}, + {0x0, 0, 1, 3659}, + {0x0, 0, 1, 3660}, + {0x0, 3, 4, 3661}, + {0x0, 0, 1, 3662}, + {0x0, 0, 10, 3663}, + {0x1ea6, 16, 16, 3673}, + {0x1ea4, 16, 16, 3673}, + {0x1eaa, 16, 16, 3673}, + {0x0, 14, 15, 3673}, + {0xf92c, 16, 16, 3674}, + {0x1ea8, 16, 16, 3674}, + {0x0, 0, 1, 3674}, + {0x0, 3, 4, 3675}, + {0x0, 0, 1, 3676}, + {0x0, 9, 10, 3677}, + {0x0, 9, 10, 3678}, + {0x30c2, 16, 16, 3679}, + {0x0, 0, 9, 3679}, + {0x340, 16, 16, 3688}, + {0x341, 16, 16, 3688}, + {0x0, 0, 15, 3688}, + {0x0, 6, 7, 3703}, + {0x2f94c, 16, 16, 3704}, + {0x0, 3, 4, 3704}, + {0x2f8e9, 16, 16, 3705}, + {0x0, 6, 7, 3705}, + {0xf9fe, 16, 16, 3706}, + {0x0, 8, 9, 3706}, + {0x0, 0, 1, 3707}, + {0x2f965, 16, 16, 3708}, + {0x0, 12, 13, 3708}, + {0x0, 0, 1, 3709}, + {0x0, 0, 1, 3710}, + {0x0, 3, 4, 3711}, + {0x0, 3, 4, 3712}, + {0x0, 8, 9, 3713}, + {0x2241, 16, 16, 3714}, + {0x1f75, 0, 1, 3714}, + {0x0, 0, 1, 3715}, + {0x0, 3, 4, 3716}, + {0x0, 4, 5, 3717}, + {0x0, 5, 6, 3718}, + {0x1fc4, 16, 16, 3719}, + {0x0, 8, 9, 3719}, + {0x0, 1, 2, 3720}, + {0x2f876, 16, 16, 3721}, + {0x0, 0, 15, 3721}, + {0xfa19, 16, 16, 3736}, + {0x0, 15, 16, 3736}, + {0x0, 0, 1, 3737}, + {0x0, 3, 4, 3738}, + {0x0, 0, 1, 3739}, + {0x0, 9, 10, 3740}, + {0x0, 9, 10, 3741}, + {0x30f7, 16, 16, 3742}, + {0x0, 1, 2, 3742}, + {0xf9e8, 16, 16, 3743}, + {0x0, 1, 16, 3743}, + {0x154, 16, 16, 3758}, + {0x0, 7, 8, 3758}, + {0x0, 12, 13, 3759}, + {0x2f95c, 16, 16, 3760}, + {0x0, 7, 8, 3760}, + {0xf933, 16, 16, 3761}, + {0x0, 0, 16, 3761}, + {0x0, 3, 11, 3777}, + {0x2f8df, 16, 16, 3785}, + {0xfa50, 16, 16, 3785}, + {0xfa4f, 16, 16, 3785}, + {0x0, 8, 12, 3785}, + {0x2f920, 16, 16, 3789}, + {0x0, 3, 4, 3789}, + {0x1e88, 16, 16, 3790}, + {0x0, 0, 1, 3790}, + {0x0, 3, 4, 3791}, + {0x0, 0, 1, 3792}, + {0x0, 9, 10, 3793}, + {0x0, 9, 11, 3794}, + {0x3077, 16, 16, 3796}, + {0x0, 10, 11, 3796}, + {0x2f917, 16, 16, 3797}, + {0x0, 14, 16, 3797}, + {0x0, 12, 13, 3799}, + {0x2f868, 16, 16, 3800}, + {0x0, 1, 7, 3800}, + {0x0, 2, 3, 3806}, + {0x2fa0a, 16, 16, 3807}, + {0x0, 0, 1, 3807}, + {0x0, 0, 1, 3808}, + {0x0, 3, 4, 3809}, + {0x0, 4, 5, 3810}, + {0x0, 5, 6, 3811}, + {0x1f86, 16, 16, 3812}, + {0x0, 1, 6, 3812}, + {0xfa59, 16, 16, 3817}, + {0x2f970, 16, 16, 3817}, + {0x0, 9, 10, 3817}, + {0x2f887, 16, 16, 3818}, + {0x0, 0, 9, 3818}, + {0x0, 8, 9, 3827}, + {0xf9fc, 16, 16, 3828}, + {0x0, 7, 8, 3828}, + {0xf9f4, 16, 16, 3829}, + {0x0, 8, 10, 3829}, + {0x0, 0, 1, 3831}, + {0x0, 0, 1, 3832}, + {0x0, 3, 4, 3833}, + {0x0, 0, 1, 3834}, + {0x0, 8, 9, 3835}, + {0x4da, 16, 16, 3836}, + {0x0, 1, 2, 3836}, + {0xf9b9, 16, 16, 3837}, + {0x0, 3, 13, 3837}, + {0x0, 14, 15, 3847}, + {0x2f9cd, 16, 16, 3848}, + {0x0, 6, 7, 3848}, + {0x2f866, 16, 16, 3849}, + {0x0, 8, 10, 3849}, + {0x0, 0, 1, 3851}, + {0x0, 0, 1, 3852}, + {0x0, 3, 4, 3853}, + {0x0, 0, 1, 3854}, + {0x0, 2, 3, 3855}, + {0x1ec7, 16, 16, 3856}, + {0x0, 14, 15, 3856}, + {0x2f867, 16, 16, 3857}, + {0x0, 3, 14, 3857}, + {0x118, 16, 16, 3868}, + {0x0, 0, 1, 3868}, + {0x0, 0, 1, 3869}, + {0x0, 3, 4, 3870}, + {0x0, 0, 5, 3871}, + {0x0, 0, 2, 3876}, + {0x1f2d, 16, 16, 3878}, + {0x228, 16, 16, 3878}, + {0x0, 4, 15, 3878}, + {0x0, 7, 8, 3889}, + {0x2f8fe, 16, 16, 3890}, + {0x1eb8, 16, 16, 3890}, + {0x0, 2, 13, 3890}, + {0x0, 0, 1, 3901}, + {0xf9f8, 16, 16, 3902}, + {0x0, 14, 15, 3902}, + {0xf989, 16, 16, 3903}, + {0x0, 2, 8, 3903}, + {0x2f8f3, 16, 16, 3909}, + {0x0, 6, 7, 3909}, + {0x2f873, 16, 16, 3910}, + {0x0, 0, 16, 3910}, + {0x0, 1, 2, 3926}, + {0x2f8be, 16, 16, 3927}, + {0x0, 12, 15, 3927}, + {0xfa18, 16, 16, 3930}, + {0x0, 8, 9, 3930}, + {0xf969, 16, 16, 3931}, + {0x0, 5, 13, 3931}, + {0x0, 3, 13, 3939}, + {0x2f98a, 16, 16, 3949}, + {0x0, 9, 10, 3949}, + {0xf9cd, 16, 16, 3950}, + {0x1e18, 16, 16, 3950}, + {0x0, 0, 1, 3950}, + {0x0, 0, 1, 3951}, + {0x0, 3, 4, 3952}, + {0x0, 0, 1, 3953}, + {0x0, 4, 5, 3954}, + {0x1e5c, 16, 16, 3955}, + {0xf98c, 16, 16, 3955}, + {0x0, 12, 16, 3955}, + {0x0, 13, 14, 3959}, + {0x2fa0e, 16, 16, 3960}, + {0x0, 9, 14, 3960}, + {0x0, 15, 16, 3965}, + {0x2f81f, 16, 16, 3966}, + {0x0, 2, 13, 3966}, + {0x0, 6, 7, 3977}, + {0x2f952, 16, 16, 3978}, + {0x0, 0, 1, 3978}, + {0x0, 0, 1, 3979}, + {0x0, 3, 4, 3980}, + {0x0, 0, 3, 3981}, + {0x0, 1, 13, 3984}, + {0x160, 16, 16, 3996}, + {0x0, 0, 1, 3996}, + {0x0, 3, 4, 3997}, + {0x0, 0, 1, 3998}, + {0x0, 9, 10, 3999}, + {0x0, 9, 10, 4000}, + {0x30ac, 16, 16, 4001}, + {0x0, 9, 10, 4001}, + {0xf9d5, 16, 16, 4002}, + {0x0, 0, 1, 4002}, + {0x0, 0, 1, 4003}, + {0x0, 3, 4, 4004}, + {0x0, 0, 5, 4005}, + {0x0, 0, 2, 4010}, + {0x3ce, 16, 16, 4012}, + {0x0, 11, 12, 4012}, + {0x2f8f8, 16, 16, 4013}, + {0x0, 0, 1, 4013}, + {0x0, 0, 1, 4014}, + {0x0, 3, 4, 4015}, + {0x0, 0, 1, 4016}, + {0x0, 0, 9, 4017}, + {0x451, 16, 16, 4026}, + {0x450, 16, 16, 4026}, + {0x0, 3, 13, 4026}, + {0x0, 3, 4, 4036}, + {0x2fa03, 16, 16, 4037}, + {0x4d7, 16, 16, 4037}, + {0xf9c9, 16, 16, 4037}, + {0x1e60, 16, 16, 4037}, + {0x15a, 16, 16, 4037}, + {0x15c, 16, 16, 4037}, + {0xf91e, 16, 16, 4037}, + {0x0, 0, 1, 4037}, + {0x0, 0, 1, 4038}, + {0x0, 3, 4, 4039}, + {0x0, 0, 1, 4040}, + {0x0, 0, 10, 4041}, + {0x1eab, 16, 16, 4051}, + {0x1ea7, 16, 16, 4051}, + {0x1ea5, 16, 16, 4051}, + {0x1ea9, 16, 16, 4051}, + {0x0, 2, 14, 4051}, + {0x0, 10, 11, 4063}, + {0xfa16, 16, 16, 4064}, + {0x0, 11, 12, 4064}, + {0xf9a4, 16, 16, 4065}, + {0x0, 0, 1, 4065}, + {0x0, 0, 1, 4066}, + {0x0, 3, 4, 4067}, + {0x0, 3, 4, 4068}, + {0x0, 8, 9, 4069}, + {0x226d, 16, 16, 4070}, + {0x0, 0, 1, 4070}, + {0x0, 0, 1, 4071}, + {0x0, 3, 4, 4072}, + {0x0, 4, 5, 4073}, + {0x0, 5, 6, 4074}, + {0x1f9f, 16, 16, 4075}, + {0x0, 0, 1, 4075}, + {0x0, 0, 1, 4076}, + {0x0, 3, 4, 4077}, + {0x0, 4, 5, 4078}, + {0x0, 5, 6, 4079}, + {0x1fad, 16, 16, 4080}, + {0x0, 0, 1, 4080}, + {0x0, 0, 1, 4081}, + {0x0, 3, 4, 4082}, + {0x0, 0, 3, 4083}, + {0x0, 3, 4, 4086}, + {0x1ee3, 16, 16, 4087}, + {0x0, 13, 14, 4087}, + {0x2f9ae, 16, 16, 4088}, + {0x0, 3, 15, 4088}, + {0x1e2b, 16, 16, 4100}, + {0x0, 12, 13, 4100}, + {0x2f9ea, 16, 16, 4101}, + {0x0, 12, 13, 4101}, + {0x0, 10, 11, 4102}, + {0x2f9ab, 16, 16, 4103}, + {0x0, 0, 1, 4103}, + {0x0, 0, 1, 4104}, + {0x0, 3, 4, 4105}, + {0x0, 0, 5, 4106}, + {0x0, 0, 7, 4111}, + {0x1fba, 16, 16, 4118}, + {0x386, 16, 16, 4118}, + {0x1fb8, 16, 16, 4118}, + {0x0, 7, 8, 4118}, + {0x2f811, 16, 16, 4119}, + {0x1fb9, 16, 16, 4119}, + {0x0, 1, 14, 4119}, + {0x0, 14, 15, 4132}, + {0x2f909, 16, 16, 4133}, + {0x0, 0, 13, 4133}, + {0xf936, 16, 16, 4146}, + {0x0, 6, 7, 4146}, + {0x0, 0, 1, 4147}, + {0x0, 0, 1, 4148}, + {0x0, 3, 4, 4149}, + {0x0, 4, 5, 4150}, + {0x0, 5, 6, 4151}, + {0x1fc7, 16, 16, 4152}, + {0x0, 0, 11, 4152}, + {0x0, 0, 1, 4163}, + {0x0, 0, 1, 4164}, + {0x0, 3, 4, 4165}, + {0x0, 0, 1, 4166}, + {0x0, 7, 9, 4167}, + {0x1e8b, 16, 16, 4169}, + {0x0, 1, 8, 4169}, + {0x1e3f, 16, 16, 4176}, + {0x1e41, 16, 16, 4176}, + {0x0, 0, 16, 4176}, + {0x0, 4, 5, 4192}, + {0xf93f, 16, 16, 4193}, + {0x0, 7, 8, 4193}, + {0x2f964, 16, 16, 4194}, + {0x0, 6, 7, 4194}, + {0x2f9be, 16, 16, 4195}, + {0x1e8d, 16, 16, 4195}, + {0x0, 0, 1, 4195}, + {0x0, 0, 1, 4196}, + {0x0, 3, 4, 4197}, + {0x0, 0, 1, 4198}, + {0x0, 0, 2, 4199}, + {0x1e14, 16, 16, 4201}, + {0x0, 7, 8, 4201}, + {0xfa31, 16, 16, 4202}, + {0x0, 0, 1, 4202}, + {0x0, 0, 1, 4203}, + {0x0, 3, 4, 4204}, + {0x0, 0, 1, 4205}, + {0x0, 1, 2, 4206}, + {0x1e2f, 16, 16, 4207}, + {0x0, 7, 8, 4207}, + {0xf963, 16, 16, 4208}, + {0x2f9b3, 16, 16, 4208}, + {0x0, 0, 1, 4208}, + {0x0, 0, 1, 4209}, + {0x0, 3, 4, 4210}, + {0x0, 0, 5, 4211}, + {0x0, 2, 3, 4216}, + {0x1f3e, 16, 16, 4217}, + {0x0, 0, 1, 4217}, + {0x0, 0, 1, 4218}, + {0x0, 3, 4, 4219}, + {0x0, 0, 1, 4220}, + {0x0, 1, 2, 4221}, + {0x1e2e, 16, 16, 4222}, + {0x1e29, 16, 16, 4222}, + {0x0, 0, 1, 4222}, + {0x0, 0, 1, 4223}, + {0x0, 3, 4, 4224}, + {0x0, 0, 4, 4225}, + {0x0, 1, 2, 4229}, + {0x1e06, 16, 16, 4230}, + {0x1e25, 16, 16, 4230}, + {0xec, 16, 16, 4230}, + {0xed, 16, 16, 4230}, + {0xee, 16, 16, 4230}, + {0x129, 16, 16, 4230}, + {0x12b, 16, 16, 4230}, + {0x12d, 16, 16, 4230}, + {0xef, 16, 16, 4230}, + {0x1ec9, 16, 16, 4230}, + {0x0, 6, 16, 4230}, + {0x2f83b, 16, 16, 4240}, + {0x0, 1, 2, 4240}, + {0xf909, 16, 16, 4241}, + {0x2f969, 16, 16, 4241}, + {0x0, 8, 11, 4241}, + {0x2f9c9, 16, 16, 4244}, + {0x0, 1, 13, 4244}, + {0x1e30, 16, 16, 4256}, + {0x1a1, 16, 16, 4256}, + {0x0, 3, 12, 4256}, + {0x0, 0, 1, 4265}, + {0x0, 0, 1, 4266}, + {0x0, 3, 4, 4267}, + {0x0, 3, 4, 4268}, + {0x0, 8, 9, 4269}, + {0x2209, 16, 16, 4270}, + {0x0, 13, 14, 4270}, + {0xf918, 16, 16, 4271}, + {0xf97b, 16, 16, 4271}, + {0x0, 1, 13, 4271}, + {0x2f9a9, 16, 16, 4283}, + {0x2f9a8, 16, 16, 4283}, + {0x0, 8, 9, 4283}, + {0x2f86e, 16, 16, 4284}, + {0x0, 4, 5, 4284}, + {0x2f9e2, 16, 16, 4285}, + {0xf9de, 16, 16, 4285}, + {0x1e8, 16, 16, 4285}, + {0x0, 3, 4, 4285}, + {0x2f99c, 16, 16, 4286}, + {0x0, 6, 7, 4286}, + {0x2f94b, 16, 16, 4287}, + {0x209, 16, 16, 4287}, + {0x0, 2, 3, 4287}, + {0xfa4a, 16, 16, 4288}, + {0xf9c2, 16, 16, 4288}, + {0x0, 0, 1, 4288}, + {0x0, 0, 1, 4289}, + {0x0, 3, 4, 4290}, + {0x0, 0, 1, 4291}, + {0x0, 8, 9, 4292}, + {0x4db, 16, 16, 4293}, + {0x0, 5, 6, 4293}, + {0xfa1a, 16, 16, 4294}, + {0x0, 4, 15, 4294}, + {0x2f8a9, 16, 16, 4305}, + {0x0, 3, 14, 4305}, + {0x0, 0, 1, 4316}, + {0x0, 0, 1, 4317}, + {0x0, 3, 4, 4318}, + {0x0, 0, 1, 4319}, + {0x0, 4, 12, 4320}, + {0x4f0, 16, 16, 4328}, + {0x0, 5, 10, 4328}, + {0xf993, 16, 16, 4333}, + {0x2f8a8, 16, 16, 4333}, + {0x2f91c, 16, 16, 4333}, + {0x40e, 16, 16, 4333}, + {0x4ee, 16, 16, 4333}, + {0x0, 5, 6, 4333}, + {0x2f986, 16, 16, 4334}, + {0x0, 11, 12, 4334}, + {0xf922, 16, 16, 4335}, + {0x0, 5, 6, 4335}, + {0x1fcc, 16, 16, 4336}, + {0x0, 0, 1, 4336}, + {0x0, 3, 4, 4337}, + {0x0, 0, 1, 4338}, + {0x0, 9, 10, 4339}, + {0x0, 9, 10, 4340}, + {0x3056, 16, 16, 4341}, + {0x0, 7, 16, 4341}, + {0xf9da, 16, 16, 4350}, + {0x0, 7, 8, 4350}, + {0x2f96e, 16, 16, 4351}, + {0xf9d9, 16, 16, 4351}, + {0x4f2, 16, 16, 4351}, + {0x2f8a6, 16, 16, 4351}, + {0x0, 8, 9, 4351}, + {0x2f869, 16, 16, 4352}, + {0x0, 8, 9, 4352}, + {0xf9ef, 16, 16, 4353}, + {0x0, 5, 6, 4353}, + {0x2f8e0, 16, 16, 4354}, + {0x0, 0, 9, 4354}, + {0x0, 11, 12, 4363}, + {0x2f94a, 16, 16, 4364}, + {0x0, 0, 10, 4364}, + {0x0, 13, 14, 4374}, + {0xf9c4, 16, 16, 4375}, + {0x2f8e5, 16, 16, 4375}, + {0x0, 0, 1, 4375}, + {0x1e1a, 16, 16, 4376}, + {0x0, 10, 11, 4376}, + {0x0, 11, 12, 4377}, + {0x2f91f, 16, 16, 4378}, + {0x0, 0, 1, 4378}, + {0x0, 0, 1, 4379}, + {0x0, 3, 4, 4380}, + {0x0, 0, 3, 4381}, + {0x0, 0, 16, 4384}, + {0x200, 16, 16, 4400}, + {0x1cd, 16, 16, 4400}, + {0xc5, 16, 16, 4400}, + {0x0, 13, 14, 4400}, + {0x2f8d6, 16, 16, 4401}, + {0x0, 5, 6, 4401}, + {0xf976, 16, 16, 4402}, + {0x0, 6, 12, 4402}, + {0xf9b5, 16, 16, 4408}, + {0x0, 0, 1, 4408}, + {0x0, 0, 1, 4409}, + {0x0, 3, 4, 4410}, + {0x0, 0, 4, 4411}, + {0x0, 3, 14, 4415}, + {0x21a, 16, 16, 4426}, + {0x162, 16, 16, 4426}, + {0x1e6c, 16, 16, 4426}, + {0x0, 0, 2, 4426}, + {0x1f05, 16, 16, 4428}, + {0x1f03, 16, 16, 4428}, + {0x0, 1, 2, 4428}, + {0x2f8ef, 16, 16, 4429}, + {0x0, 7, 8, 4429}, + {0x2f9ce, 16, 16, 4430}, + {0xf92d, 16, 16, 4430}, + {0x0, 10, 15, 4430}, + {0x0, 8, 9, 4435}, + {0x2f860, 16, 16, 4436}, + {0x1e70, 16, 16, 4436}, + {0x0, 4, 5, 4436}, + {0xfa2d, 16, 16, 4437}, + {0x0, 12, 13, 4437}, + {0x2f8c9, 16, 16, 4438}, + {0x102, 16, 16, 4438}, + {0x226, 16, 16, 4438}, + {0x100, 16, 16, 4438}, + {0xc2, 16, 16, 4438}, + {0xc3, 16, 16, 4438}, + {0xc0, 16, 16, 4438}, + {0xc1, 16, 16, 4438}, + {0x0, 2, 3, 4438}, + {0x2fa06, 16, 16, 4439}, + {0x0, 2, 3, 4439}, + {0x1f57, 16, 16, 4440}, + {0x0, 5, 6, 4440}, + {0x2f9d2, 16, 16, 4441}, + {0xc4, 16, 16, 4441}, + {0x1ea2, 16, 16, 4441}, + {0x0, 8, 9, 4441}, + {0x2f8bb, 16, 16, 4442}, + {0x0, 15, 16, 4442}, + {0xf910, 16, 16, 4443}, + {0x0, 0, 1, 4443}, + {0x0, 0, 1, 4444}, + {0x0, 3, 4, 4445}, + {0x0, 0, 1, 4446}, + {0x0, 1, 8, 4447}, + {0x1e57, 16, 16, 4454}, + {0x1e55, 16, 16, 4454}, + {0x0, 3, 4, 4454}, + {0xf9e0, 16, 16, 4455}, + {0x0, 0, 1, 4455}, + {0x0, 0, 1, 4456}, + {0x0, 3, 4, 4457}, + {0x0, 0, 3, 4458}, + {0x0, 0, 16, 4461}, + {0xd5, 16, 16, 4477}, + {0x0, 0, 10, 4477}, + {0x1ee0, 16, 16, 4487}, + {0x1eda, 16, 16, 4487}, + {0x1edc, 16, 16, 4487}, + {0x0, 0, 1, 4487}, + {0x0, 0, 1, 4488}, + {0x0, 3, 4, 4489}, + {0x0, 3, 4, 4490}, + {0x0, 8, 9, 4491}, + {0x22ea, 16, 16, 4492}, + {0x1ede, 16, 16, 4492}, + {0x0, 1, 16, 4492}, + {0x0, 14, 15, 4507}, + {0x2f852, 16, 16, 4508}, + {0x0, 0, 12, 4508}, + {0x2f8b2, 16, 16, 4520}, + {0x0, 12, 14, 4520}, + {0x0, 4, 5, 4522}, + {0x2f9de, 16, 16, 4523}, + {0x0, 12, 13, 4523}, + {0x2f88a, 16, 16, 4524}, + {0x0, 0, 14, 4524}, + {0xfa32, 16, 16, 4538}, + {0x0, 0, 1, 4538}, + {0x0, 0, 1, 4539}, + {0x0, 3, 4, 4540}, + {0x0, 0, 1, 4541}, + {0x0, 7, 8, 4542}, + {0x1e67, 16, 16, 4543}, + {0x0, 8, 9, 4543}, + {0x2f9b8, 16, 16, 4544}, + {0x0, 9, 10, 4544}, + {0x2f8de, 16, 16, 4545}, + {0x1f7c, 16, 16, 4545}, + {0x0, 2, 3, 4545}, + {0x1fdf, 16, 16, 4546}, + {0x0, 6, 7, 4546}, + {0x0, 11, 12, 4547}, + {0x2f9a5, 16, 16, 4548}, + {0x0, 6, 7, 4548}, + {0xfa01, 16, 16, 4549}, + {0x0, 9, 10, 4549}, + {0x2f809, 16, 16, 4550}, + {0x0, 4, 14, 4550}, + {0x0, 15, 16, 4560}, + {0x2f81c, 16, 16, 4561}, + {0x0, 9, 10, 4561}, + {0x2f9b7, 16, 16, 4562}, + {0x0, 12, 15, 4562}, + {0xf973, 16, 16, 4565}, + {0x0, 0, 1, 4565}, + {0x0, 3, 4, 4566}, + {0x0, 0, 1, 4567}, + {0x0, 9, 10, 4568}, + {0x0, 9, 10, 4569}, + {0x30c0, 16, 16, 4570}, + {0x0, 3, 5, 4570}, + {0x1f08, 16, 16, 4572}, + {0x2f8b3, 16, 16, 4572}, + {0x1f09, 16, 16, 4572}, + {0x2f8ba, 16, 16, 4572}, + {0x0, 0, 1, 4572}, + {0x0, 0, 1, 4573}, + {0x0, 3, 4, 4574}, + {0x0, 0, 5, 4575}, + {0x0, 0, 2, 4580}, + {0x1fd2, 16, 16, 4582}, + {0x390, 16, 16, 4582}, + {0xfa0c, 16, 16, 4582}, + {0x0, 0, 1, 4582}, + {0x0, 0, 1, 4583}, + {0x0, 3, 4, 4584}, + {0x0, 0, 1, 4585}, + {0x0, 1, 2, 4586}, + {0x1e79, 16, 16, 4587}, + {0x0, 4, 16, 4587}, + {0x2f8ad, 16, 16, 4599}, + {0x0, 2, 3, 4599}, + {0x0, 15, 16, 4600}, + {0x2f958, 16, 16, 4601}, + {0x0, 5, 8, 4601}, + {0x2f81b, 16, 16, 4604}, + {0x0, 0, 1, 4604}, + {0x0, 0, 1, 4605}, + {0x0, 3, 4, 4606}, + {0x0, 3, 4, 4607}, + {0x0, 8, 9, 4608}, + {0x2275, 16, 16, 4609}, + {0x0, 0, 13, 4609}, + {0x148, 16, 16, 4622}, + {0x0, 0, 15, 4622}, + {0x0, 14, 15, 4637}, + {0x2f985, 16, 16, 4638}, + {0x0, 0, 7, 4638}, + {0xfa66, 16, 16, 4645}, + {0xf971, 16, 16, 4645}, + {0x0, 1, 2, 4645}, + {0x20b, 16, 16, 4646}, + {0x0, 0, 1, 4646}, + {0x0, 0, 1, 4647}, + {0x0, 3, 4, 4648}, + {0x0, 0, 5, 4649}, + {0x0, 2, 3, 4654}, + {0x1fe6, 16, 16, 4655}, + {0x0, 2, 3, 4655}, + {0x1f3f, 16, 16, 4656}, + {0x0, 7, 8, 4656}, + {0x0, 1, 2, 4657}, + {0x0, 0, 1, 4658}, + {0x0, 0, 1, 4659}, + {0x0, 15, 16, 4660}, + {0x0, 7, 9, 4661}, + {0x0, 0, 1, 4663}, + {0xf81, 16, 16, 4664}, + {0x0, 0, 1, 4664}, + {0x0, 0, 1, 4665}, + {0x0, 3, 4, 4666}, + {0x0, 4, 5, 4667}, + {0x0, 5, 6, 4668}, + {0x1fb2, 16, 16, 4669}, + {0x0, 3, 4, 4669}, + {0x1e04, 16, 16, 4670}, + {0x0, 1, 2, 4670}, + {0x2f96d, 16, 16, 4671}, + {0x0, 0, 16, 4671}, + {0x2f95b, 16, 16, 4687}, + {0x2f95a, 16, 16, 4687}, + {0x1e45, 16, 16, 4687}, + {0x1f9, 16, 16, 4687}, + {0x144, 16, 16, 4687}, + {0x0, 9, 10, 4687}, + {0x2f9eb, 16, 16, 4688}, + {0xf1, 16, 16, 4688}, + {0x0, 0, 1, 4688}, + {0x0, 0, 1, 4689}, + {0x0, 3, 4, 4690}, + {0x0, 0, 1, 4691}, + {0x0, 2, 7, 4692}, + {0x1ead, 16, 16, 4697}, + {0x0, 9, 10, 4697}, + {0x2f913, 16, 16, 4698}, + {0x1eb7, 16, 16, 4698}, + {0x0, 0, 1, 4698}, + {0x0, 0, 1, 4699}, + {0x0, 3, 4, 4700}, + {0x0, 0, 4, 4701}, + {0x0, 0, 13, 4705}, + {0x147, 16, 16, 4718}, + {0x0, 11, 14, 4718}, + {0xfa09, 16, 16, 4721}, + {0x0, 8, 9, 4721}, + {0x2f83d, 16, 16, 4722}, + {0x0, 10, 12, 4722}, + {0x0, 7, 8, 4724}, + {0x2f987, 16, 16, 4725}, + {0x0, 3, 4, 4725}, + {0x2f951, 16, 16, 4726}, + {0x0, 5, 9, 4726}, + {0x0, 14, 15, 4730}, + {0x2f910, 16, 16, 4731}, + {0xfa54, 16, 16, 4731}, + {0x0, 10, 11, 4731}, + {0xfa46, 16, 16, 4732}, + {0x0, 3, 4, 4732}, + {0x2f86d, 16, 16, 4733}, + {0x0, 0, 16, 4733}, + {0x1ecf, 16, 16, 4749}, + {0xf6, 16, 16, 4749}, + {0x14d, 16, 16, 4749}, + {0x0, 3, 4, 4749}, + {0x2f9a0, 16, 16, 4750}, + {0x14f, 16, 16, 4750}, + {0xf3, 16, 16, 4750}, + {0xf2, 16, 16, 4750}, + {0xf5, 16, 16, 4750}, + {0xf4, 16, 16, 4750}, + {0x0, 5, 6, 4750}, + {0x2f8c0, 16, 16, 4751}, + {0x0, 6, 7, 4751}, + {0x2f841, 16, 16, 4752}, + {0x0, 0, 1, 4752}, + {0x0, 0, 1, 4753}, + {0x0, 3, 4, 4754}, + {0x0, 4, 5, 4755}, + {0x0, 5, 6, 4756}, + {0x1f9d, 16, 16, 4757}, + {0x0, 15, 16, 4757}, + {0xf93c, 16, 16, 4758}, + {0x0, 0, 13, 4758}, + {0xf9fd, 16, 16, 4771}, + {0x0, 0, 2, 4771}, + {0x1f65, 16, 16, 4773}, + {0x1f63, 16, 16, 4773}, + {0x2f8ae, 16, 16, 4773}, + {0x0, 0, 1, 4773}, + {0x0, 0, 1, 4774}, + {0x0, 3, 4, 4775}, + {0x0, 0, 1, 4776}, + {0x0, 4, 5, 4777}, + {0x231, 16, 16, 4778}, + {0x0, 2, 4, 4778}, + {0x2f942, 16, 16, 4780}, + {0x2f941, 16, 16, 4780}, + {0xf951, 16, 16, 4780}, + {0x0, 8, 9, 4780}, + {0x2f8ee, 16, 16, 4781}, + {0x2f819, 16, 16, 4781}, + {0x20d, 16, 16, 4781}, + {0x1d2, 16, 16, 4781}, + {0x151, 16, 16, 4781}, + {0x0, 0, 1, 4781}, + {0x0, 0, 1, 4782}, + {0x0, 3, 4, 4783}, + {0x0, 0, 3, 4784}, + {0x0, 3, 4, 4787}, + {0x1e7f, 16, 16, 4788}, + {0x0, 14, 15, 4788}, + {0x2f80c, 16, 16, 4789}, + {0x2f828, 16, 16, 4789}, + {0x0, 15, 16, 4789}, + {0x2f980, 16, 16, 4790}, + {0x0, 5, 10, 4790}, + {0x2f931, 16, 16, 4795}, + {0x0, 14, 15, 4795}, + {0x2f98d, 16, 16, 4796}, + {0x0, 9, 10, 4796}, + {0xfa63, 16, 16, 4797}, + {0xf994, 16, 16, 4797}, + {0x0, 14, 16, 4797}, + {0x2f947, 16, 16, 4799}, + {0x0, 2, 8, 4799}, + {0x0, 0, 1, 4805}, + {0x0, 0, 1, 4806}, + {0x0, 3, 4, 4807}, + {0x0, 3, 4, 4808}, + {0x0, 8, 9, 4809}, + {0x2289, 16, 16, 4810}, + {0x0, 13, 14, 4810}, + {0x0, 1, 2, 4811}, + {0x2f90d, 16, 16, 4812}, + {0x0, 7, 8, 4812}, + {0x2f8a5, 16, 16, 4813}, + {0x0, 5, 11, 4813}, + {0xf9a7, 16, 16, 4819}, + {0x0, 9, 12, 4819}, + {0x2f813, 16, 16, 4822}, + {0x0, 8, 10, 4822}, + {0x0, 15, 16, 4824}, + {0x2f939, 16, 16, 4825}, + {0x0, 0, 1, 4825}, + {0x0, 0, 1, 4826}, + {0x0, 3, 4, 4827}, + {0x0, 0, 1, 4828}, + {0x0, 0, 10, 4829}, + {0x1ec1, 16, 16, 4839}, + {0x0, 10, 11, 4839}, + {0xf911, 16, 16, 4840}, + {0x2f928, 16, 16, 4840}, + {0x0, 11, 12, 4840}, + {0xf9c8, 16, 16, 4841}, + {0x0, 0, 1, 4841}, + {0xf962, 16, 16, 4842}, + {0x0, 14, 15, 4842}, + {0xf957, 16, 16, 4843}, + {0x0, 0, 1, 4843}, + {0x0, 0, 1, 4844}, + {0x0, 3, 4, 4845}, + {0x0, 0, 1, 4846}, + {0x0, 4, 5, 4847}, + {0x1e1, 16, 16, 4848}, + {0x0, 1, 2, 4848}, + {0x1e6e, 16, 16, 4849}, + {0x0, 10, 11, 4849}, + {0x2f8aa, 16, 16, 4850}, + {0x0, 8, 9, 4850}, + {0xf9c5, 16, 16, 4851}, + {0x0, 0, 1, 4851}, + {0x0, 0, 1, 4852}, + {0x0, 3, 4, 4853}, + {0x0, 0, 1, 4854}, + {0x0, 4, 5, 4855}, + {0x1df, 16, 16, 4856}, + {0x0, 0, 2, 4856}, + {0x1f02, 16, 16, 4858}, + {0x1f04, 16, 16, 4858}, + {0x0, 14, 15, 4858}, + {0xf984, 16, 16, 4859}, + {0x0, 2, 3, 4859}, + {0x0, 5, 6, 4860}, + {0x0, 0, 1, 4861}, + {0x0, 1, 2, 4862}, + {0x0, 0, 1, 4863}, + {0x0, 2, 3, 4864}, + {0x0, 14, 15, 4865}, + {0x1026, 16, 16, 4866}, + {0x0, 14, 15, 4866}, + {0x2f8fa, 16, 16, 4867}, + {0x2f9ca, 16, 16, 4867}, + {0x0, 0, 1, 4867}, + {0x0, 0, 1, 4868}, + {0x0, 3, 4, 4869}, + {0x0, 0, 5, 4870}, + {0x0, 0, 2, 4875}, + {0x1f25, 16, 16, 4877}, + {0x0, 11, 16, 4877}, + {0x2f806, 16, 16, 4882}, + {0x0, 1, 2, 4882}, + {0x202, 16, 16, 4883}, + {0x0, 0, 1, 4883}, + {0x2f8b7, 16, 16, 4884}, + {0x0, 2, 3, 4884}, + {0x2f982, 16, 16, 4885}, + {0x0, 8, 10, 4885}, + {0x0, 0, 1, 4887}, + {0x0, 0, 1, 4888}, + {0x0, 3, 4, 4889}, + {0x0, 0, 1, 4890}, + {0x0, 8, 9, 4891}, + {0x4ea, 16, 16, 4892}, + {0x0, 0, 1, 4892}, + {0xf98f, 16, 16, 4893}, + {0x0, 13, 15, 4893}, + {0x0, 13, 14, 4895}, + {0x2f9e1, 16, 16, 4896}, + {0x0, 0, 1, 4896}, + {0x0, 0, 1, 4897}, + {0x0, 3, 4, 4898}, + {0x0, 0, 2, 4899}, + {0x0, 0, 2, 4901}, + {0x38c, 16, 16, 4903}, + {0x0, 2, 7, 4903}, + {0xf90d, 16, 16, 4908}, + {0x0, 2, 3, 4908}, + {0x2f875, 16, 16, 4909}, + {0x0, 14, 15, 4909}, + {0xf9d2, 16, 16, 4910}, + {0x0, 10, 11, 4910}, + {0xf902, 16, 16, 4911}, + {0x22f, 16, 16, 4911}, + {0x0, 2, 3, 4911}, + {0x1f56, 16, 16, 4912}, + {0x0, 3, 8, 4912}, + {0x15e, 16, 16, 4917}, + {0x218, 16, 16, 4917}, + {0x1e62, 16, 16, 4917}, + {0x0, 2, 7, 4917}, + {0xf9ba, 16, 16, 4922}, + {0xf91b, 16, 16, 4922}, + {0x0, 3, 10, 4922}, + {0x0, 6, 7, 4929}, + {0x2f916, 16, 16, 4930}, + {0x0, 0, 1, 4930}, + {0x0, 0, 1, 4931}, + {0x0, 3, 4, 4932}, + {0x0, 3, 4, 4933}, + {0x0, 8, 9, 4934}, + {0x22ae, 16, 16, 4935}, + {0x0, 7, 8, 4935}, + {0x2f973, 16, 16, 4936}, + {0x0, 0, 1, 4936}, + {0x0, 0, 1, 4937}, + {0x0, 3, 4, 4938}, + {0x0, 4, 5, 4939}, + {0x0, 5, 6, 4940}, + {0x1fa6, 16, 16, 4941}, + {0x0, 0, 1, 4941}, + {0x0, 0, 1, 4942}, + {0x0, 3, 4, 4943}, + {0x0, 0, 1, 4944}, + {0x0, 0, 2, 4945}, + {0x1f42, 16, 16, 4947}, + {0x1f44, 16, 16, 4947}, + {0x0, 3, 4, 4947}, + {0x2f843, 16, 16, 4948}, + {0x0, 10, 11, 4948}, + {0x0, 3, 4, 4949}, + {0x2f8ec, 16, 16, 4950}, + {0x0, 0, 10, 4950}, + {0x1edd, 16, 16, 4960}, + {0x1edb, 16, 16, 4960}, + {0x0, 15, 16, 4960}, + {0xf9eb, 16, 16, 4961}, + {0x1ee1, 16, 16, 4961}, + {0x1edf, 16, 16, 4961}, + {0x622, 16, 16, 4961}, + {0x0, 0, 1, 4961}, + {0x0, 3, 4, 4962}, + {0x0, 0, 1, 4963}, + {0x0, 9, 10, 4964}, + {0x0, 9, 11, 4965}, + {0x30d3, 16, 16, 4967}, + {0x0, 1, 4, 4967}, + {0x0, 12, 13, 4970}, + {0x2f8a2, 16, 16, 4971}, + {0x0, 0, 1, 4971}, + {0xf944, 16, 16, 4972}, + {0x0, 0, 1, 4972}, + {0x1e2c, 16, 16, 4973}, + {0x0, 0, 1, 4973}, + {0x0, 0, 1, 4974}, + {0x0, 3, 4, 4975}, + {0x0, 0, 4, 4976}, + {0x0, 3, 8, 4980}, + {0x1e33, 16, 16, 4985}, + {0x0, 2, 3, 4985}, + {0x2f888, 16, 16, 4986}, + {0x0, 4, 5, 4986}, + {0x2f80f, 16, 16, 4987}, + {0x0, 0, 10, 4987}, + {0x0, 14, 15, 4997}, + {0x2fa13, 16, 16, 4998}, + {0x0, 2, 3, 4998}, + {0x2f960, 16, 16, 4999}, + {0x0, 8, 9, 4999}, + {0x0, 0, 1, 5000}, + {0x0, 0, 1, 5001}, + {0x0, 9, 10, 5002}, + {0x0, 3, 4, 5003}, + {0x0, 12, 13, 5004}, + {0x929, 16, 16, 5005}, + {0x0, 0, 1, 5005}, + {0x0, 10, 11, 5006}, + {0x2f8ca, 16, 16, 5007}, + {0x0, 0, 1, 5007}, + {0x0, 0, 1, 5008}, + {0x0, 3, 4, 5009}, + {0x0, 0, 5, 5010}, + {0x0, 2, 6, 5015}, + {0x1fa8, 16, 16, 5019}, + {0x0, 0, 1, 5019}, + {0x0, 0, 1, 5020}, + {0x0, 3, 4, 5021}, + {0x0, 4, 5, 5022}, + {0x0, 5, 6, 5023}, + {0x1f9e, 16, 16, 5024}, + {0x0, 0, 1, 5024}, + {0x0, 3, 4, 5025}, + {0x0, 0, 1, 5026}, + {0x0, 9, 10, 5027}, + {0x0, 9, 10, 5028}, + {0x30fe, 16, 16, 5029}, + {0x0, 2, 13, 5029}, + {0x1e27, 16, 16, 5040}, + {0x1e23, 16, 16, 5040}, + {0x125, 16, 16, 5040}, + {0x0, 4, 5, 5040}, + {0x2f8f1, 16, 16, 5041}, + {0x0, 3, 5, 5041}, + {0x1f60, 16, 16, 5043}, + {0x0, 4, 5, 5043}, + {0x2f971, 16, 16, 5044}, + {0x30d4, 16, 16, 5044}, + {0x1f61, 16, 16, 5044}, + {0x0, 0, 1, 5044}, + {0x0, 3, 4, 5045}, + {0x0, 0, 1, 5046}, + {0x0, 9, 10, 5047}, + {0x0, 9, 10, 5048}, + {0x304c, 16, 16, 5049}, + {0x0, 0, 1, 5049}, + {0x0, 0, 1, 5050}, + {0x0, 3, 4, 5051}, + {0x0, 0, 1, 5052}, + {0x0, 1, 2, 5053}, + {0x1e78, 16, 16, 5054}, + {0x0, 0, 1, 5054}, + {0x0, 3, 4, 5055}, + {0x0, 0, 1, 5056}, + {0x0, 9, 10, 5057}, + {0x0, 9, 11, 5058}, + {0x30d9, 16, 16, 5060}, + {0x0, 8, 9, 5060}, + {0xf9b3, 16, 16, 5061}, + {0x0, 11, 15, 5061}, + {0x2f914, 16, 16, 5065}, + {0x0, 8, 14, 5065}, + {0xfa5c, 16, 16, 5071}, + {0x0, 0, 2, 5071}, + {0x1f34, 16, 16, 5073}, + {0x2f915, 16, 16, 5073}, + {0x0, 0, 1, 5073}, + {0x0, 0, 1, 5074}, + {0x0, 3, 4, 5075}, + {0x0, 4, 5, 5076}, + {0x0, 5, 6, 5077}, + {0x1f85, 16, 16, 5078}, + {0x0, 4, 15, 5078}, + {0x2f907, 16, 16, 5089}, + {0x0, 2, 3, 5089}, + {0x2f8bf, 16, 16, 5090}, + {0x0, 15, 16, 5090}, + {0xf937, 16, 16, 5091}, + {0x2126, 0, 1, 5091}, + {0x0, 0, 1, 5092}, + {0x0, 3, 4, 5093}, + {0x0, 0, 5, 5094}, + {0x0, 0, 2, 5099}, + {0x1ffa, 16, 16, 5101}, + {0x38f, 16, 16, 5101}, + {0x0, 4, 13, 5101}, + {0x0, 0, 1, 5110}, + {0x0, 0, 1, 5111}, + {0x0, 3, 4, 5112}, + {0x0, 0, 1, 5113}, + {0x0, 1, 2, 5114}, + {0x1ff, 16, 16, 5115}, + {0x0, 0, 1, 5115}, + {0x0, 0, 1, 5116}, + {0x0, 3, 4, 5117}, + {0x0, 4, 5, 5118}, + {0x0, 5, 6, 5119}, + {0x1f84, 16, 16, 5120}, + {0xf9f6, 16, 16, 5120}, + {0x0, 8, 10, 5120}, + {0x2329, 16, 16, 5122}, + {0x232a, 16, 16, 5122}, + {0x0, 0, 1, 5122}, + {0x0, 0, 1, 5123}, + {0x0, 3, 4, 5124}, + {0x0, 3, 4, 5125}, + {0x0, 8, 9, 5126}, + {0x2274, 16, 16, 5127}, + {0x30da, 16, 16, 5127}, + {0x0, 4, 13, 5127}, + {0x0, 0, 1, 5136}, + {0x0, 0, 1, 5137}, + {0x0, 3, 4, 5138}, + {0x0, 0, 1, 5139}, + {0x0, 0, 10, 5140}, + {0x1ed4, 16, 16, 5150}, + {0x0, 4, 5, 5150}, + {0xfa34, 16, 16, 5151}, + {0x1ed0, 16, 16, 5151}, + {0x1ed2, 16, 16, 5151}, + {0x1ed6, 16, 16, 5151}, + {0x2f900, 16, 16, 5151}, + {0x0, 4, 5, 5151}, + {0x2f940, 16, 16, 5152}, + {0x0, 0, 1, 5152}, + {0x0, 0, 1, 5153}, + {0x0, 3, 4, 5154}, + {0x0, 0, 1, 5155}, + {0x0, 1, 9, 5156}, + {0x1e4e, 16, 16, 5164}, + {0x1e4c, 16, 16, 5164}, + {0x22c, 16, 16, 5164}, + {0x0, 9, 15, 5164}, + {0x2fa18, 16, 16, 5170}, + {0x0, 12, 13, 5170}, + {0x0, 8, 9, 5171}, + {0x2f86c, 16, 16, 5172}, + {0x0, 7, 8, 5172}, + {0x2fa0f, 16, 16, 5173}, + {0x0, 1, 3, 5173}, + {0x0, 0, 1, 5175}, + {0x0, 0, 1, 5176}, + {0x0, 3, 4, 5177}, + {0x0, 3, 4, 5178}, + {0x0, 8, 9, 5179}, + {0x22e2, 16, 16, 5180}, + {0x0, 4, 5, 5180}, + {0xfa06, 16, 16, 5181}, + {0x0, 0, 1, 5181}, + {0x0, 0, 1, 5182}, + {0x0, 3, 4, 5183}, + {0x0, 0, 4, 5184}, + {0x0, 1, 16, 5188}, + {0x155, 16, 16, 5203}, + {0x0, 8, 9, 5203}, + {0xfa3e, 16, 16, 5204}, + {0x0, 0, 1, 5204}, + {0xf93d, 16, 16, 5205}, + {0x0, 0, 8, 5205}, + {0x0, 0, 1, 5213}, + {0x0, 0, 1, 5214}, + {0x0, 3, 4, 5215}, + {0x0, 0, 3, 5216}, + {0x0, 3, 4, 5219}, + {0x1ef1, 16, 16, 5220}, + {0x0, 6, 7, 5220}, + {0x2f935, 16, 16, 5221}, + {0x2fa17, 16, 16, 5221}, + {0x0, 14, 15, 5221}, + {0xfa48, 16, 16, 5222}, + {0x0, 15, 16, 5222}, + {0xf939, 16, 16, 5223}, + {0x0, 0, 1, 5223}, + {0x0, 0, 1, 5224}, + {0x0, 3, 4, 5225}, + {0x0, 0, 1, 5226}, + {0x0, 12, 13, 5227}, + {0x1ee, 16, 16, 5228}, + {0x0, 8, 9, 5228}, + {0x2fa11, 16, 16, 5229}, + {0x0, 8, 9, 5229}, + {0x2f97e, 16, 16, 5230}, + {0x0, 4, 5, 5230}, + {0xfa12, 16, 16, 5231}, + {0x0, 0, 1, 5231}, + {0x0, 3, 4, 5232}, + {0x0, 0, 1, 5233}, + {0x0, 9, 10, 5234}, + {0x0, 9, 10, 5235}, + {0x305c, 16, 16, 5236}, + {0x0, 10, 11, 5236}, + {0x2f954, 16, 16, 5237}, + {0x0, 7, 13, 5237}, + {0x1e6a, 16, 16, 5243}, + {0x0, 0, 1, 5243}, + {0x0, 0, 1, 5244}, + {0x0, 3, 4, 5245}, + {0x0, 0, 1, 5246}, + {0x0, 1, 2, 5247}, + {0x344, 16, 16, 5248}, + {0x0, 0, 1, 5248}, + {0x0, 0, 1, 5249}, + {0x0, 3, 4, 5250}, + {0x0, 0, 1, 5251}, + {0x0, 0, 2, 5252}, + {0x1f45, 16, 16, 5254}, + {0x1f43, 16, 16, 5254}, + {0x0, 0, 1, 5254}, + {0x0, 0, 1, 5255}, + {0x0, 3, 4, 5256}, + {0x0, 0, 4, 5257}, + {0x0, 1, 2, 5261}, + {0x1e94, 16, 16, 5262}, + {0x0, 15, 16, 5262}, + {0xf9bd, 16, 16, 5263}, + {0x0, 1, 13, 5263}, + {0xfa43, 16, 16, 5275}, + {0x0, 0, 1, 5275}, + {0x0, 0, 1, 5276}, + {0x0, 3, 4, 5277}, + {0x0, 0, 1, 5278}, + {0x0, 0, 2, 5279}, + {0x1e51, 16, 16, 5281}, + {0x1e53, 16, 16, 5281}, + {0x0, 3, 4, 5281}, + {0x2f889, 16, 16, 5282}, + {0x0, 3, 9, 5282}, + {0x104, 16, 16, 5288}, + {0x164, 16, 16, 5288}, + {0x0, 7, 8, 5288}, + {0x2fa05, 16, 16, 5289}, + {0x1ea0, 16, 16, 5289}, + {0x1e00, 16, 16, 5289}, + {0x0, 13, 14, 5289}, + {0x0, 0, 1, 5290}, + {0x0, 3, 4, 5291}, + {0x0, 0, 1, 5292}, + {0x0, 9, 10, 5293}, + {0x0, 9, 10, 5294}, + {0x309e, 16, 16, 5295}, + {0x0, 2, 3, 5295}, + {0x2f840, 16, 16, 5296}, + {0x0, 10, 11, 5296}, + {0x2f948, 16, 16, 5297}, + {0x2f8d5, 16, 16, 5297}, + {0x0, 11, 12, 5297}, + {0xf9f7, 16, 16, 5298}, + {0x0, 0, 1, 5298}, + {0x0, 0, 1, 5299}, + {0x0, 3, 4, 5300}, + {0x0, 0, 1, 5301}, + {0x0, 6, 9, 5302}, + {0x4c1, 16, 16, 5305}, + {0x1f24, 16, 16, 5305}, + {0x0, 0, 1, 5305}, + {0x0, 0, 1, 5306}, + {0x0, 3, 4, 5307}, + {0x0, 0, 5, 5308}, + {0x0, 2, 6, 5313}, + {0x1f6f, 16, 16, 5317}, + {0x4dc, 16, 16, 5317}, + {0x0, 0, 1, 5317}, + {0x0, 0, 1, 5318}, + {0x0, 3, 4, 5319}, + {0x0, 0, 1, 5320}, + {0x0, 1, 2, 5321}, + {0x1fe, 16, 16, 5322}, + {0x1fa9, 16, 16, 5322}, + {0x0, 13, 14, 5322}, + {0x2f99b, 16, 16, 5323}, + {0x0, 0, 1, 5323}, + {0x0, 0, 1, 5324}, + {0x0, 3, 4, 5325}, + {0x0, 3, 4, 5326}, + {0x0, 8, 9, 5327}, + {0x2204, 16, 16, 5328}, + {0x0, 10, 12, 5328}, + {0x0, 8, 9, 5330}, + {0x2f92d, 16, 16, 5331}, + {0x0, 0, 1, 5331}, + {0x0, 0, 1, 5332}, + {0x0, 3, 4, 5333}, + {0x0, 0, 1, 5334}, + {0x0, 0, 10, 5335}, + {0x1ec2, 16, 16, 5345}, + {0x1ebe, 16, 16, 5345}, + {0x1ec0, 16, 16, 5345}, + {0x1ec4, 16, 16, 5345}, + {0x0, 2, 3, 5345}, + {0x2f9e0, 16, 16, 5346}, + {0x0, 2, 3, 5346}, + {0x0, 12, 13, 5347}, + {0x2f834, 16, 16, 5348}, + {0x0, 7, 9, 5348}, + {0x2f904, 16, 16, 5350}, + {0x0, 6, 7, 5350}, + {0x0, 0, 1, 5351}, + {0x0, 0, 1, 5352}, + {0x0, 3, 4, 5353}, + {0x0, 0, 1, 5354}, + {0x0, 8, 9, 5355}, + {0x457, 16, 16, 5356}, + {0x0, 0, 1, 5356}, + {0x0, 0, 1, 5357}, + {0x0, 3, 4, 5358}, + {0x0, 0, 2, 5359}, + {0x0, 0, 2, 5361}, + {0x3ad, 16, 16, 5363}, + {0x0, 0, 14, 5363}, + {0x0, 8, 9, 5377}, + {0x2f8eb, 16, 16, 5378}, + {0x0, 0, 1, 5378}, + {0x0, 0, 1, 5379}, + {0x0, 3, 4, 5380}, + {0x0, 0, 3, 5381}, + {0x0, 3, 8, 5384}, + {0x1e63, 16, 16, 5389}, + {0x15f, 16, 16, 5389}, + {0x219, 16, 16, 5389}, + {0x0, 0, 1, 5389}, + {0x0, 0, 1, 5390}, + {0x0, 3, 4, 5391}, + {0x0, 3, 4, 5392}, + {0x0, 8, 9, 5393}, + {0x2285, 16, 16, 5394}, + {0x4ef, 16, 16, 5394}, + {0xcf, 16, 16, 5394}, + {0x0, 0, 1, 5394}, + {0x0, 0, 1, 5395}, + {0x0, 13, 14, 5396}, + {0x0, 12, 14, 5397}, + {0x0, 15, 16, 5399}, + {0xdde, 16, 16, 5400}, + {0x4f1, 16, 16, 5400}, + {0x130, 16, 16, 5400}, + {0x12a, 16, 16, 5400}, + {0xce, 16, 16, 5400}, + {0x128, 16, 16, 5400}, + {0xcc, 16, 16, 5400}, + {0xcd, 16, 16, 5400}, + {0x0, 10, 11, 5400}, + {0x2f8ea, 16, 16, 5401}, + {0x0, 2, 6, 5401}, + {0x1fc3, 16, 16, 5405}, + {0x0, 7, 8, 5405}, + {0x1e02, 16, 16, 5406}, + {0x1fc6, 16, 16, 5406}, + {0x0, 2, 4, 5406}, + {0x0, 0, 1, 5408}, + {0x0, 0, 1, 5409}, + {0x0, 3, 4, 5410}, + {0x0, 0, 1, 5411}, + {0x0, 0, 10, 5412}, + {0x1eaf, 16, 16, 5422}, + {0x0, 2, 16, 5422}, + {0x2fa02, 16, 16, 5436}, + {0x0, 2, 6, 5436}, + {0x1fb3, 16, 16, 5440}, + {0x0, 0, 1, 5440}, + {0x0, 0, 1, 5441}, + {0x0, 3, 4, 5442}, + {0x0, 0, 1, 5443}, + {0x0, 8, 9, 5444}, + {0x4f4, 16, 16, 5445}, + {0x1fb6, 16, 16, 5445}, + {0x0, 6, 7, 5445}, + {0xfa1c, 16, 16, 5446}, + {0x0, 2, 3, 5446}, + {0x1f37, 16, 16, 5447}, + {0x0, 13, 14, 5447}, + {0x2f815, 16, 16, 5448}, + {0x0, 11, 12, 5448}, + {0x2f855, 16, 16, 5449}, + {0x0, 12, 14, 5449}, + {0x2f8fd, 16, 16, 5451}, + {0x4f3, 16, 16, 5451}, + {0xf968, 16, 16, 5451}, + {0x208, 16, 16, 5451}, + {0x0, 1, 2, 5451}, + {0xf90a, 16, 16, 5452}, + {0x1cf, 16, 16, 5452}, + {0x0, 14, 15, 5452}, + {0xf9c6, 16, 16, 5453}, + {0xfa2a, 16, 16, 5453}, + {0x0, 3, 5, 5453}, + {0x1f68, 16, 16, 5455}, + {0x1f69, 16, 16, 5455}, + {0x0, 1, 5, 5455}, + {0x2f98c, 16, 16, 5459}, + {0x2f893, 16, 16, 5459}, + {0x0, 8, 9, 5459}, + {0xf926, 16, 16, 5460}, + {0x0, 3, 9, 5460}, + {0x1ecd, 16, 16, 5466}, + {0x0, 0, 1, 5466}, + {0x0, 3, 4, 5467}, + {0x0, 0, 1, 5468}, + {0x0, 9, 10, 5469}, + {0x0, 9, 10, 5470}, + {0x3052, 16, 16, 5471}, + {0x1eb, 16, 16, 5471}, + {0x0, 0, 10, 5471}, + {0xf975, 16, 16, 5481}, + {0x2f8c1, 16, 16, 5481}, + {0x0, 0, 1, 5481}, + {0x0, 0, 1, 5482}, + {0x0, 3, 4, 5483}, + {0x0, 0, 4, 5484}, + {0x0, 7, 13, 5488}, + {0x1e0a, 16, 16, 5494}, + {0x0, 0, 1, 5494}, + {0x2f9dc, 16, 16, 5495}, + {0x0, 0, 1, 5495}, + {0x1e1b, 16, 16, 5496}, + {0x0, 2, 15, 5496}, + {0xf952, 16, 16, 5509}, + {0x0, 13, 14, 5509}, + {0xfa1e, 16, 16, 5510}, + {0x0, 4, 5, 5510}, + {0x2f8d1, 16, 16, 5511}, + {0x10e, 16, 16, 5511}, + {0x0, 14, 15, 5511}, + {0xf977, 16, 16, 5512}, + {0x0, 0, 1, 5512}, + {0xfa60, 16, 16, 5513}, + {0x0, 10, 12, 5513}, + {0x0, 1, 2, 5515}, + {0x2f93b, 16, 16, 5516}, + {0x0, 3, 4, 5516}, + {0x1e7d, 16, 16, 5517}, + {0x0, 0, 1, 5517}, + {0x0, 0, 1, 5518}, + {0x0, 3, 4, 5519}, + {0x0, 4, 5, 5520}, + {0x0, 5, 6, 5521}, + {0x1fac, 16, 16, 5522}, + {0x0, 1, 2, 5522}, + {0x0, 8, 9, 5523}, + {0x2f871, 16, 16, 5524}, + {0x0, 10, 13, 5524}, + {0xf947, 16, 16, 5527}, + {0x2f950, 16, 16, 5527}, + {0x0, 0, 1, 5527}, + {0x0, 0, 1, 5528}, + {0x0, 3, 4, 5529}, + {0x0, 4, 5, 5530}, + {0x0, 5, 6, 5531}, + {0x1ff7, 16, 16, 5532}, + {0x0, 10, 15, 5532}, + {0xf96c, 16, 16, 5537}, + {0x0, 0, 1, 5537}, + {0x0, 0, 1, 5538}, + {0x0, 3, 4, 5539}, + {0x0, 0, 1, 5540}, + {0x0, 8, 9, 5541}, + {0x4ec, 16, 16, 5542}, + {0xfa10, 16, 16, 5542}, + {0x0, 0, 10, 5542}, + {0x0, 10, 11, 5552}, + {0x2f9fb, 16, 16, 5553}, + {0xf92f, 16, 16, 5553}, + {0x0, 6, 7, 5553}, + {0xf98b, 16, 16, 5554}, + {0x0, 4, 5, 5554}, + {0x2f8e6, 16, 16, 5555}, + {0x0, 0, 1, 5555}, + {0x0, 0, 1, 5556}, + {0x0, 3, 4, 5557}, + {0x0, 4, 5, 5558}, + {0x0, 5, 6, 5559}, + {0x1fab, 16, 16, 5560}, + {0x0, 7, 8, 5560}, + {0x0, 7, 8, 5561}, + {0x2f9f1, 16, 16, 5562}, + {0x0, 0, 1, 5562}, + {0x0, 0, 1, 5563}, + {0x0, 3, 4, 5564}, + {0x0, 0, 1, 5565}, + {0x0, 4, 5, 5566}, + {0x22a, 16, 16, 5567}, + {0x0, 0, 1, 5567}, + {0x0, 0, 1, 5568}, + {0x0, 3, 4, 5569}, + {0x0, 3, 4, 5570}, + {0x0, 8, 9, 5571}, + {0x219a, 16, 16, 5572}, + {0xf92e, 16, 16, 5572}, + {0xf965, 16, 16, 5572}, + {0x0, 0, 1, 5572}, + {0x0, 0, 1, 5573}, + {0x0, 3, 4, 5574}, + {0x0, 0, 4, 5575}, + {0x0, 7, 13, 5579}, + {0x165, 16, 16, 5585}, + {0x0, 2, 6, 5585}, + {0x1f99, 16, 16, 5589}, + {0x1f2f, 16, 16, 5589}, + {0x0, 0, 1, 5589}, + {0x0, 0, 1, 5590}, + {0x0, 3, 4, 5591}, + {0x0, 0, 1, 5592}, + {0x0, 8, 9, 5593}, + {0x4de, 16, 16, 5594}, + {0x0, 14, 15, 5594}, + {0xfa1d, 16, 16, 5595}, + {0x1ec3, 16, 16, 5595}, + {0x0, 0, 1, 5595}, + {0x0, 0, 1, 5596}, + {0x0, 3, 4, 5597}, + {0x0, 0, 2, 5598}, + {0x0, 0, 2, 5600}, + {0x1f78, 16, 16, 5602}, + {0x3cc, 16, 16, 5602}, + {0x1ec5, 16, 16, 5602}, + {0x1ebf, 16, 16, 5602}, + {0x0, 11, 12, 5602}, + {0x2fa1c, 16, 16, 5603}, + {0x0, 3, 15, 5603}, + {0x2f8db, 16, 16, 5615}, + {0x0, 1, 2, 5615}, + {0xf904, 16, 16, 5616}, + {0x0, 3, 4, 5616}, + {0x1e92, 16, 16, 5617}, + {0x0, 1, 2, 5617}, + {0x2f9c1, 16, 16, 5618}, + {0x1e6b, 16, 16, 5618}, + {0x1e97, 16, 16, 5618}, + {0x0, 0, 1, 5618}, + {0x0, 0, 1, 5619}, + {0x0, 3, 4, 5620}, + {0x0, 4, 5, 5621}, + {0x0, 5, 6, 5622}, + {0x1ff2, 16, 16, 5623}, + {0x0, 0, 1, 5623}, + {0x0, 0, 1, 5624}, + {0x0, 3, 4, 5625}, + {0x0, 0, 2, 5626}, + {0x0, 0, 9, 5628}, + {0x3aa, 16, 16, 5637}, + {0x0, 0, 1, 5637}, + {0x0, 0, 1, 5638}, + {0x0, 3, 4, 5639}, + {0x0, 0, 1, 5640}, + {0x0, 6, 9, 5641}, + {0x4c2, 16, 16, 5644}, + {0x4dd, 16, 16, 5644}, + {0x0, 8, 9, 5644}, + {0x2f885, 16, 16, 5645}, + {0x1fda, 16, 16, 5645}, + {0x38a, 16, 16, 5645}, + {0x1fd8, 16, 16, 5645}, + {0x1fd9, 16, 16, 5645}, + {0x0, 5, 10, 5645}, + {0xf9a3, 16, 16, 5650}, + {0x0, 0, 1, 5650}, + {0xf921, 16, 16, 5651}, + {0x2f89f, 16, 16, 5651}, + {0x0, 0, 1, 5651}, + {0x0, 0, 1, 5652}, + {0x0, 3, 4, 5653}, + {0x0, 3, 4, 5654}, + {0x0, 8, 9, 5655}, + {0x2288, 16, 16, 5656}, + {0x0, 0, 1, 5656}, + {0x0, 0, 1, 5657}, + {0x0, 3, 4, 5658}, + {0x0, 0, 4, 5659}, + {0x0, 1, 12, 5663}, + {0x1b0, 16, 16, 5674}, + {0xf9aa, 16, 16, 5674}, + {0x0, 2, 3, 5674}, + {0x0, 0, 1, 5675}, + {0x0, 0, 1, 5676}, + {0x0, 3, 4, 5677}, + {0x0, 0, 1, 5678}, + {0x0, 12, 13, 5679}, + {0x1ef, 16, 16, 5680}, + {0x217, 16, 16, 5680}, + {0x0, 11, 12, 5680}, + {0x2f9bd, 16, 16, 5681}, + {0x0, 0, 1, 5681}, + {0x0, 0, 1, 5682}, + {0x0, 3, 4, 5683}, + {0x0, 0, 4, 5684}, + {0x0, 0, 1, 5688}, + {0x1e74, 16, 16, 5689}, + {0x0, 0, 1, 5689}, + {0x0, 0, 1, 5690}, + {0x0, 3, 4, 5691}, + {0x0, 0, 1, 5692}, + {0x0, 0, 10, 5693}, + {0x1eb0, 16, 16, 5703}, + {0x1eae, 16, 16, 5703}, + {0x1eb4, 16, 16, 5703}, + {0x1eb2, 16, 16, 5703}, + {0x0, 8, 9, 5703}, + {0x2f972, 16, 16, 5704}, + {0x0, 15, 16, 5704}, + {0x2f837, 16, 16, 5705}, + {0x0, 0, 1, 5705}, + {0x0, 0, 1, 5706}, + {0x0, 3, 4, 5707}, + {0x0, 4, 5, 5708}, + {0x0, 5, 6, 5709}, + {0x1fa7, 16, 16, 5710}, + {0x0, 0, 1, 5710}, + {0x0, 3, 4, 5711}, + {0x0, 0, 1, 5712}, + {0x0, 9, 10, 5713}, + {0x0, 9, 10, 5714}, + {0x305a, 16, 16, 5715}, + {0x0, 1, 13, 5715}, + {0x1e9, 16, 16, 5727}, + {0x0, 15, 16, 5727}, + {0x2f908, 16, 16, 5728}, + {0x0, 15, 16, 5728}, + {0x2f8fc, 16, 16, 5729}, + {0xfa51, 16, 16, 5729}, + {0x0, 13, 14, 5729}, + {0x2f8e7, 16, 16, 5730}, + {0x0, 5, 6, 5730}, + {0x1fbc, 16, 16, 5731}, + {0x0, 10, 11, 5731}, + {0x2f8a1, 16, 16, 5732}, + {0x0, 1, 14, 5732}, + {0xfa26, 16, 16, 5745}, + {0x0, 11, 15, 5745}, + {0x0, 0, 1, 5749}, + {0x0, 0, 1, 5750}, + {0x0, 3, 4, 5751}, + {0x0, 3, 4, 5752}, + {0x0, 8, 9, 5753}, + {0x2260, 16, 16, 5754}, + {0x0, 3, 4, 5754}, + {0x0, 12, 13, 5755}, + {0x2f997, 16, 16, 5756}, + {0x0, 4, 5, 5756}, + {0x2f853, 16, 16, 5757}, + {0x3076, 16, 16, 5757}, + {0x0, 12, 13, 5757}, + {0xf92b, 16, 16, 5758}, + {0x0, 2, 3, 5758}, + {0x0, 2, 3, 5759}, + {0x2f803, 16, 16, 5760}, + {0x0, 1, 2, 5760}, + {0x20a, 16, 16, 5761}, + {0x0, 0, 1, 5761}, + {0x0, 0, 1, 5762}, + {0x0, 12, 13, 5763}, + {0x0, 12, 14, 5764}, + {0x0, 2, 3, 5766}, + {0xcca, 16, 16, 5767}, + {0x0, 8, 9, 5767}, + {0x2f865, 16, 16, 5768}, + {0x1e31, 16, 16, 5768}, + {0x0, 3, 4, 5768}, + {0x0, 10, 11, 5769}, + {0x2f80d, 16, 16, 5770}, + {0x0, 2, 8, 5770}, + {0x2f817, 16, 16, 5776}, + {0x2f8d2, 16, 16, 5776}, + {0x2f9e3, 16, 16, 5776}, + {0x0, 0, 2, 5776}, + {0x1f3c, 16, 16, 5778}, + {0x1f3a, 16, 16, 5778}, + {0x0, 6, 8, 5778}, + {0xb48, 16, 16, 5780}, + {0xb4c, 16, 16, 5780}, + {0x0, 0, 1, 5780}, + {0x0, 0, 1, 5781}, + {0x0, 3, 4, 5782}, + {0x0, 3, 4, 5783}, + {0x0, 8, 9, 5784}, + {0x2280, 16, 16, 5785}, + {0x0, 0, 1, 5785}, + {0x0, 3, 4, 5786}, + {0x0, 0, 1, 5787}, + {0x0, 9, 10, 5788}, + {0x0, 9, 10, 5789}, + {0x30f4, 16, 16, 5790}, + {0x0, 6, 8, 5790}, + {0xf9b2, 16, 16, 5792}, + {0x0, 3, 8, 5792}, + {0x1e5b, 16, 16, 5797}, + {0x0, 0, 1, 5797}, + {0x0, 0, 1, 5798}, + {0x0, 3, 4, 5799}, + {0x0, 0, 1, 5800}, + {0x0, 8, 9, 5801}, + {0x4f5, 16, 16, 5802}, + {0x157, 16, 16, 5802}, + {0x0, 9, 10, 5802}, + {0x2f9c2, 16, 16, 5803}, + {0x0, 5, 6, 5803}, + {0x2f988, 16, 16, 5804}, + {0x0, 0, 1, 5804}, + {0x0, 0, 1, 5805}, + {0x0, 3, 4, 5806}, + {0x0, 0, 1, 5807}, + {0x0, 0, 9, 5808}, + {0x40d, 16, 16, 5817}, + {0x0, 0, 1, 5817}, + {0x0, 0, 1, 5818}, + {0x0, 3, 4, 5819}, + {0x0, 0, 1, 5820}, + {0x0, 1, 8, 5821}, + {0x1e56, 16, 16, 5828}, + {0x1e54, 16, 16, 5828}, + {0x0, 2, 9, 5828}, + {0x2f83e, 16, 16, 5835}, + {0x0, 0, 1, 5835}, + {0x0, 0, 1, 5836}, + {0x0, 3, 4, 5837}, + {0x0, 4, 5, 5838}, + {0x0, 5, 6, 5839}, + {0x1fa2, 16, 16, 5840}, + {0xf980, 16, 16, 5840}, + {0x0, 10, 11, 5840}, + {0x0, 7, 8, 5841}, + {0x2f8f0, 16, 16, 5842}, + {0x0, 14, 15, 5842}, + {0xd4a, 16, 16, 5843}, + {0x0, 6, 15, 5843}, + {0x2f8ff, 16, 16, 5852}, + {0x0, 0, 1, 5852}, + {0x0, 0, 1, 5853}, + {0x0, 3, 4, 5854}, + {0x0, 0, 3, 5855}, + {0x0, 3, 4, 5858}, + {0x1e89, 16, 16, 5859}, + {0x0, 0, 1, 5859}, + {0x0, 0, 1, 5860}, + {0x0, 9, 10, 5861}, + {0x0, 3, 4, 5862}, + {0x0, 12, 13, 5863}, + {0x934, 16, 16, 5864}, + {0x0, 2, 3, 5864}, + {0x2f8ac, 16, 16, 5865}, + {0x0, 4, 5, 5865}, + {0x2f9ac, 16, 16, 5866}, + {0x0, 11, 12, 5866}, + {0x2f816, 16, 16, 5867}, + {0x0, 14, 15, 5867}, + {0x2f911, 16, 16, 5868}, + {0x0, 8, 9, 5868}, + {0x0, 6, 7, 5869}, + {0x2f96b, 16, 16, 5870}, + {0x1e15, 16, 16, 5870}, + {0x0, 3, 4, 5870}, + {0x1e05, 16, 16, 5871}, + {0x0, 8, 9, 5871}, + {0x2f93f, 16, 16, 5872}, + {0x0, 8, 9, 5872}, + {0x2f8d0, 16, 16, 5873}, + {0x0, 0, 1, 5873}, + {0x0, 0, 1, 5874}, + {0x0, 6, 7, 5875}, + {0x0, 5, 6, 5876}, + {0x0, 4, 5, 5877}, + {0x6d3, 16, 16, 5878}, + {0x0, 1, 2, 5878}, + {0x1e0e, 16, 16, 5879}, + {0x0, 7, 10, 5879}, + {0xfa33, 16, 16, 5882}, + {0x0, 0, 1, 5882}, + {0x0, 0, 1, 5883}, + {0x0, 3, 4, 5884}, + {0x0, 3, 4, 5885}, + {0x0, 8, 9, 5886}, + {0x2279, 16, 16, 5887}, + {0x0, 2, 12, 5887}, + {0x0, 1, 2, 5897}, + {0x2f9b0, 16, 16, 5898}, + {0x0, 0, 1, 5898}, + {0xfa39, 16, 16, 5899}, + {0x2f825, 16, 16, 5899}, + {0x0, 3, 4, 5899}, + {0x2f983, 16, 16, 5900}, + {0xfa05, 16, 16, 5900}, + {0x0, 9, 10, 5900}, + {0xf916, 16, 16, 5901}, + {0xf915, 16, 16, 5901}, + {0x0, 12, 13, 5901}, + {0xf908, 16, 16, 5902}, + {0x0, 9, 13, 5902}, + {0xf955, 16, 16, 5906}, + {0x0, 14, 15, 5906}, + {0xf9e1, 16, 16, 5907}, + {0x2f8d3, 16, 16, 5907}, + {0x0, 8, 9, 5907}, + {0x2f93c, 16, 16, 5908}, + {0x0, 0, 1, 5908}, + {0x0, 0, 1, 5909}, + {0x0, 3, 4, 5910}, + {0x0, 0, 3, 5911}, + {0x0, 2, 13, 5914}, + {0x21e, 16, 16, 5925}, + {0x0, 0, 1, 5925}, + {0x0, 0, 1, 5926}, + {0x0, 3, 4, 5927}, + {0x0, 0, 1, 5928}, + {0x0, 6, 9, 5929}, + {0x4d0, 16, 16, 5932}, + {0x0, 6, 7, 5932}, + {0x0, 6, 7, 5933}, + {0x2f9cc, 16, 16, 5934}, + {0x0, 10, 11, 5934}, + {0xf985, 16, 16, 5935}, + {0x4d2, 16, 16, 5935}, + {0x0, 3, 4, 5935}, + {0x2f99a, 16, 16, 5936}, + {0x1fd3, 16, 16, 5936}, + {0x0, 4, 6, 5936}, + {0x0, 0, 1, 5938}, + {0x0, 0, 1, 5939}, + {0x0, 3, 4, 5940}, + {0x0, 0, 1, 5941}, + {0x0, 15, 16, 5942}, + {0x477, 16, 16, 5943}, + {0x1e26, 16, 16, 5943}, + {0x1e22, 16, 16, 5943}, + {0x124, 16, 16, 5943}, + {0xf979, 16, 16, 5943}, + {0x0, 0, 1, 5943}, + {0x2f93a, 16, 16, 5944}, + {0xfa49, 16, 16, 5944}, + {0x0, 8, 9, 5944}, + {0xf900, 16, 16, 5945}, + {0x0, 4, 5, 5945}, + {0xf924, 16, 16, 5946}, + {0x1f23, 16, 16, 5946}, + {0x0, 5, 6, 5946}, + {0x2f925, 16, 16, 5947}, + {0x0, 4, 13, 5947}, + {0x2f818, 16, 16, 5956}, + {0x0, 10, 11, 5956}, + {0x2f979, 16, 16, 5957}, + {0x0, 0, 1, 5957}, + {0x0, 0, 1, 5958}, + {0x0, 3, 4, 5959}, + {0x0, 0, 1, 5960}, + {0x0, 2, 3, 5961}, + {0x1ec6, 16, 16, 5962}, + {0x0, 2, 3, 5962}, + {0x2f895, 16, 16, 5963}, + {0x0, 6, 7, 5963}, + {0x0, 0, 1, 5964}, + {0x0, 0, 1, 5965}, + {0x0, 3, 4, 5966}, + {0x0, 0, 1, 5967}, + {0x0, 8, 9, 5968}, + {0x407, 16, 16, 5969}, + {0xf949, 16, 16, 5969}, + {0x0, 0, 10, 5969}, + {0x1eed, 16, 16, 5979}, + {0x0, 5, 12, 5979}, + {0x2f839, 16, 16, 5986}, + {0x1eeb, 16, 16, 5986}, + {0x1ee9, 16, 16, 5986}, + {0x0, 3, 5, 5986}, + {0x1f38, 16, 16, 5988}, + {0x1eef, 16, 16, 5988}, + {0x1f39, 16, 16, 5988}, + {0x0, 0, 10, 5988}, + {0x2f962, 16, 16, 5998}, + {0xfa56, 16, 16, 5998}, + {0x0, 3, 4, 5998}, + {0x2f87c, 16, 16, 5999}, + {0x2f963, 16, 16, 5999}, + {0x0, 0, 1, 5999}, + {0x0, 0, 1, 6000}, + {0x0, 3, 4, 6001}, + {0x0, 0, 1, 6002}, + {0x0, 1, 5, 6003}, + {0x1e2, 16, 16, 6007}, + {0x1fc, 16, 16, 6007}, + {0x0, 7, 8, 6007}, + {0xf9f2, 16, 16, 6008}, + {0xf906, 16, 16, 6008}, + {0x0, 13, 14, 6008}, + {0x2f886, 16, 16, 6009}, + {0x0, 15, 16, 6009}, + {0xf927, 16, 16, 6010}, + {0x0, 12, 13, 6010}, + {0x2f92a, 16, 16, 6011}, + {0x0, 3, 5, 6011}, + {0x1f40, 16, 16, 6013}, + {0x1f41, 16, 16, 6013}, + {0x0, 0, 16, 6013}, + {0xfa, 16, 16, 6029}, + {0xf9, 16, 16, 6029}, + {0x169, 16, 16, 6029}, + {0xfb, 16, 16, 6029}, + {0x16b, 16, 16, 6029}, + {0x0, 3, 14, 6029}, + {0x1ee4, 16, 16, 6040}, + {0x16d, 16, 16, 6040}, + {0x1ee7, 16, 16, 6040}, + {0xfc, 16, 16, 6040}, + {0x0, 0, 1, 6040}, + {0x0, 3, 4, 6041}, + {0x0, 0, 1, 6042}, + {0x0, 9, 10, 6043}, + {0x0, 9, 10, 6044}, + {0x3062, 16, 16, 6045}, + {0x172, 16, 16, 6045}, + {0x0, 0, 1, 6045}, + {0x0, 0, 1, 6046}, + {0x0, 3, 4, 6047}, + {0x0, 0, 1, 6048}, + {0x0, 7, 8, 6049}, + {0x1e65, 16, 16, 6050}, + {0x0, 1, 13, 6050}, + {0x161, 16, 16, 6062}, + {0x0, 9, 13, 6062}, + {0x2f9a1, 16, 16, 6066}, + {0x0, 0, 1, 6066}, + {0x0, 0, 1, 6067}, + {0x0, 3, 4, 6068}, + {0x0, 0, 1, 6069}, + {0x0, 0, 13, 6070}, + {0x1da, 16, 16, 6083}, + {0x0, 0, 1, 6083}, + {0x0, 0, 1, 6084}, + {0x0, 3, 4, 6085}, + {0x0, 0, 4, 6086}, + {0x0, 1, 13, 6090}, + {0x13a, 16, 16, 6102}, + {0x16f, 16, 16, 6102}, + {0x1e76, 16, 16, 6102}, + {0x0, 0, 1, 6102}, + {0x0, 0, 1, 6103}, + {0x0, 3, 4, 6104}, + {0x0, 3, 4, 6105}, + {0x0, 8, 9, 6106}, + {0x219b, 16, 16, 6107}, + {0x171, 16, 16, 6107}, + {0x215, 16, 16, 6107}, + {0x0, 0, 1, 6107}, + {0x0, 3, 4, 6108}, + {0x0, 0, 1, 6109}, + {0x0, 9, 10, 6110}, + {0x0, 9, 10, 6111}, + {0x3050, 16, 16, 6112}, + {0x0, 10, 11, 6112}, + {0x0, 7, 8, 6113}, + {0x2f95e, 16, 16, 6114}, + {0x0, 2, 3, 6114}, + {0x2f9ba, 16, 16, 6115}, + {0x0, 14, 15, 6115}, + {0xfa30, 16, 16, 6116}, + {0x0, 10, 11, 6116}, + {0x2f861, 16, 16, 6117}, + {0x13e, 16, 16, 6117}, + {0x1dc, 16, 16, 6117}, + {0x1d8, 16, 16, 6117}, + {0x1d6, 16, 16, 6117}, + {0x0, 2, 3, 6117}, + {0x1fd7, 16, 16, 6118}, + {0x0, 1, 2, 6118}, + {0x0, 4, 5, 6119}, + {0x2f927, 16, 16, 6120}, + {0x15d, 16, 16, 6120}, + {0x15b, 16, 16, 6120}, + {0x1e61, 16, 16, 6120}, + {0x0, 3, 5, 6120}, + {0x1f49, 16, 16, 6122}, + {0x0, 0, 1, 6122}, + {0x0, 3, 4, 6123}, + {0x0, 0, 1, 6124}, + {0x0, 9, 10, 6125}, + {0x0, 9, 10, 6126}, + {0x30c5, 16, 16, 6127}, + {0xf93e, 16, 16, 6127}, + {0x0, 0, 14, 6127}, + {0x0, 4, 5, 6141}, + {0x2f9d9, 16, 16, 6142}, + {0x0, 13, 14, 6142}, + {0x2f8b4, 16, 16, 6143}, + {0x1f48, 16, 16, 6143}, + {0x0, 8, 9, 6143}, + {0xf9e2, 16, 16, 6144}, + {0x0, 3, 9, 6144}, + {0x1eca, 16, 16, 6150}, + {0x12e, 16, 16, 6150}, + {0x0, 0, 9, 6150}, + {0x1f7a, 16, 16, 6159}, + {0x3cd, 16, 16, 6159}, + {0x1fe1, 16, 16, 6159}, + {0x0, 1, 2, 6159}, + {0x1e35, 16, 16, 6160}, + {0x1fe0, 16, 16, 6160}, + {0x0, 0, 1, 6160}, + {0x0, 3, 4, 6161}, + {0x0, 0, 1, 6162}, + {0x0, 9, 10, 6163}, + {0x0, 9, 11, 6164}, + {0x3074, 16, 16, 6166}, + {0x3cb, 16, 16, 6166}, + {0x0, 3, 4, 6166}, + {0xf99d, 16, 16, 6167}, + {0x0, 0, 1, 6167}, + {0x0, 0, 1, 6168}, + {0x0, 3, 4, 6169}, + {0x0, 0, 1, 6170}, + {0x0, 8, 9, 6171}, + {0x4e7, 16, 16, 6172}, + {0x1f3b, 16, 16, 6172}, + {0x0, 0, 1, 6172}, + {0x0, 0, 1, 6173}, + {0x0, 3, 4, 6174}, + {0x0, 4, 5, 6175}, + {0x0, 5, 6, 6176}, + {0x1f92, 16, 16, 6177}, + {0x0, 2, 4, 6177}, + {0xfa42, 16, 16, 6179}, + {0x0, 1, 2, 6179}, + {0x1e5f, 16, 16, 6180}, + {0x0, 0, 1, 6180}, + {0x0, 0, 1, 6181}, + {0x0, 3, 4, 6182}, + {0x0, 3, 4, 6183}, + {0x0, 8, 9, 6184}, + {0x22ed, 16, 16, 6185}, + {0x0, 2, 6, 6185}, + {0x1ff6, 16, 16, 6189}, + {0x1ff3, 16, 16, 6189}, + {0x0, 9, 11, 6189}, + {0xf92a, 16, 16, 6191}, + {0x0, 0, 1, 6191}, + {0x0, 0, 1, 6192}, + {0x0, 3, 4, 6193}, + {0x0, 0, 5, 6194}, + {0x0, 2, 6, 6199}, + {0x1fa0, 16, 16, 6203}, + {0x0, 4, 5, 6203}, + {0xf9b7, 16, 16, 6204}, + {0x1f66, 16, 16, 6204}, + {0x3073, 16, 16, 6204}, + {0x0, 2, 8, 6204}, + {0x2f823, 16, 16, 6210}, + {0x0, 12, 13, 6210}, + {0x2f862, 16, 16, 6211}, + {0x2f822, 16, 16, 6211}, + {0x0, 2, 3, 6211}, + {0xf9e5, 16, 16, 6212}, + {0x2f903, 16, 16, 6212}, + {0x0, 11, 12, 6212}, + {0x2f957, 16, 16, 6213}, + {0x0, 11, 12, 6213}, + {0xf98a, 16, 16, 6214}, + {0x0, 9, 10, 6214}, + {0x2f9bb, 16, 16, 6215}, + {0x0, 0, 1, 6215}, + {0x0, 0, 1, 6216}, + {0x0, 3, 4, 6217}, + {0x0, 0, 1, 6218}, + {0x0, 15, 16, 6219}, + {0x476, 16, 16, 6220}, + {0x0, 0, 1, 6220}, + {0x0, 0, 1, 6221}, + {0x0, 3, 4, 6222}, + {0x0, 0, 1, 6223}, + {0x0, 8, 9, 6224}, + {0x4eb, 16, 16, 6225}, + {0x0, 1, 6, 6225}, + {0xfa5b, 16, 16, 6230}, + {0xf934, 16, 16, 6230}, + {0x0, 0, 10, 6230}, + {0x0, 0, 1, 6240}, + {0x0, 0, 1, 6241}, + {0x0, 3, 4, 6242}, + {0x0, 0, 1, 6243}, + {0x0, 0, 2, 6244}, + {0x1f14, 16, 16, 6246}, + {0x1f12, 16, 16, 6246}, + {0x0, 3, 14, 6246}, + {0x1e0c, 16, 16, 6257}, + {0x1e10, 16, 16, 6257}, + {0x1ffb, 16, 16, 6257}, + {0x1feb, 16, 16, 6257}, + {0x1ff9, 16, 16, 6257}, + {0x1fdb, 16, 16, 6257}, + {0x0, 3, 4, 6257}, + {0x2f992, 16, 16, 6258}, + {0x0, 0, 1, 6258}, + {0x0, 3, 4, 6259}, + {0x0, 0, 1, 6260}, + {0x0, 9, 10, 6261}, + {0x0, 9, 10, 6262}, + {0x30b6, 16, 16, 6263}, + {0x0, 0, 1, 6263}, + {0x0, 0, 1, 6264}, + {0x0, 3, 4, 6265}, + {0x0, 0, 4, 6266}, + {0x0, 3, 14, 6270}, + {0x1e36, 16, 16, 6281}, + {0x13b, 16, 16, 6281}, + {0x1e12, 16, 16, 6281}, + {0x0, 1, 2, 6281}, + {0x0, 14, 15, 6282}, + {0x2f906, 16, 16, 6283}, + {0x0, 0, 1, 6283}, + {0x0, 0, 1, 6284}, + {0x0, 3, 4, 6285}, + {0x0, 0, 1, 6286}, + {0x0, 8, 9, 6287}, + {0x4ed, 16, 16, 6288}, + {0x2f8dc, 16, 16, 6288}, + {0x0, 6, 7, 6288}, + {0x0, 3, 4, 6289}, + {0x2f91d, 16, 16, 6290}, + {0x1e3c, 16, 16, 6290}, + {0x1fbb, 16, 16, 6290}, + {0x1fee, 16, 16, 6290}, + {0x0, 14, 15, 6290}, + {0x2fa08, 16, 16, 6291}, + {0x1fc9, 16, 16, 6291}, + {0x0, 0, 1, 6291}, + {0x0, 0, 1, 6292}, + {0x0, 13, 14, 6293}, + {0x0, 3, 4, 6294}, + {0x0, 14, 15, 6295}, + {0xd4b, 16, 16, 6296}, + {0x0, 6, 7, 6296}, + {0x2fa1b, 16, 16, 6297}, + {0x0, 7, 8, 6297}, + {0x2f896, 16, 16, 6298}, + {0xf97a, 16, 16, 6298}, + {0x0, 1, 13, 6298}, + {0x17d, 16, 16, 6310}, + {0x0, 4, 5, 6310}, + {0xfa57, 16, 16, 6311}, + {0x0, 8, 9, 6311}, + {0xf972, 16, 16, 6312}, + {0x0, 0, 1, 6312}, + {0x0, 0, 1, 6313}, + {0x0, 3, 4, 6314}, + {0x0, 3, 4, 6315}, + {0x0, 8, 9, 6316}, + {0x226f, 16, 16, 6317}, + {0x0, 0, 1, 6317}, + {0x0, 0, 1, 6318}, + {0x0, 3, 4, 6319}, + {0x0, 0, 1, 6320}, + {0x0, 0, 13, 6321}, + {0x1d5, 16, 16, 6334}, + {0x0, 6, 7, 6334}, + {0x0, 7, 8, 6335}, + {0x2f9c5, 16, 16, 6336}, + {0x0, 0, 1, 6336}, + {0x0, 0, 1, 6337}, + {0x0, 3, 4, 6338}, + {0x0, 4, 5, 6339}, + {0x0, 5, 6, 6340}, + {0x1fb7, 16, 16, 6341}, + {0x1db, 16, 16, 6341}, + {0x1d7, 16, 16, 6341}, + {0x0, 3, 14, 6341}, + {0x1e71, 16, 16, 6352}, + {0x0, 0, 1, 6352}, + {0x2f924, 16, 16, 6353}, + {0x0, 0, 1, 6353}, + {0x0, 0, 1, 6354}, + {0x0, 3, 4, 6355}, + {0x0, 3, 4, 6356}, + {0x0, 8, 9, 6357}, + {0x2247, 16, 16, 6358}, + {0x0, 5, 6, 6358}, + {0x0, 6, 7, 6359}, + {0x2fa16, 16, 16, 6360}, + {0x0, 0, 1, 6360}, + {0x0, 0, 1, 6361}, + {0x0, 3, 4, 6362}, + {0x0, 4, 5, 6363}, + {0x0, 5, 6, 6364}, + {0x1f8a, 16, 16, 6365}, + {0x0, 14, 15, 6365}, + {0x2fa0d, 16, 16, 6366}, + {0x0, 1, 2, 6366}, + {0x2f8a0, 16, 16, 6367}, + {0x2f8e4, 16, 16, 6367}, + {0x0, 9, 10, 6367}, + {0x2f8cd, 16, 16, 6368}, + {0x0, 5, 10, 6368}, + {0x2f8d7, 16, 16, 6373}, + {0x1e90, 16, 16, 6373}, + {0x179, 16, 16, 6373}, + {0x2f981, 16, 16, 6373}, + {0x17b, 16, 16, 6373}, + {0x21b, 16, 16, 6373}, + {0x163, 16, 16, 6373}, + {0xfa4c, 16, 16, 6373}, + {0x1e6d, 16, 16, 6373}, + {0x37e, 16, 16, 6373}, + {0x1d9, 16, 16, 6373}, + {0x0, 0, 1, 6373}, + {0x0, 3, 4, 6374}, + {0x0, 0, 1, 6375}, + {0x0, 9, 10, 6376}, + {0x0, 9, 11, 6377}, + {0x30d7, 16, 16, 6379}, + {0x0, 0, 1, 6379}, + {0x0, 3, 4, 6380}, + {0x0, 0, 1, 6381}, + {0x0, 9, 10, 6382}, + {0x0, 9, 10, 6383}, + {0x3060, 16, 16, 6384}, + {0x0, 2, 6, 6384}, + {0x1f91, 16, 16, 6388}, + {0x1e16, 16, 16, 6388}, + {0x1f27, 16, 16, 6388}, + {0x0, 7, 8, 6388}, + {0x2f89e, 16, 16, 6389}, + {0x0, 9, 10, 6389}, + {0x2f8c3, 16, 16, 6390}, + {0x0, 1, 2, 6390}, + {0x2f83a, 16, 16, 6391}, + {0x0, 12, 13, 6391}, + {0x2f880, 16, 16, 6392}, + {0x2f989, 16, 16, 6392}, + {0xd1, 16, 16, 6392}, + {0x1f8, 16, 16, 6392}, + {0x143, 16, 16, 6392}, + {0x1e44, 16, 16, 6392}, + {0x0, 11, 12, 6392}, + {0x2f98e, 16, 16, 6393}, + {0x0, 11, 12, 6393}, + {0x2f933, 16, 16, 6394}, + {0x0, 10, 11, 6394}, + {0xf99b, 16, 16, 6395}, + {0x0, 0, 1, 6395}, + {0x1e75, 16, 16, 6396}, + {0x0, 0, 1, 6396}, + {0x0, 0, 1, 6397}, + {0x0, 3, 4, 6398}, + {0x0, 4, 5, 6399}, + {0x0, 5, 6, 6400}, + {0x1f8d, 16, 16, 6401}, + {0x30d6, 16, 16, 6401}, + {0x1f2b, 16, 16, 6401}, + {0x0, 2, 3, 6401}, + {0xf9ad, 16, 16, 6402}, + {0xf95d, 16, 16, 6402}, + {0x0, 0, 1, 6402}, + {0x0, 0, 1, 6403}, + {0x0, 3, 4, 6404}, + {0x0, 0, 3, 6405}, + {0x0, 3, 4, 6408}, + {0x1e7c, 16, 16, 6409}, + {0x0, 3, 4, 6409}, + {0x0, 14, 15, 6410}, + {0x2f977, 16, 16, 6411}, + {0x0, 0, 1, 6411}, + {0x0, 3, 4, 6412}, + {0x0, 0, 1, 6413}, + {0x0, 9, 10, 6414}, + {0x0, 9, 10, 6415}, + {0x305e, 16, 16, 6416}, + {0x0, 0, 1, 6416}, + {0x2f842, 16, 16, 6417}, + {0x0, 3, 4, 6417}, + {0x2f90a, 16, 16, 6418}, + {0x0, 0, 9, 6418}, + {0x38e, 16, 16, 6427}, + {0x0, 0, 1, 6427}, + {0xf9ee, 16, 16, 6428}, + {0x0, 15, 16, 6428}, + {0x2f80b, 16, 16, 6429}, + {0x0, 10, 11, 6429}, + {0xf919, 16, 16, 6430}, + {0xf912, 16, 16, 6430}, + {0x0, 13, 14, 6430}, + {0x0, 10, 11, 6431}, + {0x2f898, 16, 16, 6432}, + {0x211, 16, 16, 6432}, + {0x159, 16, 16, 6432}, + {0x0, 12, 13, 6432}, + {0xfa2b, 16, 16, 6433}, + {0x0, 10, 11, 6433}, + {0xf9bb, 16, 16, 6434}, + {0x0, 0, 1, 6434}, + {0x0, 0, 1, 6435}, + {0x0, 3, 4, 6436}, + {0x0, 4, 5, 6437}, + {0x0, 5, 6, 6438}, + {0x1f83, 16, 16, 6439}, + {0x1ff8, 16, 16, 6439}, + {0x0, 11, 12, 6439}, + {0x2f9d4, 16, 16, 6440}, + {0x0, 1, 12, 6440}, + {0x216, 16, 16, 6451}, + {0x0, 0, 1, 6451}, + {0x0, 0, 1, 6452}, + {0x0, 3, 4, 6453}, + {0x0, 0, 1, 6454}, + {0x0, 4, 5, 6455}, + {0x1e0, 16, 16, 6456}, + {0x0, 0, 16, 6456}, + {0x0, 6, 7, 6472}, + {0xfa37, 16, 16, 6473}, + {0x0, 0, 1, 6473}, + {0x0, 0, 1, 6474}, + {0x0, 3, 4, 6475}, + {0x0, 3, 4, 6476}, + {0x0, 8, 9, 6477}, + {0x22e3, 16, 16, 6478}, + {0x0, 0, 2, 6478}, + {0x1f6a, 16, 16, 6480}, + {0x1f6c, 16, 16, 6480}, + {0x137, 16, 16, 6480}, + {0x0, 3, 5, 6480}, + {0x1f51, 16, 16, 6482}, + {0x1f50, 16, 16, 6482}, + {0x0, 1, 2, 6482}, + {0x0, 5, 6, 6483}, + {0x2f9ec, 16, 16, 6484}, + {0x0, 14, 15, 6484}, + {0x2f8c2, 16, 16, 6485}, + {0x0, 13, 14, 6485}, + {0x2f99d, 16, 16, 6486}, + {0x1af, 16, 16, 6486}, + {0x0, 9, 10, 6486}, + {0xf9c7, 16, 16, 6487}, + {0x1e59, 16, 16, 6487}, + {0x4d3, 16, 16, 6487}, + {0x0, 0, 1, 6487}, + {0x0, 0, 1, 6488}, + {0x0, 3, 4, 6489}, + {0x0, 0, 1, 6490}, + {0x0, 7, 8, 6491}, + {0x1e1f, 16, 16, 6492}, + {0x0, 7, 8, 6492}, + {0x2f9bf, 16, 16, 6493}, + {0x0, 2, 5, 6493}, + {0xf73, 16, 16, 6496}, + {0xf75, 16, 16, 6496}, + {0x0, 8, 9, 6496}, + {0x2f83f, 16, 16, 6497}, + {0x0, 3, 5, 6497}, + {0x1f30, 16, 16, 6499}, + {0x1f31, 16, 16, 6499}, + {0x0, 15, 16, 6499}, + {0xf913, 16, 16, 6500}, + {0x0, 0, 11, 6500}, + {0x1e87, 16, 16, 6511}, + {0x0, 0, 2, 6511}, + {0x1fcd, 16, 16, 6513}, + {0x1fce, 16, 16, 6513}, + {0x175, 16, 16, 6513}, + {0x1e83, 16, 16, 6513}, + {0x1e81, 16, 16, 6513}, + {0x0, 12, 13, 6513}, + {0x2f8b8, 16, 16, 6514}, + {0x0, 5, 6, 6514}, + {0x1ffc, 16, 16, 6515}, + {0xfa45, 16, 16, 6515}, + {0x1e85, 16, 16, 6515}, + {0x0, 3, 9, 6515}, + {0x1ecc, 16, 16, 6521}, + {0x0, 0, 1, 6521}, + {0x0, 0, 1, 6522}, + {0x0, 11, 12, 6523}, + {0x0, 11, 12, 6524}, + {0x0, 14, 15, 6525}, + {0xbcb, 16, 16, 6526}, + {0x1ea, 16, 16, 6526}, + {0x0, 0, 1, 6526}, + {0x0, 0, 1, 6527}, + {0x0, 3, 4, 6528}, + {0x0, 3, 4, 6529}, + {0x0, 8, 9, 6530}, + {0x22ac, 16, 16, 6531}, + {0x0, 1, 2, 6531}, + {0x0, 10, 11, 6532}, + {0x2f9f7, 16, 16, 6533}, + {0x0, 12, 13, 6533}, + {0xf956, 16, 16, 6534}, + {0x0, 0, 1, 6534}, + {0x0, 0, 1, 6535}, + {0x0, 3, 4, 6536}, + {0x0, 0, 1, 6537}, + {0x0, 8, 9, 6538}, + {0x4f8, 16, 16, 6539}, + {0x0, 12, 16, 6539}, + {0xf9e9, 16, 16, 6543}, + {0xf97e, 16, 16, 6543}, + {0x0, 14, 15, 6543}, + {0x2f8af, 16, 16, 6544}, + {0x21f, 16, 16, 6544}, + {0x1e98, 16, 16, 6544}, + {0x0, 1, 2, 6544}, + {0x1e3a, 16, 16, 6545}, + {0x0, 7, 8, 6545}, + {0x9cc, 16, 16, 6546}, + {0x0, 3, 15, 6546}, + {0x1e2a, 16, 16, 6558}, + {0x0, 5, 16, 6558}, + {0x2fa1a, 16, 16, 6569}, + {0x2f81a, 16, 16, 6569}, + {0x0, 7, 12, 6569}, + {0x2f929, 16, 16, 6574}, + {0x0, 2, 16, 6574}, + {0xf94f, 16, 16, 6588}, + {0x0, 14, 15, 6588}, + {0xf920, 16, 16, 6589}, + {0x0, 10, 11, 6589}, + {0x0, 14, 15, 6590}, + {0x2f9cb, 16, 16, 6591}, + {0xf9a0, 16, 16, 6591}, + {0x1e28, 16, 16, 6591}, + {0x0, 1, 2, 6591}, + {0x2f8da, 16, 16, 6592}, + {0x1e24, 16, 16, 6592}, + {0x2fa19, 16, 16, 6592}, + {0xf9db, 16, 16, 6592}, + {0x0, 0, 1, 6592}, + {0x0, 0, 1, 6593}, + {0x0, 3, 4, 6594}, + {0x0, 0, 3, 6595}, + {0x0, 7, 8, 6598}, + {0x122, 16, 16, 6599}, + {0x0, 0, 2, 6599}, + {0x1f2a, 16, 16, 6601}, + {0x1f2c, 16, 16, 6601}, + {0x0, 0, 1, 6601}, + {0x0, 0, 1, 6602}, + {0x0, 3, 4, 6603}, + {0x0, 4, 5, 6604}, + {0x0, 5, 6, 6605}, + {0x1f93, 16, 16, 6606}, + {0x0, 14, 15, 6606}, + {0xbca, 16, 16, 6607}, + {0x0, 6, 7, 6607}, + {0x2f912, 16, 16, 6608}, + {0x0, 5, 6, 6608}, + {0x2f9f6, 16, 16, 6609}, + {0x0, 3, 4, 6609}, + {0x2f8dd, 16, 16, 6610}, + {0xf96a, 16, 16, 6610}, + {0x0, 14, 15, 6610}, + {0x2f90f, 16, 16, 6611}, + {0x0, 9, 10, 6611}, + {0x374, 16, 16, 6612}, + {0x0, 6, 11, 6612}, + {0xf998, 16, 16, 6617}, + {0x0, 4, 5, 6617}, + {0xfa3d, 16, 16, 6618}, + {0x0, 2, 6, 6618}, + {0x1f26, 16, 16, 6622}, + {0x0, 7, 15, 6622}, + {0x2f8c4, 16, 16, 6630}, + {0x0, 0, 1, 6630}, + {0x2f922, 16, 16, 6631}, + {0x0, 1, 2, 6631}, + {0xf96d, 16, 16, 6632}, + {0x0, 1, 2, 6632}, + {0x1e6f, 16, 16, 6633}, + {0x0, 0, 1, 6633}, + {0x0, 0, 1, 6634}, + {0x0, 3, 4, 6635}, + {0x0, 4, 5, 6636}, + {0x0, 5, 6, 6637}, + {0x1fa4, 16, 16, 6638}, + {0x0, 0, 1, 6638}, + {0x0, 0, 1, 6639}, + {0x0, 3, 4, 6640}, + {0x0, 0, 4, 6641}, + {0x0, 1, 13, 6645}, + {0x17e, 16, 16, 6657}, + {0x1f90, 16, 16, 6657}, + {0x0, 0, 2, 6657}, + {0x1f5b, 16, 16, 6659}, + {0x1f5d, 16, 16, 6659}, + {0x0, 5, 6, 6659}, + {0xfa04, 16, 16, 6660}, + {0x1f6e, 16, 16, 6660}, + {0x0, 0, 1, 6660}, + {0x0, 0, 1, 6661}, + {0x0, 3, 4, 6662}, + {0x0, 0, 3, 6663}, + {0x0, 1, 13, 6666}, + {0x11f, 16, 16, 6678}, + {0x121, 16, 16, 6678}, + {0x1e21, 16, 16, 6678}, + {0x11d, 16, 16, 6678}, + {0x1f5, 16, 16, 6678}, + {0x0, 3, 4, 6678}, + {0x2f8bc, 16, 16, 6679}, + {0x17c, 16, 16, 6679}, + {0x17a, 16, 16, 6679}, + {0x1e91, 16, 16, 6679}, + {0x0, 1, 2, 6679}, + {0x2f8b5, 16, 16, 6680}, + {0xf9d7, 16, 16, 6680}, + {0x2f8c6, 16, 16, 6680}, + {0x1e7, 16, 16, 6680}, + {0x0, 4, 5, 6680}, + {0xf943, 16, 16, 6681}, + {0x0, 0, 1, 6681}, + {0x0, 0, 1, 6682}, + {0x0, 3, 4, 6683}, + {0x0, 0, 1, 6684}, + {0x0, 0, 10, 6685}, + {0x1ed7, 16, 16, 6695}, + {0x0, 0, 1, 6695}, + {0x0, 0, 1, 6696}, + {0x0, 3, 4, 6697}, + {0x0, 4, 5, 6698}, + {0x0, 5, 6, 6699}, + {0x1f8f, 16, 16, 6700}, + {0x1ed1, 16, 16, 6700}, + {0x1ed3, 16, 16, 6700}, + {0x0, 2, 14, 6700}, + {0xf95e, 16, 16, 6712}, + {0x2f801, 16, 16, 6712}, + {0x1ed5, 16, 16, 6712}, + {0xf905, 16, 16, 6712}, + {0x0, 0, 2, 6712}, + {0x1f6d, 16, 16, 6714}, + {0x1f6b, 16, 16, 6714}, + {0x0, 10, 11, 6714}, + {0x2f808, 16, 16, 6715}, + {0x0, 15, 16, 6715}, + {0x0, 0, 1, 6716}, + {0x0, 0, 1, 6717}, + {0x0, 12, 13, 6718}, + {0x0, 13, 14, 6719}, + {0x0, 5, 6, 6720}, + {0xcc0, 16, 16, 6721}, + {0x0, 0, 16, 6721}, + {0x214, 16, 16, 6737}, + {0x0, 11, 12, 6737}, + {0xf953, 16, 16, 6738}, + {0x1d3, 16, 16, 6738}, + {0x170, 16, 16, 6738}, + {0x16e, 16, 16, 6738}, + {0x0, 3, 14, 6738}, + {0x1e77, 16, 16, 6749}, + {0x0, 3, 14, 6749}, + {0x13c, 16, 16, 6760}, + {0x1e37, 16, 16, 6760}, + {0x0, 0, 1, 6760}, + {0x0, 0, 1, 6761}, + {0x0, 3, 4, 6762}, + {0x0, 1, 2, 6763}, + {0x0, 4, 5, 6764}, + {0x1fec, 16, 16, 6765}, + {0x0, 14, 15, 6765}, + {0x0, 4, 5, 6766}, + {0x2f859, 16, 16, 6767}, + {0x2f800, 16, 16, 6767}, + {0x1e3d, 16, 16, 6767}, + {0x0, 0, 1, 6767}, + {0x0, 3, 4, 6768}, + {0x0, 0, 1, 6769}, + {0x0, 9, 10, 6770}, + {0x0, 9, 10, 6771}, + {0x304e, 16, 16, 6772}, + {0x0, 11, 15, 6772}, + {0x2f87e, 16, 16, 6776}, + {0x2f8cb, 16, 16, 6776}, + {0x1e84, 16, 16, 6776}, + {0x0, 0, 1, 6776}, + {0x0, 0, 1, 6777}, + {0x0, 3, 4, 6778}, + {0x0, 0, 1, 6779}, + {0x0, 1, 2, 6780}, + {0x403, 16, 16, 6781}, + {0x173, 16, 16, 6781}, + {0x1ee6, 16, 16, 6781}, + {0xdc, 16, 16, 6781}, + {0x1ee5, 16, 16, 6781}, + {0x16c, 16, 16, 6781}, + {0x16a, 16, 16, 6781}, + {0x168, 16, 16, 6781}, + {0xdb, 16, 16, 6781}, + {0x0, 8, 11, 6781}, + {0x0, 0, 1, 6784}, + {0x0, 0, 1, 6785}, + {0x0, 6, 7, 6786}, + {0x0, 5, 6, 6787}, + {0x0, 4, 5, 6788}, + {0x626, 16, 16, 6789}, + {0x1e73, 16, 16, 6789}, + {0x0, 5, 7, 6789}, + {0xcc7, 16, 16, 6791}, + {0x0, 0, 1, 6791}, + {0x0, 0, 1, 6792}, + {0x0, 3, 4, 6793}, + {0x0, 0, 3, 6794}, + {0x0, 0, 11, 6797}, + {0x233, 16, 16, 6808}, + {0x1e8f, 16, 16, 6808}, + {0xcc8, 16, 16, 6808}, + {0xfd, 16, 16, 6808}, + {0x1ef3, 16, 16, 6808}, + {0x1ef9, 16, 16, 6808}, + {0x177, 16, 16, 6808}, + {0x0, 12, 13, 6808}, + {0x2f812, 16, 16, 6809}, + {0x1ef7, 16, 16, 6809}, + {0xff, 16, 16, 6809}, + {0x1e80, 16, 16, 6809}, + {0x0, 14, 15, 6809}, + {0x2f83c, 16, 16, 6810}, + {0x0, 2, 3, 6810}, + {0x0, 0, 1, 6811}, + {0x0, 0, 1, 6812}, + {0x0, 11, 12, 6813}, + {0x0, 13, 14, 6814}, + {0x0, 7, 8, 6815}, + {0xb94, 16, 16, 6816}, + {0x0, 10, 11, 6816}, + {0x0, 11, 12, 6817}, + {0x2f961, 16, 16, 6818}, + {0x0, 1, 2, 6818}, + {0x213, 16, 16, 6819}, + {0x0, 1, 12, 6819}, + {0x1a0, 16, 16, 6830}, + {0x0, 0, 9, 6830}, + {0x3ca, 16, 16, 6839}, + {0x0, 11, 12, 6839}, + {0xf9f5, 16, 16, 6840}, + {0x3af, 16, 16, 6840}, + {0x1f76, 16, 16, 6840}, + {0x1fd1, 16, 16, 6840}, + {0x1fd0, 16, 16, 6840}, + {0x1e99, 16, 16, 6840}, + {0x0, 1, 2, 6840}, + {0xf9ca, 16, 16, 6841}, + {0x0, 1, 2, 6841}, + {0x2f802, 16, 16, 6842}, + {0x0, 0, 1, 6842}, + {0x0, 0, 1, 6843}, + {0x0, 6, 7, 6844}, + {0x0, 5, 6, 6845}, + {0x0, 4, 5, 6846}, + {0x624, 16, 16, 6847}, + {0x20e, 16, 16, 6847}, + {0x0, 0, 1, 6847}, + {0x0, 0, 1, 6848}, + {0x0, 3, 4, 6849}, + {0x0, 4, 5, 6850}, + {0x0, 5, 6, 6851}, + {0x1fae, 16, 16, 6852}, + {0x0, 4, 5, 6852}, + {0x2f8bd, 16, 16, 6853}, + {0x0, 9, 10, 6853}, + {0x2f949, 16, 16, 6854}, + {0x0, 4, 5, 6854}, + {0xf9a8, 16, 16, 6855}, + {0x0, 3, 9, 6855}, + {0x1e01, 16, 16, 6861}, + {0x1ea1, 16, 16, 6861}, + {0x1ef8, 16, 16, 6861}, + {0x0, 0, 16, 6861}, + {0x101, 16, 16, 6877}, + {0x105, 16, 16, 6877}, + {0x1f32, 16, 16, 6877}, + {0x0, 0, 1, 6877}, + {0x0, 3, 4, 6878}, + {0x0, 0, 1, 6879}, + {0x0, 9, 10, 6880}, + {0x0, 9, 10, 6881}, + {0x3069, 16, 16, 6882}, + {0x0, 1, 13, 6882}, + {0x139, 16, 16, 6894}, + {0x0, 12, 13, 6894}, + {0x2f9db, 16, 16, 6895}, + {0x0, 9, 10, 6895}, + {0xf96e, 16, 16, 6896}, + {0x0, 3, 4, 6896}, + {0x0, 0, 1, 6897}, + {0x2fa09, 16, 16, 6898}, + {0x0, 13, 14, 6898}, + {0xf99e, 16, 16, 6899}, + {0x0, 2, 3, 6899}, + {0x2f85e, 16, 16, 6900}, + {0x0, 13, 14, 6900}, + {0xf91f, 16, 16, 6901}, + {0x0, 13, 14, 6901}, + {0x2f91a, 16, 16, 6902}, + {0x13d, 16, 16, 6902}, + {0x0, 0, 1, 6902}, + {0x0, 3, 4, 6903}, + {0x0, 0, 1, 6904}, + {0x0, 9, 10, 6905}, + {0x0, 9, 10, 6906}, + {0x30f8, 16, 16, 6907}, + {0x0, 5, 6, 6907}, + {0x2f81d, 16, 16, 6908}, + {0x2f945, 16, 16, 6908}, + {0x0, 0, 1, 6908}, + {0x0, 3, 4, 6909}, + {0x0, 0, 1, 6910}, + {0x0, 9, 10, 6911}, + {0x0, 9, 10, 6912}, + {0x30fa, 16, 16, 6913}, + {0x0, 7, 12, 6913}, + {0xf929, 16, 16, 6918}, + {0x0, 14, 15, 6918}, + {0xf917, 16, 16, 6919}, + {0x0, 8, 12, 6919}, + {0xfa07, 16, 16, 6923}, + {0x0, 2, 6, 6923}, + {0x1f0e, 16, 16, 6927}, + {0x0, 0, 1, 6927}, + {0x0, 0, 1, 6928}, + {0x0, 3, 4, 6929}, + {0x0, 0, 1, 6930}, + {0x0, 1, 2, 6931}, + {0x45c, 16, 16, 6932}, + {0x1f88, 16, 16, 6932}, + {0x0, 0, 1, 6932}, + {0x0, 0, 1, 6933}, + {0x0, 3, 4, 6934}, + {0x0, 0, 1, 6935}, + {0x0, 0, 2, 6936}, + {0x1f4d, 16, 16, 6938}, + {0x1f4b, 16, 16, 6938}, + {0x0, 0, 1, 6938}, + {0x0, 0, 1, 6939}, + {0x0, 3, 4, 6940}, + {0x0, 3, 4, 6941}, + {0x0, 8, 9, 6942}, + {0x22eb, 16, 16, 6943}, + {0x0, 0, 1, 6943}, + {0x0, 0, 1, 6944}, + {0x0, 3, 4, 6945}, + {0x0, 3, 4, 6946}, + {0x0, 8, 9, 6947}, + {0x226e, 16, 16, 6948}, + {0x0, 0, 1, 6948}, + {0xf9cf, 16, 16, 6949}, + {0x0, 15, 16, 6949}, + {0x2f8f4, 16, 16, 6950}, + {0x0, 3, 5, 6950}, + {0x1f11, 16, 16, 6952}, + {0x1f10, 16, 16, 6952}, + {0x0, 0, 1, 6952}, + {0x0, 0, 1, 6953}, + {0x0, 3, 4, 6954}, + {0x0, 1, 2, 6955}, + {0x0, 3, 5, 6956}, + {0x1fe4, 16, 16, 6958}, + {0x2f9df, 16, 16, 6958}, + {0x1fe5, 16, 16, 6958}, + {0x0, 0, 1, 6958}, + {0x0, 3, 4, 6959}, + {0x0, 0, 1, 6960}, + {0x0, 9, 10, 6961}, + {0x0, 9, 10, 6962}, + {0x3067, 16, 16, 6963}, + {0x1f4c, 16, 16, 6963}, + {0x0, 6, 7, 6963}, + {0x0, 10, 11, 6964}, + {0xf987, 16, 16, 6965}, + {0x2f87f, 16, 16, 6965}, + {0x2f8d9, 16, 16, 6965}, + {0x0, 0, 1, 6965}, + {0xf990, 16, 16, 6966}, + {0x0, 0, 1, 6966}, + {0x2f879, 16, 16, 6967}, + {0x1f73, 16, 16, 6967}, + {0x0, 7, 8, 6967}, + {0x2f9f0, 16, 16, 6968}, + {0x1f77, 16, 16, 6968}, + {0x1f71, 0, 1, 6968}, + {0x0, 3, 4, 6969}, + {0x0, 1, 2, 6970}, + {0x2f892, 16, 16, 6971}, + {0x0, 1, 2, 6971}, + {0x1e95, 16, 16, 6972}, + {0x0, 0, 1, 6972}, + {0x0, 0, 1, 6973}, + {0x0, 3, 4, 6974}, + {0x0, 4, 5, 6975}, + {0x0, 5, 6, 6976}, + {0x1fa5, 16, 16, 6977}, + {0x0, 0, 1, 6977}, + {0x0, 3, 4, 6978}, + {0x0, 4, 5, 6979}, + {0x0, 5, 6, 6980}, + {0x1fb4, 16, 16, 6981}, + {0xf925, 16, 16, 6981}, + {0xda, 16, 16, 6981}, + {0x0, 6, 10, 6981}, + {0xf9cc, 16, 16, 6985}, + {0xf9e4, 16, 16, 6985}, + {0x0, 3, 14, 6985}, + {0x145, 16, 16, 6996}, + {0x1e46, 16, 16, 6996}, + {0x0, 3, 4, 6996}, + {0x0, 5, 6, 6997}, + {0x2f926, 16, 16, 6998}, + {0x0, 2, 3, 6998}, + {0x1fc1, 16, 16, 6999}, + {0x0, 11, 12, 6999}, + {0x2f9ff, 16, 16, 7000}, + {0x0, 5, 6, 7000}, + {0x2f955, 16, 16, 7001}, + {0x0, 0, 1, 7001}, + {0x0, 0, 1, 7002}, + {0x0, 3, 4, 7003}, + {0x0, 0, 1, 7004}, + {0x0, 7, 8, 7005}, + {0x1e66, 16, 16, 7006}, + {0x0, 0, 1, 7006}, + {0x0, 0, 1, 7007}, + {0x0, 3, 4, 7008}, + {0x0, 0, 1, 7009}, + {0x0, 8, 9, 7010}, + {0x4e6, 16, 16, 7011}, + {0x0, 1, 2, 7011}, + {0x1e3b, 16, 16, 7012}, + {0x0, 7, 8, 7012}, + {0x2f99e, 16, 16, 7013}, + {0x1e4a, 16, 16, 7013}, + {0xd9, 16, 16, 7013}, + {0x0, 3, 4, 7013}, + {0x1e7e, 16, 16, 7014}, + {0x0, 0, 1, 7014}, + {0x0, 0, 1, 7015}, + {0x0, 3, 4, 7016}, + {0x0, 0, 1, 7017}, + {0x0, 1, 9, 7018}, + {0x22d, 16, 16, 7026}, + {0x0, 0, 1, 7026}, + {0x0, 3, 4, 7027}, + {0x0, 0, 1, 7028}, + {0x0, 9, 10, 7029}, + {0x0, 9, 10, 7030}, + {0x30be, 16, 16, 7031}, + {0x1e4d, 16, 16, 7031}, + {0x1e4f, 16, 16, 7031}, + {0x0, 0, 1, 7031}, + {0x0, 0, 1, 7032}, + {0x0, 3, 4, 7033}, + {0x0, 3, 4, 7034}, + {0x0, 8, 9, 7035}, + {0x220c, 16, 16, 7036}, + {0x0, 4, 5, 7036}, + {0x2f84f, 16, 16, 7037}, + {0x0, 3, 12, 7037}, + {0xf931, 16, 16, 7046}, + {0x0, 3, 4, 7046}, + {0x2f849, 16, 16, 7047}, + {0x0, 0, 1, 7047}, + {0x0, 0, 1, 7048}, + {0x0, 3, 4, 7049}, + {0x0, 0, 1, 7050}, + {0x0, 0, 2, 7051}, + {0x1f1b, 16, 16, 7053}, + {0x1f1d, 16, 16, 7053}, + {0x0, 0, 1, 7053}, + {0x0, 0, 1, 7054}, + {0x0, 3, 4, 7055}, + {0x0, 0, 1, 7056}, + {0x0, 4, 5, 7057}, + {0x22b, 16, 16, 7058}, + {0x0, 8, 9, 7058}, + {0xfa38, 16, 16, 7059}, + {0x0, 7, 8, 7059}, + {0xc7, 16, 16, 7060}, + {0x0, 14, 15, 7060}, + {0x2f936, 16, 16, 7061}, + {0x0, 1, 9, 7061}, + {0xf948, 16, 16, 7069}, + {0x2f9d5, 16, 16, 7069}, + {0x0, 12, 13, 7069}, + {0x2f9a3, 16, 16, 7070}, + {0xf903, 16, 16, 7070}, + {0x2f8ed, 16, 16, 7070}, + {0x0, 8, 9, 7070}, + {0xf9b8, 16, 16, 7071}, + {0x0, 11, 12, 7071}, + {0x2f9da, 16, 16, 7072}, + {0x0, 0, 11, 7072}, + {0x2f9cf, 16, 16, 7083}, + {0x0, 0, 1, 7083}, + {0x0, 0, 1, 7084}, + {0x0, 3, 4, 7085}, + {0x0, 3, 4, 7086}, + {0x0, 8, 9, 7087}, + {0x2249, 16, 16, 7088}, + {0x0, 6, 8, 7088}, + {0x2f84b, 16, 16, 7090}, + {0x2f84d, 16, 16, 7090}, + {0x0, 6, 7, 7090}, + {0x2f821, 16, 16, 7091}, + {0x1ece, 16, 16, 7091}, + {0xd6, 16, 16, 7091}, + {0x22e, 16, 16, 7091}, + {0x14e, 16, 16, 7091}, + {0x14c, 16, 16, 7091}, + {0x0, 13, 14, 7091}, + {0x0, 10, 11, 7092}, + {0x2f97b, 16, 16, 7093}, + {0xd4, 16, 16, 7093}, + {0xd3, 16, 16, 7093}, + {0xd2, 16, 16, 7093}, + {0x1eb3, 16, 16, 7093}, + {0xfa40, 16, 16, 7093}, + {0x1eb5, 16, 16, 7093}, + {0x0, 13, 14, 7093}, + {0x2f854, 16, 16, 7094}, + {0x1eb1, 16, 16, 7094}, + {0x0, 14, 15, 7094}, + {0x2f890, 16, 16, 7095}, + {0x0, 8, 9, 7095}, + {0xfa67, 16, 16, 7096}, + {0x0, 10, 16, 7096}, + {0xdda, 16, 16, 7102}, + {0x0, 8, 9, 7102}, + {0xf9b4, 16, 16, 7103}, + {0xddc, 16, 16, 7103}, + {0xf9a1, 16, 16, 7103}, + {0x0, 0, 1, 7103}, + {0x0, 0, 1, 7104}, + {0x0, 3, 4, 7105}, + {0x0, 4, 5, 7106}, + {0x0, 5, 6, 7107}, + {0x1f8b, 16, 16, 7108}, + {0x0, 3, 4, 7108}, + {0x2f9f5, 16, 16, 7109}, + {0x0, 14, 15, 7109}, + {0x2f9b9, 16, 16, 7110}, + {0x20c, 16, 16, 7110}, + {0x0, 0, 1, 7110}, + {0x0, 0, 1, 7111}, + {0x0, 3, 4, 7112}, + {0x0, 3, 4, 7113}, + {0x0, 8, 9, 7114}, + {0x2284, 16, 16, 7115}, + {0x1d1, 16, 16, 7115}, + {0x150, 16, 16, 7115}, + {0x0, 7, 8, 7115}, + {0xfa5f, 16, 16, 7116}, + {0x0, 1, 13, 7116}, + {0x1e6, 16, 16, 7128}, + {0x0, 6, 7, 7128}, + {0x2f9fd, 16, 16, 7129}, + {0x0, 0, 1, 7129}, + {0x0, 5, 6, 7130}, + {0x2fa12, 16, 16, 7131}, + {0x0, 8, 10, 7131}, + {0x2fa04, 16, 16, 7133}, + {0xfa2c, 16, 16, 7133}, + {0x0, 15, 16, 7133}, + {0xf940, 16, 16, 7134}, + {0x0, 1, 2, 7134}, + {0xfa4b, 16, 16, 7135}, + {0x30d1, 16, 16, 7135}, + {0x0, 2, 11, 7135}, + {0x2f9f4, 16, 16, 7144}, + {0x0, 15, 16, 7144}, + {0xf94e, 16, 16, 7145}, + {0x0, 0, 1, 7145}, + {0x2f8d4, 16, 16, 7146}, + {0x1f00, 16, 16, 7146}, + {0x1f4, 16, 16, 7146}, + {0x11c, 16, 16, 7146}, + {0x1e20, 16, 16, 7146}, + {0x11e, 16, 16, 7146}, + {0x120, 16, 16, 7146}, + {0x0, 3, 4, 7146}, + {0x2f9f3, 16, 16, 7147}, + {0x0, 9, 10, 7147}, + {0xf9fb, 16, 16, 7148}, + {0x1fef, 16, 16, 7148}, + {0xf9ab, 16, 16, 7148}, + {0x0, 3, 4, 7148}, + {0xf94c, 16, 16, 7149}, + {0x0, 0, 1, 7149}, + {0x0, 0, 1, 7150}, + {0x0, 3, 4, 7151}, + {0x0, 4, 5, 7152}, + {0x0, 5, 6, 7153}, + {0x1f96, 16, 16, 7154}, + {0x0, 0, 1, 7154}, + {0x2f96a, 16, 16, 7155}, + {0x1f72, 16, 16, 7155}, + {0x0, 7, 12, 7155}, + {0x2f90c, 16, 16, 7160}, + {0x0, 0, 11, 7160}, + {0x2f9d1, 16, 16, 7171}, + {0x0, 0, 1, 7171}, + {0x0, 0, 1, 7172}, + {0x0, 3, 4, 7173}, + {0x0, 0, 1, 7174}, + {0x0, 1, 2, 7175}, + {0x40c, 16, 16, 7176}, + {0x0, 2, 12, 7176}, + {0x2f89a, 16, 16, 7186}, + {0x0, 7, 8, 7186}, + {0x123, 16, 16, 7187}, + {0x0, 5, 7, 7187}, + {0xf974, 16, 16, 7189}, + {0x2f996, 16, 16, 7189}, + {0x0, 3, 4, 7189}, + {0x1e93, 16, 16, 7190}, + {0x0, 2, 3, 7190}, + {0x1fe7, 16, 16, 7191}, + {0x0, 2, 3, 7191}, + {0x2f9fc, 16, 16, 7192}, + {0x2f90b, 16, 16, 7192}, + {0xf95a, 16, 16, 7192}, + {0x0, 3, 5, 7192}, + {0xfa02, 16, 16, 7194}, + {0x2f8b6, 16, 16, 7194}, + {0x0, 1, 2, 7194}, + {0x1e48, 16, 16, 7195}, + {0x4e4, 16, 16, 7195}, + {0x4e2, 16, 16, 7195}, + {0x0, 0, 1, 7195}, + {0x0, 0, 1, 7196}, + {0x0, 3, 4, 7197}, + {0x0, 3, 4, 7198}, + {0x0, 8, 9, 7199}, + {0x2278, 16, 16, 7200}, + {0x419, 16, 16, 7200}, + {0x0, 1, 2, 7200}, + {0x2f9c0, 16, 16, 7201}, + {0x2f899, 16, 16, 7201}, + {0x1e72, 16, 16, 7201}, + {0x0, 4, 5, 7201}, + {0xf98e, 16, 16, 7202}, + {0x0, 5, 6, 7202}, + {0x2f92b, 16, 16, 7203}, + {0x0, 0, 1, 7203}, + {0x2f9fa, 16, 16, 7204}, + {0x0, 3, 14, 7204}, + {0x1e0d, 16, 16, 7215}, + {0x0, 6, 7, 7215}, + {0x2f9f2, 16, 16, 7216}, + {0x1e11, 16, 16, 7216}, + {0x0, 14, 15, 7216}, + {0x2f851, 16, 16, 7217}, + {0x0, 6, 7, 7217}, + {0x2f9f9, 16, 16, 7218}, + {0x0, 2, 3, 7218}, + {0xf9f9, 16, 16, 7219}, + {0x0, 14, 15, 7219}, + {0xf9a5, 16, 16, 7220}, + {0x10f, 16, 16, 7220}, + {0x0, 2, 6, 7220}, + {0x1f0f, 16, 16, 7224}, + {0x1f89, 16, 16, 7224}, + {0x0, 15, 16, 7224}, + {0x0, 0, 1, 7225}, + {0x0, 0, 1, 7226}, + {0x0, 3, 4, 7227}, + {0x0, 0, 1, 7228}, + {0x0, 7, 8, 7229}, + {0x1e9b, 16, 16, 7230}, + {0x1e13, 16, 16, 7230}, + {0x0, 0, 3, 7230}, + {0x2f84a, 16, 16, 7233}, + {0xfa0d, 16, 16, 7233}, + {0x0, 1, 2, 7233}, + {0x2fa14, 16, 16, 7234}, + {0x0, 12, 13, 7234}, + {0x2f9ad, 16, 16, 7235}, + {0x0, 10, 12, 7235}, + {0xf9ff, 16, 16, 7237}, + {0x2f820, 16, 16, 7237}, + {0x0, 1, 2, 7237}, + {0x2f84e, 16, 16, 7238}, + {0x1fe8, 16, 16, 7238}, + {0x1e58, 16, 16, 7238}, + {0x1fe9, 16, 16, 7238}, + {0x1fea, 16, 16, 7238}, + {0x0, 13, 14, 7238}, + {0x2f8f7, 16, 16, 7239}, + {0x0, 0, 1, 7239}, + {0x0, 0, 1, 7240}, + {0x0, 3, 4, 7241}, + {0x0, 4, 5, 7242}, + {0x0, 5, 6, 7243}, + {0x1f97, 16, 16, 7244}, + {0x3ab, 16, 16, 7244}, + {0x0, 3, 4, 7244}, + {0xf9f1, 16, 16, 7245}, + {0x210, 16, 16, 7245}, + {0x2f9a2, 16, 16, 7245}, + {0x158, 16, 16, 7245}, + {0x0, 5, 6, 7245}, + {0x2f9c8, 16, 16, 7246}, + {0x0, 0, 2, 7246}, + {0x1fc8, 16, 16, 7248}, + {0x388, 16, 16, 7248}, + {0x0, 12, 13, 7248}, + {0xf9cb, 16, 16, 7249}, + {0x0, 1, 2, 7249}, + {0xfa62, 16, 16, 7250}, + {0x0, 9, 10, 7250}, + {0xf9a9, 16, 16, 7251}, + {0x0, 14, 15, 7251}, + {0xf9b6, 16, 16, 7252}, + {0x0, 5, 6, 7252}, + {0xf9e3, 16, 16, 7253}, + {0x0, 11, 12, 7253}, + {0xf9ce, 16, 16, 7254}, + {0x0, 3, 4, 7254}, + {0x1ef5, 16, 16, 7255}, + {0x0, 1, 2, 7255}, + {0x1e49, 16, 16, 7256}, + {0x0, 0, 1, 7256}, + {0x0, 0, 1, 7257}, + {0x0, 3, 4, 7258}, + {0x0, 0, 1, 7259}, + {0x0, 0, 2, 7260}, + {0x1f1c, 16, 16, 7262}, + {0x1f1a, 16, 16, 7262}, + {0x0, 3, 4, 7262}, + {0xf99a, 16, 16, 7263}, + {0xe4, 16, 16, 7263}, + {0x1ea3, 16, 16, 7263}, + {0x0, 0, 1, 7263}, + {0x0, 3, 4, 7264}, + {0x0, 0, 1, 7265}, + {0x0, 9, 10, 7266}, + {0x0, 9, 10, 7267}, + {0x3054, 16, 16, 7268}, + {0x0, 1, 3, 7268}, + {0x2f856, 16, 16, 7270}, + {0x2f857, 16, 16, 7270}, + {0xe0, 16, 16, 7270}, + {0xe1, 16, 16, 7270}, + {0xe2, 16, 16, 7270}, + {0xe3, 16, 16, 7270}, + {0x0, 9, 10, 7270}, + {0x2f82c, 16, 16, 7271}, + {0x103, 16, 16, 7271}, + {0x227, 16, 16, 7271}, + {0x0, 0, 1, 7271}, + {0x0, 0, 1, 7272}, + {0x0, 3, 4, 7273}, + {0x0, 0, 1, 7274}, + {0x0, 0, 2, 7275}, + {0x1f13, 16, 16, 7277}, + {0x1f15, 16, 16, 7277}, + {0x0, 1, 2, 7277}, + {0x2f930, 16, 16, 7278}, + {0x0, 0, 2, 7278}, + {0x1f62, 16, 16, 7280}, + {0x1f64, 16, 16, 7280}, + {0x0, 2, 3, 7280}, + {0xf938, 16, 16, 7281}, + {0x0, 12, 13, 7281}, + {0xf93b, 16, 16, 7282}, + {0x0, 6, 7, 7282}, + {0xf935, 16, 16, 7283}, + {0x0, 0, 1, 7283}, + {0x0, 0, 1, 7284}, + {0x0, 3, 4, 7285}, + {0x0, 4, 5, 7286}, + {0x0, 5, 6, 7287}, + {0x1f8c, 16, 16, 7288}, + {0x0, 0, 1, 7288}, + {0x0, 0, 1, 7289}, + {0x0, 3, 4, 7290}, + {0x0, 0, 1, 7291}, + {0x0, 2, 3, 7292}, + {0x1ed9, 16, 16, 7293}, + {0xe5, 16, 16, 7293}, + {0x1ce, 16, 16, 7293}, + {0x0, 11, 12, 7293}, + {0x2f9a7, 16, 16, 7294}, + {0x201, 16, 16, 7294}, + {0x0, 11, 12, 7294}, + {0x2f990, 16, 16, 7295}, + {0x0, 6, 7, 7295}, + {0x2f85c, 16, 16, 7296}, + {0x0, 0, 1, 7296}, + {0x0, 0, 1, 7297}, + {0x0, 3, 4, 7298}, + {0x0, 4, 5, 7299}, + {0x0, 5, 6, 7300}, + {0x1fa3, 16, 16, 7301}, + {0x0, 6, 7, 7301}, + {0x2f9aa, 16, 16, 7302}, + {0x0, 6, 7, 7302}, + {0xf9b0, 16, 16, 7303}, + {0x0, 1, 3, 7303}, + {0x2f881, 16, 16, 7305}, + {0x2f882, 16, 16, 7305}, + {0x0, 2, 3, 7305}, + {0xf9c1, 16, 16, 7306}, + {0x0, 2, 7, 7306}, + {0xfa03, 16, 16, 7311}, + {0x0, 10, 11, 7311}, + {0x2f932, 16, 16, 7312}, + {0x2f966, 16, 16, 7312}, + {0x0, 10, 11, 7312}, + {0xf9ec, 16, 16, 7313}, + {0x1e50, 16, 16, 7313}, + {0x0, 6, 7, 7313}, + {0xfa61, 16, 16, 7314}, + {0x0, 1, 13, 7314}, + {0x109, 16, 16, 7326}, + {0x107, 16, 16, 7326}, + {0x10b, 16, 16, 7326}, + {0x0, 1, 2, 7326}, + {0x0, 0, 1, 7327}, + {0x0, 0, 1, 7328}, + {0x0, 6, 7, 7329}, + {0x0, 5, 6, 7330}, + {0x0, 4, 5, 7331}, + {0x6c2, 16, 16, 7332}, + {0x0, 2, 3, 7332}, + {0xf9bf, 16, 16, 7333}, + {0x0, 0, 1, 7333}, + {0x0, 0, 1, 7334}, + {0x2fa1d, 16, 16, 7335}, + {0x0, 3, 4, 7335}, + {0x1ef4, 16, 16, 7336}, + {0x0, 14, 15, 7336}, + {0x2f9dd, 16, 16, 7337}, + {0x0, 0, 4, 7337}, + {0x2f9c4, 16, 16, 7341}, + {0x0, 0, 1, 7341}, + {0x0, 0, 1, 7342}, + {0x0, 3, 4, 7343}, + {0x0, 4, 5, 7344}, + {0x0, 5, 6, 7345}, + {0x1f87, 16, 16, 7346}, + {0x2f9c3, 16, 16, 7346}, + {0x0, 11, 12, 7346}, + {0xf964, 16, 16, 7347}, + {0x0, 12, 15, 7347}, + {0xfa15, 16, 16, 7350}, + {0xf954, 16, 16, 7350}, + {0x0, 2, 3, 7350}, + {0xf946, 16, 16, 7351}, + {0x0, 0, 1, 7351}, + {0x0, 0, 1, 7352}, + {0x0, 3, 4, 7353}, + {0x0, 3, 4, 7354}, + {0x0, 8, 9, 7355}, + {0x2226, 16, 16, 7356}, + {0x1f79, 16, 16, 7356}, + {0x0, 0, 1, 7356}, + {0x0, 0, 1, 7357}, + {0x0, 3, 4, 7358}, + {0x0, 3, 4, 7359}, + {0x0, 8, 9, 7360}, + {0x21ce, 16, 16, 7361}, + {0x1d4, 16, 16, 7361}, + {0x1f7b, 16, 16, 7361}, + {0x10d, 16, 16, 7361}, + {0x0, 2, 10, 7361}, + {0x2f96f, 16, 16, 7369}, + {0xfa58, 16, 16, 7369}, +}; + +const unsigned short _wind_canon_next_table[] = { + 1, + 0, + 46, + 29, + 15, + 73, + 64, + 11, + 6, + 24, + 38, + 2, + 42, + 722, + 2119, + 3, + 140, + 1467, + 221, + 325, + 285, + 682, + 360, + 729, + 1610, + 635, + 106, + 2045, + 510, + 2830, + 0, + 0, + 0, + 0, + 0, + 748, + 1101, + 4614, + 273, + 0, + 4, + 0, + 0, + 4440, + 5, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 97, + 224, + 1388, + 270, + 249, + 1440, + 550, + 3741, + 2040, + 7, + 419, + 54, + 109, + 883, + 1230, + 275, + 336, + 4348, + 0, + 0, + 4568, + 3216, + 2891, + 0, + 0, + 0, + 0, + 1305, + 0, + 0, + 8, + 4480, + 937, + 112, + 0, + 0, + 0, + 0, + 0, + 0, + 9, + 1532, + 2106, + 1144, + 236, + 1215, + 1449, + 1624, + 0, + 0, + 12, + 194, + 1718, + 1680, + 3611, + 217, + 398, + 13, + 0, + 0, + 0, + 0, + 4477, + 14, + 2316, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 328, + 16, + 553, + 3511, + 17, + 646, + 732, + 426, + 532, + 57, + 0, + 0, + 0, + 278, + 1790, + 0, + 0, + 658, + 695, + 2327, + 3451, + 3868, + 18, + 666, + 4417, + 4518, + 391, + 1640, + 1458, + 567, + 340, + 2209, + 2458, + 1747, + 19, + 20, + 21, + 22, + 23, + 1307, + 304, + 1254, + 227, + 750, + 51, + 1120, + 1576, + 467, + 1270, + 2751, + 25, + 1647, + 183, + 1785, + 363, + 1315, + 0, + 1982, + 0, + 0, + 2474, + 0, + 1656, + 0, + 4178, + 4486, + 26, + 28, + 27, + 132, + 82, + 346, + 186, + 98, + 0, + 30, + 0, + 0, + 1028, + 0, + 1050, + 739, + 113, + 0, + 2135, + 1415, + 0, + 4020, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4647, + 31, + 3197, + 0, + 0, + 32, + 33, + 34, + 35, + 36, + 37, + 354, + 809, + 436, + 1736, + 39, + 547, + 708, + 1945, + 850, + 367, + 594, + 1651, + 388, + 416, + 1251, + 705, + 4230, + 0, + 1894, + 0, + 886, + 424, + 40, + 4586, + 2250, + 1941, + 0, + 0, + 4635, + 41, + 1224, + 1391, + 813, + 1807, + 3757, + 308, + 442, + 43, + 439, + 121, + 4198, + 1596, + 1298, + 529, + 1244, + 1948, + 4367, + 4591, + 2500, + 2808, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4473, + 44, + 45, + 239, + 1073, + 1218, + 543, + 506, + 124, + 47, + 128, + 772, + 725, + 291, + 3715, + 357, + 3693, + 4339, + 759, + 0, + 2181, + 0, + 0, + 0, + 3076, + 48, + 2065, + 0, + 3213, + 49, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1375, + 50, + 1333, + 0, + 1993, + 1665, + 0, + 52, + 0, + 0, + 1352, + 0, + 3457, + 53, + 1249, + 55, + 0, + 0, + 0, + 1627, + 0, + 0, + 0, + 0, + 1920, + 56, + 2143, + 0, + 0, + 0, + 58, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2970, + 59, + 60, + 61, + 62, + 63, + 65, + 0, + 0, + 0, + 1683, + 403, + 1593, + 1555, + 862, + 2420, + 151, + 259, + 1010, + 2377, + 2719, + 385, + 2542, + 0, + 0, + 0, + 826, + 894, + 66, + 610, + 0, + 2676, + 513, + 90, + 452, + 1152, + 1560, + 470, + 3342, + 0, + 0, + 67, + 0, + 4191, + 0, + 4103, + 0, + 0, + 0, + 0, + 0, + 0, + 1443, + 68, + 69, + 70, + 71, + 72, + 539, + 985, + 74, + 1870, + 0, + 675, + 1542, + 75, + 0, + 1085, + 210, + 2259, + 2582, + 498, + 295, + 76, + 0, + 3605, + 0, + 0, + 4323, + 0, + 0, + 0, + 0, + 1741, + 77, + 78, + 79, + 80, + 81, + 2790, + 587, + 0, + 0, + 978, + 1368, + 83, + 4492, + 0, + 0, + 161, + 2601, + 0, + 0, + 628, + 4245, + 2052, + 0, + 0, + 0, + 0, + 0, + 0, + 2488, + 2098, + 1037, + 84, + 85, + 86, + 87, + 88, + 89, + 372, + 0, + 154, + 0, + 3528, + 0, + 1493, + 0, + 91, + 0, + 1275, + 0, + 4271, + 0, + 2079, + 92, + 93, + 94, + 95, + 96, + 3288, + 1345, + 1907, + 99, + 1176, + 2738, + 0, + 3255, + 0, + 0, + 0, + 0, + 0, + 1615, + 2341, + 764, + 0, + 0, + 1103, + 0, + 1711, + 2982, + 100, + 143, + 0, + 4150, + 0, + 0, + 0, + 3444, + 101, + 102, + 103, + 104, + 105, + 527, + 881, + 0, + 0, + 0, + 0, + 0, + 107, + 0, + 0, + 0, + 4111, + 4319, + 0, + 2519, + 2853, + 108, + 1939, + 0, + 0, + 110, + 0, + 0, + 0, + 0, + 3917, + 0, + 0, + 0, + 2192, + 1883, + 1470, + 1202, + 111, + 318, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 114, + 2770, + 0, + 0, + 115, + 116, + 117, + 118, + 119, + 120, + 4389, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2672, + 0, + 2002, + 0, + 0, + 122, + 123, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 179, + 925, + 125, + 0, + 0, + 1310, + 0, + 1686, + 0, + 0, + 1571, + 3387, + 4056, + 1539, + 0, + 0, + 3187, + 126, + 0, + 954, + 127, + 1047, + 0, + 0, + 1771, + 0, + 0, + 3590, + 0, + 3849, + 3246, + 0, + 0, + 129, + 0, + 0, + 433, + 130, + 131, + 3069, + 133, + 197, + 168, + 1797, + 0, + 0, + 579, + 1377, + 445, + 2552, + 460, + 2528, + 1957, + 1845, + 134, + 2847, + 901, + 1326, + 3859, + 3234, + 1193, + 993, + 753, + 3534, + 520, + 2171, + 2023, + 135, + 136, + 137, + 138, + 0, + 4306, + 181, + 182, + 0, + 0, + 0, + 0, + 180, + 0, + 0, + 0, + 0, + 139, + 842, + 1889, + 1537, + 0, + 2198, + 3252, + 0, + 0, + 0, + 2711, + 3762, + 3357, + 4313, + 4259, + 141, + 142, + 144, + 145, + 146, + 147, + 160, + 0, + 0, + 0, + 150, + 0, + 149, + 0, + 148, + 3760, + 0, + 0, + 0, + 152, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2861, + 153, + 155, + 156, + 157, + 158, + 159, + 1382, + 1759, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 162, + 163, + 164, + 165, + 166, + 0, + 958, + 799, + 167, + 0, + 175, + 0, + 0, + 0, + 0, + 0, + 177, + 4413, + 312, + 479, + 792, + 561, + 169, + 3769, + 3920, + 1487, + 230, + 1065, + 2427, + 3365, + 573, + 1452, + 204, + 170, + 171, + 172, + 962, + 1366, + 173, + 2855, + 174, + 0, + 0, + 0, + 176, + 178, + 0, + 0, + 0, + 0, + 220, + 3165, + 0, + 2515, + 4072, + 0, + 3470, + 2736, + 685, + 0, + 0, + 0, + 4065, + 956, + 1426, + 184, + 185, + 1529, + 1199, + 0, + 0, + 0, + 0, + 0, + 0, + 1294, + 252, + 187, + 406, + 263, + 802, + 3985, + 0, + 0, + 0, + 188, + 0, + 0, + 0, + 2521, + 0, + 0, + 4211, + 4207, + 1549, + 4210, + 189, + 190, + 191, + 3706, + 192, + 193, + 195, + 4482, + 0, + 0, + 0, + 4447, + 196, + 3144, + 0, + 198, + 1689, + 1971, + 3023, + 3687, + 844, + 1257, + 816, + 2650, + 199, + 200, + 201, + 1569, + 202, + 623, + 1006, + 203, + 205, + 206, + 207, + 2194, + 208, + 2835, + 209, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1869, + 2545, + 2111, + 0, + 0, + 4458, + 3207, + 0, + 0, + 3111, + 491, + 243, + 211, + 212, + 213, + 214, + 215, + 216, + 218, + 0, + 0, + 3956, + 4074, + 0, + 0, + 0, + 2374, + 0, + 2864, + 0, + 2217, + 0, + 4093, + 219, + 4624, + 0, + 0, + 0, + 0, + 3181, + 0, + 0, + 0, + 0, + 0, + 1313, + 0, + 0, + 222, + 223, + 225, + 0, + 960, + 0, + 0, + 0, + 0, + 3964, + 0, + 2070, + 0, + 0, + 3710, + 3722, + 1821, + 226, + 228, + 0, + 2337, + 2010, + 1739, + 3930, + 0, + 2844, + 0, + 2205, + 0, + 4089, + 229, + 231, + 232, + 233, + 234, + 2125, + 1147, + 1504, + 1852, + 1853, + 1854, + 1855, + 1856, + 0, + 1857, + 0, + 1858, + 1859, + 0, + 0, + 235, + 0, + 0, + 1893, + 2151, + 0, + 0, + 2478, + 0, + 237, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3627, + 238, + 3084, + 0, + 0, + 0, + 240, + 3098, + 0, + 3417, + 0, + 2733, + 288, + 4042, + 241, + 0, + 3183, + 242, + 244, + 245, + 246, + 247, + 248, + 1464, + 1829, + 0, + 2409, + 4575, + 250, + 0, + 1026, + 0, + 0, + 0, + 0, + 422, + 3040, + 3298, + 3659, + 311, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 251, + 3254, + 1774, + 0, + 0, + 0, + 253, + 0, + 378, + 0, + 2976, + 0, + 0, + 0, + 0, + 0, + 2353, + 254, + 255, + 256, + 4532, + 257, + 262, + 258, + 3195, + 260, + 0, + 0, + 2060, + 0, + 0, + 0, + 0, + 3061, + 261, + 4183, + 0, + 0, + 0, + 2127, + 0, + 0, + 0, + 1703, + 2090, + 1263, + 4685, + 4693, + 264, + 265, + 266, + 267, + 268, + 269, + 1017, + 644, + 271, + 4507, + 4332, + 0, + 0, + 3482, + 3765, + 3492, + 3442, + 3526, + 3205, + 2857, + 2559, + 701, + 272, + 307, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 274, + 2989, + 3322, + 0, + 0, + 1608, + 4469, + 0, + 0, + 2068, + 302, + 1380, + 276, + 626, + 4351, + 277, + 3593, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 279, + 280, + 281, + 282, + 3789, + 0, + 0, + 0, + 283, + 284, + 4369, + 0, + 286, + 0, + 0, + 0, + 3021, + 3494, + 1812, + 0, + 0, + 2284, + 0, + 0, + 4465, + 287, + 289, + 290, + 1317, + 4386, + 2437, + 292, + 0, + 0, + 4656, + 293, + 294, + 2033, + 4164, + 296, + 3461, + 297, + 298, + 299, + 300, + 301, + 1015, + 0, + 0, + 1016, + 0, + 0, + 303, + 1905, + 0, + 2597, + 2301, + 305, + 2348, + 2104, + 3179, + 0, + 3830, + 0, + 2359, + 306, + 309, + 0, + 477, + 4208, + 310, + 313, + 314, + 315, + 4099, + 316, + 4095, + 317, + 319, + 3561, + 320, + 321, + 322, + 3163, + 0, + 323, + 324, + 4595, + 326, + 4122, + 2012, + 0, + 1788, + 719, + 0, + 2058, + 0, + 2075, + 0, + 0, + 0, + 3390, + 327, + 1058, + 0, + 712, + 408, + 0, + 0, + 0, + 329, + 1629, + 1110, + 330, + 2162, + 331, + 332, + 333, + 334, + 335, + 0, + 0, + 0, + 339, + 3940, + 0, + 3286, + 0, + 0, + 337, + 4436, + 0, + 1343, + 871, + 1287, + 0, + 1301, + 3655, + 0, + 2995, + 338, + 341, + 342, + 343, + 344, + 345, + 347, + 0, + 0, + 0, + 0, + 0, + 0, + 3013, + 0, + 3885, + 3735, + 2293, + 919, + 348, + 0, + 0, + 0, + 0, + 1396, + 2223, + 349, + 350, + 351, + 352, + 353, + 2502, + 0, + 2168, + 1591, + 0, + 0, + 355, + 0, + 4411, + 4124, + 0, + 1008, + 3222, + 402, + 0, + 0, + 0, + 0, + 0, + 0, + 401, + 0, + 0, + 0, + 0, + 0, + 356, + 3038, + 0, + 2386, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 358, + 359, + 2866, + 0, + 0, + 0, + 0, + 3271, + 0, + 361, + 4641, + 362, + 4399, + 0, + 364, + 0, + 0, + 0, + 3883, + 0, + 0, + 0, + 0, + 0, + 3876, + 0, + 1922, + 2314, + 366, + 365, + 3249, + 1663, + 1241, + 1558, + 1903, + 2215, + 368, + 0, + 4541, + 0, + 687, + 0, + 3490, + 370, + 369, + 371, + 373, + 374, + 375, + 376, + 377, + 379, + 380, + 381, + 382, + 865, + 0, + 0, + 1924, + 383, + 384, + 3670, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 386, + 387, + 1408, + 0, + 0, + 2423, + 0, + 0, + 4484, + 0, + 2946, + 0, + 4633, + 389, + 1864, + 0, + 0, + 0, + 1879, + 390, + 392, + 393, + 394, + 3865, + 0, + 0, + 0, + 395, + 396, + 0, + 0, + 397, + 399, + 0, + 1969, + 0, + 3392, + 2333, + 400, + 404, + 405, + 407, + 1019, + 0, + 0, + 0, + 2745, + 0, + 1136, + 0, + 415, + 0, + 0, + 0, + 0, + 0, + 2949, + 835, + 409, + 410, + 411, + 412, + 413, + 414, + 653, + 4423, + 4176, + 3845, + 0, + 0, + 0, + 417, + 0, + 0, + 0, + 2599, + 2291, + 1934, + 0, + 0, + 3574, + 418, + 4616, + 420, + 4120, + 0, + 1510, + 1862, + 762, + 1191, + 0, + 0, + 0, + 0, + 0, + 3095, + 3484, + 421, + 505, + 0, + 0, + 0, + 0, + 0, + 0, + 423, + 425, + 999, + 597, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 427, + 428, + 429, + 430, + 3914, + 0, + 0, + 0, + 431, + 432, + 434, + 435, + 437, + 1581, + 1239, + 0, + 3895, + 4677, + 0, + 3603, + 3274, + 0, + 0, + 1507, + 0, + 0, + 3082, + 438, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1726, + 4241, + 4357, + 703, + 440, + 0, + 1043, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2797, + 3720, + 441, + 2824, + 0, + 2177, + 0, + 0, + 1092, + 1434, + 0, + 4525, + 4317, + 4409, + 0, + 443, + 3123, + 459, + 444, + 1512, + 0, + 855, + 446, + 3312, + 970, + 0, + 0, + 2722, + 0, + 0, + 0, + 0, + 1838, + 447, + 448, + 449, + 450, + 451, + 1523, + 0, + 0, + 3410, + 0, + 689, + 0, + 453, + 0, + 0, + 0, + 0, + 0, + 0, + 875, + 454, + 455, + 456, + 457, + 458, + 1727, + 0, + 2305, + 928, + 485, + 461, + 0, + 0, + 2278, + 0, + 0, + 0, + 0, + 1823, + 462, + 463, + 464, + 465, + 466, + 1932, + 0, + 0, + 0, + 468, + 0, + 0, + 1303, + 0, + 3423, + 469, + 4127, + 471, + 4136, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2464, + 472, + 473, + 474, + 475, + 476, + 478, + 480, + 481, + 482, + 483, + 0, + 3191, + 873, + 484, + 486, + 487, + 488, + 489, + 490, + 0, + 0, + 497, + 492, + 493, + 494, + 495, + 496, + 3810, + 0, + 0, + 0, + 0, + 0, + 604, + 2380, + 0, + 499, + 500, + 501, + 502, + 503, + 504, + 3552, + 1954, + 0, + 0, + 951, + 4236, + 3402, + 0, + 0, + 0, + 507, + 0, + 0, + 2868, + 2608, + 0, + 0, + 0, + 0, + 0, + 508, + 509, + 3887, + 4146, + 0, + 0, + 511, + 0, + 0, + 2252, + 0, + 2122, + 512, + 3117, + 0, + 0, + 0, + 0, + 1695, + 0, + 888, + 0, + 514, + 515, + 516, + 517, + 518, + 519, + 521, + 522, + 523, + 524, + 0, + 1296, + 525, + 0, + 0, + 0, + 0, + 0, + 526, + 528, + 2580, + 0, + 0, + 0, + 0, + 1991, + 0, + 0, + 0, + 530, + 531, + 3472, + 786, + 3153, + 4618, + 3901, + 4217, + 2388, + 3042, + 2452, + 2697, + 533, + 2908, + 2873, + 1753, + 4083, + 1402, + 534, + 535, + 536, + 537, + 538, + 540, + 542, + 541, + 2449, + 0, + 544, + 1667, + 934, + 0, + 2403, + 0, + 3160, + 0, + 868, + 0, + 1133, + 3542, + 2266, + 2186, + 545, + 546, + 548, + 4308, + 0, + 1670, + 1967, + 2289, + 0, + 0, + 0, + 0, + 0, + 0, + 3487, + 549, + 3702, + 0, + 0, + 0, + 2401, + 1428, + 0, + 672, + 1045, + 551, + 4289, + 4500, + 552, + 941, + 554, + 1337, + 3724, + 2535, + 2509, + 1599, + 4665, + 779, + 1355, + 3614, + 4361, + 4597, + 3676, + 638, + 3948, + 555, + 556, + 557, + 1979, + 0, + 0, + 0, + 558, + 559, + 0, + 0, + 560, + 562, + 563, + 564, + 565, + 0, + 4475, + 1430, + 566, + 0, + 0, + 0, + 0, + 4488, + 568, + 569, + 570, + 571, + 572, + 574, + 575, + 576, + 1804, + 0, + 577, + 578, + 580, + 581, + 582, + 583, + 584, + 0, + 0, + 0, + 4239, + 585, + 586, + 1815, + 588, + 589, + 590, + 591, + 592, + 3190, + 593, + 3819, + 0, + 0, + 2153, + 0, + 0, + 0, + 770, + 0, + 0, + 0, + 2688, + 0, + 595, + 596, + 598, + 599, + 600, + 601, + 0, + 0, + 0, + 2004, + 602, + 603, + 605, + 606, + 607, + 608, + 609, + 3435, + 0, + 0, + 1585, + 0, + 0, + 611, + 0, + 0, + 617, + 612, + 613, + 614, + 615, + 616, + 950, + 618, + 619, + 620, + 621, + 940, + 622, + 624, + 0, + 0, + 0, + 625, + 627, + 629, + 1208, + 630, + 631, + 632, + 633, + 634, + 3269, + 2006, + 0, + 0, + 0, + 0, + 3731, + 0, + 4310, + 636, + 637, + 639, + 640, + 641, + 642, + 643, + 645, + 1170, + 1320, + 0, + 0, + 0, + 0, + 0, + 0, + 1832, + 647, + 648, + 649, + 650, + 651, + 0, + 0, + 0, + 2133, + 3450, + 652, + 654, + 655, + 4063, + 3782, + 0, + 0, + 656, + 657, + 2885, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 659, + 660, + 661, + 662, + 663, + 0, + 0, + 0, + 2063, + 665, + 664, + 667, + 668, + 669, + 670, + 671, + 674, + 0, + 0, + 673, + 676, + 0, + 4679, + 677, + 678, + 679, + 680, + 681, + 2966, + 3324, + 0, + 0, + 683, + 0, + 4663, + 0, + 0, + 0, + 0, + 0, + 1117, + 1149, + 1567, + 1865, + 684, + 686, + 688, + 690, + 691, + 692, + 693, + 694, + 696, + 697, + 698, + 699, + 0, + 0, + 0, + 3891, + 700, + 2696, + 702, + 0, + 0, + 0, + 0, + 2247, + 704, + 706, + 1228, + 800, + 0, + 2859, + 0, + 0, + 0, + 3278, + 711, + 0, + 0, + 0, + 0, + 0, + 0, + 707, + 747, + 3266, + 0, + 0, + 4631, + 0, + 777, + 0, + 0, + 0, + 0, + 0, + 709, + 0, + 1574, + 2565, + 710, + 1673, + 713, + 714, + 715, + 716, + 717, + 718, + 720, + 0, + 721, + 3508, + 0, + 0, + 0, + 4626, + 0, + 723, + 1205, + 3975, + 0, + 1965, + 2339, + 776, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 724, + 2072, + 3816, + 0, + 2900, + 726, + 0, + 0, + 0, + 0, + 0, + 4115, + 727, + 728, + 4321, + 0, + 0, + 1499, + 1071, + 730, + 731, + 0, + 0, + 0, + 0, + 0, + 3686, + 2394, + 2643, + 0, + 0, + 0, + 0, + 0, + 0, + 733, + 4157, + 734, + 735, + 736, + 737, + 738, + 4197, + 740, + 0, + 0, + 0, + 0, + 0, + 0, + 3966, + 1159, + 741, + 742, + 743, + 744, + 745, + 746, + 749, + 2517, + 0, + 0, + 0, + 3657, + 3893, + 0, + 1363, + 0, + 0, + 751, + 752, + 754, + 755, + 756, + 1867, + 0, + 1168, + 757, + 758, + 760, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2623, + 761, + 763, + 765, + 766, + 767, + 768, + 769, + 0, + 3768, + 771, + 2350, + 0, + 1289, + 0, + 0, + 0, + 773, + 0, + 2914, + 774, + 775, + 778, + 780, + 781, + 782, + 783, + 0, + 0, + 0, + 4148, + 784, + 785, + 787, + 788, + 789, + 2219, + 0, + 0, + 0, + 790, + 791, + 0, + 0, + 798, + 793, + 794, + 795, + 4643, + 0, + 796, + 797, + 801, + 0, + 0, + 0, + 0, + 861, + 803, + 804, + 805, + 806, + 807, + 812, + 0, + 0, + 0, + 0, + 0, + 0, + 808, + 1914, + 0, + 2611, + 0, + 0, + 810, + 0, + 0, + 1432, + 3708, + 811, + 1166, + 0, + 0, + 0, + 1769, + 0, + 0, + 0, + 0, + 0, + 814, + 841, + 815, + 817, + 818, + 819, + 820, + 0, + 4659, + 823, + 822, + 821, + 4098, + 825, + 0, + 0, + 824, + 834, + 833, + 827, + 0, + 0, + 0, + 0, + 2482, + 0, + 3996, + 0, + 3381, + 828, + 829, + 830, + 831, + 832, + 836, + 837, + 838, + 839, + 840, + 843, + 845, + 846, + 847, + 848, + 0, + 1583, + 4046, + 849, + 853, + 0, + 0, + 0, + 0, + 854, + 4005, + 851, + 0, + 4545, + 0, + 4593, + 4394, + 0, + 0, + 2882, + 0, + 0, + 4672, + 852, + 856, + 857, + 858, + 859, + 860, + 1124, + 0, + 0, + 0, + 2433, + 2048, + 0, + 0, + 0, + 0, + 3569, + 0, + 863, + 864, + 866, + 867, + 4516, + 0, + 0, + 0, + 0, + 0, + 0, + 869, + 870, + 872, + 874, + 876, + 877, + 878, + 879, + 880, + 4396, + 882, + 1658, + 0, + 2361, + 2656, + 0, + 0, + 884, + 0, + 1410, + 0, + 0, + 0, + 4205, + 916, + 0, + 915, + 0, + 918, + 917, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 885, + 887, + 889, + 890, + 891, + 892, + 893, + 2837, + 0, + 4562, + 0, + 1926, + 0, + 895, + 0, + 3048, + 0, + 2627, + 0, + 3696, + 0, + 3645, + 896, + 897, + 898, + 899, + 900, + 902, + 903, + 904, + 905, + 1292, + 1638, + 1952, + 910, + 911, + 908, + 909, + 914, + 0, + 912, + 913, + 906, + 907, + 0, + 0, + 947, + 0, + 0, + 948, + 920, + 921, + 922, + 923, + 924, + 926, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2229, + 927, + 929, + 930, + 931, + 932, + 933, + 935, + 936, + 939, + 0, + 0, + 0, + 0, + 938, + 942, + 943, + 944, + 2311, + 0, + 0, + 0, + 945, + 946, + 0, + 0, + 949, + 952, + 953, + 955, + 957, + 959, + 961, + 966, + 967, + 968, + 969, + 963, + 0, + 964, + 965, + 976, + 977, + 0, + 0, + 1014, + 0, + 0, + 1013, + 971, + 972, + 973, + 974, + 975, + 979, + 2660, + 980, + 981, + 982, + 983, + 4640, + 984, + 1126, + 0, + 0, + 0, + 986, + 1472, + 0, + 987, + 0, + 4686, + 988, + 989, + 990, + 991, + 992, + 994, + 995, + 996, + 997, + 998, + 1000, + 1001, + 1002, + 1003, + 0, + 0, + 0, + 2368, + 1005, + 1004, + 1007, + 1009, + 2233, + 0, + 0, + 1011, + 1012, + 1018, + 0, + 0, + 0, + 1025, + 1020, + 1021, + 1022, + 1412, + 1023, + 0, + 0, + 2799, + 4403, + 1024, + 1123, + 0, + 1119, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1027, + 0, + 1036, + 2442, + 1029, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1078, + 1030, + 0, + 0, + 3173, + 1031, + 1032, + 1033, + 1034, + 1035, + 1038, + 1039, + 1040, + 1041, + 1042, + 1044, + 1046, + 0, + 0, + 0, + 1094, + 1048, + 1049, + 1051, + 0, + 0, + 0, + 0, + 4049, + 0, + 0, + 1184, + 1052, + 1053, + 1054, + 1055, + 1056, + 0, + 3108, + 1057, + 1281, + 1059, + 1060, + 1061, + 1062, + 1063, + 1064, + 1066, + 1067, + 1068, + 1069, + 1070, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1142, + 1072, + 3991, + 0, + 1987, + 0, + 0, + 2577, + 0, + 2879, + 0, + 1074, + 1709, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1075, + 1077, + 0, + 1076, + 1079, + 1080, + 1081, + 1082, + 1083, + 0, + 3836, + 1084, + 1478, + 0, + 0, + 1086, + 1095, + 1087, + 1088, + 1089, + 1090, + 1091, + 1093, + 0, + 0, + 1109, + 1096, + 1097, + 1098, + 1099, + 1100, + 1102, + 1104, + 1105, + 1106, + 1107, + 1108, + 1111, + 4603, + 1112, + 1113, + 1114, + 1115, + 1116, + 3852, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1118, + 2021, + 0, + 0, + 3625, + 0, + 0, + 2625, + 2303, + 2658, + 0, + 2589, + 2904, + 0, + 0, + 1121, + 1122, + 0, + 0, + 0, + 1207, + 1125, + 2923, + 0, + 3373, + 0, + 1127, + 1128, + 1129, + 1130, + 1131, + 1132, + 1134, + 1135, + 1137, + 1138, + 1139, + 1484, + 1140, + 0, + 0, + 2785, + 1143, + 1141, + 2440, + 0, + 1810, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1145, + 1146, + 1151, + 0, + 0, + 0, + 0, + 1148, + 1222, + 0, + 0, + 0, + 0, + 0, + 0, + 1150, + 2414, + 0, + 0, + 3639, + 0, + 0, + 2494, + 0, + 0, + 1153, + 1154, + 1155, + 1156, + 1157, + 1158, + 1214, + 3089, + 0, + 0, + 0, + 1160, + 1161, + 1162, + 1163, + 1164, + 1165, + 1204, + 0, + 0, + 0, + 1167, + 1169, + 0, + 0, + 0, + 1183, + 1171, + 1172, + 1173, + 2506, + 0, + 0, + 0, + 1174, + 1175, + 1177, + 0, + 0, + 0, + 3127, + 0, + 0, + 0, + 1233, + 0, + 3545, + 1178, + 1179, + 1180, + 1181, + 2768, + 0, + 1182, + 0, + 2776, + 0, + 0, + 2818, + 1185, + 3803, + 1186, + 1187, + 1188, + 3874, + 0, + 1189, + 1190, + 1192, + 1194, + 1195, + 1196, + 1197, + 3087, + 3425, + 2425, + 2781, + 2782, + 2779, + 2780, + 2778, + 0, + 1201, + 2777, + 2769, + 1198, + 0, + 0, + 2823, + 0, + 0, + 2820, + 1200, + 1203, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1223, + 1206, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1227, + 1209, + 1210, + 1211, + 1212, + 1213, + 1216, + 0, + 0, + 0, + 0, + 0, + 3668, + 1217, + 2275, + 0, + 4212, + 0, + 0, + 1219, + 0, + 0, + 0, + 0, + 1660, + 1220, + 1221, + 4558, + 4353, + 0, + 0, + 0, + 1225, + 3785, + 1885, + 0, + 0, + 1520, + 0, + 0, + 3067, + 1226, + 1229, + 1701, + 0, + 0, + 3309, + 2997, + 4002, + 3661, + 0, + 0, + 0, + 4397, + 0, + 0, + 4628, + 1231, + 1232, + 1234, + 1235, + 1236, + 1237, + 1238, + 1240, + 1243, + 1242, + 3847, + 0, + 0, + 0, + 0, + 0, + 4392, + 0, + 1247, + 0, + 1245, + 1654, + 0, + 0, + 2575, + 1246, + 1248, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1273, + 1250, + 4695, + 0, + 0, + 1252, + 1605, + 1253, + 4203, + 2043, + 2363, + 0, + 0, + 3420, + 0, + 0, + 0, + 0, + 0, + 3935, + 1255, + 4451, + 0, + 2077, + 4228, + 0, + 0, + 0, + 0, + 0, + 1256, + 1258, + 1259, + 1260, + 1261, + 1262, + 1274, + 1264, + 1265, + 1266, + 1267, + 0, + 0, + 0, + 4445, + 1269, + 1268, + 2906, + 0, + 0, + 1271, + 0, + 0, + 0, + 0, + 0, + 1535, + 0, + 0, + 0, + 2783, + 1272, + 1276, + 1277, + 1278, + 1279, + 1280, + 1282, + 1283, + 1284, + 1285, + 1286, + 1288, + 1290, + 1291, + 1293, + 3557, + 3556, + 0, + 3560, + 1295, + 3525, + 0, + 3524, + 0, + 3523, + 3522, + 1297, + 1299, + 3319, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1394, + 1300, + 1302, + 3571, + 0, + 0, + 0, + 1304, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3624, + 1306, + 0, + 0, + 0, + 1336, + 1308, + 0, + 0, + 0, + 0, + 0, + 0, + 3622, + 3889, + 0, + 0, + 2269, + 0, + 1622, + 1309, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1335, + 1311, + 1312, + 1314, + 1316, + 1318, + 1319, + 1321, + 1322, + 1323, + 1324, + 0, + 0, + 0, + 2810, + 1325, + 1332, + 1327, + 1328, + 1329, + 1330, + 1331, + 1334, + 1338, + 1339, + 1340, + 1341, + 1342, + 1344, + 3240, + 0, + 0, + 4006, + 0, + 1346, + 2690, + 2940, + 3138, + 0, + 4430, + 0, + 0, + 0, + 4251, + 1347, + 1348, + 1349, + 1350, + 1354, + 0, + 0, + 0, + 0, + 0, + 1351, + 0, + 1362, + 1353, + 1356, + 1357, + 1358, + 1359, + 0, + 0, + 0, + 4489, + 1361, + 1360, + 1365, + 0, + 0, + 1364, + 1367, + 1369, + 3349, + 1370, + 1371, + 1372, + 1373, + 1374, + 1376, + 1379, + 0, + 0, + 1378, + 1425, + 1381, + 1383, + 1384, + 1385, + 2029, + 0, + 1386, + 1387, + 2050, + 2435, + 1389, + 1782, + 2812, + 3101, + 3276, + 2109, + 3227, + 4674, + 0, + 4133, + 1436, + 0, + 0, + 1437, + 0, + 1438, + 0, + 0, + 0, + 1390, + 1392, + 0, + 0, + 0, + 0, + 3712, + 0, + 0, + 0, + 0, + 3478, + 3827, + 2821, + 1439, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1393, + 1395, + 1397, + 1398, + 1399, + 1400, + 1401, + 1403, + 1404, + 1405, + 1406, + 1407, + 1409, + 1411, + 1414, + 1413, + 0, + 0, + 1423, + 0, + 1424, + 1416, + 1417, + 1418, + 1419, + 1420, + 2413, + 1421, + 1422, + 1427, + 1429, + 1431, + 1433, + 1435, + 1860, + 1441, + 0, + 2179, + 3151, + 0, + 3780, + 0, + 0, + 4047, + 2683, + 4118, + 0, + 0, + 0, + 2207, + 1442, + 1444, + 1445, + 1446, + 1447, + 1509, + 1448, + 4611, + 0, + 0, + 1765, + 1450, + 0, + 0, + 0, + 0, + 0, + 0, + 3775, + 0, + 3134, + 1451, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1506, + 1453, + 1454, + 1455, + 2117, + 0, + 1456, + 4549, + 1502, + 0, + 0, + 0, + 1503, + 0, + 0, + 0, + 0, + 0, + 1457, + 1459, + 1460, + 1461, + 1462, + 1463, + 1465, + 1466, + 1877, + 4113, + 4380, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1468, + 1880, + 1469, + 3012, + 0, + 0, + 0, + 0, + 0, + 0, + 1471, + 1473, + 1474, + 1475, + 1476, + 1477, + 1479, + 1480, + 1481, + 1482, + 1483, + 1486, + 1485, + 1488, + 1489, + 1490, + 2470, + 0, + 1767, + 1491, + 1492, + 1494, + 1495, + 1496, + 1497, + 1498, + 1500, + 0, + 0, + 0, + 1501, + 1505, + 1508, + 1511, + 1513, + 1514, + 1515, + 1516, + 1517, + 1518, + 0, + 1519, + 0, + 0, + 0, + 0, + 0, + 1522, + 1521, + 1524, + 1525, + 1526, + 1527, + 1528, + 1530, + 1531, + 0, + 0, + 0, + 0, + 0, + 0, + 2637, + 3193, + 0, + 0, + 4091, + 1891, + 0, + 0, + 0, + 0, + 1533, + 0, + 0, + 0, + 0, + 2184, + 1534, + 1536, + 1538, + 1540, + 1541, + 1543, + 1544, + 1545, + 1546, + 1547, + 1548, + 1550, + 1551, + 1552, + 1553, + 1554, + 1556, + 1557, + 1580, + 0, + 0, + 0, + 0, + 0, + 1579, + 0, + 0, + 0, + 0, + 0, + 0, + 3060, + 1559, + 1561, + 1562, + 1563, + 1564, + 1565, + 1566, + 1568, + 1570, + 0, + 0, + 0, + 0, + 0, + 4513, + 0, + 0, + 0, + 0, + 4529, + 0, + 0, + 4527, + 1572, + 1573, + 1575, + 4401, + 4142, + 3854, + 0, + 3229, + 2960, + 0, + 2287, + 1943, + 1613, + 0, + 0, + 0, + 0, + 0, + 1577, + 1722, + 0, + 0, + 0, + 0, + 0, + 0, + 1578, + 1582, + 0, + 0, + 3268, + 1584, + 1586, + 1587, + 1588, + 1589, + 3081, + 1590, + 1592, + 1636, + 1594, + 1595, + 1597, + 0, + 0, + 0, + 0, + 2613, + 1598, + 1600, + 1601, + 1602, + 1603, + 1604, + 1606, + 0, + 0, + 0, + 1607, + 1609, + 4537, + 0, + 0, + 2254, + 0, + 1611, + 0, + 0, + 4428, + 1612, + 1614, + 1616, + 1897, + 1617, + 1618, + 1619, + 1620, + 1621, + 1623, + 4530, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1625, + 1984, + 1626, + 1628, + 3280, + 1630, + 1631, + 1632, + 1633, + 1634, + 1635, + 1637, + 1650, + 0, + 0, + 0, + 1646, + 1639, + 0, + 0, + 0, + 0, + 1672, + 1641, + 1642, + 1643, + 1644, + 0, + 0, + 0, + 2937, + 3683, + 1645, + 2324, + 0, + 1648, + 0, + 3576, + 0, + 0, + 3058, + 2816, + 0, + 4543, + 1649, + 1652, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3306, + 1653, + 1655, + 1657, + 0, + 0, + 0, + 0, + 1679, + 1659, + 3795, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1661, + 1662, + 1664, + 0, + 3635, + 1666, + 2248, + 0, + 0, + 0, + 1668, + 0, + 0, + 3880, + 3663, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1669, + 1671, + 1674, + 1675, + 1676, + 1677, + 1678, + 3620, + 0, + 1681, + 2621, + 1682, + 2245, + 0, + 2273, + 0, + 1684, + 1685, + 1687, + 0, + 0, + 0, + 0, + 0, + 0, + 2633, + 0, + 0, + 4243, + 1688, + 1690, + 1691, + 1692, + 1693, + 0, + 2370, + 1724, + 1725, + 0, + 0, + 0, + 0, + 1723, + 0, + 0, + 0, + 0, + 1694, + 1696, + 1697, + 1698, + 1699, + 1700, + 1702, + 1704, + 1705, + 1706, + 1707, + 2476, + 0, + 0, + 3467, + 2062, + 1708, + 1710, + 1712, + 1713, + 1714, + 1715, + 1717, + 0, + 0, + 0, + 0, + 0, + 1721, + 0, + 1716, + 1719, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3558, + 1720, + 1728, + 1729, + 1730, + 1731, + 1733, + 1734, + 0, + 1732, + 0, + 0, + 0, + 0, + 0, + 1735, + 1737, + 0, + 0, + 0, + 0, + 2271, + 3843, + 0, + 4471, + 3684, + 0, + 4144, + 1738, + 1740, + 1742, + 1743, + 1744, + 1745, + 1746, + 1748, + 1749, + 1750, + 1751, + 1752, + 1754, + 1755, + 1756, + 1757, + 1758, + 1760, + 1761, + 1762, + 2406, + 0, + 1763, + 1764, + 1766, + 1851, + 0, + 0, + 0, + 1844, + 0, + 0, + 0, + 0, + 0, + 0, + 1768, + 1770, + 1772, + 1773, + 1775, + 1776, + 1777, + 1778, + 2085, + 0, + 0, + 3063, + 1779, + 1780, + 0, + 0, + 1784, + 0, + 1781, + 1783, + 2190, + 3056, + 0, + 0, + 0, + 1786, + 0, + 0, + 4535, + 0, + 4638, + 4426, + 2962, + 1787, + 1831, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1789, + 1791, + 1792, + 1793, + 1794, + 1795, + 1796, + 2014, + 0, + 2591, + 2754, + 2931, + 3006, + 2239, + 3167, + 1798, + 4030, + 3907, + 1799, + 1800, + 1801, + 1802, + 1803, + 1814, + 1805, + 0, + 0, + 0, + 0, + 0, + 1806, + 1808, + 0, + 0, + 0, + 3672, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2159, + 1809, + 1811, + 1813, + 1816, + 1817, + 1818, + 1819, + 1820, + 3653, + 1822, + 1824, + 1825, + 1826, + 1827, + 1828, + 1830, + 1833, + 1834, + 1835, + 3105, + 0, + 0, + 0, + 1836, + 1837, + 1839, + 1840, + 1841, + 1842, + 1843, + 1846, + 1847, + 1848, + 2787, + 0, + 2149, + 1849, + 1850, + 1861, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1887, + 1863, + 3714, + 0, + 1866, + 1868, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1888, + 2713, + 0, + 0, + 0, + 0, + 1871, + 0, + 0, + 4279, + 1872, + 1873, + 1874, + 1875, + 1876, + 1878, + 1882, + 0, + 1881, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1896, + 1884, + 1886, + 1890, + 1892, + 1895, + 1898, + 1899, + 1900, + 1901, + 1902, + 1904, + 1936, + 0, + 0, + 0, + 1938, + 0, + 0, + 0, + 1906, + 0, + 1916, + 1908, + 0, + 0, + 0, + 2801, + 0, + 0, + 0, + 3821, + 0, + 2893, + 1909, + 1910, + 1911, + 1912, + 1919, + 0, + 1918, + 0, + 1913, + 0, + 0, + 1937, + 1917, + 0, + 0, + 0, + 1915, + 1921, + 1923, + 1925, + 1927, + 1928, + 1929, + 1930, + 1931, + 1933, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1951, + 1935, + 1940, + 1942, + 1944, + 3897, + 2257, + 0, + 0, + 2685, + 0, + 0, + 0, + 1946, + 1947, + 3840, + 3567, + 0, + 2958, + 0, + 0, + 0, + 0, + 1949, + 3225, + 1950, + 1953, + 1955, + 1956, + 1958, + 1959, + 1960, + 1961, + 2335, + 2669, + 2000, + 2001, + 1998, + 1999, + 1997, + 0, + 1995, + 1996, + 2008, + 2009, + 1964, + 0, + 1963, + 0, + 0, + 1962, + 1966, + 1968, + 1986, + 0, + 0, + 0, + 0, + 1970, + 1972, + 1973, + 1974, + 2635, + 0, + 1975, + 2299, + 1978, + 0, + 0, + 1976, + 1977, + 0, + 0, + 0, + 0, + 0, + 1990, + 1981, + 1980, + 1983, + 1985, + 1988, + 0, + 0, + 0, + 3394, + 1989, + 1992, + 1994, + 2003, + 2005, + 2007, + 2011, + 2013, + 2015, + 2016, + 2017, + 2018, + 2020, + 0, + 0, + 0, + 0, + 0, + 2019, + 2022, + 2024, + 2025, + 2026, + 2027, + 4061, + 3801, + 4344, + 4343, + 4342, + 2028, + 4338, + 0, + 4337, + 4336, + 4335, + 4334, + 0, + 4379, + 4378, + 0, + 0, + 4371, + 2032, + 2031, + 0, + 2030, + 0, + 0, + 0, + 0, + 0, + 2039, + 2034, + 2035, + 2036, + 2037, + 2038, + 4329, + 0, + 0, + 0, + 0, + 0, + 0, + 2814, + 0, + 0, + 0, + 2041, + 0, + 0, + 3079, + 2042, + 2044, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2087, + 2365, + 2046, + 2047, + 2049, + 2097, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2051, + 2053, + 2054, + 2055, + 2056, + 2057, + 2059, + 2061, + 2064, + 2066, + 2067, + 2069, + 2071, + 3878, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2073, + 2074, + 2076, + 2089, + 0, + 2078, + 2080, + 2081, + 2082, + 2083, + 2084, + 2086, + 2088, + 2091, + 2092, + 2093, + 2094, + 0, + 0, + 0, + 3400, + 2095, + 2096, + 2099, + 2100, + 2101, + 2102, + 2103, + 2105, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2222, + 2107, + 2108, + 2110, + 0, + 2929, + 2112, + 2113, + 2114, + 2115, + 2116, + 2157, + 2158, + 0, + 2161, + 0, + 0, + 0, + 2156, + 0, + 0, + 0, + 0, + 2118, + 3219, + 0, + 0, + 2120, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2833, + 2504, + 2121, + 2124, + 0, + 0, + 0, + 0, + 0, + 2123, + 2126, + 2128, + 2129, + 2130, + 3428, + 3754, + 0, + 0, + 2131, + 2132, + 2134, + 2136, + 2137, + 2138, + 2139, + 2140, + 3777, + 2141, + 2142, + 2144, + 2145, + 2146, + 2147, + 2148, + 2150, + 2152, + 2189, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2155, + 0, + 0, + 0, + 0, + 2154, + 2160, + 2163, + 2164, + 2165, + 2166, + 2167, + 0, + 0, + 0, + 2170, + 2169, + 2172, + 2173, + 2174, + 2175, + 0, + 4233, + 4454, + 3665, + 3666, + 0, + 3664, + 0, + 0, + 0, + 3667, + 0, + 0, + 0, + 0, + 2176, + 2232, + 0, + 2178, + 2180, + 2182, + 3136, + 2183, + 2185, + 2187, + 0, + 0, + 3185, + 2188, + 2191, + 2193, + 2202, + 2201, + 2204, + 2203, + 2197, + 0, + 2200, + 2367, + 2196, + 2195, + 0, + 2238, + 2237, + 0, + 0, + 2236, + 2199, + 2206, + 2208, + 2210, + 2211, + 2212, + 2213, + 2214, + 2216, + 2218, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2235, + 2221, + 2220, + 2224, + 2225, + 2226, + 2227, + 2228, + 2230, + 2231, + 2234, + 2240, + 2241, + 2242, + 2871, + 0, + 2243, + 2244, + 2246, + 2249, + 2251, + 0, + 0, + 0, + 2256, + 2253, + 2255, + 4135, + 2258, + 4372, + 2762, + 0, + 0, + 3000, + 2260, + 2261, + 2262, + 2263, + 2264, + 2265, + 2267, + 2268, + 2270, + 2272, + 0, + 0, + 0, + 0, + 2286, + 2274, + 0, + 2326, + 2667, + 2276, + 2277, + 2279, + 2280, + 2281, + 2282, + 2283, + 2957, + 0, + 2956, + 0, + 0, + 0, + 0, + 0, + 2948, + 2285, + 2288, + 2290, + 2292, + 2294, + 2295, + 2296, + 2297, + 2298, + 2300, + 2302, + 2304, + 2306, + 2307, + 2308, + 2309, + 2310, + 2312, + 2313, + 2315, + 2317, + 2318, + 2319, + 2320, + 2321, + 2322, + 2323, + 2325, + 2328, + 2329, + 2330, + 2331, + 0, + 0, + 0, + 3651, + 3273, + 2332, + 2334, + 0, + 0, + 0, + 2930, + 2336, + 2338, + 2340, + 2342, + 3502, + 2343, + 2344, + 2345, + 2346, + 2347, + 2349, + 2731, + 2351, + 2352, + 2354, + 2355, + 2356, + 2357, + 3408, + 3730, + 2358, + 4346, + 0, + 0, + 0, + 2360, + 2362, + 2364, + 2366, + 2369, + 2373, + 0, + 0, + 2372, + 2371, + 2376, + 0, + 0, + 0, + 2375, + 3704, + 0, + 0, + 0, + 0, + 0, + 2378, + 2379, + 2381, + 2382, + 2383, + 2384, + 2385, + 2387, + 2389, + 2390, + 2391, + 2392, + 2393, + 2395, + 2396, + 2397, + 2398, + 2399, + 2400, + 2402, + 2404, + 2405, + 2407, + 2408, + 0, + 2411, + 0, + 0, + 0, + 0, + 0, + 2412, + 2410, + 2415, + 2416, + 2417, + 2418, + 2419, + 2480, + 2421, + 0, + 3065, + 2422, + 2424, + 2426, + 2428, + 2429, + 2430, + 3054, + 0, + 2431, + 3432, + 2432, + 0, + 0, + 0, + 3753, + 2434, + 2436, + 2438, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4503, + 2439, + 2441, + 2443, + 2444, + 2445, + 2446, + 2447, + 2448, + 2450, + 2451, + 2453, + 2454, + 2455, + 3750, + 0, + 0, + 0, + 2456, + 3919, + 0, + 0, + 2457, + 2459, + 2460, + 2461, + 2462, + 2463, + 2465, + 2466, + 2467, + 2468, + 2469, + 2473, + 0, + 0, + 0, + 0, + 2472, + 2471, + 0, + 0, + 0, + 3832, + 2475, + 2477, + 2481, + 2479, + 2483, + 2484, + 2485, + 2486, + 2487, + 2489, + 2490, + 2491, + 2492, + 2493, + 2495, + 2496, + 2497, + 2498, + 2499, + 2551, + 2501, + 2508, + 0, + 0, + 2503, + 2541, + 0, + 0, + 0, + 0, + 2505, + 4102, + 2507, + 2510, + 2511, + 2512, + 2513, + 2514, + 2516, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2564, + 2518, + 2520, + 2522, + 2523, + 2524, + 2525, + 2827, + 0, + 0, + 3797, + 2526, + 2527, + 3942, + 4265, + 4298, + 0, + 2529, + 0, + 0, + 0, + 3359, + 2530, + 2531, + 2532, + 2533, + 2534, + 2536, + 2537, + 2538, + 2539, + 2540, + 2543, + 2544, + 2546, + 2547, + 2548, + 2549, + 2550, + 2553, + 2567, + 2917, + 0, + 2704, + 0, + 0, + 0, + 3584, + 2554, + 2555, + 2556, + 2557, + 2562, + 2561, + 0, + 2563, + 0, + 0, + 0, + 0, + 0, + 2558, + 2560, + 2566, + 2568, + 2569, + 2570, + 2571, + 2573, + 0, + 0, + 2574, + 0, + 0, + 0, + 2572, + 2610, + 0, + 0, + 0, + 0, + 2576, + 2578, + 2579, + 2581, + 2583, + 3744, + 2584, + 2585, + 2586, + 2587, + 2588, + 2590, + 2592, + 2593, + 2594, + 2595, + 4059, + 3125, + 3459, + 2596, + 0, + 0, + 0, + 0, + 0, + 3767, + 0, + 0, + 0, + 0, + 3719, + 0, + 0, + 3718, + 2598, + 2600, + 2602, + 0, + 0, + 0, + 0, + 0, + 0, + 2615, + 2603, + 2604, + 2605, + 3296, + 0, + 2606, + 2607, + 2609, + 2612, + 2614, + 2616, + 2617, + 2618, + 2619, + 2620, + 2622, + 2624, + 2626, + 2628, + 2629, + 2630, + 2631, + 2632, + 2634, + 2636, + 0, + 0, + 0, + 0, + 2671, + 2638, + 2639, + 2640, + 2641, + 2642, + 2644, + 2645, + 2646, + 2647, + 2649, + 2648, + 2651, + 2652, + 2653, + 3572, + 0, + 2964, + 2654, + 2655, + 2657, + 2659, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2687, + 2661, + 2662, + 2663, + 2664, + 2665, + 2666, + 2668, + 2674, + 0, + 2675, + 0, + 0, + 2670, + 2673, + 2677, + 2678, + 2679, + 2680, + 2681, + 2682, + 2684, + 2686, + 2689, + 2691, + 2692, + 2693, + 2694, + 2695, + 0, + 2703, + 2698, + 2699, + 2700, + 3961, + 0, + 0, + 0, + 2701, + 2702, + 0, + 0, + 2710, + 2705, + 2706, + 2707, + 2708, + 2709, + 2712, + 2714, + 2715, + 2716, + 2717, + 2718, + 3326, + 2720, + 2721, + 2723, + 2724, + 2725, + 2726, + 2729, + 2728, + 0, + 2730, + 0, + 0, + 0, + 0, + 0, + 2727, + 2732, + 2734, + 2735, + 3799, + 2737, + 2739, + 2740, + 2741, + 2742, + 2743, + 2744, + 2746, + 2747, + 2748, + 2749, + 4180, + 4425, + 2750, + 4654, + 4415, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2752, + 0, + 0, + 4287, + 2753, + 2755, + 2756, + 2757, + 3355, + 0, + 2758, + 2759, + 0, + 0, + 2761, + 2760, + 2763, + 2764, + 2765, + 2766, + 2767, + 2771, + 2772, + 2773, + 4355, + 2774, + 2775, + 2784, + 2789, + 0, + 0, + 2786, + 2788, + 3029, + 2791, + 2792, + 2793, + 2794, + 2795, + 4350, + 2796, + 0, + 4347, + 0, + 0, + 0, + 0, + 0, + 4345, + 2798, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2826, + 2807, + 0, + 0, + 2800, + 2802, + 2803, + 2804, + 2805, + 2806, + 2809, + 2811, + 2813, + 2815, + 2819, + 2817, + 2822, + 2825, + 2828, + 2829, + 2832, + 0, + 0, + 2831, + 2834, + 2836, + 0, + 0, + 0, + 0, + 2843, + 2838, + 2839, + 2840, + 2841, + 2842, + 2845, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2846, + 2848, + 2849, + 2850, + 2851, + 0, + 3519, + 3203, + 2852, + 0, + 0, + 0, + 0, + 2863, + 2854, + 2856, + 2858, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2903, + 2860, + 2862, + 2865, + 2867, + 2869, + 3232, + 2870, + 2872, + 2874, + 2875, + 2876, + 2877, + 2878, + 2880, + 2881, + 2883, + 0, + 2884, + 2886, + 2887, + 2888, + 2889, + 2890, + 2899, + 0, + 0, + 0, + 2892, + 2894, + 2895, + 2896, + 2897, + 2898, + 2901, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4384, + 2902, + 2905, + 2907, + 2909, + 2910, + 2911, + 2912, + 2913, + 2915, + 2916, + 2918, + 2919, + 2920, + 2921, + 2922, + 2924, + 2925, + 2926, + 2927, + 2928, + 2932, + 2933, + 2934, + 2935, + 0, + 3601, + 3899, + 2968, + 2969, + 0, + 0, + 0, + 2936, + 2939, + 0, + 0, + 2938, + 2941, + 2942, + 2943, + 2944, + 2945, + 2947, + 2950, + 2951, + 2952, + 2953, + 3328, + 2954, + 2955, + 2959, + 3551, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2961, + 2963, + 2965, + 2967, + 2971, + 2972, + 2973, + 2974, + 2975, + 2977, + 2978, + 2979, + 2980, + 3302, + 2991, + 2992, + 0, + 0, + 2994, + 0, + 2993, + 0, + 2981, + 2983, + 2984, + 2985, + 2986, + 2987, + 0, + 2988, + 2990, + 2996, + 0, + 0, + 0, + 2999, + 2998, + 3001, + 3002, + 3003, + 3004, + 3005, + 3007, + 3008, + 3009, + 3331, + 3010, + 3980, + 3674, + 3020, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3011, + 3014, + 3015, + 3016, + 3017, + 3018, + 3019, + 3022, + 3024, + 3025, + 3026, + 3973, + 3733, + 3337, + 3027, + 3028, + 3030, + 3031, + 3032, + 3033, + 3034, + 3035, + 0, + 3036, + 0, + 0, + 0, + 0, + 0, + 3037, + 3039, + 3041, + 3043, + 3044, + 3045, + 3046, + 3047, + 3049, + 3050, + 3051, + 3052, + 3053, + 3097, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3055, + 3057, + 3059, + 3062, + 3064, + 3066, + 3104, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3068, + 3637, + 4170, + 3070, + 3578, + 3071, + 3072, + 3073, + 3074, + 3075, + 3077, + 3078, + 3080, + 3083, + 3085, + 3086, + 3088, + 3090, + 3091, + 3092, + 3093, + 4028, + 3094, + 3096, + 3099, + 3100, + 3103, + 0, + 0, + 3231, + 0, + 3102, + 3107, + 3106, + 3109, + 3110, + 3112, + 3113, + 3114, + 3115, + 3116, + 3118, + 3119, + 3120, + 3121, + 3122, + 3124, + 3295, + 3126, + 0, + 0, + 0, + 3133, + 3128, + 3129, + 3130, + 3131, + 3132, + 3135, + 3137, + 3139, + 3140, + 3141, + 3142, + 3143, + 0, + 0, + 0, + 4457, + 0, + 4464, + 0, + 4456, + 3145, + 3146, + 3147, + 3148, + 3150, + 0, + 0, + 0, + 0, + 0, + 3149, + 3159, + 0, + 0, + 0, + 0, + 0, + 3152, + 3154, + 3155, + 3156, + 3157, + 3158, + 3161, + 3162, + 3164, + 3166, + 0, + 0, + 0, + 0, + 3224, + 0, + 0, + 3221, + 3168, + 3169, + 3170, + 3787, + 0, + 3171, + 3172, + 3174, + 3175, + 3176, + 3177, + 3178, + 3180, + 3182, + 3184, + 3186, + 3188, + 3189, + 3192, + 3194, + 3196, + 3198, + 3199, + 3200, + 3201, + 3202, + 3204, + 3218, + 0, + 3206, + 3208, + 3209, + 3210, + 3211, + 3212, + 4505, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3214, + 3215, + 3217, + 3220, + 3223, + 3226, + 3265, + 0, + 0, + 3228, + 3230, + 3233, + 3235, + 3236, + 3237, + 3238, + 0, + 3838, + 3264, + 0, + 0, + 0, + 0, + 3263, + 3262, + 0, + 0, + 0, + 3239, + 3241, + 3242, + 3243, + 3244, + 3245, + 0, + 3251, + 3247, + 3248, + 3250, + 3253, + 3496, + 3256, + 3257, + 3258, + 3259, + 3260, + 3261, + 3267, + 3270, + 3272, + 3275, + 3277, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3842, + 3279, + 3281, + 3282, + 3283, + 3284, + 3285, + 3287, + 3289, + 3290, + 3291, + 3292, + 3293, + 3294, + 3300, + 3301, + 0, + 3304, + 0, + 0, + 0, + 0, + 0, + 3297, + 3321, + 0, + 0, + 0, + 0, + 0, + 3299, + 3303, + 3305, + 3308, + 0, + 0, + 0, + 0, + 0, + 3307, + 0, + 0, + 3311, + 3310, + 3313, + 3314, + 3315, + 3316, + 3318, + 0, + 0, + 3317, + 3320, + 3323, + 3325, + 3327, + 3329, + 3330, + 3333, + 3332, + 3335, + 3334, + 3336, + 0, + 3339, + 0, + 3341, + 3340, + 3371, + 3379, + 4692, + 0, + 0, + 3380, + 3338, + 4468, + 0, + 0, + 0, + 3348, + 0, + 0, + 0, + 0, + 3372, + 3343, + 3344, + 3345, + 3346, + 3347, + 3350, + 3351, + 3352, + 3353, + 3354, + 3406, + 3405, + 0, + 0, + 0, + 0, + 3407, + 0, + 0, + 0, + 0, + 3356, + 3416, + 3358, + 0, + 4528, + 3360, + 3361, + 3362, + 3363, + 3397, + 3398, + 0, + 0, + 3399, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3364, + 3366, + 3367, + 3368, + 3369, + 0, + 3982, + 4257, + 3370, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3396, + 3374, + 3375, + 3376, + 3377, + 3378, + 3382, + 3383, + 3384, + 3385, + 3386, + 3388, + 3389, + 3391, + 3393, + 3395, + 3401, + 3403, + 3404, + 3422, + 3409, + 3411, + 3412, + 3413, + 3414, + 3415, + 3418, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4661, + 3419, + 3421, + 3424, + 3426, + 0, + 0, + 0, + 0, + 3427, + 3429, + 3430, + 0, + 0, + 3431, + 0, + 3434, + 0, + 3441, + 3433, + 3436, + 3437, + 3438, + 3439, + 3481, + 3440, + 3443, + 3445, + 3446, + 3447, + 3448, + 3449, + 3452, + 3453, + 3454, + 3455, + 3456, + 3458, + 4004, + 3460, + 3462, + 3463, + 3464, + 3465, + 3466, + 3468, + 0, + 0, + 3469, + 3489, + 3471, + 3473, + 3474, + 3475, + 4588, + 0, + 0, + 0, + 3476, + 3480, + 0, + 0, + 3477, + 3479, + 3486, + 0, + 0, + 0, + 0, + 3483, + 3485, + 3488, + 3491, + 3493, + 3495, + 3497, + 3498, + 3499, + 3500, + 3501, + 3503, + 3504, + 3505, + 3506, + 3507, + 3510, + 0, + 0, + 0, + 3509, + 3512, + 4579, + 0, + 0, + 0, + 0, + 0, + 0, + 4551, + 4291, + 3513, + 3514, + 3515, + 3516, + 3518, + 3517, + 3520, + 0, + 0, + 0, + 3521, + 0, + 0, + 0, + 0, + 0, + 3541, + 3527, + 3529, + 3530, + 3531, + 3532, + 3533, + 3535, + 3536, + 3537, + 4109, + 0, + 3538, + 3834, + 3539, + 0, + 0, + 0, + 3540, + 0, + 0, + 0, + 0, + 0, + 3555, + 3543, + 3544, + 3546, + 3547, + 3548, + 3549, + 3550, + 3553, + 3554, + 3559, + 3562, + 3563, + 3564, + 3565, + 3566, + 3568, + 3570, + 3630, + 3629, + 0, + 0, + 0, + 0, + 3632, + 0, + 0, + 0, + 0, + 3573, + 3575, + 3577, + 3579, + 3580, + 3581, + 3582, + 3583, + 3585, + 3586, + 3587, + 3588, + 3599, + 3600, + 0, + 0, + 3589, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3638, + 3591, + 3592, + 3594, + 3595, + 3596, + 3597, + 3598, + 3636, + 0, + 0, + 3633, + 3634, + 0, + 0, + 0, + 0, + 0, + 3602, + 3604, + 3606, + 3607, + 3608, + 3609, + 3610, + 3612, + 3613, + 3615, + 3616, + 3617, + 3618, + 3619, + 3621, + 3623, + 3626, + 3631, + 0, + 0, + 0, + 3628, + 3640, + 3641, + 3642, + 3643, + 3682, + 3644, + 3646, + 3647, + 3648, + 3649, + 3650, + 3654, + 0, + 0, + 3652, + 3656, + 3658, + 3660, + 3662, + 3669, + 3671, + 3673, + 3675, + 3677, + 3678, + 3679, + 3680, + 3681, + 3685, + 3688, + 3689, + 3690, + 3691, + 0, + 4263, + 3692, + 3694, + 3695, + 3697, + 3698, + 3699, + 3700, + 3701, + 3703, + 3705, + 4515, + 3707, + 0, + 0, + 4514, + 0, + 4512, + 0, + 4524, + 3709, + 3711, + 3713, + 3716, + 3717, + 3721, + 3723, + 3725, + 3726, + 3727, + 3728, + 3729, + 3732, + 3734, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3764, + 3736, + 3737, + 3738, + 3739, + 3740, + 3742, + 0, + 0, + 0, + 0, + 4510, + 4304, + 4285, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4539, + 3743, + 3745, + 3746, + 3747, + 3748, + 3749, + 3751, + 3752, + 3756, + 3755, + 3758, + 3759, + 3761, + 3763, + 3766, + 3770, + 3771, + 3772, + 3773, + 3774, + 3776, + 3778, + 0, + 3779, + 3781, + 3783, + 3784, + 3786, + 3794, + 3793, + 3792, + 0, + 0, + 0, + 0, + 3788, + 3800, + 0, + 3833, + 3790, + 3791, + 3796, + 3798, + 3802, + 0, + 0, + 0, + 0, + 3809, + 3804, + 3805, + 3806, + 3807, + 3808, + 3811, + 3812, + 3813, + 3814, + 3815, + 3817, + 3818, + 3820, + 3822, + 3823, + 3824, + 3825, + 3826, + 3828, + 0, + 0, + 3829, + 3831, + 3835, + 3837, + 3856, + 0, + 0, + 0, + 3853, + 0, + 0, + 0, + 0, + 0, + 0, + 3839, + 3857, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3841, + 3858, + 0, + 0, + 0, + 3844, + 3882, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3846, + 3848, + 3850, + 3851, + 3855, + 3860, + 3861, + 3862, + 4382, + 0, + 3863, + 3864, + 3866, + 3867, + 3869, + 3870, + 3871, + 3872, + 3873, + 3875, + 3877, + 3879, + 3881, + 3884, + 3886, + 3888, + 0, + 0, + 0, + 3937, + 3890, + 3892, + 0, + 0, + 3913, + 3938, + 0, + 0, + 0, + 0, + 0, + 0, + 3894, + 3896, + 3898, + 3900, + 3902, + 3903, + 3904, + 3905, + 3906, + 3908, + 3909, + 3910, + 3911, + 0, + 4443, + 4215, + 3933, + 3934, + 0, + 0, + 0, + 0, + 3932, + 0, + 0, + 0, + 0, + 3912, + 3915, + 3916, + 3918, + 3921, + 3922, + 3923, + 3924, + 0, + 4438, + 3929, + 3928, + 0, + 3927, + 0, + 3925, + 3926, + 0, + 0, + 0, + 0, + 3939, + 3931, + 3936, + 3941, + 3943, + 3944, + 3945, + 3946, + 3955, + 3954, + 0, + 3947, + 0, + 0, + 0, + 0, + 0, + 3959, + 3949, + 3950, + 3951, + 3952, + 3953, + 3960, + 0, + 0, + 0, + 0, + 0, + 3958, + 3957, + 0, + 0, + 0, + 3994, + 3963, + 3962, + 3965, + 3967, + 3968, + 3969, + 3970, + 3971, + 3972, + 4262, + 4229, + 4019, + 4018, + 4017, + 0, + 4016, + 0, + 4014, + 4013, + 3979, + 3978, + 3977, + 0, + 0, + 3974, + 3976, + 4015, + 4027, + 0, + 0, + 0, + 4012, + 0, + 0, + 0, + 0, + 3981, + 3984, + 0, + 0, + 0, + 3983, + 0, + 0, + 0, + 0, + 0, + 3995, + 3986, + 3987, + 3988, + 3989, + 3990, + 3992, + 3993, + 3997, + 3998, + 3999, + 4000, + 4001, + 4201, + 0, + 0, + 4003, + 4007, + 4008, + 4009, + 4010, + 4011, + 4076, + 0, + 4021, + 4022, + 4023, + 4024, + 4025, + 4026, + 4029, + 4037, + 4031, + 4032, + 4033, + 4034, + 0, + 4547, + 4039, + 4038, + 4041, + 4040, + 4035, + 0, + 0, + 4036, + 4045, + 4044, + 4071, + 4043, + 4048, + 4050, + 4051, + 4052, + 4053, + 4054, + 4055, + 4057, + 4058, + 4060, + 4082, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4062, + 4068, + 4067, + 0, + 0, + 4069, + 0, + 4070, + 0, + 4064, + 4066, + 4073, + 4075, + 4077, + 4078, + 4079, + 4080, + 4081, + 4084, + 4085, + 4086, + 4087, + 4088, + 4090, + 4092, + 4094, + 4097, + 0, + 4096, + 0, + 0, + 4101, + 4571, + 4572, + 4573, + 4574, + 4100, + 0, + 4577, + 4578, + 4560, + 4561, + 4609, + 0, + 4610, + 0, + 0, + 4613, + 4104, + 4105, + 4106, + 4107, + 4108, + 4110, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4126, + 4112, + 4114, + 4116, + 4117, + 4119, + 4121, + 4123, + 4125, + 4128, + 4129, + 4130, + 4131, + 4132, + 4134, + 4137, + 4138, + 4139, + 4140, + 4141, + 4143, + 0, + 0, + 0, + 4202, + 4145, + 4189, + 0, + 0, + 4147, + 4149, + 0, + 0, + 4156, + 4151, + 4152, + 4153, + 4154, + 4155, + 4158, + 4159, + 4160, + 4161, + 4163, + 4162, + 4165, + 4166, + 4167, + 4168, + 4169, + 4171, + 4172, + 4173, + 4174, + 4175, + 4177, + 4179, + 4182, + 4181, + 4184, + 4185, + 4186, + 4187, + 4188, + 4190, + 4192, + 4193, + 4194, + 4195, + 4196, + 4199, + 4200, + 4204, + 4206, + 4209, + 4223, + 4213, + 4214, + 4216, + 4218, + 4219, + 4220, + 4221, + 4222, + 4224, + 4225, + 4226, + 4227, + 4232, + 0, + 0, + 4231, + 4235, + 0, + 0, + 0, + 4234, + 0, + 0, + 0, + 0, + 0, + 4261, + 4237, + 4238, + 4240, + 4242, + 4244, + 4246, + 4247, + 4248, + 4249, + 4250, + 4252, + 4253, + 4254, + 4255, + 4256, + 4258, + 4260, + 4264, + 4266, + 4267, + 4268, + 4269, + 4277, + 0, + 0, + 4270, + 0, + 0, + 0, + 4278, + 4272, + 4273, + 4274, + 4275, + 4276, + 4280, + 4281, + 4282, + 4283, + 4284, + 4286, + 4288, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4316, + 4290, + 4292, + 4293, + 4294, + 4295, + 4296, + 4297, + 4299, + 4300, + 4301, + 4302, + 4303, + 4305, + 4307, + 4309, + 4312, + 4311, + 0, + 0, + 0, + 0, + 0, + 4315, + 4314, + 4318, + 4320, + 4322, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4360, + 4324, + 4325, + 4326, + 4327, + 4328, + 4330, + 4331, + 4333, + 4340, + 4341, + 4349, + 4352, + 4354, + 4356, + 0, + 0, + 0, + 0, + 4359, + 4358, + 4362, + 4363, + 4364, + 4365, + 4366, + 4368, + 4370, + 4373, + 4374, + 4375, + 4376, + 4377, + 4381, + 4404, + 4405, + 0, + 4406, + 0, + 4407, + 4408, + 0, + 0, + 0, + 0, + 4383, + 4385, + 4387, + 4388, + 4391, + 4390, + 4393, + 4395, + 4398, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4414, + 4400, + 4402, + 4410, + 4412, + 4416, + 4418, + 4419, + 4420, + 4421, + 4422, + 4424, + 4427, + 0, + 0, + 0, + 4449, + 4450, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4429, + 4431, + 4432, + 4433, + 4434, + 4435, + 4467, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4437, + 4439, + 4441, + 4442, + 4444, + 4446, + 4448, + 4452, + 4453, + 4455, + 4459, + 4460, + 4461, + 4462, + 4463, + 4466, + 4470, + 4472, + 4474, + 4476, + 0, + 0, + 0, + 4479, + 0, + 0, + 0, + 0, + 0, + 4499, + 4478, + 4481, + 4483, + 4485, + 4487, + 4490, + 0, + 0, + 4491, + 4493, + 4494, + 4495, + 4496, + 4497, + 4498, + 4502, + 0, + 4501, + 4504, + 4506, + 4508, + 4509, + 4511, + 4517, + 4519, + 4520, + 4521, + 4522, + 4523, + 4526, + 4531, + 4533, + 4534, + 4536, + 4538, + 4540, + 4542, + 4544, + 4546, + 4548, + 4550, + 4552, + 4553, + 4554, + 4555, + 4557, + 4556, + 4559, + 4563, + 4564, + 4565, + 4566, + 4567, + 4570, + 4569, + 4576, + 4580, + 4581, + 4582, + 4583, + 4584, + 4585, + 4587, + 4589, + 4590, + 4592, + 4594, + 4596, + 4598, + 4599, + 4600, + 4601, + 4602, + 4604, + 4605, + 4606, + 4607, + 4608, + 4612, + 4615, + 4617, + 4619, + 4620, + 4621, + 4622, + 4623, + 4625, + 4627, + 4629, + 4630, + 4632, + 4637, + 0, + 0, + 0, + 4634, + 4636, + 4639, + 4642, + 4645, + 4644, + 0, + 0, + 0, + 0, + 4646, + 0, + 0, + 0, + 0, + 4694, + 4648, + 4649, + 4650, + 4651, + 4652, + 4653, + 4655, + 4657, + 4658, + 4660, + 4662, + 4671, + 0, + 0, + 4664, + 4666, + 4667, + 4668, + 4669, + 4670, + 4673, + 4676, + 0, + 4675, + 4678, + 4680, + 4681, + 4682, + 4683, + 4684, + 4687, + 4688, + 4689, + 4690, + 4691, + 4696, + 0, + 0, + 0, + 0, + 0, + 0, + 4697, +}; + diff --git a/source4/heimdal/lib/wind/normalize_table.h b/source4/heimdal/lib/wind/normalize_table.h new file mode 100644 index 00000000000..90b62e645d9 --- /dev/null +++ b/source4/heimdal/lib/wind/normalize_table.h @@ -0,0 +1,34 @@ +/* normalize_table.h */ +/* Automatically generated at 2008-03-18T11:38:08.923674 */ + +#ifndef NORMALIZE_TABLE_H +#define NORMALIZE_TABLE_H 1 + +#include <stddef.h> +#include <stdint.h> + +#define MAX_LENGTH_CANON 18 + +struct translation { + uint32_t key; + unsigned short val_len; + unsigned short val_offset; +}; + +extern const struct translation _wind_normalize_table[]; + +extern const uint32_t _wind_normalize_val_table[]; + +extern const size_t _wind_normalize_table_size; + +struct canon_node { + uint32_t val; + unsigned char next_start; + unsigned char next_end; + unsigned short next_offset; +}; + +extern const struct canon_node _wind_canon_table[]; + +extern const unsigned short _wind_canon_next_table[]; +#endif /* NORMALIZE_TABLE_H */ diff --git a/source4/heimdal/lib/wind/stringprep.c b/source4/heimdal/lib/wind/stringprep.c new file mode 100644 index 00000000000..0beba763840 --- /dev/null +++ b/source4/heimdal/lib/wind/stringprep.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2004, 2006, 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "windlocl.h" +#include <stdlib.h> +#include <strings.h> +#include <errno.h> + +RCSID("$Id: stringprep.c 22593 2008-02-12 11:58:01Z lha $"); + +/** + * Process a input UCS4 string according a string-prep profile. + * + * @param in input UCS4 string to process + * @param in_len length of the input string + * @param out output UCS4 string + * @param out_len length of the output string. + * @param flags stringprep profile. + * + * @return returns 0 on success, an wind error code otherwise + * @ingroup wind + */ + +int +wind_stringprep(const uint32_t *in, size_t in_len, + uint32_t *out, size_t *out_len, + wind_profile_flags flags) +{ + size_t tmp_len = in_len * 3; + uint32_t *tmp = malloc(tmp_len * sizeof(uint32_t)); + int ret; + size_t olen; + + if (tmp == NULL) + return ENOMEM; + + ret = _wind_stringprep_map(in, in_len, tmp, &tmp_len, flags); + if (ret) { + free(tmp); + return ret; + } + + olen = *out_len; + ret = _wind_stringprep_normalize(tmp, tmp_len, tmp, &olen); + if (ret) { + free(tmp); + return ret; + } + ret = _wind_stringprep_prohibited(tmp, olen, flags); + if (ret) { + free(tmp); + return ret; + } + ret = _wind_stringprep_testbidi(tmp, olen, flags); + if (ret) { + free(tmp); + return ret; + } + + /* Insignificant Character Handling for ldap-prep */ + if (flags & WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE) { + ret = _wind_ldap_case_exact_attribute(tmp, olen, out, out_len); +#if 0 + } else if (flags & WIND_PROFILE_LDAP_CASE_EXACT_ASSERTION) { + } else if (flags & WIND_PROFILE_LDAP_NUMERIC) { + } else if (flags & WIND_PROFILE_LDAP_TELEPHONE) { +#endif + } else { + memcpy(out, tmp, sizeof(out[0]) * olen); + *out_len = olen; + } + free(tmp); + + return ret; +} + +static struct { + const char *name; + wind_profile_flags flags; +} profiles[] = { + { "nameprep", WIND_PROFILE_NAME }, + { "saslprep", WIND_PROFILE_SASL }, + { "ldapprep", WIND_PROFILE_LDAP } +}; + +/** + * Try to find the profile given a name. + * + * @param name name of the profile. + * @param flags the resulting profile. + * + * @return returns 0 on success, an wind error code otherwise + * @ingroup wind + */ + +int +wind_profile(const char *name, wind_profile_flags *flags) +{ + unsigned int i; + + for (i = 0; i < sizeof(profiles)/sizeof(profiles[0]); i++) { + if (strcasecmp(profiles[i].name, name) == 0) { + *flags = profiles[i].flags; + return 0; + } + } + return WIND_ERR_NO_PROFILE; +} diff --git a/source4/heimdal/lib/wind/utf8.c b/source4/heimdal/lib/wind/utf8.c new file mode 100644 index 00000000000..c49e80522eb --- /dev/null +++ b/source4/heimdal/lib/wind/utf8.c @@ -0,0 +1,443 @@ +/* + * Copyright (c) 2004, 2006, 2007, 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "windlocl.h" + +RCSID("$Id: utf8.c 22572 2008-02-05 20:22:39Z lha $"); + +/** + * Convert an UTF-8 string to an UCS4 string. + * + * @param in an UTF-8 string to convert. + * @param out the resulting UCS4 strint, must be at least + * wind_utf8ucs4_length() long. If out is NULL, the function will + * calculate the needed space for the out variable (just like + * wind_utf8ucs4_length()). + * @param out_len before processing out_len should be the length of + * the out variable, after processing it will be the length of the out + * string. + * + * @return returns 0 on success, an wind error code otherwise + * @ingroup wind + */ + +int +wind_utf8ucs4(const char *in, uint32_t *out, size_t *out_len) +{ + const unsigned char *p; + size_t o = 0; + + for (p = (const unsigned char *)in; *p != '\0'; ++p) { + unsigned c = *p; + uint32_t u; + + if (c & 0x80) { + if ((c & 0xE0) == 0xC0) { + const unsigned c2 = *++p; + if ((c2 & 0xC0) == 0x80) { + u = ((c & 0x1F) << 6) + | (c2 & 0x3F); + } else { + return WIND_ERR_INVALID_UTF8; + } + } else if ((c & 0xF0) == 0xE0) { + const unsigned c2 = *++p; + if ((c2 & 0xC0) == 0x80) { + const unsigned c3 = *++p; + if ((c3 & 0xC0) == 0x80) { + u = ((c & 0x0F) << 12) + | ((c2 & 0x3F) << 6) + | (c3 & 0x3F); + } else { + return WIND_ERR_INVALID_UTF8; + } + } else { + return WIND_ERR_INVALID_UTF8; + } + } else if ((c & 0xF8) == 0xF0) { + const unsigned c2 = *++p; + if ((c2 & 0xC0) == 0x80) { + const unsigned c3 = *++p; + if ((c3 & 0xC0) == 0x80) { + const unsigned c4 = *++p; + if ((c4 & 0xC0) == 0x80) { + u = ((c & 0x07) << 18) + | ((c2 & 0x3F) << 12) + | ((c3 & 0x3F) << 6) + | (c4 & 0x3F); + } else { + return WIND_ERR_INVALID_UTF8; + } + } else { + return WIND_ERR_INVALID_UTF8; + } + } else { + return WIND_ERR_INVALID_UTF8; + } + } else { + return WIND_ERR_INVALID_UTF8; + } + } else { + u = c; + } + if (out) { + if (o >= *out_len) + return WIND_ERR_OVERRUN; + out[o] = u; + } + o++; + } + *out_len = o; + return 0; +} + +/** + * Calculate the length of from converting a UTF-8 string to a UCS4 + * string. + * + * @param in an UTF-8 string to convert. + * @param out_len the length of the resulting UCS4 string. + * + * @return returns 0 on success, an wind error code otherwise + * @ingroup wind + */ + +int +wind_utf8ucs4_length(const char *in, size_t *out_len) +{ + return wind_utf8ucs4(in, NULL, out_len); +} + +static const char first_char[4] = + { 0x00, 0xC0, 0xE0, 0xF0 }; + +/** + * Convert an UCS4 string to a UTF-8 string. + * + * @param in an UCS4 string to convert. + * @param in_len the length input array. + + * @param out the resulting UTF-8 strint, must be at least + * wind_ucs4utf8_length() + 1 long (the extra char for the NUL). If + * out is NULL, the function will calculate the needed space for the + * out variable (just like wind_ucs4utf8_length()). + + * @param out_len before processing out_len should be the length of + * the out variable, after processing it will be the length of the out + * string. + * + * @return returns 0 on success, an wind error code otherwise + * @ingroup wind + */ + +int +wind_ucs4utf8(const uint32_t *in, size_t in_len, char *out, size_t *out_len) +{ + uint32_t ch; + size_t i, len, o; + + for (o = 0, i = 0; i < in_len; i++) { + ch = in[i]; + + if (ch < 0x80) { + len = 1; + } else if (ch < 0x800) { + len = 2; + } else if (ch < 0x10000) { + len = 3; + } else if (ch <= 0x10FFFF) { + len = 4; + } else + return WIND_ERR_INVALID_UTF32; + + o += len; + + if (out) { + if (o >= *out_len) + return WIND_ERR_OVERRUN; + + switch(len) { + case 4: + out[3] = (ch | 0x80) & 0xbf; + ch = ch << 6; + case 3: + out[2] = (ch | 0x80) & 0xbf; + ch = ch << 6; + case 2: + out[1] = (ch | 0x80) & 0xbf; + ch = ch << 6; + case 1: + out[0] = ch | first_char[len - 1]; + } + } + out += len; + } + if (out) { + if (o + 1 >= *out_len) + return WIND_ERR_OVERRUN; + *out = '\0'; + } + *out_len = o; + return 0; +} + +/** + * Calculate the length of from converting a UCS4 string to an UTF-8 string. + * + * @param in an UCS4 string to convert. + * @param in_len the length of UCS4 string to convert. + * @param out_len the length of the resulting UTF-8 string. + * + * @return returns 0 on success, an wind error code otherwise + * @ingroup wind + */ + +int +wind_ucs4utf8_length(const uint32_t *in, size_t in_len, size_t *out_len) +{ + return wind_ucs4utf8(in, in_len, NULL, out_len); +} + +/** + * Read in an UCS2 from a buffer. + * + * @param ptr The input buffer to read from. + * @param len the length of the input buffer. + * @param flags Flags to control the behavior of the function. + * @param out the output UCS2, the array must be at least out/2 long. + * @param out_len the output length + * + * @return returns 0 on success, an wind error code otherwise. + * @ingroup wind + */ + +int +wind_ucs2read(const void *ptr, size_t len, unsigned int *flags, + uint16_t *out, size_t *out_len) +{ + const unsigned char *p = ptr; + int little = ((*flags) & WIND_RW_LE); + size_t olen = *out_len; + + /** if len is zero, flags are unchanged */ + if (len == 0) { + *out_len = 0; + return 0; + } + + /** if len is odd, WIND_ERR_LENGTH_NOT_MOD2 is returned */ + if (len & 1) + return WIND_ERR_LENGTH_NOT_MOD2; + + /** + * If the flags WIND_RW_BOM is set, check for BOM. If not BOM is + * found, check is LE/BE flag is already and use that otherwise + * fail with WIND_ERR_NO_BOM. When done, clear WIND_RW_BOM and + * the LE/BE flag and set the resulting LE/BE flag. + */ + if ((*flags) & WIND_RW_BOM) { + uint16_t bom = (p[0] << 8) + p[1]; + if (bom == 0xfffe || bom == 0xfeff) { + little = (bom == 0xfffe); + p += 2; + len -= 2; + } else if (((*flags) & (WIND_RW_LE|WIND_RW_BE)) != 0) { + /* little already set */ + } else + return WIND_ERR_NO_BOM; + *flags = ((*flags) & ~(WIND_RW_BOM|WIND_RW_LE|WIND_RW_BE)); + *flags |= little ? WIND_RW_LE : WIND_RW_BE; + } + + while (len) { + if (olen < 1) + return WIND_ERR_OVERRUN; + if (little) + *out = (p[1] << 8) + p[0]; + else + *out = (p[0] << 8) + p[1]; + out++; p += 2; len -= 2; olen--; + } + *out_len -= olen; + return 0; +} + +/** + * Write an UCS2 string to a buffer. + * + * @param in The input UCS2 string. + * @param in_len the length of the input buffer. + * @param flags Flags to control the behavior of the function. + * @param ptr The input buffer to write to, the array must be at least + * (in + 1) * 2 bytes long. + * @param out_len the output length + * + * @return returns 0 on success, an wind error code otherwise. + * @ingroup wind + */ + +int +wind_ucs2write(const uint16_t *in, size_t in_len, unsigned int *flags, + void *ptr, size_t *out_len) +{ + unsigned char *p = ptr; + size_t len = *out_len; + + /** If in buffer is not of length be mod 2, WIND_ERR_LENGTH_NOT_MOD2 is returned*/ + if (len & 1) + return WIND_ERR_LENGTH_NOT_MOD2; + + /** On zero input length, flags are preserved */ + if (in_len == 0) { + *out_len = 0; + return 0; + } + /** If flags have WIND_RW_BOM set, the byte order mark is written + * first to the output data */ + if ((*flags) & WIND_RW_BOM) { + uint16_t bom = 0xfffe; + + if (len < 2) + return WIND_ERR_OVERRUN; + + if ((*flags) & WIND_RW_LE) { + p[0] = (bom >> 8) & 0xff; + p[1] = (bom ) & 0xff; + } else { + p[1] = (bom ) & 0xff; + p[0] = (bom >> 8) & 0xff; + } + len -= 2; + } + + while (in_len) { + /** If the output wont fit into out_len, WIND_ERR_OVERRUN is returned */ + if (len < 2) + return WIND_ERR_OVERRUN; + if ((*flags) & WIND_RW_LE) { + p[0] = (in[0] >> 8) & 0xff; + p[1] = (in[0] ) & 0xff; + } else { + p[1] = (in[0] ) & 0xff; + p[0] = (in[0] >> 8) & 0xff; + } + len -= 2; + in_len--; + p += 2; + in++; + } + *out_len -= len; + return 0; +} + + +/** + * Convert an UCS2 string to a UTF-8 string. + * + * @param in an UCS2 string to convert. + * @param in_len the length of the in UCS2 string. + * @param out the resulting UTF-8 strint, must be at least + * wind_ucs2utf8_length() long. If out is NULL, the function will + * calculate the needed space for the out variable (just like + * wind_ucs2utf8_length()). + * @param out_len before processing out_len should be the length of + * the out variable, after processing it will be the length of the out + * string. + * + * @return returns 0 on success, an wind error code otherwise + * @ingroup wind + */ + +int +wind_ucs2utf8(const uint16_t *in, size_t in_len, char *out, size_t *out_len) +{ + uint16_t ch; + size_t i, len, o; + + for (o = 0, i = 0; i < in_len; i++) { + ch = in[i]; + + if (ch < 0x80) { + len = 1; + } else if (ch < 0x800) { + len = 2; + } else + len = 3; + + o += len; + + if (out) { + if (o >= *out_len) + return WIND_ERR_OVERRUN; + + switch(len) { + case 3: + out[2] = (ch | 0x80) & 0xbf; + ch = ch << 6; + case 2: + out[1] = (ch | 0x80) & 0xbf; + ch = ch << 6; + case 1: + out[0] = ch | first_char[len - 1]; + } + out += len; + } + } + if (out) { + if (o >= *out_len) + return WIND_ERR_OVERRUN; + *out = '\0'; + } + *out_len = o; + return 0; +} + +/** + * Calculate the length of from converting a UCS2 string to an UTF-8 string. + * + * @param in an UCS2 string to convert. + * @param in_len an UCS2 string length to convert. + * @param out_len the length of the resulting UTF-8 string. + * + * @return returns 0 on success, an wind error code otherwise + * @ingroup wind + */ + +int +wind_ucs2utf8_length(const uint16_t *in, size_t in_len, size_t *out_len) +{ + return wind_ucs2utf8(in, in_len, NULL, out_len); +} diff --git a/source4/heimdal/lib/wind/wind.h b/source4/heimdal/lib/wind/wind.h new file mode 100644 index 00000000000..6921b619f53 --- /dev/null +++ b/source4/heimdal/lib/wind/wind.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: wind.h 22595 2008-02-12 11:59:05Z lha $ */ + +#ifndef _WIND_H_ +#define _WIND_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <wind_err.h> + +typedef unsigned int wind_profile_flags; + +#define WIND_PROFILE_NAME 0x00000001 +#define WIND_PROFILE_SASL 0x00000002 +#define WIND_PROFILE_LDAP 0x00000004 + +#define WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE 0x00010000 +#define WIND_PROFILE_LDAP_CASE_EXACT_ASSERTION 0x00020000 +#define WIND_PROFILE_LDAP_NUMERIC 0x00040000 +#define WIND_PROFILE_LDAP_TELEPHONE 0x00080000 + + +/* flags to wind_ucs2read/wind_ucs2write */ +#define WIND_RW_LE 1 +#define WIND_RW_BE 2 +#define WIND_RW_BOM 4 + +int wind_stringprep(const unsigned *in, size_t in_len, + unsigned *out, size_t *out_len, + wind_profile_flags flags); +int wind_profile(const char *, wind_profile_flags *); + +int wind_punycode_label_toascii(const uint32_t *, size_t, + char *, size_t *); + +int wind_utf8ucs4(const char *, uint32_t *, size_t *); +int wind_utf8ucs4_length(const char *, size_t *); + +int wind_ucs4utf8(const uint32_t *, size_t, char *, size_t *); +int wind_ucs4utf8_length(const uint32_t *, size_t, size_t *); + +int wind_ucs2utf8(const uint16_t *, size_t, char *, size_t *); +int wind_ucs2utf8_length(const uint16_t *, size_t, size_t *); + + +int wind_ucs2read(const void *, size_t, unsigned int *, uint16_t *, size_t *); +int wind_ucs2write(const uint16_t *, size_t, unsigned int *, void *, size_t *); + +#endif /* _WIND_H_ */ diff --git a/source4/heimdal/lib/wind/wind_err.et b/source4/heimdal/lib/wind/wind_err.et new file mode 100644 index 00000000000..025c402790b --- /dev/null +++ b/source4/heimdal/lib/wind/wind_err.et @@ -0,0 +1,22 @@ +# +# Error messages for the wind library +# +# This might look like a com_err file, but is not +# +id "$Id: wind_err.et 22559 2008-02-03 16:35:07Z lha $" + +error_table wind + +prefix WIND_ERR +error_code NONE, "No error" +error_code NO_PROFILE, "No such profile" +error_code OVERRUN, "Buffer overrun" +error_code UNDERUN, "Buffer underrun" +error_code LENGTH_NOT_MOD2, "Lenght not mod2" +error_code LENGTH_NOT_MOD4, "Lenght not mod4" +error_code INVALID_UTF8, "Invalid UTF-8 combination in string" +error_code INVALID_UTF16, "Invalid UTF-16 combination in string" +error_code INVALID_UTF32, "Invalid UTF-32 combination in string" +error_code NO_BOM, "No byte order mark (BOM) in string" + +end diff --git a/source4/heimdal/lib/wind/windlocl.h b/source4/heimdal/lib/wind/windlocl.h new file mode 100644 index 00000000000..02e8c46481c --- /dev/null +++ b/source4/heimdal/lib/wind/windlocl.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: windlocl.h 22582 2008-02-11 20:43:50Z lha $ */ + +#ifndef _WINDLOCL_H_ +#define _WINDLOCL_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "wind.h" +#include "wind_err.h" + +int _wind_combining_class(uint32_t); + +int _wind_stringprep_testbidi(const uint32_t *, size_t, wind_profile_flags); + +int _wind_stringprep_error(const uint32_t, wind_profile_flags); + +int _wind_stringprep_prohibited(const uint32_t *, size_t, wind_profile_flags); + +int _wind_stringprep_map(const uint32_t *, size_t, + uint32_t *, size_t *, + wind_profile_flags); + +int _wind_stringprep_normalize(const uint32_t *, size_t, uint32_t *, size_t *); + +int _wind_ldap_case_exact_attribute(const uint32_t *, size_t, + uint32_t *, size_t *); + + +#endif /* _WINDLOCL_H_ */ diff --git a/source4/heimdal_build/config.h b/source4/heimdal_build/config.h index 7a51def3c61..e2c735a65f8 100644 --- a/source4/heimdal_build/config.h +++ b/source4/heimdal_build/config.h @@ -19,4 +19,6 @@ #define SIGRETURN(x) return (RETSIGTYPE)(x) #endif +#define HDB_DB_DIR "" + #endif diff --git a/source4/heimdal_build/config.mk b/source4/heimdal_build/config.mk index d3d87f7a70f..d58d06f909b 100644 --- a/source4/heimdal_build/config.mk +++ b/source4/heimdal_build/config.mk @@ -46,6 +46,7 @@ PRIVATE_DEPENDENCIES = HDB_LDB HEIMDAL_KRB5 HEIMDAL_HDB_KEYS HEIMDAL_ROKEN HEIMD HEIMDAL_HDB_OBJ_FILES = \ ./heimdal/lib/hdb/db.o \ + ./heimdal/lib/hdb/dbinfo.o \ ./heimdal/lib/hdb/hdb.o \ ./heimdal/lib/hdb/ext.o \ ./heimdal/lib/hdb/keytab.o \ @@ -175,7 +176,7 @@ HEIMDAL_GSSAPI_OBJ_FILES = \ # Start SUBSYSTEM HEIMDAL_KRB5 [SUBSYSTEM::HEIMDAL_KRB5] CFLAGS = -Iheimdal_build -Iheimdal/lib/krb5 -PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN HEIMDAL_PKINIT_ASN1 +PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN HEIMDAL_PKINIT_ASN1 HEIMDAL_WIND PUBLIC_DEPENDENCIES = HEIMDAL_KRB5_ASN1 HEIMDAL_GLUE HEIMDAL_HX509 HEIMDAL_HCRYPTO # End SUBSYSTEM HEIMDAL_KRB5 ####################### @@ -334,8 +335,9 @@ HEIMDAL_HCRYPTO_OBJ_FILES = \ ./heimdal/lib/hcrypto/rand-unix.o \ ./heimdal/lib/hcrypto/rand-fortuna.o \ ./heimdal/lib/hcrypto/rand-timer.o \ - ./heimdal/lib/hcrypto/hmac.o - + ./heimdal/lib/hcrypto/hmac.o \ + ./heimdal/lib/hcrypto/camellia.o \ + ./heimdal/lib/hcrypto/camellia-ntt.o ####################### # Start SUBSYSTEM HEIMDAL_HX509 @@ -347,7 +349,8 @@ PRIVATE_DEPENDENCIES = \ HEIMDAL_CMS_ASN1 HEIMDAL_RFC2459_ASN1 \ HEIMDAL_OCSP_ASN1 HEIMDAL_PKCS8_ASN1 \ HEIMDAL_PKCS9_ASN1 HEIMDAL_PKCS12_ASN1 \ - HEIMDAL_PKINIT_ASN1 HEIMDAL_PKCS10_ASN1 + HEIMDAL_PKINIT_ASN1 HEIMDAL_PKCS10_ASN1 \ + HEIMDAL_WIND # End SUBSYSTEM HEIMDAL_HX509 ####################### @@ -376,6 +379,31 @@ HEIMDAL_HX509_OBJ_FILES = \ ./heimdal/lib/hx509/revoke.o \ ./heimdal/lib/hx509/hx509_err.o +####################### +# Start SUBSYSTEM HEIMDAL_WIND +[SUBSYSTEM::HEIMDAL_WIND] +CFLAGS = -Iheimdal_build -Iheimdal/lib/wind +PRIVATE_DEPENDENCIES = \ + HEIMDAL_ROKEN HEIMDAL_COM_ERR + +HEIMDAL_WIND_OBJ_FILES = \ + ./heimdal/lib/wind/wind_err.o \ + ./heimdal/lib/wind/stringprep.o \ + ./heimdal/lib/wind/errorlist.o \ + ./heimdal/lib/wind/errorlist_table.o \ + ./heimdal/lib/wind/normalize.o \ + ./heimdal/lib/wind/normalize_table.o \ + ./heimdal/lib/wind/combining.o \ + ./heimdal/lib/wind/combining_table.o \ + ./heimdal/lib/wind/utf8.o \ + ./heimdal/lib/wind/bidi.o \ + ./heimdal/lib/wind/bidi_table.o \ + ./heimdal/lib/wind/ldap.o \ + ./heimdal/lib/wind/map.o \ + ./heimdal/lib/wind/map_table.o +# End SUBSYSTEM HEIMDAL_WIND +####################### + [SUBSYSTEM::HEIMDAL_ROKEN_GETPROGNAME] CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper @@ -399,7 +427,7 @@ PUBLIC_DEPENDENCIES = \ HEIMDAL_ROKEN_GETPROGNAME \ HEIMDAL_ROKEN_CLOSEFROM \ RESOLV \ - EXT_SOCKET + LIBREPLACE_NETWORK # End SUBSYSTEM HEIMDAL_ROKEN ####################### @@ -470,7 +498,7 @@ HEIMDAL_ASN1_COMPILE_LEX_OBJ_FILES = ./heimdal/lib/asn1/lex.ho [BINARY::asn1_compile] CFLAGS = -Iheimdal_build -Iheimdal/lib/roken USE_HOSTCC = YES -PRIVATE_DEPENDENCIES = HEIMDAL_ASN1_COMPILE_LEX HEIMDAL_ROKEN_GETPROGNAME_H EXT_SOCKET EXT_NSL +PRIVATE_DEPENDENCIES = HEIMDAL_ASN1_COMPILE_LEX HEIMDAL_ROKEN_GETPROGNAME_H LIBREPLACE_NETWORK asn1_compile_OBJ_FILES = \ ./heimdal/lib/asn1/main.ho \ @@ -513,7 +541,7 @@ HEIMDAL_COM_ERR_COMPILE_LEX_OBJ_FILES = ./heimdal/lib/com_err/lex.ho [BINARY::compile_et] CFLAGS = -Iheimdal_build -Iheimdal/lib/roken USE_HOSTCC = YES -PRIVATE_DEPENDENCIES = HEIMDAL_COM_ERR_COMPILE_LEX HEIMDAL_ROKEN_GETPROGNAME_H EXT_SOCKET EXT_NSL +PRIVATE_DEPENDENCIES = HEIMDAL_COM_ERR_COMPILE_LEX HEIMDAL_ROKEN_GETPROGNAME_H LIBREPLACE_NETWORK # End BINARY compile_et ####################### @@ -554,6 +582,7 @@ mkinclude perl_path_wrapper.sh et_deps.pl heimdal/lib/krb5/krb_err.et heimdal/li mkinclude perl_path_wrapper.sh et_deps.pl heimdal/lib/krb5/krb5_err.et heimdal/lib/krb5| mkinclude perl_path_wrapper.sh et_deps.pl heimdal/lib/gssapi/krb5/gkrb5_err.et heimdal/lib/gssapi| mkinclude perl_path_wrapper.sh et_deps.pl heimdal/lib/hx509/hx509_err.et heimdal/lib/hx509| +mkinclude perl_path_wrapper.sh et_deps.pl heimdal/lib/wind/wind_err.et heimdal/lib/wind| clean:: @-rm -f bin/compile_et bin/asn1_compile diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c index bc5a45ae2bb..d983b77b40d 100644 --- a/source4/kdc/hdb-ldb.c +++ b/source4/kdc/hdb-ldb.c @@ -510,7 +510,7 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, entry_ex->entry.valid_start = NULL; - acct_expiry = samdb_result_account_expires(msg, 0); + acct_expiry = samdb_result_account_expires(msg); if (acct_expiry == 0x7FFFFFFFFFFFFFFFULL) { entry_ex->entry.valid_end = NULL; } else { diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c index 92a5dc26e0a..72b5bb14a93 100644 --- a/source4/kdc/kdc.c +++ b/source4/kdc/kdc.c @@ -639,9 +639,9 @@ static void kdc_task_init(struct task_server *task) } /* Registar WinDC hooks */ - ret = _krb5_plugin_register(kdc->smb_krb5_context->krb5_context, - PLUGIN_TYPE_DATA, "windc", - &windc_plugin_table); + ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context, + PLUGIN_TYPE_DATA, "windc", + &windc_plugin_table); if(ret) { task_server_terminate(task, "kdc: failed to register hdb keytab"); return; diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 66f36af870f..1c68d4c37de 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -220,13 +220,47 @@ krb5_error_code samba_kdc_reget_pac(void *priv, krb5_context context, return ret; } +static void samba_kdc_build_edata_reply(TALLOC_CTX *tmp_ctx, krb5_data *e_data, + NTSTATUS nt_status) +{ + PA_DATA pa; + unsigned char *buf; + size_t len; + krb5_error_code ret = 0; + + if (!e_data) + return; + + pa.padata_type = KRB5_PADATA_PW_SALT; + pa.padata_value.length = 12; + pa.padata_value.data = malloc(pa.padata_value.length); + if (!pa.padata_value.data) { + e_data->length = 0; + e_data->data = NULL; + return; + } + + SIVAL(pa.padata_value.data, 0, NT_STATUS_V(nt_status)); + SIVAL(pa.padata_value.data, 4, 0); + SIVAL(pa.padata_value.data, 8, 1); + + ASN1_MALLOC_ENCODE(PA_DATA, buf, len, &pa, &len, ret); + free(pa.padata_value.data); + + e_data->data = buf; + e_data->length = len; + + return; +} + /* Given an hdb entry (and in particular it's private member), consult * the account_ok routine in auth/auth_sam.c for consistancy */ krb5_error_code samba_kdc_check_client_access(void *priv, krb5_context context, hdb_entry_ex *entry_ex, - KDC_REQ *req) + KDC_REQ *req, + krb5_data *e_data) { krb5_error_code ret; NTSTATUS nt_status; @@ -274,30 +308,28 @@ krb5_error_code samba_kdc_check_client_access(void *priv, name); free(name); - /* TODO: Need a more complete mapping of NTSTATUS to krb5kdc errors */ - - /* TODO: Also need to add the appropriate e-data struct of type - * PA-PW-SALT (3) that includes the NT_STATUS code, which gives Windows - * the information it needs to display the appropriate dialog. */ + if (NT_STATUS_IS_OK(nt_status)) + return 0; if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE)) - return KRB5KDC_ERR_KEY_EXPIRED; + ret = KRB5KDC_ERR_KEY_EXPIRED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED)) - return KRB5KDC_ERR_KEY_EXPIRED; + ret = KRB5KDC_ERR_KEY_EXPIRED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_EXPIRED)) - return KRB5KDC_ERR_CLIENT_REVOKED; + ret = KRB5KDC_ERR_CLIENT_REVOKED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) - return KRB5KDC_ERR_CLIENT_REVOKED; + ret = KRB5KDC_ERR_CLIENT_REVOKED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_LOGON_HOURS)) - return KRB5KDC_ERR_CLIENT_REVOKED; + ret = KRB5KDC_ERR_CLIENT_REVOKED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_LOCKED_OUT)) - return KRB5KDC_ERR_CLIENT_REVOKED; + ret = KRB5KDC_ERR_CLIENT_REVOKED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_WORKSTATION)) - return KRB5KDC_ERR_POLICY; - else if (!NT_STATUS_IS_OK(nt_status)) { - return KRB5KDC_ERR_POLICY; - } + ret = KRB5KDC_ERR_POLICY; + else + ret = KRB5KDC_ERR_POLICY; - return 0; + samba_kdc_build_edata_reply(tmp_ctx, e_data, nt_status); + + return ret; } diff --git a/source4/lib/events/events_signal.c b/source4/lib/events/events_signal.c index aec34339c36..c0771cbe01f 100644 --- a/source4/lib/events/events_signal.c +++ b/source4/lib/events/events_signal.c @@ -257,7 +257,7 @@ int common_event_check_signal(struct event_context *ev) for (j=0;j<count;j++) { /* note the use of the sig_info array as a ring buffer */ - int ofs = (counter.count + j) % SA_INFO_QUEUE_COUNT; + int ofs = ((count-1) + j) % SA_INFO_QUEUE_COUNT; se->handler(ev, se, i, 1, (void*)&sig_state->sig_info[i][ofs], se->private_data); diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index d88f82b726f..a53c5542da3 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -121,7 +121,7 @@ distclean:: clean rm -f Makefile realdistclean:: distclean - rm -f configure.in include/config.h.in + rm -f configure include/config.h.in check:: test @PYTHON_CHECK_TARGET@ diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 3c9ef3ff693..b51c2889938 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -65,7 +65,7 @@ static struct backends_list_entry { #ifdef HAVE_LDB_LDAP #define LDAP_INIT &ldb_ldap_backend_ops, \ - &ldb_ildap_backend_ops, \ + &ldb_ldapi_backend_ops, \ &ldb_ldaps_backend_ops, #else #define LDAP_INIT diff --git a/source4/lib/ldb/include/ldb_includes.h b/source4/lib/ldb/include/ldb_includes.h index e2bcca2b04b..cc9b46ac1ff 100644 --- a/source4/lib/ldb/include/ldb_includes.h +++ b/source4/lib/ldb/include/ldb_includes.h @@ -18,7 +18,6 @@ #include "replace.h" #include "system/filesys.h" -#include "system/network.h" #include "system/time.h" #include "talloc.h" #include "ldb.h" diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 880aafd5938..ea8533bc38f 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -200,7 +200,7 @@ extern const struct ldb_module_ops ldb_ranged_results_module_ops; extern const struct ldb_backend_ops ldb_tdb_backend_ops; extern const struct ldb_backend_ops ldb_sqlite3_backend_ops; extern const struct ldb_backend_ops ldb_ldap_backend_ops; -extern const struct ldb_backend_ops ldb_ildap_backend_ops; +extern const struct ldb_backend_ops ldb_ldapi_backend_ops; extern const struct ldb_backend_ops ldb_ldaps_backend_ops; int ldb_match_msg(struct ldb_context *ldb, diff --git a/source4/lib/ldb/ldb.i b/source4/lib/ldb/ldb.i index 0d9679d21e9..e01a1107d25 100644 --- a/source4/lib/ldb/ldb.i +++ b/source4/lib/ldb/ldb.i @@ -257,12 +257,19 @@ int ldb_dn_from_pyobject(TALLOC_CTX *mem_ctx, PyObject *object, int ret; struct ldb_dn *odn; if (ldb_ctx != NULL && PyString_Check(object)) { - *dn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object)); + odn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object)); + if (!odn) { + return SWIG_ERROR; + } + *dn = odn; return 0; } ret = SWIG_ConvertPtr(object, (void **)&odn, SWIGTYPE_p_ldb_dn, SWIG_POINTER_EXCEPTION); *dn = ldb_dn_copy(mem_ctx, odn); + if (odn && !*dn) { + return SWIG_ERROR; + } return ret; } @@ -462,6 +469,8 @@ typedef struct ldb_ldif ldb_ldif; #ifdef SWIGPYTHON %{ +static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0); + static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) { char *text; @@ -557,22 +566,29 @@ PyObject *PyExc_LdbError; }; %typemap(in,numinputs=1) ldb_msg *add_msg { - int dict_pos, msg_pos; - PyObject *key, *value; + Py_ssize_t dict_pos, msg_pos; ldb_msg_element *msgel; + PyObject *key, *value; if (PyDict_Check($input)) { + PyObject *dn_value = PyDict_GetItemString($input, "dn"); $1 = ldb_msg_new(NULL); $1->elements = talloc_zero_array($1, struct ldb_message_element, PyDict_Size($input)); msg_pos = dict_pos = 0; - while (PyDict_Next($input, &dict_pos, &key, &value)) { - if (!strcmp(PyString_AsString(key), "dn")) { - /* using argp0 (magic SWIG value) here is a hack */ - if (ldb_dn_from_pyobject($1, value, argp1, &$1->dn) != 0) { + if (dn_value) { + /* using argp1 (magic SWIG value) here is a hack */ + if (ldb_dn_from_pyobject($1, dn_value, argp1, &$1->dn) != 0) { SWIG_exception(SWIG_TypeError, "unable to import dn object"); } - } else { - msgel = ldb_msg_element_from_pyobject($1->elements, value, 0, PyString_AsString(key)); + if ($1->dn == NULL) { + SWIG_exception(SWIG_TypeError, "dn set but not found"); + } + } + + while (PyDict_Next($input, &dict_pos, &key, &value)) { + char *key_str = PyString_AsString(key); + if (strcmp(key_str, "dn") != 0) { + msgel = ldb_msg_element_from_pyobject($1->elements, value, 0, key_str); if (msgel == NULL) { SWIG_exception(SWIG_TypeError, "unable to import element"); } diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 3f6ff3fd5b8..a4534c549ad 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -826,17 +826,17 @@ failed: return -1; } -_PUBLIC_ struct ldb_backend_ops ldb_ldap_backend_ops = { +const struct ldb_backend_ops ldb_ldap_backend_ops = { .name = "ldap", .connect_fn = lldb_connect }; -_PUBLIC_ struct ldb_backend_ops ldb_ldapi_backend_ops = { +const struct ldb_backend_ops ldb_ldapi_backend_ops = { .name = "ldapi", .connect_fn = lldb_connect }; -_PUBLIC_ struct ldb_backend_ops ldb_ldaps_backend_ops = { +const struct ldb_backend_ops ldb_ldaps_backend_ops = { .name = "ldaps", .connect_fn = lldb_connect }; diff --git a/source4/lib/ldb/ldb_wrap.c b/source4/lib/ldb/ldb_wrap.c index cf05048b021..082c6d9cad5 100644 --- a/source4/lib/ldb/ldb_wrap.c +++ b/source4/lib/ldb/ldb_wrap.c @@ -2471,7 +2471,7 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) #define SWIGTYPE_p_ldb_module_ops swig_types[9] #define SWIGTYPE_p_ldb_result swig_types[10] #define SWIGTYPE_p_ldb_val swig_types[11] -#define SWIGTYPE_p_long_long swig_types[12] +#define SWIGTYPE_p_long swig_types[12] #define SWIGTYPE_p_p_char swig_types[13] #define SWIGTYPE_p_p_ldb_control swig_types[14] #define SWIGTYPE_p_p_ldb_result swig_types[15] @@ -2480,11 +2480,10 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) #define SWIGTYPE_p_unsigned_char swig_types[18] #define SWIGTYPE_p_unsigned_int swig_types[19] #define SWIGTYPE_p_unsigned_long swig_types[20] -#define SWIGTYPE_p_unsigned_long_long swig_types[21] -#define SWIGTYPE_p_unsigned_short swig_types[22] -#define SWIGTYPE_p_void swig_types[23] -static swig_type_info *swig_types[25]; -static swig_module_info swig_module = {swig_types, 24, 0, 0, 0, 0}; +#define SWIGTYPE_p_unsigned_short swig_types[21] +#define SWIGTYPE_p_void swig_types[22] +static swig_type_info *swig_types[24]; +static swig_module_info swig_module = {swig_types, 23, 0, 0, 0, 0}; #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) @@ -2713,12 +2712,19 @@ int ldb_dn_from_pyobject(TALLOC_CTX *mem_ctx, PyObject *object, int ret; struct ldb_dn *odn; if (ldb_ctx != NULL && PyString_Check(object)) { - *dn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object)); + odn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object)); + if (!odn) { + return SWIG_ERROR; + } + *dn = odn; return 0; } ret = SWIG_ConvertPtr(object, (void **)&odn, SWIGTYPE_p_ldb_dn, SWIG_POINTER_EXCEPTION); *dn = ldb_dn_copy(mem_ctx, odn); + if (odn && !*dn) { + return SWIG_ERROR; + } return ret; } @@ -2992,6 +2998,8 @@ SWIGINTERN PyObject *ldb_msg___iter__(ldb_msg *self){ return PyObject_GetIter(ldb_msg_list_elements(self)); } +static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0); + static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) { char *text; @@ -4708,22 +4716,29 @@ SWIGINTERN PyObject *_wrap_Ldb_add(PyObject *SWIGUNUSEDPARM(self), PyObject *arg } arg1 = (ldb *)(argp1); { - int dict_pos, msg_pos; - PyObject *key, *value; + Py_ssize_t dict_pos, msg_pos; ldb_msg_element *msgel; + PyObject *key, *value; if (PyDict_Check(obj1)) { + PyObject *dn_value = PyDict_GetItemString(obj1, "dn"); arg2 = ldb_msg_new(NULL); arg2->elements = talloc_zero_array(arg2, struct ldb_message_element, PyDict_Size(obj1)); msg_pos = dict_pos = 0; + if (dn_value) { + /* using argp1 (magic SWIG value) here is a hack */ + if (ldb_dn_from_pyobject(arg2, dn_value, argp1, &arg2->dn) != 0) { + SWIG_exception(SWIG_TypeError, "unable to import dn object"); + } + if (arg2->dn == NULL) { + SWIG_exception(SWIG_TypeError, "dn set but not found"); + } + } + while (PyDict_Next(obj1, &dict_pos, &key, &value)) { - if (!strcmp(PyString_AsString(key), "dn")) { - /* using argp0 (magic SWIG value) here is a hack */ - if (ldb_dn_from_pyobject(arg2, value, argp1, &arg2->dn) != 0) { - SWIG_exception(SWIG_TypeError, "unable to import dn object"); - } - } else { - msgel = ldb_msg_element_from_pyobject(arg2->elements, value, 0, PyString_AsString(key)); + char *key_str = PyString_AsString(key); + if (strcmp(key_str, "dn") != 0) { + msgel = ldb_msg_element_from_pyobject(arg2->elements, value, 0, key_str); if (msgel == NULL) { SWIG_exception(SWIG_TypeError, "unable to import element"); } @@ -5696,7 +5711,7 @@ static PyMethodDef SwigMethods[] = { static swig_type_info _swigt__p_TALLOC_CTX = {"_p_TALLOC_CTX", "TALLOC_CTX *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_f_p_void_enum_ldb_debug_level_p_q_const__char_va_list__void = {"_p_f_p_void_enum_ldb_debug_level_p_q_const__char_va_list__void", "void (*)(void *,enum ldb_debug_level,char const *,va_list)", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_int = {"_p_int", "int *|int_least32_t *|int32_t *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_context = {"_p_ldb_context", "struct ldb_context *|ldb *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_dn = {"_p_ldb_dn", "struct ldb_dn *|ldb_dn *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_ldif = {"_p_ldb_ldif", "struct ldb_ldif *|ldb_ldif *", 0, 0, (void*)0, 0}; @@ -5705,16 +5720,15 @@ static swig_type_info _swigt__p_ldb_message_element = {"_p_ldb_message_element", static swig_type_info _swigt__p_ldb_module_ops = {"_p_ldb_module_ops", "struct ldb_module_ops *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_result = {"_p_ldb_result", "struct ldb_result *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_val = {"_p_ldb_val", "struct ldb_val *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_long = {"_p_long", "intptr_t *|int_least64_t *|int_fast32_t *|int_fast64_t *|int64_t *|long *|int_fast16_t *|intmax_t *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_p_ldb_control = {"_p_p_ldb_control", "struct ldb_control **", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_p_ldb_result = {"_p_p_ldb_result", "struct ldb_result **", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_signed_char = {"_p_signed_char", "signed char *|int_least8_t *|int_fast8_t *|int8_t *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "unsigned char *|uint_least8_t *|uint_fast8_t *|uint8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uintptr_t *|uint_least32_t *|uint_fast32_t *|uint32_t *|unsigned int *|uint_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_long = {"_p_unsigned_long", "unsigned long *|time_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_long_long = {"_p_unsigned_long_long", "uint_least64_t *|uint_fast64_t *|uint64_t *|unsigned long long *|uintmax_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uint_least32_t *|uint32_t *|unsigned int *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_long = {"_p_unsigned_long", "uintptr_t *|uint_least64_t *|uint_fast32_t *|uint_fast64_t *|uint64_t *|unsigned long *|time_t *|uint_fast16_t *|uintmax_t *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned short *|uint_least16_t *|uint16_t *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_void = {"_p_void", "void *", 0, 0, (void*)0, 0}; @@ -5731,7 +5745,7 @@ static swig_type_info *swig_type_initial[] = { &_swigt__p_ldb_module_ops, &_swigt__p_ldb_result, &_swigt__p_ldb_val, - &_swigt__p_long_long, + &_swigt__p_long, &_swigt__p_p_char, &_swigt__p_p_ldb_control, &_swigt__p_p_ldb_result, @@ -5740,7 +5754,6 @@ static swig_type_info *swig_type_initial[] = { &_swigt__p_unsigned_char, &_swigt__p_unsigned_int, &_swigt__p_unsigned_long, - &_swigt__p_unsigned_long_long, &_swigt__p_unsigned_short, &_swigt__p_void, }; @@ -5757,7 +5770,7 @@ static swig_cast_info _swigc__p_ldb_message_element[] = { {&_swigt__p_ldb_messa static swig_cast_info _swigc__p_ldb_module_ops[] = { {&_swigt__p_ldb_module_ops, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ldb_result[] = { {&_swigt__p_ldb_result, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ldb_val[] = { {&_swigt__p_ldb_val, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_long[] = { {&_swigt__p_long, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_p_char[] = { {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_p_ldb_control[] = { {&_swigt__p_p_ldb_control, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_p_ldb_result[] = { {&_swigt__p_p_ldb_result, 0, 0, 0},{0, 0, 0, 0}}; @@ -5766,7 +5779,6 @@ static swig_cast_info _swigc__p_signed_char[] = { {&_swigt__p_signed_char, 0, 0 static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_unsigned_int[] = { {&_swigt__p_unsigned_int, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_unsigned_long[] = { {&_swigt__p_unsigned_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_long_long[] = { {&_swigt__p_unsigned_long_long, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_void[] = { {&_swigt__p_void, 0, 0, 0},{0, 0, 0, 0}}; @@ -5783,7 +5795,7 @@ static swig_cast_info *swig_cast_initial[] = { _swigc__p_ldb_module_ops, _swigc__p_ldb_result, _swigc__p_ldb_val, - _swigc__p_long_long, + _swigc__p_long, _swigc__p_p_char, _swigc__p_p_ldb_control, _swigc__p_p_ldb_result, @@ -5792,7 +5804,6 @@ static swig_cast_info *swig_cast_initial[] = { _swigc__p_unsigned_char, _swigc__p_unsigned_int, _swigc__p_unsigned_long, - _swigc__p_unsigned_long_long, _swigc__p_unsigned_short, _swigc__p_void, }; diff --git a/source4/lib/ldb/rules.mk b/source4/lib/ldb/rules.mk index 534ba016ab7..ff5dc027429 100644 --- a/source4/lib/ldb/rules.mk +++ b/source4/lib/ldb/rules.mk @@ -7,7 +7,7 @@ ctags: .SUFFIXES: _wrap.c .i .i_wrap.c: - [ "$(SWIG)" == "no" ] || $(SWIG) -O -Wall -python -keyword $< + [ "$(SWIG)" = "no" ] || $(SWIG) -O -Wall -python -keyword $< .SUFFIXES: .1 .1.xml .3 .3.xml .xml .html .c .o diff --git a/source4/lib/ldb/tests/sample_module.c b/source4/lib/ldb/tests/sample_module.c index 98d8e865dd0..1a9e72c907b 100644 --- a/source4/lib/ldb/tests/sample_module.c +++ b/source4/lib/ldb/tests/sample_module.c @@ -32,7 +32,7 @@ int sample_add(struct ldb_module *mod, struct ldb_request *req) return ldb_next_request(mod, req); } -_PUBLIC_ const struct ldb_module_ops ldb_sample_module_ops = { +const struct ldb_module_ops ldb_sample_module_ops = { .name = "sample", .add = sample_add, }; diff --git a/source4/lib/ldb/tests/test-soloading.sh b/source4/lib/ldb/tests/test-soloading.sh index c42c9b22bae..da6d57541e5 100755 --- a/source4/lib/ldb/tests/test-soloading.sh +++ b/source4/lib/ldb/tests/test-soloading.sh @@ -19,7 +19,7 @@ fi cat <<EOF | $VALGRIND ldbadd || exit 1 dn: @MODULES -@LIST: sample_module +@LIST: sample EOF cat <<EOF | $VALGRIND ldbadd || exit 1 diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 6a879ab9627..29d6e002477 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -462,6 +462,8 @@ NTSTATUS messaging_send(struct messaging_context *msg, struct server_id server, rec->retries = 0; rec->msg = msg; rec->header = (struct messaging_header *)rec->packet.data; + /* zero padding */ + ZERO_STRUCTP(rec->header); rec->header->version = MESSAGING_VERSION; rec->header->msg_type = msg_type; rec->header->from = msg->server_id; diff --git a/source4/lib/registry/registry_wrap.c b/source4/lib/registry/registry_wrap.c index c5741b7e2c9..51c255e9f70 100644 --- a/source4/lib/registry/registry_wrap.c +++ b/source4/lib/registry/registry_wrap.c @@ -2950,7 +2950,7 @@ SWIGINTERN PyObject *_wrap_Registry(PyObject *SWIGUNUSEDPARM(self), PyObject *ar } result = reg_open_local(arg1,arg2,arg3,arg4); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3001,7 +3001,7 @@ SWIGINTERN PyObject *_wrap_reg_get_predefined_key_by_name(PyObject *SWIGUNUSEDPA arg3 = (struct registry_key **)(argp3); result = reg_get_predefined_key_by_name(arg1,(char const *)arg2,arg3); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3044,7 +3044,7 @@ SWIGINTERN PyObject *_wrap_reg_key_del_abs(PyObject *SWIGUNUSEDPARM(self), PyObj arg2 = (char *)(buf2); result = reg_key_del_abs(arg1,(char const *)arg2); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3095,7 +3095,7 @@ SWIGINTERN PyObject *_wrap_reg_get_predefined_key(PyObject *SWIGUNUSEDPARM(self) arg3 = (struct registry_key **)(argp3); result = reg_get_predefined_key(arg1,arg2,arg3); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3136,7 +3136,7 @@ SWIGINTERN PyObject *_wrap_reg_diff_apply(PyObject *SWIGUNUSEDPARM(self), PyObje arg2 = (char *)(buf2); result = reg_diff_apply(arg1,(char const *)arg2); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3194,7 +3194,7 @@ SWIGINTERN PyObject *_wrap_reg_generate_diff(PyObject *SWIGUNUSEDPARM(self), PyO } result = reg_generate_diff(arg1,arg2,(struct reg_diff_callbacks const *)arg3,arg4); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3260,7 +3260,7 @@ SWIGINTERN PyObject *_wrap_reg_mount_hive__SWIG_0(PyObject *SWIGUNUSEDPARM(self) } result = reg_mount_hive(arg1,arg2,arg3,(char const **)arg4); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3373,7 +3373,7 @@ SWIGINTERN PyObject *_wrap_reg_mount_hive__SWIG_1(PyObject *SWIGUNUSEDPARM(self) arg3 = (char *)(buf3); result = reg_mount_hive__SWIG_1(arg1,arg2,(char const *)arg3); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3524,7 +3524,7 @@ SWIGINTERN PyObject *_wrap_hive_key(PyObject *SWIGUNUSEDPARM(self), PyObject *ar } result = reg_open_hive(arg1,(char const *)arg2,arg3,arg4,arg5,arg6); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3601,7 +3601,7 @@ SWIGINTERN PyObject *_wrap_open_ldb(PyObject *SWIGUNUSEDPARM(self), PyObject *ar } result = reg_open_ldb_file(arg1,(char const *)arg2,arg3,arg4,arg5,arg6); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3642,7 +3642,7 @@ SWIGINTERN PyObject *_wrap_create_dir(PyObject *SWIGUNUSEDPARM(self), PyObject * arg2 = (char *)(buf2); result = reg_create_directory(arg1,(char const *)arg2,arg3); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3683,7 +3683,7 @@ SWIGINTERN PyObject *_wrap_open_dir(PyObject *SWIGUNUSEDPARM(self), PyObject *ar arg2 = (char *)(buf2); result = reg_open_directory(arg1,(char const *)arg2,arg3); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3750,7 +3750,7 @@ SWIGINTERN PyObject *_wrap_open_samba(PyObject *SWIGUNUSEDPARM(self), PyObject * } result = reg_open_samba(arg1,arg2,arg3,arg4,arg5); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { diff --git a/source4/lib/replace/README b/source4/lib/replace/README index 268a1b15cf3..43f7b08572f 100644 --- a/source4/lib/replace/README +++ b/source4/lib/replace/README @@ -15,7 +15,6 @@ rename initgroups memmove strdup -inet_ntoa setlinebuf vsyslog timegm @@ -52,6 +51,7 @@ readline (the library) inet_ntoa inet_ntop inet_pton +inet_aton strtoll strtoull socketpair diff --git a/source4/lib/replace/configure.ac b/source4/lib/replace/configure.ac index f5e054f4767..02dc08bf72c 100644 --- a/source4/lib/replace/configure.ac +++ b/source4/lib/replace/configure.ac @@ -21,6 +21,9 @@ if test "$ac_cv_prog_gcc" = yes; then CFLAGS="$CFLAGS -Wno-format-y2k" fi +LIBS="${LIBREPLACE_NETWORK_LIBS}" +AC_SUBST(LIBS) + AC_SUBST(LDFLAGS) AC_OUTPUT(Makefile) diff --git a/source4/lib/replace/getifaddrs.m4 b/source4/lib/replace/getifaddrs.m4 index 6cca155de37..927bc677db5 100644 --- a/source4/lib/replace/getifaddrs.m4 +++ b/source4/lib/replace/getifaddrs.m4 @@ -34,10 +34,12 @@ fi ################## # look for a method of finding the list of network interfaces # -# This tests need LIBS="$NSL_LIBS $SOCKET_LIBS" +# This tests need LIBS="${LIBREPLACE_NETWORK_LIBS}" # old_LIBS=$LIBS -LIBS="$NSL_LIBS $SOCKET_LIBS" +LIBS="${LIBREPLACE_NETWORK_LIBS}" +SAVE_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -I$libreplacedir" iface=no; ################## # look for a method of finding the list of network interfaces @@ -79,7 +81,6 @@ AC_TRY_RUN([ libreplace_cv_HAVE_IFACE_AIX=yes,libreplace_cv_HAVE_IFACE_AIX=no,libreplace_cv_HAVE_IFACE_AIX=cross)]) if test x"$libreplace_cv_HAVE_IFACE_AIX" = x"yes"; then iface=yes;AC_DEFINE(HAVE_IFACE_AIX,1,[Whether iface AIX is available]) - old_LIBS="$old_LIBS $LIBS" fi fi @@ -100,7 +101,6 @@ AC_TRY_RUN([ libreplace_cv_HAVE_IFACE_IFCONF=yes,libreplace_cv_HAVE_IFACE_IFCONF=no,libreplace_cv_HAVE_IFACE_IFCONF=cross)]) if test x"$libreplace_cv_HAVE_IFACE_IFCONF" = x"yes"; then iface=yes;AC_DEFINE(HAVE_IFACE_IFCONF,1,[Whether iface ifconf is available]) - old_LIBS="$old_LIBS $LIBS" fi fi @@ -120,8 +120,9 @@ AC_TRY_RUN([ libreplace_cv_HAVE_IFACE_IFREQ=yes,libreplace_cv_HAVE_IFACE_IFREQ=no,libreplace_cv_HAVE_IFACE_IFREQ=cross)]) if test x"$libreplace_cv_HAVE_IFACE_IFREQ" = x"yes"; then iface=yes;AC_DEFINE(HAVE_IFACE_IFREQ,1,[Whether iface ifreq is available]) - old_LIBS="$old_LIBS $LIBS" fi fi LIBS=$old_LIBS +CPPFLAGS="$SAVE_CPPFLAGS" + diff --git a/source4/lib/replace/getpass.c b/source4/lib/replace/getpass.c index d91d029f6a7..73333b90219 100644 --- a/source4/lib/replace/getpass.c +++ b/source4/lib/replace/getpass.c @@ -185,7 +185,13 @@ char *rep_getpass(const char *prompt) buf[0] = 0; if (!gotintr) { in_fd = fileno(in); - fgets(buf, bufsize, in); + if (fgets(buf, bufsize, in) == NULL) { + buf[0] = 0; + if (in && in != stdin) { + fclose(in); + } + return buf; + } } nread = strlen(buf); if (nread) { diff --git a/source4/lib/replace/inet_aton.c b/source4/lib/replace/inet_aton.c new file mode 100644 index 00000000000..c6b3bb11a74 --- /dev/null +++ b/source4/lib/replace/inet_aton.c @@ -0,0 +1,33 @@ +/* + * Unix SMB/CIFS implementation. + * replacement functions + * Copyright (C) Michael Adam <obnox@samba.org> 2008 + * + * ** NOTE! The following LGPL license applies to the replace + * ** library. This does NOT imply that all of Samba is released + * ** under the LGPL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/network.h" + +/** + * We know that we have inet_pton from earlier libreplace checks. + */ +int rep_inet_aton(const char *src, struct in_addr *dst) +{ + return (inet_pton(AF_INET, src, dst) > 0) ? 1 : 0; +} diff --git a/source4/lib/replace/inet_aton.m4 b/source4/lib/replace/inet_aton.m4 new file mode 100644 index 00000000000..853688ef6bc --- /dev/null +++ b/source4/lib/replace/inet_aton.m4 @@ -0,0 +1 @@ +AC_CHECK_FUNCS(inet_aton,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} inet_aton.o"]) diff --git a/source4/lib/replace/inet_ntoa.c b/source4/lib/replace/inet_ntoa.c new file mode 100644 index 00000000000..e3b80ebef8b --- /dev/null +++ b/source4/lib/replace/inet_ntoa.c @@ -0,0 +1,39 @@ +/* + * Unix SMB/CIFS implementation. + * replacement routines for broken systems + * Copyright (C) Andrew Tridgell 2003 + * Copyright (C) Michael Adam 2008 + * + * ** NOTE! The following LGPL license applies to the replace + * ** library. This does NOT imply that all of Samba is released + * ** under the LGPL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/network.h" + +/** + * NOTE: this is not thread safe, but it can't be, either + * since it returns a pointer to static memory. + */ +char *rep_inet_ntoa(struct in_addr ip) +{ + uint8_t *p = (uint8_t *)&ip.s_addr; + static char buf[18]; + slprintf(buf, 17, "%d.%d.%d.%d", + (int)p[0], (int)p[1], (int)p[2], (int)p[3]); + return buf; +} diff --git a/source4/lib/replace/inet_ntoa.m4 b/source4/lib/replace/inet_ntoa.m4 new file mode 100644 index 00000000000..5aaa9350c5a --- /dev/null +++ b/source4/lib/replace/inet_ntoa.m4 @@ -0,0 +1,19 @@ +AC_CHECK_FUNCS(inet_ntoa,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} inet_ntoa.o"]) + +AC_CACHE_CHECK([for broken inet_ntoa],libreplace_cv_REPLACE_INET_NTOA,[ +AC_TRY_RUN([ +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <netinet/in.h> +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +main() { struct in_addr ip; ip.s_addr = 0x12345678; +if (strcmp(inet_ntoa(ip),"18.52.86.120") && + strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); } +exit(1);}], + libreplace_cv_REPLACE_INET_NTOA=yes,libreplace_cv_REPLACE_INET_NTOA=no,libreplace_cv_REPLACE_INET_NTOA=cross)]) +if test x"$libreplace_cv_REPLACE_INET_NTOA" = x"yes"; then + AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) +fi diff --git a/source4/lib/replace/libreplace.m4 b/source4/lib/replace/libreplace.m4 index e0cc57f4c80..8e17258918b 100644 --- a/source4/lib/replace/libreplace.m4 +++ b/source4/lib/replace/libreplace.m4 @@ -120,24 +120,6 @@ if test x"$libreplace_cv_USABLE_NET_IF_H" = x"yes";then AC_DEFINE(HAVE_NET_IF_H, 1, usability of net/if.h) fi -AC_CACHE_CHECK([for broken inet_ntoa],libreplace_cv_REPLACE_INET_NTOA,[ -AC_TRY_RUN([ -#include <stdio.h> -#include <unistd.h> -#include <sys/types.h> -#include <netinet/in.h> -#ifdef HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -main() { struct in_addr ip; ip.s_addr = 0x12345678; -if (strcmp(inet_ntoa(ip),"18.52.86.120") && - strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); } -exit(1);}], - libreplace_cv_REPLACE_INET_NTOA=yes,libreplace_cv_REPLACE_INET_NTOA=no,libreplace_cv_REPLACE_INET_NTOA=cross)]) -if test x"$libreplace_cv_REPLACE_INET_NTOA" = x"yes"; then - AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) -fi - AC_HAVE_TYPE([socklen_t],[#include <sys/socket.h>]) AC_HAVE_TYPE([sa_family_t],[#include <sys/socket.h>]) AC_HAVE_TYPE([struct addrinfo], [#include <netdb.h>]) @@ -176,7 +158,7 @@ fi AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror) AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize rename) AC_CHECK_FUNCS(waitpid strlcpy strlcat initgroups memmove strdup) -AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp socketpair) +AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp) AC_CHECK_FUNCS(isatty) AC_HAVE_DECL(setresuid, [#include <unistd.h>]) AC_HAVE_DECL(setresgid, [#include <unistd.h>]) @@ -347,9 +329,12 @@ m4_include(timegm.m4) m4_include(socket.m4) m4_include(inet_ntop.m4) m4_include(inet_pton.m4) +m4_include(inet_aton.m4) +m4_include(inet_ntoa.m4) m4_include(getaddrinfo.m4) m4_include(repdir.m4) m4_include(getifaddrs.m4) +m4_include(socketpair.m4) AC_CHECK_FUNCS([syslog printf memset memcpy],,[AC_MSG_ERROR([Required function not found])]) diff --git a/source4/lib/replace/replace.c b/source4/lib/replace/replace.c index b2a240e8ab4..6930f9b0791 100644 --- a/source4/lib/replace/replace.c +++ b/source4/lib/replace/replace.c @@ -27,7 +27,6 @@ #include "system/time.h" #include "system/passwd.h" #include "system/syslog.h" -#include "system/network.h" #include "system/locale.h" #include "system/wait.h" @@ -295,20 +294,6 @@ char *rep_strdup(const char *s) } #endif /* HAVE_STRDUP */ -#ifndef WITH_PTHREADS -/* REWRITE: not thread safe */ -#ifdef REPLACE_INET_NTOA -char *rep_inet_ntoa(struct in_addr ip) -{ - uint8_t *p = (uint8_t *)&ip.s_addr; - static char buf[18]; - slprintf(buf, 17, "%d.%d.%d.%d", - (int)p[0], (int)p[1], (int)p[2], (int)p[3]); - return buf; -} -#endif /* REPLACE_INET_NTOA */ -#endif - #ifndef HAVE_SETLINEBUF void rep_setlinebuf(FILE *stream) { @@ -599,25 +584,3 @@ int rep_unsetenv(const char *name) return 0; } #endif - -#ifndef HAVE_SOCKETPAIR -int rep_socketpair(int d, int type, int protocol, int sv[2]) -{ - if (d != AF_UNIX) { - errno = EAFNOSUPPORT; - return -1; - } - - if (protocol != 0) { - errno = EPROTONOSUPPORT; - return -1; - } - - if (type != SOCK_STREAM) { - errno = EOPNOTSUPP; - return -1; - } - - return pipe(sv); -} -#endif diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index 0d16f4ffd0a..5fe79394ebf 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -212,7 +212,7 @@ int rep_dlclose(void *handle); #ifndef HAVE_SOCKETPAIR #define socketpair rep_socketpair -int rep_socketpair(int d, int type, int protocol, int sv[2]); +/* prototype is in system/network.h */ #endif #ifndef PRINTF_ATTRIBUTE @@ -325,7 +325,7 @@ ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset); ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset); #endif -#ifdef REPLACE_INET_NTOA +#if !defined(HAVE_INET_NTOA) || defined(REPLACE_INET_NTOA) #define inet_ntoa rep_inet_ntoa /* prototype is in "system/network.h" */ #endif @@ -340,6 +340,11 @@ ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset) /* prototype is in "system/network.h" */ #endif +#ifndef HAVE_INET_ATON +#define inet_aton rep_inet_aton +/* prototype is in "system/network.h" */ +#endif + #ifndef HAVE_CONNECT #define connect rep_connect /* prototype is in "system/network.h" */ diff --git a/source4/lib/replace/samba.m4 b/source4/lib/replace/samba.m4 index a2e04f53b1d..e62c3d3cd17 100644 --- a/source4/lib/replace/samba.m4 +++ b/source4/lib/replace/samba.m4 @@ -3,6 +3,9 @@ AC_LIBREPLACE_BROKEN_CHECKS SMB_EXT_LIB(LIBREPLACE_EXT, [${LIBDL}]) SMB_ENABLE(LIBREPLACE_EXT) +SMB_EXT_LIB(LIBREPLACE_NETWORK, [${LIBREPLACE_NETWORK_LIBS}]) +SMB_ENABLE(LIBREPLACE_NETWORK) + # remove leading ./ LIBREPLACE_DIR=`echo ${libreplacedir} |sed -e 's/^\.\///g'` diff --git a/source4/lib/replace/snprintf.c b/source4/lib/replace/snprintf.c index 9f8a7657e52..a174dcffed7 100644 --- a/source4/lib/replace/snprintf.c +++ b/source4/lib/replace/snprintf.c @@ -1264,7 +1264,7 @@ static int add_cnk_list_entry(struct pr_chunk_x **list, VA_COPY(ap2, ap); ret = vsnprintf(NULL, 0, format, ap2); va_end(ap2); - if (ret <= 0) return ret; + if (ret < 0) return ret; (*ptr) = (char *)malloc(ret+1); if (!*ptr) return -1; diff --git a/source4/lib/replace/socket.m4 b/source4/lib/replace/socket.m4 index c0c8f93e81d..984f81f15f3 100644 --- a/source4/lib/replace/socket.m4 +++ b/source4/lib/replace/socket.m4 @@ -7,10 +7,10 @@ dnl only looks in /etc/hosts), so we only look for -lsocket if we need dnl it. AC_CHECK_FUNCS(connect) if test x"$ac_cv_func_connect" = x"no"; then - AC_CHECK_LIB_EXT(nsl_s, SOCKET_LIBS, connect) - AC_CHECK_LIB_EXT(nsl, SOCKET_LIBS, connect) - AC_CHECK_LIB_EXT(socket, SOCKET_LIBS, connect) - AC_CHECK_LIB_EXT(inet, SOCKET_LIBS, connect) + AC_CHECK_LIB_EXT(nsl_s, LIBREPLACE_NETWORK_LIBS, connect) + AC_CHECK_LIB_EXT(nsl, LIBREPLACE_NETWORK_LIBS, connect) + AC_CHECK_LIB_EXT(socket, LIBREPLACE_NETWORK_LIBS, connect) + AC_CHECK_LIB_EXT(inet, LIBREPLACE_NETWORK_LIBS, connect) dnl We can't just call AC_CHECK_FUNCS(connect) here, dnl because the value has been cached. if test x"$ac_cv_lib_ext_nsl_s_connect" = x"yes" || @@ -24,9 +24,9 @@ fi AC_CHECK_FUNCS(gethostbyname) if test x"$ac_cv_func_gethostbyname" = x"no"; then - AC_CHECK_LIB_EXT(nsl_s, NSL_LIBS, gethostbyname) - AC_CHECK_LIB_EXT(nsl, NSL_LIBS, gethostbyname) - AC_CHECK_LIB_EXT(socket, NSL_LIBS, gethostbyname) + AC_CHECK_LIB_EXT(nsl_s, LIBREPLACE_NETWORK_LIBS, gethostbyname) + AC_CHECK_LIB_EXT(nsl, LIBREPLACE_NETWORK_LIBS, gethostbyname) + AC_CHECK_LIB_EXT(socket, LIBREPLACE_NETWORK_LIBS, gethostbyname) dnl We can't just call AC_CHECK_FUNCS(gethostbyname) here, dnl because the value has been cached. if test x"$ac_cv_lib_ext_nsl_s_gethostbyname" = x"yes" || @@ -37,4 +37,3 @@ if test x"$ac_cv_func_gethostbyname" = x"no"; then [Whether the system has gethostbyname()]) fi fi - diff --git a/source4/lib/replace/socketpair.c b/source4/lib/replace/socketpair.c new file mode 100644 index 00000000000..c7757309522 --- /dev/null +++ b/source4/lib/replace/socketpair.c @@ -0,0 +1,46 @@ +/* + * Unix SMB/CIFS implementation. + * replacement routines for broken systems + * Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2006 + * Copyright (C) Michael Adam <obnox@samba.org> 2008 + * + * ** NOTE! The following LGPL license applies to the replace + * ** library. This does NOT imply that all of Samba is released + * ** under the LGPL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/network.h" + +int rep_socketpair(int d, int type, int protocol, int sv[2]) +{ + if (d != AF_UNIX) { + errno = EAFNOSUPPORT; + return -1; + } + + if (protocol != 0) { + errno = EPROTONOSUPPORT; + return -1; + } + + if (type != SOCK_STREAM) { + errno = EOPNOTSUPP; + return -1; + } + + return pipe(sv); +} diff --git a/source4/lib/replace/socketpair.m4 b/source4/lib/replace/socketpair.m4 new file mode 100644 index 00000000000..7088334cda3 --- /dev/null +++ b/source4/lib/replace/socketpair.m4 @@ -0,0 +1 @@ +AC_CHECK_FUNCS(socketpair,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} socketpair.o"]) diff --git a/source4/lib/replace/system/network.h b/source4/lib/replace/system/network.h index 410c6d7cca2..a5fb813aa15 100644 --- a/source4/lib/replace/system/network.h +++ b/source4/lib/replace/system/network.h @@ -88,7 +88,7 @@ typedef int socklen_t; #endif -#ifdef REPLACE_INET_NTOA +#if !defined (HAVE_INET_NTOA) || defined(REPLACE_INET_NTOA) /* define is in "replace.h" */ char *rep_inet_ntoa(struct in_addr ip); #endif @@ -103,6 +103,11 @@ int rep_inet_pton(int af, const char *src, void *dst); const char *rep_inet_ntop(int af, const void *src, char *dst, socklen_t size); #endif +#ifndef HAVE_INET_ATON +/* define is in "replace.h" */ +int rep_inet_aton(const char *src, struct in_addr *dst); +#endif + #ifndef HAVE_CONNECT /* define is in "replace.h" */ int rep_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); @@ -138,6 +143,11 @@ int rep_getifaddrs(struct ifaddrs **); void rep_freeifaddrs(struct ifaddrs *); #endif +#ifndef HAVE_SOCKETPAIR +/* define is in "replace.h" */ +int rep_socketpair(int d, int type, int protocol, int sv[2]); +#endif + /* * Some systems have getaddrinfo but not the * defines needed to use it. @@ -305,7 +315,7 @@ struct addrinfo { /* Needed for some systems that don't define it (Solaris). */ #ifndef ifr_netmask -#define ifr_netmask ifr_addrs +#define ifr_netmask ifr_addr #endif #ifdef SOCKET_WRAPPER diff --git a/source4/lib/replace/test/os2_delete.c b/source4/lib/replace/test/os2_delete.c index c6ef1800178..b45c135355a 100644 --- a/source4/lib/replace/test/os2_delete.c +++ b/source4/lib/replace/test/os2_delete.c @@ -39,8 +39,15 @@ static void create_files(void) int i; for (i=0;i<NUM_FILES;i++) { char fname[40]; + int fd; sprintf(fname, TESTDIR "/test%u.txt", i); - close(open(fname, O_CREAT|O_RDWR, 0600)) == 0 || FAILED("close"); + fd = open(fname, O_CREAT|O_RDWR, 0600); + if (fd < 0) { + FAILED("open"); + } + if (close(fd) != 0) { + FAILED("close"); + } } } diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index a713090c6da..b40002b3211 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -11,50 +11,6 @@ if test x"$samba_cv_HAVE_SOCK_SIN_LEN" = x"yes"; then AC_DEFINE(HAVE_SOCK_SIN_LEN,1,[Whether the sockaddr_in struct has a sin_len property]) fi -# The following test taken from the cvs sources -# If we can't find connect, try looking in -lsocket, -lnsl, and -linet. -# The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has -# libsocket.so which has a bad implementation of gethostbyname (it -# only looks in /etc/hosts), so we only look for -lsocket if we need -# it. -AC_CHECK_FUNCS(connect) -if test x"$ac_cv_func_connect" = x"no"; then - AC_CHECK_LIB_EXT(nsl_s, SOCKET_LIBS, connect) - AC_CHECK_LIB_EXT(nsl, SOCKET_LIBS, connect) - AC_CHECK_LIB_EXT(socket, SOCKET_LIBS, connect) - AC_CHECK_LIB_EXT(inet, SOCKET_LIBS, connect) - SMB_ENABLE(EXT_SOCKET,YES) - dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value - dnl has been cached. - if test x"$ac_cv_lib_ext_nsl_s_connect" = x"yes" || - test x"$ac_cv_lib_ext_nsl_connect" = x"yes" || - test x"$ac_cv_lib_ext_socket_connect" = x"yes" || - test x"$ac_cv_lib_ext_inet_connect" = x"yes"; then - AC_DEFINE(HAVE_CONNECT,1,[Whether the system has connect()]) - else - AC_MSG_ERROR([no connect() function available!]) - fi -fi - -SMB_EXT_LIB(EXT_SOCKET,[${SOCKET_LIBS}],[${SOCKET_CFLAGS}],[${SOCKET_CPPFLAGS}],[${SOCKET_LDFLAGS}]) - -AC_CHECK_FUNCS(gethostbyname) -if test x"$ac_cv_func_gethostbyname" = x"no"; then - AC_CHECK_LIB_EXT(nsl_s, NSL_LIBS, gethostbyname) - AC_CHECK_LIB_EXT(nsl, NSL_LIBS, gethostbyname) - AC_CHECK_LIB_EXT(socket, NSL_LIBS, gethostbyname) - SMB_ENABLE(EXT_NSL,YES) - dnl We can't just call AC_CHECK_FUNCS(gethostbyname) here, because the value - dnl has been cached. - if test x"$ac_cv_lib_ext_nsl_s_gethostbyname" != x"yes" && - test x"$ac_cv_lib_ext_nsl_gethostbyname" != x"yes" && - test x"$ac_cv_lib_ext_socket_gethostbyname" != x"yes"; then - AC_MSG_ERROR([no gethostbyname() function available!]) - fi -fi - -SMB_EXT_LIB(EXT_NSL,[${NSL_LIBS}],[],[],[]) - ############################################ # check for unix domain sockets AC_CACHE_CHECK([for unix domain sockets],samba_cv_unixsocket, [ diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk index 354b1b51986..24001901754 100644 --- a/source4/lib/socket/config.mk +++ b/source4/lib/socket/config.mk @@ -2,7 +2,7 @@ # Start SUBSYSTEM LIBNETIF [SUBSYSTEM::LIBNETIF] PRIVATE_PROTO_HEADER = netif_proto.h -PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL EXT_SOCKET EXT_NSL +PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL LIBREPLACE_NETWORK # End SUBSYSTEM LIBNETIF ############################## @@ -13,7 +13,7 @@ LIBNETIF_OBJ_FILES = $(addprefix lib/socket/, interface.o netif.o) [MODULE::socket_ip] SUBSYSTEM = samba-socket OUTPUT_TYPE = MERGED_OBJ -PRIVATE_DEPENDENCIES = EXT_SOCKET EXT_NSL LIBSAMBA-ERRORS +PRIVATE_DEPENDENCIES = LIBSAMBA-ERRORS LIBREPLACE_NETWORK # End MODULE socket_ip ################################################ @@ -24,7 +24,7 @@ socket_ip_OBJ_FILES = lib/socket/socket_ip.o [MODULE::socket_unix] SUBSYSTEM = samba-socket OUTPUT_TYPE = MERGED_OBJ -PRIVATE_DEPENDENCIES = EXT_SOCKET EXT_NSL +PRIVATE_DEPENDENCIES = LIBREPLACE_NETWORK # End MODULE socket_unix ################################################ diff --git a/source4/lib/socket_wrapper/config.mk b/source4/lib/socket_wrapper/config.mk index f7e874d8e28..75d3ade28b0 100644 --- a/source4/lib/socket_wrapper/config.mk +++ b/source4/lib/socket_wrapper/config.mk @@ -1,7 +1,7 @@ ############################## # Start SUBSYSTEM SOCKET_WRAPPER [SUBSYSTEM::SOCKET_WRAPPER] -PRIVATE_DEPENDENCIES = EXT_SOCKET +PRIVATE_DEPENDENCIES = LIBREPLACE_NETWORK # End SUBSYSTEM SOCKET_WRAPPER ############################## diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index 644365a6659..86d9f7a312d 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -64,6 +64,7 @@ #include <unistd.h> #include <string.h> #include <stdio.h> +#include <stdint.h> #endif @@ -624,67 +625,67 @@ enum swrap_packet_type { }; struct swrap_file_hdr { - unsigned long magic; - unsigned short version_major; - unsigned short version_minor; - long timezone; - unsigned long sigfigs; - unsigned long frame_max_len; + uint32_t magic; + uint16_t version_major; + uint16_t version_minor; + int32_t timezone; + uint32_t sigfigs; + uint32_t frame_max_len; #define SWRAP_FRAME_LENGTH_MAX 0xFFFF - unsigned long link_type; + uint32_t link_type; }; #define SWRAP_FILE_HDR_SIZE 24 struct swrap_packet { struct { - unsigned long seconds; - unsigned long micro_seconds; - unsigned long recorded_length; - unsigned long full_length; + uint32_t seconds; + uint32_t micro_seconds; + uint32_t recorded_length; + uint32_t full_length; } frame; #define SWRAP_PACKET__FRAME_SIZE 16 struct { struct { - unsigned char ver_hdrlen; - unsigned char tos; - unsigned short packet_length; - unsigned short identification; - unsigned char flags; - unsigned char fragment; - unsigned char ttl; - unsigned char protocol; - unsigned short hdr_checksum; - unsigned long src_addr; - unsigned long dest_addr; + uint8_t ver_hdrlen; + uint8_t tos; + uint16_t packet_length; + uint16_t identification; + uint8_t flags; + uint8_t fragment; + uint8_t ttl; + uint8_t protocol; + uint16_t hdr_checksum; + uint32_t src_addr; + uint32_t dest_addr; } hdr; #define SWRAP_PACKET__IP_HDR_SIZE 20 union { struct { - unsigned short source_port; - unsigned short dest_port; - unsigned long seq_num; - unsigned long ack_num; - unsigned char hdr_length; - unsigned char control; - unsigned short window; - unsigned short checksum; - unsigned short urg; + uint16_t source_port; + uint16_t dest_port; + uint32_t seq_num; + uint32_t ack_num; + uint8_t hdr_length; + uint8_t control; + uint16_t window; + uint16_t checksum; + uint16_t urg; } tcp; #define SWRAP_PACKET__IP_P_TCP_SIZE 20 struct { - unsigned short source_port; - unsigned short dest_port; - unsigned short length; - unsigned short checksum; + uint16_t source_port; + uint16_t dest_port; + uint16_t length; + uint16_t checksum; } udp; #define SWRAP_PACKET__IP_P_UDP_SIZE 8 struct { - unsigned char type; - unsigned char code; - unsigned short checksum; - unsigned long unused; + uint8_t type; + uint8_t code; + uint16_t checksum; + uint32_t unused; } icmp; #define SWRAP_PACKET__IP_P_ICMP_SIZE 8 } p; diff --git a/source4/lib/util/config.mk b/source4/lib/util/config.mk index b0978ca5f5a..3afe398a8f3 100644 --- a/source4/lib/util/config.mk +++ b/source4/lib/util/config.mk @@ -2,7 +2,8 @@ PUBLIC_DEPENDENCIES = \ LIBTALLOC LIBCRYPTO \ SOCKET_WRAPPER EXT_NSL \ - CHARSET EXECINFO DYNCONFIG + CHARSET EXECINFO DYNCONFIG \ + LIBREPLACE_NETWORK LIBSAMBA-UTIL_OBJ_FILES = $(addprefix lib/util/, \ xfile.o \ @@ -37,7 +38,6 @@ PUBLIC_HEADERS += $(addprefix lib/util/, util.h \ [SUBSYSTEM::ASN1_UTIL] PRIVATE_PROTO_HEADER = asn1_proto.h - ASN1_UTIL_OBJ_FILES = lib/util/asn1.o PUBLIC_HEADERS += lib/util/asn1.h diff --git a/source4/libcli/composite/composite.c b/source4/libcli/composite/composite.c index aab7487a424..26169e78389 100644 --- a/source4/libcli/composite/composite.c +++ b/source4/libcli/composite/composite.c @@ -1,6 +1,7 @@ /* Unix SMB/CIFS implementation. + Copyright (C) Volker Lendecke 2005 Copyright (C) Andrew Tridgell 2005 This program is free software; you can redistribute it and/or modify diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h index 24e8ad4afcf..3965c58204c 100644 --- a/source4/libcli/raw/interfaces.h +++ b/source4/libcli/raw/interfaces.h @@ -175,7 +175,7 @@ struct smb_rmdir { }; /* struct used in rename() call */ -enum smb_rename_level {RAW_RENAME_RENAME, RAW_RENAME_NTRENAME}; +enum smb_rename_level {RAW_RENAME_RENAME, RAW_RENAME_NTRENAME, RAW_RENAME_NTTRANS}; union smb_rename { struct { @@ -206,6 +206,17 @@ union smb_rename { const char *new_name; } in; } ntrename; + + /* NT TRANS rename interface */ + struct { + enum smb_rename_level level; + + struct { + union smb_handle file; + uint16_t flags;/* see RENAME_REPLACE_IF_EXISTS */ + const char *new_name; + } in; + } nttrans; }; enum smb_tcon_level { diff --git a/source4/libcli/raw/rawfile.c b/source4/libcli/raw/rawfile.c index d9383401b7a..725034c3a91 100644 --- a/source4/libcli/raw/rawfile.c +++ b/source4/libcli/raw/rawfile.c @@ -36,6 +36,8 @@ struct smbcli_request *smb_raw_rename_send(struct smbcli_tree *tree, union smb_rename *parms) { struct smbcli_request *req = NULL; + struct smb_nttrans nt; + TALLOC_CTX *mem_ctx; switch (parms->generic.level) { case RAW_RENAME_RENAME: @@ -53,6 +55,30 @@ struct smbcli_request *smb_raw_rename_send(struct smbcli_tree *tree, smbcli_req_append_ascii4(req, parms->ntrename.in.old_name, STR_TERMINATE); smbcli_req_append_ascii4(req, parms->ntrename.in.new_name, STR_TERMINATE); break; + + case RAW_RENAME_NTTRANS: + + mem_ctx = talloc_new(tree); + + nt.in.max_setup = 0; + nt.in.max_param = 0; + nt.in.max_data = 0; + nt.in.setup_count = 0; + nt.in.setup = NULL; + nt.in.function = NT_TRANSACT_RENAME; + nt.in.params = data_blob_talloc(mem_ctx, NULL, 4); + nt.in.data = data_blob(NULL, 0); + + SSVAL(nt.in.params.data, VWV(0), parms->nttrans.in.file.fnum); + SSVAL(nt.in.params.data, VWV(1), parms->nttrans.in.flags); + + smbcli_blob_append_string(tree->session, mem_ctx, + &nt.in.params, parms->nttrans.in.new_name, + STR_TERMINATE); + + req = smb_raw_nttrans_send(tree, &nt); + talloc_free(mem_ctx); + return req; } if (!smbcli_request_send(req)) { diff --git a/source4/libcli/security/security.h b/source4/libcli/security/security.h index d9485c825fe..c7f2a093113 100644 --- a/source4/libcli/security/security.h +++ b/source4/libcli/security/security.h @@ -18,4 +18,12 @@ */ #include "librpc/gen_ndr/security.h" + +enum security_user_level { + SECURITY_ANONYMOUS, + SECURITY_USER, + SECURITY_ADMINISTRATOR, + SECURITY_SYSTEM +}; + #include "libcli/security/proto.h" diff --git a/source4/libcli/security/security_token.c b/source4/libcli/security/security_token.c index e126340c465..0680c542588 100644 --- a/source4/libcli/security/security_token.c +++ b/source4/libcli/security/security_token.c @@ -23,6 +23,7 @@ #include "includes.h" #include "dsdb/samdb/samdb.h" #include "libcli/security/security.h" +#include "auth/session.h" /* return a blank security token @@ -141,3 +142,29 @@ bool security_token_has_nt_authenticated_users(const struct security_token *toke { return security_token_has_sid_string(token, SID_NT_AUTHENTICATED_USERS); } + +enum security_user_level security_session_user_level(struct auth_session_info *session_info) +{ + if (!session_info) { + return SECURITY_ANONYMOUS; + } + + if (security_token_is_system(session_info->security_token)) { + return SECURITY_SYSTEM; + } + + if (security_token_is_anonymous(session_info->security_token)) { + return SECURITY_ANONYMOUS; + } + + if (security_token_has_builtin_administrators(session_info->security_token)) { + return SECURITY_ADMINISTRATOR; + } + + if (security_token_has_nt_authenticated_users(session_info->security_token)) { + return SECURITY_USER; + } + + return SECURITY_ANONYMOUS; +} + diff --git a/source4/libcli/security/security_wrap.c b/source4/libcli/security/security_wrap.c index 72118b23590..eb9e4c45d98 100644 --- a/source4/libcli/security/security_wrap.c +++ b/source4/libcli/security/security_wrap.c @@ -3116,7 +3116,7 @@ SWIGINTERN PyObject *_wrap_security_descriptor_sacl_add(PyObject *SWIGUNUSEDPARM arg2 = (struct security_ace *)(argp2); result = security_descriptor_sacl_add(arg1,(struct security_ace const *)arg2); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3156,7 +3156,7 @@ SWIGINTERN PyObject *_wrap_security_descriptor_dacl_add(PyObject *SWIGUNUSEDPARM arg2 = (struct security_ace *)(argp2); result = security_descriptor_dacl_add(arg1,(struct security_ace const *)arg2); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3196,7 +3196,7 @@ SWIGINTERN PyObject *_wrap_security_descriptor_dacl_del(PyObject *SWIGUNUSEDPARM arg2 = (struct dom_sid *)(argp2); result = security_descriptor_dacl_del(arg1,(struct dom_sid const *)arg2); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3236,7 +3236,7 @@ SWIGINTERN PyObject *_wrap_security_descriptor_sacl_del(PyObject *SWIGUNUSEDPARM arg2 = (struct dom_sid *)(argp2); result = security_descriptor_sacl_del(arg1,(struct dom_sid const *)arg2); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { diff --git a/source4/libcli/swig/libcli_nbt_wrap.c b/source4/libcli/swig/libcli_nbt_wrap.c index f67e6dd0e3b..e0bdb27cfc9 100644 --- a/source4/libcli/swig/libcli_nbt_wrap.c +++ b/source4/libcli/swig/libcli_nbt_wrap.c @@ -4065,7 +4065,7 @@ SWIGINTERN PyObject *_wrap_do_nbt_name_query(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct nbt_name_query *)(argp3); result = do_nbt_name_query(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { diff --git a/source4/libcli/util/errors.i b/source4/libcli/util/errors.i index ede536a9957..17efcbf62a8 100644 --- a/source4/libcli/util/errors.i +++ b/source4/libcli/util/errors.i @@ -20,7 +20,7 @@ #ifdef SWIGPYTHON %typemap(out,noblock=1) WERROR { if (!W_ERROR_IS_OK($1)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", $1.v, win_errstr($1)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V($1), win_errstr($1)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if ($result == NULL) { @@ -30,7 +30,7 @@ %typemap(out,noblock=1) NTSTATUS { if (NT_STATUS_IS_ERR($1)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", $1.v, nt_errstr($1)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V($1), nt_errstr($1)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if ($result == NULL) { diff --git a/source4/libnet/libnet_rpc.c b/source4/libnet/libnet_rpc.c index 667f54c4474..50cc1145d24 100644 --- a/source4/libnet/libnet_rpc.c +++ b/source4/libnet/libnet_rpc.c @@ -867,8 +867,11 @@ static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct } else { if (s->r.out.error_string) { r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string); - } else { + } else if (r->in.binding == NULL) { r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC failed: %s", nt_errstr(status)); + } else { + r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC %s failed: %s", + r->in.binding, nt_errstr(status)); } } diff --git a/source4/libnet/net_wrap.c b/source4/libnet/net_wrap.c index a4e27c151c7..29b30a87c2e 100644 --- a/source4/libnet/net_wrap.c +++ b/source4/libnet/net_wrap.c @@ -2679,7 +2679,7 @@ SWIGINTERN PyObject *_wrap_libnet_samsync_ldb(PyObject *SWIGUNUSEDPARM(self), Py arg3 = (struct libnet_samsync_ldb *)(argp3); result = libnet_samsync_ldb(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -2721,7 +2721,7 @@ SWIGINTERN PyObject *_wrap_libnet_DomainList(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_DomainList *)(argp3); result = libnet_DomainList(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -2763,7 +2763,7 @@ SWIGINTERN PyObject *_wrap_libnet_DomainClose(PyObject *SWIGUNUSEDPARM(self), Py arg3 = (struct libnet_DomainClose *)(argp3); result = libnet_DomainClose(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -2805,7 +2805,7 @@ SWIGINTERN PyObject *_wrap_libnet_DomainOpen(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_DomainOpen *)(argp3); result = libnet_DomainOpen(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -2847,7 +2847,7 @@ SWIGINTERN PyObject *_wrap_libnet_LookupName(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_LookupName *)(argp3); result = libnet_LookupName(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -2889,7 +2889,7 @@ SWIGINTERN PyObject *_wrap_libnet_LookupDCs(PyObject *SWIGUNUSEDPARM(self), PyOb arg3 = (struct libnet_LookupDCs *)(argp3); result = libnet_LookupDCs(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -2931,7 +2931,7 @@ SWIGINTERN PyObject *_wrap_libnet_LookupHost(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_Lookup *)(argp3); result = libnet_LookupHost(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -2973,7 +2973,7 @@ SWIGINTERN PyObject *_wrap_libnet_Lookup(PyObject *SWIGUNUSEDPARM(self), PyObjec arg3 = (struct libnet_Lookup *)(argp3); result = libnet_Lookup(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3015,7 +3015,7 @@ SWIGINTERN PyObject *_wrap_libnet_ListShares(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_ListShares *)(argp3); result = libnet_ListShares(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3057,7 +3057,7 @@ SWIGINTERN PyObject *_wrap_libnet_AddShare(PyObject *SWIGUNUSEDPARM(self), PyObj arg3 = (struct libnet_AddShare *)(argp3); result = libnet_AddShare(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3099,7 +3099,7 @@ SWIGINTERN PyObject *_wrap_libnet_DelShare(PyObject *SWIGUNUSEDPARM(self), PyObj arg3 = (struct libnet_DelShare *)(argp3); result = libnet_DelShare(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3141,7 +3141,7 @@ SWIGINTERN PyObject *_wrap_libnet_GroupList(PyObject *SWIGUNUSEDPARM(self), PyOb arg3 = (struct libnet_GroupList *)(argp3); result = libnet_GroupList(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3183,7 +3183,7 @@ SWIGINTERN PyObject *_wrap_libnet_GroupInfo(PyObject *SWIGUNUSEDPARM(self), PyOb arg3 = (struct libnet_GroupInfo *)(argp3); result = libnet_GroupInfo(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3225,7 +3225,7 @@ SWIGINTERN PyObject *_wrap_libnet_UserList(PyObject *SWIGUNUSEDPARM(self), PyObj arg3 = (struct libnet_UserList *)(argp3); result = libnet_UserList(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3267,7 +3267,7 @@ SWIGINTERN PyObject *_wrap_libnet_UserInfo(PyObject *SWIGUNUSEDPARM(self), PyObj arg3 = (struct libnet_UserInfo *)(argp3); result = libnet_UserInfo(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3309,7 +3309,7 @@ SWIGINTERN PyObject *_wrap_libnet_ModifyUser(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_ModifyUser *)(argp3); result = libnet_ModifyUser(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3351,7 +3351,7 @@ SWIGINTERN PyObject *_wrap_libnet_DeleteUser(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_DeleteUser *)(argp3); result = libnet_DeleteUser(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3393,7 +3393,7 @@ SWIGINTERN PyObject *_wrap_libnet_CreateUser(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_CreateUser *)(argp3); result = libnet_CreateUser(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3435,7 +3435,7 @@ SWIGINTERN PyObject *_wrap_libnet_SamDump_keytab(PyObject *SWIGUNUSEDPARM(self), arg3 = (struct libnet_SamDump_keytab *)(argp3); result = libnet_SamDump_keytab(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3477,7 +3477,7 @@ SWIGINTERN PyObject *_wrap_libnet_SamDump(PyObject *SWIGUNUSEDPARM(self), PyObje arg3 = (struct libnet_SamDump *)(argp3); result = libnet_SamDump(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3519,7 +3519,7 @@ SWIGINTERN PyObject *_wrap_libnet_SamSync_netlogon(PyObject *SWIGUNUSEDPARM(self arg3 = (struct libnet_SamSync *)(argp3); result = libnet_SamSync_netlogon(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3561,7 +3561,7 @@ SWIGINTERN PyObject *_wrap_libnet_UnbecomeDC(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_UnbecomeDC *)(argp3); result = libnet_UnbecomeDC(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3603,7 +3603,7 @@ SWIGINTERN PyObject *_wrap_libnet_BecomeDC(PyObject *SWIGUNUSEDPARM(self), PyObj arg3 = (struct libnet_BecomeDC *)(argp3); result = libnet_BecomeDC(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3652,7 +3652,7 @@ SWIGINTERN PyObject *_wrap_libnet_JoinSite(PyObject *SWIGUNUSEDPARM(self), PyObj arg3 = (struct libnet_JoinDomain *)(argp3); result = libnet_JoinSite(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3694,7 +3694,7 @@ SWIGINTERN PyObject *_wrap_libnet_JoinDomain(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_JoinDomain *)(argp3); result = libnet_JoinDomain(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3736,7 +3736,7 @@ SWIGINTERN PyObject *_wrap_libnet_Join(PyObject *SWIGUNUSEDPARM(self), PyObject arg3 = (struct libnet_Join *)(argp3); result = libnet_Join(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3778,7 +3778,7 @@ SWIGINTERN PyObject *_wrap_libnet_RpcConnect(PyObject *SWIGUNUSEDPARM(self), PyO arg3 = (struct libnet_RpcConnect *)(argp3); result = libnet_RpcConnect(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3820,7 +3820,7 @@ SWIGINTERN PyObject *_wrap_libnet_RemoteTOD(PyObject *SWIGUNUSEDPARM(self), PyOb arg3 = (union libnet_RemoteTOD *)(argp3); result = libnet_RemoteTOD(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3862,7 +3862,7 @@ SWIGINTERN PyObject *_wrap_libnet_ChangePassword(PyObject *SWIGUNUSEDPARM(self), arg3 = (union libnet_ChangePassword *)(argp3); result = libnet_ChangePassword(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { @@ -3904,7 +3904,7 @@ SWIGINTERN PyObject *_wrap_libnet_SetPassword(PyObject *SWIGUNUSEDPARM(self), Py arg3 = (union libnet_SetPassword *)(argp3); result = libnet_SetPassword(arg1,arg2,arg3); if (NT_STATUS_IS_ERR(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, nt_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", NT_STATUS_V(result), nt_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { diff --git a/source4/librpc/config.mk b/source4/librpc/config.mk index 682a3b81cde..bb81888d127 100644 --- a/source4/librpc/config.mk +++ b/source4/librpc/config.mk @@ -2,7 +2,7 @@ # Start SUBSYSTEM LIBNDR [LIBRARY::LIBNDR] PRIVATE_PROTO_HEADER = ndr/libndr_proto.h -PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBTALLOC LIBSAMBA-UTIL CHARSET EXT_NSL \ +PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBTALLOC LIBSAMBA-UTIL CHARSET \ LIBSAMBA-CONFIG LIBNDR_OBJ_FILES = $(addprefix librpc/ndr/, ndr.o ndr_basic.o ndr_string.o uuid.o) diff --git a/source4/librpc/idl/opendb.idl b/source4/librpc/idl/opendb.idl index e3bc2d0f177..72bf23a9b4b 100644 --- a/source4/librpc/idl/opendb.idl +++ b/source4/librpc/idl/opendb.idl @@ -20,6 +20,7 @@ interface opendb uint32 share_access; uint32 access_mask; pointer file_handle; + pointer fd; /* we need a per-entry delete on close, as well as a per-file one, to cope with strange semantics on open */ boolean8 delete_on_close; diff --git a/source4/nsswitch/config.m4 b/source4/nsswitch/config.m4 index a3b74128416..207b7fa53ff 100644 --- a/source4/nsswitch/config.m4 +++ b/source4/nsswitch/config.m4 @@ -4,8 +4,7 @@ case "$host_os" in *linux*) SMB_LIBRARY(nss_winbind, [nsswitch/winbind_nss_linux.o], - [LIBWINBIND-CLIENT], - [2],[2]) + [LIBWINBIND-CLIENT]) ;; *) ;; diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index 58183b5e603..3c090b5f5c6 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -595,6 +595,13 @@ static NTSTATUS cvfs_rename(struct ntvfs_module_context *ntvfs, SETUP_PID; + if (ren->nttrans.level == RAW_RENAME_NTTRANS) { + struct cvfs_file *f; + f = ntvfs_handle_get_backend_data(ren->nttrans.in.file.ntvfs, ntvfs); + if (!f) return NT_STATUS_INVALID_HANDLE; + ren->nttrans.in.file.fnum = f->fnum; + } + if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return smb_raw_rename(private->tree, ren); } diff --git a/source4/ntvfs/common/config.mk b/source4/ntvfs/common/config.mk index 356f6465c3b..c66257b73f7 100644 --- a/source4/ntvfs/common/config.mk +++ b/source4/ntvfs/common/config.mk @@ -2,7 +2,7 @@ # Start LIBRARY ntvfs_common [SUBSYSTEM::ntvfs_common] PRIVATE_PROTO_HEADER = proto.h -PUBLIC_DEPENDENCIES = NDR_OPENDB NDR_NOTIFY sys_notify share LIBDBWRAP +PUBLIC_DEPENDENCIES = NDR_OPENDB NDR_NOTIFY sys_notify sys_lease share LIBDBWRAP PRIVATE_DEPENDENCIES = brlock_ctdb opendb_ctdb # End LIBRARY ntvfs_common ################################################ diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c index 1cc077137cc..676706e03f1 100644 --- a/source4/ntvfs/common/opendb.c +++ b/source4/ntvfs/common/opendb.c @@ -97,11 +97,11 @@ _PUBLIC_ DATA_BLOB odb_get_key(TALLOC_CTX *mem_ctx, struct odb_lock *lck) */ _PUBLIC_ NTSTATUS odb_open_file(struct odb_lock *lck, void *file_handle, const char *path, - bool allow_level_II_oplock, + int *fd, bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted) { return ops->odb_open_file(lck, file_handle, path, - allow_level_II_oplock, + fd, allow_level_II_oplock, oplock_level, oplock_granted); } diff --git a/source4/ntvfs/common/opendb.h b/source4/ntvfs/common/opendb.h index fb3223aea92..045476337ab 100644 --- a/source4/ntvfs/common/opendb.h +++ b/source4/ntvfs/common/opendb.h @@ -27,7 +27,7 @@ struct opendb_ops { DATA_BLOB (*odb_get_key)(TALLOC_CTX *mem_ctx, struct odb_lock *lck); NTSTATUS (*odb_open_file)(struct odb_lock *lck, void *file_handle, const char *path, - bool allow_level_II_oplock, + int *fd, bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted); NTSTATUS (*odb_open_file_pending)(struct odb_lock *lck, void *private); NTSTATUS (*odb_close_file)(struct odb_lock *lck, void *file_handle, diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c index 17fcdfbbb45..fc05b342a8f 100644 --- a/source4/ntvfs/common/opendb_tdb.c +++ b/source4/ntvfs/common/opendb_tdb.c @@ -49,11 +49,13 @@ #include "ntvfs/common/ntvfs_common.h" #include "cluster/cluster.h" #include "param/param.h" +#include "ntvfs/sysdep/sys_lease.h" struct odb_context { struct tdb_wrap *w; struct ntvfs_context *ntvfs_ctx; bool oplocks; + struct sys_lease_context *lease_ctx; }; /* @@ -72,6 +74,10 @@ struct odb_lock { } can_open; }; +static NTSTATUS odb_oplock_break_send(struct messaging_context *msg_ctx, + struct opendb_entry *e, + uint8_t level); + /* Open up the openfiles.tdb database. Close it down using talloc_free(). We need the messaging_ctx to allow for pending open @@ -96,7 +102,12 @@ static struct odb_context *odb_tdb_init(TALLOC_CTX *mem_ctx, odb->ntvfs_ctx = ntvfs_ctx; /* leave oplocks disabled by default until the code is working */ - odb->oplocks = lp_parm_bool(ntvfs_ctx->lp_ctx, NULL, "opendb", "oplocks", false); + odb->oplocks = lp_parm_bool(ntvfs_ctx->lp_ctx, NULL, "opendb", "oplocks", true); + + odb->lease_ctx = sys_lease_context_create(ntvfs_ctx->config, odb, + ntvfs_ctx->event_ctx, + ntvfs_ctx->msg_ctx, + odb_oplock_break_send); return odb; } @@ -442,7 +453,7 @@ static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb, */ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle, const char *path, - bool allow_level_II_oplock, + int *fd, bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted) { struct odb_context *odb = lck->odb; @@ -491,22 +502,29 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, oplock_level = OPLOCK_NONE; } + lck->can_open.e->file_handle = file_handle; + lck->can_open.e->fd = fd; + lck->can_open.e->allow_level_II_oplock = allow_level_II_oplock; + lck->can_open.e->oplock_level = oplock_level; + + if (odb->lease_ctx && fd) { + NTSTATUS status; + status = sys_lease_setup(odb->lease_ctx, lck->can_open.e); + NT_STATUS_NOT_OK_RETURN(status); + } + if (oplock_granted) { - if (oplock_level == OPLOCK_EXCLUSIVE) { + if (lck->can_open.e->oplock_level == OPLOCK_EXCLUSIVE) { *oplock_granted = EXCLUSIVE_OPLOCK_RETURN; - } else if (oplock_level == OPLOCK_BATCH) { + } else if (lck->can_open.e->oplock_level == OPLOCK_BATCH) { *oplock_granted = BATCH_OPLOCK_RETURN; - } else if (oplock_level == OPLOCK_LEVEL_II) { + } else if (lck->can_open.e->oplock_level == OPLOCK_LEVEL_II) { *oplock_granted = LEVEL_II_OPLOCK_RETURN; } else { *oplock_granted = NO_OPLOCK_RETURN; } } - lck->can_open.e->file_handle = file_handle; - lck->can_open.e->allow_level_II_oplock = allow_level_II_oplock; - lck->can_open.e->oplock_level = oplock_level; - /* it doesn't conflict, so add it to the end */ lck->file.entries = talloc_realloc(lck, lck->file.entries, struct opendb_entry, @@ -569,6 +587,11 @@ static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle, if (lck->file.entries[i].delete_on_close) { lck->file.delete_on_close = true; } + if (odb->lease_ctx && lck->file.entries[i].fd) { + NTSTATUS status; + status = sys_lease_remove(odb->lease_ctx, &lck->file.entries[i]); + NT_STATUS_NOT_OK_RETURN(status); + } if (i < lck->file.num_entries-1) { memmove(lck->file.entries+i, lck->file.entries+i+1, (lck->file.num_entries - (i+1)) * @@ -622,6 +645,13 @@ static NTSTATUS odb_tdb_update_oplock(struct odb_lock *lck, void *file_handle, if (file_handle == lck->file.entries[i].file_handle && cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.entries[i].server)) { lck->file.entries[i].oplock_level = oplock_level; + + if (odb->lease_ctx && lck->file.entries[i].fd) { + NTSTATUS status; + status = sys_lease_update(odb->lease_ctx, &lck->file.entries[i]); + NT_STATUS_NOT_OK_RETURN(status); + } + break; } } @@ -800,6 +830,7 @@ static NTSTATUS odb_tdb_can_open(struct odb_lock *lck, lck->can_open.e->server = odb->ntvfs_ctx->server_id; lck->can_open.e->file_handle = NULL; + lck->can_open.e->fd = NULL; lck->can_open.e->stream_id = stream_id; lck->can_open.e->share_access = share_access; lck->can_open.e->access_mask = access_mask; @@ -831,5 +862,6 @@ static const struct opendb_ops opendb_tdb_ops = { void odb_tdb_init_ops(void) { + sys_lease_init(); odb_set_ops(&opendb_tdb_ops); } diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 2e757e17425..6e77cb7c756 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -300,7 +300,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* now really mark the file as open */ status = odb_open_file(lck, f->handle, name->full_name, - false, OPLOCK_NONE, NULL); + NULL, false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); @@ -360,7 +360,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } status = odb_open_file(lck, f->handle, name->full_name, - false, OPLOCK_NONE, NULL); + NULL, false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; @@ -600,7 +600,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, mode = pvfs_fileperms(pvfs, attrib); /* create the file */ - fd = open(name->full_name, flags | O_CREAT | O_EXCL, mode); + fd = open(name->full_name, flags | O_CREAT | O_EXCL| O_NONBLOCK, mode); if (fd == -1) { return pvfs_map_errno(pvfs, errno); } @@ -688,19 +688,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } - status = odb_open_file(lck, f->handle, name->full_name, - allow_level_II_oplock, - oplock_level, &oplock_granted); - talloc_free(lck); - if (!NT_STATUS_IS_OK(status)) { - /* bad news, we must have hit a race - we don't delete the file - here as the most likely scenario is that someone else created - the file at the same time */ - close(fd); - return status; - } - - f->ntvfs = h; f->pvfs = pvfs; f->pending_list = NULL; @@ -723,6 +710,18 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->sticky_write_time = false; f->handle->open_completed = false; + status = odb_open_file(lck, f->handle, name->full_name, + &f->handle->fd, allow_level_II_oplock, + oplock_level, &oplock_granted); + talloc_free(lck); + if (!NT_STATUS_IS_OK(status)) { + /* bad news, we must have hit a race - we don't delete the file + here as the most likely scenario is that someone else created + the file at the same time */ + close(fd); + return status; + } + DLIST_ADD(pvfs->files.list, f); /* setup a destructor to avoid file descriptor leaks on @@ -859,7 +858,13 @@ NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs, /* setup a pending lock */ status = odb_open_file_pending(lck, r); - if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND,status)) { + /* + * maybe only a unix application + * has the file open + */ + data_blob_free(&r->odb_locking_key); + } else if (!NT_STATUS_IS_OK(status)) { return status; } @@ -876,8 +881,6 @@ NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs, talloc_steal(r, wait_handle); - talloc_steal(pvfs, r); - return NT_STATUS_OK; } @@ -892,8 +895,14 @@ static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r, enum pvfs_wait_notice reason) { union smb_open *io = talloc_get_type(_io, union smb_open); + struct timeval *final_timeout = NULL; NTSTATUS status; + if (private_data) { + final_timeout = talloc_get_type(private_data, + struct timeval); + } + /* w2k3 ignores SMBntcancel for outstanding open requests. It's probably just a bug in their server, but we better do the same */ if (reason == PVFS_WAIT_CANCEL) { @@ -901,6 +910,16 @@ static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r, } if (reason == PVFS_WAIT_TIMEOUT) { + if (final_timeout && + !timeval_expired(final_timeout)) { + /* + * we need to retry periodictly + * after an EAGAIN as there's + * no way the kernel tell us + * an oplock is released. + */ + goto retry; + } /* if it timed out, then give the failure immediately */ talloc_free(r); @@ -909,6 +928,7 @@ static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r, return; } +retry: talloc_free(r); /* try the open again, which could trigger another retry setup @@ -1028,6 +1048,7 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; NTSTATUS status; struct timeval end_time; + struct timeval *final_timeout = NULL; if (io->generic.in.create_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { @@ -1048,12 +1069,28 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, } else if (NT_STATUS_EQUAL(parent_status, NT_STATUS_OPLOCK_NOT_GRANTED)) { end_time = timeval_add(&req->statistics.request_time, pvfs->oplock_break_timeout, 0); + } else if (NT_STATUS_EQUAL(parent_status, STATUS_MORE_ENTRIES)) { + /* + * we got EAGAIN which means a unix application + * has an oplock or share mode + * + * we retry every 4/5 of the sharing violation delay + * to see if the unix application + * has released the oplock or share mode. + */ + final_timeout = talloc(req, struct timeval); + NT_STATUS_HAVE_NO_MEMORY(final_timeout); + *final_timeout = timeval_add(&req->statistics.request_time, + pvfs->oplock_break_timeout, + 0); + end_time = timeval_current_ofs(0, (pvfs->sharing_violation_delay*4)/5); + end_time = timeval_min(final_timeout, &end_time); } else { return NT_STATUS_INTERNAL_ERROR; } - return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL, - pvfs_retry_open_sharing); + return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, + final_timeout, pvfs_retry_open_sharing); } /* @@ -1297,9 +1334,34 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } + if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { + flags |= O_RDWR; + } else { + flags |= O_RDONLY; + } + + /* do the actual open */ + fd = open(f->handle->name->full_name, flags | O_NONBLOCK); + if (fd == -1) { + status = pvfs_map_errno(f->pvfs, errno); + + /* + * STATUS_MORE_ENTRIES is EAGAIN or EWOULDBLOCK + */ + if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && + (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { + return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status); + } + + talloc_free(lck); + return status; + } + + f->handle->fd = fd; + /* now really mark the file as open */ status = odb_open_file(lck, f->handle, name->full_name, - allow_level_II_oplock, + &f->handle->fd, allow_level_II_oplock, oplock_level, &oplock_granted); if (!NT_STATUS_IS_OK(status)) { @@ -1307,6 +1369,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } + f->handle->have_opendb_entry = true; + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { oplock_granted = OPLOCK_BATCH; } else if (oplock_granted != OPLOCK_NONE) { @@ -1317,23 +1381,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } } - f->handle->have_opendb_entry = true; - - if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { - flags |= O_RDWR; - } else { - flags |= O_RDONLY; - } - - /* do the actual open */ - fd = open(f->handle->name->full_name, flags); - if (fd == -1) { - talloc_free(lck); - return pvfs_map_errno(f->pvfs, errno); - } - - f->handle->fd = fd; - stream_existed = name->stream_exists; /* if this was a stream create then create the stream as well */ diff --git a/source4/ntvfs/posix/pvfs_rename.c b/source4/ntvfs/posix/pvfs_rename.c index 29b2d030059..5c2a627084c 100644 --- a/source4/ntvfs/posix/pvfs_rename.c +++ b/source4/ntvfs/posix/pvfs_rename.c @@ -568,6 +568,9 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs, NTSTATUS pvfs_rename(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_rename *ren) { + struct pvfs_state *pvfs = ntvfs->private_data; + struct pvfs_file *f; + switch (ren->generic.level) { case RAW_RENAME_RENAME: return pvfs_rename_mv(ntvfs, req, ren); @@ -575,6 +578,15 @@ NTSTATUS pvfs_rename(struct ntvfs_module_context *ntvfs, case RAW_RENAME_NTRENAME: return pvfs_rename_nt(ntvfs, req, ren); + case RAW_RENAME_NTTRANS: + f = pvfs_find_fd(pvfs, req, ren->nttrans.in.file.ntvfs); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + + /* wk23 ignores the request */ + return NT_STATUS_OK; + default: break; } diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index 7a2d964b9dd..4cb47a4f1fa 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -219,6 +219,12 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, return pvfs_unlink_one(pvfs, req, unl, name); } + /* + * disable async requests in the wildcard case + * untill we have proper tests for this + */ + req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC; + /* get list of matching files */ status = pvfs_list_start(pvfs, name, req, &dir); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/ntvfs/sysdep/config.m4 b/source4/ntvfs/sysdep/config.m4 index f70cac5e642..6de75a42941 100644 --- a/source4/ntvfs/sysdep/config.m4 +++ b/source4/ntvfs/sysdep/config.m4 @@ -11,3 +11,13 @@ fi if test x"$ac_cv_header_linux_inotify_h" = x"yes" -a x"$ac_cv_have___NR_inotify_init_decl" = x"yes"; then SMB_ENABLE(sys_notify_inotify, YES) fi + +AC_HAVE_DECL(F_SETLEASE, [#include <fcntl.h>]) +AC_HAVE_DECL(SA_SIGINFO, [#include <signal.h>]) + +SMB_ENABLE(sys_lease_linux, NO) + +if test x"$ac_cv_have_F_SETLEASE_decl" = x"yes" \ + -a x"$ac_cv_have_SA_SIGINFO_decl" = x"yes"; then + SMB_ENABLE(sys_lease_linux, YES) +fi diff --git a/source4/ntvfs/sysdep/config.mk b/source4/ntvfs/sysdep/config.mk index 6cd5d88aca2..68be660049e 100644 --- a/source4/ntvfs/sysdep/config.mk +++ b/source4/ntvfs/sysdep/config.mk @@ -15,3 +15,11 @@ sys_notify_inotify_OBJ_FILES = ntvfs/sysdep/inotify.o ################################################ sys_notify_OBJ_FILES = ntvfs/sysdep/sys_notify.o + +[SUBSYSTEM::sys_lease_linux] + +sys_lease_linux_OBJ_FILES = ntvfs/sysdep/sys_lease_linux.o + +[SUBSYSTEM::sys_lease] + +sys_lease_OBJ_FILES = ntvfs/sysdep/sys_lease.o diff --git a/source4/ntvfs/sysdep/sys_lease.c b/source4/ntvfs/sysdep/sys_lease.c new file mode 100644 index 00000000000..28dd27a7082 --- /dev/null +++ b/source4/ntvfs/sysdep/sys_lease.c @@ -0,0 +1,142 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Stefan Metzmacher 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + abstract the various kernel interfaces to leases (oplocks) into a + single Samba friendly interface +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "ntvfs/sysdep/sys_lease.h" +#include "lib/events/events.h" +#include "lib/util/dlinklist.h" +#include "param/param.h" +#include "build.h" + +/* list of registered backends */ +static struct sys_lease_ops *backends; +static uint32_t num_backends; + +#define LEASE_BACKEND "lease:backend" + +/* + initialise a system change notify backend +*/ +_PUBLIC_ struct sys_lease_context *sys_lease_context_create(struct share_config *scfg, + TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct messaging_context *msg, + sys_lease_send_break_fn break_send) +{ + struct sys_lease_context *ctx; + const char *bname; + int i; + NTSTATUS status; + + if (num_backends == 0) { + return NULL; + } + + if (ev == NULL) { + ev = event_context_find(mem_ctx); + } + + ctx = talloc_zero(mem_ctx, struct sys_lease_context); + if (ctx == NULL) { + return NULL; + } + + ctx->event_ctx = ev; + ctx->msg_ctx = msg; + ctx->break_send = break_send; + + bname = share_string_option(scfg, LEASE_BACKEND, NULL); + if (!bname) { + talloc_free(ctx); + return NULL; + } + + for (i=0;i<num_backends;i++) { + if (strcasecmp(backends[i].name, bname) == 0) { + ctx->ops = &backends[i]; + break; + } + } + + if (!ctx->ops) { + talloc_free(ctx); + return NULL; + } + + status = ctx->ops->init(ctx); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(ctx); + return NULL; + } + + return ctx; +} + +/* + register a lease backend +*/ +_PUBLIC_ NTSTATUS sys_lease_register(const struct sys_lease_ops *backend) +{ + struct sys_lease_ops *b; + b = talloc_realloc(talloc_autofree_context(), backends, + struct sys_lease_ops, num_backends+1); + NT_STATUS_HAVE_NO_MEMORY(b); + backends = b; + backends[num_backends] = *backend; + num_backends++; + return NT_STATUS_OK; +} + +_PUBLIC_ NTSTATUS sys_lease_init(void) +{ + static bool initialized = false; + + init_module_fn static_init[] = { STATIC_sys_lease_MODULES }; + + if (initialized) return NT_STATUS_OK; + initialized = true; + + run_init_functions(static_init); + + return NT_STATUS_OK; +} + +NTSTATUS sys_lease_setup(struct sys_lease_context *ctx, + struct opendb_entry *e) +{ + return ctx->ops->setup(ctx, e); +} + +NTSTATUS sys_lease_update(struct sys_lease_context *ctx, + struct opendb_entry *e) +{ + return ctx->ops->update(ctx, e); +} + +NTSTATUS sys_lease_remove(struct sys_lease_context *ctx, + struct opendb_entry *e) +{ + return ctx->ops->remove(ctx, e); +} diff --git a/source4/ntvfs/sysdep/sys_lease.h b/source4/ntvfs/sysdep/sys_lease.h new file mode 100644 index 00000000000..e53760fb1eb --- /dev/null +++ b/source4/ntvfs/sysdep/sys_lease.h @@ -0,0 +1,65 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Stefan Metzmacher 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "param/share.h" + +struct sys_lease_context; +struct opendb_entry; +struct messaging_context; + +typedef NTSTATUS (*sys_lease_send_break_fn)(struct messaging_context *, + struct opendb_entry *, + uint8_t level); + +struct sys_lease_ops { + const char *name; + NTSTATUS (*init)(struct sys_lease_context *ctx); + NTSTATUS (*setup)(struct sys_lease_context *ctx, + struct opendb_entry *e); + NTSTATUS (*update)(struct sys_lease_context *ctx, + struct opendb_entry *e); + NTSTATUS (*remove)(struct sys_lease_context *ctx, + struct opendb_entry *e); +}; + +struct sys_lease_context { + struct event_context *event_ctx; + struct messaging_context *msg_ctx; + sys_lease_send_break_fn break_send; + void *private_data; /* for use of backend */ + const struct sys_lease_ops *ops; +}; + +NTSTATUS sys_lease_register(const struct sys_lease_ops *ops); +NTSTATUS sys_lease_init(void); + +struct sys_lease_context *sys_lease_context_create(struct share_config *scfg, + TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct messaging_context *msg_ctx, + sys_lease_send_break_fn break_send); + +NTSTATUS sys_lease_setup(struct sys_lease_context *ctx, + struct opendb_entry *e); + +NTSTATUS sys_lease_update(struct sys_lease_context *ctx, + struct opendb_entry *e); + +NTSTATUS sys_lease_remove(struct sys_lease_context *ctx, + struct opendb_entry *e); diff --git a/source4/ntvfs/sysdep/sys_lease_linux.c b/source4/ntvfs/sysdep/sys_lease_linux.c new file mode 100644 index 00000000000..0727eed2121 --- /dev/null +++ b/source4/ntvfs/sysdep/sys_lease_linux.c @@ -0,0 +1,213 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Stefan Metzmacher 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + lease (oplock) implementation using fcntl F_SETLEASE on linux +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "lib/events/events.h" +#include "ntvfs/sysdep/sys_lease.h" +#include "ntvfs/ntvfs.h" +#include "librpc/gen_ndr/ndr_opendb.h" +#include "lib/util/dlinklist.h" +#include "cluster/cluster.h" + +#define LINUX_LEASE_RT_SIGNAL (SIGRTMIN+1) + +struct linux_lease_pending { + struct linux_lease_pending *prev, *next; + struct sys_lease_context *ctx; + struct opendb_entry e; +}; + +/* the global linked list of pending leases */ +static struct linux_lease_pending *leases; + +static void linux_lease_signal_handler(struct event_context *ev_ctx, + struct signal_event *se, + int signum, int count, + void *_info, void *private_data) +{ + struct sys_lease_context *ctx = talloc_get_type(private_data, + struct sys_lease_context); + siginfo_t *info = (siginfo_t *)_info; + struct linux_lease_pending *c; + int got_fd = info->si_fd; + + for (c = leases; c; c = c->next) { + int *fd = (int *)c->e.fd; + + if (got_fd == *fd) { + break; + } + } + + if (!c) { + return; + } + + ctx->break_send(ctx->msg_ctx, &c->e, OPLOCK_BREAK_TO_NONE); +} + +static int linux_lease_pending_destructor(struct linux_lease_pending *p) +{ + int ret; + int *fd = (int *)p->e.fd; + + DLIST_REMOVE(leases, p); + + if (*fd == -1) { + return 0; + } + + ret = fcntl(*fd, F_SETLEASE, F_UNLCK); + if (ret == -1) { + DEBUG(0,("%s: failed to remove oplock: %s\n", + __FUNCTION__, strerror(errno))); + } + + return 0; +} + +static NTSTATUS linux_lease_init(struct sys_lease_context *ctx) +{ + struct signal_event *se; + + se = event_add_signal(ctx->event_ctx, ctx, + LINUX_LEASE_RT_SIGNAL, SA_SIGINFO, + linux_lease_signal_handler, ctx); + NT_STATUS_HAVE_NO_MEMORY(se); + + return NT_STATUS_OK; +} + +static NTSTATUS linux_lease_setup(struct sys_lease_context *ctx, + struct opendb_entry *e) +{ + int ret; + int *fd = (int *)e->fd; + struct linux_lease_pending *p; + + if (e->oplock_level == OPLOCK_NONE) { + e->fd = NULL; + return NT_STATUS_OK; + } else if (e->oplock_level == OPLOCK_LEVEL_II) { + /* + * the linux kernel doesn't support level2 oplocks + * so fix up the granted oplock level + */ + e->oplock_level = OPLOCK_NONE; + e->allow_level_II_oplock = false; + e->fd = NULL; + return NT_STATUS_OK; + } + + p = talloc(ctx, struct linux_lease_pending); + NT_STATUS_HAVE_NO_MEMORY(p); + + p->ctx = ctx; + p->e = *e; + + ret = fcntl(*fd, F_SETSIG, LINUX_LEASE_RT_SIGNAL); + if (ret == -1) { + talloc_free(p); + return map_nt_error_from_unix(errno); + } + + ret = fcntl(*fd, F_SETLEASE, F_WRLCK); + if (ret == -1) { + talloc_free(p); + return map_nt_error_from_unix(errno); + } + + DLIST_ADD(leases, p); + + talloc_set_destructor(p, linux_lease_pending_destructor); + + return NT_STATUS_OK; +} + +static NTSTATUS linux_lease_remove(struct sys_lease_context *ctx, + struct opendb_entry *e); + +static NTSTATUS linux_lease_update(struct sys_lease_context *ctx, + struct opendb_entry *e) +{ + struct linux_lease_pending *c; + + for (c = leases; c; c = c->next) { + if (c->e.fd == e->fd) { + break; + } + } + + if (!c) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* + * set the fd pointer to NULL so that the caller + * will not call the remove function as the oplock + * is already removed + */ + e->fd = NULL; + + talloc_free(c); + + return NT_STATUS_OK; +} + +static NTSTATUS linux_lease_remove(struct sys_lease_context *ctx, + struct opendb_entry *e) +{ + struct linux_lease_pending *c; + + for (c = leases; c; c = c->next) { + if (c->e.fd == e->fd) { + break; + } + } + + if (!c) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + talloc_free(c); + + return NT_STATUS_OK; +} + +static struct sys_lease_ops linux_lease_ops = { + .name = "linux", + .init = linux_lease_init, + .setup = linux_lease_setup, + .update = linux_lease_update, + .remove = linux_lease_remove +}; + +/* + initialialise the linux lease module + */ +NTSTATUS sys_lease_linux_init(void) +{ + /* register ourselves as a system lease module */ + return sys_lease_register(&linux_lease_ops); +} diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm b/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm index 86b8951026c..7a2575b8972 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm @@ -44,6 +44,36 @@ sub new($) bless($self, $class); } +sub ElementDirection($) +{ + my ($e) = @_; + + return "[in,out]" if (has_property($e, "in") and has_property($e, "out")); + return "[in]" if (has_property($e, "in")); + return "[out]" if (has_property($e, "out")); + return "[in,out]"; +} + +sub HeaderProperties($$) +{ + my($props,$ignores) = @_; + my $ret = ""; + + foreach my $d (keys %{$props}) { + next if (grep(/^$d$/, @$ignores)); + if($props->{$d} ne "1") { + $ret.= "$d($props->{$d}),"; + } else { + $ret.="$d,"; + } + } + + if ($ret) { + return "[" . substr($ret, 0, -1) . "]"; + } +} + + sub ParseFunction($$$) { my ($self, $if, $fn) = @_; @@ -57,7 +87,9 @@ sub ParseFunction($$$) $fn_args .= "struct rpc_pipe_client *cli,\n" . $pad . "TALLOC_CTX *mem_ctx"; foreach (@{$fn->{ELEMENTS}}) { - $fn_args .= ",\n" . $pad . DeclLong($_); + my $dir = ElementDirection($_); + my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]); + $fn_args .= ",\n" . $pad . DeclLong($_) . " /* $dir $prop */"; } if (defined($fn->{RETURN_TYPE}) && ($fn->{RETURN_TYPE} eq "WERROR")) { diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 4375088e170..429c413b980 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -99,8 +99,21 @@ static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX int ret; DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY); + if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) { struct lsa_secret_state *secret_state = h->data; + + /* Ensure user is permitted to delete this... */ + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + break; + default: + /* Users and annonymous are not allowed delete things */ + return NT_STATUS_ACCESS_DENIED; + } + ret = ldb_delete(secret_state->sam_ldb, secret_state->secret_dn); talloc_free(h); @@ -446,6 +459,8 @@ static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TAL /* lsa_CreateAccount + + This call does not seem to have any long-term effects, hence no database operations */ static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct lsa_CreateAccount *r) @@ -644,9 +659,26 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_cal /* create the trusted_domain */ ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg); - if (ret != LDB_SUCCESS) { - DEBUG(0,("Failed to create trusted_domain record %s: %s\n", - ldb_dn_get_linearized(msg->dn), ldb_errstring(trusted_domain_state->policy->sam_ldb))); + switch (ret) { + case LDB_SUCCESS: + break; + case LDB_ERR_ENTRY_ALREADY_EXISTS: + ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb); + DEBUG(0,("Failed to create trusted domain record %s: %s\n", + ldb_dn_get_linearized(msg->dn), + ldb_errstring(trusted_domain_state->policy->sam_ldb))); + return NT_STATUS_DOMAIN_EXISTS; + case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: + ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb); + DEBUG(0,("Failed to create trusted domain record %s: %s\n", + ldb_dn_get_linearized(msg->dn), + ldb_errstring(trusted_domain_state->policy->sam_ldb))); + return NT_STATUS_ACCESS_DENIED; + default: + ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb); + DEBUG(0,("Failed to create user record %s: %s\n", + ldb_dn_get_linearized(msg->dn), + ldb_errstring(trusted_domain_state->policy->sam_ldb))); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -1656,6 +1688,16 @@ static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALL DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); ZERO_STRUCTP(r->out.sec_handle); + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + break; + default: + /* Users and annonymous are not allowed create secrets */ + return NT_STATUS_ACCESS_DENIED; + } + policy_state = policy_handle->data; if (!r->in.name.string) { @@ -1802,6 +1844,16 @@ static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC return NT_STATUS_INVALID_PARAMETER; } + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + break; + default: + /* Users and annonymous are not allowed to access secrets */ + return NT_STATUS_ACCESS_DENIED; + } + secret_state = talloc(mem_ctx, struct lsa_secret_state); if (!secret_state) { return NT_STATUS_NO_MEMORY; @@ -1833,10 +1885,10 @@ static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC } } else { + secret_state->global = false; secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx)); - secret_state->global = false; name = r->in.name.string; if (strlen(name) < 1) { return NT_STATUS_INVALID_PARAMETER; @@ -2068,6 +2120,17 @@ static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLO DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET); + /* Ensure user is permitted to read this... */ + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + break; + default: + /* Users and annonymous are not allowed to read secrets */ + return NT_STATUS_ACCESS_DENIED; + } + secret_state = h->data; /* pull all the user attributes */ diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c index bcc2af97a7a..e01efa82338 100644 --- a/source4/rpc_server/lsa/lsa_lookup.c +++ b/source4/rpc_server/lsa/lsa_lookup.c @@ -220,6 +220,7 @@ static NTSTATUS dcesrv_lsa_lookup_name(struct loadparm_context *lp_ctx, } else if (strchr_m(name, '@')) { status = crack_name_to_nt4_name(mem_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username); if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status))); return status; } } else { diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index 8193e0a882a..0aa4d65d8c5 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -324,11 +324,11 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL struct samr_connect_state *c_state; struct dcesrv_handle *h; struct samr_SamArray *array; - int count, i, start_i; + int i, start_i, ret; const char * const dom_attrs[] = { "cn", NULL}; const char * const ref_attrs[] = { "nETBIOSName", NULL}; - struct ldb_message **dom_msgs; - struct ldb_message **ref_msgs; + struct ldb_result *dom_res; + struct ldb_result *ref_res; struct ldb_dn *partitions_basedn; *r->out.resume_handle = 0; @@ -341,19 +341,18 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx); - count = gendb_search(c_state->sam_ctx, - mem_ctx, NULL, &dom_msgs, dom_attrs, - "(objectClass=domain)"); - if (count == -1) { - DEBUG(0,("samdb: no domains found in EnumDomains\n")); + ret = ldb_search_exp_fmt(c_state->sam_ctx, mem_ctx, &dom_res, ldb_get_default_basedn(c_state->sam_ctx), + LDB_SCOPE_SUBTREE, dom_attrs, "(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain))"); + if (ret != LDB_SUCCESS) { + DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx))); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - *r->out.resume_handle = count; + *r->out.resume_handle = dom_res->count; start_i = *r->in.resume_handle; - if (start_i >= count) { + if (start_i >= dom_res->count) { /* search past end of list is not an error for this call */ return NT_STATUS_OK; } @@ -366,23 +365,27 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL array->count = 0; array->entries = NULL; - array->entries = talloc_array(mem_ctx, struct samr_SamEntry, count - start_i); + array->entries = talloc_array(mem_ctx, struct samr_SamEntry, dom_res->count - start_i); if (array->entries == NULL) { return NT_STATUS_NO_MEMORY; } - for (i=0;i<count-start_i;i++) { - int ret; + for (i=0;i<dom_res->count-start_i;i++) { array->entries[i].idx = start_i + i; /* try and find the domain */ - ret = gendb_search(c_state->sam_ctx, mem_ctx, partitions_basedn, - &ref_msgs, ref_attrs, - "(&(objectClass=crossRef)(ncName=%s))", - ldb_dn_get_linearized(dom_msgs[i]->dn)); - if (ret == 1) { - array->entries[i].name.string = samdb_result_string(ref_msgs[0], "nETBIOSName", NULL); + ret = ldb_search_exp_fmt(c_state->sam_ctx, mem_ctx, &ref_res, partitions_basedn, + LDB_SCOPE_SUBTREE, ref_attrs, "(&(objectClass=crossRef)(ncName=%s))", + ldb_dn_get_linearized(dom_res->msgs[i]->dn)); + + if (ret != LDB_SUCCESS) { + DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx))); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + if (ref_res->count == 1) { + array->entries[i].name.string = samdb_result_string(ref_res->msgs[0], "nETBIOSName", NULL); } else { - array->entries[i].name.string = samdb_result_string(dom_msgs[i], "cn", NULL); + array->entries[i].name.string = samdb_result_string(dom_res->msgs[i], "cn", NULL); } } @@ -425,7 +428,7 @@ static NTSTATUS dcesrv_samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLO ret = gendb_search(c_state->sam_ctx, mem_ctx, NULL, &dom_msgs, dom_attrs, - "(&(objectSid=%s)(&(|(objectclass=domain)(objectClass=builtinDomain))))", + "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid)); if (ret == 0) { return NT_STATUS_NO_SUCH_DOMAIN; @@ -472,6 +475,14 @@ static NTSTATUS dcesrv_samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLO } d_state->access_mask = r->in.access_mask; + if (dom_sid_equal(d_state->domain_sid, dom_sid_parse_talloc(mem_ctx, SID_BUILTIN))) { + d_state->builtin = true; + } else { + d_state->builtin = false; + } + + d_state->lp_ctx = dce_call->conn->dce_ctx->lp_ctx; + h_domain = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_DOMAIN); if (!h_domain) { talloc_free(d_state); @@ -520,6 +531,10 @@ static NTSTATUS dcesrv_samr_info_DomInfo2(struct samr_domain_state *state, string */ info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, dom_msgs[0], "fSMORoleOwner"); + if (!info->primary.string) { + info->primary.string = lp_netbios_name(state->lp_ctx); + } + info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff", 0x8000000000000000LL); @@ -614,6 +629,10 @@ static NTSTATUS dcesrv_samr_info_DomInfo6(struct samr_domain_state *state, info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, dom_msgs[0], "fSMORoleOwner"); + if (!info->primary.string) { + info->primary.string = lp_netbios_name(state->lp_ctx); + } + return NT_STATUS_OK; } @@ -1004,6 +1023,11 @@ static NTSTATUS dcesrv_samr_CreateDomainGroup(struct dcesrv_call_state *dce_call d_state = h->data; + if (d_state->builtin) { + DEBUG(5, ("Cannot create a domain group in the BUILTIN domain")); + return NT_STATUS_ACCESS_DENIED; + } + groupname = r->in.name->string; if (groupname == NULL) { @@ -1130,9 +1154,6 @@ static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, if (ldb_cnt == -1) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } - if (ldb_cnt == 0 || r->in.max_size == 0) { - return NT_STATUS_OK; - } /* convert to SamEntry format */ entries = talloc_array(mem_ctx, struct samr_SamEntry, ldb_cnt); @@ -1166,10 +1187,6 @@ static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, first<count && entries[first].idx <= *r->in.resume_handle; first++) ; - if (first == count) { - return NT_STATUS_OK; - } - /* return the rest, limit by max_size. Note that we use the w2k3 element size value of 54 */ r->out.num_entries = count - first; @@ -1234,6 +1251,10 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL d_state = h->data; + if (d_state->builtin) { + DEBUG(5, ("Cannot create a user in the BUILTIN domain")); + return NT_STATUS_ACCESS_DENIED; + } account_name = r->in.account_name->string; if (account_name == NULL) { @@ -1318,15 +1339,16 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL /* create the user */ ret = ldb_add(d_state->sam_ctx, msg); switch (ret) { - case LDB_SUCCESS: + case LDB_SUCCESS: break; - case LDB_ERR_ENTRY_ALREADY_EXISTS: + case LDB_ERR_ENTRY_ALREADY_EXISTS: ldb_transaction_cancel(d_state->sam_ctx); DEBUG(0,("Failed to create user record %s: %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(d_state->sam_ctx))); return NT_STATUS_USER_EXISTS; - case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: + case LDB_ERR_UNWILLING_TO_PERFORM: + case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: ldb_transaction_cancel(d_state->sam_ctx); DEBUG(0,("Failed to create user record %s: %s\n", ldb_dn_get_linearized(msg->dn), @@ -1466,8 +1488,8 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, { struct dcesrv_handle *h; struct samr_domain_state *d_state; - struct ldb_message **res; - int count, num_filtered_entries, i, first; + struct ldb_result *res; + int ret, num_filtered_entries, i, first; struct samr_SamEntry *entries; const char * const attrs[] = { "objectSid", "sAMAccountName", "userAccountControl", NULL }; @@ -1479,32 +1501,30 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, d_state = h->data; - /* search for all users in this domain. This could possibly be cached and - resumed based on resume_key */ - count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs, - "objectclass=user"); - if (count == -1) { + /* don't have to worry about users in the builtin domain, as there are none */ + ret = ldb_search_exp_fmt(d_state->sam_ctx, mem_ctx, &res, d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=user"); + + if (ret != LDB_SUCCESS) { + DEBUG(3, ("Failed to search for Domain Users in %s: %s\n", + ldb_dn_get_linearized(d_state->domain_dn), ldb_errstring(d_state->sam_ctx))); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - if (count == 0 || r->in.max_size == 0) { - return NT_STATUS_OK; - } /* convert to SamEntry format */ - entries = talloc_array(mem_ctx, struct samr_SamEntry, count); + entries = talloc_array(mem_ctx, struct samr_SamEntry, res->count); if (!entries) { return NT_STATUS_NO_MEMORY; } num_filtered_entries = 0; - for (i=0;i<count;i++) { + for (i=0;i<res->count;i++) { /* Check if a mask has been requested */ if (r->in.acct_flags - && ((samdb_result_acct_flags(d_state->sam_ctx, mem_ctx, res[i], + && ((samdb_result_acct_flags(d_state->sam_ctx, mem_ctx, res->msgs[i], d_state->domain_dn) & r->in.acct_flags) == 0)) { continue; } - entries[num_filtered_entries].idx = samdb_result_rid_from_sid(mem_ctx, res[i], "objectSid", 0); - entries[num_filtered_entries].name.string = samdb_result_string(res[i], "sAMAccountName", ""); + entries[num_filtered_entries].idx = samdb_result_rid_from_sid(mem_ctx, res->msgs[i], "objectSid", 0); + entries[num_filtered_entries].name.string = samdb_result_string(res->msgs[i], "sAMAccountName", ""); num_filtered_entries++; } @@ -1566,6 +1586,11 @@ static NTSTATUS dcesrv_samr_CreateDomAlias(struct dcesrv_call_state *dce_call, T d_state = h->data; + if (d_state->builtin) { + DEBUG(5, ("Cannot create a domain alias in the BUILTIN domain")); + return NT_STATUS_ACCESS_DENIED; + } + alias_name = r->in.alias_name->string; if (alias_name == NULL) { @@ -2073,7 +2098,8 @@ static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, T { struct dcesrv_handle *h; struct samr_account_state *a_state; - struct ldb_message *msg, **res; + struct ldb_message *msg; + struct ldb_result *res; const char * const attrs[4] = { "sAMAccountName", "description", "numMembers", NULL }; int ret; @@ -2083,14 +2109,22 @@ static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, T DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP); a_state = h->data; + + ret = ldb_search_exp_fmt(a_state->sam_ctx, mem_ctx, &res, a_state->account_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=*"); + + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + return NT_STATUS_NO_SUCH_GROUP; + } else if (ret != LDB_SUCCESS) { + DEBUG(2, ("Error reading group info: %s\n", ldb_errstring(a_state->sam_ctx))); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } - /* pull all the group attributes */ - ret = gendb_search_dn(a_state->sam_ctx, mem_ctx, - a_state->account_dn, &res, attrs); - if (ret != 1) { + if (res->count != 1) { + DEBUG(2, ("Error finding group info, got %d entries\n", res->count)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; } - msg = res[0]; + msg = res->msgs[0]; /* allocate the info structure */ r->out.info = talloc(mem_ctx, union samr_GroupInfo); diff --git a/source4/rpc_server/samr/dcesrv_samr.h b/source4/rpc_server/samr/dcesrv_samr.h index 7a6978344be..a28a4bec437 100644 --- a/source4/rpc_server/samr/dcesrv_samr.h +++ b/source4/rpc_server/samr/dcesrv_samr.h @@ -52,6 +52,8 @@ struct samr_domain_state { const char *domain_name; struct ldb_dn *domain_dn; enum server_role role; + bool builtin; + struct loadparm_context *lp_ctx; }; /* diff --git a/source4/rpc_server/winreg/rpc_winreg.c b/source4/rpc_server/winreg/rpc_winreg.c index 681e3b918f8..9993dc14c11 100644 --- a/source4/rpc_server/winreg/rpc_winreg.c +++ b/source4/rpc_server/winreg/rpc_winreg.c @@ -26,6 +26,7 @@ #include "rpc_server/common/common.h" #include "librpc/gen_ndr/ndr_security.h" #include "param/param.h" +#include "libcli/security/security.h" enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY }; @@ -120,32 +121,39 @@ static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call, newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY); - /* the security descriptor is optional */ - if (r->in.secdesc != NULL) { - DATA_BLOB sdblob; - enum ndr_err_code ndr_err; - sdblob.data = r->in.secdesc->sd.data; - sdblob.length = r->in.secdesc->sd.len; - if (sdblob.data == NULL) { - return WERR_INVALID_PARAM; + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + /* the security descriptor is optional */ + if (r->in.secdesc != NULL) { + DATA_BLOB sdblob; + enum ndr_err_code ndr_err; + sdblob.data = r->in.secdesc->sd.data; + sdblob.length = r->in.secdesc->sd.len; + if (sdblob.data == NULL) { + return WERR_INVALID_PARAM; + } + ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd, + (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return WERR_INVALID_PARAM; + } } - ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd, - (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return WERR_INVALID_PARAM; + + error = reg_key_add_name(newh, (struct registry_key *)h->data, + r->in.name.name, NULL, r->in.secdesc?&sd:NULL, + (struct registry_key **)&newh->data); + if (W_ERROR_IS_OK(error)) { + r->out.new_handle = &newh->wire_handle; + } else { + talloc_free(newh); } + + return error; + default: + return WERR_ACCESS_DENIED; } - - error = reg_key_add_name(newh, (struct registry_key *)h->data, - r->in.name.name, NULL, r->in.secdesc?&sd:NULL, - (struct registry_key **)&newh->data); - if (W_ERROR_IS_OK(error)) { - r->out.new_handle = &newh->wire_handle; - } else { - talloc_free(newh); - } - - return error; } @@ -160,7 +168,14 @@ static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call, DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); - return reg_key_del((struct registry_key *)h->data, r->in.key.name); + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + return reg_key_del((struct registry_key *)h->data, r->in.key.name); + default: + return WERR_ACCESS_DENIED; + } } @@ -176,9 +191,16 @@ static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call, DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); - key = h->data; - - return reg_del_value(key, r->in.value.name); + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + key = h->data; + + return reg_del_value(key, r->in.value.name); + default: + return WERR_ACCESS_DENIED; + } } @@ -289,7 +311,14 @@ static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call, DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); - return reg_key_flush(h->data); + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + return reg_key_flush(h->data); + default: + return WERR_ACCESS_DENIED; + } } @@ -342,23 +371,31 @@ static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call, DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY); - if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) { - newh = talloc_reference(dce_call->context, h); - result = WERR_OK; - } else { - newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY); - result = reg_open_key(newh, (struct registry_key *)h->data, - r->in.keyname.name, - (struct registry_key **)&newh->data); - } - - if (W_ERROR_IS_OK(result)) { - r->out.handle = &newh->wire_handle; - } else { - talloc_free(newh); + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + case SECURITY_USER: + if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) { + newh = talloc_reference(dce_call->context, h); + result = WERR_OK; + } else { + newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY); + result = reg_open_key(newh, (struct registry_key *)h->data, + r->in.keyname.name, + (struct registry_key **)&newh->data); + } + + if (W_ERROR_IS_OK(result)) { + r->out.handle = &newh->wire_handle; + } else { + talloc_free(newh); + } + return result; + default: + return WERR_ACCESS_DENIED; } - return result; } @@ -376,17 +413,25 @@ static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call, DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); - k = h->data; - - ret = reg_key_get_info(mem_ctx, k, &classname, r->out.num_subkeys, - r->out.num_values, r->out.last_changed_time, - r->out.max_subkeylen, r->out.max_valnamelen, - r->out.max_valbufsize); - - if (r->out.classname != NULL) - r->out.classname->name = classname; - - return ret; + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + case SECURITY_USER: + k = h->data; + + ret = reg_key_get_info(mem_ctx, k, &classname, r->out.num_subkeys, + r->out.num_values, r->out.last_changed_time, + r->out.max_subkeylen, r->out.max_valnamelen, + r->out.max_valbufsize); + + if (r->out.classname != NULL) + r->out.classname->name = classname; + + return ret; + default: + return WERR_ACCESS_DENIED; + } } @@ -405,35 +450,43 @@ static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call, DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); - key = h->data; - - result = reg_key_get_value_by_name(mem_ctx, key, r->in.value_name.name, - &value_type, &value_data); - - if (!W_ERROR_IS_OK(result)) { - return result; - } - - /* Just asking for the size of the buffer */ - r->out.type = talloc(mem_ctx, uint32_t); - if (!r->out.type) { - return WERR_NOMEM; - } - *r->out.type = value_type; - r->out.length = talloc(mem_ctx, uint32_t); - if (!r->out.length) { - return WERR_NOMEM; - } - *r->out.length = value_data.length; - if (r->in.data == NULL) { - r->out.size = talloc(mem_ctx, uint32_t); - *r->out.size = value_data.length; - } else { - r->out.size = r->in.size; - r->out.data = value_data.data; + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + case SECURITY_USER: + key = h->data; + + result = reg_key_get_value_by_name(mem_ctx, key, r->in.value_name.name, + &value_type, &value_data); + + if (!W_ERROR_IS_OK(result)) { + return result; + } + + /* Just asking for the size of the buffer */ + r->out.type = talloc(mem_ctx, uint32_t); + if (!r->out.type) { + return WERR_NOMEM; + } + *r->out.type = value_type; + r->out.length = talloc(mem_ctx, uint32_t); + if (!r->out.length) { + return WERR_NOMEM; + } + *r->out.length = value_data.length; + if (r->in.data == NULL) { + r->out.size = talloc(mem_ctx, uint32_t); + *r->out.size = value_data.length; + } else { + r->out.size = r->in.size; + r->out.data = value_data.data; + } + + return WERR_OK; + default: + return WERR_ACCESS_DENIED; } - - return WERR_OK; } @@ -497,11 +550,17 @@ static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call, key = h->data; - data.data = r->in.data; - data.length = r->in.size; - result = reg_val_set(key, r->in.name.name, r->in.type, data); - - return result; + switch (security_session_user_level(dce_call->conn->auth_state.session_info)) + { + case SECURITY_SYSTEM: + case SECURITY_ADMINISTRATOR: + data.data = r->in.data; + data.length = r->in.size; + result = reg_val_set(key, r->in.name.name, r->in.type, data); + return result; + default: + return WERR_ACCESS_DENIED; + } } diff --git a/source4/script/valgrind_run b/source4/script/valgrind_run index 45361c22b10..5171d171a74 100755 --- a/source4/script/valgrind_run +++ b/source4/script/valgrind_run @@ -4,4 +4,6 @@ ENV="$1" shift 1 -$ENV valgrind -q --db-attach=yes --num-callers=30 $@ +CMD="$ENV valgrind -q --db-attach=yes --num-callers=30 $@" +echo $CMD +eval $CMD diff --git a/source4/scripting/python/config.m4 b/source4/scripting/python/config.m4 index 2142cd9abd1..3790071ba88 100644 --- a/source4/scripting/python/config.m4 +++ b/source4/scripting/python/config.m4 @@ -22,8 +22,8 @@ AC_DEFUN([TRY_LINK_PYTHON], CFLAGS="$CFLAGS $2" AC_TRY_LINK([ + /* we have our own configure tests */ #include <Python.h> - #include <stdlib.h> ],[ Py_InitModule(NULL, NULL); ],[ diff --git a/source4/scripting/python/misc_wrap.c b/source4/scripting/python/misc_wrap.c index f467f851bdd..cf85e91e1e6 100644 --- a/source4/scripting/python/misc_wrap.c +++ b/source4/scripting/python/misc_wrap.c @@ -3027,7 +3027,7 @@ SWIGINTERN PyObject *_wrap_dsdb_attach_schema_from_ldif_file(PyObject *SWIGUNUSE "ldb context must be non-NULL"); result = dsdb_attach_schema_from_ldif_file(arg1,(char const *)arg2,(char const *)arg3); if (!W_ERROR_IS_OK(result)) { - PyObject *obj = Py_BuildValue((char *)"(i,s)", (&result)->v, win_errstr(result)); + PyObject *obj = Py_BuildValue((char *)"(i,s)", W_ERROR_V(result), win_errstr(result)); PyErr_SetObject(PyExc_RuntimeError, obj); SWIG_fail; } else if (resultobj == NULL) { diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index ebca1f8e40a..e97ce694b4c 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -51,7 +51,6 @@ class InvalidNetbiosName(Exception): class ProvisionPaths: def __init__(self): - self.smbconf = None self.shareconf = None self.hklm = None self.hkcu = None @@ -67,7 +66,27 @@ class ProvisionPaths: self.dns = None self.winsdb = None self.private_dir = None - + self.ldapdir = None + self.slapdconf = None + self.modulesconf = None + self.memberofconf = None + self.fedoradsinf = None + self.fedoradspartitions = None + +class ProvisionNames: + def __init__(self): + self.rootdn = None + self.domaindn = None + self.configdn = None + self.schemadn = None + self.ldapmanagerdn = None + self.dnsdomain = None + self.realm = None + self.netbiosname = None + self.domain = None + self.hostname = None + self.sitename = None + class ProvisionResult: def __init__(self): self.paths = None @@ -217,9 +236,20 @@ def provision_paths_from_lp(lp, dnsdomain): paths.dns = os.path.join(paths.private_dir, dnsdomain + ".zone") paths.winsdb = os.path.join(paths.private_dir, "wins.ldb") paths.s4_ldapi_path = os.path.join(paths.private_dir, "ldapi") - paths.smbconf = os.path.join(paths.private_dir, "smb.conf") paths.phpldapadminconfig = os.path.join(paths.private_dir, "phpldapadmin-config.php") + paths.ldapdir = os.path.join(paths.private_dir, + "ldap") + paths.slapdconf = os.path.join(paths.ldapdir, + "slapd.conf") + paths.modulesconf = os.path.join(paths.ldapdir, + "modules.conf") + paths.memberofconf = os.path.join(paths.ldapdir, + "memberof.conf") + paths.fedoradsinf = os.path.join(paths.ldapdir, + "fedorads.inf") + paths.fedoradspartitions = os.path.join(paths.ldapdir, + "fedorads-partitions.ldif") paths.hklm = "hklm.ldb" paths.hkcr = "hkcr.ldb" paths.hkcu = "hkcu.ldb" @@ -227,16 +257,145 @@ def provision_paths_from_lp(lp, dnsdomain): paths.hkpd = "hkpd.ldb" paths.hkpt = "hkpt.ldb" - paths.sysvol = lp.get("sysvol", "path") - if paths.sysvol is None: - paths.sysvol = os.path.join(lp.get("lock dir"), "sysvol") + paths.sysvol = lp.get("path", "sysvol") - paths.netlogon = lp.get("netlogon", "path") - if paths.netlogon is None: - paths.netlogon = os.path.join(os.path.join(paths.sysvol, "scripts")) + paths.netlogon = lp.get("path", "netlogon") return paths +def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None, serverrole=None, + rootdn=None, domaindn=None, configdn=None, schemadn=None, sitename=None): + + if hostname is None: + hostname = gethostname().split(".")[0].lower() + + netbiosname = hostname.upper() + if not valid_netbios_name(netbiosname): + raise InvalidNetbiosName(netbiosname) + + hostname = hostname.lower() + + if dnsdomain is None: + dnsdomain = lp.get("realm") + + if serverrole is None: + serverrole = lp.get("server role") + + assert dnsdomain is not None + realm = dnsdomain.upper() + + if lp.get("realm").upper() != realm: + raise Exception("realm '%s' in %s must match chosen realm '%s'" % + (lp.get("realm"), smbconf, realm)) + + dnsdomain = dnsdomain.lower() + + if (serverrole == "domain controller"): + if domain is None: + domain = lp.get("workgroup") + if domaindn is None: + domaindn = "DC=" + dnsdomain.replace(".", ",DC=") + if lp.get("workgroup").upper() != domain.upper(): + raise Error("workgroup '%s' in smb.conf must match chosen domain '%s'", + lp.get("workgroup"), domain) + else: + domain = netbiosname + if domaindn is None: + domaindn = "CN=" + netbiosname + + assert domain is not None + domain = domain.upper() + if not valid_netbios_name(domain): + raise InvalidNetbiosName(domain) + + if rootdn is None: + rootdn = domaindn + + if configdn is None: + configdn = "CN=Configuration," + rootdn + if schemadn is None: + schemadn = "CN=Schema," + configdn + + if sitename is None: + sitename=DEFAULTSITE + + names = ProvisionNames() + names.rootdn = rootdn + names.domaindn = domaindn + names.configdn = configdn + names.schemadn = schemadn + names.ldapmanagerdn = "CN=Manager," + rootdn + names.dnsdomain = dnsdomain + names.domain = domain + names.realm = realm + names.netbiosname = netbiosname + names.hostname = hostname + names.sitename = sitename + + return names + + +def load_or_make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, targetdir): + if targetdir is not None: + if not os.path.exists(targetdir): + os.mkdir(targetdir) + if not os.path.exists(os.path.join(targetdir, "etc")): + os.mkdir(os.path.join(targetdir, "etc")) + + smbconf = os.path.join(targetdir, "etc", "smb.conf") + + # only install a new smb.conf if there isn't one there already + + if not os.path.exists(smbconf): + if hostname is None: + hostname = gethostname().split(".")[0].lower() + + if serverrole is None: + serverrole = "standalone" + + assert serverrole in ("domain controller", "member server", "standalone") + if serverrole == "domain controller": + smbconfsuffix = "dc" + elif serverrole == "member server": + smbconfsuffix = "member" + elif serverrole == "standalone": + smbconfsuffix = "standalone" + + assert domain is not None + assert realm is not None + + default_lp = param.LoadParm() + #Load non-existant file + default_lp.load(smbconf) + + if targetdir is not None: + privatedir_line = "private dir = " + os.path.abspath(os.path.join(targetdir, "private")) + lockdir_line = "lock dir = " + os.path.abspath(targetdir) + + default_lp.set("lock dir", os.path.abspath(targetdir)) + else: + privatedir_line = "private_dir = " + default_lp.get("private dir") + lockdir_line = "lock dir = " + default_lp.get("lock dir") + + sysvol = os.path.join(default_lp.get("lock dir"), "sysvol") + netlogon = os.path.join(sysvol, realm.lower(), "scripts") + + setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix), + smbconf, { + "HOSTNAME": hostname, + "DOMAIN": domain, + "REALM": realm, + "SERVERROLE": serverrole, + "NETLOGONPATH": netlogon, + "SYSVOLPATH": sysvol, + "PRIVATEDIR_LINE": privatedir_line, + "LOCKDIR_LINE": lockdir_line + }) + + lp = param.LoadParm() + lp.load(smbconf) + + return lp def setup_name_mappings(ldb, sid, domaindn, root, nobody, nogroup, users, wheel, backup): @@ -279,9 +438,8 @@ def setup_name_mappings(ldb, sid, domaindn, root, nobody, nogroup, users, def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, - credentials, configdn, schemadn, domaindn, - hostname, netbiosname, dnsdomain, realm, - rootdn, serverrole, sitename, ldap_backend=None, + credentials, names, + serverrole, ldap_backend=None, ldap_backend_type=None, erase=False): """Setup the partitions for the SAM database. @@ -368,12 +526,12 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, samdb.transaction_start() try: setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), { - "SCHEMADN": schemadn, + "SCHEMADN": names.schemadn, "SCHEMADN_LDB": schemadn_ldb, "SCHEMADN_MOD2": ",objectguid", - "CONFIGDN": configdn, + "CONFIGDN": names.configdn, "CONFIGDN_LDB": configdn_ldb, - "DOMAINDN": domaindn, + "DOMAINDN": names.domaindn, "DOMAINDN_LDB": domaindn_ldb, "SCHEMADN_MOD": "schema_fsmo,instancetype", "CONFIGDN_MOD": "naming_fsmo,instancetype", @@ -399,9 +557,9 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, samdb.load_ldif_file_add(setup_path("provision_init.ldif")) message("Setting up sam.ldb rootDSE") - setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, hostname, - dnsdomain, realm, rootdn, configdn, netbiosname, - sitename) + setup_samdb_rootdse(samdb, setup_path, names.schemadn, names.domaindn, names.hostname, + names.dnsdomain, names.realm, names.rootdn, names.configdn, names.netbiosname, + names.sitename) if erase: message("Erasing data from partitions") @@ -534,10 +692,10 @@ def setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, hostname, }) -def setup_self_join(samdb, configdn, schemadn, domaindn, - netbiosname, hostname, dnsdomain, machinepass, dnspass, - realm, domainname, domainsid, invocationid, setup_path, - policyguid, sitename, hostguid=None): +def setup_self_join(samdb, names, + machinepass, dnspass, + domainsid, invocationid, setup_path, + policyguid, hostguid=None): """Join a host to its own domain.""" if hostguid is not None: hostguid_add = "objectGUID: %s" % hostguid @@ -545,33 +703,32 @@ def setup_self_join(samdb, configdn, schemadn, domaindn, hostguid_add = "" setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), { - "CONFIGDN": configdn, - "SCHEMADN": schemadn, - "DOMAINDN": domaindn, + "CONFIGDN": names.configdn, + "SCHEMADN": names.schemadn, + "DOMAINDN": names.domaindn, "INVOCATIONID": invocationid, - "NETBIOSNAME": netbiosname, - "DEFAULTSITE": sitename, - "DNSNAME": "%s.%s" % (hostname, dnsdomain), + "NETBIOSNAME": names.netbiosname, + "DEFAULTSITE": names.sitename, + "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain), "MACHINEPASS_B64": b64encode(machinepass), "DNSPASS_B64": b64encode(dnspass), - "REALM": realm, - "DOMAIN": domainname, + "REALM": names.realm, + "DOMAIN": names.domain, "HOSTGUID_ADD": hostguid_add, - "DNSDOMAIN": dnsdomain}) + "DNSDOMAIN": names.dnsdomain}) setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), { "POLICYGUID": policyguid, - "DNSDOMAIN": dnsdomain, + "DNSDOMAIN": names.dnsdomain, "DOMAINSID": str(domainsid), - "DOMAINDN": domaindn}) + "DOMAINDN": names.domaindn}) def setup_samdb(path, setup_path, session_info, credentials, lp, - schemadn, configdn, domaindn, dnsdomain, realm, - netbiosname, message, hostname, rootdn, + names, message, domainsid, aci, domainguid, policyguid, - domainname, fill, adminpass, krbtgtpass, + fill, adminpass, krbtgtpass, machinepass, hostguid, invocationid, dnspass, - serverrole, sitename, ldap_backend=None, + serverrole, ldap_backend=None, ldap_backend_type=None): """Setup a complete SAM Database. @@ -581,14 +738,11 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, erase = (fill != FILL_DRS) # Also wipes the database - setup_samdb_partitions(path, setup_path, schemadn=schemadn, configdn=configdn, - domaindn=domaindn, message=message, lp=lp, + setup_samdb_partitions(path, setup_path, message=message, lp=lp, credentials=credentials, session_info=session_info, - hostname=hostname, netbiosname=netbiosname, - dnsdomain=dnsdomain, realm=realm, rootdn=rootdn, + names=names, ldap_backend=ldap_backend, serverrole=serverrole, - ldap_backend_type=ldap_backend_type, erase=erase, - sitename=sitename) + ldap_backend_type=ldap_backend_type, erase=erase) samdb = SamDB(path, session_info=session_info, credentials=credentials, lp=lp) @@ -606,18 +760,24 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, if serverrole == "domain controller": samdb.set_invocation_id(invocationid) - load_schema(setup_path, samdb, schemadn, netbiosname, configdn, sitename) + load_schema(setup_path, samdb, names.schemadn, names.netbiosname, names.configdn, names.sitename) samdb.transaction_start() try: - message("Adding DomainDN: %s (permitted to fail)" % domaindn) + message("Adding DomainDN: %s (permitted to fail)" % names.domaindn) + if serverrole == "domain controller": + domain_oc = "domainDNS" + else: + domain_oc = "samba4LocalDomain" + setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), { - "DOMAINDN": domaindn, + "DOMAINDN": names.domaindn, "ACI": aci, + "DOMAIN_OC": domain_oc }) - message("Modifying DomainDN: " + domaindn + "") + message("Modifying DomainDN: " + names.domaindn + "") if domainguid is not None: domainguid_mod = "replace: objectGUID\nobjectGUID: %s\n-" % domainguid else: @@ -626,104 +786,102 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, setup_modify_ldif(samdb, setup_path("provision_basedn_modify.ldif"), { "LDAPTIME": timestring(int(time.time())), "DOMAINSID": str(domainsid), - "SCHEMADN": schemadn, - "NETBIOSNAME": netbiosname, - "DEFAULTSITE": sitename, - "CONFIGDN": configdn, + "SCHEMADN": names.schemadn, + "NETBIOSNAME": names.netbiosname, + "DEFAULTSITE": names.sitename, + "CONFIGDN": names.configdn, "POLICYGUID": policyguid, - "DOMAINDN": domaindn, + "DOMAINDN": names.domaindn, "DOMAINGUID_MOD": domainguid_mod, }) message("Adding configuration container (permitted to fail)") setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), { - "CONFIGDN": configdn, + "CONFIGDN": names.configdn, "ACI": aci, "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb", }) message("Modifying configuration container") setup_modify_ldif(samdb, setup_path("provision_configuration_basedn_modify.ldif"), { - "CONFIGDN": configdn, - "SCHEMADN": schemadn, + "CONFIGDN": names.configdn, + "SCHEMADN": names.schemadn, }) message("Adding schema container (permitted to fail)") setup_add_ldif(samdb, setup_path("provision_schema_basedn.ldif"), { - "SCHEMADN": schemadn, + "SCHEMADN": names.schemadn, "ACI": aci, "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb" }) message("Modifying schema container") setup_modify_ldif(samdb, setup_path("provision_schema_basedn_modify.ldif"), { - "SCHEMADN": schemadn, - "NETBIOSNAME": netbiosname, - "DEFAULTSITE": sitename, - "CONFIGDN": configdn, + "SCHEMADN": names.schemadn, + "NETBIOSNAME": names.netbiosname, + "DEFAULTSITE": names.sitename, + "CONFIGDN": names.configdn, }) message("Setting up sam.ldb Samba4 schema") setup_add_ldif(samdb, setup_path("schema_samba4.ldif"), - {"SCHEMADN": schemadn }) + {"SCHEMADN": names.schemadn }) message("Setting up sam.ldb AD schema") setup_add_ldif(samdb, setup_path("schema.ldif"), - {"SCHEMADN": schemadn}) + {"SCHEMADN": names.schemadn}) message("Setting up sam.ldb configuration data") setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), { - "CONFIGDN": configdn, - "NETBIOSNAME": netbiosname, - "DEFAULTSITE": sitename, - "DNSDOMAIN": dnsdomain, - "DOMAIN": domainname, - "SCHEMADN": schemadn, - "DOMAINDN": domaindn, + "CONFIGDN": names.configdn, + "NETBIOSNAME": names.netbiosname, + "DEFAULTSITE": names.sitename, + "DNSDOMAIN": names.dnsdomain, + "DOMAIN": names.domain, + "SCHEMADN": names.schemadn, + "DOMAINDN": names.domaindn, }) message("Setting up display specifiers") setup_add_ldif(samdb, setup_path("display_specifiers.ldif"), - {"CONFIGDN": configdn}) + {"CONFIGDN": names.configdn}) message("Adding users container (permitted to fail)") setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), { - "DOMAINDN": domaindn}) + "DOMAINDN": names.domaindn}) message("Modifying users container") setup_modify_ldif(samdb, setup_path("provision_users_modify.ldif"), { - "DOMAINDN": domaindn}) + "DOMAINDN": names.domaindn}) message("Adding computers container (permitted to fail)") setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), { - "DOMAINDN": domaindn}) + "DOMAINDN": names.domaindn}) message("Modifying computers container") setup_modify_ldif(samdb, setup_path("provision_computers_modify.ldif"), { - "DOMAINDN": domaindn}) + "DOMAINDN": names.domaindn}) message("Setting up sam.ldb data") setup_add_ldif(samdb, setup_path("provision.ldif"), { - "DOMAINDN": domaindn, - "NETBIOSNAME": netbiosname, - "DEFAULTSITE": sitename, - "CONFIGDN": configdn, + "DOMAINDN": names.domaindn, + "NETBIOSNAME": names.netbiosname, + "DEFAULTSITE": names.sitename, + "CONFIGDN": names.configdn, }) if fill == FILL_FULL: message("Setting up sam.ldb users and groups") setup_add_ldif(samdb, setup_path("provision_users.ldif"), { - "DOMAINDN": domaindn, + "DOMAINDN": names.domaindn, "DOMAINSID": str(domainsid), - "CONFIGDN": configdn, + "CONFIGDN": names.configdn, "ADMINPASS_B64": b64encode(adminpass), "KRBTGTPASS_B64": b64encode(krbtgtpass), }) if serverrole == "domain controller": message("Setting up self join") - setup_self_join(samdb, configdn=configdn, schemadn=schemadn, - domaindn=domaindn, invocationid=invocationid, - dnspass=dnspass, netbiosname=netbiosname, - dnsdomain=dnsdomain, realm=realm, - machinepass=machinepass, domainname=domainname, + setup_self_join(samdb, names=names, invocationid=invocationid, + dnspass=dnspass, + machinepass=machinepass, domainsid=domainsid, policyguid=policyguid, - hostname=hostname, hostguid=hostguid, - setup_path=setup_path, sitename=sitename) + hostguid=hostguid, + setup_path=setup_path) #We want to setup the index last, as adds are faster unindexed message("Setting up sam.ldb index") @@ -748,7 +906,7 @@ def provision(setup_dir, message, session_info, policyguid=None, invocationid=None, machinepass=None, dnspass=None, root=None, nobody=None, nogroup=None, users=None, wheel=None, backup=None, aci=None, serverrole=None, - ldap_backend=None, ldap_backend_type=None, sitename=DEFAULTSITE): + ldap_backend=None, ldap_backend_type=None, sitename=None): """Provision samba4 :note: caution, this wipes all existing data! @@ -759,6 +917,9 @@ def provision(setup_dir, message, session_info, if domainsid is None: domainsid = security.random_sid() + else: + domainsid = security.Sid(domainsid) + if policyguid is None: policyguid = uuid.random() if adminpass is None: @@ -784,129 +945,37 @@ def provision(setup_dir, message, session_info, backup = findnss(grp.getgrnam, ["backup", "wheel", "root", "staff"])[0] if aci is None: aci = "# no aci for local ldb" - if hostname is None: - hostname = gethostname().split(".")[0].lower() - - if hostip is None: - hostip = gethostbyname(hostname) - - netbiosname = hostname.upper() - if not valid_netbios_name(netbiosname): - raise InvalidNetbiosName(netbiosname) - if targetdir is not None: - if not os.path.exists(targetdir): - os.mkdir(targetdir) - if not os.path.exists(os.path.join(targetdir, "etc")): - os.mkdir(os.path.join(targetdir, "etc")) - - smbconf = os.path.join(targetdir, os.path.join("etc", "smb.conf")) - - # only install a new smb.conf if there isn't one there already - - if not os.path.exists(smbconf): - message("Setting up smb.conf") - if serverrole is None: - serverrole = "standalone" - - assert serverrole in ("domain controller", "member server", "standalone") - if serverrole == "domain controller": - smbconfsuffix = "dc" - elif serverrole == "member server": - smbconfsuffix = "member" - elif serverrole == "standalone": - smbconfsuffix = "standalone" + lp = load_or_make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, targetdir) - assert domain is not None - assert realm is not None + names = guess_names(lp=lp, hostname=hostname, domain=domain, + dnsdomain=realm, serverrole=serverrole, sitename=sitename, + rootdn=rootdn, domaindn=domaindn, configdn=configdn, schemadn=schemadn) - default_lp = param.LoadParm() - #Load non-existant file - default_lp.load(smbconf) - - if targetdir is not None: - privatedir_line = "private dir = " + os.path.abspath(os.path.join(targetdir, "private")) - lockdir_line = "lock dir = " + os.path.abspath(targetdir) + paths = provision_paths_from_lp(lp, names.dnsdomain) - default_lp.set("lock dir", os.path.abspath(targetdir)) - - sysvol = os.path.join(default_lp.get("lock dir"), "sysvol") - netlogon = os.path.join(os.path.join(sysvol, "scripts")) - - setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix), - smbconf, { - "HOSTNAME": hostname, - "DOMAIN": domain, - "REALM": realm, - "SERVERROLE": serverrole, - "NETLOGONPATH": netlogon, - "SYSVOLPATH": sysvol, - "PRIVATEDIR_LINE": privatedir_line, - "LOCKDIR_LINE": lockdir_line - }) - - lp = param.LoadParm() - lp.load(smbconf) + if hostip is None: + hostip = gethostbyname(names.hostname) if serverrole is None: serverrole = lp.get("server role") + assert serverrole in ("domain controller", "member server", "standalone") if invocationid is None and serverrole == "domain controller": invocationid = uuid.random() - if realm is None: - realm = lp.get("realm") - - assert realm is not None - realm = realm.upper() - - if lp.get("realm").upper() != realm.upper(): - raise Exception("realm '%s' in %s must match chosen realm '%s'" % - (lp.get("realm"), smbconf, realm)) - - dnsdomain = realm.lower() - - paths = provision_paths_from_lp(lp, dnsdomain) - - if targetdir is not None: - if not os.path.exists(paths.private_dir): - os.mkdir(paths.private_dir) + if not os.path.exists(paths.private_dir): + os.mkdir(paths.private_dir) ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="") - if ldap_backend == "ldapi": - # provision-backend will set this path suggested slapd command line / fedorads.inf - ldap_backend = "ldapi://" % urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="") - - if serverrole == "domain controller": - if domaindn is None: - domaindn = "DC=" + dnsdomain.replace(".", ",DC=") - if domain is None: - domain = lp.get("workgroup") - - if lp.get("workgroup").upper() != domain.upper(): - raise Error("workgroup '%s' in smb.conf must match chosen domain '%s'", - lp.get("workgroup"), domain) - - assert domain is not None - domain = domain.upper() - if not valid_netbios_name(domain): - raise InvalidNetbiosName(domain) - else: - if domaindn is None: - domaindn = "CN=" + netbiosname - domain = netbiosname - - if rootdn is None: - rootdn = domaindn - - if configdn is None: - configdn = "CN=Configuration," + rootdn - if schemadn is None: - schemadn = "CN=Schema," + configdn - + if ldap_backend is not None: + if ldap_backend == "ldapi": + # provision-backend will set this path suggested slapd command line / fedorads.inf + ldap_backend = "ldapi://" % urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="") + message("set DOMAIN SID: %s" % str(domainsid)) - message("Provisioning for %s in realm %s" % (domain, realm)) + message("Provisioning for %s in realm %s" % (names.domain, realm)) message("Using administrator password: %s" % adminpass) # only install a new shares config db if there is none @@ -935,21 +1004,19 @@ def provision(setup_dir, message, session_info, credentials=credentials, lp=lp) samdb = setup_samdb(paths.samdb, setup_path, session_info=session_info, - credentials=credentials, lp=lp, schemadn=schemadn, - configdn=configdn, domaindn=domaindn, - dnsdomain=dnsdomain, netbiosname=netbiosname, - realm=realm, message=message, hostname=hostname, - rootdn=rootdn, domainsid=domainsid, + credentials=credentials, lp=lp, names=names, + message=message, + domainsid=domainsid, aci=aci, domainguid=domainguid, policyguid=policyguid, - domainname=domain, fill=samdb_fill, + fill=samdb_fill, adminpass=adminpass, krbtgtpass=krbtgtpass, hostguid=hostguid, invocationid=invocationid, machinepass=machinepass, dnspass=dnspass, serverrole=serverrole, ldap_backend=ldap_backend, - ldap_backend_type=ldap_backend_type, sitename=sitename) + ldap_backend_type=ldap_backend_type) if lp.get("server role") == "domain controller": - policy_path = os.path.join(paths.sysvol, dnsdomain, "Policies", + policy_path = os.path.join(paths.sysvol, names.dnsdomain, "Policies", "{" + policyguid + "}") os.makedirs(policy_path, 0755) os.makedirs(os.path.join(policy_path, "Machine"), 0755) @@ -958,14 +1025,14 @@ def provision(setup_dir, message, session_info, os.makedirs(paths.netlogon, 0755) secrets_ldb = Ldb(paths.secrets, session_info=session_info, credentials=credentials, lp=lp) - secretsdb_become_dc(secrets_ldb, setup_path, domain=domain, realm=realm, - netbiosname=netbiosname, domainsid=domainsid, + secretsdb_become_dc(secrets_ldb, setup_path, domain=domain, realm=names.realm, + netbiosname=names.netbiosname, domainsid=domainsid, keytab_path=paths.keytab, samdb_url=paths.samdb, dns_keytab_path=paths.dns_keytab, dnspass=dnspass, - machinepass=machinepass, dnsdomain=dnsdomain) + machinepass=machinepass, dnsdomain=names.dnsdomain) if samdb_fill == FILL_FULL: - setup_name_mappings(samdb, str(domainsid), domaindn, root=root, + setup_name_mappings(samdb, str(domainsid), names.domaindn, root=root, nobody=nobody, nogroup=nogroup, wheel=wheel, users=users, backup=backup) @@ -980,14 +1047,14 @@ def provision(setup_dir, message, session_info, domainguid = samdb.searchone(basedn=domaindn, attribute="objectGUID") assert isinstance(domainguid, str) hostguid = samdb.searchone(basedn=domaindn, attribute="objectGUID", - expression="(&(objectClass=computer)(cn=%s))" % hostname, + expression="(&(objectClass=computer)(cn=%s))" % names.hostname, scope=SCOPE_SUBTREE) assert isinstance(hostguid, str) - message("Setting up DNS zone: %s" % dnsdomain) + message("Setting up DNS zone: %s" % names.dnsdomain) create_zone_file(paths.dns, setup_path, samdb, - hostname=hostname, hostip=hostip, dnsdomain=dnsdomain, - domaindn=domaindn, dnspass=dnspass, realm=realm, + hostname=names.hostname, hostip=hostip, dnsdomain=names.dnsdomain, + domaindn=names.domaindn, dnspass=dnspass, realm=names.realm, domainguid=domainguid, hostguid=hostguid) message("Please install the zone located in %s into your DNS server" % paths.dns) @@ -1024,6 +1091,149 @@ def provision_become_dc(setup_dir=None, domain=domain, hostname=hostname, hostip="127.0.0.1", domainsid=domainsid, machinepass=machinepass, serverrole="domain controller", sitename=sitename); +def setup_db_config(setup_path, file, dbdir): + if not os.path.isdir(os.path.join(dbdir, "bdb-logs")): + os.makedirs(os.path.join(dbdir, "bdb-logs"), 0700); + if not os.path.isdir(os.path.join(dbdir, "tmp")): + os.makedirs(os.path.join(dbdir, "tmp"), 0700); + + setup_file(setup_path("DB_CONFIG"), os.path.join(dbdir, "DB_CONFIG"), + {"LDAPDBDIR": dbdir}) + + + +def provision_backend(setup_dir=None, message=None, + smbconf=None, targetdir=None, realm=None, + rootdn=None, domaindn=None, schemadn=None, configdn=None, + domain=None, hostname=None, adminpass=None, root=None, serverrole=None, + ldap_backend_type=None): + + def setup_path(file): + return os.path.join(setup_dir, file) + + if hostname is None: + hostname = gethostname().split(".")[0].lower() + + if root is None: + root = findnss(pwd.getpwnam, ["root"])[0] + + lp = load_or_make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, targetdir) + + names = guess_names(lp=lp, hostname=hostname, domain=domain, + dnsdomain=realm, serverrole=serverrole, + rootdn=rootdn, domaindn=domaindn, configdn=configdn, schemadn=schemadn) + + paths = provision_paths_from_lp(lp, names.dnsdomain) + + if not os.path.isdir(paths.ldapdir): + os.makedirs(paths.ldapdir) + schemadb_path = os.path.join(paths.ldapdir, "schema-tmp.ldb") + try: + os.unlink(schemadb_path) + except: + pass + + schemadb = Ldb(schemadb_path, lp=lp) + + setup_add_ldif(schemadb, setup_path("provision_schema_basedn.ldif"), + {"SCHEMADN": names.schemadn, + "ACI": "#", + "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb" + }) + setup_modify_ldif(schemadb, + setup_path("provision_schema_basedn_modify.ldif"), \ + {"SCHEMADN": names.schemadn, + "NETBIOSNAME": names.netbiosname, + "DEFAULTSITE": DEFAULTSITE, + "CONFIGDN": names.configdn, + }) + + setup_add_ldif(schemadb, setup_path("schema_samba4.ldif"), + {"SCHEMADN": names.schemadn }) + setup_add_ldif(schemadb, setup_path("schema.ldif"), + {"SCHEMADN": names.schemadn}) + + if ldap_backend_type == "fedora-ds": + setup_file(setup_path("fedora-ds.inf"), paths.fedoradsinf, + {"ROOT": root, + "HOSTNAME": hostname, + "DNSDOMAIN": names.dnsdomain, + "LDAPDIR": paths.ldapdir, + "DOMAINDN": names.domaindn, + "LDAPMANAGERDN": names.ldapmanagerdn, + "LDAPMANAGERPASS": adminpass, + "SERVERPORT": ""}) + + setup_file(setup_path("fedora-partitions.ldif"), paths.fedoradspartitions, + {"CONFIGDN": names.configdn, + "SCHEMADN": names.schemadn, + }) + + setup_file(setup_path("fedora-partitions.ldif"), paths.fedoradspartitions, + {"CONFIGDN": names.configdn, + "SCHEMADN": names.schemadn, + }) + mapping = "schema-map-fedora-ds-1.0" + backend_schema = "99_ad.ldif" + elif ldap_backend_type == "openldap": + attrs = ["linkID", "lDAPDisplayName"] + res = schemadb.search(expression="(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", base=names.schemadn, scope=SCOPE_SUBTREE, attrs=attrs); + + memberof_config = "# Generated from schema in " + schemadb_path + "\n"; + refint_attributes = ""; + for i in range (0, len(res)): + linkid = res[i]["linkID"][0] + linkid = str(int(linkid) + 1) + expression = "(&(objectclass=attributeSchema)(linkID=" + (linkid) + "))" + target = schemadb.searchone(basedn=names.schemadn, + expression=expression, + attribute="lDAPDisplayName", + scope=SCOPE_SUBTREE); + if target is not None: + refint_attributes = refint_attributes + " " + target + " " + res[i]["lDAPDisplayName"][0]; + memberof_config = memberof_config + """overlay memberof +memberof-dangling error +memberof-refint TRUE +memberof-group-oc top +memberof-member-ad """ + res[i]["lDAPDisplayName"][0] + """ +memberof-memberof-ad """ + target + """ +memberof-dangling-error 32 + +"""; + + memberof_config = memberof_config + """ +overlay refint +refint_attributes""" + refint_attributes + "\n"; + + setup_file(setup_path("slapd.conf"), paths.slapdconf, + {"DNSDOMAIN": names.dnsdomain, + "LDAPDIR": paths.ldapdir, + "DOMAINDN": names.domaindn, + "CONFIGDN": names.configdn, + "SCHEMADN": names.schemadn, + "LDAPMANAGERDN": names.ldapmanagerdn, + "LDAPMANAGERPASS": adminpass, + "MEMBEROF_CONFIG": memberof_config}) + setup_file(setup_path("modules.conf"), paths.modulesconf, + {"REALM": names.realm}) + + setup_db_config(setup_path, file, os.path.join(paths.ldapdir, "db", "user")) + setup_db_config(setup_path, file, os.path.join(paths.ldapdir, "db", "config")) + setup_db_config(setup_path, file, os.path.join(paths.ldapdir, "db", "schema")) + mapping = "schema-map-openldap-2.3" + backend_schema = "backend-schema.schema" + + + ldapi_uri = "ldapi://" + urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="") + message("Start slapd with: slapd -f " + paths.ldapdir + "/slapd.conf -h " + ldapi_uri) + + + schema_command = "bin/ad2oLschema --option=convert:target=" + ldap_backend_type + " -I " + setup_path(mapping) + " -H tdb://" + schemadb_path + " -O " + os.path.join(paths.ldapdir, backend_schema); + + os.system(schema_command) + + + def create_phpldapadmin_config(path, setup_path, ldapi_uri): """Create a PHP LDAP admin configuration file. diff --git a/source4/scripting/python/uuidmodule.c b/source4/scripting/python/uuidmodule.c index e05b286dd01..cd9a1cb4d52 100644 --- a/source4/scripting/python/uuidmodule.c +++ b/source4/scripting/python/uuidmodule.c @@ -24,6 +24,7 @@ static PyObject *uuid_random(PyObject *self, PyObject *args) { struct GUID guid; + PyObject *pyobj; char *str; if (!PyArg_ParseTuple(args, (char *)"")) @@ -37,9 +38,11 @@ static PyObject *uuid_random(PyObject *self, PyObject *args) return NULL; } + pyobj = PyString_FromString(str); + talloc_free(str); - return PyString_FromString(str); + return pyobj; } static PyMethodDef methods[] = { diff --git a/source4/selftest/output/plain.pm b/source4/selftest/output/plain.pm index e491a999ab1..25ff74792e5 100644 --- a/source4/selftest/output/plain.pm +++ b/source4/selftest/output/plain.pm @@ -7,8 +7,6 @@ use Exporter; use FindBin qw($RealBin); use lib "$RealBin/.."; -use Subunit qw(parse_results); - use strict; sub new($$$$$$$) { @@ -62,7 +60,9 @@ sub output_msg($$) my ($self, $output) = @_; if ($self->{verbose}) { + require FileHandle; print $output; + STDOUT->flush(); } else { $self->{test_output}->{$self->{NAME}} .= $output; } diff --git a/source4/selftest/selftest.pl b/source4/selftest/selftest.pl index 73d03f3d4ca..39a1b5a4508 100755 --- a/source4/selftest/selftest.pl +++ b/source4/selftest/selftest.pl @@ -584,7 +584,7 @@ push (@torture_options, "--configfile=$conffile"); push (@torture_options, "--maximum-runtime=$torture_maxtime"); push (@torture_options, "--target=$opt_target"); push (@torture_options, "--basedir=$prefix_abs"); -push (@torture_options, "--option=torture:progress=no") if ($opt_format eq "buildfarm"); +push (@torture_options, "--option=torture:progress=no") unless ($opt_verbose); push (@torture_options, "--format=subunit"); push (@torture_options, "--option=torture:quick=yes") if ($opt_quick); diff --git a/source4/selftest/target/Samba4.pm b/source4/selftest/target/Samba4.pm index 48fda175993..262c8035f63 100644 --- a/source4/selftest/target/Samba4.pm +++ b/source4/selftest/target/Samba4.pm @@ -544,7 +544,7 @@ sub provision($$$$$$) my $localbasedn = $basedn; - $localbasedn = "DC=$netbiosname" if $server_role eq "member server"; + $localbasedn = "CN=$netbiosname" if $server_role eq "member server"; open(CONFFILE, ">$conffile"); print CONFFILE " @@ -577,9 +577,6 @@ sub provision($$$$$$) gensec:require_pac = true log level = $smbd_loglevel - # this is a global option - opendb:oplocks = yes - [tmp] path = $tmpdir read only = no @@ -617,6 +614,14 @@ sub provision($$$$$$) read only = no ntvfs handler = simple +[sysvol] + path = $lockdir/sysvol + read only = yes + +[netlogon] + path = $lockdir/sysvol/$dnsname/scripts + read only = no + [cifsposix] copy = simple ntvfs handler = cifsposix @@ -746,7 +751,7 @@ nogroup:x:65534:nobody if (defined($self->{ldap})) { push (@provision_options, "--ldap-backend=$ldap_uri"); - system("$self->{bindir}/smbscript $self->{setupdir}/provision-backend $configuration --ldap-manager-pass=$password --root=$unix_name --realm=$realm --host-name=$netbiosname --ldap-backend-type=$self->{ldap}>&2") == 0 or die("backend provision failed"); + system("$self->{bindir}/smbpython $self->{setupdir}/provision-backend $configuration --ldap-manager-pass=$password --root=$unix_name --realm=$realm --domain=$domain --host-name=$netbiosname --ldap-backend-type=$self->{ldap}>&2") == 0 or die("backend provision failed"); if ($self->{ldap} eq "openldap") { ($ret->{SLAPD_CONF}, $ret->{OPENLDAP_PIDFILE}) = $self->mk_openldap($ldapdir, $configuration) or die("Unable to create openldap directories"); diff --git a/source4/setup/newuser b/source4/setup/newuser index 7c80e9e8de0..03ae4e5ffb6 100755 --- a/source4/setup/newuser +++ b/source4/setup/newuser @@ -1,80 +1,61 @@ -#!/bin/sh -exec smbscript "$0" ${1+"$@"} -/* - add a new user to a Samba4 server - Copyright Andrew Tridgell 2005 - Released under the GNU GPL v2 or later -*/ - -options = GetOptions(ARGV, - "POPT_AUTOHELP", - 'username=s', - 'unixname=s', - 'password=s', - "POPT_COMMON_SAMBA", - "POPT_COMMON_VERSION", - "POPT_COMMON_CREDENTIALS", - 'quiet'); - -if (options == undefined) { - println("Failed to parse options"); - return -1; -} - -libinclude("base.js"); -libinclude("provision.js"); - -/* - print a message if quiet is not set -*/ -function message() -{ - if (options["quiet"] == undefined) { - print(vsprintf(arguments)); - } -} - -/* - show some help -*/ -function ShowHelp() -{ - print(" -Samba4 newuser - -newuser [options] - --username USERNAME choose new username - --unixname USERNAME choose unix name of new user - --password PASSWORD set password - -You must provide at least a username -"); - exit(1); -} - -if (options['username'] == undefined) { - ShowHelp(); -} - -if (options['password'] == undefined) { - random_init(local); - options.password = randpass(12); - printf("chose random password %s\n", options.password); -} -if (options['unixname'] == undefined) { - options.unixname = options.username; -} - -var nss = nss_init(); -if (nss.getpwnam(options.unixname) == undefined) { - printf("ERROR: Unix user '%s' does not exist\n", options.unixname); - exit(1); -} - -var creds = options.get_credentials(); -var system_session = system_session(); - - -newuser(options.username, options.unixname, options.password, message, system_session, creds); - -return 0; +#!/usr/bin/python +# +# add a new user to a Samba4 server +# Copyright Andrew Tridgell 2005 +# Copyright Jelmer Vernooij 2008 +# Released under the GNU GPL v2 or later +# + +import samba.getopt as options +import optparse +import pwd +import sys + +from auth import system_session +from samba.samdb import SamDB + +parser = optparse.OptionParser("newuser [options] <username> [<password>]") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +parser.add_option_group(options.VersionOptions(parser)) +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +parser.add_option("--quiet", help="Be quiet", action="store_true") +parser.add_option("--unixname", help="Unix Username", type=str) + +opts, args = parser.parse_args() + +# +# print a message if quiet is not set +# +def message(text): + if not opts.quiet: + print text + +if len(args) == 0: + parser.print_usage() + sys.exit(1) + +username = args[0] +if len(args) > 1: + password = args[1] +else: + random_init(local) + options.password = randpass(12) + print "chose random password %s\n" % password + +if opts.unixname is None: + opts.unixname = username + +try: + pwd.getpwnam(opts.unixname) +except KeyError: + print "ERROR: Unix user '%s' does not exist" % opts.unixname + sys.exit(1) + +creds = credopts.get_credentials() + +lp = sambaopts.get_loadparm() +samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), + credentials=creds, lp=lp) +samdb.newuser(username, opts.unixname, password) diff --git a/source4/setup/newuser.py b/source4/setup/newuser.py deleted file mode 100755 index 03ae4e5ffb6..00000000000 --- a/source4/setup/newuser.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/python -# -# add a new user to a Samba4 server -# Copyright Andrew Tridgell 2005 -# Copyright Jelmer Vernooij 2008 -# Released under the GNU GPL v2 or later -# - -import samba.getopt as options -import optparse -import pwd -import sys - -from auth import system_session -from samba.samdb import SamDB - -parser = optparse.OptionParser("newuser [options] <username> [<password>]") -sambaopts = options.SambaOptions(parser) -parser.add_option_group(sambaopts) -parser.add_option_group(options.VersionOptions(parser)) -credopts = options.CredentialsOptions(parser) -parser.add_option_group(credopts) -parser.add_option("--quiet", help="Be quiet", action="store_true") -parser.add_option("--unixname", help="Unix Username", type=str) - -opts, args = parser.parse_args() - -# -# print a message if quiet is not set -# -def message(text): - if not opts.quiet: - print text - -if len(args) == 0: - parser.print_usage() - sys.exit(1) - -username = args[0] -if len(args) > 1: - password = args[1] -else: - random_init(local) - options.password = randpass(12) - print "chose random password %s\n" % password - -if opts.unixname is None: - opts.unixname = username - -try: - pwd.getpwnam(opts.unixname) -except KeyError: - print "ERROR: Unix user '%s' does not exist" % opts.unixname - sys.exit(1) - -creds = credopts.get_credentials() - -lp = sambaopts.get_loadparm() -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) -samdb.newuser(username, opts.unixname, password) diff --git a/source4/setup/provision b/source4/setup/provision index 629bfa10e0f..b0363d8a8f2 100755 --- a/source4/setup/provision +++ b/source4/setup/provision @@ -27,6 +27,7 @@ import optparse import os, sys import samba +import param from auth import system_session import samba.getopt as options @@ -110,7 +111,7 @@ if opts.realm is None or opts.domain is None: parser.print_usage() sys.exit(1) -smbconf = sambaopts.get_loadparm_path() +smbconf = sambaopts.get_loadparm().configfile() if opts.aci is not None: print "set ACI: %s" % opts.aci diff --git a/source4/setup/provision-backend b/source4/setup/provision-backend index abd1b9a875a..ada6dcef8dd 100755 --- a/source4/setup/provision-backend +++ b/source4/setup/provision-backend @@ -1,189 +1,98 @@ -#!/bin/sh -exec smbscript "$0" ${1+"$@"} -/* - provision a Samba4 server - Copyright Andrew Tridgell 2005 - Released under the GNU GPL v2 or later -*/ - -options = GetOptions(ARGV, - "POPT_AUTOHELP", - "POPT_COMMON_SAMBA", - "POPT_COMMON_VERSION", - "POPT_COMMON_CREDENTIALS", - 'realm=s', - 'host-name=s', - 'ldap-manager-pass=s', - 'root=s', - 'quiet', - 'ldap-backend-type=s', - 'ldap-backend-port=i'); - -if (options == undefined) { - println("Failed to parse options"); - return -1; -} - -sys = sys_init(); - -libinclude("base.js"); -libinclude("provision.js"); - -/* - print a message if quiet is not set -*/ -function message() -{ - if (options["quiet"] == undefined) { - print(vsprintf(arguments)); - } -} - -/* - show some help -*/ -function ShowHelp() -{ - print(" -Samba4 provisioning - -provision [options] - --realm REALM set realm - --host-name HOSTNAME set hostname - --ldap-manager-pass PASSWORD choose LDAP Manager password (otherwise random) - --root USERNAME choose 'root' unix username - --quiet Be quiet - --ldap-backend-type LDAPSERVER Select either \"openldap\" or \"fedora-ds\" as a target to configure - --ldap-backend-port PORT Select the TCP port (if any) that the LDAP backend should listen on (Fedora DS only) -You must provide at least a realm and ldap-backend-type - -"); - exit(1); -} - -if (options['host-name'] == undefined) { - options['host-name'] = hostname(); -} - -/* - main program -*/ -if (options["realm"] == undefined || - options["ldap-backend-type"] == undefined || - options["host-name"] == undefined) { - ShowHelp(); -} - -/* cope with an initially blank smb.conf */ -var lp = loadparm_init(); -lp.set("realm", options.realm); -lp.reload(); - -var subobj = provision_guess(); -for (r in options) { - var key = strupper(join("", split("-", r))); - subobj[key] = options[r]; -} - - - -var paths = provision_default_paths(subobj); -provision_fix_subobj(subobj, paths); -message("Provisioning LDAP backend for %s in realm %s into %s\n", subobj.HOSTNAME, subobj.REALM, subobj.LDAPDIR); -message("Using %s password: %s\n", subobj.LDAPMANAGERDN, subobj.LDAPMANAGERPASS); -var tmp_schema_ldb = subobj.LDAPDIR + "/schema-tmp.ldb"; -sys.mkdir(subobj.LDAPDIR, 0700); - -provision_schema(subobj, message, tmp_schema_ldb, paths); - -var mapping; -var backend_schema; -var slapd_command; -if (options["ldap-backend-type"] == "fedora-ds") { - mapping = "schema-map-fedora-ds-1.0"; - backend_schema = "99_ad.ldif"; - if (options["ldap-backend-port"] != undefined) { - message("Will listen on TCP port " + options["ldap-backend-port"] + "\n"); - subobj.SERVERPORT="ServerPort = " + options["ldap-backend-port"]; - } else { - message("Will listen on LDAPI only\n"); - subobj.SERVERPORT=""; - } - setup_file("fedorads.inf", message, subobj.LDAPDIR + "/fedorads.inf", subobj); - setup_file("fedorads-partitions.ldif", message, subobj.LDAPDIR + "/fedorads-partitions.ldif", subobj); - - slapd_command = "(see documentation)"; -} else if (options["ldap-backend-type"] == "openldap") { - mapping = "schema-map-openldap-2.3"; - backend_schema = "backend-schema.schema"; - setup_file("slapd.conf", message, subobj.LDAPDIR + "/slapd.conf", subobj); - setup_file("modules.conf", message, subobj.LDAPDIR + "/modules.conf", subobj); - sys.mkdir(subobj.LDAPDIR + "/db", 0700); - subobj.LDAPDBDIR = subobj.LDAPDIR + "/db/user"; - sys.mkdir(subobj.LDAPDBDIR, 0700); - sys.mkdir(subobj.LDAPDBDIR + "/bdb-logs", 0700); - sys.mkdir(subobj.LDAPDBDIR + "/tmp", 0700); - setup_file("DB_CONFIG", message, subobj.LDAPDBDIR + "/DB_CONFIG", subobj); - subobj.LDAPDBDIR = subobj.LDAPDIR + "/db/config"; - sys.mkdir(subobj.LDAPDBDIR, 0700); - sys.mkdir(subobj.LDAPDBDIR + "/bdb-logs", 0700); - sys.mkdir(subobj.LDAPDBDIR + "/tmp", 0700); - setup_file("DB_CONFIG", message, subobj.LDAPDBDIR + "/DB_CONFIG", subobj); - subobj.LDAPDBDIR = subobj.LDAPDIR + "/db/schema"; - sys.mkdir(subobj.LDAPDBDIR, 0700); - sys.mkdir(subobj.LDAPDBDIR + "/tmp", 0700); - sys.mkdir(subobj.LDAPDBDIR + "/bdb-logs", 0700); - setup_file("DB_CONFIG", message, subobj.LDAPDBDIR + "/DB_CONFIG", subobj); - if (options["ldap-backend-port"] != undefined) { - message("\nStart slapd with: \n"); - slapd_command = "slapd -f " + subobj.LDAPDIR + "/slapd.conf -h \"ldap://0.0.0.0:" + options["ldap-backend-port"] + " " + subobj.LDAPI_URI "\""; - } else { - slapd_command = "slapd -f " + subobj.LDAPDIR + "/slapd.conf -h " + subobj.LDAPI_URI; - } - - var ldb = ldb_init(); - ldb.filename = tmp_schema_ldb; - - var connect_ok = ldb.connect(ldb.filename); - assert(connect_ok); - var attrs = new Array("linkID", "lDAPDisplayName"); - var res = ldb.search("(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", subobj.SCHEMADN, ldb.SCOPE_SUBTREE, attrs); - assert(res.error == 0); - var memberof_config = ""; - var refint_attributes = ""; - for (i=0; i < res.msgs.length; i++) { -searchone(ldb, subobj.DOMAINDN, "(&(objectClass=computer)(cn=" + subobj.NETBIOSNAME + "))", "objectGUID"); - var target = searchone(ldb, subobj.SCHEMADN, "(&(objectclass=attributeSchema)(linkID=" + (res.msgs[i].linkID + 1) + "))", "lDAPDisplayName"); - if (target != undefined) { - refint_attributes = refint_attributes + " " + target + " " + res.msgs[i].lDAPDisplayName; - memberof_config = memberof_config + "overlay memberof -memberof-dangling error -memberof-refint TRUE -memberof-group-oc top -memberof-member-ad " + res.msgs[i].lDAPDisplayName + " -memberof-memberof-ad " + target + " -memberof-dangling-error 32 - -"; - } - } - - memberof_config = memberof_config + " -overlay refint -refint_attributes" + refint_attributes + " -"; - - ok = sys.file_save(subobj.LDAPDIR + "/memberof.conf", memberof_config); - if (!ok) { - message("failed to create file: " + f + "\n"); - assert(ok); - } - -} -var schema_command = "ad2oLschema --option=convert:target=" + options["ldap-backend-type"] + " -I " + lp.get("setup directory") + "/" + mapping + " -H tdb://" + tmp_schema_ldb + " -O " + subobj.LDAPDIR + "/" + backend_schema; - -message("\nCreate a suitable schema file with:\n%s\n", schema_command); -message("\nStart slapd with: \n%s\n", slapd_command); - -message("All OK\n"); -return 0; +#!/usr/bin/python +# +# Unix SMB/CIFS implementation. +# provision a Samba4 server +# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008 +# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008 +# +# Based on the original in EJS: +# Copyright (C) Andrew Tridgell 2005 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import getopt +import optparse +import os, sys + +import samba +import param + +from auth import system_session +import samba.getopt as options +from samba.provision import (provision_backend) + +parser = optparse.OptionParser("provision [options]") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +parser.add_option_group(options.VersionOptions(parser)) +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +parser.add_option("--setupdir", type="string", metavar="DIR", + help="directory with setup files") +parser.add_option("--realm", type="string", metavar="REALM", help="set realm") +parser.add_option("--domain", type="string", metavar="DOMAIN", + help="set domain") +parser.add_option("--host-name", type="string", metavar="HOSTNAME", + help="set hostname") +parser.add_option("--ldap-manager-pass", type="string", metavar="PASSWORD", + help="choose LDAP manager password (otherwise random)") +parser.add_option("--root", type="string", metavar="USERNAME", + help="choose 'root' unix username") +parser.add_option("--quiet", help="Be quiet", action="store_true") +parser.add_option("--ldap-backend-type", type="choice", metavar="LDAP-BACKEND-TYPE", + help="LDB mapping module to use for the LDAP backend", + choices=["fedora-ds", "openldap"]) +parser.add_option("--server-role", type="choice", metavar="ROLE", + choices=["domain controller", "dc", "member server", "member", "standalone"], + help="Set server role to provision for (default standalone)") +parser.add_option("--targetdir", type="string", metavar="DIR", + help="Set target directory") + +opts = parser.parse_args()[0] + +def message(text): + """print a message if quiet is not set.""" + if not opts.quiet: + print text + +if opts.realm is None or opts.domain is None: + if opts.realm is None: + print >>sys.stderr, "No realm set" + if opts.domain is None: + print >>sys.stderr, "No domain set" + parser.print_usage() + sys.exit(1) + +smbconf = sambaopts.get_loadparm().configfile() + +if opts.server_role == "dc": + server_role = "domain controller" +elif opts.server_role == "member": + server_role = "member server" +else: + server_role = opts.server_role + +setup_dir = opts.setupdir +if setup_dir is None: + setup_dir = "setup" + +provision_backend(setup_dir=setup_dir, message=message, smbconf=smbconf, targetdir=opts.targetdir, + realm=opts.realm, domain=opts.domain, + hostname=opts.host_name, + adminpass=opts.ldap_manager_pass, + root=opts.root, serverrole=server_role, + ldap_backend_type=opts.ldap_backend_type) + +message("All OK") diff --git a/source4/setup/provision-backend.js b/source4/setup/provision-backend.js new file mode 100644 index 00000000000..edc09907a89 --- /dev/null +++ b/source4/setup/provision-backend.js @@ -0,0 +1,188 @@ +#!/bin/sh +exec smbscript "$0" ${1+"$@"} +/* + provision a Samba4 server + Copyright Andrew Tridgell 2005 + Released under the GNU GPL v2 or later +*/ + +options = GetOptions(ARGV, + "POPT_AUTOHELP", + "POPT_COMMON_SAMBA", + "POPT_COMMON_VERSION", + "POPT_COMMON_CREDENTIALS", + 'realm=s', + 'host-name=s', + 'ldap-manager-pass=s', + 'root=s', + 'quiet', + 'ldap-backend-type=s', + 'ldap-backend-port=i'); + +if (options == undefined) { + println("Failed to parse options"); + return -1; +} + +sys = sys_init(); + +libinclude("base.js"); +libinclude("provision.js"); + +/* + print a message if quiet is not set +*/ +function message() +{ + if (options["quiet"] == undefined) { + print(vsprintf(arguments)); + } +} + +/* + show some help +*/ +function ShowHelp() +{ + print(" +Samba4 provisioning + +provision [options] + --realm REALM set realm + --host-name HOSTNAME set hostname + --ldap-manager-pass PASSWORD choose LDAP Manager password (otherwise random) + --root USERNAME choose 'root' unix username + --quiet Be quiet + --ldap-backend-type LDAPSERVER Select either \"openldap\" or \"fedora-ds\" as a target to configure + --ldap-backend-port PORT Select the TCP port (if any) that the LDAP backend should listen on (Fedora DS only) +You must provide at least a realm and ldap-backend-type + +"); + exit(1); +} + +if (options['host-name'] == undefined) { + options['host-name'] = hostname(); +} + +/* + main program +*/ +if (options["realm"] == undefined || + options["ldap-backend-type"] == undefined || + options["host-name"] == undefined) { + ShowHelp(); +} + +/* cope with an initially blank smb.conf */ +var lp = loadparm_init(); +lp.set("realm", options.realm); +lp.reload(); + +var subobj = provision_guess(); +for (r in options) { + var key = strupper(join("", split("-", r))); + subobj[key] = options[r]; +} + + + +var paths = provision_default_paths(subobj); +provision_fix_subobj(subobj, paths); +message("Provisioning LDAP backend for %s in realm %s into %s\n", subobj.HOSTNAME, subobj.REALM, subobj.LDAPDIR); +message("Using %s password: %s\n", subobj.LDAPMANAGERDN, subobj.LDAPMANAGERPASS); +var tmp_schema_ldb = subobj.LDAPDIR + "/schema-tmp.ldb"; +sys.mkdir(subobj.LDAPDIR, 0700); + +provision_schema(subobj, message, tmp_schema_ldb, paths); + +var mapping; +var backend_schema; +var slapd_command; +if (options["ldap-backend-type"] == "fedora-ds") { + mapping = "schema-map-fedora-ds-1.0"; + backend_schema = "99_ad.ldif"; + if (options["ldap-backend-port"] != undefined) { + message("Will listen on TCP port " + options["ldap-backend-port"] + "\n"); + subobj.SERVERPORT="ServerPort = " + options["ldap-backend-port"]; + } else { + message("Will listen on LDAPI only\n"); + subobj.SERVERPORT=""; + } + setup_file("fedorads.inf", message, subobj.LDAPDIR + "/fedorads.inf", subobj); + setup_file("fedorads-partitions.ldif", message, subobj.LDAPDIR + "/fedorads-partitions.ldif", subobj); + + slapd_command = "(see documentation)"; +} else if (options["ldap-backend-type"] == "openldap") { + mapping = "schema-map-openldap-2.3"; + backend_schema = "backend-schema.schema"; + setup_file("slapd.conf", message, subobj.LDAPDIR + "/slapd.conf", subobj); + setup_file("modules.conf", message, subobj.LDAPDIR + "/modules.conf", subobj); + sys.mkdir(subobj.LDAPDIR + "/db", 0700); + subobj.LDAPDBDIR = subobj.LDAPDIR + "/db/user"; + sys.mkdir(subobj.LDAPDBDIR, 0700); + sys.mkdir(subobj.LDAPDBDIR + "/bdb-logs", 0700); + sys.mkdir(subobj.LDAPDBDIR + "/tmp", 0700); + setup_file("DB_CONFIG", message, subobj.LDAPDBDIR + "/DB_CONFIG", subobj); + subobj.LDAPDBDIR = subobj.LDAPDIR + "/db/config"; + sys.mkdir(subobj.LDAPDBDIR, 0700); + sys.mkdir(subobj.LDAPDBDIR + "/bdb-logs", 0700); + sys.mkdir(subobj.LDAPDBDIR + "/tmp", 0700); + setup_file("DB_CONFIG", message, subobj.LDAPDBDIR + "/DB_CONFIG", subobj); + subobj.LDAPDBDIR = subobj.LDAPDIR + "/db/schema"; + sys.mkdir(subobj.LDAPDBDIR, 0700); + sys.mkdir(subobj.LDAPDBDIR + "/tmp", 0700); + sys.mkdir(subobj.LDAPDBDIR + "/bdb-logs", 0700); + setup_file("DB_CONFIG", message, subobj.LDAPDBDIR + "/DB_CONFIG", subobj); + if (options["ldap-backend-port"] != undefined) { + message("\nStart slapd with: \n"); + slapd_command = "slapd -f " + subobj.LDAPDIR + "/slapd.conf -h \"ldap://0.0.0.0:" + options["ldap-backend-port"] + " " + subobj.LDAPI_URI "\""; + } else { + slapd_command = "slapd -f " + subobj.LDAPDIR + "/slapd.conf -h " + subobj.LDAPI_URI; + } + + var ldb = ldb_init(); + ldb.filename = tmp_schema_ldb; + + var connect_ok = ldb.connect(ldb.filename); + assert(connect_ok); + var attrs = new Array("linkID", "lDAPDisplayName"); + var res = ldb.search("(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", subobj.SCHEMADN, ldb.SCOPE_SUBTREE, attrs); + assert(res.error == 0); + var memberof_config = ""; + var refint_attributes = ""; + for (i=0; i < res.msgs.length; i++) { + var target = searchone(ldb, subobj.SCHEMADN, "(&(objectclass=attributeSchema)(linkID=" + (res.msgs[i].linkID + 1) + "))", "lDAPDisplayName"); + if (target != undefined) { + refint_attributes = refint_attributes + " " + target + " " + res.msgs[i].lDAPDisplayName; + memberof_config = memberof_config + "overlay memberof +memberof-dangling error +memberof-refint TRUE +memberof-group-oc top +memberof-member-ad " + res.msgs[i].lDAPDisplayName + " +memberof-memberof-ad " + target + " +memberof-dangling-error 32 + +"; + } + } + + memberof_config = memberof_config + " +overlay refint +refint_attributes" + refint_attributes + " +"; + + ok = sys.file_save(subobj.LDAPDIR + "/memberof.conf", memberof_config); + if (!ok) { + message("failed to create file: " + f + "\n"); + assert(ok); + } + +} +var schema_command = "ad2oLschema --option=convert:target=" + options["ldap-backend-type"] + " -I " + lp.get("setup directory") + "/" + mapping + " -H tdb://" + tmp_schema_ldb + " -O " + subobj.LDAPDIR + "/" + backend_schema; + +message("\nCreate a suitable schema file with:\n%s\n", schema_command); +message("\nStart slapd with: \n%s\n", slapd_command); + +message("All OK\n"); +return 0; diff --git a/source4/setup/provision.js b/source4/setup/provision.js deleted file mode 100755 index 328754fd9c8..00000000000 --- a/source4/setup/provision.js +++ /dev/null @@ -1,198 +0,0 @@ -#!/bin/sh -exec smbscript "$0" ${1+"$@"} -/* - provision a Samba4 server - Copyright Andrew Tridgell 2005 - Released under the GNU GPL v2 or later -*/ - -options = GetOptions(ARGV, - "POPT_AUTOHELP", - "POPT_COMMON_SAMBA", - "POPT_COMMON_VERSION", - "POPT_COMMON_CREDENTIALS", - 'realm=s', - 'domain=s', - 'domain-guid=s', - 'domain-sid=s', - 'policy-guid=s', - 'host-name=s', - 'host-ip=s', - 'host-guid=s', - 'invocationid=s', - 'adminpass=s', - 'krbtgtpass=s', - 'machinepass=s', - 'dnspass=s', - 'root=s', - 'nobody=s', - 'nogroup=s', - 'wheel=s', - 'users=s', - 'quiet', - 'blank', - 'server-role=s', - 'partitions-only', - 'ldap-base', - 'ldap-backend=s', - 'ldap-backend-type=s', - 'aci=s'); - -if (options == undefined) { - println("Failed to parse options"); - return -1; -} - -libinclude("base.js"); -libinclude("provision.js"); - -/* - print a message if quiet is not set -*/ -function message() -{ - if (options["quiet"] == undefined) { - print(vsprintf(arguments)); - } -} - -/* - show some help -*/ -function ShowHelp() -{ - print(" -Samba4 provisioning - -provision [options] - --realm REALM set realm - --domain DOMAIN set domain - --domain-guid GUID set domainguid (otherwise random) - --domain-sid SID set domainsid (otherwise random) - --host-name HOSTNAME set hostname - --host-ip IPADDRESS set ipaddress - --host-guid GUID set hostguid (otherwise random) - --policy-guid GUID set group policy guid (otherwise random) - --invocationid GUID set invocationid (otherwise random) - --adminpass PASSWORD choose admin password (otherwise random) - --krbtgtpass PASSWORD choose krbtgt password (otherwise random) - --machinepass PASSWORD choose machine password (otherwise random) - --root USERNAME choose 'root' unix username - --nobody USERNAME choose 'nobody' user - --nogroup GROUPNAME choose 'nogroup' group - --wheel GROUPNAME choose 'wheel' privileged group - --users GROUPNAME choose 'users' group - --quiet Be quiet - --blank do not add users or groups, just the structure - --server-role ROLE Set server role to provision for (default standalone) - --partitions-only Configure Samba's partitions, but do not modify them (ie, join a BDC) - --ldap-base output only an LDIF file, suitable for creating an LDAP baseDN - --ldap-backend LDAPSERVER LDAP server to use for this provision - --ldap-backend-type TYPE OpenLDAP or Fedora DS - --aci ACI An arbitary LDIF fragment, particularly useful to loading a backend ACI value into a target LDAP server -You must provide at least a realm and domain - -"); - exit(1); -} - -if (options['host-name'] == undefined) { - options['host-name'] = hostname(); -} - -/* - main program -*/ -if (options["realm"] == undefined || - options["domain"] == undefined || - options["host-name"] == undefined) { - ShowHelp(); -} - -/* cope with an initially blank smb.conf */ -var lp = loadparm_init(); -lp.set("realm", options.realm); -lp.set("workgroup", options.domain); -lp.set("server role", options["server-role"]); -lp.reload(); - -var subobj = provision_guess(); -for (r in options) { - var key = strupper(join("", split("-", r))); - subobj[key] = options[r]; -} - -var blank = (options["blank"] != undefined); -var ldapbackend = (options["ldap-backend"] != undefined); -var ldapbackendtype = options["ldap-backend-type"]; -var partitions_only = (options["partitions-only"] != undefined); -var paths = provision_default_paths(subobj); -if (options["aci"] != undefined) { - message("set ACI: %s\n", subobj["ACI"]); -} - -message("set DOMAIN SID: %s\n", subobj["DOMAINSID"]); - -provision_fix_subobj(subobj, paths); - -if (ldapbackend) { - if (options["ldap-backend"] == "ldapi") { - subobj.LDAPBACKEND = subobj.LDAPI_URI; - } - if (ldapbackendtype == undefined) { - - } else if (ldapbackendtype == "openldap") { - subobj.LDAPMODULE = "normalise,entryuuid"; - subobj.TDB_MODULES_LIST = ""; - } else if (ldapbackendtype == "fedora-ds") { - subobj.LDAPMODULE = "nsuniqueid"; - } - subobj.BACKEND_MOD = subobj.LDAPMODULE + ",paged_searches"; - subobj.DOMAINDN_LDB = subobj.LDAPBACKEND; - subobj.CONFIGDN_LDB = subobj.LDAPBACKEND; - subobj.SCHEMADN_LDB = subobj.LDAPBACKEND; - message("LDAP module: %s on backend: %s\n", subobj.LDAPMODULE, subobj.LDAPBACKEND); -} - -if (!provision_validate(subobj, message)) { - return -1; -} - -var system_session = system_session(); -var creds = options.get_credentials(); -message("Provisioning for %s in realm %s\n", subobj.DOMAIN, subobj.REALM); -message("Using administrator password: %s\n", subobj.ADMINPASS); -if (partitions_only) { - provision_become_dc(subobj, message, false, paths, system_session); -} else { - provision(subobj, message, blank, paths, system_session, creds, ldapbackend); - provision_dns(subobj, message, paths, system_session, creds); - message("To reproduce this provision, run with:\n"); -/* There has to be a better way than this... */ - message("--realm='%s' --domain='%s' \\\n", subobj.REALM_CONF, subobj.DOMAIN_CONF); - if (subobj.DOMAINGUID != undefined) { - message("--domain-guid='%s' \\\n", subobj.DOMAINGUID); - } - if (subobj.HOSTGUID != undefined) { - message("--host-guid='%s' \\\n", subobj.HOSTGUID); - } - message("--policy-guid='%s' --host-name='%s' --host-ip='%s' \\\n", subobj.POLICYGUID, subobj.HOSTNAME, subobj.HOSTIP); - if (subobj.INVOCATIONID != undefined) { - message("--invocationid='%s' \\\n", subobj.INVOCATIONID); - } - message("--adminpass='%s' --krbtgtpass='%s' \\\n", subobj.ADMINPASS, subobj.KRBTGTPASS); - message("--machinepass='%s' --dnspass='%s' \\\n", subobj.MACHINEPASS, subobj.DNSPASS); - message("--root='%s' --nobody='%s' --nogroup='%s' \\\n", subobj.ROOT, subobj.NOBODY, subobj.NOGROUP); - message("--wheel='%s' --users='%s' --server-role='%s' \\\n", subobj.WHEEL, subobj.USERS, subobj.SERVERROLE); - if (ldapbackend) { - message("--ldap-backend='%s' \\\n", subobj.LDAPBACKEND); - } - if (ldapbackendtype != undefined) { - message("--ldap-backend-type='%s' \\\n", + ldapbackendtype); - } - message("--aci='" + subobj.ACI + "' \\\n") -} - - -message("All OK\n"); -return 0; diff --git a/source4/setup/provision_basedn.ldif b/source4/setup/provision_basedn.ldif index 11eb0593e8d..7fdecfa3c00 100644 --- a/source4/setup/provision_basedn.ldif +++ b/source4/setup/provision_basedn.ldif @@ -3,7 +3,6 @@ ################################ dn: ${DOMAINDN} objectClass: top -objectClass: domain -objectClass: domainDNS +objectClass: ${DOMAIN_OC} ${ACI} diff --git a/source4/setup/schema-map-openldap-2.3 b/source4/setup/schema-map-openldap-2.3 index 0bce95afba4..3f07a9d50f6 100644 --- a/source4/setup/schema-map-openldap-2.3 +++ b/source4/setup/schema-map-openldap-2.3 @@ -11,6 +11,7 @@ distinguishedName description cn top +#The memberOf plugin provides this attribute memberOf #This shouldn't make it to the ldap server sambaPassword diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif index 8bd17054687..7146091c8ea 100644 --- a/source4/setup/schema_samba4.ldif +++ b/source4/setup/schema_samba4.ldif @@ -194,3 +194,41 @@ attributeID: 1.3.6.1.4.1.7165.4.1.11 attributeSyntax: 2.5.5.4 oMSyntax: 20 +# +# Based on domainDNS, but without the DNS bits. +# + +dn: CN=Samba4-Local-Domain,${SCHEMADN} +objectClass: top +objectClass: classSchema +subClassOf: top +governsID: 1.3.6.1.4.1.7165.4.2.2 +possibleInferiors: group +possibleInferiors: lostAndFound +possibleInferiors: builtinDomain +possibleInferiors: computer +possibleInferiors: user +possibleInferiors: container +possibleInferiors: groupPolicyContainer +possibleInferiors: organization +possibleInferiors: domainDNS +possibleInferiors: locality +possibleInferiors: msDS-AzAdminManager +possibleInferiors: country +possibleInferiors: organizationalUnit +rDNAttID: cn +showInAdvancedViewOnly: TRUE +adminDisplayName: Samba4-Local-Domain +adminDescription: Samba4-Local-Domain +systemMayContain: msDS-Behavior-Version +systemMayContain: managedBy +objectClassCategory: 1 +lDAPDisplayName: samba4LocalDomain +schemaIDGUID: 07be1647-8310-4fba-91ae-34e55d5a8293 +systemOnly: FALSE +systemAuxiliaryClass: samDomainBase +defaultSecurityDescriptor: D:(A;;RPLCLORC;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +defaultObjectCategory: CN=Builtin-Domain,${SCHEMADN} + diff --git a/source4/setup/slapd.conf b/source4/setup/slapd.conf index 83f4da33590..cdf9ff79a98 100644 --- a/source4/setup/slapd.conf +++ b/source4/setup/slapd.conf @@ -21,7 +21,7 @@ include ${LDAPDIR}/modules.conf defaultsearchbase ${DOMAINDN} -include ${LDAPDIR}/memberof.conf +${MEMBEROF_CONFIG} database hdb suffix ${SCHEMADN} @@ -62,8 +62,6 @@ syncprov-sessionlog 100 database hdb suffix ${DOMAINDN} -rootdn ${LDAPMANAGERDN} -rootpw ${LDAPMANAGERPASS} directory ${LDAPDIR}/db/user index objectClass eq index samAccountName eq @@ -82,8 +80,12 @@ index dnsRoot eq index nETBIOSName eq index cn eq +rootdn ${LDAPMANAGERDN} +rootpw ${LDAPMANAGERPASS} + #syncprov is stable in OpenLDAP 2.3, and available in 2.2. #We only need this for the contextCSN attribute anyway.... overlay syncprov syncprov-checkpoint 100 10 syncprov-sessionlog 100 + diff --git a/source4/setup/tests/blackbox_provision.sh b/source4/setup/tests/blackbox_provision.sh index 83c045e40d7..75d4fcfcb4b 100755 --- a/source4/setup/tests/blackbox_provision.sh +++ b/source4/setup/tests/blackbox_provision.sh @@ -28,7 +28,7 @@ testit() { } testit "simple-default" $PYTHON ./setup/provision $CONFIGURATION --domain=FOO --realm=foo.example.com --targetdir=$PREFIX/simple-default -testit "simple-dc" $PYTHON ./setup/provision $CONFIGURATION --server-role="dc" --domain=FOO --realm=foo.example.com --targetdir=$PREFIX/simple-dc +testit "simple-dc" $PYTHON ./setup/provision $CONFIGURATION --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/simple-dc testit "simple-member" $PYTHON ./setup/provision $CONFIGURATION --server-role="member" --domain=FOO --realm=foo.example.com --targetdir=$PREFIX/simple-member testit "simple-standalone" $PYTHON ./setup/provision $CONFIGURATION --server-role="standalone" --domain=FOO --realm=foo.example.com --targetdir=$PREFIX/simple-standalone diff --git a/source4/smb_server/smb/nttrans.c b/source4/smb_server/smb/nttrans.c index a20c41ba4d0..1b49e235113 100644 --- a/source4/smb_server/smb/nttrans.c +++ b/source4/smb_server/smb/nttrans.c @@ -287,7 +287,30 @@ static NTSTATUS nttrans_set_sec_desc(struct smbsrv_request *req, static NTSTATUS nttrans_rename(struct smbsrv_request *req, struct nttrans_op *op) { - return NT_STATUS_NOT_IMPLEMENTED; + struct smb_nttrans *trans = op->trans; + union smb_rename *io; + + if (trans->in.params.length < 5) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* parse the request */ + io = talloc(req, union smb_rename); + NT_STATUS_HAVE_NO_MEMORY(io); + + io->nttrans.level = RAW_RENAME_NTTRANS; + io->nttrans.in.file.ntvfs = smbsrv_pull_fnum(req, trans->in.params.data, 0); + io->nttrans.in.flags = SVAL(trans->in.params.data, 2); + + smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 4, + &io->nttrans.in.new_name, + STR_TERMINATE); + if (!io->nttrans.in.new_name) { + return NT_STATUS_INVALID_PARAMETER; + } + + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(io->nttrans.in.file.ntvfs); + return ntvfs_rename(req->ntvfs, io); } /* diff --git a/source4/static_deps.mk b/source4/static_deps.mk index 1f86372aa37..ade41614c24 100644 --- a/source4/static_deps.mk +++ b/source4/static_deps.mk @@ -36,7 +36,8 @@ heimdal_basics: \ heimdal/lib/krb5/krb_err.h \ heimdal/lib/krb5/krb5_err.h \ heimdal/lib/gssapi/gkrb5_err.h \ - heimdal/lib/hx509/hx509_err.h + heimdal/lib/hx509/hx509_err.h \ + heimdal/lib/wind/wind_err.h proto: basics basics: include/includes.h \ diff --git a/source4/torture/raw/openbench.c b/source4/torture/raw/openbench.c index 87b27d07283..e8b2f568135 100644 --- a/source4/torture/raw/openbench.c +++ b/source4/torture/raw/openbench.c @@ -37,7 +37,7 @@ static int nprocs; static int open_failed; -static int open_retries; +static int close_failed; static char **fnames; static int num_connected; static struct timed_event *report_te; @@ -49,12 +49,16 @@ struct benchopen_state { struct smbcli_state *cli; struct smbcli_tree *tree; int client_num; - int old_fnum; - int fnum; - int file_num; + int close_fnum; + int open_fnum; + int close_file_num; + int open_file_num; + int pending_file_num; + int next_file_num; int count; int lastcount; union smb_open open_parms; + int open_retries; union smb_close close_parms; struct smbcli_request *req_open; struct smbcli_request *req_close; @@ -95,11 +99,11 @@ static void reopen_connection_complete(struct composite_context *ctx) num_connected++; - DEBUG(0,("reconnect to %s finished (%u connected)\n", state->dest_host, - num_connected)); + DEBUG(0,("[%u] reconnect to %s finished (%u connected)\n", + state->client_num, state->dest_host, num_connected)); - state->fnum = -1; - state->old_fnum = -1; + state->open_fnum = -1; + state->close_fnum = -1; next_open(state); } @@ -136,7 +140,8 @@ static void reopen_connection(struct event_context *ev, struct timed_event *te, /* kill off the remnants of the old connection */ talloc_free(state->tree); state->tree = NULL; - state->fnum = -1; + state->open_fnum = -1; + state->close_fnum = -1; ctx = smb_composite_connect_send(io, state->mem_ctx, lp_resolve_context(state->tctx->lp_ctx), @@ -158,9 +163,10 @@ static void next_open(struct benchopen_state *state) { state->count++; - state->file_num = (state->file_num+1) % (3*nprocs); + state->pending_file_num = state->next_file_num; + state->next_file_num = (state->next_file_num+1) % (3*nprocs); - DEBUG(2,("[%d] opening %u\n", state->client_num, state->file_num)); + DEBUG(2,("[%d] opening %u\n", state->client_num, state->pending_file_num)); state->open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX; state->open_parms.ntcreatex.in.flags = 0; state->open_parms.ntcreatex.in.root_fid = 0; @@ -172,7 +178,7 @@ static void next_open(struct benchopen_state *state) state->open_parms.ntcreatex.in.create_options = 0; state->open_parms.ntcreatex.in.impersonation = 0; state->open_parms.ntcreatex.in.security_flags = 0; - state->open_parms.ntcreatex.in.fname = fnames[state->file_num]; + state->open_parms.ntcreatex.in.fname = fnames[state->pending_file_num]; state->req_open = smb_raw_open_send(state->tree, &state->open_parms); state->req_open->async.fn = open_completed; @@ -182,18 +188,18 @@ static void next_open(struct benchopen_state *state) static void next_close(struct benchopen_state *state) { - DEBUG(2,("[%d] closing %d\n", state->client_num, state->old_fnum)); - if (state->old_fnum == -1) { + if (state->close_fnum == -1) { return; } + DEBUG(2,("[%d] closing %d (fnum[%d])\n", + state->client_num, state->close_file_num, state->close_fnum)); state->close_parms.close.level = RAW_CLOSE_CLOSE; - state->close_parms.close.in.file.fnum = state->old_fnum; + state->close_parms.close.in.file.fnum = state->close_fnum; state->close_parms.close.in.write_time = 0; state->req_close = smb_raw_close_send(state->tree, &state->close_parms); state->req_close->async.fn = close_completed; state->req_close->async.private = state; - state->old_fnum = -1; } /* @@ -218,7 +224,8 @@ static void open_completed(struct smbcli_request *req) state->tree = NULL; state->cli = NULL; num_connected--; - DEBUG(0,("reopening connection to %s\n", state->dest_host)); + DEBUG(0,("[%u] reopening connection to %s\n", + state->client_num, state->dest_host)); talloc_free(state->te); state->te = event_add_timed(state->ev, state->mem_ctx, timeval_current_ofs(1,0), @@ -227,8 +234,9 @@ static void open_completed(struct smbcli_request *req) } if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) { - DEBUG(2,("[%d] retrying open\n", state->client_num)); - open_retries++; + DEBUG(2,("[%d] retrying open %d\n", + state->client_num, state->pending_file_num)); + state->open_retries++; state->req_open = smb_raw_open_send(state->tree, &state->open_parms); state->req_open->async.fn = open_completed; state->req_open->async.private = state; @@ -237,17 +245,21 @@ static void open_completed(struct smbcli_request *req) if (!NT_STATUS_IS_OK(status)) { open_failed++; - DEBUG(0,("open failed - %s\n", nt_errstr(status))); + DEBUG(0,("[%u] open failed %d - %s\n", + state->client_num, state->pending_file_num, + nt_errstr(status))); return; } - state->old_fnum = state->fnum; - state->fnum = state->open_parms.ntcreatex.out.file.fnum; + state->close_file_num = state->open_file_num; + state->close_fnum = state->open_fnum; + state->open_file_num = state->pending_file_num; + state->open_fnum = state->open_parms.ntcreatex.out.file.fnum; - DEBUG(2,("[%d] open completed: fnum=%d old_fnum=%d\n", - state->client_num, state->fnum, state->old_fnum)); + DEBUG(2,("[%d] open completed %d (fnum[%d])\n", + state->client_num, state->open_file_num, state->open_fnum)); - if (state->old_fnum != -1) { + if (state->close_fnum != -1) { next_close(state); } @@ -271,7 +283,8 @@ static void close_completed(struct smbcli_request *req) state->tree = NULL; state->cli = NULL; num_connected--; - DEBUG(0,("reopening connection to %s\n", state->dest_host)); + DEBUG(0,("[%u] reopening connection to %s\n", + state->client_num, state->dest_host)); talloc_free(state->te); state->te = event_add_timed(state->ev, state->mem_ctx, timeval_current_ofs(1,0), @@ -280,13 +293,17 @@ static void close_completed(struct smbcli_request *req) } if (!NT_STATUS_IS_OK(status)) { - open_failed++; - DEBUG(0,("close failed - %s\n", nt_errstr(status))); + close_failed++; + DEBUG(0,("[%u] close failed %d (fnum[%d]) - %s\n", + state->client_num, state->close_file_num, + state->close_fnum, + nt_errstr(status))); return; } - DEBUG(2,("[%d] close completed: fnum=%d old_fnum=%d\n", - state->client_num, state->fnum, state->old_fnum)); + DEBUG(2,("[%d] close completed %d (fnum[%d])\n", + state->client_num, state->close_file_num, + state->close_fnum)); } static void echo_completion(struct smbcli_request *req) @@ -298,7 +315,8 @@ static void echo_completion(struct smbcli_request *req) talloc_free(state->tree); state->tree = NULL; num_connected--; - DEBUG(0,("reopening connection to %s\n", state->dest_host)); + DEBUG(0,("[%u] reopening connection to %s\n", + state->client_num, state->dest_host)); talloc_free(state->te); state->te = event_add_timed(state->ev, state->mem_ctx, timeval_current_ofs(1,0), @@ -352,7 +370,9 @@ bool torture_bench_open(struct torture_context *torture) struct timeval tv; struct event_context *ev = event_context_find(mem_ctx); struct benchopen_state *state; - int total = 0, minops=0; + int total = 0; + int total_retries = 0; + int minops = 0; bool progress=false; progress = torture_setting_bool(torture, "progress", true); @@ -397,11 +417,10 @@ bool torture_bench_open(struct torture_context *torture) } for (i=0;i<nprocs;i++) { - state[i].file_num = i; - state[i].fnum = smbcli_open(state[i].tree, - fnames[state->file_num], - O_RDWR|O_CREAT, DENY_ALL); - state[i].old_fnum = -1; + /* all connections start with the same file */ + state[i].next_file_num = 0; + state[i].open_fnum = -1; + state[i].close_fnum = -1; next_open(&state[i]); } @@ -420,17 +439,30 @@ bool torture_bench_open(struct torture_context *torture) DEBUG(0,("open failed\n")); goto failed; } + if (close_failed) { + DEBUG(0,("open failed\n")); + goto failed; + } } talloc_free(report_te); + if (progress) { + for (i=0;i<nprocs;i++) { + printf(" "); + } + printf("\r"); + } - printf("%.2f ops/second (%d retries)\n", - total/timeval_elapsed(&tv), open_retries); minops = state[0].count; for (i=0;i<nprocs;i++) { - printf("[%d] %u ops\n", i, state[i].count); + total += state[i].count; + total_retries += state[i].open_retries; + printf("[%d] %u ops (%u retries)\n", + i, state[i].count, state[i].open_retries); if (state[i].count < minops) minops = state[i].count; } + printf("%.2f ops/second (%d retries)\n", + total/timeval_elapsed(&tv), total_retries); if (minops < 0.5*total/nprocs) { printf("Failed: unbalanced open\n"); goto failed; diff --git a/source4/torture/raw/oplock.c b/source4/torture/raw/oplock.c index 1926b121289..8b2e4fb1771 100644 --- a/source4/torture/raw/oplock.c +++ b/source4/torture/raw/oplock.c @@ -229,7 +229,7 @@ static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbc io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n"); + torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK; @@ -294,7 +294,7 @@ static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbc io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open a file with an exclusive oplock (share mode: all)\n"); + torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ| @@ -363,7 +363,6 @@ static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbc union smb_open io; union smb_setfileinfo sfi; uint16_t fnum=0; - bool s3 = torture_setting_bool(tctx, "samba3", false); if (!torture_setup_dir(cli1, BASEDIR)) { return false; @@ -389,15 +388,10 @@ static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbc io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open a file with an exclusive oplock (share mode: %s)\n", - s3?"all":"none"); + torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n"); + ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK; - if (s3) { - io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ| - NTCREATEX_SHARE_ACCESS_WRITE| - NTCREATEX_SHARE_ACCESS_DELETE; - } status = smb_raw_open(cli1->tree, tctx, &io); CHECK_STATUS(tctx, status, NT_STATUS_OK); @@ -458,7 +452,7 @@ static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbc io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open with exclusive oplock\n"); + torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -523,7 +517,7 @@ static bool test_raw_oplock_exclusive5(struct torture_context *tctx, struct smbc io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open with exclusive oplock\n"); + torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -570,7 +564,6 @@ static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbc union smb_open io; union smb_rename rn; uint16_t fnum=0; - bool s3 = torture_setting_bool(tctx, "samba3", false); if (!torture_setup_dir(cli1, BASEDIR)) { return false; @@ -597,16 +590,9 @@ static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbc io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname1; - /* we should use no share mode, when samba3 passes this */ - torture_comment(tctx, "open a file with an exclusive oplock (share mode: %s)\n", - s3?"all":"none"); + torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive oplock (share mode: none)\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK; - if (s3) { - io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ| - NTCREATEX_SHARE_ACCESS_WRITE| - NTCREATEX_SHARE_ACCESS_DELETE; - } status = smb_raw_open(cli1->tree, tctx, &io); CHECK_STATUS(tctx, status, NT_STATUS_OK); @@ -673,7 +659,7 @@ static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_s /* with a batch oplock we get a break */ - torture_comment(tctx, "open with batch oplock\n"); + torture_comment(tctx, "BATCH1: open with batch oplock\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | @@ -754,7 +740,7 @@ static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_s io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open with batch oplock\n"); + torture_comment(tctx, "BATCH2: open with batch oplock\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | @@ -832,7 +818,7 @@ static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_s io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "if we close on break then the unlink can succeed\n"); + torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | @@ -896,7 +882,7 @@ static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_s io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "a self read should not cause a break\n"); + torture_comment(tctx, "BATCH4: a self read should not cause a break\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -959,7 +945,7 @@ static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_s io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "a 2nd open should give a break\n"); + torture_comment(tctx, "BATCH5: a 2nd open should give a break\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -1024,7 +1010,7 @@ static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_s io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "a 2nd open should give a break to level II if the first open allowed shared read\n"); + torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree); @@ -1104,7 +1090,7 @@ static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_s io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "a 2nd open should get an oplock when we close instead of ack\n"); + torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree); @@ -1174,7 +1160,7 @@ static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_s io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open with batch oplock\n"); + torture_comment(tctx, "BATCH8: open with batch oplock\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -1243,7 +1229,7 @@ static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_s io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open with attributes only can create file\n"); + torture_comment(tctx, "BATCH9: open with attributes only can create file\n"); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | @@ -1348,7 +1334,7 @@ static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "Open with oplock after a non-oplock open should grant level2\n"); + torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock open should grant level2\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; @@ -1458,7 +1444,7 @@ static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.fname = fname; /* Test if a set-eof on pathname breaks an exclusive oplock. */ - torture_comment(tctx, "Test if setpathinfo set EOF breaks oplocks.\n"); + torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -1533,7 +1519,7 @@ static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.fname = fname; /* Test if a set-allocation size on pathname breaks an exclusive oplock. */ - torture_comment(tctx, "Test if setpathinfo allocation size breaks oplocks.\n"); + torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -1607,7 +1593,7 @@ static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open with batch oplock\n"); + torture_comment(tctx, "BATCH13: open with batch oplock\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -1684,7 +1670,7 @@ static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open with batch oplock\n"); + torture_comment(tctx, "BATCH14: open with batch oplock\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -1761,7 +1747,7 @@ static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.fname = fname; /* Test if a qpathinfo all info on pathname breaks a batch oplock. */ - torture_comment(tctx, "Test if qpathinfo all info breaks a batch oplock (should not).\n"); + torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -1833,7 +1819,7 @@ static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "open with batch oplock\n"); + torture_comment(tctx, "BATCH16: open with batch oplock\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); @@ -1887,7 +1873,6 @@ static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_ union smb_open io; union smb_rename rn; uint16_t fnum=0; - bool s3 = torture_setting_bool(tctx, "samba3", false); if (!torture_setup_dir(cli1, BASEDIR)) { return false; @@ -1914,18 +1899,12 @@ static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname1; - /* we should use no share mode, when samba3 passes this */ - torture_comment(tctx, "open a file with an batch oplock (share mode: %s)\n", - s3?"all":"none"); + torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n"); + ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; - if (s3) { - io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ| - NTCREATEX_SHARE_ACCESS_WRITE| - NTCREATEX_SHARE_ACCESS_DELETE; - } status = smb_raw_open(cli1->tree, tctx, &io); CHECK_STATUS(tctx, status, NT_STATUS_OK); @@ -1965,7 +1944,6 @@ static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_ union smb_open io; union smb_rename rn; uint16_t fnum=0; - bool s3 = torture_setting_bool(tctx, "samba3", false); if (!torture_setup_dir(cli1, BASEDIR)) { return false; @@ -1992,18 +1970,12 @@ static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname1; - /* we should use no share mode, when samba3 passes this */ - torture_comment(tctx, "open a file with an batch oplock (share mode: %s)\n", - s3?"all":"none"); + torture_comment(tctx, "BATCH18: open a file with an batch oplock (share mode: none)\n"); + ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; - if (s3) { - io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ| - NTCREATEX_SHARE_ACCESS_WRITE| - NTCREATEX_SHARE_ACCESS_DELETE; - } status = smb_raw_open(cli1->tree, tctx, &io); CHECK_STATUS(tctx, status, NT_STATUS_OK); @@ -2046,10 +2018,6 @@ static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_ union smb_setfileinfo sfi; uint16_t fnum=0; - if (torture_setting_bool(tctx, "samba3", false)) { - torture_skip(tctx, "BACHT19 disabled against samba3\n"); - } - if (!torture_setup_dir(cli1, BASEDIR)) { return false; } @@ -2076,7 +2044,7 @@ static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname1; - torture_comment(tctx, "open a file with an batch oplock (share mode: none)\n"); + torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | @@ -2136,6 +2104,232 @@ done: return ret; } +/**************************************************** + Called from raw-rename - we need oplock handling for + this test so this is why it's in oplock.c, not rename.c +****************************************************/ + +bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2) +{ + const char *fname1 = BASEDIR "\\test_trans2rename_1.dat"; + const char *fname2 = BASEDIR "\\test_trans2rename_2.dat"; + const char *fname3 = BASEDIR "\\test_trans2rename_3.dat"; + NTSTATUS status; + bool ret = true; + union smb_open io; + union smb_fileinfo qfi; + union smb_setfileinfo sfi; + uint16_t fnum=0; + + if (!torture_setup_dir(cli1, BASEDIR)) { + return false; + } + + /* cleanup */ + smbcli_unlink(cli1->tree, fname1); + smbcli_unlink(cli1->tree, fname2); + smbcli_unlink(cli1->tree, fname3); + + smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); + + /* + base ntcreatex parms + */ + io.generic.level = RAW_OPEN_NTCREATEX; + io.ntcreatex.in.root_fid = 0; + io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; + io.ntcreatex.in.alloc_size = 0; + io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; + io.ntcreatex.in.create_options = 0; + io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; + io.ntcreatex.in.security_flags = 0; + io.ntcreatex.in.fname = fname1; + + torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n"); + ZERO_STRUCT(break_info); + io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | + NTCREATEX_FLAGS_REQUEST_OPLOCK; + status = smb_raw_open(cli1->tree, tctx, &io); + CHECK_STATUS(tctx, status, NT_STATUS_OK); + fnum = io.ntcreatex.out.file.fnum; + CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN); + + torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n"); + ZERO_STRUCT(sfi); + sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION; + sfi.generic.in.file.path = fname1; + sfi.rename_information.in.overwrite = 0; + sfi.rename_information.in.root_fid = 0; + sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1; + + status = smb_raw_setpathinfo(cli2->tree, &sfi); + + CHECK_STATUS(tctx, status, NT_STATUS_OK); + CHECK_VAL(break_info.count, 0); + + ZERO_STRUCT(qfi); + qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION; + qfi.generic.in.file.fnum = fnum; + + status = smb_raw_fileinfo(cli1->tree, tctx, &qfi); + CHECK_STATUS(tctx, status, NT_STATUS_OK); + CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2); + + torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n"); + ZERO_STRUCT(sfi); + sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION; + sfi.generic.in.file.fnum = fnum; + sfi.rename_information.in.overwrite = 0; + sfi.rename_information.in.root_fid = 0; + sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1; + + status = smb_raw_setfileinfo(cli1->tree, &sfi); + CHECK_STATUS(tctx, status, NT_STATUS_OK); + CHECK_VAL(break_info.count, 0); + + ZERO_STRUCT(qfi); + qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION; + qfi.generic.in.file.fnum = fnum; + + status = smb_raw_fileinfo(cli1->tree, tctx, &qfi); + CHECK_STATUS(tctx, status, NT_STATUS_OK); + CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3); + + smbcli_close(cli1->tree, fnum); + +done: + smb_raw_exit(cli1->session); + smb_raw_exit(cli2->session); + smbcli_deltree(cli1->tree, BASEDIR); + return ret; +} + +/**************************************************** + Called from raw-rename - we need oplock handling for + this test so this is why it's in oplock.c, not rename.c +****************************************************/ + +bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1) +{ + const char *fname1 = BASEDIR "\\test_nttransrename_1.dat"; + const char *fname2 = BASEDIR "\\test_nttransrename_2.dat"; + NTSTATUS status; + bool ret = true; + union smb_open io; + union smb_fileinfo qfi, qpi; + union smb_rename rn; + uint16_t fnum=0; + + if (!torture_setup_dir(cli1, BASEDIR)) { + return false; + } + + /* cleanup */ + smbcli_unlink(cli1->tree, fname1); + smbcli_unlink(cli1->tree, fname2); + + smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); + + /* + base ntcreatex parms + */ + io.generic.level = RAW_OPEN_NTCREATEX; + io.ntcreatex.in.root_fid = 0; + io.ntcreatex.in.access_mask = 0;/* ask for no access at all */; + io.ntcreatex.in.alloc_size = 0; + io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; + io.ntcreatex.in.create_options = 0; + io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; + io.ntcreatex.in.security_flags = 0; + io.ntcreatex.in.fname = fname1; + + torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n"); + ZERO_STRUCT(break_info); + io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | + NTCREATEX_FLAGS_REQUEST_OPLOCK; + status = smb_raw_open(cli1->tree, tctx, &io); + CHECK_STATUS(tctx, status, NT_STATUS_OK); + fnum = io.ntcreatex.out.file.fnum; + CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN); + + torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n"); + ZERO_STRUCT(rn); + rn.generic.level = RAW_RENAME_NTTRANS; + rn.nttrans.in.file.fnum = fnum; + rn.nttrans.in.flags = 0; + rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1; + + status = smb_raw_rename(cli1->tree, &rn); + + CHECK_STATUS(tctx, status, NT_STATUS_OK); + CHECK_VAL(break_info.count, 0); + + /* w2k3 does nothing, it doesn't rename the file */ + torture_comment(tctx, "nttrans_rename: the server should have done nothing\n"); + ZERO_STRUCT(qfi); + qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION; + qfi.generic.in.file.fnum = fnum; + + status = smb_raw_fileinfo(cli1->tree, tctx, &qfi); + CHECK_STATUS(tctx, status, NT_STATUS_OK); + CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1); + + ZERO_STRUCT(qpi); + qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION; + qpi.generic.in.file.path = fname1; + + status = smb_raw_pathinfo(cli1->tree, tctx, &qpi); + CHECK_STATUS(tctx, status, NT_STATUS_OK); + CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1); + + ZERO_STRUCT(qpi); + qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION; + qpi.generic.in.file.path = fname2; + + status = smb_raw_pathinfo(cli1->tree, tctx, &qpi); + CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND); + + torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n"); + status = smbcli_close(cli1->tree, fnum); + CHECK_STATUS(tctx, status, NT_STATUS_OK); + + ZERO_STRUCT(qpi); + qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION; + qpi.generic.in.file.path = fname1; + + status = smb_raw_pathinfo(cli1->tree, tctx, &qpi); + CHECK_STATUS(tctx, status, NT_STATUS_OK); + CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1); + + ZERO_STRUCT(qpi); + qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION; + qpi.generic.in.file.path = fname2; + + status = smb_raw_pathinfo(cli1->tree, tctx, &qpi); + CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND); + + torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n"); + ZERO_STRUCT(rn); + rn.generic.level = RAW_RENAME_NTTRANS; + rn.nttrans.in.file.fnum = fnum+1; + rn.nttrans.in.flags = 0; + rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1; + + status = smb_raw_rename(cli1->tree, &rn); + + CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE); + +done: + smb_raw_exit(cli1->session); + smbcli_deltree(cli1->tree, BASEDIR); + return ret; +} + + static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2) { const char *fname1 = BASEDIR "\\test_batch20_1.dat"; @@ -2148,10 +2342,6 @@ static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_ union smb_setfileinfo sfi; uint16_t fnum=0,fnum2=0; - if (torture_setting_bool(tctx, "samba3", false)) { - torture_skip(tctx, "BACHT20 disabled against samba3\n"); - } - if (!torture_setup_dir(cli1, BASEDIR)) { return false; } @@ -2178,7 +2368,7 @@ static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname1; - torture_comment(tctx, "open a file with an batch oplock (share mode: all)\n"); + torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | @@ -2212,7 +2402,6 @@ static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_ CHECK_STATUS(tctx, status, NT_STATUS_OK); CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2); - /* we should use no share mode, when samba3 passes this */ torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | @@ -2307,7 +2496,7 @@ static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_ /* with a batch oplock we get a break */ - torture_comment(tctx, "open with batch oplock\n"); + torture_comment(tctx, "BATCH21: open with batch oplock\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | @@ -2350,7 +2539,7 @@ static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_ int te; if (torture_setting_bool(tctx, "samba3", false)) { - torture_skip(tctx, "BACHT22 disabled against samba3\n"); + torture_skip(tctx, "BATCH22 disabled against samba3\n"); } if (!torture_setup_dir(cli1, BASEDIR)) { @@ -2380,7 +2569,7 @@ static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_ /* with a batch oplock we get a break */ - torture_comment(tctx, "open with batch oplock\n"); + torture_comment(tctx, "BATCH22: open with batch oplock\n"); ZERO_STRUCT(break_info); io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | @@ -2440,7 +2629,7 @@ static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_ struct smbcli_state *cli3 = NULL; if (torture_setting_bool(tctx, "samba3", false)) { - torture_skip(tctx, "BACHT23 disabled against samba3\n"); + torture_skip(tctx, "BATCH23 disabled against samba3\n"); } if (!torture_setup_dir(cli1, BASEDIR)) { @@ -2470,7 +2659,7 @@ static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "a open and ask for a batch oplock\n"); + torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree); @@ -2557,7 +2746,7 @@ static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_ io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; - torture_comment(tctx, "a open without level support and ask for a batch oplock\n"); + torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n"); ZERO_STRUCT(break_info); smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree); diff --git a/source4/torture/raw/rename.c b/source4/torture/raw/rename.c index 4b0d9866595..9765c041011 100644 --- a/source4/torture/raw/rename.c +++ b/source4/torture/raw/rename.c @@ -434,6 +434,8 @@ done: return ret; } +extern bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2); +extern bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1); /* basic testing of rename calls @@ -443,6 +445,10 @@ struct torture_suite *torture_raw_rename(TALLOC_CTX *mem_ctx) struct torture_suite *suite = torture_suite_create(mem_ctx, "RENAME"); torture_suite_add_1smb_test(suite, "mv", test_mv); + /* test_trans2rename and test_nttransrename are actually in torture/raw/oplock.c to + use the handlers and macros there. */ + torture_suite_add_2smb_test(suite, "trans2rename", test_trans2rename); + torture_suite_add_1smb_test(suite, "nttransrename", test_nttransrename); torture_suite_add_1smb_test(suite, "ntrename", test_ntrename); return suite; diff --git a/source4/torture/raw/search.c b/source4/torture/raw/search.c index 0242b9c5450..725ed261aac 100644 --- a/source4/torture/raw/search.c +++ b/source4/torture/raw/search.c @@ -708,6 +708,16 @@ static bool test_many_files(struct torture_context *tctx, for (t=0;t<ARRAY_SIZE(search_types);t++) { ZERO_STRUCT(result); + + if ((search_types[t].cont_type == CONT_RESUME_KEY) && + (search_types[t].data_level != RAW_SEARCH_DATA_SEARCH) && + torture_setting_bool(tctx, "samba3", false)) { + torture_comment(tctx, + "SKIP: Continue %s via %s\n", + search_types[t].name, search_types[t].cont_name); + continue; + } + result.tctx = talloc_new(tctx); torture_comment(tctx, diff --git a/source4/torture/raw/streams.c b/source4/torture/raw/streams.c index ca6b488af5a..1dab36c28b2 100644 --- a/source4/torture/raw/streams.c +++ b/source4/torture/raw/streams.c @@ -356,22 +356,24 @@ static bool test_stream_sharemodes(struct torture_context *tctx, * A different stream does not give a sharing violation */ + io.ntcreatex.in.fname = sname2; + status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); - fnum1 = io.ntcreatex.out.file.fnum; + fnum2 = io.ntcreatex.out.file.fnum; /* * ... whereas the same stream does with unchanged access/share_access * flags */ + io.ntcreatex.in.fname = sname1; io.ntcreatex.in.open_disposition = 0; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); io.ntcreatex.in.fname = sname2; status = smb_raw_open(cli->tree, mem_ctx, &io); - CHECK_STATUS(status, NT_STATUS_OK); - fnum2 = io.ntcreatex.out.file.fnum; + CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); done: if (fnum1 != -1) smbcli_close(cli->tree, fnum1); @@ -558,7 +560,9 @@ bool torture_raw_streams(struct torture_context *torture, } ret &= test_stream_io(torture, cli, torture); + smb_raw_exit(cli->session); ret &= test_stream_sharemodes(torture, cli, torture); + smb_raw_exit(cli->session); if (!torture_setting_bool(torture, "samba4", false)) { ret &= test_stream_delete(torture, cli, torture); } diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index 60d022fbea7..04d13a97c1c 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -295,8 +295,8 @@ static bool test_LookupNames_wellknown(struct dcerpc_pipe *p, ret &= test_LookupNames(p, mem_ctx, handle, &tnames); name.name.string = "BUILTIN\\Administrators"; - ret &= test_LookupNames(p, mem_ctx, handle, &tnames); name.sid_type = SID_NAME_ALIAS; + ret &= test_LookupNames(p, mem_ctx, handle, &tnames); name.name.string = "SYSTEM"; name.sid_type = SID_NAME_WKN_GRP; diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c index 95252e7397f..204a9f2865c 100644 --- a/source4/torture/rpc/samba3rpc.c +++ b/source4/torture/rpc/samba3rpc.c @@ -47,6 +47,7 @@ #include "libcli/smb_composite/smb_composite.h" #include "libcli/auth/libcli_auth.h" #include "lib/crypto/crypto.h" +#include "auth/ntlmssp/ntlmssp.h" #include "libcli/security/proto.h" #include "param/param.h" #include "lib/registry/registry.h" @@ -682,6 +683,7 @@ static bool join3(struct smbcli_state *cli, struct dcerpc_pipe *samr_pipe; struct policy_handle *wks_handle; bool ret = false; + NTTIME last_password_change; if ((mem_ctx = talloc_init("join3")) == NULL) { d_printf("talloc_init failed\n"); @@ -701,6 +703,22 @@ static bool join3(struct smbcli_state *cli, goto done; } + { + struct samr_QueryUserInfo q; + + q.in.user_handle = wks_handle; + q.in.level = 21; + + status = dcerpc_samr_QueryUserInfo(samr_pipe, mem_ctx, &q); + if (!NT_STATUS_IS_OK(status)) { + d_printf("(%s) QueryUserInfo failed: %s\n", + __location__, nt_errstr(status)); + goto done; + } + + last_password_change = q.out.info->info21.last_password_change; + } + cli_credentials_set_domain(wks_creds, dom_name, CRED_SPECIFIED); if (use_level25) { @@ -794,6 +812,39 @@ static bool join3(struct smbcli_state *cli, } } + { + struct samr_QueryUserInfo q; + + q.in.user_handle = wks_handle; + q.in.level = 21; + + status = dcerpc_samr_QueryUserInfo(samr_pipe, mem_ctx, &q); + if (!NT_STATUS_IS_OK(status)) { + d_printf("(%s) QueryUserInfo failed: %s\n", + __location__, nt_errstr(status)); + goto done; + } + + if (use_level25) { + if (last_password_change + == q.out.info->info21.last_password_change) { + d_printf("(%s) last_password_change unchanged " + "during join, level25 must change " + "it\n", __location__); + goto done; + } + } + else { + if (last_password_change + != q.out.info->info21.last_password_change) { + d_printf("(%s) last_password_change changed " + "during join, level24 doesn't " + "change it\n", __location__); + goto done; + } + } + } + ret = true; done: @@ -1321,6 +1372,8 @@ bool torture_samba3_sessionkey(struct torture_context *torture) goto done; } + cli_credentials_set_workstation(anon_creds, wks_name, CRED_SPECIFIED); + ret = true; if (!torture_setting_bool(torture, "samba3", false)) { diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index 1d6ec433998..55c75ba270e 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -2332,9 +2332,15 @@ static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx status = dcerpc_samr_CreateDomAlias(p, tctx, &r); - if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { - printf("Server refused create of '%s'\n", r.in.alias_name->string); - return true; + if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) { + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + printf("Server correctly refused create of '%s'\n", r.in.alias_name->string); + return true; + } else { + printf("Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string, + nt_errstr(status)); + return false; + } } if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) { @@ -2515,7 +2521,8 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle *domain_handle, - struct policy_handle *user_handle_out, + struct policy_handle *user_handle_out, + struct dom_sid *domain_sid, enum torture_samr_choice which_ops) { @@ -2546,10 +2553,15 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx, status = dcerpc_samr_CreateUser(p, user_ctx, &r); - if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { - printf("Server refused create of '%s': %s\n", r.in.account_name->string, nt_errstr(status)); - talloc_free(user_ctx); - return true; + if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) { + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + printf("Server correctly refused create of '%s'\n", r.in.account_name->string); + return true; + } else { + printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string, + nt_errstr(status)); + return false; + } } if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { @@ -2610,7 +2622,9 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx, static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx, - struct policy_handle *domain_handle, enum torture_samr_choice which_ops) + struct policy_handle *domain_handle, + struct dom_sid *domain_sid, + enum torture_samr_choice which_ops) { NTSTATUS status; struct samr_CreateUser2 r; @@ -2663,12 +2677,19 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx status = dcerpc_samr_CreateUser2(p, user_ctx, &r); - if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { - talloc_free(user_ctx); - printf("Server refused create of '%s'\n", r.in.account_name->string); - continue; + if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) { + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + printf("Server correctly refused create of '%s'\n", r.in.account_name->string); + continue; + } else { + printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string, + nt_errstr(status)); + ret = false; + continue; + } + } - } else if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) { talloc_free(user_ctx); ret = false; @@ -3893,6 +3914,7 @@ static bool test_GroupList(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, } if (!q1.out.sam) { + printf("EnumDomainGroups failed to return q1.out.sam\n"); return false; } @@ -4138,7 +4160,9 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t static bool test_CreateDomainGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct policy_handle *domain_handle, struct policy_handle *group_handle) + struct policy_handle *domain_handle, + struct policy_handle *group_handle, + struct dom_sid *domain_sid) { NTSTATUS status; struct samr_CreateDomainGroup r; @@ -4158,15 +4182,19 @@ static bool test_CreateDomainGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, status = dcerpc_samr_CreateDomainGroup(p, mem_ctx, &r); - if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { - printf("Server refused create of '%s'\n", r.in.name->string); - ZERO_STRUCTP(group_handle); - return true; + if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(mem_ctx, SID_BUILTIN))) { + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + printf("Server correctly refused create of '%s'\n", r.in.name->string); + return true; + } else { + printf("Server should have refused create of '%s', got %s instead\n", r.in.name->string, + nt_errstr(status)); + return false; + } } if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) { if (!test_DeleteGroup_byname(p, mem_ctx, domain_handle, r.in.name->string)) { - printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string, nt_errstr(status)); return false; @@ -4244,7 +4272,7 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx, ZERO_STRUCT(group_handle); ZERO_STRUCT(domain_handle); - printf("Testing OpenDomain\n"); + printf("Testing OpenDomain of %s\n", dom_sid_string(tctx, sid)); r.in.connect_handle = handle; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; @@ -4264,17 +4292,23 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx, switch (which_ops) { case TORTURE_SAMR_USER_ATTRIBUTES: case TORTURE_SAMR_PASSWORDS: - ret &= test_CreateUser2(p, tctx, &domain_handle, which_ops); - ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, which_ops); + ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops); + ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops); /* This test needs 'complex' users to validate */ ret &= test_QueryDisplayInfo(p, tctx, &domain_handle); + if (!ret) { + printf("Testing PASSWORDS or ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid)); + } break; case TORTURE_SAMR_OTHER: - ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, which_ops); + ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops); + if (!ret) { + printf("Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid)); + } ret &= test_QuerySecurity(p, tctx, &domain_handle); ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle); ret &= test_CreateAlias(p, tctx, &domain_handle, &alias_handle, sid); - ret &= test_CreateDomainGroup(p, tctx, &domain_handle, &group_handle); + ret &= test_CreateDomainGroup(p, tctx, &domain_handle, &group_handle, sid); ret &= test_QueryDomainInfo(p, tctx, &domain_handle); ret &= test_QueryDomainInfo2(p, tctx, &domain_handle); ret &= test_EnumDomainUsers(p, tctx, &domain_handle); @@ -4295,6 +4329,9 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx, ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle); ret &= test_RidToSid(p, tctx, sid, &domain_handle); ret &= test_GetBootKeyInformation(p, tctx, &domain_handle); + if (!ret) { + printf("Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid)); + } break; } diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c index 3144fe91b10..0c9a41fd70d 100644 --- a/source4/utils/ntlm_auth.c +++ b/source4/utils/ntlm_auth.c @@ -285,7 +285,7 @@ static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mod DATA_BLOB in; if (strlen(buf) < 2) { DEBUG(1, ("query [%s] invalid", buf)); - mux_printf(mux_id, "BH\n"); + mux_printf(mux_id, "BH Query invalid\n"); return; } @@ -302,7 +302,7 @@ static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mod if (*password == NULL) { DEBUG(1, ("Out of memory\n")); - mux_printf(mux_id, "BH\n"); + mux_printf(mux_id, "BH Out of memory\n"); data_blob_free(&in); return; } @@ -312,7 +312,7 @@ static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mod return; } DEBUG(1, ("Asked for (and expected) a password\n")); - mux_printf(mux_id, "BH\n"); + mux_printf(mux_id, "BH Expected a password\n"); data_blob_free(&in); } @@ -420,7 +420,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, if (strlen(buf) < 2) { DEBUG(1, ("query [%s] invalid", buf)); - mux_printf(mux_id, "BH\n"); + mux_printf(mux_id, "BH Query invalid\n"); return; } @@ -444,7 +444,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, } } else if ( (strncmp(buf, "OK", 2) == 0)) { /* Just return BH, like ntlm_auth from Samba 3 does. */ - mux_printf(mux_id, "BH\n"); + mux_printf(mux_id, "BH Command expected\n"); data_blob_free(&in); return; } else if ( (strncmp(buf, "TT ", 3) != 0) && @@ -456,7 +456,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, (strncmp(buf, "GK", 2) != 0) && (strncmp(buf, "GF", 2) != 0)) { DEBUG(1, ("SPNEGO request [%s] invalid\n", buf)); - mux_printf(mux_id, "BH\n"); + mux_printf(mux_id, "BH SPNEGO request invalid\n"); data_blob_free(&in); return; } @@ -545,7 +545,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("GENSEC mech failed to start: %s\n", nt_errstr(nt_status))); - mux_printf(mux_id, "BH\n"); + mux_printf(mux_id, "BH GENSEC mech failed to start\n"); return; } @@ -655,11 +655,11 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) { - reply_code = "BH"; + reply_code = "BH NT_STATUS_ACCESS_DENIED"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status))); } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_UNSUCCESSFUL)) { - reply_code = "BH"; + reply_code = "BH NT_STATUS_UNSUCCESSFUL"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status))); } else if (!NT_STATUS_IS_OK(nt_status)) { @@ -671,7 +671,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, nt_status = gensec_session_info(state->gensec_state, &session_info); if (!NT_STATUS_IS_OK(nt_status)) { - reply_code = "BH"; + reply_code = "BH Failed to retrive session info"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC failed to retreive the session info: %s\n", nt_errstr(nt_status))); } else { diff --git a/source4/winbind/config.mk b/source4/winbind/config.mk index d303d209015..3c5b740e68a 100644 --- a/source4/winbind/config.mk +++ b/source4/winbind/config.mk @@ -28,6 +28,8 @@ WINBIND_OBJ_FILES = $(addprefix winbind/, \ wb_dom_info_trusted.o \ wb_sid2domain.o \ wb_name2domain.o \ + wb_sids2xids.o \ + wb_xids2sids.o \ wb_gid2sid.o \ wb_sid2uid.o \ wb_sid2gid.o \ diff --git a/source4/winbind/idmap.c b/source4/winbind/idmap.c index 3372ad51eea..de8a43ec02c 100644 --- a/source4/winbind/idmap.c +++ b/source4/winbind/idmap.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. - Map SIDs to uids/gids and back + Map SIDs to unixids and back Copyright (C) Kai Blin 2008 @@ -177,39 +177,46 @@ struct idmap_context *idmap_init(TALLOC_CTX *mem_ctx, return NULL; } + idmap_ctx->unix_groups_sid = dom_sid_parse_talloc(mem_ctx, "S-1-22-2"); + if (idmap_ctx->unix_groups_sid == NULL) { + return NULL; + } + + idmap_ctx->unix_users_sid = dom_sid_parse_talloc(mem_ctx, "S-1-22-1"); + if (idmap_ctx->unix_users_sid == NULL) { + return NULL; + } + return idmap_ctx; } /** - * Convert a uid to the corresponding SID + * Convert an unixid to the corresponding SID * * \param idmap_ctx idmap context to use * \param mem_ctx talloc context the memory for the struct dom_sid is allocated * from. - * \param uid Unix uid to map to a SID - * \param sid Pointer that will take the struct dom_sid pointer if the mapping + * \param unixid pointer to a unixid struct to convert + * \param sid pointer that will take the struct dom_sid pointer if the mapping * succeeds. * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping not * possible or some other NTSTATUS that is more descriptive on failure. */ -NTSTATUS idmap_uid_to_sid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, - const uid_t uid, struct dom_sid **sid) +NTSTATUS idmap_xid_to_sid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, + const struct unixid *unixid, struct dom_sid **sid) { int ret; NTSTATUS status = NT_STATUS_NONE_MAPPED; struct ldb_context *ldb = idmap_ctx->ldb_ctx; - struct ldb_message *msg; struct ldb_result *res = NULL; - int trans = -1; - uid_t low, high; - char *sid_string, *uid_string; - struct dom_sid *unix_users_sid, *new_sid; + uint32_t low, high; + struct dom_sid *unix_sid, *new_sid; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); ret = ldb_search_exp_fmt(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, - NULL, "(&(objectClass=sidMap)(uidNumber=%u))", - uid); + NULL, "(&(objectClass=sidMap)(xidNumber=%u))", + unixid->id); if (ret != LDB_SUCCESS) { DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb))); status = NT_STATUS_NONE_MAPPED; @@ -228,19 +235,13 @@ NTSTATUS idmap_uid_to_sid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - DEBUG(6, ("uid not found in idmap db, trying to allocate SID.\n")); - - trans = ldb_transaction_start(ldb); - if (trans != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } + DEBUG(6, ("xid not found in idmap db, trying to allocate SID.\n")); /* Now redo the search to make sure noone added a mapping for that SID * while we weren't looking.*/ ret = ldb_search_exp_fmt(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, - NULL, "(&(objectClass=sidMap)(uidNumber=%u))", - uid); + NULL, "(&(objectClass=sidMap)(xidNumber=%u))", + unixid->id); if (ret != LDB_SUCCESS) { DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb))); status = NT_STATUS_NONE_MAPPED; @@ -260,285 +261,58 @@ NTSTATUS idmap_uid_to_sid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, goto failed; } - if (uid >= low && uid <= high) { - /* An existing user would have been mapped before */ - status = NT_STATUS_NO_SUCH_USER; + if (unixid->id >= low && unixid->id <= high) { + /* An existing xid would have been mapped before */ + status = NT_STATUS_NONE_MAPPED; goto failed; } /* For local users, we just create a rid = uid +1, so root doesn't end * up with a 0 rid */ - unix_users_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-22-1"); - if (unix_users_sid == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - new_sid = dom_sid_add_rid(mem_ctx, unix_users_sid, uid + 1); - if (new_sid == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - sid_string = dom_sid_string(tmp_ctx, new_sid); - if (sid_string == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - uid_string = talloc_asprintf(tmp_ctx, "%u", uid); - if (uid_string == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - msg = ldb_msg_new(tmp_ctx); - if (msg == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s", sid_string); - if (msg->dn == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - ret = ldb_msg_add_string(msg, "uidNumber", uid_string); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = idmap_msg_add_dom_sid(idmap_ctx, tmp_ctx, msg, "objectSid", - new_sid); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = ldb_msg_add_string(msg, "objectClass", "sidMap"); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = ldb_msg_add_string(msg, "cn", sid_string); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = ldb_add(ldb, msg); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - trans = ldb_transaction_commit(ldb); - if (trans != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - *sid = new_sid; - talloc_free(tmp_ctx); - return NT_STATUS_OK; - -failed: - if (trans == LDB_SUCCESS) ldb_transaction_cancel(ldb); - talloc_free(tmp_ctx); - return status; -} - -/** - * Map a Unix gid to the corresponding SID - * - * \param idmap_ctx idmap context to use - * \param mem_ctx talloc context the memory for the struct dom_sid is allocated - * from. - * \param gid Unix gid to map to a SID - * \param sid Pointer that will take the struct dom_sid pointer if mapping - * succeeds. - * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping not - * possible or some other NTSTATUS that is more descriptive on failure. - */ -NTSTATUS idmap_gid_to_sid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, - const gid_t gid, struct dom_sid **sid) -{ - int ret; - NTSTATUS status = NT_STATUS_NONE_MAPPED; - struct ldb_context *ldb = idmap_ctx->ldb_ctx; - struct ldb_message *msg; - struct ldb_result *res = NULL; - int trans = -1; - gid_t low, high; - char *sid_string, *gid_string; - struct dom_sid *unix_groups_sid, *new_sid; - TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); - - ret = ldb_search_exp_fmt(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, - NULL, "(&(objectClass=sidMap)(gidNumber=%u))", gid); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb))); - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - if (res->count == 1) { - *sid = idmap_msg_get_dom_sid(mem_ctx, res->msgs[0], - "objectSid"); - if (*sid == NULL) { - DEBUG(1, ("Failed to get sid from db: %u\n", ret)); - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - /* No change, so cancel the transaction */ - ldb_transaction_cancel(ldb); - talloc_free(tmp_ctx); - return NT_STATUS_OK; - } - - DEBUG(6, ("gid not found in idmap db, trying to allocate SID.\n")); - - trans = ldb_transaction_start(ldb); - if (trans != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - /* Now redo the search to make sure noone added a mapping for that SID - * while we weren't looking.*/ - ret = ldb_search_exp_fmt(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, - NULL, "(&(objectClass=sidMap)(gidNumber=%u))", - gid); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb))); - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - if (res->count > 0) { - DEBUG(1, ("sidMap modified while trying to add a mapping.\n")); - status = NT_STATUS_RETRY; - goto failed; - } - - ret = idmap_get_bounds(idmap_ctx, &low, &high); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to get id bounds from db: %u\n", ret)); - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - if (gid >= low && gid <= high) { - /* An existing group would have been mapped before */ - status = NT_STATUS_NO_SUCH_USER; - goto failed; + if (unixid->type == ID_TYPE_UID) { + unix_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-22-1"); + } else { + unix_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-22-2"); } - - /* For local groups, we just create a rid = gid +1, so root doesn't end - * up with a 0 rid */ - unix_groups_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-22-2"); - if (unix_groups_sid == NULL) { + if (unix_sid == NULL) { status = NT_STATUS_NO_MEMORY; goto failed; } - new_sid = dom_sid_add_rid(mem_ctx, unix_groups_sid, gid + 1); + new_sid = dom_sid_add_rid(mem_ctx, unix_sid, unixid->id + 1); if (new_sid == NULL) { status = NT_STATUS_NO_MEMORY; goto failed; } - sid_string = dom_sid_string(tmp_ctx, new_sid); - if (sid_string == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - gid_string = talloc_asprintf(tmp_ctx, "%u", gid); - if (gid_string == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - msg = ldb_msg_new(tmp_ctx); - if (msg == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s", sid_string); - if (msg->dn == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - ret = ldb_msg_add_string(msg, "gidNumber", gid_string); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = idmap_msg_add_dom_sid(idmap_ctx, tmp_ctx, msg, "objectSid", - new_sid); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = ldb_msg_add_string(msg, "objectClass", "sidMap"); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = ldb_msg_add_string(msg, "cn", sid_string); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = ldb_add(ldb, msg); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - trans = ldb_transaction_commit(ldb); - if (trans != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - *sid = new_sid; talloc_free(tmp_ctx); return NT_STATUS_OK; failed: - if (trans == LDB_SUCCESS) ldb_transaction_cancel(ldb); talloc_free(tmp_ctx); return status; } + /** - * Map a SID to a Unix uid. + * Map a SID to an unixid struct. * * If no mapping exists, a new mapping will be created. * * \todo Check if SIDs can be resolved if lp_idmap_trusted_only() == true + * \todo Fix backwards compatibility for Samba3 * * \param idmap_ctx idmap context to use * \param mem_ctx talloc context to use - * \param sid SID to map to a Unix uid - * \param uid pointer to receive the mapped uid + * \param sid SID to map to an unixid struct + * \param unixid pointer to a unixid struct pointer * \return NT_STATUS_OK on success, NT_STATUS_INVALID_SID if the sid is not from * a trusted domain and idmap trusted only = true, NT_STATUS_NONE_MAPPED if the * mapping failed. */ -NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, - const struct dom_sid *sid, uid_t *uid) +NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, + const struct dom_sid *sid, struct unixid **unixid) { int ret; NTSTATUS status = NT_STATUS_NONE_MAPPED; @@ -547,8 +321,8 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, struct ldb_message *hwm_msg, *map_msg; struct ldb_result *res = NULL; int trans; - uid_t low, high, hwm, new_uid; - char *sid_string, *uid_string, *hwm_string; + uint32_t low, high, hwm, new_xid; + char *sid_string, *unixid_string, *hwm_string; bool hwm_entry_exists; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); @@ -562,20 +336,65 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, } if (res->count == 1) { - new_uid = ldb_msg_find_attr_as_uint(res->msgs[0], "uidNumber", + new_xid = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber", -1); - if (new_uid == (uid_t) -1) { - DEBUG(1, ("Invalid uid mapping.\n")); + if (new_xid == (uint32_t) -1) { + DEBUG(1, ("Invalid xid mapping.\n")); status = NT_STATUS_NONE_MAPPED; goto failed; } - *uid = new_uid; + + *unixid = talloc(mem_ctx, struct unixid); + if (*unixid == NULL) { + status = NT_STATUS_NO_MEMORY; + goto failed; + } + + (*unixid)->id = new_xid; + (*unixid)->type = ID_TYPE_BOTH; + talloc_free(tmp_ctx); return NT_STATUS_OK; } DEBUG(6, ("No existing mapping found, attempting to create one.\n")); + if (dom_sid_in_domain(idmap_ctx->unix_users_sid, sid)) { + uint32_t rid; + DEBUG(6, ("This is a local unix uid, just calculate that.\n")); + status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid); + if (!NT_STATUS_IS_OK(status)) goto failed; + + *unixid = talloc(mem_ctx, struct unixid); + if (*unixid == NULL) { + status = NT_STATUS_NO_MEMORY; + goto failed; + } + (*unixid)->id = rid - 1; + (*unixid)->type = ID_TYPE_UID; + + talloc_free(tmp_ctx); + return NT_STATUS_OK; + } + + if (dom_sid_in_domain(idmap_ctx->unix_groups_sid, sid)) { + uint32_t rid; + DEBUG(6, ("This is a local unix gid, just calculate that.\n")); + status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid); + if (!NT_STATUS_IS_OK(status)) goto failed; + + *unixid = talloc(mem_ctx, struct unixid); + if (*unixid == NULL) { + status = NT_STATUS_NO_MEMORY; + goto failed; + } + (*unixid)->id = rid - 1; + (*unixid)->type = ID_TYPE_GID; + + talloc_free(tmp_ctx); + return NT_STATUS_OK; + } + trans = ldb_transaction_start(ldb); if (trans != LDB_SUCCESS) { status = NT_STATUS_NONE_MAPPED; @@ -629,8 +448,8 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, goto failed; } - hwm = ldb_msg_find_attr_as_uint(res->msgs[0], "uidNumber", -1); - if (hwm == (uid_t)-1) { + hwm = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber", -1); + if (hwm == (uint32_t)-1) { hwm = low; hwm_entry_exists = false; } else { @@ -638,7 +457,7 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, } if (hwm > high) { - DEBUG(1, ("Out of uids to allocate.\n")); + DEBUG(1, ("Out of xids to allocate.\n")); status = NT_STATUS_NONE_MAPPED; goto failed; } @@ -652,7 +471,7 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, hwm_msg->dn = dn; - new_uid = hwm; + new_xid = hwm; hwm++; hwm_string = talloc_asprintf(tmp_ctx, "%u", hwm); @@ -667,8 +486,8 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, goto failed; } - uid_string = talloc_asprintf(tmp_ctx, "%u", new_uid); - if (uid_string == NULL) { + unixid_string = talloc_asprintf(tmp_ctx, "%u", new_xid); + if (unixid_string == NULL) { status = NT_STATUS_NO_MEMORY; goto failed; } @@ -696,7 +515,7 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, els[0].num_values = 1; els[0].values = &vals[0]; els[0].flags = LDB_FLAG_MOD_DELETE; - els[0].name = talloc_strdup(tmp_ctx, "uidNumber"); + els[0].name = talloc_strdup(tmp_ctx, "xidNumber"); if (els[0].name == NULL) { status = NT_STATUS_NO_MEMORY; goto failed; @@ -707,19 +526,19 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, els[1].flags = LDB_FLAG_MOD_ADD; els[1].name = els[0].name; - vals[0].data = (uint8_t *)uid_string; - vals[0].length = strlen(uid_string); + vals[0].data = (uint8_t *)unixid_string; + vals[0].length = strlen(unixid_string); vals[1].data = (uint8_t *)hwm_string; vals[1].length = strlen(hwm_string); } else { - ret = ldb_msg_add_empty(hwm_msg, "uidNumber", LDB_FLAG_MOD_ADD, + ret = ldb_msg_add_empty(hwm_msg, "xidNumber", LDB_FLAG_MOD_ADD, NULL); if (ret != LDB_SUCCESS) { status = NT_STATUS_NONE_MAPPED; goto failed; } - ret = ldb_msg_add_string(hwm_msg, "uidNumber", hwm_string); + ret = ldb_msg_add_string(hwm_msg, "xidNumber", hwm_string); if (ret != LDB_SUCCESS) { status = NT_STATUS_NONE_MAPPED; @@ -729,7 +548,7 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, ret = ldb_modify(ldb, hwm_msg); if (ret != LDB_SUCCESS) { - DEBUG(1, ("Updating the uid high water mark failed: %s\n", + DEBUG(1, ("Updating the xid high water mark failed: %s\n", ldb_errstring(ldb))); status = NT_STATUS_NONE_MAPPED; goto failed; @@ -747,7 +566,7 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, goto failed; } - ret = ldb_msg_add_string(map_msg, "uidNumber", uid_string); + ret = ldb_msg_add_string(map_msg, "xidNumber", unixid_string); if (ret != LDB_SUCCESS) { status = NT_STATUS_NONE_MAPPED; goto failed; @@ -786,7 +605,14 @@ NTSTATUS idmap_sid_to_uid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, goto failed; } - *uid = new_uid; + *unixid = talloc(mem_ctx, struct unixid); + if (*unixid == NULL) { + status = NT_STATUS_NO_MEMORY; + goto failed; + } + + (*unixid)->id = new_xid; + (*unixid)->type = ID_TYPE_BOTH; talloc_free(tmp_ctx); return NT_STATUS_OK; @@ -797,276 +623,92 @@ failed: } /** - * Map a SID to a Unix gid. - * - * If no mapping exist, a new mapping will be created. - * - * \todo Check if SID resolve when lp_idmap_trusted_only() == true + * Convert an array of unixids to the corresponding array of SIDs * * \param idmap_ctx idmap context to use - * \param mem_ctx talloc context to use - * \param sid SID to map to a Unix gid - * \param gid pointer to receive the mapped gid - * \return NT_STATUS_OK on success, NT_STATUS_INVALID_SID if the sid is not from - * a trusted domain and idmap trusted only = true, NT_STATUS_NONE_MAPPED if the - * mapping failed. + * \param mem_ctx talloc context the memory for the dom_sids is allocated + * from. + * \param count length of id_mapping array. + * \param id array of id_mappings. + * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping is not + * possible at all, NT_STATUS_SOME_UNMAPPED if some mappings worked and some + * did not. */ -NTSTATUS idmap_sid_to_gid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx, - const struct dom_sid *sid, gid_t *gid) -{ - int ret; - NTSTATUS status = NT_STATUS_NONE_MAPPED; - struct ldb_context *ldb = idmap_ctx->ldb_ctx; - struct ldb_dn *dn; - struct ldb_message *hwm_msg, *map_msg; - struct ldb_result *res = NULL; - int trans = -1; - gid_t low, high, hwm, new_gid; - char *sid_string, *gid_string, *hwm_string; - bool hwm_entry_exists; - TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); - ret = ldb_search_exp_fmt(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, - NULL, "(&(objectClass=sidMap)(objectSid=%s))", - ldap_encode_ndr_dom_sid(tmp_ctx, sid)); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb))); - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - if (res->count == 1) { - new_gid = ldb_msg_find_attr_as_uint(res->msgs[0], "gidNumber", - -1); - if (new_gid == (gid_t) -1) { - DEBUG(1, ("Invalid gid mapping.\n")); - status = NT_STATUS_NONE_MAPPED; - goto failed; +NTSTATUS idmap_xids_to_sids(struct idmap_context *idmap_ctx, + TALLOC_CTX *mem_ctx, int count, + struct id_mapping *id) +{ + int i; + int error_count = 0; + + for (i = 0; i < count; ++i) { + id[i].status = idmap_xid_to_sid(idmap_ctx, mem_ctx, + id[i].unixid, &id[i].sid); + if (NT_STATUS_EQUAL(id[i].status, NT_STATUS_RETRY)) { + id[i].status = idmap_xid_to_sid(idmap_ctx, mem_ctx, + id[i].unixid, + &id[i].sid); + } + if (!NT_STATUS_IS_OK(id[i].status)) { + DEBUG(1, ("idmapping failed for id[%d]\n", i)); + error_count++; } - *gid = new_gid; - talloc_free(tmp_ctx); - return NT_STATUS_OK; - } - - DEBUG(6, ("No existing mapping found, attempting to create one.\n")); - - trans = ldb_transaction_start(ldb); - if (trans != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - /* Redo the search to make sure noone changed the mapping while we - * weren't looking */ - ret = ldb_search_exp_fmt(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, - NULL, "(&(objectClass=sidMap)(objectSid=%s))", - ldap_encode_ndr_dom_sid(tmp_ctx, sid)); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb))); - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - if (res->count > 0) { - DEBUG(1, ("Database changed while trying to add a sidmap.\n")); - status = NT_STATUS_RETRY; - goto failed; - } - - /*FIXME: if lp_idmap_trusted_only() == true, check if SID can be - * resolved here. */ - - ret = idmap_get_bounds(idmap_ctx, &low, &high); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG"); - if (dn == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, NULL, &res); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb))); - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - talloc_steal(tmp_ctx, res); - - if (res->count != 1) { - DEBUG(1, ("No CN=CONFIG record, idmap database is broken.\n")); - status = NT_STATUS_NONE_MAPPED; - goto failed; } - hwm = ldb_msg_find_attr_as_uint(res->msgs[0], "gidNumber", -1); - if (hwm == (gid_t)-1) { - hwm = low; - hwm_entry_exists = false; + if (error_count == count) { + /* Mapping did not work at all. */ + return NT_STATUS_NONE_MAPPED; + } else if (error_count > 0) { + /* Some mappings worked, some did not. */ + return STATUS_SOME_UNMAPPED; } else { - hwm_entry_exists = true; - } - - if (hwm > high) { - DEBUG(1, ("Out of gids to allocate.\n")); - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - hwm_msg = ldb_msg_new(tmp_ctx); - if (hwm_msg == NULL) { - DEBUG(1, ("Out of memory when creating ldb_message\n")); - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - hwm_msg->dn = dn; - - new_gid = hwm; - hwm++; - - hwm_string = talloc_asprintf(tmp_ctx, "%u", hwm); - if (hwm_string == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - sid_string = dom_sid_string(tmp_ctx, sid); - if (sid_string == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - gid_string = talloc_asprintf(tmp_ctx, "%u", new_gid); - if (gid_string == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; + return NT_STATUS_OK; } +} - if (hwm_entry_exists) { - struct ldb_message_element *els; - struct ldb_val *vals; - - /* We're modifying the entry, not just adding a new one. */ - els = talloc_array(tmp_ctx, struct ldb_message_element, 2); - if (els == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - vals = talloc_array(tmp_ctx, struct ldb_val, 2); - if (els == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - hwm_msg->num_elements = 2; - hwm_msg->elements = els; - - els[0].num_values = 1; - els[0].values = &vals[0]; - els[0].flags = LDB_FLAG_MOD_DELETE; - els[0].name = talloc_strdup(tmp_ctx, "gidNumber"); - if (els[0].name == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - els[1].num_values = 1; - els[1].values = &vals[1]; - els[1].flags = LDB_FLAG_MOD_ADD; - els[1].name = els[0].name; +/** + * Convert an array of SIDs to the corresponding array of unixids + * + * \param idmap_ctx idmap context to use + * \param mem_ctx talloc context the memory for the unixids is allocated + * from. + * \param count length of id_mapping array. + * \param id array of id_mappings. + * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping is not + * possible at all, NT_STATUS_SOME_UNMAPPED if some mappings worked and some + * did not. + */ - vals[0].data = (uint8_t *)gid_string; - vals[0].length = strlen(gid_string); - vals[1].data = (uint8_t *)hwm_string; - vals[1].length = strlen(hwm_string); - } else { - ret = ldb_msg_add_empty(hwm_msg, "gidNumber", LDB_FLAG_MOD_ADD, - NULL); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; +NTSTATUS idmap_sids_to_xids(struct idmap_context *idmap_ctx, + TALLOC_CTX *mem_ctx, int count, + struct id_mapping *id) +{ + int i; + int error_count = 0; + + for (i = 0; i < count; ++i) { + id[i].status = idmap_sid_to_xid(idmap_ctx, mem_ctx, + id[i].sid, &id[i].unixid); + if (NT_STATUS_EQUAL(id[i].status, NT_STATUS_RETRY)) { + id[i].status = idmap_sid_to_xid(idmap_ctx, mem_ctx, + id[i].sid, + &id[i].unixid); } - - ret = ldb_msg_add_string(hwm_msg, "gidNumber", hwm_string); - if (ret != LDB_SUCCESS) - { - status = NT_STATUS_NONE_MAPPED; - goto failed; + if (!NT_STATUS_IS_OK(id[i].status)) { + DEBUG(1, ("idmapping failed for id[%d]\n", i)); + error_count++; } } - ret = ldb_modify(ldb, hwm_msg); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Updating the gid high water mark failed: %s\n", - ldb_errstring(ldb))); - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - map_msg = ldb_msg_new(tmp_ctx); - if (map_msg == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - map_msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s", sid_string); - if (map_msg->dn == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - ret = ldb_msg_add_string(map_msg, "gidNumber", gid_string); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = idmap_msg_add_dom_sid(idmap_ctx, tmp_ctx, map_msg, "objectSid", - sid); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = ldb_msg_add_string(map_msg, "objectClass", "sidMap"); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = ldb_msg_add_string(map_msg, "cn", sid_string); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = ldb_add(ldb, map_msg); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Adding a sidmap failed: %s\n", ldb_errstring(ldb))); - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - trans = ldb_transaction_commit(ldb); - if (trans != LDB_SUCCESS) { - DEBUG(1, ("Transaction failed: %s\n", ldb_errstring(ldb))); - status = NT_STATUS_NONE_MAPPED; - goto failed; + if (error_count == count) { + /* Mapping did not work at all. */ + return NT_STATUS_NONE_MAPPED; + } else if (error_count > 0) { + /* Some mappings worked, some did not. */ + return STATUS_SOME_UNMAPPED; + } else { + return NT_STATUS_OK; } - - *gid = new_gid; - talloc_free(tmp_ctx); - return NT_STATUS_OK; - -failed: - if (trans == LDB_SUCCESS) ldb_transaction_cancel(ldb); - talloc_free(tmp_ctx); - return status; } diff --git a/source4/winbind/idmap.h b/source4/winbind/idmap.h index 8781819be02..045d50c568b 100644 --- a/source4/winbind/idmap.h +++ b/source4/winbind/idmap.h @@ -25,6 +25,26 @@ struct idmap_context { struct loadparm_context *lp_ctx; struct ldb_context *ldb_ctx; + struct dom_sid *unix_groups_sid; + struct dom_sid *unix_users_sid; +}; + +enum id_type { + ID_TYPE_NOT_SPECIFIED = 0, + ID_TYPE_UID, + ID_TYPE_GID, + ID_TYPE_BOTH +}; + +struct unixid { + uint32_t id; + enum id_type type; +}; + +struct id_mapping { + struct unixid *unixid; + struct dom_sid *sid; + NTSTATUS status; }; #include "winbind/idmap_proto.h" diff --git a/source4/winbind/wb_gid2sid.c b/source4/winbind/wb_gid2sid.c index f2577029aab..834d869845e 100644 --- a/source4/winbind/wb_gid2sid.c +++ b/source4/winbind/wb_gid2sid.c @@ -3,7 +3,7 @@ Command backend for wbinfo -G - Copyright (C) Kai Blin 2007 + Copyright (C) 2007-2008 Kai Blin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,35 +33,60 @@ struct gid2sid_state { struct dom_sid *sid; }; +static void gid2sid_recv_sid(struct composite_context *ctx); + struct composite_context *wb_gid2sid_send(TALLOC_CTX *mem_ctx, struct wbsrv_service *service, gid_t gid) { - struct composite_context *result; + struct composite_context *result, *ctx; struct gid2sid_state *state; + struct unixid *unixid; + struct id_mapping *ids; DEBUG(5, ("wb_gid2sid_send called\n")); result = composite_create(mem_ctx, service->task->event_ctx); if (!result) return NULL; - state = talloc(mem_ctx, struct gid2sid_state); + state = talloc(result, struct gid2sid_state); if (composite_nomem(state, result)) return result; state->ctx = result; result->private_data = state; state->service = service; - state->ctx->status = idmap_gid_to_sid(service->idmap_ctx, mem_ctx, gid, - &state->sid); - if (NT_STATUS_EQUAL(state->ctx->status, NT_STATUS_RETRY)) { - state->ctx->status = idmap_gid_to_sid(service->idmap_ctx, - mem_ctx, gid, - &state->sid); + unixid = talloc(result, struct unixid); + if (composite_nomem(unixid, result)) return result; + unixid->id = gid; + unixid->type = ID_TYPE_GID; + + ids = talloc(result, struct id_mapping); + if (composite_nomem(ids, result)) return result; + ids->unixid = unixid; + ids->sid = NULL; + + ctx = wb_xids2sids_send(result, service, 1, ids); + if (composite_nomem(ctx, result)) return result; + + composite_continue(result, ctx, gid2sid_recv_sid, state); + return result; +} + +static void gid2sid_recv_sid(struct composite_context *ctx) +{ + struct gid2sid_state *state = talloc_get_type(ctx->async.private_data, + struct gid2sid_state); + struct id_mapping *ids = NULL; + state->ctx->status = wb_xids2sids_recv(ctx, &ids); + if (!composite_is_ok(state->ctx)) return; + + if (!NT_STATUS_IS_OK(ids->status)) { + composite_error(state->ctx, ids->status); + return; } - if (!composite_is_ok(state->ctx)) return result; + state->sid = ids->sid; composite_done(state->ctx); - return result; } NTSTATUS wb_gid2sid_recv(struct composite_context *ctx, TALLOC_CTX *mem_ctx, diff --git a/source4/winbind/wb_sid2gid.c b/source4/winbind/wb_sid2gid.c index 12129226be5..d68956ce851 100644 --- a/source4/winbind/wb_sid2gid.c +++ b/source4/winbind/wb_sid2gid.c @@ -3,7 +3,7 @@ Map a SID to a gid - Copyright (C) Kai Blin 2007 + Copyright (C) 2007-2008 Kai Blin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,11 +33,14 @@ struct sid2gid_state { gid_t gid; }; +static void sid2gid_recv_gid(struct composite_context *ctx); + struct composite_context *wb_sid2gid_send(TALLOC_CTX *mem_ctx, struct wbsrv_service *service, const struct dom_sid *sid) { - struct composite_context *result; + struct composite_context *result, *ctx; struct sid2gid_state *state; + struct id_mapping *ids; DEBUG(5, ("wb_sid2gid_send called\n")); @@ -51,18 +54,43 @@ struct composite_context *wb_sid2gid_send(TALLOC_CTX *mem_ctx, result->private_data = state; state->service = service; - state->ctx->status = idmap_sid_to_gid(service->idmap_ctx, state, sid, - &state->gid); - if (NT_STATUS_EQUAL(state->ctx->status, NT_STATUS_RETRY)) { - state->ctx->status = idmap_sid_to_gid(service->idmap_ctx, state, - sid, &state->gid); - } - if (!composite_is_ok(state->ctx)) return result; + ids = talloc(result, struct id_mapping); + if (composite_nomem(ids, result)) return result; + + ids->sid = dom_sid_dup(result, sid); + if (composite_nomem(ids->sid, result)) return result; + + ctx = wb_sids2xids_send(result, service, 1, ids); + if (composite_nomem(ctx, result)) return result; - composite_done(state->ctx); + composite_continue(result, ctx, sid2gid_recv_gid, state); return result; } +static void sid2gid_recv_gid(struct composite_context *ctx) +{ + struct sid2gid_state *state = talloc_get_type(ctx->async.private_data, + struct sid2gid_state); + + struct id_mapping *ids = NULL; + + state->ctx->status = wb_sids2xids_recv(ctx, &ids); + if (!composite_is_ok(state->ctx)) return; + + if (!NT_STATUS_IS_OK(ids->status)) { + composite_error(state->ctx, ids->status); + return; + } + + if (ids->unixid->type == ID_TYPE_BOTH || + ids->unixid->type == ID_TYPE_GID) { + state->gid = ids->unixid->id; + composite_done(state->ctx); + } else { + composite_error(state->ctx, NT_STATUS_INVALID_SID); + } +} + NTSTATUS wb_sid2gid_recv(struct composite_context *ctx, gid_t *gid) { NTSTATUS status = composite_wait(ctx); diff --git a/source4/winbind/wb_sid2uid.c b/source4/winbind/wb_sid2uid.c index 0de45fdea9b..b65e41978cc 100644 --- a/source4/winbind/wb_sid2uid.c +++ b/source4/winbind/wb_sid2uid.c @@ -3,7 +3,7 @@ Map a SID to a uid - Copyright (C) Kai Blin 2007-2008 + Copyright (C) 2007-2008 Kai Blin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,11 +33,14 @@ struct sid2uid_state { uid_t uid; }; +static void sid2uid_recv_uid(struct composite_context *ctx); + struct composite_context *wb_sid2uid_send(TALLOC_CTX *mem_ctx, struct wbsrv_service *service, const struct dom_sid *sid) { - struct composite_context *result; + struct composite_context *result, *ctx; struct sid2uid_state *state; + struct id_mapping *ids; DEBUG(5, ("wb_sid2uid_send called\n")); @@ -45,24 +48,49 @@ struct composite_context *wb_sid2uid_send(TALLOC_CTX *mem_ctx, if (!result) return NULL; state = talloc(result, struct sid2uid_state); - if(composite_nomem(state, result)) return result; + if (composite_nomem(state, result)) return result; state->ctx = result; result->private_data = state; state->service = service; - state->ctx->status = idmap_sid_to_uid(service->idmap_ctx, state, sid, - &state->uid); - if (NT_STATUS_EQUAL(state->ctx->status, NT_STATUS_RETRY)) { - state->ctx->status = idmap_sid_to_uid(service->idmap_ctx, state, - sid, &state->uid); - } - if (!composite_is_ok(state->ctx)) return result; + ids = talloc(result, struct id_mapping); + if (composite_nomem(ids, result)) return result; + + ids->sid = dom_sid_dup(result, sid); + if (composite_nomem(ids->sid, result)) return result; + + ctx = wb_sids2xids_send(result, service, 1, ids); + if (composite_nomem(ctx, result)) return result; - composite_done(state->ctx); + composite_continue(result, ctx, sid2uid_recv_uid, state); return result; } +static void sid2uid_recv_uid(struct composite_context *ctx) +{ + struct sid2uid_state *state = talloc_get_type(ctx->async.private_data, + struct sid2uid_state); + + struct id_mapping *ids = NULL; + + state->ctx->status = wb_sids2xids_recv(ctx, &ids); + if (!composite_is_ok(state->ctx)) return; + + if (!NT_STATUS_IS_OK(ids->status)) { + composite_error(state->ctx, ids->status); + return; + } + + if (ids->unixid->type == ID_TYPE_BOTH || + ids->unixid->type == ID_TYPE_UID) { + state->uid = ids->unixid->id; + composite_done(state->ctx); + } else { + composite_error(state->ctx, NT_STATUS_INVALID_SID); + } +} + NTSTATUS wb_sid2uid_recv(struct composite_context *ctx, uid_t *uid) { NTSTATUS status = composite_wait(ctx); diff --git a/source4/winbind/wb_sids2xids.c b/source4/winbind/wb_sids2xids.c new file mode 100644 index 00000000000..302b915ff5b --- /dev/null +++ b/source4/winbind/wb_sids2xids.c @@ -0,0 +1,82 @@ +/* + Unix SMB/CIFS implementation. + + Map SIDs to unixids. + + Copyright (C) 2008 Kai Blin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "libcli/composite/composite.h" +#include "winbind/wb_server.h" +#include "smbd/service_task.h" +#include "winbind/wb_helper.h" +#include "libcli/security/proto.h" +#include "winbind/idmap.h" + +struct sids2xids_state { + struct composite_context *ctx; + struct wbsrv_service *service; + struct id_mapping *ids; + int count; +}; + +struct composite_context *wb_sids2xids_send(TALLOC_CTX *mem_ctx, + struct wbsrv_service *service, + int count, struct id_mapping *ids) +{ + struct composite_context *result; + struct sids2xids_state *state; + + DEBUG(5, ("wb_sids2xids_send called\n")); + + result = composite_create(mem_ctx, service->task->event_ctx); + if (!result) return NULL; + + state = talloc(result, struct sids2xids_state); + if (composite_nomem(state, result)) return result; + + state->ctx = result; + result->private_data = state; + state->service = service; + state->count = count; + state->ids = ids; + + state->ctx->status = idmap_sids_to_xids(service->idmap_ctx, mem_ctx, + count, state->ids); + if (!composite_is_ok(state->ctx)) return result; + + composite_done(state->ctx); + return result; +} + +NTSTATUS wb_sids2xids_recv(struct composite_context *ctx, + struct id_mapping **ids) +{ + NTSTATUS status = composite_wait(ctx); + + DEBUG(5, ("wb_sids2xids_recv called\n")); + + if (NT_STATUS_IS_OK(status)) { + struct sids2xids_state *state = + talloc_get_type(ctx->private_data, + struct sids2xids_state); + *ids = state->ids; + } + talloc_free(ctx); + return status; +} + diff --git a/source4/winbind/wb_uid2sid.c b/source4/winbind/wb_uid2sid.c index e81d2e46717..fd43dd64b99 100644 --- a/source4/winbind/wb_uid2sid.c +++ b/source4/winbind/wb_uid2sid.c @@ -3,7 +3,7 @@ Command backend for wbinfo -U - Copyright (C) Kai Blin 2007-2008 + Copyright (C) 2007-2008 Kai Blin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,35 +33,62 @@ struct uid2sid_state { struct dom_sid *sid; }; +static void uid2sid_recv_sid(struct composite_context *ctx); + struct composite_context *wb_uid2sid_send(TALLOC_CTX *mem_ctx, struct wbsrv_service *service, uid_t uid) { - struct composite_context *result; + struct composite_context *result, *ctx; struct uid2sid_state *state; + struct unixid *unixid; + struct id_mapping *ids; DEBUG(5, ("wb_uid2sid_send called\n")); result = composite_create(mem_ctx, service->task->event_ctx); if (!result) return NULL; - state = talloc(mem_ctx, struct uid2sid_state); + state = talloc(result, struct uid2sid_state); if (composite_nomem(state, result)) return result; state->ctx = result; result->private_data = state; state->service = service; - state->ctx->status = idmap_uid_to_sid(service->idmap_ctx, mem_ctx, uid, - &state->sid); - if (NT_STATUS_EQUAL(state->ctx->status, NT_STATUS_RETRY)) { - state->ctx->status = idmap_uid_to_sid(service->idmap_ctx, - mem_ctx, uid, - &state->sid); + unixid = talloc(result, struct unixid); + if (composite_nomem(unixid, result)) return result; + unixid->id = uid; + unixid->type = ID_TYPE_UID; + + ids = talloc(result, struct id_mapping); + if (composite_nomem(ids, result)) return result; + ids->unixid = unixid; + ids->sid = NULL; + + ctx = wb_xids2sids_send(result, service, 1, ids); + if (composite_nomem(ctx, result)) return result; + + composite_continue(result, ctx, uid2sid_recv_sid, state); + return result; +} + +static void uid2sid_recv_sid(struct composite_context *ctx) +{ + struct uid2sid_state *state = talloc_get_type(ctx->async.private_data, + struct uid2sid_state); + struct id_mapping *ids = NULL; + + state->ctx->status = wb_xids2sids_recv(ctx, &ids); + if (!composite_is_ok(state->ctx)) return; + + if (!NT_STATUS_IS_OK(ids->status)) { + composite_error(state->ctx, ids->status); + return; } - if (!composite_is_ok(state->ctx)) return result; + + state->sid = ids->sid; composite_done(state->ctx); - return result; } NTSTATUS wb_uid2sid_recv(struct composite_context *ctx, TALLOC_CTX *mem_ctx, diff --git a/source4/winbind/wb_xids2sids.c b/source4/winbind/wb_xids2sids.c new file mode 100644 index 00000000000..843d292c070 --- /dev/null +++ b/source4/winbind/wb_xids2sids.c @@ -0,0 +1,82 @@ +/* + Unix SMB/CIFS implementation. + + Convet an unixid struct to a SID + + Copyright (C) 2008 Kai Blin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "libcli/composite/composite.h" +#include "winbind/wb_server.h" +#include "smbd/service_task.h" +#include "winbind/wb_helper.h" +#include "libcli/security/proto.h" +#include "winbind/idmap.h" + +struct xids2sids_state { + struct composite_context *ctx; + struct wbsrv_service *service; + struct id_mapping *ids; + int count; +}; + +struct composite_context *wb_xids2sids_send(TALLOC_CTX *mem_ctx, + struct wbsrv_service *service, + int count, struct id_mapping *ids) +{ + struct composite_context *result; + struct xids2sids_state *state; + + DEBUG(0, ("wb_xids2sids_send called\n")); + + result = composite_create(mem_ctx, service->task->event_ctx); + if (!result) return NULL; + + state = talloc(mem_ctx, struct xids2sids_state); + if (composite_nomem(state, result)) return result; + + state->ctx = result; + result->private_data = state; + state->service = service; + state->count = count; + state->ids = ids; + + state->ctx->status = idmap_xids_to_sids(service->idmap_ctx, mem_ctx, + count, state->ids); + if (!composite_is_ok(state->ctx)) return result; + + composite_done(state->ctx); + return result; +} + +NTSTATUS wb_xids2sids_recv(struct composite_context *ctx, + struct id_mapping **ids) +{ + NTSTATUS status = composite_wait(ctx); + + DEBUG(0, ("wb_xids2sids_recv called.\n")); + + if (NT_STATUS_IS_OK(status)) { + struct xids2sids_state *state = + talloc_get_type(ctx->private_data, + struct xids2sids_state); + *ids = state->ids; + } + talloc_free(ctx); + return status; +} + diff --git a/testprogs/ejs/ldap.js b/testprogs/ejs/ldap.js index c30f29e2495..44e4c83e671 100755 --- a/testprogs/ejs/ldap.js +++ b/testprogs/ejs/ldap.js @@ -866,12 +866,30 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer," + base_dn + " } assert(res.msgs[0].dn == ("CN=ldaptestuser4,CN=ldaptestcontainer2," + base_dn)); - assert(strupper(res.msgs[0].memberOf[0]) == strupper(("CN=ldaptestgroup2,CN=Users," + base_dn))); + assert(strupper(res.msgs[0].memberOf[0]) == (strupper("CN=ldaptestgroup2,CN=Users," + base_dn))); - println("Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + base_dn + ")(objectclass=group)) to check subtree renames and linked attributes"); - var res = ldb.search("(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + base_dn + ")(objectclass=group))", base_dn, ldb.SCOPE_SUBTREE); + println("Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) in cn=users"); + var res_group = ldb.search("(&(cn=ldaptestgroup2)(objectClass=group))", "cn=users," + base_dn, ldb.SCOPE_SUBTREE); + if (res_group.error != 0 || res_group.msgs.length != 1) { + println("Could not find (&(cn=ldaptestgroup2)(objectClass=group)) under cn=users," + base_dn); + assert(res_group.error == 0); + assert(res_group.msgs.length == 1); + } + + println("Testing ldb.search for (member=CN=ldaptestuser4,CN=ldaptestcontainer2," + base_dn + ") to check subtree renames and linked attributes"); + var res = ldb.search("(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + base_dn + ")", base_dn, ldb.SCOPE_SUBTREE); if (res.error != 0 || res.msgs.length != 1) { - println("Could not find (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + base_dn + ")(objectclass=group)), perhaps linked attributes are not conistant with subtree renames?"); + for (i=0; i < res_group.msgs[0].member.length; i++) { + println("res_group.member[" + i + "]: " + res_group.msgs[0].member[i]); + } + + println("Could not find (member=CN=ldaptestuser4,CN=ldaptestcontainer2," + base_dn + "), perhaps linked attributes are not conistant with subtree renames?"); + println("Testing ldb.search for (member=CN=ldaptestuser4,CN=ldaptestcontainer," + base_dn + ") to check if it just hasn't been updated"); + var res2 = ldb.search("(member=CN=ldaptestuser4,CN=ldaptestcontainer," + base_dn + ")", base_dn, ldb.SCOPE_SUBTREE); + if (res2.error != 0 || res2.msgs.length != 1) { + println("Could not find (member=CN=ldaptestuser4,CN=ldaptestcontainer," + base_dn + "), very odd, it wasn't here at all.."); + } + assert(res.error == 0); assert(res.msgs.length == 1); } @@ -992,7 +1010,7 @@ objectClass: user assert(res.msgs[0].objectCategory == ("CN=Person,CN=Schema,CN=Configuration," + base_dn)); assert(res.msgs[0].sAMAccountType == 805306368); assert(res.msgs[0].userAccountControl == 546); - assert(res.msgs[0].memberOf[0] == ("CN=ldaptestgroup2,CN=Users," + base_dn)); + assert(strupper(res.msgs[0].memberOf[0]) == strupper("CN=ldaptestgroup2,CN=Users," + base_dn)); assert(res.msgs[0].memberOf.length == 1); println("Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + base_dn + "))"); |