1 /* $NetBSD: user_acl.c,v 1.1.1.1 2009/06/23 10:08:48 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 52 /* Global library. */ 53 54 #include <string_list.h> 55 #include <mypwd.h> 56 #include <mail_params.h> /* STATIC_ANYONE_ACL */ 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. 75 */ 76 if (strcmp(acl, STATIC_ANYONE_ACL) == 0) 77 return (0); 78 79 /* 80 * XXX: Substitute "unknown" for UIDs without username, so that 81 * static:anyone results in "permit" even when the uid is not found in 82 * the password file, and so that a pattern of !unknown can be used to 83 * block non-existent accounts. 84 * 85 * The alternative is to use the UID as a surrogate lookup key for 86 * non-existent accounts. There are several reasons why this is not a 87 * good idea. 1) An ACL with a numerical UID should work regardless of 88 * whether or not an account has a password file entry. Therefore we 89 * would always have search on the numerical UID whenever the username 90 * fails to produce a match. 2) The string-list infrastructure is not 91 * really suitable for mixing numerical and non-numerical user 92 * information, because the numerical match is done in a separate pass 93 * from the non-numerical match. This breaks when the ! operator is used. 94 */ 95 if ((mypwd = mypwuid(uid)) == 0) { 96 name = "unknown"; 97 } else { 98 name = mypwd->pw_name; 99 } 100 101 list = string_list_init(MATCH_FLAG_NONE, acl); 102 if ((matched = string_list_match(list, name)) == 0) { 103 if (!who) 104 who = vstring_alloc(10); 105 vstring_strcpy(who, name); 106 } 107 string_list_free(list); 108 if (mypwd) 109 mypwfree(mypwd); 110 111 return (matched ? 0 : vstring_str(who)); 112 } 113