2
* Userspace daemon which responds to the eCryptfs kernel module's requests
4
* Copyright (C) 2004-2006 International Business Machines Corp.
5
* Author(s): Tyler Hicks <tyhicks@ou.edu>
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License as
9
* published by the Free Software Foundation; either version 2 of the
10
* License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful, but
13
* WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
32
#include <sys/resource.h>
34
#include "../include/ecryptfs.h"
36
static int ecryptfs_socket = 0;
37
static char *pidfile = NULL;
38
static char *prompt_prog = NULL;
42
prompt_callback(char *prompt_type, char *prompt, char *input, int input_size) {
45
int fds[2] = {-1, -1};
50
* Make sure we don't reuse input
53
memset (input, 0, input_size);
56
if (prompt_prog == NULL) {
61
if (pipe (fds) == -1) {
66
if ((pid = fork ()) == -1) {
75
if (dup2 (fds[1], 1) == -1) {
98
(r=waitpid (pid, &status, __WNOTHREAD)) == 0 ||
99
(r == -1 && errno == EINTR)
107
if (!WIFEXITED (status)) {
112
if (WEXITSTATUS (status) != 0) {
117
if (!strcmp (prompt_type, "password")) {
118
if ((r = read (fds[0], input, input_size)) == -1) {
125
if (strlen (input) > 0 && input[strlen (input)-1] == '\n') {
126
input[strlen (input)-1] = '\0';
135
memset (input, 0, input_size);
153
static void ecryptfsd_exit(int retval)
155
if (pidfile != NULL) {
160
if (!ecryptfs_socket)
162
if (ecryptfs_send_netlink(ecryptfs_socket, NULL,
163
ECRYPTFS_NLMSG_QUIT, 0, 0) < 0) {
164
ecryptfs_syslog(LOG_ERR, "Failed to unregister netlink "
165
"daemon with the eCryptfs kernel module\n");
167
ecryptfs_release_netlink(ecryptfs_socket);
169
ecryptfs_syslog(LOG_INFO, "Closing eCryptfs userspace netlink "
170
"daemon [%u]\n", getpid());
181
return; /* Already a daemon */
182
if ((pid=fork()) == -1) {
183
fprintf(stderr, "Failed to create daemon process: %s\n",
192
if ((pid=fork()) == -1) { /* Fork in new session */
193
syslog(LOG_ERR, "Failed to create daemon process: %s",
199
/* Make std handles write to null; close all others. */
200
if ((null = open("/dev/null", O_RDWR)) == -1) {
201
syslog(LOG_ERR, "Cannot open /dev/null");
204
for (fd=0; fd < 3; fd++) {
205
if (dup2(null, 0) == -1) {
206
syslog(LOG_ERR, "Failed to dup null: %s",
211
for (fd = (getdtablesize() - 1); fd > 2; fd--)
213
/* Ignore major signals */
214
if (signal(SIGHUP, SIG_IGN) == SIG_ERR
215
|| signal(SIGTERM, SIG_IGN) == SIG_ERR
216
|| signal(SIGINT, SIG_IGN) == SIG_ERR) {
217
syslog(LOG_ERR, "Failed to setup initial signals");
222
void sigterm_handler(int sig)
227
void usage(const char * const me, const struct option * const options,
228
const char * const short_options)
230
const struct option *opt;
232
printf("Usage: %s [options]", me);
233
for (opt = options; opt->name; opt++) {
234
const char *descr = opt->name + strlen(opt->name) + 1;
236
if (strchr(short_options, opt->val))
237
printf("\n -%c, --%s", opt->val, opt->name);
239
printf("\n --%s", opt->name);
241
printf(" <%s>", opt->name);
243
printf("\t%s",descr);
248
int main(int argc, char **argv)
250
static struct option long_options[] = {
251
{ "pidfile\0\tSet pid file name", required_argument, NULL, 'p' },
252
{ "foreground\0\t\tDon't fork into background", no_argument, NULL, 'f' },
253
{ "chroot\0\t\tChroot to directory", required_argument, NULL, 'C' },
254
{ "prompt-prog\0Program to execute for user prompt", required_argument, NULL, 'R' },
255
{ "version\0\t\t\tShow version information", no_argument, NULL, 'V' },
256
{ "help\0\t\t\tShow usage information", no_argument, NULL, 'h' },
259
static char *short_options = "p:f:C:R:Vh";
260
int long_options_ret;
261
struct rlimit core = { 0, 0 };
263
char *chrootdir = NULL;
267
while ((long_options_ret = getopt_long (argc, argv, short_options,
268
long_options, NULL)) != -1) {
269
switch (long_options_ret) {
271
pidfile = strdup(optarg);
277
chrootdir = strdup(optarg);
280
prompt_prog = strdup(optarg);
283
printf(("%s (%s) %s\n"
285
"This is free software. You may redistribute copies of it under the terms of\n"
286
"the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"
287
"There is NO WARRANTY, to the extent permitted by law.\n"
296
usage(basename(argv[0]), long_options,
302
tty = ttyname(0); /* We may need the tty name later */
304
setenv ("TERM_DEVICE", tty, 0);
306
daemonize(); /* This will exit if cannot be completed */
307
/* Disallow core file; secret values may be in it */
308
if (setrlimit(RLIMIT_CORE, &core) == -1) {
310
syslog(LOG_ERR, "Cannot setrlimit: %s", strerror (errno));
313
if (chrootdir != NULL) {
314
if (chroot(chrootdir) == -1) {
316
syslog(LOG_ERR, "Failed to chroot to '%s': %s",
317
chrootdir, strerror(errno));
323
if (pidfile != NULL) {
324
FILE *fp = fopen(pidfile, "w");
328
syslog(LOG_ERR, "Failed to open pid file '%s': %s",
329
pidfile, strerror(errno));
332
fprintf(fp, "%d", (int)getpid());
335
if (signal(SIGTERM, sigterm_handler) == SIG_ERR) {
337
syslog(LOG_ERR, "Failed to attach handler to SIGTERM");
340
if (signal(SIGINT, sigterm_handler) == SIG_ERR) {
342
syslog(LOG_ERR, "Failed to attach handler to SIGINT");
345
/* TODO: eCryptfs context via daemon */
346
cryptfs_get_ctx_opts()->prompt = prompt_callback;
347
rc = init_netlink_daemon();
350
"Error initializing netlink daemon; rc = [%d]\n", rc);
353
rc = ecryptfs_init_netlink(&ecryptfs_socket);
355
syslog(LOG_ERR, "Failed to run netlink daemon\n");
358
rc = ecryptfs_send_netlink(ecryptfs_socket, NULL,
359
ECRYPTFS_NLMSG_HELO, 0, 0);
361
syslog(LOG_ERR, "Failed to register netlink daemon with the "
362
"eCryptfs kernel module\n");
365
rc = ecryptfs_run_netlink_daemon(ecryptfs_socket);