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