2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
33 #include "util-misc.h"
34 #include "util-string.h"
42 do_validate_peer (assuan_context_t ctx
, const char *section
,
43 assuan_peercred_t
*peer
)
48 struct client_s
*client
= assuan_get_pointer (ctx
);
51 return GPG_ERR_FORBIDDEN
;
54 if (client
->thd
->remote
)
55 return tls_validate_access (client
, section
);
58 rc
= assuan_get_peercred (ctx
, peer
);
62 users
= config_get_list (section
, "allowed");
65 for (char **p
= users
; !rc
&& *p
; p
++)
67 rc
= acl_check_common(client
, *p
, (*peer
)->uid
, (*peer
)->gid
,
73 else if (client
->no_access_param
)
76 return allowed
&& !rc
? 0 : rc
? rc
: GPG_ERR_FORBIDDEN
;
79 /* Test if uid is a member of group 'name'. Invert when 'not' is true. */
80 #ifdef HAVE_GETGRNAM_R
82 acl_check_group (const char *name
, uid_t uid
, gid_t gid
, int not, int *allowed
)
85 struct group gr
, *gresult
;
86 size_t len
= sysconf (_SC_GETGR_R_SIZE_MAX
);
95 return GPG_ERR_ENOMEM
;
97 err
= getgrnam_r (name
, &gr
, buf
, len
, &gresult
);
100 if (gresult
->gr_gid
== gid
)
107 for (char **t
= gresult
->gr_mem
; !rc
&& *t
; t
++)
111 struct passwd
*result
= get_pwd_struct (*t
, 0, &pw
, &tbuf
, &rc
);
113 if (!rc
&& result
&& result
->pw_uid
== uid
)
127 rc
= gpg_error_from_errno (err
);
130 return rc
? rc
: !gresult
? 0 : GPG_ERR_EACCES
;
134 acl_check_group (const char *name
, uid_t uid
, gid_t gid
, int not, int *allowed
)
136 struct group
*gresult
;
140 gresult
= getgrnam (name
);
141 if (!errno
&& gresult
&& gresult
->gr_gid
== gid
)
147 rc
= gpg_error_from_syserror ();
151 for (char **t
= gresult
->gr_mem
; !rc
&& *t
; t
++)
155 struct passwd
*result
= get_pwd_struct (*t
, 0, &pw
, &buf
, &rc
);
157 if (!rc
&& result
&& result
->pw_uid
== uid
)
172 peer_is_invoker(struct client_s
*client
)
174 struct invoking_user_s
*user
;
177 if (client
->thd
->state
== CLIENT_STATE_UNKNOWN
)
178 return GPG_ERR_EACCES
;
180 for (user
= invoking_users
; user
; user
= user
->next
)
183 if (client
->thd
->remote
)
185 if (user
->type
== INVOKING_TLS
186 && !strcmp(client
->thd
->tls
->fp
, user
->id
))
187 allowed
= user
->not ? 0 : 1;
193 if (user
->type
== INVOKING_GID
)
195 gpg_error_t rc
= acl_check_group (user
->id
,
196 client
->thd
->peer
->uid
,
197 client
->thd
->peer
->gid
,
198 user
->not, &allowed
);
202 else if (user
->type
== INVOKING_UID
&& client
->thd
->peer
->uid
== user
->uid
)
203 allowed
= user
->not ? 0 : 1;
206 return allowed
? 0 : GPG_ERR_EACCES
;
209 #ifdef HAVE_GETGRNAM_R
211 acl_check_common (struct client_s
*client
, const char *user
, uid_t uid
,
212 gid_t gid
, int *allowed
)
222 if (*user
== '-' || *user
== '!')
225 if (*user
== '+') // not implemented yet
228 if (*user
== '#') // TLS fingerprint hash
231 if (not || rw
|| tls
)
237 if (client
->thd
->remote
)
239 if (!strcasecmp (client
->thd
->tls
->fp
, user
))
249 else if (client
->thd
->remote
) // Remote client with no FP in the ACL
253 if (*user
== '@') // all users in group
254 return acl_check_group (user
+1, uid
, gid
, not, allowed
);
259 struct passwd
*pwd
= get_pwd_struct (user
, 0, &pw
, &buf
, &rc
);
261 if (!rc
&& pwd
&& pwd
->pw_uid
== uid
)
271 acl_check_common (struct client_s
*client
, const char *user
, uid_t uid
,
272 gid_t gid
, int *allowed
)
282 if (*user
== '-' || *user
== '!')
285 if (*user
== '+') // not implemented yet
288 if (*user
== '#') // TLS fingerprint hash
291 if (not || rw
|| tls
)
297 if (client
->thd
->remote
)
299 if (!strcasecmp (client
->thd
->tls
->fp
, user
))
309 if (*user
== '@') // all users in group
310 return acl_check_group (user
+1, uid
, gid
, not, allowed
);
315 struct passwd
*result
= get_pwd_struct (user
, 0, &pw
, &buf
, &rc
);
317 if (!rc
&& result
&& result
->pw_uid
== uid
)
328 validate_peer (struct client_s
*cl
)
334 return tls_validate_access (cl
, NULL
);
337 MUTEX_LOCK (&cn_mutex
);
338 pthread_cleanup_push (release_mutex_cb
, &cn_mutex
);
339 rc
= do_validate_peer (cl
->ctx
, "global", &cl
->thd
->peer
);
340 pthread_cleanup_pop (1);
341 log_write ("peer %s: uid=%i, gid=%i, pid=%i, rc=%u",
342 !rc
? _("accepted") : _("rejected"), cl
->thd
->peer
->uid
,
343 cl
->thd
->peer
->gid
, cl
->thd
->peer
->pid
, rc
);