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