Compare commits

...

29 Commits

Author SHA1 Message Date
TIP Automation User
511c53a9c0 Chg: update image tag in helm values to v2.11.0-RC2 2023-09-26 14:44:41 +00:00
Stephane Bourque
db33693157 Merge pull request #105 from Telecominfraproject/main
Merge latest to main
2023-09-24 11:56:51 -07:00
stephb9959
54d6565411 https://telecominfraproject.atlassian.net/browse/WIFI-12954
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-24 11:05:22 -07:00
stephb9959
5052a818ff https://telecominfraproject.atlassian.net/browse/WIFI-12954
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-23 15:27:40 -07:00
stephb9959
5e1f3e0e31 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-19 22:00:19 -07:00
stephb9959
c0740a9760 https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-13 13:15:48 -07:00
stephb9959
88ebeead8c https://telecominfraproject.atlassian.net/browse/WIFI-7831
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-13 12:17:44 -07:00
stephb9959
41c155c332 https://telecominfraproject.atlassian.net/browse/WIFI-12930
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 10:58:51 -07:00
stephb9959
aaf6c933b5 https://telecominfraproject.atlassian.net/browse/WIFI-12930
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 10:54:20 -07:00
stephb9959
5e58f7ef37 https://telecominfraproject.atlassian.net/browse/WIFI-12930
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 10:38:13 -07:00
stephb9959
9fdd0019c1 https://telecominfraproject.atlassian.net/browse/WIFI-12930
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 09:00:04 -07:00
stephb9959
f94e4b3aed https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 08:49:14 -07:00
stephb9959
b2b183f95c https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 08:45:22 -07:00
stephb9959
2cfa5040dc https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 08:34:19 -07:00
stephb9959
3112e2ad36 https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 08:32:21 -07:00
stephb9959
0e45f3700b https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 08:28:51 -07:00
stephb9959
78d9e508fc https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 08:27:26 -07:00
stephb9959
81ff75f1cc https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 08:23:04 -07:00
stephb9959
ab276bb474 https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 08:13:48 -07:00
stephb9959
2a8f09cb46 https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 08:11:07 -07:00
stephb9959
239dcffc98 https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-06 08:09:47 -07:00
stephb9959
5fb32934fa https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-01 09:26:25 -07:00
stephb9959
38010d4628 https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-09-01 09:09:41 -07:00
TIP Automation User
d966f53423 Chg: update image tag in helm values to v2.11.0-RC1 2023-09-01 16:08:47 +00:00
stephb9959
669f7f3433 https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-08-03 22:28:28 -07:00
stephb9959
3576d5516f https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-08-03 11:08:07 -07:00
stephb9959
0781f15bae https://telecominfraproject.atlassian.net/browse/WIFI-12868
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-08-03 10:30:30 -07:00
stephb9959
e87f4d6476 https://telecominfraproject.atlassian.net/browse/WIFI-12738
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-07-10 12:59:58 -07:00
stephb9959
dd7d5e8ab6 https://telecominfraproject.atlassian.net/browse/WIFI-12525
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-07-03 08:26:09 -07:00
30 changed files with 1188 additions and 537 deletions

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
project(owsec VERSION 2.10.0) project(owsec VERSION 2.11.0)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
@@ -42,7 +42,7 @@ if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}") string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}")
endif() endif()
add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT) add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT -DBOOST_NO_CXX98_FUNCTION_BASE=1)
set(BUILD_SHARED_LIBS 1) set(BUILD_SHARED_LIBS 1)

2
build
View File

@@ -1 +1 @@
21 9

View File

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

View File

@@ -565,12 +565,6 @@ components:
- $ref: '#/components/schemas/StringList' - $ref: '#/components/schemas/StringList'
- $ref: '#/components/schemas/TagValuePairList' - $ref: '#/components/schemas/TagValuePairList'
SystemCommandResults:
type: object
oneOf:
- $ref: '#/components/schemas/StringList'
- $ref: '#/components/schemas/TagValuePairList'
SystemInfoResults: SystemInfoResults:
type: object type: object
properties: properties:
@@ -599,6 +593,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'
ProfileAction: ProfileAction:
type: object type: object
properties: properties:
@@ -1967,16 +1988,12 @@ paths:
type: string type: string
enum: enum:
- info - info
- extraConfiguration
- resources
required: true required: true
responses: responses:
200: 200:
description: Successful 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

@@ -28,10 +28,13 @@ namespace OpenWifi {
poco_information(Logger(), "Stopped..."); poco_information(Logger(), "Stopped...");
} }
void ActionLinkManager::run() {
void ActionLinkManager::run() {
Running_ = true; Running_ = true;
Utils::SetThreadName("action-mgr"); Utils::SetThreadName("action-mgr");
Poco::Thread::trySleep(10000);
while (Running_) { while (Running_) {
Poco::Thread::trySleep(2000); Poco::Thread::trySleep(2000);
if (!Running_) if (!Running_)
@@ -98,10 +101,8 @@ namespace OpenWifi {
} break; } break;
case OpenWifi::SecurityObjects::LinkActions::SUB_FORGOT_PASSWORD: { case OpenWifi::SecurityObjects::LinkActions::SUB_FORGOT_PASSWORD: {
auto Signup = Poco::StringTokenizer(UInfo.signingUp, ":");
if (AuthService()->SendEmailToSubUser(i.id, UInfo.email, if (AuthService()->SendEmailToSubUser(i.id, UInfo.email,
MessagingTemplates::SUB_FORGOT_PASSWORD, MessagingTemplates::SUB_FORGOT_PASSWORD,"")) {
Signup.count() == 1 ? "" : Signup[0])) {
poco_information( poco_information(
Logger(), Logger(),
fmt::format("Send subscriber password reset link to {}", UInfo.email)); fmt::format("Send subscriber password reset link to {}", UInfo.email));
@@ -110,10 +111,8 @@ namespace OpenWifi {
} break; } break;
case OpenWifi::SecurityObjects::LinkActions::SUB_VERIFY_EMAIL: { case OpenWifi::SecurityObjects::LinkActions::SUB_VERIFY_EMAIL: {
auto Signup = Poco::StringTokenizer(UInfo.signingUp, ":");
if (AuthService()->SendEmailToSubUser( if (AuthService()->SendEmailToSubUser(
i.id, UInfo.email, MessagingTemplates::SUB_EMAIL_VERIFICATION, i.id, UInfo.email, MessagingTemplates::SUB_EMAIL_VERIFICATION,"")) {
Signup.count() == 1 ? "" : Signup[0])) {
poco_information( poco_information(
Logger(), fmt::format("Send subscriber email verification link to {}", Logger(), fmt::format("Send subscriber email verification link to {}",
UInfo.email)); UInfo.email));

View File

@@ -342,10 +342,8 @@ namespace OpenWifi {
Obj.set("event", "remove-token"); Obj.set("event", "remove-token");
Obj.set("id", MicroServiceID()); Obj.set("id", MicroServiceID());
Obj.set("token", token); Obj.set("token", token);
std::stringstream ResultText;
Poco::JSON::Stringifier::stringify(Obj, ResultText);
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,
MicroServicePrivateEndPoint(), std::make_shared<std::string>(ResultText.str()), false); MicroServicePrivateEndPoint(), Obj, false);
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
@@ -800,7 +798,6 @@ namespace OpenWifi {
if (StorageService()->SubDB().GetUserByEmail(Email, UInfo)) { if (StorageService()->SubDB().GetUserByEmail(Email, UInfo)) {
switch (Reason) { switch (Reason) {
case MessagingTemplates::SUB_FORGOT_PASSWORD: { case MessagingTemplates::SUB_FORGOT_PASSWORD: {
MessageAttributes Attrs; MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = UInfo.email; Attrs[RECIPIENT_EMAIL] = UInfo.email;

View File

@@ -37,9 +37,9 @@ namespace OpenWifi {
instance_ = instance_ =
new Daemon(vDAEMON_PROPERTIES_FILENAME, vDAEMON_ROOT_ENV_VAR, new Daemon(vDAEMON_PROPERTIES_FILENAME, vDAEMON_ROOT_ENV_VAR,
vDAEMON_CONFIG_ENV_VAR, vDAEMON_APP_NAME, vDAEMON_BUS_TIMER, vDAEMON_CONFIG_ENV_VAR, vDAEMON_APP_NAME, vDAEMON_BUS_TIMER,
SubSystemVec{StorageService(), SMSSender(), ActionLinkManager(), SubSystemVec{StorageService(), SMSSender(), AuthService(), ActionLinkManager(),
SMTPMailerService(), RESTAPI_RateLimiter(), TotpCache(), SMTPMailerService(), RESTAPI_RateLimiter(), TotpCache(),
AuthService(), UI_WebSocketClientServer(), SecretStore()}); UI_WebSocketClientServer(), SecretStore()});
} }
return instance_; return instance_;
} }

View File

@@ -37,11 +37,11 @@ namespace OpenWifi {
if (Action == "password_reset") if (Action == "password_reset")
return RequestResetPassword(Link); return RequestResetPassword(Link);
else if (Action == "sub_password_reset") else if (Action == "sub_password_reset")
return RequestSubResetPassword(Link); return RequestResetPassword(Link);
else if (Action == "email_verification") else if (Action == "email_verification")
return DoEmailVerification(Link); return DoEmailVerification(Link);
else if (Action == "sub_email_verification") else if (Action == "sub_email_verification")
return DoSubEmailVerification(Link); return DoEmailVerification(Link);
else if (Action == "signup_verification") else if (Action == "signup_verification")
return DoNewSubVerification(Link); return DoNewSubVerification(Link);
else else
@@ -101,7 +101,6 @@ namespace OpenWifi {
} }
void RESTAPI_action_links::CompleteResetPassword() { void RESTAPI_action_links::CompleteResetPassword() {
// form has been posted...
RESTAPI_PartHandler PartHandler; RESTAPI_PartHandler PartHandler;
Poco::Net::HTMLForm Form(*Request, Request->stream(), PartHandler); Poco::Net::HTMLForm Form(*Request, Request->stream(), PartHandler);
if (!Form.empty()) { if (!Form.empty()) {

View File

@@ -1,4 +1,4 @@
// //
// Created by stephane bourque on 2021-10-23. // Created by stephane bourque on 2021-10-23.
// //

View File

@@ -34,7 +34,9 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SMSCouldNotValidate); return BadRequest(RESTAPI::Errors::SMSCouldNotValidate);
} }
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT && if(Internal_) {
poco_information(Logger(),fmt::format("Internal SMS request: TID={}", TransactionId_));
} else if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
UserInfo_.userinfo.userRole != SecurityObjects::PARTNER && UserInfo_.userinfo.userRole != SecurityObjects::PARTNER &&
UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) { UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED); return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);

View File

@@ -185,7 +185,7 @@ namespace OpenWifi {
} }
} }
if (GetBoolParameter("forgotPassword")) { if (GetBoolParameter("forgotPassword") || GetBoolParameter("resetPassword")) {
Existing.changePassword = true; Existing.changePassword = true;
Logger_.information(fmt::format("FORGOTTEN-PASSWORD({}): Request for {}", Logger_.information(fmt::format("FORGOTTEN-PASSWORD({}): Request for {}",
Request->clientAddress().toString(), Existing.email)); Request->clientAddress().toString(), Existing.email));

View File

@@ -33,7 +33,7 @@ namespace OpenWifi {
return NotFound(); return NotFound();
} }
if (!ACLProcessor::Can(UserInfo_.userinfo, UInfo, ACLProcessor::READ)) { if (!Internal_ && !ACLProcessor::Can(UserInfo_.userinfo, UInfo, ACLProcessor::READ)) {
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED); return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
} }

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,7 +2065,14 @@ static std::string DefaultUCentralSchema = R"foo(
"$ref": "#/$defs/interface.ssid.rate-limit" "$ref": "#/$defs/interface.ssid.rate-limit"
}, },
"roaming": { "roaming": {
"$ref": "#/$defs/interface.ssid.roaming" "anyOf": [
{
"$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;
try {
std::vector<cppkafka::Message> MsgVec = Dispatcher_ = std::make_unique<cppkafka::ConsumerDispatcher>(Consumer);
Consumer.poll_batch(BatchSize, std::chrono::milliseconds(100));
for (auto const &Msg : MsgVec) { Dispatcher_->run(
if (!Msg) // Callback executed whenever a new message is consumed
continue; [&](cppkafka::Message msg) {
if (Msg.get_error()) { // Print the key (if any)
if (!Msg.is_eof()) { std::lock_guard G(ConsumerMutex_);
poco_error(Logger_, auto It = Notifiers_.find(msg.get_topic());
fmt::format("Error: {}", Msg.get_error().to_string())); if (It != Notifiers_.end()) {
const auto &FL = It->second;
for (const auto &[CallbackFunc, _] : FL) {
try {
CallbackFunc(msg.get_key(), msg.get_payload());
} catch(const Poco::Exception &E) {
} catch(...) {
} }
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) { Consumer.commit(msg);
poco_warning(Logger_, },
fmt::format("Caught a Kafka exception (consumer): {}", E.what())); // Whenever there's an error (other than the EOF soft error)
} catch (const Poco::Exception &E) { [&Logger_](cppkafka::Error error) {
Logger_.log(E); poco_warning(Logger_,fmt::format("Error: {}", error.to_string()));
} catch (...) { },
poco_error(Logger_, "std::exception"); // 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,39 +291,28 @@ 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(
Logger(), fmt::format("Partition assigned: {}...", partitions.front().get_partition())); Logger(), fmt::format("Partition assigned: {}...", partitions.front().get_partition()));

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_; Types::NotifyTable Notifiers_;
Poco::Thread Worker_;
mutable std::atomic_bool Running_ = false; mutable std::atomic_bool Running_ = false;
}; uint64_t FunctionId_ = 1;
std::unique_ptr<cppkafka::ConsumerDispatcher> Dispatcher_;
std::set<std::string> Topics_;
class KafkaDispatcher : public Poco::Runnable { void run() override;
public: friend class KafkaManager;
void Start(); std::uint64_t RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F);
void Stop();
auto RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F);
void UnregisterTopicWatcher(const std::string &Topic, int Id); 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_;
Poco::Thread Worker_;
mutable std::atomic_bool Running_ = false;
uint64_t FunctionId_ = 1;
Poco::NotificationQueue Queue_;
}; };
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,7 +574,37 @@ namespace OpenWifi {
Poco::JSON::Stringifier::stringify(Object, Answer); Poco::JSON::Stringifier::stringify(Object, Answer);
} }
inline void ReturnRawJSON(const std::string &json_doc) { 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) {
PrepareResponse(); PrepareResponse();
if (Request != nullptr) { if (Request != nullptr) {
// can we compress ??? // can we compress ???

View File

@@ -24,50 +24,63 @@ 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)) {
Poco::JSON::Object Answer; if (Arg == "info") {
Answer.set(RESTAPI::Protocol::VERSION, MicroServiceVersion()); Poco::JSON::Object Answer;
Answer.set(RESTAPI::Protocol::UPTIME, MicroServiceUptimeTotalSeconds()); Answer.set(RESTAPI::Protocol::VERSION, MicroServiceVersion());
Answer.set(RESTAPI::Protocol::START, MicroServiceStartTimeEpochTime()); Answer.set(RESTAPI::Protocol::UPTIME, MicroServiceUptimeTotalSeconds());
Answer.set(RESTAPI::Protocol::OS, Poco::Environment::osName()); Answer.set(RESTAPI::Protocol::START, MicroServiceStartTimeEpochTime());
Answer.set(RESTAPI::Protocol::PROCESSORS, Poco::Environment::processorCount()); Answer.set(RESTAPI::Protocol::OS, Poco::Environment::osName());
Answer.set(RESTAPI::Protocol::HOSTNAME, Poco::Environment::nodeName()); Answer.set(RESTAPI::Protocol::PROCESSORS, Poco::Environment::processorCount());
Answer.set(RESTAPI::Protocol::UI, MicroServiceGetUIURI()); Answer.set(RESTAPI::Protocol::HOSTNAME, Poco::Environment::nodeName());
Answer.set(RESTAPI::Protocol::UI, MicroServiceGetUIURI());
Poco::JSON::Array Certificates; Poco::JSON::Array Certificates;
auto SubSystems = MicroServiceGetFullSubSystems(); auto SubSystems = MicroServiceGetFullSubSystems();
std::set<std::string> CertNames; std::set<std::string> CertNames;
for (const auto &i : SubSystems) { for (const auto &i : SubSystems) {
auto Hosts = i->HostSize(); auto Hosts = i->HostSize();
for (uint64_t j = 0; j < Hosts; ++j) { for (uint64_t j = 0; j < Hosts; ++j) {
auto CertFileName = i->Host(j).CertFile(); auto CertFileName = i->Host(j).CertFile();
if (!CertFileName.empty()) { if (!CertFileName.empty()) {
Poco::File F1(CertFileName); Poco::File F1(CertFileName);
if (F1.exists()) { if (F1.exists()) {
auto InsertResult = CertNames.insert(CertFileName); auto InsertResult = CertNames.insert(CertFileName);
if (InsertResult.second) { if (InsertResult.second) {
Poco::JSON::Object Inner; Poco::JSON::Object Inner;
Poco::Path F(CertFileName); Poco::Path F(CertFileName);
Inner.set("filename", F.getFileName()); Inner.set("filename", F.getFileName());
Poco::Crypto::X509Certificate C(CertFileName); Poco::Crypto::X509Certificate C(CertFileName);
auto ExpiresOn = C.expiresOn(); auto ExpiresOn = C.expiresOn();
Inner.set("expiresOn", ExpiresOn.timestamp().epochTime()); Inner.set("expiresOn", ExpiresOn.timestamp().epochTime());
Certificates.add(Inner); Certificates.add(Inner);
}
} }
} }
} }
} }
Answer.set("certificates", Certificates);
return ReturnObject(Answer);
}
if (Arg == "extraConfiguration") {
Poco::JSON::Object Answer;
MicroServiceGetExtraConfiguration(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);
} }
Answer.set("certificates", Certificates);
return ReturnObject(Answer);
}
if (GetBoolParameter("extraConfiguration")) {
Poco::JSON::Object Answer;
MicroServiceGetExtraConfiguration(Answer);
return ReturnObject(Answer);
} }
BadRequest(RESTAPI::Errors::InvalidCommand); BadRequest(RESTAPI::Errors::InvalidCommand);
} }

View File

@@ -102,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)
@@ -284,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:
std::unique_ptr<Poco::Data::SessionPool> Pool_; protected:
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) {
@@ -132,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);
@@ -599,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"
@@ -71,6 +73,7 @@ namespace OpenWifi::Utils {
[[nodiscard]] bool ValidSerialNumbers(const std::vector<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;
@@ -181,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