xref: /freebsd/crypto/krb5/src/appl/simple/client/sim_client.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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