├── .eslintrc.json ├── .githooks └── pre-commit ├── .github └── workflows │ └── main.yml ├── .gitignore ├── .gitlab-ci.yml ├── .gitlab └── merge_request_templates │ └── default.md ├── .prettierrc ├── CHANGELOG.md ├── README.md ├── bin ├── fenix.exe ├── prey ├── prey-user ├── prey.cmd ├── trinity ├── trinity.exe └── updater.exe ├── docs ├── clear_files_prey_temp.js.html ├── clear_folders.js.html ├── fonts │ ├── OpenSans-Bold-webfont.eot │ ├── OpenSans-Bold-webfont.svg │ ├── OpenSans-Bold-webfont.woff │ ├── OpenSans-BoldItalic-webfont.eot │ ├── OpenSans-BoldItalic-webfont.svg │ ├── OpenSans-BoldItalic-webfont.woff │ ├── OpenSans-Italic-webfont.eot │ ├── OpenSans-Italic-webfont.svg │ ├── OpenSans-Italic-webfont.woff │ ├── OpenSans-Light-webfont.eot │ ├── OpenSans-Light-webfont.svg │ ├── OpenSans-Light-webfont.woff │ ├── OpenSans-LightItalic-webfont.eot │ ├── OpenSans-LightItalic-webfont.svg │ ├── OpenSans-LightItalic-webfont.woff │ ├── OpenSans-Regular-webfont.eot │ ├── OpenSans-Regular-webfont.svg │ └── OpenSans-Regular-webfont.woff ├── global.html ├── index.html ├── scripts │ ├── linenumber.js │ └── prettify │ │ ├── Apache-License-2.0.txt │ │ ├── lang-css.js │ │ └── prettify.js └── styles │ ├── jsdoc-default.css │ ├── prettify-jsdoc.css │ └── prettify-tomorrow.css ├── lib ├── agent │ ├── ack.js │ ├── actions.js │ ├── actions │ │ ├── alarm │ │ │ ├── bin │ │ │ │ ├── mpg123.exe │ │ │ │ ├── unmuter.exe │ │ │ │ └── voladjust.exe │ │ │ ├── index.js │ │ │ ├── lib │ │ │ │ ├── alarm.mp3 │ │ │ │ ├── modem.mp3 │ │ │ │ ├── ring.mp3 │ │ │ │ └── siren.mp3 │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ └── windows.js │ │ ├── alert │ │ │ ├── darwin │ │ │ │ └── flash.py │ │ │ ├── index.js │ │ │ ├── linux │ │ │ │ ├── flash.py │ │ │ │ └── flash3.py │ │ │ └── win32 │ │ │ │ └── flash.exe │ │ ├── diskencryption │ │ │ └── index.js │ │ ├── factoryreset │ │ │ ├── bin │ │ │ │ └── factory-reset.ps1 │ │ │ ├── factory-reset-option.js │ │ │ └── index.js │ │ ├── fileretrieval │ │ │ ├── index.js │ │ │ └── upload.js │ │ ├── fullwipe │ │ │ ├── bin │ │ │ │ └── dskwipe.exe │ │ │ └── index.js │ │ ├── lock │ │ │ ├── index.js │ │ │ ├── lib │ │ │ │ └── bg-lock.png │ │ │ ├── linux │ │ │ │ ├── prey-lock │ │ │ │ └── prey-lock3 │ │ │ ├── mac │ │ │ │ └── prey-lock │ │ │ └── windows │ │ │ │ ├── new-prey-lock.exe │ │ │ │ ├── prey-lock.exe │ │ │ │ └── tb-enable.exe │ │ ├── logretrieval │ │ │ └── index.js │ │ ├── osquery │ │ │ └── index.js │ │ ├── request_permission │ │ │ └── index.js │ │ ├── sync_settings │ │ │ └── index.js │ │ ├── triggers │ │ │ └── index.js │ │ └── wipe │ │ │ ├── index.js │ │ │ ├── linux │ │ │ ├── index.js │ │ │ └── wipe-linux │ │ │ ├── mac │ │ │ ├── index.js │ │ │ └── wipe-osx │ │ │ ├── runner.js │ │ │ ├── windows │ │ │ ├── index.js │ │ │ └── wipe-win.exe │ │ │ └── wipe.js │ ├── cli.js │ ├── commands.js │ ├── common.js │ ├── control-panel │ │ ├── api │ │ │ ├── accounts.js │ │ │ ├── devices.js │ │ │ ├── errors.js │ │ │ ├── index.js │ │ │ ├── keys.js │ │ │ ├── logger.js │ │ │ ├── push.js │ │ │ └── request.js │ │ ├── bus.js │ │ ├── index.js │ │ ├── long-polling │ │ │ ├── index.js │ │ │ └── server.js │ │ ├── prompt.js │ │ ├── secure.js │ │ ├── sender.js │ │ ├── setup.js │ │ └── websockets │ │ │ ├── index.js │ │ │ └── server.js │ ├── errors │ │ ├── factoryreset.js │ │ ├── fullwipe.js │ │ └── index.js │ ├── helpers.js │ ├── hooks.js │ ├── index.js │ ├── permissions │ │ ├── darwin.js │ │ ├── index.js │ │ ├── linux.js │ │ └── windows.js │ ├── providers.js │ ├── providers │ │ ├── bandwidth │ │ │ ├── index.js │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ └── windows.js │ │ ├── connections │ │ │ ├── index.js │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ └── windows.js │ │ ├── encryption-keys │ │ │ └── index.js │ │ ├── encryption-status │ │ │ └── index.js │ │ ├── files │ │ │ ├── attr.js │ │ │ ├── finder.js │ │ │ ├── index.js │ │ │ └── tree.js │ │ ├── geo │ │ │ ├── darwin │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── linux │ │ │ │ └── index.js │ │ │ ├── strategies.js │ │ │ └── win32 │ │ │ │ ├── index.js │ │ │ │ └── windows.devices.geolocation │ │ │ │ ├── .npmignore │ │ │ │ ├── README.md │ │ │ │ ├── bin │ │ │ │ ├── ia32 │ │ │ │ │ └── NodeRT_Windows_Devices_Geolocation.node │ │ │ │ └── x64 │ │ │ │ │ └── NodeRT_Windows_Devices_Geolocation.node │ │ │ │ ├── lib │ │ │ │ ├── NodeRT_Windows_Devices_Geolocation.d.js │ │ │ │ ├── NodeRT_Windows_Devices_Geolocation.d.ts │ │ │ │ └── main.js │ │ │ │ └── package.json │ │ ├── hardware │ │ │ ├── index.js │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ ├── ramcheck.vbs │ │ │ └── windows.js │ │ ├── indicators │ │ │ ├── index.js │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ └── windows.js │ │ ├── lan │ │ │ ├── index.js │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ └── windows.js │ │ ├── network │ │ │ ├── index.js │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ └── windows.js │ │ ├── processes │ │ │ ├── index.js │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ └── windows.js │ │ ├── screenshot │ │ │ ├── index.js │ │ │ ├── linux │ │ │ │ └── index.js │ │ │ ├── mac │ │ │ │ └── index.js │ │ │ └── windows │ │ │ │ ├── index.js │ │ │ │ └── preyshot.exe │ │ ├── system │ │ │ └── index.js │ │ ├── users │ │ │ ├── index.js │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ └── windows.js │ │ ├── webcam-extra │ │ │ └── index.js │ │ └── webcam │ │ │ ├── index.js │ │ │ ├── linux │ │ │ └── index.js │ │ │ ├── mac │ │ │ ├── README │ │ │ ├── imagesnap │ │ │ └── index.js │ │ │ └── windows │ │ │ ├── DirectShowLib-2005.dll │ │ │ ├── README.md │ │ │ ├── index.js │ │ │ ├── prey-webcam.exe │ │ │ └── snapshot.exe │ ├── reports.js │ ├── reports │ │ ├── actions.js │ │ ├── load.js │ │ ├── specs.js │ │ ├── status.js │ │ └── stolen.js │ ├── socket │ │ ├── index.js │ │ ├── listeners.js │ │ └── messages.js │ ├── startup.js │ ├── token.js │ ├── transports │ │ ├── http │ │ │ └── index.js │ │ └── smtp │ │ │ └── index.js │ ├── triggers.js │ ├── triggers │ │ ├── README.md │ │ ├── auto-connect │ │ │ ├── bin │ │ │ │ ├── ManagedWifi.dll │ │ │ │ └── wifion.exe │ │ │ ├── index.js │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ ├── reconnect.js │ │ │ └── windows.js │ │ ├── connection │ │ │ └── index.js │ │ ├── hostname │ │ │ └── index.js │ │ ├── location │ │ │ ├── index.js │ │ │ ├── lib │ │ │ │ └── latlng.js │ │ │ └── test_latlng.js │ │ ├── network │ │ │ └── index.js │ │ ├── power │ │ │ └── index.js │ │ └── status │ │ │ └── index.js │ ├── updater.js │ └── utils │ │ ├── Prey.app │ │ └── Contents │ │ │ ├── CodeResources │ │ │ ├── Info.plist │ │ │ ├── MacOS │ │ │ └── Prey │ │ │ └── _CodeSignature │ │ │ └── CodeResources │ │ ├── custom-dirs.js │ │ ├── logo.js │ │ ├── openwebbrowser.sh │ │ ├── pidfile.js │ │ ├── prey-actions.app │ │ └── Contents │ │ │ ├── Info.plist │ │ │ ├── MacOS │ │ │ └── prey-actions │ │ │ ├── PkgInfo │ │ │ ├── Resources │ │ │ ├── Assets.car │ │ │ ├── Base.lproj │ │ │ │ └── MainMenu.nib │ │ │ ├── bg-lock.png │ │ │ ├── en.lproj │ │ │ │ └── Localizable.strings │ │ │ └── es.lproj │ │ │ │ ├── Localizable.strings │ │ │ │ └── MainMenu.nib │ │ │ └── _CodeSignature │ │ │ └── CodeResources │ │ ├── prey-configuration │ │ ├── preyconf.js │ │ ├── util-preyconf.js │ │ └── validationpreyconf.js │ │ ├── storage.js │ │ ├── storage │ │ ├── database.js │ │ ├── restore.js │ │ └── utilstorage.js │ │ ├── utilinformation.js │ │ └── utilsprey.js ├── common.js ├── conf │ ├── account.js │ ├── action.js │ ├── cli.js │ ├── gui │ │ ├── index.js │ │ ├── linux │ │ │ ├── prey-config.glade │ │ │ ├── prey-config.py │ │ │ └── prey-config3.py │ │ ├── mac │ │ │ └── PreyConfig.app │ │ │ │ └── Contents │ │ │ │ ├── Info.plist │ │ │ │ ├── MacOS │ │ │ │ ├── PreyConfig │ │ │ │ └── prey-config.py │ │ │ │ ├── Resources │ │ │ │ └── prey.icns │ │ │ │ └── _CodeSignature │ │ │ │ ├── CodeDirectory │ │ │ │ ├── CodeRequirements │ │ │ │ ├── CodeResources │ │ │ │ └── CodeSignature │ │ ├── pixmaps │ │ │ ├── agent.bmp │ │ │ ├── conf │ │ │ │ ├── check.png │ │ │ │ ├── connect.bmp │ │ │ │ ├── controlpanel.bmp │ │ │ │ ├── controlpanel.png │ │ │ │ ├── delay.bmp │ │ │ │ ├── delay.png │ │ │ │ ├── email.bmp │ │ │ │ ├── email.png │ │ │ │ ├── newuser.bmp │ │ │ │ ├── newuser.png │ │ │ │ ├── olduser.bmp │ │ │ │ ├── olduser.png │ │ │ │ ├── secure.bmp │ │ │ │ ├── secure.png │ │ │ │ ├── settings.bmp │ │ │ │ ├── system.bmp │ │ │ │ ├── system.png │ │ │ │ ├── user.bmp │ │ │ │ ├── user.png │ │ │ │ ├── wifi.bmp │ │ │ │ └── wifi.png │ │ │ ├── prey-agent-48.png │ │ │ ├── prey-text-shadow.png │ │ │ ├── prey-text.png │ │ │ ├── prey.ico │ │ │ └── prey.png │ │ └── windows │ │ │ └── prey-config.exe │ ├── install.js │ ├── log.js │ ├── long-polling.js │ ├── panel │ │ └── index.js │ ├── settings.js │ ├── shared.js │ ├── shared │ │ ├── keys.js │ │ ├── log.js │ │ ├── messages.js │ │ ├── panel.js │ │ └── version_manager.js │ ├── tasks │ │ ├── clear_files_prey_temp.js │ │ ├── clear_folders.js │ │ ├── daemon.js │ │ ├── index.js │ │ ├── os │ │ │ ├── linux.js │ │ │ ├── mac.js │ │ │ └── windows.js │ │ ├── prey_owl.js │ │ ├── prey_user.js │ │ └── utils │ │ │ └── create_user.sh │ ├── utils │ │ ├── cp.js │ │ ├── operetta.js │ │ ├── run.js │ │ └── run_synced.js │ └── versions.js ├── constants │ ├── actions.js │ ├── index.js │ ├── os.js │ └── storage.js ├── exceptions.js ├── package.js ├── system │ ├── index.js │ ├── linux │ │ ├── index.js │ │ └── paths.js │ ├── mac │ │ ├── airport.js │ │ ├── index.js │ │ └── paths.js │ ├── paths.js │ ├── utils │ │ └── runner.js │ └── windows │ │ ├── bin │ │ ├── autowc.exe │ │ ├── autowcxp.exe │ │ ├── safexec.exe │ │ ├── updater.exe │ │ ├── wapi.dll │ │ ├── wlanscan.exe │ │ ├── wpxsvc.exe │ │ ├── wpxsvc_old.exe │ │ └── wzcapis.dll │ │ ├── index.js │ │ ├── paths.js │ │ └── registry.js └── utils │ ├── configfile.js │ ├── configutil.js │ ├── fetch-env-var.js │ └── permissionfile.js ├── license.txt ├── package-lock.json ├── package.json ├── prey.conf.default ├── test └── lib │ ├── agent │ ├── ack.test.js │ ├── actions │ │ └── logretrieval │ │ │ └── logretrieval.test.js │ ├── control-panel │ │ ├── api │ │ │ ├── accounts.test.js │ │ │ ├── devices.test.js │ │ │ ├── errors.test.js │ │ │ ├── index.test.js │ │ │ ├── keys.test.js │ │ │ ├── logger.test.js │ │ │ ├── push.test.js │ │ │ └── request.test.js │ │ └── websockets │ │ │ └── server.test.js │ ├── helpers.test.js │ ├── providers │ │ └── hardware │ │ │ └── hardware.test.js │ ├── socket │ │ ├── listeners.test.js │ │ └── socket.test.js │ ├── triggers │ │ └── location │ │ │ └── locationindex.test.js │ └── utils │ │ ├── pdifile.test.js │ │ ├── prey-configuration │ │ └── preyconf.test.js │ │ ├── storage │ │ ├── database.test.js │ │ ├── restore.test.js │ │ └── utilstorage.test.js │ │ └── utilsprey.test.js │ ├── conf │ └── account.test.js │ └── utils │ └── configutil.test.js └── tools ├── build.sh ├── node_bins.sh └── sqlite3 ├── linux └── napi-v6-linux-x64 │ └── node_sqlite3.node ├── mac ├── napi-v6-darwin-unknown-arm64 │ └── node_sqlite3.node └── napi-v6-darwin-unknown-x64 │ └── node_sqlite3.node └── windows ├── napi-v6-win32-unknown-ia32 └── node_sqlite3.node └── napi-v6-win32-unknown-x64 └── node_sqlite3.node /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es2021": true 6 | }, 7 | "extends": "airbnb-base", 8 | "overrides": [ 9 | ], 10 | "plugins": ["node"], 11 | "parserOptions": { 12 | "ecmaVersion": "latest" 13 | }, 14 | "rules": { 15 | "linebreak-style": "off", 16 | "node/no-deprecated-api": "error" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.githooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | @@ -0,0 +1,22 @@ 3 | #!/usr/bin/env bash 4 | LC_ALL=C 5 | 6 | local_branch="$(git rev-parse --abbrev-ref HEAD)" 7 | 8 | valid_branch_regex="^(feat|fix|docs|style|refactor|perf|test|chore)\/[a-z0-9._-]+$" 9 | 10 | message1="There is something wrong with your branch name." 11 | message2="Branch names must start with one of these words: $valid_branch_regex" 12 | message3="You should rename your branch using: git branch -m BRANCH-NAME" 13 | 14 | if [[ ! $local_branch =~ $valid_branch_regex ]] 15 | then 16 | echo "$message1" 17 | echo "$message2" 18 | echo "$message3" 19 | exit 1 20 | fi 21 | 22 | exit 0 -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/stale-branches.yml 2 | 3 | name: Stale Branches 4 | 5 | on: 6 | schedule: 7 | - cron: '00 10 9 8 *' 8 | 9 | permissions: 10 | issues: write 11 | contents: write 12 | 13 | jobs: 14 | stale_branches: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Stale Branches 18 | uses: crs-k/stale-branches@v3.0.0 19 | with: 20 | repo-token: '${{ secrets.GITHUB_TOKEN }}' 21 | days-before-stale: 120 22 | days-before-delete: 180 23 | comment-updates: false 24 | max-issues: 20 25 | tag-committer: false 26 | stale-branch-label: 'stale branch 🗑️' 27 | compare-branches: 'info' 28 | branches-filter-regex: '^((?!dependabot))' 29 | 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | builds 3 | node 4 | node_modules 5 | *~ 6 | install 7 | bin/node.* 8 | npm-debug.log 9 | sandbox 10 | .DS_Store 11 | .scannerwork 12 | coverage 13 | .env 14 | **oq-installer.log 15 | sonar-project.properties 16 | **.sonar 17 | .nyc_output/** 18 | **.vscode 19 | **files.json 20 | .aider* 21 | -------------------------------------------------------------------------------- /.gitlab/merge_request_templates/default.md: -------------------------------------------------------------------------------- 1 | ## Change description 2 | 3 | > Description here 4 | 5 | ## Type of change 6 | - [ ] Bug fix (fixes an issue) 7 | - [ ] New feature (adds functionality) 8 | 9 | ## Related issues 10 | 11 | > Fix [#1]() 12 | 13 | ## Checklists 14 | 15 | ### Development 16 | 17 | - [ ] Lint rules pass locally 18 | - [ ] Application changes have been tested thoroughly 19 | - [ ] Automated tests covering modified code pass 20 | 21 | ### Security 22 | 23 | - [ ] Security impact of change has been considered 24 | - [ ] Code follows company security practices and guidelines 25 | 26 | ### Code review 27 | 28 | - [ ] Pull request has a descriptive title and context useful to a reviewer. Screenshots or screencasts are attached as necessary 29 | - [ ] "Ready for review" label attached and reviewers assigned 30 | - [ ] Changes have been reviewed by at least one other contributor 31 | - [ ] Pull request linked to task tracker where applicable 32 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": false, 5 | "singleQuote": true 6 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Code Climate](https://codeclimate.com/github/prey/prey-node-client/badges/gpa.svg)](https://codeclimate.com/github/prey/prey-node-client) 2 | 3 | [![Build Status](https://travis-ci.org/prey/prey-node-client.svg?branch=travis-ci)](https://travis-ci.org/prey/prey-node-client) 4 | 5 | # Prey Node.js client 6 | 7 | Here you will find all the source code for the current and in development releases of the Prey client for Mac, Linux, and Windows. 8 | 9 | Prey is the most complete anti-theft application! It lets you track and locate your lost or stolen laptop. Locate and recover your device with geolocation and many more features. 10 | 11 | > Prey is a freemium web service for tracking and monitoring laptops, smartphones and other electronic devices, based on an open-source software agent that connects to a host computer, also referred to as the control panel. The host can signal the agent, prompting it to reply with information about its current location, and can trigger various other actions. 12 | 13 | ## Installation 14 | 15 | Download the [appropiate installer](https://github.com/prey/prey-node-client/releases) from the releases section. 16 | 17 | ## Authors 18 | 19 | By Tomás Pollak, with the help of the following contributors: 20 | 21 | - Carlos Yaconi 22 | - Javier Acuña 23 | - Mauricio Schneider 24 | - Rodrigo Aliste 25 | 26 | ## Credits 27 | 28 | - To Robert Harder for the ImageSnap utility for OS X. 29 | - To Michael Hipp for mpg123. 30 | - And to all the Node.js developers for their awesome modules (async, connect, rimraf, etc). 31 | 32 | ## Legal 33 | 34 | Copyright © 2011-2014 Fork, Ltd. 35 | Copyright © 2014-2019 Prey, Inc. 36 | Released under the GPLv3 license. 37 | For full details see the `license.txt` file included in this distribution. 38 | -------------------------------------------------------------------------------- /bin/fenix.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/bin/fenix.exe -------------------------------------------------------------------------------- /bin/prey: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PATH="$PATH:/usr/local/bin" 4 | dir="$(dirname $0)" 5 | [ -x "$dir/node" ] && node="$dir/node" || node="$(command -v node || command -v nodejs)" 6 | 7 | # if current file is a symlink (e.g. installed via npm) we'll append 8 | # the relative path to where the package is actually installed. 9 | if [ -n "$(readlink $0 2> /dev/null)" ]; then 10 | rel="$(dirname $(readlink $0))" 11 | dir="$dir/$rel" 12 | fi 13 | 14 | script="lib/agent/cli.js" 15 | if [ "$1" = "config" ]; then 16 | script="lib/conf/cli.js" 17 | elif [ "$1" = "test" ]; then 18 | script="node_modules/.bin/_mocha" 19 | fi 20 | 21 | exec "$node" "$dir/../${script}" "$@" 22 | -------------------------------------------------------------------------------- /bin/prey-user: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/bin/prey-user -------------------------------------------------------------------------------- /bin/prey.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set dir=%~dp0 4 | 5 | if "%1" == "config" ( 6 | set script=\lib\conf\cli.js 7 | ) else if "%1" == "test" ( 8 | set script=\node_modules\mocha\bin\mocha 9 | ) else ( 10 | set script=\lib\agent\cli.js 11 | ) 12 | 13 | @IF EXIST "%dir%\node.exe" ( 14 | "%dir%\node.exe" "%dir%\..\%script%" %* 15 | ) ELSE ( 16 | node "%dir%\..\%script%" %* 17 | ) 18 | -------------------------------------------------------------------------------- /bin/trinity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/bin/trinity -------------------------------------------------------------------------------- /bin/trinity.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/bin/trinity.exe -------------------------------------------------------------------------------- /bin/updater.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/bin/updater.exe -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-Bold-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-Bold-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-BoldItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-BoldItalic-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-BoldItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-BoldItalic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Italic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-Italic-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Italic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-Italic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-Light-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-LightItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-LightItalic-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-LightItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-LightItalic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-Regular-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/docs/fonts/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSDoc: Home 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |

Home

21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |

30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
51 | 52 | 55 | 56 |
57 | 58 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /docs/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | /*global document */ 2 | (() => { 3 | const source = document.getElementsByClassName('prettyprint source linenums'); 4 | let i = 0; 5 | let lineNumber = 0; 6 | let lineId; 7 | let lines; 8 | let totalLines; 9 | let anchorHash; 10 | 11 | if (source && source[0]) { 12 | anchorHash = document.location.hash.substring(1); 13 | lines = source[0].getElementsByTagName('li'); 14 | totalLines = lines.length; 15 | 16 | for (; i < totalLines; i++) { 17 | lineNumber++; 18 | lineId = `line${lineNumber}`; 19 | lines[i].id = lineId; 20 | if (lineId === anchorHash) { 21 | lines[i].className += ' selected'; 22 | } 23 | } 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /docs/scripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /docs/styles/prettify-jsdoc.css: -------------------------------------------------------------------------------- 1 | /* JSDoc prettify.js theme */ 2 | 3 | /* plain text */ 4 | .pln { 5 | color: #000000; 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | /* string content */ 11 | .str { 12 | color: #006400; 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | 17 | /* a keyword */ 18 | .kwd { 19 | color: #000000; 20 | font-weight: bold; 21 | font-style: normal; 22 | } 23 | 24 | /* a comment */ 25 | .com { 26 | font-weight: normal; 27 | font-style: italic; 28 | } 29 | 30 | /* a type name */ 31 | .typ { 32 | color: #000000; 33 | font-weight: normal; 34 | font-style: normal; 35 | } 36 | 37 | /* a literal value */ 38 | .lit { 39 | color: #006400; 40 | font-weight: normal; 41 | font-style: normal; 42 | } 43 | 44 | /* punctuation */ 45 | .pun { 46 | color: #000000; 47 | font-weight: bold; 48 | font-style: normal; 49 | } 50 | 51 | /* lisp open bracket */ 52 | .opn { 53 | color: #000000; 54 | font-weight: bold; 55 | font-style: normal; 56 | } 57 | 58 | /* lisp close bracket */ 59 | .clo { 60 | color: #000000; 61 | font-weight: bold; 62 | font-style: normal; 63 | } 64 | 65 | /* a markup tag name */ 66 | .tag { 67 | color: #006400; 68 | font-weight: normal; 69 | font-style: normal; 70 | } 71 | 72 | /* a markup attribute name */ 73 | .atn { 74 | color: #006400; 75 | font-weight: normal; 76 | font-style: normal; 77 | } 78 | 79 | /* a markup attribute value */ 80 | .atv { 81 | color: #006400; 82 | font-weight: normal; 83 | font-style: normal; 84 | } 85 | 86 | /* a declaration */ 87 | .dec { 88 | color: #000000; 89 | font-weight: bold; 90 | font-style: normal; 91 | } 92 | 93 | /* a variable name */ 94 | .var { 95 | color: #000000; 96 | font-weight: normal; 97 | font-style: normal; 98 | } 99 | 100 | /* a function name */ 101 | .fun { 102 | color: #000000; 103 | font-weight: bold; 104 | font-style: normal; 105 | } 106 | 107 | /* Specify class=linenums on a pre to get line numbering */ 108 | ol.linenums { 109 | margin-top: 0; 110 | margin-bottom: 0; 111 | } 112 | -------------------------------------------------------------------------------- /docs/styles/prettify-tomorrow.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* Pretty printing styles. Used with prettify.js. */ 4 | /* SPAN elements with the classes below are added by prettyprint. */ 5 | /* plain text */ 6 | .pln { 7 | color: #4d4d4c; } 8 | 9 | @media screen { 10 | /* string content */ 11 | .str { 12 | color: #718c00; } 13 | 14 | /* a keyword */ 15 | .kwd { 16 | color: #8959a8; } 17 | 18 | /* a comment */ 19 | .com { 20 | color: #8e908c; } 21 | 22 | /* a type name */ 23 | .typ { 24 | color: #4271ae; } 25 | 26 | /* a literal value */ 27 | .lit { 28 | color: #f5871f; } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #4d4d4c; } 33 | 34 | /* lisp open bracket */ 35 | .opn { 36 | color: #4d4d4c; } 37 | 38 | /* lisp close bracket */ 39 | .clo { 40 | color: #4d4d4c; } 41 | 42 | /* a markup tag name */ 43 | .tag { 44 | color: #c82829; } 45 | 46 | /* a markup attribute name */ 47 | .atn { 48 | color: #f5871f; } 49 | 50 | /* a markup attribute value */ 51 | .atv { 52 | color: #3e999f; } 53 | 54 | /* a declaration */ 55 | .dec { 56 | color: #f5871f; } 57 | 58 | /* a variable name */ 59 | .var { 60 | color: #c82829; } 61 | 62 | /* a function name */ 63 | .fun { 64 | color: #4271ae; } } 65 | /* Use higher contrast and text-weight for printable form. */ 66 | @media print, projection { 67 | .str { 68 | color: #060; } 69 | 70 | .kwd { 71 | color: #006; 72 | font-weight: bold; } 73 | 74 | .com { 75 | color: #600; 76 | font-style: italic; } 77 | 78 | .typ { 79 | color: #404; 80 | font-weight: bold; } 81 | 82 | .lit { 83 | color: #044; } 84 | 85 | .pun, .opn, .clo { 86 | color: #440; } 87 | 88 | .tag { 89 | color: #006; 90 | font-weight: bold; } 91 | 92 | .atn { 93 | color: #404; } 94 | 95 | .atv { 96 | color: #060; } } 97 | /* Style */ 98 | /* 99 | pre.prettyprint { 100 | background: white; 101 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 102 | font-size: 12px; 103 | line-height: 1.5; 104 | border: 1px solid #ccc; 105 | padding: 10px; } 106 | */ 107 | 108 | /* Specify class=linenums on a pre to get line numbering */ 109 | ol.linenums { 110 | margin-top: 0; 111 | margin-bottom: 0; } 112 | 113 | /* IE indents via margin-left */ 114 | li.L0, 115 | li.L1, 116 | li.L2, 117 | li.L3, 118 | li.L4, 119 | li.L5, 120 | li.L6, 121 | li.L7, 122 | li.L8, 123 | li.L9 { 124 | /* */ } 125 | 126 | /* Alternate shading for lines */ 127 | li.L1, 128 | li.L3, 129 | li.L5, 130 | li.L7, 131 | li.L9 { 132 | /* */ } 133 | -------------------------------------------------------------------------------- /lib/agent/ack.js: -------------------------------------------------------------------------------- 1 | const ackType = 'ack'; 2 | 3 | const existKeyAckInJson = (json) => Object.hasOwn(json, 'ack_id'); 4 | 5 | exports.processAck = (json, cb) => { 6 | if (!existKeyAckInJson(json)) return cb(new Error('there is no key ack_id in the json')); 7 | 8 | const { ack_id: ackId, id = '' } = json; 9 | 10 | return cb(null, { 11 | ack_id: ackId, 12 | type: ackType, 13 | id, 14 | }); 15 | }; 16 | 17 | exports.existKeyAckInJson = existKeyAckInJson; 18 | -------------------------------------------------------------------------------- /lib/agent/actions/alarm/bin/mpg123.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/alarm/bin/mpg123.exe -------------------------------------------------------------------------------- /lib/agent/actions/alarm/bin/unmuter.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/alarm/bin/unmuter.exe -------------------------------------------------------------------------------- /lib/agent/actions/alarm/bin/voladjust.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/alarm/bin/voladjust.exe -------------------------------------------------------------------------------- /lib/agent/actions/alarm/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | ////////////////////////////////////////// 4 | // Prey JS Alarm Module 5 | // (c) 2011 - Fork Ltd. 6 | // by Tomas Pollak - http://forkhq.com 7 | // GPLv3 Licensed 8 | ////////////////////////////////////////// 9 | 10 | var fs = require('fs'), 11 | path = require('path'), 12 | exec = require('child_process').exec, 13 | os_name = process.platform.replace('darwin', 'mac').replace('win32', 'windows'), 14 | commands = require('./' + os_name), 15 | Emitter = require('events').EventEmitter, 16 | common = require('./../../common'), 17 | logger = common.logger.prefix('actions'), 18 | system = common.system; 19 | 20 | var child, 21 | emitter, 22 | raise_interval; 23 | 24 | exports.start = function(id, options, cb) { 25 | var error, 26 | self = this, 27 | returned = 0; 28 | 29 | var options = options || {}, 30 | type = options.file || options.sound || 'alarm', 31 | file = type + '.mp3', 32 | loops = options.loops ? parseInt(options.loops) : 1; 33 | 34 | var done = function(id, err) { 35 | clearInterval(raise_interval); 36 | if (returned++) returned; 37 | if (emitter) emitter.emit('end', id, err); 38 | emitter = null; 39 | } 40 | 41 | var raise_volume = function(cb) { 42 | if (os_name == 'linux'){ 43 | const unmuteRaiseCommands = commands.raise_volume.split('&&'); 44 | if(unmuteRaiseCommands.length < 2) return; 45 | system.run_as_logged_user(unmuteRaiseCommands[0], [], (err) => { 46 | if (err) 47 | logger.info(`ERROR while raising volume: ${err}`); 48 | system.run_as_logged_user(unmuteRaiseCommands[1], [], cb); 49 | }); 50 | return; 51 | } 52 | exec(commands.raise_volume, cb); 53 | } 54 | 55 | var play_queue = function() { 56 | loops--; 57 | 58 | system.spawn_as_logged_user(commands.play, [ file ], function(err, alarm) { 59 | if (err) return done(id, err); 60 | 61 | alarm.on('error', done); 62 | 63 | alarm.once('exit', function(code) { 64 | child = null; 65 | 66 | if (loops === 0) 67 | return done(id); 68 | 69 | play_queue(); 70 | }) 71 | 72 | child = alarm; 73 | }); 74 | }; 75 | 76 | let exists = fs.existsSync(file); 77 | if (!exists) file = path.join(__dirname, 'lib', file); 78 | 79 | emitter = new Emitter(); 80 | cb(null, emitter); 81 | 82 | play_queue(); 83 | 84 | raise_interval = setInterval(function() { 85 | raise_volume(); 86 | }, 1000) 87 | }; 88 | 89 | exports.stop = function() { 90 | if (child && !child.exitCode) { 91 | child.kill(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/agent/actions/alarm/lib/alarm.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/alarm/lib/alarm.mp3 -------------------------------------------------------------------------------- /lib/agent/actions/alarm/lib/modem.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/alarm/lib/modem.mp3 -------------------------------------------------------------------------------- /lib/agent/actions/alarm/lib/ring.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/alarm/lib/ring.mp3 -------------------------------------------------------------------------------- /lib/agent/actions/alarm/lib/siren.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/alarm/lib/siren.mp3 -------------------------------------------------------------------------------- /lib/agent/actions/alarm/linux.js: -------------------------------------------------------------------------------- 1 | exports.play = 'mpg123'; 2 | exports.raise_volume = 'pactl set-sink-mute @DEFAULT_SINK@ 0&&pactl set-sink-volume @DEFAULT_SINK@ 100%'; 3 | -------------------------------------------------------------------------------- /lib/agent/actions/alarm/mac.js: -------------------------------------------------------------------------------- 1 | exports.play = 'afplay'; 2 | exports.raise_volume = 'osascript -e "set Volume 10"'; // unmutes as well -------------------------------------------------------------------------------- /lib/agent/actions/alarm/windows.js: -------------------------------------------------------------------------------- 1 | var join = require('path').join, 2 | unmute = join(__dirname, 'bin', 'unmuter.exe'), 3 | voladjust = join(__dirname, 'bin', 'voladjust.exe'); 4 | 5 | exports.play = join(__dirname, 'bin', 'mpg123.exe'); 6 | exports.raise_volume = unmute + ' & ' + voladjust + ' 100'; 7 | -------------------------------------------------------------------------------- /lib/agent/actions/alert/win32/flash.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/alert/win32/flash.exe -------------------------------------------------------------------------------- /lib/agent/actions/fullwipe/bin/dskwipe.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/fullwipe/bin/dskwipe.exe -------------------------------------------------------------------------------- /lib/agent/actions/lock/lib/bg-lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/lock/lib/bg-lock.png -------------------------------------------------------------------------------- /lib/agent/actions/lock/windows/new-prey-lock.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/lock/windows/new-prey-lock.exe -------------------------------------------------------------------------------- /lib/agent/actions/lock/windows/prey-lock.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/lock/windows/prey-lock.exe -------------------------------------------------------------------------------- /lib/agent/actions/lock/windows/tb-enable.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/lock/windows/tb-enable.exe -------------------------------------------------------------------------------- /lib/agent/actions/sync_settings/index.js: -------------------------------------------------------------------------------- 1 | const { EventEmitter } = require('events'); 2 | const common = require('../../common'); 3 | const api = require('../../control-panel/api'); 4 | 5 | const logger = common.logger.prefix('sync_settings'); 6 | const config = require('../../../utils/configfile'); 7 | const errorsActions = require('../../../constants/actions'); 8 | 9 | let emitter; 10 | 11 | const done = (id, err) => { 12 | if (!emitter) emitter = new EventEmitter(); 13 | emitter.emit('end', id, err); 14 | }; 15 | 16 | const verifyNewDataForKey = (newData, oldData, cb) => { 17 | if (typeof newData !== 'undefined' 18 | && oldData !== newData) cb(); 19 | }; 20 | 21 | const process = (valuesFn, target, locals = false) => { 22 | const values = valuesFn; 23 | Object.keys(values).forEach((key) => { 24 | const newValue = locals ? `control-panel.${key}` : key; 25 | const valueConfigData = config.getData(newValue); 26 | if (values[key] == null) values[key] = false; 27 | verifyNewDataForKey(values[key], valueConfigData, () => { 28 | logger.notice(`Updating value of ${key} to ${values[key]}`); 29 | config.setData(newValue, values[key]); 30 | }); 31 | }); 32 | }; 33 | const updateSettings = (obj) => { 34 | if (obj.global) process(obj.global, config); 35 | if (obj.local) process(obj.local, config, true); 36 | }; 37 | // eslint-disable-next-line consistent-return 38 | exports.start = (id, _opts, cb) => { 39 | cb(); 40 | api.devices.get.status((err, response) => { 41 | if (err) return; 42 | const result = response && response.body; 43 | // eslint-disable-next-line consistent-return, max-len 44 | if (!result || (response && response.statusCode > 300)) return done(id, new Error(errorsActions.INVALID_RESPONSE)); 45 | if (result.settings) { 46 | updateSettings(result.settings); 47 | // eslint-disable-next-line consistent-return 48 | return done(id); 49 | } 50 | done(id, new Error(errorsActions.RESPONSE_NOT_FOUND)); 51 | }); 52 | }; 53 | 54 | exports.stop = () => { 55 | }; 56 | -------------------------------------------------------------------------------- /lib/agent/actions/wipe/linux/index.js: -------------------------------------------------------------------------------- 1 | var exec = require('child_process').exec; 2 | 3 | exports.killTasks = (tasks, cb) =>{ 4 | if (tasks.length == 0) return cb(); 5 | var cmd = ''; 6 | tasks.map((taks) => { cmd = `${cmd} pkill -9 ${taks};`}) 7 | exec(cmd, cb); 8 | } 9 | 10 | exports.getDropboxOldDirs = (home, cb) => { 11 | var paths = []; 12 | exec('find ' + home + ' -maxdepth 2 -name "Dropbox (*"', (err, stdout) => { 13 | if (err || !stdout) return cb(null, paths) 14 | 15 | stdout = stdout.split("\n").slice(0, -1); 16 | 17 | stdout.forEach((entry, index) => { 18 | paths[index] = entry.split('/').pop() 19 | }) 20 | // Delete repeated values 21 | paths = paths.filter((elem, index, self) => { 22 | return index == self.indexOf(elem); 23 | }) 24 | 25 | cb(null, paths); 26 | }) 27 | } 28 | 29 | exports.paths = { 30 | keychains: ['.gnome2/keyrings', '.ssh'], 31 | documents: ['Documents', 'Downloads', 'Desktop', 'Pictures', 'Videos'], 32 | emails: ['.thunderbird', 'Maildir'], 33 | browsers: [ 34 | '.mozilla', 35 | '.config/google-chrome', 36 | '.config/chromium' 37 | ], 38 | clouds: [ 39 | { 'Dropbox' : [ '.dropbox' ] } 40 | ], 41 | cloud_files: [ 42 | 'Dropbox' 43 | ], 44 | directories: [] 45 | } 46 | 47 | exports.tasks = { 48 | clouds: [ 49 | { 'Dropbox' : [ 'Dropbox' ] } 50 | ] 51 | } -------------------------------------------------------------------------------- /lib/agent/actions/wipe/linux/wipe-linux: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/wipe/linux/wipe-linux -------------------------------------------------------------------------------- /lib/agent/actions/wipe/mac/index.js: -------------------------------------------------------------------------------- 1 | var exec = require('child_process').exec; 2 | 3 | exports.killTasks = function(tasks, cb) { 4 | if (tasks.length == 0) return cb(); 5 | tasks.forEach(function(value, index) { 6 | var task = tasks[index] == 'outlook' ? 'Microsoft\ Outlook' : tasks[index]; 7 | tasks[index] = task; 8 | }) 9 | tasks = `"${tasks.join('" "')}"`; 10 | exec('pkill -9 ' + tasks, cb) 11 | } 12 | 13 | exports.getDropboxOldDirs = function(home, cb) { 14 | var paths = []; 15 | exec('find ' + home + ' -maxdepth 2 -name "Dropbox (*"', function(err, stdout) { 16 | if (err || !stdout) return cb(null, paths) 17 | 18 | stdout = stdout.split("\n").slice(0, -1); 19 | stdout.forEach(function(entry, index) { 20 | paths[index] = entry.split('/').pop() 21 | }) 22 | // Delete repeated values 23 | paths = paths.filter(function(elem, index, self) { 24 | return index == self.indexOf(elem); 25 | }) 26 | 27 | cb(null, paths); 28 | }) 29 | } 30 | 31 | exports.paths = { 32 | keychains: ['Library/Keychains', '.ssh'], 33 | documents: ['Documents', 'Downloads', 'Desktop', 'Pictures', 'Videos'], 34 | emails: [ 35 | 'Library/Thunderbird', 36 | 'Library/Mail', 37 | 'Library/Group\ Containers/UBF8T346G9.Office/Outlook' 38 | ], 39 | browsers: [ 40 | 'Library/Safari', 41 | 'Library/Application\ Support/Google/Chrome', 42 | 'Library/Mozilla/Firefox', 43 | 'Library/Application\ Support/Firefox' 44 | ], 45 | clouds: [ 46 | { 'Google Drive': [ 'Library/Application\ Support/Google/Drive', 'Library/Application\ Support/Google/DriveFS'] }, 47 | { 'Dropbox' : [ '.dropbox' ] } 48 | ], 49 | cloud_files: [ 50 | 'Google\ Drive', 51 | 'Dropbox' 52 | ], 53 | directories: [] 54 | } 55 | 56 | exports.tasks = { 57 | clouds: [ 58 | { 'Google Drive': [ 'Google\ Drive', 'Backup\ and\ Sync'] }, 59 | { 'Dropbox' : [ 'Dropbox' ] } 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /lib/agent/actions/wipe/mac/wipe-osx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/wipe/mac/wipe-osx -------------------------------------------------------------------------------- /lib/agent/actions/wipe/runner.js: -------------------------------------------------------------------------------- 1 | const wipe = require('./wipe'); 2 | 3 | const what = process.argv; 4 | // variable to store last error 5 | let last_err; 6 | // pad node binary and script path 7 | what.shift(); 8 | what.shift(); 9 | // Get the cloud config dirs and processes 10 | 11 | const fillOnly = what.pop(); 12 | const keepRoot = what.pop(); 13 | const threePass = what.pop(); 14 | const to_erase = what.pop().split(','); // 'Google Drive', 'Dropbox' 15 | const to_kill = what.pop().split(','); 16 | 17 | what.pop(); 18 | what.pop(); 19 | // process each of the requested items to wipe 20 | 21 | wipe.wipeConfiguration(fillOnly, keepRoot, threePass); 22 | wipe.fetch_dirs(Array.isArray(what) ? what : [what], to_erase, to_kill, null, (err) => { 23 | if (err) last_err = err; 24 | wipe.wipeout((err, out) => { 25 | if (err) last_err = err; 26 | console.log(out); 27 | process.exit(); 28 | }); 29 | }); 30 | process.on('SIGTERM', () => { 31 | process.exit(); 32 | }); 33 | process.on('exit', (code) => { 34 | console.log(`Wipe finished. Last error: ${last_err || 'none.'}`); 35 | }); 36 | -------------------------------------------------------------------------------- /lib/agent/actions/wipe/windows/wipe-win.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/actions/wipe/windows/wipe-win.exe -------------------------------------------------------------------------------- /lib/agent/common.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | 3 | // eslint-disable-next-line import/no-dynamic-require 4 | const common = require(join(__dirname, '..', 'common')); 5 | const { program } = common; 6 | const { paths } = common.system; 7 | const osName = process.platform.replace('win32', 'windows').replace('darwin', 'mac'); 8 | const fs = require('fs'); 9 | const fetchEnvVar = require('../utils/fetch-env-var'); 10 | 11 | common.helpers = require('./helpers'); 12 | // TODO: fix the two commons imports 13 | const logFile = program.logfile || common.helpers.running_on_background() 14 | ? program.logfile || paths.log_file 15 | : null; 16 | 17 | const logLevel = fetchEnvVar('DEBUG') && fetchEnvVar('DEBUG').localeCompare('true') === 0 ? 'debug' : 'info'; 18 | common.logger = require('petit').new({ 19 | level: logLevel, 20 | file: logFile, 21 | rotate: true, 22 | size: 2000000, 23 | limit: 9, 24 | compress: true, 25 | dest: paths.config, 26 | }); 27 | 28 | common.logger_restarts = osName === 'windows' ? require('petit').new({ 29 | level: logLevel, 30 | file: paths.log_restarts, 31 | rotate: false, 32 | size: 200, 33 | limit: 0, 34 | compress: false, 35 | dest: paths.config, 36 | }) : () => {}; 37 | 38 | common.writeFileLoggerRestart = (textToWrite) => { 39 | if (!common.helpers.running_on_background() || osName !== 'windows') return; 40 | fs.appendFile(paths.log_restarts, `${textToWrite}\n`, () => {}); 41 | }; 42 | 43 | common.countLinesLoggerRestarts = () => { 44 | if (!common.helpers.running_on_background() || osName !== 'windows') return; 45 | const fileBuffer = fs.readFileSync(paths.log_restarts); 46 | const toString = fileBuffer.toString(); 47 | const splitLines = toString.split('\n'); 48 | if (splitLines.length > 5) { fs.writeFileSync(paths.log_restarts, splitLines.slice(1, 6).join('\n')); } 49 | }; 50 | 51 | module.exports = common; 52 | -------------------------------------------------------------------------------- /lib/agent/control-panel/api/errors.js: -------------------------------------------------------------------------------- 1 | var list = { 2 | 'MISSING_KEY' : 'Both API and Device keys are needed.', 3 | 'NO_API_KEY' : 'No API key set! Please run `prey config account setup`.', 4 | 'NO_DEVICE_KEY' : 'No Device key set!', 5 | 'API_KEY_SET' : 'API key already set!', 6 | 'DEVICE_KEY_SET' : 'Device key already set!', 7 | 'INVALID_DEVICE_KEY' : 'Device not found in database. Please reconfigure.', 8 | 'INVALID_CREDENTIALS': 'Invalid credentials.', 9 | 'NO_AVAILABLE_SLOTS' : 'Account is valid, but no available slots are left.', 10 | 'SAME_MISSING_STATE' : 'Missing state already set.' 11 | } 12 | 13 | var capitalize = function(key) { 14 | if (!key) return key; 15 | return key[0].toUpperCase() + key.slice(1); 16 | } 17 | 18 | exports.get = function(code) { 19 | if (!list[code]) return new Error(code); 20 | var err = new Error(list[code]); 21 | err.code = code; 22 | return err; 23 | } 24 | 25 | exports.arguments = function(msg) { 26 | var err = new Error(msg || 'Invalid arguments.'); 27 | err.code = 'ARGUMENT_ERROR'; 28 | return err; 29 | } 30 | 31 | exports.unprocessable = function(errors) { 32 | if (typeof errors == 'object') { 33 | var arr = []; 34 | for (var key in errors) { 35 | var err_key; 36 | if (key == 'error') err_key = ''; 37 | else err_key = key == 'password_confirmation' ? 'password: ' : key + ': '; 38 | 39 | if (process.platform == 'win32') 40 | errors[key].forEach(function(e, index) { errors[key][index] = errors[key][index].replace(/í/g, 'i'); }) 41 | 42 | arr.push(capitalize(err_key) + errors[key].join(', ')); 43 | } 44 | msg = '\n' + arr.join('\n'); 45 | } else { 46 | msg = errors; 47 | } 48 | 49 | var err = new Error(msg); 50 | err.code = 'UNPROCESSABLE_DATA'; 51 | return err; 52 | } 53 | 54 | // unknown response code, or body doesn't contain what we expect 55 | exports.unknown = function(resp) { 56 | var err = new Error(resp.body + ' (' + resp.statusCode + ')'); 57 | err.code = 'UNKNOWN_RESPONSE'; 58 | return err; 59 | } 60 | 61 | exports.validation = function(msg) { 62 | var err = new Error(msg); 63 | err.code = 'VALIDATION_ERROR'; 64 | return err; 65 | } 66 | -------------------------------------------------------------------------------- /lib/agent/control-panel/api/index.js: -------------------------------------------------------------------------------- 1 | exports.logger = require('./logger'); 2 | exports.keys = require('./keys'); 3 | exports.accounts = require('./accounts'); 4 | exports.devices = require('./devices'); 5 | exports.push = require('./push'); 6 | 7 | /** 8 | * Allows to pass a custom logger and/or request client to be used 9 | * across all control-panel api. 10 | * 11 | * @param {Object} obj 12 | * @param {Object} [obj.logger] - A custom logger to use. 13 | * @param {Object} [obj.request] - A custom request client to use. 14 | */ 15 | exports.use = (obj) => { 16 | if (obj.logger) exports.logger.use(obj.logger); 17 | require('./request').use(obj); 18 | } 19 | -------------------------------------------------------------------------------- /lib/agent/control-panel/api/keys.js: -------------------------------------------------------------------------------- 1 | const errors = require('./errors'); 2 | const request = require('./request'); 3 | 4 | const keys = {}; 5 | 6 | /** 7 | * If cb is given, calls it with err as the first argument (if given). Otherwise, 8 | * throws err. 9 | * @param {Error} [err] - error to throw or pass to cb 10 | * @param {Function} [cb] - callback function 11 | * @throws {Error} if no cb is given and err is given 12 | */ 13 | exports.shoot = (err, cb) => { 14 | if (cb) return cb(err); 15 | throw err; 16 | }; 17 | 18 | /** 19 | * Verifies API and Device keys against the Panel. 20 | * 21 | * @param {Object} obj - keys to verify 22 | * @param {string} obj.api - API key 23 | * @param {string} obj.device - Device key 24 | * @param {Function} cb - callback function 25 | * @throws {Error} if the verification fails 26 | */ 27 | exports.verifyKeys = (obj, cb) => { 28 | const url = `/devices/${obj.device}/verify.json`; 29 | const opts = { username: obj.api, password: 'x' }; 30 | 31 | request.get(url, opts, (err, resp, body) => { 32 | if (err) return cb(err); 33 | 34 | if (resp.statusCode === 200) cb(); 35 | else if (resp.statusCode === 406 || resp.statusCode === 404) cb(errors.get('INVALID_DEVICE_KEY')); 36 | else if (resp.statusCode === 401) cb(errors.get('INVALID_CREDENTIALS')); 37 | else cb(new Error(`Unable to verify keys: ${body.toString()}`)); 38 | }); 39 | }; 40 | 41 | exports.present = () => !!(keys.api && keys.device); 42 | 43 | exports.get = () => keys; 44 | 45 | // only returns error if api key is empty 46 | exports.set = (obj, cb) => { 47 | if (!obj.api && !keys.api) return exports.shoot(errors.get('NO_API_KEY'), cb); 48 | 49 | if (obj.api) keys.api = obj.api; 50 | 51 | if (obj.device) keys.device = obj.device; 52 | 53 | cb && cb(); 54 | return keys; 55 | }; 56 | 57 | /** 58 | * Verifies the given API and Device keys against the Panel and if the 59 | * verification is successful, sets them as the current keys. 60 | * 61 | * @param {Object} obj - keys to verify and set 62 | * @param {string} obj.api - API key to set 63 | * @param {string} obj.device - Device key to set 64 | * @param {Function} [cb] - callback function 65 | * @throws {Error} if the verification fails 66 | */ 67 | exports.verify = (obj, cb) => { 68 | if (!obj.api) return exports.shoot(errors.get('NO_API_KEY'), cb); 69 | if (!obj.device) return exports.shoot(errors.get('NO_DEVICE_KEY'), cb); 70 | 71 | exports.verifyKeys(obj, (err) => { 72 | if (err) return exports.shoot(err, cb); 73 | 74 | exports.set(obj); 75 | cb && cb(); 76 | }); 77 | }; 78 | 79 | exports.unset = (key) => delete keys[key]; 80 | -------------------------------------------------------------------------------- /lib/agent/control-panel/api/logger.js: -------------------------------------------------------------------------------- 1 | let writer; 2 | 3 | const logger = { 4 | write: (type, str) => { if (writer) writer[type](str); }, 5 | debug: (str) => { logger.write('debug', str); }, 6 | info: (str) => { logger.write('info', str); }, 7 | warn: (str) => { logger.write('warn', str); }, 8 | error: (str) => { logger.write('error', str); }, 9 | }; 10 | 11 | module.exports = logger; 12 | 13 | module.exports.use = (obj) => { 14 | writer = obj; 15 | }; 16 | -------------------------------------------------------------------------------- /lib/agent/control-panel/api/push.js: -------------------------------------------------------------------------------- 1 | const keys = require('./keys'); 2 | const errors = require('./errors'); 3 | const request = require('./request'); 4 | const common = require('../../../common'); 5 | 6 | const checkKeys = () => { 7 | if (!keys.present()) throw errors.get('MISSING_KEY'); 8 | }; 9 | 10 | exports.post = (url, data, opts, cb) => { 11 | const options = opts; 12 | if (options && typeof (options) === 'object' && options?.status) { 13 | const stats = JSON.stringify(options.status); 14 | options.headers = { 'X-Prey-Status': stats }; 15 | delete options.status; 16 | } 17 | if (options && typeof (options) === 'object' && !options?.user_agent) options.user_agent = common.system.user_agent; 18 | 19 | request.post(url, data, options, cb); 20 | }; 21 | 22 | exports.formatUrl = (endpoint) => { 23 | const format = '.json'; 24 | const resp = `/devices/${keys.get().device}/${endpoint}${format}`; 25 | return resp; 26 | }; 27 | 28 | exports.response = (data, opts, cb) => { 29 | checkKeys(); 30 | const url = exports.formatUrl('response'); 31 | exports.post(url, data, opts, cb); 32 | }; 33 | 34 | exports.event = (data, opts, cb) => { 35 | checkKeys(); 36 | const url = exports.formatUrl('events'); 37 | exports.post(url, data, opts, cb); 38 | }; 39 | 40 | exports.report = (data, opts, cb) => { 41 | checkKeys(); 42 | const url = exports.formatUrl('reports'); 43 | exports.post(url, data, opts, cb); 44 | }; 45 | 46 | exports.data = (dta, opts, cb) => { 47 | checkKeys(); 48 | const url = exports.formatUrl('data'); 49 | exports.post(url, dta, opts, cb); 50 | }; 51 | 52 | exports.methods = { 53 | report: this.report, 54 | data: this.data, 55 | event: this.event, 56 | response: this.response, 57 | }; -------------------------------------------------------------------------------- /lib/agent/control-panel/bus.js: -------------------------------------------------------------------------------- 1 | // this is a simple way of transmitting events 2 | // between the different components of the control-panel plugin. 3 | 4 | var Emitter = require('events').EventEmitter; 5 | 6 | module.exports = new Emitter(); -------------------------------------------------------------------------------- /lib/agent/errors/factoryreset.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | code: 0, 4 | message: 'OK', 5 | }, 6 | { 7 | code: 2, 8 | message: 'data_error', 9 | }, 10 | { 11 | code: 3, 12 | message: 'action_only_windows_error', 13 | }, 14 | { 15 | code: 4, 16 | message: 'admin_windows_error', 17 | }, 18 | { 19 | code: 5, 20 | message: 'token_error', 21 | }, 22 | ]; 23 | -------------------------------------------------------------------------------- /lib/agent/errors/fullwipe.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | code: 0, 4 | message: 'OK', 5 | }, 6 | { 7 | code: 1, 8 | message: 'Error_getting_disk', 9 | }, 10 | { 11 | code: 2, 12 | message: 'Checking_Permissions_failed', 13 | }, 14 | { 15 | code: 3, 16 | message: 'admin_windows_error', 17 | }, 18 | { 19 | code: 4, 20 | message: 'data_error', 21 | }, 22 | { 23 | code: 5, 24 | message: 'token_error', 25 | }, 26 | { 27 | code: 6, 28 | message: 'action_only_windows_error', 29 | }, 30 | ]; 31 | -------------------------------------------------------------------------------- /lib/agent/errors/index.js: -------------------------------------------------------------------------------- 1 | exports.errorFactoryReset = require('./factoryreset'); 2 | exports.errorFullwipe = require('./fullwipe'); 3 | -------------------------------------------------------------------------------- /lib/agent/helpers.js: -------------------------------------------------------------------------------- 1 | const semver = require('semver'); 2 | 3 | const helpers = {}; 4 | 5 | helpers.running_on_background = () => helpers.run_via_service() || helpers.no_console_attached(); 6 | 7 | // returns true if no terminal attached, or stdout is not a tty 8 | helpers.no_console_attached = () => (!process.stdout.isTTY || process.env.TERM === 'dumb'); 9 | 10 | helpers.run_via_service = () => (process.platform === 'win32' && !process.env.HOMEPATH); 11 | 12 | helpers.greaterOrEqual = (first, second) => { 13 | if (typeof first !== 'string' || typeof second !== 'string') return -1; 14 | const versionAOutDot = first.replaceAll('.', ''); 15 | const versionBOutDot = second.replaceAll('.', ''); 16 | let versionADotInt = parseInt(versionAOutDot, 10); 17 | let versionBDotInt = parseInt(versionBOutDot, 10); 18 | 19 | if (versionAOutDot.length === versionBOutDot.length) return (versionADotInt >= versionBDotInt); 20 | if (versionAOutDot.length > versionBOutDot.length) { 21 | versionBDotInt *= 10 ** (versionAOutDot.length - versionBOutDot.length); 22 | } 23 | if (versionAOutDot.length < versionBOutDot.length) { 24 | versionADotInt *= 10 ** (versionBOutDot.length - versionAOutDot.length); 25 | } 26 | 27 | return (versionADotInt >= versionBDotInt); 28 | }; 29 | 30 | const validateVersions = (versions) => { 31 | const invalidVersions = []; 32 | 33 | versions.forEach((el) => { 34 | if (!semver.valid(el)) { 35 | invalidVersions.push(el); 36 | } 37 | }); 38 | 39 | return invalidVersions.length <= 0; 40 | }; 41 | 42 | const semverWrapper = (methodName, first, second) => { 43 | const valid = validateVersions([first, second]); 44 | return valid && semver[methodName](first, second); 45 | }; 46 | // is_greater_than("1.3.10", "1.3.9") returns true 47 | helpers.is_greater_than = (first, second) => semverWrapper('gt', first, second); 48 | 49 | helpers.is_greater_or_equal = (first, second) => semverWrapper('gte', first, second); 50 | 51 | helpers.semverWrapper = semverWrapper; 52 | module.exports = helpers; 53 | -------------------------------------------------------------------------------- /lib/agent/hooks.js: -------------------------------------------------------------------------------- 1 | const logger = require('./common').logger.prefix('hooks'); 2 | const Emitter = require('events').EventEmitter; 3 | 4 | const emitter = new Emitter(); 5 | const fetchEnvVar = require('../utils/fetch-env-var'); 6 | 7 | const trigger = function (event) { 8 | if (fetchEnvVar('DEBUG') && fetchEnvVar('DEBUG').localeCompare('true') === 0) logger.debug(`Hook triggered: ${JSON.stringify(arguments)}`); 9 | else if (event.localeCompare('device_unseen') !== 0) logger.info(`Hook triggered: ${event}`, arguments[1]); 10 | emitter.emit.apply(this, arguments); 11 | }; 12 | 13 | const remove = function (event, fn) { 14 | if (fn) emitter.removeListener(event, fn); 15 | else if (event) emitter.removeAllListeners(event); 16 | }; 17 | 18 | const unload = function () { 19 | logger.info('Unregistering hooks.'); 20 | emitter.removeAllListeners(); 21 | }; 22 | 23 | emitter.on('error', (err) => { 24 | logger.error(`error on emitter${(err) ? JSON.stringify(err) : ''}`); 25 | // prevents 'Unspecified Error event' 26 | }); 27 | 28 | module.exports = emitter; 29 | module.exports.trigger = trigger; 30 | module.exports.remove = remove; 31 | module.exports.unload = unload; 32 | -------------------------------------------------------------------------------- /lib/agent/permissions/darwin.js: -------------------------------------------------------------------------------- 1 | const socket = require('../socket'); 2 | 3 | const { nameArray } = require('../socket/messages'); 4 | /** 5 | * Executes the `getLocationPermission` function. 6 | * 7 | * @param {type} paramName - description of parameter 8 | * @return {type} description of return value 9 | */ 10 | const getLocationPermission = () => { 11 | socket.writeMessage(nameArray[1]); 12 | }; 13 | 14 | exports.getLocationPermission = getLocationPermission; 15 | -------------------------------------------------------------------------------- /lib/agent/permissions/index.js: -------------------------------------------------------------------------------- 1 | const osName = process.platform.replace('win32', 'windows'); 2 | // eslint-disable-next-line import/no-dynamic-require 3 | const osFunctions = require(`./${osName}`); 4 | 5 | const { getLocationPermission } = osFunctions; 6 | 7 | exports.getLocationPermission = getLocationPermission; 8 | -------------------------------------------------------------------------------- /lib/agent/permissions/linux.js: -------------------------------------------------------------------------------- 1 | const getLocationPermission = () => { 2 | }; 3 | 4 | exports.getLocationPermission = getLocationPermission; 5 | -------------------------------------------------------------------------------- /lib/agent/permissions/windows.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const { join } = path; 4 | const system = require('../../system'); 5 | 6 | const actionLocationWin = 'location-permission'; 7 | const nodeBin = join(system.paths.current, 'bin', 'node'); 8 | const { nameArray } = require('../socket/messages'); 9 | const hooks = require('../hooks'); 10 | 11 | const getLocationPermission = (cb) => { 12 | const data = { 13 | key: 'device-key', 14 | token: 'token', 15 | logged: false, 16 | dirs: ['get'], 17 | }; 18 | system.spawn_as_admin_user(nodeBin, data, ( 19 | errorRequestPermissionWin, 20 | permissionWindowsLocation, 21 | // eslint-disable-next-line consistent-return 22 | ) => { 23 | if (errorRequestPermissionWin) { 24 | if (cb) cb(); 25 | return; 26 | } 27 | if (typeof permissionWindowsLocation !== 'function') { 28 | if (cb) cb(); 29 | return; 30 | } 31 | // eslint-disable-next-line consistent-return 32 | permissionWindowsLocation( 33 | actionLocationWin, 34 | data, 35 | // eslint-disable-next-line consistent-return 36 | (errPermissionWindowsLocation, outPutpermissionWindowsLocation) => { 37 | if (errPermissionWindowsLocation || (outPutpermissionWindowsLocation 38 | && (!(Object.hasOwn(outPutpermissionWindowsLocation, 'code')) 39 | || outPutpermissionWindowsLocation.code !== 0))) { 40 | if (cb) cb(); 41 | return; 42 | } 43 | hooks.trigger(nameArray[1], [true, outPutpermissionWindowsLocation.message, 44 | cb ? cb(outPutpermissionWindowsLocation.message) : () => {}]); 45 | }, 46 | ); 47 | }); 48 | }; 49 | 50 | exports.getLocationPermission = getLocationPermission; 51 | -------------------------------------------------------------------------------- /lib/agent/providers/bandwidth/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | ////////////////////////////////////////// 4 | // Prey Bandwidth Provider 5 | // Written by Tomas Pollak 6 | // (c) 2012 - Fork Ltd. 7 | // GPLv3 Licensed 8 | ////////////////////////////////////////// 9 | 10 | var async = require('async'), 11 | network = require('./../network'), 12 | os_name = process.platform.replace('darwin', 'mac').replace('win32', 'windows'), 13 | os_functions = require('./' + os_name), 14 | max_samples = 3; 15 | 16 | var parseBytes = function(bytes){ 17 | if (bytes > 1048576) 18 | return (bytes/(1024*1024)).toString().substring(0,4) + " MB/s"; 19 | else 20 | return (bytes/1024).toString().substring(0,5) + " KB/s"; 21 | }; 22 | 23 | var average = function(a){ 24 | var total = 0; 25 | a.forEach(function(e){ 26 | total += e; 27 | }); 28 | return total/a.length; 29 | }; 30 | 31 | var differentials = function(a) { 32 | var d = []; 33 | for (var i = 1; i < a.length; i++) 34 | d.push(a[i] - a[i-1]); 35 | return d; 36 | }; 37 | 38 | var averages = function(a) { 39 | return parseBytes(average(differentials(a))); 40 | }; 41 | 42 | /** 43 | * callsback {in:number, out:number} averages for the active network interface 44 | **/ 45 | exports.get_bandwidth_usage = function(callback) { 46 | 47 | var bag = { 48 | sampled: 0, 49 | sent: [], 50 | received: [] 51 | }; 52 | 53 | network.get_active_network_interface(function(err, nic) { 54 | if (err) return callback(err); 55 | 56 | var sample = function(callback) { 57 | callback.data = bag; 58 | os_functions.sample(nic.name, callback); 59 | }; 60 | 61 | async.whilst(function() { 62 | return bag.sampled < max_samples; 63 | }, 64 | sample, 65 | function(err) { 66 | if (err) return callback(err); 67 | 68 | var data = { 69 | in: averages(bag.received), 70 | out: averages(bag.sent) 71 | } 72 | 73 | callback(null, data); 74 | }); 75 | 76 | }); 77 | 78 | }; 79 | -------------------------------------------------------------------------------- /lib/agent/providers/bandwidth/linux.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var 4 | exec = require('child_process').exec; 5 | 6 | /** 7 | * 8 | **/ 9 | exports.sample = function(iface, callback) { 10 | 11 | exec('cat /proc/net/dev | grep ' + iface, function(err, stdout){ 12 | 13 | if (err) return callback(err); 14 | 15 | var stats = stdout.toString().trim().split(/\s+/); 16 | // var mtu = stats[1]; 17 | var total_received = parseInt(stats[1]); 18 | var total_sent = parseInt(stats[9]); 19 | 20 | callback.data.sampled++; 21 | callback.data.received.push(total_received); 22 | callback.data.sent.push(total_sent); 23 | 24 | setTimeout(callback, 1000); 25 | }); 26 | 27 | }; 28 | -------------------------------------------------------------------------------- /lib/agent/providers/bandwidth/mac.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var 4 | exec = require('child_process').exec; 5 | 6 | /** 7 | * 8 | **/ 9 | exports.sample = function(iface, callback) { 10 | 11 | var cmd = 'netstat -b -I ' + iface; 12 | 13 | exec(cmd, function(err, stdout){ 14 | if (err) return callback(err); 15 | 16 | var str = stdout.toString().split('\n').splice(0)[1], 17 | cols = str.split(/\s+/); 18 | 19 | var total_sent = cols[9]; 20 | var total_received = cols[6]; 21 | 22 | callback.data.sampled++; 23 | callback.data.received.push(parseInt(total_received)); 24 | callback.data.sent.push(parseInt(total_sent)); 25 | 26 | setTimeout(callback, 1000); 27 | }); 28 | 29 | }; 30 | -------------------------------------------------------------------------------- /lib/agent/providers/bandwidth/windows.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var 4 | exec = require('child_process').exec; 5 | 6 | /** 7 | * Sample total network traffic, 8 | * Ignore iface, don't know how to get by adapter (yet). 9 | **/ 10 | exports.sample = function(iface,callback) { 11 | 12 | exec('netstat -e', function(err, stdout){ 13 | if (err) return callback(err); 14 | 15 | var lines = stdout.toString().trim().split(/\n/); 16 | var stats = lines[4].split(/\s+/); // 5th line of output has send/receive stats 17 | 18 | var total_received = parseInt(stats[1]); 19 | var total_sent = parseInt(stats[2]); 20 | 21 | callback.data.sampled++; 22 | callback.data.received.push(total_received); 23 | callback.data.sent.push(total_sent); 24 | 25 | setTimeout(callback, 1000); 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /lib/agent/providers/connections/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | ////////////////////////////////////////// 4 | // Prey Process List Provider 5 | // (c) 2011 - Fork Ltd. 6 | // By Tomas Pollak - http://forkhq.com 7 | // GPLv3 Licensed 8 | ////////////////////////////////////////// 9 | 10 | var join = require('path').join, 11 | os_name = process.platform.replace('darwin', 'mac').replace('win32', 'windows'); 12 | 13 | module.exports = require(join(__dirname, os_name)); 14 | -------------------------------------------------------------------------------- /lib/agent/providers/connections/linux.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var exec = require('child_process').exec; 4 | 5 | /** 6 | * 7 | **/ 8 | exports.get_outbound_connections_list = function(callback) { 9 | 10 | var connections = [], 11 | command = 'netstat -tupn | grep -v "127.0.0.1"'; 12 | 13 | exec(command, function(err, stdout) { 14 | if (err) return callback(err); 15 | 16 | stdout.toString().split("\n").forEach(function(line) { 17 | 18 | var columns = line.trim().split(/\s+/); 19 | 20 | if (columns[0] === 'tcp' || columns[0] === 'tcp4' || columns[0] === 'udp') { 21 | 22 | var connection = { 23 | protocol: columns[0], 24 | recv: columns[1], 25 | send: columns[2], 26 | local_address: columns[3], 27 | remote_address: columns[4], 28 | state: columns[5] 29 | }; 30 | 31 | connection.program_pid = columns[6].split('/')[0]; 32 | connection.program_name = columns[6].split('/')[1]; 33 | 34 | connections.push(connection); 35 | } 36 | }); 37 | 38 | callback(null, connections); 39 | }); 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /lib/agent/providers/connections/mac.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var exec = require('child_process').exec; 4 | 5 | exports.get_outbound_connections_list = function(callback) { 6 | 7 | var connections = [], 8 | command = 'netstat -p tcp -n'; 9 | 10 | exec(command, function(err, stdout) { 11 | if (err) return callback(err); 12 | 13 | stdout.toString().split("\n").splice(2).forEach(function(line){ 14 | 15 | var state, pid, columns = line.trim().split(/\s+/); 16 | if (columns.length < 2) return; 17 | 18 | var connection = { 19 | protocol: columns[0], 20 | recv: columns[1], 21 | send: columns[2], 22 | local_address: columns[3].replace(/\.(\d+)$/, ":$1"), 23 | remote_address: columns[4].replace(/\.(\d+)$/, ":$1"), 24 | state: columns[5], 25 | program_pid: null, 26 | program_name: null 27 | }; 28 | 29 | connections.push(connection); 30 | }); 31 | 32 | callback(null, connections); 33 | }); 34 | }; 35 | -------------------------------------------------------------------------------- /lib/agent/providers/connections/windows.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var exec = require('child_process').exec; 4 | 5 | /** 6 | * 7 | **/ 8 | exports.get_outbound_connections_list = function(callback) { 9 | 10 | var connections = [], 11 | command = 'netstat -ano'; 12 | 13 | exec(command, function(err, stdout){ 14 | if (err) return callback(err); 15 | 16 | stdout.toString().split("\n").splice(4).forEach(function(line){ 17 | 18 | var state, pid, columns = line.trim().split(/\s+/); 19 | 20 | if (columns[0] === 'TCP' || columns[0] === 'TCP4' || columns[0] === 'UDP') { 21 | 22 | if (columns.length === 5) { 23 | state = columns[3]; 24 | pid = columns[4]; 25 | } else { 26 | pid = columns[3]; 27 | state = "Unknown"; 28 | } 29 | 30 | var connection = { 31 | protocol: columns[0], 32 | recv: null, 33 | send: null, 34 | local_address: columns[1], 35 | remote_address: columns[2], 36 | state: state, 37 | program_pid: pid, 38 | program_name: null 39 | }; 40 | 41 | connections.push(connection); 42 | } 43 | 44 | }); 45 | 46 | callback(null, connections); 47 | }); 48 | }; 49 | -------------------------------------------------------------------------------- /lib/agent/providers/encryption-keys/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable consistent-return */ 2 | const os = require('os'); 3 | const common = require('../../common'); 4 | const commands = require('../../commands'); 5 | 6 | const logger = common.logger.prefix('encryption'); 7 | const osName = os.platform().replace('win32', 'windows').replace('darwin', 'mac'); 8 | const { system } = common; 9 | let processing = false; 10 | 11 | exports.scheduled = false; 12 | exports.timeout = 2 * 60 * 60 * 1000; // Every 2 hours 13 | 14 | module.exports.get_encryption_keys = (cb) => { 15 | if (osName === 'windows') { 16 | logger.info('Getting encryption keys'); 17 | system.get_as_admin_user('recoveryKeys', (err, info) => { 18 | if (err) return cb(err); 19 | if (!Array.isArray(info)) return cb(new Error('Invalid encryption keys information')); 20 | 21 | // Schedule another keys fetch if there's at least one disk encrypted. 22 | processing = false; 23 | info.forEach((disk) => { 24 | if (disk.diskStatus === 'encrypted' || disk.diskStatus === 'locked') { 25 | processing = true; 26 | } 27 | }); 28 | 29 | if (processing) { 30 | if (!exports.scheduled) { 31 | exports.scheduled = true; 32 | setTimeout(() => { 33 | exports.scheduled = false; 34 | commands.perform({ command: 'get', target: 'encryption_keys' }); 35 | }, exports.timeout); 36 | } 37 | } else { 38 | processing = false; 39 | } 40 | 41 | return cb(null, JSON.stringify(info)); 42 | }); 43 | } else { 44 | return typeof (cb) === 'function' && cb(new Error('Action only allowed on Windows')); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /lib/agent/providers/encryption-status/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | ////////////////////////////////////////// 4 | // (C) 2020 Prey, Inc. 5 | // By Javier Acuña - http://preyproject.com 6 | // GPLv3 Licensed 7 | //////////////////////////////////////////// 8 | 9 | var common = require('./../../common'), 10 | commands = require('./../../commands'), 11 | logger = common.logger.prefix('encryption'), 12 | system = common.system, 13 | processing = false; 14 | 15 | exports.scheduled = false; 16 | exports.timeout = 10 * 60 * 1000 // Every 10 minutes 17 | 18 | module.exports.get_encryption_status = function(cb) { 19 | logger.info("Getting encryption status"); 20 | system.get_as_admin_user('encryptStatus', (err, info) => { 21 | if (err) return cb(err); 22 | if (!Array.isArray(info)) return cb(new Error("Invalid encryption status information")); 23 | 24 | // Schedule another status fetch if there's at least one disk encrypting or decrypting. 25 | processing = false; 26 | info.forEach((disk) => { 27 | if (disk.volumeStatus != "FullyDecrypted" && disk.volumeStatus != "FullyEncrypted" && disk.volumeStatus != "None") { 28 | processing = true; 29 | } 30 | }) 31 | 32 | if (processing) { 33 | if (!exports.scheduled) { 34 | exports.scheduled = true; 35 | setTimeout(() => { 36 | exports.scheduled = false; 37 | commands.perform({command: 'get', target: 'encryption_status'}) 38 | }, exports.timeout) 39 | } 40 | } else { 41 | processing = false; 42 | } 43 | return cb(null, JSON.stringify(info)) 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /lib/agent/providers/files/attr.js: -------------------------------------------------------------------------------- 1 | var fs = new ActiveXObject("Scripting.FileSystemObject"), 2 | name = WScript.Arguments.item (0); 3 | 4 | var file, out, error; 5 | 6 | try { 7 | file = fs.getFile(name); 8 | 9 | } catch (e) { 10 | try { file = fs.GetFolder(name); } 11 | catch(e) { error = e.message; } 12 | } 13 | 14 | if (error) out = 'Error: ' + error; 15 | else { 16 | out = '{'; 17 | out += '"readonly":' + !!(file.attributes & 1) +','; //Read-only 18 | out += '"hidden":' + !!(file.attributes & 2) +','; //Hidden 19 | out += '"system":' + !!(file.attributes & 4) +','; //System 20 | out += '"directory":'+ !!(file.attributes & 16) +','; //Directory 21 | out += '"archive":' + !!(file.attributes & 32) +','; //Archive 22 | out += '"symlink":' + !!(file.attributes & 1024) ; // Reparse point (symbolic link) 23 | out += '}'; 24 | } 25 | 26 | WScript.echo(out); -------------------------------------------------------------------------------- /lib/agent/providers/geo/darwin/index.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | const common = require('../../../common'); 3 | const socket = require('../../../socket'); 4 | const { nameArray } = require('../../../socket/messages'); 5 | 6 | const app = join(__dirname, '..', '..', '..', 'utils', 'Prey.app'); 7 | const { system } = common; 8 | const runAsUser = system.run_as_logged_user; 9 | const { greaterOrEqual } = common.helpers; 10 | 11 | const parseResponse = (data, cb) => { 12 | try { 13 | const responseData = data.result.messages[1].message; 14 | if (Object.prototype.hasOwnProperty.call(responseData, 'accuracy')) responseData.accuracy = parseFloat(responseData.accuracy).toFixed(6); 15 | return cb(null, responseData); 16 | } catch (errExcept) { 17 | return cb(new Error(errExcept.message)); 18 | } 19 | }; 20 | 21 | const getLocationOld = (cb) => { 22 | const bin = join(app, 'Contents', 'MacOS', 'Prey'); 23 | const args = ['-location']; 24 | try { 25 | runAsUser(bin, args, { timeout: 120000 }, (errRun, data) => { 26 | if (errRun || (data && data.includes('error'))) return cb(new Error('Unable to get native location')); 27 | return parseResponse(data, cb); 28 | }); 29 | } catch (err) { 30 | cb(new Error(err.message)); 31 | } 32 | }; 33 | 34 | const getLocation = (cb) => { 35 | // eslint-disable-next-line consistent-return 36 | system.get_os_version((_err, version) => { 37 | if (version && greaterOrEqual(version, '10.6.0')) { 38 | socket.writeMessage(nameArray[0], (err, data) => { 39 | if (err) { 40 | return getLocationOld(cb); 41 | } 42 | return parseResponse(data, cb); 43 | }); 44 | } else { 45 | return cb(new Error('Not yet supported')); 46 | } 47 | }); 48 | }; 49 | 50 | const askLocationNativePermission = (cb) => { 51 | socket.writeMessage(nameArray[0], (err, data) => { 52 | if (err) return cb(err); 53 | return cb(null, data); 54 | }, 31000); 55 | }; 56 | 57 | exports.get_location = getLocation; 58 | exports.askLocationNativePermission = askLocationNativePermission; 59 | -------------------------------------------------------------------------------- /lib/agent/providers/geo/index.js: -------------------------------------------------------------------------------- 1 | const strategies = require('./strategies'); 2 | const hooks = require('../../hooks'); 3 | const logger = require('../../common').logger.prefix('geo'); 4 | const permissionFile = require('../../../utils/permissionfile'); 5 | const socket = require('../../socket'); 6 | const { nameArray } = require('../../socket/messages'); 7 | const { getLocationPermission } = require('../../permissions'); 8 | 9 | const osName = process.platform.replace('win32', 'windows').replace('darwin', 'mac'); 10 | const strategiesList = ['native', 'wifi', 'geoip']; 11 | 12 | let defaultStrategy = 'wifi'; 13 | let current; 14 | 15 | const logError = (err, strategy) => { 16 | logger.debug(`Error getting location using ${strategy} strategy: ${err}`); 17 | }; 18 | 19 | exports.set_default = (strategy) => { 20 | defaultStrategy = strategy; 21 | }; 22 | 23 | exports.get_location = (cb) => { 24 | hooks.trigger('get_location', cb); 25 | }; 26 | exports.getLocationRequest = (cb) => { 27 | hooks.trigger('get_location_request', cb); 28 | }; 29 | exports.get_location_native = (cb) => { 30 | strategies.native((err) => { cb(err); }); 31 | }; 32 | 33 | const strategyCallback = (err, res, cb) => { 34 | if (err) { 35 | logError(err, current); 36 | const next = strategiesList.indexOf(current) + 1; 37 | if (next === strategiesList.length) return cb(err); 38 | current = strategiesList[next]; 39 | return strategies[strategiesList[next]]((errInside, resInside) => { 40 | strategyCallback(errInside, resInside, cb); 41 | }); 42 | } 43 | return cb(null, res); 44 | }; 45 | 46 | // eslint-disable-next-line consistent-return 47 | exports.fetch_location = (cb) => { 48 | if (osName === 'mac') { 49 | socket.writeMessage(nameArray[1], () => { 50 | const permissionNative = permissionFile.getData('nativeLocation'); 51 | const permissionWifi = permissionFile.getData('wifiLocation'); 52 | if ((!permissionNative || permissionNative.localeCompare('true') !== 0) 53 | && (!permissionWifi || permissionWifi.localeCompare('true') !== 0)) { 54 | defaultStrategy = 'geoip'; 55 | } 56 | if (permissionNative.localeCompare('true') === 0) { 57 | defaultStrategy = 'native'; 58 | } else if (permissionWifi.localeCompare('true') === 0) { 59 | defaultStrategy = 'wifi'; 60 | } 61 | strategies[defaultStrategy]((err, res) => strategyCallback(err, res, cb)); 62 | }); 63 | } else { 64 | if (osName === 'windows') setTimeout(() => { getLocationPermission(); }, 8000); 65 | current = defaultStrategy; 66 | strategies[defaultStrategy]((err, res) => strategyCallback(err, res, cb)); 67 | } 68 | }; 69 | -------------------------------------------------------------------------------- /lib/agent/providers/geo/linux/index.js: -------------------------------------------------------------------------------- 1 | // geolocation provider using geoclue service 2 | 3 | var exec = require('child_process').exec; 4 | 5 | /* 6 | 7 | valid dbus reply format: 8 | 9 | int32 # number of fields 10 | int32 # timestamp 11 | double # lat 12 | double # lng 13 | double # altitude 14 | struct { # accuracy 15 | int32 3 16 | double 0 17 | double 0 18 | } 19 | 20 | */ 21 | 22 | function parse(out, cb) { 23 | var matches = out.match(/double ([\d\.-]+)/g); 24 | if (matches < 2) 25 | return cb(new Error('Unable to get location.')) 26 | 27 | var res = { 28 | lat: parseFloat(matches[0].replace('double ', '')), 29 | lng: parseFloat(matches[1].replace('double ', '')), 30 | altitude: parseFloat(matches[2].replace('double ', '')) 31 | } 32 | 33 | cb(null, res); 34 | } 35 | 36 | function get_command_one(provider) { 37 | var bin = 'dbus-send', 38 | service = 'org.freedesktop.Geoclue.Providers.' + provider, 39 | path = '/org/freedesktop/Geoclue/Providers/' + provider, 40 | command = 'org.freedesktop.Geoclue.Position.GetPosition'; 41 | 42 | return [bin, '--print-reply', '--dest=' + service, path, command].join(' '); 43 | } 44 | 45 | function geoclue_one(provider, cb) { 46 | var cmd = get_command_one(provider); 47 | 48 | exec(cmd, function(err, out) { 49 | if (err) return cb(err); 50 | 51 | parse(out, cb); 52 | }) 53 | } 54 | 55 | function get_command_two() { 56 | var bin = 'dbus-send', 57 | service = 'org.freedesktop.GeoClue2', 58 | path = '/org/freedesktop/GeoClue2', 59 | command = 'org.freedesktop.GeoClue2.Location'; 60 | 61 | return [bin, '--print-reply', '--dest=' + service, path, command].join(' '); 62 | } 63 | 64 | function geoclue_two(cb) { 65 | exec(get_command_two, function(err, out) { 66 | if (err) return cb(err); 67 | 68 | parse(out, cb); 69 | }) 70 | } 71 | 72 | exports.get_location = function(cb) { 73 | geoclue_two(function(err, res) { 74 | if (res) return cb(null, res); 75 | 76 | geoclue_one('Skyhook', function(err, res) { 77 | if (res) return cb(null, res); 78 | 79 | geoclue_one('UbuntuGeoIP', cb); 80 | }); 81 | }) 82 | }; 83 | 84 | const askLocationNativePermission = (cb) => { 85 | if (typeof cb === 'function') cb(); 86 | }; 87 | 88 | exports.askLocationNativePermission = askLocationNativePermission; 89 | -------------------------------------------------------------------------------- /lib/agent/providers/geo/win32/index.js: -------------------------------------------------------------------------------- 1 | var geo; 2 | 3 | function load_geo() { 4 | if (geo) 5 | return geo; 6 | 7 | try { 8 | geo = require('./windows.devices.geolocation'); 9 | return geo; 10 | } catch(e) { 11 | return e; 12 | } 13 | } 14 | 15 | exports.get_location = function(cb) { 16 | var geo = load_geo(); 17 | 18 | if (!geo.Geolocator) 19 | return cb(new Error('Unable to load geolocation module: ' + geo.message)) 20 | 21 | function locate() { 22 | var loc = new geo.Geolocator(); 23 | 24 | loc.getGeopositionAsync(function(err, res) { 25 | if (err || !res.coordinate) 26 | return cb(err || new Error('Unable to get location.')) 27 | 28 | var obj = { 29 | lat: res.coordinate.latitude, 30 | lng: res.coordinate.longitude, 31 | accuracy: res.coordinate.accuracy 32 | } 33 | 34 | cb(null, obj); 35 | }); 36 | } 37 | 38 | locate(); 39 | }; 40 | 41 | const askLocationNativePermission = (cb) => { 42 | if (typeof cb === 'function') cb(); 43 | }; 44 | 45 | exports.askLocationNativePermission = askLocationNativePermission; 46 | -------------------------------------------------------------------------------- /lib/agent/providers/geo/win32/windows.devices.geolocation/.npmignore: -------------------------------------------------------------------------------- 1 | binding.gyp 2 | *.cc 3 | *.cpp 4 | *.h 5 | *.vcxproj 6 | *.filters 7 | *.user 8 | Debug 9 | Release 10 | test -------------------------------------------------------------------------------- /lib/agent/providers/geo/win32/windows.devices.geolocation/README.md: -------------------------------------------------------------------------------- 1 | Windows.Devices.Geolocation 2 | ===== 3 | This addon wraps Windows.Devices.Geolocation WinRT namespace. 4 | 5 | Please see below the documantation from http://msdn.microsoft.com/en-us/library/windows/apps/Windows.Devices.Geolocation.aspx 6 | 8 | -------------------------------------------------------------------------------- /lib/agent/providers/geo/win32/windows.devices.geolocation/bin/ia32/NodeRT_Windows_Devices_Geolocation.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/providers/geo/win32/windows.devices.geolocation/bin/ia32/NodeRT_Windows_Devices_Geolocation.node -------------------------------------------------------------------------------- /lib/agent/providers/geo/win32/windows.devices.geolocation/bin/x64/NodeRT_Windows_Devices_Geolocation.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/providers/geo/win32/windows.devices.geolocation/bin/x64/NodeRT_Windows_Devices_Geolocation.node -------------------------------------------------------------------------------- /lib/agent/providers/geo/win32/windows.devices.geolocation/lib/main.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation 2 | // All rights reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the ""License""); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 5 | // 6 | // THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 7 | // 8 | // See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. 9 | var path = require('path'); 10 | var fs = require('fs'); 11 | 12 | try { 13 | // this little trick makes node.js Tools for VS load intellisense for the modul 14 | if (fs.existsSync(path.join(__dirname, 'NodeRT_Windows_Devices_Geolocation.d.js)'))) { 15 | module.exports = require('./NodeRT_Windows_Devices_Geolocation.d.js'); 16 | } 17 | module.exports = require('../bin/' + process.arch + '/NodeRT_Windows_Devices_Geolocation.node'); 18 | } 19 | catch(e) { 20 | throw e; 21 | } 22 | -------------------------------------------------------------------------------- /lib/agent/providers/geo/win32/windows.devices.geolocation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "windows.devices.geolocation", 3 | "version": "0.1.0", 4 | "description": "NodeRT Wrapper for Windows.Devices.Geolocation", 5 | "main": "lib/main.js", 6 | "keywords": [ 7 | "Windows.Devices.Geolocation", 8 | "Windows", 9 | "Devices", 10 | "Geolocation", 11 | "IGeoshape", 12 | "Geopoint", 13 | "GeocoordinateSatelliteData", 14 | "Geocoordinate", 15 | "CivicAddress", 16 | "Geoposition", 17 | "PositionChangedEventArgs", 18 | "StatusChangedEventArgs", 19 | "Geolocator", 20 | "Geocircle", 21 | "PositionAccuracy", 22 | "PositionStatus", 23 | "PositionSource", 24 | "GeoshapeType", 25 | "AltitudeReferenceSystem", 26 | "BasicGeoposition" 27 | ], 28 | "author": "Generated by NodeRT", 29 | "license": "Apache 2.0" 30 | } 31 | -------------------------------------------------------------------------------- /lib/agent/providers/indicators/index.js: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////// 2 | // Prey JS System Module 3 | // (c) 2011 - Fork Ltd. 4 | // By Tomas Pollak - http://forkhq.com 5 | // GPLv3 Licensed 6 | ////////////////////////////////////////// 7 | 8 | "use strict"; 9 | 10 | var 11 | os = require('os'), 12 | os_name = process.platform.replace('darwin', 'mac').replace('win32', 'windows'), 13 | os_functions = require('./' + os_name), 14 | battery_available = true; 15 | 16 | /** 17 | * Callsback current uptime in seconds. 18 | **/ 19 | exports.get_uptime = function (callback) { 20 | callback(null, parseInt(os.uptime())); 21 | }; 22 | 23 | /** 24 | * Callsback percentage of battery remaining in integer: ('80%' -> 80) 25 | **/ 26 | exports.get_remaining_battery = function (callback) { 27 | os_functions.get_battery_status(function (err, data) { 28 | if (err || !data) 29 | return callback(err || new Error("Couldn't read battery status.")); 30 | 31 | callback(null, data.percentage_remaining + '%'); 32 | }); 33 | }; 34 | 35 | /** 36 | * Callsback object with last_min, last_five and last_fifteen fields of load 37 | **/ 38 | exports.get_cpu_load = function (callback) { 39 | var data = os.loadavg(); 40 | 41 | var info = { 42 | last_min: data[0], 43 | last_five: data[1], 44 | last_fifteen: data[2] 45 | }; 46 | 47 | callback(null, info); 48 | }; 49 | 50 | exports.get_memory_usage = function (callback) { 51 | var trimInt = function (number, len) { 52 | return number.toString().substring(0, len || 4); 53 | }; 54 | 55 | var mem_usage = { 56 | total_bytes: os.totalmem(), 57 | free_bytes: os.freemem(), 58 | used: 100 - trimInt(os.freemem() * 100 / os.totalmem()) + '%' 59 | }; 60 | // mem_usage.used = 100 - parseFloat(mem_usage.remaining) + '%'; 61 | 62 | callback(null, mem_usage); 63 | }; 64 | 65 | /** 66 | * Get battery info. 67 | **/ 68 | exports.get_battery_status = function (callback) { 69 | if (!battery_available) return callback(); 70 | os_functions.get_battery_status((err, stdout) => { 71 | if (err && err.message == 'No Instance(s) Available.') { 72 | battery_available = false; 73 | callback() 74 | } 75 | callback(err, stdout) 76 | }); 77 | } 78 | 79 | /** 80 | * Callsback an object with fields size_gb, free_gb, used 81 | **/ 82 | exports.get_remaining_storage = os_functions.get_remaining_storage; 83 | -------------------------------------------------------------------------------- /lib/agent/providers/indicators/linux.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var fs = require('fs'), 4 | exec = require('child_process').exec, 5 | _ = require('underscore'); 6 | 7 | var battery_fallback = function(callback) { 8 | 9 | var battery_path = '/proc/acpi/battery/BAT0', 10 | cmd ='cat ' + battery_path + '/state'; 11 | 12 | let exists = fs.existsSync(battery_path) 13 | if (!exists) return callback(new Error(battery_path + ' not found.')); 14 | 15 | exec(cmd, function(err, stdout) { 16 | if (err) return callback(err); 17 | 18 | var output = stdout.toString(), 19 | remaining = output.match(/remaining capacity:\s+(\d+)/)[1], 20 | state = output.match(/charging state:\s+(\w+)/)[1], 21 | cmdInfo = 'cat ' + battery_path + '/info'; 22 | 23 | exec(cmdInfo, function(err, stdout){ 24 | if(err) return callback(err); 25 | 26 | var full = stdout.toString().match(/last full capacity:\s+(\d+)/)[1]; 27 | 28 | var data = { 29 | percentage_remaining: parseInt(remaining) * 100 / parseInt(full), 30 | time_remaining: null, // TODO 31 | state: state.toLowerCase() 32 | }; 33 | 34 | callback(null, data); 35 | }); 36 | }); 37 | }; 38 | 39 | /** 40 | * Try upower, then fallback to /proc/acpi if upower does not exist. 41 | **/ 42 | exports.get_battery_status = function(callback){ 43 | 44 | var cmd = 'upower --dump'; 45 | 46 | exec(cmd, function(err, stdout) { 47 | if (err) { 48 | if (err.code === 127) { // command not found 49 | return battery_fallback(callback); 50 | } else { 51 | return callback(err); 52 | } 53 | } 54 | 55 | var obj = _.chain(stdout.split('\n\n')) 56 | .map(function(block) { 57 | return block.split('\n'); 58 | }).filter(function(blockarray) { 59 | return blockarray[0].match(/battery_BAT/); 60 | }) 61 | .flatten() 62 | .reduce(function(o, el) { 63 | var m = el.match(/(percentage|state):\s+(\S+)/); 64 | if (m) { 65 | if (m[1] === "percentage") 66 | o.percentage_remaining = m[2].replace(/\%/g, ''); 67 | else 68 | o[m[1]] = m[2].toLowerCase(); // o.state = 69 | } 70 | return o; 71 | }, {time_remaining: null}).value(); 72 | 73 | if (obj.state) 74 | callback(null, obj) 75 | else 76 | callback(new Error('Unable to read battery info.')) 77 | 78 | }); 79 | 80 | }; 81 | 82 | exports.get_remaining_storage = function(callback) { 83 | 84 | exec("df -kh / | tail -1", function(err, stdout){ 85 | if (err) return callback(err); 86 | 87 | var data = stdout.toString().trim().split(/\s+/); 88 | 89 | var info = { 90 | total_gb: data[1], 91 | free_gb : data[3], 92 | used : data[4] 93 | }; 94 | 95 | callback(null, info); 96 | }); 97 | }; 98 | -------------------------------------------------------------------------------- /lib/agent/providers/indicators/mac.js: -------------------------------------------------------------------------------- 1 | var exec = require('child_process').exec; 2 | 3 | // when battery is charging, time remaining is actually 4 | // what remains until the battery is full. 5 | exports.get_battery_status = function(callback){ 6 | 7 | exec('pmset -g batt', function(err, stdout){ 8 | if (err) return callback(err); 9 | 10 | var time_remaining, output = stdout.toString(); 11 | 12 | try { 13 | var percentage_remaining = output.match(/(\d+)%;/)[1]; 14 | var state = output.match(/%;\s+(\w+)/)[1]; 15 | } catch (err) { 16 | return callback(new Error('No battery found.')) 17 | } 18 | 19 | // when plugged, for a second the status is 'AC attached, not charging' 20 | if (state == 'AC') state = 'charging'; 21 | 22 | if (time_value = output.match(/;\s+(\d+:\d+)/)) 23 | time_remaining = time_value[1]; 24 | 25 | var data = { 26 | percentage_remaining: percentage_remaining, 27 | time_remaining: time_remaining, 28 | state: state 29 | } 30 | 31 | callback(null, data); 32 | 33 | }); 34 | 35 | }; 36 | 37 | 38 | exports.get_remaining_storage = function(callback) { 39 | 40 | exec("df -kh / | tail -1", function(err, stdout){ 41 | if (err) return callback(err); 42 | 43 | var data = stdout.toString().trim().split(/\s+/); 44 | 45 | var info = { 46 | total_gb: data[1], 47 | free_gb: data[3], 48 | used: data[4] 49 | }; 50 | 51 | callback(null, info); 52 | }); 53 | }; 54 | -------------------------------------------------------------------------------- /lib/agent/providers/indicators/windows.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable consistent-return */ 2 | const { battery, getRemainingStorage } = require('../../utils/utilinformation'); 3 | 4 | /** 5 | * 6 | * */ 7 | exports.get_remaining_storage = (cb) => { 8 | getRemainingStorage((err, stdout) => { 9 | if (err) return cb(err); 10 | const cols = stdout.trim().split('\n'); 11 | const totalGb = cols[0].replace('\r', '').split(':')[1].trim(); 12 | 13 | const freeGb = cols[1].replace('\r', '').split(':')[1].trim(); 14 | const info = { 15 | total_gb: totalGb, 16 | free_gb: freeGb, 17 | used: (totalGb / freeGb) * 100, 18 | }; 19 | 20 | cb(null, info); 21 | }); 22 | }; 23 | 24 | /** 25 | * 26 | * */ 27 | exports.get_battery_status = (cb) => { 28 | const getStateBattery = (batteryData) => { 29 | if (batteryData.isCharging) { 30 | return 'charging'; 31 | } 32 | if (!batteryData.isCharging && batteryData.percent < 100) { 33 | return 'discharging'; 34 | } 35 | if (batteryData.percent === 100) { 36 | return 'charged'; 37 | } 38 | }; 39 | 40 | battery((memory) => { 41 | const data = { 42 | percentage_remaining: parseInt(memory.percent, 10), 43 | state: getStateBattery(memory), 44 | time_remaining: memory.timeRemaining || 'unknown', 45 | }; 46 | cb(null, data); 47 | }); 48 | }; 49 | -------------------------------------------------------------------------------- /lib/agent/providers/lan/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | ////////////////////////////////////////// 4 | // Prey LAN Info Provider 5 | // (c) 2011 - Fork Ltd. 6 | // By Tomas Pollak - http://forkhq.com 7 | // GPLv3 Licensed 8 | ////////////////////////////////////////// 9 | 10 | var os_name = process.platform.replace('darwin', 'mac').replace('win32', 'windows'); 11 | module.exports = require('./' + os_name); 12 | -------------------------------------------------------------------------------- /lib/agent/providers/lan/linux.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var network = require('./../network'), 4 | async = require('async'), 5 | exec = require('child_process').exec; 6 | 7 | /** 8 | * 9 | **/ 10 | var ip_from_host = function(hostname, callback) { 11 | 12 | exec('nmblookup ' + hostname+' 2>&1', function(err, stdout){ 13 | if (err) return callback(err); 14 | 15 | var out = stdout.trim(); 16 | if (out.indexOf("name_query failed") !== -1) 17 | return callback(new Error('Name query failed.')); 18 | 19 | callback(null, out); 20 | }); 21 | 22 | }; 23 | 24 | /** 25 | * Callback an array of nodes of the form {name:'',ip_address:''}. 26 | **/ 27 | exports.get_active_nodes_list = function(callback){ 28 | 29 | var nodes = [], skip = ['WORKGROUP', '..__MSBROWSE__.']; 30 | 31 | network.get_active_network_interface(function(err, nic) { 32 | if (err) return callback(err); 33 | 34 | exec('nmblookup -A ' + nic.broadcast_address, function(err, stdout) { 35 | if (err) return callback(err); 36 | 37 | if (stdout.toString().match('No reply from')) 38 | return callback(new Error("Couldln't get list of devices in LAN.")) 39 | 40 | var lines = stdout.trim().toString().split("\n"); 41 | 42 | async.parallel(lines.map(function(line) { 43 | 44 | var columns = line.trim().split(/\s+/); 45 | 46 | if (skip.indexOf(columns[0]) === -1 && columns[columns.length-1] === '') { 47 | 48 | return function(ascb) { 49 | ip_from_host(columns[0], function(err, ip) { 50 | if (err) return; 51 | 52 | var node = { 53 | name: columns[0], 54 | ip_address: ip 55 | }; 56 | 57 | if (skip.indexOf(columns[0]) === -1) { 58 | nodes.push(node); 59 | skip.push(node.name); 60 | } 61 | ascb(); 62 | }); 63 | }; 64 | } else { 65 | return null; 66 | } 67 | 68 | }).filter(function(fns) { return fns !== null; }), 69 | 70 | function() { 71 | callback(null, nodes); 72 | }); 73 | 74 | }); 75 | }); 76 | 77 | }; 78 | -------------------------------------------------------------------------------- /lib/agent/providers/lan/mac.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var 4 | network = require('./../network'), 5 | async = require('async'), 6 | exec = require('child_process').exec; 7 | 8 | /** 9 | * 10 | **/ 11 | var ip_from_host = function(hostname, callback) { 12 | callback(new Error('TODO!')); 13 | }; 14 | 15 | /** 16 | * Callback an array of nodes of the form {name:'',ip_address:''}. 17 | **/ 18 | exports.get_active_nodes_list = function(callback){ 19 | callback(new Error('TODO!')); 20 | }; 21 | -------------------------------------------------------------------------------- /lib/agent/providers/lan/windows.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var 4 | async = require('async'), 5 | exec = require('child_process').exec, 6 | ip_regex = require('./../network').ip_address_regex; 7 | 8 | exports.get_active_nodes_list = function(callback) { 9 | var cmd = 'nbtstat -c'; 10 | exec(cmd, function(err,stdout) { 11 | if (err) return callback(err); 12 | 13 | if (stdout.indexOf('----------') === -1) 14 | return callback(null,[]); // does not exist 15 | 16 | var table = stdout.split("\n").splice(6); 17 | 18 | // columns in format NAME <00> TYPE IP 19 | var netstatC = /([A-Z0-9]+)\s+(\S+)\s+(\S)+\s+(\S)+/; 20 | 21 | callback(null, table.map(function(line) { 22 | return line.match(netstatC); 23 | }).filter(function(match) { 24 | return match !== null; 25 | }).map(function(match) { 26 | return { 27 | name:match[0], 28 | ip_address:match[3] 29 | }; 30 | })); 31 | }); 32 | }; 33 | 34 | /** 35 | * Callsback an ip address or null if can't find the hostname 36 | **/ 37 | var ip_from_host = function(hostname, callback) { 38 | get_nodes(function(err,nodes) { 39 | if (err) return callback(err); 40 | 41 | var n = nodes.filter(function(node) { 42 | return node.name === hostname; 43 | }); 44 | 45 | callback(null,(n.length === 1) ? n[0].ip_address : null); 46 | }); 47 | }; 48 | -------------------------------------------------------------------------------- /lib/agent/providers/processes/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | ////////////////////////////////////////// 4 | // Prey Process List Provider 5 | // (c) 2011 - Fork Ltd. 6 | // By Tomas Pollak - http://forkhq.com 7 | // GPLv3 Licensed 8 | ////////////////////////////////////////// 9 | 10 | var os_name = process.platform.replace('darwin', 'mac').replace('win32', 'windows'), 11 | os_functions = require('./' + os_name), 12 | is_windows = os_name == 'windows'; 13 | 14 | exports.get_process_list = os_functions.get_process_list; 15 | 16 | /** 17 | * 18 | **/ 19 | exports.get_parent_process_list = function(callback) { 20 | var root_process_id = 1; 21 | 22 | exports.get_process_list(function(err, list) { 23 | if (err) return callback(err); 24 | 25 | var parents = []; 26 | 27 | list.forEach(function(p) { 28 | if (is_windows || (p.ppid === root_process_id)) 29 | parents.push(p); 30 | }); 31 | 32 | callback(null, parents); 33 | }); 34 | }; 35 | 36 | exports.get_user_process_list = function(cb) { 37 | 38 | var master_process_id = 1; 39 | 40 | exports.get_process_list(function(err, list) { 41 | if (err) return callback(err); 42 | 43 | if (is_windows) { 44 | var master_process = list.filter(function(p) { return p.name == 'services.exe' }); 45 | if (master_process[0]) master_process_id = master_process[0].pid; 46 | } 47 | 48 | var user_list = []; 49 | 50 | list.forEach(function(p) { 51 | if (p.ppid !== 0 && p.ppid !== master_process_id && p.pid != master_process_id) 52 | user_list.push(p); 53 | }); 54 | 55 | cb(null, user_list); 56 | }); 57 | }; -------------------------------------------------------------------------------- /lib/agent/providers/processes/linux.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var exec = require('child_process').exec; 4 | 5 | exports.get_process_list = function(callback) { 6 | 7 | var processes = [], 8 | cmd = 'ps axo stat,user,ppid,pid,pcpu,pmem,time,comm | egrep -v " ps|grep"'; 9 | 10 | var child = exec(cmd, function(err, stdout){ 11 | if (err) return callback(err); 12 | 13 | stdout.toString().split("\n").forEach(function(line){ 14 | 15 | var columns = line.trim().split(/\s+/); 16 | if (columns[0] != '' && columns[0] != 'STAT' && columns[columns.length] != ''){ 17 | 18 | var process = { 19 | status: columns[0], 20 | user: columns[1], 21 | ppid: parseInt(columns[2]), 22 | pid: parseInt(columns[3]), 23 | cpu: columns[4], 24 | mem: columns[5], 25 | time: columns[6], 26 | name: columns[7] 27 | }; 28 | 29 | // don't add the id for this prey process 30 | if (process.pid !== child.pid) 31 | processes.push(process); 32 | } 33 | }); 34 | 35 | processes.sort(function(a,b){ 36 | return (a.pid > b.pid); 37 | }); 38 | 39 | callback(null, processes); 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /lib/agent/providers/processes/mac.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var exec = require('child_process').exec; 4 | 5 | exports.get_process_list = function(callback) { 6 | 7 | var processes = [], 8 | cmd = 'ps axo stat,user,ppid,pid,pcpu,pmem,time,comm | egrep -v " ps|grep"'; 9 | 10 | var child = exec(cmd, function(err, stdout){ 11 | if (err) return callback(err); 12 | 13 | stdout.toString().split("\n").forEach(function(line){ 14 | 15 | var columns = line.trim().split(/\s+/); 16 | if (columns[0] !== '' && columns[columns.length] !== ''){ 17 | 18 | var process = { 19 | status: columns[0], 20 | user: columns[1], 21 | ppid: parseInt(columns[2]), 22 | pid: parseInt(columns[3]), 23 | cpu: columns[4], 24 | mem: columns[5], 25 | time: columns[6], 26 | name: columns[7] 27 | }; 28 | 29 | // don't add the id for this prey process 30 | if (process.pid !== child.pid) 31 | processes.push(process); 32 | } 33 | }); 34 | 35 | processes.sort(function(a,b){ 36 | return (a.pid > b.pid); 37 | }); 38 | 39 | callback(null, processes); 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /lib/agent/providers/processes/windows.js: -------------------------------------------------------------------------------- 1 | const { getProcessList } = require('../../utils/utilinformation'); 2 | 3 | /** 4 | * Callsback an array of processes. 5 | * 6 | * */ 7 | 8 | // NOTE: Not sure if UserModeTime is correct here of if need to add KernelModeTime too. 9 | 10 | exports.get_process_list = function (callback) { 11 | // eslint-disable-next-line consistent-return 12 | getProcessList((err, out) => { 13 | if (err) return callback(err); 14 | 15 | callback(null, out.split(/\n/) 16 | .filter((line) => line.length > 1 && line.indexOf('System Idle Process') === -1) 17 | .splice(1) 18 | .map((line) => { 19 | const fields = line.split(/\s+/); 20 | const pid = parseInt(fields[2], 10); 21 | 22 | return { 23 | name: fields[0], 24 | ppid: parseInt(fields[1], 10), 25 | pid, 26 | time: fields[3], 27 | }; 28 | }) 29 | .filter((obj) => obj !== null)); 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /lib/agent/providers/screenshot/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const common = require('../../common'); 3 | 4 | // eslint-disable-next-line import/no-dynamic-require 5 | const osFunctions = require(`./${common.os_name}`); 6 | 7 | exports.get_screenshot = (callback) => { 8 | // eslint-disable-next-line consistent-return 9 | osFunctions.get_screenshot((err, filePath, fileType) => { 10 | if (err) return callback(err); 11 | 12 | const exists = fs.existsSync(filePath); 13 | if (!exists) { 14 | return callback(new Error('Screenshot failed')); 15 | } 16 | 17 | const { size } = fs.statSync(filePath); 18 | if (size > 20000000) { 19 | return callback(new Error('Screenshot failed: Image is too heavy')); 20 | } 21 | callback(null, { file: filePath, content_type: fileType }); 22 | }); 23 | }; 24 | -------------------------------------------------------------------------------- /lib/agent/providers/screenshot/linux/index.js: -------------------------------------------------------------------------------- 1 | var common = require('./../../../common'), 2 | system = common.system, 3 | run_as_user = system.run_as_logged_user, 4 | temp_path = common.system.tempfile_path; 5 | 6 | exports.get_screenshot = (callback) => { 7 | let file_path = temp_path('screenshot.' + process.pid + '.jpg'); 8 | 9 | run_as_user('scrot', ['"' + file_path + '"'], (err) => { 10 | if (err) return callback(err); 11 | callback(null, file_path, 'image/jpeg') 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /lib/agent/providers/screenshot/windows/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const common = require('../../../common'); 3 | 4 | const { system } = common; 5 | const runAsUser = system.run_as_logged_user; 6 | 7 | const tempPath = system.tempfile_path; 8 | /** 9 | * Generates a screenshot and returns the file path and image type. 10 | * 11 | * @param {function} callback - The callback function to be called when the screenshot is generated. 12 | * @return {void} Returns nothing. 13 | */ 14 | exports.get_screenshot = (callback) => { 15 | const filePath = tempPath('screenshot.jpg'); 16 | runAsUser(`del /f ${filePath}`, [], { timeout: 2500 }, () => { 17 | try { 18 | runAsUser(`${path.join(__dirname, 'preyshot.exe')}`, [`${filePath}`], { timeout: 2500 }, () => { 19 | callback(null, filePath, 'image/jpeg'); 20 | }); 21 | } catch (error) { 22 | callback(null, filePath, 'image/jpeg'); 23 | } 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /lib/agent/providers/screenshot/windows/preyshot.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/providers/screenshot/windows/preyshot.exe -------------------------------------------------------------------------------- /lib/agent/providers/system/index.js: -------------------------------------------------------------------------------- 1 | // this is basically a link to the shared system functions 2 | 3 | var common = require('./../../common'); 4 | 5 | exports.get_logged_user = common.system.get_logged_user; 6 | exports.get_os_info = common.system.get_os_info; 7 | exports.get_os_name = common.system.get_os_name; 8 | exports.get_os_version = common.system.get_os_version; 9 | exports.get_current_hostname = common.system.get_current_hostname; 10 | -------------------------------------------------------------------------------- /lib/agent/providers/users/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | ////////////////////////////////////////// 4 | // (C) 2019 Prey, Inc. 5 | // By Mauricio Schneider - http://preyproject.com 6 | // GPLv3 Licensed 7 | // Prey Users Provider returns the list of users of the device, 8 | // particularly useful when child processes must be ran as a specific user or directory, 9 | // ie: filebrowser. 10 | //////////////////////////////////////////// 11 | 12 | var os_name = process.platform.replace('darwin', 'mac').replace('win32', 'windows'), 13 | os_functions = require('./' + os_name); 14 | 15 | module.exports.get_users_list = function(cb) { 16 | os_functions.get_users_list(function(err, users) { 17 | if (err) { 18 | return cb(err); 19 | } 20 | 21 | return cb(null, users); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /lib/agent/providers/users/linux.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | //////////////////////////////////////////// 4 | // (C) 2019 Prey, Inc. 5 | // By Mauricio Schneider - http://preyproject.com 6 | // GPLv3 Licensed 7 | //////////////////////////////////////////// 8 | 9 | var exec = require('child_process').exec, 10 | cmd = 'ls /home/'; 11 | 12 | module.exports.get_users_list = function(cb) { 13 | exec(cmd, function(err, stdout) { 14 | cb(err, stdout.split("\n").slice(0, -1)); 15 | }); 16 | }; 17 | -------------------------------------------------------------------------------- /lib/agent/providers/users/mac.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | //////////////////////////////////////////// 4 | // (C) 2019 Prey, Inc. 5 | // By Mauricio Schneider - http://preyproject.com 6 | // GPLv3 Licensed 7 | //////////////////////////////////////////// 8 | 9 | var exec = require('child_process').exec, 10 | cmd = 'ls /Users/'; 11 | 12 | module.exports.get_users_list = function(cb) { 13 | exec(cmd, function(err, stdout) { 14 | cb(err, stdout.split("\n").slice(0, -1)); 15 | }); 16 | }; 17 | -------------------------------------------------------------------------------- /lib/agent/providers/users/windows.js: -------------------------------------------------------------------------------- 1 | const { getUsersList } = require('../../utils/utilinformation'); 2 | 3 | /// ///////////////////////////////////////// 4 | // (c) 2019 Prey, Inc. 5 | // By Javier Acuña - http://preyproject.com 6 | // GPLv3 Licensed 7 | /// ///////////////////////////////////////// 8 | 9 | module.exports.get_users_list = function (cb) { 10 | getUsersList((err, stdout) => { 11 | cb(err, stdout.trim().replaceAll('\r', '').split('\n')); 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /lib/agent/providers/webcam-extra/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { join } = require('path'); 3 | const { exec } = require('child_process'); 4 | const common = require('../../common'); 5 | 6 | const osName = process.platform.replace('win32', 'windows').replace('darwin', 'mac'); 7 | // eslint-disable-next-line camelcase 8 | const { tempfile_path } = common.system; 9 | const exe = '/prey-webcam.exe'; 10 | const opts = ' -invalid youcam,cyberlink,google,rear -frame 10 -outfile '; 11 | const filePath = tempfile_path('extra_attachment.jpg'); 12 | const pictureCommand = `"${join(__dirname, '..', 'webcam', 'windows', exe)}"${opts}${filePath}`; 13 | 14 | /** 15 | * Takes a picture using the webcam and calls the provided callback function. 16 | * 17 | * @param {function} callback - The callback function to be called after the picture is taken. 18 | * @return {undefined} - This function does not return a value. 19 | */ 20 | const takePicture = (callback) => { 21 | // eslint-disable-next-line consistent-return 22 | exec(pictureCommand, { timeout: 20000 }, (err) => { 23 | if (err) { 24 | return callback(err); 25 | } 26 | const exists = fs.existsSync(filePath); 27 | if (exists) callback(null, { file: filePath, content_type: 'image/jpeg' }); 28 | callback(err || new Error('Couldnt grab extra picture using the webcam.')); 29 | }); 30 | }; 31 | /** 32 | * Retrieves an extra attachment using the webcam on Windows. 33 | * 34 | * @param {function} callback - The callback function to handle the result. 35 | * @return {void} 36 | */ 37 | // eslint-disable-next-line consistent-return 38 | exports.get_extra_attachment = (callback) => { 39 | if (osName !== 'windows') return callback(new Error('Only available on windows')); 40 | fs.unlink(filePath, () => { 41 | takePicture(callback); 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /lib/agent/providers/webcam/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const common = require('../../common'); 3 | 4 | // eslint-disable-next-line import/no-dynamic-require, prefer-template 5 | const osFunction = require('./' + common.os_name); 6 | /** 7 | * Retrieves a picture using the osFunction module. 8 | * 9 | * @param {function} callback - The callback function to be executed once the picture is retrieved. 10 | * @return {undefined} 11 | */ 12 | exports.get_picture = (callback) => { 13 | // eslint-disable-next-line consistent-return 14 | osFunction.get_picture((err, filePath, fileType) => { 15 | try { 16 | if (err) return callback(err, null, 'picture'); 17 | if (fs.existsSync(filePath)) callback(null, { file: filePath, content_type: fileType }, 'picture'); 18 | else callback(err || new Error("Couldn't grab a picture using the webcam.")); 19 | } catch (error) { 20 | callback(error, null, 'picture'); 21 | } 22 | }); 23 | }; 24 | -------------------------------------------------------------------------------- /lib/agent/providers/webcam/mac/README: -------------------------------------------------------------------------------- 1 | Imagesnap is the work of Robert Harder. 2 | http://www.iharder.net/current/macosx/imagesnap/ 3 | ======================================= 4 | 5 | ImageSnap is a Public Domain command-line tool that lets you capture 6 | still images from an iSight or other video source. You might remember 7 | Axel Bauer's original isightcapture tool (that is no longer supported 8 | but still works on most systems). With ImageSnap I hope we'll be able 9 | to move forward and add features, adapt to the ever-changing Apple 10 | architectures, etc. -------------------------------------------------------------------------------- /lib/agent/providers/webcam/mac/imagesnap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/providers/webcam/mac/imagesnap -------------------------------------------------------------------------------- /lib/agent/providers/webcam/windows/DirectShowLib-2005.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/providers/webcam/windows/DirectShowLib-2005.dll -------------------------------------------------------------------------------- /lib/agent/providers/webcam/windows/README.md: -------------------------------------------------------------------------------- 1 | ## Prey's new webcam module 2 | 3 | ### Introduction 4 | 5 | This is the new webcam executable, based on DirectShow, that grabs a bright image from any available webcam installed on the computer, regardless if YouCam is installed or not. 6 | 7 | As it's written in C#, it uses DirectShow's binding project [DirectShowNet](http://directshownet.sourceforge.net/), and that's why the executable needs the included DirectShowLib-2005.dll file. 8 | 9 | The way the executable works when it runs without any parameter is as follow: 10 | 11 | - It gets the first available video input device. 12 | - It opens a video stream and discards the first 4 frames to avoid dark images. 13 | - It saves the picture taken into the same execution directory. 14 | 15 | In case it can't find any available input device, then will silently finish. 16 | 17 | 18 | ### Tweaking it. 19 | 20 | These are the available command line options: 21 | 22 | - **outfile**: Name of the output file (default: prey-picture.jpg) 23 | - **framerate**: Framerate of the video stream used to get the picture. It is not recommended to modify the default value (default: 15). 24 | - **height**: Height of the picture. There's not a default value since Prey will try to get max size. 25 | - **width**: Height of the picture. There's not a default value since Prey will try to get max size. 26 | - **frame**: Frame number, from the video stream, to use as the picture (default: 4) 27 | - **invalid**: Comma-separated strings with the invalid input source names (default ''). 28 | - **kill_youcam**: If YouCam.exe process is running, then Prey will kill it before trying to get a video device (default: false). 29 | - **debug**: Prints verbose log (default: false) 30 | 31 | ### Example 32 | 33 | Avoid the use of any device that its name contains the word "youcam" or "cyberlink" or "google" and use the frame number 10 of the video stream as the valid picture: 34 | 35 | prey-webcam.exe -invalid youcam,cyberlink,google -frame 10 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /lib/agent/providers/webcam/windows/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { join } = require('path'); 3 | const { exec } = require('child_process'); 4 | const common = require('../../../common'); 5 | 6 | const tempPath = common.system.tempfile_path; 7 | const exes = ['/prey-webcam.exe', '/snapshot.exe']; 8 | const opts = [' -invalid youcam,cyberlink,google -frame 10 -outfile ', ' /T ']; 9 | const file = tempPath('picture.jpg'); 10 | const pictureCommand = (index, fileText) => `"${join(__dirname, exes[index])}"${opts[index]}${fileText}`; 11 | /** 12 | * Takes a picture and returns the file path and image type. 13 | * 14 | * @param {function} callback - The callback function to be called when the picture is taken. 15 | * @return {string} The file path of the picture. 16 | * @return {string} The image type of the picture. 17 | */ 18 | const takePicture = (callback) => { 19 | const fileReplaced = file.replace(/.jpg/g, ''); 20 | exec(pictureCommand(1, fileReplaced), { timeout: 2500 }, () => { 21 | if (!fs.existsSync(fileReplaced)) { 22 | exec(pictureCommand(0, file), { timeout: 20000 }, () => { 23 | callback(null, file, 'image/jpeg'); 24 | }); 25 | } else { 26 | callback(null, `${fileReplaced}.jpg`, 'image/jpeg'); 27 | } 28 | }); 29 | }; 30 | /** 31 | * Deletes the existing picture file and takes a new picture. 32 | * 33 | * @param {function} callback - The callback function to be executed after taking the picture. 34 | * @return {undefined} - This function does not return a value. 35 | */ 36 | exports.get_picture = (callback) => { 37 | fs.unlink(file, () => { 38 | takePicture(callback); 39 | }); 40 | }; 41 | -------------------------------------------------------------------------------- /lib/agent/providers/webcam/windows/prey-webcam.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/providers/webcam/windows/prey-webcam.exe -------------------------------------------------------------------------------- /lib/agent/providers/webcam/windows/snapshot.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/providers/webcam/windows/snapshot.exe -------------------------------------------------------------------------------- /lib/agent/reports/actions.js: -------------------------------------------------------------------------------- 1 | exports.actions = [ 2 | 'fullwipewindows', 3 | //'wipe', 4 | 'factoryreset' 5 | ]; -------------------------------------------------------------------------------- /lib/agent/reports/load.js: -------------------------------------------------------------------------------- 1 | exports.includes = [ 2 | 'cpu_load', 3 | 'memory_usage', 4 | 'remaining_storage', 5 | 'uptime' 6 | ] 7 | -------------------------------------------------------------------------------- /lib/agent/reports/specs.js: -------------------------------------------------------------------------------- 1 | exports.includes = [ 2 | 'processor_info', 3 | 'firmware_info', 4 | 'network_interfaces_list', 5 | 'ram_module_list', 6 | 'model_name', 7 | 'vendor_name', 8 | ...(process.platform === 'win32' 9 | ? ['os_edition', 'winsvc_version', 'rp_module', 'killswitch_compatible', 'osquery_running'] 10 | : []), 11 | ...(process.platform === 'darwin' ? ['prey_user_version', 'osquery_running'] : []), 12 | ]; 13 | -------------------------------------------------------------------------------- /lib/agent/reports/status.js: -------------------------------------------------------------------------------- 1 | exports.includes = [ 2 | 'uptime', 3 | 'logged_user', 4 | 'active_access_point', 5 | 'battery_status', 6 | ...(process.platform === 'win32' ? ['osquery_running'] : []), 7 | ...(process.platform === 'darwin' ? ['osquery_running'] : []), 8 | ] 9 | -------------------------------------------------------------------------------- /lib/agent/reports/stolen.js: -------------------------------------------------------------------------------- 1 | exports.includes = [ 2 | 'public_ip', 3 | 'private_ip', 4 | 'gateway_ip', 5 | 'location', 6 | 'access_points_list', 7 | 'active_access_point', 8 | 'logged_user', 9 | 'screenshot', 10 | 'picture', 11 | ...(process.platform === 'win32' ? ['extra_attachment'] : []), 12 | ]; 13 | -------------------------------------------------------------------------------- /lib/agent/socket/messages.js: -------------------------------------------------------------------------------- 1 | const functionObject = { 2 | 'location-get-location-native': { 3 | name: 'location', 4 | function: 'get-location-native', 5 | }, 6 | 'location-check-location-perms': { 7 | name: 'location', 8 | function: 'check-location-perms', 9 | }, 10 | picture: { 11 | name: 'picture', 12 | }, 13 | 'screenshot-native': { 14 | name: 'screenshot', 15 | function: 'native', 16 | }, 17 | 'screenshot-agent': { 18 | name: 'screenshot', 19 | function: 'agent', 20 | }, 21 | 'wdutil-info': { 22 | name: 'wdutil', 23 | function: 'info', 24 | }, 25 | 'watcher-set-watcher': { 26 | name: 'watcher', 27 | function: 'set-watcher', 28 | }, 29 | }; 30 | 31 | const nameArray = [ 32 | 'location-get-location-native', 33 | 'location-check-location-perms', 34 | 'picture', 35 | 'screenshot-native', 36 | 'screenshot-agent', 37 | 'wdutil-info', 38 | 'watcher-set-watcher', 39 | ]; 40 | 41 | exports.functionObject = functionObject; 42 | exports.nameArray = nameArray; 43 | -------------------------------------------------------------------------------- /lib/agent/startup.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | 3 | const fs = require('fs'); 4 | const root_path = process.env.ROOT_PATH || join(__dirname, '..', '..'); 5 | 6 | const configFileName = 'prey.conf'; 7 | const defaultConfigFilePath = join(root_path, `${configFileName}.default`); 8 | const osName = process.platform.replace('win32', 'windows').replace('darwin', 'mac'); 9 | const pathsByOs = require(`../system/${osName}/paths`); 10 | const configFilePath = join(pathsByOs.config, `${configFileName}`); 11 | 12 | const ensureAndCreateDb = (cb) => { 13 | const exists = fs.existsSync(pathsByOs.config) 14 | if (exists) return ensureDb(cb); 15 | fs.mkdir(pathsByOs.config, (err) => { 16 | if (err) return err; 17 | ensureDb(cb); 18 | }); 19 | 20 | }; 21 | 22 | const ensureDb = (cb) => { 23 | const storage = require('../agent/utils/storage'); 24 | storage.init(null, null, () => { 25 | ensurePreyConf(cb); 26 | }); 27 | }; 28 | 29 | const ensurePreyConf = (cb) => { 30 | const exists = fs.existsSync(configFilePath); 31 | if (exists) return cb(); 32 | fs.copyFile(defaultConfigFilePath, configFilePath, (err) => { 33 | if (err) return cb(err); 34 | if (osName === 'windows') { 35 | return cb(); 36 | } 37 | const { setup_permissions, create_user } = require('../conf/tasks/prey_user'); 38 | create_user(() => { 39 | setup_permissions(cb); 40 | }); 41 | }); 42 | }; 43 | 44 | exports.ensureAndCreateDb = ensureAndCreateDb; -------------------------------------------------------------------------------- /lib/agent/token.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable consistent-return */ 2 | const needle = require('needle'); 3 | const keys = require('./control-panel/api/keys'); 4 | const errors = require('./control-panel/api/errors'); 5 | const specs = require('./reports/actions'); 6 | const config = require('../utils/configfile'); 7 | 8 | const protocol = config.getData('control-panel.protocol'); 9 | const host = config.getData('control-panel.host'); 10 | const url = `${protocol}://${host}/token/v2/check`; 11 | 12 | exports.post_token = (opts, cb) => { 13 | if (!keys.get().api || !keys.get().device) return cb(errors.get('MISSING_KEY')); 14 | 15 | if (!opts) return cb(errors.arguments('Empty data.')); 16 | 17 | const existsAction = specs.actions.find((x) => x === opts.action); 18 | 19 | if (!existsAction) return cb(null); 20 | 21 | const options = { 22 | json: true, 23 | }; 24 | 25 | const data = { 26 | key: keys.get().device, 27 | token: opts.token, 28 | action: opts.action, 29 | }; 30 | 31 | needle.post(url, data, options, (errPost, resp) => { 32 | if (errPost) return cb(errPost); 33 | if (resp.statusCode !== 200) { 34 | const newErrPost = new Error('There was an error communicating with the server api Token'); 35 | return cb(newErrPost); 36 | } 37 | return cb(null); 38 | }); 39 | }; 40 | -------------------------------------------------------------------------------- /lib/agent/transports/http/index.js: -------------------------------------------------------------------------------- 1 | var needle = require('needle'), 2 | hooks = require('./../../hooks'); 3 | 4 | exports.request = function request(method, url, data, opts, cb) { 5 | needle.request(method, url, data, opts, function(err, resp) { 6 | if (err) hooks.trigger('error', err); 7 | 8 | // hooks.trigger('response', err, resp, data); 9 | cb && cb(err, resp); 10 | }) 11 | } 12 | 13 | exports.defaults = function(opts) { 14 | return needle.defaults(opts); 15 | } 16 | 17 | exports.get = function(url, opts, cb) { 18 | return this.request('GET', url, null, opts, cb) 19 | } 20 | 21 | exports.post = function(url, data, opts, cb) { 22 | return this.request('POST', url, data, opts, cb) 23 | } 24 | 25 | exports.put = function(url, data, opts, cb) { 26 | return this.request('PUT', url, data, opts, cb) 27 | } 28 | 29 | exports.del = function(url, data, opts, cb) { 30 | return this.request('DELETE', url, data, opts, cb) 31 | } 32 | -------------------------------------------------------------------------------- /lib/agent/triggers/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/triggers/README.md -------------------------------------------------------------------------------- /lib/agent/triggers/auto-connect/bin/ManagedWifi.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/triggers/auto-connect/bin/ManagedWifi.dll -------------------------------------------------------------------------------- /lib/agent/triggers/auto-connect/bin/wifion.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/triggers/auto-connect/bin/wifion.exe -------------------------------------------------------------------------------- /lib/agent/triggers/auto-connect/linux.js: -------------------------------------------------------------------------------- 1 | var join = require('path').join, 2 | exec = require('child_process').exec; 3 | network = require('./../../providers/network/linux'); 4 | 5 | var net_interface = null; 6 | 7 | var get_interface = function(cb) { 8 | network.get_first_wireless_interface(function(err, data) { 9 | net_interface = data; 10 | }); 11 | } 12 | 13 | exports.enable_wifi = function(cb) { 14 | var turn_on_wifi = function() { 15 | var cmd = 'nmcli networking on; nmcli radio wifi on'; 16 | exec(cmd, function(err, data) { 17 | return cb(); 18 | }) 19 | } 20 | net_interface ? turn_on_wifi() : get_interface(turn_on_wifi); 21 | } 22 | 23 | exports.get_existing_profiles = function(cb) { 24 | var get_profiles = function() { 25 | var cmd = 'ls /etc/NetworkManager/system-connections' 26 | exec(cmd, function(err, stdout) { 27 | cb(null, stdout.split("\n").slice(0, -1)); 28 | }) 29 | } 30 | net_interface ? get_profiles() : get_interface(get_profiles); 31 | } 32 | 33 | exports.create_profile = function(ssid, cb) { 34 | var create = function() { 35 | var cmd = `nmcli connection add type wifi ifname ${net_interface} con-name "${ssid}" ssid "${ssid}"`; 36 | exec(cmd, function(err, out) { 37 | return cb && cb(err); 38 | }) 39 | } 40 | net_interface ? create() : get_interface(create); 41 | } 42 | 43 | exports.delete_profile = function(ssid, cb) { 44 | var discard = function() { 45 | var cmd = `nmcli connection delete "${ssid}"`; 46 | exec('nmcli connection delete ' + '"' + ssid + '"', function(err, out) { 47 | return cb && cb(err); 48 | }) 49 | } 50 | net_interface ? discard() : get_interface(discard); 51 | } 52 | 53 | exports.connect_to_ap = function(ssid, cb) { 54 | var connect = function() { 55 | var cmd = `nmcli connection up "${ssid}"`; 56 | exec(cmd, function(err, out) { 57 | return cb(err, out); 58 | }); 59 | } 60 | net_interface ? connect() : get_interface(connect); 61 | } 62 | -------------------------------------------------------------------------------- /lib/agent/triggers/auto-connect/mac.js: -------------------------------------------------------------------------------- 1 | var join = require('path').join, 2 | exec = require('child_process').exec, 3 | system = require('./../../../system'), 4 | run_as_user = system.run_as_logged_user; 5 | 6 | var net_interface = null; 7 | 8 | var get_interface = function(cb) { 9 | var cmd = 'networksetup -listallhardwareports | awk "/Hardware Port: Wi-Fi/,/Ethernet/" | awk "NR==2" | cut -d " " -f 2'; 10 | exec(cmd, function(err, data) { 11 | if (err) return cb(err); 12 | 13 | net_interface = data.split("\n").slice(0, -1); 14 | return cb(null, net_interface); 15 | }) 16 | } 17 | 18 | exports.enable_wifi = function(cb) { 19 | var turn_on_wifi = function() { 20 | var cmd = `networksetup -setairportpower ${net_interface} on`; 21 | exec(cmd, function(err, data) { 22 | return cb(); 23 | }) 24 | } 25 | net_interface ? turn_on_wifi() : get_interface(turn_on_wifi); 26 | } 27 | 28 | exports.get_existing_profiles = function(cb) { 29 | var get_profiles = function() { 30 | var cmd = `networksetup -listpreferredwirelessnetworks ${net_interface} | awk 'NR>1' | awk '{$1=$1;print}'` 31 | exec(cmd, function(err, stdout) { 32 | cb(null, stdout.split("\n").slice(0, -1)); 33 | }) 34 | } 35 | net_interface ? get_profiles() : get_interface(get_profiles); 36 | } 37 | 38 | exports.create_profile = function(ssid, cb) { 39 | var create = function() { 40 | var cmd = `networksetup -addpreferredwirelessnetworkatindex ${net_interface} "${ssid}" 0 open`; 41 | run_as_user(cmd, [], function(err) { 42 | return cb && cb(err); 43 | }) 44 | } 45 | net_interface ? create() : get_interface(create); 46 | } 47 | 48 | exports.delete_profile = function(ssid, cb) { 49 | var discard = function() { 50 | var cmd = `networksetup -removepreferredwirelessnetwork ${net_interface} "${ssid}"`; 51 | run_as_user(cmd, [], function(err) { 52 | return cb && cb(err); 53 | }) 54 | } 55 | net_interface ? discard() : get_interface(discard); 56 | } 57 | 58 | exports.connect_to_ap = function(ssid, cb) { // revisar cb si va 59 | var connect = function() { 60 | var cmd = `networksetup -setairportnetwork ${net_interface} "${ssid}"`; 61 | run_as_user(cmd, [], function(err, out) { 62 | return cb(err, out); 63 | }); 64 | } 65 | net_interface ? connect() : get_interface(connect); 66 | } 67 | -------------------------------------------------------------------------------- /lib/agent/triggers/connection/index.js: -------------------------------------------------------------------------------- 1 | var join = require('path').join, 2 | base_path = join(__dirname, '..', '..'), 3 | hooks = require(join(base_path, 'hooks')), 4 | network = require(join(base_path, 'providers', 'network')), 5 | Emitter = require('events').EventEmitter; 6 | 7 | var emitter, 8 | status, // either connected or disconnected 9 | checking = false; 10 | 11 | var timer, 12 | attempt = 0, 13 | attempts_delays = [ 3, 3, 5, 10, 20, 30, 60, 2*60 ]; 14 | 15 | var check_status = function() { 16 | if (checking) return; 17 | checking = true; 18 | 19 | network.get_connection_status(function(new_status) { 20 | checking = false; 21 | 22 | // If there's a disconnected event triggered, the connection is checked on time intervals 23 | if (new_status != 'connected') { 24 | var index = attempt; 25 | if (attempt >= attempts_delays.length - 1) index = attempts_delays.length - 1; 26 | timer = setTimeout(check_status, attempts_delays[index] * 1000) 27 | attempt++; 28 | } else { 29 | attempt = 0; 30 | } 31 | 32 | if (new_status != status) { 33 | hooks.trigger(new_status); 34 | // trigger directly the event instead of emitting it to the actions manager 35 | status = new_status; 36 | } 37 | }); 38 | } 39 | 40 | exports.start = function(opts, cb) { 41 | check_status(); 42 | hooks.on('network_state_changed', () => { 43 | clearTimeout(timer); 44 | attempt = 0; 45 | check_status(); 46 | }); 47 | // Connection Heartbeat 48 | // todo @lemavri Dinamically change interval from 49 | // 15-60 seconds if status remains. Reset otherwise 50 | 51 | emitter = new Emitter(); 52 | cb(null, emitter) 53 | } 54 | 55 | exports.stop = function(cb) { 56 | hooks.remove('network_state_changed', check_status); 57 | if (emitter) { 58 | emitter.removeAllListeners(); 59 | emitter = null; 60 | } 61 | } 62 | 63 | // by leaving empty this, we make sure that the connected/disconnected 64 | // events are not captured by the actions manager, and not reported 65 | // as trigger events to the servers. 66 | // exports.events = [ 'connected', 'disconnected' ]; 67 | exports.events = []; 68 | -------------------------------------------------------------------------------- /lib/agent/triggers/location/lib/latlng.js: -------------------------------------------------------------------------------- 1 | /* 2 | Latitude/longitude spherical geodesy formulae & scripts (c) Chris Veness 2002-2011 3 | www.movable-type.co.uk/scripts/latlong.html 4 | */ 5 | 6 | var LatLon = function(lat, lon, rad) { 7 | if (typeof(rad) == 'undefined') rad = 6371; // earth's mean radius in km 8 | // only accept numbers or valid numeric strings 9 | this._lat = typeof(lat)=='number' ? lat : typeof(lat)=='string' && lat.trim()!='' ? +lat : NaN; 10 | this._lon = typeof(lon)=='number' ? lon : typeof(lon)=='string' && lon.trim()!='' ? +lon : NaN; 11 | this._radius = typeof(rad)=='number' ? rad : typeof(rad)=='string' && trim(lon)!='' ? +rad : NaN; 12 | } 13 | 14 | LatLon.prototype.distanceTo = function(point, precision) { 15 | // default 4 sig figs reflects typical 0.3% accuracy of spherical model 16 | if (typeof precision == 'undefined') precision = 4; 17 | 18 | var R = this._radius; 19 | var lat1 = toRad(this._lat), lon1 = toRad(this._lon); 20 | var lat2 = toRad(point._lat), lon2 = toRad(point._lon); 21 | var dLat = lat2 - lat1; 22 | var dLon = lon2 - lon1; 23 | 24 | var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 25 | Math.cos(lat1) * Math.cos(lat2) * 26 | Math.sin(dLon/2) * Math.sin(dLon/2); 27 | var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 28 | var d = R * c; 29 | return toPrecisionFixed(d, precision); 30 | } 31 | 32 | var toRad = function(number) { 33 | return number * Math.PI / 180; 34 | } 35 | 36 | var toPrecisionFixed = function(number, precision) { 37 | if (isNaN(number)) return 'NaN'; 38 | var numb = number < 0 ? -number : number; // can't take log of -ve number... 39 | var sign = number < 0 ? '-' : ''; 40 | 41 | if (numb == 0) { // can't take log of zero, just format with precision zeros 42 | var n = '0.'; 43 | while (precision--) n += '0'; 44 | return n 45 | } 46 | 47 | var scale = Math.ceil(Math.log(numb)*Math.LOG10E); // no of digits before decimal 48 | var n = String(Math.round(numb * Math.pow(10, precision-scale))); 49 | if (scale > 0) { // add trailing zeros & insert decimal as required 50 | l = scale - n.length; 51 | while (l-- > 0) n = n + '0'; 52 | if (scale < n.length) n = n.slice(0,scale) + '.' + n.slice(scale); 53 | } else { // prefix decimal and leading zeros if required 54 | while (scale++ < 0) n = '0' + n; 55 | n = '0.' + n; 56 | } 57 | return sign + n; 58 | } 59 | 60 | module.exports = LatLon; -------------------------------------------------------------------------------- /lib/agent/triggers/location/test_latlng.js: -------------------------------------------------------------------------------- 1 | var LatLon = require('./lib/latlng'), 2 | logger = require('./../../../common').logger;; 3 | 4 | function calculateDistance(latlng1, latlng2){ 5 | 6 | var p1 = new LatLon(latlng1[0], latlng1[1]); 7 | var p2 = new LatLon(latlng2[0], latlng2[1]); 8 | var dist = p1.distanceTo(p2); 9 | 10 | logger.info(p1); 11 | logger.info(p2); 12 | logger.info(dist); 13 | 14 | } 15 | 16 | calculateDistance([51.5136, -0.0983], [51.4778, -0.0015]); 17 | calculateDistance([-33.4240, -70.6090], [-33.4236, -70.6067]); 18 | -------------------------------------------------------------------------------- /lib/agent/triggers/network/index.js: -------------------------------------------------------------------------------- 1 | var triggers = require('os-triggers'), 2 | join = require('path').join, 3 | base_path = join(__dirname, '..', '..'), 4 | hooks = require(join(base_path, 'hooks')), 5 | providers = require(join(base_path, 'providers')), 6 | provider = require(join(base_path, 'providers', 'network')), 7 | Emitter = require('events').EventEmitter; 8 | 9 | var emitter, 10 | current = {}, 11 | checking = {}; 12 | 13 | var get_current = (list) => { 14 | list.forEach(field => { 15 | providers.get(field, (err, data) => { 16 | // console.log(field + ' -> ' + data); 17 | current[field] = data; 18 | }) 19 | }) 20 | } 21 | 22 | var check_if_changed = (field, event) => { 23 | 24 | if (checking[field] || !current[field]) return; 25 | 26 | var done = (err) => { 27 | checking[field] = false; 28 | } 29 | 30 | checking[field] = true; 31 | providers.get(field, (err, data) => { 32 | // emitter may be null if trigger is stopped while getting data 33 | if (err || !data || !emitter) return done(err); 34 | 35 | // console.log(field + ' -> ' + data); 36 | if (current[field] != data) 37 | emitter.emit(event, data); 38 | 39 | current[field] = data; 40 | done() 41 | }); 42 | }; 43 | 44 | exports.start = (opts, cb) => { 45 | setTimeout(() => { 46 | triggers.watch('network', (err, network) => { 47 | if (err) return cb(err); 48 | 49 | network.on('state_changed', function(info) { 50 | setTimeout(() => { 51 | hooks.trigger('network_state_changed'); // for connection watcher 52 | 53 | check_if_changed('private_ip', 'private_ip_changed'); 54 | check_if_changed('public_ip', 'public_ip_changed'); 55 | }, 200); // wait a sec so IP gets assigned 56 | }); 57 | 58 | hooks.on('connected', () => { 59 | setTimeout(() => { 60 | check_if_changed('active_access_point_name', 'ssid_changed'); 61 | check_if_changed('active_access_point_mac', 'mac_address_changed'); 62 | }, 500) // wait for an updated data query 63 | }); 64 | 65 | emitter = new Emitter(); 66 | cb(null, emitter); 67 | }); 68 | get_current(['active_access_point_name', 'private_ip', 'active_access_point_mac', 'public_ip']); 69 | }, 500); 70 | // get current SSID name and private ip so we can compare afterwards 71 | }; 72 | 73 | exports.stop = () => { 74 | triggers.unwatch('network'); 75 | hooks.remove('connected'); 76 | if (emitter) { 77 | emitter.removeAllListeners(); 78 | emitter = null; 79 | } 80 | }; 81 | 82 | exports.events = [ 'ssid_changed', 'private_ip_changed', 'mac_address_changed', 'public_ip_changed']; 83 | -------------------------------------------------------------------------------- /lib/agent/triggers/power/index.js: -------------------------------------------------------------------------------- 1 | var triggers = require('os-triggers'), 2 | join = require('path').join, 3 | base_path = join(__dirname, '..', '..'), 4 | os_name = process.platform.replace('win32', 'windows').replace('darwin', 'mac'), 5 | status = require('./../status'), 6 | providers = require(join(base_path, 'providers')), 7 | Emitter = require('events').EventEmitter; 8 | 9 | var emitter, 10 | attempt = 0, 11 | checking = false, 12 | previous = {}; 13 | 14 | var check_battery_status = (first) => { 15 | 16 | providers.get('battery_status', (err, current) => { 17 | if (err || !emitter) return; 18 | 19 | // console.log('Current: ' + current.state); 20 | // console.log('Previous: ' + previous.state); 21 | 22 | if (first) return previous = current; 23 | 24 | // On mac we check 4 more times the battery status because of the realization time. 25 | if ((previous.state == current.state || (previous.state != 'discharging' && current.state != 'discharging')) && os_name == 'mac') { 26 | if (attempt == 4) { 27 | checking = false; 28 | attempt = 0; 29 | return; 30 | } 31 | attempt ++; 32 | return setTimeout(check_battery_status, 4000); 33 | } 34 | 35 | checking = false; 36 | attempt = 0; 37 | // Update battery status for next request 38 | status.set_status('battery_status', current) 39 | 40 | if ((previous.state == 'discharging' || !previous.state) && current.state != 'discharging') { 41 | if (previous.state) emitter.emit('started_charging'); 42 | } 43 | 44 | else if (current.state == 'discharging' && (previous.state != 'discharging' || !previous.state)) { 45 | if (previous.state) emitter.emit('stopped_charging'); 46 | } 47 | 48 | previous = current; 49 | }); 50 | 51 | }; 52 | 53 | exports.start = (opts, cb) => { 54 | 55 | triggers.watch('power', (err, power) => { 56 | if (err) return cb(err); 57 | 58 | power.on('state_changed', (info) => { 59 | if (checking) return; 60 | checking = true; 61 | setTimeout(check_battery_status, 2000); 62 | }); 63 | 64 | check_battery_status(true); 65 | emitter = new Emitter(); 66 | cb(null, emitter); 67 | }); 68 | 69 | }; 70 | 71 | exports.stop = () => { 72 | triggers.unwatch('power'); 73 | if (emitter) { 74 | emitter.removeAllListeners(); 75 | emitter = null; 76 | } 77 | }; 78 | 79 | exports.events = [ 'low_battery', 'started_charging', 'stopped_charging' ]; 80 | -------------------------------------------------------------------------------- /lib/agent/utils/Prey.app/Contents/CodeResources: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/utils/Prey.app/Contents/CodeResources -------------------------------------------------------------------------------- /lib/agent/utils/Prey.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 23A344 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | Prey 11 | CFBundleIconFile 12 | AppIcon 13 | CFBundleIconName 14 | AppIcon 15 | CFBundleIdentifier 16 | com.preypatchmojave 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | Prey 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | 3.1 25 | CFBundleSupportedPlatforms 26 | 27 | MacOSX 28 | 29 | CFBundleVersion 30 | 2019101101 31 | DTCompiler 32 | com.apple.compilers.llvm.clang.1_0 33 | DTPlatformBuild 34 | 35 | DTPlatformName 36 | macosx 37 | DTPlatformVersion 38 | 14.0 39 | DTSDKBuild 40 | 23A334 41 | DTSDKName 42 | macosx14.0 43 | DTXcode 44 | 1500 45 | DTXcodeBuild 46 | 15A240d 47 | LSMinimumSystemVersion 48 | 10.13 49 | LSUIElement 50 | 51 | NSCameraUsageDescription 52 | Prey utilizes the device's camera to take pictures when you request evidence reports. 53 | NSLocationUsageDescription 54 | When Prey cannot get the Wifi MAC addresses, it will use the location of the device to track it. 55 | NSLocationAlwaysUsageDescription 56 | When Prey cannot get the Wifi MAC addresses, it will use the location of the device to track it. 57 | NSLocationWhenInUseUsageDescription 58 | When Prey cannot get the Wifi MAC addresses, it will use the location of the device to track it. 59 | NSMainNibFile 60 | MainView 61 | NSPrincipalClass 62 | NSApplication 63 | 64 | 65 | -------------------------------------------------------------------------------- /lib/agent/utils/Prey.app/Contents/MacOS/Prey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/utils/Prey.app/Contents/MacOS/Prey -------------------------------------------------------------------------------- /lib/agent/utils/logo.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | ' ████████████████ ████████████████ ████████████████ ██ ██', 3 | ' ██ ██ ██ ██ ██ ██ ██', 4 | ' ██ ██ ██ ████████████████ ██ ██', 5 | ' ██ ██ ██ ██ ██ ██', 6 | ' ████████████████ ██ ████████████████ ████████████████', 7 | ' ██ ██', 8 | ' ██ ████████████████', 9 | ].join('\n'); 10 | -------------------------------------------------------------------------------- /lib/agent/utils/openwebbrowser.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | webbrowser=`xdg-settings get default-web-browser` 4 | if [ "$webbrowser" == "firefox.desktop" ]; then 5 | firefox -CreateProfile Prey 6 | firefox -P Prey -url $1 7 | else 8 | xdg-open $1 9 | fi -------------------------------------------------------------------------------- /lib/agent/utils/pidfile.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | exports.remove = (pidFile, cb) => { 4 | fs.unlink(pidFile, (err) => { 5 | if (typeof cb !== 'function') return; 6 | cb(err); 7 | }); 8 | }; 9 | 10 | // eslint-disable-next-line consistent-return 11 | exports.checkPidPermissions = (pid, cb) => { 12 | try { 13 | process.kill(pid, 0); 14 | cb(null); 15 | } catch (e) { 16 | if (e.code === 'EPERM') { 17 | if (typeof cb === 'function') return cb(null); 18 | } 19 | if (typeof cb === 'function') cb(e); // probaby e.code == 'ESRCH', not really running 20 | } 21 | }; 22 | 23 | exports.readFileRaw = (file, cb) => { 24 | // eslint-disable-next-line consistent-return 25 | fs.readFile(file, (errRead, str) => { 26 | if (errRead) return cb(errRead); 27 | cb(null, str); 28 | }); 29 | }; 30 | 31 | exports.parsePid = (str, cb) => { 32 | const pid = parseInt(str, 10); 33 | cb(null, pid); 34 | }; 35 | 36 | exports.readFile = (file, cb) => { 37 | // eslint-disable-next-line consistent-return 38 | exports.readFileRaw(file, (err, str) => { 39 | if (err) return cb(err); 40 | // eslint-disable-next-line consistent-return 41 | exports.parsePid(str, (errParse, pid) => { 42 | if (errParse) return cb(errParse); 43 | cb(null, pid); 44 | }); 45 | }); 46 | }; 47 | 48 | exports.statFile = (file, cb) => { 49 | // eslint-disable-next-line consistent-return 50 | fs.stat(file, (err, stat) => { 51 | if (err) return cb(err); 52 | 53 | cb(null, stat); 54 | }); 55 | }; 56 | 57 | exports.read = (file, cb) => { 58 | // eslint-disable-next-line consistent-return 59 | exports.statFile(file, (errStat, stat) => { 60 | if (errStat) return cb(errStat); 61 | 62 | // eslint-disable-next-line consistent-return 63 | exports.readFile(file, (errRead, pid) => { 64 | if (errRead) return cb(errRead); 65 | 66 | const obj = { stat, pid }; 67 | 68 | // eslint-disable-next-line consistent-return 69 | exports.checkPidPermissions(pid, (errPerm) => { 70 | if (errPerm) return cb(errPerm); 71 | 72 | cb(null, obj); 73 | }); 74 | }); 75 | }); 76 | }; 77 | 78 | exports.store = (file, callback) => { 79 | // eslint-disable-next-line consistent-return 80 | exports.read(file, (err, running) => { 81 | if (running) return callback(err, running); 82 | // if all was good, then callback(err) will be null 83 | fs.writeFile(file, process.pid.toString(), callback); 84 | }); 85 | }; 86 | -------------------------------------------------------------------------------- /lib/agent/utils/prey-actions.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 24D70 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | prey-actions 11 | CFBundleIdentifier 12 | com.prey.actions 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | prey-actions 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.1 21 | CFBundleSupportedPlatforms 22 | 23 | MacOSX 24 | 25 | CFBundleVersion 26 | 1 27 | DTCompiler 28 | com.apple.compilers.llvm.clang.1_0 29 | DTPlatformBuild 30 | 24E241 31 | DTPlatformName 32 | macosx 33 | DTPlatformVersion 34 | 15.4 35 | DTSDKBuild 36 | 24E241 37 | DTSDKName 38 | macosx15.4 39 | DTXcode 40 | 1630 41 | DTXcodeBuild 42 | 16E140 43 | LSApplicationCategoryType 44 | public.app-category.utilities 45 | LSMinimumSystemVersion 46 | 10.15 47 | NSHumanReadableCopyright 48 | Copyright © 2023 Prey, Inc. All rights reserved. 49 | NSMainNibFile 50 | MainMenu 51 | NSPrincipalClass 52 | NSApplication 53 | NSSupportsAutomaticTermination 54 | 55 | NSSupportsSuddenTermination 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /lib/agent/utils/prey-actions.app/Contents/MacOS/prey-actions: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/utils/prey-actions.app/Contents/MacOS/prey-actions -------------------------------------------------------------------------------- /lib/agent/utils/prey-actions.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /lib/agent/utils/prey-actions.app/Contents/Resources/Assets.car: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/utils/prey-actions.app/Contents/Resources/Assets.car -------------------------------------------------------------------------------- /lib/agent/utils/prey-actions.app/Contents/Resources/Base.lproj/MainMenu.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/utils/prey-actions.app/Contents/Resources/Base.lproj/MainMenu.nib -------------------------------------------------------------------------------- /lib/agent/utils/prey-actions.app/Contents/Resources/bg-lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/utils/prey-actions.app/Contents/Resources/bg-lock.png -------------------------------------------------------------------------------- /lib/agent/utils/prey-actions.app/Contents/Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/utils/prey-actions.app/Contents/Resources/en.lproj/Localizable.strings -------------------------------------------------------------------------------- /lib/agent/utils/prey-actions.app/Contents/Resources/es.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/utils/prey-actions.app/Contents/Resources/es.lproj/Localizable.strings -------------------------------------------------------------------------------- /lib/agent/utils/prey-actions.app/Contents/Resources/es.lproj/MainMenu.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/agent/utils/prey-actions.app/Contents/Resources/es.lproj/MainMenu.nib -------------------------------------------------------------------------------- /lib/agent/utils/storage/database.js: -------------------------------------------------------------------------------- 1 | const sqlite3 = require('sqlite3').verbose(); 2 | const { promisify } = require('util'); 3 | const { exec } = require('child_process'); 4 | 5 | const createDatabase = (dbPath, cb) => { 6 | // eslint-disable-next-line consistent-return 7 | const db = new sqlite3.Database(dbPath, (err) => { 8 | if (err) return cb(err); 9 | cb(null, db); 10 | }); 11 | }; 12 | 13 | const backupDatabase = (db, path, cb) => { 14 | const backupPreyDb = db.backup(path); 15 | cb(backupPreyDb); 16 | }; 17 | 18 | const stepDatabase = (db, cb) => { 19 | // eslint-disable-next-line consistent-return 20 | db.step(-1, (err) => { 21 | if (err) return cb(new Error(err)); 22 | cb(null); 23 | }); 24 | }; 25 | 26 | const closeDatabase = (db, backupTempDB, cb) => { 27 | // eslint-disable-next-line consistent-return 28 | db.finish((errFinished) => { 29 | if (errFinished) return cb(new Error(errFinished)); 30 | // eslint-disable-next-line consistent-return 31 | backupTempDB.close((err) => { 32 | if (err) return cb(err); 33 | cb(null); 34 | }); 35 | }); 36 | }; 37 | 38 | const deleteDatabase = (backupDBPath, cb) => { 39 | exec(`del /f ${backupDBPath}`, (errDelete, _stdout, stderr) => cb(errDelete, stderr)); 40 | }; 41 | 42 | const dbToJson = async (dbPath) => { 43 | let dbConn = null; 44 | try { 45 | dbConn = new sqlite3.Database(dbPath); 46 | const dbAll = promisify(dbConn.all.bind(dbConn)); 47 | const tables = await dbAll('SELECT name FROM sqlite_master WHERE type="table" AND name NOT LIKE "sqlite_%";'); 48 | if (tables.length === 0) return 'No tables found in the database.'; 49 | const databaseData = {}; 50 | const tableDataPromises = tables.map(async ({ name }) => { 51 | const rows = await dbAll(`SELECT * FROM ${name};`); 52 | databaseData[name] = rows; 53 | }); 54 | await Promise.all(tableDataPromises); 55 | return databaseData; 56 | } catch (errorVacuum) { 57 | return errorVacuum; 58 | } finally { 59 | if (dbConn) { 60 | await new Promise((resolve, reject) => { 61 | dbConn.close((errClose) => { 62 | if (errClose) return reject(errClose); 63 | return resolve(); 64 | }); 65 | }); 66 | } 67 | } 68 | }; 69 | 70 | module.exports = { 71 | createDatabase, 72 | backupDatabase, 73 | stepDatabase, 74 | closeDatabase, 75 | deleteDatabase, 76 | dbToJson, 77 | }; 78 | -------------------------------------------------------------------------------- /lib/agent/utils/storage/restore.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { join } = require('path'); 3 | const { paths } = require('../../../common').system; 4 | const { storageConst, osConst } = require('../../../constants'); 5 | 6 | exports.osName = process.platform.replace('win32', 'windows').replace('darwin', 'mac'); 7 | const dbPath = join(paths.config, 'commands.db'); 8 | const backupDBPath = join(paths.temp, 'prey', 'commands.db'); 9 | 10 | exports.verifyTempDatabase = () => fs.existsSync(backupDBPath); 11 | 12 | exports.database = require('./database'); 13 | 14 | // eslint-disable-next-line consistent-return 15 | const stepDatabaseReact = (backupPreyDb, backupTempDB, err, cb) => { 16 | if (err) return cb(err); 17 | // eslint-disable-next-line consistent-return 18 | exports.database.closeDatabase(backupPreyDb, backupTempDB, (errClosing) => { 19 | if (errClosing) { 20 | return cb(new Error(`${storageConst.BACKUP.CLOSING_ERROR}: ${errClosing}`)); 21 | } 22 | exports.database.deleteDatabase(backupDBPath, (errDelete, stderr) => { 23 | if (errDelete || stderr) return cb(new Error(`${storageConst.BACKUP.DELETING_ERROR}: ${errDelete || stderr}`)); 24 | return cb(null, `${storageConst.BACKUP.RESTORE_SUCCESS}`); 25 | }); 26 | }); 27 | }; 28 | 29 | const databaseBackUpReact = (backupTempDB, backupPreyDb, cb) => { 30 | exports.database.stepDatabase(backupPreyDb, (err) => { 31 | stepDatabaseReact(backupPreyDb, backupTempDB, err, cb); 32 | }); 33 | }; 34 | 35 | // eslint-disable-next-line consistent-return 36 | const databaseCreateReact = (err, backupTempDB, cb) => { 37 | if (err) { 38 | return cb(new Error(storageConst.SQLITE_ACCESS_ERR)); 39 | } 40 | 41 | exports.database.backupDatabase(backupTempDB, dbPath, (backupPreyDb) => { 42 | databaseBackUpReact(backupTempDB, backupPreyDb, cb); 43 | }); 44 | }; 45 | 46 | /** 47 | * Restores the database from a backup. 48 | * 49 | * @param {function} cb - The callback function to be called after the restore is complete. 50 | * @return {undefined} The callback function is called with either an error or a success message. 51 | */ 52 | // eslint-disable-next-line consistent-return 53 | exports.restore = (cb) => { 54 | try { 55 | if (exports.osName !== 'windows') return cb(`${storageConst.TITLE}: ${osConst.RESTRICTION.ONLY_WINDOWS}`); 56 | if (!exports.verifyTempDatabase()) return cb(); 57 | // eslint-disable-next-line consistent-return 58 | exports.database.createDatabase(backupDBPath, (err, backupTempDB) => { 59 | databaseCreateReact(err, backupTempDB, cb); 60 | }); 61 | } catch (errorRestore) { 62 | cb(new Error(errorRestore)); 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /lib/agent/utils/storage/utilstorage.js: -------------------------------------------------------------------------------- 1 | const storage = require('../storage'); 2 | 3 | const updateDataDbKey = (typeDb, idName, columName, data, callback) => { 4 | try { 5 | storage.do('update', { 6 | type: typeDb, id: idName, columns: columName, values: data, 7 | }, (err) => { 8 | if (err) callback(err, null); 9 | }); 10 | } catch (e) { 11 | callback(e, null); 12 | } 13 | }; 14 | 15 | const saveDataDbKey = (typeDb, columName, data, callback) => { 16 | try { 17 | storage.do('set', { 18 | type: typeDb, 19 | id: columName, 20 | data: { 21 | value: data, 22 | }, 23 | }, (err) => { 24 | if (err) callback(err, null); 25 | }); 26 | } catch (e) { 27 | callback(e, null); 28 | } 29 | }; 30 | 31 | const getDataDbKey = (whatToGet, callback) => { 32 | try { 33 | storage.do('query', { type: 'keys', column: 'id', data: whatToGet }, (err, stored) => { 34 | if (err) { 35 | return callback(err, null); 36 | } 37 | if (stored && stored.length > 0) { 38 | return callback(null, stored); 39 | } 40 | return callback(null, null); 41 | }); 42 | } catch (e) { 43 | callback(e, null); 44 | } 45 | }; 46 | 47 | const saveDataWifi = (dataWifi) => { 48 | storage.do('query', { type: 'keys', column: 'id', data: 'wifiDataStored' }, (err, stored) => { 49 | if (err) return; 50 | if (stored && stored.length > 0) { 51 | let storedData = stored[0].value; 52 | 53 | if (typeof storedData === 'string') storedData = JSON.parse(storedData); 54 | if (!storedData.dataWifi) return; 55 | storedData.dataWifi.push(dataWifi); 56 | if (storedData.dataWifi.length > 200) { 57 | storedData.dataWifi = storedData.dataWifi.slice(1); 58 | } 59 | storage.do('update', { 60 | type: 'keys', id: 'wifiDataStored', columns: 'value', values: JSON.stringify(storedData), 61 | }, () => { 62 | }); 63 | } else { 64 | storage.do('set', { type: 'keys', id: 'wifiDataStored', data: { value: JSON.stringify({ dataWifi: [dataWifi] }) } }, () => { 65 | }); 66 | } 67 | }); 68 | }; 69 | 70 | const deleteDbKey = (whatToGet, callback) => { 71 | try { 72 | storage.do('del', { type: 'keys', id: whatToGet }, (errDel) => { 73 | if (errDel) return callback(errDel); 74 | return callback(null); 75 | }); 76 | } catch (e) { 77 | callback(e); 78 | } 79 | }; 80 | 81 | exports.deleteDbKey = deleteDbKey; 82 | exports.saveDataWifi = saveDataWifi; 83 | exports.getDataDbKey = getDataDbKey; 84 | exports.saveDataDbKey = saveDataDbKey; 85 | exports.updateDataDbKey = updateDataDbKey; 86 | exports.storage = storage; 87 | -------------------------------------------------------------------------------- /lib/agent/utils/utilsprey.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line consistent-return 2 | const isBoolean = (type) => { 3 | if (typeof type === 'string') { 4 | const resp = type.trim().toLowerCase(); 5 | return resp === 'true'; 6 | } 7 | if (typeof type === 'number' && type !== 1 && type !== 0) return false; 8 | return Boolean(type); 9 | }; 10 | 11 | const stringBooleanOrEmpty = (str) => { 12 | // eslint-disable-next-line no-constant-condition 13 | if (!str && str !== false) return ''; 14 | const stringStr = str.toString(); 15 | if (stringStr.localeCompare('Allow') === 0) return 'true'; 16 | if (stringStr.localeCompare('Deny') === 0) return 'false'; 17 | if (/^(true|false)$/.test(stringStr)) return stringStr; 18 | return ''; 19 | }; 20 | 21 | const splitGfromString = (str) => { 22 | const separatedG = str.split('g'); 23 | if (separatedG.length > 1) { 24 | const regex = /-?\d+/g; 25 | const matches = separatedG[1].match(regex); 26 | if (!matches) return str; 27 | return matches[0]; 28 | } 29 | return str; 30 | }; 31 | 32 | const getChannelDifFormat = (str) => { 33 | let dataSeparator = ''; 34 | const splittedStr = str.split('('); 35 | if (splittedStr.length > 1) { 36 | const trimmedStr = splittedStr[0].trim(); 37 | dataSeparator = trimmedStr; 38 | } 39 | if (dataSeparator.localeCompare('') !== 0) { 40 | return splitGfromString(dataSeparator); 41 | } 42 | return splitGfromString(str); 43 | }; 44 | 45 | const getInformationChannel = (str) => { 46 | const regex = /\d+(?= \(.*\))/; 47 | const match = str.match(regex); 48 | const number = match ? match[0] : ''; 49 | if (number.localeCompare('') === 0) { 50 | return getChannelDifFormat(str); 51 | } 52 | return number; 53 | }; 54 | 55 | const removeBackslash = (str) => { 56 | let stringData = str; 57 | if (typeof stringData === 'object') stringData = JSON.stringify(stringData); 58 | return stringData.replace(/\\/g, ''); 59 | }; 60 | 61 | exports.getChannelDifFormat = getChannelDifFormat; 62 | exports.getInformationChannel = getInformationChannel; 63 | exports.isBoolean = isBoolean; 64 | exports.stringBooleanOrEmpty = stringBooleanOrEmpty; 65 | exports.removeBackslash = removeBackslash; 66 | exports.splitGfromString = splitGfromString; 67 | -------------------------------------------------------------------------------- /lib/common.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | const { resolve } = require('path'); 3 | const program = require('commander'); 4 | 5 | const root_path = process.env.ROOT_PATH || join(__dirname, '..'); 6 | 7 | // eslint-disable-next-line import/no-dynamic-require 8 | const system = require(join(root_path, 'lib', 'system')); 9 | // eslint-disable-next-line import/no-dynamic-require 10 | const { version } = require(join(root_path, 'package')); 11 | 12 | const config_file = 'prey.conf'; 13 | const default_config_file = join(root_path, `${config_file}.default`); 14 | const config_path = program.path ? resolve(program.path) : system.paths.config; 15 | 16 | module.exports = { 17 | package: require(join(root_path, 'lib', 'package')), 18 | exceptions: require(join(root_path, 'lib', 'exceptions')), 19 | system, 20 | config_path, 21 | default_config_file, 22 | pid_file: system.tempfile_path('prey.pid'), 23 | os_name: system.os_name, 24 | os_release: system.os_release, 25 | program, 26 | root_path, 27 | version, 28 | }; 29 | -------------------------------------------------------------------------------- /lib/conf/action.js: -------------------------------------------------------------------------------- 1 | const http = require('node:http'); 2 | const { v4: uuidv4 } = require('uuid'); 3 | 4 | const shared = require('./shared'); 5 | 6 | const log = (str) => shared.log(str); 7 | 8 | const postDataNativeLocation = JSON.stringify({ 9 | body: { 10 | command: 'start', 11 | options: { 12 | name: 'native_location', 13 | }, 14 | target: 'request_permission', 15 | }, 16 | id: uuidv4(), 17 | time: (new Date()).toISOString(), 18 | type: 'action', 19 | }); 20 | 21 | const sendAction = (values, cb) => { 22 | const { key } = values; 23 | let postData; 24 | if (key.localeCompare('native_location') === 0) { 25 | postData = postDataNativeLocation; 26 | } 27 | const options = { 28 | hostname: 'localhost', 29 | port: 7738, 30 | path: '/actions', 31 | method: 'POST', 32 | headers: { 33 | 'Content-Type': 'application/json', 34 | 'Content-Length': Buffer.byteLength(postData), 35 | }, 36 | }; 37 | const req = http.request(options, (res) => { 38 | log(`STATUS: ${res.statusCode}`); 39 | log(`HEADERS: ${JSON.stringify(res.headers)}`); 40 | res.setEncoding('utf8'); 41 | res.on('data', (chunk) => { 42 | log(`BODY: ${chunk}`); 43 | }); 44 | res.on('end', () => { 45 | log('No more data in response.'); 46 | }); 47 | }); 48 | req.on('error', (e) => { 49 | log(`problem with request: ${e.message}`); 50 | return typeof cb === 'function' ? cb() : null; 51 | }); 52 | // Write data to request body 53 | req.write(postData); 54 | req.end(); 55 | return typeof cb === 'function' ? cb() : null; 56 | }; 57 | 58 | exports.sendAction = sendAction; 59 | -------------------------------------------------------------------------------- /lib/conf/gui/index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | join = require('path').join, 3 | spawn = require('child_process').spawn, 4 | common = require('./../../common'), 5 | system = common.system, 6 | shared = require('../shared'), 7 | os_name = process.platform.replace('darwin', 'mac').replace('win32', 'windows'); 8 | 9 | function log(str) { 10 | shared.log(str); 11 | } 12 | 13 | function run_detached(cmd, args, cb) { 14 | var opts = { detached: true, stdio: 'ignore' }; 15 | var child = spawn(cmd, args, opts); 16 | child.unref(); 17 | cb && cb(); 18 | }; 19 | 20 | var show_and_exit = function(force) { 21 | 22 | var args = [], 23 | gui_path = join(__dirname, os_name, 'prey-config'); 24 | 25 | if (os_name == 'windows') { 26 | gui_path = gui_path + '.exe'; 27 | } else if (os_name == 'linux') { 28 | gui_path += ((system.python_version && system.python_version >= "3.0.0") ? '3.py' : '.py'); 29 | } else { 30 | args = [gui_path.replace('prey-config', 'PreyConfig.app/Contents/MacOS/prey-config.py')]; 31 | gui_path = '/usr/bin/python'; 32 | } 33 | 34 | // pass --force param to GUI app, to skip key verification check 35 | if (force) args = args.concat(['--force']); 36 | 37 | log('Firing up config GUI!'); 38 | run_detached(gui_path, args); 39 | 40 | setTimeout(function(){ 41 | // helpers.log('Exitting...'); 42 | process.exit(0); 43 | }, 100); // make sure any edits to the config file are saved 44 | } 45 | 46 | 47 | exports.check_and_show = function(values, cb) { 48 | var force = values['-f'] === true; 49 | var old_config = (values['-c'] || values['--check-file']) && values.positional[0]; 50 | 51 | var show = function() { 52 | shared.keys.verify_current(function(err) { 53 | if (!err) // no error, meaning existing keys are valid 54 | log('Valid existing keys found. Proceeding anyway.') 55 | 56 | // if (!err && !force) 57 | // return cb(new Error('Account already set up! Run with -f/--force to continue anyway.')); 58 | 59 | if (err && err.code == 'INVALID_CREDENTIALS') 60 | shared.keys.set_api_key(''); // clears both API and device keys 61 | 62 | if (err && err.code == 'INVALID_DEVICE_KEY') 63 | shared.keys.set_device_key(''); // invalid, so clear it out 64 | 65 | show_and_exit(force); 66 | }) 67 | } 68 | 69 | if (!old_config || old_config == '' || !fs.existsSync(old_config)) 70 | return show(); 71 | 72 | // check old config file for api/device keys 73 | // returns error if empty or invalid 74 | shared.keys.retrieve_old_keys(old_config, function(err) { 75 | if (!err) 76 | log('Configuration restored from previous client!'); 77 | 78 | show(); 79 | }); 80 | } 81 | -------------------------------------------------------------------------------- /lib/conf/gui/mac/PreyConfig.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleGetInfoString 6 | PreyConfig 7 | CFBundleExecutable 8 | PreyConfig 9 | CFBundleIdentifier 10 | com.prey.config 11 | CFBundleName 12 | PreyConfig 13 | CFBundleIconFile 14 | prey.icns 15 | CFBundleShortVersionString 16 | 0.01 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundlePackageType 20 | APPL 21 | IFPkgFlagAuthorizationAction 22 | RootAuthorization 23 | IFMajorVersion 24 | 0 25 | IFMinorVersion 26 | 1 27 | 28 | 29 | -------------------------------------------------------------------------------- /lib/conf/gui/mac/PreyConfig.app/Contents/MacOS/PreyConfig: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # export PATH="$PATH:/usr/local/bin" 4 | # [ "$(whoami)" != "root" ] && prefix="sudo" 5 | $prefix /usr/bin/python "`dirname "$0"`/prey-config.py" 6 | -------------------------------------------------------------------------------- /lib/conf/gui/mac/PreyConfig.app/Contents/Resources/prey.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/mac/PreyConfig.app/Contents/Resources/prey.icns -------------------------------------------------------------------------------- /lib/conf/gui/mac/PreyConfig.app/Contents/_CodeSignature/CodeDirectory: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/mac/PreyConfig.app/Contents/_CodeSignature/CodeDirectory -------------------------------------------------------------------------------- /lib/conf/gui/mac/PreyConfig.app/Contents/_CodeSignature/CodeRequirements: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/mac/PreyConfig.app/Contents/_CodeSignature/CodeRequirements -------------------------------------------------------------------------------- /lib/conf/gui/mac/PreyConfig.app/Contents/_CodeSignature/CodeSignature: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/mac/PreyConfig.app/Contents/_CodeSignature/CodeSignature -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/agent.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/agent.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/check.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/connect.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/connect.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/controlpanel.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/controlpanel.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/controlpanel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/controlpanel.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/delay.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/delay.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/delay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/delay.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/email.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/email.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/email.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/newuser.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/newuser.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/newuser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/newuser.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/olduser.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/olduser.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/olduser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/olduser.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/secure.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/secure.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/secure.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/settings.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/settings.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/system.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/system.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/system.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/user.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/user.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/user.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/wifi.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/wifi.bmp -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/conf/wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/conf/wifi.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/prey-agent-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/prey-agent-48.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/prey-text-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/prey-text-shadow.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/prey-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/prey-text.png -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/prey.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/prey.ico -------------------------------------------------------------------------------- /lib/conf/gui/pixmaps/prey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/pixmaps/prey.png -------------------------------------------------------------------------------- /lib/conf/gui/windows/prey-config.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/conf/gui/windows/prey-config.exe -------------------------------------------------------------------------------- /lib/conf/log.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const shared = require('./shared'); 4 | const paths = require('../system/paths'); 5 | const { cp } = require('./utils/cp'); 6 | 7 | // eslint-disable-next-line camelcase 8 | const { restart_client } = require('../package'); 9 | 10 | const pathEnv = path.join(__dirname, '../../..'); 11 | const logfile = paths.log_file; 12 | 13 | const read = (file) => { 14 | const stream = fs.createReadStream(file); 15 | stream.on('data', shared.log); 16 | stream.on('error', (err) => { 17 | shared.log(err.message); 18 | }); 19 | }; 20 | 21 | // eslint-disable-next-line consistent-return 22 | exports.write = (values, cb) => { 23 | const output = values['-o'] && values.positional[0]; 24 | if (!output) return read(logfile); 25 | // eslint-disable-next-line consistent-return 26 | cp(logfile, output, (err) => { 27 | if (err) return cb(err); 28 | shared.log(`Successfully dump log contents to ${output}`); 29 | }); 30 | }; 31 | 32 | const envFileCreate = (values) => { 33 | const { value } = values; 34 | const contenido = `DEBUG=${value}`; 35 | fs.writeFileSync(`${pathEnv}/.env`, contenido); 36 | shared.log('Restarting Prey services if it\'s running'); 37 | setTimeout(() => { 38 | restart_client(); 39 | }, 5000); 40 | }; 41 | 42 | exports.envFileCreate = envFileCreate; 43 | -------------------------------------------------------------------------------- /lib/conf/shared.js: -------------------------------------------------------------------------------- 1 | var whenever = require('whenever'); 2 | module.exports = whenever('*', __dirname + '/shared'); 3 | -------------------------------------------------------------------------------- /lib/conf/shared/log.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | join = require('path').join, 3 | inspect = require('util').inspect, 4 | tmpdir = process.platform == 'win32' ? process.env.WINDIR + '\\Temp' : '/tmp'; 5 | 6 | var stream; 7 | 8 | function empty(msg) { 9 | return typeof msg == 'undefined' || msg === null || msg.toString().trim() == ''; 10 | } 11 | 12 | module.exports = function(msg) { 13 | if (empty(msg)) return; 14 | 15 | if (!stream) { 16 | if (process.stdout && process.stdout.writable) { 17 | stream = process.stdout; 18 | } else { 19 | var fallback = join(tmpdir, 'prey-config.log'); 20 | stream = fs.createWriteStream(fallback); 21 | } 22 | } 23 | 24 | if (!Buffer.isBuffer(msg) && typeof msg == 'object') 25 | msg = inspect(msg); 26 | 27 | stream.write(msg.toString() + "\n"); 28 | } 29 | -------------------------------------------------------------------------------- /lib/conf/shared/messages.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | no_config: 'Config file not found! Please run bin/prey config activate.', 3 | no_perms: 'Oops. Seems you don\'t have write permissions. Try running with sudo.', 4 | ssl_keygen_error: 'Unable to generate SSL keys:', 5 | ssl_keygen_success: 'SSL keys in place!', 6 | done_no_config: 'All done. No configurable options for driver ', 7 | setup_success: '\nPrey has been setup successfully!', 8 | first_run: 'Running Prey for the first time...', 9 | first_run_error: 'Shoot, something went wrong. Try running Prey again to see what\'s going on.', 10 | first_run_ok: 'Done! You can now close this window.\n', 11 | try_console: 'Or if you wish to play around with Prey, try the console mode: \n\n\t $ prey -d console\n', 12 | maybe_next_time: 'Ok maybe next time. Farewell!', 13 | error_creating_log_file: 'Couldn\'t create log file in ', 14 | error_storing_values: 'Could not store config values: ', 15 | connection_timeout: 'Timeout while trying to connect to server', 16 | exit_ok: 'Voila! All good.', 17 | }; 18 | -------------------------------------------------------------------------------- /lib/conf/shared/panel.js: -------------------------------------------------------------------------------- 1 | const panel = require('../../agent/control-panel'); 2 | 3 | const config = require('../../utils/configfile'); 4 | 5 | let api; 6 | 7 | const setup_api = (cb) => { 8 | const opts = config.all(); 9 | if (api) { return cb(api); } 10 | 11 | if (!opts) { 12 | console.log("Empty or outdated config file. Please run 'config activate' and retry."); 13 | return process.exit(1); 14 | } 15 | 16 | opts.try_proxy = config.getData('try_proxy'); 17 | 18 | api = panel.load_api(opts); 19 | cb(api); 20 | }; 21 | 22 | exports.verify_keys = (keys, cb) => { 23 | setup_api(() => { 24 | api.keys.verify(keys, cb); 25 | }); 26 | }; 27 | 28 | exports.authorize = (opts, cb) => { 29 | setup_api(() => { 30 | api.accounts.authorize(opts, cb); 31 | }); 32 | }; 33 | 34 | exports.signup = (data, cb) => { 35 | setup_api(() => { 36 | api.accounts.signup(data, cb); 37 | }); 38 | }; 39 | 40 | exports.link = (cb) => { 41 | panel.enabled(cb, 'cli'); 42 | }; 43 | -------------------------------------------------------------------------------- /lib/conf/tasks/clear_files_prey_temp.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'), 2 | common = require('../../common'), 3 | paths = common.system.paths, 4 | join = require('path').join, 5 | remove = require('remover'); 6 | 7 | /** 8 | * Entry point function of files deletion. 9 | * It is responsible for deleting files with prey-config 10 | * It’s called from the post-install script and applies for all OSs 11 | * To run it you must have administrator permissions 12 | * test in mac : ./prey config hooks post_install 13 | * After executing the command, the node client should continue to operate without problems. 14 | * @param {Function} cb - function 15 | */ 16 | exports.start = function (cb) { 17 | 18 | var count, 19 | last_err, 20 | files_removed = []; 21 | 22 | var done = function (err) { 23 | if (err) last_err = err; 24 | --count || finished(); 25 | } 26 | 27 | /**finish to remove files */ 28 | var finished = function () { 29 | return cb() 30 | } 31 | 32 | /** get files with prey-config */ 33 | const files_not_delete = [".DS_Store"]; 34 | 35 | var get_files_prey_in_temp = function (cb) { 36 | 37 | try { 38 | let files = fs.readdirSync(paths.temp); 39 | let files_to_delete = files.filter(x => x.includes("prey-config-")); //only remove files prey-config-%%%%% 40 | files_to_delete = files_to_delete.filter(x => !files_not_delete.includes(x) ); 41 | if (files_to_delete.length == 0) return cb(null,[]) 42 | else return cb(null, files_to_delete) 43 | } catch (err) { 44 | if (err) console.log(err); 45 | // Here you get the error when the file was not found, 46 | // but you also get any other error 47 | return cb(err); 48 | 49 | } 50 | 51 | } 52 | 53 | /** 54 | * @param {Array} files - list files to remove 55 | */ 56 | /** remove files prey-config */ 57 | var remove_files = function (files) { 58 | files.forEach(element => { 59 | let file = join(paths.temp, element); 60 | fs.unlink(file, (err) => { 61 | if (err) console.log(err); 62 | if (err) return cb(); 63 | files_removed.push(file); 64 | return done(); 65 | }) 66 | }); 67 | } 68 | 69 | get_files_prey_in_temp(function (err, files) { 70 | if (err) console.log(err); 71 | if (err) return cb(); 72 | if (files && files.length == 0) return cb(); 73 | count = files.length; 74 | remove_files(files) 75 | }) 76 | } -------------------------------------------------------------------------------- /lib/conf/tasks/clear_folders.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'), 2 | common = require('./../../common'), 3 | paths = common.system.paths, 4 | join = require('path').join, 5 | remove = require('remover'); 6 | 7 | /** 8 | * Entry point function of old folders deletion. 9 | * It is responsible for deleting folders with old versions and keeping the folder with the current version 10 | * It’s called from the post-install script and applies for all OSs 11 | * To run it you must have administrator permissions 12 | * test in mac : ./prey config hooks post_install 13 | * After executing the command, the node client should continue to operate without problems. 14 | * @param {Function} cb - function 15 | */ 16 | exports.start = function (cb) { 17 | 18 | var count, 19 | last_err, 20 | folders_removed = []; 21 | 22 | var done = function (err) { 23 | if (err) last_err = err; 24 | --count || finished(); 25 | } 26 | 27 | /**finish to remove folders */ 28 | var finished = function () { 29 | return cb() 30 | } 31 | 32 | let folder_not_delete = [".DS_Store","prey-user"] 33 | 34 | /** get folders with versions olds */ 35 | var get_folders_old_versions = function (cb) { 36 | 37 | try { 38 | let folders = fs.readdirSync(paths.versions); 39 | let folders_to_delete = folders.filter(x => x !== common.version); //only remove folders with old versions 40 | folders_to_delete = folders_to_delete.filter(x => !folder_not_delete.includes(x) ); 41 | if (folders_to_delete.length == 0) return cb(null,[]) 42 | else return cb(null, folders_to_delete) 43 | } catch (err) { 44 | if (err) console.log(err); 45 | // Here you get the error when the file was not found, 46 | // but you also get any other error 47 | return cb(err); 48 | 49 | } 50 | 51 | } 52 | 53 | /** 54 | * @param {Array} folders - folder list to remove 55 | */ 56 | /** remove olds folders */ 57 | var remove_folders = function (folders) { 58 | folders.forEach(element => { 59 | let folder = join(paths.versions, element); 60 | remove(folder, (err) => { 61 | if (err) console.log(err); 62 | if (err) return cb(); 63 | folders_removed.push(folder); 64 | return done(); 65 | }) 66 | }); 67 | } 68 | 69 | get_folders_old_versions(function (err, folders) { 70 | if (err) console.log(err); 71 | if (err) return cb(); 72 | if (folders && folders.length == 0) return cb(); 73 | count = folders.length; 74 | remove_folders(folders) 75 | }) 76 | } -------------------------------------------------------------------------------- /lib/conf/tasks/os/linux.js: -------------------------------------------------------------------------------- 1 | exports.post_install = function(cb) { 2 | cb(); 3 | }; 4 | 5 | exports.pre_uninstall = function(cb) { 6 | cb(); 7 | }; 8 | 9 | exports.post_activate = function(cb) { 10 | cb(); 11 | }; 12 | 13 | exports.deleteOsquery = (cb) => { 14 | cb(); 15 | }; -------------------------------------------------------------------------------- /lib/conf/tasks/os/mac.js: -------------------------------------------------------------------------------- 1 | const { exec } = require('child_process'); 2 | const join = require('path').join; 3 | const paths = require(join('..', '..', '..', 'system', 'paths')); 4 | 5 | exports.post_install = function(cb) { 6 | cb(); 7 | }; 8 | 9 | exports.pre_uninstall = function(cb) { 10 | cb(); 11 | }; 12 | 13 | exports.post_activate = function(cb) { 14 | cb(); 15 | }; 16 | 17 | exports.deleteOsquery = (cb) => { 18 | exec(`${paths.current}/bin/trinity --uninstall`, () => { 19 | if (cb && typeof cb !== 'undefined') cb(); 20 | }); 21 | }; -------------------------------------------------------------------------------- /lib/conf/utils/cp.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | join = require('path').join, 3 | async = require('async'); 4 | 5 | /** 6 | * Copy a single file. 7 | **/ 8 | var cp = exports.cp = function(source, target, cb) { 9 | var is = fs.createReadStream(source), 10 | os = fs.createWriteStream(target), 11 | out = 0; 12 | 13 | var done = function(err) { 14 | if (out++ > 0) return; 15 | cb(err); 16 | }; 17 | 18 | is.on('end', done); 19 | is.on('error', done); 20 | os.on('error', done); 21 | 22 | is.pipe(os); 23 | }; 24 | 25 | /** 26 | * Recursive file copy. 27 | **/ 28 | var cp_r = exports.cp_r = function(src, dst, callback) { 29 | fs.stat(src, function(err, stat) { 30 | if (stat.isDirectory()) { 31 | fs.mkdir(dst, function(err) { 32 | fs.readdir(src, function(err, files) { 33 | async.forEach(files, function(file, cb) { 34 | cp_r(join(src, file), join(dst, file), cb); 35 | }, callback); 36 | }); 37 | }); 38 | } else { 39 | cp(src, dst, callback); 40 | } 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /lib/conf/utils/run.js: -------------------------------------------------------------------------------- 1 | // run.js, by tomas pollak 2 | // 3 | // call spawn() with exec() syntax 4 | // pass opts.stdout or opts.stderr to capture 5 | // the output of the command's streams 6 | 7 | const fetchEnvVar = require('../../utils/fetch-env-var'); 8 | 9 | var path = require('path'), 10 | spawn = require('child_process').spawn; 11 | 12 | var debugging = !!fetchEnvVar('debug'); 13 | 14 | var check_error = function(code, out, err) { 15 | if (code == 0) return; 16 | 17 | var str = err || out; 18 | var error = new Error(str.trim()); 19 | error.exit_code = code; 20 | return error; 21 | } 22 | 23 | module.exports = function(cmd, opts, cb) { 24 | var out = '', 25 | err = '', 26 | args = Array.isArray(cmd) ? cmd : cmd.split(' '), 27 | bin = args.shift(); 28 | 29 | if (!opts.cwd && bin[0] == '/') 30 | opts.cwd = path.dirname(bin); 31 | 32 | if (debugging) { 33 | console.log(bin); 34 | console.log(args); 35 | } 36 | 37 | var child = spawn(bin, args, opts); 38 | 39 | child.stdout.on('data', function(data) { 40 | out += data; 41 | if (opts.stdout && opts.stdout.writable) 42 | opts.stdout.write(data); 43 | }); 44 | 45 | child.stderr.on('data', function(data) { 46 | err += data; 47 | if (opts.stderr && opts.stderr.writable) 48 | opts.stderr.write(data); 49 | }); 50 | 51 | child.on('error', function(err) { 52 | if (opts.stderr && opts.stderr.writable) 53 | opts.stderr.write(err.toString()); 54 | }); 55 | 56 | child.on('exit', function(code) { 57 | var error = check_error(code, out, err); 58 | cb && cb(error, out, err); 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /lib/conf/utils/run_synced.js: -------------------------------------------------------------------------------- 1 | var util = require('util'), 2 | spawn = require('child_process').spawn; 3 | 4 | module.exports = function(cmd, args, opts, cb) { 5 | 6 | var opts = opts || {}; 7 | 8 | // set detached so that when running from an already-detached process we don't 9 | // get a new console window popping up. 10 | opts.detached = true; 11 | 12 | var timer, 13 | finished, 14 | child = spawn(cmd, args, opts); 15 | 16 | var print = function(str) { 17 | if (process.stdout.writable) 18 | console.log(str); 19 | } 20 | 21 | var done = function(e, code) { 22 | if (timer) clearTimeout(timer); 23 | if (finished) return; 24 | 25 | print('Exited with code ' + code); 26 | finished = true; 27 | cb(e, code); 28 | } 29 | 30 | child.stdout.on('data', function(data){ 31 | print(data.toString().replace(/\n$/, '')); 32 | }) 33 | 34 | child.stderr.on('data', function(data){ 35 | print(data.toString().trim()); 36 | }) 37 | 38 | child.on('error', function(err) { 39 | if (err == 'ENOENT') 40 | err.message = 'ENOENT - Command not found: ' + cmd; 41 | 42 | done(err); 43 | }) 44 | 45 | child.on('exit', function(code) { 46 | done(null, code); 47 | }); 48 | 49 | // don't allow synced processes to run for more than a minute 50 | timer = setTimeout(function(){ 51 | if (!child.exitCode) 52 | child.kill(); 53 | }, 60 * 1000); 54 | } 55 | -------------------------------------------------------------------------------- /lib/conf/versions.js: -------------------------------------------------------------------------------- 1 | var shared = require('./shared'), 2 | log = shared.log; 3 | 4 | exports.current = function(values, cb) { 5 | var curr = shared.version_manager.current(); 6 | if (curr) log(curr); 7 | } 8 | 9 | exports.this = function(values, cb) { 10 | var ver = shared.version_manager.this(); 11 | if (ver) log(ver); 12 | } 13 | 14 | exports.list = function(values, cb) { 15 | var list = shared.version_manager.list(); 16 | if (list) log(list.join('\n')); 17 | }; 18 | 19 | exports.set = function(values, cb) { 20 | var version = values.version; 21 | if (!version) return cb(new Error('Version not passed.')); 22 | 23 | shared.version_manager.set_current(version, cb); 24 | } -------------------------------------------------------------------------------- /lib/constants/actions.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | SYNC_SETTINGS: { 3 | INVALID_RESPONSE: 'Invalid response from API', 4 | RESPONSE_NOT_FOUND: 'Reponse settings not found', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /lib/constants/index.js: -------------------------------------------------------------------------------- 1 | exports.storageConst = require('./storage'); 2 | exports.osConst = require('./os'); 3 | -------------------------------------------------------------------------------- /lib/constants/os.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | RESTRICTION: { 3 | ONLY_WINDOWS: 'Only for Windows', 4 | ONLY_MACOS: 'Only for MacOS', 5 | ONLY_UBUNTU: 'Only for Ubuntu', 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /lib/constants/storage.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | TITLE: 'STORAGE', 3 | SQLITE_ACCESS_ERR: 'Access denied to commands database, must run agent as prey user', 4 | BACKUP: { 5 | CLOSING_ERROR: 'After restoring, there was an error closing backup db', 6 | DELETING_ERROR: 'There was an error deleting backup db', 7 | RESTORE_SUCCESS: 'Restore successfully', 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /lib/exceptions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable global-require */ 2 | /* eslint-disable consistent-return */ 3 | const client = require('needle'); 4 | 5 | const fetEnvVAr = require('./utils/fetch-env-var'); 6 | 7 | const host = fetEnvVAr('debug') ? 'https://exceptions.preyhq.com' : 'https://exceptions.preyproject.com'; 8 | 9 | exports.send = (err, cb) => { 10 | const { release } = require('os'); 11 | const { version } = require('./common'); 12 | const keys = require('./agent/control-panel/api/keys'); 13 | // prevent exceptions from being sent when running tests 14 | if (process.env.TESTING) return cb && cb(); 15 | if (!(err instanceof Error)) return cb && cb(new Error('Not an error.')); 16 | 17 | const data = { 18 | message: err.message, 19 | backtrace: err.stack, 20 | deviceKey: keys.get().device, 21 | cwd: process.cwd(), 22 | language: 'node', 23 | version: process.version, 24 | framework: `Prey/${version}`, 25 | platform: process.platform, 26 | release: release(), 27 | user: process.env.USER || process.env.LOGNAME, 28 | args: process.argv, 29 | env: process.env, 30 | gid: process.getgid && process.getgid(), 31 | uid: process.getuid && process.getuid(), 32 | pid: process.pid, 33 | memory: process.memoryUsage(), 34 | }; 35 | 36 | client.post( 37 | host, 38 | data, 39 | { 40 | content_type: 'application/json', 41 | timeout: 4500, 42 | }, 43 | (errPost) => cb && cb(errPost), 44 | ); 45 | }; 46 | -------------------------------------------------------------------------------- /lib/system/linux/paths.js: -------------------------------------------------------------------------------- 1 | exports.bin = 'prey'; 2 | exports.config = '/etc/prey'; 3 | exports.temp = '/tmp'; 4 | exports.log = '/var/log'; 5 | exports.log_file = exports.log + '/prey.log'; 6 | exports.log_restarts = exports.log + '/prey_restarts.log'; 7 | -------------------------------------------------------------------------------- /lib/system/mac/airport.js: -------------------------------------------------------------------------------- 1 | var exec = require('child_process').exec; 2 | var network_setup_cmd = '/usr/sbin/networksetup'; 3 | 4 | function more_descriptive_error(err, out) { 5 | err.message = 'Unable to reconnect. ' + err.message; 6 | if (out && out.toString().trim() != '') 7 | err.message += ' ' + out; 8 | 9 | return err; 10 | } 11 | 12 | exports.reconnect = function(done) { 13 | 14 | var network_service, 15 | airport_name = '', 16 | providers = require('./../../agent/providers'); 17 | 18 | var set_airport_names = function(osx_version) { 19 | network_service = "AirPort"; 20 | 21 | if (parseFloat(osx_version) >= 10.7){ 22 | network_service = 'Wi-Fi'; 23 | airport_name = 'en1'; 24 | } else if(parseFloat(osx_version) > 10.6){ 25 | airport_name = 'AirPort'; 26 | } 27 | } 28 | 29 | var toggle_airport = function(direction, cb) { 30 | var cmd = [network_setup_cmd, '-setnetworkserviceenabled', network_service, direction].join(' '); 31 | exec(cmd, function(err, out) { 32 | if (err) return cb(err, out); 33 | 34 | var cmd = [network_setup_cmd, '-setairportpower', airport_name, direction].join(' '); 35 | exec(cmd, cb) 36 | }) 37 | } 38 | 39 | var connect_to_access_point = function(ap, cb) { 40 | var cmd = [network_setup_cmd, '-setairportnetwork', airport_name, ap.ssid].join(' '); 41 | exec(cmd, cb); 42 | } 43 | 44 | // logger.debug('Getting list of open Wifi access points...'); 45 | providers.get('open_access_points_list', function(err, list) { 46 | if (err || !list[0]) return done(err || new Error('No open access point found.')); 47 | 48 | require('./').get_os_version(function(err, version) { 49 | if (err) return done(err); // this shouldn't fail 50 | 51 | set_airport_names(version); 52 | 53 | // logger.debug('Toggling Airport off...'); 54 | toggle_airport('off', function(err, out) { 55 | if (err) return done(more_descriptive_error(err, out)); 56 | 57 | // logger.debug('Toggling Airport back on...'); 58 | toggle_airport('on', function(err, out) { 59 | if (err) return done(more_descriptive_error(err, out)); 60 | 61 | // logger.debug('Connecting to ' + list[0] + '...'); 62 | connect_to_access_point(list[0], done); 63 | }); 64 | 65 | }); 66 | 67 | }); 68 | 69 | }); 70 | 71 | } 72 | -------------------------------------------------------------------------------- /lib/system/mac/paths.js: -------------------------------------------------------------------------------- 1 | exports.bin = 'prey'; 2 | exports.config = '/etc/prey'; 3 | exports.temp = '/tmp'; 4 | exports.log = '/var/log'; 5 | exports.log_file = exports.log + '/prey.log'; 6 | exports.log_restarts = exports.log + '/prey_restarts.log'; 7 | -------------------------------------------------------------------------------- /lib/system/paths.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const os_name = process.platform.replace('darwin', 'mac').replace('win32', 'windows'); 5 | const paths = require(path.join(__dirname, os_name, 'paths')); 6 | 7 | const package_path = path.resolve(__dirname, '..', '..'); 8 | 9 | module.exports = paths; 10 | paths.package = package_path; 11 | paths.install = package_path; 12 | paths.current = package_path; 13 | 14 | // check if parent path directory is called 'versions'. if not, then we assume 15 | // this was installed on a static location (eg. via apt-get), which means we 16 | // can't keep different versions. 17 | 18 | const package_parent_path = fs.realpathSync(path.resolve(package_path, '..')); 19 | 20 | if (path.basename(package_path) == 'current') { // not symlinked (XP and below) 21 | paths.current = package_path; // C:\Windows\Prey\Current 22 | paths.install = package_parent_path; // C:\Windows\Prey 23 | paths.versions = path.join(paths.install, 'versions'); 24 | paths.package = path.join(paths.versions, require('../../package.json').version); 25 | } else if (path.basename(package_parent_path) == 'versions') { 26 | paths.install = path.resolve(package_parent_path, '..'); 27 | paths.current = path.join(paths.install, 'current'); 28 | paths.versions = path.join(paths.install, 'versions'); 29 | } 30 | 31 | // either /usr/local/lib/prey/versions/0.1.2/bin/prey 32 | // or /usr/local/lib/prey/bin/prey 33 | paths.package_bin = path.join(paths.package, 'bin', paths.bin); 34 | 35 | // either /usr/local/lib/prey/current/bin/prey 36 | // or /usr/local/lib/prey/bin/prey 37 | paths.current_bin = path.join(paths.current, 'bin', paths.bin); 38 | -------------------------------------------------------------------------------- /lib/system/utils/runner.js: -------------------------------------------------------------------------------- 1 | // This script lets us call programs as a local user rather than root. 2 | // Usage: ./runner.js [user_name] [command] [arg1] [arg2] [arg3] 3 | 4 | var cp = require('child_process') 5 | exec = cp.exec, 6 | spawn = cp.spawn, 7 | args = process.argv, 8 | sudo_bin = '/usr/bin/sudo'; 9 | 10 | args.shift() && args.shift(); 11 | 12 | var run_as = args.shift(), 13 | command = args.shift(); 14 | 15 | if (!run_as || !command) { 16 | console.log('Usage: runner.js [user_name] [command] '); 17 | process.exit(1); 18 | } 19 | 20 | // console.log('Current uid: ' + process.getuid()); 21 | 22 | var run_command = function(command, args){ 23 | 24 | // console.log("Running " + command + " with uid " + process.getuid()); 25 | 26 | var opts = { env: process.env } 27 | 28 | if (process.platform == 'linux' && !opts.env.DISPLAY) 29 | opts.env.DISPLAY = ':0'; // so it uses active display 30 | 31 | var child = spawn(command, args, opts); 32 | 33 | child.stdout.pipe(process.stdout); 34 | child.stderr.pipe(process.stderr); 35 | 36 | child.on('exit', function(code){ 37 | setTimeout(function(){ 38 | process.exit(code); 39 | }, 10) 40 | }) 41 | 42 | process.on('SIGTERM', function(){ 43 | child.kill('SIGTERM'); 44 | }) 45 | 46 | process.on('SIGINT', function(){ 47 | child.kill('SIGINT'); 48 | }) 49 | 50 | } 51 | 52 | var safe_escape = function(str) { 53 | return str.replace(/[\"\`\$\|]/g, "\\$&"); 54 | } 55 | 56 | try { 57 | process.setuid(run_as); 58 | // console.log('New uid: ' + process.getuid()); 59 | } catch (err) { 60 | if (process.platform != 'win32') { 61 | args = args.map(function(a){ return safe_escape(a); }) 62 | command = ['"' + command].concat(args).join('" "') + '"'; 63 | args = ['-n', 'su', run_as, '-c', command]; 64 | command = sudo_bin; 65 | } 66 | } 67 | 68 | run_command(command, args); 69 | -------------------------------------------------------------------------------- /lib/system/windows/bin/autowc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/system/windows/bin/autowc.exe -------------------------------------------------------------------------------- /lib/system/windows/bin/autowcxp.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/system/windows/bin/autowcxp.exe -------------------------------------------------------------------------------- /lib/system/windows/bin/safexec.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/system/windows/bin/safexec.exe -------------------------------------------------------------------------------- /lib/system/windows/bin/updater.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/system/windows/bin/updater.exe -------------------------------------------------------------------------------- /lib/system/windows/bin/wapi.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/system/windows/bin/wapi.dll -------------------------------------------------------------------------------- /lib/system/windows/bin/wlanscan.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/system/windows/bin/wlanscan.exe -------------------------------------------------------------------------------- /lib/system/windows/bin/wpxsvc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/system/windows/bin/wpxsvc.exe -------------------------------------------------------------------------------- /lib/system/windows/bin/wpxsvc_old.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/system/windows/bin/wpxsvc_old.exe -------------------------------------------------------------------------------- /lib/system/windows/bin/wzcapis.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/lib/system/windows/bin/wzcapis.dll -------------------------------------------------------------------------------- /lib/system/windows/paths.js: -------------------------------------------------------------------------------- 1 | exports.bin = 'prey.cmd'; 2 | exports.config = process.env.WINDIR + '\\Prey'; // __dirname + '/../../../' 3 | exports.temp = process.env.WINDIR + '\\Temp'; 4 | exports.log = exports.config; 5 | exports.log_file = exports.log + '\\prey.log'; 6 | exports.log_restarts = exports.log + '\\prey_restarts.log'; -------------------------------------------------------------------------------- /lib/system/windows/registry.js: -------------------------------------------------------------------------------- 1 | var exec = require('child_process').exec; 2 | 3 | exports.get = function(path, key, cb){ 4 | var cmd = 'reg query ' + path + ' /v ' + key; 5 | 6 | exec(cmd, function(err, stdout) { 7 | if (err) return cb(err); 8 | 9 | var match = stdout.toString().match(/REG_SZ\s+(.+)/); 10 | 11 | if (match) 12 | cb(null, match[1]); 13 | else 14 | cb(new Error('Unable to find key ' + key + ' in ' + path)) 15 | 16 | }); 17 | } 18 | 19 | exports.set = function(path, key, val, cb){ 20 | var cmd = 'reg add ' + path + ' /v ' + key + ' /d ' + val + ' /f'; 21 | exec(cmd, cb); 22 | } 23 | 24 | exports.del = function(path, key, cb){ 25 | var cmd = 'reg delete ' + path + ' /v ' + key + ' /f'; 26 | exec(cmd, function(err){ 27 | cb(); // don't mind if it does not exist. 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /lib/utils/configutil.js: -------------------------------------------------------------------------------- 1 | const storage = require('../agent/utils/storage'); 2 | /** 3 | * Retrieves data from the database based on the specified key. 4 | * 5 | * @param {string} whatToGet - The key to search for in the database 6 | * @param {Function} callback - The callback function to handle the retrieved data or errors 7 | * @return {void} 8 | */ 9 | const getDataDbKey = (whatToGet, callback) => { 10 | try { 11 | storage.do('query', { type: 'keys', column: 'id', data: whatToGet }, (err, stored) => { 12 | if (err) { 13 | return callback(err, null); 14 | } 15 | if (stored && stored.length > 0) { 16 | return callback(null, stored); 17 | } 18 | return callback(null, null); 19 | }); 20 | } catch (e) { 21 | callback(e, null); 22 | } 23 | }; 24 | /** 25 | * Sets the value of a key in the storage. 26 | * 27 | * @param {string} whatToGet - the key to set the value for 28 | * @param {any} valuetoSet - the value to set for the key 29 | * @param {function} cb - the callback function to be called after the value is set 30 | * @return {void} 31 | */ 32 | const setKey = (whatToGet, valuetoSet, cb) => { 33 | storage.do( 34 | 'set', 35 | { type: 'keys', id: whatToGet, data: { value: JSON.stringify(valuetoSet) } }, 36 | () => { cb(); }, 37 | ); 38 | }; 39 | /** 40 | * Sets the value of a key in the storage. 41 | * 42 | * @param {string} whatToGet - the key to set the value for 43 | * @param {any} valuetoSet - the value to set for the key 44 | * @param {function} cb - the callback function to be called after the value is set 45 | * @return {void} 46 | */ 47 | const updateKey = (whatToGet, valuetoSet, cb) => { 48 | storage.do('update', { 49 | type: 'keys', id: whatToGet, columns: 'value', values: JSON.stringify(valuetoSet), 50 | }, () => { cb(); }); 51 | }; 52 | /** 53 | * Save a value to the database based on a key, either updating 54 | * an existing key or setting a new key. 55 | * 56 | * @param {string} whatToGet - the key to retrieve from the database 57 | * @param {any} valuetoSet - the value to set or update in the database 58 | * @param {function} cb - a callback function to handle the result of the database operation 59 | * @return {void} 60 | */ 61 | const saveToDbKey = (whatToGet, valuetoSet, cb) => { 62 | getDataDbKey(whatToGet, (err, stored) => { 63 | if (err) return; 64 | if (stored) { 65 | updateKey(whatToGet, valuetoSet, cb); 66 | } else { 67 | setKey(whatToGet, valuetoSet, cb); 68 | } 69 | }); 70 | }; 71 | 72 | exports.setKey = setKey; 73 | exports.updateKey = updateKey; 74 | exports.saveToDbKey = saveToDbKey; 75 | exports.getDataDbKey = getDataDbKey; 76 | -------------------------------------------------------------------------------- /lib/utils/fetch-env-var.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const dotenv = require('dotenv'); 3 | 4 | const dotEnvPath = path.join(__dirname, '../../../.env'); 5 | dotenv.config({ path: dotEnvPath }); 6 | const environment = process.env; 7 | 8 | const isString = (key) => { 9 | let isOk = true; 10 | if (typeof key !== 'string') { 11 | isOk = false; 12 | throw new Error('the key received isn\'t an valid string'); 13 | } 14 | return isOk; 15 | }; 16 | 17 | const fetchEnvVar = (key2find) => { 18 | let keyFound; 19 | try { 20 | if (isString(key2find) && environment[`${key2find}`]) { 21 | keyFound = environment[`${key2find}`]; 22 | } else if (isString(key2find) && key2find === 'all') { 23 | keyFound = environment; 24 | } 25 | } catch (error) { 26 | return error; 27 | } 28 | return keyFound; 29 | }; 30 | 31 | module.exports = fetchEnvVar; 32 | -------------------------------------------------------------------------------- /lib/utils/permissionfile.js: -------------------------------------------------------------------------------- 1 | const { getDataDbKey, saveToDbKey, setKey } = require('./configutil'); 2 | 3 | const keyValue = 'permissions'; 4 | 5 | class PermissionData { 6 | permissionData = { 7 | nativeLocation: '', 8 | wifiLocation: '', 9 | }; 10 | 11 | constructor() { 12 | // eslint-disable-next-line no-constructor-return 13 | if (PermissionData.instance instanceof PermissionData) return PermissionData.instance; 14 | this.load(() => { 15 | PermissionData.instance = this; 16 | }); 17 | } 18 | 19 | // eslint-disable-next-line class-methods-use-this 20 | load = (cb) => { 21 | // eslint-disable-next-line consistent-return 22 | getDataDbKey(keyValue, (error, stored) => { 23 | if (error) return; 24 | if (!stored) { 25 | setKey(keyValue, JSON.stringify(this.permissionData), () => { 26 | cb(); 27 | }); 28 | } else { 29 | const data = JSON.parse(stored[0].value); 30 | Object.keys(this.permissionData).forEach((key) => { 31 | if (data[key]) this.permissionData[key] = data[key]; 32 | }); 33 | cb(); 34 | } 35 | }); 36 | }; 37 | 38 | all = () => this.permissionData; 39 | 40 | getData = (key) => this.permissionData[key]; 41 | 42 | setData = (key, value, cb) => { 43 | this.permissionData[key] = value; 44 | saveToDbKey(keyValue, this.permissionData, () => { 45 | if (cb && typeof cb === 'function') cb(); 46 | }); 47 | }; 48 | 49 | update = (key, value, cb) => { 50 | this.permissionData[key] = value; 51 | saveToDbKey(keyValue, this.permissionData, () => { 52 | if (cb && typeof cb === 'function') cb(); 53 | }); 54 | }; 55 | 56 | setFullFromData = (data, cb) => { 57 | Object.keys(this.permissionData).forEach((key) => { 58 | if (data[key]) { 59 | this.permissionData[key] = data[key]; 60 | } 61 | }); 62 | saveToDbKey(keyValue, this.permissionData, () => { 63 | if (cb && typeof cb === 'function') cb(); 64 | }); 65 | }; 66 | 67 | setFull = (cb) => { 68 | saveToDbKey(keyValue, this.permissionData, () => { 69 | if (cb && typeof cb === 'function') cb(); 70 | }); 71 | }; 72 | } 73 | 74 | const instance = new PermissionData(); 75 | Object.freeze(instance); 76 | 77 | module.exports = instance; 78 | -------------------------------------------------------------------------------- /prey.conf.default: -------------------------------------------------------------------------------- 1 | ############################# 2 | # Prey Configuration 3 | ############################# 4 | 5 | # Whether to try to connect to an open Wifi network if not online, when needing to send data. 6 | auto_connect = false 7 | 8 | # Allows Prey to auto-update itself when new versions are released. 9 | auto_update = true 10 | 11 | # Fetch edge releases before they reach the stable branch. No effect without auto_update. 12 | download_edge = false 13 | 14 | # Whether to inform about runtime errors to the development team. It helps. :) 15 | send_crash_reports = true 16 | 17 | # HTTP proxy server to try if a request fails (eg. http://my.proxy.com:3128) 18 | try_proxy = 19 | 20 | # These are temporary placeholders to persist the values when upgrading. Do not remove. 21 | api_key = 22 | device_key = 23 | 24 | [control-panel] 25 | 26 | # Host to connect to. 27 | host = solid.preyproject.com 28 | 29 | # Protocol to use. Either http or https. 30 | protocol = https 31 | 32 | # Your account's API key. 33 | api_key = 34 | 35 | # Your device's unique key. 36 | device_key = 37 | 38 | # Includes status info (battery info, logged user, etc) when checking in. 39 | send_status_info = true 40 | 41 | # Whether to send hardware information on boot, to detect any changes. 42 | scan_hardware = false 43 | 44 | # Allows to keep location info updated, retrieving it on connection status changes. 45 | location_aware = false -------------------------------------------------------------------------------- /test/lib/agent/ack.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-expressions */ 2 | /* eslint-disable no-undef */ 3 | const { expect } = require('chai'); 4 | const ack = require('../../../lib/agent/ack'); 5 | 6 | describe('ack testing', () => { 7 | describe('existKeyAckInJson', () => { 8 | it('debería regresar true si el objeto tiene una propiedad ack_id', () => { 9 | const json = { ack_id: '123' }; 10 | expect(ack.existKeyAckInJson(json)).to.be.true; 11 | }); 12 | 13 | it('debería regresar false si el objeto no tiene una propiedad ack_id', () => { 14 | const json = { foo: 'bar' }; 15 | expect(ack.existKeyAckInJson(json)).to.be.false; 16 | }); 17 | }); 18 | 19 | describe('existKeyIdInJson', () => { 20 | it('debería regresar true si el objeto tiene una propiedad id', () => { 21 | const json = { id: '123' }; 22 | expect(ack.existKeyIdInJson(json)).to.be.true; 23 | }); 24 | 25 | it('debería regresar false si el objeto no tiene una propiedad id', () => { 26 | const json = { foo: 'bar' }; 27 | expect(ack.existKeyIdInJson(json)).to.be.false; 28 | }); 29 | }); 30 | describe('processAck', () => { 31 | it('should return an error if json does not have ack_id', (done) => { 32 | const json = { foo: 'bar' }; 33 | ack.processAck(json, (err, result) => { 34 | expect(err).to.be.an('error'); 35 | expect(err.message).to.equal('there is no key ack_id in the json'); 36 | expect(result).to.be.undefined; 37 | done(); 38 | }); 39 | }); 40 | it('should return the expected object if json has ack_id', (done) => { 41 | const json = { ack_id: '123', id: '456' }; 42 | ack.processAck(json, (err, result) => { 43 | expect(err).to.be.null; 44 | expect(result).to.deep.equal({ 45 | ack_id: '123', 46 | type: 'ack', 47 | id: '456', 48 | }); 49 | done(); 50 | }); 51 | }); 52 | it('should return the expected object if json has ack_id but does not have id', (done) => { 53 | const json = { ack_id: '123' }; 54 | ack.processAck(json, (err, result) => { 55 | expect(err).to.be.null; 56 | expect(result).to.deep.equal({ 57 | ack_id: '123', 58 | type: 'ack', 59 | id: '', 60 | }); 61 | done(); 62 | }); 63 | }); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /test/lib/agent/control-panel/api/index.test.js: -------------------------------------------------------------------------------- 1 | const { expect } = require('chai'); 2 | const sinon = require('sinon'); 3 | const logger = require('../../../../../lib/agent/control-panel/api/logger'); 4 | const request = require('../../../../../lib/agent/control-panel/api/request'); 5 | const index = require('../../../../../lib/agent/control-panel/api/index'); 6 | 7 | describe('Module Exports and use Function', () => { 8 | 9 | describe('Module Exports', () => { 10 | it('should export logger, keys, accounts, devices, and push modules', () => { 11 | expect(index.logger).to.exist; 12 | expect(index.keys).to.exist; 13 | expect(index.accounts).to.exist; 14 | expect(index.devices).to.exist; 15 | expect(index.push).to.exist; 16 | }); 17 | }); 18 | 19 | describe('use function', () => { 20 | let loggerUseStub; 21 | let requestUseStub; 22 | 23 | beforeEach(() => { 24 | loggerUseStub = sinon.stub(logger, 'use'); 25 | requestUseStub = sinon.stub(request, 'use'); 26 | }); 27 | 28 | afterEach(() => { 29 | sinon.restore(); 30 | }); 31 | 32 | it('should call logger.use with a custom logger when provided', () => { 33 | const customLogger = { log: () => {} }; 34 | index.use({ logger: customLogger }); 35 | 36 | expect(loggerUseStub.calledOnceWith(customLogger)).to.be.true; 37 | }); 38 | 39 | it('should call request.use with the object when provided', () => { 40 | const customRequestClient = { request: () => {} }; 41 | index.use({ request: customRequestClient }); 42 | 43 | expect(requestUseStub.calledOnceWith({ request: customRequestClient })).to.be.true; 44 | }); 45 | 46 | it('should not call logger.use if no custom logger is provided', () => { 47 | index.use({}); 48 | expect(loggerUseStub.notCalled).to.be.true; 49 | }); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/lib/agent/control-panel/api/logger.test.js: -------------------------------------------------------------------------------- 1 | const { expect } = require('chai'); 2 | const sinon = require('sinon'); 3 | const logger = require('../../../../../lib/agent/control-panel/api/logger'); 4 | 5 | describe('Logger Module', () => { 6 | let writerMock; 7 | 8 | beforeEach(() => { 9 | writerMock = { 10 | debug: sinon.spy(), 11 | info: sinon.spy(), 12 | warn: sinon.spy(), 13 | error: sinon.spy(), 14 | }; 15 | logger.use(writerMock); 16 | }); 17 | 18 | afterEach(() => { 19 | sinon.restore(); 20 | }); 21 | 22 | describe('write function', () => { 23 | it('should call the correct writer method for debug', () => { 24 | logger.write('debug', 'Debug message'); 25 | expect(writerMock.debug.calledOnceWith('Debug message')).to.be.true; 26 | }); 27 | 28 | it('should call the correct writer method for info', () => { 29 | logger.write('info', 'Info message'); 30 | expect(writerMock.info.calledOnceWith('Info message')).to.be.true; 31 | }); 32 | 33 | it('should call the correct writer method for warn', () => { 34 | logger.write('warn', 'Warn message'); 35 | expect(writerMock.warn.calledOnceWith('Warn message')).to.be.true; 36 | }); 37 | 38 | it('should call the correct writer method for error', () => { 39 | logger.write('error', 'Error message'); 40 | expect(writerMock.error.calledOnceWith('Error message')).to.be.true; 41 | }); 42 | 43 | it('should not fail if writer is not set', () => { 44 | logger.use(null); 45 | expect(() => logger.write('info', 'This should not fail')).to.not.throw(); 46 | }); 47 | }); 48 | 49 | describe('specific log methods', () => { 50 | it('should call writer.debug for logger.debug', () => { 51 | logger.debug('Debugging message'); 52 | expect(writerMock.debug.calledOnceWith('Debugging message')).to.be.true; 53 | }); 54 | 55 | it('should call writer.info for logger.info', () => { 56 | logger.info('Informational message'); 57 | expect(writerMock.info.calledOnceWith('Informational message')).to.be.true; 58 | }); 59 | 60 | it('should call writer.warn for logger.warn', () => { 61 | logger.warn('Warning message'); 62 | expect(writerMock.warn.calledOnceWith('Warning message')).to.be.true; 63 | }); 64 | 65 | it('should call writer.error for logger.error', () => { 66 | logger.error('Error message'); 67 | expect(writerMock.error.calledOnceWith('Error message')).to.be.true; 68 | }); 69 | }); 70 | 71 | describe('use function', () => { 72 | it('should set the writer', () => { 73 | const newWriter = { debug: sinon.spy() }; 74 | logger.use(newWriter); 75 | logger.debug('Testing new writer'); 76 | expect(newWriter.debug.calledOnceWith('Testing new writer')).to.be.true; 77 | }); 78 | }); 79 | }); 80 | -------------------------------------------------------------------------------- /test/lib/agent/utils/prey-configuration/preyconf.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-expressions */ 2 | /* eslint-disable no-undef */ 3 | const chai = require('chai'); 4 | const fs = require('fs'); 5 | 6 | const { expect } = chai; 7 | const sinon = require('sinon'); 8 | const preyConf = require('../../../../../lib/agent/utils/prey-configuration/preyconf'); 9 | 10 | describe('PreyConf', () => { 11 | describe('getFileContent', () => { 12 | it('debería leer el contenido de un archivo', () => { 13 | const filePath = 'path/to/file'; 14 | const fileContent = 'contenido del archivo'; 15 | sinon.stub(fs, 'readFileSync').returns(fileContent); 16 | const result = preyConf.getFileContent(filePath); 17 | expect(result).to.equal(fileContent); 18 | fs.readFileSync.restore(); 19 | }); 20 | 21 | it('debería manejar un error al leer el archivo', () => { 22 | const filePath = 'path/to/file'; 23 | const error = new Error('Error reading prey.conf'); 24 | sinon.stub(fs, 'readFileSync').throws(error); 25 | try { 26 | preyConf.getFileContent(filePath); 27 | } catch (except) { 28 | expect(except).to.be.an.instanceOf(Error); 29 | } 30 | fs.readFileSync.restore(); 31 | }); 32 | }); 33 | 34 | describe('verifyPreyConf', () => { 35 | it('debería verificar la configuración de Prey', () => { 36 | const preyConfData = { /* datos de configuración */ }; 37 | const result = preyConf.verifyPreyConf(preyConfData); 38 | expect(result).to.be.true; 39 | }); 40 | 41 | it('debería manejar un error al verificar la configuración', () => { 42 | const preyConfData = { /* datos de configuración */ }; 43 | const error = new Error('Error verificando configuración'); 44 | sinon.stub(preyConf, 'verifyPreyConfData').throws(error); 45 | const result = preyConf.verifyPreyConf(preyConfData); 46 | expect(result).to.be.false; 47 | preyConf.verifyPreyConfData.restore(); 48 | }); 49 | }); 50 | 51 | describe('store', () => { 52 | it('debería almacenar la configuración de Prey', () => { 53 | const file = 'path/to/file'; 54 | const callback = sinon.stub(); 55 | preyConf.store(file, callback); 56 | expect(callback.calledOnce).to.be.true; 57 | }); 58 | 59 | it('debería manejar un error al almacenar la configuración', () => { 60 | const file = 'path/to/file'; 61 | const error = new Error('Error almacenando configuración'); 62 | sinon.stub(preyConf.fs, 'writeFile').throws(error); 63 | const callback = sinon.stub(); 64 | preyConf.store(file, callback); 65 | expect(callback.calledOnce).to.be.true; 66 | expect(callback.args[0][0]).to.equal(error); 67 | preyConf.fs.writeFile.restore(); 68 | }); 69 | }); 70 | 71 | // ... otros tests ... 72 | }); 73 | -------------------------------------------------------------------------------- /tools/sqlite3/linux/napi-v6-linux-x64/node_sqlite3.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/tools/sqlite3/linux/napi-v6-linux-x64/node_sqlite3.node -------------------------------------------------------------------------------- /tools/sqlite3/mac/napi-v6-darwin-unknown-arm64/node_sqlite3.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/tools/sqlite3/mac/napi-v6-darwin-unknown-arm64/node_sqlite3.node -------------------------------------------------------------------------------- /tools/sqlite3/mac/napi-v6-darwin-unknown-x64/node_sqlite3.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/tools/sqlite3/mac/napi-v6-darwin-unknown-x64/node_sqlite3.node -------------------------------------------------------------------------------- /tools/sqlite3/windows/napi-v6-win32-unknown-ia32/node_sqlite3.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/tools/sqlite3/windows/napi-v6-win32-unknown-ia32/node_sqlite3.node -------------------------------------------------------------------------------- /tools/sqlite3/windows/napi-v6-win32-unknown-x64/node_sqlite3.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prey/prey-node-client/c9dca93e5f028e07d9f2089bacd298b3791de795/tools/sqlite3/windows/napi-v6-win32-unknown-x64/node_sqlite3.node --------------------------------------------------------------------------------