Compare commits

..

47 Commits

Author SHA1 Message Date
TIP Automation User
d03dbcf96c Update OpenAPI docs for GitHub pages 2025-08-22 13:16:53 +00:00
TIP Automation User
aaded5fdd1 Update OpenAPI docs for GitHub pages 2025-08-14 20:33:59 +00:00
TIP Automation User
9121892a03 Update OpenAPI docs for GitHub pages 2024-09-25 19:10:55 +00:00
TIP Automation User
7a40cd26e7 Update OpenAPI docs for GitHub pages 2024-03-27 05:06:49 +00:00
TIP Automation User
f32fc95d0b Update OpenAPI docs for GitHub pages 2024-03-15 15:49:35 +00:00
TIP Automation User
9b0c06dc12 Update OpenAPI docs for GitHub pages 2024-03-15 15:07:15 +00:00
TIP Automation User
240b24f7b5 Update OpenAPI docs for GitHub pages 2024-03-15 15:01:09 +00:00
TIP Automation User
afc2c30621 Update OpenAPI docs for GitHub pages 2024-03-13 21:20:04 +00:00
TIP Automation User
46a5d59f99 Update OpenAPI docs for GitHub pages 2024-02-20 21:27:48 +00:00
TIP Automation User
41eb4eca2c Update OpenAPI docs for GitHub pages 2024-01-11 23:19:12 +00:00
TIP Automation User
ccc36c69ad Update OpenAPI docs for GitHub pages 2024-01-05 20:21:55 +00:00
TIP Automation User
94e40fab26 Update OpenAPI docs for GitHub pages 2024-01-04 16:10:27 +00:00
TIP Automation User
80a346e389 Update OpenAPI docs for GitHub pages 2023-11-21 05:13:49 +00:00
TIP Automation User
e0a688f67d Update OpenAPI docs for GitHub pages 2023-11-15 19:16:47 +00:00
TIP Automation User
d35d6b0597 Update OpenAPI docs for GitHub pages 2023-10-31 14:15:29 +00:00
TIP Automation User
98677ab128 Update OpenAPI docs for GitHub pages 2023-10-19 23:24:27 +00:00
TIP Automation User
6f5f51fcc6 Update OpenAPI docs for GitHub pages 2023-10-19 18:09:19 +00:00
TIP Automation User
f3ee562810 Update OpenAPI docs for GitHub pages 2023-10-06 15:34:55 +00:00
TIP Automation User
907e2fc7f1 Update OpenAPI docs for GitHub pages 2023-09-26 04:58:09 +00:00
TIP Automation User
9f67078884 Update OpenAPI docs for GitHub pages 2023-09-15 19:08:30 +00:00
TIP Automation User
86cbf39533 Update OpenAPI docs for GitHub pages 2023-08-31 17:43:21 +00:00
TIP Automation User
d79ab1069f Update OpenAPI docs for GitHub pages 2023-08-03 17:35:08 +00:00
TIP Automation User
f35d141d2c Update OpenAPI docs for GitHub pages 2023-08-03 17:13:23 +00:00
TIP Automation User
d758269f1f Update OpenAPI docs for GitHub pages 2023-07-12 16:07:53 +00:00
TIP Automation User
e301775fcd Update OpenAPI docs for GitHub pages 2023-07-12 15:45:57 +00:00
TIP Automation User
962867f5c9 Update OpenAPI docs for GitHub pages 2023-07-12 15:31:36 +00:00
TIP Automation User
f6c9b98a4b Update OpenAPI docs for GitHub pages 2023-07-12 06:15:29 +00:00
TIP Automation User
2645dd0800 Update OpenAPI docs for GitHub pages 2023-05-22 21:32:55 +00:00
TIP Automation User
374f56425e Update OpenAPI docs for GitHub pages 2023-05-22 19:12:34 +00:00
TIP Automation User
3015bba32d Update OpenAPI docs for GitHub pages 2023-05-22 15:52:05 +00:00
TIP Automation User
5502ea12e1 Update OpenAPI docs for GitHub pages 2023-05-16 16:42:23 +00:00
TIP Automation User
a211c62091 Update OpenAPI docs for GitHub pages 2023-05-16 16:31:26 +00:00
TIP Automation User
efd61ed51a Update OpenAPI docs for GitHub pages 2023-04-18 23:24:19 +00:00
TIP Automation User
5b0c775499 Update OpenAPI docs for GitHub pages 2023-04-18 22:09:49 +00:00
TIP Automation User
1c23a8584e Update OpenAPI docs for GitHub pages 2023-04-17 14:57:39 +00:00
TIP Automation User
c80c3be99e Update OpenAPI docs for GitHub pages 2023-04-06 15:59:49 +00:00
TIP Automation User
eadfa6bfc4 Update OpenAPI docs for GitHub pages 2023-04-04 16:04:59 +00:00
TIP Automation User
e594475f6c Update OpenAPI docs for GitHub pages 2023-04-04 03:45:05 +00:00
TIP Automation User
c4576a6858 Update OpenAPI docs for GitHub pages 2023-04-03 18:46:16 +00:00
TIP Automation User
90671250c1 Update OpenAPI docs for GitHub pages 2023-04-03 06:53:18 +00:00
TIP Automation User
f1d4a81946 Update OpenAPI docs for GitHub pages 2023-03-17 22:58:31 +00:00
TIP Automation User
1504b76dc7 Update OpenAPI docs for GitHub pages 2023-03-07 15:35:42 +00:00
TIP Automation User
9742304822 Update OpenAPI docs for GitHub pages 2023-02-28 06:26:09 +00:00
TIP Automation User
b19fcab532 Update OpenAPI docs for GitHub pages 2022-12-12 21:21:53 +00:00
TIP Automation User
6557e6e297 Update OpenAPI docs for GitHub pages 2022-12-01 10:17:45 +00:00
TIP Automation User
06b656d9e5 Update OpenAPI docs for GitHub pages 2022-11-27 21:57:21 +00:00
TIP Automation User
e215618c2c Update OpenAPI docs for GitHub pages 2022-11-25 19:01:09 +00:00
90 changed files with 45193 additions and 5969 deletions

View File

@@ -34,7 +34,6 @@ jobs:
git config --global user.name "TIP Automation User"
git pull
git checkout gh-pages || git checkout -b gh-pages
rm -rf docs
mv tmp-docs docs
git add docs
git commit -m'Update OpenAPI docs for GitHub pages'

View File

@@ -165,6 +165,10 @@ add_executable( owgw
src/CapabilitiesCache.h src/FindCountry.h
src/rttys/RTTYS_server.cpp
src/rttys/RTTYS_server.h
src/rttys/RTTYS_device.cpp
src/rttys/RTTYS_device.h
src/rttys/RTTYS_ClientConnection.cpp
src/rttys/RTTYS_ClientConnection.h
src/rttys/RTTYS_WebServer.cpp
src/rttys/RTTYS_WebServer.h src/RESTAPI/RESTAPI_device_helper.h
src/SDKcalls.cpp
@@ -195,7 +199,7 @@ add_executable( owgw
src/AP_WS_Process_telemetry.cpp
src/AP_WS_Process_venuebroadcast.cpp
src/RADSEC_server.h
src/UI_GW_WebSocketNotifications.cpp src/UI_GW_WebSocketNotifications.h src/framework/RESTAPI_SystemConfiguration.h src/ScriptManager.cpp src/ScriptManager.h src/RESTAPI/RESTAPI_scripts_handler.cpp src/RESTAPI/RESTAPI_scripts_handler.h src/RESTAPI/RESTAPI_script_handler.cpp src/RESTAPI/RESTAPI_script_handler.h src/storage/storage_scripts.cpp src/storage/storage_scripts.h src/SignatureMgr.cpp src/SignatureMgr.h)
src/UI_GW_WebSocketNotifications.cpp src/UI_GW_WebSocketNotifications.h src/framework/RESTAPI_SystemConfiguration.h src/AP_restrictions.h)
if(NOT SMALL_BUILD)

View File

@@ -1,5 +1,5 @@
ARG DEBIAN_VERSION=11.5-slim
ARG POCO_VERSION=poco-tip-v2
ARG POCO_VERSION=poco-tip-v1
ARG CPPKAFKA_VERSION=tip-v1
ARG JSON_VALIDATOR_VERSION=2.1.0

View File

@@ -1,82 +0,0 @@
# Restricted devices
## What is a restricted device?
A restricted device is one that because of regulations or a desire for utmost security, requires signatures to access restricted or blocked
features. The restriction process is burnt in the device at manufacturing or later by running a specific command on the device. Once a device
is restricted, it cannot be unlocked.
## Current restrictions
Restrictions are stored on the AP in a protected partition. They are contained in a file called `restrictions.json`. Here is a sample:
```json
{
"country": [
"US", "CA"
],
"dfs": true,
"rtty": true,
"tty": true,
"developer": true,
"sysupgrade": true,
"commands": true,
"key_info": {
"vendor": "dummy",
"algo": "static"
}
}
```
- country
- List of countries where this device may be used
- dfs
- Disallow DFS Override during wifi-scan. If set to `true`, device will not allow to override DFS channels
- rtty
- Disallow the use of the RTTY command for this device
- tty
- Do not allow the AP to accept `tty` connection
- developer
- Internal use only.
- sysupgrade
- If set to `true`, only signed firmware upgrade command will be allowed.
- commands
- If set to `true`, do not allow commands.
- key_info
- This structure defines how signatures should be generated and verified in a secure system
- vendor
- An identified that must match the vendor name provided in the controller
- algo
- The signature algorithm. Here are the supported algorithms
- `static`
- A test algorithm that always returns and uses a value of `aaaaaaaaaa`. This should never be used in the field.
- `dgst-sha256`
- The default OpenSSL RSA signature generation and verification. The controller will use the following command to generate the signature
```sh
openssl dgst -sha256 -sign private-key.pem -out signature.txt myfile
```
- The AP will be using the following to verify the signature
```sh
openssl dgst -sha256 -verify public-key.pem -signature signature.txt myfile
```
## Creating signatures on the controller
When a device is restricted and a signature is required, the controller can generate the signature
for the specified `vendor`. However, on the controlelr side, you must configure the vendors. In
order to do so we suggest the following.
- Create a directory called `signatures` under your `certs` directory
- Copy the public and private keys for each `vendor` name. We suggest naming them accordingly
- `vendor`-private-key.pem
- `vendor`-public-key.pem
- In the `owgw.properties` file, you need to declare these signatures the following way
```properties
signature.manager.0.key.public = $OWGW_ROOT/certs/signatures/test1-public-key.pem
signature.manager.0.key.private = $OWGW_ROOT/certs/signatures/test1-private-key.pem
signature.manager.0.vendor = test1
signature.manager.1.key.public = $OWGW_ROOT/certs/signatures/test2-public-key.pem
signature.manager.1.key.private = $OWGW_ROOT/certs/signatures/test2-private-key.pem
signature.manager.1.vendor = test2
```
## How do you use the signatures?
There is nothing to do really. Now the controller will use the proper key to create the signatures
when it sends commands to the AP. It will use the algorithm that the device understands too. This is transparent
to the user. The `vendor` name used in the controller configuration must match the `vendor` name provided in the
`restrictions.json` file.

2
build
View File

@@ -1 +1 @@
94
44

View File

@@ -73,7 +73,6 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"owgw"} \
STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"owgw"} \
STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \
CERTIFICATES_ALLOWMISMATCH=${CERTIFICATES_ALLOWMISMATCH:-"false"} \
envsubst < /owgw.properties.tmpl > $OWGW_CONFIG/owgw.properties
fi

40844
docs/index.html Normal file

File diff suppressed because one or more lines are too long

View File

@@ -9,7 +9,7 @@ fullnameOverride: ""
images:
owgw:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
tag: v2.8.0
tag: master
pullPolicy: Always
# regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
@@ -230,7 +230,6 @@ configProperties:
openwifi.devicetypes.0: AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
openwifi.devicetypes.1: SWITCH:edgecore_ecs4100-12ph
openwifi.devicetypes.2: IOT:esp32
openwifi.certificates.allowmismatch: "false"
oui.download.uri: https://standards-oui.ieee.org/oui/oui.txt
firmware.autoupdate.policy.default: auto
iptocountry.provider: ipinfo

View File

@@ -49,38 +49,6 @@ components:
- IOT
- MESH
DeviceRestrictionsKeyInfo:
type: object
properties:
vendor:
type: string
algo:
type: string
DeviceRestrictions:
type: object
properties:
dfs:
type: boolean
ssh:
type: boolean
rtty:
type: boolean
tty:
type: boolean
developer:
type: boolean
upgrade:
type: boolean
commands:
type: boolean
country:
type: array
items:
type: string
key_info:
$ref: '#/components/schemas/DeviceRestrictionsKeyInfo'
Device:
type: object
description: Definition of uCentral device
@@ -139,19 +107,12 @@ components:
type: string
minLength: 2
maxLength: 2
restrictedDevice:
FCC:
type: boolean
default: false
certificateExpiryDate:
type: integer
format: int64
pendingConfiguration:
type: string
pendingConfigurationCmd:
type: string
format: uuid
restrictionDetails:
$ref: '#/components/schemas/DeviceRestrictions'
DeviceWithStatus:
type: object
@@ -253,13 +214,6 @@ components:
certificateDate:
type: integer
format: int64
pendingConfiguration:
type: string
pendingConfigurationCmd:
type: string
format: uuid
restrictionDetails:
$ref: '#/components/schemas/DeviceRestrictions'
DeviceList:
type: object
@@ -560,11 +514,8 @@ components:
enum:
- shell
- bundle
- diagnostic
script:
type: string
scriptId:
type: string
when:
type: integer
format: int64
@@ -576,52 +527,6 @@ components:
uri:
type: string
ScriptEntry:
type: object
properties:
id:
type: string
name:
type: string
description:
type: string
uri:
type: string
content:
type: string
version:
type: string
type:
enum:
- shell
- bundle
created:
type: integer
modified:
type: integer
author:
type: string
restricted:
type: array
items:
type: string
deferred:
type: boolean
default: false
timeout:
type: integer
default: 30
defaultUploadURI:
type: string
ScriptEntryList:
type: object
properties:
scripts:
type: array
items:
$ref: '#/components/schemas/ScriptEntry'
FactoryRequest:
type: object
properties:
@@ -2569,148 +2474,6 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/scripts:
get:
tags:
- Scripting
summary: Returns a list scripts.
description: Get a list of scripts.
operationId: getScripts
parameters:
- in: query
description: Pagination start (starts at 0. If not specified, 0 is assumed)
name: offset
schema:
type: integer
required: false
- in: query
description: Maximum number of entries to return (if absent, no limit is assumed)
name: limit
schema:
type: integer
required: false
- in: query
description: Filter the results
name: filter
schema:
type: string
required: false
responses:
200:
description: List all scripts
content:
application/json:
schema:
$ref: '#/components/schemas/ScriptEntryList'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/script/{uuid}:
get:
tags:
- Scripting
summary: Returns a script entry.
description: Get a specific script entry.
operationId: getScript
parameters:
- in: path
description: The UUID of the script
name: uuid
schema:
type: string
format: uuid
required: true
responses:
200:
description: A script entry
content:
application/json:
schema:
$ref: '#/components/schemas/ScriptEntry'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
post:
tags:
- Scripting
summary: Create a new script.
operationId: createScript
parameters:
- in: path
description: The UUID of the script. Must be set to 0 for creation
name: uuid
schema:
type: string
format: uuid
required: true
requestBody:
description: Complet script entry
content:
application/json:
schema:
$ref: '#/components/schemas/ScriptEntry'
responses:
200:
$ref: '#/components/schemas/ScriptEntry'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- Scripting
summary: Modify a script.
operationId: modifyScript
parameters:
- in: path
description: The UUID of the script.
name: uuid
schema:
type: string
format: uuid
required: true
requestBody:
description: Complete script entry. You may only modify the name, description, version, uri, and content
content:
application/json:
schema:
$ref: '#/components/schemas/ScriptEntry'
responses:
200:
$ref: '#/components/schemas/ScriptEntry'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
delete:
tags:
- Scripting
summary: Delete a script.
operationId: deleteScript
parameters:
- in: path
name: uuid
schema:
type: string
format: uuid
required: true
responses:
204:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/blacklist:
get:
tags:

View File

@@ -75,7 +75,6 @@ openwifi.autoprovisioning = true
openwifi.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
openwifi.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
openwifi.devicetypes.2 = IOT:esp32
openwifi.certificates.allowmismatch = ${CERTIFICATES_ALLOWMISMATCH}
oui.download.uri = https://standards-oui.ieee.org/oui/oui.txt
simulatorid = ${SIMULATORID}
iptocountry.default = US

View File

@@ -16,7 +16,6 @@
"weight" : 10,
"radsec" : true,
"radsecPort" : 2083,
"allowSelfSigned" : false,
"radsecSecret" : "radsec",
"radsecKey" : "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUR6RnpXeTZlYXg0QVoxTySG9VUURRZ0FFS3BnWVBHMktPTVd2S0w1Z3NMRXpUc09rREg1M3NHaEQyS3RsRXBDTXVnNDNIZlFnTFVpUgpTR1R2S1l0bDFmbmJaU1lnY0RJdncxdjNYRy9hVDhOY2JBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=",
"radsecCert" : "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNRVENDQWVpZ0F3SUJBZ0lVY3BKS3pVM0Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBb1RDa0oxZEhSdmJuZHZiMlF4SFRBYkJnTlZCQU1URkVKMQpkSFJ2Ym5kdmIyUWdVbUZrYzJWaklFTkJNQjRYRFRJeU1EY3dNekExTWpVeE5Gb1hEVEkzTURVeE9UQTFNalV4Ck5Gb3dkVEVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFvVENrSjFkSFJ2Ym5kdmIyUXhOakEwQmdOVkJBTVQKTFdGeWFXeHBZUzVqWWpFd2FtTnVjemgxYlhCbk9HWnBjRFowTUM1dmNtbHZiaTVoY21WaE1USXdMbU52YlRFWgpNQmNHQ2dtU0pvbVQ4aXhrQVFFVENVZHZiMmRzWlRwVlV6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCQ3FZR0R4dGlqakZyeWkrWUxDeE0wN0RwQXgrZDdCb1E5aXJaUktRakxvT054MzBJQzFJa1Voazd5bUwKWmRYNTIyVW1JSEF5TDhOYjkxeHYyay9EWEd5amdZa3dnWVl3RGdZRFZSMFBBUUgvQkFRREFnZUFNQk1HQTFVZApKUVFNTUFvR0NDc0dBUVVGQndNQ01Bd0dBMVVkRXdFQi93UUNNQUF3T0FZRFZSMFJCREV3TDRJdFlYSnBiR2xoCkxtTmlNVEJxWTI1ek9IVnRjR2M0Wm1sd05uUXdMbTl5YVc5dUxtRnlaV0V4TWpBdVkyOXRNQmNHQTFVZElBUVEKTUE0d0RBWUtLd1lCQkFIdUtnRUJCVEFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUFwTmM1dUNBSkp6KzVyakdqdwpCWGtOdHE3UU83bWU5dUg5bkNsTDZnSVE5Z0lnUHM2VkVKVW5CcEZ0RktXbFF4eWJ1YlBxYnpJNjBPSERHQ0ExCmhXUk1PS1U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",

View File

@@ -28,8 +28,6 @@
#include "fmt/format.h"
#include "framework/ow_constants.h"
#include "RADIUS_proxy_server.h"
@@ -292,7 +290,7 @@ namespace OpenWifi {
bool Sent;
StorageService()->AddCommand(SerialNumber_, Cmd, Storage::CommandExecutionType::COMMAND_EXECUTED);
CommandManager()->PostCommand(CommandManager()->Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()),SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent);
CommandManager()->PostCommand(CommandManager()->Next_RPC_ID(),SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent);
GWWebSocketNotifications::SingleDeviceConfigurationChange_t Notification;
Notification.content.serialNumber = D.SerialNumber;

View File

@@ -15,6 +15,7 @@
#include "Poco/Net/WebSocket.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
#include "AP_restrictions.h"
namespace OpenWifi {
@@ -77,7 +78,7 @@ namespace OpenWifi {
State = State_;
}
inline void GetRestrictions(GWObjects::DeviceRestrictions & R) const {
inline void GetRestrictions(AP_Restrictions & R) const {
std::shared_lock G(ConnectionMutex_);
R = Restrictions_;
}
@@ -114,7 +115,7 @@ namespace OpenWifi {
friend class AP_WS_Server;
inline GWObjects::DeviceRestrictions Restrictions() const {
inline AP_Restrictions Restrictions() const {
std::shared_lock G(ConnectionMutex_);
return Restrictions_;
}
@@ -149,7 +150,7 @@ namespace OpenWifi {
std::atomic_flag Dead_=false;
std::atomic_bool DeviceValidated_=false;
std::atomic_bool Valid_=false;
OpenWifi::GWObjects::DeviceRestrictions Restrictions_;
AP_Restrictions Restrictions_;
static inline std::atomic_uint64_t ConcurrentStartingDevices_=0;

View File

@@ -50,10 +50,12 @@ namespace OpenWifi {
}
bool RestrictedDevice = false;
if(Capabilities->has("restrictions")){
if(ParamsObj->has("restricted") && ParamsObj->get("restricted").isBoolean()) {
RestrictedDevice = true;
Poco::JSON::Object::Ptr RestrictionObject = Capabilities->getObject("restrictions");
Restrictions_.from_json(RestrictionObject);
if(Capabilities->has("restrictions")) {
auto RestrictionObject = Capabilities->getObject("restrictions");
Restrictions_.initialize(Logger_, SerialNumber_, RestrictionObject);
}
}
State_.locale = FindCountryFromIP()->Get(IP);
@@ -95,15 +97,9 @@ namespace OpenWifi {
++Updated;
}
if(Restrictions_ != DeviceInfo.restrictionDetails) {
DeviceInfo.restrictionDetails = Restrictions_;
++Updated;
}
if(Updated) {
StorageService()->UpdateDevice(DeviceInfo);
}
uint64_t UpgradedUUID=0;
LookForUpgrade(UUID,UpgradedUUID);
State_.UUID = UpgradedUUID;
@@ -115,7 +111,7 @@ namespace OpenWifi {
State_.connectionCompletionTime = ConnectionCompletionTime_.count();
if(State_.VerifiedCertificate == GWObjects::VALID_CERTIFICATE) {
if (( Utils::SerialNumberMatch(CN_, SerialNumber_, (int)AP_WS_Server()->MismatchDepth())) ||
if (( Utils::SerialNumberMatch(CN_, SerialNumber_, AP_WS_Server()->MismatchDepth())) ||
AP_WS_Server()->IsSimSerialNumber(CN_)) {
State_.VerifiedCertificate = GWObjects::VERIFIED;
poco_information(Logger_, fmt::format("CONNECT({}): Fully validated and authenticated device. Session={} ConnectionCompletion Time={}",
@@ -131,8 +127,9 @@ namespace OpenWifi {
State_.connectionCompletionTime));
} else {
poco_information(
Logger_, fmt::format("CONNECT({}): Serial number mismatch disallowed. Device rejected. CN={} Serial={} Session={}",
CId_, CN_, SerialNumber_, State_.sessionId));
Logger_, fmt::format("CONNECT({}): Serial number mismatch disallowed. Device rejected. CN={} Serial={} Session={} ConnectionCompletion Time={}",
CId_, CN_, SerialNumber_, State_.sessionId,
State_.connectionCompletionTime));
return EndConnection();
}
}

View File

@@ -9,7 +9,6 @@
#include "framework/ow_constants.h"
#include "framework/MicroServiceFuncs.h"
#include "fmt/format.h"
#include "framework/ow_constants.h"
namespace OpenWifi {
void AP_WS_Connection::Process_recovery(Poco::JSON::Object::Ptr ParamsObj) {
@@ -52,7 +51,7 @@ namespace OpenWifi {
Poco::JSON::Stringifier::stringify(Params, O);
Cmd.Details = O.str();
bool Sent;
CommandManager()->PostCommand(CommandManager()->Next_RPC_ID(), APCommands::Commands::reboot, SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent);
CommandManager()->PostCommand(CommandManager()->Next_RPC_ID(),SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent);
StorageService()->AddCommand(SerialNumber_, Cmd, Storage::CommandExecutionType::COMMAND_EXECUTED);
poco_information(Logger_, fmt::format("RECOVERY({}): Recovery mode received, need for a reboot.", CId_));
} else {

View File

@@ -296,7 +296,7 @@ namespace OpenWifi {
return false;
}
bool AP_WS_Server::Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions & Restrictions) const {
bool AP_WS_Server::Connected(uint64_t SerialNumber, AP_Restrictions & Restrictions) const {
std::shared_ptr<AP_WS_Connection> DevicePtr;
{
std::lock_guard Lock(WSServerMutex_);

View File

@@ -134,7 +134,7 @@ namespace OpenWifi {
}
bool GetHealthcheck(uint64_t SerialNumber, GWObjects::HealthCheck & CheckData) const ;
bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions & Restrictions) const ;
bool Connected(uint64_t SerialNumber, AP_Restrictions & Restrictions) const ;
bool Connected(uint64_t SerialNumber) const ;
inline bool SendFrame(const std::string & SerialNumber, const std::string & Payload) const {

77
src/AP_restrictions.h Normal file
View File

@@ -0,0 +1,77 @@
//
// Created by stephane bourque on 2022-11-14.
//
#pragma once
#include <string>
#include <set>
#include "Poco/JSON/Object.h"
#include "Poco/Logger.h"
#include "fmt/format.h"
/*
{
“country”: [
“US”, “CA”
],
“dfs”: true,
“ssh”: true,
“rtty”: true,
“tty”: true,
“developer”: true,
“sysupgrade”: true,
“commands”: true
}
*/
namespace OpenWifi {
class AP_Restrictions {
public:
inline bool initialize(Poco::Logger & Logger, const std::string & serialNumber, const Poco::JSON::Object::Ptr &O) {
try {
dfs_ = O->optValue("dfs",false);
ssh_ = O->optValue("ssh",false);
rtty_ = O->optValue("rtty",false);
tty_ = O->optValue("tty",false);
developer_ = O->optValue("developer",false);
sysupgrade_ = O->optValue("sysupgrade",false);
commands_ = O->optValue("commands",false);
if(O->has("country") && O->isArray("country")) {
auto Countries = O->getArray("country");
for(const auto &country:*Countries) {
countries_.insert(Poco::toLower(country.toString()));
}
}
return true;
} catch (...) {
poco_error(Logger,fmt::format("Cannot parse restrictions for device {}", serialNumber));
}
return false;
}
[[nodiscard]] inline auto dfs_not_allowed() const { return dfs_; }
[[nodiscard]] inline auto ssh_not_allowed() const { return ssh_; }
[[nodiscard]] inline auto rtty_not_allowed() const { return rtty_; }
[[nodiscard]] inline auto tty_not_allowed() const { return tty_; }
[[nodiscard]] inline auto developer_not_allowed() const { return developer_; }
[[nodiscard]] inline auto sysupgrade_not_allowed() const { return sysupgrade_; }
[[nodiscard]] inline auto commands_not_allowed() const { return commands_; }
[[nodiscard]] inline bool valid_country(const std::string &c) const {
if(countries_.empty())
return true;
return countries_.find(Poco::toLower(c))!=countries_.end();
}
private:
std::set<std::string> countries_;
bool dfs_ = false;
bool ssh_ = false;
bool rtty_ = false;
bool tty_ = false;
bool developer_ = false;
bool sysupgrade_ = false;
bool commands_ = false;
};
}

View File

@@ -67,11 +67,11 @@ R"lit(
"ipv4": {
"addressing": "static",
"dhcp": {
"lease-count": 100,
"lease-count": 10000,
"lease-first": 10,
"lease-time": "6h"
},
"subnet": "192.168.1.1/24"
"subnet": "192.168.1.1/16"
},
"name": "LAN",
"role": "downstream",

View File

@@ -34,13 +34,13 @@ namespace OpenWifi {
Poco::JSON::Object::Ptr Payload = Resp->Payload_;
std::string SerialNumberStr = Utils::IntToSerialNumber(Resp->SerialNumber_);
bool NoReply = false;
std::ostringstream SS;
Payload->stringify(SS);
if (!Payload->has(uCentralProtocol::ID)) {
poco_error(Logger(), fmt::format("({}): Invalid RPC response.", SerialNumberStr));
} else {
uint64_t ID = Payload->get(uCentralProtocol::ID);
std::shared_ptr<promise_type_t> TmpRpcEntry;
poco_debug(Logger(),fmt::format("({}): Processing {} response.", SerialNumberStr, ID));
if (ID > 1) {
std::lock_guard Lock(LocalMutex_);
@@ -53,65 +53,16 @@ namespace OpenWifi {
std::chrono::duration<double, std::milli> rpc_execution_time =
std::chrono::high_resolution_clock::now() -
RPC->second.submitted;
StorageService()->CommandCompleted(RPC->second.UUID, Payload,
rpc_execution_time, true);
if (RPC->second.rpc_entry) {
RPC->second.rpc_entry->set_value(Payload);
}
poco_debug(Logger(),
fmt::format("({}): Received RPC answer {}. Command={}",
SerialNumberStr, ID, APCommands::to_string(RPC->second.Command)));
if(RPC->second.Command==APCommands::Commands::script) {
if(RPC->second.State==2) {
// look at the payload to see if we should continue or not...
if (RPC->second.rpc_entry) {
TmpRpcEntry = RPC->second.rpc_entry;
}
// Payload->stringify(std::cout);
if (Payload->has("result")) {
auto Result = Payload->getObject("result");
if (Result->has("status")) {
auto Status = Result->getObject("status");
// Status->stringify(std::cout);
std::uint64_t Error = Status->get("error");
if(Error==0) {
StorageService()->CommandCompleted(RPC->second.UUID, Payload,
rpc_execution_time, true);
RPC->second.State = 1 ;
} else {
StorageService()->CommandCompleted(RPC->second.UUID, Payload,
rpc_execution_time, true);
std::string ErrorTxt = Status->get("result");
StorageService()->CancelWaitFile(RPC->second.UUID, ErrorTxt);
RPC->second.State = 0 ;
}
}
} else {
// std::cout << "Bad payload on command result" << std::endl;
RPC->second.State=0;
}
} else {
// std::cout << "Completing script 2 phase commit." << std::endl;
StorageService()->CommandCompleted(RPC->second.UUID, Payload,
rpc_execution_time, true);
NoReply = true;
RPC->second.State=0;
}
} else {
if(RPC->second.Command!=APCommands::Commands::telemetry) {
StorageService()->CommandCompleted(
RPC->second.UUID, Payload, rpc_execution_time, true);
}
if (RPC->second.rpc_entry) {
TmpRpcEntry = RPC->second.rpc_entry;
}
RPC->second.State = 0 ;
}
if(RPC->second.State==0) {
OutStandingRequests_.erase(ID);
}
SerialNumberStr, ID, RPC->second.Command));
OutStandingRequests_.erase(ID);
}
if(!NoReply && TmpRpcEntry != nullptr)
TmpRpcEntry->set_value(Payload);
}
}
}
@@ -169,7 +120,7 @@ namespace OpenWifi {
if(delta > 10min) {
MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.",
request->second.UUID,
APCommands::to_string(request->second.Command),
request->second.Command,
Utils::IntToSerialNumber(request->second.SerialNumber)));
request = OutStandingRequests_.erase(request);
} else {
@@ -238,15 +189,14 @@ namespace OpenWifi {
continue;
}
std::string ExecutingUUID;
APCommands::Commands ExecutingCommand=APCommands::Commands::unknown;
std::string ExecutingCommand, ExecutingUUID;
if (CommandRunningForDevice(Utils::SerialNumberToInt(Cmd.SerialNumber),
ExecutingUUID, ExecutingCommand)) {
poco_trace(
MyLogger,
fmt::format(
"{}: Serial={} Command={} Device is already busy with command {} (Command={})."
, Cmd.UUID, Cmd.SerialNumber, Cmd.Command, ExecutingUUID, APCommands::to_string(ExecutingCommand)));
, Cmd.UUID, Cmd.SerialNumber, Cmd.Command,ExecutingUUID, ExecutingCommand));
continue;
}
@@ -255,7 +205,7 @@ namespace OpenWifi {
poco_information(MyLogger, fmt::format("{}: Serial={} Command={} Preparing execution.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
auto Params = P.parse(Cmd.Details).extract<Poco::JSON::Object::Ptr>();
auto Result = PostCommandDisk(Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()), Cmd.SerialNumber, Cmd.Command,
auto Result = PostCommandDisk(Next_RPC_ID(), Cmd.SerialNumber, Cmd.Command,
*Params, Cmd.UUID, Sent);
if (Sent) {
StorageService()->SetCommandExecuted(Cmd.UUID);
@@ -290,10 +240,9 @@ namespace OpenWifi {
}
std::shared_ptr<CommandManager::promise_type_t> CommandManager::PostCommand(
uint64_t RPC_ID,
APCommands::Commands Command,
uint64_t RPCID,
const std::string &SerialNumber,
const std::string &CommandStr,
const std::string &Command,
const Poco::JSON::Object &Params,
const std::string &UUID,
bool oneway_rpc,
@@ -306,33 +255,31 @@ namespace OpenWifi {
std::stringstream ToSend;
CommandInfo Idx;
Idx.Id = oneway_rpc ? 1 : RPC_ID;
Idx.Id = oneway_rpc ? 1 : RPCID;
Idx.SerialNumber = SerialNumberInt;
Idx.Command = Command;
if(Command == APCommands::Commands::script)
Idx.State=2;
Idx.UUID = UUID;
Poco::JSON::Object CompleteRPC;
CompleteRPC.set(uCentralProtocol::JSONRPC, uCentralProtocol::JSONRPC_VERSION);
CompleteRPC.set(uCentralProtocol::ID, RPC_ID);
CompleteRPC.set(uCentralProtocol::METHOD, CommandStr);
CompleteRPC.set(uCentralProtocol::ID, RPCID);
CompleteRPC.set(uCentralProtocol::METHOD, Command);
CompleteRPC.set(uCentralProtocol::PARAMS, Params);
Poco::JSON::Stringifier::stringify(CompleteRPC, ToSend);
Idx.rpc_entry = disk_only ? nullptr : std::make_shared<CommandManager::promise_type_t>();
poco_debug(Logger(), fmt::format("{}: Sending command {} to {}. ID: {}", UUID, CommandStr, SerialNumber, RPC_ID));
poco_debug(Logger(), fmt::format("{}: Sending command. ID: {}", UUID, RPCID));
if(AP_WS_Server()->SendFrame(SerialNumber, ToSend.str())) {
if(!oneway_rpc) {
std::lock_guard M(Mutex_);
OutStandingRequests_[RPC_ID] = Idx;
OutStandingRequests_[RPCID] = Idx;
}
poco_debug(Logger(), fmt::format("{}: Sent command. ID: {}", UUID, RPC_ID));
poco_debug(Logger(), fmt::format("{}: Sent command. ID: {}", UUID, RPCID));
Sent=true;
return Idx.rpc_entry;
}
poco_warning(Logger(), fmt::format("{}: Failed to send command. ID: {}", UUID, RPC_ID));
poco_warning(Logger(), fmt::format("{}: Failed to send command. ID: {}", UUID, RPCID));
return nullptr;
}
} // namespace

View File

@@ -49,11 +49,10 @@ namespace OpenWifi {
using promise_type_t = std::promise<objtype_t>;
struct CommandInfo {
std::uint64_t Id=0;
std::uint64_t SerialNumber=0;
APCommands::Commands Command;
std::string UUID;
std::uint64_t State=1;
std::uint64_t Id=0;
std::uint64_t SerialNumber=0;
std::string Command;
std::string UUID;
std::chrono::time_point<std::chrono::high_resolution_clock> submitted = std::chrono::high_resolution_clock::now();
std::shared_ptr<promise_type_t> rpc_entry;
};
@@ -77,15 +76,12 @@ namespace OpenWifi {
}
std::shared_ptr<promise_type_t> PostCommandOneWayDisk(uint64_t RPC_ID,
APCommands::Commands Command,
const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,
const std::string &UUID,
bool & Sent) {
return PostCommand(RPC_ID,
Command,
SerialNumber,
return PostCommand(RPC_ID, SerialNumber,
Method,
Params,
UUID,
@@ -94,14 +90,12 @@ namespace OpenWifi {
std::shared_ptr<promise_type_t> PostCommandDisk(
uint64_t RPC_ID,
APCommands::Commands Command,
const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,
const std::string &UUID,
bool & Sent) {
return PostCommand(RPC_ID,
Command,
SerialNumber,
Method,
Params,
@@ -111,15 +105,12 @@ namespace OpenWifi {
std::shared_ptr<promise_type_t> PostCommand(
uint64_t RPC_ID,
APCommands::Commands Command,
const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,
const std::string &UUID,
bool & Sent) {
return PostCommand(RPC_ID,
Command,
SerialNumber,
return PostCommand(RPC_ID, SerialNumber,
Method,
Params,
UUID,
@@ -129,14 +120,12 @@ namespace OpenWifi {
std::shared_ptr<promise_type_t> PostCommandOneWay(
uint64_t RPC_ID,
APCommands::Commands Command,
const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,
const std::string &UUID,
bool & Sent) {
return PostCommand(RPC_ID,
Command,
SerialNumber,
Method,
Params,
@@ -164,7 +153,7 @@ namespace OpenWifi {
OutStandingRequests_.erase(Id);
}
inline bool CommandRunningForDevice(std::uint64_t SerialNumber, std::string & uuid, APCommands::Commands &command) {
inline bool CommandRunningForDevice(std::uint64_t SerialNumber, std::string & uuid, std::string &command) {
std::lock_guard Lock(LocalMutex_);
for(const auto &[Request,Command]:OutStandingRequests_) {
@@ -201,7 +190,6 @@ namespace OpenWifi {
std::shared_ptr<promise_type_t> PostCommand(
uint64_t RPCID,
APCommands::Commands Command,
const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,

View File

@@ -28,8 +28,6 @@
#include "rttys/RTTYS_server.h"
#include "framework/UI_WebSocketClientServer.h"
#include "UI_GW_WebSocketNotifications.h"
#include "ScriptManager.h"
#include "SignatureMgr.h"
namespace OpenWifi {
class Daemon *Daemon::instance() {
@@ -52,8 +50,6 @@ namespace OpenWifi {
RTTYS_server(),
RADIUS_proxy_server(),
VenueBroadcaster(),
ScriptManager(),
SignatureManager(),
AP_WS_Server()
});
return &instance;

View File

@@ -7,45 +7,14 @@
#include "framework/utils.h"
namespace OpenWifi {
bool DeviceDashboard::Get(GWObjects::Dashboard &D, Poco::Logger & Logger) {
void DeviceDashboard::Create() {
uint64_t Now = Utils::Now();
if(!ValidDashboard_ || LastRun_==0 || (Now-LastRun_)>120) {
Generate(D, Logger);
} else {
std::lock_guard G(DataMutex_);
D = DB_;
}
return ValidDashboard_;
};
void DeviceDashboard::Generate(GWObjects::Dashboard &D, Poco::Logger & Logger ) {
if (GeneratingDashboard_.load()) {
// std::cout << "Trying to generate dashboard but already being generated" << std::endl;
while(GeneratingDashboard_.load()) {
Poco::Thread::trySleep(100);
}
std::lock_guard G(DataMutex_);
D = DB_;
} else {
GeneratingDashboard_ = true;
ValidDashboard_ = false;
try {
// std::cout << "Generating dashboard." << std::endl;
poco_information(Logger, "DASHBOARD: Generating a new dashboard.");
GWObjects::Dashboard NewData;
StorageService()->AnalyzeCommands(NewData.commands);
StorageService()->AnalyzeDevices(NewData);
LastRun_ = Utils::Now();
NewData.snapshot = LastRun_;
D = NewData;
std::lock_guard G(DataMutex_);
DB_ = NewData;
ValidDashboard_=true;
} catch(...) {
}
GeneratingDashboard_ = false;
if(LastRun_==0 || (Now-LastRun_)>120) {
DB_.reset();
StorageService()->AnalyzeCommands(DB_.commands);
StorageService()->AnalyzeDevices(DB_);
LastRun_ = Now;
}
}
}

View File

@@ -4,24 +4,19 @@
#pragma once
#include <mutex>
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "framework/OpenWifiTypes.h"
#include "Poco/Logger.h"
namespace OpenWifi {
class DeviceDashboard {
public:
bool Get(GWObjects::Dashboard &D, Poco::Logger & Logger);
DeviceDashboard() { DB_.reset(); }
void Create();
[[nodiscard]] const GWObjects::Dashboard & Report() const { return DB_;}
private:
std::mutex DataMutex_;
volatile std::atomic_bool GeneratingDashboard_=false;
volatile bool ValidDashboard_=false;
GWObjects::Dashboard DB_;
uint64_t LastRun_=0;
void Generate(GWObjects::Dashboard &D, Poco::Logger & Logger);
GWObjects::Dashboard DB_;
uint64_t LastRun_=0;
inline void Reset() { DB_.reset(); }
};
}

View File

@@ -22,7 +22,7 @@ namespace OpenWifi {
struct UploadId {
std::string UUID;
std::uint64_t Expires;
std::uint64_t Expires;
std::string Type;
};

View File

@@ -291,8 +291,6 @@ static const struct tok radius_attribute_names[] = {
constexpr unsigned char CoA_ACK = 44;
constexpr unsigned char CoA_NAK = 45;
constexpr unsigned char ATTR_MessageAuthenticator = 80;
inline bool IsAuthentication(unsigned char t) {
return (t == RADIUS::Access_Request ||
t == RADIUS::Access_Accept ||
@@ -332,11 +330,6 @@ static const struct tok radius_attribute_names[] = {
return "Unknown";
}
inline void MakeRadiusAuthenticator(unsigned char *authenticator) {
for(int i=0;i<16;i++)
authenticator[i]=std::rand() & 0xff;
}
//
// From: https://github.com/Telecominfraproject/wlan-dictionary/blob/main/dictionary.tip
//
@@ -673,44 +666,6 @@ static const struct tok radius_attribute_names[] = {
bool Valid_=false;
};
class RadiusOutputPacket {
public:
explicit RadiusOutputPacket(const std::string &Secret)
: Secret_(Secret) {
}
inline void MakeStatusMessage() {
P_.code = RADCMD_STATUS_SER;
P_.identifier = std::rand() & 0x00ff;
MakeRadiusAuthenticator(P_.authenticator);
unsigned char MessageAuthenticator[16]{0};
AddAttribute(ATTR_MessageAuthenticator,sizeof(MessageAuthenticator),MessageAuthenticator);
P_.rawlen = 1 + 1 + 2 + 16 + 1 + 1 + 16;
Poco::HMACEngine<Poco::MD5Engine> H(Secret_);
H.update((const unsigned char *)&P_, P_.rawlen);
auto digest = H.digest();
int p = 0;
for (const auto &i : digest)
P_.attributes[1 + 1 + p++] = i;
}
inline void AddAttribute(unsigned char attr, uint8_t len, const unsigned char * data) {
P_.attributes[AttributesLen_++] = attr;
P_.attributes[AttributesLen_++] = len;
memcpy(&P_.attributes[AttributesLen_],data,len);
AttributesLen_+=len;
}
[[nodiscard]] inline const unsigned char * Data() const { return (const unsigned char *) &P_;}
[[nodiscard]] inline std::uint16_t Len() const { return P_.rawlen; }
private:
RawRadiusPacket P_;
uint16_t AttributesLen_=0;
std::string Secret_;
};
inline std::ostream &operator<<(std::ostream &os, RadiusPacket const &P) {
os << P.Attrs_ ;
return os;

View File

@@ -22,132 +22,124 @@ namespace OpenWifi {
ConfigFilename_ = MicroServiceDataDirectory()+"/radius_pool_config.json";
Poco::File Config(ConfigFilename_);
Enabled_ = MicroServiceConfigGetBool("radius.proxy.enable",false);
if(!Enabled_ && !Config.exists()) {
enabled_ = MicroServiceConfigGetBool("radius.proxy.enable",false);
if(!enabled_ && !Config.exists()) {
StopRADSECServers();
return 0;
}
poco_notice(Logger(),"Starting...");
Enabled_ = true;
enabled_ = true;
Poco::Net::SocketAddress AuthSockAddrV4(Poco::Net::AddressFamily::IPv4,
MicroServiceConfigGetInt("radius.proxy.authentication.port",DEFAULT_RADIUS_AUTHENTICATION_PORT));
AuthenticationSocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV4,true,true);
AuthenticationSocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV4,true);
Poco::Net::SocketAddress AuthSockAddrV6(Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.authentication.port",DEFAULT_RADIUS_AUTHENTICATION_PORT));
AuthenticationSocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV6,true,true);
AuthenticationSocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV6,true);
Poco::Net::SocketAddress AcctSockAddrV4(Poco::Net::AddressFamily::IPv4,
MicroServiceConfigGetInt("radius.proxy.accounting.port",DEFAULT_RADIUS_ACCOUNTING_PORT));
AccountingSocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV4,true,true);
AccountingSocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV4,true);
Poco::Net::SocketAddress AcctSockAddrV6(Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.accounting.port",DEFAULT_RADIUS_ACCOUNTING_PORT));
AccountingSocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV6,true,true);
AccountingSocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV6,true);
Poco::Net::SocketAddress CoASockAddrV4(Poco::Net::AddressFamily::IPv4,
MicroServiceConfigGetInt("radius.proxy.coa.port",DEFAULT_RADIUS_CoA_PORT));
CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4,true,true);
CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4,true);
Poco::Net::SocketAddress CoASockAddrV6(Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.coa.port",DEFAULT_RADIUS_CoA_PORT));
CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6,true,true);
CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6,true);
RadiusReactor_.reset();
RadiusReactor_ = std::make_unique<Poco::Net::SocketReactor>();
RadiusReactor_->addEventHandler(*AuthenticationSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
RadiusReactor_.addEventHandler(*AuthenticationSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
RadiusReactor_->addEventHandler(*AuthenticationSocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
RadiusReactor_.addEventHandler(*AuthenticationSocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
RadiusReactor_->addEventHandler(*AccountingSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
RadiusReactor_.addEventHandler(*AccountingSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
RadiusReactor_->addEventHandler(*AccountingSocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
RadiusReactor_.addEventHandler(*AccountingSocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
RadiusReactor_->addEventHandler(*CoASocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
RadiusReactor_.addEventHandler(*CoASocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnCoASocketReadable));
RadiusReactor_->addEventHandler(*CoASocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
RadiusReactor_.addEventHandler(*CoASocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnCoASocketReadable));
ParseConfig();
// start RADSEC servers...
StopRADSECServers();
StartRADSECServers();
RadiusReactorThread_.start(*RadiusReactor_);
RadiusReactorThread_.start(RadiusReactor_);
Utils::SetThreadName(RadiusReactorThread_,"rad:reactor");
Running_ = true;
running_ = true;
return 0;
}
void RADIUS_proxy_server::Stop() {
if(Enabled_ && Running_) {
poco_information(Logger(),"Stopping...");
RadiusReactor_->removeEventHandler(
poco_information(Logger(),"Stopping...");
if(enabled_ && running_) {
RadiusReactor_.removeEventHandler(
*AuthenticationSocketV4_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
RadiusReactor_->removeEventHandler(
RadiusReactor_.removeEventHandler(
*AuthenticationSocketV6_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
RadiusReactor_->removeEventHandler(
RadiusReactor_.removeEventHandler(
*AccountingSocketV4_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
RadiusReactor_->removeEventHandler(
RadiusReactor_.removeEventHandler(
*AccountingSocketV6_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
RadiusReactor_->removeEventHandler(
RadiusReactor_.removeEventHandler(
*CoASocketV4_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnCoASocketReadable));
RadiusReactor_->removeEventHandler(
RadiusReactor_.removeEventHandler(
*CoASocketV6_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnCoASocketReadable));
AuthenticationSocketV4_->close();
AuthenticationSocketV6_->close();
AccountingSocketV4_->close();
AccountingSocketV6_->close();
CoASocketV4_->close();
CoASocketV6_->close();
AuthenticationSocketV4_.reset();
AuthenticationSocketV6_.reset();
AccountingSocketV4_.reset();
AccountingSocketV6_.reset();
CoASocketV4_.reset();
CoASocketV6_.reset();
StopRADSECServers();
RadiusReactor_->stop();
RadiusReactor_.stop();
RadiusReactorThread_.join();
Running_=false;
poco_information(Logger(),"Stopped...");
enabled_=false;
running_=false;
}
poco_information(Logger(),"Stopped...");
}
void RADIUS_proxy_server::StartRADSECServers() {
std::lock_guard G(Mutex_);
for(const auto &pool:PoolList_.pools) {
for(const auto &entry:pool.authConfig.servers) {
if(entry.radsec) {
RADSECservers_[ Poco::Net::SocketAddress(entry.ip,0) ] = std::make_unique<RADSEC_server>(*RadiusReactor_,entry);
StartRADSECServer(entry);
}
}
}
}
void RADIUS_proxy_server::StopRADSECServers() {
std::lock_guard G(Mutex_);
RADSECservers_.clear();
}
void RADIUS_proxy_server::StartRADSECServer(const GWObjects::RadiusProxyServerEntry &E) {
RADSECservers_[ Poco::Net::SocketAddress(E.ip,0) ] = std::make_unique<RADSEC_server>(RadiusReactor_,E);
}
void RADIUS_proxy_server::OnAccountingSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) {
Poco::Net::SocketAddress Sender;
RADIUS::RadiusPacket P;
@@ -216,7 +208,7 @@ namespace OpenWifi {
void RADIUS_proxy_server::SendAccountingData(const std::string &serialNumber, const char *buffer, std::size_t size) {
if(!Continue())
if(Pools_.empty() || !enabled_)
return;
try {
@@ -274,7 +266,7 @@ namespace OpenWifi {
void RADIUS_proxy_server::SendAuthenticationData(const std::string &serialNumber, const char *buffer, std::size_t size) {
if(!Continue())
if(Pools_.empty() || !enabled_)
return;
try {
@@ -327,7 +319,7 @@ namespace OpenWifi {
void RADIUS_proxy_server::SendCoAData(const std::string &serialNumber, const char *buffer, std::size_t size) {
if(!Continue())
if(Pools_.empty() || !enabled_)
return;
try {
@@ -397,7 +389,7 @@ namespace OpenWifi {
};
if(setAsDefault && D.useRADSEC)
DefaultIsRADSEC_ = true;
defaultIsRADSEC_ = true;
if(S.family()==Poco::Net::IPAddress::IPv4) {
TotalV4 += server.weight;
@@ -491,26 +483,26 @@ namespace OpenWifi {
}
}
if(DefaultIsRADSEC_) {
if(defaultIsRADSEC_) {
UseRADSEC = true;
return (IsV4 ? Pools_[DefaultPoolIndex_].AuthV4[0].Addr : Pools_[DefaultPoolIndex_].AuthV6[0].Addr );
return (IsV4 ? Pools_[defaultPoolIndex_].AuthV4[0].Addr : Pools_[defaultPoolIndex_].AuthV6[0].Addr );
}
switch(rtype) {
case radius_type::auth: {
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].AuthV4
: Pools_[DefaultPoolIndex_].AuthV6,
return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].AuthV4
: Pools_[defaultPoolIndex_].AuthV6,
RequestedAddress);
}
case radius_type::acct:
default: {
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].AcctV4
: Pools_[DefaultPoolIndex_].AcctV6,
return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].AcctV4
: Pools_[defaultPoolIndex_].AcctV6,
RequestedAddress);
}
case radius_type::coa: {
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].CoaV4
: Pools_[DefaultPoolIndex_].CoaV6,
return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].CoaV4
: Pools_[defaultPoolIndex_].CoaV6,
RequestedAddress);
}
}
@@ -629,6 +621,7 @@ namespace OpenWifi {
void RADIUS_proxy_server::SetConfig(const GWObjects::RadiusProxyPoolList &C) {
std::lock_guard G(Mutex_);
PoolList_ = C;
Poco::JSON::Object Disk;
C.to_json(Disk);
@@ -637,17 +630,17 @@ namespace OpenWifi {
Disk.stringify(ofs);
ofs.close();
Stop();
ResetConfig();
PoolList_ = C;
Start();
if(!running_) {
Start();
}
ParseConfig();
}
void RADIUS_proxy_server::ResetConfig() {
PoolList_.pools.clear();
Pools_.clear();
DefaultPoolIndex_=0;
DefaultIsRADSEC_=false;
defaultPoolIndex_=0;
}
void RADIUS_proxy_server::DeleteConfig() {
@@ -660,8 +653,8 @@ namespace OpenWifi {
} catch (...) {
}
Stop();
ResetConfig();
Stop();
}
void RADIUS_proxy_server::GetConfig(GWObjects::RadiusProxyPoolList &C) {

View File

@@ -29,7 +29,7 @@ namespace OpenWifi {
int Start() final;
void Stop() final;
inline bool Enabled() const { return Enabled_; }
inline bool Enabled() const { return enabled_; }
void OnAccountingSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
void OnAuthenticationSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
@@ -44,6 +44,7 @@ namespace OpenWifi {
void GetConfig(GWObjects::RadiusProxyPoolList &C);
void StartRADSECServers();
void StartRADSECServer(const GWObjects::RadiusProxyServerEntry &E);
void StopRADSECServers();
struct Destination {
@@ -61,10 +62,6 @@ namespace OpenWifi {
std::vector<std::string> realms;
};
inline bool Continue() const {
return Running_ && Enabled_ && !Pools_.empty();
}
private:
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV4_;
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV6_;
@@ -72,8 +69,8 @@ namespace OpenWifi {
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV6_;
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV4_;
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_;
std::unique_ptr<Poco::Net::SocketReactor> RadiusReactor_;
Poco::Thread RadiusReactorThread_;
Poco::Net::SocketReactor RadiusReactor_;
Poco::Thread RadiusReactorThread_;
GWObjects::RadiusProxyPoolList PoolList_;
std::string ConfigFilename_;
@@ -90,10 +87,10 @@ namespace OpenWifi {
};
std::vector<RadiusPool> Pools_;
uint DefaultPoolIndex_=0;
bool Enabled_=false;
bool DefaultIsRADSEC_=false;
std::atomic_bool Running_=false;
uint defaultPoolIndex_=0;
bool enabled_=false;
bool defaultIsRADSEC_=false;
std::atomic_bool running_=false;
RADIUS_proxy_server() noexcept:
SubSystemServer("RADIUS-PROXY", "RADIUS-PROXY", "radius.proxy")

View File

@@ -33,17 +33,15 @@ namespace OpenWifi {
Logger_(Poco::Logger::get(fmt::format("RADSEC: {}@{}:{}",
Server_.name ,
Server_.ip,
Server_.port))) {
Start();
Server_.port)))
{
ReconnectThread_.start(*this);
}
~RADSEC_server() {
Stop();
}
inline int Start() {
ReconnectThread_.start(*this);
return 0;
if(ReconnectThread_.isRunning()) {
Stop();
}
}
inline void Stop() {
@@ -54,22 +52,12 @@ namespace OpenWifi {
}
inline void run() final {
Poco::Thread::trySleep(3000);
std::uint64_t LastStatus=0 ;
auto RadSecKeepAlive = MicroServiceConfigGetInt("radsec.keepalive",120);
while(TryAgain_) {
if(!Connected_) {
std::lock_guard G(LocalMutex_);
LastStatus = Utils::Now() ;
std::unique_lock G(Mutex_);
Connect();
} else if( (Utils::Now() - LastStatus) > RadSecKeepAlive) {
RADIUS::RadiusOutputPacket P(Server_.radsecSecret);
P.MakeStatusMessage();
poco_information(Logger_,"Keep-Alive message.");
Socket_->sendBytes(P.Data(), P.Len());
LastStatus = Utils::Now();
}
Poco::Thread::trySleep(!Connected_ ? 3000 : 10000);
Poco::Thread::trySleep(3000);
}
}
@@ -77,23 +65,22 @@ namespace OpenWifi {
try {
if (Connected_) {
RADIUS::RadiusPacket P(buffer, length);
// std::cout << serial_number << " Sending " << P.PacketType() << " " << length << " bytes" << std::endl;
int sent_bytes;
if (P.VerifyMessageAuthenticator(Server_.radsecSecret)) {
poco_debug(Logger_, fmt::format("{}: {} Sending {} bytes", serial_number,
P.PacketType(), length));
poco_debug(Logger_,fmt::format("{}: {} Sending {} bytes", serial_number,
P.PacketType(), length));
sent_bytes = Socket_->sendBytes(buffer, length);
} else {
poco_debug(Logger_, fmt::format("{}: {} Sending {} bytes", serial_number,
P.PacketType(), length));
poco_debug(Logger_,fmt::format("{}: {} Sending {} bytes", serial_number,
P.PacketType(), length));
P.ComputeMessageAuthenticator(Server_.radsecSecret);
sent_bytes = Socket_->sendBytes(P.Buffer(), length);
}
return (sent_bytes == length);
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
} catch (...) {
poco_warning(Logger_,"Exception occurred: while sending data.");
}
return false;
}
@@ -103,7 +90,7 @@ namespace OpenWifi {
try {
auto NumberOfReceivedBytes = Socket_->receiveBytes(Buffer,sizeof(Buffer));
if(NumberOfReceivedBytes>=20) {
if(NumberOfReceivedBytes>40) {
RADIUS::RadiusPacket P(Buffer,NumberOfReceivedBytes);
if (P.IsAuthentication()) {
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
@@ -114,7 +101,9 @@ namespace OpenWifi {
AP_WS_Server()->SendRadiusAuthenticationData(SerialNumber, Buffer,
NumberOfReceivedBytes);
} else {
poco_debug(Logger_, "AUTH packet dropped.");
poco_debug(Logger_,
fmt::format("Invalid AUTH packet received in proxy dropped. No serial number Source={}",
Socket_->address().toString()));
}
} else if (P.IsAccounting()) {
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
@@ -125,72 +114,53 @@ namespace OpenWifi {
AP_WS_Server()->SendRadiusAccountingData(SerialNumber, Buffer,
NumberOfReceivedBytes);
} else {
poco_debug(Logger_, "ACCT packet dropped.");
poco_debug(Logger_,
fmt::format("Invalid ACCT packet received in proxy dropped. No serial number Source={}",
Socket_->address().toString()));
}
} else if (P.IsAuthority()) {
auto SerialNumber = P.ExtractSerialNumberTIP();
if(!SerialNumber.empty()) {
poco_debug(Logger_,
fmt::format("{}: {} Received {} bytes.", SerialNumber,
P.PacketType(), NumberOfReceivedBytes));
AP_WS_Server()->SendRadiusCoAData(SerialNumber, Buffer,
NumberOfReceivedBytes);
} else {
poco_debug(Logger_, "CoA/DM packet dropped.");
}
} else {
poco_warning(Logger_,fmt::format("Unknown packet: Type: {} (type={}) Length={}", P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
}
} else {
poco_warning(Logger_,"Invalid packet received. Resetting the connection.");
Disconnect();
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
Disconnect();
} catch (...) {
Disconnect();
poco_warning(Logger_,"Exception occurred. Resetting the connection.");
}
}
inline void onError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf) {
poco_warning(Logger_,"Socker error. Terminating connection.");
std::cout << "onError" << std::endl;
Disconnect();
}
inline void onShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
poco_warning(Logger_,"Socker socket shutdown. Terminating connection.");
std::cout << "onShutdown" << std::endl;
Disconnect();
}
inline bool Connect() {
if(TryAgain_) {
std::lock_guard G(LocalMutex_);
Poco::TemporaryFile CertFile_(MicroServiceDataDirectory());
Poco::TemporaryFile KeyFile_(MicroServiceDataDirectory());
std::vector<std::unique_ptr<Poco::TemporaryFile>> CaCertFiles_;
std::vector<Poco::TemporaryFile> CaCertFiles_;
DecodeFile(CertFile_.path(), Server_.radsecCert);
DecodeFile(KeyFile_.path(), Server_.radsecKey);
for(auto &cert:Server_.radsecCacerts) {
CaCertFiles_.emplace_back(std::make_unique<Poco::TemporaryFile>(MicroServiceDataDirectory()));
DecodeFile(CaCertFiles_[CaCertFiles_.size()-1]->path(), cert);
CaCertFiles_.emplace_back(Poco::TemporaryFile(MicroServiceDataDirectory()));
DecodeFile(CaCertFiles_[CaCertFiles_.size()-1].path(), cert);
}
Poco::Net::Context::Ptr SecureContext = Poco::AutoPtr<Poco::Net::Context>(
new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE,
KeyFile_.path(),
CertFile_.path(),""));
if(Server_.allowSelfSigned) {
SecureContext->setSecurityLevel(Poco::Net::Context::SECURITY_LEVEL_NONE);
SecureContext->enableExtendedCertificateVerification(false);
}
for(const auto &ca:CaCertFiles_) {
Poco::Crypto::X509Certificate cert(ca->path());
Poco::Crypto::X509Certificate cert(ca.path());
SecureContext->addCertificateAuthority(cert);
}
@@ -202,10 +172,7 @@ namespace OpenWifi {
poco_information(Logger_, "Attempting to connect");
Socket_->connect(Destination, Poco::Timespan(100, 0));
Socket_->completeHandshake();
if(!Server_.allowSelfSigned) {
Socket_->verifyPeerCertificate();
}
Socket_->verifyPeerCertificate();
if(Socket_->havePeerCertificate()) {
Peer_Cert_ = std::make_unique<Poco::Crypto::X509Certificate>(Socket_->peerCertificate());
@@ -227,6 +194,9 @@ namespace OpenWifi {
*Socket_,
Poco::NObserver<RADSEC_server, Poco::Net::ShutdownNotification>(
*this, &RADSEC_server::onShutdown));
Socket_->setBlocking(false);
Socket_->setNoDelay(true);
Socket_->setKeepAlive(true);
Connected_ = true;
poco_information(Logger_,fmt::format("Connected. CN={}",CommonName()));
@@ -246,7 +216,7 @@ namespace OpenWifi {
inline void Disconnect() {
if(Connected_) {
std::lock_guard G(LocalMutex_);
std::unique_lock G(Mutex_);
Reactor_.removeEventHandler(
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ReadableNotification>(
@@ -257,7 +227,6 @@ namespace OpenWifi {
Reactor_.removeEventHandler(
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ShutdownNotification>(
*this, &RADSEC_server::onShutdown));
Socket_->close();
Connected_ = false;
}
poco_information(Logger_,"Disconnecting.");
@@ -290,7 +259,7 @@ namespace OpenWifi {
}
private:
std::recursive_mutex LocalMutex_;
std::recursive_mutex Mutex_;
Poco::Net::SocketReactor &Reactor_;
GWObjects::RadiusProxyServerEntry Server_;
Poco::Logger &Logger_;

View File

@@ -34,7 +34,6 @@ namespace OpenWifi::RESTAPI_RPC {
}
void WaitForCommand(uint64_t RPCID,
APCommands::Commands Command,
bool RetryLater,
GWObjects::CommandDetails &Cmd,
Poco::JSON::Object & Params,
@@ -65,7 +64,7 @@ namespace OpenWifi::RESTAPI_RPC {
bool Sent;
std::chrono::time_point<std::chrono::high_resolution_clock> rpc_submitted = std::chrono::high_resolution_clock::now();
std::shared_ptr<CommandManager::promise_type_t> rpc_endpoint =
CommandManager()->PostCommand(RPCID, Command, Cmd.SerialNumber, Cmd.Command, Params, Cmd.UUID, Sent);
CommandManager()->PostCommand(RPCID, Cmd.SerialNumber, Cmd.Command, Params, Cmd.UUID, Sent);
if(RetryLater && (!Sent || rpc_endpoint== nullptr)) {
Logger.information(fmt::format("{},{}: Pending completion. Device is not connected.", Cmd.UUID, RPCID));

View File

@@ -18,13 +18,10 @@
#include "StorageService.h"
#include "framework/RESTAPI_Handler.h"
#include "framework/ow_constants.h"
namespace OpenWifi::RESTAPI_RPC {
void WaitForCommand(
uint64_t RPCID,
APCommands::Commands Command,
bool RetryLater,
GWObjects::CommandDetails &Cmd,
Poco::JSON::Object & Params,

View File

@@ -20,8 +20,6 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
poco_debug(Logger(),fmt::format("BLACKLIST-DELETE: {}", SerialNumber));
GWObjects::BlackListedDevice D;
if(!StorageService()->GetBlackListDevice(SerialNumber, D)) {
return NotFound();
@@ -40,12 +38,14 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
poco_debug(Logger(),fmt::format("BLACKLIST-GET: {}", SerialNumber));
GWObjects::BlackListedDevice D;
if(!StorageService()->GetBlackListDevice(SerialNumber, D)) {
return NotFound();
}
return Object(D);
Poco::JSON::Object Answer;
D.to_json(Answer);
return ReturnObject(Answer);
}
void RESTAPI_blacklist::DoPost() {
@@ -60,8 +60,6 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
poco_debug(Logger(),fmt::format("BLACKLIST-POST: {}", D.serialNumber));
Poco::toLowerInPlace(D.serialNumber);
if(StorageService()->IsBlackListed(D.serialNumber)) {
return BadRequest(RESTAPI::Errors::SerialNumberExists);
@@ -72,8 +70,12 @@ namespace OpenWifi {
if(StorageService()->AddBlackListDevice(D)) {
GWObjects::BlackListedDevice CreatedDevice;
StorageService()->GetBlackListDevice(D.serialNumber,CreatedDevice);
return Object(CreatedDevice);
Poco::JSON::Object Answer;
CreatedDevice.to_json(Answer);
return ReturnObject(Answer);
}
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
@@ -90,8 +92,6 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
poco_debug(Logger(),fmt::format("BLACKLIST-PUT: {}", SerialNumber));
GWObjects::BlackListedDevice NewDevice;
if(!NewDevice.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -104,7 +104,10 @@ namespace OpenWifi {
GWObjects::BlackListedDevice CreatedDevice;
StorageService()->GetBlackListDevice(SerialNumber,CreatedDevice);
return Object(CreatedDevice);
Poco::JSON::Object Answer;
CreatedDevice.to_json(Answer);
return ReturnObject(Answer);
}
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}

View File

@@ -10,16 +10,22 @@
namespace OpenWifi {
void RESTAPI_blacklist_list::DoGet() {
poco_debug(Logger(),fmt::format("BLACKLIST-GET: Device serial number list"));
std::vector<GWObjects::BlackListedDevice> Devices;
Poco::JSON::Array Arr;
Poco::JSON::Object Answer;
if(QB_.CountOnly) {
auto Count = StorageService()->GetBlackListDeviceCount();
return ReturnCountOnly(Count);
} else if(StorageService()->GetBlackListDevices(QB_.Offset, QB_.Limit, Devices)) {
return Object("devices",Devices);
for(const auto &i:Devices) {
Poco::JSON::Object O;
i.to_json(O);
Arr.add(O);
}
}
NotFound();
Answer.set("devices", Arr);
return ReturnObject(Answer);
}
}

View File

@@ -20,7 +20,9 @@ namespace OpenWifi {
GWObjects::CommandDetails Command;
if (StorageService()->GetCommand(CommandUUID, Command)) {
return Object(Command);
Poco::JSON::Object RetObj;
Command.to_json(RetObj);
return ReturnObject(RetObj);
}
return NotFound();
}

View File

@@ -24,7 +24,15 @@ namespace OpenWifi {
StorageService()->GetCommands(SerialNumber, QB_.StartDate, QB_.EndDate, QB_.Offset, QB_.Limit,
Commands);
}
return Object(RESTAPI::Protocol::COMMANDS, Commands);
Poco::JSON::Array ArrayObj;
for (const auto &i : Commands) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::COMMANDS, ArrayObj);
ReturnObject(RetObj);
}
void RESTAPI_commands::DoDelete() {

View File

@@ -22,7 +22,9 @@ namespace OpenWifi {
std::string Name = ORM::Escape(GetBinding(RESTAPI::Protocol::NAME, ""));
GWObjects::DefaultConfiguration DefConfig;
if (StorageService()->GetDefaultConfiguration(Name, DefConfig)) {
return Object(DefConfig);
Poco::JSON::Object Obj;
DefConfig.to_json(Obj);
return ReturnObject(Obj);
}
NotFound();
}
@@ -104,9 +106,12 @@ namespace OpenWifi {
GWObjects::DefaultConfiguration ModifiedConfig;
StorageService()->GetDefaultConfiguration(Name,ModifiedConfig);
return Object(ModifiedConfig);
Poco::JSON::Object Answer;
ModifiedConfig.to_json(Answer);
return ReturnObject(Answer);
}
BadRequest(RESTAPI::Errors::RecordNotUpdated);
}
}

View File

@@ -23,6 +23,16 @@ namespace OpenWifi {
std::vector<GWObjects::DefaultConfiguration> DefConfigs;
StorageService()->GetDefaultConfigurations(QB_.Offset, QB_.Limit, DefConfigs);
return Object(RESTAPI::Protocol::CONFIGURATIONS, DefConfigs);
Poco::JSON::Array Objects;
for (const auto &i : DefConfigs) {
Poco::JSON::Object Obj;
i.to_json(Obj);
Objects.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::CONFIGURATIONS, Objects);
ReturnObject(RetObj);
}
}

View File

@@ -8,11 +8,9 @@
namespace OpenWifi {
void RESTAPI_deviceDashboardHandler::DoGet() {
poco_information(Logger(),fmt::format("GET-DASHBOARD: {}", Requester()));
GWObjects::Dashboard Data;
if(Daemon()->GetDashboard().Get(Data, Logger())) {
return Object(Data);
}
return BadRequest(RESTAPI::Errors::InternalError);
Daemon()->GetDashboard().Create();
Poco::JSON::Object Answer;
Daemon()->GetDashboard().Report().to_json(Answer);
ReturnObject(Answer);
}
}

View File

@@ -21,8 +21,6 @@
#include "TelemetryStream.h"
#include "CommandManager.h"
#include "SignatureMgr.h"
#include "framework/ConfigurationValidator.h"
#include "framework/KafkaTopics.h"
#include "framework/ow_constants.h"
@@ -52,40 +50,33 @@ namespace OpenWifi {
return NotFound();
}
auto Command = APCommands::to_apcommand(Command_.c_str());
if(Command==APCommands::Commands::unknown) {
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
Poco::Thread::current()->setName(fmt::format("{}:{}:{}", Command_, TransactionId_, SerialNumber_));
switch(Command) {
case APCommands::Commands::capabilities:
return GetCapabilities();
case APCommands::Commands::logs:
return GetLogs();
case APCommands::Commands::healthchecks:
return GetChecks();
case APCommands::Commands::statistics:
return GetStatistics();
case APCommands::Commands::status:
return GetStatus();
case APCommands::Commands::rtty: {
GWObjects::DeviceRestrictions Restrictions;
if(!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
auto UUID = MicroServiceCreateUUID();
auto RPC = CommandManager()->Next_RPC_ID();
poco_debug(Logger_,fmt::format("Command rtty TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
TransactionId_, UUID, RPC,
Poco::Thread::current()->id()));
return Rtty(UUID,RPC,60000ms, Restrictions);
};
default:
return BadRequest(RESTAPI::Errors::InvalidCommand);
if (Command_ == RESTAPI::Protocol::CAPABILITIES){
return GetCapabilities();
} else if (Command_ == RESTAPI::Protocol::LOGS) {
return GetLogs();
} else if (Command_ == RESTAPI::Protocol::HEALTHCHECKS) {
return GetChecks();
} else if (Command_ == RESTAPI::Protocol::STATISTICS) {
return GetStatistics();
} else if (Command_ == RESTAPI::Protocol::STATUS) {
return GetStatus();
} else if (Command_ == RESTAPI::Protocol::RTTY) {
AP_Restrictions Restrictions;
if(!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
auto UUID = MicroServiceCreateUUID();
auto RPC = CommandManager()->Next_RPC_ID();
poco_debug(Logger_,fmt::format("Command rtty TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
TransactionId_, UUID, RPC,
Poco::Thread::current()->id()));
return Rtty(UUID,RPC,60000ms, Restrictions);
} else {
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
}
@@ -103,50 +94,44 @@ namespace OpenWifi {
return NotFound();
}
auto Command = APCommands::to_apcommand(Command_.c_str());
if(Command==APCommands::Commands::unknown) {
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
Poco::Thread::current()->setName(fmt::format("{}:{}:{}",Command_, TransactionId_,SerialNumber_));
switch(Command) {
case APCommands::Commands::capabilities:
if (Command_ == RESTAPI::Protocol::CAPABILITIES) {
return DeleteCapabilities();
case APCommands::Commands::logs:
} else if (Command_ == RESTAPI::Protocol::LOGS){
return DeleteLogs();
case APCommands::Commands::healthchecks:
} else if (Command_ == RESTAPI::Protocol::HEALTHCHECKS){
return DeleteChecks();
case APCommands::Commands::statistics:
} else if (Command_ == RESTAPI::Protocol::STATISTICS) {
return DeleteStatistics();
default:
} else {
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
}
struct PostDeviceCommand {
APCommands::Commands Command=APCommands::Commands::unknown;
bool AllowParallel=false;
bool RequireConnection = true;
void (RESTAPI_device_commandHandler::*funPtr)(const std::string &, std::uint64_t, std::chrono::milliseconds, const GWObjects::DeviceRestrictions &R );
const char * Command;
bool AllowParallel=false;
bool RequireConnection = true;
void (RESTAPI_device_commandHandler::*funPtr)(const std::string &, std::uint64_t, std::chrono::milliseconds, const AP_Restrictions &R );
std::chrono::milliseconds Timeout=120ms;
};
static const std::vector<PostDeviceCommand> PostCommands =
const std::vector<PostDeviceCommand> PostCommands =
{
{ APCommands::Commands::configure, false, false, &RESTAPI_device_commandHandler::Configure, 120000ms },
{ APCommands::Commands::upgrade, false, false, &RESTAPI_device_commandHandler::Upgrade, 30000ms },
{ APCommands::Commands::reboot, false, true, &RESTAPI_device_commandHandler::Reboot, 30000ms },
{ APCommands::Commands::factory, false, false, &RESTAPI_device_commandHandler::Factory, 30000ms },
{ APCommands::Commands::leds, false, true, &RESTAPI_device_commandHandler::LEDs, 120000ms },
{ APCommands::Commands::trace, false, true, &RESTAPI_device_commandHandler::Trace, 300000ms },
{ APCommands::Commands::request, false, true, &RESTAPI_device_commandHandler::MakeRequest, 120000ms },
{ APCommands::Commands::wifiscan, false, true, &RESTAPI_device_commandHandler::WifiScan, 120000ms },
{ APCommands::Commands::eventqueue, false, true, &RESTAPI_device_commandHandler::EventQueue, 30000ms },
{ APCommands::Commands::telemetry, false, true, &RESTAPI_device_commandHandler::Telemetry, 30000ms },
{ APCommands::Commands::ping, false, true, &RESTAPI_device_commandHandler::Ping, 60000ms },
{ APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script, 300000ms }
{ RESTAPI::Protocol::CONFIGURE, false, false, &RESTAPI_device_commandHandler::Configure, 120000ms },
{ RESTAPI::Protocol::UPGRADE, false, false, &RESTAPI_device_commandHandler::Upgrade, 30000ms },
{ RESTAPI::Protocol::REBOOT, false, true, &RESTAPI_device_commandHandler::Reboot, 30000ms },
{ RESTAPI::Protocol::FACTORY, false, false, &RESTAPI_device_commandHandler::Factory, 30000ms },
{ RESTAPI::Protocol::LEDS, false, true, &RESTAPI_device_commandHandler::LEDs, 120000ms },
{ RESTAPI::Protocol::TRACE, false, true, &RESTAPI_device_commandHandler::Trace, 300000ms },
{ RESTAPI::Protocol::REQUEST, false, true, &RESTAPI_device_commandHandler::MakeRequest, 120000ms },
{ RESTAPI::Protocol::WIFISCAN, false, true, &RESTAPI_device_commandHandler::WifiScan, 120000ms },
{ RESTAPI::Protocol::EVENTQUEUE, false, true, &RESTAPI_device_commandHandler::EventQueue, 30000ms },
{ RESTAPI::Protocol::TELEMETRY, false, true, &RESTAPI_device_commandHandler::Telemetry, 30000ms },
{ RESTAPI::Protocol::PING, false, true, &RESTAPI_device_commandHandler::Ping, 60000ms },
{ RESTAPI::Protocol::SCRIPT, false, true, &RESTAPI_device_commandHandler::Script, 300000ms }
};
void RESTAPI_device_commandHandler::DoPost() {
@@ -156,39 +141,32 @@ namespace OpenWifi {
if(!Utils::NormalizeMac(SerialNumber_)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
auto Command = APCommands::to_apcommand(Command_.c_str());
if(Command==APCommands::Commands::unknown) {
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
GWObjects::Device TheDevice;
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
return NotFound();
}
for(const auto &PostCommand:PostCommands) {
if(Command==PostCommand.Command) {
Poco::Thread::current()->setName(fmt::format("{}:{}:{}",Command_, TransactionId_,SerialNumber_));
GWObjects::DeviceRestrictions Restrictions;
if(PostCommand.RequireConnection && !AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
for(const auto &Command:PostCommands) {
if(Command_==Command.Command) {
Poco::Thread::current()->setName(fmt::format("{}:{}:{}",Command.Command, TransactionId_,SerialNumber_));
AP_Restrictions Restrictions;
if(Command.RequireConnection && !AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
CallCanceled(Command.Command, RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
std::string Command_UUID;
APCommands::Commands CommandName;
if(!PostCommand.AllowParallel && CommandManager()->CommandRunningForDevice(SerialNumberInt_,Command_UUID,CommandName)) {
auto Extra = fmt::format("UUID={} Command={}", Command_UUID, APCommands::to_string(CommandName));
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
std::string Command_UUID, CommandName;
if(!Command.AllowParallel && CommandManager()->CommandRunningForDevice(SerialNumberInt_,Command_UUID,CommandName)) {
auto Extra = fmt::format("UUID={} Command={}", Command_UUID, CommandName);
CallCanceled(Command.Command, RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
return BadRequest(RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
}
auto UUID = MicroServiceCreateUUID();
auto RPC = CommandManager()->Next_RPC_ID();
poco_debug(Logger_,fmt::format("Command {} TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
Command_, TransactionId_, UUID, RPC,
Command.Command, TransactionId_, UUID, RPC,
Poco::Thread::current()->id()));
return (*this.*PostCommand.funPtr)(UUID,RPC,PostCommand.Timeout, Restrictions);
return (*this.*Command.funPtr)(UUID,RPC,Command.Timeout, Restrictions);
}
}
return BadRequest(RESTAPI::Errors::InvalidCommand);
@@ -229,9 +207,6 @@ namespace OpenWifi {
if (AP_WS_Server()->GetStatistics(SerialNumber_, Stats) && !Stats.empty()) {
return ReturnRawJSON(Stats);
}
if(AP_WS_Server()->Connected(SerialNumberInt_)) {
return BadRequest(RESTAPI::Errors::NoDeviceStatisticsYet);
}
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
@@ -251,13 +226,12 @@ namespace OpenWifi {
QB_.Offset, QB_.Limit, Stats);
}
Poco::JSON::Array::Ptr ArrayObj = Poco::SharedPtr<Poco::JSON::Array>(new Poco::JSON::Array);
Poco::JSON::Array ArrayObj;
for (const auto &i : Stats) {
Poco::JSON::Object::Ptr Obj = Poco::SharedPtr<Poco::JSON::Object>(new Poco::JSON::Object);
i.to_json(*Obj);
ArrayObj->add(Obj);
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::DATA, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
@@ -375,7 +349,7 @@ namespace OpenWifi {
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
}
void RESTAPI_device_commandHandler::Ping(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::Ping(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("PING({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
@@ -399,7 +373,7 @@ namespace OpenWifi {
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::ping,false,Cmd, Params, *Request, *Response, timeout, nullptr, nullptr, Logger_);
RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, nullptr, Logger_);
GWObjects::CommandDetails Cmd2;
if(StorageService()->GetCommand(CMD_UUID,Cmd2)) {
@@ -435,8 +409,12 @@ namespace OpenWifi {
return t=="shell" || t=="bundle";
}
void RESTAPI_device_commandHandler::Script(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::Script(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("SCRIPT({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if(!Internal_ && UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
const auto &Obj = ParsedBody_;
GWObjects::ScriptRequest SCR;
@@ -445,25 +423,11 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
bool DiagnosticScript = (SCR.type=="diagnostic");
if(!SCR.script.empty() && !SCR.scriptId.empty()) {
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::InvalidScriptSelection);
return UnAuthorized(RESTAPI::Errors::InvalidScriptSelection);
}
if(!Internal_ && UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && SCR.scriptId.empty()) {
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
if (SCR.script.empty() && SCR.scriptId.empty() && !DiagnosticScript) {
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::InvalidScriptSelection);
return BadRequest(RESTAPI::Errors::InvalidScriptSelection);
}
if(DiagnosticScript && (!SCR.scriptId.empty() || !SCR.script.empty())){
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::InvalidScriptSelection);
return BadRequest(RESTAPI::Errors::InvalidScriptSelection);
if (SCR.serialNumber.empty() ||
SCR.script.empty() ||
!ValidateScriptType(SCR.type)) {
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::MissingOrInvalidParameters);
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if (SerialNumber_ != SCR.serialNumber) {
@@ -471,48 +435,13 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
if(!SCR.uri.empty() && !Utils::ValidateURI(SCR.uri)) {
return BadRequest(RESTAPI::Errors::InvalidURI);
}
GWObjects::Device D;
if(!StorageService()->GetDevice(SerialNumber_,D)) {
return NotFound();
}
if(!SCR.scriptId.empty()) {
GWObjects::ScriptEntry Existing;
if(!StorageService()->ScriptDB().GetRecord("id",SCR.scriptId,Existing)) {
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::MissingOrInvalidParameters);
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
// verify the role...
if(Existing.restricted.empty() && UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
if (std::find(Existing.restricted.begin(), Existing.restricted.end(),
SecurityObjects::UserTypeToString(UserInfo_.userinfo.userRole)) ==
end(Existing.restricted)) {
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
}
poco_information(Logger_,fmt::format("SCRIPT({},{}): TID={} Name={}", CMD_UUID, CMD_RPC, TransactionId_, Existing.name));
SCR.script = Existing.content;
SCR.type = Existing.type;
if(!ParsedBody_->has("deferred"))
SCR.deferred = Existing.deferred;
if(!ParsedBody_->has("timeout"))
SCR.timeout = Existing.timeout;
} else {
if(!DiagnosticScript && !ValidateScriptType(SCR.type)) {
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::MissingOrInvalidParameters);
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if(D.restrictedDevice && SCR.signature.empty()) {
return BadRequest(RESTAPI::Errors::DeviceRequiresSignature);
}
uint64_t ap_timeout = SCR.timeout==0 ? 30 : SCR.timeout;
@@ -540,21 +469,8 @@ namespace OpenWifi {
if(!SCR.signature.empty()) {
Params.set(uCentralProtocol::SIGNATURE, SCR.signature);
}
if(D.restrictedDevice && SCR.signature.empty()) {
SCR.signature = SignatureManager()->Sign(R, SCR.script);
}
if(D.restrictedDevice && SCR.signature.empty()) {
return BadRequest(RESTAPI::Errors::DeviceRequiresSignature);
}
// convert script to base64 ...
auto EncodedScript = Utils::base64encode((const unsigned char *)SCR.script.c_str(),SCR.script.size());
Params.set(uCentralProtocol::TYPE, SCR.type);
if(!DiagnosticScript) {
Params.set(uCentralProtocol::SCRIPT, EncodedScript);
}
Params.set(uCentralProtocol::SCRIPT, SCR.script);
Params.set(uCentralProtocol::WHEN, SCR.when);
std::stringstream ParamStream;
@@ -562,10 +478,10 @@ namespace OpenWifi {
Cmd.Details = ParamStream.str();
FileUploader()->AddUUID(CMD_UUID, 15min, "script_result");
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::script,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
}
void RESTAPI_device_commandHandler::Configure(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::Configure(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("CONFIGURE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
@@ -610,14 +526,14 @@ namespace OpenWifi {
Cmd.Details = ParamStream.str();
// AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID);
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure,true,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
}
return BadRequest(RESTAPI::Errors::RecordNotUpdated);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::Upgrade(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::Upgrade(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("UPGRADE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
@@ -632,11 +548,16 @@ namespace OpenWifi {
}
GWObjects::Device DeviceInfo;
if(!StorageService()->GetDevice(SerialNumber_,DeviceInfo)) {
return NotFound();
}
std::string FWSignature = GetParameter("FWsignature","");
if(FWSignature.empty() && R.sysupgrade_not_allowed()) {
return BadRequest(RESTAPI::Errors::DeviceRequiresSignature);
}
auto URI = GetS(RESTAPI::Protocol::URI, Obj);
auto When = GetWhen(Obj);
@@ -655,32 +576,21 @@ namespace OpenWifi {
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::URI, URI);
Params.set(uCentralProtocol::KEEP_REDIRECTOR, KeepRedirector ? 1 : 0);
if(DeviceInfo.restrictionDetails.upgrade && FWSignature.empty()) {
Poco::URI uri(URI);
FWSignature = SignatureManager()->Sign(DeviceInfo.restrictionDetails,uri);
}
if(FWSignature.empty() && DeviceInfo.restrictionDetails.upgrade) {
return BadRequest(RESTAPI::Errors::DeviceRequiresSignature);
}
if(!FWSignature.empty()) {
Params.set(uCentralProtocol::SIGNATURE, FWSignature);
Params.set(uCentralProtocol::FWSIGNATURE, FWSignature);
}
Params.set(uCentralProtocol::WHEN, When);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::upgrade,true,Cmd,Params, *Request, *Response, timeout, nullptr, this, Logger_);
return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd,Params, *Request, *Response, timeout, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::Reboot(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::Reboot(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("REBOOT({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
@@ -709,12 +619,12 @@ namespace OpenWifi {
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::reboot, false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
void RESTAPI_device_commandHandler::Factory(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::Factory(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("FACTORY-RESET({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
@@ -749,12 +659,12 @@ namespace OpenWifi {
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::factory,true,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::LEDs(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::LEDs(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("LEDS({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
@@ -797,12 +707,12 @@ namespace OpenWifi {
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::leds,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::Trace(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::Trace(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("TRACE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
@@ -850,12 +760,12 @@ namespace OpenWifi {
Cmd.Details = ParamStream.str();
FileUploader()->AddUUID(CMD_UUID, 10min, "trace");
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::trace,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::WifiScan(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::WifiScan(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("WIFISCAN({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
@@ -885,7 +795,7 @@ namespace OpenWifi {
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
if(R.dfs && OverrideDFS) {
if(R.dfs_not_allowed() && OverrideDFS) {
return BadRequest(RESTAPI::Errors::DeviceIsRestricted);
}
@@ -899,13 +809,13 @@ namespace OpenWifi {
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::wifiscan,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
if (Cmd.ErrorCode == 0) {
KafkaManager()->PostMessage(KafkaTopics::WIFISCAN, SerialNumber_, Cmd.Results);
}
}
void RESTAPI_device_commandHandler::EventQueue(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::EventQueue(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("EVENT-QUEUE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
@@ -934,7 +844,7 @@ namespace OpenWifi {
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::eventqueue,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
if(Cmd.ErrorCode==0) {
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber_,
Cmd.Results);
@@ -944,7 +854,7 @@ namespace OpenWifi {
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::MakeRequest(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::MakeRequest(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("FORCE-REQUEST({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
@@ -981,17 +891,15 @@ namespace OpenWifi {
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::request,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_ );
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_ );
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
#define DBGLINE { std::cout << __LINE__ << std::endl; }
void RESTAPI_device_commandHandler::Rtty(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
void RESTAPI_device_commandHandler::Rtty(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
poco_information(Logger_,fmt::format("RTTY({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if(R.rtty) {
if(R.rtty_not_allowed()) {
return BadRequest(RESTAPI::Errors::DeviceIsRestricted);
}
@@ -999,15 +907,14 @@ namespace OpenWifi {
GWObjects::Device Device;
if (StorageService()->GetDevice(SerialNumber_, Device)) {
static std::uint64_t rtty_sid = 0;
rtty_sid += std::rand();
GWObjects::RttySessionDetails Rtty{
.SerialNumber = SerialNumber_,
.Server = MicroServiceConfigGetString("rtty.server", "localhost"),
.Port = MicroServiceConfigGetInt("rtty.port", 5912),
.Token = MicroServiceConfigGetString("rtty.token", "nothing"),
.TimeOut = MicroServiceConfigGetInt("rtty.timeout", 60),
.ConnectionId = Utils::ComputeHash(SerialNumber_,Utils::Now(),rtty_sid).substr(0,RTTY_DEVICE_TOKEN_LENGTH),
.ConnectionId = Utils::ComputeHash(SerialNumber_,Utils::Now()).substr(0,RTTY_DEVICE_TOKEN_LENGTH),
.Started = Utils::Now(),
.CommandUUID = CMD_UUID,
.ViewPort = MicroServiceConfigGetInt("rtty.viewport", 5913),
@@ -1047,7 +954,7 @@ namespace OpenWifi {
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
poco_information(Logger_,fmt::format("RTTY: user={} serial={} rttyid={} token={} cmd={}.", Requester(), SerialNumber_, Rtty.ConnectionId, Rtty.Token, CMD_UUID));
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::rtty,false,Cmd, Params, *Request, *Response, timeout, &ReturnedObject, this, Logger_);
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, &ReturnedObject, this, Logger_);
}
return NotFound();
}
@@ -1055,7 +962,9 @@ namespace OpenWifi {
return ReturnStatus(Poco::Net::HTTPResponse::HTTP_SERVICE_UNAVAILABLE);
}
void RESTAPI_device_commandHandler::Telemetry(const std::string &CMD_UUID, uint64_t CMD_RPC, [[maybe_unused]] std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R){
// #define DBG { std::cout << __LINE__ << std::endl; }
void RESTAPI_device_commandHandler::Telemetry(const std::string &CMD_UUID, uint64_t CMD_RPC, [[maybe_unused]] std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R){
poco_information(Logger_,fmt::format("TELEMETRY({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_;
@@ -1072,6 +981,7 @@ namespace OpenWifi {
std::stringstream oooss;
Obj->stringify(oooss);
// std::cout << "Payload:" << oooss.str() << std::endl;
std::uint64_t Lifetime = 60 * 60 ; // 1 hour
std::uint64_t Interval = 5;

View File

@@ -9,7 +9,7 @@
#pragma once
#include "framework/RESTAPI_Handler.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
#include "AP_restrictions.h"
namespace OpenWifi {
class RESTAPI_device_commandHandler : public RESTAPIHandler {
@@ -34,19 +34,19 @@ namespace OpenWifi {
void GetChecks();
void DeleteChecks();
void Configure(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void Upgrade(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void Reboot(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void Factory(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void LEDs(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void Trace(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void MakeRequest(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void WifiScan(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void EventQueue(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void Rtty(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void Telemetry(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void Ping(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void Script(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
void Configure(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void Upgrade(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void Reboot(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void Factory(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void LEDs(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void Trace(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void MakeRequest(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void WifiScan(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void EventQueue(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void Rtty(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void Telemetry(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void Ping(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
void Script(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
static auto PathName() { return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"}; };
void DoGet() final;

View File

@@ -32,7 +32,9 @@ namespace OpenWifi {
CompleteDeviceInfo(Device, Answer);
return ReturnObject(Answer);
} else {
return Object(Device);
Poco::JSON::Object Obj;
Device.to_json(Obj);
return ReturnObject(Obj);
}
}
NotFound();
@@ -137,7 +139,9 @@ namespace OpenWifi {
if (StorageService()->CreateDevice(Device)) {
SetCurrentConfigurationID(SerialNumber, Device.UUID);
return Object(Device);
Poco::JSON::Object DevObj;
Device.to_json(DevObj);
return ReturnObject(DevObj);
}
InternalError(RESTAPI::Errors::RecordNotCreated);
}
@@ -187,9 +191,9 @@ namespace OpenWifi {
Existing.LastConfigurationChange = Utils::Now();
if (StorageService()->UpdateDevice(Existing)) {
SetCurrentConfigurationID(SerialNumber, Existing.UUID);
GWObjects::Device UpdatedDevice;
StorageService()->GetDevice(SerialNumber, UpdatedDevice);
return Object(UpdatedDevice);
Poco::JSON::Object DevObj;
NewDevice.to_json(DevObj);
return ReturnObject(DevObj);
}
InternalError(RESTAPI::Errors::RecordNotUpdated);
}

View File

@@ -25,12 +25,7 @@ namespace OpenWifi {
if (!StorageService()->GetAttachedFileContent(UUID, SerialNumber, FileContent, FileType)) {
return NotFound();
}
if(FileType=="pcap")
SendFileContent(FileContent,"application/vnd.tcpdump.pcap",UUID+".pcap");
else if(FileType=="gzip")
SendFileContent(FileContent,"application/gzip",UUID+".tar.gz");
else
SendFileContent(FileContent,"application/txt",UUID+".txt");
SendFileContent(FileContent,"pcap",UUID+".pcap");
}
void RESTAPI_file::DoDelete() {

View File

@@ -14,7 +14,9 @@ namespace OpenWifi {
Poco::Thread::current()->id()));
GWObjects::RadiusProxyPoolList C;
RADIUS_proxy_server()->GetConfig(C);
return Object(C);
Poco::JSON::Object Answer;
C.to_json(Answer);
return ReturnObject(Answer);
}
void RESTAPI_radiusProxyConfig_handler::DoDelete() {
@@ -75,7 +77,7 @@ namespace OpenWifi {
TransactionId_, Requester(),
Poco::Thread::current()->id()));
RADIUS_proxy_server()->SetConfig(C);
return Object(C);
return ReturnObject(*ParsedBody_);
}
}

View File

@@ -18,8 +18,6 @@
#include "RESTAPI/RESTAPI_telemetryWebSocket.h"
#include "RESTAPI/RESTAPI_iptocountry_handler.h"
#include "RESTAPI/RESTAPI_radiusProxyConfig_handler.h"
#include "RESTAPI/RESTAPI_script_handler.h"
#include "RESTAPI/RESTAPI_scripts_handler.h"
#include "framework/RESTAPI_SystemCommand.h"
#include "framework/RESTAPI_WebSocketServer.h"
@@ -48,8 +46,6 @@ namespace OpenWifi {
RESTAPI_blacklist_list,
RESTAPI_iptocountry_handler,
RESTAPI_radiusProxyConfig_handler,
RESTAPI_scripts_handler,
RESTAPI_script_handler,
RESTAPI_capabilities_handler, RESTAPI_telemetryWebSocket>(Path,Bindings,L, S, TransactionId);
}
@@ -69,8 +65,6 @@ namespace OpenWifi {
RESTAPI_blacklist,
RESTAPI_iptocountry_handler,
RESTAPI_radiusProxyConfig_handler,
RESTAPI_scripts_handler,
RESTAPI_script_handler,
RESTAPI_blacklist_list>(Path,Bindings,L, S, TransactionId);
}
}

View File

@@ -1,160 +0,0 @@
//
// Created by stephane bourque on 2022-11-21.
//
#include "RESTAPI_script_handler.h"
namespace OpenWifi {
void RESTAPI_script_handler::DoGet() {
std::string UUID = GetBinding("uuid","");
if(UUID.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
GWObjects::ScriptEntry SE;
if(DB_.GetRecord("id",UUID, SE)) {
return Object(SE);
}
return NotFound();
}
void RESTAPI_script_handler::DoDelete() {
std::string UUID = GetBinding("uuid","");
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
}
if(UUID.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if(DB_.DeleteRecord("id",UUID)) {
return OK();
}
return NotFound();
}
void RESTAPI_script_handler::DoPost() {
std::string UUID = GetBinding("uuid","");
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
}
if(UUID.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
GWObjects::ScriptEntry SE;
if(!SE.from_json(ParsedBody_)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if( SE.name.empty() ||
SE.author.empty() ||
(SE.type!="bundle" && SE.type!="shell") ||
SE.content.empty() ||
SE.version.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if(!SE.restricted.empty()) {
for(const auto &role:SE.restricted) {
if(SecurityObjects::UserTypeFromString(role)==SecurityObjects::UNKNOWN) {
return BadRequest(RESTAPI::Errors::InvalidUserRole);
}
}
std::sort(SE.restricted.begin(),SE.restricted.end());
}
if(!SE.uri.empty() && !Utils::ValidateURI(SE.uri)) {
return BadRequest(RESTAPI::Errors::InvalidURI);
}
if(!SE.defaultUploadURI.empty() && !Utils::ValidateURI(SE.defaultUploadURI)) {
return BadRequest(RESTAPI::Errors::InvalidURI);
}
SE.id = MicroServiceCreateUUID();
SE.created = SE.modified = Utils::Now();
if(DB_.CreateRecord(SE)) {
return Object(SE);
}
return BadRequest(RESTAPI::Errors::RecordNotCreated);
}
void RESTAPI_script_handler::DoPut() {
std::string UUID = GetBinding("uuid","");
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
}
if(UUID.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
GWObjects::ScriptEntry SE;
if(!SE.from_json(ParsedBody_)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(!SE.restricted.empty()) {
for(const auto &role:SE.restricted) {
if(SecurityObjects::UserTypeFromString(role)==SecurityObjects::UNKNOWN) {
return BadRequest(RESTAPI::Errors::InvalidUserRole);
}
}
std::sort(SE.restricted.begin(),SE.restricted.end());
}
GWObjects::ScriptEntry Existing;
if(!DB_.GetRecord("id", UUID, Existing)) {
return NotFound();
}
if(ParsedBody_->has("name") && SE.name.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if(ParsedBody_->has("content") && SE.content.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if(ParsedBody_->has("version") && SE.version.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if(!SE.uri.empty() && !Utils::ValidateURI(SE.uri)) {
return BadRequest(RESTAPI::Errors::InvalidURI);
}
if(!SE.defaultUploadURI.empty() && !Utils::ValidateURI(SE.defaultUploadURI)) {
return BadRequest(RESTAPI::Errors::InvalidURI);
}
if(ParsedBody_->has("restricted")) {
Existing.restricted = SE.restricted;
}
AssignIfPresent(ParsedBody_, "name", Existing.name);
AssignIfPresent(ParsedBody_, "description", Existing.description);
AssignIfPresent(ParsedBody_, "uri", Existing.uri);
AssignIfPresent(ParsedBody_, "content", Existing.content);
AssignIfPresent(ParsedBody_, "version", Existing.version);
AssignIfPresent(ParsedBody_, "deferred", Existing.deferred);
AssignIfPresent(ParsedBody_, "timeout", Existing.timeout);
AssignIfPresent(ParsedBody_, "defaultUploadURI", Existing.defaultUploadURI);
Existing.modified = Utils::Now();
if(DB_.UpdateRecord("id", UUID, Existing)) {
return Object(Existing);
}
return BadRequest(RESTAPI::Errors::RecordNotUpdated);
}
} // namespace OpenWifi

View File

@@ -1,31 +0,0 @@
//
// Created by stephane bourque on 2022-11-21.
//
#pragma once
#include "framework/RESTAPI_Handler.h"
#include "StorageService.h"
namespace OpenWifi {
class RESTAPI_script_handler : public RESTAPIHandler {
public:
RESTAPI_script_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_PUT,
Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal){};
static auto PathName() { return std::list<std::string>{"/api/v1/script/{uuid}"}; };
private:
ScriptDB & DB_{ StorageService()->ScriptDB() };
void DoGet() final;
void DoDelete() final;
void DoPost() final;
void DoPut() final;
};
}

View File

@@ -1,20 +0,0 @@
//
// Created by stephane bourque on 2022-11-21.
//
#include "RESTAPI_scripts_handler.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
#include "StorageService.h"
namespace OpenWifi {
void RESTAPI_scripts_handler::DoGet() {
GWObjects::ScriptEntryList L;
StorageService()->ScriptDB().GetRecords(QB_.Offset,QB_.Limit,L.scripts);
Poco::JSON::Object Answer;
L.to_json(Answer);
return ReturnObject(Answer);
}
} // namespace OpenWifi

View File

@@ -1,25 +0,0 @@
//
// Created by stephane bourque on 2022-11-21.
//
#pragma once
#include "framework/RESTAPI_Handler.h"
namespace OpenWifi {
class RESTAPI_scripts_handler : public RESTAPIHandler {
public:
RESTAPI_scripts_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal){};
static auto PathName() { return std::list<std::string>{"/api/v1/scripts"}; };
void DoGet() final;
void DoDelete() final{};
void DoPost() final{};
void DoPut() final{};
};
}

View File

@@ -51,9 +51,7 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"modified", modified);
field_to_json(Obj,"locale", locale);
field_to_json(Obj,"restrictedDevice", restrictedDevice);
field_to_json(Obj,"pendingConfiguration", pendingConfiguration);
field_to_json(Obj,"pendingConfigurationCmd", pendingConfigurationCmd);
field_to_json(Obj,"restrictionDetails", restrictionDetails);
}
void Device::to_json_with_status(Poco::JSON::Object &Obj) const {
@@ -95,9 +93,6 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj,"entity", entity);
field_from_json(Obj,"locale", locale);
field_from_json(Obj,"restrictedDevice", restrictedDevice);
field_from_json(Obj,"pendingConfiguration", pendingConfiguration);
field_from_json(Obj,"pendingConfigurationCmd", pendingConfigurationCmd);
field_from_json(Obj,"restrictionDetails", restrictionDetails);
return true;
} catch (const Poco::Exception &E) {
}
@@ -309,7 +304,6 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"serialNumber",serialNumber);
field_to_json(Obj,"timeout",timeout);
field_to_json(Obj,"type",type);
field_to_json(Obj,"scriptId",scriptId);
field_to_json(Obj,"script",script);
field_to_json(Obj,"when",when);
field_to_json(Obj,"signature", signature);
@@ -323,7 +317,6 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj,"timeout",timeout);
field_from_json(Obj,"type",type);
field_from_json(Obj,"script",script);
field_from_json(Obj,"scriptId",scriptId);
field_from_json(Obj,"when",when);
field_from_json(Obj,"signature", signature);
field_from_json(Obj,"deferred", deferred);
@@ -399,7 +392,6 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"secret",secret);
field_to_json(Obj,"certificate",certificate);
field_to_json(Obj,"radsec",radsec);
field_to_json(Obj,"allowSelfSigned",allowSelfSigned);
field_to_json(Obj,"radsecPort",radsecPort);
field_to_json(Obj,"radsecSecret",radsecSecret);
field_to_json(Obj,"radsecCacerts",radsecCacerts);
@@ -418,7 +410,6 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj,"secret",secret);
field_from_json(Obj,"certificate",certificate);
field_from_json(Obj,"radsec",radsec);
field_from_json(Obj,"allowSelfSigned",allowSelfSigned);
field_from_json(Obj,"radsecSecret",radsecSecret);
field_from_json(Obj,"radsecPort",radsecPort);
field_from_json(Obj,"radsecCacerts",radsecCacerts);
@@ -431,117 +422,5 @@ namespace OpenWifi::GWObjects {
}
return false;
}
void ScriptEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"name", name);
field_to_json(Obj,"description", description);
field_to_json(Obj,"uri", uri);
field_to_json(Obj,"content", content);
field_to_json(Obj,"version", version);
field_to_json(Obj,"type", type);
field_to_json(Obj,"created", created);
field_to_json(Obj,"modified", modified);
field_to_json(Obj,"author", author);
field_to_json(Obj,"restricted", restricted);
field_to_json(Obj,"deferred", deferred);
field_to_json(Obj,"timeout", timeout);
field_to_json(Obj,"defaultUploadURI", defaultUploadURI);
}
bool ScriptEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"name", name);
field_from_json(Obj,"description", description);
field_from_json(Obj,"uri", uri);
field_from_json(Obj,"content", content);
field_from_json(Obj,"version", version);
field_from_json(Obj,"type", type);
field_from_json(Obj,"created", created);
field_from_json(Obj,"modified", modified);
field_from_json(Obj,"author", author);
field_from_json(Obj,"restricted", restricted);
field_from_json(Obj,"deferred", deferred);
field_from_json(Obj,"timeout", timeout);
field_from_json(Obj,"defaultUploadURI", defaultUploadURI);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void ScriptEntryList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"scripts",scripts);
}
bool ScriptEntryList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"scripts",scripts);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void DeviceRestrictionsKeyInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"vendor", vendor);
field_to_json(Obj,"algo", algo);
}
bool DeviceRestrictionsKeyInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"vendor", vendor);
field_from_json(Obj,"algo", algo);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void DeviceRestrictions::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"dfs", dfs);
field_to_json(Obj,"ssh", ssh);
field_to_json(Obj,"rtty", rtty);
field_to_json(Obj,"tty", tty);
field_to_json(Obj,"developer", developer);
field_to_json(Obj,"upgrade", upgrade);
field_to_json(Obj,"commands", commands);
field_to_json(Obj,"country", country);
field_to_json(Obj,"key_info", key_info);
}
bool DeviceRestrictions::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"dfs", dfs);
field_from_json(Obj,"ssh", ssh);
field_from_json(Obj,"rtty", rtty);
field_from_json(Obj,"tty", tty);
field_from_json(Obj,"developer", developer);
field_from_json(Obj,"upgrade", upgrade);
field_from_json(Obj,"commands", commands);
field_from_json(Obj,"country", country);
field_from_json(Obj,"key_info", key_info);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool DeviceRestrictionsKeyInfo::operator!=(const OpenWifi::GWObjects::DeviceRestrictionsKeyInfo &T) const {
return (T.algo!=algo) || (T.vendor!=vendor);
}
bool DeviceRestrictions::operator!=(const OpenWifi::GWObjects::DeviceRestrictions &T) const {
return ( (T.dfs!=dfs) ||
(T.rtty!=rtty) ||
(T.upgrade!=upgrade) ||
(T.commands != commands) ||
(T.developer != developer) ||
(T.ssh !=ssh) ||
(T.key_info != key_info) ||
(T.country != country) );
}
}

View File

@@ -47,33 +47,6 @@ namespace OpenWifi::GWObjects {
void to_json(Poco::JSON::Object &Obj) const;
};
struct DeviceRestrictionsKeyInfo {
std::string vendor;
std::string algo;
bool operator !=(const DeviceRestrictionsKeyInfo &b) const;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct DeviceRestrictions {
bool dfs = false;
bool ssh = false;
bool rtty = false;
bool tty = false;
bool developer = false;
bool upgrade = false;
bool commands = false;
std::vector<std::string> country;
DeviceRestrictionsKeyInfo key_info;
bool operator !=(const DeviceRestrictions &D) const;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct Device {
std::string SerialNumber;
std::string DeviceType;
@@ -98,9 +71,6 @@ namespace OpenWifi::GWObjects {
uint64_t modified=0;
std::string locale;
bool restrictedDevice=false;
std::string pendingConfiguration;
std::string pendingConfigurationCmd;
DeviceRestrictions restrictionDetails;
void to_json(Poco::JSON::Object &Obj) const;
void to_json_with_status(Poco::JSON::Object &Obj) const;
@@ -246,39 +216,11 @@ namespace OpenWifi::GWObjects {
void to_json(Poco::JSON::Object &Obj) const;
};
struct ScriptEntry {
std::string id;
std::string name;
std::string description;
std::string uri;
std::string content;
std::string version;
std::string type;
std::uint64_t created;
std::uint64_t modified;
std::string author;
Types::StringVec restricted;
bool deferred=false;
std::uint64_t timeout=30;
std::string defaultUploadURI;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct ScriptEntryList {
std::vector<ScriptEntry> scripts;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct ScriptRequest {
std::string serialNumber;
uint64_t timeout=30;
std::string type;
std::string script;
std::string scriptId;
std::uint64_t when;
std::string signature;
bool deferred;
@@ -296,7 +238,6 @@ namespace OpenWifi::GWObjects {
std::string secret;
std::string certificate;
bool radsec=false;
bool allowSelfSigned=false;
uint16_t radsecPort=2083;
std::string radsecSecret;
std::string radsecKey;
@@ -338,5 +279,4 @@ namespace OpenWifi::GWObjects {
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
}

View File

@@ -1,23 +0,0 @@
//
// Created by stephane bourque on 2022-11-21.
//
#include "ScriptManager.h"
#include "framework/MicroServiceFuncs.h"
#include <fstream>
#include "Poco/JSON/Parser.h"
namespace OpenWifi {
int ScriptManager::Start() {
poco_notice(Logger(),"Starting...");
ScriptDir_ = MicroServiceConfigPath("script.manager.directory", MicroServiceDataDirectory() + "/included_scripts" );
return 0;
}
void ScriptManager::Stop() {
poco_notice(Logger(),"Stopping...");
poco_notice(Logger(),"Stopped...");
}
} // namespace OpenWifi

View File

@@ -1,34 +0,0 @@
//
// Created by stephane bourque on 2022-11-21.
//
#pragma once
#include "framework/SubSystemServer.h"
namespace OpenWifi {
class ScriptManager : public SubSystemServer {
public:
static auto instance() {
auto static instance_ = new ScriptManager;
return instance_;
}
int Start();
void Stop();
private:
std::string ScriptDir_;
explicit ScriptManager() noexcept:
SubSystemServer("ScriptManager", "SCRIPT-MGR", "script.manager")
{
}
};
inline auto ScriptManager() { return ScriptManager::instance(); }
} // namespace OpenWifi

View File

@@ -1,7 +0,0 @@
//
// Created by stephane bourque on 2022-11-22.
//
#include "SignatureMgr.h"
namespace OpenWifi {} // namespace OpenWifi

View File

@@ -1,176 +0,0 @@
//
// Created by stephane bourque on 2022-11-22.
//
#pragma once
#include <fstream>
#include <shared_mutex>
#include "framework/SubSystemServer.h"
#include "framework/MicroServiceFuncs.h"
#include "framework/utils.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
#include "Poco/DigestStream.h"
#include "Poco/DigestEngine.h"
#include "Poco/Crypto/RSADigestEngine.h"
#include "Poco/StreamCopier.h"
#include "Poco/File.h"
#include "Poco/StringTokenizer.h"
#include "Poco/TemporaryFile.h"
#include "fmt/format.h"
namespace OpenWifi {
class SignatureManager : public SubSystemServer {
public:
inline static auto instance() {
static auto instance_ = new SignatureManager;
return instance_;
}
struct SignatureCacheEntry {
std::string vendor_uri_hash;
std::string signature;
};
inline int Start() final {
poco_notice(Logger(),"Starting...");
std::shared_lock L(KeyMutex_);
CacheFilename_ = MicroServiceDataDirectory() + "/signature_cache";
Poco::File CacheFile(CacheFilename_);
if(CacheFile.exists()) {
std::fstream CacheFileContent(CacheFilename_, std::ios_base::in);
std::string line;
while(std::getline(CacheFileContent, line)) {
auto Tokens = Poco::StringTokenizer(line,":");
if(Tokens.count()==2) {
SignatureCache_[Tokens[0]] = Tokens[1];
}
}
}
poco_information(Logger(),fmt::format("Found {} entries in signature cache.", SignatureCache_.size()));
// read all the key vendors.
// signature.manager.0.key.public
// signature.manager.0.key.private
// signature.manager.0.vendor
int i=0;
while(true) {
auto Vendor = MicroServiceConfigGetString("signature.manager." + std::to_string(i) + ".vendor","");
auto PrivateKey = MicroServiceConfigPath("signature.manager." + std::to_string(i) + ".key.private","");
auto PublicKey = MicroServiceConfigPath("signature.manager." + std::to_string(i) + ".key.public","");
if(Vendor.empty() || PrivateKey.empty() || PublicKey.empty()) {
break;
}
Poco::File PubKey(PublicKey), PrivKey(PrivateKey);
if(PubKey.exists() && PrivKey.exists()) {
Keys_[Vendor] = Poco::SharedPtr<Poco::Crypto::RSAKey>(
new Poco::Crypto::RSAKey(PublicKey, PrivateKey, ""));
}
++i;
}
poco_information(Logger(),fmt::format("{} signatures in dictionary.", Keys_.size()));
return 0;
}
inline void Stop() final {
poco_notice(Logger(),"Stopping...");
poco_notice(Logger(),"Stopped...");
}
inline std::string Sign(const GWObjects::DeviceRestrictions &Restrictions, const std::string &Data) const {
std::shared_lock L(KeyMutex_);
try {
if (Restrictions.key_info.algo == "static") {
return "aaaaaaaaaa";
}
auto Vendor = Keys_.find(Restrictions.key_info.vendor);
if (Vendor == Keys_.end()) {
poco_error( Logger(), fmt::format("{}: vendor unknown.", Vendor->first));
return "";
}
if (Restrictions.key_info.algo == "dgst-sha256") {
Poco::Crypto::RSADigestEngine R(*Vendor->second, "SHA256");
Poco::DigestOutputStream ostr(R);
ostr << Data;
ostr.flush();
auto Signature = Utils::base64encode(
(const unsigned char *)R.signature().data(), R.signature().size());
return Signature;
}
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return "";
}
inline std::string Sign(const GWObjects::DeviceRestrictions &Restrictions, const Poco::URI &uri) {
std::shared_lock L(KeyMutex_);
try {
if (Restrictions.key_info.algo == "static") {
return "aaaaaaaaaa";
}
auto Vendor = Keys_.find(Restrictions.key_info.vendor);
if (Vendor == Keys_.end()) {
poco_error( Logger(), fmt::format("{}: vendor unknown.", Restrictions.key_info.vendor));
return "";
}
if (Restrictions.key_info.algo == "dgst-sha256") {
auto FileHash =
Utils::ComputeHash(Restrictions.key_info.vendor, Restrictions.key_info.algo, uri.getPathAndQuery());
auto CacheEntry = SignatureCache_.find(FileHash);
if (CacheEntry != end(SignatureCache_)) {
return CacheEntry->second;
}
Poco::TemporaryFile TempDownloadedFile;
if (Utils::wgetfile(uri, TempDownloadedFile.path())) {
Poco::Crypto::RSADigestEngine R(*Vendor->second, "SHA256");
Poco::DigestOutputStream ofs(R);
std::fstream ifs(TempDownloadedFile.path(),
std::ios_base::in | std::ios_base::binary);
Poco::StreamCopier::copyStream(ifs, ofs);
ofs.flush();
auto Signature = Utils::base64encode((const unsigned char *)R.signature().data(),R.signature().size());
SignatureCache_[FileHash] = Signature;
SaveCache();
return Signature;
}
}
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return "";
}
void SaveCache() {
std::ofstream ofs(CacheFilename_, std::ios_base::trunc | std::ios_base::out);
for(const auto &[hash,signature]:SignatureCache_) {
ofs << hash << ":" << signature << std::endl;
}
}
private:
mutable std::shared_mutex KeyMutex_;
std::map<std::string, Poco::SharedPtr<Poco::Crypto::RSAKey>> Keys_;
std::map<std::string,std::string> SignatureCache_;
std::string CacheFilename_;
explicit SignatureManager() noexcept
: SubSystemServer("SignatureManager", "SIGNATURE-MGR", "signature.manager") {}
};
inline auto SignatureManager() { return SignatureManager::instance(); }
}

View File

@@ -12,14 +12,7 @@ namespace OpenWifi::StateUtils {
return 5;
}
static int BandToInt(const std::string &band) {
if(band=="2G") return 2;
if(band=="5G") return 5;
if(band=="6G") return 6;
return 2;
}
bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject,
bool ComputeAssociations(const Poco::JSON::Object::Ptr & RawObject,
uint64_t &Radios_2G,
uint64_t &Radios_5G, uint64_t &Radios_6G) {
Radios_2G = 0 ;
@@ -31,56 +24,47 @@ namespace OpenWifi::StateUtils {
// map of phy to 2g/5g
std::map<std::string,int> RadioPHYs;
// parse radios and get the phy out with the band
bool UseBandInfo = false;
for(auto const &i:*RA) {
// Poco::JSON::Parser p2;
Poco::JSON::Parser p2;
auto RadioObj = i.extract<Poco::JSON::Object::Ptr>();
if(RadioObj->has("band")) {
// std::cout << "Use band info" << std::endl;
UseBandInfo = true ;
} else if(RadioObj->has("phy") && RadioObj->has("channel")) {
if(RadioObj->has("phy") && RadioObj->has("channel")) {
if(RadioObj->isArray("channel")) {
auto ChannelArray = RadioObj->getArray("channel");
if(ChannelArray->size()) {
RadioPHYs[RadioObj->get("phy")] =
RadioPHYs[RadioObj->get("phy").toString()] =
ChannelToBand( ChannelArray->getElement<uint64_t>(0) );
}
} else {
RadioPHYs[RadioObj->get("phy")] =
RadioPHYs[RadioObj->get("phy").toString()] =
ChannelToBand(RadioObj->get("channel"));
}
}
}
auto InterfaceArray = RawObject->getArray("interfaces");
for(auto const &interface:*InterfaceArray) {
auto InterfaceObj = interface.extract<Poco::JSON::Object::Ptr>();
auto IA = RawObject->getArray("interfaces");
for(auto const &i:*IA) {
auto InterfaceObj = i.extract<Poco::JSON::Object::Ptr>();
if(InterfaceObj->isArray("ssids")) {
auto SSIDArray = InterfaceObj->getArray("ssids");
for(const auto &ssid:*SSIDArray) {
auto SSID_info = ssid.extract<Poco::JSON::Object::Ptr>();
if(SSID_info->isArray("associations") && SSID_info->has("phy")) {
auto SSIDA = InterfaceObj->getArray("ssids");
for(const auto &s:*SSIDA) {
auto SSIDinfo = s.extract<Poco::JSON::Object::Ptr>();
if(SSIDinfo->isArray("associations") && SSIDinfo->has("phy")) {
auto PHY = SSIDinfo->get("phy").toString();
int Radio = 2;
if(UseBandInfo) {
Radio = BandToInt(SSID_info->get("band"));
} else {
auto PHY = SSID_info->get("phy");
auto Rit = RadioPHYs.find(PHY);
if (Rit != RadioPHYs.end())
Radio = Rit->second;
auto Rit = RadioPHYs.find(PHY);
if(Rit!=RadioPHYs.end())
Radio = Rit->second;
auto AssocA = SSIDinfo->getArray("associations");
if(Radio==2) {
Radios_2G += AssocA->size();
}
auto AssocA = SSID_info->getArray("associations");
switch(Radio) {
case 2: Radios_2G += AssocA->size(); break;
case 5: Radios_5G += AssocA->size(); break;
case 6: Radios_6G += AssocA->size(); break;
default: Radios_2G += AssocA->size(); break;
else {
Radios_5G += AssocA->size();
}
}
}
}
}
// std::cout << Radios_2G << " " << Radios_5G << " " << Radios_6G << std::endl;
return true;
}
return false;

View File

@@ -7,6 +7,6 @@
#include "Poco/JSON/Object.h"
namespace OpenWifi::StateUtils {
bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
bool ComputeAssociations(const Poco::JSON::Object::Ptr & RawObject, uint64_t &Radios_2G,
uint64_t &Radios_5G, uint64_t &Radio_6G);
}

View File

@@ -18,40 +18,36 @@ namespace OpenWifi {
void Archiver::onTimer([[maybe_unused]] Poco::Timer &timer){
Utils::SetThreadName("strg-archiver");
auto now = Utils::Now();
for(const auto &[DBName, Keep]:DBs_) {
if (!Poco::icompare(DBName, "healthchecks")) {
for(const auto &i:DBs_) {
if (!Poco::icompare(i.DBName, "healthchecks")) {
poco_information(Logger(),"Archiving HealthChecks...");
StorageService()->RemoveHealthChecksRecordsOlderThan(
now - (Keep * 24 * 60 * 60));
} else if (!Poco::icompare(DBName, "statistics")) {
now - (i.HowManyDays * 24 * 60 * 60));
} else if (!Poco::icompare(i.DBName, "statistics")) {
poco_information(Logger(),"Archiving Statistics...");
StorageService()->RemoveStatisticsRecordsOlderThan(
now - (Keep * 24 * 60 * 60));
} else if (!Poco::icompare(DBName, "devicelogs")) {
now - (i.HowManyDays * 24 * 60 * 60));
} else if (!Poco::icompare(i.DBName, "devicelogs")) {
poco_information(Logger(),"Archiving Device Logs...");
StorageService()->RemoveDeviceLogsRecordsOlderThan(
now - (Keep * 24 * 60 * 60));
} else if (!Poco::icompare(DBName, "commandlist")) {
now - (i.HowManyDays * 24 * 60 * 60));
} else if (!Poco::icompare(i.DBName, "commandlist")) {
poco_information(Logger(),"Archiving Command History...");
StorageService()->RemoveCommandListRecordsOlderThan(
now - (Keep * 24 * 60 * 60));
} else if (!Poco::icompare(DBName, "fileuploads")) {
poco_information(Logger(),"Archiving Upload files...");
StorageService()->RemoveUploadedFilesRecordsOlderThan(
now - (Keep * 24 * 60 * 60));
now - (i.HowManyDays * 24 * 60 * 60));
} else {
poco_information(Logger(),fmt::format("Cannot archive DB '{}'", DBName));
poco_information(Logger(),fmt::format("Cannot archive DB '{}'", i.DBName));
}
}
AppServiceRegistry().Set("lastStorageArchiverRun", (uint64_t) now);
}
static auto CalculateDelta(std::uint64_t H, std::uint64_t M) {
static auto CalculateDelta(int H, int M) {
Poco::LocalDateTime dt;
Poco::LocalDateTime scheduled(dt.year(), dt.month(), dt.day(), (int)H, (int)M, 0);
Poco::LocalDateTime scheduled(dt.year(), dt.month(), dt.day(), H, M, 0);
std::uint64_t delta = 0;
if ((dt.hour() < (int)H) || (dt.hour()==(int)H && dt.minute()<(int)M)) {
size_t delta = 0;
if ((dt.hour() < H) || (dt.hour()==H && dt.minute()<M)) {
delta = scheduled.timestamp().epochTime() - dt.timestamp().epochTime();
} else {
delta = (24*60*60) - (dt.timestamp().epochTime() - scheduled.timestamp().epochTime());
@@ -73,13 +69,13 @@ namespace OpenWifi {
auto Schedule = MicroServiceConfigGetString("archiver.schedule","03:00");
auto S = Poco::StringTokenizer(Schedule,":");
std::uint64_t RunAtHour_, RunAtMin_;
int RunAtHour_, RunAtMin_;
if(S.count()!=2) {
RunAtHour_ = 3 ;
RunAtMin_ = 0;
} else {
RunAtHour_ = std::strtoull(S[0].c_str(), nullptr, 10);
RunAtMin_ = std::strtoull(S[1].c_str(), nullptr, 10);
RunAtHour_ = std::atoi(S[0].c_str());
RunAtMin_ = std::atoi(S[1].c_str());
}
for(int i=0;i<20;i++) {
@@ -90,7 +86,10 @@ namespace OpenWifi {
if(Poco::icompare(DBName,DB)==0) {
std::string Key = "archiver.db." + std::to_string(i) + ".keep";
auto Keep = MicroServiceConfigGetInt(Key,7);
Archiver_->AddDb(DB, Keep);
Archiver_->AddDb(Archiver::ArchiverDBEntry{
.DBName = DB,
.HowManyDays = Keep
});
}
}
}

View File

@@ -13,26 +13,28 @@
namespace OpenWifi {
static const std::list<std::string> AllInternalDBNames{"healthchecks", "statistics", "devicelogs" , "commandlist", "fileuploads"};
static const std::list<std::string> AllInternalDBNames{"healthchecks", "statistics", "devicelogs" , "commandlist" };
class Archiver {
public:
struct ArchiverDBEntry {
std::string DBName;
uint64_t HowManyDays=7;
};
typedef std::vector<ArchiverDBEntry> ArchiverDBEntryVec;
explicit Archiver(Poco::Logger &Logger):
Logger_(Logger) {
for(const auto &db:AllInternalDBNames) {
DBs_[db] = 7 ;
}
}
void onTimer(Poco::Timer & timer);
inline void AddDb(const std::string &dbname, std::uint64_t retain) {
DBs_[dbname] = retain;
inline void AddDb(const ArchiverDBEntry &E ) {
DBs_.push_back(E);
}
inline Poco::Logger & Logger() { return Logger_; }
private:
Poco::Logger &Logger_;
std::map<std::string,std::uint64_t> DBs_;
Poco::Logger &Logger_;
ArchiverDBEntryVec DBs_;
};
class StorageArchiver : public SubSystemServer {

View File

@@ -17,10 +17,6 @@ namespace OpenWifi {
Create_Tables();
InitializeBlackListCache();
ScriptDB_ = std::make_unique<OpenWifi::ScriptDB>("Scripts", "scr", dbType_,*Pool_, Logger());
ScriptDB_->Create();
ScriptDB_->Initialize();
return 0;
}

View File

@@ -12,7 +12,6 @@
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "Poco/Net/IPAddress.h"
#include "CentralConfig.h"
#include "storage/storage_scripts.h"
namespace OpenWifi {
@@ -30,8 +29,6 @@ namespace OpenWifi {
COMMAND_EXECUTING
};
inline OpenWifi::ScriptDB & ScriptDB() { return *ScriptDB_; }
inline std::string to_string(const CommandExecutionType &C) {
switch(C) {
case CommandExecutionType::COMMAND_PENDING: return "pending";
@@ -150,8 +147,10 @@ namespace OpenWifi {
bool GetReadyToExecuteCommands( uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::CommandDetails> & Commands );
bool CommandExecuted(std::string & UUID);
bool CommandCompleted(std::string & UUID, Poco::JSON::Object::Ptr ReturnVars, const std::chrono::duration<double, std::milli> & execution_time, bool FullCommand);
// bool AttachFileToCommand(std::string & UUID);
bool AttachFileDataToCommand(std::string & UUID, const std::stringstream &s, const std::string &Type);
bool CancelWaitFile( std::string & UUID, std::string & ErrorText );
// bool GetAttachedFile(std::string & UUID, const std::string & SerialNumber, const std::string & FileName, std::string &Type);
bool GetAttachedFileContent(std::string & UUID, const std::string & SerialNumber, std::string & FileContent, std::string &Type);
bool RemoveAttachedFile(std::string & UUID);
bool SetCommandResult(std::string & UUID, std::string & Result);
@@ -178,7 +177,6 @@ namespace OpenWifi {
bool RemoveDeviceLogsRecordsOlderThan(uint64_t Date);
bool RemoveStatisticsRecordsOlderThan(uint64_t Date);
bool RemoveCommandListRecordsOlderThan(uint64_t Date);
bool RemoveUploadedFilesRecordsOlderThan(uint64_t Date);
int Create_Tables();
int Create_Statistics();
@@ -199,8 +197,6 @@ namespace OpenWifi {
private:
std::unique_ptr<OpenWifi::ScriptDB> ScriptDB_;
};
inline auto StorageService() { return Storage::instance(); }

View File

@@ -51,13 +51,7 @@ namespace OpenWifi {
poco_information(Logger(),"Starting...");
Running_=true;
Port_ = (int)MicroServiceConfigGetInt("alb.port",15015);
Poco::Net::IPAddress Addr(Poco::Net::IPAddress::wildcard(
Poco::Net::Socket::supportsIPv6() ? Poco::Net::AddressFamily::IPv6
: Poco::Net::AddressFamily::IPv4));
Poco::Net::SocketAddress SockAddr(Addr, Port_);
Poco::Net::ServerSocket ClientSocket(SockAddr, 64);
Socket_ = std::make_unique<Poco::Net::ServerSocket>(SockAddr, Port_);
Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_);
auto Params = new Poco::Net::HTTPServerParams;
Params->setName("ws:alb");
Server_ = std::make_unique<Poco::Net::HTTPServer>(new ALBRequestHandlerFactory(Logger()), *Socket_, Params);

File diff suppressed because it is too large Load Diff

View File

@@ -245,7 +245,7 @@ namespace OpenWifi {
Poco::Logger::root().setChannel(Splitter);
}
}
Poco::Logger::root().information(fmt::format("Enabled console logs: asynch={} websocket={}",UseAsync,DisableWebSocketLogging));
}
void MicroService::SetColorConsoleLogs(bool UseAsync, bool DisableWebSocketLogging, const std::string & FormatterPattern) {
@@ -274,7 +274,7 @@ namespace OpenWifi {
Poco::Logger::root().setChannel(Splitter);
}
}
Poco::Logger::root().information(fmt::format("Enabled color console logs: asynch={} websocket={}",UseAsync,DisableWebSocketLogging));
}
void MicroService::SetSQLLogs([[maybe_unused]] bool UseAsync,[[maybe_unused]] bool DisableWebSocketLogging,[[maybe_unused]] const std::string & FormatterPattern) {
@@ -327,7 +327,6 @@ namespace OpenWifi {
Poco::Logger::root().setChannel(Splitter);
}
}
Poco::Logger::root().information(fmt::format("Enabled file logs: asynch={} websocket={}",UseAsync,DisableWebSocketLogging));
}
void DaemonPostInitialization(Poco::Util::Application &self);

View File

@@ -102,48 +102,6 @@ namespace OpenWifi {
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::TimeoutException &E) {
poco_error(App_.logger(), fmt::format("Poco::TimeoutException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::NoThreadAvailableException &E) {
poco_error(App_.logger(), fmt::format("Poco::NoThreadAvailableException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::OutOfMemoryException &E) {
poco_error(App_.logger(), fmt::format("Poco::OutOfMemoryException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::BadCastException &E) {
poco_error(App_.logger(), fmt::format("Poco::BadCastException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::DataException &E) {
poco_error(App_.logger(), fmt::format("Poco::DataException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::PoolOverflowException &E) {
poco_error(App_.logger(), fmt::format("Poco::PoolOverflowException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::SystemException &E) {
poco_error(App_.logger(), fmt::format("Poco::SystemException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::RuntimeException &E) {
poco_error(App_.logger(), fmt::format("Poco::RuntimeException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),

View File

@@ -633,18 +633,6 @@ namespace OpenWifi {
ReturnObject(Answer);
}
template<typename T> void Object(const char *Name, const std::vector<T> & Objects) {
Poco::JSON::Object Answer;
RESTAPI_utils::field_to_json(Answer,Name,Objects);
ReturnObject(Answer);
}
template <typename T> void Object(const T &O) {
Poco::JSON::Object Answer;
O.to_json(Answer);
ReturnObject(Answer);
}
Poco::Logger & Logger() { return Logger_; }
virtual void DoGet() = 0 ;

View File

@@ -119,7 +119,7 @@ namespace OpenWifi {
}
bool UI_WebSocketClientServer::SendToUser(const std::string &UserName, std::uint64_t id, const std::string &Payload) {
std::lock_guard G(LocalMutex_);
std::lock_guard G(Mutex_);
for(const auto &Client:Clients_) {
if(Client.second->UserName_ == UserName) {
@@ -139,7 +139,7 @@ namespace OpenWifi {
}
void UI_WebSocketClientServer::SendToAll(std::uint64_t id, const std::string &Payload) {
std::lock_guard G(LocalMutex_);
std::lock_guard G(Mutex_);
for(const auto &Client:Clients_) {
try {
@@ -189,6 +189,7 @@ namespace OpenWifi {
void UI_WebSocketClientServer::OnSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
UI_WebSocketClientServer::ClientList::iterator Client;
std::lock_guard G(LocalMutex_);
try {
@@ -294,7 +295,6 @@ namespace OpenWifi {
void UI_WebSocketClientServer::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
try {
std::lock_guard G(LocalMutex_);
auto Client = Clients_.find(pNf->socket().impl()->sockfd());
if (Client == end(Clients_))
return;

View File

@@ -229,11 +229,7 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg ApiKeyDoesNotExist{1150,"API Key does not exist."};
static const struct msg DeviceIsRestricted{1151,"Device is protected by regulation. This function is not allowed."};
static const struct msg InvalidURI{1152,"Invalid URI."};
static const struct msg InvalidScriptSelection{1153,"Only script or scriptId must be specified. Not both."};
static const struct msg NoDeviceStatisticsYet{1154,"Device statistics not available yet."};
}
}
@@ -528,63 +524,6 @@ namespace OpenWifi::uCentralProtocol::Events {
};
}
namespace OpenWifi::APCommands {
enum class Commands:uint8_t {
capabilities,
logs,
healthchecks,
statistics,
status,
rtty,
configure,
upgrade,
reboot,
factory,
leds,
trace,
request,
wifiscan,
eventqueue,
telemetry,
ping,
script,
unknown
};
inline static const std::vector<const char *> uCentralAPCommands {
RESTAPI::Protocol::CAPABILITIES,
RESTAPI::Protocol::LOGS,
RESTAPI::Protocol::HEALTHCHECKS,
RESTAPI::Protocol::STATISTICS,
RESTAPI::Protocol::STATUS,
RESTAPI::Protocol::RTTY,
RESTAPI::Protocol::CONFIGURE,
RESTAPI::Protocol::UPGRADE,
RESTAPI::Protocol::REBOOT,
RESTAPI::Protocol::FACTORY,
RESTAPI::Protocol::LEDS,
RESTAPI::Protocol::TRACE,
RESTAPI::Protocol::REQUEST,
RESTAPI::Protocol::WIFISCAN,
RESTAPI::Protocol::EVENTQUEUE,
RESTAPI::Protocol::TELEMETRY,
RESTAPI::Protocol::PING,
RESTAPI::Protocol::SCRIPT};
inline const char * to_string(Commands Cmd) {
return uCentralAPCommands[(uint8_t)Cmd];
}
inline Commands to_apcommand(const char *cmd) {
for(auto i=(uint8_t)Commands::capabilities;i!=(uint8_t)Commands::unknown;++i) {
if(strcmp(uCentralAPCommands[i],cmd)==0)
return (Commands)i;
}
return Commands::unknown;
}
}
namespace OpenWifi::Provisioning::DeviceClass {
static const char * ANY = "any";

View File

@@ -487,25 +487,6 @@ void ReplaceVariables( std::string & Content , const Types::StringPairVec & P) {
return false;
}
[[nodiscard]] bool wgetfile(const Poco::URI &uri, const std::string &FileName) {
try {
Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort());
// send request
Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_GET, uri.getPath(), Poco::Net::HTTPMessage::HTTP_1_1);
session.sendRequest(req);
Poco::Net::HTTPResponse res;
std::istream &is = session.receiveResponse(res);
std::fstream os(FileName,std::ios_base::trunc | std::ios_base::binary | std::ios_base::out);
Poco::StreamCopier::copyStream(is,os);
return true;
} catch (...) {
}
return false;
}
bool ExtractBase64CompressedData(const std::string &CompressedData,
std::string &UnCompressedData, uint64_t compress_sz ) {
std::istringstream ifs(CompressedData);
@@ -550,14 +531,4 @@ bool ExtractBase64CompressedData(const std::string &CompressedData,
return "*******";
}
[[nodiscard]] bool ValidateURI(const std::string &uri) {
try {
Poco::URI u(uri);
return true;
} catch (...) {
}
return false;
}
}

View File

@@ -11,7 +11,6 @@
#include <random>
#include <regex>
#include <thread>
#include <shared_mutex>
#include "Poco/Thread.h"
#include "Poco/StringTokenizer.h"
@@ -116,10 +115,8 @@ namespace OpenWifi::Utils {
[[nodiscard]] std::string BinaryFileToHexString(const Poco::File &F);
[[nodiscard]] std::string SecondsToNiceText(uint64_t Seconds);
[[nodiscard]] bool wgets(const std::string &URL, std::string &Response);
[[nodiscard]] bool wgetfile(const Poco::URI &uri, const std::string &FileName);
[[nodiscard]] bool IsAlphaNumeric(const std::string &s);
[[nodiscard]] bool IsAlphaNumeric(const std::string &s);
[[nodiscard]] std::string SanitizeToken(const std::string &Token);
[[nodiscard]] bool ValidateURI(const std::string &uri);
template< typename T >
std::string int_to_hex( T i )
@@ -129,23 +126,6 @@ namespace OpenWifi::Utils {
<< std::hex << i;
return stream.str();
}
inline bool SpinLock_Read(std::shared_mutex &M, volatile bool &Flag, uint64_t wait_ms=100) {
while(!M.try_lock_shared() && Flag) {
Poco::Thread::yield();
Poco::Thread::trySleep((long)wait_ms);
}
return Flag;
}
inline bool SpinLock_Write(std::shared_mutex &M, volatile bool &Flag, uint64_t wait_ms=100) {
while(!M.try_lock() && Flag) {
Poco::Thread::yield();
Poco::Thread::trySleep(wait_ms);
}
return Flag;
}
bool ExtractBase64CompressedData(const std::string &CompressedData,
std::string &UnCompressedData, uint64_t compress_sz );
}

View File

@@ -0,0 +1,175 @@
//
// Created by stephane bourque on 2021-11-23.
//
#include "RTTYS_ClientConnection.h"
#include "rttys/RTTYS_device.h"
#include "rttys/RTTYS_server.h"
#include "fmt/format.h"
#include "nlohmann/json.hpp"
namespace OpenWifi {
RTTYS_ClientConnection::RTTYS_ClientConnection(
Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response,
Poco::Net::SocketReactor &reactor,
const std::string &Id)
:
Reactor_(reactor),
Id_(Id),
Logger_(Poco::Logger::get(fmt::format("RTTY-client({})",Id_)))
{
Valid_ = true;
WS_ = std::make_unique<Poco::Net::WebSocket>(request,response);
WS_->setBlocking(false);
WS_->setNoDelay(true);
WS_->setKeepAlive(true);
Registered_ = true;
Reactor_.addEventHandler(
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
*this, &RTTYS_ClientConnection::onSocketReadable));
Reactor_.addEventHandler(
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
*this, &RTTYS_ClientConnection::onSocketShutdown));
Logger_.information("Starting connection");
}
RTTYS_ClientConnection::~RTTYS_ClientConnection() {
poco_information(Logger_,
fmt::format("Client {} session ending", Id_)
);
DeRegister();
}
void RTTYS_ClientConnection::DeRegister() {
Valid_ = false;
if(Registered_) {
Registered_ = false;
Reactor_.removeEventHandler(
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
*this, &RTTYS_ClientConnection::onSocketReadable));
Reactor_.removeEventHandler(
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
*this, &RTTYS_ClientConnection::onSocketShutdown));
}
}
void RTTYS_ClientConnection::EndConnection() {
DeRegister();
RTTYS_server()->NotifyClientDisconnect(Id_, this);
}
void RTTYS_ClientConnection::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
bool MustDisconnect = false;
{
if(!Valid_ || !Registered_)
return;
std::lock_guard G(Mutex_);
try {
int flags;
Poco::Buffer<char> IncomingFrame(0);
auto n = WS_->receiveFrame(IncomingFrame, flags);
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
switch (Op) {
case Poco::Net::WebSocket::FRAME_OP_PING: {
WS_->sendFrame("", 0,
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
} break;
case Poco::Net::WebSocket::FRAME_OP_PONG: {
} break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
if (n == 0) {
Logger_.information("Socket readable shutdown.");
MustDisconnect = true;
} else {
std::string s((char *)IncomingFrame.begin(), IncomingFrame.size());
try {
auto Doc = nlohmann::json::parse(s);
if (Doc.contains("type")) {
auto Type = Doc["type"];
if (Type == "winsize") {
auto cols = Doc["cols"];
auto rows = Doc["rows"];
if (!RTTYS_server()->WindowSize(Id_, cols, rows)) {
Logger_.information("Winsize shutdown.");
MustDisconnect = true;
}
}
}
} catch (...) {
// just ignore parse errors
Logger_.information("Frame text exception shutdown.");
MustDisconnect = true;
}
}
} break;
case Poco::Net::WebSocket::FRAME_OP_BINARY: {
if (n == 0) {
Logger_.information("Frame binary size shutdown.");
MustDisconnect = true;
} else {
poco_trace(Logger_, fmt::format("Sending {} key strokes to device.", n));
if (!RTTYS_server()->SendKeyStrokes(
Id_, (const unsigned char *)IncomingFrame.begin(),
IncomingFrame.size())) {
Logger_.information("Sendkeystrokes shutdown.");
MustDisconnect = true;
}
}
} break;
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
Logger_.information("Frame frame close shutdown.");
MustDisconnect = true;
} break;
default: {
}
}
} catch (...) {
Logger_.information("Frame readable shutdown.");
MustDisconnect = true;
}
}
if(MustDisconnect) {
EndConnection();
}
}
void RTTYS_ClientConnection::SendData( const u_char *Buf, size_t len ) {
if(!Valid_ || !Registered_)
return;
try {
WS_->sendFrame(Buf, len,
Poco::Net::WebSocket::FRAME_FLAG_FIN |
Poco::Net::WebSocket::FRAME_OP_BINARY);
return;
} catch (...) {
Logger_.information("SendData shutdown.");
}
EndConnection();
}
void RTTYS_ClientConnection::SendData( const std::string &s) {
if(!Valid_ || !Registered_)
return;
try {
WS_->sendFrame(s.c_str(), s.length());
return;
} catch (...) {
Logger_.information("SendData shutdown.");
}
EndConnection();
}
void RTTYS_ClientConnection::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
Logger_.information("Socket shutdown.");
EndConnection();
}
}

View File

@@ -0,0 +1,49 @@
//
// Created by stephane bourque on 2021-11-23.
//
#pragma once
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/NObserver.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/FIFOBuffer.h"
#include "Poco/Logger.h"
#include <mutex>
#include <shared_mutex>
namespace OpenWifi {
class RTTYS_ClientConnection {
public:
RTTYS_ClientConnection(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response,
Poco::Net::SocketReactor & reactor,
const std::string &Id);
~RTTYS_ClientConnection();
void onSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
void onSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
void SendData( const u_char *Buf, size_t len );
void SendData( const std::string & S );
void DeRegister();
[[nodiscard]] inline std::string ID() { return Id_; }
[[nodiscard]] inline bool Valid() { return Valid_; }
private:
Poco::Net::SocketReactor &Reactor_;
std::string Id_;
std::unique_ptr<Poco::Net::WebSocket> WS_;
Poco::Logger &Logger_;
std::string Sid_;
std::recursive_mutex Mutex_;
volatile bool Valid_=false;
volatile bool Registered_=false;
void EndConnection();
};
}

View File

@@ -7,8 +7,9 @@
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "RTTYS_server.h"
#include "RTTYS_ClientConnection.h"
#include "RTTYS_WebServer.h"
#include "RTTYS_server.h"
#include "fmt/format.h"
#include "nlohmann/json.hpp"
@@ -36,7 +37,7 @@ namespace OpenWifi {
}
try {
RTTYS_server()->CreateWSClient(request,response,T[2]);
RTTYS_server()->CreateNewClient(request,response,T[2]);
} catch (...) {
poco_warning(Logger_,"Exception during WS creation");
}
@@ -112,7 +113,7 @@ namespace OpenWifi {
Utils::SetThreadName("rt:webserver");
[[maybe_unused]] uint64_t id = rtty_ws_id++;
poco_trace(Logger(),fmt::format("{}: Starting request.",id));
poco_debug(Logger(),fmt::format("{}: Starting request.",id));
Poco::URI uri(request.getURI());
auto Path = uri.getPath();
@@ -134,7 +135,7 @@ namespace OpenWifi {
if (ParsedPath.count() > 1) {
if (ParsedPath[1] == "connect") {
response.redirect(Poco::replace(Path,"/connect/","/rtty/"));
poco_trace(Logger(),fmt::format("{}: Redirect: {}",id,Path));
poco_debug(Logger(),fmt::format("{}: Redirect: {}",id,Path));
return;
} else if (ParsedPath[1] == "authorized") {
SetCommonHeaders(request,response, false);
@@ -143,7 +144,7 @@ namespace OpenWifi {
response.setContentType("application/json");
std::ostream &answer = response.send();
answer << to_string(doc);
poco_trace(Logger(),fmt::format("{}: Finishing authorization request.",id));
poco_debug(Logger(),fmt::format("{}: Finishing authorization request.",id));
return;
} else if (ParsedPath[1] == "fontsize") {
SetCommonHeaders(request,response, false);
@@ -152,7 +153,7 @@ namespace OpenWifi {
response.setContentType("application/json");
std::ostream &answer = response.send();
answer << to_string(doc);
poco_trace(Logger(),fmt::format("{}: Finishing font size request.",id));
poco_debug(Logger(),fmt::format("{}: Finishing font size request.",id));
return;
}
}
@@ -160,12 +161,12 @@ namespace OpenWifi {
}
if(Path.find("../")!=std::string::npos) {
poco_trace(Logger(),fmt::format("{}: Finishing request.",id));
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
return;
}
if(Path.find("~/")!=std::string::npos) {
poco_trace(Logger(),fmt::format("{}: Finishing request.",id));
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
return;
}
@@ -175,7 +176,7 @@ namespace OpenWifi {
// std::cout << id << ": Path " << Path << " does not exist" << std::endl;
Path = RTTYS_server()->UIAssets() + "/index.html";
response.sendFile(Path,"text/html");
poco_trace(Logger(),fmt::format("{}: Finishing request.",id));
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
return;
}
Poco::Path P(Path);
@@ -192,7 +193,7 @@ namespace OpenWifi {
} else if (Ext == "css") {
Type = "text/css; charset=utf-8";
if(IsFileGZipped(Path)) {
poco_trace(Logger(),fmt::format("{}: Downloading UI Assets.",id));
poco_debug(Logger(),fmt::format("{}: Downloading UI Assets.",id));
response.set("Content-Encoding", "gzip");
}
} else if (Ext == "ico")
@@ -206,7 +207,7 @@ namespace OpenWifi {
response.setContentLength(F.getSize());
response.sendFile(Path, Type);
poco_trace(Logger(),fmt::format("{}: Finishing request.",id));
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
}
RTTYS_Client_RequestHandlerFactory::RTTYS_Client_RequestHandlerFactory(Poco::Logger & L)

524
src/rttys/RTTYS_device.cpp Normal file
View File

@@ -0,0 +1,524 @@
//
// Created by stephane bourque on 2021-11-23.
//
#include "RTTYS_device.h"
#include "rttys/RTTYS_server.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/StreamSocket.h"
#include "nlohmann/json.hpp"
#include "fmt/format.h"
void dump(const u_char *b, uint s) {
static const char hex[] = "0123456789abcdef";
int l=0;
std::cout << std::endl;
while(s) {
std::string SS;
SS += (hex[(*b & 0xf0) >> 4]);
SS += (hex[(*b & 0x0f)]);
std::cout << SS << " ";
l++;
if((l % 16) == 0)
std::cout << std::endl;
b++;
--s;
}
std::cout << std::endl;
}
#define SOCKET_DEBUG(X,Y,Z) { std::cout << __func__ << ":" << __LINE__ << std::endl; (Z)=socket_.sendBytes(X,Y); dump(X,Y); }
namespace OpenWifi {
RTTYS_Device_ConnectionHandler::RTTYS_Device_ConnectionHandler(Poco::Net::StreamSocket& socket, Poco::Net::SocketReactor & reactor):
socket_(socket),
reactor_(reactor),
Logger_(Poco::Logger::get(fmt::format("RTTY-device({})",socket_.peerAddress().toString())))
{
// std::thread T([=]() { CompleteConnection(); });
// T.detach();
inBuf_ = std::make_unique<Poco::FIFOBuffer>(RTTY_DEVICE_BUFSIZE);
CompleteConnection();
}
void RTTYS_Device_ConnectionHandler::CompleteConnection() {
try {
valid_=true;
device_address_ = socket_.peerAddress();
auto SS = dynamic_cast<Poco::Net::SecureStreamSocketImpl *>(socket_.impl());
while (true) {
auto V = SS->completeHandshake();
if (V == 1)
break;
}
if ((SS->secure())) {
poco_information(Logger(), "Secure connection.");
}
socket_.setBlocking(false);
socket_.setKeepAlive(true);
socket_.setNoDelay(true);
socket_.setReceiveTimeout(Poco::Timespan(60*60,0));
registered_=true;
reactor_.addEventHandler(
socket_,
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
*this, &RTTYS_Device_ConnectionHandler::onSocketReadable));
reactor_.addEventHandler(
socket_,
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ShutdownNotification>(
*this, &RTTYS_Device_ConnectionHandler::onSocketShutdown));
} catch (...) {
poco_warning(Logger(), "Device caused exception while completing connection.");
std::unique_lock G(M_);
EndConnection();
}
}
RTTYS_Device_ConnectionHandler::~RTTYS_Device_ConnectionHandler() {
poco_information(Logger_,
fmt::format("Device {} session ending", id_)
);
DeRegister();
}
void RTTYS_Device_ConnectionHandler::DeRegister() {
if(registered_) {
registered_ = false;
reactor_.removeEventHandler(
socket_,
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
*this, &RTTYS_Device_ConnectionHandler::onSocketReadable));
reactor_.removeEventHandler(
socket_,
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ShutdownNotification>(
*this, &RTTYS_Device_ConnectionHandler::onSocketShutdown));
}
}
void RTTYS_Device_ConnectionHandler::EndConnection() {
if(valid_) {
valid_ = false;
DeRegister();
if(deviceIsRegistered_) {
deviceIsRegistered_ = false;
RTTYS_server()->NotifyDeviceDisconnect(id_, this);
} else {
delete this;
}
}
}
[[maybe_unused]] static void dump(unsigned char *p,uint l) {
for(uint i=0;i<l;i++) {
std::cout << std::hex << (uint) p[i] << " ";
if(i % 16 == 0)
std::cout << std::endl;
}
std::cout << std::dec << std::endl ;
}
void RTTYS_Device_ConnectionHandler::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
bool good = true;
if(!valid_ || !registered_)
return;
std::unique_lock G(M_);
try {
auto received_bytes = socket_.receiveBytes(*inBuf_);
if (received_bytes == 0) {
poco_information(Logger(), fmt::format("{}: Device Closing connection - 0 bytes received.",id_));
return EndConnection();
}
while (inBuf_->isReadable() && good) {
uint32_t msg_len = 0;
if (waiting_for_bytes_ != 0) {
} else {
if (inBuf_->used() >= RTTY_HDR_SIZE) {
auto *head = (unsigned char *)inBuf_->begin();
last_command_ = head[0];
msg_len = head[1] * 256 + head[2];
inBuf_->drain(RTTY_HDR_SIZE);
} else {
good = false;
continue;
}
}
switch (last_command_) {
case msgTypeRegister: {
good = do_msgTypeRegister(msg_len);
} break;
case msgTypeLogin: {
good = do_msgTypeLogin(msg_len);
} break;
case msgTypeLogout: {
good = do_msgTypeLogout(msg_len);
} break;
case msgTypeTermData: {
good = do_msgTypeTermData(msg_len);
} break;
case msgTypeWinsize: {
good = do_msgTypeWinsize(msg_len);
} break;
case msgTypeCmd: {
good = do_msgTypeCmd(msg_len);
} break;
case msgTypeHeartbeat: {
good = do_msgTypeHeartbeat(msg_len);
} break;
case msgTypeFile: {
good = do_msgTypeFile(msg_len);
} break;
case msgTypeHttp: {
good = do_msgTypeHttp(msg_len);
} break;
case msgTypeAck: {
good = do_msgTypeAck(msg_len);
} break;
case msgTypeMax: {
good = do_msgTypeMax(msg_len);
} break;
default: {
poco_warning(Logger(),
fmt::format("{}: Unknown command {} from device. GW closing connection.", id_,
(int)last_command_));
good = false;
}
}
}
} catch (const Poco::Exception &E) {
good = false;
poco_warning(Logger(),fmt::format("{}: Exception: {} GW closing connection.", id_, E.what()));
} catch (const std::exception &E) {
poco_warning(Logger(),fmt::format("{}: std::exception: {}. GW closing connection.", id_, E.what()));
good = false;
}
if(!good) {
return EndConnection();
}
}
void RTTYS_Device_ConnectionHandler::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
poco_information(Logger(),fmt::format("{}: Connection being closed - socket shutdown.",id_));
EndConnection();
}
bool RTTYS_Device_ConnectionHandler::SendToClient(const u_char *Buf, int Len) {
u_char bb[64000]{0};
if(old_rtty_) {
bb[0] = session_id_[0];
memcpy(&bb[1],Buf,Len);
} else {
bb[0] = 0;
memcpy(&bb[1],Buf,Len);
}
return RTTYS_server()->SendToClient(id_, Buf, Len );
}
bool RTTYS_Device_ConnectionHandler::SendToClient(const std::string &S) {
if(!valid_ || !registered_)
return false;
return RTTYS_server()->SendToClient(id_,S);
}
bool RTTYS_Device_ConnectionHandler::KeyStrokes(const u_char *buf, size_t len) {
if(!valid_ || !registered_)
return false;
if(len<=(sizeof(small_buf_)-RTTY_HDR_SIZE-session_length_)) {
small_buf_[0] = msgTypeTermData;
small_buf_[1] = ((len-1+session_length_) & 0xff00) >> 8;
small_buf_[2] = ((len-1+session_length_) & 0x00ff);
memcpy(&small_buf_[RTTY_HDR_SIZE],session_id_,session_length_);
memcpy(&small_buf_[RTTY_HDR_SIZE+session_length_], &buf[1], len-1);
try {
auto Sent = socket_.sendBytes(small_buf_, RTTY_HDR_SIZE + session_length_ + len - 1);
return (Sent==(int)(RTTY_HDR_SIZE + session_length_ + len - 1));
} catch (...) {
return false;
}
} else {
auto Msg = std::make_unique<unsigned char []>(len + RTTY_HDR_SIZE + session_length_);
Msg.get()[0] = msgTypeTermData;
Msg.get()[1] = ((len-1+session_length_) & 0xff00) >> 8;
Msg.get()[2] = ((len-1+session_length_) & 0x00ff);
memcpy((Msg.get()+RTTY_HDR_SIZE),session_id_,session_length_);
memcpy((Msg.get()+RTTY_HDR_SIZE+session_length_), &buf[1], len-1);
try {
auto Sent = socket_.sendBytes(Msg.get(), RTTY_HDR_SIZE + session_length_ + len - 1);
return (Sent==(int)( RTTY_HDR_SIZE + session_length_ + len - 1));
} catch (...) {
return false;
}
}
}
bool RTTYS_Device_ConnectionHandler::WindowSize(int cols, int rows) {
if(!valid_ || !registered_)
return false;
u_char outBuf[8+RTTY_SESSION_ID_LENGTH]{0};
outBuf[0] = msgTypeWinsize;
outBuf[1] = 0 ;
outBuf[2] = 4 + session_length_ ;
memcpy(&outBuf[RTTY_HDR_SIZE],session_id_,session_length_);
outBuf[RTTY_HDR_SIZE+0+session_length_] = cols >> 8 ;
outBuf[RTTY_HDR_SIZE+1+session_length_] = cols & 0x00ff;
outBuf[RTTY_HDR_SIZE+2+session_length_] = rows >> 8;
outBuf[RTTY_HDR_SIZE+3+session_length_] = rows & 0x00ff;
try {
auto Sent = socket_.sendBytes(outBuf, RTTY_HDR_SIZE + 4 + session_length_ );
return (Sent==(int)(RTTY_HDR_SIZE + 4 + session_length_));
} catch (...) {
}
return false;
}
bool RTTYS_Device_ConnectionHandler::Login() {
if(!valid_ || !registered_)
return false;
u_char outBuf[RTTY_HDR_SIZE+RTTY_SESSION_ID_LENGTH]{0};
outBuf[0] = msgTypeLogin;
outBuf[1] = 0;
if(old_rtty_) {
outBuf[2] = 0;
} else {
outBuf[2] = RTTY_SESSION_ID_LENGTH;
std::strncpy(session_id_,Utils::ComputeHash(id_,token_).substr(0,RTTY_SESSION_ID_LENGTH/2).c_str(),RTTY_SESSION_ID_LENGTH);
memcpy(&outBuf[RTTY_HDR_SIZE],session_id_,RTTY_SESSION_ID_LENGTH);
}
try {
poco_information(Logger(),fmt::format("{}: Device login", id_));
auto Sent = socket_.sendBytes( outBuf, RTTY_HDR_SIZE + (old_rtty_ ? 0 : RTTY_SESSION_ID_LENGTH));
return Sent==(int)(RTTY_HDR_SIZE + (old_rtty_ ? 0 : RTTY_SESSION_ID_LENGTH));
} catch (const Poco::IOException &E) {
return false;
} catch (const Poco::Exception &E) {
return false;
}
}
bool RTTYS_Device_ConnectionHandler::Logout() {
if(!valid_ || !registered_)
return false;
u_char outBuf[4+RTTY_SESSION_ID_LENGTH]{0};
outBuf[0] = msgTypeLogout;
outBuf[1] = 0;
outBuf[2] = session_length_;
memcpy(&outBuf[3],session_id_,session_length_);
poco_information(Logger(),fmt::format("{}: Logout", id_));
try {
auto Sent = socket_.sendBytes(outBuf, RTTY_HDR_SIZE + session_length_);
return Sent==(int)(RTTY_HDR_SIZE+session_length_);
} catch (...) {
}
return false;
}
std::string RTTYS_Device_ConnectionHandler::ReadString() {
std::string Res;
while(inBuf_->used()) {
char C;
inBuf_->read(&C,1);
if(C==0) {
break;
}
Res += C;
}
return Res;
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeRegister([[maybe_unused]] std::size_t msg_len) {
bool good = true;
if(deviceIsRegistered_)
return false;
try {
// establish if this is an old rtty or a new one.
old_rtty_ = ((*inBuf_)[0] != 0x03); // rtty_proto_ver for full session ID inclusion
if(old_rtty_) {
session_length_ = 1;
} else {
inBuf_->drain(1); // remove protocol if used.
session_length_ = RTTY_SESSION_ID_LENGTH;
}
id_ = ReadString();
desc_ = ReadString();
token_ = ReadString();
if(id_.size()!=RTTY_DEVICE_TOKEN_LENGTH || token_.size()!=RTTY_DEVICE_TOKEN_LENGTH || desc_.empty()) {
return false;
}
poco_information(Logger(),
fmt::format("{}: Description:{} Device registration", id_, desc_));
if(!RTTYS_server()->NotifyDeviceRegistration(id_,token_,this)) {
return false;
}
u_char OutBuf[8];
OutBuf[0] = msgTypeRegister;
OutBuf[1] = 0; // Data length
OutBuf[2] = 4; //
OutBuf[3] = 0; // Error
OutBuf[4] = 'O';
OutBuf[5] = 'K';
OutBuf[6] = 0;
if (socket_.sendBytes(OutBuf, 7) != 7) {
poco_information(Logger(),
fmt::format("{}: Description:{} Could not send data to complete registration",
id_, desc_));
good = false;
}
deviceIsRegistered_ = true;
} catch (...) {
good = false;
}
return good;
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeLogin([[maybe_unused]] std::size_t msg_len) {
poco_information(Logger(),fmt::format("{}: Asking for login", id_));
if(!deviceIsRegistered_)
return false;
nlohmann::json doc;
char Error;
if(old_rtty_) {
inBuf_->read(&Error, 1);
inBuf_->read(&session_id_[0], session_length_);
} else {
char session[RTTY_SESSION_ID_LENGTH+1]{0};
inBuf_->read(&session[0], session_length_);
inBuf_->read(&Error, 1);
}
doc["type"] = "login";
doc["err"] = Error;
const auto login_msg = to_string(doc);
return SendToClient(login_msg);
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeLogout([[maybe_unused]] std::size_t msg_len) {
if(!deviceIsRegistered_)
return false;
char session[RTTY_SESSION_ID_LENGTH];
if(old_rtty_) {
inBuf_->read(&session[0],1);
} else {
inBuf_->read(&session[0],RTTY_SESSION_ID_LENGTH);
}
poco_information(Logger(),fmt::format("{}: Logout", id_));
return false;
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeTermData(std::size_t msg_len) {
if(!deviceIsRegistered_)
return false;
bool good;
if(waiting_for_bytes_>0) {
if(inBuf_->used()<waiting_for_bytes_) {
waiting_for_bytes_ = waiting_for_bytes_ - inBuf_->used();
good = SendToClient((unsigned char *)inBuf_->begin(), (int) inBuf_->used());
inBuf_->drain();
} else {
good = SendToClient((unsigned char *)inBuf_->begin(), waiting_for_bytes_);
inBuf_->drain(waiting_for_bytes_);
waiting_for_bytes_ = 0 ;
}
} else {
if(old_rtty_) {
inBuf_->drain(1);
msg_len -= 1;
} else {
inBuf_->drain(RTTY_SESSION_ID_LENGTH);
msg_len -= RTTY_SESSION_ID_LENGTH;
}
if(inBuf_->used()<msg_len) {
good = SendToClient((unsigned char *)inBuf_->begin(), inBuf_->used());
waiting_for_bytes_ = msg_len - inBuf_->used();
inBuf_->drain();
} else {
waiting_for_bytes_ = 0 ;
good = SendToClient((unsigned char *)inBuf_->begin(), msg_len);
inBuf_->drain(msg_len);
}
}
return good;
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeWinsize([[maybe_unused]] std::size_t msg_len) {
if(!deviceIsRegistered_)
return false;
poco_information(Logger(),fmt::format("{}: Asking for msgTypeWinsize", id_));
return true;
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeCmd([[maybe_unused]] std::size_t msg_len) {
if(!deviceIsRegistered_)
return false;
poco_information(Logger(),fmt::format("{}: Asking for msgTypeCmd", id_));
return true;
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeHeartbeat([[maybe_unused]] std::size_t msg_len) {
if(!deviceIsRegistered_)
return false;
u_char MsgBuf[RTTY_HDR_SIZE + 16]{0};
if(msg_len)
inBuf_->drain(msg_len);
MsgBuf[0] = msgTypeHeartbeat;
MsgBuf[1] = 0;
MsgBuf[2] = 0;
auto Sent = socket_.sendBytes(MsgBuf, RTTY_HDR_SIZE);
return Sent == RTTY_HDR_SIZE;
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeFile([[maybe_unused]] std::size_t msg_len) {
if(!deviceIsRegistered_)
return false;
poco_information(Logger(),fmt::format("{}: Asking for msgTypeFile", id_));
return true;
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeHttp([[maybe_unused]] std::size_t msg_len) {
if(!deviceIsRegistered_)
return false;
poco_information(Logger(),fmt::format("{}: Asking for msgTypeHttp", id_));
return true;
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeAck([[maybe_unused]] std::size_t msg_len) {
if(!deviceIsRegistered_)
return false;
poco_information(Logger(),fmt::format("{}: Asking for msgTypeAck", id_));
return true;
}
bool RTTYS_Device_ConnectionHandler::do_msgTypeMax([[maybe_unused]] std::size_t msg_len) {
poco_information(Logger(),fmt::format("{}: Asking for msgTypeMax", id_));
return true;
}
}

93
src/rttys/RTTYS_device.h Normal file
View File

@@ -0,0 +1,93 @@
//
// Created by stephane bourque on 2021-11-23.
//
#pragma once
#include <array>
#include <shared_mutex>
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/FIFOBuffer.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Logger.h"
namespace OpenWifi {
constexpr std::size_t RTTY_DEVICE_BUFSIZE=64000;
constexpr std::size_t RTTY_SESSION_ID_LENGTH=32;
constexpr std::size_t RTTY_HDR_SIZE=3;
class RTTYS_Device_ConnectionHandler{
public:
enum RTTY_MSG_TYPE {
msgTypeRegister = 0,
msgTypeLogin,
msgTypeLogout,
msgTypeTermData,
msgTypeWinsize,
msgTypeCmd,
msgTypeHeartbeat,
msgTypeFile,
msgTypeHttp,
msgTypeAck,
msgTypeMax };
explicit RTTYS_Device_ConnectionHandler(Poco::Net::StreamSocket& socket, Poco::Net::SocketReactor& reactor);
~RTTYS_Device_ConnectionHandler();
bool Login();
bool Logout();
[[nodiscard]] bool SendToClient(const u_char *buf, int len);
[[nodiscard]] bool SendToClient(const std::string &S);
[[nodiscard]] bool WindowSize(int cols, int rows);
[[nodiscard]] bool KeyStrokes(const u_char *buf, size_t len);
std::string ReadString();
// inline auto SessionID() const { return conn_id_; }
void onSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
void onSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf);
inline Poco::Logger &Logger() { return Logger_; }
inline bool Valid() const { return valid_; }
private:
Poco::Net::StreamSocket socket_;
Poco::Net::SocketReactor &reactor_;
std::unique_ptr<Poco::FIFOBuffer> inBuf_;
Poco::Logger &Logger_;
volatile bool valid_=false;
volatile bool old_rtty_=true;
Poco::Net::SocketAddress device_address_;
std::shared_mutex M_;
std::string id_;
std::string token_;
std::string desc_;
char session_id_[RTTY_SESSION_ID_LENGTH+1]{0};
std::uint64_t session_length_=1;
std::size_t waiting_for_bytes_{0};
u_char last_command_=0;
volatile bool registered_=false;
unsigned char small_buf_[64+RTTY_SESSION_ID_LENGTH];
volatile bool deviceIsRegistered_=false;
void EndConnection() ;
void CompleteConnection();
void DeRegister();
[[nodiscard]] bool do_msgTypeRegister(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeLogin(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeLogout(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeTermData(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeWinsize(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeCmd(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeHeartbeat(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeFile(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeHttp(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeAck(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeMax(std::size_t msg_len);
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -12,45 +12,119 @@
#include "Poco/NotificationQueue.h"
#include "Poco/Timer.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/WebSocket.h"
#include "framework/SubSystemServer.h"
#include "framework/utils.h"
#include <fmt/format.h>
#include "rttys/RTTYS_device.h"
#include "rttys/RTTYS_ClientConnection.h"
using namespace std::chrono_literals;
namespace OpenWifi {
constexpr uint RTTY_DEVICE_TOKEN_LENGTH=32;
constexpr std::size_t RTTY_DEVICE_BUFSIZE=64000;
constexpr std::size_t RTTY_SESSION_ID_LENGTH=32;
constexpr std::size_t RTTY_HDR_SIZE=3;
class RTTYS_server;
class RTTYS_Device_ConnectionHandler;
class RTTYS_ClientConnection;
class RTTYS_server * RTTYS_server();
template <typename T> class MutexLockerDbg {
public:
MutexLockerDbg(const std::string &name, T &L) :
name_(name),
L_(L)
{
std::cout << name_ << ":L:0:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
L_.lock();
std::cout << name_ << ":L:1:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
}
~MutexLockerDbg() {
std::cout << name_ << ":U:0:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
L_.unlock();
std::cout << name_ << ":U:1:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
}
private:
std::string name_;
T & L_;
};
enum class RTTYS_Notification_type {
unknown,
device_disconnection,
client_disconnection,
client_registration,
device_registration
};
class RTTYS_Notification: public Poco::Notification {
public:
RTTYS_Notification(const RTTYS_Notification_type &type, const std::string &id,
RTTYS_Device_ConnectionHandler * device) :
type_(type),
id_(id),
device_(device) {
}
RTTYS_Notification(const RTTYS_Notification_type &type, const std::string &id,
RTTYS_ClientConnection * client) :
type_(type),
id_(id),
client_(client) {
}
RTTYS_Notification(const RTTYS_Notification_type &type,
const std::string &id,
const std::string &token,
RTTYS_Device_ConnectionHandler * device) :
type_(type),
id_(id),
token_(token),
device_(device) {
}
RTTYS_Notification_type type_=RTTYS_Notification_type::unknown;
std::string id_;
std::string token_;
RTTYS_Device_ConnectionHandler *device_= nullptr;
RTTYS_ClientConnection *client_ = nullptr;
};
class RTTYS_EndPoint {
public:
RTTYS_EndPoint(const std::string &Id, const std::string &Token, const std::string &SerialNumber, const std::string &UserName );
~RTTYS_EndPoint();
RTTYS_EndPoint(const std::string &Token, const std::string &SerialNumber, const std::string &UserName ):
Token_(Token),
SerialNumber_(SerialNumber),
UserName_(UserName)
{
Created_ = std::chrono::high_resolution_clock::now();
}
enum RTTY_MSG_TYPE {
msgTypeRegister = 0,
msgTypeLogin,
msgTypeLogout,
msgTypeTermData,
msgTypeWinsize,
msgTypeCmd,
msgTypeHeartbeat,
msgTypeFile,
msgTypeHttp,
msgTypeAck,
msgTypeMax };
inline void SetClient(RTTYS_ClientConnection *Client) {
ClientConnected_ = std::chrono::high_resolution_clock::now();
Client_ = std::unique_ptr<RTTYS_ClientConnection>(Client);
}
bool Login();
bool Logout();
inline void SetDevice(RTTYS_Device_ConnectionHandler* Device) {
DeviceConnected_ = std::chrono::high_resolution_clock::now();
Device_ = std::unique_ptr<RTTYS_Device_ConnectionHandler>(Device);
}
inline bool Login() {
if(Device_!= nullptr) {
return Device_->Login();
}
return false;
}
inline void DisconnectClient() {
ClientDisconnected_ = std::chrono::high_resolution_clock::now();
}
inline void DisconnectDevice() {
DeviceDisconnected_ = std::chrono::high_resolution_clock::now();
}
[[nodiscard]] inline bool TooOld() {
std::chrono::time_point<std::chrono::high_resolution_clock> now = std::chrono::high_resolution_clock::now();
@@ -67,6 +141,51 @@ namespace OpenWifi {
return true;
}
if(!Joined_ && (now-Created_)>30s) {
return true;
}
return false;
}
bool SendToClient(const u_char *Buf, std::size_t Len) {
if(Client_!= nullptr && Client_->Valid()) {
Client_->SendData(Buf,Len);
return true;
}
return false;
}
inline bool KeyStrokes(const u_char *buffer, std::size_t len) {
if( Device_!= nullptr && Device_->Valid() )
return Device_->KeyStrokes(buffer,len);
return false;
}
inline bool WindowSize( int cols, int rows) {
if(Device_!= nullptr && Device_->Valid())
return Device_->WindowSize(cols,rows);
return false;
}
[[nodiscard]] inline bool ValidClient() const {
return Client_!= nullptr && Client_->Valid();
}
[[nodiscard]] inline bool ValidDevice() const {
return Device_!= nullptr && Device_->Valid();
}
[[nodiscard]] inline bool Joined() volatile const { return Joined_; }
void Join() {
Joined_=true;
}
inline bool SendToClient(const std::string &S) {
if(Client_!= nullptr && Client_->Valid()) {
Client_->SendData(S);
return true;
}
return false;
}
@@ -86,47 +205,20 @@ namespace OpenWifi {
return std::chrono::duration<double>{ClientDisconnected_ - ClientConnected_}.count();
}
[[nodiscard]] bool do_msgTypeRegister(Poco::Net::Socket &Socket, Poco::Buffer<char> &B, [[maybe_unused]] std::size_t msg_len);
[[nodiscard]] bool do_msgTypeLogin(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeLogout(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeTermData(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeWinsize(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeCmd(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeHeartbeat(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeFile(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeHttp(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeAck(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeMax(std::size_t msg_len);
bool SendToClient(const u_char *buf, int len);
bool SendToClient(const std::string &S);
[[nodiscard]] bool WindowSize(int cols, int rows);
[[nodiscard]] bool KeyStrokes(const u_char *buf, size_t len);
inline Poco::Logger & Logger() { return Logger_; }
Poco::Net::SocketAddress device_address_;
std::string Id_;
std::string Token_;
std::string SerialNumber_;
std::string UserName_;
std::unique_ptr<Poco::Net::StreamSocket> DeviceSocket_;
std::unique_ptr<Poco::Net::WebSocket> WSSocket_;
Poco::Logger &Logger_;
std::unique_ptr<Poco::FIFOBuffer> DeviceInBuf_;
char session_id_[RTTY_SESSION_ID_LENGTH+1]{0};
std::uint64_t session_length_=1;
std::size_t waiting_for_bytes_{0};
u_char last_command_=0;
unsigned char small_buf_[64+RTTY_SESSION_ID_LENGTH];
std::uint64_t TID_=0;
bool old_rtty_=false;
bool completed_=false;
private:
std::string Token_;
std::string SerialNumber_;
std::string UserName_;
std::unique_ptr<RTTYS_ClientConnection> Client_;
std::unique_ptr<RTTYS_Device_ConnectionHandler> Device_;
std::string Id_;
std::chrono::time_point<std::chrono::high_resolution_clock>
Created_{0s},DeviceDisconnected_{0s},
ClientDisconnected_{0s},DeviceConnected_{0s} ,ClientConnected_{0s};
volatile bool Joined_=false;
};
class RTTYS_server : public SubSystemServer
class RTTYS_server : public SubSystemServer, Poco::Runnable
{
public:
static auto instance() {
@@ -140,97 +232,77 @@ namespace OpenWifi {
inline auto UIAssets() { return RTTY_UIAssets_; }
bool CreateEndPoint(const std::string &Id, const std::string & Token, const std::string & UserName, const std::string & SerialNumber );
bool SendKeyStrokes(const std::string &Id, const u_char *buffer, std::size_t s);
bool WindowSize(const std::string &Id, int cols, int rows);
bool SendToClient(const std::string &id, const u_char *Buf, std::size_t Len);
bool SendToClient(const std::string &id, const std::string &s);
bool ValidId(const std::string &Id);
void run() final;
inline void NotifyDeviceDisconnect(const std::string &id, RTTYS_Device_ConnectionHandler *device) {
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::device_disconnection,id,device));
}
inline void NotifyClientDisconnect(const std::string &id, RTTYS_ClientConnection *client) {
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::client_disconnection,id,client));
}
inline bool NotifyDeviceRegistration(const std::string &id, const std::string &token, RTTYS_Device_ConnectionHandler *device) {
{
std::lock_guard G(LocalMutex_);
if (EndPoints_.find(id) == end(EndPoints_))
return false;
}
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::device_registration,id,token,device));
return true;
}
inline void NotifyClientRegistration(const std::string &id, RTTYS_ClientConnection *client) {
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::client_registration,id,client));
}
void CreateNewClient(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response, const std::string &id);
void onTimer(Poco::Timer & timer);
inline bool UseInternal() const {
return Internal_;
}
std::string ReadString(unsigned char *buf, int len, int &pos);
void onDeviceAccept(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
void onDeviceSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
void onDeviceSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf);
void onDeviceSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf);
void onClientSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
void onClientSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf);
void onClientSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf);
void RemoveConnectingDeviceEventHandlers(Poco::Net::StreamSocket &Socket);
void RemoveClientEventHandlers(Poco::Net::StreamSocket &Socket);
void RemoveDeviceEventHandlers(Poco::Net::StreamSocket &Socket);
void AddConnectingDeviceEventHandlers(Poco::Net::StreamSocket &Socket);
void AddClientEventHandlers(Poco::Net::StreamSocket &Socket, std::shared_ptr<RTTYS_EndPoint> EndPoint);
void AddDeviceEventHandlers(Poco::Net::StreamSocket &Socket, std::shared_ptr<RTTYS_EndPoint> EndPoint);
void onConnectingDeviceData(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
void onConnectingDeviceShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
void onConnectingDeviceError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf);
bool do_msgTypeRegister(Poco::Net::StreamSocket &Socket, unsigned char *Buffer, int Len);
bool do_msgTypeHeartbeat(Poco::Net::StreamSocket &Socket);
void CloseDevice(std::shared_ptr<RTTYS_EndPoint> Device);
void CloseClient(std::shared_ptr<RTTYS_EndPoint> Client);
void CloseConnection(std::shared_ptr<RTTYS_EndPoint> Connection);
inline Poco::Net::SocketReactor & ClientReactor() { return ClientReactor_; }
inline auto Uptime() const { return Utils::Now() - Started_; }
void CreateWSClient(
Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response,
const std::string &Id);
Poco::Net::SocketReactor & Reactor() { return Reactor_; }
void SendData( std::shared_ptr<RTTYS_EndPoint> & Connection, const u_char *Buf, size_t len );
void SendData( std::shared_ptr<RTTYS_EndPoint> & Connection, const std::string &s) ;
inline std::shared_ptr<RTTYS_EndPoint> FindConnection(const std::string &Id,const std::string &Token) {
std::shared_ptr<RTTYS_EndPoint> Res;
auto EndPoint = EndPoints_.find(Id);
if(EndPoint!=end(EndPoints_) && EndPoint->second->Token_==Token) {
Res = EndPoint->second;
}
return Res;
}
void LogStdException(const std::exception &E, const char *msg);
private:
Poco::Net::SocketReactor Reactor_;
Poco::Thread ReactorThread_;
Poco::Net::SocketReactor ClientReactor_;
Poco::Net::SocketReactor DeviceReactor_;
Poco::Thread ClientReactorThread_;
std::string RTTY_UIAssets_;
bool Internal_ = false;
bool NoSecurity_=false;
volatile bool Running_ = false;
std::map<std::string,std::unique_ptr<RTTYS_EndPoint>> EndPoints_; // id, endpoint
std::unique_ptr<Poco::Net::HTTPServer> WebServer_;
std::map<std::string,std::shared_ptr<RTTYS_EndPoint>> EndPoints_; // id, endpoint
std::map<int, std::shared_ptr<RTTYS_EndPoint> > Connections_;
std::map<int, std::pair<Poco::Net::StreamSocket,std::chrono::time_point<std::chrono::high_resolution_clock>>> ConnectingDevices_;
std::unique_ptr<Poco::Net::SocketAcceptor<RTTYS_Device_ConnectionHandler>> DeviceAcceptor_;
Poco::Thread DeviceReactorThread_;
Poco::NotificationQueue ResponseQueue_;
std::atomic_bool NotificationManagerRunning_=false;
Poco::Thread NotificationManager_;
Poco::Timer Timer_;
std::unique_ptr<Poco::TimerCallback<RTTYS_server>> GCCallBack_;
std::mutex ServerMutex_;
std::list<std::unique_ptr<RTTYS_Device_ConnectionHandler>> FailedDevices;
std::list<std::unique_ptr<RTTYS_ClientConnection>> FailedClients;
std::recursive_mutex LocalMutex_;
std::atomic_uint64_t TotalEndPoints_=0;
std::chrono::duration<double,std::milli> TotalConnectedDeviceTime_{0ms},
TotalConnectedClientTime_{0ms};
std::atomic_uint64_t FailedNumDevices_=0;
std::atomic_uint64_t FailedNumClients_=0;
double TotalConnectedDeviceTime_=0.0;
double TotalConnectedClientTime_=0.0;
std::atomic_uint64_t Started_=Utils::Now();
std::atomic_uint64_t MaxConcurrentSessions_=0;
std::unique_ptr<Poco::Net::ServerSocket> DeviceSocket_;
std::unique_ptr<Poco::Net::SecureServerSocket> SecureDeviceSocket_;
static inline std::uint64_t CurrentTID_=0;
explicit RTTYS_server() noexcept:
SubSystemServer("RTTY_Server", "RTTY-SVR", "rtty.server")
@@ -238,6 +310,6 @@ namespace OpenWifi {
}
};
inline class RTTYS_server * RTTYS_server() { return RTTYS_server::instance(); }
inline RTTYS_server * RTTYS_server() { return RTTYS_server::instance(); }
} // namespace OpenWifi

View File

@@ -120,8 +120,6 @@ typedef Poco::Tuple<
Poco::Data::Keywords::use(SerialNumber),
Poco::Data::Keywords::use(Command);
Delete.execute();
Delete.reset(Sess);
return true;
} catch(const Poco::Exception &E) {
Logger().log(E);
@@ -207,8 +205,6 @@ typedef Poco::Tuple<
ConvertCommandRecord(i, R);
Commands.push_back(R);
}
Select.reset(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -241,7 +237,6 @@ typedef Poco::Tuple<
Delete << IntroStatement + DateSelector;
Delete.execute();
Delete.reset(Sess);
return true;
} catch (const Poco::Exception &E) {
@@ -279,7 +274,7 @@ typedef Poco::Tuple<
if (Records.size() < HowMany)
Done = true;
}
Select.reset(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -348,8 +343,6 @@ typedef Poco::Tuple<
Poco::Data::Keywords::use(Status),
Poco::Data::Keywords::use(Window);
Update.execute();
Update.reset(Sess);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
@@ -366,7 +359,6 @@ typedef Poco::Tuple<
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Window);
Update.execute();
Update.reset(Sess);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
@@ -426,11 +418,6 @@ typedef Poco::Tuple<
Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
Delete.execute();
Delete.reset(Sess);
St = "DELETE FROM FileUploads WHERE UUID=?";
Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
Delete.execute();
Delete.reset(Sess);
return true;
} catch (const Poco::Exception &E) {
@@ -459,7 +446,6 @@ typedef Poco::Tuple<
ConvertCommandRecord(i,R);
Commands.push_back(R);
}
Select.reset(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -600,26 +586,23 @@ typedef Poco::Tuple<
bool Storage::AttachFileDataToCommand(std::string & UUID, const std::stringstream & FileContent, const std::string &Type) {
try {
Poco::Data::Session Sess = Pool_->get();
auto Now = Utils::Now();
uint64_t WaitForFile = 0;
Poco::Data::Statement Update(Sess);
uint64_t Size = FileContent.str().size();
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Statement(Sess);
std::string St{
"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?"};
std::string StatementStr;
// Get the existing command
StatementStr = "UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
Statement << ConvertParams(StatementStr),
Update << ConvertParams(St),
Poco::Data::Keywords::use(WaitForFile),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Size),
Poco::Data::Keywords::use(UUID);
Statement.execute();
Update.execute();
if (Size < FileUploader()->MaxSize()) {
@@ -661,11 +644,9 @@ typedef Poco::Tuple<
Poco::Data::Statement Select1(Sess);
std::string TmpSerialNumber;
std::string st1{"SELECT SerialNumber, Command FROM CommandList WHERE UUID=?"};
std::string Command;
std::string st1{"SELECT SerialNumber FROM CommandList WHERE UUID=?"};
Select1 << ConvertParams(st1),
Poco::Data::Keywords::into(TmpSerialNumber),
Poco::Data::Keywords::into(Command),
Poco::Data::Keywords::use(UUID);
Select1.execute();
@@ -674,18 +655,15 @@ typedef Poco::Tuple<
}
std::string St2{"SELECT FileContent, Type FROM FileUploads WHERE UUID=?"};
Poco::Data::Statement Select2(Sess);
Select2 << ConvertParams(St2),
Poco::Data::Keywords::into(L),
Poco::Data::Keywords::into(Type),
Poco::Data::Keywords::use(UUID);
Select2.execute();
FileContent.assign(L.content().begin(),L.content().end());
if(Command=="script")
Type = "gzip";
else if(Command=="trace")
Type = "pcap";
FileContent.assign(L.content().begin(),L.content().end());
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -734,21 +712,6 @@ typedef Poco::Tuple<
return false;
}
bool Storage::RemoveUploadedFilesRecordsOlderThan(uint64_t Date) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Delete(Sess);
std::string St1{"delete from FileUploads where Created<?"};
Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
Delete.execute();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::RemoveCommandListRecordsOlderThan(uint64_t Date) {
try {
Poco::Data::Session Sess = Pool_->get();

View File

@@ -48,10 +48,7 @@ namespace OpenWifi {
"entity, "
"modified, "
"locale,"
"restrictedDevice,"
"pendingConfiguration, "
"pendingConfigurationCmd, "
"restrictionDetails "
"restrictedDevice"
};
const static std::string DB_DeviceUpdateFields{
@@ -77,13 +74,10 @@ namespace OpenWifi {
"entity=?, "
"modified=?, "
"locale=?, "
"restrictedDevice=?, "
"pendingConfiguration=?, "
"pendingConfigurationCmd=?, "
"restrictionDetails=? "
"restrictedDevice=?"
};
const static std::string DB_DeviceInsertValues{" VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "};
const static std::string DB_DeviceInsertValues{" VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "};
typedef Poco::Tuple<
std::string,
@@ -108,10 +102,7 @@ namespace OpenWifi {
std::string,
uint64_t,
std::string,
bool,
std::string,
std::string,
std::string
bool
> DeviceRecordTuple;
typedef std::vector<DeviceRecordTuple> DeviceRecordList;
@@ -139,9 +130,6 @@ namespace OpenWifi {
D.modified = R.get<20>();
D.locale = R.get<21>();
D.restrictedDevice = R.get<22>();
D.pendingConfiguration = R.get<23>();
D.pendingConfigurationCmd = R.get<24>();
D.restrictionDetails = RESTAPI_utils::to_object<OpenWifi::GWObjects::DeviceRestrictions>(R.get<25>());
}
void ConvertDeviceRecord(const GWObjects::Device &D, DeviceRecordTuple & R) {
@@ -168,9 +156,6 @@ namespace OpenWifi {
R.set<20>(D.modified);
R.set<21>(D.locale);
R.set<22>(D.restrictedDevice);
R.set<23>(D.pendingConfiguration);
R.set<24>(D.pendingConfigurationCmd);
R.set<25>(RESTAPI_utils::to_string(D.restrictionDetails));
}
bool Storage::GetDeviceCount(uint64_t &Count) {

View File

@@ -98,7 +98,6 @@ namespace OpenWifi {
ConvertHealthCheckRecord(i,R);
Checks.push_back(R);
}
Select.reset(Sess);
return true;
}
catch (const Poco::Exception &E) {
@@ -126,7 +125,6 @@ namespace OpenWifi {
ConvertHealthCheckRecord(i,R);
Checks.push_back(R);
}
Select.reset(Sess);
return true;
}
catch (const Poco::Exception &E) {

View File

@@ -107,7 +107,6 @@ namespace OpenWifi {
ConvertLogsRecord(i,R);
Stats.push_back(R);
}
Select.reset(Sess);
return true;
}
catch (const Poco::Exception &E) {
@@ -145,7 +144,6 @@ namespace OpenWifi {
Delete << StatementStr + DateSelector + TypeSelector;
Delete.execute();
Delete.reset(Sess);
return true;
}
@@ -174,7 +172,6 @@ namespace OpenWifi {
ConvertLogsRecord(i,R);
Stats.push_back(R);
}
Select.reset(Sess);
return true;
}
catch (const Poco::Exception &E) {

View File

@@ -1,136 +0,0 @@
//
// Created by stephane bourque on 2022-11-21.
//
#include "storage_scripts.h"
#include "framework/RESTAPI_utils.h"
#include "fmt/format.h"
#include "framework/AppServiceRegistry.h"
namespace OpenWifi {
static ORM::FieldVec ScriptDB_Fields{
ORM::Field{"id", 36, true},
ORM::Field{"name", ORM::FieldType::FT_TEXT},
ORM::Field{"description", ORM::FieldType::FT_TEXT},
ORM::Field{"uri", ORM::FieldType::FT_TEXT},
ORM::Field{"content", ORM::FieldType::FT_TEXT},
ORM::Field{"version", ORM::FieldType::FT_TEXT},
ORM::Field{"type", ORM::FieldType::FT_TEXT},
ORM::Field{"created", ORM::FieldType::FT_BIGINT},
ORM::Field{"modified", ORM::FieldType::FT_BIGINT},
ORM::Field{"author", ORM::FieldType::FT_TEXT},
ORM::Field{"restricted", ORM::FieldType::FT_TEXT},
ORM::Field{"deferred", ORM::FieldType::FT_BOOLEAN},
ORM::Field{"timeout", ORM::FieldType::FT_BIGINT},
ORM::Field{"defaultUploadURI", ORM::FieldType::FT_TEXT}
};
static ORM::IndexVec MakeIndices(const std::string & shortname) {
return ORM::IndexVec{
{std::string(shortname + "_name_index"),
ORM::IndexEntryVec{
{
std::string("name"),
ORM::Indextype::ASC }}}
};
};
ScriptDB::ScriptDB( const std::string &TableName, const std::string &Shortname ,OpenWifi::DBType T,
Poco::Data::SessionPool &P, Poco::Logger &L) :
DB(T, TableName.c_str(), ScriptDB_Fields, MakeIndices(Shortname), P, L, Shortname.c_str()) {
}
bool ScriptDB::Upgrade([[maybe_unused]] uint32_t from, uint32_t &to) {
to = Version();
std::vector<std::string> Script{
};
for(const auto &i:Script) {
try {
auto Session = Pool_.get();
Session << i , Poco::Data::Keywords::now;
} catch (...) {
}
}
return true;
}
void ScriptDB::Initialize() {
bool Initialized = false;
AppServiceRegistry().Get("script_db_initialized",Initialized);
if(Initialized)
return;
GWObjects::ScriptEntry SE;
SE.id = MicroServiceCreateUUID();
SE.name = "ASB Bundle";
SE.description = "Automated on-demand detailed debugging information collection from an AP";
SE.uri = "https://telecominfraproject.atlassian.net/wiki/spaces/WIFI/pages/1678147585/AP+Support+Bundle+ASB";
SE.version = "1.0";
SE.author = "blogic";
SE.modified = SE.created = Utils::Now();
SE.type = "bundle";
SE.deferred = true;
SE.timeout = 30;
SE.content = std::string{
R"lit(
bundle.wifi();
let paths = [
[ 'network.wireless', 'status' ],
[ 'network.device', 'status' ],
[ 'network.interface', 'dump' ],
[ 'log', 'read', { stream: false } ],
];
for (let path in paths)
bundle.ubus(path[0], path[1], path[2]);
for (let config in [ 'network', 'wireless', 'dhcp', 'firewall', 'system' ])
bundle.uci(config);
for (let cmd in [ "route", "ifconfig", "logread" ])
bundle.shell(cmd);
)lit"};
if(CreateRecord(SE)) {
AppServiceRegistry().Set("script_db_initialized",true);
poco_information(Logger(), "Script DB has been in initialized.");
return;
}
poco_error(Logger(), "Script DB could not be initialized.");
}
} // OpenWifi
template<> void ORM::DB<OpenWifi::ScriptRecordTuple, OpenWifi::GWObjects::ScriptEntry>::Convert(const OpenWifi::ScriptRecordTuple &In, OpenWifi::GWObjects::ScriptEntry &Out) {
Out.id = In.get<0>();
Out.name = In.get<1>();
Out.description = In.get<2>();
Out.uri = In.get<3>();
Out.content = In.get<4>();
Out.version = In.get<5>();
Out.type = In.get<6>();
Out.created = In.get<7>();
Out.modified = In.get<8>();
Out.author = In.get<9>();
Out.restricted = OpenWifi::RESTAPI_utils::to_object_array(In.get<10>());
Out.deferred = In.get<11>();
Out.timeout = In.get<12>();
Out.defaultUploadURI = In.get<13>();
}
template<> void ORM::DB<OpenWifi::ScriptRecordTuple, OpenWifi::GWObjects::ScriptEntry>::Convert(const OpenWifi::GWObjects::ScriptEntry &In, OpenWifi::ScriptRecordTuple &Out) {
Out.set<0>(In.id);
Out.set<1>(In.name);
Out.set<2>(In.description);
Out.set<3>(In.uri);
Out.set<4>(In.content);
Out.set<5>(In.version);
Out.set<6>(In.type);
Out.set<7>(In.created);
Out.set<8>(In.modified);
Out.set<9>(In.author);
Out.set<10>(OpenWifi::RESTAPI_utils::to_string(In.restricted));
Out.set<11>(In.deferred);
Out.set<12>(In.timeout);
Out.set<13>(In.defaultUploadURI);
}

View File

@@ -1,42 +0,0 @@
//
// Created by stephane bourque on 2022-11-21.
//
#pragma once
#include "framework/orm.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
namespace OpenWifi {
typedef Poco::Tuple<
std::string, // id
std::string, // name
std::string, // description
std::string, // uri
std::string, // content
std::string, // version
std::string, // type
uint64_t, // created = 0;
uint64_t, // modified = 0;
std::string, // author
std::string, // restricted
bool, // deferred
uint64_t, // timeout
std::string
> ScriptRecordTuple;
typedef std::vector <ScriptRecordTuple> ScriptRecordTupleList;
class ScriptDB : public ORM::DB<ScriptRecordTuple, GWObjects::ScriptEntry> {
public:
ScriptDB( const std::string &name, const std::string &shortname, OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L);
virtual ~ScriptDB() {}
inline uint32_t Version() override {
return 1;
}
bool Upgrade(uint32_t from, uint32_t &to) override;
void Initialize();
};
}

View File

@@ -130,13 +130,11 @@ namespace OpenWifi {
ConvertStatsRecord(i,R);
Stats.emplace_back(R);
}
Select.reset(Sess);
return true;
}
catch (const Poco::Exception &E) {
poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
}
return false;
}

View File

@@ -81,11 +81,7 @@ namespace OpenWifi {
"subscriber VARCHAR(64), "
"entity VARCHAR(64), "
"modified BIGINT,"
"locale varchar(32), "
"restrictedDevice BOOLEAN, "
"pendingConfiguration TEXT, "
"pendingConfigurationCmd VARCHAR(64), "
"restrictionDetails TEXT "
"locale varchar(32) "
",INDEX DeviceOwner (Owner ASC),"
"INDEX LocationIndex (Location ASC))", Poco::Data::Keywords::now;
} else if(dbType_==sqlite || dbType_==pgsql) {
@@ -112,10 +108,7 @@ namespace OpenWifi {
"entity VARCHAR(64) , "
"modified BIGINT,"
"locale varchar(32), "
"restrictedDevice BOOLEAN, "
"pendingConfiguration TEXT,"
"pendingConfigurationCmd VARCHAR(64), "
"restrictionDetails TEXT "
"restrictedDevice BOOLEAN "
")", Poco::Data::Keywords::now;
Sess << "CREATE INDEX IF NOT EXISTS DeviceOwner ON Devices (Owner ASC)", Poco::Data::Keywords::now;
Sess << "CREATE INDEX IF NOT EXISTS DeviceLocation ON Devices (Location ASC)", Poco::Data::Keywords::now;
@@ -128,9 +121,6 @@ namespace OpenWifi {
"alter table devices add column modified bigint",
"alter table devices add column locale varchar(32)",
"alter table devices add column restrictedDevice boolean",
"alter table devices add column pendingConfiguration TEXT",
"alter table devices add column pendingConfigurationCmd VARCHAR(64)",
"alter table devices add column restrictionDetails TEXT",
};
for(const auto &i:Script) {

View File

@@ -794,22 +794,6 @@ stats7count() {
jq < ${result_file}
}
listscripts() {
curl ${FLAGS} -X GET "https://${OWGW}/api/v1/scripts" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
getscript() {
curl ${FLAGS} -X GET "https://${OWGW}/api/v1/script/$1" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
check_response() {
if [ -s "$1" ]; then
@@ -1081,8 +1065,6 @@ case "$1" in
"notifications") login; notifications "$2"; logout;;
"stats7") login; stats7 "$2"; logout;;
"stats7count") login; stats7count "$2"; logout;;
"listscripts") login; listscripts; logout;;
"getscript") login; getscript "$2"; logout;;
"testtoken") testtoken;;
*) help ;;
esac

View File

@@ -1,9 +0,0 @@
#!/bin/bash
private_key_name="$1"-private-key.pem
public_key_name="$1"-public-key.pem
echo "Generating private key..."
openssl genrsa -out ${private_key_name} 2048
echo "Extracting public key"
openssl rsa -in ${private_key_name} -outform PEM -pubout -out ${public_key_name}

View File

@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvDyH5dKXDH6inAB6HeKekywaPoHi/kogKtsezOEaSoijdrJm
8k3ohC4NzmmXzMa9taaQCE5DMDq1ZWuv8uKyCyRSqhnBIqj6Oa7KRzVnYDpk4Vkd
FS+A++VpYhYVFeUFhtb6Ey1gkXVjOXiy3UiJuEv9aeX2PzL3IUF+o4cfkOe42QQB
k3hgWFhinjb39TtssrhUt1+/kq2EEFZmjKK7szTqpjBTZKgfvL7pkjtZ1+V7/G5R
pkYCrITh9WqyBp2lFyQbnN4GIrPVc+pr1Tk0ZbgAyRnkNaijLm79akNt3xIBzJSB
46kAUjZsKJY/Kh3FM4OoqvJRwYcWvoMXb8rRaQIDAQABAoIBAQCVgS4ep0g5MEtO
xEI5gkiYc6rUgq0bcxxhbW/lIdST5jqOh9ukD6ThdwKYMt3SUvdSU1yKfD55C+gP
CZzRuKPYnZzaZWI0eSlkryMRs6TLlRWStgiXTwePCgLNWOSeYywkkJJGsP/GCAor
F2ZYwsg/jHtVpMQUJhKKY06F60hy+Xtpe8fYEkbLfh1j7OzwBKGZOn+lp2YXXJBU
3ccSwwIpJQu/O9SM8rMchL7izNU60zONYlswr3fF148mMwDS9RYMBMCPqb6wNfNm
EhmMPR7PlsJmlV96rlniwbTh0/I67w7xEThFM2xRx2JZjBZVYD5GMNWE3tKBQnwX
H23PXzuRAoGBAOfWBTxDJZzAMXU8EK12su8bhFOv13D7HlGUA+Y2a9ngzs/rOZmg
buNTjLyod50dSPjZm2b2TDZOXPrA13b3HR+NTfDYzhMElzr4DWPF/X4c2qRylWqb
8G8xrrTsq1HQYTWbJI60zuorD8s+w3Kt/G2w6Iq590Q4Iw7uHMra8IbvAoGBAM/b
KX5BxliqNQIv3+XnSEBhQqLbE7VjPJztXtsknAO8mv/vUJJWta9NjoCGKdaKh4KF
9u88ixkfvOYYVZTbQwUhNCj5PuqW+i2ikmAucMsiVoPBXFUqnoIA5274+hQ7sf0K
JndP7FDKiJkAGb0nF6okmEQO+tHji6oL31ITde0nAoGASEyQOWjfU/ED+4GN2erI
hpTYQZj24P8PR3WXebXDEKFxHZpHzkcgDbjCjRskolS9qw2BzyxEPDNX/8Mf7rPF
208f3VpfecLWvscYteLK2Qd6kApD2oljA+pEh5u/GbaYejU1w2NTm+dt935NSXhE
3phrDMhN+nJfTIqpZAG/PPUCgYEAi5tWSTkAcbkQlYF2TsKDIsqwqRWgLSqUIYrF
NUdnipL5QIGKil+29CGRXv29yB2PWrmD27e8bYmFpL4fbTW/1AgzMnoGKiZxrokM
65EFrUpI9YG/9GwFvqfAyiZsQX6+04gnwedqf/EowirxHrzNBjhCFSRCjwrYWcRT
oJr1j+0CgYA7LktUigAIoLTlo09nGoN7UBySRBRCn6e+vSSyasWLVQ3KPX9tmKDH
UXSSFoki+vcbFG/IgrwfawhmPlcXUPxa021Kj0HPiNGrKK/klhuSmkWulP9xzuAM
8SqN58+BnOYxFQDXJq2ui6NJ+I1O7Mj+uaSiNzpMgqcHazRQy5c+cQ==
-----END RSA PRIVATE KEY-----

View File

@@ -1,9 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvDyH5dKXDH6inAB6HeKe
kywaPoHi/kogKtsezOEaSoijdrJm8k3ohC4NzmmXzMa9taaQCE5DMDq1ZWuv8uKy
CyRSqhnBIqj6Oa7KRzVnYDpk4VkdFS+A++VpYhYVFeUFhtb6Ey1gkXVjOXiy3UiJ
uEv9aeX2PzL3IUF+o4cfkOe42QQBk3hgWFhinjb39TtssrhUt1+/kq2EEFZmjKK7
szTqpjBTZKgfvL7pkjtZ1+V7/G5RpkYCrITh9WqyBp2lFyQbnN4GIrPVc+pr1Tk0
ZbgAyRnkNaijLm79akNt3xIBzJSB46kAUjZsKJY/Kh3FM4OoqvJRwYcWvoMXb8rR
aQIDAQAB
-----END PUBLIC KEY-----

View File

@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvPbxCM3RvHaAZq0G9yXgzaHy9q/RzuIKiCC8cmVQ2PsTvx2m
YP75Ech0omMbWr+nfcgNGHrIxmTXM8Jr77oH9J1pUiBZj0plWp3Bj6S4on7OfRBi
tq6rFUvjyGVg08Khp+KLnPE2Ga+YksC/mK7oXjYRyjH99uX9pOCPJDj1rFpsvDjP
0xu9nkgvhWfzqPvLsLZv5RHM+a1TigckSGl3CpWUNkU/o7ozfvMUQgTBvalbCSTY
9PE3JvkoPd2DARoOmtpAsUkCVx5V18+j5aCxYIG8tPONh8addblLYeskKI9PvzSE
hmazT5deaQHSSLwZo96qtXcdMPIilcSqet9NfQIDAQABAoIBABSEi691Caz5AQAl
EXiMeFhbmVIHzTQ1fwdA5rVVIu4sdPxvb71gchLoPSHUuQelf748lo9t5ZcFJAjO
t4GUJYD+Bo2QTaktXsv0DSxXqmSaeDlEKjPDy3fIgbckqtrTa1IbWyVzW3h2hI6K
t0MQ2tI/9LaLrxO77UqVx3UbajGIf/M2GI91ZChaEa37YpIDu1so4NNZIzGQV3oT
Gq+XpWOtmw/6Dk2AEQHdibytge58yTXZLoe49n02X2UepHNd9Bnwv5WvmJZqgA+r
UI67YCfg35NoT45p7RMYcZCHvZU7+nYMCgDxV9o91VpylZ99plhFVRZSCfI0Ynrq
t9aX4tECgYEA9QSTbTGDZwzmKHHc75ZapjJKkATnszOYF7pgRqOv+5UWayhy3J/z
hyTAGjGr2FQH5HwGAvAwVsJ1WhQHedk/W8lqea+EqCHSau/HGsYQKD061jP0x2G6
zSiBKi0sHxFDRztV9Llny2eCLHGBR+yFQRZW1DwLwpsFg8EeYIcmoV8CgYEAxW8w
sJHW8uz3wW0ntE0dSKVEKImb+pgNI0LS30X0KJilDTliNLHPphhYQvEl4H2t2XXd
x3O4KbQ0fnXi7iyEO6v95ZH8P4OcjpZ2wXV51t8H5DD9hCTXc7yLR+FhaH3XoNVf
EETjiTwPdCa0MsswKRF/39chYQ1sF5a6n6t+MqMCgYEA8jPjyDz5uBR4L+Lek7f9
Q+zS6CrxH6QQ5OPH6AxHGlr2HleNs6oqAZ3CiCIxzVbDtokjKCRmpFz1xGWoPjsS
9pjUOBXY/JrydeMw3raLojtkvfn+LlndXpB7nkWpJ8zYxMFS5uegQuG/PE+3jHGy
B/UdQA9bULQNb4CnlqQC++ECgYEAunNWFPm1d7aoBygRXemRZSCF7I6AGjjr90fN
IwPKH2iAPqvZfZAKXH4TJCzeK1IlEv+HkStMWT4QcPjddTXfLwcvAFVMVaLx/4pC
3lIV3QDFUA+f6uJsAaWmFxzWQ7rMHtxCKXgVNW3d3kAK3wkaEz6ud3KP2Dq3wNMc
rVtkE2cCgYB5cNbmStIlmc/bpBGkfW7Sv1RwPVCV3U5Vv4NDoM+EDJ4UDmRKB0Ht
cG5bfym6bgcBOWVAQNsNgpGJGAfF3RIVzeFgiD/cDDG04dIia9T7HuSbsJSoXYde
gSI068hPzfh3xksus0RPPr5DDKlTUsD5e02ZgrlmRez6ILV2dMhyCQ==
-----END RSA PRIVATE KEY-----

View File

@@ -1,9 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvPbxCM3RvHaAZq0G9yXg
zaHy9q/RzuIKiCC8cmVQ2PsTvx2mYP75Ech0omMbWr+nfcgNGHrIxmTXM8Jr77oH
9J1pUiBZj0plWp3Bj6S4on7OfRBitq6rFUvjyGVg08Khp+KLnPE2Ga+YksC/mK7o
XjYRyjH99uX9pOCPJDj1rFpsvDjP0xu9nkgvhWfzqPvLsLZv5RHM+a1TigckSGl3
CpWUNkU/o7ozfvMUQgTBvalbCSTY9PE3JvkoPd2DARoOmtpAsUkCVx5V18+j5aCx
YIG8tPONh8addblLYeskKI9PvzSEhmazT5deaQHSSLwZo96qtXcdMPIilcSqet9N
fQIDAQAB
-----END PUBLIC KEY-----