/*
* 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;
}
}