xref: /onnv-gate/usr/src/lib/krb5/kdb/kdb_default.c (revision 4960:a4746a82a247)
1*4960Swillf /*
2*4960Swillf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
3*4960Swillf  * Use is subject to license terms.
4*4960Swillf  */
5*4960Swillf 
6*4960Swillf #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*4960Swillf 
8*4960Swillf /*
9*4960Swillf  * lib/kdb/kdb_helper.c
10*4960Swillf  *
11*4960Swillf  * Copyright 1995 by the Massachusetts Institute of Technology.
12*4960Swillf  * All Rights Reserved.
13*4960Swillf  *
14*4960Swillf  * Export of this software from the United States of America may
15*4960Swillf  *   require a specific license from the United States Government.
16*4960Swillf  *   It is the responsibility of any person or organization contemplating
17*4960Swillf  *   export to obtain such a license before exporting.
18*4960Swillf  *
19*4960Swillf  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
20*4960Swillf  * distribute this software and its documentation for any purpose and
21*4960Swillf  * without fee is hereby granted, provided that the above copyright
22*4960Swillf  * notice appear in all copies and that both that copyright notice and
23*4960Swillf  * this permission notice appear in supporting documentation, and that
24*4960Swillf  * the name of M.I.T. not be used in advertising or publicity pertaining
25*4960Swillf  * to distribution of the software without specific, written prior
26*4960Swillf  * permission.  Furthermore if you modify this software you must label
27*4960Swillf  * your software as modified software and not distribute it in such a
28*4960Swillf  * fashion that it might be confused with the original M.I.T. software.
29*4960Swillf  * M.I.T. makes no representations about the suitability of
30*4960Swillf  * this software for any purpose.  It is provided "as is" without express
31*4960Swillf  * or implied warranty.
32*4960Swillf  *
33*4960Swillf  */
34*4960Swillf 
35*4960Swillf #include "k5-int.h"
36*4960Swillf #include "kdb.h"
37*4960Swillf #include <string.h>
38*4960Swillf #include <stdio.h>
39*4960Swillf #include <errno.h>
40*4960Swillf #include <libintl.h>
41*4960Swillf 
42*4960Swillf 
43*4960Swillf /*
44*4960Swillf  * Given a particular enctype and optional salttype and kvno, find the
45*4960Swillf  * most appropriate krb5_key_data entry of the database entry.
46*4960Swillf  *
47*4960Swillf  * If stype or kvno is negative, it is ignored.
48*4960Swillf  * If kvno is 0 get the key which is maxkvno for the princ and matches
49*4960Swillf  * the other attributes.
50*4960Swillf  */
51*4960Swillf krb5_error_code
krb5_dbe_def_search_enctype(kcontext,dbentp,start,ktype,stype,kvno,kdatap)52*4960Swillf krb5_dbe_def_search_enctype(kcontext, dbentp, start, ktype, stype, kvno, kdatap)
53*4960Swillf     krb5_context	kcontext;
54*4960Swillf     krb5_db_entry	*dbentp;
55*4960Swillf     krb5_int32		*start;
56*4960Swillf     krb5_int32		ktype;
57*4960Swillf     krb5_int32		stype;
58*4960Swillf     krb5_int32		kvno;
59*4960Swillf     krb5_key_data	**kdatap;
60*4960Swillf {
61*4960Swillf     int			i, idx;
62*4960Swillf     int			maxkvno;
63*4960Swillf     krb5_key_data	*datap;
64*4960Swillf     krb5_error_code	ret;
65*4960Swillf 
66*4960Swillf     ret = 0;
67*4960Swillf     if (kvno == -1 && stype == -1 && ktype == -1)
68*4960Swillf 	kvno = 0;
69*4960Swillf 
70*4960Swillf     if (kvno == 0) {
71*4960Swillf 	/* Get the max key version */
72*4960Swillf 	for (i = 0; i < dbentp->n_key_data; i++) {
73*4960Swillf 	    if (kvno < dbentp->key_data[i].key_data_kvno) {
74*4960Swillf 		kvno = dbentp->key_data[i].key_data_kvno;
75*4960Swillf 	    }
76*4960Swillf 	}
77*4960Swillf     }
78*4960Swillf 
79*4960Swillf     maxkvno = -1;
80*4960Swillf     datap = (krb5_key_data *) NULL;
81*4960Swillf     for (i = *start; i < dbentp->n_key_data; i++) {
82*4960Swillf         krb5_boolean    similar;
83*4960Swillf         krb5_int32      db_stype;
84*4960Swillf 
85*4960Swillf 	ret = 0;
86*4960Swillf 	if (dbentp->key_data[i].key_data_ver > 1) {
87*4960Swillf 	    db_stype = dbentp->key_data[i].key_data_type[1];
88*4960Swillf 	} else {
89*4960Swillf 	    db_stype = KRB5_KDB_SALTTYPE_NORMAL;
90*4960Swillf 	}
91*4960Swillf 
92*4960Swillf 	/*
93*4960Swillf 	 * Filter out non-permitted enctypes.
94*4960Swillf 	 */
95*4960Swillf 	if (!krb5_is_permitted_enctype(kcontext,
96*4960Swillf 				       dbentp->key_data[i].key_data_type[0])) {
97*4960Swillf 	    ret = KRB5_KDB_NO_PERMITTED_KEY;
98*4960Swillf 	    continue;
99*4960Swillf 	}
100*4960Swillf 
101*4960Swillf 
102*4960Swillf 	if (ktype > 0) {
103*4960Swillf 	    if ((ret = krb5_c_enctype_compare(kcontext, (krb5_enctype) ktype,
104*4960Swillf 					      dbentp->key_data[i].key_data_type[0],
105*4960Swillf 					      &similar)))
106*4960Swillf 
107*4960Swillf 		return(ret);
108*4960Swillf 	}
109*4960Swillf 
110*4960Swillf 	if (((ktype <= 0) || similar) &&
111*4960Swillf 	    ((db_stype == stype) || (stype < 0))) {
112*4960Swillf 	    if (kvno >= 0) {
113*4960Swillf 		if (kvno == dbentp->key_data[i].key_data_kvno) {
114*4960Swillf 		    datap = &dbentp->key_data[i];
115*4960Swillf 		    idx = i;
116*4960Swillf 		    maxkvno = kvno;
117*4960Swillf 		    break;
118*4960Swillf 		}
119*4960Swillf 	    } else {
120*4960Swillf 		if (dbentp->key_data[i].key_data_kvno > maxkvno) {
121*4960Swillf 		    maxkvno = dbentp->key_data[i].key_data_kvno;
122*4960Swillf 		    datap = &dbentp->key_data[i];
123*4960Swillf 		    idx = i;
124*4960Swillf 		}
125*4960Swillf 	    }
126*4960Swillf 	}
127*4960Swillf     }
128*4960Swillf     if (maxkvno < 0)
129*4960Swillf 	return ret ? ret : KRB5_KDB_NO_MATCHING_KEY;
130*4960Swillf     *kdatap = datap;
131*4960Swillf     *start = idx+1;
132*4960Swillf     return 0;
133*4960Swillf }
134*4960Swillf 
135*4960Swillf /*
136*4960Swillf  *  kdb default functions. Ideally, some other file should have this functions. For now, TBD.
137*4960Swillf  */
138*4960Swillf #ifndef min
139*4960Swillf #define min(a,b) (((a) < (b)) ? (a) : (b))
140*4960Swillf #endif
141*4960Swillf 
142*4960Swillf krb5_error_code
krb5_def_store_mkey(context,keyfile,mname,key,master_pwd)143*4960Swillf krb5_def_store_mkey(context, keyfile, mname, key, master_pwd)
144*4960Swillf     krb5_context context;
145*4960Swillf     char *keyfile;
146*4960Swillf     krb5_principal mname;
147*4960Swillf     krb5_keyblock *key;
148*4960Swillf     char *master_pwd;
149*4960Swillf {
150*4960Swillf     FILE *kf;
151*4960Swillf     krb5_error_code retval = 0;
152*4960Swillf     krb5_ui_2 enctype;
153*4960Swillf     char defkeyfile[MAXPATHLEN+1];
154*4960Swillf     krb5_data *realm = krb5_princ_realm(context, mname);
155*4960Swillf #if HAVE_UMASK
156*4960Swillf     mode_t oumask;
157*4960Swillf #endif
158*4960Swillf 
159*4960Swillf     if (!keyfile) {
160*4960Swillf 	(void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
161*4960Swillf 	(void) strncat(defkeyfile, realm->data,
162*4960Swillf 		       min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
163*4960Swillf 			   realm->length));
164*4960Swillf 	defkeyfile[sizeof(defkeyfile) - 1] = '\0';
165*4960Swillf 	keyfile = defkeyfile;
166*4960Swillf     }
167*4960Swillf 
168*4960Swillf #if HAVE_UMASK
169*4960Swillf     oumask = umask(077);
170*4960Swillf #endif
171*4960Swillf #ifdef ANSI_STDIO
172*4960Swillf     /* Solaris Kerberos: using F to deal with 256 open file limit */
173*4960Swillf     if (!(kf = fopen(keyfile, "wbF")))
174*4960Swillf #else
175*4960Swillf     if (!(kf = fopen(keyfile, "wF")))
176*4960Swillf #endif
177*4960Swillf     {
178*4960Swillf 	int e = errno;
179*4960Swillf #if HAVE_UMASK
180*4960Swillf 	(void) umask(oumask);
181*4960Swillf #endif
182*4960Swillf 	krb5_set_error_message (context, e,
183*4960Swillf 				gettext("%s accessing file '%s'"),
184*4960Swillf 				error_message (e), keyfile);
185*4960Swillf 	return e;
186*4960Swillf     }
187*4960Swillf     enctype = key->enctype;
188*4960Swillf     if ((fwrite((krb5_pointer) &enctype,
189*4960Swillf 		2, 1, kf) != 1) ||
190*4960Swillf 	(fwrite((krb5_pointer) &key->length,
191*4960Swillf 		sizeof(key->length), 1, kf) != 1) ||
192*4960Swillf 	(fwrite((krb5_pointer) key->contents,
193*4960Swillf 		sizeof(key->contents[0]), (unsigned) key->length,
194*4960Swillf 		kf) != key->length)) {
195*4960Swillf 	retval = errno;
196*4960Swillf 	(void) fclose(kf);
197*4960Swillf     }
198*4960Swillf     if (fclose(kf) == EOF)
199*4960Swillf 	retval = errno;
200*4960Swillf #if HAVE_UMASK
201*4960Swillf     (void) umask(oumask);
202*4960Swillf #endif
203*4960Swillf     return retval;
204*4960Swillf }
205*4960Swillf 
206*4960Swillf 
207*4960Swillf krb5_error_code
krb5_db_def_fetch_mkey(krb5_context context,krb5_principal mname,krb5_keyblock * key,int * kvno,char * db_args)208*4960Swillf krb5_db_def_fetch_mkey( krb5_context   context,
209*4960Swillf 			krb5_principal mname,
210*4960Swillf 			krb5_keyblock *key,
211*4960Swillf 			int           *kvno,
212*4960Swillf 			char          *db_args)
213*4960Swillf {
214*4960Swillf     krb5_error_code retval;
215*4960Swillf     krb5_ui_2 enctype;
216*4960Swillf     char defkeyfile[MAXPATHLEN+1];
217*4960Swillf     krb5_data *realm = krb5_princ_realm(context, mname);
218*4960Swillf     FILE *kf = NULL;
219*4960Swillf 
220*4960Swillf     retval = 0;
221*4960Swillf     key->magic = KV5M_KEYBLOCK;
222*4960Swillf     (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
223*4960Swillf     (void) strncat(defkeyfile, realm->data,
224*4960Swillf 		   min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
225*4960Swillf 		       realm->length));
226*4960Swillf     defkeyfile[sizeof(defkeyfile) - 1] = '\0';
227*4960Swillf 
228*4960Swillf #ifdef ANSI_STDIO
229*4960Swillf     /* Solaris Kerberos: using F to deal with 256 open file limit */
230*4960Swillf     if (!(kf = fopen((db_args) ? db_args : defkeyfile, "rbF")))
231*4960Swillf #else
232*4960Swillf     if (!(kf = fopen((db_args) ? db_args : defkeyfile, "rF")))
233*4960Swillf #endif
234*4960Swillf 	return KRB5_KDB_CANTREAD_STORED;
235*4960Swillf 
236*4960Swillf     if (fread((krb5_pointer) &enctype, 2, 1, kf) != 1) {
237*4960Swillf 	retval = KRB5_KDB_CANTREAD_STORED;
238*4960Swillf 	goto errout;
239*4960Swillf     }
240*4960Swillf 
241*4960Swillf     if (key->enctype == ENCTYPE_UNKNOWN)
242*4960Swillf 	key->enctype = enctype;
243*4960Swillf     else if (enctype != key->enctype) {
244*4960Swillf 	retval = KRB5_KDB_BADSTORED_MKEY;
245*4960Swillf 	goto errout;
246*4960Swillf     }
247*4960Swillf 
248*4960Swillf     if (fread((krb5_pointer) &key->length,
249*4960Swillf 	      sizeof(key->length), 1, kf) != 1) {
250*4960Swillf 	retval = KRB5_KDB_CANTREAD_STORED;
251*4960Swillf 	goto errout;
252*4960Swillf     }
253*4960Swillf 
254*4960Swillf     if (!key->length || ((int) key->length) < 0) {
255*4960Swillf 	retval = KRB5_KDB_BADSTORED_MKEY;
256*4960Swillf 	goto errout;
257*4960Swillf     }
258*4960Swillf 
259*4960Swillf     if (!(key->contents = (krb5_octet *)malloc(key->length))) {
260*4960Swillf 	retval = ENOMEM;
261*4960Swillf 	goto errout;
262*4960Swillf     }
263*4960Swillf 
264*4960Swillf     if (fread((krb5_pointer) key->contents,
265*4960Swillf 	      sizeof(key->contents[0]), key->length, kf)
266*4960Swillf 	!= key->length) {
267*4960Swillf 	retval = KRB5_KDB_CANTREAD_STORED;
268*4960Swillf 	memset(key->contents, 0,  key->length);
269*4960Swillf 	free(key->contents);
270*4960Swillf 	key->contents = 0;
271*4960Swillf     } else
272*4960Swillf 	retval = 0;
273*4960Swillf 
274*4960Swillf     *kvno = 0;
275*4960Swillf 
276*4960Swillf  errout:
277*4960Swillf     (void) fclose(kf);
278*4960Swillf     return retval;
279*4960Swillf 
280*4960Swillf }
281*4960Swillf 
282*4960Swillf 
283*4960Swillf krb5_error_code
krb5_def_verify_master_key(context,mprinc,mkey)284*4960Swillf krb5_def_verify_master_key(context, mprinc, mkey)
285*4960Swillf     krb5_context context;
286*4960Swillf     krb5_principal mprinc;
287*4960Swillf     krb5_keyblock *mkey;
288*4960Swillf {
289*4960Swillf     krb5_error_code retval;
290*4960Swillf     krb5_db_entry master_entry;
291*4960Swillf     int nprinc;
292*4960Swillf     krb5_boolean more;
293*4960Swillf     krb5_keyblock tempkey;
294*4960Swillf 
295*4960Swillf     nprinc = 1;
296*4960Swillf     if ((retval = krb5_db_get_principal(context, mprinc,
297*4960Swillf 					&master_entry, &nprinc, &more)))
298*4960Swillf 	return(retval);
299*4960Swillf 
300*4960Swillf     if (nprinc != 1) {
301*4960Swillf 	if (nprinc)
302*4960Swillf 	    krb5_db_free_principal(context, &master_entry, nprinc);
303*4960Swillf 	return(KRB5_KDB_NOMASTERKEY);
304*4960Swillf     } else if (more) {
305*4960Swillf 	krb5_db_free_principal(context, &master_entry, nprinc);
306*4960Swillf 	return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
307*4960Swillf     }
308*4960Swillf 
309*4960Swillf     if ((retval = krb5_dbekd_decrypt_key_data(context, mkey,
310*4960Swillf 					      &master_entry.key_data[0],
311*4960Swillf 					      &tempkey, NULL))) {
312*4960Swillf 	krb5_db_free_principal(context, &master_entry, nprinc);
313*4960Swillf 	return retval;
314*4960Swillf     }
315*4960Swillf 
316*4960Swillf     if (mkey->length != tempkey.length ||
317*4960Swillf 	memcmp((char *)mkey->contents,
318*4960Swillf 	       (char *)tempkey.contents,mkey->length)) {
319*4960Swillf 	retval = KRB5_KDB_BADMASTERKEY;
320*4960Swillf     }
321*4960Swillf 
322*4960Swillf     memset((char *)tempkey.contents, 0, tempkey.length);
323*4960Swillf     krb5_xfree(tempkey.contents);
324*4960Swillf     krb5_db_free_principal(context, &master_entry, nprinc);
325*4960Swillf 
326*4960Swillf     return retval;
327*4960Swillf }
328*4960Swillf 
329*4960Swillf 
kdb_def_set_mkey(krb5_context kcontext,char * pwd,krb5_keyblock * key)330*4960Swillf krb5_error_code kdb_def_set_mkey ( krb5_context kcontext,
331*4960Swillf 				   char *pwd,
332*4960Swillf 				   krb5_keyblock *key )
333*4960Swillf {
334*4960Swillf     /* printf("default set master key\n"); */
335*4960Swillf     return 0;
336*4960Swillf }
337*4960Swillf 
kdb_def_get_mkey(krb5_context kcontext,krb5_keyblock ** key)338*4960Swillf krb5_error_code kdb_def_get_mkey ( krb5_context kcontext,
339*4960Swillf 				   krb5_keyblock **key )
340*4960Swillf {
341*4960Swillf     /* printf("default get master key\n"); */
342*4960Swillf     return 0;
343*4960Swillf }
344*4960Swillf 
krb5_def_promote_db(krb5_context kcontext,char * s,char ** args)345*4960Swillf krb5_error_code krb5_def_promote_db (krb5_context kcontext,
346*4960Swillf 				     char *s, char **args)
347*4960Swillf {
348*4960Swillf     /* printf("default promote_db\n"); */
349*4960Swillf     return KRB5_PLUGIN_OP_NOTSUPP;
350*4960Swillf }
351