Пример #1
0
        private static FileStream CreateSharedBackingObject(
            Interop.libc.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.libc.OpenFlags flags = (protections & Interop.libc.MemoryMappedProtections.PROT_WRITE) != 0 ?
                                           Interop.libc.OpenFlags.O_RDWR :
                                           Interop.libc.OpenFlags.O_RDONLY;
            flags |= Interop.libc.OpenFlags.O_CREAT | Interop.libc.OpenFlags.O_EXCL; // CreateNew

            // Determine the permissions with which to create the file
            Interop.libc.Permissions perms = default(Interop.libc.Permissions);
            if ((protections & Interop.libc.MemoryMappedProtections.PROT_READ) != 0)
            {
                perms |= Interop.libc.Permissions.S_IRUSR;
            }
            if ((protections & Interop.libc.MemoryMappedProtections.PROT_WRITE) != 0)
            {
                perms |= Interop.libc.Permissions.S_IWUSR;
            }
            if ((protections & Interop.libc.MemoryMappedProtections.PROT_EXEC) != 0)
            {
                perms |= Interop.libc.Permissions.S_IXUSR;
            }

            // Create the shared memory object.
            int fd;

            Interop.CheckIo(fd = Interop.libc.shm_open(mapName, flags, (int)perms), mapName);
            SafeFileHandle fileHandle = new SafeFileHandle((IntPtr)fd, ownsHandle: true);

            try
            {
                // Unlink the shared memory object immediatley 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.libc.shm_unlink(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.libc.ftruncate(fd, capacity));

                // Wrap the file descriptor in a stream and return it.
                return(new FileStream(fileHandle, TranslateProtectionsToFileAccess(protections)));
            }
            catch
            {
                fileHandle.Dispose();
                throw;
            }
        }
Пример #2
0
        /// <summary>Initializes a stream for reading or writing a Unix file.</summary>
        /// <param name="path">The path to the file.</param>
        /// <param name="mode">How the file should be opened.</param>
        /// <param name="access">Whether the file will be read, written, or both.</param>
        /// <param name="share">What other access to the file should be allowed.  This is currently ignored.</param>
        /// <param name="bufferSize">The size of the buffer to use when buffering.</param>
        /// <param name="options">Additional options for working with the file.</param>
        internal UnixFileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, FileStream parent)
            : base(parent)
        {
            // FileStream performs most of the general argument validation.  We can assume here that the arguments
            // are all checked and consistent (e.g. non-null-or-empty path; valid enums in mode, access, share, and options; etc.)
            // Store the arguments
            _path         = path;
            _access       = access;
            _mode         = mode;
            _options      = options;
            _bufferLength = bufferSize;
            _useAsyncIO   = (options & FileOptions.Asynchronous) != 0;

            // Translate the arguments into arguments for an open call
            Interop.libc.OpenFlags   openFlags       = PreOpenConfigurationFromOptions(mode, access, options); // FileShare currently ignored
            Interop.libc.Permissions openPermissions = Interop.libc.Permissions.S_IRWXU;                       // creator has read/write/execute permissions; no permissions for anyone else

            // Open the file and store the safe handle. Subsequent code in this method expects the safe handle to be initialized.
            _fileHandle         = SafeFileHandle.Open(path, openFlags, (int)openPermissions);
            _fileHandle.IsAsync = _useAsyncIO;

            // Lock the file if requested via FileShare.  This is only advisory locking. FileShare.None implies an exclusive
            // lock on the file and all other modes use a shared lock.  While this is not as granular as Windows, not mandatory,
            // and not atomic with file opening, it's better than nothing.
            try
            {
                Interop.libc.LockOperations lockOperation = (share == FileShare.None) ? Interop.libc.LockOperations.LOCK_EX : Interop.libc.LockOperations.LOCK_SH;
                SysCall <Interop.libc.LockOperations, int>((fd, op, _) => Interop.libc.flock(fd, op), lockOperation | Interop.libc.LockOperations.LOCK_NB);
            }
            catch
            {
                _fileHandle.Dispose();
                throw;
            }

            // Support additional options after the file has been opened.
            // These provide hints around how the file will be accessed.
            Interop.libc.Advice fadv =
                _options == FileOptions.RandomAccess ? Interop.libc.Advice.POSIX_FADV_RANDOM :
                _options == FileOptions.SequentialScan ? Interop.libc.Advice.POSIX_FADV_SEQUENTIAL :
                0;
            if (fadv != 0)
            {
                SysCall <Interop.libc.Advice, int>((fd, advice, _) => Interop.libc.posix_fadvise(fd, 0, 0, advice), fadv);
            }

            // Jump to the end of the file if opened as Append.
            if (_mode == FileMode.Append)
            {
                _appendStart = SeekCore(0, SeekOrigin.End);
            }
        }
Пример #3
0
        private static FileStream CreateSharedBackingObject(
            Interop.libc.MemoryMappedProtections protections, long capacity,
            out string mapName, out SafeMemoryMappedFileHandle.FileStreamSource fileStreamSource)
        {
            // The POSIX shared memory object name must begin with '/'.  After that we just want something short and unique.
            mapName          = "/" + MemoryMapObjectFilePrefix + Guid.NewGuid().ToString("N");
            fileStreamSource = SafeMemoryMappedFileHandle.FileStreamSource.ManufacturedSharedMemory;

            // Determine the flags to use when creating the shared memory object
            Interop.libc.OpenFlags flags = (protections & Interop.libc.MemoryMappedProtections.PROT_WRITE) != 0 ?
                                           Interop.libc.OpenFlags.O_RDWR :
                                           Interop.libc.OpenFlags.O_RDONLY;
            flags |= Interop.libc.OpenFlags.O_CREAT | Interop.libc.OpenFlags.O_EXCL; // CreateNew

            // Determine the permissions with which to create the file
            Interop.libc.Permissions perms = default(Interop.libc.Permissions);
            if ((protections & Interop.libc.MemoryMappedProtections.PROT_READ) != 0)
            {
                perms |= Interop.libc.Permissions.S_IRUSR;
            }
            if ((protections & Interop.libc.MemoryMappedProtections.PROT_WRITE) != 0)
            {
                perms |= Interop.libc.Permissions.S_IWUSR;
            }
            if ((protections & Interop.libc.MemoryMappedProtections.PROT_EXEC) != 0)
            {
                perms |= Interop.libc.Permissions.S_IXUSR;
            }

            // Create the shared memory object. Then enlarge it to the requested capacity.
            int fd;

            Interop.CheckIo(fd = Interop.libc.shm_open(mapName, flags, (int)perms), mapName);
            SafeFileHandle fileHandle = new SafeFileHandle((IntPtr)fd, ownsHandle: true);

            // Wrap the handle in a stream and return it.
            var fs = new FileStream(fileHandle, TranslateProtectionsToFileAccess(protections));

            fs.SetLength(capacity);
            return(fs);
        }
Пример #4
0
        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.libc.Permissions requiredPermissions =
                    Interop.libc.Permissions.S_IRUSR |
                    Interop.libc.Permissions.S_IWUSR;

                const Interop.libc.Permissions forbiddenPermissions =
                    Interop.libc.Permissions.S_IROTH |
                    Interop.libc.Permissions.S_IWOTH |
                    Interop.libc.Permissions.S_IRGRP |
                    Interop.libc.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;
        }