示例#1
0
        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);
        }
示例#2
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;
        }
示例#5
0
        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;
            }