xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/user_acl.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
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