1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/keytab/ktbase.c - Registration functions for keytab */
3 /*
4 * Copyright 1990,2008 by the Massachusetts Institute of Technology.
5 * All Rights Reserved.
6 *
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
11 *
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
25 */
26 /*
27 * Copyright 2007 by Secure Endpoints Inc.
28 *
29 * Permission is hereby granted, free of charge, to any person
30 * obtaining a copy of this software and associated documentation files
31 * (the "Software"), to deal in the Software without restriction,
32 * including without limitation the rights to use, copy, modify, merge,
33 * publish, distribute, sublicense, and/or sell copies of the Software,
34 * and to permit persons to whom the Software is furnished to do so,
35 * subject to the following conditions:
36 *
37 * The above copyright notice and this permission notice shall be
38 * included in all copies or substantial portions of the Software.
39 *
40 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
41 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
42 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
43 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
44 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
45 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
46 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
47 * SOFTWARE.
48 */
49
50 #include "k5-int.h"
51 #include "k5-thread.h"
52 #include "kt-int.h"
53
54 #ifndef LEAN_CLIENT
55
56 extern const krb5_kt_ops krb5_ktf_ops;
57 extern const krb5_kt_ops krb5_ktf_writable_ops;
58 extern const krb5_kt_ops krb5_mkt_ops;
59
60 struct krb5_kt_typelist {
61 const krb5_kt_ops *ops;
62 const struct krb5_kt_typelist *next;
63 };
64 const static struct krb5_kt_typelist krb5_kt_typelist_memory = {
65 &krb5_mkt_ops,
66 NULL
67 };
68 const static struct krb5_kt_typelist krb5_kt_typelist_wrfile = {
69 &krb5_ktf_writable_ops,
70 &krb5_kt_typelist_memory
71 };
72 const static struct krb5_kt_typelist krb5_kt_typelist_file = {
73 &krb5_ktf_ops,
74 &krb5_kt_typelist_wrfile
75 };
76
77 static const struct krb5_kt_typelist *kt_typehead = &krb5_kt_typelist_file;
78 /* Lock for protecting the type list. */
79 static k5_mutex_t kt_typehead_lock = K5_MUTEX_PARTIAL_INITIALIZER;
80
krb5int_kt_initialize(void)81 int krb5int_kt_initialize(void)
82 {
83 int err;
84
85 err = k5_mutex_finish_init(&kt_typehead_lock);
86 if (err)
87 goto done;
88 err = krb5int_mkt_initialize();
89 if (err)
90 goto done;
91
92 done:
93 return(err);
94 }
95
96 void
krb5int_kt_finalize(void)97 krb5int_kt_finalize(void)
98 {
99 const struct krb5_kt_typelist *t, *t_next;
100
101 k5_mutex_destroy(&kt_typehead_lock);
102 for (t = kt_typehead; t != &krb5_kt_typelist_file; t = t_next) {
103 t_next = t->next;
104 free((struct krb5_kt_typelist *)t);
105 }
106
107 krb5int_mkt_finalize();
108 }
109
110
111 /*
112 * Register a new key table type
113 * don't replace if it already exists; return an error instead.
114 */
115
116 krb5_error_code KRB5_CALLCONV
krb5_kt_register(krb5_context context,const krb5_kt_ops * ops)117 krb5_kt_register(krb5_context context, const krb5_kt_ops *ops)
118 {
119 const struct krb5_kt_typelist *t;
120 struct krb5_kt_typelist *newt;
121
122 k5_mutex_lock(&kt_typehead_lock);
123 for (t = kt_typehead; t && strcmp(t->ops->prefix,ops->prefix);t = t->next)
124 ;
125 if (t) {
126 k5_mutex_unlock(&kt_typehead_lock);
127 return KRB5_KT_TYPE_EXISTS;
128 }
129 if (!(newt = (struct krb5_kt_typelist *) malloc(sizeof(*t)))) {
130 k5_mutex_unlock(&kt_typehead_lock);
131 return ENOMEM;
132 }
133 newt->next = kt_typehead;
134 newt->ops = ops;
135 kt_typehead = newt;
136 k5_mutex_unlock(&kt_typehead_lock);
137 return 0;
138 }
139
140 /*
141 * Resolve a key table name into a keytab object.
142 *
143 * The name is currently constrained to be of the form "type:residual";
144 *
145 * The "type" portion corresponds to one of the registered key table
146 * types, while the "residual" portion is specific to the
147 * particular keytab type.
148 */
149
150 #include <ctype.h>
151 krb5_error_code KRB5_CALLCONV
krb5_kt_resolve(krb5_context context,const char * name,krb5_keytab * ktid)152 krb5_kt_resolve (krb5_context context, const char *name, krb5_keytab *ktid)
153 {
154 const struct krb5_kt_typelist *tlist;
155 char *pfx = NULL;
156 unsigned int pfxlen;
157 const char *cp, *resid;
158 krb5_error_code err = 0;
159 krb5_keytab id;
160
161 *ktid = NULL;
162
163 cp = strchr (name, ':');
164 if (!cp)
165 return (*krb5_kt_dfl_ops.resolve)(context, name, ktid);
166
167 pfxlen = cp - name;
168
169 if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) {
170 /* We found a drive letter not a prefix - use FILE */
171 pfx = strdup("FILE");
172 if (!pfx)
173 return ENOMEM;
174
175 resid = name;
176 } else if (name[0] == '/') {
177 pfx = strdup("FILE");
178 if (!pfx)
179 return ENOMEM;
180 resid = name;
181 } else {
182 resid = name + pfxlen + 1;
183 pfx = k5memdup0(name, pfxlen, &err);
184 if (pfx == NULL)
185 return err;
186 }
187
188 *ktid = (krb5_keytab) 0;
189
190 k5_mutex_lock(&kt_typehead_lock);
191 tlist = kt_typehead;
192 /* Don't need to hold the lock, since entries are never modified
193 or removed once they're in the list. Just need to protect
194 access to the list head variable itself. */
195 k5_mutex_unlock(&kt_typehead_lock);
196 for (; tlist; tlist = tlist->next) {
197 if (strcmp (tlist->ops->prefix, pfx) == 0) {
198 err = (*tlist->ops->resolve)(context, resid, &id);
199 if (!err)
200 *ktid = id;
201 goto cleanup;
202 }
203 }
204 err = KRB5_KT_UNKNOWN_TYPE;
205
206 cleanup:
207 free(pfx);
208 return err;
209 }
210
211 krb5_error_code KRB5_CALLCONV
krb5_kt_dup(krb5_context context,krb5_keytab in,krb5_keytab * out)212 krb5_kt_dup(krb5_context context, krb5_keytab in, krb5_keytab *out)
213 {
214 krb5_error_code err;
215 char name[BUFSIZ];
216
217 err = in->ops->get_name(context, in, name, sizeof(name));
218 return err ? err : krb5_kt_resolve(context, name, out);
219 }
220
221 #endif /* LEAN_CLIENT */
222