Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/kcm/client.c
34859 views
1
/*
2
* Copyright (c) 2005, PADL Software Pty Ltd.
3
* All rights reserved.
4
*
5
* Portions Copyright (c) 2009 Apple Inc. All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
*
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
*
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* 3. Neither the name of PADL Software nor the names of its contributors
19
* may be used to endorse or promote products derived from this software
20
* without specific prior written permission.
21
*
22
* THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
23
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
* ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
26
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
* SUCH DAMAGE.
33
*/
34
35
#include "kcm_locl.h"
36
#include <pwd.h>
37
38
krb5_error_code
39
kcm_ccache_resolve_client(krb5_context context,
40
kcm_client *client,
41
kcm_operation opcode,
42
const char *name,
43
kcm_ccache *ccache)
44
{
45
krb5_error_code ret;
46
47
ret = kcm_ccache_resolve(context, name, ccache);
48
if (ret) {
49
kcm_log(1, "Failed to resolve cache %s: %s",
50
name, krb5_get_err_text(context, ret));
51
return ret;
52
}
53
54
ret = kcm_access(context, client, opcode, *ccache);
55
if (ret) {
56
ret = KRB5_FCC_NOFILE; /* don't disclose */
57
kcm_release_ccache(context, *ccache);
58
}
59
60
return ret;
61
}
62
63
krb5_error_code
64
kcm_ccache_destroy_client(krb5_context context,
65
kcm_client *client,
66
const char *name)
67
{
68
krb5_error_code ret;
69
kcm_ccache ccache;
70
71
ret = kcm_ccache_resolve(context, name, &ccache);
72
if (ret) {
73
kcm_log(1, "Failed to resolve cache %s: %s",
74
name, krb5_get_err_text(context, ret));
75
return ret;
76
}
77
78
ret = kcm_access(context, client, KCM_OP_DESTROY, ccache);
79
kcm_cleanup_events(context, ccache);
80
kcm_release_ccache(context, ccache);
81
if (ret)
82
return ret;
83
84
return kcm_ccache_destroy(context, name);
85
}
86
87
krb5_error_code
88
kcm_ccache_new_client(krb5_context context,
89
kcm_client *client,
90
const char *name,
91
kcm_ccache *ccache_p)
92
{
93
krb5_error_code ret;
94
kcm_ccache ccache;
95
96
/* We insist the ccache name starts with UID or UID: */
97
if (name_constraints != 0) {
98
char prefix[64];
99
size_t prefix_len;
100
int bad = 1;
101
102
snprintf(prefix, sizeof(prefix), "%ld:", (long)client->uid);
103
prefix_len = strlen(prefix);
104
105
if (strncmp(name, prefix, prefix_len) == 0)
106
bad = 0;
107
else {
108
prefix[prefix_len - 1] = '\0';
109
if (strcmp(name, prefix) == 0)
110
bad = 0;
111
}
112
113
/* Allow root to create badly-named ccaches */
114
if (bad && !CLIENT_IS_ROOT(client))
115
return KRB5_CC_BADNAME;
116
}
117
118
ret = kcm_ccache_resolve(context, name, &ccache);
119
if (ret == 0) {
120
if ((ccache->uid != client->uid ||
121
ccache->gid != client->gid) && !CLIENT_IS_ROOT(client))
122
return KRB5_FCC_PERM;
123
} else if (ret != KRB5_FCC_NOFILE && !(CLIENT_IS_ROOT(client) && ret == KRB5_FCC_PERM)) {
124
return ret;
125
}
126
127
if (ret == KRB5_FCC_NOFILE) {
128
ret = kcm_ccache_new(context, name, &ccache);
129
if (ret) {
130
kcm_log(1, "Failed to initialize cache %s: %s",
131
name, krb5_get_err_text(context, ret));
132
return ret;
133
}
134
135
/* bind to current client */
136
ccache->uid = client->uid;
137
ccache->gid = client->gid;
138
ccache->session = client->session;
139
} else {
140
ret = kcm_zero_ccache_data(context, ccache);
141
if (ret) {
142
kcm_log(1, "Failed to empty cache %s: %s",
143
name, krb5_get_err_text(context, ret));
144
kcm_release_ccache(context, ccache);
145
return ret;
146
}
147
kcm_cleanup_events(context, ccache);
148
}
149
150
ret = kcm_access(context, client, KCM_OP_INITIALIZE, ccache);
151
if (ret) {
152
kcm_release_ccache(context, ccache);
153
kcm_ccache_destroy(context, name);
154
return ret;
155
}
156
157
/*
158
* Finally, if the user is root and the cache was created under
159
* another user's name, chown the cache to that user and their
160
* default gid.
161
*/
162
if (CLIENT_IS_ROOT(client)) {
163
unsigned long uid;
164
int matches = sscanf(name,"%ld:",&uid);
165
if (matches == 0)
166
matches = sscanf(name,"%ld",&uid);
167
if (matches == 1) {
168
struct passwd *pwd = getpwuid(uid);
169
if (pwd != NULL) {
170
gid_t gid = pwd->pw_gid;
171
kcm_chown(context, client, ccache, uid, gid);
172
}
173
}
174
}
175
176
*ccache_p = ccache;
177
return 0;
178
}
179
180
181