chiark / gitweb /
Major overhaul. Separate functions for manipulating keysets from
[tripe] / tripe.c
CommitLineData
410c8acf 1/* -*-c-*-
2 *
efd6c9e3 3 * $Id: tripe.c,v 1.3 2001/02/04 17:10:40 mdw Exp $
410c8acf 4 *
5 * Main program
6 *
7 * (c) 2001 Straylight/Edgeware
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Trivial IP Encryption (TrIPE).
13 *
14 * TrIPE is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * TrIPE is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with TrIPE; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29/*----- Revision history --------------------------------------------------*
30 *
31 * $Log: tripe.c,v $
efd6c9e3 32 * Revision 1.3 2001/02/04 17:10:40 mdw
33 * Remove a debugging @abort@ call.
34 *
e31c0b14 35 * Revision 1.2 2001/02/03 22:33:00 mdw
36 * Stuff more randomness into the pool in the interval timer.
37 *
410c8acf 38 * Revision 1.1 2001/02/03 20:26:37 mdw
39 * Initial checkin.
40 *
41 */
42
43/*----- Header files ------------------------------------------------------*/
44
45#include "tripe.h"
46
47/*----- Global variables --------------------------------------------------*/
48
49sel_state sel;
50octet buf_i[PKBUFSZ], buf_o[PKBUFSZ];
51
52/*----- Static variables --------------------------------------------------*/
53
54static sel_timer it;
55#define T_INTERVAL MIN(1)
56
57/*----- Main code ---------------------------------------------------------*/
58
59/* --- @interval@ --- *
60 *
61 * Arguments: @struct timeval *tv@ = time when called
62 * @void *v@ = boring pointer
63 *
64 * Returns: ---
65 *
66 * Use: Called periodically to do housekeeping tasks.
67 */
68
69void interval(struct timeval *tv, void *v)
70{
71 struct timeval tvv;
72 T( trace(T_PEER, "peer: interval timer"); )
e31c0b14 73 rand_seed(RAND_GLOBAL, RMD160_HASHSZ);
410c8acf 74 p_interval();
75 tvv = *tv;
76 tvv.tv_sec += T_INTERVAL;
77 sel_addtimer(&sel, &it, &tvv, interval, v);
78}
79
80/* --- @main@ --- *
81 *
82 * Arguments: @int argc@ = number of command line arguments
83 * @char *argv[]@ = vector of arguments
84 *
85 * Returns: Zero if OK, nonzero on error.
86 *
87 * Use: Main program. Provides a simple VPN.
88 */
89
90static void usage(FILE *fp)
91{
92 pquis(fp, "Usage: $ [-options]\n");
93}
94
95static void version(FILE *fp)
96{
97 pquis(fp, "$, version " VERSION "\n");
98}
99
100static void help(FILE *fp)
101{
102 version(fp);
103 fputc('\n', fp);
104 usage(fp);
105 fputs("\n\
106Options:\n\
107\n\
108-h, --help Display this help text.\n\
109-v, --version Display version number.\n\
110-u, --usage Display pointless usage message.\n\
111\n\
112-D, --daemon Run in the background.\n\
113-d, --directory=DIR Switch to directory DIR (default $TRIPEDIR).\n\
114-p, --port=PORT Select UDP port to listen to.\n\
115-k, --priv-keyring=FILE Get private key from FILE.\n\
116-K, --pub-keyring=FILE Get public keys from FILE.\n\
117-t, --tag=KEYTAG Use private key labelled TAG.\n\
118-a, --admin-socket=FILE Use FILE as the adminstration socket.\n\
119-T, --trace=OPTIONS Turn on tracing options.\n\
120", fp);
121}
122
123int main(int argc, char *argv[])
124{
125 const char *kr_priv = "keyring", *kr_pub = "keyring.pub";
126 const char *tag_priv = "tripe-dh";
127 const char *csock = "tripesock";
128 const char *dir = "/var/lib/tripe";
129 const char *p;
130 unsigned port = 0;
131 unsigned f = 0;
132 uid_t u = -1;
133 gid_t g = -1;
134
135#define f_bogus 1u
136#define f_daemon 2u
137
138 ego(argv[0]);
139 trace_on(stderr, 0);
140
141 if ((p = getenv("TRIPEDIR")) != 0)
142 dir = p;
143
144 for (;;) {
145 static const struct option opts[] = {
146 { "help", 0, 0, 'h' },
147 { "version", 0, 0, 'v' },
148 { "usage", 0, 0, 'u' },
149
150 { "daemon", 0, 0, 'D' },
151 { "uid", OPTF_ARGREQ, 0, 'U' },
152 { "setuid", OPTF_ARGREQ, 0, 'U' },
153 { "gid", OPTF_ARGREQ, 0, 'G' },
154 { "setgid", OPTF_ARGREQ, 0, 'G' },
155 { "port", OPTF_ARGREQ, 0, 'p' },
156 { "directory", OPTF_ARGREQ, 0, 'd' },
157 { "priv-keyring", OPTF_ARGREQ, 0, 'k' },
158 { "pub-keyring", OPTF_ARGREQ, 0, 'K' },
159 { "tag", OPTF_ARGREQ, 0, 't' },
160 { "admin-socket", OPTF_ARGREQ, 0, 'a' },
161#ifndef NTRACE
162 { "trace", OPTF_ARGREQ, 0, 'T' },
163#endif
164
165 { 0, 0, 0, 0 }
166 };
167
168 int i = mdwopt(argc, argv, "hvu DU:G: p:d:k:K:t:a:" T("T:"),
169 opts, 0, 0, 0);
170 if (i < 0)
171 break;
172 switch (i) {
173 case 'h':
174 help(stdout);
175 exit(0);
176 case 'v':
177 version(stdout);
178 exit(0);
179 case 'u':
180 usage(stdout);
181 exit(0);
182
183 case 'D':
184 f |= f_daemon;
185 break;
186 case 'U': {
187 char *p;
188 unsigned long i = strtoul(optarg, &p, 0);
189 if (!*p)
190 u = i;
191 else {
192 struct passwd *pw;
193 if ((pw = getpwnam(optarg)) == 0)
194 die(EXIT_FAILURE, "user name `%s' not found", optarg);
195 u = pw->pw_uid;
196 }
197 } break;
198 case 'G': {
199 char *p;
200 unsigned long i = strtoul(optarg, &p, 0);
201 if (!*p)
202 g = i;
203 else {
204 struct group *gr;
205 if ((gr = getgrnam(optarg)) == 0)
206 die(EXIT_FAILURE, "group name `%s' not found", optarg);
207 g = gr->gr_gid;
208 }
209 } break;
210
211 case 'p': {
212 char *p;
213 unsigned long i = strtoul(optarg, &p, 0);
214 if (*p) {
215 struct servent *s = getservbyname(optarg, "udp");
216 if (!s)
217 die(EXIT_FAILURE, "unknown service name `%s'", optarg);
218 i = ntohs(s->s_port);
219 }
220 if (i == 0 || i >= 65536)
221 die(EXIT_FAILURE, "bad port number %lu", i);
222 port = i;
223 } break;
224 case 'd':
225 dir = optarg;
226 break;
227 case 'k':
228 kr_priv = optarg;
229 break;
230 case 'K':
231 kr_pub = optarg;
232 break;
233 case 'a':
234 csock = optarg;
235 break;
236 case 't':
237 tag_priv = optarg;
238 break;
239#ifndef NTRACE
240 case 'T':
241 tr_flags = traceopt(tr_opts, optarg, tr_flags, 0);
242 trace_level(tr_flags);
243 break;
244#endif
245 default:
246 f |= f_bogus;
247 break;
248 }
249 }
250
251 if (optind < argc || (f & f_bogus)) {
252 usage(stderr);
253 exit(EXIT_FAILURE);
254 }
255
256 if (chdir(dir)) {
257 die(EXIT_FAILURE, "can't set current directory to `%s': %s",
258 dir, strerror(errno));
259 }
260
261 sel_init(&sel);
262 sig_init(&sel);
263 rand_noisesrc(RAND_GLOBAL, &noise_source);
264 rand_seed(RAND_GLOBAL, RMD160_HASHSZ);
265 signal(SIGPIPE, SIG_IGN);
266 tun_init();
267 p_init(port);
268 if (!(f & f_daemon))
269 a_create(STDIN_FILENO, STDOUT_FILENO);
270 if (g != -1) {
271 if (setgid(g)) {
272 die(EXIT_FAILURE, "couldn't setgid to %u: %s",
273 (unsigned)g, strerror(errno));
274 }
275 }
276 if (u != -1) {
277 if (setuid(u)) {
278 die(EXIT_FAILURE, "couldn't setuid to %u: %s",
279 (unsigned)u, strerror(errno));
280 }
281 }
282 km_init(kr_priv, kr_pub, tag_priv);
283 a_init(csock);
284 if (f & f_daemon) {
285 if (u_daemon)
286 die(EXIT_FAILURE, "couldn't become a daemon: %s", strerror(errno));
287 a_daemon();
288 }
289
290 {
291 struct timeval tv;
292 tv.tv_sec = time(0) + T_INTERVAL;
293 tv.tv_usec = 0;
294 sel_addtimer(&sel, &it, &tv, interval, 0);
295 }
296
297 {
298 int selerr = 0;
299 for (;;) {
300 if (!sel_select(&sel))
301 selerr = 0;
302 else if (errno != EINTR && errno != EAGAIN) {
303 a_warn("select failed: %s", strerror(errno));
410c8acf 304 selerr++;
305 if (selerr > 8) {
306 a_warn("too many select errors: bailing out");
307 a_quit();
308 }
309 }
310 }
311 }
312
313 return (0);
314}
315
316/*----- That's all, folks -------------------------------------------------*/