From 0ade6209bba807dd61f14188ff63740ce492b402 Mon Sep 17 00:00:00 2001 From: Jean-Gabriel Gill-Couture Date: Mon, 3 Feb 2025 08:16:24 -0500 Subject: [PATCH] feat: Support opnsense 25.1 config --- .../src/data/interfaces.rs | 1 + .../opnsense-config-xml/src/data/opnsense.rs | 14 +- .../opnsense-config/src/config/config.rs | 1 + .../src/tests/data/config-opnsense-25.1.xml | 940 ++++++++++++++++++ 4 files changed, 953 insertions(+), 3 deletions(-) create mode 100644 harmony-rs/opnsense-config/src/tests/data/config-opnsense-25.1.xml diff --git a/harmony-rs/opnsense-config-xml/src/data/interfaces.rs b/harmony-rs/opnsense-config-xml/src/data/interfaces.rs index 2da5e7f..4e518c7 100644 --- a/harmony-rs/opnsense-config-xml/src/data/interfaces.rs +++ b/harmony-rs/opnsense-config-xml/src/data/interfaces.rs @@ -33,6 +33,7 @@ pub struct Interface { pub networks: Option, pub subnetv6: Option, pub gateway: Option, + pub gatewayv6: Option, pub media: Option, pub mediaopt: Option, #[yaserde(rename = "track6-interface")] diff --git a/harmony-rs/opnsense-config-xml/src/data/opnsense.rs b/harmony-rs/opnsense-config-xml/src/data/opnsense.rs index 8fad4ed..aa39621 100644 --- a/harmony-rs/opnsense-config-xml/src/data/opnsense.rs +++ b/harmony-rs/opnsense-config-xml/src/data/opnsense.rs @@ -13,7 +13,6 @@ pub struct OPNsense { pub theme: String, pub sysctl: Sysctl, pub system: System, - // pub interfaces: RawXml, pub interfaces: NamedList, pub dhcpd: NamedList, pub snmpd: Snmpd, @@ -176,7 +175,7 @@ pub struct System { pub use_mfs_var: Option, pub serialspeed: u32, pub primaryconsole: String, - pub secondaryconsole: String, + pub secondaryconsole: Option, pub optimization: String, pub hostname: String, pub domain: String, @@ -216,7 +215,7 @@ pub struct System { pub aliasesresolveinterval: Option, pub maximumtableentries: Option, pub language: String, - pub dnsserver: MaybeString, + pub dnsserver: Option, pub dns1gw: Option, pub dns2gw: Option, pub dns3gw: Option, @@ -281,6 +280,14 @@ pub struct User { pub groupname: Option, pub password: String, pub uid: u32, + pub disabled: Option, + pub landing_page: Option, + pub comment: Option, + pub email: Option, + pub apikeys: Option, + #[yaserde(rename = "priv")] + pub priv_field: Option, + pub language: Option, pub expires: Option, pub authorizedkeys: Option, pub dashboard: Option, @@ -1560,6 +1567,7 @@ pub struct Hasync { pub synchronizednsresolver: Option, pub pfsyncinterface: Option, pub synchronizetoip: Option, + pub verifypeer: Option, pub username: Option, pub password: Option, pub pfsyncenabled: Option, diff --git a/harmony-rs/opnsense-config/src/config/config.rs b/harmony-rs/opnsense-config/src/config/config.rs index 205c1e6..614ebca 100644 --- a/harmony-rs/opnsense-config/src/config/config.rs +++ b/harmony-rs/opnsense-config/src/config/config.rs @@ -197,6 +197,7 @@ mod tests { #[tokio::test] async fn test_load_config_from_local_file() { for path in vec![ + "src/tests/data/config-opnsense-25.1.xml", "src/tests/data/config-vm-test.xml", "src/tests/data/config-structure.xml", "src/tests/data/config-full-1.xml", diff --git a/harmony-rs/opnsense-config/src/tests/data/config-opnsense-25.1.xml b/harmony-rs/opnsense-config/src/tests/data/config-opnsense-25.1.xml new file mode 100644 index 0000000..c6bc1a8 --- /dev/null +++ b/harmony-rs/opnsense-config/src/tests/data/config-opnsense-25.1.xml @@ -0,0 +1,940 @@ + + + opnsense + + + vfs.read_max + default + Increase UFS read-ahead speeds to match the state of hard drives and NCQ. + + + net.inet.ip.portrange.first + default + Set the ephemeral port range to be lower. + + + net.inet.tcp.blackhole + default + Drop packets to closed TCP ports without returning a RST + + + net.inet.udp.blackhole + default + Do not send ICMP port unreachable messages for closed UDP ports + + + net.inet.ip.random_id + default + Randomize the ID field in IP packets + + + net.inet.ip.sourceroute + default + + Source routing is another way for an attacker to try to reach non-routable addresses behind your box. + It can also be used to probe for information about your internal networks. These functions come enabled + as part of the standard FreeBSD core system. + + + + net.inet.ip.accept_sourceroute + default + + Source routing is another way for an attacker to try to reach non-routable addresses behind your box. + It can also be used to probe for information about your internal networks. These functions come enabled + as part of the standard FreeBSD core system. + + + + net.inet.icmp.log_redirect + default + + This option turns off the logging of redirect packets because there is no limit and this could fill + up your logs consuming your whole hard drive. + + + + net.inet.tcp.drop_synfin + default + Drop SYN-FIN packets (breaks RFC1379, but nobody uses it anyway) + + + net.inet6.ip6.redirect + default + Enable sending IPv6 redirects + + + net.inet6.ip6.use_tempaddr + default + Enable privacy settings for IPv6 (RFC 4941) + + + net.inet6.ip6.prefer_tempaddr + default + Prefer privacy addresses and use them over the normal addresses + + + net.inet.tcp.syncookies + default + Generate SYN cookies for outbound SYN-ACK packets + + + net.inet.tcp.recvspace + default + Maximum incoming/outgoing TCP datagram size (receive) + + + net.inet.tcp.sendspace + default + Maximum incoming/outgoing TCP datagram size (send) + + + net.inet.tcp.delayed_ack + default + Do not delay ACK to try and piggyback it onto a data packet + + + net.inet.udp.maxdgram + default + Maximum outgoing UDP datagram size + + + net.link.bridge.pfil_onlyip + default + Handling of non-IP packets which are not passed to pfil (see if_bridge(4)) + + + net.link.bridge.pfil_local_phys + default + Set to 1 to additionally filter on the physical interface for locally destined packets + + + net.link.bridge.pfil_member + default + Set to 0 to disable filtering on the incoming and outgoing member interfaces. + + + net.link.bridge.pfil_bridge + default + Set to 1 to enable filtering on the bridge interface + + + net.link.tap.user_open + default + Allow unprivileged access to tap(4) device nodes + + + kern.randompid + default + Randomize PID's (see src/sys/kern/kern_fork.c: sysctl_kern_randompid()) + + + hw.syscons.kbd_reboot + default + Disable CTRL+ALT+Delete reboot from keyboard. + + + net.inet.tcp.log_debug + default + Enable TCP extended debugging + + + net.inet.icmp.icmplim + default + Set ICMP Limits + + + net.inet.tcp.tso + default + TCP Offload Engine + + + net.inet.udp.checksum + default + UDP Checksums + + + kern.ipc.maxsockbuf + default + Maximum socket buffer size + + + vm.pmap.pti + default + Page Table Isolation (Meltdown mitigation, requires reboot.) + + + hw.ibrs_disable + default + Disable Indirect Branch Restricted Speculation (Spectre V2 mitigation) + + + security.bsd.see_other_gids + default + Hide processes running as other groups + + + security.bsd.see_other_uids + default + Hide processes running as other users + + + net.inet.ip.redirect + default + Enable/disable sending of ICMP redirects in response to IP packets for which a better, + and for the sender directly reachable, route and next hop is known. + + + + net.local.dgram.maxdgram + default + Maximum outgoing UDP datagram size + + + + normal + fw0 + harmony.mcd + 1 + + 1999 + admins + system + System Administrators + page-all + 0 + + + 0 + root + 0 + system + + + + + $2y$10$YRVoF4SkuhasdkjhasdkjhasdkjhasdkjhasdkjhasdkjhdsTwBfS + + + + + + + System Administrator + + + 2000 + 2000 + America/Toronto + 0.opnsense.pool.ntp.org 1.opnsense.pool.ntp.org 2.opnsense.pool.ntp.org 3.opnsense.pool.ntp.org + + https + 6796970f3b58c + + + + + + yes + 1 + 1 + 1 + 1 + 1 + 1 + 1 + hadp + hadp + hadp + + monthly + + 1 + 1 + + admins + 1 + + + + + + + enabled + 1 + 1 + + -1 + -1 + + + + + + + + + en_US + 115200 + video + + + + 1 + igc3 + dhcp + dhcp6 + WAN_GW + + + 0 + + + 1 + igc0 + 192.168.33.1 + 24 + + + + + + + + + 1 + Loopback + 1 + lo0 + 127.0.0.1 + ::1 + 8 + 128 + none + 1 + + + + + 1 + + 192.168.33.10 + 192.168.33.245 + + + + + + + public + + + + automatic + + + + + pass + inet + Default allow LAN to any rule + lan + + lan + + + + + + + pass + inet6 + Default allow LAN IPv6 to any rule + lan + + lan + + + + + + + + + + + 0.opnsense.pool.ntp.org + + + system_information-container:00000000-col3:show,services_status-container:00000001-col4:show,gateways-container:00000002-col4:show,interface_list-container:00000003-col4:show + 2 + + + (system) + /usr/local/opnsense/mvc/script/run_migrations.php made changes + + + + + + + + + + 0 + + + + + + + + + 0 + 0 + + + + + 16 + 32 + 4 + 1000 + 1 + + + + + + + + + 1 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + v9 + + + + 0 + + 1800 + 15 + + + + + + + + + 0 + 0 + 0 + wan + 192.168.0.0/16,10.0.0.0/8,172.16.0.0/12 + + + W0D23 + 4 + + + + + + + 0 + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + + 0 + 127.0.0.1 + 8000 + + + + + 0 + + 4000 + 1 + raw + + + 0 + + 2 + + + + + + + + + 0 + 120 + 120 + 127.0.0.1 + 25 + + + 0 + auto + 1 + + + + + 0 + root + + 2812 + + + 5 + 1 + + + 0 + root@localhost.local + 0 + + + + + + + 1 + $HOST + + system + + + + 300 + 30 +
+ + + + b9a4410c-bc95-4de6-ac83-567dd8cf60c0,c1ec5aac-2fda-45f5-a0d8-9bea7db470d6,f1a4fa3a-65a2-43da-b6e0-18b0361ac43b,76c03880-d148-413e-8097-3ee0aa33cb2c + + + + + 1 + RootFs + + filesystem + + + / + 300 + 30 +
+ + + + f24e0d56-0445-4e5f-9b58-3af0f246b80d + + + + + 0 + carp_status_change + + custom + + + /usr/local/opnsense/scripts/OPNsense/Monit/carp_status + 300 + 30 +
+ + + + f48cfab6-de1e-4006-bcd7-c8f8990d25d6 + + + + + 0 + gateway_alert + + custom + + + /usr/local/opnsense/scripts/OPNsense/Monit/gateway_alert + 300 + 30 +
+ + + + 5e0dc1c7-90ac-48cc-944e-e0b20c482656 + + + + + Ping + NetworkPing + failed ping + alert + + + + NetworkLink + NetworkInterface + failed link + alert + + + + NetworkSaturation + NetworkInterface + saturation is greater than 75% + alert + + + + MemoryUsage + SystemResource + memory usage is greater than 75% + alert + + + + CPUUsage + SystemResource + cpu usage is greater than 75% + alert + + + + LoadAvg1 + SystemResource + loadavg (1min) is greater than 8 + alert + + + + LoadAvg5 + SystemResource + loadavg (5min) is greater than 6 + alert + + + + LoadAvg15 + SystemResource + loadavg (15min) is greater than 4 + alert + + + + SpaceUsage + SpaceUsage + space usage is greater than 75% + alert + + + + ChangedStatus + ProgramStatus + changed status + alert + + + + NonZeroStatus + ProgramStatus + status != 0 + alert + + + + + + 0 + WAN_GW + WAN Gateway + wan + inet + + 1 + + 1 + + + + 255 + 1 + + + + + + + + + + + + + 1 + 1 + 31 + + + + + + + + + + + + 1 + 53 + + + + + + + + + + + + + + transparent + + + + + + + + + + 1 + + + + + + + + + + + + + 1 + 0 + + 0.0.0.0/8,10.0.0.0/8,100.64.0.0/10,169.254.0.0/16,172.16.0.0/12,192.0.2.0/24,192.168.0.0/16,198.18.0.0/15,198.51.100.0/24,203.0.113.0/24,233.252.0.0/24,::1/128,2001:db8::/32,fc00::/8,fd00::/8,fe80::/10 + + + + + + + + + + + + + + + + + + + allow + + + 0 + + + + + + +
+ + + + + + + + + + + + 0 + 0 + 0 + 1 + 0 + + + + + + + + + + + 0 + 0 + + + 1400 + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6796970f3b58c + Web GUI TLS certificate + + LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUhIakNDQlFhZ0F3SUJBZ0lVR3B1ZFZqRzR5a0JVYS9NUWxyU2ZBcWs5VCtRd0RRWUpLb1pJaHZjTkFRRUwKQlFBd2dZa3hIVEFiQmdOVkJBTU1GRTlRVG5ObGJuTmxMbXh2WTJGc1pHOXRZV2x1TVFzd0NRWURWUVFHRXdKTwpUREVWTUJNR0ExVUVDQXdNV25WcFpDMUliMnhzWVc1a01SVXdFd1lEVlFRSERBeE5hV1JrWld4b1lYSnVhWE14CkxUQXJCZ05WQkFvTUpFOVFUbk5sYm5ObElITmxiR1l0YzJsbmJtVmtJSGRsWWlCalpYSjBhV1pwWTJGMFpUQWUKRncweU5UQXhNall5TURFeU1EWmFGdzB5TmpBeU1qY3lNREV5TURaYU1JR0pNUjB3R3dZRFZRUUREQlJQVUU1egpaVzV6WlM1c2IyTmhiR1J2YldGcGJqRUxNQWtHQTFVRUJoTUNUa3d4RlRBVEJnTlZCQWdNREZwMWFXUXRTRzlzCmJHRnVaREVWTUJNR0ExVUVCd3dNVFdsa1pHVnNhR0Z5Ym1sek1TMHdLd1lEVlFRS0RDUlBVRTV6Wlc1elpTQnoKWld4bUxYTnBaMjVsWkNCM1pXSWdZMlZ5ZEdsbWFXTmhkR1V3Z2dJaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQwpEd0F3Z2dJS0FvSUNBUUM0alhjOXE4VENxMmZzc05zRU94dktuZm1FVjRNTzFRWDZNdmRReVN2QXIzNmRlNXVMCmZ3bkJSRnVkRC9zQ1B0ZzhXajVCaCtiNGF3WC9mOUdnQnNJbnhKNVB2SWFXMlBtWThpS0Q1Q01WQXhxUE1lMlQKT0VxaEYvWkJxZlNNUWk2RkVhTTRFS0J6bllMbzhnMlAyTW93VjBDbmI3aXVJVWlKRFF3a2JWOVZESG55VkhGaApkVVlONjlpTXRYMEZiSHVtY2tKWHJwQTVQcGFSdVdsaUNnNHl4dWxEOGRsL3dJOXAzZENQY2tNaXgvYjQ1aWdJCjZHbC9GUmhhZmx5VWJ2WWxSMEw5d1pVMmNpcHFQemJJR0tlZ2pkRVdIcGRzVW5sTnJiR1I0azZieWQ4ZGd1a0YKWlNVNUlUSkZRSFdNN3ZNNkZuMTloUE51NG94TEtVUTc1b1YwZDdHV2RaQ1RIYnU3R1hqekhhVHJKYnhTTjMyVApIcDFEMlhUQ1BPTEs1NjNMc2YrNm12Ty9BQSt5SWQyZ0tvWllsdG9GUDdGcHNwWmIwYnhqeWt1amxvOUg0TW1iCmpDeCtWTVkwWUozelVTU3NCOE5IdHpyS0hyVW9oMG9oNTZPNzBNQjZpUWt5dTNaZzNlL1lTUnJwOVJwMTFMMWwKU2F3NmIzMEtFOUh6VHkxWDVXczJlQmxYajFvS2FBVktlTEN4dzlnRDJuSFdqaHViTlFwSmhmdFY2S3F0TjFVeQp4NXBWUTRrL0l1VUNTRlRMK3JOTThWOEc1NCsxTlFTaWZlWVpLdzF4bGRIMlpDbjA1QURrWUhEaFI3VUtkSGhCCncycjkrTjNjdENSaVM1V1BlRTBhQzJ5bFU2czdtU0RwWGM1cy84SnA2QlN5c1ZYL3dpZGRFMWl4N1FJREFRQUIKbzRJQmVqQ0NBWFl3Q1FZRFZSMFRCQUl3QURBUkJnbGdoa2dCaHZoQ0FRRUVCQU1DQmtBd05BWUpZSVpJQVliNApRZ0VOQkNjV0pVOVFUbk5sYm5ObElFZGxibVZ5WVhSbFpDQlRaWEoyWlhJZ1EyVnlkR2xtYVdOaGRHVXdIUVlEClZSME9CQllFRkhIMGNpYU9qNXdrKzBLeFlYUFNtL1pveFpHT01JR3pCZ05WSFNNRWdhc3dnYWloZ1kra2dZd3cKZ1lreEhUQWJCZ05WQkFNTUZFOVFUbk5sYm5ObExteHZZMkZzWkc5dFlXbHVNUXN3Q1FZRFZRUUdFd0pPVERFVgpNQk1HQTFVRUNBd01XblZwWkMxSWIyeHNZVzVrTVJVd0V3WURWUVFIREF4TmFXUmtaV3hvWVhKdWFYTXhMVEFyCkJnTlZCQW9NSkU5UVRuTmxibk5sSUhObGJHWXRjMmxuYm1Wa0lIZGxZaUJqWlhKMGFXWnBZMkYwWllJVUdwdWQKVmpHNHlrQlVhL01RbHJTZkFxazlUK1F3SFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQ0FJQwpNQXNHQTFVZER3UUVBd0lGb0RBZkJnTlZIUkVFR0RBV2doUlBVRTV6Wlc1elpTNXNiMk5oYkdSdmJXRnBiakFOCkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQUhwcjZXQ2RmMzFWblR2RlMwUjA4RTUySHJvZHc3TjVJMGpwNkYrdHMKR2xsdGxaMDdvOWxvN2E5VFNBK1FnSGFQK1VOMkZUZmlFeHZ0RG0vdDZEQjhSald4ZnV4eloyOTMxeE8wWEhUNwp1Vll3OGpaYnlhOVQyU1VjTGR2ZFpyUHZFajJscnExYXRnc2UwMmhUUTdOSGhpd0hrbEdWTHR5K0FpaVc1STBPCkpPNGFiUHdBU3Z0SEtTU2hYTEhJY1NqWTIwLzF0TjUvdFRMTTFKUUFHZFM1NWU4YVpkdWRHWkVJdHlTZk0ya3kKY21zVnNMS0ZsL1ZLRmUrQnQySmd0d0FPUk0xbzM5WTZLQ2RHTkJPYThGUS9GQWhqZ2JrM1IwYVk3MEFBRDlyNQpXT0dPeEFxS0g5YmdhUUhrY05zSnNWekJlTFZzd3NPYnI2dktqUkUzSm1jTC9COGsxNVJaeXdMV2YxV2N6QzhwCjd5VDNUcW5vRXhQUlZZa3AzSmFQRkNncDN1YzQ0S01UZ1laQW4xeHJLS3hQdUV3NE0rSisyNzBGRzhqckJPN1UKdENMajVPMVpVMXBoVDBEckswVGloOHJlbkgrWDZkVUY4UmY4WDA0QXd5a3MzbjYramNoT3E2azFaaWVYT0NVYwppclM5eTFnNnZCM25YdW1kU05JdEZvQVhTWXRtOE5KaVUxN3kyanlnOWRHK3B4K1FpZTV2YjBMNE5xdzVoMFZhCldiWVpsMjA2cVpFenpFVEJtTHNuaWYydHB0aUlkbWh0UEZPYXBvT3hTL1ByV0V3VXc4NXdNQ0ZLcW1tZ3QzeVYKRUVlRXVRVTJIMFE5NS8wWGJOZnhKcVJSUXltOTBHeTlmTTUzU2VGbnpwVlU2VzJ6WTQyd3AwQktBZGxDdW9CdAplTjg9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + + LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRd0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1Mwd2dna3BBZ0VBQW9JQ0FRQzRqWGM5cThUQ3EyZnMKc05zRU94dktuZm1FVjRNTzFRWDZNdmRReVN2QXIzNmRlNXVMZnduQlJGdWREL3NDUHRnOFdqNUJoK2I0YXdYLwpmOUdnQnNJbnhKNVB2SWFXMlBtWThpS0Q1Q01WQXhxUE1lMlRPRXFoRi9aQnFmU01RaTZGRWFNNEVLQnpuWUxvCjhnMlAyTW93VjBDbmI3aXVJVWlKRFF3a2JWOVZESG55VkhGaGRVWU42OWlNdFgwRmJIdW1ja0pYcnBBNVBwYVIKdVdsaUNnNHl4dWxEOGRsL3dJOXAzZENQY2tNaXgvYjQ1aWdJNkdsL0ZSaGFmbHlVYnZZbFIwTDl3WlUyY2lwcQpQemJJR0tlZ2pkRVdIcGRzVW5sTnJiR1I0azZieWQ4ZGd1a0ZaU1U1SVRKRlFIV003dk02Rm4xOWhQTnU0b3hMCktVUTc1b1YwZDdHV2RaQ1RIYnU3R1hqekhhVHJKYnhTTjMyVEhwMUQyWFRDUE9MSzU2M0xzZis2bXZPL0FBK3kKSWQyZ0tvWllsdG9GUDdGcHNwWmIwYnhqeWt1amxvOUg0TW1iakN4K1ZNWTBZSjN6VVNTc0I4Tkh0enJLSHJVbwpoMG9oNTZPNzBNQjZpUWt5dTNaZzNlL1lTUnJwOVJwMTFMMWxTYXc2YjMwS0U5SHpUeTFYNVdzMmVCbFhqMW9LCmFBVktlTEN4dzlnRDJuSFdqaHViTlFwSmhmdFY2S3F0TjFVeXg1cFZRNGsvSXVVQ1NGVEwrck5NOFY4RzU0KzEKTlFTaWZlWVpLdzF4bGRIMlpDbjA1QURrWUhEaFI3VUtkSGhCdzJyOStOM2N0Q1JpUzVXUGVFMGFDMnlsVTZzNwptU0RwWGM1cy84SnA2QlN5c1ZYL3dpZGRFMWl4N1FJREFRQUJBb0lDQUJ4UldLS1Y0TE1lS2V3Zmx2dW5OalI0CjJQaDlsUmFKaVVsQzJNQUVuam9LczVybWhJOTdCcndwQ1FXb2xoTmFJVVBoZFB3SkpsK256RnZQK1JKYzl4MnoKQmJlbWJlQm5tcVRsUW5hS1l2ZXVhanplcEYyYW5aanFYRmJuQlNjZ1lKTDZpZGpvZERaSlRQVUJieU5MV0hyaQphSUZJbTBYY3hZeUIvQUw2NVUzZmhEYXl6bEx0ODduZkhuTTR4ZDQzTHlIekZrcnQ5aU5TZnpnTkF5YVA5RzNHCko3VE5QMXBpNlo2TThwdVFKTTBKY2RQdlBPVmhCQThENWFDOUV1ZVR2eUVwTmhaSnhlTjgwUlZNYmROMk5RSmwKd0Zkc2lqK015Q0FyTHJ2N3hhUVI3YkpSaS8vUDdVNCswYi9lakNyNzMwWmlmUTd0ZjR6Y0pqckNNajRldVF0SwowSHdmYll0L2NLVWc0aTlTd0hCRlg4QUxva2M1WkNkOXkxVEQzSU1LVlpDS0pFY24rT2gvMGRTT0pDWlFoTDdKClN1czBtUU1BVDYwTGkwZXhyMC92NjZ2dWJqTWpNcHhQVjlIY2RDbTRSbVU3aFMvQlJpaGpBc0ZqelhOVlFXQzMKSUVWVTNNRC92Q1hQRzZKb284bi9UOGhQWHc0T3U0NkE5RXF5dnR4VzFlWDgrMERFVFBreCtkbzJ2R0ZWRGtRMQpoNmNLSGVmMFFGSUViaHV2V1FKRTRWNE9VdEYyRlp6VjliS3laWE5jQnNTNWdkTlFKRmt1ZkYvOFV2SlFLT0tHCi9VeVYvejZrY01xMHNUc2JSRjNVSzM2QnUxSENudldoVlVvV3NBb2JKV3pBemRpRkt0V1BpclBJNW9TUWFob24Kc2JqejAwdUJJQkFhdk5rUVhiY0JBb0lCQVFEemF5bHc1VEFWYnBza3A1WUpnaWppTzVhRUNPQlNka1FwZ1Jodwo1Y0VWenZhbUlZZ2NDMVBjSE1DeUUvMjFITFF3OUtpcVRqSGJrTWhOMEs0TW1HeWJwM1hKL2hHYkd6UzRVSGFKClQrdyt4NDRWTUxxN2l4Q2dmc3JXRHNOU2RhOUFGYnEzYWg4REpaVjNIcHplRVlOR3BIZ2hzM041STNNckR2Q2QKeXowWjhNOStWdUpIVDBjYXVqa0JlTWtZbEhYVEdabnFtYzBoaFlUdDlZVGxTTXNMV1JEdUpkdDNoQjkyTDZLOApOa082Z2lxeURteWswbHZWejhSdFZBdUQ2TWtJaDEwT3lCRksyaEpCaVhQa0R5dmM4b1JSa2xpSmxaR3UzN2VXCmVacENYSmJ4MU5meGhnckhBbnhtbU91N3dVUG5oUUNGRW1RMmZicnNZcVkxZGVrMUFvSUJBUURDRjJoV0YwQjgKc0dUMVBoek0zR3RiVkpyVFh3bXFxb3BVYjlTVi9IU1JGMkJiWUUxNWFFMy9vMmVQVmovNDVoaUlyYVhweklVeQpaWkV4Yml4WkhoZy9Qa2NqeG1oTllmTUJrdFdQZHBvMFh6ZVBWQ1hFV0J2VXNBclc4RDI1ZzlkbHEzTlEyd0hqCktDQUtoZGJudU9OeUllT25DZ0tTTEdNbjJMbGJ0dWFJcmcxUnFkOU5KOCszOVQrUXZmNHVvWmxTenpPRHgwaTEKRlFMUEgxcitRdVZYMUVqL08va3kvSzJxcWRZSXlyUHRGTXpjSVdTZ3EyTWErZ1c5T29CK3NhL2JwNWZOMEl4cAp4WjlKa2grNDRjaFgvVkE4dDJORk9HVW5TOXNXRTlsNE9wcEdxSDNtZmtLMk12SnRpS3FSTG43S0k3dnVhRnRtCnk1eFdXdXNURW5UWkFvSUJBQUYxcmd6d1F1YU9BRDRyQnhwTmZvTkV5alZHZkZuaVBheG1Dc2g2aURyaVA5WmwKTXhTLytLUEVSRitOQVNONTVaYTVrTjFjbEszMVkwNGNKejhLRnZTai8yL1RwelZmNTJRSGozNXBUVWhmRi9vRwpqY2djSUdCbUFqOWdYVWw4VFMyOE01OXY4bm1wV3drWTFPWDhBdWFFaS9mZnhKeUFXdXR5TG4wenY4ME5CYUdEClVkNE5tcWFOWVZRaDdrckljU0J2OGQxWFNNU2ZzVmxmOUlrUGM3QkF1M3BDSGR2TW5nZXVaM0pyZk9KOGIxY2MKQVFqSC9pYjlGUGQyM283TzhZMnNpaUZSajlEOEY4bnUwaFFYQnpOTy9QNGtPNFd2c096MGlIeE5oR0JMZjlnNQpaNFlhUUt4SzFvWWkrcDdvbk1paG9vd3B2UklhbE9sZitoRXVBTlVDZ2dFQkFMcWJpc01MQkFOZURSTUZMdWVBCkhPL29maHN2U3JuOTBaV3hGM0ZGRWtYVmRkMGswQmdrUXFuQVQzY3VjNzg0YXVvdUdsQ1pSSTdadkNrTVJqTkEKamd0d016R2dOdlAvY29aV3lHRndwSDRwOWQ4bUJsR3FiTWVtb2lWWlFkODFkVWpZK0x3S2ROd1QzZ3AvOThrKwpwOTg1MmdqbHhPY0pLaVJMYUp0WFZIcWc3VWxReTlNQXJlT3VOZmxSMGlxL1VBeWdEbVZxbXVzUFVtNFZOWVUwCmlCQlRtQU5kaEJDVGc5Mk1BSzdmUlBKeWh5dzJKdXViSEdQNWNyOG1taGcxZW1EejF5NFlqb2U3YTVSdW0zVkUKRHowWjNhVWlwSjBPeGFKc2VpM1YwOGFXZ1hIaDJYcGNkb042cEQ3UG9UNkl0M3BkdFBoWStWZng5MVBIZ2pBSwpGTEVDZ2dFQkFLeVVmRjBqK09TZWFSV3JtdnhCdSs2czF0Y3hFNG1IYzNtaTZuenp3WGxPRTFuSGR2b2lyNmtVCldscVRVcU5kbFF3NU9oUUlOeHMxWXpyNWdvVmlSZlhsSUd3VVFJOTRuY09XSWhNNXY5SXU4RUV4alY2TnNjUUoKRGIzNjdFamV2NWJnbFJ5ejExcmdQZTlBVzlWcXpzZHNMcjdJUVcybHlaRWR6VmEzRUVCbXpaTW00T1V6a1dkVQo5TVd4N2kyRFlWNVF2b1BSMzcwNzR2elNNeFYrZDhYZmp4MFcwbzl2WWU1UHNVMVRTaEp3SkVtWXc0bmNmL3h1CitBVzRNQWtISlRONm1FYXg4SUlpV2VIN3VZT3UveDZtazZBejVIK3UyK2ZRcHpyZEtVVm02SWFLT2I1THlLQzcKTnFrZnpXeXdTNXlUWmorN3FibVZ2b3ZLYjZubXczRT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo= + + + +