support of crlcheckinterval=0 to disable IKEv2 CRL fetching
[strongswan.git] / src / starter / invokecharon.c
1 /* strongSwan charon launcher
2 * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
3 * Copyright (C) 2006 Martin Willi - Hochschule fuer Technik Rapperswil
4 *
5 * Ported from invokepluto.c to fit charons needs.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 *
17 * RCSID $Id: invokecharon.c $
18 */
19
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include <signal.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <errno.h>
27
28 #include <freeswan.h>
29
30 #include "../pluto/constants.h"
31 #include "../pluto/defs.h"
32 #include "../pluto/log.h"
33
34 #include "confread.h"
35 #include "invokecharon.h"
36 #include "files.h"
37
38 static int _charon_pid = 0;
39 static int _stop_requested;
40
41 pid_t
42 starter_charon_pid(void)
43 {
44 return _charon_pid;
45 }
46
47 void
48 starter_charon_sigchild(pid_t pid)
49 {
50 if (pid == _charon_pid)
51 {
52 _charon_pid = 0;
53 if (!_stop_requested)
54 {
55 plog("charon has died -- restart scheduled (%dsec)"
56 , CHARON_RESTART_DELAY);
57 alarm(CHARON_RESTART_DELAY); // restart in 5 sec
58 }
59 unlink(CHARON_PID_FILE);
60 }
61 }
62
63 int
64 starter_stop_charon (void)
65 {
66 pid_t pid;
67 int i;
68
69 pid = _charon_pid;
70 if (pid)
71 {
72 _stop_requested = 1;
73
74 /* be more and more aggressive */
75 for (i = 0; i < 20 && (pid = _charon_pid) != 0; i++)
76 {
77 if (i == 0)
78 kill(pid, SIGINT);
79 else if (i < 10)
80 kill(pid, SIGTERM);
81 else
82 kill(pid, SIGKILL);
83 usleep(20000);
84 }
85 if (_charon_pid == 0)
86 return 0;
87 plog("starter_stop_charon(): can't stop charon !!!");
88 return -1;
89 }
90 else
91 {
92 plog("stater_stop_charon(): charon is not started...");
93 }
94 return -1;
95 }
96
97
98 int
99 starter_start_charon (starter_config_t *cfg, bool debug)
100 {
101 int pid, i;
102 struct stat stb;
103 int argc = 1;
104 char *arg[] = {
105 CHARON_CMD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
106 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
107 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
108 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
109 };
110
111 if (!debug)
112 {
113 arg[argc++] = "--use-syslog";
114 }
115 if (cfg->setup.strictcrlpolicy)
116 {
117 arg[argc++] = "--strictcrlpolicy";
118 }
119 if (cfg->setup.crlcheckinterval > 0)
120 {
121 char buffer[BUF_LEN];
122
123 snprintf(buffer, BUF_LEN, "%u", cfg->setup.crlcheckinterval);
124 arg[argc++] = "--crlcheckinterval";
125 arg[argc++] = buffer;
126 }
127 if (cfg->setup.eapdir)
128 {
129 arg[argc++] = "--eapdir";
130 arg[argc++] = cfg->setup.eapdir;
131 }
132
133 { /* parse debug string */
134 char *pos, *level, *buf_pos, type[4], buffer[BUF_LEN];
135 pos = cfg->setup.charondebug;
136 buf_pos = buffer;
137 while (pos && sscanf(pos, "%4s %d,", type, &level) == 2)
138 {
139 snprintf(buf_pos, buffer + sizeof(buffer) - buf_pos, "--debug-%s", type);
140 arg[argc++] = buf_pos;
141 buf_pos += strlen(buf_pos) + 1;
142 if (buf_pos >= buffer + sizeof(buffer))
143 {
144 break;
145 }
146 snprintf(buf_pos, buffer + sizeof(buffer) - buf_pos, "%d", level);
147 arg[argc++] = buf_pos;
148 buf_pos += strlen(buf_pos) + 1;
149 if (buf_pos >= buffer + sizeof(buffer))
150 {
151 break;
152 }
153
154 /* get next */
155 pos = strchr(pos, ',');
156 if (pos)
157 {
158 pos++;
159 }
160 }
161 }
162
163 if (_charon_pid)
164 {
165 plog("starter_start_charon(): charon already started...");
166 return -1;
167 }
168 else
169 {
170 unlink(CHARON_CTL_FILE);
171 _stop_requested = 0;
172
173 /* if ipsec.secrets file is missing then generate RSA default key pair */
174 if (stat(SECRETS_FILE, &stb) != 0)
175 {
176 mode_t oldmask;
177 FILE *f;
178
179 plog("no %s file, generating RSA key", SECRETS_FILE);
180 system("ipsec scepclient --out pkcs1 --out cert-self --quiet");
181
182 /* ipsec.secrets is root readable only */
183 oldmask = umask(0066);
184
185 f = fopen(SECRETS_FILE, "w");
186 if (f)
187 {
188 fprintf(f, "# /etc/ipsec.secrets - strongSwan IPsec secrets file\n");
189 fprintf(f, "\n");
190 fprintf(f, ": RSA myKey.der\n");
191 fclose(f);
192 }
193 umask(oldmask);
194 }
195
196 pid = fork();
197 switch (pid)
198 {
199 case -1:
200 plog("can't fork(): %s", strerror(errno));
201 return -1;
202 case 0:
203 /* child */
204 setsid();
205 sigprocmask(SIG_SETMASK, 0, NULL);
206 execv(arg[0], arg);
207 plog("can't execv(%s,...): %s", arg[0], strerror(errno));
208 exit(1);
209 default:
210 /* father */
211 _charon_pid = pid;
212 for (i = 0; i < 50 && _charon_pid; i++)
213 {
214 /* wait for charon */
215 usleep(20000);
216 if (stat(CHARON_PID_FILE, &stb) == 0)
217 {
218 DBG(DBG_CONTROL,
219 DBG_log("charon (%d) started", _charon_pid)
220 )
221 return 0;
222 }
223 }
224 if (_charon_pid)
225 {
226 /* If charon is started but with no ctl file, stop it */
227 plog("charon too long to start... - kill kill");
228 for (i = 0; i < 20 && (pid = _charon_pid) != 0; i++)
229 {
230 if (i == 0)
231 kill(pid, SIGINT);
232 else if (i < 10)
233 kill(pid, SIGTERM);
234 else
235 kill(pid, SIGKILL);
236 usleep(20000);
237 }
238 }
239 else
240 {
241 plog("charon refused to be started");
242 }
243 return -1;
244 }
245 }
246 return -1;
247 }