1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* appl/simple/client/sim_client.c */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright 1989,1991 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert * All Rights Reserved.
6*7f2fe78bSCy Schubert *
7*7f2fe78bSCy Schubert * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert * require a specific license from the United States Government.
9*7f2fe78bSCy Schubert * It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert * export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert *
12*7f2fe78bSCy Schubert * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert * permission. Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert * this software for any purpose. It is provided "as is" without express
24*7f2fe78bSCy Schubert * or implied warranty.
25*7f2fe78bSCy Schubert */
26*7f2fe78bSCy Schubert
27*7f2fe78bSCy Schubert /*
28*7f2fe78bSCy Schubert * Simple UDP-based sample client program. For demonstration.
29*7f2fe78bSCy Schubert * This program performs no useful function.
30*7f2fe78bSCy Schubert */
31*7f2fe78bSCy Schubert
32*7f2fe78bSCy Schubert #include <krb5.h>
33*7f2fe78bSCy Schubert #include "com_err.h"
34*7f2fe78bSCy Schubert
35*7f2fe78bSCy Schubert #include <sys/types.h>
36*7f2fe78bSCy Schubert #include <sys/socket.h>
37*7f2fe78bSCy Schubert #include <netinet/in.h>
38*7f2fe78bSCy Schubert #include <stdio.h>
39*7f2fe78bSCy Schubert #include <string.h>
40*7f2fe78bSCy Schubert #include <errno.h>
41*7f2fe78bSCy Schubert #include <netdb.h>
42*7f2fe78bSCy Schubert #include <unistd.h>
43*7f2fe78bSCy Schubert
44*7f2fe78bSCy Schubert #include "simple.h"
45*7f2fe78bSCy Schubert
46*7f2fe78bSCy Schubert /* for old Unixes and friends ... */
47*7f2fe78bSCy Schubert #ifndef MAXHOSTNAMELEN
48*7f2fe78bSCy Schubert #define MAXHOSTNAMELEN 64
49*7f2fe78bSCy Schubert #endif
50*7f2fe78bSCy Schubert
51*7f2fe78bSCy Schubert #define MSG "hi there!" /* message text */
52*7f2fe78bSCy Schubert
53*7f2fe78bSCy Schubert void usage (char *);
54*7f2fe78bSCy Schubert
55*7f2fe78bSCy Schubert void
usage(char * name)56*7f2fe78bSCy Schubert usage(char *name)
57*7f2fe78bSCy Schubert {
58*7f2fe78bSCy Schubert fprintf(stderr, "usage: %s [-p port] [-h host] [-m message] [-s service] [host]\n", name);
59*7f2fe78bSCy Schubert }
60*7f2fe78bSCy Schubert
61*7f2fe78bSCy Schubert int
main(int argc,char * argv[])62*7f2fe78bSCy Schubert main(int argc, char *argv[])
63*7f2fe78bSCy Schubert {
64*7f2fe78bSCy Schubert int sock, i;
65*7f2fe78bSCy Schubert socklen_t len;
66*7f2fe78bSCy Schubert int flags = 0; /* flags for sendto() */
67*7f2fe78bSCy Schubert struct servent *serv;
68*7f2fe78bSCy Schubert struct hostent *host;
69*7f2fe78bSCy Schubert #ifdef BROKEN_STREAMS_SOCKETS
70*7f2fe78bSCy Schubert char my_hostname[MAXHOSTNAMELEN];
71*7f2fe78bSCy Schubert #endif
72*7f2fe78bSCy Schubert struct sockaddr_in s_sock; /* server address */
73*7f2fe78bSCy Schubert struct sockaddr_in c_sock; /* client address */
74*7f2fe78bSCy Schubert extern int opterr, optind;
75*7f2fe78bSCy Schubert extern char * optarg;
76*7f2fe78bSCy Schubert int ch;
77*7f2fe78bSCy Schubert
78*7f2fe78bSCy Schubert short port = 0;
79*7f2fe78bSCy Schubert char *message = MSG;
80*7f2fe78bSCy Schubert char *hostname = 0;
81*7f2fe78bSCy Schubert char *service = SIMPLE_SERVICE;
82*7f2fe78bSCy Schubert char *progname = 0;
83*7f2fe78bSCy Schubert
84*7f2fe78bSCy Schubert krb5_error_code retval;
85*7f2fe78bSCy Schubert krb5_data packet, inbuf;
86*7f2fe78bSCy Schubert krb5_ccache ccdef;
87*7f2fe78bSCy Schubert krb5_address addr;
88*7f2fe78bSCy Schubert
89*7f2fe78bSCy Schubert krb5_context context;
90*7f2fe78bSCy Schubert krb5_auth_context auth_context = NULL;
91*7f2fe78bSCy Schubert
92*7f2fe78bSCy Schubert retval = krb5_init_context(&context);
93*7f2fe78bSCy Schubert if (retval) {
94*7f2fe78bSCy Schubert com_err(argv[0], retval, "while initializing krb5");
95*7f2fe78bSCy Schubert exit(1);
96*7f2fe78bSCy Schubert }
97*7f2fe78bSCy Schubert
98*7f2fe78bSCy Schubert progname = argv[0];
99*7f2fe78bSCy Schubert
100*7f2fe78bSCy Schubert /*
101*7f2fe78bSCy Schubert * Parse command line arguments
102*7f2fe78bSCy Schubert *
103*7f2fe78bSCy Schubert */
104*7f2fe78bSCy Schubert opterr = 0;
105*7f2fe78bSCy Schubert while ((ch = getopt(argc, argv, "p:m:h:s:")) != -1)
106*7f2fe78bSCy Schubert switch (ch) {
107*7f2fe78bSCy Schubert case 'p':
108*7f2fe78bSCy Schubert port = atoi(optarg);
109*7f2fe78bSCy Schubert break;
110*7f2fe78bSCy Schubert case 'm':
111*7f2fe78bSCy Schubert message = optarg;
112*7f2fe78bSCy Schubert break;
113*7f2fe78bSCy Schubert case 'h':
114*7f2fe78bSCy Schubert hostname = optarg;
115*7f2fe78bSCy Schubert break;
116*7f2fe78bSCy Schubert case 's':
117*7f2fe78bSCy Schubert service = optarg;
118*7f2fe78bSCy Schubert break;
119*7f2fe78bSCy Schubert case '?':
120*7f2fe78bSCy Schubert default:
121*7f2fe78bSCy Schubert usage(progname);
122*7f2fe78bSCy Schubert exit(1);
123*7f2fe78bSCy Schubert break;
124*7f2fe78bSCy Schubert }
125*7f2fe78bSCy Schubert argc -= optind;
126*7f2fe78bSCy Schubert argv += optind;
127*7f2fe78bSCy Schubert if (argc > 0) {
128*7f2fe78bSCy Schubert if (hostname)
129*7f2fe78bSCy Schubert usage(progname);
130*7f2fe78bSCy Schubert hostname = argv[0];
131*7f2fe78bSCy Schubert }
132*7f2fe78bSCy Schubert
133*7f2fe78bSCy Schubert if (hostname == 0) {
134*7f2fe78bSCy Schubert fprintf(stderr, "You must specify a hostname to contact.\n\n");
135*7f2fe78bSCy Schubert usage(progname);
136*7f2fe78bSCy Schubert exit(1);
137*7f2fe78bSCy Schubert }
138*7f2fe78bSCy Schubert
139*7f2fe78bSCy Schubert /* Look up server host */
140*7f2fe78bSCy Schubert if ((host = gethostbyname(hostname)) == (struct hostent *) 0) {
141*7f2fe78bSCy Schubert fprintf(stderr, "%s: unknown host\n", hostname);
142*7f2fe78bSCy Schubert exit(1);
143*7f2fe78bSCy Schubert }
144*7f2fe78bSCy Schubert
145*7f2fe78bSCy Schubert /* Set server's address */
146*7f2fe78bSCy Schubert (void) memset(&s_sock, 0, sizeof(s_sock));
147*7f2fe78bSCy Schubert
148*7f2fe78bSCy Schubert memcpy(&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr));
149*7f2fe78bSCy Schubert #ifdef DEBUG
150*7f2fe78bSCy Schubert printf("s_sock.sin_addr is %s\n", inet_ntoa(s_sock.sin_addr));
151*7f2fe78bSCy Schubert #endif
152*7f2fe78bSCy Schubert s_sock.sin_family = AF_INET;
153*7f2fe78bSCy Schubert
154*7f2fe78bSCy Schubert if (port == 0) {
155*7f2fe78bSCy Schubert /* Look up service */
156*7f2fe78bSCy Schubert if ((serv = getservbyname(SIMPLE_PORT, "udp")) == NULL) {
157*7f2fe78bSCy Schubert fprintf(stderr, "service unknown: %s/udp\n", SIMPLE_PORT);
158*7f2fe78bSCy Schubert exit(1);
159*7f2fe78bSCy Schubert }
160*7f2fe78bSCy Schubert s_sock.sin_port = serv->s_port;
161*7f2fe78bSCy Schubert } else {
162*7f2fe78bSCy Schubert s_sock.sin_port = htons(port);
163*7f2fe78bSCy Schubert }
164*7f2fe78bSCy Schubert
165*7f2fe78bSCy Schubert /* Open a socket */
166*7f2fe78bSCy Schubert if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
167*7f2fe78bSCy Schubert com_err(progname, errno, "opening datagram socket");
168*7f2fe78bSCy Schubert exit(1);
169*7f2fe78bSCy Schubert }
170*7f2fe78bSCy Schubert
171*7f2fe78bSCy Schubert memset(&c_sock, 0, sizeof(c_sock));
172*7f2fe78bSCy Schubert c_sock.sin_family = AF_INET;
173*7f2fe78bSCy Schubert #ifdef BROKEN_STREAMS_SOCKETS
174*7f2fe78bSCy Schubert if (gethostname(my_hostname, sizeof(my_hostname)) < 0) {
175*7f2fe78bSCy Schubert perror("gethostname");
176*7f2fe78bSCy Schubert exit(1);
177*7f2fe78bSCy Schubert }
178*7f2fe78bSCy Schubert
179*7f2fe78bSCy Schubert if ((host = gethostbyname(my_hostname)) == (struct hostent *)0) {
180*7f2fe78bSCy Schubert fprintf(stderr, "%s: unknown host\n", hostname);
181*7f2fe78bSCy Schubert exit(1);
182*7f2fe78bSCy Schubert }
183*7f2fe78bSCy Schubert memcpy(&c_sock.sin_addr, host->h_addr, sizeof(c_sock.sin_addr));
184*7f2fe78bSCy Schubert #endif
185*7f2fe78bSCy Schubert
186*7f2fe78bSCy Schubert
187*7f2fe78bSCy Schubert /* Bind it to set the address; kernel will fill in port # */
188*7f2fe78bSCy Schubert if (bind(sock, (struct sockaddr *)&c_sock, sizeof(c_sock)) < 0) {
189*7f2fe78bSCy Schubert com_err(progname, errno, "while binding datagram socket");
190*7f2fe78bSCy Schubert exit(1);
191*7f2fe78bSCy Schubert }
192*7f2fe78bSCy Schubert
193*7f2fe78bSCy Schubert /* PREPARE KRB_AP_REQ MESSAGE */
194*7f2fe78bSCy Schubert
195*7f2fe78bSCy Schubert inbuf.data = hostname;
196*7f2fe78bSCy Schubert inbuf.length = strlen(hostname);
197*7f2fe78bSCy Schubert
198*7f2fe78bSCy Schubert /* Get credentials for server */
199*7f2fe78bSCy Schubert if ((retval = krb5_cc_default(context, &ccdef))) {
200*7f2fe78bSCy Schubert com_err(progname, retval, "while getting default ccache");
201*7f2fe78bSCy Schubert exit(1);
202*7f2fe78bSCy Schubert }
203*7f2fe78bSCy Schubert
204*7f2fe78bSCy Schubert retval = krb5_mk_req(context, &auth_context, AP_OPTS_USE_SUBKEY, service,
205*7f2fe78bSCy Schubert hostname, &inbuf, ccdef, &packet);
206*7f2fe78bSCy Schubert if (retval) {
207*7f2fe78bSCy Schubert com_err(progname, retval, "while preparing AP_REQ");
208*7f2fe78bSCy Schubert exit(1);
209*7f2fe78bSCy Schubert }
210*7f2fe78bSCy Schubert printf("Got credentials for %s.\n", service);
211*7f2fe78bSCy Schubert
212*7f2fe78bSCy Schubert /* "connect" the datagram socket; this is necessary to get a local address
213*7f2fe78bSCy Schubert properly bound for getsockname() below. */
214*7f2fe78bSCy Schubert
215*7f2fe78bSCy Schubert if (connect(sock, (struct sockaddr *)&s_sock, sizeof(s_sock)) == -1) {
216*7f2fe78bSCy Schubert com_err(progname, errno, "while connecting to server");
217*7f2fe78bSCy Schubert exit(1);
218*7f2fe78bSCy Schubert }
219*7f2fe78bSCy Schubert /* Send authentication info to server */
220*7f2fe78bSCy Schubert if ((i = send(sock, (char *)packet.data, (unsigned) packet.length,
221*7f2fe78bSCy Schubert flags)) < 0)
222*7f2fe78bSCy Schubert com_err(progname, errno, "while sending KRB_AP_REQ message");
223*7f2fe78bSCy Schubert printf("Sent authentication data: %d bytes\n", i);
224*7f2fe78bSCy Schubert krb5_free_data_contents(context, &packet);
225*7f2fe78bSCy Schubert
226*7f2fe78bSCy Schubert /* PREPARE KRB_SAFE MESSAGE */
227*7f2fe78bSCy Schubert
228*7f2fe78bSCy Schubert /* Get my address */
229*7f2fe78bSCy Schubert memset(&c_sock, 0, sizeof(c_sock));
230*7f2fe78bSCy Schubert len = sizeof(c_sock);
231*7f2fe78bSCy Schubert if (getsockname(sock, (struct sockaddr *)&c_sock, &len) < 0) {
232*7f2fe78bSCy Schubert com_err(progname, errno, "while getting socket name");
233*7f2fe78bSCy Schubert exit(1);
234*7f2fe78bSCy Schubert }
235*7f2fe78bSCy Schubert
236*7f2fe78bSCy Schubert addr.addrtype = ADDRTYPE_IPPORT;
237*7f2fe78bSCy Schubert addr.length = sizeof(c_sock.sin_port);
238*7f2fe78bSCy Schubert addr.contents = (krb5_octet *)&c_sock.sin_port;
239*7f2fe78bSCy Schubert if ((retval = krb5_auth_con_setports(context, auth_context,
240*7f2fe78bSCy Schubert &addr, NULL))) {
241*7f2fe78bSCy Schubert com_err(progname, retval, "while setting local port\n");
242*7f2fe78bSCy Schubert exit(1);
243*7f2fe78bSCy Schubert }
244*7f2fe78bSCy Schubert
245*7f2fe78bSCy Schubert addr.addrtype = ADDRTYPE_INET;
246*7f2fe78bSCy Schubert addr.length = sizeof(c_sock.sin_addr);
247*7f2fe78bSCy Schubert addr.contents = (krb5_octet *)&c_sock.sin_addr;
248*7f2fe78bSCy Schubert if ((retval = krb5_auth_con_setaddrs(context, auth_context,
249*7f2fe78bSCy Schubert &addr, NULL))) {
250*7f2fe78bSCy Schubert com_err(progname, retval, "while setting local addr\n");
251*7f2fe78bSCy Schubert exit(1);
252*7f2fe78bSCy Schubert }
253*7f2fe78bSCy Schubert
254*7f2fe78bSCy Schubert /* Make the safe message */
255*7f2fe78bSCy Schubert inbuf.data = message;
256*7f2fe78bSCy Schubert inbuf.length = strlen(message);
257*7f2fe78bSCy Schubert
258*7f2fe78bSCy Schubert if ((retval = krb5_mk_safe(context, auth_context, &inbuf, &packet, NULL))){
259*7f2fe78bSCy Schubert com_err(progname, retval, "while making KRB_SAFE message");
260*7f2fe78bSCy Schubert exit(1);
261*7f2fe78bSCy Schubert }
262*7f2fe78bSCy Schubert
263*7f2fe78bSCy Schubert /* Send it */
264*7f2fe78bSCy Schubert if ((i = send(sock, (char *)packet.data, (unsigned) packet.length,
265*7f2fe78bSCy Schubert flags)) < 0)
266*7f2fe78bSCy Schubert com_err(progname, errno, "while sending SAFE message");
267*7f2fe78bSCy Schubert printf("Sent checksummed message: %d bytes\n", i);
268*7f2fe78bSCy Schubert krb5_free_data_contents(context, &packet);
269*7f2fe78bSCy Schubert
270*7f2fe78bSCy Schubert /* PREPARE KRB_PRIV MESSAGE */
271*7f2fe78bSCy Schubert
272*7f2fe78bSCy Schubert /* Make the encrypted message */
273*7f2fe78bSCy Schubert if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
274*7f2fe78bSCy Schubert &packet, NULL))) {
275*7f2fe78bSCy Schubert com_err(progname, retval, "while making KRB_PRIV message");
276*7f2fe78bSCy Schubert exit(1);
277*7f2fe78bSCy Schubert }
278*7f2fe78bSCy Schubert
279*7f2fe78bSCy Schubert /* Send it */
280*7f2fe78bSCy Schubert if ((i = send(sock, (char *)packet.data, (unsigned) packet.length,
281*7f2fe78bSCy Schubert flags)) < 0)
282*7f2fe78bSCy Schubert com_err(progname, errno, "while sending PRIV message");
283*7f2fe78bSCy Schubert printf("Sent encrypted message: %d bytes\n", i);
284*7f2fe78bSCy Schubert krb5_free_data_contents(context, &packet);
285*7f2fe78bSCy Schubert
286*7f2fe78bSCy Schubert krb5_auth_con_free(context, auth_context);
287*7f2fe78bSCy Schubert krb5_free_context(context);
288*7f2fe78bSCy Schubert
289*7f2fe78bSCy Schubert exit(0);
290*7f2fe78bSCy Schubert }
291