/*++ Copyright (c) 1998-2001 Microsoft Corporation Module Name: secutil.c Abstract: Domain Name System (DNS) Library DNS secure update API. Author: Jim Gilroy (jamesg) January, 1998 Revision History: --*/ #include "local.h" // security headers //#define SECURITY_WIN32 //#include "sspi.h" //#include "issperr.h" //#include "rpc.h" //#include "rpcndr.h" //#include "ntdsapi.h" // // Security utilities // DNS_STATUS Dns_CreateSecurityDescriptor( OUT PSECURITY_DESCRIPTOR * ppSD, IN DWORD AclCount, IN PSID * SidPtrArray, IN DWORD * AccessMaskArray ) /*++ Routine Description: Build security descriptor. Arguments: ppSD -- addr to receive SD created AclCount -- number of ACLs to add SidPtrArray -- array of SIDs to create ACLs for AccessMaskArray -- array of access masks corresponding to SIDs Return Value: ERROR_SUCCESS if successful Error code on failure. --*/ { DNS_STATUS status; DWORD i; DWORD lengthAcl; PSECURITY_DESCRIPTOR psd = NULL; PACL pacl; // // calculate space for SD // lengthAcl = sizeof(ACL); for ( i=0; iFlags == SEC_WINNT_AUTH_IDENTITY_UNICODE ); // // allocate credentials struct // - zero for simple cleanup on subfield alloc failures // pauthCopy = ALLOCATE_HEAP_ZERO( sizeof(SEC_WINNT_AUTH_IDENTITY_W) ); if ( !pauthCopy ) { return NULL; } // // copy subfields // // user pauthCopy->UserLength = pAuthIn->UserLength; if ( pAuthIn->UserLength ) { ASSERT( pAuthIn->UserLength == wcslen(pAuthIn->User) ); pauthCopy->User = ALLOCATE_HEAP( (pAuthIn->UserLength + 1) * sizeof(WCHAR) ); if ( ! pauthCopy->User ) { goto Failed; } wcscpy( pauthCopy->User, pAuthIn->User ); } // password // - must allow zero length password pauthCopy->PasswordLength = pAuthIn->PasswordLength; if ( pAuthIn->PasswordLength || pAuthIn->Password ) { ASSERT( pAuthIn->PasswordLength == wcslen(pAuthIn->Password) ); pauthCopy->Password = ALLOCATE_HEAP( (pAuthIn->PasswordLength + 1) * sizeof(WCHAR) ); if ( ! pauthCopy->Password ) { goto Failed; } wcscpy( pauthCopy->Password, pAuthIn->Password ); } // domain pauthCopy->DomainLength = pAuthIn->DomainLength; if ( pAuthIn->DomainLength ) { ASSERT( pAuthIn->DomainLength == wcslen(pAuthIn->Domain) ); pauthCopy->Domain = ALLOCATE_HEAP( (pAuthIn->DomainLength + 1) * sizeof(WCHAR) ); if ( ! pauthCopy->Domain ) { goto Failed; } wcscpy( pauthCopy->Domain, pAuthIn->Domain ); } pauthCopy->Flags = pAuthIn->Flags; DNSDBG( SECURITY, ( "Exit Dns_AllocateAndInitializeCredentialsW()\n" )); return pauthCopy; Failed: // allocation failure // - cleanup what was allocated and get out Dns_FreeAuthIdentityCredentials( pauthCopy ); return( NULL ); } PSEC_WINNT_AUTH_IDENTITY_A Dns_AllocateAndInitializeCredentialsA( IN PSEC_WINNT_AUTH_IDENTITY_A pAuthIn ) /*++ Description: Allocates auth identity info and initializes pAuthIn info Note: it is more work to convert to unicode and call previous function than to call this one Parameters: pAuthIn -- auth identity info Return: Ptr to newly create credentials. NULL on failure. --*/ { PSEC_WINNT_AUTH_IDENTITY_A pauthCopy = NULL; DNSDBG( SECURITY, ( "Call Dns_AllocateAndInitializeCredentialsA\n" )); // // allocate credentials struct // - zero for simple cleanup on subfield alloc failures // if ( !pAuthIn ) { return NULL; } ASSERT( pAuthIn->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI ); // // allocate credentials struct // - zero for simple cleanup on subfield alloc failures // pauthCopy = ALLOCATE_HEAP_ZERO( sizeof(SEC_WINNT_AUTH_IDENTITY_A) ); if ( !pauthCopy ) { return NULL; } // // copy subfields // // user pauthCopy->UserLength = pAuthIn->UserLength; if ( pAuthIn->UserLength ) { ASSERT( pAuthIn->UserLength == strlen(pAuthIn->User) ); pauthCopy->User = ALLOCATE_HEAP( (pAuthIn->UserLength + 1) * sizeof(CHAR) ); if ( ! pauthCopy->User ) { goto Failed; } strcpy( pauthCopy->User, pAuthIn->User ); } // password // - must allow zero length password pauthCopy->PasswordLength = pAuthIn->PasswordLength; if ( pAuthIn->PasswordLength || pAuthIn->Password ) { ASSERT( pAuthIn->PasswordLength == strlen(pAuthIn->Password) ); pauthCopy->Password = ALLOCATE_HEAP( (pAuthIn->PasswordLength + 1) * sizeof(CHAR) ); if ( ! pauthCopy->Password ) { goto Failed; } strcpy( pauthCopy->Password, pAuthIn->Password ); } // domain pauthCopy->DomainLength = pAuthIn->DomainLength; if ( pAuthIn->DomainLength ) { ASSERT( pAuthIn->DomainLength == strlen(pAuthIn->Domain) ); pauthCopy->Domain = ALLOCATE_HEAP( (pAuthIn->DomainLength + 1) * sizeof(CHAR) ); if ( ! pauthCopy->Domain ) { goto Failed; } strcpy( pauthCopy->Domain, pAuthIn->Domain ); } pauthCopy->Flags = pAuthIn->Flags; DNSDBG( SECURITY, ( "Exit Dns_AllocateAndInitializeCredentialsA()\n" )); return pauthCopy; Failed: // allocation failure // - cleanup what was allocated and get out Dns_FreeAuthIdentityCredentials( pauthCopy ); return( NULL ); } VOID Dns_FreeAuthIdentityCredentials( IN OUT PVOID pAuthIn ) /*++ Routine Description (Dns_FreeAuthIdentityCredentials): Free's structure given Arguments: pAuthIn -- in param to free Return Value: None --*/ { register PSEC_WINNT_AUTH_IDENTITY_W pauthId; pauthId = (PSEC_WINNT_AUTH_IDENTITY_W) pAuthIn; if ( !pauthId ) { return; } // // assuming _W and _A structs are equivalent except // for string types // ASSERT( sizeof( SEC_WINNT_AUTH_IDENTITY_W ) == sizeof( SEC_WINNT_AUTH_IDENTITY_A ) ); if ( pauthId->User ) { FREE_HEAP ( pauthId->User ); } if ( pauthId->Password ) { FREE_HEAP ( pauthId->Password ); } if ( pauthId->Domain ) { FREE_HEAP ( pauthId->Domain ); } FREE_HEAP ( pauthId ); } PSEC_WINNT_AUTH_IDENTITY_W Dns_AllocateCredentials( IN PWSTR pwsUserName, IN PWSTR pwsDomain, IN PWSTR pwsPassword ) /*++ Description: Allocates auth identity info and initializes pAuthIn info Parameters: pwsUserName -- user name pwsDomain -- domain name pwsPassword -- password Return: Ptr to newly create credentials. NULL on failure. --*/ { PSEC_WINNT_AUTH_IDENTITY_W pauth = NULL; DWORD length; PWSTR pstr; DNSDBG( SECURITY, ( "Enter Dns_AllocateCredentials()\n" "\tuser = %S\n" "\tdomain = %S\n" "\tpassword = %S\n", pwsUserName, pwsDomain, pwsPassword )); // // allocate credentials struct // - zero for simple cleanup on subfield alloc failures // pauth = ALLOCATE_HEAP_ZERO( sizeof(SEC_WINNT_AUTH_IDENTITY_W) ); if ( !pauth ) { return NULL; } // copy user length = wcslen( pwsUserName ); pstr = ALLOCATE_HEAP( (length + 1) * sizeof(WCHAR) ); if ( ! pstr ) { goto Failed; } wcscpy( pstr, pwsUserName ); pauth->User = pstr; pauth->UserLength = length; // copy domain length = wcslen( pwsDomain ); pstr = ALLOCATE_HEAP( (length + 1) * sizeof(WCHAR) ); if ( ! pstr ) { goto Failed; } wcscpy( pstr, pwsDomain ); pauth->Domain = pstr; pauth->DomainLength = length; // copy password length = wcslen( pwsPassword ); pstr = ALLOCATE_HEAP( (length + 1) * sizeof(WCHAR) ); if ( ! pstr ) { goto Failed; } wcscpy( pstr, pwsPassword ); pauth->Password = pstr; pauth->PasswordLength = length; // set to unicode pauth->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; DNSDBG( SECURITY, ( "Exit Dns_AllocateCredentialsW( %p )\n", pauth )); return pauth; Failed: // allocation failure // - cleanup what was allocated and get out Dns_FreeAuthIdentityCredentials( pauth ); return( NULL ); } // // DNS Credential utilities (unused) // DNS_STATUS Dns_ImpersonateUser( IN PDNS_CREDENTIALS pCreds ) /*++ Routine Description: Impersonate a user. Arguments: pCreds -- credentials of user to impersonate Return Value: ERROR_SUCCESS if successful Error code on failure. --*/ { DNS_STATUS status = NO_ERROR; HANDLE htoken; // // attempt logon // if ( ! LogonUserW( pCreds->pUserName, pCreds->pDomain, pCreds->pPassword, LOGON32_LOGON_SERVICE, LOGON32_PROVIDER_WINNT50, &htoken ) ) { status = GetLastError(); if ( status == NO_ERROR ) { status = ERROR_CANNOT_IMPERSONATE; DNS_ASSERT( FALSE ); } DNSDBG( SECURITY, ( "LogonUser() failed => %d\n" "\tuser = %S\n" "\tdomain = %S\n" "\tpassword = %S\n", status, pCreds->pUserName, pCreds->pDomain, pCreds->pPassword )); return status; } // // impersonate // if ( !ImpersonateLoggedOnUser( htoken ) ) { status = GetLastError(); if ( status == NO_ERROR ) { status = ERROR_CANNOT_IMPERSONATE; DNS_ASSERT( FALSE ); } DNSDBG( SECURITY, ( "ImpersonateLoggedOnUser() failed = %d\n", status )); } CloseHandle( htoken ); DNSDBG( SECURITY, ( "%s\n" "\tuser = %S\n" "\tdomain = %S\n" "\tpassword = %S\n", (status == NO_ERROR) ? "Successfully IMPERSONATING!" : "Failed IMPERSONATION!", pCreds->pUserName, pCreds->pDomain, pCreds->pPassword )); return status; } VOID Dns_FreeCredentials( IN PDNS_CREDENTIALS pCreds ) /*++ Routine Description: Free DNS credentials. Arguments: pCreds -- credentials to free Return Value: None --*/ { // // free subfields, then credentials // if ( !pCreds ) { return; } if ( pCreds->pUserName ) { FREE_HEAP( pCreds->pUserName ); } if ( pCreds->pDomain ) { FREE_HEAP( pCreds->pDomain ); } if ( pCreds->pPassword ) { FREE_HEAP( pCreds->pPassword ); } FREE_HEAP( pCreds ); } PDNS_CREDENTIALS Dns_CopyCredentials( IN PDNS_CREDENTIALS pCreds ) /*++ Routine Description: Create copy of DNS credentials. Arguments: pCreds -- credentials of user to copy Return Value: Ptr to allocated copy of credentials. --*/ { PDNS_CREDENTIALS pnewCreds = NULL; PWSTR pfield; // // allocate credentials // - copy of subfields // pnewCreds = (PDNS_CREDENTIALS) ALLOCATE_HEAP_ZERO( sizeof(*pnewCreds) ); if ( !pnewCreds ) { return( NULL ); } pfield = (PWSTR) Dns_CreateStringCopy_W( pCreds->pUserName ); if ( !pfield ) { goto Failed; } pnewCreds->pUserName = pfield; pfield = (PWSTR) Dns_CreateStringCopy_W( pCreds->pDomain ); if ( !pfield ) { goto Failed; } pnewCreds->pDomain = pfield; pfield = (PWSTR) Dns_CreateStringCopy_W( pCreds->pPassword ); if ( !pfield ) { goto Failed; } pnewCreds->pPassword = pfield; return( pnewCreds ); Failed: Dns_FreeCredentials( pnewCreds ); return( NULL ); } // // End secutil.c //