static unsafe SecStatusCode AddInternetPassword(byte[] label, byte[] desc, SecAuthenticationType auth, byte[] user, byte[] passwd, SecProtocolType protocol, byte[] host, int port, byte[] path) { // Note: the following code does more-or-less the same as: //SecKeychainAddInternetPassword (CurrentKeychain, (uint) host.Length, host, 0, null, // (uint) user.Length, user, (uint) path.Length, path, (ushort) port, // protocol, auth, (uint) passwd.Length, passwd, ref item); fixed(byte *labelPtr = label, descPtr = desc, userPtr = user, hostPtr = host, pathPtr = path) { SecKeychainAttribute *attrs = stackalloc SecKeychainAttribute [8]; int *protoPtr = (int *)&protocol; int *authPtr = (int *)&auth; int *portPtr = &port; int n = 0; attrs[n++] = new SecKeychainAttribute(SecItemAttr.Label, (uint)label.Length, (IntPtr)labelPtr); if (desc != null) { attrs[n++] = new SecKeychainAttribute(SecItemAttr.Description, (uint)desc.Length, (IntPtr)descPtr); } attrs[n++] = new SecKeychainAttribute(SecItemAttr.Account, (uint)user.Length, (IntPtr)userPtr); attrs[n++] = new SecKeychainAttribute(SecItemAttr.Protocol, (uint)4, (IntPtr)protoPtr); attrs[n++] = new SecKeychainAttribute(SecItemAttr.AuthType, (uint)4, (IntPtr)authPtr); attrs[n++] = new SecKeychainAttribute(SecItemAttr.Server, (uint)host.Length, (IntPtr)hostPtr); attrs[n++] = new SecKeychainAttribute(SecItemAttr.Port, (uint)4, (IntPtr)portPtr); attrs[n++] = new SecKeychainAttribute(SecItemAttr.Path, (uint)path.Length, (IntPtr)pathPtr); SecKeychainAttributeList attrList = new SecKeychainAttributeList(n, (IntPtr)attrs); var result = SecKeychainItemCreateFromContent(SecItemClass.InternetPassword, &attrList, (uint)passwd.Length, passwd, CurrentKeychain, IntPtr.Zero, IntPtr.Zero); return(result); } }
static unsafe OSStatus ReplaceInternetPassword(IntPtr item, byte[] desc, byte[] passwd) { fixed(byte *descPtr = desc) { SecKeychainAttribute *attrs = stackalloc SecKeychainAttribute [1]; int n = 0; if (desc != null) { attrs[n++] = new SecKeychainAttribute(SecItemAttr.Description, (uint)desc.Length, (IntPtr)descPtr); } SecKeychainAttributeList attrList = new SecKeychainAttributeList(n, (IntPtr)attrs); return(SecKeychainItemModifyAttributesAndData(item, &attrList, (uint)passwd.Length, passwd)); } }
public static unsafe bool ContainsCertificate(X509Certificate2 certificate) { // Note: we don't have to use an alias attribute, it's just that it might be faster to use it (fewer certificates we have to compare raw data for) byte[] alias = Encoding.UTF8.GetBytes(GetCertificateCommonName(certificate)); IntPtr searchRef, itemRef; bool found = false; byte[] certData; OSStatus status; fixed(byte *aliasPtr = alias) { SecKeychainAttribute *attrs = stackalloc SecKeychainAttribute [1]; int n = 0; if (alias != null) { attrs[n++] = new SecKeychainAttribute(SecItemAttr.Alias, (uint)alias.Length, (IntPtr)aliasPtr); } SecKeychainAttributeList attrList = new SecKeychainAttributeList(n, (IntPtr)attrs); status = SecKeychainSearchCreateFromAttributes(CurrentKeychain, SecItemClass.Certificate, &attrList, out searchRef); if (status != OSStatus.Ok) { throw new Exception("Could not enumerate certificates from the keychain. Error:\n" + GetError(status)); } // we cache certificate.RawData to avoid unneccessary duplication (X509Certificate2.RawData clones the byte[] each time) certData = certificate.RawData; while (!found && (status = SecKeychainSearchCopyNext(searchRef, out itemRef)) == OSStatus.Ok) { SecItemClass itemClass = 0; IntPtr data = IntPtr.Zero; uint length = 0; status = SecKeychainItemCopyContent(itemRef, ref itemClass, IntPtr.Zero, ref length, ref data); if (status == OSStatus.Ok) { if (certData.Length == (int)length) { byte[] rawData = new byte[(int)length]; Marshal.Copy(data, rawData, 0, (int)length); found = true; for (int i = 0; i < rawData.Length; i++) { if (rawData[i] != certData[i]) { found = false; break; } } } SecKeychainItemFreeContent(IntPtr.Zero, data); } CFRelease(itemRef); } CFRelease(searchRef); } return(found); }