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