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