Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / kerberosIV / appl / kip / kipd.c
1 /* $FreeBSD: src/crypto/kerberosIV/appl/kip/kipd.c,v 1.1.1.3.2.2 2001/03/04 12:52:43 markm Exp $ */
2
3 /*
4  * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  * 
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35
36 #include "kip.h"
37
38 RCSID("$Id: kipd.c,v 1.16.2.3 2000/10/18 20:46:45 assar Exp $");
39
40 static int
41 recv_conn (int sock, des_cblock *key, des_key_schedule schedule,
42            struct sockaddr_in *retaddr, char *user, size_t len)
43 {
44      int status;
45      KTEXT_ST ticket;
46      AUTH_DAT auth;
47      char instance[INST_SZ];
48      struct sockaddr_in thisaddr, thataddr;
49      int addrlen;
50      char version[KRB_SENDAUTH_VLEN + 1];
51      u_char ok = 0;
52      struct passwd *passwd;
53
54      addrlen = sizeof(thisaddr);
55      if (getsockname (sock, (struct sockaddr *)&thisaddr, &addrlen) < 0 ||
56          addrlen != sizeof(thisaddr)) {
57           return 1;
58      }
59      addrlen = sizeof(thataddr);
60      if (getpeername (sock, (struct sockaddr *)&thataddr, &addrlen) < 0 ||
61          addrlen != sizeof(thataddr)) {
62           return 1;
63      }
64
65      k_getsockinst (sock, instance, sizeof(instance));
66      status = krb_recvauth (KOPT_DO_MUTUAL, sock, &ticket, "rcmd", instance,
67                             &thataddr, &thisaddr, &auth, "", schedule,
68                             version);
69      if (status != KSUCCESS ||
70          strncmp(version, KIP_VERSION, KRB_SENDAUTH_VLEN) != 0) {
71           return 1;
72      }
73      passwd = k_getpwnam ("root");
74      if (passwd == NULL) {
75           fatal (sock, "Cannot find root", schedule, &auth.session);
76           return 1;
77      }
78      if (kuserok(&auth, "root") != 0) {
79           fatal (sock, "Permission denied", schedule, &auth.session);
80           return 1;
81      }
82      if (write (sock, &ok, sizeof(ok)) != sizeof(ok))
83           return 1;
84
85      snprintf (user, len, "%s%s%s@%s", auth.pname, 
86                auth.pinst[0] != '\0' ? "." : "",
87                auth.pinst, auth.prealm);
88
89      memcpy(key, &auth.session, sizeof(des_cblock));
90      *retaddr = thataddr;
91      return 0;
92 }
93
94 static int
95 doit(int sock)
96 {
97      char msg[1024];
98      char cmd[MAXPATHLEN];
99      char tun_if_name[64];
100      char user[MAX_K_NAME_SZ];
101      struct sockaddr_in thataddr;
102      des_key_schedule schedule;
103      des_cblock key;
104      int this, ret, ret2;
105
106      isserver = 1;
107
108      if (recv_conn (sock, &key, schedule, &thataddr, user, sizeof(user)))
109           return 1;
110      this = tunnel_open (tun_if_name, sizeof(tun_if_name));
111      if (this < 0)
112           fatal (sock, "Cannot open " _PATH_DEV TUNDEV, schedule, &key);
113
114      strlcpy(cmd, LIBEXECDIR "/kipd-control", sizeof(cmd));
115
116      ret = kip_exec (cmd, msg, sizeof(msg), "kipd-control",
117                      "up", tun_if_name, inet_ntoa(thataddr.sin_addr), user,
118                      NULL);
119      if (ret) {
120          fatal (sock, msg, schedule, &key);
121          return -1;
122      }
123
124      ret = copy_packets (this, sock, TUNMTU, &key, schedule);
125      
126      ret2 = kip_exec (cmd,  msg, sizeof(msg), "kipd-control",
127                       "down", tun_if_name, user, NULL);
128      if (ret2)
129          syslog(LOG_ERR, "%s", msg);
130      return ret;
131 }
132
133 static char *port_str           = NULL;
134 static int inetd_flag           = 1;
135 static int version_flag         = 0;
136 static int help_flag            = 0;
137
138 struct getargs args[] = {
139     { "inetd",          'i',    arg_negative_flag,      &inetd_flag,
140       "Not started from inetd" },
141     { "port",           'p',    arg_string,     &port_str,      "Use this port",
142       "port" },
143     { "version",        0,      arg_flag,               &version_flag },
144     { "help",           0,      arg_flag,               &help_flag }
145 };
146
147 static void
148 usage(int ret)
149 {
150     arg_printusage (args,
151                     sizeof(args) / sizeof(args[0]),
152                     NULL,
153                     "");
154     exit (ret);
155 }
156
157 /*
158  * kipd - receive forwarded IP
159  */
160
161 int
162 main (int argc, char **argv)
163 {
164     int port;
165     int optind = 0;
166
167     set_progname (argv[0]);
168     roken_openlog(__progname, LOG_PID|LOG_CONS, LOG_DAEMON);
169
170     if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
171                 &optind))
172         usage (1);
173
174     if (help_flag)
175         usage (0);
176
177     if (version_flag) {
178         print_version (NULL);
179         return 0;
180     }
181
182     if(port_str) {
183         struct servent *s = roken_getservbyname (port_str, "tcp");
184
185         if (s)
186             port = s->s_port;
187         else {
188             char *ptr;
189
190             port = strtol (port_str, &ptr, 10);
191             if (port == 0 && ptr == port_str)
192                 errx (1, "bad port `%s'", port_str);
193             port = htons(port);
194         }
195     } else {
196         port = k_getportbyname ("kip", "tcp", htons(KIPPORT));
197     }
198
199     if (!inetd_flag)
200         mini_inetd (port);
201
202     signal (SIGCHLD, childhandler);
203     return doit(STDIN_FILENO);
204 }