1

我正在编写一个工具,可用于管理 Ubuntu 上的虚拟主机和 Web 服务器。至于我需要特权的许多功能,我正在寻找实现这一点的方法。

目前我通过“gksu”或“gksudo”意识到这一点。这也有效。问题是提示用户进行任何需要特权才能输入密码的活动。 是否可以仅检索一次此密码并在程序的剩余时间内记住?还有其他方法可以实现吗?

    public void OnToogledVirtualHost(object o, ToggledArgs args)
    {
        VirtualHost host = (VirtualHost)store.GetNode(new TreePath(args.Path));
        host.Enabled = !host.Enabled;
        Process process = new Process();
        process.StartInfo.UseShellExecute = false;

        if (host.Enabled)
        {
            process.StartInfo.FileName = "gksu";
            process.StartInfo.Arguments = "a2ensite " + System.IO.Path.GetFileName(host.FilePath);
        }
        else
        {
            process.StartInfo.FileName = "gksu";
            process.StartInfo.Arguments = "a2dissite " + System.IO.Path.GetFileName(host.FilePath);
        }
        process.Start();
    }
4

4 回答 4

1

AFAIK,“su”的一项安全功能是不缓存密码(更准确地说是身份验证票)超过几秒钟,因此设计为不被绕过。

您始终可以使用中间进程并尝试使子进程继承其授权,但您需要保护 IPC(工具前端和中间进程之间的通信通道)。

所以我的建议是不要试图降低整体解决方案的安全性,所以让用户根据需要被询问多次......

于 2013-03-27T11:56:57.580 回答
1

这个问题有几个(至少 3 个)“安全”解决方案:

  1. 使用“sudo”,允许密码缓存。如果我可以在机器上安装和配置 sudo,这是我的首选解决方案。优点:sudo 将缓存密码。缺点:它取决于正确配置外部依赖项(sudo)。
  2. 编写不同的辅助可执行文件(例如“修改配置并重新启动 apache”程序),并在需要时要求用户使用 gksu 进行身份验证,然后启动它们。优点:每组操作只要求用户输入一次密码。缺点:用户仍然会多次被要求输入密码,并且您必须将程序分成多个部分。
  3. 编写一个以 root 权限运行的单独服务,并使用 polkit/DBUS 对用户进行身份验证并连接到它以要求服务(例如,“请重新启动 apache”)。优点:凭据缓存和身份验证对话框由 dekstop/polkit 管理。缺点:要编写更多代码,并且您需要运行 DBUS 服务。

引用“安全”是因为以 root 身份运行代码(尤其是依赖于诸如 Mono 等大型应用程序的托管代码)总是具有安全隐患。

于 2013-04-08T12:31:11.597 回答
0

你知道,我不会使用 gksu 或 sudo 来做这些,听起来你想看看userv

您基本上可以允许不同的用户运行不同的程序,

于 2013-05-01T14:00:57.560 回答
0

感谢您提供有用的方法。昨天我找到了一个解决问题的方法,我把它包含在一个静态类中。首先,区分正常流程和特权流程。

每当需要以提升的权限运行进程时,我都会检查我是否已经知道用户的密码。如果没有,我会得到它(gksudo -p)并将其存储在内存中。现在我可以执行具有 privilligierten 权限的命令。然后通过标准输入 (sudo -S) 传输存储的密码。

你怎么看?您有任何安全问题吗?

public static class SystemProcess
{
    private static string output;
    private static string error;
    private static string password;

    public static void Start (string filename, string arguments)
    {
        ProcessStartInfo startInfo = SystemProcess.Prepare(filename, arguments);

        using (Process process = Process.Start(startInfo)) {
            SystemProcess.output = process.StandardOutput.ReadToEnd();
            SystemProcess.error = process.StandardError.ReadToEnd();

            process.WaitForExit();
        }
    }

    public static void StartPrivileged (string filename, string arguments)
    {
        ProcessStartInfo startInfo;

        if (SystemProcess.password == default(string))
        {
            startInfo = SystemProcess.Prepare("gksudo", "-p true -D 'MyApplication'");

            using (Process process = Process.Start(startInfo)) {
                SystemProcess.password = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
            }
        }

        startInfo = SystemProcess.Prepare("sudo", "-S " + filename + " " + arguments);

        using (Process process = Process.Start(startInfo)) {
            process.StandardInput.WriteLine(SystemProcess.password);
            SystemProcess.output = process.StandardOutput.ReadToEnd();
            SystemProcess.error = process.StandardError.ReadToEnd();

            process.WaitForExit();
        }
    }

    private static ProcessStartInfo Prepare (string filename, string arguments)
    {
        ProcessStartInfo startInfo = new ProcessStartInfo (filename, arguments);

        startInfo.RedirectStandardError = true;
        startInfo.RedirectStandardOutput = true;
        startInfo.RedirectStandardInput = true;
        startInfo.UseShellExecute = false;

        return startInfo;
    }

    public static string Output {
        get {
            return SystemProcess.output;
        }
    }

    public static string Error {
        get {
            return SystemProcess.error;
        }
    }
}
于 2013-04-10T07:26:28.053 回答