189 lines
7.0 KiB
C#
189 lines
7.0 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Reflection;
|
|
using Microsoft.Deployment.Compression.Cab;
|
|
using System.Collections.Generic;
|
|
using Microsoft.Deployment.Compression;
|
|
|
|
namespace Lucidiot.CertBoat {
|
|
public class ExtractException : Exception {
|
|
public ExtractException() : base() {
|
|
}
|
|
public ExtractException(string message)
|
|
: base(message) {
|
|
}
|
|
}
|
|
|
|
static class Program {
|
|
static int Main(string[] args) {
|
|
bool showHelp = false, showVersion = false, doUpdate = false, doCreateTask = false, doRemoveTask = false;
|
|
foreach (string rawArg in args) {
|
|
// One day, I will write a cool command line parser, but today is not that day.
|
|
string arg = rawArg.TrimStart(new char[] { '-', '/' });
|
|
if (arg.Equals("?", StringComparison.InvariantCultureIgnoreCase) || arg.Equals("help", StringComparison.InvariantCultureIgnoreCase))
|
|
showHelp = true;
|
|
else if (arg.Equals("version", StringComparison.InvariantCultureIgnoreCase))
|
|
showVersion = true;
|
|
else if (arg.Equals("update", StringComparison.InvariantCultureIgnoreCase))
|
|
doUpdate = true;
|
|
else if (arg.Equals("createscheduledtask", StringComparison.InvariantCultureIgnoreCase)
|
|
|| arg.Equals("create-scheduled-task", StringComparison.InvariantCultureIgnoreCase))
|
|
doCreateTask = true;
|
|
else if (arg.Equals("removescheduledtask", StringComparison.InvariantCultureIgnoreCase)
|
|
|| arg.Equals("remove-scheduled-task", StringComparison.InvariantCultureIgnoreCase))
|
|
doRemoveTask = true;
|
|
else {
|
|
Console.WriteLine(String.Format(Strings.UnknownArgument, rawArg));
|
|
PrintUsage();
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
if (showHelp) {
|
|
PrintUsage();
|
|
return 0;
|
|
}
|
|
|
|
if (showVersion) {
|
|
Console.WriteLine(Assembly.GetExecutingAssembly().GetName().Version);
|
|
return 0;
|
|
}
|
|
|
|
// Creating and removing the scheduled tasks does not make sense; resolve this by only removing the scheduled tasks.
|
|
if (doCreateTask && doRemoveTask)
|
|
doCreateTask = false;
|
|
|
|
// Nothing was specified: update certs by default.
|
|
if (!doUpdate && !doCreateTask && !doRemoveTask)
|
|
doUpdate = true;
|
|
|
|
if (doCreateTask && !CreateScheduledTask())
|
|
return 1;
|
|
|
|
if (doRemoveTask && !RemoveScheduledTask())
|
|
return 1;
|
|
|
|
if (doUpdate && !Update())
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void PrintUsage() {
|
|
Console.WriteLine(String.Format(
|
|
Strings.Help,
|
|
Environment.GetCommandLineArgs()[0]
|
|
));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update the system certificate stores from the downloaded certificate trust lists.
|
|
/// </summary>
|
|
/// <returns>Whether or not at least one list was successfully downloaded and applied.</returns>
|
|
static bool Update() {
|
|
if (Properties.Settings.Default.CabinetUris.Count < 1) {
|
|
Console.WriteLine(Strings.NoCabinetUris);
|
|
}
|
|
|
|
bool success = false;
|
|
foreach (string uriString in Properties.Settings.Default.CabinetUris) {
|
|
Uri uri;
|
|
try {
|
|
uri = new Uri(uriString);
|
|
} catch (UriFormatException e) {
|
|
Console.WriteLine(String.Format(Strings.InvalidUri, e.ToString()));
|
|
continue;
|
|
}
|
|
success |= Update(uri);
|
|
}
|
|
return success;
|
|
}
|
|
|
|
private static bool Update(Uri uri) {
|
|
string cabpath, filepath;
|
|
try {
|
|
cabpath = Download(uri);
|
|
} catch (Exception e) {
|
|
Console.WriteLine(String.Format(Strings.DownloadFailure, uri, e.ToString()));
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
filepath = ExtractSingleFileCabinet(cabpath);
|
|
} catch (Exception e) {
|
|
Console.WriteLine(String.Format(Strings.ExtractFailure, uri, e.ToString()));
|
|
return false;
|
|
} finally {
|
|
if (File.Exists(cabpath))
|
|
File.Delete(cabpath);
|
|
}
|
|
|
|
try {
|
|
NativeMethods.ImportSTL(filepath);
|
|
} catch (Exception e) {
|
|
Console.WriteLine(String.Format(Strings.ApplyFailure, uri, e.ToString()));
|
|
return false;
|
|
} finally {
|
|
if (File.Exists(filepath))
|
|
File.Delete(filepath);
|
|
}
|
|
|
|
Console.WriteLine(String.Format(Strings.ApplySuccess, uri));
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Perform a GET request on a URI and store the response body into a temporary file.
|
|
/// </summary>
|
|
/// <param name="uri">URI to make a GET request on.</param>
|
|
/// <returns>Path to the temporary file.</returns>
|
|
private static string Download(Uri uri) {
|
|
WebClient client = new WebClient();
|
|
client.Headers.Add(
|
|
HttpRequestHeader.UserAgent,
|
|
String.Format(
|
|
Properties.Settings.Default.UserAgent,
|
|
Assembly.GetExecutingAssembly().GetName().Version
|
|
)
|
|
);
|
|
string path = Path.GetTempFileName();
|
|
client.DownloadFile(uri, path);
|
|
return path;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extract the file of a cabinet file that only includes a single-file.
|
|
/// </summary>
|
|
/// <param name="cabPath">Path to the cabinet file.</param>
|
|
/// <returns>Path to the extracted file.</returns>
|
|
private static string ExtractSingleFileCabinet(string cabPath) {
|
|
CabInfo info = new CabInfo(cabPath);
|
|
|
|
IList<CabFileInfo> files = info.GetFiles();
|
|
if (files.Count < 1)
|
|
throw new ExtractException(Strings.ExtractFileNotFound);
|
|
if (files.Count > 1)
|
|
throw new ExtractException(Strings.ExtractMultipleFilesFound);
|
|
|
|
string destPath = Path.GetTempFileName();
|
|
info.UnpackFile(files[0].Name, destPath);
|
|
return destPath;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set up a task in the Task Scheduler to automatically update the certificates once a day.
|
|
/// </summary>
|
|
static bool CreateScheduledTask() {
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Remove any existing task related to this program from the Task Scheduler.
|
|
/// </summary>
|
|
static bool RemoveScheduledTask() {
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|