]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/gnome-ask-password-agent.vala
Revert "update TODO"
[thirdparty/systemd.git] / src / gnome-ask-password-agent.vala
CommitLineData
490aed58
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
20using Gtk;
21using GLib;
22using DBus;
23using Linux;
24using Posix;
efb3237e 25using Notify;
490aed58
LP
26
27[CCode (cheader_filename = "time.h")]
28extern int clock_gettime(int id, out timespec ts);
29
30public class PasswordDialog : Dialog {
31
32 public Entry entry;
33
34 public PasswordDialog(string message, string icon) {
35 set_title("System Password");
36 set_has_separator(false);
37 set_border_width(8);
38 set_default_response(ResponseType.OK);
39 set_icon_name(icon);
40
230e5a3f
KS
41 add_button(Stock.CANCEL, ResponseType.CANCEL);
42 add_button(Stock.OK, ResponseType.OK);
490aed58
LP
43
44 Container content = (Container) get_content_area();
45
46 Box hbox = new HBox(false, 16);
47 hbox.set_border_width(8);
48 content.add(hbox);
49
50 Image image = new Image.from_icon_name(icon, IconSize.DIALOG);
51 hbox.pack_start(image, false, false);
52
53 Box vbox = new VBox(false, 8);
54 hbox.pack_start(vbox, true, true);
55
56 Label label = new Label(message);
57 vbox.pack_start(label, false, false);
58
59 entry = new Entry();
60 entry.set_visibility(false);
61 entry.set_activates_default(true);
62 vbox.pack_start(entry, false, false);
63
64 entry.activate.connect(on_entry_activated);
65
66 show_all();
67 }
68
69 public void on_entry_activated() {
70 response(ResponseType.OK);
71 }
72}
73
74public class MyStatusIcon : StatusIcon {
75
76 File directory;
77 File current;
78 FileMonitor file_monitor;
79
80 string message;
81 string icon;
82 string socket;
83
84 PasswordDialog password_dialog;
85
86 public MyStatusIcon() throws GLib.Error {
87 GLib.Object(icon_name : "dialog-password");
efb3237e 88 set_title("System Password");
490aed58
LP
89
90 directory = File.new_for_path("/dev/.systemd/ask-password/");
91 file_monitor = directory.monitor_directory(0);
92 file_monitor.changed.connect(file_monitor_changed);
93
94 current = null;
95 look_for_password();
96
97 activate.connect(status_icon_activate);
98 }
99
100 void file_monitor_changed(GLib.File file, GLib.File? other_file, GLib.FileMonitorEvent event_type) throws GLib.Error {
101
102 if (!file.get_basename().has_prefix("ask."))
103 return;
104
105 if (event_type == FileMonitorEvent.CREATED ||
106 event_type == FileMonitorEvent.DELETED)
107 look_for_password();
108 }
109
110 void look_for_password() throws GLib.Error {
111
112 if (current != null) {
113 if (!current.query_exists()) {
114 current = null;
115 if (password_dialog != null)
116 password_dialog.response(ResponseType.REJECT);
117 }
118 }
119
120 if (current == null) {
121 FileEnumerator enumerator = directory.enumerate_children("standard::name", FileQueryInfoFlags.NOFOLLOW_SYMLINKS);
122
123 FileInfo i;
124 while ((i = enumerator.next_file()) != null) {
125 if (!i.get_name().has_prefix("ask."))
126 continue;
127
128 current = directory.get_child(i.get_name());
129
130 if (load_password())
131 break;
132
133 current = null;
134 }
135 }
136
137 if (current == null)
138 set_visible(false);
139
140 }
141
efb3237e 142 bool load_password() throws GLib.Error {
490aed58
LP
143
144 KeyFile key_file = new KeyFile();
145
146 try {
147 timespec ts;
148
149 key_file.load_from_file(current.get_path(), KeyFileFlags.NONE);
150
151 string not_after_as_string = key_file.get_string("Ask", "NotAfter");
152
153 clock_gettime(1, out ts);
154 uint64 now = (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
155
156 uint64 not_after;
157 if (not_after_as_string.scanf("%llu", out not_after) != 1)
158 return false;
159
160 if (not_after < now)
161 return false;
162
163 socket = key_file.get_string("Ask", "Socket");
164 } catch (GLib.Error e) {
165 return false;
166 }
167
168 try {
169 message = key_file.get_string("Ask", "Message").compress();
170 } catch (GLib.Error e) {
171 message = "Please Enter System Password!";
172 }
173 set_tooltip_text(message);
174
175 try {
176 icon = key_file.get_string("Ask", "Icon");
177 } catch (GLib.Error e) {
178 icon = "dialog-password";
179 }
180 set_from_icon_name(icon);
181
182 set_visible(true);
efb3237e 183
230e5a3f 184 Notification n = new Notification(title, message, icon);
efb3237e
LP
185 n.set_timeout(5000);
186 n.show();
187
490aed58
LP
188 return true;
189 }
190
191 void status_icon_activate() throws GLib.Error {
192
193 if (current == null)
194 return;
195
196 if (password_dialog != null) {
197 password_dialog.present();
198 return;
199 }
200
201 password_dialog = new PasswordDialog(message, icon);
202
203 int result = password_dialog.run();
204 string password = password_dialog.entry.get_text();
205
206 password_dialog.destroy();
207 password_dialog = null;
208
209 if (result == ResponseType.REJECT ||
210 result == ResponseType.DELETE_EVENT)
211 return;
212
213 int to_process;
214
215 Process.spawn_async_with_pipes(
216 null,
217 { "/usr/bin/pkexec", "/lib/systemd/systemd-reply-password", result == ResponseType.OK ? "1" : "0", socket },
218 null,
219 0,
220 null,
221 null,
222 out to_process,
223 null,
224 null);
225
226 OutputStream stream = new UnixOutputStream(to_process, true);
227
230e5a3f 228 stream.write(password.data, null);
490aed58
LP
229 }
230}
231
232static const OptionEntry entries[] = {
233 { null }
234};
235
236void show_error(string e) {
237 var m = new MessageDialog(null, 0, MessageType.ERROR, ButtonsType.CLOSE, "%s", e);
238 m.run();
239 m.destroy();
240}
241
242int main(string[] args) {
243 try {
244 Gtk.init_with_args(ref args, "[OPTION...]", entries, "systemd-ask-password-agent");
efb3237e 245 Notify.init("Password Agent");
490aed58
LP
246
247 MyStatusIcon i = new MyStatusIcon();
248 Gtk.main();
249
250 } catch (DBus.Error e) {
251 show_error(e.message);
252 } catch (GLib.Error e) {
253 show_error(e.message);
254 }
255
256 return 0;
257}