| @@ -0,0 +1,178 @@ | |||
| const DEBUG = 0; | |||
| const DIRECT_PROXY = { | |||
| type: 'direct' | |||
| }; | |||
| const DEFAULT_PROXY_SETTINGS = { | |||
| type: 'direct', | |||
| host: '', | |||
| port: 0, | |||
| username: '', | |||
| password: '', | |||
| proxyDNS: false | |||
| }; | |||
| let proxies = [ DIRECT_PROXY, DIRECT_PROXY ]; | |||
| var skipLocal = 1; | |||
| var pendingRequests = []; | |||
| var currentProxy = 0; | |||
| function buttonClicked() { | |||
| currentProxy = (currentProxy ? 0 : 1); | |||
| if ( proxies[1].type == 'direct' ){ | |||
| currentProxy = 0; | |||
| } | |||
| browser.storage.local.set({ currentProxy: currentProxy }); | |||
| updateState(); | |||
| } | |||
| function updateState() { | |||
| if(currentProxy==0) | |||
| { | |||
| browser.browserAction.setIcon({path: "icons/unlock48.png"}); | |||
| browser.browserAction.setTitle({title: "Local IP"}); | |||
| } | |||
| else | |||
| { | |||
| browser.browserAction.setIcon({path: "icons/lock48.png"}); | |||
| browser.browserAction.setTitle({title: "Biukop Secure Internet"}); | |||
| } | |||
| } | |||
| function decodepass(pass) { | |||
| var result = atob(pass); | |||
| if (result.length <=3) | |||
| return pass; | |||
| if ("#!" != result.substring(result.length-3,result.length-1)) | |||
| return pass; | |||
| var tail = Number(result.substring(2,3)); | |||
| result = result.substring(5, result.length - tail); | |||
| return result; | |||
| } | |||
| function settingsChanged(settings) { | |||
| if ("proxySettings" in settings){ | |||
| proxies[1] = settings.proxySettings.newValue; | |||
| proxies[1].password = decodepass(proxies[1].password); | |||
| } | |||
| if ("skipLocal" in settings){ | |||
| skipLocal = settings.skipLocal.newValue; | |||
| } | |||
| if ("currentProxy" in settings) { | |||
| currentProxy = settings.currentProxy.newValue; | |||
| updateState(); | |||
| } | |||
| } | |||
| function completed(requestDetails) { | |||
| if (DEBUG) { | |||
| console.log("completed request: " + requestDetails.requestId); | |||
| } | |||
| var index = pendingRequests.indexOf(requestDetails.requestId); | |||
| if (index > -1) { | |||
| pendingRequests.splice(index, 1); | |||
| } | |||
| console.log("completed"); | |||
| } | |||
| function provideCredentialsSync(requestDetails) { | |||
| console.log("check credential"); | |||
| if (!requestDetails.isProxy) | |||
| return; | |||
| if (!currentProxy == 1) | |||
| return; | |||
| if (pendingRequests.indexOf(requestDetails.requestId) != -1) { | |||
| //if we've seen the request before, assume bad credentials and give up | |||
| console.log("Bad proxy credentials for request: " + requestDetails.requestId); | |||
| return {cancel:true}; | |||
| } | |||
| var credentials = { | |||
| username: proxies[1].username, | |||
| password: proxies[1].password | |||
| } | |||
| pendingRequests.push(requestDetails.requestId); | |||
| if (DEBUG) { | |||
| console.log(`Providing proxy credentials for request: ${requestDetails.requestId} username: ${credentials.username}`); | |||
| } | |||
| return {authCredentials: credentials}; | |||
| } | |||
| function isLocalIPv4(host) | |||
| { | |||
| var octets = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(host); | |||
| if(!octets) | |||
| return false; | |||
| if(octets[1]>255||octets[2]>255||octets[3]>255||octets[4]>255) | |||
| return false; | |||
| if(octets[1]==10||octets[1]==127) //class A or local loopback | |||
| return true; | |||
| if(octets[1]==172&&octets[2]>=16&&octets[2]<=31) //class B | |||
| return true; | |||
| if(octets[1]==192&&octets[2]==168) //class C | |||
| return true; | |||
| return false; | |||
| } | |||
| function isLocal(host) | |||
| { | |||
| if(host.indexOf('biukop') != -1) | |||
| return true; | |||
| if(host.indexOf('.') == -1) | |||
| return true; | |||
| if(host.endsWith(".local")) | |||
| return true; | |||
| if(host=="::1") | |||
| return true; | |||
| return(isLocalIPv4(host)); | |||
| } | |||
| function handleProxyRequest(requestInfo) { | |||
| const url = new URL(requestInfo.url); | |||
| var host = url.hostname; | |||
| var proxyNum = currentProxy; | |||
| if (skipLocal) { | |||
| if(isLocal(host)) { | |||
| if (DEBUG) | |||
| console.log(`Local host detected: ${host}`); | |||
| proxyNum = 0; | |||
| } | |||
| } | |||
| if (DEBUG) { | |||
| console.log(`Proxying: ${url.hostname}`); | |||
| console.log(proxies[proxyNum]); | |||
| } | |||
| return(proxies[proxyNum]); | |||
| } | |||
| browser.storage.local.get({ currentProxy: 0, skipLocal: true, proxySettings: DEFAULT_PROXY_SETTINGS }, items=>{ | |||
| currentProxy = items.currentProxy; | |||
| skipLocal = items.skipLocal; | |||
| proxies[1] = items.proxySettings; | |||
| proxies[1].password = decodepass(proxies[1].password); | |||
| updateState(); | |||
| }); | |||
| browser.storage.onChanged.addListener(settingsChanged); | |||
| browser.browserAction.onClicked.addListener(buttonClicked); | |||
| browser.proxy.onRequest.addListener(handleProxyRequest, {urls: ["<all_urls>"]}); | |||
| browser.proxy.onError.addListener(error => { | |||
| console.error(`Proxy error: ${error.message}`); | |||
| }); | |||
| browser.webRequest.onAuthRequired.addListener( | |||
| provideCredentialsSync, | |||
| {urls: ["<all_urls>"]}, | |||
| ["blocking"] | |||
| ); | |||
| browser.webRequest.onCompleted.addListener( | |||
| completed, | |||
| {urls: ["<all_urls>"]} | |||
| ); | |||
| browser.webRequest.onErrorOccurred.addListener( | |||
| completed, | |||
| {urls: ["<all_urls>"]} | |||
| ); | |||
| @@ -0,0 +1,44 @@ | |||
| { | |||
| "manifest_version": 2, | |||
| "name": "Biukop Secure Internet", | |||
| "version": "1.2.4", | |||
| "description": "Enforced Security communication through professional network.", | |||
| "icons": { | |||
| "48": "icons/lock48.png", | |||
| "96": "icons/lock96.png" | |||
| }, | |||
| "permissions": [ | |||
| "storage", | |||
| "proxy", | |||
| "<all_urls>", | |||
| "webRequest", | |||
| "webRequestBlocking" | |||
| ], | |||
| "browser_action": { | |||
| "browser_style": true, | |||
| "default_icon": "icons/lock48.png", | |||
| "default_title": "Secure Channel - Biukop" | |||
| }, | |||
| "commands": { | |||
| "_execute_browser_action": { | |||
| "suggested_key": { | |||
| "default": "Ctrl+Shift+Y" | |||
| }, | |||
| "description": "Enable/Disable Secure Connection" | |||
| } | |||
| }, | |||
| "background": { | |||
| "scripts": [ | |||
| "background.js" | |||
| ] | |||
| }, | |||
| "options_ui": { | |||
| "page": "settings.html", | |||
| "browser_style": true | |||
| }, | |||
| "applications": { | |||
| "gecko": { | |||
| "strict_min_version": "68.0" | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| #dnsrow{ | |||
| display: none; | |||
| } | |||
| .configtable { | |||
| border-collapse:collapse; | |||
| margin: 0px; | |||
| font-size: 12pt; | |||
| width:100%; | |||
| border: 0px dotted grey; | |||
| box-shadow: 3px 3px 12px #000 inset; | |||
| border-radius: 10px; | |||
| } | |||
| .configtable th,.configtable td { | |||
| border: 1px solid white; | |||
| padding: 10px; | |||
| } | |||
| .configtable th { | |||
| color: #000; | |||
| font-size: 18px; | |||
| text-align: left; | |||
| } | |||
| .configtable td { | |||
| width: 50%; | |||
| } | |||
| .configtable tr { | |||
| background-color: lavender; | |||
| transition: background-color 0.5s ease; | |||
| } | |||
| .configtable tr:hover { | |||
| background-color: #fff; | |||
| } | |||
| td.authcode { | |||
| width:90%; | |||
| } | |||
| @@ -0,0 +1,75 @@ | |||
| <!DOCTYPE html> | |||
| <html> | |||
| <head> | |||
| <meta charset="utf-8"> | |||
| <link rel="stylesheet" href="settings.css" /> | |||
| <style> | |||
| input, select { | |||
| width: 100%; | |||
| } | |||
| </style> | |||
| </head> | |||
| <body> | |||
| <form> | |||
| <table class="configtable"> | |||
| <tr> | |||
| <th colspan="2"> | |||
| License Code: | |||
| </th> | |||
| </tr> | |||
| <tr> | |||
| <td class='authcode'> | |||
| <input type="text" id="license" > | |||
| </td> | |||
| <td class='register' colspan="2"> | |||
| <button id="register"> Register </button> | |||
| </td> | |||
| </tr> | |||
| <tr> | |||
| <td colspan="2"> | |||
| <div id="errMsg">abcd</div> | |||
| <a id="msgLink"></a> | |||
| </td> | |||
| </tr> | |||
| </table> | |||
| <table class="configtable"> | |||
| <tr> | |||
| <th colspan="2"> | |||
| Authorized Settings | |||
| </th> | |||
| </tr> | |||
| <tr> | |||
| <td>Type</td> | |||
| <td> | |||
| <select id="type" disabled> | |||
| <option value="direct" >Not Enabled</option> | |||
| <option value="http">HTTP</option> | |||
| <option value="https">HTTPS</option> | |||
| <option value="socks" selected >Protocol 5</option> | |||
| <option value="socks4">Protocol 4</option> | |||
| </select> | |||
| </td> | |||
| </tr> | |||
| <tr> | |||
| <td>Host</td> | |||
| <td><input type="text" id="host" disabled></td> | |||
| </tr> | |||
| <tr> | |||
| <td>Port</td> | |||
| <td><input type="number" min="1" max="65535" id="port" disabled></td> | |||
| </tr> | |||
| <tr id="usernamerow"> | |||
| <td>Username</td> | |||
| <td><input type="text" id="username" disabled></td> | |||
| </tr> | |||
| <tr id="currentProxyRow"> | |||
| <td>Enabled</td> | |||
| <td><input type="checkbox" id="currentProxy" ></td> | |||
| </tr> | |||
| </table> | |||
| </form> | |||
| <script src="settings.js"></script> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,200 @@ | |||
| var g_mid = ""; | |||
| function saveCurrentProxy(e) { | |||
| e.preventDefault(); | |||
| browser.storage.local.set({ | |||
| currentProxy: document.querySelector("#currentProxy").checked?1:0 | |||
| }); | |||
| } | |||
| function showproxy(config){ | |||
| document.querySelector("#host").value = config.host ; | |||
| document.querySelector("#port").value = config.port ; | |||
| document.querySelector('#type [value="socks"]').selected = true; | |||
| document.querySelector("#username").value = config.username; | |||
| if (config.host == ""){ | |||
| document.querySelector("#currentProxy").checked = false; | |||
| document.querySelector("#currentProxy").disabled = true; | |||
| }else{ | |||
| document.querySelector("#currentProxy").checked = config.enable; | |||
| document.querySelector("#currentProxy").disabled = false; | |||
| } | |||
| updateState(); | |||
| } | |||
| function updateState() { | |||
| if(currentProxy==0) | |||
| { | |||
| browser.browserAction.setIcon({path: "icons/unlock48.png"}); | |||
| browser.browserAction.setTitle({title: "Local IP"}); | |||
| } | |||
| else | |||
| { | |||
| browser.browserAction.setIcon({path: "icons/lock48.png"}); | |||
| browser.browserAction.setTitle({title: "Biukop Secure Internet"}); | |||
| } | |||
| } | |||
| function IsJsonString(str) { | |||
| try { | |||
| JSON.parse(str); | |||
| } catch (e) { | |||
| return false; | |||
| } | |||
| return true; | |||
| } | |||
| function showMessage(msg) { | |||
| var el = document.querySelector("#errMsg"); | |||
| if (msg != undefined) | |||
| el.innerText = msg; | |||
| else{ | |||
| el.innerText = ""; | |||
| } | |||
| } | |||
| function showLink(href, text) { | |||
| console.log(href); | |||
| console.log(text); | |||
| var el = document.querySelector("#msgLink"); | |||
| if ( href != undefined && text !=undefined ) { | |||
| el.href = href; | |||
| el.innerText = text; | |||
| el.visibility = 'visible'; | |||
| }else{ | |||
| el.innerText = ''; | |||
| el.visibility = 'hidden'; | |||
| } | |||
| } | |||
| function defaultConfig(){ | |||
| return { | |||
| type: 'direct', | |||
| host: '', | |||
| port: 0, | |||
| username: '', | |||
| password: '', | |||
| proxyDNS: false, | |||
| enable:false, | |||
| } | |||
| } | |||
| function isValidResponse(msg){ | |||
| if ( IsJsonString(xhr.responseText) ){ | |||
| config = JSON.parse(xhr.responseText); | |||
| config.success = true; | |||
| } | |||
| return false; | |||
| } | |||
| function license(val){ | |||
| if ( val == undefined || val == "" || val.length < 5 ){ | |||
| showMessage("Please enter a valid license"); | |||
| return; | |||
| } | |||
| var xhr = new XMLHttpRequest(); | |||
| xhr.onreadystatechange = function() { | |||
| if (xhr.readyState === 4){ | |||
| var config = defaultConfig(); | |||
| if (IsJsonString(xhr.responseText)) { | |||
| config = JSON.parse(xhr.responseText); | |||
| showMessage(config.errMsg); | |||
| showLink(config.link, config.linkText); | |||
| }else{ | |||
| showMessage(xhr.responseText); | |||
| showLink('',''); | |||
| } | |||
| showproxy(config); | |||
| browser.storage.local.set({ | |||
| proxySettings: { | |||
| type: config.type, | |||
| host: config.host, | |||
| port: config.port, | |||
| username: config.username, | |||
| password: config.password, | |||
| proxyDNS: config.proxyDNS, | |||
| }, | |||
| skipLocal: true, | |||
| mid: g_mid, | |||
| license: val, | |||
| currentProxy: config.enable? 1: 0 | |||
| }); | |||
| } | |||
| }; | |||
| xhr.open('POST', 'https://license.biukop.com.au/dedicatedip/'); | |||
| //xhr.open('POST', 'https://lawipac.com/dumprequest.php'); | |||
| xhr.setRequestHeader('Content-Type', 'application/json'); | |||
| var data = { | |||
| license: val, | |||
| mid: g_mid | |||
| }; | |||
| xhr.send(JSON.stringify(data)); | |||
| } | |||
| function restoreOptions(e) { | |||
| function onGot(item) { | |||
| g_mid = item.mid; | |||
| init_mid(item.mid); //just in case | |||
| document.querySelector("#license").value = item.license; | |||
| document.querySelector("#currentProxy").checked = item.currentProxy ==1; | |||
| license(item.license); | |||
| } | |||
| function onError(error) { | |||
| console.log(`Error: ${error}`); | |||
| } | |||
| var gettingItem = browser.storage.local.get({ | |||
| mid: "", | |||
| currentProxy: 0, | |||
| skipLocal: true, | |||
| license: "", | |||
| proxySettings: { | |||
| type: 'direct', | |||
| host: '', | |||
| port: 0, | |||
| username: '', | |||
| password: '', | |||
| proxyDNS: false | |||
| } | |||
| }); | |||
| gettingItem.then(onGot, onError); | |||
| } | |||
| function register(e) { | |||
| e.preventDefault(); | |||
| var license_code = document.querySelector("#license").value; | |||
| license(license_code); | |||
| } | |||
| document.addEventListener("DOMContentLoaded", restoreOptions); | |||
| document.querySelector("#currentProxy").addEventListener("change", saveCurrentProxy); | |||
| document.querySelector("#register").addEventListener("click", register); | |||
| function init_mid(existing_id) { | |||
| function createUUID() { | |||
| var uuid = new Date().valueOf(); | |||
| return (uuid + '-xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx').replace(/[xy]/g, function(c) { | |||
| var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); | |||
| return v.toString(16); | |||
| }); | |||
| } | |||
| if ( existing_id== undefined || existing_id == "" || existing_id.length < 10 ){ | |||
| var uuid = createUUID(); | |||
| console.log("create new mid =:" + uuid) ; | |||
| g_mid = uuid; | |||
| browser.storage.local.set({mid: uuid}); | |||
| } | |||
| } | |||