Merge pull request #1653 from pi-hole/tweak/api_auth_https
Add /api/info/login
This commit is contained in:
commit
80d4a0efec
|
@ -44,6 +44,7 @@ static struct {
|
|||
{ "/api/groups", "/{name}", api_list, { false, true, 0 }, true, HTTP_GET | HTTP_POST | HTTP_PUT | HTTP_DELETE },
|
||||
{ "/api/lists", "/{list}", api_list, { false, true, 0 }, true, HTTP_GET | HTTP_POST | HTTP_PUT | HTTP_DELETE },
|
||||
{ "/api/info/client", "", api_info_client, { false, true, 0 }, false, HTTP_GET },
|
||||
{ "/api/info/login", "", api_info_login, { false, true, 0 }, false, HTTP_GET },
|
||||
{ "/api/info/system", "", api_info_system, { false, true, 0 }, true, HTTP_GET },
|
||||
{ "/api/info/database", "", api_info_database, { false, true, 0 }, true, HTTP_GET },
|
||||
{ "/api/info/sensors", "", api_info_sensors, { false, true, 0 }, true, HTTP_GET },
|
||||
|
|
|
@ -60,6 +60,7 @@ int api_info_version(struct ftl_conn *api);
|
|||
int api_info_messages_count(struct ftl_conn *api);
|
||||
int api_info_messages(struct ftl_conn *api);
|
||||
int api_info_metrics(struct ftl_conn *api);
|
||||
int api_info_login(struct ftl_conn *api);
|
||||
|
||||
// Config methods
|
||||
int api_config(struct ftl_conn *api);
|
||||
|
|
|
@ -302,7 +302,6 @@ static int get_all_sessions(struct ftl_conn *api, cJSON *json)
|
|||
static int get_session_object(struct ftl_conn *api, cJSON *json, const int user_id, const time_t now)
|
||||
{
|
||||
cJSON *session = JSON_NEW_OBJECT();
|
||||
const bool dns = get_blockingstatus() != DNS_FAILED;
|
||||
|
||||
// Authentication not needed
|
||||
if(user_id == API_AUTH_LOCALHOST || user_id == API_AUTH_EMPTYPASS)
|
||||
|
@ -312,7 +311,6 @@ static int get_session_object(struct ftl_conn *api, cJSON *json, const int user_
|
|||
JSON_ADD_NULL_TO_OBJECT(session, "sid");
|
||||
JSON_ADD_NUMBER_TO_OBJECT(session, "validity", -1);
|
||||
JSON_ADD_ITEM_TO_OBJECT(json, "session", session);
|
||||
JSON_ADD_BOOL_TO_OBJECT(json, "dns", dns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -325,7 +323,6 @@ static int get_session_object(struct ftl_conn *api, cJSON *json, const int user_
|
|||
JSON_REF_STR_IN_OBJECT(session, "csrf", auth_data[user_id].csrf);
|
||||
JSON_ADD_NUMBER_TO_OBJECT(session, "validity", auth_data[user_id].valid_until - now);
|
||||
JSON_ADD_ITEM_TO_OBJECT(json, "session", session);
|
||||
JSON_ADD_BOOL_TO_OBJECT(json, "dns", dns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -335,7 +332,6 @@ static int get_session_object(struct ftl_conn *api, cJSON *json, const int user_
|
|||
JSON_ADD_NULL_TO_OBJECT(session, "sid");
|
||||
JSON_ADD_NUMBER_TO_OBJECT(session, "validity", -1);
|
||||
JSON_ADD_ITEM_TO_OBJECT(json, "session", session);
|
||||
JSON_ADD_BOOL_TO_OBJECT(json, "dns", dns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@ components:
|
|||
$ref: 'auth.yaml#/components/examples/no_login_required'
|
||||
login_required:
|
||||
$ref: 'auth.yaml#/components/examples/login_required'
|
||||
dns_failure:
|
||||
$ref: 'auth.yaml#/components/examples/dns_failure'
|
||||
post:
|
||||
summary: Submit password for login
|
||||
tags:
|
||||
|
@ -157,6 +155,7 @@ components:
|
|||
tags:
|
||||
- Authentication
|
||||
operationId: "get_auth_totp"
|
||||
security: []
|
||||
description: Suggest new TOTP credentials for two-factor authentication (2FA)
|
||||
responses:
|
||||
'200':
|
||||
|
@ -245,9 +244,6 @@ components:
|
|||
validity:
|
||||
type: integer
|
||||
description: Remaining lifetime of this session unless refreshed (seconds)
|
||||
dns:
|
||||
type: boolean
|
||||
description: Whether the DNS server is up and running. False only in failed state
|
||||
|
||||
password:
|
||||
type: object
|
||||
|
@ -371,7 +367,6 @@ components:
|
|||
sid: null
|
||||
csrf: null
|
||||
validity: 300
|
||||
dns: true
|
||||
no_login_required:
|
||||
summary: No login required for this client
|
||||
value:
|
||||
|
@ -381,7 +376,6 @@ components:
|
|||
sid: null
|
||||
csrf: null
|
||||
validity: -1
|
||||
dns: true
|
||||
login_required:
|
||||
summary: Login required
|
||||
value:
|
||||
|
@ -391,7 +385,6 @@ components:
|
|||
sid: null
|
||||
csrf: null
|
||||
validity: -1
|
||||
dns: true
|
||||
login_failed:
|
||||
summary: Login failed
|
||||
value:
|
||||
|
@ -401,17 +394,6 @@ components:
|
|||
sid: null
|
||||
csrf: null
|
||||
validity: -1
|
||||
dns: true
|
||||
dns_failure:
|
||||
summary: DNS server failure
|
||||
value:
|
||||
session:
|
||||
valid: false
|
||||
totp: false
|
||||
sid: null
|
||||
csrf: null
|
||||
validity: -1
|
||||
dns: false
|
||||
errors:
|
||||
no_payload:
|
||||
summary: Bad request (no valid JSON payload)
|
||||
|
|
|
@ -6,6 +6,7 @@ components:
|
|||
summary: Get information about requesting client
|
||||
tags:
|
||||
- "FTL information"
|
||||
security: []
|
||||
operationId: "get_client"
|
||||
description: |
|
||||
The property `timer` may contain additional details concerning a temporary en-/disabling.
|
||||
|
@ -278,6 +279,24 @@ components:
|
|||
allOf:
|
||||
- $ref: 'common.yaml#/components/errors/unauthorized'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
login:
|
||||
get:
|
||||
summary: Login page related information
|
||||
tags:
|
||||
- "FTL information"
|
||||
operationId: "get_logininfo"
|
||||
security: []
|
||||
description: |
|
||||
This API hook returns information used on the login page to possibly display messages/warnings.
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: 'info.yaml#/components/schemas/login'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
|
||||
schemas:
|
||||
client:
|
||||
|
@ -1068,6 +1087,15 @@ components:
|
|||
type: integer
|
||||
description: Number of items
|
||||
example: 42
|
||||
login:
|
||||
type: object
|
||||
properties:
|
||||
https_port:
|
||||
type: integer
|
||||
description: HTTPS port of the Pi-hole webserver (0 if disabled)
|
||||
dns:
|
||||
type: boolean
|
||||
description: Whether the DNS server is up and running. False only in failed state
|
||||
examples:
|
||||
errors:
|
||||
messages:
|
||||
|
|
|
@ -190,6 +190,9 @@ paths:
|
|||
/info/metrics:
|
||||
$ref: 'info.yaml#/components/paths/metrics'
|
||||
|
||||
/info/login:
|
||||
$ref: 'info.yaml#/components/paths/login'
|
||||
|
||||
/logs/dnsmasq:
|
||||
$ref: 'logs.yaml#/components/paths/logs/dnsmasq'
|
||||
|
||||
|
|
|
@ -49,6 +49,9 @@
|
|||
#include <limits.h>
|
||||
#include "metrics.h"
|
||||
|
||||
// get_https_port()
|
||||
#include "webserver/webserver.h"
|
||||
|
||||
// DIR
|
||||
#include <dirent.h>
|
||||
|
||||
|
@ -1032,3 +1035,15 @@ int api_info_metrics(struct ftl_conn *api)
|
|||
JSON_ADD_ITEM_TO_OBJECT(json2, "metrics", json);
|
||||
JSON_SEND_OBJECT(json2);
|
||||
}
|
||||
|
||||
int api_info_login(struct ftl_conn *api)
|
||||
{
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
|
||||
const bool dns = get_blockingstatus() != DNS_FAILED;
|
||||
JSON_ADD_BOOL_TO_OBJECT(json, "dns", dns);
|
||||
|
||||
JSON_ADD_NUMBER_TO_OBJECT(json, "https_port", get_https_port());
|
||||
|
||||
JSON_SEND_OBJECT(json);
|
||||
}
|
||||
|
|
|
@ -177,6 +177,52 @@ void FTL_mbed_debug(void *user_param, int level, const char *file, int line, con
|
|||
log_web("mbedTLS(%s:%d, %d): %.*s", file, line, level, (int)len, message);
|
||||
}
|
||||
|
||||
#define MAXPORTS 8
|
||||
static struct serverports
|
||||
{
|
||||
bool is_secure;
|
||||
unsigned char protocol; // 1 = IPv4, 2 = IPv4+IPv6, 3 = IPv6
|
||||
in_port_t port;
|
||||
} server_ports[MAXPORTS] = { 0 };
|
||||
static in_port_t https_port = 0;
|
||||
static void get_server_ports(void)
|
||||
{
|
||||
if(ctx == NULL)
|
||||
return;
|
||||
|
||||
// Loop over all listening ports
|
||||
struct mg_server_port mgports[MAXPORTS] = { 0 };
|
||||
if(mg_get_server_ports(ctx, MAXPORTS, mgports) > 0)
|
||||
{
|
||||
// Loop over all ports
|
||||
for(unsigned int i = 0; i < MAXPORTS; i++)
|
||||
{
|
||||
// Stop if no more ports are configured
|
||||
if(mgports[i].protocol == 0)
|
||||
break;
|
||||
|
||||
// Store port information
|
||||
server_ports[i].port = mgports[i].port;
|
||||
server_ports[i].is_secure = mgports[i].is_ssl;
|
||||
server_ports[i].protocol = mgports[i].protocol;
|
||||
|
||||
// Store HTTPS port if not already set
|
||||
if(mgports[i].is_ssl && https_port == 0)
|
||||
https_port = mgports[i].port;
|
||||
|
||||
// Print port information
|
||||
log_debug(DEBUG_API, "Listening on port %d (HTTP%s, IPv%s)",
|
||||
mgports[i].port, mgports[i].is_ssl ? "S" : "",
|
||||
mgports[i].protocol == 1 ? "4" : (mgports[i].protocol == 3 ? "6" : "4+6"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
in_port_t __attribute__((pure)) get_https_port(void)
|
||||
{
|
||||
return https_port;
|
||||
}
|
||||
|
||||
void http_init(void)
|
||||
{
|
||||
log_web("Initializing HTTP server on port %s", config.webserver.port.v.s);
|
||||
|
@ -311,6 +357,9 @@ void http_init(void)
|
|||
|
||||
// Prepare prerequisites for Lua
|
||||
allocate_lua();
|
||||
|
||||
// Get server ports
|
||||
get_server_ports();
|
||||
}
|
||||
|
||||
static char *append_to_path(char *path, const char *append)
|
||||
|
|
|
@ -13,4 +13,6 @@
|
|||
void http_init(void);
|
||||
void http_terminate(void);
|
||||
|
||||
in_port_t get_https_port(void) __attribute__((pure));
|
||||
|
||||
#endif // WEBSERVER_H
|
|
@ -1266,7 +1266,7 @@
|
|||
@test "API authorization (without password): No login required" {
|
||||
run bash -c 'curl -s 127.0.0.1/api/auth'
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ ${lines[0]} == '{"session":{"valid":true,"totp":false,"sid":null,"validity":-1},"dns":true,"took":'*'}' ]]
|
||||
[[ ${lines[0]} == '{"session":{"valid":true,"totp":false,"sid":null,"validity":-1},"took":'*'}' ]]
|
||||
}
|
||||
|
||||
@test "API authorization: Setting password" {
|
||||
|
|
Loading…
Reference in New Issue