|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000
//
// File: parserutil.cpp
//
// Contents: Helpful functions for manipulating and validating
// generic command line arguments
//
// History: 07-Sep-2000 JeffJon Created
//
//
//--------------------------------------------------------------------------
#include "pch.h"
#include "iostream.h"
#include "cstrings.h"
#include "commonstrings.h"
//+--------------------------------------------------------------------------
//
// Function: GetPasswdStr
//
// Synopsis: Reads a password string from stdin without echoing the keystrokes
//
// Arguments: [buf - OUT] : buffer to put string in
// [buflen - IN] : size of the buffer
// [&len - OUT] : length of the string placed into the buffer
//
// Returns: DWORD : 0 or ERROR_INSUFFICIENT_BUFFER if user typed too much.
// Buffer contents are only valid on 0 return.
//
// History: 07-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
#define CR 0xD
#define BACKSPACE 0x8
DWORD GetPasswdStr(LPTSTR buf, DWORD buflen, PDWORD len) { TCHAR ch; TCHAR *bufPtr = buf; DWORD c; int err; DWORD mode;
buflen -= 1; /* make space for null terminator */ *len = 0; /* GP fault probe (a la API's) */ GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode); SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), (~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & mode);
while (TRUE) { //Security Review:Correct buffer len is passed.
err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &c, 0); if (!err || c != 1) ch = 0xffff;
if ((ch == CR) || (ch == 0xffff)) /* end of the line */ break;
if (ch == BACKSPACE) { /* back up one or two */ /*
* IF bufPtr == buf then the next two lines are * a no op. */ if (bufPtr != buf) { bufPtr--; (*len)--; } } else { *bufPtr = ch;
if (*len < buflen) bufPtr++ ; /* don't overflow buf */ (*len)++; /* always increment len */ } }
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode); *bufPtr = TEXT('\0'); /* null terminate the string */ putwchar(TEXT('\n'));
return ((*len <= buflen) ? 0 : ERROR_INSUFFICIENT_BUFFER); }
//+--------------------------------------------------------------------------
//
// Function: ValidatePassword
//
// Synopsis: Password validation function called by parser
//
// Arguments: [pArg - IN] : pointer argument structure which contains
// the value to be validated
//
// Returns: DWORD : ERROR_INVALID_PARAMETER if the argument record or
// the value it contains is not valid
// ERROR_NOT_ENOUGH_MEMORY
// ERROR_SUCCESS if everything succeeded and it is a
// valid password
// Otherwise it is an error condition returned from
// GetPasswdStr
//
// History: 07-Sep-2000 JeffJon Created
// 03-27-2002 hiteshr changed the function
// //NTRAID#NTBUG9-571544-2000/11/13-hiteshr
//---------------------------------------------------------------------------
DWORD ValidatePassword(PVOID pArg, UINT IdStr, UINT IdPromptConfirm) { PARG_RECORD pRec = (PARG_RECORD)pArg; if(!pRec || !pRec->strValue) { return ERROR_INVALID_PARAMETER; }
//Validate the length of password. Password length must be
//less than MAX_PASSWORD_LENGTH
size_t cchInputPassword = 0; HRESULT hr = StringCchLength(pRec->strValue, MAX_PASSWORD_LENGTH, &cchInputPassword);
if(FAILED(hr)) { DisplayErrorMessage(g_pszDSCommandName,NULL,E_INVALIDARG,IDS_ERROR_LONG_PASSWORD); return VLDFN_ERROR_NO_ERROR; } //If Password is *, store encrypted password
if(wcscmp(pRec->strValue, L"*") != 0 ) { DATA_BLOB EncryptedPasswordDataBlob; hr = EncryptPasswordString(pRec->strValue, &EncryptedPasswordDataBlob); //Clear the cleartext password
SecureZeroMemory(pRec->strValue,cchInputPassword*sizeof(WCHAR)); if(SUCCEEDED(hr)) { LocalFree(pRec->strValue); pRec->encryptedDataBlob = EncryptedPasswordDataBlob; return ERROR_SUCCESS; }
return hr; }
//User entered * in commandline. Prompt for password.
CComBSTR sbstrPrompt; if(sbstrPrompt.LoadString(::GetModuleHandle(NULL),IdStr)) { DisplayOutput(sbstrPrompt); } else DisplayOutput(L"Enter Password\n"); WCHAR buffer[MAX_PASSWORD_LENGTH]; DWORD len = 0; DWORD dwErr = GetPasswdStr(buffer,MAX_PASSWORD_LENGTH,&len); if(dwErr != ERROR_SUCCESS) return dwErr;
if(IdPromptConfirm) { if(sbstrPrompt.LoadString(::GetModuleHandle(NULL),IdPromptConfirm)) { DisplayOutput(sbstrPrompt); } else DisplayOutput(L"Confirm Password\n");
WCHAR buffer1[MAX_PASSWORD_LENGTH]; DWORD len1 = 0; dwErr = GetPasswdStr(buffer1,MAX_PASSWORD_LENGTH,&len1); if(dwErr != ERROR_SUCCESS) return dwErr;
//Security Review:This is fine.
if(wcscmp(buffer,buffer1) != 0) { SecureZeroMemory(buffer,sizeof(buffer)); SecureZeroMemory(buffer1,sizeof(buffer1)); CComBSTR sbstrError; sbstrError.LoadString(::GetModuleHandle(NULL),IDS_ERROR_PASSWORD_MISSMATCH);
DisplayErrorMessage(g_pszDSCommandName,NULL,S_OK,sbstrError); //Security Review:SecureZeroMemory buffer and buffer1 before returning
return VLDFN_ERROR_NO_ERROR; }
//Two passwords are same. Clear the buffer1
SecureZeroMemory(buffer1,sizeof(buffer1)); } //CryptProtectMemory strValue
DATA_BLOB EncryptedPasswordDataBlob; hr = EncryptPasswordString(buffer, &EncryptedPasswordDataBlob); //Clear the cleartext password in buffer
SecureZeroMemory(buffer,sizeof(buffer)); if(SUCCEEDED(hr)) { LocalFree(pRec->strValue); pRec->encryptedDataBlob = EncryptedPasswordDataBlob; return ERROR_SUCCESS; }
return hr; }
//+--------------------------------------------------------------------------
//
// Function: ValidateAdminPassword
//
// Synopsis: Password validation function called by parser for Admin
//
// Arguments: [pArg - IN] : pointer argument structure which contains
// the value to be validated
//
// Returns: DWORD : ERROR_INVALID_PARAMETER if the argument record or
// the value it contains is not valid
// ERROR_SUCCESS if everything succeeded and it is a
// valid password
//
// History: 07-Sep-2000 Hiteshr Created
//
//---------------------------------------------------------------------------
DWORD ValidateAdminPassword(PVOID pArg) { return ValidatePassword(pArg,IDS_ADMIN_PASSWORD_PROMPT,0); }
//+--------------------------------------------------------------------------
//
// Function: ValidateUserPassword
//
// Synopsis: Password validation function called by parser for Admin
//
// Arguments: [pArg - IN] : pointer argument structure which contains
// the value to be validated
//
// Returns: DWORD : Same as ValidatePassword
//
// History: 07-Sep-2000 Hiteshr Created
//
//---------------------------------------------------------------------------
DWORD ValidateUserPassword(PVOID pArg) { return ValidatePassword(pArg, IDS_USER_PASSWORD_PROMPT,IDS_USER_PASSWORD_CONFIRM); }
//+--------------------------------------------------------------------------
//
// Function: ValidateYesNo
//
// Synopsis: Password validation function called by parser for Admin
//
// Arguments: [pArg - IN] : pointer argument structure which contains
// the value to be validated
//
// Returns: DWORD : Same as ValidatePassword
//
// History: 07-Sep-2000 Hiteshr Created
//
//---------------------------------------------------------------------------
DWORD ValidateYesNo(PVOID pArg) { PARG_RECORD pRec = (PARG_RECORD)pArg; if(!pRec || !pRec->strValue) return ERROR_INVALID_PARAMETER;
CComBSTR sbstrInput;
sbstrInput = pRec->strValue; sbstrInput.ToLower(); if( sbstrInput == g_bstrYes ) { LocalFree(pRec->strValue); pRec->bValue = TRUE; } else if( sbstrInput == g_bstrNo ) { LocalFree(pRec->strValue); pRec->bValue = FALSE; } else return ERROR_INVALID_PARAMETER;
//
// Have to set this to bool or else
// FreeCmd will try to free the string
// which AVs when the bool is true
//
pRec->fType = ARG_TYPE_BOOL; return ERROR_SUCCESS; }
//+--------------------------------------------------------------------------
//
// Function: ValidateNever
//
// Synopsis: Password validation function called by parser for Admin
// Verifies the value contains digits or "NEVER"
//
// Arguments: [pArg - IN] : pointer argument structure which contains
// the value to be validated
//
// Returns: DWORD : Same as ValidatePassword
//
// History: 07-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
DWORD ValidateNever(PVOID pArg) { PARG_RECORD pRec = (PARG_RECORD)pArg; if(!pRec) return ERROR_INVALID_PARAMETER;
if (pRec->fType == ARG_TYPE_STR) { CComBSTR sbstrInput; sbstrInput = pRec->strValue; //Security Review:This is fine, though we don't need
//to copy it sbstrInput. A direct comparison should be
//good enough.
if( _wcsicmp(sbstrInput, g_bstrNever) ) { return ERROR_INVALID_PARAMETER; } } return ERROR_SUCCESS; }
//+--------------------------------------------------------------------------
//
// Function: ValidateGroupScope
//
// Synopsis: Makes sure that the value following the -scope switch is one
// of (l/g/u)
//
// Arguments: [pArg - IN] : pointer argument structure which contains
// the value to be validated
//
// Returns: DWORD : Same as ValidatePassword
//
// History: 18-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
DWORD ValidateGroupScope(PVOID pArg) { DWORD dwReturn = ERROR_SUCCESS; PARG_RECORD pRec = (PARG_RECORD)pArg; if(!pRec || !pRec->strValue) return ERROR_INVALID_PARAMETER;
CComBSTR sbstrInput; sbstrInput = pRec->strValue; sbstrInput.ToLower(); if(sbstrInput == _T("l") || sbstrInput == _T("g") || sbstrInput == _T("u")) { dwReturn = ERROR_SUCCESS; } else { dwReturn = ERROR_INVALID_PARAMETER; }
return dwReturn; }
//+--------------------------------------------------------------------------
//
// Function: MergeArgCommand
//
// Synopsis: Combines two ARG_RECORD arrays into a single
//
// Arguments: [pCommand1 - IN] : first ARG_RECORD array to merge
// [pCommand2 - IN] : second ARG_RECORD array to merge
// [ppOutCommand - OUT] : the array that results from the merge
//
// Returns: HRESULT : S_OK on success
// E_OUTOFMEMORY if failed to allocate memory for new array
//
// History: 08-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
HRESULT MergeArgCommand(PARG_RECORD pCommand1, PARG_RECORD pCommand2, PARG_RECORD *ppOutCommand) { HRESULT hr = S_OK;
//
// Verify parameters
//
if (!pCommand1 && !pCommand2) { return E_INVALIDARG; }
LONG nSize1 = 0; LONG nSize2 = 0;
UINT i = 0;
if (NULL != pCommand1) { for(i=0; pCommand1[i].fType != ARG_TYPE_LAST ;i++) { ++nSize1; } } if (NULL != pCommand2) { for(i=0; pCommand2[i].fType != ARG_TYPE_LAST ;i++) { ++nSize2; } }
*ppOutCommand = (PARG_RECORD)LocalAlloc(LPTR, sizeof(ARG_RECORD)*(nSize1+nSize2+1)); if(!*ppOutCommand) { return E_OUTOFMEMORY; }
if (NULL != pCommand1) { //Security Review:This is fine.
memcpy(*ppOutCommand,pCommand1,sizeof(ARG_RECORD)*(nSize1+1)); } if (NULL != pCommand2) { //Security Review:This is fine.
memcpy((*ppOutCommand+nSize1),pCommand2,sizeof(ARG_RECORD)*(nSize2+1)); }
return hr; }
//+--------------------------------------------------------------------------
//
// Function: ParseStringByChar
//
// Synopsis: Parses a string into elements separated by the given character
//
// Arguments: [psz - IN] : string to be parsed
// [tchar - IN] : character that is to be used as the separator
// [pszArr - OUT] : the array to receive the parsed strings
// [pnArrEntries - OUT] : the number of strings parsed from the list
//
// Returns:
//
// History: 18-Sep-2000 JeffJon Created
// 14-Apr-2001 JeffJon Modified to separate on a generic character
//
//---------------------------------------------------------------------------
void ParseStringByChar(PTSTR psz, TCHAR tchar, PTSTR** ppszArr, UINT* pnArrEntries) { //
// Verify parameters
//
if (!psz || !ppszArr || !pnArrEntries) { ASSERT(psz); ASSERT(ppszArr); ASSERT(pnArrEntries);
return; }
//
// Count the number of strings
//
UINT nCount = 0; PTSTR pszTemp = psz; while (true) { if (pszTemp[0] == tchar && pszTemp[1] == tchar) { nCount++; break; } else if (pszTemp[0] == tchar && pszTemp[1] != tchar) { nCount++; pszTemp++; } else { pszTemp++; } }
*pnArrEntries = nCount;
//
// Allocate the array
//
*ppszArr = (PTSTR*)LocalAlloc(LPTR, nCount * sizeof(PTSTR)); if (*ppszArr) { //
// Copy the string pointers into the array
//
UINT nIdx = 0; pszTemp = psz; (*ppszArr)[nIdx] = pszTemp; nIdx++;
while (true) { if (pszTemp[0] == tchar && pszTemp[1] == tchar) { break; } else if (pszTemp[0] == tchar && pszTemp[1] != tchar) { (*ppszArr)[nIdx] = &(pszTemp[1]); nIdx++; pszTemp++; } else { pszTemp++; } } } }
//+--------------------------------------------------------------------------
//
// Function: ParseNullSeparatedString
//
// Synopsis: Parses a '\0' separated list that ends in "\0\0" into a string
// array
//
// Arguments: [psz - IN] : '\0' separated string to be parsed
// [pszArr - OUT] : the array to receive the parsed strings
// [pnArrEntries - OUT] : the number of strings parsed from the list
//
// Returns:
//
// History: 14-Apr-2001 JeffJon Created
//
//---------------------------------------------------------------------------
void ParseNullSeparatedString(PTSTR psz, PTSTR** ppszArr, UINT* pnArrEntries) { ParseStringByChar(psz, L'\0', ppszArr, pnArrEntries); }
//+--------------------------------------------------------------------------
//
// Function: ParseSemicolonSeparatedString
//
// Synopsis: Parses a ';' separated list
//
// Arguments: [psz - IN] : ';' separated string to be parsed
// [pszArr - OUT] : the array to receive the parsed strings
// [pnArrEntries - OUT] : the number of strings parsed from the list
//
// Returns:
//
// History: 14-Apr-2001 JeffJon Created
//
//---------------------------------------------------------------------------
void ParseSemicolonSeparatedString(PTSTR psz, PTSTR** ppszArr, UINT* pnArrEntries) { ParseStringByChar(psz, L';', ppszArr, pnArrEntries); }
|