xref: /freebsd/crypto/krb5/src/lib/krb5/rcache/rc_base.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/rcache/rc_base.c */
3 /*
4  * This file of the Kerberos V5 software is derived from public-domain code
5  * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
6  *
7  */
8 
9 /*
10  * Base "glue" functions for the replay cache.
11  */
12 
13 #include "k5-int.h"
14 #include "rc-int.h"
15 #include "k5-thread.h"
16 #include "../os/os-proto.h"
17 
18 struct typelist {
19     const krb5_rc_ops *ops;
20     struct typelist *next;
21 };
22 static struct typelist none = { &k5_rc_none_ops, 0 };
23 static struct typelist file2 = { &k5_rc_file2_ops, &none };
24 static struct typelist dfl = { &k5_rc_dfl_ops, &file2 };
25 static struct typelist *typehead = &dfl;
26 
27 krb5_error_code
k5_rc_default(krb5_context context,krb5_rcache * rc_out)28 k5_rc_default(krb5_context context, krb5_rcache *rc_out)
29 {
30     krb5_error_code ret;
31     const char *val;
32     char *profstr, *rcname;
33 
34     *rc_out = NULL;
35 
36     /* If KRB5RCACHENAME is set in the environment, resolve it. */
37     val = secure_getenv("KRB5RCACHENAME");
38     if (val != NULL)
39         return k5_rc_resolve(context, val, rc_out);
40 
41     /* If KRB5RCACHETYPE is set in the environment, resolve it with an empty
42      * residual (primarily to support KRB5RCACHETYPE=none). */
43     val = secure_getenv("KRB5RCACHETYPE");
44     if (val != NULL) {
45         if (asprintf(&rcname, "%s:", val) < 0)
46             return ENOMEM;
47         ret = k5_rc_resolve(context, rcname, rc_out);
48         free(rcname);
49         return ret;
50     }
51 
52     /* If [libdefaults] default_rcache_name is set, expand path tokens in the
53      * value and resolve it. */
54     if (profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
55                            KRB5_CONF_DEFAULT_RCACHE_NAME, NULL, NULL,
56                            &profstr) == 0 && profstr != NULL) {
57         ret = k5_expand_path_tokens(context, profstr, &rcname);
58         profile_release_string(profstr);
59         if (ret)
60             return ret;
61         ret = k5_rc_resolve(context, rcname, rc_out);
62         free(rcname);
63         return ret;
64     }
65 
66     /* Resolve the default type with no residual. */
67     return k5_rc_resolve(context, "dfl:", rc_out);
68 }
69 
70 
71 krb5_error_code
k5_rc_resolve(krb5_context context,const char * name,krb5_rcache * rc_out)72 k5_rc_resolve(krb5_context context, const char *name, krb5_rcache *rc_out)
73 {
74     krb5_error_code ret;
75     struct typelist *t;
76     const char *sep;
77     size_t len;
78     krb5_rcache rc = NULL;
79 
80     *rc_out = NULL;
81 
82     sep = strchr(name, ':');
83     if (sep == NULL)
84         return KRB5_RC_PARSE;
85     len = sep - name;
86 
87     for (t = typehead; t != NULL; t = t->next) {
88         if (strncmp(t->ops->type, name, len) == 0 && t->ops->type[len] == '\0')
89             break;
90     }
91     if (t == NULL)
92         return KRB5_RC_TYPE_NOTFOUND;
93 
94     rc = k5alloc(sizeof(*rc), &ret);
95     if (rc == NULL)
96         goto error;
97     rc->name = strdup(name);
98     if (rc->name == NULL) {
99         ret = ENOMEM;
100         goto error;
101     }
102     ret = t->ops->resolve(context, sep + 1, &rc->data);
103     if (ret)
104         goto error;
105     rc->ops = t->ops;
106     rc->magic = KV5M_RCACHE;
107 
108     *rc_out = rc;
109     return 0;
110 
111 error:
112     if (rc != NULL) {
113         free(rc->name);
114         free(rc);
115     }
116     return ret;
117 }
118 
119 void
k5_rc_close(krb5_context context,krb5_rcache rc)120 k5_rc_close(krb5_context context, krb5_rcache rc)
121 {
122     rc->ops->close(context, rc->data);
123     free(rc->name);
124     free(rc);
125 }
126 
127 krb5_error_code
k5_rc_store(krb5_context context,krb5_rcache rc,const krb5_enc_data * authenticator)128 k5_rc_store(krb5_context context, krb5_rcache rc,
129             const krb5_enc_data *authenticator)
130 {
131     krb5_error_code ret;
132     krb5_data tag;
133 
134     ret = k5_rc_tag_from_ciphertext(context, authenticator, &tag);
135     if (ret)
136         return ret;
137     return rc->ops->store(context, rc->data, &tag);
138 }
139 
140 const char *
k5_rc_get_name(krb5_context context,krb5_rcache rc)141 k5_rc_get_name(krb5_context context, krb5_rcache rc)
142 {
143     return rc->name;
144 }
145 
146 krb5_error_code
k5_rc_tag_from_ciphertext(krb5_context context,const krb5_enc_data * enc,krb5_data * tag_out)147 k5_rc_tag_from_ciphertext(krb5_context context, const krb5_enc_data *enc,
148                           krb5_data *tag_out)
149 {
150     krb5_error_code ret;
151     const krb5_data *cdata = &enc->ciphertext;
152     unsigned int len;
153 
154     *tag_out = empty_data();
155 
156     ret = krb5_c_crypto_length(context, enc->enctype,
157                                KRB5_CRYPTO_TYPE_CHECKSUM, &len);
158     if (ret)
159         return ret;
160     if (cdata->length < len)
161         return EINVAL;
162     *tag_out = make_data(cdata->data + cdata->length - len, len);
163     return 0;
164 }
165 
166 /*
167  * Stub functions for former internal replay cache functions used by OpenSSL
168  * (despite the lack of prototypes) before the OpenSSL 1.1 release.
169  */
170 
171 krb5_error_code krb5_rc_default(krb5_context, krb5_rcache *);
172 krb5_error_code KRB5_CALLCONV krb5_rc_destroy(krb5_context, krb5_rcache);
173 krb5_error_code KRB5_CALLCONV krb5_rc_get_lifespan(krb5_context, krb5_rcache,
174                                                    krb5_deltat *);
175 krb5_error_code KRB5_CALLCONV krb5_rc_initialize(krb5_context, krb5_rcache,
176                                                  krb5_deltat);
177 
178 krb5_error_code
krb5_rc_default(krb5_context context,krb5_rcache * rc)179 krb5_rc_default(krb5_context context, krb5_rcache *rc)
180 {
181     return EINVAL;
182 }
183 
184 krb5_error_code KRB5_CALLCONV
krb5_rc_destroy(krb5_context context,krb5_rcache rc)185 krb5_rc_destroy(krb5_context context, krb5_rcache rc)
186 {
187     return EINVAL;
188 }
189 
190 krb5_error_code KRB5_CALLCONV
krb5_rc_get_lifespan(krb5_context context,krb5_rcache rc,krb5_deltat * span)191 krb5_rc_get_lifespan(krb5_context context, krb5_rcache rc, krb5_deltat *span)
192 {
193     return EINVAL;
194 }
195 
196 krb5_error_code KRB5_CALLCONV
krb5_rc_initialize(krb5_context context,krb5_rcache rc,krb5_deltat span)197 krb5_rc_initialize(krb5_context context, krb5_rcache rc, krb5_deltat span)
198 {
199     return EINVAL;
200 }
201