Compare commits

...

18 Commits

Author SHA1 Message Date
TIP Automation User
8466e0e025 Chg: update image tag in helm values to v2.11.0 2023-10-04 14:03:33 +00:00
TIP Automation User
a408d0d128 Chg: update image tag in helm values to v2.11.0-RC2 2023-09-26 14:44:44 +00:00
Stephane Bourque
fb2f53c63d Merge pull request #86 from Telecominfraproject/main
Merge latest into 2.11
2023-09-24 11:58:05 -07:00
stephb9959
b018dc70ef https://telecominfraproject.atlassian.net/browse/WIFI-12954
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-24 11:04:47 -07:00
stephb9959
42d44b056e https://telecominfraproject.atlassian.net/browse/WIFI-12954
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-23 15:28:13 -07:00
stephb9959
7d9d5b4d15 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-19 21:58:55 -07:00
stephb9959
7fc77e529b https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-13 13:16:09 -07:00
stephb9959
e8986d84b4 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-13 12:14:45 -07:00
stephb9959
f54fd2b411 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-13 10:04:30 -07:00
stephb9959
86f3754c7e https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-01 09:25:29 -07:00
TIP Automation User
4223cb8146 Chg: update image tag in helm values to v2.11.0-RC1 2023-09-01 16:08:50 +00:00
stephb9959
260927a3eb https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-08-28 11:33:08 -07:00
stephb9959
bb571ad11a https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-08-28 10:46:29 -07:00
stephb9959
bd0fbfd6d2 https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-08-03 22:28:43 -07:00
stephb9959
33ba7b2323 https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-08-03 11:07:46 -07:00
stephb9959
28cbc79890 https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-08-03 10:34:25 -07:00
stephb9959
0137d8ee66 https://telecominfraproject.atlassian.net/browse/WIFI-12738
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-07-12 16:36:07 -07:00
stephb9959
1ca77de37e https://telecominfraproject.atlassian.net/browse/WIFI-12738
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-07-10 13:15:11 -07:00
23 changed files with 1216 additions and 533 deletions

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
project(owfms VERSION 2.10.0) project(owfms VERSION 2.11.0)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
@@ -61,7 +61,7 @@ include_directories(/usr/local/include /usr/local/opt/openssl/include src inclu
configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY) configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY)
add_compile_options(-Wall -Wextra) add_compile_options(-Wall -Wextra)
add_definitions(-DPOCO_LOG_DEBUG="1") add_definitions(-DPOCO_LOG_DEBUG="1" -DBOOST_NO_CXX98_FUNCTION_BASE=1)
if(ASAN) if(ASAN)
add_compile_options(-fsanitize=address) add_compile_options(-fsanitize=address)

View File

@@ -1,6 +1,9 @@
ARG DEBIAN_VERSION=11.5-slim ARG DEBIAN_VERSION=11.5-slim
ARG POCO_VERSION=poco-tip-v2 ARG POCO_VERSION=poco-tip-v2
ARG CPPKAFKA_VERSION=tip-v1 ARG CPPKAFKA_VERSION=tip-v1
ARG VALIJASON_VERSION=tip-v1
ARG APP_NAME=owfms
ARG APP_HOME_DIR=/openwifi
FROM debian:$DEBIAN_VERSION AS build-base FROM debian:$DEBIAN_VERSION AS build-base
@@ -38,14 +41,17 @@ RUN cmake ..
RUN cmake --build . --config Release -j8 RUN cmake --build . --config Release -j8
RUN cmake --build . --target install RUN cmake --build . --target install
FROM build-base AS owfms-build FROM build-base AS app-build
ADD CMakeLists.txt build /owfms/ ARG APP_NAME
ADD overlays /owfms/overlays
ADD cmake /owfms/cmake ADD CMakeLists.txt build /${APP_NAME}/
ADD src /owfms/src ADD overlays /${APP_NAME}/overlays
ADD .git /owfms/.git ADD cmake /${APP_NAME}/cmake
ADD src /${APP_NAME}/src
ADD .git /${APP_NAME}/.git
ARG VCPKG_VERSION=2022.11.14 ARG VCPKG_VERSION=2022.11.14
RUN git clone --depth 1 --branch ${VCPKG_VERSION} https://github.com/microsoft/vcpkg && \ RUN git clone --depth 1 --branch ${VCPKG_VERSION} https://github.com/microsoft/vcpkg && \
./vcpkg/bootstrap-vcpkg.sh && \ ./vcpkg/bootstrap-vcpkg.sh && \
mkdir /vcpkg/custom-triplets && \ mkdir /vcpkg/custom-triplets && \
@@ -58,23 +64,28 @@ COPY --from=poco-build /usr/local/lib /usr/local/lib
COPY --from=cppkafka-build /usr/local/include /usr/local/include COPY --from=cppkafka-build /usr/local/include /usr/local/include
COPY --from=cppkafka-build /usr/local/lib /usr/local/lib COPY --from=cppkafka-build /usr/local/lib /usr/local/lib
WORKDIR /owfms WORKDIR /${APP_NAME}
RUN mkdir cmake-build RUN mkdir cmake-build
WORKDIR /owfms/cmake-build WORKDIR /${APP_NAME}/cmake-build
RUN cmake -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake .. RUN cmake -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake ..
RUN cmake --build . --config Release -j8 RUN cmake --build . --config Release -j8
FROM debian:$DEBIAN_VERSION FROM debian:$DEBIAN_VERSION
ENV OWFMS_USER=owfms \ ARG APP_NAME
OWFMS_ROOT=/owfms-data \ ARG APP_HOME_DIR
OWFMS_CONFIG=/owfms-data
RUN useradd "$OWFMS_USER" ENV APP_NAME=$APP_NAME \
APP_USER=$APP_NAME \
APP_ROOT=/$APP_NAME-data \
APP_CONFIG=/$APP_NAME-data \
APP_HOME_DIR=$APP_HOME_DIR
RUN mkdir /openwifi RUN useradd $APP_USER
RUN mkdir -p "$OWFMS_ROOT" "$OWFMS_CONFIG" && \
chown "$OWFMS_USER": "$OWFMS_ROOT" "$OWFMS_CONFIG" RUN mkdir $APP_HOME_DIR
RUN mkdir -p "$APP_ROOT" "$APP_CONFIG" && \
chown "$APP_USER": "$APP_ROOT" "$APP_CONFIG"
RUN apt-get update && apt-get install --no-install-recommends -y \ RUN apt-get update && apt-get install --no-install-recommends -y \
librdkafka++1 gosu gettext ca-certificates bash jq curl wget \ librdkafka++1 gosu gettext ca-certificates bash jq curl wget \
@@ -83,14 +94,14 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
COPY readiness_check /readiness_check COPY readiness_check /readiness_check
COPY test_scripts/curl/cli /cli COPY test_scripts/curl/cli /cli
COPY owfms.properties.tmpl / COPY $APP_NAME.properties.tmpl /
COPY docker-entrypoint.sh / COPY docker-entrypoint.sh /
COPY wait-for-postgres.sh / COPY wait-for-postgres.sh /
RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \ RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.crt -O /usr/local/share/ca-certificates/restapi-ca-selfsigned.crt
COPY --from=owfms-build /owfms/cmake-build/owfms /openwifi/owfms COPY --from=app-build /$APP_NAME/cmake-build/$APP_NAME $APP_HOME_DIR/$APP_NAME
COPY --from=owfms-build /vcpkg/installed/x64-linux/lib/ /usr/local/lib/ COPY --from=app-build /vcpkg/installed/x64-linux/lib/ /usr/local/lib/
COPY --from=cppkafka-build /cppkafka/cmake-build/src/lib/ /usr/local/lib/ COPY --from=cppkafka-build /cppkafka/cmake-build/src/lib/ /usr/local/lib/
COPY --from=poco-build /poco/cmake-build/lib/ /usr/local/lib/ COPY --from=poco-build /poco/cmake-build/lib/ /usr/local/lib/
@@ -99,4 +110,4 @@ RUN ldconfig
EXPOSE 16004 17004 16104 EXPOSE 16004 17004 16104
ENTRYPOINT ["/docker-entrypoint.sh"] ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/openwifi/owfms"] CMD ${APP_HOME_DIR}/${APP_NAME}

2
build
View File

@@ -1 +1 @@
17 11

View File

@@ -9,7 +9,7 @@ fullnameOverride: ""
images: images:
owfms: owfms:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owfms repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owfms
tag: main tag: v2.11.0
pullPolicy: Always pullPolicy: Always
# regcred: # regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io # registry: tip-tip-wlan-cloud-ucentral.jfrog.io

View File

@@ -353,6 +353,33 @@ components:
type: integer type: integer
format: int64 format: int64
SystemResources:
type: object
properties:
numberOfFileDescriptors:
type: integer
format: int64
currRealMem:
type: integer
format: int64
peakRealMem:
type: integer
format: int64
currVirtMem:
type: integer
format: int64
peakVirtMem:
type: integer
format: int64
SystemCommandResults:
type: object
oneOf:
- $ref: '#/components/schemas/SystemResources'
- $ref: '#/components/schemas/SystemInfoResults'
- $ref: '#/components/schemas/StringList'
- $ref: '#/components/schemas/TagValuePairList'
SystemCommandSetLogLevel: SystemCommandSetLogLevel:
type: object type: object
properties: properties:
@@ -743,19 +770,19 @@ paths:
operationId: getFirmwareAge operationId: getFirmwareAge
parameters: parameters:
- in: query - in: query
description: The exact current verion of the firmware on that device. description: The exact current version of the firmware on that device.
name: revision name: revision
schema: schema:
type: string type: string
required: true required: true
- in: query - in: query
description: The exact current verion of the firmware on that device. description: The exact current version of the firmware on that device.
name: deviceType name: deviceType
schema: schema:
type: string type: string
required: true required: true
- in: query - in: query
description: Specify lits of serial numbers to retrive age for description: Specify list of serial numbers to retrieve age for
name: select name: select
schema: schema:
type: string type: string
@@ -925,16 +952,12 @@ paths:
type: string type: string
enum: enum:
- info - info
- extraConfiguration
- resources
required: true required: true
responses: responses:
200: 200:
description: Successfull command execution $ref: '#/components/schemas/SystemCommandResults'
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemInfoResults'
403: 403:
$ref: '#/components/responses/Unauthorized' $ref: '#/components/responses/Unauthorized'
404: 404:

View File

@@ -26,7 +26,7 @@ namespace OpenWifi {
Response.set("Connection", "keep-alive"); Response.set("Connection", "keep-alive");
Response.setVersion(Poco::Net::HTTPMessage::HTTP_1_1); Response.setVersion(Poco::Net::HTTPMessage::HTTP_1_1);
std::ostream &Answer = Response.send(); std::ostream &Answer = Response.send();
Answer << "process Alive and kicking!"; Answer << ALBHealthCheckServer()->CallbackText();
} catch (...) { } catch (...) {
} }
} }

View File

@@ -37,6 +37,8 @@ namespace OpenWifi {
inline static std::atomic_uint64_t req_id_ = 1; inline static std::atomic_uint64_t req_id_ = 1;
}; };
typedef std::string ALBHealthMessageCallback();
class ALBHealthCheckServer : public SubSystemServer { class ALBHealthCheckServer : public SubSystemServer {
public: public:
ALBHealthCheckServer(); ALBHealthCheckServer();
@@ -48,10 +50,22 @@ namespace OpenWifi {
int Start() override; int Start() override;
void Stop() override; void Stop() override;
inline void RegisterExtendedHealthMessage(ALBHealthMessageCallback *F) {
Callback_=F;
};
inline std::string CallbackText() {
if(Callback_== nullptr) {
return "process Alive and kicking!";
} else {
return Callback_();
}
}
private: private:
std::unique_ptr<Poco::Net::HTTPServer> Server_; std::unique_ptr<Poco::Net::HTTPServer> Server_;
std::unique_ptr<Poco::Net::ServerSocket> Socket_; std::unique_ptr<Poco::Net::ServerSocket> Socket_;
ALBHealthMessageCallback *Callback_= nullptr;
int Port_ = 0; int Port_ = 0;
mutable std::atomic_bool Running_ = false; mutable std::atomic_bool Running_ = false;
}; };

View File

@@ -34,9 +34,17 @@ static std::string DefaultUCentralSchema = R"foo(
"$schema": "http://json-schema.org/draft-07/schema#", "$schema": "http://json-schema.org/draft-07/schema#",
"type": "object", "type": "object",
"properties": { "properties": {
"strict": {
"type": "boolean",
"default": false
},
"uuid": { "uuid": {
"type": "integer" "type": "integer"
}, },
"public_ip_lookup": {
"type": "string",
"format": "uc-fqdn"
},
"unit": { "unit": {
"$ref": "#/$defs/unit" "$ref": "#/$defs/unit"
}, },
@@ -110,6 +118,20 @@ static std::string DefaultUCentralSchema = R"foo(
"random-password": { "random-password": {
"type": "boolean", "type": "boolean",
"default": false "default": false
},
"beacon-advertisement": {
"type": "object",
"properties": {
"device-name": {
"type": "boolean"
},
"device-serial": {
"type": "boolean"
},
"network-id": {
"type": "integer"
}
}
} }
} }
}, },
@@ -218,6 +240,52 @@ static std::string DefaultUCentralSchema = R"foo(
} }
} }
}, },
"interface.ssid.encryption": {
"type": "object",
"properties": {
"proto": {
"type": "string",
"enum": [
"none",
"owe",
"owe-transition",
"psk",
"psk2",
"psk-mixed",
"psk2-radius",
"wpa",
"wpa2",
"wpa-mixed",
"sae",
"sae-mixed",
"wpa3",
"wpa3-192",
"wpa3-mixed"
],
"examples": [
"psk2"
]
},
"key": {
"type": "string",
"maxLength": 63,
"minLength": 8
},
"ieee80211w": {
"type": "string",
"enum": [
"disabled",
"optional",
"required"
],
"default": "disabled"
},
"key-caching": {
"type": "boolean",
"default": true
}
}
},
"definitions": { "definitions": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -634,26 +702,6 @@ static std::string DefaultUCentralSchema = R"foo(
"type": "string", "type": "string",
"format": "uc-timeout", "format": "uc-timeout",
"default": "6h" "default": "6h"
},
"relay-server": {
"type": "string",
"format": "ipv4",
"example": "192.168.2.1"
},
"circuit-id-format": {
"type": "string",
"example": [
"\\{Interface\\}:\\{VLAN-Id\\}:\\{SSID\\}:\\{Model\\}:\\{Name\\}:\\{AP-MAC\\}:\\{Location\\}",
"\\{AP-MAC\\};\\{SSID\\};\\{Crypto\\}",
"\\{Name\\} \\{ESSID\\}"
]
},
"remote-id-format": {
"type": "string",
"example": [
"\\{Client-MAC-hex\\} \\{SSID\\}",
"\\{AP-MAC-hex\\} \\{SSID\\}"
]
} }
} }
}, },
@@ -732,7 +780,8 @@ static std::string DefaultUCentralSchema = R"foo(
"type": "string", "type": "string",
"enum": [ "enum": [
"dynamic", "dynamic",
"static" "static",
"none"
], ],
"examples": [ "examples": [
"static" "static"
@@ -1022,52 +1071,6 @@ static std::string DefaultUCentralSchema = R"foo(
} }
] ]
}, },
"interface.ssid.encryption": {
"type": "object",
"properties": {
"proto": {
"type": "string",
"enum": [
"none",
"owe",
"owe-transition",
"psk",
"psk2",
"psk-mixed",
"psk2-radius",
"wpa",
"wpa2",
"wpa-mixed",
"sae",
"sae-mixed",
"wpa3",
"wpa3-192",
"wpa3-mixed"
],
"examples": [
"psk2"
]
},
"key": {
"type": "string",
"maxLength": 63,
"minLength": 8
},
"ieee80211w": {
"type": "string",
"enum": [
"disabled",
"optional",
"required"
],
"default": "disabled"
},
"key-caching": {
"type": "boolean",
"default": true
}
}
},
"interface.ssid.multi-psk": { "interface.ssid.multi-psk": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -1232,6 +1235,32 @@ static std::string DefaultUCentralSchema = R"foo(
"secret" "secret"
] ]
}, },
"secondary": {
"type": "object",
"properties": {
"host": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"examples": [
1812
]
},
"secret": {
"type": "string",
"examples": [
"secret"
]
}
}
},
"request-attribute": { "request-attribute": {
"type": "array", "type": "array",
"items": { "items": {
@@ -1309,6 +1338,25 @@ static std::string DefaultUCentralSchema = R"foo(
"value": "Example Operator" "value": "Example Operator"
} }
] ]
},
{
"type": "object",
"properties": {
"id": {
"type": "integer",
"maximum": 255,
"minimum": 1
},
"hex-value": {
"type": "string"
}
},
"examples": [
{
"id": 32,
"value": "0a0b0c0d"
}
]
} }
] ]
} }
@@ -1658,6 +1706,236 @@ static std::string DefaultUCentralSchema = R"foo(
} }
} }
}, },
"service.captive.click": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "click-to-continue"
}
}
},
"service.captive.radius": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "radius"
},
"auth-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"auth-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"auth-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"acct-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"acct-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-interval": {
"type": "integer",
"default": 600
}
}
},
"service.captive.credentials": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "credentials"
},
"credentials": {
"type": "array",
"items": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
}
}
}
},
"service.captive.uam": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "uam"
},
"uam-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 3990
},
"uam-secret": {
"type": "string"
},
"uam-server": {
"type": "string"
},
"nasid": {
"type": "string"
},
"nasmac": {
"type": "string"
},
"auth-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"auth-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"auth-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"acct-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"acct-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-interval": {
"type": "integer",
"default": 600
},
"ssid": {
"type": "string"
},
"mac-format": {
"type": "string",
"enum": [
"aabbccddeeff",
"aa-bb-cc-dd-ee-ff",
"aa:bb:cc:dd:ee:ff",
"AABBCCDDEEFF",
"AA:BB:CC:DD:EE:FF",
"AA-BB-CC-DD-EE-FF"
]
},
"final-redirect-url": {
"type": "string",
"enum": [
"default",
"uam"
]
},
"mac-auth": {
"type": "boolean",
"default": "default"
},
"radius-gw-proxy": {
"type": "boolean",
"default": false
}
}
},
"service.captive": {
"allOf": [
{
"oneOf": [
{
"$ref": "#/$defs/service.captive.click"
},
{
"$ref": "#/$defs/service.captive.radius"
},
{
"$ref": "#/$defs/service.captive.credentials"
},
{
"$ref": "#/$defs/service.captive.uam"
}
]
},
{
"type": "object",
"properties": {
"walled-garden-fqdn": {
"type": "array",
"items": {
"type": "string"
}
},
"walled-garden-ipaddr": {
"type": "array",
"items": {
"type": "string",
"format": "uc-ip"
}
},
"web-root": {
"type": "string",
"format": "uc-base64"
},
"idle-timeout": {
"type": "integer",
"default": 600
},
"session-timeout": {
"type": "integer"
}
}
}
]
},
"interface.ssid": { "interface.ssid": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -1710,6 +1988,10 @@ static std::string DefaultUCentralSchema = R"foo(
"isolate-clients": { "isolate-clients": {
"type": "boolean" "type": "boolean"
}, },
"strict-forwarding": {
"type": "boolean",
"default": false
},
"power-save": { "power-save": {
"type": "boolean" "type": "boolean"
}, },
@@ -1757,6 +2039,11 @@ static std::string DefaultUCentralSchema = R"foo(
"decription": "This option allows embedding custom vendor specific IEs inside the beacons of a BSS in AP mode.", "decription": "This option allows embedding custom vendor specific IEs inside the beacons of a BSS in AP mode.",
"type": "string" "type": "string"
}, },
"tip-information-element": {
"decription": "The device will broadcast the TIP vendor IE inside its beacons if this option is enabled.",
"type": "boolean",
"default": true
},
"fils-discovery-interval": { "fils-discovery-interval": {
"type": "integer", "type": "integer",
"default": 20, "default": 20,
@@ -1778,8 +2065,15 @@ static std::string DefaultUCentralSchema = R"foo(
"$ref": "#/$defs/interface.ssid.rate-limit" "$ref": "#/$defs/interface.ssid.rate-limit"
}, },
"roaming": { "roaming": {
"anyOf": [
{
"$ref": "#/$defs/interface.ssid.roaming" "$ref": "#/$defs/interface.ssid.roaming"
}, },
{
"type": "boolean"
}
]
},
"radius": { "radius": {
"$ref": "#/$defs/interface.ssid.radius" "$ref": "#/$defs/interface.ssid.radius"
}, },
@@ -1795,6 +2089,9 @@ static std::string DefaultUCentralSchema = R"foo(
"access-control-list": { "access-control-list": {
"$ref": "#/$defs/interface.ssid.acl" "$ref": "#/$defs/interface.ssid.acl"
}, },
"captive": {
"$ref": "#/$defs/service.captive"
},
"hostapd-bss-raw": { "hostapd-bss-raw": {
"type": "array", "type": "array",
"items": { "items": {
@@ -1962,6 +2259,17 @@ static std::string DefaultUCentralSchema = R"foo(
] ]
} }
}, },
"vlan-awareness": {
"type": "object",
"properties": {
"first": {
"type": "integer"
},
"last": {
"type": "integer"
}
}
},
"vlan": { "vlan": {
"$ref": "#/$defs/interface.vlan" "$ref": "#/$defs/interface.vlan"
}, },
@@ -2084,6 +2392,10 @@ static std::string DefaultUCentralSchema = R"foo(
"examples": [ "examples": [
"01234567890123456789012345678901" "01234567890123456789012345678901"
] ]
},
"mutual-tls": {
"type": "boolean",
"default": true
} }
} }
}, },
@@ -2155,6 +2467,24 @@ static std::string DefaultUCentralSchema = R"foo(
"type": "boolean", "type": "boolean",
"default": false "default": false
}, },
"mode": {
"type": "string",
"enum": [
"radius",
"user"
]
},
"port-filter": {
"type": "array",
"items": {
"type": "string",
"examples": [
{
"LAN1": null
}
]
}
},
"server-certificate": { "server-certificate": {
"type": "string" "type": "string"
}, },
@@ -2166,6 +2496,77 @@ static std::string DefaultUCentralSchema = R"foo(
"items": { "items": {
"$ref": "#/$defs/interface.ssid.radius.local-user" "$ref": "#/$defs/interface.ssid.radius.local-user"
} }
},
"radius": {
"type": "object",
"properties": {
"nas-identifier": {
"type": "string"
},
"auth-server-addr": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"auth-server-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"examples": [
1812
]
},
"auth-server-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-server-addr": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"acct-server-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"examples": [
1813
]
},
"acct-server-secret": {
"type": "string",
"examples": [
"secret"
]
},
"coa-server-addr": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"coa-server-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"examples": [
1814
]
},
"coa-server-secret": {
"type": "string",
"examples": [
"secret"
]
}
}
} }
} }
}, },
@@ -2489,6 +2890,12 @@ static std::string DefaultUCentralSchema = R"foo(
} }
} }
}, },
"services": {
"type": "array",
"items": {
"type": "string"
}
},
"classifier": { "classifier": {
"type": "array", "type": "array",
"items": { "items": {
@@ -2693,236 +3100,6 @@ static std::string DefaultUCentralSchema = R"foo(
} }
} }
}, },
"service.captive.click": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "click-to-continue"
}
}
},
"service.captive.radius": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "radius"
},
"auth-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"auth-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"auth-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"acct-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"acct-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-interval": {
"type": "integer",
"default": 600
}
}
},
"service.captive.credentials": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "credentials"
},
"credentials": {
"type": "array",
"items": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
}
}
}
},
"service.captive.uam": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "uam"
},
"uam-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 3990
},
"uam-secret": {
"type": "string"
},
"uam-server": {
"type": "string"
},
"nasid": {
"type": "string"
},
"nasmac": {
"type": "string"
},
"auth-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"auth-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"auth-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"acct-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"acct-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-interval": {
"type": "integer",
"default": 600
},
"ssid": {
"type": "string"
},
"mac-format": {
"type": "string",
"enum": [
"aabbccddeeff",
"aa-bb-cc-dd-ee-ff",
"aa:bb:cc:dd:ee:ff",
"AABBCCDDEEFF",
"AA:BB:CC:DD:EE:FF",
"AA-BB-CC-DD-EE-FF"
]
},
"final-redirect-url": {
"type": "string",
"enum": [
"default",
"uam"
]
},
"mac-auth": {
"type": "boolean",
"default": "default"
},
"radius-gw-proxy": {
"type": "boolean",
"default": false
}
}
},
"service.captive": {
"allOf": [
{
"oneOf": [
{
"$ref": "#/$defs/service.captive.click"
},
{
"$ref": "#/$defs/service.captive.radius"
},
{
"$ref": "#/$defs/service.captive.credentials"
},
{
"$ref": "#/$defs/service.captive.uam"
}
]
},
{
"type": "object",
"properties": {
"walled-garden-fqdn": {
"type": "array",
"items": {
"type": "string"
}
},
"walled-garden-ipaddr": {
"type": "array",
"items": {
"type": "string",
"format": "uc-ip"
}
},
"web-root": {
"type": "string",
"format": "uc-base64"
},
"idle-timeout": {
"type": "integer",
"default": 600
},
"session-timeout": {
"type": "integer"
}
}
}
]
},
"service.gps": { "service.gps": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -2941,6 +3118,50 @@ static std::string DefaultUCentralSchema = R"foo(
} }
} }
}, },
"service.dhcp-relay": {
"type": "object",
"properties": {
"select-ports": {
"type": "array",
"items": {
"type": "string"
}
},
"vlans": {
"type": "array",
"items": {
"type": "object",
"properties": {
"vlan": {
"type": "number"
},
"relay-server": {
"type": "string",
"format": "uc-ip"
},
"circuit-id-format": {
"type": "string",
"enum": [
"vlan-id",
"ap-mac",
"ssid"
],
"default": "vlan-id"
},
"remote-id-format": {
"type": "string",
"enum": [
"vlan-id",
"ap-mac",
"ssid"
],
"default": "ap-mac"
}
}
}
}
}
},
"service": { "service": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -3000,6 +3221,9 @@ static std::string DefaultUCentralSchema = R"foo(
}, },
"gps": { "gps": {
"$ref": "#/$defs/service.gps" "$ref": "#/$defs/service.gps"
},
"dhcp-relay": {
"$ref": "#/$defs/service.dhcp-relay"
} }
} }
}, },

View File

@@ -14,18 +14,18 @@ namespace OpenWifi {
void EventBusManager::run() { void EventBusManager::run() {
Running_ = true; Running_ = true;
Utils::SetThreadName("fmwk:EventMgr"); Utils::SetThreadName("fmwk:EventMgr");
auto Msg = std::make_shared<std::string>(MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN)); auto Msg = (MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN));
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg, KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
false); false);
while (Running_) { while (Running_) {
Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer()); Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer());
if (!Running_) if (!Running_)
break; break;
Msg = std::make_shared<std::string>(MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE)); Msg = (MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE));
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(),
Msg, false); Msg, false);
} }
Msg = std::make_shared<std::string>(MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_LEAVE)); Msg = (MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_LEAVE));
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg, KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
false); false);
}; };

View File

@@ -6,6 +6,7 @@
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "cppkafka/utils/consumer_dispatcher.h"
namespace OpenWifi { namespace OpenWifi {
@@ -99,9 +100,12 @@ namespace OpenWifi {
try { try {
auto Msg = dynamic_cast<KafkaMessage *>(Note.get()); auto Msg = dynamic_cast<KafkaMessage *>(Note.get());
if (Msg != nullptr) { if (Msg != nullptr) {
Producer.produce(cppkafka::MessageBuilder(Msg->Topic()) auto NewMessage = cppkafka::MessageBuilder(Msg->Topic());
.key(Msg->Key()) NewMessage.key(Msg->Key());
.payload(Msg->Payload())); NewMessage.partition(0);
NewMessage.payload(Msg->Payload());
Producer.produce(NewMessage);
Producer.flush();
} }
} catch (const cppkafka::HandleException &E) { } catch (const cppkafka::HandleException &E) {
poco_warning(Logger_, poco_warning(Logger_,
@@ -156,43 +160,49 @@ namespace OpenWifi {
} }
}); });
bool AutoCommit = MicroServiceConfigGetBool("openwifi.kafka.auto.commit", false); // bool AutoCommit = MicroServiceConfigGetBool("openwifi.kafka.auto.commit", false);
auto BatchSize = MicroServiceConfigGetInt("openwifi.kafka.consumer.batchsize", 20); // auto BatchSize = MicroServiceConfigGetInt("openwifi.kafka.consumer.batchsize", 100);
Types::StringVec Topics; Types::StringVec Topics;
KafkaManager()->Topics(Topics); std::for_each(Topics_.begin(),Topics_.end(),
[&](const std::string & T) { Topics.emplace_back(T); });
Consumer.subscribe(Topics); Consumer.subscribe(Topics);
Running_ = true; Running_ = true;
while (Running_) { std::vector<cppkafka::Message> MsgVec;
Dispatcher_ = std::make_unique<cppkafka::ConsumerDispatcher>(Consumer);
Dispatcher_->run(
// Callback executed whenever a new message is consumed
[&](cppkafka::Message msg) {
// Print the key (if any)
std::lock_guard G(ConsumerMutex_);
auto It = Notifiers_.find(msg.get_topic());
if (It != Notifiers_.end()) {
const auto &FL = It->second;
for (const auto &[CallbackFunc, _] : FL) {
try { try {
std::vector<cppkafka::Message> MsgVec = CallbackFunc(msg.get_key(), msg.get_payload());
Consumer.poll_batch(BatchSize, std::chrono::milliseconds(100)); } catch(const Poco::Exception &E) {
for (auto const &Msg : MsgVec) {
if (!Msg) } catch(...) {
continue;
if (Msg.get_error()) {
if (!Msg.is_eof()) {
poco_error(Logger_,
fmt::format("Error: {}", Msg.get_error().to_string()));
}
if (!AutoCommit)
Consumer.async_commit(Msg);
continue;
}
KafkaManager()->Dispatch(Msg.get_topic().c_str(), Msg.get_key(), std::make_shared<std::string>(Msg.get_payload()));
if (!AutoCommit)
Consumer.async_commit(Msg);
}
} catch (const cppkafka::HandleException &E) {
poco_warning(Logger_,
fmt::format("Caught a Kafka exception (consumer): {}", E.what()));
} catch (const Poco::Exception &E) {
Logger_.log(E);
} catch (...) {
poco_error(Logger_, "std::exception");
} }
} }
}
Consumer.commit(msg);
},
// Whenever there's an error (other than the EOF soft error)
[&Logger_](cppkafka::Error error) {
poco_warning(Logger_,fmt::format("Error: {}", error.to_string()));
},
// Whenever EOF is reached on a partition, print this
[&Logger_](cppkafka::ConsumerDispatcher::EndOfFile, const cppkafka::TopicPartition& topic_partition) {
poco_debug(Logger_,fmt::format("Partition {} EOF", topic_partition.get_partition()));
}
);
Consumer.unsubscribe(); Consumer.unsubscribe();
poco_information(Logger_, "Stopped..."); poco_information(Logger_, "Stopped...");
} }
@@ -213,14 +223,13 @@ namespace OpenWifi {
} }
void KafkaProducer::Produce(const char *Topic, const std::string &Key, void KafkaProducer::Produce(const char *Topic, const std::string &Key,
const std::shared_ptr<std::string> Payload) { const std::string &Payload) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
Queue_.enqueueNotification(new KafkaMessage(Topic, Key, Payload)); Queue_.enqueueNotification(new KafkaMessage(Topic, Key, Payload));
} }
void KafkaConsumer::Start() { void KafkaConsumer::Start() {
if (!Running_) { if (!Running_) {
Running_ = true;
Worker_.start(*this); Worker_.start(*this);
} }
} }
@@ -228,29 +237,16 @@ namespace OpenWifi {
void KafkaConsumer::Stop() { void KafkaConsumer::Stop() {
if (Running_) { if (Running_) {
Running_ = false; Running_ = false;
Worker_.wakeUp(); if(Dispatcher_) {
Dispatcher_->stop();
}
Worker_.join(); Worker_.join();
} }
} }
void KafkaDispatcher::Start() { std::uint64_t KafkaConsumer::RegisterTopicWatcher(const std::string &Topic,
if (!Running_) {
Running_ = true;
Worker_.start(*this);
}
}
void KafkaDispatcher::Stop() {
if (Running_) {
Running_ = false;
Queue_.wakeUpAll();
Worker_.join();
}
}
auto KafkaDispatcher::RegisterTopicWatcher(const std::string &Topic,
Types::TopicNotifyFunction &F) { Types::TopicNotifyFunction &F) {
std::lock_guard G(Mutex_); std::lock_guard G(ConsumerMutex_);
auto It = Notifiers_.find(Topic); auto It = Notifiers_.find(Topic);
if (It == Notifiers_.end()) { if (It == Notifiers_.end()) {
Types::TopicNotifyFunctionList L; Types::TopicNotifyFunctionList L;
@@ -259,11 +255,12 @@ namespace OpenWifi {
} else { } else {
It->second.emplace(It->second.end(), std::make_pair(F, FunctionId_)); It->second.emplace(It->second.end(), std::make_pair(F, FunctionId_));
} }
Topics_.insert(Topic);
return FunctionId_++; return FunctionId_++;
} }
void KafkaDispatcher::UnregisterTopicWatcher(const std::string &Topic, int Id) { void KafkaConsumer::UnregisterTopicWatcher(const std::string &Topic, int Id) {
std::lock_guard G(Mutex_); std::lock_guard G(ConsumerMutex_);
auto It = Notifiers_.find(Topic); auto It = Notifiers_.find(Topic);
if (It != Notifiers_.end()) { if (It != Notifiers_.end()) {
Types::TopicNotifyFunctionList &L = It->second; Types::TopicNotifyFunctionList &L = It->second;
@@ -275,56 +272,17 @@ namespace OpenWifi {
} }
} }
void KafkaDispatcher::Dispatch(const char *Topic, const std::string &Key,
const std::shared_ptr<std::string> Payload) {
std::lock_guard G(Mutex_);
auto It = Notifiers_.find(Topic);
if (It != Notifiers_.end()) {
Queue_.enqueueNotification(new KafkaMessage(Topic, Key, Payload));
}
}
void KafkaDispatcher::run() {
Poco::Logger &Logger_ =
Poco::Logger::create("KAFKA-DISPATCHER", KafkaManager()->Logger().getChannel());
poco_information(Logger_, "Starting...");
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
Utils::SetThreadName("kafka:dispatch");
while (Note && Running_) {
auto Msg = dynamic_cast<KafkaMessage *>(Note.get());
if (Msg != nullptr) {
auto It = Notifiers_.find(Msg->Topic());
if (It != Notifiers_.end()) {
const auto &FL = It->second;
for (const auto &[CallbackFunc, _] : FL) {
CallbackFunc(Msg->Key(), Msg->Payload());
}
}
}
Note = Queue_.waitDequeueNotification();
}
poco_information(Logger_, "Stopped...");
}
void KafkaDispatcher::Topics(std::vector<std::string> &T) {
T.clear();
for (const auto &[TopicName, _] : Notifiers_)
T.push_back(TopicName);
}
int KafkaManager::Start() { int KafkaManager::Start() {
if (!KafkaEnabled_) if (!KafkaEnabled_)
return 0; return 0;
ConsumerThr_.Start(); ConsumerThr_.Start();
ProducerThr_.Start(); ProducerThr_.Start();
Dispatcher_.Start();
return 0; return 0;
} }
void KafkaManager::Stop() { void KafkaManager::Stop() {
if (KafkaEnabled_) { if (KafkaEnabled_) {
poco_information(Logger(), "Stopping..."); poco_information(Logger(), "Stopping...");
Dispatcher_.Stop();
ProducerThr_.Stop(); ProducerThr_.Stop();
ConsumerThr_.Stop(); ConsumerThr_.Stop();
poco_information(Logger(), "Stopped..."); poco_information(Logger(), "Stopped...");
@@ -333,38 +291,27 @@ namespace OpenWifi {
} }
void KafkaManager::PostMessage(const char *topic, const std::string &key, void KafkaManager::PostMessage(const char *topic, const std::string &key,
const std::shared_ptr<std::string> PayLoad, bool WrapMessage) { const std::string & PayLoad, bool WrapMessage) {
if (KafkaEnabled_) { if (KafkaEnabled_) {
ProducerThr_.Produce(topic, key, WrapMessage ? WrapSystemId(PayLoad) : PayLoad); ProducerThr_.Produce(topic, key, WrapMessage ? WrapSystemId(PayLoad) : PayLoad);
} }
} }
void KafkaManager::Dispatch(const char *Topic, const std::string &Key, void KafkaManager::PostMessage(const char *topic, const std::string &key,
const std::shared_ptr<std::string> Payload) { const Poco::JSON::Object &Object, bool WrapMessage) {
Dispatcher_.Dispatch(Topic, Key, Payload);
}
[[nodiscard]] const std::shared_ptr<std::string> KafkaManager::WrapSystemId(const std::shared_ptr<std::string> PayLoad) {
*PayLoad = SystemInfoWrapper_ + *PayLoad + "}";
return PayLoad;
}
uint64_t KafkaManager::RegisterTopicWatcher(const std::string &Topic,
Types::TopicNotifyFunction &F) {
if (KafkaEnabled_) { if (KafkaEnabled_) {
return Dispatcher_.RegisterTopicWatcher(Topic, F); std::ostringstream ObjectStr;
} else { Object.stringify(ObjectStr);
return 0; ProducerThr_.Produce(topic, key, WrapMessage ? WrapSystemId(ObjectStr.str()) : ObjectStr.str());
} }
} }
void KafkaManager::UnregisterTopicWatcher(const std::string &Topic, uint64_t Id) { [[nodiscard]] std::string KafkaManager::WrapSystemId(const std::string & PayLoad) {
if (KafkaEnabled_) { return fmt::format( R"lit({{ "system" : {{ "id" : {},
Dispatcher_.UnregisterTopicWatcher(Topic, Id); "host" : "{}" }},
"payload" : {} }})lit", MicroServiceID(),
MicroServicePrivateEndPoint(), PayLoad ) ;
} }
}
void KafkaManager::Topics(std::vector<std::string> &T) { Dispatcher_.Topics(T); }
void KafkaManager::PartitionAssignment(const cppkafka::TopicPartitionList &partitions) { void KafkaManager::PartitionAssignment(const cppkafka::TopicPartitionList &partitions) {
poco_information( poco_information(

View File

@@ -6,7 +6,7 @@
#include "Poco/Notification.h" #include "Poco/Notification.h"
#include "Poco/NotificationQueue.h" #include "Poco/NotificationQueue.h"
#include "Poco/JSON/Object.h"
#include "framework/KafkaTopics.h" #include "framework/KafkaTopics.h"
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "framework/SubSystemServer.h" #include "framework/SubSystemServer.h"
@@ -18,17 +18,17 @@ namespace OpenWifi {
class KafkaMessage : public Poco::Notification { class KafkaMessage : public Poco::Notification {
public: public:
KafkaMessage(const char * Topic, const std::string &Key, const std::shared_ptr<std::string> Payload) KafkaMessage(const char * Topic, const std::string &Key, const std::string &Payload)
: Topic_(Topic), Key_(Key), Payload_(std::move(Payload)) {} : Topic_(Topic), Key_(Key), Payload_(Payload) {}
inline const char * Topic() { return Topic_; } inline const char * Topic() { return Topic_; }
inline const std::string &Key() { return Key_; } inline const std::string &Key() { return Key_; }
inline const std::string &Payload() { return *Payload_; } inline const std::string &Payload() { return Payload_; }
private: private:
const char *Topic_; const char *Topic_;
std::string Key_; std::string Key_;
std::shared_ptr<std::string> Payload_; std::string Payload_;
}; };
class KafkaProducer : public Poco::Runnable { class KafkaProducer : public Poco::Runnable {
@@ -36,10 +36,10 @@ namespace OpenWifi {
void run() override; void run() override;
void Start(); void Start();
void Stop(); void Stop();
void Produce(const char *Topic, const std::string &Key, const std::shared_ptr<std::string> Payload); void Produce(const char *Topic, const std::string &Key, const std::string & Payload);
private: private:
std::recursive_mutex Mutex_; std::mutex Mutex_;
Poco::Thread Worker_; Poco::Thread Worker_;
mutable std::atomic_bool Running_ = false; mutable std::atomic_bool Running_ = false;
Poco::NotificationQueue Queue_; Poco::NotificationQueue Queue_;
@@ -47,33 +47,22 @@ namespace OpenWifi {
class KafkaConsumer : public Poco::Runnable { class KafkaConsumer : public Poco::Runnable {
public: public:
void run() override;
void Start(); void Start();
void Stop(); void Stop();
private: private:
std::recursive_mutex Mutex_; std::mutex ConsumerMutex_;
Poco::Thread Worker_;
mutable std::atomic_bool Running_ = false;
};
class KafkaDispatcher : public Poco::Runnable {
public:
void Start();
void Stop();
auto RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F);
void UnregisterTopicWatcher(const std::string &Topic, int Id);
void Dispatch(const char *Topic, const std::string &Key, const std::shared_ptr<std::string> Payload);
void run() override;
void Topics(std::vector<std::string> &T);
private:
std::recursive_mutex Mutex_;
Types::NotifyTable Notifiers_; Types::NotifyTable Notifiers_;
Poco::Thread Worker_; Poco::Thread Worker_;
mutable std::atomic_bool Running_ = false; mutable std::atomic_bool Running_ = false;
uint64_t FunctionId_ = 1; uint64_t FunctionId_ = 1;
Poco::NotificationQueue Queue_; std::unique_ptr<cppkafka::ConsumerDispatcher> Dispatcher_;
std::set<std::string> Topics_;
void run() override;
friend class KafkaManager;
std::uint64_t RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F);
void UnregisterTopicWatcher(const std::string &Topic, int Id);
}; };
class KafkaManager : public SubSystemServer { class KafkaManager : public SubSystemServer {
@@ -92,20 +81,24 @@ namespace OpenWifi {
void Stop() override; void Stop() override;
void PostMessage(const char *topic, const std::string &key, void PostMessage(const char *topic, const std::string &key,
const std::shared_ptr<std::string> PayLoad, bool WrapMessage = true); const std::string &PayLoad, bool WrapMessage = true);
void Dispatch(const char *Topic, const std::string &Key, const std::shared_ptr<std::string> Payload); void PostMessage(const char *topic, const std::string &key,
[[nodiscard]] const std::shared_ptr<std::string> WrapSystemId(const std::shared_ptr<std::string> PayLoad); const Poco::JSON::Object &Object, bool WrapMessage = true);
[[nodiscard]] std::string WrapSystemId(const std::string & PayLoad);
[[nodiscard]] inline bool Enabled() const { return KafkaEnabled_; } [[nodiscard]] inline bool Enabled() const { return KafkaEnabled_; }
uint64_t RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F); inline std::uint64_t RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F) {
void UnregisterTopicWatcher(const std::string &Topic, uint64_t Id); return ConsumerThr_.RegisterTopicWatcher(Topic,F);
void Topics(std::vector<std::string> &T); }
inline void UnregisterTopicWatcher(const std::string &Topic, uint64_t Id) {
return ConsumerThr_.UnregisterTopicWatcher(Topic,Id);
}
private: private:
bool KafkaEnabled_ = false; bool KafkaEnabled_ = false;
std::string SystemInfoWrapper_; std::string SystemInfoWrapper_;
KafkaProducer ProducerThr_; KafkaProducer ProducerThr_;
KafkaConsumer ConsumerThr_; KafkaConsumer ConsumerThr_;
KafkaDispatcher Dispatcher_;
void PartitionAssignment(const cppkafka::TopicPartitionList &partitions); void PartitionAssignment(const cppkafka::TopicPartitionList &partitions);
void PartitionRevocation(const cppkafka::TopicPartitionList &partitions); void PartitionRevocation(const cppkafka::TopicPartitionList &partitions);

View File

@@ -129,6 +129,8 @@ namespace OpenWifi {
} }
} else { } else {
poco_error(logger(), "Bad bus message."); poco_error(logger(), "Bad bus message.");
std::ostringstream os;
Object->stringify(std::cout);
} }
auto i = Services_.begin(); auto i = Services_.begin();

View File

@@ -5,6 +5,8 @@
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/MicroService.h" #include "framework/MicroService.h"
#include "framework/ALBserver.h"
namespace OpenWifi { namespace OpenWifi {
const std::string &MicroServiceDataDirectory() { return MicroService::instance().DataDir(); } const std::string &MicroServiceDataDirectory() { return MicroService::instance().DataDir(); }
@@ -123,4 +125,8 @@ namespace OpenWifi {
return MicroService::instance().AllowExternalMicroServices(); return MicroService::instance().AllowExternalMicroServices();
} }
void MicroServiceALBCallback( std::string Callback()) {
return ALBHealthCheckServer()->RegisterExtendedHealthMessage(Callback);
}
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -53,4 +53,5 @@ namespace OpenWifi {
std::string MicroServiceGetPublicAPIEndPoint(); std::string MicroServiceGetPublicAPIEndPoint();
void MicroServiceDeleteOverrideConfiguration(); void MicroServiceDeleteOverrideConfiguration();
bool AllowExternalMicroServices(); bool AllowExternalMicroServices();
void MicroServiceALBCallback( std::string Callback());
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -28,6 +28,9 @@ namespace OpenWifi::Types {
typedef std::string UUID_t; typedef std::string UUID_t;
typedef std::vector<UUID_t> UUIDvec_t; typedef std::vector<UUID_t> UUIDvec_t;
typedef std::map<std::string, std::map<uint32_t, uint64_t>> Counted3DMapSII; typedef std::map<std::string, std::map<uint32_t, uint64_t>> Counted3DMapSII;
typedef std::vector<int64_t> IntList;
typedef std::vector<uint64_t> UIntList;
typedef std::vector<double> DoubleList;
struct MicroServiceMeta { struct MicroServiceMeta {
uint64_t Id = 0; uint64_t Id = 0;

View File

@@ -574,6 +574,36 @@ namespace OpenWifi {
Poco::JSON::Stringifier::stringify(Object, Answer); Poco::JSON::Stringifier::stringify(Object, Answer);
} }
inline void ReturnObject(const std::vector<std::string> &Strings) {
Poco::JSON::Array Arr;
for(const auto &String:Strings) {
Arr.add(String);
}
std::ostringstream os;
Arr.stringify(os);
return ReturnRawJSON(os.str());
}
template<class T> void ReturnObject(const std::vector<T> &Objects) {
Poco::JSON::Array Arr;
for(const auto &Object:Objects) {
Poco::JSON::Object O;
Object.to_json(O);
Arr.add(O);
}
std::ostringstream os;
Arr.stringify(os);
return ReturnRawJSON(os.str());
}
template<class T> void ReturnObject(const T &Object) {
Poco::JSON::Object O;
Object.to_json(O);
std::ostringstream os;
O.stringify(os);
return ReturnRawJSON(os.str());
}
inline void ReturnRawJSON(const std::string &json_doc) { inline void ReturnRawJSON(const std::string &json_doc) {
PrepareResponse(); PrepareResponse();
if (Request != nullptr) { if (Request != nullptr) {

View File

@@ -24,9 +24,10 @@ namespace OpenWifi {
Server, TransactionId, Internal) {} Server, TransactionId, Internal) {}
static auto PathName() { return std::list<std::string>{"/api/v1/system"}; } static auto PathName() { return std::list<std::string>{"/api/v1/system"}; }
inline void DoGet() { inline void DoGet() final {
std::string Arg; std::string Arg;
if (HasParameter("command", Arg) && Arg == "info") { if (HasParameter("command", Arg)) {
if (Arg == "info") {
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
Answer.set(RESTAPI::Protocol::VERSION, MicroServiceVersion()); Answer.set(RESTAPI::Protocol::VERSION, MicroServiceVersion());
Answer.set(RESTAPI::Protocol::UPTIME, MicroServiceUptimeTotalSeconds()); Answer.set(RESTAPI::Protocol::UPTIME, MicroServiceUptimeTotalSeconds());
@@ -64,11 +65,23 @@ namespace OpenWifi {
Answer.set("certificates", Certificates); Answer.set("certificates", Certificates);
return ReturnObject(Answer); return ReturnObject(Answer);
} }
if (GetBoolParameter("extraConfiguration")) { if (Arg == "extraConfiguration") {
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
MicroServiceGetExtraConfiguration(Answer); MicroServiceGetExtraConfiguration(Answer);
return ReturnObject(Answer); return ReturnObject(Answer);
} }
if (Arg == "resources") {
Poco::JSON::Object Answer;
Answer.set("numberOfFileDescriptors", Utils::get_open_fds());
std::uint64_t currRealMem, peakRealMem, currVirtMem, peakVirtMem;
Utils::getMemory(currRealMem, peakRealMem, currVirtMem, peakVirtMem);
Answer.set("currRealMem", currRealMem);
Answer.set("peakRealMem", peakRealMem);
Answer.set("currVirtMem", currVirtMem);
Answer.set("peakVirtMem", peakVirtMem);
return ReturnObject(Answer);
}
}
BadRequest(RESTAPI::Errors::InvalidCommand); BadRequest(RESTAPI::Errors::InvalidCommand);
} }

View File

@@ -14,8 +14,15 @@
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "framework/utils.h" #include "framework/utils.h"
#include <RESTObjects/RESTAPI_SecurityObjects.h>
namespace OpenWifi::RESTAPI_utils { namespace OpenWifi::RESTAPI_utils {
inline bool IsRootOrAdmin(const SecurityObjects::UserInfo &UI) {
return UI.userRole==SecurityObjects::ROOT ||
UI.userRole==SecurityObjects::ADMIN;
}
inline void EmbedDocument(const std::string &ObjName, Poco::JSON::Object &Obj, inline void EmbedDocument(const std::string &ObjName, Poco::JSON::Object &Obj,
const std::string &ObjStr) { const std::string &ObjStr) {
std::string D = ObjStr.empty() ? "{}" : ObjStr; std::string D = ObjStr.empty() ? "{}" : ObjStr;
@@ -95,6 +102,20 @@ namespace OpenWifi::RESTAPI_utils {
Obj.set(Field, A); Obj.set(Field, A);
} }
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::DoubleList &V) {
Poco::JSON::Array A;
for (const auto &i : V)
A.add(i);
Obj.set(Field, A);
}
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::IntList &V) {
Poco::JSON::Array A;
for (const auto &i : V)
A.add(i);
Obj.set(Field, A);
}
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::TagList &V) { inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::TagList &V) {
Poco::JSON::Array A; Poco::JSON::Array A;
for (const auto &i : V) for (const auto &i : V)
@@ -277,6 +298,28 @@ namespace OpenWifi::RESTAPI_utils {
} }
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
Types::DoubleList &Value) {
if (Obj->isArray(Field) && !Obj->isNull(Field)) {
Value.clear();
Poco::JSON::Array::Ptr A = Obj->getArray(Field);
for (const auto &i : *A) {
Value.push_back(i);
}
}
}
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
Types::IntList &Value) {
if (Obj->isArray(Field) && !Obj->isNull(Field)) {
Value.clear();
Poco::JSON::Array::Ptr A = Obj->getArray(Field);
for (const auto &i : *A) {
Value.push_back(i);
}
}
}
template <class T> template <class T>
void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
std::vector<T> &Value) { std::vector<T> &Value) {

View File

@@ -22,9 +22,8 @@ namespace OpenWifi {
class StorageClass : public SubSystemServer { class StorageClass : public SubSystemServer {
public: public:
StorageClass() noexcept : SubSystemServer("StorageClass", "STORAGE-SVR", "storage") {}
int Start() override { inline int Start() override {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
Logger().notice("Starting."); Logger().notice("Starting.");
@@ -40,17 +39,22 @@ namespace OpenWifi {
return 0; return 0;
} }
void Stop() override { Pool_->shutdown(); } inline void Stop() override { Pool_->shutdown(); }
DBType Type() const { return dbType_; }; DBType Type() const { return dbType_; };
StorageClass() noexcept : SubSystemServer("StorageClass", "STORAGE-SVR", "storage") {
}
private: private:
inline int Setup_SQLite(); inline int Setup_SQLite();
inline int Setup_MySQL(); inline int Setup_MySQL();
inline int Setup_PostgreSQL(); inline int Setup_PostgreSQL();
protected: protected:
std::unique_ptr<Poco::Data::SessionPool> Pool_; std::shared_ptr<Poco::Data::SessionPool> Pool_;
Poco::Data::SQLite::Connector SQLiteConn_; Poco::Data::SQLite::Connector SQLiteConn_;
Poco::Data::PostgreSQL::Connector PostgresConn_; Poco::Data::PostgreSQL::Connector PostgresConn_;
Poco::Data::MySQL::Connector MySQLConn_; Poco::Data::MySQL::Connector MySQLConn_;
@@ -81,7 +85,7 @@ namespace OpenWifi {
// Poco::Data::SessionPool(SQLiteConn_.name(), DBName, 8, // Poco::Data::SessionPool(SQLiteConn_.name(), DBName, 8,
// (int)NumSessions, // (int)NumSessions,
// (int)IdleTime)); // (int)IdleTime));
Pool_ = std::make_unique<Poco::Data::SessionPool>(SQLiteConn_.name(), DBName, 8, Pool_ = std::make_shared<Poco::Data::SessionPool>(SQLiteConn_.name(), DBName, 8,
(int)NumSessions, (int)IdleTime); (int)NumSessions, (int)IdleTime);
return 0; return 0;
} }
@@ -102,7 +106,7 @@ namespace OpenWifi {
";compress=true;auto-reconnect=true"; ";compress=true;auto-reconnect=true";
Poco::Data::MySQL::Connector::registerConnector(); Poco::Data::MySQL::Connector::registerConnector();
Pool_ = std::make_unique<Poco::Data::SessionPool>(MySQLConn_.name(), ConnectionStr, 8, Pool_ = std::make_shared<Poco::Data::SessionPool>(MySQLConn_.name(), ConnectionStr, 8,
NumSessions, IdleTime); NumSessions, IdleTime);
return 0; return 0;
@@ -126,7 +130,7 @@ namespace OpenWifi {
" connect_timeout=" + ConnectionTimeout; " connect_timeout=" + ConnectionTimeout;
Poco::Data::PostgreSQL::Connector::registerConnector(); Poco::Data::PostgreSQL::Connector::registerConnector();
Pool_ = std::make_unique<Poco::Data::SessionPool>(PostgresConn_.name(), ConnectionStr, 8, Pool_ = std::make_shared<Poco::Data::SessionPool>(PostgresConn_.name(), ConnectionStr, 8,
NumSessions, IdleTime); NumSessions, IdleTime);
return 0; return 0;

View File

@@ -37,6 +37,7 @@ namespace OpenWifi {
P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"; P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
P.dhUse2048Bits = true; P.dhUse2048Bits = true;
P.caLocation = cas_; P.caLocation = cas_;
// P.securityLevel =
auto Context = Poco::AutoPtr<Poco::Net::Context>( auto Context = Poco::AutoPtr<Poco::Net::Context>(
new Poco::Net::Context(Poco::Net::Context::TLS_SERVER_USE, P)); new Poco::Net::Context(Poco::Net::Context::TLS_SERVER_USE, P));
@@ -53,7 +54,6 @@ namespace OpenWifi {
Context->useCertificate(Cert); Context->useCertificate(Cert);
Context->addChainCertificate(Root); Context->addChainCertificate(Root);
Context->addCertificateAuthority(Root); Context->addCertificateAuthority(Root);
if (level_ == Poco::Net::Context::VERIFY_STRICT) { if (level_ == Poco::Net::Context::VERIFY_STRICT) {
@@ -76,18 +76,18 @@ namespace OpenWifi {
L.fatal(fmt::format("Wrong Certificate({}) for Key({})", cert_file_, key_file_)); L.fatal(fmt::format("Wrong Certificate({}) for Key({})", cert_file_, key_file_));
} }
SSL_CTX_set_verify(SSLCtx, SSL_VERIFY_PEER, nullptr); SSL_CTX_set_verify(SSLCtx, level_==Poco::Net::Context::VERIFY_NONE ? SSL_VERIFY_NONE : SSL_VERIFY_PEER, nullptr);
if (level_ == Poco::Net::Context::VERIFY_STRICT) { if (level_ == Poco::Net::Context::VERIFY_STRICT) {
SSL_CTX_set_client_CA_list(SSLCtx, SSL_load_client_CA_file(client_cas_.c_str())); SSL_CTX_set_client_CA_list(SSLCtx, SSL_load_client_CA_file(client_cas_.c_str()));
}
SSL_CTX_enable_ct(SSLCtx, SSL_CT_VALIDATION_STRICT); SSL_CTX_enable_ct(SSLCtx, SSL_CT_VALIDATION_STRICT);
}
SSL_CTX_dane_enable(SSLCtx); SSL_CTX_dane_enable(SSLCtx);
Context->enableSessionCache(); Context->enableSessionCache();
Context->setSessionCacheSize(0); Context->setSessionCacheSize(0);
Context->setSessionTimeout(60); Context->setSessionTimeout(60);
Context->enableExtendedCertificateVerification(true); Context->enableExtendedCertificateVerification( level_!= Poco::Net::Context::VERIFY_NONE );
Context->disableStatelessSessionResumption(); Context->disableStatelessSessionResumption();
} }

View File

@@ -40,6 +40,7 @@ namespace OpenWifi {
}; };
} }
#define DBGLINE std::cout << __LINE__ << ":" << __FILE__ << ", " << __func__ << std::endl;
namespace OpenWifi::RESTAPI::Errors { namespace OpenWifi::RESTAPI::Errors {
struct msg { struct msg {
uint64_t err_num; uint64_t err_num;
@@ -401,6 +402,23 @@ namespace OpenWifi::RESTAPI::Errors {
1171, "Command not supported on simulated device." 1171, "Command not supported on simulated device."
}; };
static const struct msg VenuesNameAlreadyExists {
1172, "The venue name already exists."
};
static const struct msg InvalidGlobalReachAccount {
1173, "Invalid Global Reach account information."
};
static const struct msg CannotCreateCSR {
1174, "Cannot create a CSR certificate."
};
static const struct msg DefFirmwareNameExists { 1175, "Firmware name already exists." };
static const struct msg NotAValidECKey { 1176, "Not a valid Signing Key." };
static const struct msg NotAValidRadiusPoolType { 1177, "Not a valid RADIUS pool type." };
static const struct msg SimulationDoesNotExist { static const struct msg SimulationDoesNotExist {
7000, "Simulation Instance ID does not exist." 7000, "Simulation Instance ID does not exist."
}; };

View File

@@ -3,10 +3,17 @@
// //
#include "Poco/Path.h" #include "Poco/Path.h"
#include "Poco/TemporaryFile.h"
#include "Poco/Crypto/ECKey.h"
#include "framework/AppServiceRegistry.h" #include "framework/AppServiceRegistry.h"
#include "framework/utils.h" #include "framework/utils.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
#include <algorithm>
namespace OpenWifi::Utils { namespace OpenWifi::Utils {
bool NormalizeMac(std::string &Mac) { bool NormalizeMac(std::string &Mac) {
@@ -27,6 +34,10 @@ namespace OpenWifi::Utils {
std::all_of(Serial.begin(), Serial.end(), [](auto i) { return std::isxdigit(i); })); std::all_of(Serial.begin(), Serial.end(), [](auto i) { return std::isxdigit(i); }));
} }
[[nodiscard]] bool ValidSerialNumbers(const std::vector<std::string> &numbers) {
return std::all_of(numbers.begin(),numbers.end(),[](auto &number) {return ValidSerialNumber(number);});
}
[[nodiscard]] bool ValidUUID(const std::string &UUID) { [[nodiscard]] bool ValidUUID(const std::string &UUID) {
if (UUID.size() > 36) if (UUID.size() > 36)
return false; return false;
@@ -128,6 +139,15 @@ namespace OpenWifi::Utils {
return std::regex_match(Hostname, HostNameRegex); return std::regex_match(Hostname, HostNameRegex);
} }
[[nodiscard]] bool ValidNumber(const std::string &number, bool isSigned)
{
static std::regex IntRegex("^-?[0-9]\\d*(\\.\\d+)?$");
if(!isSigned) {
IntRegex = "^[0-9]\\d*(\\.\\d+)?$";
}
return std::regex_match(number, IntRegex);
}
[[nodiscard]] std::string ToHex(const std::vector<unsigned char> &B) { [[nodiscard]] std::string ToHex(const std::vector<unsigned char> &B) {
std::string R; std::string R;
R.reserve(B.size() * 2); R.reserve(B.size() * 2);
@@ -595,4 +615,251 @@ namespace OpenWifi::Utils {
return DT.timestamp().epochTime(); return DT.timestamp().epochTime();
} }
static std::string FileToString(const std::string &Filename) {
std::ifstream ifs(Filename.c_str(),std::ios_base::in|std::ios_base::binary);
std::ostringstream os;
Poco::StreamCopier::copyStream(ifs,os);
return os.str();
}
bool CreateX509CSR(const CSRCreationParameters & Parameters, CSRCreationResults & Results) {
int ret = 0;
RSA *r = nullptr;
BIGNUM *bne = nullptr;
int nVersion = 0;
unsigned long e = RSA_F4;
X509_REQ *x509_req = nullptr;
X509_NAME *x509_name = nullptr;
EVP_PKEY *pKey = nullptr;
// RSA *tem = nullptr;
// BIO *bio_err = nullptr;
const char *szCountry = Parameters.Country.c_str();
const char *szProvince = Parameters.Province.c_str();
const char *szCity = Parameters.City.c_str();
const char *szOrganization = Parameters.Organization.c_str();
const char *szCommon = Parameters.CommonName.c_str();
Poco::TemporaryFile CsrPath, PubKey, PrivateKey;
std::string Result;
std::ifstream ifs;
std::ostringstream ss;
BIO *bp_public = nullptr,
*bp_private = nullptr,
*bp_csr = nullptr;
// 1. generate rsa key
bne = BN_new();
ret = BN_set_word(bne,e);
if(ret != 1){
goto free_all;
}
r = RSA_new();
ret = RSA_generate_key_ex(r, Parameters.bits, bne, nullptr);
if(ret != 1){
goto free_all;
}
bp_public = BIO_new_file(PubKey.path().c_str(), "w+");
ret = PEM_write_bio_RSAPublicKey(bp_public, r);
if(ret != 1) {
goto free_all;
}
bp_private = BIO_new_file(PrivateKey.path().c_str(), "w+");
ret = PEM_write_bio_RSAPrivateKey(bp_private, r, NULL, NULL, 0, NULL, NULL);
if(ret != 1) {
goto free_all;
}
// 2. set version of x509 req
x509_req = X509_REQ_new();
ret = X509_REQ_set_version(x509_req, nVersion);
if (ret != 1){
goto free_all;
}
// 3. set subject of x509 req
x509_name = X509_REQ_get_subject_name(x509_req);
ret = X509_NAME_add_entry_by_txt(x509_name,"C", MBSTRING_ASC, (const unsigned char*)szCountry, -1, -1, 0);
if (ret != 1){
goto free_all;
}
ret = X509_NAME_add_entry_by_txt(x509_name,"ST", MBSTRING_ASC, (const unsigned char*)szProvince, -1, -1, 0);
if (ret != 1){
goto free_all;
}
ret = X509_NAME_add_entry_by_txt(x509_name,"L", MBSTRING_ASC, (const unsigned char*)szCity, -1, -1, 0);
if (ret != 1){
goto free_all;
}
ret = X509_NAME_add_entry_by_txt(x509_name,"O", MBSTRING_ASC, (const unsigned char*)szOrganization, -1, -1, 0);
if (ret != 1){
goto free_all;
}
ret = X509_NAME_add_entry_by_txt(x509_name,"CN", MBSTRING_ASC, (const unsigned char*)szCommon, -1, -1, 0);
if (ret != 1){
goto free_all;
}
// 4. set public key of x509 req
pKey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pKey, r);
r = nullptr; // will be free rsa when EVP_PKEY_free(pKey)
ret = X509_REQ_set_pubkey(x509_req, pKey);
if (ret != 1){
goto free_all;
}
// 5. set sign key of x509 req
ret = X509_REQ_sign(x509_req, pKey, EVP_sha1()); // return x509_req->signature->length
if (ret <= 0){
goto free_all;
}
bp_csr = BIO_new_file(CsrPath.path().c_str(),"w");
ret = PEM_write_bio_X509_REQ(bp_csr, x509_req);
// 6. free
free_all:
X509_REQ_free(x509_req);
BIO_free_all(bp_csr);
BIO_free_all(bp_public);
BIO_free_all(bp_private);
EVP_PKEY_free(pKey);
BN_free(bne);
if(ret==1) {
Results.CSR = FileToString(CsrPath.path());
Results.PrivateKey = FileToString(PrivateKey.path());
Results.PublicKey = FileToString(PubKey.path());
}
return ret;
}
bool VerifyECKey(const std::string &key) {
try {
Poco::TemporaryFile F;
std::ofstream of(F.path().c_str(), std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);
of << key;
of.close();
auto Key = Poco::SharedPtr<Poco::Crypto::ECKey>(
new Poco::Crypto::ECKey("", F.path(),""));
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool VerifyRSAKey([[
maybe_unused]] const std::string &key) {
try {
Poco::TemporaryFile F;
std::ofstream of(F.path().c_str(), std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);
of << key;
of.close();
auto Key = Poco::SharedPtr<Poco::Crypto::RSAKey>(
new Poco::Crypto::RSAKey("", F.path(),""));
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool ValidX509Certificate([[
maybe_unused]] const std::string &Cert) {
try {
Poco::TemporaryFile F;
std::ofstream of(F.path().c_str(), std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);
of << Cert;
of.close();
auto Key = Poco::SharedPtr<Poco::Crypto::X509Certificate>(
new Poco::Crypto::X509Certificate(F.path()));
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool ValidX509Certificate([[
maybe_unused]] const std::vector<std::string> &Certs) {
auto F = [](const std::string &C) -> bool { return ValidX509Certificate(C); };
return std::all_of(Certs.begin(),Certs.end(), F);
}
std::string generateStrongPassword(int minLength, int maxLength, int numDigits, int minLowercase, int minSpecial, int minUppercase) {
// Define character sets for each category
const std::string lowercaseChars = "abcdefghijklmnopqrstuvwxyz";
const std::string uppercaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const std::string digitChars = "0123456789";
const std::string specialChars = "!@#$%^&*()_+[]{}|;:,.<>?";
// Check if parameters are valid
if (minLength < 1 || minLength > maxLength || minLowercase + minUppercase + numDigits + minSpecial > maxLength) {
return "Invalid parameters";
}
// Initialize random seed
std::random_device rd;
std::mt19937 g(rd());
// Initialize the password string
std::string password;
// Generate the required number of each character type
for (int i = 0; i < minLowercase; ++i) {
password += lowercaseChars[g() % lowercaseChars.length()];
}
for (int i = 0; i < minUppercase; ++i) {
password += uppercaseChars[g() % uppercaseChars.length()];
}
for (int i = 0; i < numDigits; ++i) {
password += digitChars[g() % digitChars.length()];
}
for (int i = 0; i < minSpecial; ++i) {
password += specialChars[g() % specialChars.length()];
}
// Calculate how many more characters are needed
int remainingLength = maxLength - (int)password.length();
// Generate random characters to fill the remaining length
for (int i = 0; i < remainingLength; ++i) {
int category = g() % 4; // Randomly select a category
if (category == 0) {
password += lowercaseChars[g() % lowercaseChars.length()];
} else if (category == 1) {
password += uppercaseChars[g() % uppercaseChars.length()];
} else if (category == 2) {
password += digitChars[g() % digitChars.length()];
} else {
password += specialChars[g() % specialChars.length()];
}
}
// Shuffle the password to randomize the character order
std::shuffle(password.begin(), password.end(),g);
return password;
}
} // namespace OpenWifi::Utils } // namespace OpenWifi::Utils

View File

@@ -13,6 +13,8 @@
#include <string> #include <string>
#include <thread> #include <thread>
#include <dirent.h>
#include "Poco/Base64Decoder.h" #include "Poco/Base64Decoder.h"
#include "Poco/Base64Encoder.h" #include "Poco/Base64Encoder.h"
#include "Poco/File.h" #include "Poco/File.h"
@@ -68,8 +70,10 @@ namespace OpenWifi::Utils {
}; };
[[nodiscard]] bool ValidSerialNumber(const std::string &Serial); [[nodiscard]] bool ValidSerialNumber(const std::string &Serial);
[[nodiscard]] bool ValidSerialNumbers(const std::vector<std::string> &Serial);
[[nodiscard]] bool ValidUUID(const std::string &UUID); [[nodiscard]] bool ValidUUID(const std::string &UUID);
[[nodiscard]] bool ValidHostname(const std::string &hostname); [[nodiscard]] bool ValidHostname(const std::string &hostname);
[[nodiscard]] bool ValidNumber(const std::string &number, bool isSigned);
template <typename... Args> std::string ComputeHash(Args &&...args) { template <typename... Args> std::string ComputeHash(Args &&...args) {
Poco::SHA2Engine E; Poco::SHA2Engine E;
@@ -180,4 +184,84 @@ namespace OpenWifi::Utils {
return false; return false;
} }
static inline std::uint64_t GetValue(FILE *file) {
unsigned long v=0;
char factor[32];
if(fscanf(file, " %lu %31s", &v, factor)==2) {
switch (factor[0]) {
case 'k':
return v * 1000;
case 'M':
return v * 1000000;
case 'G':
return v * 1000000000;
}
}
return v;
}
inline bool getMemory(
std::uint64_t &currRealMem, std::uint64_t &peakRealMem,
std::uint64_t &currVirtMem, std::uint64_t &peakVirtMem) {
// stores each word in status file
char buffer[1024] = "";
currRealMem = peakRealMem = currVirtMem = peakVirtMem = 0;
// linux file contains this-process info
FILE * file = std::fopen("/proc/self/status", "r");
if (file == nullptr) {
return false;
}
// read the entire file, recording mems in kB
while (fscanf(file, " %1023s", buffer) == 1) {
if (strcmp(buffer, "VmRSS:") == 0) {
currRealMem= GetValue(file);
} else if (strcmp(buffer, "VmHWM:") == 0) {
peakRealMem= GetValue(file);
} else if (strcmp(buffer, "VmSize:") == 0) {
currVirtMem= GetValue(file);
} else if (strcmp(buffer, "VmPeak:") == 0) {
peakVirtMem= GetValue(file);
}
}
fclose(file);
return true;
}
inline int get_open_fds() {
DIR *dp = opendir("/proc/self/fd");
struct dirent *de;
int count = -3; // '.', '..', dp
if (dp == nullptr)
return -1;
while ((de = readdir(dp)) != nullptr)
count++;
(void)closedir(dp);
return count;
}
struct CSRCreationParameters {
std::string Country, Province, City,
Organization, CommonName;
int bits=2048;
};
struct CSRCreationResults {
std::string CSR, PublicKey, PrivateKey;
};
bool CreateX509CSR(const CSRCreationParameters & Parameters, CSRCreationResults & Results);
std::string generateStrongPassword(int minLength, int maxLength, int numDigits, int minLowercase, int minSpecial, int minUppercase);
bool VerifyECKey(const std::string &key);
bool VerifyRSAKey(const std::string &key);
bool ValidX509Certificate(const std::string &Cert);
bool ValidX509Certificate(const std::vector<std::string> &Certs);
} // namespace OpenWifi::Utils } // namespace OpenWifi::Utils