Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastien Pouliot <sebastien@ximian.com>2004-12-14 04:58:24 +0300
committerSebastien Pouliot <sebastien@ximian.com>2004-12-14 04:58:24 +0300
commit52dcb75610d713953ef0d79bcd143943159ccc70 (patch)
tree0e6488b716293284dc16c8e829ba6c175ed54397 /mcs/tools/security/certmgr.cs
parent346bef5d92cf86e6a97469b65dab85c763fc8c28 (diff)
2004-12-13 Sebastien Pouliot <sebastien@ximian.com>
* certmgr.cs: Add a new -ssl action to download and add the certificates from an SSL connection into thr right stores. svn path=/trunk/mcs/; revision=37709
Diffstat (limited to 'mcs/tools/security/certmgr.cs')
-rw-r--r--mcs/tools/security/certmgr.cs213
1 files changed, 188 insertions, 25 deletions
diff --git a/mcs/tools/security/certmgr.cs b/mcs/tools/security/certmgr.cs
index 5f5862bf11e..432dd7fb4ef 100644
--- a/mcs/tools/security/certmgr.cs
+++ b/mcs/tools/security/certmgr.cs
@@ -10,12 +10,16 @@
using System;
using System.Collections;
using System.IO;
+using System.Net;
+using System.Net.Sockets;
using System.Reflection;
using System.Security.Cryptography;
+using SSCX = System.Security.Cryptography.X509Certificates;
using System.Text;
using Mono.Security.Authenticode;
using Mono.Security.X509;
+using Mono.Security.Protocol.Tls;
[assembly: AssemblyTitle ("Mono Certificate Manager")]
[assembly: AssemblyDescription ("Add/Remove certificates and CRL from stores")]
@@ -31,11 +35,13 @@ namespace Mono.Tools {
static private void Help ()
{
- Console.WriteLine ("Usage: certmgr [action] [object type] [options] store [filename]{0}", Environment.NewLine);
+ Console.WriteLine ("Usage: certmgr [action] [object type] [options] store [filename]", Environment.NewLine);
+ Console.WriteLine (" or: certmgr -ssl [options] url{0}", Environment.NewLine);
Console.WriteLine ("actions");
Console.WriteLine ("\t-add\tAdd a certificate, CRL or CTL to specified store");
Console.WriteLine ("\t-del\tRemove a certificate, CRL or CTL to specified store");
Console.WriteLine ("\t-put\tCopy a certificate, CRL or CTL from a store to a file");
+ Console.WriteLine ("\t-ssl\tDownload and add certificates from an SSL session");
Console.WriteLine ("object types");
Console.WriteLine ("\t-c\tadd/del/put certificates");
Console.WriteLine ("\t-crl\tadd/del/put certificate revocation lists");
@@ -44,6 +50,7 @@ namespace Mono.Tools {
Console.WriteLine ("\t-m\tuse the machine certificate store (default to user)");
Console.WriteLine ("\t-v\tverbose mode (display status for every steps)");
Console.WriteLine ("\t-?\th[elp]\tDisplay this help message");
+ Console.WriteLine ();
}
static string GetCommand (string arg)
@@ -68,7 +75,8 @@ namespace Mono.Tools {
None,
Add,
Delete,
- Put
+ Put,
+ Ssl
}
static Action GetAction (string arg)
@@ -84,6 +92,10 @@ namespace Mono.Tools {
case "PUT":
action = Action.Put;
break;
+ case "SSL":
+ case "TLS":
+ action = Action.Ssl;
+ break;
}
return action;
}
@@ -263,28 +275,163 @@ namespace Mono.Tools {
}*/
}
+ static X509CertificateCollection GetCertificatesFromSslSession (string url)
+ {
+ Uri uri = new Uri (url);
+ IPHostEntry host = Dns.Resolve (uri.Host);
+ IPAddress ip = host.AddressList [0];
+ Socket socket = new Socket (ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+ socket.Connect (new IPEndPoint (ip, uri.Port));
+ NetworkStream ns = new NetworkStream (socket, false);
+ SslClientStream ssl = new SslClientStream (ns, uri.Host, false, Mono.Security.Protocol.Tls.SecurityProtocolType.Default, null);
+ ssl.ServerCertValidationDelegate += new CertificateValidationCallback (CertificateValidation);
+
+ try {
+ // we don't really want to write to the server (as we don't know
+ // the protocol it using) but we must send something to be sure the
+ // SSL handshake is done (so we receive the X.509 certificates).
+ StreamWriter sw = new StreamWriter (ssl);
+ sw.WriteLine (Environment.NewLine);
+ sw.Flush ();
+ socket.Poll (30000, SelectMode.SelectRead);
+ }
+ finally {
+ socket.Close ();
+ }
+
+ // we need a little reflection magic to get this information
+ PropertyInfo pi = typeof (SslClientStream).GetProperty ("ServerCertificates", BindingFlags.Instance | BindingFlags.NonPublic);
+ if (pi == null) {
+ Console.WriteLine ("Sorry but you need a newer version of Mono.Security.dll to use this feature.");
+ return null;
+ }
+ return (X509CertificateCollection) pi.GetValue (ssl, null);
+ }
+
+ static bool CertificateValidation (SSCX.X509Certificate certificate, int[] certificateErrors)
+ {
+ // the main reason to download it is that it's not trusted
+ return true;
+ // OTOH we ask user confirmation before adding certificates into the stores
+ }
+
+ static void Ssl (string host, bool machine, bool verbose)
+ {
+ if (verbose) {
+ Console.WriteLine ("Importing certificates from '{0}' into the {1} stores.",
+ host, machine ? "machine" : "user");
+ }
+ int n=0;
+
+ X509CertificateCollection coll = GetCertificatesFromSslSession (host);
+ if (coll != null) {
+ X509Store store = null;
+ // start by the end (root) so we can stop adding them anytime afterward
+ for (int i = coll.Count - 1; i >= 0; i--) {
+ X509Certificate x509 = coll [i];
+ bool selfsign = false;
+ bool failed = false;
+ try {
+ selfsign = x509.IsSelfSigned;
+ }
+ catch {
+ // sadly it's hard to interpret old certificates with MD2
+ // without manually changing the machine.config file
+ failed = true;
+ }
+
+ if (selfsign) {
+ // this is a root
+ store = GetStoreFromName (X509Stores.Names.TrustedRoot, machine);
+ } else if (i == 0) {
+ // server certificate isn't (generally) an intermediate CA
+ store = GetStoreFromName (X509Stores.Names.OtherPeople, machine);
+ } else {
+ // all other certificates should be intermediate CA
+ store = GetStoreFromName (X509Stores.Names.IntermediateCA, machine);
+ }
+
+ Console.WriteLine ("{0}{1} X.509 Certificate v{2}",
+ Environment.NewLine,
+ selfsign ? "Self-signed " : String.Empty,
+ x509.Version);
+ Console.WriteLine (" Issued from: {0}", x509.IssuerName);
+ Console.WriteLine (" Issued to: {0}", x509.SubjectName);
+ Console.WriteLine (" Valid from: {0}", x509.ValidFrom);
+ Console.WriteLine (" Valid until: {0}", x509.ValidUntil);
+
+ if (!x509.IsCurrent)
+ Console.WriteLine (" *** WARNING: Certificate isn't current ***");
+ if ((i > 0) && !selfsign) {
+ X509Certificate signer = coll [i-1];
+ bool signed = false;
+ try {
+ if (signer.RSA != null) {
+ signed = x509.VerifySignature (signer.RSA);
+ } else if (signer.DSA != null) {
+ signed = x509.VerifySignature (signer.RSA);
+ } else {
+ Console.WriteLine (" *** WARNING: Couldn't not find who signed this certificate ***");
+ signed = true; // skip next warning
+ }
+
+ if (!signed)
+ Console.WriteLine (" *** WARNING: Certificate signature is INVALID ***");
+ }
+ catch {
+ failed = true;
+ }
+ }
+ if (failed) {
+ Console.WriteLine (" *** ERROR: Couldn't decode certificate properly ***");
+ Console.WriteLine (" *** try 'man certmgr' for additional help or report to bugzilla.ximian.com ***");
+ break;
+ }
+
+ if (store.Certificates.Contains (x509)) {
+ Console.WriteLine ("This certificate is already in the {0} store.", store.Name);
+ } else {
+ Console.Write ("Import this certificate into the {0} store ?", store.Name);
+ string answer = Console.ReadLine ().ToUpper ();
+ if ((answer == "YES") || (answer == "Y")) {
+ store.Import (x509);
+ n++;
+ } else {
+ if (verbose) {
+ Console.WriteLine ("Certificate not imported into store {0}.",
+ store.Name);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ Console.WriteLine ();
+ if (n == 0) {
+ Console.WriteLine ("No certificate were added to the stores.");
+ } else {
+ Console.WriteLine ("{0} certificate{1} added to the stores.",
+ n, (n == 1) ? String.Empty : "s");
+ }
+ }
+
[STAThread]
static void Main (string[] args)
{
Header ();
- if (args.Length < 4) {
+ if (args.Length < 2) {
Help ();
return;
}
Action action = GetAction (args [0]);
- ObjectType type = GetObjectType (args [1]);
-
- if ((action == Action.None) || (type == ObjectType.None)) {
- Help ();
- return;
- }
- if (type == ObjectType.CTL) {
- Console.WriteLine ("CTL are not supported");
- return;
- }
+ ObjectType type = ObjectType.None;
- int n = 2;
+ int n = 1;
+ if (action != Action.Ssl)
+ type = GetObjectType (args [n++]);
+
bool verbose = (GetCommand (args [n]) == "V");
if (verbose)
n++;
@@ -292,17 +439,30 @@ namespace Mono.Tools {
if (machine)
n++;
- string storeName = args [n++];
- X509Store store = GetStoreFromName (storeName, machine);
- if (store == null) {
- Console.WriteLine ("Invalid Store: {0}", storeName);
- Console.WriteLine ("Valid stores are: {0}, {1}, {2}, {3} and {4}",
- X509Stores.Names.Personal,
- X509Stores.Names.OtherPeople,
- X509Stores.Names.IntermediateCA,
- X509Stores.Names.TrustedRoot,
- X509Stores.Names.Untrusted);
- return;
+ X509Store store = null;
+ string storeName = null;
+ if (action != Action.Ssl) {
+ if ((action == Action.None) || (type == ObjectType.None)) {
+ Help ();
+ return;
+ }
+ if (type == ObjectType.CTL) {
+ Console.WriteLine ("CTL are not supported");
+ return;
+ }
+
+ storeName = args [n++];
+ store = GetStoreFromName (storeName, machine);
+ if (store == null) {
+ Console.WriteLine ("Invalid Store: {0}", storeName);
+ Console.WriteLine ("Valid stores are: {0}, {1}, {2}, {3} and {4}",
+ X509Stores.Names.Personal,
+ X509Stores.Names.OtherPeople,
+ X509Stores.Names.IntermediateCA,
+ X509Stores.Names.TrustedRoot,
+ X509Stores.Names.Untrusted);
+ return;
+ }
}
string file = args [n];
@@ -319,6 +479,9 @@ namespace Mono.Tools {
case Action.Put:
Put (type, store, file, verbose);
break;
+ case Action.Ssl:
+ Ssl (file, machine, verbose);
+ break;
default:
throw new NotSupportedException (action.ToString ());
}