Ceci est un message signC) cryptographiquement au format MIME.
--------------ms000000000208070102090606
Content-Type: multipart/mixed;
boundary="------------050908090805020607010105"
This is a multi-part message in MIME format.
--------------050908090805020607010105
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Here is the patch.
--=20
Guillaume Rousse
INRIA, Direction des syst=E8mes d'information
Domaine de Voluceau
Rocquencourt - BP 105
78153 Le Chesnay
Tel: 01 39 63 58 31
--------------050908090805020607010105
Content-Type: text/x-patch;
name="0001-ITS-7348-new-check_password-contrib-module.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename*0="0001-ITS-7348-new-check_password-contrib-module.patch"
=46rom fa2f6730171ab5755f56ca66715b723df726026d Mon Sep 17 00:00:00 2001
From: Guillaume Rousse <guillomovitch(a)gmail.com>
Date: Tue, 7 Aug 2012 17:39:21 +0200
Subject: [PATCH] ITS #7348: new check_password contrib module
Signed-off-by: Guillaume Rousse <Guillame.Rousse(a)inria.fr>
---
contrib/slapd-modules/README | 3 +
contrib/slapd-modules/check-password/Makefile | 52 +++
contrib/slapd-modules/check-password/README | 146 +++++++++
.../slapd-modules/check-password/check_password.c | 356 +++++++++++++++=
++++++
4 files changed, 557 insertions(+)
create mode 100644 contrib/slapd-modules/check-password/Makefile
create mode 100644 contrib/slapd-modules/check-password/README
create mode 100644 contrib/slapd-modules/check-password/check_password.c=
diff --git a/contrib/slapd-modules/README b/contrib/slapd-modules/README
index db74379..d8005ff 100644
--- a/contrib/slapd-modules/README
+++ b/contrib/slapd-modules/README
@@ -20,6 +20,9 @@ allop (overlay)
autogroup (overlay)
Automated updates of group memberships.
=20
+check_password (plugin)
+ External password quality check module for ppolicy
+
cloak (overlay)
Hide specific attributes unless explicitely requested
=20
diff --git a/contrib/slapd-modules/check-password/Makefile b/contrib/slap=
d-modules/check-password/Makefile
new file mode 100644
index 0000000..42dd18f
--- /dev/null
+++ b/contrib/slapd-modules/check-password/Makefile
@@ -0,0 +1,52 @@
+
+LDAP_SRC =3D ../../..
+LDAP_BUILD =3D ../../..
+LDAP_INC =3D -I$(LDAP_BUILD)/include -I$(LDAP_SRC)/include -I$(LDAP_SRC)=
/servers/slapd
+LDAP_LIB =3D $(LDAP_BUILD)/libraries/libldap_r/libldap_r.la \
+ $(LDAP_BUILD)/libraries/liblber/liblber.la
+
+CRACKLIB_PATH =3D /usr/share/cracklib/pw_dict
+CRACKLIB_INC =3D=20
+CRACKLIB_LIB =3D -lcrack
+
+CONFIG_PATH =3D /etc/openldap/check_password.conf
+
+LIBTOOL =3D $(LDAP_BUILD)/libtool
+CC =3D gcc
+OPT =3D -g -O2 -Wall
+DEFS =3D -DHAVE_CRACKLIB -DCRACKLIB_DICTPATH=3D"\"$(CRACKLIB_PATH)\"" \
+ -DCONFIG_FILE=3D"\"$(CONFIG_PATH)\"" -DDEBUG
+INCS =3D $(LDAP_INC) $(CRACKLIB_INC)
+LIBS =3D $(LDAP_LIB) $(CRACKLIB_LIB)
+
+PROGRAMS =3D check_password.la
+LTVER =3D 0:0:0
+
+prefix=3D/usr/local
+exec_prefix=3D$(prefix)
+ldap_subdir=3D/openldap
+
+libdir=3D$(exec_prefix)/lib
+libexecdir=3D$(exec_prefix)/libexec
+moduledir =3D $(libexecdir)$(ldap_subdir)
+
+.SUFFIXES: .c .o .lo
+
+.c.lo:
+ $(LIBTOOL) --mode=3Dcompile $(CC) $(OPT) $(DEFS) $(INCS) -c $<
+
+all: $(PROGRAMS)
+
+check_password.la: check_password.lo
+ $(LIBTOOL) --mode=3Dlink $(CC) $(OPT) -version-info $(LTVER) \
+ -rpath $(moduledir) -module -o $@ $? $(LIBS)
+
+clean:
+ rm -rf *.o *.lo *.la .libs
+
+install: $(PROGRAMS)
+ mkdir -p $(DESTDIR)$(moduledir)
+ for p in $(PROGRAMS) ; do \
+ $(LIBTOOL) --mode=3Dinstall cp $$p $(DESTDIR)$(moduledir) ; \
+ done
+
diff --git a/contrib/slapd-modules/check-password/README b/contrib/slapd-=
modules/check-password/README
new file mode 100644
index 0000000..10191c2
--- /dev/null
+++ b/contrib/slapd-modules/check-password/README
@@ -0,0 +1,146 @@
+
+check_password.c - OpenLDAP pwdChecker library
+
+2007-06-06 Michael Steinmann <msl(a)calivia.com>
+2008-01-30 Pierre-Yves Bonnetain <py.bonnetain(a)ba-cst.com>
+2009 Clement Oudot <clem.oudot(a)gmail.com> - LTB-project
+2009 Jerome HUET - LTB-project
+
+check_password.c is an OpenLDAP pwdPolicyChecker module used to check th=
e
+strength and quality of user-provided passwords.
+
+This module is used as an extension of the OpenLDAP password policy cont=
rols,
+see slapo-ppolicy(5) section pwdCheckModule.
+
+check_password.c will run a number of checks on the passwords to ensure =
minimum
+strength and quality requirements are met. Passwords that do not meet th=
ese
+requirements are rejected.
+
+
+Password checks
+---------------
+ - passwords shorter than 6 characters are rejected if cracklib is used =
(because
+ cracklib WILL reject them).
+
+ - syntactic checks controls how many different character classes are us=
ed
+ (lower, upper, digit and punctuation characters). The minimum number =
of
+ classes is defined in a configuration file. You can set the minimum f=
or each
+ class.
+
+ - passwords are checked against cracklib if cracklib is enabled at comp=
ile
+ time. It can be disabled in configuration file.
+
+INSTALLATION
+------------
+Use the provided Makefile to build the module.
+
+Compilation constants :
+
+CONFIG_FILE : Path to the configuration file.=20
+ Defaults to /etc/openldap/check_password.conf
+
+DEBUG : If defined, check_password will syslog() its actions.
+
+Build dependencies
+cracklib header files (link with -lcrack). The Makefile does not look fo=
r
+cracklib; you may need to provide the paths manually.
+
+Install into the slapd server module path. Change the installation
+path to match with the OpenLDAP module path in the Makefile.
+
+The module may be defined with slapd.conf parameter "modulepath".
+
+USAGE
+-----
+To use this module you need to add objectClass pwdPolicyChecker with an =
+attribute 'pwdCheckModule: check_password.so' to a password policy entry=
=2E
+
+The module depends on a working cracklib installation including wordlist=
files.
+If the wordlist files are not readable, the cracklib check will be skipp=
ed
+silently.
+
+Note: pwdPolicyChecker modules are loaded on *every* password change ope=
ration.
+
+Configuration
+-------------
+The configuration file (/etc/openldap/check_password.conf by default) co=
ntains
+parameters for the module. If the file is not found, parameters are give=
n their
+default value.
+
+The syntax of the file is :
+
+parameter value
+
+with spaces being delimiters. Parameter names ARE case sensitive (this m=
ay
+change in the future).
+
+Current parameters :
+
+- useCracklib: integer. Default value: 1. Set it to 0 to disable crackl=
ib verification.
+ It has no effect if cracklib is not included at compile time.
+
+- minPoints: integer. Default value: 3. Minimum number of quality point=
s a new
+ password must have to be accepted. One quality point is awarded for e=
ach character
+ class used in the password.
+
+- minUpper: integer. Defaut value: 0. Minimum upper characters expected.=
+
+- minLower: integer. Defaut value: 0. Minimum lower characters expected.=
+
+- minDigit: integer. Defaut value: 0. Minimum digit characters expected.=
+
+- minPunct: integer. Defaut value: 0. Minimum punctuation characters exp=
ected.
+
+Logs
+----
+If a user password is rejected by an OpenLDAP pwdChecker module, the use=
r will
+*not* get a detailed error message, this is by design.
+
+Typical user message from ldappasswd(5):
+ Result: Constraint violation (19)
+ Additional info: Password fails quality checking policy
+
+A more detailed message is written to the server log.
+
+Server log:
+ check_password_quality: module error: (check_password.so)
+ Password for dn=3D".." does not pass required number of strength check=
s (2 of 3)
+
+
+Caveats
+-------
+Runtime errors with this module (such as cracklib configuration problems=
) may
+bring down the slapd process.
+
+Use at your own risk.
+
+
+TODO
+----
+* use proper malloc function, see ITS#4998
+
+
+HISTORY
+-------
+* 2009-10-30 Clement OUDOT - LTB-project
+ Version 1.1
+ - Apply patch from Jerome HUET for minUpper/minLower/minDigit/minPunc=
t
+
+* 2009-02-05 Clement Oudot <clem.oudot(a)gmail.com> - LINAGORA Group
+ Version 1.0.3
+ - Add useCracklib parameter in config file (with help of Pascal Pejac)=
+ - Prefix log messages with "check_password: "
+ - Log what character type is found for quality checking
+
+* 2008-01-31 Pierre-Yves Bonnetain <py.bonnetain(a)ba-cst.com>
+ Version 1.0.2
+ - Several bug fixes.
+ - Add external config file
+
+* 2007-06-06 Michael Steinmann <msl(a)calivia.com>
+ Version 1.0.1
+ - add dn to error messages
+
+* 2007-06-02 Michael Steinmann <msl(a)calivia.com>
+ Version 1.0
+
diff --git a/contrib/slapd-modules/check-password/check_password.c b/cont=
rib/slapd-modules/check-password/check_password.c
new file mode 100644
index 0000000..da427e7
--- /dev/null
+++ b/contrib/slapd-modules/check-password/check_password.c
@@ -0,0 +1,356 @@
+/*
+ * check_password.c for OpenLDAP
+ *
+ * See LICENSE, README and INSTALL files
+ */
+
+#include <string.h>
+#include <ctype.h>
+#include <portable.h>
+#include <slap.h>
+
+#ifdef HAVE_CRACKLIB
+#include "crack.h"
+#endif
+
+#if defined(DEBUG)
+#include <syslog.h>
+#endif
+
+#ifndef CRACKLIB_DICTPATH
+#define CRACKLIB_DICTPATH "/usr/share/cracklib/pw_dict"
+#endif
+
+#ifndef CONFIG_FILE
+#define CONFIG_FILE "/etc/openldap/check_password.conf"
+#endif
+
+#define DEFAULT_QUALITY 3
+#define DEFAULT_CRACKLIB 1
+#define MEMORY_MARGIN 50
+#define MEM_INIT_SZ 64
+#define FILENAME_MAXLEN 512
+
+#define PASSWORD_TOO_SHORT_SZ \
+ "Password for dn=3D\"%s\" is too short (%d/6)"
+#define PASSWORD_QUALITY_SZ \
+ "Password for dn=3D\"%s\" does not pass required number of strength che=
cks (%d of %d)"
+#define BAD_PASSWORD_SZ \
+ "Bad password for dn=3D\"%s\" because %s"
+
+typedef int (*validator) (char*);
+static int read_config_file (char *);
+static validator valid_word (char *);
+static int set_quality (char *);
+static int set_cracklib (char *);
+
+int check_password (char *pPasswd, char **ppErrStr, Entry *pEntry);
+
+static int set_quality (char *value)
+{
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Setting quality to [%s]", value);
+#endif
+
+ /* No need to require more quality than we can check for. */
+ if (!isdigit(*value) || (int) (value[0] - '0') > 4) return DEFAULT_QUAL=
ITY;
+ return (int) (value[0] - '0');
+
+}
+
+static int set_cracklib (char *value)
+{
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Setting cracklib usage to [%s]", va=
lue);
+#endif
+
+
+ return (int) (value[0] - '0');
+
+}
+
+static int set_digit (char *value)
+{
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Setting parameter to [%s]", value);=
+#endif
+ if (!isdigit(*value) || (int) (value[0] - '0') > 9) return 0;
+ return (int) (value[0] - '0');
+}
+
+static validator valid_word (char *word)
+{
+ struct {
+ char * parameter;
+ validator dealer;
+ } list[] =3D { { "minPoints", set_quality },
+ { "useCracklib", set_cracklib },
+ { "minUpper", set_digit },
+ { "minLower", set_digit },
+ { "minDigit", set_digit },
+ { "minPunct", set_digit },
+ { NULL, NULL } };
+ int index =3D 0;
+
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Validating parameter [%s]", word);
+#endif
+
+ while (list[index].parameter !=3D NULL) {
+ if (strlen(word) =3D=3D strlen(list[index].parameter) &&
+ strcmp(list[index].parameter, word) =3D=3D 0) {
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Parameter accepted.");
+#endif
+ return list[index].dealer;
+ }
+ index++;
+ }
+
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Parameter rejected.");
+#endif
+
+ return NULL;
+}
+
+static int read_config_file (char *keyWord)
+{
+ FILE * config;
+ char * line;
+ int returnValue =3D -1;
+
+ if ((line =3D ber_memcalloc(260, sizeof(char))) =3D=3D NULL) {
+ return returnValue;
+ }
+
+ if ( (config =3D fopen(CONFIG_FILE, "r")) =3D=3D NULL) {
+#if defined(DEBUG)
+ syslog(LOG_ERR, "check_password: Opening file %s failed", CONFIG_FILE)=
;
+#endif
+
+ ber_memfree(line);
+ return returnValue;
+ }
+
+ while (fgets(line, 256, config) !=3D NULL) {
+ char *start =3D line;
+ char *word, *value;
+ validator dealer;
+
+#if defined(DEBUG)
+ /* Debug traces to syslog. */
+ syslog(LOG_NOTICE, "check_password: Got line |%s|", line);
+#endif
+
+ while (isspace(*start) && isascii(*start)) start++;
+
+ if (! isascii(*start))
+ continue;
+
+ if ((word =3D strtok(start, " \t")) && (dealer =3D valid_word(word)) &=
& (strcmp(keyWord,word)=3D=3D0)) {
+ if ((value =3D strtok(NULL, " \t")) =3D=3D NULL)
+ continue;
+
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Word =3D %s, value =3D %s", word,=
value);
+#endif
+
+ returnValue =3D (*dealer)(value);
+ }
+ }
+
+ fclose(config);
+ ber_memfree(line);
+ return returnValue;
+}
+
+static int realloc_error_message (char ** target, int curlen, int nextle=
n)
+{
+ if (curlen < nextlen + MEMORY_MARGIN) {
+#if defined(DEBUG)
+ syslog(LOG_WARNING, "check_password: Reallocating szErrStr from %d to =
%d",
+ curlen, nextlen + MEMORY_MARGIN);
+#endif
+ ber_memfree(*target);
+ curlen =3D nextlen + MEMORY_MARGIN;
+ *target =3D (char *) ber_memalloc(curlen);
+ }
+
+ return curlen;
+}
+
+ int
+check_password (char *pPasswd, char **ppErrStr, Entry *pEntry)
+{
+
+ char *szErrStr =3D (char *) ber_memalloc(MEM_INIT_SZ);
+ int mem_len =3D MEM_INIT_SZ;
+
+ int nLen;
+ int nLower =3D 0;
+ int nUpper =3D 0;
+ int nDigit =3D 0;
+ int nPunct =3D 0;
+ int minLower =3D 0;
+ int minUpper =3D 0;
+ int minDigit =3D 0;
+ int minPunct =3D 0;
+ int nQuality =3D 0;
+ int i;
+
+ /* Set a sensible default to keep original behaviour. */
+ int minQuality =3D DEFAULT_QUALITY;
+ int useCracklib =3D DEFAULT_CRACKLIB;
+
+ /** bail out early as cracklib will reject passwords shorter
+ * than 6 characters
+ */
+
+ nLen =3D strlen (pPasswd);
+ if ( nLen < 6) {
+ mem_len =3D realloc_error_message(&szErrStr, mem_len,
+ strlen(PASSWORD_TOO_SHORT_SZ) +
+ strlen(pEntry->e_name.bv_val) + 1);
+ sprintf (szErrStr, PASSWORD_TOO_SHORT_SZ, pEntry->e_name.bv_val, nLen)=
;
+ goto fail;
+ }
+
+ /* Read config file */
+ minQuality =3D read_config_file("minPoints");
+
+ useCracklib =3D read_config_file("useCracklib");
+ minUpper =3D read_config_file("minUpper");
+ minLower =3D read_config_file("minLower");
+ minDigit =3D read_config_file("minDigit");
+ minPunct =3D read_config_file("minPunct");
+
+ /** The password must have at least minQuality strength points with one=
+ * point for the first occurrance of a lower, upper, digit and
+ * punctuation character
+ */
+
+ for ( i =3D 0; i < nLen; i++ ) {
+
+ if ( nQuality >=3D minQuality ) break;
+
+ if ( islower (pPasswd[i]) ) {
+ minLower--;
+ if ( !nLower && (minLower < 1)) {
+ nLower =3D 1; nQuality++;
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Found lower character - quality =
raise %d", nQuality);
+#endif
+ }
+ continue;
+ }
+
+ if ( isupper (pPasswd[i]) ) {
+ minUpper--;
+ if ( !nUpper && (minUpper < 1)) {
+ nUpper =3D 1; nQuality++;
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Found upper character - quality =
raise %d", nQuality);
+#endif
+ }
+ continue;
+ }
+
+ if ( isdigit (pPasswd[i]) ) {
+ minDigit--;
+ if ( !nDigit && (minDigit < 1)) {
+ nDigit =3D 1; nQuality++;
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Found digit character - quality =
raise %d", nQuality);
+#endif
+ }
+ continue;
+ }
+
+ if ( ispunct (pPasswd[i]) ) {
+ minPunct--;
+ if ( !nPunct && (minPunct < 1)) {
+ nPunct =3D 1; nQuality++;
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Found punctuation character - qu=
ality raise %d", nQuality);
+#endif
+ }
+ continue;
+ }
+ }
+
+ if ( nQuality < minQuality ) {
+ mem_len =3D realloc_error_message(&szErrStr, mem_len,
+ strlen(PASSWORD_QUALITY_SZ) +
+ strlen(pEntry->e_name.bv_val) + 2);
+ sprintf (szErrStr, PASSWORD_QUALITY_SZ, pEntry->e_name.bv_val,
+ nQuality, minQuality);
+ goto fail;
+ }
+
+#ifdef HAVE_CRACKLIB
+
+ /** Check password with cracklib */
+
+ if ( useCracklib > 0 ) {
+ int j =3D 0;
+ FILE* fp;
+ char filename[FILENAME_MAXLEN];
+ char const* ext[] =3D { "hwm", "pwd", "pwi" };
+ int nErr =3D 0;
+
+ /**
+ * Silently fail when cracklib wordlist is not found
+ */
+
+ for ( j =3D 0; j < 3; j++ ) {
+
+ snprintf (filename, FILENAME_MAXLEN - 1, "%s.%s", \
+ CRACKLIB_DICTPATH, ext[j]);
+
+ if (( fp =3D fopen ( filename, "r")) =3D=3D NULL ) {
+
+ nErr =3D 1;
+ break;
+
+ } else {
+
+ fclose (fp);
+
+ }
+ }
+
+ char *r;
+ if ( nErr =3D=3D 0) {
+
+ r =3D (char *) FascistCheck (pPasswd, CRACKLIB_DICTPATH);
+ if ( r !=3D NULL ) {
+ mem_len =3D realloc_error_message(&szErrStr, mem_len,
+ strlen(BAD_PASSWORD_SZ) +
+ strlen(pEntry->e_name.bv_val) +
+ strlen(r));
+ sprintf (szErrStr, BAD_PASSWORD_SZ, pEntry->e_name.bv_val, r);
+ goto fail;
+ }
+ }
+ }
+
+ else {
+#if defined(DEBUG)
+ syslog(LOG_NOTICE, "check_password: Cracklib verification disabled by =
configuration");
+#endif
+ }
+
+#endif
+
+ *ppErrStr =3D strdup ("");
+ ber_memfree(szErrStr);
+ return (LDAP_SUCCESS);
+
+fail:
+ *ppErrStr =3D strdup (szErrStr);
+ ber_memfree(szErrStr);
+ return (EXIT_FAILURE);
+
+}
+
--=20
1.7.11.4
--------------050908090805020607010105--
--------------ms000000000208070102090606
Content-Type: application/pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
Content-Description: Signature cryptographique S/MIME
MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIN7jCC
BIowggNyoAMCAQICECf06hH0eobEbp27bqkXBwcwDQYJKoZIhvcNAQEFBQAwbzELMAkGA1UE
BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9vdDAeFw0w
NTA2MDcwODA5MTBaFw0yMDA1MzAxMDQ4MzhaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
VVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l
dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UEAxMtVVRO
LVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWlsMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3BYHW8OWX5ShpHornMSMxqmNVN
NRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQy
lbsMTzC9mKALi+VuG6JG+ni8om+rWV6lL8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXq
vgvOdjp6Dpvq/NonWz1zHyLmSGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6
hw2v+vPhwvCkxWeM1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu
9mIwFIws6wIDAQABo4HhMIHeMB8GA1UdIwQYMBaAFK29mHo0tCb3+sQmVO8DveAky1QaMB0G
A1UdDgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
BAUwAwEB/zB7BgNVHR8EdDByMDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9BZGRU
cnVzdEV4dGVybmFsQ0FSb290LmNybDA2oDSgMoYwaHR0cDovL2NybC5jb21vZG8ubmV0L0Fk
ZFRydXN0RXh0ZXJuYWxDQVJvb3QuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQAZ2IkRbyispgCi
54fBm5AD236hEv0e8+LwAamUVEJrmgnEoG3XkJIEA2Z5Q3H8+G+v23ZF4jcaPd3kWQR4rBz0
g0bzes9bhHIt5UbBuhgRKfPLSXmHPLptBZ2kbWhPrXIUNqi5sf2/z3/wpGqUNVCPz4FtVbHd
WTBK322gnGQfSXzvNrv042n0+DmPWq1LhTq3Du3Tzw1EovsEv+QvcI4l+1pUBrPQxLxtjftz
Mizpm4QkLdZ/kXpoAlAfDj9N6cz1u2fo3BwuO/xOzf4CjuOoEwqlJkRl6RDyTVKnrtw+ymsy
XEFs/vVdoOr/0fqbhlhtPZZH5f4ulQTCAMyOofK7MIIElTCCA32gAwIBAgIQK7maWQuBMVtp
KDwyDC57STANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDEPMA0GA1UEChMGVEVSRU5B
MRswGQYDVQQDExJURVJFTkEgUGVyc29uYWwgQ0EwHhcNMTEwMTExMDAwMDAwWhcNMTQwMTEw
MjM1OTU5WjBYMQswCQYDVQQGEwJGUjEOMAwGA1UEChMFSU5SSUExGTAXBgNVBAMTEEd1aWxs
YXVtZSBST1VTU0UxHjAcBgkqhkiG9w0BCQIWD3JvdXNzZUBpbnJpYS5mcjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBANT2GRniP4zFepDfXQ9qHZCqmyGFsnxP1sAK5gRwh2xm
7EJgNSAlRVkmYdkrohltfjGJWvzmlIc8lgbzPSddeHhlc3SI8ZV3b9gWlyq3asH4oPJ3KuKh
d8s2JLoll4pYRo+EqH/kLr8Tz3xfDEHtXNXiZ4QM6kniyLyk2QKc8UUsxd8f8gbiUW8yP2rB
9MgwbKYHn+EudkGbn+krQGbrBQRK83phYVGNnRy13mlu8Mb+9mmNCJq8cL6vhhIsGB4VRvhb
k3pcZc2zFm9QJFziYLpdqINoh3vmSVHEVN0Oa3KecuXjiaboonCzXnxvdgLWQYAJNglpP7TV
H4PTw+xXLZsCAwEAAaOCAXYwggFyMB8GA1UdIwQYMBaAFGNNQ1oZSD/ERsECur/uDuWCt2am
MB0GA1UdDgQWBBRPxfiKCFknW2HnMSChZnApNelBwjAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0T
AQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDBAYIKwYBBQUHAwIwGAYDVR0gBBEwDzANBgsr
BgEEAbIxAQICHTA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLnRjcy50ZXJlbmEub3Jn
L1RFUkVOQVBlcnNvbmFsQ0EuY3JsMHIGCCsGAQUFBwEBBGYwZDA6BggrBgEFBQcwAoYuaHR0
cDovL2NydC50Y3MudGVyZW5hLm9yZy9URVJFTkFQZXJzb25hbENBLmNydDAmBggrBgEFBQcw
AYYaaHR0cDovL29jc3AudGNzLnRlcmVuYS5vcmcwJAYDVR0RBB0wG4EZR3VpbGxhdW1lLlJv
dXNzZUBpbnJpYS5mcjANBgkqhkiG9w0BAQUFAAOCAQEAQi0EyaS/cO1avHkqFkOVhX5kuG3y
kUlOIrzga2dnR2H7ylRILOTxBLweXL2DKJN+ZPJleLJSmdVcstq0GneSA7D1kJt0aPdMHqI6
8fMcppQer+N1V/9LYJWWRTV6RFrlSduzEU5tmdlG7QbYtvgNtvBliZL06AYPO54FDkHrhfnJ
ldS55eeuAkwFrYkJP1Aa+zo/H2ytzVnIICtZMsZSa7Y2xo4j5Ykxd0HIsc48lmnkDnZ08+yf
AOjJis2tc9eeBdcvQ/Pck+woIDeW9vnahCRcOOqCbmith0cqFvEm8cb1ajPIKmlUGBJi97Qh
XJV8FZcuIK1Naelj/8MDbcd3ZzCCBMMwggOroAMCAQICEHP+V/rfuMUIgXtmuWvwLe8wDQYJ
KoZIhvcNAQEFBQAwga4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2Fs
dCBMYWtlIENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMTYwNAYDVQQDEy1VVE4tVVNFUkZpcnN0LUNsaWVu
dCBBdXRoZW50aWNhdGlvbiBhbmQgRW1haWwwHhcNMDkwNTE4MDAwMDAwWhcNMjgxMjMxMjM1
OTU5WjA7MQswCQYDVQQGEwJOTDEPMA0GA1UEChMGVEVSRU5BMRswGQYDVQQDExJURVJFTkEg
UGVyc29uYWwgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIFdn1M2ojoZAN
z7sFRMOrH0o1hRohhaBP+PBA4kpDm/5bsbC/tFfcdYBBS2Qa9ttPb4/QJUU1+erLSvr72tPt
RYgRlDbkzKgN78U9N+0We+PClZ5YM38i+/j/7Oa+264KZSUih9pvhItG6ECGKD+/VgjiSumD
ouki+y36tigfkcHDcftTwCtOpAyhbp1V7ezhJIc6COINHOTETdDLJ/qEZObRl51WJFuTuyku
Q+JBaj3iSmX8ml9ahoe8h8d5gJaZUcaQD2SRmX0Q3awsAyrheGT+zj1O9CtQEUvRWNSbA/B/
9TtTsFND+8UvxAQpGjqs11Xp0Q6V0Tsxf3hPriktAgMBAAGjggFNMIIBSTAfBgNVHSMEGDAW
gBSJgmd9xJ0mcABLtFBIfN49rgRufTAdBgNVHQ4EFgQUY01DWhlIP8RGwQK6v+4O5YK3ZqYw
DgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwGAYDVR0gBBEwDzANBgsrBgEE
AbIxAQICHTBYBgNVHR8EUTBPME2gS6BJhkdodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVRO
LVVTRVJGaXJzdC1DbGllbnRBdXRoZW50aWNhdGlvbmFuZEVtYWlsLmNybDBvBggrBgEFBQcB
AQRjMGEwOAYIKwYBBQUHMAKGLGh0dHA6Ly9jcnQudXNlcnRydXN0LmNvbS9VVE5BQUFDbGll
bnRfQ0EuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3QuY29tMA0GCSqG
SIb3DQEBBQUAA4IBAQAGK6lTLxPcXDkWzIafXkx7cvvsjVWKXpoK/1NMdvQGPVDPV/Ciz6+Z
jKr+oBl2PpkDMvp1gziKu2uapQwTstQbduaULmeYWeORbAKQmpzIYEtVq8qIWo0r5WmVAwfR
1A78JCIuWbFjpF/t2SNy5JzOOlxsH0+pAMkd/vp/RS22LoTdDyegWRhO1XYlRfSZJnnbb58j
90O7Kw8Eo4EmLLd7Nfk9d19AIeZ/HaWWWr3QyxY6bLthi4r9BDlECsss4cvOLhCYGtvgk+1J
ZGQIIJ+3o1Dwot3KtMZ8DD3nXhXcJ4bkOjtSWherqQZTK50Jc2QcAcP9MNKHA2/kFQN6OV9o
MYIDBzCCAwMCAQEwTzA7MQswCQYDVQQGEwJOTDEPMA0GA1UEChMGVEVSRU5BMRswGQYDVQQD
ExJURVJFTkEgUGVyc29uYWwgQ0ECECu5mlkLgTFbaSg8Mgwue0kwCQYFKw4DAhoFAKCCAY0w
GAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTIwODA3MTU1NzI1
WjAjBgkqhkiG9w0BCQQxFgQUQ1jLCcKguMOiIFP7wDC8SLbfFfYwXgYJKwYBBAGCNxAEMVEw
TzA7MQswCQYDVQQGEwJOTDEPMA0GA1UEChMGVEVSRU5BMRswGQYDVQQDExJURVJFTkEgUGVy
c29uYWwgQ0ECECu5mlkLgTFbaSg8Mgwue0kwYAYLKoZIhvcNAQkQAgsxUaBPMDsxCzAJBgNV
BAYTAk5MMQ8wDQYDVQQKEwZURVJFTkExGzAZBgNVBAMTElRFUkVOQSBQZXJzb25hbCBDQQIQ
K7maWQuBMVtpKDwyDC57STBsBgkqhkiG9w0BCQ8xXzBdMAsGCWCGSAFlAwQBKjALBglghkgB
ZQMEAQIwCgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsO
AwIHMA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBANISMWbCVg4clpyyoU7WyOoP
ENBalFbEzAbA7iBn6edoAEV8jgj41VcGlNsevz8kQrb59GzkjOqMXsIwHTsGvjky738QcFPu
uXyb8ZY+ExFOhgscUVlQ924+idn6xPMstKuM/cPKrknqdrRsS6igOTMVhKjI0s0MX2vsSA8/
FLd48o7B8XE5vWCXpJKExRgZvJdbzxrY3fSFugo3/jrCPz62mquY9u4U55nspkADfd6Ws86J
tzVhlZzAM+CGmBvXETbPOJpP6HV2ORAXhxSX/x2Rn07Rm8kShMVUSeSpg2cH5MiyAXNFwfix
kZDykKSrudGq7u+YrAC/Q6isV4ohEZMAAAAAAAA=
--------------ms000000000208070102090606--