using CPF.Mac.CoreFoundation; using CPF.Mac.Foundation; using CPF.Mac.ObjCRuntime; using System; namespace CPF.Mac.Security { public class SecRecord : IDisposable { internal NSMutableDictionary queryDict; public SecAccessible Accessible { get { return KeysAccessible.ToSecAccessible(Fetch(SecAttributeKey.AttrAccessible)); } set { SetValue(KeysAccessible.FromSecAccessible(value), SecAttributeKey.AttrAccessible); } } public NSDate CreationDate { get { return (NSDate)FetchObject(SecAttributeKey.AttrCreationDate); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(value, SecAttributeKey.AttrCreationDate); } } public NSDate ModificationDate { get { return (NSDate)FetchObject(SecAttributeKey.AttrModificationDate); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(value, SecAttributeKey.AttrModificationDate); } } public string Description { get { return FetchString(SecAttributeKey.AttrDescription); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecAttributeKey.AttrDescription); } } public string Comment { get { return FetchString(SecAttributeKey.AttrComment); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecAttributeKey.AttrComment); } } public int Creator { get { return FetchNumber(SecAttributeKey.AttrCreator).Int32Value; } set { SetValue(new NSNumber(value), SecAttributeKey.AttrCreator); } } public int CreatorType { get { return FetchNumber(SecAttributeKey.AttrType).Int32Value; } set { SetValue(new NSNumber(value), SecAttributeKey.AttrType); } } public string Label { get { return FetchString(SecAttributeKey.AttrLabel); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecAttributeKey.AttrLabel); } } public bool Invisible { get { return Fetch(SecAttributeKey.AttrIsInvisible) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecAttributeKey.AttrIsInvisible); } } public bool IsNegative { get { return Fetch(SecAttributeKey.AttrIsNegative) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecAttributeKey.AttrIsNegative); } } public string Account { get { return FetchString(SecAttributeKey.AttrAccount); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecAttributeKey.AttrAccount); } } public string Service { get { return FetchString(SecAttributeKey.AttrService); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecAttributeKey.AttrService); } } public NSData Generic { get { return FetchData(SecAttributeKey.AttrGeneric); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(value, SecAttributeKey.AttrGeneric); } } public string SecurityDomain { get { return FetchString(SecAttributeKey.AttrSecurityDomain); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecAttributeKey.AttrSecurityDomain); } } public string Server { get { return FetchString(SecAttributeKey.AttrServer); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecAttributeKey.AttrServer); } } public SecProtocol Protocol { get { return SecProtocolKeys.ToSecProtocol(Fetch(SecAttributeKey.AttrProtocol)); } set { SetValue(SecProtocolKeys.FromSecProtocol(value), SecAttributeKey.AttrProtocol); } } public SecAuthenticationType AuthenticationType { get { IntPtr intPtr = Fetch(SecAttributeKey.AttrAuthenticationType); if (intPtr == IntPtr.Zero) { return SecAuthenticationType.Default; } return KeysAuthenticationType.ToSecAuthenticationType(intPtr); } set { SetValue(KeysAuthenticationType.FromSecAuthenticationType(value), SecAttributeKey.AttrAuthenticationType); } } public int Port { get { return FetchNumber(SecAttributeKey.AttrPort).Int32Value; } set { SetValue(new NSNumber(value), SecAttributeKey.AttrPort); } } public string Path { get { return FetchString(SecAttributeKey.AttrPath); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecAttributeKey.AttrPath); } } public string Subject => FetchString(SecAttributeKey.AttrSubject); public NSData Issuer => FetchData(SecAttributeKey.AttrIssuer); public NSData SerialNumber => FetchData(SecAttributeKey.AttrSerialNumber); public NSData SubjectKeyID => FetchData(SecAttributeKey.AttrSubjectKeyID); public NSData PublicKeyHash => FetchData(SecAttributeKey.AttrPublicKeyHash); public NSNumber CertificateType => FetchNumber(SecAttributeKey.AttrCertificateType); public NSNumber CertificateEncoding => FetchNumber(SecAttributeKey.AttrCertificateEncoding); public SecKeyClass KeyClass { get { IntPtr value = Fetch(SecAttributeKey.AttrKeyClass); if (value == ClassKeys.Public) { return SecKeyClass.Public; } if (value == ClassKeys.Private) { return SecKeyClass.Private; } if (value == ClassKeys.Symmetric) { return SecKeyClass.Symmetric; } throw new Exception("Unknown value"); } set { IntPtr val; switch (value) { default: val = ClassKeys.Symmetric; break; case SecKeyClass.Private: val = ClassKeys.Private; break; case SecKeyClass.Public: val = ClassKeys.Public; break; } SetValue(val, SecAttributeKey.AttrKeyClass); } } public string ApplicationLabel { get { return FetchString(SecAttributeKey.AttrApplicationLabel); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecAttributeKey.AttrApplicationLabel); } } public bool IsPermanent { get { return Fetch(SecAttributeKey.AttrIsPermanent) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecAttributeKey.AttrIsPermanent); } } public NSData ApplicationTag { get { return FetchData(SecAttributeKey.AttrApplicationTag); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(value, SecAttributeKey.AttrApplicationTag); } } public SecKeyType KeyType { get { if (Fetch(SecAttributeKey.AttrKeyType) == KeyTypeKeys.RSA) { return SecKeyType.RSA; } return SecKeyType.EC; } set { SetValue((value == SecKeyType.RSA) ? KeyTypeKeys.RSA : KeyTypeKeys.EC, SecAttributeKey.AttrKeyType); } } public int KeySizeInBits { get { return FetchNumber(SecAttributeKey.AttrKeySizeInBits).Int32Value; } set { SetValue(new NSNumber(value), SecAttributeKey.AttrKeySizeInBits); } } public int EffectiveKeySize { get { return FetchNumber(SecAttributeKey.AttrEffectiveKeySize).Int32Value; } set { SetValue(new NSNumber(value), SecAttributeKey.AttrEffectiveKeySize); } } public bool CanEncrypt { get { return Fetch(SecAttributeKey.AttrCanEncrypt) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecAttributeKey.AttrCanEncrypt); } } public bool CanDecrypt { get { return Fetch(SecAttributeKey.AttrCanDecrypt) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecAttributeKey.AttrCanDecrypt); } } public bool CanDerive { get { return Fetch(SecAttributeKey.AttrCanDerive) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecAttributeKey.AttrCanDerive); } } public bool CanSign { get { return Fetch(SecAttributeKey.AttrCanSign) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecAttributeKey.AttrCanSign); } } public bool CanVerify { get { return Fetch(SecAttributeKey.AttrCanVerify) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecAttributeKey.AttrCanVerify); } } public bool CanWrap { get { return Fetch(SecAttributeKey.AttrCanWrap) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecAttributeKey.AttrCanWrap); } } public bool CanUnwrap { get { return Fetch(SecAttributeKey.AttrCanUnwrap) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecAttributeKey.AttrCanUnwrap); } } public string AccessGroup { get { return FetchString(SecAttributeKey.AttrAccessGroup); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecAttributeKey.AttrAccessGroup); } } public SecPolicy MatchPolicy { get { return new SecPolicy(Fetch(SecItem.MatchPolicy)); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(value.Handle, SecItem.MatchPolicy); } } public NSArray MatchItemList { get { return (NSArray)Runtime.GetNSObject(Fetch(SecItem.MatchItemList)); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(value, SecItem.MatchItemList); } } public NSData[] MatchIssuers { set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(NSArray.FromNSObjects(value), SecItem.MatchIssuers); } } public string MatchEmailAddressIfPresent { get { return FetchString(SecItem.MatchEmailAddressIfPresent); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecItem.MatchEmailAddressIfPresent); } } public string MatchSubjectContains { get { return FetchString(SecItem.MatchSubjectContains); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(new NSString(value), SecItem.MatchSubjectContains); } } public bool MatchCaseInsensitive { get { return Fetch(SecItem.MatchCaseInsensitive) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecItem.MatchCaseInsensitive); } } public bool MatchTrustedOnly { get { return Fetch(SecItem.MatchTrustedOnly) == CFBoolean.True.Handle; } set { SetValue(CFBoolean.FromBoolean(value).Handle, SecItem.MatchTrustedOnly); } } public NSDate MatchValidOnDate { get { return (NSDate)Runtime.GetNSObject(Fetch(SecItem.MatchValidOnDate)); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(value, SecItem.MatchValidOnDate); } } public NSData ValueData { get { return FetchData(SecItem.ValueData); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(value, SecItem.ValueData); } } public NSObject ValueRef { get { return FetchObject(SecItem.ValueRef); } set { if (value == null) { throw new ArgumentNullException("value"); } SetValue(value, SecItem.ValueRef); } } internal SecRecord(NSMutableDictionary dict) { queryDict = dict; } public SecRecord(SecKind secKind) { IntPtr intPtr = SecClass.FromSecKind(secKind); if (intPtr == SecClass.Identity) { queryDict = new NSMutableDictionary(); } else { queryDict = NSMutableDictionary.LowlevelFromObjectAndKey(intPtr, SecClass.SecClassKey); } } public SecRecord Clone() { return new SecRecord(NSMutableDictionary.FromDictionary(queryDict)); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } public virtual void Dispose(bool disposing) { if (queryDict != null && disposing) { queryDict.Dispose(); queryDict = null; } } ~SecRecord() { Dispose(disposing: false); } private IntPtr Fetch(IntPtr key) { return queryDict.LowlevelObjectForKey(key); } private NSObject FetchObject(IntPtr key) { return Runtime.GetNSObject(queryDict.LowlevelObjectForKey(key)); } private string FetchString(IntPtr key) { return (NSString)Runtime.GetNSObject(queryDict.LowlevelObjectForKey(key)); } private NSNumber FetchNumber(IntPtr key) { return (NSNumber)Runtime.GetNSObject(queryDict.LowlevelObjectForKey(key)); } private NSData FetchData(IntPtr key) { return (NSData)Runtime.GetNSObject(queryDict.LowlevelObjectForKey(key)); } private void SetValue(NSObject val, IntPtr key) { queryDict.LowlevelSetObject(val, key); } private void SetValue(IntPtr val, IntPtr key) { queryDict.LowlevelSetObject(val, key); } } }