xref: /freebsd/crypto/krb5/src/appl/simple/server/sim_server.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* appl/simple/server/sim_server.c */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  * Copyright 1989,1991 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All Rights Reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert  *   require a specific license from the United States Government.
9*7f2fe78bSCy Schubert  *   It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert  *   export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert  *
12*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
24*7f2fe78bSCy Schubert  * or implied warranty.
25*7f2fe78bSCy Schubert  */
26*7f2fe78bSCy Schubert 
27*7f2fe78bSCy Schubert /*
28*7f2fe78bSCy Schubert  * Usage:
29*7f2fe78bSCy Schubert  * sample_server servername
30*7f2fe78bSCy Schubert  *
31*7f2fe78bSCy Schubert  * Simple UDP-based server application.  For demonstration.
32*7f2fe78bSCy Schubert  * This program performs no useful function.
33*7f2fe78bSCy Schubert  */
34*7f2fe78bSCy Schubert 
35*7f2fe78bSCy Schubert #include "krb5.h"
36*7f2fe78bSCy Schubert #include "port-sockets.h"
37*7f2fe78bSCy Schubert #include <stdio.h>
38*7f2fe78bSCy Schubert #include <string.h>
39*7f2fe78bSCy Schubert #include <unistd.h>
40*7f2fe78bSCy Schubert #include <stdlib.h>
41*7f2fe78bSCy Schubert #include <sys/types.h>
42*7f2fe78bSCy Schubert #include <sys/socket.h>
43*7f2fe78bSCy Schubert #include <netinet/in.h>
44*7f2fe78bSCy Schubert #include <netdb.h>
45*7f2fe78bSCy Schubert #include <arpa/inet.h>
46*7f2fe78bSCy Schubert 
47*7f2fe78bSCy Schubert #include "com_err.h"
48*7f2fe78bSCy Schubert 
49*7f2fe78bSCy Schubert #include "simple.h"
50*7f2fe78bSCy Schubert 
51*7f2fe78bSCy Schubert /* for old Unixes and friends ... */
52*7f2fe78bSCy Schubert #ifndef MAXHOSTNAMELEN
53*7f2fe78bSCy Schubert #define MAXHOSTNAMELEN 64
54*7f2fe78bSCy Schubert #endif
55*7f2fe78bSCy Schubert 
56*7f2fe78bSCy Schubert #define PROGNAME argv[0]
57*7f2fe78bSCy Schubert 
58*7f2fe78bSCy Schubert static void
usage(char * name)59*7f2fe78bSCy Schubert usage(char *name)
60*7f2fe78bSCy Schubert {
61*7f2fe78bSCy Schubert     fprintf(stderr, "usage: %s [-p port] [-s service] [-S keytab]\n", name);
62*7f2fe78bSCy Schubert }
63*7f2fe78bSCy Schubert 
64*7f2fe78bSCy Schubert int
main(int argc,char * argv[])65*7f2fe78bSCy Schubert main(int argc, char *argv[])
66*7f2fe78bSCy Schubert {
67*7f2fe78bSCy Schubert     int sock, i;
68*7f2fe78bSCy Schubert     socklen_t len;
69*7f2fe78bSCy Schubert     int flags = 0;                      /* for recvfrom() */
70*7f2fe78bSCy Schubert     int on = 1;
71*7f2fe78bSCy Schubert     struct servent *serv;
72*7f2fe78bSCy Schubert     struct sockaddr_in s_sock;          /* server's address */
73*7f2fe78bSCy Schubert     struct sockaddr_in c_sock;          /* client's address */
74*7f2fe78bSCy Schubert     char *cp;
75*7f2fe78bSCy Schubert     extern char * optarg;
76*7f2fe78bSCy Schubert     int ch;
77*7f2fe78bSCy Schubert 
78*7f2fe78bSCy Schubert     short port = 0;             /* If user specifies port */
79*7f2fe78bSCy Schubert     krb5_keytab keytab = NULL;  /* Allow specification on command line */
80*7f2fe78bSCy Schubert     char *service = SIMPLE_SERVICE;
81*7f2fe78bSCy Schubert 
82*7f2fe78bSCy Schubert     krb5_error_code retval;
83*7f2fe78bSCy Schubert     krb5_data packet, message;
84*7f2fe78bSCy Schubert     unsigned char pktbuf[BUFSIZ];
85*7f2fe78bSCy Schubert     krb5_principal sprinc;
86*7f2fe78bSCy Schubert     krb5_context context;
87*7f2fe78bSCy Schubert     krb5_auth_context auth_context = NULL;
88*7f2fe78bSCy Schubert     krb5_address addr;
89*7f2fe78bSCy Schubert     krb5_ticket *ticket = NULL;
90*7f2fe78bSCy Schubert 
91*7f2fe78bSCy Schubert     retval = krb5_init_context(&context);
92*7f2fe78bSCy Schubert     if (retval) {
93*7f2fe78bSCy Schubert         com_err(argv[0], retval, "while initializing krb5");
94*7f2fe78bSCy Schubert         exit(1);
95*7f2fe78bSCy Schubert     }
96*7f2fe78bSCy Schubert 
97*7f2fe78bSCy Schubert     /*
98*7f2fe78bSCy Schubert      * Parse command line arguments
99*7f2fe78bSCy Schubert      *
100*7f2fe78bSCy Schubert      */
101*7f2fe78bSCy Schubert     while ((ch = getopt(argc, argv, "p:s:S:")) != -1) {
102*7f2fe78bSCy Schubert         switch (ch) {
103*7f2fe78bSCy Schubert         case 'p':
104*7f2fe78bSCy Schubert             port = atoi(optarg);
105*7f2fe78bSCy Schubert             break;
106*7f2fe78bSCy Schubert         case 's':
107*7f2fe78bSCy Schubert             service = optarg;
108*7f2fe78bSCy Schubert             break;
109*7f2fe78bSCy Schubert         case 'S':
110*7f2fe78bSCy Schubert             if ((retval = krb5_kt_resolve(context, optarg, &keytab))) {
111*7f2fe78bSCy Schubert                 com_err(PROGNAME, retval,
112*7f2fe78bSCy Schubert                         "while resolving keytab file %s", optarg);
113*7f2fe78bSCy Schubert                 exit(2);
114*7f2fe78bSCy Schubert             }
115*7f2fe78bSCy Schubert             break;
116*7f2fe78bSCy Schubert 
117*7f2fe78bSCy Schubert         case '?':
118*7f2fe78bSCy Schubert         default:
119*7f2fe78bSCy Schubert             usage(PROGNAME);
120*7f2fe78bSCy Schubert             exit(1);
121*7f2fe78bSCy Schubert             break;
122*7f2fe78bSCy Schubert         }
123*7f2fe78bSCy Schubert     }
124*7f2fe78bSCy Schubert 
125*7f2fe78bSCy Schubert     if ((retval = krb5_sname_to_principal(context, NULL, service,
126*7f2fe78bSCy Schubert                                           KRB5_NT_SRV_HST, &sprinc))) {
127*7f2fe78bSCy Schubert         com_err(PROGNAME, retval, "while generating service name %s", service);
128*7f2fe78bSCy Schubert         exit(1);
129*7f2fe78bSCy Schubert     }
130*7f2fe78bSCy Schubert 
131*7f2fe78bSCy Schubert     /* Set up server address */
132*7f2fe78bSCy Schubert     memset(&s_sock, 0, sizeof(s_sock));
133*7f2fe78bSCy Schubert     s_sock.sin_family = AF_INET;
134*7f2fe78bSCy Schubert     s_sock.sin_addr.s_addr = INADDR_ANY;
135*7f2fe78bSCy Schubert 
136*7f2fe78bSCy Schubert     if (port == 0) {
137*7f2fe78bSCy Schubert         /* Look up service */
138*7f2fe78bSCy Schubert         if ((serv = getservbyname(SIMPLE_PORT, "udp")) == NULL) {
139*7f2fe78bSCy Schubert             fprintf(stderr, "service unknown: %s/udp\n", SIMPLE_PORT);
140*7f2fe78bSCy Schubert             exit(1);
141*7f2fe78bSCy Schubert         }
142*7f2fe78bSCy Schubert         s_sock.sin_port = serv->s_port;
143*7f2fe78bSCy Schubert     } else {
144*7f2fe78bSCy Schubert         s_sock.sin_port = htons(port);
145*7f2fe78bSCy Schubert     }
146*7f2fe78bSCy Schubert 
147*7f2fe78bSCy Schubert     /* Open socket */
148*7f2fe78bSCy Schubert     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
149*7f2fe78bSCy Schubert         perror("opening datagram socket");
150*7f2fe78bSCy Schubert         exit(1);
151*7f2fe78bSCy Schubert     }
152*7f2fe78bSCy Schubert 
153*7f2fe78bSCy Schubert     /* Let the socket be reused right away */
154*7f2fe78bSCy Schubert     (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
155*7f2fe78bSCy Schubert                       sizeof(on));
156*7f2fe78bSCy Schubert 
157*7f2fe78bSCy Schubert     /* Bind the socket */
158*7f2fe78bSCy Schubert     if (bind(sock, (struct sockaddr *)&s_sock, sizeof(s_sock))) {
159*7f2fe78bSCy Schubert         perror("binding datagram socket");
160*7f2fe78bSCy Schubert         exit(1);
161*7f2fe78bSCy Schubert     }
162*7f2fe78bSCy Schubert 
163*7f2fe78bSCy Schubert     printf("starting...\n");
164*7f2fe78bSCy Schubert     fflush(stdout);
165*7f2fe78bSCy Schubert 
166*7f2fe78bSCy Schubert #ifdef DEBUG
167*7f2fe78bSCy Schubert     printf("socket has port # %d\n", ntohs(s_sock.sin_port));
168*7f2fe78bSCy Schubert #endif
169*7f2fe78bSCy Schubert 
170*7f2fe78bSCy Schubert     /* GET KRB_AP_REQ MESSAGE */
171*7f2fe78bSCy Schubert 
172*7f2fe78bSCy Schubert     /* use "recvfrom" so we know client's address */
173*7f2fe78bSCy Schubert     len = sizeof(struct sockaddr_in);
174*7f2fe78bSCy Schubert     if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags,
175*7f2fe78bSCy Schubert                       (struct sockaddr *)&c_sock, &len)) < 0) {
176*7f2fe78bSCy Schubert         perror("receiving datagram");
177*7f2fe78bSCy Schubert         exit(1);
178*7f2fe78bSCy Schubert     }
179*7f2fe78bSCy Schubert 
180*7f2fe78bSCy Schubert     printf("Received %d bytes\n", i);
181*7f2fe78bSCy Schubert     packet.length = i;
182*7f2fe78bSCy Schubert     packet.data = (krb5_pointer) pktbuf;
183*7f2fe78bSCy Schubert 
184*7f2fe78bSCy Schubert     /* Check authentication info */
185*7f2fe78bSCy Schubert     if ((retval = krb5_rd_req(context, &auth_context, &packet,
186*7f2fe78bSCy Schubert                               sprinc, keytab, NULL, &ticket))) {
187*7f2fe78bSCy Schubert         com_err(PROGNAME, retval, "while reading request");
188*7f2fe78bSCy Schubert         exit(1);
189*7f2fe78bSCy Schubert     }
190*7f2fe78bSCy Schubert     if ((retval = krb5_unparse_name(context, ticket->enc_part2->client,
191*7f2fe78bSCy Schubert                                     &cp))) {
192*7f2fe78bSCy Schubert         com_err(PROGNAME, retval, "while unparsing client name");
193*7f2fe78bSCy Schubert         exit(1);
194*7f2fe78bSCy Schubert     }
195*7f2fe78bSCy Schubert     printf("Got authentication info from %s\n", cp);
196*7f2fe78bSCy Schubert     free(cp);
197*7f2fe78bSCy Schubert 
198*7f2fe78bSCy Schubert     /* Set foreign_addr for rd_safe() and rd_priv() */
199*7f2fe78bSCy Schubert     addr.addrtype = ADDRTYPE_INET;
200*7f2fe78bSCy Schubert     addr.length = sizeof(c_sock.sin_addr);
201*7f2fe78bSCy Schubert     addr.contents = (krb5_octet *)&c_sock.sin_addr;
202*7f2fe78bSCy Schubert     if ((retval = krb5_auth_con_setaddrs(context, auth_context,
203*7f2fe78bSCy Schubert                                          NULL, &addr))) {
204*7f2fe78bSCy Schubert         com_err(PROGNAME, retval, "while setting foreign addr");
205*7f2fe78bSCy Schubert         exit(1);
206*7f2fe78bSCy Schubert     }
207*7f2fe78bSCy Schubert 
208*7f2fe78bSCy Schubert     addr.addrtype = ADDRTYPE_IPPORT;
209*7f2fe78bSCy Schubert     addr.length = sizeof(c_sock.sin_port);
210*7f2fe78bSCy Schubert     addr.contents = (krb5_octet *)&c_sock.sin_port;
211*7f2fe78bSCy Schubert     if ((retval = krb5_auth_con_setports(context, auth_context,
212*7f2fe78bSCy Schubert                                          NULL, &addr))) {
213*7f2fe78bSCy Schubert         com_err(PROGNAME, retval, "while setting foreign port");
214*7f2fe78bSCy Schubert         exit(1);
215*7f2fe78bSCy Schubert     }
216*7f2fe78bSCy Schubert 
217*7f2fe78bSCy Schubert     /* GET KRB_MK_SAFE MESSAGE */
218*7f2fe78bSCy Schubert 
219*7f2fe78bSCy Schubert     /* use "recvfrom" so we know client's address */
220*7f2fe78bSCy Schubert     len = sizeof(struct sockaddr_in);
221*7f2fe78bSCy Schubert     if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags,
222*7f2fe78bSCy Schubert                       (struct sockaddr *)&c_sock, &len)) < 0) {
223*7f2fe78bSCy Schubert         perror("receiving datagram");
224*7f2fe78bSCy Schubert         exit(1);
225*7f2fe78bSCy Schubert     }
226*7f2fe78bSCy Schubert #ifdef DEBUG
227*7f2fe78bSCy Schubert     printf("&c_sock.sin_addr is %s\n", inet_ntoa(c_sock.sin_addr));
228*7f2fe78bSCy Schubert #endif
229*7f2fe78bSCy Schubert     printf("Received %d bytes\n", i);
230*7f2fe78bSCy Schubert 
231*7f2fe78bSCy Schubert     packet.length = i;
232*7f2fe78bSCy Schubert     packet.data = (krb5_pointer) pktbuf;
233*7f2fe78bSCy Schubert 
234*7f2fe78bSCy Schubert     if ((retval = krb5_rd_safe(context, auth_context, &packet,
235*7f2fe78bSCy Schubert                                &message, NULL))) {
236*7f2fe78bSCy Schubert         com_err(PROGNAME, retval, "while verifying SAFE message");
237*7f2fe78bSCy Schubert         exit(1);
238*7f2fe78bSCy Schubert     }
239*7f2fe78bSCy Schubert     printf("Safe message is: '%.*s'\n", (int) message.length, message.data);
240*7f2fe78bSCy Schubert 
241*7f2fe78bSCy Schubert     krb5_free_data_contents(context, &message);
242*7f2fe78bSCy Schubert 
243*7f2fe78bSCy Schubert     /* NOW GET ENCRYPTED MESSAGE */
244*7f2fe78bSCy Schubert 
245*7f2fe78bSCy Schubert     /* use "recvfrom" so we know client's address */
246*7f2fe78bSCy Schubert     len = sizeof(struct sockaddr_in);
247*7f2fe78bSCy Schubert     if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags,
248*7f2fe78bSCy Schubert                       (struct sockaddr *)&c_sock, &len)) < 0) {
249*7f2fe78bSCy Schubert         perror("receiving datagram");
250*7f2fe78bSCy Schubert         exit(1);
251*7f2fe78bSCy Schubert     }
252*7f2fe78bSCy Schubert     printf("Received %d bytes\n", i);
253*7f2fe78bSCy Schubert 
254*7f2fe78bSCy Schubert     packet.length = i;
255*7f2fe78bSCy Schubert     packet.data = (krb5_pointer) pktbuf;
256*7f2fe78bSCy Schubert 
257*7f2fe78bSCy Schubert     if ((retval = krb5_rd_priv(context, auth_context, &packet,
258*7f2fe78bSCy Schubert                                &message, NULL))) {
259*7f2fe78bSCy Schubert         com_err(PROGNAME, retval, "while verifying PRIV message");
260*7f2fe78bSCy Schubert         exit(1);
261*7f2fe78bSCy Schubert     }
262*7f2fe78bSCy Schubert     printf("Decrypted message is: '%.*s'\n", (int) message.length,
263*7f2fe78bSCy Schubert            message.data);
264*7f2fe78bSCy Schubert 
265*7f2fe78bSCy Schubert     krb5_auth_con_free(context, auth_context);
266*7f2fe78bSCy Schubert     krb5_free_context(context);
267*7f2fe78bSCy Schubert 
268*7f2fe78bSCy Schubert     exit(0);
269*7f2fe78bSCy Schubert }
270