xref: /freebsd/crypto/krb5/src/appl/user_user/server.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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