1/* $NetBSD: user_acl.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ 2 3/*++ 4/* NAME 5/* user_acl 3 6/* SUMMARY 7/* user name based access control 8/* SYNOPSIS 9/* #include <user_acl.h> 10/* 11/* const char *check_user_acl_byuid(pname, acl, uid) 12/* const char *pname; 13/* const char *acl; 14/* uid_t uid; 15/* DESCRIPTION 16/* check_user_acl_byuid() converts the given uid into a user 17/* name, and checks the result against a user name matchlist. 18/* If the uid cannot be resolved to a user name, "unknown" 19/* is used as the lookup key instead. 20/* The result is NULL on success, the username upon failure. 21/* The error result lives in static storage and must be saved 22/* if it is to be used to across multiple check_user_acl_byuid() 23/* calls. 24/* 25/* Arguments: 26/* .IP pname 27/* The parameter name of the acl. 28/* .IP acl 29/* Authorized user name list suitable for input to string_list_init(3). 30/* .IP uid 31/* The uid to be checked against the access list. 32/* LICENSE 33/* .ad 34/* .fi 35/* The Secure Mailer license must be distributed with this software. 36/* AUTHOR(S) 37/* Wietse Venema 38/* IBM T.J. Watson Research 39/* P.O. Box 704 40/* Yorktown Heights, NY 10598, USA 41/* 42/* Victor Duchovni 43/* Morgan Stanley 44/*--*/ 45 46/* System library. */ 47 48#include <sys_defs.h> 49#include <string.h> 50 51/* Utility library. */ 52 53#include <vstring.h> 54#include <dict_static.h> 55 56/* Global library. */ 57 58#include <string_list.h> 59#include <mypwd.h> 60 61/* Application-specific. */ 62 63#include "user_acl.h" 64 65/* check_user_acl_byuid - check user authorization */ 66 67const char *check_user_acl_byuid(const char *pname, const char *acl, uid_t uid) 68{ 69 struct mypasswd *mypwd; 70 STRING_LIST *list; 71 static VSTRING *who = 0; 72 int matched; 73 const char *name; 74 75 /* 76 * Optimize for the most common case. This also makes Postfix a little 77 * more robust in the face of local infrastructure failures. Note that we 78 * only need to match the "static:" substring, not the result value. 79 */ 80 if (strncmp(acl, DICT_TYPE_STATIC ":", sizeof(DICT_TYPE_STATIC)) == 0) 81 return (0); 82 83 /* 84 * XXX: Substitute "unknown" for UIDs without username, so that 85 * static:anyone results in "permit" even when the uid is not found in 86 * the password file, and so that a pattern of !unknown can be used to 87 * block non-existent accounts. 88 * 89 * The alternative is to use the UID as a surrogate lookup key for 90 * non-existent accounts. There are several reasons why this is not a 91 * good idea. 1) An ACL with a numerical UID should work regardless of 92 * whether or not an account has a password file entry. Therefore we 93 * would always have search on the numerical UID whenever the username 94 * fails to produce a match. 2) The string-list infrastructure is not 95 * really suitable for mixing numerical and non-numerical user 96 * information, because the numerical match is done in a separate pass 97 * from the non-numerical match. This breaks when the ! operator is used. 98 * 99 * XXX To avoid waiting until the lookup completes (e.g., LDAP or NIS down) 100 * invoke mypwuid_err(), and either change the user_acl() API to 101 * propagate the error to the caller, or treat lookup errors as fatal. 102 */ 103 if ((mypwd = mypwuid(uid)) == 0) { 104 name = "unknown"; 105 } else { 106 name = mypwd->pw_name; 107 } 108 109 list = string_list_init(pname, MATCH_FLAG_NONE, acl); 110 if ((matched = string_list_match(list, name)) == 0) { 111 if (!who) 112 who = vstring_alloc(10); 113 vstring_strcpy(who, name); 114 } 115 string_list_free(list); 116 if (mypwd) 117 mypwfree(mypwd); 118 119 return (matched ? 0 : vstring_str(who)); 120} 121