Re: using polkit

Nikos Mavrogiannopoulos <[email protected]>
Newsgroups gmane.comp.lib.muscle
Message-ID <[email protected]>
On Tue, 2013-12-17 at 16:41 +0100, Nikos Mavrogiannopoulos wrote:
> Hello,
>  This patch adds polkit [0] support to pcscd, if the --with-polkit
> configure option is specified. That allows more fine grained access
> control to smart cards (e.g., only console users can access the card
> and so on). It is a preliminary patch and the pcscd option with
> very crude access control (allowed to access or not).  Please let me
> know of any comments.

The attached patch provides more fine-grained access control. It splits
the access control to PCSC daemon access, and smart card access. The
latter can even be restricted with a polkit ruleset to specific smart cards.

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, 12 KB)
From 85291d0e1f1249d60be198fef6c7f31ba28d01b7 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                    |  20 ++++++
 doc/Makefile.am                 |   3 +-
 doc/org.debian.pcsc-lite.policy |  30 ++++++++
 src/Makefile.am                 |   6 +-
 src/auth.c                      | 148 ++++++++++++++++++++++++++++++++++++++++
 src/auth.h                      |  35 ++++++++++
 src/winscard_svc.c              |  18 +++++
 7 files changed, 258 insertions(+), 2 deletions(-)
 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..7efe46e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -280,6 +280,25 @@ 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])
+	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 +408,7 @@ PTHREAD_LIBS:        ${PTHREAD_LIBS}
 PCSC_ARCH:           ${PCSC_ARCH}
 
 pcscd binary            ${PCSCD_BINARY}
+polkit support:		${use_polkit}
 libudev support:        ${use_libudev}
 libusb support:         ${use_libusb}
 USB drop directory:     ${usbdropdir}
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 8c72357..7c5d402 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -8,7 +8,8 @@ doc_DATA = \
 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
diff --git a/doc/org.debian.pcsc-lite.policy b/doc/org.debian.pcsc-lite.policy
new file mode 100644
index 0000000..c9d4041
--- /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>drive-removable-media</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..40a90b4
--- /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) {
+		Log3(PCSC_LOG_CRITICAL,
+		     "Process %u (user: %u) is unauthorized to access pcscd", 
+		     	(unsigned)cr.pid, (unsigned)cr.uid);
+	}
+
+	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.