From e62b3c925d03239a372d425fb87b2cac65d8ef19 Mon Sep 17 00:00:00 2001
From: Dave Mielke <dave@mielke.cc>
Date: Thu, 28 Jan 2016 18:46:28 -0500
Subject: [PATCH] Add Polkit authorization manager support. (mg)

---
 Auth/Polkit/org.brltty.policy | 19 ++++++++++
 Programs/Makefile.in          |  2 +-
 Programs/auth.c               | 87 +++++++++++++++++++++++++++++++++++++++++++
 config.h.in                   |  3 ++
 config.mk.in                  |  6 ++-
 configure.ac                  |  3 ++
 6 files changed, 118 insertions(+), 2 deletions(-)
 create mode 100644 Auth/Polkit/org.brltty.policy

diff --git a/Auth/Polkit/org.brltty.policy b/Auth/Polkit/org.brltty.policy
new file mode 100644
index 0000000..bc312c5
--- /dev/null
+++ b/Auth/Polkit/org.brltty.policy
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+<policyconfig>
+  <vendor>The BRLTTY developers</vendor>
+  <vendor_url>http://www.brltty.com/</vendor_url>
+
+  <action id="org.brltty.write-display">
+    <description>Write to the Braille display</description>
+    <message>Privileges are required to access the Braille display</message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>yes</allow_active>
+    </defaults>
+  </action>
+
+</policyconfig>
diff --git a/Programs/Makefile.in b/Programs/Makefile.in
index 93f3a36..33b28ad 100644
--- a/Programs/Makefile.in
+++ b/Programs/Makefile.in
@@ -308,7 +308,7 @@ pid.$O:
 ###############################################################################
 
 auth.$O:
-	$(CC) $(LIBCFLAGS) -c $(SRC_DIR)/auth.c
+	$(CC) $(LIBCFLAGS) $(POLKIT_INCLUDES) -c $(SRC_DIR)/auth.c
 
 dataarea.$O:
 	$(CC) $(LIBCFLAGS) -c $(SRC_DIR)/dataarea.c
diff --git a/Programs/auth.c b/Programs/auth.c
index fe56020..1913640 100644
--- a/Programs/auth.c
+++ b/Programs/auth.c
@@ -437,6 +437,84 @@ authGroup_server (AuthDescriptor *auth, FileDescriptor fd, void *data) {
   return getPeerCredentials(auth, fd) &&
          checkPeerGroup(&auth->peerCredentials, group);
 }
+
+#ifdef USE_POLKIT
+#include <polkit/polkit.h>
+
+typedef struct {
+  PolkitAuthority *authority;
+} MethodDescriptor_polkit;
+
+static void *
+authPolkit_initialize (const char *parameter) {
+  MethodDescriptor_polkit *polkit;
+
+  if ((polkit = malloc(sizeof(*polkit)))) {
+    memset(polkit, 0, sizeof(*polkit));
+
+    GError *error_local = NULL;
+    polkit->authority = polkit_authority_get_sync(NULL, &error_local);
+
+    if (polkit->authority) {
+      return polkit;
+    } else {
+      g_error_free(error_local);
+      g_free(polkit);
+    }
+  } else {
+    logMallocError();
+  }
+
+  return NULL;
+}
+
+static void
+authPolkit_release (void *data) {
+  MethodDescriptor_polkit *polkit = data;
+  g_object_unref (polkit->authority);
+  free(polkit);
+}
+
+static int
+authPolkit_server (AuthDescriptor *auth, FileDescriptor fd, void *data) {
+  MethodDescriptor_polkit *polkit = data;
+
+  struct ucred cred;
+  socklen_t length = sizeof(cred);
+
+  if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &length) != -1) {
+    logMessage(LOG_DEBUG, "attempting to authenticate pid %d via polkit", cred.pid);
+
+    PolkitSubject *subject = polkit_unix_process_new_for_owner(cred.pid, -1, -1);
+    GError *error_local = NULL;
+
+    PolkitAuthorizationResult *result = polkit_authority_check_authorization_sync(
+      polkit->authority,
+      subject,
+      "org.brltty.write-display",
+      NULL,
+      POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
+      NULL,
+      &error_local
+    );
+
+    if (result) {
+      g_object_unref(result);
+
+      int isAuthorized = polkit_authorization_result_get_is_authorized(result);
+      logMessage(LOG_DEBUG, "polkit_authority_check_authorization_sync returned %d", isAuthorized);
+      return isAuthorized;
+    } else {
+      logSystemError("polkit_authority_check_authorization_sync");
+      g_error_free(error_local);
+    }
+  } else {
+    logSystemError("getsockopt[SO_PEERCRED]");
+  }
+
+  return 0;
+}
+#endif /* USE_POLKIT */
 #endif /* CAN_CHECK_CREDENTIALS */
 
 /* general functions */
@@ -463,6 +541,15 @@ static const MethodDefinition methodDefinitions[] = {
     .client = NULL,
     .server = authGroup_server
   },
+
+#ifdef USE_POLKIT
+  { .name = "polkit",
+    .initialize = authPolkit_initialize,
+    .release = authPolkit_release,
+    .client = NULL,
+    .server = authPolkit_server
+  },
+#endif /* USE_POLKIT */
 #endif /* CAN_CHECK_CREDENTIALS */
 
   {.name = NULL}
diff --git a/config.h.in b/config.h.in
index caa952f..9d03007 100644
--- a/config.h.in
+++ b/config.h.in
@@ -424,6 +424,9 @@ extern "C" {
 #undef USE_PKG_PORTS_MSDOS
 #undef USE_PKG_PORTS_WINDOWS
 
+/* Define this if the Polkit authorization manager is to be used. */
+#undef USE_POLKIT
+
 /* Define only one of the following curses packages. */
 #undef HAVE_PKG_CURSES
 #undef HAVE_PKG_NCURSES
diff --git a/config.mk.in b/config.mk.in
index b1ea111..b707bd4 100644
--- a/config.mk.in
+++ b/config.mk.in
@@ -102,6 +102,10 @@ DBUS_PACKAGE = @dbus_package@
 DBUS_INCLUDES = @dbus_includes@
 DBUS_LIBS = @dbus_libs@
 
+POLKIT_PACKAGE = @polkit_package@
+POLKIT_INCLUDES = @polkit_includes@
+POLKIT_LIBS = @polkit_libs@
+
 ICU_INCLUDES = @icu_includes@
 ICU_LIBS = @icu_libs@
 
@@ -244,7 +248,7 @@ LIBCXXFLAGS = $(CXXFLAGS) @LIBCXXFLAGS@
 
 LD = @LD@
 LDFLAGS = @LDFLAGS@
-LDLIBS = $(ICU_LIBS) $(SYSTEM_LIBS) @LIBS@
+LDLIBS = $(ICU_LIBS) $(POLKIT_LIBS) $(SYSTEM_LIBS) @LIBS@
 
 MKOBJ = @MKOBJ@
 MKMOD = @MKMOD@
diff --git a/configure.ac b/configure.ac
index b4382cd..aacdc29 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1778,6 +1778,9 @@ BRLTTY_HAVE_PACKAGE([dbus], ["dbus-1 >= 1.0"], [dnl
 BRLTTY_ARG_DRIVER([screen], [Screen])
 BRLTTY_SUMMARY_ITEM([screen-driver], [default_screen_driver])
 
+BRLTTY_HAVE_PACKAGE([polkit], [polkit-gobject-1],
+AC_DEFINE(USE_POLKIT, 1, [if the Polkit authorization manager should be used]))
+
 BRLTTY_ARG_ENABLE(
    [relocatable-install],
    [installation using paths relative to the program directory])
-- 
2.6.2

From b010048fdb6bdfbcadcd984fe5a85aa7a429d72a Mon Sep 17 00:00:00 2001
From: Dave Mielke <dave@mielke.cc>
Date: Thu, 28 Jan 2016 19:12:04 -0500
Subject: [PATCH] Add some spacing to the Polkit policy file. (dm)

---
 Auth/Polkit/org.brltty.policy | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/Auth/Polkit/org.brltty.policy b/Auth/Polkit/org.brltty.policy
index bc312c5..5460e81 100644
--- a/auth/Polkit/org.brltty.policy
+++ b/Auth/Polkit/org.brltty.policy
@@ -1,19 +1,22 @@
 <?xml version="1.0" encoding="UTF-8"?>
+
 <!DOCTYPE policyconfig PUBLIC
  "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"
+>
+
 <policyconfig>
-  <vendor>The BRLTTY developers</vendor>
+  <vendor>The BRLTTY Developers</vendor>
   <vendor_url>http://www.brltty.com/</vendor_url>
 
   <action id="org.brltty.write-display">
-    <description>Write to the Braille display</description>
-    <message>Privileges are required to access the Braille display</message>
+    <description>Write to the braille display</description>
+    <message>Privileges are required to access the braille display</message>
+
     <defaults>
       <allow_any>no</allow_any>
       <allow_inactive>no</allow_inactive>
       <allow_active>yes</allow_active>
     </defaults>
   </action>
-
 </policyconfig>
-- 
2.6.2

From 07d01a34bacc7166b4440fec02a89f9f74c2298a Mon Sep 17 00:00:00 2001
From: Dave Mielke <dave@mielke.cc>
Date: Tue, 2 Feb 2016 23:34:11 -0500
Subject: [PATCH] Fixes to Polkit authorization: (mg)

Log if polkit_unix_process_new_for_owner() fails.
Add comments to the arguments to polkit_authority_check_authorization_sync().
Move the g_object_unref() so that it isn't called until we're finished with the result.
---
 Programs/auth.c | 44 ++++++++++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 20 deletions(-)

diff --git a/Programs/auth.c b/Programs/auth.c
index 1913640..113fe9a 100644
--- a/Programs/auth.c
+++ b/Programs/auth.c
@@ -486,27 +486,31 @@ authPolkit_server (AuthDescriptor *auth, FileDescriptor fd, void *data) {
     logMessage(LOG_DEBUG, "attempting to authenticate pid %d via polkit", cred.pid);
 
     PolkitSubject *subject = polkit_unix_process_new_for_owner(cred.pid, -1, -1);
-    GError *error_local = NULL;
-
-    PolkitAuthorizationResult *result = polkit_authority_check_authorization_sync(
-      polkit->authority,
-      subject,
-      "org.brltty.write-display",
-      NULL,
-      POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
-      NULL,
-      &error_local
-    );
-
-    if (result) {
-      g_object_unref(result);
-
-      int isAuthorized = polkit_authorization_result_get_is_authorized(result);
-      logMessage(LOG_DEBUG, "polkit_authority_check_authorization_sync returned %d", isAuthorized);
-      return isAuthorized;
+    if (subject) {
+      GError *error_local = NULL;
+
+      PolkitAuthorizationResult *result = polkit_authority_check_authorization_sync(
+        polkit->authority,			/* authority */
+        subject,				/* PolkitSubject for client */
+        "org.brltty.write-display",		/* name of polkit action */
+        NULL,					/* details */
+        POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,	/* disallow interaction */
+        NULL,					/* GCancellable */
+        &error_local				/* returned error */
+      );
+
+      if (result) {
+        int isAuthorized = polkit_authorization_result_get_is_authorized(result);
+        g_object_unref(result);
+
+        logMessage(LOG_DEBUG, "polkit_authority_check_authorization_sync returned %d", isAuthorized);
+        return isAuthorized;
+      } else {
+        logSystemError("polkit_authority_check_authorization_sync");
+        g_error_free(error_local);
+      }
     } else {
-      logSystemError("polkit_authority_check_authorization_sync");
-      g_error_free(error_local);
+      logSystemError("polkit_unix_process_new_for_owner");
     }
   } else {
     logSystemError("getsockopt[SO_PEERCRED]");
-- 
2.6.2

From 74affe7d1401f2b43ad32e18cb78704d22604ad7 Mon Sep 17 00:00:00 2001
From: Dave Mielke <dave@mielke.cc>
Date: Tue, 12 Apr 2016 14:11:09 -0400
Subject: [PATCH] Fix a Polkit authorization race condition. (sk)

Using just the PID is deprecated as the obtained UID may be inaccurate.
---
 Documents/CONTRIBUTORS | 1 +
 Programs/auth.c        | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documents/CONTRIBUTORS b/Documents/CONTRIBUTORS
index b2afc0b..77329a7 100644
--- a/Documents/CONTRIBUTORS
+++ b/Documents/CONTRIBUTORS
@@ -51,6 +51,7 @@ Rudolf Weeber <Rudolf.Weeber@gmx.de>
 Samuel Thibault <samuel.thibault@ens-lyon.org>
 Samuel Yang <mison@bbs.ee.ntu.edu.tw>
 Sébastien Hinderer <sebastien.hinderer@ens-lyon.org>
+Sebastian Krahmer <krahmer@suse.com>
 Sérgio Neves <sergionevess@gmail.com>
 Simon Kainz <simon@familiekainz.at>
 Simon Meers <drmeers@gmail.com>
diff --git a/Programs/auth.c b/Programs/auth.c
index 113fe9a..f93afad 100644
--- a/Programs/auth.c
+++ b/Programs/auth.c
@@ -485,7 +485,7 @@ authPolkit_server (AuthDescriptor *auth, FileDescriptor fd, void *data) {
   if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &length) != -1) {
     logMessage(LOG_DEBUG, "attempting to authenticate pid %d via polkit", cred.pid);
 
-    PolkitSubject *subject = polkit_unix_process_new_for_owner(cred.pid, -1, -1);
+    PolkitSubject *subject = polkit_unix_process_new_for_owner(cred.pid, -1, cred.uid);
     if (subject) {
       GError *error_local = NULL;
 
-- 
2.6.2

diff --git a/Documents/brltty.conf.in b/Documents/brltty.conf.in
index 34ef415..05e37c7 100644
--- a/Documents/brltty.conf.in
+++ b/Documents/brltty.conf.in
@@ -537,6 +537,7 @@
 #api-parameters Auth=keyfile:@CONFIGURATION_DIRECTORY@/@api_authkeyfile@	# Require authentication key
 #api-parameters Auth=user:joe		# Allow some local user
 #api-parameters Auth=group:brl		# Allow some local group
+#api-parameters Auth=polkit		# authenticate via polkit
 #api-parameters Host=:0			# Accept only local Unix connections
 #api-parameters Host=0.0.0.0:0		# Accept any internet connection.
 #api-parameters StackSize=65536
