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
42 int
main(int argc,char * argv[])43 main(int argc, char *argv[])
44 {
45 krb5_data pname_data, tkt_data;
46 int sock = 0;
47 socklen_t l;
48 int retval;
49 struct sockaddr_in l_inaddr, f_inaddr; /* local, foreign address */
50 krb5_creds creds, *new_creds;
51 krb5_ccache cc;
52 krb5_data msgtext, msg;
53 krb5_context context;
54 krb5_auth_context auth_context = NULL;
55
56 #ifndef DEBUG
57 freopen("/tmp/uu-server.log", "w", stderr);
58 #endif
59
60 retval = krb5_init_context(&context);
61 if (retval) {
62 com_err(argv[0], retval, "while initializing krb5");
63 exit(1);
64 }
65
66 #ifdef DEBUG
67 {
68 int one = 1;
69 int acc;
70 struct servent *sp;
71 socklen_t namelen = sizeof(f_inaddr);
72
73 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
74 com_err("uu-server", errno, "creating socket");
75 exit(3);
76 }
77
78 l_inaddr.sin_family = AF_INET;
79 l_inaddr.sin_addr.s_addr = 0;
80 if (argc == 2) {
81 l_inaddr.sin_port = htons(atoi(argv[1]));
82 } else {
83 if (!(sp = getservbyname("uu-sample", "tcp"))) {
84 com_err("uu-server", 0, "can't find uu-sample/tcp service");
85 exit(3);
86 }
87 l_inaddr.sin_port = sp->s_port;
88 }
89
90 (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (one));
91 if (bind(sock, (struct sockaddr *)&l_inaddr, sizeof(l_inaddr))) {
92 com_err("uu-server", errno, "binding socket");
93 exit(3);
94 }
95 if (listen(sock, 1) == -1) {
96 com_err("uu-server", errno, "listening");
97 exit(3);
98 }
99
100 printf("Server started\n");
101 fflush(stdout);
102
103 if ((acc = accept(sock, (struct sockaddr *)&f_inaddr, &namelen)) == -1) {
104 com_err("uu-server", errno, "accepting");
105 exit(3);
106 }
107 dup2(acc, 0);
108 close(sock);
109 sock = 0;
110 }
111 #endif
112
113 /* principal name must be sent null-terminated. */
114 retval = krb5_read_message(context, (krb5_pointer) &sock, &pname_data);
115 if (retval || pname_data.length == 0 ||
116 pname_data.data[pname_data.length - 1] != '\0') {
117 com_err ("uu-server", retval, "reading pname");
118 return 2;
119 }
120
121 retval = krb5_read_message(context, (krb5_pointer) &sock, &tkt_data);
122 if (retval) {
123 com_err ("uu-server", retval, "reading ticket data");
124 return 2;
125 }
126
127 retval = krb5_cc_default(context, &cc);
128 if (retval) {
129 com_err("uu-server", retval, "getting credentials cache");
130 return 4;
131 }
132
133 memset (&creds, 0, sizeof(creds));
134 retval = krb5_cc_get_principal(context, cc, &creds.client);
135 if (retval) {
136 com_err("uu-client", retval, "getting principal name");
137 return 6;
138 }
139
140 /* client sends it already null-terminated. */
141 printf ("uu-server: client principal is \"%s\".\n", pname_data.data);
142
143 retval = krb5_parse_name(context, pname_data.data, &creds.server);
144 if (retval) {
145 com_err("uu-server", retval, "parsing client name");
146 return 3;
147 }
148
149 creds.second_ticket = tkt_data;
150 printf ("uu-server: client ticket is %d bytes.\n",
151 creds.second_ticket.length);
152
153 retval = krb5_get_credentials(context, KRB5_GC_USER_USER, cc,
154 &creds, &new_creds);
155 if (retval) {
156 com_err("uu-server", retval, "getting user-user ticket");
157 return 5;
158 }
159
160 #ifndef DEBUG
161 l = sizeof(f_inaddr);
162 if (getpeername(0, (struct sockaddr *)&f_inaddr, &l) == -1)
163 {
164 com_err("uu-server", errno, "getting client address");
165 return 6;
166 }
167 #endif
168 l = sizeof(l_inaddr);
169 if (getsockname(0, (struct sockaddr *)&l_inaddr, &l) == -1)
170 {
171 com_err("uu-server", errno, "getting local address");
172 return 6;
173 }
174
175 /* send a ticket/authenticator to the other side, so it can get the key
176 we're using for the krb_safe below. */
177
178 retval = krb5_auth_con_init(context, &auth_context);
179 if (retval) {
180 com_err("uu-server", retval, "making auth_context");
181 return 8;
182 }
183
184 retval = krb5_auth_con_setflags(context, auth_context,
185 KRB5_AUTH_CONTEXT_DO_SEQUENCE);
186 if (retval) {
187 com_err("uu-server", retval, "initializing the auth_context flags");
188 return 8;
189 }
190
191 retval =
192 krb5_auth_con_genaddrs(context, auth_context, sock,
193 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
194 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
195 if (retval) {
196 com_err("uu-server", retval, "generating addrs for auth_context");
197 return 9;
198 }
199
200 #if 1
201 retval = krb5_mk_req_extended(context, &auth_context,
202 AP_OPTS_USE_SESSION_KEY,
203 NULL, new_creds, &msg);
204 if (retval) {
205 com_err("uu-server", retval, "making AP_REQ");
206 return 8;
207 }
208 retval = krb5_write_message(context, (krb5_pointer) &sock, &msg);
209 #else
210 retval = krb5_sendauth(context, &auth_context, (krb5_pointer)&sock, "???",
211 0, 0,
212 AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SESSION_KEY,
213 NULL, &creds, cc, NULL, NULL, NULL);
214 #endif
215 if (retval)
216 goto cl_short_wrt;
217
218 free(msg.data);
219
220 msgtext.length = 32;
221 msgtext.data = "Hello, other end of connection.";
222
223 retval = krb5_mk_safe(context, auth_context, &msgtext, &msg, NULL);
224 if (retval) {
225 com_err("uu-server", retval, "encoding message to client");
226 return 6;
227 }
228
229 retval = krb5_write_message(context, (krb5_pointer) &sock, &msg);
230 if (retval) {
231 cl_short_wrt:
232 com_err("uu-server", retval, "writing message to client");
233 return 7;
234 }
235
236
237 krb5_free_data_contents(context, &msg);
238 krb5_free_data_contents(context, &pname_data);
239 /* tkt_data freed with creds */
240 krb5_free_cred_contents(context, &creds);
241 krb5_free_creds(context, new_creds);
242 krb5_cc_close(context, cc);
243 krb5_auth_con_free(context, auth_context);
244 krb5_free_context(context);
245 return 0;
246 }
247