瀏覽代碼

[Web] Update libs, fix U2F for Firefox Quantum

André 7 年之前
父節點
當前提交
e1eb83ef87

+ 34 - 30
data/web/inc/footer.inc.php

@@ -40,6 +40,7 @@ $(document).ready(function() {
     backdrop: 'static',
     keyboard: false
   });
+  $('#u2f_status_auth').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> Initializing, please wait...</p>');
   $('#ConfirmTFAModal').on('shown.bs.modal', function(){
       $(this).find('#token').focus();
       // If U2F
@@ -49,20 +50,21 @@ $(document).ready(function() {
           cache: false,
           dataType: 'script',
           url: "/api/v1/get/u2f-authentication/<?= (isset($_SESSION['pending_mailcow_cc_username'])) ? $_SESSION['pending_mailcow_cc_username'] : null; ?>",
-          success: function(data){
+          complete: function(data){
+            $('#u2f_status_auth').html('<?=$lang['tfa']['waiting_usb_auth'];?>');
             data;
+            setTimeout(function() {
+              console.log("Ready to authenticate");
+              u2f.sign(appId, challenge, registeredKeys, function(data) {
+                var form = document.getElementById('u2f_auth_form');
+                var auth = document.getElementById('u2f_auth_data');
+                console.log("Authenticate callback", data);
+                auth.value = JSON.stringify(data);
+                form.submit();
+              });
+            }, 1000);
           }
         });
-        setTimeout(function() {
-          console.log("sign: ", req);
-          u2f.sign(req, function(data) {
-            var form = document.getElementById('u2f_auth_form');
-            var auth = document.getElementById('u2f_auth_data');
-            console.log("Authenticate callback", data);
-            auth.value = JSON.stringify(data);
-            form.submit();
-          });
-        }, 1000);
       }
   });
   <?php endif; ?>
@@ -81,32 +83,34 @@ $(document).ready(function() {
     if ($(this).val() == "u2f") {
       $('#U2FModal').modal('show');
       $("option:selected").prop("selected", false);
+      $('#u2f_status_reg').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> Initializing, please wait...</p>');
       $.ajax({
         type: "GET",
         cache: false,
         dataType: 'script',
         url: "/api/v1/get/u2f-registration/<?= (isset($_SESSION['mailcow_cc_username'])) ? $_SESSION['mailcow_cc_username'] : null; ?>",
-        success: function(data){
+        complete: function(data){
           data;
+          setTimeout(function() {
+            console.log("Ready to register");
+            $('#u2f_status_reg').html('<?=$lang['tfa']['waiting_usb_register'];?>');
+            u2f.register(appId, registerRequests, registeredKeys, function(deviceResponse) {
+              var form  = document.getElementById('u2f_reg_form');
+              var reg   = document.getElementById('u2f_register_data');
+              console.log("Register callback: ", data);
+              if (deviceResponse.errorCode && deviceResponse.errorCode != 0) {
+                var u2f_return_code = document.getElementById('u2f_return_code');
+                u2f_return_code.style.display = u2f_return_code.style.display === 'none' ? '' : null;
+                if (deviceResponse.errorCode == "4") { deviceResponse.errorCode = "4 - The presented device is not eligible for this request. For a registration request this may mean that the token is already registered, and for a sign request it may mean that the token does not know the presented key handle"; }
+                u2f_return_code.innerHTML = 'Error code: ' + deviceResponse.errorCode;
+                return;
+              }
+              reg.value = JSON.stringify(deviceResponse);
+              form.submit();
+            });
+          }, 1000);
         }
       });
-      setTimeout(function() {
-        console.log("Register: ", req);
-        u2f.register([req], sigs, function(data) {
-          var form  = document.getElementById('u2f_reg_form');
-          var reg   = document.getElementById('u2f_register_data');
-          console.log("Register callback", data);
-          if (data.errorCode && data.errorCode != 0) {
-            var u2f_return_code = document.getElementById('u2f_return_code');
-            u2f_return_code.style.display = u2f_return_code.style.display === 'none' ? '' : null;
-            if (data.errorCode == "4") { data.errorCode = "4 - The presented device is not eligible for this request. For a registration request this may mean that the token is already registered, and for a sign request it may mean that the token does not know the presented key handle"; }
-            u2f_return_code.innerHTML = 'Error code: ' + data.errorCode;
-            return;
-          }
-          reg.value = JSON.stringify(data);
-          form.submit();
-        });
-      }, 1000);
     }
     if ($(this).val() == "none") {
       $('#DisableTFAModal').modal('show');
@@ -212,4 +216,4 @@ $(document).ready(function() {
 </html>
 <?php
 $stmt = null;
-$pdo = null;
+$pdo = null;

+ 10 - 10
data/web/inc/lib/composer.lock

@@ -8,16 +8,16 @@
     "packages": [
         {
             "name": "phpmailer/phpmailer",
-            "version": "v5.2.25",
+            "version": "v5.2.26",
             "source": {
                 "type": "git",
                 "url": "https://github.com/PHPMailer/PHPMailer.git",
-                "reference": "2baf20b01690fba8cf720c1ebcf9b988eda50915"
+                "reference": "70362997bda4376378be7d92d81e2200550923f7"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2baf20b01690fba8cf720c1ebcf9b988eda50915",
-                "reference": "2baf20b01690fba8cf720c1ebcf9b988eda50915",
+                "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/70362997bda4376378be7d92d81e2200550923f7",
+                "reference": "70362997bda4376378be7d92d81e2200550923f7",
                 "shasum": ""
             },
             "require": {
@@ -81,20 +81,20 @@
                 }
             ],
             "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
-            "time": "2017-08-28T11:12:07+00:00"
+            "time": "2017-11-04T09:26:05+00:00"
         },
         {
             "name": "robthree/twofactorauth",
-            "version": "1.6",
+            "version": "1.6.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/RobThree/TwoFactorAuth.git",
-                "reference": "5093ab230cd8f1296d792afb6a49545f37e7fd5a"
+                "reference": "a77e7d822343bb88112baef808839cfae7bc5abb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/5093ab230cd8f1296d792afb6a49545f37e7fd5a",
-                "reference": "5093ab230cd8f1296d792afb6a49545f37e7fd5a",
+                "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/a77e7d822343bb88112baef808839cfae7bc5abb",
+                "reference": "a77e7d822343bb88112baef808839cfae7bc5abb",
                 "shasum": ""
             },
             "require": {
@@ -132,7 +132,7 @@
                 "php",
                 "tfa"
             ],
-            "time": "2017-02-17T15:24:54+00:00"
+            "time": "2017-11-06T17:55:56+00:00"
         },
         {
             "name": "yubico/u2flib-server",

+ 49 - 49
data/web/inc/lib/vendor/composer/installed.json

@@ -1,17 +1,54 @@
 [
+    {
+        "name": "yubico/u2flib-server",
+        "version": "1.0.1",
+        "version_normalized": "1.0.1.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/Yubico/php-u2flib-server.git",
+            "reference": "dc318c80b59e62921c210f31b014def26ceebbab"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/Yubico/php-u2flib-server/zipball/dc318c80b59e62921c210f31b014def26ceebbab",
+            "reference": "dc318c80b59e62921c210f31b014def26ceebbab",
+            "shasum": ""
+        },
+        "require": {
+            "ext-openssl": "*",
+            "php": ">=5.6"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "~5.7"
+        },
+        "time": "2017-05-09T07:33:58+00:00",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-2-Clause"
+        ],
+        "description": "Library for U2F implementation",
+        "homepage": "https://developers.yubico.com/php-u2flib-server"
+    },
     {
         "name": "robthree/twofactorauth",
-        "version": "1.6",
-        "version_normalized": "1.6.0.0",
+        "version": "1.6.1",
+        "version_normalized": "1.6.1.0",
         "source": {
             "type": "git",
             "url": "https://github.com/RobThree/TwoFactorAuth.git",
-            "reference": "5093ab230cd8f1296d792afb6a49545f37e7fd5a"
+            "reference": "a77e7d822343bb88112baef808839cfae7bc5abb"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/5093ab230cd8f1296d792afb6a49545f37e7fd5a",
-            "reference": "5093ab230cd8f1296d792afb6a49545f37e7fd5a",
+            "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/a77e7d822343bb88112baef808839cfae7bc5abb",
+            "reference": "a77e7d822343bb88112baef808839cfae7bc5abb",
             "shasum": ""
         },
         "require": {
@@ -20,7 +57,7 @@
         "require-dev": {
             "phpunit/phpunit": "@stable"
         },
-        "time": "2017-02-17T15:24:54+00:00",
+        "time": "2017-11-06T17:55:56+00:00",
         "type": "library",
         "installation-source": "dist",
         "autoload": {
@@ -52,56 +89,19 @@
             "tfa"
         ]
     },
-    {
-        "name": "yubico/u2flib-server",
-        "version": "1.0.1",
-        "version_normalized": "1.0.1.0",
-        "source": {
-            "type": "git",
-            "url": "https://github.com/Yubico/php-u2flib-server.git",
-            "reference": "dc318c80b59e62921c210f31b014def26ceebbab"
-        },
-        "dist": {
-            "type": "zip",
-            "url": "https://api.github.com/repos/Yubico/php-u2flib-server/zipball/dc318c80b59e62921c210f31b014def26ceebbab",
-            "reference": "dc318c80b59e62921c210f31b014def26ceebbab",
-            "shasum": ""
-        },
-        "require": {
-            "ext-openssl": "*",
-            "php": ">=5.6"
-        },
-        "require-dev": {
-            "phpunit/phpunit": "~5.7"
-        },
-        "time": "2017-05-09T07:33:58+00:00",
-        "type": "library",
-        "installation-source": "dist",
-        "autoload": {
-            "classmap": [
-                "src/"
-            ]
-        },
-        "notification-url": "https://packagist.org/downloads/",
-        "license": [
-            "BSD-2-Clause"
-        ],
-        "description": "Library for U2F implementation",
-        "homepage": "https://developers.yubico.com/php-u2flib-server"
-    },
     {
         "name": "phpmailer/phpmailer",
-        "version": "v5.2.25",
-        "version_normalized": "5.2.25.0",
+        "version": "v5.2.26",
+        "version_normalized": "5.2.26.0",
         "source": {
             "type": "git",
             "url": "https://github.com/PHPMailer/PHPMailer.git",
-            "reference": "2baf20b01690fba8cf720c1ebcf9b988eda50915"
+            "reference": "70362997bda4376378be7d92d81e2200550923f7"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2baf20b01690fba8cf720c1ebcf9b988eda50915",
-            "reference": "2baf20b01690fba8cf720c1ebcf9b988eda50915",
+            "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/70362997bda4376378be7d92d81e2200550923f7",
+            "reference": "70362997bda4376378be7d92d81e2200550923f7",
             "shasum": ""
         },
         "require": {
@@ -131,7 +131,7 @@
         "suggest": {
             "league/oauth2-google": "Needed for Google XOAUTH2 authentication"
         },
-        "time": "2017-08-28T11:12:07+00:00",
+        "time": "2017-11-04T09:26:05+00:00",
         "type": "library",
         "installation-source": "dist",
         "autoload": {

+ 1 - 1
data/web/inc/lib/vendor/phpmailer/phpmailer/VERSION

@@ -1 +1 @@
-5.2.25
+5.2.26

+ 3 - 1
data/web/inc/lib/vendor/phpmailer/phpmailer/class.phpmailer.php

@@ -31,7 +31,7 @@ class PHPMailer
      * The PHPMailer Version number.
      * @var string
      */
-    public $Version = '5.2.25';
+    public $Version = '5.2.26';
 
     /**
      * Email priority.
@@ -659,6 +659,8 @@ class PHPMailer
         if ($exceptions !== null) {
             $this->exceptions = (boolean)$exceptions;
         }
+        //Pick an appropriate debug output format automatically
+        $this->Debugoutput = (strpos(PHP_SAPI, 'cli') !== false ? 'echo' : 'html');
     }
 
     /**

+ 1 - 1
data/web/inc/lib/vendor/phpmailer/phpmailer/class.pop3.php

@@ -34,7 +34,7 @@ class POP3
      * @var string
      * @access public
      */
-    public $Version = '5.2.25';
+    public $Version = '5.2.26';
 
     /**
      * Default POP3 port number.

+ 2 - 2
data/web/inc/lib/vendor/phpmailer/phpmailer/class.smtp.php

@@ -30,7 +30,7 @@ class SMTP
      * The PHPMailer SMTP version number.
      * @var string
      */
-    const VERSION = '5.2.25';
+    const VERSION = '5.2.26';
 
     /**
      * SMTP line break constant.
@@ -81,7 +81,7 @@ class SMTP
      * @deprecated Use the `VERSION` constant instead
      * @see SMTP::VERSION
      */
-    public $Version = '5.2.25';
+    public $Version = '5.2.26';
 
     /**
      * SMTP server port number.

+ 4 - 1
data/web/inc/lib/vendor/robthree/twofactorauth/.gitignore

@@ -183,4 +183,7 @@ UpgradeLog*.htm
 FakesAssemblies/
 
 # Composer
-/vendor
+/vendor
+
+# .vs
+.vs/

+ 10 - 3
data/web/inc/lib/vendor/robthree/twofactorauth/.travis.yml

@@ -1,11 +1,18 @@
 language: php
 
+dist: trusty
+matrix:
+  include:
+    - php: 5.3
+      dist: precise
+
 php:
-  - 5.3
   - 5.4
   - 5.5
   - 5.6
-  - 7
+  - 7.0
+  - 7.1
   - hhvm
 
-script: phpunit --coverage-text tests
+script:
+  - if [[ "$TRAVIS_PHP_VERSION" == '5.6' ]]; then phpunit --coverage-text tests ; fi

+ 0 - 1031
data/web/inc/lib/vendor/robthree/twofactorauth/.vs/config/applicationhost.config

@@ -1,1031 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    IIS configuration sections.
-
-    For schema documentation, see
-    %IIS_BIN%\config\schema\IIS_schema.xml.
-    
-    Please make a backup of this file before making any changes to it.
-
-    NOTE: The following environment variables are available to be used
-          within this file and are understood by the IIS Express.
-
-          %IIS_USER_HOME% - The IIS Express home directory for the user
-          %IIS_SITES_HOME% - The default home directory for sites
-          %IIS_BIN% - The location of the IIS Express binaries
-          %SYSTEMDRIVE% - The drive letter of %IIS_BIN%
-
--->
-<configuration>
-
-    <!--
-
-        The <configSections> section controls the registration of sections.
-        Section is the basic unit of deployment, locking, searching and
-        containment for configuration settings.
-        
-        Every section belongs to one section group.
-        A section group is a container of logically-related sections.
-        
-        Sections cannot be nested.
-        Section groups may be nested.
-        
-        <section
-            name=""  [Required, Collection Key] [XML name of the section]
-            allowDefinition="Everywhere" [MachineOnly|MachineToApplication|AppHostOnly|Everywhere] [Level where it can be set]
-            overrideModeDefault="Allow"  [Allow|Deny] [Default delegation mode]
-            allowLocation="true"  [true|false] [Allowed in location tags]
-        />
-        
-        The recommended way to unlock sections is by using a location tag:
-        <location path="Default Web Site" overrideMode="Allow">
-            <system.webServer>
-                <asp />
-            </system.webServer>
-        </location>
-
-    -->
-    <configSections>
-        <sectionGroup name="system.applicationHost">
-            <section name="applicationPools" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-            <section name="configHistory" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-            <section name="customMetadata" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-            <section name="listenerAdapters" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-            <section name="log" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-            <section name="serviceAutoStartProviders" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-            <section name="sites" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-            <section name="webLimits" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-        </sectionGroup>
-
-        <sectionGroup name="system.webServer">
-            <section name="asp" overrideModeDefault="Deny" />
-            <section name="caching" overrideModeDefault="Allow" />
-            <section name="cgi" overrideModeDefault="Deny" />
-            <section name="defaultDocument" overrideModeDefault="Allow" />
-            <section name="directoryBrowse" overrideModeDefault="Allow" />
-            <section name="fastCgi" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-            <section name="globalModules" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-            <section name="handlers" overrideModeDefault="Deny" />
-            <section name="httpCompression" overrideModeDefault="Allow" />
-            <section name="httpErrors" overrideModeDefault="Allow" />
-            <section name="httpLogging" overrideModeDefault="Deny" />
-            <section name="httpProtocol" overrideModeDefault="Allow" />
-            <section name="httpRedirect" overrideModeDefault="Allow" />
-            <section name="httpTracing" overrideModeDefault="Deny" />
-            <section name="isapiFilters" allowDefinition="MachineToApplication" overrideModeDefault="Deny" />
-            <section name="modules" allowDefinition="MachineToApplication" overrideModeDefault="Deny" />
-            <section name="applicationInitialization" allowDefinition="MachineToApplication" overrideModeDefault="Allow" />
-            <section name="odbcLogging" overrideModeDefault="Deny" />
-            <sectionGroup name="security">
-                <section name="access" overrideModeDefault="Deny" />
-                <section name="applicationDependencies" overrideModeDefault="Deny" />
-                <sectionGroup name="authentication">
-                    <section name="anonymousAuthentication" overrideModeDefault="Deny" />
-                    <section name="basicAuthentication" overrideModeDefault="Deny" />
-                    <section name="clientCertificateMappingAuthentication" overrideModeDefault="Deny" />
-                    <section name="digestAuthentication" overrideModeDefault="Deny" />
-                    <section name="iisClientCertificateMappingAuthentication" overrideModeDefault="Deny" />
-                    <section name="windowsAuthentication" overrideModeDefault="Deny" />
-                </sectionGroup>
-                <section name="authorization" overrideModeDefault="Allow" />
-                <section name="ipSecurity" overrideModeDefault="Deny" />
-                <section name="dynamicIpSecurity" overrideModeDefault="Deny" />
-                <section name="isapiCgiRestriction" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
-                <section name="requestFiltering" overrideModeDefault="Allow" />
-            </sectionGroup>
-            <section name="serverRuntime" overrideModeDefault="Deny" />
-            <section name="serverSideInclude" overrideModeDefault="Deny" />
-            <section name="staticContent" overrideModeDefault="Allow" />
-            <sectionGroup name="tracing">
-                <section name="traceFailedRequests" overrideModeDefault="Allow" />
-                <section name="traceProviderDefinitions" overrideModeDefault="Deny" />
-            </sectionGroup>
-            <section name="urlCompression" overrideModeDefault="Allow" />
-            <section name="validation" overrideModeDefault="Allow" />
-            <sectionGroup name="webdav">
-                <section name="globalSettings" overrideModeDefault="Deny" />
-                <section name="authoring" overrideModeDefault="Deny" />
-                <section name="authoringRules" overrideModeDefault="Deny" />
-            </sectionGroup>
-            <sectionGroup name="rewrite">
-                <section name="allowedServerVariables" overrideModeDefault="Deny" />
-                <section name="rules" overrideModeDefault="Allow" />
-                <section name="outboundRules" overrideModeDefault="Allow" />
-                <section name="globalRules" overrideModeDefault="Deny" allowDefinition="AppHostOnly" />
-                <section name="providers" overrideModeDefault="Allow" />
-                <section name="rewriteMaps" overrideModeDefault="Allow" />
-            </sectionGroup>
-            <section name="webSocket" overrideModeDefault="Deny" />
-        <section name="aspNetCore" overrideModeDefault="Allow" /></sectionGroup>
-    </configSections>
-
-    <configProtectedData>
-        <providers>
-            <add name="IISWASOnlyRsaProvider" type="" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="iisWasKey" cspProviderName="" useMachineContainer="true" useOAEP="false" />
-            <add name="AesProvider" type="Microsoft.ApplicationHost.AesProtectedConfigurationProvider" description="Uses an AES session key to encrypt and decrypt" keyContainerName="iisConfigurationKey" cspProviderName="" useOAEP="false" useMachineContainer="true" sessionKey="AQIAAA5mAAAApAAAKmFQvWHDEETRz8l2bjZlRxIkwcqTFaCUnCLljn3Q1OkesrhEO9YyLyx4bUhsj1/DyShAv7OAFFhXlrlomaornnk5PLeyO4lIXxaiT33yOFUUgxDx4GSaygkqghVV0tO5yQ/XguUBp2juMfZyztnsNa4pLcz7ZNZQ6p4yn9hxwNs=" />
-            <add name="IISWASOnlyAesProvider" type="Microsoft.ApplicationHost.AesProtectedConfigurationProvider" description="Uses an AES session key to encrypt and decrypt" keyContainerName="iisWasKey" cspProviderName="" useOAEP="false" useMachineContainer="true" sessionKey="AQIAAA5mAAAApAAA4WoiRJ8KHwzAG8AgejPxEOO4/2Vhkolbwo/8gZeNdUDSD36m55hWv4uC9tr/MlKdnwRLL0NhT50Gccyftqz5xTZ0dg5FtvQhTw/he1NwexTKbV+I4Zrd+sZUqHZTsr7JiEr6OHGXL70qoISW5G2m9U8wKT3caPiDPNj2aAaYPLo=" />
-        </providers>
-    </configProtectedData>
-
-    <system.applicationHost>
-
-        <applicationPools>
-            <add name="Clr4IntegratedAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
-            <add name="Clr4ClassicAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
-            <add name="Clr2IntegratedAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
-            <add name="Clr2ClassicAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
-            <add name="UnmanagedClassicAppPool" managedRuntimeVersion="" managedPipelineMode="Classic" autoStart="true" />
-            <applicationPoolDefaults managedRuntimeLoader="v4.0">
-                <processModel />
-            </applicationPoolDefaults>
-        </applicationPools>
-
-        <!--
-
-          The <listenerAdapters> section defines the protocols with which the
-          Windows Process Activation Service (WAS) binds.
-
-        -->
-        <listenerAdapters>
-            <add name="http" />
-        </listenerAdapters>
-
-        <sites>
-            <site name="WebSite1" id="1" serverAutoStart="true">
-                <application path="/">
-                    <virtualDirectory path="/" physicalPath="%IIS_SITES_HOME%\WebSite1" />
-                </application>
-                <bindings>
-                    <binding protocol="http" bindingInformation=":8080:localhost" />
-                </bindings>
-            </site>
-            <siteDefaults>
-                <logFile logFormat="W3C" directory="%IIS_USER_HOME%\Logs" />
-                <traceFailedRequestsLogging directory="%IIS_USER_HOME%\TraceLogFiles" enabled="true" maxLogFileSizeKB="1024" />
-            </siteDefaults>
-            <applicationDefaults applicationPool="Clr4IntegratedAppPool" />
-            <virtualDirectoryDefaults allowSubDirConfig="true" />
-        </sites>
-
-        <webLimits />
-
-    </system.applicationHost>
-
-    <system.webServer>
-
-        <serverRuntime />
-
-        <asp scriptErrorSentToBrowser="true">
-            <cache diskTemplateCacheDirectory="%TEMP%\iisexpress\ASP Compiled Templates" />
-            <limits />
-        </asp>
-
-        <caching enabled="true" enableKernelCache="true">
-        </caching>
-
-        <cgi />
-
-        <defaultDocument enabled="true">
-            <files>
-                <add value="Default.htm" />
-                <add value="Default.asp" />
-                <add value="index.htm" />
-                <add value="index.html" />
-                <add value="iisstart.htm" />
-                <add value="default.aspx" />
-            </files>
-        </defaultDocument>
-
-        <directoryBrowse enabled="false" />
-
-        <fastCgi />
-
-        <!--
-
-          The <globalModules> section defines all native-code modules.
-          To enable a module, specify it in the <modules> section.
-
-        -->
-        <globalModules>
-            <add name="HttpLoggingModule" image="%IIS_BIN%\loghttp.dll" />
-            <add name="UriCacheModule" image="%IIS_BIN%\cachuri.dll" />
-<!--            <add name="FileCacheModule" image="%IIS_BIN%\cachfile.dll" />  -->
-            <add name="TokenCacheModule" image="%IIS_BIN%\cachtokn.dll" />
-<!--            <add name="HttpCacheModule" image="%IIS_BIN%\cachhttp.dll" /> -->
-            <add name="DynamicCompressionModule" image="%IIS_BIN%\compdyn.dll" />
-            <add name="StaticCompressionModule" image="%IIS_BIN%\compstat.dll" />
-            <add name="DefaultDocumentModule" image="%IIS_BIN%\defdoc.dll" />
-            <add name="DirectoryListingModule" image="%IIS_BIN%\dirlist.dll" />
-            <add name="ProtocolSupportModule" image="%IIS_BIN%\protsup.dll" />
-            <add name="HttpRedirectionModule" image="%IIS_BIN%\redirect.dll" />
-            <add name="ServerSideIncludeModule" image="%IIS_BIN%\iis_ssi.dll" />
-            <add name="StaticFileModule" image="%IIS_BIN%\static.dll" />
-            <add name="AnonymousAuthenticationModule" image="%IIS_BIN%\authanon.dll" />
-            <add name="CertificateMappingAuthenticationModule" image="%IIS_BIN%\authcert.dll" />
-            <add name="UrlAuthorizationModule" image="%IIS_BIN%\urlauthz.dll" />
-            <add name="BasicAuthenticationModule" image="%IIS_BIN%\authbas.dll" />
-            <add name="WindowsAuthenticationModule" image="%IIS_BIN%\authsspi.dll" />
-<!--            <add name="DigestAuthenticationModule" image="%IIS_BIN%\authmd5.dll" /> -->
-            <add name="IISCertificateMappingAuthenticationModule" image="%IIS_BIN%\authmap.dll" />
-            <add name="IpRestrictionModule" image="%IIS_BIN%\iprestr.dll" />
-            <add name="DynamicIpRestrictionModule" image="%IIS_BIN%\diprestr.dll" />
-            <add name="RequestFilteringModule" image="%IIS_BIN%\modrqflt.dll" />
-            <add name="CustomLoggingModule" image="%IIS_BIN%\logcust.dll" />
-            <add name="CustomErrorModule" image="%IIS_BIN%\custerr.dll" />
-<!--            <add name="TracingModule" image="%IIS_BIN%\iisetw.dll" /> -->
-            <add name="FailedRequestsTracingModule" image="%IIS_BIN%\iisfreb.dll" />
-            <add name="RequestMonitorModule" image="%IIS_BIN%\iisreqs.dll" />
-            <add name="IsapiModule" image="%IIS_BIN%\isapi.dll" />
-            <add name="IsapiFilterModule" image="%IIS_BIN%\filter.dll" />
-            <add name="CgiModule" image="%IIS_BIN%\cgi.dll" />
-            <add name="FastCgiModule" image="%IIS_BIN%\iisfcgi.dll" />
-<!--            <add name="WebDAVModule" image="%IIS_BIN%\webdav.dll" /> -->
-            <add name="RewriteModule" image="%IIS_BIN%\rewrite.dll" />
-            <add name="ConfigurationValidationModule" image="%IIS_BIN%\validcfg.dll" />
-            <add name="WebSocketModule" image="%IIS_BIN%\iiswsock.dll" />
-            <add name="WebMatrixSupportModule" image="%IIS_BIN%\webmatrixsup.dll" />
-            <add name="ManagedEngine" image="%windir%\Microsoft.NET\Framework\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness32" />
-            <add name="ManagedEngine64" image="%windir%\Microsoft.NET\Framework64\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness64" />
-            <add name="ManagedEngineV4.0_32bit" image="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness32" />
-            <add name="ManagedEngineV4.0_64bit" image="%windir%\Microsoft.NET\Framework64\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness64" />
-            <add name="ApplicationInitializationModule" image="%IIS_BIN%\warmup.dll" />
-            <add name="AspNetCoreModule" image="%IIS_BIN%\aspnetcore.dll" />
-        </globalModules>
-
-        <httpCompression directory="%TEMP%\iisexpress\IIS Temporary Compressed Files">
-            <scheme name="gzip" dll="%IIS_BIN%\gzip.dll" />
-            <dynamicTypes>
-                <add mimeType="text/*" enabled="true" />
-                <add mimeType="message/*" enabled="true" />
-                <add mimeType="application/javascript" enabled="true" />
-                <add mimeType="application/atom+xml" enabled="true" />
-                <add mimeType="application/xaml+xml" enabled="true" />
-                <add mimeType="*/*" enabled="false" />
-            </dynamicTypes>
-            <staticTypes>
-                <add mimeType="text/*" enabled="true" />
-                <add mimeType="message/*" enabled="true" />
-                <add mimeType="image/svg+xml" enabled="true" />
-                <add mimeType="application/javascript" enabled="true" />
-                <add mimeType="application/atom+xml" enabled="true" />
-                <add mimeType="application/xaml+xml" enabled="true" />
-                <add mimeType="*/*" enabled="false" />
-            </staticTypes>
-        </httpCompression>
-
-        <httpErrors lockAttributes="allowAbsolutePathsWhenDelegated,defaultPath">
-            <error statusCode="401" prefixLanguageFilePath="%IIS_BIN%\custerr" path="401.htm" />
-            <error statusCode="403" prefixLanguageFilePath="%IIS_BIN%\custerr" path="403.htm" />
-            <error statusCode="404" prefixLanguageFilePath="%IIS_BIN%\custerr" path="404.htm" />
-            <error statusCode="405" prefixLanguageFilePath="%IIS_BIN%\custerr" path="405.htm" />
-            <error statusCode="406" prefixLanguageFilePath="%IIS_BIN%\custerr" path="406.htm" />
-            <error statusCode="412" prefixLanguageFilePath="%IIS_BIN%\custerr" path="412.htm" />
-            <error statusCode="500" prefixLanguageFilePath="%IIS_BIN%\custerr" path="500.htm" />
-            <error statusCode="501" prefixLanguageFilePath="%IIS_BIN%\custerr" path="501.htm" />
-            <error statusCode="502" prefixLanguageFilePath="%IIS_BIN%\custerr" path="502.htm" />
-        </httpErrors>
-
-        <httpLogging dontLog="false" />
-
-        <httpProtocol>
-            <customHeaders>
-                <clear />
-                <add name="X-Powered-By" value="ASP.NET" />
-            </customHeaders>
-            <redirectHeaders>
-                <clear />
-            </redirectHeaders>
-        </httpProtocol>
-
-        <httpRedirect enabled="false" />
-
-        <httpTracing>
-        </httpTracing>
-
-        <isapiFilters>
-            <filter name="ASP.Net_2.0.50727-64" path="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="bitness64,runtimeVersionv2.0" />
-            <filter name="ASP.Net_2.0.50727.0" path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="bitness32,runtimeVersionv2.0" />
-            <filter name="ASP.Net_2.0_for_v1.1" path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="runtimeVersionv1.1" />
-            <filter name="ASP.Net_4.0_32bit" path="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_filter.dll" enableCache="true" preCondition="bitness32,runtimeVersionv4.0" />
-            <filter name="ASP.Net_4.0_64bit" path="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_filter.dll" enableCache="true" preCondition="bitness64,runtimeVersionv4.0" />
-        </isapiFilters>
-
-        <odbcLogging />
-
-        <security>
-
-            <access sslFlags="None" />
-
-            <applicationDependencies>
-                <application name="Active Server Pages" groupId="ASP" />
-            </applicationDependencies>
-
-            <authentication>
-
-                <anonymousAuthentication enabled="true" userName="" />
-
-                <basicAuthentication enabled="false" />
-
-                <clientCertificateMappingAuthentication enabled="false" />
-
-                <digestAuthentication enabled="false" />
-
-                <iisClientCertificateMappingAuthentication enabled="false">
-                </iisClientCertificateMappingAuthentication>
-
-                <windowsAuthentication enabled="false">
-                    <providers>
-                        <add value="Negotiate" />
-                        <add value="NTLM" />
-                    </providers>
-                </windowsAuthentication>
-
-            </authentication>
-
-            <authorization>
-                <add accessType="Allow" users="*" />
-            </authorization>
-
-            <ipSecurity allowUnlisted="true" />
-
-            <isapiCgiRestriction notListedIsapisAllowed="true" notListedCgisAllowed="true">
-                <add path="%windir%\Microsoft.NET\Framework64\v4.0.30319\webengine4.dll" allowed="true" groupId="ASP.NET_v4.0" description="ASP.NET_v4.0" />
-                <add path="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" allowed="true" groupId="ASP.NET_v4.0" description="ASP.NET_v4.0" />
-                <add path="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" allowed="true" groupId="ASP.NET v2.0.50727" description="ASP.NET v2.0.50727" />
-                <add path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" allowed="true" groupId="ASP.NET v2.0.50727" description="ASP.NET v2.0.50727" />
-            </isapiCgiRestriction>
-
-            <requestFiltering>
-                <fileExtensions allowUnlisted="true" applyToWebDAV="true">
-                    <add fileExtension=".asa" allowed="false" />
-                    <add fileExtension=".asax" allowed="false" />
-                    <add fileExtension=".ascx" allowed="false" />
-                    <add fileExtension=".master" allowed="false" />
-                    <add fileExtension=".skin" allowed="false" />
-                    <add fileExtension=".browser" allowed="false" />
-                    <add fileExtension=".sitemap" allowed="false" />
-                    <add fileExtension=".config" allowed="false" />
-                    <add fileExtension=".cs" allowed="false" />
-                    <add fileExtension=".csproj" allowed="false" />
-                    <add fileExtension=".vb" allowed="false" />
-                    <add fileExtension=".vbproj" allowed="false" />
-                    <add fileExtension=".webinfo" allowed="false" />
-                    <add fileExtension=".licx" allowed="false" />
-                    <add fileExtension=".resx" allowed="false" />
-                    <add fileExtension=".resources" allowed="false" />
-                    <add fileExtension=".mdb" allowed="false" />
-                    <add fileExtension=".vjsproj" allowed="false" />
-                    <add fileExtension=".java" allowed="false" />
-                    <add fileExtension=".jsl" allowed="false" />
-                    <add fileExtension=".ldb" allowed="false" />
-                    <add fileExtension=".dsdgm" allowed="false" />
-                    <add fileExtension=".ssdgm" allowed="false" />
-                    <add fileExtension=".lsad" allowed="false" />
-                    <add fileExtension=".ssmap" allowed="false" />
-                    <add fileExtension=".cd" allowed="false" />
-                    <add fileExtension=".dsprototype" allowed="false" />
-                    <add fileExtension=".lsaprototype" allowed="false" />
-                    <add fileExtension=".sdm" allowed="false" />
-                    <add fileExtension=".sdmDocument" allowed="false" />
-                    <add fileExtension=".mdf" allowed="false" />
-                    <add fileExtension=".ldf" allowed="false" />
-                    <add fileExtension=".ad" allowed="false" />
-                    <add fileExtension=".dd" allowed="false" />
-                    <add fileExtension=".ldd" allowed="false" />
-                    <add fileExtension=".sd" allowed="false" />
-                    <add fileExtension=".adprototype" allowed="false" />
-                    <add fileExtension=".lddprototype" allowed="false" />
-                    <add fileExtension=".exclude" allowed="false" />
-                    <add fileExtension=".refresh" allowed="false" />
-                    <add fileExtension=".compiled" allowed="false" />
-                    <add fileExtension=".msgx" allowed="false" />
-                    <add fileExtension=".vsdisco" allowed="false" />
-                    <add fileExtension=".rules" allowed="false" />
-                </fileExtensions>
-                <verbs allowUnlisted="true" applyToWebDAV="true" />
-                <hiddenSegments applyToWebDAV="true">
-                    <add segment="web.config" />
-                    <add segment="bin" />
-                    <add segment="App_code" />
-                    <add segment="App_GlobalResources" />
-                    <add segment="App_LocalResources" />
-                    <add segment="App_WebReferences" />
-                    <add segment="App_Data" />
-                    <add segment="App_Browsers" />
-                </hiddenSegments>
-            </requestFiltering>
-
-        </security>
-
-        <serverSideInclude ssiExecDisable="false" />
-
-        <staticContent lockAttributes="isDocFooterFileName">
-            <mimeMap fileExtension=".323" mimeType="text/h323" />
-            <mimeMap fileExtension=".3g2" mimeType="video/3gpp2" />
-            <mimeMap fileExtension=".3gp2" mimeType="video/3gpp2" />
-            <mimeMap fileExtension=".3gp" mimeType="video/3gpp" />
-            <mimeMap fileExtension=".3gpp" mimeType="video/3gpp" />
-            <mimeMap fileExtension=".aac" mimeType="audio/aac" />
-            <mimeMap fileExtension=".aaf" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".aca" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".accdb" mimeType="application/msaccess" />
-            <mimeMap fileExtension=".accde" mimeType="application/msaccess" />
-            <mimeMap fileExtension=".accdt" mimeType="application/msaccess" />
-            <mimeMap fileExtension=".acx" mimeType="application/internet-property-stream" />
-            <mimeMap fileExtension=".adt" mimeType="audio/vnd.dlna.adts" />
-            <mimeMap fileExtension=".adts" mimeType="audio/vnd.dlna.adts" />
-            <mimeMap fileExtension=".afm" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".ai" mimeType="application/postscript" />
-            <mimeMap fileExtension=".aif" mimeType="audio/x-aiff" />
-            <mimeMap fileExtension=".aifc" mimeType="audio/aiff" />
-            <mimeMap fileExtension=".aiff" mimeType="audio/aiff" />
-            <mimeMap fileExtension=".appcache" mimeType="text/cache-manifest" />
-            <mimeMap fileExtension=".application" mimeType="application/x-ms-application" />
-            <mimeMap fileExtension=".art" mimeType="image/x-jg" />
-            <mimeMap fileExtension=".asd" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".asf" mimeType="video/x-ms-asf" />
-            <mimeMap fileExtension=".asi" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".asm" mimeType="text/plain" />
-            <mimeMap fileExtension=".asr" mimeType="video/x-ms-asf" />
-            <mimeMap fileExtension=".asx" mimeType="video/x-ms-asf" />
-            <mimeMap fileExtension=".atom" mimeType="application/atom+xml" />
-            <mimeMap fileExtension=".au" mimeType="audio/basic" />
-            <mimeMap fileExtension=".avi" mimeType="video/msvideo" />
-            <mimeMap fileExtension=".axs" mimeType="application/olescript" />
-            <mimeMap fileExtension=".bas" mimeType="text/plain" />
-            <mimeMap fileExtension=".bcpio" mimeType="application/x-bcpio" />
-            <mimeMap fileExtension=".bin" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".bmp" mimeType="image/bmp" />
-            <mimeMap fileExtension=".c" mimeType="text/plain" />
-            <mimeMap fileExtension=".cab" mimeType="application/vnd.ms-cab-compressed" />
-            <mimeMap fileExtension=".calx" mimeType="application/vnd.ms-office.calx" />
-            <mimeMap fileExtension=".cat" mimeType="application/vnd.ms-pki.seccat" />
-            <mimeMap fileExtension=".cdf" mimeType="application/x-cdf" />
-            <mimeMap fileExtension=".chm" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".class" mimeType="application/x-java-applet" />
-            <mimeMap fileExtension=".clp" mimeType="application/x-msclip" />
-            <mimeMap fileExtension=".cmx" mimeType="image/x-cmx" />
-            <mimeMap fileExtension=".cnf" mimeType="text/plain" />
-            <mimeMap fileExtension=".cod" mimeType="image/cis-cod" />
-            <mimeMap fileExtension=".cpio" mimeType="application/x-cpio" />
-            <mimeMap fileExtension=".cpp" mimeType="text/plain" />
-            <mimeMap fileExtension=".crd" mimeType="application/x-mscardfile" />
-            <mimeMap fileExtension=".crl" mimeType="application/pkix-crl" />
-            <mimeMap fileExtension=".crt" mimeType="application/x-x509-ca-cert" />
-            <mimeMap fileExtension=".csh" mimeType="application/x-csh" />
-            <mimeMap fileExtension=".css" mimeType="text/css" />
-            <mimeMap fileExtension=".csv" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".cur" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".dcr" mimeType="application/x-director" />
-            <mimeMap fileExtension=".deploy" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".der" mimeType="application/x-x509-ca-cert" />
-            <mimeMap fileExtension=".dib" mimeType="image/bmp" />
-            <mimeMap fileExtension=".dir" mimeType="application/x-director" />
-            <mimeMap fileExtension=".disco" mimeType="text/xml" />
-            <mimeMap fileExtension=".dll" mimeType="application/x-msdownload" />
-            <mimeMap fileExtension=".dll.config" mimeType="text/xml" />
-            <mimeMap fileExtension=".dlm" mimeType="text/dlm" />
-            <mimeMap fileExtension=".doc" mimeType="application/msword" />
-            <mimeMap fileExtension=".docm" mimeType="application/vnd.ms-word.document.macroEnabled.12" />
-            <mimeMap fileExtension=".docx" mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
-            <mimeMap fileExtension=".dot" mimeType="application/msword" />
-            <mimeMap fileExtension=".dotm" mimeType="application/vnd.ms-word.template.macroEnabled.12" />
-            <mimeMap fileExtension=".dotx" mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.template" />
-            <mimeMap fileExtension=".dsp" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".dtd" mimeType="text/xml" />
-            <mimeMap fileExtension=".dvi" mimeType="application/x-dvi" />
-            <mimeMap fileExtension=".dvr-ms" mimeType="video/x-ms-dvr" />
-            <mimeMap fileExtension=".dwf" mimeType="drawing/x-dwf" />
-            <mimeMap fileExtension=".dwp" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".dxr" mimeType="application/x-director" />
-            <mimeMap fileExtension=".eml" mimeType="message/rfc822" />
-            <mimeMap fileExtension=".emz" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
-            <mimeMap fileExtension=".eps" mimeType="application/postscript" />
-            <mimeMap fileExtension=".etx" mimeType="text/x-setext" />
-            <mimeMap fileExtension=".evy" mimeType="application/envoy" />
-            <mimeMap fileExtension=".exe" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".exe.config" mimeType="text/xml" />
-            <mimeMap fileExtension=".fdf" mimeType="application/vnd.fdf" />
-            <mimeMap fileExtension=".fif" mimeType="application/fractals" />
-            <mimeMap fileExtension=".fla" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".flr" mimeType="x-world/x-vrml" />
-            <mimeMap fileExtension=".flv" mimeType="video/x-flv" />
-            <mimeMap fileExtension=".gif" mimeType="image/gif" />
-            <mimeMap fileExtension=".gtar" mimeType="application/x-gtar" />
-            <mimeMap fileExtension=".gz" mimeType="application/x-gzip" />
-            <mimeMap fileExtension=".h" mimeType="text/plain" />
-            <mimeMap fileExtension=".hdf" mimeType="application/x-hdf" />
-            <mimeMap fileExtension=".hdml" mimeType="text/x-hdml" />
-            <mimeMap fileExtension=".hhc" mimeType="application/x-oleobject" />
-            <mimeMap fileExtension=".hhk" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".hhp" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".hlp" mimeType="application/winhlp" />
-            <mimeMap fileExtension=".hqx" mimeType="application/mac-binhex40" />
-            <mimeMap fileExtension=".hta" mimeType="application/hta" />
-            <mimeMap fileExtension=".htc" mimeType="text/x-component" />
-            <mimeMap fileExtension=".htm" mimeType="text/html" />
-            <mimeMap fileExtension=".html" mimeType="text/html" />
-            <mimeMap fileExtension=".htt" mimeType="text/webviewhtml" />
-            <mimeMap fileExtension=".hxt" mimeType="text/html" />
-            <mimeMap fileExtension=".ico" mimeType="image/x-icon" />
-            <mimeMap fileExtension=".ics" mimeType="text/calendar" />
-            <mimeMap fileExtension=".ief" mimeType="image/ief" />
-            <mimeMap fileExtension=".iii" mimeType="application/x-iphone" />
-            <mimeMap fileExtension=".inf" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".ins" mimeType="application/x-internet-signup" />
-            <mimeMap fileExtension=".isp" mimeType="application/x-internet-signup" />
-            <mimeMap fileExtension=".IVF" mimeType="video/x-ivf" />
-            <mimeMap fileExtension=".jar" mimeType="application/java-archive" />
-            <mimeMap fileExtension=".java" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".jck" mimeType="application/liquidmotion" />
-            <mimeMap fileExtension=".jcz" mimeType="application/liquidmotion" />
-            <mimeMap fileExtension=".jfif" mimeType="image/pjpeg" />
-            <mimeMap fileExtension=".jpb" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".jpe" mimeType="image/jpeg" />
-            <mimeMap fileExtension=".jpeg" mimeType="image/jpeg" />
-            <mimeMap fileExtension=".jpg" mimeType="image/jpeg" />
-            <mimeMap fileExtension=".js" mimeType="application/javascript" />
-            <mimeMap fileExtension=".json" mimeType="application/json" />
-            <mimeMap fileExtension=".jsonld" mimeType="application/ld+json" />
-            <mimeMap fileExtension=".jsx" mimeType="text/jscript" />
-            <mimeMap fileExtension=".latex" mimeType="application/x-latex" />
-            <mimeMap fileExtension=".less" mimeType="text/css" />
-            <mimeMap fileExtension=".lit" mimeType="application/x-ms-reader" />
-            <mimeMap fileExtension=".lpk" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".lsf" mimeType="video/x-la-asf" />
-            <mimeMap fileExtension=".lsx" mimeType="video/x-la-asf" />
-            <mimeMap fileExtension=".lzh" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".m13" mimeType="application/x-msmediaview" />
-            <mimeMap fileExtension=".m14" mimeType="application/x-msmediaview" />
-            <mimeMap fileExtension=".m1v" mimeType="video/mpeg" />
-            <mimeMap fileExtension=".m2ts" mimeType="video/vnd.dlna.mpeg-tts" />
-            <mimeMap fileExtension=".m3u" mimeType="audio/x-mpegurl" />
-            <mimeMap fileExtension=".m4a" mimeType="audio/mp4" />
-            <mimeMap fileExtension=".m4v" mimeType="video/mp4" />
-            <mimeMap fileExtension=".man" mimeType="application/x-troff-man" />
-            <mimeMap fileExtension=".manifest" mimeType="application/x-ms-manifest" />
-            <mimeMap fileExtension=".map" mimeType="text/plain" />
-            <mimeMap fileExtension=".mdb" mimeType="application/x-msaccess" />
-            <mimeMap fileExtension=".mdp" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".me" mimeType="application/x-troff-me" />
-            <mimeMap fileExtension=".mht" mimeType="message/rfc822" />
-            <mimeMap fileExtension=".mhtml" mimeType="message/rfc822" />
-            <mimeMap fileExtension=".mid" mimeType="audio/mid" />
-            <mimeMap fileExtension=".midi" mimeType="audio/mid" />
-            <mimeMap fileExtension=".mix" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".mmf" mimeType="application/x-smaf" />
-            <mimeMap fileExtension=".mno" mimeType="text/xml" />
-            <mimeMap fileExtension=".mny" mimeType="application/x-msmoney" />
-            <mimeMap fileExtension=".mov" mimeType="video/quicktime" />
-            <mimeMap fileExtension=".movie" mimeType="video/x-sgi-movie" />
-            <mimeMap fileExtension=".mp2" mimeType="video/mpeg" />
-            <mimeMap fileExtension=".mp3" mimeType="audio/mpeg" />
-            <mimeMap fileExtension=".mp4" mimeType="video/mp4" />
-            <mimeMap fileExtension=".mp4v" mimeType="video/mp4" />
-            <mimeMap fileExtension=".mpa" mimeType="video/mpeg" />
-            <mimeMap fileExtension=".mpe" mimeType="video/mpeg" />
-            <mimeMap fileExtension=".mpeg" mimeType="video/mpeg" />
-            <mimeMap fileExtension=".mpg" mimeType="video/mpeg" />
-            <mimeMap fileExtension=".mpp" mimeType="application/vnd.ms-project" />
-            <mimeMap fileExtension=".mpv2" mimeType="video/mpeg" />
-            <mimeMap fileExtension=".ms" mimeType="application/x-troff-ms" />
-            <mimeMap fileExtension=".msi" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".mso" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".mvb" mimeType="application/x-msmediaview" />
-            <mimeMap fileExtension=".mvc" mimeType="application/x-miva-compiled" />
-            <mimeMap fileExtension=".nc" mimeType="application/x-netcdf" />
-            <mimeMap fileExtension=".nsc" mimeType="video/x-ms-asf" />
-            <mimeMap fileExtension=".nws" mimeType="message/rfc822" />
-            <mimeMap fileExtension=".ocx" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".oda" mimeType="application/oda" />
-            <mimeMap fileExtension=".odc" mimeType="text/x-ms-odc" />
-            <mimeMap fileExtension=".ods" mimeType="application/oleobject" />
-            <mimeMap fileExtension=".oga" mimeType="audio/ogg" />
-            <mimeMap fileExtension=".ogg" mimeType="video/ogg" />
-            <mimeMap fileExtension=".ogv" mimeType="video/ogg" />
-            <mimeMap fileExtension=".one" mimeType="application/onenote" />
-            <mimeMap fileExtension=".onea" mimeType="application/onenote" />
-            <mimeMap fileExtension=".onetoc" mimeType="application/onenote" />
-            <mimeMap fileExtension=".onetoc2" mimeType="application/onenote" />
-            <mimeMap fileExtension=".onetmp" mimeType="application/onenote" />
-            <mimeMap fileExtension=".onepkg" mimeType="application/onenote" />
-            <mimeMap fileExtension=".osdx" mimeType="application/opensearchdescription+xml" />
-            <mimeMap fileExtension=".otf" mimeType="font/otf" />
-            <mimeMap fileExtension=".p10" mimeType="application/pkcs10" />
-            <mimeMap fileExtension=".p12" mimeType="application/x-pkcs12" />
-            <mimeMap fileExtension=".p7b" mimeType="application/x-pkcs7-certificates" />
-            <mimeMap fileExtension=".p7c" mimeType="application/pkcs7-mime" />
-            <mimeMap fileExtension=".p7m" mimeType="application/pkcs7-mime" />
-            <mimeMap fileExtension=".p7r" mimeType="application/x-pkcs7-certreqresp" />
-            <mimeMap fileExtension=".p7s" mimeType="application/pkcs7-signature" />
-            <mimeMap fileExtension=".pbm" mimeType="image/x-portable-bitmap" />
-            <mimeMap fileExtension=".pcx" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".pcz" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".pdf" mimeType="application/pdf" />
-            <mimeMap fileExtension=".pfb" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".pfm" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".pfx" mimeType="application/x-pkcs12" />
-            <mimeMap fileExtension=".pgm" mimeType="image/x-portable-graymap" />
-            <mimeMap fileExtension=".pko" mimeType="application/vnd.ms-pki.pko" />
-            <mimeMap fileExtension=".pma" mimeType="application/x-perfmon" />
-            <mimeMap fileExtension=".pmc" mimeType="application/x-perfmon" />
-            <mimeMap fileExtension=".pml" mimeType="application/x-perfmon" />
-            <mimeMap fileExtension=".pmr" mimeType="application/x-perfmon" />
-            <mimeMap fileExtension=".pmw" mimeType="application/x-perfmon" />
-            <mimeMap fileExtension=".png" mimeType="image/png" />
-            <mimeMap fileExtension=".pnm" mimeType="image/x-portable-anymap" />
-            <mimeMap fileExtension=".pnz" mimeType="image/png" />
-            <mimeMap fileExtension=".pot" mimeType="application/vnd.ms-powerpoint" />
-            <mimeMap fileExtension=".potm" mimeType="application/vnd.ms-powerpoint.template.macroEnabled.12" />
-            <mimeMap fileExtension=".potx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.template" />
-            <mimeMap fileExtension=".ppam" mimeType="application/vnd.ms-powerpoint.addin.macroEnabled.12" />
-            <mimeMap fileExtension=".ppm" mimeType="image/x-portable-pixmap" />
-            <mimeMap fileExtension=".pps" mimeType="application/vnd.ms-powerpoint" />
-            <mimeMap fileExtension=".ppsm" mimeType="application/vnd.ms-powerpoint.slideshow.macroEnabled.12" />
-            <mimeMap fileExtension=".ppsx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.slideshow" />
-            <mimeMap fileExtension=".ppt" mimeType="application/vnd.ms-powerpoint" />
-            <mimeMap fileExtension=".pptm" mimeType="application/vnd.ms-powerpoint.presentation.macroEnabled.12" />
-            <mimeMap fileExtension=".pptx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" />
-            <mimeMap fileExtension=".prf" mimeType="application/pics-rules" />
-            <mimeMap fileExtension=".prm" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".prx" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".ps" mimeType="application/postscript" />
-            <mimeMap fileExtension=".psd" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".psm" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".psp" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".pub" mimeType="application/x-mspublisher" />
-            <mimeMap fileExtension=".qt" mimeType="video/quicktime" />
-            <mimeMap fileExtension=".qtl" mimeType="application/x-quicktimeplayer" />
-            <mimeMap fileExtension=".qxd" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".ra" mimeType="audio/x-pn-realaudio" />
-            <mimeMap fileExtension=".ram" mimeType="audio/x-pn-realaudio" />
-            <mimeMap fileExtension=".rar" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".ras" mimeType="image/x-cmu-raster" />
-            <mimeMap fileExtension=".rf" mimeType="image/vnd.rn-realflash" />
-            <mimeMap fileExtension=".rgb" mimeType="image/x-rgb" />
-            <mimeMap fileExtension=".rm" mimeType="application/vnd.rn-realmedia" />
-            <mimeMap fileExtension=".rmi" mimeType="audio/mid" />
-            <mimeMap fileExtension=".roff" mimeType="application/x-troff" />
-            <mimeMap fileExtension=".rpm" mimeType="audio/x-pn-realaudio-plugin" />
-            <mimeMap fileExtension=".rtf" mimeType="application/rtf" />
-            <mimeMap fileExtension=".rtx" mimeType="text/richtext" />
-            <mimeMap fileExtension=".scd" mimeType="application/x-msschedule" />
-            <mimeMap fileExtension=".sct" mimeType="text/scriptlet" />
-            <mimeMap fileExtension=".sea" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".setpay" mimeType="application/set-payment-initiation" />
-            <mimeMap fileExtension=".setreg" mimeType="application/set-registration-initiation" />
-            <mimeMap fileExtension=".sgml" mimeType="text/sgml" />
-            <mimeMap fileExtension=".sh" mimeType="application/x-sh" />
-            <mimeMap fileExtension=".shar" mimeType="application/x-shar" />
-            <mimeMap fileExtension=".sit" mimeType="application/x-stuffit" />
-            <mimeMap fileExtension=".sldm" mimeType="application/vnd.ms-powerpoint.slide.macroEnabled.12" />
-            <mimeMap fileExtension=".sldx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.slide" />
-            <mimeMap fileExtension=".smd" mimeType="audio/x-smd" />
-            <mimeMap fileExtension=".smi" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".smx" mimeType="audio/x-smd" />
-            <mimeMap fileExtension=".smz" mimeType="audio/x-smd" />
-            <mimeMap fileExtension=".snd" mimeType="audio/basic" />
-            <mimeMap fileExtension=".snp" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".spc" mimeType="application/x-pkcs7-certificates" />
-            <mimeMap fileExtension=".spl" mimeType="application/futuresplash" />
-            <mimeMap fileExtension=".spx" mimeType="audio/ogg" />
-            <mimeMap fileExtension=".src" mimeType="application/x-wais-source" />
-            <mimeMap fileExtension=".ssm" mimeType="application/streamingmedia" />
-            <mimeMap fileExtension=".sst" mimeType="application/vnd.ms-pki.certstore" />
-            <mimeMap fileExtension=".stl" mimeType="application/vnd.ms-pki.stl" />
-            <mimeMap fileExtension=".sv4cpio" mimeType="application/x-sv4cpio" />
-            <mimeMap fileExtension=".sv4crc" mimeType="application/x-sv4crc" />
-            <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
-            <mimeMap fileExtension=".svgz" mimeType="image/svg+xml" />
-            <mimeMap fileExtension=".swf" mimeType="application/x-shockwave-flash" />
-            <mimeMap fileExtension=".t" mimeType="application/x-troff" />
-            <mimeMap fileExtension=".tar" mimeType="application/x-tar" />
-            <mimeMap fileExtension=".tcl" mimeType="application/x-tcl" />
-            <mimeMap fileExtension=".tex" mimeType="application/x-tex" />
-            <mimeMap fileExtension=".texi" mimeType="application/x-texinfo" />
-            <mimeMap fileExtension=".texinfo" mimeType="application/x-texinfo" />
-            <mimeMap fileExtension=".tgz" mimeType="application/x-compressed" />
-            <mimeMap fileExtension=".thmx" mimeType="application/vnd.ms-officetheme" />
-            <mimeMap fileExtension=".thn" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".tif" mimeType="image/tiff" />
-            <mimeMap fileExtension=".tiff" mimeType="image/tiff" />
-            <mimeMap fileExtension=".toc" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".tr" mimeType="application/x-troff" />
-            <mimeMap fileExtension=".trm" mimeType="application/x-msterminal" />
-            <mimeMap fileExtension=".ts" mimeType="video/vnd.dlna.mpeg-tts" />
-            <mimeMap fileExtension=".tsv" mimeType="text/tab-separated-values" />
-            <mimeMap fileExtension=".ttf" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".tts" mimeType="video/vnd.dlna.mpeg-tts" />
-            <mimeMap fileExtension=".txt" mimeType="text/plain" />
-            <mimeMap fileExtension=".u32" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".uls" mimeType="text/iuls" />
-            <mimeMap fileExtension=".ustar" mimeType="application/x-ustar" />
-            <mimeMap fileExtension=".vbs" mimeType="text/vbscript" />
-            <mimeMap fileExtension=".vcf" mimeType="text/x-vcard" />
-            <mimeMap fileExtension=".vcs" mimeType="text/plain" />
-            <mimeMap fileExtension=".vdx" mimeType="application/vnd.ms-visio.viewer" />
-            <mimeMap fileExtension=".vml" mimeType="text/xml" />
-            <mimeMap fileExtension=".vsd" mimeType="application/vnd.visio" />
-            <mimeMap fileExtension=".vss" mimeType="application/vnd.visio" />
-            <mimeMap fileExtension=".vst" mimeType="application/vnd.visio" />
-            <mimeMap fileExtension=".vsto" mimeType="application/x-ms-vsto" />
-            <mimeMap fileExtension=".vsw" mimeType="application/vnd.visio" />
-            <mimeMap fileExtension=".vsx" mimeType="application/vnd.visio" />
-            <mimeMap fileExtension=".vtx" mimeType="application/vnd.visio" />
-            <mimeMap fileExtension=".wav" mimeType="audio/wav" />
-            <mimeMap fileExtension=".wax" mimeType="audio/x-ms-wax" />
-            <mimeMap fileExtension=".wbmp" mimeType="image/vnd.wap.wbmp" />
-            <mimeMap fileExtension=".wcm" mimeType="application/vnd.ms-works" />
-            <mimeMap fileExtension=".wdb" mimeType="application/vnd.ms-works" />
-            <mimeMap fileExtension=".webm" mimeType="video/webm" />
-            <mimeMap fileExtension=".wks" mimeType="application/vnd.ms-works" />
-            <mimeMap fileExtension=".wm" mimeType="video/x-ms-wm" />
-            <mimeMap fileExtension=".wma" mimeType="audio/x-ms-wma" />
-            <mimeMap fileExtension=".wmd" mimeType="application/x-ms-wmd" />
-            <mimeMap fileExtension=".wmf" mimeType="application/x-msmetafile" />
-            <mimeMap fileExtension=".wml" mimeType="text/vnd.wap.wml" />
-            <mimeMap fileExtension=".wmlc" mimeType="application/vnd.wap.wmlc" />
-            <mimeMap fileExtension=".wmls" mimeType="text/vnd.wap.wmlscript" />
-            <mimeMap fileExtension=".wmlsc" mimeType="application/vnd.wap.wmlscriptc" />
-            <mimeMap fileExtension=".wmp" mimeType="video/x-ms-wmp" />
-            <mimeMap fileExtension=".wmv" mimeType="video/x-ms-wmv" />
-            <mimeMap fileExtension=".wmx" mimeType="video/x-ms-wmx" />
-            <mimeMap fileExtension=".wmz" mimeType="application/x-ms-wmz" />
-            <mimeMap fileExtension=".woff" mimeType="font/x-woff" />
-            <mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
-            <mimeMap fileExtension=".wps" mimeType="application/vnd.ms-works" />
-            <mimeMap fileExtension=".wri" mimeType="application/x-mswrite" />
-            <mimeMap fileExtension=".wrl" mimeType="x-world/x-vrml" />
-            <mimeMap fileExtension=".wrz" mimeType="x-world/x-vrml" />
-            <mimeMap fileExtension=".wsdl" mimeType="text/xml" />
-            <mimeMap fileExtension=".wtv" mimeType="video/x-ms-wtv" />
-            <mimeMap fileExtension=".wvx" mimeType="video/x-ms-wvx" />
-            <mimeMap fileExtension=".x" mimeType="application/directx" />
-            <mimeMap fileExtension=".xaf" mimeType="x-world/x-vrml" />
-            <mimeMap fileExtension=".xaml" mimeType="application/xaml+xml" />
-            <mimeMap fileExtension=".xap" mimeType="application/x-silverlight-app" />
-            <mimeMap fileExtension=".xbap" mimeType="application/x-ms-xbap" />
-            <mimeMap fileExtension=".xbm" mimeType="image/x-xbitmap" />
-            <mimeMap fileExtension=".xdr" mimeType="text/plain" />
-            <mimeMap fileExtension=".xht" mimeType="application/xhtml+xml" />
-            <mimeMap fileExtension=".xhtml" mimeType="application/xhtml+xml" />
-            <mimeMap fileExtension=".xla" mimeType="application/vnd.ms-excel" />
-            <mimeMap fileExtension=".xlam" mimeType="application/vnd.ms-excel.addin.macroEnabled.12" />
-            <mimeMap fileExtension=".xlc" mimeType="application/vnd.ms-excel" />
-            <mimeMap fileExtension=".xlm" mimeType="application/vnd.ms-excel" />
-            <mimeMap fileExtension=".xls" mimeType="application/vnd.ms-excel" />
-            <mimeMap fileExtension=".xlsb" mimeType="application/vnd.ms-excel.sheet.binary.macroEnabled.12" />
-            <mimeMap fileExtension=".xlsm" mimeType="application/vnd.ms-excel.sheet.macroEnabled.12" />
-            <mimeMap fileExtension=".xlsx" mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
-            <mimeMap fileExtension=".xlt" mimeType="application/vnd.ms-excel" />
-            <mimeMap fileExtension=".xltm" mimeType="application/vnd.ms-excel.template.macroEnabled.12" />
-            <mimeMap fileExtension=".xltx" mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.template" />
-            <mimeMap fileExtension=".xlw" mimeType="application/vnd.ms-excel" />
-            <mimeMap fileExtension=".xml" mimeType="text/xml" />
-            <mimeMap fileExtension=".xof" mimeType="x-world/x-vrml" />
-            <mimeMap fileExtension=".xpm" mimeType="image/x-xpixmap" />
-            <mimeMap fileExtension=".xps" mimeType="application/vnd.ms-xpsdocument" />
-            <mimeMap fileExtension=".xsd" mimeType="text/xml" />
-            <mimeMap fileExtension=".xsf" mimeType="text/xml" />
-            <mimeMap fileExtension=".xsl" mimeType="text/xml" />
-            <mimeMap fileExtension=".xslt" mimeType="text/xml" />
-            <mimeMap fileExtension=".xsn" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".xtp" mimeType="application/octet-stream" />
-            <mimeMap fileExtension=".xwd" mimeType="image/x-xwindowdump" />
-            <mimeMap fileExtension=".z" mimeType="application/x-compress" />
-            <mimeMap fileExtension=".zip" mimeType="application/x-zip-compressed" />
-        </staticContent>
-
-        <tracing>
-
-             <traceProviderDefinitions>
-                <add name="WWW Server" guid="{3a2a4e84-4c21-4981-ae10-3fda0d9b0f83}">
-                    <areas>
-                        <clear />
-                        <add name="Authentication" value="2" />
-                        <add name="Security" value="4" />
-                        <add name="Filter" value="8" />
-                        <add name="StaticFile" value="16" />
-                        <add name="CGI" value="32" />
-                        <add name="Compression" value="64" />
-                        <add name="Cache" value="128" />
-                        <add name="RequestNotifications" value="256" />
-                        <add name="Module" value="512" />
-                        <add name="Rewrite" value="1024" />
-                        <add name="FastCGI" value="4096" />
-                        <add name="WebSocket" value="16384" />
-                    </areas>
-                </add>
-                <add name="ASP" guid="{06b94d9a-b15e-456e-a4ef-37c984a2cb4b}">
-                    <areas>
-                        <clear />
-                    </areas>
-                </add>
-                <add name="ISAPI Extension" guid="{a1c2040e-8840-4c31-ba11-9871031a19ea}">
-                    <areas>
-                        <clear />
-                    </areas>
-                </add>
-                <add name="ASPNET" guid="{AFF081FE-0247-4275-9C4E-021F3DC1DA35}">
-                    <areas>
-                        <add name="Infrastructure" value="1" />
-                        <add name="Module" value="2" />
-                        <add name="Page" value="4" />
-                        <add name="AppServices" value="8" />
-                    </areas>
-                </add>
-            </traceProviderDefinitions>
-
-            <traceFailedRequests>
-                <add path="*">
-                    <traceAreas>
-                        <add provider="ASP" verbosity="Verbose" />
-                        <add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />
-                        <add provider="ISAPI Extension" verbosity="Verbose" />
-                        <add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,Rewrite,WebSocket" verbosity="Verbose" />
-                    </traceAreas>
-                    <failureDefinitions statusCodes="200-999" />
-                </add>
-            </traceFailedRequests>
-
-        </tracing>
-
-        <urlCompression />
-
-        <validation />
-        <webdav>
-            <globalSettings>
-                <propertyStores>
-                    <add name="webdav_simple_prop" image="%IIS_BIN%\webdav_simple_prop.dll" image32="%IIS_BIN%\webdav_simple_prop.dll" />
-                </propertyStores>
-                <lockStores>
-                    <add name="webdav_simple_lock" image="%IIS_BIN%\webdav_simple_lock.dll" image32="%IIS_BIN%\webdav_simple_lock.dll" />
-                </lockStores>
-
-            </globalSettings>
-            <authoring>
-                <locks enabled="true" lockStore="webdav_simple_lock" />
-            </authoring>
-            <authoringRules />
-        </webdav>
-        <webSocket />
-        <applicationInitialization />
-
-    </system.webServer>
-    <location path="" overrideMode="Allow">
-        <system.webServer>
-            <modules>
-                <add name="IsapiFilterModule" lockItem="true" />
-                <add name="BasicAuthenticationModule" lockItem="true" />
-                <add name="IsapiModule" lockItem="true" />
-                <add name="HttpLoggingModule" lockItem="true" />
-                <!--
-                <add name="HttpCacheModule" lockItem="true" />
--->
-                <add name="DynamicCompressionModule" lockItem="true" />
-                <add name="StaticCompressionModule" lockItem="true" />
-                <add name="DefaultDocumentModule" lockItem="true" />
-                <add name="DirectoryListingModule" lockItem="true" />
-
-                <add name="ProtocolSupportModule" lockItem="true" />
-                <add name="HttpRedirectionModule" lockItem="true" />
-                <add name="ServerSideIncludeModule" lockItem="true" />
-                <add name="StaticFileModule" lockItem="true" />
-                <add name="AnonymousAuthenticationModule" lockItem="true" />
-                <add name="CertificateMappingAuthenticationModule" lockItem="true" />
-                <add name="UrlAuthorizationModule" lockItem="true" />
-                <add name="WindowsAuthenticationModule" lockItem="true" />
-                <!--
-                <add name="DigestAuthenticationModule" lockItem="true" />
--->
-                <add name="IISCertificateMappingAuthenticationModule" lockItem="true" />
-                <add name="WebMatrixSupportModule" lockItem="true" />
-                <add name="IpRestrictionModule" lockItem="true" />
-                <add name="DynamicIpRestrictionModule" lockItem="true" />
-                <add name="RequestFilteringModule" lockItem="true" />
-                <add name="CustomLoggingModule" lockItem="true" />
-                <add name="CustomErrorModule" lockItem="true" />
-                <add name="FailedRequestsTracingModule" lockItem="true" />
-                <add name="CgiModule" lockItem="true" />
-                <add name="FastCgiModule" lockItem="true" />
-                <!--                <add name="WebDAVModule" /> -->
-                <add name="RewriteModule" />
-                <add name="OutputCache" type="System.Web.Caching.OutputCacheModule" preCondition="managedHandler" />
-                <add name="Session" type="System.Web.SessionState.SessionStateModule" preCondition="managedHandler" />
-                <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" preCondition="managedHandler" />
-                <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" preCondition="managedHandler" />
-                <add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" preCondition="managedHandler" />
-                <add name="RoleManager" type="System.Web.Security.RoleManagerModule" preCondition="managedHandler" />
-                <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" preCondition="managedHandler" />
-                <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" preCondition="managedHandler" />
-                <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule" preCondition="managedHandler" />
-                <add name="Profile" type="System.Web.Profile.ProfileModule" preCondition="managedHandler" />
-                <add name="UrlMappingsModule" type="System.Web.UrlMappingsModule" preCondition="managedHandler" />
-                <add name="ConfigurationValidationModule" lockItem="true" />
-                <add name="WebSocketModule" lockItem="true" />
-                <add name="ServiceModel-4.0" type="System.ServiceModel.Activation.ServiceHttpModule,System.ServiceModel.Activation,Version=4.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler,runtimeVersionv4.0" />
-                <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler,runtimeVersionv4.0" />
-                <add name="ScriptModule-4.0" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler,runtimeVersionv4.0" />
-                <add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler,runtimeVersionv2.0" />
-                <add name="ApplicationInitializationModule" lockItem="true" />
-                <add name="AspNetCoreModule" lockItem="true" />
-            </modules>
-            <handlers accessPolicy="Read, Script">
-                <!--                <add name="WebDAV" path="*" verb="PROPFIND,PROPPATCH,MKCOL,PUT,COPY,DELETE,MOVE,LOCK,UNLOCK" modules="WebDAVModule" resourceType="Unspecified" requireAccess="None" /> -->
-                <add name="AXD-ISAPI-4.0_64bit" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="PageHandlerFactory-ISAPI-4.0_64bit" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="SimpleHandlerFactory-ISAPI-4.0_64bit" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="WebServiceHandlerFactory-ISAPI-4.0_64bit" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="HttpRemotingHandlerFactory-rem-ISAPI-4.0_64bit" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="HttpRemotingHandlerFactory-soap-ISAPI-4.0_64bit" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="svc-ISAPI-4.0_64bit" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
-                <add name="rules-ISAPI-4.0_64bit" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
-                <add name="xoml-ISAPI-4.0_64bit" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
-                <add name="xamlx-ISAPI-4.0_64bit" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
-                <add name="aspq-ISAPI-4.0_64bit" path="*.aspq" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="cshtm-ISAPI-4.0_64bit" path="*.cshtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="cshtml-ISAPI-4.0_64bit" path="*.cshtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="vbhtm-ISAPI-4.0_64bit" path="*.vbhtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="vbhtml-ISAPI-4.0_64bit" path="*.vbhtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="svc-Integrated" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="svc-ISAPI-2.0" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
-                <add name="xoml-Integrated" path="*.xoml" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="xoml-ISAPI-2.0" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
-                <add name="rules-Integrated" path="*.rules" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="rules-ISAPI-2.0" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
-                <add name="AXD-ISAPI-4.0_32bit" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="PageHandlerFactory-ISAPI-4.0_32bit" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="SimpleHandlerFactory-ISAPI-4.0_32bit" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="WebServiceHandlerFactory-ISAPI-4.0_32bit" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="HttpRemotingHandlerFactory-rem-ISAPI-4.0_32bit" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="HttpRemotingHandlerFactory-soap-ISAPI-4.0_32bit" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="svc-ISAPI-4.0_32bit" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
-                <add name="rules-ISAPI-4.0_32bit" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
-                <add name="xoml-ISAPI-4.0_32bit" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
-                <add name="xamlx-ISAPI-4.0_32bit" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
-                <add name="aspq-ISAPI-4.0_32bit" path="*.aspq" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="cshtm-ISAPI-4.0_32bit" path="*.cshtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="cshtml-ISAPI-4.0_32bit" path="*.cshtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="vbhtm-ISAPI-4.0_32bit" path="*.vbhtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="vbhtml-ISAPI-4.0_32bit" path="*.vbhtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="TraceHandler-Integrated-4.0" path="trace.axd" verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TraceHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="WebAdminHandler-Integrated-4.0" path="WebAdmin.axd" verb="GET,DEBUG" type="System.Web.Handlers.WebAdminHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="AssemblyResourceLoader-Integrated-4.0" path="WebResource.axd" verb="GET,DEBUG" type="System.Web.Handlers.AssemblyResourceLoader" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="PageHandlerFactory-Integrated-4.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.SimpleHandlerFactory" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="WebServiceHandlerFactory-Integrated-4.0" path="*.asmx" verb="GET,HEAD,POST,DEBUG" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="HttpRemotingHandlerFactory-rem-Integrated-4.0" path="*.rem" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="HttpRemotingHandlerFactory-soap-Integrated-4.0" path="*.soap" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="svc-Integrated-4.0" path="*.svc" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="rules-Integrated-4.0" path="*.rules" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="xoml-Integrated-4.0" path="*.xoml" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="xamlx-Integrated-4.0" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" type="System.Xaml.Hosting.XamlHttpHandlerFactory, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="aspq-Integrated-4.0" path="*.aspq" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="cshtm-Integrated-4.0" path="*.cshtm" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="cshtml-Integrated-4.0" path="*.cshtml" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="vbhtm-Integrated-4.0" path="*.vbhtm" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="vbhtml-Integrated-4.0" path="*.vbhtml" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="ScriptHandlerFactoryAppServices-Integrated-4.0" path="*_AppService.axd" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="ScriptResourceIntegrated-4.0" path="*ScriptResource.axd" verb="GET,HEAD" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" preCondition="integratedMode,runtimeVersionv4.0" />
-                <add name="ASPClassic" path="*.asp" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%IIS_BIN%\asp.dll" resourceType="File" />
-                <add name="SecurityCertificate" path="*.cer" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%IIS_BIN%\asp.dll" resourceType="File" />
-                <add name="ISAPI-dll" path="*.dll" verb="*" modules="IsapiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
-                <add name="TraceHandler-Integrated" path="trace.axd" verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TraceHandler" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="WebAdminHandler-Integrated" path="WebAdmin.axd" verb="GET,DEBUG" type="System.Web.Handlers.WebAdminHandler" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="AssemblyResourceLoader-Integrated" path="WebResource.axd" verb="GET,DEBUG" type="System.Web.Handlers.AssemblyResourceLoader" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="PageHandlerFactory-Integrated" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="SimpleHandlerFactory-Integrated" path="*.ashx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.SimpleHandlerFactory" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="WebServiceHandlerFactory-Integrated" path="*.asmx" verb="GET,HEAD,POST,DEBUG" type="System.Web.Services.Protocols.WebServiceHandlerFactory,System.Web.Services,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="HttpRemotingHandlerFactory-rem-Integrated" path="*.rem" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,System.Runtime.Remoting,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="HttpRemotingHandlerFactory-soap-Integrated" path="*.soap" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,System.Runtime.Remoting,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
-                <add name="AXD-ISAPI-2.0" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
-                <add name="PageHandlerFactory-ISAPI-2.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
-                <add name="SimpleHandlerFactory-ISAPI-2.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
-                <add name="WebServiceHandlerFactory-ISAPI-2.0" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
-                <add name="HttpRemotingHandlerFactory-rem-ISAPI-2.0" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
-                <add name="HttpRemotingHandlerFactory-soap-ISAPI-2.0" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
-                <add name="svc-ISAPI-2.0-64" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
-                <add name="AXD-ISAPI-2.0-64" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
-                <add name="PageHandlerFactory-ISAPI-2.0-64" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
-                <add name="SimpleHandlerFactory-ISAPI-2.0-64" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
-                <add name="WebServiceHandlerFactory-ISAPI-2.0-64" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
-                <add name="HttpRemotingHandlerFactory-rem-ISAPI-2.0-64" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
-                <add name="HttpRemotingHandlerFactory-soap-ISAPI-2.0-64" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
-                <add name="rules-64-ISAPI-2.0" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
-                <add name="xoml-64-ISAPI-2.0" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
-                <add name="CGI-exe" path="*.exe" verb="*" modules="CgiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
-                <add name="SSINC-stm" path="*.stm" verb="GET,HEAD,POST" modules="ServerSideIncludeModule" resourceType="File" />
-                <add name="SSINC-shtm" path="*.shtm" verb="GET,HEAD,POST" modules="ServerSideIncludeModule" resourceType="File" />
-                <add name="SSINC-shtml" path="*.shtml" verb="GET,HEAD,POST" modules="ServerSideIncludeModule" resourceType="File" />
-                <add name="TRACEVerbHandler" path="*" verb="TRACE" modules="ProtocolSupportModule" requireAccess="None" />
-                <add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" />
-                <add name="ExtensionlessUrl-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
-                <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
-                <add name="ExtensionlessUrl-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" />
-                <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
-            </handlers>
-        </system.webServer>
-    </location>
-</configuration>

+ 1 - 1
data/web/inc/lib/vendor/robthree/twofactorauth/README.md

@@ -10,7 +10,7 @@ PHP library for [two-factor (or multi-factor) authentication](http://en.wikipedi
 
 ## Requirements
 
-* Tested on PHP 5.3, 5.4, 5.5 and 5.6, 7 and HHVM
+* Tested on PHP 5.3, 5.4, 5.5 and 5.6, 7.0, 7.1 and HHVM
 * [cURL](http://php.net/manual/en/book.curl.php) when using the provided `GoogleQRCodeProvider` (default), `QRServerProvider` or `QRicketProvider` but you can also provide your own QR-code provider.
 * [random_bytes()](http://php.net/manual/en/function.random-bytes.php), [MCrypt](http://php.net/manual/en/book.mcrypt.php), [OpenSSL](http://php.net/manual/en/book.openssl.php) or [Hash](http://php.net/manual/en/book.hash.php) depending on which built-in RNG you use (TwoFactorAuth will try to 'autodetect' and use the best available); however: feel free to provide your own (CS)RNG.
 

+ 1 - 1
data/web/inc/lib/vendor/robthree/twofactorauth/composer.json

@@ -1,7 +1,7 @@
 {
     "name": "robthree/twofactorauth",
     "description": "Two Factor Authentication",
-    "version": "1.6",
+    "version": "1.6.1",
     "type": "library",
     "keywords": [ "Authentication", "Two Factor Authentication", "Multi Factor Authentication", "TFA", "MFA", "PHP", "Authenticator", "Authy" ],
     "homepage": "https://github.com/RobThree/TwoFactorAuth",

+ 1 - 1
data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/ConvertUnixTimeDotComTimeProvider.php

@@ -6,7 +6,7 @@ class ConvertUnixTimeDotComTimeProvider implements ITimeProvider
 {
     public function getTime() {
         $json = @json_decode(
-            @file_get_contents('http://www.convert-unix-time.com/api?timestamp=now')
+            @file_get_contents('http://www.convert-unix-time.com/api?timestamp=now&r=' . uniqid(null, true))
         );
         if ($json === null || !is_int($json->timestamp))
             throw new \TimeException('Unable to retrieve time from convert-unix-time.com');

+ 2 - 1
data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/HttpTimeProvider.php

@@ -26,7 +26,8 @@ class HttpTimeProvider implements ITimeProvider
                     'request_fulluri' => true,
                     'header' => array(
                         'Connection: close',
-                        'User-agent: TwoFactorAuth HttpTimeProvider (https://github.com/RobThree/TwoFactorAuth)'
+                        'User-agent: TwoFactorAuth HttpTimeProvider (https://github.com/RobThree/TwoFactorAuth)',
+                        'Cache-Control: no-cache'
                     )
                 )
             );

+ 507 - 0
data/web/inc/lib/vendor/yubico/u2flib-server/src/u2flib_server/U2F.php.1

@@ -0,0 +1,507 @@
+<?php
+/* Copyright (c) 2014 Yubico AB
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+
+namespace u2flib_server;
+
+/** Constant for the version of the u2f protocol */
+const U2F_VERSION = "U2F_V2";
+
+/** Error for the authentication message not matching any outstanding
+ * authentication request */
+const ERR_NO_MATCHING_REQUEST = 1;
+
+/** Error for the authentication message not matching any registration */
+const ERR_NO_MATCHING_REGISTRATION = 2;
+
+/** Error for the signature on the authentication message not verifying with
+ * the correct key */
+const ERR_AUTHENTICATION_FAILURE = 3;
+
+/** Error for the challenge in the registration message not matching the
+ * registration challenge */
+const ERR_UNMATCHED_CHALLENGE = 4;
+
+/** Error for the attestation signature on the registration message not
+ * verifying */
+const ERR_ATTESTATION_SIGNATURE = 5;
+
+/** Error for the attestation verification not verifying */
+const ERR_ATTESTATION_VERIFICATION = 6;
+
+/** Error for not getting good random from the system */
+const ERR_BAD_RANDOM = 7;
+
+/** Error when the counter is lower than expected */
+const ERR_COUNTER_TOO_LOW = 8;
+
+/** Error decoding public key */
+const ERR_PUBKEY_DECODE = 9;
+
+/** Error user-agent returned error */
+const ERR_BAD_UA_RETURNING = 10;
+
+/** Error old OpenSSL version */
+const ERR_OLD_OPENSSL = 11;
+
+/** @internal */
+const PUBKEY_LEN = 65;
+
+class U2F
+{
+    /** @var string  */
+    private $appId;
+
+    /** @var null|string */
+    private $attestDir;
+
+    /** @internal */
+    private $FIXCERTS = array(
+        '349bca1031f8c82c4ceca38b9cebf1a69df9fb3b94eed99eb3fb9aa3822d26e8',
+        'dd574527df608e47ae45fbba75a2afdd5c20fd94a02419381813cd55a2a3398f',
+        '1d8764f0f7cd1352df6150045c8f638e517270e8b5dda1c63ade9c2280240cae',
+        'd0edc9a91a1677435a953390865d208c55b3183c6759c9b5a7ff494c322558eb',
+        '6073c436dcd064a48127ddbf6032ac1a66fd59a0c24434f070d4e564c124c897',
+        'ca993121846c464d666096d35f13bf44c1b05af205f9b4a1e00cf6cc10c5e511'
+    );
+
+    /**
+     * @param string $appId Application id for the running application
+     * @param string|null $attestDir Directory where trusted attestation roots may be found
+     * @throws Error If OpenSSL older than 1.0.0 is used
+     */
+    public function __construct($appId, $attestDir = null)
+    {
+        if(OPENSSL_VERSION_NUMBER < 0x10000000) {
+            throw new Error('OpenSSL has to be at least version 1.0.0, this is ' . OPENSSL_VERSION_TEXT, ERR_OLD_OPENSSL);
+        }
+        $this->appId = $appId;
+        $this->attestDir = $attestDir;
+    }
+
+    /**
+     * Called to get a registration request to send to a user.
+     * Returns an array of one registration request and a array of sign requests.
+     *
+     * @param array $registrations List of current registrations for this
+     * user, to prevent the user from registering the same authenticator several
+     * times.
+     * @return array An array of two elements, the first containing a
+     * RegisterRequest the second being an array of SignRequest
+     * @throws Error
+     */
+    public function getRegisterData(array $registrations = array())
+    {
+        $challenge = $this->createChallenge();
+        $request = new RegisterRequest($challenge, $this->appId);
+        $signs = $this->getAuthenticateData($registrations);
+        return array($request, $signs);
+    }
+
+    /**
+     * Called to verify and unpack a registration message.
+     *
+     * @param RegisterRequest $request this is a reply to
+     * @param object $response response from a user
+     * @param bool $includeCert set to true if the attestation certificate should be
+     * included in the returned Registration object
+     * @return Registration
+     * @throws Error
+     */
+    public function doRegister($request, $response, $includeCert = true)
+    {
+        if( !is_object( $request ) ) {
+            throw new \InvalidArgumentException('$request of doRegister() method only accepts object.');
+        }
+
+        if( !is_object( $response ) ) {
+            throw new \InvalidArgumentException('$response of doRegister() method only accepts object.');
+        }
+
+        if( property_exists( $response, 'errorCode') && $response->errorCode !== 0 ) {
+            throw new Error('User-agent returned error. Error code: ' . $response->errorCode, ERR_BAD_UA_RETURNING );
+        }
+
+        if( !is_bool( $includeCert ) ) {
+            throw new \InvalidArgumentException('$include_cert of doRegister() method only accepts boolean.');
+        }
+
+        $rawReg = $this->base64u_decode($response->registrationData);
+        $regData = array_values(unpack('C*', $rawReg));
+        $clientData = $this->base64u_decode($response->clientData);
+        $cli = json_decode($clientData);
+
+        if($cli->challenge !== $request->challenge) {
+            throw new Error('Registration challenge does not match', ERR_UNMATCHED_CHALLENGE );
+        }
+
+        $registration = new Registration();
+        $offs = 1;
+        $pubKey = substr($rawReg, $offs, PUBKEY_LEN);
+        $offs += PUBKEY_LEN;
+        // decode the pubKey to make sure it's good
+        $tmpKey = $this->pubkey_to_pem($pubKey);
+        if($tmpKey === null) {
+            throw new Error('Decoding of public key failed', ERR_PUBKEY_DECODE );
+        }
+        $registration->publicKey = base64_encode($pubKey);
+        $khLen = $regData[$offs++];
+        $kh = substr($rawReg, $offs, $khLen);
+        $offs += $khLen;
+        $registration->keyHandle = $this->base64u_encode($kh);
+
+        // length of certificate is stored in byte 3 and 4 (excluding the first 4 bytes)
+        $certLen = 4;
+        $certLen += ($regData[$offs + 2] << 8);
+        $certLen += $regData[$offs + 3];
+
+        $rawCert = $this->fixSignatureUnusedBits(substr($rawReg, $offs, $certLen));
+        $offs += $certLen;
+        $pemCert  = "-----BEGIN CERTIFICATE-----\r\n";
+        $pemCert .= chunk_split(base64_encode($rawCert), 64);
+        $pemCert .= "-----END CERTIFICATE-----";
+        if($includeCert) {
+            $registration->certificate = base64_encode($rawCert);
+        }
+        if($this->attestDir) {
+            if(openssl_x509_checkpurpose($pemCert, -1, $this->get_certs()) !== true) {
+                throw new Error('Attestation certificate can not be validated', ERR_ATTESTATION_VERIFICATION );
+            }
+        }
+
+        if(!openssl_pkey_get_public($pemCert)) {
+            throw new Error('Decoding of public key failed', ERR_PUBKEY_DECODE );
+        }
+        $signature = substr($rawReg, $offs);
+
+        $dataToVerify  = chr(0);
+        $dataToVerify .= hash('sha256', $request->appId, true);
+        $dataToVerify .= hash('sha256', $clientData, true);
+        $dataToVerify .= $kh;
+        $dataToVerify .= $pubKey;
+
+        if(openssl_verify($dataToVerify, $signature, $pemCert, 'sha256') === 1) {
+            return $registration;
+        } else {
+            throw new Error('Attestation signature does not match', ERR_ATTESTATION_SIGNATURE );
+        }
+    }
+
+    /**
+     * Called to get an authentication request.
+     *
+     * @param array $registrations An array of the registrations to create authentication requests for.
+     * @return array An array of SignRequest
+     * @throws Error
+     */
+    public function getAuthenticateData(array $registrations)
+    {
+        $sigs = array();
+        $challenge = $this->createChallenge();
+        foreach ($registrations as $reg) {
+            if( !is_object( $reg ) ) {
+                throw new \InvalidArgumentException('$registrations of getAuthenticateData() method only accepts array of object.');
+            }
+
+            $sig = new SignRequest();
+            $sig->appId = $this->appId;
+            $sig->keyHandle = $reg->keyHandle;
+            $sig->challenge = $challenge;
+            $sigs[] = $sig;
+        }
+        return $sigs;
+    }
+
+    /**
+     * Called to verify an authentication response
+     *
+     * @param array $requests An array of outstanding authentication requests
+     * @param array $registrations An array of current registrations
+     * @param object $response A response from the authenticator
+     * @return Registration
+     * @throws Error
+     *
+     * The Registration object returned on success contains an updated counter
+     * that should be saved for future authentications.
+     * If the Error returned is ERR_COUNTER_TOO_LOW this is an indication of
+     * token cloning or similar and appropriate action should be taken.
+     */
+    public function doAuthenticate(array $requests, array $registrations, $response)
+    {
+        if( !is_object( $response ) ) {
+            throw new \InvalidArgumentException('$response of doAuthenticate() method only accepts object.');
+        }
+
+        if( property_exists( $response, 'errorCode') && $response->errorCode !== 0 ) {
+            throw new Error('User-agent returned error. Error code: ' . $response->errorCode, ERR_BAD_UA_RETURNING );
+        }
+
+        /** @var object|null $req */
+        $req = null;
+
+        /** @var object|null $reg */
+        $reg = null;
+
+        $clientData = $this->base64u_decode($response->clientData);
+        $decodedClient = json_decode($clientData);
+        foreach ($requests as $req) {
+            if( !is_object( $req ) ) {
+                throw new \InvalidArgumentException('$requests of doAuthenticate() method only accepts array of object.');
+            }
+
+            if($req->keyHandle === $response->keyHandle && $req->challenge === $decodedClient->challenge) {
+                break;
+            }
+
+            $req = null;
+        }
+        if($req === null) {
+            throw new Error('No matching request found', ERR_NO_MATCHING_REQUEST );
+        }
+        foreach ($registrations as $reg) {
+            if( !is_object( $reg ) ) {
+                throw new \InvalidArgumentException('$registrations of doAuthenticate() method only accepts array of object.');
+            }
+
+            if($reg->keyHandle === $response->keyHandle) {
+                break;
+            }
+            $reg = null;
+        }
+        if($reg === null) {
+            throw new Error('No matching registration found', ERR_NO_MATCHING_REGISTRATION );
+        }
+        $pemKey = $this->pubkey_to_pem($this->base64u_decode($reg->publicKey));
+        if($pemKey === null) {
+            throw new Error('Decoding of public key failed', ERR_PUBKEY_DECODE );
+        }
+
+        $signData = $this->base64u_decode($response->signatureData);
+        $dataToVerify  = hash('sha256', $req->appId, true);
+        $dataToVerify .= substr($signData, 0, 5);
+        $dataToVerify .= hash('sha256', $clientData, true);
+        $signature = substr($signData, 5);
+
+        if(openssl_verify($dataToVerify, $signature, $pemKey, 'sha256') === 1) {
+            $ctr = unpack("Nctr", substr($signData, 1, 4));
+            $counter = $ctr['ctr'];
+            /* TODO: wrap-around should be handled somehow.. */
+            if($counter > $reg->counter) {
+                $reg->counter = $counter;
+                return $reg;
+            } else {
+                throw new Error('Counter too low.', ERR_COUNTER_TOO_LOW );
+            }
+        } else {
+            throw new Error('Authentication failed', ERR_AUTHENTICATION_FAILURE );
+        }
+    }
+
+    /**
+     * @return array
+     */
+    private function get_certs()
+    {
+        $files = array();
+        $dir = $this->attestDir;
+        if($dir && $handle = opendir($dir)) {
+            while(false !== ($entry = readdir($handle))) {
+                if(is_file("$dir/$entry")) {
+                    $files[] = "$dir/$entry";
+                }
+            }
+            closedir($handle);
+        }
+        return $files;
+    }
+
+    /**
+     * @param string $data
+     * @return string
+     */
+    private function base64u_encode($data)
+    {
+        return trim(strtr(base64_encode($data), '+/', '-_'), '=');
+    }
+
+    /**
+     * @param string $data
+     * @return string
+     */
+    private function base64u_decode($data)
+    {
+        return base64_decode(strtr($data, '-_', '+/'));
+    }
+
+    /**
+     * @param string $key
+     * @return null|string
+     */
+    private function pubkey_to_pem($key)
+    {
+        if(strlen($key) !== PUBKEY_LEN || $key[0] !== "\x04") {
+            return null;
+        }
+
+        /*
+         * Convert the public key to binary DER format first
+         * Using the ECC SubjectPublicKeyInfo OIDs from RFC 5480
+         *
+         *  SEQUENCE(2 elem)                        30 59
+         *   SEQUENCE(2 elem)                       30 13
+         *    OID1.2.840.10045.2.1 (id-ecPublicKey) 06 07 2a 86 48 ce 3d 02 01
+         *    OID1.2.840.10045.3.1.7 (secp256r1)    06 08 2a 86 48 ce 3d 03 01 07
+         *   BIT STRING(520 bit)                    03 42 ..key..
+         */
+        $der  = "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01";
+        $der .= "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42";
+        $der .= "\0".$key;
+
+        $pem  = "-----BEGIN PUBLIC KEY-----\r\n";
+        $pem .= chunk_split(base64_encode($der), 64);
+        $pem .= "-----END PUBLIC KEY-----";
+
+        return $pem;
+    }
+
+    /**
+     * @return string
+     * @throws Error
+     */
+    private function createChallenge()
+    {
+        $challenge = openssl_random_pseudo_bytes(32, $crypto_strong );
+        if( $crypto_strong !== true ) {
+            throw new Error('Unable to obtain a good source of randomness', ERR_BAD_RANDOM);
+        }
+
+        $challenge = $this->base64u_encode( $challenge );
+
+        return $challenge;
+    }
+
+    /**
+     * Fixes a certificate where the signature contains unused bits.
+     *
+     * @param string $cert
+     * @return mixed
+     */
+    private function fixSignatureUnusedBits($cert)
+    {
+        if(in_array(hash('sha256', $cert), $this->FIXCERTS)) {
+            $cert[strlen($cert) - 257] = "\0";
+        }
+        return $cert;
+    }
+}
+
+/**
+ * Class for building a registration request
+ *
+ * @package u2flib_server
+ */
+class RegisterRequest
+{
+    /** Protocol version */
+    public $version = U2F_VERSION;
+
+    /** Registration challenge */
+    public $challenge;
+
+    /** Application id */
+    public $appId;
+
+    /**
+     * @param string $challenge
+     * @param string $appId
+     * @internal
+     */
+    public function __construct($challenge, $appId)
+    {
+        $this->challenge = $challenge;
+        $this->appId = $appId;
+    }
+}
+
+/**
+ * Class for building up an authentication request
+ *
+ * @package u2flib_server
+ */
+class SignRequest
+{
+    /** Protocol version */
+    public $version = U2F_VERSION;
+
+    /** Authentication challenge */
+    public $challenge;
+
+    /** Key handle of a registered authenticator */
+    public $keyHandle;
+
+    /** Application id */
+    public $appId;
+}
+
+/**
+ * Class returned for successful registrations
+ *
+ * @package u2flib_server
+ */
+class Registration
+{
+    /** The key handle of the registered authenticator */
+    public $keyHandle;
+
+    /** The public key of the registered authenticator */
+    public $publicKey;
+
+    /** The attestation certificate of the registered authenticator */
+    public $certificate;
+
+    /** The counter associated with this registration */
+    public $counter = -1;
+}
+
+/**
+ * Error class, returned on errors
+ *
+ * @package u2flib_server
+ */
+class Error extends \Exception
+{
+    /**
+     * Override constructor and make message and code mandatory
+     * @param string $message
+     * @param int $code
+     * @param \Exception|null $previous
+     */
+    public function __construct($message, $code, \Exception $previous = null) {
+        parent::__construct($message, $code, $previous);
+    }
+}

+ 8 - 6
data/web/index.php

@@ -73,12 +73,14 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
           <?php
           endforeach;
           $app_links = customize('get', 'app_links');
-          foreach ($app_links as $row) {
-            foreach ($row as $key => $val):
-          ?>
-            <a href="<?= htmlspecialchars($val); ?>" role="button" class="btn btn-lg btn-default"><?= htmlspecialchars($key); ?></a>&nbsp;
-          <?php 
-            endforeach;
+          if (!empty($app_links)) {
+            foreach ($app_links as $row) {
+              foreach ($row as $key => $val):
+            ?>
+              <a href="<?= htmlspecialchars($val); ?>" role="button" class="btn btn-lg btn-default"><?= htmlspecialchars($key); ?></a>&nbsp;
+            <?php 
+              endforeach;
+            }
           }
           ?>
         </div>

+ 450 - 353
data/web/js/u2f-api.js

@@ -1,26 +1,40 @@
-// Copyright 2014-2015 Google Inc. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
+//Copyright 2014-2015 Google Inc. All rights reserved.
+
+//Use of this source code is governed by a BSD-style
+//license that can be found in the LICENSE file or at
+//https://developers.google.com/open-source/licenses/bsd
 
 /**
  * @fileoverview The U2F api.
  */
-
 'use strict';
 
-/** Namespace for the U2F api.
+
+/**
+ * Namespace for the U2F api.
  * @type {Object}
  */
 var u2f = u2f || {};
 
+/**
+ * FIDO U2F Javascript API Version
+ * @number
+ */
+var js_api_version;
+
 /**
  * The U2F extension id
- * @type {string}
- * @const
+ * @const {string}
  */
-u2f.EXTENSION_ID = 'kmendfapggjehodndflmmgagdbamhnfd';
+// The Chrome packaged app extension ID.
+// Uncomment this if you want to deploy a server instance that uses
+// the package Chrome app and does not require installing the U2F Chrome extension.
+ u2f.EXTENSION_ID = 'kmendfapggjehodndflmmgagdbamhnfd';
+// The U2F Chrome extension ID.
+// Uncomment this if you want to deploy a server instance that uses
+// the U2F Chrome extension to authenticate.
+// u2f.EXTENSION_ID = 'pfboblefjcgdjicmnffhdgionmgcdmne';
+
 
 /**
  * Message types for messsages to/from the extension
@@ -29,11 +43,14 @@ u2f.EXTENSION_ID = 'kmendfapggjehodndflmmgagdbamhnfd';
  */
 u2f.MessageTypes = {
     'U2F_REGISTER_REQUEST': 'u2f_register_request',
-    'U2F_SIGN_REQUEST': 'u2f_sign_request',
     'U2F_REGISTER_RESPONSE': 'u2f_register_response',
-    'U2F_SIGN_RESPONSE': 'u2f_sign_response'
+    'U2F_SIGN_REQUEST': 'u2f_sign_request',
+    'U2F_SIGN_RESPONSE': 'u2f_sign_response',
+    'U2F_GET_API_VERSION_REQUEST': 'u2f_get_api_version_request',
+    'U2F_GET_API_VERSION_RESPONSE': 'u2f_get_api_version_response'
 };
 
+
 /**
  * Response status codes
  * @const
@@ -48,17 +65,18 @@ u2f.ErrorCodes = {
     'TIMEOUT': 5
 };
 
+
 /**
- * A message type for registration requests
+ * A message for registration requests
  * @typedef {{
  *   type: u2f.MessageTypes,
- *   signRequests: Array<u2f.SignRequest>,
- *   registerRequests: ?Array<u2f.RegisterRequest>,
+ *   appId: ?string,
  *   timeoutSeconds: ?number,
  *   requestId: ?number
  * }}
  */
-u2f.Request;
+u2f.U2fRequest;
+
 
 /**
  * A message for registration responses
@@ -68,7 +86,8 @@ u2f.Request;
  *   requestId: ?number
  * }}
  */
-u2f.Response;
+u2f.U2fResponse;
+
 
 /**
  * An error object for responses
@@ -79,6 +98,19 @@ u2f.Response;
  */
 u2f.Error;
 
+/**
+ * Data object for a single sign request.
+ * @typedef {enum {BLUETOOTH_RADIO, BLUETOOTH_LOW_ENERGY, USB, NFC}}
+ */
+u2f.Transport;
+
+
+/**
+ * Data object for a single sign request.
+ * @typedef {Array<u2f.Transport>}
+ */
+u2f.Transports;
+
 /**
  * Data object for a single sign request.
  * @typedef {{
@@ -90,6 +122,7 @@ u2f.Error;
  */
 u2f.SignRequest;
 
+
 /**
  * Data object for a sign response.
  * @typedef {{
@@ -100,27 +133,51 @@ u2f.SignRequest;
  */
 u2f.SignResponse;
 
+
 /**
  * Data object for a registration request.
  * @typedef {{
  *   version: string,
- *   challenge: string,
- *   appId: string
+ *   challenge: string
  * }}
  */
 u2f.RegisterRequest;
 
+
 /**
  * Data object for a registration response.
  * @typedef {{
- *   registrationData: string,
- *   clientData: string
+ *   version: string,
+ *   keyHandle: string,
+ *   transports: Transports,
+ *   appId: string
  * }}
  */
 u2f.RegisterResponse;
 
 
-// Low level MessagePort API support
+/**
+ * Data object for a registered key.
+ * @typedef {{
+ *   version: string,
+ *   keyHandle: string,
+ *   transports: ?Transports,
+ *   appId: ?string
+ * }}
+ */
+u2f.RegisteredKey;
+
+
+/**
+ * Data object for a get API register response.
+ * @typedef {{
+ *   js_api_version: number
+ * }}
+ */
+u2f.GetJsApiVersionResponse;
+
+
+//Low level MessagePort API support
 
 /**
  * Sets up a MessagePort to the U2F extension using the
@@ -128,32 +185,34 @@ u2f.RegisterResponse;
  * @param {function((MessagePort|u2f.WrappedChromeRuntimePort_))} callback
  */
 u2f.getMessagePort = function(callback) {
-    if (typeof chrome != 'undefined' && chrome.runtime) {
-        // The actual message here does not matter, but we need to get a reply
-        // for the callback to run. Thus, send an empty signature request
-        // in order to get a failure response.
-        var msg = {
-            type: u2f.MessageTypes.U2F_SIGN_REQUEST,
-            signRequests: []
-        };
-        chrome.runtime.sendMessage(u2f.EXTENSION_ID, msg, function() {
-            if (!chrome.runtime.lastError) {
-                // We are on a whitelisted origin and can talk directly
-                // with the extension.
-                u2f.getChromeRuntimePort_(callback);
-            } else {
-                // chrome.runtime was available, but we couldn't message
-                // the extension directly, use iframe
-                u2f.getIframePort_(callback);
-            }
-        });
-    } else if (u2f.isAndroidChrome_()) {
-        u2f.getAuthenticatorPort_(callback);
-    } else {
-        // chrome.runtime was not available at all, which is normal
-        // when this origin doesn't have access to any extensions.
+  if (typeof chrome != 'undefined' && chrome.runtime) {
+    // The actual message here does not matter, but we need to get a reply
+    // for the callback to run. Thus, send an empty signature request
+    // in order to get a failure response.
+    var msg = {
+        type: u2f.MessageTypes.U2F_SIGN_REQUEST,
+        signRequests: []
+    };
+    chrome.runtime.sendMessage(u2f.EXTENSION_ID, msg, function() {
+      if (!chrome.runtime.lastError) {
+        // We are on a whitelisted origin and can talk directly
+        // with the extension.
+        u2f.getChromeRuntimePort_(callback);
+      } else {
+        // chrome.runtime was available, but we couldn't message
+        // the extension directly, use iframe
         u2f.getIframePort_(callback);
-    }
+      }
+    });
+  } else if (u2f.isAndroidChrome_()) {
+    u2f.getAuthenticatorPort_(callback);
+  } else if (u2f.isIosChrome_()) {
+    u2f.getIosPort_(callback);
+  } else {
+    // chrome.runtime was not available at all, which is normal
+    // when this origin doesn't have access to any extensions.
+    u2f.getIframePort_(callback);
+  }
 };
 
 /**
@@ -161,22 +220,30 @@ u2f.getMessagePort = function(callback) {
  * @private
  */
 u2f.isAndroidChrome_ = function() {
-    var userAgent = navigator.userAgent;
-    return userAgent.indexOf('Chrome') != -1 &&
-        userAgent.indexOf('Android') != -1;
+  var userAgent = navigator.userAgent;
+  return userAgent.indexOf('Chrome') != -1 &&
+  userAgent.indexOf('Android') != -1;
 };
 
 /**
- * Connects directly to the extension via chrome.runtime.connect
+ * Detect chrome running on iOS based on the browser's platform.
+ * @private
+ */
+u2f.isIosChrome_ = function() {
+  return ["iPhone", "iPad", "iPod"].indexOf(navigator.platform) > -1;
+};
+
+/**
+ * Connects directly to the extension via chrome.runtime.connect.
  * @param {function(u2f.WrappedChromeRuntimePort_)} callback
  * @private
  */
 u2f.getChromeRuntimePort_ = function(callback) {
-    var port = chrome.runtime.connect(u2f.EXTENSION_ID,
-        {'includeTlsChannelId': true});
-    setTimeout(function() {
-        callback(new u2f.WrappedChromeRuntimePort_(port));
-    }, 0);
+  var port = chrome.runtime.connect(u2f.EXTENSION_ID,
+      {'includeTlsChannelId': true});
+  setTimeout(function() {
+    callback(new u2f.WrappedChromeRuntimePort_(port));
+  }, 0);
 };
 
 /**
@@ -185,9 +252,20 @@ u2f.getChromeRuntimePort_ = function(callback) {
  * @private
  */
 u2f.getAuthenticatorPort_ = function(callback) {
-    setTimeout(function() {
-        callback(new u2f.WrappedAuthenticatorPort_());
-    }, 0);
+  setTimeout(function() {
+    callback(new u2f.WrappedAuthenticatorPort_());
+  }, 0);
+};
+
+/**
+ * Return a 'port' abstraction to the iOS client app.
+ * @param {function(u2f.WrappedIosPort_)} callback
+ * @private
+ */
+u2f.getIosPort_ = function(callback) {
+  setTimeout(function() {
+    callback(new u2f.WrappedIosPort_());
+  }, 0);
 };
 
 /**
@@ -197,53 +275,100 @@ u2f.getAuthenticatorPort_ = function(callback) {
  * @private
  */
 u2f.WrappedChromeRuntimePort_ = function(port) {
-    this.port_ = port;
+  this.port_ = port;
 };
 
 /**
- * Format a return a sign request.
+ * Format and return a sign request compliant with the JS API version supported by the extension.
  * @param {Array<u2f.SignRequest>} signRequests
  * @param {number} timeoutSeconds
  * @param {number} reqId
  * @return {Object}
  */
-u2f.WrappedChromeRuntimePort_.prototype.formatSignRequest_ =
-    function(signRequests, timeoutSeconds, reqId) {
-        return {
-            type: u2f.MessageTypes.U2F_SIGN_REQUEST,
-            signRequests: signRequests,
-            timeoutSeconds: timeoutSeconds,
-            requestId: reqId
-        };
+u2f.formatSignRequest_ =
+  function(appId, challenge, registeredKeys, timeoutSeconds, reqId) {
+  if (js_api_version === undefined || js_api_version < 1.1) {
+    // Adapt request to the 1.0 JS API
+    var signRequests = [];
+    for (var i = 0; i < registeredKeys.length; i++) {
+      signRequests[i] = {
+          version: registeredKeys[i].version,
+          challenge: challenge,
+          keyHandle: registeredKeys[i].keyHandle,
+          appId: appId
+      };
+    }
+    return {
+      type: u2f.MessageTypes.U2F_SIGN_REQUEST,
+      signRequests: signRequests,
+      timeoutSeconds: timeoutSeconds,
+      requestId: reqId
     };
+  }
+  // JS 1.1 API
+  return {
+    type: u2f.MessageTypes.U2F_SIGN_REQUEST,
+    appId: appId,
+    challenge: challenge,
+    registeredKeys: registeredKeys,
+    timeoutSeconds: timeoutSeconds,
+    requestId: reqId
+  };
+};
 
 /**
- * Format a return a register request.
+ * Format and return a register request compliant with the JS API version supported by the extension..
  * @param {Array<u2f.SignRequest>} signRequests
  * @param {Array<u2f.RegisterRequest>} signRequests
  * @param {number} timeoutSeconds
  * @param {number} reqId
  * @return {Object}
  */
-u2f.WrappedChromeRuntimePort_.prototype.formatRegisterRequest_ =
-    function(signRequests, registerRequests, timeoutSeconds, reqId) {
-        return {
-            type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
-            signRequests: signRequests,
-            registerRequests: registerRequests,
-            timeoutSeconds: timeoutSeconds,
-            requestId: reqId
-        };
+u2f.formatRegisterRequest_ =
+  function(appId, registeredKeys, registerRequests, timeoutSeconds, reqId) {
+  if (js_api_version === undefined || js_api_version < 1.1) {
+    // Adapt request to the 1.0 JS API
+    for (var i = 0; i < registerRequests.length; i++) {
+      registerRequests[i].appId = appId;
+    }
+    var signRequests = [];
+    for (var i = 0; i < registeredKeys.length; i++) {
+      signRequests[i] = {
+          version: registeredKeys[i].version,
+          challenge: registerRequests[0],
+          keyHandle: registeredKeys[i].keyHandle,
+          appId: appId
+      };
+    }
+    return {
+      type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
+      signRequests: signRequests,
+      registerRequests: registerRequests,
+      timeoutSeconds: timeoutSeconds,
+      requestId: reqId
     };
+  }
+  // JS 1.1 API
+  return {
+    type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
+    appId: appId,
+    registerRequests: registerRequests,
+    registeredKeys: registeredKeys,
+    timeoutSeconds: timeoutSeconds,
+    requestId: reqId
+  };
+};
+
 
 /**
  * Posts a message on the underlying channel.
  * @param {Object} message
  */
 u2f.WrappedChromeRuntimePort_.prototype.postMessage = function(message) {
-    this.port_.postMessage(message);
+  this.port_.postMessage(message);
 };
 
+
 /**
  * Emulates the HTML 5 addEventListener interface. Works only for the
  * onmessage event, which is hooked up to the chrome.runtime.Port.onMessage.
@@ -252,16 +377,16 @@ u2f.WrappedChromeRuntimePort_.prototype.postMessage = function(message) {
  */
 u2f.WrappedChromeRuntimePort_.prototype.addEventListener =
     function(eventName, handler) {
-        var name = eventName.toLowerCase();
-        if (name == 'message' || name == 'onmessage') {
-            this.port_.onMessage.addListener(function(message) {
-                // Emulate a minimal MessageEvent object
-                handler({'data': message});
-            });
-        } else {
-            console.error('WrappedChromeRuntimePort only supports onMessage');
-        }
-    };
+  var name = eventName.toLowerCase();
+  if (name == 'message' || name == 'onmessage') {
+    this.port_.onMessage.addListener(function(message) {
+      // Emulate a minimal MessageEvent object
+      handler({'data': message});
+    });
+  } else {
+    console.error('WrappedChromeRuntimePort only supports onMessage');
+  }
+};
 
 /**
  * Wrap the Authenticator app with a MessagePort interface.
@@ -269,8 +394,8 @@ u2f.WrappedChromeRuntimePort_.prototype.addEventListener =
  * @private
  */
 u2f.WrappedAuthenticatorPort_ = function() {
-    this.requestId_ = -1;
-    this.requestObject_ = null;
+  this.requestId_ = -1;
+  this.requestObject_ = null;
 }
 
 /**
@@ -278,28 +403,39 @@ u2f.WrappedAuthenticatorPort_ = function() {
  * @param {Object} message
  */
 u2f.WrappedAuthenticatorPort_.prototype.postMessage = function(message) {
-    var intentLocation = /** @type {string} */ (message);
-    document.location = intentLocation;
+  var intentUrl =
+    u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ +
+    ';S.request=' + encodeURIComponent(JSON.stringify(message)) +
+    ';end';
+  document.location = intentUrl;
 };
 
+/**
+ * Tells what type of port this is.
+ * @return {String} port type
+ */
+u2f.WrappedAuthenticatorPort_.prototype.getPortType = function() {
+  return "WrappedAuthenticatorPort_";
+};
+
+
 /**
  * Emulates the HTML 5 addEventListener interface.
  * @param {string} eventName
  * @param {function({data: Object})} handler
  */
-u2f.WrappedAuthenticatorPort_.prototype.addEventListener =
-    function(eventName, handler) {
-        var name = eventName.toLowerCase();
-        if (name == 'message') {
-            var self = this;
-            /* Register a callback to that executes when
-             * chrome injects the response. */
-            window.addEventListener(
-                'message', self.onRequestUpdate_.bind(self, handler), false);
-        } else {
-            console.error('WrappedAuthenticatorPort only supports message');
-        }
-    };
+u2f.WrappedAuthenticatorPort_.prototype.addEventListener = function(eventName, handler) {
+  var name = eventName.toLowerCase();
+  if (name == 'message') {
+    var self = this;
+    /* Register a callback to that executes when
+     * chrome injects the response. */
+    window.addEventListener(
+        'message', self.onRequestUpdate_.bind(self, handler), false);
+  } else {
+    console.error('WrappedAuthenticatorPort only supports message');
+  }
+};
 
 /**
  * Callback invoked  when a response is received from the Authenticator.
@@ -308,72 +444,18 @@ u2f.WrappedAuthenticatorPort_.prototype.addEventListener =
  */
 u2f.WrappedAuthenticatorPort_.prototype.onRequestUpdate_ =
     function(callback, message) {
-        var messageObject = JSON.parse(message.data);
-        var intentUrl = messageObject['intentURL'];
-
-        var errorCode = messageObject['errorCode'];
-        var responseObject = null;
-        if (messageObject.hasOwnProperty('data')) {
-            responseObject = /** @type {Object} */ (
-                JSON.parse(messageObject['data']));
-            responseObject['requestId'] = this.requestId_;
-        }
-
-        /* Sign responses from the authenticator do not conform to U2F,
-         * convert to U2F here. */
-        responseObject = this.doResponseFixups_(responseObject);
-        callback({'data': responseObject});
-    };
+  var messageObject = JSON.parse(message.data);
+  var intentUrl = messageObject['intentURL'];
 
-/**
- * Fixup the response provided by the Authenticator to conform with
- * the U2F spec.
- * @param {Object} responseData
- * @return {Object} the U2F compliant response object
- */
-u2f.WrappedAuthenticatorPort_.prototype.doResponseFixups_ =
-    function(responseObject) {
-        if (responseObject.hasOwnProperty('responseData')) {
-            return responseObject;
-        } else if (this.requestObject_['type'] != u2f.MessageTypes.U2F_SIGN_REQUEST) {
-            // Only sign responses require fixups.  If this is not a response
-            // to a sign request, then an internal error has occurred.
-            return {
-                'type': u2f.MessageTypes.U2F_REGISTER_RESPONSE,
-                'responseData': {
-                    'errorCode': u2f.ErrorCodes.OTHER_ERROR,
-                    'errorMessage': 'Internal error: invalid response from Authenticator'
-                }
-            };
-        }
-
-        /* Non-conformant sign response, do fixups. */
-        var encodedChallengeObject = responseObject['challenge'];
-        if (typeof encodedChallengeObject !== 'undefined') {
-            var challengeObject = JSON.parse(atob(encodedChallengeObject));
-            var serverChallenge = challengeObject['challenge'];
-            var challengesList = this.requestObject_['signData'];
-            var requestChallengeObject = null;
-            for (var i = 0; i < challengesList.length; i++) {
-                var challengeObject = challengesList[i];
-                if (challengeObject['keyHandle'] == responseObject['keyHandle']) {
-                    requestChallengeObject = challengeObject;
-                    break;
-                }
-            }
-        }
-        var responseData = {
-            'errorCode': responseObject['resultCode'],
-            'keyHandle': responseObject['keyHandle'],
-            'signatureData': responseObject['signature'],
-            'clientData': encodedChallengeObject
-        };
-        return {
-            'type': u2f.MessageTypes.U2F_SIGN_RESPONSE,
-            'responseData': responseData,
-            'requestId': responseObject['requestId']
-        }
-    };
+  var errorCode = messageObject['errorCode'];
+  var responseObject = null;
+  if (messageObject.hasOwnProperty('data')) {
+    responseObject = /** @type {Object} */ (
+        JSON.parse(messageObject['data']));
+  }
+
+  callback({'data': responseObject});
+};
 
 /**
  * Base URL for intents to Authenticator.
@@ -381,126 +463,44 @@ u2f.WrappedAuthenticatorPort_.prototype.doResponseFixups_ =
  * @private
  */
 u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ =
-    'intent:#Intent;action=com.google.android.apps.authenticator.AUTHENTICATE';
+  'intent:#Intent;action=com.google.android.apps.authenticator.AUTHENTICATE';
 
 /**
- * Format a return a sign request.
- * @param {Array<u2f.SignRequest>} signRequests
- * @param {number} timeoutSeconds (ignored for now)
- * @param {number} reqId
- * @return {string}
- */
-u2f.WrappedAuthenticatorPort_.prototype.formatSignRequest_ =
-    function(signRequests, timeoutSeconds, reqId) {
-        if (!signRequests || signRequests.length == 0) {
-            return null;
-        }
-        /* TODO(fixme): stash away requestId, as the authenticator app does
-         * not return it for sign responses. */
-        this.requestId_ = reqId;
-        /* TODO(fixme): stash away the signRequests, to deal with the legacy
-         * response format returned by the Authenticator app. */
-        this.requestObject_ = {
-            'type': u2f.MessageTypes.U2F_SIGN_REQUEST,
-            'signData': signRequests,
-            'requestId': reqId,
-            'timeout': timeoutSeconds
-        };
-
-        var appId = signRequests[0]['appId'];
-        var intentUrl =
-            u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ +
-            ';S.appId=' + encodeURIComponent(appId) +
-            ';S.eventId=' + reqId +
-            ';S.challenges=' +
-            encodeURIComponent(
-                JSON.stringify(this.getBrowserDataList_(signRequests))) + ';end';
-        return intentUrl;
-    };
+ * Wrap the iOS client app with a MessagePort interface.
+ * @constructor
+ * @private
+ */
+u2f.WrappedIosPort_ = function() {};
 
 /**
- * Get the browser data objects from the challenge list
- * @param {Array} challenges list of challenges
- * @return {Array} list of browser data objects
- * @private
+ * Launch the iOS client app request
+ * @param {Object} message
  */
-u2f.WrappedAuthenticatorPort_
-    .prototype.getBrowserDataList_ = function(challenges) {
-    return challenges
-        .map(function(challenge) {
-            var browserData = {
-                'typ': 'navigator.id.getAssertion',
-                'challenge': challenge['challenge']
-            };
-            var challengeObject = {
-                'challenge' : browserData,
-                'keyHandle' : challenge['keyHandle']
-            };
-            return challengeObject;
-        });
+u2f.WrappedIosPort_.prototype.postMessage = function(message) {
+  var str = JSON.stringify(message);
+  var url = "u2f://auth?" + encodeURI(str);
+  location.replace(url);
 };
 
 /**
- * Format a return a register request.
- * @param {Array<u2f.SignRequest>} signRequests
- * @param {Array<u2f.RegisterRequest>} enrollChallenges
- * @param {number} timeoutSeconds (ignored for now)
- * @param {number} reqId
- * @return {Object}
+ * Tells what type of port this is.
+ * @return {String} port type
  */
-u2f.WrappedAuthenticatorPort_.prototype.formatRegisterRequest_ =
-    function(signRequests, enrollChallenges, timeoutSeconds, reqId) {
-        if (!enrollChallenges || enrollChallenges.length == 0) {
-            return null;
-        }
-        // Assume the appId is the same for all enroll challenges.
-        var appId = enrollChallenges[0]['appId'];
-        var registerRequests = [];
-        for (var i = 0; i < enrollChallenges.length; i++) {
-            var registerRequest = {
-                'challenge': enrollChallenges[i]['challenge'],
-                'version': enrollChallenges[i]['version']
-            };
-            if (enrollChallenges[i]['appId'] != appId) {
-                // Only include the appId when it differs from the first appId.
-                registerRequest['appId'] = enrollChallenges[i]['appId'];
-            }
-            registerRequests.push(registerRequest);
-        }
-        var registeredKeys = [];
-        if (signRequests) {
-            for (i = 0; i < signRequests.length; i++) {
-                var key = {
-                    'keyHandle': signRequests[i]['keyHandle'],
-                    'version': signRequests[i]['version']
-                };
-                // Only include the appId when it differs from the appId that's
-                // being registered now.
-                if (signRequests[i]['appId'] != appId) {
-                    key['appId'] = signRequests[i]['appId'];
-                }
-                registeredKeys.push(key);
-            }
-        }
-        var request = {
-            'type': u2f.MessageTypes.U2F_REGISTER_REQUEST,
-            'appId': appId,
-            'registerRequests': registerRequests,
-            'registeredKeys': registeredKeys,
-            'requestId': reqId,
-            'timeoutSeconds': timeoutSeconds
-        };
-        var intentUrl =
-            u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ +
-            ';S.request=' + encodeURIComponent(JSON.stringify(request)) +
-            ';end';
-        /* TODO(fixme): stash away requestId, this is is not necessary for
-         * register requests, but here to keep parity with sign.
-         */
-        this.requestId_ = reqId;
-        return intentUrl;
-    };
+u2f.WrappedIosPort_.prototype.getPortType = function() {
+  return "WrappedIosPort_";
+};
 
+/**
+ * Emulates the HTML 5 addEventListener interface.
+ * @param {string} eventName
+ * @param {function({data: Object})} handler
+ */
+u2f.WrappedIosPort_.prototype.addEventListener = function(eventName, handler) {
+  var name = eventName.toLowerCase();
+  if (name !== 'message') {
+    console.error('WrappedIosPort only supports message');
+  }
+};
 
 /**
  * Sets up an embedded trampoline iframe, sourced from the extension.
@@ -508,33 +508,33 @@ u2f.WrappedAuthenticatorPort_.prototype.formatRegisterRequest_ =
  * @private
  */
 u2f.getIframePort_ = function(callback) {
-    // Create the iframe
-    var iframeOrigin = 'chrome-extension://' + u2f.EXTENSION_ID;
-    var iframe = document.createElement('iframe');
-    iframe.src = iframeOrigin + '/u2f-comms.html';
-    iframe.setAttribute('style', 'display:none');
-    document.body.appendChild(iframe);
-
-    var channel = new MessageChannel();
-    var ready = function(message) {
-        if (message.data == 'ready') {
-            channel.port1.removeEventListener('message', ready);
-            callback(channel.port1);
-        } else {
-            console.error('First event on iframe port was not "ready"');
-        }
-    };
-    channel.port1.addEventListener('message', ready);
-    channel.port1.start();
-
-    iframe.addEventListener('load', function() {
-        // Deliver the port to the iframe and initialize
-        iframe.contentWindow.postMessage('init', iframeOrigin, [channel.port2]);
-    });
+  // Create the iframe
+  var iframeOrigin = 'chrome-extension://' + u2f.EXTENSION_ID;
+  var iframe = document.createElement('iframe');
+  iframe.src = iframeOrigin + '/u2f-comms.html';
+  iframe.setAttribute('style', 'display:none');
+  document.body.appendChild(iframe);
+
+  var channel = new MessageChannel();
+  var ready = function(message) {
+    if (message.data == 'ready') {
+      channel.port1.removeEventListener('message', ready);
+      callback(channel.port1);
+    } else {
+      console.error('First event on iframe port was not "ready"');
+    }
+  };
+  channel.port1.addEventListener('message', ready);
+  channel.port1.start();
+
+  iframe.addEventListener('load', function() {
+    // Deliver the port to the iframe and initialize
+    iframe.contentWindow.postMessage('init', iframeOrigin, [channel.port2]);
+  });
 };
 
 
-// High-level JS API
+//High-level JS API
 
 /**
  * Default extension response timeout in seconds.
@@ -577,22 +577,22 @@ u2f.callbackMap_ = {};
  * @private
  */
 u2f.getPortSingleton_ = function(callback) {
-    if (u2f.port_) {
-        callback(u2f.port_);
-    } else {
-        if (u2f.waitingForPort_.length == 0) {
-            u2f.getMessagePort(function(port) {
-                u2f.port_ = port;
-                u2f.port_.addEventListener('message',
-                    /** @type {function(Event)} */ (u2f.responseHandler_));
-
-                // Careful, here be async callbacks. Maybe.
-                while (u2f.waitingForPort_.length)
-                    u2f.waitingForPort_.shift()(u2f.port_);
-            });
-        }
-        u2f.waitingForPort_.push(callback);
+  if (u2f.port_) {
+    callback(u2f.port_);
+  } else {
+    if (u2f.waitingForPort_.length == 0) {
+      u2f.getMessagePort(function(port) {
+        u2f.port_ = port;
+        u2f.port_.addEventListener('message',
+            /** @type {function(Event)} */ (u2f.responseHandler_));
+
+        // Careful, here be async callbacks. Maybe.
+        while (u2f.waitingForPort_.length)
+          u2f.waitingForPort_.shift()(u2f.port_);
+      });
     }
+    u2f.waitingForPort_.push(callback);
+  }
 };
 
 /**
@@ -601,51 +601,148 @@ u2f.getPortSingleton_ = function(callback) {
  * @private
  */
 u2f.responseHandler_ = function(message) {
-    var response = message.data;
-    var reqId = response['requestId'];
-    if (!reqId || !u2f.callbackMap_[reqId]) {
-        console.error('Unknown or missing requestId in response.');
-        return;
-    }
-    var cb = u2f.callbackMap_[reqId];
-    delete u2f.callbackMap_[reqId];
-    cb(response['responseData']);
+  var response = message.data;
+  var reqId = response['requestId'];
+  if (!reqId || !u2f.callbackMap_[reqId]) {
+    console.error('Unknown or missing requestId in response.');
+    return;
+  }
+  var cb = u2f.callbackMap_[reqId];
+  delete u2f.callbackMap_[reqId];
+  cb(response['responseData']);
 };
 
 /**
  * Dispatches an array of sign requests to available U2F tokens.
- * @param {Array<u2f.SignRequest>} signRequests
+ * If the JS API version supported by the extension is unknown, it first sends a
+ * message to the extension to find out the supported API version and then it sends
+ * the sign request.
+ * @param {string=} appId
+ * @param {string=} challenge
+ * @param {Array<u2f.RegisteredKey>} registeredKeys
  * @param {function((u2f.Error|u2f.SignResponse))} callback
  * @param {number=} opt_timeoutSeconds
  */
-u2f.sign = function(signRequests, callback, opt_timeoutSeconds) {
-    u2f.getPortSingleton_(function(port) {
-        var reqId = ++u2f.reqCounter_;
-        u2f.callbackMap_[reqId] = callback;
-        var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
-            opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
-        var req = port.formatSignRequest_(signRequests, timeoutSeconds, reqId);
-        port.postMessage(req);
-    });
+u2f.sign = function(appId, challenge, registeredKeys, callback, opt_timeoutSeconds) {
+  if (js_api_version === undefined) {
+    // Send a message to get the extension to JS API version, then send the actual sign request.
+    u2f.getApiVersion(
+        function (response) {
+          js_api_version = response['js_api_version'] === undefined ? 0 : response['js_api_version'];
+          console.log("Extension JS API Version: ", js_api_version);
+          u2f.sendSignRequest(appId, challenge, registeredKeys, callback, opt_timeoutSeconds);
+        });
+  } else {
+    // We know the JS API version. Send the actual sign request in the supported API version.
+    u2f.sendSignRequest(appId, challenge, registeredKeys, callback, opt_timeoutSeconds);
+  }
+};
+
+/**
+ * Dispatches an array of sign requests to available U2F tokens.
+ * @param {string=} appId
+ * @param {string=} challenge
+ * @param {Array<u2f.RegisteredKey>} registeredKeys
+ * @param {function((u2f.Error|u2f.SignResponse))} callback
+ * @param {number=} opt_timeoutSeconds
+ */
+u2f.sendSignRequest = function(appId, challenge, registeredKeys, callback, opt_timeoutSeconds) {
+  u2f.getPortSingleton_(function(port) {
+    var reqId = ++u2f.reqCounter_;
+    u2f.callbackMap_[reqId] = callback;
+    var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
+        opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
+    var req = u2f.formatSignRequest_(appId, challenge, registeredKeys, timeoutSeconds, reqId);
+    port.postMessage(req);
+  });
 };
 
 /**
  * Dispatches register requests to available U2F tokens. An array of sign
  * requests identifies already registered tokens.
+ * If the JS API version supported by the extension is unknown, it first sends a
+ * message to the extension to find out the supported API version and then it sends
+ * the register request.
+ * @param {string=} appId
  * @param {Array<u2f.RegisterRequest>} registerRequests
- * @param {Array<u2f.SignRequest>} signRequests
+ * @param {Array<u2f.RegisteredKey>} registeredKeys
  * @param {function((u2f.Error|u2f.RegisterResponse))} callback
  * @param {number=} opt_timeoutSeconds
  */
-u2f.register = function(registerRequests, signRequests,
-                        callback, opt_timeoutSeconds) {
-    u2f.getPortSingleton_(function(port) {
-        var reqId = ++u2f.reqCounter_;
-        u2f.callbackMap_[reqId] = callback;
-        var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
-            opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
-        var req = port.formatRegisterRequest_(
-            signRequests, registerRequests, timeoutSeconds, reqId);
-        port.postMessage(req);
-    });
-};
+u2f.register = function(appId, registerRequests, registeredKeys, callback, opt_timeoutSeconds) {
+  if (js_api_version === undefined) {
+    // Send a message to get the extension to JS API version, then send the actual register request.
+    u2f.getApiVersion(
+        function (response) {
+          js_api_version = response['js_api_version'] === undefined ? 0: response['js_api_version'];
+          console.log("Extension JS API Version: ", js_api_version);
+          u2f.sendRegisterRequest(appId, registerRequests, registeredKeys,
+              callback, opt_timeoutSeconds);
+        });
+  } else {
+    // We know the JS API version. Send the actual register request in the supported API version.
+    u2f.sendRegisterRequest(appId, registerRequests, registeredKeys,
+        callback, opt_timeoutSeconds);
+  }
+};
+
+/**
+ * Dispatches register requests to available U2F tokens. An array of sign
+ * requests identifies already registered tokens.
+ * @param {string=} appId
+ * @param {Array<u2f.RegisterRequest>} registerRequests
+ * @param {Array<u2f.RegisteredKey>} registeredKeys
+ * @param {function((u2f.Error|u2f.RegisterResponse))} callback
+ * @param {number=} opt_timeoutSeconds
+ */
+u2f.sendRegisterRequest = function(appId, registerRequests, registeredKeys, callback, opt_timeoutSeconds) {
+  u2f.getPortSingleton_(function(port) {
+    var reqId = ++u2f.reqCounter_;
+    u2f.callbackMap_[reqId] = callback;
+    var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
+        opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
+    var req = u2f.formatRegisterRequest_(
+        appId, registeredKeys, registerRequests, timeoutSeconds, reqId);
+    port.postMessage(req);
+  });
+};
+
+
+/**
+ * Dispatches a message to the extension to find out the supported
+ * JS API version.
+ * If the user is on a mobile phone and is thus using Google Authenticator instead
+ * of the Chrome extension, don't send the request and simply return 0.
+ * @param {function((u2f.Error|u2f.GetJsApiVersionResponse))} callback
+ * @param {number=} opt_timeoutSeconds
+ */
+u2f.getApiVersion = function(callback, opt_timeoutSeconds) {
+ u2f.getPortSingleton_(function(port) {
+   // If we are using Android Google Authenticator or iOS client app,
+   // do not fire an intent to ask which JS API version to use.
+   if (port.getPortType) {
+     var apiVersion;
+     switch (port.getPortType()) {
+       case 'WrappedIosPort_':
+       case 'WrappedAuthenticatorPort_':
+         apiVersion = 1.1;
+         break;
+
+       default:
+         apiVersion = 0;
+         break;
+     }
+     callback({ 'js_api_version': apiVersion });
+     return;
+   }
+    var reqId = ++u2f.reqCounter_;
+    u2f.callbackMap_[reqId] = callback;
+    var req = {
+      type: u2f.MessageTypes.U2F_GET_API_VERSION_REQUEST,
+      timeoutSeconds: (typeof opt_timeoutSeconds !== 'undefined' ?
+          opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC),
+      requestId: reqId
+    };
+    port.postMessage(req);
+  });
+};

+ 19 - 6
data/web/json_api.php

@@ -1342,10 +1342,13 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
           case "u2f-registration":
             header('Content-Type: application/javascript');
             if (($_SESSION["mailcow_cc_role"] == "admin" || $_SESSION["mailcow_cc_role"] == "domainadmin") && $_SESSION["mailcow_cc_username"] == $object) {
-              $data = $u2f->getRegisterData(get_u2f_registrations($object));
-              list($req, $sigs) = $data;
+              list($req, $sigs) = $u2f->getRegisterData(get_u2f_registrations($object));
               $_SESSION['regReq'] = json_encode($req);
-              echo 'var req = ' . json_encode($req) . '; var sigs = ' . json_encode($sigs) . ';';
+              $_SESSION['regSigs'] = json_encode($sigs);
+              echo 'var req = ' . json_encode($req) . ';';
+              echo 'var registeredKeys = ' . json_encode($sigs) . ';';
+              echo 'var appId = req.appId;';
+              echo 'var registerRequests = [{version: req.version, challenge: req.challenge}];';
             }
             else {
               return;
@@ -1354,9 +1357,19 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
           case "u2f-authentication":
             header('Content-Type: application/javascript');
             if (isset($_SESSION['pending_mailcow_cc_username']) && $_SESSION['pending_mailcow_cc_username'] == $object) {
-              $reqs = json_encode($u2f->getAuthenticateData(get_u2f_registrations($object)));
-              $_SESSION['authReq']  = $reqs;
-              echo 'var req = ' . $reqs . ';';
+              $auth_data = $u2f->getAuthenticateData(get_u2f_registrations($object));
+              $challenge = $auth_data[0]->challenge;
+              $appId = $auth_data[0]->appId;
+              foreach ($auth_data as $each) {
+                $key = array(); // Empty array
+                $key['version']   = $each->version;
+                $key['keyHandle'] = $each->keyHandle;
+                $registeredKey[]  = $key;
+              }
+              $_SESSION['authReq']  = json_encode($auth_data);
+              echo 'var appId = "' . $appId . '";';
+              echo 'var challenge = ' . json_encode($challenge) . ';';
+              echo 'var registeredKeys = ' . json_encode($registeredKey) . ';';
             }
             else {
               return;