xref: /freebsd/crypto/krb5/src/lib/krb5/rcache/rc_dfl.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/rcache/rc_dfl.c - default replay cache type */
3 /*
4  * Copyright (C) 2019 by the Massachusetts Institute of Technology.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in
16  *   the documentation and/or other materials provided with the
17  *   distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30  * OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * The dfl rcache type is a wrapper around the file2 rcache type, selecting a
35  * filename and (on Unix-like systems) applying open() safety appropriate for
36  * using a shared temporary directory.
37  */
38 
39 #include "k5-int.h"
40 #include "rc-int.h"
41 #ifdef _WIN32
42 #include "../os/os-proto.h"
43 #else
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #endif
47 
48 #ifdef _WIN32
49 
50 static krb5_error_code
open_file(krb5_context context,int * fd_out)51 open_file(krb5_context context, int *fd_out)
52 {
53     krb5_error_code ret;
54     char *fname;
55     const char *dir;
56 
57     *fd_out = -1;
58 
59     dir = getenv("KRB5RCACHEDIR");
60     if (dir != NULL) {
61         if (asprintf(&fname, "%s\\krb5.rcache2") < 0)
62             return ENOMEM;
63     } else {
64         ret = k5_expand_path_tokens(context, "%{LOCAL_APPDATA}\\krb5.rcache2",
65                                     &fname);
66         if (ret)
67             return ret;
68     }
69 
70     *fd_out = open(fname, O_CREAT | O_RDWR | O_BINARY, 0600);
71     ret = (*fd_out < 0) ? errno : 0;
72     if (ret) {
73         k5_setmsg(context, ret, "%s (filename: %s)",
74                   error_message(ret), fname);
75     }
76     free(fname);
77     return ret;
78 }
79 
80 #else /* _WIN32 */
81 
82 static krb5_error_code
open_file(krb5_context context,int * fd_out)83 open_file(krb5_context context, int *fd_out)
84 {
85     krb5_error_code ret;
86     int fd = -1;
87     char *fname = NULL;
88     const char *dir;
89     struct stat statbuf;
90     uid_t euid = geteuid();
91 
92     *fd_out = -1;
93 
94     dir = secure_getenv("KRB5RCACHEDIR");
95     if (dir == NULL) {
96         dir = secure_getenv("TMPDIR");
97         if (dir == NULL)
98             dir = RCTMPDIR;
99     }
100     if (asprintf(&fname, "%s/krb5_%lu.rcache2", dir, (unsigned long)euid) < 0)
101         return ENOMEM;
102 
103     fd = open(fname, O_CREAT | O_RDWR | O_NOFOLLOW, 0600);
104     if (fd < 0) {
105         ret = errno;
106         k5_setmsg(context, ret, "%s (filename: %s)",
107                   error_message(ret), fname);
108         goto cleanup;
109     }
110 
111     if (fstat(fd, &statbuf) < 0 || statbuf.st_uid != euid) {
112         ret = EIO;
113         k5_setmsg(context, ret, "Replay cache file %s is not owned by uid %lu",
114                   fname, (unsigned long)euid);
115         goto cleanup;
116     }
117 
118     *fd_out = fd;
119     fd = -1;
120     ret = 0;
121 
122 cleanup:
123     if (fd != -1)
124         close(fd);
125     free(fname);
126     return ret;
127 }
128 
129 #endif /* not _WIN32 */
130 
131 static krb5_error_code
dfl_resolve(krb5_context context,const char * residual,void ** rcdata_out)132 dfl_resolve(krb5_context context, const char *residual, void **rcdata_out)
133 {
134     *rcdata_out = NULL;
135     return 0;
136 }
137 
138 static void
dfl_close(krb5_context context,void * rcdata)139 dfl_close(krb5_context context, void *rcdata)
140 {
141 }
142 
143 static krb5_error_code
dfl_store(krb5_context context,void * rcdata,const krb5_data * tag)144 dfl_store(krb5_context context, void *rcdata, const krb5_data *tag)
145 {
146     krb5_error_code ret;
147     int fd;
148 
149     ret = open_file(context, &fd);
150     if (ret)
151         return ret;
152 
153     ret = k5_rcfile2_store(context, fd, tag);
154     close(fd);
155     return ret;
156 }
157 
158 const krb5_rc_ops k5_rc_dfl_ops =
159 {
160     "dfl",
161     dfl_resolve,
162     dfl_close,
163     dfl_store
164 };
165