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