1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6
7 /*
8 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
9 *
10 * Openvision retains the copyright to derivative works of
11 * this source code. Do *NOT* create a derivative of this
12 * source code before consulting with your legal department.
13 * Do *NOT* integrate *ANY* of this source code into another
14 * product before consulting with your legal department.
15 *
16 * For further information, read the top-level Openvision
17 * copyright which is contained in the top-level MIT Kerberos
18 * copyright.
19 *
20 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
21 *
22 */
23
24
25 /*
26 * lib/kadm/str_conv.c
27 *
28 * Copyright 1995 by the Massachusetts Institute of Technology.
29 * All Rights Reserved.
30 *
31 * Export of this software from the United States of America may
32 * require a specific license from the United States Government.
33 * It is the responsibility of any person or organization contemplating
34 * export to obtain such a license before exporting.
35 *
36 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
37 * distribute this software and its documentation for any purpose and
38 * without fee is hereby granted, provided that the above copyright
39 * notice appear in all copies and that both that copyright notice and
40 * this permission notice appear in supporting documentation, and that
41 * the name of M.I.T. not be used in advertising or publicity pertaining
42 * to distribution of the software without specific, written prior
43 * permission. Furthermore if you modify this software you must label
44 * your software as modified software and not distribute it in such a
45 * fashion that it might be confused with the original M.I.T. software.
46 * M.I.T. makes no representations about the suitability of
47 * this software for any purpose. It is provided "as is" without express
48 * or implied warranty.
49 *
50 */
51
52 /*
53 * str_conv.c - Convert between strings and Kerberos internal data.
54 */
55
56 /*
57 * Table of contents:
58 *
59 * String decoding:
60 * ----------------
61 * krb5_string_to_flags() - Convert string to krb5_flags.
62 *
63 * String encoding:
64 * ----------------
65 * krb5_flags_to_string() - Convert krb5_flags to string.
66 */
67
68 #include "k5-int.h"
69 #include "admin_internal.h"
70 #include "adm_proto.h"
71
72 /*
73 * Local data structures.
74 */
75 struct flags_lookup_entry {
76 krb5_flags fl_flags; /* Flag */
77 krb5_boolean fl_sense; /* Sense of the flag */
78 const char * fl_specifier; /* How to recognize it */
79 const char * fl_output; /* How to spit it out */
80 };
81
82 /*
83 * Local strings
84 */
85
86 static const char default_tupleseps[] = ", \t";
87 static const char default_ksaltseps[] = ":.";
88
89 /* Keytype strings */
90 /* Flags strings */
91 static const char flags_pdate_in[] = "postdateable";
92 static const char flags_fwd_in[] = "forwardable";
93 static const char flags_tgtbased_in[] = "tgt-based";
94 static const char flags_renew_in[] = "renewable";
95 static const char flags_proxy_in[] = "proxiable";
96 static const char flags_dup_skey_in[] = "dup-skey";
97 static const char flags_tickets_in[] = "allow-tickets";
98 static const char flags_preauth_in[] = "preauth";
99 static const char flags_hwauth_in[] = "hwauth";
100 static const char flags_pwchange_in[] = "pwchange";
101 static const char flags_service_in[] = "service";
102 static const char flags_pwsvc_in[] = "pwservice";
103 static const char flags_md5_in[] = "md5";
104 static const char flags_pdate_out[] = "Not Postdateable";
105 static const char flags_fwd_out[] = "Not Forwardable";
106 static const char flags_tgtbased_out[] = "No TGT-based requests";
107 static const char flags_renew_out[] = "Not renewable";
108 static const char flags_proxy_out[] = "Not proxiable";
109 static const char flags_dup_skey_out[] = "No DUP_SKEY requests";
110 static const char flags_tickets_out[] = "All Tickets Disallowed";
111 static const char flags_preauth_out[] = "Preauthorization required";
112 static const char flags_hwauth_out[] = "HW Authorization required";
113 static const char flags_pwchange_out[] = "Password Change required";
114 static const char flags_service_out[] = "Service Disabled";
115 static const char flags_pwsvc_out[] = "Password Changing Service";
116 static const char flags_md5_out[] = "RSA-MD5 supported";
117 static const char flags_default_neg[] = "-";
118 static const char flags_default_sep[] = " ";
119
120 /*
121 * Lookup tables.
122 */
123
124 static const struct flags_lookup_entry flags_table[] = {
125 /* flag sense input specifier output string */
126 /*----------------------------- ------- ------------------ ------------------*/
127 { KRB5_KDB_DISALLOW_POSTDATED, 0, flags_pdate_in, flags_pdate_out },
128 { KRB5_KDB_DISALLOW_FORWARDABLE,0, flags_fwd_in, flags_fwd_out },
129 { KRB5_KDB_DISALLOW_TGT_BASED, 0, flags_tgtbased_in, flags_tgtbased_out},
130 { KRB5_KDB_DISALLOW_RENEWABLE, 0, flags_renew_in, flags_renew_out },
131 { KRB5_KDB_DISALLOW_PROXIABLE, 0, flags_proxy_in, flags_proxy_out },
132 { KRB5_KDB_DISALLOW_DUP_SKEY, 0, flags_dup_skey_in, flags_dup_skey_out},
133 { KRB5_KDB_DISALLOW_ALL_TIX, 0, flags_tickets_in, flags_tickets_out },
134 { KRB5_KDB_REQUIRES_PRE_AUTH, 1, flags_preauth_in, flags_preauth_out },
135 { KRB5_KDB_REQUIRES_HW_AUTH, 1, flags_hwauth_in, flags_hwauth_out },
136 { KRB5_KDB_REQUIRES_PWCHANGE, 1, flags_pwchange_in, flags_pwchange_out},
137 { KRB5_KDB_DISALLOW_SVR, 0, flags_service_in, flags_service_out },
138 { KRB5_KDB_PWCHANGE_SERVICE, 1, flags_pwsvc_in, flags_pwsvc_out },
139 { KRB5_KDB_SUPPORT_DESMD5, 1, flags_md5_in, flags_md5_out }
140 };
141 static const int flags_table_nents = sizeof(flags_table)/
142 sizeof(flags_table[0]);
143
144
145 krb5_error_code
krb5_string_to_flags(string,positive,negative,flagsp)146 krb5_string_to_flags(string, positive, negative, flagsp)
147 char * string;
148 const char * positive;
149 const char * negative;
150 krb5_flags * flagsp;
151 {
152 int i;
153 int found;
154 const char *neg;
155 size_t nsize, psize;
156 int cpos;
157 int sense;
158
159 found = 0;
160 /* We need to have a way to negate it. */
161 neg = (negative) ? negative : flags_default_neg;
162 nsize = strlen(neg);
163 psize = (positive) ? strlen(positive) : 0;
164
165 cpos = 0;
166 sense = 1;
167 /* First check for positive or negative sense */
168 if (!strncasecmp(neg, string, nsize)) {
169 sense = 0;
170 cpos += (int) nsize;
171 }
172 else if (psize && !strncasecmp(positive, string, psize)) {
173 cpos += (int) psize;
174 }
175
176 for (i=0; i<flags_table_nents; i++) {
177 if (!strcasecmp(&string[cpos], flags_table[i].fl_specifier)) {
178 found = 1;
179 if (sense == (int) flags_table[i].fl_sense)
180 *flagsp |= flags_table[i].fl_flags;
181 else
182 *flagsp &= ~flags_table[i].fl_flags;
183
184 break;
185 }
186 }
187 return((found) ? 0 : EINVAL);
188 }
189
190 krb5_error_code
krb5_flags_to_string(flags,sep,buffer,buflen)191 krb5_flags_to_string(flags, sep, buffer, buflen)
192 krb5_flags flags;
193 const char * sep;
194 char * buffer;
195 size_t buflen;
196 {
197 int i;
198 krb5_flags pflags;
199 const char *sepstring;
200 char *op;
201 int initial;
202 krb5_error_code retval;
203
204 retval = 0;
205 op = buffer;
206 pflags = 0;
207 initial = 1;
208 sepstring = (sep) ? sep : flags_default_sep;
209 /* Blast through the table matching all we can */
210 for (i=0; i<flags_table_nents; i++) {
211 if (flags & flags_table[i].fl_flags) {
212 /* Found a match, see if it'll fit into the output buffer */
213 if ((op+strlen(flags_table[i].fl_output)+strlen(sepstring)) <
214 (buffer + buflen)) {
215 if (!initial) {
216 strcpy(op, sep);
217 op += strlen(sep);
218 }
219 initial = 0;
220 strcpy(op, flags_table[i].fl_output);
221 op += strlen(flags_table[i].fl_output);
222 }
223 else {
224 retval = ENOMEM;
225 break;
226 }
227 /* Keep track of what we matched */
228 pflags |= flags_table[i].fl_flags;
229 }
230 }
231 if (!retval) {
232 /* See if there's any leftovers */
233 if (flags & ~pflags)
234 retval = EINVAL;
235 else if (initial)
236 *buffer = '\0';
237 }
238 return(retval);
239 }
240
241 krb5_error_code
krb5_input_flag_to_string(flag,buffer,buflen)242 krb5_input_flag_to_string(flag, buffer, buflen)
243 int flag;
244 char * buffer;
245 size_t buflen;
246 {
247 if(flag < 0 || flag >= flags_table_nents) return ENOENT; /* End of list */
248 if(strlen(flags_table[flag].fl_specifier) > buflen) return ENOMEM;
249 strcpy(buffer, flags_table[flag].fl_specifier);
250 return 0;
251 }
252
253 /*
254 * krb5_keysalt_is_present() - Determine if a key/salt pair is present
255 * in a list of key/salt tuples.
256 *
257 * Salttype may be negative to indicate a search for only a enctype.
258 */
259 krb5_boolean
krb5_keysalt_is_present(ksaltlist,nksalts,enctype,salttype)260 krb5_keysalt_is_present(ksaltlist, nksalts, enctype, salttype)
261 krb5_key_salt_tuple *ksaltlist;
262 krb5_int32 nksalts;
263 krb5_enctype enctype;
264 krb5_int32 salttype;
265 {
266 krb5_boolean foundit;
267 int i;
268
269 foundit = 0;
270 if (ksaltlist) {
271 for (i=0; i<nksalts; i++) {
272 if ((ksaltlist[i].ks_enctype == enctype) &&
273 ((ksaltlist[i].ks_salttype == salttype) ||
274 (salttype < 0))) {
275 foundit = 1;
276 break;
277 }
278 }
279 }
280 return(foundit);
281 }
282
283 /*
284 * krb5_string_to_keysalts() - Convert a string representation to a list
285 * of key/salt tuples.
286 */
287 krb5_error_code
krb5_string_to_keysalts(string,tupleseps,ksaltseps,dups,ksaltp,nksaltp)288 krb5_string_to_keysalts(string, tupleseps, ksaltseps, dups, ksaltp, nksaltp)
289 char *string;
290 const char *tupleseps;
291 const char *ksaltseps;
292 krb5_boolean dups;
293 krb5_key_salt_tuple **ksaltp;
294 krb5_int32 *nksaltp;
295 {
296 krb5_error_code kret;
297 char *kp, *sp, *ep;
298 char sepchar, trailchar;
299 krb5_enctype ktype;
300 krb5_int32 stype;
301 krb5_key_salt_tuple *savep;
302 const char *tseplist;
303 const char *ksseplist;
304 const char *septmp;
305 size_t len;
306
307 kret = 0;
308 kp = string;
309 tseplist = (tupleseps) ? tupleseps : default_tupleseps;
310 ksseplist = (ksaltseps) ? ksaltseps : default_ksaltseps;
311 while (kp) {
312 /* Attempt to find a separator */
313 ep = (char *) NULL;
314 if (*tseplist) {
315 septmp = tseplist;
316 for (ep = strchr(kp, (int) *septmp);
317 *(++septmp) && !ep;
318 ep = strchr(kp, (int) *septmp));
319 }
320
321 if (ep) {
322 trailchar = *ep;
323 *ep = '\0';
324 ep++;
325 }
326 /*
327 * kp points to something (hopefully) of the form:
328 * <enctype><ksseplist><salttype>
329 * or
330 * <enctype>
331 */
332 sp = (char *) NULL;
333 /* Attempt to find a separator */
334 septmp = ksseplist;
335 for (sp = strchr(kp, (int) *septmp);
336 *(++septmp) && !sp;
337 sp = strchr(kp, (int)*septmp)); /* Solaris Kerberos */
338
339 if (sp) {
340 /* Separate enctype from salttype */
341 sepchar = *sp;
342 *sp = '\0';
343 sp++;
344 }
345 else
346 stype = -1;
347
348 /*
349 * Attempt to parse enctype and salttype. If we parse well
350 * then make sure that it specifies a unique key/salt combo
351 */
352 if (!(kret = krb5_string_to_enctype(kp, &ktype)) &&
353 (!sp || !(kret = krb5_string_to_salttype(sp, &stype))) &&
354 (dups ||
355 !krb5_keysalt_is_present(*ksaltp, *nksaltp, ktype, stype))) {
356
357 /* Squirrel away old keysalt array */
358 savep = *ksaltp;
359 len = (size_t) *nksaltp;
360
361 /* Get new keysalt array */
362 *ksaltp = (krb5_key_salt_tuple *)
363 malloc((len + 1) * sizeof(krb5_key_salt_tuple));
364 if (*ksaltp) {
365
366 /* Copy old keysalt if appropriate */
367 if (savep) {
368 memcpy(*ksaltp, savep,
369 len * sizeof(krb5_key_salt_tuple));
370 krb5_xfree(savep);
371 }
372
373 /* Save our values */
374 (*ksaltp)[(*nksaltp)].ks_enctype = ktype;
375 (*ksaltp)[(*nksaltp)].ks_salttype = stype;
376 (*nksaltp)++;
377 }
378 else {
379 *ksaltp = savep;
380 break;
381 }
382 }
383 /*
384 * Solaris Kerberos
385 * If the string did not yield a valid enctype/keysalt
386 * just ignore it and continue on. MIT kerberos stops
387 * searching when if finds an unknown string.
388 */
389 if (sp)
390 sp[-1] = sepchar;
391 if (ep)
392 ep[-1] = trailchar;
393 kp = ep;
394
395 /* Skip over extra separators - like spaces */
396 if (kp && *tseplist) {
397 septmp = tseplist;
398 while(*septmp && *kp) {
399 if(*septmp == *kp) {
400 /* Increment string - reset separator list */
401 kp++;
402 septmp = tseplist;
403 } else {
404 septmp++;
405 }
406 }
407 if (!*kp) kp = NULL;
408 }
409 } /* while kp */
410 return(kret);
411 }
412
413 /*
414 * krb5_keysalt_iterate() - Do something for each unique key/salt
415 * combination.
416 *
417 * If ignoresalt set, then salttype is ignored.
418 */
419 krb5_error_code
krb5_keysalt_iterate(ksaltlist,nksalt,ignoresalt,iterator,arg)420 krb5_keysalt_iterate(ksaltlist, nksalt, ignoresalt, iterator, arg)
421 krb5_key_salt_tuple *ksaltlist;
422 krb5_int32 nksalt;
423 krb5_boolean ignoresalt;
424 krb5_error_code (*iterator) (krb5_key_salt_tuple *, krb5_pointer);
425 krb5_pointer arg;
426 {
427 int i;
428 krb5_error_code kret;
429 krb5_key_salt_tuple scratch;
430
431 kret = 0;
432 for (i=0; i<nksalt; i++) {
433 scratch.ks_enctype = ksaltlist[i].ks_enctype;
434 scratch.ks_salttype = (ignoresalt) ? -1 : ksaltlist[i].ks_salttype;
435 if (!krb5_keysalt_is_present(ksaltlist,
436 i,
437 scratch.ks_enctype,
438 scratch.ks_salttype)) {
439 kret = (*iterator)(&scratch, arg);
440 if (kret)
441 break;
442 }
443 }
444 return(kret);
445 }
446