pcsc-lite  2.5.0
auth.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3  *
4  * Copyright (C) 2013 Red Hat
5  *
6  * All rights reserved.
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29  * DAMAGE.
30  *
31  * Author: Nikos Mavrogiannopoulos <nmav@redhat.com>
32  */
33 
42 #include "config.h"
43 #define _GNU_SOURCE
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <sys/ioctl.h>
47 #include <sys/un.h>
48 #include <stdio.h>
49 #include "debuglog.h"
50 #include "auth.h"
51 
52 #include <errno.h>
53 
54 #ifdef HAVE_POLKIT
55 
56 #if defined(SO_PEERCRED) || defined(LOCAL_PEERCRED)
57 
58 #include <polkit/polkit.h>
59 #include <stdbool.h>
60 
61 #ifdef __FreeBSD__
62 
63 #include <sys/ucred.h>
64 typedef struct xucred platform_cred;
65 #define CRED_PID(uc) (uc).cr_pid
66 #define CRED_UID(uc) (uc).cr_uid
67 
68 #else
69 
70 typedef struct ucred platform_cred;
71 #define CRED_PID(uc) (uc).pid
72 #define CRED_UID(uc) (uc).uid
73 
74 #endif
75 
76 extern bool disable_polkit;
77 
78 /* Returns non zero when the client is authorized */
79 unsigned IsClientAuthorized(int socket, const char* action, const char* reader)
80 {
81  platform_cred cr;
82  socklen_t cr_len;
83  int ret;
84  PolkitSubject *subject;
85  PolkitAuthority *authority;
86  PolkitAuthorizationResult *result;
87  PolkitDetails *details;
88  GError *error = NULL;
89  char action_name[128];
90 
91  if (disable_polkit)
92  return 1;
93 
94  snprintf(action_name, sizeof(action_name), "org.debian.pcsc-lite.%s", action);
95 
96  cr_len = sizeof(cr);
97 #ifdef LOCAL_PEERCRED
98  ret = getsockopt(socket, SOL_LOCAL, LOCAL_PEERCRED, &cr, &cr_len);
99 #else
100  ret = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len);
101 #endif
102  if (ret == -1)
103  {
104 #ifndef NO_LOG
105  int e = errno;
106  Log2(PCSC_LOG_CRITICAL,
107  "Error obtaining client process credentials: %s", strerror(e));
108 #endif
109  return 0;
110  }
111 
112  authority = polkit_authority_get_sync(NULL, &error);
113  if (authority == NULL)
114  {
115  Log2(PCSC_LOG_CRITICAL, "polkit_authority_get_sync failed: %s",
116  error->message);
117  g_error_free(error);
118  return 0;
119  }
120 
121  subject = polkit_unix_process_new_for_owner(CRED_PID(cr), 0, CRED_UID(cr));
122  if (subject == NULL)
123  {
124  Log1(PCSC_LOG_CRITICAL, "polkit_unix_process_new_for_owner failed");
125  ret = 0;
126  goto cleanup1;
127  }
128 
129  details = polkit_details_new();
130  if (details == NULL)
131  {
132  Log1(PCSC_LOG_CRITICAL, "polkit_details_new failed");
133  ret = 0;
134  goto cleanup0;
135  }
136 
137  if (reader != NULL)
138  polkit_details_insert(details, "reader", reader);
139 
140  result = polkit_authority_check_authorization_sync(authority, subject,
141  action_name, details,
142  POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
143  NULL,
144  &error);
145 
146  if (result == NULL)
147  {
148  Log2(PCSC_LOG_CRITICAL, "Error in authorization: %s", error->message);
149  g_error_free(error);
150  ret = 0;
151  }
152  else
153  {
154  if (polkit_authorization_result_get_is_authorized(result))
155  {
156  ret = 1;
157  }
158  else
159  {
160  ret = 0;
161  }
162  }
163 
164  if (ret == 0)
165  {
166  Log4(PCSC_LOG_CRITICAL,
167  "Process %u (user: %u) is NOT authorized for action: %s",
168  (unsigned)CRED_PID(cr), (unsigned)CRED_UID(cr), action);
169  }
170 
171  if (result)
172  g_object_unref(result);
173 
174  g_object_unref(subject);
175 cleanup0:
176  g_object_unref(details);
177 cleanup1:
178  g_object_unref(authority);
179 
180  while (g_main_context_pending(NULL))
181  g_main_context_iteration(NULL, TRUE);
182 
183  return ret;
184 }
185 
186 #else
187 
188 /* Do not enable polkit if it not yet supported on your system.
189  * Patches are welcome. */
190 #error polkit is enabled, but no socket cred implementation for this platform
191 
192 #endif
193 
194 #else
195 
196 unsigned IsClientAuthorized(int socket, const char* action, const char* reader)
197 {
198  (void)socket;
199  (void)action;
200  (void)reader;
201 
202  return 1;
203 }
204 
205 #endif
This handles debugging.