1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <krb5.h> 7 #include "k5-platform.h" 8 9 static char *prog; 10 static int quiet = 0; 11 12 static void 13 xusage(void) 14 { 15 fprintf(stderr, "xusage: %s [-c from_ccache] [-e etype] [-f flags] " 16 "dest_ccache service1 service2 ...\n", prog); 17 exit(1); 18 } 19 20 static void 21 do_kcpytkt(int argc, char *argv[], char *fromccachestr, char *etypestr, 22 int flags); 23 24 int 25 main(int argc, char *argv[]) 26 { 27 int option; 28 char *etypestr = NULL, *fromccachestr = NULL; 29 int flags = 0; 30 31 prog = strrchr(argv[0], '/'); 32 prog = (prog != NULL) ? prog + 1 : argv[0]; 33 34 while ((option = getopt(argc, argv, "c:e:f:hq")) != -1) { 35 switch (option) { 36 case 'c': 37 fromccachestr = optarg; 38 break; 39 case 'e': 40 etypestr = optarg; 41 break; 42 case 'f': 43 flags = atoi(optarg); 44 break; 45 case 'q': 46 quiet = 1; 47 break; 48 case 'h': 49 default: 50 xusage(); 51 break; 52 } 53 } 54 55 if (argc - optind < 2) 56 xusage(); 57 58 do_kcpytkt(argc - optind, argv + optind, fromccachestr, etypestr, flags); 59 return 0; 60 } 61 62 static void 63 do_kcpytkt(int count, char *names[], const char *fromccachestr, char *etypestr, 64 int flags) 65 { 66 krb5_context context; 67 krb5_error_code ret; 68 krb5_enctype etype; 69 krb5_ccache fromccache, destccache; 70 krb5_principal me; 71 krb5_creds in_creds, out_creds; 72 int i, errors, retflags; 73 char *princ; 74 75 ret = krb5_init_context(&context); 76 if (ret) { 77 com_err(prog, ret, "while initializing krb5 library"); 78 exit(1); 79 } 80 if (etypestr != NULL) { 81 ret = krb5_string_to_enctype(etypestr, &etype); 82 if (ret) { 83 com_err(prog, ret, "while converting etype"); 84 exit(1); 85 } 86 retflags = KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES; 87 } else { 88 etype = 0; 89 retflags = KRB5_TC_MATCH_SRV_NAMEONLY; 90 } 91 92 if (fromccachestr != NULL) 93 ret = krb5_cc_resolve(context, fromccachestr, &fromccache); 94 else 95 ret = krb5_cc_default(context, &fromccache); 96 if (ret) { 97 com_err(prog, ret, "while opening source ccache"); 98 exit(1); 99 } 100 101 ret = krb5_cc_get_principal(context, fromccache, &me); 102 if (ret) { 103 com_err(prog, ret, "while getting client principal name"); 104 exit(1); 105 } 106 107 ret = krb5_cc_resolve(context, names[0], &destccache); 108 if (ret) { 109 com_err(prog, ret, "while opening destination cache"); 110 exit(1); 111 } 112 113 errors = 0; 114 115 for (i = 1; i < count; i++) { 116 memset(&in_creds, 0, sizeof(in_creds)); 117 118 in_creds.client = me; 119 120 ret = krb5_parse_name(context, names[i], &in_creds.server); 121 if (ret) { 122 if (!quiet) { 123 fprintf(stderr, "%s: %s while parsing principal name\n", 124 names[i], error_message(ret)); 125 } 126 errors++; 127 continue; 128 } 129 130 ret = krb5_unparse_name(context, in_creds.server, &princ); 131 if (ret) { 132 fprintf(stderr, "%s: %s while printing principal name\n", 133 names[i], error_message(ret)); 134 errors++; 135 continue; 136 } 137 138 in_creds.keyblock.enctype = etype; 139 140 ret = krb5_cc_retrieve_cred(context, fromccache, retflags, 141 &in_creds, &out_creds); 142 if (ret) { 143 fprintf(stderr, "%s: %s while retrieving credentials\n", 144 princ, error_message(ret)); 145 krb5_free_unparsed_name(context, princ); 146 errors++; 147 continue; 148 } 149 150 ret = krb5_cc_store_cred(context, destccache, &out_creds); 151 krb5_free_principal(context, in_creds.server); 152 if (ret) { 153 fprintf(stderr, "%s: %s while removing credentials\n", 154 princ, error_message(ret)); 155 krb5_free_cred_contents(context, &out_creds); 156 krb5_free_unparsed_name(context, princ); 157 errors++; 158 continue; 159 } 160 161 krb5_free_unparsed_name(context, princ); 162 krb5_free_cred_contents(context, &out_creds); 163 } 164 165 krb5_free_principal(context, me); 166 krb5_cc_close(context, fromccache); 167 krb5_cc_close(context, destccache); 168 krb5_free_context(context); 169 170 if (errors) 171 exit(1); 172 173 exit(0); 174 } 175