diff --git a/mcs/class/System/Mono.AppleTls/AppleCertificateHelper.cs b/mcs/class/System/Mono.AppleTls/AppleCertificateHelper.cs index d26abe989b..3eb18f9c7c 100644 --- a/mcs/class/System/Mono.AppleTls/AppleCertificateHelper.cs +++ b/mcs/class/System/Mono.AppleTls/AppleCertificateHelper.cs @@ -36,14 +36,63 @@ namespace Mono.AppleTls */ var certificate2 = certificate as X509Certificate2; if (certificate2 != null) +#if MONOTOUCH return SecIdentity.Import (certificate2); +#else + return SecImportExport.ItemImport (certificate2); +#endif /* - * Otherwise, we require the private key to be in the keychain. + * Reading Certificates from the Mac Keychain + * ========================================== + * + * Reading the private key from the keychain is a new feature introduced with + * AppleTls on XamMac and iOS. On Desktop Mono, this new feature has several + * known issues and it also did not received any testing yet. We go back to the old + * way of doing things, which is to explicitly provide an X509Certificate2 with a + * private key. + * + * Keychain Dialog Popups + * ====================== + * + * When using Xamarin.Mac or Xamarin.iOS, we try to search the keychain + * for the certificate and private key. + * + * On Xamarin.iOS, this is easy because each app has its own keychain. + * + * On Xamarin.Mac, the .app package needs to be trusted via code-sign + * to get permission to access the user's keychain. [FIXME: I still have to + * research how to actually do that.] Without this, you will get a popup + * message each time, asking you whether you want to allow the app to access + * the keychain, but you can make these go away by selecting "Trust always". + * + * On Desktop Mono, this is problematic because selecting "Trust always" + * give the 'mono' binary (and thus everything you'll ever run with Mono) + * permission to retrieve the private key from the keychain. + * + * This code would also trigger constant keychain popup messages, + * which could only be suppressed by granting full trust. It also makes it + * impossible to run Mono in headless mode. + * + * SecIdentityCreate + * ================= + * + * To avoid these problems, we are currently using an undocumented API + * called SecIdentityRef() to avoid using the Mac keychain whenever a + * X509Certificate2 with a private key is used. + * + * On iOS and XamMac, you can still provide the X509Certificate without + * a private key - in this case, a keychain search will be performed (and you + * may get a popup message on XamMac). */ + +#if MOBILE using (var secCert = new SecCertificate (certificate)) { return SecKeyChain.FindIdentity (secCert, true); } +#else + return null; +#endif } public static SecIdentity GetIdentity (X509Certificate certificate, out SecCertificate[] intermediateCerts) diff --git a/mcs/class/System/Mono.AppleTls/Certificate.cs b/mcs/class/System/Mono.AppleTls/Certificate.cs index e78a85f174..1bcf1b2937 100644 --- a/mcs/class/System/Mono.AppleTls/Certificate.cs +++ b/mcs/class/System/Mono.AppleTls/Certificate.cs @@ -31,6 +31,7 @@ #if SECURITY_DEP && MONO_FEATURE_APPLETLS using System; +using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using Mono.Net; @@ -198,6 +199,8 @@ namespace Mono.AppleTls { static readonly CFString ImportExportPassphase; static readonly CFString ImportItemIdentity; + static readonly CFString ImportExportAccess; + static readonly CFString ImportExportKeychain; static SecIdentity () { @@ -208,6 +211,8 @@ namespace Mono.AppleTls { try { ImportExportPassphase = CFObject.GetStringConstant (handle, "kSecImportExportPassphrase"); ImportItemIdentity = CFObject.GetStringConstant (handle, "kSecImportItemIdentity"); + ImportExportAccess = CFObject.GetStringConstant (handle, "kSecImportExportAccess"); + ImportExportKeychain = CFObject.GetStringConstant (handle, "kSecImportExportKeychain"); } finally { CFObject.dlclose (handle); } @@ -240,16 +245,46 @@ namespace Mono.AppleTls { } } - public static SecIdentity Import (byte[] data, string password) + internal class ImportOptions + { +#if !MONOTOUCH + public SecAccess Access { + get; set; + } + public SecKeyChain KeyChain { + get; set; + } +#endif + } + + static CFDictionary CreateImportOptions (CFString password, ImportOptions options = null) + { + if (options == null) + return CFDictionary.FromObjectAndKey (password.Handle, ImportExportPassphase.Handle); + + var items = new List> (); + items.Add (new Tuple (ImportExportPassphase.Handle, password.Handle)); + +#if !MONOTOUCH + if (options.KeyChain != null) + items.Add (new Tuple (ImportExportKeychain.Handle, options.KeyChain.Handle)); + if (options.Access != null) + items.Add (new Tuple (ImportExportAccess.Handle, options.Access.Handle)); +#endif + + return CFDictionary.FromKeysAndObjects (items); + } + + public static SecIdentity Import (byte[] data, string password, ImportOptions options = null) { if (data == null) throw new ArgumentNullException ("data"); if (string.IsNullOrEmpty (password)) // SecPKCS12Import() doesn't allow empty passwords. throw new ArgumentException ("password"); using (var pwstring = CFString.Create (password)) - using (var options = CFDictionary.FromObjectAndKey (pwstring.Handle, ImportExportPassphase.Handle)) { + using (var optionDict = CreateImportOptions (pwstring, options)) { CFDictionary [] array; - SecStatusCode result = SecImportExport.ImportPkcs12 (data, options, out array); + SecStatusCode result = SecImportExport.ImportPkcs12 (data, optionDict, out array); if (result != SecStatusCode.Success) throw new InvalidOperationException (result.ToString ()); @@ -257,7 +292,7 @@ namespace Mono.AppleTls { } } - public static SecIdentity Import (X509Certificate2 certificate) + public static SecIdentity Import (X509Certificate2 certificate, ImportOptions options = null) { if (certificate == null) throw new ArgumentNullException ("certificate"); @@ -270,7 +305,7 @@ namespace Mono.AppleTls { */ var password = Guid.NewGuid ().ToString (); var pkcs12 = certificate.Export (X509ContentType.Pfx, password); - return Import (pkcs12, password); + return Import (pkcs12, password, options); } ~SecIdentity () @@ -301,6 +336,7 @@ namespace Mono.AppleTls { partial class SecKey : INativeObject, IDisposable { internal IntPtr handle; + internal IntPtr owner; public SecKey (IntPtr handle, bool owns = false) { @@ -309,6 +345,17 @@ namespace Mono.AppleTls { CFObject.CFRetain (handle); } + /* + * SecItemImport() returns a SecArrayRef. We need to free the array, not the items inside it. + * + */ + internal SecKey (IntPtr handle, IntPtr owner) + { + this.handle = handle; + this.owner = owner; + CFObject.CFRetain (owner); + } + [DllImport (AppleTlsContext.SecurityLibrary, EntryPoint="SecKeyGetTypeID")] public extern static IntPtr GetTypeID (); @@ -331,11 +378,73 @@ namespace Mono.AppleTls { protected virtual void Dispose (bool disposing) { - if (handle != IntPtr.Zero){ + if (owner != IntPtr.Zero) { + CFObject.CFRelease (owner); + owner = handle = IntPtr.Zero; + } else if (handle != IntPtr.Zero) { CFObject.CFRelease (handle); handle = IntPtr.Zero; } } } + +#if !MONOTOUCH + class SecAccess : INativeObject, IDisposable { + internal IntPtr handle; + + public SecAccess (IntPtr handle, bool owns = false) + { + this.handle = handle; + if (!owns) + CFObject.CFRetain (handle); + } + + ~SecAccess () + { + Dispose (false); + } + + public IntPtr Handle { + get { + return handle; + } + } + + [DllImport (AppleTlsContext.SecurityLibrary)] + extern static /* OSStatus */ SecStatusCode SecAccessCreate (/* CFStringRef */ IntPtr descriptor, /* CFArrayRef */ IntPtr trustedList, /* SecAccessRef _Nullable * */ out IntPtr accessRef); + + public static SecAccess Create (string descriptor) + { + var descriptorHandle = CFString.Create (descriptor); + if (descriptorHandle == null) + throw new InvalidOperationException (); + + try { + IntPtr accessRef; + var result = SecAccessCreate (descriptorHandle.Handle, IntPtr.Zero, out accessRef); + if (result != SecStatusCode.Success) + throw new InvalidOperationException (result.ToString ()); + + return new SecAccess (accessRef, true); + } finally { + descriptorHandle.Dispose (); + } + } + + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + protected virtual void Dispose (bool disposing) + { + if (handle != IntPtr.Zero) { + CFObject.CFRelease (handle); + handle = IntPtr.Zero; + } + } + } +#endif } #endif diff --git a/mcs/class/System/Mono.AppleTls/Enums.cs b/mcs/class/System/Mono.AppleTls/Enums.cs index 3ec2107673..e71e94ff14 100644 --- a/mcs/class/System/Mono.AppleTls/Enums.cs +++ b/mcs/class/System/Mono.AppleTls/Enums.cs @@ -9,8 +9,386 @@ namespace Mono.AppleTls { // values are defined in Security.framework/Headers/SecBase.h enum SecStatusCode { Success = 0, - DuplicateItem = -25299, + Unimplemented = -4, + DiskFull = -34, + IO = -36, + OpWr = -49, Param = -50, + WritePermissions = -61, + Allocate = -108, + UserCanceled = -128, + BadReq = -909, + InternalComponent = -2070, + CoreFoundationUnknown = -4960, + NotAvailable = -25291, + ReadOnly = -25292, + AuthFailed = -25293, + NoSuchKeyChain = -25294, + InvalidKeyChain = -25295, + DuplicateKeyChain = -25296, + DuplicateItem = -25299, + ItemNotFound = -25300, + InteractionNotAllowed = -25308, + Decode = -26275, + DuplicateCallback = -25297, + InvalidCallback = -25298, + BufferTooSmall = -25301, + DataTooLarge = -25302, + NoSuchAttribute = -25303, + InvalidItemRef = -25304, + InvalidSearchRef = -25305, + NoSuchClass = -25306, + NoDefaultKeychain = -25307, + ReadOnlyAttribute = -25309, + WrongSecVersion = -25310, + KeySizeNotAllowed = -25311, + NoStorageModule = -25312, + NoCertificateModule = -25313, + NoPolicyModule = -25314, + InteractionRequired = -25315, + DataNotAvailable = -25316, + DataNotModifiable = -25317, + CreateChainFailed = -25318, + InvalidPrefsDomain = -25319, + InDarkWake = -25320, + ACLNotSimple = -25240, + PolicyNotFound = -25241, + InvalidTrustSetting = -25242, + NoAccessForItem = -25243, + InvalidOwnerEdit = -25244, + TrustNotAvailable = -25245, + UnsupportedFormat = -25256, + UnknownFormat = -25257, + KeyIsSensitive = -25258, + MultiplePrivateKeys = -25259, + PassphraseRequired = -25260, + InvalidPasswordRef = -25261, + InvalidTrustSettings = -25262, + NoTrustSettings = -25263, + Pkcs12VerifyFailure = -25264, + NotSigner = -26267, + ServiceNotAvailable = -67585, + InsufficientClientID = -67586, + DeviceReset = -67587, + DeviceFailed = -67588, + AppleAddAppACLSubject = -67589, + ApplePublicKeyIncomplete = -67590, + AppleSignatureMismatch = -67591, + AppleInvalidKeyStartDate = -67592, + AppleInvalidKeyEndDate = -67593, + ConversionError = -67594, + AppleSSLv2Rollback = -67595, + QuotaExceeded = -67596, + FileTooBig = -67597, + InvalidDatabaseBlob = -67598, + InvalidKeyBlob = -67599, + IncompatibleDatabaseBlob = -67600, + IncompatibleKeyBlob = -67601, + HostNameMismatch = -67602, + UnknownCriticalExtensionFlag = -67603, + NoBasicConstraints = -67604, + NoBasicConstraintsCA = -67605, + InvalidAuthorityKeyID = -67606, + InvalidSubjectKeyID = -67607, /* The subject key ID is not valid. */ + InvalidKeyUsageForPolicy = -67608, /* The key usage is not valid for the specified policy. */ + InvalidExtendedKeyUsage = -67609, /* The extended key usage is not valid. */ + InvalidIDLinkage = -67610, /* The ID linkage is not valid. */ + PathLengthConstraintExceeded = -67611, /* The path length constraint was exceeded. */ + InvalidRoot = -67612, /* The root or anchor certificate is not valid. */ + CRLExpired = -67613, /* The CRL has expired. */ + CRLNotValidYet = -67614, /* The CRL is not yet valid. */ + CRLNotFound = -67615, /* The CRL was not found. */ + CRLServerDown = -67616, /* The CRL server is down. */ + CRLBadURI = -67617, /* The CRL has a bad Uniform Resource Identifier. */ + UnknownCertExtension = -67618, /* An unknown certificate extension was encountered. */ + UnknownCRLExtension = -67619, /* An unknown CRL extension was encountered. */ + CRLNotTrusted = -67620, /* The CRL is not trusted. */ + CRLPolicyFailed = -67621, /* The CRL policy failed. */ + IDPFailure = -67622, /* The issuing distribution point was not valid. */ + SMIMEEmailAddressesNotFound = -67623, /* An email address mismatch was encountered. */ + SMIMEBadExtendedKeyUsage = -67624, /* The appropriate extended key usage for SMIME was not found. */ + SMIMEBadKeyUsage = -67625, /* The key usage is not compatible with SMIME. */ + SMIMEKeyUsageNotCritical = -67626, /* The key usage extension is not marked as critical. */ + SMIMENoEmailAddress = -67627, /* No email address was found in the certificate. */ + SMIMESubjAltNameNotCritical = -67628, /* The subject alternative name extension is not marked as critical. */ + SSLBadExtendedKeyUsage = -67629, /* The appropriate extended key usage for SSL was not found. */ + OCSPBadResponse = -67630, /* The OCSP response was incorrect or could not be parsed. */ + OCSPBadRequest = -67631, /* The OCSP request was incorrect or could not be parsed. */ + OCSPUnavailable = -67632, /* OCSP service is unavailable. */ + OCSPStatusUnrecognized = -67633, /* The OCSP server did not recognize this certificate. */ + EndOfData = -67634, /* An end-of-data was detected. */ + IncompleteCertRevocationCheck = -67635, /* An incomplete certificate revocation check occurred. */ + NetworkFailure = -67636, /* A network failure occurred. */ + OCSPNotTrustedToAnchor = -67637, /* The OCSP response was not trusted to a root or anchor certificate. */ + RecordModified = -67638, /* The record was modified. */ + OCSPSignatureError = -67639, /* The OCSP response had an invalid signature. */ + OCSPNoSigner = -67640, /* The OCSP response had no signer. */ + OCSPResponderMalformedReq = -67641, /* The OCSP responder was given a malformed request. */ + OCSPResponderInternalError = -67642, /* The OCSP responder encountered an internal error. */ + OCSPResponderTryLater = -67643, /* The OCSP responder is busy, try again later. */ + OCSPResponderSignatureRequired = -67644, /* The OCSP responder requires a signature. */ + OCSPResponderUnauthorized = -67645, /* The OCSP responder rejected this request as unauthorized. */ + OCSPResponseNonceMismatch = -67646, /* The OCSP response nonce did not match the request. */ + CodeSigningBadCertChainLength = -67647, /* Code signing encountered an incorrect certificate chain length. */ + CodeSigningNoBasicConstraints = -67648, /* Code signing found no basic constraints. */ + CodeSigningBadPathLengthConstraint = -67649, /* Code signing encountered an incorrect path length constraint. */ + CodeSigningNoExtendedKeyUsage = -67650, /* Code signing found no extended key usage. */ + CodeSigningDevelopment = -67651, /* Code signing indicated use of a development-only certificate. */ + ResourceSignBadCertChainLength = -67652, /* Resource signing has encountered an incorrect certificate chain length. */ + ResourceSignBadExtKeyUsage = -67653, /* Resource signing has encountered an error in the extended key usage. */ + TrustSettingDeny = -67654, /* The trust setting for this policy was set to Deny. */ + InvalidSubjectName = -67655, /* An invalid certificate subject name was encountered. */ + UnknownQualifiedCertStatement = -67656, /* An unknown qualified certificate statement was encountered. */ + MobileMeRequestQueued = -67657, /* The MobileMe request will be sent during the next connection. */ + MobileMeRequestRedirected = -67658, /* The MobileMe request was redirected. */ + MobileMeServerError = -67659, /* A MobileMe server error occurred. */ + MobileMeServerNotAvailable = -67660, /* The MobileMe server is not available. */ + MobileMeServerAlreadyExists = -67661, /* The MobileMe server reported that the item already exists. */ + MobileMeServerServiceErr = -67662, /* A MobileMe service error has occurred. */ + MobileMeRequestAlreadyPending = -67663, /* A MobileMe request is already pending. */ + MobileMeNoRequestPending = -67664, /* MobileMe has no request pending. */ + MobileMeCSRVerifyFailure = -67665, /* A MobileMe CSR verification failure has occurred. */ + MobileMeFailedConsistencyCheck = -67666, /* MobileMe has found a failed consistency check. */ + NotInitialized = -67667, /* A function was called without initializing CSSM. */ + InvalidHandleUsage = -67668, /* The CSSM handle does not match with the service type. */ + PVCReferentNotFound = -67669, /* A reference to the calling module was not found in the list of authorized callers. */ + FunctionIntegrityFail = -67670, /* A function address was not within the verified module. */ + InternalError = -67671, /* An internal error has occurred. */ + MemoryError = -67672, /* A memory error has occurred. */ + InvalidData = -67673, /* Invalid data was encountered. */ + MDSError = -67674, /* A Module Directory Service error has occurred. */ + InvalidPointer = -67675, /* An invalid pointer was encountered. */ + SelfCheckFailed = -67676, /* Self-check has failed. */ + FunctionFailed = -67677, /* A function has failed. */ + ModuleManifestVerifyFailed = -67678, /* A module manifest verification failure has occurred. */ + InvalidGUID = -67679, /* An invalid GUID was encountered. */ + InvalidHandle = -67680, /* An invalid handle was encountered. */ + InvalidDBList = -67681, /* An invalid DB list was encountered. */ + InvalidPassthroughID = -67682, /* An invalid passthrough ID was encountered. */ + InvalidNetworkAddress = -67683, /* An invalid network address was encountered. */ + CRLAlreadySigned = -67684, /* The certificate revocation list is already signed. */ + InvalidNumberOfFields = -67685, /* An invalid number of fields were encountered. */ + VerificationFailure = -67686, /* A verification failure occurred. */ + UnknownTag = -67687, /* An unknown tag was encountered. */ + InvalidSignature = -67688, /* An invalid signature was encountered. */ + InvalidName = -67689, /* An invalid name was encountered. */ + InvalidCertificateRef = -67690, /* An invalid certificate reference was encountered. */ + InvalidCertificateGroup = -67691, /* An invalid certificate group was encountered. */ + TagNotFound = -67692, /* The specified tag was not found. */ + InvalidQuery = -67693, /* The specified query was not valid. */ + InvalidValue = -67694, /* An invalid value was detected. */ + CallbackFailed = -67695, /* A callback has failed. */ + ACLDeleteFailed = -67696, /* An ACL delete operation has failed. */ + ACLReplaceFailed = -67697, /* An ACL replace operation has failed. */ + ACLAddFailed = -67698, /* An ACL add operation has failed. */ + ACLChangeFailed = -67699, /* An ACL change operation has failed. */ + InvalidAccessCredentials = -67700, /* Invalid access credentials were encountered. */ + InvalidRecord = -67701, /* An invalid record was encountered. */ + InvalidACL = -67702, /* An invalid ACL was encountered. */ + InvalidSampleValue = -67703, /* An invalid sample value was encountered. */ + IncompatibleVersion = -67704, /* An incompatible version was encountered. */ + PrivilegeNotGranted = -67705, /* The privilege was not granted. */ + InvalidScope = -67706, /* An invalid scope was encountered. */ + PVCAlreadyConfigured = -67707, /* The PVC is already configured. */ + InvalidPVC = -67708, /* An invalid PVC was encountered. */ + EMMLoadFailed = -67709, /* The EMM load has failed. */ + EMMUnloadFailed = -67710, /* The EMM unload has failed. */ + AddinLoadFailed = -67711, /* The add-in load operation has failed. */ + InvalidKeyRef = -67712, /* An invalid key was encountered. */ + InvalidKeyHierarchy = -67713, /* An invalid key hierarchy was encountered. */ + AddinUnloadFailed = -67714, /* The add-in unload operation has failed. */ + LibraryReferenceNotFound = -67715, /* A library reference was not found. */ + InvalidAddinFunctionTable = -67716, /* An invalid add-in function table was encountered. */ + InvalidServiceMask = -67717, /* An invalid service mask was encountered. */ + ModuleNotLoaded = -67718, /* A module was not loaded. */ + InvalidSubServiceID = -67719, /* An invalid subservice ID was encountered. */ + AttributeNotInContext = -67720, /* An attribute was not in the context. */ + ModuleManagerInitializeFailed = -67721, /* A module failed to initialize. */ + ModuleManagerNotFound = -67722, /* A module was not found. */ + EventNotificationCallbackNotFound = -67723, /* An event notification callback was not found. */ + InputLengthError = -67724, /* An input length error was encountered. */ + OutputLengthError = -67725, /* An output length error was encountered. */ + PrivilegeNotSupported = -67726, /* The privilege is not supported. */ + DeviceError = -67727, /* A device error was encountered. */ + AttachHandleBusy = -67728, /* The CSP handle was busy. */ + NotLoggedIn = -67729, /* You are not logged in. */ + AlgorithmMismatch = -67730, /* An algorithm mismatch was encountered. */ + KeyUsageIncorrect = -67731, /* The key usage is incorrect. */ + KeyBlobTypeIncorrect = -67732, /* The key blob type is incorrect. */ + KeyHeaderInconsistent = -67733, /* The key header is inconsistent. */ + UnsupportedKeyFormat = -67734, /* The key header format is not supported. */ + UnsupportedKeySize = -67735, /* The key size is not supported. */ + InvalidKeyUsageMask = -67736, /* The key usage mask is not valid. */ + UnsupportedKeyUsageMask = -67737, /* The key usage mask is not supported. */ + InvalidKeyAttributeMask = -67738, /* The key attribute mask is not valid. */ + UnsupportedKeyAttributeMask = -67739, /* The key attribute mask is not supported. */ + InvalidKeyLabel = -67740, /* The key label is not valid. */ + UnsupportedKeyLabel = -67741, /* The key label is not supported. */ + InvalidKeyFormat = -67742, /* The key format is not valid. */ + UnsupportedVectorOfBuffers = -67743, /* The vector of buffers is not supported. */ + InvalidInputVector = -67744, /* The input vector is not valid. */ + InvalidOutputVector = -67745, /* The output vector is not valid. */ + InvalidContext = -67746, /* An invalid context was encountered. */ + InvalidAlgorithm = -67747, /* An invalid algorithm was encountered. */ + InvalidAttributeKey = -67748, /* A key attribute was not valid. */ + MissingAttributeKey = -67749, /* A key attribute was missing. */ + InvalidAttributeInitVector = -67750, /* An init vector attribute was not valid. */ + MissingAttributeInitVector = -67751, /* An init vector attribute was missing. */ + InvalidAttributeSalt = -67752, /* A salt attribute was not valid. */ + MissingAttributeSalt = -67753, /* A salt attribute was missing. */ + InvalidAttributePadding = -67754, /* A padding attribute was not valid. */ + MissingAttributePadding = -67755, /* A padding attribute was missing. */ + InvalidAttributeRandom = -67756, /* A random number attribute was not valid. */ + MissingAttributeRandom = -67757, /* A random number attribute was missing. */ + InvalidAttributeSeed = -67758, /* A seed attribute was not valid. */ + MissingAttributeSeed = -67759, /* A seed attribute was missing. */ + InvalidAttributePassphrase = -67760, /* A passphrase attribute was not valid. */ + MissingAttributePassphrase = -67761, /* A passphrase attribute was missing. */ + InvalidAttributeKeyLength = -67762, /* A key length attribute was not valid. */ + MissingAttributeKeyLength = -67763, /* A key length attribute was missing. */ + InvalidAttributeBlockSize = -67764, /* A block size attribute was not valid. */ + MissingAttributeBlockSize = -67765, /* A block size attribute was missing. */ + InvalidAttributeOutputSize = -67766, /* An output size attribute was not valid. */ + MissingAttributeOutputSize = -67767, /* An output size attribute was missing. */ + InvalidAttributeRounds = -67768, /* The number of rounds attribute was not valid. */ + MissingAttributeRounds = -67769, /* The number of rounds attribute was missing. */ + InvalidAlgorithmParms = -67770, /* An algorithm parameters attribute was not valid. */ + MissingAlgorithmParms = -67771, /* An algorithm parameters attribute was missing. */ + InvalidAttributeLabel = -67772, /* A label attribute was not valid. */ + MissingAttributeLabel = -67773, /* A label attribute was missing. */ + InvalidAttributeKeyType = -67774, /* A key type attribute was not valid. */ + MissingAttributeKeyType = -67775, /* A key type attribute was missing. */ + InvalidAttributeMode = -67776, /* A mode attribute was not valid. */ + MissingAttributeMode = -67777, /* A mode attribute was missing. */ + InvalidAttributeEffectiveBits = -67778, /* An effective bits attribute was not valid. */ + MissingAttributeEffectiveBits = -67779, /* An effective bits attribute was missing. */ + InvalidAttributeStartDate = -67780, /* A start date attribute was not valid. */ + MissingAttributeStartDate = -67781, /* A start date attribute was missing. */ + InvalidAttributeEndDate = -67782, /* An end date attribute was not valid. */ + MissingAttributeEndDate = -67783, /* An end date attribute was missing. */ + InvalidAttributeVersion = -67784, /* A version attribute was not valid. */ + MissingAttributeVersion = -67785, /* A version attribute was missing. */ + InvalidAttributePrime = -67786, /* A prime attribute was not valid. */ + MissingAttributePrime = -67787, /* A prime attribute was missing. */ + InvalidAttributeBase = -67788, /* A base attribute was not valid. */ + MissingAttributeBase = -67789, /* A base attribute was missing. */ + InvalidAttributeSubprime = -67790, /* A subprime attribute was not valid. */ + MissingAttributeSubprime = -67791, /* A subprime attribute was missing. */ + InvalidAttributeIterationCount = -67792, /* An iteration count attribute was not valid. */ + MissingAttributeIterationCount = -67793, /* An iteration count attribute was missing. */ + InvalidAttributeDLDBHandle = -67794, /* A database handle attribute was not valid. */ + MissingAttributeDLDBHandle = -67795, /* A database handle attribute was missing. */ + InvalidAttributeAccessCredentials = -67796, /* An access credentials attribute was not valid. */ + MissingAttributeAccessCredentials = -67797, /* An access credentials attribute was missing. */ + InvalidAttributePublicKeyFormat = -67798, /* A public key format attribute was not valid. */ + MissingAttributePublicKeyFormat = -67799, /* A public key format attribute was missing. */ + InvalidAttributePrivateKeyFormat = -67800, /* A private key format attribute was not valid. */ + MissingAttributePrivateKeyFormat = -67801, /* A private key format attribute was missing. */ + InvalidAttributeSymmetricKeyFormat = -67802, /* A symmetric key format attribute was not valid. */ + MissingAttributeSymmetricKeyFormat = -67803, /* A symmetric key format attribute was missing. */ + InvalidAttributeWrappedKeyFormat = -67804, /* A wrapped key format attribute was not valid. */ + MissingAttributeWrappedKeyFormat = -67805, /* A wrapped key format attribute was missing. */ + StagedOperationInProgress = -67806, /* A staged operation is in progress. */ + StagedOperationNotStarted = -67807, /* A staged operation was not started. */ + VerifyFailed = -67808, /* A cryptographic verification failure has occurred. */ + QuerySizeUnknown = -67809, /* The query size is unknown. */ + BlockSizeMismatch = -67810, /* A block size mismatch occurred. */ + PublicKeyInconsistent = -67811, /* The public key was inconsistent. */ + DeviceVerifyFailed = -67812, /* A device verification failure has occurred. */ + InvalidLoginName = -67813, /* An invalid login name was detected. */ + AlreadyLoggedIn = -67814, /* The user is already logged in. */ + InvalidDigestAlgorithm = -67815, /* An invalid digest algorithm was detected. */ + InvalidCRLGroup = -67816, /* An invalid CRL group was detected. */ + CertificateCannotOperate = -67817, /* The certificate cannot operate. */ + CertificateExpired = -67818, /* An expired certificate was detected. */ + CertificateNotValidYet = -67819, /* The certificate is not yet valid. */ + CertificateRevoked = -67820, /* The certificate was revoked. */ + CertificateSuspended = -67821, /* The certificate was suspended. */ + InsufficientCredentials = -67822, /* Insufficient credentials were detected. */ + InvalidAction = -67823, /* The action was not valid. */ + InvalidAuthority = -67824, /* The authority was not valid. */ + VerifyActionFailed = -67825, /* A verify action has failed. */ + InvalidCertAuthority = -67826, /* The certificate authority was not valid. */ + InvalidCRLAuthority = -67827, /* The CRL authority was not valid. */ +#if MONOMAC + [Obsolete ("Use InvalidCRLAuthority")] + InvaldCRLAuthority = InvalidCRLAuthority, +#endif + InvalidCRLEncoding = -67828, /* The CRL encoding was not valid. */ + InvalidCRLType = -67829, /* The CRL type was not valid. */ + InvalidCRL = -67830, /* The CRL was not valid. */ + InvalidFormType = -67831, /* The form type was not valid. */ + InvalidID = -67832, /* The ID was not valid. */ + InvalidIdentifier = -67833, /* The identifier was not valid. */ + InvalidIndex = -67834, /* The index was not valid. */ + InvalidPolicyIdentifiers = -67835, /* The policy identifiers are not valid. */ + InvalidTimeString = -67836, /* The time specified was not valid. */ + InvalidReason = -67837, /* The trust policy reason was not valid. */ + InvalidRequestInputs = -67838, /* The request inputs are not valid. */ + InvalidResponseVector = -67839, /* The response vector was not valid. */ + InvalidStopOnPolicy = -67840, /* The stop-on policy was not valid. */ + InvalidTuple = -67841, /* The tuple was not valid. */ + MultipleValuesUnsupported = -67842, /* Multiple values are not supported. */ + NotTrusted = -67843, /* The trust policy was not trusted. */ + NoDefaultAuthority = -67844, /* No default authority was detected. */ + RejectedForm = -67845, /* The trust policy had a rejected form. */ + RequestLost = -67846, /* The request was lost. */ + RequestRejected = -67847, /* The request was rejected. */ + UnsupportedAddressType = -67848, /* The address type is not supported. */ + UnsupportedService = -67849, /* The service is not supported. */ + InvalidTupleGroup = -67850, /* The tuple group was not valid. */ + InvalidBaseACLs = -67851, /* The base ACLs are not valid. */ + InvalidTupleCredentials = -67852, /* The tuple credentials are not valid. */ +#if MONOMAC + [Obsolete ("Use InvalidTupleCredentials")] + InvalidTupleCredendtials = InvalidTupleCredentials, +#endif + InvalidEncoding = -67853, /* The encoding was not valid. */ + InvalidValidityPeriod = -67854, /* The validity period was not valid. */ + InvalidRequestor = -67855, /* The requestor was not valid. */ + RequestDescriptor = -67856, /* The request descriptor was not valid. */ + InvalidBundleInfo = -67857, /* The bundle information was not valid. */ + InvalidCRLIndex = -67858, /* The CRL index was not valid. */ + NoFieldValues = -67859, /* No field values were detected. */ + UnsupportedFieldFormat = -67860, /* The field format is not supported. */ + UnsupportedIndexInfo = -67861, /* The index information is not supported. */ + UnsupportedLocality = -67862, /* The locality is not supported. */ + UnsupportedNumAttributes = -67863, /* The number of attributes is not supported. */ + UnsupportedNumIndexes = -67864, /* The number of indexes is not supported. */ + UnsupportedNumRecordTypes = -67865, /* The number of record types is not supported. */ + FieldSpecifiedMultiple = -67866, /* Too many fields were specified. */ + IncompatibleFieldFormat = -67867, /* The field format was incompatible. */ + InvalidParsingModule = -67868, /* The parsing module was not valid. */ + DatabaseLocked = -67869, /* The database is locked. */ + DatastoreIsOpen = -67870, /* The data store is open. */ + MissingValue = -67871, /* A missing value was detected. */ + UnsupportedQueryLimits = -67872, /* The query limits are not supported. */ + UnsupportedNumSelectionPreds = -67873, /* The number of selection predicates is not supported. */ + UnsupportedOperator = -67874, /* The operator is not supported. */ + InvalidDBLocation = -67875, /* The database location is not valid. */ + InvalidAccessRequest = -67876, /* The access request is not valid. */ + InvalidIndexInfo = -67877, /* The index information is not valid. */ + InvalidNewOwner = -67878, /* The new owner is not valid. */ + InvalidModifyMode = -67879, /* The modify mode is not valid. */ + MissingRequiredExtension = -67880, /* A required certificate extension is missing. */ + ExtendedKeyUsageNotCritical = -67881, /* The extended key usage extension was not marked critical. */ + TimestampMissing = -67882, /* A timestamp was expected but was not found. */ + TimestampInvalid = -67883, /* The timestamp was not valid. */ + TimestampNotTrusted = -67884, /* The timestamp was not trusted. */ + TimestampServiceNotAvailable = -67885, /* The timestamp service is not available. */ + TimestampBadAlg = -67886, /* An unrecognized or unsupported Algorithm Identifier in timestamp. */ + TimestampBadRequest = -67887, /* The timestamp transaction is not permitted or supported. */ + TimestampBadDataFormat = -67888, /* The timestamp data submitted has the wrong format. */ + TimestampTimeNotAvailable = -67889, /* The time source for the Timestamp Authority is not available. */ + TimestampUnacceptedPolicy = -67890, /* The requested policy is not supported by the Timestamp Authority. */ + TimestampUnacceptedExtension = -67891, /* The requested extension is not supported by the Timestamp Authority. */ + TimestampAddInfoNotAvailable = -67892, /* The additional information requested is not available. */ + TimestampSystemFailure = -67893, /* The timestamp request cannot be handled due to system failure. */ + SigningTimeMissing = -67894, /* A signing time was expected but was not found. */ + TimestampRejection = -67895, /* A timestamp transaction was rejected. */ + TimestampWaiting = -67896, /* A timestamp transaction is waiting. */ + TimestampRevocationWarning = -67897, /* A timestamp authority revocation warning was issued. */ + TimestampRevocationNotification = -67898, /* A timestamp authority revocation notification was issued. */ } // typedef uint32_t SecTrustResultType; diff --git a/mcs/class/System/Mono.AppleTls/ImportExport.cs b/mcs/class/System/Mono.AppleTls/ImportExport.cs index 518f0b13fc..390dc38138 100644 --- a/mcs/class/System/Mono.AppleTls/ImportExport.cs +++ b/mcs/class/System/Mono.AppleTls/ImportExport.cs @@ -1,4 +1,4 @@ -#if SECURITY_DEP && MONO_FEATURE_APPLETLS +#if SECURITY_DEP && MONO_FEATURE_APPLETLS // // ImportExport.cs // @@ -29,9 +29,17 @@ using System; using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; using ObjCRuntime; using Mono.Net; +#if MONO_FEATURE_BTLS +using Mono.Btls; +#else +using Mono.Security.Cryptography; +#endif + namespace Mono.AppleTls { internal partial class SecImportExport { @@ -54,9 +62,163 @@ namespace Mono.AppleTls { IntPtr handle; SecStatusCode code = SecPKCS12Import (data.Handle, options.Handle, out handle); array = CFArray.ArrayFromHandle (handle, h => new CFDictionary (h, false)); - CFObject.CFRelease (handle); + if (handle != IntPtr.Zero) + CFObject.CFRelease (handle); return code; } + +#if !MONOTOUCH + [DllImport (AppleTlsContext.SecurityLibrary)] + extern static SecStatusCode SecItemImport ( + /* CFDataRef */ IntPtr importedData, + /* CFStringRef */ IntPtr fileNameOrExtension, // optional + /* SecExternalFormat* */ ref SecExternalFormat inputFormat, // optional, IN/OUT + /* SecExternalItemType* */ ref SecExternalItemType itemType, // optional, IN/OUT + /* SecItemImportExportFlags */ SecItemImportExportFlags flags, + /* const SecItemImportExportKeyParameters* */ IntPtr keyParams, // optional + /* SecKeychainRef */ IntPtr importKeychain, // optional + /* CFArrayRef* */ out IntPtr outItems); + + static public CFArray ItemImport (byte[] buffer, string password) + { + using (var data = CFData.FromData (buffer)) + using (var pwstring = CFString.Create (password)) { + SecItemImportExportKeyParameters keyParams = new SecItemImportExportKeyParameters (); + keyParams.passphrase = pwstring.Handle; + + return ItemImport (data, SecExternalFormat.PKCS12, SecExternalItemType.Aggregate, SecItemImportExportFlags.None, keyParams); + } + } + + static CFArray ItemImport (CFData data, SecExternalFormat format, SecExternalItemType itemType, + SecItemImportExportFlags flags = SecItemImportExportFlags.None, + SecItemImportExportKeyParameters? keyParams = null) + { + return ItemImport (data, ref format, ref itemType, flags, keyParams); + } + + static CFArray ItemImport (CFData data, ref SecExternalFormat format, ref SecExternalItemType itemType, + SecItemImportExportFlags flags = SecItemImportExportFlags.None, + SecItemImportExportKeyParameters? keyParams = null) + { + IntPtr keyParamsPtr = IntPtr.Zero; + if (keyParams != null) { + keyParamsPtr = Marshal.AllocHGlobal (Marshal.SizeOf (keyParams.Value)); + if (keyParamsPtr == IntPtr.Zero) + throw new OutOfMemoryException (); + Marshal.StructureToPtr (keyParams.Value, keyParamsPtr, false); + } + + IntPtr result; + var status = SecItemImport (data.Handle, IntPtr.Zero, ref format, ref itemType, flags, keyParamsPtr, IntPtr.Zero, out result); + + if (keyParamsPtr != IntPtr.Zero) + Marshal.FreeHGlobal (keyParamsPtr); + + if (status != SecStatusCode.Success) + throw new NotSupportedException (status.ToString ()); + + return new CFArray (result, true); + } + + [DllImport (AppleTlsContext.SecurityLibrary)] + extern static /* SecIdentityRef */ IntPtr SecIdentityCreate ( + /* CFAllocatorRef */ IntPtr allocator, + /* SecCertificateRef */ IntPtr certificate, + /* SecKeyRef */ IntPtr privateKey); + + static public SecIdentity ItemImport (X509Certificate2 certificate) + { + if (!certificate.HasPrivateKey) + throw new NotSupportedException (); + + using (var key = ImportPrivateKey (certificate)) + using (var cert = new SecCertificate (certificate)) { + var identity = SecIdentityCreate (IntPtr.Zero, cert.Handle, key.Handle); + if (CFType.GetTypeID (identity) != SecIdentity.GetTypeID ()) + throw new InvalidOperationException (); + + return new SecIdentity (identity, true); + } + } + + static byte[] ExportKey (RSA key) + { +#if MONO_FEATURE_BTLS + using (var btlsKey = MonoBtlsKey.CreateFromRSAPrivateKey (key)) + return btlsKey.GetBytes (true); +#else + return PKCS8.PrivateKeyInfo.Encode (key); +#endif + } + + static SecKey ImportPrivateKey (X509Certificate2 certificate) + { + if (!certificate.HasPrivateKey) + throw new NotSupportedException (); + + CFArray items; + using (var data = CFData.FromData (ExportKey ((RSA)certificate.PrivateKey))) + items = ItemImport (data, SecExternalFormat.OpenSSL, SecExternalItemType.PrivateKey); + + try { + if (items.Count != 1) + throw new InvalidOperationException ("Private key import failed."); + + var imported = items[0]; + if (CFType.GetTypeID (imported) != SecKey.GetTypeID ()) + throw new InvalidOperationException ("Private key import doesn't return SecKey."); + + return new SecKey (imported, items.Handle); + } finally { + items.Dispose (); + } + } + + const int SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION = 0; + + // Native enum; don't change. + enum SecExternalFormat : int { + Unknown = 0, + OpenSSL = 1, + X509Cert = 9, + PEMSequence = 10, + PKCS7 = 11, + PKCS12 = 12 + } + + // Native enum; don't change. + enum SecExternalItemType : int { + Unknown = 0, + PrivateKey = 1, + PublicKey = 2, + SessionKey = 3, + Certificate = 4, + Aggregate = 5 + } + + // Native enum; don't change + enum SecItemImportExportFlags : int { + None, + PemArmour = 0x00000001, /* exported blob is PEM formatted */ + } + + // Native struct; don't change + [StructLayout (LayoutKind.Sequential)] + struct SecItemImportExportKeyParameters { + public int version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */ + public int flags; /* SecKeyImportExportFlags bits */ + public IntPtr passphrase; /* SecExternalFormat.PKCS12 only. Legal types are CFStringRef and CFDataRef. */ + + IntPtr alertTitle; + IntPtr alertPrompt; + + public IntPtr accessRef; /* SecAccessRef */ + + IntPtr keyUsage; + IntPtr keyAttributes; + } +#endif } } #endif diff --git a/mcs/class/System/Mono.AppleTls/Items.cs b/mcs/class/System/Mono.AppleTls/Items.cs index 1c9fd0375e..cb37e48e07 100644 --- a/mcs/class/System/Mono.AppleTls/Items.cs +++ b/mcs/class/System/Mono.AppleTls/Items.cs @@ -1,4 +1,4 @@ -#if SECURITY_DEP && MONO_FEATURE_APPLETLS +#if SECURITY_DEP && MONO_FEATURE_APPLETLS // // Items.cs: Implements the KeyChain query access APIs // @@ -40,13 +40,32 @@ using Mono.Net; namespace Mono.AppleTls { enum SecKind { - Identity + Identity, + Certificate } +#if MONOTOUCH static class SecKeyChain { - static readonly IntPtr MatchLimitAll; - static readonly IntPtr MatchLimitOne; - static readonly IntPtr MatchLimit; +#else + class SecKeyChain : INativeObject, IDisposable { +#endif + internal static readonly IntPtr MatchLimitAll; + internal static readonly IntPtr MatchLimitOne; + internal static readonly IntPtr MatchLimit; + +#if !MONOTOUCH + IntPtr handle; + + internal SecKeyChain (IntPtr handle, bool owns = false) + { + if (handle == IntPtr.Zero) + throw new ArgumentException ("Invalid handle"); + + this.handle = handle; + if (!owns) + CFObject.CFRetain (handle); + } +#endif static SecKeyChain () { @@ -98,39 +117,47 @@ namespace Mono.AppleTls { return null; } - - public static INativeObject[] QueryAsReference (SecRecord query, int max, out SecStatusCode result) + + static INativeObject [] QueryAsReference (SecRecord query, int max, out SecStatusCode result) { - if (query == null){ + if (query == null) { result = SecStatusCode.Param; return null; } - using (var copy = query.queryDict.MutableCopy ()) { + using (var copy = query.QueryDict.MutableCopy ()) { copy.SetValue (CFBoolean.True.Handle, SecItem.ReturnRef); SetLimit (copy, max); - - IntPtr ptr; - result = SecItem.SecItemCopyMatching (copy.Handle, out ptr); - if ((result == SecStatusCode.Success) && (ptr != IntPtr.Zero)) { - var array = CFArray.ArrayFromHandle (ptr, p => { - IntPtr cfType = CFType.GetTypeID (p); - if (cfType == SecCertificate.GetTypeID ()) - return new SecCertificate (p, true); - else if (cfType == SecKey.GetTypeID ()) - return new SecKey (p, true); - else if (cfType == SecIdentity.GetTypeID ()) - return new SecIdentity (p, true); - else - throw new Exception (String.Format ("Unexpected type: 0x{0:x}", cfType)); - }); - return array; - } - return null; + return QueryAsReference (copy, out result); } } - static CFNumber SetLimit (CFMutableDictionary dict, int max) + static INativeObject [] QueryAsReference (CFDictionary query, out SecStatusCode result) + { + if (query == null) { + result = SecStatusCode.Param; + return null; + } + + IntPtr ptr; + result = SecItem.SecItemCopyMatching (query.Handle, out ptr); + if (result == SecStatusCode.Success && ptr != IntPtr.Zero) { + var array = CFArray.ArrayFromHandle (ptr, p => { + IntPtr cfType = CFType.GetTypeID (p); + if (cfType == SecCertificate.GetTypeID ()) + return new SecCertificate (p, true); + if (cfType == SecKey.GetTypeID ()) + return new SecKey (p, true); + if (cfType == SecIdentity.GetTypeID ()) + return new SecIdentity (p, true); + throw new Exception (String.Format ("Unexpected type: 0x{0:x}", cfType)); + }); + return array; + } + return null; + } + + internal static CFNumber SetLimit (CFMutableDictionary dict, int max) { CFNumber n = null; IntPtr val; @@ -142,47 +169,61 @@ namespace Mono.AppleTls { n = CFNumber.FromInt32 (max); val = n.Handle; } - + dict.SetValue (val, SecKeyChain.MatchLimit); return n; } - } - - class SecRecord : IDisposable { - static readonly IntPtr SecClassKey; - static SecRecord () +#if !MONOTOUCH + [DllImport (AppleTlsContext.SecurityLibrary)] + extern static /* OSStatus */ SecStatusCode SecKeychainCreate (/* const char * */ IntPtr pathName, uint passwordLength, /* const void * */ IntPtr password, + bool promptUser, /* SecAccessRef */ IntPtr initialAccess, + /* SecKeychainRef _Nullable * */ out IntPtr keychain); + + internal static SecKeyChain Create (string pathName, string password) { - var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0); - if (handle == IntPtr.Zero) - return; + IntPtr handle; + var pathNamePtr = Marshal.StringToHGlobalAnsi (pathName); + var passwordPtr = Marshal.StringToHGlobalAnsi (password); + var result = SecKeychainCreate (pathNamePtr, (uint)password.Length, passwordPtr, false, IntPtr.Zero, out handle); + if (result != SecStatusCode.Success) + throw new InvalidOperationException (result.ToString ()); + return new SecKeyChain (handle, true); + } - try { - SecClassKey = CFObject.GetIntPtr (handle, "kSecClassKey"); + [DllImport (AppleTlsContext.SecurityLibrary)] + extern static /* OSStatus */ SecStatusCode SecKeychainOpen (/* const char * */ IntPtr pathName, /* SecKeychainRef _Nullable * */ out IntPtr keychain); + + internal static SecKeyChain Open (string pathName) + { + IntPtr handle; + IntPtr pathNamePtr = IntPtr.Zero; + try { + pathNamePtr = Marshal.StringToHGlobalAnsi (pathName); + var result = SecKeychainOpen (pathNamePtr, out handle); + if (result != SecStatusCode.Success) + throw new InvalidOperationException (result.ToString ()); + return new SecKeyChain (handle, true); } finally { - CFObject.dlclose (handle); + if (pathNamePtr != IntPtr.Zero) + Marshal.FreeHGlobal (pathNamePtr); } } - // Fix <= iOS 6 Behaviour - Desk #83099 - // NSCFDictionary: mutating method sent to immutable object - // iOS 6 returns an inmutable NSDictionary handle and when we try to set its values it goes kaboom - // By explicitly calling `MutableCopy` we ensure we always have a mutable reference we expect that. - CFDictionary _queryDict; - internal CFDictionary queryDict - { - get { - return _queryDict; - } - set { - _queryDict = value != null ? value.Copy () : null; - } - } - - public SecRecord (SecKind secKind) + internal static SecKeyChain OpenSystemRootCertificates () { - var kind = SecClass.FromSecKind (secKind); - queryDict = CFDictionary.FromObjectAndKey (kind, SecClassKey); + return Open ("/System/Library/Keychains/SystemRootCertificates.keychain"); + } + + ~SecKeyChain () + { + Dispose (false); + } + + public IntPtr Handle { + get { + return handle; + } } public void Dispose () @@ -193,10 +234,61 @@ namespace Mono.AppleTls { protected virtual void Dispose (bool disposing) { - if (queryDict != null){ + if (handle != IntPtr.Zero) { + CFObject.CFRelease (handle); + handle = IntPtr.Zero; + } + } +#endif + } + + class SecRecord : IDisposable { + + internal static readonly IntPtr SecClassKey; + static SecRecord () + { + var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0); + if (handle == IntPtr.Zero) + return; + + try { + SecClassKey = CFObject.GetIntPtr (handle, "kSecClass"); + } finally { + CFObject.dlclose (handle); + } + } + + CFMutableDictionary _queryDict; + internal CFMutableDictionary QueryDict { + get { + return _queryDict; + } + } + + internal void SetValue (IntPtr key, IntPtr value) + { + _queryDict.SetValue (key, value); + } + + public SecRecord (SecKind secKind) + { + var kind = SecClass.FromSecKind (secKind); + _queryDict = CFMutableDictionary.Create (); + _queryDict.SetValue (SecClassKey, kind); + } + + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + protected virtual void Dispose (bool disposing) + { + if (_queryDict != null){ if (disposing){ - queryDict.Dispose (); - queryDict = null; + _queryDict.Dispose (); + _queryDict = null; } } } @@ -209,6 +301,7 @@ namespace Mono.AppleTls { partial class SecItem { public static readonly IntPtr ReturnRef; + public static readonly IntPtr MatchSearchList; static SecItem () { @@ -218,6 +311,7 @@ namespace Mono.AppleTls { try { ReturnRef = CFObject.GetIntPtr (handle, "kSecReturnRef"); + MatchSearchList = CFObject.GetIntPtr (handle, "kSecMatchSearchList"); } finally { CFObject.dlclose (handle); } @@ -230,6 +324,7 @@ namespace Mono.AppleTls { static partial class SecClass { public static readonly IntPtr Identity; + public static readonly IntPtr Certificate; static SecClass () { @@ -237,8 +332,9 @@ namespace Mono.AppleTls { if (handle == IntPtr.Zero) return; - try { + try { Identity = CFObject.GetIntPtr (handle, "kSecClassIdentity"); + Certificate = CFObject.GetIntPtr (handle, "kSecClassCertificate"); } finally { CFObject.dlclose (handle); } @@ -249,6 +345,8 @@ namespace Mono.AppleTls { switch (secKind){ case SecKind.Identity: return Identity; + case SecKind.Certificate: + return Certificate; default: throw new ArgumentException ("secKind"); } diff --git a/mcs/class/System/System.Net/MacProxy.cs b/mcs/class/System/System.Net/MacProxy.cs index bd2cdc10b9..7dbb895715 100644 --- a/mcs/class/System/System.Net/MacProxy.cs +++ b/mcs/class/System/System.Net/MacProxy.cs @@ -469,7 +469,18 @@ namespace Mono.Net { return new CFDictionary (CFDictionaryCreate (IntPtr.Zero, new IntPtr[] { key }, new IntPtr [] { obj }, (IntPtr)1, KeyCallbacks, ValueCallbacks), true); } - + + public static CFDictionary FromKeysAndObjects (IList> items) + { + var keys = new IntPtr [items.Count]; + var values = new IntPtr [items.Count]; + for (int i = 0; i < items.Count; i++) { + keys [i] = items [i].Item1; + values [i] = items [i].Item2; + } + return new CFDictionary (CFDictionaryCreate (IntPtr.Zero, keys, values, (IntPtr)items.Count, KeyCallbacks, ValueCallbacks), true); + } + [DllImport (CoreFoundationLibrary)] extern static IntPtr CFDictionaryCreate (IntPtr allocator, IntPtr[] keys, IntPtr[] vals, IntPtr len, IntPtr keyCallbacks, IntPtr valCallbacks); @@ -513,8 +524,20 @@ namespace Mono.Net CFDictionarySetValue (Handle, key, val); } + public static CFMutableDictionary Create () + { + var handle = CFDictionaryCreateMutable (IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + if (handle == IntPtr.Zero) + throw new InvalidOperationException (); + return new CFMutableDictionary (handle, true); + } + [DllImport (CoreFoundationLibrary)] extern static void CFDictionarySetValue (IntPtr handle, IntPtr key, IntPtr val); + + [DllImport (CoreFoundationLibrary)] + extern static IntPtr CFDictionaryCreateMutable (IntPtr allocator, IntPtr capacity, IntPtr keyCallback, IntPtr valueCallbacks); + } internal class CFUrl : CFObject diff --git a/mcs/class/System/System.Net/WebConnection.cs b/mcs/class/System/System.Net/WebConnection.cs index 0a36e21004..f8922a4df5 100644 --- a/mcs/class/System/System.Net/WebConnection.cs +++ b/mcs/class/System/System.Net/WebConnection.cs @@ -1016,6 +1016,18 @@ namespace System.Net IAsyncResult result = null; try { result = s.BeginWrite (buffer, offset, size, cb, state); + } catch (ObjectDisposedException) { + lock (this) { + if (Data.request != request) + return null; + } + throw; + } catch (IOException e) { + SocketException se = e.InnerException as SocketException; + if (se != null && se.SocketErrorCode == SocketError.NotConnected) { + return null; + } + throw; } catch (Exception) { status = WebExceptionStatus.SendFailure; throw; diff --git a/mcs/class/lib/monolite/1050000000/System.dll.REMOVED.git-id b/mcs/class/lib/monolite/1050000000/System.dll.REMOVED.git-id index c37a8ebb5d..a5176f9968 100644 --- a/mcs/class/lib/monolite/1050000000/System.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/1050000000/System.dll.REMOVED.git-id @@ -1 +1 @@ -08d4642d4dfb3cb6a43b58d442f02e11e747742b \ No newline at end of file +9730a8aa4510c1e02ddaf93e1b0858f961a19d27 \ No newline at end of file diff --git a/mono/metadata/debug-mono-ppdb.c b/mono/metadata/debug-mono-ppdb.c index b96edfdf69..036029d611 100644 --- a/mono/metadata/debug-mono-ppdb.c +++ b/mono/metadata/debug-mono-ppdb.c @@ -435,6 +435,9 @@ mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrAr if (sfiles) g_ptr_array_add (sfiles, docinfo); + if (source_file) + *source_file = g_strdup (docinfo->source_file); + iloffset = 0; start_line = 0; start_col = 0; @@ -492,8 +495,6 @@ mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrAr memcpy (*seq_points, sps->data, sps->len * sizeof (MonoSymSeqPoint)); } - if (source_file) - *source_file = g_strdup (((MonoDebugSourceInfo*)g_ptr_array_index (sfiles, 0))->source_file); if (source_files) { *source_files = g_new (int, sps->len); for (i = 0; i < sps->len; ++i) diff --git a/mono/mini/Makefile.am b/mono/mini/Makefile.am index 12bae8047a..332eda807f 100644 --- a/mono/mini/Makefile.am +++ b/mono/mini/Makefile.am @@ -878,7 +878,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 5.0.0.48/851b6c7\"" > version.h + echo "#define FULL_VERSION \"Stable 5.0.0.61/4242008\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index 12bae8047a..332eda807f 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -878,7 +878,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 5.0.0.48/851b6c7\"" > version.h + echo "#define FULL_VERSION \"Stable 5.0.0.61/4242008\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.in.REMOVED.git-id b/mono/mini/Makefile.in.REMOVED.git-id index c3e4e31a11..4fddd14392 100644 --- a/mono/mini/Makefile.in.REMOVED.git-id +++ b/mono/mini/Makefile.in.REMOVED.git-id @@ -1 +1 @@ -6cfc9c6b9b9f5d22de9a650e7d5527a33b533cca \ No newline at end of file +434fe4e634a1bfba7eb1b7d400bb980490f1e895 \ No newline at end of file diff --git a/mono/mini/debugger-agent.c.REMOVED.git-id b/mono/mini/debugger-agent.c.REMOVED.git-id index b17134c9fd..dcfe203f7e 100644 --- a/mono/mini/debugger-agent.c.REMOVED.git-id +++ b/mono/mini/debugger-agent.c.REMOVED.git-id @@ -1 +1 @@ -c61a76885b8fb2ba68708558b39487a7d53e1f9c \ No newline at end of file +c3ec223220f37f6e77b2a9b2e9b02a82c06da77c \ No newline at end of file diff --git a/mono/mini/mini-arm-gsharedvt.c b/mono/mini/mini-arm-gsharedvt.c index 2c7f8812a6..43172ed82a 100644 --- a/mono/mini/mini-arm-gsharedvt.c +++ b/mono/mini/mini-arm-gsharedvt.c @@ -217,8 +217,8 @@ mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_si else src_slot = map_stack_slot (ainfo->offset / 4); g_assert (ndst < 256); - g_assert (src_slot < 16); - src [0] = (ndst << 4) | src_slot; + g_assert (src_slot < 256); + src [0] = (ndst << 8) | src_slot; if (ainfo2->storage == RegTypeGeneral && ainfo2->size != 0 && ainfo2->size != 4) { /* Have to load less than 4 bytes */ @@ -256,7 +256,7 @@ mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_si ndst = get_arg_slots (ainfo2, &dst); } if (nsrc) - src [0] |= (arg_marshal << 16); + src [0] |= (arg_marshal << 24); nslots = MIN (nsrc, ndst); for (i = 0; i < nslots; ++i) diff --git a/mono/mini/tramp-arm-gsharedvt.c b/mono/mini/tramp-arm-gsharedvt.c index acc1dd839f..5525bed4f5 100644 --- a/mono/mini/tramp-arm-gsharedvt.c +++ b/mono/mini/tramp-arm-gsharedvt.c @@ -53,7 +53,7 @@ mono_arm_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpoint for (i = 0; i < info->map_count; ++i) { int src = info->map [i * 2]; int dst = info->map [(i * 2) + 1]; - int arg_marshal = (src >> 16) & 0xff; + int arg_marshal = (src >> 24) & 0xff; switch (arg_marshal) { case GSHAREDVT_ARG_NONE: @@ -66,8 +66,8 @@ mono_arm_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpoint break; case GSHAREDVT_ARG_BYREF_TO_BYVAL: { /* gsharedvt argument passed by value */ - int nslots = (src >> 4) & 0xff; - int src_slot = src & 0xf; + int nslots = (src >> 8) & 0xff; + int src_slot = src & 0xff; int j; gpointer *addr = caller [src_slot]; @@ -76,28 +76,28 @@ mono_arm_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpoint break; } case GSHAREDVT_ARG_BYREF_TO_BYVAL_I1: { - int src_slot = src & 0xf; + int src_slot = src & 0xff; gpointer *addr = caller [src_slot]; callee [dst] = GINT_TO_POINTER ((int)*(gint8*)addr); break; } case GSHAREDVT_ARG_BYREF_TO_BYVAL_I2: { - int src_slot = src & 0xf; + int src_slot = src & 0xff; gpointer *addr = caller [src_slot]; callee [dst] = GINT_TO_POINTER ((int)*(gint16*)addr); break; } case GSHAREDVT_ARG_BYREF_TO_BYVAL_U1: { - int src_slot = src & 0xf; + int src_slot = src & 0xff; gpointer *addr = caller [src_slot]; callee [dst] = GUINT_TO_POINTER ((guint)*(guint8*)addr); break; } case GSHAREDVT_ARG_BYREF_TO_BYVAL_U2: { - int src_slot = src & 0xf; + int src_slot = src & 0xff; gpointer *addr = caller [src_slot]; callee [dst] = GUINT_TO_POINTER ((guint)*(guint16*)addr); diff --git a/mono/mini/version.h b/mono/mini/version.h index b77c6f5e0c..eb460c9d86 100644 --- a/mono/mini/version.h +++ b/mono/mini/version.h @@ -1 +1 @@ -#define FULL_VERSION "Stable 5.0.0.48/851b6c7" +#define FULL_VERSION "Stable 5.0.0.61/4242008" diff --git a/po/mcs/de.gmo b/po/mcs/de.gmo index 6195a54c86..806f52500c 100644 Binary files a/po/mcs/de.gmo and b/po/mcs/de.gmo differ diff --git a/po/mcs/de.po.REMOVED.git-id b/po/mcs/de.po.REMOVED.git-id index dc9905ff14..e272a173b5 100644 --- a/po/mcs/de.po.REMOVED.git-id +++ b/po/mcs/de.po.REMOVED.git-id @@ -1 +1 @@ -5f068b378071d61ca60f10fd4f4604c4bae5bdbc \ No newline at end of file +760fdff9f33684cc748d1e946bb6c13a689618e8 \ No newline at end of file diff --git a/po/mcs/es.gmo b/po/mcs/es.gmo index 5bb723e163..6f8d3f9137 100644 Binary files a/po/mcs/es.gmo and b/po/mcs/es.gmo differ diff --git a/po/mcs/es.po.REMOVED.git-id b/po/mcs/es.po.REMOVED.git-id index 780eec8b64..39453518cb 100644 --- a/po/mcs/es.po.REMOVED.git-id +++ b/po/mcs/es.po.REMOVED.git-id @@ -1 +1 @@ -40663cf47875043c34b953349e194fcf894a95cc \ No newline at end of file +1a6e2559d7a80797c4b973e659acc65b68c848ef \ No newline at end of file diff --git a/po/mcs/ja.gmo b/po/mcs/ja.gmo index d0450f9e26..083e3cdf5e 100644 Binary files a/po/mcs/ja.gmo and b/po/mcs/ja.gmo differ diff --git a/po/mcs/ja.po.REMOVED.git-id b/po/mcs/ja.po.REMOVED.git-id index 7fc4b7be53..dad517b1c5 100644 --- a/po/mcs/ja.po.REMOVED.git-id +++ b/po/mcs/ja.po.REMOVED.git-id @@ -1 +1 @@ -2e03765163e24dbfee9880d67d978f9da4cded26 \ No newline at end of file +5d060c5c9574e03c012c0535098ff6fda7f95bf8 \ No newline at end of file diff --git a/po/mcs/mcs.pot b/po/mcs/mcs.pot index 33feaca771..f5488011f7 100644 --- a/po/mcs/mcs.pot +++ b/po/mcs/mcs.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: mono 5.0.0\n" "Report-Msgid-Bugs-To: http://www.mono-project.com/Bugs\n" -"POT-Creation-Date: 2017-04-11 11:15+0000\n" +"POT-Creation-Date: 2017-04-19 15:43+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/po/mcs/pt_BR.gmo b/po/mcs/pt_BR.gmo index e9cdfa90c6..df39a2b7a9 100644 Binary files a/po/mcs/pt_BR.gmo and b/po/mcs/pt_BR.gmo differ diff --git a/po/mcs/pt_BR.po.REMOVED.git-id b/po/mcs/pt_BR.po.REMOVED.git-id index 1dbf8f2797..9f2252addd 100644 --- a/po/mcs/pt_BR.po.REMOVED.git-id +++ b/po/mcs/pt_BR.po.REMOVED.git-id @@ -1 +1 @@ -b0660e81b0e4e4028fcebdc20dd98903b7e86651 \ No newline at end of file +b85343d1642203f49c23501b87fd68392a48afa0 \ No newline at end of file