Skip to content

Commit 9919c8d

Browse files
BornToBeRootclaude
andcommitted
Fix: IP Scanner: Certificate of a web page after a redirect to http (R18)
The certificate was only replaced by https responses, so after a redirect from https to http (e.g. https://host:8443/ -> http://host:8080/login) the certificate of the first response was shown for the plain http page. The certificate of the last response is used (null for http). The URL stays the first URL on purpose (the Web Console opens the port that answered), documented in WebPageInfo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent beeb475 commit 9919c8d

3 files changed

Lines changed: 15 additions & 8 deletions

File tree

‎Source/NETworkManager.Models/Network/WebPageInfo.cs‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
/// <summary>
44
/// Web page of a host, see <see cref="WebPageResolver" />.
55
/// </summary>
6-
/// <param name="URL">URL that answered (e.g. "https://192.168.1.1/").</param>
6+
/// <param name="URL">
7+
/// URL that was requested on the port that answered (e.g. "https://192.168.1.1/") - also after a redirect on the
8+
/// same host, so the Web Console opens the port (and scheme) that answered; the other values are of the last
9+
/// response.
10+
/// </param>
711
/// <param name="StatusCode">HTTP status code of the (last) response, e.g. 200.</param>
812
/// <param name="Title">Title of the web page, empty if it has none (e.g. a redirect to another host).</param>
913
/// <param name="Server">Value of the <c>Server</c> header (e.g. "nginx"), empty if there is none.</param>
@@ -14,7 +18,10 @@
1418
/// <param name="RedirectURL">
1519
/// Target of a redirect to another host (e.g. "https://unifi.local:8443/"), empty if there is none.
1620
/// </param>
17-
/// <param name="Certificate">TLS certificate of the web server, null for http.</param>
21+
/// <param name="Certificate">
22+
/// TLS certificate of the web server (of the last response), null for http (also after a redirect from https to
23+
/// http).
24+
/// </param>
1825
public sealed record WebPageInfo(
1926
string URL,
2027
int StatusCode,

‎Source/NETworkManager.Models/Network/WebPageResolver.cs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,6 @@ public static string[] GetSchemes(int port)
159159
private static async Task<WebPageInfo> GetWebPageAsync(string url, int timeout,
160160
CancellationToken cancellationToken)
161161
{
162-
// Certificate of the last https response (e.g. after a redirect from http to https)
163-
WebCertificateInfo certificate = null;
164-
165162
try
166163
{
167164
// In the try: an URL that can't be parsed only means no web page for this host, not the end of the scan
@@ -180,8 +177,11 @@ private static async Task<WebPageInfo> GetWebPageAsync(string url, int timeout,
180177
using var response = await Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead,
181178
linkedCts.Token).ConfigureAwait(false);
182179

183-
if (request.Options.TryGetValue(CertificateKey, out var requestCertificate))
184-
certificate = requestCertificate;
180+
// Certificate of this response (e.g. after a redirect from http to https), null for http (also after a
181+
// redirect from https to http)
182+
var certificate = request.Options.TryGetValue(CertificateKey, out var requestCertificate)
183+
? requestCertificate
184+
: null;
185185

186186
var statusCode = (int)response.StatusCode;
187187
var server = CleanHeaderValue(response.Headers.Server.ToString());

‎Website/docs/application/ip-scanner.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ Timeout in milliseconds after which an mDNS request is considered lost.
420420

421421
### Read web pages
422422

423-
Read the web page (`GET /`) of every reachable host with an open port of the [Ports](#ports-1) below: status code, title, the `Server` and `X-Powered-By` headers, the realm of a login prompt (`WWW-Authenticate` header of a `401` response, e.g. `RT-AC68U` - routers, cameras and printers often name their model there) the target of a redirect to another host (e.g. `https://unifi.local:8443/`) and, for https, the TLS certificate: subject, issuer (`Self-signed` for a self-signed certificate) and the end of the validity (`(expired)` if it is expired). The title is shown in the **Web** column (the URL in the tooltip), all values in the **Web** section of the row details. The ports are tried in the order of the list, the first one that answers is used: https on `443` and `8443`, http on `80` and `8080`, https and then http on any other port. On ports other than `443` / `8443`, the https attempt waits at most 1 second (also with a higher timeout), so a plain http device that doesn't answer the TLS handshake doesn't cost the whole timeout before http is tried. Redirects on the same host (e.g. http to https, `/` to `/login.html`) are followed. If the page has no title, the column shows the realm, the `Server` header (e.g. `nginx`) or the redirect target. The values are in the search and the export (`WebStatusCode`, `WebServer`, `WebPoweredBy`, `WebRealm`, `WebRedirectURL`, `WebCertificateSubject`, `WebCertificateIssuer`, `WebCertificateNotAfter`, `WebCertificateSelfSigned`). **Web Console** in the context menu opens the port (and scheme) that answered.
423+
Read the web page (`GET /`) of every reachable host with an open port of the [Ports](#ports-1) below: status code, title, the `Server` and `X-Powered-By` headers, the realm of a login prompt (`WWW-Authenticate` header of a `401` response, e.g. `RT-AC68U` - routers, cameras and printers often name their model there) the target of a redirect to another host (e.g. `https://unifi.local:8443/`) and, for https, the TLS certificate: subject, issuer (`Self-signed` for a self-signed certificate) and the end of the validity (`(expired)` if it is expired). The title is shown in the **Web** column (the URL in the tooltip), all values in the **Web** section of the row details. The ports are tried in the order of the list, the first one that answers is used: https on `443` and `8443`, http on `80` and `8080`, https and then http on any other port. On ports other than `443` / `8443`, the https attempt waits at most 1 second (also with a higher timeout), so a plain http device that doesn't answer the TLS handshake doesn't cost the whole timeout before http is tried. Redirects on the same host (e.g. http to https, `/` to `/login.html`) are followed, the values (also the certificate) are those of the last response. If the page has no title, the column shows the realm, the `Server` header (e.g. `nginx`) or the redirect target. The values are in the search and the export (`WebStatusCode`, `WebServer`, `WebPoweredBy`, `WebRealm`, `WebRedirectURL`, `WebCertificateSubject`, `WebCertificateIssuer`, `WebCertificateNotAfter`, `WebCertificateSelfSigned`). **Web Console** in the context menu opens the port (and scheme) that answered.
424424

425425
**Type:** `Boolean`
426426

0 commit comments

Comments
 (0)