Line data Source code
1 : /*
2 : * Copyright (c) 2021, PADL Software Pty Ltd.
3 : * All rights reserved.
4 : *
5 : * Redistribution and use in source and binary forms, with or without
6 : * modification, are permitted provided that the following conditions
7 : * are met:
8 : *
9 : * 1. Redistributions of source code must retain the above copyright
10 : * notice, this list of conditions and the following disclaimer.
11 : *
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : *
16 : * 3. Neither the name of PADL Software nor the names of its contributors
17 : * may be used to endorse or promote products derived from this software
18 : * without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 : * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 : * SUCH DAMAGE.
31 : */
32 :
33 : #include <krb5_locl.h>
34 : #include <mech_locl.h>
35 : #include <heimntlm.h>
36 :
37 : #include "gss-preauth-protos.h"
38 : #include "gss-preauth-private.h"
39 :
40 : krb5_error_code
41 0 : _krb5_gss_map_error(OM_uint32 major, OM_uint32 minor)
42 : {
43 0 : krb5_error_code ret;
44 :
45 0 : if (minor != 0)
46 0 : return (krb5_error_code)minor;
47 :
48 0 : switch (major) {
49 0 : case GSS_S_COMPLETE:
50 0 : ret = 0;
51 0 : break;
52 0 : case GSS_S_CONTINUE_NEEDED:
53 0 : ret = HEIM_ERR_PA_CONTINUE_NEEDED;
54 0 : break;
55 0 : case GSS_S_BAD_NAME:
56 : case GSS_S_BAD_NAMETYPE:
57 0 : ret = KRB5_PRINC_NOMATCH;
58 0 : break;
59 0 : case GSS_S_NO_CRED:
60 0 : ret = KRB5_CC_NOTFOUND;
61 0 : break;
62 0 : case GSS_S_BAD_MIC:
63 : case GSS_S_DEFECTIVE_CREDENTIAL:
64 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
65 0 : break;
66 0 : case GSS_S_FAILURE:
67 : default:
68 0 : ret = KRB5KDC_ERR_PREAUTH_FAILED;
69 0 : break;
70 : }
71 :
72 0 : return ret;
73 : }
74 :
75 : krb5_error_code
76 0 : _krb5_gss_pa_derive_key(krb5_context context,
77 : gss_ctx_id_t ctx,
78 : krb5int32 nonce,
79 : krb5_enctype enctype,
80 : krb5_keyblock **keyblock)
81 : {
82 0 : krb5_error_code ret;
83 0 : u_char saltdata[12] = "KRB-GSS";
84 0 : krb5_keyblock kdkey;
85 0 : size_t keysize;
86 :
87 0 : OM_uint32 major, minor;
88 0 : gss_buffer_desc salt, dkey = GSS_C_EMPTY_BUFFER;
89 :
90 0 : *keyblock = NULL;
91 :
92 0 : ret = krb5_enctype_keysize(context, enctype, &keysize);
93 0 : if (ret)
94 0 : return ret;
95 :
96 0 : saltdata[ 8] = (nonce >> 0 ) & 0xFF;
97 0 : saltdata[ 9] = (nonce >> 8 ) & 0xFF;
98 0 : saltdata[10] = (nonce >> 16) & 0xFF;
99 0 : saltdata[11] = (nonce >> 24) & 0xFF;
100 :
101 0 : salt.value = saltdata;
102 0 : salt.length = sizeof(saltdata);
103 :
104 0 : major = gss_pseudo_random(&minor, ctx, GSS_C_PRF_KEY_FULL,
105 : &salt, keysize, &dkey);
106 0 : if (GSS_ERROR(major))
107 0 : return KRB5_PREAUTH_NO_KEY;
108 :
109 0 : kdkey.keytype = enctype;
110 0 : kdkey.keyvalue.data = dkey.value;
111 0 : kdkey.keyvalue.length = dkey.length;
112 :
113 0 : ret = krb5_copy_keyblock(context, &kdkey, keyblock);
114 :
115 0 : if (dkey.value) {
116 0 : memset_s(dkey.value, dkey.length, 0, dkey.length);
117 0 : gss_release_buffer(&minor, &dkey);
118 : }
119 :
120 0 : return ret;
121 : }
122 :
123 : krb5_error_code
124 0 : _krb5_gss_pa_unparse_name(krb5_context context,
125 : krb5_const_principal principal,
126 : gss_name_t *namep)
127 : {
128 0 : krb5_error_code ret;
129 0 : char *name = NULL;
130 :
131 0 : OM_uint32 major, minor;
132 0 : gss_buffer_desc name_buf;
133 :
134 0 : *namep = GSS_C_NO_NAME;
135 :
136 0 : if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
137 0 : if (principal->name.name_string.len != 1)
138 0 : return EINVAL;
139 :
140 0 : name = principal->name.name_string.val[0];
141 : } else {
142 0 : ret = krb5_unparse_name(context, principal, &name);
143 0 : if (ret)
144 0 : return ret;
145 : }
146 :
147 0 : name_buf.length = strlen(name);
148 0 : name_buf.value = name;
149 :
150 0 : major = gss_import_name(&minor, &name_buf,
151 : GSS_KRB5_NT_PRINCIPAL_NAME, namep);
152 0 : if (major == GSS_S_BAD_NAMETYPE) {
153 0 : gss_OID name_type = GSS_C_NO_OID;
154 0 : int flags = 0;
155 :
156 0 : if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
157 0 : name_type = GSS_C_NT_USER_NAME;
158 0 : } else if (principal->name.name_type == KRB5_NT_PRINCIPAL) {
159 0 : flags = KRB5_PRINCIPAL_UNPARSE_SHORT;
160 0 : name_type = GSS_C_NT_USER_NAME;
161 0 : } else if ((principal->name.name_type == KRB5_NT_SRV_HST ||
162 0 : principal->name.name_type == KRB5_NT_SRV_INST) &&
163 0 : principal->name.name_string.len == 2) {
164 0 : flags = KRB5_PRINCIPAL_UNPARSE_NO_REALM;
165 0 : name_type = GSS_C_NT_HOSTBASED_SERVICE;
166 : }
167 :
168 0 : if (flags) {
169 0 : krb5_xfree(name);
170 :
171 0 : ret = krb5_unparse_name_flags(context, principal, flags, &name);
172 0 : if (ret)
173 0 : return ret;
174 :
175 0 : if (gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE)) {
176 0 : char *inst = strchr(name, '/');
177 0 : if (inst)
178 0 : *inst = '@';
179 : }
180 :
181 0 : name_buf.length = strlen(name);
182 0 : name_buf.value = name;
183 : }
184 :
185 0 : if (name_type)
186 0 : major = gss_import_name(&minor, &name_buf, name_type, namep);
187 : }
188 :
189 0 : if (name != principal->name.name_string.val[0])
190 0 : krb5_xfree(name);
191 :
192 0 : return _krb5_gss_map_error(major, minor);
193 : }
194 :
195 : krb5_error_code
196 0 : _krb5_gss_pa_parse_name(krb5_context context,
197 : gss_const_name_t name,
198 : int flags,
199 : krb5_principal *principal)
200 : {
201 0 : krb5_error_code ret;
202 0 : char *displayed_name0;
203 :
204 0 : OM_uint32 major, minor;
205 0 : gss_OID name_type = GSS_C_NO_OID;
206 0 : gss_buffer_desc displayed_name = GSS_C_EMPTY_BUFFER;
207 :
208 0 : major = gss_display_name(&minor, name, &displayed_name, &name_type);
209 0 : if (GSS_ERROR(major))
210 0 : return _krb5_gss_map_error(major, minor);
211 :
212 0 : if (gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS)) {
213 0 : ret = krb5_make_principal(context, principal, KRB5_ANON_REALM,
214 : KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL);
215 0 : if (ret == 0)
216 0 : (*principal)->name.name_type = KRB5_NT_WELLKNOWN;
217 : } else {
218 0 : displayed_name0 = malloc(displayed_name.length + 1);
219 0 : if (displayed_name0 == NULL)
220 0 : return krb5_enomem(context);
221 :
222 0 : memcpy(displayed_name0, displayed_name.value, displayed_name.length);
223 0 : displayed_name0[displayed_name.length] = '\0';
224 :
225 0 : ret = krb5_parse_name_flags(context, displayed_name0, flags, principal);
226 0 : gss_release_buffer(&minor, &displayed_name);
227 0 : free(displayed_name0);
228 : }
229 :
230 0 : gss_release_buffer(&minor, &displayed_name);
231 :
232 0 : return ret;
233 : }
234 :
235 : void
236 0 : _krb5_gss_data_to_buffer(const krb5_data *data, gss_buffer_t buffer)
237 : {
238 0 : if (data) {
239 0 : buffer->length = data->length;
240 0 : buffer->value = data->data;
241 : } else {
242 0 : _mg_buffer_zero(buffer);
243 : }
244 0 : }
245 :
246 : void
247 0 : _krb5_gss_buffer_to_data(gss_const_buffer_t buffer, krb5_data *data)
248 : {
249 0 : if (buffer) {
250 0 : data->length = buffer->length;
251 0 : data->data = buffer->value;
252 : } else {
253 0 : krb5_data_zero(data);
254 : }
255 0 : }
|