|
|
/*++
SECPRINC.C
Code for setting security principal data in the DS-- specifically, the UPN, SPN, and AltSecurityIdentity
Copyright (C) 1998 Microsoft Corporation, all rights reserved.
Created, Jun 18, 1998 by DavidCHR.
CONTENTS: SetStringProperty FindUser SetUserData
--*/
#include "master.h"
#include "keytab.h"
#include <winldap.h>
#include <malloc.h>
#include "secprinc.h"
#include "delegtools.h"
extern BOOL /* delegation.c */ LdapFindAttributeInMessageA( IN PLDAP pLdap, IN PLDAPMessage pMessage, IN LPSTR PropertyName, OUT OPTIONAL PULONG pcbData, OUT OPTIONAL PVOID *ppvData );
/*****************************************************************
NAME: ConnectToDsa
connects to the DSA, binds, and searches for the base DN. TAKES: nothing RETURNS: TRUE ( and a pLdap and wide-string baseDn ) on success FALSE and a stderr message on failure. CALLED BY: FREE WITH: BaseDN should be freed with free(), the ldap handle should be closed with ldap_unbind. *****************************************************************/
BOOL ConnectToDsa( OUT PLDAP *ppLdap, OUT LPSTR *BaseDN ) { // free with free()
PLDAP pLdap; BOOL ret = FALSE; ULONG lderr;
pLdap = ldap_open( NULL, LDAP_PORT ); if ( pLdap ) {
lderr = ldap_bind_s( pLdap, NULL, NULL, LDAP_AUTH_SSPI );
if ( lderr == LDAP_SUCCESS ) {
LPSTR Context = "defaultNamingContext"; LPSTR Attributes[] = { Context, NULL }; PLDAPMessage pMessage, pEntry; LPSTR *pValue;
// now, guess the DSA Base:
lderr = ldap_search_sA( pLdap, NULL, LDAP_SCOPE_BASE, "objectClass=*", Attributes, FALSE, // just return attributes
&pMessage );
if ( lderr == LDAP_SUCCESS ) {
pEntry = ldap_first_entry( pLdap, pMessage );
if ( pEntry ) { pValue = ldap_get_valuesA( pLdap, pEntry, Context );
if ( pValue ) {
ULONG size;
size = ldap_count_valuesA( pValue );
if ( 1 == size ) { LPSTR dn; size = ( lstrlenA( *pValue ) +1 /*null*/) * sizeof( WCHAR );
dn = (LPSTR) malloc( size ); if ( dn ) {
memcpy( dn, *pValue, size ); *BaseDN = dn; *ppLdap = pLdap; ret = TRUE;
} else fprintf( stderr, "failed to malloc to duplicate \"%s\".\n", *pValue );
} else fprintf( stderr, "too many values (expected one, got %ld) for" " %s.\n", size, Context );
ldap_value_freeA( pValue );
} else fprintf( stderr, "ldap_get_values failed: 0x%x.\n", GetLastError() );
} else fprintf( stderr, "ldap_first_entry failed: 0x%x.\n", GetLastError() );
ldap_msgfree( pMessage );
} else fprintf( stderr, "ldap_search failed (0x%x). " "Couldn't search for base DN.\n", lderr );
if ( !ret ) ldap_unbind_s( pLdap );
} else fprintf( stderr, "Failed to bind to DSA: 0x%x.\n", lderr );
// there is no ldap_disconnect.
} else fprintf( stderr, "Failed to contact DSA: 0x%x.\n", GetLastError() );
return ret;
} /*++**************************************************************
NAME: SetStringProperty
sets the given property of the given object to the given string
MODIFIES: object's property value
TAKES: pLdap -- ldap connection handle Dn -- FQDN of the object whose property is munged PropertyName -- property to modify Property -- value to put in the property Operation -- set / add / delete, etc.
RETURNS: TRUE when the function succeeds. FALSE otherwise. LASTERROR: set
LOGGING: on failure CREATED: Jan 22, 1999 LOCKING: none CALLED BY: anyone FREE WITH: n/a -- no resources are returned **************************************************************--*/
BOOL SetStringProperty( IN PLDAP pLdap, IN LPSTR Dn, IN LPSTR PropertyName, IN LPSTR Property, IN ULONG Operation ) {
LPSTR Vals[] = { Property, NULL }; LDAPModA Mod = { Operation, PropertyName, Vals }; PLDAPModA Mods[] = { &Mod, NULL }; ULONG lderr;
lderr = ldap_modify_sA( pLdap, Dn, Mods );
if ( lderr == LDAP_SUCCESS ) {
return TRUE;
} else { fprintf( stderr, "Failed to set property \"%hs\" to \"%hs\" on Dn \"%hs\": " "0x%x.\n",
PropertyName, Property, Dn, lderr );
SetLastError( lderr );
} return FALSE; }
/*++**************************************************************
NAME: FindUser
searches the DS for the given user.
MODIFIES: pDn -- returned DN for that user. puacflags -- receives the user's AccountControl flags
TAKES: pLdap -- LDAP handle UserName -- user samaccountname for which to search
RETURNS: TRUE when the function succeeds. FALSE otherwise. LASTERROR: not explicitly set LOGGING: on failure CREATED: Jan 22, 1999 LOCKING: none CALLED BY: anyone FREE WITH: free the dn with ldap_memfree **************************************************************--*/
BOOL FindUser( IN PLDAP pLdap, IN LPSTR UserName, OUT PULONG puacFlags, OUT LPSTR *pDn ) {
LPSTR Query; BOOL ret = FALSE; LPSTR Attributes[] = { "userAccountControl", NULL }; // what attributes to fetch; none
PLDAPMessage pMessage = NULL; LPSTR StringUac;
Query = (LPSTR) malloc( lstrlenA( UserName ) + 100 ); // arbitrary
if ( Query ) {
wsprintfA( Query, "(& (objectClass=person) (samaccountname=%hs))", UserName );
if( LdapSearchForUniqueDnA( pLdap, Query, Attributes, pDn, &pMessage ) ) {
if ( LdapFindAttributeInMessageA( pLdap, pMessage, Attributes[ 0 ], NULL, // length doesn't matter
&StringUac ) ) {
*puacFlags = strtoul( StringUac, NULL, 0 );
} else {
/* Signal the caller that we don't know the uacflags. */ *puacFlags = 0;
}
ret = TRUE;
} else {
fprintf( stderr, "Failed to locate user \"%hs\".\n", Query );
}
if ( pMessage ) ldap_msgfree( pMessage ); free( Query );
} else {
fprintf( stderr, "allocation failed building query for LDAP search.\n" );
}
return ret; }
|