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