From: Dmitry Lenev Date: October 7 2010 4:45pm Subject: bzr push into mysql-5.5-runtime branch (Dmitry.Lenev:3158 to 3159) Bug#57061 List-Archive: http://lists.mysql.com/commits/120284 X-Bug: 57061 Message-Id: <20101007164554.C31291E5138@mockturtle> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0767789217==" --===============0767789217== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline 3159 Dmitry Lenev 2010-10-07 Fix for bug#57061 "User without privilege on routine can discover its existence". The problem was that user without any privileges on routine was able to find out whether it existed or not. DROP FUNCTION and DROP PROCEDURE statements were checking if routine being dropped existed and reported ER_SP_DOES_NOT_EXIST error/warning before checking if user had enough privileges to drop it. This patch solves this problem by changing code not to check if routine exists before checking if user has enough privileges to drop it. Moreover we no longer perform this check using a separate call instead we rely on sp_drop_routine() returning SP_KEY_NOT_FOUND if routine doesn't exist. This change also simplifies one of upcoming patches refactoring global read lock implementation. @ mysql-test/r/grant.result Updated test case after fixing bug#57061 "User without privilege on routine can discover its existence". Removed DROP PROCEDURE/FUNCTION statements which have started to fail after this fix (correctly). There is no need in dropping routines in freshly created database anyway. @ mysql-test/r/sp-security.result Added new test case for bug#57061 "User without privilege on routine can discover its existence". Updated existing tests according to new behaviour. @ mysql-test/suite/funcs_1/r/innodb_storedproc_06.result Updated test case after fixing bug#57061 "User without privilege on routine can discover its existence". Now we drop routines under user which has enough privileges to do so. @ mysql-test/suite/funcs_1/r/memory_storedproc_06.result Updated test case after fixing bug#57061 "User without privilege on routine can discover its existence". Now we drop routines under user which has enough privileges to do so. @ mysql-test/suite/funcs_1/r/myisam_storedproc_06.result Updated test case after fixing bug#57061 "User without privilege on routine can discover its existence". Now we drop routines under user which has enough privileges to do so. @ mysql-test/suite/funcs_1/storedproc/storedproc_06.inc Updated test case after fixing bug#57061 "User without privilege on routine can discover its existence". Now we drop routines under user which has enough privileges to do so. @ mysql-test/t/grant.test Updated test case after fixing bug#57061 "User without privilege on routine can discover its existence". Removed DROP PROCEDURE/FUNCTION statements which have started to fail after this fix (correctly). There is no need in dropping routines in freshly created database anyway. @ mysql-test/t/sp-security.test Added new test case for bug#57061 "User without privilege on routine can discover its existence". Updated existing tests according to new behaviour. @ sql/sp.cc Removed sp_routine_exists_in_table() which is no longer used. @ sql/sp.h Removed sp_routine_exists_in_table() which is no longer used. @ sql/sql_parse.cc When dropping routine we no longer check if routine exists before checking if user has enough privileges to do so. Moreover we no longer perform this check using a separate call instead we rely on sp_drop_routine() returning SP_KEY_NOT_FOUND if routine doesn't exist. modified: mysql-test/r/grant.result mysql-test/r/sp-security.result mysql-test/suite/funcs_1/r/innodb_storedproc_06.result mysql-test/suite/funcs_1/r/memory_storedproc_06.result mysql-test/suite/funcs_1/r/myisam_storedproc_06.result mysql-test/suite/funcs_1/storedproc/storedproc_06.inc mysql-test/t/grant.test mysql-test/t/sp-security.test sql/sp.cc sql/sp.h sql/sql_parse.cc 3158 Jon Olav Hauglid 2010-10-07 [merge] Merge from mysql-5.5-bugteam to mysql-5.5-runtime No conflicts added: include/welcome_copyright_notice.h renamed: config/ac-macros/ha_ndbcluster.m4 => storage/ndb/ndb_configure.m4 modified: client/mysql.cc client/mysql_upgrade.c client/mysqladmin.cc client/mysqlbinlog.cc client/mysqlcheck.c client/mysqldump.c client/mysqlimport.c client/mysqlshow.c client/mysqlslap.c client/mysqltest.cc configure.in mysql-test/collections/default.experimental mysql-test/include/ctype_numconv.inc mysql-test/include/index_merge2.inc mysql-test/r/ctype_ucs.result mysql-test/r/func_time.result mysql-test/r/index_merge_myisam.result mysql-test/suite/innodb/r/innodb-index.result mysql-test/suite/innodb/r/innodb-zip.result mysql-test/suite/innodb/r/innodb_bug52745.result mysql-test/suite/innodb/r/innodb_bug53591.result mysql-test/suite/innodb/r/innodb_file_format.result mysql-test/suite/sys_vars/r/innodb_file_format_basic.result mysql-test/t/func_time.test mysys/my_winfile.c sql/item_cmpfunc.cc sql/item_timefunc.cc sql/item_timefunc.h sql/mysqld.cc sql/sql_insert.cc sql/sql_update.cc sql/sql_update.h storage/innobase/handler/ha_innodb.cc storage/innobase/row/row0sel.c storage/ndb/plug.in storage/ndb/ndb_configure.m4 === modified file 'mysql-test/r/grant.result' --- a/mysql-test/r/grant.result 2010-08-16 15:16:07 +0000 +++ b/mysql-test/r/grant.result 2010-10-07 16:01:17 +0000 @@ -1448,8 +1448,6 @@ CREATE USER 'userbug33464'@'localhost'; GRANT CREATE ROUTINE ON dbbug33464.* TO 'userbug33464'@'localhost'; userbug33464@localhost dbbug33464 -DROP PROCEDURE IF EXISTS sp3; -DROP FUNCTION IF EXISTS fn1; CREATE PROCEDURE sp3(v1 char(20)) BEGIN SELECT * from dbbug33464.t6 where t6.f2= 'xyz'; === modified file 'mysql-test/r/sp-security.result' --- a/mysql-test/r/sp-security.result 2010-03-01 09:45:36 +0000 +++ b/mysql-test/r/sp-security.result 2010-10-07 16:01:17 +0000 @@ -44,7 +44,7 @@ ERROR 42000: SELECT command denied to us create procedure db1_secret.dummy() begin end; ERROR 42000: Access denied for user 'user1'@'localhost' to database 'db1_secret' drop procedure db1_secret.dummy; -ERROR 42000: PROCEDURE db1_secret.dummy does not exist +ERROR 42000: alter routine command denied to user 'user1'@'localhost' for routine 'db1_secret.dummy' drop procedure db1_secret.stamp; ERROR 42000: alter routine command denied to user 'user1'@'localhost' for routine 'db1_secret.stamp' drop function db1_secret.db; @@ -58,7 +58,7 @@ ERROR 42000: SELECT command denied to us create procedure db1_secret.dummy() begin end; ERROR 42000: Access denied for user ''@'%' to database 'db1_secret' drop procedure db1_secret.dummy; -ERROR 42000: PROCEDURE db1_secret.dummy does not exist +ERROR 42000: alter routine command denied to user ''@'%' for routine 'db1_secret.dummy' drop procedure db1_secret.stamp; ERROR 42000: alter routine command denied to user ''@'%' for routine 'db1_secret.stamp' drop function db1_secret.db; @@ -567,3 +567,28 @@ DROP USER 'tester'; DROP USER 'Tester'; DROP DATABASE B48872; End of 5.0 tests. +# +# Test for bug#57061 "User without privilege on routine can discover +# its existence." +# +drop database if exists mysqltest_db; +create database mysqltest_db; +# Create user with no privileges on mysqltest_db database. +create user bug57061_user@localhost; +create function mysqltest_db.f1() returns int return 0; +create procedure mysqltest_db.p1() begin end; +# Connect as user 'bug57061_user@localhost' +# Attempt to drop routine on which user doesn't have privileges +# should result in the same 'access denied' type of error whether +# routine exists or not. +drop function if exists mysqltest_db.f_does_not_exist; +ERROR 42000: alter routine command denied to user 'bug57061_user'@'localhost' for routine 'mysqltest_db.f_does_not_exist' +drop procedure if exists mysqltest_db.p_does_not_exist; +ERROR 42000: alter routine command denied to user 'bug57061_user'@'localhost' for routine 'mysqltest_db.p_does_not_exist' +drop function if exists mysqltest_db.f1; +ERROR 42000: alter routine command denied to user 'bug57061_user'@'localhost' for routine 'mysqltest_db.f1' +drop procedure if exists mysqltest_db.p1; +ERROR 42000: alter routine command denied to user 'bug57061_user'@'localhost' for routine 'mysqltest_db.p1' +# Connection 'default'. +drop user bug57061_user@localhost; +drop database mysqltest_db; === modified file 'mysql-test/suite/funcs_1/r/innodb_storedproc_06.result' --- a/mysql-test/suite/funcs_1/r/innodb_storedproc_06.result 2010-03-19 08:56:26 +0000 +++ b/mysql-test/suite/funcs_1/r/innodb_storedproc_06.result 2010-10-07 16:01:17 +0000 @@ -110,10 +110,10 @@ Ensure that root always has the GRANT CR -------------------------------------------------------------------------------- grant create routine on db_storedproc_1.* to 'user_1'@'localhost'; flush privileges; +DROP PROCEDURE IF EXISTS db_storedproc_1.sp3; +DROP FUNCTION IF EXISTS db_storedproc_1.fn1; user_1@localhost db_storedproc_1 -DROP PROCEDURE IF EXISTS sp3; -DROP FUNCTION IF EXISTS fn1; CREATE PROCEDURE sp3(v1 char(20)) BEGIN SELECT * from db_storedproc_1.t6 where t6.f2= 'xyz'; === modified file 'mysql-test/suite/funcs_1/r/memory_storedproc_06.result' --- a/mysql-test/suite/funcs_1/r/memory_storedproc_06.result 2010-03-19 08:56:26 +0000 +++ b/mysql-test/suite/funcs_1/r/memory_storedproc_06.result 2010-10-07 16:01:17 +0000 @@ -111,10 +111,10 @@ Ensure that root always has the GRANT CR -------------------------------------------------------------------------------- grant create routine on db_storedproc_1.* to 'user_1'@'localhost'; flush privileges; +DROP PROCEDURE IF EXISTS db_storedproc_1.sp3; +DROP FUNCTION IF EXISTS db_storedproc_1.fn1; user_1@localhost db_storedproc_1 -DROP PROCEDURE IF EXISTS sp3; -DROP FUNCTION IF EXISTS fn1; CREATE PROCEDURE sp3(v1 char(20)) BEGIN SELECT * from db_storedproc_1.t6 where t6.f2= 'xyz'; === modified file 'mysql-test/suite/funcs_1/r/myisam_storedproc_06.result' --- a/mysql-test/suite/funcs_1/r/myisam_storedproc_06.result 2010-03-19 08:56:26 +0000 +++ b/mysql-test/suite/funcs_1/r/myisam_storedproc_06.result 2010-10-07 16:01:17 +0000 @@ -111,10 +111,10 @@ Ensure that root always has the GRANT CR -------------------------------------------------------------------------------- grant create routine on db_storedproc_1.* to 'user_1'@'localhost'; flush privileges; +DROP PROCEDURE IF EXISTS db_storedproc_1.sp3; +DROP FUNCTION IF EXISTS db_storedproc_1.fn1; user_1@localhost db_storedproc_1 -DROP PROCEDURE IF EXISTS sp3; -DROP FUNCTION IF EXISTS fn1; CREATE PROCEDURE sp3(v1 char(20)) BEGIN SELECT * from db_storedproc_1.t6 where t6.f2= 'xyz'; === modified file 'mysql-test/suite/funcs_1/storedproc/storedproc_06.inc' --- a/mysql-test/suite/funcs_1/storedproc/storedproc_06.inc 2010-03-19 08:56:26 +0000 +++ b/mysql-test/suite/funcs_1/storedproc/storedproc_06.inc 2010-10-07 16:01:17 +0000 @@ -117,15 +117,15 @@ create user 'user_1'@'localhost'; grant create routine on db_storedproc_1.* to 'user_1'@'localhost'; flush privileges; +--disable_warnings +DROP PROCEDURE IF EXISTS db_storedproc_1.sp3; +DROP FUNCTION IF EXISTS db_storedproc_1.fn1; +--enable_warnings + # disconnect default; connect (user2, localhost, user_1, , db_storedproc_1); --source suite/funcs_1/include/show_connection.inc ---disable_warnings -DROP PROCEDURE IF EXISTS sp3; -DROP FUNCTION IF EXISTS fn1; ---enable_warnings - delimiter //; CREATE PROCEDURE sp3(v1 char(20)) BEGIN === modified file 'mysql-test/t/grant.test' --- a/mysql-test/t/grant.test 2010-08-16 15:16:07 +0000 +++ b/mysql-test/t/grant.test 2010-10-07 16:01:17 +0000 @@ -1419,11 +1419,6 @@ GRANT CREATE ROUTINE ON dbbug33464.* TO connect (connbug33464, localhost, userbug33464, , dbbug33464); --source suite/funcs_1/include/show_connection.inc ---disable_warnings -DROP PROCEDURE IF EXISTS sp3; -DROP FUNCTION IF EXISTS fn1; ---enable_warnings - delimiter //; CREATE PROCEDURE sp3(v1 char(20)) BEGIN === modified file 'mysql-test/t/sp-security.test' --- a/mysql-test/t/sp-security.test 2010-02-26 13:16:46 +0000 +++ b/mysql-test/t/sp-security.test 2010-10-07 16:01:17 +0000 @@ -82,7 +82,7 @@ select * from db1_secret.t1; # ...and not this --error ER_DBACCESS_DENIED_ERROR create procedure db1_secret.dummy() begin end; ---error ER_SP_DOES_NOT_EXIST +--error ER_PROCACCESS_DENIED_ERROR drop procedure db1_secret.dummy; --error ER_PROCACCESS_DENIED_ERROR drop procedure db1_secret.stamp; @@ -106,7 +106,7 @@ select * from db1_secret.t1; # ...and not this --error ER_DBACCESS_DENIED_ERROR create procedure db1_secret.dummy() begin end; ---error ER_SP_DOES_NOT_EXIST +--error ER_PROCACCESS_DENIED_ERROR drop procedure db1_secret.dummy; --error ER_PROCACCESS_DENIED_ERROR drop procedure db1_secret.stamp; @@ -926,6 +926,39 @@ DROP DATABASE B48872; --echo End of 5.0 tests. + +--echo # +--echo # Test for bug#57061 "User without privilege on routine can discover +--echo # its existence." +--echo # +--disable_warnings +drop database if exists mysqltest_db; +--enable_warnings +create database mysqltest_db; +--echo # Create user with no privileges on mysqltest_db database. +create user bug57061_user@localhost; +create function mysqltest_db.f1() returns int return 0; +create procedure mysqltest_db.p1() begin end; +--echo # Connect as user 'bug57061_user@localhost' +connect (conn1, localhost, bug57061_user,,); +--echo # Attempt to drop routine on which user doesn't have privileges +--echo # should result in the same 'access denied' type of error whether +--echo # routine exists or not. +--error ER_PROCACCESS_DENIED_ERROR +drop function if exists mysqltest_db.f_does_not_exist; +--error ER_PROCACCESS_DENIED_ERROR +drop procedure if exists mysqltest_db.p_does_not_exist; +--error ER_PROCACCESS_DENIED_ERROR +drop function if exists mysqltest_db.f1; +--error ER_PROCACCESS_DENIED_ERROR +drop procedure if exists mysqltest_db.p1; +--echo # Connection 'default'. +connection default; +disconnect conn1; +drop user bug57061_user@localhost; +drop database mysqltest_db; + + # Wait till all disconnects are completed --source include/wait_until_count_sessions.inc === modified file 'sql/sp.cc' --- a/sql/sp.cc 2010-09-30 10:43:43 +0000 +++ b/sql/sp.cc 2010-10-07 16:01:17 +0000 @@ -1636,38 +1636,6 @@ sp_exist_routines(THD *thd, TABLE_LIST * } -/** - Check if a routine exists in the mysql.proc table, without actually - parsing the definition. (Used for dropping). - - @param thd thread context - @param name name of procedure - - @retval - 0 Success - @retval - non-0 Error; SP_OPEN_TABLE_FAILED or SP_KEY_NOT_FOUND -*/ - -int -sp_routine_exists_in_table(THD *thd, int type, sp_name *name) -{ - TABLE *table; - int ret; - Open_tables_backup open_tables_state_backup; - - if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup))) - ret= SP_OPEN_TABLE_FAILED; - else - { - if ((ret= db_find_routine_aux(thd, type, name, table)) != SP_OK) - ret= SP_KEY_NOT_FOUND; - close_system_tables(thd, &open_tables_state_backup); - } - return ret; -} - - extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen, my_bool first) { === modified file 'sql/sp.h' --- a/sql/sp.h 2010-06-11 01:30:49 +0000 +++ b/sql/sp.h 2010-10-07 16:01:17 +0000 @@ -100,9 +100,6 @@ sp_cache_routine(THD *thd, int type, sp_ bool sp_exist_routines(THD *thd, TABLE_LIST *procs, bool any); -int -sp_routine_exists_in_table(THD *thd, int type, sp_name *name); - bool sp_show_create_routine(THD *thd, int type, sp_name *name); === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2010-10-06 14:34:28 +0000 +++ b/sql/sql_parse.cc 2010-10-07 16:01:17 +0000 @@ -4023,49 +4023,39 @@ create_sp_error: int sp_result; int type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ? TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION); + char *db= lex->spname->m_db.str; + char *name= lex->spname->m_name.str; - /* - @todo: here we break the metadata locking protocol by - looking up the information about the routine without - a metadata lock. Rewrite this piece to make sp_drop_routine - return whether the routine existed or not. - */ - sp_result= sp_routine_exists_in_table(thd, type, lex->spname); - thd->warning_info->opt_clear_warning_info(thd->query_id); - if (sp_result == SP_OK) - { - char *db= lex->spname->m_db.str; - char *name= lex->spname->m_name.str; - - if (check_routine_access(thd, ALTER_PROC_ACL, db, name, - lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) - goto error; + if (check_routine_access(thd, ALTER_PROC_ACL, db, name, + lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) + goto error; - /* Conditionally writes to binlog */ - sp_result= sp_drop_routine(thd, type, lex->spname); + /* Conditionally writes to binlog */ + sp_result= sp_drop_routine(thd, type, lex->spname); #ifndef NO_EMBEDDED_ACCESS_CHECKS - /* - We're going to issue an implicit REVOKE statement. - It takes metadata locks and updates system tables. - Make sure that sp_create_routine() did not leave any - locks in the MDL context, so there is no risk to - deadlock. - */ - close_mysql_tables(thd); + /* + We're going to issue an implicit REVOKE statement. + It takes metadata locks and updates system tables. + Make sure that sp_create_routine() did not leave any + locks in the MDL context, so there is no risk to + deadlock. + */ + close_mysql_tables(thd); - if (sp_automatic_privileges && !opt_noacl && - sp_revoke_privileges(thd, db, name, - lex->sql_command == SQLCOM_DROP_PROCEDURE)) - { - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_PROC_AUTO_REVOKE_FAIL, - ER(ER_PROC_AUTO_REVOKE_FAIL)); - /* If this happens, an error should have been reported. */ - goto error; - } -#endif + if (sp_result != SP_KEY_NOT_FOUND && + sp_automatic_privileges && !opt_noacl && + sp_revoke_privileges(thd, db, name, + lex->sql_command == SQLCOM_DROP_PROCEDURE)) + { + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_PROC_AUTO_REVOKE_FAIL, + ER(ER_PROC_AUTO_REVOKE_FAIL)); + /* If this happens, an error should have been reported. */ + goto error; } +#endif + res= sp_result; switch (sp_result) { case SP_OK: --===============0767789217== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/dmitry.lenev@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: dmitry.lenev@stripped # target_branch: file:///home/dlenev/src/bzr/mysql-5.5-rt-57061/ # testament_sha1: 2f13af7a13cab493a4078d68669d5f8bb6625305 # timestamp: 2010-10-07 20:45:54 +0400 # base_revision_id: jon.hauglid@stripped\ # spdl2b52bxbmzrae # # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWdLDMwoAC8b/gFUQIAh79/// f2//4L////JgFwcb2O+8OjrdvM5St3NNVN2ddYpUDjrHLs73dUqlzNas02w9moiilOw1C2yjSJUm SK4SkICn6ibUHoQZkmm0htJ6g0ANMg0ABoaCSgAQBGhGmpD01DT0gNAAAaBoNGgOMmTRoDRpiMjQ xDAmjTEGI0GEABgkKBBJT2mKnqfqZTyjyaJ6jQ9TRoE0xGEZGACBFJATRkaNCMCZCeSNEPVP1TNR iDRtIGjQNAikEBMiYTBFPaBGmgpk0A0aGmg0AAHMcCIC0tfGosNZVdJJUleSSyXOOFKTBORtjM7Y Hgg9rn93dv4pzIrKPVp9LPj06rC8wjGxRu0oLpuA/NWapV3KSVH3H2XCly9DaPayI9zpiJ1k9Pnd Hq+F8gzi04mlgfYXB5psFhg09HbjPXYBcN+WerCFhKWK81Drw8ON0p+p0nObltbT5d/N4r3tSPt3 7sq4d6G/TNjDWMZ9p0F5gjtc08x1jUkct7403NbvY+riYgVypk4ZlLBPj+WTLaQMGMgJfjZ+ZZNl zUnJTopsSG2NsaG0222JtDYmzx7F+aS8R4ujly9J9DK4gr+qTJnUMu+qmdKO1IYdGUZkHXoppfMx jFYWzlcUJR1gWvlL1OwTzd65krCVWKyOBUKmqcU1UO1KRWzAoRkYmEDIh3hiB+9Jna9mBE1WH5+6 DSTCZ3t4+BH1DjLTrsnjBBF0/gf9Ke2o7kwgP7gCoBTWDXqTBQ8sS49AQP6LHwgevEVjJwjFE8Bo NDB6iKTeJ5pGRBkUhpMiIYhQeUE48cjyC9GlxoEjBlK+QGmFhxMIi9ybLDRj5KimdQ0oUWNrhiDm T39gy3xTRa8GBYYDAYRPOkWDBUsmcg6U2Jqm5kQRkKt1wkU5qF6IkqFCT8QYZMLXsKHALwVdrxMk kNE1aFjFMCxmRgTzYjK+2mJU9Q6DdeycRdDUSIxqrpmJrDhUs4BhTcni5GkQm+yHDJG81Iq4HlqQ unEC3Ro1Y+oFlUiGCJXwFomv785fZuz0UMbwW6IPYbnw3JdTTn7qpUcPLpJHflyLvd16bmb4oPVQ FeKREgXogxtjG22MfckTu9CqvEY6GNn+GGo+2yZdZ3BQGqQGXQJVJsEH4pj4mmKeJr+xDx9fk1NJ z7/lLwl7USsy/e2MM/AQhbfyBDvSUBMXcpDxGZh9wCdWXzvtEYptfHKeidawrf4A1NTmZgLbD2DW 2vKe2hohhhvW+0r4/OHCTUMMDaw5Q7ANJVvfozPojnBMPZ1E5fDKdTwILDxpqMi4LjXlX5F+yGAj rWBAwJdwHIKhMI4JaXCFULgYpZRRORmAytWwMH8h9H0+VI8hrjNJbs2nqnH0DSHTroKvhX3uFNgJ HBi3NA2FIZ2SLBmwDMgYGAYADeMy2i0FYQCq7Ci7TMQoUZMArAo6GCRSCGcTErAiTlxYFUqQ/cEV SMGYKArly5mXQSZUxmVC86F40nawSG9GTcaDSSJmIaBlos1ayoZ5Z4V4CyZo8NZJDWpMWhbo7NsJ GmkcwNe/Mgh+vLcTDDFxpMMxvplCtIjA+Ei4FYTBQ/Fhab6a8S3ThrsyMbYBal9woXZiaUNfBqWT owQkssJH4UaNxMYLdBtqUZm/deWlCzchbUyEczIoVh9lgrMC4NoYA4cjrLD6Yaj2bqC3GUhq6N5a xeFMUy3uEbSUuxTe2kWKYEzIg13KRUzOHOqAXHZkHHGkmyHh1Ec5a5kbLDOg7RQJiEgIGoMQPZay GlKdQi7wWqTjI54FeonDF7o2hgF5jnzrZPgNHVViVW7GJaZYCN5U5TtF8uRHGJf9e50GgJvW7MtJ /w5s+TzUVqIXi0zWa3UV9cobT3IZIYPmZbcqInxGlR6pxZSgYGZAEEFGYapk6MZmknS4O0saZ1Wq Q0fheNwO9Y0GGHOmKeUKRzueKZ6S95OFXXHUcthh0uGo6QLs5YLqDI8HhacTkUWfEeUKhEuuKGZ0 NT4vHk72gtfzdffve9qEbzGZMjZo7Du4Srg0Tp58seoxQTRhCvawUV7CiDNvnHKsyBZS4Ng2PAPJ sTYkiYSVbulipyB7VAbNuAfIqis/PAmQMCJ4QtFwVs5gNYvWSOAKpIgdbypzdxaGI1NbpMCodZg2 vRh6M3fgHa+DobacN+LNE3ThsaabDY2raYtuy4v3mhEWB1ojYzXSBoQd2Pi30rWDec8aVuIy6Coq zOwwdOe0oNWII+tTVzSMDea3mhljkZGWEjsYQacbKRvcXhQffoOOJq737xn2tCpBMep6Nhi97RtZ m53Olmy5vYy7DsM7bdcTpsnKJUpo2ISoENsM1LC0R3kFwT3lVIwLyeEusncQjQhTf5ZYBdzbjleF hPnfiUN5iPuaSNliWO3KoWNC43HhKWlvLzIsiJe6hwmjfzC4qWHYctJU1BZk5up0M35nhdmWwRyO VaCNrsIcbrQwKg2DcgzLiiLiSoUIwLmkKeFULTRqWPFjvMFMNwwOtbLmRHgnDqq9+BeXnSV206O0 9Hu7sHVtMOEHI2lhvzLVOJ5xOyOlaxibPQmuJqwbwqVDU0Jnd0ThtCBzGrBWWS7VEMlesQpplixu EGvHtsmpieZ9DQ7ITbUZePkQsQ4dY0cTCV9jXA4DzAhMaXEzHCj47O00IEyRcbrTMDAnect0AciJ bNrE90led0BTIEgvDWlX4PnuwIkh95I7bGZBRK1J2TSBQmECUTRl2rsBwhanpzCYweV4c2hc8wKn LbnmKMmo+Ga6t5YIbKXKsiGcaUpyuu1IxlCYFpQFQFXGV1xMs8kKqRLOAr3DF7SsxTLMSlH0954E 2KhTorJWjflj5AkbozUap0+cF93zGOOBpYY2yIHvUxymQkKQYjb9Snw4L6jnHcYskMlHy83cFve/ 6J/Ucv8FDtKG5cWmIYDP0+H9Rfkk0GqVHv+c+hKKqk1Q+6QqMqgiwaQALv37w87EY/z5M0F/nF6L nC87RYCZiL9PLCFEt2/FUoBki8ByHI7TWmwngcDFL/EDvvwqmE9LhvoIVbyp87WlCrdZrr/4JYOA WUsCBDLe5Ga0UeoPmY1mQOI4pBBD/UJkMA5RmhWprP7CGkXQjcqRN5wuAo80Yf7JLNBik1nLVLIc BmEyjBhqszmQzlBmHzUyBlm1RMhyh+wF/eBZmcq66jOo692BDY8Lut4DQhvIu8Pu+wj2iHzwMv1x BASGqB9MlJKbCFbJzG1NtfpalzZ8KzfjBYWCQ/QvrWqkhIwKi2Gy6RpoHzl/WIVAXwKZkqDDrMQv qIQcOw5kWOsISIJtmIeFtKbRDCYy+YwviJF59h5Unb9ekQLBHfYa+xyZyR8n7XE1lPE1GYGINgvd 9txee/DniDxykdeS5LIQtopQnt5E0DBnJhJB8na63a0zMHynUfqP8jJLSVRi8yHqIIAyqRxUo3GZ xRoBgEUUsJ1BqbjOandZSlhB90OY2CP7aD5QoR+BIOhoJHEr/mci0pZJ1MHqBpJOIoIbDTWSJoBM 4eHaJ5Mn2kyDE9PPMKkrzo/lhMrpVDN625dBBk43e/0a+bRDYp5BEEBM9Gtm6ZlE/7LHeVEDJzPe csiD4iMiZsNgVN56NQm+u84eB2GJItDTzNEG94G88MAX3aCQO3bCh7W4hoLvcJYmp1T7FKzlumtH mcycN5VeB3wVpF5+JGiI++UoKfYJZ0dkzTBFJJImoG46OPi4b0E4e8mO3VLVhzgVKpHV5lcDLBtO AG0gMBNQW0IUTEb1sismmKsXg1GcHUqQAlS3kqbERIj2FuWfd29532uYmOTAbjIXygb0c7tJioh8 AqbIXRejGMsyGUkYlH4MxkxcjMatYm5DcbCYhAuPU764BUf6+CXAczb+g9jXcdpqP0epx46zJCQU 5jWYUaQepceRuoIgCy1qe0yfebAYU2VpsFpFtElAIMGJlFCHVz5rl7zIXgrKyp+J5MNHIgevQafP 9ExFFcKVsDIj0CA6KUk5QkhoYWXR0GNEDMzXMwQodumtwwdZ3IP+UVh7XKCeksISQgThS4Ljq2Go 6iA+BU8Sb4HqHU7OrntnPLTMjPMxKh9Bmx4u50lh8AzZTPUvDA8jV71IUpKIE1yzsgvFLBezCecN MjbbMjPyPQSqFxgthITgXhtgyL8SdSANgEWnxLJxjIbeR8j192YrcOXidAmHLz2FlLHTOO/OZvcX qdVZcUCZxTGtZ6y3FVw12vk/ibDW7ba6kfIEOymwmU9p8axGLwJl4Y8cKRwYZI+r3EjiQVDOIoUB iDQMM6IUKAYBMqAy8KTH0tcT3FNQ5jTEsjic5PjjnE1qGyUe8bOokHc7QbgPrIAGUBUUxZ6GY44Q oyVgJJ8jSQEIsHfeA3ZHHMkr9spPup3IB5M5yO8PgHcPXad3f31PGdoTJq6FSo9wXJsz2xqaTPZ3 FF2GXISoKCouBuvB73k/Fm/qp8L1IU3AlieOAVcShTS9xIrg3t4HNn9A5BSPi9xjWIVMFI2PW4FF Pvvq6i2EM0NRCBpKJQXvblsJifwZwyOXqXMvU1npDplJlYHo4ni34PlrTkBeSJPYETDmIxc7HlMN zf6sy5Pgg7pEQQMzEJJadjDQfhB2WoW/TRqRT5O5vZCUrARHW9Q7szSw4CQ83i6wZt4PYfHJ+PmI 1anIlqgNre9tr3UXiSy09afAQJwlRJoAz1/E3q5oLAav8RrK0UzoOIqNUOghMpvSrQLUqlt8jNPF hHIcenRS8va69JiTztfHxoMA/V5+zDBDCIRjgcTtG9IMD8SQDUXdXgqHhJ9AKeAtvAFoUicTvfBo ZkHgffA3qcw6GgPc8nAczM6w3hFBoebg2NjOGSA8/fLXkUdTsq5zM1rtbDO832C5A9XzOpD9D08m k7XydboOV1Os3mFSuAcnS4C+DbQybKsH1XAdHsemSlzGYgQpiQKTB4SQZGfUIyN1D/47t+kGvmsS PRg63F8M3Nq/0fWlsgjtj18JJi6NmNUge0ANduc6mlne47SVTrdhQ9SLwEsY+o0JgBY0yaAnm/P8 +CdAe7TG9yCOP5GwRmxul8+rUBqEYvJmi5C/KDc52cpO8PW4ucMLEPfpOUBEEQEQBSvi3HLuCbSU EbakZQIwowVEzvB70mi4Ps2hEm944TBvMCVNBBn9c1MTJuC5SL8hCEJQQLMyoGNBWIA9CHNcCkxt BZhI8WAW+qRIOjxddwGYFrZCEJeJqxS5mkxtWp0e9zcErUIMhIBxCGcAENjJoHmX7woEgW5YIdHF ImHBklD1YKou+h4OF+jy82YASBgYCacdRTUJveZb7MeGWh16EE2wJYa1gghDyIZHzBF7CP4T8Mqb HE0EQQa3BV/K5kPaljAyHzEDMLWTshX7jgSmS9KDsZ3Wm2/KDgpx1naTLO6yAc+dVJywLVMx+AYx TAX2tMEgU4MB2sEzA0MGP0bz0mpCPkkiSmtwfL7gIyBwfi8UvMr2bpWFRfDku85TGFk2tc1ojxiZ tYQG5DyiSYr6TIP7KzFofS5w6vF7djxfJ4nJJDqe4+l97oVGG98SjzYe12u/YLiTUkIwykSGBiAI IVOaUPvJSgRpIkNrIQPewLloEwOjm1K4fmyBMw6XhAHmQ9CoV2vOkyIM5I8jCR0UlCXkx8bpA1yC 4iW2dO7SJxQaJrZkgzJEDayJ1FDff5IM4DWDiAGUVWBtMgep0J50kRSO90SIUYH4tnGwhivfK6Zv ih3FBokUVi3AlRFUQIQlmhMopd2fDmWz1AMFRjzMD1MAZJrPr9zwIaA36RDJMus2XMEMcTEhU9Ri EgHsiAKQFimBpe9uC0yFukPT2TekdTItA2Lv0S3Lz+Vt2UkUiQ3tkkkkkkkkkkkkkkk7Q/9g7X83 z1oZr400GqDNUNKrWwkozkSW5guJBigoMBhAiAXj0KEyskcBd18IYYM5i6iy4hXt4tgWBUE++uGW 58XNn3nMeEu7TSZpAj3FJkiw3WI9My/zXrKWujI0BNBB+EUE128DWvJNVKcCom6ZGCkho+p6Exxg jPMmA4jgppmaRSBX90GI5Vv5O6XSzuqpmqYLmDRhLm5wGxRQ9JHNKh4yJHmFYTKVxsA6gOsDAAQ8 jTUUp+FtLlKHmkOthaA/U133surobVU1mxCt8g7n24Ez4iOQsyBL7wUroYMmZPAFkEKQDJgtkj/E n1uYdzwcCgSIbX4Mz6ScrnaWLs5DvFNC6Q6M4GDO3zAUEDEDY3El+QVF0h8zBS01Xlw03iWj2FwD 0TzgeuZejikKpHN3v0Oh2Pjyize8n2tK4kKOt7SxtHSFIb3cyR5PoUlyDBjFwY3NZwZ5wxB07E7D QcJKnJgW93t3Fng8no525MDob312Vut363vcridraNqoYr3JNQ6fJ4t7QA+LJrzu39VSUE4pXgTK 6iFGgkduXe0u1NiWiNH5mxNrxnexxvc0oJG5qcxdzyuxuzvpneDQ7QcHZIa5c11aLE4+5/4u5Ipw oSGlhmYU --===============0767789217==--