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