/// <summary> /// Unregisters object identifier from OID registration database. /// </summary> /// <param name="value">Specifies the object identifier value.</param> /// <param name="group">Specifies the OID group from which the OID is removed. </param> /// <param name="deleteFromDirectory"> /// Specifies whether to perform registration removal from Active Directory. If Active Directory is unavailable, /// the method will attempt to unregister OID from a local OID registration database. /// </param> /// <exception cref="ArgumentNullException"><strong>value</strong> parameter is null or empty.</exception> /// <returns> /// <strong>True</strong> if OID or OIDs were unregistered successfully. If specified OID information is not /// registered, the method returns <strong>False</strong>. An exception is thrown when caller do not have /// appropriate permissions. See <strong>Remarks</strong> section for additional details. /// </returns> /// <remarks> /// <strong>Permissions:</strong> a caller must have local administrator permissions in order to remove OID /// registration from local OID database. When <strong>deleteFromDirectory</strong> is set to <strong>True</strong>, /// a caller must be a member of <strong>Enterprise Admins</strong> group or have delegated permissions on a OID /// container in Active Directory. OID container location is /// <i>CN=OID, CN=Public Key Services, CN=Services,CN=Configuration, {Configuration naming context}</i>. /// </remarks> public static Boolean Unregister(String value, OidGroupEnum group, Boolean deleteFromDirectory) { if (String.IsNullOrEmpty(value)) { throw new ArgumentNullException("value"); } List <Oid2> oids = new List <Oid2>(); if (group == OidGroupEnum.AllGroups) { try { oids.AddRange(GetAllOids(value, deleteFromDirectory)); } catch { return(false); } } else { oids.Add(new Oid2(value, group, deleteFromDirectory)); if (String.IsNullOrEmpty(oids[0].Value)) { return(false); } } if (!deleteFromDirectory || !ActiveDirectory.Ping()) { return(unregisterLocal(oids)); } List <Int32> valid = new List <Int32>(new[] { 0, 7, 8, 9 }); if (oids.Where(oid => !String.IsNullOrEmpty(oid.DistinguishedName)).Any(oid => oid.OidGroup != @group && @group != OidGroupEnum.AllGroups)) { return(false); } return(valid.Contains((Int32)@group) && unregisterDS(oids[0].Value, @group)); }
static bool unregisterDS(string oid, OidGroupEnum group) { String cn = computeOidHash(oid); DirectoryEntry child = new DirectoryEntry("LDAP://CN=" + cn + ",CN=OID,CN=Public Key Services,CN=Services," + ActiveDirectory.ConfigContext); switch (group) { case OidGroupEnum.ApplicationPolicy: if ((Int32)child.Properties["flags"].Value != 3) { return(false); } break; case OidGroupEnum.IssuancePolicy: if ((Int32)child.Properties["flags"].Value != 2) { return(false); } break; case OidGroupEnum.CertificateTemplate: if ((Int32)child.Properties["flags"].Value != 1) { return(false); } break; } DirectoryEntry entry = new DirectoryEntry("LDAP://CN=OID,CN=Public Key Services,CN=Services," + ActiveDirectory.ConfigContext); entry.Children.Remove(child); entry.CommitChanges(); return(true); }
/// <summary> /// Initializes a new instance of the Oid2 class using the specified Oid friendly name or value, OID registration group and search conditions. /// </summary> /// <param name="oid">Specifies the object identifier friendly name or value to search.</param> /// <param name="group">Specifies the OID registration group to search.</param> /// <param name="searchInDirectory">Specifies whether to search for an object identifier in Active Directory. If the machine is not /// domain-joined, an OID is searched by using local registration information.</param> public Oid2(String oid, OidGroupEnum group, Boolean searchInDirectory) { try { CryptoConfig.EncodeOID(oid); searchBy = "ByValue"; } catch { searchBy = "ByName"; } if (Environment.OSVersion.Version.Major >= 6) { _cng = true; } if (searchInDirectory) { if (ActiveDirectory.Ping()) { initializeDS(oid, group); } else { initializeLocal(oid, group); } } else { initializeLocal(oid, group); } }
static void registerDS(Oid oid, OidGroupEnum group, CultureInfo localeId, String cpsUrl) { String cn = computeOidHash(oid.Value); DirectoryEntry entry = new DirectoryEntry("LDAP://CN=OID,CN=Public Key Services,CN=Services," + ActiveDirectory.ConfigContext); entry = entry.Children.Add("CN=" + cn, "msPKI-Enterprise-Oid"); switch (group) { case OidGroupEnum.ApplicationPolicy: entry.Properties["flags"].Value = 3; break; case OidGroupEnum.IssuancePolicy: entry.Properties["flags"].Value = 2; if (!String.IsNullOrEmpty(cpsUrl)) { entry.Properties["msPKI-OID-CPS"].Value = cpsUrl; } break; } entry.Properties["msPKI-Cert-Template-OID"].Value = oid.Value; if (localeId == null) { entry.Properties["displayName"].Value = oid.FriendlyName; } else { entry.Properties["msPKI-OIDLocalizedName"].Value = localeId.LCID + "," + oid.FriendlyName; } entry.CommitChanges(); }
static Boolean unregisterDS(String oid, OidGroupEnum group) { String cn = computeOidHash(oid); String ldapPath = $"CN={cn},{_baseDsPath}"; Int32 flags = (Int32)ActiveDirectory.GetEntryProperty(ldapPath, ActiveDirectory.PropFlags); switch (group) { case OidGroupEnum.ApplicationPolicy: if (flags != 3) { return(false); } break; case OidGroupEnum.IssuancePolicy: if (flags != 2) { return(false); } break; case OidGroupEnum.CertificateTemplate: if (flags != 1) { return(false); } break; } ActiveDirectory.RemoveEntry(ldapPath); return(true); }
void initializeLocal(String oid, OidGroupEnum group) { IntPtr ptr, oidptr; if (searchBy.ToLower() == "byvalue") { oidptr = Marshal.StringToHGlobalAnsi(oid); ptr = Crypt32.CryptFindOIDInfo(Wincrypt.CRYPT_OID_INFO_OID_KEY, oidptr, (UInt32)group); } else { oidptr = Marshal.StringToHGlobalUni(oid); ptr = Crypt32.CryptFindOIDInfo(Wincrypt.CRYPT_OID_INFO_NAME_KEY, oidptr, (UInt32)group); } if (ptr.Equals(IntPtr.Zero)) { return; } if (_cng) { Wincrypt.CRYPT_OID_INFO OidInfo = (Wincrypt.CRYPT_OID_INFO)Marshal.PtrToStructure(ptr, typeof(Wincrypt.CRYPT_OID_INFO)); FriendlyName = OidInfo.pwszName; Value = OidInfo.pszOID; OidGroup = (OidGroupEnum)OidInfo.dwGroupId; } else { Wincrypt.CRYPT_OID_INFO_Win2k3 OidInfo = (Wincrypt.CRYPT_OID_INFO_Win2k3)Marshal.PtrToStructure(ptr, typeof(Wincrypt.CRYPT_OID_INFO_Win2k3)); FriendlyName = OidInfo.pwszName; Value = OidInfo.pszOID; OidGroup = (OidGroupEnum)OidInfo.dwGroupId; } Marshal.FreeHGlobal(oidptr); }
static void registerDS(Oid oid, OidGroupEnum group, CultureInfo localeId, String cpsUrl) { String cn = computeOidHash(oid.Value); String entryDN = ActiveDirectory.AddEntry( _baseDsPath, $"CN={cn}", ActiveDirectory.SchemaObjectIdentifier); switch (group) { case OidGroupEnum.ApplicationPolicy: ActiveDirectory.SetEntryProperty(entryDN, ActiveDirectory.PropFlags, 3); break; case OidGroupEnum.IssuancePolicy: ActiveDirectory.SetEntryProperty(entryDN, ActiveDirectory.PropFlags, 2); if (!String.IsNullOrEmpty(cpsUrl)) { ActiveDirectory.SetEntryProperty(entryDN, ActiveDirectory.PropCpsOid, cpsUrl); } break; } ActiveDirectory.SetEntryProperty(entryDN, ActiveDirectory.PropCertTemplateOid, oid.Value); if (localeId == null) { ActiveDirectory.SetEntryProperty(entryDN, ActiveDirectory.PropDisplayName, oid.FriendlyName); } else { ActiveDirectory.SetEntryProperty(entryDN, ActiveDirectory.PropLocalizedOid, $"{localeId.LCID},{oid.FriendlyName}"); } }
/// <summary> /// Initializes a new instance of the Oid2 class using the specified Oid friendly name or value, OID registration group and search conditions. /// </summary> /// <param name="oid">Specifies the object identifier friendly name or value to search.</param> /// <param name="group">Specifies the OID registration group to search.</param> /// <param name="searchInDirectory">Specifies whether to search for an object identifier in Active Directory. If the machine is not /// domain-joined, an OID is searched by using local registration information.</param> public Oid2(String oid, OidGroupEnum group, Boolean searchInDirectory) { var flatOid = new Oid(oid); try { // try to validate if input OID contains OID value instead of friendly name Asn1Utils.EncodeObjectIdentifier(flatOid); oid = flatOid.Value; _searchBy = "ByValue"; } catch { _searchBy = "ByName"; } if (Environment.OSVersion.Version.Major >= 6) { _cng = true; } if (searchInDirectory) { if (DsUtils.Ping()) { initializeDS(oid, group); } else { initializeLocal(oid, group); } } else { initializeLocal(oid, group); } }
static void registerCNG(Oid oid, OidGroupEnum group) { Wincrypt.CRYPT_OID_INFO oidinfo = new Wincrypt.CRYPT_OID_INFO { cbSize = Marshal.SizeOf(typeof(Wincrypt.CRYPT_OID_INFO)), pszOID = oid.Value, pwszName = oid.FriendlyName, dwGroupId = (Int32)@group }; if (!Crypt32.CryptRegisterOIDInfo(oidinfo, 0)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
static void registerLocal(Oid oid, OidGroupEnum group) { Boolean CNG = Environment.OSVersion.Version.Major >= 6; if (CNG) { registerCNG(oid, @group); } else { registerLegacy(oid, @group); } }
/// <summary> /// Registers object identifier in the OID database, either, local or in Active Directory. /// </summary> /// <param name="value">An object identifier value to register.</param> /// <param name="friendlyName">A friendly name associated with the object identifier.</param> /// <param name="group">Specifies the OID group where specified object identifier should be registered.</param> /// <param name="writeInDirectory">Specifies, whether object is registered locally or in Active Directory.</param> /// <param name="localeId"> /// Specifies the locale ID. This parameter can be used to provide localized friendly name. This parameter can /// be used only when <strong>writeInDirectory</strong> is set to <strong>True</strong> in other cases it is /// silently ignored. /// </param> /// <param name="cpsUrl"> /// Specifies the URL to a <i>certificate practice statement</i> (<strong>CPS</strong>) location. /// </param> /// <exception cref="ArgumentNullException"> /// <strong>value</strong> and/or <strong>friendlyName</strong> is null or empty. /// </exception> /// <exception cref="ArgumentException"> /// Specified OID group is not supported. See <strong>Remarks</strong> section for more details. /// </exception> /// <exception cref="InvalidDataException"><strong>value</strong> parameter is not object idnetifier value.</exception> /// <exception cref="NotSupportedException"> /// A caller chose OID registration in Active Directory, however, the current computer is not a member of any /// Active Directory domain. /// </exception> /// <exception cref="InvalidOperationException"> /// An object identifier is already registered. /// </exception> /// <remarks> /// <para> /// <strong>Permissions:</strong> for this method to succeed, the caller must be a member of the local /// administrators group (if <strong>writeInDirectory</strong> is set to <strong>False</strong>) or /// be a member of <strong>Enterprise Admins</strong> group or has delegated write permissions on the /// <strong>OID</strong> container in Active Directory. OID container location is /// <i>CN=OID, CN=Public Key Services, CN=Services,CN=Configuration, {Configuration naming context}</i>. /// </para> /// <para> /// A newly registered OID is not resolvable by an application immediately. You may need to restart an application /// to allow new OID lookup. /// </para> /// <para> /// When <strong>writeInDirectory</strong> is set to <strong>True</strong>, <strong>group</strong> parameter /// is limited only to one of the following value: <strong>ApplicationPolicy</strong>,<strong>IssuancePolicy</strong> /// and <strong>CertificateTemplate</strong>. Other OID groups are not allowed to be stored in Active Directory. /// </para> /// </remarks> /// <returns>Registered object identifier.</returns> public static Oid2 Register(String value, String friendlyName, OidGroupEnum group, Boolean writeInDirectory, CultureInfo localeId, String cpsUrl = null) { if (String.IsNullOrEmpty(value)) { throw new ArgumentNullException(nameof(value)); } if (String.IsNullOrEmpty(friendlyName)) { throw new ArgumentNullException(nameof(friendlyName)); } try { Asn1Utils.EncodeObjectIdentifier(new Oid(value)); } catch { throw new InvalidDataException("The value is not valid OID string."); } String cn = null; if (writeInDirectory) { if (!DsUtils.Ping()) { throw new NotSupportedException("Workgroup environment is not supported."); } if (!String.IsNullOrEmpty(new Oid2(value, group, true).DistinguishedName)) { throw new InvalidOperationException("The object already exist."); } List <Int32> exclude = new List <Int32>(new[] { 0, 1, 2, 3, 4, 5, 6, 9, 10 }); if (exclude.Contains((Int32)group)) { throw new ArgumentException("The OID group is not valid."); } registerDS(new Oid(value, friendlyName), group, localeId, cpsUrl); cn = "CN=" + computeOidHash(value) + ",CN=OID," + DsUtils.ConfigContext; } else { registerLocal(new Oid(value, friendlyName), group); } return(new Oid2 { FriendlyName = friendlyName, Value = value, OidGroup = group, DistinguishedName = cn }); }
void initializeDS(String oid, OidGroupEnum group) { List <Int32> exclude = new List <Int32>(new[] { 1, 2, 3, 4, 5, 6, 10 }); if (exclude.Contains((Int32)group)) { initializeLocal(oid, group); return; } Boolean found = false; String oidvalue = oid; if (searchBy.ToLower() == "byname") { Oid oidobj = new Oid(oid); if (String.IsNullOrEmpty(oidobj.Value)) { return; } oidvalue = oidobj.Value; } String cn = computeOidHash(oidvalue); DirectoryEntry entry = new DirectoryEntry("LDAP://" + "CN=" + cn + ",CN=OID,CN=Public Key Services,CN=Services," + ActiveDirectory.ConfigContext); try { if (String.IsNullOrEmpty(entry.Path)) { return; } if ((String)entry.Properties["cn"].Value == cn) { found = true; DistinguishedName = (String)entry.Properties["distinguishedName"].Value; flags = (Int32)entry.Properties["flags"].Value; FriendlyName = (String)entry.Properties["displayName"].Value; Value = oidvalue; switch (flags) { case 1: if (group != OidGroupEnum.AllGroups && group != OidGroupEnum.CertificateTemplate) { throw new Exception("Oid type mismatch."); } OidGroup = OidGroupEnum.CertificateTemplate; break; case 2: if (group != OidGroupEnum.AllGroups && group != OidGroupEnum.IssuancePolicy) { throw new Exception("Oid type mismatch."); } OidGroup = OidGroupEnum.IssuancePolicy; if (entry.Properties["msPKI-OID-CPS"].Value == null) { break; } try { Object[] cps = (Object[])entry.Properties["msPKI-OID-CPS"].Value; urls = cps.Cast <String>().ToArray(); } catch { urls = new[] { (String)entry.Properties["msPKI-OID-CPS"].Value }; } break; case 3: if (group != OidGroupEnum.AllGroups && group != OidGroupEnum.ApplicationPolicy) { throw new Exception("Oid type mismatch."); } OidGroup = OidGroupEnum.ApplicationPolicy; break; } } } catch { FriendlyName = String.Empty; Value = String.Empty; OidGroup = OidGroupEnum.AllGroups; DistinguishedName = String.Empty; } if (!found) { initializeLocal(oid, group); } }
void initializeDS(String oid, OidGroupEnum group) { List <Int32> exclude = new List <Int32>(new[] { 1, 2, 3, 4, 5, 6, 10 }); if (exclude.Contains((Int32)group)) { initializeLocal(oid, group); return; } Boolean found = false; String oidvalue = oid; if (_searchBy.ToLower() == "byname") { Oid oidobj = new Oid(oid); if (String.IsNullOrEmpty(oidobj.Value)) { return; } oidvalue = oidobj.Value; } String cn = computeOidHash(oidvalue); String ldapPath = $"CN={cn},{_baseDsPath}"; try { IDictionary <String, Object> oidInDs = ActiveDirectory.GetEntryProperties( ldapPath, ActiveDirectory.PropFlags, ActiveDirectory.PropDN, ActiveDirectory.PropDisplayName, ActiveDirectory.PropCpsOid); found = true; DistinguishedName = (String)oidInDs[ActiveDirectory.PropDN]; flags = (Int32)oidInDs[ActiveDirectory.PropFlags]; FriendlyName = (String)oidInDs[ActiveDirectory.PropDisplayName]; switch (flags) { case 1: if (group != OidGroupEnum.AllGroups && group != OidGroupEnum.CertificateTemplate) { throw new Exception("Oid type mismatch."); } OidGroup = OidGroupEnum.CertificateTemplate; break; case 2: if (group != OidGroupEnum.AllGroups && group != OidGroupEnum.IssuancePolicy) { throw new Exception("Oid type mismatch."); } OidGroup = OidGroupEnum.IssuancePolicy; if (oidInDs[ActiveDirectory.PropCpsOid] == null) { break; } try { Object[] cps = (Object[])oidInDs[ActiveDirectory.PropCpsOid]; urls = cps.Cast <String>().ToArray(); } catch { urls = new[] { (String)oidInDs[ActiveDirectory.PropCpsOid] }; } break; case 3: if (group != OidGroupEnum.AllGroups && group != OidGroupEnum.ApplicationPolicy) { throw new Exception("Oid type mismatch."); } OidGroup = OidGroupEnum.ApplicationPolicy; break; } } catch { FriendlyName = String.Empty; Value = String.Empty; OidGroup = OidGroupEnum.AllGroups; DistinguishedName = String.Empty; } if (!found) { initializeLocal(oid, group); } }
/// <summary> /// Initializes a new instance of the Oid2 class from an existing <see cref="Oid"/> object, OID registration group and search conditions. /// </summary> /// <param name="oid">Specifies the object identifier friendly name or value to search.</param> /// <param name="group">Specifies the OID registration group to search.</param> /// <param name="searchInDirectory">Specifies whether to search for an object identifier in Active Directory. If the machine is not /// domain-joined, an OID is searched by using local registration information.</param> public Oid2(Oid oid, OidGroupEnum group, Boolean searchInDirectory) : this(oid.Value, group, searchInDirectory) { }