xref: /freebsd/crypto/krb5/src/appl/user_user/client.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* appl/user_user/client.c - Other end of user-user client/server pair */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  * Copyright 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 #include "k5-int.h"
28*7f2fe78bSCy Schubert #include "com_err.h"
29*7f2fe78bSCy Schubert 
30*7f2fe78bSCy Schubert #include <sys/types.h>
31*7f2fe78bSCy Schubert #include <sys/socket.h>
32*7f2fe78bSCy Schubert #include <netinet/in.h>
33*7f2fe78bSCy Schubert #include <arpa/inet.h>
34*7f2fe78bSCy Schubert #include <netdb.h>
35*7f2fe78bSCy Schubert 
main(int argc,char * argv[])36*7f2fe78bSCy Schubert int main (int argc, char *argv[])
37*7f2fe78bSCy Schubert {
38*7f2fe78bSCy Schubert     int s;
39*7f2fe78bSCy Schubert     int retval, i;
40*7f2fe78bSCy Schubert     char *hname;          /* full name of server */
41*7f2fe78bSCy Schubert     char **srealms;       /* realm(s) of server */
42*7f2fe78bSCy Schubert     char *princ;          /* principal in credentials cache */
43*7f2fe78bSCy Schubert     struct servent *serv;
44*7f2fe78bSCy Schubert     struct hostent *host;
45*7f2fe78bSCy Schubert     struct sockaddr_in serv_net_addr, cli_net_addr;
46*7f2fe78bSCy Schubert     krb5_ccache cc;
47*7f2fe78bSCy Schubert     krb5_creds creds, *new_creds;
48*7f2fe78bSCy Schubert     krb5_data reply, msg, princ_data;
49*7f2fe78bSCy Schubert     krb5_auth_context auth_context = NULL;
50*7f2fe78bSCy Schubert     krb5_ticket * ticket = NULL;
51*7f2fe78bSCy Schubert     krb5_context context;
52*7f2fe78bSCy Schubert     unsigned short port;
53*7f2fe78bSCy Schubert 
54*7f2fe78bSCy Schubert     if (argc < 2 || argc > 4) {
55*7f2fe78bSCy Schubert         fputs ("usage: uu-client <hostname> [message [port]]\n", stderr);
56*7f2fe78bSCy Schubert         exit(1);
57*7f2fe78bSCy Schubert     }
58*7f2fe78bSCy Schubert 
59*7f2fe78bSCy Schubert     retval = krb5_init_context(&context);
60*7f2fe78bSCy Schubert     if (retval) {
61*7f2fe78bSCy Schubert         com_err(argv[0], retval, "while initializing krb5");
62*7f2fe78bSCy Schubert         exit(1);
63*7f2fe78bSCy Schubert     }
64*7f2fe78bSCy Schubert 
65*7f2fe78bSCy Schubert     if (argc == 4) {
66*7f2fe78bSCy Schubert         port = htons(atoi(argv[3]));
67*7f2fe78bSCy Schubert     }
68*7f2fe78bSCy Schubert     else if ((serv = getservbyname ("uu-sample", "tcp")) == NULL)
69*7f2fe78bSCy Schubert     {
70*7f2fe78bSCy Schubert         fputs ("uu-client: unknown service \"uu-sample/tcp\"\n", stderr);
71*7f2fe78bSCy Schubert         exit(2);
72*7f2fe78bSCy Schubert     } else {
73*7f2fe78bSCy Schubert         port = serv->s_port;
74*7f2fe78bSCy Schubert     }
75*7f2fe78bSCy Schubert 
76*7f2fe78bSCy Schubert     if ((host = gethostbyname (argv[1])) == NULL) {
77*7f2fe78bSCy Schubert         fprintf (stderr, "uu-client: can't get address of host \"%s\".\n",
78*7f2fe78bSCy Schubert                  argv[1]);
79*7f2fe78bSCy Schubert         exit(3);
80*7f2fe78bSCy Schubert     }
81*7f2fe78bSCy Schubert 
82*7f2fe78bSCy Schubert     if (host->h_addrtype != AF_INET) {
83*7f2fe78bSCy Schubert         fprintf (stderr, "uu-client: bad address type %d for \"%s\".\n",
84*7f2fe78bSCy Schubert                  host->h_addrtype, argv[1]);
85*7f2fe78bSCy Schubert         exit(3);
86*7f2fe78bSCy Schubert     }
87*7f2fe78bSCy Schubert 
88*7f2fe78bSCy Schubert     hname = strdup (host->h_name);
89*7f2fe78bSCy Schubert 
90*7f2fe78bSCy Schubert #ifndef USE_STDOUT
91*7f2fe78bSCy Schubert     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
92*7f2fe78bSCy Schubert         com_err ("uu-client", errno, "creating socket");
93*7f2fe78bSCy Schubert         exit(4);
94*7f2fe78bSCy Schubert     } else {
95*7f2fe78bSCy Schubert         cli_net_addr.sin_family = AF_INET;
96*7f2fe78bSCy Schubert         cli_net_addr.sin_port = 0;
97*7f2fe78bSCy Schubert         cli_net_addr.sin_addr.s_addr = 0;
98*7f2fe78bSCy Schubert         if (bind (s, (struct sockaddr *)&cli_net_addr,
99*7f2fe78bSCy Schubert                   sizeof (cli_net_addr)) < 0) {
100*7f2fe78bSCy Schubert             com_err ("uu-client", errno, "binding socket");
101*7f2fe78bSCy Schubert             exit(4);
102*7f2fe78bSCy Schubert         }
103*7f2fe78bSCy Schubert     }
104*7f2fe78bSCy Schubert 
105*7f2fe78bSCy Schubert     serv_net_addr.sin_family = AF_INET;
106*7f2fe78bSCy Schubert     serv_net_addr.sin_port = port;
107*7f2fe78bSCy Schubert 
108*7f2fe78bSCy Schubert     i = 0;
109*7f2fe78bSCy Schubert     while (1) {
110*7f2fe78bSCy Schubert         if (host->h_addr_list[i] == 0) {
111*7f2fe78bSCy Schubert             fprintf (stderr, "uu-client: unable to connect to \"%s\"\n", hname);
112*7f2fe78bSCy Schubert             exit(5);
113*7f2fe78bSCy Schubert         }
114*7f2fe78bSCy Schubert 
115*7f2fe78bSCy Schubert         memcpy (&serv_net_addr.sin_addr, host->h_addr_list[i++],
116*7f2fe78bSCy Schubert                 sizeof(serv_net_addr.sin_addr));
117*7f2fe78bSCy Schubert 
118*7f2fe78bSCy Schubert         if (connect(s, (struct sockaddr *)&serv_net_addr,
119*7f2fe78bSCy Schubert                     sizeof (serv_net_addr)) == 0)
120*7f2fe78bSCy Schubert             break;
121*7f2fe78bSCy Schubert         com_err ("uu-client", errno, "connecting to \"%s\" (%s).",
122*7f2fe78bSCy Schubert                  hname, inet_ntoa(serv_net_addr.sin_addr));
123*7f2fe78bSCy Schubert     }
124*7f2fe78bSCy Schubert #else
125*7f2fe78bSCy Schubert     s = 1;
126*7f2fe78bSCy Schubert #endif
127*7f2fe78bSCy Schubert 
128*7f2fe78bSCy Schubert     retval = krb5_cc_default(context, &cc);
129*7f2fe78bSCy Schubert     if (retval) {
130*7f2fe78bSCy Schubert         com_err("uu-client", retval, "getting credentials cache");
131*7f2fe78bSCy Schubert         exit(6);
132*7f2fe78bSCy Schubert     }
133*7f2fe78bSCy Schubert 
134*7f2fe78bSCy Schubert     memset (&creds, 0, sizeof(creds));
135*7f2fe78bSCy Schubert 
136*7f2fe78bSCy Schubert     retval = krb5_cc_get_principal(context, cc, &creds.client);
137*7f2fe78bSCy Schubert     if (retval) {
138*7f2fe78bSCy Schubert         com_err("uu-client", retval, "getting principal name");
139*7f2fe78bSCy Schubert         exit(6);
140*7f2fe78bSCy Schubert     }
141*7f2fe78bSCy Schubert 
142*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, creds.client, &princ);
143*7f2fe78bSCy Schubert     if (retval) {
144*7f2fe78bSCy Schubert         com_err("uu-client", retval, "printing principal name");
145*7f2fe78bSCy Schubert         exit(7);
146*7f2fe78bSCy Schubert     }
147*7f2fe78bSCy Schubert     else
148*7f2fe78bSCy Schubert         fprintf(stderr, "uu-client: client principal is \"%s\".\n", princ);
149*7f2fe78bSCy Schubert 
150*7f2fe78bSCy Schubert     retval = krb5_get_host_realm(context, hname, &srealms);
151*7f2fe78bSCy Schubert     if (retval) {
152*7f2fe78bSCy Schubert         com_err("uu-client", retval, "getting realms for \"%s\"", hname);
153*7f2fe78bSCy Schubert         exit(7);
154*7f2fe78bSCy Schubert     }
155*7f2fe78bSCy Schubert 
156*7f2fe78bSCy Schubert     retval =
157*7f2fe78bSCy Schubert         krb5_build_principal_ext(context, &creds.server,
158*7f2fe78bSCy Schubert                                  krb5_princ_realm(context,
159*7f2fe78bSCy Schubert                                                   creds.client)->length,
160*7f2fe78bSCy Schubert                                  krb5_princ_realm(context,
161*7f2fe78bSCy Schubert                                                   creds.client)->data,
162*7f2fe78bSCy Schubert                                  6, "krbtgt",
163*7f2fe78bSCy Schubert                                  krb5_princ_realm(context,
164*7f2fe78bSCy Schubert                                                   creds.client)->length,
165*7f2fe78bSCy Schubert                                  krb5_princ_realm(context,
166*7f2fe78bSCy Schubert                                                   creds.client)->data,
167*7f2fe78bSCy Schubert                                  0);
168*7f2fe78bSCy Schubert     if (retval) {
169*7f2fe78bSCy Schubert         com_err("uu-client", retval, "setting up tgt server name");
170*7f2fe78bSCy Schubert         exit(7);
171*7f2fe78bSCy Schubert     }
172*7f2fe78bSCy Schubert 
173*7f2fe78bSCy Schubert     /* Get TGT from credentials cache */
174*7f2fe78bSCy Schubert     retval = krb5_get_credentials(context, KRB5_GC_CACHED, cc,
175*7f2fe78bSCy Schubert                                   &creds, &new_creds);
176*7f2fe78bSCy Schubert     if (retval) {
177*7f2fe78bSCy Schubert         com_err("uu-client", retval, "getting TGT");
178*7f2fe78bSCy Schubert         exit(6);
179*7f2fe78bSCy Schubert     }
180*7f2fe78bSCy Schubert 
181*7f2fe78bSCy Schubert     i = strlen(princ) + 1;
182*7f2fe78bSCy Schubert 
183*7f2fe78bSCy Schubert     fprintf(stderr, "uu-client: sending %d bytes\n",
184*7f2fe78bSCy Schubert             new_creds->ticket.length + i);
185*7f2fe78bSCy Schubert     princ_data.data = princ;
186*7f2fe78bSCy Schubert     princ_data.length = i;                /* include null terminator for
187*7f2fe78bSCy Schubert                                              server's convenience */
188*7f2fe78bSCy Schubert     retval = krb5_write_message(context, (krb5_pointer) &s, &princ_data);
189*7f2fe78bSCy Schubert     if (retval) {
190*7f2fe78bSCy Schubert         com_err("uu-client", retval, "sending principal name to server");
191*7f2fe78bSCy Schubert         exit(8);
192*7f2fe78bSCy Schubert     }
193*7f2fe78bSCy Schubert 
194*7f2fe78bSCy Schubert     free(princ);
195*7f2fe78bSCy Schubert 
196*7f2fe78bSCy Schubert     retval = krb5_write_message(context, (krb5_pointer) &s,
197*7f2fe78bSCy Schubert                                 &new_creds->ticket);
198*7f2fe78bSCy Schubert     if (retval) {
199*7f2fe78bSCy Schubert         com_err("uu-client", retval, "sending ticket to server");
200*7f2fe78bSCy Schubert         exit(8);
201*7f2fe78bSCy Schubert     }
202*7f2fe78bSCy Schubert 
203*7f2fe78bSCy Schubert     retval = krb5_read_message(context, (krb5_pointer) &s, &reply);
204*7f2fe78bSCy Schubert     if (retval) {
205*7f2fe78bSCy Schubert         com_err("uu-client", retval, "reading reply from server");
206*7f2fe78bSCy Schubert         exit(9);
207*7f2fe78bSCy Schubert     }
208*7f2fe78bSCy Schubert 
209*7f2fe78bSCy Schubert     retval = krb5_auth_con_init(context, &auth_context);
210*7f2fe78bSCy Schubert     if (retval) {
211*7f2fe78bSCy Schubert         com_err("uu-client", retval, "initializing the auth_context");
212*7f2fe78bSCy Schubert         exit(9);
213*7f2fe78bSCy Schubert     }
214*7f2fe78bSCy Schubert 
215*7f2fe78bSCy Schubert     retval =
216*7f2fe78bSCy Schubert         krb5_auth_con_genaddrs(context, auth_context, s,
217*7f2fe78bSCy Schubert                                KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
218*7f2fe78bSCy Schubert                                KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
219*7f2fe78bSCy Schubert     if (retval) {
220*7f2fe78bSCy Schubert         com_err("uu-client", retval, "generating addrs for auth_context");
221*7f2fe78bSCy Schubert         exit(9);
222*7f2fe78bSCy Schubert     }
223*7f2fe78bSCy Schubert 
224*7f2fe78bSCy Schubert     retval = krb5_auth_con_setflags(context, auth_context,
225*7f2fe78bSCy Schubert                                     KRB5_AUTH_CONTEXT_DO_SEQUENCE);
226*7f2fe78bSCy Schubert     if (retval) {
227*7f2fe78bSCy Schubert         com_err("uu-client", retval, "initializing the auth_context flags");
228*7f2fe78bSCy Schubert         exit(9);
229*7f2fe78bSCy Schubert     }
230*7f2fe78bSCy Schubert 
231*7f2fe78bSCy Schubert     retval = krb5_auth_con_setuseruserkey(context, auth_context,
232*7f2fe78bSCy Schubert                                           &new_creds->keyblock);
233*7f2fe78bSCy Schubert     if (retval) {
234*7f2fe78bSCy Schubert         com_err("uu-client", retval, "setting useruserkey for authcontext");
235*7f2fe78bSCy Schubert         exit(9);
236*7f2fe78bSCy Schubert     }
237*7f2fe78bSCy Schubert 
238*7f2fe78bSCy Schubert     /* read the ap_req to get the session key */
239*7f2fe78bSCy Schubert     retval = krb5_rd_req(context, &auth_context, &reply, creds.client, NULL,
240*7f2fe78bSCy Schubert                          NULL, &ticket);
241*7f2fe78bSCy Schubert     krb5_free_data_contents(context, &reply);
242*7f2fe78bSCy Schubert     if (retval) {
243*7f2fe78bSCy Schubert         com_err("uu-client", retval, "reading AP_REQ from server");
244*7f2fe78bSCy Schubert         exit(9);
245*7f2fe78bSCy Schubert     }
246*7f2fe78bSCy Schubert 
247*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, ticket->enc_part2->client, &princ);
248*7f2fe78bSCy Schubert     if (retval)
249*7f2fe78bSCy Schubert         com_err("uu-client", retval, "while unparsing client name");
250*7f2fe78bSCy Schubert     else {
251*7f2fe78bSCy Schubert         printf("server is named \"%s\"\n", princ);
252*7f2fe78bSCy Schubert         free(princ);
253*7f2fe78bSCy Schubert     }
254*7f2fe78bSCy Schubert 
255*7f2fe78bSCy Schubert     retval = krb5_read_message(context, (krb5_pointer) &s, &reply);
256*7f2fe78bSCy Schubert     if (retval) {
257*7f2fe78bSCy Schubert         com_err("uu-client", retval, "reading reply from server");
258*7f2fe78bSCy Schubert         exit(9);
259*7f2fe78bSCy Schubert     }
260*7f2fe78bSCy Schubert 
261*7f2fe78bSCy Schubert     retval = krb5_rd_safe(context, auth_context, &reply, &msg, NULL);
262*7f2fe78bSCy Schubert     if (retval) {
263*7f2fe78bSCy Schubert         com_err("uu-client", retval, "decoding reply from server");
264*7f2fe78bSCy Schubert         exit(10);
265*7f2fe78bSCy Schubert     }
266*7f2fe78bSCy Schubert 
267*7f2fe78bSCy Schubert     printf ("uu-client: server says \"%s\".\n", msg.data);
268*7f2fe78bSCy Schubert 
269*7f2fe78bSCy Schubert #ifndef USE_STDOUT
270*7f2fe78bSCy Schubert     close(s);
271*7f2fe78bSCy Schubert #endif
272*7f2fe78bSCy Schubert     krb5_free_ticket(context, ticket);
273*7f2fe78bSCy Schubert     krb5_free_host_realm(context, srealms);
274*7f2fe78bSCy Schubert     free(hname);
275*7f2fe78bSCy Schubert     krb5_free_cred_contents(context, &creds);
276*7f2fe78bSCy Schubert     krb5_free_creds(context, new_creds);
277*7f2fe78bSCy Schubert     krb5_free_data_contents(context, &msg);
278*7f2fe78bSCy Schubert     krb5_free_data_contents(context, &reply);
279*7f2fe78bSCy Schubert     krb5_cc_close(context, cc);
280*7f2fe78bSCy Schubert     krb5_auth_con_free(context, auth_context);
281*7f2fe78bSCy Schubert     krb5_free_context(context);
282*7f2fe78bSCy Schubert     return 0;
283*7f2fe78bSCy Schubert }
284