Browse Source

adding tests for all cases

El RIDO 4 months ago
parent
commit
603f7fd911
19 changed files with 145 additions and 100 deletions
  1. 3 1
      i18n/de.json
  2. 3 1
      i18n/es.json
  3. 3 1
      i18n/fr.json
  4. 3 1
      i18n/hu.json
  5. 3 1
      i18n/it.json
  6. 2 2
      i18n/nl.json
  7. 3 1
      i18n/no.json
  8. 3 1
      i18n/oc.json
  9. 3 1
      i18n/pl.json
  10. 4 2
      i18n/pt.json
  11. 3 1
      i18n/ru.json
  12. 3 1
      i18n/sl.json
  13. 3 1
      i18n/zh.json
  14. 41 62
      js/privatebin.js
  15. 2 2
      js/test/CryptTool.js
  16. 60 18
      js/test/InitialCheck.js
  17. 1 1
      js/test/ServerInteraction.js
  18. 1 1
      tpl/bootstrap.php
  19. 1 1
      tpl/page.php

+ 3 - 1
i18n/de.json

@@ -159,5 +159,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 3 - 1
i18n/es.json

@@ -159,5 +159,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 3 - 1
i18n/fr.json

@@ -168,5 +168,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 3 - 1
i18n/hu.json

@@ -159,5 +159,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 3 - 1
i18n/it.json

@@ -159,5 +159,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 2 - 2
i18n/nl.json

@@ -160,6 +160,6 @@
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
         "For more information <a href=\"%s\">see this FAQ entry</a>.",
-    "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 3 - 1
i18n/no.json

@@ -159,5 +159,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 3 - 1
i18n/oc.json

@@ -168,5 +168,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 3 - 1
i18n/pl.json

@@ -159,5 +159,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 4 - 2
i18n/pt.json

@@ -159,5 +159,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
-}
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
+}

+ 3 - 1
i18n/ru.json

@@ -169,5 +169,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 3 - 1
i18n/sl.json

@@ -168,5 +168,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 3 - 1
i18n/zh.json

@@ -159,5 +159,7 @@
     "This website is using an insecure HTTP connection! Please use it only for testing.":
         "This website is using an insecure HTTP connection! Please use it only for testing.",
     "For more information <a href=\"%s\">see this FAQ entry</a>.":
-        "For more information <a href=\"%s\">see this FAQ entry</a>."
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 41 - 62
js/privatebin.js

@@ -830,28 +830,13 @@ jQuery.PrivateBin = (function($, RawDeflate) {
          */
         function getRandomBytes(length)
         {
-            if (
-                typeof window !== 'undefined' &&
-                typeof Uint8Array !== 'undefined' &&
-                String.fromCodePoint &&
-                (
-                    typeof window.crypto !== 'undefined' ||
-                    typeof window.msCrypto !== 'undefined'
-                )
-            ) {
-                // modern browser environment
-                let bytes       = '';
-                const byteArray = new Uint8Array(length),
-                      crypto    = window.crypto || window.msCrypto;
-                crypto.getRandomValues(byteArray);
-                for (let i = 0; i < length; ++i) {
-                    bytes += String.fromCharCode(byteArray[i]);
-                }
-                return bytes;
-            } else {
-                // legacy browser or unsupported environment
-                throw 'No supported crypto API detected, you may read pastes and comments, but can\'t create pastes or add new comments.';
+            let bytes       = '';
+            const byteArray = new Uint8Array(length);
+            window.crypto.getRandomValues(byteArray);
+            for (let i = 0; i < length; ++i) {
+                bytes += String.fromCharCode(byteArray[i]);
             }
+            return bytes;
         }
 
         /**
@@ -4538,36 +4523,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
         ];
 
         /**
-         * blacklist of UserAgent versions known not to work with this application
-         *
-         * @private
-         * @enum   {Object}
-         * @readonly
-         */
-        const oldUA = [
-            {
-                'regex': /Chrome\/([0-9]+)/,
-                'minVersion': 57,
-            },
-            {
-                'regex': /Edge\/([0-9]+)/,
-                'minVersion': 16,
-            },
-            {
-                'regex': /Firefox\/([0-9]+)/,
-                'minVersion': 54,
-            },
-            {
-                'regex': /Opera\/.*Version\/([0-9]+)/,
-                'minVersion': 44,
-            },
-            {
-                'regex': /Version\/([0-9]+).*Safari/,
-                'minVersion': 11,
-            }
-        ];
-
-        /**
          * check if the connection is insecure
          *
          * @private
@@ -4602,7 +4557,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             // check whether a bot user agent part can be found in the current
             // user agent
             for (let i = 0; i < badBotUA.length; ++i) {
-                if (navigator.userAgent.indexOf(badBotUA) >= 0) {
+                if (navigator.userAgent.indexOf(badBotUA[i]) >= 0) {
                     return true;
                 }
             }
@@ -4610,7 +4565,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
         }
 
         /**
-         * checks whether this is an unsupported browser
+         * checks whether this is an unsupported browser, via feature detection
          *
          * @private
          * @name   InitialCheck.isOldBrowser
@@ -4618,13 +4573,34 @@ jQuery.PrivateBin = (function($, RawDeflate) {
          * @return {bool}
          */
         function isOldBrowser() {
-            for (let i = 0; i < oldUA.length; ++i) {
-                let result = oldUA[i]['regex'].exec(navigator.userAgent);
-                if (result && result[1] < oldUA[i]['minVersion']) {
-                    return true;
+            // webcrypto support
+            if (typeof window.crypto !== 'object') {
+                return false;
+            }
+
+            if (typeof WebAssembly !== 'object' && typeof WebAssembly.instantiate !== 'function') {
+                return false;
+            }
+            try {
+                // [\0, 'a', 's', 'm', (uint_32) 1] - smallest valid wasm module
+                const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
+                if (
+                    !(
+                        module instanceof WebAssembly.Module &&
+                        new WebAssembly.Instance(module) instanceof WebAssembly.Instance
+                    )
+                ) {
+                    return false;
                 }
+            } catch (e) {
+                return false;
             }
-            return false;
+
+             // not checking for async/await, ES6, Promise or Uint8Array support,
+             // as most browsers introduced these earlier then webassembly and webcrypto:
+             // https://github.com/PrivateBin/PrivateBin/pull/431#issuecomment-493129359
+
+            return true;
         }
 
         /**
@@ -4644,13 +4620,16 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             }
 
             if (isOldBrowser()) {
-                $('#oldnotice').toggle(true);
-                // execution will likely fail, but the user agent may be
-                // deliberately set to an incorrect value, so let it proceed
+                // some browsers (Chrome based ones) would have webcrypto support if using HTTPS
+                if (isInsecureConnection()) {
+                    Alert.showError(['Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href="%s">switching to HTTPS</a>.', 'https' + window.location.href.slice(4)]);
+                }
+                $('#oldnotice').removeClass('hidden');
+                return false;
             }
 
             if (isInsecureConnection()) {
-                $('#httpnotice').toggle(true);
+                $('#httpnotice').removeClass('hidden');
             }
 
             return true;

+ 2 - 2
js/test/CryptTool.js

@@ -10,7 +10,7 @@ describe('CryptTool', function () {
 
         this.timeout(30000);
         it('can en- and decrypt any message', function () {
-            jsc.check(jsc.forall(
+            jsc.assert(jsc.forall(
                 'string',
                 'string',
                 'string',
@@ -193,7 +193,7 @@ describe('CryptTool', function () {
         });
 
         it('can en- and decrypt a particular message (#260)', function () {
-            jsc.check(jsc.forall(
+            jsc.assert(jsc.forall(
                 'string',
                 'string',
                 async function (key, password) {

+ 60 - 18
js/test/InitialCheck.js

@@ -8,24 +8,66 @@ describe('InitialCheck', function () {
             cleanup();
         });
 
-        jsc.property(
-            'returns false and shows error, if a bot UA is detected',
-            'string',
-            jsc.elements(['Bot', 'bot']),
-            'string',
-            function (
-                prefix, botBit, suffix
-            ) {
-                const clean = jsdom(
-                    '<html><body><div id="errormessage" class="hidden"></div></body></html>',
-                    {'userAgent': prefix + botBit + suffix}
-                );
-                var result1 = $.PrivateBin.InitialCheck.init(),
-                    result2 = !$('#errormessage').hasClass('hidden');
-                clean();
-                return result1 && result2;
-            }
-        );
+        it('returns false and shows error, if a bot UA is detected', function () {
+            jsc.assert(jsc.forall(
+                'string',
+                jsc.elements(['Bot', 'bot']),
+                'string',
+                function (prefix, botBit, suffix) {
+                    const clean = jsdom('', {
+                        'userAgent': prefix + botBit + suffix
+                    });
+                    $('body').html(
+                        '<html><body><div id="errormessage" class="hidden"></div>' +
+                        '</body></html>'
+                    );
+                    $.PrivateBin.Alert.init();
+                    const result1 = !$.PrivateBin.InitialCheck.init(),
+                          result2 = !$('#errormessage').hasClass('hidden');
+                    clean();
+                    return result1 && result2;
+                }
+            ),
+            {tests: 1});
+        });
+
+        it('shows error, if no webcrypto is detected', function () {
+            [true, false].map(
+                function (secureProtocol) {
+                    const clean = jsdom('', {
+                        'url': (secureProtocol ? 'https' : 'http' ) + '://[::1]/'
+                    });
+                    $('body').html(
+                        '<html><body><div id="errormessage" class="hidden"></div>'+
+                        '<div id="oldnotice" class="hidden"></div></body></html>'
+                    );
+                    const crypto = window.crypto;
+                    window.crypto = null;
+                    $.PrivateBin.Alert.init();
+                    assert(!$.PrivateBin.InitialCheck.init());
+                    assert(secureProtocol === $('#errormessage').hasClass('hidden'));
+                    assert(!$('#oldnotice').hasClass('hidden'));
+                    window.crypto = crypto;
+                    clean();
+                }
+            );
+        });
+
+        it('shows error, if HTTP only site is detected', function () {
+            [true, false].map(
+                function (secureProtocol) {
+                    const clean = jsdom('', {
+                        'url': (secureProtocol ? 'https' : 'http' ) + '://[::1]/'
+                    });
+                    $('body').html(
+                        '<html><body><div id="httpnotice" class="hidden"></div></body></html>'
+                    );
+                    assert($.PrivateBin.InitialCheck.init());
+                    assert(secureProtocol === $('#httpnotice').hasClass('hidden'));
+                    clean();
+                }
+            );
+        });
     });
 });
 

+ 1 - 1
js/test/ServerInteraction.js

@@ -9,7 +9,7 @@ describe('ServerInteraction', function () {
         });
         this.timeout(30000);
         it('can prepare an encrypted paste', function () {
-            jsc.check(jsc.forall(
+            jsc.assert(jsc.forall(
                 'string',
                 'string',
                 'string',

+ 1 - 1
tpl/bootstrap.php

@@ -72,7 +72,7 @@ if ($MARKDOWN):
 endif;
 ?>
 		<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.10.js" integrity="sha512-CqskSFXERL38A1PJP9BlO04me7kmwgDIhN1+k24RoFiisEwXA0BMdm0lzJC7g5jCRZ4k5OYdOJGEqW9CwDl4CA==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-PuvR+R5FHPl2S8Gh6UdybTvipakps3ndEDAUAKoRhgmjmljHqAQLnvG13IkdCTIG2Xxn6peumQPvWhrOg1Xx3Q==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-PCFDgDmb2Q5KUo65OaSSyFBtXMUBcpvr1ah2jVvgRWMo1UYiuRaShnkmhiq0gKDRlTi5w2Z9Ttb1hmOmljP0+A==" crossorigin="anonymous"></script>
 		<!--[if IE]>
 		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;}</style>
 		<![endif]-->

+ 1 - 1
tpl/page.php

@@ -50,7 +50,7 @@ if ($MARKDOWN):
 endif;
 ?>
 		<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.10.js" integrity="sha512-CqskSFXERL38A1PJP9BlO04me7kmwgDIhN1+k24RoFiisEwXA0BMdm0lzJC7g5jCRZ4k5OYdOJGEqW9CwDl4CA==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-PuvR+R5FHPl2S8Gh6UdybTvipakps3ndEDAUAKoRhgmjmljHqAQLnvG13IkdCTIG2Xxn6peumQPvWhrOg1Xx3Q==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-PCFDgDmb2Q5KUo65OaSSyFBtXMUBcpvr1ah2jVvgRWMo1UYiuRaShnkmhiq0gKDRlTi5w2Z9Ttb1hmOmljP0+A==" crossorigin="anonymous"></script>
 		<!--[if IE]>
 		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;}</style>
 		<![endif]-->