2 // httpcfg.cs: manages certificates used by HttpListener
5 // Gonzalo Paniagua Javier <gonzalo@novell.com>
6 // Sebastien Pouliot <sebastien@ximian.com>
8 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
13 using System
.Reflection
;
14 using System
.Security
.Cryptography
;
15 using System
.Security
.Cryptography
.X509Certificates
;
16 using Mono
.Security
.Authenticode
;
18 [assembly
: AssemblyTitle ("Mono Certificate Management for HttpListener use")]
19 [assembly
: AssemblyDescription ("Manage X.509 certificates to be used in HttpListener.")]
21 namespace Mono
.Tools
{
31 static string pvkfile
;
32 static string certfile
;
34 static string p12file;
39 static void Help (bool exit
)
41 Console
.WriteLine ("Usage is:\n" +
42 "\thttpcfg -add -port NN -cert CERT -pvk PVK\n" +
43 "\thttpcfg -del -port NN\n" +
49 static void ProcessArguments (string [] args
)
51 for (int i
= 0; i
< args
.Length
; i
++){
52 string arg
= args
[i
];
55 if (action
!= Action
.None
) {
56 Console
.Error
.WriteLine ("error: conflicting options.");
63 if (action
!= Action
.None
) {
64 Console
.Error
.WriteLine ("error: conflicting options.");
67 action
= Action
.Delete
;
70 if (action
!= Action
.None
) {
71 Console
.Error
.WriteLine ("error: conflicting options.");
78 Console
.Error
.WriteLine ("error: more than one port specified.");
83 port
= Convert
.ToUInt16 (args
[++i
]);
84 } catch (IndexOutOfRangeException
) {
85 Console
.Error
.WriteLine ("Error: no port specified.");
88 Console
.Error
.WriteLine ("Error: invalid port.");
94 if (p12file != null) {
95 Console.Error.WriteLine ("error: more than one p12 file specified.");
99 if (pvkfile != null || certfile != null) {
100 Console.Error.WriteLine ("error: use either -p12 or -pvk and -cert.");
103 p12file = args [++i];
107 if (pvkfile
!= null) {
108 Console
.Error
.WriteLine ("error: more than one PVK file specified.");
113 if (p12file != null) {
114 Console.Error.WriteLine ("error: use either -p12 or -pvk and -cert.");
118 pvkfile
= args
[++i
];
121 if (certfile
!= null) {
122 Console
.Error
.WriteLine ("error: more than one CER file specified.");
127 if (p12file != null) {
128 Console.Error.WriteLine ("error: use either -p12 or -pvk and -cert.");
132 certfile
= args
[++i
];
136 if (passwd != null) {
137 Console.Error.WriteLine ("error: more than one password specified.");
144 Console
.Error
.WriteLine ("error: Unknown argument: {0}", arg
);
150 if (action
== Action
.None
) {
151 Console
.Error
.WriteLine ("error: no action specified.");
155 if ((pvkfile
!= null && certfile
== null) || (pvkfile
== null && certfile
!= null)) {
156 Console
.Error
.WriteLine ("error: -cert and -pvk must be used.");
160 if (action
!= Action
.List
&& port
== 0) {
161 Console
.Error
.WriteLine ("error: -port is missing or bogus.");
165 //if (action == Action.Delete && (pvkfile != null || certfile != null || p12file != null)) {
166 if (action
== Action
.Delete
&& (pvkfile
!= null || certfile
!= null)) {
167 Console
.Error
.WriteLine ("error: -delete only expects a -port option.");
173 static void AddP12 (string path, string filename, string password, ushort port)
175 X509Certificate2 x509 = null;
177 x509 = new X509Certificate2 (filename, password);
178 } catch (Exception e) {
179 Console.Error.WriteLine ("error loading certificate [{0}]", e.Message);
183 string target_cert = Path.Combine (path, String.Format ("{0}.cer", port));
184 if (File.Exists (target_cert)) {
185 Console.Error.WriteLine ("error: there is already a certificate for that port.");
188 string target_pvk = Path.Combine (path, String.Format ("{0}.pvk", port));
189 if (File.Exists (target_pvk)) {
190 Console.Error.WriteLine ("error: there is already a certificate for that port.");
194 using (Stream cer = File.OpenWrite (target_cert)) {
195 byte [] raw = x509.RawData;
196 cer.Write (raw, 0, raw.Length);
199 x509.PrivateKey.Save (target_pvk);
203 static void AddCertPvk (string path
, string cert
, string pvk
, ushort port
)
206 X509Certificate2 x509
= new X509Certificate2 (cert
);
207 x509
.PrivateKey
= PrivateKey
.CreateFromFile (pvk
).RSA
;
208 } catch (Exception e
) {
209 Console
.Error
.WriteLine ("error loading certificate or private key [{0}]", e
.Message
);
213 string target_cert
= Path
.Combine (path
, String
.Format ("{0}.cer", port
));
214 if (File
.Exists (target_cert
)) {
215 Console
.Error
.WriteLine ("error: there is already a certificate for that port.");
218 string target_pvk
= Path
.Combine (path
, String
.Format ("{0}.pvk", port
));
219 if (File
.Exists (target_pvk
)) {
220 Console
.Error
.WriteLine ("error: there is already a certificate for that port.");
223 File
.Copy (cert
, target_cert
);
224 File
.Copy (pvk
, target_pvk
);
227 static void Delete (string path
, ushort port
)
229 string pattern
= String
.Format ("{0}.*", port
);
230 string [] files
= Directory
.GetFiles (path
, pattern
);
231 foreach (string f
in files
) {
234 } catch (Exception e
) {
235 Console
.Error
.WriteLine ("error removing file {0} [{1}].", f
, e
.Message
);
240 static void List (string path
)
242 string [] files
= Directory
.GetFiles (path
, "*");
243 foreach (string f
in files
) {
244 if (f
.EndsWith (".cer")) {
245 X509Certificate2 x509
= new X509Certificate2 (f
);
246 Console
.WriteLine ("Port: {0} Thumbprint: {1}", Path
.GetFileNameWithoutExtension (f
), x509
.Thumbprint
);
251 static int Main (string[] args
)
254 ProcessArguments (args
);
255 } catch (IndexOutOfRangeException
) {
256 Console
.Error
.WriteLine ("error: missing argument.");
260 if (action
== Action
.None
) {
264 string dirname
= Environment
.GetFolderPath (Environment
.SpecialFolder
.ApplicationData
);
265 string path
= Path
.Combine (dirname
, ".mono");
266 path
= Path
.Combine (path
, "httplistener");
267 if (false == Directory
.Exists (path
)) {
269 Directory
.CreateDirectory (path
);
270 } catch (Exception e
) {
271 Console
.Error
.WriteLine ("error: creating directory {0} [{1}]", path
, e
.Message
);
280 AddP12 (path, p12file, passwd, port);
283 AddCertPvk (path
, certfile
, pvkfile
, port
);