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
;
33 static string p12file
;
37 static void Help (bool exit
)
39 Console
.WriteLine ("Usage is:\n" +
40 "\thttpcfg -add -port NN [-cert CERT -pvk PVK] [-p12 P12 -pwd PASSWORD]\n" +
41 "\thttpcfg -del -port NN\n" +
47 static void ProcessArguments (string [] args
)
49 for (int i
= 0; i
< args
.Length
; i
++){
50 string arg
= args
[i
];
53 if (action
!= Action
.None
) {
54 Console
.Error
.WriteLine ("error: conflicting options.");
61 if (action
!= Action
.None
) {
62 Console
.Error
.WriteLine ("error: conflicting options.");
65 action
= Action
.Delete
;
68 if (action
!= Action
.None
) {
69 Console
.Error
.WriteLine ("error: conflicting options.");
76 Console
.Error
.WriteLine ("error: more than one port specified.");
81 port
= Convert
.ToUInt16 (args
[++i
]);
82 } catch (IndexOutOfRangeException
) {
83 Console
.Error
.WriteLine ("Error: no port specified.");
86 Console
.Error
.WriteLine ("Error: invalid port.");
92 if (p12file
!= null) {
93 Console
.Error
.WriteLine ("error: more than one p12 file specified.");
97 if (pvkfile
!= null || certfile
!= null) {
98 Console
.Error
.WriteLine ("error: use either -p12 or -pvk and -cert.");
101 p12file
= args
[++i
];
105 if (pvkfile
!= null) {
106 Console
.Error
.WriteLine ("error: more than one PVK file specified.");
110 if (p12file
!= null) {
111 Console
.Error
.WriteLine ("error: use either -p12 or -pvk and -cert.");
115 pvkfile
= args
[++i
];
118 if (certfile
!= null) {
119 Console
.Error
.WriteLine ("error: more than one CER file specified.");
123 if (p12file
!= null) {
124 Console
.Error
.WriteLine ("error: use either -p12 or -pvk and -cert.");
128 certfile
= args
[++i
];
132 if (passwd
!= null) {
133 Console
.Error
.WriteLine ("error: more than one password specified.");
140 Console
.Error
.WriteLine ("error: Unknown argument: {0}", arg
);
146 if (action
== Action
.None
) {
147 Console
.Error
.WriteLine ("error: no action specified.");
151 if ((pvkfile
!= null && certfile
== null) || (pvkfile
== null && certfile
!= null)) {
152 Console
.Error
.WriteLine ("error: -cert and -pvk must be used.");
156 if (action
!= Action
.List
&& port
== 0) {
157 Console
.Error
.WriteLine ("error: -port is missing or bogus.");
161 if (action
== Action
.Delete
&& (pvkfile
!= null || certfile
!= null || p12file
!= null)) {
162 //if (action == Action.Delete && (pvkfile != null || certfile != null)) {
163 Console
.Error
.WriteLine ("error: -delete only expects a -port option.");
169 static void AddP12 (string path
, string filename
, string password
, ushort port
)
171 X509Certificate2 x509
= null;
173 x509
= new X509Certificate2 (filename
, password
);
174 } catch (Exception e
) {
175 Console
.Error
.WriteLine ("error loading certificate [{0}]", e
.Message
);
179 string target_cert
= Path
.Combine (path
, String
.Format ("{0}.cer", port
));
180 if (File
.Exists (target_cert
)) {
181 Console
.Error
.WriteLine ("error: there is already a certificate for that port.");
184 string target_pvk
= Path
.Combine (path
, String
.Format ("{0}.pvk", port
));
185 if (File
.Exists (target_pvk
)) {
186 Console
.Error
.WriteLine ("error: there is already a certificate for that port.");
190 using (Stream cer
= File
.OpenWrite (target_cert
)) {
191 byte [] raw
= x509
.RawData
;
192 cer
.Write (raw
, 0, raw
.Length
);
195 PrivateKey pvk
= new PrivateKey();
196 pvk
.RSA
= x509
.PrivateKey
as RSA
;
197 pvk
.Save(target_pvk
);
201 static void AddCertPvk (string path
, string cert
, string pvk
, ushort port
)
204 X509Certificate2 x509
= new X509Certificate2 (cert
);
205 x509
.PrivateKey
= PrivateKey
.CreateFromFile (pvk
).RSA
;
206 } catch (Exception e
) {
207 Console
.Error
.WriteLine ("error loading certificate or private key [{0}]", e
.Message
);
211 string target_cert
= Path
.Combine (path
, String
.Format ("{0}.cer", port
));
212 if (File
.Exists (target_cert
)) {
213 Console
.Error
.WriteLine ("error: there is already a certificate for that port.");
216 string target_pvk
= Path
.Combine (path
, String
.Format ("{0}.pvk", port
));
217 if (File
.Exists (target_pvk
)) {
218 Console
.Error
.WriteLine ("error: there is already a certificate for that port.");
221 File
.Copy (cert
, target_cert
);
222 File
.Copy (pvk
, target_pvk
);
225 static void Delete (string path
, ushort port
)
227 string pattern
= String
.Format ("{0}.*", port
);
228 string [] files
= Directory
.GetFiles (path
, pattern
);
229 foreach (string f
in files
) {
232 } catch (Exception e
) {
233 Console
.Error
.WriteLine ("error removing file {0} [{1}].", f
, e
.Message
);
238 static void List (string path
)
240 string [] files
= Directory
.GetFiles (path
, "*");
241 foreach (string f
in files
) {
242 if (f
.EndsWith (".cer")) {
243 X509Certificate2 x509
= new X509Certificate2 (f
);
244 Console
.WriteLine ("Port: {0} Thumbprint: {1}", Path
.GetFileNameWithoutExtension (f
), x509
.Thumbprint
);
249 static int Main (string[] args
)
252 ProcessArguments (args
);
253 } catch (IndexOutOfRangeException
) {
254 Console
.Error
.WriteLine ("error: missing argument.");
258 if (action
== Action
.None
) {
262 string dirname
= Environment
.GetFolderPath (Environment
.SpecialFolder
.ApplicationData
);
263 string path
= Path
.Combine (dirname
, ".mono");
264 path
= Path
.Combine (path
, "httplistener");
265 if (false == Directory
.Exists (path
)) {
267 Directory
.CreateDirectory (path
);
268 } catch (Exception e
) {
269 Console
.Error
.WriteLine ("error: creating directory {0} [{1}]", path
, e
.Message
);
277 AddP12 (path
, p12file
, passwd
, port
);
279 AddCertPvk (path
, certfile
, pvkfile
, port
);