s4:torture: Adapt KDC canon test to Heimdal upstream changes
[metze/samba/wip.git] / source4 / 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$");
37 #endif
38 #include <ctype.h>
39 #ifdef KRB5
40 #include <krb5.h>
41 #endif
42 #include <kafs.h>
43 #include <roken.h>
44 #include <getarg.h>
45 #include <err.h>
46
47 static int help_flag;
48 static int version_flag;
49 static getarg_strings cells;
50 static char *realm;
51 static getarg_strings files;
52 static int unlog_flag;
53 static int verbose;
54 #ifdef KRB5
55 static char *client_string;
56 static char *cache_string;
57 static int use_krb5 = 1;
58 #endif
59
60 struct getargs args[] = {
61     { "cell",   'c', arg_strings, &cells, "cells to get tokens for", "cell" },
62     { "file",   'p', arg_strings, &files, "files to get tokens for", "path" },
63     { "realm",  'k', arg_string, &realm, "realm for afs cell", "realm" },
64     { "unlog",  'u', arg_flag, &unlog_flag, "remove tokens", NULL },
65 #ifdef KRB5
66     { "principal",'P',arg_string,&client_string,"principal to use","principal"},
67     { "cache",   0,  arg_string, &cache_string, "ccache to use", "cache"},
68     { "v5",      0,  arg_negative_flag, &use_krb5, "don't use Kerberos 5",
69       NULL },
70 #endif
71     { "verbose",'v', arg_flag, &verbose, NULL, NULL },
72     { "version", 0,  arg_flag, &version_flag, NULL, NULL },
73     { "help",   'h', arg_flag, &help_flag, NULL, NULL },
74 };
75
76 static int num_args = sizeof(args) / sizeof(args[0]);
77
78 #ifdef KRB5
79 krb5_context context;
80 krb5_ccache id;
81 #endif
82
83 static const char *
84 expand_one_file(FILE *f, const char *cell)
85 {
86     static char buf[1024];
87     char *p;
88
89     while (fgets (buf, sizeof(buf), f) != NULL) {
90         if(buf[0] == '>') {
91             for(p = buf; *p && !isspace((unsigned char)*p) && *p != '#'; p++)
92                 ;
93             *p = '\0';
94             if(strncmp(buf + 1, cell, strlen(cell)) == 0)
95                 return buf + 1;
96         }
97         buf[0] = '\0';
98     }
99     return NULL;
100 }
101
102 static const char *
103 expand_cell_name(const char *cell)
104 {
105     FILE *f;
106     const char *c;
107     const char **fn, *fns[] = { _PATH_CELLSERVDB,
108                                 _PATH_ARLA_CELLSERVDB,
109                                 _PATH_OPENAFS_DEBIAN_CELLSERVDB,
110                                 _PATH_ARLA_DEBIAN_CELLSERVDB,
111                                 NULL };
112     for(fn = fns; *fn; fn++) {
113         f = fopen(*fn, "r");
114         if(f == NULL)
115             continue;
116         c = expand_one_file(f, cell);
117         fclose(f);
118         if(c)
119             return c;
120     }
121     return cell;
122 }
123
124 static void
125 usage(int ecode)
126 {
127     arg_printusage(args, num_args, NULL, "[cell|path]...");
128     exit(ecode);
129 }
130
131 struct cell_list {
132     char *cell;
133     struct cell_list *next;
134 } *cell_list;
135
136 static int
137 afslog_cell(const char *cell, int expand)
138 {
139     struct cell_list *p, **q;
140     const char *c = cell;
141     if(expand){
142         c = expand_cell_name(cell);
143         if(c == NULL){
144             warnx("No cell matching \"%s\" found.", cell);
145             return -1;
146         }
147         if(verbose && strcmp(c, cell) != 0)
148             warnx("Cell \"%s\" expanded to \"%s\"", cell, c);
149     }
150     /* add to list of cells to get tokens for, and also remove
151        duplicates; the actual afslog takes place later */
152     for(p = cell_list, q = &cell_list; p; q = &p->next, p = p->next)
153         if(strcmp(p->cell, c) == 0)
154             return 0;
155     p = malloc(sizeof(*p));
156     if(p == NULL)
157         return -1;
158     p->cell = strdup(c);
159     if(p->cell == NULL) {
160         free(p);
161         return -1;
162     }
163     p->next = NULL;
164     *q = p;
165     return 0;
166 }
167
168 static int
169 afslog_file(const char *path)
170 {
171     char cell[64];
172     if(k_afs_cell_of_file(path, cell, sizeof(cell))){
173         warnx("No cell found for file \"%s\".", path);
174         return -1;
175     }
176     if(verbose)
177         warnx("File \"%s\" lives in cell \"%s\"", path, cell);
178     return afslog_cell(cell, 0);
179 }
180
181 static int
182 do_afslog(const char *cell)
183 {
184     int k5ret;
185
186     k5ret = 0;
187
188 #ifdef KRB5
189     if(context != NULL && id != NULL && use_krb5) {
190         k5ret = krb5_afslog(context, id, cell, realm);
191         if(k5ret == 0)
192             return 0;
193     }
194 #endif
195     if (cell == NULL)
196         cell = "<default cell>";
197 #ifdef KRB5
198     if (k5ret)
199         krb5_warn(context, k5ret, "krb5_afslog(%s)", cell);
200 #endif
201     if (k5ret)
202         return 1;
203     return 0;
204 }
205
206 static void
207 log_func(void *ctx, const char *str)
208 {
209     fprintf(stderr, "%s\n", str);
210 }
211
212 int
213 main(int argc, char **argv)
214 {
215     int optidx = 0;
216     int i;
217     int num;
218     int ret = 0;
219     int failed = 0;
220     struct cell_list *p;
221
222     setprogname(argv[0]);
223
224     if(getarg(args, num_args, argc, argv, &optidx))
225         usage(1);
226     if(help_flag)
227         usage(0);
228     if(version_flag) {
229         print_version(NULL);
230         exit(0);
231     }
232
233     if(!k_hasafs())
234         errx(1, "AFS does not seem to be present on this machine");
235
236     if(unlog_flag){
237         k_unlog();
238         exit(0);
239     }
240 #ifdef KRB5
241     ret = krb5_init_context(&context);
242     if (ret) {
243         context = NULL;
244     } else {
245         if (client_string) {
246             krb5_principal client;
247
248             ret = krb5_parse_name(context, client_string, &client);
249             if (ret == 0)
250                 ret = krb5_cc_cache_match(context, client, &id);
251             if (ret)
252                 id = NULL;
253         }
254         if (id == NULL && cache_string) {
255             if(krb5_cc_resolve(context, cache_string, &id) != 0) {
256                 krb5_warnx(context, "failed to open kerberos 5 cache '%s'",
257                            cache_string);
258                 id = NULL;
259             }
260         }
261         if (id == NULL)
262             if(krb5_cc_default(context, &id) != 0)
263                 id = NULL;
264     }
265 #endif
266
267     if (verbose)
268         kafs_set_verbose(log_func, NULL);
269
270     num = 0;
271     for(i = 0; i < files.num_strings; i++){
272         afslog_file(files.strings[i]);
273         num++;
274     }
275     free_getarg_strings (&files);
276     for(i = 0; i < cells.num_strings; i++){
277         afslog_cell(cells.strings[i], 1);
278         num++;
279     }
280     free_getarg_strings (&cells);
281     for(i = optidx; i < argc; i++){
282         num++;
283         if(strcmp(argv[i], ".") == 0 ||
284            strcmp(argv[i], "..") == 0 ||
285            strchr(argv[i], '/') ||
286            access(argv[i], F_OK) == 0)
287             afslog_file(argv[i]);
288         else
289             afslog_cell(argv[i], 1);
290     }
291     if(num == 0) {
292         if(do_afslog(NULL))
293             failed++;
294     } else
295         for(p = cell_list; p; p = p->next) {
296             if(verbose)
297                 warnx("Getting tokens for cell \"%s\"", p->cell);
298             if(do_afslog(p->cell))
299                 failed++;
300     }
301
302     return failed;
303 }