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