1 /* krb5/cred.c --- Kerberos 5 GSS-API credential management functions.
2 * Copyright (C) 2003-2014 Simon Josefsson
3 *
4 * This file is part of the Generic Security Service (GSS).
5 *
6 * GSS is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSS is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 * License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSS; if not, see http://www.gnu.org/licenses or write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19 * Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 /* Get specification. */
24 #include "k5internal.h"
25
26 static OM_uint32
acquire_cred1(OM_uint32 * minor_status,const gss_name_t desired_name,OM_uint32 time_req,const gss_OID_set desired_mechs,gss_cred_usage_t cred_usage,gss_cred_id_t * output_cred_handle,gss_OID_set * actual_mechs,OM_uint32 * time_rec)27 acquire_cred1 (OM_uint32 * minor_status,
28 const gss_name_t desired_name,
29 OM_uint32 time_req,
30 const gss_OID_set desired_mechs,
31 gss_cred_usage_t cred_usage,
32 gss_cred_id_t * output_cred_handle,
33 gss_OID_set * actual_mechs, OM_uint32 * time_rec)
34 {
35 gss_name_t name = desired_name;
36 _gss_krb5_cred_t k5 = (*output_cred_handle)->krb5;
37 OM_uint32 maj_stat;
38
39 if (desired_name == GSS_C_NO_NAME)
40 {
41 gss_buffer_desc buf = { 4, (char *) "host" };
42
43 maj_stat = gss_import_name (minor_status, &buf,
44 GSS_C_NT_HOSTBASED_SERVICE, &name);
45 if (GSS_ERROR (maj_stat))
46 return maj_stat;
47 }
48
49 maj_stat = gss_krb5_canonicalize_name (minor_status, name,
50 GSS_KRB5, &k5->peerptr);
51 if (GSS_ERROR (maj_stat))
52 return maj_stat;
53
54 if (k5->peerptr == GSS_C_NO_NAME)
55 {
56 maj_stat = gss_release_name (minor_status, &name);
57 if (GSS_ERROR (maj_stat))
58 return maj_stat;
59 return GSS_S_BAD_NAME;
60 }
61
62 if (shishi_init_server (&k5->sh) != SHISHI_OK)
63 return GSS_S_FAILURE;
64
65 {
66 char *p;
67
68 p = malloc (k5->peerptr->length + 1);
69 if (!p)
70 {
71 if (minor_status)
72 *minor_status = ENOMEM;
73 return GSS_S_FAILURE;
74 }
75 memcpy (p, k5->peerptr->value, k5->peerptr->length);
76 p[k5->peerptr->length] = 0;
77
78 k5->key = shishi_hostkeys_for_serverrealm (k5->sh, p, NULL);
79
80 free (p);
81 }
82
83 if (!k5->key)
84 {
85 if (minor_status)
86 *minor_status = GSS_KRB5_S_KG_KEYTAB_NOMATCH;
87 return GSS_S_NO_CRED;
88 }
89
90 if (time_rec)
91 *time_rec = GSS_C_INDEFINITE;
92
93 return GSS_S_COMPLETE;
94 }
95
96 OM_uint32
gss_krb5_acquire_cred(OM_uint32 * minor_status,const gss_name_t desired_name,OM_uint32 time_req,const gss_OID_set desired_mechs,gss_cred_usage_t cred_usage,gss_cred_id_t * output_cred_handle,gss_OID_set * actual_mechs,OM_uint32 * time_rec)97 gss_krb5_acquire_cred (OM_uint32 * minor_status,
98 const gss_name_t desired_name,
99 OM_uint32 time_req,
100 const gss_OID_set desired_mechs,
101 gss_cred_usage_t cred_usage,
102 gss_cred_id_t * output_cred_handle,
103 gss_OID_set * actual_mechs, OM_uint32 * time_rec)
104 {
105 OM_uint32 maj_stat;
106 gss_cred_id_t p = *output_cred_handle;
107
108 p->krb5 = calloc (sizeof (*p->krb5), 1);
109 if (!p->krb5)
110 {
111 if (minor_status)
112 *minor_status = ENOMEM;
113 return GSS_S_FAILURE;
114 }
115
116 if (actual_mechs)
117 {
118 maj_stat = gss_create_empty_oid_set (minor_status, actual_mechs);
119 if (GSS_ERROR (maj_stat))
120 {
121 free (p->krb5);
122 return maj_stat;
123 }
124 maj_stat = gss_add_oid_set_member (minor_status, GSS_KRB5,
125 actual_mechs);
126 if (GSS_ERROR (maj_stat))
127 {
128 free (p->krb5);
129 return maj_stat;
130 }
131 }
132
133 maj_stat = acquire_cred1 (minor_status, desired_name, time_req,
134 desired_mechs, cred_usage,
135 &p, actual_mechs, time_rec);
136 if (GSS_ERROR (maj_stat))
137 {
138 if (actual_mechs)
139 gss_release_oid_set (NULL, actual_mechs);
140 free (p->krb5);
141
142 return maj_stat;
143 }
144
145 if (minor_status)
146 *minor_status = 0;
147 return GSS_S_COMPLETE;
148 }
149
150 static OM_uint32
inquire_cred(OM_uint32 * minor_status,const gss_cred_id_t cred_handle,gss_name_t * name,OM_uint32 * lifetime,gss_cred_usage_t * cred_usage,gss_OID_set * mechanisms)151 inquire_cred (OM_uint32 * minor_status,
152 const gss_cred_id_t cred_handle,
153 gss_name_t * name,
154 OM_uint32 * lifetime,
155 gss_cred_usage_t * cred_usage, gss_OID_set * mechanisms)
156 {
157 OM_uint32 maj_stat;
158
159 if (cred_handle == GSS_C_NO_CREDENTIAL)
160 return GSS_S_NO_CRED;
161
162 if (mechanisms)
163 {
164 maj_stat = gss_create_empty_oid_set (minor_status, mechanisms);
165 if (GSS_ERROR (maj_stat))
166 return maj_stat;
167 maj_stat = gss_add_oid_set_member (minor_status, GSS_KRB5, mechanisms);
168 if (GSS_ERROR (maj_stat))
169 return maj_stat;
170 }
171
172 if (name)
173 {
174 maj_stat = gss_duplicate_name (minor_status, cred_handle->krb5->peerptr,
175 name);
176 if (GSS_ERROR (maj_stat))
177 return maj_stat;
178 }
179
180 if (cred_usage)
181 *cred_usage = GSS_C_BOTH;
182
183 if (lifetime)
184 *lifetime = GSS_C_INDEFINITE;
185
186 if (minor_status)
187 *minor_status = 0;
188 return GSS_S_COMPLETE;
189 }
190
191 OM_uint32
gss_krb5_inquire_cred(OM_uint32 * minor_status,const gss_cred_id_t cred_handle,gss_name_t * name,OM_uint32 * lifetime,gss_cred_usage_t * cred_usage,gss_OID_set * mechanisms)192 gss_krb5_inquire_cred (OM_uint32 * minor_status,
193 const gss_cred_id_t cred_handle,
194 gss_name_t * name,
195 OM_uint32 * lifetime,
196 gss_cred_usage_t * cred_usage,
197 gss_OID_set * mechanisms)
198 {
199 return inquire_cred (minor_status, cred_handle, name, lifetime,
200 cred_usage, mechanisms);
201 }
202
203 OM_uint32
gss_krb5_inquire_cred_by_mech(OM_uint32 * minor_status,const gss_cred_id_t cred_handle,const gss_OID mech_type,gss_name_t * name,OM_uint32 * initiator_lifetime,OM_uint32 * acceptor_lifetime,gss_cred_usage_t * cred_usage)204 gss_krb5_inquire_cred_by_mech (OM_uint32 * minor_status,
205 const gss_cred_id_t cred_handle,
206 const gss_OID mech_type,
207 gss_name_t * name,
208 OM_uint32 * initiator_lifetime,
209 OM_uint32 * acceptor_lifetime,
210 gss_cred_usage_t * cred_usage)
211 {
212 OM_uint32 maj_stat;
213
214 maj_stat = inquire_cred (minor_status, cred_handle, name,
215 initiator_lifetime, cred_usage, NULL);
216
217 if (acceptor_lifetime)
218 *acceptor_lifetime = *initiator_lifetime;
219
220 return maj_stat;
221 }
222
223 OM_uint32
gss_krb5_release_cred(OM_uint32 * minor_status,gss_cred_id_t * cred_handle)224 gss_krb5_release_cred (OM_uint32 * minor_status, gss_cred_id_t * cred_handle)
225 {
226 _gss_krb5_cred_t k5 = (*cred_handle)->krb5;
227
228 if (k5->peerptr != GSS_C_NO_NAME)
229 gss_release_name (NULL, &k5->peerptr);
230
231 shishi_key_done (k5->key);
232 shishi_done (k5->sh);
233 free (k5);
234
235 if (minor_status)
236 *minor_status = 0;
237 return GSS_S_COMPLETE;
238 }
239