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