Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/appl/sample/sclient/sclient.c
34889 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* appl/sample/sclient/sclient.c */
3
/*
4
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
5
* All Rights Reserved.
6
*
7
* Export of this software from the United States of America may
8
* require a specific license from the United States Government.
9
* It is the responsibility of any person or organization contemplating
10
* export to obtain such a license before exporting.
11
*
12
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
* distribute this software and its documentation for any purpose and
14
* without fee is hereby granted, provided that the above copyright
15
* notice appear in all copies and that both that copyright notice and
16
* this permission notice appear in supporting documentation, and that
17
* the name of M.I.T. not be used in advertising or publicity pertaining
18
* to distribution of the software without specific, written prior
19
* permission. Furthermore if you modify this software you must label
20
* your software as modified software and not distribute it in such a
21
* fashion that it might be confused with the original M.I.T. software.
22
* M.I.T. makes no representations about the suitability of
23
* this software for any purpose. It is provided "as is" without express
24
* or implied warranty.
25
*/
26
27
/*
28
*
29
* Sample Kerberos v5 client.
30
*
31
* Usage: sample_client hostname
32
*/
33
34
#include "krb5.h"
35
#include "com_err.h"
36
37
#include <stdio.h>
38
#include <string.h>
39
#include <ctype.h>
40
#include <errno.h>
41
42
#include <sys/types.h>
43
#include <sys/socket.h>
44
#include <netinet/in.h>
45
#include <netdb.h>
46
#include "fake-addrinfo.h" /* not everyone implements getaddrinfo yet */
47
48
#include <signal.h>
49
50
#ifdef HAVE_UNISTD_H
51
#include <unistd.h>
52
#endif
53
54
#include <stdlib.h>
55
56
#include "../sample.h"
57
58
#ifndef GETSOCKNAME_ARG3_TYPE
59
#define GETSOCKNAME_ARG3_TYPE int
60
#endif
61
62
static int
63
net_read(int fd, char *buf, int len)
64
{
65
int cc, len2 = 0;
66
67
do {
68
cc = SOCKET_READ((SOCKET)fd, buf, len);
69
if (cc < 0) {
70
if (SOCKET_ERRNO == SOCKET_EINTR)
71
continue;
72
73
/* XXX this interface sucks! */
74
errno = SOCKET_ERRNO;
75
76
return(cc); /* errno is already set */
77
}
78
else if (cc == 0) {
79
return(len2);
80
} else {
81
buf += cc;
82
len2 += cc;
83
len -= cc;
84
}
85
} while (len > 0);
86
return(len2);
87
}
88
89
int
90
main(int argc, char *argv[])
91
{
92
struct addrinfo *ap, aihints, *apstart;
93
int aierr;
94
int sock;
95
krb5_context context;
96
krb5_data recv_data;
97
krb5_data cksum_data;
98
krb5_error_code retval;
99
krb5_ccache ccdef;
100
krb5_principal client, server;
101
krb5_error *err_ret;
102
krb5_ap_rep_enc_part *rep_ret;
103
krb5_auth_context auth_context = 0;
104
short xmitlen;
105
char *portstr;
106
char *service = SAMPLE_SERVICE;
107
108
if (argc != 2 && argc != 3 && argc != 4) {
109
fprintf(stderr, "usage: %s <hostname> [port] [service]\n",argv[0]);
110
exit(1);
111
}
112
113
retval = krb5_init_context(&context);
114
if (retval) {
115
com_err(argv[0], retval, "while initializing krb5");
116
exit(1);
117
}
118
119
(void) signal(SIGPIPE, SIG_IGN);
120
121
if (argc > 2)
122
portstr = argv[2];
123
else
124
portstr = SAMPLE_PORT;
125
126
memset(&aihints, 0, sizeof(aihints));
127
aihints.ai_socktype = SOCK_STREAM;
128
aihints.ai_flags = AI_ADDRCONFIG;
129
aierr = getaddrinfo(argv[1], portstr, &aihints, &ap);
130
if (aierr) {
131
fprintf(stderr, "%s: error looking up host '%s' port '%s'/tcp: %s\n",
132
argv[0], argv[1], portstr, gai_strerror(aierr));
133
exit(1);
134
}
135
if (ap == 0) {
136
/* Should never happen. */
137
fprintf(stderr, "%s: error looking up host '%s' port '%s'/tcp: no addresses returned?\n",
138
argv[0], argv[1], portstr);
139
exit(1);
140
}
141
142
if (argc > 3) {
143
service = argv[3];
144
}
145
146
retval = krb5_sname_to_principal(context, argv[1], service,
147
KRB5_NT_SRV_HST, &server);
148
if (retval) {
149
com_err(argv[0], retval, "while creating server name for host %s service %s",
150
argv[1], service);
151
exit(1);
152
}
153
154
/* set up the address of the foreign socket for connect() */
155
apstart = ap; /* For freeing later */
156
for (sock = -1; ap && sock == -1; ap = ap->ai_next) {
157
char abuf[NI_MAXHOST], pbuf[NI_MAXSERV];
158
char mbuf[NI_MAXHOST + NI_MAXSERV + 64];
159
if (getnameinfo(ap->ai_addr, ap->ai_addrlen, abuf, sizeof(abuf),
160
pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
161
memset(abuf, 0, sizeof(abuf));
162
memset(pbuf, 0, sizeof(pbuf));
163
strncpy(abuf, "[error, cannot print address?]",
164
sizeof(abuf)-1);
165
strncpy(pbuf, "[?]", sizeof(pbuf)-1);
166
}
167
memset(mbuf, 0, sizeof(mbuf));
168
strncpy(mbuf, "error contacting ", sizeof(mbuf)-1);
169
strncat(mbuf, abuf, sizeof(mbuf) - strlen(mbuf) - 1);
170
strncat(mbuf, " port ", sizeof(mbuf) - strlen(mbuf) - 1);
171
strncat(mbuf, pbuf, sizeof(mbuf) - strlen(mbuf) - 1);
172
sock = socket(ap->ai_family, SOCK_STREAM, 0);
173
if (sock < 0) {
174
fprintf(stderr, "%s: socket: %s\n", mbuf, strerror(errno));
175
continue;
176
}
177
if (connect(sock, ap->ai_addr, ap->ai_addrlen) < 0) {
178
fprintf(stderr, "%s: connect: %s\n", mbuf, strerror(errno));
179
close(sock);
180
sock = -1;
181
continue;
182
}
183
/* connected, yay! */
184
}
185
if (sock == -1)
186
/* Already printed error message above. */
187
exit(1);
188
printf("connected\n");
189
190
cksum_data.data = argv[1];
191
cksum_data.length = strlen(argv[1]);
192
193
retval = krb5_cc_default(context, &ccdef);
194
if (retval) {
195
com_err(argv[0], retval, "while getting default ccache");
196
exit(1);
197
}
198
199
retval = krb5_cc_get_principal(context, ccdef, &client);
200
if (retval) {
201
com_err(argv[0], retval, "while getting client principal name");
202
exit(1);
203
}
204
retval = krb5_sendauth(context, &auth_context, (krb5_pointer) &sock,
205
SAMPLE_VERSION, client, server,
206
AP_OPTS_MUTUAL_REQUIRED,
207
&cksum_data,
208
0, /* no creds, use ccache instead */
209
ccdef, &err_ret, &rep_ret, NULL);
210
211
krb5_free_principal(context, server); /* finished using it */
212
krb5_free_principal(context, client);
213
krb5_cc_close(context, ccdef);
214
if (auth_context) krb5_auth_con_free(context, auth_context);
215
216
if (retval && retval != KRB5_SENDAUTH_REJECTED) {
217
com_err(argv[0], retval, "while using sendauth");
218
exit(1);
219
}
220
if (retval == KRB5_SENDAUTH_REJECTED) {
221
/* got an error */
222
printf("sendauth rejected, error reply is:\n\t\"%*s\"\n",
223
err_ret->text.length, err_ret->text.data);
224
} else if (rep_ret) {
225
/* got a reply */
226
krb5_free_ap_rep_enc_part(context, rep_ret);
227
228
printf("sendauth succeeded, reply is:\n");
229
if ((retval = net_read(sock, (char *)&xmitlen,
230
sizeof(xmitlen))) <= 0) {
231
if (retval == 0)
232
errno = ECONNABORTED;
233
com_err(argv[0], errno, "while reading data from server");
234
exit(1);
235
}
236
recv_data.length = ntohs(xmitlen);
237
if (!(recv_data.data = (char *)malloc((size_t) recv_data.length + 1))) {
238
com_err(argv[0], ENOMEM,
239
"while allocating buffer to read from server");
240
exit(1);
241
}
242
if ((retval = net_read(sock, (char *)recv_data.data,
243
recv_data.length)) <= 0) {
244
if (retval == 0)
245
errno = ECONNABORTED;
246
com_err(argv[0], errno, "while reading data from server");
247
exit(1);
248
}
249
recv_data.data[recv_data.length] = '\0';
250
printf("reply len %d, contents:\n%s\n",
251
recv_data.length,recv_data.data);
252
free(recv_data.data);
253
} else {
254
com_err(argv[0], 0, "no error or reply from sendauth!");
255
exit(1);
256
}
257
freeaddrinfo(apstart);
258
krb5_free_context(context);
259
exit(0);
260
}
261
262