xref: /freebsd/crypto/heimdal/appl/afsutil/afslog.c (revision 7aa383846770374466b1dcb2cefd71bde9acf463)
1 /*
2  * Copyright (c) 1997-2003 Kungliga Tekniska H�gskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 RCSID("$Id: afslog.c 16438 2006-01-03 09:27:54Z lha $");
37 #endif
38 #include <ctype.h>
39 #ifdef KRB5
40 #include <krb5.h>
41 #endif
42 #ifdef KRB4
43 #include <krb.h>
44 #endif
45 #include <kafs.h>
46 #include <roken.h>
47 #include <getarg.h>
48 #include <err.h>
49 
50 static int help_flag;
51 static int version_flag;
52 static getarg_strings cells;
53 static char *realm;
54 static getarg_strings files;
55 static int unlog_flag;
56 static int verbose;
57 #ifdef KRB4
58 static int use_krb4 = 1;
59 #endif
60 #ifdef KRB5
61 static char *client_string;
62 static char *cache_string;
63 static int use_krb5 = 1;
64 #endif
65 
66 struct getargs args[] = {
67     { "cell",	'c', arg_strings, &cells, "cells to get tokens for", "cell" },
68     { "file",	'p', arg_strings, &files, "files to get tokens for", "path" },
69     { "realm",	'k', arg_string, &realm, "realm for afs cell", "realm" },
70     { "unlog",	'u', arg_flag, &unlog_flag, "remove tokens" },
71 #ifdef KRB4
72     { "v4",	 0, arg_negative_flag, &use_krb4, "don't use Kerberos 4" },
73 #endif
74 #ifdef KRB5
75     { "principal",'P',arg_string,&client_string,"principal to use","principal"},
76     { "cache",   0,  arg_string, &cache_string, "ccache to use", "cache"},
77     { "v5",	 0,  arg_negative_flag, &use_krb5, "don't use Kerberos 5" },
78 #endif
79     { "verbose",'v', arg_flag, &verbose },
80     { "version", 0,  arg_flag, &version_flag },
81     { "help",	'h', arg_flag, &help_flag },
82 };
83 
84 static int num_args = sizeof(args) / sizeof(args[0]);
85 
86 #ifdef KRB5
87 krb5_context context;
88 krb5_ccache id;
89 #endif
90 
91 static const char *
92 expand_one_file(FILE *f, const char *cell)
93 {
94     static char buf[1024];
95     char *p;
96 
97     while (fgets (buf, sizeof(buf), f) != NULL) {
98 	if(buf[0] == '>') {
99 	    for(p = buf; *p && !isspace((unsigned char)*p) && *p != '#'; p++)
100 		;
101 	    *p = '\0';
102 	    if(strncmp(buf + 1, cell, strlen(cell)) == 0)
103 		return buf + 1;
104 	}
105 	buf[0] = '\0';
106     }
107     return NULL;
108 }
109 
110 static const char *
111 expand_cell_name(const char *cell)
112 {
113     FILE *f;
114     const char *c;
115     const char **fn, *files[] = { _PATH_CELLSERVDB,
116 				  _PATH_ARLA_CELLSERVDB,
117 				  _PATH_OPENAFS_DEBIAN_CELLSERVDB,
118 				  _PATH_ARLA_DEBIAN_CELLSERVDB,
119 				  NULL };
120     for(fn = files; *fn; fn++) {
121 	f = fopen(*fn, "r");
122 	if(f == NULL)
123 	    continue;
124 	c = expand_one_file(f, cell);
125 	fclose(f);
126 	if(c)
127 	    return c;
128     }
129     return cell;
130 }
131 
132 static void
133 usage(int ecode)
134 {
135     arg_printusage(args, num_args, NULL, "[cell|path]...");
136     exit(ecode);
137 }
138 
139 struct cell_list {
140     char *cell;
141     struct cell_list *next;
142 } *cell_list;
143 
144 static int
145 afslog_cell(const char *cell, int expand)
146 {
147     struct cell_list *p, **q;
148     const char *c = cell;
149     if(expand){
150 	c = expand_cell_name(cell);
151 	if(c == NULL){
152 	    warnx("No cell matching \"%s\" found.", cell);
153 	    return -1;
154 	}
155 	if(verbose && strcmp(c, cell) != 0)
156 	    warnx("Cell \"%s\" expanded to \"%s\"", cell, c);
157     }
158     /* add to list of cells to get tokens for, and also remove
159        duplicates; the actual afslog takes place later */
160     for(p = cell_list, q = &cell_list; p; q = &p->next, p = p->next)
161 	if(strcmp(p->cell, c) == 0)
162 	    return 0;
163     p = malloc(sizeof(*p));
164     if(p == NULL)
165 	return -1;
166     p->cell = strdup(c);
167     if(p->cell == NULL) {
168 	free(p);
169 	return -1;
170     }
171     p->next = NULL;
172     *q = p;
173     return 0;
174 }
175 
176 static int
177 afslog_file(const char *path)
178 {
179     char cell[64];
180     if(k_afs_cell_of_file(path, cell, sizeof(cell))){
181 	warnx("No cell found for file \"%s\".", path);
182 	return -1;
183     }
184     if(verbose)
185 	warnx("File \"%s\" lives in cell \"%s\"", path, cell);
186     return afslog_cell(cell, 0);
187 }
188 
189 static int
190 do_afslog(const char *cell)
191 {
192     int k5ret, k4ret;
193 
194     k5ret = k4ret = 0;
195 
196 #ifdef KRB5
197     if(context != NULL && id != NULL && use_krb5) {
198 	k5ret = krb5_afslog(context, id, cell, realm);
199 	if(k5ret == 0)
200 	    return 0;
201     }
202 #endif
203 #if KRB4
204     if (use_krb4) {
205 	k4ret = krb_afslog(cell, realm);
206 	if(k4ret == 0)
207 	    return 0;
208     }
209 #endif
210     if (cell == NULL)
211 	cell = "<default cell>";
212 #ifdef KRB5
213     if (k5ret)
214 	warnx("krb5_afslog(%s): %s", cell, krb5_get_err_text(context, k5ret));
215 #endif
216 #ifdef KRB4
217     if (k4ret)
218 	warnx("krb_afslog(%s): %s", cell, krb_get_err_text(k4ret));
219 #endif
220     if (k5ret || k4ret)
221 	return 1;
222     return 0;
223 }
224 
225 static void
226 log_func(void *ctx, const char *str)
227 {
228     fprintf(stderr, "%s\n", str);
229 }
230 
231 int
232 main(int argc, char **argv)
233 {
234     int optind = 0;
235     int i;
236     int num;
237     int ret = 0;
238     int failed = 0;
239     struct cell_list *p;
240 
241     setprogname(argv[0]);
242 
243     if(getarg(args, num_args, argc, argv, &optind))
244 	usage(1);
245     if(help_flag)
246 	usage(0);
247     if(version_flag) {
248 	print_version(NULL);
249 	exit(0);
250     }
251 
252     if(!k_hasafs())
253 	errx(1, "AFS does not seem to be present on this machine");
254 
255     if(unlog_flag){
256 	k_unlog();
257 	exit(0);
258     }
259 #ifdef KRB5
260     ret = krb5_init_context(&context);
261     if (ret) {
262 	context = NULL;
263     } else {
264 	if (client_string) {
265 	    krb5_principal client;
266 
267 	    ret = krb5_parse_name(context, client_string, &client);
268 	    if (ret == 0)
269 		ret = krb5_cc_cache_match(context, client, NULL, &id);
270 	    if (ret)
271 		id = NULL;
272 	}
273 	if (id == NULL && cache_string) {
274 	    if(krb5_cc_resolve(context, cache_string, &id) != 0) {
275 		krb5_warnx(context, "failed to open kerberos 5 cache '%s'",
276 			   cache_string);
277 		id = NULL;
278 	    }
279 	}
280 	if (id == NULL)
281 	    if(krb5_cc_default(context, &id) != 0)
282 		id = NULL;
283     }
284 #endif
285 
286     if (verbose)
287 	kafs_set_verbose(log_func, NULL);
288 
289     num = 0;
290     for(i = 0; i < files.num_strings; i++){
291 	afslog_file(files.strings[i]);
292 	num++;
293     }
294     free_getarg_strings (&files);
295     for(i = 0; i < cells.num_strings; i++){
296 	afslog_cell(cells.strings[i], 1);
297 	num++;
298     }
299     free_getarg_strings (&cells);
300     for(i = optind; i < argc; i++){
301 	num++;
302 	if(strcmp(argv[i], ".") == 0 ||
303 	   strcmp(argv[i], "..") == 0 ||
304 	   strchr(argv[i], '/') ||
305 	   access(argv[i], F_OK) == 0)
306 	    afslog_file(argv[i]);
307 	else
308 	    afslog_cell(argv[i], 1);
309     }
310     if(num == 0) {
311 	if(do_afslog(NULL))
312 	    failed++;
313     } else
314 	for(p = cell_list; p; p = p->next) {
315 	    if(verbose)
316 		warnx("Getting tokens for cell \"%s\"", p->cell);
317 	    if(do_afslog(p->cell))
318 		failed++;
319     }
320 
321     return failed;
322 }
323