1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
namespace AutoUpdateBuilder
{
public class Program
{
private static RSACryptoServiceProvider privkey;
private static string keyfile;
private static string keyfilepassword;
private static string outputfolder;
private static void CompareToManifestPublicKey()
{
if (Duplicati.Library.AutoUpdater.AutoUpdateSettings.SignKey == null || privkey.ToXmlString(false) != Duplicati.Library.AutoUpdater.AutoUpdateSettings.SignKey.ToXmlString(false))
{
Console.WriteLine("The public key in the project is not the same as the public key from the file");
Console.WriteLine("Try setting the key to: ");
Console.WriteLine(privkey.ToXmlString(false));
System.Environment.Exit(5);
}
}
private static void LoadKeyFromFile()
{
using (var enc = new Duplicati.Library.Encryption.AESEncryption(keyfilepassword, new Dictionary<string, string>()))
using (var ms = new System.IO.MemoryStream())
using (var fs = System.IO.File.OpenRead(keyfile))
{
enc.Decrypt(fs, ms);
ms.Position = 0;
using (var sr = new System.IO.StreamReader(ms))
privkey.FromXmlString(sr.ReadToEnd());
}
}
public static int Main(string[] _args)
{
var args = new List<string>(_args);
var opts = Duplicati.Library.Utility.CommandLineParser.ExtractOptions(args);
opts.TryGetValue("input", out string inputfolder);
opts.TryGetValue("output", out outputfolder);
opts.TryGetValue("allow-new-key", out string allowNewKey);
opts.TryGetValue("keyfile", out keyfile);
opts.TryGetValue("manifest", out string manifestfile);
opts.TryGetValue("keyfile-password", out keyfilepassword);
var usedoptions = new [] { "allow-new-key", "input", "output", "keyfile", "manifest", "keyfile-password" };
if (string.IsNullOrWhiteSpace(inputfolder))
{
Console.WriteLine("Missing input folder");
return 4;
}
if (string.IsNullOrWhiteSpace(outputfolder))
{
Console.WriteLine("Missing output folder");
return 4;
}
if (string.IsNullOrWhiteSpace(keyfile))
{
Console.WriteLine("Missing keyfile");
return 4;
}
if (!System.IO.Directory.Exists(inputfolder))
{
Console.WriteLine("Input folder not found");
return 4;
}
if (string.IsNullOrWhiteSpace(keyfilepassword))
{
Console.WriteLine("Enter keyfile passphrase: ");
keyfilepassword = Console.ReadLine().Trim();
}
if (!System.IO.File.Exists(keyfile))
{
Console.WriteLine("Keyfile not found, creating new");
var newkey = RSA.Create().ToXmlString(true);
using (var enc = new Duplicati.Library.Encryption.AESEncryption(keyfilepassword, new Dictionary<string, string>()))
using (var fs = System.IO.File.OpenWrite(keyfile))
using (var ms = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(newkey)))
enc.Encrypt(ms, fs);
}
if (!System.IO.Directory.Exists(outputfolder))
System.IO.Directory.CreateDirectory(outputfolder);
privkey = (RSACryptoServiceProvider) RSA.Create();
LoadKeyFromFile();
if (!Boolean.TryParse(allowNewKey, out Boolean newKeyAllowed) || !newKeyAllowed)
{
CompareToManifestPublicKey();
}
Duplicati.Library.AutoUpdater.UpdateInfo updateInfo;
using (var fs = System.IO.File.OpenRead(manifestfile))
using (var sr = new System.IO.StreamReader(fs))
using (var jr = new Newtonsoft.Json.JsonTextReader(sr))
updateInfo = new Newtonsoft.Json.JsonSerializer().Deserialize<Duplicati.Library.AutoUpdater.UpdateInfo>(jr);
var isopts = new Dictionary<string, string>(opts, StringComparer.InvariantCultureIgnoreCase);
foreach (var usedopt in usedoptions)
{
isopts.Remove(usedopt);
}
foreach (var k in updateInfo.GetType().GetFields())
{
if (!isopts.ContainsKey(k.Name))
{
continue;
}
try
{
//Console.WriteLine("Setting {0} to {1}", k.Name, isopts[k.Name]);
if (k.FieldType == typeof(string[]))
k.SetValue(updateInfo, isopts[k.Name].Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
else if (k.FieldType == typeof(Version))
k.SetValue(updateInfo, new Version(isopts[k.Name]));
else if (k.FieldType == typeof(int))
k.SetValue(updateInfo, int.Parse(isopts[k.Name]));
else if (k.FieldType == typeof(long))
k.SetValue(updateInfo, long.Parse(isopts[k.Name]));
else
k.SetValue(updateInfo, isopts[k.Name]);
}
catch (Exception ex)
{
Console.WriteLine("Failed setting {0} to {1}: {2}", k.Name, isopts[k.Name], ex.Message);
}
isopts.Remove(k.Name);
}
foreach (var opt in isopts)
{
Console.WriteLine("Warning! unused option: {0} = {1}", opt.Key, opt.Value);
}
using (var tf = new Duplicati.Library.Utility.TempFile())
{
using (var fs = System.IO.File.OpenWrite(tf))
using (var tw = new System.IO.StreamWriter(fs))
new Newtonsoft.Json.JsonSerializer().Serialize(tw, updateInfo);
Duplicati.Library.AutoUpdater.UpdaterManager.CreateUpdatePackage(privkey, inputfolder, outputfolder, tf);
}
return 0;
}
}
}
|