629 lines
17 KiB
C
629 lines
17 KiB
C
/*
|
|
File: user.c
|
|
|
|
Handles routemon options to get and set RAS user properties.
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#define NT40_BUILD_NUMBER 1381
|
|
const WCHAR pszBuildNumPath[] =
|
|
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
|
|
const WCHAR pszBuildVal[] = L"CurrentBuildNumber";
|
|
|
|
//
|
|
// Defines a macro to perform string copies to
|
|
// unicode strings regardless of the UNICODE setting.
|
|
//
|
|
#if defined( UNICODE ) || defined( _UNICODE )
|
|
#define UserStrcpy(dst, src) wcscpy((dst), (src));
|
|
#else
|
|
#define UserStrcpy(dst, src) mbstowcs((dst), (src), strlen((src)));
|
|
#endif
|
|
|
|
//
|
|
// Defines structure of parameters that can be sent to
|
|
// a User api's.
|
|
//
|
|
typedef struct _USER_PARAMS {
|
|
PWCHAR pszMachine; // Given machine
|
|
DWORD dwToken; // Token designating the desired command
|
|
WCHAR pszAccount[1024]; // The account in question
|
|
BOOL bPolicySpecified; // Whether policy given on cmd line
|
|
DWORD dwTokenPolicy; // Specifies the token for the callback policy
|
|
RAS_USER_0 UserInfo; // Buffer to hold user info
|
|
} USER_PARAMS, * PUSER_PARAMS;
|
|
|
|
//
|
|
// Determines the role of the given computer (NTW, NTS, NTS DC, etc.)
|
|
//
|
|
DWORD UserGetMachineRole(
|
|
IN PWCHAR pszMachine,
|
|
OUT DSROLE_MACHINE_ROLE * peRole)
|
|
{
|
|
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pGlobalDomainInfo = NULL;
|
|
DWORD dwErr;
|
|
|
|
if (!peRole)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
//
|
|
// Get the name of the domain this machine is a member of
|
|
//
|
|
__try {
|
|
dwErr = DsRoleGetPrimaryDomainInformation(
|
|
pszMachine,
|
|
DsRolePrimaryDomainInfoBasic,
|
|
(LPBYTE *)&pGlobalDomainInfo );
|
|
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
*peRole = pGlobalDomainInfo->MachineRole;
|
|
}
|
|
|
|
__finally {
|
|
if (pGlobalDomainInfo)
|
|
DsRoleFreeMemory (pGlobalDomainInfo);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Determines the build number of a given machine
|
|
//
|
|
DWORD UserGetNtosBuildNumber(
|
|
IN PWCHAR pszMachine,
|
|
OUT LPDWORD lpdwBuild)
|
|
{
|
|
WCHAR pszComputer[1024], pszBuf[64];
|
|
HKEY hkBuild = NULL, hkMachine = NULL;
|
|
DWORD dwErr, dwType = REG_SZ, dwSize = sizeof(pszBuf);
|
|
|
|
__try {
|
|
if (pszMachine) {
|
|
if (*pszMachine != L'\\')
|
|
wsprintfW(pszComputer, L"\\\\%s", pszMachine);
|
|
else
|
|
wcscpy(pszComputer, pszMachine);
|
|
dwErr = RegConnectRegistryW (pszComputer,
|
|
HKEY_LOCAL_MACHINE,
|
|
&hkMachine);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
return dwErr;
|
|
}
|
|
else
|
|
hkMachine = HKEY_LOCAL_MACHINE;
|
|
|
|
// Open the build number key
|
|
dwErr = RegOpenKeyExW ( hkMachine,
|
|
pszBuildNumPath,
|
|
0,
|
|
KEY_READ,
|
|
&hkBuild);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
return dwErr;
|
|
|
|
// Get the value
|
|
dwErr = RegQueryValueExW ( hkBuild,
|
|
pszBuildVal,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)pszBuf,
|
|
&dwSize);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
return dwErr;
|
|
|
|
*lpdwBuild = (DWORD) _wtoi(pszBuf);
|
|
}
|
|
__finally {
|
|
if (hkMachine && pszMachine)
|
|
RegCloseKey(hkMachine);
|
|
if (hkBuild)
|
|
RegCloseKey(hkBuild);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
//
|
|
// Returns a static error message
|
|
//
|
|
PWCHAR UserError (DWORD dwErr) {
|
|
static WCHAR pszRet[512];
|
|
|
|
ZeroMemory(pszRet, sizeof(pszRet));
|
|
|
|
FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
dwErr,
|
|
0,
|
|
pszRet,
|
|
sizeof(pszRet) / sizeof(WCHAR),
|
|
NULL);
|
|
|
|
return pszRet;
|
|
}
|
|
|
|
//
|
|
// Displays usage and returns a generic error.
|
|
//
|
|
DWORD UserUsage(
|
|
IN HINSTANCE hInst,
|
|
IN PROUTEMON_PARAMS pRmParams,
|
|
IN PROUTEMON_UTILS pUtils)
|
|
{
|
|
pUtils->put_msg (hInst,
|
|
MSG_USER_HELP,
|
|
pRmParams->pszProgramName);
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// Parses the register command line and fills
|
|
// the parameters accordingly.
|
|
//
|
|
DWORD UserParse (
|
|
IN int argc,
|
|
IN TCHAR *argv[],
|
|
IN PROUTEMON_PARAMS pRmParams,
|
|
IN PROUTEMON_UTILS pUtils,
|
|
IN BOOL bLoad,
|
|
OUT USER_PARAMS * pParams)
|
|
{
|
|
DWORD dwSize, dwErr;
|
|
BOOL bValidCmd = FALSE;
|
|
HINSTANCE hInst = GetModuleHandle(NULL);
|
|
TCHAR buf[MAX_TOKEN];
|
|
|
|
// Initialize the return val
|
|
ZeroMemory(pParams, sizeof(USER_PARAMS));
|
|
|
|
// Parse out the name of the computer
|
|
if (pRmParams->wszRouterName[0])
|
|
pParams->pszMachine = (PWCHAR)&(pRmParams->wszRouterName[0]);
|
|
|
|
// Make sure some command was issued
|
|
if (argc == 0)
|
|
return UserUsage(hInst, pRmParams, pUtils);
|
|
|
|
// Parse out the command
|
|
if (_tcsicmp(argv[0], GetString (hInst, TOKEN_ENABLE, buf))==0) {
|
|
pParams->dwToken = TOKEN_ENABLE;
|
|
if (argc == 1)
|
|
return UserUsage(hInst, pRmParams, pUtils);
|
|
UserStrcpy(pParams->pszAccount, argv[1]);
|
|
|
|
// Optional setting of callback policy and number
|
|
if (argc > 2) {
|
|
pParams->bPolicySpecified = TRUE;
|
|
if (_tcsicmp(argv[2], GetString (hInst, TOKEN_NONE, buf))==0)
|
|
pParams->dwTokenPolicy = TOKEN_NONE;
|
|
else if (_tcsicmp(argv[2], GetString (hInst, TOKEN_CALLER, buf))==0)
|
|
pParams->dwTokenPolicy = TOKEN_CALLER;
|
|
else if (_tcsicmp(argv[2], GetString (hInst, TOKEN_ADMIN, buf))==0)
|
|
pParams->dwTokenPolicy = TOKEN_ADMIN;
|
|
|
|
if ((pParams->dwTokenPolicy == TOKEN_ADMIN) &&
|
|
(argc < 3))
|
|
{
|
|
return UserUsage(hInst, pRmParams, pUtils);
|
|
}
|
|
else if (pParams->dwTokenPolicy == TOKEN_ADMIN) {
|
|
UserStrcpy(pParams->UserInfo.wszPhoneNumber, argv[3]);
|
|
}
|
|
}
|
|
}
|
|
else if (_tcsicmp(argv[0], GetString (hInst, TOKEN_DISABLE, buf))==0) {
|
|
pParams->dwToken = TOKEN_DISABLE;
|
|
if (argc == 1)
|
|
return UserUsage(hInst, pRmParams, pUtils);
|
|
UserStrcpy(pParams->pszAccount, argv[1]);
|
|
}
|
|
else if (_tcsicmp(argv[0], GetString (hInst, TOKEN_SHOW, buf))==0) {
|
|
pParams->dwToken = TOKEN_SHOW;
|
|
if (argc == 1)
|
|
return UserUsage(hInst, pRmParams, pUtils);
|
|
UserStrcpy(pParams->pszAccount, argv[1]);
|
|
}
|
|
else if (_tcsicmp(argv[0], GetString (hInst, TOKEN_UPGRADE, buf))==0) {
|
|
pParams->dwToken = TOKEN_UPGRADE;
|
|
}
|
|
else
|
|
return UserUsage(hInst, pRmParams, pUtils);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Cleans up any User parameters
|
|
//
|
|
DWORD UserCleanup (
|
|
IN PUSER_PARAMS pParams)
|
|
{
|
|
if (pParams->pszMachine)
|
|
free(pParams->pszMachine);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Gets user info
|
|
//
|
|
DWORD UserGetInfo (
|
|
IN PWCHAR lpszServer,
|
|
IN PWCHAR lpszUser,
|
|
IN DWORD dwLevel,
|
|
OUT LPBYTE lpbBuffer)
|
|
{
|
|
DWORD dwErr, dwBuild;
|
|
|
|
// Find out the OS of the given machine.
|
|
dwErr = UserGetNtosBuildNumber(
|
|
lpszServer,
|
|
&dwBuild);
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
// If the target machine is nt4, use nt4 userparms
|
|
if (dwBuild <= NT40_BUILD_NUMBER) {
|
|
return MprAdminUserGetInfo(
|
|
lpszServer,
|
|
lpszUser,
|
|
dwLevel,
|
|
lpbBuffer);
|
|
}
|
|
|
|
// Otherwise, use SDO's
|
|
else {
|
|
HANDLE hServer, hUser;
|
|
|
|
dwErr = MprAdminUserServerConnect(
|
|
lpszServer,
|
|
TRUE,
|
|
&hServer);
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
dwErr = MprAdminUserOpen(
|
|
hServer,
|
|
lpszUser,
|
|
&hUser);
|
|
if (dwErr != NO_ERROR) {
|
|
MprAdminUserServerDisconnect(hServer);
|
|
return dwErr;
|
|
}
|
|
|
|
dwErr = MprAdminUserRead(
|
|
hUser,
|
|
dwLevel,
|
|
lpbBuffer);
|
|
if (dwErr != NO_ERROR) {
|
|
MprAdminUserClose(hUser);
|
|
MprAdminUserServerDisconnect(hServer);
|
|
return dwErr;
|
|
}
|
|
|
|
MprAdminUserClose(hUser);
|
|
MprAdminUserServerDisconnect(hServer);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Sets user info
|
|
//
|
|
DWORD UserSetInfo (
|
|
IN PWCHAR lpszServer,
|
|
IN PWCHAR lpszUser,
|
|
IN DWORD dwLevel,
|
|
OUT LPBYTE lpbBuffer)
|
|
{
|
|
DWORD dwErr, dwBuild;
|
|
|
|
// Find out the OS of the given machine.
|
|
dwErr = UserGetNtosBuildNumber(
|
|
lpszServer,
|
|
&dwBuild);
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
// If the target machine is nt4, use nt4 userparms
|
|
if (dwBuild <= NT40_BUILD_NUMBER) {
|
|
return MprAdminUserSetInfo(
|
|
lpszServer,
|
|
lpszUser,
|
|
dwLevel,
|
|
lpbBuffer);
|
|
}
|
|
|
|
// Otherwise, use SDO's
|
|
else {
|
|
HANDLE hServer, hUser;
|
|
|
|
dwErr = MprAdminUserServerConnect(
|
|
lpszServer,
|
|
TRUE,
|
|
&hServer);
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
dwErr = MprAdminUserOpen(
|
|
hServer,
|
|
lpszUser,
|
|
&hUser);
|
|
if (dwErr != NO_ERROR) {
|
|
MprAdminUserServerDisconnect(hServer);
|
|
return dwErr;
|
|
}
|
|
|
|
dwErr = MprAdminUserWrite(
|
|
hUser,
|
|
dwLevel,
|
|
lpbBuffer);
|
|
if (dwErr != NO_ERROR) {
|
|
MprAdminUserClose(hUser);
|
|
MprAdminUserServerDisconnect(hServer);
|
|
return dwErr;
|
|
}
|
|
|
|
MprAdminUserClose(hUser);
|
|
MprAdminUserServerDisconnect(hServer);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Enables or disables a user
|
|
//
|
|
DWORD UserEnableDisable(
|
|
IN PROUTEMON_PARAMS pRmParams,
|
|
IN PROUTEMON_UTILS pUtils,
|
|
IN PUSER_PARAMS pParams)
|
|
{
|
|
DWORD dwErr;
|
|
|
|
// Read in the old user properties if all the options
|
|
// weren't specified on the command line.
|
|
if (pParams->dwTokenPolicy != TOKEN_ADMIN) {
|
|
dwErr = UserGetInfo(
|
|
pParams->pszMachine,
|
|
pParams->pszAccount,
|
|
0,
|
|
(LPBYTE)&(pParams->UserInfo));
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
}
|
|
|
|
// Set the dialin policy
|
|
if (pParams->dwToken == TOKEN_ENABLE)
|
|
pParams->UserInfo.bfPrivilege |= RASPRIV_DialinPrivilege;
|
|
else
|
|
pParams->UserInfo.bfPrivilege &= ~RASPRIV_DialinPrivilege;
|
|
|
|
// Set the callback policy. The callback number will already
|
|
// be set through the parsing.
|
|
if (pParams->bPolicySpecified) {
|
|
// Initialize
|
|
pParams->UserInfo.bfPrivilege &= ~RASPRIV_NoCallback;
|
|
pParams->UserInfo.bfPrivilege &= ~RASPRIV_CallerSetCallback;
|
|
pParams->UserInfo.bfPrivilege &= ~RASPRIV_AdminSetCallback;
|
|
|
|
// Set
|
|
if (pParams->dwTokenPolicy == TOKEN_NONE)
|
|
pParams->UserInfo.bfPrivilege |= RASPRIV_NoCallback;
|
|
else if (pParams->dwTokenPolicy == TOKEN_CALLER)
|
|
pParams->UserInfo.bfPrivilege |= RASPRIV_CallerSetCallback;
|
|
else
|
|
pParams->UserInfo.bfPrivilege |= RASPRIV_AdminSetCallback;
|
|
}
|
|
|
|
// Otherwise, initialize the display token
|
|
else {
|
|
if (pParams->UserInfo.bfPrivilege & RASPRIV_NoCallback)
|
|
pParams->dwTokenPolicy = TOKEN_NONE;
|
|
else if (pParams->UserInfo.bfPrivilege & RASPRIV_CallerSetCallback)
|
|
pParams->dwTokenPolicy = TOKEN_CALLER;
|
|
else
|
|
pParams->dwTokenPolicy = TOKEN_ADMIN;
|
|
}
|
|
|
|
// Commit the changes to the system
|
|
dwErr = UserSetInfo(
|
|
pParams->pszMachine,
|
|
pParams->pszAccount,
|
|
0,
|
|
(LPBYTE)&(pParams->UserInfo));
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
// Print out the results
|
|
{
|
|
HINSTANCE hInst = GetModuleHandle(NULL);
|
|
TCHAR buf1[MAX_TOKEN], buf2[MAX_TOKEN];
|
|
DWORD dwYesNo;
|
|
|
|
dwYesNo = (pParams->dwToken == TOKEN_ENABLE) ? VAL_YES : VAL_NO;
|
|
|
|
pUtils->put_msg(
|
|
hInst,
|
|
MSG_USER_ENABLEDISABLE_SUCCESS,
|
|
pParams->pszAccount,
|
|
GetString (hInst, dwYesNo, buf1),
|
|
GetString (hInst, pParams->dwTokenPolicy, buf2),
|
|
pParams->UserInfo.wszPhoneNumber
|
|
);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Shows a user
|
|
//
|
|
DWORD UserShow(
|
|
IN PROUTEMON_PARAMS pRmParams,
|
|
IN PROUTEMON_UTILS pUtils,
|
|
IN PUSER_PARAMS pParams)
|
|
{
|
|
DWORD dwErr;
|
|
|
|
dwErr = UserGetInfo(
|
|
pParams->pszMachine,
|
|
pParams->pszAccount,
|
|
0,
|
|
(LPBYTE)&(pParams->UserInfo));
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
// Print out the results
|
|
{
|
|
HINSTANCE hInst = GetModuleHandle(NULL);
|
|
TCHAR buf1[MAX_TOKEN], buf2[MAX_TOKEN];
|
|
DWORD dwTknEnable, dwTknPolicy;
|
|
|
|
dwTknEnable = (pParams->UserInfo.bfPrivilege & RASPRIV_DialinPrivilege) ?
|
|
VAL_YES :
|
|
VAL_NO;
|
|
|
|
if (pParams->UserInfo.bfPrivilege & RASPRIV_NoCallback)
|
|
dwTknPolicy = TOKEN_NONE;
|
|
else if (pParams->UserInfo.bfPrivilege & RASPRIV_CallerSetCallback)
|
|
dwTknPolicy = TOKEN_CALLER;
|
|
else
|
|
dwTknPolicy = TOKEN_ADMIN;
|
|
|
|
pUtils->put_msg(
|
|
hInst,
|
|
MSG_USER_SHOW_SUCCESS,
|
|
pParams->pszAccount,
|
|
GetString (hInst, dwTknEnable, buf1),
|
|
GetString (hInst, dwTknPolicy, buf2),
|
|
pParams->UserInfo.wszPhoneNumber
|
|
);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Upgrades a user
|
|
//
|
|
DWORD UserUpgrade(
|
|
IN PROUTEMON_PARAMS pRmParams,
|
|
IN PROUTEMON_UTILS pUtils,
|
|
IN PUSER_PARAMS pParams)
|
|
{
|
|
BOOL bLocal = FALSE;
|
|
DWORD dwErr, dwBuild;
|
|
DSROLE_MACHINE_ROLE eRole;
|
|
|
|
// Determine whether this should be local or
|
|
// domain upgrade.
|
|
dwErr = UserGetNtosBuildNumber(pParams->pszMachine, &dwBuild);
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
// You can upgrade nt4->nt4
|
|
if (dwBuild <= NT40_BUILD_NUMBER)
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
|
|
// Find out the role of the machine
|
|
dwErr = UserGetMachineRole(pParams->pszMachine, &eRole);
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
// Now we know whether we're local
|
|
bLocal = ((eRole != DsRole_RoleBackupDomainController) &&
|
|
(eRole != DsRole_RolePrimaryDomainController));
|
|
|
|
|
|
// Upgrade the users
|
|
dwErr = MprAdminUpgradeUsers(pParams->pszMachine, bLocal);
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
// Print out the results
|
|
{
|
|
HINSTANCE hInst = GetModuleHandle(NULL);
|
|
TCHAR buf[MAX_TOKEN];
|
|
DWORD dwToken;
|
|
|
|
dwToken = (bLocal) ? VAL_LOCAL : VAL_DOMAIN;
|
|
|
|
pUtils->put_msg(
|
|
hInst,
|
|
MSG_USER_UPGRADE_SUCCESS,
|
|
GetString(hInst, dwToken, buf)
|
|
);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// The User functionality engine
|
|
//
|
|
DWORD UserEngine (
|
|
IN PROUTEMON_PARAMS pRmParams,
|
|
IN PROUTEMON_UTILS pUtils,
|
|
IN PUSER_PARAMS pParams)
|
|
{
|
|
DWORD dwErr;
|
|
HINSTANCE hInst = GetModuleHandle(NULL);
|
|
|
|
switch (pParams->dwToken) {
|
|
case TOKEN_ENABLE:
|
|
case TOKEN_DISABLE:
|
|
return UserEnableDisable(pRmParams, pUtils, pParams);
|
|
case TOKEN_SHOW:
|
|
return UserShow(pRmParams, pUtils, pParams);
|
|
case TOKEN_UPGRADE:
|
|
return UserUpgrade(pRmParams, pUtils, pParams);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Handles requests register a ras server in a domain
|
|
// or to deregister a ras server in a domain or to query
|
|
// whether a given ras server is registered in a given domain.
|
|
//
|
|
DWORD APIENTRY
|
|
UserMonitor (
|
|
IN int argc,
|
|
IN TCHAR *argv[],
|
|
IN PROUTEMON_PARAMS params,
|
|
IN PROUTEMON_UTILS utils
|
|
)
|
|
{
|
|
DWORD dwErr;
|
|
USER_PARAMS UserParams;
|
|
|
|
dwErr = UserParse (
|
|
argc,
|
|
argv,
|
|
params,
|
|
utils,
|
|
TRUE,
|
|
&UserParams);
|
|
if (dwErr != NO_ERROR)
|
|
return NO_ERROR;
|
|
|
|
dwErr = UserEngine (params, utils, &UserParams);
|
|
|
|
UserCleanup(&UserParams);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
|