Exemplo n.º 1
0
        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);
            }
        }
Exemplo n.º 2
0
        private static byte[] GetAccountNameAttributeData(IntPtr itemRef)
        {
            IntPtr tagArrayPtr    = IntPtr.Zero;
            IntPtr formatArrayPtr = IntPtr.Zero;
            IntPtr attrListPtr    = IntPtr.Zero; // SecKeychainAttributeList

            try
            {
                // Extract the user name by querying for the item's 'account' attribute
                tagArrayPtr = Marshal.AllocCoTaskMem(sizeof(SecKeychainAttrType));
                Marshal.Copy(new[] { (int)SecKeychainAttrType.AccountItem }, 0, tagArrayPtr, 1);

                formatArrayPtr = Marshal.AllocCoTaskMem(sizeof(CssmDbAttributeFormat));
                Marshal.Copy(new[] { (int)CssmDbAttributeFormat.String }, 0, formatArrayPtr, 1);

                var attributeInfo = new SecKeychainAttributeInfo
                {
                    Count  = 1,
                    Tag    = tagArrayPtr,
                    Format = formatArrayPtr,
                };

                ThrowOnError(
                    SecKeychainItemCopyAttributesAndData(
                        itemRef, ref attributeInfo,
                        IntPtr.Zero, out attrListPtr, out var _, IntPtr.Zero)
                    );

                SecKeychainAttributeList attrList = Marshal.PtrToStructure <SecKeychainAttributeList>(attrListPtr);
                Debug.Assert(attrList.Count == 1);

                byte[] attrListArrayBytes = NativeMethods.ToByteArray(
                    attrList.Attributes, Marshal.SizeOf <SecKeychainAttribute>() * attrList.Count);

                SecKeychainAttribute[] attributes = NativeMethods.ToStructArray <SecKeychainAttribute>(attrListArrayBytes);
                Debug.Assert(attributes.Length == 1);

                return(NativeMethods.ToByteArray(attributes[0].Data, attributes[0].Length));
            }
            finally
            {
                if (tagArrayPtr != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(tagArrayPtr);
                }

                if (formatArrayPtr != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(formatArrayPtr);
                }

                if (attrListPtr != IntPtr.Zero)
                {
                    SecKeychainItemFreeAttributesAndData(attrListPtr, IntPtr.Zero);
                }
            }
        }
Exemplo n.º 3
0
        private static byte[] GetAccountNameAttributeData(IntPtr itemRef)
        {
            IntPtr tagArrayPtr    = IntPtr.Zero;
            IntPtr formatArrayPtr = IntPtr.Zero;
            IntPtr attrListPtr    = IntPtr.Zero; // SecKeychainAttributeList

            try
            {
                // Extract the user name by querying for the item's 'account' attribute
                tagArrayPtr = Marshal.AllocHGlobal(sizeof(SecKeychainAttrType));
                Marshal.WriteInt32(tagArrayPtr, (int)SecKeychainAttrType.AccountItem);

                formatArrayPtr = Marshal.AllocHGlobal(sizeof(CssmDbAttributeFormat));
                Marshal.WriteInt32(formatArrayPtr, (int)CssmDbAttributeFormat.String);

                var attributeInfo = new SecKeychainAttributeInfo
                {
                    Count  = 1,
                    Tag    = tagArrayPtr,
                    Format = formatArrayPtr,
                };

                ThrowIfError(
                    SecKeychainItemCopyAttributesAndData(
                        itemRef, ref attributeInfo,
                        IntPtr.Zero, out attrListPtr, out _, IntPtr.Zero)
                    );

                SecKeychainAttributeList attrList = Marshal.PtrToStructure <SecKeychainAttributeList>(attrListPtr);
                Debug.Assert(attrList.Count == 1, "Only expecting a list structure containing one attribute to be returned");

                SecKeychainAttribute attribute = Marshal.PtrToStructure <SecKeychainAttribute>(attrList.Attributes);

                return(InteropUtils.ToByteArray(attribute.Data, attribute.Length));
            }
            finally
            {
                if (tagArrayPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(tagArrayPtr);
                }

                if (formatArrayPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(formatArrayPtr);
                }

                if (attrListPtr != IntPtr.Zero)
                {
                    SecKeychainItemFreeAttributesAndData(attrListPtr, IntPtr.Zero);
                }
            }
        }
Exemplo n.º 4
0
        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));
            }
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 6
0
		static unsafe OSStatus 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 item = IntPtr.Zero;
				var result = SecKeychainItemCreateFromContent (SecItemClass.InternetPassword, &attrList, (uint) passwd.Length, passwd, CurrentKeychain, IntPtr.Zero, ref item);
				CFRelease (item);

				return result;
			}
		}
Exemplo n.º 7
0
		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);
			}
		}
Exemplo n.º 8
0
		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;
		}
Exemplo n.º 9
0
		static extern unsafe OSStatus SecKeychainItemModifyAttributesAndData (IntPtr itemRef, SecKeychainAttributeList *attrList, uint length, byte [] data);
Exemplo n.º 10
0
		static extern unsafe OSStatus SecKeychainItemCopyAttributesAndData (IntPtr itemRef, SecKeychainAttributeInfo* info, ref SecItemClass itemClass,
		                                                                    SecKeychainAttributeList** attrList, ref uint length, ref IntPtr outData);
Exemplo n.º 11
0
		static extern unsafe OSStatus SecKeychainItemCreateFromContent (SecItemClass itemClass, SecKeychainAttributeList *attrList,
		                                                                uint passwordLength, byte[] password, IntPtr keychain,
		                                                                IntPtr initialAccess, ref IntPtr itemRef);
Exemplo n.º 12
0
		static extern unsafe OSStatus SecKeychainSearchCreateFromAttributes (IntPtr keychainOrArray, SecItemClass itemClass, SecKeychainAttributeList *attrList, out IntPtr searchRef);
Exemplo n.º 13
0
		public static unsafe void AddInternetPassword (Uri uri, string password)
		{
			byte[] path = Encoding.UTF8.GetBytes (string.Join (string.Empty, uri.Segments).Substring (1)); // don't include the leading '/'
			byte[] user = Encoding.UTF8.GetBytes (Uri.UnescapeDataString (uri.UserInfo));
			byte[] passwd = Encoding.UTF8.GetBytes (password);
			byte[] host = Encoding.UTF8.GetBytes (uri.Host);
			var auth = GetSecAuthenticationType (uri.Query);
			var protocol = GetSecProtocolType (uri.Scheme);
			IntPtr passwordPtr = IntPtr.Zero;
			IntPtr itemRef = IntPtr.Zero;
			uint passwordLength = 0;
			int port = uri.Port;
			byte[] desc = null;

			if (auth == SecAuthenticationType.HTMLForm)
				desc = WebFormPassword;

			// See if there is already a password there for this uri
			var result = SecKeychainFindInternetPassword (IntPtr.Zero, (uint) host.Length, host, 0, null,
			                                              (uint) user.Length, user, (uint) path.Length, path, (ushort) port,
			                                              protocol, auth, out passwordLength, out passwordPtr, ref itemRef);

			if (result == OSStatus.Ok) {
				// If there is, replace it with the new one
				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);

					result = SecKeychainItemModifyAttributesAndData (itemRef, &attrList, (uint) passwd.Length, passwd);
					CFRelease (itemRef);
				}
			} else {
				// Otherwise add a new entry with the password
//				result = SecKeychainAddInternetPassword (IntPtr.Zero, (uint) uri.Host.Length, uri.Host, 0, null,
//			                                             (uint) user.Length, user, (uint) path.Length, path, (ushort) uri.Port,
//				                                         (int) protocol, (int) auth, (uint) passwordBytes.Length, passwordBytes, ref itemRef);

				var label = Encoding.UTF8.GetBytes (string.Format ("{0} ({1})", uri.Host, Uri.UnescapeDataString (uri.UserInfo)));

				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);

					itemRef = IntPtr.Zero;
					result = SecKeychainItemCreateFromContent (SecItemClass.InternetPassword, &attrList, (uint) passwd.Length, passwd, IntPtr.Zero, IntPtr.Zero, ref itemRef);
					CFRelease (itemRef);
				}
			}
			
			if (result != OSStatus.Ok)
				throw new Exception ("Could not add internet password to keychain: " + GetError (result));
		}