summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/lib/lsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/lib/lsa.c')
-rw-r--r--private/nw/svcdlls/nwwks/lib/lsa.c537
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;
+}