Compare commits

...

6 commits

2 changed files with 95 additions and 6 deletions

View file

@ -94,6 +94,21 @@ namespace SafeExamBrowser.Browser.Handlers
return base.OnBeforeBrowse(webBrowser, browser, frame, request, userGesture, isRedirect); return base.OnBeforeBrowse(webBrowser, browser, frame, request, userGesture, isRedirect);
} }
protected override bool OnOpenUrlFromTab(IWebBrowser webBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
{
switch (targetDisposition)
{
case WindowOpenDisposition.NewBackgroundTab:
case WindowOpenDisposition.NewForegroundTab:
case WindowOpenDisposition.NewPopup:
case WindowOpenDisposition.NewWindow:
case WindowOpenDisposition.SaveToDisk:
return true;
default:
return base.OnOpenUrlFromTab(webBrowser, browser, frame, targetUrl, targetDisposition, userGesture);
}
}
private bool IsQuitUrl(IRequest request) private bool IsQuitUrl(IRequest request)
{ {
var isQuitUrl = false; var isQuitUrl = false;
@ -124,7 +139,8 @@ namespace SafeExamBrowser.Browser.Handlers
{ {
var result = filter.Process(new Request { Url = request.Url }); var result = filter.Process(new Request { Url = request.Url });
if (result == FilterResult.Block) // We apparently can't filter chrome extension requests, as this prevents the rendering of PDFs.
if (result == FilterResult.Block && !request.Url.StartsWith("chrome-extension://"))
{ {
block = true; block = true;
logger.Info($"Blocked main request{(windowSettings.UrlPolicy.CanLog() ? $" for '{request.Url}'" : "")} ({request.ResourceType}, {request.TransitionType})."); logger.Info($"Blocked main request{(windowSettings.UrlPolicy.CanLog() ? $" for '{request.Url}'" : "")} ({request.ResourceType}, {request.TransitionType}).");

View file

@ -9,6 +9,7 @@
using System; using System;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Net.Mime; using System.Net.Mime;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
@ -93,7 +94,7 @@ namespace SafeExamBrowser.Browser.Handlers
protected override void OnResourceRedirect(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl) protected override void OnResourceRedirect(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl)
{ {
SearchSessionIdentifiers(response); SearchSessionIdentifiers(request, response);
base.OnResourceRedirect(chromiumWebBrowser, browser, frame, request, response, ref newUrl); base.OnResourceRedirect(chromiumWebBrowser, browser, frame, request, response, ref newUrl);
} }
@ -107,7 +108,7 @@ namespace SafeExamBrowser.Browser.Handlers
return true; return true;
} }
SearchSessionIdentifiers(response); SearchSessionIdentifiers(request, response);
return base.OnResourceResponse(webBrowser, browser, frame, request, response); return base.OnResourceResponse(webBrowser, browser, frame, request, response);
} }
@ -243,10 +244,10 @@ namespace SafeExamBrowser.Browser.Handlers
} }
} }
private void SearchSessionIdentifiers(IResponse response) private void SearchSessionIdentifiers(IRequest request, IResponse response)
{ {
SearchEdxIdentifier(response); SearchEdxIdentifier(response);
SearchMoodleIdentifier(response); SearchMoodleIdentifier(request, response);
} }
private void SearchEdxIdentifier(IResponse response) private void SearchEdxIdentifier(IResponse response)
@ -269,6 +270,7 @@ namespace SafeExamBrowser.Browser.Handlers
var userName = json["username"].Value<string>(); var userName = json["username"].Value<string>();
Task.Run(() => SessionIdentifierDetected?.Invoke(userName)); Task.Run(() => SessionIdentifierDetected?.Invoke(userName));
logger.Info("EdX session detected.");
} }
} }
catch (Exception e) catch (Exception e)
@ -278,7 +280,17 @@ namespace SafeExamBrowser.Browser.Handlers
} }
} }
private void SearchMoodleIdentifier(IResponse response) private void SearchMoodleIdentifier(IRequest request, IResponse response)
{
var success = TrySearchByLocation(response);
if (!success)
{
TrySearchBySession(request, response);
}
}
private bool TrySearchByLocation(IResponse response)
{ {
var locations = response.Headers.GetValues("Location"); var locations = response.Headers.GetValues("Location");
@ -293,6 +305,9 @@ namespace SafeExamBrowser.Browser.Handlers
var userId = location.Substring(location.IndexOf("=") + 1); var userId = location.Substring(location.IndexOf("=") + 1);
Task.Run(() => SessionIdentifierDetected?.Invoke(userId)); Task.Run(() => SessionIdentifierDetected?.Invoke(userId));
logger.Info("Moodle session detected.");
return true;
} }
} }
catch (Exception e) catch (Exception e)
@ -300,6 +315,64 @@ namespace SafeExamBrowser.Browser.Handlers
logger.Error("Failed to parse Moodle session identifier!", e); logger.Error("Failed to parse Moodle session identifier!", e);
} }
} }
return false;
}
private void TrySearchBySession(IRequest request, IResponse response)
{
var cookies = response.Headers.GetValues("Set-Cookie");
if (cookies != default(string[]))
{
var session = cookies.FirstOrDefault(c => c.Contains("MoodleSession"));
if (session != default(string))
{
var requestUrl = request.Url;
Task.Run(async () =>
{
try
{
var start = session.IndexOf("=") + 1;
var end = session.IndexOf(";");
var value = session.Substring(start, end - start);
var uri = new Uri(requestUrl);
var message = new HttpRequestMessage(HttpMethod.Get, $"{uri.Scheme}{Uri.SchemeDelimiter}{uri.Host}/theme/boost_ethz/sebuser.php");
using (var handler = new HttpClientHandler { UseCookies = false })
using (var client = new HttpClient(handler))
{
message.Headers.Add("Cookie", $"MoodleSession={value}");
var result = await client.SendAsync(message);
if (result.IsSuccessStatusCode)
{
var userId = await result.Content.ReadAsStringAsync();
if (int.TryParse(userId, out var id) && id > 0)
{
#pragma warning disable CS4014
Task.Run(() => SessionIdentifierDetected?.Invoke(userId));
#pragma warning restore CS4014
logger.Info("Moodle session detected.");
}
}
else
{
logger.Error($"Failed to retrieve Moodle session identifier! Response: {result.StatusCode} {result.ReasonPhrase}");
}
}
}
catch (Exception e)
{
logger.Error("Failed to parse Moodle session identifier!", e);
}
});
}
}
} }
} }
} }