diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/nw/svcdlls/nwwks/lib/lsa.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to '')
-rw-r--r-- | private/nw/svcdlls/nwwks/lib/lsa.c | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/lib/lsa.c b/private/nw/svcdlls/nwwks/lib/lsa.c new file mode 100644 index 000000000..1dc664aa4 --- /dev/null +++ b/private/nw/svcdlls/nwwks/lib/lsa.c @@ -0,0 +1,537 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + lsa.c + +Abstract: + + This module provides helpers to call LSA, particularly for + manipulating secret objects. + +Author: + + Rita Wong (ritaw) 22-Apr-1993 + +--*/ + +#include <stdlib.h> + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> + +#include <windef.h> +#include <winerror.h> +#include <winbase.h> + +#include <nwlsa.h> + +//-------------------------------------------------------------------// +// // +// Constants and Macros // +// // +//-------------------------------------------------------------------// + +#define NW_SECRET_PREFIX L"_MS_NWCS_" + + +DWORD +NwOpenPolicy( + IN ACCESS_MASK DesiredAccess, + OUT LSA_HANDLE *PolicyHandle + ) +/*++ + +Routine Description: + + This function gets a handle to the local security policy by calling + LsaOpenPolicy. + +Arguments: + + DesiredAccess - Supplies the desired access to the local security + policy. + + PolicyHandle - Receives a handle to the opened policy. + +Return Value: + + NO_ERROR - Policy handle is returned. + + Error from LSA. + +--*/ +{ + NTSTATUS ntstatus; + OBJECT_ATTRIBUTES ObjAttributes; + + + // + // Open a handle to the local security policy. Initialize the + // objects attributes structure first. + // + InitializeObjectAttributes( + &ObjAttributes, + NULL, + 0L, + NULL, + NULL + ); + + ntstatus = LsaOpenPolicy( + NULL, + &ObjAttributes, + DesiredAccess, + PolicyHandle + ); + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION: LsaOpenPolicy returns %08lx\n", + ntstatus)); + + return RtlNtStatusToDosError(ntstatus); + } + + return NO_ERROR; +} + + +DWORD +NwOpenSecret( + IN ACCESS_MASK DesiredAccess, + IN LSA_HANDLE PolicyHandle, + IN LPWSTR LsaSecretName, + OUT PLSA_HANDLE SecretHandle + ) +/*++ + +Routine Description: + + This function opens a handle to the specified secret object. + +Arguments: + + DesiredAccess - Supplies the desired access to the secret object. + + PolicyHandle - Supplies a handle to an already opened LSA policy. + + LsaSecretName - Supplies the name of the secret to open. + + SecretHandle - Receives the handle of the opened secret. + +Return Value: + + NO_ERROR - Secret handle is returned. + + Error from LSA. + +--*/ +{ + NTSTATUS ntstatus; + UNICODE_STRING SecretNameString; + + + RtlInitUnicodeString(&SecretNameString, LsaSecretName); + + ntstatus = LsaOpenSecret( + PolicyHandle, + &SecretNameString, + DesiredAccess, + SecretHandle + ); + + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION: LsaOpenSecret %ws returns %08lx\n", + LsaSecretName, ntstatus)); + + return RtlNtStatusToDosError(ntstatus); + } + + return NO_ERROR; +} + + +DWORD +NwFormSecretName( + IN LPWSTR Qualifier, + OUT LPWSTR *LsaSecretName + ) +/*++ + +Routine Description: + + This function creates a secret name from the user name. + It also allocates the buffer to return the created secret name which + must be freed by the caller using LocalFree when done with it. + +Arguments: + + Qualifier - Supplies the qualifier which forms part of part of the secret + object name we are creating. + + LsaSecretName - Receives a pointer to the buffer which contains the + secret object name. + +Return Value: + + NO_ERROR - Successfully returned secret name. + + ERROR_NOT_ENOUGH_MEMORY - Failed to allocate buffer to hold the secret + name. + +--*/ +{ + if ((*LsaSecretName = (LPWSTR)LocalAlloc( + 0, + (wcslen(NW_SECRET_PREFIX) + + wcslen(Qualifier) + + 1) * sizeof(WCHAR) + )) == NULL) { + + KdPrint(("NWWORKSTATION: NwFormSecretName: LocalAlloc failed %lu\n", + GetLastError())); + return ERROR_NOT_ENOUGH_MEMORY; + } + + wcscpy(*LsaSecretName, NW_SECRET_PREFIX); + wcscat(*LsaSecretName, Qualifier); + + return NO_ERROR; +} + + + +DWORD +NwSetPassword( + IN LPWSTR Qualifier, + IN LPWSTR Password + ) +/*++ + +Routine Description: + + This function opens ( creates one if needed ) the LSA secret object, + and sets it with the specified password. + +Arguments: + + Qualifier - Supplies the qualifier which forms part of part of the secret + object name to be created. + + Password - Supplies the user specified password for an account. + +Return Value: + + NO_ERROR - Secret object for the password is created and set with new value. + + Error from LSA. + +--*/ +{ + DWORD status; + NTSTATUS ntstatus; + LSA_HANDLE PolicyHandle; + + LSA_HANDLE SecretHandle; + UNICODE_STRING SecretNameString; + LPWSTR LsaSecretName; + + UNICODE_STRING NewPasswordString; + UNICODE_STRING OldPasswordString; + + + // + // Open a handle to the local security policy. + // + if ((status = NwOpenPolicy( + POLICY_CREATE_SECRET, + &PolicyHandle + )) != NO_ERROR) { + KdPrint(("NWWORKSTATION: NwCreatePassword: NwOpenPolicy failed\n")); + return status; + } + + // + // Create the LSA secret object. But first, form a secret name. + // + if ((status = NwFormSecretName( + Qualifier, + &LsaSecretName + )) != NO_ERROR) { + (void) LsaClose(PolicyHandle); + return status; + } + + RtlInitUnicodeString(&SecretNameString, LsaSecretName); + + ntstatus = LsaCreateSecret( + PolicyHandle, + &SecretNameString, + SECRET_SET_VALUE | DELETE, + &SecretHandle + ); + + + // + // note: ignore object already exists error. just use the existing + // object. this could be because the user didnt completely cleanup + // during deinstall. the unique names makes it unlikely to be a real + // collision. + // + if ( ntstatus == STATUS_OBJECT_NAME_COLLISION ) { + ntstatus = NwOpenSecret( + SECRET_SET_VALUE, + PolicyHandle, + LsaSecretName, + &SecretHandle + ); + } + + // + // Don't need the name or policy handle anymore. + // + (void) LocalFree((HLOCAL) LsaSecretName); + (void) LsaClose(PolicyHandle); + + if (! NT_SUCCESS(ntstatus)) { + + KdPrint(("NWWORKSTATION: NwCreatePassword: LsaCreateSecret or LsaOpenSecret returned %08lx for %ws\n", ntstatus, LsaSecretName)); + + return RtlNtStatusToDosError(ntstatus); + } + + + RtlInitUnicodeString(&OldPasswordString, NULL); + RtlInitUnicodeString(&NewPasswordString, Password); + + ntstatus = LsaSetSecret( + SecretHandle, + &NewPasswordString, + &OldPasswordString + ); + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION NwCreatePassword: LsaSetSecret returned %08lx\n", + ntstatus)); + + status = RtlNtStatusToDosError(ntstatus); + + // + // Delete the secret object + // + ntstatus = LsaDelete(SecretHandle); + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION: NwCreatePassword: LsaDelete to restore back to original returned %08lx\n", + ntstatus)); + (void) LsaClose(SecretHandle); + } + + // + // Secret handle is closed by LsaDelete if successfully deleted. + // + return status; + } + + (void) LsaClose(SecretHandle); + + return NO_ERROR; +} + + + +DWORD +NwDeletePassword( + IN LPWSTR Qualifier + ) +/*++ + +Routine Description: + + This function deletes the LSA secret object whose name is derived + from the specified Qualifier. + +Arguments: + + Qualifier - Supplies the qualifier which forms part of part of the secret + object name to be deleted. + +Return Value: + + NO_ERROR - Secret object for password is deleted. + + Error from LSA. + +--*/ +{ + DWORD status; + NTSTATUS ntstatus; + + LSA_HANDLE PolicyHandle; + + LSA_HANDLE SecretHandle; + LPWSTR LsaSecretName; + + + // + // Open a handle to the local security policy. + // + if ((status = NwOpenPolicy( + POLICY_VIEW_LOCAL_INFORMATION, + &PolicyHandle + )) != NO_ERROR) { + KdPrint(("NWWORKSTATION: NwDeletePassword: NwOpenPolicy failed\n")); + return status; + } + + // + // Get the secret object name from the specified user name. + // + if ((status = NwFormSecretName( + Qualifier, + &LsaSecretName + )) != NO_ERROR) { + (void) LsaClose(PolicyHandle); + return status; + } + + status = NwOpenSecret( + DELETE, + PolicyHandle, + LsaSecretName, + &SecretHandle + ); + + // + // Don't need the name or policy handle anymore. + // + (void) LocalFree((HLOCAL) LsaSecretName); + (void) LsaClose(PolicyHandle); + + if (status != NO_ERROR) { + KdPrint(("NWWORKSTATION: NwDeletePassword: NwOpenSecret failed\n")); + return status; + } + + ntstatus = LsaDelete(SecretHandle); + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION: NwDeletePassword: LsaDelete returned %08lx\n", + ntstatus)); + (void) LsaClose(SecretHandle); + return RtlNtStatusToDosError(ntstatus); + } + + return NO_ERROR; +} + + + +DWORD +NwGetPassword( + IN LPWSTR Qualifier, + OUT PUNICODE_STRING *Password, + OUT PUNICODE_STRING *OldPassword + ) +/*++ + +Routine Description: + + This function retrieves the current password and old password + values from the service secret object given the user name. + +Arguments: + + Qualifier - Supplies the qualifier which forms part of the key to the + secret object name. + + Password - Receives a pointer to the string structure that contains + the password. + + OldPassword - Receives a pointer to the string structure that + contains the old password. + +Return Value: + + NO_ERROR - Secret object for password is changed to new value. + + Error from LSA. + +--*/ +{ + DWORD status; + NTSTATUS ntstatus; + + LSA_HANDLE PolicyHandle; + LSA_HANDLE SecretHandle; + + LPWSTR LsaSecretName; + + + // + // Open a handle to the local security policy to read the + // value of the secret. + // + if ((status = NwOpenPolicy( + POLICY_VIEW_LOCAL_INFORMATION, + &PolicyHandle + )) != NO_ERROR) { + return status; + } + + // + // Get the secret object name from the specified user name. + // + if ((status = NwFormSecretName( + Qualifier, + &LsaSecretName + )) != NO_ERROR) { + (void) LsaClose(PolicyHandle); + return status; + } + + status = NwOpenSecret( + SECRET_QUERY_VALUE, + PolicyHandle, + LsaSecretName, + &SecretHandle + ); + + // + // Don't need the name or policy handle anymore. + // + (void) LocalFree((HLOCAL) LsaSecretName); + (void) LsaClose(PolicyHandle); + + if (status != NO_ERROR) { + KdPrint(("NWWORKSTATION: ScGetSecret: ScOpenSecret failed\n")); + return status; + } + + // + // Query the old value of the secret object so that we can + // we can restore it if we fail to change the password later. + // + ntstatus = LsaQuerySecret( + SecretHandle, + Password, + NULL, // don't need set time + OldPassword, + NULL // don't need set time + ); + + (void) LsaClose(SecretHandle); + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION: NwGetPassword: LsaQuerySecret for previous values returned %08lx\n", + ntstatus)); + + return RtlNtStatusToDosError(ntstatus); + } + + return NO_ERROR; +} |