Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/appl/kf/kf.c
34889 views
1
/*
2
* Copyright (c) 1997 - 2000, 2002 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
#include "kf_locl.h"
35
RCSID("$Id$");
36
37
krb5_context context;
38
static int help_flag;
39
static int version_flag;
40
static char *port_str;
41
const char *service = KF_SERVICE;
42
const char *remote_name = NULL;
43
int forwardable = 0;
44
const char *ccache_name = NULL;
45
46
static struct getargs args[] = {
47
{ "port", 'p', arg_string, &port_str, "port to connect to", "port" },
48
{ "login", 'l',arg_string, &remote_name,"remote login name","login"},
49
{ "ccache", 'c',arg_string, &ccache_name, "remote cred cache","ccache"},
50
{ "forwardable",'F',arg_flag,&forwardable,
51
"Forward forwardable credentials", NULL },
52
{ "forwardable",'G',arg_negative_flag,&forwardable,
53
"Don't forward forwardable credentials", NULL },
54
{ "help", 'h', arg_flag, &help_flag },
55
{ "version", 0, arg_flag, &version_flag }
56
};
57
58
static int num_args = sizeof(args) / sizeof(args[0]);
59
60
static void
61
usage(int code, struct getargs *args, int num_args)
62
{
63
arg_printusage(args, num_args, NULL, "hosts");
64
exit(code);
65
}
66
67
static int
68
client_setup(krb5_context *context, int *argc, char **argv)
69
{
70
int optind = 0;
71
int port = 0;
72
int status;
73
74
setprogname (argv[0]);
75
76
status = krb5_init_context (context);
77
if (status)
78
errx(1, "krb5_init_context failed: %d", status);
79
80
forwardable = krb5_config_get_bool (*context, NULL,
81
"libdefaults",
82
"forwardable",
83
NULL);
84
85
if (getarg (args, num_args, *argc, argv, &optind))
86
usage(1, args, num_args);
87
88
if(help_flag)
89
usage (0, args, num_args);
90
if(version_flag) {
91
print_version(NULL);
92
exit(0);
93
}
94
95
if(port_str) {
96
struct servent *s = roken_getservbyname(port_str, "tcp");
97
if(s)
98
port = s->s_port;
99
else {
100
char *ptr;
101
102
port = strtol (port_str, &ptr, 10);
103
if (port == 0 && ptr == port_str)
104
errx (1, "Bad port `%s'", port_str);
105
port = htons(port);
106
}
107
}
108
109
if (port == 0)
110
port = krb5_getportbyname (*context, KF_PORT_NAME, "tcp", KF_PORT_NUM);
111
112
if(*argc - optind < 1)
113
usage(1, args, num_args);
114
*argc = optind;
115
116
return port;
117
}
118
119
/*
120
* forward creds to `hostname'/`service' over `sock'
121
* return 0 iff OK
122
*/
123
124
static int
125
proto (int sock, const char *hostname, const char *service,
126
char *message, size_t len)
127
{
128
krb5_auth_context auth_context;
129
krb5_error_code status;
130
krb5_principal server;
131
krb5_data data;
132
krb5_data data_send;
133
134
krb5_ccache ccache;
135
krb5_creds creds;
136
krb5_kdc_flags flags;
137
krb5_principal principal;
138
139
status = krb5_auth_con_init (context, &auth_context);
140
if (status) {
141
krb5_warn (context, status, "krb5_auth_con_init");
142
return 1;
143
}
144
145
status = krb5_auth_con_setaddrs_from_fd (context,
146
auth_context,
147
&sock);
148
if (status) {
149
krb5_auth_con_free(context, auth_context);
150
krb5_warn (context, status, "krb5_auth_con_setaddr");
151
return 1;
152
}
153
154
status = krb5_sname_to_principal (context,
155
hostname,
156
service,
157
KRB5_NT_SRV_HST,
158
&server);
159
if (status) {
160
krb5_auth_con_free(context, auth_context);
161
krb5_warn (context, status, "krb5_sname_to_principal");
162
return 1;
163
}
164
165
status = krb5_sendauth (context,
166
&auth_context,
167
&sock,
168
KF_VERSION_1,
169
NULL,
170
server,
171
AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
172
NULL,
173
NULL,
174
NULL,
175
NULL,
176
NULL,
177
NULL);
178
if (status) {
179
krb5_auth_con_free(context, auth_context);
180
krb5_warn(context, status, "krb5_sendauth");
181
return 1;
182
}
183
184
if (ccache_name == NULL)
185
ccache_name = "";
186
187
data_send.data = (void *)remote_name;
188
data_send.length = strlen(remote_name) + 1;
189
status = krb5_write_priv_message(context, auth_context, &sock, &data_send);
190
if (status) {
191
krb5_auth_con_free(context, auth_context);
192
krb5_warn (context, status, "krb5_write_message");
193
return 1;
194
}
195
data_send.data = (void *)ccache_name;
196
data_send.length = strlen(ccache_name)+1;
197
status = krb5_write_priv_message(context, auth_context, &sock, &data_send);
198
if (status) {
199
krb5_auth_con_free(context, auth_context);
200
krb5_warn (context, status, "krb5_write_message");
201
return 1;
202
}
203
204
memset (&creds, 0, sizeof(creds));
205
206
status = krb5_cc_default (context, &ccache);
207
if (status) {
208
krb5_auth_con_free(context, auth_context);
209
krb5_warn (context, status, "krb5_cc_default");
210
return 1;
211
}
212
213
status = krb5_cc_get_principal (context, ccache, &principal);
214
if (status) {
215
krb5_auth_con_free(context, auth_context);
216
krb5_warn (context, status, "krb5_cc_get_principal");
217
return 1;
218
}
219
220
creds.client = principal;
221
222
status = krb5_make_principal (context,
223
&creds.server,
224
principal->realm,
225
KRB5_TGS_NAME,
226
principal->realm,
227
NULL);
228
229
if (status) {
230
krb5_auth_con_free(context, auth_context);
231
krb5_warn (context, status, "krb5_make_principal");
232
return 1;
233
}
234
235
creds.times.endtime = 0;
236
237
flags.i = 0;
238
flags.b.forwarded = 1;
239
flags.b.forwardable = forwardable;
240
241
status = krb5_get_forwarded_creds (context,
242
auth_context,
243
ccache,
244
flags.i,
245
hostname,
246
&creds,
247
&data);
248
if (status) {
249
krb5_auth_con_free(context, auth_context);
250
krb5_warn (context, status, "krb5_get_forwarded_creds");
251
return 1;
252
}
253
254
status = krb5_write_priv_message(context, auth_context, &sock, &data);
255
256
if (status) {
257
krb5_auth_con_free(context, auth_context);
258
krb5_warn (context, status, "krb5_mk_priv");
259
return 1;
260
}
261
262
krb5_data_free (&data);
263
264
status = krb5_read_priv_message(context, auth_context, &sock, &data);
265
krb5_auth_con_free(context, auth_context);
266
if (status) {
267
krb5_warn (context, status, "krb5_mk_priv");
268
return 1;
269
}
270
if(data.length >= len) {
271
krb5_warnx (context, "returned string is too long, truncating");
272
memcpy(message, data.data, len);
273
message[len - 1] = '\0';
274
} else {
275
memcpy(message, data.data, data.length);
276
message[data.length] = '\0';
277
}
278
krb5_data_free (&data);
279
280
return(strcmp(message, "ok"));
281
}
282
283
static int
284
doit (const char *hostname, int port, const char *service,
285
char *message, size_t len)
286
{
287
struct addrinfo *ai, *a;
288
struct addrinfo hints;
289
int error;
290
char portstr[NI_MAXSERV];
291
292
memset (&hints, 0, sizeof(hints));
293
hints.ai_socktype = SOCK_STREAM;
294
hints.ai_protocol = IPPROTO_TCP;
295
296
snprintf (portstr, sizeof(portstr), "%u", ntohs(port));
297
298
error = getaddrinfo (hostname, portstr, &hints, &ai);
299
if (error) {
300
errx (1, "getaddrinfo(%s): %s", hostname, gai_strerror(error));
301
}
302
303
for (a = ai; a != NULL; a = a->ai_next) {
304
int s;
305
306
s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
307
if (s < 0)
308
continue;
309
if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
310
warn ("connect(%s)", hostname);
311
close (s);
312
continue;
313
}
314
freeaddrinfo (ai);
315
return proto (s, hostname, service, message, len);
316
}
317
warnx ("failed to contact %s", hostname);
318
freeaddrinfo (ai);
319
return 1;
320
}
321
322
int
323
main(int argc, char **argv)
324
{
325
int argcc,port,i;
326
int ret=0;
327
328
argcc = argc;
329
port = client_setup(&context, &argcc, argv);
330
331
if (remote_name == NULL) {
332
remote_name = get_default_username ();
333
if (remote_name == NULL)
334
errx (1, "who are you?");
335
}
336
337
for (i = argcc;i < argc; i++) {
338
char message[128];
339
ret = doit (argv[i], port, service, message, sizeof(message));
340
if(ret == 0)
341
warnx ("%s: ok", argv[i]);
342
else
343
warnx ("%s: failed: %s", argv[i], message);
344
}
345
return(ret);
346
}
347
348