private static bool IsExecutable(string fullPath) { Interop.Sys.FileStatus fileinfo; if (Interop.Sys.Stat(fullPath, out fileinfo) < 0) { return(false); } // Check if the path is a directory. if ((fileinfo.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR) { return(false); } Interop.Sys.Permissions permissions = (Interop.Sys.Permissions)fileinfo.Mode; if (s_euid == 0) { // We're root. return((permissions & Interop.Sys.Permissions.S_IXUGO) != 0); } if (s_euid == fileinfo.Uid) { // We own the file. return((permissions & Interop.Sys.Permissions.S_IXUSR) != 0); } if (s_egid == fileinfo.Gid || (s_groups != null && Array.BinarySearch(s_groups, fileinfo.Gid) >= 0)) { // A group we're a member of owns the file. return((permissions & Interop.Sys.Permissions.S_IXGRP) != 0); } // Other. return((permissions & Interop.Sys.Permissions.S_IXOTH) != 0); }
/// <summary> /// Checks the file has the correct permissions. /// </summary> /// <param name="stream"> /// The file stream to check. /// </param> /// <param name="userId"> /// The current userId from GetEUid(). /// </param> private static void EnsureFilePermissions(FileStream stream, uint userId) { // Verify that we're creating files with u+rw and o-rw, g-rw. const Interop.Sys.Permissions requiredPermissions = Interop.Sys.Permissions.S_IRUSR | Interop.Sys.Permissions.S_IWUSR; const Interop.Sys.Permissions forbiddenPermissions = Interop.Sys.Permissions.S_IROTH | Interop.Sys.Permissions.S_IWOTH | Interop.Sys.Permissions.S_IRGRP | Interop.Sys.Permissions.S_IWGRP; Interop.Sys.FileStatus stat; if (Interop.Sys.FStat(stream.SafeFileHandle, out stat) != 0) { Interop.ErrorInfo error = Interop.Sys.GetLastErrorInfo(); throw new CryptographicException( SR.Cryptography_FileStatusError, new IOException(error.GetErrorMessage(), error.RawErrno)); } if (stat.Uid != userId) { throw new CryptographicException(SR.Format(SR.Cryptography_OwnerNotCurrentUser, stream.Name)); } if ((stat.Mode & (int)requiredPermissions) != (int)requiredPermissions) { throw new CryptographicException(SR.Format(SR.Cryptography_InsufficientFilePermissions, stream.Name)); } if ((stat.Mode & (int)forbiddenPermissions) != 0) { throw new CryptographicException(SR.Format(SR.Cryptography_TooBroadFilePermissions, stream.Name)); } }
// ----------------------------- // ---- PAL layer ends here ---- // ----------------------------- private static FileStream CreateSharedBackingObjectUsingMemory( Interop.Sys.MemoryMappedProtections protections, long capacity) { // The POSIX shared memory object name must begin with '/'. After that we just want something short and unique. string mapName = "/corefx_map_" + Guid.NewGuid().ToString("N"); // Determine the flags to use when creating the shared memory object Interop.Sys.OpenFlags flags = (protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0 ? Interop.Sys.OpenFlags.O_RDWR : Interop.Sys.OpenFlags.O_RDONLY; flags |= Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_EXCL; // CreateNew // Determine the permissions with which to create the file Interop.Sys.Permissions perms = default(Interop.Sys.Permissions); if ((protections & Interop.Sys.MemoryMappedProtections.PROT_READ) != 0) { perms |= Interop.Sys.Permissions.S_IRUSR; } if ((protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0) { perms |= Interop.Sys.Permissions.S_IWUSR; } if ((protections & Interop.Sys.MemoryMappedProtections.PROT_EXEC) != 0) { perms |= Interop.Sys.Permissions.S_IXUSR; } // Create the shared memory object. SafeFileHandle fd = Interop.Sys.ShmOpen(mapName, flags, (int)perms); if (fd.IsInvalid) { Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); if (errorInfo.Error == Interop.Error.ENOTSUP) { // If ShmOpen is not supported, fall back to file backing object. // Note that the System.Native shim will force this failure on platforms where // the result of native shm_open does not work well with our subsequent call // to mmap. return(null); } throw Interop.GetExceptionForIoErrno(errorInfo); } try { // Unlink the shared memory object immediately so that it'll go away once all handles // to it are closed (as with opened then unlinked files, it'll remain usable via // the open handles even though it's unlinked and can't be opened anew via its name). Interop.CheckIo(Interop.Sys.ShmUnlink(mapName)); // Give it the right capacity. We do this directly with ftruncate rather // than via FileStream.SetLength after the FileStream is created because, on some systems, // lseek fails on shared memory objects, causing the FileStream to think it's unseekable, // causing it to preemptively throw from SetLength. Interop.CheckIo(Interop.Sys.FTruncate(fd, capacity)); // Wrap the file descriptor in a stream and return it. return(new FileStream(fd, TranslateProtectionsToFileAccess(protections))); } catch { fd.Dispose(); throw; } }
public void Add(ICertificatePal certPal) { if (_readOnly) { // Windows compatibility: Remove only throws when it needs to do work, add throws always. throw new CryptographicException(SR.Cryptography_X509_StoreReadOnly); } // Save the collection to a local so it's consistent for the whole method List <X509Certificate2> certificates = _certificates; OpenSslX509CertificateReader cert = (OpenSslX509CertificateReader)certPal; using (X509Certificate2 copy = new X509Certificate2(cert.DuplicateHandles())) { // certificates will be null if anything has changed since the last call to // get_Certificates; including Add being called without get_Certificates being // called at all. if (certificates != null) { foreach (X509Certificate2 inCollection in certificates) { if (inCollection.Equals(copy)) { if (!copy.HasPrivateKey || inCollection.HasPrivateKey) { // If the existing store only knows about a public key, but we're // adding a public+private pair, continue with the add. // // So, therefore, if we aren't adding a private key, or already have one, // we don't need to do anything. return; } } } } // This may well be the first time that we've added something to this store. Directory.CreateDirectory(_storePath); string thumbprint = copy.Thumbprint; bool findOpenSlot; // The odds are low that we'd have a thumbprint colission, but check anyways. string existingFilename = FindExistingFilename(copy, _storePath, out findOpenSlot); if (existingFilename != null) { bool dataExistsAlready = false; // If the file on disk is just a public key, but we're trying to add a private key, // we'll want to overwrite it. if (copy.HasPrivateKey) { try { using (X509Certificate2 fromFile = new X509Certificate2(existingFilename)) { if (fromFile.HasPrivateKey) { // We have a private key, the file has a private key, we're done here. dataExistsAlready = true; } } } catch (CryptographicException) { // We can't read this file anymore, but a moment ago it was this certificate, // so go ahead and overwrite it. } } else { // If we're just a public key then the file has at least as much data as we do. dataExistsAlready = true; } if (dataExistsAlready) { // The file was added but our collection hasn't resynced yet. // Set _certificates to null to force a resync. _certificates = null; return; } } string destinationFilename; FileMode mode = FileMode.CreateNew; if (existingFilename != null) { destinationFilename = existingFilename; mode = FileMode.Create; } else if (findOpenSlot) { destinationFilename = FindOpenSlot(thumbprint); } else { destinationFilename = Path.Combine(_storePath, thumbprint + PfxExtension); } using (FileStream stream = new FileStream(destinationFilename, mode)) { byte[] pkcs12 = copy.Export(X509ContentType.Pkcs12); stream.Write(pkcs12, 0, pkcs12.Length); } #if DEBUG // Verify that we're creating files with u+rw and o-rw, g-rw. const Interop.Sys.Permissions requiredPermissions = Interop.Sys.Permissions.S_IRUSR | Interop.Sys.Permissions.S_IWUSR; const Interop.Sys.Permissions forbiddenPermissions = Interop.Sys.Permissions.S_IROTH | Interop.Sys.Permissions.S_IWOTH | Interop.Sys.Permissions.S_IRGRP | Interop.Sys.Permissions.S_IWGRP; Interop.Sys.FileStatus stat; Debug.Assert(Interop.Sys.Stat(destinationFilename, out stat) == 0); Debug.Assert((stat.Mode & (int)requiredPermissions) != 0, "Created PFX has insufficient permissions to function"); Debug.Assert((stat.Mode & (int)forbiddenPermissions) == 0, "Created PFX has too broad of permissions"); #endif } // Null out _certificates so the next call to get_Certificates causes a re-scan. _certificates = null; }
private static FileStream?CreateSharedBackingObjectUsingMemory( Interop.Sys.MemoryMappedProtections protections, long capacity, HandleInheritability inheritability) { // Determine the flags to use when creating the shared memory object Interop.Sys.OpenFlags flags = (protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0 ? Interop.Sys.OpenFlags.O_RDWR : Interop.Sys.OpenFlags.O_RDONLY; flags |= Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_EXCL; // CreateNew // Determine the permissions with which to create the file Interop.Sys.Permissions perms = default(Interop.Sys.Permissions); if ((protections & Interop.Sys.MemoryMappedProtections.PROT_READ) != 0) { perms |= Interop.Sys.Permissions.S_IRUSR; } if ((protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0) { perms |= Interop.Sys.Permissions.S_IWUSR; } if ((protections & Interop.Sys.MemoryMappedProtections.PROT_EXEC) != 0) { perms |= Interop.Sys.Permissions.S_IXUSR; } string mapName; SafeFileHandle fd; do { mapName = GenerateMapName(); fd = Interop.Sys.ShmOpen(mapName, flags, (int)perms); // Create the shared memory object. if (fd.IsInvalid) { Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); fd.Dispose(); if (errorInfo.Error == Interop.Error.ENOTSUP) { // If ShmOpen is not supported, fall back to file backing object. // Note that the System.Native shim will force this failure on platforms where // the result of native shm_open does not work well with our subsequent call to mmap. return(null); } else if (errorInfo.Error != Interop.Error.EEXIST) // map with same name already existed { throw Interop.GetExceptionForIoErrno(errorInfo); } } } while (fd.IsInvalid); try { // Unlink the shared memory object immediately so that it'll go away once all handles // to it are closed (as with opened then unlinked files, it'll remain usable via // the open handles even though it's unlinked and can't be opened anew via its name). Interop.CheckIo(Interop.Sys.ShmUnlink(mapName)); // Give it the right capacity. We do this directly with ftruncate rather // than via FileStream.SetLength after the FileStream is created because, on some systems, // lseek fails on shared memory objects, causing the FileStream to think it's unseekable, // causing it to preemptively throw from SetLength. Interop.CheckIo(Interop.Sys.FTruncate(fd, capacity)); // shm_open sets CLOEXEC implicitly. If the inheritability requested is Inheritable, remove CLOEXEC. if (inheritability == HandleInheritability.Inheritable && Interop.Sys.Fcntl.SetFD(fd, 0) == -1) { throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo()); } // Wrap the file descriptor in a stream and return it. return(new FileStream(fd, TranslateProtectionsToFileAccess(protections))); } catch { fd.Dispose(); throw; }