xref: /titanic_54/usr/src/lib/krb5/kdb/keytab.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
2*7c478bd9Sstevel@tonic-gate /*
3*7c478bd9Sstevel@tonic-gate  * kadmin/v5server/keytab.c
4*7c478bd9Sstevel@tonic-gate  *
5*7c478bd9Sstevel@tonic-gate  * Copyright 1995 by the Massachusetts Institute of Technology.
6*7c478bd9Sstevel@tonic-gate  * All Rights Reserved.
7*7c478bd9Sstevel@tonic-gate  *
8*7c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
9*7c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
10*7c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
11*7c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
12*7c478bd9Sstevel@tonic-gate  *
13*7c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14*7c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
15*7c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
16*7c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
17*7c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
18*7c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
19*7c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
20*7c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
21*7c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
22*7c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
23*7c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
24*7c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
25*7c478bd9Sstevel@tonic-gate  * or implied warranty.
26*7c478bd9Sstevel@tonic-gate  *
27*7c478bd9Sstevel@tonic-gate  */
28*7c478bd9Sstevel@tonic-gate #include <string.h>
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #include "k5-int.h"
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate static int
33*7c478bd9Sstevel@tonic-gate is_xrealm_tgt(krb5_context, krb5_const_principal);
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate krb5_error_code krb5_ktkdb_close (krb5_context, krb5_keytab);
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate krb5_error_code krb5_ktkdb_get_entry (krb5_context, krb5_keytab, krb5_const_principal,
38*7c478bd9Sstevel@tonic-gate 		   krb5_kvno, krb5_enctype, krb5_keytab_entry *);
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate krb5_error_code krb5_ktkdb_resolve(
41*7c478bd9Sstevel@tonic-gate     krb5_context  	  context,
42*7c478bd9Sstevel@tonic-gate     const char		* name,
43*7c478bd9Sstevel@tonic-gate     krb5_keytab		* id);
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate krb5_kt_ops krb5_kt_kdb_ops = {
46*7c478bd9Sstevel@tonic-gate     0,
47*7c478bd9Sstevel@tonic-gate     "KDB", 	/* Prefix -- this string should not appear anywhere else! */
48*7c478bd9Sstevel@tonic-gate     krb5_ktkdb_resolve,		/* resolve */
49*7c478bd9Sstevel@tonic-gate     NULL,			/* get_name */
50*7c478bd9Sstevel@tonic-gate     krb5_ktkdb_close,		/* close */
51*7c478bd9Sstevel@tonic-gate     krb5_ktkdb_get_entry,	/* get */
52*7c478bd9Sstevel@tonic-gate     NULL,			/* start_seq_get */
53*7c478bd9Sstevel@tonic-gate     NULL,			/* get_next */
54*7c478bd9Sstevel@tonic-gate     NULL,			/* end_get */
55*7c478bd9Sstevel@tonic-gate     NULL,			/* add (extended) */
56*7c478bd9Sstevel@tonic-gate     NULL,			/* remove (extended) */
57*7c478bd9Sstevel@tonic-gate     NULL, 		/* (void *) &krb5_ktfile_ser_entry */
58*7c478bd9Sstevel@tonic-gate };
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate typedef struct krb5_ktkdb_data {
61*7c478bd9Sstevel@tonic-gate     char * name;
62*7c478bd9Sstevel@tonic-gate } krb5_ktkdb_data;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate krb5_error_code
65*7c478bd9Sstevel@tonic-gate krb5_ktkdb_resolve(context, name, id)
66*7c478bd9Sstevel@tonic-gate     krb5_context  	  context;
67*7c478bd9Sstevel@tonic-gate     const char		* name;
68*7c478bd9Sstevel@tonic-gate     krb5_keytab		* id;
69*7c478bd9Sstevel@tonic-gate {
70*7c478bd9Sstevel@tonic-gate     if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL)
71*7c478bd9Sstevel@tonic-gate         return(ENOMEM);
72*7c478bd9Sstevel@tonic-gate     (*id)->ops = &krb5_kt_kdb_ops;
73*7c478bd9Sstevel@tonic-gate     (*id)->magic = KV5M_KEYTAB;
74*7c478bd9Sstevel@tonic-gate     return(0);
75*7c478bd9Sstevel@tonic-gate }
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate krb5_error_code
78*7c478bd9Sstevel@tonic-gate krb5_ktkdb_close(context, kt)
79*7c478bd9Sstevel@tonic-gate      krb5_context context;
80*7c478bd9Sstevel@tonic-gate      krb5_keytab kt;
81*7c478bd9Sstevel@tonic-gate {
82*7c478bd9Sstevel@tonic-gate   /*
83*7c478bd9Sstevel@tonic-gate    * This routine is responsible for freeing all memory allocated
84*7c478bd9Sstevel@tonic-gate    * for this keytab.  There are no system resources that need
85*7c478bd9Sstevel@tonic-gate    * to be freed nor are there any open files.
86*7c478bd9Sstevel@tonic-gate    *
87*7c478bd9Sstevel@tonic-gate    * This routine should undo anything done by krb5_ktkdb_resolve().
88*7c478bd9Sstevel@tonic-gate    */
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate   kt->ops = NULL;
91*7c478bd9Sstevel@tonic-gate   krb5_xfree(kt);
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate   return 0;
94*7c478bd9Sstevel@tonic-gate }
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate static krb5_context ktkdb_ctx = NULL;
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate /*
99*7c478bd9Sstevel@tonic-gate  * Set a different context for use with ktkdb_get_entry().  This is
100*7c478bd9Sstevel@tonic-gate  * primarily useful for kadmind, where the gssapi library context,
101*7c478bd9Sstevel@tonic-gate  * which will be used for the keytab, will necessarily have a
102*7c478bd9Sstevel@tonic-gate  * different context than that used by the kadm5 library to access the
103*7c478bd9Sstevel@tonic-gate  * database for its own purposes.
104*7c478bd9Sstevel@tonic-gate  */
105*7c478bd9Sstevel@tonic-gate krb5_error_code
106*7c478bd9Sstevel@tonic-gate krb5_ktkdb_set_context(krb5_context ctx)
107*7c478bd9Sstevel@tonic-gate {
108*7c478bd9Sstevel@tonic-gate     ktkdb_ctx = ctx;
109*7c478bd9Sstevel@tonic-gate     return 0;
110*7c478bd9Sstevel@tonic-gate }
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate krb5_error_code
113*7c478bd9Sstevel@tonic-gate krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry)
114*7c478bd9Sstevel@tonic-gate     krb5_context 	  in_context;
115*7c478bd9Sstevel@tonic-gate     krb5_keytab 	  id;
116*7c478bd9Sstevel@tonic-gate     krb5_const_principal  principal;
117*7c478bd9Sstevel@tonic-gate     krb5_kvno 	 	  kvno;
118*7c478bd9Sstevel@tonic-gate     krb5_enctype 	  enctype;
119*7c478bd9Sstevel@tonic-gate     krb5_keytab_entry 	* entry;
120*7c478bd9Sstevel@tonic-gate {
121*7c478bd9Sstevel@tonic-gate     krb5_context	  context;
122*7c478bd9Sstevel@tonic-gate     krb5_keyblock       * master_key;
123*7c478bd9Sstevel@tonic-gate     krb5_error_code 	  kerror = 0;
124*7c478bd9Sstevel@tonic-gate     krb5_key_data 	* key_data;
125*7c478bd9Sstevel@tonic-gate     krb5_db_entry 	  db_entry;
126*7c478bd9Sstevel@tonic-gate     krb5_boolean 	  more = 0;
127*7c478bd9Sstevel@tonic-gate     int 	 	  n = 0;
128*7c478bd9Sstevel@tonic-gate     int xrealm_tgt = is_xrealm_tgt(context, principal);
129*7c478bd9Sstevel@tonic-gate     krb5_boolean	 similar;
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate     if (ktkdb_ctx)
132*7c478bd9Sstevel@tonic-gate 	context = ktkdb_ctx;
133*7c478bd9Sstevel@tonic-gate     else
134*7c478bd9Sstevel@tonic-gate 	context = in_context;
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate     /* Open database */
137*7c478bd9Sstevel@tonic-gate     /* krb5_db_init(context); */
138*7c478bd9Sstevel@tonic-gate     if ((kerror = krb5_db_open_database(context)))
139*7c478bd9Sstevel@tonic-gate         return(kerror);
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate     /* get_principal */
142*7c478bd9Sstevel@tonic-gate     kerror = krb5_db_get_principal(context, principal, &
143*7c478bd9Sstevel@tonic-gate 				       db_entry, &n, &more);
144*7c478bd9Sstevel@tonic-gate     if (kerror) {
145*7c478bd9Sstevel@tonic-gate         krb5_db_close_database(context);
146*7c478bd9Sstevel@tonic-gate         return(kerror);
147*7c478bd9Sstevel@tonic-gate     }
148*7c478bd9Sstevel@tonic-gate     if (n != 1) {
149*7c478bd9Sstevel@tonic-gate 	krb5_db_close_database(context);
150*7c478bd9Sstevel@tonic-gate 	return KRB5_KT_NOTFOUND;
151*7c478bd9Sstevel@tonic-gate     }
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate     if (db_entry.attributes & KRB5_KDB_DISALLOW_SVR
154*7c478bd9Sstevel@tonic-gate 	|| db_entry.attributes & KRB5_KDB_DISALLOW_ALL_TIX) {
155*7c478bd9Sstevel@tonic-gate 	kerror = KRB5_KT_NOTFOUND;
156*7c478bd9Sstevel@tonic-gate 	goto error;
157*7c478bd9Sstevel@tonic-gate     }
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate     /* match key */
160*7c478bd9Sstevel@tonic-gate     kerror = krb5_db_get_mkey(context, &master_key);
161*7c478bd9Sstevel@tonic-gate     if (kerror)
162*7c478bd9Sstevel@tonic-gate 	goto error;
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate     /* For cross realm tgts, we match whatever enctype is provided;
165*7c478bd9Sstevel@tonic-gate      * for other principals, we only match the first enctype that is
166*7c478bd9Sstevel@tonic-gate      * found.  Since the TGS and AS code do the same thing, then we
167*7c478bd9Sstevel@tonic-gate      * will only successfully decrypt  tickets we have issued.*/
168*7c478bd9Sstevel@tonic-gate     kerror = krb5_dbe_find_enctype(context, &db_entry,
169*7c478bd9Sstevel@tonic-gate 				   xrealm_tgt?enctype:-1,
170*7c478bd9Sstevel@tonic-gate 				   -1, kvno, &key_data);
171*7c478bd9Sstevel@tonic-gate     if (kerror)
172*7c478bd9Sstevel@tonic-gate 	goto error;
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate     kerror = krb5_dbekd_decrypt_key_data(context, master_key,
176*7c478bd9Sstevel@tonic-gate 					 key_data, &entry->key, NULL);
177*7c478bd9Sstevel@tonic-gate     if (kerror)
178*7c478bd9Sstevel@tonic-gate 	goto error;
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate     if (enctype > 0) {
181*7c478bd9Sstevel@tonic-gate 	kerror = krb5_c_enctype_compare(context, enctype,
182*7c478bd9Sstevel@tonic-gate 					entry->key.enctype, &similar);
183*7c478bd9Sstevel@tonic-gate 	if (kerror)
184*7c478bd9Sstevel@tonic-gate 	    goto error;
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate 	if (!similar) {
187*7c478bd9Sstevel@tonic-gate 	    kerror = KRB5_KDB_NO_PERMITTED_KEY;
188*7c478bd9Sstevel@tonic-gate 	    goto error;
189*7c478bd9Sstevel@tonic-gate 	}
190*7c478bd9Sstevel@tonic-gate     }
191*7c478bd9Sstevel@tonic-gate     /*
192*7c478bd9Sstevel@tonic-gate      * Coerce the enctype of the output keyblock in case we got an
193*7c478bd9Sstevel@tonic-gate      * inexact match on the enctype.
194*7c478bd9Sstevel@tonic-gate      */
195*7c478bd9Sstevel@tonic-gate     entry->key.enctype = enctype;
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate     kerror = krb5_copy_principal(context, principal, &entry->principal);
198*7c478bd9Sstevel@tonic-gate     if (kerror)
199*7c478bd9Sstevel@tonic-gate 	goto error;
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate     /* Close database */
202*7c478bd9Sstevel@tonic-gate   error:
203*7c478bd9Sstevel@tonic-gate     krb5_dbe_free_contents(context, &db_entry);
204*7c478bd9Sstevel@tonic-gate     krb5_db_close_database(context);
205*7c478bd9Sstevel@tonic-gate     return(kerror);
206*7c478bd9Sstevel@tonic-gate }
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate /*
209*7c478bd9Sstevel@tonic-gate  * is_xrealm_tgt: Returns true if the principal is a cross-realm  TGT
210*7c478bd9Sstevel@tonic-gate  * principal-- a principal with first component  krbtgt and second
211*7c478bd9Sstevel@tonic-gate  * component not equal to realm.
212*7c478bd9Sstevel@tonic-gate  */
213*7c478bd9Sstevel@tonic-gate static int
214*7c478bd9Sstevel@tonic-gate is_xrealm_tgt(krb5_context context, krb5_const_principal princ)
215*7c478bd9Sstevel@tonic-gate {
216*7c478bd9Sstevel@tonic-gate     krb5_data *dat;
217*7c478bd9Sstevel@tonic-gate     if (krb5_princ_size(context, princ) != 2)
218*7c478bd9Sstevel@tonic-gate 	return 0;
219*7c478bd9Sstevel@tonic-gate     dat = krb5_princ_component(context, princ, 0);
220*7c478bd9Sstevel@tonic-gate     if (strncmp("krbtgt", dat->data, dat->length) != 0)
221*7c478bd9Sstevel@tonic-gate 	return 0;
222*7c478bd9Sstevel@tonic-gate     dat = krb5_princ_component(context, princ, 1);
223*7c478bd9Sstevel@tonic-gate     if (dat->length != princ->realm.length)
224*7c478bd9Sstevel@tonic-gate 	return 1;
225*7c478bd9Sstevel@tonic-gate     if (strncmp(dat->data, princ->realm.data, dat->length) == 0)
226*7c478bd9Sstevel@tonic-gate 	return 0;
227*7c478bd9Sstevel@tonic-gate     return 1;
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate }
230*7c478bd9Sstevel@tonic-gate 
231