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 } 303