/*++ /* NAME /* user_acl 3 /* SUMMARY /* user name based access control /* SYNOPSIS /* #include /* /* 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 #include /* Utility library. */ #include #include /* Global library. */ #include #include /* 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)); }