/* * Mentalis.org Security Library * * Copyright © 2002-2005, The KPD-Team * All rights reserved. * http://www.mentalis.org/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Neither the name of the KPD-Team, nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.IO; using System.Text; using System.Collections; using System.Security; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Runtime.InteropServices; using System.Collections.Specialized; using Org.Mentalis.Security.Cryptography; namespace Org.Mentalis.Security.Certificates { /// /// Represents a Relative Distinguished Name (RDN) of a . /// public class DistinguishedName { /// /// Initializes a new instance of the class. /// public DistinguishedName() { m_List = new ArrayList(); } /// /// Initializes a new instance of the class. /// /// A instance that's used to initialize the object. internal DistinguishedName(CertificateNameInfo cni) : this() { Initialize(cni); } /// /// Initializes a new instance of the class. /// /// A pointer to a buffer that's used to initialize the object. /// The length of the buffer. /// Could not decode the buffer. internal DistinguishedName(IntPtr input, int length) : this() { int size = 0; SspiProvider.CryptDecodeObject(SecurityConstants.PKCS_7_ASN_ENCODING | SecurityConstants.X509_ASN_ENCODING, new IntPtr(SecurityConstants.X509_UNICODE_NAME), input, length, 0, IntPtr.Zero, ref size); if (size <= 0) throw new CertificateException("Unable to decode the name of the certificate."); IntPtr buffer = Marshal.AllocHGlobal(size); if (SspiProvider.CryptDecodeObject(SecurityConstants.PKCS_7_ASN_ENCODING | SecurityConstants.X509_ASN_ENCODING, new IntPtr(SecurityConstants.X509_UNICODE_NAME), input, length, 0, buffer, ref size) == 0) throw new CertificateException("Unable to decode the name of the certificate."); try { CertificateNameInfo cni = (CertificateNameInfo)Marshal.PtrToStructure(buffer, typeof(CertificateNameInfo)); Initialize(cni); } catch (CertificateException ce) { throw ce; } catch (Exception e) { throw new CertificateException("Could not get the certificate distinguished name.", e); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } /// /// Initializes a new instance of the class with a given instance. /// /// The CertificateNameInfo instance to initialize from. /// An error occurs while initializeing the DistinguishedName object. private void Initialize(CertificateNameInfo cni) { if (cni.cRDN <= 0) throw new CertificateException("Certificate does not have a subject relative distinguished name."); RelativeDistinguishedName cr; RdnAttribute cra; for(int i = 0; i < cni.cRDN; i++) { cr = (RelativeDistinguishedName)Marshal.PtrToStructure(new IntPtr(cni.rgRDN.ToInt64() + i * Marshal.SizeOf(typeof(RelativeDistinguishedName))), typeof(RelativeDistinguishedName)); for(int j = 0; j < cr.cRDNAttr; j++) { cra = (RdnAttribute)Marshal.PtrToStructure(new IntPtr(cr.rgRDNAttr.ToInt64() + j * Marshal.SizeOf(typeof(RdnAttribute))), typeof(RdnAttribute)); m_List.Add(new NameAttribute(Marshal.PtrToStringAnsi(cra.pszObjId), Marshal.PtrToStringUni(cra.pbData))); } } } /// /// Adds a to the end of the list. /// /// The NameAttribute to be added to the end of the list. /// The index at which the value has been added. public int Add(NameAttribute attribute) { return m_List.Add(attribute); } /// /// Gets or sets the element at the specified index. /// /// The zero-based index of the element to get or set. /// is less than zero -or- is equal to or greater than . public NameAttribute this[int index] { get { return (NameAttribute)m_List[index]; } set { m_List[index] = value; } } /// /// Gets the number of elements actually contained in the list. /// /// The number of elements actually contained in the list. public int Count { get { return m_List.Count; } } /// /// Removes all elements from the list. /// public void Clear() { m_List.Clear(); } /// /// Determines whether an element is in the list. /// /// The to locate in the list. /// true if item is found in the list; otherwise, false. public bool Contains(NameAttribute value) { return m_List.Contains(value); } /// /// Searches for the specified Object and returns the zero-based index of the first occurrence within the entire list. /// /// The to locate in the list. /// The zero-based index of the first occurrence of value within the entire list, if found; otherwise, -1. public int IndexOf(NameAttribute value) { return m_List.IndexOf(value); } /// /// Searches for an Object with the specified Object identifier and returns the zero-based index of the first occurrence within the entire list. /// /// The object identifier to search for. /// The zero-based index of the first occurrence of value within the entire list, if found; otherwise, -1. public int IndexOf(string oid) { for(int i = 0; i < m_List.Count; i++) { if (((NameAttribute)m_List[i]).ObjectID == oid) return i; } return -1; } /// /// Inserts an element into the list at the specified index. /// /// The zero-based index at which value should be inserted. /// The to insert. public void Insert(int index, NameAttribute value) { m_List.Insert(index, value); } /// /// Removes the first occurrence of a specific element from the list. /// /// The to remove from the list. public void Remove(NameAttribute value) { m_List.Remove(value); } /// /// Removes the element at the specified index of the list. /// /// The zero-based index of the element to remove. public void RemoveAt(int index) { m_List.RemoveAt(index); } /// /// The internal list instance. /// private ArrayList m_List; } }