]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - crypto/heimdal/appl/afsutil/afslog.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / crypto / heimdal / appl / afsutil / afslog.c
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 }