You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
407 lines
12 KiB
407 lines
12 KiB
/*---------------------------------------------------------------------------
|
|
File: ARUtil.cpp
|
|
|
|
Comments: Helper functions and command-line parsing for Account Replicator
|
|
|
|
(c) Copyright 1995-1998, Mission Critical Software, Inc., All Rights Reserved
|
|
Proprietary and confidential to Mission Critical Software, Inc.
|
|
|
|
REVISION LOG ENTRY
|
|
Revision By: Christy Boles
|
|
Revised on 6/23/98 4:26:54 PM
|
|
|
|
---------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#define INCL_NETUSER
|
|
#define INCL_NETGROUP
|
|
#define INCL_NETERRORS
|
|
#include <lm.h>
|
|
|
|
#include "Mcs.h"
|
|
#include "Common.hpp"
|
|
#include "TNode.hpp"
|
|
#include "UString.hpp"
|
|
|
|
#include "ErrDct.hpp"
|
|
|
|
//#import "\bin\McsDctWorkerObjects.tlb"
|
|
//#import "WorkObj.tlb" //#imported via ARUtil.hpp below
|
|
|
|
#include "UserCopy.hpp"
|
|
#include "ARUtil.hpp"
|
|
#include "PWGen.hpp"
|
|
#include "ResStr.h"
|
|
#include <TxtSid.h>
|
|
|
|
|
|
extern TErrorDct err;
|
|
bool bAllowReplicateOnSelf;
|
|
|
|
extern PSID srcSid; // SID of source domain
|
|
|
|
/***************************************************************************************************
|
|
CompVal: used as a compare function for TANode trees
|
|
|
|
It compares a UNICODE string, with the name field in the node
|
|
|
|
Return Values:
|
|
0 tn->acct_name == actname
|
|
1 tn->acct_name < actname
|
|
-1 tn->acct_name > actname
|
|
|
|
/***************************************************************************************************/
|
|
|
|
int
|
|
CompVal(
|
|
const TNode * tn, //in -tree node
|
|
const void * actname //in -name to look for
|
|
)
|
|
{
|
|
|
|
LPWSTR str1 = ((TANode *)tn)->GetName();
|
|
LPWSTR str2 = (LPWSTR) actname;
|
|
|
|
return UStrICmp(str1,str2);
|
|
}
|
|
/***************************************************************************************************/
|
|
/* CompNode: used as a compare function for TANode Trees
|
|
|
|
It compares the name fields of TANodes
|
|
|
|
Return Values:
|
|
0 t1->acct_name == t2->acct_name
|
|
1 t1->acct_name > t2->acct_name
|
|
-1 t1->acct_name < t2->acct_name
|
|
|
|
Error Handling:
|
|
if given bad inputs, CompN displays an error message and returns 0
|
|
/***************************************************************************************************/
|
|
|
|
int
|
|
CompNode(
|
|
const TNode * v1, //in -first node to compare
|
|
const TNode * v2 //in -second node to compare
|
|
)
|
|
{
|
|
|
|
TANode * t1 = (TANode *)v1;
|
|
TANode * t2 = (TANode *)v2;
|
|
|
|
return UStrICmp(t1->GetName(),t2->GetName());
|
|
}
|
|
|
|
|
|
int
|
|
CompareSid(
|
|
PSID const sid1, // in - first SID to compare
|
|
PSID const sid2 // in - second SID to compare
|
|
)
|
|
{
|
|
DWORD len1,
|
|
len2;
|
|
int retval = 0;
|
|
|
|
len1 = GetLengthSid(sid1);
|
|
len2 = GetLengthSid(sid2);
|
|
|
|
if ( len1 < len2 )
|
|
{
|
|
retval = -1;
|
|
}
|
|
if ( len1 > len2 )
|
|
{
|
|
retval = 1;
|
|
}
|
|
if ( len1 == len2 )
|
|
{
|
|
retval = memcmp(sid1,sid2,len1);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
int
|
|
CompSid(
|
|
const TNode * v1, // in -first node to compare
|
|
const TNode * v2 // in -second node to compare
|
|
)
|
|
{
|
|
TANode * t1 = (TANode *)v1;
|
|
TANode * t2 = (TANode *)v2;
|
|
|
|
return CompareSid(t1->GetSid(),t2->GetSid());
|
|
}
|
|
|
|
int
|
|
CompSidVal(
|
|
const TNode * tn, // in -node to compare
|
|
const void * pVal // in -value to compare
|
|
)
|
|
{
|
|
TANode * node = (TANode *)tn;
|
|
PSID pSid = (PSID)pVal;
|
|
|
|
return CompareSid(node->GetSid(),pSid);
|
|
}
|
|
|
|
|
|
BOOL // ret-TRUE if the password is successfully generated
|
|
PasswordGenerate(
|
|
Options const * options, // in -includes PW Generating options
|
|
WCHAR * password, // out -buffer for generated password
|
|
DWORD dwPWBufferLength, // in -DIM length of password buffer
|
|
BOOL isAdminAccount // in -Whether to use the Admin rules
|
|
)
|
|
{
|
|
DWORD rc = 0;
|
|
DWORD dwMinUC; // minimum upper case chars
|
|
DWORD dwMinLC; // minimum lower case chars
|
|
DWORD dwMinDigit; // minimum numeric digits
|
|
DWORD dwMinSpecial; // minimum special chars
|
|
DWORD dwMaxConsecutiveAlpha; // maximum consecutive alpha chars
|
|
DWORD dwMinLength; // minimum length
|
|
WCHAR eaPassword[PWLEN+1]; // EA generated password
|
|
DWORD dwEaBufferLength = DIM(eaPassword);// DIM length of newPassword
|
|
|
|
// default values, if not enforcing PW strength through EA or MS DLL
|
|
dwMinUC = 0;
|
|
dwMinLC = 0;
|
|
dwMinDigit = 1; // if no enforcement, require one digit (this is what the GUI does)
|
|
dwMinSpecial = 0;
|
|
dwMaxConsecutiveAlpha = 0;
|
|
dwMinLength = options->minPwdLength;
|
|
|
|
|
|
// Get password enforcement rules, if in effect
|
|
dwMinUC = options->policyInfo.minUpper;
|
|
dwMinLC = options->policyInfo.minLower;
|
|
dwMinDigit = options->policyInfo.minDigits;
|
|
dwMinSpecial = options->policyInfo.minSpecial;
|
|
dwMaxConsecutiveAlpha = options->policyInfo.maxConsecutiveAlpha;
|
|
|
|
rc = EaPasswordGenerate(dwMinUC,dwMinLC,dwMinDigit,dwMinSpecial,
|
|
dwMaxConsecutiveAlpha,dwMinLength,eaPassword,dwEaBufferLength);
|
|
|
|
if ( ! rc )
|
|
{
|
|
UStrCpy(password,eaPassword,dwPWBufferLength);
|
|
}
|
|
else
|
|
{
|
|
if ( dwPWBufferLength )
|
|
password[0] = 0;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
PSID
|
|
GetWellKnownSid(
|
|
DWORD wellKnownAccount, // in - constant defined in this file, representing well-known account
|
|
Options * opt, // in - migration options
|
|
BOOL bTarget // in - flag, whether to use source or target domain information
|
|
)
|
|
{
|
|
PSID pSid = NULL;
|
|
PUCHAR numsubs = NULL;
|
|
DWORD * rid = NULL;
|
|
BOOL error = FALSE;
|
|
DWORD rc;
|
|
DWORD wellKnownRid = wellKnownAccount;
|
|
BOOL bNeedToBuildDomainSid = FALSE;
|
|
|
|
|
|
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
|
|
SID_IDENTIFIER_AUTHORITY creatorIA = SECURITY_CREATOR_SID_AUTHORITY;
|
|
|
|
//
|
|
// Sid is the same regardless of machine, since the well-known
|
|
// BUILTIN domain is referenced.
|
|
//
|
|
switch ( wellKnownAccount )
|
|
{
|
|
case CREATOR_OWNER:
|
|
if( ! AllocateAndInitializeSid(
|
|
&creatorIA,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
SECURITY_CREATOR_OWNER_RID,
|
|
0, 0, 0, 0, 0, 0,
|
|
&pSid
|
|
))
|
|
{
|
|
err.SysMsgWrite(ErrE,GetLastError(),DCT_MSG_INITIALIZE_SID_FAILED_D,GetLastError());
|
|
}
|
|
break;
|
|
case ADMINISTRATORS:
|
|
if( ! AllocateAndInitializeSid(
|
|
&sia,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&pSid
|
|
))
|
|
{
|
|
err.SysMsgWrite(ErrE,GetLastError(),DCT_MSG_INITIALIZE_SID_FAILED_D,GetLastError());
|
|
}
|
|
break;
|
|
case ACCOUNT_OPERATORS:
|
|
if( ! AllocateAndInitializeSid(
|
|
&sia,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ACCOUNT_OPS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&pSid
|
|
))
|
|
{
|
|
err.SysMsgWrite(ErrE,GetLastError(),DCT_MSG_INITIALIZE_SID_FAILED_D,GetLastError());
|
|
}
|
|
break;
|
|
case BACKUP_OPERATORS:
|
|
if( ! AllocateAndInitializeSid(
|
|
&sia,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_BACKUP_OPS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&pSid
|
|
))
|
|
{
|
|
err.SysMsgWrite(ErrE,GetLastError(),DCT_MSG_INITIALIZE_SID_FAILED_D,GetLastError());
|
|
}
|
|
break;
|
|
case DOMAIN_ADMINS:
|
|
wellKnownRid = DOMAIN_GROUP_RID_ADMINS;
|
|
bNeedToBuildDomainSid = TRUE;
|
|
break;
|
|
case DOMAIN_USERS:
|
|
wellKnownRid = DOMAIN_GROUP_RID_USERS;
|
|
bNeedToBuildDomainSid = TRUE;
|
|
break;
|
|
case DOMAIN_CONTROLLERS:
|
|
wellKnownRid = DOMAIN_GROUP_RID_CONTROLLERS;
|
|
bNeedToBuildDomainSid = TRUE;
|
|
break;
|
|
case DOMAIN_COMPUTERS:
|
|
wellKnownRid = DOMAIN_GROUP_RID_COMPUTERS;
|
|
bNeedToBuildDomainSid = TRUE;
|
|
break;
|
|
default:
|
|
wellKnownRid = wellKnownAccount;
|
|
bNeedToBuildDomainSid = TRUE;
|
|
break;
|
|
}
|
|
|
|
if ( bNeedToBuildDomainSid )
|
|
{
|
|
// For the default case we can return a SID by using the wellKnownAccount parameter as a RID
|
|
// this one is based on the sid for the domain
|
|
// Get the domain SID
|
|
USER_MODALS_INFO_2 * uinf = NULL;
|
|
MCSASSERT(opt);
|
|
srcSid = bTarget ? opt->tgtSid : opt->srcSid;
|
|
if ( ! srcSid )
|
|
{
|
|
rc = NetUserModalsGet(bTarget ? opt->tgtComp :opt->srcComp,2,(LPBYTE*)&uinf);
|
|
if ( rc )
|
|
{
|
|
err.SysMsgWrite(ErrE,rc,DCT_MSG_NO_DOMAIN_SID_SD,bTarget ? opt->tgtDomain :opt->srcDomain,rc );
|
|
error = TRUE;
|
|
srcSid = NULL;
|
|
}
|
|
else
|
|
{
|
|
srcSid = uinf->usrmod2_domain_id;
|
|
// make a copy of the SID to keep in the Options structure for next time
|
|
PSID temp = LocalAlloc(LPTR,GetLengthSid(srcSid));
|
|
|
|
memcpy(temp,srcSid,GetLengthSid(srcSid));
|
|
|
|
if ( bTarget )
|
|
opt->tgtSid = temp;
|
|
else
|
|
opt->srcSid = temp;
|
|
NetApiBufferFree(uinf);
|
|
srcSid = temp;
|
|
}
|
|
}
|
|
if ( srcSid )
|
|
{
|
|
numsubs = GetSidSubAuthorityCount(srcSid);
|
|
if (! AllocateAndInitializeSid(
|
|
&sia,
|
|
(*numsubs)+1,
|
|
0,0,0,0,0,0,0,0,
|
|
&pSid) )
|
|
{
|
|
err.SysMsgWrite(ErrE,GetLastError(),DCT_MSG_INITIALIZE_SID_FAILED_D,GetLastError());
|
|
}
|
|
if ( ! CopySid(GetLengthSid(srcSid), pSid, srcSid) )
|
|
{
|
|
err.SysMsgWrite(ErrE,GetLastError(),DCT_MSG_COPY_SID_FAILED_D,GetLastError());
|
|
}
|
|
// reset number of subauthorities in pSid, since we just overwrote it with information from srcSid
|
|
numsubs = GetSidSubAuthorityCount(pSid);
|
|
(*numsubs)++;
|
|
rid = GetSidSubAuthority(pSid,(*numsubs)-1);
|
|
*rid = wellKnownRid;
|
|
|
|
}
|
|
}
|
|
if ( error )
|
|
{
|
|
LocalFree(pSid);
|
|
pSid = NULL;
|
|
}
|
|
return pSid;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// GenerateSidAsString Function
|
|
//
|
|
// Synopsis
|
|
// Generate a SID in string format from specifed domain and given RID.
|
|
//
|
|
// Arguments
|
|
// IN pOptions - account replicator options structure
|
|
// IN bTarget - specifies whether to use the target domain or source domain
|
|
// IN dwRid - specified RID
|
|
//
|
|
// Return
|
|
// The generated SID as a string if successfull or an empty string if not.
|
|
//---------------------------------------------------------------------------
|
|
|
|
_bstr_t __stdcall GenerateSidAsString(Options* pOptions, BOOL bTarget, DWORD dwRid)
|
|
{
|
|
_bstr_t strSid;
|
|
|
|
PSID pSid = GetWellKnownSid(dwRid, pOptions, bTarget);
|
|
|
|
if (pSid)
|
|
{
|
|
WCHAR szSid[LEN_Path];
|
|
DWORD cchSid = DIM(szSid);
|
|
|
|
if (GetTextualSid(pSid, szSid, &cchSid))
|
|
{
|
|
strSid = szSid;
|
|
}
|
|
|
|
FreeSid(pSid);
|
|
}
|
|
|
|
return strSid;
|
|
}
|