1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* appl/simple/server/sim_server.c */
4 * Copyright 1989,1991 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
29 * sample_server servername
31 * Simple UDP-based server application. For demonstration.
32 * This program performs no useful function.
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
44 #include <arpa/inet.h>
50 /* for old Unixes and friends ... */
51 #ifndef MAXHOSTNAMELEN
52 #define MAXHOSTNAMELEN 64
55 #define PROGNAME argv[0]
60 fprintf(stderr, "usage: %s [-p port] [-s service] [-S keytab]\n", name);
64 main(int argc, char *argv[])
68 int flags = 0; /* for recvfrom() */
72 struct sockaddr_in s_sock; /* server's address */
73 struct sockaddr_in c_sock; /* client's address */
74 char full_hname[MAXHOSTNAMELEN];
79 short port = 0; /* If user specifies port */
80 krb5_keytab keytab = NULL; /* Allow specification on command line */
81 char *service = SIMPLE_SERVICE;
83 krb5_error_code retval;
84 krb5_data packet, message;
85 unsigned char pktbuf[BUFSIZ];
86 krb5_principal sprinc;
88 krb5_auth_context auth_context = NULL;
90 krb5_ticket *ticket = NULL;
92 retval = krb5_init_context(&context);
94 com_err(argv[0], retval, "while initializing krb5");
99 * Parse command line arguments
102 while ((ch = getopt(argc, argv, "p:s:S:")) != -1) {
111 if ((retval = krb5_kt_resolve(context, optarg, &keytab))) {
112 com_err(PROGNAME, retval,
113 "while resolving keytab file %s", optarg);
126 if ((retval = krb5_sname_to_principal(context, NULL, service,
127 KRB5_NT_SRV_HST, &sprinc))) {
128 com_err(PROGNAME, retval, "while generating service name %s", service);
132 /* Set up server address */
133 memset(&s_sock, 0, sizeof(s_sock));
134 s_sock.sin_family = AF_INET;
137 /* Look up service */
138 if ((serv = getservbyname(SIMPLE_PORT, "udp")) == NULL) {
139 fprintf(stderr, "service unknown: %s/udp\n", SIMPLE_PORT);
142 s_sock.sin_port = serv->s_port;
144 s_sock.sin_port = htons(port);
147 if (gethostname(full_hname, sizeof(full_hname)) < 0) {
148 perror("gethostname");
152 if ((host = gethostbyname(full_hname)) == (struct hostent *)0) {
153 fprintf(stderr, "%s: host unknown\n", full_hname);
156 memcpy(&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr));
159 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
160 perror("opening datagram socket");
164 /* Let the socket be reused right away */
165 (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
168 /* Bind the socket */
169 if (bind(sock, (struct sockaddr *)&s_sock, sizeof(s_sock))) {
170 perror("binding datagram socket");
174 printf("starting...\n");
177 printf("socket has port # %d\n", ntohs(s_sock.sin_port));
180 /* GET KRB_AP_REQ MESSAGE */
182 /* use "recvfrom" so we know client's address */
183 len = sizeof(struct sockaddr_in);
184 if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags,
185 (struct sockaddr *)&c_sock, &len)) < 0) {
186 perror("receiving datagram");
190 printf("Received %d bytes\n", i);
192 packet.data = (krb5_pointer) pktbuf;
194 /* Check authentication info */
195 if ((retval = krb5_rd_req(context, &auth_context, &packet,
196 sprinc, keytab, NULL, &ticket))) {
197 com_err(PROGNAME, retval, "while reading request");
200 if ((retval = krb5_unparse_name(context, ticket->enc_part2->client,
202 com_err(PROGNAME, retval, "while unparsing client name");
205 printf("Got authentication info from %s\n", cp);
208 /* Set foreign_addr for rd_safe() and rd_priv() */
209 addr.addrtype = ADDRTYPE_INET;
210 addr.length = sizeof(c_sock.sin_addr);
211 addr.contents = (krb5_octet *)&c_sock.sin_addr;
212 if ((retval = krb5_auth_con_setaddrs(context, auth_context,
214 com_err(PROGNAME, retval, "while setting foreign addr");
218 addr.addrtype = ADDRTYPE_IPPORT;
219 addr.length = sizeof(c_sock.sin_port);
220 addr.contents = (krb5_octet *)&c_sock.sin_port;
221 if ((retval = krb5_auth_con_setports(context, auth_context,
223 com_err(PROGNAME, retval, "while setting foreign port");
227 /* GET KRB_MK_SAFE MESSAGE */
229 /* use "recvfrom" so we know client's address */
230 len = sizeof(struct sockaddr_in);
231 if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags,
232 (struct sockaddr *)&c_sock, &len)) < 0) {
233 perror("receiving datagram");
237 printf("&c_sock.sin_addr is %s\n", inet_ntoa(c_sock.sin_addr));
239 printf("Received %d bytes\n", i);
242 packet.data = (krb5_pointer) pktbuf;
244 if ((retval = krb5_rd_safe(context, auth_context, &packet,
246 com_err(PROGNAME, retval, "while verifying SAFE message");
249 printf("Safe message is: '%.*s'\n", (int) message.length, message.data);
251 krb5_free_data_contents(context, &message);
253 /* NOW GET ENCRYPTED MESSAGE */
255 /* use "recvfrom" so we know client's address */
256 len = sizeof(struct sockaddr_in);
257 if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags,
258 (struct sockaddr *)&c_sock, &len)) < 0) {
259 perror("receiving datagram");
262 printf("Received %d bytes\n", i);
265 packet.data = (krb5_pointer) pktbuf;
267 if ((retval = krb5_rd_priv(context, auth_context, &packet,
269 com_err(PROGNAME, retval, "while verifying PRIV message");
272 printf("Decrypted message is: '%.*s'\n", (int) message.length,
275 krb5_auth_con_free(context, auth_context);
276 krb5_free_context(context);