diff options
Diffstat (limited to 'src/global/user_acl.c')
-rw-r--r-- | src/global/user_acl.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/global/user_acl.c b/src/global/user_acl.c new file mode 100644 index 0000000..a79b7d5 --- /dev/null +++ b/src/global/user_acl.c @@ -0,0 +1,118 @@ +/*++ +/* NAME +/* user_acl 3 +/* SUMMARY +/* user name based access control +/* SYNOPSIS +/* #include <user_acl.h> +/* +/* const char *check_user_acl_byuid(pname, acl, uid) +/* const char *pname; +/* const char *acl; +/* uid_t uid; +/* DESCRIPTION +/* check_user_acl_byuid() converts the given uid into a user +/* name, and checks the result against a user name matchlist. +/* If the uid cannot be resolved to a user name, "unknown" +/* is used as the lookup key instead. +/* The result is NULL on success, the username upon failure. +/* The error result lives in static storage and must be saved +/* if it is to be used to across multiple check_user_acl_byuid() +/* calls. +/* +/* Arguments: +/* .IP pname +/* The parameter name of the acl. +/* .IP acl +/* Authorized user name list suitable for input to string_list_init(3). +/* .IP uid +/* The uid to be checked against the access list. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Victor Duchovni +/* Morgan Stanley +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <string.h> + +/* Utility library. */ + +#include <vstring.h> +#include <dict_static.h> + +/* Global library. */ + +#include <string_list.h> +#include <mypwd.h> + +/* Application-specific. */ + +#include "user_acl.h" + +/* check_user_acl_byuid - check user authorization */ + +const char *check_user_acl_byuid(const char *pname, const char *acl, uid_t uid) +{ + struct mypasswd *mypwd; + STRING_LIST *list; + static VSTRING *who = 0; + int matched; + const char *name; + + /* + * Optimize for the most common case. This also makes Postfix a little + * more robust in the face of local infrastructure failures. Note that we + * only need to match the "static:" substring, not the result value. + */ + if (strncmp(acl, DICT_TYPE_STATIC ":", sizeof(DICT_TYPE_STATIC)) == 0) + return (0); + + /* + * XXX: Substitute "unknown" for UIDs without username, so that + * static:anyone results in "permit" even when the uid is not found in + * the password file, and so that a pattern of !unknown can be used to + * block non-existent accounts. + * + * The alternative is to use the UID as a surrogate lookup key for + * non-existent accounts. There are several reasons why this is not a + * good idea. 1) An ACL with a numerical UID should work regardless of + * whether or not an account has a password file entry. Therefore we + * would always have search on the numerical UID whenever the username + * fails to produce a match. 2) The string-list infrastructure is not + * really suitable for mixing numerical and non-numerical user + * information, because the numerical match is done in a separate pass + * from the non-numerical match. This breaks when the ! operator is used. + * + * XXX To avoid waiting until the lookup completes (e.g., LDAP or NIS down) + * invoke mypwuid_err(), and either change the user_acl() API to + * propagate the error to the caller, or treat lookup errors as fatal. + */ + if ((mypwd = mypwuid(uid)) == 0) { + name = "unknown"; + } else { + name = mypwd->pw_name; + } + + list = string_list_init(pname, MATCH_FLAG_NONE, acl); + if ((matched = string_list_match(list, name)) == 0) { + if (!who) + who = vstring_alloc(10); + vstring_strcpy(who, name); + } + string_list_free(list); + if (mypwd) + mypwfree(mypwd); + + return (matched ? 0 : vstring_str(who)); +} |