17c478bd9Sstevel@tonic-gate /*
2159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate  * lib/krb5/keytab/ktbase.c
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Copyright 1990 by the Massachusetts Institute of Technology.
117c478bd9Sstevel@tonic-gate  * All Rights Reserved.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
147c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
157c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
167c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
17*55fea89dSDan Cross  *
187c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
197c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
207c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
217c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
227c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
237c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
247c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
257c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
267c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
277c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
287c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
297c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
307c478bd9Sstevel@tonic-gate  * or implied warranty.
31*55fea89dSDan Cross  *
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * Registration functions for keytab.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
36159d09a2SMark Phalan #include "k5-int.h"
37159d09a2SMark Phalan #include "k5-thread.h"
38159d09a2SMark Phalan #include "kt-int.h"
397c478bd9Sstevel@tonic-gate 
40505d05c7Sgtb extern const krb5_kt_ops krb5_ktf_ops;
41505d05c7Sgtb extern const krb5_kt_ops krb5_ktf_writable_ops;
42505d05c7Sgtb extern const krb5_kt_ops krb5_kts_ops;
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate struct krb5_kt_typelist {
45505d05c7Sgtb     const krb5_kt_ops *ops;
46505d05c7Sgtb     const struct krb5_kt_typelist *next;
477c478bd9Sstevel@tonic-gate };
48159d09a2SMark Phalan /* Solaris Kerberos */
49505d05c7Sgtb static const struct krb5_kt_typelist krb5_kt_typelist_wrfile  = {
50505d05c7Sgtb     &krb5_ktf_writable_ops,
51505d05c7Sgtb     0
52505d05c7Sgtb };
53159d09a2SMark Phalan /* Solaris Kerberos */
54159d09a2SMark Phalan static const  struct krb5_kt_typelist krb5_kt_typelist_file  = {
55505d05c7Sgtb     &krb5_ktf_ops,
56505d05c7Sgtb     &krb5_kt_typelist_wrfile
57505d05c7Sgtb };
58159d09a2SMark Phalan /* Solaris Kerberos */
59505d05c7Sgtb static const struct krb5_kt_typelist krb5_kt_typelist_srvtab = {
60505d05c7Sgtb     &krb5_kts_ops,
61505d05c7Sgtb     &krb5_kt_typelist_file
62505d05c7Sgtb };
6356a424ccSmp static const struct krb5_kt_typelist *kt_typehead = &krb5_kt_typelist_srvtab;
64505d05c7Sgtb /* Lock for protecting the type list.  */
65505d05c7Sgtb static k5_mutex_t kt_typehead_lock = K5_MUTEX_PARTIAL_INITIALIZER;
66505d05c7Sgtb 
krb5int_kt_initialize(void)67505d05c7Sgtb int krb5int_kt_initialize(void)
68505d05c7Sgtb {
69505d05c7Sgtb     return k5_mutex_finish_init(&kt_typehead_lock);
70505d05c7Sgtb }
71505d05c7Sgtb 
72505d05c7Sgtb void
krb5int_kt_finalize(void)73505d05c7Sgtb krb5int_kt_finalize(void)
74505d05c7Sgtb {
75505d05c7Sgtb     struct krb5_kt_typelist *t, *t_next;
76505d05c7Sgtb     k5_mutex_destroy(&kt_typehead_lock);
77159d09a2SMark Phalan     /* Solaris Kerberos */
78505d05c7Sgtb     for (t = (struct krb5_kt_typelist *)kt_typehead; t != &krb5_kt_typelist_srvtab;
79505d05c7Sgtb 	t = t_next) {
80505d05c7Sgtb         t_next = (struct krb5_kt_typelist *)t->next;
81505d05c7Sgtb 	free(t);
82505d05c7Sgtb     }
83505d05c7Sgtb }
84505d05c7Sgtb 
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * Register a new key table type
887c478bd9Sstevel@tonic-gate  * don't replace if it already exists; return an error instead.
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate /*ARGSUSED*/
91505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_kt_register(krb5_context context,const krb5_kt_ops * ops)92505d05c7Sgtb krb5_kt_register(krb5_context context, const krb5_kt_ops *ops)
937c478bd9Sstevel@tonic-gate {
94505d05c7Sgtb     const struct krb5_kt_typelist *t;
95505d05c7Sgtb     struct krb5_kt_typelist *newt;
96505d05c7Sgtb     krb5_error_code err;
97505d05c7Sgtb 
98505d05c7Sgtb     err = k5_mutex_lock(&kt_typehead_lock);
99505d05c7Sgtb     if (err)
100505d05c7Sgtb 	return err;
101505d05c7Sgtb     for (t = kt_typehead; t && strcmp(t->ops->prefix,ops->prefix);t = t->next)
1027c478bd9Sstevel@tonic-gate 	;
1037c478bd9Sstevel@tonic-gate     if (t) {
104505d05c7Sgtb 	k5_mutex_unlock(&kt_typehead_lock);
1057c478bd9Sstevel@tonic-gate 	return KRB5_KT_TYPE_EXISTS;
1067c478bd9Sstevel@tonic-gate     }
107505d05c7Sgtb     if (!(newt = (struct krb5_kt_typelist *) malloc(sizeof(*t)))) {
108505d05c7Sgtb 	k5_mutex_unlock(&kt_typehead_lock);
1097c478bd9Sstevel@tonic-gate 	return ENOMEM;
110505d05c7Sgtb     }
111505d05c7Sgtb     newt->next = kt_typehead;
112505d05c7Sgtb     newt->ops = ops;
113505d05c7Sgtb     kt_typehead = newt;
114505d05c7Sgtb     k5_mutex_unlock(&kt_typehead_lock);
1157c478bd9Sstevel@tonic-gate     return 0;
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * Resolve a key table name into a keytab object.
1207c478bd9Sstevel@tonic-gate  *
1217c478bd9Sstevel@tonic-gate  * The name is currently constrained to be of the form "type:residual";
1227c478bd9Sstevel@tonic-gate  *
1237c478bd9Sstevel@tonic-gate  * The "type" portion corresponds to one of the registered key table
1247c478bd9Sstevel@tonic-gate  * types, while the "residual" portion is specific to the
1257c478bd9Sstevel@tonic-gate  * particular keytab type.
1267c478bd9Sstevel@tonic-gate  */
1277c478bd9Sstevel@tonic-gate 
128505d05c7Sgtb #include <ctype.h>
129505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_kt_resolve(krb5_context context,const char * name,krb5_keytab * ktid)130505d05c7Sgtb krb5_kt_resolve (krb5_context context, const char *name, krb5_keytab *ktid)
1317c478bd9Sstevel@tonic-gate {
132505d05c7Sgtb     const struct krb5_kt_typelist *tlist;
133505d05c7Sgtb     char *pfx;
134505d05c7Sgtb     unsigned int pfxlen;
135505d05c7Sgtb     const char *cp, *resid;
136505d05c7Sgtb     krb5_error_code err;
137*55fea89dSDan Cross 
1387c478bd9Sstevel@tonic-gate     cp = strchr (name, ':');
1397c478bd9Sstevel@tonic-gate     if (!cp) {
1407c478bd9Sstevel@tonic-gate 	    return (*krb5_kt_dfl_ops.resolve)(context, name, ktid);
1417c478bd9Sstevel@tonic-gate     }
1427c478bd9Sstevel@tonic-gate 
143505d05c7Sgtb     pfxlen = cp - name;
144505d05c7Sgtb 
145159d09a2SMark Phalan     if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) {
146159d09a2SMark Phalan         /* We found a drive letter not a prefix - use FILE */
147159d09a2SMark Phalan         pfx = strdup("FILE");
148505d05c7Sgtb         if (!pfx)
149505d05c7Sgtb             return ENOMEM;
150505d05c7Sgtb 
151505d05c7Sgtb         resid = name;
152505d05c7Sgtb     } else {
153505d05c7Sgtb         resid = name + pfxlen + 1;
154*55fea89dSDan Cross 
155505d05c7Sgtb         pfx = malloc (pfxlen+1);
156505d05c7Sgtb         if (!pfx)
157505d05c7Sgtb             return ENOMEM;
1587c478bd9Sstevel@tonic-gate 
159505d05c7Sgtb         memcpy (pfx, name, pfxlen);
160505d05c7Sgtb         pfx[pfxlen] = '\0';
161505d05c7Sgtb     }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate     *ktid = (krb5_keytab) 0;
1647c478bd9Sstevel@tonic-gate 
165505d05c7Sgtb     err = k5_mutex_lock(&kt_typehead_lock);
166505d05c7Sgtb     if (err)
167505d05c7Sgtb 	return err;
168505d05c7Sgtb     tlist = kt_typehead;
169505d05c7Sgtb     /* Don't need to hold the lock, since entries are never modified
170505d05c7Sgtb        or removed once they're in the list.  Just need to protect
171505d05c7Sgtb        access to the list head variable itself.  */
172505d05c7Sgtb     k5_mutex_unlock(&kt_typehead_lock);
173505d05c7Sgtb     for (; tlist; tlist = tlist->next) {
1747c478bd9Sstevel@tonic-gate 	if (strcmp (tlist->ops->prefix, pfx) == 0) {
1757c478bd9Sstevel@tonic-gate 	    free(pfx);
1767c478bd9Sstevel@tonic-gate 	    return (*tlist->ops->resolve)(context, resid, ktid);
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate     }
1797c478bd9Sstevel@tonic-gate     free(pfx);
1807c478bd9Sstevel@tonic-gate     return KRB5_KT_UNKNOWN_TYPE;
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate  * Routines to deal with externalizingt krb5_keytab.
1857c478bd9Sstevel@tonic-gate  *	krb5_keytab_size();
1867c478bd9Sstevel@tonic-gate  *	krb5_keytab_externalize();
1877c478bd9Sstevel@tonic-gate  *	krb5_keytab_internalize();
1887c478bd9Sstevel@tonic-gate  */
1897c478bd9Sstevel@tonic-gate static krb5_error_code krb5_keytab_size
190505d05c7Sgtb 	(krb5_context, krb5_pointer, size_t *);
1917c478bd9Sstevel@tonic-gate static krb5_error_code krb5_keytab_externalize
192505d05c7Sgtb 	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
1937c478bd9Sstevel@tonic-gate static krb5_error_code krb5_keytab_internalize
194505d05c7Sgtb 	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate /*
1977c478bd9Sstevel@tonic-gate  * Serialization entry for this type.
1987c478bd9Sstevel@tonic-gate  */
1997c478bd9Sstevel@tonic-gate static const krb5_ser_entry krb5_keytab_ser_entry = {
2007c478bd9Sstevel@tonic-gate     KV5M_KEYTAB,			/* Type			*/
2017c478bd9Sstevel@tonic-gate     krb5_keytab_size,			/* Sizer routine	*/
2027c478bd9Sstevel@tonic-gate     krb5_keytab_externalize,		/* Externalize routine	*/
2037c478bd9Sstevel@tonic-gate     krb5_keytab_internalize		/* Internalize routine	*/
2047c478bd9Sstevel@tonic-gate };
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate static krb5_error_code
krb5_keytab_size(krb5_context kcontext,krb5_pointer arg,size_t * sizep)207505d05c7Sgtb krb5_keytab_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
2107c478bd9Sstevel@tonic-gate     krb5_keytab		keytab;
2117c478bd9Sstevel@tonic-gate     krb5_ser_handle	shandle;
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate     kret = EINVAL;
214159d09a2SMark Phalan     /* Solaris Kerberos */
2157c478bd9Sstevel@tonic-gate     keytab = (krb5_keytab) arg;
2167c478bd9Sstevel@tonic-gate     shandle = (krb5_ser_handle) keytab->ops->serializer;
2177c478bd9Sstevel@tonic-gate     if ((keytab != NULL) && (keytab->ops) &&
2187c478bd9Sstevel@tonic-gate 	(shandle != NULL) && (shandle->sizer))
2197c478bd9Sstevel@tonic-gate 	kret = (*shandle->sizer)(kcontext, arg, sizep);
2207c478bd9Sstevel@tonic-gate     return(kret);
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate static krb5_error_code
krb5_keytab_externalize(krb5_context kcontext,krb5_pointer arg,krb5_octet ** buffer,size_t * lenremain)224505d05c7Sgtb krb5_keytab_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
2257c478bd9Sstevel@tonic-gate {
2267c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
2277c478bd9Sstevel@tonic-gate     krb5_keytab		keytab;
2287c478bd9Sstevel@tonic-gate     krb5_ser_handle	shandle;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate     kret = EINVAL;
231159d09a2SMark Phalan     /* Solaris Kerberos */
2327c478bd9Sstevel@tonic-gate     keytab = (krb5_keytab) arg;
2337c478bd9Sstevel@tonic-gate     shandle = (krb5_ser_handle) keytab->ops->serializer;
2347c478bd9Sstevel@tonic-gate     if ((keytab != NULL) && (keytab->ops) &&
2357c478bd9Sstevel@tonic-gate 	(shandle != NULL) && (shandle->externalizer))
2367c478bd9Sstevel@tonic-gate 	kret = (*shandle->externalizer)(kcontext, arg, buffer, lenremain);
2377c478bd9Sstevel@tonic-gate     return(kret);
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate static krb5_error_code
krb5_keytab_internalize(krb5_context kcontext,krb5_pointer * argp,krb5_octet ** buffer,size_t * lenremain)241505d05c7Sgtb krb5_keytab_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
2447c478bd9Sstevel@tonic-gate     krb5_ser_handle	shandle;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate     kret = EINVAL;
247159d09a2SMark Phalan     /* Solaris Kerberos */
2487c478bd9Sstevel@tonic-gate     shandle = (krb5_ser_handle) krb5_kt_dfl_ops.serializer;
2497c478bd9Sstevel@tonic-gate     if ((shandle != NULL) && (shandle->internalizer))
2507c478bd9Sstevel@tonic-gate 	kret = (*shandle->internalizer)(kcontext, argp, buffer, lenremain);
2517c478bd9Sstevel@tonic-gate     return(kret);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate 
254505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_ser_keytab_init(krb5_context kcontext)255505d05c7Sgtb krb5_ser_keytab_init(krb5_context kcontext)
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate     return(krb5_register_serializer(kcontext, &krb5_keytab_ser_entry));
2587c478bd9Sstevel@tonic-gate }
259