├── .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 | [](https://codeclimate.com/github/prey/prey-node-client)
2 |
3 | [](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
--------------------------------------------------------------------------------