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