xref: /freebsd/crypto/krb5/src/clients/kcpytkt/kcpytkt.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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