Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include "krb5_locl.h"
35 :
36 : /* coverity[+alloc : arg-*3] */
37 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
38 0 : krb5_salttype_to_string (krb5_context context,
39 : krb5_enctype etype,
40 : krb5_salttype stype,
41 : char **string)
42 : {
43 0 : struct _krb5_encryption_type *e;
44 0 : struct salt_type *st;
45 :
46 0 : *string = NULL;
47 0 : e = _krb5_find_enctype (etype);
48 0 : if (e == NULL) {
49 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
50 : "encryption type %d not supported",
51 : etype);
52 0 : return KRB5_PROG_ETYPE_NOSUPP;
53 : }
54 0 : for (st = e->keytype->string_to_key; st && st->type; st++) {
55 0 : if (st->type == stype) {
56 0 : *string = strdup (st->name);
57 0 : if (*string == NULL)
58 0 : return krb5_enomem(context);
59 0 : return 0;
60 : }
61 : }
62 0 : krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
63 : "salttype %d not supported", stype);
64 0 : return HEIM_ERR_SALTTYPE_NOSUPP;
65 : }
66 :
67 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
68 0 : krb5_string_to_salttype (krb5_context context,
69 : krb5_enctype etype,
70 : const char *string,
71 : krb5_salttype *salttype)
72 : {
73 0 : struct _krb5_encryption_type *e;
74 0 : struct salt_type *st;
75 :
76 0 : e = _krb5_find_enctype (etype);
77 0 : if (e == NULL) {
78 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
79 0 : N_("encryption type %d not supported", ""),
80 : etype);
81 0 : return KRB5_PROG_ETYPE_NOSUPP;
82 : }
83 0 : for (st = e->keytype->string_to_key; st && st->type; st++) {
84 0 : if (strcasecmp (st->name, string) == 0) {
85 0 : *salttype = st->type;
86 0 : return 0;
87 : }
88 : }
89 0 : krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
90 0 : N_("salttype %s not supported", ""), string);
91 0 : return HEIM_ERR_SALTTYPE_NOSUPP;
92 : }
93 :
94 : /*
95 : * Like MIT's krb5_string_to_keysalts(), but simpler and with a context
96 : * argument.
97 : */
98 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
99 0 : krb5_string_to_keysalts2(krb5_context context, const char *string,
100 : size_t *nksaltp, krb5_key_salt_tuple **ksaltp)
101 : {
102 : /* deleted: tupleseps, ksaltseps, dups */
103 0 : krb5_key_salt_tuple *tmp = NULL;
104 0 : krb5_error_code ret = 0;
105 0 : char *copy, *token, *stype_str;
106 0 : char *lasts = NULL;
107 0 : krb5_enctype etype;
108 0 : krb5_salttype stype;
109 0 : size_t i;
110 :
111 0 : *ksaltp = NULL;
112 0 : *nksaltp = 0;
113 0 : if ((copy = strdup(string)) == NULL)
114 0 : return krb5_enomem(context);
115 0 : for (token = strtok_r(copy, ", \t", &lasts), ret = 0;
116 0 : token != NULL;
117 0 : token = strtok_r(NULL, ", \t", &lasts)) {
118 0 : if ((stype_str = strchr(token, ':')) != NULL)
119 0 : *(stype_str++) = '\0';
120 0 : if ((ret = krb5_string_to_enctype(context, token, &etype)))
121 0 : continue;
122 0 : if (stype_str == NULL)
123 0 : stype = KRB5_PW_SALT;
124 0 : else if ((ret = krb5_string_to_salttype(context, etype, stype_str, &stype)))
125 0 : continue;
126 0 : for (i = 0; i < *nksaltp; i++) {
127 0 : if ((*ksaltp)[i].ks_enctype == etype &&
128 0 : (*ksaltp)[i].ks_salttype == stype)
129 0 : goto skip;
130 : }
131 0 : tmp = realloc(*ksaltp, ((*nksaltp) + 1) * sizeof(**ksaltp));
132 0 : if (tmp == NULL) {
133 0 : ret = krb5_enomem(context);
134 0 : break;
135 : }
136 0 : *ksaltp = tmp;
137 0 : (*ksaltp)[*nksaltp].ks_enctype = etype;
138 0 : (*ksaltp)[*nksaltp].ks_salttype = stype;
139 0 : (*nksaltp)++;
140 0 : skip:
141 0 : (void)1;
142 : }
143 0 : free(copy);
144 0 : if (ret == ENOMEM) {
145 0 : free(*ksaltp);
146 0 : *nksaltp = 0;
147 0 : *ksaltp = NULL;
148 0 : } else if (*nksaltp) {
149 0 : return 0;
150 0 : } else if (ret == 0) {
151 0 : return KRB5_PROG_ETYPE_NOSUPP;
152 : }
153 0 : return ret;
154 : }
155 :
156 :
157 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
158 46185 : krb5_get_pw_salt(krb5_context context,
159 : krb5_const_principal principal,
160 : krb5_salt *salt)
161 : {
162 839 : size_t len;
163 839 : size_t i;
164 839 : krb5_error_code ret;
165 839 : char *p;
166 :
167 46185 : salt->salttype = KRB5_PW_SALT;
168 46185 : len = strlen(principal->realm);
169 107766 : for (i = 0; i < principal->name.name_string.len; ++i)
170 61581 : len += strlen(principal->name.name_string.val[i]);
171 46185 : ret = krb5_data_alloc (&salt->saltvalue, len);
172 46185 : if (ret)
173 0 : return ret;
174 46185 : p = salt->saltvalue.data;
175 46185 : memcpy (p, principal->realm, strlen(principal->realm));
176 46185 : p += strlen(principal->realm);
177 107766 : for (i = 0; i < principal->name.name_string.len; ++i) {
178 61581 : memcpy (p,
179 60571 : principal->name.name_string.val[i],
180 61581 : strlen(principal->name.name_string.val[i]));
181 61581 : p += strlen(principal->name.name_string.val[i]);
182 : }
183 45346 : return 0;
184 : }
185 :
186 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
187 85972 : krb5_free_salt(krb5_context context,
188 : krb5_salt salt)
189 : {
190 85972 : krb5_data_free(&salt.saltvalue);
191 85972 : return 0;
192 : }
193 :
194 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
195 0 : krb5_string_to_key_data (krb5_context context,
196 : krb5_enctype enctype,
197 : krb5_data password,
198 : krb5_const_principal principal,
199 : krb5_keyblock *key)
200 : {
201 0 : krb5_error_code ret;
202 0 : krb5_salt salt;
203 :
204 0 : ret = krb5_get_pw_salt(context, principal, &salt);
205 0 : if(ret)
206 0 : return ret;
207 0 : ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
208 0 : krb5_free_salt(context, salt);
209 0 : return ret;
210 : }
211 :
212 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
213 0 : krb5_string_to_key (krb5_context context,
214 : krb5_enctype enctype,
215 : const char *password,
216 : krb5_const_principal principal,
217 : krb5_keyblock *key)
218 : {
219 0 : krb5_data pw;
220 0 : pw.data = rk_UNCONST(password);
221 0 : pw.length = strlen(password);
222 0 : return krb5_string_to_key_data(context, enctype, pw, principal, key);
223 : }
224 :
225 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
226 59264 : krb5_string_to_key_data_salt (krb5_context context,
227 : krb5_enctype enctype,
228 : krb5_data password,
229 : krb5_salt salt,
230 : krb5_keyblock *key)
231 : {
232 482 : krb5_data opaque;
233 59264 : krb5_data_zero(&opaque);
234 59264 : return krb5_string_to_key_data_salt_opaque(context, enctype, password,
235 : salt, opaque, key);
236 : }
237 :
238 : /*
239 : * Do a string -> key for encryption type `enctype' operation on
240 : * `password' (with salt `salt' and the enctype specific data string
241 : * `opaque'), returning the resulting key in `key'
242 : */
243 :
244 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
245 87744 : krb5_string_to_key_data_salt_opaque (krb5_context context,
246 : krb5_enctype enctype,
247 : krb5_data password,
248 : krb5_salt salt,
249 : krb5_data opaque,
250 : krb5_keyblock *key)
251 : {
252 87744 : struct _krb5_encryption_type *et =_krb5_find_enctype(enctype);
253 1646 : struct salt_type *st;
254 87744 : if(et == NULL) {
255 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
256 0 : N_("encryption type %d not supported", ""),
257 : enctype);
258 0 : return KRB5_PROG_ETYPE_NOSUPP;
259 : }
260 87744 : for(st = et->keytype->string_to_key; st && st->type; st++)
261 87744 : if(st->type == salt.salttype)
262 87744 : return (*st->string_to_key)(context, enctype, password,
263 : salt, opaque, key);
264 0 : krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
265 0 : N_("salt type %d not supported", ""),
266 0 : salt.salttype);
267 0 : return HEIM_ERR_SALTTYPE_NOSUPP;
268 : }
269 :
270 : /*
271 : * Do a string -> key for encryption type `enctype' operation on the
272 : * string `password' (with salt `salt'), returning the resulting key
273 : * in `key'
274 : */
275 :
276 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
277 59264 : krb5_string_to_key_salt (krb5_context context,
278 : krb5_enctype enctype,
279 : const char *password,
280 : krb5_salt salt,
281 : krb5_keyblock *key)
282 : {
283 482 : krb5_data pw;
284 59264 : pw.data = rk_UNCONST(password);
285 59264 : pw.length = strlen(password);
286 59264 : return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
287 : }
288 :
289 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
290 0 : krb5_string_to_key_salt_opaque (krb5_context context,
291 : krb5_enctype enctype,
292 : const char *password,
293 : krb5_salt salt,
294 : krb5_data opaque,
295 : krb5_keyblock *key)
296 : {
297 0 : krb5_data pw;
298 0 : pw.data = rk_UNCONST(password);
299 0 : pw.length = strlen(password);
300 0 : return krb5_string_to_key_data_salt_opaque(context, enctype,
301 : pw, salt, opaque, key);
302 : }
303 :
304 :
305 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
306 0 : krb5_string_to_key_derived(krb5_context context,
307 : const void *str,
308 : size_t len,
309 : krb5_enctype etype,
310 : krb5_keyblock *key)
311 : {
312 0 : struct _krb5_encryption_type *et = _krb5_find_enctype(etype);
313 0 : krb5_error_code ret;
314 0 : struct _krb5_key_data kd;
315 0 : size_t keylen;
316 0 : u_char *tmp;
317 :
318 0 : if(et == NULL) {
319 0 : krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
320 0 : N_("encryption type %d not supported", ""),
321 : etype);
322 0 : return KRB5_PROG_ETYPE_NOSUPP;
323 : }
324 0 : keylen = et->keytype->bits / 8;
325 :
326 0 : ALLOC(kd.key, 1);
327 0 : if (kd.key == NULL)
328 0 : return krb5_enomem(context);
329 0 : ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
330 0 : if(ret) {
331 0 : free(kd.key);
332 0 : return ret;
333 : }
334 0 : kd.key->keytype = etype;
335 0 : tmp = malloc (keylen);
336 0 : if(tmp == NULL) {
337 0 : krb5_free_keyblock(context, kd.key);
338 0 : return krb5_enomem(context);
339 : }
340 0 : ret = _krb5_n_fold(str, len, tmp, keylen);
341 0 : if (ret) {
342 0 : free(tmp);
343 0 : krb5_enomem(context);
344 0 : return ret;
345 : }
346 0 : kd.schedule = NULL;
347 0 : _krb5_DES3_random_to_key(context, kd.key, tmp, keylen);
348 0 : memset(tmp, 0, keylen);
349 0 : free(tmp);
350 0 : ret = _krb5_derive_key(context,
351 : et,
352 : &kd,
353 : "kerberos", /* XXX well known constant */
354 : strlen("kerberos"));
355 0 : if (ret) {
356 0 : _krb5_free_key_data(context, &kd, et);
357 0 : return ret;
358 : }
359 0 : ret = krb5_copy_keyblock_contents(context, kd.key, key);
360 0 : _krb5_free_key_data(context, &kd, et);
361 0 : return ret;
362 : }
|