Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / kerberosIV / appl / sample / sample_server.c
1 /* $FreeBSD: src/crypto/kerberosIV/appl/sample/sample_server.c,v 1.1.1.2.2.1 2000/07/20 14:04:34 assar Exp $ */
2
3 /*
4  *
5  * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
6  *
7  * For copying and distribution information,
8  * please see the file <mit-copyright.h>.
9  *
10  * sample_server:
11  * A sample Kerberos server, which reads a ticket from a TCP socket,
12  * decodes it, and writes back the results (in ASCII) to the client.
13  *
14  * Usage:
15  * sample_server
16  *
17  * file descriptor 0 (zero) should be a socket connected to the requesting
18  * client (this will be correct if this server is started by inetd).
19  */
20
21 #include "sample.h"
22
23 RCSID("$Id: sample_server.c,v 1.14.2.1 2000/06/28 19:08:00 assar Exp $");
24
25 static void
26 usage (void)
27 {
28     fprintf (stderr, "Usage: %s [-i] [-s service] [-t srvtab]\n",
29              __progname);
30     exit (1);
31 }
32
33 int
34 main(int argc, char **argv)
35 {
36     struct sockaddr_in peername, myname;
37     int namelen = sizeof(peername);
38     int status, count, len;
39     long authopts;
40     AUTH_DAT auth_data;
41     KTEXT_ST clt_ticket;
42     des_key_schedule sched;
43     char instance[INST_SZ];
44     char service[ANAME_SZ];
45     char version[KRB_SENDAUTH_VLEN+1];
46     char retbuf[512];
47     char lname[ANAME_SZ];
48     char srvtab[MaxPathLen];
49     int c;
50     int no_inetd = 0;
51
52     /* open a log connection */
53
54     set_progname (argv[0]);
55
56     roken_openlog(__progname, LOG_ODELAY, LOG_DAEMON);
57
58     strlcpy (service, SAMPLE_SERVICE, sizeof(service));
59     *srvtab = '\0';
60
61     while ((c = getopt (argc, argv, "s:t:i")) != -1)
62         switch (c) {
63         case 's' :
64             strlcpy (service, optarg, sizeof(service));
65             break;
66         case 't' :
67             strlcpy (srvtab, optarg, sizeof(srvtab));
68             break;
69         case 'i':
70             no_inetd = 1;
71             break;
72         case '?' :
73         default :
74             usage ();
75         }
76
77     if (no_inetd)
78         mini_inetd (htons(SAMPLE_PORT));
79
80     /*
81      * To verify authenticity, we need to know the address of the
82      * client.
83      */
84     if (getpeername(STDIN_FILENO,
85                     (struct sockaddr *)&peername,
86                     &namelen) < 0) {
87         syslog(LOG_ERR, "getpeername: %m");
88         return 1;
89     }
90
91     /* for mutual authentication, we need to know our address */
92     namelen = sizeof(myname);
93     if (getsockname(STDIN_FILENO, (struct sockaddr *)&myname, &namelen) < 0) {
94         syslog(LOG_ERR, "getsocknamename: %m");
95         return 1;
96     }
97
98     /* read the authenticator and decode it.  Using `k_getsockinst' we
99      * always get the right instance on a multi-homed host.
100      */
101     k_getsockinst (STDIN_FILENO, instance, sizeof(instance));
102
103     /* we want mutual authentication */
104     authopts = KOPT_DO_MUTUAL;
105     status = krb_recvauth(authopts, STDIN_FILENO, &clt_ticket,
106                           service, instance, &peername, &myname,
107                           &auth_data, srvtab,
108                           sched, version);
109     if (status != KSUCCESS) {
110         snprintf(retbuf, sizeof(retbuf),
111                  "Kerberos error: %s\n",
112                  krb_get_err_text(status));
113         syslog(LOG_ERR, "%s", retbuf);
114     } else {
115         /* Check the version string (KRB_SENDAUTH_VLEN chars) */
116         if (strncmp(version, SAMPLE_VERSION, KRB_SENDAUTH_VLEN)) {
117             /* didn't match the expected version */
118             /* could do something different, but we just log an error
119                and continue */
120             version[8] = '\0';          /* make sure null term */
121             syslog(LOG_ERR, "Version mismatch: '%s' isn't '%s'",
122                    version, SAMPLE_VERSION);
123         }
124         /* now that we have decoded the authenticator, translate
125            the kerberos principal.instance@realm into a local name */
126         if (krb_kntoln(&auth_data, lname) != KSUCCESS)
127             strlcpy(lname,
128                             "*No local name returned by krb_kntoln*",
129                             sizeof(lname));
130         /* compose the reply */
131         snprintf(retbuf, sizeof(retbuf),
132                 "You are %s.%s@%s (local name %s),\n at address %s, version %s, cksum %ld\n",
133                 auth_data.pname,
134                 auth_data.pinst,
135                 auth_data.prealm,
136                 lname,
137                 inet_ntoa(peername.sin_addr),
138                 version,
139                 (long)auth_data.checksum);
140     }
141
142     /* write back the response */
143     if ((count = write(0, retbuf, (len = strlen(retbuf) + 1))) < 0) {
144         syslog(LOG_ERR,"write: %m");
145         return 1;
146     } else if (count != len) {
147         syslog(LOG_ERR, "write count incorrect: %d != %d\n",
148                 count, len);
149         return 1;
150     }
151
152     /* close up and exit */
153     close(0);
154     return 0;
155 }