Merge lp:~elementary-apps/switchboard-plug-parental-controls/saving-rewrite into lp:~elementary-pantheon/switchboard-plug-parental-controls/trunk

Proposed by Adam Bieńkowski
Status: Merged
Approved by: Danielle Foré
Approved revision: 232
Merged at revision: 280
Proposed branch: lp:~elementary-apps/switchboard-plug-parental-controls/saving-rewrite
Merge into: lp:~elementary-pantheon/switchboard-plug-parental-controls/trunk
Diff against target: 1129 lines (+502/-418)
14 files modified
lib/exec-monitor.c (+2/-2)
src/daemon/CMakeLists.txt (+7/-4)
src/daemon/IptablesHelper.vala (+0/-105)
src/daemon/ProcessWatcher.vala (+0/-110)
src/daemon/Restriction.vala (+60/-0)
src/daemon/RestrictionController.vala (+48/-0)
src/daemon/Restrictions/AppRestriction.vala (+114/-0)
src/daemon/Restrictions/TimeRestriction.vala (+118/-0)
src/daemon/Restrictions/WebRestriction.vala (+82/-0)
src/daemon/SessionHandler.vala (+59/-34)
src/daemon/SessionManager.vala (+7/-12)
src/daemon/Timer.vala (+0/-116)
src/daemon/UserConfig.vala (+3/-33)
vapi/exec-monitor.vapi (+2/-2)
To merge this branch: bzr merge lp:~elementary-apps/switchboard-plug-parental-controls/saving-rewrite
Reviewer Review Type Date Requested Status
Corentin Noël code Approve
Review via email: mp+320256@code.launchpad.net

Commit message

* Rework daemon backend

Description of the change

This branch reworks the way backend is set up. The restrictions are now based on abstract Restriction class, they can start, stop, store their targets etc. The behaviour of the daemon should not change in any way. I want to also make some improvements to the AppRestriction and WebRestriction but for now the core code remains the same.

Before approving, please test every feature & if it works how it should.

To post a comment you must log in.
232. By Adam Bieńkowski

Resolve conflicts

Revision history for this message
Corentin Noël (tintou) wrote :

The code looks good to me, it only requires more testing

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/exec-monitor.c'
--- lib/exec-monitor.c 2016-08-30 18:01:00 +0000
+++ lib/exec-monitor.c 2017-03-17 20:20:51 +0000
@@ -74,7 +74,7 @@
74}74}
7575
76void76void
77exec_monitor_start (ExecMonitor *self,77exec_monitor_start_monitor (ExecMonitor *self,
78 GAsyncReadyCallback callback,78 GAsyncReadyCallback callback,
79 gpointer user_data)79 gpointer user_data)
80{80{
@@ -102,7 +102,7 @@
102}102}
103103
104void104void
105exec_monitor_stop (ExecMonitor *self)105exec_monitor_stop_monitor (ExecMonitor *self)
106{106{
107 ExecMonitorInterface *iface;107 ExecMonitorInterface *iface;
108108
109109
=== modified file 'src/daemon/CMakeLists.txt'
--- src/daemon/CMakeLists.txt 2016-09-10 22:16:01 +0000
+++ src/daemon/CMakeLists.txt 2017-03-17 20:20:51 +0000
@@ -9,15 +9,17 @@
99
10vala_precompile (VALA_C ${DAEMON_EXEC_NAME}10vala_precompile (VALA_C ${DAEMON_EXEC_NAME}
11 Daemon.vala11 Daemon.vala
12 ProcessWatcher.vala
13 Process.vala12 Process.vala
14 IptablesHelper.vala
15 Timer.vala
16 SessionManager.vala13 SessionManager.vala
17 SessionHandler.vala14 SessionHandler.vala
18 Interfaces.vala15 Interfaces.vala
19 UserConfig.vala16 UserConfig.vala
20 Server.vala17 Server.vala
18 Restriction.vala
19 Restrictions/AppRestriction.vala
20 Restrictions/TimeRestriction.vala
21 Restrictions/WebRestriction.vala
22 RestrictionController.vala
21 ${CMAKE_SOURCE_DIR}/src/shared/Constants.vala23 ${CMAKE_SOURCE_DIR}/src/shared/Constants.vala
22 ${CMAKE_SOURCE_DIR}/src/shared/Utils.vala24 ${CMAKE_SOURCE_DIR}/src/shared/Utils.vala
23 ${CMAKE_SOURCE_DIR}/src/shared/PAM/Token.vala25 ${CMAKE_SOURCE_DIR}/src/shared/PAM/Token.vala
@@ -28,6 +30,7 @@
28 accountsservice30 accountsservice
29 polkit-gobject-131 polkit-gobject-1
30 gio-2.032 gio-2.0
33 gee-0.8
31 exec-monitor34 exec-monitor
32OPTIONS35OPTIONS
33 --vapidir=${CMAKE_SOURCE_DIR}/vapi/36 --vapidir=${CMAKE_SOURCE_DIR}/vapi/
@@ -42,4 +45,4 @@
4245
43# Installation46# Installation
44install (TARGETS ${DAEMON_EXEC_NAME} RUNTIME DESTINATION bin)47install (TARGETS ${DAEMON_EXEC_NAME} RUNTIME DESTINATION bin)
45install (TARGETS ${EXEC_MONITOR_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
46\ No newline at end of file48\ No newline at end of file
49install (TARGETS ${EXEC_MONITOR_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
4750
=== removed file 'src/daemon/IptablesHelper.vala'
--- src/daemon/IptablesHelper.vala 2016-09-10 22:16:01 +0000
+++ src/daemon/IptablesHelper.vala 1970-01-01 00:00:00 +0000
@@ -1,105 +0,0 @@
1// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2/*-
3 * Copyright (c) 2015 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 3 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Authored by: Adam Bieńkowski <donadigos159@gmail.com>
21 */
22
23 namespace PC.Daemon {
24 public class IptablesHelper : Object {
25 private const string IPTABLES_EXEC = "iptables";
26 private const int DPORT = 80;
27
28 private UserConfig config;
29 private string[] current_urls;
30
31 public static bool get_can_start () {
32 return Environment.find_program_in_path (IPTABLES_EXEC) != null;
33 }
34
35 public IptablesHelper (UserConfig config) {
36 this.config = config;
37 }
38
39 public void start () {
40 this.current_urls = config.get_block_urls ();
41 add_rules ();
42 }
43
44 public void restart () {
45 remove_rules ();
46
47 current_urls = config.get_block_urls ();
48 add_rules ();
49 }
50
51 public void stop () {
52 remove_rules ();
53 }
54
55 private void add_rules () {
56 foreach (string url in current_urls) {
57 string[] addresses = get_addresses_from_name (url);
58 foreach (string address in addresses) {
59 process_adress (address, "-A");
60 }
61 }
62 }
63
64 private string[] get_addresses_from_name (string name) {
65 string[] address_list = {};
66 var resolver = Resolver.get_default ();
67 try {
68 var addresses = resolver.lookup_by_name (name, null);
69 foreach (InetAddress address in addresses) {
70 if (address.get_family () == SocketFamily.IPV4) {
71 address_list += address.to_string ();
72 }
73 }
74 } catch (Error e) {
75 warning (e.message);
76 }
77
78 return address_list;
79 }
80
81 private void process_adress (string address, string option) {
82 try {
83 GLib.Process.spawn_sync ("/",
84 { IPTABLES_EXEC, option, "OUTPUT", "-p", "tcp", "-d", address, "--dport", DPORT.to_string (), "-j", "REJECT" },
85 Environ.get (),
86 SpawnFlags.SEARCH_PATH,
87 null,
88 null,
89 null,
90 null);
91 } catch (SpawnError e) {
92 warning ("%s\n", e.message);
93 }
94 }
95
96 private void remove_rules () {
97 foreach (string url in current_urls) {
98 string[] addresses = get_addresses_from_name (url);
99 foreach (string address in addresses) {
100 process_adress (address, "-D");
101 }
102 }
103 }
104 }
105}
106\ No newline at end of file0\ No newline at end of file
1071
=== removed file 'src/daemon/ProcessWatcher.vala'
--- src/daemon/ProcessWatcher.vala 2016-12-09 17:17:31 +0000
+++ src/daemon/ProcessWatcher.vala 1970-01-01 00:00:00 +0000
@@ -1,110 +0,0 @@
1// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2/*-
3 * Copyright (c) 2015 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 3 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Authored by: Adam Bieńkowski <donadigos159@gmail.com>
21 */
22
23namespace PC.Daemon {
24 public class ProcessWatcher : GLib.Object, ExecMonitor {
25 public UserConfig? config = null;
26 private List<string> allowed_executables;
27 private Polkit.Authority authority;
28
29 public ProcessWatcher () {
30 allowed_executables = new List<string> ();
31
32 try {
33 authority = Polkit.Authority.get_sync ();
34 } catch (Error e) {
35 warning ("%s\n", e.message);
36 }
37 }
38
39 public void set_config (UserConfig? config) {
40 this.config = config;
41 allowed_executables = new List<string> ();
42 }
43
44 private void handle_pid (int pid) {
45 if (config == null || !config.get_active ()) {
46 return;
47 }
48
49 var process = new Process (pid);
50
51 string? command = process.get_command ();
52 if (command == null || command == "") {
53 return;
54 }
55
56 string[]? args = {};
57 try {
58 Shell.parse_argv (command, out args);
59 if (args == null || args.length < 1) {
60 return;
61 }
62 } catch (ShellError e) {
63 warning ("%s\n", e.message);
64 return;
65 }
66
67 string executable = args[0];
68
69 if (!executable.has_prefix (Path.DIR_SEPARATOR_S)) {
70 executable = Environment.find_program_in_path (executable);
71 }
72
73 unowned List<string> link = allowed_executables.find_custom (executable, strcmp);
74 if (link != null) {
75 allowed_executables.remove_link (link);
76 return;
77 }
78
79 if (executable != null && executable in config.get_targets ()) {
80 process.kill ();
81
82 var server = Server.get_default ();
83 if (config.get_admin () && authority != null) {
84 ulong signal_id = 0;
85 signal_id = server.app_authorization_ended.connect ((client_pid) => {
86 try {
87 var unix_user = new Polkit.UnixUser.for_name (config.username);
88 var result = authority.check_authorization_sync (new Polkit.UnixProcess.for_owner (client_pid, 0, unix_user.get_uid ()),
89 Constants.PARENTAL_CONTROLS_ACTION_ID,
90 null,
91 Polkit.CheckAuthorizationFlags.NONE);
92 if (result.get_is_authorized ()) {
93 allowed_executables.append (executable);
94 server.launch (args);
95 }
96 } catch (Error e) {
97 warning ("%s\n", e.message);
98 }
99
100 server.disconnect (signal_id);
101 });
102
103 server.app_authorize (config.username, executable, Constants.PARENTAL_CONTROLS_ACTION_ID);
104 } else {
105 server.show_app_unavailable (executable);
106 }
107 }
108 }
109 }
110}
1110
=== added file 'src/daemon/Restriction.vala'
--- src/daemon/Restriction.vala 1970-01-01 00:00:00 +0000
+++ src/daemon/Restriction.vala 2017-03-17 20:20:51 +0000
@@ -0,0 +1,60 @@
1/*-
2 * Copyright (c) 2016 elementary LLC (https://elementary.io)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 3 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 *
19 * Authored by: Felipe Escoto <felescoto95@hotmail.com>
20 */
21
22namespace PC.Daemon {
23 public abstract class Restriction<T> : Object {
24 public GLib.List<T> targets;
25
26 construct {
27 targets = new GLib.List<T> ();
28 }
29
30 public static bool get_supported () {
31 return true;
32 }
33
34 public abstract void start ();
35 public abstract void stop ();
36
37 public void add_target (T item) {
38 targets.append (item);
39 }
40
41 public void remove_target (T item) {
42 targets.remove (item);
43 }
44
45 public void update_targets (GLib.List<T> new_targets) {
46 stop ();
47 clear_targets ();
48
49 foreach (T target in new_targets) {
50 add_target (target);
51 }
52
53 start ();
54 }
55
56 public void clear_targets () {
57 targets.remove (targets.data);
58 }
59 }
60}
0\ No newline at end of file61\ No newline at end of file
162
=== added file 'src/daemon/RestrictionController.vala'
--- src/daemon/RestrictionController.vala 1970-01-01 00:00:00 +0000
+++ src/daemon/RestrictionController.vala 2017-03-17 20:20:51 +0000
@@ -0,0 +1,48 @@
1/*-
2 * Copyright (c) 2016 elementary LLC (https://elementary.io)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 3 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 *
19 * Authored by: Adam Bieńkowski <donadigos159@gmail.com>
20 */
21
22namespace PC.Daemon {
23 public class RestrictionController : Object {
24 private Gee.ArrayList<Restriction> restrictions;
25
26 construct {
27 restrictions = new Gee.ArrayList<Restriction> ();
28 }
29
30 public void add_restriction (Restriction restriction) {
31 if (restrictions.contains (restriction)) {
32 return;
33 }
34
35 restrictions.add (restriction);
36 restriction.start ();
37 }
38
39 public void remove_restriction (Restriction restriction) {
40 if (!restrictions.contains (restriction)) {
41 return;
42 }
43
44 restrictions.remove (restriction);
45 restriction.stop ();
46 }
47 }
48}
0\ No newline at end of file49\ No newline at end of file
150
=== added directory 'src/daemon/Restrictions'
=== added file 'src/daemon/Restrictions/AppRestriction.vala'
--- src/daemon/Restrictions/AppRestriction.vala 1970-01-01 00:00:00 +0000
+++ src/daemon/Restrictions/AppRestriction.vala 2017-03-17 20:20:51 +0000
@@ -0,0 +1,114 @@
1// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2/*-
3 * Copyright (c) 2015 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 3 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Authored by: Adam Bieńkowski <donadigos159@gmail.com>
21 */
22
23namespace PC.Daemon {
24 public class AppRestriction : Restriction<string>, ExecMonitor {
25 public string username { get; set; }
26 public bool admin { get; set; }
27
28 private Gee.ArrayList<string> allowed_executables;
29 private Polkit.Authority authority;
30
31 construct {
32 allowed_executables = new Gee.ArrayList<string> ();
33
34 try {
35 authority = Polkit.Authority.get_sync ();
36 } catch (Error e) {
37 warning ("%s\n", e.message);
38 }
39 }
40
41 public override void start () {
42 start_monitor.begin ();
43 }
44
45 public override void stop () {
46 stop_monitor ();
47 allowed_executables.clear ();
48 }
49
50 private void handle_pid (int pid) {
51 var process = new Process (pid);
52
53 string? command = process.get_command ();
54 if (command == null || command == "") {
55 return;
56 }
57
58 string[]? args = {};
59 try {
60 Shell.parse_argv (command, out args);
61 if (args == null || args.length < 1) {
62 return;
63 }
64 } catch (ShellError e) {
65 warning ("%s\n", e.message);
66 return;
67 }
68
69 string executable = args[0];
70
71 if (!executable.has_prefix (Path.DIR_SEPARATOR_S)) {
72 executable = Environment.find_program_in_path (executable);
73 }
74
75 if (allowed_executables.contains (executable)) {
76 allowed_executables.remove (executable);
77 return;
78 }
79
80 if (executable == null || targets.find_custom (executable, strcmp) == null) {
81 return;
82 }
83
84 process.kill ();
85
86 var server = Server.get_default ();
87 if (!admin || authority == null) {
88 server.show_app_unavailable (executable);
89 return;
90 }
91
92 ulong signal_id = 0;
93 signal_id = server.app_authorization_ended.connect ((client_pid) => {
94 try {
95 var unix_user = (Polkit.UnixUser)Polkit.UnixUser.new_for_name (username);
96 var result = authority.check_authorization_sync (Polkit.UnixProcess.new_for_owner (client_pid, 0, unix_user.get_uid ()),
97 Constants.PARENTAL_CONTROLS_ACTION_ID,
98 null,
99 Polkit.CheckAuthorizationFlags.NONE);
100 if (result.get_is_authorized ()) {
101 allowed_executables.add (executable);
102 server.launch (args);
103 }
104 } catch (Error e) {
105 warning ("%s\n", e.message);
106 }
107
108 server.disconnect (signal_id);
109 });
110
111 server.app_authorize (username, executable, Constants.PARENTAL_CONTROLS_ACTION_ID);
112 }
113 }
114}
0\ No newline at end of file115\ No newline at end of file
1116
=== added file 'src/daemon/Restrictions/TimeRestriction.vala'
--- src/daemon/Restrictions/TimeRestriction.vala 1970-01-01 00:00:00 +0000
+++ src/daemon/Restrictions/TimeRestriction.vala 2017-03-17 20:20:51 +0000
@@ -0,0 +1,118 @@
1// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2/*-
3 * Copyright (c) 2016 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 3 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Authored by: Adam Bieńkowski <donadigos159@gmail.com>
21 */
22
23namespace PC.Daemon {
24 public class TimeRestriction : Restriction<PAM.Token> {
25 private const int MINUTE_INTERVAL = 60;
26 private const int HOUR_INTERVAL = 3600;
27
28 public signal void terminate ();
29
30 private uint[] timeout_ids;
31
32 public override void start () {
33 foreach (PAM.Token token in targets) {
34 process_token (token);
35 }
36 }
37
38 private void process_token (PAM.Token token) {
39 var times_info = token.get_times_info ();
40 if (times_info.length () == 0) {
41 return;
42 }
43
44 PAM.TimeInfo? current = null;
45
46 int day_of_week = new DateTime.now_local ().get_day_of_week ();
47 foreach (PAM.TimeInfo info in times_info) {
48 if ((day_of_week < 6 && info.day_type == PAM.DayType.WEEKDAY)
49 || (day_of_week >= 6 && info.day_type == PAM.DayType.WEEKEND)
50 || info.day_type == PAM.DayType.ALL) {
51 current = info;
52 break;
53 }
54 }
55
56 if (current == null) {
57 return;
58 }
59
60 var span = get_difference_span (current.to);
61 int minutes = ((int)(span / GLib.TimeSpan.MINUTE)).abs ();
62
63 if (minutes > 0) {
64 start_loop (minutes);
65 } else {
66 terminate ();
67 }
68
69 timeout_ids += Timeout.add_seconds (HOUR_INTERVAL * 24, () => {
70 stop ();
71 start ();
72 return true;
73 });
74 }
75
76 public override void stop () {
77 foreach (uint timeout_id in timeout_ids) {
78 GLib.Source.remove (timeout_id);
79 }
80 }
81
82 private TimeSpan get_difference_span (string estimated_time_str) {
83 int hour = int.parse (estimated_time_str.slice (0, 2));
84 int minute = int.parse (estimated_time_str.substring (2));
85
86 if (hour == 24) {
87 hour = 0;
88 }
89
90 var current_date = new DateTime.now_local ();
91 var estimated_date = current_date.add_full (0, 0,
92 (hour < current_date.get_hour ()) ? 1 : 0,
93 hour - current_date.get_hour (),
94 minute - current_date.get_minute (),
95 0);
96 return estimated_date.difference (current_date);
97 }
98
99 private void start_loop (int minutes) {
100 Server.get_default ().show_timeout (minutes / MINUTE_INTERVAL, minutes % MINUTE_INTERVAL);
101 timeout_ids += Timeout.add_seconds (MINUTE_INTERVAL, () => {
102 minutes--;
103 if (minutes == MINUTE_INTERVAL ||
104 minutes == 10 ||
105 minutes == 5 ||
106 minutes == 1) {
107 Server.get_default ().show_timeout (minutes / MINUTE_INTERVAL, minutes % MINUTE_INTERVAL);
108 }
109
110 if (minutes == 0) {
111 terminate ();
112 }
113
114 return (minutes > 0);
115 });
116 }
117 }
118}
0\ No newline at end of file119\ No newline at end of file
1120
=== added file 'src/daemon/Restrictions/WebRestriction.vala'
--- src/daemon/Restrictions/WebRestriction.vala 1970-01-01 00:00:00 +0000
+++ src/daemon/Restrictions/WebRestriction.vala 2017-03-17 20:20:51 +0000
@@ -0,0 +1,82 @@
1// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2/*-
3 * Copyright (c) 2015 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 3 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Authored by: Adam Bieńkowski <donadigos159@gmail.com>
21 */
22
23 namespace PC.Daemon {
24 public class WebRestriction : Restriction<string> {
25 private const string IPTABLES_EXEC = "iptables";
26 private const int DPORT = 80;
27
28 public new static bool get_supported () {
29 return Environment.find_program_in_path (IPTABLES_EXEC) != null;
30 }
31
32 public override void start () {
33 foreach (string url in targets) {
34 string[] addresses = get_addresses_from_name (url);
35 foreach (string address in addresses) {
36 process_adress (address, "-A");
37 }
38 }
39 }
40
41 public override void stop () {
42 foreach (string url in targets) {
43 string[] addresses = get_addresses_from_name (url);
44 foreach (string address in addresses) {
45 process_adress (address, "-D");
46 }
47 }
48 }
49
50 private string[] get_addresses_from_name (string name) {
51 string[] address_list = {};
52 var resolver = Resolver.get_default ();
53 try {
54 var addresses = resolver.lookup_by_name (name, null);
55 foreach (InetAddress address in addresses) {
56 if (address.get_family () == SocketFamily.IPV4) {
57 address_list += address.to_string ();
58 }
59 }
60 } catch (Error e) {
61 warning (e.message);
62 }
63
64 return address_list;
65 }
66
67 private void process_adress (string address, string option) {
68 try {
69 GLib.Process.spawn_sync ("/",
70 { IPTABLES_EXEC, option, "OUTPUT", "-p", "tcp", "-d", address, "--dport", DPORT.to_string (), "-j", "REJECT" },
71 Environ.get (),
72 SpawnFlags.SEARCH_PATH,
73 null,
74 null,
75 null,
76 null);
77 } catch (SpawnError e) {
78 warning ("%s\n", e.message);
79 }
80 }
81 }
82}
0\ No newline at end of file83\ No newline at end of file
184
=== modified file 'src/daemon/SessionHandler.vala'
--- src/daemon/SessionHandler.vala 2016-09-10 22:16:01 +0000
+++ src/daemon/SessionHandler.vala 2017-03-17 20:20:51 +0000
@@ -22,8 +22,11 @@
2222
23 namespace PC.Daemon {23 namespace PC.Daemon {
24 public class SessionHandler : Object {24 public class SessionHandler : Object {
25 private IptablesHelper iptables_helper;25 private RestrictionController controller;
26 private Timer? timer;26
27 private AppRestriction app_restriction;
28 private WebRestriction web_restriction;
29 private TimeRestriction time_restriction;
2730
28 private UserConfig config;31 private UserConfig config;
29 public ISession session;32 public ISession session;
@@ -41,19 +44,19 @@
41 return;44 return;
42 }45 }
4346
44 iptables_helper = new IptablesHelper (config);47 controller = new RestrictionController ();
4548
46 var token = PAM.Reader.get_token_for_user (Constants.PAM_TIME_CONF_PATH, session.name);49 app_restriction = new AppRestriction ();
47 if (token != null) {50 web_restriction = new WebRestriction ();
48 timer = new Timer (token);51
49 timer.terminate.connect (() => {52 time_restriction = new TimeRestriction ();
50 try {53 time_restriction.terminate.connect (() => {
51 session.terminate ();54 try {
52 } catch (IOError e) {55 session.terminate ();
53 warning (e.message);56 } catch (IOError e) {
54 } 57 warning (e.message);
55 });58 }
56 }59 });
57 }60 }
5861
59 public string get_id () {62 public string get_id () {
@@ -69,35 +72,57 @@
69 return;72 return;
70 }73 }
7174
72 if (IptablesHelper.get_can_start ()) {75 app_restriction.username = config.username;
73 iptables_helper.start ();76 app_restriction.admin = config.get_admin ();
74 }77
7578 foreach (string target in config.get_targets ()) {
76 if (timer != null) {79 app_restriction.add_target (target);
77 timer.start ();80 }
78 }81
82 controller.add_restriction (app_restriction);
83
84 if (WebRestriction.get_supported ()) {
85 foreach (string url in config.get_block_urls ()) {
86 web_restriction.add_target (url);
87 }
88
89 controller.add_restriction (web_restriction);
90 }
91
92 var token = PAM.Reader.get_token_for_user (Constants.PAM_TIME_CONF_PATH, session.name);
93 time_restriction.add_target (token);
94
95 controller.add_restriction (time_restriction);
79 }96 }
8097
81 public void update () {98 public void update () {
82 if (!config.get_active ()) {99 if (!config.get_active ()) {
83 iptables_helper.stop ();100 stop ();
84 if (timer != null) {
85 timer.stop ();
86 }
87
88 return;101 return;
89 }102 }
90103
91 if (IptablesHelper.get_can_start ()) {104 app_restriction.username = config.username;
92 iptables_helper.restart ();105 app_restriction.admin = config.get_admin ();
93 }106
107 var new_targets = new GLib.List<string> ();
108 foreach (string target in config.get_targets ()) {
109 new_targets.append (target);
110 }
111
112 app_restriction.update_targets (new_targets);
113
114 new_targets = new GLib.List<string> ();
115 foreach (string url in config.get_block_urls ()) {
116 new_targets.append (url);
117 }
118
119 web_restriction.update_targets (new_targets);
94 }120 }
95121
96 public void stop () {122 public void stop () {
97 iptables_helper.stop ();123 controller.remove_restriction (app_restriction);
98 if (timer != null) {124 controller.remove_restriction (web_restriction);
99 timer.stop ();125 controller.remove_restriction (time_restriction);
100 }
101 } 126 }
102 }127 }
103}128}
104\ No newline at end of file129\ No newline at end of file
105130
=== modified file 'src/daemon/SessionManager.vala'
--- src/daemon/SessionManager.vala 2016-09-10 22:16:01 +0000
+++ src/daemon/SessionManager.vala 2017-03-17 20:20:51 +0000
@@ -25,7 +25,6 @@
25 public SessionHandler? current_handler = null;25 public SessionHandler? current_handler = null;
26 private IManager? manager = null;26 private IManager? manager = null;
27 private DBusConnection? conn = null;27 private DBusConnection? conn = null;
28 private ProcessWatcher pwatcher;
2928
30 private uint[] signal_ids;29 private uint[] signal_ids;
3130
@@ -45,9 +44,6 @@
45 } catch (IOError e) {44 } catch (IOError e) {
46 warning ("%s\n", e.message);45 warning ("%s\n", e.message);
47 }46 }
48
49 pwatcher = new ProcessWatcher ();
50 pwatcher.start.begin ();
51 }47 }
5248
53 public void start () {49 public void start () {
@@ -107,13 +103,14 @@
107103
108 stop_current_handler ();104 stop_current_handler ();
109105
110 if (session != null &&106 if (session == null ||
111 session.name != null &&107 session.name == null ||
112 !(session.name in Constants.DAEMON_IGNORED_USERS)) {108 session.name in Constants.DAEMON_IGNORED_USERS) {
113 current_handler = new SessionHandler (session);109 return;
114 current_handler.start ();
115 pwatcher.set_config (current_handler.get_config ());
116 }110 }
111
112 current_handler = new SessionHandler (session);
113 current_handler.start ();
117 }114 }
118115
119 private void stop_current_handler () {116 private void stop_current_handler () {
@@ -121,8 +118,6 @@
121 current_handler.stop ();118 current_handler.stop ();
122 current_handler = null;119 current_handler = null;
123 }120 }
124
125 pwatcher.set_config (null);
126 }121 }
127 }122 }
128}123}
129\ No newline at end of file124\ No newline at end of file
130125
=== removed file 'src/daemon/Timer.vala'
--- src/daemon/Timer.vala 2016-08-30 17:28:55 +0000
+++ src/daemon/Timer.vala 1970-01-01 00:00:00 +0000
@@ -1,116 +0,0 @@
1// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2/*-
3 * Copyright (c) 2016 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 3 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Authored by: Adam Bieńkowski <donadigos159@gmail.com>
21 */
22
23namespace PC.Daemon {
24 public class Timer : Object {
25 private const int MINUTE_INTERVAL = 60;
26 private const int HOUR_INTERVAL = 3600;
27
28 public signal void terminate ();
29
30 private PAM.Token token;
31 private uint[] timeout_ids;
32
33 public Timer (PAM.Token token) {
34 this.token = token;
35 }
36
37 public void start () {
38 var times_info = token.get_times_info ();
39 if (times_info.length () == 0) {
40 return;
41 }
42
43 PAM.TimeInfo? current = null;
44
45 int day_of_week = new DateTime.now_local ().get_day_of_week ();
46 foreach (PAM.TimeInfo info in times_info) {
47 if ((day_of_week < 6 && info.day_type == PAM.DayType.WEEKDAY)
48 || (day_of_week >= 6 && info.day_type == PAM.DayType.WEEKEND)
49 || info.day_type == PAM.DayType.ALL) {
50 current = info;
51 break;
52 }
53 }
54
55 if (current == null) {
56 return;
57 }
58
59 var span = get_difference_span (current.to);
60 int minutes = ((int)(span / GLib.TimeSpan.MINUTE)).abs ();
61
62 if (minutes > 0) {
63 start_loop (minutes);
64 } else {
65 terminate ();
66 }
67
68 timeout_ids += Timeout.add_seconds (HOUR_INTERVAL * 24, () => {
69 start ();
70 return true;
71 });
72 }
73
74 public void stop () {
75 foreach (uint timeout_id in timeout_ids) {
76 GLib.Source.remove (timeout_id);
77 }
78 }
79
80 private TimeSpan get_difference_span (string estimated_time_str) {
81 int hour = int.parse (estimated_time_str.slice (0, 2));
82 int minute = int.parse (estimated_time_str.substring (2));
83
84 if (hour == 24) {
85 hour = 0;
86 }
87
88 var current_date = new DateTime.now_local ();
89 var estimated_date = current_date.add_full (0, 0,
90 (hour < current_date.get_hour ()) ? 1 : 0,
91 hour - current_date.get_hour (),
92 minute - current_date.get_minute (),
93 0);
94 return estimated_date.difference (current_date);
95 }
96
97 private void start_loop (int minutes) {
98 Server.get_default ().show_timeout (minutes / MINUTE_INTERVAL, minutes % MINUTE_INTERVAL);
99 timeout_ids += Timeout.add_seconds (MINUTE_INTERVAL, () => {
100 minutes--;
101 if (minutes == MINUTE_INTERVAL ||
102 minutes == 10 ||
103 minutes == 5 ||
104 minutes == 1) {
105 Server.get_default ().show_timeout (minutes / MINUTE_INTERVAL, minutes % MINUTE_INTERVAL);
106 }
107
108 if (minutes == 0) {
109 terminate ();
110 }
111
112 return (minutes > 0);
113 });
114 }
115 }
116}
117\ No newline at end of file0\ No newline at end of file
1181
=== modified file 'src/daemon/UserConfig.vala'
--- src/daemon/UserConfig.vala 2016-09-10 22:16:01 +0000
+++ src/daemon/UserConfig.vala 2017-03-17 20:20:51 +0000
@@ -22,7 +22,7 @@
2222
23namespace PC.Daemon {23namespace PC.Daemon {
24 public class UserConfig : Object {24 public class UserConfig : Object {
25 public string username;25 public string username { get; set; }
2626
27 private static KeyFile key;27 private static KeyFile key;
28 private static List<UserConfig> config_list;28 private static List<UserConfig> config_list;
@@ -63,12 +63,7 @@
63 warning (e.message);63 warning (e.message);
64 }64 }
65 65
66 foreach (Act.User user in Utils.get_usermanager ().list_users ()) {66 foreach (string username in key.get_groups ()) {
67 string username = user.get_user_name ();
68 if (!key.has_group (username)) {
69 continue;
70 }
71
72 var user_config = new UserConfig (username);67 var user_config = new UserConfig (username);
73 config_list.append (user_config);68 config_list.append (user_config);
74 }69 }
@@ -77,25 +72,10 @@
77 private static bool init_config_file () {72 private static bool init_config_file () {
78 var file = File.new_for_path (Constants.DAEMON_CONF_FILE);73 var file = File.new_for_path (Constants.DAEMON_CONF_FILE);
79 if (!file.query_exists ()) {74 if (!file.query_exists ()) {
80 critical ("Could not found daemon config file: %s does not exist".printf (file.get_path ()));75 critical ("Could not find daemon config file: %s does not exist".printf (file.get_path ()));
81 return false;76 return false;
82 }77 }
8378
84 try {
85 var monitor = file.monitor (FileMonitorFlags.NONE, null);
86 monitor.changed.connect ((src, dest, event) => {
87 if (event == FileMonitorEvent.CHANGES_DONE_HINT) {
88 foreach (UserConfig config in config_list) {
89 config.update_key ();
90 }
91
92 Server.get_default ().config_changed ();
93 }
94 });
95 } catch (Error e) {
96 warning (e.message);
97 }
98
99 return true;79 return true;
100 }80 }
10181
@@ -175,16 +155,6 @@
175 return false;155 return false;
176 }156 }
177157
178 public void update_key () {
179 try {
180 key.load_from_file (Constants.DAEMON_CONF_FILE, KeyFileFlags.KEEP_COMMENTS | KeyFileFlags.KEEP_TRANSLATIONS);
181 } catch (KeyFileError e) {
182 warning (e.message);
183 } catch (FileError e) {
184 warning (e.message);
185 }
186 }
187
188 private void save () {158 private void save () {
189 try {159 try {
190 key.save_to_file (Constants.DAEMON_CONF_FILE);160 key.save_to_file (Constants.DAEMON_CONF_FILE);
191161
=== modified file 'vapi/exec-monitor.vapi'
--- vapi/exec-monitor.vapi 2016-02-21 18:52:25 +0000
+++ vapi/exec-monitor.vapi 2017-03-17 20:20:51 +0000
@@ -1,6 +1,6 @@
1[CCode (cheader_filename = "exec-monitor.h", type_id = "exec_monitor_get_type ()")]1[CCode (cheader_filename = "exec-monitor.h", type_id = "exec_monitor_get_type ()")]
2public interface ExecMonitor : GLib.Object {2public interface ExecMonitor : GLib.Object {
3 public virtual async void start ();3 public virtual async void start_monitor ();
4 public virtual void stop ();4 public virtual void stop_monitor ();
5 public abstract void handle_pid (int pid);5 public abstract void handle_pid (int pid);
6}6}
7\ No newline at end of file7\ No newline at end of file

Subscribers

People subscribed via source and target branches