2 Copyright (C) 2006-2020 Ben Kibbey <bjk@luxsci.net>
4 This file is part of pwmd.
6 Pwmd is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
11 Pwmd is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/types.h>
31 #include "util-misc.h"
32 #include "util-string.h"
40 do_validate_peer (assuan_context_t ctx
, const char *section
,
41 assuan_peercred_t
*peer
)
46 struct client_s
*client
= assuan_get_pointer (ctx
);
49 return GPG_ERR_FORBIDDEN
;
52 if (client
->thd
->remote
)
53 return tls_validate_access (client
, section
);
56 rc
= assuan_get_peercred (ctx
, peer
);
60 users
= config_get_list (section
, "allowed");
63 for (char **p
= users
; !rc
&& *p
; p
++)
65 rc
= acl_check_common(client
, *p
, (*peer
)->uid
, (*peer
)->gid
,
71 else if (client
->no_access_param
)
74 return allowed
&& !rc
? 0 : rc
? rc
: GPG_ERR_FORBIDDEN
;
77 /* Test if uid is a member of group 'name'. Invert when 'not' is true. */
78 #ifdef HAVE_GETGRNAM_R
80 acl_check_group (const char *name
, uid_t uid
, gid_t gid
, int not, int *allowed
)
83 struct group gr
, *gresult
;
84 size_t len
= sysconf (_SC_GETGR_R_SIZE_MAX
);
93 return GPG_ERR_ENOMEM
;
95 err
= getgrnam_r (name
, &gr
, buf
, len
, &gresult
);
98 if (gresult
->gr_gid
== gid
)
105 for (char **t
= gresult
->gr_mem
; !rc
&& *t
; t
++)
109 struct passwd
*result
= get_pwd_struct (*t
, 0, &pw
, &tbuf
, &rc
);
111 if (!rc
&& result
&& result
->pw_uid
== uid
)
125 rc
= gpg_error_from_errno (err
);
128 return rc
? rc
: !gresult
? 0 : GPG_ERR_EACCES
;
132 acl_check_group (const char *name
, uid_t uid
, gid_t gid
, int not, int *allowed
)
134 struct group
*gresult
;
138 gresult
= getgrnam (name
);
139 if (!errno
&& gresult
&& gresult
->gr_gid
== gid
)
145 rc
= gpg_error_from_syserror ();
149 for (char **t
= gresult
->gr_mem
; !rc
&& *t
; t
++)
153 struct passwd
*result
= get_pwd_struct (*t
, 0, &pw
, &buf
, &rc
);
155 if (!rc
&& result
&& result
->pw_uid
== uid
)
170 peer_is_invoker(struct client_s
*client
)
172 struct invoking_user_s
*user
;
175 if (client
->thd
->state
== CLIENT_STATE_UNKNOWN
)
176 return GPG_ERR_EACCES
;
178 for (user
= invoking_users
; user
; user
= user
->next
)
181 if (client
->thd
->remote
)
183 if (user
->type
== INVOKING_TLS
184 && !strcmp(client
->thd
->tls
->fp
, user
->id
))
185 allowed
= user
->not ? 0 : 1;
191 if (user
->type
== INVOKING_GID
)
193 gpg_error_t rc
= acl_check_group (user
->id
,
194 client
->thd
->peer
->uid
,
195 client
->thd
->peer
->gid
,
196 user
->not, &allowed
);
200 else if (user
->type
== INVOKING_UID
&& client
->thd
->peer
->uid
== user
->uid
)
201 allowed
= user
->not ? 0 : 1;
204 return allowed
? 0 : GPG_ERR_EACCES
;
207 #ifdef HAVE_GETGRNAM_R
209 acl_check_common (struct client_s
*client
, const char *user
, uid_t uid
,
210 gid_t gid
, int *allowed
)
220 if (*user
== '-' || *user
== '!')
223 if (*user
== '+') // not implemented yet
226 if (*user
== '#') // TLS fingerprint hash
229 if (not || rw
|| tls
)
235 if (client
->thd
->remote
)
237 if (!strcasecmp (client
->thd
->tls
->fp
, user
))
248 else if (client
->thd
->remote
) // Remote client with no FP in the ACL
252 if (*user
== '@') // all users in group
253 return acl_check_group (user
+1, uid
, gid
, not, allowed
);
258 struct passwd
*pwd
= get_pwd_struct (user
, 0, &pw
, &buf
, &rc
);
260 if (!rc
&& pwd
&& pwd
->pw_uid
== uid
)
270 acl_check_common (struct client_s
*client
, const char *user
, uid_t uid
,
271 gid_t gid
, int *allowed
)
281 if (*user
== '-' || *user
== '!')
284 if (*user
== '+') // not implemented yet
287 if (*user
== '#') // TLS fingerprint hash
290 if (not || rw
|| tls
)
296 if (client
->thd
->remote
)
298 if (!strcasecmp (client
->thd
->tls
->fp
, user
))
308 if (*user
== '@') // all users in group
309 return acl_check_group (user
+1, uid
, gid
, not, allowed
);
314 struct passwd
*result
= get_pwd_struct (user
, 0, &pw
, &buf
, &rc
);
316 if (!rc
&& result
&& result
->pw_uid
== uid
)
327 validate_peer (struct client_s
*cl
)
333 return tls_validate_access (cl
, NULL
);
336 MUTEX_LOCK (&cn_mutex
);
337 pthread_cleanup_push (release_mutex_cb
, &cn_mutex
);
338 rc
= do_validate_peer (cl
->ctx
, "global", &cl
->thd
->peer
);
339 pthread_cleanup_pop (1);
340 log_write ("peer %s: uid=%i, gid=%i, pid=%i, rc=%u",
341 !rc
? _("accepted") : _("rejected"), cl
->thd
->peer
->uid
,
342 cl
->thd
->peer
->gid
, cl
->thd
->peer
->pid
, rc
);