Re: using polkit

Nikos Mavrogiannopoulos <[email protected]>
Newsgroups gmane.comp.lib.muscle
Message-ID <[email protected]>
On Mon, 2014-01-06 at 10:57 +0100, Nikos Mavrogiannopoulos wrote:

> I've also made the polkit support optional (--with-polkit needs to be
> explicitly specified), so someone enabling it will be most probably
> installing his own policies. I could add some README file that explains
> few things with polkit. Let me know for that.

This patch adds documentation (README.polkit) and installs the default
polkit policy to the appropriate location as well as other small
changes.

regards,
Nikos

_______________________________________________
Muscle mailing list
[email protected]
http://lists.musclecard.com/mailman/listinfo/muscle_lists.musclecard.com
0001-Use-polkit-to-authorize-incoming-winscard-sessions.patch (text/x-patch, 13.9 KB)
From 821072efbedf010e22d349d9b17d1544e5b98c4c Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue, 17 Dec 2013 11:44:02 +0100
Subject: [PATCH] Use polkit to authorize incoming winscard sessions.

This patch adds the configure option --with-polkit that when
specified access to smart cards is only allowed if the polkit daemon
authorizes it.
---
 configure.ac                    |  23 +++++++
 doc/Makefile.am                 |   8 ++-
 doc/README.polkit               |  39 +++++++++++
 doc/org.debian.pcsc-lite.policy |  30 ++++++++
 src/Makefile.am                 |   6 +-
 src/auth.c                      | 148 ++++++++++++++++++++++++++++++++++++++++
 src/auth.h                      |  35 ++++++++++
 src/winscard_svc.c              |  18 +++++
 8 files changed, 304 insertions(+), 3 deletions(-)
 create mode 100644 doc/README.polkit
 create mode 100644 doc/org.debian.pcsc-lite.policy
 create mode 100644 src/auth.c
 create mode 100644 src/auth.h

diff --git a/configure.ac b/configure.ac
index 7410f74..d7c9b7c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -280,6 +280,27 @@ if test x$use_libusb = xyes; then
   PCSCLITE_FEATURES="${PCSCLITE_FEATURES} libusb"
 fi
 
+POLKIT_MINIMUM=0.111
+AC_ARG_WITH(polkit,
+	AS_HELP_STRING([--with-polkit],
+		[Build without polkit support]),
+		use_polkit=$withval, use_polkit=no)
+if test "$use_polkit" != "no"; then
+	PKG_CHECK_MODULES(POLKIT, [polkit-gobject-1 >= $POLKIT_MINIMUM], [use_polkit=yes], [use_polkit=no])
+	if test "$use_polkit" != "no";then
+		AC_DEFINE([HAVE_POLKIT], 1, [Build polkit access control support])
+		polkit_policy_dir=$($PKG_CONFIG polkit-gobject-1 --variable=policydir)
+		AC_SUBST(POLICY_DIR, [$polkit_policy_dir])
+	else
+	        use_polkit=no
+	        AC_MSG_WARN([[
+*** 
+*** polkit >= $POLKIT_MINIMUM was not found. Access control will be disabled.
+*** You may get it from http://www.freedesktop.org/software/polkit/
+*** ]])
+	fi
+fi
+
 # --with-systemdsystemunitdir=DIR
 AC_ARG_WITH([systemdsystemunitdir],
   AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
@@ -389,6 +410,8 @@ PTHREAD_LIBS:        ${PTHREAD_LIBS}
 PCSC_ARCH:           ${PCSC_ARCH}
 
 pcscd binary            ${PCSCD_BINARY}
+polkit support:		${use_polkit}
+polkit policy dir:	${polkit_policy_dir}
 libudev support:        ${use_libudev}
 libusb support:         ${use_libusb}
 USB drop directory:     ${usbdropdir}
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 8c72357..4f4fe9c 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -3,13 +3,17 @@
 SUBDIRS = . example
 
 doc_DATA = \
-	README.DAEMON
+	README.DAEMON README.polkit
 
 man_MANS = pcscd.8 reader.conf.5 
 man_in = pcscd.8.in reader.conf.5.in
 
-EXTRA_DIST = $(doc_DATA) $(man_in) doxygen.conf.in formaticc.1
+EXTRA_DIST = $(doc_DATA) $(man_in) doxygen.conf.in formaticc.1 \
+	org.debian.pcsc-lite.policy
 
 doxygen:
 	rm -fr api ; cd .. ; doxygen doc/doxygen.conf
 #	cp doxygen.css api/
+
+install-data-local:
+	$(INSTALL_DATA) org.debian.pcsc-lite.policy $(POLICY_DIR)
diff --git a/doc/README.polkit b/doc/README.polkit
new file mode 100644
index 0000000..ecbee1c
--- /dev/null
+++ b/doc/README.polkit
@@ -0,0 +1,39 @@
+When pcsc-lite is compiled using the --with-polkit option then
+polkit will be used to control access to the pcsc-lite daemon.
+
+That allows more fine grained access control to smart cards that
+is tied to the system processes rather than solely depending on
+the smart card controls (e.g., only console users can access the 
+card and so on). 
+
+Polkit is documented at:
+http://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html
+
+A default polkit policy is shipped with pcsc-lite in org.debian.pcsc-lite.policy.
+The policy file allows restricting access to the daemon as well as 
+access to smart cards.
+
+Polkit allows for additional rules, e.g., restricting access to
+particular smart cards. The rules are javascript files placed
+in /usr/share/polkit-1/rules.d/. To make specific smart card 
+reader accessible by the web server (run as www-data user) you 
+may use the following rules:
+
+polkit.addRule(function(action, subject) {
+    if (action.id == "org.debian.pcsc-lite.access_card" &&
+        action.lookup("reader") == 'name of reader' &&
+        subject.user == "www-data") {
+            return polkit.Result.YES;
+    }
+});
+
+polkit.addRule(function(action, subject) {
+    if (action.id == "org.debian.pcsc-lite.access_pcsc" &&
+        subject.user == "www-data") {
+            return polkit.Result.YES;
+    }
+});
+
+
+Note that the name of the reader can be obtained using "opensc-tool -l".
+
diff --git a/doc/org.debian.pcsc-lite.policy b/doc/org.debian.pcsc-lite.policy
new file mode 100644
index 0000000..cbae505
--- /dev/null
+++ b/doc/org.debian.pcsc-lite.policy
@@ -0,0 +1,30 @@
+<?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 PCSC-lite Project</vendor>
+  <vendor_url>http://pcsclite.alioth.debian.org/</vendor_url>
+<!--  <icon_name>smart-card</icon_name> -->
+
+  <action id="org.debian.pcsc-lite.access_pcsc">
+    <description>Access to the PC/SC daemon</description>
+    <message>Authentication is required to access the PC/SC daemon</message>
+    <defaults>
+      <allow_any>auth_admin</allow_any>
+      <allow_inactive>auth_admin</allow_inactive>
+      <allow_active>yes</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.debian.pcsc-lite.access_card">
+    <description>Access to the smart card</description>
+    <message>Authentication is required to access the smart card</message>
+    <defaults>
+      <allow_any>auth_admin</allow_any>
+      <allow_inactive>auth_admin</allow_inactive>
+      <allow_active>yes</allow_active>
+    </defaults>
+  </action>
+
+</policyconfig>
diff --git a/src/Makefile.am b/src/Makefile.am
index 7db6f70..bec502b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,6 +35,8 @@ libpcsclite_la_CFLAGS = $(CFLAGS) $(PTHREAD_CFLAGS) -DLIBPCSCLITE -DSIMCLIST_NO_
 libpcsclite_la_LIBADD = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
 
 pcscd_SOURCES = \
+	auth.c \
+	auth.h \
 	atrhandler.c \
 	atrhandler.h \
 	configfile.h \
@@ -84,12 +86,14 @@ pcscd_SOURCES = \
 	winscard_svc.c \
 	winscard_svc.h
 pcscd_CFLAGS = $(CFLAGS) $(PTHREAD_CFLAGS) $(LIBUSB_CFLAGS) $(LIBUDEV_CFLAGS) \
+	$(POLKIT_CFLAGS) \
 	-DPCSCD -DSIMCLIST_NO_DUMPRESTORE
 pcscd_LDFLAGS = $(LDFLAGS) -export-dynamic
 pcscd_LDADD = \
 	$(PTHREAD_LIBS) $(COREFOUNDATION) \
 	$(LIBUSB_LIBS) $(IOKIT) $(LIBUDEV_LIBS) \
-	$(PTHREAD_LIBS) $(PTHREAD_CFLAGS)
+	$(PTHREAD_LIBS) $(PTHREAD_CFLAGS) \
+	$(POLKIT_LIBS) 
 
 fix-rights: install-sbinPROGRAMS
 	chgrp pcscd $(DESTDIR)$(sbindir)/pcscd
diff --git a/src/auth.c b/src/auth.c
new file mode 100644
index 0000000..3e5e0d5
--- /dev/null
+++ b/src/auth.c
@@ -0,0 +1,148 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2013 Red Hat
+ *
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE.
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ */
+
+/**
+ * @file
+ * @brief polkit authorization of clients
+ *
+ * IsClientAuthorized() checks whether the connecting client is authorized
+ * to access the resources using polkit.
+ */
+
+#include "config.h"
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include "debuglog.h"
+              
+#include <errno.h>
+
+#if defined(HAVE_POLKIT) && defined(SO_PEERCRED)
+
+#include <polkit/polkit.h>
+
+/* Returns non zero when the client is authorized */
+unsigned IsClientAuthorized(int socket, const char* action, const char* reader)
+{
+	struct ucred cr;
+	socklen_t cr_len;
+	int e, ret;
+	PolkitSubject *subject;
+	PolkitAuthority *authority;
+	PolkitAuthorizationResult *result;
+	PolkitDetails *details;
+	GError *error = NULL;
+	char action_name[128];
+	
+	snprintf(action_name, sizeof(action_name), "org.debian.pcsc-lite.%s", action);
+
+	cr_len = sizeof(cr);
+	ret = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len);
+	if (ret == -1) {
+		e = errno;
+		Log2(PCSC_LOG_CRITICAL,
+		     "Error obtaining client process credentials: %s", strerror(e));
+		return 0;
+	}
+	
+	authority = polkit_authority_get_sync(NULL, NULL);
+	if (authority == NULL) {
+		Log3(PCSC_LOG_CRITICAL,
+		     "Error in %s:%d", __func__, __LINE__);
+		return 0;
+	}
+
+	subject = polkit_unix_process_new_for_owner(cr.pid, 0, cr.uid);
+	if (subject == NULL) {
+		Log3(PCSC_LOG_CRITICAL,
+		     "Error in %s:%d", __func__, __LINE__);
+		ret = 0;
+		goto cleanup1;
+	}
+
+	details = polkit_details_new();
+	if (details == NULL) {
+		Log3(PCSC_LOG_CRITICAL,
+		     "Error in %s:%d", __func__, __LINE__);
+		ret = 0;
+		goto cleanup0;
+	}
+
+	if (reader != NULL)
+		polkit_details_insert(details, "reader", reader);
+
+	result = polkit_authority_check_authorization_sync(authority, subject,
+			action_name, details,
+			POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
+			NULL,
+			&error);
+
+	if (result == NULL) {
+		Log2(PCSC_LOG_CRITICAL,
+		     "Error in authorization: %s", error->message);
+		g_error_free(error);
+		ret = 0;
+	} else {
+		if (polkit_authorization_result_get_is_authorized(result)) {
+			ret = 1;
+		} else {
+			ret = 0;
+		}
+	}
+
+	if (ret == 0) {
+		Log4(PCSC_LOG_CRITICAL,
+		     "Process %u (user: %u) is unauthorized for action: %s",
+		     	(unsigned)cr.pid, (unsigned)cr.uid, action);
+	}
+
+	g_object_unref(subject);
+cleanup0:
+	g_object_unref(details);
+cleanup1:
+	g_object_unref(authority);
+	
+	return ret;
+}
+
+#else
+
+int IsClientAuthorized(int socket, const char* action, const char* reader)
+{
+	return 1;
+}
+
+#endif
diff --git a/src/auth.h b/src/auth.h
new file mode 100644
index 0000000..c01771f
--- /dev/null
+++ b/src/auth.h
@@ -0,0 +1,35 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2013 Red Hat
+ *
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE.
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ */
+
+unsigned IsClientAuthorized(int socket, const char* action, const char* reader);
diff --git a/src/winscard_svc.c b/src/winscard_svc.c
index fcb65a4..809fba3 100644
--- a/src/winscard_svc.c
+++ b/src/winscard_svc.c
@@ -42,6 +42,7 @@
 #include "readerfactory.h"
 #include "eventhandler.h"
 #include "simclist.h"
+#include "auth.h"
 
 /**
  * @brief Represents an Application Context on the Server side.
@@ -297,6 +298,14 @@ static void ContextThread(LPVOID newContext)
 	SCONTEXT * threadContext = (SCONTEXT *) newContext;
 	int32_t filedes = threadContext->dwClientID;
 
+	if (IsClientAuthorized(filedes, "access_pcsc", NULL) == 0)
+	{
+		Log1(PCSC_LOG_CRITICAL, "Rejected unauthorized PC/SC client");
+		goto exit;
+	} else {
+		Log1(PCSC_LOG_DEBUG, "Authorized PC/SC client");
+	}
+
 	Log3(PCSC_LOG_DEBUG, "Thread is started: dwClientID=%d, threadContext @%p",
 		threadContext->dwClientID, threadContext);
 
@@ -435,6 +444,15 @@ static void ContextThread(LPVOID newContext)
 				DWORD dwActiveProtocol;
 
 				READ_BODY(coStr)
+				coStr.szReader[MAX_READERNAME-1] = 0;
+
+				if (IsClientAuthorized(filedes, "access_card", coStr.szReader) == 0)
+				{
+					Log2(PCSC_LOG_CRITICAL, "Rejected unauthorized client for '%s'", coStr.szReader);
+					goto exit;
+				} else {
+					Log2(PCSC_LOG_DEBUG, "Authorized client for '%s'", coStr.szReader);
+				}
 
 				hCard = coStr.hCard;
 				dwActiveProtocol = coStr.dwActiveProtocol;
-- 
1.8.4.2
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.