xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/srv_rcache.c (revision 55fea89dcaa64928bed4327112404dcb3e07b79f)
17c478bd9Sstevel@tonic-gate /*
2*159d09a2SMark 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/krb/srv_rcache.c
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Copyright 1991 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.
177c478bd9Sstevel@tonic-gate  *
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.
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * Allocate & prepare a default replay cache for a server.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
36*159d09a2SMark Phalan #include "k5-int.h"
377c478bd9Sstevel@tonic-gate #include <ctype.h>
387c478bd9Sstevel@tonic-gate #include <stdio.h>
397c478bd9Sstevel@tonic-gate 
40*159d09a2SMark Phalan /* Macro for valid RC name characters*/
41505d05c7Sgtb #define isvalidrcname(x) ((!ispunct(x))&&isgraph(x))
42505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_get_server_rcache(krb5_context context,const krb5_data * piece,krb5_rcache * rcptr)43505d05c7Sgtb krb5_get_server_rcache(krb5_context context, const krb5_data *piece,
44505d05c7Sgtb 		       krb5_rcache *rcptr)
457c478bd9Sstevel@tonic-gate {
467c478bd9Sstevel@tonic-gate     krb5_rcache rcache = 0;
47505d05c7Sgtb     char *cachename = 0, *def_env = 0, *cachetype;
484ef135ebSsemery     char tmp[4], *full_name;
497c478bd9Sstevel@tonic-gate     krb5_error_code retval;
50505d05c7Sgtb     int p, i;
51505d05c7Sgtb     unsigned int len;
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #ifdef HAVE_GETEUID
547c478bd9Sstevel@tonic-gate     unsigned long tens;
557c478bd9Sstevel@tonic-gate     unsigned long uid = geteuid();
567c478bd9Sstevel@tonic-gate #endif
577c478bd9Sstevel@tonic-gate 
58505d05c7Sgtb     if (piece == NULL)
597c478bd9Sstevel@tonic-gate 	return ENOMEM;
607c478bd9Sstevel@tonic-gate 
614ef135ebSsemery     cachetype = krb5_rc_default_type(context);
624ef135ebSsemery 
637c478bd9Sstevel@tonic-gate     /*
64*159d09a2SMark Phalan      * Solaris Kerberos: Check to see if something other than the default replay
65*159d09a2SMark Phalan      * cache name will be used.  If so then skip over the construction of
667c478bd9Sstevel@tonic-gate      * said name.
677c478bd9Sstevel@tonic-gate      */
687c478bd9Sstevel@tonic-gate     if ((def_env = krb5_rc_default_name(context)) != 0) {
697c478bd9Sstevel@tonic-gate 	cachename = strdup(def_env);
704ef135ebSsemery 	if (cachename == NULL)
717c478bd9Sstevel@tonic-gate 		return (ENOMEM);
724ef135ebSsemery 	/*
734ef135ebSsemery 	 * We expect to have the fully qualified rcache name (<type>:<name>),
744ef135ebSsemery 	 * so we populate the default type here if the type is missing.
754ef135ebSsemery 	 */
764ef135ebSsemery 	if (strchr(cachename, ':') == NULL) {
774ef135ebSsemery 		full_name = malloc(strlen(cachetype) + 1 +
784ef135ebSsemery 				   strlen(cachename) + 1);
794ef135ebSsemery 		if (full_name == NULL) {
804ef135ebSsemery 			free(cachename);
814ef135ebSsemery 			return(ENOMEM);
824ef135ebSsemery 		}
834ef135ebSsemery 		(void) sprintf(full_name, "%s:%s", cachetype, cachename);
844ef135ebSsemery 		free(cachename);
854ef135ebSsemery 		cachename = full_name;
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 	goto skip_create;
887c478bd9Sstevel@tonic-gate     }
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate     len = piece->length + 3 + 1;
917c478bd9Sstevel@tonic-gate     for (i = 0; i < piece->length; i++) {
92505d05c7Sgtb 	if (piece->data[i] == '-')
937c478bd9Sstevel@tonic-gate 	    len++;
94505d05c7Sgtb 	else if (!isvalidrcname((int) piece->data[i]))
957c478bd9Sstevel@tonic-gate 	    len += 3;
967c478bd9Sstevel@tonic-gate     }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #ifdef HAVE_GETEUID
997c478bd9Sstevel@tonic-gate     len += 2;	/* _<uid> */
1007c478bd9Sstevel@tonic-gate     for (tens = 1; (uid / tens) > 9 ; tens *= 10)
1017c478bd9Sstevel@tonic-gate 	len++;
1027c478bd9Sstevel@tonic-gate #endif
1037c478bd9Sstevel@tonic-gate 
104505d05c7Sgtb     cachename = malloc(strlen(cachetype) + 5 + len);
1057c478bd9Sstevel@tonic-gate     if (!cachename) {
1067c478bd9Sstevel@tonic-gate 	retval = ENOMEM;
1077c478bd9Sstevel@tonic-gate 	goto cleanup;
1087c478bd9Sstevel@tonic-gate     }
109505d05c7Sgtb     strcpy(cachename, cachetype);
110505d05c7Sgtb 
111505d05c7Sgtb     p = strlen(cachename);
112505d05c7Sgtb     cachename[p++] = ':';
1137c478bd9Sstevel@tonic-gate     for (i = 0; i < piece->length; i++) {
114505d05c7Sgtb 	if (piece->data[i] == '-') {
115505d05c7Sgtb 	    cachename[p++] = '-';
116505d05c7Sgtb 	    cachename[p++] = '-';
1177c478bd9Sstevel@tonic-gate 	    continue;
1187c478bd9Sstevel@tonic-gate 	}
119505d05c7Sgtb 	if (!isvalidrcname((int) piece->data[i])) {
1207c478bd9Sstevel@tonic-gate 	    sprintf(tmp, "%03o", piece->data[i]);
121505d05c7Sgtb 	    cachename[p++] = '-';
1227c478bd9Sstevel@tonic-gate 	    cachename[p++] = tmp[0];
1237c478bd9Sstevel@tonic-gate 	    cachename[p++] = tmp[1];
1247c478bd9Sstevel@tonic-gate 	    cachename[p++] = tmp[2];
1257c478bd9Sstevel@tonic-gate 	    continue;
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate 	cachename[p++] = piece->data[i];
1287c478bd9Sstevel@tonic-gate     }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate #ifdef HAVE_GETEUID
1317c478bd9Sstevel@tonic-gate     cachename[p++] = '_';
1327c478bd9Sstevel@tonic-gate     while (tens) {
1337c478bd9Sstevel@tonic-gate 	cachename[p++] = '0' + ((uid / tens) % 10);
1347c478bd9Sstevel@tonic-gate 	tens /= 10;
1357c478bd9Sstevel@tonic-gate     }
1367c478bd9Sstevel@tonic-gate #endif
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate     cachename[p++] = '\0';
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate skip_create:
141505d05c7Sgtb     retval = krb5_rc_resolve_full(context, &rcache, cachename);
142e49962a0Ssemery     if (retval) {
143e49962a0Ssemery 	rcache = 0;
1447c478bd9Sstevel@tonic-gate 	goto cleanup;
145e49962a0Ssemery     }
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate     /*
1487c478bd9Sstevel@tonic-gate      * First try to recover the replay cache; if that doesn't work,
1497c478bd9Sstevel@tonic-gate      * initialize it.
1507c478bd9Sstevel@tonic-gate      */
151505d05c7Sgtb     retval = krb5_rc_recover_or_initialize(context, rcache, context->clockskew);
1527c478bd9Sstevel@tonic-gate     if (retval) {
153505d05c7Sgtb 	krb5_rc_close(context, rcache);
1547c478bd9Sstevel@tonic-gate 	rcache = 0;
1557c478bd9Sstevel@tonic-gate 	goto cleanup;
1567c478bd9Sstevel@tonic-gate     }
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate     *rcptr = rcache;
1597c478bd9Sstevel@tonic-gate     rcache = 0;
1607c478bd9Sstevel@tonic-gate     retval = 0;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate cleanup:
1637c478bd9Sstevel@tonic-gate     if (rcache)
1647c478bd9Sstevel@tonic-gate 	krb5_xfree(rcache);
1657c478bd9Sstevel@tonic-gate     if (cachename)
1667c478bd9Sstevel@tonic-gate 	krb5_xfree(cachename);
1677c478bd9Sstevel@tonic-gate     return retval;
1687c478bd9Sstevel@tonic-gate }
169