ktbase.c revision 781:57319a72b15f
1132458Sroberto/*
2132458Sroberto * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3276486Sngie * Use is subject to license terms.
4156813Sru */
5156813Sru
6156813Sru#pragma ident	"%Z%%M%	%I%	%E% SMI"
7285612Sdelphij
8285612Sdelphij/*
9132458Sroberto * lib/krb5/keytab/ktbase.c
10132458Sroberto *
11182008Sroberto * Copyright 1990 by the Massachusetts Institute of Technology.
12132458Sroberto * All Rights Reserved.
13285612Sdelphij *
14285612Sdelphij * Export of this software from the United States of America may
15285612Sdelphij *   require a specific license from the United States Government.
16285612Sdelphij *   It is the responsibility of any person or organization contemplating
17285612Sdelphij *   export to obtain such a license before exporting.
18285612Sdelphij *
19285612Sdelphij * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
20285612Sdelphij * distribute this software and its documentation for any purpose and
21285612Sdelphij * without fee is hereby granted, provided that the above copyright
22132458Sroberto * notice appear in all copies and that both that copyright notice and
23285612Sdelphij * this permission notice appear in supporting documentation, and that
24285612Sdelphij * the name of M.I.T. not be used in advertising or publicity pertaining
25132458Sroberto * to distribution of the software without specific, written prior
26285612Sdelphij * permission.  Furthermore if you modify this software you must label
27285612Sdelphij * your software as modified software and not distribute it in such a
28285612Sdelphij * fashion that it might be confused with the original M.I.T. software.
29285612Sdelphij * M.I.T. makes no representations about the suitability of
30285612Sdelphij * this software for any purpose.  It is provided "as is" without express
31285612Sdelphij * or implied warranty.
32132535Sroberto *
33132535Sroberto *
34132458Sroberto * Registration functions for keytab.
35 */
36
37#include <k5-int.h>
38#include <k5-thread.h>
39#include <kt-int.h>
40
41extern const krb5_kt_ops krb5_ktf_ops;
42extern const krb5_kt_ops krb5_ktf_writable_ops;
43extern const krb5_kt_ops krb5_kts_ops;
44
45struct krb5_kt_typelist {
46    const krb5_kt_ops *ops;
47    const struct krb5_kt_typelist *next;
48};
49static const struct krb5_kt_typelist krb5_kt_typelist_dfl = { &krb5_kt_dfl_ops, 0 };
50static const struct krb5_kt_typelist *kt_typehead = &krb5_kt_typelist_dfl;
51
52static const struct krb5_kt_typelist krb5_kt_typelist_wrfile  = {
53    &krb5_ktf_writable_ops,
54    0
55};
56static const struct krb5_kt_typelist krb5_kt_typelist_file  = {
57    &krb5_ktf_ops,
58    &krb5_kt_typelist_wrfile
59};
60static const struct krb5_kt_typelist krb5_kt_typelist_srvtab = {
61    &krb5_kts_ops,
62    &krb5_kt_typelist_file
63};
64
65/* SUNW14resync */
66/*
67static const struct krb5_kt_typelist *kt_typehead = &krb5_kt_typelist_srvtab;*/
68
69/* Lock for protecting the type list.  */
70static k5_mutex_t kt_typehead_lock = K5_MUTEX_PARTIAL_INITIALIZER;
71
72int krb5int_kt_initialize(void)
73{
74    return k5_mutex_finish_init(&kt_typehead_lock);
75}
76
77void
78krb5int_kt_finalize(void)
79{
80    struct krb5_kt_typelist *t, *t_next;
81    k5_mutex_destroy(&kt_typehead_lock);
82    for (t = (struct krb5_kt_typelist *)kt_typehead; t != &krb5_kt_typelist_srvtab;
83	t = t_next) {
84        t_next = (struct krb5_kt_typelist *)t->next;
85	free(t);
86    }
87}
88
89
90/*
91 * Register a new key table type
92 * don't replace if it already exists; return an error instead.
93 */
94/*ARGSUSED*/
95krb5_error_code KRB5_CALLCONV
96krb5_kt_register(krb5_context context, const krb5_kt_ops *ops)
97{
98    const struct krb5_kt_typelist *t;
99    struct krb5_kt_typelist *newt;
100    krb5_error_code err;
101
102    err = k5_mutex_lock(&kt_typehead_lock);
103    if (err)
104	return err;
105    for (t = kt_typehead; t && strcmp(t->ops->prefix,ops->prefix);t = t->next)
106	;
107    if (t) {
108	k5_mutex_unlock(&kt_typehead_lock);
109	return KRB5_KT_TYPE_EXISTS;
110    }
111    if (!(newt = (struct krb5_kt_typelist *) malloc(sizeof(*t)))) {
112	k5_mutex_unlock(&kt_typehead_lock);
113	return ENOMEM;
114    }
115    newt->next = kt_typehead;
116    newt->ops = ops;
117    kt_typehead = newt;
118    k5_mutex_unlock(&kt_typehead_lock);
119    return 0;
120}
121
122/*
123 * Resolve a key table name into a keytab object.
124 *
125 * The name is currently constrained to be of the form "type:residual";
126 *
127 * The "type" portion corresponds to one of the registered key table
128 * types, while the "residual" portion is specific to the
129 * particular keytab type.
130 */
131
132#include <ctype.h>
133krb5_error_code KRB5_CALLCONV
134krb5_kt_resolve (krb5_context context, const char *name, krb5_keytab *ktid)
135{
136    const struct krb5_kt_typelist *tlist;
137    char *pfx;
138    unsigned int pfxlen;
139    const char *cp, *resid;
140    krb5_error_code err;
141
142    cp = strchr (name, ':');
143    if (!cp) {
144	    return (*krb5_kt_dfl_ops.resolve)(context, name, ktid);
145    }
146
147    pfxlen = cp - name;
148
149    if ( pfxlen == 1 && isalpha(name[0]) ) {
150        /* We found a drive letter not a prefix - use FILE: */
151        pfx = strdup("FILE:");
152        if (!pfx)
153            return ENOMEM;
154
155        resid = name;
156    } else {
157        resid = name + pfxlen + 1;
158
159        pfx = malloc (pfxlen+1);
160        if (!pfx)
161            return ENOMEM;
162
163        memcpy (pfx, name, pfxlen);
164        pfx[pfxlen] = '\0';
165    }
166
167    *ktid = (krb5_keytab) 0;
168
169    err = k5_mutex_lock(&kt_typehead_lock);
170    if (err)
171	return err;
172    tlist = kt_typehead;
173    /* Don't need to hold the lock, since entries are never modified
174       or removed once they're in the list.  Just need to protect
175       access to the list head variable itself.  */
176    k5_mutex_unlock(&kt_typehead_lock);
177    for (; tlist; tlist = tlist->next) {
178	if (strcmp (tlist->ops->prefix, pfx) == 0) {
179	    free(pfx);
180	    return (*tlist->ops->resolve)(context, resid, ktid);
181	}
182    }
183    free(pfx);
184    return KRB5_KT_UNKNOWN_TYPE;
185}
186
187
188/*
189 * Routines to deal with externalizingt krb5_keytab.
190 *	krb5_keytab_size();
191 *	krb5_keytab_externalize();
192 *	krb5_keytab_internalize();
193 */
194static krb5_error_code krb5_keytab_size
195	(krb5_context, krb5_pointer, size_t *);
196static krb5_error_code krb5_keytab_externalize
197	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
198static krb5_error_code krb5_keytab_internalize
199	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
200
201/*
202 * Serialization entry for this type.
203 */
204static const krb5_ser_entry krb5_keytab_ser_entry = {
205    KV5M_KEYTAB,			/* Type			*/
206    krb5_keytab_size,			/* Sizer routine	*/
207    krb5_keytab_externalize,		/* Externalize routine	*/
208    krb5_keytab_internalize		/* Internalize routine	*/
209};
210
211static krb5_error_code
212krb5_keytab_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
213{
214    krb5_error_code	kret;
215    krb5_keytab		keytab;
216    krb5_ser_handle	shandle;
217
218    kret = EINVAL;
219    keytab = (krb5_keytab) arg;
220    shandle = (krb5_ser_handle) keytab->ops->serializer;
221    if ((keytab != NULL) && (keytab->ops) &&
222	(shandle != NULL) && (shandle->sizer))
223	kret = (*shandle->sizer)(kcontext, arg, sizep);
224    return(kret);
225}
226
227static krb5_error_code
228krb5_keytab_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
229{
230    krb5_error_code	kret;
231    krb5_keytab		keytab;
232    krb5_ser_handle	shandle;
233
234    kret = EINVAL;
235    keytab = (krb5_keytab) arg;
236    shandle = (krb5_ser_handle) keytab->ops->serializer;
237    if ((keytab != NULL) && (keytab->ops) &&
238	(shandle != NULL) && (shandle->externalizer))
239	kret = (*shandle->externalizer)(kcontext, arg, buffer, lenremain);
240    return(kret);
241}
242
243static krb5_error_code
244krb5_keytab_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
245{
246    krb5_error_code	kret;
247    krb5_ser_handle	shandle;
248
249    kret = EINVAL;
250    shandle = (krb5_ser_handle) krb5_kt_dfl_ops.serializer;
251    if ((shandle != NULL) && (shandle->internalizer))
252	kret = (*shandle->internalizer)(kcontext, argp, buffer, lenremain);
253    return(kret);
254}
255
256krb5_error_code KRB5_CALLCONV
257krb5_ser_keytab_init(krb5_context kcontext)
258{
259    return(krb5_register_serializer(kcontext, &krb5_keytab_ser_entry));
260}
261