support of PKCS#11 init arguments required by NSS softoken, patch contributed by...
[strongswan.git] / src / starter / invokepluto.c
1 /* strongSwan Pluto launcher
2 * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * RCSID $Id: invokepluto.c,v 1.12 2006/02/17 21:41:50 as Exp $
15 */
16
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include <signal.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <errno.h>
24
25 #include <freeswan.h>
26
27 #include "../pluto/constants.h"
28 #include "../pluto/defs.h"
29 #include "../pluto/log.h"
30
31 #include "confread.h"
32 #include "invokepluto.h"
33 #include "files.h"
34 #include "starterwhack.h"
35 #
36 static int _pluto_pid = 0;
37 static int _stop_requested;
38
39 pid_t
40 starter_pluto_pid(void)
41 {
42 return _pluto_pid;
43 }
44
45 void
46 starter_pluto_sigchild(pid_t pid)
47 {
48 if (pid == _pluto_pid)
49 {
50 _pluto_pid = 0;
51 if (!_stop_requested)
52 {
53 plog("pluto has died -- restart scheduled (%dsec)"
54 , PLUTO_RESTART_DELAY);
55 alarm(PLUTO_RESTART_DELAY); // restart in 5 sec
56 }
57 unlink(PLUTO_PID_FILE);
58 }
59 }
60
61 int
62 starter_stop_pluto (void)
63 {
64 pid_t pid;
65 int i;
66
67 pid = _pluto_pid;
68 if (pid)
69 {
70 _stop_requested = 1;
71 if (starter_whack_shutdown() == 0)
72 {
73 for (i = 0; i < 20; i++)
74 {
75 usleep(20000);
76 if (_pluto_pid == 0)
77 return 0;
78 }
79 }
80 /* be more and more aggressive */
81 for (i = 0; i < 20 && (pid = _pluto_pid) != 0; i++)
82 {
83 if (i < 10)
84 kill(pid, SIGTERM);
85 else
86 kill(pid, SIGKILL);
87 usleep(20000);
88 }
89 if (_pluto_pid == 0)
90 return 0;
91 plog("starter_stop_pluto(): can't stop pluto !!!");
92 return -1;
93 }
94 else
95 {
96 plog("stater_stop_pluto(): pluto is not started...");
97 }
98 return -1;
99 }
100
101 #define ADD_DEBUG(v) { \
102 for (l = cfg->setup.plutodebug; l && *l; l++) if (streq(*l, v)) \
103 arg[argc++] = "--debug-" v; \
104 }
105
106 int
107 starter_start_pluto (starter_config_t *cfg, bool debug)
108 {
109 int i;
110 struct stat stb;
111 pid_t pid;
112 char **l;
113 int argc = 2;
114 char *arg[] = {
115 PLUTO_CMD, "--nofork"
116 , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
117 , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
118 , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
119 , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
120 };
121
122 printf ("starter_start_pluto entered\n");
123
124 if (debug)
125 {
126 arg[argc++] = "--stderrlog";
127 }
128 if (cfg->setup.uniqueids)
129 {
130 arg[argc++] = "--uniqueids";
131 }
132 ADD_DEBUG("none")
133 ADD_DEBUG("all")
134 ADD_DEBUG("raw")
135 ADD_DEBUG("crypt")
136 ADD_DEBUG("parsing")
137 ADD_DEBUG("emitting")
138 ADD_DEBUG("control")
139 ADD_DEBUG("lifecycle")
140 ADD_DEBUG("klips")
141 ADD_DEBUG("dns")
142 ADD_DEBUG("natt")
143 ADD_DEBUG("oppo")
144 ADD_DEBUG("controlmore")
145 ADD_DEBUG("private")
146 if (cfg->setup.crlcheckinterval > 0)
147 {
148 static char buf1[15];
149
150 arg[argc++] = "--crlcheckinterval";
151 snprintf(buf1, sizeof(buf1), "%u", cfg->setup.crlcheckinterval);
152 arg[argc++] = buf1;
153 }
154 if (cfg->setup.cachecrls)
155 {
156 arg[argc++] = "--cachecrls";
157 }
158 if (cfg->setup.strictcrlpolicy)
159 {
160 arg[argc++] = "--strictcrlpolicy";
161 }
162 if (cfg->setup.nocrsend)
163 {
164 arg[argc++] = "--nocrsend";
165 }
166 if (cfg->setup.nat_traversal)
167 {
168 arg[argc++] = "--nat_traversal";
169 }
170 if (cfg->setup.keep_alive)
171 {
172 static char buf2[15];
173
174 arg[argc++] = "--keep_alive";
175 snprintf(buf2, sizeof(buf2), "%u", cfg->setup.keep_alive);
176 arg[argc++] = buf2;
177 }
178 #ifdef VIRTUAL_IP
179 if (cfg->setup.virtual_private)
180 {
181 arg[argc++] = "--virtual_private";
182 arg[argc++] = cfg->setup.virtual_private;
183 }
184 #endif
185 if (cfg->setup.pkcs11module)
186 {
187 arg[argc++] = "--pkcs11module";
188 arg[argc++] = cfg->setup.pkcs11module;
189 }
190 if (cfg->setup.pkcs11initargs)
191 {
192 arg[argc++] = "--pkcs11initargs";
193 arg[argc++] = cfg->setup.pkcs11initargs;
194 }
195 if (cfg->setup.pkcs11keepstate)
196 {
197 arg[argc++] = "--pkcs11keepstate";
198 }
199 if (cfg->setup.pkcs11proxy)
200 {
201 arg[argc++] = "--pkcs11proxy";
202 }
203
204 if (_pluto_pid)
205 {
206 plog("starter_start_pluto(): pluto already started...");
207 return -1;
208 }
209 else
210 {
211 unlink(PLUTO_CTL_FILE);
212 _stop_requested = 0;
213
214 if (cfg->setup.prepluto)
215 system(cfg->setup.prepluto);
216
217 /* if ipsec.secrets file is missing then generate RSA default key pair */
218 if (stat(SECRETS_FILE, &stb) != 0)
219 {
220 mode_t oldmask;
221 FILE *f;
222
223 plog("no %s file, generating RSA key", SECRETS_FILE);
224 seteuid(IPSEC_UID);
225 setegid(IPSEC_GID);
226 system("ipsec scepclient --out pkcs1 --out cert-self --quiet");
227 seteuid(0);
228 setegid(0);
229
230 /* ipsec.secrets is root readable only */
231 oldmask = umask(0066);
232
233 f = fopen(SECRETS_FILE, "w");
234 if (f)
235 {
236 fprintf(f, "# /etc/ipsec.secrets - strongSwan IPsec secrets file\n");
237 fprintf(f, "\n");
238 fprintf(f, ": RSA myKey.der\n");
239 fclose(f);
240 }
241 chown(SECRETS_FILE, IPSEC_UID, IPSEC_GID);
242 umask(oldmask);
243 }
244
245 pid = fork();
246 switch (pid)
247 {
248 case -1:
249 plog("can't fork(): %s", strerror(errno));
250 return -1;
251 case 0:
252 /* child */
253 setsid();
254 sigprocmask(SIG_SETMASK, 0, NULL);
255 execv(arg[0], arg);
256 plog("can't execv(%s,...): %s", arg[0], strerror(errno));
257 exit(1);
258 default:
259 /* father */
260 _pluto_pid = pid;
261 for (i = 0; i < 50 && _pluto_pid; i++)
262 {
263 /* wait for pluto */
264 usleep(20000);
265 if (stat(PLUTO_CTL_FILE, &stb) == 0)
266 {
267 DBG(DBG_CONTROL,
268 DBG_log("pluto (%d) started", _pluto_pid)
269 )
270 if (cfg->setup.postpluto)
271 system(cfg->setup.postpluto);
272 return 0;
273 }
274 }
275 if (_pluto_pid)
276 {
277 /* If pluto is started but with no ctl file, stop it */
278 plog("pluto too long to start... - kill kill");
279 for (i = 0; i < 20 && (pid = _pluto_pid) != 0; i++)
280 {
281 if (i < 10)
282 kill(pid, SIGTERM);
283 else
284 kill(pid, SIGKILL);
285 usleep(20000);
286 }
287 }
288 else
289 {
290 plog("pluto refused to be started");
291 }
292 return -1;
293 }
294 }
295 return -1;
296 }