1178825Sdfr/*
2178825Sdfr * Copyright (c) 2005, PADL Software Pty Ltd.
3178825Sdfr * All rights reserved.
4178825Sdfr *
5178825Sdfr * Redistribution and use in source and binary forms, with or without
6178825Sdfr * modification, are permitted provided that the following conditions
7178825Sdfr * are met:
8178825Sdfr *
9178825Sdfr * 1. Redistributions of source code must retain the above copyright
10178825Sdfr *    notice, this list of conditions and the following disclaimer.
11178825Sdfr *
12178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright
13178825Sdfr *    notice, this list of conditions and the following disclaimer in the
14178825Sdfr *    documentation and/or other materials provided with the distribution.
15178825Sdfr *
16178825Sdfr * 3. Neither the name of PADL Software nor the names of its contributors
17178825Sdfr *    may be used to endorse or promote products derived from this software
18178825Sdfr *    without specific prior written permission.
19178825Sdfr *
20178825Sdfr * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23178825Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30178825Sdfr * SUCH DAMAGE.
31178825Sdfr */
32178825Sdfr
33178825Sdfr#include "kcm_locl.h"
34178825Sdfr
35178825SdfrRCSID("$Id: acl.c 20472 2007-04-20 10:43:25Z lha $");
36178825Sdfr
37178825Sdfrkrb5_error_code
38178825Sdfrkcm_access(krb5_context context,
39178825Sdfr	   kcm_client *client,
40178825Sdfr	   kcm_operation opcode,
41178825Sdfr	   kcm_ccache ccache)
42178825Sdfr{
43178825Sdfr    int read_p = 0;
44178825Sdfr    int write_p = 0;
45178825Sdfr    uint16_t mask;
46178825Sdfr    krb5_error_code ret;
47178825Sdfr
48178825Sdfr    KCM_ASSERT_VALID(ccache);
49178825Sdfr
50178825Sdfr    switch (opcode) {
51178825Sdfr    case KCM_OP_INITIALIZE:
52178825Sdfr    case KCM_OP_DESTROY:
53178825Sdfr    case KCM_OP_STORE:
54178825Sdfr    case KCM_OP_REMOVE_CRED:
55178825Sdfr    case KCM_OP_SET_FLAGS:
56178825Sdfr    case KCM_OP_CHOWN:
57178825Sdfr    case KCM_OP_CHMOD:
58178825Sdfr    case KCM_OP_GET_INITIAL_TICKET:
59178825Sdfr    case KCM_OP_GET_TICKET:
60178825Sdfr	write_p = 1;
61178825Sdfr	read_p = 0;
62178825Sdfr	break;
63178825Sdfr    case KCM_OP_NOOP:
64178825Sdfr    case KCM_OP_GET_NAME:
65178825Sdfr    case KCM_OP_RESOLVE:
66178825Sdfr    case KCM_OP_GEN_NEW:
67178825Sdfr    case KCM_OP_RETRIEVE:
68178825Sdfr    case KCM_OP_GET_PRINCIPAL:
69178825Sdfr    case KCM_OP_GET_FIRST:
70178825Sdfr    case KCM_OP_GET_NEXT:
71178825Sdfr    case KCM_OP_END_GET:
72178825Sdfr    case KCM_OP_MAX:
73178825Sdfr	write_p = 0;
74178825Sdfr	read_p = 1;
75178825Sdfr	break;
76178825Sdfr    }
77178825Sdfr
78178825Sdfr    if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM) {
79178825Sdfr	/* System caches cannot be reinitialized or destroyed by users */
80178825Sdfr	if (opcode == KCM_OP_INITIALIZE ||
81178825Sdfr	    opcode == KCM_OP_DESTROY ||
82178825Sdfr	    opcode == KCM_OP_REMOVE_CRED) {
83178825Sdfr	    ret = KRB5_FCC_PERM;
84178825Sdfr	    goto out;
85178825Sdfr	}
86178825Sdfr
87178825Sdfr	/* Let root always read system caches */
88178825Sdfr	if (client->uid == 0) {
89178825Sdfr	    ret = 0;
90178825Sdfr	    goto out;
91178825Sdfr	}
92178825Sdfr    }
93178825Sdfr
94178825Sdfr    mask = 0;
95178825Sdfr
96178825Sdfr    /* Root may do whatever they like */
97178825Sdfr    if (client->uid == ccache->uid || CLIENT_IS_ROOT(client)) {
98178825Sdfr	if (read_p)
99178825Sdfr	    mask |= S_IRUSR;
100178825Sdfr	if (write_p)
101178825Sdfr	    mask |= S_IWUSR;
102178825Sdfr    } else if (client->gid == ccache->gid || CLIENT_IS_ROOT(client)) {
103178825Sdfr	if (read_p)
104178825Sdfr	    mask |= S_IRGRP;
105178825Sdfr	if (write_p)
106178825Sdfr	    mask |= S_IWGRP;
107178825Sdfr    } else {
108178825Sdfr	if (read_p)
109178825Sdfr	    mask |= S_IROTH;
110178825Sdfr	if (write_p)
111178825Sdfr	    mask |= S_IWOTH;
112178825Sdfr    }
113178825Sdfr
114178825Sdfr    ret = ((ccache->mode & mask) == mask) ? 0 : KRB5_FCC_PERM;
115178825Sdfr
116178825Sdfrout:
117178825Sdfr    if (ret) {
118178825Sdfr	kcm_log(2, "Process %d is not permitted to call %s on cache %s",
119178825Sdfr		client->pid, kcm_op2string(opcode), ccache->name);
120178825Sdfr    }
121178825Sdfr
122178825Sdfr    return ret;
123178825Sdfr}
124178825Sdfr
125178825Sdfrkrb5_error_code
126178825Sdfrkcm_chmod(krb5_context context,
127178825Sdfr	  kcm_client *client,
128178825Sdfr	  kcm_ccache ccache,
129178825Sdfr	  uint16_t mode)
130178825Sdfr{
131178825Sdfr    KCM_ASSERT_VALID(ccache);
132178825Sdfr
133178825Sdfr    /* System cache mode can only be set at startup */
134178825Sdfr    if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM)
135178825Sdfr	return KRB5_FCC_PERM;
136178825Sdfr
137178825Sdfr    if (ccache->uid != client->uid)
138178825Sdfr	return KRB5_FCC_PERM;
139178825Sdfr
140178825Sdfr    if (ccache->gid != client->gid)
141178825Sdfr	return KRB5_FCC_PERM;
142178825Sdfr
143178825Sdfr    HEIMDAL_MUTEX_lock(&ccache->mutex);
144178825Sdfr
145178825Sdfr    ccache->mode = mode;
146178825Sdfr
147178825Sdfr    HEIMDAL_MUTEX_unlock(&ccache->mutex);
148178825Sdfr
149178825Sdfr    return 0;
150178825Sdfr}
151178825Sdfr
152178825Sdfrkrb5_error_code
153178825Sdfrkcm_chown(krb5_context context,
154178825Sdfr	  kcm_client *client,
155178825Sdfr	  kcm_ccache ccache,
156178825Sdfr	  uid_t uid,
157178825Sdfr	  gid_t gid)
158178825Sdfr{
159178825Sdfr    KCM_ASSERT_VALID(ccache);
160178825Sdfr
161178825Sdfr    /* System cache owner can only be set at startup */
162178825Sdfr    if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM)
163178825Sdfr	return KRB5_FCC_PERM;
164178825Sdfr
165178825Sdfr    if (ccache->uid != client->uid)
166178825Sdfr	return KRB5_FCC_PERM;
167178825Sdfr
168178825Sdfr    if (ccache->gid != client->gid)
169178825Sdfr	return KRB5_FCC_PERM;
170178825Sdfr
171178825Sdfr    HEIMDAL_MUTEX_lock(&ccache->mutex);
172178825Sdfr
173178825Sdfr    ccache->uid = uid;
174178825Sdfr    ccache->gid = gid;
175178825Sdfr
176178825Sdfr    HEIMDAL_MUTEX_unlock(&ccache->mutex);
177178825Sdfr
178178825Sdfr    return 0;
179178825Sdfr}
180178825Sdfr
181