1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6
7 /*
8 * lib/krb5/krb/srv_rcache.c
9 *
10 * Copyright 1991 by the Massachusetts Institute of Technology.
11 * All Rights Reserved.
12 *
13 * Export of this software from the United States of America may
14 * require a specific license from the United States Government.
15 * It is the responsibility of any person or organization contemplating
16 * export to obtain such a license before exporting.
17 *
18 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19 * distribute this software and its documentation for any purpose and
20 * without fee is hereby granted, provided that the above copyright
21 * notice appear in all copies and that both that copyright notice and
22 * this permission notice appear in supporting documentation, and that
23 * the name of M.I.T. not be used in advertising or publicity pertaining
24 * to distribution of the software without specific, written prior
25 * permission. Furthermore if you modify this software you must label
26 * your software as modified software and not distribute it in such a
27 * fashion that it might be confused with the original M.I.T. software.
28 * M.I.T. makes no representations about the suitability of
29 * this software for any purpose. It is provided "as is" without express
30 * or implied warranty.
31 *
32 *
33 * Allocate & prepare a default replay cache for a server.
34 */
35
36 #include "k5-int.h"
37 #include <ctype.h>
38 #include <stdio.h>
39
40 /* Macro for valid RC name characters*/
41 #define isvalidrcname(x) ((!ispunct(x))&&isgraph(x))
42 krb5_error_code KRB5_CALLCONV
krb5_get_server_rcache(krb5_context context,const krb5_data * piece,krb5_rcache * rcptr)43 krb5_get_server_rcache(krb5_context context, const krb5_data *piece,
44 krb5_rcache *rcptr)
45 {
46 krb5_rcache rcache = 0;
47 char *cachename = 0, *def_env = 0, *cachetype;
48 char tmp[4], *full_name;
49 krb5_error_code retval;
50 int p, i;
51 unsigned int len;
52
53 #ifdef HAVE_GETEUID
54 unsigned long tens;
55 unsigned long uid = geteuid();
56 #endif
57
58 if (piece == NULL)
59 return ENOMEM;
60
61 cachetype = krb5_rc_default_type(context);
62
63 /*
64 * Solaris Kerberos: Check to see if something other than the default replay
65 * cache name will be used. If so then skip over the construction of
66 * said name.
67 */
68 if ((def_env = krb5_rc_default_name(context)) != 0) {
69 cachename = strdup(def_env);
70 if (cachename == NULL)
71 return (ENOMEM);
72 /*
73 * We expect to have the fully qualified rcache name (<type>:<name>),
74 * so we populate the default type here if the type is missing.
75 */
76 if (strchr(cachename, ':') == NULL) {
77 full_name = malloc(strlen(cachetype) + 1 +
78 strlen(cachename) + 1);
79 if (full_name == NULL) {
80 free(cachename);
81 return(ENOMEM);
82 }
83 (void) sprintf(full_name, "%s:%s", cachetype, cachename);
84 free(cachename);
85 cachename = full_name;
86 }
87 goto skip_create;
88 }
89
90 len = piece->length + 3 + 1;
91 for (i = 0; i < piece->length; i++) {
92 if (piece->data[i] == '-')
93 len++;
94 else if (!isvalidrcname((int) piece->data[i]))
95 len += 3;
96 }
97
98 #ifdef HAVE_GETEUID
99 len += 2; /* _<uid> */
100 for (tens = 1; (uid / tens) > 9 ; tens *= 10)
101 len++;
102 #endif
103
104 cachename = malloc(strlen(cachetype) + 5 + len);
105 if (!cachename) {
106 retval = ENOMEM;
107 goto cleanup;
108 }
109 strcpy(cachename, cachetype);
110
111 p = strlen(cachename);
112 cachename[p++] = ':';
113 for (i = 0; i < piece->length; i++) {
114 if (piece->data[i] == '-') {
115 cachename[p++] = '-';
116 cachename[p++] = '-';
117 continue;
118 }
119 if (!isvalidrcname((int) piece->data[i])) {
120 sprintf(tmp, "%03o", piece->data[i]);
121 cachename[p++] = '-';
122 cachename[p++] = tmp[0];
123 cachename[p++] = tmp[1];
124 cachename[p++] = tmp[2];
125 continue;
126 }
127 cachename[p++] = piece->data[i];
128 }
129
130 #ifdef HAVE_GETEUID
131 cachename[p++] = '_';
132 while (tens) {
133 cachename[p++] = '0' + ((uid / tens) % 10);
134 tens /= 10;
135 }
136 #endif
137
138 cachename[p++] = '\0';
139
140 skip_create:
141 retval = krb5_rc_resolve_full(context, &rcache, cachename);
142 if (retval) {
143 rcache = 0;
144 goto cleanup;
145 }
146
147 /*
148 * First try to recover the replay cache; if that doesn't work,
149 * initialize it.
150 */
151 retval = krb5_rc_recover_or_initialize(context, rcache, context->clockskew);
152 if (retval) {
153 krb5_rc_close(context, rcache);
154 rcache = 0;
155 goto cleanup;
156 }
157
158 *rcptr = rcache;
159 rcache = 0;
160 retval = 0;
161
162 cleanup:
163 if (rcache)
164 krb5_xfree(rcache);
165 if (cachename)
166 krb5_xfree(cachename);
167 return retval;
168 }
169