From: Subject: Okapi, home of the stange girafe Date: Fri, 7 Feb 2003 08:59:06 +0100 MIME-Version: 1.0 Content-Type: multipart/related; type="text/html"; boundary="----=_NextPart_000_0000_01C2CE87.2BBF9D80" X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 This is a multi-part message in MIME format. ------=_NextPart_000_0000_01C2CE87.2BBF9D80 Content-Type: text/html; charset="windows-1250" Content-Transfer-Encoding: quoted-printable Content-Location: http://www.okapi.ca/up2/solaris8_ldap.php Okapi, home of the stange girafe
=

LDAP Account information in Solaris 8

 

Solaris 8 comes with "Out-of-the-box" support for LDAP account=20 databases - there's a module "/usr/lib/nss_ldap.so.1", and some = programs=20 called "ldapclient", "ldap_gen_profile", and "ldapcachemgr". At = the time=20 of writing, the documentation is sparse. (NOTE: Since then, = documentation=20 has appeared - see below)

See http://www.sun= .com/blueprints/1000/ldap-sol8.html=20 for extra info. Despite what the article says (you need various=20 crappy^H^H^H^H^H^H unnecessay LDAP extensions) you can get it to = work=20 against OpenLDAP 2.x

Here's how things are supposed to work:

  1. You run "ldap_gen_profile" with the appropriate arguments = (see the=20 man page). This returns an LDAP LDIF file. The directory entry = this=20 would create is called a profile.=20
  2. When the machine boots, "ldapclient" is run. It bootstraps = itself=20 (locating the LDAP server using either a commandline option or = some=20 mysterious DNS method). It loads the given profile from the LDAP = server.=20 It re-binds to the (possibly new) LDAP server, if necessary, and = stores=20 the configuration data under /var/ldap/ldap_client_file and=20 /var/ldap/ldap_client_cred=20
  3. "ldapcachemgr" runs, increasing performance by caching the = results.=20

Here's what really happens:

  1. You run ldap_gen_profile. It generates something like: =
dn: cn=3Ddefault,ou=3Dprofile,dc=3Ddomain,dc=3Dcom
SolarisLDAPServers: 192.168.3.5:389
SolarisSearchBaseDN: dc=3Ddomain,dc=3Dcom
SolarisAuthMethod: NS_LDAP_AUTH_NONE
SolarisTransportSecurity: NS_LDAP_SEC_NONE
SolarisSearchReferral: NS_LDAP_FOLLOWREF
SolarisSearchScope: NS_LDAP_SCOPE_ONELEVEL
SolarisSearchTimeLimit: 30
SolarisCacheTTL: 43200
cn: default
ObjectClass: top
ObjectClass: SolarisNamingProfile
  1. You realise you don't have the schema for the = SolarisNamingProfile=20 objectclass, or any of it's properties. Since LDAPv3 servers = require=20 that it (or you) know this, you can't use this. Note to Sun - = the LDAPv3=20 schema (including OIDs and syntaxes for the attributes) would be = a very=20 helpful thing to release.=20
  2. You try to use "ldapclient", passing commandline options = rather than=20 letting it bootstrap itself. This fails, because it seems to = want=20 something from the directory RootDSE which your server isn't=20 supplying.

    The answer is this: the "ldapclient" program=20 requires the "simple page mode" and "VLV (virtual list = view)"=20 optional LDAP controls. Since they're optional, this is = appalling=20 behaviour on the part of Sun. OpenLDAP users will find that = (currently)=20 OpenLDAP does not support these. Thus, the "ldapclient" will not = work.

    Interestingly, the NSS/PAM will work, just = not the=20 automated setup. What you have to do is listed below.
     =20
  3. You look for something, anything, which constitutes=20 documentation. There isn't any to speak of.

    Correction: = Sun have=20 now released the documentation for the Solaris 8 LDAP support in = Acrobat=20 format. The filename is "sun_ldap_setup.pdf", and the title is = "LDAP=20 Setup and Configuration guide". You can probably find in on http://docs.sun.com/ - if = you're using=20 OpenLDAP, since it assumes the existence of the "simple paged = mode" and=20 "VLV" controls.

    There is also now a (beginning of a = series,=20 apparently) article at: http://www.sun= .com/blueprints/1000/ldap-sol8.html
  4. What I did:
bash-2.03# ldd =
/usr/lib/nss_ldap.so.1
libsldap.so.1 =3D> /usr/lib/libsldap.so.1
libnsl.so.1 =3D> /usr/lib/libnsl.so.1
libsocket.so.1 =3D> /usr/lib/libsocket.so.1
libc.so.1 =3D> /usr/lib/libc.so.1
libldap.so.4 =3D> /usr/lib/libldap.so.4
libdoor.so.1 =3D> /usr/lib/libdoor.so.1
libdl.so.1 =3D> /usr/lib/libdl.so.1
libmp.so.2 =3D> /usr/lib/libmp.so.2
libresolv.so.2 =3D> /usr/lib/libresolv.so.2
/usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1

Hmm. What is "libsldap". It turns out this is the config file = parser.=20 You do this:

bash-2.03# strings /usr/lib/libsldap.so.1 | =
less

After a lot of hacking, you come up with = this:

bash-2.03# cat /var/ldap/ldap_client_file
NS_LDAP_SERVERS=3D192.168.3.5:389
NS_LDAP_SEARCH_BASEDN=3Ddc=3Ddomain,dc=3Dcom

And it works.

I believe the other available parameters are as follows. Mail me if you find any = others, or can=20 help document the /var/ldap/ldap_client_cred file. Note to SUN: = Please=20 assist me/us here?

 

Addendum - Jason J Hinze supplied the following information = about=20 ldap_client_cred:

 

Hello,=20
  
You may have already found the solution to this problem=20
yourself, but just in case you haven't, I thought I'd pass=20
on a recipe that worked for me. 
After much pain and agony, =
and finding your (very helpful!)=20
web page of notes, I've got the whole Solaris 8 / nss_ldap.so.1 /=20
OpenLDAP mess working.=20
  
  
I basically followed your recipe, generating a =
bogus profile=20
with ldap_gen_profile: 
# ldap_gen_profile -P bogus_profile -a =
simple \
  -b 'dc=3Ddomain,dc=3Dcom' -d 'domain.com' \
  -D 'cn=3Droot,dc=3Ddomain,dc=3Dcom' -w 'secret_stuff' \
  10.0.0.42
dn: cn=3Dbogus_profile,ou=3Dprofile,dc=3Ddomain,dc=3Dcom
        SolarisBindDN: cn=3Droot,dc=3Ddomain,dc=3Dcom
        SolarisBindPassword: {NS1}aBuncH0fCh4rs
        SolarisLDAPServers: 10.0.0.42
        SolarisSearchBaseDN: dc=3Ddomain,dc=3Dcom
        SolarisAuthMethod: NS_LDAP_AUTH_SIMPLE
        SolarisTransportSecurity: NS_LDAP_SEC_NONE
        SolarisSearchReferral: NS_LDAP_FOLLOWREF
        SolarisSearchScope: NS_LDAP_SCOPE_ONELEVEL
        SolarisSearchTimeLimit: 30
        SolarisCacheTTL: 43200
        cn: bogus_profile
        ObjectClass: top
        ObjectClass: SolarisNamingProfile
  
  
Using your handy-dandy attribute-name to =
config-file-key=20
conversion chart, I built ldap_client_file by hand: =
NS_LDAP_SERVERS=3D10.0.0.42
NS_LDAP_SEARCH_BASEDN=3Ddc=3Ddomain,dc=3Dcom
NS_LDAP_AUTH=3DNS_LDAP_AUTH_SIMPLE
  
  
And then I build ldap_client_cred by hand: =
NS_LDAP_BINDDN=3Dcn=3Droot,dc=3Ddomain,dc=3Dcom
NS_LDAP_BINDPASSWD=3D{NS1}aBuncH0FreallyWWIERDshiT
  
  
Then: 
# chown root =
/var/ldap/ldap_client_*
# chgrp bin /var/ldap/ldap_client_*
# chmod 644 /var/ldap/ldap_client_file
# chmod 600 /var/ldap/ldap_client_cred
# /etc/init.d/ldap.client start
And nss_ldap worked.  Finally. 

 

The available configuration options (and their mapping to the = LDAP=20 objectClasses) are:

 

Name = in=20 /var/ldap/ldap_client_file LDAP profile attribute Option prefix Default value Other options
NS_LDAP_FILE_VERSION        
NS_LDAP_BINDDN SolarisBindDN      
NS_LDAP_BINDPASSWD SolarisBindPassword      
NS_LDAP_SERVERS SolarisLDAPServers      
NS_LDAP_SEARCH_BASEDN SolarisSearchBaseDN      
NS_LDAP_AUTH SolarisAuthMethod NS_LDAP_AUTH_ NONE SIMPLE; SASL_CRAM_MD5; SASL_GSSAPI; = SASL_SPNEGO;=20 TLS
NS_LDAP_TRANSPORT_SEC SolarisTransportSecurity NS_LDAP_SEC_ NONE TLS; SASL_PRIVACY; SASL_INTEGRITY
NS_LDAP_SEARCH_REF SolarisSearchReferral NS_LDAP_ FOLLOWREF NOREF
NS_LDAP_DOMAIN        
NS_LDAP_EXP        
NS_LDAP_CERT_PATH SolarisCertificatePath      
NS_LDAP_CERT_PASS SolarisCertificatePassword      
NS_LDAP_SEARCH_DN SolarisDataSearchDN      
NS_LDAP_SEARCH_SCOPE SolarisSearchScope NS_LDAP_SCOPE_ _ONELEVEL BASE; SUBTREE
NS_LDAP_SEARCH_TIME SolarisSearchTimeLimit      
NS_LDAP_SERVER_PREF SolarisPreferredServer      
NS_LDAP_PREF_ONLY SolarisPreferredServerOnly NS_LDAP_   TRUE; FALSE
NS_LDAP_CACHETTL SolarisCacheTTL   43200  
NS_LDAP_PROFILE        

 

There are a couple of other points:

 

  1. LDAP server faliure

If the LDAP server fails, all logins (even local password = files) will=20 fail except root. You need to change this:

 

passwd: files ldap
group: files ldap

To this:

passwd: files ldap [TRYAGAIN=3D5]
group: files ldap [TRYAGAIN=3D5]

In the /etc/nsswitch.conf file. This will allow the LDAP = lookups to=20 timeout after 5 attempts (in this example).

  1. For user account entries, I think you need this: =
dn: =
uid=3Duid,ou=3DPeople,ou=3DDirectory,dc=3Ddomain,dc=3Dcom
objec=
tclass: top
objectclass: posixAccount
objectclass: =
shadowAccount
<posix/shadowAccount specific stuff>

 

NOTE: the "objectclass: shadowAccount" is MANDATORY - this must = be=20 there, or things won't work.

 

Also - the following LDAPv3 schema may help, from a posting on = the=20 OpenLDAP mailing list. TBD is probably 42, Sun's enterprise number = as=20 registered with IANA.

# solaris.schema
# ''works in progress and incomplete''. =20
# It would help if sun would publish this information!=20
# If you have any comments/suggestion/correction
# please let me know (igor 'at' ipass 'dot' net)

attributetype ( 1.3.6.1.4.1.TBD.1.1.12 SUP name
	NAME 'nisDomain' )

objectclass ( 1.3.6.1.4.1.TBD.1.4.2
	NAME 'nisDomainObject'
	SUP top AUXILIARY
	MUST ( nisDomain ) )

# Below is optional unless you want to use ldap_gen_profile
attributetype ( 1.3.6.1.4.1.TBD.1.1.1 SUP name
	NAME 'SolarisBindDN'
	SINGLE-VALUE )

attributetype ( 1.3.6.1.4.1.TBD.1.1.2 SUP name
	NAME 'SolarisBindPassword'
	SINGLE-VALUE)

attributetype ( 1.3.6.1.4.1.TBD.1.1.3 SUP name
	NAME 'SolarisLDAPServers'
	SINGLE-VALUE)

attributetype ( 1.3.6.1.4.1.TBD.1.1.4 SUP name
	NAME 'SolarisSearchBaseDN'
	SINGLE-VALUE)

attributetype ( 1.3.6.1.4.1.TBD.1.1.5 SUP name
	NAME 'SolarisAuthMethod'
	SINGLE-VALUE)

attributetype ( 1.3.6.1.4.1.TBD.1.1.6 SUP name
	NAME 'SolarisTransportSecurity'
	SINGLE-VALUE)

attributetype ( 1.3.6.1.4.1.TBD.1.1.7 SUP name
	NAME 'SolarisSearchReferral'
	SINGLE-VALUE)

attributetype ( 1.3.6.1.4.1.TBD.1.1.8 SUP name
	NAME 'SolarisDataSearchDN'
	SINGLE-VALUE)

attributetype ( 1.3.6.1.4.1.TBD.1.1.9 SUP name
	NAME 'SolarisSearchScope'
	SINGLE-VALUE)

attributetype ( 1.3.6.1.4.1.TBD.1.1.10=20
	NAME 'SolarisSearchTimeLimit'
	EQUALITY integerMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )

attributetype ( 1.3.6.1.4.1.TBD.1.1.11=20
	NAME 'SolarisCacheTTL'
	EQUALITY integerMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )

objectclass ( 1.3.6.1.4.1.TBD.1.4.1
	NAME 'SolarisNamingProfile'
	DESC 'Solaris LDAP NSS Profile'
	SUP top AUXILIARY
	MUST ( cn $ SolarisLDAPServers )
	MAY	( SolarisBindDN $ SolarisBindPassword $=20
		SolarisSearchBaseDN $ SolarisAuthMethod $
		SolarisTransportSecurity $ SolarisSearchReferral $
		SolarisDataSearchDN $ SolarisSearchScope $
		SolarisSearchTimeLimit $ SolarisCacheTTL ) )


# End of solaris.scheam 

This is courtesy of Igor Brezac, whose full mail to the=20 openldap-software list is show below:

 

Here it goes.
First apply the patch =
below to OpenLDAP.  This patch allows OpenLDAP to
return all root DSE attributes without explicitely specifying=20
attribute list in a query.  Kurt, please let me know if I am missing
something.  
--- servers/slapd/result.c.orig	Fri Sep  8 =
12:59:11 2000
+++ servers/slapd/result.c	Fri Sep  8 18:38:50 2000
@@ -628,8 +628,10 @@
 			/* all addrs request, skip operational attributes */
 			if( is_at_operational( desc->ad_type ) )
 			{
-				continue;
-			}
+				if (strcasecmp( e->e_dn, LDAP_ROOT_DSE )) {
+					continue;
+				}
+			}=20
 
 		} else {
 			/* specific addrs requested */
@@ -700,7 +702,9 @@
 		if ( attrs =3D=3D NULL ) {
 			/* all addrs request, skip operational attributes */
 			if( is_at_operational( desc->ad_type ) ) {
-				continue;
+				if (strcasecmp( e->e_dn, LDAP_ROOT_DSE )) {
+					continue;
+				}
 			}
 
 		} else =
{
------------------------------------------------
Ad=
d the following schema to your OpenLDAP config:
# =
solaris.schema
# ''works in progress and incomplete''. =20
# It would help if sun would publish this information!=20
# If you have any comments/suggestion/correction
# please let me know (igor 'at' ipass 'dot' net)
attributetype =
( 1.3.6.1.4.1.TBD.1.1.12 SUP name
	NAME 'nisDomain' )
objectclass ( 1.3.6.1.4.1.TBD.1.4.2
	NAME 'nisDomainObject'
	SUP top AUXILIARY
	MUST ( nisDomain ) )
# Below is optional unless you want to =
use ldap_gen_profile
attributetype ( 1.3.6.1.4.1.TBD.1.1.1 SUP name
	NAME 'SolarisBindDN'
	SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.TBD.1.1.2 SUP name
	NAME 'SolarisBindPassword'
	SINGLE-VALUE)
attributetype ( 1.3.6.1.4.1.TBD.1.1.3 SUP name
	NAME 'SolarisLDAPServers'
	SINGLE-VALUE)
attributetype ( 1.3.6.1.4.1.TBD.1.1.4 SUP name
	NAME 'SolarisSearchBaseDN'
	SINGLE-VALUE)
attributetype ( 1.3.6.1.4.1.TBD.1.1.5 SUP name
	NAME 'SolarisAuthMethod'
	SINGLE-VALUE)
attributetype ( 1.3.6.1.4.1.TBD.1.1.6 SUP name
	NAME 'SolarisTransportSecurity'
	SINGLE-VALUE)
attributetype ( 1.3.6.1.4.1.TBD.1.1.7 SUP name
	NAME 'SolarisSearchReferral'
	SINGLE-VALUE)
attributetype ( 1.3.6.1.4.1.TBD.1.1.8 SUP name
	NAME 'SolarisDataSearchDN'
	SINGLE-VALUE)
attributetype ( 1.3.6.1.4.1.TBD.1.1.9 SUP name
	NAME 'SolarisSearchScope'
	SINGLE-VALUE)
attributetype ( 1.3.6.1.4.1.TBD.1.1.10=20
	NAME 'SolarisSearchTimeLimit'
	EQUALITY integerMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE =
)
attributetype ( 1.3.6.1.4.1.TBD.1.1.11=20
	NAME 'SolarisCacheTTL'
	EQUALITY integerMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE =
)
objectclass ( 1.3.6.1.4.1.TBD.1.4.1
	NAME 'SolarisNamingProfile'
	DESC 'Solaris LDAP NSS Profile'
	SUP top AUXILIARY
	MUST ( cn $ SolarisLDAPServers )
	MAY	( SolarisBindDN $ SolarisBindPassword $=20
		SolarisSearchBaseDN $ SolarisAuthMethod $
		SolarisTransportSecurity $ SolarisSearchReferral $
		SolarisDataSearchDN $ SolarisSearchScope $
		SolarisSearchTimeLimit $ SolarisCacheTTL ) )
# End of solaris.scheam =
-----------------------------------------------------
The nisDomainObject object must be added to the root DN: dn: dc=3Dexample,dc=3Dcom objectclass: nisDomainObject nisDomain: = example.com
---------------------------------------------------=
---
Run ldapclient
# ldapclient -i -d example.com -b dc=3Dexample,dc=3Dcom <ldap =
servers>
Check "man ldapclient" for more info.  You may =
need to pass -a -D -w
OR  =
-------------------
Profile use:
Add to ldap directory:
dn: ou=3DProfile,dc=3Dexample,dc=3Dcom
objectclass: top
objectclass: organizationalUnit
ou: Profile
ldap_gen_profile -P eng -d example.com -b =
dc=3Dexample,dc=3Dcom <ldap servers>|\
ldapadd=20
Again, You may need to pass -a -D -w=20
ldapclient -P eng -d example.com <ldap servers>
------------------------------------------------------
Double check /etc/nssswitch.conf.
If you use LDAP for groups, =
make sure to add userPassword (ex. userPassword:
{crypt}*) to (objectclass=3DposixGroup) entries.  Otherwise nscd will be
crashing and, trust me, you want nscd to work.
Be careful with =
pam_ldap.  Service names need to look similar to
other   auth required   /usr/lib/security/$ISA/pam_unix.so.1
other   auth sufficient  /usr/lib/security/$ISA/pam_ldap.so.1 =
use_first_pass
The Man pages suggest=20
other   auth sufficient   /usr/lib/security/$ISA/pam_unix.so.1
other   auth required     /usr/lib/security/$ISA/pam_ldap.so.1 =
use_first_pass
which will make your system open for public use.
I think that =
this is it...
Good luck.
-Igor
On Tue, 12 =
Sep 2000, Donald Hudson wrote:
> Date: Tue, 12 Sep 2000 =
12:19:55 -0700
> From: Donald Hudson
> Subject: configuring Solaris 8 pre-installed LDAP as NIS =
replacement?
>=20
> Has anyone successfully pulled together the information necessary =
to set
> up a directory to work as a NIS replacement for Solaris 8 clients =
using
> the "pre-installed" ldap support?  Solaris 8 appears to come
> pre-installed with the necessary modules (nss_ldap, pam_ldap) to =
use
> LDAP as a replacement for NIS, but documentation for setting it up =
seems
> to be almost non-existent!
>=20
> To start with, I've run into schema isssues.   Their client
> configuration utility "ldapclient", which is supposed to be the way =
to
> quickly configure a client for LDAP replacement of NIS, looks for a
> "nisDomainObject", which I was unable to find in the current set of
> nis/rfc2307 defs.  I did eventually locate a copy of Luke's 2307bis
> draft  with the additional defs (though that was difficult, as it
> appears to have expired and been dropped from the IETF site), so I =
was
> able to add the missing classes and attributes by hand.
>=20
> If I run their "ldap_gen_profile", which is supposed to create a =
LDIF
> file that can used to set up an LDAP entry that client machines can =
then
> use to when being configured for LDAP support, I see another set of
> objects and atttributes ( SolarisNamingProfile,  =
SolarisLDAPServers,
> SolarisSearchBaseDN, etc.)  that also don't appear to be in the =
schemas
> known to either the OpenLDAP server or the Netscape Directory =
Server.
> Anyone know where I can find the Solaris schema?
>=20
> Also, one side note about schema conflicts that I noticed when =
searching
> through the schemas.  RFC2307(bis) defines "nisMap" as .2.9, and =
appears
> to skip .2.13 in the list of class definitions.  Netscape's server
> appears to define .2.9 as "automount" (noting that it is =
deprecated),
> and defines .2.13 as "nisMap".
>=20
> Anyhow, if anyone out there has been through this same headache of
> trying to set up a Solaris 8 ldap client with the pre-installed =
software
> and can post a few details on how to do it, I'm sure it will be
> appreciated by more than just me.
>=20
> Donald Hudson



 

------=_NextPart_000_0000_01C2CE87.2BBF9D80 Content-Type: image/jpeg Content-Transfer-Encoding: base64 Content-Location: http://www.okapi.ca/images/okapi.jpg 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 ------=_NextPart_000_0000_01C2CE87.2BBF9D80 Content-Type: image/png Content-Transfer-Encoding: base64 Content-Location: http://www.okapi.ca/images/vi-htmls.png iVBORw0KGgoAAAANSUhEUgAAAGMAAACDCAMAAACuoVUlAAAAb1BMVEX/////9vb/7u7/5ub/3t7/ 1dX/zc3/xcX/vb3Nzc3/tLT/rKz/pKT/nJycnJz/YmL/Wlr/UlL/Skr/QUH/OTn/MTFzamr/KSn/ ICBiYmL/GBj/EBD/CAj/AADNAAA5MTExMTGcAABiAAAxAAAAAAAyy7sPAAAAFnRFWHRTb2Z0d2Fy ZQBnaWYycG5nIDIuMy4yphFRiwAABpVJREFUeJztWot24ygMNX4kITNLO3GyDm2zy+76/79xAfEQ L9txnE7nnFF7EiyDriWBuLZTVZ8tVItqEdM031hsN93PdfDDyTTGqEToJtNtar6RiIqaFtj1B9Bk M37ch8F9v6dh6I4iwVgcK2IwyATG6IY86AeIcDYrY0uAOWaaT8HgkBBumnfGCksZg8HVCNO8049l GFSpqGoK+jQMFSGmXOARxnaxotq8Blrhh2BKxByG7qz01RoM1SJz84ra1SdWY8zOXVcBWIxBKvjb AoPalIUYEGopNIdwZ6zMDKkijGS+rPGDWJtayR/HIEU/CHSR4bfHMUY+JffFKvs968dv+XqSW6IT y3aV0MwijXWYbKW66EQizPIMwVKdq3dohtp+0cQdU9NWBOrFjY5jizTGsLrFGCLoxjI6WFkZe0sx TLUWQvh+sU5kMPgdGP7ywbLamkfXcrXc1xzKncFlG5QpUdwkQXA1kZAOnfcecWvaYUxvUWEZzOic aY9BQwy/QRVAguKa07kDj+HDFqajtD4+HSO3OW2AwbE9ltHNY3BbSgrpMPMGjDOVPxrqJnJOFs5d eyn+kt3lCYs7okUjvJ9s6fqwseDUri2GdXbF+zVIKYvXIJ+tu7l6EN+rcRc0LywztgjCk6GxDqI2 JjqyGCMwaG8ksCem3qeepX6Ud05b5XQGnE5EOuSD1S33Q/fOze8FDyl+y2/5uSKKM1vW4PmSt8TQ 1KnPwLhP1mKQiaNlhrjaE+CUotGGLeumqnuEgUZ345LlymN1kvtuLDGUAI/6H+6KhRnNoCkqm4/R PXhjsmHPoRHYUOIFh/NqsGawAm70qVYzM698N7XXwyYbjkCGYgEdhSc6mk1S1dmogZfKLQV1Y/bJ aHZEBoOaLU6oh2uGUqrdlgNBqUysUDc7l6MRuMcUhpPKbI2C5TFIOmIphsDsAtgHh3ygbiTww42Y wKgMGzT5AFz3ocNm8uG6eYxgBOoRi7A3N9Q0dU6pG2HmLvfdfKzwCGwoDdbI9INI/dBLkjFuHiDJ lMsFxg0GVckRY+QHHoEMxQLUluswusd4lSOKru7qB7sszEcwAhtKPVG3P4Z+qIlInBpuiyw1odRc PDXqzAhnaI2YmjR1k/+w6MxQ4Z4QPEPMchNPhFDBFvK2+lfkjGz2XcDDcicf+QpCPBF4WnQsK1CP vQKuQEKC4GjD/YIrUMwVMEHwtGGNH75ae64AWkQQJkjBMgzrh+cKxPoRnVqHgWMVcgUSEoTK9lrn h41VxBU2xfCjLVdwfjgS8ghGsLM5rkAiP6ZIwSI/1CVSeElqDCX5ILxMChYI2u5jrhASBEsb1ohO NLPcfbTUnYXTwdGGVRjEbPemyaBhfp8BbXCYZnKOf8OxCh1JkTb4J0TiYYwSbdgQo0QbyIYYBGhD emJDjKJ8AsaWsSoKZU5+Nv+qm6Z+NkbT903hVHYVY93Sdd4N17ZwimcyGt4CL8x5ex26kh+BvRjX vymbxZjwA70pZKmKzmIQQhI/nM4eexO2UtFAM70+6valJZEfXuckCZYPld2ZyxikP/0Ag84P0v44 9dE0DqOPQyXILEbdDj2AWD8kRD+0EUYYGnzMomBmMDxIN2g/shD4uqvwuqvoOIfhQKQfXRECGaEB JFuEYUGas1znJQiU9fD1ECzr+bpbt5f+tSFNQ6rmtQDhsy7wZdupPL8G6/b8UhNVE+uXcx4ivHSB 2gsxVM1tusulrbUzecEpSAwuqiWkGz7er12tlnj+HTiKD/NwujdpEIa0UNe+UtRN23Xyv6nrbni/ 3d6vf+x3+/3OSdftdvvD4Xg4Ho+Hv60Zn5vvIN+OCKM7gBxhRTf99TrI/75pzu/Xj9vt400eXpSc TydZAeTf6XwZdKfrP9aMa/x7s+JU439OdzMYg5KrxLgYjLfrm7Q3SLu3RJwZ2/hrAUbddFp8rL4f dzpa6kMG6JsM0eEgo6UCuP9zDIXvj7KX6rDDsdpBgPfJ/DQ5b5TUNXzWMp3QblqVuORlY9PqbvID YejrVmOiiUPQ3FXwaq5MTV+whsYvW4PNzBoMpq8WzKRmMWSc+lft8kQt0RJg5NHzGLImXk+yJva6 Jp6mQPDLaXx/MBcr5cVJ1Xa9D5YLrxKc9YBIzexRnfYi2KMuXenHFSLrxtx+rgOlrtvu55PhYnk3 ZnhJfzoBZ3C8RHOGUvUtUM5JLup5judXROo2pdeuCpt8BLqtZYLvbiZNfy7dG2wmdXmb/dLyP7Yw 50RAhfd9AAAAAElFTkSuQmCC ------=_NextPart_000_0000_01C2CE87.2BBF9D80--