155682Smarkm/*
2233294Sstas * Copyright (c) 1997-2003 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
955682Smarkm *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
2055682Smarkm *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#ifdef HAVE_CONFIG_H
3555682Smarkm#include <config.h>
36233294SstasRCSID("$Id$");
3755682Smarkm#endif
3855682Smarkm#include <ctype.h>
39120945Snectar#ifdef KRB5
4055682Smarkm#include <krb5.h>
41120945Snectar#endif
4255682Smarkm#include <kafs.h>
4355682Smarkm#include <roken.h>
4455682Smarkm#include <getarg.h>
4572445Sassar#include <err.h>
4655682Smarkm
4755682Smarkmstatic int help_flag;
4855682Smarkmstatic int version_flag;
4955682Smarkmstatic getarg_strings cells;
5055682Smarkmstatic char *realm;
5155682Smarkmstatic getarg_strings files;
5255682Smarkmstatic int unlog_flag;
5355682Smarkmstatic int verbose;
54120945Snectar#ifdef KRB5
55178825Sdfrstatic char *client_string;
56178825Sdfrstatic char *cache_string;
57120945Snectarstatic int use_krb5 = 1;
58120945Snectar#endif
5955682Smarkm
6055682Smarkmstruct getargs args[] = {
61120945Snectar    { "cell",	'c', arg_strings, &cells, "cells to get tokens for", "cell" },
62120945Snectar    { "file",	'p', arg_strings, &files, "files to get tokens for", "path" },
6355682Smarkm    { "realm",	'k', arg_string, &realm, "realm for afs cell", "realm" },
6455682Smarkm    { "unlog",	'u', arg_flag, &unlog_flag, "remove tokens" },
65120945Snectar#ifdef KRB5
66178825Sdfr    { "principal",'P',arg_string,&client_string,"principal to use","principal"},
67178825Sdfr    { "cache",   0,  arg_string, &cache_string, "ccache to use", "cache"},
68178825Sdfr    { "v5",	 0,  arg_negative_flag, &use_krb5, "don't use Kerberos 5" },
69120945Snectar#endif
7055682Smarkm    { "verbose",'v', arg_flag, &verbose },
7155682Smarkm    { "version", 0,  arg_flag, &version_flag },
7255682Smarkm    { "help",	'h', arg_flag, &help_flag },
7355682Smarkm};
7455682Smarkm
7555682Smarkmstatic int num_args = sizeof(args) / sizeof(args[0]);
7655682Smarkm
77120945Snectar#ifdef KRB5
78120945Snectarkrb5_context context;
79120945Snectarkrb5_ccache id;
80120945Snectar#endif
81120945Snectar
8255682Smarkmstatic const char *
83120945Snectarexpand_one_file(FILE *f, const char *cell)
8455682Smarkm{
85120945Snectar    static char buf[1024];
8655682Smarkm    char *p;
8755682Smarkm
8855682Smarkm    while (fgets (buf, sizeof(buf), f) != NULL) {
89120945Snectar	if(buf[0] == '>') {
90120945Snectar	    for(p = buf; *p && !isspace((unsigned char)*p) && *p != '#'; p++)
9155682Smarkm		;
9255682Smarkm	    *p = '\0';
93120945Snectar	    if(strncmp(buf + 1, cell, strlen(cell)) == 0)
9455682Smarkm		return buf + 1;
9555682Smarkm	}
96120945Snectar	buf[0] = '\0';
9755682Smarkm    }
98120945Snectar    return NULL;
99120945Snectar}
100120945Snectar
101120945Snectarstatic const char *
102120945Snectarexpand_cell_name(const char *cell)
103120945Snectar{
104120945Snectar    FILE *f;
105120945Snectar    const char *c;
106120945Snectar    const char **fn, *files[] = { _PATH_CELLSERVDB,
107120945Snectar				  _PATH_ARLA_CELLSERVDB,
108120945Snectar				  _PATH_OPENAFS_DEBIAN_CELLSERVDB,
109120945Snectar				  _PATH_ARLA_DEBIAN_CELLSERVDB,
110120945Snectar				  NULL };
111120945Snectar    for(fn = files; *fn; fn++) {
112120945Snectar	f = fopen(*fn, "r");
113120945Snectar	if(f == NULL)
114120945Snectar	    continue;
115120945Snectar	c = expand_one_file(f, cell);
116120945Snectar	fclose(f);
117120945Snectar	if(c)
118120945Snectar	    return c;
119120945Snectar    }
12055682Smarkm    return cell;
12155682Smarkm}
12255682Smarkm
12355682Smarkmstatic void
12455682Smarkmusage(int ecode)
12555682Smarkm{
126120945Snectar    arg_printusage(args, num_args, NULL, "[cell|path]...");
12755682Smarkm    exit(ecode);
12855682Smarkm}
12955682Smarkm
130120945Snectarstruct cell_list {
131120945Snectar    char *cell;
132120945Snectar    struct cell_list *next;
133120945Snectar} *cell_list;
134120945Snectar
13555682Smarkmstatic int
136120945Snectarafslog_cell(const char *cell, int expand)
13755682Smarkm{
138120945Snectar    struct cell_list *p, **q;
13955682Smarkm    const char *c = cell;
14055682Smarkm    if(expand){
14155682Smarkm	c = expand_cell_name(cell);
14255682Smarkm	if(c == NULL){
143120945Snectar	    warnx("No cell matching \"%s\" found.", cell);
14455682Smarkm	    return -1;
14555682Smarkm	}
146120945Snectar	if(verbose && strcmp(c, cell) != 0)
147120945Snectar	    warnx("Cell \"%s\" expanded to \"%s\"", cell, c);
14855682Smarkm    }
149120945Snectar    /* add to list of cells to get tokens for, and also remove
150120945Snectar       duplicates; the actual afslog takes place later */
151120945Snectar    for(p = cell_list, q = &cell_list; p; q = &p->next, p = p->next)
152120945Snectar	if(strcmp(p->cell, c) == 0)
153120945Snectar	    return 0;
154120945Snectar    p = malloc(sizeof(*p));
155120945Snectar    if(p == NULL)
156120945Snectar	return -1;
157120945Snectar    p->cell = strdup(c);
158120945Snectar    if(p->cell == NULL) {
159120945Snectar	free(p);
160120945Snectar	return -1;
161120945Snectar    }
162120945Snectar    p->next = NULL;
163120945Snectar    *q = p;
164120945Snectar    return 0;
16555682Smarkm}
16655682Smarkm
16755682Smarkmstatic int
168120945Snectarafslog_file(const char *path)
16955682Smarkm{
17055682Smarkm    char cell[64];
17155682Smarkm    if(k_afs_cell_of_file(path, cell, sizeof(cell))){
172120945Snectar	warnx("No cell found for file \"%s\".", path);
17355682Smarkm	return -1;
17455682Smarkm    }
17555682Smarkm    if(verbose)
176120945Snectar	warnx("File \"%s\" lives in cell \"%s\"", path, cell);
177120945Snectar    return afslog_cell(cell, 0);
17855682Smarkm}
17955682Smarkm
180120945Snectarstatic int
181120945Snectardo_afslog(const char *cell)
182120945Snectar{
183233294Sstas    int k5ret;
184120945Snectar
185233294Sstas    k5ret = 0;
186120945Snectar
187120945Snectar#ifdef KRB5
188120945Snectar    if(context != NULL && id != NULL && use_krb5) {
189178825Sdfr	k5ret = krb5_afslog(context, id, cell, realm);
190120945Snectar	if(k5ret == 0)
191120945Snectar	    return 0;
192120945Snectar    }
193120945Snectar#endif
194127808Snectar    if (cell == NULL)
195127808Snectar	cell = "<default cell>";
196120945Snectar#ifdef KRB5
197120945Snectar    if (k5ret)
198233294Sstas	krb5_warn(context, k5ret, "krb5_afslog(%s)", cell);
199120945Snectar#endif
200233294Sstas    if (k5ret)
201120945Snectar	return 1;
202120945Snectar    return 0;
203120945Snectar}
204120945Snectar
205120945Snectarstatic void
206120945Snectarlog_func(void *ctx, const char *str)
207120945Snectar{
208120945Snectar    fprintf(stderr, "%s\n", str);
209120945Snectar}
210120945Snectar
21155682Smarkmint
21255682Smarkmmain(int argc, char **argv)
21355682Smarkm{
21455682Smarkm    int optind = 0;
21555682Smarkm    int i;
21655682Smarkm    int num;
21755682Smarkm    int ret = 0;
218120945Snectar    int failed = 0;
219120945Snectar    struct cell_list *p;
220233294Sstas
22178527Sassar    setprogname(argv[0]);
22255682Smarkm
22355682Smarkm    if(getarg(args, num_args, argc, argv, &optind))
22455682Smarkm	usage(1);
22555682Smarkm    if(help_flag)
22655682Smarkm	usage(0);
22755682Smarkm    if(version_flag) {
22855682Smarkm	print_version(NULL);
22955682Smarkm	exit(0);
23055682Smarkm    }
23155682Smarkm
23255682Smarkm    if(!k_hasafs())
233120945Snectar	errx(1, "AFS does not seem to be present on this machine");
23455682Smarkm
23555682Smarkm    if(unlog_flag){
23655682Smarkm	k_unlog();
23755682Smarkm	exit(0);
23855682Smarkm    }
239120945Snectar#ifdef KRB5
240120945Snectar    ret = krb5_init_context(&context);
241178825Sdfr    if (ret) {
242120945Snectar	context = NULL;
243178825Sdfr    } else {
244178825Sdfr	if (client_string) {
245178825Sdfr	    krb5_principal client;
246178825Sdfr
247178825Sdfr	    ret = krb5_parse_name(context, client_string, &client);
248178825Sdfr	    if (ret == 0)
249233294Sstas		ret = krb5_cc_cache_match(context, client, &id);
250178825Sdfr	    if (ret)
251178825Sdfr		id = NULL;
252178825Sdfr	}
253178825Sdfr	if (id == NULL && cache_string) {
254178825Sdfr	    if(krb5_cc_resolve(context, cache_string, &id) != 0) {
255178825Sdfr		krb5_warnx(context, "failed to open kerberos 5 cache '%s'",
256178825Sdfr			   cache_string);
257178825Sdfr		id = NULL;
258178825Sdfr	    }
259178825Sdfr	}
260178825Sdfr	if (id == NULL)
261178825Sdfr	    if(krb5_cc_default(context, &id) != 0)
262178825Sdfr		id = NULL;
263178825Sdfr    }
264120945Snectar#endif
265120945Snectar
266120945Snectar    if (verbose)
267120945Snectar	kafs_set_verbose(log_func, NULL);
268120945Snectar
26955682Smarkm    num = 0;
27055682Smarkm    for(i = 0; i < files.num_strings; i++){
271120945Snectar	afslog_file(files.strings[i]);
27255682Smarkm	num++;
27355682Smarkm    }
274120945Snectar    free_getarg_strings (&files);
27555682Smarkm    for(i = 0; i < cells.num_strings; i++){
276120945Snectar	afslog_cell(cells.strings[i], 1);
27755682Smarkm	num++;
27855682Smarkm    }
279120945Snectar    free_getarg_strings (&cells);
28055682Smarkm    for(i = optind; i < argc; i++){
28155682Smarkm	num++;
28255682Smarkm	if(strcmp(argv[i], ".") == 0 ||
28355682Smarkm	   strcmp(argv[i], "..") == 0 ||
28455682Smarkm	   strchr(argv[i], '/') ||
28555682Smarkm	   access(argv[i], F_OK) == 0)
286120945Snectar	    afslog_file(argv[i]);
28755682Smarkm	else
288120945Snectar	    afslog_cell(argv[i], 1);
289233294Sstas    }
29055682Smarkm    if(num == 0) {
291120945Snectar	if(do_afslog(NULL))
292120945Snectar	    failed++;
293120945Snectar    } else
294120945Snectar	for(p = cell_list; p; p = p->next) {
295120945Snectar	    if(verbose)
296120945Snectar		warnx("Getting tokens for cell \"%s\"", p->cell);
297120945Snectar	    if(do_afslog(p->cell))
298120945Snectar		failed++;
29955682Smarkm    }
30055682Smarkm
301120945Snectar    return failed;
30255682Smarkm}
303