/// <summary> /// Prompt. /// </summary> public override Dictionary <string, PSObject> Prompt(string caption, string message, Collection <FieldDescription> descriptions) { // forward the call to the client host Dictionary <string, PSObject> results = _serverMethodExecutor.ExecuteMethod <Dictionary <string, PSObject> >( RemoteHostMethodId.Prompt, new object[] { caption, message, descriptions }); // attempt to do the requested type casts on the server (it is okay to fail the cast and return the original object) foreach (FieldDescription description in descriptions) { Type requestedType = InternalHostUserInterface.GetFieldType(description); if (requestedType != null) { PSObject valueFromClient; if (results.TryGetValue(description.Name, out valueFromClient)) { object conversionResult; if (LanguagePrimitives.TryConvertTo(valueFromClient, requestedType, CultureInfo.InvariantCulture, out conversionResult)) { if (conversionResult != null) { results[description.Name] = PSObject.AsPSObject(conversionResult); } else { results[description.Name] = null; } } } } } return(results); }
/// <summary> /// This message performs various security checks on the /// remote host call message. If there is a need to modify /// the message or discard it for security reasons then /// such modifications will be made here /// </summary> /// <param name="computerName">computer name to use in /// warning messages</param> /// <returns>A collection of remote host calls which will /// have to be executed before this host call can be /// executed.</returns> internal Collection <RemoteHostCall> PerformSecurityChecksOnHostMessage(string computerName) { Dbg.Assert(!String.IsNullOrEmpty(computerName), "Computer Name must be passed for use in warning messages"); _computerName = computerName; Collection <RemoteHostCall> prerequisiteCalls = new Collection <RemoteHostCall>(); // check if the incoming message is a PromptForCredential message // if so, do the following: // (a) prepend "Windows PowerShell Credential Request" in the title // (b) prepend "Message from Server XXXXX" to the text message if (MethodId == RemoteHostMethodId.PromptForCredential1 || MethodId == RemoteHostMethodId.PromptForCredential2) { // modify the caption which is _parameters[0] string modifiedCaption = ModifyCaption((string)Parameters[0]); // modify the message which is _parameters[1] string modifiedMessage = ModifyMessage((string)Parameters[1], computerName); Parameters[0] = modifiedCaption; Parameters[1] = modifiedMessage; } // Check if the incoming message is a Prompt message // if so, then do the following: // (a) check if any of the field descriptions // correspond to PSCredential // (b) if field descriptions correspond to // PSCredential modify the caption and // message as in the previous case above else if (MethodId == RemoteHostMethodId.Prompt) { // check if any of the field descriptions is for type // PSCredential if (Parameters.Length == 3) { Collection <FieldDescription> fieldDescs = (Collection <FieldDescription>)Parameters[2]; bool havePSCredential = false; foreach (FieldDescription fieldDesc in fieldDescs) { fieldDesc.IsFromRemoteHost = true; Type fieldType = InternalHostUserInterface.GetFieldType(fieldDesc); if (fieldType != null) { if (fieldType == typeof(PSCredential)) { havePSCredential = true; fieldDesc.ModifiedByRemotingProtocol = true; } else if (fieldType == typeof(System.Security.SecureString)) { prerequisiteCalls.Add(ConstructWarningMessageForSecureString( computerName, RemotingErrorIdStrings.RemoteHostPromptSecureStringPrompt)); } } } if (havePSCredential) { // modify the caption which is parameter[0] string modifiedCaption = ModifyCaption((string)Parameters[0]); // modify the message which is parameter[1] string modifiedMessage = ModifyMessage((string)Parameters[1], computerName); Parameters[0] = modifiedCaption; Parameters[1] = modifiedMessage; } } } // Check if the incoming message is a readline as secure string // if so do the following: // (a) Specify a warning message that the server is // attempting to read something securely on the client else if (MethodId == RemoteHostMethodId.ReadLineAsSecureString) { prerequisiteCalls.Add(ConstructWarningMessageForSecureString( computerName, RemotingErrorIdStrings.RemoteHostReadLineAsSecureStringPrompt)); } // check if the incoming call is GetBufferContents // if so do the following: // (a) Specify a warning message that the server is // attempting to read the screen buffer contents // on screen and it has been blocked // (b) Modify the message so that call is not executed else if (MethodId == RemoteHostMethodId.GetBufferContents) { prerequisiteCalls.Add(ConstructWarningMessageForGetBufferContents(computerName)); } return(prerequisiteCalls); }
Prompt(string caption, string message, Collection <FieldDescription> descriptions) { // Need to implement EchoOnPrompt HandleThrowOnReadAndPrompt(); if (descriptions == null) { throw PSTraceSource.NewArgumentNullException("descriptions"); } if (descriptions.Count < 1) { throw PSTraceSource.NewArgumentException("descriptions", ConsoleHostUserInterfaceStrings.PromptEmptyDescriptionsErrorTemplate, "descriptions"); } // we lock here so that multiple threads won't interleave the various reads and writes here. lock (_instanceLock) { Dictionary <string, PSObject> results = new Dictionary <string, PSObject>(); bool cancelInput = false; if (!string.IsNullOrEmpty(caption)) { // Should be a skin lookup WriteLineToConsole(); WriteLineToConsole(PromptColor, RawUI.BackgroundColor, WrapToCurrentWindowWidth(caption)); } if (!string.IsNullOrEmpty(message)) { WriteLineToConsole(WrapToCurrentWindowWidth(message)); } if (AtLeastOneHelpMessageIsPresent(descriptions)) { WriteLineToConsole(WrapToCurrentWindowWidth(ConsoleHostUserInterfaceStrings.PromptHelp)); } int descIndex = -1; foreach (FieldDescription desc in descriptions) { descIndex++; if (desc == null) { throw PSTraceSource.NewArgumentException("descriptions", ConsoleHostUserInterfaceStrings.NullErrorTemplate, string.Format(CultureInfo.InvariantCulture, "descriptions[{0}]", descIndex)); } PSObject inputPSObject = null; string fieldPrompt = null; fieldPrompt = desc.Name; bool fieldEchoOnPrompt = true; // FieldDescription.ParameterAssemblyFullName never returns null. But this is // defense in depth. if (string.IsNullOrEmpty(desc.ParameterAssemblyFullName)) { string paramName = string.Format(CultureInfo.InvariantCulture, "descriptions[{0}].AssemblyFullName", descIndex); throw PSTraceSource.NewArgumentException(paramName, ConsoleHostUserInterfaceStrings.NullOrEmptyErrorTemplate, paramName); } Type fieldType = InternalHostUserInterface.GetFieldType(desc); if (fieldType == null) { if (InternalHostUserInterface.IsSecuritySensitiveType(desc.ParameterTypeName)) { string errMsg = StringUtil.Format(ConsoleHostUserInterfaceStrings.PromptTypeLoadErrorTemplate, desc.Name, desc.ParameterTypeFullName); PromptingException e = new PromptingException(errMsg, null, "BadTypeName", ErrorCategory.InvalidType); throw e; } fieldType = typeof(string); } if (fieldType.GetInterface(typeof(IList).FullName) != null) { // field is a type implementing IList ArrayList inputList = new ArrayList(); // stores all converted user input before // assigned to an array // if the field is an array, the element type can be found; else, use Object Type elementType = typeof(object); if (fieldType.IsArray) { elementType = fieldType.GetElementType(); int rank = fieldType.GetArrayRank(); // This check may be redundant because it doesn't seem possible to create // an array of zero dimension. if (rank <= 0) { string msg = StringUtil.Format(ConsoleHostUserInterfaceStrings.RankZeroArrayErrorTemplate, desc.Name); ArgumentException innerException = PSTraceSource.NewArgumentException( string.Format(CultureInfo.InvariantCulture, "descriptions[{0}].AssemblyFullName", descIndex)); PromptingException e = new PromptingException(msg, innerException, "ZeroRankArray", ErrorCategory.InvalidOperation); throw e; } } StringBuilder fieldPromptList = new StringBuilder(fieldPrompt); // fieldPromptList = fieldPrompt + "[i] :" fieldPromptList.Append("["); while (true) { fieldPromptList.Append( string.Format(CultureInfo.InvariantCulture, "{0}]: ", inputList.Count)); bool inputListEnd = false; object convertedObj = null; string inputString = PromptForSingleItem(elementType, fieldPromptList.ToString(), fieldPrompt, caption, message, desc, fieldEchoOnPrompt, true, out inputListEnd, out cancelInput, out convertedObj); if (cancelInput || inputListEnd) { break; } else if (!cancelInput) { inputList.Add(convertedObj); // Remove the indices from the prompt fieldPromptList.Length = fieldPrompt.Length + 1; } } // if cancelInput, should throw OperationCancelException? if (!cancelInput) { object tryConvertResult = null; if (LanguagePrimitives.TryConvertTo(inputList, fieldType, out tryConvertResult)) { inputPSObject = PSObject.AsPSObject(tryConvertResult); } else { inputPSObject = PSObject.AsPSObject(inputList); } } } else { string printFieldPrompt = StringUtil.Format(ConsoleHostUserInterfaceStrings.PromptFieldPromptInputSeparatorTemplate, fieldPrompt); // field is not a list object convertedObj = null; bool dummy = false; PromptForSingleItem(fieldType, printFieldPrompt, fieldPrompt, caption, message, desc, fieldEchoOnPrompt, false, out dummy, out cancelInput, out convertedObj); if (!cancelInput) { inputPSObject = PSObject.AsPSObject(convertedObj); } } if (cancelInput) { s_tracer.WriteLine("Prompt canceled"); WriteLineToConsole(); results.Clear(); break; } results.Add(desc.Name, PSObject.AsPSObject(inputPSObject)); } return(results); } }