windows-nt/Source/XPSP1/NT/net/rras/routemon/user.c
2020-09-26 16:20:57 +08:00

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;
}