1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using System.Diagnostics; 10 11 namespace Antmicro.Renode.Utilities 12 { 13 /// <summary> 14 /// Sudo tools. Set of methods related to the process elevation. 15 /// </summary> 16 public static class SudoTools 17 { 18 /// <summary> 19 /// Wraps the command into a sudo-tool call if necessary, creates a new Process object and exectues it. 20 /// </summary> 21 /// <description> 22 /// Checks whether user is root. If it is exectues command, id not tries to elevate priviledged and run the command. 23 /// </description> 24 /// <returns>The sudo execute.</returns> 25 /// <param name="command">Command.</param> 26 /// <param name = "arguments">Command's arguments.</param> 27 /// <param name="description">Optional description.</param> EnsureSudoExecute(string command, string arguments = R, string description = R)28 public static Process EnsureSudoExecute(string command, string arguments = "", string description = "") 29 { 30 Process process; 31 process = Misc.IsRoot ? Process.Start(command, arguments) : SudoExecute(command + " " + arguments, description); 32 return process; 33 } 34 35 /// <summary> 36 /// Tries to wrap existing Process, with supported sudo tool. It switched the command's filename and arguments, and wraps them 37 /// into a call to the supported sudo tool, if it's found. 38 /// </summary> 39 /// <param name="process">Process to be elevated.</param> 40 /// <param name="description">Process description.</param> EnsureSudoProcess(Process process, string description = R)41 public static void EnsureSudoProcess(Process process, string description = "") 42 { 43 if(Misc.IsRoot) 44 { 45 return; 46 } 47 Process sudoProcess = process; 48 string sudoName = FindSudoToolName(); 49 if(string.IsNullOrWhiteSpace(sudoProcess.StartInfo.FileName)) 50 { 51 throw new ArgumentException("EnsureSudoProcess needs to work on a process with initliazed StartInfo.FileName."); 52 } 53 var command = sudoProcess.StartInfo.FileName + " " + sudoProcess.StartInfo.Arguments; 54 sudoProcess.StartInfo.Arguments = SudoDecorateCommand(sudoName, command, description); 55 sudoProcess.StartInfo.FileName = sudoName; 56 } 57 58 /// <summary> 59 /// Finds the name of the sudo tool. 60 /// </summary> 61 /// <returns><c>true</c>, if sudo tool name was found, <c>false</c> otherwise.</returns> 62 /// <param name="name">Sudo tool name, if found.</param> TryFindSudoToolName(out string name)63 private static bool TryFindSudoToolName(out string name) 64 { 65 name = default(string); 66 foreach(var nameToCheck in knownToolNames) 67 { 68 if(Misc.IsCommandAvaialble(nameToCheck)) 69 { 70 name = nameToCheck; 71 return true; 72 } 73 } 74 return false; 75 } 76 77 /// <summary> 78 /// Finds the name of the sudo tool. Throwing version of <see cref="TryFindSudoToolName"/>. 79 /// </summary> 80 /// <returns>The sudo tool name.</returns> FindSudoToolName()81 private static string FindSudoToolName() 82 { 83 string name; 84 if(!TryFindSudoToolName(out name)) 85 { 86 throw new PlatformNotSupportedException( 87 String.Format("Error: No supported sudo tool found. Supported tools are {0}.", string.Join(", ", knownToolNames)) 88 ); 89 } 90 return name; 91 } 92 93 /// <summary> 94 /// Tries to find sudo tool, and execute the command with elevated rigths. 95 /// </summary> 96 /// <returns>The Process object, after the execution.</returns> 97 /// <param name="command">Command.</param> 98 /// <param name="description">Description.</param> SudoExecute(string command, string description = R)99 private static Process SudoExecute(string command, string description = "") 100 { 101 string sudoName = FindSudoToolName(); 102 Process process; 103 command = SudoDecorateCommand(sudoName, command, description); 104 process = Process.Start(sudoName, command); 105 return process; 106 } 107 108 /// <summary> 109 /// Decorates the command for a specific sudo tool. 110 /// </summary> 111 /// <returns>The decorated command.</returns> 112 /// <param name="sudoName">Sudo tool name.</param> 113 /// <param name="command">Command to be decorated.</param> 114 /// <param name="description">Description.</param> SudoDecorateCommand(string sudoName, string command, string description = R)115 private static string SudoDecorateCommand(string sudoName, string command, string description = "") 116 { 117 string result; 118 119 switch(sudoName) 120 { 121 // Tool specific adjustments. 122 case "gksudo": 123 result = string.Format(@"-D ""{0}"" ""{1}""", description, command); 124 break; 125 case "kdesudo": 126 result = string.Format(@"-c ""{0}"" --comment ""{1}""", command, description); 127 break; 128 case "pkexec": 129 // We do nothing, because 'pkexec' (version 0.105) doesn't accept description as a parameter. 130 default: 131 result = command; 132 break; 133 } 134 135 return result; 136 } 137 138 /// <summary> 139 /// List of supported tool names. 140 /// </summary> 141 private static string[] knownToolNames = { "gksudo", "kdesudo", "pkexec" }; 142 } 143 } 144 145