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
xusage()13 xusage()
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
main(int argc,char * argv[])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
do_kcpytkt(int count,char * names[],const char * fromccachestr,char * etypestr,int flags)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