1
2 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 /* appl/user_user/server.c - One end of user-user client-server pair */
4 /*
5 * Copyright 1991 by the Massachusetts Institute of Technology.
6 * All Rights Reserved.
7 *
8 * Export of this software from the United States of America may
9 * require a specific license from the United States Government.
10 * It is the responsibility of any person or organization contemplating
11 * export to obtain such a license before exporting.
12 *
13 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14 * distribute this software and its documentation for any purpose and
15 * without fee is hereby granted, provided that the above copyright
16 * notice appear in all copies and that both that copyright notice and
17 * this permission notice appear in supporting documentation, and that
18 * the name of M.I.T. not be used in advertising or publicity pertaining
19 * to distribution of the software without specific, written prior
20 * permission. Furthermore if you modify this software you must label
21 * your software as modified software and not distribute it in such a
22 * fashion that it might be confused with the original M.I.T. software.
23 * M.I.T. makes no representations about the suitability of
24 * this software for any purpose. It is provided "as is" without express
25 * or implied warranty.
26 */
27
28 #include "k5-int.h"
29 #include "port-sockets.h"
30 #include "com_err.h"
31
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <netdb.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39
40 /* fd 0 is a tcp socket used to talk to the client */
41
main(argc,argv)42 int main(argc, argv)
43 int argc;
44 char *argv[];
45 {
46 krb5_data pname_data, tkt_data;
47 int sock = 0;
48 socklen_t l;
49 int retval;
50 struct sockaddr_in l_inaddr, f_inaddr; /* local, foreign address */
51 krb5_creds creds, *new_creds;
52 krb5_ccache cc;
53 krb5_data msgtext, msg;
54 krb5_context context;
55 krb5_auth_context auth_context = NULL;
56
57 #ifndef DEBUG
58 freopen("/tmp/uu-server.log", "w", stderr);
59 #endif
60
61 retval = krb5_init_context(&context);
62 if (retval) {
63 com_err(argv[0], retval, "while initializing krb5");
64 exit(1);
65 }
66
67 #ifdef DEBUG
68 {
69 int one = 1;
70 int acc;
71 struct servent *sp;
72 socklen_t namelen = sizeof(f_inaddr);
73
74 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
75 com_err("uu-server", errno, "creating socket");
76 exit(3);
77 }
78
79 l_inaddr.sin_family = AF_INET;
80 l_inaddr.sin_addr.s_addr = 0;
81 if (argc == 2) {
82 l_inaddr.sin_port = htons(atoi(argv[1]));
83 } else {
84 if (!(sp = getservbyname("uu-sample", "tcp"))) {
85 com_err("uu-server", 0, "can't find uu-sample/tcp service");
86 exit(3);
87 }
88 l_inaddr.sin_port = sp->s_port;
89 }
90
91 (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (one));
92 if (bind(sock, (struct sockaddr *)&l_inaddr, sizeof(l_inaddr))) {
93 com_err("uu-server", errno, "binding socket");
94 exit(3);
95 }
96 if (listen(sock, 1) == -1) {
97 com_err("uu-server", errno, "listening");
98 exit(3);
99 }
100
101 printf("Server started\n");
102 fflush(stdout);
103
104 if ((acc = accept(sock, (struct sockaddr *)&f_inaddr, &namelen)) == -1) {
105 com_err("uu-server", errno, "accepting");
106 exit(3);
107 }
108 dup2(acc, 0);
109 close(sock);
110 sock = 0;
111 }
112 #endif
113
114 /* principal name must be sent null-terminated. */
115 retval = krb5_read_message(context, (krb5_pointer) &sock, &pname_data);
116 if (retval || pname_data.length == 0 ||
117 pname_data.data[pname_data.length - 1] != '\0') {
118 com_err ("uu-server", retval, "reading pname");
119 return 2;
120 }
121
122 retval = krb5_read_message(context, (krb5_pointer) &sock, &tkt_data);
123 if (retval) {
124 com_err ("uu-server", retval, "reading ticket data");
125 return 2;
126 }
127
128 retval = krb5_cc_default(context, &cc);
129 if (retval) {
130 com_err("uu-server", retval, "getting credentials cache");
131 return 4;
132 }
133
134 memset (&creds, 0, sizeof(creds));
135 retval = krb5_cc_get_principal(context, cc, &creds.client);
136 if (retval) {
137 com_err("uu-client", retval, "getting principal name");
138 return 6;
139 }
140
141 /* client sends it already null-terminated. */
142 printf ("uu-server: client principal is \"%s\".\n", pname_data.data);
143
144 retval = krb5_parse_name(context, pname_data.data, &creds.server);
145 if (retval) {
146 com_err("uu-server", retval, "parsing client name");
147 return 3;
148 }
149
150 creds.second_ticket = tkt_data;
151 printf ("uu-server: client ticket is %d bytes.\n",
152 creds.second_ticket.length);
153
154 retval = krb5_get_credentials(context, KRB5_GC_USER_USER, cc,
155 &creds, &new_creds);
156 if (retval) {
157 com_err("uu-server", retval, "getting user-user ticket");
158 return 5;
159 }
160
161 #ifndef DEBUG
162 l = sizeof(f_inaddr);
163 if (getpeername(0, (struct sockaddr *)&f_inaddr, &l) == -1)
164 {
165 com_err("uu-server", errno, "getting client address");
166 return 6;
167 }
168 #endif
169 l = sizeof(l_inaddr);
170 if (getsockname(0, (struct sockaddr *)&l_inaddr, &l) == -1)
171 {
172 com_err("uu-server", errno, "getting local address");
173 return 6;
174 }
175
176 /* send a ticket/authenticator to the other side, so it can get the key
177 we're using for the krb_safe below. */
178
179 retval = krb5_auth_con_init(context, &auth_context);
180 if (retval) {
181 com_err("uu-server", retval, "making auth_context");
182 return 8;
183 }
184
185 retval = krb5_auth_con_setflags(context, auth_context,
186 KRB5_AUTH_CONTEXT_DO_SEQUENCE);
187 if (retval) {
188 com_err("uu-server", retval, "initializing the auth_context flags");
189 return 8;
190 }
191
192 retval =
193 krb5_auth_con_genaddrs(context, auth_context, sock,
194 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
195 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
196 if (retval) {
197 com_err("uu-server", retval, "generating addrs for auth_context");
198 return 9;
199 }
200
201 #if 1
202 retval = krb5_mk_req_extended(context, &auth_context,
203 AP_OPTS_USE_SESSION_KEY,
204 NULL, new_creds, &msg);
205 if (retval) {
206 com_err("uu-server", retval, "making AP_REQ");
207 return 8;
208 }
209 retval = krb5_write_message(context, (krb5_pointer) &sock, &msg);
210 #else
211 retval = krb5_sendauth(context, &auth_context, (krb5_pointer)&sock, "???",
212 0, 0,
213 AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SESSION_KEY,
214 NULL, &creds, cc, NULL, NULL, NULL);
215 #endif
216 if (retval)
217 goto cl_short_wrt;
218
219 free(msg.data);
220
221 msgtext.length = 32;
222 msgtext.data = "Hello, other end of connection.";
223
224 retval = krb5_mk_safe(context, auth_context, &msgtext, &msg, NULL);
225 if (retval) {
226 com_err("uu-server", retval, "encoding message to client");
227 return 6;
228 }
229
230 retval = krb5_write_message(context, (krb5_pointer) &sock, &msg);
231 if (retval) {
232 cl_short_wrt:
233 com_err("uu-server", retval, "writing message to client");
234 return 7;
235 }
236
237
238 krb5_free_data_contents(context, &msg);
239 krb5_free_data_contents(context, &pname_data);
240 /* tkt_data freed with creds */
241 krb5_free_cred_contents(context, &creds);
242 krb5_free_creds(context, new_creds);
243 krb5_cc_close(context, cc);
244 krb5_auth_con_free(context, auth_context);
245 krb5_free_context(context);
246 return 0;
247 }
248