add --eapdir option only if defined in ipsec.conf
[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.eapdir)
120 {
121 arg[argc++] = "--eapdir";
122 arg[argc++] = cfg->setup.eapdir;
123 }
124
125 { /* parse debug string */
126 char *pos, *level, *buf_pos, type[4], buffer[512];
127 pos = cfg->setup.charondebug;
128 buf_pos = buffer;
129 while (pos && sscanf(pos, "%4s %d,", type, &level) == 2)
130 {
131 snprintf(buf_pos, buffer + sizeof(buffer) - buf_pos, "--debug-%s", type);
132 arg[argc++] = buf_pos;
133 buf_pos += strlen(buf_pos) + 1;
134 if (buf_pos >= buffer + sizeof(buffer))
135 {
136 break;
137 }
138 snprintf(buf_pos, buffer + sizeof(buffer) - buf_pos, "%d", level);
139 arg[argc++] = buf_pos;
140 buf_pos += strlen(buf_pos) + 1;
141 if (buf_pos >= buffer + sizeof(buffer))
142 {
143 break;
144 }
145
146 /* get next */
147 pos = strchr(pos, ',');
148 if (pos)
149 {
150 pos++;
151 }
152 }
153 }
154
155 if (_charon_pid)
156 {
157 plog("starter_start_charon(): charon already started...");
158 return -1;
159 }
160 else
161 {
162 unlink(CHARON_CTL_FILE);
163 _stop_requested = 0;
164
165 /* if ipsec.secrets file is missing then generate RSA default key pair */
166 if (stat(SECRETS_FILE, &stb) != 0)
167 {
168 mode_t oldmask;
169 FILE *f;
170
171 plog("no %s file, generating RSA key", SECRETS_FILE);
172 system("ipsec scepclient --out pkcs1 --out cert-self --quiet");
173
174 /* ipsec.secrets is root readable only */
175 oldmask = umask(0066);
176
177 f = fopen(SECRETS_FILE, "w");
178 if (f)
179 {
180 fprintf(f, "# /etc/ipsec.secrets - strongSwan IPsec secrets file\n");
181 fprintf(f, "\n");
182 fprintf(f, ": RSA myKey.der\n");
183 fclose(f);
184 }
185 umask(oldmask);
186 }
187
188 pid = fork();
189 switch (pid)
190 {
191 case -1:
192 plog("can't fork(): %s", strerror(errno));
193 return -1;
194 case 0:
195 /* child */
196 setsid();
197 sigprocmask(SIG_SETMASK, 0, NULL);
198 execv(arg[0], arg);
199 plog("can't execv(%s,...): %s", arg[0], strerror(errno));
200 exit(1);
201 default:
202 /* father */
203 _charon_pid = pid;
204 for (i = 0; i < 50 && _charon_pid; i++)
205 {
206 /* wait for charon */
207 usleep(20000);
208 if (stat(CHARON_PID_FILE, &stb) == 0)
209 {
210 DBG(DBG_CONTROL,
211 DBG_log("charon (%d) started", _charon_pid)
212 )
213 return 0;
214 }
215 }
216 if (_charon_pid)
217 {
218 /* If charon is started but with no ctl file, stop it */
219 plog("charon too long to start... - kill kill");
220 for (i = 0; i < 20 && (pid = _charon_pid) != 0; i++)
221 {
222 if (i == 0)
223 kill(pid, SIGINT);
224 else if (i < 10)
225 kill(pid, SIGTERM);
226 else
227 kill(pid, SIGKILL);
228 usleep(20000);
229 }
230 }
231 else
232 {
233 plog("charon refused to be started");
234 }
235 return -1;
236 }
237 }
238 return -1;
239 }