Merge branch 'development-v6' into tweak/limit_history_clients
This commit is contained in:
commit
58637597bf
|
@ -336,14 +336,18 @@ static int get_session_object(struct ftl_conn *api, cJSON *json, const int user_
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void delete_session(const int user_id)
|
||||
static bool delete_session(const int user_id)
|
||||
{
|
||||
// Skip if nothing to be done here
|
||||
if(user_id < 0 || user_id >= max_sessions)
|
||||
return;
|
||||
return false;
|
||||
|
||||
const bool was_valid = auth_data[user_id].used;
|
||||
|
||||
// Zero out this session (also sets valid to false == 0)
|
||||
memset(&auth_data[user_id], 0, sizeof(auth_data[user_id]));
|
||||
|
||||
return was_valid;
|
||||
}
|
||||
|
||||
void delete_all_sessions(void)
|
||||
|
@ -354,24 +358,6 @@ void delete_all_sessions(void)
|
|||
|
||||
static int send_api_auth_status(struct ftl_conn *api, const int user_id, const time_t now)
|
||||
{
|
||||
if(user_id == API_AUTH_LOCALHOST)
|
||||
{
|
||||
log_debug(DEBUG_API, "API Auth status: OK (localhost does not need auth)");
|
||||
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
get_session_object(api, json, user_id, now);
|
||||
JSON_SEND_OBJECT(json);
|
||||
}
|
||||
|
||||
if(user_id == API_AUTH_EMPTYPASS)
|
||||
{
|
||||
log_debug(DEBUG_API, "API Auth status: OK (empty password)");
|
||||
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
get_session_object(api, json, user_id, now);
|
||||
JSON_SEND_OBJECT(json);
|
||||
}
|
||||
|
||||
if(user_id > API_AUTH_UNAUTHORIZED && (api->method == HTTP_GET || api->method == HTTP_POST))
|
||||
{
|
||||
log_debug(DEBUG_API, "API Auth status: OK");
|
||||
|
@ -388,17 +374,45 @@ static int send_api_auth_status(struct ftl_conn *api, const int user_id, const t
|
|||
get_session_object(api, json, user_id, now);
|
||||
JSON_SEND_OBJECT(json);
|
||||
}
|
||||
else if(user_id > API_AUTH_UNAUTHORIZED && api->method == HTTP_DELETE)
|
||||
else if(api->method == HTTP_DELETE)
|
||||
{
|
||||
log_debug(DEBUG_API, "API Auth status: Logout, asking to delete cookie");
|
||||
if(user_id > API_AUTH_UNAUTHORIZED)
|
||||
{
|
||||
log_debug(DEBUG_API, "API Auth status: Logout, asking to delete cookie");
|
||||
|
||||
// Revoke client authentication. This slot can be used by a new client afterwards.
|
||||
delete_session(user_id);
|
||||
strncpy(pi_hole_extra_headers, FTL_DELETE_COOKIE, sizeof(pi_hole_extra_headers));
|
||||
|
||||
// Revoke client authentication. This slot can be used by a new client afterwards.
|
||||
const int code = delete_session(user_id) ? 204 : 404;
|
||||
|
||||
// Send empty reply with appropriate HTTP status code
|
||||
send_http_code(api, "application/json; charset=utf-8", code, "");
|
||||
return code;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_debug(DEBUG_API, "API Auth status: Logout, but not authenticated");
|
||||
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
get_session_object(api, json, user_id, now);
|
||||
JSON_SEND_OBJECT_CODE(json, 401); // 401 Unauthorized
|
||||
}
|
||||
}
|
||||
else if(user_id == API_AUTH_LOCALHOST)
|
||||
{
|
||||
log_debug(DEBUG_API, "API Auth status: OK (localhost does not need auth)");
|
||||
|
||||
strncpy(pi_hole_extra_headers, FTL_DELETE_COOKIE, sizeof(pi_hole_extra_headers));
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
get_session_object(api, json, user_id, now);
|
||||
JSON_SEND_OBJECT_CODE(json, 410); // 410 Gone
|
||||
JSON_SEND_OBJECT(json);
|
||||
}
|
||||
else if(user_id == API_AUTH_EMPTYPASS)
|
||||
{
|
||||
log_debug(DEBUG_API, "API Auth status: OK (empty password)");
|
||||
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
get_session_object(api, json, user_id, now);
|
||||
JSON_SEND_OBJECT(json);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -563,7 +577,7 @@ int api_auth(struct ftl_conn *api)
|
|||
{
|
||||
// Expired slow, mark as unused
|
||||
if(auth_data[i].used &&
|
||||
auth_data[i].valid_until < now)
|
||||
auth_data[i].valid_until < now)
|
||||
{
|
||||
log_debug(DEBUG_API, "API: Session of client %u (%s) expired, freeing...",
|
||||
i, auth_data[i].remote_addr);
|
||||
|
@ -634,6 +648,11 @@ int api_auth(struct ftl_conn *api)
|
|||
"Rate-limiting login attempts",
|
||||
NULL);
|
||||
}
|
||||
else if(result == NO_PASSWORD_SET)
|
||||
{
|
||||
// No password set
|
||||
log_debug(DEBUG_API, "API: Trying to auth with password but none set: '%s'", password);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_debug(DEBUG_API, "API: Password incorrect: '%s'", password);
|
||||
|
@ -667,9 +686,9 @@ int api_auth_session_delete(struct ftl_conn *api)
|
|||
return send_json_error(api, 400, "bad_request", "Session ID not in use", NULL);
|
||||
|
||||
// Delete session
|
||||
delete_session(uid);
|
||||
const int code = delete_session(uid) ? 204 : 404;
|
||||
|
||||
// Send empty reply with code 204 No Content
|
||||
send_http_code(api, "application/json; charset=utf-8", 204, "");
|
||||
return 204;
|
||||
// Send empty reply with appropriate HTTP status code
|
||||
send_http_code(api, "application/json; charset=utf-8", code, "");
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -294,7 +294,7 @@ static const char *getJSONvalue(struct conf_item *conf_item, cJSON *elem, struct
|
|||
}
|
||||
|
||||
if(!set_and_check_password(conf_item, elem->valuestring))
|
||||
return "Failed to create password hash (verification failed), password remains unchanged";
|
||||
return "password hash verification failed";
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -904,7 +904,7 @@ static int api_config_put_delete(struct ftl_conn *api)
|
|||
key, true);
|
||||
}
|
||||
|
||||
// Check if this entry does already exist in the array
|
||||
// Check if this entry exists in the array
|
||||
int idx = 0;
|
||||
for(; idx < cJSON_GetArraySize(new_item->v.json); idx++)
|
||||
{
|
||||
|
@ -938,13 +938,12 @@ static int api_config_put_delete(struct ftl_conn *api)
|
|||
if(found)
|
||||
{
|
||||
// Remove item from array
|
||||
found = true;
|
||||
cJSON_DeleteItemFromArray(new_item->v.json, idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Item not found
|
||||
message = "Item not found";
|
||||
hint = "Can only delete existing items";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -964,13 +963,16 @@ static int api_config_put_delete(struct ftl_conn *api)
|
|||
// Release allocated memory
|
||||
free_config_path(requested_path);
|
||||
|
||||
// Error 404 if not found
|
||||
if(!found || message != NULL)
|
||||
// Error 404 if config element not found
|
||||
if(!found)
|
||||
{
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
JSON_SEND_OBJECT_CODE(json, 404);
|
||||
}
|
||||
|
||||
// Error 400 if unique item already present
|
||||
if(message != NULL)
|
||||
{
|
||||
// For any other error, a more specific message will have been added
|
||||
// above
|
||||
if(!message)
|
||||
message = "No item specified";
|
||||
return send_json_error(api, 400,
|
||||
"bad_request",
|
||||
message,
|
||||
|
|
|
@ -85,16 +85,18 @@ int api_dhcp_leases_DELETE(struct ftl_conn *api)
|
|||
// Send empty reply with code 204 No Content
|
||||
return send_json_error(api,
|
||||
400,
|
||||
"bad_request",
|
||||
"bad_request",
|
||||
"The provided IPv4 address is invalid",
|
||||
api->item);
|
||||
api->item);
|
||||
}
|
||||
|
||||
// Delete lease
|
||||
log_debug(DEBUG_API, "Deleting DHCP lease for address %s", api->item);
|
||||
FTL_unlink_DHCP_lease(api->item);
|
||||
const bool found = FTL_unlink_DHCP_lease(api->item);
|
||||
|
||||
// Send empty reply with code 204 No Content
|
||||
// Send empty reply with codes:
|
||||
// - 204 No Content (if a lease was deleted)
|
||||
// - 404 Not Found (if no lease was found)
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
JSON_SEND_OBJECT_CODE(json, 204);
|
||||
JSON_SEND_OBJECT_CODE(json, found ? 204 : 404);
|
||||
}
|
|
@ -118,21 +118,27 @@ components:
|
|||
- Authentication
|
||||
operationId: "delete_groups"
|
||||
description: |
|
||||
A logout attempt without a valid session will result in a `401 Unauthorized` error.
|
||||
This endpoint can be used to delete the current session. It will
|
||||
invalidate the session token and the CSRF token. The session can be
|
||||
extended before its expiration by performing any authenticated action.
|
||||
By default, the session lasts for 5 minutes. It can be invalidated by
|
||||
either logging out or deleting the session. Additionally, the session
|
||||
becomes invalid when the password is altered or a new application
|
||||
password is created.
|
||||
|
||||
A session that was not created due to a login cannot be deleted (e.g., empty API password).
|
||||
You can also delete a session by its ID using the `DELETE /auth/session/{id}` endpoint.
|
||||
|
||||
Note that you cannot delete the current session if you have not
|
||||
authenticated (e.g., no password has been set on your Pi-hole).
|
||||
responses:
|
||||
'200':
|
||||
description: OK (session not deletable)
|
||||
'204':
|
||||
description: No Content (deleted)
|
||||
'404':
|
||||
description: Not Found (no session active)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: 'auth.yaml#/components/schemas/session'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
examples:
|
||||
no_login_required:
|
||||
$ref: 'auth.yaml#/components/examples/no_login_required'
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'401':
|
||||
description: Unauthorized
|
||||
content:
|
||||
|
@ -141,17 +147,6 @@ components:
|
|||
allOf:
|
||||
- $ref: 'common.yaml#/components/errors/unauthorized'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
'410':
|
||||
description: Gone
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: 'auth.yaml#/components/schemas/session'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
examples:
|
||||
login_failed:
|
||||
$ref: 'auth.yaml#/components/examples/login_failed'
|
||||
session_list:
|
||||
get:
|
||||
summary: List of all current sessions
|
||||
|
@ -213,6 +208,12 @@ components:
|
|||
responses:
|
||||
'204':
|
||||
description: No Content (deleted)
|
||||
'404':
|
||||
description: Not Found (session not found)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad Request
|
||||
content:
|
||||
|
|
|
@ -95,6 +95,12 @@ components:
|
|||
responses:
|
||||
'204':
|
||||
description: Item deleted
|
||||
'404':
|
||||
description: Item not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
@ -233,6 +239,12 @@ components:
|
|||
responses:
|
||||
'204':
|
||||
description: Items deleted
|
||||
'404':
|
||||
description: Item not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
|
|
@ -121,7 +121,7 @@ components:
|
|||
examples:
|
||||
invalid_path_depth:
|
||||
$ref: 'config.yaml#/components/examples/errors/bad_request/invalid_path_depth'
|
||||
item_not_found:
|
||||
item_already_present:
|
||||
$ref: 'config.yaml#/components/examples/errors/bad_request/item_already_present'
|
||||
'401':
|
||||
description: Unauthorized
|
||||
|
@ -144,6 +144,12 @@ components:
|
|||
responses:
|
||||
'204':
|
||||
description: Item deleted
|
||||
'404':
|
||||
description: Item not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
@ -155,8 +161,8 @@ components:
|
|||
examples:
|
||||
invalid_path_depth:
|
||||
$ref: 'config.yaml#/components/examples/errors/bad_request/invalid_path_depth'
|
||||
item_not_found:
|
||||
$ref: 'config.yaml#/components/examples/errors/bad_request/item_not_found'
|
||||
item_already_present:
|
||||
$ref: 'config.yaml#/components/examples/errors/bad_request/item_already_present'
|
||||
'401':
|
||||
description: Unauthorized
|
||||
content:
|
||||
|
@ -795,13 +801,6 @@ components:
|
|||
key: "bad_request"
|
||||
message: "Invalid path depth"
|
||||
hint: "Use, e.g., DELETE /config/dnsmasq/upstreams/127.0.0.1 to remove \"127.0.0.1\" from config.dns.upstreams"
|
||||
item_not_found:
|
||||
summary: Item to be deleted does not exist
|
||||
value:
|
||||
error:
|
||||
key: "bad_request"
|
||||
message: "Item not found"
|
||||
hint: "Can only delete existing items"
|
||||
item_already_present:
|
||||
summary: Item to be added exists already
|
||||
value:
|
||||
|
|
|
@ -40,6 +40,12 @@ components:
|
|||
responses:
|
||||
'204':
|
||||
description: Item deleted
|
||||
'404':
|
||||
description: Item not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
|
|
@ -128,6 +128,12 @@ components:
|
|||
responses:
|
||||
'204':
|
||||
description: Item deleted
|
||||
'404':
|
||||
description: Item not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
@ -251,6 +257,12 @@ components:
|
|||
responses:
|
||||
'204':
|
||||
description: Items deleted
|
||||
'404':
|
||||
description: Item not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
|
|
@ -63,6 +63,9 @@ components:
|
|||
- $ref: 'groups.yaml#/components/schemas/groups/get' # identical to GET
|
||||
- $ref: 'groups.yaml#/components/schemas/lists_processed'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
headers:
|
||||
Location:
|
||||
$ref: 'common.yaml#/components/headers/Location'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
@ -94,6 +97,12 @@ components:
|
|||
responses:
|
||||
'204':
|
||||
description: Item deleted
|
||||
'404':
|
||||
description: Item not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
@ -193,18 +202,14 @@ components:
|
|||
- "item": "test1"
|
||||
- "item": "test2"
|
||||
responses:
|
||||
'201':
|
||||
description: Created item
|
||||
'204':
|
||||
description: Items deleted
|
||||
'404':
|
||||
description: Item not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: 'groups.yaml#/components/schemas/groups/get' # identical to GET
|
||||
- $ref: 'groups.yaml#/components/schemas/lists_processed'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
headers:
|
||||
Location:
|
||||
$ref: 'common.yaml#/components/headers/Location'
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
|
|
@ -218,10 +218,16 @@ components:
|
|||
parameters:
|
||||
- $ref: 'info.yaml#/components/parameters/message_id'
|
||||
description: |
|
||||
*Note:* There will be no content on success. You may specify multiple IDs to delete multiple messages at once (comma-separated in the path like `1,2,3`)
|
||||
You may specify multiple IDs to delete multiple messages at once (comma-separated in the path like `1,2,3`)
|
||||
responses:
|
||||
'204':
|
||||
description: Item deleted
|
||||
'404':
|
||||
description: Not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
@ -235,6 +241,14 @@ components:
|
|||
$ref: 'info.yaml#/components/examples/errors/messages/uri_error'
|
||||
bad_request:
|
||||
$ref: 'info.yaml#/components/examples/errors/messages/bad_request'
|
||||
'401':
|
||||
description: Unauthorized
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: 'common.yaml#/components/errors/unauthorized'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
messages_count:
|
||||
get:
|
||||
summary: Get count of Pi-hole diagnosis messages
|
||||
|
|
|
@ -93,6 +93,12 @@ components:
|
|||
responses:
|
||||
'204':
|
||||
description: Item deleted
|
||||
'404':
|
||||
description: Item not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
@ -189,18 +195,14 @@ components:
|
|||
schema:
|
||||
$ref: 'lists.yaml#/components/schemas/lists/post'
|
||||
responses:
|
||||
'201':
|
||||
description: Created item
|
||||
'204':
|
||||
description: Items deleted
|
||||
'404':
|
||||
description: Item not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: 'lists.yaml#/components/schemas/lists/get'
|
||||
- $ref: 'lists.yaml#/components/schemas/lists_processed'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
headers:
|
||||
Location:
|
||||
$ref: 'common.yaml#/components/headers/Location'
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
|
|
@ -93,6 +93,20 @@ components:
|
|||
responses:
|
||||
'204':
|
||||
description: No Content (deleted)
|
||||
'404':
|
||||
description: Not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'common.yaml#/components/schemas/took'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: 'common.yaml#/components/errors/bad_request'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
'401':
|
||||
description: Unauthorized
|
||||
content:
|
||||
|
|
|
@ -940,15 +940,18 @@ static int api_info_messages_DELETE(struct ftl_conn *api)
|
|||
}
|
||||
|
||||
// Delete message with this ID from the database
|
||||
delete_message(ids);
|
||||
int deleted = 0;
|
||||
delete_message(ids, &deleted);
|
||||
|
||||
// Free memory
|
||||
free(id);
|
||||
cJSON_free(ids);
|
||||
|
||||
// Send empty reply with code 204 No Content
|
||||
// Send empty reply with codes:
|
||||
// - 204 No Content (if any items were deleted)
|
||||
// - 404 Not Found (if no items were deleted)
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
JSON_SEND_OBJECT_CODE(json, 204);
|
||||
JSON_SEND_OBJECT_CODE(json, deleted > 0 ? 204 : 404);
|
||||
}
|
||||
|
||||
int api_info_messages(struct ftl_conn *api)
|
||||
|
|
|
@ -705,7 +705,8 @@ static int api_list_remove(struct ftl_conn *api,
|
|||
}
|
||||
|
||||
// From here on, we can assume the JSON payload is valid
|
||||
if(gravityDB_delFromTable(listtype, array, &sql_msg))
|
||||
unsigned int deleted = 0u;
|
||||
if(gravityDB_delFromTable(listtype, array, &deleted, &sql_msg))
|
||||
{
|
||||
// Inform the resolver that it needs to reload gravity
|
||||
set_event(RELOAD_GRAVITY);
|
||||
|
@ -714,9 +715,11 @@ static int api_list_remove(struct ftl_conn *api,
|
|||
if(allocated_json)
|
||||
cJSON_free(array);
|
||||
|
||||
// Send empty reply with code 204 No Content
|
||||
// Send empty reply with codes:
|
||||
// - 204 No Content (if any items were deleted)
|
||||
// - 404 Not Found (if no items were deleted)
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
JSON_SEND_OBJECT_CODE(json, 204);
|
||||
JSON_SEND_OBJECT_CODE(json, deleted > 0u ? 204 : 404);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -440,7 +440,8 @@ static int api_network_devices_DELETE(struct ftl_conn *api)
|
|||
|
||||
// Delete row from network table by ID
|
||||
const char *sql_msg = NULL;
|
||||
if(!networkTable_deleteDevice(db, device_id, &sql_msg))
|
||||
int deleted = 0;
|
||||
if(!networkTable_deleteDevice(db, device_id, &deleted, &sql_msg))
|
||||
{
|
||||
// Add SQL message (may be NULL = not available)
|
||||
return send_json_error(api, 500,
|
||||
|
@ -452,9 +453,11 @@ static int api_network_devices_DELETE(struct ftl_conn *api)
|
|||
// Close database
|
||||
dbclose(&db);
|
||||
|
||||
// Send empty reply with code 204 No Content
|
||||
// Send empty reply with codes:
|
||||
// - 204 No Content (if any items were deleted)
|
||||
// - 404 Not Found (if no items were deleted)
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
JSON_SEND_OBJECT_CODE(json, 204);
|
||||
JSON_SEND_OBJECT_CODE(json, deleted > 0 ? 204 : 404);
|
||||
}
|
||||
|
||||
int api_network_devices(struct ftl_conn *api)
|
||||
|
|
|
@ -160,8 +160,9 @@ static bool readStringValue(struct conf_item *conf_item, const char *value, stru
|
|||
// Get password hash as allocated string (an empty string is hashed to an empty string)
|
||||
char *pwhash = strlen(value) > 0 ? create_password(value) : strdup("");
|
||||
|
||||
// Verify that the password hash is valid
|
||||
if(verify_password(value, pwhash, false) != PASSWORD_CORRECT)
|
||||
// Verify that the password hash is either valid or empty
|
||||
const enum password_result status = verify_password(value, pwhash, false);
|
||||
if(status != PASSWORD_CORRECT && status != NO_PASSWORD_SET)
|
||||
{
|
||||
log_err("Failed to create password hash (verification failed), password remains unchanged");
|
||||
free(pwhash);
|
||||
|
|
|
@ -328,6 +328,7 @@ enum password_result verify_login(const char *password)
|
|||
log_debug(DEBUG_API, "App password correct");
|
||||
return APPPASSWORD_CORRECT;
|
||||
}
|
||||
|
||||
// Return result
|
||||
return pw;
|
||||
}
|
||||
|
@ -336,7 +337,7 @@ enum password_result verify_password(const char *password, const char *pwhash, c
|
|||
{
|
||||
// No password set
|
||||
if(pwhash == NULL || pwhash[0] == '\0')
|
||||
return PASSWORD_CORRECT;
|
||||
return NO_PASSWORD_SET;
|
||||
|
||||
// No password supplied
|
||||
if(password == NULL || password[0] == '\0')
|
||||
|
@ -606,8 +607,9 @@ bool set_and_check_password(struct conf_item *conf_item, const char *password)
|
|||
// Get password hash as allocated string (an empty string is hashed to an empty string)
|
||||
char *pwhash = strlen(password) > 0 ? create_password(password) : strdup("");
|
||||
|
||||
// Verify that the password hash is valid
|
||||
if(verify_password(password, pwhash, false) != PASSWORD_CORRECT)
|
||||
// Verify that the password hash is valid or that no password is set
|
||||
const enum password_result status = verify_password(password, pwhash, false);
|
||||
if(status != PASSWORD_CORRECT && status != NO_PASSWORD_SET)
|
||||
{
|
||||
free(pwhash);
|
||||
log_warn("Failed to create password hash (verification failed), password remains unchanged");
|
||||
|
|
|
@ -26,6 +26,7 @@ enum password_result {
|
|||
PASSWORD_INCORRECT = 0,
|
||||
PASSWORD_CORRECT = 1,
|
||||
APPPASSWORD_CORRECT = 2,
|
||||
NO_PASSWORD_SET = 3,
|
||||
PASSWORD_RATE_LIMITED = -1
|
||||
} __attribute__((packed));
|
||||
|
||||
|
|
|
@ -1792,8 +1792,9 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
|
|||
return okay;
|
||||
}
|
||||
|
||||
bool gravityDB_delFromTable(const enum gravity_list_type listtype, const cJSON* array, const char **message)
|
||||
bool gravityDB_delFromTable(const enum gravity_list_type listtype, const cJSON* array, unsigned int *deleted, const char **message)
|
||||
{
|
||||
// Return early if database is not available
|
||||
if(gravity_db == NULL)
|
||||
{
|
||||
*message = "Database not available";
|
||||
|
@ -2004,6 +2005,9 @@ bool gravityDB_delFromTable(const enum gravity_list_type listtype, const cJSON*
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
// Add number of deleted rows
|
||||
*deleted += sqlite3_changes(gravity_db);
|
||||
}
|
||||
|
||||
// Drop temporary table
|
||||
|
|
|
@ -69,7 +69,7 @@ bool gravityDB_readTableGetRow(const enum gravity_list_type listtype, tablerow *
|
|||
void gravityDB_readTableFinalize(void);
|
||||
bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
|
||||
const char **message, const enum http_method method);
|
||||
bool gravityDB_delFromTable(const enum gravity_list_type listtype, const cJSON* array, const char **message);
|
||||
bool gravityDB_delFromTable(const enum gravity_list_type listtype, const cJSON* array, unsigned int *deleted, const char **message);
|
||||
bool gravityDB_edit_groups(const enum gravity_list_type listtype, cJSON *groups,
|
||||
const tablerow *row, const char **message);
|
||||
|
||||
|
|
|
@ -378,7 +378,7 @@ end_of_add_message: // Close database connection
|
|||
return rowid;
|
||||
}
|
||||
|
||||
bool delete_message(cJSON *ids)
|
||||
bool delete_message(cJSON *ids, int *deleted)
|
||||
{
|
||||
// Return early if database is known to be broken
|
||||
if(FTLDBerror())
|
||||
|
@ -413,6 +413,10 @@ bool delete_message(cJSON *ids)
|
|||
log_err("SQL error (%i): %s", sqlite3_errcode(db), sqlite3_errmsg(db));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add to deleted count
|
||||
*deleted += sqlite3_changes(db);
|
||||
|
||||
sqlite3_reset(res);
|
||||
sqlite3_clear_bindings(res);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
int count_messages(const bool filter_dnsmasq_warnings);
|
||||
bool format_messages(cJSON *array);
|
||||
bool create_message_table(sqlite3 *db);
|
||||
bool delete_message(cJSON *ids);
|
||||
bool delete_message(cJSON *ids, int *deleted);
|
||||
bool flush_message_table(void);
|
||||
void logg_regex_warning(const char *type, const char *warning, const int dbindex, const char *regex);
|
||||
void logg_subnet_warning(const char *ip, const int matching_count, const char *matching_ids,
|
||||
|
|
|
@ -2425,7 +2425,7 @@ void networkTable_readIPsFinalize(sqlite3_stmt *read_stmt)
|
|||
sqlite3_finalize(read_stmt);
|
||||
}
|
||||
|
||||
bool networkTable_deleteDevice(sqlite3 *db, const int id, const char **message)
|
||||
bool networkTable_deleteDevice(sqlite3 *db, const int id, int *deleted, const char **message)
|
||||
{
|
||||
// First step: Delete all associated IPs of this device
|
||||
// Prepare SQLite statement
|
||||
|
@ -2462,6 +2462,9 @@ bool networkTable_deleteDevice(sqlite3 *db, const int id, const char **message)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check if we deleted any rows
|
||||
*deleted += sqlite3_changes(db);
|
||||
|
||||
// Finalize statement
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
|
@ -2498,6 +2501,9 @@ bool networkTable_deleteDevice(sqlite3 *db, const int id, const char **message)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check if we deleted any rows
|
||||
*deleted += sqlite3_changes(db);
|
||||
|
||||
// Finalize statement
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
|
|
|
@ -52,6 +52,6 @@ bool networkTable_readIPs(sqlite3 *db, sqlite3_stmt **read_stmt, const int id, c
|
|||
bool networkTable_readIPsGetRecord(sqlite3_stmt *read_stmt, network_addresses_record *network_addresses, const char **message);
|
||||
void networkTable_readIPsFinalize(sqlite3_stmt *read_stmt);
|
||||
|
||||
bool networkTable_deleteDevice(sqlite3 *db, const int id, const char **message);
|
||||
bool networkTable_deleteDevice(sqlite3 *db, const int id, int *deleted, const char **message);
|
||||
|
||||
#endif //NETWORKTABLE_H
|
||||
|
|
|
@ -94,7 +94,7 @@ int main_dnsmasq (int argc, char **argv)
|
|||
sigaction(SIGUSR1, &sigact, NULL);
|
||||
sigaction(SIGUSR2, &sigact, NULL);
|
||||
sigaction(SIGHUP, &sigact, NULL);
|
||||
sigaction(SIGTERM, &sigact, NULL);
|
||||
sigaction(SIGUSR6, &sigact, NULL); // Pi-hole modification
|
||||
sigaction(SIGALRM, &sigact, NULL);
|
||||
sigaction(SIGCHLD, &sigact, NULL);
|
||||
sigaction(SIGINT, &sigact, NULL);
|
||||
|
@ -1330,7 +1330,7 @@ static void sig_handler(int sig)
|
|||
event = EVENT_CHILD;
|
||||
else if (sig == SIGALRM)
|
||||
event = EVENT_ALARM;
|
||||
else if (sig == SIGTERM)
|
||||
else if (sig == SIGUSR6) // Pi-hole modified
|
||||
event = EVENT_TERM;
|
||||
else if (sig == SIGUSR1)
|
||||
event = EVENT_DUMP;
|
||||
|
|
|
@ -3263,6 +3263,7 @@ bool FTL_unlink_DHCP_lease(const char *ipaddr)
|
|||
#endif
|
||||
else
|
||||
{
|
||||
// Invalid IP address or no lease found
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -311,11 +311,94 @@ static void SIGRT_handler(int signum, siginfo_t *si, void *unused)
|
|||
// Parse neighbor cache
|
||||
set_event(PARSE_NEIGHBOR_CACHE);
|
||||
}
|
||||
// else if(rtsig == 6)
|
||||
// {
|
||||
// // Signal internally used to signal dnsmasq it has to stop
|
||||
// }
|
||||
|
||||
// Restore errno before returning back to previous context
|
||||
errno = _errno;
|
||||
}
|
||||
|
||||
static void SIGTERM_handler(int signum, siginfo_t *si, void *unused)
|
||||
{
|
||||
// Ignore SIGTERM outside of the main process (TCP forks)
|
||||
if(mpid != getpid())
|
||||
return;
|
||||
|
||||
// Get PID and UID of the process that sent the terminating signal
|
||||
const pid_t kill_pid = si->si_pid;
|
||||
const uid_t kill_uid = si->si_uid;
|
||||
|
||||
// Get name of the process that sent the terminating signal
|
||||
char kill_name[256] = { 0 };
|
||||
char kill_exe [256] = { 0 };
|
||||
snprintf(kill_exe, sizeof(kill_exe), "/proc/%ld/cmdline", (long int)kill_pid);
|
||||
FILE *fp = fopen(kill_exe, "r");
|
||||
if(fp != NULL)
|
||||
{
|
||||
// Successfully opened file
|
||||
size_t read = 0;
|
||||
// Read line from file
|
||||
if((read = fread(kill_name, sizeof(char), sizeof(kill_name), fp)) > 0)
|
||||
{
|
||||
// Successfully read line
|
||||
|
||||
// cmdline contains the command-line arguments as a set
|
||||
// of strings separated by null bytes ('\0'), with a
|
||||
// further null byte after the last string. Hence, we
|
||||
// need to replace all null bytes with spaces for
|
||||
// displaying it below
|
||||
for(unsigned int i = 0; i < min((size_t)read, sizeof(kill_name)); i++)
|
||||
{
|
||||
if(kill_name[i] == '\0')
|
||||
kill_name[i] = ' ';
|
||||
}
|
||||
|
||||
// Remove any trailing spaces
|
||||
for(unsigned int i = read - 1; i > 0; i--)
|
||||
{
|
||||
if(kill_name[i] == ' ')
|
||||
kill_name[i] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to read line
|
||||
strcpy(kill_name, "N/A");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to open file
|
||||
strcpy(kill_name, "N/A");
|
||||
}
|
||||
|
||||
// Get username of the process that sent the terminating signal
|
||||
char kill_user[256] = { 0 };
|
||||
struct passwd *pwd = getpwuid(kill_uid);
|
||||
if(pwd != NULL)
|
||||
{
|
||||
// Successfully obtained username
|
||||
strncpy(kill_user, pwd->pw_name, sizeof(kill_user));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to obtain username
|
||||
strcpy(kill_user, "N/A");
|
||||
}
|
||||
|
||||
// Log who sent the signal
|
||||
log_info("Asked to terminate by \"%s\" (PID %ld, user %s UID %ld)",
|
||||
kill_name, (long int)kill_pid,
|
||||
kill_user, (long int)kill_uid);
|
||||
|
||||
// Terminate dnsmasq to stop DNS service
|
||||
raise(SIGUSR6);
|
||||
}
|
||||
|
||||
// Register ordinary signals handler
|
||||
void handle_signals(void)
|
||||
{
|
||||
|
@ -337,6 +420,13 @@ void handle_signals(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Also catch SIGTERM
|
||||
struct sigaction SIGaction = { 0 };
|
||||
SIGaction.sa_flags = SA_SIGINFO;
|
||||
sigemptyset(&SIGaction.sa_mask);
|
||||
SIGaction.sa_sigaction = &SIGTERM_handler;
|
||||
sigaction(SIGTERM, &SIGaction, NULL);
|
||||
|
||||
// Log start time of FTL
|
||||
FTLstarttime = time(NULL);
|
||||
}
|
||||
|
@ -351,8 +441,12 @@ void handle_realtime_signals(void)
|
|||
// Catch all real-time signals
|
||||
for(int signum = SIGRTMIN; signum <= SIGRTMAX; signum++)
|
||||
{
|
||||
struct sigaction SIGACTION;
|
||||
memset(&SIGACTION, 0, sizeof(struct sigaction));
|
||||
if(signum == SIGUSR6)
|
||||
// Skip SIGUSR6 as it is used internally to signify
|
||||
// dnsmasq to stop
|
||||
continue;
|
||||
|
||||
struct sigaction SIGACTION = { 0 };
|
||||
SIGACTION.sa_flags = SA_SIGINFO;
|
||||
sigemptyset(&SIGACTION.sa_mask);
|
||||
SIGACTION.sa_sigaction = &SIGRT_handler;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include "enums.h"
|
||||
|
||||
#define SIGUSR6 (SIGRTMIN + 6)
|
||||
|
||||
// defined in dnsmasq/dnsmasq.h
|
||||
extern volatile char FTL_terminate;
|
||||
|
||||
|
|
|
@ -542,8 +542,6 @@ end_of_parseList:
|
|||
// Print newline
|
||||
puts("");
|
||||
}
|
||||
// Print final newline
|
||||
puts("");
|
||||
}
|
||||
|
||||
// Free memory
|
||||
|
|
|
@ -200,7 +200,10 @@
|
|||
})
|
||||
|
||||
#define JSON_SEND_OBJECT_CODE(object, code)({ \
|
||||
cJSON_AddNumberToObject(object, "took", double_time() - api->now);\
|
||||
if((code) != 204) \
|
||||
{ \
|
||||
cJSON_AddNumberToObject(object, "took", double_time() - api->now); \
|
||||
} \
|
||||
char *json_string = json_formatter(object); \
|
||||
if(json_string == NULL) \
|
||||
{ \
|
||||
|
|
Loading…
Reference in New Issue