/// <summary> /// Set the group attribute flags. /// </summary> /// <param name="attributes">The attributes to set.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The NT status code.</returns> public NtStatus SetGroupAttributes(GroupAttributes attributes, bool throw_on_error) { using (var buffer = new GROUP_ATTRIBUTE_INFORMATION() { Attributes = attributes }.ToBuffer()) { return(SecurityNativeMethods.SamSetInformationGroup(Handle, GROUP_INFORMATION_CLASS.GroupAttributeInformation, buffer).ToNtException(throw_on_error)); } }
private string GetTargetName() { using (var buffer = new SafeStructureInOutBuffer <SecPkgContext_ClientSpecifiedTarget>()) { var result = SecurityNativeMethods.QueryContextAttributesEx(_context, SECPKG_ATTR.CLIENT_SPECIFIED_TARGET, buffer, buffer.Length); if (result == SecStatusCode.Success) { return(Marshal.PtrToStringUni(buffer.Result.sTargetName)); } } return(string.Empty); }
private NtResult <T> Query <T, S>(UserInformationClass info_class, Func <S, T> func, bool throw_on_error) where S : struct { return(SecurityNativeMethods.SamQueryInformationUser(Handle, info_class, out SafeSamMemoryBuffer buffer).CreateResult(throw_on_error, () => { using (buffer) { buffer.Initialize <S>(1); return func(buffer.Read <S>(0)); } })); }
/// <summary> /// Set the Auditing Security Descriptor. /// </summary> /// <param name="security_information">The security information to set.</param> /// <param name="security_descriptor">The security descriptor to set.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The NT status code.</returns> public static NtStatus SetSecurity(SecurityInformation security_information, SecurityDescriptor security_descriptor, bool throw_on_error) { using (var buffer = security_descriptor.ToSafeBuffer()) { if (!SecurityNativeMethods.AuditSetSecurity(security_information, buffer)) { return(NtObjectUtils.MapDosErrorToStatus().ToNtException(throw_on_error)); } return(NtStatus.STATUS_SUCCESS); } }
/// <summary> /// Query the Auditing Security Descriptor. /// </summary> /// <param name="security_information">The security information to query.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The security descriptor.</returns> public static NtResult <SecurityDescriptor> QuerySecurity(SecurityInformation security_information, bool throw_on_error) { if (!SecurityNativeMethods.AuditQuerySecurity(security_information, out SafeAuditBuffer buffer)) { return(NtObjectUtils.MapDosErrorToStatus().CreateResultFromError <SecurityDescriptor>(throw_on_error)); } using (buffer) { return(SecurityDescriptor.Parse(buffer, NtType, throw_on_error)); } }
private void Dispose(bool _) { if (_context != null) { SecurityNativeMethods.DeleteSecurityContext(_context); } if (OwnsCredentials) { _creds?.Dispose(); } }
/// <summary> /// Convert a RID to a SID for the current object. /// </summary> /// <param name="relative_id">The relative ID.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The converted SID.</returns> public NtResult <Sid> RidToSid(uint relative_id, bool throw_on_error) { return(SecurityNativeMethods.SamRidToSid(Handle, relative_id, out SafeSamMemoryBuffer buffer).CreateResult(throw_on_error, () => { using (buffer) { return new Sid(buffer); } } )); }
/// <summary> /// Store LSA private data. /// </summary> /// <param name="keyname">The name of the key.</param> /// <param name="data">The data to store. If you pass null then the value will be deleted.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The NT status code.</returns> public NtStatus StorePrivateData(string keyname, byte[] data, bool throw_on_error) { if (keyname is null) { throw new ArgumentNullException(nameof(keyname)); } using (var data_buffer = data == null ? UnicodeStringBytesSafeBuffer.Null : new UnicodeStringBytesSafeBuffer(data)) { return(SecurityNativeMethods.LsaStorePrivateData(Handle, new UnicodeString(keyname), data_buffer).ToNtException(throw_on_error)); } }
/// <summary> /// Get an authentication package by name. /// </summary> /// <param name="package">The name of the package.</param> /// <returns>The authentication package.</returns> public static AuthenticationPackage FromName(string package) { SecurityNativeMethods.QuerySecurityPackageInfo(package, out IntPtr package_info).CheckResult(); try { return(new AuthenticationPackage(package_info)); } finally { SecurityNativeMethods.FreeContextBuffer(package_info); } }
/// <summary> /// Perform an Access Check. /// </summary> /// <param name="sd">The security descriptor for the check.</param> /// <param name="optional_sd">Optional list of security descriptors to merge.</param> /// <param name="desired_access">The desired access.</param> /// <param name="principal">Optional Principal SID.</param> /// <param name="object_types">Optional list of object types.</param> /// <param name="type">NT Type for access checking.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The list of access check results.</returns> /// <remarks>The list of object types is restricted to 256 entries for remote access checks.</remarks> public NtResult <AuthZAccessCheckResult[]> AccessCheck(SecurityDescriptor sd, IEnumerable <SecurityDescriptor> optional_sd, AccessMask desired_access, Sid principal, IEnumerable <ObjectTypeEntry> object_types, NtType type, bool throw_on_error) { if (sd is null) { throw new ArgumentNullException(nameof(sd)); } if (type is null) { throw new ArgumentNullException(nameof(type)); } using (var list = new DisposableList()) { AUTHZ_ACCESS_REQUEST request = new AUTHZ_ACCESS_REQUEST(); request.DesiredAccess = desired_access; if (principal != null) { request.PrincipalSelfSid = list.AddResource(principal.ToSafeBuffer()).DangerousGetHandle(); } int result_count = 1; var object_list = NtSecurity.ConvertObjectTypes(object_types, list); if (object_list?.Length > 0) { result_count = object_list.Length; request.ObjectTypeList = list.AddResource(object_list.ToBuffer()).DangerousGetHandle(); request.ObjectTypeListLength = object_list.Length; } var sd_buffer = list.AddResource(sd.ToSafeBuffer()); int optional_sd_count = optional_sd?.Count() ?? 0; IntPtr[] optional_sd_buffers = null; if (optional_sd_count > 0) { optional_sd_buffers = optional_sd.Select(s => list.AddResource(s.ToSafeBuffer()).DangerousGetHandle()).ToArray(); } AUTHZ_ACCESS_REPLY reply = new AUTHZ_ACCESS_REPLY(); reply.ResultListLength = result_count; var error_buffer = list.AddResource(new int[result_count].ToBuffer()); reply.Error = error_buffer.DangerousGetHandle(); var access_buffer = list.AddResource(new AccessMask[result_count].ToBuffer()); reply.GrantedAccessMask = access_buffer.DangerousGetHandle(); var audit_buffer = list.AddResource(new int[result_count].ToBuffer()); reply.SaclEvaluationResults = audit_buffer.DangerousGetHandle(); return(SecurityNativeMethods.AuthzAccessCheck(AuthZAccessCheckFlags.None, _handle, ref request, IntPtr.Zero, sd_buffer, optional_sd_buffers, optional_sd_count, ref reply, IntPtr.Zero).CreateWin32Result(throw_on_error, () => CreateResult(result_count, error_buffer, access_buffer, object_types?.ToArray(), type))); } }
/// <summary> /// Change a user's password. /// </summary> /// <param name="old_password">The old password.</param> /// <param name="new_password">The new password.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The NT status code.</returns> public NtStatus ChangePassword(SecureString old_password, SecureString new_password, bool throw_on_error) { using (var list = new DisposableList()) { var old_pwd_buf = list.AddResource(new SecureStringMarshalBuffer(old_password)); var new_pwd_buf = list.AddResource(new SecureStringMarshalBuffer(new_password)); return(SecurityNativeMethods.SamChangePasswordUser(Handle, new UnicodeStringSecure(old_pwd_buf, old_password.Length), new UnicodeStringSecure(new_pwd_buf, new_password.Length)).ToNtException(throw_on_error)); } }
/// <summary> /// Query group attribute flags. /// </summary> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The group attribute flags.</returns> public NtResult <GroupAttributes> QueryGroupAttributes(bool throw_on_error) { return(SecurityNativeMethods.SamQueryInformationGroup(Handle, GROUP_INFORMATION_CLASS.GroupAttributeInformation, out SafeSamMemoryBuffer buffer).CreateResult(throw_on_error, () => { using (buffer) { buffer.Initialize <GROUP_ATTRIBUTE_INFORMATION>(1); return buffer.Read <GROUP_ATTRIBUTE_INFORMATION>(0).Attributes; } })); }
/// <summary> /// Get the security descriptor specifying which parts to retrieve /// </summary> /// <param name="security_information">What parts of the security descriptor to retrieve</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The security descriptor</returns> public NtResult <SecurityDescriptor> GetSecurityDescriptor(SecurityInformation security_information, bool throw_on_error) { var status = SecurityNativeMethods.SamQuerySecurityObject(_handle, security_information, out SafeSamMemoryBuffer sd); if (!status.IsSuccess()) { return(status.CreateResultFromError <SecurityDescriptor>(throw_on_error)); } using (sd) { return(SecurityDescriptor.Parse(sd, NtType, throw_on_error)); } }
internal override void FromBuffer(SecBuffer buffer) { if (buffer.pvBuffer == IntPtr.Zero) { _array = new byte[0]; return; } _array = new byte[buffer.cbBuffer]; Marshal.Copy(buffer.pvBuffer, _array, 0, _array.Length); SecurityNativeMethods.FreeContextBuffer(buffer.pvBuffer); buffer.pvBuffer = IntPtr.Zero; _type = buffer.BufferType; }
internal static byte[] GetSessionKey(SecHandle context) { using (var buffer = new SafeStructureInOutBuffer <SecPkgContext_SessionKey>()) { var result = SecurityNativeMethods.QueryContextAttributesEx(context, SECPKG_ATTR.SESSION_KEY, buffer, buffer.Length); if (result == SecStatusCode.Success) { byte[] ret = new byte[buffer.Result.SessionKeyLength]; Marshal.Copy(buffer.Result.SessionKey, ret, 0, ret.Length); return(ret); } } return(new byte[0]); }
private static X509Certificate2 GetCertificate(SecHandle context, SECPKG_ATTR attr) { var cert = QueryContextAttribute <IntPtr>(context, attr); try { return(new X509Certificate2(cert)); } finally { SecurityNativeMethods.CertFreeCertificateContext(cert); } }
internal static SecStatusCode InitializeSecurityContext( CredentialHandle credential, SecHandle context, string target_name, InitializeContextReqFlags req_attributes, SecDataRep data_rep, IList <SecurityBuffer> input, SecHandle new_context, IList <SecurityBuffer> output, out InitializeContextRetFlags ret_attributes, LargeInteger expiry, bool throw_on_error) { using (DisposableList list = new DisposableList()) { var input_buffers = input?.ToBufferList(list); var output_buffers = output?.ToBufferList(list); var in_buffer_desc = input_buffers.ToDesc(list); var out_buffer_desc = output_buffers.ToDesc(list); var result = SecurityNativeMethods.InitializeSecurityContext(credential.CredHandle, context, target_name, req_attributes, 0, data_rep, in_buffer_desc, 0, new_context, out_buffer_desc, out ret_attributes, expiry).CheckResult(throw_on_error); if (!result.IsSuccess()) { return(result); } try { if (result == SecStatusCode.SEC_I_COMPLETE_NEEDED || result == SecStatusCode.SEC_I_COMPLETE_AND_CONTINUE) { var comp_result = SecurityNativeMethods.CompleteAuthToken(new_context, out_buffer_desc).CheckResult(throw_on_error); if (!comp_result.IsSuccess()) { return(comp_result); } } } finally { if (result.IsSuccess()) { output?.UpdateBuffers(out_buffer_desc); } } return(result); } }
/// <summary> /// Enumerate account rights for a SID. /// </summary> /// <param name="sid">The SID to enumerate for.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The list of assigned account rights.</returns> public NtResult <IReadOnlyList <string> > EnumerateAccountRights(Sid sid, bool throw_on_error) { if (sid is null) { throw new ArgumentNullException(nameof(sid)); } using (var sid_buffer = sid.ToSafeBuffer()) { return(SecurityNativeMethods.LsaEnumerateAccountRights(Handle, sid_buffer, out SafeLsaMemoryBuffer buffer, out int count) .CreateResult(throw_on_error, () => ParseRights(buffer, count))); } }
/// <summary> /// Set a user's password. /// </summary> /// <param name="password">The password to set.</param> /// <param name="expired">Whether the password has expired.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The NT status code.</returns> public NtStatus SetPassword(SecureString password, bool expired, bool throw_on_error) { using (var pwd_buf = new SecureStringMarshalBuffer(password)) { var set_info = new USER_SET_PASSWORD_INFORMATION(); set_info.Password = new UnicodeStringInSecure(pwd_buf, password.Length); set_info.PasswordExpired = expired; using (var buf = set_info.ToBuffer()) { return(SecurityNativeMethods.SamSetInformationUser(Handle, UserInformationClass.UserSetPasswordInformation, buf).ToNtException(throw_on_error)); } } }
/// <summary> /// Query the global SACL. /// </summary> /// <param name="type">The global SACL type.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The global SACL in a Security Descriptor.</returns> public static NtResult <SecurityDescriptor> QueryGlobalSacl(AuditGlobalSaclType type, bool throw_on_error) { if (!SecurityNativeMethods.AuditQueryGlobalSacl(type.ToString(), out SafeAuditBuffer buffer)) { return(NtObjectUtils.MapDosErrorToStatus().CreateResultFromError <SecurityDescriptor>(throw_on_error)); } using (buffer) { NtType nt_type = type == AuditGlobalSaclType.File ? NtType.GetTypeByType <NtFile>() : NtType.GetTypeByType <NtKey>(); return(new SecurityDescriptor(nt_type) { Sacl = new Acl(buffer.DangerousGetHandle(), false) }.CreateResult()); } }
/// <summary> /// Set the global SACL. /// </summary> /// <param name="type">The global SACL type.</param> /// <param name="security_descriptor">The SACL to set in an Security Descriptor.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The NT status code.</returns> public static NtStatus SetGlobalSacl(AuditGlobalSaclType type, SecurityDescriptor security_descriptor, bool throw_on_error) { if (!security_descriptor.SaclPresent) { throw new ArgumentException("Must specify a SACL."); } using (var buffer = security_descriptor.Sacl.ToSafeBuffer()) { if (!SecurityNativeMethods.AuditSetGlobalSacl(type.ToString(), buffer)) { return(NtObjectUtils.MapDosErrorToStatus().ToNtException(throw_on_error)); } return(NtStatus.STATUS_SUCCESS); } }
private bool GenClientContext(AuthenticationToken token) { using (DisposableList list = new DisposableList()) { SecStatusCode result = 0; SecBuffer out_sec_buffer = list.AddResource(new SecBuffer(SecBufferType.Token, 64 * 1024)); SecBufferDesc out_buffer_desc = list.AddResource(new SecBufferDesc(out_sec_buffer)); InitializeContextRetFlags flags; LargeInteger expiry = new LargeInteger(); if (token != null) { List <SecBuffer> buffers = new List <SecBuffer>(); buffers.Add(list.AddResource(new SecBuffer(SecBufferType.Token, token.ToArray()))); if (_channel_binding != null) { buffers.Add(list.AddResource(SecBuffer.CreateForChannelBinding(_channel_binding))); } SecBufferDesc in_buffer_desc = list.AddResource(new SecBufferDesc(buffers.ToArray())); result = SecurityNativeMethods.InitializeSecurityContext(_creds.CredHandle, _context, _target, _req_attributes, 0, _data_rep, in_buffer_desc, 0, _context, out_buffer_desc, out flags, expiry).CheckResult(); Flags = flags; } else { SecBufferDesc in_buffer_desc = null; List <SecBuffer> buffers = new List <SecBuffer>(); if (_channel_binding != null) { buffers.Add(list.AddResource(SecBuffer.CreateForChannelBinding(_channel_binding))); in_buffer_desc = list.AddResource(new SecBufferDesc(buffers.ToArray())); } result = SecurityNativeMethods.InitializeSecurityContext(_creds.CredHandle, null, _target, _req_attributes, 0, _data_rep, in_buffer_desc, 0, _context, out_buffer_desc, out flags, expiry).CheckResult(); } Expiry = expiry.QuadPart; Flags = flags; if (result == SecStatusCode.CompleteNeeded || result == SecStatusCode.CompleteAndContinue) { SecurityNativeMethods.CompleteAuthToken(_context, out_buffer_desc).CheckResult(); } Token = AuthenticationToken.Parse(_creds.PackageName, _token_count++, true, out_buffer_desc.ToArray()[0].ToArray()); return(!(result == SecStatusCode.ContinueNeeded || result == SecStatusCode.CompleteAndContinue)); } }
/// <summary> /// Open trusted domain object. /// </summary> /// <param name="sid">The SID of the trusted domain.</param> /// <param name="desired_access">The desired access for the object.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The trusted domain object.</returns> public NtResult <LsaTrustedDomain> OpenTrustedDomain(Sid sid, LsaTrustedDomainAccessRights desired_access, bool throw_on_error) { if (sid is null) { throw new ArgumentNullException(nameof(sid)); } using (var sid_buffer = sid.ToSafeBuffer()) { return(SecurityNativeMethods.LsaOpenTrustedDomain(Handle, sid_buffer, desired_access, out SafeLsaHandle handle).CreateResult(throw_on_error, () => new LsaTrustedDomain(handle, desired_access, null, sid, QueryDomainInfo(sid_buffer), SystemName))); } }
/// <summary> /// Create a new AuthZ resource manager. /// </summary> /// <param name="name">The name of the resource manager, optional.</param> /// <param name="flags">Optional flags for the resource manager.</param> /// <param name="handle_callback_ace">Optional callback to handle callback ACEs.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The created AuthZ resource manager.</returns> public static NtResult <AuthZResourceManager> Create(string name, AuthZResourceManagerInitializeFlags flags, AuthZHandleCallbackAce handle_callback_ace, bool throw_on_error) { AuthZResourceManager ret = new AuthZResourceManager(name); AuthzAccessCheckCallback callback = null; if (handle_callback_ace != null) { ret._handle_callback_ace = handle_callback_ace; callback = ret.HandleCallbackAce; } return(SecurityNativeMethods.AuthzInitializeResourceManager(flags, callback, IntPtr.Zero, IntPtr.Zero, name, out ret._handle).CreateWin32Result(throw_on_error, () => ret)); }
private static X509Certificate2 GetCertificate(SecHandle context, SECPKG_ATTR attr) { using (var buffer = new SafeStructureInOutBuffer <IntPtr>()) { SecurityNativeMethods.QueryContextAttributesEx(context, attr, buffer, buffer.Length).CheckResult(); try { return(new X509Certificate2(buffer.Result)); } finally { SecurityNativeMethods.CertFreeCertificateContext(buffer.Result); } } }
/// <summary> /// Set AppContainer Information to Context. /// </summary> /// <param name="package_sid">The package SID.</param> /// <param name="capabilities">List of capabilities.</param> /// <param name="throw_on_error">True to throw on error</param> /// <returns>The NT status code.</returns> public NtStatus SetAppContainer(Sid package_sid, IEnumerable <UserGroup> capabilities, bool throw_on_error) { using (var list = new DisposableList()) { var sid_buffer = list.AddResource(package_sid.ToSafeBuffer()); var cap_sids = capabilities?.ToArray() ?? new UserGroup[0]; SafeTokenGroupsBuffer cap_buffer = list.AddResource(SafeTokenGroupsBuffer.Create(cap_sids)); SafeBuffer buffer = cap_sids.Length > 0 ? cap_buffer.Data : SafeHGlobalBuffer.Null; if (!SecurityNativeMethods.AuthzSetAppContainerInformation(_handle, sid_buffer, cap_sids.Length, buffer)) { return(NtObjectUtils.MapDosErrorToStatus().ToNtException(throw_on_error)); } return(NtStatus.STATUS_SUCCESS); } }
/// <summary> /// Lookup the domain SID for a domain name. /// </summary> /// <param name="name">The name of the domain.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The domain SID.</returns> public NtResult <Sid> LookupDomain(string name, bool throw_on_error) { if (string.IsNullOrEmpty(name)) { throw new System.ArgumentException($"'{nameof(name)}' cannot be null or empty.", nameof(name)); } return(SecurityNativeMethods.SamLookupDomainInSamServer(Handle, new UnicodeString(name), out SafeSamMemoryBuffer domain_id).CreateResult(throw_on_error, () => { using (domain_id) { return new Sid(domain_id); } })); }
/// <summary> /// Enumerate accounts with a user right. /// </summary> /// <param name="user_right">The name of the user right.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The list of SIDs with the user right.</returns> public NtResult <IReadOnlyList <Sid> > EnumerateAccountsWithUserRight(string user_right, bool throw_on_error) { if (user_right is null) { throw new ArgumentNullException(nameof(user_right)); } NtStatus status = SecurityNativeMethods.LsaEnumerateAccountsWithUserRight(Handle, new UnicodeString(user_right), out SafeLsaMemoryBuffer buffer, out int count); if (status == NtStatus.STATUS_NO_MORE_ENTRIES) { return(new List <Sid>().AsReadOnly().CreateResult <IReadOnlyList <Sid> >()); } return(status.CreateResult(throw_on_error, () => ParseSids(buffer, count))); }
private static NtResult <List <Sid> > GetSids(SafeLsaHandle policy, string name, bool throw_on_error) { if (name is null) { throw new ArgumentNullException(nameof(name)); } NtStatus status = SecurityNativeMethods.LsaEnumerateAccountsWithUserRight(policy, new UnicodeString(name), out SafeLsaMemoryBuffer buffer, out int count); if (status == NtStatus.STATUS_NO_MORE_ENTRIES) { return(new List <Sid>().CreateResult()); } return(status.CreateResult(throw_on_error, () => ParseSids(buffer, count))); }
internal static bool VerifySignature( SecHandle context, IEnumerable <SecurityBuffer> messages, byte[] signature, int sequence_no) { List <SecurityBuffer> sig_buffers = new List <SecurityBuffer>(messages); sig_buffers.Add(new SecurityBufferInOut(SecurityBufferType.Token | SecurityBufferType.ReadOnly, signature)); using (var list = new DisposableList()) { List <SecBuffer> buffers = sig_buffers.ToBufferList(list); SecBufferDesc desc = buffers.ToDesc(list); return(SecurityNativeMethods.VerifySignature(context, desc, sequence_no, out int _) == SecStatusCode.SUCCESS); } }